Current File : /home/mmdealscpanel/yummmdeals.com/pear.zip
PKm�ZPi��.depdbnu�[���a:3:{s:8:"_version";s:3:"1.0";s:12:"dependencies";a:1:{s:12:"pear.php.net";a:6:{s:4:"pear";a:9:{i:0;a:3:{s:3:"dep";a:4:{s:4:"name";s:11:"Archive_Tar";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.4.0";s:11:"recommended";s:5:"1.4.4";}s:4:"type";s:8:"required";s:5:"group";b:0;}i:1;a:3:{s:3:"dep";a:4:{s:4:"name";s:16:"Structures_Graph";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.1.0";s:11:"recommended";s:5:"1.1.1";}s:4:"type";s:8:"required";s:5:"group";b:0;}i:2;a:3:{s:3:"dep";a:4:{s:4:"name";s:14:"Console_Getopt";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.4.1";s:11:"recommended";s:5:"1.4.1";}s:4:"type";s:8:"required";s:5:"group";b:0;}i:3;a:3:{s:3:"dep";a:4:{s:4:"name";s:8:"XML_Util";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.3.0";s:11:"recommended";s:5:"1.4.3";}s:4:"type";s:8:"required";s:5:"group";b:0;}i:4;a:3:{s:3:"dep";a:4:{s:4:"name";s:17:"PEAR_Frontend_Web";s:7:"channel";s:12:"pear.php.net";s:3:"max";s:3:"0.4";s:9:"conflicts";s:0:"";}s:4:"type";s:8:"required";s:5:"group";b:0;}i:5;a:3:{s:3:"dep";a:5:{s:4:"name";s:17:"PEAR_Frontend_Gtk";s:7:"channel";s:12:"pear.php.net";s:3:"max";s:5:"0.4.0";s:7:"exclude";s:5:"0.4.0";s:9:"conflicts";s:0:"";}s:4:"type";s:8:"required";s:5:"group";b:0;}i:6;a:3:{s:3:"dep";a:3:{s:4:"name";s:17:"PEAR_Frontend_Web";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"0.5.1";}s:4:"type";s:8:"optional";s:5:"group";s:12:"webinstaller";}i:7;a:3:{s:3:"dep";a:3:{s:4:"name";s:17:"PEAR_Frontend_Gtk";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"0.4.0";}s:4:"type";s:8:"optional";s:5:"group";s:12:"gtkinstaller";}i:8;a:3:{s:3:"dep";a:2:{s:4:"name";s:18:"PEAR_Frontend_Gtk2";s:7:"channel";s:12:"pear.php.net";}s:4:"type";s:8:"optional";s:5:"group";s:13:"gtk2installer";}}s:9:"file_marc";a:1:{i:0;a:3:{s:3:"dep";a:2:{s:4:"name";s:13:"Validate_ISPN";s:7:"channel";s:12:"pear.php.net";}s:4:"type";s:8:"optional";s:5:"group";b:0;}}s:4:"mail";a:1:{i:0;a:3:{s:3:"dep";a:3:{s:4:"name";s:8:"Net_SMTP";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.4.1";}s:4:"type";s:8:"optional";s:5:"group";b:0;}}s:15:"mail_mimedecode";a:1:{i:0;a:3:{s:3:"dep";a:4:{s:4:"name";s:9:"Mail_Mime";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.4.0";s:7:"exclude";s:5:"1.4.0";}s:4:"type";s:8:"required";s:5:"group";b:0;}}s:9:"net_sieve";a:2:{i:0;a:3:{s:3:"dep";a:3:{s:4:"name";s:10:"Net_Socket";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:3:"1.0";}s:4:"type";s:8:"required";s:5:"group";b:0;}i:1;a:3:{s:3:"dep";a:3:{s:4:"name";s:9:"Auth_SASL";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:3:"1.0";}s:4:"type";s:8:"optional";s:5:"group";b:0;}}s:8:"net_smtp";a:2:{i:0;a:3:{s:3:"dep";a:3:{s:4:"name";s:10:"Net_Socket";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.0.7";}s:4:"type";s:8:"required";s:5:"group";b:0;}i:1;a:3:{s:3:"dep";a:3:{s:4:"name";s:9:"Auth_SASL";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.0.5";}s:4:"type";s:8:"optional";s:5:"group";b:0;}}}}s:8:"packages";a:1:{s:12:"pear.php.net";a:12:{s:11:"archive_tar";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:4:"pear";}}s:16:"structures_graph";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:4:"pear";}}s:14:"console_getopt";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:4:"pear";}}s:8:"xml_util";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:4:"pear";}}s:17:"pear_frontend_web";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:4:"pear";}}s:17:"pear_frontend_gtk";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:4:"pear";}}s:18:"pear_frontend_gtk2";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:4:"pear";}}s:13:"validate_ispn";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:9:"file_marc";}}s:8:"net_smtp";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:4:"mail";}}s:9:"mail_mime";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:15:"mail_mimedecode";}}s:10:"net_socket";a:2:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:9:"net_sieve";}i:1;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:8:"net_smtp";}}s:9:"auth_sasl";a:2:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:9:"net_sieve";}i:1;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:8:"net_smtp";}}}}}PKm�Z�{��
Mail/null.phpnu�[���<?php
/**
 * Null implementation of the PEAR Mail interface
 *
 * PHP version 5
 *
 * LICENSE:
 *
 * Copyright (c) 2010-2017, Phil Kernick
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category    Mail
 * @package     Mail
 * @author      Phil Kernick <philk@rotfl.com.au>
 * @copyright   2010-2017 Phil Kernick
 * @license     http://opensource.org/licenses/BSD-3-Clause New BSD License
 * @version     CVS: $Id$
 * @link        http://pear.php.net/package/Mail/
 */

/**
 * Null implementation of the PEAR Mail:: interface.
 * @access public
 * @package Mail
 * @version $Revision$
 */
class Mail_null extends Mail {

    /**
     * Implements Mail_null::send() function. Silently discards all
     * mail.
     *
     * @param mixed $recipients Either a comma-seperated list of recipients
     *              (RFC822 compliant), or an array of recipients,
     *              each RFC822 valid. This may contain recipients not
     *              specified in the headers, for Bcc:, resending
     *              messages, etc.
     *
     * @param array $headers The array of headers to send with the mail, in an
     *              associative array, where the array key is the
     *              header name (ie, 'Subject'), and the array value
     *              is the header value (ie, 'test'). The header
     *              produced from those values would be 'Subject:
     *              test'.
     *
     * @param string $body The full text of the message body, including any
     *               Mime parts, etc.
     *
     * @return mixed Returns true on success, or a PEAR_Error
     *               containing a descriptive error message on
     *               failure.
     */
    public function send($recipients, $headers, $body)
    {
        return true;
    }

}
PKm�ZE@�%>>Mail/sendmail.phpnu�[���<?php
/**
 * Sendmail implementation of the PEAR Mail interface.
 *
 * PHP version 5
 *
 * LICENSE:
 *
 * Copyright (c) 2010-2017, Chuck Hagenbuch & Jon Parise
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category    Mail
 * @package     Mail
 * @author      Jon Parise <jon@php.net>
 * @author      Chuck Hagenbuch <chuck@horde.org>
 * @copyright   2010-2017 Chuck Hagenbuch
 * @license     http://opensource.org/licenses/BSD-3-Clause New BSD License
 * @version     CVS: $Id$
 * @link        http://pear.php.net/package/Mail/
 */

/**
 * Sendmail implementation of the PEAR Mail:: interface.
 * @access public
 * @package Mail
 * @version $Revision$
 */
class Mail_sendmail extends Mail {

    /**
     * The location of the sendmail or sendmail wrapper binary on the
     * filesystem.
     * @var string
     */
    var $sendmail_path = '/usr/sbin/sendmail';

    /**
     * Any extra command-line parameters to pass to the sendmail or
     * sendmail wrapper binary.
     * @var string
     */
    var $sendmail_args = '-i';

    /**
     * Constructor.
     *
     * Instantiates a new Mail_sendmail:: object based on the parameters
     * passed in. It looks for the following parameters:
     *     sendmail_path    The location of the sendmail binary on the
     *                      filesystem. Defaults to '/usr/sbin/sendmail'.
     *
     *     sendmail_args    Any extra parameters to pass to the sendmail
     *                      or sendmail wrapper binary.
     *
     * If a parameter is present in the $params array, it replaces the
     * default.
     *
     * @param array $params Hash containing any parameters different from the
     *              defaults.
     */
    public function __construct($params)
    {
        if (isset($params['sendmail_path'])) {
            $this->sendmail_path = $params['sendmail_path'];
        }
        if (isset($params['sendmail_args'])) {
            $this->sendmail_args = $params['sendmail_args'];
        }

        /*
         * Because we need to pass message headers to the sendmail program on
         * the commandline, we can't guarantee the use of the standard "\r\n"
         * separator.  Instead, we use the system's native line separator.
         */
        if (defined('PHP_EOL')) {
            $this->sep = PHP_EOL;
        } else {
            $this->sep = (strpos(PHP_OS, 'WIN') === false) ? "\n" : "\r\n";
        }
    }

    /**
     * Implements Mail::send() function using the sendmail
     * command-line binary.
     *
     * @param mixed $recipients Either a comma-seperated list of recipients
     *              (RFC822 compliant), or an array of recipients,
     *              each RFC822 valid. This may contain recipients not
     *              specified in the headers, for Bcc:, resending
     *              messages, etc.
     *
     * @param array $headers The array of headers to send with the mail, in an
     *              associative array, where the array key is the
     *              header name (ie, 'Subject'), and the array value
     *              is the header value (ie, 'test'). The header
     *              produced from those values would be 'Subject:
     *              test'.
     *
     * @param string $body The full text of the message body, including any
     *               Mime parts, etc.
     *
     * @return mixed Returns true on success, or a PEAR_Error
     *               containing a descriptive error message on
     *               failure.
     */
    public function send($recipients, $headers, $body)
    {
        if (!is_array($headers)) {
            return PEAR::raiseError('$headers must be an array');
        }

        $result = $this->_sanitizeHeaders($headers);
        if (is_a($result, 'PEAR_Error')) {
            return $result;
        }

        $recipients = $this->parseRecipients($recipients);
        if (is_a($recipients, 'PEAR_Error')) {
            return $recipients;
        }
        $recipients = implode(' ', array_map('escapeshellarg', $recipients));

        $headerElements = $this->prepareHeaders($headers);
        if (is_a($headerElements, 'PEAR_Error')) {
            return $headerElements;
        }
        list($from, $text_headers) = $headerElements;

        /* Since few MTAs are going to allow this header to be forged
         * unless it's in the MAIL FROM: exchange, we'll use
         * Return-Path instead of From: if it's set. */
        if (!empty($headers['Return-Path'])) {
            $from = $headers['Return-Path'];
        }

        if (!isset($from)) {
            return PEAR::raiseError('No from address given.');
        } elseif (strpos($from, ' ') !== false ||
                  strpos($from, ';') !== false ||
                  strpos($from, '&') !== false ||
                  strpos($from, '`') !== false) {
            return PEAR::raiseError('From address specified with dangerous characters.');
        }

        $from = escapeshellarg($from); // Security bug #16200

        $mail = @popen($this->sendmail_path . (!empty($this->sendmail_args) ? ' ' . $this->sendmail_args : '') . " -f$from -- $recipients", 'w');
        if (!$mail) {
            return PEAR::raiseError('Failed to open sendmail [' . $this->sendmail_path . '] for execution.');
        }

        // Write the headers following by two newlines: one to end the headers
        // section and a second to separate the headers block from the body.
        fputs($mail, $text_headers . $this->sep . $this->sep);

        fputs($mail, $body);
        $result = pclose($mail);
        if (version_compare(phpversion(), '4.2.3') == -1) {
            // With older php versions, we need to shift the pclose
            // result to get the exit code.
            $result = $result >> 8 & 0xFF;
        }

        if ($result != 0) {
            return PEAR::raiseError('sendmail returned error code ' . $result,
                                    $result);
        }

        return true;
    }

}
PKm�Z��A~�{�{Mail/RFC822.phpnu�[���<?php
/**
 * RFC 822 Email address list validation Utility
 *
 * PHP version 5
 *
 * LICENSE:
 *
 * Copyright (c) 2001-2017, Chuck Hagenbuch & Richard Heyes
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category    Mail
 * @package     Mail
 * @author      Richard Heyes <richard@phpguru.org>
 * @author      Chuck Hagenbuch <chuck@horde.org
 * @copyright   2001-2017 Richard Heyes
 * @license     http://opensource.org/licenses/BSD-3-Clause New BSD License
 * @version     CVS: $Id$
 * @link        http://pear.php.net/package/Mail/
 */

/**
 * RFC 822 Email address list validation Utility
 *
 * What is it?
 *
 * This class will take an address string, and parse it into it's consituent
 * parts, be that either addresses, groups, or combinations. Nested groups
 * are not supported. The structure it returns is pretty straight forward,
 * and is similar to that provided by the imap_rfc822_parse_adrlist(). Use
 * print_r() to view the structure.
 *
 * How do I use it?
 *
 * $address_string = 'My Group: "Richard" <richard@localhost> (A comment), ted@example.com (Ted Bloggs), Barney;';
 * $structure = Mail_RFC822::parseAddressList($address_string, 'example.com', true)
 * print_r($structure);
 *
 * @author  Richard Heyes <richard@phpguru.org>
 * @author  Chuck Hagenbuch <chuck@horde.org>
 * @version $Revision$
 * @license BSD
 * @package Mail
 */
class Mail_RFC822 {

    /**
     * The address being parsed by the RFC822 object.
     * @var string $address
     */
    var $address = '';

    /**
     * The default domain to use for unqualified addresses.
     * @var string $default_domain
     */
    var $default_domain = 'localhost';

    /**
     * Should we return a nested array showing groups, or flatten everything?
     * @var boolean $nestGroups
     */
    var $nestGroups = true;

    /**
     * Whether or not to validate atoms for non-ascii characters.
     * @var boolean $validate
     */
    var $validate = true;

    /**
     * The array of raw addresses built up as we parse.
     * @var array $addresses
     */
    var $addresses = array();

    /**
     * The final array of parsed address information that we build up.
     * @var array $structure
     */
    var $structure = array();

    /**
     * The current error message, if any.
     * @var string $error
     */
    var $error = null;

    /**
     * An internal counter/pointer.
     * @var integer $index
     */
    var $index = null;

    /**
     * The number of groups that have been found in the address list.
     * @var integer $num_groups
     * @access public
     */
    var $num_groups = 0;

    /**
     * A variable so that we can tell whether or not we're inside a
     * Mail_RFC822 object.
     * @var boolean $mailRFC822
     */
    var $mailRFC822 = true;

    /**
    * A limit after which processing stops
    * @var int $limit
    */
    var $limit = null;

    /**
     * Sets up the object. The address must either be set here or when
     * calling parseAddressList(). One or the other.
     *
     * @param string  $address         The address(es) to validate.
     * @param string  $default_domain  Default domain/host etc. If not supplied, will be set to localhost.
     * @param boolean $nest_groups     Whether to return the structure with groups nested for easier viewing.
     * @param boolean $validate        Whether to validate atoms. Turn this off if you need to run addresses through before encoding the personal names, for instance.
     *
     * @return object Mail_RFC822 A new Mail_RFC822 object.
     */
    public function __construct($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null)
    {
        if (isset($address))        $this->address        = $address;
        if (isset($default_domain)) $this->default_domain = $default_domain;
        if (isset($nest_groups))    $this->nestGroups     = $nest_groups;
        if (isset($validate))       $this->validate       = $validate;
        if (isset($limit))          $this->limit          = $limit;
    }

    /**
     * Starts the whole process. The address must either be set here
     * or when creating the object. One or the other.
     *
     * @param string  $address         The address(es) to validate.
     * @param string  $default_domain  Default domain/host etc.
     * @param boolean $nest_groups     Whether to return the structure with groups nested for easier viewing.
     * @param boolean $validate        Whether to validate atoms. Turn this off if you need to run addresses through before encoding the personal names, for instance.
     *
     * @return array A structured array of addresses.
     */
    public function parseAddressList($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null)
    {
        if (!isset($this) || !isset($this->mailRFC822)) {
            $obj = new Mail_RFC822($address, $default_domain, $nest_groups, $validate, $limit);
            return $obj->parseAddressList();
        }

        if (isset($address))        $this->address        = $address;
        if (isset($default_domain)) $this->default_domain = $default_domain;
        if (isset($nest_groups))    $this->nestGroups     = $nest_groups;
        if (isset($validate))       $this->validate       = $validate;
        if (isset($limit))          $this->limit          = $limit;

        $this->structure  = array();
        $this->addresses  = array();
        $this->error      = null;
        $this->index      = null;

        // Unfold any long lines in $this->address.
        $this->address = preg_replace('/\r?\n/', "\r\n", $this->address);
        $this->address = preg_replace('/\r\n(\t| )+/', ' ', $this->address);

        while ($this->address = $this->_splitAddresses($this->address));

        if ($this->address === false || isset($this->error)) {
            require_once 'PEAR.php';
            return PEAR::raiseError($this->error);
        }

        // Validate each address individually.  If we encounter an invalid
        // address, stop iterating and return an error immediately.
        foreach ($this->addresses as $address) {
            $valid = $this->_validateAddress($address);

            if ($valid === false || isset($this->error)) {
                require_once 'PEAR.php';
                return PEAR::raiseError($this->error);
            }

            if (!$this->nestGroups) {
                $this->structure = array_merge($this->structure, $valid);
            } else {
                $this->structure[] = $valid;
            }
        }

        return $this->structure;
    }

    /**
     * Splits an address into separate addresses.
     *
     * @param string $address The addresses to split.
     * @return boolean Success or failure.
     */
    protected function _splitAddresses($address)
    {
        if (!empty($this->limit) && count($this->addresses) == $this->limit) {
            return '';
        }

        if ($this->_isGroup($address) && !isset($this->error)) {
            $split_char = ';';
            $is_group   = true;
        } elseif (!isset($this->error)) {
            $split_char = ',';
            $is_group   = false;
        } elseif (isset($this->error)) {
            return false;
        }

        // Split the string based on the above ten or so lines.
        $parts  = explode($split_char, $address);
        $string = $this->_splitCheck($parts, $split_char);

        // If a group...
        if ($is_group) {
            // If $string does not contain a colon outside of
            // brackets/quotes etc then something's fubar.

            // First check there's a colon at all:
            if (strpos($string, ':') === false) {
                $this->error = 'Invalid address: ' . $string;
                return false;
            }

            // Now check it's outside of brackets/quotes:
            if (!$this->_splitCheck(explode(':', $string), ':')) {
                return false;
            }

            // We must have a group at this point, so increase the counter:
            $this->num_groups++;
        }

        // $string now contains the first full address/group.
        // Add to the addresses array.
        $this->addresses[] = array(
                                   'address' => trim($string),
                                   'group'   => $is_group
                                   );

        // Remove the now stored address from the initial line, the +1
        // is to account for the explode character.
        $address = trim(substr($address, strlen($string) + 1));

        // If the next char is a comma and this was a group, then
        // there are more addresses, otherwise, if there are any more
        // chars, then there is another address.
        if ($is_group && substr($address, 0, 1) == ','){
            $address = trim(substr($address, 1));
            return $address;

        } elseif (strlen($address) > 0) {
            return $address;

        } else {
            return '';
        }

        // If you got here then something's off
        return false;
    }

    /**
     * Checks for a group at the start of the string.
     *
     * @param string $address The address to check.
     * @return boolean Whether or not there is a group at the start of the string.
     */
    protected function _isGroup($address)
    {
        // First comma not in quotes, angles or escaped:
        $parts  = explode(',', $address);
        $string = $this->_splitCheck($parts, ',');

        // Now we have the first address, we can reliably check for a
        // group by searching for a colon that's not escaped or in
        // quotes or angle brackets.
        if (count($parts = explode(':', $string)) > 1) {
            $string2 = $this->_splitCheck($parts, ':');
            return ($string2 !== $string);
        } else {
            return false;
        }
    }

    /**
     * A common function that will check an exploded string.
     *
     * @param array $parts The exloded string.
     * @param string $char  The char that was exploded on.
     * @return mixed False if the string contains unclosed quotes/brackets, or the string on success.
     */
    protected function _splitCheck($parts, $char)
    {
        $string = $parts[0];

        for ($i = 0; $i < count($parts); $i++) {
            if ($this->_hasUnclosedQuotes($string)
                || $this->_hasUnclosedBrackets($string, '<>')
                || $this->_hasUnclosedBrackets($string, '[]')
                || $this->_hasUnclosedBrackets($string, '()')
                || substr($string, -1) == '\\') {
                if (isset($parts[$i + 1])) {
                    $string = $string . $char . $parts[$i + 1];
                } else {
                    $this->error = 'Invalid address spec. Unclosed bracket or quotes';
                    return false;
                }
            } else {
                $this->index = $i;
                break;
            }
        }

        return $string;
    }

    /**
     * Checks if a string has unclosed quotes or not.
     *
     * @param string $string  The string to check.
     * @return boolean  True if there are unclosed quotes inside the string,
     *                  false otherwise.
     */
    protected function _hasUnclosedQuotes($string)
    {
        $string = trim($string);
        $iMax = strlen($string);
        $in_quote = false;
        $i = $slashes = 0;

        for (; $i < $iMax; ++$i) {
            switch ($string[$i]) {
            case '\\':
                ++$slashes;
                break;

            case '"':
                if ($slashes % 2 == 0) {
                    $in_quote = !$in_quote;
                }
                // Fall through to default action below.

            default:
                $slashes = 0;
                break;
            }
        }

        return $in_quote;
    }

    /**
     * Checks if a string has an unclosed brackets or not. IMPORTANT:
     * This function handles both angle brackets and square brackets;
     *
     * @param string $string The string to check.
     * @param string $chars  The characters to check for.
     * @return boolean True if there are unclosed brackets inside the string, false otherwise.
     */
    protected function _hasUnclosedBrackets($string, $chars)
    {
        $num_angle_start = substr_count($string, $chars[0]);
        $num_angle_end   = substr_count($string, $chars[1]);

        $this->_hasUnclosedBracketsSub($string, $num_angle_start, $chars[0]);
        $this->_hasUnclosedBracketsSub($string, $num_angle_end, $chars[1]);

        if ($num_angle_start < $num_angle_end) {
            $this->error = 'Invalid address spec. Unmatched quote or bracket (' . $chars . ')';
            return false;
        } else {
            return ($num_angle_start > $num_angle_end);
        }
    }

    /**
     * Sub function that is used only by hasUnclosedBrackets().
     *
     * @param string $string The string to check.
     * @param integer &$num    The number of occurences.
     * @param string $char   The character to count.
     * @return integer The number of occurences of $char in $string, adjusted for backslashes.
     */
    protected function _hasUnclosedBracketsSub($string, &$num, $char)
    {
        $parts = explode($char, $string);
        for ($i = 0; $i < count($parts); $i++){
            if (substr($parts[$i], -1) == '\\' || $this->_hasUnclosedQuotes($parts[$i]))
                $num--;
            if (isset($parts[$i + 1]))
                $parts[$i + 1] = $parts[$i] . $char . $parts[$i + 1];
        }

        return $num;
    }

    /**
     * Function to begin checking the address.
     *
     * @param string $address The address to validate.
     * @return mixed False on failure, or a structured array of address information on success.
     */
    protected function _validateAddress($address)
    {
        $is_group = false;
        $addresses = array();

        if ($address['group']) {
            $is_group = true;

            // Get the group part of the name
            $parts     = explode(':', $address['address']);
            $groupname = $this->_splitCheck($parts, ':');
            $structure = array();

            // And validate the group part of the name.
            if (!$this->_validatePhrase($groupname)){
                $this->error = 'Group name did not validate.';
                return false;
            } else {
                // Don't include groups if we are not nesting
                // them. This avoids returning invalid addresses.
                if ($this->nestGroups) {
                    $structure = new stdClass;
                    $structure->groupname = $groupname;
                }
            }

            $address['address'] = ltrim(substr($address['address'], strlen($groupname . ':')));
        }

        // If a group then split on comma and put into an array.
        // Otherwise, Just put the whole address in an array.
        if ($is_group) {
            while (strlen($address['address']) > 0) {
                $parts       = explode(',', $address['address']);
                $addresses[] = $this->_splitCheck($parts, ',');
                $address['address'] = trim(substr($address['address'], strlen(end($addresses) . ',')));
            }
        } else {
            $addresses[] = $address['address'];
        }

        // Trim the whitespace from all of the address strings.
        array_map('trim', $addresses);

        // Validate each mailbox.
        // Format could be one of: name <geezer@domain.com>
        //                         geezer@domain.com
        //                         geezer
        // ... or any other format valid by RFC 822.
        for ($i = 0; $i < count($addresses); $i++) {
            if (!$this->validateMailbox($addresses[$i])) {
                if (empty($this->error)) {
                    $this->error = 'Validation failed for: ' . $addresses[$i];
                }
                return false;
            }
        }

        // Nested format
        if ($this->nestGroups) {
            if ($is_group) {
                $structure->addresses = $addresses;
            } else {
                $structure = $addresses[0];
            }

        // Flat format
        } else {
            if ($is_group) {
                $structure = array_merge($structure, $addresses);
            } else {
                $structure = $addresses;
            }
        }

        return $structure;
    }

    /**
     * Function to validate a phrase.
     *
     * @param string $phrase The phrase to check.
     * @return boolean Success or failure.
     */
    protected function _validatePhrase($phrase)
    {
        // Splits on one or more Tab or space.
        $parts = preg_split('/[ \\x09]+/', $phrase, -1, PREG_SPLIT_NO_EMPTY);

        $phrase_parts = array();
        while (count($parts) > 0){
            $phrase_parts[] = $this->_splitCheck($parts, ' ');
            for ($i = 0; $i < $this->index + 1; $i++)
                array_shift($parts);
        }

        foreach ($phrase_parts as $part) {
            // If quoted string:
            if (substr($part, 0, 1) == '"') {
                if (!$this->_validateQuotedString($part)) {
                    return false;
                }
                continue;
            }

            // Otherwise it's an atom:
            if (!$this->_validateAtom($part)) return false;
        }

        return true;
    }

    /**
     * Function to validate an atom which from rfc822 is:
     * atom = 1*<any CHAR except specials, SPACE and CTLs>
     *
     * If validation ($this->validate) has been turned off, then
     * validateAtom() doesn't actually check anything. This is so that you
     * can split a list of addresses up before encoding personal names
     * (umlauts, etc.), for example.
     *
     * @param string $atom The string to check.
     * @return boolean Success or failure.
     */
    protected function _validateAtom($atom)
    {
        if (!$this->validate) {
            // Validation has been turned off; assume the atom is okay.
            return true;
        }

        // Check for any char from ASCII 0 - ASCII 127
        if (!preg_match('/^[\\x00-\\x7E]+$/i', $atom, $matches)) {
            return false;
        }

        // Check for specials:
        if (preg_match('/[][()<>@,;\\:". ]/', $atom)) {
            return false;
        }

        // Check for control characters (ASCII 0-31):
        if (preg_match('/[\\x00-\\x1F]+/', $atom)) {
            return false;
        }

        return true;
    }

    /**
     * Function to validate quoted string, which is:
     * quoted-string = <"> *(qtext/quoted-pair) <">
     *
     * @param string $qstring The string to check
     * @return boolean Success or failure.
     */
    protected function _validateQuotedString($qstring)
    {
        // Leading and trailing "
        $qstring = substr($qstring, 1, -1);

        // Perform check, removing quoted characters first.
        return !preg_match('/[\x0D\\\\"]/', preg_replace('/\\\\./', '', $qstring));
    }

    /**
     * Function to validate a mailbox, which is:
     * mailbox =   addr-spec         ; simple address
     *           / phrase route-addr ; name and route-addr
     *
     * @param string &$mailbox The string to check.
     * @return boolean Success or failure.
     */
    public function validateMailbox(&$mailbox)
    {
        // A couple of defaults.
        $phrase  = '';
        $comment = '';
        $comments = array();

        // Catch any RFC822 comments and store them separately.
        $_mailbox = $mailbox;
        while (strlen(trim($_mailbox)) > 0) {
            $parts = explode('(', $_mailbox);
            $before_comment = $this->_splitCheck($parts, '(');
            if ($before_comment != $_mailbox) {
                // First char should be a (.
                $comment    = substr(str_replace($before_comment, '', $_mailbox), 1);
                $parts      = explode(')', $comment);
                $comment    = $this->_splitCheck($parts, ')');
                $comments[] = $comment;

                // +2 is for the brackets
                $_mailbox = substr($_mailbox, strpos($_mailbox, '('.$comment)+strlen($comment)+2);
            } else {
                break;
            }
        }

        foreach ($comments as $comment) {
            $mailbox = str_replace("($comment)", '', $mailbox);
        }

        $mailbox = trim($mailbox);

        // Check for name + route-addr
        if (substr($mailbox, -1) == '>' && substr($mailbox, 0, 1) != '<') {
            $parts  = explode('<', $mailbox);
            $name   = $this->_splitCheck($parts, '<');

            $phrase     = trim($name);
            $route_addr = trim(substr($mailbox, strlen($name.'<'), -1));

            if ($this->_validatePhrase($phrase) === false || ($route_addr = $this->_validateRouteAddr($route_addr)) === false) {
                return false;
            }

        // Only got addr-spec
        } else {
            // First snip angle brackets if present.
            if (substr($mailbox, 0, 1) == '<' && substr($mailbox, -1) == '>') {
                $addr_spec = substr($mailbox, 1, -1);
            } else {
                $addr_spec = $mailbox;
            }

            if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) {
                return false;
            }
        }

        // Construct the object that will be returned.
        $mbox = new stdClass();

        // Add the phrase (even if empty) and comments
        $mbox->personal = $phrase;
        $mbox->comment  = isset($comments) ? $comments : array();

        if (isset($route_addr)) {
            $mbox->mailbox = $route_addr['local_part'];
            $mbox->host    = $route_addr['domain'];
            $route_addr['adl'] !== '' ? $mbox->adl = $route_addr['adl'] : '';
        } else {
            $mbox->mailbox = $addr_spec['local_part'];
            $mbox->host    = $addr_spec['domain'];
        }

        $mailbox = $mbox;
        return true;
    }

    /**
     * This function validates a route-addr which is:
     * route-addr = "<" [route] addr-spec ">"
     *
     * Angle brackets have already been removed at the point of
     * getting to this function.
     *
     * @param string $route_addr The string to check.
     * @return mixed False on failure, or an array containing validated address/route information on success.
     */
    protected function _validateRouteAddr($route_addr)
    {
        // Check for colon.
        if (strpos($route_addr, ':') !== false) {
            $parts = explode(':', $route_addr);
            $route = $this->_splitCheck($parts, ':');
        } else {
            $route = $route_addr;
        }

        // If $route is same as $route_addr then the colon was in
        // quotes or brackets or, of course, non existent.
        if ($route === $route_addr){
            unset($route);
            $addr_spec = $route_addr;
            if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) {
                return false;
            }
        } else {
            // Validate route part.
            if (($route = $this->_validateRoute($route)) === false) {
                return false;
            }

            $addr_spec = substr($route_addr, strlen($route . ':'));

            // Validate addr-spec part.
            if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) {
                return false;
            }
        }

        if (isset($route)) {
            $return['adl'] = $route;
        } else {
            $return['adl'] = '';
        }

        $return = array_merge($return, $addr_spec);
        return $return;
    }

    /**
     * Function to validate a route, which is:
     * route = 1#("@" domain) ":"
     *
     * @param string $route The string to check.
     * @return mixed False on failure, or the validated $route on success.
     */
    protected function _validateRoute($route)
    {
        // Split on comma.
        $domains = explode(',', trim($route));

        foreach ($domains as $domain) {
            $domain = str_replace('@', '', trim($domain));
            if (!$this->_validateDomain($domain)) return false;
        }

        return $route;
    }

    /**
     * Function to validate a domain, though this is not quite what
     * you expect of a strict internet domain.
     *
     * domain = sub-domain *("." sub-domain)
     *
     * @param string $domain The string to check.
     * @return mixed False on failure, or the validated domain on success.
     */
    protected function _validateDomain($domain)
    {
        // Note the different use of $subdomains and $sub_domains
        $subdomains = explode('.', $domain);

        while (count($subdomains) > 0) {
            $sub_domains[] = $this->_splitCheck($subdomains, '.');
            for ($i = 0; $i < $this->index + 1; $i++)
                array_shift($subdomains);
        }

        foreach ($sub_domains as $sub_domain) {
            if (!$this->_validateSubdomain(trim($sub_domain)))
                return false;
        }

        // Managed to get here, so return input.
        return $domain;
    }

    /**
     * Function to validate a subdomain:
     *   subdomain = domain-ref / domain-literal
     *
     * @param string $subdomain The string to check.
     * @return boolean Success or failure.
     */
    protected function _validateSubdomain($subdomain)
    {
        if (preg_match('|^\[(.*)]$|', $subdomain, $arr)){
            if (!$this->_validateDliteral($arr[1])) return false;
        } else {
            if (!$this->_validateAtom($subdomain)) return false;
        }

        // Got here, so return successful.
        return true;
    }

    /**
     * Function to validate a domain literal:
     *   domain-literal =  "[" *(dtext / quoted-pair) "]"
     *
     * @param string $dliteral The string to check.
     * @return boolean Success or failure.
     */
    protected function _validateDliteral($dliteral)
    {
        return !preg_match('/(.)[][\x0D\\\\]/', $dliteral, $matches) && ((! isset($matches[1])) || $matches[1] != '\\');
    }

    /**
     * Function to validate an addr-spec.
     *
     * addr-spec = local-part "@" domain
     *
     * @param string $addr_spec The string to check.
     * @return mixed False on failure, or the validated addr-spec on success.
     */
    protected function _validateAddrSpec($addr_spec)
    {
        $addr_spec = trim($addr_spec);

        // Split on @ sign if there is one.
        if (strpos($addr_spec, '@') !== false) {
            $parts      = explode('@', $addr_spec);
            $local_part = $this->_splitCheck($parts, '@');
            $domain     = substr($addr_spec, strlen($local_part . '@'));

        // No @ sign so assume the default domain.
        } else {
            $local_part = $addr_spec;
            $domain     = $this->default_domain;
        }

        if (($local_part = $this->_validateLocalPart($local_part)) === false) return false;
        if (($domain     = $this->_validateDomain($domain)) === false) return false;

        // Got here so return successful.
        return array('local_part' => $local_part, 'domain' => $domain);
    }

    /**
     * Function to validate the local part of an address:
     *   local-part = word *("." word)
     *
     * @param string $local_part
     * @return mixed False on failure, or the validated local part on success.
     */
    protected function _validateLocalPart($local_part)
    {
        $parts = explode('.', $local_part);
        $words = array();

        // Split the local_part into words.
        while (count($parts) > 0) {
            $words[] = $this->_splitCheck($parts, '.');
            for ($i = 0; $i < $this->index + 1; $i++) {
                array_shift($parts);
            }
        }

        // Validate each word.
        foreach ($words as $word) {
            // word cannot be empty (#17317)
            if ($word === '') {
                return false;
            }
            // If this word contains an unquoted space, it is invalid. (6.2.4)
            if (strpos($word, ' ') && $word[0] !== '"')
            {
                return false;
            }

            if ($this->_validatePhrase(trim($word)) === false) return false;
        }

        // Managed to get here, so return the input.
        return $local_part;
    }

    /**
     * Returns an approximate count of how many addresses are in the
     * given string. This is APPROXIMATE as it only splits based on a
     * comma which has no preceding backslash. Could be useful as
     * large amounts of addresses will end up producing *large*
     * structures when used with parseAddressList().
     *
     * @param  string $data Addresses to count
     * @return int          Approximate count
     */
    public function approximateCount($data)
    {
        return count(preg_split('/(?<!\\\\),/', $data));
    }

    /**
     * This is a email validating function separate to the rest of the
     * class. It simply validates whether an email is of the common
     * internet form: <user>@<domain>. This can be sufficient for most
     * people. Optional stricter mode can be utilised which restricts
     * mailbox characters allowed to alphanumeric, full stop, hyphen
     * and underscore.
     *
     * @param  string  $data   Address to check
     * @param  boolean $strict Optional stricter mode
     * @return mixed           False if it fails, an indexed array
     *                         username/domain if it matches
     */
    public function isValidInetAddress($data, $strict = false)
    {
        $regex = $strict ? '/^([.0-9a-z_+-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})$/i' : '/^([*+!.&#$|\'\\%\/0-9a-z^_`{}=?~:-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})$/i';
        if (preg_match($regex, trim($data), $matches)) {
            return array($matches[1], $matches[2]);
        } else {
            return false;
        }
    }

}
PKn�Z�+V����
Mail/mime.phpnu�[���<?php

/**
 * The Mail_Mime class is used to create MIME E-mail messages
 *
 * The Mail_Mime class provides an OO interface to create MIME
 * enabled email messages. This way you can create emails that
 * contain plain-text bodies, HTML bodies, attachments, inline
 * images and specific headers.
 *
 * Compatible with PHP version 5, 7 and 8
 *
 * LICENSE: This LICENSE is in the BSD license style.
 * Copyright (c) 2002-2003, Richard Heyes <richard@phpguru.org>
 * Copyright (c) 2003-2006, PEAR <pear-group@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 * - Neither the name of the authors, nor the names of its contributors 
 *   may be used to endorse or promote products derived from this 
 *   software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  Mail
 * @package   Mail_Mime
 * @author    Richard Heyes  <richard@phpguru.org>
 * @author    Tomas V.V. Cox <cox@idecnet.com>
 * @author    Cipriano Groenendal <cipri@php.net>
 * @author    Sean Coates <sean@php.net>
 * @author    Aleksander Machniak <alec@php.net>
 * @copyright 2003-2006 PEAR <pear-group@php.net>
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/Mail_mime
 *
 *            This class is based on HTML Mime Mail class from
 *            Richard Heyes <richard@phpguru.org> which was based also
 *            in the mime_mail.class by Tobias Ratschiller <tobias@dnet.it>
 *            and Sascha Schumann <sascha@schumann.cx>
 */


require_once 'PEAR.php';
require_once 'Mail/mimePart.php';


/**
 * The Mail_Mime class provides an OO interface to create MIME
 * enabled email messages. This way you can create emails that
 * contain plain-text bodies, HTML bodies, attachments, inline
 * images and specific headers.
 *
 * @category  Mail
 * @package   Mail_Mime
 * @author    Richard Heyes  <richard@phpguru.org>
 * @author    Tomas V.V. Cox <cox@idecnet.com>
 * @author    Cipriano Groenendal <cipri@php.net>
 * @author    Sean Coates <sean@php.net>
 * @copyright 2003-2006 PEAR <pear-group@php.net>
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/Mail_mime
 */
class Mail_mime
{
    /**
     * Contains the plain text part of the email
     *
     * @var string
     */
    protected $txtbody = '';

    /**
     * Contains the html part of the email
     *
     * @var string
     */
    protected $htmlbody = '';

    /**
     * Contains the text/calendar part of the email
     *
     * @var string
     */
    protected $calbody = '';

    /**
     * List of the attached images
     *
     * @var array
     */
    protected $html_images = array();

    /**
     * List of the attachements
     *
     * @var array
     */
    protected $parts = array();

    /**
     * Headers for the mail
     *
     * @var array
     */
    protected $headers = array();

    /**
     * Build parameters
     *
     * @var array
     */
    protected $build_params = array(
        // What encoding to use for the headers
        // Options: quoted-printable or base64
        'head_encoding' => 'quoted-printable',
        // What encoding to use for plain text
        // Options: 7bit, 8bit, base64, or quoted-printable
        'text_encoding' => 'quoted-printable',
        // What encoding to use for html
        // Options: 7bit, 8bit, base64, or quoted-printable
        'html_encoding' => 'quoted-printable',
        // What encoding to use for calendar part
        // Options: 7bit, 8bit, base64, or quoted-printable
        'calendar_encoding' => 'quoted-printable',
        // The character set to use for html
        'html_charset'  => 'ISO-8859-1',
        // The character set to use for text
        'text_charset'  => 'ISO-8859-1',
        // The character set to use for calendar part
        'calendar_charset'  => 'UTF-8',
        // The character set to use for headers
        'head_charset'  => 'ISO-8859-1',
        // End-of-line sequence
        'eol'           => "\r\n",
        // Delay attachment files IO until building the message
        'delay_file_io' => false,
        // Default calendar method
        'calendar_method' => 'request',
        // multipart part preamble (RFC2046 5.1.1)
        'preamble' => '',
    );


    /**
     * Constructor function
     *
     * @param mixed $params Build parameters that change the way the email
     *                      is built. Should be an associative array.
     *                      See $_build_params.
     *
     * @return void
     */
    public function __construct($params = array())
    {
        // Backward-compatible EOL setting
        if (is_string($params)) {
            $this->build_params['eol'] = $params;
        } else if (defined('MAIL_MIME_CRLF') && !isset($params['eol'])) {
            $this->build_params['eol'] = MAIL_MIME_CRLF;
        }

        // Update build parameters
        if (!empty($params) && is_array($params)) {
            $this->build_params = array_merge($this->build_params, $params);
        }
    }

    /**
     * Set build parameter value
     *
     * @param string $name  Parameter name
     * @param string $value Parameter value
     *
     * @return void
     * @since  1.6.0
     */
    public function setParam($name, $value)
    {
        $this->build_params[$name] = $value;
    }

    /**
     * Get build parameter value
     *
     * @param string $name Parameter name
     *
     * @return mixed Parameter value
     * @since  1.6.0
     */
    public function getParam($name)
    {
        return isset($this->build_params[$name]) ? $this->build_params[$name] : null;
    }

    /**
     * Accessor function to set the body text. Body text is used if
     * it's not an html mail being sent or else is used to fill the
     * text/plain part that emails clients who don't support
     * html should show.
     *
     * @param string $data   Either a string or the file name with the contents
     * @param bool   $isfile If true the first param should be treated
     *                       as a file name, else as a string (default)
     * @param bool   $append If true the text or file is appended to
     *                       the existing body, else the old body is
     *                       overwritten
     *
     * @return mixed True on success or PEAR_Error object
     */
    public function setTXTBody($data, $isfile = false, $append = false)
    {
        return $this->setBody('txtbody', $data, $isfile, $append);
    }

    /**
     * Get message text body
     *
     * @return string Text body
     * @since  1.6.0
     */
    public function getTXTBody()
    {
        return $this->txtbody;
    }

    /**
     * Adds a html part to the mail.
     *
     * @param string $data   Either a string or the file name with the contents
     * @param bool   $isfile A flag that determines whether $data is a
     *                       filename, or a string(false, default)
     *
     * @return bool True on success or PEAR_Error object
     */
    public function setHTMLBody($data, $isfile = false)
    {
        return $this->setBody('htmlbody', $data, $isfile);
    }

    /**
     * Get message HTML body
     *
     * @return string HTML body
     * @since  1.6.0
     */
    public function getHTMLBody()
    {
        return $this->htmlbody;
    }

    /**
     * Function to set a body of text/calendar part (not attachment)
     *
     * @param string $data     Either a string or the file name with the contents
     * @param bool   $isfile   If true the first param should be treated
     *                         as a file name, else as a string (default)
     * @param bool   $append   If true the text or file is appended to
     *                         the existing body, else the old body is
     *                         overwritten
     * @param string $method   iCalendar object method
     * @param string $charset  iCalendar character set
     * @param string $encoding Transfer encoding
     *
     * @return mixed True on success or PEAR_Error object
     * @since  1.9.0
     */
    public function setCalendarBody($data, $isfile = false, $append = false,
        $method = 'request', $charset = 'UTF-8', $encoding = 'quoted-printable'
    ) {
        $result = $this->setBody('calbody', $data, $isfile, $append);

        if ($result === true) {
            $this->build_params['calendar_method']  = $method;
            $this->build_params['calendar_charset'] = $charset;
            $this->build_params['calendar_encoding'] = $encoding;
        }
    }

    /**
     * Get body of calendar part
     *
     * @return string Calendar part body
     * @since  1.9.0
     */
    public function getCalendarBody()
    {
        return $this->calbody;
    }

    /**
     * Adds an image to the list of embedded images.
     * Images added this way will be added as related parts of the HTML message.
     *
     * To correctly match the HTML image with the related attachment
     * HTML should refer to it by a filename (specified in $file or $name
     * arguments) or by cid:<content-id> (specified in $content_id arg).
     *
     * @param string $file       The image file name OR image data itself
     * @param string $c_type     The content type
     * @param string $name       The filename of the image. Used to find
     *                           the image in HTML content.
     * @param bool   $isfile     Whether $file is a filename or not.
     *                           Defaults to true
     * @param string $content_id Desired Content-ID of MIME part
     *                           Defaults to generated unique ID
     *
     * @return bool True on success
     */
    public function addHTMLImage($file,
        $c_type = 'application/octet-stream',
        $name = '',
        $isfile = true,
        $content_id = null
    ) {
        $bodyfile = null;

        if ($isfile) {
            // Don't load file into memory
            if ($this->build_params['delay_file_io']) {
                $filedata = null;
                $bodyfile = $file;
            } else {
                if (self::isError($filedata = $this->file2str($file))) {
                    return $filedata;
                }
            }

            $filename = $name ? $name : $file;
        } else {
            $filedata = $file;
            $filename = $name;
        }

        if (!$content_id) {
            $content_id = preg_replace('/[^0-9a-zA-Z]/', '', uniqid(time(), true));
        }

        $this->html_images[] = array(
            'body'      => $filedata,
            'body_file' => $bodyfile,
            'name'      => $filename,
            'c_type'    => $c_type,
            'cid'       => $content_id
        );

        return true;
    }

    /**
     * Adds a file to the list of attachments.
     *
     * @param mixed  $file        The file name or the file contents itself,
     *                            it can be also Mail_mimePart object
     * @param string $c_type      The content type
     * @param string $name        The filename of the attachment
     *                            Only use if $file is the contents
     * @param bool   $isfile      Whether $file is a filename or not. Defaults to true
     * @param string $encoding    The type of encoding to use. Defaults to base64.
     *                            Possible values: 7bit, 8bit, base64 or quoted-printable.
     * @param string $disposition The content-disposition of this file
     *                            Defaults to attachment.
     *                            Possible values: attachment, inline.
     * @param string $charset     The character set of attachment's content.
     * @param string $language    The language of the attachment
     * @param string $location    The RFC 2557.4 location of the attachment
     * @param string $n_encoding  Encoding of the attachment's name in Content-Type
     *                            By default filenames are encoded using RFC2231 method
     *                            Here you can set RFC2047 encoding (quoted-printable
     *                            or base64) instead
     * @param string $f_encoding  Encoding of the attachment's filename
     *                            in Content-Disposition header.
     * @param string $description Content-Description header
     * @param string $h_charset   The character set of the headers e.g. filename
     *                            If not specified, $charset will be used
     * @param array  $add_headers Additional part headers. Array keys can be in form
     *                            of <header_name>:<parameter_name>
     *
     * @return mixed True on success or PEAR_Error object
     */
    public function addAttachment($file,
        $c_type      = 'application/octet-stream',
        $name        = '',
        $isfile      = true,
        $encoding    = 'base64',
        $disposition = 'attachment',
        $charset     = '',
        $language    = '',
        $location    = '',
        $n_encoding  = null,
        $f_encoding  = null,
        $description = '',
        $h_charset   = null,
        $add_headers = array()
    ) {
        if ($file instanceof Mail_mimePart) {
            $this->parts[] = $file;
            return true;
        }

        $bodyfile = null;

        if ($isfile) {
            // Don't load file into memory
            if ($this->build_params['delay_file_io']) {
                $filedata = null;
                $bodyfile = $file;
            } else {
                if (self::isError($filedata = $this->file2str($file))) {
                    return $filedata;
                }
            }
            // Force the name the user supplied, otherwise use $file
            $filename = ($name ? $name : $this->basename($file));
        } else {
            $filedata = $file;
            $filename = $name;
        }

        if (!strlen($filename)) {
            $msg = "The supplied filename for the attachment can't be empty";
            return self::raiseError($msg);
        }

        $this->parts[] = array(
            'body'        => $filedata,
            'body_file'   => $bodyfile,
            'name'        => $filename,
            'c_type'      => $c_type,
            'charset'     => $charset,
            'encoding'    => $encoding,
            'language'    => $language,
            'location'    => $location,
            'disposition' => $disposition,
            'description' => $description,
            'add_headers' => $add_headers,
            'name_encoding'     => $n_encoding,
            'filename_encoding' => $f_encoding,
            'headers_charset'   => $h_charset,
        );

        return true;
    }

    /**
     * Checks if the current message has many parts
     *
     * @return bool True if the message has many parts, False otherwise.
     * @since  1.9.0
     */
    public function isMultipart()
    {
        return count($this->parts) > 0 || count($this->html_images) > 0
            || (strlen($this->htmlbody) > 0 && strlen($this->txtbody) > 0);
    }

    /**
     * Get the contents of the given file name as string
     *
     * @param string $file_name Path of file to process
     *
     * @return string Contents of $file_name
     */
    protected function file2str($file_name)
    {
        // Check state of file and raise an error properly
        if (!file_exists($file_name)) {
            return self::raiseError('File not found: ' . $file_name);
        }
        if (!is_file($file_name)) {
            return self::raiseError('Not a regular file: ' . $file_name);
        }
        if (!is_readable($file_name)) {
            return self::raiseError('File is not readable: ' . $file_name);
        }

        // Temporarily reset magic_quotes_runtime and read file contents
        if (version_compare(PHP_VERSION, '5.4.0', '<')) {
            $magic_quotes = @ini_set('magic_quotes_runtime', 0);
        }

        $cont = file_get_contents($file_name);

        if (isset($magic_quotes)) {
            @ini_set('magic_quotes_runtime', $magic_quotes);
        }

        return $cont;
    }

    /**
     * Adds a text subpart to the mimePart object and
     * returns it during the build process.
     *
     * @param mixed $obj The object to add the part to, or
     *                   anything else if a new object is to be created.
     *
     * @return object The text mimePart object
     */
    protected function addTextPart($obj = null)
    {
        return $this->addBodyPart($obj, $this->txtbody, 'text/plain', 'text');
    }

    /**
     * Adds a html subpart to the mimePart object and
     * returns it during the build process.
     *
     * @param mixed $obj The object to add the part to, or
     *                   anything else if a new object is to be created.
     *
     * @return object The html mimePart object
     */
    protected function addHtmlPart($obj = null)
    {
        return $this->addBodyPart($obj, $this->htmlbody, 'text/html', 'html');
    }

    /**
     * Adds a calendar subpart to the mimePart object and
     * returns it during the build process.
     *
     * @param mixed $obj The object to add the part to, or
     *                   anything else if a new object is to be created.
     *
     * @return object The text mimePart object
     */
    protected function addCalendarPart($obj = null)
    {
        $ctype = 'text/calendar; method='. $this->build_params['calendar_method'];

        return $this->addBodyPart($obj, $this->calbody, $ctype, 'calendar');
    }

    /**
     * Creates a new mimePart object, using multipart/mixed as
     * the initial content-type and returns it during the
     * build process.
     *
     * @param array $params Additional part parameters
     *
     * @return object The multipart/mixed mimePart object
     */
    protected function addMixedPart($params = array())
    {
        $params['content_type'] = 'multipart/mixed';
        $params['eol']          = $this->build_params['eol'];

        // Create empty multipart/mixed Mail_mimePart object to return
        return new Mail_mimePart('', $params);
    }

    /**
     * Adds a multipart/alternative part to a mimePart
     * object (or creates one), and returns it during
     * the build process.
     *
     * @param mixed $obj The object to add the part to, or
     *                   anything else if a new object is to be created.
     *
     * @return object The multipart/mixed mimePart object
     */
    protected function addAlternativePart($obj = null)
    {
        $params['content_type'] = 'multipart/alternative';
        $params['eol']          = $this->build_params['eol'];

        if (is_object($obj)) {
            $ret = $obj->addSubpart('', $params);
        } else {
            $ret = new Mail_mimePart('', $params);
        }

        return $ret;
    }

    /**
     * Adds a multipart/related part to a mimePart
     * object (or creates one), and returns it during
     * the build process.
     *
     * @param mixed $obj The object to add the part to, or
     *                   anything else if a new object is to be created
     *
     * @return object The multipart/mixed mimePart object
     */
    protected function addRelatedPart($obj = null)
    {
        $params['content_type'] = 'multipart/related';
        $params['eol']          = $this->build_params['eol'];

        if (is_object($obj)) {
            $ret = $obj->addSubpart('', $params);
        } else {
            $ret = new Mail_mimePart('', $params);
        }

        return $ret;
    }

    /**
     * Adds an html image subpart to a mimePart object
     * and returns it during the build process.
     *
     * @param object $obj   The mimePart to add the image to
     * @param array  $value The image information
     *
     * @return object The image mimePart object
     */
    protected function addHtmlImagePart($obj, $value)
    {
        $params['content_type'] = $value['c_type'];
        $params['encoding']     = 'base64';
        $params['disposition']  = 'inline';
        $params['filename']     = $value['name'];
        $params['cid']          = $value['cid'];
        $params['body_file']    = $value['body_file'];
        $params['eol']          = $this->build_params['eol'];

        if (!empty($value['name_encoding'])) {
            $params['name_encoding'] = $value['name_encoding'];
        }
        if (!empty($value['filename_encoding'])) {
            $params['filename_encoding'] = $value['filename_encoding'];
        }

        return $obj->addSubpart($value['body'], $params);
    }

    /**
     * Adds an attachment subpart to a mimePart object
     * and returns it during the build process.
     *
     * @param object $obj   The mimePart to add the image to
     * @param mixed  $value The attachment information array or Mail_mimePart object
     *
     * @return object The image mimePart object
     */
    protected function addAttachmentPart($obj, $value)
    {
        if ($value instanceof Mail_mimePart) {
            return $obj->addSubpart($value);
        }

        $params['eol']          = $this->build_params['eol'];
        $params['filename']     = $value['name'];
        $params['encoding']     = $value['encoding'];
        $params['content_type'] = $value['c_type'];
        $params['body_file']    = $value['body_file'];
        $params['disposition']  = isset($value['disposition']) ?
                                  $value['disposition'] : 'attachment';

        // content charset
        if (!empty($value['charset'])) {
            $params['charset'] = $value['charset'];
        }
        // headers charset (filename, description)
        if (!empty($value['headers_charset'])) {
            $params['headers_charset'] = $value['headers_charset'];
        }
        if (!empty($value['language'])) {
            $params['language'] = $value['language'];
        }
        if (!empty($value['location'])) {
            $params['location'] = $value['location'];
        }
        if (!empty($value['name_encoding'])) {
            $params['name_encoding'] = $value['name_encoding'];
        }
        if (!empty($value['filename_encoding'])) {
            $params['filename_encoding'] = $value['filename_encoding'];
        }
        if (!empty($value['description'])) {
            $params['description'] = $value['description'];
        }
        if (is_array($value['add_headers'])) {
            $params['headers'] = $value['add_headers'];
        }

        return $obj->addSubpart($value['body'], $params);
    }

    /**
     * Returns the complete e-mail, ready to send using an alternative
     * mail delivery method. Note that only the mailpart that is made
     * with Mail_Mime is created. This means that,
     * YOU WILL HAVE NO TO: HEADERS UNLESS YOU SET IT YOURSELF
     * using the $headers parameter!
     *
     * @param string $separation The separation between these two parts.
     * @param array  $params     The Build parameters passed to the
     *                           get() function. See get() for more info.
     * @param array  $headers    The extra headers that should be passed
     *                           to the headers() method.
     *                           See that function for more info.
     * @param bool   $overwrite  Overwrite the existing headers with new.
     *
     * @return mixed The complete e-mail or PEAR error object
     */
    public function getMessage($separation = null, $params = null, $headers = null,
        $overwrite = false
    ) {
        if ($separation === null) {
            $separation = $this->build_params['eol'];
        }

        $body = $this->get($params);

        if (self::isError($body)) {
            return $body;
        }

        return $this->txtHeaders($headers, $overwrite) . $separation . $body;
    }

    /**
     * Returns the complete e-mail body, ready to send using an alternative
     * mail delivery method.
     *
     * @param array $params The Build parameters passed to the
     *                      get() method. See get() for more info.
     *
     * @return mixed The e-mail body or PEAR error object
     * @since  1.6.0
     */
    public function getMessageBody($params = null)
    {
        return $this->get($params, null, true);
    }

    /**
     * Writes (appends) the complete e-mail into file.
     *
     * @param string $filename  Output file location
     * @param array  $params    The Build parameters passed to the
     *                          get() method. See get() for more info.
     * @param array  $headers   The extra headers that should be passed
     *                          to the headers() function.
     *                          See that function for more info.
     * @param bool   $overwrite Overwrite the existing headers with new.
     *
     * @return mixed True or PEAR error object
     * @since  1.6.0
     */
    public function saveMessage($filename, $params = null, $headers = null, $overwrite = false)
    {
        // Check state of file and raise an error properly
        if (file_exists($filename) && !is_writable($filename)) {
            return self::raiseError('File is not writable: ' . $filename);
        }

        // Temporarily reset magic_quotes_runtime and read file contents
        if (version_compare(PHP_VERSION, '5.4.0', '<')) {
            $magic_quotes = @ini_set('magic_quotes_runtime', 0);
        }

        if (!($fh = fopen($filename, 'ab'))) {
            return self::raiseError('Unable to open file: ' . $filename);
        }

        // Write message headers into file (skipping Content-* headers)
        $head = $this->txtHeaders($headers, $overwrite, true);
        if (fwrite($fh, $head) === false) {
            return self::raiseError('Error writing to file: ' . $filename);
        }

        fclose($fh);

        if (isset($magic_quotes)) {
            @ini_set('magic_quotes_runtime', $magic_quotes);
        }

        // Write the rest of the message into file
        $res = $this->get($params, $filename);

        return $res ? $res : true;
    }

    /**
     * Writes (appends) the complete e-mail body into file or stream.
     *
     * @param mixed $filename Output filename or file pointer where to save
     *                        the message instead of returning it
     * @param array $params   The Build parameters passed to the
     *                        get() method. See get() for more info.
     *
     * @return mixed True or PEAR error object
     * @since  1.6.0
     */
    public function saveMessageBody($filename, $params = null)
    {
        if (!is_resource($filename)) {
            // Check state of file and raise an error properly
            if (!file_exists($filename) || !is_writable($filename)) {
                return self::raiseError('File is not writable: ' . $filename);
            }

            if (!($fh = fopen($filename, 'ab'))) {
                return self::raiseError('Unable to open file: ' . $filename);
            }
        } else {
            $fh = $filename;
        }

        // Temporarily reset magic_quotes_runtime and read file contents
        if (version_compare(PHP_VERSION, '5.4.0', '<')) {
            $magic_quotes = @ini_set('magic_quotes_runtime', 0);
        }

        // Write the rest of the message into file
        $res = $this->get($params, $fh, true);

        if (!is_resource($filename)) {
            fclose($fh);
        }

        if (isset($magic_quotes)) {
            @ini_set('magic_quotes_runtime', $magic_quotes);
        }

        return $res ? $res : true;
    }

    /**
     * Builds the multipart message from the list ($this->parts) and
     * returns the mime content.
     *
     * @param array   $params    Build parameters that change the way the email
     *                           is built. Should be associative. See $_build_params.
     * @param mixed   $filename  Output filename or file pointer where to save
     *                           the message instead of returning it
     * @param boolean $skip_head True if you want to return/save only the message
     *                           without headers
     *
     * @return mixed The MIME message content string, null or PEAR error object
     */
    public function get($params = null, $filename = null, $skip_head = false)
    {
        if (!empty($params) && is_array($params)) {
            $this->build_params = array_merge($this->build_params, $params);
        }

        if (isset($this->headers['From'])) {
            // Bug #11381: Illegal characters in domain ID
            if (preg_match('#(@[0-9a-zA-Z\-\.]+)#', $this->headers['From'], $matches)) {
                $domainID = $matches[1];
            } else {
                $domainID = '@localhost';
            }

            foreach ($this->html_images as $i => $img) {
                $cid = $this->html_images[$i]['cid'];
                if (!preg_match('#'.preg_quote($domainID).'$#', $cid)) {
                    $this->html_images[$i]['cid'] = $cid . $domainID;
                }
            }
        }

        if (count($this->html_images) && strlen($this->htmlbody) > 0) {
            foreach ($this->html_images as $key => $value) {
                $rval  = preg_quote($value['name'], '#');
                $regex = array(
                    '#(\s)((?i)src|background|href(?-i))\s*=\s*(["\']?)' . $rval . '\3#',
                    '#(?i)url(?-i)\(\s*(["\']?)' . $rval . '\1\s*\)#',
                );

                $rep = array(
                    '\1\2=\3cid:' . $value['cid'] .'\3',
                    'url(\1cid:' . $value['cid'] . '\1)',
                );

                $this->htmlbody = preg_replace($regex, $rep, $this->htmlbody);
                $this->html_images[$key]['name']
                    = $this->basename($this->html_images[$key]['name']);
            }
        }

        $this->checkParams();

        $message = $this->buildBodyPart();

        if (!isset($message)) {
            return null;
        }

        // Use saved boundary
        if (!empty($this->build_params['boundary'])) {
            $boundary = $this->build_params['boundary'];
        } else {
            $boundary = null;
        }

        // Write output to file
        if ($filename) {
            // Append mimePart message headers and body into file
            $headers = $message->encodeToFile($filename, $boundary, $skip_head);
            if (self::isError($headers)) {
                return $headers;
            }
            $this->headers = array_merge($this->headers, $headers);
        } else {
            $output = $message->encode($boundary, $skip_head);
            if (self::isError($output)) {
                return $output;
            }
            $this->headers = array_merge($this->headers, $output['headers']);
        }

        // remember the boundary used, in case we'd handle headers() call later
        if (empty($boundary) && !empty($this->headers['Content-Type'])) {
            if (preg_match('/boundary="([^"]+)/', $this->headers['Content-Type'], $m)) {
                $this->build_params['boundary'] = $m[1];
            }
        }

        return $filename ? null : $output['body'];
    }

    /**
     * Builds the main body MIME part for the email body. It will add a mixed part
     * if attachments are found.  If no attachments are found  it will return an
     * alternative part if several body texts are found (text, html, calendar),
     * or a single part if only one body text is found.
     *
     * @return Mail_mimePart|null The corresponding part for the body or null.
     *
     * @see buildAlternativeParts
     * @see buildHtmlParts
     */
    protected function buildBodyPart()
    {
        $parts_count  = count($this->parts);
        $mixed_params = array('preamble' => $this->build_params['preamble']);
        $message      = null;

        if ($parts_count > 0) {
            $message = $this->addMixedPart($mixed_params);
            $this->buildAlternativeParts($message, null);
            for ($i = 0; $i < $parts_count; $i++) {
                $this->addAttachmentPart($message, $this->parts[$i]);
            }
        } else {
            $message = $this->buildAlternativeParts(null, $mixed_params);
        }

        return $message;
    }

    /**
     * Builds a single text, html, or calendar part only if one of them is found.
     * If two or more parts are found, then an alternative part containing them is built.
     *
     * @param Mail_mimePart|null $parent_part  The parent mime part to add
     *                                         the part or null
     * @param array              $mixed_params The needed params to create the
     *                                         part when no parent_part is
     *                                         received.
     *
     * @return null|object The main part built inside the method. It will be an
     *                     alternative part or text, html, or calendar part.
     *                     Null if no body texts are found.
     */
    protected function buildAlternativeParts($parent_part, $mixed_params = null)
    {
        $html               = strlen($this->htmlbody) > 0;
        $calendar           = strlen($this->calbody) > 0;
        $has_text           = strlen($this->txtbody) > 0;
        $alternatives_count = $html + $calendar + $has_text;

        if ($alternatives_count > 1) {
            $alt_part = $this->addAlternativePart($parent_part ? $parent_part : $mixed_params);
        } else {
            $alt_part = null;
        }

        $dest_part = $alt_part ? $alt_part : $parent_part;
        $part = null;

        if ($has_text) {
            $part = $this->addTextPart($dest_part);
        }

        if ($html) {
            $part = $this->buildHtmlParts($dest_part);
        }

        if ($calendar) {
            $part = $this->addCalendarPart($dest_part);
        }

        return $dest_part ? $dest_part : $part;
    }

    /**
     * Builds html part as a single part or inside a related part with the html
     * images thar were found.
     *
     * @param Mail_mimePart|null $parent_part The object to add the part to,
     *                                        or anything else if a new object
     *                                        is to be created.
     *
     * @return Mail_mimePart|null The created part or null if no htmlbody found.
     */
    protected function buildHtmlParts($parent_part)
    {
        if (!strlen($this->htmlbody)) {
            return null;
        }

        $count_html_images = count($this->html_images);

        if ($count_html_images > 0) {
            $part = $this->addRelatedPart($parent_part);
            $this->addHtmlPart($part);
        } else {
            $part = $this->addHtmlPart($parent_part);
        }

        for ($i = 0; $i < $count_html_images; $i++) {
            $this->addHtmlImagePart($part, $this->html_images[$i]);
        }

        return $part;
    }

    /**
     * Returns an array with the headers needed to prepend to the email
     * (MIME-Version and Content-Type). Format of argument is:
     * $array['header-name'] = 'header-value';
     *
     * @param array $xtra_headers Assoc array with any extra headers (optional)
     *                            (Don't set Content-Type for multipart messages here!)
     * @param bool  $overwrite    Overwrite already existing headers.
     * @param bool  $skip_content Don't return content headers: Content-Type,
     *                            Content-Disposition and Content-Transfer-Encoding
     *
     * @return array Assoc array with the mime headers
     */
    public function headers($xtra_headers = null, $overwrite = false, $skip_content = false)
    {
        // Add mime version header
        $headers['MIME-Version'] = '1.0';

        if (!empty($xtra_headers)) {
            $headers = array_merge($headers, $xtra_headers);
        }

        if ($overwrite) {
            $this->headers = array_merge($this->headers, $headers);
        } else {
            $this->headers = array_merge($headers, $this->headers);
        }

        // Always reset Content-Type/Content-Transfer-Encoding headers
        // In case the message structure changed in meantime
        unset($this->headers['Content-Type']);
        unset($this->headers['Content-Transfer-Encoding']);
        unset($this->headers['Content-Disposition']);

        $this->headers = array_merge($this->headers, $this->contentHeaders());

        $headers = $this->headers;

        if ($skip_content) {
            unset($headers['Content-Type']);
            unset($headers['Content-Transfer-Encoding']);
            unset($headers['Content-Disposition']);
        } else if (!empty($this->build_params['ctype'])) {
            $headers['Content-Type'] = $this->build_params['ctype'];
        }

        return $this->encodeHeaders($headers);
    }

    /**
     * Get the text version of the headers
     * (usefull if you want to use the PHP mail() function)
     *
     * @param array $xtra_headers Assoc array with any extra headers (optional)
     *                            (Don't set Content-Type for multipart messages here!)
     * @param bool  $overwrite    Overwrite the existing headers with new.
     * @param bool  $skip_content Don't return content headers: Content-Type,
     *                            Content-Disposition and Content-Transfer-Encoding
     *
     * @return string Plain text headers
     */
    public function txtHeaders($xtra_headers = null, $overwrite = false, $skip_content = false)
    {
        $headers = $this->headers($xtra_headers, $overwrite, $skip_content);

        // Place Received: headers at the beginning of the message
        // Spam detectors often flag messages with it after the Subject: as spam
        if (isset($headers['Received'])) {
            $received = $headers['Received'];
            unset($headers['Received']);
            $headers = array('Received' => $received) + $headers;
        }

        $ret = '';
        $eol = $this->build_params['eol'];

        foreach ($headers as $key => $val) {
            if (is_array($val)) {
                foreach ($val as $value) {
                    $ret .= "$key: $value" . $eol;
                }
            } else {
                $ret .= "$key: $val" . $eol;
            }
        }

        return $ret;
    }

    /**
     * Sets message Content-Type header.
     * Use it to build messages with various content-types e.g. miltipart/raport
     * not supported by contentHeaders() function.
     *
     * @param string $type   Type name
     * @param array  $params Hash array of header parameters
     *
     * @return void
     * @since  1.7.0
     */
    public function setContentType($type, $params = array())
    {
        $header = $type;

        $eol = !empty($this->build_params['eol']) ? $this->build_params['eol'] : "\r\n";

        // add parameters
        $token_regexp = '#([^\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7E])#';

        if (is_array($params)) {
            foreach ($params as $name => $value) {
                if ($name == 'boundary') {
                    $this->build_params['boundary'] = $value;
                } else if (!preg_match($token_regexp, $value)) {
                    $header .= ";$eol $name=$value";
                } else {
                    $value = addcslashes($value, '\\"');
                    $header .= ";$eol $name=\"$value\"";
                }
            }
        }

        // add required boundary parameter if not defined
        if (stripos($type, 'multipart/') === 0) {
            if (empty($this->build_params['boundary'])) {
                $this->build_params['boundary'] = '=_' . md5(rand() . microtime());
            }

            $header .= ";$eol boundary=\"".$this->build_params['boundary']."\"";
        }

        $this->build_params['ctype'] = $header;
    }

    /**
     * Sets the Subject header
     *
     * @param string $subject String to set the subject to.
     *
     * @return void
     */
    public function setSubject($subject)
    {
        $this->headers['Subject'] = $subject;
    }

    /**
     * Set an email to the From (the sender) header
     *
     * @param string $email The email address to use
     *
     * @return void
     */
    public function setFrom($email)
    {
        $this->headers['From'] = $email;
    }

    /**
     * Add an email to the To header
     * (multiple calls to this method are allowed)
     *
     * @param string $email The email direction to add
     *
     * @return void
     */
    public function addTo($email)
    {
        if (isset($this->headers['To'])) {
            $this->headers['To'] .= ", $email";
        } else {
            $this->headers['To'] = $email;
        }
    }

    /**
     * Add an email to the Cc (carbon copy) header
     * (multiple calls to this method are allowed)
     *
     * @param string $email The email direction to add
     *
     * @return void
     */
    public function addCc($email)
    {
        if (isset($this->headers['Cc'])) {
            $this->headers['Cc'] .= ", $email";
        } else {
            $this->headers['Cc'] = $email;
        }
    }

    /**
     * Add an email to the Bcc (blank carbon copy) header
     * (multiple calls to this method are allowed)
     *
     * @param string $email The email direction to add
     *
     * @return void
     */
    public function addBcc($email)
    {
        if (isset($this->headers['Bcc'])) {
            $this->headers['Bcc'] .= ", $email";
        } else {
            $this->headers['Bcc'] = $email;
        }
    }

    /**
     * Since the PHP send function requires you to specify
     * recipients (To: header) separately from the other
     * headers, the To: header is not properly encoded.
     * To fix this, you can use this public method to encode
     * your recipients before sending to the send function.
     *
     * @param string $recipients A comma-delimited list of recipients
     *
     * @return string Encoded data
     */
    public function encodeRecipients($recipients)
    {
        $input  = array('To' => $recipients);
        $retval = $this->encodeHeaders($input);

        return $retval['To'] ;
    }

    /**
     * Encodes headers as per RFC2047
     *
     * @param array $input  The header data to encode
     * @param array $params Extra build parameters
     *
     * @return array Encoded data
     */
    protected function encodeHeaders($input, $params = array())
    {
        $build_params = $this->build_params;

        if (!empty($params)) {
            $build_params = array_merge($build_params, $params);
        }

        foreach ($input as $hdr_name => $hdr_value) {
            if (is_array($hdr_value)) {
                foreach ($hdr_value as $idx => $value) {
                    $input[$hdr_name][$idx] = $this->encodeHeader(
                        $hdr_name, $value,
                        $build_params['head_charset'], $build_params['head_encoding']
                    );
                }
            } else if ($hdr_value !== null) {
                $input[$hdr_name] = $this->encodeHeader(
                    $hdr_name, $hdr_value,
                    $build_params['head_charset'], $build_params['head_encoding']
                );
            } else {
                unset($input[$hdr_name]);
            }
        }

        return $input;
    }

    /**
     * Encodes a header as per RFC2047
     *
     * @param string $name     The header name
     * @param string $value    The header data to encode
     * @param string $charset  Character set name
     * @param string $encoding Encoding name (base64 or quoted-printable)
     *
     * @return string Encoded header data (without a name)
     * @since  1.5.3
     */
    public function encodeHeader($name, $value, $charset, $encoding)
    {
        return Mail_mimePart::encodeHeader(
            $name, $value, $charset, $encoding, $this->build_params['eol']
        );
    }

    /**
     * Get file's basename (locale independent)
     *
     * @param string $filename Filename
     *
     * @return string Basename
     */
    protected function basename($filename)
    {
        // basename() is not unicode safe and locale dependent
        if (stristr(PHP_OS, 'win') || stristr(PHP_OS, 'netware')) {
            return preg_replace('/^.*[\\\\\\/]/', '', $filename);
        } else {
            return preg_replace('/^.*[\/]/', '', $filename);
        }
    }

    /**
     * Get Content-Type and Content-Transfer-Encoding headers of the message
     *
     * @return array Headers array
     */
    protected function contentHeaders()
    {
        $attachments      = count($this->parts) > 0;
        $html_images      = count($this->html_images) > 0;
        $html             = strlen($this->htmlbody) > 0;
        $calendar         = strlen($this->calbody) > 0;
        $has_text         = strlen($this->txtbody) > 0;
        $has_alternatives = ($html + $calendar + $has_text) > 1;
        $headers          = array();

        // See get()
        switch (true) {
        case $has_text && !$attachments && !$has_alternatives:
            $headers['Content-Type'] = 'text/plain';
            break;

        case $html && !$html_images && !$attachments && !$has_alternatives:
            $headers['Content-Type'] = 'text/html';
            break;

        case $html && $html_images && !$attachments && !$has_alternatives:
            $headers['Content-Type'] = 'multipart/related';
            break;

        case $calendar && !$attachments && !$has_alternatives:
            $headers['Content-Type'] = 'text/calendar';
            break;

        case $has_alternatives && !$attachments:
            $headers['Content-Type'] = 'multipart/alternative';
            break;

        case $attachments:
            $headers['Content-Type'] = 'multipart/mixed';
            break;
        }

        // Note: This is outside of the above switch construct to workaround
        // opcache bug: https://bugzilla.opensuse.org/show_bug.cgi?id=1166235
        if (empty($headers)) {
            return $headers;
        }

        $this->checkParams();

        $eol = !empty($this->build_params['eol'])
            ? $this->build_params['eol'] : "\r\n";

        if ($headers['Content-Type'] == 'text/plain') {
            // single-part message: add charset and encoding
            if ($this->build_params['text_charset']) {
                $charset = 'charset=' . $this->build_params['text_charset'];
                // place charset parameter in the same line, if possible
                // 26 = strlen("Content-Type: text/plain; ")
                $headers['Content-Type']
                    .= (strlen($charset) + 26 <= 76) ? "; $charset" : ";$eol $charset";
            }

            $headers['Content-Transfer-Encoding']
                = $this->build_params['text_encoding'];
        } else if ($headers['Content-Type'] == 'text/html') {
            // single-part message: add charset and encoding
            if ($this->build_params['html_charset']) {
                $charset = 'charset=' . $this->build_params['html_charset'];
                // place charset parameter in the same line, if possible
                $headers['Content-Type']
                    .= (strlen($charset) + 25 <= 76) ? "; $charset" : ";$eol $charset";
            }
            $headers['Content-Transfer-Encoding']
                = $this->build_params['html_encoding'];
        } else if ($headers['Content-Type'] == 'text/calendar') {
            // single-part message: add charset and encoding
            if ($this->build_params['calendar_charset']) {
                $charset = 'charset=' . $this->build_params['calendar_charset'];
                $headers['Content-Type'] .= "; $charset";
            }

            if ($this->build_params['calendar_method']) {
                $method = 'method=' . $this->build_params['calendar_method'];
                $headers['Content-Type'] .= "; $method";
            }

            $headers['Content-Transfer-Encoding']
                = $this->build_params['calendar_encoding'];
        } else {
            // multipart message: and boundary
            if (!empty($this->build_params['boundary'])) {
                $boundary = $this->build_params['boundary'];
            } else if (!empty($this->headers['Content-Type'])
                && preg_match('/boundary="([^"]+)"/', $this->headers['Content-Type'], $m)
            ) {
                $boundary = $m[1];
            } else {
                $boundary = '=_' . md5(rand() . microtime());
            }

            $this->build_params['boundary'] = $boundary;
            $headers['Content-Type'] .= ";$eol boundary=\"$boundary\"";
        }

        return $headers;
    }

    /**
     * Validate and set build parameters
     *
     * @return void
     */
    protected function checkParams()
    {
        $encodings = array('7bit', '8bit', 'base64', 'quoted-printable');

        $this->build_params['text_encoding']
            = strtolower($this->build_params['text_encoding']);
        $this->build_params['html_encoding']
            = strtolower($this->build_params['html_encoding']);
        $this->build_params['calendar_encoding']
            = strtolower($this->build_params['calendar_encoding']);

        if (!in_array($this->build_params['text_encoding'], $encodings)) {
            $this->build_params['text_encoding'] = '7bit';
        }
        if (!in_array($this->build_params['html_encoding'], $encodings)) {
            $this->build_params['html_encoding'] = '7bit';
        }
        if (!in_array($this->build_params['calendar_encoding'], $encodings)) {
            $this->build_params['calendar_encoding'] = '7bit';
        }

        // text body
        if ($this->build_params['text_encoding'] == '7bit'
            && !preg_match('/ascii/i', $this->build_params['text_charset'])
            && preg_match('/[^\x00-\x7F]/', $this->txtbody)
        ) {
            $this->build_params['text_encoding'] = 'quoted-printable';
        }
        // html body
        if ($this->build_params['html_encoding'] == '7bit'
            && !preg_match('/ascii/i', $this->build_params['html_charset'])
            && preg_match('/[^\x00-\x7F]/', $this->htmlbody)
        ) {
            $this->build_params['html_encoding'] = 'quoted-printable';
        }
        // calendar body
        if ($this->build_params['calendar_encoding'] == '7bit'
            && !preg_match('/ascii/i', $this->build_params['calendar_charset'])
            && preg_match('/[^\x00-\x7F]/', $this->calbody)
        ) {
            $this->build_params['calendar_encoding'] = 'quoted-printable';
        }
    }

    /**
     * Set body of specified message part
     *
     * @param string $type   One of: txtbody, calbody, htmlbody
     * @param string $data   Either a string or the file name with the contents
     * @param bool   $isfile If true the first param should be treated
     *                       as a file name, else as a string (default)
     * @param bool   $append If true the text or file is appended to
     *                       the existing body, else the old body is
     *                       overwritten
     *
     * @return mixed True on success or PEAR_Error object
     */
    protected function setBody($type, $data, $isfile = false, $append = false)
    {
        if ($isfile) {
            $data = $this->file2str($data);
            if (self::isError($data)) {
                return $data;
            }
        }

        if (!$append) {
            $this->{$type} = $data;
        } else {
            $this->{$type} .= $data;
        }

        return true;
    }

    /**
     * Adds a subpart to the mimePart object and
     * returns it during the build process.
     *
     * @param mixed  $obj   The object to add the part to, or
     *                      anything else if a new object is to be created.
     * @param string $body  Part body
     * @param string $ctype Part content type
     * @param string $type  Internal part type
     *
     * @return object The mimePart object
     */
    protected function addBodyPart($obj, $body, $ctype, $type)
    {
        $params['content_type'] = $ctype;
        $params['encoding']     = $this->build_params[$type . '_encoding'];
        $params['charset']      = $this->build_params[$type . '_charset'];
        $params['eol']          = $this->build_params['eol'];

        if (is_object($obj)) {
            $ret = $obj->addSubpart($body, $params);
        } else {
            $ret = new Mail_mimePart($body, $params);
        }

        return $ret;
    }

    /**
     * PEAR::isError implementation
     *
     * @param mixed $data Object
     *
     * @return bool True if object is an instance of PEAR_Error
     */
    public static function isError($data)
    {
        // PEAR::isError() is not PHP 5.4 compatible (see Bug #19473)
        if (is_a($data, 'PEAR_Error')) {
            return true;
        }

        return false;
    }

    /**
     * PEAR::raiseError implementation
     *
     * @param string $message A text error message
     *
     * @return PEAR_Error Instance of PEAR_Error
     */
    public static function raiseError($message)
    {
        // PEAR::raiseError() is not PHP 5.4 compatible
        return new PEAR_Error($message);
    }
}
PKn�Zx�ع���Mail/mimeDecode.phpnu�[���<?php
/**
 * The Mail_mimeDecode class is used to decode mail/mime messages
 *
 * This class will parse a raw mime email and return
 * the structure. Returned structure is similar to
 * that returned by imap_fetchstructure().
 *
 *  +----------------------------- IMPORTANT ------------------------------+
 *  | Usage of this class compared to native php extensions such as        |
 *  | mailparse or imap, is slow and may be feature deficient. If available|
 *  | you are STRONGLY recommended to use the php extensions.              |
 *  +----------------------------------------------------------------------+
 *
 * Compatible with PHP versions 4 and 5
 *
 * LICENSE: This LICENSE is in the BSD license style.
 * Copyright (c) 2002-2003, Richard Heyes <richard@phpguru.org>
 * Copyright (c) 2003-2006, PEAR <pear-group@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 * - Neither the name of the authors, nor the names of its contributors 
 *   may be used to endorse or promote products derived from this 
 *   software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   Mail
 * @package    Mail_Mime
 * @author     Richard Heyes  <richard@phpguru.org>
 * @author     George Schlossnagle <george@omniti.com>
 * @author     Cipriano Groenendal <cipri@php.net>
 * @author     Sean Coates <sean@php.net>
 * @copyright  2003-2006 PEAR <pear-group@php.net>
 * @license    http://www.opensource.org/licenses/bsd-license.php BSD License
 * @version    CVS: $Id: mimeDecode.php 337165 2015-07-15 09:42:08Z alan_k $
 * @link       http://pear.php.net/package/Mail_mime
 */


/**
 * require PEAR
 *
 * This package depends on PEAR to raise errors.
 */
require_once 'PEAR.php';


/**
 * The Mail_mimeDecode class is used to decode mail/mime messages
 *
 * This class will parse a raw mime email and return the structure.
 * Returned structure is similar to that returned by imap_fetchstructure().
 *
 *  +----------------------------- IMPORTANT ------------------------------+
 *  | Usage of this class compared to native php extensions such as        |
 *  | mailparse or imap, is slow and may be feature deficient. If available|
 *  | you are STRONGLY recommended to use the php extensions.              |
 *  +----------------------------------------------------------------------+
 *
 * @category   Mail
 * @package    Mail_Mime
 * @author     Richard Heyes  <richard@phpguru.org>
 * @author     George Schlossnagle <george@omniti.com>
 * @author     Cipriano Groenendal <cipri@php.net>
 * @author     Sean Coates <sean@php.net>
 * @copyright  2003-2006 PEAR <pear-group@php.net>
 * @license    http://www.opensource.org/licenses/bsd-license.php BSD License
 * @version    Release: @package_version@
 * @link       http://pear.php.net/package/Mail_mime
 */
class Mail_mimeDecode extends PEAR
{
    /**
     * The raw email to decode
     *
     * @var    string
     * @access private
     */
    var $_input;

    /**
     * The header part of the input
     *
     * @var    string
     * @access private
     */
    var $_header;

    /**
     * The body part of the input
     *
     * @var    string
     * @access private
     */
    var $_body;

    /**
     * If an error occurs, this is used to store the message
     *
     * @var    string
     * @access private
     */
    var $_error;

    /**
     * Flag to determine whether to include bodies in the
     * returned object.
     *
     * @var    boolean
     * @access private
     */
    var $_include_bodies;

    /**
     * Flag to determine whether to decode bodies
     *
     * @var    boolean
     * @access private
     */
    var $_decode_bodies;

    /**
     * Flag to determine whether to decode headers
     * (set to UTF8 to iconv convert headers)
     * @var    mixed 
     * @access private
     */
    var $_decode_headers;
  

    /**
     * Flag to determine whether to include attached messages
     * as body in the returned object. Depends on $_include_bodies
     *
     * @var    boolean
     * @access private
     */
    var $_rfc822_bodies;

    /**
     * Constructor.
     *
     * Sets up the object, initialise the variables, and splits and
     * stores the header and body of the input.
     *
     * @param string The input to decode
     * @access public
     */
    function __construct($input)
    {
        list($header, $body)   = $this->_splitBodyHeader($input);

        $this->_input          = $input;
        $this->_header         = $header;
        $this->_body           = $body;
        $this->_decode_bodies  = false;
        $this->_include_bodies = true;
        $this->_rfc822_bodies  = false;
    }
    // BC
    function Mail_mimeDecode($input)
    {
        $this->__construct($input);
    }
    

    /**
     * Begins the decoding process. If called statically
     * it will create an object and call the decode() method
     * of it.
     *
     * @param array An array of various parameters that determine
     *              various things:
     *              include_bodies - Whether to include the body in the returned
     *                               object.
     *              decode_bodies  - Whether to decode the bodies
     *                               of the parts. (Transfer encoding)
     *              decode_headers - Whether to decode headers,
     *                             - use "UTF8//IGNORE" to convert charset.
     *              
     *              input          - If called statically, this will be treated
     *                               as the input
     * @return object Decoded results
     * @access public
     */
    function decode($params = null)
    {
        // determine if this method has been called statically
        $isStatic = empty($this) || !is_a($this, __CLASS__);

        // Have we been called statically?
	// If so, create an object and pass details to that.
        if ($isStatic AND isset($params['input'])) {

            $obj = new Mail_mimeDecode($params['input']);
            $structure = $obj->decode($params);

        // Called statically but no input
        } elseif ($isStatic) {
            return PEAR::raiseError('Called statically and no input given');

        // Called via an object
        } else {
            $this->_include_bodies = isset($params['include_bodies']) ?
	                             $params['include_bodies'] : false;
            $this->_decode_bodies  = isset($params['decode_bodies']) ?
	                             $params['decode_bodies']  : false;
            $this->_decode_headers = isset($params['decode_headers']) ?
	                             $params['decode_headers'] : false;
            $this->_rfc822_bodies  = isset($params['rfc_822bodies']) ?
	                             $params['rfc_822bodies']  : false;
                                 
            if (is_string($this->_decode_headers) && !function_exists('iconv')) {
                 PEAR::raiseError('header decode conversion requested, however iconv is missing');
            }
                                 
            $structure = $this->_decode($this->_header, $this->_body);
            if ($structure === false) {
                $structure = $this->raiseError($this->_error);
            }
        }
    
        return $structure;
    }

    /**
     * Performs the decoding. Decodes the body string passed to it
     * If it finds certain content-types it will call itself in a
     * recursive fashion
     *
     * @param string Header section
     * @param string Body section
     * @return object Results of decoding process
     * @access private
     */
    function _decode($headers, $body, $default_ctype = 'text/plain')
    {
        $return = new stdClass;
        $return->headers = array();
        $headers = $this->_parseHeaders($headers);

        foreach ($headers as $value) {
            $value['value'] =  $this->_decodeHeader($value['value']);
            if (isset($return->headers[strtolower($value['name'])]) AND !is_array($return->headers[strtolower($value['name'])])) {
                $return->headers[strtolower($value['name'])]   = array($return->headers[strtolower($value['name'])]);
                $return->headers[strtolower($value['name'])][] = $value['value'];

            } elseif (isset($return->headers[strtolower($value['name'])])) {
                $return->headers[strtolower($value['name'])][] = $value['value'];

            } else {
                $return->headers[strtolower($value['name'])] = $value['value'];
            }
        }


        foreach ($headers as $key => $value) {
            $headers[$key]['name'] = strtolower($headers[$key]['name']);
            switch ($headers[$key]['name']) {

                case 'content-type':
                    $content_type = $this->_parseHeaderValue($headers[$key]['value']);

                    if (preg_match('/([0-9a-z+.-]+)\/([0-9a-z+.-]+)/i', $content_type['value'], $regs)) {
                        $return->ctype_primary   = $regs[1];
                        $return->ctype_secondary = $regs[2];
                    }

                    if (isset($content_type['other'])) {
                        foreach($content_type['other'] as $p_name => $p_value) {
                            $return->ctype_parameters[$p_name] = $p_value;
                        }
                    }
                    break;

                case 'content-disposition':
                    $content_disposition = $this->_parseHeaderValue($headers[$key]['value']);
                    $return->disposition   = $content_disposition['value'];
                    if (isset($content_disposition['other'])) {
                        foreach($content_disposition['other'] as $p_name => $p_value) {
                            $return->d_parameters[$p_name] = $p_value;
                        }
                    }
                    break;

                case 'content-transfer-encoding':
                    $content_transfer_encoding = $this->_parseHeaderValue($headers[$key]['value']);
                    break;
            }
        }

        if (isset($content_type)) {
            switch (strtolower($content_type['value'])) {
                case 'text/plain':
                    $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit';
                    $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $encoding) : $body) : null;
                    break;

                case 'text/html':
                    $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit';
                    $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $encoding) : $body) : null;
                    break;
                
                case 'multipart/signed': // PGP
                    $parts = $this->_boundarySplit($body, $content_type['other']['boundary'], true);
                    $return->parts['msg_body'] = $parts[0]; 
                    list($part_header, $part_body) = $this->_splitBodyHeader($parts[1]);
                    $return->parts['sig_hdr'] = $part_header;
                    $return->parts['sig_body'] = $part_body;
                    break;

                case 'multipart/parallel':
                case 'multipart/appledouble': // Appledouble mail
                case 'multipart/report': // RFC1892
                case 'multipart/signed': // PGP
                case 'multipart/digest':
                case 'multipart/alternative':
                case 'multipart/related':
                case 'multipart/relative': //#20431 - android
                case 'multipart/mixed':
                case 'application/vnd.wap.multipart.related':
                    if(!isset($content_type['other']['boundary'])){
                        $this->_error = 'No boundary found for ' . $content_type['value'] . ' part';
                        return false;
                    }

                    $default_ctype = (strtolower($content_type['value']) === 'multipart/digest') ? 'message/rfc822' : 'text/plain';

                    $parts = $this->_boundarySplit($body, $content_type['other']['boundary']);
                    for ($i = 0; $i < count($parts); $i++) {
                        list($part_header, $part_body) = $this->_splitBodyHeader($parts[$i]);
                        $part = $this->_decode($part_header, $part_body, $default_ctype);
                        if($part === false)
                            $part = $this->raiseError($this->_error);
                        $return->parts[] = $part;
                    }
                    break;

                case 'message/rfc822':
                case 'message/delivery-status': // #bug #18693
					if ($this->_rfc822_bodies) {
						$encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit';
						$return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $encoding) : $body);
					}
                    $obj = new Mail_mimeDecode($body);
                    $return->parts[] = $obj->decode(array('include_bodies' => $this->_include_bodies,
					                                      'decode_bodies'  => $this->_decode_bodies,
														  'decode_headers' => $this->_decode_headers));
                    unset($obj);
                    break;

                default:
                    if(!isset($content_transfer_encoding['value']))
                        $content_transfer_encoding['value'] = '7bit';
                    $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $content_transfer_encoding['value']) : $body) : null;
                    break;
            }

        } else {
            $ctype = explode('/', $default_ctype);
            $return->ctype_primary   = $ctype[0];
            $return->ctype_secondary = $ctype[1];
            $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body) : $body) : null;
        }

        return $return;
    }

    /**
     * Given the output of the above function, this will return an
     * array of references to the parts, indexed by mime number.
     *
     * @param  object $structure   The structure to go through
     * @param  string $mime_number Internal use only.
     * @return array               Mime numbers
     */
    function &getMimeNumbers(&$structure, $no_refs = false, $mime_number = '', $prepend = '')
    {
        $return = array();
        if (!empty($structure->parts)) {
            if ($mime_number != '') {
                $structure->mime_id = $prepend . $mime_number;
                $return[$prepend . $mime_number] = &$structure;
            }
            for ($i = 0; $i < count($structure->parts); $i++) {

            
                if (!empty($structure->headers['content-type']) AND substr(strtolower($structure->headers['content-type']), 0, 8) == 'message/') {
                    $prepend      = $prepend . $mime_number . '.';
                    $_mime_number = '';
                } else {
                    $_mime_number = ($mime_number == '' ? $i + 1 : sprintf('%s.%s', $mime_number, $i + 1));
                }

                $arr = &Mail_mimeDecode::getMimeNumbers($structure->parts[$i], $no_refs, $_mime_number, $prepend);
                foreach ($arr as $key => $val) {
                    $no_refs ? $return[$key] = '' : $return[$key] = &$arr[$key];
                }
            }
        } else {
            if ($mime_number == '') {
                $mime_number = '1';
            }
            $structure->mime_id = $prepend . $mime_number;
            $no_refs ? $return[$prepend . $mime_number] = '' : $return[$prepend . $mime_number] = &$structure;
        }
        
        return $return;
    }

    /**
     * Given a string containing a header and body
     * section, this function will split them (at the first
     * blank line) and return them.
     *
     * @param string Input to split apart
     * @return array Contains header and body section
     * @access private
     */
    function _splitBodyHeader($input)
    {
        if (preg_match("/^(.*?)\r?\n\r?\n(.*)/s", $input, $match)) {
            return array($match[1], $match[2]);
        }
        // bug #17325 - empty bodies are allowed. - we just check that at least one line 
        // of headers exist..
        if (count(explode("\n",$input))) {
            return array($input, '');
        }
        $this->_error = 'Could not split header and body';
        return false;
    }

    /**
     * Parse headers given in $input and return
     * as assoc array.
     *
     * @param string Headers to parse
     * @return array Contains parsed headers
     * @access private
     */
    function _parseHeaders($input)
    {

        if ($input !== '') {
            // Unfold the input
            $input   = preg_replace("/\r?\n/", "\r\n", $input);
            //#7065 - wrapping.. with encoded stuff.. - probably not needed,
            // wrapping space should only get removed if the trailing item on previous line is a 
            // encoded character
            $input   = preg_replace("/=\r\n(\t| )+/", '=', $input);
            $input   = preg_replace("/\r\n(\t| )+/", ' ', $input);
            
            $headers = explode("\r\n", trim($input));
            $got_start = false;
            foreach ($headers as $value) {
                if (!$got_start) {
                    // munge headers for mbox style from
                    if ($value[0] == '>') {
                        $value = substring($value, 1); // remove mbox >
                    }
                    if (substr($value,0,5) == 'From ') {
                        $value = 'Return-Path: ' . substr($value, 5);
                    } else {
                        $got_start = true;
                    }
                }
                
                $hdr_name = substr($value, 0, $pos = strpos($value, ':'));
                $hdr_value = substr($value, $pos+1);
                if($hdr_value[0] == ' ') {
                    $hdr_value = substr($hdr_value, 1);
                }

                $return[] = array(
                                  'name'  => $hdr_name,
                                  'value' =>  $hdr_value
                                 );
            }
        } else {
            $return = array();
        }

        return $return;
    }

    /**
     * Function to parse a header value,
     * extract first part, and any secondary
     * parts (after ;) This function is not as
     * robust as it could be. Eg. header comments
     * in the wrong place will probably break it.
     *
     * Extra things this can handle
     *   filename*0=......
     *   filename*1=......
     *
     *  This is where lines are broken in, and need merging.
     *
     *   filename*0*=ENC'lang'urlencoded data.
     *   filename*1*=ENC'lang'urlencoded data.
     *
     * 
     *
     * @param string Header value to parse
     * @return array Contains parsed result
     * @access private
     */
    function _parseHeaderValue($input)
    {
         if (($pos = strpos($input, ';')) === false) {
            $input = $this->_decodeHeader($input);
            $return['value'] = trim($input);
            return $return;
        }



        $value = substr($input, 0, $pos);
        $value = $this->_decodeHeader($value);
        $return['value'] = trim($value);
        $input = trim(substr($input, $pos+1));

        if (!strlen($input) > 0) {
            return $return;
        }
        // at this point input contains xxxx=".....";zzzz="...."
        // since we are dealing with quoted strings, we need to handle this properly..
        $i = 0;
        $l = strlen($input);
        $key = '';
        $val = false; // our string - including quotes..
        $q = false; // in quote..
        $lq = ''; // last quote..

        while ($i < $l) {
            
            $c = $input[$i];
            //var_dump(array('i'=>$i,'c'=>$c,'q'=>$q, 'lq'=>$lq, 'key'=>$key, 'val' =>$val));

            $escaped = false;
            if ($c == '\\') {
                $i++;
                if ($i == $l-1) { // end of string.
                    break;
                }
                $escaped = true;
                $c = $input[$i];
            }            


            // state - in key..
            if ($val === false) {
                if (!$escaped && $c == '=') {
                    $val = '';
                    $key = trim($key);
                    $i++;
                    continue;
                }
                if (!$escaped && $c == ';') {
                    if ($key) { // a key without a value..
                        $key= trim($key);
                        $return['other'][$key] = '';
                    }
                    $key = '';
                }
                $key .= $c;
                $i++;
                continue;
            }
                     
            // state - in value.. (as $val is set..)

            if ($q === false) {
                // not in quote yet.
                if ((!strlen($val) || $lq !== false) && $c == ' ' ||  $c == "\t") {
                    $i++;
                    continue; // skip leading spaces after '=' or after '"'
                }
                
                // do not de-quote 'xxx*= itesm.. 
                $key_is_trans = $key[strlen($key)-1] == '*';
                
                if (!$key_is_trans && !$escaped && ($c == '"' || $c == "'")) {
                    // start quoted area..
                    $q = $c;
                    // in theory should not happen raw text in value part..
                    // but we will handle it as a merged part of the string..
                    $val = !strlen(trim($val)) ? '' : trim($val);
                    $i++;
                    continue;
                }
                // got end....
                if (!$escaped && $c == ';') {
                     
                    $return['other'][$key] = trim($val);
                    $val = false;
                    $key = '';
                    $lq = false;
                    $i++;
                    continue;
                }

                $val .= $c;
                $i++;
                continue;
            }
            
            // state - in quote..
            if (!$escaped && $c == $q) {  // potential exit state..
                
                // end of quoted string..
                $lq = $q;
                $q = false;
                $i++;
                continue;
            }
                
            // normal char inside of quoted string..
            $val.= $c;
            $i++;
        }
        
        // do we have anything left..
        if (strlen(trim($key)) || $val !== false) {
           
            $val = trim($val);
          
            $return['other'][$key] = $val;
        }
       
        
        $clean_others = array();
        // merge added values. eg. *1[*]
        foreach($return['other'] as $key =>$val) {
            if (preg_match('/\*[0-9]+\**$/', $key)) {
                $key = preg_replace('/(.*)\*[0-9]+(\**)$/', '\1\2', $key);
                if (isset($clean_others[$key])) {
                    $clean_others[$key] .= $val;
                    continue;
                }
                
            }
            $clean_others[$key] = $val;
            
        }
         
        // handle language translation of '*' ending others.
        foreach( $clean_others as $key =>$val) {
            if ( $key[strlen($key)-1] != '*') {
                $clean_others[strtolower($key)] = $val;
                continue;
            }
            unset($clean_others[$key]);
            $key = substr($key,0,-1);
            //extended-initial-value := [charset] "'" [language] "'"
            //              extended-other-values
            $match = array();
            $info = preg_match("/^([^']+)'([^']*)'(.*)$/", $val, $match);
             
            $clean_others[$key] = urldecode($match[3]);
            $clean_others[strtolower($key)] = $clean_others[$key];
            $clean_others[strtolower($key).'-charset'] = $match[1];
            $clean_others[strtolower($key).'-language'] = $match[2];
            
            
        }
        
        
        $return['other'] = $clean_others;
        
        // decode values.
        foreach($return['other'] as $key =>$val) {
            $charset = isset($return['other'][$key . '-charset']) ?
                $return['other'][$key . '-charset']  : false;
            
            $return['other'][$key] = $this->_decodeHeader($val, $charset);
        }
        
        return $return;
    }

    /**
     * This function splits the input based
     * on the given boundary
     *
     * @param string Input to parse
     * @return array Contains array of resulting mime parts
     * @access private
     */
    function _boundarySplit($input, $boundary, $eatline = false)
    {
        $parts = array();

        $bs_possible = substr($boundary, 2, -2);
        $bs_check = '\"' . $bs_possible . '\"';

        if ($boundary == $bs_check) {
            $boundary = $bs_possible;
        }
        // eatline is used by multipart/signed.
        $tmp = $eatline ?
            preg_split("/\r?\n--".preg_quote($boundary, '/')."(|--)\n/", $input) :
            preg_split("/--".preg_quote($boundary, '/')."((?=\s)|--)/", $input);

        $len = count($tmp) -1;
        for ($i = 1; $i < $len; $i++) {
            if (strlen(trim($tmp[$i]))) {
                $parts[] = $tmp[$i];
            }
        }
        
        // add the last part on if it does not end with the 'closing indicator'
        if (!empty($tmp[$len]) && strlen(trim($tmp[$len])) && $tmp[$len][0] != '-') {
            $parts[] = $tmp[$len];
        }
        return $parts;
    }

    /**
     * Given a header, this function will decode it
     * according to RFC2047. Probably not *exactly*
     * conformant, but it does pass all the given
     * examples (in RFC2047).
     *
     * @param string Input header value to decode
     * @return string Decoded header value
     * @access private
     */
    function _decodeHeader($input, $default_charset=false)
    {
        if (!$this->_decode_headers) {
            return $input;
        }
        // Remove white space between encoded-words
        $input = preg_replace('/(=\?[^?]+\?(q|b)\?[^?]*\?=)(\s)+=\?/i', '\1=?', $input);

        // For each encoded-word...
        while (preg_match('/(=\?([^?]+)\?(q|b)\?([^?]*)\?=)/i', $input, $matches)) {

            $encoded  = $matches[1];
            $charset  = $matches[2];
            $encoding = $matches[3];
            $text     = $matches[4];

            switch (strtolower($encoding)) {
                case 'b':
                    $text = base64_decode($text);
                    break;

                case 'q':
                    $text = str_replace('_', ' ', $text);
                    preg_match_all('/=([a-f0-9]{2})/i', $text, $matches);
                    foreach($matches[1] as $value)
                        $text = str_replace('='.$value, chr(hexdec($value)), $text);
                    break;
            }
            if (is_string($this->_decode_headers)) {
                $conv = @iconv($charset, $this->_decode_headers, $text);
                $text = ($conv === false) ? $text : $conv;
            }
            $input = str_replace($encoded, $text, $input);
        }
        
        if ($default_charset  && is_string($this->_decode_headers)) {
            $conv = @iconv($charset, $this->_decode_headers, $input);
            $input = ($conv === false) ? $input : $conv;
        }
        
        return $input;
    }

    /**
     * Given a body string and an encoding type,
     * this function will decode and return it.
     *
     * @param  string Input body to decode
     * @param  string Encoding type to use.
     * @return string Decoded body
     * @access private
     */
    function _decodeBody($input, $encoding = '7bit')
    {
        switch (strtolower($encoding)) {
            case '7bit':
                return $input;
                break;

            case 'quoted-printable':
                return $this->_quotedPrintableDecode($input);
                break;

            case 'base64':
                return base64_decode($input);
                break;

            default:
                return $input;
        }
    }

    /**
     * Given a quoted-printable string, this
     * function will decode and return it.
     *
     * @param  string Input body to decode
     * @return string Decoded body
     * @access private
     */
    function _quotedPrintableDecode($input)
    {
        // Remove soft line breaks
        $input = preg_replace("/=\r?\n/", '', $input);

        // Replace encoded characters
		 
        $cb = create_function('$matches',  ' return chr(hexdec($matches[0]));');
         
        $input = preg_replace_callback( '/=([a-f0-9]{2})/i', $cb, $input);

        return $input;
    }

    /**
     * Checks the input for uuencoded files and returns
     * an array of them. Can be called statically, eg:
     *
     * $files =& Mail_mimeDecode::uudecode($some_text);
     *
     * It will check for the begin 666 ... end syntax
     * however and won't just blindly decode whatever you
     * pass it.
     *
     * @param  string Input body to look for attahcments in
     * @return array  Decoded bodies, filenames and permissions
     * @access public
     * @author Unknown
     */
    function &uudecode($input)
    {
        // Find all uuencoded sections
        preg_match_all("/begin ([0-7]{3}) (.+)\r?\n(.+)\r?\nend/Us", $input, $matches);

        for ($j = 0; $j < count($matches[3]); $j++) {

            $str      = $matches[3][$j];
            $filename = $matches[2][$j];
            $fileperm = $matches[1][$j];

            $file = '';
            $str = preg_split("/\r?\n/", trim($str));
            $strlen = count($str);

            for ($i = 0; $i < $strlen; $i++) {
                $pos = 1;
                $d = 0;
                $len=(int)(((ord(substr($str[$i],0,1)) -32) - ' ') & 077);

                while (($d + 3 <= $len) AND ($pos + 4 <= strlen($str[$i]))) {
                    $c0 = (ord(substr($str[$i],$pos,1)) ^ 0x20);
                    $c1 = (ord(substr($str[$i],$pos+1,1)) ^ 0x20);
                    $c2 = (ord(substr($str[$i],$pos+2,1)) ^ 0x20);
                    $c3 = (ord(substr($str[$i],$pos+3,1)) ^ 0x20);
                    $file .= chr(((($c0 - ' ') & 077) << 2) | ((($c1 - ' ') & 077) >> 4));

                    $file .= chr(((($c1 - ' ') & 077) << 4) | ((($c2 - ' ') & 077) >> 2));

                    $file .= chr(((($c2 - ' ') & 077) << 6) |  (($c3 - ' ') & 077));

                    $pos += 4;
                    $d += 3;
                }

                if (($d + 2 <= $len) && ($pos + 3 <= strlen($str[$i]))) {
                    $c0 = (ord(substr($str[$i],$pos,1)) ^ 0x20);
                    $c1 = (ord(substr($str[$i],$pos+1,1)) ^ 0x20);
                    $c2 = (ord(substr($str[$i],$pos+2,1)) ^ 0x20);
                    $file .= chr(((($c0 - ' ') & 077) << 2) | ((($c1 - ' ') & 077) >> 4));

                    $file .= chr(((($c1 - ' ') & 077) << 4) | ((($c2 - ' ') & 077) >> 2));

                    $pos += 3;
                    $d += 2;
                }

                if (($d + 1 <= $len) && ($pos + 2 <= strlen($str[$i]))) {
                    $c0 = (ord(substr($str[$i],$pos,1)) ^ 0x20);
                    $c1 = (ord(substr($str[$i],$pos+1,1)) ^ 0x20);
                    $file .= chr(((($c0 - ' ') & 077) << 2) | ((($c1 - ' ') & 077) >> 4));

                }
            }
            $files[] = array('filename' => $filename, 'fileperm' => $fileperm, 'filedata' => $file);
        }

        return $files;
    }

    /**
     * getSendArray() returns the arguments required for Mail::send()
     * used to build the arguments for a mail::send() call 
     *
     * Usage:
     * $mailtext = Full email (for example generated by a template)
     * $decoder = new Mail_mimeDecode($mailtext);
     * $parts =  $decoder->getSendArray();
     * if (!PEAR::isError($parts) {
     *     list($recipents,$headers,$body) = $parts;
     *     $mail = Mail::factory('smtp');
     *     $mail->send($recipents,$headers,$body);
     * } else {
     *     echo $parts->message;
     * }
     * @return mixed   array of recipeint, headers,body or Pear_Error
     * @access public
     * @author Alan Knowles <alan@akbkhome.com>
     */
    function getSendArray()
    {
        // prevent warning if this is not set
        $this->_decode_headers = FALSE;
        $headerlist =$this->_parseHeaders($this->_header);
        $to = "";
        if (!$headerlist) {
            return $this->raiseError("Message did not contain headers");
        }
        foreach($headerlist as $item) {
            $header[$item['name']] = $item['value'];
            switch (strtolower($item['name'])) {
                case "to":
                case "cc":
                case "bcc":
                    $to .= ",".$item['value'];
                default:
                   break;
            }
        }
        if ($to == "") {
            return $this->raiseError("Message did not contain any recipents");
        }
        $to = substr($to,1);
        return array($to,$header,$this->_body);
    } 

    /**
     * Returns a xml copy of the output of
     * Mail_mimeDecode::decode. Pass the output in as the
     * argument. This function can be called statically. Eg:
     *
     * $output = $obj->decode();
     * $xml    = Mail_mimeDecode::getXML($output);
     *
     * The DTD used for this should have been in the package. Or
     * alternatively you can get it from cvs, or here:
     * http://www.phpguru.org/xmail/xmail.dtd.
     *
     * @param  object Input to convert to xml. This should be the
     *                output of the Mail_mimeDecode::decode function
     * @return string XML version of input
     * @access public
     */
    function getXML($input)
    {
        $crlf    =  "\r\n";
        $output  = '<?xml version=\'1.0\'?>' . $crlf .
                   '<!DOCTYPE email SYSTEM "http://www.phpguru.org/xmail/xmail.dtd">' . $crlf .
                   '<email>' . $crlf .
                   Mail_mimeDecode::_getXML($input) .
                   '</email>';

        return $output;
    }

    /**
     * Function that does the actual conversion to xml. Does a single
     * mimepart at a time.
     *
     * @param  object  Input to convert to xml. This is a mimepart object.
     *                 It may or may not contain subparts.
     * @param  integer Number of tabs to indent
     * @return string  XML version of input
     * @access private
     */
    function _getXML($input, $indent = 1)
    {
        $htab    =  "\t";
        $crlf    =  "\r\n";
        $output  =  '';
        $headers = @(array)$input->headers;

        foreach ($headers as $hdr_name => $hdr_value) {

            // Multiple headers with this name
            if (is_array($headers[$hdr_name])) {
                for ($i = 0; $i < count($hdr_value); $i++) {
                    $output .= Mail_mimeDecode::_getXML_helper($hdr_name, $hdr_value[$i], $indent);
                }

            // Only one header of this sort
            } else {
                $output .= Mail_mimeDecode::_getXML_helper($hdr_name, $hdr_value, $indent);
            }
        }

        if (!empty($input->parts)) {
            for ($i = 0; $i < count($input->parts); $i++) {
                $output .= $crlf . str_repeat($htab, $indent) . '<mimepart>' . $crlf .
                           Mail_mimeDecode::_getXML($input->parts[$i], $indent+1) .
                           str_repeat($htab, $indent) . '</mimepart>' . $crlf;
            }
        } elseif (isset($input->body)) {
            $output .= $crlf . str_repeat($htab, $indent) . '<body><![CDATA[' .
                       $input->body . ']]></body>' . $crlf;
        }

        return $output;
    }

    /**
     * Helper function to _getXML(). Returns xml of a header.
     *
     * @param  string  Name of header
     * @param  string  Value of header
     * @param  integer Number of tabs to indent
     * @return string  XML version of input
     * @access private
     */
    function _getXML_helper($hdr_name, $hdr_value, $indent)
    {
        $htab   = "\t";
        $crlf   = "\r\n";
        $return = '';

        $new_hdr_value = ($hdr_name != 'received') ? Mail_mimeDecode::_parseHeaderValue($hdr_value) : array('value' => $hdr_value);
        $new_hdr_name  = str_replace(' ', '-', ucwords(str_replace('-', ' ', $hdr_name)));

        // Sort out any parameters
        if (!empty($new_hdr_value['other'])) {
            foreach ($new_hdr_value['other'] as $paramname => $paramvalue) {
                $params[] = str_repeat($htab, $indent) . $htab . '<parameter>' . $crlf .
                            str_repeat($htab, $indent) . $htab . $htab . '<paramname>' . htmlspecialchars($paramname) . '</paramname>' . $crlf .
                            str_repeat($htab, $indent) . $htab . $htab . '<paramvalue>' . htmlspecialchars($paramvalue) . '</paramvalue>' . $crlf .
                            str_repeat($htab, $indent) . $htab . '</parameter>' . $crlf;
            }

            $params = implode('', $params);
        } else {
            $params = '';
        }

        $return = str_repeat($htab, $indent) . '<header>' . $crlf .
                  str_repeat($htab, $indent) . $htab . '<headername>' . htmlspecialchars($new_hdr_name) . '</headername>' . $crlf .
                  str_repeat($htab, $indent) . $htab . '<headervalue>' . htmlspecialchars($new_hdr_value['value']) . '</headervalue>' . $crlf .
                  $params .
                  str_repeat($htab, $indent) . '</header>' . $crlf;

        return $return;
    }

} // End of class
PKn�ZB�_Ǭ=�=
Mail/smtp.phpnu�[���<?php
/**
 * SMTP implementation of the PEAR Mail interface. Requires the Net_SMTP class.
 *
 * PHP version 5
 *
 * LICENSE:
 *
 * Copyright (c) 2010-2017, Chuck Hagenbuch & Jon Parise
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category    HTTP
 * @package     HTTP_Request
 * @author      Jon Parise <jon@php.net> 
 * @author      Chuck Hagenbuch <chuck@horde.org>
 * @copyright   2010-2017 Chuck Hagenbuch
 * @license     http://opensource.org/licenses/BSD-3-Clause New BSD License
 * @version     CVS: $Id$
 * @link        http://pear.php.net/package/Mail/
 */

/** Error: Failed to create a Net_SMTP object */
define('PEAR_MAIL_SMTP_ERROR_CREATE', 10000);

/** Error: Failed to connect to SMTP server */
define('PEAR_MAIL_SMTP_ERROR_CONNECT', 10001);

/** Error: SMTP authentication failure */
define('PEAR_MAIL_SMTP_ERROR_AUTH', 10002);

/** Error: No From: address has been provided */
define('PEAR_MAIL_SMTP_ERROR_FROM', 10003);

/** Error: Failed to set sender */
define('PEAR_MAIL_SMTP_ERROR_SENDER', 10004);

/** Error: Failed to add recipient */
define('PEAR_MAIL_SMTP_ERROR_RECIPIENT', 10005);

/** Error: Failed to send data */
define('PEAR_MAIL_SMTP_ERROR_DATA', 10006);

/**
 * SMTP implementation of the PEAR Mail interface. Requires the Net_SMTP class.
 * @access public
 * @package Mail
 * @version $Revision$
 */
class Mail_smtp extends Mail {

    /**
     * SMTP connection object.
     *
     * @var object
     * @access private
     */
    var $_smtp = null;

    /**
     * The list of service extension parameters to pass to the Net_SMTP
     * mailFrom() command.
     *
     * @var array
     */
    var $_extparams = array();

    /**
     * The SMTP host to connect to.
     *
     * @var string
     */
    var $host = 'localhost';

    /**
     * The port the SMTP server is on.
     *
     * @var integer
     */
    var $port = 25;

    /**
     * Should SMTP authentication be used?
     *
     * This value may be set to true, false or the name of a specific
     * authentication method.
     *
     * If the value is set to true, the Net_SMTP package will attempt to use
     * the best authentication method advertised by the remote SMTP server.
     *
     * @var mixed
     */
    var $auth = false;

    /**
     * The username to use if the SMTP server requires authentication.
     *
     * @var string
     */
    var $username = '';

    /**
     * The password to use if the SMTP server requires authentication.
     *
     * @var string
     */
    var $password = '';

    /**
     * Hostname or domain that will be sent to the remote SMTP server in the
     * HELO / EHLO message.
     *
     * @var string
     */
    var $localhost = 'localhost';

    /**
     * SMTP connection timeout value.  NULL indicates no timeout.
     *
     * @var integer
     */
    var $timeout = null;

    /**
     * Turn on Net_SMTP debugging?
     *
     * @var boolean $debug
     */
    var $debug = false;

    /**
     * Indicates whether or not the SMTP connection should persist over
     * multiple calls to the send() method.
     *
     * @var boolean
     */
    var $persist = false;

    /**
     * Use SMTP command pipelining (specified in RFC 2920) if the SMTP server
     * supports it. This speeds up delivery over high-latency connections. By
     * default, use the default value supplied by Net_SMTP.
     *
     * @var boolean
     */
    var $pipelining;

    /**
     * The list of socket options
     *
     * @var array
     */
    var $socket_options = array();

    /**
     * Constructor.
     *
     * Instantiates a new Mail_smtp:: object based on the parameters
     * passed in. It looks for the following parameters:
     *     host        The server to connect to. Defaults to localhost.
     *     port        The port to connect to. Defaults to 25.
     *     auth        SMTP authentication.  Defaults to none.
     *     username    The username to use for SMTP auth. No default.
     *     password    The password to use for SMTP auth. No default.
     *     localhost   The local hostname / domain. Defaults to localhost.
     *     timeout     The SMTP connection timeout. Defaults to none.
     *     verp        Whether to use VERP or not. Defaults to false.
     *                 DEPRECATED as of 1.2.0 (use setMailParams()).
     *     debug       Activate SMTP debug mode? Defaults to false.
     *     persist     Should the SMTP connection persist?
     *     pipelining  Use SMTP command pipelining
     *
     * If a parameter is present in the $params array, it replaces the
     * default.
     *
     * @param array Hash containing any parameters different from the
     *              defaults.
     */
    public function __construct($params)
    {
        if (isset($params['host'])) $this->host = $params['host'];
        if (isset($params['port'])) $this->port = $params['port'];
        if (isset($params['auth'])) $this->auth = $params['auth'];
        if (isset($params['username'])) $this->username = $params['username'];
        if (isset($params['password'])) $this->password = $params['password'];
        if (isset($params['localhost'])) $this->localhost = $params['localhost'];
        if (isset($params['timeout'])) $this->timeout = $params['timeout'];
        if (isset($params['debug'])) $this->debug = (bool)$params['debug'];
        if (isset($params['persist'])) $this->persist = (bool)$params['persist'];
        if (isset($params['pipelining'])) $this->pipelining = (bool)$params['pipelining'];
        if (isset($params['socket_options'])) $this->socket_options = $params['socket_options'];
        // Deprecated options
        if (isset($params['verp'])) {
            $this->addServiceExtensionParameter('XVERP', is_bool($params['verp']) ? null : $params['verp']);
        }
    }

    /**
     * Destructor implementation to ensure that we disconnect from any
     * potentially-alive persistent SMTP connections.
     */
    public function __destruct()
    {
        $this->disconnect();
    }

    /**
     * Implements Mail::send() function using SMTP.
     *
     * @param mixed $recipients Either a comma-seperated list of recipients
     *              (RFC822 compliant), or an array of recipients,
     *              each RFC822 valid. This may contain recipients not
     *              specified in the headers, for Bcc:, resending
     *              messages, etc.
     *
     * @param array $headers The array of headers to send with the mail, in an
     *              associative array, where the array key is the
     *              header name (e.g., 'Subject'), and the array value
     *              is the header value (e.g., 'test'). The header
     *              produced from those values would be 'Subject:
     *              test'.
     *
     * @param string $body The full text of the message body, including any
     *               MIME parts, etc.
     *
     * @return mixed Returns true on success, or a PEAR_Error
     *               containing a descriptive error message on
     *               failure.
     */
    public function send($recipients, $headers, $body)
    {
        $result = $this->send_or_fail($recipients, $headers, $body);

        /* If persistent connections are disabled, destroy our SMTP object. */
        if ($this->persist === false) {
            $this->disconnect();
        }

        return $result;
    }

    protected function send_or_fail($recipients, $headers, $body)
    {
        /* If we don't already have an SMTP object, create one. */
        $result = $this->getSMTPObject();
        if (PEAR::isError($result)) {
            return $result;
        }

        if (!is_array($headers)) {
            return PEAR::raiseError('$headers must be an array');
        }

        $this->_sanitizeHeaders($headers);

        $headerElements = $this->prepareHeaders($headers);
        if (is_a($headerElements, 'PEAR_Error')) {
            $this->_smtp->rset();
            return $headerElements;
        }
        list($from, $textHeaders) = $headerElements;

        /* Since few MTAs are going to allow this header to be forged
         * unless it's in the MAIL FROM: exchange, we'll use
         * Return-Path instead of From: if it's set. */
        if (!empty($headers['Return-Path'])) {
            $from = $headers['Return-Path'];
        }

        if (!isset($from)) {
            $this->_smtp->rset();
            return PEAR::raiseError('No From: address has been provided',
                                    PEAR_MAIL_SMTP_ERROR_FROM);
        }

        $params = null;
        if (!empty($this->_extparams)) {
            foreach ($this->_extparams as $key => $val) {
                $params .= ' ' . $key . (is_null($val) ? '' : '=' . $val);
            }
        }
        if (PEAR::isError($res = $this->_smtp->mailFrom($from, ltrim($params)))) {
            $error = $this->_error("Failed to set sender: $from", $res);
            $this->_smtp->rset();
            return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_SENDER);
        }

        $recipients = $this->parseRecipients($recipients);
        if (is_a($recipients, 'PEAR_Error')) {
            $this->_smtp->rset();
            return $recipients;
        }

        foreach ($recipients as $recipient) {
            $res = $this->_smtp->rcptTo($recipient);
            if (is_a($res, 'PEAR_Error')) {
                $error = $this->_error("Failed to add recipient: $recipient", $res);
                $this->_smtp->rset();
                return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_RECIPIENT);
            }
        }

        /* Send the message's headers and the body as SMTP data. */
        $res = $this->_smtp->data($body, $textHeaders);
        list(,$args) = $this->_smtp->getResponse();

        if (preg_match("/ queued as (.*)/", $args, $queued)) {
            $this->queued_as = $queued[1];
        }

        /* we need the greeting; from it we can extract the authorative name of the mail server we've really connected to.
         * ideal if we're connecting to a round-robin of relay servers and need to track which exact one took the email */
        $this->greeting = $this->_smtp->getGreeting();

        if (is_a($res, 'PEAR_Error')) {
            $error = $this->_error('Failed to send data', $res);
            $this->_smtp->rset();
            return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_DATA);
        }

        return true;
    }

    /**
     * Connect to the SMTP server by instantiating a Net_SMTP object.
     *
     * @return mixed Returns a reference to the Net_SMTP object on success, or
     *               a PEAR_Error containing a descriptive error message on
     *               failure.
     *
     * @since  1.2.0
     */
    public function getSMTPObject()
    {
        if (is_object($this->_smtp) !== false) {
            return $this->_smtp;
        }

        include_once 'Net/SMTP.php';
        $this->_smtp = new Net_SMTP($this->host,
                                     $this->port,
                                     $this->localhost,
                                     $this->pipelining,
                                     0,
                                     $this->socket_options);

        /* If we still don't have an SMTP object at this point, fail. */
        if (is_object($this->_smtp) === false) {
            return PEAR::raiseError('Failed to create a Net_SMTP object',
                                    PEAR_MAIL_SMTP_ERROR_CREATE);
        }

        /* Configure the SMTP connection. */
        if ($this->debug) {
            $this->_smtp->setDebug(true);
        }

        /* Attempt to connect to the configured SMTP server. */
        if (PEAR::isError($res = $this->_smtp->connect($this->timeout))) {
            $error = $this->_error('Failed to connect to ' .
                                   $this->host . ':' . $this->port,
                                   $res);
            return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_CONNECT);
        }

        /* Attempt to authenticate if authentication has been enabled. */
        if ($this->auth) {
            $method = is_string($this->auth) ? $this->auth : '';

            if (PEAR::isError($res = $this->_smtp->auth($this->username,
                                                        $this->password,
                                                        $method))) {
                $error = $this->_error("$method authentication failure",
                                       $res);
                $this->_smtp->rset();
                return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_AUTH);
            }
        }

        return $this->_smtp;
    }

    /**
     * Add parameter associated with a SMTP service extension.
     *
     * @param string Extension keyword.
     * @param string Any value the keyword needs.
     *
     * @since 1.2.0
     */
    public function addServiceExtensionParameter($keyword, $value = null)
    {
        $this->_extparams[$keyword] = $value;
    }

    /**
     * Disconnect and destroy the current SMTP connection.
     *
     * @return boolean True if the SMTP connection no longer exists.
     *
     * @since  1.1.9
     */
    public function disconnect()
    {
        /* If we have an SMTP object, disconnect and destroy it. */
        if (is_object($this->_smtp) && $this->_smtp->disconnect()) {
            $this->_smtp = null;
        }

        /* We are disconnected if we no longer have an SMTP object. */
        return ($this->_smtp === null);
    }

    /**
     * Build a standardized string describing the current SMTP error.
     *
     * @param string $text  Custom string describing the error context.
     * @param object $error Reference to the current PEAR_Error object.
     *
     * @return string       A string describing the current SMTP error.
     *
     * @since  1.1.7
     */
    protected function _error($text, $error)
    {
        /* Split the SMTP response into a code and a response string. */
        list($code, $response) = $this->_smtp->getResponse();

        /* Build our standardized error string. */
        return $text
            . ' [SMTP: ' . $error->getMessage()
            . " (code: $code, response: $response)]";
    }

}
PKn�ZwԐE;E;Mail/smtpmx.phpnu�[���<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */

/**
 * SMTP MX
 *
 * SMTP MX implementation of the PEAR Mail interface. Requires the Net_SMTP class.
 *
 * PHP version 5
 *
 * LICENSE:
 *
 * Copyright (c) 2010-2017 gERD Schaufelberger
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   Mail
 * @package    Mail_smtpmx
 * @author     gERD Schaufelberger <gerd@php-tools.net>
 * @copyright  2010-2017 gERD Schaufelberger
 * @license    http://opensource.org/licenses/BSD-3-Clause New BSD License
 * @version    CVS: $Id$
 * @link       http://pear.php.net/package/Mail/
 */

require_once 'Net/SMTP.php';

/**
 * SMTP MX implementation of the PEAR Mail interface. Requires the Net_SMTP class.
 *
 *
 * @access public
 * @author  gERD Schaufelberger <gerd@php-tools.net>
 * @package Mail
 * @version $Revision$
 */
class Mail_smtpmx extends Mail {

    /**
     * SMTP connection object.
     *
     * @var object
     * @access private
     */
    var $_smtp = null;

    /**
     * The port the SMTP server is on.
     * @var integer
     * @see getservicebyname()
     */
    var $port = 25;

    /**
     * Hostname or domain that will be sent to the remote SMTP server in the
     * HELO / EHLO message.
     *
     * @var string
     * @see posix_uname()
     */
    var $mailname = 'localhost';

    /**
     * SMTP connection timeout value.  NULL indicates no timeout.
     *
     * @var integer
     */
    var $timeout = 10;

    /**
     * use either PEAR:Net_DNS or getmxrr
     *
     * @var boolean
     */
    var $withNetDns = true;

    /**
     * PEAR:Net_DNS_Resolver
     *
     * @var object
     */
    var $resolver;

    /**
     * Whether to use VERP or not. If not a boolean, the string value
     * will be used as the VERP separators.
     *
     * @var mixed boolean or string
     */
    var $verp = false;

    /**
     * Whether to use VRFY or not.
     *
     * @var boolean $vrfy
     */
    var $vrfy = false;

    /**
     * Switch to test mode - don't send emails for real
     *
     * @var boolean $debug
     */
    var $test = false;

    /**
     * Turn on Net_SMTP debugging?
     *
     * @var boolean $peardebug
     */
    var $debug = false;

    /**
     * internal error codes
     *
     * translate internal error identifier to PEAR-Error codes and human
     * readable messages.
     *
     * @var boolean $debug
     * @todo as I need unique error-codes to identify what exactly went wrond
     *       I did not use intergers as it should be. Instead I added a "namespace"
     *       for each code. This avoids conflicts with error codes from different
     *       classes. How can I use unique error codes and stay conform with PEAR?
     */
    var $errorCode = array(
        'not_connected' => array(
            'code'  => 1,
            'msg'   => 'Could not connect to any mail server ({HOST}) at port {PORT} to send mail to {RCPT}.'
        ),
        'failed_vrfy_rcpt' => array(
            'code'  => 2,
            'msg'   => 'Recipient "{RCPT}" could not be veryfied.'
        ),
        'failed_set_from' => array(
            'code'  => 3,
            'msg'   => 'Failed to set sender: {FROM}.'
        ),
        'failed_set_rcpt' => array(
            'code'  => 4,
            'msg'   => 'Failed to set recipient: {RCPT}.'
        ),
        'failed_send_data' => array(
            'code'  => 5,
            'msg'   => 'Failed to send mail to: {RCPT}.'
        ),
        'no_from' => array(
            'code'  => 5,
            'msg'   => 'No from address has be provided.'
        ),
        'send_data' => array(
            'code'  => 7,
            'msg'   => 'Failed to create Net_SMTP object.'
        ),
        'no_mx' => array(
            'code'  => 8,
            'msg'   => 'No MX-record for {RCPT} found.'
        ),
        'no_resolver' => array(
            'code'  => 9,
            'msg'   => 'Could not start resolver! Install PEAR:Net_DNS or switch off "netdns"'
        ),
        'failed_rset' => array(
            'code'  => 10,
            'msg'   => 'RSET command failed, SMTP-connection corrupt.'
        ),
    );

    /**
     * Constructor.
     *
     * Instantiates a new Mail_smtp:: object based on the parameters
     * passed in. It looks for the following parameters:
     *     mailname    The name of the local mail system (a valid hostname which matches the reverse lookup)
     *     port        smtp-port - the default comes from getservicebyname() and should work fine
     *     timeout     The SMTP connection timeout. Defaults to 30 seconds.
     *     vrfy        Whether to use VRFY or not. Defaults to false.
     *     verp        Whether to use VERP or not. Defaults to false.
     *     test        Activate test mode? Defaults to false.
     *     debug       Activate SMTP and Net_DNS debug mode? Defaults to false.
     *     netdns      whether to use PEAR:Net_DNS or the PHP build in function getmxrr, default is true
     *
     * If a parameter is present in the $params array, it replaces the
     * default.
     *
     * @access public
     * @param array Hash containing any parameters different from the
     *              defaults.
     * @see _Mail_smtpmx()
     */
    function __construct($params)
    {
        if (isset($params['mailname'])) {
            $this->mailname = $params['mailname'];
        } else {
            // try to find a valid mailname
            if (function_exists('posix_uname')) {
                $uname = posix_uname();
                $this->mailname = $uname['nodename'];
            }
        }

        // port number
        if (isset($params['port'])) {
            $this->_port = $params['port'];
        } else {
            $this->_port = getservbyname('smtp', 'tcp');
        }

        if (isset($params['timeout'])) $this->timeout = $params['timeout'];
        if (isset($params['verp'])) $this->verp = $params['verp'];
        if (isset($params['test'])) $this->test = $params['test'];
        if (isset($params['peardebug'])) $this->test = $params['peardebug'];
        if (isset($params['netdns'])) $this->withNetDns = $params['netdns'];
    }

    /**
     * Constructor wrapper for PHP4
     *
     * @access public
     * @param array Hash containing any parameters different from the defaults
     * @see __construct()
     */
    function Mail_smtpmx($params)
    {
        $this->__construct($params);
        register_shutdown_function(array(&$this, '__destruct'));
    }

    /**
     * Destructor implementation to ensure that we disconnect from any
     * potentially-alive persistent SMTP connections.
     */
    function __destruct()
    {
        if (is_object($this->_smtp)) {
            $this->_smtp->disconnect();
            $this->_smtp = null;
        }
    }

    /**
     * Implements Mail::send() function using SMTP direct delivery
     *
     * @access public
     * @param mixed $recipients in RFC822 style or array
     * @param array $headers The array of headers to send with the mail.
     * @param string $body The full text of the message body,
     * @return mixed Returns true on success, or a PEAR_Error
     */
    function send($recipients, $headers, $body)
    {
        if (!is_array($headers)) {
            return PEAR::raiseError('$headers must be an array');
        }

        $result = $this->_sanitizeHeaders($headers);
        if (is_a($result, 'PEAR_Error')) {
            return $result;
        }

        // Prepare headers
        $headerElements = $this->prepareHeaders($headers);
        if (is_a($headerElements, 'PEAR_Error')) {
            return $headerElements;
        }
        list($from, $textHeaders) = $headerElements;

        // use 'Return-Path' if possible
        if (!empty($headers['Return-Path'])) {
            $from = $headers['Return-Path'];
        }
        if (!isset($from)) {
            return $this->_raiseError('no_from');
        }

        // Prepare recipients
        $recipients = $this->parseRecipients($recipients);
        if (is_a($recipients, 'PEAR_Error')) {
            return $recipients;
        }

        foreach ($recipients as $rcpt) {
            list($user, $host) = explode('@', $rcpt);

            $mx = $this->_getMx($host);
            if (is_a($mx, 'PEAR_Error')) {
                return $mx;
            }

            if (empty($mx)) {
                $info = array('rcpt' => $rcpt);
                return $this->_raiseError('no_mx', $info);
            }

            $connected = false;
            foreach ($mx as $mserver => $mpriority) {
                $this->_smtp = new Net_SMTP($mserver, $this->port, $this->mailname);

                // configure the SMTP connection.
                if ($this->debug) {
                    $this->_smtp->setDebug(true);
                }

                // attempt to connect to the configured SMTP server.
                $res = $this->_smtp->connect($this->timeout);
                if (is_a($res, 'PEAR_Error')) {
                    $this->_smtp = null;
                    continue;
                }

                // connection established
                if ($res) {
                    $connected = true;
                    break;
                }
            }

            if (!$connected) {
                $info = array(
                    'host' => implode(', ', array_keys($mx)),
                    'port' => $this->port,
                    'rcpt' => $rcpt,
                );
                return $this->_raiseError('not_connected', $info);
            }

            // Verify recipient
            if ($this->vrfy) {
                $res = $this->_smtp->vrfy($rcpt);
                if (is_a($res, 'PEAR_Error')) {
                    $info = array('rcpt' => $rcpt);
                    return $this->_raiseError('failed_vrfy_rcpt', $info);
                }
            }

            // mail from:
            $args['verp'] = $this->verp;
            $res = $this->_smtp->mailFrom($from, $args);
            if (is_a($res, 'PEAR_Error')) {
                $info = array('from' => $from);
                return $this->_raiseError('failed_set_from', $info);
            }

            // rcpt to:
            $res = $this->_smtp->rcptTo($rcpt);
            if (is_a($res, 'PEAR_Error')) {
                $info = array('rcpt' => $rcpt);
                return $this->_raiseError('failed_set_rcpt', $info);
            }

            // Don't send anything in test mode
            if ($this->test) {
                $result = $this->_smtp->rset();
                $res = $this->_smtp->rset();
                if (is_a($res, 'PEAR_Error')) {
                    return $this->_raiseError('failed_rset');
                }

                $this->_smtp->disconnect();
                $this->_smtp = null;
                return true;
            }

            // Send data
            $res = $this->_smtp->data($body, $textHeaders);
            if (is_a($res, 'PEAR_Error')) {
                $info = array('rcpt' => $rcpt);
                return $this->_raiseError('failed_send_data', $info);
            }

            $this->_smtp->disconnect();
            $this->_smtp = null;
        }

        return true;
    }

    /**
     * Recieve mx rexords for a spciefied host
     *
     * The MX records
     *
     * @access private
     * @param string $host mail host
     * @return mixed sorted
     */
    function _getMx($host)
    {
        $mx = array();

        if ($this->withNetDns) {
            $res = $this->_loadNetDns();
            if (is_a($res, 'PEAR_Error')) {
                return $res;
            }

            $response = $this->resolver->query($host, 'MX');
            if (!$response) {
                return false;
            }

            foreach ($response->answer as $rr) {
                if ($rr->type == 'MX') {
                    $mx[$rr->exchange] = $rr->preference;
                }
            }
        } else {
            $mxHost = array();
            $mxWeight = array();

            if (!getmxrr($host, $mxHost, $mxWeight)) {
                return false;
            }
            for ($i = 0; $i < count($mxHost); ++$i) {
                $mx[$mxHost[$i]] = $mxWeight[$i];
            }
        }

        asort($mx);
        return $mx;
    }

    /**
     * initialize PEAR:Net_DNS_Resolver
     *
     * @access private
     * @return boolean true on success
     */
    function _loadNetDns()
    {
        if (is_object($this->resolver)) {
            return true;
        }

        if (!include_once 'Net/DNS.php') {
            return $this->_raiseError('no_resolver');
        }

        $this->resolver = new Net_DNS_Resolver();
        if ($this->debug) {
            $this->resolver->test = 1;
        }

        return true;
    }

    /**
     * raise standardized error
     *
     * include additional information in error message
     *
     * @access private
     * @param string $id maps error ids to codes and message
     * @param array $info optional information in associative array
     * @see _errorCode
     */
    function _raiseError($id, $info = array())
    {
        $code = $this->errorCode[$id]['code'];
        $msg = $this->errorCode[$id]['msg'];

        // include info to messages
        if (!empty($info)) {
            $search = array();
            $replace = array();

            foreach ($info as $key => $value) {
                array_push($search, '{' . strtoupper($key) . '}');
                array_push($replace, $value);
            }

            $msg = str_replace($search, $replace, $msg);
        }

        return PEAR::raiseError($msg, $code);
    }

}
PKn�Z�؛�J�J�Mail/mimePart.phpnu�[���<?php
/**
 * The Mail_mimePart class is used to create MIME E-mail messages
 *
 * This class enables you to manipulate and build a mime email
 * from the ground up. The Mail_Mime class is a userfriendly api
 * to this class for people who aren't interested in the internals
 * of mime mail.
 * This class however allows full control over the email.
 *
 * Compatible with PHP version 5, 7 and 8
 *
 * LICENSE: This LICENSE is in the BSD license style.
 * Copyright (c) 2002-2003, Richard Heyes <richard@phpguru.org>
 * Copyright (c) 2003-2006, PEAR <pear-group@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 * - Neither the name of the authors, nor the names of its contributors
 *   may be used to endorse or promote products derived from this
 *   software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  Mail
 * @package   Mail_Mime
 * @author    Richard Heyes  <richard@phpguru.org>
 * @author    Cipriano Groenendal <cipri@php.net>
 * @author    Sean Coates <sean@php.net>
 * @author    Aleksander Machniak <alec@php.net>
 * @copyright 2003-2006 PEAR <pear-group@php.net>
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/Mail_mime
 */

/**
 * Require PEAR
 *
 * This package depends on PEAR to raise errors.
 */
require_once 'PEAR.php';

/**
 * The Mail_mimePart class is used to create MIME E-mail messages
 *
 * This class enables you to manipulate and build a mime email
 * from the ground up. The Mail_Mime class is a userfriendly api
 * to this class for people who aren't interested in the internals
 * of mime mail.
 * This class however allows full control over the email.
 *
 * @category  Mail
 * @package   Mail_Mime
 * @author    Richard Heyes  <richard@phpguru.org>
 * @author    Cipriano Groenendal <cipri@php.net>
 * @author    Sean Coates <sean@php.net>
 * @author    Aleksander Machniak <alec@php.net>
 * @copyright 2003-2006 PEAR <pear-group@php.net>
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/Mail_mime
 */
class Mail_mimePart
{
    /**
     * The encoding type of this part
     *
     * @var string
     */
    protected $encoding;

    /**
     * An array of subparts
     *
     * @var array
     */
    protected $subparts = array();

    /**
     * The output of this part after being built
     *
     * @var string
     */
    protected $encoded;

    /**
     * Headers for this part
     *
     * @var array
     */
    protected $headers = array();

    /**
     * The body of this part (not encoded)
     *
     * @var string
     */
    protected $body;

    /**
     * The location of file with body of this part (not encoded)
     *
     * @var string
     */
    protected $body_file;

    /**
     * The short text of multipart part preamble (RFC2046 5.1.1)
     *
     * @var string
     */
    protected $preamble;

    /**
     * The end-of-line sequence
     *
     * @var string
     */
    protected $eol = "\r\n";


    /**
     * Constructor.
     *
     * Sets up the object.
     *
     * @param string $body   The body of the mime part if any.
     * @param array  $params An associative array of optional parameters:
     *                       - content_type: The content type for this part eg multipart/mixed
     *                       - encoding:  The encoding to use, 7bit, 8bit, base64, or quoted-printable
     *                       - charset: Content character set
     *                       - cid: Content ID to apply
     *                       - disposition: Content disposition, inline or attachment
     *                       - filename: Filename parameter for content disposition
     *                       - description: Content description
     *                       - name_encoding: Encoding of the attachment name (Content-Type)
     *                       By default filenames are encoded using RFC2231
     *                       Here you can set RFC2047 encoding (quoted-printable
     *                       or base64) instead
     *                       - filename_encoding: Encoding of the attachment filename (Content-Disposition)
     *                       See 'name_encoding'
     *                       - headers_charset: Charset of the headers e.g. filename, description.
     *                       If not set, 'charset' will be used
     *                       - eol: End of line sequence. Default: "\r\n"
     *                       - headers: Hash array with additional part headers. Array keys
     *                       can be in form of <header_name>:<parameter_name>
     *                       - body_file: Location of file with part's body (instead of $body)
     *                       - preamble: short text of multipart part preamble (RFC2046 5.1.1)
     */
    public function __construct($body = '', $params = array())
    {
        if (!empty($params['eol'])) {
            $this->eol = $params['eol'];
        } else if (defined('MAIL_MIMEPART_CRLF')) { // backward-copat.
            $this->eol = MAIL_MIMEPART_CRLF;
        }

        // Additional part headers
        if (!empty($params['headers']) && is_array($params['headers'])) {
            $headers = $params['headers'];
        }

        foreach ($params as $key => $value) {
            switch ($key) {
            case 'encoding':
                $this->encoding = $value;
                $headers['Content-Transfer-Encoding'] = $value;
                break;

            case 'cid':
                $headers['Content-ID'] = '<' . $value . '>';
                break;

            case 'location':
                $headers['Content-Location'] = $value;
                break;

            case 'body_file':
                $this->body_file = $value;
                break;

            case 'preamble':
                $this->preamble = $value;
                break;

            // for backward compatibility
            case 'dfilename':
                $params['filename'] = $value;
                break;
            }
        }

        // Default content-type
        if (empty($params['content_type'])) {
            $params['content_type'] = 'text/plain';
        }

        // Content-Type
        $headers['Content-Type'] = $params['content_type'];
        if (!empty($params['charset'])) {
            $charset = "charset={$params['charset']}";
            // place charset parameter in the same line, if possible
            if ((strlen($headers['Content-Type']) + strlen($charset) + 16) <= 76) {
                $headers['Content-Type'] .= '; ';
            } else {
                $headers['Content-Type'] .= ';' . $this->eol . ' ';
            }
            $headers['Content-Type'] .= $charset;

            // Default headers charset
            if (!isset($params['headers_charset'])) {
                $params['headers_charset'] = $params['charset'];
            }
        }

        // header values encoding parameters
        $h_charset  = !empty($params['headers_charset']) ? $params['headers_charset'] : 'US-ASCII';
        $h_language = !empty($params['language']) ? $params['language'] : null;
        $h_encoding = !empty($params['name_encoding']) ? $params['name_encoding'] : null;

        if (!empty($params['filename'])) {
            $headers['Content-Type'] .= ';' . $this->eol;
            $headers['Content-Type'] .= $this->buildHeaderParam(
                'name', $params['filename'], $h_charset, $h_language, $h_encoding
            );
        }

        // Content-Disposition
        if (!empty($params['disposition'])) {
            $headers['Content-Disposition'] = $params['disposition'];
            if (!empty($params['filename'])) {
                $headers['Content-Disposition'] .= ';' . $this->eol;
                $headers['Content-Disposition'] .= $this->buildHeaderParam(
                    'filename', $params['filename'], $h_charset, $h_language,
                    !empty($params['filename_encoding']) ? $params['filename_encoding'] : null
                );
            }

            // add attachment size
            $size = $this->body_file ? filesize($this->body_file) : strlen($body);
            if ($size) {
                $headers['Content-Disposition'] .= ';' . $this->eol . ' size=' . $size;
            }
        }

        if (!empty($params['description'])) {
            $headers['Content-Description'] = $this->encodeHeader(
                'Content-Description', $params['description'], $h_charset, $h_encoding,
                $this->eol
            );
        }

        // Search and add existing headers' parameters
        foreach ($headers as $key => $value) {
            $items = explode(':', $key);
            if (count($items) == 2) {
                $header = $items[0];
                $param  = $items[1];
                if (isset($headers[$header])) {
                    $headers[$header] .= ';' . $this->eol;
                }
                $headers[$header] .= $this->buildHeaderParam(
                    $param, $value, $h_charset, $h_language, $h_encoding
                );
                unset($headers[$key]);
            }
        }

        // Default encoding
        if (!isset($this->encoding)) {
            $this->encoding = '7bit';
        }

        // Assign stuff to member variables
        $this->encoded  = array();
        $this->headers  = $headers;
        $this->body     = $body;
    }

    /**
     * Encodes and returns the email. Also stores
     * it in the encoded member variable
     *
     * @param string $boundary Pre-defined boundary string
     *
     * @return An associative array containing two elements,
     *         body and headers. The headers element is itself
     *         an indexed array. On error returns PEAR error object.
     */
    public function encode($boundary=null)
    {
        $encoded =& $this->encoded;

        if (count($this->subparts)) {
            $boundary = $boundary ? $boundary : '=_' . md5(rand() . microtime());
            $eol = $this->eol;

            $this->headers['Content-Type'] .= ";$eol boundary=\"$boundary\"";

            $encoded['body'] = '';

            if ($this->preamble) {
                $encoded['body'] .= $this->preamble . $eol . $eol;
            }

            for ($i = 0; $i < count($this->subparts); $i++) {
                $encoded['body'] .= '--' . $boundary . $eol;
                $tmp = $this->subparts[$i]->encode();
                if (is_a($tmp, 'PEAR_Error')) {
                    return $tmp;
                }
                foreach ($tmp['headers'] as $key => $value) {
                    $encoded['body'] .= $key . ': ' . $value . $eol;
                }
                $encoded['body'] .= $eol . $tmp['body'] . $eol;
            }

            $encoded['body'] .= '--' . $boundary . '--' . $eol;
        } else if ($this->body) {
            $encoded['body'] = $this->getEncodedData($this->body, $this->encoding);
        } else if ($this->body_file) {
            // Temporarily reset magic_quotes_runtime for file reads and writes
            if (version_compare(PHP_VERSION, '5.4.0', '<')) {
                $magic_quotes = @ini_set('magic_quotes_runtime', 0);
            }
            $body = $this->getEncodedDataFromFile($this->body_file, $this->encoding);
            if (isset($magic_quotes)) {
                @ini_set('magic_quotes_runtime', $magic_quotes);
            }

            if (is_a($body, 'PEAR_Error')) {
                return $body;
            }
            $encoded['body'] = $body;
        } else {
            $encoded['body'] = '';
        }

        // Add headers to $encoded
        $encoded['headers'] =& $this->headers;

        return $encoded;
    }

    /**
     * Encodes and saves the email into file or stream.
     * Data will be appended to the file/stream.
     *
     * @param mixed   $filename  Existing file location
     *                           or file pointer resource
     * @param string  $boundary  Pre-defined boundary string
     * @param boolean $skip_head True if you don't want to save headers
     *
     * @return array An associative array containing message headers
     *               or PEAR error object
     * @since  1.6.0
     */
    public function encodeToFile($filename, $boundary = null, $skip_head = false)
    {
        if (!is_resource($filename)) {
            if (file_exists($filename) && !is_writable($filename)) {
                $err = self::raiseError('File is not writeable: ' . $filename);
                return $err;
            }

            if (!($fh = fopen($filename, 'ab'))) {
                $err = self::raiseError('Unable to open file: ' . $filename);
                return $err;
            }
        } else {
            $fh = $filename;
        }

        // Temporarily reset magic_quotes_runtime for file reads and writes
        if (version_compare(PHP_VERSION, '5.4.0', '<')) {
            $magic_quotes = @ini_set('magic_quotes_runtime', 0);
        }

        $res = $this->encodePartToFile($fh, $boundary, $skip_head);

        if (!is_resource($filename)) {
            fclose($fh);
        }

        if (isset($magic_quotes)) {
            @ini_set('magic_quotes_runtime', $magic_quotes);
        }

        return is_a($res, 'PEAR_Error') ? $res : $this->headers;
    }

    /**
     * Encodes given email part into file
     *
     * @param string  $fh        Output file handle
     * @param string  $boundary  Pre-defined boundary string
     * @param boolean $skip_head True if you don't want to save headers
     *
     * @return array True on sucess or PEAR error object
     */
    protected function encodePartToFile($fh, $boundary = null, $skip_head = false)
    {
        $eol = $this->eol;

        if (count($this->subparts)) {
            $boundary = $boundary ? $boundary : '=_' . md5(rand() . microtime());
            $this->headers['Content-Type'] .= ";$eol boundary=\"$boundary\"";
        }

        if (!$skip_head) {
            foreach ($this->headers as $key => $value) {
                fwrite($fh, $key . ': ' . $value . $eol);
            }
            $f_eol = $eol;
        } else {
            $f_eol = '';
        }

        if (count($this->subparts)) {
            if ($this->preamble) {
                fwrite($fh, $f_eol . $this->preamble . $eol);
                $f_eol = $eol;
            }

            for ($i = 0; $i < count($this->subparts); $i++) {
                fwrite($fh, $f_eol . '--' . $boundary . $eol);
                $res = $this->subparts[$i]->encodePartToFile($fh);
                if (is_a($res, 'PEAR_Error')) {
                    return $res;
                }
                $f_eol = $eol;
            }

            fwrite($fh, $eol . '--' . $boundary . '--' . $eol);
        } else if ($this->body) {
            fwrite($fh, $f_eol);
            fwrite($fh, $this->getEncodedData($this->body, $this->encoding));
        } else if ($this->body_file) {
            fwrite($fh, $f_eol);
            $res = $this->getEncodedDataFromFile(
                $this->body_file, $this->encoding, $fh
            );
            if (is_a($res, 'PEAR_Error')) {
                return $res;
            }
        }

        return true;
    }

    /**
     * Adds a subpart to current mime part and returns
     * a reference to it
     *
     * @param mixed $body   The body of the subpart or Mail_mimePart object
     * @param array $params The parameters for the subpart, same
     *                      as the $params argument for constructor
     *
     * @return Mail_mimePart A reference to the part you just added.
     */
    public function addSubpart($body, $params = null)
    {
        if ($body instanceof Mail_mimePart) {
            $part = $body;
        } else {
            $part = new Mail_mimePart($body, $params);
        }

        $this->subparts[] = $part;

        return $part;
    }

    /**
     * Returns encoded data based upon encoding passed to it
     *
     * @param string $data     The data to encode.
     * @param string $encoding The encoding type to use, 7bit, base64,
     *                         or quoted-printable.
     *
     * @return string Encoded data string
     */
    protected function getEncodedData($data, $encoding)
    {
        switch ($encoding) {
        case 'quoted-printable':
            return self::quotedPrintableEncode($data, 76, $this->eol);
            break;

        case 'base64':
            return rtrim(chunk_split(base64_encode($data), 76, $this->eol));
            break;

        case '8bit':
        case '7bit':
        default:
            return $data;
        }
    }

    /**
     * Returns encoded data based upon encoding passed to it
     *
     * @param string   $filename Data file location
     * @param string   $encoding The encoding type to use, 7bit, base64,
     *                           or quoted-printable.
     * @param resource $fh       Output file handle. If set, data will be
     *                           stored into it instead of returning it
     *
     * @return string Encoded data or PEAR error object
     */
    protected function getEncodedDataFromFile($filename, $encoding, $fh = null)
    {
        if (!is_readable($filename)) {
            $err = self::raiseError('Unable to read file: ' . $filename);
            return $err;
        }

        if (!($fd = fopen($filename, 'rb'))) {
            $err = self::raiseError('Could not open file: ' . $filename);
            return $err;
        }

        $data = '';

        switch ($encoding) {
        case 'quoted-printable':
            while (!feof($fd)) {
                $buffer = self::quotedPrintableEncode(fgets($fd), 76, $this->eol);
                if ($fh) {
                    fwrite($fh, $buffer);
                } else {
                    $data .= $buffer;
                }
            }
            break;

        case 'base64':
            while (!feof($fd)) {
                // Should read in a multiple of 57 bytes so that
                // the output is 76 bytes per line. Don't use big chunks
                // because base64 encoding is memory expensive
                $buffer = fread($fd, 57 * 9198); // ca. 0.5 MB
                $buffer = base64_encode($buffer);
                $buffer = chunk_split($buffer, 76, $this->eol);
                if (feof($fd)) {
                    $buffer = rtrim($buffer);
                }

                if ($fh) {
                    fwrite($fh, $buffer);
                } else {
                    $data .= $buffer;
                }
            }
            break;

        case '8bit':
        case '7bit':
        default:
            while (!feof($fd)) {
                $buffer = fread($fd, 1048576); // 1 MB
                if ($fh) {
                    fwrite($fh, $buffer);
                } else {
                    $data .= $buffer;
                }
            }
        }

        fclose($fd);

        if (!$fh) {
            return $data;
        }
    }

    /**
     * Encodes data to quoted-printable standard.
     *
     * @param string $input    The data to encode
     * @param int    $line_max Optional max line length. Should
     *                         not be more than 76 chars
     * @param string $eol      End-of-line sequence. Default: "\r\n"
     *
     * @return string Encoded data
     */
    public static function quotedPrintableEncode($input , $line_max = 76, $eol = "\r\n")
    {
        /*
        // imap_8bit() is extremely fast, but doesn't handle properly some characters
        if (function_exists('imap_8bit') && $line_max == 76) {
            $input = preg_replace('/\r?\n/', "\r\n", $input);
            $input = imap_8bit($input);
            if ($eol != "\r\n") {
                $input = str_replace("\r\n", $eol, $input);
            }
            return $input;
        }
        */
        $lines  = preg_split("/\r?\n/", $input);
        $escape = '=';
        $output = '';

        foreach ($lines as $idx => $line) {
            $newline = '';
            $i = 0;

            while (isset($line[$i])) {
                $char = $line[$i];
                $dec  = ord($char);
                $i++;

                if (($dec == 32) && (!isset($line[$i]))) {
                    // convert space at eol only
                    $char = '=20';
                } elseif ($dec == 9 && isset($line[$i])) {
                    ; // Do nothing if a TAB is not on eol
                } elseif (($dec == 61) || ($dec < 32) || ($dec > 126)) {
                    // Escape unprintable chars
                    $char = $escape . sprintf('%02X', $dec);
                } elseif (($dec == 46) && (($newline == '')
                    || ((strlen($newline) + strlen(".=")) > $line_max
                    && isset($line[$i])))
                ) {
                    // Bug #9722: convert full-stop at bol,
                    // some Windows servers need this, won't break anything (cipri)
                    // Bug #11731: full-stop at bol also needs to be encoded
                    // if this line would push us over the line_max limit.
                    $char = '=2E';
                }

                // EOL is not counted
                if ((strlen($newline) + strlen($char) == $line_max)
                    && !isset($line[$i])
                ) {
                    ; // no soft break is needed if we're the last char
                } elseif ((strlen($newline) + strlen($char)) >= $line_max) {
                    // soft line break; " =\r\n" is okay
                    $output  .= $newline . $escape . $eol;
                    $newline  = '';
                }

                $newline .= $char;
            } // end of for

            $output .= $newline . $eol;
            unset($lines[$idx]);
        }

        // Don't want last crlf
        $output = substr($output, 0, -1 * strlen($eol));

        return $output;
    }

    /**
     * Encodes the parameter of a header.
     *
     * @param string $name      The name of the header-parameter
     * @param string $value     The value of the paramter
     * @param string $charset   The characterset of $value
     * @param string $language  The language used in $value
     * @param string $encoding  Parameter encoding. If not set, parameter value
     *                          is encoded according to RFC2231
     * @param int    $maxLength The maximum length of a line. Defauls to 75
     *
     * @return string
     */
    protected function buildHeaderParam($name, $value, $charset = null,
        $language = null, $encoding = null, $maxLength = 75
    ) {
        // RFC 2045:
        // value needs encoding if contains non-ASCII chars or is longer than 78 chars
        if (!preg_match('#[^\x20-\x7E]#', $value)) {
            $token_regexp = '#([^\x21\x23-\x27\x2A\x2B\x2D'
                . '\x2E\x30-\x39\x41-\x5A\x5E-\x7E])#';
            if (!preg_match($token_regexp, $value)) {
                // token
                if (strlen($name) + strlen($value) + 3 <= $maxLength) {
                    return " {$name}={$value}";
                }
            } else {
                // quoted-string
                $quoted = addcslashes($value, '\\"');
                if (strlen($name) + strlen($quoted) + 5 <= $maxLength) {
                    return " {$name}=\"{$quoted}\"";
                }
            }
        }

        // RFC2047: use quoted-printable/base64 encoding
        if ($encoding == 'quoted-printable' || $encoding == 'base64') {
            return $this->buildRFC2047Param($name, $value, $charset, $encoding);
        }

        // RFC2231:
        $encValue = preg_replace_callback(
            '/([^\x21\x23\x24\x26\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7E])/',
            array($this, 'encodeReplaceCallback'), $value
        );
        $value = "$charset'$language'$encValue";

        $header = " {$name}*={$value}";
        if (strlen($header) <= $maxLength) {
            return $header;
        }

        $preLength = strlen(" {$name}*0*=");
        $maxLength = max(16, $maxLength - $preLength - 3);
        $maxLengthReg = "|(.{0,$maxLength}[^\%][^\%])|";

        $headers = array();
        $headCount = 0;
        while ($value) {
            $matches = array();
            $found = preg_match($maxLengthReg, $value, $matches);
            if ($found) {
                $headers[] = " {$name}*{$headCount}*={$matches[0]}";
                $value = substr($value, strlen($matches[0]));
            } else {
                $headers[] = " {$name}*{$headCount}*={$value}";
                $value = '';
            }
            $headCount++;
        }

        $headers = implode(';' . $this->eol, $headers);
        return $headers;
    }

    /**
     * Encodes header parameter as per RFC2047 if needed
     *
     * @param string $name      The parameter name
     * @param string $value     The parameter value
     * @param string $charset   The parameter charset
     * @param string $encoding  Encoding type (quoted-printable or base64)
     * @param int    $maxLength Encoded parameter max length. Default: 76
     *
     * @return string Parameter line
     */
    protected function buildRFC2047Param($name, $value, $charset,
        $encoding = 'quoted-printable', $maxLength = 76
    ) {
        // WARNING: RFC 2047 says: "An 'encoded-word' MUST NOT be used in
        // parameter of a MIME Content-Type or Content-Disposition field",
        // but... it's supported by many clients/servers
        $quoted = '';

        if ($encoding == 'base64') {
            $value = base64_encode($value);
            $prefix = '=?' . $charset . '?B?';
            $suffix = '?=';

            // 2 x SPACE, 2 x '"', '=', ';'
            $add_len = strlen($prefix . $suffix) + strlen($name) + 6;
            $len = $add_len + strlen($value);

            while ($len > $maxLength) { 
                // We can cut base64-encoded string every 4 characters
                $real_len = floor(($maxLength - $add_len) / 4) * 4;
                $_quote = substr($value, 0, $real_len);
                $value = substr($value, $real_len);

                $quoted .= $prefix . $_quote . $suffix . $this->eol . ' ';
                $add_len = strlen($prefix . $suffix) + 4; // 2 x SPACE, '"', ';'
                $len = strlen($value) + $add_len;
            }
            $quoted .= $prefix . $value . $suffix;

        } else {
            // quoted-printable
            $value = $this->encodeQP($value);
            $prefix = '=?' . $charset . '?Q?';
            $suffix = '?=';

            // 2 x SPACE, 2 x '"', '=', ';'
            $add_len = strlen($prefix . $suffix) + strlen($name) + 6;
            $len = $add_len + strlen($value);

            while ($len > $maxLength) {
                $length = $maxLength - $add_len;
                // don't break any encoded letters
                if (preg_match("/^(.{0,$length}[^\=][^\=])/", $value, $matches)) {
                    $_quote = $matches[1];
                }

                $quoted .= $prefix . $_quote . $suffix . $this->eol . ' ';
                $value = substr($value, strlen($_quote));
                $add_len = strlen($prefix . $suffix) + 4; // 2 x SPACE, '"', ';'
                $len = strlen($value) + $add_len;
            }

            $quoted .= $prefix . $value . $suffix;
        }

        return " {$name}=\"{$quoted}\"";
    }

    /**
     * Return charset for mbstring functions.
     * Replace ISO-2022-JP with ISO-2022-JP-MS to convert Windows dependent
     * characters.
     *
     * @param string $charset A original charset
     *
     * @return string A charset for mbstring
     * @since  1.10.8
     */
    protected static function mbstringCharset($charset)
    {
        $mb_charset = $charset;

        if ($charset == 'ISO-2022-JP') {
            $mb_charset = 'ISO-2022-JP-MS';
        }

        return $mb_charset;
    }

    /**
     * Encodes a header as per RFC2047
     *
     * @param string $name     The header name
     * @param string $value    The header data to encode
     * @param string $charset  Character set name
     * @param string $encoding Encoding name (base64 or quoted-printable)
     * @param string $eol      End-of-line sequence. Default: "\r\n"
     *
     * @return string Encoded header data (without a name)
     * @since  1.6.1
     */
    public static function encodeHeader($name, $value, $charset = 'ISO-8859-1',
        $encoding = 'quoted-printable', $eol = "\r\n"
    ) {
        // Structured headers
        $comma_headers = array(
            'from', 'to', 'cc', 'bcc', 'sender', 'reply-to',
            'resent-from', 'resent-to', 'resent-cc', 'resent-bcc',
            'resent-sender', 'resent-reply-to',
            'mail-reply-to', 'mail-followup-to',
            'return-receipt-to', 'disposition-notification-to',
        );
        $other_headers = array(
            'references', 'in-reply-to', 'message-id', 'resent-message-id',
        );

        $name = strtolower($name);

        if (in_array($name, $comma_headers)) {
            $separator = ',';
        } else if (in_array($name, $other_headers)) {
            $separator = ' ';
        }

        if (!$charset) {
            $charset = 'ISO-8859-1';
        }

        // exploding quoted strings as well as some regexes below do not
        // work properly with some charset e.g. ISO-2022-JP, we'll use UTF-8
        $mb = $charset != 'UTF-8' && function_exists('mb_convert_encoding');
        $mb_charset = Mail_mimePart::mbstringCharset($charset);

        // Structured header (make sure addr-spec inside is not encoded)
        if (!empty($separator)) {
            // Simple e-mail address regexp
            $email_regexp = '([^\s<]+|("[^\r\n"]+"))@[^\s"]+';

            if ($mb) {
                $value = mb_convert_encoding($value, 'UTF-8', $mb_charset);
            }

            $parts = Mail_mimePart::explodeQuotedString("[\t$separator]", $value);
            $value = '';

            foreach ($parts as $part) {
                $part = preg_replace('/\r?\n[\s\t]*/', $eol . ' ', $part);
                $part = trim($part);

                if (!$part) {
                    continue;
                }
                if ($value) {
                    $value .= $separator == ',' ? $separator . ' ' : ' ';
                } else {
                    $value = $name . ': ';
                }

                // let's find phrase (name) and/or addr-spec
                if (preg_match('/^<' . $email_regexp . '>$/', $part)) {
                    $value .= $part;
                } else if (preg_match('/^' . $email_regexp . '$/', $part)) {
                    // address without brackets and without name
                    $value .= $part;
                } else if (preg_match('/<*' . $email_regexp . '>*$/', $part, $matches)) {
                    // address with name (handle name)
                    $address = $matches[0];
                    $word    = str_replace($address, '', $part);
                    $word    = trim($word);

                    // check if phrase requires quoting
                    if ($word) {
                        // non-ASCII: require encoding
                        if (preg_match('#([^\s\x21-\x7E]){1}#', $word)) {
                            if ($word[0] == '"' && $word[strlen($word)-1] == '"') {
                                // de-quote quoted-string, encoding changes
                                // string to atom
                                $word = substr($word, 1, -1);
                                $word = preg_replace('/\\\\([\\\\"])/', '$1', $word);
                            }
                            if ($mb) {
                                $word = mb_convert_encoding($word, $mb_charset, 'UTF-8');
                            }

                            // find length of last line
                            if (($pos = strrpos($value, $eol)) !== false) {
                                $last_len = strlen($value) - $pos;
                            } else {
                                $last_len = strlen($value);
                            }

                            $word = Mail_mimePart::encodeHeaderValue(
                                $word, $charset, $encoding, $last_len, $eol
                            );
                        } else if (($word[0] != '"' || $word[strlen($word)-1] != '"')
                            && preg_match('/[\(\)\<\>\\\.\[\]@,;:"]/', $word)
                        ) {
                            // ASCII: quote string if needed
                            $word = '"'.addcslashes($word, '\\"').'"';
                        }
                    }

                    $value .= $word.' '.$address;
                } else {
                    if ($mb) {
                        $part = mb_convert_encoding($part, $mb_charset, 'UTF-8');
                    }
                    // addr-spec not found, don't encode (?)
                    $value .= $part;
                }

                // RFC2822 recommends 78 characters limit, use 76 from RFC2047
                $value = wordwrap($value, 76, $eol . ' ');
            }

            // remove header name prefix (there could be EOL too)
            $value = preg_replace(
                '/^'.$name.':('.preg_quote($eol, '/').')* /', '', $value
            );
        } else {
            // Unstructured header
            // non-ASCII: require encoding
            if (preg_match('#([^\s\x21-\x7E]){1}#', $value)) {
                if ($value[0] == '"' && $value[strlen($value)-1] == '"') {
                    if ($mb) {
                        $value = mb_convert_encoding($value, 'UTF-8', $mb_charset);
                    }
                    // de-quote quoted-string, encoding changes
                    // string to atom
                    $value = substr($value, 1, -1);
                    $value = preg_replace('/\\\\([\\\\"])/', '$1', $value);
                    if ($mb) {
                        $value = mb_convert_encoding($value, $mb_charset, 'UTF-8');
                    }
                }

                $value = Mail_mimePart::encodeHeaderValue(
                    $value, $charset, $encoding, strlen($name) + 2, $eol
                );
            } else if (strlen($name.': '.$value) > 78) {
                // ASCII: check if header line isn't too long and use folding
                $value = preg_replace('/\r?\n[\s\t]*/', $eol . ' ', $value);
                $tmp   = wordwrap($name . ': ' . $value, 78, $eol . ' ');
                $value = preg_replace('/^' . $name . ':\s*/', '', $tmp);
                // hard limit 998 (RFC2822)
                $value = wordwrap($value, 998, $eol . ' ', true);
            }
        }

        return $value;
    }

    /**
     * Explode quoted string
     *
     * @param string $delimiter Delimiter expression string for preg_match()
     * @param string $string    Input string
     *
     * @return array String tokens array
     */
    protected static function explodeQuotedString($delimiter, $string)
    {
        $result = array();
        $strlen = strlen($string);
        $quoted_string = '"(?:[^"\\\\]|\\\\.)*"';

        for ($p=$i=0; $i < $strlen; $i++) {
            if ($string[$i] === '"') {
                $r = preg_match("/$quoted_string/", $string, $matches, 0, $i);
                if (!$r || empty($matches[0])) {
                    break;
                }
                $i += strlen($matches[0]) - 1;
            } else if (preg_match("/$delimiter/", $string[$i])) {
                $result[] = substr($string, $p, $i - $p);
                $p = $i + 1;
            }
        }
        $result[] = substr($string, $p);
        return $result;
    }

    /**
     * Encodes a header value as per RFC2047
     *
     * @param string $value      The header data to encode
     * @param string $charset    Character set name
     * @param string $encoding   Encoding name (base64 or quoted-printable)
     * @param int    $prefix_len Prefix length. Default: 0
     * @param string $eol        End-of-line sequence. Default: "\r\n"
     *
     * @return string Encoded header data
     * @since  1.6.1
     */
    public static function encodeHeaderValue($value, $charset, $encoding, $prefix_len = 0, $eol = "\r\n")
    {
        // #17311: Use multibyte aware method (requires mbstring extension)
        if ($result = Mail_mimePart::encodeMB($value, $charset, $encoding, $prefix_len, $eol)) {
            return $result;
        }

        // Generate the header using the specified params and dynamicly
        // determine the maximum length of such strings.
        // 75 is the value specified in the RFC.
        $encoding = $encoding == 'base64' ? 'B' : 'Q';
        $prefix = '=?' . $charset . '?' . $encoding .'?';
        $suffix = '?=';
        $maxLength = 75 - strlen($prefix . $suffix);
        $maxLength1stLine = $maxLength - $prefix_len;

        if ($encoding == 'B') {
            // Base64 encode the entire string
            $value = base64_encode($value);

            // We can cut base64 every 4 characters, so the real max
            // we can get must be rounded down.
            $maxLength = $maxLength - ($maxLength % 4);
            $maxLength1stLine = $maxLength1stLine - ($maxLength1stLine % 4);

            $cutpoint = $maxLength1stLine;
            $output = '';

            while ($value) {
                // Split translated string at every $maxLength
                $part = substr($value, 0, $cutpoint);
                $value = substr($value, $cutpoint);
                $cutpoint = $maxLength;
                // RFC 2047 specifies that any split header should
                // be separated by a CRLF SPACE.
                if ($output) {
                    $output .= $eol . ' ';
                }
                $output .= $prefix . $part . $suffix;
            }
            $value = $output;
        } else {
            // quoted-printable encoding has been selected
            $value = Mail_mimePart::encodeQP($value);

            // This regexp will break QP-encoded text at every $maxLength
            // but will not break any encoded letters.
            $reg1st = "|(.{0,$maxLength1stLine}[^\=][^\=])|";
            $reg2nd = "|(.{0,$maxLength}[^\=][^\=])|";

            if (strlen($value) > $maxLength1stLine) {
                // Begin with the regexp for the first line.
                $reg = $reg1st;
                $output = '';
                while ($value) {
                    // Split translated string at every $maxLength
                    // But make sure not to break any translated chars.
                    $found = preg_match($reg, $value, $matches);

                    // After this first line, we need to use a different
                    // regexp for the first line.
                    $reg = $reg2nd;

                    // Save the found part and encapsulate it in the
                    // prefix & suffix. Then remove the part from the
                    // $value_out variable.
                    if ($found) {
                        $part = $matches[0];
                        $len = strlen($matches[0]);
                        $value = substr($value, $len);
                    } else {
                        $part = $value;
                        $value = '';
                    }

                    // RFC 2047 specifies that any split header should
                    // be separated by a CRLF SPACE
                    if ($output) {
                        $output .= $eol . ' ';
                    }
                    $output .= $prefix . $part . $suffix;
                }
                $value = $output;
            } else {
                $value = $prefix . $value . $suffix;
            }
        }

        return $value;
    }

    /**
     * Encodes the given string using quoted-printable
     *
     * @param string $str String to encode
     *
     * @return string Encoded string
     * @since  1.6.0
     */
    public static function encodeQP($str)
    {
        // Bug #17226 RFC 2047 restricts some characters
        // if the word is inside a phrase, permitted chars are only:
        // ASCII letters, decimal digits, "!", "*", "+", "-", "/", "=", and "_"

        // "=",  "_",  "?" must be encoded
        $regexp = '/([\x22-\x29\x2C\x2E\x3A-\x40\x5B-\x60\x7B-\x7E\x80-\xFF])/';
        $str = preg_replace_callback(
            $regexp, array('Mail_mimePart', 'qpReplaceCallback'), $str
        );

        return str_replace(' ', '_', $str);
    }

    /**
     * Encodes the given string using base64 or quoted-printable.
     * This method makes sure that encoded-word represents an integral
     * number of characters as per RFC2047.
     *
     * @param string $str        String to encode
     * @param string $charset    Character set name
     * @param string $encoding   Encoding name (base64 or quoted-printable)
     * @param int    $prefix_len Prefix length. Default: 0
     * @param string $eol        End-of-line sequence. Default: "\r\n"
     *
     * @return string Encoded string
     * @since  1.8.0
     */
    public static function encodeMB($str, $charset, $encoding, $prefix_len=0, $eol="\r\n")
    {
        if (!function_exists('mb_substr') || !function_exists('mb_strlen')) {
            return;
        }

        $encoding = $encoding == 'base64' ? 'B' : 'Q';
        // 75 is the value specified in the RFC
        $prefix = '=?' . $charset . '?'.$encoding.'?';
        $suffix = '?=';
        $maxLength = 75 - strlen($prefix . $suffix);
        $mb_charset = Mail_mimePart::mbstringCharset($charset);

        // A multi-octet character may not be split across adjacent encoded-words
        // So, we'll loop over each character
        // mb_stlen() with wrong charset will generate a warning here and return null
        $length      = mb_strlen($str, $mb_charset);
        $result      = '';
        $line_length = $prefix_len;

        if ($encoding == 'B') {
            // base64
            $start = 0;
            $prev  = '';

            for ($i=1; $i<=$length; $i++) {
                // See #17311
                $chunk = mb_substr($str, $start, $i-$start, $mb_charset);
                $chunk = base64_encode($chunk);
                $chunk_len = strlen($chunk);

                if ($line_length + $chunk_len == $maxLength || $i == $length) {
                    if ($result) {
                        $result .= "\n";
                    }
                    $result .= $chunk;
                    $line_length = 0;
                    $start = $i;
                } else if ($line_length + $chunk_len > $maxLength) {
                    if ($result) {
                        $result .= "\n";
                    }
                    if ($prev) {
                        $result .= $prev;
                    }
                    $line_length = 0;
                    $start = $i - 1;
                } else {
                    $prev = $chunk;
                }
            }
        } else {
            // quoted-printable
            // see encodeQP()
            $regexp = '/([\x22-\x29\x2C\x2E\x3A-\x40\x5B-\x60\x7B-\x7E\x80-\xFF])/';

            for ($i=0; $i<=$length; $i++) {
                $char = mb_substr($str, $i, 1, $mb_charset);
                // RFC recommends underline (instead of =20) in place of the space
                // that's one of the reasons why we're not using iconv_mime_encode()
                if ($char == ' ') {
                    $char = '_';
                    $char_len = 1;
                } else {
                    $char = preg_replace_callback(
                        $regexp, array('Mail_mimePart', 'qpReplaceCallback'), $char
                    );
                    $char_len = strlen($char);
                }

                if ($line_length + $char_len > $maxLength) {
                    if ($result) {
                        $result .= "\n";
                    }
                    $line_length = 0;
                }

                $result      .= $char;
                $line_length += $char_len;
            }
        }

        if ($result) {
            $result = $prefix
                .str_replace("\n", $suffix.$eol.' '.$prefix, $result).$suffix;
        }

        return $result;
    }

    /**
     * Callback function to replace extended characters (\x80-xFF) with their
     * ASCII values (RFC2047: quoted-printable)
     *
     * @param array $matches Preg_replace's matches array
     *
     * @return string Encoded character string
     */
    protected static function qpReplaceCallback($matches)
    {
        return sprintf('=%02X', ord($matches[1]));
    }

    /**
     * Callback function to replace extended characters (\x80-xFF) with their
     * ASCII values (RFC2231)
     *
     * @param array $matches Preg_replace's matches array
     *
     * @return string Encoded character string
     */
    protected static function encodeReplaceCallback($matches)
    {
        return sprintf('%%%02X', ord($matches[1]));
    }

    /**
     * PEAR::raiseError implementation
     *
     * @param string $message A text error message
     *
     * @return PEAR_Error Instance of PEAR_Error
     */
    public static function raiseError($message)
    {
        // PEAR::raiseError() is not PHP 5.4 compatible
        return new PEAR_Error($message);
    }
}
PKn�ZB��shh
Mail/mock.phpnu�[���<?php
/**
 * Mock implementation
 *
 * PHP version 5
 *
 * LICENSE:
 *
 * Copyright (c) 2010-2017, Chuck Hagenbuch
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category    Mail
 * @package     Mail
 * @author      Chuck Hagenbuch <chuck@horde.org> 
 * @copyright   2010-2017 Chuck Hagenbuch
 * @license     http://opensource.org/licenses/BSD-3-Clause New BSD License
 * @version     CVS: $Id$
 * @link        http://pear.php.net/package/Mail/
 */

/**
 * Mock implementation of the PEAR Mail:: interface for testing.
 * @access public
 * @package Mail
 * @version $Revision$
 */
class Mail_mock extends Mail {

    /**
     * Array of messages that have been sent with the mock.
     *
     * @var array
     */
    public $sentMessages = array();

    /**
     * Callback before sending mail.
     *
     * @var callback
     */
    protected $_preSendCallback;

    /**
     * Callback after sending mai.
     *
     * @var callback
     */
    protected $_postSendCallback;

    /**
     * Constructor.
     *
     * Instantiates a new Mail_mock:: object based on the parameters
     * passed in. It looks for the following parameters, both optional:
     *     preSendCallback   Called before an email would be sent.
     *     postSendCallback  Called after an email would have been sent.
     *
     * @param array Hash containing any parameters.
     */
    public function __construct($params)
    {
        if (isset($params['preSendCallback']) &&
            is_callable($params['preSendCallback'])) {
            $this->_preSendCallback = $params['preSendCallback'];
        }

        if (isset($params['postSendCallback']) &&
            is_callable($params['postSendCallback'])) {
            $this->_postSendCallback = $params['postSendCallback'];
        }
    }

    /**
     * Implements Mail_mock::send() function. Silently discards all
     * mail.
     *
     * @param mixed $recipients Either a comma-seperated list of recipients
     *              (RFC822 compliant), or an array of recipients,
     *              each RFC822 valid. This may contain recipients not
     *              specified in the headers, for Bcc:, resending
     *              messages, etc.
     *
     * @param array $headers The array of headers to send with the mail, in an
     *              associative array, where the array key is the
     *              header name (ie, 'Subject'), and the array value
     *              is the header value (ie, 'test'). The header
     *              produced from those values would be 'Subject:
     *              test'.
     *
     * @param string $body The full text of the message body, including any
     *               Mime parts, etc.
     *
     * @return mixed Returns true on success, or a PEAR_Error
     *               containing a descriptive error message on
     *               failure.
     */
    public function send($recipients, $headers, $body)
    {
        if ($this->_preSendCallback) {
            call_user_func_array($this->_preSendCallback,
                                 array(&$this, $recipients, $headers, $body));
        }

        $entry = array('recipients' => $recipients, 'headers' => $headers, 'body' => $body);
        $this->sentMessages[] = $entry;

        if ($this->_postSendCallback) {
            call_user_func_array($this->_postSendCallback,
                                 array(&$this, $recipients, $headers, $body));
        }

        return true;
    }

}
PKn�Z@iE�\\
Mail/mail.phpnu�[���<?php
/**
 * internal PHP-mail() implementation of the PEAR Mail:: interface.
 *
 * PHP version 5
 *
 * LICENSE:
 *
 * Copyright (c) 2010-2017, Chuck Hagenbuch
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category    Mail
 * @package     Mail
 * @author      Chuck Hagenbuch <chuck@horde.org> 
 * @copyright   2010-2017 Chuck Hagenbuch
 * @license     http://opensource.org/licenses/BSD-3-Clause New BSD License
 * @version     CVS: $Id$
 * @link        http://pear.php.net/package/Mail/
 */

/**
 * internal PHP-mail() implementation of the PEAR Mail:: interface.
 * @package Mail
 * @version $Revision$
 */
class Mail_mail extends Mail {

    /**
     * Any arguments to pass to the mail() function.
     * @var string
     */
    var $_params = '';

    /**
     * Constructor.
     *
     * Instantiates a new Mail_mail:: object based on the parameters
     * passed in.
     *
     * @param array $params Extra arguments for the mail() function.
     */
    public function __construct($params = null)
    {
        // The other mail implementations accept parameters as arrays.
        // In the interest of being consistent, explode an array into
        // a string of parameter arguments.
        if (is_array($params)) {
            $this->_params = join(' ', $params);
        } else {
            $this->_params = $params;
        }

        /* Because the mail() function may pass headers as command
         * line arguments, we can't guarantee the use of the standard
         * "\r\n" separator.  Instead, we use the system's native line
         * separator. */
        if (defined('PHP_EOL')) {
            $this->sep = PHP_EOL;
        } else {
            $this->sep = (strpos(PHP_OS, 'WIN') === false) ? "\n" : "\r\n";
        }
    }

    /**
     * Implements Mail_mail::send() function using php's built-in mail()
     * command.
     *
     * @param mixed $recipients Either a comma-seperated list of recipients
     *              (RFC822 compliant), or an array of recipients,
     *              each RFC822 valid. This may contain recipients not
     *              specified in the headers, for Bcc:, resending
     *              messages, etc.
     *
     * @param array $headers The array of headers to send with the mail, in an
     *              associative array, where the array key is the
     *              header name (ie, 'Subject'), and the array value
     *              is the header value (ie, 'test'). The header
     *              produced from those values would be 'Subject:
     *              test'.
     *
     * @param string $body The full text of the message body, including any
     *               Mime parts, etc.
     *
     * @return mixed Returns true on success, or a PEAR_Error
     *               containing a descriptive error message on
     *               failure.
     */
    public function send($recipients, $headers, $body)
    {
        if (!is_array($headers)) {
            return PEAR::raiseError('$headers must be an array');
        }

        $result = $this->_sanitizeHeaders($headers);
        if (is_a($result, 'PEAR_Error')) {
            return $result;
        }

        // If we're passed an array of recipients, implode it.
        if (is_array($recipients)) {
            $recipients = implode(', ', $recipients);
        }

        // Get the Subject out of the headers array so that we can
        // pass it as a seperate argument to mail().
        $subject = '';
        if (isset($headers['Subject'])) {
            $subject = $headers['Subject'];
            unset($headers['Subject']);
        }

        // Also remove the To: header.  The mail() function will add its own
        // To: header based on the contents of $recipients.
        unset($headers['To']);

        // Flatten the headers out.
        $headerElements = $this->prepareHeaders($headers);
        if (is_a($headerElements, 'PEAR_Error')) {
            return $headerElements;
        }
        list(, $text_headers) = $headerElements;

        // We only use mail()'s optional fifth parameter if the additional
        // parameters have been provided and we're not running in safe mode.
        if (empty($this->_params) || ini_get('safe_mode')) {
            $result = mail($recipients, $subject, $body, $text_headers);
        } else {
            $result = mail($recipients, $subject, $body, $text_headers,
                           $this->_params);
        }

        // If the mail() function returned failure, we need to create a
        // PEAR_Error object and return it instead of the boolean result.
        if ($result === false) {
            $result = PEAR::raiseError('mail() returned failure');
        }

        return $result;
    }

}
PKn�Z.locknu�[���PKn�Z�*�z%-%- Structures/LinkedList/Double.phpnu�[���<?php

/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker textwidth=80: */

/**
 * Linked list structure
 * 
 * This package implements a doubly linked list structure. Each node
 * (Structures_LinkedList_DoubleNode object) in the list
 * (Structures_LinkedList_Double) knows the previous node and the next
 * node in the list. Unlike an array, you can insert or delete nodes at
 * arbitrary points in the list.
 *
 * If your application normally traverses the linked list in a forward-only
 * direction, use the singly-linked list implemented by
 * {@link Structures_LinkedList_Single}. If, however, your application
 * needs to traverse the list backwards, or insert nodes into the list before
 * other nodes in the list, use the double-linked list implemented by
 * {@link Structures_LinkedList_Double} to give your application better
 * performance at the cost of a slightly larger memory footprint.
 *
 * Structures_LinkedList_Double implements the Iterator interface so control
 * structures like foreach($list as $node) and while($list->next()) work
 * as expected.
 *
 * To use this package, derive a child class from
 * Structures_LinkedList_DoubleNode  and add data to the object. Then use the
 * Structures_LinkedList_Double class to access the nodes.
 *
 * PHP version 5
 *
 * LICENSE:  Copyright 2006 Dan Scott
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may obtain
 * a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @category  Structures
 * @package   Structures_LinkedList_Double
 * @author    Dan Scott <dscott@laurentian.ca>
 * @copyright 2006 Dan Scott
 * @license   http://www.apache.org/licenses/LICENSE-2.0  Apache License, Version 2.0
 * @version   CVS: $Id: Double.php -1   $
 * @link      http://pear.php.net/package/Structures_LinkedList
 * @example   double_link_example.php
 *
 * @todo Add some actual error conditions
 **/

require_once 'PEAR/Exception.php';
require_once 'Single.php';

// {{{ class Structures_LinkedList_Double
/**
 * The Structures_LinkedList_Double class represents a linked list structure
 * composed of {@link Structures_LinkedList_DoubleNode} objects.
 *
 * @category Structures
 * @package  Structures_LinkedList_Double
 * @author   Dan Scott <dscott@laurentian.ca>
 * @license  http://www.apache.org/licenses/LICENSE-2.0  Apache License, Version 2.0
 * @link     http://pear.php.net/package/Structures_LinkedList
 */
class Structures_LinkedList_Double extends Structures_LinkedList_Single implements Iterator
{
    // {{{ properties
    /**
     * Tail node of the linked list
     * @var Structures_LinkedList_DoubleNode
     */
    protected $tail_node;
    // }}}

    // {{{ Constructor: function __construct()
    /**
     * Structures_LinkedList_Double constructor
     *
     * @param Structures_LinkedList_DoubleNode $root root node for the
     * linked list
     */
    function __construct(Structures_LinkedList_DoubleNode $root = null)
    {
        if ($root) {
            $this->tail_node = $root;
        } else {
            $this->tail_node = null;
        }
        parent::__construct($root);
    }
    // }}}

    // {{{ Destructor: function __destruct()
    /**
     * Structures_LinkedList_Double destructor
     *
     * If we do not destroy all of the references in the linked list,
     * we will quickly run out of memory for large / complex structures.
     *
     */
    function __destruct()
    {
        /*
         * Starting with root node, set last node = root_node
         *   get next node
         *   if next node exists:
         *     delete last node's references to next node and previous node
         *     make the old next node the new last node
         */
        if (!$last_node = $this->root_node) {
            return;
        }
        while (($next_node = $last_node->next()) !== false) {
            $last_node->setNext(null);
            $last_node->setPrevious(null);
            $last_node = $next_node;
        }
        $this->current = null;
        $this->root_node = null;
        $this->tail_node = null;
        $last_node = null;
        $next_node = null;
    }
    // }}}

    // {{{ function end()
    /**
     * Sets the pointer for the linked list to its last node
     *
     * @return Structures_LinkedList_DoubleNode last node in the linked list
     */
    public function end()
    {
        if ($this->tail_node) {
            $this->current = $this->tail_node;
        } else {
            $this->current = null;
        }
        return $this->current;
    }
    // }}}

    // {{{ function previous()
    /**
     * Sets the pointer for the linked list to the previous node and
     * returns that node
     *
     * @return Structures_LinkedList_DoubleNode previous node in the linked list
     */
    public function previous()
    {
        if (!$this->current()->previous()) {
            return false;
        }
        $this->current = $this->current()->previous();
        return $this->current();
    }
    // }}}

    // {{{ function insertNode()
    /**
     * Inserts a {@link Structures_LinkedList_DoubleNode} object into the linked
     * list, based on a reference node that already exists in the list.
     *
     * @param Structures_LinkedList_DoubleNode $new_node      New node to add to the list
     * @param Structures_LinkedList_DoubleNode $existing_node Reference position node
     * @param bool                             $before        Insert new node before or after the existing node
     *
     * @return bool Success or failure
     **/
    public function insertNode($new_node, $existing_node, $before = false)
    {
        if (!$this->root_node) {
            $this->__construct($new_node);
        }

        // Now add the node according to the requested mode
        switch ($before) {

        case true:
            $previous_node = $existing_node->previous();
            if ($previous_node) {
                $previous_node->setNext($new_node);
                $new_node->setPrevious($previous_node);
            } else {
                // The existing node must be root node; make new node root
                $this->root_node = $new_node;
                $new_node->setPrevious();
            }
            $new_node->setNext($existing_node);
            $existing_node->setPrevious($new_node);

            break;

        case false:
            $new_node->setPrevious($existing_node);
            $next_node = $existing_node->next();
            if ($next_node) {
                $new_node->setNext($next_node);
                $next_node->setPrevious($new_node);
            } else {
                // The existing node must have been the tail node
                $this->tail_node = $new_node;
            }
            $existing_node->setNext($new_node);

            break;

        }

        return true;
    }
    // }}}

    // {{{ protected function getTailNode()
    /**
     * Returns the tail node of the linked list.
     *
     * This is a cheap operation for a doubly-linked list.
     *
     * @return bool Success or failure
     **/
    protected function getTailNode()
    {
        return $this->tail_node;
    }
    // }}}

    // {{{ function deleteNode()
    /**
     * Deletes a {@link Structures_LinkedList_DoubleNode} from the list.
     *
     * @param Structures_LinkedList_DoubleNode $node Node to delete.
     *
     * @return null
     */
    public function deleteNode($node)
    {
        /* If this is the root node, and there are more nodes in the list,
         * make the next node the new root node before deleting this node.
         */
        if ($node === $this->root_node) {
            $this->root_node = $node->next();
        }
        
        /* If this is the tail node, and there are more nodes in the list,
         * make the previous node the tail node before deleting this node
         */
        if ($node === $this->tail_node) {
            $this->tail_node = $node->previous();
        }

        /* If this is the current node, and there are other nodes in the list,
         * try making the previous node the current node so that next() works
         * as expected.
         *
         * If that fails, make the next node the current node.
         *
         * If that fails, null isn't such a bad place to be.
         */
        if ($node === $this->current) {
            if ($node->previous()) {
                $this->current = $node->previous();
            } elseif ($node->next()) {
                $this->current = $node->next();
            } else {
                $this->current = null;
            }
        }
        $node->__destruct();
    }
    // }}}

}
// }}}

// {{{ class Structures_LinkedList_DoubleNode
/**
 * The Structures_LinkedList_DoubleNode class represents a node in a
 * {@link Structures_LinkedList_Double} linked list structure.
 *
 * @category Structures
 * @package  Structures_LinkedList_Double
 * @author   Dan Scott <dscott@laurentian.ca>
 * @license  http://www.apache.org/licenses/LICENSE-2.0  Apache License, Version 2.0
 * @link     http://pear.php.net/package/Structures_LinkedList
 */
class Structures_LinkedList_DoubleNode extends Structures_LinkedList_SingleNode
{
    // {{{ properties
    /**
     * Previous node in the linked list
     * @var Structures_LinkedList_DoubleNode
     */
    protected $previous;
    // }}}

    // {{{ Constructor: function __construct()
    /**
     * Structures_LinkedList_DoubleNode constructor
     */
    public function __construct()
    {
        $this->next = null;
        $this->previous = null;
    }
    // }}}

    // {{{ Destructor: function __destruct()
    /**
     * Removes node from the list, adjusting the related nodes accordingly.
     *
     * This is a problem if the node is the root node for the list.
     * At this point, however, we do not have access to the list itself. Hmm.
     */
    public function __destruct()
    {
        $next = $this->next();
        $previous = $this->previous();
        if ($previous && $next) {
            $previous->setNext($next);
            $next->setPrevious($previous);
        } elseif ($previous) {
            $previous->setNext();
        } elseif ($next) {
            $next->setPrevious();
        }
    }
    // }}}

    // {{{ function previous()
    /**
     * Return the previous node in the linked list
     *
     * @return Structures_LinkedList_DoubleNode previous node in the linked list
     */
    public function previous()
    {
        if ($this->previous) {
            return $this->previous;
        } else {
            return false;
        }
    }
    // }}}

    // {{{ function setPrevious()
    /**
     * Sets the pointer for the previous node in the linked list
     * to the specified node
     *
     * @param Structures_LinkedList_DoubleNode $node new previous node
     * in the linked list
     *
     * @return Structures_LinkedList_DoubleNode new previous node in
     * the linked list
     */
    public function setPrevious($node = null)
    {
        $this->previous = $node;
        return $this->previous;
    }
    // }}}

}
// }}}

?>
PKn�Z����p:p: Structures/LinkedList/Single.phpnu�[���<?php

/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker textwidth=80: */

/**
 * Linked list structure
 * 
 * This package implements a singly linked list structure. Each node
 * (Structures_LinkedList_SingleNode object) in the list
 * (Structures_LinkedList_Single) knows the the next node in the list.
 * Unlike an array, you can insert or delete nodes at arbitrary points
 * in the list.
 *
 * If your application normally traverses the linked list in a forward-only
 * direction, use the singly-linked list implemented by
 * {@link Structures_LinkedList_Single}. If, however, your application
 * needs to traverse the list backwards, or insert nodes into the list before
 * other nodes in the list, use the double-linked list implemented by
 * {@link Structures_LinkedList_Double} to give your application better
 * performance at the cost of a slightly larger memory footprint.
 *
 * Structures_LinkedList_Single implements the Iterator interface so control
 * structures like foreach($list as $node) and while($list->next()) work
 * as expected.
 *
 * To use this package, derive a child class from
 * Structures_LinkedList_SingleNode and add data to the object. Then use the
 * Structures_LinkedList_Single class to access the nodes.
 *
 * PHP version 5
 *
 * LICENSE:  Copyright 2006 Dan Scott
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may obtain
 * a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @category  Structures
 * @package   Structures_LinkedList_Single
 * @author    Dan Scott <dscott@laurentian.ca>
 * @copyright 2006 Dan Scott
 * @license   http://www.apache.org/licenses/LICENSE-2.0  Apache License, Version 2.0
 * @version   CVS: $Id: Single.php -1   $
 * @link      http://pear.php.net/package/Structures_LinkedList_Single
 * @example   single_link_example.php
 *
 * @todo Add some actual error conditions
 **/

require_once 'PEAR/Exception.php';

// {{{ class Structures_LinkedList_Single
/**
 * The Structures_LinkedList_Single class represents a linked list structure
 * composed of {@link Structures_LinkedList_SingleNode} objects.
 *
 * @category Structures
 * @package  Structures_LinkedList_Single
 * @author   Dan Scott <dscott@laurentian.ca>
 * @license  http://www.apache.org/licenses/LICENSE-2.0  Apache License, Version 2.0
 * @link     http://pear.php.net/package/Structures_LinkedList_Single
 */
class Structures_LinkedList_Single implements Iterator
{
    // {{{ properties
    /**
     * Current node in the linked list
     * @var Structures_LinkedList_SingleNode
     */
    protected $current;

    /**
     * Root node of the linked list
     * @var Structures_LinkedList_SingleNode
     */
    protected $root_node;

    /**
     * The linked list contains no nodes
     */
    const ERROR_EMPTY = -1;

    public static $messages = array(
        self::ERROR_EMPTY => 'No nodes in this linked list' 
    );
    // }}}

    // {{{ Constructor: function __construct()
    /**
     * Structures_LinkedList_Single constructor
     *
     * @param Structures_LinkedList_SingleNode $root root node for the
     * linked list
     */
    function __construct(Structures_LinkedList_SingleNode $root = null)
    {
        if ($root) {
            $this->root_node = $root;
            $this->current = $root;
        } else {
            $this->root_node = null;
            $this->current = null;
        }
    }
    // }}}

    // {{{ Destructor: function __destruct()
    /**
     * Structures_LinkedList_Single destructor
     *
     * If we do not destroy all of the references in the linked list,
     * we will quickly run out of memory for large / complex structures.
     *
     */
    function __destruct()
    {
        /*
         * Starting with root node, set last node = root_node
         *   get next node
         *   if next node exists, delete last node reference to next node
         */
        if (!$last_node = $this->root_node) {
            return;
        }
        while (($next_node = $last_node->next()) !== false) {
            $last_node->setNext(null);
            $temp_node = $last_node;
            $last_node = $next_node;
            unset($temp_node);
        }
        $this->current = null;
        $this->root_node = null;
        $last_node = null;
        $next_node = null;
    }
    // }}}

    // {{{ function current()
    /**
     * Returns the current node in the linked list
     *
     * @return Structures_LinkedList_SingleNode current node in the linked list
     */
    public function current()
    {
        return $this->current;
    }
    // }}}

    // {{{ function rewind()
    /**
     * Sets the pointer for the linked list to the root node
     *
     * @return Structures_LinkedList_SingleNode root node in the linked list
     */
    public function rewind()
    {
        if ($this->root_node) {
            $this->current = $this->root_node;
        } else {
            $this->current = null;
        }
        return $this->current;
    }
    // }}}

    // {{{ function end()
    /**
     * Sets the pointer for the linked list to the root node
     *
     * @return Structures_LinkedList_SingleNode root node in the linked list
     */
    public function end()
    {
        $this->current = $this->getTailNode();
        return $this->current;
    }
    // }}}

    // {{{ function key()
    /**
     * Stub for Iterator interface that simply returns the current node
     *
     * @return Structures_LinkedList_SingleNode current node in the linked list
     */
    public function key()
    {
        return $this->current;
    }
    // }}}

    // {{{ function valid()
    /**
     * Stub for Iterator interface that simply returns the current node
     *
     * @return Structures_LinkedList_SingleNode current node in the linked list
     */
    public function valid()
    {
        return $this->current();
    }
    // }}}

    // {{{ function next()
    /**
     * Sets the pointer for the linked list to the next node and
     * returns that node
     *
     * @return Structures_LinkedList_SingleNode next node in the linked list
     */
    public function next()
    {
        if (!$this->current) {
            return false;
        }
        $this->current = $this->current()->next();
        return $this->current;
    }
    // }}}

    // {{{ function previous()
    /**
     * Sets the pointer for the linked list to the previous node and
     * returns that node
     *
     * @return Structures_LinkedList_SingleNode previous node in the linked list
     */
    public function previous()
    {
        if (!$this->current) {
            return false;
        }
        $this->current = $this->_getPreviousNode();
        return $this->current;
    }
    // }}}

    // {{{ protected function getTailNode()
    /**
     * Returns the tail node of the linked list.
     *
     * This is an expensive operation!
     *
     * @return bool Success or failure
     **/
    protected function getTailNode()
    {
        $tail_node = $this->root_node;
        while (($y = $tail_node->next()) !== false) {
            $tail_node = $y;
        }
        return $tail_node;
    }
    // }}}

    // {{{ private function _getPreviousNode()
    /**
     * Returns the node prior to the current node in the linked list.
     *
     * This is an expensive operation for a singly linked list!
     *
     * @param Structures_LinkedList_SingleNode $node (Optional) Specific node 
     * for which we want to find the previous node
     *
     * @return Structures_LinkedList_SingleNode Previous node
     **/
    private function _getPreviousNode($node = null)
    {
        if (!$node) {
            $node = $this->current;
        }
        $prior_node = $this->root_node;
        while (($y = $prior_node->next()) !== false) {
            if ($y == $node) {
                return $prior_node;
            }
            $prior_node = $y;
        }
        return null;
    }
    // }}}

    // {{{ function appendNode()
    /**
     * Adds a {@link Structures_LinkedList_SingleNode} object to the end of
     * the linked list.
     *
     * @param Structures_LinkedList_SingleNode $new_node New node to append
     *
     * @return bool Success or failure
     **/
    public function appendNode(Structures_LinkedList_SingleNode $new_node)
    {
        if (!$this->root_node) {
            $this->__construct($new_node);
            return true;
        }

        // This is just a special case of insertNode()
        $this->insertNode($new_node, $this->getTailNode());

        return true;
    }
    // }}}

    // {{{ function insertNode()
    /**
     * Inserts a {@link Structures_LinkedList_SingleNode} object into the linked
     * list, based on a reference node that already exists in the list.
     *
     * @param Structures_LinkedList_SingleNode $new_node      New node to add to
     * the list
     * @param Structures_LinkedList_SingleNode $existing_node Reference
     * position node
     * @param bool                             $before        Insert new node
     * before or after the existing node
     *
     * @return bool Success or failure
     **/
    public function insertNode($new_node, $existing_node, $before = false)
    {
        if (!$this->root_node) {
            $this->__construct($new_node);
            return true;
        }

        // Now add the node according to the requested mode
        switch ($before) {

        case true:
            if ($existing_node === $this->root_node) {
                $this->root_node = $new_node;
            }
            $previous_node = $this->_getPreviousNode($existing_node);
            if ($previous_node) {
                $previous_node->setNext($new_node);
            }
            $new_node->setNext($existing_node);

            break;

        case false:
            $next_node = $existing_node->next();
            if ($next_node) {
                $new_node->setNext($next_node);
            }
            $existing_node->setNext($new_node);

            break;

        }

        return true;
    }
    // }}}

    // {{{ function prependNode()
    /**
     * Adds a {@link Structures_LinkedList_SingleNode} object to the start
     * of the linked list.
     *
     * @param Structures_LinkedList_SingleNode $new_node Node to prepend
     * to the list
     *
     * @return bool Success or failure
     **/
    public function prependNode(Structures_LinkedList_SingleNode $new_node)
    {
        if (!$this->root_node) {
            $this->__construct($new_node);
            return true;
        }

        // This is just a special case of insertNode()
        $this->insertNode($new_node, $this->root_node, true);

        return true;
    }
    // }}}

    // {{{ function deleteNode()
    /**
     * Deletes a {@link Structures_LinkedList_SingleNode} from the list.
     *
     * @param Structures_LinkedList_SingleNode $node Node to delete.
     *
     * @return null
     */
    public function deleteNode($node)
    {
        /* If this is the root node, and there are more nodes in the list,
         * make the next node the new root node before deleting this node.
         */
        if ($node === $this->root_node) {
            $this->root_node = $node->next();
        }
        
        /* If this is the current node, make the next node the current node.
         *
         * If that fails, null isn't such a bad place to be.
         */
        if ($node === $this->current) {
            if ($node->next()) {
                $this->current = $node->next();
            } else {
                $this->current = null;
            }
        }
        $node->__destruct();
    }
    // }}}

}
// }}}

// {{{ class Structures_LinkedList_SingleNode
/**
 * The Structures_LinkedList_SingleNode class represents a node in a
 * {@link Structures_LinkedList_Single} linked list structure.
 *
 * @category Structures
 * @package  Structures_LinkedList_Single
 * @author   Dan Scott <dscott@laurentian.ca>
 * @license  http://www.apache.org/licenses/LICENSE-2.0  Apache License, Version 2.0
 * @link     http://pear.php.net/package/Structures_LinkedList_Single
 */
class Structures_LinkedList_SingleNode
{
    // {{{ properties
    /**
     * Next node in the linked list
     * @var Structures_LinkedList_SingleNode
     */
    protected $next;
    // }}}

    // {{{ Constructor: function __construct()
    /**
     * Structures_LinkedList_SingleNode constructor
     */
    public function __construct()
    {
        $this->next = null;
    }
    // }}}

    // {{{ Destructor: function __destruct()
    /**
     * Removes node from the list, adjusting the related nodes accordingly.
     *
     * This is a problem if the node is the root node for the list.
     * At this point, however, we do not have access to the list itself. Hmm.
     */
    public function __destruct()
    {
    }
    // }}}

    // {{{ function next()
    /**
     * Return the next node in the linked list
     *
     * @return Structures_LinkedList_SingleNode next node in the linked list
     */
    public function next()
    {
        if ($this->next) {
            return $this->next;
        } else {
            return false;
        }
    }
    // }}}

    // {{{ function previous()
    /**
     * Return the previous node in the linked list
     *
     * Stub method for Structures_LinkedList_DoubleNode to override.
     *
     * @return Structures_LinkedList_SingleNode previous node in the linked list
     */
    public function previous()
    {
        return false;
    }
    // }}}

    // {{{ function setNext()
    /**
     * Sets the pointer for the next node in the linked list to the
     * specified node
     *
     * @param Structures_LinkedList_SingleNode $node new next node in
     * the linked list
     *
     * @return Structures_LinkedList_SingleNode new next node in the linked list
     */
    public function setNext($node = null)
    {
        $this->next = $node;
        return $this->next;
    }
    // }}}

    // {{{ function setPrevious()
    /**
     * Sets the pointer for the next node in the linked list to the
     * specified node
     *
     * Stub method for Structures_LinkedList_DoubleNode to override.
     *
     * @param Structures_LinkedList_SingleNode $node new next node in
     * the linked list
     *
     * @return Structures_LinkedList_SingleNode new next node in the linked list
     */
    public function setPrevious($node = null)
    {
        return false;
    }
    // }}}
}

// }}}

?>
PKn�ZUyv�Structures/Graph.phpnu�[���<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
// +-----------------------------------------------------------------------------+
// | Copyright (c) 2003 S�rgio Gon�alves Carvalho                                |
// +-----------------------------------------------------------------------------+
// | This file is part of Structures_Graph.                                      |
// |                                                                             |
// | Structures_Graph is free software; you can redistribute it and/or modify    |
// | it under the terms of the GNU Lesser General Public License as published by |
// | the Free Software Foundation; either version 2.1 of the License, or         |
// | (at your option) any later version.                                         |
// |                                                                             |
// | Structures_Graph is distributed in the hope that it will be useful,         |
// | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
// | GNU Lesser General Public License for more details.                         |
// |                                                                             |
// | You should have received a copy of the GNU Lesser General Public License    |
// | along with Structures_Graph; if not, write to the Free Software             |
// | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA                    |
// | 02111-1307 USA                                                              |
// +-----------------------------------------------------------------------------+
// | Author: S�rgio Carvalho <sergio.carvalho@portugalmail.com>                  |
// +-----------------------------------------------------------------------------+
//
/**
 * The Graph.php file contains the definition of the Structures_Graph class 
 *
 * @package Structures_Graph
 */

/* dependencies {{{ */
require_once 'PEAR.php';
require_once 'Structures/Graph/Node.php';
/* }}} */

define('STRUCTURES_GRAPH_ERROR_GENERIC', 100);

/* class Structures_Graph {{{ */
/**
 * The Structures_Graph class represents a graph data structure. 
 *
 * A Graph is a data structure composed by a set of nodes, connected by arcs.
 * Graphs may either be directed or undirected. In a directed graph, arcs are 
 * directional, and can be traveled only one way. In an undirected graph, arcs
 * are bidirectional, and can be traveled both ways.
 *
 * @author    S�rgio Carvalho <sergio.carvalho@portugalmail.com> 
 * @copyright (c) 2004 by S�rgio Carvalho
 * @package   Structures_Graph
 */
/* }}} */
class Structures_Graph
{
    /**
     * List of node objects in this graph
     * @access private
     */
    var $_nodes = array();

    /**
     * If the graph is directed or not
     * @access private
     */
    var $_directed = false;


    /**
     * Constructor
     *
     * @param boolean $directed Set to true if the graph is directed.
     *                          Set to false if it is not directed.
     */
    public function __construct($directed = true)
    {
        $this->_directed = $directed;
    }

    /**
     * Old constructor (PHP4-style; kept for BC with extending classes)
     *
     * @param boolean $directed Set to true if the graph is directed.
     *                          Set to false if it is not directed.
     *
     * @return void
     */
    public function Structures_Graph($directed = true)
    {
        $this->__construct($directed);
    }

    /**
     * Return true if a graph is directed
     *
     * @return boolean true if the graph is directed
     */
    public function isDirected()
    {
        return (boolean) $this->_directed;
    }

    /**
     * Add a Node to the Graph
     *
     * @param Structures_Graph_Node $newNode The node to be added.
     *
     * @return void
     */
    public function addNode(&$newNode)
    {
        // We only add nodes
        if (!is_a($newNode, 'Structures_Graph_Node')) {
            return Pear::raiseError(
                'Structures_Graph::addNode received an object that is not'
                . ' a Structures_Graph_Node',
                STRUCTURES_GRAPH_ERROR_GENERIC
            );
        }

        //Graphs are node *sets*, so duplicates are forbidden.
        // We allow nodes that are exactly equal, but disallow equal references.
        foreach ($this->_nodes as $key => $node) {
            /*
             ZE1 equality operators choke on the recursive cycle introduced
             by the _graph field in the Node object.
             So, we'll check references the hard way
             (change $this->_nodes[$key] and check if the change reflects in
             $node)
            */
            $savedData = $this->_nodes[$key];
            $referenceIsEqualFlag = false;
            $this->_nodes[$key] = true;
            if ($node === true) {
                $this->_nodes[$key] = false;
                if ($node === false) {
                    $referenceIsEqualFlag = true;
                }
            }
            $this->_nodes[$key] = $savedData;
            if ($referenceIsEqualFlag) {
                return Pear::raiseError(
                    'Structures_Graph::addNode received an object that is'
                    . ' a duplicate for this dataset',
                    STRUCTURES_GRAPH_ERROR_GENERIC
                );
            }
        }
        $this->_nodes[] =& $newNode;
        $newNode->setGraph($this);
    }

    /**
     * Remove a Node from the Graph
     *
     * @param Structures_Graph_Node $node The node to be removed from the graph
     *
     * @return void
     * @todo   This is unimplemented
     */
    public function removeNode(&$node)
    {
    }

    /**
     * Return the node set, in no particular order.
     * For ordered node sets, use a Graph Manipulator insted.
     *
     * @return array The set of nodes in this graph
     * @see    Structures_Graph_Manipulator_TopologicalSorter
     */
    public function &getNodes()
    {
        return $this->_nodes;
    }
}
?>
PKn�Z�C� + +Structures/Graph/Node.phpnu�[���<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
// +-----------------------------------------------------------------------------+
// | Copyright (c) 2003 S�rgio Gon�alves Carvalho                                |
// +-----------------------------------------------------------------------------+
// | This file is part of Structures_Graph.                                      |
// |                                                                             |
// | Structures_Graph is free software; you can redistribute it and/or modify    |
// | it under the terms of the GNU Lesser General Public License as published by |
// | the Free Software Foundation; either version 2.1 of the License, or         |
// | (at your option) any later version.                                         |
// |                                                                             |
// | Structures_Graph is distributed in the hope that it will be useful,         |
// | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
// | GNU Lesser General Public License for more details.                         |
// |                                                                             |
// | You should have received a copy of the GNU Lesser General Public License    |
// | along with Structures_Graph; if not, write to the Free Software             |
// | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA                    |
// | 02111-1307 USA                                                              |
// +-----------------------------------------------------------------------------+
// | Author: S�rgio Carvalho <sergio.carvalho@portugalmail.com>                  |
// +-----------------------------------------------------------------------------+
//
/**
 * This file contains the definition of the Structures_Graph_Node class
 * 
 * @see Structures_Graph_Node
 * @package Structures_Graph
 */

/* dependencies {{{ */
/** */
require_once 'PEAR.php';
/** */
require_once 'Structures/Graph.php';
/* }}} */

/* class Structures_Graph_Node {{{ */
/**
 * The Structures_Graph_Node class represents a Node that can be member of a 
 * graph node set.
 *
 * A graph node can contain data. Under this API, the node contains default data, 
 * and key index data. It behaves, thus, both as a regular data node, and as a 
 * dictionary (or associative array) node.
 * 
 * Regular data is accessed via getData and setData. Key indexed data is accessed
 * via getMetadata and setMetadata.
 *
 * @author		S�rgio Carvalho <sergio.carvalho@portugalmail.com> 
 * @copyright	(c) 2004 by S�rgio Carvalho
 * @package Structures_Graph
 */
/* }}} */
class Structures_Graph_Node {
    /* fields {{{ */
    /** 
     * @access private 
     */
    var $_data = null;
    /** @access private */
    var $_metadata = array();
    /** @access private */
    var $_arcs = array();
    /** @access private */
    var $_graph = null;
    /* }}} */

    /* Constructor {{{ */
    /**
    *
    * Constructor
    *
    * @access	public
    */
    function __construct() {
    }
    /* }}} */

    /* getGraph {{{ */
    /**
    *
    * Node graph getter
    *
    * @return	Structures_Graph	Graph where node is stored
    * @access	public
    */
    function &getGraph() {
        return $this->_graph;
    }
    /* }}} */

    /* setGraph {{{ */
    /**
    *
    * Node graph setter. This method should not be called directly. Use Graph::addNode instead.
    *
    * @param    Structures_Graph   Set the graph for this node. 
    * @see      Structures_Graph::addNode()
    * @access	public
    */
    function setGraph(&$graph) {
        $this->_graph =& $graph;
    }
    /* }}} */

    /* getData {{{ */
    /**
    *
    * Node data getter.
    * 
    * Each graph node can contain a reference to one variable. This is the getter for that reference.
    *
    * @return	mixed	Data stored in node
    * @access	public
    */
    function &getData() {
        return $this->_data;
    }
    /* }}} */

    /* setData {{{ */
    /**
    *
    * Node data setter
    *
    * Each graph node can contain a reference to one variable. This is the setter for that reference.
    *
    * @return	mixed	Data to store in node
    * @access	public
    */
    function setData(&$data) {
        $this->_data =& $data;
    }
    /* }}} */

    /* metadataKeyExists {{{ */
    /**
    *
    * Test for existence of metadata under a given key.
    *
    * Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an 
    * associative array or in a dictionary. This method tests whether a given metadata key exists for this node.
    *
    * @param    string    Key to test
    * @return	boolean	 
    * @access	public
    */
    function metadataKeyExists($key) {
        return array_key_exists($key, $this->_metadata);
    }
    /* }}} */

    /* getMetadata {{{ */
    /**
    *
    * Node metadata getter
    *
    * Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an 
    * associative array or in a dictionary. This method gets the data under the given key. If the key does
    * not exist, an error will be thrown, so testing using metadataKeyExists might be needed.
    *
    * @param    string  Key
    * @param    boolean nullIfNonexistent (defaults to false).
    * @return	mixed	Metadata Data stored in node under given key
    * @see      metadataKeyExists
    * @access	public
    */
    function &getMetadata($key, $nullIfNonexistent = false) {
        if (array_key_exists($key, $this->_metadata)) {
            return $this->_metadata[$key];
        } else {
            if ($nullIfNonexistent) {
                $a = null;
                return $a;
            } else {
                $a = Pear::raiseError('Structures_Graph_Node::getMetadata: Requested key does not exist', STRUCTURES_GRAPH_ERROR_GENERIC);
                return $a;
            }
        }
    }
    /* }}} */

    /* unsetMetadata {{{ */
    /**
    *
    * Delete metadata by key
    *
    * Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an 
    * associative array or in a dictionary. This method removes any data that might be stored under the provided key.
    * If the key does not exist, no error is thrown, so it is safe using this method without testing for key existence.
    *
    * @param    string  Key
    * @access	public
    */
    function unsetMetadata($key) {
        if (array_key_exists($key, $this->_metadata)) unset($this->_metadata[$key]);
    }
    /* }}} */

    /* setMetadata {{{ */
    /**
    *
    * Node metadata setter
    *
    * Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an 
    * associative array or in a dictionary. This method stores data under the given key. If the key already exists,
    * previously stored data is discarded.
    *
    * @param    string  Key
    * @param    mixed   Data 
    * @access	public
    */
    function setMetadata($key, &$data) {
        $this->_metadata[$key] =& $data;
    }
    /* }}} */

    /* _connectTo {{{ */
    /** @access private */
    function _connectTo(&$destinationNode) {
        $this->_arcs[] =& $destinationNode;
    }
    /* }}} */

    /* connectTo {{{ */
    /**
    *
    * Connect this node to another one.
    * 
    * If the graph is not directed, the reverse arc, connecting $destinationNode to $this is also created.
    *
    * @param    Structures_Graph_Node Node to connect to
    * @access	public
    */
    function connectTo(&$destinationNode) {
        // We only connect to nodes
        if (!is_a($destinationNode, 'Structures_Graph_Node')) return Pear::raiseError('Structures_Graph_Node::connectTo received an object that is not a Structures_Graph_Node', STRUCTURES_GRAPH_ERROR_GENERIC);
        // Nodes must already be in graphs to be connected
        if ($this->_graph == null) return Pear::raiseError('Structures_Graph_Node::connectTo Tried to connect a node that is not in a graph', STRUCTURES_GRAPH_ERROR_GENERIC);
        if ($destinationNode->getGraph() == null) return Pear::raiseError('Structures_Graph_Node::connectTo Tried to connect to a node that is not in a graph', STRUCTURES_GRAPH_ERROR_GENERIC);
        // Connect here
        $this->_connectTo($destinationNode);
        // If graph is undirected, connect back
        if (!$this->_graph->isDirected()) {
            $destinationNode->_connectTo($this);
        }
    }
    /* }}} */

    /* getNeighbours {{{ */
    /**
    *
    * Return nodes connected to this one.
    * 
    * @return   array   Array of nodes
    * @access	public
    */
    function getNeighbours() {
        return $this->_arcs;
    }
    /* }}} */

    /* connectsTo {{{ */
    /**
    *
    * Test wether this node has an arc to the target node
    *
    * @return	boolean   True if the two nodes are connected
    * @access	public
    */
    function connectsTo(&$target) {
        if (version_compare(PHP_VERSION, '5.0.0') >= 0) {
            return in_array($target, $this->getNeighbours(), true);
        }

        $copy = $target;
        $arcKeys = array_keys($this->_arcs);
        foreach($arcKeys as $key) {
            /* ZE1 chokes on this expression:
                if ($target === $arc) return true;
              so, we'll use more convoluted stuff
            */
            $arc =& $this->_arcs[$key];
            $target = true;
            if ($arc === true) {
                $target = false;
                if ($arc === false) {
                    $target = $copy;
                    return true;
                }
            }
        }
        $target = $copy;
        return false;
    }
    /* }}} */

    /* inDegree {{{ */
    /**
    *
    * Calculate the in degree of the node.
    * 
    * The indegree for a node is the number of arcs entering the node. For non directed graphs, 
    * the indegree is equal to the outdegree.
    *
    * @return	integer	 In degree of the node
    * @access	public
    */
    function inDegree() {
        if ($this->_graph == null) return 0;
        if (!$this->_graph->isDirected()) return $this->outDegree();
        $result = 0;
        $graphNodes =& $this->_graph->getNodes();
        foreach (array_keys($graphNodes) as $key) {
            if ($graphNodes[$key]->connectsTo($this)) $result++;
        }
        return $result;
        
    }
    /* }}} */

    /* outDegree {{{ */
    /**
    *
    * Calculate the out degree of the node.
    *
    * The outdegree for a node is the number of arcs exiting the node. For non directed graphs,
    * the outdegree is always equal to the indegree.
    * 
    * @return	integer	 Out degree of the node
    * @access	public
    */
    function outDegree() {
        if ($this->_graph == null) return 0;
        return sizeof($this->_arcs);
    }
    /* }}} */
}
?>
PKn�Z9����,Structures/Graph/Manipulator/AcyclicTest.phpnu�[���<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
// +-----------------------------------------------------------------------------+
// | Copyright (c) 2003 S�rgio Gon�alves Carvalho                                |
// +-----------------------------------------------------------------------------+
// | This file is part of Structures_Graph.                                      |
// |                                                                             |
// | Structures_Graph is free software; you can redistribute it and/or modify    |
// | it under the terms of the GNU Lesser General Public License as published by |
// | the Free Software Foundation; either version 2.1 of the License, or         |
// | (at your option) any later version.                                         |
// |                                                                             |
// | Structures_Graph is distributed in the hope that it will be useful,         |
// | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
// | GNU Lesser General Public License for more details.                         |
// |                                                                             |
// | You should have received a copy of the GNU Lesser General Public License    |
// | along with Structures_Graph; if not, write to the Free Software             |
// | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA                    |
// | 02111-1307 USA                                                              |
// +-----------------------------------------------------------------------------+
// | Author: S�rgio Carvalho <sergio.carvalho@portugalmail.com>                  |
// +-----------------------------------------------------------------------------+
//
/**
 * This file contains the definition of the Structures_Graph_Manipulator_AcyclicTest graph manipulator.
 * 
 * @see Structures_Graph_Manipulator_AcyclicTest
 * @package Structures_Graph
 */

/* dependencies {{{ */
/** */
require_once 'PEAR.php';
/** */
require_once 'Structures/Graph.php';
/** */
require_once 'Structures/Graph/Node.php';
/* }}} */

/* class Structures_Graph_Manipulator_AcyclicTest {{{ */
/**
 * The Structures_Graph_Manipulator_AcyclicTest is a graph manipulator
 * which tests whether a graph contains a cycle. 
 * 
 * The definition of an acyclic graph used in this manipulator is that of a 
 * DAG. The graph must be directed, or else it is considered cyclic, even when 
 * there are no arcs.
 *
 * @author		S�rgio Carvalho <sergio.carvalho@portugalmail.com> 
 * @copyright	(c) 2004 by S�rgio Carvalho
 * @package Structures_Graph
 */
class Structures_Graph_Manipulator_AcyclicTest {
    /* _nonVisitedInDegree {{{ */
    /**
    *
    * This is a variant of Structures_Graph::inDegree which does 
    * not count nodes marked as visited.
    *
    * @return	integer	 Number of non-visited nodes that link to this one
    */
    protected static function _nonVisitedInDegree(&$node) {
        $result = 0;
        $graphNodes =& $node->_graph->getNodes();
        foreach (array_keys($graphNodes) as $key) {
            if ((!$graphNodes[$key]->getMetadata('acyclic-test-visited')) && $graphNodes[$key]->connectsTo($node)) $result++;
        }
        return $result;
        
    }
    /* }}} */

    /* _isAcyclic {{{ */
    /**
     * Check if the graph is acyclic
     */
    protected static function _isAcyclic(&$graph) {
        // Mark every node as not visited
        $nodes =& $graph->getNodes();
        $nodeKeys = array_keys($nodes);
        $refGenerator = array();
        foreach($nodeKeys as $key) {
            $refGenerator[] = false;
            $nodes[$key]->setMetadata('acyclic-test-visited', $refGenerator[sizeof($refGenerator) - 1]);
        }

        // Iteratively peel off leaf nodes
        do {
            // Find out which nodes are leafs (excluding visited nodes)
            $leafNodes = array();
            foreach($nodeKeys as $key) {
                if ((!$nodes[$key]->getMetadata('acyclic-test-visited')) && Structures_Graph_Manipulator_AcyclicTest::_nonVisitedInDegree($nodes[$key]) == 0) {
                    $leafNodes[] =& $nodes[$key];
                }
            }
            // Mark leafs as visited
            for ($i=sizeof($leafNodes) - 1; $i>=0; $i--) {
                $visited =& $leafNodes[$i]->getMetadata('acyclic-test-visited');
                $visited = true;
                $leafNodes[$i]->setMetadata('acyclic-test-visited', $visited);
            }
        } while (sizeof($leafNodes) > 0);

        // If graph is a DAG, there should be no non-visited nodes. Let's try to prove otherwise
        $result = true;
        foreach($nodeKeys as $key) if (!$nodes[$key]->getMetadata('acyclic-test-visited')) $result = false;
        
        // Cleanup visited marks
        foreach($nodeKeys as $key) $nodes[$key]->unsetMetadata('acyclic-test-visited');

        return $result;
    }
    /* }}} */

    /* isAcyclic {{{ */
    /**
    *
    * isAcyclic returns true if a graph contains no cycles, false otherwise.
    *
    * @return	boolean	 true iff graph is acyclic
    */
    public static function isAcyclic(&$graph) {
        // We only test graphs
        if (!is_a($graph, 'Structures_Graph')) return Pear::raiseError('Structures_Graph_Manipulator_AcyclicTest::isAcyclic received an object that is not a Structures_Graph', STRUCTURES_GRAPH_ERROR_GENERIC);
        if (!$graph->isDirected()) return false; // Only directed graphs may be acyclic

        return Structures_Graph_Manipulator_AcyclicTest::_isAcyclic($graph);
    }
    /* }}} */
}
/* }}} */
?>
PKn�Z~(�htt2Structures/Graph/Manipulator/TopologicalSorter.phpnu�[���<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
// +-----------------------------------------------------------------------------+
// | Copyright (c) 2003 S�rgio Gon�alves Carvalho                                |
// +-----------------------------------------------------------------------------+
// | This file is part of Structures_Graph.                                      |
// |                                                                             |
// | Structures_Graph is free software; you can redistribute it and/or modify    |
// | it under the terms of the GNU Lesser General Public License as published by |
// | the Free Software Foundation; either version 2.1 of the License, or         |
// | (at your option) any later version.                                         |
// |                                                                             |
// | Structures_Graph is distributed in the hope that it will be useful,         |
// | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
// | GNU Lesser General Public License for more details.                         |
// |                                                                             |
// | You should have received a copy of the GNU Lesser General Public License    |
// | along with Structures_Graph; if not, write to the Free Software             |
// | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA                    |
// | 02111-1307 USA                                                              |
// +-----------------------------------------------------------------------------+
// | Author: S�rgio Carvalho <sergio.carvalho@portugalmail.com>                  |
// +-----------------------------------------------------------------------------+
//
/**
 * This file contains the definition of the Structures_Graph_Manipulator_TopologicalSorter class.
 * 
 * @package Structures_Graph
 */

require_once 'PEAR.php';
require_once 'Structures/Graph.php';
require_once 'Structures/Graph/Node.php';
require_once 'Structures/Graph/Manipulator/AcyclicTest.php';

/**
 * The Structures_Graph_Manipulator_TopologicalSorter is a manipulator 
 * which is able to return the set of nodes in a graph, sorted by topological 
 * order.
 *
 * A graph may only be sorted topologically iff it's a DAG. You can test it
 * with the Structures_Graph_Manipulator_AcyclicTest.
 * 
 * @author    S�rgio Carvalho <sergio.carvalho@portugalmail.com> 
 * @copyright (c) 2004 by S�rgio Carvalho
 * @see       Structures_Graph_Manipulator_AcyclicTest
 * @package   Structures_Graph
 */
class Structures_Graph_Manipulator_TopologicalSorter
{
    /**
     * This is a variant of Structures_Graph::inDegree which does 
     * not count nodes marked as visited.
     *
     * @param object $node Node to check
     *
     * @return integer Number of non-visited nodes that link to this one
     */
    protected static function _nonVisitedInDegree(&$node)
    {
        $result = 0;
        $graphNodes =& $node->_graph->getNodes();
        foreach (array_keys($graphNodes) as $key) {
            if ((!$graphNodes[$key]->getMetadata('topological-sort-visited'))
                && $graphNodes[$key]->connectsTo($node)
            ) {
                $result++;
            }
        }
        return $result;
        
    }

    /**
     * Sort implementation
     *
     * @param object $graph Graph to sort
     *
     * @return void
     */
    protected static function _sort(&$graph)
    {
        // Mark every node as not visited
        $nodes =& $graph->getNodes();
        $nodeKeys = array_keys($nodes);
        $refGenerator = array();
        foreach ($nodeKeys as $key) {
            $refGenerator[] = false;
            $nodes[$key]->setMetadata(
                'topological-sort-visited',
                $refGenerator[sizeof($refGenerator) - 1]
            );
        }

        // Iteratively peel off leaf nodes
        $topologicalLevel = 0;
        do {
            // Find out which nodes are leafs (excluding visited nodes)
            $leafNodes = array();
            foreach ($nodeKeys as $key) {
                if ((!$nodes[$key]->getMetadata('topological-sort-visited'))
                    && static::_nonVisitedInDegree($nodes[$key]) == 0
                ) {
                    $leafNodes[] =& $nodes[$key];
                }
            }
            // Mark leafs as visited
            $refGenerator[] = $topologicalLevel;
            for ($i = sizeof($leafNodes) - 1; $i>=0; $i--) {
                $visited =& $leafNodes[$i]->getMetadata('topological-sort-visited');
                $visited = true;
                $leafNodes[$i]->setMetadata('topological-sort-visited', $visited);
                $leafNodes[$i]->setMetadata(
                    'topological-sort-level',
                    $refGenerator[sizeof($refGenerator) - 1]
                );
            }
            $topologicalLevel++;
        } while (sizeof($leafNodes) > 0);

        // Cleanup visited marks
        foreach ($nodeKeys as $key) {
            $nodes[$key]->unsetMetadata('topological-sort-visited');
        }
    }

    /**
     * Sort returns the graph's nodes, sorted by topological order. 
     * 
     * The result is an array with as many entries as topological levels.
     * Each entry in this array is an array of nodes within
     * the given topological level.
     *
     * @param object $graph Graph to sort
     *
     * @return array The graph's nodes, sorted by topological order.
     */
    public static function sort(&$graph)
    {
        // We only sort graphs
        if (!is_a($graph, 'Structures_Graph')) {
            return Pear::raiseError(
                'Structures_Graph_Manipulator_TopologicalSorter::sort received'
                . ' an object that is not a Structures_Graph',
                STRUCTURES_GRAPH_ERROR_GENERIC
            );
        }
        if (!Structures_Graph_Manipulator_AcyclicTest::isAcyclic($graph)) {
            return Pear::raiseError(
                'Structures_Graph_Manipulator_TopologicalSorter::sort'
                . ' received an graph that has cycles',
                STRUCTURES_GRAPH_ERROR_GENERIC
            );
        }

        Structures_Graph_Manipulator_TopologicalSorter::_sort($graph);
        $result = array();

        // Fill out result array
        $nodes =& $graph->getNodes();
        $nodeKeys = array_keys($nodes);
        foreach ($nodeKeys as $key) {
            if (!array_key_exists($nodes[$key]->getMetadata('topological-sort-level'), $result)) {
                $result[$nodes[$key]->getMetadata('topological-sort-level')]
                    = array();
            }
            $result[$nodes[$key]->getMetadata('topological-sort-level')][]
                =& $nodes[$key];
            $nodes[$key]->unsetMetadata('topological-sort-level');
        }

        return $result;
    }
}
?>
PKn�Z�J�}
}
Auth/SASL/Anonymous.phpnu�[���<?php
// +-----------------------------------------------------------------------+ 
// | Copyright (c) 2002-2003 Richard Heyes                                 | 
// | All rights reserved.                                                  | 
// |                                                                       | 
// | Redistribution and use in source and binary forms, with or without    | 
// | modification, are permitted provided that the following conditions    | 
// | are met:                                                              | 
// |                                                                       | 
// | o Redistributions of source code must retain the above copyright      | 
// |   notice, this list of conditions and the following disclaimer.       | 
// | o Redistributions in binary form must reproduce the above copyright   | 
// |   notice, this list of conditions and the following disclaimer in the | 
// |   documentation and/or other materials provided with the distribution.| 
// | o The names of the authors may not be used to endorse or promote      | 
// |   products derived from this software without specific prior written  | 
// |   permission.                                                         | 
// |                                                                       | 
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   | 
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     | 
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  | 
// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      | 
// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   | 
// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  | 
// |                                                                       | 
// +-----------------------------------------------------------------------+ 
// | Author: Richard Heyes <richard@php.net>                               | 
// +-----------------------------------------------------------------------+ 
// 
// $Id$

/**
* Implmentation of ANONYMOUS SASL mechanism
*
* @author  Richard Heyes <richard@php.net>
* @access  public
* @version 1.0
* @package Auth_SASL
*/

require_once('Auth/SASL/Common.php');

class Auth_SASL_Anonymous extends Auth_SASL_Common
{
    /**
    * Not much to do here except return the token supplied.
    * No encoding, hashing or encryption takes place for this
    * mechanism, simply one of:
    *  o An email address
    *  o An opaque string not containing "@" that can be interpreted
    *    by the sysadmin
    *  o Nothing
    *
    * We could have some logic here for the second option, but this
    * would by no means create something interpretable.
    *
    * @param  string $token Optional email address or string to provide
    *                       as trace information.
    * @return string        The unaltered input token
    */
    function getResponse($token = '')
    {
        return $token;
    }
}
?>PKn�ZP(~�T
T
Auth/SASL/CramMD5.phpnu�[���<?php
// +-----------------------------------------------------------------------+ 
// | Copyright (c) 2002-2003 Richard Heyes                                 | 
// | All rights reserved.                                                  | 
// |                                                                       | 
// | Redistribution and use in source and binary forms, with or without    | 
// | modification, are permitted provided that the following conditions    | 
// | are met:                                                              | 
// |                                                                       | 
// | o Redistributions of source code must retain the above copyright      | 
// |   notice, this list of conditions and the following disclaimer.       | 
// | o Redistributions in binary form must reproduce the above copyright   | 
// |   notice, this list of conditions and the following disclaimer in the | 
// |   documentation and/or other materials provided with the distribution.| 
// | o The names of the authors may not be used to endorse or promote      | 
// |   products derived from this software without specific prior written  | 
// |   permission.                                                         | 
// |                                                                       | 
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   | 
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     | 
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  | 
// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      | 
// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   | 
// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  | 
// |                                                                       | 
// +-----------------------------------------------------------------------+ 
// | Author: Richard Heyes <richard@php.net>                               | 
// +-----------------------------------------------------------------------+ 
// 
// $Id$

/**
* Implmentation of CRAM-MD5 SASL mechanism
*
* @author  Richard Heyes <richard@php.net>
* @access  public
* @version 1.0
* @package Auth_SASL
*/

require_once('Auth/SASL/Common.php');

class Auth_SASL_CramMD5 extends Auth_SASL_Common
{
    /**
    * Implements the CRAM-MD5 SASL mechanism
    * This DOES NOT base64 encode the return value,
    * you will need to do that yourself.
    *
    * @param string $user      Username
    * @param string $pass      Password
    * @param string $challenge The challenge supplied by the server.
    *                          this should be already base64_decoded.
    *
    * @return string The string to pass back to the server, of the form
    *                "<user> <digest>". This is NOT base64_encoded.
    */
    function getResponse($user, $pass, $challenge)
    {
        return $user . ' ' . $this->_HMAC_MD5($pass, $challenge);
    }
}
?>PKn�Z����==Auth/SASL/Plain.phpnu�[���<?php
// +-----------------------------------------------------------------------+ 
// | Copyright (c) 2002-2003 Richard Heyes                                 | 
// | All rights reserved.                                                  | 
// |                                                                       | 
// | Redistribution and use in source and binary forms, with or without    | 
// | modification, are permitted provided that the following conditions    | 
// | are met:                                                              | 
// |                                                                       | 
// | o Redistributions of source code must retain the above copyright      | 
// |   notice, this list of conditions and the following disclaimer.       | 
// | o Redistributions in binary form must reproduce the above copyright   | 
// |   notice, this list of conditions and the following disclaimer in the | 
// |   documentation and/or other materials provided with the distribution.| 
// | o The names of the authors may not be used to endorse or promote      | 
// |   products derived from this software without specific prior written  | 
// |   permission.                                                         | 
// |                                                                       | 
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   | 
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     | 
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  | 
// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      | 
// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   | 
// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  | 
// |                                                                       | 
// +-----------------------------------------------------------------------+ 
// | Author: Richard Heyes <richard@php.net>                               | 
// +-----------------------------------------------------------------------+ 
// 
// $Id$

/**
* Implmentation of PLAIN SASL mechanism
*
* @author  Richard Heyes <richard@php.net>
* @access  public
* @version 1.0
* @package Auth_SASL
*/

require_once('Auth/SASL/Common.php');

class Auth_SASL_Plain extends Auth_SASL_Common
{
    /**
    * Returns PLAIN response
    *
    * @param  string $authcid   Authentication id (username)
    * @param  string $pass      Password
    * @param  string $authzid   Autorization id
    * @return string            PLAIN Response
    */
    function getResponse($authcid, $pass, $authzid = '')
    {
        return $authzid . chr(0) . $authcid . chr(0) . $pass;
    }
}
?>
PKn�Z�<� OOAuth/SASL/Login.phpnu�[���<?php
// +-----------------------------------------------------------------------+ 
// | Copyright (c) 2002-2003 Richard Heyes                                 | 
// | All rights reserved.                                                  | 
// |                                                                       | 
// | Redistribution and use in source and binary forms, with or without    | 
// | modification, are permitted provided that the following conditions    | 
// | are met:                                                              | 
// |                                                                       | 
// | o Redistributions of source code must retain the above copyright      | 
// |   notice, this list of conditions and the following disclaimer.       | 
// | o Redistributions in binary form must reproduce the above copyright   | 
// |   notice, this list of conditions and the following disclaimer in the | 
// |   documentation and/or other materials provided with the distribution.| 
// | o The names of the authors may not be used to endorse or promote      | 
// |   products derived from this software without specific prior written  | 
// |   permission.                                                         | 
// |                                                                       | 
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   | 
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     | 
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  | 
// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      | 
// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   | 
// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  | 
// |                                                                       | 
// +-----------------------------------------------------------------------+ 
// | Author: Richard Heyes <richard@php.net>                               | 
// +-----------------------------------------------------------------------+ 
// 
// $Id$

/**
* This is technically not a SASL mechanism, however
* it's used by Net_Sieve, Net_Cyrus and potentially
* other protocols , so here is a good place to abstract
* it.
*
* @author  Richard Heyes <richard@php.net>
* @access  public
* @version 1.0
* @package Auth_SASL
*/

require_once('Auth/SASL/Common.php');

class Auth_SASL_Login extends Auth_SASL_Common
{
    /**
    * Pseudo SASL LOGIN mechanism
    *
    * @param  string $user Username
    * @param  string $pass Password
    * @return string       LOGIN string
    */
    function getResponse($user, $pass)
    {
        return sprintf('LOGIN %s %s', $user, $pass);
    }
}
?>PKn�Z%ׅtg!g!Auth/SASL/DigestMD5.phpnu�[���<?php
// +-----------------------------------------------------------------------+ 
// | Copyright (c) 2002-2003 Richard Heyes                                 | 
// | All rights reserved.                                                  | 
// |                                                                       | 
// | Redistribution and use in source and binary forms, with or without    | 
// | modification, are permitted provided that the following conditions    | 
// | are met:                                                              | 
// |                                                                       | 
// | o Redistributions of source code must retain the above copyright      | 
// |   notice, this list of conditions and the following disclaimer.       | 
// | o Redistributions in binary form must reproduce the above copyright   | 
// |   notice, this list of conditions and the following disclaimer in the | 
// |   documentation and/or other materials provided with the distribution.| 
// | o The names of the authors may not be used to endorse or promote      | 
// |   products derived from this software without specific prior written  | 
// |   permission.                                                         | 
// |                                                                       | 
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   | 
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     | 
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  | 
// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      | 
// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   | 
// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  | 
// |                                                                       | 
// +-----------------------------------------------------------------------+ 
// | Author: Richard Heyes <richard@php.net>                               | 
// +-----------------------------------------------------------------------+ 
// 
// $Id$

/**
* Implmentation of DIGEST-MD5 SASL mechanism
*
* @author  Richard Heyes <richard@php.net>
* @access  public
* @version 1.0
* @package Auth_SASL
*/

require_once('Auth/SASL/Common.php');

class Auth_SASL_DigestMD5 extends Auth_SASL_Common
{
    /**
    * Provides the (main) client response for DIGEST-MD5
    * requires a few extra parameters than the other
    * mechanisms, which are unavoidable.
    * 
    * @param  string $authcid   Authentication id (username)
    * @param  string $pass      Password
    * @param  string $challenge The digest challenge sent by the server
    * @param  string $hostname  The hostname of the machine you're connecting to
    * @param  string $service   The servicename (eg. imap, pop, acap etc)
    * @param  string $authzid   Authorization id (username to proxy as)
    * @return string            The digest response (NOT base64 encoded)
    * @access public
    */
    function getResponse($authcid, $pass, $challenge, $hostname, $service, $authzid = '')
    {
        $challenge = $this->_parseChallenge($challenge);
        $authzid_string = '';
        if ($authzid != '') {
            $authzid_string = ',authzid="' . $authzid . '"'; 
        }

        if (!empty($challenge)) {
            $cnonce         = $this->_getCnonce();
            $digest_uri     = sprintf('%s/%s', $service, $hostname);
            $response_value = $this->_getResponseValue($authcid, $pass, $challenge['realm'], $challenge['nonce'], $cnonce, $digest_uri, $authzid);

            if ($challenge['realm']) {
                return sprintf('username="%s",realm="%s"' . $authzid_string  .
',nonce="%s",cnonce="%s",nc=00000001,qop=auth,digest-uri="%s",response=%s,maxbuf=%d', $authcid, $challenge['realm'], $challenge['nonce'], $cnonce, $digest_uri, $response_value, $challenge['maxbuf']);
            } else {
                return sprintf('username="%s"' . $authzid_string  . ',nonce="%s",cnonce="%s",nc=00000001,qop=auth,digest-uri="%s",response=%s,maxbuf=%d', $authcid, $challenge['nonce'], $cnonce, $digest_uri, $response_value, $challenge['maxbuf']);
            }
        } else {
            return PEAR::raiseError('Invalid digest challenge');
        }
    }
    
    /**
    * Parses and verifies the digest challenge*
    *
    * @param  string $challenge The digest challenge
    * @return array             The parsed challenge as an assoc
    *                           array in the form "directive => value".
    * @access private
    */
    function _parseChallenge($challenge)
    {
        $tokens = array();
        while (preg_match('/^([a-z-]+)=("[^"]+(?<!\\\)"|[^,]+)/i', $challenge, $matches)) {

            // Ignore these as per rfc2831
            if ($matches[1] == 'opaque' OR $matches[1] == 'domain') {
                $challenge = substr($challenge, strlen($matches[0]) + 1);
                continue;
            }

            // Allowed multiple "realm" and "auth-param"
            if (!empty($tokens[$matches[1]]) AND ($matches[1] == 'realm' OR $matches[1] == 'auth-param')) {
                if (is_array($tokens[$matches[1]])) {
                    $tokens[$matches[1]][] = preg_replace('/^"(.*)"$/', '\\1', $matches[2]);
                } else {
                    $tokens[$matches[1]] = array($tokens[$matches[1]], preg_replace('/^"(.*)"$/', '\\1', $matches[2]));
                }

            // Any other multiple instance = failure
            } elseif (!empty($tokens[$matches[1]])) {
                $tokens = array();
                break;

            } else {
                $tokens[$matches[1]] = preg_replace('/^"(.*)"$/', '\\1', $matches[2]);
            }

            // Remove the just parsed directive from the challenge
            $challenge = substr($challenge, strlen($matches[0]) + 1);
        }

        /**
        * Defaults and required directives
        */
        // Realm
        if (empty($tokens['realm'])) {
            $tokens['realm'] = "";
        }

        // Maxbuf
        if (empty($tokens['maxbuf'])) {
            $tokens['maxbuf'] = 65536;
        }

        // Required: nonce, algorithm
        if (empty($tokens['nonce']) OR empty($tokens['algorithm'])) {
            return array();
        }

        return $tokens;
    }

    /**
    * Creates the response= part of the digest response
    *
    * @param  string $authcid    Authentication id (username)
    * @param  string $pass       Password
    * @param  string $realm      Realm as provided by the server
    * @param  string $nonce      Nonce as provided by the server
    * @param  string $cnonce     Client nonce
    * @param  string $digest_uri The digest-uri= value part of the response
    * @param  string $authzid    Authorization id
    * @return string             The response= part of the digest response
    * @access private
    */    
    function _getResponseValue($authcid, $pass, $realm, $nonce, $cnonce, $digest_uri, $authzid = '')
    {
        if ($authzid == '') {
            $A1 = sprintf('%s:%s:%s', pack('H32', md5(sprintf('%s:%s:%s', $authcid, $realm, $pass))), $nonce, $cnonce);
        } else {
            $A1 = sprintf('%s:%s:%s:%s', pack('H32', md5(sprintf('%s:%s:%s', $authcid, $realm, $pass))), $nonce, $cnonce, $authzid);
        }
        $A2 = 'AUTHENTICATE:' . $digest_uri;
        return md5(sprintf('%s:%s:00000001:%s:auth:%s', md5($A1), $nonce, $cnonce, md5($A2)));
    }

    /**
    * Creates the client nonce for the response
    *
    * @return string  The cnonce value
    * @access private
    */
    function _getCnonce()
    {
        if (@file_exists('/dev/urandom') && $fd = @fopen('/dev/urandom', 'r')) {
            return base64_encode(fread($fd, 32));

        } elseif (@file_exists('/dev/random') && $fd = @fopen('/dev/random', 'r')) {
            return base64_encode(fread($fd, 32));

        } else {
            $str = '';
            for ($i=0; $i<32; $i++) {
                $str .= chr(mt_rand(0, 255));
            }
            
            return base64_encode($str);
        }
    }
}
?>
PKn�Z�T�Auth/SASL/Common.phpnu�[���<?php
// +-----------------------------------------------------------------------+
// | Copyright (c) 2002-2003 Richard Heyes                                 |
// | All rights reserved.                                                  |
// |                                                                       |
// | Redistribution and use in source and binary forms, with or without    |
// | modification, are permitted provided that the following conditions    |
// | are met:                                                              |
// |                                                                       |
// | o Redistributions of source code must retain the above copyright      |
// |   notice, this list of conditions and the following disclaimer.       |
// | o Redistributions in binary form must reproduce the above copyright   |
// |   notice, this list of conditions and the following disclaimer in the |
// |   documentation and/or other materials provided with the distribution.|
// | o The names of the authors may not be used to endorse or promote      |
// |   products derived from this software without specific prior written  |
// |   permission.                                                         |
// |                                                                       |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  |
// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      |
// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   |
// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  |
// |                                                                       |
// +-----------------------------------------------------------------------+
// | Author: Richard Heyes <richard@php.net>                               |
// +-----------------------------------------------------------------------+
//
// $Id$

/**
* Common functionality to SASL mechanisms
*
* @author  Richard Heyes <richard@php.net>
* @access  public
* @version 1.0
* @package Auth_SASL
*/

class Auth_SASL_Common
{
    /**
    * Function which implements HMAC MD5 digest
    *
    * @param  string $key  The secret key
    * @param  string $data The data to hash
    * @param  bool $raw_output Whether the digest is returned in binary or hexadecimal format.
    *
    * @return string       The HMAC-MD5 digest
    */
    function _HMAC_MD5($key, $data, $raw_output = FALSE)
    {
        if (strlen($key) > 64) {
            $key = pack('H32', md5($key));
        }

        if (strlen($key) < 64) {
            $key = str_pad($key, 64, 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, $raw_output);

        return $digest;
    }

    /**
    * Function which implements HMAC-SHA-1 digest
    *
    * @param  string $key  The secret key
    * @param  string $data The data to hash
    * @param  bool $raw_output Whether the digest is returned in binary or hexadecimal format.
    * @return string       The HMAC-SHA-1 digest
    * @author Jehan <jehan.marmottard@gmail.com>
    * @access protected
    */
    protected function _HMAC_SHA1($key, $data, $raw_output = FALSE)
    {
        if (strlen($key) > 64) {
            $key = sha1($key, TRUE);
        }

        if (strlen($key) < 64) {
            $key = str_pad($key, 64, 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('H40', sha1($k_ipad . $data));
        $digest = sha1($k_opad . $inner, $raw_output);

         return $digest;
     }
}
?>
PKn�ZvR�r,,Auth/SASL/External.phpnu�[���<?php
// +-----------------------------------------------------------------------+ 
// | Copyright (c) 2008 Christoph Schulz                                   | 
// | All rights reserved.                                                  | 
// |                                                                       | 
// | Redistribution and use in source and binary forms, with or without    | 
// | modification, are permitted provided that the following conditions    | 
// | are met:                                                              | 
// |                                                                       | 
// | o Redistributions of source code must retain the above copyright      | 
// |   notice, this list of conditions and the following disclaimer.       | 
// | o Redistributions in binary form must reproduce the above copyright   | 
// |   notice, this list of conditions and the following disclaimer in the | 
// |   documentation and/or other materials provided with the distribution.| 
// | o The names of the authors may not be used to endorse or promote      | 
// |   products derived from this software without specific prior written  | 
// |   permission.                                                         | 
// |                                                                       | 
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   | 
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     | 
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  | 
// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      | 
// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   | 
// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  | 
// |                                                                       | 
// +-----------------------------------------------------------------------+ 
// | Author: Christoph Schulz <develop@kristov.de>                         | 
// +-----------------------------------------------------------------------+ 
// 
// $Id$

/**
* Implmentation of EXTERNAL SASL mechanism
*
* @author  Christoph Schulz <develop@kristov.de>
* @access  public
* @version 1.0.3
* @package Auth_SASL
*/

require_once('Auth/SASL/Common.php');

class Auth_SASL_External extends Auth_SASL_Common
{
    /**
    * Returns EXTERNAL response
    *
    * @param  string $authcid   Authentication id (username)
    * @param  string $pass      Password
    * @param  string $authzid   Autorization id
    * @return string            EXTERNAL Response
    */
    function getResponse($authcid, $pass, $authzid = '')
    {
        return $authzid;
    }
}
?>
PKn�Zќ��0�0Auth/SASL/SCRAM.phpnu�[���<?php
// +-----------------------------------------------------------------------+
// | Copyright (c) 2011 Jehan                                              |
// | All rights reserved.                                                  |
// |                                                                       |
// | Redistribution and use in source and binary forms, with or without    |
// | modification, are permitted provided that the following conditions    |
// | are met:                                                              |
// |                                                                       |
// | o Redistributions of source code must retain the above copyright      |
// |   notice, this list of conditions and the following disclaimer.       |
// | o Redistributions in binary form must reproduce the above copyright   |
// |   notice, this list of conditions and the following disclaimer in the |
// |   documentation and/or other materials provided with the distribution.|
// | o The names of the authors may not be used to endorse or promote      |
// |   products derived from this software without specific prior written  |
// |   permission.                                                         |
// |                                                                       |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  |
// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      |
// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   |
// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  |
// |                                                                       |
// +-----------------------------------------------------------------------+
// | Author: Jehan <jehan.marmottard@gmail.com                             |
// +-----------------------------------------------------------------------+
//
// $Id$

/**
* Implementation of SCRAM-* SASL mechanisms.
* SCRAM mechanisms have 3 main steps (initial response, response to the server challenge, then server signature
* verification) which keep state-awareness. Therefore a single class instanciation must be done and reused for the whole
* authentication process.
*
* @author  Jehan <jehan.marmottard@gmail.com>
* @access  public
* @version 1.0
* @package Auth_SASL
*/

require_once('Auth/SASL/Common.php');

class Auth_SASL_SCRAM extends Auth_SASL_Common
{
    /**
    * Construct a SCRAM-H client where 'H' is a cryptographic hash function.
    *
    * @param string $hash The name cryptographic hash function 'H' as registered by IANA in the "Hash Function Textual
    * Names" registry.
    * @link http://www.iana.org/assignments/hash-function-text-names/hash-function-text-names.xml "Hash Function Textual
    * Names"
    * format of core PHP hash function.
    * @access public
    */
    function __construct($hash)
    {
        // Though I could be strict, I will actually also accept the naming used in the PHP core hash framework.
        // For instance "sha1" is accepted, while the registered hash name should be "SHA-1".
        $hash = strtolower($hash);
        $hashes = array('md2' => 'md2',
            'md5' => 'md5',
            'sha-1' => 'sha1',
            'sha1' => 'sha1',
            'sha-224' > 'sha224',
            'sha224' > 'sha224',
            'sha-256' => 'sha256',
            'sha256' => 'sha256',
            'sha-384' => 'sha384',
            'sha384' => 'sha384',
            'sha-512' => 'sha512',
            'sha512' => 'sha512');
        if (function_exists('hash_hmac') && isset($hashes[$hash]))
        {
            $this->hash = create_function('$data', 'return hash("' . $hashes[$hash] . '", $data, TRUE);');
            $this->hmac = create_function('$key,$str,$raw', 'return hash_hmac("' . $hashes[$hash] . '", $str, $key, $raw);');
        }
        elseif ($hash == 'md5')
        {
            $this->hash = create_function('$data', 'return md5($data, true);');
            $this->hmac = array($this, '_HMAC_MD5');
        }
        elseif (in_array($hash, array('sha1', 'sha-1')))
        {
            $this->hash = create_function('$data', 'return sha1($data, true);');
            $this->hmac = array($this, '_HMAC_SHA1');
        }
        else
            return PEAR::raiseError('Invalid SASL mechanism type');
    }

    /**
    * Provides the (main) client response for SCRAM-H.
    *
    * @param  string $authcid   Authentication id (username)
    * @param  string $pass      Password
    * @param  string $challenge The challenge sent by the server.
    * If the challenge is NULL or an empty string, the result will be the "initial response".
    * @param  string $authzid   Authorization id (username to proxy as)
    * @return string|false      The response (binary, NOT base64 encoded)
    * @access public
    */
    public function getResponse($authcid, $pass, $challenge = NULL, $authzid = NULL)
    {
        $authcid = $this->_formatName($authcid);
        if (empty($authcid))
        {
            return false;
        }
        if (!empty($authzid))
        {
            $authzid = $this->_formatName($authzid);
            if (empty($authzid))
            {
                return false;
            }
        }

        if (empty($challenge))
        {
            return $this->_generateInitialResponse($authcid, $authzid);
        }
        else
        {
            return $this->_generateResponse($challenge, $pass);
        }

    }

    /**
    * Prepare a name for inclusion in a SCRAM response.
    *
    * @param string $username a name to be prepared.
    * @return string the reformated name.
    * @access private
    */
    private function _formatName($username)
    {
        // TODO: prepare through the SASLprep profile of the stringprep algorithm.
        // See RFC-4013.

        $username = str_replace('=', '=3D', $username);
        $username = str_replace(',', '=2C', $username);
        return $username;
    }

    /**
    * Generate the initial response which can be either sent directly in the first message or as a response to an empty
    * server challenge.
    *
    * @param string $authcid Prepared authentication identity.
    * @param string $authzid Prepared authorization identity.
    * @return string The SCRAM response to send.
    * @access private
    */
    private function _generateInitialResponse($authcid, $authzid)
    {
        $init_rep = '';
        $gs2_cbind_flag = 'n,'; // TODO: support channel binding.
        $this->gs2_header = $gs2_cbind_flag . (!empty($authzid)? 'a=' . $authzid : '') . ',';

        // I must generate a client nonce and "save" it for later comparison on second response.
        $this->cnonce = $this->_getCnonce();
        // XXX: in the future, when mandatory and/or optional extensions are defined in any updated RFC,
        // this message can be updated.
        $this->first_message_bare = 'n=' . $authcid . ',r=' . $this->cnonce;
        return $this->gs2_header . $this->first_message_bare;
    }

    /**
    * Parses and verifies a non-empty SCRAM challenge.
    *
    * @param  string $challenge The SCRAM challenge
    * @return string|false      The response to send; false in case of wrong challenge or if an initial response has not
    * been generated first.
    * @access private
    */
    private function _generateResponse($challenge, $password)
    {
        // XXX: as I don't support mandatory extension, I would fail on them.
        // And I simply ignore any optional extension.
        $server_message_regexp = "#^r=([\x21-\x2B\x2D-\x7E]+),s=((?:[A-Za-z0-9/+]{4})*(?:[A-Za-z0-9]{3}=|[A-Xa-z0-9]{2}==)?),i=([0-9]*)(,[A-Za-z]=[^,])*$#";
        if (!isset($this->cnonce, $this->gs2_header)
            || !preg_match($server_message_regexp, $challenge, $matches))
        {
            return false;
        }
        $nonce = $matches[1];
        $salt = base64_decode($matches[2]);
        if (!$salt)
        {
            // Invalid Base64.
            return false;
        }
        $i = intval($matches[3]);

        $cnonce = substr($nonce, 0, strlen($this->cnonce));
        if ($cnonce <> $this->cnonce)
        {
            // Invalid challenge! Are we under attack?
            return false;
        }

        $channel_binding = 'c=' . base64_encode($this->gs2_header); // TODO: support channel binding.
        $final_message = $channel_binding . ',r=' . $nonce; // XXX: no extension.

        // TODO: $password = $this->normalize($password); // SASLprep profile of stringprep.
        $saltedPassword = $this->hi($password, $salt, $i);
        $this->saltedPassword = $saltedPassword;
        $clientKey = call_user_func($this->hmac, $saltedPassword, "Client Key", TRUE);
        $storedKey = call_user_func($this->hash, $clientKey, TRUE);
        $authMessage = $this->first_message_bare . ',' . $challenge . ',' . $final_message;
        $this->authMessage = $authMessage;
        $clientSignature = call_user_func($this->hmac, $storedKey, $authMessage, TRUE);
        $clientProof = $clientKey ^ $clientSignature;
        $proof = ',p=' . base64_encode($clientProof);

        return $final_message . $proof;
    }

    /**
    * SCRAM has also a server verification step. On a successful outcome, it will send additional data which must
    * absolutely be checked against this function. If this fails, the entity which we are communicating with is probably
    * not the server as it has not access to your ServerKey.
    *
    * @param string $data The additional data sent along a successful outcome.
    * @return bool Whether the server has been authenticated.
    * If false, the client must close the connection and consider to be under a MITM attack.
    * @access public
    */
    public function processOutcome($data)
    {
        $verifier_regexp = '#^v=((?:[A-Za-z0-9/+]{4})*(?:[A-Za-z0-9]{3}=|[A-Xa-z0-9]{2}==)?)$#';
        if (!isset($this->saltedPassword, $this->authMessage)
            || !preg_match($verifier_regexp, $data, $matches))
        {
            // This cannot be an outcome, you never sent the challenge's response.
            return false;
        }

        $verifier = $matches[1];
        $proposed_serverSignature = base64_decode($verifier);
        $serverKey = call_user_func($this->hmac, $this->saltedPassword, "Server Key", true);
        $serverSignature = call_user_func($this->hmac, $serverKey, $this->authMessage, TRUE);
        return ($proposed_serverSignature === $serverSignature);
    }

    /**
    * Hi() call, which is essentially PBKDF2 (RFC-2898) with HMAC-H() as the pseudorandom function.
    *
    * @param string $str The string to hash.
    * @param string $hash The hash value.
    * @param int $i The iteration count.
    * @access private
    */
    private function hi($str, $salt, $i)
    {
        $int1 = "\0\0\0\1";
        $ui = call_user_func($this->hmac, $str, $salt . $int1, true);
        $result = $ui;
        for ($k = 1; $k < $i; $k++)
        {
            $ui = call_user_func($this->hmac, $str, $ui, true);
            $result = $result ^ $ui;
        }
        return $result;
    }


    /**
    * Creates the client nonce for the response
    *
    * @return string  The cnonce value
    * @access private
    * @author  Richard Heyes <richard@php.net>
    */
    private function _getCnonce()
    {
        // TODO: I reused the nonce function from the DigestMD5 class.
        // I should probably make this a protected function in Common.
        if (@file_exists('/dev/urandom') && $fd = @fopen('/dev/urandom', 'r')) {
            return base64_encode(fread($fd, 32));

        } elseif (@file_exists('/dev/random') && $fd = @fopen('/dev/random', 'r')) {
            return base64_encode(fread($fd, 32));

        } else {
            $str = '';
            for ($i=0; $i<32; $i++) {
                $str .= chr(mt_rand(0, 255));
            }

            return base64_encode($str);
        }
    }

}

?>
PKn�Z2r����
Auth/SASL.phpnu�[���<?php
// +-----------------------------------------------------------------------+
// | Copyright (c) 2002-2003 Richard Heyes                                 |
// | All rights reserved.                                                  |
// |                                                                       |
// | Redistribution and use in source and binary forms, with or without    |
// | modification, are permitted provided that the following conditions    |
// | are met:                                                              |
// |                                                                       |
// | o Redistributions of source code must retain the above copyright      |
// |   notice, this list of conditions and the following disclaimer.       |
// | o Redistributions in binary form must reproduce the above copyright   |
// |   notice, this list of conditions and the following disclaimer in the |
// |   documentation and/or other materials provided with the distribution.|
// | o The names of the authors may not be used to endorse or promote      |
// |   products derived from this software without specific prior written  |
// |   permission.                                                         |
// |                                                                       |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  |
// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      |
// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   |
// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  |
// |                                                                       |
// +-----------------------------------------------------------------------+
// | Author: Richard Heyes <richard@php.net>                               |
// +-----------------------------------------------------------------------+
//
// $Id$

/**
* Client implementation of various SASL mechanisms
*
* @author  Richard Heyes <richard@php.net>
* @access  public
* @version 1.0
* @package Auth_SASL
*/

require_once('PEAR.php');

class Auth_SASL
{
    /**
    * Factory class. Returns an object of the request
    * type.
    *
    * @param string $type One of: Anonymous
    *                             Plain
    *                             CramMD5
    *                             DigestMD5
    *                             SCRAM-* (any mechanism of the SCRAM family)
    *                     Types are not case sensitive
    */
    public static function factory($type)
    {
        switch (strtolower($type)) {
            case 'anonymous':
                $filename  = 'Auth/SASL/Anonymous.php';
                $classname = 'Auth_SASL_Anonymous';
                break;

            case 'login':
                $filename  = 'Auth/SASL/Login.php';
                $classname = 'Auth_SASL_Login';
                break;

            case 'plain':
                $filename  = 'Auth/SASL/Plain.php';
                $classname = 'Auth_SASL_Plain';
                break;

            case 'external':
                $filename  = 'Auth/SASL/External.php';
                $classname = 'Auth_SASL_External';
                break;

            case 'crammd5':
                // $msg = 'Deprecated mechanism name. Use IANA-registered name: CRAM-MD5.';
                // trigger_error($msg, E_USER_DEPRECATED);
            case 'cram-md5':
                $filename  = 'Auth/SASL/CramMD5.php';
                $classname = 'Auth_SASL_CramMD5';
                break;

            case 'digestmd5':
                // $msg = 'Deprecated mechanism name. Use IANA-registered name: DIGEST-MD5.';
                // trigger_error($msg, E_USER_DEPRECATED);
            case 'digest-md5':
                // $msg = 'DIGEST-MD5 is a deprecated SASL mechanism as per RFC-6331. Using it could be a security risk.';
                // trigger_error($msg, E_USER_NOTICE);
                $filename  = 'Auth/SASL/DigestMD5.php';
                $classname = 'Auth_SASL_DigestMD5';
                break;

            default:
                $scram = '/^SCRAM-(.{1,9})$/i';
                if (preg_match($scram, $type, $matches))
                {
                    $hash = $matches[1];
                    $filename = dirname(__FILE__) .'/SASL/SCRAM.php';
                    $classname = 'Auth_SASL_SCRAM';
                    $parameter = $hash;
                    break;
                }
                return PEAR::raiseError('Invalid SASL mechanism type');
                break;
        }

        require_once($filename);
        if (isset($parameter))
            $obj = new $classname($parameter);
        else
            $obj = new $classname();
        return $obj;
    }
}

?>
PKn�Z�T�,�,OS/Guess.phpnu�[���<?php
/**
 * The OS_Guess class
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Stig Bakken <ssb@php.net>
 * @author    Gregory Beaver <cellog@php.net>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 * @since     File available since PEAR 0.1
 */

// {{{ uname examples

// php_uname() without args returns the same as 'uname -a', or a PHP-custom
// string for Windows.
// PHP versions prior to 4.3 return the uname of the host where PHP was built,
// as of 4.3 it returns the uname of the host running the PHP code.
//
// PC RedHat Linux 7.1:
// Linux host.example.com 2.4.2-2 #1 Sun Apr 8 20:41:30 EDT 2001 i686 unknown
//
// PC Debian Potato:
// Linux host 2.4.17 #2 SMP Tue Feb 12 15:10:04 CET 2002 i686 unknown
//
// PC FreeBSD 3.3:
// FreeBSD host.example.com 3.3-STABLE FreeBSD 3.3-STABLE #0: Mon Feb 21 00:42:31 CET 2000     root@example.com:/usr/src/sys/compile/CONFIG  i386
//
// PC FreeBSD 4.3:
// FreeBSD host.example.com 4.3-RELEASE FreeBSD 4.3-RELEASE #1: Mon Jun 25 11:19:43 EDT 2001     root@example.com:/usr/src/sys/compile/CONFIG  i386
//
// PC FreeBSD 4.5:
// FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb  6 23:59:23 CET 2002     root@example.com:/usr/src/sys/compile/CONFIG  i386
//
// PC FreeBSD 4.5 w/uname from GNU shellutils:
// FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb  i386 unknown
//
// HP 9000/712 HP-UX 10:
// HP-UX iq B.10.10 A 9000/712 2008429113 two-user license
//
// HP 9000/712 HP-UX 10 w/uname from GNU shellutils:
// HP-UX host B.10.10 A 9000/712 unknown
//
// IBM RS6000/550 AIX 4.3:
// AIX host 3 4 000003531C00
//
// AIX 4.3 w/uname from GNU shellutils:
// AIX host 3 4 000003531C00 unknown
//
// SGI Onyx IRIX 6.5 w/uname from GNU shellutils:
// IRIX64 host 6.5 01091820 IP19 mips
//
// SGI Onyx IRIX 6.5:
// IRIX64 host 6.5 01091820 IP19
//
// SparcStation 20 Solaris 8 w/uname from GNU shellutils:
// SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc
//
// SparcStation 20 Solaris 8:
// SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc SUNW,SPARCstation-20
//
// Mac OS X (Darwin)
// Darwin home-eden.local 7.5.0 Darwin Kernel Version 7.5.0: Thu Aug  5 19:26:16 PDT 2004; root:xnu/xnu-517.7.21.obj~3/RELEASE_PPC  Power Macintosh
//
// Mac OS X early versions
//

// }}}

/* TODO:
 * - define endianness, to allow matchSignature("bigend") etc.
 */

/**
 * Retrieves information about the current operating system
 *
 * This class uses php_uname() to grok information about the current OS
 *
 * @category  pear
 * @package   PEAR
 * @author    Stig Bakken <ssb@php.net>
 * @author    Gregory Beaver <cellog@php.net>
 * @copyright 1997-2020 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @version   Release: 1.10.16
 * @link      http://pear.php.net/package/PEAR
 * @since     Class available since Release 0.1
 */
class OS_Guess
{
    var $sysname;
    var $nodename;
    var $cpu;
    var $release;
    var $extra;

    function __construct($uname = null)
    {
        list($this->sysname,
             $this->release,
             $this->cpu,
             $this->extra,
             $this->nodename) = $this->parseSignature($uname);
    }

    function parseSignature($uname = null)
    {
        static $sysmap = array(
            'HP-UX' => 'hpux',
            'IRIX64' => 'irix',
        );
        static $cpumap = array(
            'i586' => 'i386',
            'i686' => 'i386',
            'ppc' => 'powerpc',
        );
        if ($uname === null) {
            $uname = php_uname();
        }
        $parts = preg_split('/\s+/', trim($uname));
        $n = count($parts);

        $release  = $machine = $cpu = '';
        $sysname  = $parts[0];
        $nodename = $parts[1];
        $cpu      = $parts[$n-1];
        $extra = '';
        if ($cpu == 'unknown') {
            $cpu = $parts[$n - 2];
        }

        switch ($sysname) {
            case 'AIX' :
                $release = "$parts[3].$parts[2]";
                break;
            case 'Windows' :
                $release = $parts[1];
                if ($release == '95/98') {
                    $release = '9x';
                }
                $cpu = 'i386';
                break;
            case 'Linux' :
                $extra = $this->_detectGlibcVersion();
                // use only the first two digits from the kernel version
                $release = preg_replace('/^([0-9]+\.[0-9]+).*/', '\1', $parts[2]);
                break;
            case 'Mac' :
                $sysname = 'darwin';
                $nodename = $parts[2];
                $release = $parts[3];
                $cpu = $this->_determineIfPowerpc($cpu, $parts);
                break;
            case 'Darwin' :
                $cpu = $this->_determineIfPowerpc($cpu, $parts);
                $release = preg_replace('/^([0-9]+\.[0-9]+).*/', '\1', $parts[2]);
                break;
            default:
                $release = preg_replace('/-.*/', '', $parts[2]);
                break;
        }

        if (isset($sysmap[$sysname])) {
            $sysname = $sysmap[$sysname];
        } else {
            $sysname = strtolower($sysname);
        }
        if (isset($cpumap[$cpu])) {
            $cpu = $cpumap[$cpu];
        }
        return array($sysname, $release, $cpu, $extra, $nodename);
    }

    function _determineIfPowerpc($cpu, $parts)
    {
        $n = count($parts);
        if ($cpu == 'Macintosh' && $parts[$n - 2] == 'Power') {
            $cpu = 'powerpc';
        }
        return $cpu;
    }

    function _detectGlibcVersion()
    {
        static $glibc = false;
        if ($glibc !== false) {
            return $glibc; // no need to run this multiple times
        }
        $major = $minor = 0;
        include_once "System.php";

        // Let's try reading possible libc.so.6 symlinks
        $libcs = array(
            '/lib64/libc.so.6',
            '/lib/libc.so.6',
            '/lib/i386-linux-gnu/libc.so.6'
        );
        $versions = array();
        foreach ($libcs as $file) {
            $versions = $this->_readGlibCVersionFromSymlink($file);
            if ($versions != []) {
                list($major, $minor) = $versions;
                break;
            }
        }

        // Use glibc's <features.h> header file to
        // get major and minor version number:
        if (!($major && $minor)) {
            $versions = $this->_readGlibCVersionFromFeaturesHeaderFile();
        }
        if (is_array($versions) && $versions != []) {
            list($major, $minor) = $versions;
        }

        if (!($major && $minor)) {
            return $glibc = '';
        }

        return $glibc = "glibc{$major}.{$minor}";
    }

    function _readGlibCVersionFromSymlink($file)
    {
        $versions = array();
        if (@is_link($file)
            && (preg_match('/^libc-(.*)\.so$/', basename(readlink($file)), $matches))
        ) {
            $versions = explode('.', $matches[1]);
        }
        return $versions;
    }


    function _readGlibCVersionFromFeaturesHeaderFile()
    {
        $features_header_file = '/usr/include/features.h';
        if (!(@file_exists($features_header_file)
            && @is_readable($features_header_file))
        ) {
            return array();
        }
        if (!@file_exists('/usr/bin/cpp') || !@is_executable('/usr/bin/cpp')) {
            return $this->_parseFeaturesHeaderFile($features_header_file);
        } // no cpp

        return $this->_fromGlibCTest();
    }

    function _parseFeaturesHeaderFile($features_header_file)
    {
        $features_file = fopen($features_header_file, 'rb');
        while (!feof($features_file)) {
            $line = fgets($features_file, 8192);
            if (!$this->_IsADefinition($line)) {
                continue;
            }
            if (strpos($line, '__GLIBC__')) {
                // major version number #define __GLIBC__ version
                $line = preg_split('/\s+/', $line);
                $glibc_major = trim($line[2]);
                if (isset($glibc_minor)) {
                    break;
                }
                continue;
            }

            if (strpos($line, '__GLIBC_MINOR__')) {
                // got the minor version number
                // #define __GLIBC_MINOR__ version
                $line = preg_split('/\s+/', $line);
                $glibc_minor = trim($line[2]);
                if (isset($glibc_major)) {
                    break;
                }
            }
        }
        fclose($features_file);
        if (!isset($glibc_major) || !isset($glibc_minor)) {
            return array();
        }
        return array(trim($glibc_major), trim($glibc_minor));
    }

    function _IsADefinition($line)
    {
        if ($line === false) {
            return false;
        }
        return strpos(trim($line), '#define') !== false;
    }

    function _fromGlibCTest()
    {
        $major = null;
        $minor = null;

        $tmpfile = System::mktemp("glibctest");
        $fp = fopen($tmpfile, "w");
        fwrite($fp, "#include <features.h>\n__GLIBC__ __GLIBC_MINOR__\n");
        fclose($fp);
        $cpp = popen("/usr/bin/cpp $tmpfile", "r");
        while ($line = fgets($cpp, 1024)) {
            if ($line[0] == '#' || trim($line) == '') {
                continue;
            }

            if (list($major, $minor) = explode(' ', trim($line))) {
                break;
            }
        }
        pclose($cpp);
        unlink($tmpfile);
        if ($major !== null && $minor !== null) {
            return [$major, $minor];
        }
    }

    function getSignature()
    {
        if (empty($this->extra)) {
            return "{$this->sysname}-{$this->release}-{$this->cpu}";
        }
        return "{$this->sysname}-{$this->release}-{$this->cpu}-{$this->extra}";
    }

    function getSysname()
    {
        return $this->sysname;
    }

    function getNodename()
    {
        return $this->nodename;
    }

    function getCpu()
    {
        return $this->cpu;
    }

    function getRelease()
    {
        return $this->release;
    }

    function getExtra()
    {
        return $this->extra;
    }

    function matchSignature($match)
    {
        $fragments = is_array($match) ? $match : explode('-', $match);
        $n = count($fragments);
        $matches = 0;
        if ($n > 0) {
            $matches += $this->_matchFragment($fragments[0], $this->sysname);
        }
        if ($n > 1) {
            $matches += $this->_matchFragment($fragments[1], $this->release);
        }
        if ($n > 2) {
            $matches += $this->_matchFragment($fragments[2], $this->cpu);
        }
        if ($n > 3) {
            $matches += $this->_matchFragment($fragments[3], $this->extra);
        }
        return ($matches == $n);
    }

    function _matchFragment($fragment, $value)
    {
        if (strcspn($fragment, '*?') < strlen($fragment)) {
            $expression = str_replace(
                array('*', '?', '/'),
                array('.*', '.', '\\/'),
                $fragment
            );
            $reg = '/^' . $expression . '\\z/';
            return preg_match($reg, $value);
        }
        return ($fragment == '*' || !strcasecmp($fragment, $value));
    }
}
/*
 * Local Variables:
 * indent-tabs-mode: nil
 * c-basic-offset: 4
 * End:
 */
PKn�Z����PEAR/Config.phpnu�[���<?php
/**
 * PEAR_Config, customized configuration handling for the PEAR Installer
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 0.1
 */

/**
 * Required for error handling
 */
require_once 'PEAR.php';
require_once 'PEAR/Registry.php';
require_once 'PEAR/Installer/Role.php';
require_once 'System.php';

/**
 * Last created PEAR_Config instance.
 * @var object
 */
$GLOBALS['_PEAR_Config_instance'] = null;
if (!defined('PEAR_INSTALL_DIR') || !PEAR_INSTALL_DIR) {
    $PEAR_INSTALL_DIR = PHP_LIBDIR . DIRECTORY_SEPARATOR . 'pear';
} else {
    $PEAR_INSTALL_DIR = PEAR_INSTALL_DIR;
}

// Below we define constants with default values for all configuration
// parameters except username/password.  All of them can have their
// defaults set through environment variables.  The reason we use the
// PHP_ prefix is for some security, PHP protects environment
// variables starting with PHP_*.

// default channel and preferred mirror is based on whether we are invoked through
// the "pear" or the "pecl" command
if (!defined('PEAR_RUNTYPE')) {
    define('PEAR_RUNTYPE', 'pear');
}

if (PEAR_RUNTYPE == 'pear') {
    define('PEAR_CONFIG_DEFAULT_CHANNEL', 'pear.php.net');
} else {
    define('PEAR_CONFIG_DEFAULT_CHANNEL', 'pecl.php.net');
}

if (getenv('PHP_PEAR_SYSCONF_DIR')) {
    define('PEAR_CONFIG_SYSCONFDIR', getenv('PHP_PEAR_SYSCONF_DIR'));
} elseif (getenv('SystemRoot')) {
    define('PEAR_CONFIG_SYSCONFDIR', getenv('SystemRoot'));
} else {
    define('PEAR_CONFIG_SYSCONFDIR', PHP_SYSCONFDIR);
}

// Default for master_server
if (getenv('PHP_PEAR_MASTER_SERVER')) {
    define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', getenv('PHP_PEAR_MASTER_SERVER'));
} else {
    define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', 'pear.php.net');
}

// Default for http_proxy
if (getenv('PHP_PEAR_HTTP_PROXY')) {
    define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('PHP_PEAR_HTTP_PROXY'));
} elseif (getenv('http_proxy')) {
    define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('http_proxy'));
} else {
    define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', '');
}

// Default for php_dir
if (getenv('PHP_PEAR_INSTALL_DIR')) {
    define('PEAR_CONFIG_DEFAULT_PHP_DIR', getenv('PHP_PEAR_INSTALL_DIR'));
} else {
    define('PEAR_CONFIG_DEFAULT_PHP_DIR', $PEAR_INSTALL_DIR);
}

// Default for metadata_dir
if (getenv('PHP_PEAR_METADATA_DIR')) {
    define('PEAR_CONFIG_DEFAULT_METADATA_DIR', getenv('PHP_PEAR_METADATA_DIR'));
} else {
    define('PEAR_CONFIG_DEFAULT_METADATA_DIR', '');
}

// Default for ext_dir
if (getenv('PHP_PEAR_EXTENSION_DIR')) {
    define('PEAR_CONFIG_DEFAULT_EXT_DIR', getenv('PHP_PEAR_EXTENSION_DIR'));
} else {
    if (ini_get('extension_dir')) {
        define('PEAR_CONFIG_DEFAULT_EXT_DIR', ini_get('extension_dir'));
    } elseif (defined('PEAR_EXTENSION_DIR') &&
              file_exists(PEAR_EXTENSION_DIR) && is_dir(PEAR_EXTENSION_DIR)) {
        define('PEAR_CONFIG_DEFAULT_EXT_DIR', PEAR_EXTENSION_DIR);
    } elseif (defined('PHP_EXTENSION_DIR')) {
        define('PEAR_CONFIG_DEFAULT_EXT_DIR', PHP_EXTENSION_DIR);
    } else {
        define('PEAR_CONFIG_DEFAULT_EXT_DIR', '.');
    }
}

// Default for doc_dir
if (getenv('PHP_PEAR_DOC_DIR')) {
    define('PEAR_CONFIG_DEFAULT_DOC_DIR', getenv('PHP_PEAR_DOC_DIR'));
} else {
    define('PEAR_CONFIG_DEFAULT_DOC_DIR',
           $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'docs');
}

// Default for bin_dir
if (getenv('PHP_PEAR_BIN_DIR')) {
    define('PEAR_CONFIG_DEFAULT_BIN_DIR', getenv('PHP_PEAR_BIN_DIR'));
} else {
    define('PEAR_CONFIG_DEFAULT_BIN_DIR', PHP_BINDIR);
}

// Default for data_dir
if (getenv('PHP_PEAR_DATA_DIR')) {
    define('PEAR_CONFIG_DEFAULT_DATA_DIR', getenv('PHP_PEAR_DATA_DIR'));
} else {
    define('PEAR_CONFIG_DEFAULT_DATA_DIR',
           $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'data');
}

// Default for cfg_dir
if (getenv('PHP_PEAR_CFG_DIR')) {
    define('PEAR_CONFIG_DEFAULT_CFG_DIR', getenv('PHP_PEAR_CFG_DIR'));
} else {
    define('PEAR_CONFIG_DEFAULT_CFG_DIR',
           $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'cfg');
}

// Default for www_dir
if (getenv('PHP_PEAR_WWW_DIR')) {
    define('PEAR_CONFIG_DEFAULT_WWW_DIR', getenv('PHP_PEAR_WWW_DIR'));
} else {
    define('PEAR_CONFIG_DEFAULT_WWW_DIR',
           $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'www');
}

// Default for man_dir
if (getenv('PHP_PEAR_MAN_DIR')) {
    define('PEAR_CONFIG_DEFAULT_MAN_DIR', getenv('PHP_PEAR_MAN_DIR'));
} else {
    if (defined('PHP_MANDIR')) { // Added in PHP5.3.7
        define('PEAR_CONFIG_DEFAULT_MAN_DIR', PHP_MANDIR);
    } else {
        define('PEAR_CONFIG_DEFAULT_MAN_DIR', PHP_PREFIX . DIRECTORY_SEPARATOR .
           'local' . DIRECTORY_SEPARATOR .'man');
    }
}

// Default for test_dir
if (getenv('PHP_PEAR_TEST_DIR')) {
    define('PEAR_CONFIG_DEFAULT_TEST_DIR', getenv('PHP_PEAR_TEST_DIR'));
} else {
    define('PEAR_CONFIG_DEFAULT_TEST_DIR',
           $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'tests');
}

// Default for temp_dir
if (getenv('PHP_PEAR_TEMP_DIR')) {
    define('PEAR_CONFIG_DEFAULT_TEMP_DIR', getenv('PHP_PEAR_TEMP_DIR'));
} else {
    define('PEAR_CONFIG_DEFAULT_TEMP_DIR',
           System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' .
           DIRECTORY_SEPARATOR . 'temp');
}

// Default for cache_dir
if (getenv('PHP_PEAR_CACHE_DIR')) {
    define('PEAR_CONFIG_DEFAULT_CACHE_DIR', getenv('PHP_PEAR_CACHE_DIR'));
} else {
    define('PEAR_CONFIG_DEFAULT_CACHE_DIR',
           System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' .
           DIRECTORY_SEPARATOR . 'cache');
}

// Default for download_dir
if (getenv('PHP_PEAR_DOWNLOAD_DIR')) {
    define('PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR', getenv('PHP_PEAR_DOWNLOAD_DIR'));
} else {
    define('PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR',
           System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' .
           DIRECTORY_SEPARATOR . 'download');
}

// Default for php_bin
if (getenv('PHP_PEAR_PHP_BIN')) {
    define('PEAR_CONFIG_DEFAULT_PHP_BIN', getenv('PHP_PEAR_PHP_BIN'));
} else {
    define('PEAR_CONFIG_DEFAULT_PHP_BIN', PEAR_CONFIG_DEFAULT_BIN_DIR.
           DIRECTORY_SEPARATOR.'php'.(OS_WINDOWS ? '.exe' : ''));
}

// Default for verbose
if (getenv('PHP_PEAR_VERBOSE')) {
    define('PEAR_CONFIG_DEFAULT_VERBOSE', getenv('PHP_PEAR_VERBOSE'));
} else {
    define('PEAR_CONFIG_DEFAULT_VERBOSE', 1);
}

// Default for preferred_state
if (getenv('PHP_PEAR_PREFERRED_STATE')) {
    define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', getenv('PHP_PEAR_PREFERRED_STATE'));
} else {
    define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', 'stable');
}

// Default for umask
if (getenv('PHP_PEAR_UMASK')) {
    define('PEAR_CONFIG_DEFAULT_UMASK', getenv('PHP_PEAR_UMASK'));
} else {
    define('PEAR_CONFIG_DEFAULT_UMASK', decoct(umask()));
}

// Default for cache_ttl
if (getenv('PHP_PEAR_CACHE_TTL')) {
    define('PEAR_CONFIG_DEFAULT_CACHE_TTL', getenv('PHP_PEAR_CACHE_TTL'));
} else {
    define('PEAR_CONFIG_DEFAULT_CACHE_TTL', 3600);
}

// Default for sig_type
if (getenv('PHP_PEAR_SIG_TYPE')) {
    define('PEAR_CONFIG_DEFAULT_SIG_TYPE', getenv('PHP_PEAR_SIG_TYPE'));
} else {
    define('PEAR_CONFIG_DEFAULT_SIG_TYPE', 'gpg');
}

// Default for sig_bin
if (getenv('PHP_PEAR_SIG_BIN')) {
    define('PEAR_CONFIG_DEFAULT_SIG_BIN', getenv('PHP_PEAR_SIG_BIN'));
} else {
    define('PEAR_CONFIG_DEFAULT_SIG_BIN',
           System::which(
               'gpg', OS_WINDOWS ? 'c:\gnupg\gpg.exe' : '/usr/local/bin/gpg'));
}

// Default for sig_keydir
if (getenv('PHP_PEAR_SIG_KEYDIR')) {
    define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR', getenv('PHP_PEAR_SIG_KEYDIR'));
} else {
    define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR',
           PEAR_CONFIG_SYSCONFDIR . DIRECTORY_SEPARATOR . 'pearkeys');
}

/**
 * This is a class for storing configuration data, keeping track of
 * which are system-defined, user-defined or defaulted.
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 0.1
 */
class PEAR_Config extends PEAR
{
    /**
     * Array of config files used.
     *
     * @var array layer => config file
     */
    var $files = array(
        'system' => '',
        'user' => '',
        );

    var $layers = array();

    /**
     * Configuration data, two-dimensional array where the first
     * dimension is the config layer ('user', 'system' and 'default'),
     * and the second dimension is keyname => value.
     *
     * The order in the first dimension is important!  Earlier
     * layers will shadow later ones when a config value is
     * requested (if a 'user' value exists, it will be returned first,
     * then 'system' and finally 'default').
     *
     * @var array layer => array(keyname => value, ...)
     */
    var $configuration = array(
        'user' => array(),
        'system' => array(),
        'default' => array(),
        );

    /**
     * Configuration values that can be set for a channel
     *
     * All other configuration values can only have a global value
     * @var array
     * @access private
     */
    var $_channelConfigInfo = array(
        'php_dir', 'ext_dir', 'doc_dir', 'bin_dir', 'data_dir', 'cfg_dir',
        'test_dir', 'www_dir', 'php_bin', 'php_prefix', 'php_suffix', 'username',
        'password', 'verbose', 'preferred_state', 'umask', 'preferred_mirror', 'php_ini'
        );

    /**
     * Channels that can be accessed
     * @see setChannels()
     * @var array
     * @access private
     */
    var $_channels = array('pear.php.net', 'pecl.php.net', '__uri');

    /**
     * This variable is used to control the directory values returned
     * @see setInstallRoot();
     * @var string|false
     * @access private
     */
    var $_installRoot = false;

    /**
     * If requested, this will always refer to the registry
     * contained in php_dir
     * @var PEAR_Registry
     */
    var $_registry = array();

    /**
     * @var array
     * @access private
     */
    var $_regInitialized = array();

    /**
     * @var bool
     * @access private
     */
    var $_noRegistry = false;

    /**
     * amount of errors found while parsing config
     * @var integer
     * @access private
     */
    var $_errorsFound = 0;
    var $_lastError = null;

    /**
     * Information about the configuration data.  Stores the type,
     * default value and a documentation string for each configuration
     * value.
     *
     * @var array layer => array(infotype => value, ...)
     */
    var $configuration_info = array(
        // Channels/Internet Access
        'default_channel' => array(
            'type' => 'string',
            'default' => PEAR_CONFIG_DEFAULT_CHANNEL,
            'doc' => 'the default channel to use for all non explicit commands',
            'prompt' => 'Default Channel',
            'group' => 'Internet Access',
            ),
        'preferred_mirror' => array(
            'type' => 'string',
            'default' => PEAR_CONFIG_DEFAULT_CHANNEL,
            'doc' => 'the default server or mirror to use for channel actions',
            'prompt' => 'Default Channel Mirror',
            'group' => 'Internet Access',
            ),
        'remote_config' => array(
            'type' => 'password',
            'default' => '',
            'doc' => 'ftp url of remote configuration file to use for synchronized install',
            'prompt' => 'Remote Configuration File',
            'group' => 'Internet Access',
            ),
        'auto_discover' => array(
            'type' => 'integer',
            'default' => 0,
            'doc' => 'whether to automatically discover new channels',
            'prompt' => 'Auto-discover new Channels',
            'group' => 'Internet Access',
            ),
        // Internet Access
        'master_server' => array(
            'type' => 'string',
            'default' => 'pear.php.net',
            'doc' => 'name of the main PEAR server [NOT USED IN THIS VERSION]',
            'prompt' => 'PEAR server [DEPRECATED]',
            'group' => 'Internet Access',
            ),
        'http_proxy' => array(
            'type' => 'string',
            'default' => PEAR_CONFIG_DEFAULT_HTTP_PROXY,
            'doc' => 'HTTP proxy (host:port) to use when downloading packages',
            'prompt' => 'HTTP Proxy Server Address',
            'group' => 'Internet Access',
            ),
        // File Locations
        'php_dir' => array(
            'type' => 'directory',
            'default' => PEAR_CONFIG_DEFAULT_PHP_DIR,
            'doc' => 'directory where .php files are installed',
            'prompt' => 'PEAR directory',
            'group' => 'File Locations',
            ),
        'ext_dir' => array(
            'type' => 'directory',
            'default' => PEAR_CONFIG_DEFAULT_EXT_DIR,
            'doc' => 'directory where loadable extensions are installed',
            'prompt' => 'PHP extension directory',
            'group' => 'File Locations',
            ),
        'doc_dir' => array(
            'type' => 'directory',
            'default' => PEAR_CONFIG_DEFAULT_DOC_DIR,
            'doc' => 'directory where documentation is installed',
            'prompt' => 'PEAR documentation directory',
            'group' => 'File Locations',
            ),
        'bin_dir' => array(
            'type' => 'directory',
            'default' => PEAR_CONFIG_DEFAULT_BIN_DIR,
            'doc' => 'directory where executables are installed',
            'prompt' => 'PEAR executables directory',
            'group' => 'File Locations',
            ),
        'data_dir' => array(
            'type' => 'directory',
            'default' => PEAR_CONFIG_DEFAULT_DATA_DIR,
            'doc' => 'directory where data files are installed',
            'prompt' => 'PEAR data directory',
            'group' => 'File Locations (Advanced)',
            ),
        'cfg_dir' => array(
            'type' => 'directory',
            'default' => PEAR_CONFIG_DEFAULT_CFG_DIR,
            'doc' => 'directory where modifiable configuration files are installed',
            'prompt' => 'PEAR configuration file directory',
            'group' => 'File Locations (Advanced)',
            ),
        'www_dir' => array(
            'type' => 'directory',
            'default' => PEAR_CONFIG_DEFAULT_WWW_DIR,
            'doc' => 'directory where www frontend files (html/js) are installed',
            'prompt' => 'PEAR www files directory',
            'group' => 'File Locations (Advanced)',
            ),
        'man_dir' => array(
            'type' => 'directory',
            'default' => PEAR_CONFIG_DEFAULT_MAN_DIR,
            'doc' => 'directory where unix manual pages are installed',
            'prompt' => 'Systems manpage files directory',
            'group' => 'File Locations (Advanced)',
            ),
        'test_dir' => array(
            'type' => 'directory',
            'default' => PEAR_CONFIG_DEFAULT_TEST_DIR,
            'doc' => 'directory where regression tests are installed',
            'prompt' => 'PEAR test directory',
            'group' => 'File Locations (Advanced)',
            ),
        'cache_dir' => array(
            'type' => 'directory',
            'default' => PEAR_CONFIG_DEFAULT_CACHE_DIR,
            'doc' => 'directory which is used for web service cache',
            'prompt' => 'PEAR Installer cache directory',
            'group' => 'File Locations (Advanced)',
            ),
        'temp_dir' => array(
            'type' => 'directory',
            'default' => PEAR_CONFIG_DEFAULT_TEMP_DIR,
            'doc' => 'directory which is used for all temp files',
            'prompt' => 'PEAR Installer temp directory',
            'group' => 'File Locations (Advanced)',
            ),
        'download_dir' => array(
            'type' => 'directory',
            'default' => PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR,
            'doc' => 'directory which is used for all downloaded files',
            'prompt' => 'PEAR Installer download directory',
            'group' => 'File Locations (Advanced)',
            ),
        'php_bin' => array(
            'type' => 'file',
            'default' => PEAR_CONFIG_DEFAULT_PHP_BIN,
            'doc' => 'PHP CLI/CGI binary for executing scripts',
            'prompt' => 'PHP CLI/CGI binary',
            'group' => 'File Locations (Advanced)',
            ),
        'php_prefix' => array(
            'type' => 'string',
            'default' => '',
            'doc' => '--program-prefix for php_bin\'s ./configure, used for pecl installs',
            'prompt' => '--program-prefix passed to PHP\'s ./configure',
            'group' => 'File Locations (Advanced)',
            ),
        'php_suffix' => array(
            'type' => 'string',
            'default' => '',
            'doc' => '--program-suffix for php_bin\'s ./configure, used for pecl installs',
            'prompt' => '--program-suffix passed to PHP\'s ./configure',
            'group' => 'File Locations (Advanced)',
            ),
        'php_ini' => array(
            'type' => 'file',
            'default' => '',
            'doc' => 'location of php.ini in which to enable PECL extensions on install',
            'prompt' => 'php.ini location',
            'group' => 'File Locations (Advanced)',
            ),
        'metadata_dir' => array(
            'type' => 'directory',
            'default' => PEAR_CONFIG_DEFAULT_METADATA_DIR,
            'doc' => 'directory where metadata files are installed (registry, filemap, channels, ...)',
            'prompt' => 'PEAR metadata directory',
            'group' => 'File Locations (Advanced)',
            ),
        // Maintainers
        'username' => array(
            'type' => 'string',
            'default' => '',
            'doc' => '(maintainers) your PEAR account name',
            'prompt' => 'PEAR username (for maintainers)',
            'group' => 'Maintainers',
            ),
        'password' => array(
            'type' => 'password',
            'default' => '',
            'doc' => '(maintainers) your PEAR account password',
            'prompt' => 'PEAR password (for maintainers)',
            'group' => 'Maintainers',
            ),
        // Advanced
        'verbose' => array(
            'type' => 'integer',
            'default' => PEAR_CONFIG_DEFAULT_VERBOSE,
            'doc' => 'verbosity level
0: really quiet
1: somewhat quiet
2: verbose
3: debug',
            'prompt' => 'Debug Log Level',
            'group' => 'Advanced',
            ),
        'preferred_state' => array(
            'type' => 'set',
            'default' => PEAR_CONFIG_DEFAULT_PREFERRED_STATE,
            'doc' => 'the installer will prefer releases with this state when installing packages without a version or state specified',
            'valid_set' => array(
                'stable', 'beta', 'alpha', 'devel', 'snapshot'),
            'prompt' => 'Preferred Package State',
            'group' => 'Advanced',
            ),
        'umask' => array(
            'type' => 'mask',
            'default' => PEAR_CONFIG_DEFAULT_UMASK,
            'doc' => 'umask used when creating files (Unix-like systems only)',
            'prompt' => 'Unix file mask',
            'group' => 'Advanced',
            ),
        'cache_ttl' => array(
            'type' => 'integer',
            'default' => PEAR_CONFIG_DEFAULT_CACHE_TTL,
            'doc' => 'amount of secs where the local cache is used and not updated',
            'prompt' => 'Cache TimeToLive',
            'group' => 'Advanced',
            ),
        'sig_type' => array(
            'type' => 'set',
            'default' => PEAR_CONFIG_DEFAULT_SIG_TYPE,
            'doc' => 'which package signature mechanism to use',
            'valid_set' => array('gpg'),
            'prompt' => 'Package Signature Type',
            'group' => 'Maintainers',
            ),
        'sig_bin' => array(
            'type' => 'string',
            'default' => PEAR_CONFIG_DEFAULT_SIG_BIN,
            'doc' => 'which package signature mechanism to use',
            'prompt' => 'Signature Handling Program',
            'group' => 'Maintainers',
            ),
        'sig_keyid' => array(
            'type' => 'string',
            'default' => '',
            'doc' => 'which key to use for signing with',
            'prompt' => 'Signature Key Id',
            'group' => 'Maintainers',
            ),
        'sig_keydir' => array(
            'type' => 'directory',
            'default' => PEAR_CONFIG_DEFAULT_SIG_KEYDIR,
            'doc' => 'directory where signature keys are located',
            'prompt' => 'Signature Key Directory',
            'group' => 'Maintainers',
            ),
        // __channels is reserved - used for channel-specific configuration
        );

    /**
     * Constructor.
     *
     * @param string file to read user-defined options from
     * @param string file to read system-wide defaults from
     * @param bool   determines whether a registry object "follows"
     *               the value of php_dir (is automatically created
     *               and moved when php_dir is changed)
     * @param bool   if true, fails if configuration files cannot be loaded
     *
     * @access public
     *
     * @see PEAR_Config::singleton
     */
    function __construct($user_file = '', $system_file = '', $ftp_file = false,
                         $strict = true)
    {
        parent::__construct();
        PEAR_Installer_Role::initializeConfig($this);
        $sl = DIRECTORY_SEPARATOR;
        if (empty($user_file)) {
            if (OS_WINDOWS) {
                $user_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini';
            } else {
                $user_file = getenv('HOME') . $sl . '.pearrc';
            }
        }

        if (empty($system_file)) {
            $system_file = PEAR_CONFIG_SYSCONFDIR . $sl;
            if (OS_WINDOWS) {
                $system_file .= 'pearsys.ini';
            } else {
                $system_file .= 'pear.conf';
            }
        }

        $this->layers = array_keys($this->configuration);
        $this->files['user']   = $user_file;
        $this->files['system'] = $system_file;
        if ($user_file && file_exists($user_file)) {
            $this->pushErrorHandling(PEAR_ERROR_RETURN);
            $this->readConfigFile($user_file, 'user', $strict);
            $this->popErrorHandling();
            if ($this->_errorsFound > 0) {
                return;
            }
        }

        if ($system_file && @file_exists($system_file)) {
            $this->mergeConfigFile($system_file, false, 'system', $strict);
            if ($this->_errorsFound > 0) {
                return;
            }

        }

        if (!$ftp_file) {
            $ftp_file = $this->get('remote_config');
        }

        if ($ftp_file && defined('PEAR_REMOTEINSTALL_OK')) {
            $this->readFTPConfigFile($ftp_file);
        }

        foreach ($this->configuration_info as $key => $info) {
            $this->configuration['default'][$key] = $info['default'];
        }

        $this->_registry['default'] = new PEAR_Registry(
            $this->configuration['default']['php_dir'], false, false,
            $this->configuration['default']['metadata_dir']);
        $this->_registry['default']->setConfig($this, false);
        $this->_regInitialized['default'] = false;
        //$GLOBALS['_PEAR_Config_instance'] = &$this;
    }

    /**
     * Return the default locations of user and system configuration files
     */
    public static function getDefaultConfigFiles()
    {
        $sl = DIRECTORY_SEPARATOR;
        if (OS_WINDOWS) {
            return array(
                'user'   => PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini',
                'system' =>  PEAR_CONFIG_SYSCONFDIR . $sl . 'pearsys.ini'
            );
        }

        return array(
            'user'   => getenv('HOME') . $sl . '.pearrc',
            'system' => PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.conf'
        );
    }

    /**
     * Static singleton method.  If you want to keep only one instance
     * of this class in use, this method will give you a reference to
     * the last created PEAR_Config object if one exists, or create a
     * new object.
     *
     * @param string (optional) file to read user-defined options from
     * @param string (optional) file to read system-wide defaults from
     *
     * @return object an existing or new PEAR_Config instance
     *
     * @see PEAR_Config::PEAR_Config
     */
    public static function &singleton($user_file = '', $system_file = '', $strict = true)
    {
        if (is_object($GLOBALS['_PEAR_Config_instance'])) {
            return $GLOBALS['_PEAR_Config_instance'];
        }

        $t_conf = new PEAR_Config($user_file, $system_file, false, $strict);
        if ($t_conf->_errorsFound > 0) {
             return $t_conf->_lastError;
        }

        $GLOBALS['_PEAR_Config_instance'] = &$t_conf;
        return $GLOBALS['_PEAR_Config_instance'];
    }

    /**
     * Determine whether any configuration files have been detected, and whether a
     * registry object can be retrieved from this configuration.
     * @return bool
     * @since PEAR 1.4.0a1
     */
    function validConfiguration()
    {
        if ($this->isDefinedLayer('user') || $this->isDefinedLayer('system')) {
            return true;
        }

        return false;
    }

    /**
     * Reads configuration data from a file.  All existing values in
     * the config layer are discarded and replaced with data from the
     * file.
     * @param string file to read from, if NULL or not specified, the
     *               last-used file for the same layer (second param) is used
     * @param string config layer to insert data into ('user' or 'system')
     * @return bool TRUE on success or a PEAR error on failure
     */
    function readConfigFile($file = null, $layer = 'user', $strict = true)
    {
        if (empty($this->files[$layer])) {
            return $this->raiseError("unknown config layer `$layer'");
        }

        if ($file === null) {
            $file = $this->files[$layer];
        }

        $data = $this->_readConfigDataFrom($file);
        if (PEAR::isError($data)) {
            if (!$strict) {
                return true;
            }

            $this->_errorsFound++;
            $this->_lastError = $data;

            return $data;
        }

        $this->files[$layer] = $file;
        $this->_decodeInput($data);
        $this->configuration[$layer] = $data;
        $this->_setupChannels();
        if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) {
            $this->_registry[$layer] = new PEAR_Registry(
                $phpdir, false, false,
                $this->get('metadata_dir', $layer, 'pear.php.net'));
            $this->_registry[$layer]->setConfig($this, false);
            $this->_regInitialized[$layer] = false;
        } else {
            unset($this->_registry[$layer]);
        }
        return true;
    }

    /**
     * @param string url to the remote config file, like ftp://www.example.com/pear/config.ini
     * @return true|PEAR_Error
     */
    function readFTPConfigFile($path)
    {
        do { // poor man's try
            if (!class_exists('PEAR_FTP')) {
                if (!class_exists('PEAR_Common')) {
                    require_once 'PEAR/Common.php';
                }
                if (PEAR_Common::isIncludeable('PEAR/FTP.php')) {
                    require_once 'PEAR/FTP.php';
                }
            }

            if (!class_exists('PEAR_FTP')) {
                return PEAR::raiseError('PEAR_RemoteInstaller must be installed to use remote config');
            }

            $this->_ftp = new PEAR_FTP;
            $this->_ftp->pushErrorHandling(PEAR_ERROR_RETURN);
            $e = $this->_ftp->init($path);
            if (PEAR::isError($e)) {
                $this->_ftp->popErrorHandling();
                return $e;
            }

            $tmp = System::mktemp('-d');
            PEAR_Common::addTempFile($tmp);
            $e = $this->_ftp->get(basename($path), $tmp . DIRECTORY_SEPARATOR .
                'pear.ini', false, FTP_BINARY);
            if (PEAR::isError($e)) {
                $this->_ftp->popErrorHandling();
                return $e;
            }

            PEAR_Common::addTempFile($tmp . DIRECTORY_SEPARATOR . 'pear.ini');
            $this->_ftp->disconnect();
            $this->_ftp->popErrorHandling();
            $this->files['ftp'] = $tmp . DIRECTORY_SEPARATOR . 'pear.ini';
            $e = $this->readConfigFile(null, 'ftp');
            if (PEAR::isError($e)) {
                return $e;
            }

            $fail = array();
            foreach ($this->configuration_info as $key => $val) {
                if (in_array($this->getGroup($key),
                      array('File Locations', 'File Locations (Advanced)')) &&
                      $this->getType($key) == 'directory') {
                    // any directory configs must be set for this to work
                    if (!isset($this->configuration['ftp'][$key])) {
                        $fail[] = $key;
                    }
                }
            }

            if (!count($fail)) {
                return true;
            }

            $fail = '"' . implode('", "', $fail) . '"';
            unset($this->files['ftp']);
            unset($this->configuration['ftp']);
            return PEAR::raiseError('ERROR: Ftp configuration file must set all ' .
                'directory configuration variables.  These variables were not set: ' .
                $fail);
        } while (false); // poor man's catch
        unset($this->files['ftp']);
        return PEAR::raiseError('no remote host specified');
    }

    /**
     * Reads the existing configurations and creates the _channels array from it
     */
    function _setupChannels()
    {
        $set = array_flip(array_values($this->_channels));
        foreach ($this->configuration as $layer => $data) {
            $i = 1000;
            if (isset($data['__channels']) && is_array($data['__channels'])) {
                foreach ($data['__channels'] as $channel => $info) {
                    $set[$channel] = $i++;
                }
            }
        }
        $this->_channels = array_values(array_flip($set));
        $this->setChannels($this->_channels);
    }

    function deleteChannel($channel)
    {
        $ch = strtolower($channel);
        foreach ($this->configuration as $layer => $data) {
            if (isset($data['__channels']) && isset($data['__channels'][$ch])) {
                unset($this->configuration[$layer]['__channels'][$ch]);
            }
        }

        $this->_channels = array_flip($this->_channels);
        unset($this->_channels[$ch]);
        $this->_channels = array_flip($this->_channels);
    }

    /**
     * Merges data into a config layer from a file.  Does the same
     * thing as readConfigFile, except it does not replace all
     * existing values in the config layer.
     * @param string file to read from
     * @param bool whether to overwrite existing data (default TRUE)
     * @param string config layer to insert data into ('user' or 'system')
     * @param string if true, errors are returned if file opening fails
     * @return bool TRUE on success or a PEAR error on failure
     */
    function mergeConfigFile($file, $override = true, $layer = 'user', $strict = true)
    {
        if (empty($this->files[$layer])) {
            return $this->raiseError("unknown config layer `$layer'");
        }

        if ($file === null) {
            $file = $this->files[$layer];
        }

        $data = $this->_readConfigDataFrom($file);
        if (PEAR::isError($data)) {
            if (!$strict) {
                return true;
            }

            $this->_errorsFound++;
            $this->_lastError = $data;

            return $data;
        }

        $this->_decodeInput($data);
        if ($override) {
            $this->configuration[$layer] =
                PEAR_Config::arrayMergeRecursive($this->configuration[$layer], $data);
        } else {
            $this->configuration[$layer] =
                PEAR_Config::arrayMergeRecursive($data, $this->configuration[$layer]);
        }

        $this->_setupChannels();
        if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) {
            $this->_registry[$layer] = new PEAR_Registry(
                $phpdir, false, false,
                $this->get('metadata_dir', $layer, 'pear.php.net'));
            $this->_registry[$layer]->setConfig($this, false);
            $this->_regInitialized[$layer] = false;
        } else {
            unset($this->_registry[$layer]);
        }
        return true;
    }

    /**
     * @param array
     * @param array
     * @return array
     */
    public static function arrayMergeRecursive($arr2, $arr1)
    {
        $ret = array();
        foreach ($arr2 as $key => $data) {
            if (!isset($arr1[$key])) {
                $ret[$key] = $data;
                unset($arr1[$key]);
                continue;
            }
            if (is_array($data)) {
                if (!is_array($arr1[$key])) {
                    $ret[$key] = $arr1[$key];
                    unset($arr1[$key]);
                    continue;
                }
                $ret[$key] = PEAR_Config::arrayMergeRecursive($arr1[$key], $arr2[$key]);
                unset($arr1[$key]);
            }
        }

        return array_merge($ret, $arr1);
    }

    /**
     * Writes data into a config layer from a file.
     *
     * @param string|null file to read from, or null for default
     * @param string config layer to insert data into ('user' or
     *               'system')
     * @param string|null data to write to config file or null for internal data [DEPRECATED]
     * @return bool TRUE on success or a PEAR error on failure
     */
    function writeConfigFile($file = null, $layer = 'user', $data = null)
    {
        $this->_lazyChannelSetup($layer);
        if ($layer == 'both' || $layer == 'all') {
            foreach ($this->files as $type => $file) {
                $err = $this->writeConfigFile($file, $type, $data);
                if (PEAR::isError($err)) {
                    return $err;
                }
            }
            return true;
        }

        if (empty($this->files[$layer])) {
            return $this->raiseError("unknown config file type `$layer'");
        }

        if ($file === null) {
            $file = $this->files[$layer];
        }

        $data = ($data === null) ? $this->configuration[$layer] : $data;
        $this->_encodeOutput($data);
        $opt = array('-p', dirname($file));
        if (!@System::mkDir($opt)) {
            return $this->raiseError("could not create directory: " . dirname($file));
        }

        if (file_exists($file) && is_file($file) && !is_writeable($file)) {
            return $this->raiseError("no write access to $file!");
        }

        $fp = @fopen($file, "w");
        if (!$fp) {
            return $this->raiseError("PEAR_Config::writeConfigFile fopen('$file','w') failed ($php_errormsg)");
        }

        $contents = "#PEAR_Config 0.9\n" . serialize($data);
        if (!@fwrite($fp, $contents)) {
            return $this->raiseError("PEAR_Config::writeConfigFile: fwrite failed ($php_errormsg)");
        }
        return true;
    }

    /**
     * Reads configuration data from a file and returns the parsed data
     * in an array.
     *
     * @param string file to read from
     * @return array configuration data or a PEAR error on failure
     * @access private
     */
    function _readConfigDataFrom($file)
    {
        $fp = false;
        if (file_exists($file)) {
            $fp = @fopen($file, "r");
        }

        if (!$fp) {
            return $this->raiseError("PEAR_Config::readConfigFile fopen('$file','r') failed");
        }

        $size = filesize($file);
        fclose($fp);
        $contents = file_get_contents($file);
        if (empty($contents)) {
            return $this->raiseError('Configuration file "' . $file . '" is empty');
        }

        $version = false;
        if (preg_match('/^#PEAR_Config\s+(\S+)\s+/si', $contents, $matches)) {
            $version = $matches[1];
            $contents = substr($contents, strlen($matches[0]));
        } else {
            // Museum config file
            if (substr($contents,0,2) == 'a:') {
                $version = '0.1';
            }
        }

        if ($version && version_compare("$version", '1', '<')) {
            $data = @unserialize($contents);

            if (!is_array($data) && !$data) {
                if ($contents == serialize(false)) {
                    $data = array();
                } else {
                    $err = $this->raiseError("PEAR_Config: bad data in $file");
                    return $err;
                }
            }
            if (!is_array($data)) {
                if (strlen(trim($contents)) > 0) {
                    $error = "PEAR_Config: bad data in $file";
                    $err = $this->raiseError($error);
                    return $err;
                }

                $data = array();
            }
        // add parsing of newer formats here...
        } else {
            $err = $this->raiseError("$file: unknown version `$version'");
            return $err;
        }

        return $data;
    }

    /**
    * Gets the file used for storing the config for a layer
    *
    * @param string $layer 'user' or 'system'
    */
    function getConfFile($layer)
    {
        return $this->files[$layer];
    }

    /**
     * @param string Configuration class name, used for detecting duplicate calls
     * @param array information on a role as parsed from its xml file
     * @return true|PEAR_Error
     * @access private
     */
    function _addConfigVars($class, $vars)
    {
        static $called = array();
        if (isset($called[$class])) {
            return;
        }

        $called[$class] = 1;
        if (count($vars) > 3) {
            return $this->raiseError('Roles can only define 3 new config variables or less');
        }

        foreach ($vars as $name => $var) {
            if (!is_array($var)) {
                return $this->raiseError('Configuration information must be an array');
            }

            if (!isset($var['type'])) {
                return $this->raiseError('Configuration information must contain a type');
            } elseif (!in_array($var['type'],
                    array('string', 'mask', 'password', 'directory', 'file', 'set'))) {
                  return $this->raiseError(
                      'Configuration type must be one of directory, file, string, ' .
                      'mask, set, or password');
            }
            if (!isset($var['default'])) {
                return $this->raiseError(
                    'Configuration information must contain a default value ("default" index)');
            }

            if (is_array($var['default'])) {
                $real_default = '';
                foreach ($var['default'] as $config_var => $val) {
                    if (strpos($config_var, 'text') === 0) {
                        $real_default .= $val;
                    } elseif (strpos($config_var, 'constant') === 0) {
                        if (!defined($val)) {
                            return $this->raiseError(
                                'Unknown constant "' . $val . '" requested in ' .
                                'default value for configuration variable "' .
                                $name . '"');
                        }

                        $real_default .= constant($val);
                    } elseif (isset($this->configuration_info[$config_var])) {
                        $real_default .=
                            $this->configuration_info[$config_var]['default'];
                    } else {
                        return $this->raiseError(
                            'Unknown request for "' . $config_var . '" value in ' .
                            'default value for configuration variable "' .
                            $name . '"');
                    }
                }
                $var['default'] = $real_default;
            }

            if ($var['type'] == 'integer') {
                $var['default'] = (integer) $var['default'];
            }

            if (!isset($var['doc'])) {
                return $this->raiseError(
                    'Configuration information must contain a summary ("doc" index)');
            }

            if (!isset($var['prompt'])) {
                return $this->raiseError(
                    'Configuration information must contain a simple prompt ("prompt" index)');
            }

            if (!isset($var['group'])) {
                return $this->raiseError(
                    'Configuration information must contain a simple group ("group" index)');
            }

            if (isset($this->configuration_info[$name])) {
                return $this->raiseError('Configuration variable "' . $name .
                    '" already exists');
            }

            $this->configuration_info[$name] = $var;
            // fix bug #7351: setting custom config variable in a channel fails
            $this->_channelConfigInfo[] = $name;
        }

        return true;
    }

    /**
     * Encodes/scrambles configuration data before writing to files.
     * Currently, 'password' values will be base64-encoded as to avoid
     * that people spot cleartext passwords by accident.
     *
     * @param array (reference) array to encode values in
     * @return bool TRUE on success
     * @access private
     */
    function _encodeOutput(&$data)
    {
        foreach ($data as $key => $value) {
            if ($key == '__channels') {
                foreach ($data['__channels'] as $channel => $blah) {
                    $this->_encodeOutput($data['__channels'][$channel]);
                }
            }

            if (!isset($this->configuration_info[$key])) {
                continue;
            }

            $type = $this->configuration_info[$key]['type'];
            switch ($type) {
                // we base64-encode passwords so they are at least
                // not shown in plain by accident
                case 'password': {
                    $data[$key] = base64_encode($data[$key]);
                    break;
                }
                case 'mask': {
                    $data[$key] = octdec($data[$key]);
                    break;
                }
            }
        }

        return true;
    }

    /**
     * Decodes/unscrambles configuration data after reading from files.
     *
     * @param array (reference) array to encode values in
     * @return bool TRUE on success
     * @access private
     *
     * @see PEAR_Config::_encodeOutput
     */
    function _decodeInput(&$data)
    {
        if (!is_array($data)) {
            return true;
        }

        foreach ($data as $key => $value) {
            if ($key == '__channels') {
                foreach ($data['__channels'] as $channel => $blah) {
                    $this->_decodeInput($data['__channels'][$channel]);
                }
            }

            if (!isset($this->configuration_info[$key])) {
                continue;
            }

            $type = $this->configuration_info[$key]['type'];
            switch ($type) {
                case 'password': {
                    $data[$key] = base64_decode($data[$key]);
                    break;
                }
                case 'mask': {
                    $data[$key] = decoct($data[$key]);
                    break;
                }
            }
        }

        return true;
    }

    /**
     * Retrieve the default channel.
     *
     * On startup, channels are not initialized, so if the default channel is not
     * pear.php.net, then initialize the config.
     * @param string registry layer
     * @return string|false
     */
    function getDefaultChannel($layer = null)
    {
        $ret = false;
        if ($layer === null) {
            foreach ($this->layers as $layer) {
                if (isset($this->configuration[$layer]['default_channel'])) {
                    $ret = $this->configuration[$layer]['default_channel'];
                    break;
                }
            }
        } elseif (isset($this->configuration[$layer]['default_channel'])) {
            $ret = $this->configuration[$layer]['default_channel'];
        }

        if ($ret == 'pear.php.net' && defined('PEAR_RUNTYPE') && PEAR_RUNTYPE == 'pecl') {
            $ret = 'pecl.php.net';
        }

        if ($ret) {
            if ($ret != 'pear.php.net') {
                $this->_lazyChannelSetup();
            }

            return $ret;
        }

        return PEAR_CONFIG_DEFAULT_CHANNEL;
    }

    /**
     * Returns a configuration value, prioritizing layers as per the
     * layers property.
     *
     * @param string config key
     * @return mixed the config value, or NULL if not found
     * @access public
     */
    function get($key, $layer = null, $channel = false)
    {
        if (!isset($this->configuration_info[$key])) {
            return null;
        }

        if ($key == '__channels') {
            return null;
        }

        if ($key == 'default_channel') {
            return $this->getDefaultChannel($layer);
        }

        if (!$channel) {
            $channel = $this->getDefaultChannel();
        } elseif ($channel != 'pear.php.net') {
            $this->_lazyChannelSetup();
        }
        $channel = strtolower($channel);

        $test = (in_array($key, $this->_channelConfigInfo)) ?
            $this->_getChannelValue($key, $layer, $channel) :
            null;
        if ($test !== null) {
            if ($this->_installRoot) {
                if (in_array($this->getGroup($key),
                      array('File Locations', 'File Locations (Advanced)')) &&
                      $this->getType($key) == 'directory') {
                    return $this->_prependPath($test, $this->_installRoot);
                }
            }
            return $test;
        }

        if ($layer === null) {
            foreach ($this->layers as $layer) {
                if (isset($this->configuration[$layer][$key])) {
                    $test = $this->configuration[$layer][$key];
                    if ($this->_installRoot) {
                        if (in_array($this->getGroup($key),
                              array('File Locations', 'File Locations (Advanced)')) &&
                              $this->getType($key) == 'directory') {
                            return $this->_prependPath($test, $this->_installRoot);
                        }
                    }

                    if ($key == 'preferred_mirror') {
                        $reg = &$this->getRegistry();
                        if (is_object($reg)) {
                            $chan = $reg->getChannel($channel);
                            if (PEAR::isError($chan)) {
                                return $channel;
                            }

                            if (!$chan->getMirror($test) && $chan->getName() != $test) {
                                return $channel; // mirror does not exist
                            }
                        }
                    }
                    return $test;
                }
            }
        } elseif (isset($this->configuration[$layer][$key])) {
            $test = $this->configuration[$layer][$key];
            if ($this->_installRoot) {
                if (in_array($this->getGroup($key),
                      array('File Locations', 'File Locations (Advanced)')) &&
                      $this->getType($key) == 'directory') {
                    return $this->_prependPath($test, $this->_installRoot);
                }
            }

            if ($key == 'preferred_mirror') {
                $reg = &$this->getRegistry();
                if (is_object($reg)) {
                    $chan = $reg->getChannel($channel);
                    if (PEAR::isError($chan)) {
                        return $channel;
                    }

                    if (!$chan->getMirror($test) && $chan->getName() != $test) {
                        return $channel; // mirror does not exist
                    }
                }
            }

            return $test;
        }

        return null;
    }

    /**
     * Returns a channel-specific configuration value, prioritizing layers as per the
     * layers property.
     *
     * @param string config key
     * @return mixed the config value, or NULL if not found
     * @access private
     */
    function _getChannelValue($key, $layer, $channel)
    {
        if ($key == '__channels' || $channel == 'pear.php.net') {
            return null;
        }

        $ret = null;
        if ($layer === null) {
            foreach ($this->layers as $ilayer) {
                if (isset($this->configuration[$ilayer]['__channels'][$channel][$key])) {
                    $ret = $this->configuration[$ilayer]['__channels'][$channel][$key];
                    break;
                }
            }
        } elseif (isset($this->configuration[$layer]['__channels'][$channel][$key])) {
            $ret = $this->configuration[$layer]['__channels'][$channel][$key];
        }

        if ($key != 'preferred_mirror') {
            return $ret;
        }


        if ($ret !== null) {
            $reg = &$this->getRegistry($layer);
            if (is_object($reg)) {
                $chan = $reg->getChannel($channel);
                if (PEAR::isError($chan)) {
                    return $channel;
                }

                if (!$chan->getMirror($ret) && $chan->getName() != $ret) {
                    return $channel; // mirror does not exist
                }
            }

            return $ret;
        }

        if ($channel != $this->getDefaultChannel($layer)) {
            return $channel; // we must use the channel name as the preferred mirror
                             // if the user has not chosen an alternate
        }

        return $this->getDefaultChannel($layer);
    }

    /**
     * Set a config value in a specific layer (defaults to 'user').
     * Enforces the types defined in the configuration_info array.  An
     * integer config variable will be cast to int, and a set config
     * variable will be validated against its legal values.
     *
     * @param string config key
     * @param string config value
     * @param string (optional) config layer
     * @param string channel to set this value for, or null for global value
     * @return bool TRUE on success, FALSE on failure
     */
    function set($key, $value, $layer = 'user', $channel = false)
    {
        if ($key == '__channels') {
            return false;
        }

        if (!isset($this->configuration[$layer])) {
            return false;
        }

        if ($key == 'default_channel') {
            // can only set this value globally
            $channel = 'pear.php.net';
            if ($value != 'pear.php.net') {
                $this->_lazyChannelSetup($layer);
            }
        }

        if ($key == 'preferred_mirror') {
            if ($channel == '__uri') {
                return false; // can't set the __uri pseudo-channel's mirror
            }

            $reg = &$this->getRegistry($layer);
            if (is_object($reg)) {
                $chan = $reg->getChannel($channel ? $channel : 'pear.php.net');
                if (PEAR::isError($chan)) {
                    return false;
                }

                if (!$chan->getMirror($value) && $chan->getName() != $value) {
                    return false; // mirror does not exist
                }
            }
        }

        if (!isset($this->configuration_info[$key])) {
            return false;
        }

        extract($this->configuration_info[$key]);
        switch ($type) {
            case 'integer':
                $value = (int)$value;
                break;
            case 'set': {
                // If a valid_set is specified, require the value to
                // be in the set.  If there is no valid_set, accept
                // any value.
                if ($valid_set) {
                    reset($valid_set);
                    if ((key($valid_set) === 0 && !in_array($value, $valid_set)) ||
                        (key($valid_set) !== 0 && empty($valid_set[$value])))
                    {
                        return false;
                    }
                }
                break;
            }
        }

        if (!$channel) {
            $channel = $this->get('default_channel', null, 'pear.php.net');
        }

        if (!in_array($channel, $this->_channels)) {
            $this->_lazyChannelSetup($layer);
            $reg = &$this->getRegistry($layer);
            if ($reg) {
                $channel = $reg->channelName($channel);
            }

            if (!in_array($channel, $this->_channels)) {
                return false;
            }
        }

        if ($channel != 'pear.php.net') {
            if (in_array($key, $this->_channelConfigInfo)) {
                $this->configuration[$layer]['__channels'][$channel][$key] = $value;
                return true;
            }

            return false;
        }

        if ($key == 'default_channel') {
            if (!isset($reg)) {
                $reg = &$this->getRegistry($layer);
                if (!$reg) {
                    $reg = &$this->getRegistry();
                }
            }

            if ($reg) {
                $value = $reg->channelName($value);
            }

            if (!$value) {
                return false;
            }
        }

        $this->configuration[$layer][$key] = $value;
        if ($key == 'php_dir' && !$this->_noRegistry) {
            if (!isset($this->_registry[$layer]) ||
                  $value != $this->_registry[$layer]->install_dir) {
                $this->_registry[$layer] = new PEAR_Registry($value);
                $this->_regInitialized[$layer] = false;
                $this->_registry[$layer]->setConfig($this, false);
            }
        }

        return true;
    }

    function _lazyChannelSetup($uselayer = false)
    {
        if ($this->_noRegistry) {
            return;
        }

        $merge = false;
        foreach ($this->_registry as $layer => $p) {
            if ($uselayer && $uselayer != $layer) {
                continue;
            }

            if (!$this->_regInitialized[$layer]) {
                if ($layer == 'default' && isset($this->_registry['user']) ||
                      isset($this->_registry['system'])) {
                    // only use the default registry if there are no alternatives
                    continue;
                }

                if (!is_object($this->_registry[$layer])) {
                    if ($phpdir = $this->get('php_dir', $layer, 'pear.php.net')) {
                        $this->_registry[$layer] = new PEAR_Registry(
                            $phpdir, false, false,
                            $this->get('metadata_dir', $layer, 'pear.php.net'));
                        $this->_registry[$layer]->setConfig($this, false);
                        $this->_regInitialized[$layer] = false;
                    } else {
                        unset($this->_registry[$layer]);
                        return;
                    }
                }

                $this->setChannels($this->_registry[$layer]->listChannels(), $merge);
                $this->_regInitialized[$layer] = true;
                $merge = true;
            }
        }
    }

    /**
     * Set the list of channels.
     *
     * This should be set via a call to {@link PEAR_Registry::listChannels()}
     * @param array
     * @param bool
     * @return bool success of operation
     */
    function setChannels($channels, $merge = false)
    {
        if (!is_array($channels)) {
            return false;
        }

        if ($merge) {
            $this->_channels = array_merge($this->_channels, $channels);
        } else {
            $this->_channels = $channels;
        }

        foreach ($channels as $channel) {
            $channel = strtolower($channel);
            if ($channel == 'pear.php.net') {
                continue;
            }

            foreach ($this->layers as $layer) {
                if (!isset($this->configuration[$layer]['__channels'])) {
                    $this->configuration[$layer]['__channels'] = array();
                }
                if (!isset($this->configuration[$layer]['__channels'][$channel])
                      || !is_array($this->configuration[$layer]['__channels'][$channel])) {
                    $this->configuration[$layer]['__channels'][$channel] = array();
                }
            }
        }

        return true;
    }

    /**
     * Get the type of a config value.
     *
     * @param string  config key
     *
     * @return string type, one of "string", "integer", "file",
     * "directory", "set" or "password".
     *
     * @access public
     *
     */
    function getType($key)
    {
        if (isset($this->configuration_info[$key])) {
            return $this->configuration_info[$key]['type'];
        }
        return false;
    }

    /**
     * Get the documentation for a config value.
     *
     * @param string  config key
     * @return string documentation string
     *
     * @access public
     *
     */
    function getDocs($key)
    {
        if (isset($this->configuration_info[$key])) {
            return $this->configuration_info[$key]['doc'];
        }

        return false;
    }

    /**
     * Get the short documentation for a config value.
     *
     * @param string  config key
     * @return string short documentation string
     *
     * @access public
     *
     */
    function getPrompt($key)
    {
        if (isset($this->configuration_info[$key])) {
            return $this->configuration_info[$key]['prompt'];
        }

        return false;
    }

    /**
     * Get the parameter group for a config key.
     *
     * @param string  config key
     * @return string parameter group
     *
     * @access public
     *
     */
    function getGroup($key)
    {
        if (isset($this->configuration_info[$key])) {
            return $this->configuration_info[$key]['group'];
        }

        return false;
    }

    /**
     * Get the list of parameter groups.
     *
     * @return array list of parameter groups
     *
     * @access public
     *
     */
    function getGroups()
    {
        $tmp = array();
        foreach ($this->configuration_info as $key => $info) {
            $tmp[$info['group']] = 1;
        }

        return array_keys($tmp);
    }

    /**
     * Get the list of the parameters in a group.
     *
     * @param string $group parameter group
     * @return array list of parameters in $group
     *
     * @access public
     *
     */
    function getGroupKeys($group)
    {
        $keys = array();
        foreach ($this->configuration_info as $key => $info) {
            if ($info['group'] == $group) {
                $keys[] = $key;
            }
        }

        return $keys;
    }

    /**
     * Get the list of allowed set values for a config value.  Returns
     * NULL for config values that are not sets.
     *
     * @param string  config key
     * @return array enumerated array of set values, or NULL if the
     *               config key is unknown or not a set
     *
     * @access public
     *
     */
    function getSetValues($key)
    {
        if (isset($this->configuration_info[$key]) &&
            isset($this->configuration_info[$key]['type']) &&
            $this->configuration_info[$key]['type'] == 'set')
        {
            $valid_set = $this->configuration_info[$key]['valid_set'];
            reset($valid_set);
            if (key($valid_set) === 0) {
                return $valid_set;
            }

            return array_keys($valid_set);
        }

        return null;
    }

    /**
     * Get all the current config keys.
     *
     * @return array simple array of config keys
     *
     * @access public
     */
    function getKeys()
    {
        $keys = array();
        foreach ($this->layers as $layer) {
            $test = $this->configuration[$layer];
            if (isset($test['__channels'])) {
                foreach ($test['__channels'] as $channel => $configs) {
                    $keys = array_merge($keys, $configs);
                }
            }

            unset($test['__channels']);
            $keys = array_merge($keys, $test);

        }
        return array_keys($keys);
    }

    /**
     * Remove the a config key from a specific config layer.
     *
     * @param string config key
     * @param string (optional) config layer
     * @param string (optional) channel (defaults to default channel)
     * @return bool TRUE on success, FALSE on failure
     *
     * @access public
     */
    function remove($key, $layer = 'user', $channel = null)
    {
        if ($channel === null) {
            $channel = $this->getDefaultChannel();
        }

        if ($channel !== 'pear.php.net') {
            if (isset($this->configuration[$layer]['__channels'][$channel][$key])) {
                unset($this->configuration[$layer]['__channels'][$channel][$key]);
                return true;
            }
        }

        if (isset($this->configuration[$layer][$key])) {
            unset($this->configuration[$layer][$key]);
            return true;
        }

        return false;
    }

    /**
     * Temporarily remove an entire config layer.  USE WITH CARE!
     *
     * @param string config key
     * @param string (optional) config layer
     * @return bool TRUE on success, FALSE on failure
     *
     * @access public
     */
    function removeLayer($layer)
    {
        if (isset($this->configuration[$layer])) {
            $this->configuration[$layer] = array();
            return true;
        }

        return false;
    }

    /**
     * Stores configuration data in a layer.
     *
     * @param string config layer to store
     * @return bool TRUE on success, or PEAR error on failure
     *
     * @access public
     */
    function store($layer = 'user', $data = null)
    {
        return $this->writeConfigFile(null, $layer, $data);
    }

    /**
     * Tells what config layer that gets to define a key.
     *
     * @param string config key
     * @param boolean return the defining channel
     *
     * @return string|array the config layer, or an empty string if not found.
     *
     *         if $returnchannel, the return is an array array('layer' => layername,
     *         'channel' => channelname), or an empty string if not found
     *
     * @access public
     */
    function definedBy($key, $returnchannel = false)
    {
        foreach ($this->layers as $layer) {
            $channel = $this->getDefaultChannel();
            if ($channel !== 'pear.php.net') {
                if (isset($this->configuration[$layer]['__channels'][$channel][$key])) {
                    if ($returnchannel) {
                        return array('layer' => $layer, 'channel' => $channel);
                    }
                    return $layer;
                }
            }

            if (isset($this->configuration[$layer][$key])) {
                if ($returnchannel) {
                    return array('layer' => $layer, 'channel' => 'pear.php.net');
                }
                return $layer;
            }
        }

        return '';
    }

    /**
     * Tells whether a given key exists as a config value.
     *
     * @param string config key
     * @return bool whether <config key> exists in this object
     *
     * @access public
     */
    function isDefined($key)
    {
        foreach ($this->layers as $layer) {
            if (isset($this->configuration[$layer][$key])) {
                return true;
            }
        }

        return false;
    }

    /**
     * Tells whether a given config layer exists.
     *
     * @param string config layer
     * @return bool whether <config layer> exists in this object
     *
     * @access public
     */
    function isDefinedLayer($layer)
    {
        return isset($this->configuration[$layer]);
    }

    /**
     * Returns the layers defined (except the 'default' one)
     *
     * @return array of the defined layers
     */
    function getLayers()
    {
        $cf = $this->configuration;
        unset($cf['default']);
        return array_keys($cf);
    }

    function apiVersion()
    {
        return '1.1';
    }

    /**
     * @return PEAR_Registry
     */
    function &getRegistry($use = null)
    {
        $layer = $use === null ? 'user' : $use;
        if (isset($this->_registry[$layer])) {
            return $this->_registry[$layer];
        } elseif ($use === null && isset($this->_registry['system'])) {
            return $this->_registry['system'];
        } elseif ($use === null && isset($this->_registry['default'])) {
            return $this->_registry['default'];
        } elseif ($use) {
            $a = false;
            return $a;
        }

        // only go here if null was passed in
        echo "CRITICAL ERROR: Registry could not be initialized from any value";
        exit(1);
    }

    /**
     * This is to allow customization like the use of installroot
     * @param PEAR_Registry
     * @return bool
     */
    function setRegistry(&$reg, $layer = 'user')
    {
        if ($this->_noRegistry) {
            return false;
        }

        if (!in_array($layer, array('user', 'system'))) {
            return false;
        }

        $this->_registry[$layer] = &$reg;
        if (is_object($reg)) {
            $this->_registry[$layer]->setConfig($this, false);
        }

        return true;
    }

    function noRegistry()
    {
        $this->_noRegistry = true;
    }

    /**
     * @return PEAR_REST
     */
    function &getREST($version, $options = array())
    {
        $version = str_replace('.', '', $version);
        if (!class_exists($class = 'PEAR_REST_' . $version)) {
            require_once 'PEAR/REST/' . $version . '.php';
        }

        $remote = new $class($this, $options);
        return $remote;
    }

    /**
     * The ftp server is set in {@link readFTPConfigFile()}.  It exists only if a
     * remote configuration file has been specified
     * @return PEAR_FTP|false
     */
    function &getFTP()
    {
        if (isset($this->_ftp)) {
            return $this->_ftp;
        }

        $a = false;
        return $a;
    }

    static function _prependPath($path, $prepend)
    {
        if (strlen($prepend) > 0) {
            if (OS_WINDOWS && preg_match('/^[a-z]:/i', $path)) {
                if (preg_match('/^[a-z]:/i', $prepend)) {
                    $prepend = substr($prepend, 2);
                } elseif ($prepend[0] != '\\') {
                    $prepend = "\\$prepend";
                }
                $path = substr($path, 0, 2) . $prepend . substr($path, 2);
            } else {
                $path = $prepend . $path;
            }
        }
        return $path;
    }

    /**
     * @param string|false installation directory to prepend to all _dir variables, or false to
     *                     disable
     */
    function setInstallRoot($root)
    {
        if (substr($root, -1) == DIRECTORY_SEPARATOR) {
            $root = substr($root, 0, -1);
        }
        $old = $this->_installRoot;
        $this->_installRoot = $root;
        if (($old != $root) && !$this->_noRegistry) {
            foreach (array_keys($this->_registry) as $layer) {
                if ($layer == 'ftp' || !isset($this->_registry[$layer])) {
                    continue;
                }
                $this->_registry[$layer] =
                    new PEAR_Registry(
                        $this->get('php_dir', $layer, 'pear.php.net'), false, false,
                        $this->get('metadata_dir', $layer, 'pear.php.net'));
                $this->_registry[$layer]->setConfig($this, false);
                $this->_regInitialized[$layer] = false;
            }
        }
    }
}
PKn�Z�`�eEAEA
PEAR/REST.phpnu�[���<?php
/**
 * PEAR_REST
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a1
 */

/**
 * For downloading xml files
 */
require_once 'PEAR.php';
require_once 'PEAR/XMLParser.php';
require_once 'PEAR/Proxy.php';

/**
 * Intelligently retrieve data, following hyperlinks if necessary, and re-directing
 * as well
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 */
class PEAR_REST
{
    var $config;
    var $_options;

    function __construct(&$config, $options = array())
    {
        $this->config   = &$config;
        $this->_options = $options;
    }

    /**
     * Retrieve REST data, but always retrieve the local cache if it is available.
     *
     * This is useful for elements that should never change, such as information on a particular
     * release
     * @param string full URL to this resource
     * @param array|false contents of the accept-encoding header
     * @param boolean     if true, xml will be returned as a string, otherwise, xml will be
     *                    parsed using PEAR_XMLParser
     * @return string|array
     */
    function retrieveCacheFirst($url, $accept = false, $forcestring = false, $channel = false)
    {
        $cachefile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
            md5($url) . 'rest.cachefile';

        if (file_exists($cachefile)) {
            return unserialize(implode('', file($cachefile)));
        }

        return $this->retrieveData($url, $accept, $forcestring, $channel);
    }

    /**
     * Retrieve a remote REST resource
     * @param string full URL to this resource
     * @param array|false contents of the accept-encoding header
     * @param boolean     if true, xml will be returned as a string, otherwise, xml will be
     *                    parsed using PEAR_XMLParser
     * @return string|array
     */
    function retrieveData($url, $accept = false, $forcestring = false, $channel = false)
    {
        $cacheId = $this->getCacheId($url);
        if ($ret = $this->useLocalCache($url, $cacheId)) {
            return $ret;
        }

        $file = $trieddownload = false;
        if (!isset($this->_options['offline'])) {
            $trieddownload = true;
            $file = $this->downloadHttp($url, $cacheId ? $cacheId['lastChange'] : false, $accept, $channel);
        }

        if (PEAR::isError($file)) {
            if ($file->getCode() !== -9276) {
                return $file;
            }

            $trieddownload = false;
            $file = false; // use local copy if available on socket connect error
        }

        if (!$file) {
            $ret = $this->getCache($url);
            if (!PEAR::isError($ret) && $trieddownload) {
                // reset the age of the cache if the server says it was unmodified
                $result = $this->saveCache($url, $ret, null, true, $cacheId);
                if (PEAR::isError($result)) {
                    return PEAR::raiseError($result->getMessage());
                }
            }

            return $ret;
        }

        if (is_array($file)) {
            $headers      = $file[2];
            $lastmodified = $file[1];
            $content      = $file[0];
        } else {
            $headers      = array();
            $lastmodified = false;
            $content      = $file;
        }

        if ($forcestring) {
            $result = $this->saveCache($url, $content, $lastmodified, false, $cacheId);
            if (PEAR::isError($result)) {
                return PEAR::raiseError($result->getMessage());
            }

            return $content;
        }

        if (isset($headers['content-type'])) {
            $content_type = explode(";", $headers['content-type']);
            $content_type = $content_type[0];
            switch ($content_type) {
                case 'text/xml' :
                case 'application/xml' :
                case 'text/plain' :
                    if ($content_type === 'text/plain') {
                        $check = substr($content, 0, 5);
                        if ($check !== '<?xml') {
                            break;
                        }
                    }

                    $parser = new PEAR_XMLParser;
                    PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                    $err = $parser->parse($content);
                    PEAR::popErrorHandling();
                    if (PEAR::isError($err)) {
                        return PEAR::raiseError('Invalid xml downloaded from "' . $url . '": ' .
                            $err->getMessage());
                    }
                    $content = $parser->getData();
                case 'text/html' :
                default :
                    // use it as a string
            }
        } else {
            // assume XML
            $parser = new PEAR_XMLParser;
            $parser->parse($content);
            $content = $parser->getData();
        }

        $result = $this->saveCache($url, $content, $lastmodified, false, $cacheId);
        if (PEAR::isError($result)) {
            return PEAR::raiseError($result->getMessage());
        }

        return $content;
    }

    function useLocalCache($url, $cacheid = null)
    {
        if (!is_array($cacheid)) {
            $cacheid = $this->getCacheId($url);
        }

        $cachettl = $this->config->get('cache_ttl');
        // If cache is newer than $cachettl seconds, we use the cache!
        if (is_array($cacheid) && time() - $cacheid['age'] < $cachettl) {
            return $this->getCache($url);
        }

        return false;
    }

    /**
     * @param string $url
     *
     * @return bool|mixed
     */
    function getCacheId($url)
    {
        $cacheidfile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
            md5($url) . 'rest.cacheid';

        if (!file_exists($cacheidfile)) {
            return false;
        }

        $ret = unserialize(implode('', file($cacheidfile)));
        return $ret;
    }

    function getCache($url)
    {
        $cachefile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
            md5($url) . 'rest.cachefile';

        if (!file_exists($cachefile)) {
            return PEAR::raiseError('No cached content available for "' . $url . '"');
        }

        return unserialize(implode('', file($cachefile)));
    }

    /**
     * @param string full URL to REST resource
     * @param string original contents of the REST resource
     * @param array  HTTP Last-Modified and ETag headers
     * @param bool   if true, then the cache id file should be regenerated to
     *               trigger a new time-to-live value
     */
    function saveCache($url, $contents, $lastmodified, $nochange = false, $cacheid = null)
    {
        $cache_dir   = $this->config->get('cache_dir');
        $d           = $cache_dir . DIRECTORY_SEPARATOR . md5($url);
        $cacheidfile = $d . 'rest.cacheid';
        $cachefile   = $d . 'rest.cachefile';

        if (!is_dir($cache_dir)) {
            if (System::mkdir(array('-p', $cache_dir)) === false) {
              return PEAR::raiseError("The value of config option cache_dir ($cache_dir) is not a directory and attempts to create the directory failed.");
            }
        }

        if (!is_writeable($cache_dir)) {
            // If writing to the cache dir is not going to work, silently do nothing.
            // An ugly hack, but retains compat with PEAR 1.9.1 where many commands
            // work fine as non-root user (w/out write access to default cache dir).
            return true;
        }

        if ($cacheid === null && $nochange) {
            $cacheid = unserialize(implode('', file($cacheidfile)));
        }

        $idData = serialize(array(
            'age'        => time(),
            'lastChange' => ($nochange ? $cacheid['lastChange'] : $lastmodified),
        ));

        $result = $this->saveCacheFile($cacheidfile, $idData);
        if (PEAR::isError($result)) {
            return $result;
        } elseif ($nochange) {
            return true;
        }

        $result = $this->saveCacheFile($cachefile, serialize($contents));
        if (PEAR::isError($result)) {
            if (file_exists($cacheidfile)) {
              @unlink($cacheidfile);
            }

            return $result;
        }

        return true;
    }

    function saveCacheFile($file, $contents)
    {
        $len = strlen($contents);

        $cachefile_fp = @fopen($file, 'xb'); // x is the O_CREAT|O_EXCL mode
        if ($cachefile_fp !== false) { // create file
            if (fwrite($cachefile_fp, $contents, $len) < $len) {
                fclose($cachefile_fp);
                return PEAR::raiseError("Could not write $file.");
            }
        } else { // update file
            $cachefile_fp = @fopen($file, 'r+b'); // do not truncate file
            if (!$cachefile_fp) {
                return PEAR::raiseError("Could not open $file for writing.");
            }

            if (OS_WINDOWS) {
                $not_symlink     = !is_link($file); // see bug #18834
            } else {
                $cachefile_lstat = lstat($file);
                $cachefile_fstat = fstat($cachefile_fp);
                $not_symlink     = $cachefile_lstat['mode'] == $cachefile_fstat['mode']
                                   && $cachefile_lstat['ino']  == $cachefile_fstat['ino']
                                   && $cachefile_lstat['dev']  == $cachefile_fstat['dev']
                                   && $cachefile_fstat['nlink'] === 1;
            }

            if ($not_symlink) {
                ftruncate($cachefile_fp, 0); // NOW truncate
                if (fwrite($cachefile_fp, $contents, $len) < $len) {
                    fclose($cachefile_fp);
                    return PEAR::raiseError("Could not write $file.");
                }
            } else {
                fclose($cachefile_fp);
                $link = function_exists('readlink') ? readlink($file) : $file;
                return PEAR::raiseError('SECURITY ERROR: Will not write to ' . $file . ' as it is symlinked to ' . $link . ' - Possible symlink attack');
            }
        }

        fclose($cachefile_fp);
        return true;
    }

    /**
     * Efficiently Download a file through HTTP.  Returns downloaded file as a string in-memory
     * This is best used for small files
     *
     * If an HTTP proxy has been configured (http_proxy PEAR_Config
     * setting), the proxy will be used.
     *
     * @param string  $url       the URL to download
     * @param string  $save_dir  directory to save file in
     * @param false|string|array $lastmodified header values to check against for caching
     *                           use false to return the header values from this download
     * @param false|array $accept Accept headers to send
     * @return string|array  Returns the contents of the downloaded file or a PEAR
     *                       error on failure.  If the error is caused by
     *                       socket-related errors, the error object will
     *                       have the fsockopen error code available through
     *                       getCode().  If caching is requested, then return the header
     *                       values.
     *
     * @access public
     */
    function downloadHttp($url, $lastmodified = null, $accept = false, $channel = false)
    {
        static $redirect = 0;
        // always reset , so we are clean case of error
        $wasredirect = $redirect;
        $redirect = 0;

        $info = parse_url($url);
        if (!isset($info['scheme']) || !in_array($info['scheme'], array('http', 'https'))) {
            return PEAR::raiseError('Cannot download non-http URL "' . $url . '"');
        }

        if (!isset($info['host'])) {
            return PEAR::raiseError('Cannot download from non-URL "' . $url . '"');
        }

        $host   = isset($info['host']) ? $info['host'] : null;
        $port   = isset($info['port']) ? $info['port'] : null;
        $path   = isset($info['path']) ? $info['path'] : null;
        $schema = (isset($info['scheme']) && $info['scheme'] == 'https') ? 'https' : 'http';

        $proxy = new PEAR_Proxy($this->config);

        if (empty($port)) {
            $port = (isset($info['scheme']) && $info['scheme'] == 'https')  ? 443 : 80;
        }

        if ($proxy->isProxyConfigured() && $schema === 'http') {
            $request = "GET $url HTTP/1.1\r\n";
        } else {
            $request = "GET $path HTTP/1.1\r\n";
        }

        $request .= "Host: $host\r\n";
        $ifmodifiedsince = '';
        if (is_array($lastmodified)) {
            if (isset($lastmodified['Last-Modified'])) {
                $ifmodifiedsince = 'If-Modified-Since: ' . $lastmodified['Last-Modified'] . "\r\n";
            }

            if (isset($lastmodified['ETag'])) {
                $ifmodifiedsince .= "If-None-Match: $lastmodified[ETag]\r\n";
            }
        } else {
            $ifmodifiedsince = ($lastmodified ? "If-Modified-Since: $lastmodified\r\n" : '');
        }

        $request .= $ifmodifiedsince .
            "User-Agent: PEAR/1.10.16/PHP/" . PHP_VERSION . "\r\n";

        $username = $this->config->get('username', null, $channel);
        $password = $this->config->get('password', null, $channel);

        if ($username && $password) {
            $tmp = base64_encode("$username:$password");
            $request .= "Authorization: Basic $tmp\r\n";
        }

        $proxyAuth = $proxy->getProxyAuth();
        if ($proxyAuth) {
            $request .= 'Proxy-Authorization: Basic ' .
                $proxyAuth . "\r\n";
        }

        if ($accept) {
            $request .= 'Accept: ' . implode(', ', $accept) . "\r\n";
        }

        $request .= "Accept-Encoding:\r\n";
        $request .= "Connection: close\r\n";
        $request .= "\r\n";

        $secure = ($schema == 'https');
        $fp = $proxy->openSocket($host, $port, $secure);
        if (PEAR::isError($fp)) {
            return $fp;
        }

        fwrite($fp, $request);

        $headers = array();
        $reply   = 0;
        while ($line = trim(fgets($fp, 1024))) {
            if (preg_match('/^([^:]+):\s+(.*)\s*\\z/', $line, $matches)) {
                $headers[strtolower($matches[1])] = trim($matches[2]);
            } elseif (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) {
                $reply = (int)$matches[1];
                if ($reply == 304 && ($lastmodified || ($lastmodified === false))) {
                    return false;
                }

                if (!in_array($reply, array(200, 301, 302, 303, 305, 307))) {
                    return PEAR::raiseError("File $schema://$host:$port$path not valid (received: $line)");
                }
            }
        }

        if ($reply != 200) {
            if (!isset($headers['location'])) {
                return PEAR::raiseError("File $schema://$host:$port$path not valid (redirected but no location)");
            }

            if ($wasredirect > 4) {
                return PEAR::raiseError("File $schema://$host:$port$path not valid (redirection looped more than 5 times)");
            }

            $redirect = $wasredirect + 1;
            return $this->downloadHttp($headers['location'], $lastmodified, $accept, $channel);
        }

        $length = isset($headers['content-length']) ? $headers['content-length'] : -1;

        $data = '';
        while ($chunk = @fread($fp, 8192)) {
            $data .= $chunk;
        }
        fclose($fp);

        if ($lastmodified === false || $lastmodified) {
            if (isset($headers['etag'])) {
                $lastmodified = array('ETag' => $headers['etag']);
            }

            if (isset($headers['last-modified'])) {
                if (is_array($lastmodified)) {
                    $lastmodified['Last-Modified'] = $headers['last-modified'];
                } else {
                    $lastmodified = $headers['last-modified'];
                }
            }

            return array($data, $lastmodified, $headers);
        }

        return $data;
    }
}
PKn�Z��ym6m6PEAR/Exception.phpnu�[���<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
/**
 * PEAR_Exception
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Tomas V. V. Cox <cox@idecnet.com>
 * @author     Hans Lellelid <hans@velum.net>
 * @author     Bertrand Mansion <bmansion@mamasam.com>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.3.3
 */


/**
 * Base PEAR_Exception Class
 *
 * 1) Features:
 *
 * - Nestable exceptions (throw new PEAR_Exception($msg, $prev_exception))
 * - Definable triggers, shot when exceptions occur
 * - Pretty and informative error messages
 * - Added more context info available (like class, method or cause)
 * - cause can be a PEAR_Exception or an array of mixed
 *   PEAR_Exceptions/PEAR_ErrorStack warnings
 * - callbacks for specific exception classes and their children
 *
 * 2) Ideas:
 *
 * - Maybe a way to define a 'template' for the output
 *
 * 3) Inherited properties from PHP Exception Class:
 *
 * protected $message
 * protected $code
 * protected $line
 * protected $file
 * private   $trace
 *
 * 4) Inherited methods from PHP Exception Class:
 *
 * __clone
 * __construct
 * getMessage
 * getCode
 * getFile
 * getLine
 * getTraceSafe
 * getTraceSafeAsString
 * __toString
 *
 * 5) Usage example
 *
 * <code>
 *  require_once 'PEAR/Exception.php';
 *
 *  class Test {
 *     function foo() {
 *         throw new PEAR_Exception('Error Message', ERROR_CODE);
 *     }
 *  }
 *
 *  function myLogger($pear_exception) {
 *     echo $pear_exception->getMessage();
 *  }
 *  // each time a exception is thrown the 'myLogger' will be called
 *  // (its use is completely optional)
 *  PEAR_Exception::addObserver('myLogger');
 *  $test = new Test;
 *  try {
 *     $test->foo();
 *  } catch (PEAR_Exception $e) {
 *     print $e;
 *  }
 * </code>
 *
 * @category   pear
 * @package    PEAR
 * @author     Tomas V.V.Cox <cox@idecnet.com>
 * @author     Hans Lellelid <hans@velum.net>
 * @author     Bertrand Mansion <bmansion@mamasam.com>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.3.3
 *
 */
class PEAR_Exception extends Exception
{
    const OBSERVER_PRINT = -2;
    const OBSERVER_TRIGGER = -4;
    const OBSERVER_DIE = -8;
    protected $cause;
    private static $_observers = array();
    private static $_uniqueid = 0;
    private $_trace;

    /**
     * Supported signatures:
     *  - PEAR_Exception(string $message);
     *  - PEAR_Exception(string $message, int $code);
     *  - PEAR_Exception(string $message, Exception $cause);
     *  - PEAR_Exception(string $message, Exception $cause, int $code);
     *  - PEAR_Exception(string $message, PEAR_Error $cause);
     *  - PEAR_Exception(string $message, PEAR_Error $cause, int $code);
     *  - PEAR_Exception(string $message, array $causes);
     *  - PEAR_Exception(string $message, array $causes, int $code);
     * @param string exception message
     * @param int|Exception|PEAR_Error|array|null exception cause
     * @param int|null exception code or null
     */
    public function __construct($message, $p2 = null, $p3 = null)
    {
        if (is_int($p2)) {
            $code = $p2;
            $this->cause = null;
        } elseif (is_object($p2) || is_array($p2)) {
            // using is_object allows both Exception and PEAR_Error
            if (is_object($p2) && !($p2 instanceof Exception)) {
                if (!class_exists('PEAR_Error') || !($p2 instanceof PEAR_Error)) {
                    throw new PEAR_Exception('exception cause must be Exception, ' .
                        'array, or PEAR_Error');
                }
            }
            $code = $p3;
            if (is_array($p2) && isset($p2['message'])) {
                // fix potential problem of passing in a single warning
                $p2 = array($p2);
            }
            $this->cause = $p2;
        } else {
            $code = null;
            $this->cause = null;
        }
        parent::__construct($message, $code);
        $this->signal();
    }

    /**
     * @param mixed $callback  - A valid php callback, see php func is_callable()
     *                         - A PEAR_Exception::OBSERVER_* constant
     *                         - An array(const PEAR_Exception::OBSERVER_*,
     *                           mixed $options)
     * @param string $label    The name of the observer. Use this if you want
     *                         to remove it later with removeObserver()
     */
    public static function addObserver($callback, $label = 'default')
    {
        self::$_observers[$label] = $callback;
    }

    public static function removeObserver($label = 'default')
    {
        unset(self::$_observers[$label]);
    }

    /**
     * @return int unique identifier for an observer
     */
    public static function getUniqueId()
    {
        return self::$_uniqueid++;
    }

    private function signal()
    {
        foreach (self::$_observers as $func) {
            if (is_callable($func)) {
                call_user_func($func, $this);
                continue;
            }
            settype($func, 'array');
            switch ($func[0]) {
                case self::OBSERVER_PRINT :
                    $f = (isset($func[1])) ? $func[1] : '%s';
                    printf($f, $this->getMessage());
                    break;
                case self::OBSERVER_TRIGGER :
                    $f = (isset($func[1])) ? $func[1] : E_USER_NOTICE;
                    trigger_error($this->getMessage(), $f);
                    break;
                case self::OBSERVER_DIE :
                    $f = (isset($func[1])) ? $func[1] : '%s';
                    die(printf($f, $this->getMessage()));
                    break;
                default:
                    trigger_error('invalid observer type', E_USER_WARNING);
            }
        }
    }

    /**
     * Return specific error information that can be used for more detailed
     * error messages or translation.
     *
     * This method may be overridden in child exception classes in order
     * to add functionality not present in PEAR_Exception and is a placeholder
     * to define API
     *
     * The returned array must be an associative array of parameter => value like so:
     * <pre>
     * array('name' => $name, 'context' => array(...))
     * </pre>
     * @return array
     */
    public function getErrorData()
    {
        return array();
    }

    /**
     * Returns the exception that caused this exception to be thrown
     * @access public
     * @return Exception|array The context of the exception
     */
    public function getCause()
    {
        return $this->cause;
    }

    /**
     * Function must be public to call on caused exceptions
     * @param array
     */
    public function getCauseMessage(&$causes)
    {
        $trace = $this->getTraceSafe();
        $cause = array('class'   => get_class($this),
                       'message' => $this->message,
                       'file' => 'unknown',
                       'line' => 'unknown');
        if (isset($trace[0])) {
            if (isset($trace[0]['file'])) {
                $cause['file'] = $trace[0]['file'];
                $cause['line'] = $trace[0]['line'];
            }
        }
        $causes[] = $cause;
        if ($this->cause instanceof PEAR_Exception) {
            $this->cause->getCauseMessage($causes);
        } elseif ($this->cause instanceof Exception) {
            $causes[] = array('class'   => get_class($this->cause),
                              'message' => $this->cause->getMessage(),
                              'file' => $this->cause->getFile(),
                              'line' => $this->cause->getLine());
        } elseif (class_exists('PEAR_Error') && $this->cause instanceof PEAR_Error) {
            $causes[] = array('class' => get_class($this->cause),
                              'message' => $this->cause->getMessage(),
                              'file' => 'unknown',
                              'line' => 'unknown');
        } elseif (is_array($this->cause)) {
            foreach ($this->cause as $cause) {
                if ($cause instanceof PEAR_Exception) {
                    $cause->getCauseMessage($causes);
                } elseif ($cause instanceof Exception) {
                    $causes[] = array('class'   => get_class($cause),
                                   'message' => $cause->getMessage(),
                                   'file' => $cause->getFile(),
                                   'line' => $cause->getLine());
                } elseif (class_exists('PEAR_Error') && $cause instanceof PEAR_Error) {
                    $causes[] = array('class' => get_class($cause),
                                      'message' => $cause->getMessage(),
                                      'file' => 'unknown',
                                      'line' => 'unknown');
                } elseif (is_array($cause) && isset($cause['message'])) {
                    // PEAR_ErrorStack warning
                    $causes[] = array(
                        'class' => $cause['package'],
                        'message' => $cause['message'],
                        'file' => isset($cause['context']['file']) ?
                                            $cause['context']['file'] :
                                            'unknown',
                        'line' => isset($cause['context']['line']) ?
                                            $cause['context']['line'] :
                                            'unknown',
                    );
                }
            }
        }
    }

    public function getTraceSafe()
    {
        if (!isset($this->_trace)) {
            $this->_trace = $this->getTrace();
            if (empty($this->_trace)) {
                $backtrace = debug_backtrace();
                $this->_trace = array($backtrace[count($backtrace)-1]);
            }
        }
        return $this->_trace;
    }

    public function getErrorClass()
    {
        $trace = $this->getTraceSafe();
        return $trace[0]['class'];
    }

    public function getErrorMethod()
    {
        $trace = $this->getTraceSafe();
        return $trace[0]['function'];
    }

    public function __toString()
    {
        if (isset($_SERVER['REQUEST_URI'])) {
            return $this->toHtml();
        }
        return $this->toText();
    }

    public function toHtml()
    {
        $trace = $this->getTraceSafe();
        $causes = array();
        $this->getCauseMessage($causes);
        $html =  '<table style="border: 1px" cellspacing="0">' . "\n";
        foreach ($causes as $i => $cause) {
            $html .= '<tr><td colspan="3" style="background: #ff9999">'
               . str_repeat('-', $i) . ' <b>' . $cause['class'] . '</b>: '
               . htmlspecialchars($cause['message']) . ' in <b>' . $cause['file'] . '</b> '
               . 'on line <b>' . $cause['line'] . '</b>'
               . "</td></tr>\n";
        }
        $html .= '<tr><td colspan="3" style="background-color: #aaaaaa; text-align: center; font-weight: bold;">Exception trace</td></tr>' . "\n"
               . '<tr><td style="text-align: center; background: #cccccc; width:20px; font-weight: bold;">#</td>'
               . '<td style="text-align: center; background: #cccccc; font-weight: bold;">Function</td>'
               . '<td style="text-align: center; background: #cccccc; font-weight: bold;">Location</td></tr>' . "\n";

        foreach ($trace as $k => $v) {
            $html .= '<tr><td style="text-align: center;">' . $k . '</td>'
                   . '<td>';
            if (!empty($v['class'])) {
                $html .= $v['class'] . $v['type'];
            }
            $html .= $v['function'];
            $args = array();
            if (!empty($v['args'])) {
                foreach ($v['args'] as $arg) {
                    if (is_null($arg)) $args[] = 'null';
                    elseif (is_array($arg)) $args[] = 'Array';
                    elseif (is_object($arg)) $args[] = 'Object('.get_class($arg).')';
                    elseif (is_bool($arg)) $args[] = $arg ? 'true' : 'false';
                    elseif (is_int($arg) || is_double($arg)) $args[] = $arg;
                    else {
                        $arg = (string)$arg;
                        $str = htmlspecialchars(substr($arg, 0, 16));
                        if (strlen($arg) > 16) $str .= '&hellip;';
                        $args[] = "'" . $str . "'";
                    }
                }
            }
            $html .= '(' . implode(', ',$args) . ')'
                   . '</td>'
                   . '<td>' . (isset($v['file']) ? $v['file'] : 'unknown')
                   . ':' . (isset($v['line']) ? $v['line'] : 'unknown')
                   . '</td></tr>' . "\n";
        }
        $html .= '<tr><td style="text-align: center;">' . ($k+1) . '</td>'
               . '<td>{main}</td>'
               . '<td>&nbsp;</td></tr>' . "\n"
               . '</table>';
        return $html;
    }

    public function toText()
    {
        $causes = array();
        $this->getCauseMessage($causes);
        $causeMsg = '';
        foreach ($causes as $i => $cause) {
            $causeMsg .= str_repeat(' ', $i) . $cause['class'] . ': '
                   . $cause['message'] . ' in ' . $cause['file']
                   . ' on line ' . $cause['line'] . "\n";
        }
        return $causeMsg . $this->getTraceAsString();
    }
}PKn�Zr"����PEAR/ChannelFile.phpnu�[���<?php
/**
 * PEAR_ChannelFile, the channel handling class
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a1
 */

/**
 * Needed for error handling
 */
require_once 'PEAR/ErrorStack.php';
require_once 'PEAR/XMLParser.php';
require_once 'PEAR/Common.php';

/**
 * Error code if the channel.xml <channel> tag does not contain a valid version
 */
define('PEAR_CHANNELFILE_ERROR_NO_VERSION', 1);
/**
 * Error code if the channel.xml <channel> tag version is not supported (version 1.0 is the only supported version,
 * currently
 */
define('PEAR_CHANNELFILE_ERROR_INVALID_VERSION', 2);

/**
 * Error code if parsing is attempted with no xml extension
 */
define('PEAR_CHANNELFILE_ERROR_NO_XML_EXT', 3);

/**
 * Error code if creating the xml parser resource fails
 */
define('PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER', 4);

/**
 * Error code used for all sax xml parsing errors
 */
define('PEAR_CHANNELFILE_ERROR_PARSER_ERROR', 5);

/**#@+
 * Validation errors
 */
/**
 * Error code when channel name is missing
 */
define('PEAR_CHANNELFILE_ERROR_NO_NAME', 6);
/**
 * Error code when channel name is invalid
 */
define('PEAR_CHANNELFILE_ERROR_INVALID_NAME', 7);
/**
 * Error code when channel summary is missing
 */
define('PEAR_CHANNELFILE_ERROR_NO_SUMMARY', 8);
/**
 * Error code when channel summary is multi-line
 */
define('PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY', 9);
/**
 * Error code when channel server is missing for protocol
 */
define('PEAR_CHANNELFILE_ERROR_NO_HOST', 10);
/**
 * Error code when channel server is invalid for protocol
 */
define('PEAR_CHANNELFILE_ERROR_INVALID_HOST', 11);
/**
 * Error code when a mirror name is invalid
 */
define('PEAR_CHANNELFILE_ERROR_INVALID_MIRROR', 21);
/**
 * Error code when a mirror type is invalid
 */
define('PEAR_CHANNELFILE_ERROR_INVALID_MIRRORTYPE', 22);
/**
 * Error code when an attempt is made to generate xml, but the parsed content is invalid
 */
define('PEAR_CHANNELFILE_ERROR_INVALID', 23);
/**
 * Error code when an empty package name validate regex is passed in
 */
define('PEAR_CHANNELFILE_ERROR_EMPTY_REGEX', 24);
/**
 * Error code when a <function> tag has no version
 */
define('PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION', 25);
/**
 * Error code when a <function> tag has no name
 */
define('PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME', 26);
/**
 * Error code when a <validatepackage> tag has no name
 */
define('PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME', 27);
/**
 * Error code when a <validatepackage> tag has no version attribute
 */
define('PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION', 28);
/**
 * Error code when a mirror does not exist but is called for in one of the set*
 * methods.
 */
define('PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND', 32);
/**
 * Error code when a server port is not numeric
 */
define('PEAR_CHANNELFILE_ERROR_INVALID_PORT', 33);
/**
 * Error code when <static> contains no version attribute
 */
define('PEAR_CHANNELFILE_ERROR_NO_STATICVERSION', 34);
/**
 * Error code when <baseurl> contains no type attribute in a <rest> protocol definition
 */
define('PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE', 35);
/**
 * Error code when a mirror is defined and the channel.xml represents the __uri pseudo-channel
 */
define('PEAR_CHANNELFILE_URI_CANT_MIRROR', 36);
/**
 * Error code when ssl attribute is present and is not "yes"
 */
define('PEAR_CHANNELFILE_ERROR_INVALID_SSL', 37);
/**#@-*/

/**
 * Mirror types allowed.  Currently only internet servers are recognized.
 */
$GLOBALS['_PEAR_CHANNELS_MIRROR_TYPES'] =  array('server');


/**
 * The Channel handling class
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 */
class PEAR_ChannelFile
{
    /**
     * @access private
     * @var PEAR_ErrorStack
     * @access private
     */
    var $_stack;

    /**
     * Supported channel.xml versions, for parsing
     * @var array
     * @access private
     */
    var $_supportedVersions = array('1.0');

    /**
     * Parsed channel information
     * @var array
     * @access private
     */
    var $_channelInfo;

    /**
     * index into the subchannels array, used for parsing xml
     * @var int
     * @access private
     */
    var $_subchannelIndex;

    /**
     * index into the mirrors array, used for parsing xml
     * @var int
     * @access private
     */
    var $_mirrorIndex;

    /**
     * Flag used to determine the validity of parsed content
     * @var boolean
     * @access private
     */
    var $_isValid = false;

    function __construct()
    {
        $this->_stack = new PEAR_ErrorStack('PEAR_ChannelFile');
        $this->_stack->setErrorMessageTemplate($this->_getErrorMessage());
        $this->_isValid = false;
    }

    /**
     * @return array
     * @access protected
     */
    function _getErrorMessage()
    {
        return
            array(
                PEAR_CHANNELFILE_ERROR_INVALID_VERSION =>
                    'While parsing channel.xml, an invalid version number "%version% was passed in, expecting one of %versions%',
                PEAR_CHANNELFILE_ERROR_NO_VERSION =>
                    'No version number found in <channel> tag',
                PEAR_CHANNELFILE_ERROR_NO_XML_EXT =>
                    '%error%',
                PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER =>
                    'Unable to create XML parser',
                PEAR_CHANNELFILE_ERROR_PARSER_ERROR =>
                    '%error%',
                PEAR_CHANNELFILE_ERROR_NO_NAME =>
                    'Missing channel name',
                PEAR_CHANNELFILE_ERROR_INVALID_NAME =>
                    'Invalid channel %tag% "%name%"',
                PEAR_CHANNELFILE_ERROR_NO_SUMMARY =>
                    'Missing channel summary',
                PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY =>
                    'Channel summary should be on one line, but is multi-line',
                PEAR_CHANNELFILE_ERROR_NO_HOST =>
                    'Missing channel server for %type% server',
                PEAR_CHANNELFILE_ERROR_INVALID_HOST =>
                    'Server name "%server%" is invalid for %type% server',
                PEAR_CHANNELFILE_ERROR_INVALID_MIRROR =>
                    'Invalid mirror name "%name%", mirror type %type%',
                PEAR_CHANNELFILE_ERROR_INVALID_MIRRORTYPE =>
                    'Invalid mirror type "%type%"',
                PEAR_CHANNELFILE_ERROR_INVALID =>
                    'Cannot generate xml, contents are invalid',
                PEAR_CHANNELFILE_ERROR_EMPTY_REGEX =>
                    'packagenameregex cannot be empty',
                PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION =>
                    '%parent% %protocol% function has no version',
                PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME =>
                    '%parent% %protocol% function has no name',
                PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE =>
                    '%parent% rest baseurl has no type',
                PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME =>
                    'Validation package has no name in <validatepackage> tag',
                PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION =>
                    'Validation package "%package%" has no version',
                PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND =>
                    'Mirror "%mirror%" does not exist',
                PEAR_CHANNELFILE_ERROR_INVALID_PORT =>
                    'Port "%port%" must be numeric',
                PEAR_CHANNELFILE_ERROR_NO_STATICVERSION =>
                    '<static> tag must contain version attribute',
                PEAR_CHANNELFILE_URI_CANT_MIRROR =>
                    'The __uri pseudo-channel cannot have mirrors',
                PEAR_CHANNELFILE_ERROR_INVALID_SSL =>
                    '%server% has invalid ssl attribute "%ssl%" can only be yes or not present',
            );
    }

    /**
     * @param string contents of package.xml file
     * @return bool success of parsing
     */
    function fromXmlString($data)
    {
        if (preg_match('/<channel\s+version="([0-9]+\.[0-9]+)"/', $data, $channelversion)) {
            if (!in_array($channelversion[1], $this->_supportedVersions)) {
                $this->_stack->push(PEAR_CHANNELFILE_ERROR_INVALID_VERSION, 'error',
                    array('version' => $channelversion[1]));
                return false;
            }
            $parser = new PEAR_XMLParser;
            $result = $parser->parse($data);
            if ($result !== true) {
                if ($result->getCode() == 1) {
                    $this->_stack->push(PEAR_CHANNELFILE_ERROR_NO_XML_EXT, 'error',
                        array('error' => $result->getMessage()));
                } else {
                    $this->_stack->push(PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER, 'error');
                }
                return false;
            }
            $this->_channelInfo = $parser->getData();
            return true;
        } else {
            $this->_stack->push(PEAR_CHANNELFILE_ERROR_NO_VERSION, 'error', array('xml' => $data));
            return false;
        }
    }

    /**
     * @return array
     */
    function toArray()
    {
        if (!$this->_isValid && !$this->validate()) {
            return false;
        }
        return $this->_channelInfo;
    }

    /**
     * @param array
     *
     * @return PEAR_ChannelFile|false false if invalid
     */
    public static function &fromArray(
        $data, $compatibility = false, $stackClass = 'PEAR_ErrorStack'
    ) {
        $a = new PEAR_ChannelFile($compatibility, $stackClass);
        $a->_fromArray($data);
        if (!$a->validate()) {
            $a = false;
            return $a;
        }
        return $a;
    }

    /**
     * Unlike {@link fromArray()} this does not do any validation
     *
     * @param array
     *
     * @return PEAR_ChannelFile
     */
    public static function &fromArrayWithErrors(
        $data, $compatibility = false, $stackClass = 'PEAR_ErrorStack'
    ) {
        $a = new PEAR_ChannelFile($compatibility, $stackClass);
        $a->_fromArray($data);
        return $a;
    }

    /**
     * @param array
     * @access private
     */
    function _fromArray($data)
    {
        $this->_channelInfo = $data;
    }

    /**
     * Wrapper to {@link PEAR_ErrorStack::getErrors()}
     * @param boolean determines whether to purge the error stack after retrieving
     * @return array
     */
    function getErrors($purge = false)
    {
        return $this->_stack->getErrors($purge);
    }

    /**
     * Unindent given string (?)
     *
     * @param string $str The string that has to be unindented.
     * @return string
     * @access private
     */
    function _unIndent($str)
    {
        // remove leading newlines
        $str = preg_replace('/^[\r\n]+/', '', $str);
        // find whitespace at the beginning of the first line
        $indent_len = strspn($str, " \t");
        $indent = substr($str, 0, $indent_len);
        $data = '';
        // remove the same amount of whitespace from following lines
        foreach (explode("\n", $str) as $line) {
            if (substr($line, 0, $indent_len) == $indent) {
                $data .= substr($line, $indent_len) . "\n";
            }
        }
        return $data;
    }

    /**
     * Parse a channel.xml file.  Expects the name of
     * a channel xml file as input.
     *
     * @param string  $descfile  name of channel xml file
     * @return bool success of parsing
     */
    function fromXmlFile($descfile)
    {
        if (!file_exists($descfile) || !is_file($descfile) || !is_readable($descfile) ||
             (!$fp = fopen($descfile, 'r'))) {
            require_once 'PEAR.php';
            return PEAR::raiseError("Unable to open $descfile");
        }

        // read the whole thing so we only get one cdata callback
        // for each block of cdata
        fclose($fp);
        $data = file_get_contents($descfile);
        return $this->fromXmlString($data);
    }

    /**
     * Parse channel information from different sources
     *
     * This method is able to extract information about a channel
     * from an .xml file or a string
     *
     * @access public
     * @param  string Filename of the source or the source itself
     * @return bool
     */
    function fromAny($info)
    {
        if (is_string($info) && file_exists($info) && strlen($info) < 255) {
            $tmp = substr($info, -4);
            if ($tmp == '.xml') {
                $info = $this->fromXmlFile($info);
            } else {
                $fp = fopen($info, "r");
                $test = fread($fp, 5);
                fclose($fp);
                if ($test == "<?xml") {
                    $info = $this->fromXmlFile($info);
                }
            }
            if (PEAR::isError($info)) {
                require_once 'PEAR.php';
                return PEAR::raiseError($info);
            }
        }
        if (is_string($info)) {
            $info = $this->fromXmlString($info);
        }
        return $info;
    }

    /**
     * Return an XML document based on previous parsing and modifications
     *
     * @return string XML data
     *
     * @access public
     */
    function toXml()
    {
        if (!$this->_isValid && !$this->validate()) {
            $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID);
            return false;
        }
        if (!isset($this->_channelInfo['attribs']['version'])) {
            $this->_channelInfo['attribs']['version'] = '1.0';
        }
        $channelInfo = $this->_channelInfo;
        $ret = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n";
        $ret .= "<channel version=\"" .
            $channelInfo['attribs']['version'] . "\" xmlns=\"http://pear.php.net/channel-1.0\"
  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
  xsi:schemaLocation=\"http://pear.php.net/dtd/channel-"
            . $channelInfo['attribs']['version'] . " http://pear.php.net/dtd/channel-" .
            $channelInfo['attribs']['version'] . ".xsd\">
 <name>$channelInfo[name]</name>
 <summary>" . htmlspecialchars($channelInfo['summary'])."</summary>
";
        if (isset($channelInfo['suggestedalias'])) {
            $ret .= ' <suggestedalias>' . $channelInfo['suggestedalias'] . "</suggestedalias>\n";
        }
        if (isset($channelInfo['validatepackage'])) {
            $ret .= ' <validatepackage version="' .
                $channelInfo['validatepackage']['attribs']['version']. '">' .
                htmlspecialchars($channelInfo['validatepackage']['_content']) .
                "</validatepackage>\n";
        }
        $ret .= " <servers>\n";
        $ret .= '  <primary';
        if (isset($channelInfo['servers']['primary']['attribs']['ssl'])) {
            $ret .= ' ssl="' . $channelInfo['servers']['primary']['attribs']['ssl'] . '"';
        }
        if (isset($channelInfo['servers']['primary']['attribs']['port'])) {
            $ret .= ' port="' . $channelInfo['servers']['primary']['attribs']['port'] . '"';
        }
        $ret .= ">\n";
        if (isset($channelInfo['servers']['primary']['rest'])) {
            $ret .= $this->_makeRestXml($channelInfo['servers']['primary']['rest'], '   ');
        }
        $ret .= "  </primary>\n";
        if (isset($channelInfo['servers']['mirror'])) {
            $ret .= $this->_makeMirrorsXml($channelInfo);
        }
        $ret .= " </servers>\n";
        $ret .= "</channel>";
        return str_replace("\r", "\n", str_replace("\r\n", "\n", $ret));
    }

    /**
     * Generate the <rest> tag
     * @access private
     */
    function _makeRestXml($info, $indent)
    {
        $ret = $indent . "<rest>\n";
        if (isset($info['baseurl']) && !isset($info['baseurl'][0])) {
            $info['baseurl'] = array($info['baseurl']);
        }

        if (isset($info['baseurl'])) {
            foreach ($info['baseurl'] as $url) {
                $ret .= "$indent <baseurl type=\"" . $url['attribs']['type'] . "\"";
                $ret .= ">" . $url['_content'] . "</baseurl>\n";
            }
        }
        $ret .= $indent . "</rest>\n";
        return $ret;
    }

    /**
     * Generate the <mirrors> tag
     * @access private
     */
    function _makeMirrorsXml($channelInfo)
    {
        $ret = "";
        if (!isset($channelInfo['servers']['mirror'][0])) {
            $channelInfo['servers']['mirror'] = array($channelInfo['servers']['mirror']);
        }
        foreach ($channelInfo['servers']['mirror'] as $mirror) {
            $ret .= '  <mirror host="' . $mirror['attribs']['host'] . '"';
            if (isset($mirror['attribs']['port'])) {
                $ret .= ' port="' . $mirror['attribs']['port'] . '"';
            }
            if (isset($mirror['attribs']['ssl'])) {
                $ret .= ' ssl="' . $mirror['attribs']['ssl'] . '"';
            }
            $ret .= ">\n";
            if (isset($mirror['rest'])) {
                if (isset($mirror['rest'])) {
                    $ret .= $this->_makeRestXml($mirror['rest'], '   ');
                }
                $ret .= "  </mirror>\n";
            } else {
                $ret .= "/>\n";
            }
        }
        return $ret;
    }

    /**
     * Generate the <functions> tag
     * @access private
     */
    function _makeFunctionsXml($functions, $indent, $rest = false)
    {
        $ret = '';
        if (!isset($functions[0])) {
            $functions = array($functions);
        }
        foreach ($functions as $function) {
            $ret .= "$indent<function version=\"" . $function['attribs']['version'] . "\"";
            if ($rest) {
                $ret .= ' uri="' . $function['attribs']['uri'] . '"';
            }
            $ret .= ">" . $function['_content'] . "</function>\n";
        }
        return $ret;
    }

    /**
     * Validation error.  Also marks the object contents as invalid
     * @param error code
     * @param array error information
     * @access private
     */
    function _validateError($code, $params = array())
    {
        $this->_stack->push($code, 'error', $params);
        $this->_isValid = false;
    }

    /**
     * Validation warning.  Does not mark the object contents invalid.
     * @param error code
     * @param array error information
     * @access private
     */
    function _validateWarning($code, $params = array())
    {
        $this->_stack->push($code, 'warning', $params);
    }

    /**
     * Validate parsed file.
     *
     * @access public
     * @return boolean
     */
    function validate()
    {
        $this->_isValid = true;
        $info = $this->_channelInfo;
        if (empty($info['name'])) {
            $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_NAME);
        } elseif (!$this->validChannelServer($info['name'])) {
            if ($info['name'] != '__uri') {
                $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME, array('tag' => 'name',
                    'name' => $info['name']));
            }
        }
        if (empty($info['summary'])) {
            $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SUMMARY);
        } elseif (strpos(trim($info['summary']), "\n") !== false) {
            $this->_validateWarning(PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY,
                array('summary' => $info['summary']));
        }
        if (isset($info['suggestedalias'])) {
            if (!$this->validChannelServer($info['suggestedalias'])) {
                $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
                    array('tag' => 'suggestedalias', 'name' =>$info['suggestedalias']));
            }
        }
        if (isset($info['localalias'])) {
            if (!$this->validChannelServer($info['localalias'])) {
                $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
                    array('tag' => 'localalias', 'name' =>$info['localalias']));
            }
        }
        if (isset($info['validatepackage'])) {
            if (!isset($info['validatepackage']['_content'])) {
                $this->_validateError(PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME);
            }
            if (!isset($info['validatepackage']['attribs']['version'])) {
                $content = isset($info['validatepackage']['_content']) ?
                    $info['validatepackage']['_content'] :
                    null;
                $this->_validateError(PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION,
                    array('package' => $content));
            }
        }

        if (isset($info['servers']['primary']['attribs'], $info['servers']['primary']['attribs']['port']) &&
              !is_numeric($info['servers']['primary']['attribs']['port'])) {
            $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_PORT,
                array('port' => $info['servers']['primary']['attribs']['port']));
        }

        if (isset($info['servers']['primary']['attribs'], $info['servers']['primary']['attribs']['ssl']) &&
              $info['servers']['primary']['attribs']['ssl'] != 'yes') {
            $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_SSL,
                array('ssl' => $info['servers']['primary']['attribs']['ssl'],
                    'server' => $info['name']));
        }

        if (isset($info['servers']['primary']['rest']) &&
              isset($info['servers']['primary']['rest']['baseurl'])) {
            $this->_validateFunctions('rest', $info['servers']['primary']['rest']['baseurl']);
        }
        if (isset($info['servers']['mirror'])) {
            if ($this->_channelInfo['name'] == '__uri') {
                $this->_validateError(PEAR_CHANNELFILE_URI_CANT_MIRROR);
            }
            if (!isset($info['servers']['mirror'][0])) {
                $info['servers']['mirror'] = array($info['servers']['mirror']);
            }
            foreach ($info['servers']['mirror'] as $mirror) {
                if (!isset($mirror['attribs']['host'])) {
                    $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_HOST,
                      array('type' => 'mirror'));
                } elseif (!$this->validChannelServer($mirror['attribs']['host'])) {
                    $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_HOST,
                        array('server' => $mirror['attribs']['host'], 'type' => 'mirror'));
                }
                if (isset($mirror['attribs']['ssl']) && $mirror['attribs']['ssl'] != 'yes') {
                    $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_SSL,
                        array('ssl' => $info['ssl'], 'server' => $mirror['attribs']['host']));
                }
                if (isset($mirror['rest'])) {
                    $this->_validateFunctions('rest', $mirror['rest']['baseurl'],
                        $mirror['attribs']['host']);
                }
            }
        }
        return $this->_isValid;
    }

    /**
     * @param string  rest - protocol name this function applies to
     * @param array the functions
     * @param string the name of the parent element (mirror name, for instance)
     */
    function _validateFunctions($protocol, $functions, $parent = '')
    {
        if (!isset($functions[0])) {
            $functions = array($functions);
        }

        foreach ($functions as $function) {
            if (!isset($function['_content']) || empty($function['_content'])) {
                $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME,
                    array('parent' => $parent, 'protocol' => $protocol));
            }

            if ($protocol == 'rest') {
                if (!isset($function['attribs']['type']) ||
                      empty($function['attribs']['type'])) {
                    $this->_validateError(PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE,
                        array('parent' => $parent, 'protocol' => $protocol));
                }
            } else {
                if (!isset($function['attribs']['version']) ||
                      empty($function['attribs']['version'])) {
                    $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION,
                        array('parent' => $parent, 'protocol' => $protocol));
                }
            }
        }
    }

    /**
     * Test whether a string contains a valid channel server.
     * @param string $ver the package version to test
     * @return bool
     */
    function validChannelServer($server)
    {
        if ($server == '__uri') {
            return true;
        }
        return (bool) preg_match(PEAR_CHANNELS_SERVER_PREG, $server);
    }

    /**
     * @return string|false
     */
    function getName()
    {
        if (isset($this->_channelInfo['name'])) {
            return $this->_channelInfo['name'];
        }

        return false;
    }

    /**
     * @return string|false
     */
    function getServer()
    {
        if (isset($this->_channelInfo['name'])) {
            return $this->_channelInfo['name'];
        }

        return false;
    }

    /**
     * @return int|80 port number to connect to
     */
    function getPort($mirror = false)
    {
        if ($mirror) {
            if ($mir = $this->getMirror($mirror)) {
                if (isset($mir['attribs']['port'])) {
                    return $mir['attribs']['port'];
                }

                if ($this->getSSL($mirror)) {
                    return 443;
                }

                return 80;
            }

            return false;
        }

        if (isset($this->_channelInfo['servers']['primary']['attribs']['port'])) {
            return $this->_channelInfo['servers']['primary']['attribs']['port'];
        }

        if ($this->getSSL()) {
            return 443;
        }

        return 80;
    }

    /**
     * @return bool Determines whether secure sockets layer (SSL) is used to connect to this channel
     */
    function getSSL($mirror = false)
    {
        if ($mirror) {
            if ($mir = $this->getMirror($mirror)) {
                if (isset($mir['attribs']['ssl'])) {
                    return true;
                }

                return false;
            }

            return false;
        }

        if (isset($this->_channelInfo['servers']['primary']['attribs']['ssl'])) {
            return true;
        }

        return false;
    }

    /**
     * @return string|false
     */
    function getSummary()
    {
        if (isset($this->_channelInfo['summary'])) {
            return $this->_channelInfo['summary'];
        }

        return false;
    }

    /**
     * @param string protocol type
     * @param string Mirror name
     * @return array|false
     */
    function getFunctions($protocol, $mirror = false)
    {
        if ($this->getName() == '__uri') {
            return false;
        }

        $function = $protocol == 'rest' ? 'baseurl' : 'function';
        if ($mirror) {
            if ($mir = $this->getMirror($mirror)) {
                if (isset($mir[$protocol][$function])) {
                    return $mir[$protocol][$function];
                }
            }

            return false;
        }

        if (isset($this->_channelInfo['servers']['primary'][$protocol][$function])) {
            return $this->_channelInfo['servers']['primary'][$protocol][$function];
        }

        return false;
    }

    /**
     * @param string Protocol type
     * @param string Function name (null to return the
     *               first protocol of the type requested)
     * @param string Mirror name, if any
     * @return array
     */
     function getFunction($type, $name = null, $mirror = false)
     {
        $protocols = $this->getFunctions($type, $mirror);
        if (!$protocols) {
            return false;
        }

        foreach ($protocols as $protocol) {
            if ($name === null) {
                return $protocol;
            }

            if ($protocol['_content'] != $name) {
                continue;
            }

            return $protocol;
        }

        return false;
     }

    /**
     * @param string protocol type
     * @param string protocol name
     * @param string version
     * @param string mirror name
     * @return boolean
     */
    function supports($type, $name = null, $mirror = false, $version = '1.0')
    {
        $protocols = $this->getFunctions($type, $mirror);
        if (!$protocols) {
            return false;
        }

        foreach ($protocols as $protocol) {
            if ($protocol['attribs']['version'] != $version) {
                continue;
            }

            if ($name === null) {
                return true;
            }

            if ($protocol['_content'] != $name) {
                continue;
            }

            return true;
        }

        return false;
    }

    /**
     * Determines whether a channel supports Representational State Transfer (REST) protocols
     * for retrieving channel information
     * @param string
     * @return bool
     */
    function supportsREST($mirror = false)
    {
        if ($mirror == $this->_channelInfo['name']) {
            $mirror = false;
        }

        if ($mirror) {
            if ($mir = $this->getMirror($mirror)) {
                return isset($mir['rest']);
            }

            return false;
        }

        return isset($this->_channelInfo['servers']['primary']['rest']);
    }

    /**
     * Get the URL to access a base resource.
     *
     * Hyperlinks in the returned xml will be used to retrieve the proper information
     * needed.  This allows extreme extensibility and flexibility in implementation
     * @param string Resource Type to retrieve
     */
    function getBaseURL($resourceType, $mirror = false)
    {
        if ($mirror == $this->_channelInfo['name']) {
            $mirror = false;
        }

        if ($mirror) {
            $mir = $this->getMirror($mirror);
            if (!$mir) {
                return false;
            }

            $rest = $mir['rest'];
        } else {
            $rest = $this->_channelInfo['servers']['primary']['rest'];
        }

        if (!isset($rest['baseurl'][0])) {
            $rest['baseurl'] = array($rest['baseurl']);
        }

        foreach ($rest['baseurl'] as $baseurl) {
            if (strtolower($baseurl['attribs']['type']) == strtolower($resourceType)) {
                return $baseurl['_content'];
            }
        }

        return false;
    }

    /**
     * Since REST does not implement RPC, provide this as a logical wrapper around
     * resetFunctions for REST
     * @param string|false mirror name, if any
     */
    function resetREST($mirror = false)
    {
        return $this->resetFunctions('rest', $mirror);
    }

    /**
     * Empty all protocol definitions
     * @param string protocol type
     * @param string|false mirror name, if any
     */
    function resetFunctions($type, $mirror = false)
    {
        if ($mirror) {
            if (isset($this->_channelInfo['servers']['mirror'])) {
                $mirrors = $this->_channelInfo['servers']['mirror'];
                if (!isset($mirrors[0])) {
                    $mirrors = array($mirrors);
                }

                foreach ($mirrors as $i => $mir) {
                    if ($mir['attribs']['host'] == $mirror) {
                        if (isset($this->_channelInfo['servers']['mirror'][$i][$type])) {
                            unset($this->_channelInfo['servers']['mirror'][$i][$type]);
                        }

                        return true;
                    }
                }

                return false;
            }

            return false;
        }

        if (isset($this->_channelInfo['servers']['primary'][$type])) {
            unset($this->_channelInfo['servers']['primary'][$type]);
        }

        return true;
    }

    /**
     * Set a channel's protocols to the protocols supported by pearweb
     */
    function setDefaultPEARProtocols($version = '1.0', $mirror = false)
    {
        switch ($version) {
            case '1.0' :
                $this->resetREST($mirror);

                if (!isset($this->_channelInfo['servers'])) {
                    $this->_channelInfo['servers'] = array('primary' =>
                        array('rest' => array()));
                } elseif (!isset($this->_channelInfo['servers']['primary'])) {
                    $this->_channelInfo['servers']['primary'] = array('rest' => array());
                }

                return true;
            break;
            default :
                return false;
            break;
        }
    }

    /**
     * @return array
     */
    function getMirrors()
    {
        if (isset($this->_channelInfo['servers']['mirror'])) {
            $mirrors = $this->_channelInfo['servers']['mirror'];
            if (!isset($mirrors[0])) {
                $mirrors = array($mirrors);
            }

            return $mirrors;
        }

        return array();
    }

    /**
     * Get the unserialized XML representing a mirror
     * @return array|false
     */
    function getMirror($server)
    {
        foreach ($this->getMirrors() as $mirror) {
            if ($mirror['attribs']['host'] == $server) {
                return $mirror;
            }
        }

        return false;
    }

    /**
     * @param string
     * @return string|false
     * @error PEAR_CHANNELFILE_ERROR_NO_NAME
     * @error PEAR_CHANNELFILE_ERROR_INVALID_NAME
     */
    function setName($name)
    {
        return $this->setServer($name);
    }

    /**
     * Set the socket number (port) that is used to connect to this channel
     * @param integer
     * @param string|false name of the mirror server, or false for the primary
     */
    function setPort($port, $mirror = false)
    {
        if ($mirror) {
            if (!isset($this->_channelInfo['servers']['mirror'])) {
                $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
                    array('mirror' => $mirror));
                return false;
            }

            if (isset($this->_channelInfo['servers']['mirror'][0])) {
                foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
                    if ($mirror == $mir['attribs']['host']) {
                        $this->_channelInfo['servers']['mirror'][$i]['attribs']['port'] = $port;
                        return true;
                    }
                }

                return false;
            } elseif ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
                $this->_channelInfo['servers']['mirror']['attribs']['port'] = $port;
                $this->_isValid = false;
                return true;
            }
        }

        $this->_channelInfo['servers']['primary']['attribs']['port'] = $port;
        $this->_isValid = false;
        return true;
    }

    /**
     * Set the socket number (port) that is used to connect to this channel
     * @param bool Determines whether to turn on SSL support or turn it off
     * @param string|false name of the mirror server, or false for the primary
     */
    function setSSL($ssl = true, $mirror = false)
    {
        if ($mirror) {
            if (!isset($this->_channelInfo['servers']['mirror'])) {
                $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
                    array('mirror' => $mirror));
                return false;
            }

            if (isset($this->_channelInfo['servers']['mirror'][0])) {
                foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
                    if ($mirror == $mir['attribs']['host']) {
                        if (!$ssl) {
                            if (isset($this->_channelInfo['servers']['mirror'][$i]
                                  ['attribs']['ssl'])) {
                                unset($this->_channelInfo['servers']['mirror'][$i]['attribs']['ssl']);
                            }
                        } else {
                            $this->_channelInfo['servers']['mirror'][$i]['attribs']['ssl'] = 'yes';
                        }

                        return true;
                    }
                }

                return false;
            } elseif ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
                if (!$ssl) {
                    if (isset($this->_channelInfo['servers']['mirror']['attribs']['ssl'])) {
                        unset($this->_channelInfo['servers']['mirror']['attribs']['ssl']);
                    }
                } else {
                    $this->_channelInfo['servers']['mirror']['attribs']['ssl'] = 'yes';
                }

                $this->_isValid = false;
                return true;
            }
        }

        if ($ssl) {
            $this->_channelInfo['servers']['primary']['attribs']['ssl'] = 'yes';
        } else {
            if (isset($this->_channelInfo['servers']['primary']['attribs']['ssl'])) {
                unset($this->_channelInfo['servers']['primary']['attribs']['ssl']);
            }
        }

        $this->_isValid = false;
        return true;
    }

    /**
     * @param string
     * @return string|false
     * @error PEAR_CHANNELFILE_ERROR_NO_SERVER
     * @error PEAR_CHANNELFILE_ERROR_INVALID_SERVER
     */
    function setServer($server, $mirror = false)
    {
        if (empty($server)) {
            $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SERVER);
            return false;
        } elseif (!$this->validChannelServer($server)) {
            $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
                array('tag' => 'name', 'name' => $server));
            return false;
        }

        if ($mirror) {
            $found = false;
            foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
                if ($mirror == $mir['attribs']['host']) {
                    $found = true;
                    break;
                }
            }

            if (!$found) {
                $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
                    array('mirror' => $mirror));
                return false;
            }

            $this->_channelInfo['mirror'][$i]['attribs']['host'] = $server;
            return true;
        }

        $this->_channelInfo['name'] = $server;
        return true;
    }

    /**
     * @param string
     * @return boolean success
     * @error PEAR_CHANNELFILE_ERROR_NO_SUMMARY
     * @warning PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY
     */
    function setSummary($summary)
    {
        if (empty($summary)) {
            $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SUMMARY);
            return false;
        } elseif (strpos(trim($summary), "\n") !== false) {
            $this->_validateWarning(PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY,
                array('summary' => $summary));
        }

        $this->_channelInfo['summary'] = $summary;
        return true;
    }

    /**
     * @param string
     * @param boolean determines whether the alias is in channel.xml or local
     * @return boolean success
     */
    function setAlias($alias, $local = false)
    {
        if (!$this->validChannelServer($alias)) {
            $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
                array('tag' => 'suggestedalias', 'name' => $alias));
            return false;
        }

        if ($local) {
            $this->_channelInfo['localalias'] = $alias;
        } else {
            $this->_channelInfo['suggestedalias'] = $alias;
        }

        return true;
    }

    /**
     * @return string
     */
    function getAlias()
    {
        if (isset($this->_channelInfo['localalias'])) {
            return $this->_channelInfo['localalias'];
        }
        if (isset($this->_channelInfo['suggestedalias'])) {
            return $this->_channelInfo['suggestedalias'];
        }
        if (isset($this->_channelInfo['name'])) {
            return $this->_channelInfo['name'];
        }
        return '';
    }

    /**
     * Set the package validation object if it differs from PEAR's default
     * The class must be includeable via changing _ in the classname to path separator,
     * but no checking of this is made.
     * @param string|false pass in false to reset to the default packagename regex
     * @return boolean success
     */
    function setValidationPackage($validateclass, $version)
    {
        if (empty($validateclass)) {
            unset($this->_channelInfo['validatepackage']);
        }
        $this->_channelInfo['validatepackage'] = array('_content' => $validateclass);
        $this->_channelInfo['validatepackage']['attribs'] = array('version' => $version);
    }

    /**
     * Add a protocol to the provides section
     * @param string protocol type
     * @param string protocol version
     * @param string protocol name, if any
     * @param string mirror name, if this is a mirror's protocol
     * @return bool
     */
    function addFunction($type, $version, $name = '', $mirror = false)
    {
        if ($mirror) {
            return $this->addMirrorFunction($mirror, $type, $version, $name);
        }

        $set = array('attribs' => array('version' => $version), '_content' => $name);
        if (!isset($this->_channelInfo['servers']['primary'][$type]['function'])) {
            if (!isset($this->_channelInfo['servers'])) {
                $this->_channelInfo['servers'] = array('primary' =>
                    array($type => array()));
            } elseif (!isset($this->_channelInfo['servers']['primary'])) {
                $this->_channelInfo['servers']['primary'] = array($type => array());
            }

            $this->_channelInfo['servers']['primary'][$type]['function'] = $set;
            $this->_isValid = false;
            return true;
        } elseif (!isset($this->_channelInfo['servers']['primary'][$type]['function'][0])) {
            $this->_channelInfo['servers']['primary'][$type]['function'] = array(
                $this->_channelInfo['servers']['primary'][$type]['function']);
        }

        $this->_channelInfo['servers']['primary'][$type]['function'][] = $set;
        return true;
    }
    /**
     * Add a protocol to a mirror's provides section
     * @param string mirror name (server)
     * @param string protocol type
     * @param string protocol version
     * @param string protocol name, if any
     */
    function addMirrorFunction($mirror, $type, $version, $name = '')
    {
        if (!isset($this->_channelInfo['servers']['mirror'])) {
            $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
                array('mirror' => $mirror));
            return false;
        }

        $setmirror = false;
        if (isset($this->_channelInfo['servers']['mirror'][0])) {
            foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
                if ($mirror == $mir['attribs']['host']) {
                    $setmirror = &$this->_channelInfo['servers']['mirror'][$i];
                    break;
                }
            }
        } else {
            if ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
                $setmirror = &$this->_channelInfo['servers']['mirror'];
            }
        }

        if (!$setmirror) {
            $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
                array('mirror' => $mirror));
            return false;
        }

        $set = array('attribs' => array('version' => $version), '_content' => $name);
        if (!isset($setmirror[$type]['function'])) {
            $setmirror[$type]['function'] = $set;
            $this->_isValid = false;
            return true;
        } elseif (!isset($setmirror[$type]['function'][0])) {
            $setmirror[$type]['function'] = array($setmirror[$type]['function']);
        }

        $setmirror[$type]['function'][] = $set;
        $this->_isValid = false;
        return true;
    }

    /**
     * @param string Resource Type this url links to
     * @param string URL
     * @param string|false mirror name, if this is not a primary server REST base URL
     */
    function setBaseURL($resourceType, $url, $mirror = false)
    {
        if ($mirror) {
            if (!isset($this->_channelInfo['servers']['mirror'])) {
                $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
                    array('mirror' => $mirror));
                return false;
            }

            $setmirror = false;
            if (isset($this->_channelInfo['servers']['mirror'][0])) {
                foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
                    if ($mirror == $mir['attribs']['host']) {
                        $setmirror = &$this->_channelInfo['servers']['mirror'][$i];
                        break;
                    }
                }
            } else {
                if ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
                    $setmirror = &$this->_channelInfo['servers']['mirror'];
                }
            }
        } else {
            $setmirror = &$this->_channelInfo['servers']['primary'];
        }

        $set = array('attribs' => array('type' => $resourceType), '_content' => $url);
        if (!isset($setmirror['rest'])) {
            $setmirror['rest'] = array();
        }

        if (!isset($setmirror['rest']['baseurl'])) {
            $setmirror['rest']['baseurl'] = $set;
            $this->_isValid = false;
            return true;
        } elseif (!isset($setmirror['rest']['baseurl'][0])) {
            $setmirror['rest']['baseurl'] = array($setmirror['rest']['baseurl']);
        }

        foreach ($setmirror['rest']['baseurl'] as $i => $url) {
            if ($url['attribs']['type'] == $resourceType) {
                $this->_isValid = false;
                $setmirror['rest']['baseurl'][$i] = $set;
                return true;
            }
        }

        $setmirror['rest']['baseurl'][] = $set;
        $this->_isValid = false;
        return true;
    }

    /**
     * @param string mirror server
     * @param int mirror http port
     * @return boolean
     */
    function addMirror($server, $port = null)
    {
        if ($this->_channelInfo['name'] == '__uri') {
            return false; // the __uri channel cannot have mirrors by definition
        }

        $set = array('attribs' => array('host' => $server));
        if (is_numeric($port)) {
            $set['attribs']['port'] = $port;
        }

        if (!isset($this->_channelInfo['servers']['mirror'])) {
            $this->_channelInfo['servers']['mirror'] = $set;
            return true;
        }

        if (!isset($this->_channelInfo['servers']['mirror'][0])) {
            $this->_channelInfo['servers']['mirror'] =
                array($this->_channelInfo['servers']['mirror']);
        }

        $this->_channelInfo['servers']['mirror'][] = $set;
        return true;
    }

    /**
     * Retrieve the name of the validation package for this channel
     * @return string|false
     */
    function getValidationPackage()
    {
        if (!$this->_isValid && !$this->validate()) {
            return false;
        }

        if (!isset($this->_channelInfo['validatepackage'])) {
            return array('attribs' => array('version' => 'default'),
                '_content' => 'PEAR_Validate');
        }

        return $this->_channelInfo['validatepackage'];
    }

    /**
     * Retrieve the object that can be used for custom validation
     * @param string|false the name of the package to validate.  If the package is
     *                     the channel validation package, PEAR_Validate is returned
     * @return PEAR_Validate|false false is returned if the validation package
     *         cannot be located
     */
    function &getValidationObject($package = false)
    {
        if (!class_exists('PEAR_Validate')) {
            require_once 'PEAR/Validate.php';
        }

        if (!$this->_isValid) {
            if (!$this->validate()) {
                $a = false;
                return $a;
            }
        }

        if (isset($this->_channelInfo['validatepackage'])) {
            if ($package == $this->_channelInfo['validatepackage']) {
                // channel validation packages are always validated by PEAR_Validate
                $val = new PEAR_Validate;
                return $val;
            }

            if (!class_exists(str_replace('.', '_',
                  $this->_channelInfo['validatepackage']['_content']))) {
                if ($this->isIncludeable(str_replace('_', '/',
                      $this->_channelInfo['validatepackage']['_content']) . '.php')) {
                    include_once str_replace('_', '/',
                        $this->_channelInfo['validatepackage']['_content']) . '.php';
                    $vclass = str_replace('.', '_',
                        $this->_channelInfo['validatepackage']['_content']);
                    $val = new $vclass;
                } else {
                    $a = false;
                    return $a;
                }
            } else {
                $vclass = str_replace('.', '_',
                    $this->_channelInfo['validatepackage']['_content']);
                $val = new $vclass;
            }
        } else {
            $val = new PEAR_Validate;
        }

        return $val;
    }

    function isIncludeable($path)
    {
        $possibilities = explode(PATH_SEPARATOR, ini_get('include_path'));
        foreach ($possibilities as $dir) {
            if (file_exists($dir . DIRECTORY_SEPARATOR . $path)
                  && is_readable($dir . DIRECTORY_SEPARATOR . $path)) {
                return true;
            }
        }

        return false;
    }

    /**
     * This function is used by the channel updater and retrieves a value set by
     * the registry, or the current time if it has not been set
     * @return string
     */
    function lastModified()
    {
        if (isset($this->_channelInfo['_lastmodified'])) {
            return $this->_channelInfo['_lastmodified'];
        }

        return time();
    }
}
PKn�Z��gk�U�UPEAR/Validate.phpnu�[���<?php
/**
 * PEAR_Validate
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a1
 */
/**#@+
 * Constants for install stage
 */
define('PEAR_VALIDATE_INSTALLING', 1);
define('PEAR_VALIDATE_UNINSTALLING', 2); // this is not bit-mapped like the others
define('PEAR_VALIDATE_NORMAL', 3);
define('PEAR_VALIDATE_DOWNLOADING', 4); // this is not bit-mapped like the others
define('PEAR_VALIDATE_PACKAGING', 7);
/**#@-*/
require_once 'PEAR/Common.php';
require_once 'PEAR/Validator/PECL.php';

/**
 * Validation class for package.xml - channel-level advanced validation
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 */
class PEAR_Validate
{
    var $packageregex = _PEAR_COMMON_PACKAGE_NAME_PREG;
    /**
     * @var PEAR_PackageFile_v1|PEAR_PackageFile_v2
     */
    var $_packagexml;
    /**
     * @var int one of the PEAR_VALIDATE_* constants
     */
    var $_state = PEAR_VALIDATE_NORMAL;
    /**
     * Format: ('error' => array('field' => name, 'reason' => reason), 'warning' => same)
     * @var array
     * @access private
     */
    var $_failures = array('error' => array(), 'warning' => array());

    /**
     * Override this method to handle validation of normal package names
     * @param string
     * @return bool
     * @access protected
     */
    function _validPackageName($name)
    {
        return (bool) preg_match('/^' . $this->packageregex . '\\z/', $name);
    }

    /**
     * @param string package name to validate
     * @param string name of channel-specific validation package
     * @final
     */
    function validPackageName($name, $validatepackagename = false)
    {
        if ($validatepackagename) {
            if (strtolower($name) == strtolower($validatepackagename)) {
                return (bool) preg_match('/^[a-zA-Z0-9_]+(?:\.[a-zA-Z0-9_]+)*\\z/', $name);
            }
        }
        return $this->_validPackageName($name);
    }

    /**
     * This validates a bundle name, and bundle names must conform
     * to the PEAR naming convention, so the method is final and static.
     * @param string
     * @final
     */
    public static function validGroupName($name)
    {
        return (bool) preg_match('/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '\\z/', $name);
    }

    /**
     * Determine whether $state represents a valid stability level
     * @param string
     * @return bool
     * @final
     */
    public static function validState($state)
    {
        return in_array($state, array('snapshot', 'devel', 'alpha', 'beta', 'stable'));
    }

    /**
     * Get a list of valid stability levels
     * @return array
     * @final
     */
    public static function getValidStates()
    {
        return array('snapshot', 'devel', 'alpha', 'beta', 'stable');
    }

    /**
     * Determine whether a version is a properly formatted version number that can be used
     * by version_compare
     * @param string
     * @return bool
     * @final
     */
    public static function validVersion($ver)
    {
        return (bool) preg_match(PEAR_COMMON_PACKAGE_VERSION_PREG, $ver);
    }

    /**
     * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
     */
    function setPackageFile(&$pf)
    {
        $this->_packagexml = &$pf;
    }

    /**
     * @access private
     */
    function _addFailure($field, $reason)
    {
        $this->_failures['errors'][] = array('field' => $field, 'reason' => $reason);
    }

    /**
     * @access private
     */
    function _addWarning($field, $reason)
    {
        $this->_failures['warnings'][] = array('field' => $field, 'reason' => $reason);
    }

    function getFailures()
    {
        $failures = $this->_failures;
        $this->_failures = array('warnings' => array(), 'errors' => array());
        return $failures;
    }

    /**
     * @param int one of the PEAR_VALIDATE_* constants
     */
    function validate($state = null)
    {
        if (!isset($this->_packagexml)) {
            return false;
        }
        if ($state !== null) {
            $this->_state = $state;
        }
        $this->_failures = array('warnings' => array(), 'errors' => array());
        $this->validatePackageName();
        $this->validateVersion();
        $this->validateMaintainers();
        $this->validateDate();
        $this->validateSummary();
        $this->validateDescription();
        $this->validateLicense();
        $this->validateNotes();
        if ($this->_packagexml->getPackagexmlVersion() == '1.0') {
            $this->validateState();
            $this->validateFilelist();
        } elseif ($this->_packagexml->getPackagexmlVersion() == '2.0' ||
                  $this->_packagexml->getPackagexmlVersion() == '2.1') {
            $this->validateTime();
            $this->validateStability();
            $this->validateDeps();
            $this->validateMainFilelist();
            $this->validateReleaseFilelist();
            //$this->validateGlobalTasks();
            $this->validateChangelog();
        }
        return !((bool) count($this->_failures['errors']));
    }

    /**
     * @access protected
     */
    function validatePackageName()
    {
        if ($this->_state == PEAR_VALIDATE_PACKAGING ||
              $this->_state == PEAR_VALIDATE_NORMAL) {
            if (($this->_packagexml->getPackagexmlVersion() == '2.0' ||
                 $this->_packagexml->getPackagexmlVersion() == '2.1') &&
                  $this->_packagexml->getExtends()) {
                $version = $this->_packagexml->getVersion() . '';
                $name = $this->_packagexml->getPackage();
                $a = explode('.', $version);
                $test = array_shift($a);
                if ($test == '0') {
                    return true;
                }
                $vlen = strlen($test);
                $majver = substr($name, strlen($name) - $vlen);
                while ($majver && !is_numeric($majver[0])) {
                    $majver = substr($majver, 1);
                }
                if ($majver != $test) {
                    $this->_addWarning('package', "package $name extends package " .
                        $this->_packagexml->getExtends() . ' and so the name should ' .
                        'have a postfix equal to the major version like "' .
                        $this->_packagexml->getExtends() . $test . '"');
                    return true;
                } elseif (substr($name, 0, strlen($name) - $vlen) !=
                            $this->_packagexml->getExtends()) {
                    $this->_addWarning('package', "package $name extends package " .
                        $this->_packagexml->getExtends() . ' and so the name must ' .
                        'be an extension like "' . $this->_packagexml->getExtends() .
                        $test . '"');
                    return true;
                }
            }
        }
        if (!$this->validPackageName($this->_packagexml->getPackage())) {
            $this->_addFailure('name', 'package name "' .
                $this->_packagexml->getPackage() . '" is invalid');
            return false;
        }
    }

    /**
     * @access protected
     */
    function validateVersion()
    {
        if ($this->_state != PEAR_VALIDATE_PACKAGING) {
            if (!$this->validVersion($this->_packagexml->getVersion())) {
                $this->_addFailure('version',
                    'Invalid version number "' . $this->_packagexml->getVersion() . '"');
            }
            return false;
        }
        $version = $this->_packagexml->getVersion();
        $versioncomponents = explode('.', $version);
        if (count($versioncomponents) != 3) {
            $this->_addWarning('version',
                'A version number should have 3 decimals (x.y.z)');
            return true;
        }
        $name = $this->_packagexml->getPackage();
        // version must be based upon state
        switch ($this->_packagexml->getState()) {
            case 'snapshot' :
                return true;
            case 'devel' :
                if ($versioncomponents[0] . 'a' == '0a') {
                    return true;
                }
                if ($versioncomponents[0] == 0) {
                    $versioncomponents[0] = '0';
                    $this->_addWarning('version',
                        'version "' . $version . '" should be "' .
                        implode('.' ,$versioncomponents) . '"');
                } else {
                    $this->_addWarning('version',
                        'packages with devel stability must be < version 1.0.0');
                }
                return true;
            break;
            case 'alpha' :
            case 'beta' :
                // check for a package that extends a package,
                // like Foo and Foo2
                if ($this->_state == PEAR_VALIDATE_PACKAGING) {
                    if (substr($versioncomponents[2], 1, 2) == 'rc') {
                        $this->_addFailure('version', 'Release Candidate versions ' .
                            'must have capital RC, not lower-case rc');
                        return false;
                    }
                }
                if (!$this->_packagexml->getExtends()) {
                    if ($versioncomponents[0] == '1') {
                        if ($versioncomponents[2][0] == '0') {
                            if ($versioncomponents[2] == '0') {
                                // version 1.*.0000
                                $this->_addWarning('version',
                                    'version 1.' . $versioncomponents[1] .
                                        '.0 probably should not be alpha or beta');
                                return true;
                            } elseif (strlen($versioncomponents[2]) > 1) {
                                // version 1.*.0RC1 or 1.*.0beta24 etc.
                                return true;
                            } else {
                                // version 1.*.0
                                $this->_addWarning('version',
                                    'version 1.' . $versioncomponents[1] .
                                        '.0 probably should not be alpha or beta');
                                return true;
                            }
                        } else {
                            $this->_addWarning('version',
                                'bugfix versions (1.3.x where x > 0) probably should ' .
                                'not be alpha or beta');
                            return true;
                        }
                    } elseif ($versioncomponents[0] != '0') {
                        $this->_addWarning('version',
                            'major versions greater than 1 are not allowed for packages ' .
                            'without an <extends> tag or an identical postfix (foo2 v2.0.0)');
                        return true;
                    }
                    if ($versioncomponents[0] . 'a' == '0a') {
                        return true;
                    }
                    if ($versioncomponents[0] == 0) {
                        $versioncomponents[0] = '0';
                        $this->_addWarning('version',
                            'version "' . $version . '" should be "' .
                            implode('.' ,$versioncomponents) . '"');
                    }
                } else {
                    $vlen = strlen($versioncomponents[0] . '');
                    $majver = substr($name, strlen($name) - $vlen);
                    while ($majver && !is_numeric($majver[0])) {
                        $majver = substr($majver, 1);
                    }
                    if (($versioncomponents[0] != 0) && $majver != $versioncomponents[0]) {
                        $this->_addWarning('version', 'first version number "' .
                            $versioncomponents[0] . '" must match the postfix of ' .
                            'package name "' . $name . '" (' .
                            $majver . ')');
                        return true;
                    }
                    if ($versioncomponents[0] == $majver) {
                        if ($versioncomponents[2][0] == '0') {
                            if ($versioncomponents[2] == '0') {
                                // version 2.*.0000
                                $this->_addWarning('version',
                                    "version $majver." . $versioncomponents[1] .
                                        '.0 probably should not be alpha or beta');
                                return false;
                            } elseif (strlen($versioncomponents[2]) > 1) {
                                // version 2.*.0RC1 or 2.*.0beta24 etc.
                                return true;
                            } else {
                                // version 2.*.0
                                $this->_addWarning('version',
                                    "version $majver." . $versioncomponents[1] .
                                        '.0 cannot be alpha or beta');
                                return true;
                            }
                        } else {
                            $this->_addWarning('version',
                                "bugfix versions ($majver.x.y where y > 0) should " .
                                'not be alpha or beta');
                            return true;
                        }
                    } elseif ($versioncomponents[0] != '0') {
                        $this->_addWarning('version',
                            "only versions 0.x.y and $majver.x.y are allowed for alpha/beta releases");
                        return true;
                    }
                    if ($versioncomponents[0] . 'a' == '0a') {
                        return true;
                    }
                    if ($versioncomponents[0] == 0) {
                        $versioncomponents[0] = '0';
                        $this->_addWarning('version',
                            'version "' . $version . '" should be "' .
                            implode('.' ,$versioncomponents) . '"');
                    }
                }
                return true;
            break;
            case 'stable' :
                if ($versioncomponents[0] == '0') {
                    $this->_addWarning('version', 'versions less than 1.0.0 cannot ' .
                    'be stable');
                    return true;
                }
                if (!is_numeric($versioncomponents[2])) {
                    if (preg_match('/\d+(rc|a|alpha|b|beta)\d*/i',
                          $versioncomponents[2])) {
                        $this->_addWarning('version', 'version "' . $version . '" or any ' .
                            'RC/beta/alpha version cannot be stable');
                        return true;
                    }
                }
                // check for a package that extends a package,
                // like Foo and Foo2
                if ($this->_packagexml->getExtends()) {
                    $vlen = strlen($versioncomponents[0] . '');
                    $majver = substr($name, strlen($name) - $vlen);
                    while ($majver && !is_numeric($majver[0])) {
                        $majver = substr($majver, 1);
                    }
                    if (($versioncomponents[0] != 0) && $majver != $versioncomponents[0]) {
                        $this->_addWarning('version', 'first version number "' .
                            $versioncomponents[0] . '" must match the postfix of ' .
                            'package name "' . $name . '" (' .
                            $majver . ')');
                        return true;
                    }
                } elseif ($versioncomponents[0] > 1) {
                    $this->_addWarning('version', 'major version x in x.y.z may not be greater than ' .
                        '1 for any package that does not have an <extends> tag');
                }
                return true;
            break;
            default :
                return false;
            break;
        }
    }

    /**
     * @access protected
     */
    function validateMaintainers()
    {
        // maintainers can only be truly validated server-side for most channels
        // but allow this customization for those who wish it
        return true;
    }

    /**
     * @access protected
     */
    function validateDate()
    {
        if ($this->_state == PEAR_VALIDATE_NORMAL ||
              $this->_state == PEAR_VALIDATE_PACKAGING) {

            if (!preg_match('/(\d\d\d\d)\-(\d\d)\-(\d\d)/',
                  $this->_packagexml->getDate(), $res) ||
                  count($res) < 4
                  || !checkdate($res[2], $res[3], $res[1])
                ) {
                $this->_addFailure('date', 'invalid release date "' .
                    $this->_packagexml->getDate() . '"');
                return false;
            }

            if ($this->_state == PEAR_VALIDATE_PACKAGING &&
                  $this->_packagexml->getDate() != date('Y-m-d')) {
                $this->_addWarning('date', 'Release Date "' .
                    $this->_packagexml->getDate() . '" is not today');
            }
        }
        return true;
    }

    /**
     * @access protected
     */
    function validateTime()
    {
        if (!$this->_packagexml->getTime()) {
            // default of no time value set
            return true;
        }

        // packager automatically sets time, so only validate if pear validate is called
        if ($this->_state = PEAR_VALIDATE_NORMAL) {
            if (!preg_match('/\d\d:\d\d:\d\d/',
                  $this->_packagexml->getTime())) {
                $this->_addFailure('time', 'invalid release time "' .
                    $this->_packagexml->getTime() . '"');
                return false;
            }

            $result = preg_match('|\d{2}\:\d{2}\:\d{2}|', $this->_packagexml->getTime(), $matches);
            if ($result === false || empty($matches)) {
                $this->_addFailure('time', 'invalid release time "' .
                    $this->_packagexml->getTime() . '"');
                return false;
            }
        }

        return true;
    }

    /**
     * @access protected
     */
    function validateState()
    {
        // this is the closest to "final" php4 can get
        if (!PEAR_Validate::validState($this->_packagexml->getState())) {
            if (strtolower($this->_packagexml->getState() == 'rc')) {
                $this->_addFailure('state', 'RC is not a state, it is a version ' .
                    'postfix, use ' . $this->_packagexml->getVersion() . 'RC1, state beta');
            }
            $this->_addFailure('state', 'invalid release state "' .
                $this->_packagexml->getState() . '", must be one of: ' .
                implode(', ', PEAR_Validate::getValidStates()));
            return false;
        }
        return true;
    }

    /**
     * @access protected
     */
    function validateStability()
    {
        $ret = true;
        $packagestability = $this->_packagexml->getState();
        $apistability = $this->_packagexml->getState('api');
        if (!PEAR_Validate::validState($packagestability)) {
            $this->_addFailure('state', 'invalid release stability "' .
                $this->_packagexml->getState() . '", must be one of: ' .
                implode(', ', PEAR_Validate::getValidStates()));
            $ret = false;
        }
        $apistates = PEAR_Validate::getValidStates();
        array_shift($apistates); // snapshot is not allowed
        if (!in_array($apistability, $apistates)) {
            $this->_addFailure('state', 'invalid API stability "' .
                $this->_packagexml->getState('api') . '", must be one of: ' .
                implode(', ', $apistates));
            $ret = false;
        }
        return $ret;
    }

    /**
     * @access protected
     */
    function validateSummary()
    {
        return true;
    }

    /**
     * @access protected
     */
    function validateDescription()
    {
        return true;
    }

    /**
     * @access protected
     */
    function validateLicense()
    {
        return true;
    }

    /**
     * @access protected
     */
    function validateNotes()
    {
        return true;
    }

    /**
     * for package.xml 2.0 only - channels can't use package.xml 1.0
     * @access protected
     */
    function validateDependencies()
    {
        return true;
    }

    /**
     * for package.xml 1.0 only
     * @access private
     */
    function _validateFilelist()
    {
        return true; // placeholder for now
    }

    /**
     * for package.xml 2.0 only
     * @access protected
     */
    function validateMainFilelist()
    {
        return true; // placeholder for now
    }

    /**
     * for package.xml 2.0 only
     * @access protected
     */
    function validateReleaseFilelist()
    {
        return true; // placeholder for now
    }

    /**
     * @access protected
     */
    function validateChangelog()
    {
        return true;
    }

    /**
     * @access protected
     */
    function validateFilelist()
    {
        return true;
    }

    /**
     * @access protected
     */
    function validateDeps()
    {
        return true;
    }
}PKn�Zd֣S��PEAR/Command/Pickle.xmlnu�[���<commands version="1.0">
 <pickle>
  <summary>Build PECL Package</summary>
  <function>doPackage</function>
  <shortcut>pi</shortcut>
  <options>
   <nocompress>
    <shortopt>Z</shortopt>
    <doc>Do not gzip the package file</doc>
   </nocompress>
   <showname>
    <shortopt>n</shortopt>
    <doc>Print the name of the packaged file.</doc>
   </showname>
  </options>
  <doc>[descfile]
Creates a PECL package from its package2.xml file.

An automatic conversion will be made to a package.xml 1.0 and written out to
disk in the current directory as &quot;package.xml&quot;.  Note that
only simple package.xml 2.0 will be converted.  package.xml 2.0 with:

 - dependency types other than required/optional PECL package/ext/php/pearinstaller
 - more than one extsrcrelease or zendextsrcrelease
 - zendextbinrelease, extbinrelease, phprelease, or bundle release type
 - dependency groups
 - ignore tags in release filelist
 - tasks other than replace
 - custom roles

will cause pickle to fail, and output an error message.  If your package2.xml
uses any of these features, you are best off using PEAR_PackageFileManager to
generate both package.xml.
</doc>
 </pickle>
</commands>PKn�Z�z��k<k<PEAR/Command/Config.phpnu�[���<?php
/**
 * PEAR_Command_Config (config-show, config-get, config-set, config-help, config-create commands)
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 0.1
 */

/**
 * base class
 */
require_once 'PEAR/Command/Common.php';

/**
 * PEAR commands for managing configuration data.
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 0.1
 */
class PEAR_Command_Config extends PEAR_Command_Common
{
    var $commands = array(
        'config-show' => array(
            'summary' => 'Show All Settings',
            'function' => 'doConfigShow',
            'shortcut' => 'csh',
            'options' => array(
                'channel' => array(
                    'shortopt' => 'c',
                    'doc' => 'show configuration variables for another channel',
                    'arg' => 'CHAN',
                    ),
),
            'doc' => '[layer]
Displays all configuration values.  An optional argument
may be used to tell which configuration layer to display.  Valid
configuration layers are "user", "system" and "default". To display
configurations for different channels, set the default_channel
configuration variable and run config-show again.
',
            ),
        'config-get' => array(
            'summary' => 'Show One Setting',
            'function' => 'doConfigGet',
            'shortcut' => 'cg',
            'options' => array(
                'channel' => array(
                    'shortopt' => 'c',
                    'doc' => 'show configuration variables for another channel',
                    'arg' => 'CHAN',
                    ),
),
            'doc' => '<parameter> [layer]
Displays the value of one configuration parameter.  The
first argument is the name of the parameter, an optional second argument
may be used to tell which configuration layer to look in.  Valid configuration
layers are "user", "system" and "default".  If no layer is specified, a value
will be picked from the first layer that defines the parameter, in the order
just specified.  The configuration value will be retrieved for the channel
specified by the default_channel configuration variable.
',
            ),
        'config-set' => array(
            'summary' => 'Change Setting',
            'function' => 'doConfigSet',
            'shortcut' => 'cs',
            'options' => array(
                'channel' => array(
                    'shortopt' => 'c',
                    'doc' => 'show configuration variables for another channel',
                    'arg' => 'CHAN',
                    ),
),
            'doc' => '<parameter> <value> [layer]
Sets the value of one configuration parameter.  The first argument is
the name of the parameter, the second argument is the new value.  Some
parameters are subject to validation, and the command will fail with
an error message if the new value does not make sense.  An optional
third argument may be used to specify in which layer to set the
configuration parameter.  The default layer is "user".  The
configuration value will be set for the current channel, which
is controlled by the default_channel configuration variable.
',
            ),
        'config-help' => array(
            'summary' => 'Show Information About Setting',
            'function' => 'doConfigHelp',
            'shortcut' => 'ch',
            'options' => array(),
            'doc' => '[parameter]
Displays help for a configuration parameter.  Without arguments it
displays help for all configuration parameters.
',
           ),
        'config-create' => array(
            'summary' => 'Create a Default configuration file',
            'function' => 'doConfigCreate',
            'shortcut' => 'coc',
            'options' => array(
                'windows' => array(
                    'shortopt' => 'w',
                    'doc' => 'create a config file for a windows install',
                    ),
            ),
            'doc' => '<root path> <filename>
Create a default configuration file with all directory configuration
variables set to subdirectories of <root path>, and save it as <filename>.
This is useful especially for creating a configuration file for a remote
PEAR installation (using the --remoteconfig option of install, upgrade,
and uninstall).
',
            ),
        );

    /**
     * PEAR_Command_Config constructor.
     *
     * @access public
     */
    function __construct(&$ui, &$config)
    {
        parent::__construct($ui, $config);
    }

    function doConfigShow($command, $options, $params)
    {
        $layer = null;
        if (is_array($params)) {
            $layer = isset($params[0]) ? $params[0] : null;
        }

        // $params[0] -> the layer
        if ($error = $this->_checkLayer($layer)) {
            return $this->raiseError("config-show:$error");
        }

        $keys = $this->config->getKeys();
        sort($keys);
        $channel = isset($options['channel']) ? $options['channel'] :
            $this->config->get('default_channel');
        $reg = &$this->config->getRegistry();
        if (!$reg->channelExists($channel)) {
            return $this->raiseError('Channel "' . $channel . '" does not exist');
        }

        $channel = $reg->channelName($channel);
        $data = array('caption' => 'Configuration (channel ' . $channel . '):');
        foreach ($keys as $key) {
            $type = $this->config->getType($key);
            $value = $this->config->get($key, $layer, $channel);
            if ($type == 'password' && $value) {
                $value = '********';
            }

            if ($value === false) {
                $value = 'false';
            } elseif ($value === true) {
                $value = 'true';
            }

            $data['data'][$this->config->getGroup($key)][] = array($this->config->getPrompt($key) , $key, $value);
        }

        foreach ($this->config->getLayers() as $layer) {
            $data['data']['Config Files'][] = array(ucfirst($layer) . ' Configuration File', 'Filename' , $this->config->getConfFile($layer));
        }

        $this->ui->outputData($data, $command);
        return true;
    }

    function doConfigGet($command, $options, $params)
    {
        $args_cnt = is_array($params) ? count($params) : 0;
        switch ($args_cnt) {
            case 1:
                $config_key = $params[0];
                $layer = null;
                break;
            case 2:
                $config_key = $params[0];
                $layer = $params[1];
                if ($error = $this->_checkLayer($layer)) {
                    return $this->raiseError("config-get:$error");
                }
                break;
            case 0:
            default:
                return $this->raiseError("config-get expects 1 or 2 parameters");
        }

        $reg = &$this->config->getRegistry();
        $channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel');
        if (!$reg->channelExists($channel)) {
            return $this->raiseError('Channel "' . $channel . '" does not exist');
        }

        $channel = $reg->channelName($channel);
        $this->ui->outputData($this->config->get($config_key, $layer, $channel), $command);
        return true;
    }

    function doConfigSet($command, $options, $params)
    {
        // $param[0] -> a parameter to set
        // $param[1] -> the value for the parameter
        // $param[2] -> the layer
        $failmsg = '';
        if (count($params) < 2 || count($params) > 3) {
            $failmsg .= "config-set expects 2 or 3 parameters";
            return PEAR::raiseError($failmsg);
        }

        if (isset($params[2]) && ($error = $this->_checkLayer($params[2]))) {
            $failmsg .= $error;
            return PEAR::raiseError("config-set:$failmsg");
        }

        $channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel');
        $reg = &$this->config->getRegistry();
        if (!$reg->channelExists($channel)) {
            return $this->raiseError('Channel "' . $channel . '" does not exist');
        }

        $channel = $reg->channelName($channel);
        if ($params[0] == 'default_channel' && !$reg->channelExists($params[1])) {
            return $this->raiseError('Channel "' . $params[1] . '" does not exist');
        }

        if ($params[0] == 'preferred_mirror'
            && (
                !$reg->mirrorExists($channel, $params[1]) &&
                (!$reg->channelExists($params[1]) || $channel != $params[1])
            )
        ) {
            $msg  = 'Channel Mirror "' . $params[1] . '" does not exist';
            $msg .= ' in your registry for channel "' . $channel . '".';
            $msg .= "\n" . 'Attempt to run "pear channel-update ' . $channel .'"';
            $msg .= ' if you believe this mirror should exist as you may';
            $msg .= ' have outdated channel information.';
            return $this->raiseError($msg);
        }

        if (count($params) == 2) {
            array_push($params, 'user');
            $layer = 'user';
        } else {
            $layer = $params[2];
        }

        array_push($params, $channel);
        if (!call_user_func_array(array(&$this->config, 'set'), $params)) {
            array_pop($params);
            $failmsg = "config-set (" . implode(", ", $params) . ") failed, channel $channel";
        } else {
            $this->config->store($layer);
        }

        if ($failmsg) {
            return $this->raiseError($failmsg);
        }

        $this->ui->outputData('config-set succeeded', $command);
        return true;
    }

    function doConfigHelp($command, $options, $params)
    {
        if (empty($params)) {
            $params = $this->config->getKeys();
        }

        $data['caption']  = "Config help" . ((count($params) == 1) ? " for $params[0]" : '');
        $data['headline'] = array('Name', 'Type', 'Description');
        $data['border']   = true;
        foreach ($params as $name) {
            $type = $this->config->getType($name);
            $docs = $this->config->getDocs($name);
            if ($type == 'set') {
                $docs = rtrim($docs) . "\nValid set: " .
                    implode(' ', $this->config->getSetValues($name));
            }

            $data['data'][] = array($name, $type, $docs);
        }

        $this->ui->outputData($data, $command);
    }

    function doConfigCreate($command, $options, $params)
    {
        if (count($params) != 2) {
            return PEAR::raiseError('config-create: must have 2 parameters, root path and ' .
                'filename to save as');
        }

        $root = $params[0];
        // Clean up the DIRECTORY_SEPARATOR mess
        $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
        $root = preg_replace(array('!\\\\+!', '!/+!', "!$ds2+!"),
                             array('/', '/', '/'),
                            $root);
        if ($root[0] != '/') {
            if (!isset($options['windows'])) {
                return PEAR::raiseError('Root directory must be an absolute path beginning ' .
                    'with "/", was: "' . $root . '"');
            }

            if (!preg_match('/^[A-Za-z]:/', $root)) {
                return PEAR::raiseError('Root directory must be an absolute path beginning ' .
                    'with "\\" or "C:\\", was: "' . $root . '"');
            }
        }

        $windows = isset($options['windows']);
        if ($windows) {
            $root = str_replace('/', '\\', $root);
        }

        if (!file_exists($params[1]) && !@touch($params[1])) {
            return PEAR::raiseError('Could not create "' . $params[1] . '"');
        }

        $params[1] = realpath($params[1]);
        $config = new PEAR_Config($params[1], '#no#system#config#', false, false);
        if ($root[strlen($root) - 1] == '/') {
            $root = substr($root, 0, strlen($root) - 1);
        }

        $config->noRegistry();
        $config->set('php_dir', $windows ? "$root\\pear\\php" : "$root/pear/php", 'user');
        $config->set('data_dir', $windows ? "$root\\pear\\data" : "$root/pear/data");
        $config->set('www_dir', $windows ? "$root\\pear\\www" : "$root/pear/www");
        $config->set('cfg_dir', $windows ? "$root\\pear\\cfg" : "$root/pear/cfg");
        $config->set('ext_dir', $windows ? "$root\\pear\\ext" : "$root/pear/ext");
        $config->set('doc_dir', $windows ? "$root\\pear\\docs" : "$root/pear/docs");
        $config->set('test_dir', $windows ? "$root\\pear\\tests" : "$root/pear/tests");
        $config->set('cache_dir', $windows ? "$root\\pear\\cache" : "$root/pear/cache");
        $config->set('download_dir', $windows ? "$root\\pear\\download" : "$root/pear/download");
        $config->set('temp_dir', $windows ? "$root\\pear\\temp" : "$root/pear/temp");
        $config->set('bin_dir', $windows ? "$root\\pear" : "$root/pear");
        $config->set('man_dir', $windows ? "$root\\pear\\man" : "$root/pear/man");
        $config->writeConfigFile();
        $this->_showConfig($config);
        $this->ui->outputData('Successfully created default configuration file "' . $params[1] . '"',
            $command);
    }

    function _showConfig(&$config)
    {
        $params = array('user');
        $keys = $config->getKeys();
        sort($keys);
        $channel = 'pear.php.net';
        $data = array('caption' => 'Configuration (channel ' . $channel . '):');
        foreach ($keys as $key) {
            $type = $config->getType($key);
            $value = $config->get($key, 'user', $channel);
            if ($type == 'password' && $value) {
                $value = '********';
            }

            if ($value === false) {
                $value = 'false';
            } elseif ($value === true) {
                $value = 'true';
            }
            $data['data'][$config->getGroup($key)][] =
                array($config->getPrompt($key) , $key, $value);
        }

        foreach ($config->getLayers() as $layer) {
            $data['data']['Config Files'][] =
                array(ucfirst($layer) . ' Configuration File', 'Filename' ,
                    $config->getConfFile($layer));
        }

        $this->ui->outputData($data, 'config-show');
        return true;
    }

    /**
     * Checks if a layer is defined or not
     *
     * @param string $layer The layer to search for
     * @return mixed False on no error or the error message
     */
    function _checkLayer($layer = null)
    {
        if (!empty($layer) && $layer != 'default') {
            $layers = $this->config->getLayers();
            if (!in_array($layer, $layers)) {
                return " only the layers: \"" . implode('" or "', $layers) . "\" are supported";
            }
        }

        return false;
    }
}
PKn�Z݄<iiPEAR/Command/Mirror.xmlnu�[���<commands version="1.0">
 <download-all>
  <summary>Downloads each available package from the default channel</summary>
  <function>doDownloadAll</function>
  <shortcut>da</shortcut>
  <options>
   <channel>
    <shortopt>c</shortopt>
    <doc>specify a channel other than the default channel</doc>
    <arg>CHAN</arg>
   </channel>
  </options>
  <doc>
Requests a list of available packages from the default channel ({config default_channel})
and downloads them to current working directory.  Note: only
packages within preferred_state ({config preferred_state}) will be downloaded</doc>
 </download-all>
</commands>PKn�Z,��t"u"uPEAR/Command/Remote.phpnu�[���<?php
/**
 * PEAR_Command_Remote (remote-info, list-upgrades, remote-list, search, list-all, download,
 * clear-cache commands)
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 0.1
 */

/**
 * base class
 */
require_once 'PEAR/Command/Common.php';
require_once 'PEAR/REST.php';

/**
 * PEAR commands for remote server querying
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 0.1
 */
class PEAR_Command_Remote extends PEAR_Command_Common
{
    var $commands = array(
        'remote-info' => array(
            'summary' => 'Information About Remote Packages',
            'function' => 'doRemoteInfo',
            'shortcut' => 'ri',
            'options' => array(),
            'doc' => '<package>
Get details on a package from the server.',
            ),
        'list-upgrades' => array(
            'summary' => 'List Available Upgrades',
            'function' => 'doListUpgrades',
            'shortcut' => 'lu',
            'options' => array(
                'channelinfo' => array(
                    'shortopt' => 'i',
                    'doc' => 'output fully channel-aware data, even on failure',
                    ),
            ),
            'doc' => '[preferred_state]
List releases on the server of packages you have installed where
a newer version is available with the same release state (stable etc.)
or the state passed as the second parameter.'
            ),
        'remote-list' => array(
            'summary' => 'List Remote Packages',
            'function' => 'doRemoteList',
            'shortcut' => 'rl',
            'options' => array(
                'channel' =>
                    array(
                    'shortopt' => 'c',
                    'doc' => 'specify a channel other than the default channel',
                    'arg' => 'CHAN',
                    )
                ),
            'doc' => '
Lists the packages available on the configured server along with the
latest stable release of each package.',
            ),
        'search' => array(
            'summary' => 'Search remote package database',
            'function' => 'doSearch',
            'shortcut' => 'sp',
            'options' => array(
                'channel' =>
                    array(
                    'shortopt' => 'c',
                    'doc' => 'specify a channel other than the default channel',
                    'arg' => 'CHAN',
                    ),
                'allchannels' => array(
                    'shortopt' => 'a',
                    'doc' => 'search packages from all known channels',
                    ),
                'channelinfo' => array(
                    'shortopt' => 'i',
                    'doc' => 'output fully channel-aware data, even on failure',
                    ),
                ),
            'doc' => '[packagename] [packageinfo]
Lists all packages which match the search parameters.  The first
parameter is a fragment of a packagename.  The default channel
will be used unless explicitly overridden.  The second parameter
will be used to match any portion of the summary/description',
            ),
        'list-all' => array(
            'summary' => 'List All Packages',
            'function' => 'doListAll',
            'shortcut' => 'la',
            'options' => array(
                'channel' =>
                    array(
                    'shortopt' => 'c',
                    'doc' => 'specify a channel other than the default channel',
                    'arg' => 'CHAN',
                    ),
                'channelinfo' => array(
                    'shortopt' => 'i',
                    'doc' => 'output fully channel-aware data, even on failure',
                    ),
                ),
            'doc' => '
Lists the packages available on the configured server along with the
latest stable release of each package.',
            ),
        'download' => array(
            'summary' => 'Download Package',
            'function' => 'doDownload',
            'shortcut' => 'd',
            'options' => array(
                'nocompress' => array(
                    'shortopt' => 'Z',
                    'doc' => 'download an uncompressed (.tar) file',
                    ),
                ),
            'doc' => '<package>...
Download package tarballs.  The files will be named as suggested by the
server, for example if you download the DB package and the latest stable
version of DB is 1.6.5, the downloaded file will be DB-1.6.5.tgz.',
            ),
        'clear-cache' => array(
            'summary' => 'Clear Web Services Cache',
            'function' => 'doClearCache',
            'shortcut' => 'cc',
            'options' => array(),
            'doc' => '
Clear the REST cache. See also the cache_ttl configuration
parameter.
',
            ),
        );

    /**
     * PEAR_Command_Remote constructor.
     *
     * @access public
     */
    function __construct(&$ui, &$config)
    {
        parent::__construct($ui, $config);
    }

    function _checkChannelForStatus($channel, $chan)
    {
        if (PEAR::isError($chan)) {
            $this->raiseError($chan);
        }
        if (!is_a($chan, 'PEAR_ChannelFile')) {
            return $this->raiseError('Internal corruption error: invalid channel "' .
                $channel . '"');
        }
        $rest = new PEAR_REST($this->config);
        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        $mirror = $this->config->get('preferred_mirror', null,
                                     $channel);
        $a = $rest->downloadHttp('http://' . $channel .
            '/channel.xml', $chan->lastModified());
        PEAR::staticPopErrorHandling();
        if (!PEAR::isError($a) && $a) {
            $this->ui->outputData('WARNING: channel "' . $channel . '" has ' .
                'updated its protocols, use "' . PEAR_RUNTYPE . ' channel-update ' . $channel .
                '" to update');
        }
    }

    function doRemoteInfo($command, $options, $params)
    {
        if (sizeof($params) != 1) {
            return $this->raiseError("$command expects one param: the remote package name");
        }
        $savechannel = $channel = $this->config->get('default_channel');
        $reg = &$this->config->getRegistry();
        $package = $params[0];
        $parsed = $reg->parsePackageName($package, $channel);
        if (PEAR::isError($parsed)) {
            return $this->raiseError('Invalid package name "' . $package . '"');
        }

        $channel = $parsed['channel'];
        $this->config->set('default_channel', $channel);
        $chan = $reg->getChannel($channel);
        if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
            return $e;
        }

        $mirror = $this->config->get('preferred_mirror');
        if ($chan->supportsREST($mirror) && $base = $chan->getBaseURL('REST1.0', $mirror)) {
            $rest = &$this->config->getREST('1.0', array());
            $info = $rest->packageInfo($base, $parsed['package'], $channel);
        }

        if (!isset($info)) {
            return $this->raiseError('No supported protocol was found');
        }

        if (PEAR::isError($info)) {
            $this->config->set('default_channel', $savechannel);
            return $this->raiseError($info);
        }

        if (!isset($info['name'])) {
            return $this->raiseError('No remote package "' . $package . '" was found');
        }

        $installed = $reg->packageInfo($info['name'], null, $channel);
        $info['installed'] = $installed ? $installed['version'] : '- no -';
        if (is_array($info['installed'])) {
            $info['installed'] = $info['installed']['release'];
        }

        $this->ui->outputData($info, $command);
        $this->config->set('default_channel', $savechannel);

        return true;
    }

    function doRemoteList($command, $options, $params)
    {
        $savechannel = $channel = $this->config->get('default_channel');
        $reg = &$this->config->getRegistry();
        if (isset($options['channel'])) {
            $channel = $options['channel'];
            if (!$reg->channelExists($channel)) {
                return $this->raiseError('Channel "' . $channel . '" does not exist');
            }

            $this->config->set('default_channel', $channel);
        }

        $chan = $reg->getChannel($channel);
        if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
            return $e;
        }

        $list_options = false;
        if ($this->config->get('preferred_state') == 'stable') {
            $list_options = true;
        }

        $available = array();
        if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
              $base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror'))
        ) {
            // use faster list-all if available
            $rest = &$this->config->getREST('1.1', array());
            $available = $rest->listAll($base, $list_options, true, false, false, $chan->getName());
        } elseif ($chan->supportsREST($this->config->get('preferred_mirror')) &&
              $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
            $rest = &$this->config->getREST('1.0', array());
            $available = $rest->listAll($base, $list_options, true, false, false, $chan->getName());
        }

        if (PEAR::isError($available)) {
            $this->config->set('default_channel', $savechannel);
            return $this->raiseError($available);
        }

        $i = $j = 0;
        $data = array(
            'caption' => 'Channel ' . $channel . ' Available packages:',
            'border' => true,
            'headline' => array('Package', 'Version'),
            'channel' => $channel
            );

        if (count($available) == 0) {
            $data = '(no packages available yet)';
        } else {
            foreach ($available as $name => $info) {
                $version = (isset($info['stable']) && $info['stable']) ? $info['stable'] : '-n/a-';
                $data['data'][] = array($name, $version);
            }
        }
        $this->ui->outputData($data, $command);
        $this->config->set('default_channel', $savechannel);
        return true;
    }

    function doListAll($command, $options, $params)
    {
        $savechannel = $channel = $this->config->get('default_channel');
        $reg = &$this->config->getRegistry();
        if (isset($options['channel'])) {
            $channel = $options['channel'];
            if (!$reg->channelExists($channel)) {
                return $this->raiseError("Channel \"$channel\" does not exist");
            }

            $this->config->set('default_channel', $channel);
        }

        $list_options = false;
        if ($this->config->get('preferred_state') == 'stable') {
            $list_options = true;
        }

        $chan = $reg->getChannel($channel);
        if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
            return $e;
        }

        if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
              $base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror'))) {
            // use faster list-all if available
            $rest = &$this->config->getREST('1.1', array());
            $available = $rest->listAll($base, $list_options, false, false, false, $chan->getName());
        } elseif ($chan->supportsREST($this->config->get('preferred_mirror')) &&
              $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
            $rest = &$this->config->getREST('1.0', array());
            $available = $rest->listAll($base, $list_options, false, false, false, $chan->getName());
        }

        if (PEAR::isError($available)) {
            $this->config->set('default_channel', $savechannel);
            return $this->raiseError('The package list could not be fetched from the remote server. Please try again. (Debug info: "' . $available->getMessage() . '")');
        }

        $data = array(
            'caption' => 'All packages [Channel ' . $channel . ']:',
            'border' => true,
            'headline' => array('Package', 'Latest', 'Local'),
            'channel' => $channel,
            );

        if (isset($options['channelinfo'])) {
            // add full channelinfo
            $data['caption'] = 'Channel ' . $channel . ' All packages:';
            $data['headline'] = array('Channel', 'Package', 'Latest', 'Local',
                'Description', 'Dependencies');
        }
        $local_pkgs = $reg->listPackages($channel);

        foreach ($available as $name => $info) {
            $installed = $reg->packageInfo($name, null, $channel);
            if ($installed && is_array($installed['version'])) {
                $installed['version'] = $installed['version']['release'];
            }
            $desc = $info['summary'];
            if (isset($params[$name])) {
                $desc .= "\n\n".$info['description'];
            }
            if (isset($options['mode']))
            {
                if ($options['mode'] == 'installed' && !isset($installed['version'])) {
                    continue;
                }
                if ($options['mode'] == 'notinstalled' && isset($installed['version'])) {
                    continue;
                }
                if ($options['mode'] == 'upgrades'
                      && (!isset($installed['version']) || version_compare($installed['version'],
                      $info['stable'], '>='))) {
                    continue;
                }
            }
            $pos = array_search(strtolower($name), $local_pkgs);
            if ($pos !== false) {
                unset($local_pkgs[$pos]);
            }

            if (isset($info['stable']) && !$info['stable']) {
                $info['stable'] = null;
            }

            if (isset($options['channelinfo'])) {
                // add full channelinfo
                if ($info['stable'] === $info['unstable']) {
                    $state = $info['state'];
                } else {
                    $state = 'stable';
                }
                $latest = $info['stable'].' ('.$state.')';
                $local = '';
                if (isset($installed['version'])) {
                    $inst_state = $reg->packageInfo($name, 'release_state', $channel);
                    $local = $installed['version'].' ('.$inst_state.')';
                }

                $packageinfo = array(
                    $channel,
                    $name,
                    $latest,
                    $local,
                    isset($desc) ? $desc : null,
                    isset($info['deps']) ? $info['deps'] : null,
                );
            } else {
                $packageinfo = array(
                    $reg->channelAlias($channel) . '/' . $name,
                    isset($info['stable']) ? $info['stable'] : null,
                    isset($installed['version']) ? $installed['version'] : null,
                    isset($desc) ? $desc : null,
                    isset($info['deps']) ? $info['deps'] : null,
                );
            }
            $data['data'][$info['category']][] = $packageinfo;
        }

        if (isset($options['mode']) && in_array($options['mode'], array('notinstalled', 'upgrades'))) {
            $this->config->set('default_channel', $savechannel);
            $this->ui->outputData($data, $command);
            return true;
        }

        foreach ($local_pkgs as $name) {
            $info = &$reg->getPackage($name, $channel);
            $data['data']['Local'][] = array(
                $reg->channelAlias($channel) . '/' . $info->getPackage(),
                '',
                $info->getVersion(),
                $info->getSummary(),
                $info->getDeps()
                );
        }

        $this->config->set('default_channel', $savechannel);
        $this->ui->outputData($data, $command);
        return true;
    }

    function doSearch($command, $options, $params)
    {
        if ((!isset($params[0]) || empty($params[0]))
            && (!isset($params[1]) || empty($params[1])))
        {
            return $this->raiseError('no valid search string supplied');
        }

        $channelinfo = isset($options['channelinfo']);
        $reg = &$this->config->getRegistry();
        if (isset($options['allchannels'])) {
            // search all channels
            unset($options['allchannels']);
            $channels = $reg->getChannels();
            $errors = array();
            PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
            foreach ($channels as $channel) {
                if ($channel->getName() != '__uri') {
                    $options['channel'] = $channel->getName();
                    $ret = $this->doSearch($command, $options, $params);
                    if (PEAR::isError($ret)) {
                        $errors[] = $ret;
                    }
                }
            }

            PEAR::staticPopErrorHandling();
            if (count($errors) !== 0) {
                // for now, only give first error
                return PEAR::raiseError($errors[0]);
            }

            return true;
        }

        $savechannel = $channel = $this->config->get('default_channel');
        $package = strtolower($params[0]);
        $summary = isset($params[1]) ? $params[1] : false;
        if (isset($options['channel'])) {
            $reg = &$this->config->getRegistry();
            $channel = $options['channel'];
            if (!$reg->channelExists($channel)) {
                return $this->raiseError('Channel "' . $channel . '" does not exist');
            }

            $this->config->set('default_channel', $channel);
        }

        $chan = $reg->getChannel($channel);
        if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
            return $e;
        }

        if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
              $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
            $rest = &$this->config->getREST('1.0', array());
            $available = $rest->listAll($base, false, false, $package, $summary, $chan->getName());
        }

        if (PEAR::isError($available)) {
            $this->config->set('default_channel', $savechannel);
            return $this->raiseError($available);
        }

        if (!$available && !$channelinfo) {
            // clean exit when not found, no error !
            $data = 'no packages found that match pattern "' . $package . '", for channel '.$channel.'.';
            $this->ui->outputData($data);
            $this->config->set('default_channel', $channel);
            return true;
        }

        if ($channelinfo) {
            $data = array(
                'caption' => 'Matched packages, channel ' . $channel . ':',
                'border' => true,
                'headline' => array('Channel', 'Package', 'Stable/(Latest)', 'Local'),
                'channel' => $channel
                );
        } else {
            $data = array(
                'caption' => 'Matched packages, channel ' . $channel . ':',
                'border' => true,
                'headline' => array('Package', 'Stable/(Latest)', 'Local'),
                'channel' => $channel
                );
        }

        if (!$available && $channelinfo) {
            unset($data['headline']);
            $data['data'] = 'No packages found that match pattern "' . $package . '".';
            $available = array();
        }

        foreach ($available as $name => $info) {
            $installed = $reg->packageInfo($name, null, $channel);
            $desc = $info['summary'];
            if (isset($params[$name]))
                $desc .= "\n\n".$info['description'];

            if (!isset($info['stable']) || !$info['stable']) {
                $version_remote = 'none';
            } else {
                if ($info['unstable']) {
                    $version_remote = $info['unstable'];
                } else {
                    $version_remote = $info['stable'];
                }
                $version_remote .= ' ('.$info['state'].')';
            }
            $version = is_array($installed['version']) ? $installed['version']['release'] :
                $installed['version'];
            if ($channelinfo) {
                $packageinfo = array(
                    $channel,
                    $name,
                    $version_remote,
                    $version,
                    $desc,
                );
            } else {
                $packageinfo = array(
                    $name,
                    $version_remote,
                    $version,
                    $desc,
                );
            }
            $data['data'][$info['category']][] = $packageinfo;
        }

        $this->ui->outputData($data, $command);
        $this->config->set('default_channel', $channel);
        return true;
    }

    function &getDownloader($options)
    {
        if (!class_exists('PEAR_Downloader')) {
            require_once 'PEAR/Downloader.php';
        }
        $a = new PEAR_Downloader($this->ui, $options, $this->config);
        return $a;
    }

    function doDownload($command, $options, $params)
    {
        // make certain that dependencies are ignored
        $options['downloadonly'] = 1;

        // eliminate error messages for preferred_state-related errors
        /* TODO: Should be an option, but until now download does respect
           preferred state */
        /* $options['ignorepreferred_state'] = 1; */
        // eliminate error messages for preferred_state-related errors

        $downloader = &$this->getDownloader($options);
        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        $e = $downloader->setDownloadDir(getcwd());
        PEAR::staticPopErrorHandling();
        if (PEAR::isError($e)) {
            return $this->raiseError('Current directory is not writeable, cannot download');
        }

        $errors = array();
        $downloaded = array();
        $err = $downloader->download($params);
        if (PEAR::isError($err)) {
            return $err;
        }

        $errors = $downloader->getErrorMsgs();
        if (count($errors)) {
            foreach ($errors as $error) {
                if ($error !== null) {
                    $this->ui->outputData($error);
                }
            }

            return $this->raiseError("$command failed");
        }

        $downloaded = $downloader->getDownloadedPackages();
        foreach ($downloaded as $pkg) {
            $this->ui->outputData("File $pkg[file] downloaded", $command);
        }

        return true;
    }

    function downloadCallback($msg, $params = null)
    {
        if ($msg == 'done') {
            $this->bytes_downloaded = $params;
        }
    }

    function doListUpgrades($command, $options, $params)
    {
        require_once 'PEAR/Common.php';
        if (isset($params[0]) && !is_array(PEAR_Common::betterStates($params[0]))) {
            return $this->raiseError($params[0] . ' is not a valid state (stable/beta/alpha/devel/etc.) try "pear help list-upgrades"');
        }

        $savechannel = $channel = $this->config->get('default_channel');
        $reg = &$this->config->getRegistry();
        foreach ($reg->listChannels() as $channel) {
            $inst = array_flip($reg->listPackages($channel));
            if (!count($inst)) {
                continue;
            }

            if ($channel == '__uri') {
                continue;
            }

            $this->config->set('default_channel', $channel);
            $state = empty($params[0]) ? $this->config->get('preferred_state') : $params[0];

            $caption = $channel . ' Available Upgrades';
            $chan = $reg->getChannel($channel);
            if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
                return $e;
            }

            $latest = array();
            $base2  = false;
            $preferred_mirror = $this->config->get('preferred_mirror');
            if ($chan->supportsREST($preferred_mirror) &&
                (
                   ($base2 = $chan->getBaseURL('REST1.3', $preferred_mirror))
                   || ($base  = $chan->getBaseURL('REST1.0', $preferred_mirror))
                )

            ) {
                if ($base2) {
                    $rest = &$this->config->getREST('1.3', array());
                    $base = $base2;
                } else {
                    $rest = &$this->config->getREST('1.0', array());
                }

                if (empty($state) || $state == 'any') {
                    $state = false;
                } else {
                    $caption .= ' (' . implode(', ', PEAR_Common::betterStates($state, true)) . ')';
                }

                PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                $latest = $rest->listLatestUpgrades($base, $state, $inst, $channel, $reg);
                PEAR::staticPopErrorHandling();
            }

            if (PEAR::isError($latest)) {
                $this->ui->outputData($latest->getMessage());
                continue;
            }

            $caption .= ':';
            if (PEAR::isError($latest)) {
                $this->config->set('default_channel', $savechannel);
                return $latest;
            }

            $data = array(
                'caption' => $caption,
                'border' => 1,
                'headline' => array('Channel', 'Package', 'Local', 'Remote', 'Size'),
                'channel' => $channel
                );

            foreach ((array)$latest as $pkg => $info) {
                $package = strtolower($pkg);
                if (!isset($inst[$package])) {
                    // skip packages we don't have installed
                    continue;
                }

                extract($info);
                $inst_version = $reg->packageInfo($package, 'version', $channel);
                $inst_state   = $reg->packageInfo($package, 'release_state', $channel);
                if (version_compare("$version", "$inst_version", "le")) {
                    // installed version is up-to-date
                    continue;
                }

                if ($filesize >= 20480) {
                    $filesize += 1024 - ($filesize % 1024);
                    $fs = sprintf("%dkB", $filesize / 1024);
                } elseif ($filesize > 0) {
                    $filesize += 103 - ($filesize % 103);
                    $fs = sprintf("%.1fkB", $filesize / 1024.0);
                } else {
                    $fs = "  -"; // XXX center instead
                }

                $data['data'][] = array($channel, $pkg, "$inst_version ($inst_state)", "$version ($state)", $fs);
            }

            if (isset($options['channelinfo'])) {
                if (empty($data['data'])) {
                    unset($data['headline']);
                    if (count($inst) == 0) {
                        $data['data'] = '(no packages installed)';
                    } else {
                        $data['data'] = '(no upgrades available)';
                    }
                }
                $this->ui->outputData($data, $command);
            } else {
                if (empty($data['data'])) {
                    $this->ui->outputData('Channel ' . $channel . ': No upgrades available');
                } else {
                    $this->ui->outputData($data, $command);
                }
            }
        }

        $this->config->set('default_channel', $savechannel);
        return true;
    }

    function doClearCache($command, $options, $params)
    {
        $cache_dir = $this->config->get('cache_dir');
        $verbose   = $this->config->get('verbose');
        $output = '';
        if (!file_exists($cache_dir) || !is_dir($cache_dir)) {
            return $this->raiseError("$cache_dir does not exist or is not a directory");
        }

        if (!($dp = @opendir($cache_dir))) {
            return $this->raiseError("opendir($cache_dir) failed: $php_errormsg");
        }

        if ($verbose >= 1) {
            $output .= "reading directory $cache_dir\n";
        }

        $num = 0;
        while ($ent = readdir($dp)) {
            if (preg_match('/rest.cache(file|id)\\z/', $ent)) {
                $path = $cache_dir . DIRECTORY_SEPARATOR . $ent;
                if (file_exists($path)) {
                    $ok = @unlink($path);
                } else {
                    $ok = false;
                    $php_errormsg = '';
                }

                if ($ok) {
                    if ($verbose >= 2) {
                        $output .= "deleted $path\n";
                    }
                    $num++;
                } elseif ($verbose >= 1) {
                    $output .= "failed to delete $path $php_errormsg\n";
                }
            }
        }

        closedir($dp);
        if ($verbose >= 1) {
            $output .= "$num cache entries cleared\n";
        }

        $this->ui->outputData(rtrim($output), $command);
        return $num;
    }
}
PKn�Z
�\���PEAR/Command/Remote.xmlnu�[���<commands version="1.0">
 <remote-info>
  <summary>Information About Remote Packages</summary>
  <function>doRemoteInfo</function>
  <shortcut>ri</shortcut>
  <options />
  <doc>&lt;package&gt;
Get details on a package from the server.</doc>
 </remote-info>
 <list-upgrades>
  <summary>List Available Upgrades</summary>
  <function>doListUpgrades</function>
  <shortcut>lu</shortcut>
  <options>
   <channelinfo>
    <shortopt>i</shortopt>
    <doc>output fully channel-aware data, even on failure</doc>
   </channelinfo>
  </options>
  <doc>[preferred_state]
List releases on the server of packages you have installed where
a newer version is available with the same release state (stable etc.)
or the state passed as the second parameter.</doc>
 </list-upgrades>
 <remote-list>
  <summary>List Remote Packages</summary>
  <function>doRemoteList</function>
  <shortcut>rl</shortcut>
  <options>
   <channel>
    <shortopt>c</shortopt>
    <doc>specify a channel other than the default channel</doc>
    <arg>CHAN</arg>
   </channel>
  </options>
  <doc>
Lists the packages available on the configured server along with the
latest stable release of each package.</doc>
 </remote-list>
 <search>
  <summary>Search remote package database</summary>
  <function>doSearch</function>
  <shortcut>sp</shortcut>
  <options>
   <channel>
    <shortopt>c</shortopt>
    <doc>specify a channel other than the default channel</doc>
    <arg>CHAN</arg>
   </channel>
   <allchannels>
    <shortopt>a</shortopt>
    <doc>search packages from all known channels</doc>
   </allchannels>
   <channelinfo>
    <shortopt>i</shortopt>
    <doc>output fully channel-aware data, even on failure</doc>
   </channelinfo>
  </options>
  <doc>[packagename] [packageinfo]
Lists all packages which match the search parameters.  The first
parameter is a fragment of a packagename.  The default channel
will be used unless explicitly overridden.  The second parameter
will be used to match any portion of the summary/description</doc>
 </search>
 <list-all>
  <summary>List All Packages</summary>
  <function>doListAll</function>
  <shortcut>la</shortcut>
  <options>
   <channel>
    <shortopt>c</shortopt>
    <doc>specify a channel other than the default channel</doc>
    <arg>CHAN</arg>
   </channel>
   <channelinfo>
    <shortopt>i</shortopt>
    <doc>output fully channel-aware data, even on failure</doc>
   </channelinfo>
  </options>
  <doc>
Lists the packages available on the configured server along with the
latest stable release of each package.</doc>
 </list-all>
 <download>
  <summary>Download Package</summary>
  <function>doDownload</function>
  <shortcut>d</shortcut>
  <options>
   <nocompress>
    <shortopt>Z</shortopt>
    <doc>download an uncompressed (.tar) file</doc>
   </nocompress>
  </options>
  <doc>&lt;package&gt;...
Download package tarballs.  The files will be named as suggested by the
server, for example if you download the DB package and the latest stable
version of DB is 1.6.5, the downloaded file will be DB-1.6.5.tgz.</doc>
 </download>
 <clear-cache>
  <summary>Clear Web Services Cache</summary>
  <function>doClearCache</function>
  <shortcut>cc</shortcut>
  <options />
  <doc>
Clear the XML-RPC/REST cache.  See also the cache_ttl configuration
parameter.
</doc>
 </clear-cache>
</commands>PKn�Zj���!�!PEAR/Command/Install.xmlnu�[���<commands version="1.0">
 <install>
  <summary>Install Package</summary>
  <function>doInstall</function>
  <shortcut>i</shortcut>
  <options>
   <force>
    <shortopt>f</shortopt>
    <doc>will overwrite newer installed packages</doc>
   </force>
   <loose>
    <shortopt>l</shortopt>
    <doc>do not check for recommended dependency version</doc>
   </loose>
   <nodeps>
    <shortopt>n</shortopt>
    <doc>ignore dependencies, install anyway</doc>
   </nodeps>
   <register-only>
    <shortopt>r</shortopt>
    <doc>do not install files, only register the package as installed</doc>
   </register-only>
   <soft>
    <shortopt>s</shortopt>
    <doc>soft install, fail silently, or upgrade if already installed</doc>
   </soft>
   <nobuild>
    <shortopt>B</shortopt>
    <doc>don&#039;t build C extensions</doc>
   </nobuild>
   <configureoptions>
    <shortopt>D</shortopt>
    <arg>OPTION1=VALUE[ OPTION2=VALUE]</arg>
   </configureoptions>
   <nocompress>
    <shortopt>Z</shortopt>
    <doc>request uncompressed files when downloading</doc>
   </nocompress>
   <installroot>
    <shortopt>R</shortopt>
    <doc>root directory used when installing files (ala PHP&#039;s INSTALL_ROOT), use packagingroot for RPM</doc>
    <arg>DIR</arg>
   </installroot>
   <packagingroot>
    <shortopt>P</shortopt>
    <doc>root directory used when packaging files, like RPM packaging</doc>
    <arg>DIR</arg>
   </packagingroot>
   <ignore-errors>
    <shortopt></shortopt>
    <doc>force install even if there were errors</doc>
   </ignore-errors>
   <alldeps>
    <shortopt>a</shortopt>
    <doc>install all required and optional dependencies</doc>
   </alldeps>
   <onlyreqdeps>
    <shortopt>o</shortopt>
    <doc>install all required dependencies</doc>
   </onlyreqdeps>
   <offline>
    <shortopt>O</shortopt>
    <doc>do not attempt to download any urls or contact channels</doc>
   </offline>
   <pretend>
    <shortopt>p</shortopt>
    <doc>Only list the packages that would be downloaded</doc>
   </pretend>
  </options>
  <doc>[channel/]&lt;package&gt; ...
Installs one or more PEAR packages.  You can specify a package to
install in four ways:

&quot;Package-1.0.tgz&quot; : installs from a local file

&quot;http://example.com/Package-1.0.tgz&quot; : installs from
anywhere on the net.

&quot;package.xml&quot; : installs the package described in
package.xml.  Useful for testing, or for wrapping a PEAR package in
another package manager such as RPM.

&quot;Package[-version/state][.tar]&quot; : queries your default channel&#039;s server
({config master_server}) and downloads the newest package with
the preferred quality/state ({config preferred_state}).

To retrieve Package version 1.1, use &quot;Package-1.1,&quot; to retrieve
Package state beta, use &quot;Package-beta.&quot;  To retrieve an uncompressed
file, append .tar (make sure there is no file by the same name first)

To download a package from another channel, prefix with the channel name like
&quot;channel/Package&quot;

More than one package may be specified at once.  It is ok to mix these
four ways of specifying packages.
</doc>
 </install>
 <upgrade>
  <summary>Upgrade Package</summary>
  <function>doInstall</function>
  <shortcut>up</shortcut>
  <options>
   <channel>
    <shortopt>c</shortopt>
    <doc>upgrade packages from a specific channel</doc>
    <arg>CHAN</arg>
   </channel>
   <force>
    <shortopt>f</shortopt>
    <doc>overwrite newer installed packages</doc>
   </force>
   <loose>
    <shortopt>l</shortopt>
    <doc>do not check for recommended dependency version</doc>
   </loose>
   <nodeps>
    <shortopt>n</shortopt>
    <doc>ignore dependencies, upgrade anyway</doc>
   </nodeps>
   <register-only>
    <shortopt>r</shortopt>
    <doc>do not install files, only register the package as upgraded</doc>
   </register-only>
   <nobuild>
    <shortopt>B</shortopt>
    <doc>don&#039;t build C extensions</doc>
   </nobuild>
   <nocompress>
    <shortopt>Z</shortopt>
    <doc>request uncompressed files when downloading</doc>
   </nocompress>
   <installroot>
    <shortopt>R</shortopt>
    <doc>root directory used when installing files (ala PHP&#039;s INSTALL_ROOT)</doc>
    <arg>DIR</arg>
   </installroot>
   <ignore-errors>
    <shortopt></shortopt>
    <doc>force install even if there were errors</doc>
   </ignore-errors>
   <alldeps>
    <shortopt>a</shortopt>
    <doc>install all required and optional dependencies</doc>
   </alldeps>
   <onlyreqdeps>
    <shortopt>o</shortopt>
    <doc>install all required dependencies</doc>
   </onlyreqdeps>
   <offline>
    <shortopt>O</shortopt>
    <doc>do not attempt to download any urls or contact channels</doc>
   </offline>
   <pretend>
    <shortopt>p</shortopt>
    <doc>Only list the packages that would be downloaded</doc>
   </pretend>
  </options>
  <doc>&lt;package&gt; ...
Upgrades one or more PEAR packages.  See documentation for the
&quot;install&quot; command for ways to specify a package.

When upgrading, your package will be updated if the provided new
package has a higher version number (use the -f option if you need to
upgrade anyway).

More than one package may be specified at once.
</doc>
 </upgrade>
 <upgrade-all>
  <summary>Upgrade All Packages [Deprecated in favor of calling upgrade with no parameters]</summary>
  <function>doUpgradeAll</function>
  <shortcut>ua</shortcut>
  <options>
   <channel>
    <shortopt>c</shortopt>
    <doc>upgrade packages from a specific channel</doc>
    <arg>CHAN</arg>
   </channel>
   <nodeps>
    <shortopt>n</shortopt>
    <doc>ignore dependencies, upgrade anyway</doc>
   </nodeps>
   <register-only>
    <shortopt>r</shortopt>
    <doc>do not install files, only register the package as upgraded</doc>
   </register-only>
   <nobuild>
    <shortopt>B</shortopt>
    <doc>don&#039;t build C extensions</doc>
   </nobuild>
   <nocompress>
    <shortopt>Z</shortopt>
    <doc>request uncompressed files when downloading</doc>
   </nocompress>
   <installroot>
    <shortopt>R</shortopt>
    <doc>root directory used when installing files (ala PHP&#039;s INSTALL_ROOT), use packagingroot for RPM</doc>
    <arg>DIR</arg>
   </installroot>
   <ignore-errors>
    <shortopt></shortopt>
    <doc>force install even if there were errors</doc>
   </ignore-errors>
   <loose>
    <shortopt></shortopt>
    <doc>do not check for recommended dependency version</doc>
   </loose>
  </options>
  <doc>
WARNING: This function is deprecated in favor of using the upgrade command with no params

Upgrades all packages that have a newer release available.  Upgrades are
done only if there is a release available of the state specified in
&quot;preferred_state&quot; (currently {config preferred_state}), or a state considered
more stable.
</doc>
 </upgrade-all>
 <uninstall>
  <summary>Un-install Package</summary>
  <function>doUninstall</function>
  <shortcut>un</shortcut>
  <options>
   <nodeps>
    <shortopt>n</shortopt>
    <doc>ignore dependencies, uninstall anyway</doc>
   </nodeps>
   <register-only>
    <shortopt>r</shortopt>
    <doc>do not remove files, only register the packages as not installed</doc>
   </register-only>
   <installroot>
    <shortopt>R</shortopt>
    <doc>root directory used when installing files (ala PHP&#039;s INSTALL_ROOT)</doc>
    <arg>DIR</arg>
   </installroot>
   <ignore-errors>
    <shortopt></shortopt>
    <doc>force install even if there were errors</doc>
   </ignore-errors>
   <offline>
    <shortopt>O</shortopt>
    <doc>do not attempt to uninstall remotely</doc>
   </offline>
  </options>
  <doc>[channel/]&lt;package&gt; ...
Uninstalls one or more PEAR packages.  More than one package may be
specified at once.  Prefix with channel name to uninstall from a
channel not in your default channel ({config default_channel})
</doc>
 </uninstall>
 <bundle>
  <summary>Unpacks a Pecl Package</summary>
  <function>doBundle</function>
  <shortcut>bun</shortcut>
  <options>
   <destination>
    <shortopt>d</shortopt>
    <doc>Optional destination directory for unpacking (defaults to current path or &quot;ext&quot; if exists)</doc>
    <arg>DIR</arg>
   </destination>
   <force>
    <shortopt>f</shortopt>
    <doc>Force the unpacking even if there were errors in the package</doc>
   </force>
  </options>
  <doc>&lt;package&gt;
Unpacks a Pecl Package into the selected location. It will download the
package if needed.
</doc>
 </bundle>
 <run-scripts>
  <summary>Run Post-Install Scripts bundled with a package</summary>
  <function>doRunScripts</function>
  <shortcut>rs</shortcut>
  <options />
  <doc>&lt;package&gt;
Run post-installation scripts in package &lt;package&gt;, if any exist.
</doc>
 </run-scripts>
</commands>PKo�Z�%q����PEAR/Command/Channels.phpnu�[���<?php
// /* vim: set expandtab tabstop=4 shiftwidth=4: */
/**
 * PEAR_Command_Channels (list-channels, update-channels, channel-delete, channel-add,
 * channel-update, channel-info, channel-alias, channel-discover commands)
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a1
 */

/**
 * base class
 */
require_once 'PEAR/Command/Common.php';

define('PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS', -500);

/**
 * PEAR commands for managing channels.
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 */
class PEAR_Command_Channels extends PEAR_Command_Common
{
    var $commands = array(
        'list-channels' => array(
            'summary' => 'List Available Channels',
            'function' => 'doList',
            'shortcut' => 'lc',
            'options' => array(),
            'doc' => '
List all available channels for installation.
',
            ),
        'update-channels' => array(
            'summary' => 'Update the Channel List',
            'function' => 'doUpdateAll',
            'shortcut' => 'uc',
            'options' => array(),
            'doc' => '
List all installed packages in all channels.
'
            ),
        'channel-delete' => array(
            'summary' => 'Remove a Channel From the List',
            'function' => 'doDelete',
            'shortcut' => 'cde',
            'options' => array(),
            'doc' => '<channel name>
Delete a channel from the registry.  You may not
remove any channel that has installed packages.
'
            ),
        'channel-add' => array(
            'summary' => 'Add a Channel',
            'function' => 'doAdd',
            'shortcut' => 'ca',
            'options' => array(),
            'doc' => '<channel.xml>
Add a private channel to the channel list.  Note that all
public channels should be synced using "update-channels".
Parameter may be either a local file or remote URL to a
channel.xml.
'
            ),
        'channel-update' => array(
            'summary' => 'Update an Existing Channel',
            'function' => 'doUpdate',
            'shortcut' => 'cu',
            'options' => array(
                'force' => array(
                    'shortopt' => 'f',
                    'doc' => 'will force download of new channel.xml if an existing channel name is used',
                    ),
                'channel' => array(
                    'shortopt' => 'c',
                    'arg' => 'CHANNEL',
                    'doc' => 'will force download of new channel.xml if an existing channel name is used',
                    ),
),
            'doc' => '[<channel.xml>|<channel name>]
Update a channel in the channel list directly.  Note that all
public channels can be synced using "update-channels".
Parameter may be a local or remote channel.xml, or the name of
an existing channel.
'
            ),
        'channel-info' => array(
            'summary' => 'Retrieve Information on a Channel',
            'function' => 'doInfo',
            'shortcut' => 'ci',
            'options' => array(),
            'doc' => '<package>
List the files in an installed package.
'
            ),
        'channel-alias' => array(
            'summary' => 'Specify an alias to a channel name',
            'function' => 'doAlias',
            'shortcut' => 'cha',
            'options' => array(),
            'doc' => '<channel> <alias>
Specify a specific alias to use for a channel name.
The alias may not be an existing channel name or
alias.
'
            ),
        'channel-discover' => array(
            'summary' => 'Initialize a Channel from its server',
            'function' => 'doDiscover',
            'shortcut' => 'di',
            'options' => array(),
            'doc' => '[<channel.xml>|<channel name>]
Initialize a channel from its server and create a local channel.xml.
If <channel name> is in the format "<username>:<password>@<channel>" then
<username> and <password> will be set as the login username/password for
<channel>. Use caution when passing the username/password in this way, as
it may allow other users on your computer to briefly view your username/
password via the system\'s process list.
'
            ),
        'channel-login' => array(
            'summary' => 'Connects and authenticates to remote channel server',
            'shortcut' => 'cli',
            'function' => 'doLogin',
            'options' => array(),
            'doc' => '<channel name>
Log in to a remote channel server.  If <channel name> is not supplied,
the default channel is used. To use remote functions in the installer
that require any kind of privileges, you need to log in first.  The
username and password you enter here will be stored in your per-user
PEAR configuration (~/.pearrc on Unix-like systems).  After logging
in, your username and password will be sent along in subsequent
operations on the remote server.',
            ),
        'channel-logout' => array(
            'summary' => 'Logs out from the remote channel server',
            'shortcut' => 'clo',
            'function' => 'doLogout',
            'options' => array(),
            'doc' => '<channel name>
Logs out from a remote channel server.  If <channel name> is not supplied,
the default channel is used. This command does not actually connect to the
remote server, it only deletes the stored username and password from your user
configuration.',
            ),
        );

    /**
     * PEAR_Command_Registry constructor.
     *
     * @access public
     */
    function __construct(&$ui, &$config)
    {
        parent::__construct($ui, $config);
    }

    function _sortChannels($a, $b)
    {
        return strnatcasecmp($a->getName(), $b->getName());
    }

    function doList($command, $options, $params)
    {
        $reg = &$this->config->getRegistry();
        $registered = $reg->getChannels();
        usort($registered, array(&$this, '_sortchannels'));
        $i = $j = 0;
        $data = array(
            'caption' => 'Registered Channels:',
            'border' => true,
            'headline' => array('Channel', 'Alias', 'Summary')
            );
        foreach ($registered as $channel) {
            $data['data'][] = array($channel->getName(),
                                    $channel->getAlias(),
                                    $channel->getSummary());
        }

        if (count($registered) === 0) {
            $data = '(no registered channels)';
        }
        $this->ui->outputData($data, $command);
        return true;
    }

    function doUpdateAll($command, $options, $params)
    {
        $reg = &$this->config->getRegistry();
        $channels = $reg->getChannels();

        $success = true;
        foreach ($channels as $channel) {
            if ($channel->getName() != '__uri') {
                PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                $err = $this->doUpdate('channel-update',
                                          $options,
                                          array($channel->getName()));
                if (PEAR::isError($err)) {
                    $this->ui->outputData($err->getMessage(), $command);
                    $success = false;
                } else {
                    $success &= $err;
                }
            }
        }
        return $success;
    }

    function doInfo($command, $options, $params)
    {
        if (count($params) !== 1) {
            return $this->raiseError("No channel specified");
        }

        $reg     = &$this->config->getRegistry();
        $channel = strtolower($params[0]);
        if ($reg->channelExists($channel)) {
            $chan = $reg->getChannel($channel);
            if (PEAR::isError($chan)) {
                return $this->raiseError($chan);
            }
        } else {
            if (strpos($channel, '://')) {
                $downloader = &$this->getDownloader();
                $tmpdir = $this->config->get('temp_dir');
                PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                $loc = $downloader->downloadHttp($channel, $this->ui, $tmpdir);
                PEAR::staticPopErrorHandling();
                if (PEAR::isError($loc)) {
                    return $this->raiseError('Cannot open "' . $channel .
                        '" (' . $loc->getMessage() . ')');
                } else {
                    $contents = implode('', file($loc));
                }
            } else {
                if (!file_exists($params[0])) {
                    return $this->raiseError('Unknown channel "' . $channel . '"');
                }

                $fp = fopen($params[0], 'r');
                if (!$fp) {
                    return $this->raiseError('Cannot open "' . $params[0] . '"');
                }

                $contents = '';
                while (!feof($fp)) {
                    $contents .= fread($fp, 1024);
                }
                fclose($fp);
            }

            if (!class_exists('PEAR_ChannelFile')) {
                require_once 'PEAR/ChannelFile.php';
            }

            $chan = new PEAR_ChannelFile;
            $chan->fromXmlString($contents);
            $chan->validate();
            if ($errs = $chan->getErrors(true)) {
                foreach ($errs as $err) {
                    $this->ui->outputData($err['level'] . ': ' . $err['message']);
                }
                return $this->raiseError('Channel file "' . $params[0] . '" is not valid');
            }
        }

        if (!$chan) {
            return $this->raiseError('Serious error: Channel "' . $params[0] .
                '" has a corrupted registry entry');
        }

        $channel = $chan->getName();
        $caption = 'Channel ' . $channel . ' Information:';
        $data1 = array(
            'caption' => $caption,
            'border' => true);
        $data1['data']['server'] = array('Name and Server', $chan->getName());
        if ($chan->getAlias() != $chan->getName()) {
            $data1['data']['alias'] = array('Alias', $chan->getAlias());
        }

        $data1['data']['summary'] = array('Summary', $chan->getSummary());
        $validate = $chan->getValidationPackage();
        $data1['data']['vpackage'] = array('Validation Package Name', $validate['_content']);
        $data1['data']['vpackageversion'] =
            array('Validation Package Version', $validate['attribs']['version']);
        $d = array();
        $d['main'] = $data1;

        $data['data'] = array();
        $data['caption'] = 'Server Capabilities';
        $data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base');
        if ($chan->supportsREST()) {
            if ($chan->supportsREST()) {
                $funcs = $chan->getFunctions('rest');
                if (!isset($funcs[0])) {
                    $funcs = array($funcs);
                }
                foreach ($funcs as $protocol) {
                    $data['data'][] = array('rest', $protocol['attribs']['type'],
                        $protocol['_content']);
                }
            }
        } else {
            $data['data'][] = array('No supported protocols');
        }

        $d['protocols'] = $data;
        $data['data'] = array();
        $mirrors = $chan->getMirrors();
        if ($mirrors) {
            $data['caption'] = 'Channel ' . $channel . ' Mirrors:';
            unset($data['headline']);
            foreach ($mirrors as $mirror) {
                $data['data'][] = array($mirror['attribs']['host']);
                $d['mirrors'] = $data;
            }

            foreach ($mirrors as $i => $mirror) {
                $data['data'] = array();
                $data['caption'] = 'Mirror ' . $mirror['attribs']['host'] . ' Capabilities';
                $data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base');
                if ($chan->supportsREST($mirror['attribs']['host'])) {
                    if ($chan->supportsREST($mirror['attribs']['host'])) {
                        $funcs = $chan->getFunctions('rest', $mirror['attribs']['host']);
                        if (!isset($funcs[0])) {
                            $funcs = array($funcs);
                        }

                        foreach ($funcs as $protocol) {
                            $data['data'][] = array('rest', $protocol['attribs']['type'],
                                $protocol['_content']);
                        }
                    }
                } else {
                    $data['data'][] = array('No supported protocols');
                }
                $d['mirrorprotocols' . $i] = $data;
            }
        }
        $this->ui->outputData($d, 'channel-info');
    }

    // }}}

    function doDelete($command, $options, $params)
    {
        if (count($params) !== 1) {
            return $this->raiseError('channel-delete: no channel specified');
        }

        $reg = &$this->config->getRegistry();
        if (!$reg->channelExists($params[0])) {
            return $this->raiseError('channel-delete: channel "' . $params[0] . '" does not exist');
        }

        $channel = $reg->channelName($params[0]);
        if ($channel == 'pear.php.net') {
            return $this->raiseError('Cannot delete the pear.php.net channel');
        }

        if ($channel == 'pecl.php.net') {
            return $this->raiseError('Cannot delete the pecl.php.net channel');
        }

        if ($channel == 'doc.php.net') {
            return $this->raiseError('Cannot delete the doc.php.net channel');
        }

        if ($channel == '__uri') {
            return $this->raiseError('Cannot delete the __uri pseudo-channel');
        }

        if (PEAR::isError($err = $reg->listPackages($channel))) {
            return $err;
        }

        if (count($err)) {
            return $this->raiseError('Channel "' . $channel .
                '" has installed packages, cannot delete');
        }

        if (!$reg->deleteChannel($channel)) {
            return $this->raiseError('Channel "' . $channel . '" deletion failed');
        } else {
            $this->config->deleteChannel($channel);
            $this->ui->outputData('Channel "' . $channel . '" deleted', $command);
        }
    }

    function doAdd($command, $options, $params)
    {
        if (count($params) !== 1) {
            return $this->raiseError('channel-add: no channel file specified');
        }

        if (strpos($params[0], '://')) {
            $downloader = &$this->getDownloader();
            $tmpdir = $this->config->get('temp_dir');
            if (!file_exists($tmpdir)) {
                require_once 'System.php';
                PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                $err = System::mkdir(array('-p', $tmpdir));
                PEAR::staticPopErrorHandling();
                if (PEAR::isError($err)) {
                    return $this->raiseError('channel-add: temp_dir does not exist: "' .
                        $tmpdir .
                        '" - You can change this location with "pear config-set temp_dir"');
                }
            }

            if (!is_writable($tmpdir)) {
                return $this->raiseError('channel-add: temp_dir is not writable: "' .
                    $tmpdir .
                    '" - You can change this location with "pear config-set temp_dir"');
            }

            PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
            $loc = $downloader->downloadHttp($params[0], $this->ui, $tmpdir, null, false);
            PEAR::staticPopErrorHandling();
            if (PEAR::isError($loc)) {
                return $this->raiseError('channel-add: Cannot open "' . $params[0] .
                    '" (' . $loc->getMessage() . ')');
            }

            list($loc, $lastmodified) = $loc;
            $contents = implode('', file($loc));
        } else {
            $lastmodified = $fp = false;
            if (file_exists($params[0])) {
                $fp = fopen($params[0], 'r');
            }

            if (!$fp) {
                return $this->raiseError('channel-add: cannot open "' . $params[0] . '"');
            }

            $contents = '';
            while (!feof($fp)) {
                $contents .= fread($fp, 1024);
            }
            fclose($fp);
        }

        if (!class_exists('PEAR_ChannelFile')) {
            require_once 'PEAR/ChannelFile.php';
        }

        $channel = new PEAR_ChannelFile;
        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        $result = $channel->fromXmlString($contents);
        PEAR::staticPopErrorHandling();
        if (!$result) {
            $exit = false;
            if (count($errors = $channel->getErrors(true))) {
                foreach ($errors as $error) {
                    $this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message']));
                    if (!$exit) {
                        $exit = $error['level'] == 'error' ? true : false;
                    }
                }
                if ($exit) {
                    return $this->raiseError('channel-add: invalid channel.xml file');
                }
            }
        }

        $reg = &$this->config->getRegistry();
        if ($reg->channelExists($channel->getName())) {
            return $this->raiseError('channel-add: Channel "' . $channel->getName() .
                '" exists, use channel-update to update entry', PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS);
        }

        $ret = $reg->addChannel($channel, $lastmodified);
        if (PEAR::isError($ret)) {
            return $ret;
        }

        if (!$ret) {
            return $this->raiseError('channel-add: adding Channel "' . $channel->getName() .
                '" to registry failed');
        }

        $this->config->setChannels($reg->listChannels());
        $this->config->writeConfigFile();
        $this->ui->outputData('Adding Channel "' . $channel->getName() . '" succeeded', $command);
    }

    function doUpdate($command, $options, $params)
    {
        if (count($params) !== 1) {
            return $this->raiseError("No channel file specified");
        }

        $tmpdir = $this->config->get('temp_dir');
        if (!file_exists($tmpdir)) {
            require_once 'System.php';
            PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
            $err = System::mkdir(array('-p', $tmpdir));
            PEAR::staticPopErrorHandling();
            if (PEAR::isError($err)) {
                return $this->raiseError('channel-add: temp_dir does not exist: "' .
                    $tmpdir .
                    '" - You can change this location with "pear config-set temp_dir"');
            }
        }

        if (!is_writable($tmpdir)) {
            return $this->raiseError('channel-add: temp_dir is not writable: "' .
                $tmpdir .
                '" - You can change this location with "pear config-set temp_dir"');
        }

        $reg = &$this->config->getRegistry();
        $lastmodified = false;
        if ((!file_exists($params[0]) || is_dir($params[0]))
              && $reg->channelExists(strtolower($params[0]))) {
            $c = $reg->getChannel(strtolower($params[0]));
            if (PEAR::isError($c)) {
                return $this->raiseError($c);
            }

            $this->ui->outputData("Updating channel \"$params[0]\"", $command);
            $dl = &$this->getDownloader(array());
            // if force is specified, use a timestamp of "1" to force retrieval
            $lastmodified = isset($options['force']) ? false : $c->lastModified();
            PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
            $contents = $dl->downloadHttp('http://' . $c->getName() . '/channel.xml',
                $this->ui, $tmpdir, null, $lastmodified);
            PEAR::staticPopErrorHandling();
            if (PEAR::isError($contents)) {
                // Attempt to fall back to https
                $this->ui->outputData("Channel \"$params[0]\" is not responding over http://, failed with message: " . $contents->getMessage());
                $this->ui->outputData("Trying channel \"$params[0]\" over https:// instead");
                PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                $contents = $dl->downloadHttp('https://' . $c->getName() . '/channel.xml',
                    $this->ui, $tmpdir, null, $lastmodified);
                PEAR::staticPopErrorHandling();
                if (PEAR::isError($contents)) {
                    return $this->raiseError('Cannot retrieve channel.xml for channel "' .
                        $c->getName() . '" (' . $contents->getMessage() . ')');
                }
            }

            list($contents, $lastmodified) = $contents;
            if (!$contents) {
                $this->ui->outputData("Channel \"$params[0]\" is up to date");
                return;
            }

            $contents = implode('', file($contents));
            if (!class_exists('PEAR_ChannelFile')) {
                require_once 'PEAR/ChannelFile.php';
            }

            $channel = new PEAR_ChannelFile;
            $channel->fromXmlString($contents);
            if (!$channel->getErrors()) {
                // security check: is the downloaded file for the channel we got it from?
                if (strtolower($channel->getName()) != strtolower($c->getName())) {
                    if (!isset($options['force'])) {
                        return $this->raiseError('ERROR: downloaded channel definition file' .
                            ' for channel "' . $channel->getName() . '" from channel "' .
                            strtolower($c->getName()) . '"');
                    }

                    $this->ui->log(0, 'WARNING: downloaded channel definition file' .
                        ' for channel "' . $channel->getName() . '" from channel "' .
                        strtolower($c->getName()) . '"');
                }
            }
        } else {
            if (strpos($params[0], '://')) {
                $dl = &$this->getDownloader();
                PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                $loc = $dl->downloadHttp($params[0],
                    $this->ui, $tmpdir, null, $lastmodified);
                PEAR::staticPopErrorHandling();
                if (PEAR::isError($loc)) {
                    return $this->raiseError("Cannot open " . $params[0] .
                         ' (' . $loc->getMessage() . ')');
                }

                list($loc, $lastmodified) = $loc;
                $contents = implode('', file($loc));
            } else {
                $fp = false;
                if (file_exists($params[0])) {
                    $fp = fopen($params[0], 'r');
                }

                if (!$fp) {
                    return $this->raiseError("Cannot open " . $params[0]);
                }

                $contents = '';
                while (!feof($fp)) {
                    $contents .= fread($fp, 1024);
                }
                fclose($fp);
            }

            if (!class_exists('PEAR_ChannelFile')) {
                require_once 'PEAR/ChannelFile.php';
            }

            $channel = new PEAR_ChannelFile;
            $channel->fromXmlString($contents);
        }

        $exit = false;
        if (count($errors = $channel->getErrors(true))) {
            foreach ($errors as $error) {
                $this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message']));
                if (!$exit) {
                    $exit = $error['level'] == 'error' ? true : false;
                }
            }
            if ($exit) {
                return $this->raiseError('Invalid channel.xml file');
            }
        }

        if (!$reg->channelExists($channel->getName())) {
            return $this->raiseError('Error: Channel "' . $channel->getName() .
                '" does not exist, use channel-add to add an entry');
        }

        $ret = $reg->updateChannel($channel, $lastmodified);
        if (PEAR::isError($ret)) {
            return $ret;
        }

        if (!$ret) {
            return $this->raiseError('Updating Channel "' . $channel->getName() .
                '" in registry failed');
        }

        $this->config->setChannels($reg->listChannels());
        $this->config->writeConfigFile();
        $this->ui->outputData('Update of Channel "' . $channel->getName() . '" succeeded');
    }

    function &getDownloader()
    {
        if (!class_exists('PEAR_Downloader')) {
            require_once 'PEAR/Downloader.php';
        }
        $a = new PEAR_Downloader($this->ui, array(), $this->config);
        return $a;
    }

    function doAlias($command, $options, $params)
    {
        if (count($params) === 1) {
            return $this->raiseError('No channel alias specified');
        }

        if (count($params) !== 2 || (!empty($params[1]) && $params[1][0] == '-')) {
            return $this->raiseError(
                'Invalid format, correct is: channel-alias channel alias');
        }

        $reg = &$this->config->getRegistry();
        if (!$reg->channelExists($params[0], true)) {
            $extra = '';
            if ($reg->isAlias($params[0])) {
                $extra = ' (use "channel-alias ' . $reg->channelName($params[0]) . ' ' .
                    strtolower($params[1]) . '")';
            }

            return $this->raiseError('"' . $params[0] . '" is not a valid channel' . $extra);
        }

        if ($reg->isAlias($params[1])) {
            return $this->raiseError('Channel "' . $reg->channelName($params[1]) . '" is ' .
                'already aliased to "' . strtolower($params[1]) . '", cannot re-alias');
        }

        $chan = $reg->getChannel($params[0]);
        if (PEAR::isError($chan)) {
            return $this->raiseError('Corrupt registry?  Error retrieving channel "' . $params[0] .
                '" information (' . $chan->getMessage() . ')');
        }

        // make it a local alias
        if (!$chan->setAlias(strtolower($params[1]), true)) {
            return $this->raiseError('Alias "' . strtolower($params[1]) .
                '" is not a valid channel alias');
        }

        $reg->updateChannel($chan);
        $this->ui->outputData('Channel "' . $chan->getName() . '" aliased successfully to "' .
            strtolower($params[1]) . '"');
    }

    /**
     * The channel-discover command
     *
     * @param string $command command name
     * @param array  $options option_name => value
     * @param array  $params  list of additional parameters.
     *               $params[0] should contain a string with either:
     *               - <channel name> or
     *               - <username>:<password>@<channel name>
     * @return null|PEAR_Error
     */
    function doDiscover($command, $options, $params)
    {
        if (count($params) !== 1) {
            return $this->raiseError("No channel server specified");
        }

        // Look for the possible input format "<username>:<password>@<channel>"
        if (preg_match('/^(.+):(.+)@(.+)\\z/', $params[0], $matches)) {
            $username = $matches[1];
            $password = $matches[2];
            $channel  = $matches[3];
        } else {
            $channel = $params[0];
        }

        $reg = &$this->config->getRegistry();
        if ($reg->channelExists($channel)) {
            if (!$reg->isAlias($channel)) {
                return $this->raiseError("Channel \"$channel\" is already initialized", PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS);
            }

            return $this->raiseError("A channel alias named \"$channel\" " .
                'already exists, aliasing channel "' . $reg->channelName($channel)
                . '"');
        }

        $this->pushErrorHandling(PEAR_ERROR_RETURN);
        $err = $this->doAdd($command, $options, array('http://' . $channel . '/channel.xml'));
        $this->popErrorHandling();
        if (PEAR::isError($err)) {
            if ($err->getCode() === PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS) {
                return $this->raiseError("Discovery of channel \"$channel\" failed (" .
                    $err->getMessage() . ')');
            }
            // Attempt fetch via https
            $this->ui->outputData("Discovering channel $channel over http:// failed with message: " . $err->getMessage());
            $this->ui->outputData("Trying to discover channel $channel over https:// instead");
            $this->pushErrorHandling(PEAR_ERROR_RETURN);
            $err = $this->doAdd($command, $options, array('https://' . $channel . '/channel.xml'));
            $this->popErrorHandling();
            if (PEAR::isError($err)) {
                return $this->raiseError("Discovery of channel \"$channel\" failed (" .
                    $err->getMessage() . ')');
            }
        }

        // Store username/password if they were given
        // Arguably we should do a logintest on the channel here, but since
        // that's awkward on a REST-based channel (even "pear login" doesn't
        // do it for those), and XML-RPC is deprecated, it's fairly pointless.
        if (isset($username)) {
            $this->config->set('username', $username, 'user', $channel);
            $this->config->set('password', $password, 'user', $channel);
            $this->config->store();
            $this->ui->outputData("Stored login for channel \"$channel\" using username \"$username\"", $command);
        }

        $this->ui->outputData("Discovery of channel \"$channel\" succeeded", $command);
    }

    /**
     * Execute the 'login' command.
     *
     * @param string $command command name
     * @param array $options option_name => value
     * @param array $params list of additional parameters
     *
     * @return bool TRUE on success or
     * a PEAR error on failure
     *
     * @access public
     */
    function doLogin($command, $options, $params)
    {
        $reg = &$this->config->getRegistry();

        // If a parameter is supplied, use that as the channel to log in to
        $channel = isset($params[0]) ? $params[0] : $this->config->get('default_channel');

        $chan = $reg->getChannel($channel);
        if (PEAR::isError($chan)) {
            return $this->raiseError($chan);
        }

        $server   = $this->config->get('preferred_mirror', null, $channel);
        $username = $this->config->get('username',         null, $channel);
        if (empty($username)) {
            $username = isset($_ENV['USER']) ? $_ENV['USER'] : null;
        }
        $this->ui->outputData("Logging in to $server.", $command);

        list($username, $password) = $this->ui->userDialog(
            $command,
            array('Username', 'Password'),
            array('text',     'password'),
            array($username,  '')
            );
        $username = trim($username);
        $password = trim($password);

        $ourfile = $this->config->getConfFile('user');
        if (!$ourfile) {
            $ourfile = $this->config->getConfFile('system');
        }

        $this->config->set('username', $username, 'user', $channel);
        $this->config->set('password', $password, 'user', $channel);

        if ($chan->supportsREST()) {
            $ok = true;
        }

        if ($ok !== true) {
            return $this->raiseError('Login failed!');
        }

        $this->ui->outputData("Logged in.", $command);
        // avoid changing any temporary settings changed with -d
        $ourconfig = new PEAR_Config($ourfile, $ourfile);
        $ourconfig->set('username', $username, 'user', $channel);
        $ourconfig->set('password', $password, 'user', $channel);
        $ourconfig->store();

        return true;
    }

    /**
     * Execute the 'logout' command.
     *
     * @param string $command command name
     * @param array $options option_name => value
     * @param array $params list of additional parameters
     *
     * @return bool TRUE on success or
     * a PEAR error on failure
     *
     * @access public
     */
    function doLogout($command, $options, $params)
    {
        $reg     = &$this->config->getRegistry();

        // If a parameter is supplied, use that as the channel to log in to
        $channel = isset($params[0]) ? $params[0] : $this->config->get('default_channel');

        $chan    = $reg->getChannel($channel);
        if (PEAR::isError($chan)) {
            return $this->raiseError($chan);
        }

        $server = $this->config->get('preferred_mirror', null, $channel);
        $this->ui->outputData("Logging out from $server.", $command);
        $this->config->remove('username', 'user', $channel);
        $this->config->remove('password', 'user', $channel);
        $this->config->store();
        return true;
    }
}
PKo�Znmi?;�;�PEAR/Command/Install.phpnu�[���<?php
/**
 * PEAR_Command_Install (install, upgrade, upgrade-all, uninstall, bundle, run-scripts commands)
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 0.1
 */

/**
 * base class
 */
require_once 'PEAR/Command/Common.php';

/**
 * PEAR commands for installation or deinstallation/upgrading of
 * packages.
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 0.1
 */
class PEAR_Command_Install extends PEAR_Command_Common
{
    // {{{ properties

    var $commands = array(
        'install' => array(
            'summary' => 'Install Package',
            'function' => 'doInstall',
            'shortcut' => 'i',
            'options' => array(
                'force' => array(
                    'shortopt' => 'f',
                    'doc' => 'will overwrite newer installed packages',
                    ),
                'loose' => array(
                    'shortopt' => 'l',
                    'doc' => 'do not check for recommended dependency version',
                    ),
                'nodeps' => array(
                    'shortopt' => 'n',
                    'doc' => 'ignore dependencies, install anyway',
                    ),
                'register-only' => array(
                    'shortopt' => 'r',
                    'doc' => 'do not install files, only register the package as installed',
                    ),
                'soft' => array(
                    'shortopt' => 's',
                    'doc' => 'soft install, fail silently, or upgrade if already installed',
                    ),
                'nobuild' => array(
                    'shortopt' => 'B',
                    'doc' => 'don\'t build C extensions',
                    ),
                'configureoptions' => array(
                    'shortopt' => 'D',
                    'arg' => 'OPTION1=VALUE[ OPTION2=VALUE]',
                    'doc' => 'space-delimited list of configure options',
                    ),
                'nocompress' => array(
                    'shortopt' => 'Z',
                    'doc' => 'request uncompressed files when downloading',
                    ),
                'installroot' => array(
                    'shortopt' => 'R',
                    'arg' => 'DIR',
                    'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT), use packagingroot for RPM',
                    ),
                'packagingroot' => array(
                    'shortopt' => 'P',
                    'arg' => 'DIR',
                    'doc' => 'root directory used when packaging files, like RPM packaging',
                    ),
                'ignore-errors' => array(
                    'doc' => 'force install even if there were errors',
                    ),
                'alldeps' => array(
                    'shortopt' => 'a',
                    'doc' => 'install all required and optional dependencies',
                    ),
                'onlyreqdeps' => array(
                    'shortopt' => 'o',
                    'doc' => 'install all required dependencies',
                    ),
                'offline' => array(
                    'shortopt' => 'O',
                    'doc' => 'do not attempt to download any urls or contact channels',
                    ),
                'pretend' => array(
                    'shortopt' => 'p',
                    'doc' => 'Only list the packages that would be downloaded',
                    ),
                ),
            'doc' => '[channel/]<package> ...
Installs one or more PEAR packages.  You can specify a package to
install in four ways:

"Package-1.0.tgz" : installs from a local file

"http://example.com/Package-1.0.tgz" : installs from
anywhere on the net.

"package.xml" : installs the package described in
package.xml.  Useful for testing, or for wrapping a PEAR package in
another package manager such as RPM.

"Package[-version/state][.tar]" : queries your default channel\'s server
({config master_server}) and downloads the newest package with
the preferred quality/state ({config preferred_state}).

To retrieve Package version 1.1, use "Package-1.1," to retrieve
Package state beta, use "Package-beta."  To retrieve an uncompressed
file, append .tar (make sure there is no file by the same name first)

To download a package from another channel, prefix with the channel name like
"channel/Package"

More than one package may be specified at once.  It is ok to mix these
four ways of specifying packages.
'),
        'upgrade' => array(
            'summary' => 'Upgrade Package',
            'function' => 'doInstall',
            'shortcut' => 'up',
            'options' => array(
                'channel' => array(
                    'shortopt' => 'c',
                    'doc' => 'upgrade packages from a specific channel',
                    'arg' => 'CHAN',
                    ),
                'force' => array(
                    'shortopt' => 'f',
                    'doc' => 'overwrite newer installed packages',
                    ),
                'loose' => array(
                    'shortopt' => 'l',
                    'doc' => 'do not check for recommended dependency version',
                    ),
                'nodeps' => array(
                    'shortopt' => 'n',
                    'doc' => 'ignore dependencies, upgrade anyway',
                    ),
                'register-only' => array(
                    'shortopt' => 'r',
                    'doc' => 'do not install files, only register the package as upgraded',
                    ),
                'nobuild' => array(
                    'shortopt' => 'B',
                    'doc' => 'don\'t build C extensions',
                    ),
                'nocompress' => array(
                    'shortopt' => 'Z',
                    'doc' => 'request uncompressed files when downloading',
                    ),
                'installroot' => array(
                    'shortopt' => 'R',
                    'arg' => 'DIR',
                    'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)',
                    ),
                'ignore-errors' => array(
                    'doc' => 'force install even if there were errors',
                    ),
                'alldeps' => array(
                    'shortopt' => 'a',
                    'doc' => 'install all required and optional dependencies',
                    ),
                'onlyreqdeps' => array(
                    'shortopt' => 'o',
                    'doc' => 'install all required dependencies',
                    ),
                'offline' => array(
                    'shortopt' => 'O',
                    'doc' => 'do not attempt to download any urls or contact channels',
                    ),
                'pretend' => array(
                    'shortopt' => 'p',
                    'doc' => 'Only list the packages that would be downloaded',
                    ),
                ),
            'doc' => '<package> ...
Upgrades one or more PEAR packages.  See documentation for the
"install" command for ways to specify a package.

When upgrading, your package will be updated if the provided new
package has a higher version number (use the -f option if you need to
upgrade anyway).

More than one package may be specified at once.
'),
        'upgrade-all' => array(
            'summary' => 'Upgrade All Packages [Deprecated in favor of calling upgrade with no parameters]',
            'function' => 'doUpgradeAll',
            'shortcut' => 'ua',
            'options' => array(
                'channel' => array(
                    'shortopt' => 'c',
                    'doc' => 'upgrade packages from a specific channel',
                    'arg' => 'CHAN',
                    ),
                'nodeps' => array(
                    'shortopt' => 'n',
                    'doc' => 'ignore dependencies, upgrade anyway',
                    ),
                'register-only' => array(
                    'shortopt' => 'r',
                    'doc' => 'do not install files, only register the package as upgraded',
                    ),
                'nobuild' => array(
                    'shortopt' => 'B',
                    'doc' => 'don\'t build C extensions',
                    ),
                'nocompress' => array(
                    'shortopt' => 'Z',
                    'doc' => 'request uncompressed files when downloading',
                    ),
                'installroot' => array(
                    'shortopt' => 'R',
                    'arg' => 'DIR',
                    'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT), use packagingroot for RPM',
                    ),
                'ignore-errors' => array(
                    'doc' => 'force install even if there were errors',
                    ),
                'loose' => array(
                    'doc' => 'do not check for recommended dependency version',
                    ),
                ),
            'doc' => '
WARNING: This function is deprecated in favor of using the upgrade command with no params

Upgrades all packages that have a newer release available.  Upgrades are
done only if there is a release available of the state specified in
"preferred_state" (currently {config preferred_state}), or a state considered
more stable.
'),
        'uninstall' => array(
            'summary' => 'Un-install Package',
            'function' => 'doUninstall',
            'shortcut' => 'un',
            'options' => array(
                'nodeps' => array(
                    'shortopt' => 'n',
                    'doc' => 'ignore dependencies, uninstall anyway',
                    ),
                'register-only' => array(
                    'shortopt' => 'r',
                    'doc' => 'do not remove files, only register the packages as not installed',
                    ),
                'installroot' => array(
                    'shortopt' => 'R',
                    'arg' => 'DIR',
                    'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)',
                    ),
                'ignore-errors' => array(
                    'doc' => 'force install even if there were errors',
                    ),
                'offline' => array(
                    'shortopt' => 'O',
                    'doc' => 'do not attempt to uninstall remotely',
                    ),
                ),
            'doc' => '[channel/]<package> ...
Uninstalls one or more PEAR packages.  More than one package may be
specified at once.  Prefix with channel name to uninstall from a
channel not in your default channel ({config default_channel})
'),
        'bundle' => array(
            'summary' => 'Unpacks a Pecl Package',
            'function' => 'doBundle',
            'shortcut' => 'bun',
            'options' => array(
                'destination' => array(
                   'shortopt' => 'd',
                    'arg' => 'DIR',
                    'doc' => 'Optional destination directory for unpacking (defaults to current path or "ext" if exists)',
                    ),
                'force' => array(
                    'shortopt' => 'f',
                    'doc' => 'Force the unpacking even if there were errors in the package',
                ),
            ),
            'doc' => '<package>
Unpacks a Pecl Package into the selected location. It will download the
package if needed.
'),
        'run-scripts' => array(
            'summary' => 'Run Post-Install Scripts bundled with a package',
            'function' => 'doRunScripts',
            'shortcut' => 'rs',
            'options' => array(
            ),
            'doc' => '<package>
Run post-installation scripts in package <package>, if any exist.
'),
    );

    // }}}
    // {{{ constructor

    /**
     * PEAR_Command_Install constructor.
     *
     * @access public
     */
    function __construct(&$ui, &$config)
    {
        parent::__construct($ui, $config);
    }

    // }}}

    /**
     * For unit testing purposes
     */
    function &getDownloader(&$ui, $options, &$config)
    {
        if (!class_exists('PEAR_Downloader')) {
            require_once 'PEAR/Downloader.php';
        }
        $a = new PEAR_Downloader($ui, $options, $config);
        return $a;
    }

    /**
     * For unit testing purposes
     */
    function &getInstaller(&$ui)
    {
        if (!class_exists('PEAR_Installer')) {
            require_once 'PEAR/Installer.php';
        }
        $a = new PEAR_Installer($ui);
        return $a;
    }

    function enableExtension($binaries, $type)
    {
        if (!($phpini = $this->config->get('php_ini', null, 'pear.php.net'))) {
            return PEAR::raiseError('configuration option "php_ini" is not set to php.ini location');
        }
        $ini = $this->_parseIni($phpini);
        if (PEAR::isError($ini)) {
            return $ini;
        }
        $line = 0;
        if ($type == 'extsrc' || $type == 'extbin') {
            $search = 'extensions';
            $enable = 'extension';
        } else {
            $search = 'zend_extensions';
            ob_start();
            phpinfo(INFO_GENERAL);
            $info = ob_get_contents();
            ob_end_clean();
            $debug = function_exists('leak') ? '_debug' : '';
            $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
            $enable = 'zend_extension' . $debug . $ts;
        }
        foreach ($ini[$search] as $line => $extension) {
            if (in_array($extension, $binaries, true) || in_array(
                  $ini['extension_dir'] . DIRECTORY_SEPARATOR . $extension, $binaries, true)) {
                // already enabled - assume if one is, all are
                return true;
            }
        }
        if ($line) {
            $newini = array_slice($ini['all'], 0, $line);
        } else {
            $newini = array();
        }
        foreach ($binaries as $binary) {
            if ($ini['extension_dir']) {
                $binary = basename($binary);
            }
            $newini[] = $enable . '="' . $binary . '"' . (OS_UNIX ? "\n" : "\r\n");
        }
        $newini = array_merge($newini, array_slice($ini['all'], $line));
        $fp = @fopen($phpini, 'wb');
        if (!$fp) {
            return PEAR::raiseError('cannot open php.ini "' . $phpini . '" for writing');
        }
        foreach ($newini as $line) {
            fwrite($fp, $line);
        }
        fclose($fp);
        return true;
    }

    function disableExtension($binaries, $type)
    {
        if (!($phpini = $this->config->get('php_ini', null, 'pear.php.net'))) {
            return PEAR::raiseError('configuration option "php_ini" is not set to php.ini location');
        }
        $ini = $this->_parseIni($phpini);
        if (PEAR::isError($ini)) {
            return $ini;
        }
        $line = 0;
        if ($type == 'extsrc' || $type == 'extbin') {
            $search = 'extensions';
            $enable = 'extension';
        } else {
            $search = 'zend_extensions';
            ob_start();
            phpinfo(INFO_GENERAL);
            $info = ob_get_contents();
            ob_end_clean();
            $debug = function_exists('leak') ? '_debug' : '';
            $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
            $enable = 'zend_extension' . $debug . $ts;
        }
        $found = false;
        foreach ($ini[$search] as $line => $extension) {
            if (in_array($extension, $binaries, true) || in_array(
                  $ini['extension_dir'] . DIRECTORY_SEPARATOR . $extension, $binaries, true)) {
                $found = true;
                break;
            }
        }
        if (!$found) {
            // not enabled
            return true;
        }
        $fp = @fopen($phpini, 'wb');
        if (!$fp) {
            return PEAR::raiseError('cannot open php.ini "' . $phpini . '" for writing');
        }
        if ($line) {
            $newini = array_slice($ini['all'], 0, $line);
            // delete the enable line
            $newini = array_merge($newini, array_slice($ini['all'], $line + 1));
        } else {
            $newini = array_slice($ini['all'], 1);
        }
        foreach ($newini as $line) {
            fwrite($fp, $line);
        }
        fclose($fp);
        return true;
    }

    function _parseIni($filename)
    {
        if (!file_exists($filename)) {
            return PEAR::raiseError('php.ini "' . $filename . '" does not exist');
        }

        if (filesize($filename) > 300000) {
            return PEAR::raiseError('php.ini "' . $filename . '" is too large, aborting');
        }

        ob_start();
        phpinfo(INFO_GENERAL);
        $info = ob_get_contents();
        ob_end_clean();
        $debug = function_exists('leak') ? '_debug' : '';
        $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
        $zend_extension_line = 'zend_extension' . $debug . $ts;
        $all = @file($filename);
        if ($all === false) {
            return PEAR::raiseError('php.ini "' . $filename .'" could not be read');
        }
        $zend_extensions = $extensions = array();
        // assume this is right, but pull from the php.ini if it is found
        $extension_dir = ini_get('extension_dir');
        foreach ($all as $linenum => $line) {
            $line = trim($line);
            if (!$line) {
                continue;
            }
            if ($line[0] == ';') {
                continue;
            }
            if (strtolower(substr($line, 0, 13)) == 'extension_dir') {
                $line = trim(substr($line, 13));
                if ($line[0] == '=') {
                    $x = trim(substr($line, 1));
                    $x = explode(';', $x);
                    $extension_dir = str_replace('"', '', array_shift($x));
                    continue;
                }
            }
            if (strtolower(substr($line, 0, 9)) == 'extension') {
                $line = trim(substr($line, 9));
                if ($line[0] == '=') {
                    $x = trim(substr($line, 1));
                    $x = explode(';', $x);
                    $extensions[$linenum] = str_replace('"', '', array_shift($x));
                    continue;
                }
            }
            if (strtolower(substr($line, 0, strlen($zend_extension_line))) ==
                  $zend_extension_line) {
                $line = trim(substr($line, strlen($zend_extension_line)));
                if ($line[0] == '=') {
                    $x = trim(substr($line, 1));
                    $x = explode(';', $x);
                    $zend_extensions[$linenum] = str_replace('"', '', array_shift($x));
                    continue;
                }
            }
        }
        return array(
            'extensions' => $extensions,
            'zend_extensions' => $zend_extensions,
            'extension_dir' => $extension_dir,
            'all' => $all,
        );
    }

    // {{{ doInstall()

    function doInstall($command, $options, $params)
    {
        if (!class_exists('PEAR_PackageFile')) {
            require_once 'PEAR/PackageFile.php';
        }

        if (isset($options['installroot']) && isset($options['packagingroot'])) {
            return $this->raiseError('ERROR: cannot use both --installroot and --packagingroot');
        }

        $reg = &$this->config->getRegistry();
        $channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel');
        if (!$reg->channelExists($channel)) {
            return $this->raiseError('Channel "' . $channel . '" does not exist');
        }

        if (empty($this->installer)) {
            $this->installer = &$this->getInstaller($this->ui);
        }

        if ($command == 'upgrade' || $command == 'upgrade-all') {
            // If people run the upgrade command but pass nothing, emulate a upgrade-all
            if ($command == 'upgrade' && empty($params)) {
                return $this->doUpgradeAll($command, $options, $params);
            }
            $options['upgrade'] = true;
        } else {
            $packages = $params;
        }

        $instreg = &$reg; // instreg used to check if package is installed
        if (isset($options['packagingroot']) && !isset($options['upgrade'])) {
            $packrootphp_dir = $this->installer->_prependPath(
                $this->config->get('php_dir', null, 'pear.php.net'),
                $options['packagingroot']);
            $metadata_dir = $this->config->get('metadata_dir', null, 'pear.php.net');
            if ($metadata_dir) {
                $metadata_dir = $this->installer->_prependPath(
                    $metadata_dir,
                    $options['packagingroot']);
            }
            $instreg = new PEAR_Registry($packrootphp_dir, false, false, $metadata_dir); // other instreg!

            if ($this->config->get('verbose') > 2) {
                $this->ui->outputData('using package root: ' . $options['packagingroot']);
            }
        }

        $abstractpackages = $otherpackages = array();
        // parse params
        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);

        foreach ($params as $param) {
            if (strpos($param, 'http://') === 0) {
                $otherpackages[] = $param;
                continue;
            }

            if (strpos($param, 'channel://') === false && @file_exists($param)) {
                if (isset($options['force'])) {
                    $otherpackages[] = $param;
                    continue;
                }

                $pkg = new PEAR_PackageFile($this->config);
                $pf  = $pkg->fromAnyFile($param, PEAR_VALIDATE_DOWNLOADING);
                if (PEAR::isError($pf)) {
                    $otherpackages[] = $param;
                    continue;
                }

                $exists   = $reg->packageExists($pf->getPackage(), $pf->getChannel());
                $pversion = $reg->packageInfo($pf->getPackage(), 'version', $pf->getChannel());
                $version_compare = version_compare($pf->getVersion(), $pversion, '<=');
                if ($exists && $version_compare) {
                    if ($this->config->get('verbose')) {
                        $this->ui->outputData('Ignoring installed package ' .
                            $reg->parsedPackageNameToString(
                            array('package' => $pf->getPackage(),
                                  'channel' => $pf->getChannel()), true));
                    }
                    continue;
                }
                $otherpackages[] = $param;
                continue;
            }

            $e = $reg->parsePackageName($param, $channel);
            if (PEAR::isError($e)) {
                $otherpackages[] = $param;
            } else {
                $abstractpackages[] = $e;
            }
        }
        PEAR::staticPopErrorHandling();

        // if there are any local package .tgz or remote static url, we can't
        // filter.  The filter only works for abstract packages
        if (count($abstractpackages) && !isset($options['force'])) {
            // when not being forced, only do necessary upgrades/installs
            if (isset($options['upgrade'])) {
                $abstractpackages = $this->_filterUptodatePackages($abstractpackages, $command);
            } else {
                $count = count($abstractpackages);
                foreach ($abstractpackages as $i => $package) {
                    if (isset($package['group'])) {
                        // do not filter out install groups
                        continue;
                    }

                    if ($instreg->packageExists($package['package'], $package['channel'])) {
                        if ($count > 1) {
                            if ($this->config->get('verbose')) {
                                $this->ui->outputData('Ignoring installed package ' .
                                    $reg->parsedPackageNameToString($package, true));
                            }
                            unset($abstractpackages[$i]);
                        } elseif ($count === 1) {
                            // Lets try to upgrade it since it's already installed
                            $options['upgrade'] = true;
                        }
                    }
                }
            }
            $abstractpackages =
                array_map(array($reg, 'parsedPackageNameToString'), $abstractpackages);
        } elseif (count($abstractpackages)) {
            $abstractpackages =
                array_map(array($reg, 'parsedPackageNameToString'), $abstractpackages);
        }

        $packages = array_merge($abstractpackages, $otherpackages);
        if (!count($packages)) {
            $c = '';
            if (isset($options['channel'])){
                $c .= ' in channel "' . $options['channel'] . '"';
            }
            $this->ui->outputData('Nothing to ' . $command . $c);
            return true;
        }

        $this->downloader = &$this->getDownloader($this->ui, $options, $this->config);
        $errors = $downloaded = $binaries = array();
        $downloaded = &$this->downloader->download($packages);
        if (PEAR::isError($downloaded)) {
            return $this->raiseError($downloaded);
        }

        $errors = $this->downloader->getErrorMsgs();
        if (count($errors)) {
            $err = array();
            $err['data'] = array();
            foreach ($errors as $error) {
                if ($error !== null) {
                    $err['data'][] = array($error);
                }
            }

            if (!empty($err['data'])) {
                $err['headline'] = 'Install Errors';
                $this->ui->outputData($err);
            }

            if (!count($downloaded)) {
                return $this->raiseError("$command failed");
            }
        }

        $data = array(
            'headline' => 'Packages that would be Installed'
        );

        if (isset($options['pretend'])) {
            foreach ($downloaded as $package) {
                $data['data'][] = array($reg->parsedPackageNameToString($package->getParsedPackage()));
            }
            $this->ui->outputData($data, 'pretend');
            return true;
        }

        $this->installer->setOptions($options);
        $this->installer->sortPackagesForInstall($downloaded);
        if (PEAR::isError($err = $this->installer->setDownloadedPackages($downloaded))) {
            $this->raiseError($err->getMessage());
            return true;
        }

        $binaries = $extrainfo = array();
        foreach ($downloaded as $param) {
            PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
            $info = $this->installer->install($param, $options);
            PEAR::staticPopErrorHandling();
            if (PEAR::isError($info)) {
                $oldinfo = $info;
                $pkg = &$param->getPackageFile();
                if ($info->getCode() != PEAR_INSTALLER_NOBINARY) {
                    if (!($info = $pkg->installBinary($this->installer))) {
                        return $this->raiseError('ERROR: ' .$oldinfo->getMessage());
                    }

                    // we just installed a different package than requested,
                    // let's change the param and info so that the rest of this works
                    $param = $info[0];
                    $info  = $info[1];
                }
            }

            if (!is_array($info)) {
                return $this->raiseError("$command failed");
            }

            if ($param->getPackageType() == 'extsrc' ||
                  $param->getPackageType() == 'extbin' ||
                  $param->getPackageType() == 'zendextsrc' ||
                  $param->getPackageType() == 'zendextbin'
            ) {
                $pkg = &$param->getPackageFile();
                if ($instbin = $pkg->getInstalledBinary()) {
                    $instpkg = &$instreg->getPackage($instbin, $pkg->getChannel());
                } else {
                    $instpkg = &$instreg->getPackage($pkg->getPackage(), $pkg->getChannel());
                }

                foreach ($instpkg->getFilelist() as $name => $atts) {
                    $pinfo = pathinfo($atts['installed_as']);
                    if (!isset($pinfo['extension']) ||
                          in_array($pinfo['extension'], array('c', 'h'))
                    ) {
                        continue; // make sure we don't match php_blah.h
                    }

                    if ((strpos($pinfo['basename'], 'php_') === 0 &&
                          $pinfo['extension'] == 'dll') ||
                          // most unices
                          $pinfo['extension'] == 'so' ||
                          // hp-ux
                          $pinfo['extension'] == 'sl') {
                        $binaries[] = array($atts['installed_as'], $pinfo);
                        break;
                    }
                }

                if (count($binaries)) {
                    foreach ($binaries as $pinfo) {
                        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                        $ret = $this->enableExtension(array($pinfo[0]), $param->getPackageType());
                        PEAR::staticPopErrorHandling();
                        if (PEAR::isError($ret)) {
                            $extrainfo[] = $ret->getMessage();
                            if ($param->getPackageType() == 'extsrc' ||
                                  $param->getPackageType() == 'extbin') {
                                $exttype = 'extension';
                                $extpath = $pinfo[1]['basename'];
                            } else {
                                $exttype = 'zend_extension';
                                $extpath = $atts['installed_as'];
                            }
                            $extrainfo[] = 'You should add "' . $exttype . '=' .
                                $extpath . '" to php.ini';
                        } else {
                            $extrainfo[] = 'Extension ' . $instpkg->getProvidesExtension() .
                                ' enabled in php.ini';
                        }
                    }
                }
            }

            if ($this->config->get('verbose') > 0) {
                $chan = $param->getChannel();
                $label = $reg->parsedPackageNameToString(
                    array(
                        'channel' => $chan,
                        'package' => $param->getPackage(),
                        'version' => $param->getVersion(),
                    ));
                $out = array('data' => "$command ok: $label");
                if (isset($info['release_warnings'])) {
                    $out['release_warnings'] = $info['release_warnings'];
                }
                $this->ui->outputData($out, $command);

                if (!isset($options['register-only']) && !isset($options['offline'])) {
                    if ($this->config->isDefinedLayer('ftp')) {
                        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                        $info = $this->installer->ftpInstall($param);
                        PEAR::staticPopErrorHandling();
                        if (PEAR::isError($info)) {
                            $this->ui->outputData($info->getMessage());
                            $this->ui->outputData("remote install failed: $label");
                        } else {
                            $this->ui->outputData("remote install ok: $label");
                        }
                    }
                }
            }

            $deps = $param->getDeps();
            if ($deps) {
                if (isset($deps['group'])) {
                    $groups = $deps['group'];
                    if (!isset($groups[0])) {
                        $groups = array($groups);
                    }

                    foreach ($groups as $group) {
                        if ($group['attribs']['name'] == 'default') {
                            // default group is always installed, unless the user
                            // explicitly chooses to install another group
                            continue;
                        }
                        $extrainfo[] = $param->getPackage() . ': Optional feature ' .
                            $group['attribs']['name'] . ' available (' .
                            $group['attribs']['hint'] . ')';
                    }

                    $extrainfo[] = $param->getPackage() .
                        ': To install optional features use "pear install ' .
                        $reg->parsedPackageNameToString(
                            array('package' => $param->getPackage(),
                                  'channel' => $param->getChannel()), true) .
                              '#featurename"';
                }
            }

            $pkg = &$instreg->getPackage($param->getPackage(), $param->getChannel());
            // $pkg may be NULL if install is a 'fake' install via --packagingroot
            if (is_object($pkg)) {
                $pkg->setConfig($this->config);
                if ($list = $pkg->listPostinstallScripts()) {
                    $pn = $reg->parsedPackageNameToString(array('channel' =>
                       $param->getChannel(), 'package' => $param->getPackage()), true);
                    $extrainfo[] = $pn . ' has post-install scripts:';
                    foreach ($list as $file) {
                        $extrainfo[] = $file;
                    }
                    $extrainfo[] = $param->getPackage() .
                        ': Use "pear run-scripts ' . $pn . '" to finish setup.';
                    $extrainfo[] = 'DO NOT RUN SCRIPTS FROM UNTRUSTED SOURCES';
                }
            }
        }

        if (count($extrainfo)) {
            foreach ($extrainfo as $info) {
                $this->ui->outputData($info);
            }
        }

        return true;
    }

    // }}}
    // {{{ doUpgradeAll()

    function doUpgradeAll($command, $options, $params)
    {
        $reg = &$this->config->getRegistry();
        $upgrade = array();

        if (isset($options['channel'])) {
            $channels = array($options['channel']);
        } else {
            $channels = $reg->listChannels();
        }

        foreach ($channels as $channel) {
            if ($channel == '__uri') {
                continue;
            }

            // parse name with channel
            foreach ($reg->listPackages($channel) as $name) {
                $upgrade[] = $reg->parsedPackageNameToString(array(
                        'channel' => $channel,
                        'package' => $name
                    ));
            }
        }

        $err = $this->doInstall($command, $options, $upgrade);
        if (PEAR::isError($err)) {
            $this->ui->outputData($err->getMessage(), $command);
        }
   }

    // }}}
    // {{{ doUninstall()

    function doUninstall($command, $options, $params)
    {
        if (count($params) < 1) {
            return $this->raiseError("Please supply the package(s) you want to uninstall");
        }

        if (empty($this->installer)) {
            $this->installer = &$this->getInstaller($this->ui);
        }

        if (isset($options['remoteconfig'])) {
            $e = $this->config->readFTPConfigFile($options['remoteconfig']);
            if (!PEAR::isError($e)) {
                $this->installer->setConfig($this->config);
            }
        }

        $reg = &$this->config->getRegistry();
        $newparams = array();
        $binaries = array();
        $badparams = array();
        foreach ($params as $pkg) {
            $channel = $this->config->get('default_channel');
            PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
            $parsed = $reg->parsePackageName($pkg, $channel);
            PEAR::staticPopErrorHandling();
            if (!$parsed || PEAR::isError($parsed)) {
                $badparams[] = $pkg;
                continue;
            }
            $package = $parsed['package'];
            $channel = $parsed['channel'];
            $info = &$reg->getPackage($package, $channel);
            if ($info === null &&
                 ($channel == 'pear.php.net' || $channel == 'pecl.php.net')) {
                // make sure this isn't a package that has flipped from pear to pecl but
                // used a package.xml 1.0
                $testc = ($channel == 'pear.php.net') ? 'pecl.php.net' : 'pear.php.net';
                $info = &$reg->getPackage($package, $testc);
                if ($info !== null) {
                    $channel = $testc;
                }
            }
            if ($info === null) {
                $badparams[] = $pkg;
            } else {
                $newparams[] = &$info;
                // check for binary packages (this is an alias for those packages if so)
                if ($installedbinary = $info->getInstalledBinary()) {
                    $this->ui->log('adding binary package ' .
                        $reg->parsedPackageNameToString(array('channel' => $channel,
                            'package' => $installedbinary), true));
                    $newparams[] = &$reg->getPackage($installedbinary, $channel);
                }
                // add the contents of a dependency group to the list of installed packages
                if (isset($parsed['group'])) {
                    $group = $info->getDependencyGroup($parsed['group']);
                    if ($group) {
                        $installed = $reg->getInstalledGroup($group);
                        if ($installed) {
                            foreach ($installed as $i => $p) {
                                $newparams[] = &$installed[$i];
                            }
                        }
                    }
                }
            }
        }
        $err = $this->installer->sortPackagesForUninstall($newparams);
        if (PEAR::isError($err)) {
            $this->ui->outputData($err->getMessage(), $command);
            return true;
        }
        $params = $newparams;
        // twist this to use it to check on whether dependent packages are also being uninstalled
        // for circular dependencies like subpackages
        $this->installer->setUninstallPackages($newparams);
        $params = array_merge($params, $badparams);
        $binaries = array();
        foreach ($params as $pkg) {
            $this->installer->pushErrorHandling(PEAR_ERROR_RETURN);
            if ($err = $this->installer->uninstall($pkg, $options)) {
                $this->installer->popErrorHandling();
                if (PEAR::isError($err)) {
                    $this->ui->outputData($err->getMessage(), $command);
                    continue;
                }
                if ($pkg->getPackageType() == 'extsrc' ||
                      $pkg->getPackageType() == 'extbin' ||
                      $pkg->getPackageType() == 'zendextsrc' ||
                      $pkg->getPackageType() == 'zendextbin') {
                    if ($instbin = $pkg->getInstalledBinary()) {
                        continue; // this will be uninstalled later
                    }

                    foreach ($pkg->getFilelist() as $name => $atts) {
                        $pinfo = pathinfo($atts['installed_as']);
                        if (!isset($pinfo['extension']) ||
                              in_array($pinfo['extension'], array('c', 'h'))) {
                            continue; // make sure we don't match php_blah.h
                        }
                        if ((strpos($pinfo['basename'], 'php_') === 0 &&
                              $pinfo['extension'] == 'dll') ||
                              // most unices
                              $pinfo['extension'] == 'so' ||
                              // hp-ux
                              $pinfo['extension'] == 'sl') {
                            $binaries[] = array($atts['installed_as'], $pinfo);
                            break;
                        }
                    }
                    if (count($binaries)) {
                        foreach ($binaries as $pinfo) {
                            PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                            $ret = $this->disableExtension(array($pinfo[0]), $pkg->getPackageType());
                            PEAR::staticPopErrorHandling();
                            if (PEAR::isError($ret)) {
                                $extrainfo[] = $ret->getMessage();
                                if ($pkg->getPackageType() == 'extsrc' ||
                                      $pkg->getPackageType() == 'extbin') {
                                    $exttype = 'extension';
                                } else {
                                    ob_start();
                                    phpinfo(INFO_GENERAL);
                                    $info = ob_get_contents();
                                    ob_end_clean();
                                    $debug = function_exists('leak') ? '_debug' : '';
                                    $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
                                    $exttype = 'zend_extension' . $debug . $ts;
                                }
                                $this->ui->outputData('Unable to remove "' . $exttype . '=' .
                                    $pinfo[1]['basename'] . '" from php.ini', $command);
                            } else {
                                $this->ui->outputData('Extension ' . $pkg->getProvidesExtension() .
                                    ' disabled in php.ini', $command);
                            }
                        }
                    }
                }
                $savepkg = $pkg;
                if ($this->config->get('verbose') > 0) {
                    if (is_object($pkg)) {
                        $pkg = $reg->parsedPackageNameToString($pkg);
                    }
                    $this->ui->outputData("uninstall ok: $pkg", $command);
                }
                if (!isset($options['offline']) && is_object($savepkg) &&
                      defined('PEAR_REMOTEINSTALL_OK')) {
                    if ($this->config->isDefinedLayer('ftp')) {
                        $this->installer->pushErrorHandling(PEAR_ERROR_RETURN);
                        $info = $this->installer->ftpUninstall($savepkg);
                        $this->installer->popErrorHandling();
                        if (PEAR::isError($info)) {
                            $this->ui->outputData($info->getMessage());
                            $this->ui->outputData("remote uninstall failed: $pkg");
                        } else {
                            $this->ui->outputData("remote uninstall ok: $pkg");
                        }
                    }
                }
            } else {
                $this->installer->popErrorHandling();
                if (!is_object($pkg)) {
                    return $this->raiseError("uninstall failed: $pkg");
                }
                $pkg = $reg->parsedPackageNameToString($pkg);
            }
        }

        return true;
    }

    // }}}


    // }}}
    // {{{ doBundle()
    /*
    (cox) It just downloads and untars the package, does not do
            any check that the PEAR_Installer::_installFile() does.
    */

    function doBundle($command, $options, $params)
    {
        $opts = array(
            'force'        => true,
            'nodeps'       => true,
            'soft'         => true,
            'downloadonly' => true
        );
        $downloader = &$this->getDownloader($this->ui, $opts, $this->config);
        $reg = &$this->config->getRegistry();
        if (count($params) < 1) {
            return $this->raiseError("Please supply the package you want to bundle");
        }

        if (isset($options['destination'])) {
            if (!is_dir($options['destination'])) {
                System::mkdir('-p ' . $options['destination']);
            }
            $dest = realpath($options['destination']);
        } else {
            $pwd  = getcwd();
            $dir  = $pwd . DIRECTORY_SEPARATOR . 'ext';
            $dest = is_dir($dir) ? $dir : $pwd;
        }
        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        $err = $downloader->setDownloadDir($dest);
        PEAR::staticPopErrorHandling();
        if (PEAR::isError($err)) {
            return PEAR::raiseError('download directory "' . $dest .
                '" is not writeable.');
        }
        $result = &$downloader->download(array($params[0]));
        if (PEAR::isError($result)) {
            return $result;
        }
        if (!isset($result[0])) {
            return $this->raiseError('unable to unpack ' . $params[0]);
        }
        $pkgfile = &$result[0]->getPackageFile();
        $pkgname = $pkgfile->getName();
        $pkgversion = $pkgfile->getVersion();

        // Unpacking -------------------------------------------------
        $dest .= DIRECTORY_SEPARATOR . $pkgname;
        $orig = $pkgname . '-' . $pkgversion;

        $tar = new Archive_Tar($pkgfile->getArchiveFile());
        if (!$tar->extractModify($dest, $orig)) {
            return $this->raiseError('unable to unpack ' . $pkgfile->getArchiveFile());
        }
        $this->ui->outputData("Package ready at '$dest'");
    // }}}
    }

    // }}}

    function doRunScripts($command, $options, $params)
    {
        if (!isset($params[0])) {
            return $this->raiseError('run-scripts expects 1 parameter: a package name');
        }

        $reg = &$this->config->getRegistry();
        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        $parsed = $reg->parsePackageName($params[0], $this->config->get('default_channel'));
        PEAR::staticPopErrorHandling();
        if (PEAR::isError($parsed)) {
            return $this->raiseError($parsed);
        }

        $package = &$reg->getPackage($parsed['package'], $parsed['channel']);
        if (!is_object($package)) {
            return $this->raiseError('Could not retrieve package "' . $params[0] . '" from registry');
        }

        $package->setConfig($this->config);
        $package->runPostinstallScripts();
        $this->ui->outputData('Install scripts complete', $command);
        return true;
    }

    /**
     * Given a list of packages, filter out those ones that are already up to date
     *
     * @param $packages: packages, in parsed array format !
     * @return list of packages that can be upgraded
     */
    function _filterUptodatePackages($packages, $command)
    {
        $reg = &$this->config->getRegistry();
        $latestReleases = array();

        $ret = array();
        foreach ($packages as $package) {
            if (isset($package['group'])) {
                $ret[] = $package;
                continue;
            }

            $channel = $package['channel'];
            $name    = $package['package'];
            if (!$reg->packageExists($name, $channel)) {
                $ret[] = $package;
                continue;
            }

            if (!isset($latestReleases[$channel])) {
                // fill in cache for this channel
                $chan = $reg->getChannel($channel);
                if (PEAR::isError($chan)) {
                    return $this->raiseError($chan);
                }

                $base2 = false;
                $preferred_mirror = $this->config->get('preferred_mirror', null, $channel);
                if ($chan->supportsREST($preferred_mirror) &&
                    (
                       //($base2 = $chan->getBaseURL('REST1.4', $preferred_mirror)) ||
                       ($base  = $chan->getBaseURL('REST1.0', $preferred_mirror))
                    )
                ) {
                    $dorest = true;
                }

                PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                if (!isset($package['state'])) {
                    $state = $this->config->get('preferred_state', null, $channel);
                } else {
                    $state = $package['state'];
                }

                if ($dorest) {
                    if ($base2) {
                        $rest = &$this->config->getREST('1.4', array());
                        $base = $base2;
                    } else {
                        $rest = &$this->config->getREST('1.0', array());
                    }

                    $installed = array_flip($reg->listPackages($channel));
                    $latest    = $rest->listLatestUpgrades($base, $state, $installed, $channel, $reg);
                }

                PEAR::staticPopErrorHandling();
                if (PEAR::isError($latest)) {
                    $this->ui->outputData('Error getting channel info from ' . $channel .
                        ': ' . $latest->getMessage());
                    continue;
                }

                $latestReleases[$channel] = array_change_key_case($latest);
            }

            // check package for latest release
            $name_lower = strtolower($name);
            if (isset($latestReleases[$channel][$name_lower])) {
                // if not set, up to date
                $inst_version    = $reg->packageInfo($name, 'version', $channel);
                $channel_version = $latestReleases[$channel][$name_lower]['version'];
                if (version_compare($channel_version, $inst_version, 'le')) {
                    // installed version is up-to-date
                    continue;
                }

                // maintain BC
                if ($command == 'upgrade-all') {
                    $this->ui->outputData(array('data' => 'Will upgrade ' .
                        $reg->parsedPackageNameToString($package)), $command);
                }
                $ret[] = $package;
            }
        }

        return $ret;
    }
}
PKo�Z�X�

PEAR/Command/Auth.phpnu�[���<?php
/**
 * PEAR_Command_Auth (login, logout commands)
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 0.1
 * @deprecated since 1.8.0alpha1
 */

/**
 * base class
 */
require_once 'PEAR/Command/Channels.php';

/**
 * PEAR commands for login/logout
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 0.1
 * @deprecated since 1.8.0alpha1
 */
class PEAR_Command_Auth extends PEAR_Command_Channels
{
    var $commands = array(
        'login' => array(
            'summary' => 'Connects and authenticates to remote server [Deprecated in favor of channel-login]',
            'shortcut' => 'li',
            'function' => 'doLogin',
            'options' => array(),
            'doc' => '<channel name>
WARNING: This function is deprecated in favor of using channel-login

Log in to a remote channel server.  If <channel name> is not supplied,
the default channel is used. To use remote functions in the installer
that require any kind of privileges, you need to log in first.  The
username and password you enter here will be stored in your per-user
PEAR configuration (~/.pearrc on Unix-like systems).  After logging
in, your username and password will be sent along in subsequent
operations on the remote server.',
            ),
        'logout' => array(
            'summary' => 'Logs out from the remote server [Deprecated in favor of channel-logout]',
            'shortcut' => 'lo',
            'function' => 'doLogout',
            'options' => array(),
            'doc' => '
WARNING: This function is deprecated in favor of using channel-logout

Logs out from the remote server.  This command does not actually
connect to the remote server, it only deletes the stored username and
password from your user configuration.',
            )

        );

    /**
     * PEAR_Command_Auth constructor.
     *
     * @access public
     */
    function __construct(&$ui, &$config)
    {
        parent::__construct($ui, $config);
    }
}
PKo�Z���s6
6
PEAR/Command/Config.xmlnu�[���<commands version="1.0">
 <config-show>
  <summary>Show All Settings</summary>
  <function>doConfigShow</function>
  <shortcut>csh</shortcut>
  <options>
   <channel>
    <shortopt>c</shortopt>
    <doc>show configuration variables for another channel</doc>
    <arg>CHAN</arg>
   </channel>
  </options>
  <doc>[layer]
Displays all configuration values.  An optional argument
may be used to tell which configuration layer to display.  Valid
configuration layers are &quot;user&quot;, &quot;system&quot; and &quot;default&quot;. To display
configurations for different channels, set the default_channel
configuration variable and run config-show again.
</doc>
 </config-show>
 <config-get>
  <summary>Show One Setting</summary>
  <function>doConfigGet</function>
  <shortcut>cg</shortcut>
  <options>
   <channel>
    <shortopt>c</shortopt>
    <doc>show configuration variables for another channel</doc>
    <arg>CHAN</arg>
   </channel>
  </options>
  <doc>&lt;parameter&gt; [layer]
Displays the value of one configuration parameter.  The
first argument is the name of the parameter, an optional second argument
may be used to tell which configuration layer to look in.  Valid configuration
layers are &quot;user&quot;, &quot;system&quot; and &quot;default&quot;.  If no layer is specified, a value
will be picked from the first layer that defines the parameter, in the order
just specified.  The configuration value will be retrieved for the channel
specified by the default_channel configuration variable.
</doc>
 </config-get>
 <config-set>
  <summary>Change Setting</summary>
  <function>doConfigSet</function>
  <shortcut>cs</shortcut>
  <options>
   <channel>
    <shortopt>c</shortopt>
    <doc>show configuration variables for another channel</doc>
    <arg>CHAN</arg>
   </channel>
  </options>
  <doc>&lt;parameter&gt; &lt;value&gt; [layer]
Sets the value of one configuration parameter.  The first argument is
the name of the parameter, the second argument is the new value.  Some
parameters are subject to validation, and the command will fail with
an error message if the new value does not make sense.  An optional
third argument may be used to specify in which layer to set the
configuration parameter.  The default layer is &quot;user&quot;.  The
configuration value will be set for the current channel, which
is controlled by the default_channel configuration variable.
</doc>
 </config-set>
 <config-help>
  <summary>Show Information About Setting</summary>
  <function>doConfigHelp</function>
  <shortcut>ch</shortcut>
  <options />
  <doc>[parameter]
Displays help for a configuration parameter.  Without arguments it
displays help for all configuration parameters.
</doc>
 </config-help>
 <config-create>
  <summary>Create a Default configuration file</summary>
  <function>doConfigCreate</function>
  <shortcut>coc</shortcut>
  <options>
   <windows>
    <shortopt>w</shortopt>
    <doc>create a config file for a windows install</doc>
   </windows>
  </options>
  <doc>&lt;root path&gt; &lt;filename&gt;
Create a default configuration file with all directory configuration
variables set to subdirectories of &lt;root path&gt;, and save it as &lt;filename&gt;.
This is useful especially for creating a configuration file for a remote
PEAR installation (using the --remoteconfig option of install, upgrade,
and uninstall).
</doc>
 </config-create>
</commands>PKo�Z�%FiiPEAR/Command/Test.xmlnu�[���<commands version="1.0">
 <run-tests>
  <summary>Run Regression Tests</summary>
  <function>doRunTests</function>
  <shortcut>rt</shortcut>
  <options>
   <recur>
    <shortopt>r</shortopt>
    <doc>Run tests in child directories, recursively.  4 dirs deep maximum</doc>
   </recur>
   <ini>
    <shortopt>i</shortopt>
    <doc>actual string of settings to pass to php in format &quot; -d setting=blah&quot;</doc>
    <arg>SETTINGS</arg>
   </ini>
   <realtimelog>
    <shortopt>l</shortopt>
    <doc>Log test runs/results as they are run</doc>
   </realtimelog>
   <quiet>
    <shortopt>q</shortopt>
    <doc>Only display detail for failed tests</doc>
   </quiet>
   <simple>
    <shortopt>s</shortopt>
    <doc>Display simple output for all tests</doc>
   </simple>
   <package>
    <shortopt>p</shortopt>
    <doc>Treat parameters as installed packages from which to run tests</doc>
   </package>
   <phpunit>
    <shortopt>u</shortopt>
    <doc>Search parameters for AllTests.php, and use that to run phpunit-based tests
If none is found, all .phpt tests will be tried instead.</doc>
   </phpunit>
   <tapoutput>
    <shortopt>t</shortopt>
    <doc>Output run-tests.log in TAP-compliant format</doc>
   </tapoutput>
   <cgi>
    <shortopt>c</shortopt>
    <doc>CGI php executable (needed for tests with POST/GET section)</doc>
    <arg>PHPCGI</arg>
   </cgi>
   <coverage>
    <shortopt>x</shortopt>
    <doc>Generate a code coverage report (requires Xdebug 2.0.0+)</doc>
   </coverage>
  </options>
  <doc>[testfile|dir ...]
Run regression tests with PHP&#039;s regression testing script (run-tests.php).</doc>
 </run-tests>
</commands>PKo�ZZ h66PEAR/Command/Package.xmlnu�[���<commands version="1.0">
 <package>
  <summary>Build Package</summary>
  <function>doPackage</function>
  <shortcut>p</shortcut>
  <options>
   <nocompress>
    <shortopt>Z</shortopt>
    <doc>Do not gzip the package file</doc>
   </nocompress>
   <showname>
    <shortopt>n</shortopt>
    <doc>Print the name of the packaged file.</doc>
   </showname>
  </options>
  <doc>[descfile] [descfile2]
Creates a PEAR package from its description file (usually called
package.xml).  If a second packagefile is passed in, then
the packager will check to make sure that one is a package.xml
version 1.0, and the other is a package.xml version 2.0.  The
package.xml version 1.0 will be saved as &quot;package.xml&quot; in the archive,
and the other as &quot;package2.xml&quot; in the archive&quot;
</doc>
 </package>
 <package-validate>
  <summary>Validate Package Consistency</summary>
  <function>doPackageValidate</function>
  <shortcut>pv</shortcut>
  <options />
  <doc>
</doc>
 </package-validate>
 <cvsdiff>
  <summary>Run a &quot;cvs diff&quot; for all files in a package</summary>
  <function>doCvsDiff</function>
  <shortcut>cd</shortcut>
  <options>
   <quiet>
    <shortopt>q</shortopt>
    <doc>Be quiet</doc>
   </quiet>
   <reallyquiet>
    <shortopt>Q</shortopt>
    <doc>Be really quiet</doc>
   </reallyquiet>
   <date>
    <shortopt>D</shortopt>
    <doc>Diff against revision of DATE</doc>
    <arg>DATE</arg>
   </date>
   <release>
    <shortopt>R</shortopt>
    <doc>Diff against tag for package release REL</doc>
    <arg>REL</arg>
   </release>
   <revision>
    <shortopt>r</shortopt>
    <doc>Diff against revision REV</doc>
    <arg>REV</arg>
   </revision>
   <context>
    <shortopt>c</shortopt>
    <doc>Generate context diff</doc>
   </context>
   <unified>
    <shortopt>u</shortopt>
    <doc>Generate unified diff</doc>
   </unified>
   <ignore-case>
    <shortopt>i</shortopt>
    <doc>Ignore case, consider upper- and lower-case letters equivalent</doc>
   </ignore-case>
   <ignore-whitespace>
    <shortopt>b</shortopt>
    <doc>Ignore changes in amount of white space</doc>
   </ignore-whitespace>
   <ignore-blank-lines>
    <shortopt>B</shortopt>
    <doc>Ignore changes that insert or delete blank lines</doc>
   </ignore-blank-lines>
   <brief>
    <shortopt></shortopt>
    <doc>Report only whether the files differ, no details</doc>
   </brief>
   <dry-run>
    <shortopt>n</shortopt>
    <doc>Don&#039;t do anything, just pretend</doc>
   </dry-run>
  </options>
  <doc>&lt;package.xml&gt;
Compares all the files in a package.  Without any options, this
command will compare the current code with the last checked-in code.
Using the -r or -R option you may compare the current code with that
of a specific release.
</doc>
 </cvsdiff>
 <svntag>
  <summary>Set SVN Release Tag</summary>
  <function>doSvnTag</function>
  <shortcut>sv</shortcut>
  <options>
   <quiet>
    <shortopt>q</shortopt>
    <doc>Be quiet</doc>
   </quiet>
   <slide>
    <shortopt>F</shortopt>
    <doc>Move (slide) tag if it exists</doc>
   </slide>
   <delete>
    <shortopt>d</shortopt>
    <doc>Remove tag</doc>
   </delete>
   <dry-run>
    <shortopt>n</shortopt>
    <doc>Don&#039;t do anything, just pretend</doc>
   </dry-run>
  </options>
  <doc>&lt;package.xml&gt; [files...]
 Sets a SVN tag on all files in a package.  Use this command after you have
 packaged a distribution tarball with the &quot;package&quot; command to tag what
 revisions of what files were in that release.  If need to fix something
 after running svntag once, but before the tarball is released to the public,
 use the &quot;slide&quot; option to move the release tag.

 to include files (such as a second package.xml, or tests not included in the
 release), pass them as additional parameters.
 </doc>
 </svntag>
 <cvstag>
  <summary>Set CVS Release Tag</summary>
  <function>doCvsTag</function>
  <shortcut>ct</shortcut>
  <options>
   <quiet>
    <shortopt>q</shortopt>
    <doc>Be quiet</doc>
   </quiet>
   <reallyquiet>
    <shortopt>Q</shortopt>
    <doc>Be really quiet</doc>
   </reallyquiet>
   <slide>
    <shortopt>F</shortopt>
    <doc>Move (slide) tag if it exists</doc>
   </slide>
   <delete>
    <shortopt>d</shortopt>
    <doc>Remove tag</doc>
   </delete>
   <dry-run>
    <shortopt>n</shortopt>
    <doc>Don&#039;t do anything, just pretend</doc>
   </dry-run>
  </options>
  <doc>&lt;package.xml&gt; [files...]
Sets a CVS tag on all files in a package.  Use this command after you have
packaged a distribution tarball with the &quot;package&quot; command to tag what
revisions of what files were in that release.  If need to fix something
after running cvstag once, but before the tarball is released to the public,
use the &quot;slide&quot; option to move the release tag.

to include files (such as a second package.xml, or tests not included in the
release), pass them as additional parameters.
</doc>
 </cvstag>
 <package-dependencies>
  <summary>Show package dependencies</summary>
  <function>doPackageDependencies</function>
  <shortcut>pd</shortcut>
  <options />
  <doc>&lt;package-file&gt; or &lt;package.xml&gt; or &lt;install-package-name&gt;
List all dependencies the package has.
Can take a tgz / tar file, package.xml or a package name of an installed package.</doc>
 </package-dependencies>
 <sign>
  <summary>Sign a package distribution file</summary>
  <function>doSign</function>
  <shortcut>si</shortcut>
  <options>
   <verbose>
    <shortopt>v</shortopt>
    <doc>Display GnuPG output</doc>
   </verbose>
  </options>
  <doc>&lt;package-file&gt;
Signs a package distribution (.tar or .tgz) file with GnuPG.</doc>
 </sign>
 <makerpm>
  <summary>Builds an RPM spec file from a PEAR package</summary>
  <function>doMakeRPM</function>
  <shortcut>rpm</shortcut>
  <options>
   <spec-template>
    <shortopt>t</shortopt>
    <doc>Use FILE as RPM spec file template</doc>
    <arg>FILE</arg>
   </spec-template>
   <rpm-pkgname>
    <shortopt>p</shortopt>
    <doc>Use FORMAT as format string for RPM package name, %s is replaced
by the PEAR package name, defaults to &quot;PEAR::%s&quot;.</doc>
    <arg>FORMAT</arg>
   </rpm-pkgname>
  </options>
  <doc>&lt;package-file&gt;

Creates an RPM .spec file for wrapping a PEAR package inside an RPM
package.  Intended to be used from the SPECS directory, with the PEAR
package tarball in the SOURCES directory:

$ pear makerpm ../SOURCES/Net_Socket-1.0.tgz
Wrote RPM spec file PEAR::Net_Geo-1.0.spec
$ rpm -bb PEAR::Net_Socket-1.0.spec
...
Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm
</doc>
 </makerpm>
 <convert>
  <summary>Convert a package.xml 1.0 to package.xml 2.0 format</summary>
  <function>doConvert</function>
  <shortcut>c2</shortcut>
  <options>
   <flat>
    <shortopt>f</shortopt>
    <doc>do not beautify the filelist.</doc>
   </flat>
  </options>
  <doc>[descfile] [descfile2]
Converts a package.xml in 1.0 format into a package.xml
in 2.0 format.  The new file will be named package2.xml by default,
and package.xml will be used as the old file by default.
This is not the most intelligent conversion, and should only be
used for automated conversion or learning the format.
</doc>
 </convert>
</commands>PKo�Z�w��zzPEAR/Command/Channels.xmlnu�[���<commands version="1.0">
 <list-channels>
  <summary>List Available Channels</summary>
  <function>doList</function>
  <shortcut>lc</shortcut>
  <options />
  <doc>
List all available channels for installation.
</doc>
 </list-channels>
 <update-channels>
  <summary>Update the Channel List</summary>
  <function>doUpdateAll</function>
  <shortcut>uc</shortcut>
  <options />
  <doc>
List all installed packages in all channels.
</doc>
 </update-channels>
 <channel-delete>
  <summary>Remove a Channel From the List</summary>
  <function>doDelete</function>
  <shortcut>cde</shortcut>
  <options />
  <doc>&lt;channel name&gt;
Delete a channel from the registry.  You may not
remove any channel that has installed packages.
</doc>
 </channel-delete>
 <channel-add>
  <summary>Add a Channel</summary>
  <function>doAdd</function>
  <shortcut>ca</shortcut>
  <options />
  <doc>&lt;channel.xml&gt;
Add a private channel to the channel list.  Note that all
public channels should be synced using &quot;update-channels&quot;.
Parameter may be either a local file or remote URL to a
channel.xml.
</doc>
 </channel-add>
 <channel-update>
  <summary>Update an Existing Channel</summary>
  <function>doUpdate</function>
  <shortcut>cu</shortcut>
  <options>
   <force>
    <shortopt>f</shortopt>
    <doc>will force download of new channel.xml if an existing channel name is used</doc>
   </force>
   <channel>
    <shortopt>c</shortopt>
    <doc>will force download of new channel.xml if an existing channel name is used</doc>
    <arg>CHANNEL</arg>
   </channel>
  </options>
  <doc>[&lt;channel.xml&gt;|&lt;channel name&gt;]
Update a channel in the channel list directly.  Note that all
public channels can be synced using &quot;update-channels&quot;.
Parameter may be a local or remote channel.xml, or the name of
an existing channel.
</doc>
 </channel-update>
 <channel-info>
  <summary>Retrieve Information on a Channel</summary>
  <function>doInfo</function>
  <shortcut>ci</shortcut>
  <options />
  <doc>&lt;package&gt;
List the files in an installed package.
</doc>
 </channel-info>
 <channel-alias>
  <summary>Specify an alias to a channel name</summary>
  <function>doAlias</function>
  <shortcut>cha</shortcut>
  <options />
  <doc>&lt;channel&gt; &lt;alias&gt;
Specify a specific alias to use for a channel name.
The alias may not be an existing channel name or
alias.
</doc>
 </channel-alias>
 <channel-discover>
  <summary>Initialize a Channel from its server</summary>
  <function>doDiscover</function>
  <shortcut>di</shortcut>
  <options />
  <doc>[&lt;channel.xml&gt;|&lt;channel name&gt;]
Initialize a channel from its server and create a local channel.xml.
If &lt;channel name&gt; is in the format &quot;&lt;username&gt;:&lt;password&gt;@&lt;channel&gt;&quot; then
&lt;username&gt; and &lt;password&gt; will be set as the login username/password for
&lt;channel&gt;. Use caution when passing the username/password in this way, as
it may allow other users on your computer to briefly view your username/
password via the system&#039;s process list.
</doc>
 </channel-discover>
 <channel-login>
  <summary>Connects and authenticates to remote channel server</summary>
  <function>doLogin</function>
  <shortcut>cli</shortcut>
  <options />
  <doc>&lt;channel name&gt;
Log in to a remote channel server.  If &lt;channel name&gt; is not supplied,
the default channel is used. To use remote functions in the installer
that require any kind of privileges, you need to log in first.  The
username and password you enter here will be stored in your per-user
PEAR configuration (~/.pearrc on Unix-like systems).  After logging
in, your username and password will be sent along in subsequent
operations on the remote server.</doc>
 </channel-login>
 <channel-logout>
  <summary>Logs out from the remote channel server</summary>
  <function>doLogout</function>
  <shortcut>clo</shortcut>
  <options />
  <doc>&lt;channel name&gt;
Logs out from a remote channel server.  If &lt;channel name&gt; is not supplied,
the default channel is used. This command does not actually connect to the
remote server, it only deletes the stored username and password from your user
configuration.</doc>
 </channel-logout>
</commands>PKo�Z+9ҜҜPEAR/Command/Package.phpnu�[���<?php
/**
 * PEAR_Command_Package (package, package-validate, cvsdiff, cvstag, package-dependencies,
 * sign, makerpm, convert commands)
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Martin Jansen <mj@php.net>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 0.1
 */

/**
 * base class
 */
require_once 'PEAR/Command/Common.php';

/**
 * PEAR commands for login/logout
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Martin Jansen <mj@php.net>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 0.1
 */

class PEAR_Command_Package extends PEAR_Command_Common
{
    var $commands = array(
        'package' => array(
            'summary' => 'Build Package',
            'function' => 'doPackage',
            'shortcut' => 'p',
            'options' => array(
                'nocompress' => array(
                    'shortopt' => 'Z',
                    'doc' => 'Do not gzip the package file'
                    ),
                'showname' => array(
                    'shortopt' => 'n',
                    'doc' => 'Print the name of the packaged file.',
                    ),
                ),
            'doc' => '[descfile] [descfile2]
Creates a PEAR package from its description file (usually called
package.xml).  If a second packagefile is passed in, then
the packager will check to make sure that one is a package.xml
version 1.0, and the other is a package.xml version 2.0.  The
package.xml version 1.0 will be saved as "package.xml" in the archive,
and the other as "package2.xml" in the archive"
'
            ),
        'package-validate' => array(
            'summary' => 'Validate Package Consistency',
            'function' => 'doPackageValidate',
            'shortcut' => 'pv',
            'options' => array(),
            'doc' => '
',
            ),
        'cvsdiff' => array(
            'summary' => 'Run a "cvs diff" for all files in a package',
            'function' => 'doCvsDiff',
            'shortcut' => 'cd',
            'options' => array(
                'quiet' => array(
                    'shortopt' => 'q',
                    'doc' => 'Be quiet',
                    ),
                'reallyquiet' => array(
                    'shortopt' => 'Q',
                    'doc' => 'Be really quiet',
                    ),
                'date' => array(
                    'shortopt' => 'D',
                    'doc' => 'Diff against revision of DATE',
                    'arg' => 'DATE',
                    ),
                'release' => array(
                    'shortopt' => 'R',
                    'doc' => 'Diff against tag for package release REL',
                    'arg' => 'REL',
                    ),
                'revision' => array(
                    'shortopt' => 'r',
                    'doc' => 'Diff against revision REV',
                    'arg' => 'REV',
                    ),
                'context' => array(
                    'shortopt' => 'c',
                    'doc' => 'Generate context diff',
                    ),
                'unified' => array(
                    'shortopt' => 'u',
                    'doc' => 'Generate unified diff',
                    ),
                'ignore-case' => array(
                    'shortopt' => 'i',
                    'doc' => 'Ignore case, consider upper- and lower-case letters equivalent',
                    ),
                'ignore-whitespace' => array(
                    'shortopt' => 'b',
                    'doc' => 'Ignore changes in amount of white space',
                    ),
                'ignore-blank-lines' => array(
                    'shortopt' => 'B',
                    'doc' => 'Ignore changes that insert or delete blank lines',
                    ),
                'brief' => array(
                    'doc' => 'Report only whether the files differ, no details',
                    ),
                'dry-run' => array(
                    'shortopt' => 'n',
                    'doc' => 'Don\'t do anything, just pretend',
                    ),
                ),
            'doc' => '<package.xml>
Compares all the files in a package.  Without any options, this
command will compare the current code with the last checked-in code.
Using the -r or -R option you may compare the current code with that
of a specific release.
',
            ),
         'svntag' => array(
             'summary' => 'Set SVN Release Tag',
             'function' => 'doSvnTag',
             'shortcut' => 'sv',
             'options' => array(
                 'quiet' => array(
                     'shortopt' => 'q',
                     'doc' => 'Be quiet',
                     ),
                 'slide' => array(
                     'shortopt' => 'F',
                     'doc' => 'Move (slide) tag if it exists',
                     ),
                 'delete' => array(
                     'shortopt' => 'd',
                     'doc' => 'Remove tag',
                     ),
                 'dry-run' => array(
                     'shortopt' => 'n',
                     'doc' => 'Don\'t do anything, just pretend',
                     ),
                 ),
             'doc' => '<package.xml> [files...]
 Sets a SVN tag on all files in a package.  Use this command after you have
 packaged a distribution tarball with the "package" command to tag what
 revisions of what files were in that release.  If need to fix something
 after running svntag once, but before the tarball is released to the public,
 use the "slide" option to move the release tag.

 to include files (such as a second package.xml, or tests not included in the
 release), pass them as additional parameters.
 ',
             ),
        'cvstag' => array(
            'summary' => 'Set CVS Release Tag',
            'function' => 'doCvsTag',
            'shortcut' => 'ct',
            'options' => array(
                'quiet' => array(
                    'shortopt' => 'q',
                    'doc' => 'Be quiet',
                    ),
                'reallyquiet' => array(
                    'shortopt' => 'Q',
                    'doc' => 'Be really quiet',
                    ),
                'slide' => array(
                    'shortopt' => 'F',
                    'doc' => 'Move (slide) tag if it exists',
                    ),
                'delete' => array(
                    'shortopt' => 'd',
                    'doc' => 'Remove tag',
                    ),
                'dry-run' => array(
                    'shortopt' => 'n',
                    'doc' => 'Don\'t do anything, just pretend',
                    ),
                ),
            'doc' => '<package.xml> [files...]
Sets a CVS tag on all files in a package.  Use this command after you have
packaged a distribution tarball with the "package" command to tag what
revisions of what files were in that release.  If need to fix something
after running cvstag once, but before the tarball is released to the public,
use the "slide" option to move the release tag.

to include files (such as a second package.xml, or tests not included in the
release), pass them as additional parameters.
',
            ),
        'package-dependencies' => array(
            'summary' => 'Show package dependencies',
            'function' => 'doPackageDependencies',
            'shortcut' => 'pd',
            'options' => array(),
            'doc' => '<package-file> or <package.xml> or <install-package-name>
List all dependencies the package has.
Can take a tgz / tar file, package.xml or a package name of an installed package.'
            ),
        'sign' => array(
            'summary' => 'Sign a package distribution file',
            'function' => 'doSign',
            'shortcut' => 'si',
            'options' => array(
                'verbose' => array(
                    'shortopt' => 'v',
                    'doc' => 'Display GnuPG output',
                    ),
            ),
            'doc' => '<package-file>
Signs a package distribution (.tar or .tgz) file with GnuPG.',
            ),
        'makerpm' => array(
            'summary' => 'Builds an RPM spec file from a PEAR package',
            'function' => 'doMakeRPM',
            'shortcut' => 'rpm',
            'options' => array(
                'spec-template' => array(
                    'shortopt' => 't',
                    'arg' => 'FILE',
                    'doc' => 'Use FILE as RPM spec file template'
                    ),
                'rpm-pkgname' => array(
                    'shortopt' => 'p',
                    'arg' => 'FORMAT',
                    'doc' => 'Use FORMAT as format string for RPM package name, %s is replaced
by the PEAR package name, defaults to "PEAR::%s".',
                    ),
                ),
            'doc' => '<package-file>

Creates an RPM .spec file for wrapping a PEAR package inside an RPM
package.  Intended to be used from the SPECS directory, with the PEAR
package tarball in the SOURCES directory:

$ pear makerpm ../SOURCES/Net_Socket-1.0.tgz
Wrote RPM spec file PEAR::Net_Geo-1.0.spec
$ rpm -bb PEAR::Net_Socket-1.0.spec
...
Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm
',
            ),
        'convert' => array(
            'summary' => 'Convert a package.xml 1.0 to package.xml 2.0 format',
            'function' => 'doConvert',
            'shortcut' => 'c2',
            'options' => array(
                'flat' => array(
                    'shortopt' => 'f',
                    'doc' => 'do not beautify the filelist.',
                    ),
                ),
            'doc' => '[descfile] [descfile2]
Converts a package.xml in 1.0 format into a package.xml
in 2.0 format.  The new file will be named package2.xml by default,
and package.xml will be used as the old file by default.
This is not the most intelligent conversion, and should only be
used for automated conversion or learning the format.
'
            ),
        );

    var $output;

    /**
     * PEAR_Command_Package constructor.
     *
     * @access public
     */
    function __construct(&$ui, &$config)
    {
        parent::__construct($ui, $config);
    }

    function _displayValidationResults($err, $warn, $strict = false)
    {
        foreach ($err as $e) {
            $this->output .= "Error: $e\n";
        }
        foreach ($warn as $w) {
            $this->output .= "Warning: $w\n";
        }
        $this->output .= sprintf('Validation: %d error(s), %d warning(s)'."\n",
                                       sizeof($err), sizeof($warn));
        if ($strict && count($err) > 0) {
            $this->output .= "Fix these errors and try again.";
            return false;
        }
        return true;
    }

    function &getPackager()
    {
        if (!class_exists('PEAR_Packager')) {
            require_once 'PEAR/Packager.php';
        }
        $a = new PEAR_Packager;
        return $a;
    }

    function &getPackageFile($config, $debug = false)
    {
        if (!class_exists('PEAR_Common')) {
            require_once 'PEAR/Common.php';
        }
        if (!class_exists('PEAR_PackageFile')) {
            require_once 'PEAR/PackageFile.php';
        }
        $a = new PEAR_PackageFile($config, $debug);
        $common = new PEAR_Common;
        $common->ui = $this->ui;
        $a->setLogger($common);
        return $a;
    }

    function doPackage($command, $options, $params)
    {
        $this->output = '';
        $pkginfofile = isset($params[0]) ? $params[0] : 'package.xml';
        $pkg2 = isset($params[1]) ? $params[1] : null;
        if (!$pkg2 && !isset($params[0]) && file_exists('package2.xml')) {
            $pkg2 = 'package2.xml';
        }

        $packager = &$this->getPackager();
        $compress = empty($options['nocompress']) ? true : false;
        $result   = $packager->package($pkginfofile, $compress, $pkg2);
        if (PEAR::isError($result)) {
            return $this->raiseError($result);
        }

        // Don't want output, only the package file name just created
        if (isset($options['showname'])) {
            $this->output = $result;
        }

        if ($this->output) {
            $this->ui->outputData($this->output, $command);
        }

        return true;
    }

    function doPackageValidate($command, $options, $params)
    {
        $this->output = '';
        if (count($params) < 1) {
            $params[0] = 'package.xml';
        }

        $obj = &$this->getPackageFile($this->config, $this->_debug);
        $obj->rawReturn();
        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        $info = $obj->fromTgzFile($params[0], PEAR_VALIDATE_NORMAL);
        if (PEAR::isError($info)) {
            $info = $obj->fromPackageFile($params[0], PEAR_VALIDATE_NORMAL);
        } else {
            $archive = $info->getArchiveFile();
            $tar = new Archive_Tar($archive);
            $tar->extract(dirname($info->getPackageFile()));
            $info->setPackageFile(dirname($info->getPackageFile()) . DIRECTORY_SEPARATOR .
                $info->getPackage() . '-' . $info->getVersion() . DIRECTORY_SEPARATOR .
                basename($info->getPackageFile()));
        }

        PEAR::staticPopErrorHandling();
        if (PEAR::isError($info)) {
            return $this->raiseError($info);
        }

        $valid = false;
        if ($info->getPackagexmlVersion() == '2.0') {
            if ($valid = $info->validate(PEAR_VALIDATE_NORMAL)) {
                $info->flattenFileList();
                $valid = $info->validate(PEAR_VALIDATE_PACKAGING);
            }
        } else {
            $valid = $info->validate(PEAR_VALIDATE_PACKAGING);
        }

        $err = $warn = array();
        if ($errors = $info->getValidationWarnings()) {
            foreach ($errors as $error) {
                if ($error['level'] == 'warning') {
                    $warn[] = $error['message'];
                } else {
                    $err[] = $error['message'];
                }
            }
        }

        $this->_displayValidationResults($err, $warn);
        $this->ui->outputData($this->output, $command);
        return true;
    }

    function doSvnTag($command, $options, $params)
    {
        $this->output = '';
        $_cmd = $command;
        if (count($params) < 1) {
            $help = $this->getHelp($command);
            return $this->raiseError("$command: missing parameter: $help[0]");
        }

        $packageFile = realpath($params[0]);
        $dir = dirname($packageFile);
        $dir = substr($dir, strrpos($dir, DIRECTORY_SEPARATOR) + 1);
        $obj  = &$this->getPackageFile($this->config, $this->_debug);
        $info = $obj->fromAnyFile($packageFile, PEAR_VALIDATE_NORMAL);
        if (PEAR::isError($info)) {
            return $this->raiseError($info);
        }

        $err = $warn = array();
        if (!$info->validate()) {
            foreach ($info->getValidationWarnings() as $error) {
                if ($error['level'] == 'warning') {
                    $warn[] = $error['message'];
                } else {
                    $err[] = $error['message'];
                }
            }
        }

        if (!$this->_displayValidationResults($err, $warn, true)) {
            $this->ui->outputData($this->output, $command);
            return $this->raiseError('SVN tag failed');
        }

        $version    = $info->getVersion();
        $package    = $info->getName();
        $svntag     = "$package-$version";

        if (isset($options['delete'])) {
            return $this->_svnRemoveTag($version, $package, $svntag, $packageFile, $options);
        }

        $path = $this->_svnFindPath($packageFile);

        // Check if there are any modified files
        $fp = popen('svn st --xml ' . dirname($packageFile), "r");
        $out = '';
        while ($line = fgets($fp, 1024)) {
            $out .= rtrim($line)."\n";
        }
        pclose($fp);

        if (!isset($options['quiet']) && strpos($out, 'item="modified"')) {
            $params = array(array(
                'name' => 'modified',
                'type' => 'yesno',
                'default' => 'no',
                'prompt' => 'You have files in your SVN checkout (' . $path['from']  . ') that have been modified but not committed, do you still want to tag ' . $version . '?',
            ));
            $answers = $this->ui->confirmDialog($params);

            if (!in_array($answers['modified'], array('y', 'yes', 'on', '1'))) {
                return true;
            }
        }

        if (isset($options['slide'])) {
            $this->_svnRemoveTag($version, $package, $svntag, $packageFile, $options);
        }

        // Check if tag already exists
        $releaseTag = $path['local']['base'] . 'tags' . DIRECTORY_SEPARATOR . $svntag;
        $existsCommand = 'svn ls ' . $path['base'] . 'tags/';

        $fp = popen($existsCommand, "r");
        $out = '';
        while ($line = fgets($fp, 1024)) {
            $out .= rtrim($line)."\n";
        }
        pclose($fp);

        if (in_array($svntag . DIRECTORY_SEPARATOR, explode("\n", $out))) {
            $this->ui->outputData($this->output, $command);
            return $this->raiseError('SVN tag ' . $svntag . ' for ' . $package . ' already exists.');
        } elseif (file_exists($path['local']['base'] . 'tags') === false) {
            return $this->raiseError('Can not locate the tags directory at ' . $path['local']['base'] . 'tags');
        } elseif (is_writeable($path['local']['base'] . 'tags') === false) {
            return $this->raiseError('Can not write to the tag directory at ' . $path['local']['base'] . 'tags');
        } else {
            $makeCommand = 'svn mkdir ' . $releaseTag;
            $this->output .= "+ $makeCommand\n";
            if (empty($options['dry-run'])) {
                // We need to create the tag dir.
                $fp = popen($makeCommand, "r");
                $out = '';
                while ($line = fgets($fp, 1024)) {
                    $out .= rtrim($line)."\n";
                }
                pclose($fp);
                $this->output .= "$out\n";
            }
        }

        $command = 'svn';
        if (isset($options['quiet'])) {
            $command .= ' -q';
        }

        $command .= ' copy --parents ';

        $dir   = dirname($packageFile);
        $dir   = substr($dir, strrpos($dir, DIRECTORY_SEPARATOR) + 1);
        $files = array_keys($info->getFilelist());
        if (!in_array(basename($packageFile), $files)) {
            $files[] = basename($packageFile);
        }

        array_shift($params);
        if (count($params)) {
            // add in additional files to be tagged (package files and such)
            $files = array_merge($files, $params);
        }

        $commands = array();
        foreach ($files as $file) {
            if (!file_exists($file)) {
                $file = $dir . DIRECTORY_SEPARATOR . $file;
            }
            $commands[] = $command . ' ' . escapeshellarg($file) . ' ' .
                          escapeshellarg($releaseTag . DIRECTORY_SEPARATOR . $file);
        }

        $this->output .= implode("\n", $commands) . "\n";
        if (empty($options['dry-run'])) {
            foreach ($commands as $command) {
                $fp = popen($command, "r");
                while ($line = fgets($fp, 1024)) {
                    $this->output .= rtrim($line)."\n";
                }
                pclose($fp);
            }
        }

        $command = 'svn ci -m "Tagging the ' . $version  . ' release" ' . $releaseTag . "\n";
        $this->output .= "+ $command\n";
        if (empty($options['dry-run'])) {
            $fp = popen($command, "r");
            while ($line = fgets($fp, 1024)) {
                $this->output .= rtrim($line)."\n";
            }
            pclose($fp);
        }

        $this->ui->outputData($this->output, $_cmd);
        return true;
    }

    function _svnFindPath($file)
    {
        $xml = '';
        $command = "svn info --xml $file";
        $fp = popen($command, "r");
        while ($line = fgets($fp, 1024)) {
            $xml .= rtrim($line)."\n";
        }
        pclose($fp);
        $url_tag = strpos($xml, '<url>');
        $url = substr($xml, $url_tag + 5, strpos($xml, '</url>', $url_tag + 5) - ($url_tag + 5));

        $path = array();
        $path['from'] = substr($url, 0, strrpos($url, '/'));
        $path['base'] = substr($path['from'], 0, strrpos($path['from'], '/') + 1);

        // Figure out the local paths - see http://pear.php.net/bugs/17463
        $pos = strpos($file, DIRECTORY_SEPARATOR . 'trunk' . DIRECTORY_SEPARATOR);
        if ($pos === false) {
            $pos = strpos($file, DIRECTORY_SEPARATOR . 'branches' . DIRECTORY_SEPARATOR);
        }
        $path['local']['base'] = substr($file, 0, $pos + 1);

        return $path;
    }

    function _svnRemoveTag($version, $package, $tag, $packageFile, $options)
    {
        $command = 'svn';

        if (isset($options['quiet'])) {
            $command .= ' -q';
        }

        $command .= ' remove';
        $command .= ' -m "Removing tag for the ' . $version  . ' release."';

        $path = $this->_svnFindPath($packageFile);
        $command .= ' ' . $path['base'] . 'tags/' . $tag;


        if ($this->config->get('verbose') > 1) {
            $this->output .= "+ $command\n";
        }

        $this->output .= "+ $command\n";
        if (empty($options['dry-run'])) {
            $fp = popen($command, "r");
            while ($line = fgets($fp, 1024)) {
                $this->output .= rtrim($line)."\n";
            }
            pclose($fp);
        }

        $this->ui->outputData($this->output, $command);
        return true;
    }

    function doCvsTag($command, $options, $params)
    {
        $this->output = '';
        $_cmd = $command;
        if (count($params) < 1) {
            $help = $this->getHelp($command);
            return $this->raiseError("$command: missing parameter: $help[0]");
        }

        $packageFile = realpath($params[0]);
        $obj  = &$this->getPackageFile($this->config, $this->_debug);
        $info = $obj->fromAnyFile($packageFile, PEAR_VALIDATE_NORMAL);
        if (PEAR::isError($info)) {
            return $this->raiseError($info);
        }

        $err = $warn = array();
        if (!$info->validate()) {
            foreach ($info->getValidationWarnings() as $error) {
                if ($error['level'] == 'warning') {
                    $warn[] = $error['message'];
                } else {
                    $err[] = $error['message'];
                }
            }
        }

        if (!$this->_displayValidationResults($err, $warn, true)) {
            $this->ui->outputData($this->output, $command);
            return $this->raiseError('CVS tag failed');
        }

        $version    = $info->getVersion();
        $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $version);
        $cvstag     = "RELEASE_$cvsversion";
        $files      = array_keys($info->getFilelist());
        $command = 'cvs';
        if (isset($options['quiet'])) {
            $command .= ' -q';
        }

        if (isset($options['reallyquiet'])) {
            $command .= ' -Q';
        }

        $command .= ' tag';
        if (isset($options['slide'])) {
            $command .= ' -F';
        }

        if (isset($options['delete'])) {
            $command .= ' -d';
        }

        $command .= ' ' . $cvstag . ' ' . escapeshellarg($params[0]);
        array_shift($params);
        if (count($params)) {
            // add in additional files to be tagged
            $files = array_merge($files, $params);
        }

        $dir = dirname($packageFile);
        $dir = substr($dir, strrpos($dir, '/') + 1);
        foreach ($files as $file) {
            if (!file_exists($file)) {
                $file = $dir . DIRECTORY_SEPARATOR . $file;
            }
            $command .= ' ' . escapeshellarg($file);
        }

        if ($this->config->get('verbose') > 1) {
            $this->output .= "+ $command\n";
        }

        $this->output .= "+ $command\n";
        if (empty($options['dry-run'])) {
            $fp = popen($command, "r");
            while ($line = fgets($fp, 1024)) {
                $this->output .= rtrim($line)."\n";
            }
            pclose($fp);
        }

        $this->ui->outputData($this->output, $_cmd);
        return true;
    }

    function doCvsDiff($command, $options, $params)
    {
        $this->output = '';
        if (sizeof($params) < 1) {
            $help = $this->getHelp($command);
            return $this->raiseError("$command: missing parameter: $help[0]");
        }

        $file = realpath($params[0]);
        $obj  = &$this->getPackageFile($this->config, $this->_debug);
        $info = $obj->fromAnyFile($file, PEAR_VALIDATE_NORMAL);
        if (PEAR::isError($info)) {
            return $this->raiseError($info);
        }

        $err = $warn = array();
        if (!$info->validate()) {
            foreach ($info->getValidationWarnings() as $error) {
                if ($error['level'] == 'warning') {
                    $warn[] = $error['message'];
                } else {
                    $err[] = $error['message'];
                }
            }
        }

        if (!$this->_displayValidationResults($err, $warn, true)) {
            $this->ui->outputData($this->output, $command);
            return $this->raiseError('CVS diff failed');
        }

        $info1 = $info->getFilelist();
        $files = $info1;
        $cmd = "cvs";
        if (isset($options['quiet'])) {
            $cmd .= ' -q';
            unset($options['quiet']);
        }

        if (isset($options['reallyquiet'])) {
            $cmd .= ' -Q';
            unset($options['reallyquiet']);
        }

        if (isset($options['release'])) {
            $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $options['release']);
            $cvstag = "RELEASE_$cvsversion";
            $options['revision'] = $cvstag;
            unset($options['release']);
        }

        $execute = true;
        if (isset($options['dry-run'])) {
            $execute = false;
            unset($options['dry-run']);
        }

        $cmd .= ' diff';
        // the rest of the options are passed right on to "cvs diff"
        foreach ($options as $option => $optarg) {
            $arg = $short = false;
            if (isset($this->commands[$command]['options'][$option])) {
                $arg = $this->commands[$command]['options'][$option]['arg'];
                $short = $this->commands[$command]['options'][$option]['shortopt'];
            }
            $cmd .= $short ? " -$short" : " --$option";
            if ($arg && $optarg) {
                $cmd .= ($short ? '' : '=') . escapeshellarg($optarg);
            }
        }

        foreach ($files as $file) {
            $cmd .= ' ' . escapeshellarg($file['name']);
        }

        if ($this->config->get('verbose') > 1) {
            $this->output .= "+ $cmd\n";
        }

        if ($execute) {
            $fp = popen($cmd, "r");
            while ($line = fgets($fp, 1024)) {
                $this->output .= rtrim($line)."\n";
            }
            pclose($fp);
        }

        $this->ui->outputData($this->output, $command);
        return true;
    }

    function doPackageDependencies($command, $options, $params)
    {
        // $params[0] -> the PEAR package to list its information
        if (count($params) !== 1) {
            return $this->raiseError("bad parameter(s), try \"help $command\"");
        }

        $obj = &$this->getPackageFile($this->config, $this->_debug);
        if (is_file($params[0]) || strpos($params[0], '.xml') > 0) {
           $info = $obj->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL);
        } else {
            $reg  = $this->config->getRegistry();
            $info = $obj->fromArray($reg->packageInfo($params[0]));
        }

        if (PEAR::isError($info)) {
            return $this->raiseError($info);
        }

        $deps = $info->getDeps();
        if (is_array($deps)) {
            if ($info->getPackagexmlVersion() == '1.0') {
                $data = array(
                    'caption' => 'Dependencies for pear/' . $info->getPackage(),
                    'border' => true,
                    'headline' => array("Required?", "Type", "Name", "Relation", "Version"),
                    );

                foreach ($deps as $d) {
                    if (isset($d['optional'])) {
                        if ($d['optional'] == 'yes') {
                            $req = 'No';
                        } else {
                            $req = 'Yes';
                        }
                    } else {
                        $req = 'Yes';
                    }

                    if (isset($this->_deps_rel_trans[$d['rel']])) {
                        $rel = $this->_deps_rel_trans[$d['rel']];
                    } else {
                        $rel = $d['rel'];
                    }

                    if (isset($this->_deps_type_trans[$d['type']])) {
                        $type = ucfirst($this->_deps_type_trans[$d['type']]);
                    } else {
                        $type = $d['type'];
                    }

                    if (isset($d['name'])) {
                        $name = $d['name'];
                    } else {
                        $name = '';
                    }

                    if (isset($d['version'])) {
                        $version = $d['version'];
                    } else {
                        $version = '';
                    }

                    $data['data'][] = array($req, $type, $name, $rel, $version);
                }
            } else { // package.xml 2.0 dependencies display
                require_once 'PEAR/Dependency2.php';
                $deps = $info->getDependencies();
                $reg = &$this->config->getRegistry();
                if (is_array($deps)) {
                    $data = array(
                        'caption' => 'Dependencies for ' . $info->getPackage(),
                        'border' => true,
                        'headline' => array("Required?", "Type", "Name", 'Versioning', 'Group'),
                        );
                    foreach ($deps as $type => $subd) {
                        $req = ($type == 'required') ? 'Yes' : 'No';
                        if ($type == 'group' && isset($subd['attribs']['name'])) {
                            $group = $subd['attribs']['name'];
                        } else {
                            $group = '';
                        }

                        if (!isset($subd[0])) {
                            $subd = array($subd);
                        }

                        foreach ($subd as $groupa) {
                            foreach ($groupa as $deptype => $depinfo) {
                                if ($deptype == 'attribs') {
                                    continue;
                                }

                                if ($deptype == 'pearinstaller') {
                                    $deptype = 'pear Installer';
                                }

                                if (!isset($depinfo[0])) {
                                    $depinfo = array($depinfo);
                                }

                                foreach ($depinfo as $inf) {
                                    $name = '';
                                    if (isset($inf['channel'])) {
                                        $alias = $reg->channelAlias($inf['channel']);
                                        if (!$alias) {
                                            $alias = '(channel?) ' .$inf['channel'];
                                        }
                                        $name = $alias . '/';

                                    }
                                    if (isset($inf['name'])) {
                                        $name .= $inf['name'];
                                    } elseif (isset($inf['pattern'])) {
                                        $name .= $inf['pattern'];
                                    } else {
                                        $name .= '';
                                    }

                                    if (isset($inf['uri'])) {
                                        $name .= ' [' . $inf['uri'] .  ']';
                                    }

                                    if (isset($inf['conflicts'])) {
                                        $ver = 'conflicts';
                                    } else {
                                        $ver = PEAR_Dependency2::_getExtraString($inf);
                                    }

                                    $data['data'][] = array($req, ucfirst($deptype), $name,
                                        $ver, $group);
                                }
                            }
                        }
                    }
                }
            }

            $this->ui->outputData($data, $command);
            return true;
        }

        // Fallback
        $this->ui->outputData("This package does not have any dependencies.", $command);
    }

    function doSign($command, $options, $params)
    {
        // should move most of this code into PEAR_Packager
        // so it'll be easy to implement "pear package --sign"
        if (count($params) !== 1) {
            return $this->raiseError("bad parameter(s), try \"help $command\"");
        }

        require_once 'System.php';
        require_once 'Archive/Tar.php';

        if (!file_exists($params[0])) {
            return $this->raiseError("file does not exist: $params[0]");
        }

        $obj = $this->getPackageFile($this->config, $this->_debug);
        $info = $obj->fromTgzFile($params[0], PEAR_VALIDATE_NORMAL);
        if (PEAR::isError($info)) {
            return $this->raiseError($info);
        }

        $tar = new Archive_Tar($params[0]);

        $tmpdir = $this->config->get('temp_dir');
        $tmpdir = System::mktemp(' -t "' . $tmpdir . '" -d pearsign');
        if (!$tar->extractList('package2.xml package.xml package.sig', $tmpdir)) {
            return $this->raiseError("failed to extract tar file");
        }

        if (file_exists("$tmpdir/package.sig")) {
            return $this->raiseError("package already signed");
        }

        $packagexml = 'package.xml';
        if (file_exists("$tmpdir/package2.xml")) {
            $packagexml = 'package2.xml';
        }

        if (file_exists("$tmpdir/package.sig")) {
            unlink("$tmpdir/package.sig");
        }

        if (!file_exists("$tmpdir/$packagexml")) {
            return $this->raiseError("Extracted file $tmpdir/$packagexml not found.");
        }

        $input = $this->ui->userDialog($command,
                                       array('GnuPG Passphrase'),
                                       array('password'));
        if (!isset($input[0])) {
            //use empty passphrase
            $input[0] = '';
        }

        $devnull = (isset($options['verbose'])) ? '' : ' 2>/dev/null';
        $gpg = popen("gpg --batch --passphrase-fd 0 --armor --detach-sign --output $tmpdir/package.sig $tmpdir/$packagexml" . $devnull, "w");
        if (!$gpg) {
            return $this->raiseError("gpg command failed");
        }

        fwrite($gpg, "$input[0]\n");
        if (pclose($gpg) || !file_exists("$tmpdir/package.sig")) {
            return $this->raiseError("gpg sign failed");
        }

        if (!$tar->addModify("$tmpdir/package.sig", '', $tmpdir)) {
            return $this->raiseError('failed adding signature to file');
        }

        $this->ui->outputData("Package signed.", $command);
        return true;
    }

    /**
     * For unit testing purposes
     */
    function &getInstaller(&$ui)
    {
        if (!class_exists('PEAR_Installer')) {
            require_once 'PEAR/Installer.php';
        }
        $a = new PEAR_Installer($ui);
        return $a;
    }

    /**
     * For unit testing purposes
     */
    function &getCommandPackaging(&$ui, &$config)
    {
        if (!class_exists('PEAR_Command_Packaging')) {
            if ($fp = @fopen('PEAR/Command/Packaging.php', 'r', true)) {
                fclose($fp);
                include_once 'PEAR/Command/Packaging.php';
            }
        }

        if (class_exists('PEAR_Command_Packaging')) {
            $a = new PEAR_Command_Packaging($ui, $config);
        } else {
            $a = null;
        }

        return $a;
    }

    function doMakeRPM($command, $options, $params)
    {

        // Check to see if PEAR_Command_Packaging is installed, and
        // transparently switch to use the "make-rpm-spec" command from it
        // instead, if it does. Otherwise, continue to use the old version
        // of "makerpm" supplied with this package (PEAR).
        $packaging_cmd = $this->getCommandPackaging($this->ui, $this->config);
        if ($packaging_cmd !== null) {
            $this->ui->outputData('PEAR_Command_Packaging is installed; using '.
                'newer "make-rpm-spec" command instead');
            return $packaging_cmd->run('make-rpm-spec', $options, $params);
        }

        $this->ui->outputData('WARNING: "pear makerpm" is no longer available; an '.
          'improved version is available via "pear make-rpm-spec", which '.
          'is available by installing PEAR_Command_Packaging');
        return true;
    }

    function doConvert($command, $options, $params)
    {
        $packagexml    = isset($params[0]) ? $params[0] : 'package.xml';
        $newpackagexml = isset($params[1]) ? $params[1] : dirname($packagexml) .
            DIRECTORY_SEPARATOR . 'package2.xml';
        $pkg = &$this->getPackageFile($this->config, $this->_debug);
        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        $pf = $pkg->fromPackageFile($packagexml, PEAR_VALIDATE_NORMAL);
        PEAR::staticPopErrorHandling();
        if (PEAR::isError($pf)) {
            if (is_array($pf->getUserInfo())) {
                foreach ($pf->getUserInfo() as $warning) {
                    $this->ui->outputData($warning['message']);
                }
            }
            return $this->raiseError($pf);
        }

        if (is_a($pf, 'PEAR_PackageFile_v2')) {
            $this->ui->outputData($packagexml . ' is already a package.xml version 2.0');
            return true;
        }

        $gen   = &$pf->getDefaultGenerator();
        $newpf = &$gen->toV2();
        $newpf->setPackagefile($newpackagexml);
        $gen = &$newpf->getDefaultGenerator();
        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        $state = (isset($options['flat']) ? PEAR_VALIDATE_PACKAGING : PEAR_VALIDATE_NORMAL);
        $saved = $gen->toPackageFile(dirname($newpackagexml), $state, basename($newpackagexml));
        PEAR::staticPopErrorHandling();
        if (PEAR::isError($saved)) {
            if (is_array($saved->getUserInfo())) {
                foreach ($saved->getUserInfo() as $warning) {
                    $this->ui->outputData($warning['message']);
                }
            }

            $this->ui->outputData($saved->getMessage());
            return true;
        }

        $this->ui->outputData('Wrote new version 2.0 package.xml to "' . $saved . '"');
        return true;
    }
}
PKo�Z
u���PEAR/Command/Build.xmlnu�[���<commands version="1.0">
 <build>
  <summary>Build an Extension From C Source</summary>
  <function>doBuild</function>
  <shortcut>b</shortcut>
  <options>
   <configureoptions>
    <shortopt>D</shortopt>
    <arg>OPTION1=VALUE[ OPTION2=VALUE]</arg>
   </configureoptions>
  </options>
  <doc>[package.xml]
Builds one or more extensions contained in a package.</doc>
 </build>
</commands>PKo�Z�����PEAR/Command/Mirror.phpnu�[���<?php
/**
 * PEAR_Command_Mirror (download-all command)
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Alexander Merz <alexmerz@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.2.0
 */

/**
 * base class
 */
require_once 'PEAR/Command/Common.php';

/**
 * PEAR commands for providing file mirrors
 *
 * @category   pear
 * @package    PEAR
 * @author     Alexander Merz <alexmerz@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.2.0
 */
class PEAR_Command_Mirror extends PEAR_Command_Common
{
    var $commands = array(
        'download-all' => array(
            'summary' => 'Downloads each available package from the default channel',
            'function' => 'doDownloadAll',
            'shortcut' => 'da',
            'options' => array(
                'channel' =>
                    array(
                    'shortopt' => 'c',
                    'doc' => 'specify a channel other than the default channel',
                    'arg' => 'CHAN',
                    ),
                ),
            'doc' => '
Requests a list of available packages from the default channel ({config default_channel})
and downloads them to current working directory.  Note: only
packages within preferred_state ({config preferred_state}) will be downloaded'
            ),
        );

    /**
     * PEAR_Command_Mirror constructor.
     *
     * @access public
     * @param object PEAR_Frontend a reference to an frontend
     * @param object PEAR_Config a reference to the configuration data
     */
    function __construct(&$ui, &$config)
    {
        parent::__construct($ui, $config);
    }

    /**
     * For unit-testing
     */
    function &factory($a)
    {
        $a = &PEAR_Command::factory($a, $this->config);
        return $a;
    }

    /**
    * retrieves a list of avaible Packages from master server
    * and downloads them
    *
    * @access public
    * @param string $command the command
    * @param array $options the command options before the command
    * @param array $params the stuff after the command name
    * @return bool true if successful
    * @throw PEAR_Error
    */
    function doDownloadAll($command, $options, $params)
    {
        $savechannel = $this->config->get('default_channel');
        $reg = &$this->config->getRegistry();
        $channel = isset($options['channel']) ? $options['channel'] :
            $this->config->get('default_channel');
        if (!$reg->channelExists($channel)) {
            $this->config->set('default_channel', $savechannel);
            return $this->raiseError('Channel "' . $channel . '" does not exist');
        }
        $this->config->set('default_channel', $channel);

        $this->ui->outputData('Using Channel ' . $this->config->get('default_channel'));
        $chan = $reg->getChannel($channel);
        if (PEAR::isError($chan)) {
            return $this->raiseError($chan);
        }

        if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
              $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
            $rest = &$this->config->getREST('1.0', array());
            $remoteInfo = array_flip($rest->listPackages($base, $channel));
        }

        if (PEAR::isError($remoteInfo)) {
            return $remoteInfo;
        }

        $cmd = &$this->factory("download");
        if (PEAR::isError($cmd)) {
            return $cmd;
        }

        $this->ui->outputData('Using Preferred State of ' .
            $this->config->get('preferred_state'));
        $this->ui->outputData('Gathering release information, please wait...');

        /**
         * Error handling not necessary, because already done by
         * the download command
         */
        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        $err = $cmd->run('download', array('downloadonly' => true), array_keys($remoteInfo));
        PEAR::staticPopErrorHandling();
        $this->config->set('default_channel', $savechannel);
        if (PEAR::isError($err)) {
            $this->ui->outputData($err->getMessage());
        }

        return true;
    }
}
PKp�Z,_�h/h/PEAR/Command/Test.phpnu�[���<?php
/**
 * PEAR_Command_Test (run-tests)
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Martin Jansen <mj@php.net>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 0.1
 */

/**
 * base class
 */
require_once 'PEAR/Command/Common.php';

/**
 * PEAR commands for login/logout
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Martin Jansen <mj@php.net>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 0.1
 */

class PEAR_Command_Test extends PEAR_Command_Common
{
    var $commands = array(
        'run-tests' => array(
            'summary' => 'Run Regression Tests',
            'function' => 'doRunTests',
            'shortcut' => 'rt',
            'options' => array(
                'recur' => array(
                    'shortopt' => 'r',
                    'doc' => 'Run tests in child directories, recursively.  4 dirs deep maximum',
                ),
                'ini' => array(
                    'shortopt' => 'i',
                    'doc' => 'actual string of settings to pass to php in format " -d setting=blah"',
                    'arg' => 'SETTINGS'
                ),
                'realtimelog' => array(
                    'shortopt' => 'l',
                    'doc' => 'Log test runs/results as they are run',
                ),
                'quiet' => array(
                    'shortopt' => 'q',
                    'doc' => 'Only display detail for failed tests',
                ),
                'simple' => array(
                    'shortopt' => 's',
                    'doc' => 'Display simple output for all tests',
                ),
                'package' => array(
                    'shortopt' => 'p',
                    'doc' => 'Treat parameters as installed packages from which to run tests',
                ),
                'phpunit' => array(
                    'shortopt' => 'u',
                    'doc' => 'Search parameters for AllTests.php, and use that to run phpunit-based tests
If none is found, all .phpt tests will be tried instead.',
                ),
                'tapoutput' => array(
                    'shortopt' => 't',
                    'doc' => 'Output run-tests.log in TAP-compliant format',
                ),
                'cgi' => array(
                    'shortopt' => 'c',
                    'doc' => 'CGI php executable (needed for tests with POST/GET section)',
                    'arg' => 'PHPCGI',
                ),
                'coverage' => array(
                    'shortopt' => 'x',
                    'doc'      => 'Generate a code coverage report (requires Xdebug 2.0.0+)',
                ),
                'showdiff' => array(
                    'shortopt' => 'd',
                    'doc' => 'Output diff on test failure',
                ),
            ),
            'doc' => '[testfile|dir ...]
Run regression tests with PHP\'s regression testing script (run-tests.php).',
            ),
        );

    var $output;

    /**
     * PEAR_Command_Test constructor.
     *
     * @access public
     */
    function __construct(&$ui, &$config)
    {
        parent::__construct($ui, $config);
    }

    function doRunTests($command, $options, $params)
    {
        if (isset($options['phpunit']) && isset($options['tapoutput'])) {
            return $this->raiseError('ERROR: cannot use both --phpunit and --tapoutput at the same time');
        }

        require_once 'PEAR/Common.php';
        require_once 'System.php';
        $log = new PEAR_Common;
        $log->ui = &$this->ui; // slightly hacky, but it will work
        $tests = array();
        $depth = isset($options['recur']) ? 14 : 1;

        if (!count($params)) {
            $params[] = '.';
        }

        if (isset($options['package'])) {
            $oldparams = $params;
            $params = array();
            $reg = &$this->config->getRegistry();
            foreach ($oldparams as $param) {
                $pname = $reg->parsePackageName($param, $this->config->get('default_channel'));
                if (PEAR::isError($pname)) {
                    return $this->raiseError($pname);
                }

                $package = &$reg->getPackage($pname['package'], $pname['channel']);
                if (!$package) {
                    return PEAR::raiseError('Unknown package "' .
                        $reg->parsedPackageNameToString($pname) . '"');
                }

                $filelist = $package->getFilelist();
                foreach ($filelist as $name => $atts) {
                    if (isset($atts['role']) && $atts['role'] != 'test') {
                        continue;
                    }

                    if (isset($options['phpunit']) && preg_match('/AllTests\.php\\z/i', $name)) {
                        $params[] = $atts['installed_as'];
                        continue;
                    } elseif (!preg_match('/\.phpt\\z/', $name)) {
                        continue;
                    }
                    $params[] = $atts['installed_as'];
                }
            }
        }

        foreach ($params as $p) {
            if (is_dir($p)) {
                if (isset($options['phpunit'])) {
                    $dir = System::find(array($p, '-type', 'f',
                                                '-maxdepth', $depth,
                                                '-name', 'AllTests.php'));
                    if (count($dir)) {
                        foreach ($dir as $p) {
                            $p = realpath($p);
                            if (!count($tests) ||
                                  (count($tests) && strlen($p) < strlen($tests[0]))) {
                                // this is in a higher-level directory, use this one instead.
                                $tests = array($p);
                            }
                        }
                    }
                    continue;
                }

                $args  = array($p, '-type', 'f', '-name', '*.phpt');
            } else {
                if (isset($options['phpunit'])) {
                    if (preg_match('/AllTests\.php\\z/i', $p)) {
                        $p = realpath($p);
                        if (!count($tests) ||
                              (count($tests) && strlen($p) < strlen($tests[0]))) {
                            // this is in a higher-level directory, use this one instead.
                            $tests = array($p);
                        }
                    }
                    continue;
                }

                if (file_exists($p) && preg_match('/\.phpt$/', $p)) {
                    $tests[] = $p;
                    continue;
                }

                if (!preg_match('/\.phpt\\z/', $p)) {
                    $p .= '.phpt';
                }

                $args  = array(dirname($p), '-type', 'f', '-name', $p);
            }

            if (!isset($options['recur'])) {
                $args[] = '-maxdepth';
                $args[] = 1;
            }

            $dir   = System::find($args);
            $tests = array_merge($tests, $dir);
        }

        $ini_settings = '';
        if (isset($options['ini'])) {
            $ini_settings .= $options['ini'];
        }

        if (isset($_ENV['TEST_PHP_INCLUDE_PATH'])) {
            $ini_settings .= " -d include_path={$_ENV['TEST_PHP_INCLUDE_PATH']}";
        }

        if ($ini_settings) {
            $this->ui->outputData('Using INI settings: "' . $ini_settings . '"');
        }

        $skipped = $passed = $failed = array();
        $tests_count = count($tests);
        $this->ui->outputData('Running ' . $tests_count . ' tests', $command);
        $start = time();
        if (isset($options['realtimelog']) && file_exists('run-tests.log')) {
            unlink('run-tests.log');
        }

        if (isset($options['tapoutput'])) {
            $tap = '1..' . $tests_count . "\n";
        }

        require_once 'PEAR/RunTest.php';
        $run = new PEAR_RunTest($log, $options);
        $run->tests_count = $tests_count;

        if (isset($options['coverage']) && extension_loaded('xdebug')){
            $run->xdebug_loaded = true;
        } else {
            $run->xdebug_loaded = false;
        }

        $j = $i = 1;
        foreach ($tests as $t) {
            if (isset($options['realtimelog'])) {
                $fp = @fopen('run-tests.log', 'a');
                if ($fp) {
                    fwrite($fp, "Running test [$i / $tests_count] $t...");
                    fclose($fp);
                }
            }
            PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
            if (isset($options['phpunit'])) {
                $result = $run->runPHPUnit($t, $ini_settings);
            } else {
                $result = $run->run($t, $ini_settings, $j);
            }
            PEAR::staticPopErrorHandling();
            if (PEAR::isError($result)) {
                $this->ui->log($result->getMessage());
                continue;
            }

            if (isset($options['tapoutput'])) {
                $tap .= $result[0] . ' ' . $i . $result[1] . "\n";
                continue;
            }

            if (isset($options['realtimelog'])) {
                $fp = @fopen('run-tests.log', 'a');
                if ($fp) {
                    fwrite($fp, "$result\n");
                    fclose($fp);
                }
            }

            if ($result == 'FAILED') {
                $failed[] = $t;
            }
            if ($result == 'PASSED') {
                $passed[] = $t;
            }
            if ($result == 'SKIPPED') {
                $skipped[] = $t;
            }

            $j++;
        }

        $total = date('i:s', time() - $start);
        if (isset($options['tapoutput'])) {
            $fp = @fopen('run-tests.log', 'w');
            if ($fp) {
                fwrite($fp, $tap, strlen($tap));
                fclose($fp);
                $this->ui->outputData('wrote TAP-format log to "' .realpath('run-tests.log') .
                    '"', $command);
            }
        } else {
            if (count($failed)) {
                $output = "TOTAL TIME: $total\n";
                $output .= count($passed) . " PASSED TESTS\n";
                $output .= count($skipped) . " SKIPPED TESTS\n";
                $output .= count($failed) . " FAILED TESTS:\n";
                foreach ($failed as $failure) {
                    $output .= $failure . "\n";
                }

                $mode = isset($options['realtimelog']) ? 'a' : 'w';
                $fp   = @fopen('run-tests.log', $mode);

                if ($fp) {
                    fwrite($fp, $output, strlen($output));
                    fclose($fp);
                    $this->ui->outputData('wrote log to "' . realpath('run-tests.log') . '"', $command);
                }
            } elseif (file_exists('run-tests.log') && !is_dir('run-tests.log')) {
                @unlink('run-tests.log');
            }
        }
        $this->ui->outputData('TOTAL TIME: ' . $total);
        $this->ui->outputData(count($passed) . ' PASSED TESTS', $command);
        $this->ui->outputData(count($skipped) . ' SKIPPED TESTS', $command);
        if (count($failed)) {
            $this->ui->outputData(count($failed) . ' FAILED TESTS:', $command);
            foreach ($failed as $failure) {
                $this->ui->outputData($failure, $command);
            }
        }

        if (count($failed) == 0) {
            return true;
        }
        return $this->raiseError('Some tests failed');
    }
}
PKp�Z�%sp  PEAR/Command/Common.phpnu�[���<?php
/**
 * PEAR_Command_Common base class
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 0.1
 */

/**
 * base class
 */
require_once 'PEAR.php';

/**
 * PEAR commands base class
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 0.1
 */
class PEAR_Command_Common extends PEAR
{
    /**
     * PEAR_Config object used to pass user system and configuration
     * on when executing commands
     *
     * @var PEAR_Config
     */
    var $config;
    /**
     * @var PEAR_Registry
     * @access protected
     */
    var $_registry;

    /**
     * User Interface object, for all interaction with the user.
     * @var object
     */
    var $ui;

    var $_deps_rel_trans = array(
                                 'lt' => '<',
                                 'le' => '<=',
                                 'eq' => '=',
                                 'ne' => '!=',
                                 'gt' => '>',
                                 'ge' => '>=',
                                 'has' => '=='
                                 );

    var $_deps_type_trans = array(
                                  'pkg' => 'package',
                                  'ext' => 'extension',
                                  'php' => 'PHP',
                                  'prog' => 'external program',
                                  'ldlib' => 'external library for linking',
                                  'rtlib' => 'external runtime library',
                                  'os' => 'operating system',
                                  'websrv' => 'web server',
                                  'sapi' => 'SAPI backend'
                                  );

    /**
     * PEAR_Command_Common constructor.
     *
     * @access public
     */
    function __construct(&$ui, &$config)
    {
        parent::__construct();
        $this->config = &$config;
        $this->ui = &$ui;
    }

    /**
     * Return a list of all the commands defined by this class.
     * @return array list of commands
     * @access public
     */
    function getCommands()
    {
        $ret = array();
        foreach (array_keys($this->commands) as $command) {
            $ret[$command] = $this->commands[$command]['summary'];
        }

        return $ret;
    }

    /**
     * Return a list of all the command shortcuts defined by this class.
     * @return array shortcut => command
     * @access public
     */
    function getShortcuts()
    {
        $ret = array();
        foreach (array_keys($this->commands) as $command) {
            if (isset($this->commands[$command]['shortcut'])) {
                $ret[$this->commands[$command]['shortcut']] = $command;
            }
        }

        return $ret;
    }

    function getOptions($command)
    {
        $shortcuts = $this->getShortcuts();
        if (isset($shortcuts[$command])) {
            $command = $shortcuts[$command];
        }

        if (isset($this->commands[$command]) &&
              isset($this->commands[$command]['options'])) {
            return $this->commands[$command]['options'];
        }

        return null;
    }

    function getGetoptArgs($command, &$short_args, &$long_args)
    {
        $short_args = '';
        $long_args = array();
        if (empty($this->commands[$command]) || empty($this->commands[$command]['options'])) {
            return;
        }

        reset($this->commands[$command]['options']);
        foreach ($this->commands[$command]['options'] as $option => $info) {
            $larg = $sarg = '';
            if (isset($info['arg'])) {
                if ($info['arg'][0] == '(') {
                    $larg = '==';
                    $sarg = '::';
                    $arg = substr($info['arg'], 1, -1);
                } else {
                    $larg = '=';
                    $sarg = ':';
                    $arg = $info['arg'];
                }
            }

            if (isset($info['shortopt'])) {
                $short_args .= $info['shortopt'] . $sarg;
            }

            $long_args[] = $option . $larg;
        }
    }

    /**
    * Returns the help message for the given command
    *
    * @param string $command The command
    * @return mixed A fail string if the command does not have help or
    *               a two elements array containing [0]=>help string,
    *               [1]=> help string for the accepted cmd args
    */
    function getHelp($command)
    {
        $config = &PEAR_Config::singleton();
        if (!isset($this->commands[$command])) {
            return "No such command \"$command\"";
        }

        $help = null;
        if (isset($this->commands[$command]['doc'])) {
            $help = $this->commands[$command]['doc'];
        }

        if (empty($help)) {
            // XXX (cox) Fallback to summary if there is no doc (show both?)
            if (!isset($this->commands[$command]['summary'])) {
                return "No help for command \"$command\"";
            }
            $help = $this->commands[$command]['summary'];
        }

        if (preg_match_all('/{config\s+([^\}]+)}/', $help, $matches)) {
            foreach($matches[0] as $k => $v) {
                $help = preg_replace("/$v/", $config->get($matches[1][$k]), $help);
            }
        }

        return array($help, $this->getHelpArgs($command));
    }

    /**
     * Returns the help for the accepted arguments of a command
     *
     * @param  string $command
     * @return string The help string
     */
    function getHelpArgs($command)
    {
        if (isset($this->commands[$command]['options']) &&
            count($this->commands[$command]['options']))
        {
            $help = "Options:\n";
            foreach ($this->commands[$command]['options'] as $k => $v) {
                if (isset($v['arg'])) {
                    if ($v['arg'][0] == '(') {
                        $arg = substr($v['arg'], 1, -1);
                        $sapp = " [$arg]";
                        $lapp = "[=$arg]";
                    } else {
                        $sapp = " $v[arg]";
                        $lapp = "=$v[arg]";
                    }
                } else {
                    $sapp = $lapp = "";
                }

                if (isset($v['shortopt'])) {
                    $s = $v['shortopt'];
                    $help .= "  -$s$sapp, --$k$lapp\n";
                } else {
                    $help .= "  --$k$lapp\n";
                }

                $p = "        ";
                $doc = rtrim(str_replace("\n", "\n$p", $v['doc']));
                $help .= "        $doc\n";
            }

            return $help;
        }

        return null;
    }

    function run($command, $options, $params)
    {
        if (empty($this->commands[$command]['function'])) {
            // look for shortcuts
            foreach (array_keys($this->commands) as $cmd) {
                if (isset($this->commands[$cmd]['shortcut']) && $this->commands[$cmd]['shortcut'] == $command) {
                    if (empty($this->commands[$cmd]['function'])) {
                        return $this->raiseError("unknown command `$command'");
                    } else {
                        $func = $this->commands[$cmd]['function'];
                    }
                    $command = $cmd;

                    //$command = $this->commands[$cmd]['function'];
                    break;
                }
            }
        } else {
            $func = $this->commands[$command]['function'];
        }

        return $this->$func($command, $options, $params);
    }
}
PKp�Z0(;rʹʹPEAR/Command/Registry.phpnu�[���<?php
/**
 * PEAR_Command_Registry (list, list-files, shell-test, info commands)
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 0.1
 */

/**
 * base class
 */
require_once 'PEAR/Command/Common.php';

/**
 * PEAR commands for registry manipulation
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 0.1
 */
class PEAR_Command_Registry extends PEAR_Command_Common
{
    var $commands = array(
        'list' => array(
            'summary' => 'List Installed Packages In The Default Channel',
            'function' => 'doList',
            'shortcut' => 'l',
            'options' => array(
                'channel' => array(
                    'shortopt' => 'c',
                    'doc' => 'list installed packages from this channel',
                    'arg' => 'CHAN',
                    ),
                'allchannels' => array(
                    'shortopt' => 'a',
                    'doc' => 'list installed packages from all channels',
                    ),
                'channelinfo' => array(
                    'shortopt' => 'i',
                    'doc' => 'output fully channel-aware data, even on failure',
                    ),
                ),
            'doc' => '<package>
If invoked without parameters, this command lists the PEAR packages
installed in your php_dir ({config php_dir}).  With a parameter, it
lists the files in a package.
',
            ),
        'list-files' => array(
            'summary' => 'List Files In Installed Package',
            'function' => 'doFileList',
            'shortcut' => 'fl',
            'options' => array(),
            'doc' => '<package>
List the files in an installed package.
'
            ),
        'shell-test' => array(
            'summary' => 'Shell Script Test',
            'function' => 'doShellTest',
            'shortcut' => 'st',
            'options' => array(),
            'doc' => '<package> [[relation] version]
Tests if a package is installed in the system. Will exit(1) if it is not.
   <relation>   The version comparison operator. One of:
                <, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne
   <version>    The version to compare with
'),
        'info' => array(
            'summary'  => 'Display information about a package',
            'function' => 'doInfo',
            'shortcut' => 'in',
            'options'  => array(),
            'doc'      => '<package>
Displays information about a package. The package argument may be a
local package file, an URL to a package file, or the name of an
installed package.'
            )
        );

    /**
     * PEAR_Command_Registry constructor.
     *
     * @access public
     */
    function __construct(&$ui, &$config)
    {
        parent::__construct($ui, $config);
    }

    function _sortinfo($a, $b)
    {
        $apackage = isset($a['package']) ? $a['package'] : $a['name'];
        $bpackage = isset($b['package']) ? $b['package'] : $b['name'];
        return strcmp($apackage, $bpackage);
    }

    function doList($command, $options, $params)
    {
        $reg = &$this->config->getRegistry();
        $channelinfo = isset($options['channelinfo']);
        if (isset($options['allchannels']) && !$channelinfo) {
            return $this->doListAll($command, array(), $params);
        }

        if (isset($options['allchannels']) && $channelinfo) {
            // allchannels with $channelinfo
            unset($options['allchannels']);
            $channels = $reg->getChannels();
            $errors = array();
            PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
            foreach ($channels as $channel) {
                $options['channel'] = $channel->getName();
                $ret = $this->doList($command, $options, $params);

                if (PEAR::isError($ret)) {
                    $errors[] = $ret;
                }
            }

            PEAR::staticPopErrorHandling();
            if (count($errors)) {
                // for now, only give first error
                return PEAR::raiseError($errors[0]);
            }

            return true;
        }

        if (count($params) === 1) {
            return $this->doFileList($command, $options, $params);
        }

        if (isset($options['channel'])) {
            if (!$reg->channelExists($options['channel'])) {
                return $this->raiseError('Channel "' . $options['channel'] .'" does not exist');
            }

            $channel = $reg->channelName($options['channel']);
        } else {
            $channel = $this->config->get('default_channel');
        }

        $installed = $reg->packageInfo(null, null, $channel);
        usort($installed, array(&$this, '_sortinfo'));

        $data = array(
            'caption' => 'Installed packages, channel ' .
                $channel . ':',
            'border' => true,
            'headline' => array('Package', 'Version', 'State'),
            'channel' => $channel,
            );
        if ($channelinfo) {
            $data['headline'] = array('Channel', 'Package', 'Version', 'State');
        }

        if (count($installed) && !isset($data['data'])) {
            $data['data'] = array();
        }

        foreach ($installed as $package) {
            $pobj = $reg->getPackage(isset($package['package']) ?
                                        $package['package'] : $package['name'], $channel);
            if ($channelinfo) {
                $packageinfo = array($pobj->getChannel(), $pobj->getPackage(), $pobj->getVersion(),
                                    $pobj->getState() ? $pobj->getState() : null);
            } else {
                $packageinfo = array($pobj->getPackage(), $pobj->getVersion(),
                                    $pobj->getState() ? $pobj->getState() : null);
            }
            $data['data'][] = $packageinfo;
        }

        if (count($installed) === 0) {
            if (!$channelinfo) {
                $data = '(no packages installed from channel ' . $channel . ')';
            } else {
                $data = array(
                    'caption' => 'Installed packages, channel ' .
                        $channel . ':',
                    'border' => true,
                    'channel' => $channel,
                    'data' => array(array('(no packages installed)')),
                );
            }
        }

        $this->ui->outputData($data, $command);
        return true;
    }

    function doListAll($command, $options, $params)
    {
        // This duplicate code is deprecated over
        // list --channelinfo, which gives identical
        // output for list and list --allchannels.
        $reg = &$this->config->getRegistry();
        $installed = $reg->packageInfo(null, null, null);
        foreach ($installed as $channel => $packages) {
            usort($packages, array($this, '_sortinfo'));
            $data = array(
                'caption'  => 'Installed packages, channel ' . $channel . ':',
                'border'   => true,
                'headline' => array('Package', 'Version', 'State'),
                'channel'  => $channel
            );

            foreach ($packages as $package) {
                $p = isset($package['package']) ? $package['package'] : $package['name'];
                $pobj = $reg->getPackage($p, $channel);
                $data['data'][] = array($pobj->getPackage(), $pobj->getVersion(),
                                        $pobj->getState() ? $pobj->getState() : null);
            }

            // Adds a blank line after each section
            $data['data'][] = array();

            if (count($packages) === 0) {
                $data = array(
                    'caption' => 'Installed packages, channel ' . $channel . ':',
                    'border' => true,
                    'data' => array(array('(no packages installed)'), array()),
                    'channel' => $channel
                    );
            }
            $this->ui->outputData($data, $command);
        }
        return true;
    }

    function doFileList($command, $options, $params)
    {
        if (count($params) !== 1) {
            return $this->raiseError('list-files expects 1 parameter');
        }

        $reg = &$this->config->getRegistry();
        $fp = false;
        if (!is_dir($params[0]) && (file_exists($params[0]) || $fp = @fopen($params[0], 'r'))) {
            if ($fp) {
                fclose($fp);
            }

            if (!class_exists('PEAR_PackageFile')) {
                require_once 'PEAR/PackageFile.php';
            }

            $pkg = new PEAR_PackageFile($this->config, $this->_debug);
            PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
            $info = &$pkg->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL);
            PEAR::staticPopErrorHandling();
            $headings = array('Package File', 'Install Path');
            $installed = false;
        } else {
            PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
            $parsed = $reg->parsePackageName($params[0], $this->config->get('default_channel'));
            PEAR::staticPopErrorHandling();
            if (PEAR::isError($parsed)) {
                return $this->raiseError($parsed);
            }

            $info = &$reg->getPackage($parsed['package'], $parsed['channel']);
            $headings = array('Type', 'Install Path');
            $installed = true;
        }

        if (PEAR::isError($info)) {
            return $this->raiseError($info);
        }

        if ($info === null) {
            return $this->raiseError("`$params[0]' not installed");
        }

        $list = ($info->getPackagexmlVersion() == '1.0' || $installed) ?
            $info->getFilelist() : $info->getContents();
        if ($installed) {
            $caption = 'Installed Files For ' . $params[0];
        } else {
            $caption = 'Contents of ' . basename($params[0]);
        }

        $data = array(
            'caption' => $caption,
            'border' => true,
            'headline' => $headings);
        if ($info->getPackagexmlVersion() == '1.0' || $installed) {
            foreach ($list as $file => $att) {
                if ($installed) {
                    if (empty($att['installed_as'])) {
                        continue;
                    }
                    $data['data'][] = array($att['role'], $att['installed_as']);
                } else {
                    if (isset($att['baseinstalldir']) && !in_array($att['role'],
                          array('test', 'data', 'doc'))) {
                        $dest = $att['baseinstalldir'] . DIRECTORY_SEPARATOR .
                            $file;
                    } else {
                        $dest = $file;
                    }
                    switch ($att['role']) {
                        case 'test':
                        case 'data':
                        case 'doc':
                            $role = $att['role'];
                            if ($role == 'test') {
                                $role .= 's';
                            }
                            $dest = $this->config->get($role . '_dir') . DIRECTORY_SEPARATOR .
                                $info->getPackage() . DIRECTORY_SEPARATOR . $dest;
                            break;
                        case 'php':
                        default:
                            $dest = $this->config->get('php_dir') . DIRECTORY_SEPARATOR .
                                $dest;
                    }
                    $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
                    $dest = preg_replace(array('!\\\\+!', '!/!', "!$ds2+!"),
                                                    array(DIRECTORY_SEPARATOR,
                                                          DIRECTORY_SEPARATOR,
                                                          DIRECTORY_SEPARATOR),
                                                    $dest);
                    $file = preg_replace('!/+!', '/', $file);
                    $data['data'][] = array($file, $dest);
                }
            }
        } else { // package.xml 2.0, not installed
            if (!isset($list['dir']['file'][0])) {
                $list['dir']['file'] = array($list['dir']['file']);
            }

            foreach ($list['dir']['file'] as $att) {
                $att = $att['attribs'];
                $file = $att['name'];
                $role = &PEAR_Installer_Role::factory($info, $att['role'], $this->config);
                $role->setup($this, $info, $att, $file);
                if (!$role->isInstallable()) {
                    $dest = '(not installable)';
                } else {
                    $dest = $role->processInstallation($info, $att, $file, '');
                    if (PEAR::isError($dest)) {
                        $dest = '(Unknown role "' . $att['role'] . ')';
                    } else {
                        list(,, $dest) = $dest;
                    }
                }
                $data['data'][] = array($file, $dest);
            }
        }

        $this->ui->outputData($data, $command);
        return true;
    }

    function doShellTest($command, $options, $params)
    {
        if (count($params) < 1) {
            return PEAR::raiseError('ERROR, usage: pear shell-test packagename [[relation] version]');
        }

        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        $reg = &$this->config->getRegistry();
        $info = $reg->parsePackageName($params[0], $this->config->get('default_channel'));
        if (PEAR::isError($info)) {
            exit(1); // invalid package name
        }

        $package = $info['package'];
        $channel = $info['channel'];
        // "pear shell-test Foo"
        if (!$reg->packageExists($package, $channel)) {
            if ($channel == 'pecl.php.net') {
                if ($reg->packageExists($package, 'pear.php.net')) {
                    $channel = 'pear.php.net'; // magically change channels for extensions
                }
            }
        }

        if (count($params) === 1) {
            if (!$reg->packageExists($package, $channel)) {
                exit(1);
            }
            // "pear shell-test Foo 1.0"
        } elseif (count($params) === 2) {
            $v = $reg->packageInfo($package, 'version', $channel);
            if (!$v || !version_compare("$v", "{$params[1]}", "ge")) {
                exit(1);
            }
            // "pear shell-test Foo ge 1.0"
        } elseif (count($params) === 3) {
            $v = $reg->packageInfo($package, 'version', $channel);
            if (!$v || !version_compare("$v", "{$params[2]}", $params[1])) {
                exit(1);
            }
        } else {
            PEAR::staticPopErrorHandling();
            $this->raiseError("$command: expects 1 to 3 parameters");
            exit(1);
        }
    }

    function doInfo($command, $options, $params)
    {
        if (count($params) !== 1) {
            return $this->raiseError('pear info expects 1 parameter');
        }

        $info = $fp = false;
        $reg = &$this->config->getRegistry();
        if (is_file($params[0]) && !is_dir($params[0]) &&
            (file_exists($params[0]) || $fp = @fopen($params[0], 'r'))
        ) {
            if ($fp) {
                fclose($fp);
            }

            if (!class_exists('PEAR_PackageFile')) {
                require_once 'PEAR/PackageFile.php';
            }

            $pkg = new PEAR_PackageFile($this->config, $this->_debug);
            PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
            $obj = &$pkg->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL);
            PEAR::staticPopErrorHandling();
            if (PEAR::isError($obj)) {
                $uinfo = $obj->getUserInfo();
                if (is_array($uinfo)) {
                    foreach ($uinfo as $message) {
                        if (is_array($message)) {
                            $message = $message['message'];
                        }
                        $this->ui->outputData($message);
                    }
                }

                return $this->raiseError($obj);
            }

            if ($obj->getPackagexmlVersion() != '1.0') {
                return $this->_doInfo2($command, $options, $params, $obj, false);
            }

            $info = $obj->toArray();
        } else {
            $parsed = $reg->parsePackageName($params[0], $this->config->get('default_channel'));
            if (PEAR::isError($parsed)) {
                return $this->raiseError($parsed);
            }

            $package = $parsed['package'];
            $channel = $parsed['channel'];
            $info = $reg->packageInfo($package, null, $channel);
            if (isset($info['old'])) {
                $obj = $reg->getPackage($package, $channel);
                return $this->_doInfo2($command, $options, $params, $obj, true);
            }
        }

        if (PEAR::isError($info)) {
            return $info;
        }

        if (empty($info)) {
            $this->raiseError("No information found for `$params[0]'");
            return;
        }

        unset($info['filelist']);
        unset($info['dirtree']);
        unset($info['changelog']);
        if (isset($info['xsdversion'])) {
            $info['package.xml version'] = $info['xsdversion'];
            unset($info['xsdversion']);
        }

        if (isset($info['packagerversion'])) {
            $info['packaged with PEAR version'] = $info['packagerversion'];
            unset($info['packagerversion']);
        }

        $keys = array_keys($info);
        $longtext = array('description', 'summary');
        foreach ($keys as $key) {
            if (is_array($info[$key])) {
                switch ($key) {
                    case 'maintainers': {
                        $i = 0;
                        $mstr = '';
                        foreach ($info[$key] as $m) {
                            if ($i++ > 0) {
                                $mstr .= "\n";
                            }
                            $mstr .= $m['name'] . " <";
                            if (isset($m['email'])) {
                                $mstr .= $m['email'];
                            } else {
                                $mstr .= $m['handle'] . '@php.net';
                            }
                            $mstr .= "> ($m[role])";
                        }
                        $info[$key] = $mstr;
                        break;
                    }
                    case 'release_deps': {
                        $i = 0;
                        $dstr = '';
                        foreach ($info[$key] as $d) {
                            if (isset($this->_deps_rel_trans[$d['rel']])) {
                                $rel = $this->_deps_rel_trans[$d['rel']];
                            } else {
                                $rel = $d['rel'];
                            }
                            if (isset($this->_deps_type_trans[$d['type']])) {
                                $type = ucfirst($this->_deps_type_trans[$d['type']]);
                            } else {
                                $type = $d['type'];
                            }
                            if (isset($d['name'])) {
                                $name = $d['name'] . ' ';
                            } else {
                                $name = '';
                            }
                            if (isset($d['version'])) {
                                $version = $d['version'] . ' ';
                            } else {
                                $version = '';
                            }
                            if (isset($d['optional']) && $d['optional'] == 'yes') {
                                $optional = ' (optional)';
                            } else {
                                $optional = '';
                            }
                            $dstr .= "$type $name$rel $version$optional\n";
                        }
                        $info[$key] = $dstr;
                        break;
                    }
                    case 'provides' : {
                        $debug = $this->config->get('verbose');
                        if ($debug < 2) {
                            $pstr = 'Classes: ';
                        } else {
                            $pstr = '';
                        }
                        $i = 0;
                        foreach ($info[$key] as $p) {
                            if ($debug < 2 && $p['type'] != "class") {
                                continue;
                            }
                            // Only print classes when verbosity mode is < 2
                            if ($debug < 2) {
                                if ($i++ > 0) {
                                    $pstr .= ", ";
                                }
                                $pstr .= $p['name'];
                            } else {
                                if ($i++ > 0) {
                                    $pstr .= "\n";
                                }
                                $pstr .= ucfirst($p['type']) . " " . $p['name'];
                                if (isset($p['explicit']) && $p['explicit'] == 1) {
                                    $pstr .= " (explicit)";
                                }
                            }
                        }
                        $info[$key] = $pstr;
                        break;
                    }
                    case 'configure_options' : {
                        foreach ($info[$key] as $i => $p) {
                            $info[$key][$i] = array_map(null, array_keys($p), array_values($p));
                            $info[$key][$i] = array_map(
                                function($a) { return join(" = ", $a); },
                                $info[$key][$i]);
                            $info[$key][$i] = implode(', ', $info[$key][$i]);
                        }
                        $info[$key] = implode("\n", $info[$key]);
                        break;
                    }
                    default: {
                        $info[$key] = implode(", ", $info[$key]);
                        break;
                    }
                }
            }

            if ($key == '_lastmodified') {
                $hdate = date('Y-m-d', $info[$key]);
                unset($info[$key]);
                $info['Last Modified'] = $hdate;
            } elseif ($key == '_lastversion') {
                $info['Previous Installed Version'] = $info[$key] ? $info[$key] : '- None -';
                unset($info[$key]);
            } else {
                $info[$key] = trim($info[$key]);
                if (in_array($key, $longtext)) {
                    $info[$key] = preg_replace('/  +/', ' ', $info[$key]);
                }
            }
        }

        $caption = 'About ' . $info['package'] . '-' . $info['version'];
        $data = array(
            'caption' => $caption,
            'border' => true);
        foreach ($info as $key => $value) {
            $key = ucwords(trim(str_replace('_', ' ', $key)));
            $data['data'][] = array($key, $value);
        }
        $data['raw'] = $info;

        $this->ui->outputData($data, 'package-info');
    }

    /**
     * @access private
     */
    function _doInfo2($command, $options, $params, &$obj, $installed)
    {
        $reg = &$this->config->getRegistry();
        $caption = 'About ' . $obj->getChannel() . '/' .$obj->getPackage() . '-' .
            $obj->getVersion();
        $data = array(
            'caption' => $caption,
            'border' => true);
        switch ($obj->getPackageType()) {
            case 'php' :
                $release = 'PEAR-style PHP-based Package';
            break;
            case 'extsrc' :
                $release = 'PECL-style PHP extension (source code)';
            break;
            case 'zendextsrc' :
                $release = 'PECL-style Zend extension (source code)';
            break;
            case 'extbin' :
                $release = 'PECL-style PHP extension (binary)';
            break;
            case 'zendextbin' :
                $release = 'PECL-style Zend extension (binary)';
            break;
            case 'bundle' :
                $release = 'Package bundle (collection of packages)';
            break;
        }
        $extends = $obj->getExtends();
        $extends = $extends ?
            $obj->getPackage() . ' (extends ' . $extends . ')' : $obj->getPackage();
        if ($src = $obj->getSourcePackage()) {
            $extends .= ' (source package ' . $src['channel'] . '/' . $src['package'] . ')';
        }

        $info = array(
            'Release Type' => $release,
            'Name' => $extends,
            'Channel' => $obj->getChannel(),
            'Summary' => preg_replace('/  +/', ' ', $obj->getSummary()),
            'Description' => preg_replace('/  +/', ' ', $obj->getDescription()),
            );
        $info['Maintainers'] = '';
        foreach (array('lead', 'developer', 'contributor', 'helper') as $role) {
            $leads = $obj->{"get{$role}s"}();
            if (!$leads) {
                continue;
            }

            if (isset($leads['active'])) {
                $leads = array($leads);
            }

            foreach ($leads as $lead) {
                if (!empty($info['Maintainers'])) {
                    $info['Maintainers'] .= "\n";
                }

                $active = $lead['active'] == 'no' ? ', inactive' : '';
                $info['Maintainers'] .= $lead['name'] . ' <';
                $info['Maintainers'] .= $lead['email'] . "> ($role$active)";
            }
        }

        $info['Release Date'] = $obj->getDate();
        if ($time = $obj->getTime()) {
            $info['Release Date'] .= ' ' . $time;
        }

        $info['Release Version'] = $obj->getVersion() . ' (' . $obj->getState() . ')';
        $info['API Version'] = $obj->getVersion('api') . ' (' . $obj->getState('api') . ')';
        $info['License'] = $obj->getLicense();
        $uri = $obj->getLicenseLocation();
        if ($uri) {
            if (isset($uri['uri'])) {
                $info['License'] .= ' (' . $uri['uri'] . ')';
            } else {
                $extra = $obj->getInstalledLocation($info['filesource']);
                if ($extra) {
                    $info['License'] .= ' (' . $uri['filesource'] . ')';
                }
            }
        }

        $info['Release Notes'] = $obj->getNotes();
        if ($compat = $obj->getCompatible()) {
            if (!isset($compat[0])) {
                $compat = array($compat);
            }

            $info['Compatible with'] = '';
            foreach ($compat as $package) {
                $info['Compatible with'] .= $package['channel'] . '/' . $package['name'] .
                    "\nVersions >= " . $package['min'] . ', <= ' . $package['max'];
                if (isset($package['exclude'])) {
                    if (is_array($package['exclude'])) {
                        $package['exclude'] = implode(', ', $package['exclude']);
                    }

                    if (!isset($info['Not Compatible with'])) {
                        $info['Not Compatible with'] = '';
                    } else {
                        $info['Not Compatible with'] .= "\n";
                    }
                    $info['Not Compatible with'] .= $package['channel'] . '/' .
                        $package['name'] . "\nVersions " . $package['exclude'];
                }
            }
        }

        $usesrole = $obj->getUsesrole();
        if ($usesrole) {
            if (!isset($usesrole[0])) {
                $usesrole = array($usesrole);
            }

            foreach ($usesrole as $roledata) {
                if (isset($info['Uses Custom Roles'])) {
                    $info['Uses Custom Roles'] .= "\n";
                } else {
                    $info['Uses Custom Roles'] = '';
                }

                if (isset($roledata['package'])) {
                    $rolepackage = $reg->parsedPackageNameToString($roledata, true);
                } else {
                    $rolepackage = $roledata['uri'];
                }
                $info['Uses Custom Roles'] .= $roledata['role'] . ' (' . $rolepackage . ')';
            }
        }

        $usestask = $obj->getUsestask();
        if ($usestask) {
            if (!isset($usestask[0])) {
                $usestask = array($usestask);
            }

            foreach ($usestask as $taskdata) {
                if (isset($info['Uses Custom Tasks'])) {
                    $info['Uses Custom Tasks'] .= "\n";
                } else {
                    $info['Uses Custom Tasks'] = '';
                }

                if (isset($taskdata['package'])) {
                    $taskpackage = $reg->parsedPackageNameToString($taskdata, true);
                } else {
                    $taskpackage = $taskdata['uri'];
                }
                $info['Uses Custom Tasks'] .= $taskdata['task'] . ' (' . $taskpackage . ')';
            }
        }

        $deps = $obj->getDependencies();
        $info['Required Dependencies'] = 'PHP version ' . $deps['required']['php']['min'];
        if (isset($deps['required']['php']['max'])) {
            $info['Required Dependencies'] .= '-' . $deps['required']['php']['max'] . "\n";
        } else {
            $info['Required Dependencies'] .= "\n";
        }

        if (isset($deps['required']['php']['exclude'])) {
            if (!isset($info['Not Compatible with'])) {
                $info['Not Compatible with'] = '';
            } else {
                $info['Not Compatible with'] .= "\n";
            }

            if (is_array($deps['required']['php']['exclude'])) {
                $deps['required']['php']['exclude'] =
                    implode(', ', $deps['required']['php']['exclude']);
            }
            $info['Not Compatible with'] .= "PHP versions\n  " .
                $deps['required']['php']['exclude'];
        }

        $info['Required Dependencies'] .= 'PEAR installer version';
        if (isset($deps['required']['pearinstaller']['max'])) {
            $info['Required Dependencies'] .= 's ' .
                $deps['required']['pearinstaller']['min'] . '-' .
                $deps['required']['pearinstaller']['max'];
        } else {
            $info['Required Dependencies'] .= ' ' .
                $deps['required']['pearinstaller']['min'] . ' or newer';
        }

        if (isset($deps['required']['pearinstaller']['exclude'])) {
            if (!isset($info['Not Compatible with'])) {
                $info['Not Compatible with'] = '';
            } else {
                $info['Not Compatible with'] .= "\n";
            }

            if (is_array($deps['required']['pearinstaller']['exclude'])) {
                $deps['required']['pearinstaller']['exclude'] =
                    implode(', ', $deps['required']['pearinstaller']['exclude']);
            }
            $info['Not Compatible with'] .= "PEAR installer\n  Versions " .
                $deps['required']['pearinstaller']['exclude'];
        }

        foreach (array('Package', 'Extension') as $type) {
            $index = strtolower($type);
            if (isset($deps['required'][$index])) {
                if (isset($deps['required'][$index]['name'])) {
                    $deps['required'][$index] = array($deps['required'][$index]);
                }

                foreach ($deps['required'][$index] as $package) {
                    if (isset($package['conflicts'])) {
                        $infoindex = 'Not Compatible with';
                        if (!isset($info['Not Compatible with'])) {
                            $info['Not Compatible with'] = '';
                        } else {
                            $info['Not Compatible with'] .= "\n";
                        }
                    } else {
                        $infoindex = 'Required Dependencies';
                        $info[$infoindex] .= "\n";
                    }

                    if ($index == 'extension') {
                        $name = $package['name'];
                    } else {
                        if (isset($package['channel'])) {
                            $name = $package['channel'] . '/' . $package['name'];
                        } else {
                            $name = '__uri/' . $package['name'] . ' (static URI)';
                        }
                    }

                    $info[$infoindex] .= "$type $name";
                    if (isset($package['uri'])) {
                        $info[$infoindex] .= "\n  Download URI: $package[uri]";
                        continue;
                    }

                    if (isset($package['max']) && isset($package['min'])) {
                        $info[$infoindex] .= " \n  Versions " .
                            $package['min'] . '-' . $package['max'];
                    } elseif (isset($package['min'])) {
                        $info[$infoindex] .= " \n  Version " .
                            $package['min'] . ' or newer';
                    } elseif (isset($package['max'])) {
                        $info[$infoindex] .= " \n  Version " .
                            $package['max'] . ' or older';
                    }

                    if (isset($package['recommended'])) {
                        $info[$infoindex] .= "\n  Recommended version: $package[recommended]";
                    }

                    if (isset($package['exclude'])) {
                        if (!isset($info['Not Compatible with'])) {
                            $info['Not Compatible with'] = '';
                        } else {
                            $info['Not Compatible with'] .= "\n";
                        }

                        if (is_array($package['exclude'])) {
                            $package['exclude'] = implode(', ', $package['exclude']);
                        }

                        $package['package'] = $package['name']; // for parsedPackageNameToString
                         if (isset($package['conflicts'])) {
                            $info['Not Compatible with'] .= '=> except ';
                        }
                       $info['Not Compatible with'] .= 'Package ' .
                            $reg->parsedPackageNameToString($package, true);
                        $info['Not Compatible with'] .= "\n  Versions " . $package['exclude'];
                    }
                }
            }
        }

        if (isset($deps['required']['os'])) {
            if (isset($deps['required']['os']['name'])) {
                $dep['required']['os']['name'] = array($dep['required']['os']['name']);
            }

            foreach ($dep['required']['os'] as $os) {
                if (isset($os['conflicts']) && $os['conflicts'] == 'yes') {
                    if (!isset($info['Not Compatible with'])) {
                        $info['Not Compatible with'] = '';
                    } else {
                        $info['Not Compatible with'] .= "\n";
                    }
                    $info['Not Compatible with'] .= "$os[name] Operating System";
                } else {
                    $info['Required Dependencies'] .= "\n";
                    $info['Required Dependencies'] .= "$os[name] Operating System";
                }
            }
        }

        if (isset($deps['required']['arch'])) {
            if (isset($deps['required']['arch']['pattern'])) {
                $dep['required']['arch']['pattern'] = array($dep['required']['os']['pattern']);
            }

            foreach ($dep['required']['arch'] as $os) {
                if (isset($os['conflicts']) && $os['conflicts'] == 'yes') {
                    if (!isset($info['Not Compatible with'])) {
                        $info['Not Compatible with'] = '';
                    } else {
                        $info['Not Compatible with'] .= "\n";
                    }
                    $info['Not Compatible with'] .= "OS/Arch matching pattern '/$os[pattern]/'";
                } else {
                    $info['Required Dependencies'] .= "\n";
                    $info['Required Dependencies'] .= "OS/Arch matching pattern '/$os[pattern]/'";
                }
            }
        }

        if (isset($deps['optional'])) {
            foreach (array('Package', 'Extension') as $type) {
                $index = strtolower($type);
                if (isset($deps['optional'][$index])) {
                    if (isset($deps['optional'][$index]['name'])) {
                        $deps['optional'][$index] = array($deps['optional'][$index]);
                    }

                    foreach ($deps['optional'][$index] as $package) {
                        if (isset($package['conflicts']) && $package['conflicts'] == 'yes') {
                            $infoindex = 'Not Compatible with';
                            if (!isset($info['Not Compatible with'])) {
                                $info['Not Compatible with'] = '';
                            } else {
                                $info['Not Compatible with'] .= "\n";
                            }
                        } else {
                            $infoindex = 'Optional Dependencies';
                            if (!isset($info['Optional Dependencies'])) {
                                $info['Optional Dependencies'] = '';
                            } else {
                                $info['Optional Dependencies'] .= "\n";
                            }
                        }

                        if ($index == 'extension') {
                            $name = $package['name'];
                        } else {
                            if (isset($package['channel'])) {
                                $name = $package['channel'] . '/' . $package['name'];
                            } else {
                                $name = '__uri/' . $package['name'] . ' (static URI)';
                            }
                        }

                        $info[$infoindex] .= "$type $name";
                        if (isset($package['uri'])) {
                            $info[$infoindex] .= "\n  Download URI: $package[uri]";
                            continue;
                        }

                        if ($infoindex == 'Not Compatible with') {
                            // conflicts is only used to say that all versions conflict
                            continue;
                        }

                        if (isset($package['max']) && isset($package['min'])) {
                            $info[$infoindex] .= " \n  Versions " .
                                $package['min'] . '-' . $package['max'];
                        } elseif (isset($package['min'])) {
                            $info[$infoindex] .= " \n  Version " .
                                $package['min'] . ' or newer';
                        } elseif (isset($package['max'])) {
                            $info[$infoindex] .= " \n  Version " .
                                $package['min'] . ' or older';
                        }

                        if (isset($package['recommended'])) {
                            $info[$infoindex] .= "\n  Recommended version: $package[recommended]";
                        }

                        if (isset($package['exclude'])) {
                            if (!isset($info['Not Compatible with'])) {
                                $info['Not Compatible with'] = '';
                            } else {
                                $info['Not Compatible with'] .= "\n";
                            }

                            if (is_array($package['exclude'])) {
                                $package['exclude'] = implode(', ', $package['exclude']);
                            }

                            $info['Not Compatible with'] .= "Package $package\n  Versions " .
                                $package['exclude'];
                        }
                    }
                }
            }
        }

        if (isset($deps['group'])) {
            if (!isset($deps['group'][0])) {
                $deps['group'] = array($deps['group']);
            }

            foreach ($deps['group'] as $group) {
                $info['Dependency Group ' . $group['attribs']['name']] = $group['attribs']['hint'];
                $groupindex = $group['attribs']['name'] . ' Contents';
                $info[$groupindex] = '';
                foreach (array('Package', 'Extension') as $type) {
                    $index = strtolower($type);
                    if (isset($group[$index])) {
                        if (isset($group[$index]['name'])) {
                            $group[$index] = array($group[$index]);
                        }

                        foreach ($group[$index] as $package) {
                            if (!empty($info[$groupindex])) {
                                $info[$groupindex] .= "\n";
                            }

                            if ($index == 'extension') {
                                $name = $package['name'];
                            } else {
                                if (isset($package['channel'])) {
                                    $name = $package['channel'] . '/' . $package['name'];
                                } else {
                                    $name = '__uri/' . $package['name'] . ' (static URI)';
                                }
                            }

                            if (isset($package['uri'])) {
                                if (isset($package['conflicts']) && $package['conflicts'] == 'yes') {
                                    $info[$groupindex] .= "Not Compatible with $type $name";
                                } else {
                                    $info[$groupindex] .= "$type $name";
                                }

                                $info[$groupindex] .= "\n  Download URI: $package[uri]";
                                continue;
                            }

                            if (isset($package['conflicts']) && $package['conflicts'] == 'yes') {
                                $info[$groupindex] .= "Not Compatible with $type $name";
                                continue;
                            }

                            $info[$groupindex] .= "$type $name";
                            if (isset($package['max']) && isset($package['min'])) {
                                $info[$groupindex] .= " \n  Versions " .
                                    $package['min'] . '-' . $package['max'];
                            } elseif (isset($package['min'])) {
                                $info[$groupindex] .= " \n  Version " .
                                    $package['min'] . ' or newer';
                            } elseif (isset($package['max'])) {
                                $info[$groupindex] .= " \n  Version " .
                                    $package['min'] . ' or older';
                            }

                            if (isset($package['recommended'])) {
                                $info[$groupindex] .= "\n  Recommended version: $package[recommended]";
                            }

                            if (isset($package['exclude'])) {
                                if (!isset($info['Not Compatible with'])) {
                                    $info['Not Compatible with'] = '';
                                } else {
                                    $info[$groupindex] .= "Not Compatible with\n";
                                }

                                if (is_array($package['exclude'])) {
                                    $package['exclude'] = implode(', ', $package['exclude']);
                                }
                                $info[$groupindex] .= "  Package $package\n  Versions " .
                                    $package['exclude'];
                            }
                        }
                    }
                }
            }
        }

        if ($obj->getPackageType() == 'bundle') {
            $info['Bundled Packages'] = '';
            foreach ($obj->getBundledPackages() as $package) {
                if (!empty($info['Bundled Packages'])) {
                    $info['Bundled Packages'] .= "\n";
                }

                if (isset($package['uri'])) {
                    $info['Bundled Packages'] .= '__uri/' . $package['name'];
                    $info['Bundled Packages'] .= "\n  (URI: $package[uri]";
                } else {
                    $info['Bundled Packages'] .= $package['channel'] . '/' . $package['name'];
                }
            }
        }

        $info['package.xml version'] = '2.0';
        if ($installed) {
            if ($obj->getLastModified()) {
                $info['Last Modified'] = date('Y-m-d H:i', $obj->getLastModified());
            }

            $v = $obj->getLastInstalledVersion();
            $info['Previous Installed Version'] = $v ? $v : '- None -';
        }

        foreach ($info as $key => $value) {
            $data['data'][] = array($key, $value);
        }

        $data['raw'] = $obj->getArray(); // no validation needed
        $this->ui->outputData($data, 'package-info');
    }
}
PKp�Z�4�{��PEAR/Command/Auth.xmlnu�[���<commands version="1.0">
 <login>
  <summary>Connects and authenticates to remote server [Deprecated in favor of channel-login]</summary>
  <function>doLogin</function>
  <shortcut>li</shortcut>
  <options />
  <doc>&lt;channel name&gt;
WARNING: This function is deprecated in favor of using channel-login

Log in to a remote channel server.  If &lt;channel name&gt; is not supplied,
the default channel is used. To use remote functions in the installer
that require any kind of privileges, you need to log in first.  The
username and password you enter here will be stored in your per-user
PEAR configuration (~/.pearrc on Unix-like systems).  After logging
in, your username and password will be sent along in subsequent
operations on the remote server.</doc>
 </login>
 <logout>
  <summary>Logs out from the remote server [Deprecated in favor of channel-logout]</summary>
  <function>doLogout</function>
  <shortcut>lo</shortcut>
  <options />
  <doc>
WARNING: This function is deprecated in favor of using channel-logout

Logs out from the remote server.  This command does not actually
connect to the remote server, it only deletes the stored username and
password from your user configuration.</doc>
 </logout>
</commands>PKp�Z��#S
S
PEAR/Command/Build.phpnu�[���<?php
/**
 * PEAR_Command_Auth (build command)
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Tomas V.V.Cox <cox@idecnet.com>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 0.1
 */

/**
 * base class
 */
require_once 'PEAR/Command/Common.php';

/**
 * PEAR commands for building extensions.
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Tomas V.V.Cox <cox@idecnet.com>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 0.1
 */
class PEAR_Command_Build extends PEAR_Command_Common
{
    var $commands = array(
        'build' => array(
            'summary' => 'Build an Extension From C Source',
            'function' => 'doBuild',
            'shortcut' => 'b',
            'options' => array(
                'configureoptions' => array(
                    'shortopt' => 'D',
                    'arg' => 'OPTION1=VALUE[ OPTION2=VALUE]',
                    'doc' => 'space-delimited list of configure options',
                    ),
                ),
            'doc' => '[package.xml]
Builds one or more extensions contained in a package.'
            ),
        );

    /**
     * PEAR_Command_Build constructor.
     *
     * @access public
     */
    function __construct(&$ui, &$config)
    {
        parent::__construct($ui, $config);
    }

    function doBuild($command, $options, $params)
    {
        require_once 'PEAR/Builder.php';
        if (sizeof($params) < 1) {
            $params[0] = 'package.xml';
        }

        $configureoptions = empty($options['configureoptions']) ? '' : $options['configureoptions'];
        $builder = new PEAR_Builder($configureoptions, $this->ui);
        $this->debug = $this->config->get('verbose');
        $err = $builder->build($params[0], array(&$this, 'buildCallback'));
        if (PEAR::isError($err)) {
            return $err;
        }

        return true;
    }

    function buildCallback($what, $data)
    {
        if (($what == 'cmdoutput' && $this->debug > 1) ||
            ($what == 'output' && $this->debug > 0)) {
            $this->ui->outputData(rtrim($data), 'build');
        }
    }
}
PKp�Z���u��PEAR/Command/Registry.xmlnu�[���<commands version="1.0">
 <list>
  <summary>List Installed Packages In The Default Channel</summary>
  <function>doList</function>
  <shortcut>l</shortcut>
  <options>
   <channel>
    <shortopt>c</shortopt>
    <doc>list installed packages from this channel</doc>
    <arg>CHAN</arg>
   </channel>
   <allchannels>
    <shortopt>a</shortopt>
    <doc>list installed packages from all channels</doc>
   </allchannels>
   <channelinfo>
    <shortopt>i</shortopt>
    <doc>output fully channel-aware data, even on failure</doc>
   </channelinfo>
  </options>
  <doc>&lt;package&gt;
If invoked without parameters, this command lists the PEAR packages
installed in your php_dir ({config php_dir}).  With a parameter, it
lists the files in a package.
</doc>
 </list>
 <list-files>
  <summary>List Files In Installed Package</summary>
  <function>doFileList</function>
  <shortcut>fl</shortcut>
  <options />
  <doc>&lt;package&gt;
List the files in an installed package.
</doc>
 </list-files>
 <shell-test>
  <summary>Shell Script Test</summary>
  <function>doShellTest</function>
  <shortcut>st</shortcut>
  <options />
  <doc>&lt;package&gt; [[relation] version]
Tests if a package is installed in the system. Will exit(1) if it is not.
   &lt;relation&gt;   The version comparison operator. One of:
                &lt;, lt, &lt;=, le, &gt;, gt, &gt;=, ge, ==, =, eq, !=, &lt;&gt;, ne
   &lt;version&gt;    The version to compare with
</doc>
 </shell-test>
 <info>
  <summary>Display information about a package</summary>
  <function>doInfo</function>
  <shortcut>in</shortcut>
  <options />
  <doc>&lt;package&gt;
Displays information about a package. The package argument may be a
local package file, an URL to a package file, or the name of an
installed package.</doc>
 </info>
</commands>PKp�Z�P>>PEAR/Command/Pickle.phpnu�[���<?php
/**
 * PEAR_Command_Pickle (pickle command)
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  2005-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.1
 */

/**
 * base class
 */
require_once 'PEAR/Command/Common.php';

/**
 * PEAR commands for login/logout
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  2005-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.1
 */

class PEAR_Command_Pickle extends PEAR_Command_Common
{
    var $commands = array(
        'pickle' => array(
            'summary' => 'Build PECL Package',
            'function' => 'doPackage',
            'shortcut' => 'pi',
            'options' => array(
                'nocompress' => array(
                    'shortopt' => 'Z',
                    'doc' => 'Do not gzip the package file'
                    ),
                'showname' => array(
                    'shortopt' => 'n',
                    'doc' => 'Print the name of the packaged file.',
                    ),
                ),
            'doc' => '[descfile]
Creates a PECL package from its package2.xml file.

An automatic conversion will be made to a package.xml 1.0 and written out to
disk in the current directory as "package.xml".  Note that
only simple package.xml 2.0 will be converted.  package.xml 2.0 with:

 - dependency types other than required/optional PECL package/ext/php/pearinstaller
 - more than one extsrcrelease or zendextsrcrelease
 - zendextbinrelease, extbinrelease, phprelease, or bundle release type
 - dependency groups
 - ignore tags in release filelist
 - tasks other than replace
 - custom roles

will cause pickle to fail, and output an error message.  If your package2.xml
uses any of these features, you are best off using PEAR_PackageFileManager to
generate both package.xml.
'
            ),
        );

    /**
     * PEAR_Command_Package constructor.
     *
     * @access public
     */
    function __construct(&$ui, &$config)
    {
        parent::__construct($ui, $config);
    }

    /**
     * For unit-testing ease
     *
     * @return PEAR_Packager
     */
    function &getPackager()
    {
        if (!class_exists('PEAR_Packager')) {
            require_once 'PEAR/Packager.php';
        }

        $a = new PEAR_Packager;
        return $a;
    }

    /**
     * For unit-testing ease
     *
     * @param PEAR_Config $config
     * @param bool $debug
     * @param string|null $tmpdir
     * @return PEAR_PackageFile
     */
    function &getPackageFile($config, $debug = false)
    {
        if (!class_exists('PEAR_Common')) {
            require_once 'PEAR/Common.php';
        }

        if (!class_exists('PEAR_PackageFile')) {
            require_once 'PEAR/PackageFile.php';
        }

        $a = new PEAR_PackageFile($config, $debug);
        $common = new PEAR_Common;
        $common->ui = $this->ui;
        $a->setLogger($common);
        return $a;
    }

    function doPackage($command, $options, $params)
    {
        $this->output = '';
        $pkginfofile = isset($params[0]) ? $params[0] : 'package2.xml';
        $packager = &$this->getPackager();
        if (PEAR::isError($err = $this->_convertPackage($pkginfofile))) {
            return $err;
        }

        $compress = empty($options['nocompress']) ? true : false;
        $result = $packager->package($pkginfofile, $compress, 'package.xml');
        if (PEAR::isError($result)) {
            return $this->raiseError($result);
        }

        // Don't want output, only the package file name just created
        if (isset($options['showname'])) {
            $this->ui->outputData($result, $command);
        }

        return true;
    }

    function _convertPackage($packagexml)
    {
        $pkg = &$this->getPackageFile($this->config);
        $pf2 = &$pkg->fromPackageFile($packagexml, PEAR_VALIDATE_NORMAL);
        if (!is_a($pf2, 'PEAR_PackageFile_v2')) {
            return $this->raiseError('Cannot process "' .
                $packagexml . '", is not a package.xml 2.0');
        }

        require_once 'PEAR/PackageFile/v1.php';
        $pf = new PEAR_PackageFile_v1;
        $pf->setConfig($this->config);
        if ($pf2->getPackageType() != 'extsrc' && $pf2->getPackageType() != 'zendextsrc') {
            return $this->raiseError('Cannot safely convert "' . $packagexml .
            '", is not an extension source package.  Using a PEAR_PackageFileManager-based ' .
            'script is an option');
        }

        if (is_array($pf2->getUsesRole())) {
            return $this->raiseError('Cannot safely convert "' . $packagexml .
            '", contains custom roles.  Using a PEAR_PackageFileManager-based script or ' .
            'the convert command is an option');
        }

        if (is_array($pf2->getUsesTask())) {
            return $this->raiseError('Cannot safely convert "' . $packagexml .
            '", contains custom tasks.  Using a PEAR_PackageFileManager-based script or ' .
            'the convert command is an option');
        }

        $deps = $pf2->getDependencies();
        if (isset($deps['group'])) {
            return $this->raiseError('Cannot safely convert "' . $packagexml .
            '", contains dependency groups.  Using a PEAR_PackageFileManager-based script ' .
            'or the convert command is an option');
        }

        if (isset($deps['required']['subpackage']) ||
              isset($deps['optional']['subpackage'])) {
            return $this->raiseError('Cannot safely convert "' . $packagexml .
            '", contains subpackage dependencies.  Using a PEAR_PackageFileManager-based  '.
            'script is an option');
        }

        if (isset($deps['required']['os'])) {
            return $this->raiseError('Cannot safely convert "' . $packagexml .
            '", contains os dependencies.  Using a PEAR_PackageFileManager-based  '.
            'script is an option');
        }

        if (isset($deps['required']['arch'])) {
            return $this->raiseError('Cannot safely convert "' . $packagexml .
            '", contains arch dependencies.  Using a PEAR_PackageFileManager-based  '.
            'script is an option');
        }

        $pf->setPackage($pf2->getPackage());
        $pf->setSummary($pf2->getSummary());
        $pf->setDescription($pf2->getDescription());
        foreach ($pf2->getMaintainers() as $maintainer) {
            $pf->addMaintainer($maintainer['role'], $maintainer['handle'],
                $maintainer['name'], $maintainer['email']);
        }

        $pf->setVersion($pf2->getVersion());
        $pf->setDate($pf2->getDate());
        $pf->setLicense($pf2->getLicense());
        $pf->setState($pf2->getState());
        $pf->setNotes($pf2->getNotes());
        $pf->addPhpDep($deps['required']['php']['min'], 'ge');
        if (isset($deps['required']['php']['max'])) {
            $pf->addPhpDep($deps['required']['php']['max'], 'le');
        }

        if (isset($deps['required']['package'])) {
            if (!isset($deps['required']['package'][0])) {
                $deps['required']['package'] = array($deps['required']['package']);
            }

            foreach ($deps['required']['package'] as $dep) {
                if (!isset($dep['channel'])) {
                    return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
                    ' contains uri-based dependency on a package.  Using a ' .
                    'PEAR_PackageFileManager-based script is an option');
                }

                if ($dep['channel'] != 'pear.php.net'
                    && $dep['channel'] != 'pecl.php.net'
                    && $dep['channel'] != 'doc.php.net') {
                    return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
                    ' contains dependency on a non-standard channel package.  Using a ' .
                    'PEAR_PackageFileManager-based script is an option');
                }

                if (isset($dep['conflicts'])) {
                    return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
                    ' contains conflicts dependency.  Using a ' .
                    'PEAR_PackageFileManager-based script is an option');
                }

                if (isset($dep['exclude'])) {
                    $this->ui->outputData('WARNING: exclude tags are ignored in conversion');
                }

                if (isset($dep['min'])) {
                    $pf->addPackageDep($dep['name'], $dep['min'], 'ge');
                }

                if (isset($dep['max'])) {
                    $pf->addPackageDep($dep['name'], $dep['max'], 'le');
                }
            }
        }

        if (isset($deps['required']['extension'])) {
            if (!isset($deps['required']['extension'][0])) {
                $deps['required']['extension'] = array($deps['required']['extension']);
            }

            foreach ($deps['required']['extension'] as $dep) {
                if (isset($dep['conflicts'])) {
                    return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
                    ' contains conflicts dependency.  Using a ' .
                    'PEAR_PackageFileManager-based script is an option');
                }

                if (isset($dep['exclude'])) {
                    $this->ui->outputData('WARNING: exclude tags are ignored in conversion');
                }

                if (isset($dep['min'])) {
                    $pf->addExtensionDep($dep['name'], $dep['min'], 'ge');
                }

                if (isset($dep['max'])) {
                    $pf->addExtensionDep($dep['name'], $dep['max'], 'le');
                }
            }
        }

        if (isset($deps['optional']['package'])) {
            if (!isset($deps['optional']['package'][0])) {
                $deps['optional']['package'] = array($deps['optional']['package']);
            }

            foreach ($deps['optional']['package'] as $dep) {
                if (!isset($dep['channel'])) {
                    return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
                    ' contains uri-based dependency on a package.  Using a ' .
                    'PEAR_PackageFileManager-based script is an option');
                }

                if ($dep['channel'] != 'pear.php.net'
                    && $dep['channel'] != 'pecl.php.net'
                    && $dep['channel'] != 'doc.php.net') {
                    return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
                    ' contains dependency on a non-standard channel package.  Using a ' .
                    'PEAR_PackageFileManager-based script is an option');
                }

                if (isset($dep['exclude'])) {
                    $this->ui->outputData('WARNING: exclude tags are ignored in conversion');
                }

                if (isset($dep['min'])) {
                    $pf->addPackageDep($dep['name'], $dep['min'], 'ge', 'yes');
                }

                if (isset($dep['max'])) {
                    $pf->addPackageDep($dep['name'], $dep['max'], 'le', 'yes');
                }
            }
        }

        if (isset($deps['optional']['extension'])) {
            if (!isset($deps['optional']['extension'][0])) {
                $deps['optional']['extension'] = array($deps['optional']['extension']);
            }

            foreach ($deps['optional']['extension'] as $dep) {
                if (isset($dep['exclude'])) {
                    $this->ui->outputData('WARNING: exclude tags are ignored in conversion');
                }

                if (isset($dep['min'])) {
                    $pf->addExtensionDep($dep['name'], $dep['min'], 'ge', 'yes');
                }

                if (isset($dep['max'])) {
                    $pf->addExtensionDep($dep['name'], $dep['max'], 'le', 'yes');
                }
            }
        }

        $contents = $pf2->getContents();
        $release  = $pf2->getReleases();
        if (isset($releases[0])) {
            return $this->raiseError('Cannot safely process "' . $packagexml . '" contains '
            . 'multiple extsrcrelease/zendextsrcrelease tags.  Using a PEAR_PackageFileManager-based script ' .
            'or the convert command is an option');
        }

        if ($configoptions = $pf2->getConfigureOptions()) {
            foreach ($configoptions as $option) {
                $default = isset($option['default']) ? $option['default'] : false;
                $pf->addConfigureOption($option['name'], $option['prompt'], $default);
            }
        }

        if (isset($release['filelist']['ignore'])) {
            return $this->raiseError('Cannot safely process "' . $packagexml . '" contains '
            . 'ignore tags.  Using a PEAR_PackageFileManager-based script or the convert' .
            ' command is an option');
        }

        if (isset($release['filelist']['install']) &&
              !isset($release['filelist']['install'][0])) {
            $release['filelist']['install'] = array($release['filelist']['install']);
        }

        if (isset($contents['dir']['attribs']['baseinstalldir'])) {
            $baseinstalldir = $contents['dir']['attribs']['baseinstalldir'];
        } else {
            $baseinstalldir = false;
        }

        if (!isset($contents['dir']['file'][0])) {
            $contents['dir']['file'] = array($contents['dir']['file']);
        }

        foreach ($contents['dir']['file'] as $file) {
            if ($baseinstalldir && !isset($file['attribs']['baseinstalldir'])) {
                $file['attribs']['baseinstalldir'] = $baseinstalldir;
            }

            $processFile = $file;
            unset($processFile['attribs']);
            if (count($processFile)) {
                foreach ($processFile as $name => $task) {
                    if ($name != $pf2->getTasksNs() . ':replace') {
                        return $this->raiseError('Cannot safely process "' . $packagexml .
                        '" contains tasks other than replace.  Using a ' .
                        'PEAR_PackageFileManager-based script is an option.');
                    }
                    $file['attribs']['replace'][] = $task;
                }
            }

            if (!in_array($file['attribs']['role'], PEAR_Common::getFileRoles())) {
                return $this->raiseError('Cannot safely convert "' . $packagexml .
                '", contains custom roles.  Using a PEAR_PackageFileManager-based script ' .
                'or the convert command is an option');
            }

            if (isset($release['filelist']['install'])) {
                foreach ($release['filelist']['install'] as $installas) {
                    if ($installas['attribs']['name'] == $file['attribs']['name']) {
                        $file['attribs']['install-as'] = $installas['attribs']['as'];
                    }
                }
            }

            $pf->addFile('/', $file['attribs']['name'], $file['attribs']);
        }

        if ($pf2->getChangeLog()) {
            $this->ui->outputData('WARNING: changelog is not translated to package.xml ' .
                '1.0, use PEAR_PackageFileManager-based script if you need changelog-' .
                'translation for package.xml 1.0');
        }

        $gen = &$pf->getDefaultGenerator();
        $gen->toPackageFile('.');
    }
}
PKp�Z��T�I�IPEAR/Builder.phpnu�[���<?php
/**
 * PEAR_Builder for building PHP extensions (PECL packages)
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 0.1
 *
 * TODO: log output parameters in PECL command line
 * TODO: msdev path in configuration
 */

/**
 * Needed for extending PEAR_Builder
 */
require_once 'PEAR/Common.php';
require_once 'PEAR/PackageFile.php';
require_once 'System.php';

/**
 * Class to handle building (compiling) extensions.
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since PHP 4.0.2
 * @see        http://pear.php.net/manual/en/core.ppm.pear-builder.php
 */
class PEAR_Builder extends PEAR_Common
{
    var $php_api_version = 0;
    var $zend_module_api_no = 0;
    var $zend_extension_api_no = 0;

    var $extensions_built = array();

    /**
     * @var string Used for reporting when it is not possible to pass function
     *             via extra parameter, e.g. log, msdevCallback
     */
    var $current_callback = null;

    // used for msdev builds
    var $_lastline = null;
    var $_firstline = null;

    /**
     * Parsed --configureoptions.
     *
     * @var mixed[]
     */
    var $_parsed_configure_options;

    /**
     * PEAR_Builder constructor.
     *
     * @param mixed[] $configureoptions
     * @param object $ui user interface object (instance of PEAR_Frontend_*)
     *
     * @access public
     */
    function __construct($configureoptions, &$ui)
    {
        parent::__construct();
        $this->setFrontendObject($ui);
        $this->_parseConfigureOptions($configureoptions);
    }

    /**
     * Parse --configureoptions string.
     *
     * @param string Options, in the form "X=1 Y=2 Z='there\'s always one'"
     */
    function _parseConfigureOptions($options)
    {
        $data = '<XML><PROPERTIES ' . $options . ' /></XML>';
        $parser = xml_parser_create('ISO-8859-1');
        xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
        xml_set_element_handler(
            $parser, array($this, '_parseConfigureOptionsStartElement'),
            array($this, '_parseConfigureOptionsEndElement'));
        xml_parse($parser, $data, true);
        xml_parser_free($parser);
    }

    /**
     * Handle element start.
     *
     * @see PEAR_Builder::_parseConfigureOptions()
     *
     * @param resource $parser
     * @param string $tagName
     * @param mixed[] $attribs
     */
    function _parseConfigureOptionsStartElement($parser, $tagName, $attribs)
    {
        if ($tagName !== 'PROPERTIES') {
            return;
        }
        $this->_parsed_configure_options = $attribs;
    }

    /**
     * Handle element end.
     *
     * @see PEAR_Builder::_parseConfigureOptions()
     *
     * @param resource
     * @param string $element
     */
    function _parseConfigureOptionsEndElement($parser, $element)
    {
    }

    /**
     * Build an extension from source on windows.
     * requires msdev
     */
    function _build_win32($descfile, $callback = null)
    {
        if (is_object($descfile)) {
            $pkg = $descfile;
            $descfile = $pkg->getPackageFile();
        } else {
            $pf = new PEAR_PackageFile($this->config, $this->debug);
            $pkg = &$pf->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL);
            if (PEAR::isError($pkg)) {
                return $pkg;
            }
        }
        $dir = dirname($descfile);
        $old_cwd = getcwd();

        if (!file_exists($dir) || !is_dir($dir) || !chdir($dir)) {
            return $this->raiseError("could not chdir to $dir");
        }

        // packages that were in a .tar have the packagefile in this directory
        $vdir = $pkg->getPackage() . '-' . $pkg->getVersion();
        if (file_exists($dir) && is_dir($vdir)) {
            if (!chdir($vdir)) {
                return $this->raiseError("could not chdir to " . realpath($vdir));
            }

            $dir = getcwd();
        }

        $this->log(2, "building in $dir");

        $dsp = $pkg->getPackage().'.dsp';
        if (!file_exists("$dir/$dsp")) {
            return $this->raiseError("The DSP $dsp does not exist.");
        }
        // XXX TODO: make release build type configurable
        $command = 'msdev '.$dsp.' /MAKE "'.$pkg->getPackage(). ' - Release"';

        $err = $this->_runCommand($command, array(&$this, 'msdevCallback'));
        if (PEAR::isError($err)) {
            return $err;
        }

        // figure out the build platform and type
        $platform = 'Win32';
        $buildtype = 'Release';
        if (preg_match('/.*?'.$pkg->getPackage().'\s-\s(\w+)\s(.*?)-+/i',$this->_firstline,$matches)) {
            $platform = $matches[1];
            $buildtype = $matches[2];
        }

        if (preg_match('/(.*)?\s-\s(\d+).*?(\d+)/', $this->_lastline, $matches)) {
            if ($matches[2]) {
                // there were errors in the build
                return $this->raiseError("There were errors during compilation.");
            }
            $out = $matches[1];
        } else {
            return $this->raiseError("Did not understand the completion status returned from msdev.exe.");
        }

        // msdev doesn't tell us the output directory :/
        // open the dsp, find /out and use that directory
        $dsptext = join('', file($dsp));

        // this regex depends on the build platform and type having been
        // correctly identified above.
        $regex ='/.*?!IF\s+"\$\(CFG\)"\s+==\s+("'.
                    $pkg->getPackage().'\s-\s'.
                    $platform.'\s'.
                    $buildtype.'").*?'.
                    '\/out:"(.*?)"/is';

        if ($dsptext && preg_match($regex, $dsptext, $matches)) {
            // what we get back is a relative path to the output file itself.
            $outfile = realpath($matches[2]);
        } else {
            return $this->raiseError("Could not retrieve output information from $dsp.");
        }
        // realpath returns false if the file doesn't exist
        if ($outfile && copy($outfile, "$dir/$out")) {
            $outfile = "$dir/$out";
        }

        $built_files[] = array(
            'file' => "$outfile",
            'php_api' => $this->php_api_version,
            'zend_mod_api' => $this->zend_module_api_no,
            'zend_ext_api' => $this->zend_extension_api_no,
            );

        return $built_files;
    }
    // }}}

    // {{{ msdevCallback()
    function msdevCallback($what, $data)
    {
        if (!$this->_firstline)
            $this->_firstline = $data;
        $this->_lastline = $data;
        call_user_func($this->current_callback, $what, $data);
    }

    /**
     * @param string
     * @param string
     * @param array
     * @access private
     */
    function _harvestInstDir($dest_prefix, $dirname, &$built_files)
    {
        $d = opendir($dirname);
        if (!$d)
            return false;

        $ret = true;
        while (($ent = readdir($d)) !== false) {
            if ($ent[0] == '.')
                continue;

            $full = $dirname . DIRECTORY_SEPARATOR . $ent;
            if (is_dir($full)) {
                if (!$this->_harvestInstDir(
                        $dest_prefix . DIRECTORY_SEPARATOR . $ent,
                        $full, $built_files)) {
                    $ret = false;
                    break;
                }
            } else {
                $dest = $dest_prefix . DIRECTORY_SEPARATOR . $ent;
                $built_files[] = array(
                        'file' => $full,
                        'dest' => $dest,
                        'php_api' => $this->php_api_version,
                        'zend_mod_api' => $this->zend_module_api_no,
                        'zend_ext_api' => $this->zend_extension_api_no,
                        );
            }
        }
        closedir($d);
        return $ret;
    }

    /**
     * Build an extension from source.  Runs "phpize" in the source
     * directory, but compiles in a temporary directory
     * (TMPDIR/pear-build-USER/PACKAGE-VERSION).
     *
     * @param string|PEAR_PackageFile_v* $descfile path to XML package description file, or
     *               a PEAR_PackageFile object
     *
     * @param mixed $callback callback function used to report output,
     * see PEAR_Builder::_runCommand for details
     *
     * @return array an array of associative arrays with built files,
     * format:
     * array( array( 'file' => '/path/to/ext.so',
     *               'php_api' => YYYYMMDD,
     *               'zend_mod_api' => YYYYMMDD,
     *               'zend_ext_api' => YYYYMMDD ),
     *        ... )
     *
     * @access public
     *
     * @see PEAR_Builder::_runCommand
     */
    function build($descfile, $callback = null)
    {
        if (preg_match('/(\\/|\\\\|^)([^\\/\\\\]+)?php([^\\/\\\\]+)?$/',
                       $this->config->get('php_bin'), $matches)) {
            if (isset($matches[2]) && strlen($matches[2]) &&
                trim($matches[2]) != trim($this->config->get('php_prefix'))) {
                $this->log(0, 'WARNING: php_bin ' . $this->config->get('php_bin') .
                           ' appears to have a prefix ' . $matches[2] . ', but' .
                           ' config variable php_prefix does not match');
            }

            if (isset($matches[3]) && strlen($matches[3]) &&
                trim($matches[3]) != trim($this->config->get('php_suffix'))) {
                $this->log(0, 'WARNING: php_bin ' . $this->config->get('php_bin') .
                           ' appears to have a suffix ' . $matches[3] . ', but' .
                           ' config variable php_suffix does not match');
            }
        }

        $this->current_callback = $callback;
        if (PEAR_OS == "Windows") {
            return $this->_build_win32($descfile, $callback);
        }

        if (PEAR_OS != 'Unix') {
            return $this->raiseError("building extensions not supported on this platform");
        }

        if (is_object($descfile)) {
            $pkg = $descfile;
            $descfile = $pkg->getPackageFile();
            if (is_a($pkg, 'PEAR_PackageFile_v1')) {
                $dir = dirname($descfile);
            } else {
                $dir = $pkg->_config->get('temp_dir') . '/' . $pkg->getName();
                // automatically delete at session end
                self::addTempFile($dir);
            }
        } else {
            $pf = new PEAR_PackageFile($this->config);
            $pkg = &$pf->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL);
            if (PEAR::isError($pkg)) {
                return $pkg;
            }
            $dir = dirname($descfile);
        }

        // Find config. outside of normal path - e.g. config.m4
        foreach (array_keys($pkg->getInstallationFileList()) as $item) {
          if (stristr(basename($item), 'config.m4') && dirname($item) != '.') {
            $dir .= DIRECTORY_SEPARATOR . dirname($item);
            break;
          }
        }

        $old_cwd = getcwd();
        if (!file_exists($dir) || !is_dir($dir) || !chdir($dir)) {
            return $this->raiseError("could not chdir to $dir");
        }

        $vdir = $pkg->getPackage() . '-' . $pkg->getVersion();
        if (is_dir($vdir)) {
            chdir($vdir);
        }

        $dir = getcwd();
        $this->log(2, "building in $dir");
        $binDir = $this->config->get('bin_dir');
        if (!preg_match('@(^|:)' . preg_quote($binDir, '@') . '(:|$)@', getenv('PATH'))) {
            putenv('PATH=' . $binDir . ':' . getenv('PATH'));
        }
        $err = $this->_runCommand($this->config->get('php_prefix')
                                . "phpize" .
                                $this->config->get('php_suffix'),
                                array(&$this, 'phpizeCallback'));
        if (PEAR::isError($err)) {
            return $err;
        }

        if (!$err) {
            return $this->raiseError("`phpize' failed");
        }

        // {{{ start of interactive part
        $configure_command = "$dir/configure";

        $phpConfigName = $this->config->get('php_prefix')
            . 'php-config'
            . $this->config->get('php_suffix');
        $phpConfigPath = System::which($phpConfigName);
        if ($phpConfigPath !== false) {
            $configure_command .= ' --with-php-config='
                . $phpConfigPath;
        }

        $configure_options = $pkg->getConfigureOptions();
        if ($configure_options) {
            foreach ($configure_options as $option) {
                $default = array_key_exists('default', $option) ? $option['default'] : null;
                if (array_key_exists($option['name'], $this->_parsed_configure_options)) {
                    $response = $this->_parsed_configure_options[$option['name']];
                } else {
                    list($response) = $this->ui->userDialog(
                            'build', [$option['prompt']], ['text'], [$default]);
                }
                if (substr($option['name'], 0, 5) === 'with-' &&
                    ($response === 'yes' || $response === 'autodetect')) {
                    $configure_command .= " --{$option['name']}";
                } else {
                    $configure_command .= " --{$option['name']}=".trim($response);
                }
            }
        }
        // }}} end of interactive part

        // FIXME make configurable
        if (!$user=getenv('USER')) {
            $user='defaultuser';
        }

        $tmpdir = $this->config->get('temp_dir');
        $build_basedir = System::mktemp(' -t "' . $tmpdir . '" -d "pear-build-' . $user . '"');
        $build_dir = "$build_basedir/$vdir";
        $inst_dir = "$build_basedir/install-$vdir";
        $this->log(1, "building in $build_dir");
        if (is_dir($build_dir)) {
            System::rm(array('-rf', $build_dir));
        }

        if (!System::mkDir(array('-p', $build_dir))) {
            return $this->raiseError("could not create build dir: $build_dir");
        }

        self::addTempFile($build_dir);
        if (!System::mkDir(array('-p', $inst_dir))) {
            return $this->raiseError("could not create temporary install dir: $inst_dir");
        }
        self::addTempFile($inst_dir);

        $make_command = getenv('MAKE') ? getenv('MAKE') : 'make';

        $to_run = array(
            $configure_command,
            $make_command,
            "$make_command INSTALL_ROOT=\"$inst_dir\" install",
            "find \"$inst_dir\" | xargs ls -dils"
            );
        if (!file_exists($build_dir) || !is_dir($build_dir) || !chdir($build_dir)) {
            return $this->raiseError("could not chdir to $build_dir");
        }
        putenv('PHP_PEAR_VERSION=1.10.16');
        foreach ($to_run as $cmd) {
            $err = $this->_runCommand($cmd, $callback);
            if (PEAR::isError($err)) {
                chdir($old_cwd);
                return $err;
            }
            if (!$err) {
                chdir($old_cwd);
                return $this->raiseError("`$cmd' failed");
            }
        }
        if (!($dp = opendir("modules"))) {
            chdir($old_cwd);
            return $this->raiseError("no `modules' directory found");
        }
        $built_files = array();
        $prefix = exec($this->config->get('php_prefix')
                        . "php-config" .
                       $this->config->get('php_suffix') . " --prefix");
        $this->_harvestInstDir($prefix, $inst_dir . DIRECTORY_SEPARATOR . $prefix, $built_files);
        chdir($old_cwd);
        return $built_files;
    }

    /**
     * Message callback function used when running the "phpize"
     * program.  Extracts the API numbers used.  Ignores other message
     * types than "cmdoutput".
     *
     * @param string $what the type of message
     * @param mixed $data the message
     *
     * @return void
     *
     * @access public
     */
    function phpizeCallback($what, $data)
    {
        if ($what != 'cmdoutput') {
            return;
        }
        $this->log(1, rtrim($data));
        if (preg_match('/You should update your .aclocal.m4/', $data)) {
            return;
        }
        $matches = array();
        if (preg_match('/^\s+(\S[^:]+):\s+(\d{8})/', $data, $matches)) {
            $member = preg_replace('/[^a-z]/', '_', strtolower($matches[1]));
            $apino = (int)$matches[2];
            if (isset($this->$member)) {
                $this->$member = $apino;
                //$msg = sprintf("%-22s : %d", $matches[1], $apino);
                //$this->log(1, $msg);
            }
        }
    }

    /**
     * Run an external command, using a message callback to report
     * output.  The command will be run through popen and output is
     * reported for every line with a "cmdoutput" message with the
     * line string, including newlines, as payload.
     *
     * @param string $command the command to run
     *
     * @param mixed $callback (optional) function to use as message
     * callback
     *
     * @return bool whether the command was successful (exit code 0
     * means success, any other means failure)
     *
     * @access private
     */
    function _runCommand($command, $callback = null)
    {
        $this->log(1, "running: $command");
        $pp = popen("$command 2>&1", "r");
        if (!$pp) {
            return $this->raiseError("failed to run `$command'");
        }
        if ($callback && $callback[0]->debug == 1) {
            $olddbg = $callback[0]->debug;
            $callback[0]->debug = 2;
        }

        while ($line = fgets($pp, 1024)) {
            if ($callback) {
                call_user_func($callback, 'cmdoutput', $line);
            } else {
                $this->log(2, rtrim($line));
            }
        }
        if ($callback && isset($olddbg)) {
            $callback[0]->debug = $olddbg;
        }

        $exitcode = is_resource($pp) ? pclose($pp) : -1;
        return ($exitcode == 0);
    }

    function log($level, $msg, $append_crlf = true)
    {
        if ($this->current_callback) {
            if ($this->debug >= $level) {
                call_user_func($this->current_callback, 'output', $msg);
            }
            return;
        }
        return parent::log($level, $msg, $append_crlf);
    }
}
PKp�Z[
�W��PEAR/XMLParser.phpnu�[���<?php
/**
 * PEAR_XMLParser
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @author     Stephan Schmidt (original XML_Unserializer code)
 * @copyright  1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a1
 */

/**
 * Parser for any xml file
 * @category  pear
 * @package   PEAR
 * @author    Greg Beaver <cellog@php.net>
 * @author    Stephan Schmidt (original XML_Unserializer code)
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.10.16
 * @link      http://pear.php.net/package/PEAR
 * @since     Class available since Release 1.4.0a1
 */
class PEAR_XMLParser
{
    /**
     * unserilialized data
     * @var string $_serializedData
     */
    var $_unserializedData = null;

    /**
     * name of the root tag
     * @var string $_root
     */
    var $_root = null;

    /**
     * stack for all data that is found
     * @var array    $_dataStack
     */
    var $_dataStack = array();

    /**
     * stack for all values that are generated
     * @var array    $_valStack
     */
    var $_valStack = array();

    /**
     * current tag depth
     * @var int    $_depth
     */
    var $_depth = 0;

    /**
     * The XML encoding to use
     * @var string $encoding
     */
    var $encoding = 'ISO-8859-1';

    /**
     * @return array
     */
    function getData()
    {
        return $this->_unserializedData;
    }

    /**
     * @param string xml content
     * @return true|PEAR_Error
     */
    function parse($data)
    {
        if (!extension_loaded('xml')) {
            include_once 'PEAR.php';
            return PEAR::raiseError("XML Extension not found", 1);
        }
        $this->_dataStack =  $this->_valStack = array();
        $this->_depth = 0;

        if (
            strpos($data, 'encoding="UTF-8"')
            || strpos($data, 'encoding="utf-8"')
            || strpos($data, "encoding='UTF-8'")
            || strpos($data, "encoding='utf-8'")
        ) {
            $this->encoding = 'UTF-8';
        }

        $xp = xml_parser_create($this->encoding);
        xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, 0);
        xml_set_object($xp, $this);
        xml_set_element_handler($xp, 'startHandler', 'endHandler');
        xml_set_character_data_handler($xp, 'cdataHandler');
        if (!xml_parse($xp, $data)) {
            $msg = xml_error_string(xml_get_error_code($xp));
            $line = xml_get_current_line_number($xp);
            xml_parser_free($xp);
            include_once 'PEAR.php';
            return PEAR::raiseError("XML Error: '$msg' on line '$line'", 2);
        }
        xml_parser_free($xp);
        return true;
    }

    /**
     * Start element handler for XML parser
     *
     * @access private
     * @param  object $parser  XML parser object
     * @param  string $element XML element
     * @param  array  $attribs attributes of XML tag
     * @return void
     */
    function startHandler($parser, $element, $attribs)
    {
        $this->_depth++;
        $this->_dataStack[$this->_depth] = null;

        $val = array(
            'name'         => $element,
            'value'        => null,
            'type'         => 'string',
            'childrenKeys' => array(),
            'aggregKeys'   => array()
       );

        if (count($attribs) > 0) {
            $val['children'] = array();
            $val['type'] = 'array';
            $val['children']['attribs'] = $attribs;
        }

        array_push($this->_valStack, $val);
    }

    /**
     * post-process data
     *
     * @param string $data
     * @param string $element element name
     */
    function postProcess($data, $element)
    {
        return trim($data);
    }

    /**
     * End element handler for XML parser
     *
     * @access private
     * @param  object XML parser object
     * @param  string
     * @return void
     */
    function endHandler($parser, $element)
    {
        $value = array_pop($this->_valStack);
        $data  = $this->postProcess($this->_dataStack[$this->_depth], $element);

        // adjust type of the value
        switch (strtolower($value['type'])) {
            // unserialize an array
            case 'array':
                if ($data !== '') {
                    $value['children']['_content'] = $data;
                }

                $value['value'] = isset($value['children']) ? $value['children'] : array();
                break;

            /*
             * unserialize a null value
             */
            case 'null':
                $data = null;
                break;

            /*
             * unserialize any scalar value
             */
            default:
                settype($data, $value['type']);
                $value['value'] = $data;
                break;
        }

        $parent = array_pop($this->_valStack);
        if ($parent === null) {
            $this->_unserializedData = &$value['value'];
            $this->_root = &$value['name'];
            return true;
        }

        // parent has to be an array
        if (!isset($parent['children']) || !is_array($parent['children'])) {
            $parent['children'] = array();
            if ($parent['type'] != 'array') {
                $parent['type'] = 'array';
            }
        }

        if (!empty($value['name'])) {
            // there already has been a tag with this name
            if (in_array($value['name'], $parent['childrenKeys'])) {
                // no aggregate has been created for this tag
                if (!in_array($value['name'], $parent['aggregKeys'])) {
                    if (isset($parent['children'][$value['name']])) {
                        $parent['children'][$value['name']] = array($parent['children'][$value['name']]);
                    } else {
                        $parent['children'][$value['name']] = array();
                    }
                    array_push($parent['aggregKeys'], $value['name']);
                }
                array_push($parent['children'][$value['name']], $value['value']);
            } else {
                $parent['children'][$value['name']] = &$value['value'];
                array_push($parent['childrenKeys'], $value['name']);
            }
        } else {
            array_push($parent['children'],$value['value']);
        }
        array_push($this->_valStack, $parent);

        $this->_depth--;
    }

    /**
     * Handler for character data
     *
     * @access private
     * @param  object XML parser object
     * @param  string CDATA
     * @return void
     */
    function cdataHandler($parser, $cdata)
    {
        $this->_dataStack[$this->_depth] .= $cdata;
    }
}PKp�Zl(e���PEAR/Downloader.phpnu�[���<?php
/**
 * PEAR_Downloader, the PEAR Installer's download utility class
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @author     Stig Bakken <ssb@php.net>
 * @author     Tomas V. V. Cox <cox@idecnet.com>
 * @author     Martin Jansen <mj@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.3.0
 */

/**
 * Needed for constants, extending
 */
require_once 'PEAR/Common.php';
require_once 'PEAR/Proxy.php';

define('PEAR_INSTALLER_OK',       1);
define('PEAR_INSTALLER_FAILED',   0);
define('PEAR_INSTALLER_SKIPPED', -1);
define('PEAR_INSTALLER_ERROR_NO_PREF_STATE', 2);

/**
 * Administration class used to download anything from the internet (PEAR Packages,
 * static URLs, xml files)
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @author     Stig Bakken <ssb@php.net>
 * @author     Tomas V. V. Cox <cox@idecnet.com>
 * @author     Martin Jansen <mj@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.3.0
 */
class PEAR_Downloader extends PEAR_Common
{
    /**
     * @var PEAR_Registry
     * @access private
     */
    var $_registry;

    /**
     * Preferred Installation State (snapshot, devel, alpha, beta, stable)
     * @var string|null
     * @access private
     */
    var $_preferredState;

    /**
     * Options from command-line passed to Install.
     *
     * Recognized options:<br />
     *  - onlyreqdeps      : install all required dependencies as well
     *  - alldeps          : install all dependencies, including optional
     *  - installroot      : base relative path to install files in
     *  - force            : force a download even if warnings would prevent it
     *  - nocompress       : download uncompressed tarballs
     *  - configureoptions : additional configure options
     * @see PEAR_Command_Install
     * @access private
     * @var array
     */
    var $_options;

    /**
     * Downloaded Packages after a call to download().
     *
     * Format of each entry:
     *
     * <code>
     * array('pkg' => 'package_name', 'file' => '/path/to/local/file',
     *    'info' => array() // parsed package.xml
     * );
     * </code>
     * @access private
     * @var array
     */
    var $_downloadedPackages = array();

    /**
     * Packages slated for download.
     *
     * This is used to prevent downloading a package more than once should it be a dependency
     * for two packages to be installed.
     * Format of each entry:
     *
     * <pre>
     * array('package_name1' => parsed package.xml, 'package_name2' => parsed package.xml,
     * );
     * </pre>
     * @access private
     * @var array
     */
    var $_toDownload = array();

    /**
     * Array of every package installed, with names lower-cased.
     *
     * Format:
     * <code>
     * array('package1' => 0, 'package2' => 1, );
     * </code>
     * @var array
     */
    var $_installed = array();

    /**
     * @var array
     * @access private
     */
    var $_errorStack = array();

    /**
     * @var boolean
     * @access private
     */
    var $_internalDownload = false;

    /**
     * Temporary variable used in sorting packages by dependency in {@link sortPkgDeps()}
     * @var array
     * @access private
     */
    var $_packageSortTree;

    /**
     * Temporary directory, or configuration value where downloads will occur
     * @var string
     */
    var $_downloadDir;

    /**
     * List of methods that can be called both statically and non-statically.
     * @var array
     */
    protected static $bivalentMethods = array(
        'setErrorHandling' => true,
        'raiseError' => true,
        'throwError' => true,
        'pushErrorHandling' => true,
        'popErrorHandling' => true,
        'downloadHttp' => true,
    );

    /**
     * @param PEAR_Frontend_*
     * @param array
     * @param PEAR_Config
     */
    function __construct($ui = null, $options = array(), $config = null)
    {
        parent::__construct();
        $this->_options = $options;
        if ($config !== null) {
            $this->config = &$config;
            $this->_preferredState = $this->config->get('preferred_state');
        }
        $this->ui = &$ui;
        if (!$this->_preferredState) {
            // don't inadvertently use a non-set preferred_state
            $this->_preferredState = null;
        }

        if ($config !== null) {
            if (isset($this->_options['installroot'])) {
                $this->config->setInstallRoot($this->_options['installroot']);
            }
            $this->_registry = &$config->getRegistry();
        }

        if (isset($this->_options['alldeps']) || isset($this->_options['onlyreqdeps'])) {
            $this->_installed = $this->_registry->listAllPackages();
            foreach ($this->_installed as $key => $unused) {
                if (!count($unused)) {
                    continue;
                }
                $strtolower = function($a) { return strtolower($a); };
                array_walk($this->_installed[$key], $strtolower);
            }
        }
    }

    /**
     * Attempt to discover a channel's remote capabilities from
     * its server name
     * @param string
     * @return boolean
     */
    function discover($channel)
    {
        $this->log(1, 'Attempting to discover channel "' . $channel . '"...');
        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        $callback = $this->ui ? array(&$this, '_downloadCallback') : null;
        if (!class_exists('System')) {
            require_once 'System.php';
        }

        $tmpdir = $this->config->get('temp_dir');
        $tmp = System::mktemp('-d -t "' . $tmpdir . '"');
        $a   = $this->downloadHttp('http://' . $channel . '/channel.xml', $this->ui, $tmp, $callback, false);
        PEAR::popErrorHandling();
        if (PEAR::isError($a)) {
            // Attempt to fallback to https automatically.
            PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
            $this->log(1, 'Attempting fallback to https instead of http on channel "' . $channel . '"...');
            $a = $this->downloadHttp('https://' . $channel . '/channel.xml', $this->ui, $tmp, $callback, false);
            PEAR::popErrorHandling();
            if (PEAR::isError($a)) {
                return false;
            }
        }

        list($a, $lastmodified) = $a;
        if (!class_exists('PEAR_ChannelFile')) {
            require_once 'PEAR/ChannelFile.php';
        }

        $b = new PEAR_ChannelFile;
        if ($b->fromXmlFile($a)) {
            unlink($a);
            if ($this->config->get('auto_discover')) {
                $this->_registry->addChannel($b, $lastmodified);
                $alias = $b->getName();
                if ($b->getName() == $this->_registry->channelName($b->getAlias())) {
                    $alias = $b->getAlias();
                }

                $this->log(1, 'Auto-discovered channel "' . $channel .
                    '", alias "' . $alias . '", adding to registry');
            }

            return true;
        }

        unlink($a);
        return false;
    }

    /**
     * For simpler unit-testing
     * @param PEAR_Downloader
     * @return PEAR_Downloader_Package
     */
    function newDownloaderPackage(&$t)
    {
        if (!class_exists('PEAR_Downloader_Package')) {
            require_once 'PEAR/Downloader/Package.php';
        }
        $a = new PEAR_Downloader_Package($t);
        return $a;
    }

    /**
     * For simpler unit-testing
     * @param PEAR_Config
     * @param array
     * @param array
     * @param int
     */
    function &getDependency2Object(&$c, $i, $p, $s)
    {
        if (!class_exists('PEAR_Dependency2')) {
            require_once 'PEAR/Dependency2.php';
        }
        $z = new PEAR_Dependency2($c, $i, $p, $s);
        return $z;
    }

    function &download($params)
    {
        if (!count($params)) {
            $a = array();
            return $a;
        }

        if (!isset($this->_registry)) {
            $this->_registry = &$this->config->getRegistry();
        }

        $channelschecked = array();
        // convert all parameters into PEAR_Downloader_Package objects
        foreach ($params as $i => $param) {
            $params[$i] = $this->newDownloaderPackage($this);
            PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
            $err = $params[$i]->initialize($param);
            PEAR::staticPopErrorHandling();
            if (!$err) {
                // skip parameters that were missed by preferred_state
                continue;
            }

            if (PEAR::isError($err)) {
                if (!isset($this->_options['soft']) && $err->getMessage() !== '') {
                    $this->log(0, $err->getMessage());
                }

                $params[$i] = false;
                if (is_object($param)) {
                    $param = $param->getChannel() . '/' . $param->getPackage();
                }

                if (!isset($this->_options['soft'])) {
                    $this->log(2, 'Package "' . $param . '" is not valid');
                }

                // Message logged above in a specific verbose mode, passing null to not show up on CLI
                $this->pushError(null, PEAR_INSTALLER_SKIPPED);
            } else {
                do {
                    if ($params[$i] && $params[$i]->getType() == 'local') {
                        // bug #7090 skip channel.xml check for local packages
                        break;
                    }

                    if ($params[$i] && !isset($channelschecked[$params[$i]->getChannel()]) &&
                          !isset($this->_options['offline'])
                    ) {
                        $channelschecked[$params[$i]->getChannel()] = true;
                        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                        if (!class_exists('System')) {
                            require_once 'System.php';
                        }

                        $curchannel = $this->_registry->getChannel($params[$i]->getChannel());
                        if (PEAR::isError($curchannel)) {
                            PEAR::staticPopErrorHandling();
                            return $this->raiseError($curchannel);
                        }

                        if (PEAR::isError($dir = $this->getDownloadDir())) {
                            PEAR::staticPopErrorHandling();
                            break;
                        }

                        $mirror = $this->config->get('preferred_mirror', null, $params[$i]->getChannel());
                        $url    = 'http://' . $mirror . '/channel.xml';
                        $a = $this->downloadHttp($url, $this->ui, $dir, null, $curchannel->lastModified());

                        PEAR::staticPopErrorHandling();
                        if ($a === false) {
                            //channel.xml not modified
                            break;
                        } else if (PEAR::isError($a)) {
                            // Attempt fallback to https automatically
                            PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                            $a = $this->downloadHttp('https://' . $mirror .
                                '/channel.xml', $this->ui, $dir, null, $curchannel->lastModified());

                            PEAR::staticPopErrorHandling();
                            if (PEAR::isError($a) || !$a) {
                                break;
                            }
                        }
                        $this->log(0, 'WARNING: channel "' . $params[$i]->getChannel() . '" has ' .
                            'updated its protocols, use "' . PEAR_RUNTYPE . ' channel-update ' . $params[$i]->getChannel() .
                            '" to update');
                    }
                } while (false);

                if ($params[$i] && !isset($this->_options['downloadonly'])) {
                    if (isset($this->_options['packagingroot'])) {
                        $checkdir = $this->_prependPath(
                            $this->config->get('php_dir', null, $params[$i]->getChannel()),
                            $this->_options['packagingroot']);
                    } else {
                        $checkdir = $this->config->get('php_dir',
                            null, $params[$i]->getChannel());
                    }

                    while ($checkdir && $checkdir != '/' && !file_exists($checkdir)) {
                        $checkdir = dirname($checkdir);
                    }

                    if ($checkdir == '.') {
                        $checkdir = '/';
                    }

                    if (!is_writeable($checkdir)) {
                        return PEAR::raiseError('Cannot install, php_dir for channel "' .
                            $params[$i]->getChannel() . '" is not writeable by the current user');
                    }
                }
            }
        }

        unset($channelschecked);
        PEAR_Downloader_Package::removeDuplicates($params);
        if (!count($params)) {
            $a = array();
            return $a;
        }

        if (!isset($this->_options['nodeps']) && !isset($this->_options['offline'])) {
            $reverify = true;
            while ($reverify) {
                $reverify = false;
                foreach ($params as $i => $param) {
                    //PHP Bug 40768 / PEAR Bug #10944
                    //Nested foreaches fail in PHP 5.2.1
                    key($params);
                    $ret = $params[$i]->detectDependencies($params);
                    if (PEAR::isError($ret)) {
                        $reverify = true;
                        $params[$i] = false;
                        PEAR_Downloader_Package::removeDuplicates($params);
                        if (!isset($this->_options['soft'])) {
                            $this->log(0, $ret->getMessage());
                        }
                        continue 2;
                    }
                }
            }
        }

        if (isset($this->_options['offline'])) {
            $this->log(3, 'Skipping dependency download check, --offline specified');
        }

        if (!count($params)) {
            $a = array();
            return $a;
        }

        while (PEAR_Downloader_Package::mergeDependencies($params));
        PEAR_Downloader_Package::removeDuplicates($params, true);
        $errorparams = array();
        if (PEAR_Downloader_Package::detectStupidDuplicates($params, $errorparams)) {
            if (count($errorparams)) {
                foreach ($errorparams as $param) {
                    $name = $this->_registry->parsedPackageNameToString($param->getParsedPackage());
                    $this->pushError('Duplicate package ' . $name . ' found', PEAR_INSTALLER_FAILED);
                }
                $a = array();
                return $a;
            }
        }

        PEAR_Downloader_Package::removeInstalled($params);
        if (!count($params)) {
            $this->pushError('No valid packages found', PEAR_INSTALLER_FAILED);
            $a = array();
            return $a;
        }

        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        $err = $this->analyzeDependencies($params);
        PEAR::popErrorHandling();
        if (!count($params)) {
            $this->pushError('No valid packages found', PEAR_INSTALLER_FAILED);
            $a = array();
            return $a;
        }

        $ret = array();
        $newparams = array();
        if (isset($this->_options['pretend'])) {
            return $params;
        }

        $somefailed = false;
        foreach ($params as $i => $package) {
            PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
            $pf = &$params[$i]->download();
            PEAR::staticPopErrorHandling();
            if (PEAR::isError($pf)) {
                if (!isset($this->_options['soft'])) {
                    $this->log(1, $pf->getMessage());
                    $this->log(0, 'Error: cannot download "' .
                        $this->_registry->parsedPackageNameToString($package->getParsedPackage(),
                            true) .
                        '"');
                }
                $somefailed = true;
                continue;
            }

            $newparams[] = &$params[$i];
            $ret[] = array(
                'file' => $pf->getArchiveFile(),
                'info' => &$pf,
                'pkg'  => $pf->getPackage()
            );
        }

        if ($somefailed) {
            // remove params that did not download successfully
            PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
            $err = $this->analyzeDependencies($newparams, true);
            PEAR::popErrorHandling();
            if (!count($newparams)) {
                $this->pushError('Download failed', PEAR_INSTALLER_FAILED);
                $a = array();
                return $a;
            }
        }

        $this->_downloadedPackages = $ret;
        return $newparams;
    }

    /**
     * @param array all packages to be installed
     */
    function analyzeDependencies(&$params, $force = false)
    {
        if (isset($this->_options['downloadonly'])) {
            return;
        }

        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        $redo  = true;
        $reset = $hasfailed = $failed = false;
        while ($redo) {
            $redo = false;
            foreach ($params as $i => $param) {
                $deps = $param->getDeps();
                if (!$deps) {
                    $depchecker = &$this->getDependency2Object($this->config, $this->getOptions(),
                        $param->getParsedPackage(), PEAR_VALIDATE_DOWNLOADING);
                    $send = $param->getPackageFile();

                    $installcheck = $depchecker->validatePackage($send, $this, $params);
                    if (PEAR::isError($installcheck)) {
                        if (!isset($this->_options['soft'])) {
                            $this->log(0, $installcheck->getMessage());
                        }
                        $hasfailed  = true;
                        $params[$i] = false;
                        $reset      = true;
                        $redo       = true;
                        $failed     = false;
                        PEAR_Downloader_Package::removeDuplicates($params);
                        continue 2;
                    }
                    continue;
                }

                if (!$reset && $param->alreadyValidated() && !$force) {
                    continue;
                }

                if (count($deps)) {
                    $depchecker = &$this->getDependency2Object($this->config, $this->getOptions(),
                        $param->getParsedPackage(), PEAR_VALIDATE_DOWNLOADING);
                    $send = $param->getPackageFile();
                    if ($send === null) {
                        $send = $param->getDownloadURL();
                    }

                    $installcheck = $depchecker->validatePackage($send, $this, $params);
                    if (PEAR::isError($installcheck)) {
                        if (!isset($this->_options['soft'])) {
                            $this->log(0, $installcheck->getMessage());
                        }
                        $hasfailed  = true;
                        $params[$i] = false;
                        $reset      = true;
                        $redo       = true;
                        $failed     = false;
                        PEAR_Downloader_Package::removeDuplicates($params);
                        continue 2;
                    }

                    $failed = false;
                    if (isset($deps['required']) && is_array($deps['required'])) {
                        foreach ($deps['required'] as $type => $dep) {
                            // note: Dependency2 will never return a PEAR_Error if ignore-errors
                            // is specified, so soft is needed to turn off logging
                            if (!isset($dep[0])) {
                                if (PEAR::isError($e = $depchecker->{"validate{$type}Dependency"}($dep,
                                      true, $params))) {
                                    $failed = true;
                                    if (!isset($this->_options['soft'])) {
                                        $this->log(0, $e->getMessage());
                                    }
                                } elseif (is_array($e) && !$param->alreadyValidated()) {
                                    if (!isset($this->_options['soft'])) {
                                        $this->log(0, $e[0]);
                                    }
                                }
                            } else {
                                foreach ($dep as $d) {
                                    if (PEAR::isError($e =
                                          $depchecker->{"validate{$type}Dependency"}($d,
                                          true, $params))) {
                                        $failed = true;
                                        if (!isset($this->_options['soft'])) {
                                            $this->log(0, $e->getMessage());
                                        }
                                    } elseif (is_array($e) && !$param->alreadyValidated()) {
                                        if (!isset($this->_options['soft'])) {
                                            $this->log(0, $e[0]);
                                        }
                                    }
                                }
                            }
                        }

                        if (isset($deps['optional']) && is_array($deps['optional'])) {
                            foreach ($deps['optional'] as $type => $dep) {
                                if (!isset($dep[0])) {
                                    if (PEAR::isError($e =
                                          $depchecker->{"validate{$type}Dependency"}($dep,
                                          false, $params))) {
                                        $failed = true;
                                        if (!isset($this->_options['soft'])) {
                                            $this->log(0, $e->getMessage());
                                        }
                                    } elseif (is_array($e) && !$param->alreadyValidated()) {
                                        if (!isset($this->_options['soft'])) {
                                            $this->log(0, $e[0]);
                                        }
                                    }
                                } else {
                                    foreach ($dep as $d) {
                                        if (PEAR::isError($e =
                                              $depchecker->{"validate{$type}Dependency"}($d,
                                              false, $params))) {
                                            $failed = true;
                                            if (!isset($this->_options['soft'])) {
                                                $this->log(0, $e->getMessage());
                                            }
                                        } elseif (is_array($e) && !$param->alreadyValidated()) {
                                            if (!isset($this->_options['soft'])) {
                                                $this->log(0, $e[0]);
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        $groupname = $param->getGroup();
                        if (isset($deps['group']) && $groupname) {
                            if (!isset($deps['group'][0])) {
                                $deps['group'] = array($deps['group']);
                            }

                            $found = false;
                            foreach ($deps['group'] as $group) {
                                if ($group['attribs']['name'] == $groupname) {
                                    $found = true;
                                    break;
                                }
                            }

                            if ($found) {
                                unset($group['attribs']);
                                foreach ($group as $type => $dep) {
                                    if (!isset($dep[0])) {
                                        if (PEAR::isError($e =
                                              $depchecker->{"validate{$type}Dependency"}($dep,
                                              false, $params))) {
                                            $failed = true;
                                            if (!isset($this->_options['soft'])) {
                                                $this->log(0, $e->getMessage());
                                            }
                                        } elseif (is_array($e) && !$param->alreadyValidated()) {
                                            if (!isset($this->_options['soft'])) {
                                                $this->log(0, $e[0]);
                                            }
                                        }
                                    } else {
                                        foreach ($dep as $d) {
                                            if (PEAR::isError($e =
                                                  $depchecker->{"validate{$type}Dependency"}($d,
                                                  false, $params))) {
                                                $failed = true;
                                                if (!isset($this->_options['soft'])) {
                                                    $this->log(0, $e->getMessage());
                                                }
                                            } elseif (is_array($e) && !$param->alreadyValidated()) {
                                                if (!isset($this->_options['soft'])) {
                                                    $this->log(0, $e[0]);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    } else {
                        foreach ($deps as $dep) {
                            if (PEAR::isError($e = $depchecker->validateDependency1($dep, $params))) {
                                $failed = true;
                                if (!isset($this->_options['soft'])) {
                                    $this->log(0, $e->getMessage());
                                }
                            } elseif (is_array($e) && !$param->alreadyValidated()) {
                                if (!isset($this->_options['soft'])) {
                                    $this->log(0, $e[0]);
                                }
                            }
                        }
                    }
                    $params[$i]->setValidated();
                }

                if ($failed) {
                    $hasfailed  = true;
                    $params[$i] = false;
                    $reset      = true;
                    $redo       = true;
                    $failed     = false;
                    PEAR_Downloader_Package::removeDuplicates($params);
                    continue 2;
                }
            }
        }

        PEAR::staticPopErrorHandling();
        if ($hasfailed && (isset($this->_options['ignore-errors']) ||
              isset($this->_options['nodeps']))) {
            // this is probably not needed, but just in case
            if (!isset($this->_options['soft'])) {
                $this->log(0, 'WARNING: dependencies failed');
            }
        }
    }

    /**
     * Retrieve the directory that downloads will happen in
     * @access private
     * @return string
     */
    function getDownloadDir()
    {
        if (isset($this->_downloadDir)) {
            return $this->_downloadDir;
        }

        $downloaddir = $this->config->get('download_dir');
        if (empty($downloaddir) || (is_dir($downloaddir) && !is_writable($downloaddir))) {
            if  (is_dir($downloaddir) && !is_writable($downloaddir)) {
                $this->log(0, 'WARNING: configuration download directory "' . $downloaddir .
                    '" is not writeable.  Change download_dir config variable to ' .
                    'a writeable dir to avoid this warning');
            }

            if (!class_exists('System')) {
                require_once 'System.php';
            }

            if (PEAR::isError($downloaddir = System::mktemp('-d'))) {
                return $downloaddir;
            }
            $this->log(3, '+ tmp dir created at ' . $downloaddir);
        }

        if (!is_writable($downloaddir)) {
            if (PEAR::isError(System::mkdir(array('-p', $downloaddir))) ||
                  !is_writable($downloaddir)) {
                return PEAR::raiseError('download directory "' . $downloaddir .
                    '" is not writeable.  Change download_dir config variable to ' .
                    'a writeable dir');
            }
        }

        return $this->_downloadDir = $downloaddir;
    }

    function setDownloadDir($dir)
    {
        if (!@is_writable($dir)) {
            if (PEAR::isError(System::mkdir(array('-p', $dir)))) {
                return PEAR::raiseError('download directory "' . $dir .
                    '" is not writeable.  Change download_dir config variable to ' .
                    'a writeable dir');
            }
        }
        $this->_downloadDir = $dir;
    }

    function configSet($key, $value, $layer = 'user', $channel = false)
    {
        $this->config->set($key, $value, $layer, $channel);
        $this->_preferredState = $this->config->get('preferred_state', null, $channel);
        if (!$this->_preferredState) {
            // don't inadvertently use a non-set preferred_state
            $this->_preferredState = null;
        }
    }

    function setOptions($options)
    {
        $this->_options = $options;
    }

    function getOptions()
    {
        return $this->_options;
    }


    /**
     * @param array output of {@link parsePackageName()}
     * @access private
     */
    function _getPackageDownloadUrl($parr)
    {
        $curchannel = $this->config->get('default_channel');
        $this->configSet('default_channel', $parr['channel']);
        // getDownloadURL returns an array.  On error, it only contains information
        // on the latest release as array(version, info).  On success it contains
        // array(version, info, download url string)
        $state = isset($parr['state']) ? $parr['state'] : $this->config->get('preferred_state');
        if (!$this->_registry->channelExists($parr['channel'])) {
            do {
                if ($this->config->get('auto_discover') && $this->discover($parr['channel'])) {
                    break;
                }

                $this->configSet('default_channel', $curchannel);
                return PEAR::raiseError('Unknown remote channel: ' . $parr['channel']);
            } while (false);
        }

        $chan = $this->_registry->getChannel($parr['channel']);
        if (PEAR::isError($chan)) {
            return $chan;
        }

        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        $version   = $this->_registry->packageInfo($parr['package'], 'version', $parr['channel']);
        $stability = $this->_registry->packageInfo($parr['package'], 'stability', $parr['channel']);
        // package is installed - use the installed release stability level
        if (!isset($parr['state']) && $stability !== null) {
            $state = $stability['release'];
        }
        PEAR::staticPopErrorHandling();
        $base2 = false;

        $preferred_mirror = $this->config->get('preferred_mirror');
        if (!$chan->supportsREST($preferred_mirror) ||
              (
               !($base2 = $chan->getBaseURL('REST1.3', $preferred_mirror))
               &&
               !($base = $chan->getBaseURL('REST1.0', $preferred_mirror))
              )
        ) {
            return $this->raiseError($parr['channel'] . ' is using an unsupported protocol - This should never happen. Use --force to continue');
        }

        if ($base2) {
            $rest = &$this->config->getREST('1.3', $this->_options);
            $base = $base2;
        } else {
            $rest = &$this->config->getREST('1.0', $this->_options);
        }

        $downloadVersion = false;
        if (!isset($parr['version']) && !isset($parr['state']) && $version
              && !PEAR::isError($version)
              && !isset($this->_options['downloadonly'])
        ) {
            $downloadVersion = $version;
        }

        $url = $rest->getDownloadURL($base, $parr, $state, $downloadVersion, $chan->getName());
        if (PEAR::isError($url)) {
            $this->configSet('default_channel', $curchannel);
            return $url;
        }

        if ($parr['channel'] != $curchannel) {
            $this->configSet('default_channel', $curchannel);
        }

        if (!is_array($url)) {
            return $url;
        }

        $url['raw'] = false; // no checking is necessary for REST
        if (!is_array($url['info'])) {
            return PEAR::raiseError('Invalid remote dependencies retrieved from REST - ' .
                'this should never happen');
        }

        if (!isset($this->_options['force']) &&
              !isset($this->_options['downloadonly']) &&
              $version &&
              !PEAR::isError($version) &&
              !isset($parr['group'])
        ) {
            if (version_compare($version, $url['version'], '=')) {
                return PEAR::raiseError($this->_registry->parsedPackageNameToString(
                    $parr, true) . ' is already installed and is the same as the ' .
                    'released version ' . $url['version'], -976);
            }

            if (version_compare($version, $url['version'], '>')) {
                return PEAR::raiseError($this->_registry->parsedPackageNameToString(
                    $parr, true) . ' is already installed and is newer than detected ' .
                    'released version ' . $url['version'], -976);
            }
        }

        if (isset($url['info']['required']) || $url['compatible']) {
            require_once 'PEAR/PackageFile/v2.php';
            $pf = new PEAR_PackageFile_v2;
            $pf->setRawChannel($parr['channel']);
            if ($url['compatible']) {
                $pf->setRawCompatible($url['compatible']);
            }
        } else {
            require_once 'PEAR/PackageFile/v1.php';
            $pf = new PEAR_PackageFile_v1;
        }

        $pf->setRawPackage($url['package']);
        $pf->setDeps($url['info']);
        if ($url['compatible']) {
            $pf->setCompatible($url['compatible']);
        }

        $pf->setRawState($url['stability']);
        $url['info'] = &$pf;
        if (!extension_loaded("zlib") || isset($this->_options['nocompress'])) {
            $ext = '.tar';
        } else {
            $ext = '.tgz';
        }

        if (is_array($url) && isset($url['url'])) {
            $url['url'] .= $ext;
        }

        return $url;
    }

    /**
     * @param array dependency array
     * @access private
     */
    function _getDepPackageDownloadUrl($dep, $parr)
    {
        $xsdversion = isset($dep['rel']) ? '1.0' : '2.0';
        $curchannel = $this->config->get('default_channel');
        if (isset($dep['uri'])) {
            $xsdversion = '2.0';
            $chan = $this->_registry->getChannel('__uri');
            if (PEAR::isError($chan)) {
                return $chan;
            }

            $version = $this->_registry->packageInfo($dep['name'], 'version', '__uri');
            $this->configSet('default_channel', '__uri');
        } else {
            if (isset($dep['channel'])) {
                $remotechannel = $dep['channel'];
            } else {
                $remotechannel = 'pear.php.net';
            }

            if (!$this->_registry->channelExists($remotechannel)) {
                do {
                    if ($this->config->get('auto_discover')) {
                        if ($this->discover($remotechannel)) {
                            break;
                        }
                    }
                    return PEAR::raiseError('Unknown remote channel: ' . $remotechannel);
                } while (false);
            }

            $chan = $this->_registry->getChannel($remotechannel);
            if (PEAR::isError($chan)) {
                return $chan;
            }

            $version = $this->_registry->packageInfo($dep['name'], 'version', $remotechannel);
            $this->configSet('default_channel', $remotechannel);
        }

        $state = isset($parr['state']) ? $parr['state'] : $this->config->get('preferred_state');
        if (isset($parr['state']) && isset($parr['version'])) {
            unset($parr['state']);
        }

        if (isset($dep['uri'])) {
            $info = $this->newDownloaderPackage($this);
            PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
            $err = $info->initialize($dep);
            PEAR::staticPopErrorHandling();
            if (!$err) {
                // skip parameters that were missed by preferred_state
                return PEAR::raiseError('Cannot initialize dependency');
            }

            if (PEAR::isError($err)) {
                if (!isset($this->_options['soft'])) {
                    $this->log(0, $err->getMessage());
                }

                if (is_object($info)) {
                    $param = $info->getChannel() . '/' . $info->getPackage();
                }
                return PEAR::raiseError('Package "' . $param . '" is not valid');
            }
            return $info;
        } elseif ($chan->supportsREST($this->config->get('preferred_mirror'))
              &&
                (
                  ($base2 = $chan->getBaseURL('REST1.3', $this->config->get('preferred_mirror')))
                    ||
                  ($base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror')))
                )
        ) {
            if ($base2) {
                $base = $base2;
                $rest = &$this->config->getREST('1.3', $this->_options);
            } else {
                $rest = &$this->config->getREST('1.0', $this->_options);
            }

            $url = $rest->getDepDownloadURL($base, $xsdversion, $dep, $parr,
                    $state, $version, $chan->getName());
            if (PEAR::isError($url)) {
                return $url;
            }

            if ($parr['channel'] != $curchannel) {
                $this->configSet('default_channel', $curchannel);
            }

            if (!is_array($url)) {
                return $url;
            }

            $url['raw'] = false; // no checking is necessary for REST
            if (!is_array($url['info'])) {
                return PEAR::raiseError('Invalid remote dependencies retrieved from REST - ' .
                    'this should never happen');
            }

            if (isset($url['info']['required'])) {
                if (!class_exists('PEAR_PackageFile_v2')) {
                    require_once 'PEAR/PackageFile/v2.php';
                }
                $pf = new PEAR_PackageFile_v2;
                $pf->setRawChannel($remotechannel);
            } else {
                if (!class_exists('PEAR_PackageFile_v1')) {
                    require_once 'PEAR/PackageFile/v1.php';
                }
                $pf = new PEAR_PackageFile_v1;

            }
            $pf->setRawPackage($url['package']);
            $pf->setDeps($url['info']);
            if ($url['compatible']) {
                $pf->setCompatible($url['compatible']);
            }

            $pf->setRawState($url['stability']);
            $url['info'] = &$pf;
            if (!extension_loaded("zlib") || isset($this->_options['nocompress'])) {
                $ext = '.tar';
            } else {
                $ext = '.tgz';
            }

            if (is_array($url) && isset($url['url'])) {
                $url['url'] .= $ext;
            }

            return $url;
        }

        return $this->raiseError($parr['channel'] . ' is using a unsupported protocol - This should never happen.');
    }

    /**
     * @deprecated in favor of _getPackageDownloadUrl
     */
    function getPackageDownloadUrl($package, $version = null, $channel = false)
    {
        if ($version) {
            $package .= "-$version";
        }
        if ($this === null || $this->_registry === null) {
            $package = "http://pear.php.net/get/$package";
        } else {
            $chan = $this->_registry->getChannel($channel);
            if (PEAR::isError($chan)) {
                return '';
            }
            $package = "http://" . $chan->getServer() . "/get/$package";
        }
        if (!extension_loaded("zlib")) {
            $package .= '?uncompress=yes';
        }
        return $package;
    }

    /**
     * Retrieve a list of downloaded packages after a call to {@link download()}.
     *
     * Also resets the list of downloaded packages.
     * @return array
     */
    function getDownloadedPackages()
    {
        $ret = $this->_downloadedPackages;
        $this->_downloadedPackages = array();
        $this->_toDownload = array();
        return $ret;
    }

    function _downloadCallback($msg, $params = null)
    {
        switch ($msg) {
            case 'saveas':
                $this->log(1, "downloading $params ...");
                break;
            case 'done':
                $this->log(1, '...done: ' . number_format($params, 0, '', ',') . ' bytes');
                break;
            case 'bytesread':
                static $bytes;
                if (empty($bytes)) {
                    $bytes = 0;
                }
                if (!($bytes % 10240)) {
                    $this->log(1, '.', false);
                }
                $bytes += $params;
                break;
            case 'start':
                if($params[1] == -1) {
                    $length = "Unknown size";
                } else {
                    $length = number_format($params[1], 0, '', ',')." bytes";
                }
                $this->log(1, "Starting to download {$params[0]} ($length)");
                break;
        }
        if (method_exists($this->ui, '_downloadCallback'))
            $this->ui->_downloadCallback($msg, $params);
    }

    function _prependPath($path, $prepend)
    {
        if (strlen($prepend) > 0) {
            if (OS_WINDOWS && preg_match('/^[a-z]:/i', $path)) {
                if (preg_match('/^[a-z]:/i', $prepend)) {
                    $prepend = substr($prepend, 2);
                } elseif ($prepend[0] != '\\') {
                    $prepend = "\\$prepend";
                }
                $path = substr($path, 0, 2) . $prepend . substr($path, 2);
            } else {
                $path = $prepend . $path;
            }
        }
        return $path;
    }

    /**
     * @param string
     * @param integer
     */
    function pushError($errmsg, $code = -1)
    {
        array_push($this->_errorStack, array($errmsg, $code));
    }

    function getErrorMsgs()
    {
        $msgs = array();
        $errs = $this->_errorStack;
        foreach ($errs as $err) {
            $msgs[] = $err[0];
        }
        $this->_errorStack = array();
        return $msgs;
    }

    /**
     * for BC
     *
     * @deprecated
     */
    function sortPkgDeps(&$packages, $uninstall = false)
    {
        $uninstall ?
            $this->sortPackagesForUninstall($packages) :
            $this->sortPackagesForInstall($packages);
    }

    /**
     * Sort a list of arrays of array(downloaded packagefilename) by dependency.
     *
     * This uses the topological sort method from graph theory, and the
     * Structures_Graph package to properly sort dependencies for installation.
     * @param array an array of downloaded PEAR_Downloader_Packages
     * @return array array of array(packagefilename, package.xml contents)
     */
    function sortPackagesForInstall(&$packages)
    {
        require_once 'Structures/Graph.php';
        require_once 'Structures/Graph/Node.php';
        require_once 'Structures/Graph/Manipulator/TopologicalSorter.php';
        $depgraph = new Structures_Graph(true);
        $nodes = array();
        $reg = &$this->config->getRegistry();
        foreach ($packages as $i => $package) {
            $pname = $reg->parsedPackageNameToString(
                array(
                    'channel' => $package->getChannel(),
                    'package' => strtolower($package->getPackage()),
                ));
            $nodes[$pname] = new Structures_Graph_Node;
            $nodes[$pname]->setData($packages[$i]);
            $depgraph->addNode($nodes[$pname]);
        }

        $deplinks = array();
        foreach ($nodes as $package => $node) {
            $pf = &$node->getData();
            $pdeps = $pf->getDeps(true);
            if (!$pdeps) {
                continue;
            }

            if ($pf->getPackagexmlVersion() == '1.0') {
                foreach ($pdeps as $dep) {
                    if ($dep['type'] != 'pkg' ||
                          (isset($dep['optional']) && $dep['optional'] == 'yes')) {
                        continue;
                    }

                    $dname = $reg->parsedPackageNameToString(
                          array(
                              'channel' => 'pear.php.net',
                              'package' => strtolower($dep['name']),
                          ));

                    if (isset($nodes[$dname])) {
                        if (!isset($deplinks[$dname])) {
                            $deplinks[$dname] = array();
                        }

                        $deplinks[$dname][$package] = 1;
                        // dependency is in installed packages
                        continue;
                    }

                    $dname = $reg->parsedPackageNameToString(
                          array(
                              'channel' => 'pecl.php.net',
                              'package' => strtolower($dep['name']),
                          ));

                    if (isset($nodes[$dname])) {
                        if (!isset($deplinks[$dname])) {
                            $deplinks[$dname] = array();
                        }

                        $deplinks[$dname][$package] = 1;
                        // dependency is in installed packages
                        continue;
                    }
                }
            } else {
                // the only ordering we care about is:
                // 1) subpackages must be installed before packages that depend on them
                // 2) required deps must be installed before packages that depend on them
                if (isset($pdeps['required']['subpackage'])) {
                    $t = $pdeps['required']['subpackage'];
                    if (!isset($t[0])) {
                        $t = array($t);
                    }

                    $this->_setupGraph($t, $reg, $deplinks, $nodes, $package);
                }

                if (isset($pdeps['group'])) {
                    if (!isset($pdeps['group'][0])) {
                        $pdeps['group'] = array($pdeps['group']);
                    }

                    foreach ($pdeps['group'] as $group) {
                        if (isset($group['subpackage'])) {
                            $t = $group['subpackage'];
                            if (!isset($t[0])) {
                                $t = array($t);
                            }

                            $this->_setupGraph($t, $reg, $deplinks, $nodes, $package);
                        }
                    }
                }

                if (isset($pdeps['optional']['subpackage'])) {
                    $t = $pdeps['optional']['subpackage'];
                    if (!isset($t[0])) {
                        $t = array($t);
                    }

                    $this->_setupGraph($t, $reg, $deplinks, $nodes, $package);
                }

                if (isset($pdeps['required']['package'])) {
                    $t = $pdeps['required']['package'];
                    if (!isset($t[0])) {
                        $t = array($t);
                    }

                    $this->_setupGraph($t, $reg, $deplinks, $nodes, $package);
                }

                if (isset($pdeps['group'])) {
                    if (!isset($pdeps['group'][0])) {
                        $pdeps['group'] = array($pdeps['group']);
                    }

                    foreach ($pdeps['group'] as $group) {
                        if (isset($group['package'])) {
                            $t = $group['package'];
                            if (!isset($t[0])) {
                                $t = array($t);
                            }

                            $this->_setupGraph($t, $reg, $deplinks, $nodes, $package);
                        }
                    }
                }
            }
        }

        $this->_detectDepCycle($deplinks);
        foreach ($deplinks as $dependent => $parents) {
            foreach ($parents as $parent => $unused) {
                $nodes[$dependent]->connectTo($nodes[$parent]);
            }
        }

        $installOrder = Structures_Graph_Manipulator_TopologicalSorter::sort($depgraph);
        $ret = array();
        for ($i = 0, $count = count($installOrder); $i < $count; $i++) {
            foreach ($installOrder[$i] as $index => $sortedpackage) {
                $data = &$installOrder[$i][$index]->getData();
                $ret[] = &$nodes[$reg->parsedPackageNameToString(
                          array(
                              'channel' => $data->getChannel(),
                              'package' => strtolower($data->getPackage()),
                          ))]->getData();
            }
        }

        $packages = $ret;
        return;
    }

    /**
     * Detect recursive links between dependencies and break the cycles
     *
     * @param array
     * @access private
     */
    function _detectDepCycle(&$deplinks)
    {
        do {
            $keepgoing = false;
            foreach ($deplinks as $dep => $parents) {
                foreach ($parents as $parent => $unused) {
                    // reset the parent cycle detector
                    $this->_testCycle(null, null, null);
                    if ($this->_testCycle($dep, $deplinks, $parent)) {
                        $keepgoing = true;
                        unset($deplinks[$dep][$parent]);
                        if (count($deplinks[$dep]) == 0) {
                            unset($deplinks[$dep]);
                        }

                        continue 3;
                    }
                }
            }
        } while ($keepgoing);
    }

    function _testCycle($test, $deplinks, $dep)
    {
        static $visited = array();
        if ($test === null) {
            $visited = array();
            return;
        }

        // this happens when a parent has a dep cycle on another dependency
        // but the child is not part of the cycle
        if (isset($visited[$dep])) {
            return false;
        }

        $visited[$dep] = 1;
        if ($test == $dep) {
            return true;
        }

        if (isset($deplinks[$dep])) {
            if (in_array($test, array_keys($deplinks[$dep]), true)) {
                return true;
            }

            foreach ($deplinks[$dep] as $parent => $unused) {
                if ($this->_testCycle($test, $deplinks, $parent)) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * Set up the dependency for installation parsing
     *
     * @param array $t dependency information
     * @param PEAR_Registry $reg
     * @param array $deplinks list of dependency links already established
     * @param array $nodes all existing package nodes
     * @param string $package parent package name
     * @access private
     */
    function _setupGraph($t, $reg, &$deplinks, &$nodes, $package)
    {
        foreach ($t as $dep) {
            $depchannel = !isset($dep['channel']) ? '__uri': $dep['channel'];
            $dname = $reg->parsedPackageNameToString(
                  array(
                      'channel' => $depchannel,
                      'package' => strtolower($dep['name']),
                  ));

            if (isset($nodes[$dname])) {
                if (!isset($deplinks[$dname])) {
                    $deplinks[$dname] = array();
                }
                $deplinks[$dname][$package] = 1;
            }
        }
    }

    function _dependsOn($a, $b)
    {
        return $this->_checkDepTree(strtolower($a->getChannel()), strtolower($a->getPackage()), $b);
    }

    function _checkDepTree($channel, $package, $b, $checked = array())
    {
        $checked[$channel][$package] = true;
        if (!isset($this->_depTree[$channel][$package])) {
            return false;
        }

        if (isset($this->_depTree[$channel][$package][strtolower($b->getChannel())]
              [strtolower($b->getPackage())])) {
            return true;
        }

        foreach ($this->_depTree[$channel][$package] as $ch => $packages) {
            foreach ($packages as $pa => $true) {
                if ($this->_checkDepTree($ch, $pa, $b, $checked)) {
                    return true;
                }
            }
        }

        return false;
    }

    function _sortInstall($a, $b)
    {
        if (!$a->getDeps() && !$b->getDeps()) {
            return 0; // neither package has dependencies, order is insignificant
        }
        if ($a->getDeps() && !$b->getDeps()) {
            return 1; // $a must be installed after $b because $a has dependencies
        }
        if (!$a->getDeps() && $b->getDeps()) {
            return -1; // $b must be installed after $a because $b has dependencies
        }
        // both packages have dependencies
        if ($this->_dependsOn($a, $b)) {
            return 1;
        }
        if ($this->_dependsOn($b, $a)) {
            return -1;
        }
        return 0;
    }

    /**
     * Download a file through HTTP.  Considers suggested file name in
     * Content-disposition: header and can run a callback function for
     * different events.  The callback will be called with two
     * parameters: the callback type, and parameters.  The implemented
     * callback types are:
     *
     *  'setup'       called at the very beginning, parameter is a UI object
     *                that should be used for all output
     *  'message'     the parameter is a string with an informational message
     *  'saveas'      may be used to save with a different file name, the
     *                parameter is the filename that is about to be used.
     *                If a 'saveas' callback returns a non-empty string,
     *                that file name will be used as the filename instead.
     *                Note that $save_dir will not be affected by this, only
     *                the basename of the file.
     *  'start'       download is starting, parameter is number of bytes
     *                that are expected, or -1 if unknown
     *  'bytesread'   parameter is the number of bytes read so far
     *  'done'        download is complete, parameter is the total number
     *                of bytes read
     *  'connfailed'  if the TCP/SSL connection fails, this callback is called
     *                with array(host,port,errno,errmsg)
     *  'writefailed' if writing to disk fails, this callback is called
     *                with array(destfile,errmsg)
     *
     * If an HTTP proxy has been configured (http_proxy PEAR_Config
     * setting), the proxy will be used.
     *
     * @param string  $url       the URL to download
     * @param object  $ui        PEAR_Frontend_* instance
     * @param object  $config    PEAR_Config instance
     * @param string  $save_dir  directory to save file in
     * @param mixed   $callback  function/method to call for status
     *                           updates
     * @param false|string|array $lastmodified header values to check against for caching
     *                           use false to return the header values from this download
     * @param false|array $accept Accept headers to send
     * @param false|string $channel Channel to use for retrieving authentication
     * @return mixed  Returns the full path of the downloaded file or a PEAR
     *                error on failure.  If the error is caused by
     *                socket-related errors, the error object will
     *                have the fsockopen error code available through
     *                getCode().  If caching is requested, then return the header
     *                values.
     *                If $lastmodified was given and the there are no changes,
     *                boolean false is returned.
     *
     * @access public
     */
    public static function _downloadHttp(
        $object, $url, &$ui, $save_dir = '.', $callback = null, $lastmodified = null,
        $accept = false, $channel = false
    ) {
        static $redirect = 0;
        // always reset , so we are clean case of error
        $wasredirect = $redirect;
        $redirect = 0;
        if ($callback) {
            call_user_func($callback, 'setup', array(&$ui));
        }

        $info = parse_url($url);
        if (!isset($info['scheme']) || !in_array($info['scheme'], array('http', 'https'))) {
            return PEAR::raiseError('Cannot download non-http URL "' . $url . '"');
        }

        if (!isset($info['host'])) {
            return PEAR::raiseError('Cannot download from non-URL "' . $url . '"');
        }

        $host = isset($info['host']) ? $info['host'] : null;
        $port = isset($info['port']) ? $info['port'] : null;
        $path = isset($info['path']) ? $info['path'] : null;

        if ($object !== null) {
            $config = $object->config;
        } else {
            $config = &PEAR_Config::singleton();
        }

        $proxy = new PEAR_Proxy($config);

        if ($proxy->isProxyConfigured() && $callback) {
            call_user_func($callback, 'message', "Using HTTP proxy $host:$port");
        }

        if (empty($port)) {
            $port = (isset($info['scheme']) && $info['scheme'] == 'https') ? 443 : 80;
        }

        $scheme = (isset($info['scheme']) && $info['scheme'] == 'https') ? 'https' : 'http';
        $secure = ($scheme == 'https');

        $fp = $proxy->openSocket($host, $port, $secure);
        if (PEAR::isError($fp)) {
            if ($callback) {
                $errno = $fp->getCode();
                $errstr = $fp->getMessage();
                call_user_func($callback, 'connfailed', array($host, $port,
                                                              $errno, $errstr));
            }
            return $fp;
        }

        $requestPath = $path;
        if ($proxy->isProxyConfigured()) {
            $requestPath = $url;
        }

        if ($lastmodified === false || $lastmodified) {
            $request  = "GET $requestPath HTTP/1.1\r\n";
        } else {
            $request  = "GET $requestPath HTTP/1.0\r\n";
        }
        $request .= "Host: $host\r\n";

        $ifmodifiedsince = '';
        if (is_array($lastmodified)) {
            if (isset($lastmodified['Last-Modified'])) {
                $ifmodifiedsince = 'If-Modified-Since: ' . $lastmodified['Last-Modified'] . "\r\n";
            }

            if (isset($lastmodified['ETag'])) {
                $ifmodifiedsince .= "If-None-Match: $lastmodified[ETag]\r\n";
            }
        } else {
            $ifmodifiedsince = ($lastmodified ? "If-Modified-Since: $lastmodified\r\n" : '');
        }

        $request .= $ifmodifiedsince .
            "User-Agent: PEAR/1.10.16/PHP/" . PHP_VERSION . "\r\n";

        if ($object !== null) { // only pass in authentication for non-static calls
            $username = $config->get('username', null, $channel);
            $password = $config->get('password', null, $channel);
            if ($username && $password) {
                $tmp = base64_encode("$username:$password");
                $request .= "Authorization: Basic $tmp\r\n";
            }
        }

        $proxyAuth = $proxy->getProxyAuth();
        if ($proxyAuth) {
            $request .= 'Proxy-Authorization: Basic ' .
                $proxyAuth . "\r\n";
        }

        if ($accept) {
            $request .= 'Accept: ' . implode(', ', $accept) . "\r\n";
        }

        $request .= "Connection: close\r\n";
        $request .= "\r\n";
        fwrite($fp, $request);
        $headers = array();
        $reply = 0;
        while (trim($line = fgets($fp, 1024))) {
            if (preg_match('/^([^:]+):\s+(.*)\s*\\z/', $line, $matches)) {
                $headers[strtolower($matches[1])] = trim($matches[2]);
            } elseif (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) {
                $reply = (int)$matches[1];
                if ($reply == 304 && ($lastmodified || ($lastmodified === false))) {
                    return false;
                }

                if (!in_array($reply, array(200, 301, 302, 303, 305, 307))) {
                    return PEAR::raiseError("File $scheme://$host:$port$path not valid (received: $line)");
                }
            }
        }

        if ($reply != 200) {
            if (!isset($headers['location'])) {
                return PEAR::raiseError("File $scheme://$host:$port$path not valid (redirected but no location)");
            }

            if ($wasredirect > 4) {
                return PEAR::raiseError("File $scheme://$host:$port$path not valid (redirection looped more than 5 times)");
            }

            $redirect = $wasredirect + 1;
            return static::_downloadHttp($object, $headers['location'],
                    $ui, $save_dir, $callback, $lastmodified, $accept);
        }

        if (isset($headers['content-disposition']) &&
            preg_match('/\sfilename=\"([^;]*\S)\"\s*(;|\\z)/', $headers['content-disposition'], $matches)) {
            $save_as = basename($matches[1]);
        } else {
            $save_as = basename($url);
        }

        if ($callback) {
            $tmp = call_user_func($callback, 'saveas', $save_as);
            if ($tmp) {
                $save_as = $tmp;
            }
        }

        $dest_file = $save_dir . DIRECTORY_SEPARATOR . $save_as;
        if (is_link($dest_file)) {
            return PEAR::raiseError('SECURITY ERROR: Will not write to ' . $dest_file . ' as it is symlinked to ' . readlink($dest_file) . ' - Possible symlink attack');
        }

        if (!$wp = @fopen($dest_file, 'wb')) {
            fclose($fp);
            if ($callback) {
                call_user_func($callback, 'writefailed',
                    array($dest_file, error_get_last()["message"]));
            }
            return PEAR::raiseError("could not open $dest_file for writing");
        }

        $length = isset($headers['content-length']) ? $headers['content-length'] : -1;

        $bytes = 0;
        if ($callback) {
            call_user_func($callback, 'start', array(basename($dest_file), $length));
        }

        while ($data = fread($fp, 1024)) {
            $bytes += strlen($data);
            if ($callback) {
                call_user_func($callback, 'bytesread', $bytes);
            }
            if (!@fwrite($wp, $data)) {
                fclose($fp);
                if ($callback) {
                    call_user_func($callback, 'writefailed',
                        array($dest_file, error_get_last()["message"]));
                }
                return PEAR::raiseError(
                    "$dest_file: write failed (" . error_get_last()["message"] . ")");
            }
        }

        fclose($fp);
        fclose($wp);
        if ($callback) {
            call_user_func($callback, 'done', $bytes);
        }

        if ($lastmodified === false || $lastmodified) {
            if (isset($headers['etag'])) {
                $lastmodified = array('ETag' => $headers['etag']);
            }

            if (isset($headers['last-modified'])) {
                if (is_array($lastmodified)) {
                    $lastmodified['Last-Modified'] = $headers['last-modified'];
                } else {
                    $lastmodified = $headers['last-modified'];
                }
            }
            return array($dest_file, $lastmodified, $headers);
        }
        return $dest_file;
    }
}
PKp�Z�b����PEAR/ErrorStack.phpnu�[���<?php
/**
 * Error Stack Implementation
 * 
 * This is an incredibly simple implementation of a very complex error handling
 * facility.  It contains the ability
 * to track multiple errors from multiple packages simultaneously.  In addition,
 * it can track errors of many levels, save data along with the error, context
 * information such as the exact file, line number, class and function that
 * generated the error, and if necessary, it can raise a traditional PEAR_Error.
 * It has built-in support for PEAR::Log, to log errors as they occur
 * 
 * Since version 0.2alpha, it is also possible to selectively ignore errors,
 * through the use of an error callback, see {@link pushCallback()}
 * 
 * Since version 0.3alpha, it is possible to specify the exception class
 * returned from {@link push()}
 *
 * Since version PEAR1.3.2, ErrorStack no longer instantiates an exception class.  This can
 * still be done quite handily in an error callback or by manipulating the returned array
 * @category   Debugging
 * @package    PEAR_ErrorStack
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  2004-2008 Greg Beaver
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR_ErrorStack
 */

/**
 * Singleton storage
 * 
 * Format:
 * <pre>
 * array(
 *  'package1' => PEAR_ErrorStack object,
 *  'package2' => PEAR_ErrorStack object,
 *  ...
 * )
 * </pre>
 * @access private
 * @global array $GLOBALS['_PEAR_ERRORSTACK_SINGLETON']
 */
$GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] = array();

/**
 * Global error callback (default)
 * 
 * This is only used if set to non-false.  * is the default callback for
 * all packages, whereas specific packages may set a default callback
 * for all instances, regardless of whether they are a singleton or not.
 *
 * To exclude non-singletons, only set the local callback for the singleton
 * @see PEAR_ErrorStack::setDefaultCallback()
 * @access private
 * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK']
 */
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'] = array(
    '*' => false,
);

/**
 * Global Log object (default)
 * 
 * This is only used if set to non-false.  Use to set a default log object for
 * all stacks, regardless of instantiation order or location
 * @see PEAR_ErrorStack::setDefaultLogger()
 * @access private
 * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']
 */
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = false;

/**
 * Global Overriding Callback
 * 
 * This callback will override any error callbacks that specific loggers have set.
 * Use with EXTREME caution
 * @see PEAR_ErrorStack::staticPushCallback()
 * @access private
 * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']
 */
$GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array();

/**#@+
 * One of four possible return values from the error Callback
 * @see PEAR_ErrorStack::_errorCallback()
 */
/**
 * If this is returned, then the error will be both pushed onto the stack
 * and logged.
 */
define('PEAR_ERRORSTACK_PUSHANDLOG', 1);
/**
 * If this is returned, then the error will only be pushed onto the stack,
 * and not logged.
 */
define('PEAR_ERRORSTACK_PUSH', 2);
/**
 * If this is returned, then the error will only be logged, but not pushed
 * onto the error stack.
 */
define('PEAR_ERRORSTACK_LOG', 3);
/**
 * If this is returned, then the error is completely ignored.
 */
define('PEAR_ERRORSTACK_IGNORE', 4);
/**
 * If this is returned, then the error is logged and die() is called.
 */
define('PEAR_ERRORSTACK_DIE', 5);
/**#@-*/

/**
 * Error code for an attempt to instantiate a non-class as a PEAR_ErrorStack in
 * the singleton method.
 */
define('PEAR_ERRORSTACK_ERR_NONCLASS', 1);

/**
 * Error code for an attempt to pass an object into {@link PEAR_ErrorStack::getMessage()}
 * that has no __toString() method
 */
define('PEAR_ERRORSTACK_ERR_OBJTOSTRING', 2);
/**
 * Error Stack Implementation
 *
 * Usage:
 * <code>
 * // global error stack
 * $global_stack = &PEAR_ErrorStack::singleton('MyPackage');
 * // local error stack
 * $local_stack = new PEAR_ErrorStack('MyPackage');
 * </code>
 * @author     Greg Beaver <cellog@php.net>
 * @version    1.10.16
 * @package    PEAR_ErrorStack
 * @category   Debugging
 * @copyright  2004-2008 Greg Beaver
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR_ErrorStack
 */
class PEAR_ErrorStack {
    /**
     * Errors are stored in the order that they are pushed on the stack.
     * @since 0.4alpha Errors are no longer organized by error level.
     * This renders pop() nearly unusable, and levels could be more easily
     * handled in a callback anyway
     * @var array
     * @access private
     */
    var $_errors = array();

    /**
     * Storage of errors by level.
     *
     * Allows easy retrieval and deletion of only errors from a particular level
     * @since PEAR 1.4.0dev
     * @var array
     * @access private
     */
    var $_errorsByLevel = array();

    /**
     * Package name this error stack represents
     * @var string
     * @access protected
     */
    var $_package;
    
    /**
     * Determines whether a PEAR_Error is thrown upon every error addition
     * @var boolean
     * @access private
     */
    var $_compat = false;
    
    /**
     * If set to a valid callback, this will be used to generate the error
     * message from the error code, otherwise the message passed in will be
     * used
     * @var false|string|array
     * @access private
     */
    var $_msgCallback = false;
    
    /**
     * If set to a valid callback, this will be used to generate the error
     * context for an error.  For PHP-related errors, this will be a file
     * and line number as retrieved from debug_backtrace(), but can be
     * customized for other purposes.  The error might actually be in a separate
     * configuration file, or in a database query.
     * @var false|string|array
     * @access protected
     */
    var $_contextCallback = false;

    /**
     * If set to a valid callback, this will be called every time an error
     * is pushed onto the stack.  The return value will be used to determine
     * whether to allow an error to be pushed or logged.
     *
     * The return value must be one an PEAR_ERRORSTACK_* constant
     * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
     * @var false|string|array
     * @access protected
     */
    var $_errorCallback = array();

    /**
     * PEAR::Log object for logging errors
     * @var false|Log
     * @access protected
     */
    var $_logger = false;

    /**
     * Error messages - designed to be overridden
     * @var array
     * @abstract
     */
    var $_errorMsgs = array();

    /**
     * Set up a new error stack
     *
     * @param string   $package name of the package this error stack represents
     * @param callback $msgCallback callback used for error message generation
     * @param callback $contextCallback callback used for context generation,
     *                 defaults to {@link getFileLine()}
     * @param boolean  $throwPEAR_Error
     */
    function __construct($package, $msgCallback = false, $contextCallback = false,
                         $throwPEAR_Error = false)
    {
        $this->_package = $package;
        $this->setMessageCallback($msgCallback);
        $this->setContextCallback($contextCallback);
        $this->_compat = $throwPEAR_Error;
    }
    
    /**
     * Return a single error stack for this package.
     * 
     * Note that all parameters are ignored if the stack for package $package
     * has already been instantiated
     * @param string   $package name of the package this error stack represents
     * @param callback $msgCallback callback used for error message generation
     * @param callback $contextCallback callback used for context generation,
     *                 defaults to {@link getFileLine()}
     * @param boolean  $throwPEAR_Error
     * @param string   $stackClass class to instantiate
     *
     * @return PEAR_ErrorStack
     */
    public static function &singleton(
        $package, $msgCallback = false, $contextCallback = false,
        $throwPEAR_Error = false, $stackClass = 'PEAR_ErrorStack'
    ) {
        if (isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
            return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package];
        }
        if (!class_exists($stackClass)) {
            if (function_exists('debug_backtrace')) {
                $trace = debug_backtrace();
            }
            PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_NONCLASS,
                'exception', array('stackclass' => $stackClass),
                'stack class "%stackclass%" is not a valid class name (should be like PEAR_ErrorStack)',
                false, $trace);
        }
        $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package] =
            new $stackClass($package, $msgCallback, $contextCallback, $throwPEAR_Error);

        return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package];
    }

    /**
     * Internal error handler for PEAR_ErrorStack class
     * 
     * Dies if the error is an exception (and would have died anyway)
     * @access private
     */
    function _handleError($err)
    {
        if ($err['level'] == 'exception') {
            $message = $err['message'];
            if (isset($_SERVER['REQUEST_URI'])) {
                echo '<br />';
            } else {
                echo "\n";
            }
            var_dump($err['context']);
            die($message);
        }
    }
    
    /**
     * Set up a PEAR::Log object for all error stacks that don't have one
     * @param Log $log 
     */
    public static function setDefaultLogger(&$log)
    {
        if (is_object($log) && method_exists($log, 'log') ) {
            $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log;
        } elseif (is_callable($log)) {
            $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log;
        }
    }
    
    /**
     * Set up a PEAR::Log object for this error stack
     * @param Log $log 
     */
    function setLogger(&$log)
    {
        if (is_object($log) && method_exists($log, 'log') ) {
            $this->_logger = &$log;
        } elseif (is_callable($log)) {
            $this->_logger = &$log;
        }
    }
    
    /**
     * Set an error code => error message mapping callback
     * 
     * This method sets the callback that can be used to generate error
     * messages for any instance
     * @param array|string Callback function/method
     */
    function setMessageCallback($msgCallback)
    {
        if (!$msgCallback) {
            $this->_msgCallback = array(&$this, 'getErrorMessage');
        } else {
            if (is_callable($msgCallback)) {
                $this->_msgCallback = $msgCallback;
            }
        }
    }
    
    /**
     * Get an error code => error message mapping callback
     * 
     * This method returns the current callback that can be used to generate error
     * messages
     * @return array|string|false Callback function/method or false if none
     */
    function getMessageCallback()
    {
        return $this->_msgCallback;
    }
    
    /**
     * Sets a default callback to be used by all error stacks
     * 
     * This method sets the callback that can be used to generate error
     * messages for a singleton
     * @param array|string Callback function/method
     * @param string Package name, or false for all packages
     */
    public static function setDefaultCallback($callback = false, $package = false)
    {
        if (!is_callable($callback)) {
            $callback = false;
        }
        $package = $package ? $package : '*';
        $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$package] = $callback;
    }
    
    /**
     * Set a callback that generates context information (location of error) for an error stack
     * 
     * This method sets the callback that can be used to generate context
     * information for an error.  Passing in NULL will disable context generation
     * and remove the expensive call to debug_backtrace()
     * @param array|string|null Callback function/method
     */
    function setContextCallback($contextCallback)
    {
        if ($contextCallback === null) {
            return $this->_contextCallback = false;
        }
        if (!$contextCallback) {
            $this->_contextCallback = array(&$this, 'getFileLine');
        } else {
            if (is_callable($contextCallback)) {
                $this->_contextCallback = $contextCallback;
            }
        }
    }
    
    /**
     * Set an error Callback
     * If set to a valid callback, this will be called every time an error
     * is pushed onto the stack.  The return value will be used to determine
     * whether to allow an error to be pushed or logged.
     * 
     * The return value must be one of the ERRORSTACK_* constants.
     * 
     * This functionality can be used to emulate PEAR's pushErrorHandling, and
     * the PEAR_ERROR_CALLBACK mode, without affecting the integrity of
     * the error stack or logging
     * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
     * @see popCallback()
     * @param string|array $cb
     */
    function pushCallback($cb)
    {
        array_push($this->_errorCallback, $cb);
    }
    
    /**
     * Remove a callback from the error callback stack
     * @see pushCallback()
     * @return array|string|false
     */
    function popCallback()
    {
        if (!count($this->_errorCallback)) {
            return false;
        }
        return array_pop($this->_errorCallback);
    }
    
    /**
     * Set a temporary overriding error callback for every package error stack
     *
     * Use this to temporarily disable all existing callbacks (can be used
     * to emulate the @ operator, for instance)
     * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
     * @see staticPopCallback(), pushCallback()
     * @param string|array $cb
     */
    public static function staticPushCallback($cb)
    {
        array_push($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'], $cb);
    }
    
    /**
     * Remove a temporary overriding error callback
     * @see staticPushCallback()
     * @return array|string|false
     */
    public static function staticPopCallback()
    {
        $ret = array_pop($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK']);
        if (!is_array($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'])) {
            $GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array();
        }
        return $ret;
    }
    
    /**
     * Add an error to the stack
     * 
     * If the message generator exists, it is called with 2 parameters.
     *  - the current Error Stack object
     *  - an array that is in the same format as an error.  Available indices
     *    are 'code', 'package', 'time', 'params', 'level', and 'context'
     * 
     * Next, if the error should contain context information, this is
     * handled by the context grabbing method.
     * Finally, the error is pushed onto the proper error stack
     * @param int    $code      Package-specific error code
     * @param string $level     Error level.  This is NOT spell-checked
     * @param array  $params    associative array of error parameters
     * @param string $msg       Error message, or a portion of it if the message
     *                          is to be generated
     * @param array  $repackage If this error re-packages an error pushed by
     *                          another package, place the array returned from
     *                          {@link pop()} in this parameter
     * @param array  $backtrace Protected parameter: use this to pass in the
     *                          {@link debug_backtrace()} that should be used
     *                          to find error context
     * @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also
     * thrown.  If a PEAR_Error is returned, the userinfo
     * property is set to the following array:
     * 
     * <code>
     * array(
     *    'code' => $code,
     *    'params' => $params,
     *    'package' => $this->_package,
     *    'level' => $level,
     *    'time' => time(),
     *    'context' => $context,
     *    'message' => $msg,
     * //['repackage' => $err] repackaged error array/Exception class
     * );
     * </code>
     * 
     * Normally, the previous array is returned.
     */
    function push($code, $level = 'error', $params = array(), $msg = false,
                  $repackage = false, $backtrace = false)
    {
        $context = false;
        // grab error context
        if ($this->_contextCallback) {
            if (!$backtrace) {
                $backtrace = debug_backtrace();
            }
            $context = call_user_func($this->_contextCallback, $code, $params, $backtrace);
        }
        
        // save error
        $time = explode(' ', microtime());
        $time = $time[1] + $time[0];
        $err = array(
                'code' => $code,
                'params' => $params,
                'package' => $this->_package,
                'level' => $level,
                'time' => $time,
                'context' => $context,
                'message' => $msg,
               );

        if ($repackage) {
            $err['repackage'] = $repackage;
        }

        // set up the error message, if necessary
        if ($this->_msgCallback) {
            $msg = call_user_func_array($this->_msgCallback,
                                        array(&$this, $err));
            $err['message'] = $msg;
        }        
        $push = $log = true;
        $die = false;
        // try the overriding callback first
        $callback = $this->staticPopCallback();
        if ($callback) {
            $this->staticPushCallback($callback);
        }
        if (!is_callable($callback)) {
            // try the local callback next
            $callback = $this->popCallback();
            if (is_callable($callback)) {
                $this->pushCallback($callback);
            } else {
                // try the default callback
                $callback = isset($GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package]) ?
                    $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package] :
                    $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK']['*'];
            }
        }
        if (is_callable($callback)) {
            switch(call_user_func($callback, $err)){
            	case PEAR_ERRORSTACK_IGNORE: 
            		return $err;
        		break;
            	case PEAR_ERRORSTACK_PUSH: 
            		$log = false;
        		break;
            	case PEAR_ERRORSTACK_LOG: 
            		$push = false;
        		break;
            	case PEAR_ERRORSTACK_DIE: 
            		$die = true;
        		break;
                // anything else returned has the same effect as pushandlog
            }
        }
        if ($push) {
            array_unshift($this->_errors, $err);
            if (!isset($this->_errorsByLevel[$err['level']])) {
                $this->_errorsByLevel[$err['level']] = array();
            }
            $this->_errorsByLevel[$err['level']][] = &$this->_errors[0];
        }
        if ($log) {
            if ($this->_logger || $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']) {
                $this->_log($err);
            }
        }
        if ($die) {
            die();
        }
        if ($this->_compat && $push) {
            return $this->raiseError($msg, $code, null, null, $err);
        }
        return $err;
    }
    
    /**
     * Static version of {@link push()}
     * 
     * @param string $package   Package name this error belongs to
     * @param int    $code      Package-specific error code
     * @param string $level     Error level.  This is NOT spell-checked
     * @param array  $params    associative array of error parameters
     * @param string $msg       Error message, or a portion of it if the message
     *                          is to be generated
     * @param array  $repackage If this error re-packages an error pushed by
     *                          another package, place the array returned from
     *                          {@link pop()} in this parameter
     * @param array  $backtrace Protected parameter: use this to pass in the
     *                          {@link debug_backtrace()} that should be used
     *                          to find error context
     * @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also
     *                          thrown.  see docs for {@link push()}
     */
    public static function staticPush(
        $package, $code, $level = 'error', $params = array(),
        $msg = false, $repackage = false, $backtrace = false
    ) {
        $s = &PEAR_ErrorStack::singleton($package);
        if ($s->_contextCallback) {
            if (!$backtrace) {
                if (function_exists('debug_backtrace')) {
                    $backtrace = debug_backtrace();
                }
            }
        }
        return $s->push($code, $level, $params, $msg, $repackage, $backtrace);
    }
    
    /**
     * Log an error using PEAR::Log
     * @param array $err Error array
     * @param array $levels Error level => Log constant map
     * @access protected
     */
    function _log($err)
    {
        if ($this->_logger) {
            $logger = &$this->_logger;
        } else {
            $logger = &$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'];
        }
        if (is_a($logger, 'Log')) {
            $levels = array(
                'exception' => PEAR_LOG_CRIT,
                'alert' => PEAR_LOG_ALERT,
                'critical' => PEAR_LOG_CRIT,
                'error' => PEAR_LOG_ERR,
                'warning' => PEAR_LOG_WARNING,
                'notice' => PEAR_LOG_NOTICE,
                'info' => PEAR_LOG_INFO,
                'debug' => PEAR_LOG_DEBUG);
            if (isset($levels[$err['level']])) {
                $level = $levels[$err['level']];
            } else {
                $level = PEAR_LOG_INFO;
            }
            $logger->log($err['message'], $level, $err);
        } else { // support non-standard logs
            call_user_func($logger, $err);
        }
    }

    
    /**
     * Pop an error off of the error stack
     * 
     * @return false|array
     * @since 0.4alpha it is no longer possible to specify a specific error
     * level to return - the last error pushed will be returned, instead
     */
    function pop()
    {
        $err = @array_shift($this->_errors);
        if (!is_null($err)) {
            @array_pop($this->_errorsByLevel[$err['level']]);
            if (!count($this->_errorsByLevel[$err['level']])) {
                unset($this->_errorsByLevel[$err['level']]);
            }
        }
        return $err;
    }

    /**
     * Pop an error off of the error stack, static method
     *
     * @param string package name
     * @return boolean
     * @since PEAR1.5.0a1
     */
    static function staticPop($package)
    {
        if ($package) {
            if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
                return false;
            }
            return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->pop();
        }
    }

    /**
     * Determine whether there are any errors on the stack
     * @param string|array Level name.  Use to determine if any errors
     * of level (string), or levels (array) have been pushed
     * @return boolean
     */
    function hasErrors($level = false)
    {
        if ($level) {
            return isset($this->_errorsByLevel[$level]);
        }
        return count($this->_errors);
    }
    
    /**
     * Retrieve all errors since last purge
     * 
     * @param boolean set in order to empty the error stack
     * @param string level name, to return only errors of a particular severity
     * @return array
     */
    function getErrors($purge = false, $level = false)
    {
        if (!$purge) {
            if ($level) {
                if (!isset($this->_errorsByLevel[$level])) {
                    return array();
                } else {
                    return $this->_errorsByLevel[$level];
                }
            } else {
                return $this->_errors;
            }
        }
        if ($level) {
            $ret = $this->_errorsByLevel[$level];
            foreach ($this->_errorsByLevel[$level] as $i => $unused) {
                // entries are references to the $_errors array
                $this->_errorsByLevel[$level][$i] = false;
            }
            // array_filter removes all entries === false
            $this->_errors = array_filter($this->_errors);
            unset($this->_errorsByLevel[$level]);
            return $ret;
        }
        $ret = $this->_errors;
        $this->_errors = array();
        $this->_errorsByLevel = array();
        return $ret;
    }
    
    /**
     * Determine whether there are any errors on a single error stack, or on any error stack
     *
     * The optional parameter can be used to test the existence of any errors without the need of
     * singleton instantiation
     * @param string|false Package name to check for errors
     * @param string Level name to check for a particular severity
     * @return boolean
     */
    public static function staticHasErrors($package = false, $level = false)
    {
        if ($package) {
            if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
                return false;
            }
            return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->hasErrors($level);
        }
        foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) {
            if ($obj->hasErrors($level)) {
                return true;
            }
        }
        return false;
    }
    
    /**
     * Get a list of all errors since last purge, organized by package
     * @since PEAR 1.4.0dev BC break! $level is now in the place $merge used to be
     * @param boolean $purge Set to purge the error stack of existing errors
     * @param string  $level Set to a level name in order to retrieve only errors of a particular level
     * @param boolean $merge Set to return a flat array, not organized by package
     * @param array   $sortfunc Function used to sort a merged array - default
     *        sorts by time, and should be good for most cases
     *
     * @return array 
     */
    public static function staticGetErrors(
        $purge = false, $level = false, $merge = false,
        $sortfunc = array('PEAR_ErrorStack', '_sortErrors')
    ) {
        $ret = array();
        if (!is_callable($sortfunc)) {
            $sortfunc = array('PEAR_ErrorStack', '_sortErrors');
        }
        foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) {
            $test = $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->getErrors($purge, $level);
            if ($test) {
                if ($merge) {
                    $ret = array_merge($ret, $test);
                } else {
                    $ret[$package] = $test;
                }
            }
        }
        if ($merge) {
            usort($ret, $sortfunc);
        }
        return $ret;
    }
    
    /**
     * Error sorting function, sorts by time
     * @access private
     */
    public static function _sortErrors($a, $b)
    {
        if ($a['time'] == $b['time']) {
            return 0;
        }
        if ($a['time'] < $b['time']) {
            return 1;
        }
        return -1;
    }

    /**
     * Standard file/line number/function/class context callback
     *
     * This function uses a backtrace generated from {@link debug_backtrace()}
     * and so will not work at all in PHP < 4.3.0.  The frame should
     * reference the frame that contains the source of the error.
     * @return array|false either array('file' => file, 'line' => line,
     *         'function' => function name, 'class' => class name) or
     *         if this doesn't work, then false
     * @param unused
     * @param integer backtrace frame.
     * @param array Results of debug_backtrace()
     */
    public static function getFileLine($code, $params, $backtrace = null)
    {
        if ($backtrace === null) {
            return false;
        }
        $frame = 0;
        $functionframe = 1;
        if (!isset($backtrace[1])) {
            $functionframe = 0;
        } else {
            while (isset($backtrace[$functionframe]['function']) &&
                  $backtrace[$functionframe]['function'] == 'eval' &&
                  isset($backtrace[$functionframe + 1])) {
                $functionframe++;
            }
        }
        if (isset($backtrace[$frame])) {
            if (!isset($backtrace[$frame]['file'])) {
                $frame++;
            }
            $funcbacktrace = $backtrace[$functionframe];
            $filebacktrace = $backtrace[$frame];
            $ret = array('file' => $filebacktrace['file'],
                         'line' => $filebacktrace['line']);
            // rearrange for eval'd code or create function errors
            if (strpos($filebacktrace['file'], '(') && 
            	  preg_match(';^(.*?)\((\d+)\) : (.*?)\\z;', $filebacktrace['file'],
                  $matches)) {
                $ret['file'] = $matches[1];
                $ret['line'] = $matches[2] + 0;
            }
            if (isset($funcbacktrace['function']) && isset($backtrace[1])) {
                if ($funcbacktrace['function'] != 'eval') {
                    if ($funcbacktrace['function'] == '__lambda_func') {
                        $ret['function'] = 'create_function() code';
                    } else {
                        $ret['function'] = $funcbacktrace['function'];
                    }
                }
            }
            if (isset($funcbacktrace['class']) && isset($backtrace[1])) {
                $ret['class'] = $funcbacktrace['class'];
            }
            return $ret;
        }
        return false;
    }
    
    /**
     * Standard error message generation callback
     * 
     * This method may also be called by a custom error message generator
     * to fill in template values from the params array, simply
     * set the third parameter to the error message template string to use
     * 
     * The special variable %__msg% is reserved: use it only to specify
     * where a message passed in by the user should be placed in the template,
     * like so:
     * 
     * Error message: %msg% - internal error
     * 
     * If the message passed like so:
     * 
     * <code>
     * $stack->push(ERROR_CODE, 'error', array(), 'server error 500');
     * </code>
     * 
     * The returned error message will be "Error message: server error 500 -
     * internal error"
     * @param PEAR_ErrorStack
     * @param array
     * @param string|false Pre-generated error message template
     *
     * @return string
     */
    public static function getErrorMessage(&$stack, $err, $template = false)
    {
        if ($template) {
            $mainmsg = $template;
        } else {
            $mainmsg = $stack->getErrorMessageTemplate($err['code']);
        }
        $mainmsg = str_replace('%__msg%', $err['message'], $mainmsg);
        if (is_array($err['params']) && count($err['params'])) {
            foreach ($err['params'] as $name => $val) {
                if (is_array($val)) {
                    // @ is needed in case $val is a multi-dimensional array
                    $val = @implode(', ', $val);
                }
                if (is_object($val)) {
                    if (method_exists($val, '__toString')) {
                        $val = $val->__toString();
                    } else {
                        PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_OBJTOSTRING,
                            'warning', array('obj' => get_class($val)),
                            'object %obj% passed into getErrorMessage, but has no __toString() method');
                        $val = 'Object';
                    }
                }
                $mainmsg = str_replace('%' . $name . '%', $val, $mainmsg);
            }
        }
        return $mainmsg;
    }
    
    /**
     * Standard Error Message Template generator from code
     * @return string
     */
    function getErrorMessageTemplate($code)
    {
        if (!isset($this->_errorMsgs[$code])) {
            return '%__msg%';
        }
        return $this->_errorMsgs[$code];
    }
    
    /**
     * Set the Error Message Template array
     * 
     * The array format must be:
     * <pre>
     * array(error code => 'message template',...)
     * </pre>
     * 
     * Error message parameters passed into {@link push()} will be used as input
     * for the error message.  If the template is 'message %foo% was %bar%', and the
     * parameters are array('foo' => 'one', 'bar' => 'six'), the error message returned will
     * be 'message one was six'
     * @return string
     */
    function setErrorMessageTemplate($template)
    {
        $this->_errorMsgs = $template;
    }
    
    
    /**
     * emulate PEAR::raiseError()
     * 
     * @return PEAR_Error
     */
    function raiseError()
    {
        require_once 'PEAR.php';
        $args = func_get_args();
        return call_user_func_array(array('PEAR', 'raiseError'), $args);
    }
}
$stack = &PEAR_ErrorStack::singleton('PEAR_ErrorStack');
$stack->pushCallback(array('PEAR_ErrorStack', '_handleError'));
?>
PKp�Z(Pz���PEAR/Proxy.phpnu�[���<?php
/**
 * PEAR_Proxy
 *
 * HTTP Proxy handling 
 *
 * @category   pear
 * @package    PEAR
 * @author     Nico Boehr 
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 */

class PEAR_Proxy
{
    var $config = null;

    /**
     * @access private
     */
    var $proxy_host;
    /**
     * @access private
     */
    var $proxy_port;
    /**
     * @access private
     */
    var $proxy_user;
    /**
     * @access private
     */
    var $proxy_pass;
    /**
     * @access private
     */
    var $proxy_schema;

    function __construct($config = null)
    {
        $this->config = $config;
        $this->_parseProxyInfo();
    }

    /**
     * @access private
     */
    function _parseProxyInfo()
    {
        $this->proxy_host = $this->proxy_port = $this->proxy_user = $this->proxy_pass = '';
        if ($this->config->get('http_proxy')&&
              $proxy = parse_url($this->config->get('http_proxy'))
        ) {
            $this->proxy_host = isset($proxy['host']) ? $proxy['host'] : null;

            $this->proxy_port   = isset($proxy['port']) ? $proxy['port'] : 8080;
            $this->proxy_user   = isset($proxy['user']) ? urldecode($proxy['user']) : null;
            $this->proxy_pass   = isset($proxy['pass']) ? urldecode($proxy['pass']) : null;
            $this->proxy_schema = (isset($proxy['scheme']) && $proxy['scheme'] == 'https') ? 'https' : 'http';
        }
    }

    /**
     * @access private
     */
    function _httpConnect($fp, $host, $port)
    {
        fwrite($fp, "CONNECT $host:$port HTTP/1.1\r\n");
        fwrite($fp, "Host: $host:$port\r\n");
        if ($this->getProxyAuth()) {
            fwrite($fp, 'Proxy-Authorization: Basic ' . $this->getProxyAuth() . "\r\n");
        }
        fwrite($fp, "\r\n");

        while ($line = trim(fgets($fp, 1024))) {
            if (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) {
                $code = (int)$matches[1];

                /* as per RFC 2817 */
                if ($code < 200 || $code >= 300) {
                    return PEAR::raiseError("Establishing a CONNECT tunnel through proxy failed with response code $code");
                }
            }
        }

        // connection was successful -- establish SSL through
        // the tunnel
        $crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT;

        if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) {
            $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
            $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
        }

        // set the correct hostname for working hostname
        // verification
        stream_context_set_option($fp, 'ssl', 'peer_name', $host);

        // blocking socket needed for
        // stream_socket_enable_crypto()
        // see
        // <http://php.net/manual/en/function.stream-socket-enable-crypto.php>
        stream_set_blocking ($fp, true);
        $crypto_res = stream_socket_enable_crypto($fp, true, $crypto_method);
        if (!$crypto_res) {
            return PEAR::raiseError("Could not establish SSL connection through proxy: $crypto_res");
        }

        return true;
    }

    /**
     * get the authorization information for the proxy, encoded to be
     * passed in the Proxy-Authentication HTTP header.
     * @return null|string the encoded authentication information if a
     *                     proxy and authentication is configured, null 
     *                     otherwise.
     */
    function getProxyAuth()
    {
        if ($this->isProxyConfigured() && $this->proxy_user != '') {
            return base64_encode($this->proxy_user . ':' . $this->proxy_pass);
        }
        return null;
    }

    function getProxyUser()
    {
        return $this->proxy_user;
    }

    /**
     * Check if we are configured to use a proxy.
     *
     * @return boolean true if we are configured to use a proxy, false
     *                 otherwise.
     * @access public
     */
    function isProxyConfigured()
    {
        return $this->proxy_host != '';
    }

    /**
     * Open a socket to a remote server, possibly involving a HTTP
     * proxy.
     *
     * If an HTTP proxy has been configured (http_proxy PEAR_Config
     * setting), the proxy will be used.
     *
     * @param string $host    the host to connect to
     * @param string $port    the port to connect to
     * @param boolean $secure if true, establish a secure connection
     *                        using TLS.
     * @access public
     */
    function openSocket($host, $port, $secure = false)
    {
        if ($this->isProxyConfigured()) {
            $fp = @fsockopen(
                $this->proxy_host, $this->proxy_port, 
                $errno, $errstr, 15
            );

            if (!$fp) {
                return PEAR::raiseError("Connection to the proxy failed: $errstr", -9276);
            }

            /* HTTPS is to be used and we have a proxy, use CONNECT verb */
            if ($secure) {
                $res = $this->_httpConnect($fp, $host, $port);

                if (PEAR::isError($res)) {
                    return $res;
                }
            }
        } else {
            if ($secure) {
                $host = 'ssl://' . $host;
            }

            $fp = @fsockopen($host, $port, $errno, $errstr);
            if (!$fp) {
                return PEAR::raiseError("Connection to `$host:$port' failed: $errstr", $errno);
            }
        }

        return $fp;
    }
}
PKp�Z��'����PEAR/RunTest.phpnu�[���<?php
/**
 * PEAR_RunTest
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Tomas V.V.Cox <cox@idecnet.com>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.3.3
 */

/**
 * for error handling
 */
require_once 'PEAR.php';
require_once 'PEAR/Config.php';

define('DETAILED', 1);
putenv("PHP_PEAR_RUNTESTS=1");

/**
 * Simplified version of PHP's test suite
 *
 * Try it with:
 *
 * $ php -r 'include "../PEAR/RunTest.php"; $t=new PEAR_RunTest; $o=$t->run("./pear_system.phpt");print_r($o);'
 *
 *
 * @category   pear
 * @package    PEAR
 * @author     Tomas V.V.Cox <cox@idecnet.com>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.3.3
 */
class PEAR_RunTest
{
    var $_headers = array();
    var $_logger;
    var $_options;
    var $_php;
    var $tests_count;
    var $xdebug_loaded;
    /**
     * Saved value of php executable, used to reset $_php when we
     * have a test that uses cgi
     *
     * @var unknown_type
     */
    var $_savephp;
    var $ini_overwrites = array(
        'output_handler=',
        'open_basedir=',
        'disable_functions=',
        'output_buffering=Off',
        'display_errors=1',
        'log_errors=0',
        'html_errors=0',
        'report_memleaks=0',
        'report_zend_debug=0',
        'docref_root=',
        'docref_ext=.html',
        'error_prepend_string=',
        'error_append_string=',
        'auto_prepend_file=',
        'auto_append_file=',
        'xdebug.default_enable=0',
        'allow_url_fopen=1',
    );

    /**
     * An object that supports the PEAR_Common->log() signature, or null
     * @param PEAR_Common|null
     */
    function __construct($logger = null, $options = array())
    {
        if (!defined('E_DEPRECATED')) {
            define('E_DEPRECATED', 0);
        }
        if (!defined('E_STRICT')) {
            define('E_STRICT', 0);
        }
        $excluded_error_reporting = E_DEPRECATED;
        if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) {
            $excluded_error_reporting |= E_STRICT;
        }
        $this->ini_overwrites[] = 'error_reporting=' . (E_ALL & ~$excluded_error_reporting);
        if (is_null($logger)) {
            require_once 'PEAR/Common.php';
            $logger = new PEAR_Common;
        }
        $this->_logger  = $logger;
        $this->_options = $options;

        $conf = &PEAR_Config::singleton();
        $this->_php = $conf->get('php_bin');
    }

    /**
     * Taken from php-src/run-tests.php
     *
     * @param string $commandline command name
     * @param array $env
     * @param string $stdin standard input to pass to the command
     * @return unknown
     */
    function system_with_timeout($commandline, $env = null, $stdin = null)
    {
        $data = '';
        $proc = proc_open($commandline, array(
            0 => array('pipe', 'r'),
            1 => array('pipe', 'w'),
            2 => array('pipe', 'w')
        ), $pipes, null, $env, array('suppress_errors' => true));

        if (!$proc) {
            return false;
        }

        if (is_string($stdin)) {
            fwrite($pipes[0], $stdin);
        }
        fclose($pipes[0]);

        while (true) {
            /* hide errors from interrupted syscalls */
            $r = $pipes;
            unset($r[0]);
            $e = $w = [];
            $n = @stream_select($r, $w, $e, 60);

            if ($n === 0) {
                /* timed out */
                $data .= "\n ** ERROR: process timed out **\n";
                proc_terminate($proc);
                return array(1234567890, $data);
            } else if ($n > 0) {
                $line = fread($pipes[1], 8192);
                if (strlen($line) == 0) {
                    /* EOF */
                    break;
                }
                $data .= $line;
            }
        }
        if (function_exists('proc_get_status')) {
            $stat = proc_get_status($proc);
            if ($stat['signaled']) {
                $data .= "\nTermsig=".$stat['stopsig'];
            }
        }
        $code = proc_close($proc);
        if (function_exists('proc_get_status')) {
            $code = $stat['exitcode'];
        }
        return array($code, $data);
    }

    /**
     * Turns a PHP INI string into an array
     *
     * Turns -d "include_path=/foo/bar" into this:
     * array(
     *   'include_path' => array(
     *          'operator' => '-d',
     *          'value'    => '/foo/bar',
     *   )
     * )
     * Works both with quotes and without
     *
     * @param string an PHP INI string, -d "include_path=/foo/bar"
     * @return array
     */
    function iniString2array($ini_string)
    {
        if (!$ini_string) {
            return array();
        }
        $split = preg_split('/[\s]|=/', $ini_string, -1, PREG_SPLIT_NO_EMPTY);
        $key   = $split[1][0] == '"'                     ? substr($split[1], 1)     : $split[1];
        $value = $split[2][strlen($split[2]) - 1] == '"' ? substr($split[2], 0, -1) : $split[2];
        // FIXME review if this is really the struct to go with
        $array = array($key => array('operator' => $split[0], 'value' => $value));
        return $array;
    }

    function settings2array($settings, $ini_settings)
    {
        foreach ($settings as $setting) {
            if (strpos($setting, '=') !== false) {
                $setting = explode('=', $setting, 2);
                $name  = trim(strtolower($setting[0]));
                $value = trim($setting[1]);
                $ini_settings[$name] = $value;
            }
        }
        return $ini_settings;
    }

    function settings2params($ini_settings)
    {
        $settings = '';
        foreach ($ini_settings as $name => $value) {
            if (is_array($value)) {
                $operator = $value['operator'];
                $value    = $value['value'];
            } else {
                $operator = '-d';
            }
            $value = addslashes($value);
            $settings .= " $operator \"$name=$value\"";
        }
        return $settings;
    }

    function _preparePhpBin($php, $file, $ini_settings)
    {
        $file = escapeshellarg($file);
        $cmd = $php . $ini_settings . ' -f ' . $file;

        return $cmd;
    }

    function runPHPUnit($file, $ini_settings = '')
    {
        if (!file_exists($file) && file_exists(getcwd() . DIRECTORY_SEPARATOR . $file)) {
            $file = realpath(getcwd() . DIRECTORY_SEPARATOR . $file);
        } elseif (file_exists($file)) {
            $file = realpath($file);
        }

        $cmd = $this->_preparePhpBin($this->_php, $file, $ini_settings);
        if (isset($this->_logger)) {
            $this->_logger->log(2, 'Running command "' . $cmd . '"');
        }

        $savedir = getcwd(); // in case the test moves us around
        chdir(dirname($file));
        echo `$cmd`;
        chdir($savedir);
        return 'PASSED'; // we have no way of knowing this information so assume passing
    }

    /**
     * Runs an individual test case.
     *
     * @param string       The filename of the test
     * @param array|string INI settings to be applied to the test run
     * @param integer      Number what the current running test is of the
     *                     whole test suite being runned.
     *
     * @return string|object Returns PASSED, WARNED, FAILED depending on how the
     *                       test came out.
     *                       PEAR Error when the tester it self fails
     */
    function run($file, $ini_settings = array(), $test_number = 1)
    {
        $this->_restorePHPBinary();

        if (empty($this->_options['cgi'])) {
            // try to see if php-cgi is in the path
            $res = $this->system_with_timeout('php-cgi -v');
            if (false !== $res && !(is_array($res) && in_array($res[0], array(-1, 127)))) {
                $this->_options['cgi'] = 'php-cgi';
            }
        }
        if (1 < $len = strlen($this->tests_count)) {
            $test_number = str_pad($test_number, $len, ' ', STR_PAD_LEFT);
            $test_nr = "[$test_number/$this->tests_count] ";
        } else {
            $test_nr = '';
        }

        $file = realpath($file);
        $section_text = $this->_readFile($file);
        if (PEAR::isError($section_text)) {
            return $section_text;
        }

        if (isset($section_text['POST_RAW']) && isset($section_text['UPLOAD'])) {
            return PEAR::raiseError("Cannot contain both POST_RAW and UPLOAD in test file: $file");
        }

        $cwd = getcwd();

        $pass_options = '';
        if (!empty($this->_options['ini'])) {
            $pass_options = $this->_options['ini'];
        }

        if (is_string($ini_settings)) {
            $ini_settings = $this->iniString2array($ini_settings);
        }

        $ini_settings = $this->settings2array($this->ini_overwrites, $ini_settings);
        if ($section_text['INI']) {
            if (strpos($section_text['INI'], '{PWD}') !== false) {
                $section_text['INI'] = str_replace('{PWD}', dirname($file), $section_text['INI']);
            }
            $ini = preg_split( "/[\n\r]+/", $section_text['INI']);
            $ini_settings = $this->settings2array($ini, $ini_settings);
        }
        $ini_settings = $this->settings2params($ini_settings);
        $shortname = str_replace($cwd . DIRECTORY_SEPARATOR, '', $file);

        $tested = trim($section_text['TEST']);
        $tested.= !isset($this->_options['simple']) ? "[$shortname]" : ' ';

        if (!empty($section_text['POST']) || !empty($section_text['POST_RAW']) ||
              !empty($section_text['UPLOAD']) || !empty($section_text['GET']) ||
              !empty($section_text['COOKIE']) || !empty($section_text['EXPECTHEADERS'])) {
            if (empty($this->_options['cgi'])) {
                if (!isset($this->_options['quiet'])) {
                    $this->_logger->log(0, "SKIP $test_nr$tested (reason: --cgi option needed for this test, type 'pear help run-tests')");
                }
                if (isset($this->_options['tapoutput'])) {
                    return array('ok', ' # skip --cgi option needed for this test, "pear help run-tests" for info');
                }
                return 'SKIPPED';
            }
            $this->_savePHPBinary();
            $this->_php = $this->_options['cgi'];
        }

        $temp_dir = realpath(dirname($file));
        $main_file_name = basename($file, 'phpt');
        $diff_filename     = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'diff';
        $log_filename      = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'log';
        $exp_filename      = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'exp';
        $output_filename   = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'out';
        $memcheck_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'mem';
        $temp_file         = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'php';
        $temp_skipif       = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'skip.php';
        $temp_clean        = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'clean.php';
        $tmp_post          = $temp_dir . DIRECTORY_SEPARATOR . uniqid('phpt.');

        // unlink old test results
        $this->_cleanupOldFiles($file);

        // Check if test should be skipped.
        $res  = $this->_runSkipIf($section_text, $temp_skipif, $tested, $ini_settings);
        if ($res == 'SKIPPED' || count($res) != 2) {
            return $res;
        }
        $info = $res['info'];
        $warn = $res['warn'];

        // We've satisfied the preconditions - run the test!
        if (isset($this->_options['coverage']) && $this->xdebug_loaded) {
            $xdebug_file = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name . 'xdebug';
            $text = "\n" . 'function coverage_shutdown() {' .
                    "\n" . '    $xdebug = var_export(xdebug_get_code_coverage(), true);';
            if (!function_exists('file_put_contents')) {
                $text .= "\n" . '    $fh = fopen(\'' . $xdebug_file . '\', "wb");' .
                        "\n" . '    if ($fh !== false) {' .
                        "\n" . '        fwrite($fh, $xdebug);' .
                        "\n" . '        fclose($fh);' .
                        "\n" . '    }';
            } else {
                $text .= "\n" . '    file_put_contents(\'' . $xdebug_file . '\', $xdebug);';
            }

            // Workaround for http://pear.php.net/bugs/bug.php?id=17292
            $lines             = explode("\n", $section_text['FILE']);
            $numLines          = count($lines);
            $namespace         = '';
            $coverage_shutdown = 'coverage_shutdown';

            if (
                substr($lines[0], 0, 2) == '<?' ||
                substr($lines[0], 0, 5) == '<?php'
            ) {
                unset($lines[0]);
            }


            for ($i = 0; $i < $numLines; $i++) {
                if (isset($lines[$i]) && substr($lines[$i], 0, 9) == 'namespace') {
                    $namespace         = substr($lines[$i], 10, -1);
                    $coverage_shutdown = $namespace . '\\coverage_shutdown';
                    $namespace         = "namespace " . $namespace . ";\n";

                    unset($lines[$i]);
                    break;
                }
            }

            $text .= "\n    xdebug_stop_code_coverage();" .
                "\n" . '} // end coverage_shutdown()' .
                "\n\n" . 'register_shutdown_function("' . $coverage_shutdown . '");';
            $text .= "\n" . 'xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE);' . "\n";

            $this->save_text($temp_file, "<?php\n" . $namespace . $text  . "\n" . implode("\n", $lines));
        } else {
            $this->save_text($temp_file, $section_text['FILE']);
        }

        $args = $section_text['ARGS'] ? ' -- '.$section_text['ARGS'] : '';
        $cmd = $this->_preparePhpBin($this->_php, $temp_file, $ini_settings);
        $cmd.= "$args 2>&1";
        if (isset($this->_logger)) {
            $this->_logger->log(2, 'Running command "' . $cmd . '"');
        }

        // Reset environment from any previous test.
        $env = $this->_resetEnv($section_text, $temp_file);

        $section_text = $this->_processUpload($section_text, $file);
        if (PEAR::isError($section_text)) {
            return $section_text;
        }

        if (array_key_exists('POST_RAW', $section_text) && !empty($section_text['POST_RAW'])) {
            $post = trim($section_text['POST_RAW']);
            $raw_lines = explode("\n", $post);

            $request = '';
            $started = false;
            foreach ($raw_lines as $i => $line) {
                if (empty($env['CONTENT_TYPE']) &&
                    preg_match('/^Content-Type:(.*)/i', $line, $res)) {
                    $env['CONTENT_TYPE'] = trim(str_replace("\r", '', $res[1]));
                    continue;
                }
                if ($started) {
                    $request .= "\n";
                }
                $started = true;
                $request .= $line;
            }

            $env['CONTENT_LENGTH'] = strlen($request);
            $env['REQUEST_METHOD'] = 'POST';

            $this->save_text($tmp_post, $request);
            $cmd = "$this->_php$pass_options$ini_settings \"$temp_file\" 2>&1 < $tmp_post";
        } elseif (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) {
            $post = trim($section_text['POST']);
            $this->save_text($tmp_post, $post);
            $content_length = strlen($post);

            $env['REQUEST_METHOD'] = 'POST';
            $env['CONTENT_TYPE']   = 'application/x-www-form-urlencoded';
            $env['CONTENT_LENGTH'] = $content_length;

            $cmd = "$this->_php$pass_options$ini_settings \"$temp_file\" 2>&1 < $tmp_post";
        } else {
            $env['REQUEST_METHOD'] = 'GET';
            $env['CONTENT_TYPE']   = '';
            $env['CONTENT_LENGTH'] = '';
        }

        if (OS_WINDOWS && isset($section_text['RETURNS'])) {
            ob_start();
            system($cmd, $return_value);
            $out = ob_get_contents();
            ob_end_clean();
            $section_text['RETURNS'] = (int) trim($section_text['RETURNS']);
            $returnfail = ($return_value != $section_text['RETURNS']);
        } else {
            $returnfail = false;
            $stdin = isset($section_text['STDIN']) ? $section_text['STDIN'] : null;
            $out = $this->system_with_timeout($cmd, $env, $stdin);
            $return_value = $out[0];
            $out = $out[1];
        }

        $output = preg_replace('/\r\n/', "\n", trim($out));

        if (isset($tmp_post) && realpath($tmp_post) && file_exists($tmp_post)) {
            @unlink(realpath($tmp_post));
        }
        chdir($cwd); // in case the test moves us around

        /* when using CGI, strip the headers from the output */
        $output = $this->_stripHeadersCGI($output);

        if (isset($section_text['EXPECTHEADERS'])) {
            $testheaders = $this->_processHeaders($section_text['EXPECTHEADERS']);
            $missing = array_diff_assoc($testheaders, $this->_headers);
            $changed = '';
            foreach ($missing as $header => $value) {
                if (isset($this->_headers[$header])) {
                    $changed .= "-$header: $value\n+$header: ";
                    $changed .= $this->_headers[$header];
                } else {
                    $changed .= "-$header: $value\n";
                }
            }
            if ($missing) {
                // tack on failed headers to output:
                $output .= "\n====EXPECTHEADERS FAILURE====:\n$changed";
            }
        }

        $this->_testCleanup($section_text, $temp_clean);

        // Does the output match what is expected?
        do {
            if (isset($section_text['EXPECTF']) || isset($section_text['EXPECTREGEX'])) {
                if (isset($section_text['EXPECTF'])) {
                    $wanted = trim($section_text['EXPECTF']);
                } else {
                    $wanted = trim($section_text['EXPECTREGEX']);
                }
                $wanted_re = preg_replace('/\r\n/', "\n", $wanted);
                if (isset($section_text['EXPECTF'])) {
                    $wanted_re = preg_quote($wanted_re, '/');
                    // Stick to basics
                    $wanted_re = str_replace("%s", ".+?", $wanted_re); //not greedy
                    $wanted_re = str_replace("%S", ".*?", $wanted_re); //not greedy
                    $wanted_re = str_replace("%i", "[+\-]?[0-9]+", $wanted_re);
                    $wanted_re = str_replace("%d", "[0-9]+", $wanted_re);
                    $wanted_re = str_replace("%x", "[0-9a-fA-F]+", $wanted_re);
                    $wanted_re = str_replace("%f", "[+\-]?\.?[0-9]+\.?[0-9]*(E-?[0-9]+)?", $wanted_re);
                    $wanted_re = str_replace("%c", ".", $wanted_re);
                    // %f allows two points "-.0.0" but that is the best *simple* expression
                }

    /* DEBUG YOUR REGEX HERE
            var_dump($wanted_re);
            print(str_repeat('=', 80) . "\n");
            var_dump($output);
    */
                if (!$returnfail && preg_match("/^$wanted_re\$/s", $output)) {
                    if (file_exists($temp_file)) {
                        unlink($temp_file);
                    }
                    if (array_key_exists('FAIL', $section_text)) {
                        break;
                    }
                    if (!isset($this->_options['quiet'])) {
                        $this->_logger->log(0, "PASS $test_nr$tested$info");
                    }
                    if (isset($this->_options['tapoutput'])) {
                        return array('ok', ' - ' . $tested);
                    }
                    return 'PASSED';
                }
            } else {
                if (isset($section_text['EXPECTFILE'])) {
                    $f = $temp_dir . '/' . trim($section_text['EXPECTFILE']);
                    if (!($fp = @fopen($f, 'rb'))) {
                        return PEAR::raiseError('--EXPECTFILE-- section file ' .
                            $f . ' not found');
                    }
                    fclose($fp);
                    $section_text['EXPECT'] = file_get_contents($f);
                }

                if (isset($section_text['EXPECT'])) {
                    $wanted = preg_replace('/\r\n/', "\n", trim($section_text['EXPECT']));
                } else {
                    $wanted = '';
                }

                // compare and leave on success
                if (!$returnfail && 0 == strcmp($output, $wanted)) {
                    if (file_exists($temp_file)) {
                        unlink($temp_file);
                    }
                    if (array_key_exists('FAIL', $section_text)) {
                        break;
                    }
                    if (!isset($this->_options['quiet'])) {
                        $this->_logger->log(0, "PASS $test_nr$tested$info");
                    }
                    if (isset($this->_options['tapoutput'])) {
                        return array('ok', ' - ' . $tested);
                    }
                    return 'PASSED';
                }
            }
        } while (false);

        if (array_key_exists('FAIL', $section_text)) {
            // we expect a particular failure
            // this is only used for testing PEAR_RunTest
            $expectf  = isset($section_text['EXPECTF']) ? $wanted_re : null;
            $faildiff = $this->generate_diff($wanted, $output, null, $expectf);
            $faildiff = preg_replace('/\r/', '', $faildiff);
            $wanted   = preg_replace('/\r/', '', trim($section_text['FAIL']));
            if ($faildiff == $wanted) {
                if (!isset($this->_options['quiet'])) {
                    $this->_logger->log(0, "PASS $test_nr$tested$info");
                }
                if (isset($this->_options['tapoutput'])) {
                    return array('ok', ' - ' . $tested);
                }
                return 'PASSED';
            }
            unset($section_text['EXPECTF']);
            $output = $faildiff;
            if (isset($section_text['RETURNS'])) {
                return PEAR::raiseError('Cannot have both RETURNS and FAIL in the same test: ' .
                    $file);
            }
        }

        // Test failed so we need to report details.
        $txt = $warn ? 'WARN ' : 'FAIL ';
        $this->_logger->log(0, $txt . $test_nr . $tested . $info);

        // write .exp
        $res = $this->_writeLog($exp_filename, $wanted);
        if (PEAR::isError($res)) {
            return $res;
        }

        // write .out
        $res = $this->_writeLog($output_filename, $output);
        if (PEAR::isError($res)) {
            return $res;
        }

        // write .diff
        $returns = isset($section_text['RETURNS']) ?
                        array(trim($section_text['RETURNS']), $return_value) : null;
        $expectf = isset($section_text['EXPECTF']) ? $wanted_re : null;
        $data = $this->generate_diff($wanted, $output, $returns, $expectf);
        $res  = $this->_writeLog($diff_filename, $data);
        if (isset($this->_options['showdiff'])) {
            $this->_logger->log(0, "========DIFF========");
            $this->_logger->log(0, $data);
            $this->_logger->log(0, "========DONE========");
        }
        if (PEAR::isError($res)) {
            return $res;
        }

        // write .log
        $data = "
---- EXPECTED OUTPUT
$wanted
---- ACTUAL OUTPUT
$output
---- FAILED
";

        if ($returnfail) {
            $data .= "
---- EXPECTED RETURN
$section_text[RETURNS]
---- ACTUAL RETURN
$return_value
";
        }

        $res = $this->_writeLog($log_filename, $data);
        if (PEAR::isError($res)) {
            return $res;
        }

        if (isset($this->_options['tapoutput'])) {
            $wanted = explode("\n", $wanted);
            $wanted = "# Expected output:\n#\n#" . implode("\n#", $wanted);
            $output = explode("\n", $output);
            $output = "#\n#\n# Actual output:\n#\n#" . implode("\n#", $output);
            return array($wanted . $output . 'not ok', ' - ' . $tested);
        }
        return $warn ? 'WARNED' : 'FAILED';
    }

    function generate_diff($wanted, $output, $rvalue, $wanted_re)
    {
        $w  = explode("\n", $wanted);
        $o  = explode("\n", $output);
        $wr = explode("\n", $wanted_re);
        $w1 = array_diff_assoc($w, $o);
        $o1 = array_diff_assoc($o, $w);
        $o2 = $w2 = array();
        foreach ($w1 as $idx => $val) {
            if (!$wanted_re || !isset($wr[$idx]) || !isset($o1[$idx]) ||
                  !preg_match('/^' . $wr[$idx] . '\\z/', $o1[$idx])) {
                $w2[sprintf("%03d<", $idx)] = sprintf("%03d- ", $idx + 1) . $val;
            }
        }
        foreach ($o1 as $idx => $val) {
            if (!$wanted_re || !isset($wr[$idx]) ||
                  !preg_match('/^' . $wr[$idx] . '\\z/', $val)) {
                $o2[sprintf("%03d>", $idx)] = sprintf("%03d+ ", $idx + 1) . $val;
            }
        }
        $diff = array_merge($w2, $o2);
        ksort($diff);
        $extra = $rvalue ? "##EXPECTED: $rvalue[0]\r\n##RETURNED: $rvalue[1]" : '';
        return implode("\r\n", $diff) . $extra;
    }

    //  Write the given text to a temporary file, and return the filename.
    function save_text($filename, $text)
    {
        if (!$fp = fopen($filename, 'w')) {
            return PEAR::raiseError("Cannot open file '" . $filename . "' (save_text)");
        }
        fwrite($fp, $text);
        fclose($fp);
    if (1 < DETAILED) echo "
FILE $filename {{{
$text
}}}
";
    }

    function _cleanupOldFiles($file)
    {
        $temp_dir = realpath(dirname($file));
        $mainFileName = basename($file, 'phpt');
        $diff_filename     = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'diff';
        $log_filename      = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'log';
        $exp_filename      = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'exp';
        $output_filename   = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'out';
        $memcheck_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'mem';
        $temp_file         = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'php';
        $temp_skipif       = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'skip.php';
        $temp_clean        = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'clean.php';
        $tmp_post          = $temp_dir . DIRECTORY_SEPARATOR . uniqid('phpt.');

        // unlink old test results
        @unlink($diff_filename);
        @unlink($log_filename);
        @unlink($exp_filename);
        @unlink($output_filename);
        @unlink($memcheck_filename);
        @unlink($temp_file);
        @unlink($temp_skipif);
        @unlink($tmp_post);
        @unlink($temp_clean);
    }

    function _runSkipIf($section_text, $temp_skipif, $tested, $ini_settings)
    {
        $info = '';
        $warn = false;
        if (array_key_exists('SKIPIF', $section_text) && trim($section_text['SKIPIF'])) {
            $this->save_text($temp_skipif, $section_text['SKIPIF']);
            $output = $this->system_with_timeout("$this->_php$ini_settings -f \"$temp_skipif\"");
            $output = $output[1];
            $loutput = ltrim($output);
            unlink($temp_skipif);
            if (!strncasecmp('skip', $loutput, 4)) {
                $skipreason = "SKIP $tested";
                if (preg_match('/^\s*skip\s*(.+)\s*/i', $output, $m)) {
                    $skipreason .= '(reason: ' . $m[1] . ')';
                }
                if (!isset($this->_options['quiet'])) {
                    $this->_logger->log(0, $skipreason);
                }
                if (isset($this->_options['tapoutput'])) {
                    return array('ok', ' # skip ' . $reason);
                }
                return 'SKIPPED';
            }

            if (!strncasecmp('info', $loutput, 4)
                && preg_match('/^\s*info\s*(.+)\s*/i', $output, $m)) {
                $info = " (info: $m[1])";
            }

            if (!strncasecmp('warn', $loutput, 4)
                && preg_match('/^\s*warn\s*(.+)\s*/i', $output, $m)) {
                $warn = true; /* only if there is a reason */
                $info = " (warn: $m[1])";
            }
        }

        return array('warn' => $warn, 'info' => $info);
    }

    function _stripHeadersCGI($output)
    {
        $this->headers = array();
        if (!empty($this->_options['cgi']) &&
              $this->_php == $this->_options['cgi'] &&
              preg_match("/^(.*?)(?:\n\n(.*)|\\z)/s", $output, $match)) {
            $output = isset($match[2]) ? trim($match[2]) : '';
            $this->_headers = $this->_processHeaders($match[1]);
        }

        return $output;
    }

    /**
     * Return an array that can be used with array_diff() to compare headers
     *
     * @param string $text
     */
    function _processHeaders($text)
    {
        $headers = array();
        $rh = preg_split("/[\n\r]+/", $text);
        foreach ($rh as $line) {
            if (strpos($line, ':')!== false) {
                $line = explode(':', $line, 2);
                $headers[trim($line[0])] = trim($line[1]);
            }
        }
        return $headers;
    }

    function _readFile($file)
    {
        // Load the sections of the test file.
        $section_text = array(
            'TEST'   => '(unnamed test)',
            'SKIPIF' => '',
            'GET'    => '',
            'COOKIE' => '',
            'POST'   => '',
            'ARGS'   => '',
            'INI'    => '',
            'CLEAN'  => '',
        );

        if (!is_file($file) || !$fp = fopen($file, "r")) {
            return PEAR::raiseError("Cannot open test file: $file");
        }

        $section = '';
        while (!feof($fp)) {
            $line = fgets($fp);

            // Match the beginning of a section.
            if (preg_match('/^--([_A-Z]+)--/', $line, $r)) {
                $section = $r[1];
                $section_text[$section] = '';
                continue;
            } elseif (empty($section)) {
                fclose($fp);
                return PEAR::raiseError("Invalid sections formats in test file: $file");
            }

            // Add to the section text.
            $section_text[$section] .= $line;
        }
        fclose($fp);

        return $section_text;
    }

    function _writeLog($logname, $data)
    {
        if (!$log = fopen($logname, 'w')) {
            return PEAR::raiseError("Cannot create test log - $logname");
        }
        fwrite($log, $data);
        fclose($log);
    }

    function _resetEnv($section_text, $temp_file)
    {
        $env = $_ENV;
        $env['REDIRECT_STATUS'] = '';
        $env['QUERY_STRING']    = '';
        $env['PATH_TRANSLATED'] = '';
        $env['SCRIPT_FILENAME'] = '';
        $env['REQUEST_METHOD']  = '';
        $env['CONTENT_TYPE']    = '';
        $env['CONTENT_LENGTH']  = '';
        if (!empty($section_text['ENV'])) {
            if (strpos($section_text['ENV'], '{PWD}') !== false) {
                $section_text['ENV'] = str_replace('{PWD}', dirname($temp_file), $section_text['ENV']);
            }
            foreach (explode("\n", trim($section_text['ENV'])) as $e) {
                $e = explode('=', trim($e), 2);
                if (!empty($e[0]) && isset($e[1])) {
                    $env[$e[0]] = $e[1];
                }
            }
        }
        if (array_key_exists('GET', $section_text)) {
            $env['QUERY_STRING'] = trim($section_text['GET']);
        } else {
            $env['QUERY_STRING'] = '';
        }
        if (array_key_exists('COOKIE', $section_text)) {
            $env['HTTP_COOKIE'] = trim($section_text['COOKIE']);
        } else {
            $env['HTTP_COOKIE'] = '';
        }
        $env['REDIRECT_STATUS'] = '1';
        $env['PATH_TRANSLATED'] = $temp_file;
        $env['SCRIPT_FILENAME'] = $temp_file;

        return $env;
    }

    function _processUpload($section_text, $file)
    {
        if (array_key_exists('UPLOAD', $section_text) && !empty($section_text['UPLOAD'])) {
            $upload_files = trim($section_text['UPLOAD']);
            $upload_files = explode("\n", $upload_files);

            $request = "Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737\n" .
                       "-----------------------------20896060251896012921717172737\n";
            foreach ($upload_files as $fileinfo) {
                $fileinfo = explode('=', $fileinfo);
                if (count($fileinfo) != 2) {
                    return PEAR::raiseError("Invalid UPLOAD section in test file: $file");
                }
                if (!realpath(dirname($file) . '/' . $fileinfo[1])) {
                    return PEAR::raiseError("File for upload does not exist: $fileinfo[1] " .
                        "in test file: $file");
                }
                $file_contents = file_get_contents(dirname($file) . '/' . $fileinfo[1]);
                $fileinfo[1] = basename($fileinfo[1]);
                $request .= "Content-Disposition: form-data; name=\"$fileinfo[0]\"; filename=\"$fileinfo[1]\"\n";
                $request .= "Content-Type: text/plain\n\n";
                $request .= $file_contents . "\n" .
                    "-----------------------------20896060251896012921717172737\n";
            }

            if (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) {
                // encode POST raw
                $post = trim($section_text['POST']);
                $post = explode('&', $post);
                foreach ($post as $i => $post_info) {
                    $post_info = explode('=', $post_info);
                    if (count($post_info) != 2) {
                        return PEAR::raiseError("Invalid POST data in test file: $file");
                    }
                    $post_info[0] = rawurldecode($post_info[0]);
                    $post_info[1] = rawurldecode($post_info[1]);
                    $post[$i] = $post_info;
                }
                foreach ($post as $post_info) {
                    $request .= "Content-Disposition: form-data; name=\"$post_info[0]\"\n\n";
                    $request .= $post_info[1] . "\n" .
                        "-----------------------------20896060251896012921717172737\n";
                }
                unset($section_text['POST']);
            }
            $section_text['POST_RAW'] = $request;
        }

        return $section_text;
    }

    function _testCleanup($section_text, $temp_clean)
    {
        if ($section_text['CLEAN']) {
            $this->_restorePHPBinary();

            // perform test cleanup
            $this->save_text($temp_clean, $section_text['CLEAN']);
            $output = $this->system_with_timeout("$this->_php $temp_clean  2>&1");
            if (strlen($output[1])) {
                echo "BORKED --CLEAN-- section! output:\n", $output[1];
            }
            if (file_exists($temp_clean)) {
                unlink($temp_clean);
            }
        }
    }

    function _savePHPBinary()
    {
        $this->_savephp = $this->_php;
    }

    function _restorePHPBinary()
    {
        if (isset($this->_savephp))
        {
            $this->_php = $this->_savephp;
            unset($this->_savephp);
        }
    }
}
PKq�Zj�y99PEAR/Validator/PECL.phpnu�[���<?php
/**
 * Channel Validator for the pecl.php.net channel
 *
 * PHP 4 and PHP 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2006 The PHP Group
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a5
 */
/**
 * This is the parent class for all validators
 */
require_once 'PEAR/Validate.php';
/**
 * Channel Validator for the pecl.php.net channel
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a5
 */
class PEAR_Validator_PECL extends PEAR_Validate
{
    function validateVersion()
    {
        if ($this->_state == PEAR_VALIDATE_PACKAGING) {
            $version = $this->_packagexml->getVersion();
            $versioncomponents = explode('.', $version);
            $last = array_pop($versioncomponents);
            if (substr($last, 1, 2) == 'rc') {
                $this->_addFailure('version', 'Release Candidate versions must have ' .
                'upper-case RC, not lower-case rc');
                return false;
            }
        }
        return true;
    }

    function validatePackageName()
    {
        $ret = parent::validatePackageName();
        if ($this->_packagexml->getPackageType() == 'extsrc' ||
              $this->_packagexml->getPackageType() == 'zendextsrc') {
            if (strtolower($this->_packagexml->getPackage()) !=
                  strtolower($this->_packagexml->getProvidesExtension())) {
                $this->_addWarning('providesextension', 'package name "' .
                    $this->_packagexml->getPackage() . '" is different from extension name "' .
                    $this->_packagexml->getProvidesExtension() . '"');
            }
        }
        return $ret;
    }
}
?>PKq�Zp�����PEAR/Dependency2.phpnu�[���<?php
/**
 * PEAR_Dependency2, advanced dependency validation
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a1
 */

/**
 * Required for the PEAR_VALIDATE_* constants
 */
require_once 'PEAR/Validate.php';

/**
 * Dependency check for PEAR packages
 *
 * This class handles both version 1.0 and 2.0 dependencies
 * WARNING: *any* changes to this class must be duplicated in the
 * test_PEAR_Dependency2 class found in tests/PEAR_Dependency2/setup.php.inc,
 * or unit tests will not actually validate the changes
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 */
class PEAR_Dependency2
{
    /**
     * One of the PEAR_VALIDATE_* states
     * @see PEAR_VALIDATE_NORMAL
     * @var integer
     */
    var $_state;

    /**
     * Command-line options to install/upgrade/uninstall commands
     * @param array
     */
    var $_options;

    /**
     * @var OS_Guess
     */
    var $_os;

    /**
     * @var PEAR_Registry
     */
    var $_registry;

    /**
     * @var PEAR_Config
     */
    var $_config;

    /**
     * @var PEAR_DependencyDB
     */
    var $_dependencydb;

    /**
     * Output of PEAR_Registry::parsedPackageName()
     * @var array
     */
    var $_currentPackage;

    /**
     * @param PEAR_Config
     * @param array installation options
     * @param array format of PEAR_Registry::parsedPackageName()
     * @param int installation state (one of PEAR_VALIDATE_*)
     */
    function __construct(&$config, $installoptions, $package,
                              $state = PEAR_VALIDATE_INSTALLING)
    {
        $this->_config = &$config;
        if (!class_exists('PEAR_DependencyDB')) {
            require_once 'PEAR/DependencyDB.php';
        }

        if (isset($installoptions['packagingroot'])) {
            // make sure depdb is in the right location
            $config->setInstallRoot($installoptions['packagingroot']);
        }

        $this->_registry = &$config->getRegistry();
        $this->_dependencydb = &PEAR_DependencyDB::singleton($config);
        if (isset($installoptions['packagingroot'])) {
            $config->setInstallRoot(false);
        }

        $this->_options = $installoptions;
        $this->_state = $state;
        if (!class_exists('OS_Guess')) {
            require_once 'OS/Guess.php';
        }

        $this->_os = new OS_Guess;
        $this->_currentPackage = $package;
    }

    static function _getExtraString($dep)
    {
        $extra = ' (';
        if (isset($dep['uri'])) {
            return '';
        }

        if (isset($dep['recommended'])) {
            $extra .= 'recommended version ' . $dep['recommended'];
        } else {
            if (isset($dep['min'])) {
                $extra .= 'version >= ' . $dep['min'];
            }

            if (isset($dep['max'])) {
                if ($extra != ' (') {
                    $extra .= ', ';
                }
                $extra .= 'version <= ' . $dep['max'];
            }

            if (isset($dep['exclude'])) {
                if (!is_array($dep['exclude'])) {
                    $dep['exclude'] = array($dep['exclude']);
                }

                if ($extra != ' (') {
                    $extra .= ', ';
                }

                $extra .= 'excluded versions: ';
                foreach ($dep['exclude'] as $i => $exclude) {
                    if ($i) {
                        $extra .= ', ';
                    }
                    $extra .= $exclude;
                }
            }
        }

        $extra .= ')';
        if ($extra == ' ()') {
            $extra = '';
        }

        return $extra;
    }

    /**
     * This makes unit-testing a heck of a lot easier
     */
    function getPHP_OS()
    {
        return PHP_OS;
    }

    /**
     * This makes unit-testing a heck of a lot easier
     */
    function getsysname()
    {
        return $this->_os->getSysname();
    }

    /**
     * Specify a dependency on an OS.  Use arch for detailed os/processor information
     *
     * There are two generic OS dependencies that will be the most common, unix and windows.
     * Other options are linux, freebsd, darwin (OS X), sunos, irix, hpux, aix
     */
    function validateOsDependency($dep)
    {
        if ($this->_state != PEAR_VALIDATE_INSTALLING && $this->_state != PEAR_VALIDATE_DOWNLOADING) {
            return true;
        }

        if ($dep['name'] == '*') {
            return true;
        }

        $not = isset($dep['conflicts']) ? true : false;
        switch (strtolower($dep['name'])) {
            case 'windows' :
                if ($not) {
                    if (strtolower(substr($this->getPHP_OS(), 0, 3)) == 'win') {
                        if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                            return $this->raiseError("Cannot install %s on Windows");
                        }

                        return $this->warning("warning: Cannot install %s on Windows");
                    }
                } else {
                    if (strtolower(substr($this->getPHP_OS(), 0, 3)) != 'win') {
                        if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                            return $this->raiseError("Can only install %s on Windows");
                        }

                        return $this->warning("warning: Can only install %s on Windows");
                    }
                }
            break;
            case 'unix' :
                $unices = array('linux', 'freebsd', 'darwin', 'sunos', 'irix', 'hpux', 'aix');
                if ($not) {
                    if (in_array($this->getSysname(), $unices)) {
                        if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                            return $this->raiseError("Cannot install %s on any Unix system");
                        }

                        return $this->warning( "warning: Cannot install %s on any Unix system");
                    }
                } else {
                    if (!in_array($this->getSysname(), $unices)) {
                        if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                            return $this->raiseError("Can only install %s on a Unix system");
                        }

                        return $this->warning("warning: Can only install %s on a Unix system");
                    }
                }
            break;
            default :
                if ($not) {
                    if (strtolower($dep['name']) == strtolower($this->getSysname())) {
                        if (!isset($this->_options['nodeps']) &&
                              !isset($this->_options['force'])) {
                            return $this->raiseError('Cannot install %s on ' . $dep['name'] .
                                ' operating system');
                        }

                        return $this->warning('warning: Cannot install %s on ' .
                            $dep['name'] . ' operating system');
                    }
                } else {
                    if (strtolower($dep['name']) != strtolower($this->getSysname())) {
                        if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                            return $this->raiseError('Cannot install %s on ' .
                                $this->getSysname() .
                                ' operating system, can only install on ' . $dep['name']);
                        }

                        return $this->warning('warning: Cannot install %s on ' .
                            $this->getSysname() .
                            ' operating system, can only install on ' . $dep['name']);
                    }
                }
        }
        return true;
    }

    /**
     * This makes unit-testing a heck of a lot easier
     */
    function matchSignature($pattern)
    {
        return $this->_os->matchSignature($pattern);
    }

    /**
     * Specify a complex dependency on an OS/processor/kernel version,
     * Use OS for simple operating system dependency.
     *
     * This is the only dependency that accepts an eregable pattern.  The pattern
     * will be matched against the php_uname() output parsed by OS_Guess
     */
    function validateArchDependency($dep)
    {
        if ($this->_state != PEAR_VALIDATE_INSTALLING) {
            return true;
        }

        $not = isset($dep['conflicts']) ? true : false;
        if (!$this->matchSignature($dep['pattern'])) {
            if (!$not) {
                if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                    return $this->raiseError('%s Architecture dependency failed, does not ' .
                        'match "' . $dep['pattern'] . '"');
                }

                return $this->warning('warning: %s Architecture dependency failed, does ' .
                    'not match "' . $dep['pattern'] . '"');
            }

            return true;
        }

        if ($not) {
            if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                return $this->raiseError('%s Architecture dependency failed, required "' .
                    $dep['pattern'] . '"');
            }

            return $this->warning('warning: %s Architecture dependency failed, ' .
                'required "' . $dep['pattern'] . '"');
        }

        return true;
    }

    /**
     * This makes unit-testing a heck of a lot easier
     */
    function extension_loaded($name)
    {
        return extension_loaded($name);
    }

    /**
     * This makes unit-testing a heck of a lot easier
     */
    function phpversion($name = null)
    {
        if ($name !== null) {
            return phpversion($name);
        }

        return phpversion();
    }

    function validateExtensionDependency($dep, $required = true)
    {
        if ($this->_state != PEAR_VALIDATE_INSTALLING &&
              $this->_state != PEAR_VALIDATE_DOWNLOADING) {
            return true;
        }

        $loaded = $this->extension_loaded($dep['name']);
        $extra  = self::_getExtraString($dep);
        if (isset($dep['exclude'])) {
            if (!is_array($dep['exclude'])) {
                $dep['exclude'] = array($dep['exclude']);
            }
        }

        if (!isset($dep['min']) && !isset($dep['max']) &&
            !isset($dep['recommended']) && !isset($dep['exclude'])
        ) {
            if ($loaded) {
                if (isset($dep['conflicts'])) {
                    if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                        return $this->raiseError('%s conflicts with PHP extension "' .
                            $dep['name'] . '"' . $extra);
                    }

                    return $this->warning('warning: %s conflicts with PHP extension "' .
                        $dep['name'] . '"' . $extra);
                }

                return true;
            }

            if (isset($dep['conflicts'])) {
                return true;
            }

            if ($required) {
                if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                    return $this->raiseError('%s requires PHP extension "' .
                        $dep['name'] . '"' . $extra);
                }

                return $this->warning('warning: %s requires PHP extension "' .
                    $dep['name'] . '"' . $extra);
            }

            return $this->warning('%s can optionally use PHP extension "' .
                $dep['name'] . '"' . $extra);
        }

        if (!$loaded) {
            if (isset($dep['conflicts'])) {
                return true;
            }

            if (!$required) {
                return $this->warning('%s can optionally use PHP extension "' .
                    $dep['name'] . '"' . $extra);
            }

            if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                return $this->raiseError('%s requires PHP extension "' . $dep['name'] .
                    '"' . $extra);
            }

            return $this->warning('warning: %s requires PHP extension "' . $dep['name'] .
                    '"' . $extra);
        }

        $version = (string) $this->phpversion($dep['name']);
        if (empty($version)) {
            $version = '0';
        }

        $fail = false;
        if (isset($dep['min']) && !version_compare($version, $dep['min'], '>=')) {
            $fail = true;
        }

        if (isset($dep['max']) && !version_compare($version, $dep['max'], '<=')) {
            $fail = true;
        }

        if ($fail && !isset($dep['conflicts'])) {
            if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                return $this->raiseError('%s requires PHP extension "' . $dep['name'] .
                    '"' . $extra . ', installed version is ' . $version);
            }

            return $this->warning('warning: %s requires PHP extension "' . $dep['name'] .
                '"' . $extra . ', installed version is ' . $version);
        } elseif ((isset($dep['min']) || isset($dep['max'])) && !$fail && isset($dep['conflicts'])) {
            if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                return $this->raiseError('%s conflicts with PHP extension "' .
                    $dep['name'] . '"' . $extra . ', installed version is ' . $version);
            }

            return $this->warning('warning: %s conflicts with PHP extension "' .
                $dep['name'] . '"' . $extra . ', installed version is ' . $version);
        }

        if (isset($dep['exclude'])) {
            foreach ($dep['exclude'] as $exclude) {
                if (version_compare($version, $exclude, '==')) {
                    if (isset($dep['conflicts'])) {
                        continue;
                    }

                    if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                        return $this->raiseError('%s is not compatible with PHP extension "' .
                            $dep['name'] . '" version ' .
                            $exclude);
                    }

                    return $this->warning('warning: %s is not compatible with PHP extension "' .
                        $dep['name'] . '" version ' .
                        $exclude);
                } elseif (version_compare($version, $exclude, '!=') && isset($dep['conflicts'])) {
                    if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                        return $this->raiseError('%s conflicts with PHP extension "' .
                            $dep['name'] . '"' . $extra . ', installed version is ' . $version);
                    }

                    return $this->warning('warning: %s conflicts with PHP extension "' .
                        $dep['name'] . '"' . $extra . ', installed version is ' . $version);
                }
            }
        }

        if (isset($dep['recommended'])) {
            if (version_compare($version, $dep['recommended'], '==')) {
                return true;
            }

            if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                return $this->raiseError('%s dependency: PHP extension ' . $dep['name'] .
                    ' version "' . $version . '"' .
                    ' is not the recommended version "' . $dep['recommended'] .
                    '", but may be compatible, use --force to install');
            }

            return $this->warning('warning: %s dependency: PHP extension ' .
                $dep['name'] . ' version "' . $version . '"' .
                ' is not the recommended version "' . $dep['recommended'].'"');
        }

        return true;
    }

    function validatePhpDependency($dep)
    {
        if ($this->_state != PEAR_VALIDATE_INSTALLING &&
              $this->_state != PEAR_VALIDATE_DOWNLOADING) {
            return true;
        }

        $version = $this->phpversion();
        $extra   = self::_getExtraString($dep);
        if (isset($dep['exclude'])) {
            if (!is_array($dep['exclude'])) {
                $dep['exclude'] = array($dep['exclude']);
            }
        }

        if (isset($dep['min'])) {
            if (!version_compare($version, $dep['min'], '>=')) {
                if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                    return $this->raiseError('%s requires PHP' .
                        $extra . ', installed version is ' . $version);
                }

                return $this->warning('warning: %s requires PHP' .
                    $extra . ', installed version is ' . $version);
            }
        }

        if (isset($dep['max'])) {
            if (!version_compare($version, $dep['max'], '<=')) {
                if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                    return $this->raiseError('%s requires PHP' .
                        $extra . ', installed version is ' . $version);
                }

                return $this->warning('warning: %s requires PHP' .
                    $extra . ', installed version is ' . $version);
            }
        }

        if (isset($dep['exclude'])) {
            foreach ($dep['exclude'] as $exclude) {
                if (version_compare($version, $exclude, '==')) {
                    if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                        return $this->raiseError('%s is not compatible with PHP version ' .
                            $exclude);
                    }

                    return $this->warning(
                        'warning: %s is not compatible with PHP version ' .
                        $exclude);
                }
            }
        }

        return true;
    }

    /**
     * This makes unit-testing a heck of a lot easier
     */
    function getPEARVersion()
    {
        return '1.10.16';
    }

    function validatePearinstallerDependency($dep)
    {
        $pearversion = $this->getPEARVersion();
        $extra = self::_getExtraString($dep);
        if (isset($dep['exclude'])) {
            if (!is_array($dep['exclude'])) {
                $dep['exclude'] = array($dep['exclude']);
            }
        }

        if (version_compare($pearversion, $dep['min'], '<')) {
            if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                return $this->raiseError('%s requires PEAR Installer' . $extra .
                    ', installed version is ' . $pearversion);
            }

            return $this->warning('warning: %s requires PEAR Installer' . $extra .
                ', installed version is ' . $pearversion);
        }

        if (isset($dep['max'])) {
            if (version_compare($pearversion, $dep['max'], '>')) {
                if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                    return $this->raiseError('%s requires PEAR Installer' . $extra .
                        ', installed version is ' . $pearversion);
                }

                return $this->warning('warning: %s requires PEAR Installer' . $extra .
                    ', installed version is ' . $pearversion);
            }
        }

        if (isset($dep['exclude'])) {
            if (!isset($dep['exclude'][0])) {
                $dep['exclude'] = array($dep['exclude']);
            }

            foreach ($dep['exclude'] as $exclude) {
                if (version_compare($exclude, $pearversion, '==')) {
                    if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                        return $this->raiseError('%s is not compatible with PEAR Installer ' .
                            'version ' . $exclude);
                    }

                    return $this->warning('warning: %s is not compatible with PEAR ' .
                        'Installer version ' . $exclude);
                }
            }
        }

        return true;
    }

    function validateSubpackageDependency($dep, $required, $params)
    {
        return $this->validatePackageDependency($dep, $required, $params);
    }

    /**
     * @param array dependency information (2.0 format)
     * @param boolean whether this is a required dependency
     * @param array a list of downloaded packages to be installed, if any
     * @param boolean if true, then deps on pear.php.net that fail will also check
     *                against pecl.php.net packages to accommodate extensions that have
     *                moved to pecl.php.net from pear.php.net
     */
    function validatePackageDependency($dep, $required, $params, $depv1 = false)
    {
        if ($this->_state != PEAR_VALIDATE_INSTALLING &&
              $this->_state != PEAR_VALIDATE_DOWNLOADING) {
            return true;
        }

        if (isset($dep['providesextension'])) {
            if ($this->extension_loaded($dep['providesextension'])) {
                $save = $dep;
                $subdep = $dep;
                $subdep['name'] = $subdep['providesextension'];
                PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                $ret = $this->validateExtensionDependency($subdep, $required);
                PEAR::popErrorHandling();
                if (!PEAR::isError($ret)) {
                    return true;
                }
            }
        }

        if ($this->_state == PEAR_VALIDATE_INSTALLING) {
            return $this->_validatePackageInstall($dep, $required, $depv1);
        }

        if ($this->_state == PEAR_VALIDATE_DOWNLOADING) {
            return $this->_validatePackageDownload($dep, $required, $params, $depv1);
        }
    }

    function _validatePackageDownload($dep, $required, $params, $depv1 = false)
    {
        $dep['package'] = $dep['name'];
        if (isset($dep['uri'])) {
            $dep['channel'] = '__uri';
        }

        $depname = $this->_registry->parsedPackageNameToString($dep, true);
        $found = false;
        foreach ($params as $param) {
            if ($param->isEqual(
                  array('package' => $dep['name'],
                        'channel' => $dep['channel']))) {
                $found = true;
                break;
            }

            if ($depv1 && $dep['channel'] == 'pear.php.net') {
                if ($param->isEqual(
                  array('package' => $dep['name'],
                        'channel' => 'pecl.php.net'))) {
                    $found = true;
                    break;
                }
            }
        }

        if (!$found && isset($dep['providesextension'])) {
            foreach ($params as $param) {
                if ($param->isExtension($dep['providesextension'])) {
                    $found = true;
                    break;
                }
            }
        }

        if ($found) {
            $version = $param->getVersion();
            $installed = false;
            $downloaded = true;
        } else {
            if ($this->_registry->packageExists($dep['name'], $dep['channel'])) {
                $installed = true;
                $downloaded = false;
                $version = $this->_registry->packageinfo($dep['name'], 'version',
                    $dep['channel']);
            } else {
                if ($dep['channel'] == 'pecl.php.net' && $this->_registry->packageExists($dep['name'],
                      'pear.php.net')) {
                    $installed = true;
                    $downloaded = false;
                    $version = $this->_registry->packageinfo($dep['name'], 'version',
                        'pear.php.net');
                } else {
                    $version = 'not installed or downloaded';
                    $installed = false;
                    $downloaded = false;
                }
            }
        }

        $extra = self::_getExtraString($dep);
        if (isset($dep['exclude']) && !is_array($dep['exclude'])) {
            $dep['exclude'] = array($dep['exclude']);
        }

        if (!isset($dep['min']) && !isset($dep['max']) &&
              !isset($dep['recommended']) && !isset($dep['exclude'])
        ) {
            if ($installed || $downloaded) {
                $installed = $installed ? 'installed' : 'downloaded';
                if (isset($dep['conflicts'])) {
                    $rest = '';
                    if ($version) {
                        $rest = ", $installed version is " . $version;
                    }

                    if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                        return $this->raiseError('%s conflicts with package "' . $depname . '"' . $extra . $rest);
                    }

                    return $this->warning('warning: %s conflicts with package "' . $depname . '"' . $extra . $rest);
                }

                return true;
            }

            if (isset($dep['conflicts'])) {
                return true;
            }

            if ($required) {
                if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                    return $this->raiseError('%s requires package "' . $depname . '"' . $extra);
                }

                return $this->warning('warning: %s requires package "' . $depname . '"' . $extra);
            }

            return $this->warning('%s can optionally use package "' . $depname . '"' . $extra);
        }

        if (!$installed && !$downloaded) {
            if (isset($dep['conflicts'])) {
                return true;
            }

            if ($required) {
                if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                    return $this->raiseError('%s requires package "' . $depname . '"' . $extra);
                }

                return $this->warning('warning: %s requires package "' . $depname . '"' . $extra);
            }

            return $this->warning('%s can optionally use package "' . $depname . '"' . $extra);
        }

        $fail = false;
        if (isset($dep['min']) && version_compare($version, $dep['min'], '<')) {
            $fail = true;
        }

        if (isset($dep['max']) && version_compare($version, $dep['max'], '>')) {
            $fail = true;
        }

        if ($fail && !isset($dep['conflicts'])) {
            $installed = $installed ? 'installed' : 'downloaded';
            $dep['package'] = $dep['name'];
            $dep = $this->_registry->parsedPackageNameToString($dep, true);
            if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                return $this->raiseError('%s requires package "' . $depname . '"' .
                    $extra . ", $installed version is " . $version);
            }

            return $this->warning('warning: %s requires package "' . $depname . '"' .
                $extra . ", $installed version is " . $version);
        } elseif ((isset($dep['min']) || isset($dep['max'])) && !$fail &&
              isset($dep['conflicts']) && !isset($dep['exclude'])) {
            $installed = $installed ? 'installed' : 'downloaded';
            if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                return $this->raiseError('%s conflicts with package "' . $depname . '"' . $extra .
                    ", $installed version is " . $version);
            }

            return $this->warning('warning: %s conflicts with package "' . $depname . '"' .
                $extra . ", $installed version is " . $version);
        }

        if (isset($dep['exclude'])) {
            $installed = $installed ? 'installed' : 'downloaded';
            foreach ($dep['exclude'] as $exclude) {
                if (version_compare($version, $exclude, '==') && !isset($dep['conflicts'])) {
                    if (!isset($this->_options['nodeps']) &&
                          !isset($this->_options['force'])
                    ) {
                        return $this->raiseError('%s is not compatible with ' .
                            $installed . ' package "' .
                            $depname . '" version ' .
                            $exclude);
                    }

                    return $this->warning('warning: %s is not compatible with ' .
                        $installed . ' package "' .
                        $depname . '" version ' .
                        $exclude);
                } elseif (version_compare($version, $exclude, '!=') && isset($dep['conflicts'])) {
                    $installed = $installed ? 'installed' : 'downloaded';
                    if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                        return $this->raiseError('%s conflicts with package "' . $depname . '"' .
                            $extra . ", $installed version is " . $version);
                    }

                    return $this->warning('warning: %s conflicts with package "' . $depname . '"' .
                        $extra . ", $installed version is " . $version);
                }
            }
        }

        if (isset($dep['recommended'])) {
            $installed = $installed ? 'installed' : 'downloaded';
            if (version_compare($version, $dep['recommended'], '==')) {
                return true;
            }

            if (!$found && $installed) {
                $param = $this->_registry->getPackage($dep['name'], $dep['channel']);
            }

            if ($param) {
                $found = false;
                foreach ($params as $parent) {
                    if ($parent->isEqual($this->_currentPackage)) {
                        $found = true;
                        break;
                    }
                }

                if ($found) {
                    if ($param->isCompatible($parent)) {
                        return true;
                    }
                } else { // this is for validPackage() calls
                    $parent = $this->_registry->getPackage($this->_currentPackage['package'],
                        $this->_currentPackage['channel']);
                    if ($parent !== null && $param->isCompatible($parent)) {
                        return true;
                    }
                }
            }

            if (!isset($this->_options['nodeps']) && !isset($this->_options['force']) &&
                  !isset($this->_options['loose'])
            ) {
                return $this->raiseError('%s dependency package "' . $depname .
                    '" ' . $installed . ' version ' . $version .
                    ' is not the recommended version ' . $dep['recommended'] .
                    ', but may be compatible, use --force to install');
            }

            return $this->warning('warning: %s dependency package "' . $depname .
                '" ' . $installed . ' version ' . $version .
                ' is not the recommended version ' . $dep['recommended']);
        }

        return true;
    }

    function _validatePackageInstall($dep, $required, $depv1 = false)
    {
        return $this->_validatePackageDownload($dep, $required, array(), $depv1);
    }

    /**
     * Verify that uninstalling packages passed in to command line is OK.
     *
     * @param PEAR_Installer $dl
     * @return PEAR_Error|true
     */
    function validatePackageUninstall(&$dl)
    {
        if (PEAR::isError($this->_dependencydb)) {
            return $this->_dependencydb;
        }

        $params = array();
        // construct an array of "downloaded" packages to fool the package dependency checker
        // into using these to validate uninstalls of circular dependencies
        $downloaded = &$dl->getUninstallPackages();
        foreach ($downloaded as $i => $pf) {
            if (!class_exists('PEAR_Downloader_Package')) {
                require_once 'PEAR/Downloader/Package.php';
            }
            $dp = new PEAR_Downloader_Package($dl);
            $dp->setPackageFile($downloaded[$i]);
            $params[$i] = $dp;
        }

        // check cache
        $memyselfandI = strtolower($this->_currentPackage['channel']) . '/' .
            strtolower($this->_currentPackage['package']);
        if (isset($dl->___uninstall_package_cache)) {
            $badpackages = $dl->___uninstall_package_cache;
            if (isset($badpackages[$memyselfandI]['warnings'])) {
                foreach ($badpackages[$memyselfandI]['warnings'] as $warning) {
                    $dl->log(0, $warning[0]);
                }
            }

            if (isset($badpackages[$memyselfandI]['errors'])) {
                foreach ($badpackages[$memyselfandI]['errors'] as $error) {
                    if (is_array($error)) {
                        $dl->log(0, $error[0]);
                    } else {
                        $dl->log(0, $error->getMessage());
                    }
                }

                if (isset($this->_options['nodeps']) || isset($this->_options['force'])) {
                    return $this->warning(
                        'warning: %s should not be uninstalled, other installed packages depend ' .
                        'on this package');
                }

                return $this->raiseError(
                    '%s cannot be uninstalled, other installed packages depend on this package');
            }

            return true;
        }

        // first, list the immediate parents of each package to be uninstalled
        $perpackagelist = array();
        $allparents = array();
        foreach ($params as $i => $param) {
            $a = array(
                'channel' => strtolower($param->getChannel()),
                'package' => strtolower($param->getPackage())
            );

            $deps = $this->_dependencydb->getDependentPackages($a);
            if ($deps) {
                foreach ($deps as $d) {
                    $pardeps = $this->_dependencydb->getDependencies($d);
                    foreach ($pardeps as $dep) {
                        if (strtolower($dep['dep']['channel']) == $a['channel'] &&
                              strtolower($dep['dep']['name']) == $a['package']) {
                            if (!isset($perpackagelist[$a['channel'] . '/' . $a['package']])) {
                                $perpackagelist[$a['channel'] . '/' . $a['package']] = array();
                            }
                            $perpackagelist[$a['channel'] . '/' . $a['package']][]
                                = array($d['channel'] . '/' . $d['package'], $dep);
                            if (!isset($allparents[$d['channel'] . '/' . $d['package']])) {
                                $allparents[$d['channel'] . '/' . $d['package']] = array();
                            }
                            if (!isset($allparents[$d['channel'] . '/' . $d['package']][$a['channel'] . '/' . $a['package']])) {
                                $allparents[$d['channel'] . '/' . $d['package']][$a['channel'] . '/' . $a['package']] = array();
                            }
                            $allparents[$d['channel'] . '/' . $d['package']]
                                       [$a['channel'] . '/' . $a['package']][]
                                = array($d, $dep);
                        }
                    }
                }
            }
        }

        // next, remove any packages from the parents list that are not installed
        $remove = array();
        foreach ($allparents as $parent => $d1) {
            foreach ($d1 as $d) {
                if ($this->_registry->packageExists($d[0][0]['package'], $d[0][0]['channel'])) {
                    continue;
                }
                $remove[$parent] = true;
            }
        }

        // next remove any packages from the parents list that are not passed in for
        // uninstallation
        foreach ($allparents as $parent => $d1) {
            foreach ($d1 as $d) {
                foreach ($params as $param) {
                    if (strtolower($param->getChannel()) == $d[0][0]['channel'] &&
                          strtolower($param->getPackage()) == $d[0][0]['package']) {
                        // found it
                        continue 3;
                    }
                }
                $remove[$parent] = true;
            }
        }

        // remove all packages whose dependencies fail
        // save which ones failed for error reporting
        $badchildren = array();
        do {
            $fail = false;
            foreach ($remove as $package => $unused) {
                if (!isset($allparents[$package])) {
                    continue;
                }

                foreach ($allparents[$package] as $kid => $d1) {
                    foreach ($d1 as $depinfo) {
                        if ($depinfo[1]['type'] != 'optional') {
                            if (isset($badchildren[$kid])) {
                                continue;
                            }
                            $badchildren[$kid] = true;
                            $remove[$kid] = true;
                            $fail = true;
                            continue 2;
                        }
                    }
                }
                if ($fail) {
                    // start over, we removed some children
                    continue 2;
                }
            }
        } while ($fail);

        // next, construct the list of packages that can't be uninstalled
        $badpackages = array();
        $save = $this->_currentPackage;
        foreach ($perpackagelist as $package => $packagedeps) {
            foreach ($packagedeps as $parent) {
                if (!isset($remove[$parent[0]])) {
                    continue;
                }

                $packagename = $this->_registry->parsePackageName($parent[0]);
                $packagename['channel'] = $this->_registry->channelAlias($packagename['channel']);
                $pa = $this->_registry->getPackage($packagename['package'], $packagename['channel']);
                $packagename['package'] = $pa->getPackage();
                $this->_currentPackage = $packagename;
                // parent is not present in uninstall list, make sure we can actually
                // uninstall it (parent dep is optional)
                $parentname['channel'] = $this->_registry->channelAlias($parent[1]['dep']['channel']);
                $pa = $this->_registry->getPackage($parent[1]['dep']['name'], $parent[1]['dep']['channel']);
                $parentname['package'] = $pa->getPackage();
                $parent[1]['dep']['package'] = $parentname['package'];
                $parent[1]['dep']['channel'] = $parentname['channel'];
                if ($parent[1]['type'] == 'optional') {
                    $test = $this->_validatePackageUninstall($parent[1]['dep'], false, $dl);
                    if ($test !== true) {
                        $badpackages[$package]['warnings'][] = $test;
                    }
                } else {
                    $test = $this->_validatePackageUninstall($parent[1]['dep'], true, $dl);
                    if ($test !== true) {
                        $badpackages[$package]['errors'][] = $test;
                    }
                }
            }
        }

        $this->_currentPackage          = $save;
        $dl->___uninstall_package_cache = $badpackages;
        if (isset($badpackages[$memyselfandI])) {
            if (isset($badpackages[$memyselfandI]['warnings'])) {
                foreach ($badpackages[$memyselfandI]['warnings'] as $warning) {
                    $dl->log(0, $warning[0]);
                }
            }

            if (isset($badpackages[$memyselfandI]['errors'])) {
                foreach ($badpackages[$memyselfandI]['errors'] as $error) {
                    if (is_array($error)) {
                        $dl->log(0, $error[0]);
                    } else {
                        $dl->log(0, $error->getMessage());
                    }
                }

                if (isset($this->_options['nodeps']) || isset($this->_options['force'])) {
                    return $this->warning(
                        'warning: %s should not be uninstalled, other installed packages depend ' .
                        'on this package');
                }

                return $this->raiseError(
                    '%s cannot be uninstalled, other installed packages depend on this package');
            }
        }

        return true;
    }

    function _validatePackageUninstall($dep, $required, $dl)
    {
        $depname = $this->_registry->parsedPackageNameToString($dep, true);
        $version = $this->_registry->packageinfo($dep['package'], 'version', $dep['channel']);
        if (!$version) {
            return true;
        }

        $extra = self::_getExtraString($dep);
        if (isset($dep['exclude']) && !is_array($dep['exclude'])) {
            $dep['exclude'] = array($dep['exclude']);
        }

        if (isset($dep['conflicts'])) {
            return true; // uninstall OK - these packages conflict (probably installed with --force)
        }

        if (!isset($dep['min']) && !isset($dep['max'])) {
            if (!$required) {
                return $this->warning('"' . $depname . '" can be optionally used by ' .
                        'installed package %s' . $extra);
            }

            if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                return $this->raiseError('"' . $depname . '" is required by ' .
                    'installed package %s' . $extra);
            }

            return $this->warning('warning: "' . $depname . '" is required by ' .
                'installed package %s' . $extra);
        }

        $fail = false;
        if (isset($dep['min']) && version_compare($version, $dep['min'], '>=')) {
            $fail = true;
        }

        if (isset($dep['max']) && version_compare($version, $dep['max'], '<=')) {
            $fail = true;
        }

        // we re-use this variable, preserve the original value
        $saverequired = $required;
        if (!$required) {
            return $this->warning($depname . $extra . ' can be optionally used by installed package' .
                    ' "%s"');
        }

        if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
            return $this->raiseError($depname . $extra . ' is required by installed package' .
                ' "%s"');
        }

        return $this->raiseError('warning: ' . $depname . $extra .
            ' is required by installed package "%s"');
    }

    /**
     * validate a downloaded package against installed packages
     *
     * As of PEAR 1.4.3, this will only validate
     *
     * @param array|PEAR_Downloader_Package|PEAR_PackageFile_v1|PEAR_PackageFile_v2
     *              $pkg package identifier (either
     *                   array('package' => blah, 'channel' => blah) or an array with
     *                   index 'info' referencing an object)
     * @param PEAR_Downloader $dl
     * @param array $params full list of packages to install
     * @return true|PEAR_Error
     */
    function validatePackage($pkg, &$dl, $params = array())
    {
        if (is_array($pkg) && isset($pkg['info'])) {
            $deps = $this->_dependencydb->getDependentPackageDependencies($pkg['info']);
        } else {
            $deps = $this->_dependencydb->getDependentPackageDependencies($pkg);
        }

        $fail = false;
        if ($deps) {
            if (!class_exists('PEAR_Downloader_Package')) {
                require_once 'PEAR/Downloader/Package.php';
            }

            $dp = new PEAR_Downloader_Package($dl);
            if (is_object($pkg)) {
                $dp->setPackageFile($pkg);
            } else {
                $dp->setDownloadURL($pkg);
            }

            PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
            foreach ($deps as $channel => $info) {
                foreach ($info as $package => $ds) {
                    foreach ($params as $packd) {
                        if (strtolower($packd->getPackage()) == strtolower($package) &&
                              $packd->getChannel() == $channel) {
                            $dl->log(3, 'skipping installed package check of "' .
                                        $this->_registry->parsedPackageNameToString(
                                            array('channel' => $channel, 'package' => $package),
                                            true) .
                                        '", version "' . $packd->getVersion() . '" will be ' .
                                        'downloaded and installed');
                            continue 2; // jump to next package
                        }
                    }

                    foreach ($ds as $d) {
                        $checker = new PEAR_Dependency2($this->_config, $this->_options,
                            array('channel' => $channel, 'package' => $package), $this->_state);
                        $dep = $d['dep'];
                        $required = $d['type'] == 'required';
                        $ret = $checker->_validatePackageDownload($dep, $required, array(&$dp));
                        if (is_array($ret)) {
                            $dl->log(0, $ret[0]);
                        } elseif (PEAR::isError($ret)) {
                            $dl->log(0, $ret->getMessage());
                            $fail = true;
                        }
                    }
                }
            }
            PEAR::popErrorHandling();
        }

        if ($fail) {
            return $this->raiseError(
                '%s cannot be installed, conflicts with installed packages');
        }

        return true;
    }

    /**
     * validate a package.xml 1.0 dependency
     */
    function validateDependency1($dep, $params = array())
    {
        if (!isset($dep['optional'])) {
            $dep['optional'] = 'no';
        }

        list($newdep, $type) = self::normalizeDep($dep);
        if (!$newdep) {
            return $this->raiseError("Invalid Dependency");
        }

        if (method_exists($this, "validate{$type}Dependency")) {
            return $this->{"validate{$type}Dependency"}($newdep, $dep['optional'] == 'no',
                $params, true);
        }
    }

    /**
     * Convert a 1.0 dep into a 2.0 dep
     */
    static function normalizeDep($dep)
    {
        $types = array(
            'pkg' => 'Package',
            'ext' => 'Extension',
            'os' => 'Os',
            'php' => 'Php'
        );

        if (!isset($types[$dep['type']])) {
            return array(false, false);
        }

        $type = $types[$dep['type']];

        $newdep = array();
        switch ($type) {
            case 'Package' :
                $newdep['channel'] = 'pear.php.net';
            case 'Extension' :
            case 'Os' :
                $newdep['name'] = $dep['name'];
            break;
        }

        $dep['rel'] = PEAR_Dependency2::signOperator($dep['rel']);
        switch ($dep['rel']) {
            case 'has' :
                return array($newdep, $type);
            break;
            case 'not' :
                $newdep['conflicts'] = true;
            break;
            case '>=' :
            case '>' :
                $newdep['min'] = $dep['version'];
                if ($dep['rel'] == '>') {
                    $newdep['exclude'] = $dep['version'];
                }
            break;
            case '<=' :
            case '<' :
                $newdep['max'] = $dep['version'];
                if ($dep['rel'] == '<') {
                    $newdep['exclude'] = $dep['version'];
                }
            break;
            case 'ne' :
            case '!=' :
                $newdep['min'] = '0';
                $newdep['max'] = '100000';
                $newdep['exclude'] = $dep['version'];
            break;
            case '==' :
                $newdep['min'] = $dep['version'];
                $newdep['max'] = $dep['version'];
            break;
        }
        if ($type == 'Php') {
            if (!isset($newdep['min'])) {
                $newdep['min'] = '4.4.0';
            }

            if (!isset($newdep['max'])) {
                $newdep['max'] = '6.0.0';
            }
        }
        return array($newdep, $type);
    }

    /**
     * Converts text comparing operators to them sign equivalents
     *
     * Example: 'ge' to '>='
     *
     * @access public
     * @param  string Operator
     * @return string Sign equivalent
     */
    static function signOperator($operator)
    {
        switch($operator) {
            case 'lt': return '<';
            case 'le': return '<=';
            case 'gt': return '>';
            case 'ge': return '>=';
            case 'eq': return '==';
            case 'ne': return '!=';
            default:
                return $operator;
        }
    }

    function raiseError($msg)
    {
        if (isset($this->_options['ignore-errors'])) {
            return $this->warning($msg);
        }

        return PEAR::raiseError(sprintf($msg, $this->_registry->parsedPackageNameToString(
            $this->_currentPackage, true)));
    }

    function warning($msg)
    {
        return array(sprintf($msg, $this->_registry->parsedPackageNameToString(
            $this->_currentPackage, true)));
    }
}
PKq�Z��wv@@PEAR/PackageFile/v2.phpnu�[���<?php
/**
 * PEAR_PackageFile_v2, package.xml version 2.0
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a1
 */
/**
 * For error handling
 */
require_once 'PEAR/ErrorStack.php';
/**
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 */
class PEAR_PackageFile_v2
{

    /**
     * Parsed package information
     * @var array
     * @access private
     */
    var $_packageInfo = array();

    /**
     * path to package .tgz or false if this is a local/extracted package.xml
     * @var string|false
     * @access private
     */
    var $_archiveFile;

    /**
     * path to package .xml or false if this is an abstract parsed-from-string xml
     * @var string|false
     * @access private
     */
    var $_packageFile;

    /**
     * This is used by file analysis routines to log progress information
     * @var PEAR_Common
     * @access protected
     */
    var $_logger;

    /**
     * This is set to the highest validation level that has been validated
     *
     * If the package.xml is invalid or unknown, this is set to 0.  If
     * normal validation has occurred, this is set to PEAR_VALIDATE_NORMAL.  If
     * downloading/installation validation has occurred it is set to PEAR_VALIDATE_DOWNLOADING
     * or INSTALLING, and so on up to PEAR_VALIDATE_PACKAGING.  This allows validation
     * "caching" to occur, which is particularly important for package validation, so
     * that PHP files are not validated twice
     * @var int
     * @access private
     */
    var $_isValid = 0;

    /**
     * True if the filelist has been validated
     * @param bool
     */
    var $_filesValid = false;

    /**
     * @var PEAR_Registry
     * @access protected
     */
    var $_registry;

    /**
     * @var PEAR_Config
     * @access protected
     */
    var $_config;

    /**
     * Optional Dependency group requested for installation
     * @var string
     * @access private
     */
    var $_requestedGroup = false;

    /**
     * @var PEAR_ErrorStack
     * @access protected
     */
    var $_stack;

    /**
     * Namespace prefix used for tasks in this package.xml - use tasks: whenever possible
     */
    var $_tasksNs;

    /**
     * Determines whether this packagefile was initialized only with partial package info
     *
     * If this package file was constructed via parsing REST, it will only contain
     *
     * - package name
     * - channel name
     * - dependencies
     * @var boolean
     * @access private
     */
    var $_incomplete = true;

    /**
     * @var PEAR_PackageFile_v2_Validator
     */
    var $_v2Validator;

    /**
     * The constructor merely sets up the private error stack
     */
    function __construct()
    {
        $this->_stack = new PEAR_ErrorStack('PEAR_PackageFile_v2', false, null);
        $this->_isValid = false;
    }

    /**
     * PHP 4 style constructor for backwards compatibility.
     * Used by PEAR_PackageFileManager2
     */
    public function PEAR_PackageFile_v2()
    {
        $this->__construct();
    }

    /**
     * To make unit-testing easier
     * @param PEAR_Frontend_*
     * @param array options
     * @param PEAR_Config
     * @return PEAR_Downloader
     * @access protected
     */
    function &getPEARDownloader(&$i, $o, &$c)
    {
        $z = new PEAR_Downloader($i, $o, $c);
        return $z;
    }

    /**
     * To make unit-testing easier
     * @param PEAR_Config
     * @param array options
     * @param array package name as returned from {@link PEAR_Registry::parsePackageName()}
     * @param int PEAR_VALIDATE_* constant
     * @return PEAR_Dependency2
     * @access protected
     */
    function &getPEARDependency2(&$c, $o, $p, $s = PEAR_VALIDATE_INSTALLING)
    {
        if (!class_exists('PEAR_Dependency2')) {
            require_once 'PEAR/Dependency2.php';
        }
        $z = new PEAR_Dependency2($c, $o, $p, $s);
        return $z;
    }

    function getInstalledBinary()
    {
        return isset($this->_packageInfo['#binarypackage']) ? $this->_packageInfo['#binarypackage'] :
            false;
    }

    /**
     * Installation of source package has failed, attempt to download and install the
     * binary version of this package.
     * @param PEAR_Installer
     * @return array|false
     */
    function installBinary(&$installer)
    {
        if (!OS_WINDOWS) {
            $a = false;
            return $a;
        }
        if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
            $releasetype = $this->getPackageType() . 'release';
            if (!is_array($installer->getInstallPackages())) {
                $a = false;
                return $a;
            }
            foreach ($installer->getInstallPackages() as $p) {
                if ($p->isExtension($this->_packageInfo['providesextension'])) {
                    if ($p->getPackageType() != 'extsrc' && $p->getPackageType() != 'zendextsrc') {
                        $a = false;
                        return $a; // the user probably downloaded it separately
                    }
                }
            }
            if (isset($this->_packageInfo[$releasetype]['binarypackage'])) {
                $installer->log(0, 'Attempting to download binary version of extension "' .
                    $this->_packageInfo['providesextension'] . '"');
                $params = $this->_packageInfo[$releasetype]['binarypackage'];
                if (!is_array($params) || !isset($params[0])) {
                    $params = array($params);
                }
                if (isset($this->_packageInfo['channel'])) {
                    foreach ($params as $i => $param) {
                        $params[$i] = array('channel' => $this->_packageInfo['channel'],
                            'package' => $param, 'version' => $this->getVersion());
                    }
                }
                $dl = &$this->getPEARDownloader($installer->ui, $installer->getOptions(),
                    $installer->config);
                $verbose = $dl->config->get('verbose');
                $dl->config->set('verbose', -1);
                foreach ($params as $param) {
                    PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                    $ret = $dl->download(array($param));
                    PEAR::popErrorHandling();
                    if (is_array($ret) && count($ret)) {
                        break;
                    }
                }
                $dl->config->set('verbose', $verbose);
                if (is_array($ret)) {
                    if (count($ret) == 1) {
                        $pf = $ret[0]->getPackageFile();
                        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                        $err = $installer->install($ret[0]);
                        PEAR::popErrorHandling();
                        if (is_array($err)) {
                            $this->_packageInfo['#binarypackage'] = $ret[0]->getPackage();
                            // "install" self, so all dependencies will work transparently
                            $this->_registry->addPackage2($this);
                            $installer->log(0, 'Download and install of binary extension "' .
                                $this->_registry->parsedPackageNameToString(
                                    array('channel' => $pf->getChannel(),
                                          'package' => $pf->getPackage()), true) . '" successful');
                            $a = array($ret[0], $err);
                            return $a;
                        }
                        $installer->log(0, 'Download and install of binary extension "' .
                            $this->_registry->parsedPackageNameToString(
                                    array('channel' => $pf->getChannel(),
                                          'package' => $pf->getPackage()), true) . '" failed');
                    }
                }
            }
        }
        $a = false;
        return $a;
    }

    /**
     * @return string|false Extension name
     */
    function getProvidesExtension()
    {
        if (in_array($this->getPackageType(),
              array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) {
            if (isset($this->_packageInfo['providesextension'])) {
                return $this->_packageInfo['providesextension'];
            }
        }
        return false;
    }

    /**
     * @param string Extension name
     * @return bool
     */
    function isExtension($extension)
    {
        if (in_array($this->getPackageType(),
              array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) {
            return $this->_packageInfo['providesextension'] == $extension;
        }
        return false;
    }

    /**
     * Tests whether every part of the package.xml 1.0 is represented in
     * this package.xml 2.0
     * @param PEAR_PackageFile_v1
     * @return bool
     */
    function isEquivalent($pf1)
    {
        if (!$pf1) {
            return true;
        }
        if ($this->getPackageType() == 'bundle') {
            return false;
        }
        $this->_stack->getErrors(true);
        if (!$pf1->validate(PEAR_VALIDATE_NORMAL)) {
            return false;
        }
        $pass = true;
        if ($pf1->getPackage() != $this->getPackage()) {
            $this->_differentPackage($pf1->getPackage());
            $pass = false;
        }
        if ($pf1->getVersion() != $this->getVersion()) {
            $this->_differentVersion($pf1->getVersion());
            $pass = false;
        }
        if (trim($pf1->getSummary()) != $this->getSummary()) {
            $this->_differentSummary($pf1->getSummary());
            $pass = false;
        }
        if (preg_replace('/\s+/', '', $pf1->getDescription()) !=
              preg_replace('/\s+/', '', $this->getDescription())) {
            $this->_differentDescription($pf1->getDescription());
            $pass = false;
        }
        if ($pf1->getState() != $this->getState()) {
            $this->_differentState($pf1->getState());
            $pass = false;
        }
        if (!strstr(preg_replace('/\s+/', '', $this->getNotes()),
              preg_replace('/\s+/', '', $pf1->getNotes()))) {
            $this->_differentNotes($pf1->getNotes());
            $pass = false;
        }
        $mymaintainers = $this->getMaintainers();
        $yourmaintainers = $pf1->getMaintainers();
        for ($i1 = 0; $i1 < count($yourmaintainers); $i1++) {
            $reset = false;
            for ($i2 = 0; $i2 < count($mymaintainers); $i2++) {
                if ($mymaintainers[$i2]['handle'] == $yourmaintainers[$i1]['handle']) {
                    if ($mymaintainers[$i2]['role'] != $yourmaintainers[$i1]['role']) {
                        $this->_differentRole($mymaintainers[$i2]['handle'],
                            $yourmaintainers[$i1]['role'], $mymaintainers[$i2]['role']);
                        $pass = false;
                    }
                    if ($mymaintainers[$i2]['email'] != $yourmaintainers[$i1]['email']) {
                        $this->_differentEmail($mymaintainers[$i2]['handle'],
                            $yourmaintainers[$i1]['email'], $mymaintainers[$i2]['email']);
                        $pass = false;
                    }
                    if ($mymaintainers[$i2]['name'] != $yourmaintainers[$i1]['name']) {
                        $this->_differentName($mymaintainers[$i2]['handle'],
                            $yourmaintainers[$i1]['name'], $mymaintainers[$i2]['name']);
                        $pass = false;
                    }
                    unset($mymaintainers[$i2]);
                    $mymaintainers = array_values($mymaintainers);
                    unset($yourmaintainers[$i1]);
                    $yourmaintainers = array_values($yourmaintainers);
                    $reset = true;
                    break;
                }
            }
            if ($reset) {
                $i1 = -1;
            }
        }
        $this->_unmatchedMaintainers($mymaintainers, $yourmaintainers);
        $filelist = $this->getFilelist();
        foreach ($pf1->getFilelist() as $file => $atts) {
            if (!isset($filelist[$file])) {
                $this->_missingFile($file);
                $pass = false;
            }
        }
        return $pass;
    }

    function _differentPackage($package)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('package' => $package,
            'self' => $this->getPackage()),
            'package.xml 1.0 package "%package%" does not match "%self%"');
    }

    function _differentVersion($version)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('version' => $version,
            'self' => $this->getVersion()),
            'package.xml 1.0 version "%version%" does not match "%self%"');
    }

    function _differentState($state)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('state' => $state,
            'self' => $this->getState()),
            'package.xml 1.0 state "%state%" does not match "%self%"');
    }

    function _differentRole($handle, $role, $selfrole)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle,
            'role' => $role, 'self' => $selfrole),
            'package.xml 1.0 maintainer "%handle%" role "%role%" does not match "%self%"');
    }

    function _differentEmail($handle, $email, $selfemail)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle,
            'email' => $email, 'self' => $selfemail),
            'package.xml 1.0 maintainer "%handle%" email "%email%" does not match "%self%"');
    }

    function _differentName($handle, $name, $selfname)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle,
            'name' => $name, 'self' => $selfname),
            'package.xml 1.0 maintainer "%handle%" name "%name%" does not match "%self%"');
    }

    function _unmatchedMaintainers($my, $yours)
    {
        if ($my) {
            array_walk($my, function(&$i, $k) { $i = $i["handle"]; });
            $this->_stack->push(__FUNCTION__, 'error', array('handles' => $my),
                'package.xml 2.0 has unmatched extra maintainers "%handles%"');
        }
        if ($yours) {
            array_walk($yours, function(&$i, $k) { $i = $i["handle"]; });
            $this->_stack->push(__FUNCTION__, 'error', array('handles' => $yours),
                'package.xml 1.0 has unmatched extra maintainers "%handles%"');
        }
    }

    function _differentNotes($notes)
    {
        $truncnotes = strlen($notes) < 25 ? $notes : substr($notes, 0, 24) . '...';
        $truncmynotes = strlen($this->getNotes()) < 25 ? $this->getNotes() :
            substr($this->getNotes(), 0, 24) . '...';
        $this->_stack->push(__FUNCTION__, 'error', array('notes' => $truncnotes,
            'self' => $truncmynotes),
            'package.xml 1.0 release notes "%notes%" do not match "%self%"');
    }

    function _differentSummary($summary)
    {
        $truncsummary = strlen($summary) < 25 ? $summary : substr($summary, 0, 24) . '...';
        $truncmysummary = strlen($this->getsummary()) < 25 ? $this->getSummary() :
            substr($this->getsummary(), 0, 24) . '...';
        $this->_stack->push(__FUNCTION__, 'error', array('summary' => $truncsummary,
            'self' => $truncmysummary),
            'package.xml 1.0 summary "%summary%" does not match "%self%"');
    }

    function _differentDescription($description)
    {
        $truncdescription = trim(strlen($description) < 25 ? $description : substr($description, 0, 24) . '...');
        $truncmydescription = trim(strlen($this->getDescription()) < 25 ? $this->getDescription() :
            substr($this->getdescription(), 0, 24) . '...');
        $this->_stack->push(__FUNCTION__, 'error', array('description' => $truncdescription,
            'self' => $truncmydescription),
            'package.xml 1.0 description "%description%" does not match "%self%"');
    }

    function _missingFile($file)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
            'package.xml 1.0 file "%file%" is not present in <contents>');
    }

    /**
     * WARNING - do not use this function unless you know what you're doing
     */
    function setRawState($state)
    {
        if (!isset($this->_packageInfo['stability'])) {
            $this->_packageInfo['stability'] = array();
        }
        $this->_packageInfo['stability']['release'] = $state;
    }

    /**
     * WARNING - do not use this function unless you know what you're doing
     */
    function setRawCompatible($compatible)
    {
        $this->_packageInfo['compatible'] = $compatible;
    }

    /**
     * WARNING - do not use this function unless you know what you're doing
     */
    function setRawPackage($package)
    {
        $this->_packageInfo['name'] = $package;
    }

    /**
     * WARNING - do not use this function unless you know what you're doing
     */
    function setRawChannel($channel)
    {
        $this->_packageInfo['channel'] = $channel;
    }

    function setRequestedGroup($group)
    {
        $this->_requestedGroup = $group;
    }

    function getRequestedGroup()
    {
        if (isset($this->_requestedGroup)) {
            return $this->_requestedGroup;
        }
        return false;
    }

    /**
     * For saving in the registry.
     *
     * Set the last version that was installed
     * @param string
     */
    function setLastInstalledVersion($version)
    {
        $this->_packageInfo['_lastversion'] = $version;
    }

    /**
     * @return string|false
     */
    function getLastInstalledVersion()
    {
        if (isset($this->_packageInfo['_lastversion'])) {
            return $this->_packageInfo['_lastversion'];
        }
        return false;
    }

    /**
     * Determines whether this package.xml has post-install scripts or not
     * @return array|false
     */
    function listPostinstallScripts()
    {
        $filelist = $this->getFilelist();
        $contents = $this->getContents();
        $contents = $contents['dir']['file'];
        if (!is_array($contents) || !isset($contents[0])) {
            $contents = array($contents);
        }
        $taskfiles = array();
        foreach ($contents as $file) {
            $atts = $file['attribs'];
            unset($file['attribs']);
            if (count($file)) {
                $taskfiles[$atts['name']] = $file;
            }
        }
        $common = new PEAR_Common;
        $common->debug = $this->_config->get('verbose');
        $this->_scripts = array();
        $ret = array();
        foreach ($taskfiles as $name => $tasks) {
            if (!isset($filelist[$name])) {
                // ignored files will not be in the filelist
                continue;
            }
            $atts = $filelist[$name];
            foreach ($tasks as $tag => $raw) {
                $task = $this->getTask($tag);
                $task = new $task($this->_config, $common, PEAR_TASK_INSTALL);
                if ($task->isScript()) {
                    $ret[] = $filelist[$name]['installed_as'];
                }
            }
        }
        if (count($ret)) {
            return $ret;
        }
        return false;
    }

    /**
     * Initialize post-install scripts for running
     *
     * This method can be used to detect post-install scripts, as the return value
     * indicates whether any exist
     * @return bool
     */
    function initPostinstallScripts()
    {
        $filelist = $this->getFilelist();
        $contents = $this->getContents();
        $contents = $contents['dir']['file'];
        if (!is_array($contents) || !isset($contents[0])) {
            $contents = array($contents);
        }
        $taskfiles = array();
        foreach ($contents as $file) {
            $atts = $file['attribs'];
            unset($file['attribs']);
            if (count($file)) {
                $taskfiles[$atts['name']] = $file;
            }
        }
        $common = new PEAR_Common;
        $common->debug = $this->_config->get('verbose');
        $this->_scripts = array();
        foreach ($taskfiles as $name => $tasks) {
            if (!isset($filelist[$name])) {
                // file was not installed due to installconditions
                continue;
            }
            $atts = $filelist[$name];
            foreach ($tasks as $tag => $raw) {
                $taskname = $this->getTask($tag);
                $task = new $taskname($this->_config, $common, PEAR_TASK_INSTALL);
                if (!$task->isScript()) {
                    continue; // scripts are only handled after installation
                }
                $lastversion = isset($this->_packageInfo['_lastversion']) ?
                    $this->_packageInfo['_lastversion'] : null;
                $task->init($raw, $atts, $lastversion);
                $res = $task->startSession($this, $atts['installed_as'], null);
                if (!$res) {
                    continue; // skip this file
                }
                if (PEAR::isError($res)) {
                    return $res;
                }
                $this->_scripts[] = $task;
            }
        }
        if (count($this->_scripts)) {
            return true;
        }
        return false;
    }

    function runPostinstallScripts()
    {
        if ($this->initPostinstallScripts()) {
            $ui = &PEAR_Frontend::singleton();
            if ($ui) {
                $ui->runPostinstallScripts($this->_scripts, $this);
            }
        }
    }


    /**
     * Convert a recursive set of <dir> and <file> tags into a single <dir> tag with
     * <file> tags.
     */
    function flattenFilelist()
    {
        if (isset($this->_packageInfo['bundle'])) {
            return;
        }
        $filelist = array();
        if (isset($this->_packageInfo['contents']['dir']['dir'])) {
            $this->_getFlattenedFilelist($filelist, $this->_packageInfo['contents']['dir']);
            if (!isset($filelist[1])) {
                $filelist = $filelist[0];
            }
            $this->_packageInfo['contents']['dir']['file'] = $filelist;
            unset($this->_packageInfo['contents']['dir']['dir']);
        } else {
            // else already flattened but check for baseinstalldir propagation
            if (isset($this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'])) {
                if (isset($this->_packageInfo['contents']['dir']['file'][0])) {
                    foreach ($this->_packageInfo['contents']['dir']['file'] as $i => $file) {
                        if (isset($file['attribs']['baseinstalldir'])) {
                            continue;
                        }
                        $this->_packageInfo['contents']['dir']['file'][$i]['attribs']['baseinstalldir']
                            = $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'];
                    }
                } else {
                    if (!isset($this->_packageInfo['contents']['dir']['file']['attribs']['baseinstalldir'])) {
                       $this->_packageInfo['contents']['dir']['file']['attribs']['baseinstalldir']
                            = $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'];
                    }
                }
            }
        }
    }

    /**
     * @param array the final flattened file list
     * @param array the current directory being processed
     * @param string|false any recursively inherited baeinstalldir attribute
     * @param string private recursion variable
     * @return array
     * @access protected
     */
    function _getFlattenedFilelist(&$files, $dir, $baseinstall = false, $path = '')
    {
        if (isset($dir['attribs']) && isset($dir['attribs']['baseinstalldir'])) {
            $baseinstall = $dir['attribs']['baseinstalldir'];
        }
        if (isset($dir['dir'])) {
            if (!isset($dir['dir'][0])) {
                $dir['dir'] = array($dir['dir']);
            }
            foreach ($dir['dir'] as $subdir) {
                if (!isset($subdir['attribs']) || !isset($subdir['attribs']['name'])) {
                    $name = '*unknown*';
                } else {
                    $name = $subdir['attribs']['name'];
                }
                $newpath = empty($path) ? $name :
                    $path . '/' . $name;
                $this->_getFlattenedFilelist($files, $subdir,
                    $baseinstall, $newpath);
            }
        }
        if (isset($dir['file'])) {
            if (!isset($dir['file'][0])) {
                $dir['file'] = array($dir['file']);
            }
            foreach ($dir['file'] as $file) {
                $attrs = $file['attribs'];
                $name = $attrs['name'];
                if ($baseinstall && !isset($attrs['baseinstalldir'])) {
                    $attrs['baseinstalldir'] = $baseinstall;
                }
                $attrs['name'] = empty($path) ? $name : $path . '/' . $name;
                $attrs['name'] = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'),
                    $attrs['name']);
                $file['attribs'] = $attrs;
                $files[] = $file;
            }
        }
    }

    function setConfig(&$config)
    {
        $this->_config = &$config;
        $this->_registry = &$config->getRegistry();
    }

    function setLogger(&$logger)
    {
        if (!is_object($logger) || !method_exists($logger, 'log')) {
            return PEAR::raiseError('Logger must be compatible with PEAR_Common::log');
        }
        $this->_logger = &$logger;
    }

    /**
     * WARNING - do not use this function directly unless you know what you're doing
     */
    function setDeps($deps)
    {
        $this->_packageInfo['dependencies'] = $deps;
    }

    /**
     * WARNING - do not use this function directly unless you know what you're doing
     */
    function setCompatible($compat)
    {
        $this->_packageInfo['compatible'] = $compat;
    }

    function setPackagefile($file, $archive = false)
    {
        $this->_packageFile = $file;
        $this->_archiveFile = $archive ? $archive : $file;
    }

    /**
     * Wrapper to {@link PEAR_ErrorStack::getErrors()}
     * @param boolean determines whether to purge the error stack after retrieving
     * @return array
     */
    function getValidationWarnings($purge = true)
    {
        return $this->_stack->getErrors($purge);
    }

    function getPackageFile()
    {
        return $this->_packageFile;
    }

    function getArchiveFile()
    {
        return $this->_archiveFile;
    }


    /**
     * Directly set the array that defines this packagefile
     *
     * WARNING: no validation.  This should only be performed by internal methods
     * inside PEAR or by inputting an array saved from an existing PEAR_PackageFile_v2
     * @param array
     */
    function fromArray($pinfo)
    {
        unset($pinfo['old']);
        unset($pinfo['xsdversion']);
        // If the changelog isn't an array then it was passed in as an empty tag
        if (isset($pinfo['changelog']) && !is_array($pinfo['changelog'])) {
          unset($pinfo['changelog']);
        }
        $this->_incomplete = false;
        $this->_packageInfo = $pinfo;
    }

    function isIncomplete()
    {
        return $this->_incomplete;
    }

    /**
     * @return array
     */
    function toArray($forreg = false)
    {
        if (!$this->validate(PEAR_VALIDATE_NORMAL)) {
            return false;
        }
        return $this->getArray($forreg);
    }

    function getArray($forReg = false)
    {
        if ($forReg) {
            $arr = $this->_packageInfo;
            $arr['old'] = array();
            $arr['old']['version'] = $this->getVersion();
            $arr['old']['release_date'] = $this->getDate();
            $arr['old']['release_state'] = $this->getState();
            $arr['old']['release_license'] = $this->getLicense();
            $arr['old']['release_notes'] = $this->getNotes();
            $arr['old']['release_deps'] = $this->getDeps();
            $arr['old']['maintainers'] = $this->getMaintainers();
            $arr['xsdversion'] = '2.0';
            return $arr;
        } else {
            $info = $this->_packageInfo;
            unset($info['dirtree']);
            if (isset($info['_lastversion'])) {
                unset($info['_lastversion']);
            }
            if (isset($info['#binarypackage'])) {
                unset($info['#binarypackage']);
            }
            return $info;
        }
    }

    function packageInfo($field)
    {
        $arr = $this->getArray(true);
        if ($field == 'state') {
            return $arr['stability']['release'];
        }
        if ($field == 'api-version') {
            return $arr['version']['api'];
        }
        if ($field == 'api-state') {
            return $arr['stability']['api'];
        }
        if (isset($arr['old'][$field])) {
            if (!is_string($arr['old'][$field])) {
                return null;
            }
            return $arr['old'][$field];
        }
        if (isset($arr[$field])) {
            if (!is_string($arr[$field])) {
                return null;
            }
            return $arr[$field];
        }
        return null;
    }

    function getName()
    {
        return $this->getPackage();
    }

    function getPackage()
    {
        if (isset($this->_packageInfo['name'])) {
            return $this->_packageInfo['name'];
        }
        return false;
    }

    function getChannel()
    {
        if (isset($this->_packageInfo['uri'])) {
            return '__uri';
        }
        if (isset($this->_packageInfo['channel'])) {
            return strtolower($this->_packageInfo['channel']);
        }
        return false;
    }

    function getUri()
    {
        if (isset($this->_packageInfo['uri'])) {
            return $this->_packageInfo['uri'];
        }
        return false;
    }

    function getExtends()
    {
        if (isset($this->_packageInfo['extends'])) {
            return $this->_packageInfo['extends'];
        }
        return false;
    }

    function getSummary()
    {
        if (isset($this->_packageInfo['summary'])) {
            return $this->_packageInfo['summary'];
        }
        return false;
    }

    function getDescription()
    {
        if (isset($this->_packageInfo['description'])) {
            return $this->_packageInfo['description'];
        }
        return false;
    }

    function getMaintainers($raw = false)
    {
        if (!isset($this->_packageInfo['lead'])) {
            return false;
        }
        if ($raw) {
            $ret = array('lead' => $this->_packageInfo['lead']);
            (isset($this->_packageInfo['developer'])) ?
                $ret['developer'] = $this->_packageInfo['developer'] :null;
            (isset($this->_packageInfo['contributor'])) ?
                $ret['contributor'] = $this->_packageInfo['contributor'] :null;
            (isset($this->_packageInfo['helper'])) ?
                $ret['helper'] = $this->_packageInfo['helper'] :null;
            return $ret;
        } else {
            $ret = array();
            $leads = isset($this->_packageInfo['lead'][0]) ? $this->_packageInfo['lead'] :
                array($this->_packageInfo['lead']);
            foreach ($leads as $lead) {
                $s = $lead;
                $s['handle'] = $s['user'];
                unset($s['user']);
                $s['role'] = 'lead';
                $ret[] = $s;
            }
            if (isset($this->_packageInfo['developer'])) {
                $leads = isset($this->_packageInfo['developer'][0]) ?
                    $this->_packageInfo['developer'] :
                    array($this->_packageInfo['developer']);
                foreach ($leads as $maintainer) {
                    $s = $maintainer;
                    $s['handle'] = $s['user'];
                    unset($s['user']);
                    $s['role'] = 'developer';
                    $ret[] = $s;
                }
            }
            if (isset($this->_packageInfo['contributor'])) {
                $leads = isset($this->_packageInfo['contributor'][0]) ?
                    $this->_packageInfo['contributor'] :
                    array($this->_packageInfo['contributor']);
                foreach ($leads as $maintainer) {
                    $s = $maintainer;
                    $s['handle'] = $s['user'];
                    unset($s['user']);
                    $s['role'] = 'contributor';
                    $ret[] = $s;
                }
            }
            if (isset($this->_packageInfo['helper'])) {
                $leads = isset($this->_packageInfo['helper'][0]) ?
                    $this->_packageInfo['helper'] :
                    array($this->_packageInfo['helper']);
                foreach ($leads as $maintainer) {
                    $s = $maintainer;
                    $s['handle'] = $s['user'];
                    unset($s['user']);
                    $s['role'] = 'helper';
                    $ret[] = $s;
                }
            }
            return $ret;
        }
        return false;
    }

    function getLeads()
    {
        if (isset($this->_packageInfo['lead'])) {
            return $this->_packageInfo['lead'];
        }
        return false;
    }

    function getDevelopers()
    {
        if (isset($this->_packageInfo['developer'])) {
            return $this->_packageInfo['developer'];
        }
        return false;
    }

    function getContributors()
    {
        if (isset($this->_packageInfo['contributor'])) {
            return $this->_packageInfo['contributor'];
        }
        return false;
    }

    function getHelpers()
    {
        if (isset($this->_packageInfo['helper'])) {
            return $this->_packageInfo['helper'];
        }
        return false;
    }

    function setDate($date)
    {
        if (!isset($this->_packageInfo['date'])) {
            // ensure that the extends tag is set up in the right location
            $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                array('time', 'version',
                    'stability', 'license', 'notes', 'contents', 'compatible',
                    'dependencies', 'providesextension', 'srcpackage', 'srcuri',
                    'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease',
                    'zendextbinrelease', 'bundle', 'changelog'), array(), 'date');
        }
        $this->_packageInfo['date'] = $date;
        $this->_isValid = 0;
    }

    function setTime($time)
    {
        $this->_isValid = 0;
        if (!isset($this->_packageInfo['time'])) {
            // ensure that the time tag is set up in the right location
            $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                    array('version',
                    'stability', 'license', 'notes', 'contents', 'compatible',
                    'dependencies', 'providesextension', 'srcpackage', 'srcuri',
                    'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease',
                    'zendextbinrelease', 'bundle', 'changelog'), $time, 'time');
        }
        $this->_packageInfo['time'] = $time;
    }

    function getDate()
    {
        if (isset($this->_packageInfo['date'])) {
            return $this->_packageInfo['date'];
        }
        return false;
    }

    function getTime()
    {
        if (isset($this->_packageInfo['time'])) {
            return $this->_packageInfo['time'];
        }
        return false;
    }

    /**
     * @param package|api version category to return
     */
    function getVersion($key = 'release')
    {
        if (isset($this->_packageInfo['version'][$key])) {
            return $this->_packageInfo['version'][$key];
        }
        return false;
    }

    function getStability()
    {
        if (isset($this->_packageInfo['stability'])) {
            return $this->_packageInfo['stability'];
        }
        return false;
    }

    function getState($key = 'release')
    {
        if (isset($this->_packageInfo['stability'][$key])) {
            return $this->_packageInfo['stability'][$key];
        }
        return false;
    }

    function getLicense($raw = false)
    {
        if (isset($this->_packageInfo['license'])) {
            if ($raw) {
                return $this->_packageInfo['license'];
            }
            if (is_array($this->_packageInfo['license'])) {
                return $this->_packageInfo['license']['_content'];
            } else {
                return $this->_packageInfo['license'];
            }
        }
        return false;
    }

    function getLicenseLocation()
    {
        if (!isset($this->_packageInfo['license']) || !is_array($this->_packageInfo['license'])) {
            return false;
        }
        return $this->_packageInfo['license']['attribs'];
    }

    function getNotes()
    {
        if (isset($this->_packageInfo['notes'])) {
            return $this->_packageInfo['notes'];
        }
        return false;
    }

    /**
     * Return the <usesrole> tag contents, if any
     * @return array|false
     */
    function getUsesrole()
    {
        if (isset($this->_packageInfo['usesrole'])) {
            return $this->_packageInfo['usesrole'];
        }
        return false;
    }

    /**
     * Return the <usestask> tag contents, if any
     * @return array|false
     */
    function getUsestask()
    {
        if (isset($this->_packageInfo['usestask'])) {
            return $this->_packageInfo['usestask'];
        }
        return false;
    }

    /**
     * This should only be used to retrieve filenames and install attributes
     */
    function getFilelist($preserve = false)
    {
        if (isset($this->_packageInfo['filelist']) && !$preserve) {
            return $this->_packageInfo['filelist'];
        }
        $this->flattenFilelist();
        if ($contents = $this->getContents()) {
            $ret = array();
            if (!isset($contents['dir'])) {
                return false;
            }
            if (!isset($contents['dir']['file'][0])) {
                $contents['dir']['file'] = array($contents['dir']['file']);
            }
            foreach ($contents['dir']['file'] as $file) {
                if (!isset($file['attribs']['name'])) {
                    continue;
                }
                $name = $file['attribs']['name'];
                if (!$preserve) {
                    $file = $file['attribs'];
                }
                $ret[$name] = $file;
            }
            if (!$preserve) {
                $this->_packageInfo['filelist'] = $ret;
            }
            return $ret;
        }
        return false;
    }

    /**
     * Return configure options array, if any
     *
     * @return array|false
     */
    function getConfigureOptions()
    {
        if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') {
            return false;
        }

        $releases = $this->getReleases();
        if (isset($releases[0])) {
            $releases = $releases[0];
        }

        if (isset($releases['configureoption'])) {
            if (!isset($releases['configureoption'][0])) {
                $releases['configureoption'] = array($releases['configureoption']);
            }

            for ($i = 0; $i < count($releases['configureoption']); $i++) {
                $releases['configureoption'][$i] = $releases['configureoption'][$i]['attribs'];
            }

            return $releases['configureoption'];
        }

        return false;
    }

    /**
     * This is only used at install-time, after all serialization
     * is over.
     */
    function resetFilelist()
    {
        $this->_packageInfo['filelist'] = array();
    }

    /**
     * Retrieve a list of files that should be installed on this computer
     * @return array
     */
    function getInstallationFilelist($forfilecheck = false)
    {
        $contents = $this->getFilelist(true);
        if (isset($contents['dir']['attribs']['baseinstalldir'])) {
            $base = $contents['dir']['attribs']['baseinstalldir'];
        }
        if (isset($this->_packageInfo['bundle'])) {
            return PEAR::raiseError(
                'Exception: bundles should be handled in download code only');
        }
        $release = $this->getReleases();
        if ($release) {
            if (!isset($release[0])) {
                if (!isset($release['installconditions']) && !isset($release['filelist'])) {
                    if ($forfilecheck) {
                        return $this->getFilelist();
                    }
                    return $contents;
                }
                $release = array($release);
            }
            $depchecker = &$this->getPEARDependency2($this->_config, array(),
                array('channel' => $this->getChannel(), 'package' => $this->getPackage()),
                PEAR_VALIDATE_INSTALLING);
            foreach ($release as $instance) {
                if (isset($instance['installconditions'])) {
                    $installconditions = $instance['installconditions'];
                    if (is_array($installconditions)) {
                        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                        foreach ($installconditions as $type => $conditions) {
                            if (!isset($conditions[0])) {
                                $conditions = array($conditions);
                            }
                            foreach ($conditions as $condition) {
                                $ret = $depchecker->{"validate{$type}Dependency"}($condition);
                                if (PEAR::isError($ret)) {
                                    PEAR::popErrorHandling();
                                    continue 3; // skip this release
                                }
                            }
                        }
                        PEAR::popErrorHandling();
                    }
                }
                // this is the release to use
                if (isset($instance['filelist'])) {
                    // ignore files
                    if (isset($instance['filelist']['ignore'])) {
                        $ignore = isset($instance['filelist']['ignore'][0]) ?
                            $instance['filelist']['ignore'] :
                            array($instance['filelist']['ignore']);
                        foreach ($ignore as $ig) {
                            unset ($contents[$ig['attribs']['name']]);
                        }
                    }
                    // install files as this name
                    if (isset($instance['filelist']['install'])) {
                        $installas = isset($instance['filelist']['install'][0]) ?
                            $instance['filelist']['install'] :
                            array($instance['filelist']['install']);
                        foreach ($installas as $as) {
                            $contents[$as['attribs']['name']]['attribs']['install-as'] =
                                $as['attribs']['as'];
                        }
                    }
                }
                if ($forfilecheck) {
                    foreach ($contents as $file => $attrs) {
                        $contents[$file] = $attrs['attribs'];
                    }
                }
                return $contents;
            }
        } else { // simple release - no installconditions or install-as
            if ($forfilecheck) {
                return $this->getFilelist();
            }
            return $contents;
        }
        // no releases matched
        return PEAR::raiseError('No releases in package.xml matched the existing operating ' .
            'system, extensions installed, or architecture, cannot install');
    }

    /**
     * This is only used at install-time, after all serialization
     * is over.
     * @param string file name
     * @param string installed path
     */
    function setInstalledAs($file, $path)
    {
        if ($path) {
            return $this->_packageInfo['filelist'][$file]['installed_as'] = $path;
        }
        unset($this->_packageInfo['filelist'][$file]['installed_as']);
    }

    function getInstalledLocation($file)
    {
        if (isset($this->_packageInfo['filelist'][$file]['installed_as'])) {
            return $this->_packageInfo['filelist'][$file]['installed_as'];
        }
        return false;
    }

    /**
     * This is only used at install-time, after all serialization
     * is over.
     */
    function installedFile($file, $atts)
    {
        if (isset($this->_packageInfo['filelist'][$file])) {
            $this->_packageInfo['filelist'][$file] =
                array_merge($this->_packageInfo['filelist'][$file], $atts['attribs']);
        } else {
            $this->_packageInfo['filelist'][$file] = $atts['attribs'];
        }
    }

    /**
     * Retrieve the contents tag
     */
    function getContents()
    {
        if (isset($this->_packageInfo['contents'])) {
            return $this->_packageInfo['contents'];
        }
        return false;
    }

    /**
     * @param string full path to file
     * @param string attribute name
     * @param string attribute value
     * @param int risky but fast - use this to choose a file based on its position in the list
     *            of files.  Index is zero-based like PHP arrays.
     * @return bool success of operation
     */
    function setFileAttribute($filename, $attr, $value, $index = false)
    {
        $this->_isValid = 0;
        if (in_array($attr, array('role', 'name', 'baseinstalldir'))) {
            $this->_filesValid = false;
        }
        if ($index !== false &&
              isset($this->_packageInfo['contents']['dir']['file'][$index]['attribs'])) {
            $this->_packageInfo['contents']['dir']['file'][$index]['attribs'][$attr] = $value;
            return true;
        }
        if (!isset($this->_packageInfo['contents']['dir']['file'])) {
            return false;
        }
        $files = $this->_packageInfo['contents']['dir']['file'];
        if (!isset($files[0])) {
            $files = array($files);
            $ind = false;
        } else {
            $ind = true;
        }
        foreach ($files as $i => $file) {
            if (isset($file['attribs'])) {
                if ($file['attribs']['name'] == $filename) {
                    if ($ind) {
                        $this->_packageInfo['contents']['dir']['file'][$i]['attribs'][$attr] = $value;
                    } else {
                        $this->_packageInfo['contents']['dir']['file']['attribs'][$attr] = $value;
                    }
                    return true;
                }
            }
        }
        return false;
    }

    function setDirtree($path)
    {
        if (!isset($this->_packageInfo['dirtree'])) {
            $this->_packageInfo['dirtree'] = array();
        }
        $this->_packageInfo['dirtree'][$path] = true;
    }

    function getDirtree()
    {
        if (isset($this->_packageInfo['dirtree']) && count($this->_packageInfo['dirtree'])) {
            return $this->_packageInfo['dirtree'];
        }
        return false;
    }

    function resetDirtree()
    {
        unset($this->_packageInfo['dirtree']);
    }

    /**
     * Determines whether this package claims it is compatible with the version of
     * the package that has a recommended version dependency
     * @param PEAR_PackageFile_v2|PEAR_PackageFile_v1|PEAR_Downloader_Package
     * @return boolean
     */
    function isCompatible($pf)
    {
        if (!isset($this->_packageInfo['compatible'])) {
            return false;
        }
        if (!isset($this->_packageInfo['channel'])) {
            return false;
        }
        $me = $pf->getVersion();
        $compatible = $this->_packageInfo['compatible'];
        if (!isset($compatible[0])) {
            $compatible = array($compatible);
        }
        $found = false;
        foreach ($compatible as $info) {
            if (strtolower($info['name']) == strtolower($pf->getPackage())) {
                if (strtolower($info['channel']) == strtolower($pf->getChannel())) {
                    $found = true;
                    break;
                }
            }
        }
        if (!$found) {
            return false;
        }
        if (isset($info['exclude'])) {
            if (!isset($info['exclude'][0])) {
                $info['exclude'] = array($info['exclude']);
            }
            foreach ($info['exclude'] as $exclude) {
                if (version_compare($me, $exclude, '==')) {
                    return false;
                }
            }
        }
        if (version_compare($me, $info['min'], '>=') && version_compare($me, $info['max'], '<=')) {
            return true;
        }
        return false;
    }

    /**
     * @return array|false
     */
    function getCompatible()
    {
        if (isset($this->_packageInfo['compatible'])) {
            return $this->_packageInfo['compatible'];
        }
        return false;
    }

    function getDependencies()
    {
        if (isset($this->_packageInfo['dependencies'])) {
            return $this->_packageInfo['dependencies'];
        }
        return false;
    }

    function isSubpackageOf($p)
    {
        return $p->isSubpackage($this);
    }

    /**
     * Determines whether the passed in package is a subpackage of this package.
     *
     * No version checking is done, only name verification.
     * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
     * @return bool
     */
    function isSubpackage($p)
    {
        $sub = array();
        if (isset($this->_packageInfo['dependencies']['required']['subpackage'])) {
            $sub = $this->_packageInfo['dependencies']['required']['subpackage'];
            if (!isset($sub[0])) {
                $sub = array($sub);
            }
        }
        if (isset($this->_packageInfo['dependencies']['optional']['subpackage'])) {
            $sub1 = $this->_packageInfo['dependencies']['optional']['subpackage'];
            if (!isset($sub1[0])) {
                $sub1 = array($sub1);
            }
            $sub = array_merge($sub, $sub1);
        }
        if (isset($this->_packageInfo['dependencies']['group'])) {
            $group = $this->_packageInfo['dependencies']['group'];
            if (!isset($group[0])) {
                $group = array($group);
            }
            foreach ($group as $deps) {
                if (isset($deps['subpackage'])) {
                    $sub2 = $deps['subpackage'];
                    if (!isset($sub2[0])) {
                        $sub2 = array($sub2);
                    }
                    $sub = array_merge($sub, $sub2);
                }
            }
        }
        foreach ($sub as $dep) {
            if (strtolower($dep['name']) == strtolower($p->getPackage())) {
                if (isset($dep['channel'])) {
                    if (strtolower($dep['channel']) == strtolower($p->getChannel())) {
                        return true;
                    }
                } else {
                    if ($dep['uri'] == $p->getURI()) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    function dependsOn($package, $channel)
    {
        if (!($deps = $this->getDependencies())) {
            return false;
        }
        foreach (array('package', 'subpackage') as $type) {
            foreach (array('required', 'optional') as $needed) {
                if (isset($deps[$needed][$type])) {
                    if (!isset($deps[$needed][$type][0])) {
                        $deps[$needed][$type] = array($deps[$needed][$type]);
                    }
                    foreach ($deps[$needed][$type] as $dep) {
                        $depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri';
                        if (strtolower($dep['name']) == strtolower($package) &&
                              $depchannel == $channel) {
                            return true;
                        }
                    }
                }
            }
            if (isset($deps['group'])) {
                if (!isset($deps['group'][0])) {
                    $dep['group'] = array($deps['group']);
                }
                foreach ($deps['group'] as $group) {
                    if (isset($group[$type])) {
                        if (!is_array($group[$type])) {
                            $group[$type] = array($group[$type]);
                        }
                        foreach ($group[$type] as $dep) {
                            $depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri';
                            if (strtolower($dep['name']) == strtolower($package) &&
                                  $depchannel == $channel) {
                                return true;
                            }
                        }
                    }
                }
            }
        }
        return false;
    }

    /**
     * Get the contents of a dependency group
     * @param string
     * @return array|false
     */
    function getDependencyGroup($name)
    {
        $name = strtolower($name);
        if (!isset($this->_packageInfo['dependencies']['group'])) {
            return false;
        }
        $groups = $this->_packageInfo['dependencies']['group'];
        if (!isset($groups[0])) {
            $groups = array($groups);
        }
        foreach ($groups as $group) {
            if (strtolower($group['attribs']['name']) == $name) {
                return $group;
            }
        }
        return false;
    }

    /**
     * Retrieve a partial package.xml 1.0 representation of dependencies
     *
     * a very limited representation of dependencies is returned by this method.
     * The <exclude> tag for excluding certain versions of a dependency is
     * completely ignored.  In addition, dependency groups are ignored, with the
     * assumption that all dependencies in dependency groups are also listed in
     * the optional group that work with all dependency groups
     * @param boolean return package.xml 2.0 <dependencies> tag
     * @return array|false
     */
    function getDeps($raw = false, $nopearinstaller = false)
    {
        if (isset($this->_packageInfo['dependencies'])) {
            if ($raw) {
                return $this->_packageInfo['dependencies'];
            }
            $ret = array();
            $map = array(
                'php' => 'php',
                'package' => 'pkg',
                'subpackage' => 'pkg',
                'extension' => 'ext',
                'os' => 'os',
                'pearinstaller' => 'pkg',
                );
            foreach (array('required', 'optional') as $type) {
                $optional = ($type == 'optional') ? 'yes' : 'no';
                if (!isset($this->_packageInfo['dependencies'][$type])
                    || empty($this->_packageInfo['dependencies'][$type])) {
                    continue;
                }
                foreach ($this->_packageInfo['dependencies'][$type] as $dtype => $deps) {
                    if ($dtype == 'pearinstaller' && $nopearinstaller) {
                        continue;
                    }
                    if ((is_array($deps) && !isset($deps[0])) || !is_array($deps)) {
                        $deps = array($deps);
                    }
                    foreach ($deps as $dep) {
                        if (!isset($map[$dtype])) {
                            // no support for arch type
                            continue;
                        }
                        if ($dtype == 'pearinstaller') {
                            $dep['name'] = 'PEAR';
                            $dep['channel'] = 'pear.php.net';
                        }
                        $s = array('type' => $map[$dtype]);
                        if (isset($dep['channel'])) {
                            $s['channel'] = $dep['channel'];
                        }
                        if (isset($dep['uri'])) {
                            $s['uri'] = $dep['uri'];
                        }
                        if (isset($dep['name'])) {
                            $s['name'] = $dep['name'];
                        }
                        if (isset($dep['conflicts'])) {
                            $s['rel'] = 'not';
                        } else {
                            if (!isset($dep['min']) &&
                                  !isset($dep['max'])) {
                                $s['rel'] = 'has';
                                $s['optional'] = $optional;
                            } elseif (isset($dep['min']) &&
                                  isset($dep['max'])) {
                                $s['rel'] = 'ge';
                                $s1 = $s;
                                $s1['rel'] = 'le';
                                $s['version'] = $dep['min'];
                                $s1['version'] = $dep['max'];
                                if (isset($dep['channel'])) {
                                    $s1['channel'] = $dep['channel'];
                                }
                                if ($dtype != 'php') {
                                    $s['name'] = $dep['name'];
                                    $s1['name'] = $dep['name'];
                                }
                                $s['optional'] = $optional;
                                $s1['optional'] = $optional;
                                $ret[] = $s1;
                            } elseif (isset($dep['min'])) {
                                if (isset($dep['exclude']) &&
                                      $dep['exclude'] == $dep['min']) {
                                    $s['rel'] = 'gt';
                                } else {
                                    $s['rel'] = 'ge';
                                }
                                $s['version'] = $dep['min'];
                                $s['optional'] = $optional;
                                if ($dtype != 'php') {
                                    $s['name'] = $dep['name'];
                                }
                            } elseif (isset($dep['max'])) {
                                if (isset($dep['exclude']) &&
                                      $dep['exclude'] == $dep['max']) {
                                    $s['rel'] = 'lt';
                                } else {
                                    $s['rel'] = 'le';
                                }
                                $s['version'] = $dep['max'];
                                $s['optional'] = $optional;
                                if ($dtype != 'php') {
                                    $s['name'] = $dep['name'];
                                }
                            }
                        }
                        $ret[] = $s;
                    }
                }
            }
            if (count($ret)) {
                return $ret;
            }
        }
        return false;
    }

    /**
     * @return php|extsrc|extbin|zendextsrc|zendextbin|bundle|false
     */
    function getPackageType()
    {
        if (isset($this->_packageInfo['phprelease'])) {
            return 'php';
        }
        if (isset($this->_packageInfo['extsrcrelease'])) {
            return 'extsrc';
        }
        if (isset($this->_packageInfo['extbinrelease'])) {
            return 'extbin';
        }
        if (isset($this->_packageInfo['zendextsrcrelease'])) {
            return 'zendextsrc';
        }
        if (isset($this->_packageInfo['zendextbinrelease'])) {
            return 'zendextbin';
        }
        if (isset($this->_packageInfo['bundle'])) {
            return 'bundle';
        }
        return false;
    }

    /**
     * @return array|false
     */
    function getReleases()
    {
        $type = $this->getPackageType();
        if ($type != 'bundle') {
            $type .= 'release';
        }
        if ($this->getPackageType() && isset($this->_packageInfo[$type])) {
            return $this->_packageInfo[$type];
        }
        return false;
    }

    /**
     * @return array
     */
    function getChangelog()
    {
        if (isset($this->_packageInfo['changelog'])) {
            return $this->_packageInfo['changelog'];
        }
        return false;
    }

    function hasDeps()
    {
        return isset($this->_packageInfo['dependencies']);
    }

    function getPackagexmlVersion()
    {
        if (isset($this->_packageInfo['zendextsrcrelease'])) {
            return '2.1';
        }
        if (isset($this->_packageInfo['zendextbinrelease'])) {
            return '2.1';
        }
        return '2.0';
    }

    /**
     * @return array|false
     */
    function getSourcePackage()
    {
        if (isset($this->_packageInfo['extbinrelease']) ||
              isset($this->_packageInfo['zendextbinrelease'])) {
            return array('channel' => $this->_packageInfo['srcchannel'],
                         'package' => $this->_packageInfo['srcpackage']);
        }
        return false;
    }

    function getBundledPackages()
    {
        if (isset($this->_packageInfo['bundle'])) {
            return $this->_packageInfo['contents']['bundledpackage'];
        }
        return false;
    }

    function getLastModified()
    {
        if (isset($this->_packageInfo['_lastmodified'])) {
            return $this->_packageInfo['_lastmodified'];
        }
        return false;
    }

    /**
     * Get the contents of a file listed within the package.xml
     * @param string
     * @return string
     */
    function getFileContents($file)
    {
        if ($this->_archiveFile == $this->_packageFile) { // unpacked
            $dir = dirname($this->_packageFile);
            $file = $dir . DIRECTORY_SEPARATOR . $file;
            $file = str_replace(array('/', '\\'),
                array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR), $file);
            if (file_exists($file) && is_readable($file)) {
                return implode('', file($file));
            }
        } else { // tgz
            $tar = new Archive_Tar($this->_archiveFile);
            $tar->pushErrorHandling(PEAR_ERROR_RETURN);
            if ($file != 'package.xml' && $file != 'package2.xml') {
                $file = $this->getPackage() . '-' . $this->getVersion() . '/' . $file;
            }
            $file = $tar->extractInString($file);
            $tar->popErrorHandling();
            if (PEAR::isError($file)) {
                return PEAR::raiseError("Cannot locate file '$file' in archive");
            }
            return $file;
        }
    }

    function &getRW()
    {
        if (!class_exists('PEAR_PackageFile_v2_rw')) {
            require_once 'PEAR/PackageFile/v2/rw.php';
        }
        $a = new PEAR_PackageFile_v2_rw;
        foreach (get_object_vars($this) as $name => $unused) {
            if (!isset($this->$name)) {
                continue;
            }
            if ($name == '_config' || $name == '_logger'|| $name == '_registry' ||
                  $name == '_stack') {
                $a->$name = &$this->$name;
            } else {
                $a->$name = $this->$name;
            }
        }
        return $a;
    }

    function &getDefaultGenerator()
    {
        if (!class_exists('PEAR_PackageFile_Generator_v2')) {
            require_once 'PEAR/PackageFile/Generator/v2.php';
        }
        $a = new PEAR_PackageFile_Generator_v2($this);
        return $a;
    }

    function analyzeSourceCode($file, $string = false)
    {
        if (!isset($this->_v2Validator) ||
              !is_a($this->_v2Validator, 'PEAR_PackageFile_v2_Validator')) {
            if (!class_exists('PEAR_PackageFile_v2_Validator')) {
                require_once 'PEAR/PackageFile/v2/Validator.php';
            }
            $this->_v2Validator = new PEAR_PackageFile_v2_Validator;
        }
        return $this->_v2Validator->analyzeSourceCode($file, $string);
    }

    function validate($state = PEAR_VALIDATE_NORMAL)
    {
        if (!isset($this->_packageInfo) || !is_array($this->_packageInfo)) {
            return false;
        }
        if (!isset($this->_v2Validator) ||
              !is_a($this->_v2Validator, 'PEAR_PackageFile_v2_Validator')) {
            if (!class_exists('PEAR_PackageFile_v2_Validator')) {
                require_once 'PEAR/PackageFile/v2/Validator.php';
            }
            $this->_v2Validator = new PEAR_PackageFile_v2_Validator;
        }
        if (isset($this->_packageInfo['xsdversion'])) {
            unset($this->_packageInfo['xsdversion']);
        }
        return $this->_v2Validator->validate($this, $state);
    }

    function getTasksNs()
    {
        if (!isset($this->_tasksNs)) {
            if (isset($this->_packageInfo['attribs'])) {
                foreach ($this->_packageInfo['attribs'] as $name => $value) {
                    if ($value == 'http://pear.php.net/dtd/tasks-1.0') {
                        $this->_tasksNs = str_replace('xmlns:', '', $name);
                        break;
                    }
                }
            }
        }
        return $this->_tasksNs;
    }

    /**
     * Determine whether a task name is a valid task.  Custom tasks may be defined
     * using subdirectories by putting a "-" in the name, as in <tasks:mycustom-task>
     *
     * Note that this method will auto-load the task class file and test for the existence
     * of the name with "-" replaced by "_" as in PEAR/Task/mycustom/task.php makes class
     * PEAR_Task_mycustom_task
     * @param string
     * @return boolean
     */
    function getTask($task)
    {
        $this->getTasksNs();
        // transform all '-' to '/' and 'tasks:' to '' so tasks:replace becomes replace
        $task = str_replace(array($this->_tasksNs . ':', '-'), array('', ' '), $task);
        $taskfile = str_replace(' ', '/', ucwords($task));
        $task = str_replace(array(' ', '/'), '_', ucwords($task));
        if (class_exists("PEAR_Task_$task")) {
            return "PEAR_Task_$task";
        }
        $fp = @fopen("PEAR/Task/$taskfile.php", 'r', true);
        if ($fp) {
            fclose($fp);
            require_once "PEAR/Task/$taskfile.php";
            return "PEAR_Task_$task";
        }
        return false;
    }

    /**
     * Key-friendly array_splice
     * @param tagname to splice a value in before
     * @param mixed the value to splice in
     * @param string the new tag name
     */
    function _ksplice($array, $key, $value, $newkey)
    {
        $offset = array_search($key, array_keys($array));
        $after = array_slice($array, $offset);
        $before = array_slice($array, 0, $offset);
        $before[$newkey] = $value;
        return array_merge($before, $after);
    }

    /**
     * @param array a list of possible keys, in the order they may occur
     * @param mixed contents of the new package.xml tag
     * @param string tag name
     * @access private
     */
    function _insertBefore($array, $keys, $contents, $newkey)
    {
        foreach ($keys as $key) {
            if (isset($array[$key])) {
                return $array = $this->_ksplice($array, $key, $contents, $newkey);
            }
        }
        $array[$newkey] = $contents;
        return $array;
    }

    /**
     * @param subsection of {@link $_packageInfo}
     * @param array|string tag contents
     * @param array format:
     * <pre>
     * array(
     *   tagname => array(list of tag names that follow this one),
     *   childtagname => array(list of child tag names that follow this one),
     * )
     * </pre>
     *
     * This allows construction of nested tags
     * @access private
     */
    function _mergeTag($manip, $contents, $order)
    {
        if (count($order)) {
            foreach ($order as $tag => $curorder) {
                if (!isset($manip[$tag])) {
                    // ensure that the tag is set up
                    $manip = $this->_insertBefore($manip, $curorder, array(), $tag);
                }
                if (count($order) > 1) {
                    $manip[$tag] = $this->_mergeTag($manip[$tag], $contents, array_slice($order, 1));
                    return $manip;
                }
            }
        } else {
            return $manip;
        }
        if (is_array($manip[$tag]) && !empty($manip[$tag]) && isset($manip[$tag][0])) {
            $manip[$tag][] = $contents;
        } else {
            if (is_array($manip[$tag]) && !count($manip[$tag])) {
                $manip[$tag] = $contents;
            } else {
                $manip[$tag] = array($manip[$tag]);
                $manip[$tag][] = $contents;
            }
        }
        return $manip;
    }
}
?>
PKq�ZC�8�L�L!PEAR/PackageFile/v2/Validator.phpnu�[���<?php
/**
 * PEAR_PackageFile_v2, package.xml version 2.0, read/write version
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a8
 */
/**
 * Private validation class used by PEAR_PackageFile_v2 - do not use directly, its
 * sole purpose is to split up the PEAR/PackageFile/v2.php file to make it smaller
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a8
 * @access private
 */
class PEAR_PackageFile_v2_Validator
{
    /**
     * @var array
     */
    var $_packageInfo;
    /**
     * @var PEAR_PackageFile_v2
     */
    var $_pf;
    /**
     * @var PEAR_ErrorStack
     */
    var $_stack;
    /**
     * @var int
     */
    var $_isValid = 0;
    /**
     * @var int
     */
    var $_filesValid = 0;
    /**
     * @var int
     */
    var $_curState = 0;
    /**
     * @param PEAR_PackageFile_v2
     * @param int
     */
    function validate(&$pf, $state = PEAR_VALIDATE_NORMAL)
    {
        $this->_pf = &$pf;
        $this->_curState = $state;
        $this->_packageInfo = $this->_pf->getArray();
        $this->_isValid = $this->_pf->_isValid;
        $this->_filesValid = $this->_pf->_filesValid;
        $this->_stack = &$pf->_stack;
        $this->_stack->getErrors(true);
        if (($this->_isValid & $state) == $state) {
            return true;
        }
        if (!isset($this->_packageInfo) || !is_array($this->_packageInfo)) {
            return false;
        }
        if (!isset($this->_packageInfo['attribs']['version']) ||
              ($this->_packageInfo['attribs']['version'] != '2.0' &&
               $this->_packageInfo['attribs']['version'] != '2.1')
        ) {
            $this->_noPackageVersion();
        }
        $structure =
        array(
            'name',
            'channel|uri',
            '*extends', // can't be multiple, but this works fine
            'summary',
            'description',
            '+lead', // these all need content checks
            '*developer',
            '*contributor',
            '*helper',
            'date',
            '*time',
            'version',
            'stability',
            'license->?uri->?filesource',
            'notes',
            'contents', //special validation needed
            '*compatible',
            'dependencies', //special validation needed
            '*usesrole',
            '*usestask', // reserve these for 1.4.0a1 to implement
                         // this will allow a package.xml to gracefully say it
                         // needs a certain package installed in order to implement a role or task
            '*providesextension',
            '*srcpackage|*srcuri',
            '+phprelease|+extsrcrelease|+extbinrelease|' .
                '+zendextsrcrelease|+zendextbinrelease|bundle', //special validation needed
            '*changelog',
        );
        $test = $this->_packageInfo;
        if (isset($test['dependencies']) &&
              isset($test['dependencies']['required']) &&
              isset($test['dependencies']['required']['pearinstaller']) &&
              isset($test['dependencies']['required']['pearinstaller']['min']) &&
              '1.10.16' != '@package' . '_version@' &&
              version_compare('1.10.16',
                $test['dependencies']['required']['pearinstaller']['min'], '<')
        ) {
            $this->_pearVersionTooLow($test['dependencies']['required']['pearinstaller']['min']);
            return false;
        }
        // ignore post-installation array fields
        if (array_key_exists('filelist', $test)) {
            unset($test['filelist']);
        }
        if (array_key_exists('_lastmodified', $test)) {
            unset($test['_lastmodified']);
        }
        if (array_key_exists('#binarypackage', $test)) {
            unset($test['#binarypackage']);
        }
        if (array_key_exists('old', $test)) {
            unset($test['old']);
        }
        if (array_key_exists('_lastversion', $test)) {
            unset($test['_lastversion']);
        }
        if (!$this->_stupidSchemaValidate($structure, $test, '<package>')) {
            return false;
        }
        if (empty($this->_packageInfo['name'])) {
            $this->_tagCannotBeEmpty('name');
        }
        $test = isset($this->_packageInfo['uri']) ? 'uri' :'channel';
        if (empty($this->_packageInfo[$test])) {
            $this->_tagCannotBeEmpty($test);
        }
        if (is_array($this->_packageInfo['license']) &&
              (!isset($this->_packageInfo['license']['_content']) ||
              empty($this->_packageInfo['license']['_content']))) {
            $this->_tagCannotBeEmpty('license');
        } elseif (empty($this->_packageInfo['license'])) {
            $this->_tagCannotBeEmpty('license');
        }
        if (empty($this->_packageInfo['summary'])) {
            $this->_tagCannotBeEmpty('summary');
        }
        if (empty($this->_packageInfo['description'])) {
            $this->_tagCannotBeEmpty('description');
        }
        if (empty($this->_packageInfo['date'])) {
            $this->_tagCannotBeEmpty('date');
        }
        if (empty($this->_packageInfo['notes'])) {
            $this->_tagCannotBeEmpty('notes');
        }
        if (isset($this->_packageInfo['time']) && empty($this->_packageInfo['time'])) {
            $this->_tagCannotBeEmpty('time');
        }
        if (isset($this->_packageInfo['dependencies'])) {
            $this->_validateDependencies();
        }
        if (isset($this->_packageInfo['compatible'])) {
            $this->_validateCompatible();
        }
        if (!isset($this->_packageInfo['bundle'])) {
            if (empty($this->_packageInfo['contents'])) {
                $this->_tagCannotBeEmpty('contents');
            }
            if (!isset($this->_packageInfo['contents']['dir'])) {
                $this->_filelistMustContainDir('contents');
                return false;
            }
            if (isset($this->_packageInfo['contents']['file'])) {
                $this->_filelistCannotContainFile('contents');
                return false;
            }
        }
        $this->_validateMaintainers();
        $this->_validateStabilityVersion();
        $fail = false;
        if (array_key_exists('usesrole', $this->_packageInfo)) {
            $roles = $this->_packageInfo['usesrole'];
            if (!is_array($roles) || !isset($roles[0])) {
                $roles = array($roles);
            }
            foreach ($roles as $role) {
                if (!isset($role['role'])) {
                    $this->_usesroletaskMustHaveRoleTask('usesrole', 'role');
                    $fail = true;
                } else {
                    if (!isset($role['channel'])) {
                        if (!isset($role['uri'])) {
                            $this->_usesroletaskMustHaveChannelOrUri($role['role'], 'usesrole');
                            $fail = true;
                        }
                    } elseif (!isset($role['package'])) {
                        $this->_usesroletaskMustHavePackage($role['role'], 'usesrole');
                        $fail = true;
                    }
                }
            }
        }
        if (array_key_exists('usestask', $this->_packageInfo)) {
            $roles = $this->_packageInfo['usestask'];
            if (!is_array($roles) || !isset($roles[0])) {
                $roles = array($roles);
            }
            foreach ($roles as $role) {
                if (!isset($role['task'])) {
                    $this->_usesroletaskMustHaveRoleTask('usestask', 'task');
                    $fail = true;
                } else {
                    if (!isset($role['channel'])) {
                        if (!isset($role['uri'])) {
                            $this->_usesroletaskMustHaveChannelOrUri($role['task'], 'usestask');
                            $fail = true;
                        }
                    } elseif (!isset($role['package'])) {
                        $this->_usesroletaskMustHavePackage($role['task'], 'usestask');
                        $fail = true;
                    }
                }
            }
        }

        if ($fail) {
            return false;
        }

        $list = $this->_packageInfo['contents'];
        if (isset($list['dir']) && is_array($list['dir']) && isset($list['dir'][0])) {
            $this->_multipleToplevelDirNotAllowed();
            return $this->_isValid = 0;
        }

        $this->_validateFilelist();
        $this->_validateRelease();
        if (!$this->_stack->hasErrors()) {
            $chan = $this->_pf->_registry->getChannel($this->_pf->getChannel(), true);
            if (PEAR::isError($chan)) {
                $this->_unknownChannel($this->_pf->getChannel());
            } else {
                $valpack = $chan->getValidationPackage();
                // for channel validator packages, always use the default PEAR validator.
                // otherwise, they can't be installed or packaged
                $validator = $chan->getValidationObject($this->_pf->getPackage());
                if (!$validator) {
                    $this->_stack->push(__FUNCTION__, 'error',
                        array('channel' => $chan->getName(),
                              'package' => $this->_pf->getPackage(),
                              'name'    => $valpack['_content'],
                              'version' => $valpack['attribs']['version']),
                        'package "%channel%/%package%" cannot be properly validated without ' .
                        'validation package "%channel%/%name%-%version%"');
                    return $this->_isValid = 0;
                }
                $validator->setPackageFile($this->_pf);
                $validator->validate($state);
                $failures = $validator->getFailures();
                foreach ($failures['errors'] as $error) {
                    $this->_stack->push(__FUNCTION__, 'error', $error,
                        'Channel validator error: field "%field%" - %reason%');
                }
                foreach ($failures['warnings'] as $warning) {
                    $this->_stack->push(__FUNCTION__, 'warning', $warning,
                        'Channel validator warning: field "%field%" - %reason%');
                }
            }
        }

        $this->_pf->_isValid = $this->_isValid = !$this->_stack->hasErrors('error');
        if ($this->_isValid && $state == PEAR_VALIDATE_PACKAGING && !$this->_filesValid) {
            if ($this->_pf->getPackageType() == 'bundle') {
                if ($this->_analyzeBundledPackages()) {
                    $this->_filesValid = $this->_pf->_filesValid = true;
                } else {
                    $this->_pf->_isValid = $this->_isValid = 0;
                }
            } else {
                if (!$this->_analyzePhpFiles()) {
                    $this->_pf->_isValid = $this->_isValid = 0;
                } else {
                    $this->_filesValid = $this->_pf->_filesValid = true;
                }
            }
        }

        if ($this->_isValid) {
            return $this->_pf->_isValid = $this->_isValid = $state;
        }

        return $this->_pf->_isValid = $this->_isValid = 0;
    }

    function _stupidSchemaValidate($structure, $xml, $root)
    {
        if (!is_array($xml)) {
            $xml = array();
        }
        $keys = array_keys($xml);
        reset($keys);
        $key = current($keys);
        while ($key == 'attribs' || $key == '_contents') {
            $key = next($keys);
        }
        $unfoundtags = $optionaltags = array();
        $ret = true;
        $mismatch = false;
        foreach ($structure as $struc) {
            if ($key) {
                $tag = $xml[$key];
            }
            $test = $this->_processStructure($struc);
            if (isset($test['choices'])) {
                $loose = true;
                foreach ($test['choices'] as $choice) {
                    if ($key == $choice['tag']) {
                        $key = next($keys);
                        while ($key == 'attribs' || $key == '_contents') {
                            $key = next($keys);
                        }
                        $unfoundtags = $optionaltags = array();
                        $mismatch = false;
                        if ($key && $key != $choice['tag'] && isset($choice['multiple'])) {
                            $unfoundtags[] = $choice['tag'];
                            $optionaltags[] = $choice['tag'];
                            if ($key) {
                                $mismatch = true;
                            }
                        }
                        $ret &= $this->_processAttribs($choice, $tag, $root);
                        continue 2;
                    } else {
                        $unfoundtags[] = $choice['tag'];
                        $mismatch = true;
                    }
                    if (!isset($choice['multiple']) || $choice['multiple'] != '*') {
                        $loose = false;
                    } else {
                        $optionaltags[] = $choice['tag'];
                    }
                }
                if (!$loose) {
                    $this->_invalidTagOrder($unfoundtags, $key, $root);
                    return false;
                }
            } else {
                if ($key != $test['tag']) {
                    if (isset($test['multiple']) && $test['multiple'] != '*') {
                        $unfoundtags[] = $test['tag'];
                        $this->_invalidTagOrder($unfoundtags, $key, $root);
                        return false;
                    } else {
                        if ($key) {
                            $mismatch = true;
                        }
                        $unfoundtags[] = $test['tag'];
                        $optionaltags[] = $test['tag'];
                    }
                    if (!isset($test['multiple'])) {
                        $this->_invalidTagOrder($unfoundtags, $key, $root);
                        return false;
                    }
                    continue;
                } else {
                    $unfoundtags = $optionaltags = array();
                    $mismatch = false;
                }
                $key = next($keys);
                while ($key == 'attribs' || $key == '_contents') {
                    $key = next($keys);
                }
                if ($key && $key != $test['tag'] && isset($test['multiple'])) {
                    $unfoundtags[] = $test['tag'];
                    $optionaltags[] = $test['tag'];
                    $mismatch = true;
                }
                $ret &= $this->_processAttribs($test, $tag, $root);
                continue;
            }
        }
        if (!$mismatch && count($optionaltags)) {
            // don't error out on any optional tags
            $unfoundtags = array_diff($unfoundtags, $optionaltags);
        }
        if (count($unfoundtags)) {
            $this->_invalidTagOrder($unfoundtags, $key, $root);
        } elseif ($key) {
            // unknown tags
            $this->_invalidTagOrder('*no tags allowed here*', $key, $root);
            while ($key = next($keys)) {
                $this->_invalidTagOrder('*no tags allowed here*', $key, $root);
            }
        }
        return $ret;
    }

    function _processAttribs($choice, $tag, $context)
    {
        if (isset($choice['attribs'])) {
            if (!is_array($tag)) {
                $tag = array($tag);
            }
            $tags = $tag;
            if (!isset($tags[0])) {
                $tags = array($tags);
            }
            $ret = true;
            foreach ($tags as $i => $tag) {
                if (!is_array($tag) || !isset($tag['attribs'])) {
                    foreach ($choice['attribs'] as $attrib) {
                        if ($attrib[0] != '?') {
                            $ret &= $this->_tagHasNoAttribs($choice['tag'],
                                $context);
                            continue 2;
                        }
                    }
                }
                foreach ($choice['attribs'] as $attrib) {
                    if ($attrib[0] != '?') {
                        if (!isset($tag['attribs'][$attrib])) {
                            $ret &= $this->_tagMissingAttribute($choice['tag'],
                                $attrib, $context);
                        }
                    }
                }
            }
            return $ret;
        }
        return true;
    }

    function _processStructure($key)
    {
        $ret = array();
        if (count($pieces = explode('|', $key)) > 1) {
            $ret['choices'] = array();
            foreach ($pieces as $piece) {
                $ret['choices'][] = $this->_processStructure($piece);
            }
            return $ret;
        }
        $multi = $key[0];
        if ($multi == '+' || $multi == '*') {
            $ret['multiple'] = $key[0];
            $key = substr($key, 1);
        }
        if (count($attrs = explode('->', $key)) > 1) {
            $ret['tag'] = array_shift($attrs);
            $ret['attribs'] = $attrs;
        } else {
            $ret['tag'] = $key;
        }
        return $ret;
    }

    function _validateStabilityVersion()
    {
        $structure = array('release', 'api');
        $a = $this->_stupidSchemaValidate($structure, $this->_packageInfo['version'], '<version>');
        $a &= $this->_stupidSchemaValidate($structure, $this->_packageInfo['stability'], '<stability>');
        if ($a) {
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                  $this->_packageInfo['version']['release'])) {
                $this->_invalidVersion('release', $this->_packageInfo['version']['release']);
            }
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                  $this->_packageInfo['version']['api'])) {
                $this->_invalidVersion('api', $this->_packageInfo['version']['api']);
            }
            if (!in_array($this->_packageInfo['stability']['release'],
                  array('snapshot', 'devel', 'alpha', 'beta', 'stable'))) {
                $this->_invalidState('release', $this->_packageInfo['stability']['release']);
            }
            if (!in_array($this->_packageInfo['stability']['api'],
                  array('devel', 'alpha', 'beta', 'stable'))) {
                $this->_invalidState('api', $this->_packageInfo['stability']['api']);
            }
        }
    }

    function _validateMaintainers()
    {
        $structure =
            array(
                'name',
                'user',
                'email',
                'active',
            );
        foreach (array('lead', 'developer', 'contributor', 'helper') as $type) {
            if (!isset($this->_packageInfo[$type])) {
                continue;
            }
            if (isset($this->_packageInfo[$type][0])) {
                foreach ($this->_packageInfo[$type] as $lead) {
                    $this->_stupidSchemaValidate($structure, $lead, '<' . $type . '>');
                }
            } else {
                $this->_stupidSchemaValidate($structure, $this->_packageInfo[$type],
                    '<' . $type . '>');
            }
        }
    }

    function _validatePhpDep($dep, $installcondition = false)
    {
        $structure = array(
            'min',
            '*max',
            '*exclude',
        );
        $type = $installcondition ? '<installcondition><php>' : '<dependencies><required><php>';
        $this->_stupidSchemaValidate($structure, $dep, $type);
        if (isset($dep['min'])) {
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/',
                  $dep['min'])) {
                $this->_invalidVersion($type . '<min>', $dep['min']);
            }
        }
        if (isset($dep['max'])) {
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/',
                  $dep['max'])) {
                $this->_invalidVersion($type . '<max>', $dep['max']);
            }
        }
        if (isset($dep['exclude'])) {
            if (!is_array($dep['exclude'])) {
                $dep['exclude'] = array($dep['exclude']);
            }
            foreach ($dep['exclude'] as $exclude) {
                if (!preg_match(
                     '/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/',
                     $exclude)) {
                    $this->_invalidVersion($type . '<exclude>', $exclude);
                }
            }
        }
    }

    function _validatePearinstallerDep($dep)
    {
        $structure = array(
            'min',
            '*max',
            '*recommended',
            '*exclude',
        );
        $this->_stupidSchemaValidate($structure, $dep, '<dependencies><required><pearinstaller>');
        if (isset($dep['min'])) {
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                  $dep['min'])) {
                $this->_invalidVersion('<dependencies><required><pearinstaller><min>',
                    $dep['min']);
            }
        }
        if (isset($dep['max'])) {
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                  $dep['max'])) {
                $this->_invalidVersion('<dependencies><required><pearinstaller><max>',
                    $dep['max']);
            }
        }
        if (isset($dep['recommended'])) {
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                  $dep['recommended'])) {
                $this->_invalidVersion('<dependencies><required><pearinstaller><recommended>',
                    $dep['recommended']);
            }
        }
        if (isset($dep['exclude'])) {
            if (!is_array($dep['exclude'])) {
                $dep['exclude'] = array($dep['exclude']);
            }
            foreach ($dep['exclude'] as $exclude) {
                if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                      $exclude)) {
                    $this->_invalidVersion('<dependencies><required><pearinstaller><exclude>',
                        $exclude);
                }
            }
        }
    }

    function _validatePackageDep($dep, $group, $type = '<package>')
    {
        if (isset($dep['uri'])) {
            if (isset($dep['conflicts'])) {
                $structure = array(
                    'name',
                    'uri',
                    'conflicts',
                    '*providesextension',
                );
            } else {
                $structure = array(
                    'name',
                    'uri',
                    '*providesextension',
                );
            }
        } else {
            if (isset($dep['conflicts'])) {
                $structure = array(
                    'name',
                    'channel',
                    '*min',
                    '*max',
                    '*exclude',
                    'conflicts',
                    '*providesextension',
                );
            } else {
                $structure = array(
                    'name',
                    'channel',
                    '*min',
                    '*max',
                    '*recommended',
                    '*exclude',
                    '*nodefault',
                    '*providesextension',
                );
            }
        }
        if (isset($dep['name'])) {
            $type .= '<name>' . $dep['name'] . '</name>';
        }
        $this->_stupidSchemaValidate($structure, $dep, '<dependencies>' . $group . $type);
        if (isset($dep['uri']) && (isset($dep['min']) || isset($dep['max']) ||
              isset($dep['recommended']) || isset($dep['exclude']))) {
            $this->_uriDepsCannotHaveVersioning('<dependencies>' . $group . $type);
        }
        if (isset($dep['channel']) && strtolower($dep['channel']) == '__uri') {
            $this->_DepchannelCannotBeUri('<dependencies>' . $group . $type);
        }
        if (isset($dep['min'])) {
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                  $dep['min'])) {
                $this->_invalidVersion('<dependencies>' . $group . $type . '<min>', $dep['min']);
            }
        }
        if (isset($dep['max'])) {
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                  $dep['max'])) {
                $this->_invalidVersion('<dependencies>' . $group . $type . '<max>', $dep['max']);
            }
        }
        if (isset($dep['recommended'])) {
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                  $dep['recommended'])) {
                $this->_invalidVersion('<dependencies>' . $group . $type . '<recommended>',
                    $dep['recommended']);
            }
        }
        if (isset($dep['exclude'])) {
            if (!is_array($dep['exclude'])) {
                $dep['exclude'] = array($dep['exclude']);
            }
            foreach ($dep['exclude'] as $exclude) {
                if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                      $exclude)) {
                    $this->_invalidVersion('<dependencies>' . $group . $type . '<exclude>',
                        $exclude);
                }
            }
        }
    }

    function _validateSubpackageDep($dep, $group)
    {
        $this->_validatePackageDep($dep, $group, '<subpackage>');
        if (isset($dep['providesextension'])) {
            $this->_subpackageCannotProvideExtension(isset($dep['name']) ? $dep['name'] : '');
        }
        if (isset($dep['conflicts'])) {
            $this->_subpackagesCannotConflict(isset($dep['name']) ? $dep['name'] : '');
        }
    }

    function _validateExtensionDep($dep, $group = false, $installcondition = false)
    {
        if (isset($dep['conflicts'])) {
            $structure = array(
                'name',
                '*min',
                '*max',
                '*exclude',
                'conflicts',
            );
        } else {
            $structure = array(
                'name',
                '*min',
                '*max',
                '*recommended',
                '*exclude',
            );
        }
        if ($installcondition) {
            $type = '<installcondition><extension>';
        } else {
            $type = '<dependencies>' . $group . '<extension>';
        }
        if (isset($dep['name'])) {
            $type .= '<name>' . $dep['name'] . '</name>';
        }
        $this->_stupidSchemaValidate($structure, $dep, $type);
        if (isset($dep['min'])) {
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                  $dep['min'])) {
                $this->_invalidVersion(substr($type, 1) . '<min', $dep['min']);
            }
        }
        if (isset($dep['max'])) {
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                  $dep['max'])) {
                $this->_invalidVersion(substr($type, 1) . '<max', $dep['max']);
            }
        }
        if (isset($dep['recommended'])) {
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                  $dep['recommended'])) {
                $this->_invalidVersion(substr($type, 1) . '<recommended', $dep['recommended']);
            }
        }
        if (isset($dep['exclude'])) {
            if (!is_array($dep['exclude'])) {
                $dep['exclude'] = array($dep['exclude']);
            }
            foreach ($dep['exclude'] as $exclude) {
                if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                      $exclude)) {
                    $this->_invalidVersion(substr($type, 1) . '<exclude', $exclude);
                }
            }
        }
    }

    function _validateOsDep($dep, $installcondition = false)
    {
        $structure = array(
            'name',
            '*conflicts',
        );
        $type = $installcondition ? '<installcondition><os>' : '<dependencies><required><os>';
        if ($this->_stupidSchemaValidate($structure, $dep, $type)) {
            if ($dep['name'] == '*') {
                if (array_key_exists('conflicts', $dep)) {
                    $this->_cannotConflictWithAllOs($type);
                }
            }
        }
    }

    function _validateArchDep($dep, $installcondition = false)
    {
        $structure = array(
            'pattern',
            '*conflicts',
        );
        $type = $installcondition ? '<installcondition><arch>' : '<dependencies><required><arch>';
        $this->_stupidSchemaValidate($structure, $dep, $type);
    }

    function _validateInstallConditions($cond, $release)
    {
        $structure = array(
            '*php',
            '*extension',
            '*os',
            '*arch',
        );
        if (!$this->_stupidSchemaValidate($structure,
              $cond, $release)) {
            return false;
        }
        foreach (array('php', 'extension', 'os', 'arch') as $type) {
            if (isset($cond[$type])) {
                $iter = $cond[$type];
                if (!is_array($iter) || !isset($iter[0])) {
                    $iter = array($iter);
                }
                foreach ($iter as $package) {
                    if ($type == 'extension') {
                        $this->{"_validate{$type}Dep"}($package, false, true);
                    } else {
                        $this->{"_validate{$type}Dep"}($package, true);
                    }
                }
            }
        }
    }

    function _validateDependencies()
    {
        $structure = array(
            'required',
            '*optional',
            '*group->name->hint'
        );
        if (!$this->_stupidSchemaValidate($structure,
              $this->_packageInfo['dependencies'], '<dependencies>')) {
            return false;
        }
        foreach (array('required', 'optional') as $simpledep) {
            if (isset($this->_packageInfo['dependencies'][$simpledep])) {
                if ($simpledep == 'optional') {
                    $structure = array(
                        '*package',
                        '*subpackage',
                        '*extension',
                    );
                } else {
                    $structure = array(
                        'php',
                        'pearinstaller',
                        '*package',
                        '*subpackage',
                        '*extension',
                        '*os',
                        '*arch',
                    );
                }
                if ($this->_stupidSchemaValidate($structure,
                      $this->_packageInfo['dependencies'][$simpledep],
                      "<dependencies><$simpledep>")) {
                    foreach (array('package', 'subpackage', 'extension') as $type) {
                        if (isset($this->_packageInfo['dependencies'][$simpledep][$type])) {
                            $iter = $this->_packageInfo['dependencies'][$simpledep][$type];
                            if (!isset($iter[0])) {
                                $iter = array($iter);
                            }
                            foreach ($iter as $package) {
                                if ($type != 'extension') {
                                    if (isset($package['uri'])) {
                                        if (isset($package['channel'])) {
                                            $this->_UrlOrChannel($type,
                                                $package['name']);
                                        }
                                    } else {
                                        if (!isset($package['channel'])) {
                                            $this->_NoChannel($type, $package['name']);
                                        }
                                    }
                                }
                                $this->{"_validate{$type}Dep"}($package, "<$simpledep>");
                            }
                        }
                    }
                    if ($simpledep == 'optional') {
                        continue;
                    }
                    foreach (array('php', 'pearinstaller', 'os', 'arch') as $type) {
                        if (isset($this->_packageInfo['dependencies'][$simpledep][$type])) {
                            $iter = $this->_packageInfo['dependencies'][$simpledep][$type];
                            if (!isset($iter[0])) {
                                $iter = array($iter);
                            }
                            foreach ($iter as $package) {
                                $this->{"_validate{$type}Dep"}($package);
                            }
                        }
                    }
                }
            }
        }
        if (isset($this->_packageInfo['dependencies']['group'])) {
            $groups = $this->_packageInfo['dependencies']['group'];
            if (!isset($groups[0])) {
                $groups = array($groups);
            }
            $structure = array(
                '*package',
                '*subpackage',
                '*extension',
            );
            foreach ($groups as $group) {
                if ($this->_stupidSchemaValidate($structure, $group, '<group>')) {
                    if (!PEAR_Validate::validGroupName($group['attribs']['name'])) {
                        $this->_invalidDepGroupName($group['attribs']['name']);
                    }
                    foreach (array('package', 'subpackage', 'extension') as $type) {
                        if (isset($group[$type])) {
                            $iter = $group[$type];
                            if (!isset($iter[0])) {
                                $iter = array($iter);
                            }
                            foreach ($iter as $package) {
                                if ($type != 'extension') {
                                    if (isset($package['uri'])) {
                                        if (isset($package['channel'])) {
                                            $this->_UrlOrChannelGroup($type,
                                                $package['name'],
                                                $group['name']);
                                        }
                                    } else {
                                        if (!isset($package['channel'])) {
                                            $this->_NoChannelGroup($type,
                                                $package['name'],
                                                $group['name']);
                                        }
                                    }
                                }
                                $this->{"_validate{$type}Dep"}($package, '<group name="' .
                                    $group['attribs']['name'] . '">');
                            }
                        }
                    }
                }
            }
        }
    }

    function _validateCompatible()
    {
        $compat = $this->_packageInfo['compatible'];
        if (!isset($compat[0])) {
            $compat = array($compat);
        }
        $required = array('name', 'channel', 'min', 'max', '*exclude');
        foreach ($compat as $package) {
            $type = '<compatible>';
            if (is_array($package) && array_key_exists('name', $package)) {
                $type .= '<name>' . $package['name'] . '</name>';
            }
            $this->_stupidSchemaValidate($required, $package, $type);
            if (is_array($package) && array_key_exists('min', $package)) {
                if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                      $package['min'])) {
                    $this->_invalidVersion(substr($type, 1) . '<min', $package['min']);
                }
            }
            if (is_array($package) && array_key_exists('max', $package)) {
                if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                      $package['max'])) {
                    $this->_invalidVersion(substr($type, 1) . '<max', $package['max']);
                }
            }
            if (is_array($package) && array_key_exists('exclude', $package)) {
                if (!is_array($package['exclude'])) {
                    $package['exclude'] = array($package['exclude']);
                }
                foreach ($package['exclude'] as $exclude) {
                    if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                          $exclude)) {
                        $this->_invalidVersion(substr($type, 1) . '<exclude', $exclude);
                    }
                }
            }
        }
    }

    function _validateBundle($list)
    {
        if (!is_array($list) || !isset($list['bundledpackage'])) {
            return $this->_NoBundledPackages();
        }
        if (!is_array($list['bundledpackage']) || !isset($list['bundledpackage'][0])) {
            return $this->_AtLeast2BundledPackages();
        }
        foreach ($list['bundledpackage'] as $package) {
            if (!is_string($package)) {
                $this->_bundledPackagesMustBeFilename();
            }
        }
    }

    function _validateFilelist($list = false, $allowignore = false, $dirs = '')
    {
        $iscontents = false;
        if (!$list) {
            $iscontents = true;
            $list = $this->_packageInfo['contents'];
            if (isset($this->_packageInfo['bundle'])) {
                return $this->_validateBundle($list);
            }
        }
        if ($allowignore) {
            $struc = array(
                '*install->name->as',
                '*ignore->name'
            );
        } else {
            $struc = array(
                '*dir->name->?baseinstalldir',
                '*file->name->role->?baseinstalldir->?md5sum'
            );
            if (isset($list['dir']) && isset($list['file'])) {
                // stave off validation errors without requiring a set order.
                $_old = $list;
                if (isset($list['attribs'])) {
                    $list = array('attribs' => $_old['attribs']);
                }
                $list['dir'] = $_old['dir'];
                $list['file'] = $_old['file'];
            }
        }
        if (!isset($list['attribs']) || !isset($list['attribs']['name'])) {
            $unknown = $allowignore ? '<filelist>' : '<dir name="*unknown*">';
            $dirname = $iscontents ? '<contents>' : $unknown;
        } else {
            $dirname = '<dir name="' . $list['attribs']['name'] . '">';
            if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
                          str_replace('\\', '/', $list['attribs']['name']))) {
                // file contains .. parent directory or . cur directory
                $this->_invalidDirName($list['attribs']['name']);
            }
        }
        $res = $this->_stupidSchemaValidate($struc, $list, $dirname);
        if ($allowignore && $res) {
            $ignored_or_installed = array();
            $this->_pf->getFilelist();
            $fcontents = $this->_pf->getContents();
            $filelist = array();
            if (!isset($fcontents['dir']['file'][0])) {
                $fcontents['dir']['file'] = array($fcontents['dir']['file']);
            }
            foreach ($fcontents['dir']['file'] as $file) {
                $filelist[$file['attribs']['name']] = true;
            }
            if (isset($list['install'])) {
                if (!isset($list['install'][0])) {
                    $list['install'] = array($list['install']);
                }
                foreach ($list['install'] as $file) {
                    if (!isset($filelist[$file['attribs']['name']])) {
                        $this->_notInContents($file['attribs']['name'], 'install');
                        continue;
                    }
                    if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) {
                        $this->_multipleInstallAs($file['attribs']['name']);
                    }
                    if (!isset($ignored_or_installed[$file['attribs']['name']])) {
                        $ignored_or_installed[$file['attribs']['name']] = array();
                    }
                    $ignored_or_installed[$file['attribs']['name']][] = 1;
                    if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
                                  str_replace('\\', '/', $file['attribs']['as']))) {
                        // file contains .. parent directory or . cur directory references
                        $this->_invalidFileInstallAs($file['attribs']['name'],
                            $file['attribs']['as']);
                    }
                }
            }
            if (isset($list['ignore'])) {
                if (!isset($list['ignore'][0])) {
                    $list['ignore'] = array($list['ignore']);
                }
                foreach ($list['ignore'] as $file) {
                    if (!isset($filelist[$file['attribs']['name']])) {
                        $this->_notInContents($file['attribs']['name'], 'ignore');
                        continue;
                    }
                    if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) {
                        $this->_ignoreAndInstallAs($file['attribs']['name']);
                    }
                }
            }
        }
        if (!$allowignore && isset($list['file'])) {
            if (is_string($list['file'])) {
                $this->_oldStyleFileNotAllowed();
                return false;
            }
            if (!isset($list['file'][0])) {
                // single file
                $list['file'] = array($list['file']);
            }
            foreach ($list['file'] as $i => $file)
            {
                if (isset($file['attribs']) && isset($file['attribs']['name'])) {
                    if ($file['attribs']['name'][0] == '.' &&
                          $file['attribs']['name'][1] == '/') {
                        // name is something like "./doc/whatever.txt"
                        $this->_invalidFileName($file['attribs']['name'], $dirname);
                    }
                    if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
                                  str_replace('\\', '/', $file['attribs']['name']))) {
                        // file contains .. parent directory or . cur directory
                        $this->_invalidFileName($file['attribs']['name'], $dirname);
                    }
                }
                if (isset($file['attribs']) && isset($file['attribs']['role'])) {
                    if (!$this->_validateRole($file['attribs']['role'])) {
                        if (isset($this->_packageInfo['usesrole'])) {
                            $roles = $this->_packageInfo['usesrole'];
                            if (!isset($roles[0])) {
                                $roles = array($roles);
                            }
                            foreach ($roles as $role) {
                                if ($role['role'] = $file['attribs']['role']) {
                                    $msg = 'This package contains role "%role%" and requires ' .
                                        'package "%package%" to be used';
                                    if (isset($role['uri'])) {
                                        $params = array('role' => $role['role'],
                                            'package' => $role['uri']);
                                    } else {
                                        $params = array('role' => $role['role'],
                                            'package' => $this->_pf->_registry->
                                            parsedPackageNameToString(array('package' =>
                                                $role['package'], 'channel' => $role['channel']),
                                                true));
                                    }
                                    $this->_stack->push('_mustInstallRole', 'error', $params, $msg);
                                }
                            }
                        }
                        $this->_invalidFileRole($file['attribs']['name'],
                            $dirname, $file['attribs']['role']);
                    }
                }
                if (!isset($file['attribs'])) {
                    continue;
                }
                $save = $file['attribs'];
                if ($dirs) {
                    $save['name'] = $dirs . '/' . $save['name'];
                }
                unset($file['attribs']);
                if (count($file) && $this->_curState != PEAR_VALIDATE_DOWNLOADING) { // has tasks
                    foreach ($file as $task => $value) {
                        if ($tagClass = $this->_pf->getTask($task)) {
                            if (!is_array($value) || !isset($value[0])) {
                                $value = array($value);
                            }
                            foreach ($value as $v) {
                                $ret = call_user_func(array($tagClass, 'validateXml'),
                                    $this->_pf, $v, $this->_pf->_config, $save);
                                if (is_array($ret)) {
                                    $this->_invalidTask($task, $ret, isset($save['name']) ?
                                        $save['name'] : '');
                                }
                            }
                        } else {
                            if (isset($this->_packageInfo['usestask'])) {
                                $roles = $this->_packageInfo['usestask'];
                                if (!isset($roles[0])) {
                                    $roles = array($roles);
                                }
                                foreach ($roles as $role) {
                                    if ($role['task'] = $task) {
                                        $msg = 'This package contains task "%task%" and requires ' .
                                            'package "%package%" to be used';
                                        if (isset($role['uri'])) {
                                            $params = array('task' => $role['task'],
                                                'package' => $role['uri']);
                                        } else {
                                            $params = array('task' => $role['task'],
                                                'package' => $this->_pf->_registry->
                                                parsedPackageNameToString(array('package' =>
                                                    $role['package'], 'channel' => $role['channel']),
                                                    true));
                                        }
                                        $this->_stack->push('_mustInstallTask', 'error',
                                            $params, $msg);
                                    }
                                }
                            }
                            $this->_unknownTask($task, $save['name']);
                        }
                    }
                }
            }
        }
        if (isset($list['ignore'])) {
            if (!$allowignore) {
                $this->_ignoreNotAllowed('ignore');
            }
        }
        if (isset($list['install'])) {
            if (!$allowignore) {
                $this->_ignoreNotAllowed('install');
            }
        }
        if (isset($list['file'])) {
            if ($allowignore) {
                $this->_fileNotAllowed('file');
            }
        }
        if (isset($list['dir'])) {
            if ($allowignore) {
                $this->_fileNotAllowed('dir');
            } else {
                if (!isset($list['dir'][0])) {
                    $list['dir'] = array($list['dir']);
                }
                foreach ($list['dir'] as $dir) {
                    if (isset($dir['attribs']) && isset($dir['attribs']['name'])) {
                        if ($dir['attribs']['name'] == '/' ||
                              !isset($this->_packageInfo['contents']['dir']['dir'])) {
                            // always use nothing if the filelist has already been flattened
                            $newdirs = '';
                        } elseif ($dirs == '') {
                            $newdirs = $dir['attribs']['name'];
                        } else {
                            $newdirs = $dirs . '/' . $dir['attribs']['name'];
                        }
                    } else {
                        $newdirs = $dirs;
                    }
                    $this->_validateFilelist($dir, $allowignore, $newdirs);
                }
            }
        }
    }

    function _validateRelease()
    {
        if (isset($this->_packageInfo['phprelease'])) {
            $release = 'phprelease';
            if (isset($this->_packageInfo['providesextension'])) {
                $this->_cannotProvideExtension($release);
            }
            if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
                $this->_cannotHaveSrcpackage($release);
            }
            $releases = $this->_packageInfo['phprelease'];
            if (!is_array($releases)) {
                return true;
            }
            if (!isset($releases[0])) {
                $releases = array($releases);
            }
            foreach ($releases as $rel) {
                $this->_stupidSchemaValidate(array(
                    '*installconditions',
                    '*filelist',
                ), $rel, '<phprelease>');
            }
        }
        foreach (array('', 'zend') as $prefix) {
            $releasetype = $prefix . 'extsrcrelease';
            if (isset($this->_packageInfo[$releasetype])) {
                $release = $releasetype;
                if (!isset($this->_packageInfo['providesextension'])) {
                    $this->_mustProvideExtension($release);
                }
                if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
                    $this->_cannotHaveSrcpackage($release);
                }
                $releases = $this->_packageInfo[$releasetype];
                if (!is_array($releases)) {
                    return true;
                }
                if (!isset($releases[0])) {
                    $releases = array($releases);
                }
                foreach ($releases as $rel) {
                    $this->_stupidSchemaValidate(array(
                        '*installconditions',
                        '*configureoption->name->prompt->?default',
                        '*binarypackage',
                        '*filelist',
                    ), $rel, '<' . $releasetype . '>');
                    if (isset($rel['binarypackage'])) {
                        if (!is_array($rel['binarypackage']) || !isset($rel['binarypackage'][0])) {
                            $rel['binarypackage'] = array($rel['binarypackage']);
                        }
                        foreach ($rel['binarypackage'] as $bin) {
                            if (!is_string($bin)) {
                                $this->_binaryPackageMustBePackagename();
                            }
                        }
                    }
                }
            }
            $releasetype = 'extbinrelease';
            if (isset($this->_packageInfo[$releasetype])) {
                $release = $releasetype;
                if (!isset($this->_packageInfo['providesextension'])) {
                    $this->_mustProvideExtension($release);
                }
                if (isset($this->_packageInfo['channel']) &&
                      !isset($this->_packageInfo['srcpackage'])) {
                    $this->_mustSrcPackage($release);
                }
                if (isset($this->_packageInfo['uri']) && !isset($this->_packageInfo['srcuri'])) {
                    $this->_mustSrcuri($release);
                }
                $releases = $this->_packageInfo[$releasetype];
                if (!is_array($releases)) {
                    return true;
                }
                if (!isset($releases[0])) {
                    $releases = array($releases);
                }
                foreach ($releases as $rel) {
                    $this->_stupidSchemaValidate(array(
                        '*installconditions',
                        '*filelist',
                    ), $rel, '<' . $releasetype . '>');
                }
            }
        }
        if (isset($this->_packageInfo['bundle'])) {
            $release = 'bundle';
            if (isset($this->_packageInfo['providesextension'])) {
                $this->_cannotProvideExtension($release);
            }
            if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
                $this->_cannotHaveSrcpackage($release);
            }
            $releases = $this->_packageInfo['bundle'];
            if (!is_array($releases) || !isset($releases[0])) {
                $releases = array($releases);
            }
            foreach ($releases as $rel) {
                $this->_stupidSchemaValidate(array(
                    '*installconditions',
                    '*filelist',
                ), $rel, '<bundle>');
            }
        }
        foreach ($releases as $rel) {
            if (is_array($rel) && array_key_exists('installconditions', $rel)) {
                $this->_validateInstallConditions($rel['installconditions'],
                    "<$release><installconditions>");
            }
            if (is_array($rel) && array_key_exists('filelist', $rel)) {
                if ($rel['filelist']) {

                    $this->_validateFilelist($rel['filelist'], true);
                }
            }
        }
    }

    /**
     * This is here to allow role extension through plugins
     * @param string
     */
    function _validateRole($role)
    {
        return in_array($role, PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType()));
    }

    function _pearVersionTooLow($version)
    {
        $this->_stack->push(__FUNCTION__, 'error',
            array('version' => $version),
            'This package.xml requires PEAR version %version% to parse properly, we are ' .
            'version 1.10.16');
    }

    function _invalidTagOrder($oktags, $actual, $root)
    {
        $this->_stack->push(__FUNCTION__, 'error',
            array('oktags' => $oktags, 'actual' => $actual, 'root' => $root),
            'Invalid tag order in %root%, found <%actual%> expected one of "%oktags%"');
    }

    function _ignoreNotAllowed($type)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
            '<%type%> is not allowed inside global <contents>, only inside ' .
            '<phprelease>/<extbinrelease>/<zendextbinrelease>, use <dir> and <file> only');
    }

    function _fileNotAllowed($type)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
            '<%type%> is not allowed inside release <filelist>, only inside ' .
            '<contents>, use <ignore> and <install> only');
    }

    function _oldStyleFileNotAllowed()
    {
        $this->_stack->push(__FUNCTION__, 'error', array(),
            'Old-style <file>name</file> is not allowed.  Use' .
            '<file name="name" role="role"/>');
    }

    function _tagMissingAttribute($tag, $attr, $context)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag,
            'attribute' => $attr, 'context' => $context),
            'tag <%tag%> in context "%context%" has no attribute "%attribute%"');
    }

    function _tagHasNoAttribs($tag, $context)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag,
            'context' => $context),
            'tag <%tag%> has no attributes in context "%context%"');
    }

    function _invalidInternalStructure()
    {
        $this->_stack->push(__FUNCTION__, 'exception', array(),
            'internal array was not generated by compatible parser, or extreme parser error, cannot continue');
    }

    function _invalidFileRole($file, $dir, $role)
    {
        $this->_stack->push(__FUNCTION__, 'error', array(
            'file' => $file, 'dir' => $dir, 'role' => $role,
            'roles' => PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType())),
            'File "%file%" in directory "%dir%" has invalid role "%role%", should be one of %roles%');
    }

    function _invalidFileName($file, $dir)
    {
        $this->_stack->push(__FUNCTION__, 'error', array(
            'file' => $file),
            'File "%file%" in directory "%dir%" cannot begin with "./" or contain ".."');
    }

    function _invalidFileInstallAs($file, $as)
    {
        $this->_stack->push(__FUNCTION__, 'error', array(
            'file' => $file, 'as' => $as),
            'File "%file%" <install as="%as%"/> cannot contain "./" or contain ".."');
    }

    function _invalidDirName($dir)
    {
        $this->_stack->push(__FUNCTION__, 'error', array(
            'dir' => $file),
            'Directory "%dir%" cannot begin with "./" or contain ".."');
    }

    function _filelistCannotContainFile($filelist)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('tag' => $filelist),
            '<%tag%> can only contain <dir>, contains <file>.  Use ' .
            '<dir name="/"> as the first dir element');
    }

    function _filelistMustContainDir($filelist)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('tag' => $filelist),
            '<%tag%> must contain <dir>.  Use <dir name="/"> as the ' .
            'first dir element');
    }

    function _tagCannotBeEmpty($tag)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag),
            '<%tag%> cannot be empty (<%tag%/>)');
    }

    function _UrlOrChannel($type, $name)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
            'name' => $name),
            'Required dependency <%type%> "%name%" can have either url OR ' .
            'channel attributes, and not both');
    }

    function _NoChannel($type, $name)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
            'name' => $name),
            'Required dependency <%type%> "%name%" must have either url OR ' .
            'channel attributes');
    }

    function _UrlOrChannelGroup($type, $name, $group)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
            'name' => $name, 'group' => $group),
            'Group "%group%" dependency <%type%> "%name%" can have either url OR ' .
            'channel attributes, and not both');
    }

    function _NoChannelGroup($type, $name, $group)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
            'name' => $name, 'group' => $group),
            'Group "%group%" dependency <%type%> "%name%" must have either url OR ' .
            'channel attributes');
    }

    function _unknownChannel($channel)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('channel' => $channel),
            'Unknown channel "%channel%"');
    }

    function _noPackageVersion()
    {
        $this->_stack->push(__FUNCTION__, 'error', array(),
            'package.xml <package> tag has no version attribute, or version is not 2.0');
    }

    function _NoBundledPackages()
    {
        $this->_stack->push(__FUNCTION__, 'error', array(),
            'No <bundledpackage> tag was found in <contents>, required for bundle packages');
    }

    function _AtLeast2BundledPackages()
    {
        $this->_stack->push(__FUNCTION__, 'error', array(),
            'At least 2 packages must be bundled in a bundle package');
    }

    function _ChannelOrUri($name)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
            'Bundled package "%name%" can have either a uri or a channel, not both');
    }

    function _noChildTag($child, $tag)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('child' => $child, 'tag' => $tag),
            'Tag <%tag%> is missing child tag <%child%>');
    }

    function _invalidVersion($type, $value)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'value' => $value),
            'Version type <%type%> is not a valid version (%value%)');
    }

    function _invalidState($type, $value)
    {
        $states = array('stable', 'beta', 'alpha', 'devel');
        if ($type != 'api') {
            $states[] = 'snapshot';
        }
        if (strtolower($value) == 'rc') {
            $this->_stack->push(__FUNCTION__, 'error',
                array('version' => $this->_packageInfo['version']['release']),
                'RC is not a state, it is a version postfix, try %version%RC1, stability beta');
        }
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'value' => $value,
            'types' => $states),
            'Stability type <%type%> is not a valid stability (%value%), must be one of ' .
            '%types%');
    }

    function _invalidTask($task, $ret, $file)
    {
        switch ($ret[0]) {
            case PEAR_TASK_ERROR_MISSING_ATTRIB :
                $info = array('attrib' => $ret[1], 'task' => $task, 'file' => $file);
                $msg = 'task <%task%> is missing attribute "%attrib%" in file %file%';
            break;
            case PEAR_TASK_ERROR_NOATTRIBS :
                $info = array('task' => $task, 'file' => $file);
                $msg = 'task <%task%> has no attributes in file %file%';
            break;
            case PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE :
                $info = array('attrib' => $ret[1], 'values' => $ret[3],
                    'was' => $ret[2], 'task' => $task, 'file' => $file);
                $msg = 'task <%task%> attribute "%attrib%" has the wrong value "%was%" '.
                    'in file %file%, expecting one of "%values%"';
            break;
            case PEAR_TASK_ERROR_INVALID :
                $info = array('reason' => $ret[1], 'task' => $task, 'file' => $file);
                $msg = 'task <%task%> in file %file% is invalid because of "%reason%"';
            break;
        }
        $this->_stack->push(__FUNCTION__, 'error', $info, $msg);
    }

    function _unknownTask($task, $file)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('task' => $task, 'file' => $file),
            'Unknown task "%task%" passed in file <file name="%file%">');
    }

    function _subpackageCannotProvideExtension($name)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
            'Subpackage dependency "%name%" cannot use <providesextension>, ' .
            'only package dependencies can use this tag');
    }

    function _subpackagesCannotConflict($name)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
            'Subpackage dependency "%name%" cannot use <conflicts/>, ' .
            'only package dependencies can use this tag');
    }

    function _cannotProvideExtension($release)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
            '<%release%> packages cannot use <providesextension>, only extbinrelease, extsrcrelease, zendextsrcrelease, and zendextbinrelease can provide a PHP extension');
    }

    function _mustProvideExtension($release)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
            '<%release%> packages must use <providesextension> to indicate which PHP extension is provided');
    }

    function _cannotHaveSrcpackage($release)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
            '<%release%> packages cannot specify a source code package, only extension binaries may use the <srcpackage> tag');
    }

    function _mustSrcPackage($release)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
            '<extbinrelease>/<zendextbinrelease> packages must specify a source code package with <srcpackage>');
    }

    function _mustSrcuri($release)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
            '<extbinrelease>/<zendextbinrelease> packages must specify a source code package with <srcuri>');
    }

    function _uriDepsCannotHaveVersioning($type)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
            '%type%: dependencies with a <uri> tag cannot have any versioning information');
    }

    function _conflictingDepsCannotHaveVersioning($type)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
            '%type%: conflicting dependencies cannot have versioning info, use <exclude> to ' .
            'exclude specific versions of a dependency');
    }

    function _DepchannelCannotBeUri($type)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
            '%type%: channel cannot be __uri, this is a pseudo-channel reserved for uri ' .
            'dependencies only');
    }

    function _bundledPackagesMustBeFilename()
    {
        $this->_stack->push(__FUNCTION__, 'error', array(),
            '<bundledpackage> tags must contain only the filename of a package release ' .
            'in the bundle');
    }

    function _binaryPackageMustBePackagename()
    {
        $this->_stack->push(__FUNCTION__, 'error', array(),
            '<binarypackage> tags must contain the name of a package that is ' .
            'a compiled version of this extsrc/zendextsrc package');
    }

    function _fileNotFound($file)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
            'File "%file%" in package.xml does not exist');
    }

    function _notInContents($file, $tag)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('file' => $file, 'tag' => $tag),
            '<%tag% name="%file%"> is invalid, file is not in <contents>');
    }

    function _cannotValidateNoPathSet()
    {
        $this->_stack->push(__FUNCTION__, 'error', array(),
            'Cannot validate files, no path to package file is set (use setPackageFile())');
    }

    function _usesroletaskMustHaveChannelOrUri($role, $tag)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag),
            '<%tag%> for role "%role%" must contain either <uri>, or <channel> and <package>');
    }

    function _usesroletaskMustHavePackage($role, $tag)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag),
            '<%tag%> for role "%role%" must contain <package>');
    }

    function _usesroletaskMustHaveRoleTask($tag, $type)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag, 'type' => $type),
            '<%tag%> must contain <%type%> defining the %type% to be used');
    }

    function _cannotConflictWithAllOs($type)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag),
            '%tag% cannot conflict with all OSes');
    }

    function _invalidDepGroupName($name)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
            'Invalid dependency group name "%name%"');
    }

    function _multipleToplevelDirNotAllowed()
    {
        $this->_stack->push(__FUNCTION__, 'error', array(),
            'Multiple top-level <dir> tags are not allowed.  Enclose them ' .
                'in a <dir name="/">');
    }

    function _multipleInstallAs($file)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
            'Only one <install> tag is allowed for file "%file%"');
    }

    function _ignoreAndInstallAs($file)
    {
        $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
            'Cannot have both <ignore> and <install> tags for file "%file%"');
    }

    function _analyzeBundledPackages()
    {
        if (!$this->_isValid) {
            return false;
        }
        if (!$this->_pf->getPackageType() == 'bundle') {
            return false;
        }
        if (!isset($this->_pf->_packageFile)) {
            return false;
        }
        $dir_prefix = dirname($this->_pf->_packageFile);
        $common = new PEAR_Common;
        $log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') :
            array($common, 'log');
        $info = $this->_pf->getContents();
        $info = $info['bundledpackage'];
        if (!is_array($info)) {
            $info = array($info);
        }
        $pkg = new PEAR_PackageFile($this->_pf->_config);
        foreach ($info as $package) {
            if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $package)) {
                $this->_fileNotFound($dir_prefix . DIRECTORY_SEPARATOR . $package);
                $this->_isValid = 0;
                continue;
            }
            call_user_func_array($log, array(1, "Analyzing bundled package $package"));
            PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
            $ret = $pkg->fromAnyFile($dir_prefix . DIRECTORY_SEPARATOR . $package,
                PEAR_VALIDATE_NORMAL);
            PEAR::popErrorHandling();
            if (PEAR::isError($ret)) {
                call_user_func_array($log, array(0, "ERROR: package $package is not a valid " .
                    'package'));
                $inf = $ret->getUserInfo();
                if (is_array($inf)) {
                    foreach ($inf as $err) {
                        call_user_func_array($log, array(1, $err['message']));
                    }
                }
                return false;
            }
        }
        return true;
    }

    function _analyzePhpFiles()
    {
        if (!$this->_isValid) {
            return false;
        }
        if (!isset($this->_pf->_packageFile)) {
            $this->_cannotValidateNoPathSet();
            return false;
        }
        $dir_prefix = dirname($this->_pf->_packageFile);
        $common = new PEAR_Common;
        $log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') :
            array(&$common, 'log');
        $info = $this->_pf->getContents();
        if (!$info || !isset($info['dir']['file'])) {
            $this->_tagCannotBeEmpty('contents><dir');
            return false;
        }
        $info = $info['dir']['file'];
        if (isset($info['attribs'])) {
            $info = array($info);
        }
        $provides = array();
        foreach ($info as $fa) {
            $fa = $fa['attribs'];
            $file = $fa['name'];
            if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $file)) {
                $this->_fileNotFound($dir_prefix . DIRECTORY_SEPARATOR . $file);
                $this->_isValid = 0;
                continue;
            }
            if (in_array($fa['role'], PEAR_Installer_Role::getPhpRoles()) && $dir_prefix) {
                call_user_func_array($log, array(1, "Analyzing $file"));
                $srcinfo = $this->analyzeSourceCode($dir_prefix . DIRECTORY_SEPARATOR . $file);
                if ($srcinfo) {
                    $provides = array_merge($provides, $this->_buildProvidesArray($srcinfo));
                }
            }
        }
        $this->_packageName = $pn = $this->_pf->getPackage();
        $pnl = strlen($pn);
        foreach ($provides as $key => $what) {
            if (isset($what['explicit']) || !$what) {
                // skip conformance checks if the provides entry is
                // specified in the package.xml file
                continue;
            }
            extract($what);
            if ($type == 'class') {
                if (!strncasecmp($name, $pn, $pnl)) {
                    continue;
                }
                $this->_stack->push(__FUNCTION__, 'warning',
                    array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn),
                    'in %file%: %type% "%name%" not prefixed with package name "%package%"');
            } elseif ($type == 'function') {
                if (strstr($name, '::') || !strncasecmp($name, $pn, $pnl)) {
                    continue;
                }
                $this->_stack->push(__FUNCTION__, 'warning',
                    array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn),
                    'in %file%: %type% "%name%" not prefixed with package name "%package%"');
            }
        }
        return $this->_isValid;
    }

    /**
     * Analyze the source code of the given PHP file
     *
     * @param  string Filename of the PHP file
     * @param  boolean whether to analyze $file as the file contents
     * @return mixed
     */
    function analyzeSourceCode($file, $string = false)
    {
        if (!function_exists("token_get_all")) {
            $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
                'Parser error: token_get_all() function must exist to analyze source code, PHP may have been compiled with --disable-tokenizer');
            return false;
        }

        if (!defined('T_DOC_COMMENT')) {
            define('T_DOC_COMMENT', T_COMMENT);
        }

        if (!defined('T_INTERFACE')) {
            define('T_INTERFACE', -1);
        }

        if (!defined('T_IMPLEMENTS')) {
            define('T_IMPLEMENTS', -1);
        }

        if ($string) {
            $contents = $file;
        } else {
            if (!$fp = @fopen($file, "r")) {
                return false;
            }
            fclose($fp);
            $contents = file_get_contents($file);
        }

        // Silence this function so we can catch PHP Warnings and show our own custom message
        $tokens = @token_get_all($contents);
        if (isset($php_errormsg)) {
            if (isset($this->_stack)) {
                $pn = $this->_pf->getPackage();
                $this->_stack->push(__FUNCTION__, 'warning',
                        array('file' => $file, 'package' => $pn),
                        'in %file%: Could not process file for unknown reasons,' .
                        ' possibly a PHP parse error in %file% from %package%');
            }
        }
/*
        for ($i = 0; $i < sizeof($tokens); $i++) {
            @list($token, $data) = $tokens[$i];
            if (is_string($token)) {
                var_dump($token);
            } else {
                print token_name($token) . ' ';
                var_dump(rtrim($data));
            }
        }
*/
        $look_for = 0;
        $paren_level = 0;
        $bracket_level = 0;
        $brace_level = 0;
        $lastphpdoc = '';
        $current_class = '';
        $current_interface = '';
        $current_class_level = -1;
        $current_function = '';
        $current_function_level = -1;
        $declared_classes = array();
        $declared_interfaces = array();
        $declared_functions = array();
        $declared_methods = array();
        $used_classes = array();
        $used_functions = array();
        $extends = array();
        $implements = array();
        $nodeps = array();
        $inquote = false;
        $interface = false;
        for ($i = 0; $i < sizeof($tokens); $i++) {
            if (is_array($tokens[$i])) {
                list($token, $data) = $tokens[$i];
            } else {
                $token = $tokens[$i];
                $data = '';
            }

            if ($inquote) {
                if ($token != '"' && $token != T_END_HEREDOC) {
                    continue;
                } else {
                    $inquote = false;
                    continue;
                }
            }

            switch ($token) {
                case T_WHITESPACE :
                    continue 2;
                case ';':
                    if ($interface) {
                        $current_function = '';
                        $current_function_level = -1;
                    }
                    break;
                case '"':
                case T_START_HEREDOC:
                    $inquote = true;
                    break;
                case T_CURLY_OPEN:
                case T_DOLLAR_OPEN_CURLY_BRACES:
                case '{': $brace_level++; continue 2;
                case '}':
                    $brace_level--;
                    if ($current_class_level == $brace_level) {
                        $current_class = '';
                        $current_class_level = -1;
                    }
                    if ($current_function_level == $brace_level) {
                        $current_function = '';
                        $current_function_level = -1;
                    }
                    continue 2;
                case '[': $bracket_level++; continue 2;
                case ']': $bracket_level--; continue 2;
                case '(': $paren_level++;   continue 2;
                case ')': $paren_level--;   continue 2;
                case T_INTERFACE:
                    $interface = true;
                case T_CLASS:
                    if (($current_class_level != -1) || ($current_function_level != -1)) {
                        if (isset($this->_stack)) {
                            $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
                            'Parser error: invalid PHP found in file "%file%"');
                        } else {
                            PEAR::raiseError("Parser error: invalid PHP found in file \"$file\"",
                                PEAR_COMMON_ERROR_INVALIDPHP);
                        }

                        return false;
                    }
                case T_FUNCTION:
                case T_NEW:
                case T_EXTENDS:
                case T_IMPLEMENTS:
                    $look_for = $token;
                    continue 2;
                case T_STRING:
                    if ($look_for == T_CLASS) {
                        $current_class = $data;
                        $current_class_level = $brace_level;
                        $declared_classes[] = $current_class;
                    } elseif ($look_for == T_INTERFACE) {
                        $current_interface = $data;
                        $current_class_level = $brace_level;
                        $declared_interfaces[] = $current_interface;
                    } elseif ($look_for == T_IMPLEMENTS) {
                        $implements[$current_class] = $data;
                    } elseif ($look_for == T_EXTENDS) {
                        $extends[$current_class] = $data;
                    } elseif ($look_for == T_FUNCTION) {
                        if ($current_class) {
                            $current_function = "$current_class::$data";
                            $declared_methods[$current_class][] = $data;
                        } elseif ($current_interface) {
                            $current_function = "$current_interface::$data";
                            $declared_methods[$current_interface][] = $data;
                        } else {
                            $current_function = $data;
                            $declared_functions[] = $current_function;
                        }

                        $current_function_level = $brace_level;
                        $m = array();
                    } elseif ($look_for == T_NEW) {
                        $used_classes[$data] = true;
                    }

                    $look_for = 0;
                    continue 2;
                case T_VARIABLE:
                    $look_for = 0;
                    continue 2;
                case T_DOC_COMMENT:
                case T_COMMENT:
                    if (preg_match('!^/\*\*\s!', $data)) {
                        $lastphpdoc = $data;
                        if (preg_match_all('/@nodep\s+(\S+)/', $lastphpdoc, $m)) {
                            $nodeps = array_merge($nodeps, $m[1]);
                        }
                    }
                    continue 2;
                case T_DOUBLE_COLON:
                    $token = $tokens[$i - 1][0];
                    if (!($token == T_WHITESPACE || $token == T_STRING || $token == T_STATIC || $token == T_VARIABLE)) {
                        if (isset($this->_stack)) {
                            $this->_stack->push(__FUNCTION__, 'warning', array('file' => $file),
                                'Parser error: invalid PHP found in file "%file%"');
                        } else {
                            PEAR::raiseError("Parser error: invalid PHP found in file \"$file\"",
                                PEAR_COMMON_ERROR_INVALIDPHP);
                        }

                        return false;
                    }

                    $class = $tokens[$i - 1][1];
                    if (strtolower($class) != 'parent') {
                        $used_classes[$class] = true;
                    }

                    continue 2;
            }
        }

        return array(
            "source_file" => $file,
            "declared_classes" => $declared_classes,
            "declared_interfaces" => $declared_interfaces,
            "declared_methods" => $declared_methods,
            "declared_functions" => $declared_functions,
            "used_classes" => array_diff(array_keys($used_classes), $nodeps),
            "inheritance" => $extends,
            "implements" => $implements,
        );
    }

    /**
     * Build a "provides" array from data returned by
     * analyzeSourceCode().  The format of the built array is like
     * this:
     *
     *  array(
     *    'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'),
     *    ...
     *  )
     *
     *
     * @param array $srcinfo array with information about a source file
     * as returned by the analyzeSourceCode() method.
     *
     * @return void
     *
     * @access private
     *
     */
    function _buildProvidesArray($srcinfo)
    {
        if (!$this->_isValid) {
            return array();
        }

        $providesret = array();
        $file        = basename($srcinfo['source_file']);
        $pn          = isset($this->_pf) ? $this->_pf->getPackage() : '';
        $pnl         = strlen($pn);
        foreach ($srcinfo['declared_classes'] as $class) {
            $key = "class;$class";
            if (isset($providesret[$key])) {
                continue;
            }

            $providesret[$key] =
                array('file'=> $file, 'type' => 'class', 'name' => $class);
            if (isset($srcinfo['inheritance'][$class])) {
                $providesret[$key]['extends'] =
                    $srcinfo['inheritance'][$class];
            }
        }

        foreach ($srcinfo['declared_methods'] as $class => $methods) {
            foreach ($methods as $method) {
                $function = "$class::$method";
                $key = "function;$function";
                if ($method[0] == '_' || !strcasecmp($method, $class) ||
                    isset($providesret[$key])) {
                    continue;
                }

                $providesret[$key] =
                    array('file'=> $file, 'type' => 'function', 'name' => $function);
            }
        }

        foreach ($srcinfo['declared_functions'] as $function) {
            $key = "function;$function";
            if ($function[0] == '_' || isset($providesret[$key])) {
                continue;
            }

            if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) {
                $warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\"";
            }

            $providesret[$key] =
                array('file'=> $file, 'type' => 'function', 'name' => $function);
        }

        return $providesret;
    }
}
PKq�Z���=_�_�PEAR/PackageFile/v2/rw.phpnu�[���<?php
/**
 * PEAR_PackageFile_v2, package.xml version 2.0, read/write version
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a8
 */
/**
 * For base class
 */
require_once 'PEAR/PackageFile/v2.php';
/**
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a8
 */
class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
{
    /**
     * @param string Extension name
     * @return bool success of operation
     */
    function setProvidesExtension($extension)
    {
        if (in_array($this->getPackageType(),
              array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) {
            if (!isset($this->_packageInfo['providesextension'])) {
                // ensure that the channel tag is set up in the right location
                $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                    array('usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease',
                    'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
                    'bundle', 'changelog'),
                    $extension, 'providesextension');
            }
            $this->_packageInfo['providesextension'] = $extension;
            return true;
        }
        return false;
    }

    function setPackage($package)
    {
        $this->_isValid = 0;
        if (!isset($this->_packageInfo['attribs'])) {
            $this->_packageInfo = array_merge(array('attribs' => array(
                                 'version' => '2.0',
                                 'xmlns' => 'http://pear.php.net/dtd/package-2.0',
                                 'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0',
                                 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
                                 'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0
    http://pear.php.net/dtd/tasks-1.0.xsd
    http://pear.php.net/dtd/package-2.0
    http://pear.php.net/dtd/package-2.0.xsd',
                             )), $this->_packageInfo);
        }
        if (!isset($this->_packageInfo['name'])) {
            return $this->_packageInfo = array_merge(array('name' => $package),
                $this->_packageInfo);
        }
        $this->_packageInfo['name'] = $package;
    }

    /**
     * set this as a package.xml version 2.1
     * @access private
     */
    function _setPackageVersion2_1()
    {
        $info = array(
                                 'version' => '2.1',
                                 'xmlns' => 'http://pear.php.net/dtd/package-2.1',
                                 'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0',
                                 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
                                 'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0
    http://pear.php.net/dtd/tasks-1.0.xsd
    http://pear.php.net/dtd/package-2.1
    http://pear.php.net/dtd/package-2.1.xsd',
                             );
        if (!isset($this->_packageInfo['attribs'])) {
            $this->_packageInfo = array_merge(array('attribs' => $info), $this->_packageInfo);
        } else {
            $this->_packageInfo['attribs'] = $info;
        }
    }

    function setUri($uri)
    {
        unset($this->_packageInfo['channel']);
        $this->_isValid = 0;
        if (!isset($this->_packageInfo['uri'])) {
            // ensure that the uri tag is set up in the right location
            $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                array('extends', 'summary', 'description', 'lead',
                'developer', 'contributor', 'helper', 'date', 'time', 'version',
                'stability', 'license', 'notes', 'contents', 'compatible',
                'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                'extbinrelease', 'bundle', 'changelog'), $uri, 'uri');
        }
        $this->_packageInfo['uri'] = $uri;
    }

    function setChannel($channel)
    {
        unset($this->_packageInfo['uri']);
        $this->_isValid = 0;
        if (!isset($this->_packageInfo['channel'])) {
            // ensure that the channel tag is set up in the right location
            $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                array('extends', 'summary', 'description', 'lead',
                'developer', 'contributor', 'helper', 'date', 'time', 'version',
                'stability', 'license', 'notes', 'contents', 'compatible',
                'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                'extbinrelease', 'bundle', 'changelog'), $channel, 'channel');
        }
        $this->_packageInfo['channel'] = $channel;
    }

    function setExtends($extends)
    {
        $this->_isValid = 0;
        if (!isset($this->_packageInfo['extends'])) {
            // ensure that the extends tag is set up in the right location
            $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                array('summary', 'description', 'lead',
                'developer', 'contributor', 'helper', 'date', 'time', 'version',
                'stability', 'license', 'notes', 'contents', 'compatible',
                'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                'extbinrelease', 'bundle', 'changelog'), $extends, 'extends');
        }
        $this->_packageInfo['extends'] = $extends;
    }

    function setSummary($summary)
    {
        $this->_isValid = 0;
        if (!isset($this->_packageInfo['summary'])) {
            // ensure that the summary tag is set up in the right location
            $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                array('description', 'lead',
                'developer', 'contributor', 'helper', 'date', 'time', 'version',
                'stability', 'license', 'notes', 'contents', 'compatible',
                'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                'extbinrelease', 'bundle', 'changelog'), $summary, 'summary');
        }
        $this->_packageInfo['summary'] = $summary;
    }

    function setDescription($desc)
    {
        $this->_isValid = 0;
        if (!isset($this->_packageInfo['description'])) {
            // ensure that the description tag is set up in the right location
            $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                array('lead',
                'developer', 'contributor', 'helper', 'date', 'time', 'version',
                'stability', 'license', 'notes', 'contents', 'compatible',
                'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                'extbinrelease', 'bundle', 'changelog'), $desc, 'description');
        }
        $this->_packageInfo['description'] = $desc;
    }

    /**
     * Adds a new maintainer - no checking of duplicates is performed, use
     * updatemaintainer for that purpose.
     */
    function addMaintainer($role, $handle, $name, $email, $active = 'yes')
    {
        if (!in_array($role, array('lead', 'developer', 'contributor', 'helper'))) {
            return false;
        }
        if (isset($this->_packageInfo[$role])) {
            if (!isset($this->_packageInfo[$role][0])) {
                $this->_packageInfo[$role] = array($this->_packageInfo[$role]);
            }
            $this->_packageInfo[$role][] =
                array(
                    'name' => $name,
                    'user' => $handle,
                    'email' => $email,
                    'active' => $active,
                );
        } else {
            $testarr = array('lead',
                    'developer', 'contributor', 'helper', 'date', 'time', 'version',
                    'stability', 'license', 'notes', 'contents', 'compatible',
                    'dependencies', 'providesextension', 'usesrole', 'usestask',
                    'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease',
                    'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog');
            foreach (array('lead', 'developer', 'contributor', 'helper') as $testrole) {
                array_shift($testarr);
                if ($role == $testrole) {
                    break;
                }
            }
            if (!isset($this->_packageInfo[$role])) {
                // ensure that the extends tag is set up in the right location
                $this->_packageInfo = $this->_insertBefore($this->_packageInfo, $testarr,
                    array(), $role);
            }
            $this->_packageInfo[$role] =
                array(
                    'name' => $name,
                    'user' => $handle,
                    'email' => $email,
                    'active' => $active,
                );
        }
        $this->_isValid = 0;
    }

    function updateMaintainer($newrole, $handle, $name, $email, $active = 'yes')
    {
        $found = false;
        foreach (array('lead', 'developer', 'contributor', 'helper') as $role) {
            if (!isset($this->_packageInfo[$role])) {
                continue;
            }
            $info = $this->_packageInfo[$role];
            if (!isset($info[0])) {
                if ($info['user'] == $handle) {
                    $found = true;
                    break;
                }
            }
            foreach ($info as $i => $maintainer) {
                if (is_array($maintainer) && $maintainer['user'] == $handle) {
                    $found = $i;
                    break 2;
                }
            }
        }
        if ($found === false) {
            return $this->addMaintainer($newrole, $handle, $name, $email, $active);
        }
        if ($found !== false) {
            if ($found === true) {
                unset($this->_packageInfo[$role]);
            } else {
                unset($this->_packageInfo[$role][$found]);
                $this->_packageInfo[$role] = array_values($this->_packageInfo[$role]);
            }
        }
        $this->addMaintainer($newrole, $handle, $name, $email, $active);
        $this->_isValid = 0;
    }

    function deleteMaintainer($handle)
    {
        $found = false;
        foreach (array('lead', 'developer', 'contributor', 'helper') as $role) {
            if (!isset($this->_packageInfo[$role])) {
                continue;
            }
            if (!isset($this->_packageInfo[$role][0])) {
                $this->_packageInfo[$role] = array($this->_packageInfo[$role]);
            }
            foreach ($this->_packageInfo[$role] as $i => $maintainer) {
                if ($maintainer['user'] == $handle) {
                    $found = $i;
                    break;
                }
            }
            if ($found !== false) {
                unset($this->_packageInfo[$role][$found]);
                if (!count($this->_packageInfo[$role]) && $role == 'lead') {
                    $this->_isValid = 0;
                }
                if (!count($this->_packageInfo[$role])) {
                    unset($this->_packageInfo[$role]);
                    return true;
                }
                $this->_packageInfo[$role] =
                    array_values($this->_packageInfo[$role]);
                if (count($this->_packageInfo[$role]) == 1) {
                    $this->_packageInfo[$role] = $this->_packageInfo[$role][0];
                }
                return true;
            }
            if (count($this->_packageInfo[$role]) == 1) {
                $this->_packageInfo[$role] = $this->_packageInfo[$role][0];
            }
        }
        return false;
    }

    function setReleaseVersion($version)
    {
        if (isset($this->_packageInfo['version']) &&
              isset($this->_packageInfo['version']['release'])) {
            unset($this->_packageInfo['version']['release']);
        }
        $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $version, array(
            'version' => array('stability', 'license', 'notes', 'contents', 'compatible',
                'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                'extbinrelease', 'bundle', 'changelog'),
            'release' => array('api')));
        $this->_isValid = 0;
    }

    function setAPIVersion($version)
    {
        if (isset($this->_packageInfo['version']) &&
              isset($this->_packageInfo['version']['api'])) {
            unset($this->_packageInfo['version']['api']);
        }
        $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $version, array(
            'version' => array('stability', 'license', 'notes', 'contents', 'compatible',
                'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                'extbinrelease', 'bundle', 'changelog'),
            'api' => array()));
        $this->_isValid = 0;
    }

    /**
     * snapshot|devel|alpha|beta|stable
     */
    function setReleaseStability($state)
    {
        if (isset($this->_packageInfo['stability']) &&
              isset($this->_packageInfo['stability']['release'])) {
            unset($this->_packageInfo['stability']['release']);
        }
        $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $state, array(
            'stability' => array('license', 'notes', 'contents', 'compatible',
                'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                'extbinrelease', 'bundle', 'changelog'),
            'release' => array('api')));
        $this->_isValid = 0;
    }

    /**
     * @param devel|alpha|beta|stable
     */
    function setAPIStability($state)
    {
        if (isset($this->_packageInfo['stability']) &&
              isset($this->_packageInfo['stability']['api'])) {
            unset($this->_packageInfo['stability']['api']);
        }
        $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $state, array(
            'stability' => array('license', 'notes', 'contents', 'compatible',
                'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                'extbinrelease', 'bundle', 'changelog'),
            'api' => array()));
        $this->_isValid = 0;
    }

    function setLicense($license, $uri = false, $filesource = false)
    {
        if (!isset($this->_packageInfo['license'])) {
            // ensure that the license tag is set up in the right location
            $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                array('notes', 'contents', 'compatible',
                'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                'extbinrelease', 'bundle', 'changelog'), 0, 'license');
        }
        if ($uri || $filesource) {
            $attribs = array();
            if ($uri) {
                $attribs['uri'] = $uri;
            }
            $uri = true; // for test below
            if ($filesource) {
                $attribs['filesource'] = $filesource;
            }
        }
        $license = $uri ? array('attribs' => $attribs, '_content' => $license) : $license;
        $this->_packageInfo['license'] = $license;
        $this->_isValid = 0;
    }

    function setNotes($notes)
    {
        $this->_isValid = 0;
        if (!isset($this->_packageInfo['notes'])) {
            // ensure that the notes tag is set up in the right location
            $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                array('contents', 'compatible',
                'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                'extbinrelease', 'bundle', 'changelog'), $notes, 'notes');
        }
        $this->_packageInfo['notes'] = $notes;
    }

    /**
     * This is only used at install-time, after all serialization
     * is over.
     * @param string file name
     * @param string installed path
     */
    function setInstalledAs($file, $path)
    {
        if ($path) {
            return $this->_packageInfo['filelist'][$file]['installed_as'] = $path;
        }
        unset($this->_packageInfo['filelist'][$file]['installed_as']);
    }

    /**
     * This is only used at install-time, after all serialization
     * is over.
     */
    function installedFile($file, $atts)
    {
        if (isset($this->_packageInfo['filelist'][$file])) {
            $this->_packageInfo['filelist'][$file] =
                array_merge($this->_packageInfo['filelist'][$file], $atts['attribs']);
        } else {
            $this->_packageInfo['filelist'][$file] = $atts['attribs'];
        }
    }

    /**
     * Reset the listing of package contents
     * @param string base installation dir for the whole package, if any
     */
    function clearContents($baseinstall = false)
    {
        $this->_filesValid = false;
        $this->_isValid = 0;
        if (!isset($this->_packageInfo['contents'])) {
            $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                array('compatible',
                    'dependencies', 'providesextension', 'usesrole', 'usestask',
                    'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease',
                    'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
                    'bundle', 'changelog'), array(), 'contents');
        }
        if ($this->getPackageType() != 'bundle') {
            $this->_packageInfo['contents'] =
                array('dir' => array('attribs' => array('name' => '/')));
            if ($baseinstall) {
                $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'] = $baseinstall;
            }
        } else {
            $this->_packageInfo['contents'] = array('bundledpackage' => array());
        }
    }

    /**
     * @param string relative path of the bundled package.
     */
    function addBundledPackage($path)
    {
        if ($this->getPackageType() != 'bundle') {
            return false;
        }
        $this->_filesValid = false;
        $this->_isValid = 0;
        $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $path, array(
                'contents' => array('compatible', 'dependencies', 'providesextension',
                'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease',
                'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
                'bundle', 'changelog'),
                'bundledpackage' => array()));
    }

    /**
     * @param string file name
     * @param PEAR_Task_Common a read/write task
     */
    function addTaskToFile($filename, $task)
    {
        if (!method_exists($task, 'getXml')) {
            return false;
        }
        if (!method_exists($task, 'getName')) {
            return false;
        }
        if (!method_exists($task, 'validate')) {
            return false;
        }
        if (!$task->validate()) {
            return false;
        }
        if (!isset($this->_packageInfo['contents']['dir']['file'])) {
            return false;
        }
        $this->getTasksNs(); // discover the tasks namespace if not done already
        $files = $this->_packageInfo['contents']['dir']['file'];
        if (!isset($files[0])) {
            $files = array($files);
            $ind = false;
        } else {
            $ind = true;
        }
        foreach ($files as $i => $file) {
            if (isset($file['attribs'])) {
                if ($file['attribs']['name'] == $filename) {
                    if ($ind) {
                        $t = isset($this->_packageInfo['contents']['dir']['file'][$i]
                              ['attribs'][$this->_tasksNs .
                              ':' . $task->getName()]) ?
                              $this->_packageInfo['contents']['dir']['file'][$i]
                              ['attribs'][$this->_tasksNs .
                              ':' . $task->getName()] : false;
                        if ($t && !isset($t[0])) {
                            $this->_packageInfo['contents']['dir']['file'][$i]
                                [$this->_tasksNs . ':' . $task->getName()] = array($t);
                        }
                        $this->_packageInfo['contents']['dir']['file'][$i][$this->_tasksNs .
                            ':' . $task->getName()][] = $task->getXml();
                    } else {
                        $t = isset($this->_packageInfo['contents']['dir']['file']
                              ['attribs'][$this->_tasksNs .
                              ':' . $task->getName()]) ? $this->_packageInfo['contents']['dir']['file']
                              ['attribs'][$this->_tasksNs .
                              ':' . $task->getName()] : false;
                        if ($t && !isset($t[0])) {
                            $this->_packageInfo['contents']['dir']['file']
                                [$this->_tasksNs . ':' . $task->getName()] = array($t);
                        }
                        $this->_packageInfo['contents']['dir']['file'][$this->_tasksNs .
                            ':' . $task->getName()][] = $task->getXml();
                    }
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * @param string path to the file
     * @param string filename
     * @param array extra attributes
     */
    function addFile($dir, $file, $attrs)
    {
        if ($this->getPackageType() == 'bundle') {
            return false;
        }
        $this->_filesValid = false;
        $this->_isValid = 0;
        $dir = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), $dir);
        if ($dir == '/' || $dir == '') {
            $dir = '';
        } else {
            $dir .= '/';
        }
        $attrs['name'] = $dir . $file;
        if (!isset($this->_packageInfo['contents'])) {
            // ensure that the contents tag is set up
            $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                array('compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask',
                'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease',
                'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
                'bundle', 'changelog'), array(), 'contents');
        }
        if (isset($this->_packageInfo['contents']['dir']['file'])) {
            if (!isset($this->_packageInfo['contents']['dir']['file'][0])) {
                $this->_packageInfo['contents']['dir']['file'] =
                    array($this->_packageInfo['contents']['dir']['file']);
            }
            $this->_packageInfo['contents']['dir']['file'][]['attribs'] = $attrs;
        } else {
            $this->_packageInfo['contents']['dir']['file']['attribs'] = $attrs;
        }
    }

    /**
     * @param string Dependent package name
     * @param string Dependent package's channel name
     * @param string minimum version of specified package that this release is guaranteed to be
     *               compatible with
     * @param string maximum version of specified package that this release is guaranteed to be
     *               compatible with
     * @param string versions of specified package that this release is not compatible with
     */
    function addCompatiblePackage($name, $channel, $min, $max, $exclude = false)
    {
        $this->_isValid = 0;
        $set = array(
            'name' => $name,
            'channel' => $channel,
            'min' => $min,
            'max' => $max,
        );
        if ($exclude) {
            $set['exclude'] = $exclude;
        }
        $this->_isValid = 0;
        $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array(
                'compatible' => array('dependencies', 'providesextension', 'usesrole', 'usestask',
                    'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                    'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')
            ));
    }

    /**
     * Removes the <usesrole> tag entirely
     */
    function resetUsesrole()
    {
        if (isset($this->_packageInfo['usesrole'])) {
            unset($this->_packageInfo['usesrole']);
        }
    }

    /**
     * @param string
     * @param string package name or uri
     * @param string channel name if non-uri
     */
    function addUsesrole($role, $packageOrUri, $channel = false) {
        $set = array('role' => $role);
        if ($channel) {
            $set['package'] = $packageOrUri;
            $set['channel'] = $channel;
        } else {
            $set['uri'] = $packageOrUri;
        }
        $this->_isValid = 0;
        $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array(
                'usesrole' => array('usestask', 'srcpackage', 'srcuri',
                    'phprelease', 'extsrcrelease', 'extbinrelease',
                    'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')
            ));
    }

    /**
     * Removes the <usestask> tag entirely
     */
    function resetUsestask()
    {
        if (isset($this->_packageInfo['usestask'])) {
            unset($this->_packageInfo['usestask']);
        }
    }


    /**
     * @param string
     * @param string package name or uri
     * @param string channel name if non-uri
     */
    function addUsestask($task, $packageOrUri, $channel = false) {
        $set = array('task' => $task);
        if ($channel) {
            $set['package'] = $packageOrUri;
            $set['channel'] = $channel;
        } else {
            $set['uri'] = $packageOrUri;
        }
        $this->_isValid = 0;
        $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array(
                'usestask' => array('srcpackage', 'srcuri',
                    'phprelease', 'extsrcrelease', 'extbinrelease',
                    'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')
            ));
    }

    /**
     * Remove all compatible tags
     */
    function clearCompatible()
    {
        unset($this->_packageInfo['compatible']);
    }

    /**
     * Reset dependencies prior to adding new ones
     */
    function clearDeps()
    {
        if (!isset($this->_packageInfo['dependencies'])) {
            $this->_packageInfo = $this->_mergeTag($this->_packageInfo, array(),
                array(
                    'dependencies' => array('providesextension', 'usesrole', 'usestask',
                        'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                        'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')));
        }
        $this->_packageInfo['dependencies'] = array();
    }

    /**
     * @param string minimum PHP version allowed
     * @param string maximum PHP version allowed
     * @param array $exclude incompatible PHP versions
     */
    function setPhpDep($min, $max = false, $exclude = false)
    {
        $this->_isValid = 0;
        $dep =
            array(
                'min' => $min,
            );
        if ($max) {
            $dep['max'] = $max;
        }
        if ($exclude) {
            if (count($exclude) == 1) {
                $exclude = $exclude[0];
            }
            $dep['exclude'] = $exclude;
        }
        if (isset($this->_packageInfo['dependencies']['required']['php'])) {
            $this->_stack->push(__FUNCTION__, 'warning', array('dep' =>
            $this->_packageInfo['dependencies']['required']['php']),
                'warning: PHP dependency already exists, overwriting');
            unset($this->_packageInfo['dependencies']['required']['php']);
        }
        $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
            array(
                'dependencies' => array('providesextension', 'usesrole', 'usestask',
                    'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                    'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                'required' => array('optional', 'group'),
                'php' => array('pearinstaller', 'package', 'subpackage', 'extension', 'os', 'arch')
            ));
        return true;
    }

    /**
     * @param string minimum allowed PEAR installer version
     * @param string maximum allowed PEAR installer version
     * @param string recommended PEAR installer version
     * @param array incompatible version of the PEAR installer
     */
    function setPearinstallerDep($min, $max = false, $recommended = false, $exclude = false)
    {
        $this->_isValid = 0;
        $dep =
            array(
                'min' => $min,
            );
        if ($max) {
            $dep['max'] = $max;
        }
        if ($recommended) {
            $dep['recommended'] = $recommended;
        }
        if ($exclude) {
            if (count($exclude) == 1) {
                $exclude = $exclude[0];
            }
            $dep['exclude'] = $exclude;
        }
        if (isset($this->_packageInfo['dependencies']['required']['pearinstaller'])) {
            $this->_stack->push(__FUNCTION__, 'warning', array('dep' =>
            $this->_packageInfo['dependencies']['required']['pearinstaller']),
                'warning: PEAR Installer dependency already exists, overwriting');
            unset($this->_packageInfo['dependencies']['required']['pearinstaller']);
        }
        $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
            array(
                'dependencies' => array('providesextension', 'usesrole', 'usestask',
                    'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                    'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                'required' => array('optional', 'group'),
                'pearinstaller' => array('package', 'subpackage', 'extension', 'os', 'arch')
            ));
    }

    /**
     * Mark a package as conflicting with this package
     * @param string package name
     * @param string package channel
     * @param string extension this package provides, if any
     * @param string|false minimum version required
     * @param string|false maximum version allowed
     * @param array|false versions to exclude from installation
     */
    function addConflictingPackageDepWithChannel($name, $channel,
                $providesextension = false, $min = false, $max = false, $exclude = false)
    {
        $this->_isValid = 0;
        $dep = $this->_constructDep($name, $channel, false, $min, $max, false,
            $exclude, $providesextension, false, true);
        $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
            array(
                'dependencies' => array('providesextension', 'usesrole', 'usestask',
                    'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                    'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                'required' => array('optional', 'group'),
                'package' => array('subpackage', 'extension', 'os', 'arch')
            ));
    }

    /**
     * Mark a package as conflicting with this package
     * @param string package name
     * @param string package channel
     * @param string extension this package provides, if any
     */
    function addConflictingPackageDepWithUri($name, $uri, $providesextension = false)
    {
        $this->_isValid = 0;
        $dep =
            array(
                'name' => $name,
                'uri' => $uri,
                'conflicts' => '',
            );
        if ($providesextension) {
            $dep['providesextension'] = $providesextension;
        }
        $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
            array(
                'dependencies' => array('providesextension', 'usesrole', 'usestask',
                    'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                    'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                'required' => array('optional', 'group'),
                'package' => array('subpackage', 'extension', 'os', 'arch')
            ));
    }

    function addDependencyGroup($name, $hint)
    {
        $this->_isValid = 0;
        $this->_packageInfo = $this->_mergeTag($this->_packageInfo,
            array('attribs' => array('name' => $name, 'hint' => $hint)),
            array(
                'dependencies' => array('providesextension', 'usesrole', 'usestask',
                    'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                    'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                'group' => array(),
            ));
    }

    /**
     * @param string package name
     * @param string|false channel name, false if this is a uri
     * @param string|false uri name, false if this is a channel
     * @param string|false minimum version required
     * @param string|false maximum version allowed
     * @param string|false recommended installation version
     * @param array|false versions to exclude from installation
     * @param string extension this package provides, if any
     * @param bool if true, tells the installer to ignore the default optional dependency group
     *             when installing this package
     * @param bool if true, tells the installer to negate this dependency (conflicts)
     * @return array
     * @access private
     */
    function _constructDep($name, $channel, $uri, $min, $max, $recommended, $exclude,
                           $providesextension = false, $nodefault = false,
                           $conflicts = false)
    {
        $dep =
            array(
                'name' => $name,
            );
        if ($channel) {
            $dep['channel'] = $channel;
        } elseif ($uri) {
            $dep['uri'] = $uri;
        }
        if ($min) {
            $dep['min'] = $min;
        }
        if ($max) {
            $dep['max'] = $max;
        }
        if ($recommended) {
            $dep['recommended'] = $recommended;
        }
        if ($exclude) {
            if (is_array($exclude) && count($exclude) == 1) {
                $exclude = $exclude[0];
            }
            $dep['exclude'] = $exclude;
        }
        if ($conflicts) {
            $dep['conflicts'] = '';
        }
        if ($nodefault) {
            $dep['nodefault'] = '';
        }
        if ($providesextension) {
            $dep['providesextension'] = $providesextension;
        }
        return $dep;
    }

    /**
     * @param package|subpackage
     * @param string group name
     * @param string package name
     * @param string package channel
     * @param string minimum version
     * @param string maximum version
     * @param string recommended version
     * @param array|false optional excluded versions
     * @param string extension this package provides, if any
     * @param bool if true, tells the installer to ignore the default optional dependency group
     *             when installing this package
     * @return bool false if the dependency group has not been initialized with
     *              {@link addDependencyGroup()}, or a subpackage is added with
     *              a providesextension
     */
    function addGroupPackageDepWithChannel($type, $groupname, $name, $channel, $min = false,
                                      $max = false, $recommended = false, $exclude = false,
                                      $providesextension = false, $nodefault = false)
    {
        if ($type == 'subpackage' && $providesextension) {
            return false; // subpackages must be php packages
        }
        $dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude,
            $providesextension, $nodefault);
        return $this->_addGroupDependency($type, $dep, $groupname);
    }

    /**
     * @param package|subpackage
     * @param string group name
     * @param string package name
     * @param string package uri
     * @param string extension this package provides, if any
     * @param bool if true, tells the installer to ignore the default optional dependency group
     *             when installing this package
     * @return bool false if the dependency group has not been initialized with
     *              {@link addDependencyGroup()}
     */
    function addGroupPackageDepWithURI($type, $groupname, $name, $uri, $providesextension = false,
                                       $nodefault = false)
    {
        if ($type == 'subpackage' && $providesextension) {
            return false; // subpackages must be php packages
        }
        $dep = $this->_constructDep($name, false, $uri, false, false, false, false,
            $providesextension, $nodefault);
        return $this->_addGroupDependency($type, $dep, $groupname);
    }

    /**
     * @param string group name (must be pre-existing)
     * @param string extension name
     * @param string minimum version allowed
     * @param string maximum version allowed
     * @param string recommended version
     * @param array incompatible versions
     */
    function addGroupExtensionDep($groupname, $name, $min = false, $max = false,
                                         $recommended = false, $exclude = false)
    {
        $this->_isValid = 0;
        $dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude);
        return $this->_addGroupDependency('extension', $dep, $groupname);
    }

    /**
     * @param package|subpackage|extension
     * @param array dependency contents
     * @param string name of the dependency group to add this to
     * @return boolean
     * @access private
     */
    function _addGroupDependency($type, $dep, $groupname)
    {
        $arr = array('subpackage', 'extension');
        if ($type != 'package') {
            array_shift($arr);
        }
        if ($type == 'extension') {
            array_shift($arr);
        }
        if (!isset($this->_packageInfo['dependencies']['group'])) {
            return false;
        } else {
            if (!isset($this->_packageInfo['dependencies']['group'][0])) {
                if ($this->_packageInfo['dependencies']['group']['attribs']['name'] == $groupname) {
                    $this->_packageInfo['dependencies']['group'] = $this->_mergeTag(
                        $this->_packageInfo['dependencies']['group'], $dep,
                        array(
                            $type => $arr
                        ));
                    $this->_isValid = 0;
                    return true;
                } else {
                    return false;
                }
            } else {
                foreach ($this->_packageInfo['dependencies']['group'] as $i => $group) {
                    if ($group['attribs']['name'] == $groupname) {
                    $this->_packageInfo['dependencies']['group'][$i] = $this->_mergeTag(
                        $this->_packageInfo['dependencies']['group'][$i], $dep,
                        array(
                            $type => $arr
                        ));
                        $this->_isValid = 0;
                        return true;
                    }
                }
                return false;
            }
        }
    }

    /**
     * @param optional|required
     * @param string package name
     * @param string package channel
     * @param string minimum version
     * @param string maximum version
     * @param string recommended version
     * @param string extension this package provides, if any
     * @param bool if true, tells the installer to ignore the default optional dependency group
     *             when installing this package
     * @param array|false optional excluded versions
     */
    function addPackageDepWithChannel($type, $name, $channel, $min = false, $max = false,
                                      $recommended = false, $exclude = false,
                                      $providesextension = false, $nodefault = false)
    {
        if (!in_array($type, array('optional', 'required'), true)) {
            $type = 'required';
        }
        $this->_isValid = 0;
        $arr = array('optional', 'group');
        if ($type != 'required') {
            array_shift($arr);
        }
        $dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude,
            $providesextension, $nodefault);
        $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
            array(
                'dependencies' => array('providesextension', 'usesrole', 'usestask',
                    'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                    'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                $type => $arr,
                'package' => array('subpackage', 'extension', 'os', 'arch')
            ));
    }

    /**
     * @param optional|required
     * @param string name of the package
     * @param string uri of the package
     * @param string extension this package provides, if any
     * @param bool if true, tells the installer to ignore the default optional dependency group
     *             when installing this package
     */
    function addPackageDepWithUri($type, $name, $uri, $providesextension = false,
                                  $nodefault = false)
    {
        $this->_isValid = 0;
        $arr = array('optional', 'group');
        if ($type != 'required') {
            array_shift($arr);
        }
        $dep = $this->_constructDep($name, false, $uri, false, false, false, false,
            $providesextension, $nodefault);
        $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
            array(
                'dependencies' => array('providesextension', 'usesrole', 'usestask',
                    'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                    'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                $type => $arr,
                'package' => array('subpackage', 'extension', 'os', 'arch')
            ));
    }

    /**
     * @param optional|required optional, required
     * @param string package name
     * @param string package channel
     * @param string minimum version
     * @param string maximum version
     * @param string recommended version
     * @param array incompatible versions
     * @param bool if true, tells the installer to ignore the default optional dependency group
     *             when installing this package
     */
    function addSubpackageDepWithChannel($type, $name, $channel, $min = false, $max = false,
                                         $recommended = false, $exclude = false,
                                         $nodefault = false)
    {
        $this->_isValid = 0;
        $arr = array('optional', 'group');
        if ($type != 'required') {
            array_shift($arr);
        }
        $dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude,
            $nodefault);
        $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
            array(
                'dependencies' => array('providesextension', 'usesrole', 'usestask',
                    'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                    'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                $type => $arr,
                'subpackage' => array('extension', 'os', 'arch')
            ));
    }

    /**
     * @param optional|required optional, required
     * @param string package name
     * @param string package uri for download
     * @param bool if true, tells the installer to ignore the default optional dependency group
     *             when installing this package
     */
    function addSubpackageDepWithUri($type, $name, $uri, $nodefault = false)
    {
        $this->_isValid = 0;
        $arr = array('optional', 'group');
        if ($type != 'required') {
            array_shift($arr);
        }
        $dep = $this->_constructDep($name, false, $uri, false, false, false, false, $nodefault);
        $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
            array(
                'dependencies' => array('providesextension', 'usesrole', 'usestask',
                    'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                    'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                $type => $arr,
                'subpackage' => array('extension', 'os', 'arch')
            ));
    }

    /**
     * @param optional|required optional, required
     * @param string extension name
     * @param string minimum version
     * @param string maximum version
     * @param string recommended version
     * @param array incompatible versions
     */
    function addExtensionDep($type, $name, $min = false, $max = false, $recommended = false,
                             $exclude = false)
    {
        $this->_isValid = 0;
        $arr = array('optional', 'group');
        if ($type != 'required') {
            array_shift($arr);
        }
        $dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude);
        $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
            array(
                'dependencies' => array('providesextension', 'usesrole', 'usestask',
                    'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                    'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                $type => $arr,
                'extension' => array('os', 'arch')
            ));
    }

    /**
     * @param string Operating system name
     * @param boolean true if this package cannot be installed on this OS
     */
    function addOsDep($name, $conflicts = false)
    {
        $this->_isValid = 0;
        $dep = array('name' => $name);
        if ($conflicts) {
            $dep['conflicts'] = '';
        }
        $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
            array(
                'dependencies' => array('providesextension', 'usesrole', 'usestask',
                    'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                    'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                'required' => array('optional', 'group'),
                'os' => array('arch')
            ));
    }

    /**
     * @param string Architecture matching pattern
     * @param boolean true if this package cannot be installed on this architecture
     */
    function addArchDep($pattern, $conflicts = false)
    {
        $this->_isValid = 0;
        $dep = array('pattern' => $pattern);
        if ($conflicts) {
            $dep['conflicts'] = '';
        }
        $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
            array(
                'dependencies' => array('providesextension', 'usesrole', 'usestask',
                    'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                    'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                'required' => array('optional', 'group'),
                'arch' => array()
            ));
    }

    /**
     * Set the kind of package, and erase all release tags
     *
     * - a php package is a PEAR-style package
     * - an extbin package is a PECL-style extension binary
     * - an extsrc package is a PECL-style source for a binary
     * - an zendextbin package is a PECL-style zend extension binary
     * - an zendextsrc package is a PECL-style source for a zend extension binary
     * - a bundle package is a collection of other pre-packaged packages
     * @param php|extbin|extsrc|zendextsrc|zendextbin|bundle
     * @return bool success
     */
    function setPackageType($type)
    {
        $this->_isValid = 0;
        if (!in_array($type, array('php', 'extbin', 'extsrc', 'zendextsrc',
                                   'zendextbin', 'bundle'))) {
            return false;
        }

        if (in_array($type, array('zendextsrc', 'zendextbin'))) {
            $this->_setPackageVersion2_1();
        }

        if ($type != 'bundle') {
            $type .= 'release';
        }

        foreach (array('phprelease', 'extbinrelease', 'extsrcrelease',
                       'zendextsrcrelease', 'zendextbinrelease', 'bundle') as $test) {
            unset($this->_packageInfo[$test]);
        }

        if (!isset($this->_packageInfo[$type])) {
            // ensure that the release tag is set up
            $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('changelog'),
                array(), $type);
        }

        $this->_packageInfo[$type] = array();
        return true;
    }

    /**
     * @return bool true if package type is set up
     */
    function addRelease()
    {
        if ($type = $this->getPackageType()) {
            if ($type != 'bundle') {
                $type .= 'release';
            }
            $this->_packageInfo = $this->_mergeTag($this->_packageInfo, array(),
                array($type => array('changelog')));
            return true;
        }
        return false;
    }

    /**
     * Get the current release tag in order to add to it
     * @param bool returns only releases that have installcondition if true
     * @return array|null
     */
    function &_getCurrentRelease($strict = true)
    {
        if ($p = $this->getPackageType()) {
            if ($strict) {
                if ($p == 'extsrc' || $p == 'zendextsrc') {
                    $a = null;
                    return $a;
                }
            }
            if ($p != 'bundle') {
                $p .= 'release';
            }
            if (isset($this->_packageInfo[$p][0])) {
                return $this->_packageInfo[$p][count($this->_packageInfo[$p]) - 1];
            } else {
                return $this->_packageInfo[$p];
            }
        } else {
            $a = null;
            return $a;
        }
    }

    /**
     * Add a file to the current release that should be installed under a different name
     * @param string <contents> path to file
     * @param string name the file should be installed as
     */
    function addInstallAs($path, $as)
    {
        $r = &$this->_getCurrentRelease();
        if ($r === null) {
            return false;
        }
        $this->_isValid = 0;
        $r = $this->_mergeTag($r, array('attribs' => array('name' => $path, 'as' => $as)),
            array(
                'filelist' => array(),
                'install' => array('ignore')
            ));
    }

    /**
     * Add a file to the current release that should be ignored
     * @param string <contents> path to file
     * @return bool success of operation
     */
    function addIgnore($path)
    {
        $r = &$this->_getCurrentRelease();
        if ($r === null) {
            return false;
        }
        $this->_isValid = 0;
        $r = $this->_mergeTag($r, array('attribs' => array('name' => $path)),
            array(
                'filelist' => array(),
                'ignore' => array()
            ));
    }

    /**
     * Add an extension binary package for this extension source code release
     *
     * Note that the package must be from the same channel as the extension source package
     * @param string
     */
    function addBinarypackage($package)
    {
        if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') {
            return false;
        }
        $r = &$this->_getCurrentRelease(false);
        if ($r === null) {
            return false;
        }
        $this->_isValid = 0;
        $r = $this->_mergeTag($r, $package,
            array(
                'binarypackage' => array('filelist'),
            ));
    }

    /**
     * Add a configureoption to an extension source package
     * @param string
     * @param string
     * @param string
     */
    function addConfigureOption($name, $prompt, $default = null)
    {
        if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') {
            return false;
        }

        $r = &$this->_getCurrentRelease(false);
        if ($r === null) {
            return false;
        }

        $opt = array('attribs' => array('name' => $name, 'prompt' => $prompt));
        if ($default !== null) {
            $opt['attribs']['default'] = $default;
        }

        $this->_isValid = 0;
        $r = $this->_mergeTag($r, $opt,
            array(
                'configureoption' => array('binarypackage', 'filelist'),
            ));
    }

    /**
     * Set an installation condition based on php version for the current release set
     * @param string minimum version
     * @param string maximum version
     * @param false|array incompatible versions of PHP
     */
    function setPhpInstallCondition($min, $max, $exclude = false)
    {
        $r = &$this->_getCurrentRelease();
        if ($r === null) {
            return false;
        }
        $this->_isValid = 0;
        if (isset($r['installconditions']['php'])) {
            unset($r['installconditions']['php']);
        }
        $dep = array('min' => $min, 'max' => $max);
        if ($exclude) {
            if (is_array($exclude) && count($exclude) == 1) {
                $exclude = $exclude[0];
            }
            $dep['exclude'] = $exclude;
        }
        if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
            $r = $this->_mergeTag($r, $dep,
                array(
                    'installconditions' => array('configureoption', 'binarypackage',
                        'filelist'),
                    'php' => array('extension', 'os', 'arch')
                ));
        } else {
            $r = $this->_mergeTag($r, $dep,
                array(
                    'installconditions' => array('filelist'),
                    'php' => array('extension', 'os', 'arch')
                ));
        }
    }

    /**
     * @param optional|required optional, required
     * @param string extension name
     * @param string minimum version
     * @param string maximum version
     * @param string recommended version
     * @param array incompatible versions
     */
    function addExtensionInstallCondition($name, $min = false, $max = false, $recommended = false,
                                          $exclude = false)
    {
        $r = &$this->_getCurrentRelease();
        if ($r === null) {
            return false;
        }
        $this->_isValid = 0;
        $dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude);
        if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
            $r = $this->_mergeTag($r, $dep,
                array(
                    'installconditions' => array('configureoption', 'binarypackage',
                        'filelist'),
                    'extension' => array('os', 'arch')
                ));
        } else {
            $r = $this->_mergeTag($r, $dep,
                array(
                    'installconditions' => array('filelist'),
                    'extension' => array('os', 'arch')
                ));
        }
    }

    /**
     * Set an installation condition based on operating system for the current release set
     * @param string OS name
     * @param bool whether this OS is incompatible with the current release
     */
    function setOsInstallCondition($name, $conflicts = false)
    {
        $r = &$this->_getCurrentRelease();
        if ($r === null) {
            return false;
        }
        $this->_isValid = 0;
        if (isset($r['installconditions']['os'])) {
            unset($r['installconditions']['os']);
        }
        $dep = array('name' => $name);
        if ($conflicts) {
            $dep['conflicts'] = '';
        }
        if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
            $r = $this->_mergeTag($r, $dep,
                array(
                    'installconditions' => array('configureoption', 'binarypackage',
                        'filelist'),
                    'os' => array('arch')
                ));
        } else {
            $r = $this->_mergeTag($r, $dep,
                array(
                    'installconditions' => array('filelist'),
                    'os' => array('arch')
                ));
        }
    }

    /**
     * Set an installation condition based on architecture for the current release set
     * @param string architecture pattern
     * @param bool whether this arch is incompatible with the current release
     */
    function setArchInstallCondition($pattern, $conflicts = false)
    {
        $r = &$this->_getCurrentRelease();
        if ($r === null) {
            return false;
        }
        $this->_isValid = 0;
        if (isset($r['installconditions']['arch'])) {
            unset($r['installconditions']['arch']);
        }
        $dep = array('pattern' => $pattern);
        if ($conflicts) {
            $dep['conflicts'] = '';
        }
        if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
            $r = $this->_mergeTag($r, $dep,
                array(
                    'installconditions' => array('configureoption', 'binarypackage',
                        'filelist'),
                    'arch' => array()
                ));
        } else {
            $r = $this->_mergeTag($r, $dep,
                array(
                    'installconditions' => array('filelist'),
                    'arch' => array()
                ));
        }
    }

    /**
     * For extension binary releases, this is used to specify either the
     * static URI to a source package, or the package name and channel of the extsrc/zendextsrc
     * package it is based on.
     * @param string Package name, or full URI to source package (extsrc/zendextsrc type)
     */
    function setSourcePackage($packageOrUri)
    {
        $this->_isValid = 0;
        if (isset($this->_packageInfo['channel'])) {
            $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('phprelease',
                'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
                'bundle', 'changelog'),
                $packageOrUri, 'srcpackage');
        } else {
            $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('phprelease',
                'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
                'bundle', 'changelog'), $packageOrUri, 'srcuri');
        }
    }

    /**
     * Generate a valid change log entry from the current package.xml
     * @param string|false
     */
    function generateChangeLogEntry($notes = false)
    {
        return array(
            'version' =>
                array(
                    'release' => $this->getVersion('release'),
                    'api' => $this->getVersion('api'),
                    ),
            'stability' =>
                $this->getStability(),
            'date' => $this->getDate(),
            'license' => $this->getLicense(true),
            'notes' => $notes ? $notes : $this->getNotes()
            );
    }

    /**
     * @param string release version to set change log notes for
     * @param array output of {@link generateChangeLogEntry()}
     */
    function setChangelogEntry($releaseversion, $contents)
    {
        if (!isset($this->_packageInfo['changelog'])) {
            $this->_packageInfo['changelog']['release'] = $contents;
            return;
        }
        if (!isset($this->_packageInfo['changelog']['release'][0])) {
            if ($this->_packageInfo['changelog']['release']['version']['release'] == $releaseversion) {
                $this->_packageInfo['changelog']['release'] = array(
                    $this->_packageInfo['changelog']['release']);
            } else {
                $this->_packageInfo['changelog']['release'] = array(
                    $this->_packageInfo['changelog']['release']);
                return $this->_packageInfo['changelog']['release'][] = $contents;
            }
        }
        foreach($this->_packageInfo['changelog']['release'] as $index => $changelog) {
            if (isset($changelog['version']) &&
                  strnatcasecmp($changelog['version']['release'], $releaseversion) == 0) {
                $curlog = $index;
            }
        }
        if (isset($curlog)) {
            $this->_packageInfo['changelog']['release'][$curlog] = $contents;
        } else {
            $this->_packageInfo['changelog']['release'][] = $contents;
        }
    }

    /**
     * Remove the changelog entirely
     */
    function clearChangeLog()
    {
        unset($this->_packageInfo['changelog']);
    }
}PKq�Z�5������PEAR/PackageFile/v1.phpnu�[���<?php
/**
 * PEAR_PackageFile_v1, package.xml version 1.0
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a1
 */
/**
 * For error handling
 */
require_once 'PEAR/ErrorStack.php';

/**
 * Error code if parsing is attempted with no xml extension
 */
define('PEAR_PACKAGEFILE_ERROR_NO_XML_EXT', 3);

/**
 * Error code if creating the xml parser resource fails
 */
define('PEAR_PACKAGEFILE_ERROR_CANT_MAKE_PARSER', 4);

/**
 * Error code used for all sax xml parsing errors
 */
define('PEAR_PACKAGEFILE_ERROR_PARSER_ERROR', 5);

/**
 * Error code used when there is no name
 */
define('PEAR_PACKAGEFILE_ERROR_NO_NAME', 6);

/**
 * Error code when a package name is not valid
 */
define('PEAR_PACKAGEFILE_ERROR_INVALID_NAME', 7);

/**
 * Error code used when no summary is parsed
 */
define('PEAR_PACKAGEFILE_ERROR_NO_SUMMARY', 8);

/**
 * Error code for summaries that are more than 1 line
 */
define('PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY', 9);

/**
 * Error code used when no description is present
 */
define('PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION', 10);

/**
 * Error code used when no license is present
 */
define('PEAR_PACKAGEFILE_ERROR_NO_LICENSE', 11);

/**
 * Error code used when a <version> version number is not present
 */
define('PEAR_PACKAGEFILE_ERROR_NO_VERSION', 12);

/**
 * Error code used when a <version> version number is invalid
 */
define('PEAR_PACKAGEFILE_ERROR_INVALID_VERSION', 13);

/**
 * Error code when release state is missing
 */
define('PEAR_PACKAGEFILE_ERROR_NO_STATE', 14);

/**
 * Error code when release state is invalid
 */
define('PEAR_PACKAGEFILE_ERROR_INVALID_STATE', 15);

/**
 * Error code when release state is missing
 */
define('PEAR_PACKAGEFILE_ERROR_NO_DATE', 16);

/**
 * Error code when release state is invalid
 */
define('PEAR_PACKAGEFILE_ERROR_INVALID_DATE', 17);

/**
 * Error code when no release notes are found
 */
define('PEAR_PACKAGEFILE_ERROR_NO_NOTES', 18);

/**
 * Error code when no maintainers are found
 */
define('PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS', 19);

/**
 * Error code when a maintainer has no handle
 */
define('PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE', 20);

/**
 * Error code when a maintainer has no handle
 */
define('PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE', 21);

/**
 * Error code when a maintainer has no name
 */
define('PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME', 22);

/**
 * Error code when a maintainer has no email
 */
define('PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL', 23);

/**
 * Error code when a maintainer has no handle
 */
define('PEAR_PACKAGEFILE_ERROR_INVALID_MAINTROLE', 24);

/**
 * Error code when a dependency is not a PHP dependency, but has no name
 */
define('PEAR_PACKAGEFILE_ERROR_NO_DEPNAME', 25);

/**
 * Error code when a dependency has no type (pkg, php, etc.)
 */
define('PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE', 26);

/**
 * Error code when a dependency has no relation (lt, ge, has, etc.)
 */
define('PEAR_PACKAGEFILE_ERROR_NO_DEPREL', 27);

/**
 * Error code when a dependency is not a 'has' relation, but has no version
 */
define('PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION', 28);

/**
 * Error code when a dependency has an invalid relation
 */
define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPREL', 29);

/**
 * Error code when a dependency has an invalid type
 */
define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPTYPE', 30);

/**
 * Error code when a dependency has an invalid optional option
 */
define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL', 31);

/**
 * Error code when a dependency is a pkg dependency, and has an invalid package name
 */
define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPNAME', 32);

/**
 * Error code when a dependency has a channel="foo" attribute, and foo is not a registered channel
 */
define('PEAR_PACKAGEFILE_ERROR_UNKNOWN_DEPCHANNEL', 33);

/**
 * Error code when rel="has" and version attribute is present.
 */
define('PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED', 34);

/**
 * Error code when type="php" and dependency name is present
 */
define('PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED', 35);

/**
 * Error code when a configure option has no name
 */
define('PEAR_PACKAGEFILE_ERROR_NO_CONFNAME', 36);

/**
 * Error code when a configure option has no name
 */
define('PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT', 37);

/**
 * Error code when a file in the filelist has an invalid role
 */
define('PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE', 38);

/**
 * Error code when a file in the filelist has no role
 */
define('PEAR_PACKAGEFILE_ERROR_NO_FILEROLE', 39);

/**
 * Error code when analyzing a php source file that has parse errors
 */
define('PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE', 40);

/**
 * Error code when analyzing a php source file reveals a source element
 * without a package name prefix
 */
define('PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX', 41);

/**
 * Error code when an unknown channel is specified
 */
define('PEAR_PACKAGEFILE_ERROR_UNKNOWN_CHANNEL', 42);

/**
 * Error code when no files are found in the filelist
 */
define('PEAR_PACKAGEFILE_ERROR_NO_FILES', 43);

/**
 * Error code when a file is not valid php according to _analyzeSourceCode()
 */
define('PEAR_PACKAGEFILE_ERROR_INVALID_FILE', 44);

/**
 * Error code when the channel validator returns an error or warning
 */
define('PEAR_PACKAGEFILE_ERROR_CHANNELVAL', 45);

/**
 * Error code when a php5 package is packaged in php4 (analysis doesn't work)
 */
define('PEAR_PACKAGEFILE_ERROR_PHP5', 46);

/**
 * Error code when a file is listed in package.xml but does not exist
 */
define('PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND', 47);

/**
 * Error code when a <dep type="php" rel="not"... is encountered (use rel="ne")
 */
define('PEAR_PACKAGEFILE_PHP_NO_NOT', 48);

/**
 * Error code when a package.xml contains non-ISO-8859-1 characters
 */
define('PEAR_PACKAGEFILE_ERROR_NON_ISO_CHARS', 49);

/**
 * Error code when a dependency is not a 'has' relation, but has no version
 */
define('PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION', 50);

/**
 * Error code when a package has no lead developer
 */
define('PEAR_PACKAGEFILE_ERROR_NO_LEAD', 51);

/**
 * Error code when a filename begins with "."
 */
define('PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME', 52);
/**
 * package.xml encapsulator
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 */
class PEAR_PackageFile_v1
{
    /**
     * @access private
     * @var PEAR_ErrorStack
     * @access private
     */
    var $_stack;

    /**
     * A registry object, used to access the package name validation regex for non-standard channels
     * @var PEAR_Registry
     * @access private
     */
    var $_registry;

    /**
     * An object that contains a log method that matches PEAR_Common::log's signature
     * @var object
     * @access private
     */
    var $_logger;

    /**
     * Parsed package information
     * @var array
     * @access private
     */
    var $_packageInfo;

    /**
     * path to package.xml
     * @var string
     * @access private
     */
    var $_packageFile;

    /**
     * path to package .tgz or false if this is a local/extracted package.xml
     * @var string
     * @access private
     */
    var $_archiveFile;

    /**
     * @var int
     * @access private
     */
    var $_isValid = 0;

    /**
     * Determines whether this packagefile was initialized only with partial package info
     *
     * If this package file was constructed via parsing REST, it will only contain
     *
     * - package name
     * - channel name
     * - dependencies 
     * @var boolean
     * @access private
     */
    var $_incomplete = true;

    /**
     * @param bool determines whether to return a PEAR_Error object, or use the PEAR_ErrorStack
     * @param string Name of Error Stack class to use.
     */
    function __construct()
    {
        $this->_stack = new PEAR_ErrorStack('PEAR_PackageFile_v1');
        $this->_stack->setErrorMessageTemplate($this->_getErrorMessage());
        $this->_isValid = 0;
    }

    function installBinary($installer)
    {
        return false;
    }

    function isExtension($name)
    {
        return false;
    }

    function setConfig(&$config)
    {
        $this->_config = &$config;
        $this->_registry = &$config->getRegistry();
    }

    function setRequestedGroup()
    {
        // placeholder
    }

    /**
     * For saving in the registry.
     *
     * Set the last version that was installed
     * @param string
     */
    function setLastInstalledVersion($version)
    {
        $this->_packageInfo['_lastversion'] = $version;
    }

    /**
     * @return string|false
     */
    function getLastInstalledVersion()
    {
        if (isset($this->_packageInfo['_lastversion'])) {
            return $this->_packageInfo['_lastversion'];
        }
        return false;
    }

    function getInstalledBinary()
    {
        return false;
    }

    function listPostinstallScripts()
    {
        return false;
    }

    function initPostinstallScripts()
    {
        return false;
    }

    function setLogger(&$logger)
    {
        if ($logger && (!is_object($logger) || !method_exists($logger, 'log'))) {
            return PEAR::raiseError('Logger must be compatible with PEAR_Common::log');
        }
        $this->_logger = &$logger;
    }

    function setPackagefile($file, $archive = false)
    {
        $this->_packageFile = $file;
        $this->_archiveFile = $archive ? $archive : $file;
    }

    function getPackageFile()
    {
        return isset($this->_packageFile) ? $this->_packageFile : false;
    }

    function getPackageType()
    {
        return 'php';
    }

    function getArchiveFile()
    {
        return $this->_archiveFile;
    }

    function packageInfo($field)
    {
        if (!is_string($field) || empty($field) ||
            !isset($this->_packageInfo[$field])) {
            return false;
        }
        return $this->_packageInfo[$field];
    }

    function setDirtree($path)
    {
        if (!isset($this->_packageInfo['dirtree'])) {
            $this->_packageInfo['dirtree'] = array();
        }
        $this->_packageInfo['dirtree'][$path] = true;
    }

    function getDirtree()
    {
        if (isset($this->_packageInfo['dirtree']) && count($this->_packageInfo['dirtree'])) {
            return $this->_packageInfo['dirtree'];
        }
        return false;
    }

    function resetDirtree()
    {
        unset($this->_packageInfo['dirtree']);
    }

    function fromArray($pinfo)
    {
        $this->_incomplete = false;
        $this->_packageInfo = $pinfo;
    }

    function isIncomplete()
    {
        return $this->_incomplete;
    }

    function getChannel()
    {
        return 'pear.php.net';
    }

    function getUri()
    {
        return false;
    }

    function getTime()
    {
        return false;
    }

    function getExtends()
    {
        if (isset($this->_packageInfo['extends'])) {
            return $this->_packageInfo['extends'];
        }
        return false;
    }

    /**
     * @return array
     */
    function toArray()
    {
        if (!$this->validate(PEAR_VALIDATE_NORMAL)) {
            return false;
        }
        return $this->getArray();
    }

    function getArray()
    {
        return $this->_packageInfo;
    }

    function getName()
    {
        return $this->getPackage();
    }

    function getPackage()
    {
        if (isset($this->_packageInfo['package'])) {
            return $this->_packageInfo['package'];
        }
        return false;
    }

    /**
     * WARNING - don't use this unless you know what you are doing
     */
    function setRawPackage($package)
    {
        $this->_packageInfo['package'] = $package;
    }

    function setPackage($package)
    {
        $this->_packageInfo['package'] = $package;
        $this->_isValid = false;
    }

    function getVersion()
    {
        if (isset($this->_packageInfo['version'])) {
            return $this->_packageInfo['version'];
        }
        return false;
    }

    function setVersion($version)
    {
        $this->_packageInfo['version'] = $version;
        $this->_isValid = false;
    }

    function clearMaintainers()
    {
        unset($this->_packageInfo['maintainers']);
    }

    function getMaintainers()
    {
        if (isset($this->_packageInfo['maintainers'])) {
            return $this->_packageInfo['maintainers'];
        }
        return false;
    }

    /**
     * Adds a new maintainer - no checking of duplicates is performed, use
     * updatemaintainer for that purpose.
     */
    function addMaintainer($role, $handle, $name, $email)
    {
        $this->_packageInfo['maintainers'][] =
            array('handle' => $handle, 'role' => $role, 'email' => $email, 'name' => $name);
        $this->_isValid = false;
    }

    function updateMaintainer($role, $handle, $name, $email)
    {
        $found = false;
        if (!isset($this->_packageInfo['maintainers']) ||
              !is_array($this->_packageInfo['maintainers'])) {
            return $this->addMaintainer($role, $handle, $name, $email);
        }
        foreach ($this->_packageInfo['maintainers'] as $i => $maintainer) {
            if ($maintainer['handle'] == $handle) {
                $found = $i;
                break;
            }
        }
        if ($found !== false) {
            unset($this->_packageInfo['maintainers'][$found]);
            $this->_packageInfo['maintainers'] =
                array_values($this->_packageInfo['maintainers']);
        }
        $this->addMaintainer($role, $handle, $name, $email);
    }

    function deleteMaintainer($handle)
    {
        $found = false;
        foreach ($this->_packageInfo['maintainers'] as $i => $maintainer) {
            if ($maintainer['handle'] == $handle) {
                $found = $i;
                break;
            }
        }
        if ($found !== false) {
            unset($this->_packageInfo['maintainers'][$found]);
            $this->_packageInfo['maintainers'] =
                array_values($this->_packageInfo['maintainers']);
            return true;
        }
        return false;
    }

    function getState()
    {
        if (isset($this->_packageInfo['release_state'])) {
            return $this->_packageInfo['release_state'];
        }
        return false;
    }

    function setRawState($state)
    {
        $this->_packageInfo['release_state'] = $state;
    }

    function setState($state)
    {
        $this->_packageInfo['release_state'] = $state;
        $this->_isValid = false;
    }

    function getDate()
    {
        if (isset($this->_packageInfo['release_date'])) {
            return $this->_packageInfo['release_date'];
        }
        return false;
    }

    function setDate($date)
    {
        $this->_packageInfo['release_date'] = $date;
        $this->_isValid = false;
    }

    function getLicense()
    {
        if (isset($this->_packageInfo['release_license'])) {
            return $this->_packageInfo['release_license'];
        }
        return false;
    }

    function setLicense($date)
    {
        $this->_packageInfo['release_license'] = $date;
        $this->_isValid = false;
    }

    function getSummary()
    {
        if (isset($this->_packageInfo['summary'])) {
            return $this->_packageInfo['summary'];
        }
        return false;
    }

    function setSummary($summary)
    {
        $this->_packageInfo['summary'] = $summary;
        $this->_isValid = false;
    }

    function getDescription()
    {
        if (isset($this->_packageInfo['description'])) {
            return $this->_packageInfo['description'];
        }
        return false;
    }

    function setDescription($desc)
    {
        $this->_packageInfo['description'] = $desc;
        $this->_isValid = false;
    }

    function getNotes()
    {
        if (isset($this->_packageInfo['release_notes'])) {
            return $this->_packageInfo['release_notes'];
        }
        return false;
    }

    function setNotes($notes)
    {
        $this->_packageInfo['release_notes'] = $notes;
        $this->_isValid = false;
    }

    function getDeps()
    {
        if (isset($this->_packageInfo['release_deps'])) {
            return $this->_packageInfo['release_deps'];
        }
        return false;
    }

    /**
     * Reset dependencies prior to adding new ones
     */
    function clearDeps()
    {
        unset($this->_packageInfo['release_deps']);
    }

    function addPhpDep($version, $rel)
    {
        $this->_isValid = false;
        $this->_packageInfo['release_deps'][] =
            array('type' => 'php',
                  'rel' => $rel,
                  'version' => $version);
    }

    function addPackageDep($name, $version, $rel, $optional = 'no')
    {
        $this->_isValid = false;
        $dep =
            array('type' => 'pkg',
                  'name' => $name,
                  'rel' => $rel,
                  'optional' => $optional);
        if ($rel != 'has' && $rel != 'not') {
            $dep['version'] = $version;
        }
        $this->_packageInfo['release_deps'][] = $dep;
    }

    function addExtensionDep($name, $version, $rel, $optional = 'no')
    {
        $this->_isValid = false;
        $this->_packageInfo['release_deps'][] =
            array('type' => 'ext',
                  'name' => $name,
                  'rel' => $rel,
                  'version' => $version,
                  'optional' => $optional);
    }

    /**
     * WARNING - do not use this function directly unless you know what you're doing
     */
    function setDeps($deps)
    {
        $this->_packageInfo['release_deps'] = $deps;
    }

    function hasDeps()
    {
        return isset($this->_packageInfo['release_deps']) &&
            count($this->_packageInfo['release_deps']);
    }

    function getDependencyGroup($group)
    {
        return false;
    }

    function isCompatible($pf)
    {
        return false;
    }

    function isSubpackageOf($p)
    {
        return $p->isSubpackage($this);
    }

    function isSubpackage($p)
    {
        return false;
    }

    function dependsOn($package, $channel)
    {
        if (strtolower($channel) != 'pear.php.net') {
            return false;
        }
        if (!($deps = $this->getDeps())) {
            return false;
        }
        foreach ($deps as $dep) {
            if ($dep['type'] != 'pkg') {
                continue;
            }
            if (strtolower($dep['name']) == strtolower($package)) {
                return true;
            }
        }
        return false;
    }

    function getConfigureOptions()
    {
        if (isset($this->_packageInfo['configure_options'])) {
            return $this->_packageInfo['configure_options'];
        }
        return false;
    }

    function hasConfigureOptions()
    {
        return isset($this->_packageInfo['configure_options']) &&
            count($this->_packageInfo['configure_options']);
    }

    function addConfigureOption($name, $prompt, $default = false)
    {
        $o = array('name' => $name, 'prompt' => $prompt);
        if ($default !== false) {
            $o['default'] = $default;
        }
        if (!isset($this->_packageInfo['configure_options'])) {
            $this->_packageInfo['configure_options'] = array();
        }
        $this->_packageInfo['configure_options'][] = $o;
    }

    function clearConfigureOptions()
    {
        unset($this->_packageInfo['configure_options']);
    }

    function getProvides()
    {
        if (isset($this->_packageInfo['provides'])) {
            return $this->_packageInfo['provides'];
        }
        return false;
    }

    function getProvidesExtension()
    {
        return false;
    }

    function addFile($dir, $file, $attrs)
    {
        $dir = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), $dir);
        if ($dir == '/' || $dir == '') {
            $dir = '';
        } else {
            $dir .= '/';
        }
        $file = $dir . $file;
        $file = preg_replace('![\\/]+!', '/', $file);
        $this->_packageInfo['filelist'][$file] = $attrs;
    }

    function getInstallationFilelist()
    {
        return $this->getFilelist();
    }

    function getFilelist()
    {
        if (isset($this->_packageInfo['filelist'])) {
            return $this->_packageInfo['filelist'];
        }
        return false;
    }

    function setFileAttribute($file, $attr, $value)
    {
        $this->_packageInfo['filelist'][$file][$attr] = $value;
    }

    function resetFilelist()
    {
        $this->_packageInfo['filelist'] = array();
    }

    function setInstalledAs($file, $path)
    {
        if ($path) {
            return $this->_packageInfo['filelist'][$file]['installed_as'] = $path;
        }
        unset($this->_packageInfo['filelist'][$file]['installed_as']);
    }

    function installedFile($file, $atts)
    {
        if (isset($this->_packageInfo['filelist'][$file])) {
            $this->_packageInfo['filelist'][$file] =
                array_merge($this->_packageInfo['filelist'][$file], $atts);
        } else {
            $this->_packageInfo['filelist'][$file] = $atts;
        }
    }

    function getChangelog()
    {
        if (isset($this->_packageInfo['changelog'])) {
            return $this->_packageInfo['changelog'];
        }
        return false;
    }

    function getPackagexmlVersion()
    {
        return '1.0';
    }

    /**
     * Wrapper to {@link PEAR_ErrorStack::getErrors()}
     * @param boolean determines whether to purge the error stack after retrieving
     * @return array
     */
    function getValidationWarnings($purge = true)
    {
        return $this->_stack->getErrors($purge);
    }

    // }}}
    /**
     * Validation error.  Also marks the object contents as invalid
     * @param error code
     * @param array error information
     * @access private
     */
    function _validateError($code, $params = array())
    {
        $this->_stack->push($code, 'error', $params, false, false, debug_backtrace());
        $this->_isValid = false;
    }

    /**
     * Validation warning.  Does not mark the object contents invalid.
     * @param error code
     * @param array error information
     * @access private
     */
    function _validateWarning($code, $params = array())
    {
        $this->_stack->push($code, 'warning', $params, false, false, debug_backtrace());
    }

    /**
     * @param integer error code
     * @access protected
     */
    function _getErrorMessage()
    {
        return array(
                PEAR_PACKAGEFILE_ERROR_NO_NAME =>
                    'Missing Package Name',
                PEAR_PACKAGEFILE_ERROR_NO_SUMMARY =>
                    'No summary found',
                PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY =>
                    'Summary should be on one line',
                PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION =>
                    'Missing description',
                PEAR_PACKAGEFILE_ERROR_NO_LICENSE =>
                    'Missing license',
                PEAR_PACKAGEFILE_ERROR_NO_VERSION =>
                    'No release version found',
                PEAR_PACKAGEFILE_ERROR_NO_STATE =>
                    'No release state found',
                PEAR_PACKAGEFILE_ERROR_NO_DATE =>
                    'No release date found',
                PEAR_PACKAGEFILE_ERROR_NO_NOTES =>
                    'No release notes found',
                PEAR_PACKAGEFILE_ERROR_NO_LEAD =>
                    'Package must have at least one lead maintainer',
                PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS =>
                    'No maintainers found, at least one must be defined',
                PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE =>
                    'Maintainer %index% has no handle (user ID at channel server)',
                PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE =>
                    'Maintainer %index% has no role',
                PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME =>
                    'Maintainer %index% has no name',
                PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL =>
                    'Maintainer %index% has no email',
                PEAR_PACKAGEFILE_ERROR_NO_DEPNAME =>
                    'Dependency %index% is not a php dependency, and has no name',
                PEAR_PACKAGEFILE_ERROR_NO_DEPREL =>
                    'Dependency %index% has no relation (rel)',
                PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE =>
                    'Dependency %index% has no type',
                PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED =>
                    'PHP Dependency %index% has a name attribute of "%name%" which will be' .
                        ' ignored!',
                PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION =>
                    'Dependency %index% is not a rel="has" or rel="not" dependency, ' .
                        'and has no version',
                PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION =>
                    'Dependency %index% is a type="php" dependency, ' .
                        'and has no version',
                PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED =>
                    'Dependency %index% is a rel="%rel%" dependency, versioning is ignored',
                PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL =>
                    'Dependency %index% has invalid optional value "%opt%", should be yes or no',
                PEAR_PACKAGEFILE_PHP_NO_NOT =>
                    'Dependency %index%: php dependencies cannot use "not" rel, use "ne"' .
                        ' to exclude specific versions',
                PEAR_PACKAGEFILE_ERROR_NO_CONFNAME =>
                    'Configure Option %index% has no name',
                PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT =>
                    'Configure Option %index% has no prompt',
                PEAR_PACKAGEFILE_ERROR_NO_FILES =>
                    'No files in <filelist> section of package.xml',
                PEAR_PACKAGEFILE_ERROR_NO_FILEROLE =>
                    'File "%file%" has no role, expecting one of "%roles%"',
                PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE =>
                    'File "%file%" has invalid role "%role%", expecting one of "%roles%"',
                PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME =>
                    'File "%file%" cannot start with ".", cannot package or install',
                PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE =>
                    'Parser error: invalid PHP found in file "%file%"',
                PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX =>
                    'in %file%: %type% "%name%" not prefixed with package name "%package%"',
                PEAR_PACKAGEFILE_ERROR_INVALID_FILE =>
                    'Parser error: invalid PHP file "%file%"',
                PEAR_PACKAGEFILE_ERROR_CHANNELVAL =>
                    'Channel validator error: field "%field%" - %reason%',
                PEAR_PACKAGEFILE_ERROR_PHP5 =>
                    'Error, PHP5 token encountered in %file%, analysis should be in PHP5',
                PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND =>
                    'File "%file%" in package.xml does not exist',
                PEAR_PACKAGEFILE_ERROR_NON_ISO_CHARS =>
                    'Package.xml contains non-ISO-8859-1 characters, and may not validate',
            );
    }

    /**
     * Validate XML package definition file.
     *
     * @access public
     * @return boolean
     */
    function validate($state = PEAR_VALIDATE_NORMAL, $nofilechecking = false)
    {
        if (($this->_isValid & $state) == $state) {
            return true;
        }
        $this->_isValid = true;
        $info = $this->_packageInfo;
        if (empty($info['package'])) {
            $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_NAME);
            $this->_packageName = $pn = 'unknown';
        } else {
            $this->_packageName = $pn = $info['package'];
        }

        if (empty($info['summary'])) {
            $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_SUMMARY);
        } elseif (strpos(trim($info['summary']), "\n") !== false) {
            $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY,
                array('summary' => $info['summary']));
        }
        if (empty($info['description'])) {
            $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION);
        }
        if (empty($info['release_license'])) {
            $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_LICENSE);
        }
        if (empty($info['version'])) {
            $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_VERSION);
        }
        if (empty($info['release_state'])) {
            $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_STATE);
        }
        if (empty($info['release_date'])) {
            $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DATE);
        }
        if (empty($info['release_notes'])) {
            $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_NOTES);
        }
        if (empty($info['maintainers'])) {
            $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS);
        } else {
            $haslead = false;
            $i = 1;
            foreach ($info['maintainers'] as $m) {
                if (empty($m['handle'])) {
                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE,
                        array('index' => $i));
                }
                if (empty($m['role'])) {
                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE,
                        array('index' => $i, 'roles' => PEAR_Common::getUserRoles()));
                } elseif ($m['role'] == 'lead') {
                    $haslead = true;
                }
                if (empty($m['name'])) {
                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME,
                        array('index' => $i));
                }
                if (empty($m['email'])) {
                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL,
                        array('index' => $i));
                }
                $i++;
            }
            if (!$haslead) {
                $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_LEAD);
            }
        }
        if (!empty($info['release_deps'])) {
            $i = 1;
            foreach ($info['release_deps'] as $d) {
                if (!isset($d['type']) || empty($d['type'])) {
                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE,
                        array('index' => $i, 'types' => PEAR_Common::getDependencyTypes()));
                    continue;
                }
                if (!isset($d['rel']) || empty($d['rel'])) {
                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPREL,
                        array('index' => $i, 'rels' => PEAR_Common::getDependencyRelations()));
                    continue;
                }
                if (!empty($d['optional'])) {
                    if (!in_array($d['optional'], array('yes', 'no'))) {
                        $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL,
                            array('index' => $i, 'opt' => $d['optional']));
                    }
                }
                if ($d['rel'] != 'has' && $d['rel'] != 'not' && empty($d['version'])) {
                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION,
                        array('index' => $i));
                } elseif (($d['rel'] == 'has' || $d['rel'] == 'not') && !empty($d['version'])) {
                    $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED,
                        array('index' => $i, 'rel' => $d['rel']));
                }
                if ($d['type'] == 'php' && !empty($d['name'])) {
                    $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED,
                        array('index' => $i, 'name' => $d['name']));
                } elseif ($d['type'] != 'php' && empty($d['name'])) {
                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPNAME,
                        array('index' => $i));
                }
                if ($d['type'] == 'php' && empty($d['version'])) {
                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION,
                        array('index' => $i));
                }
                if (($d['rel'] == 'not') && ($d['type'] == 'php')) {
                    $this->_validateError(PEAR_PACKAGEFILE_PHP_NO_NOT,
                        array('index' => $i));
                }
                $i++;
            }
        }
        if (!empty($info['configure_options'])) {
            $i = 1;
            foreach ($info['configure_options'] as $c) {
                if (empty($c['name'])) {
                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_CONFNAME,
                        array('index' => $i));
                }
                if (empty($c['prompt'])) {
                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT,
                        array('index' => $i));
                }
                $i++;
            }
        }
        if (empty($info['filelist'])) {
            $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_FILES);
            $errors[] = 'no files';
        } else {
            foreach ($info['filelist'] as $file => $fa) {
                if (empty($fa['role'])) {
                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_FILEROLE,
                        array('file' => $file, 'roles' => PEAR_Common::getFileRoles()));
                    continue;
                } elseif (!in_array($fa['role'], PEAR_Common::getFileRoles())) {
                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE,
                        array('file' => $file, 'role' => $fa['role'], 'roles' => PEAR_Common::getFileRoles()));
                }
                if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~', str_replace('\\', '/', $file))) {
                    // file contains .. parent directory or . cur directory references
                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME,
                        array('file' => $file));
                }
                if (isset($fa['install-as']) &&
                      preg_match('~/\.\.?(/|\\z)|^\.\.?/~', 
                                 str_replace('\\', '/', $fa['install-as']))) {
                    // install-as contains .. parent directory or . cur directory references
                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME,
                        array('file' => $file . ' [installed as ' . $fa['install-as'] . ']'));
                }
                if (isset($fa['baseinstalldir']) &&
                      preg_match('~/\.\.?(/|\\z)|^\.\.?/~', 
                                 str_replace('\\', '/', $fa['baseinstalldir']))) {
                    // install-as contains .. parent directory or . cur directory references
                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME,
                        array('file' => $file . ' [baseinstalldir ' . $fa['baseinstalldir'] . ']'));
                }
            }
        }
        if (isset($this->_registry) && $this->_isValid) {
            $chan = $this->_registry->getChannel('pear.php.net');
            if (PEAR::isError($chan)) {
                $this->_validateError(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $chan->getMessage());
                return $this->_isValid = 0;
            }
            $validator = $chan->getValidationObject();
            $validator->setPackageFile($this);
            $validator->validate($state);
            $failures = $validator->getFailures();
            foreach ($failures['errors'] as $error) {
                $this->_validateError(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $error);
            }
            foreach ($failures['warnings'] as $warning) {
                $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $warning);
            }
        }
        if ($this->_isValid && $state == PEAR_VALIDATE_PACKAGING && !$nofilechecking) {
            if ($this->_analyzePhpFiles()) {
                $this->_isValid = true;
            }
        }
        if ($this->_isValid) {
            return $this->_isValid = $state;
        }
        return $this->_isValid = 0;
    }

    function _analyzePhpFiles()
    {
        if (!$this->_isValid) {
            return false;
        }
        if (!isset($this->_packageFile)) {
            return false;
        }
        $dir_prefix = dirname($this->_packageFile);
        $common = new PEAR_Common;
        $log = isset($this->_logger) ? array(&$this->_logger, 'log') :
            array($common, 'log');
        $info = $this->getFilelist();
        foreach ($info as $file => $fa) {
            if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $file)) {
                $this->_validateError(PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND,
                    array('file' => realpath($dir_prefix) . DIRECTORY_SEPARATOR . $file));
                continue;
            }
            if ($fa['role'] == 'php' && $dir_prefix) {
                call_user_func_array($log, array(1, "Analyzing $file"));
                $srcinfo = $this->_analyzeSourceCode($dir_prefix . DIRECTORY_SEPARATOR . $file);
                if ($srcinfo) {
                    $this->_buildProvidesArray($srcinfo);
                }
            }
        }
        $this->_packageName = $pn = $this->getPackage();
        $pnl = strlen($pn);
        if (isset($this->_packageInfo['provides'])) {
            foreach ((array) $this->_packageInfo['provides'] as $key => $what) {
                if (isset($what['explicit'])) {
                    // skip conformance checks if the provides entry is
                    // specified in the package.xml file
                    continue;
                }
                extract($what);
                if ($type == 'class') {
                    if (!strncasecmp($name, $pn, $pnl)) {
                        continue;
                    }
                    $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX,
                        array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn));
                } elseif ($type == 'function') {
                    if (strstr($name, '::') || !strncasecmp($name, $pn, $pnl)) {
                        continue;
                    }
                    $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX,
                        array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn));
                }
            }
        }
        return $this->_isValid;
    }

    /**
     * Get the default xml generator object
     *
     * @return PEAR_PackageFile_Generator_v1
     */
    function &getDefaultGenerator()
    {
        if (!class_exists('PEAR_PackageFile_Generator_v1')) {
            require_once 'PEAR/PackageFile/Generator/v1.php';
        }
        $a = new PEAR_PackageFile_Generator_v1($this);
        return $a;
    }

    /**
     * Get the contents of a file listed within the package.xml
     * @param string
     * @return string
     */
    function getFileContents($file)
    {
        if ($this->_archiveFile == $this->_packageFile) { // unpacked
            $dir = dirname($this->_packageFile);
            $file = $dir . DIRECTORY_SEPARATOR . $file;
            $file = str_replace(array('/', '\\'),
                array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR), $file);
            if (file_exists($file) && is_readable($file)) {
                return implode('', file($file));
            }
        } else { // tgz
            if (!class_exists('Archive_Tar')) {
                require_once 'Archive/Tar.php';
            }
            $tar = new Archive_Tar($this->_archiveFile);
            $tar->pushErrorHandling(PEAR_ERROR_RETURN);
            if ($file != 'package.xml' && $file != 'package2.xml') {
                $file = $this->getPackage() . '-' . $this->getVersion() . '/' . $file;
            }
            $file = $tar->extractInString($file);
            $tar->popErrorHandling();
            if (PEAR::isError($file)) {
                return PEAR::raiseError("Cannot locate file '$file' in archive");
            }
            return $file;
        }
    }

    // {{{ analyzeSourceCode()
    /**
     * Analyze the source code of the given PHP file
     *
     * @param  string Filename of the PHP file
     * @return mixed
     * @access private
     */
    function _analyzeSourceCode($file)
    {
        if (!function_exists("token_get_all")) {
            return false;
        }
        if (!defined('T_DOC_COMMENT')) {
            define('T_DOC_COMMENT', T_COMMENT);
        }
        if (!defined('T_INTERFACE')) {
            define('T_INTERFACE', -1);
        }
        if (!defined('T_IMPLEMENTS')) {
            define('T_IMPLEMENTS', -1);
        }
        if (!$fp = @fopen($file, "r")) {
            return false;
        }
        fclose($fp);
        $contents = file_get_contents($file);
        $tokens = token_get_all($contents);
/*
        for ($i = 0; $i < sizeof($tokens); $i++) {
            @list($token, $data) = $tokens[$i];
            if (is_string($token)) {
                var_dump($token);
            } else {
                print token_name($token) . ' ';
                var_dump(rtrim($data));
            }
        }
*/
        $look_for = 0;
        $paren_level = 0;
        $bracket_level = 0;
        $brace_level = 0;
        $lastphpdoc = '';
        $current_class = '';
        $current_interface = '';
        $current_class_level = -1;
        $current_function = '';
        $current_function_level = -1;
        $declared_classes = array();
        $declared_interfaces = array();
        $declared_functions = array();
        $declared_methods = array();
        $used_classes = array();
        $used_functions = array();
        $extends = array();
        $implements = array();
        $nodeps = array();
        $inquote = false;
        $interface = false;
        for ($i = 0; $i < sizeof($tokens); $i++) {
            if (is_array($tokens[$i])) {
                list($token, $data) = $tokens[$i];
            } else {
                $token = $tokens[$i];
                $data = '';
            }
            if ($inquote) {
                if ($token != '"' && $token != T_END_HEREDOC) {
                    continue;
                } else {
                    $inquote = false;
                    continue;
                }
            }
            switch ($token) {
                case T_WHITESPACE:
                    break;
                case ';':
                    if ($interface) {
                        $current_function = '';
                        $current_function_level = -1;
                    }
                    break;
                case '"':
                case T_START_HEREDOC:
                    $inquote = true;
                    break;
                case T_CURLY_OPEN:
                case T_DOLLAR_OPEN_CURLY_BRACES:
                case '{': $brace_level++; continue 2;
                case '}':
                    $brace_level--;
                    if ($current_class_level == $brace_level) {
                        $current_class = '';
                        $current_class_level = -1;
                    }
                    if ($current_function_level == $brace_level) {
                        $current_function = '';
                        $current_function_level = -1;
                    }
                    continue 2;
                case '[': $bracket_level++; continue 2;
                case ']': $bracket_level--; continue 2;
                case '(': $paren_level++;   continue 2;
                case ')': $paren_level--;   continue 2;
                case T_INTERFACE:
                    $interface = true;
                case T_CLASS:
                    if (($current_class_level != -1) || ($current_function_level != -1)) {
                        $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE,
                            array('file' => $file));
                        return false;
                    }
                case T_FUNCTION:
                case T_NEW:
                case T_EXTENDS:
                case T_IMPLEMENTS:
                    $look_for = $token;
                    continue 2;
                case T_STRING:
                    if ($look_for == T_CLASS) {
                        $current_class = $data;
                        $current_class_level = $brace_level;
                        $declared_classes[] = $current_class;
                    } elseif ($look_for == T_INTERFACE) {
                        $current_interface = $data;
                        $current_class_level = $brace_level;
                        $declared_interfaces[] = $current_interface;
                    } elseif ($look_for == T_IMPLEMENTS) {
                        $implements[$current_class] = $data;
                    } elseif ($look_for == T_EXTENDS) {
                        $extends[$current_class] = $data;
                    } elseif ($look_for == T_FUNCTION) {
                        if ($current_class) {
                            $current_function = "$current_class::$data";
                            $declared_methods[$current_class][] = $data;
                        } elseif ($current_interface) {
                            $current_function = "$current_interface::$data";
                            $declared_methods[$current_interface][] = $data;
                        } else {
                            $current_function = $data;
                            $declared_functions[] = $current_function;
                        }
                        $current_function_level = $brace_level;
                        $m = array();
                    } elseif ($look_for == T_NEW) {
                        $used_classes[$data] = true;
                    }
                    $look_for = 0;
                    continue 2;
                case T_VARIABLE:
                    $look_for = 0;
                    continue 2;
                case T_DOC_COMMENT:
                case T_COMMENT:
                    if (preg_match('!^/\*\*\s!', $data)) {
                        $lastphpdoc = $data;
                        if (preg_match_all('/@nodep\s+(\S+)/', $lastphpdoc, $m)) {
                            $nodeps = array_merge($nodeps, $m[1]);
                        }
                    }
                    continue 2;
                case T_DOUBLE_COLON:
                    if (!($tokens[$i - 1][0] == T_WHITESPACE || $tokens[$i - 1][0] == T_STRING)) {
                        $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE,
                            array('file' => $file));
                        return false;
                    }
                    $class = $tokens[$i - 1][1];
                    if (strtolower($class) != 'parent') {
                        $used_classes[$class] = true;
                    }
                    continue 2;
            }
        }
        return array(
            "source_file" => $file,
            "declared_classes" => $declared_classes,
            "declared_interfaces" => $declared_interfaces,
            "declared_methods" => $declared_methods,
            "declared_functions" => $declared_functions,
            "used_classes" => array_diff(array_keys($used_classes), $nodeps),
            "inheritance" => $extends,
            "implements" => $implements,
            );
    }

    /**
     * Build a "provides" array from data returned by
     * analyzeSourceCode().  The format of the built array is like
     * this:
     *
     *  array(
     *    'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'),
     *    ...
     *  )
     *
     *
     * @param array $srcinfo array with information about a source file
     * as returned by the analyzeSourceCode() method.
     *
     * @return void
     *
     * @access private
     *
     */
    function _buildProvidesArray($srcinfo)
    {
        if (!$this->_isValid) {
            return false;
        }
        $file = basename($srcinfo['source_file']);
        $pn = $this->getPackage();
        $pnl = strlen($pn);
        foreach ($srcinfo['declared_classes'] as $class) {
            $key = "class;$class";
            if (isset($this->_packageInfo['provides'][$key])) {
                continue;
            }
            $this->_packageInfo['provides'][$key] =
                array('file'=> $file, 'type' => 'class', 'name' => $class);
            if (isset($srcinfo['inheritance'][$class])) {
                $this->_packageInfo['provides'][$key]['extends'] =
                    $srcinfo['inheritance'][$class];
            }
        }
        foreach ($srcinfo['declared_methods'] as $class => $methods) {
            foreach ($methods as $method) {
                $function = "$class::$method";
                $key = "function;$function";
                if ($method[0] == '_' || !strcasecmp($method, $class) ||
                    isset($this->_packageInfo['provides'][$key])) {
                    continue;
                }
                $this->_packageInfo['provides'][$key] =
                    array('file'=> $file, 'type' => 'function', 'name' => $function);
            }
        }

        foreach ($srcinfo['declared_functions'] as $function) {
            $key = "function;$function";
            if ($function[0] == '_' || isset($this->_packageInfo['provides'][$key])) {
                continue;
            }
            if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) {
                $warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\"";
            }
            $this->_packageInfo['provides'][$key] =
                array('file'=> $file, 'type' => 'function', 'name' => $function);
        }
    }

    // }}}
}
?>
PKq�Z�ɁɁ!PEAR/PackageFile/Generator/v2.phpnu�[���<?php
/**
 * package.xml generation class, package.xml version 2.0
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @author     Stephan Schmidt (original XML_Serializer code)
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a1
 */
/**
 * file/dir manipulation routines
 */
require_once 'System.php';
require_once 'XML/Util.php';

/**
 * This class converts a PEAR_PackageFile_v2 object into any output format.
 *
 * Supported output formats include array, XML string (using S. Schmidt's
 * XML_Serializer, slightly customized)
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @author     Stephan Schmidt (original XML_Serializer code)
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 */
class PEAR_PackageFile_Generator_v2
{
   /**
    * default options for the serialization
    * @access private
    * @var array $_defaultOptions
    */
    var $_defaultOptions = array(
        'indent'             => ' ',                    // string used for indentation
        'linebreak'          => "\n",                  // string used for newlines
        'typeHints'          => false,                 // automatically add type hin attributes
        'addDecl'            => true,                 // add an XML declaration
        'defaultTagName'     => 'XML_Serializer_Tag',  // tag used for indexed arrays or invalid names
        'classAsTagName'     => false,                 // use classname for objects in indexed arrays
        'keyAttribute'       => '_originalKey',        // attribute where original key is stored
        'typeAttribute'      => '_type',               // attribute for type (only if typeHints => true)
        'classAttribute'     => '_class',              // attribute for class of objects (only if typeHints => true)
        'scalarAsAttributes' => false,                 // scalar values (strings, ints,..) will be serialized as attribute
        'prependAttributes'  => '',                    // prepend string for attributes
        'indentAttributes'   => false,                 // indent the attributes, if set to '_auto', it will indent attributes so they all start at the same column
        'mode'               => 'simplexml',             // use 'simplexml' to use parent name as tagname if transforming an indexed array
        'addDoctype'         => false,                 // add a doctype declaration
        'doctype'            => null,                  // supply a string or an array with id and uri ({@see XML_Util::getDoctypeDeclaration()}
        'rootName'           => 'package',                  // name of the root tag
        'rootAttributes'     => array(
            'version' => '2.0',
            'xmlns' => 'http://pear.php.net/dtd/package-2.0',
            'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0',
            'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
            'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0
http://pear.php.net/dtd/tasks-1.0.xsd
http://pear.php.net/dtd/package-2.0
http://pear.php.net/dtd/package-2.0.xsd',
        ),               // attributes of the root tag
        'attributesArray'    => 'attribs',                  // all values in this key will be treated as attributes
        'contentName'        => '_content',                   // this value will be used directly as content, instead of creating a new tag, may only be used in conjunction with attributesArray
        'beautifyFilelist'   => false,
        'encoding' => 'UTF-8',
    );

   /**
    * options for the serialization
    * @access private
    * @var array $options
    */
    var $options = array();

   /**
    * current tag depth
    * @var integer $_tagDepth
    */
    var $_tagDepth = 0;

   /**
    * serilialized representation of the data
    * @var string $_serializedData
    */
    var $_serializedData = null;
    /**
     * @var PEAR_PackageFile_v2
     */
    var $_packagefile;
    /**
     * @param PEAR_PackageFile_v2
     */
    function __construct(&$packagefile)
    {
        $this->_packagefile = &$packagefile;
        if (isset($this->_packagefile->encoding)) {
            $this->_defaultOptions['encoding'] = $this->_packagefile->encoding;
        }
    }

    /**
     * @return string
     */
    function getPackagerVersion()
    {
        return '1.10.16';
    }

    /**
     * @param PEAR_Packager
     * @param bool generate a .tgz or a .tar
     * @param string|null temporary directory to package in
     */
    function toTgz(&$packager, $compress = true, $where = null)
    {
        $a = null;
        return $this->toTgz2($packager, $a, $compress, $where);
    }

    /**
     * Package up both a package.xml and package2.xml for the same release
     * @param PEAR_Packager
     * @param PEAR_PackageFile_v1
     * @param bool generate a .tgz or a .tar
     * @param string|null temporary directory to package in
     */
    function toTgz2(&$packager, &$pf1, $compress = true, $where = null)
    {
        require_once 'Archive/Tar.php';
        if (!$this->_packagefile->isEquivalent($pf1)) {
            return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: "' .
                basename($pf1->getPackageFile()) .
                '" is not equivalent to "' . basename($this->_packagefile->getPackageFile())
                . '"');
        }

        if ($where === null) {
            if (!($where = System::mktemp(array('-d')))) {
                return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: mktemp failed');
            }
        } elseif (!@System::mkDir(array('-p', $where))) {
            return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: "' . $where . '" could' .
                ' not be created');
        }

        $file = $where . DIRECTORY_SEPARATOR . 'package.xml';
        if (file_exists($file) && !is_file($file)) {
            return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: unable to save package.xml as' .
                ' "' . $file  .'"');
        }

        if (!$this->_packagefile->validate(PEAR_VALIDATE_PACKAGING)) {
            return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: invalid package.xml');
        }

        $ext = $compress ? '.tgz' : '.tar';
        $pkgver = $this->_packagefile->getPackage() . '-' . $this->_packagefile->getVersion();
        $dest_package = getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext;
        if (file_exists($dest_package) && !is_file($dest_package)) {
            return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: cannot create tgz file "' .
                $dest_package . '"');
        }

        $pkgfile = $this->_packagefile->getPackageFile();
        if (!$pkgfile) {
            return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: package file object must ' .
                'be created from a real file');
        }

        $pkgdir  = dirname(realpath($pkgfile));
        $pkgfile = basename($pkgfile);

        // {{{ Create the package file list
        $filelist = array();
        $i = 0;
        $this->_packagefile->flattenFilelist();
        $contents = $this->_packagefile->getContents();
        if (isset($contents['bundledpackage'])) { // bundles of packages
            $contents = $contents['bundledpackage'];
            if (!isset($contents[0])) {
                $contents = array($contents);
            }

            $packageDir = $where;
            foreach ($contents as $i => $package) {
                $fname = $package;
                $file = $pkgdir . DIRECTORY_SEPARATOR . $fname;
                if (!file_exists($file)) {
                    return $packager->raiseError("File does not exist: $fname");
                }

                $tfile = $packageDir . DIRECTORY_SEPARATOR . $fname;
                System::mkdir(array('-p', dirname($tfile)));
                copy($file, $tfile);
                $filelist[$i++] = $tfile;
                $packager->log(2, "Adding package $fname");
            }
        } else { // normal packages
            $contents = $contents['dir']['file'];
            if (!isset($contents[0])) {
                $contents = array($contents);
            }

            $packageDir = $where;
            foreach ($contents as $i => $file) {
                $fname = $file['attribs']['name'];
                $atts = $file['attribs'];
                $orig = $file;
                $file = $pkgdir . DIRECTORY_SEPARATOR . $fname;
                if (!file_exists($file)) {
                    return $packager->raiseError("File does not exist: $fname");
                }

                $origperms = fileperms($file);
                $tfile = $packageDir . DIRECTORY_SEPARATOR . $fname;
                unset($orig['attribs']);
                if (count($orig)) { // file with tasks
                    // run any package-time tasks
                    $contents = file_get_contents($file);
                    foreach ($orig as $tag => $raw) {
                        $tag = str_replace(
                            array($this->_packagefile->getTasksNs() . ':', '-'),
                            array('', '_'), $tag);
                        $task = "PEAR_Task_$tag";
                        $task = new $task($this->_packagefile->_config,
                            $this->_packagefile->_logger,
                            PEAR_TASK_PACKAGE);
                        $task->init($raw, $atts, null);
                        $res = $task->startSession($this->_packagefile, $contents, $tfile);
                        if (!$res) {
                            continue; // skip this task
                        }

                        if (PEAR::isError($res)) {
                            return $res;
                        }

                        $contents = $res; // save changes
                        System::mkdir(array('-p', dirname($tfile)));
                        $wp = fopen($tfile, "wb");
                        fwrite($wp, $contents);
                        fclose($wp);
                    }
                }

                if (!file_exists($tfile)) {
                    System::mkdir(array('-p', dirname($tfile)));
                    copy($file, $tfile);
                }

                chmod($tfile, $origperms);
                $filelist[$i++] = $tfile;
                $this->_packagefile->setFileAttribute($fname, 'md5sum', md5_file($tfile), $i - 1);
                $packager->log(2, "Adding file $fname");
            }
        }
            // }}}

        $name       = $pf1 !== null ? 'package2.xml' : 'package.xml';
        $packagexml = $this->toPackageFile($where, PEAR_VALIDATE_PACKAGING, $name);
        if ($packagexml) {
            $tar = new Archive_Tar($dest_package, $compress);
            $tar->setErrorHandling(PEAR_ERROR_RETURN); // XXX Don't print errors
            // ----- Creates with the package.xml file
            $ok = $tar->createModify(array($packagexml), '', $where);
            if (PEAR::isError($ok)) {
                return $packager->raiseError($ok);
            } elseif (!$ok) {
                return $packager->raiseError('PEAR_Packagefile_v2::toTgz(): adding ' . $name .
                    ' failed');
            }

            // ----- Add the content of the package
            if (!$tar->addModify($filelist, $pkgver, $where)) {
                return $packager->raiseError(
                    'PEAR_Packagefile_v2::toTgz(): tarball creation failed');
            }

            // add the package.xml version 1.0
            if ($pf1 !== null) {
                $pfgen = &$pf1->getDefaultGenerator();
                $packagexml1 = $pfgen->toPackageFile($where, PEAR_VALIDATE_PACKAGING, 'package.xml', true);
                if (!$tar->addModify(array($packagexml1), '', $where)) {
                    return $packager->raiseError(
                        'PEAR_Packagefile_v2::toTgz(): adding package.xml failed');
                }
            }

            return $dest_package;
        }
    }

    function toPackageFile($where = null, $state = PEAR_VALIDATE_NORMAL, $name = 'package.xml')
    {
        if (!$this->_packagefile->validate($state)) {
            return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: invalid package.xml',
                null, null, null, $this->_packagefile->getValidationWarnings());
        }

        if ($where === null) {
            if (!($where = System::mktemp(array('-d')))) {
                return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: mktemp failed');
            }
        } elseif (!@System::mkDir(array('-p', $where))) {
            return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: "' . $where . '" could' .
                ' not be created');
        }

        $newpkgfile = $where . DIRECTORY_SEPARATOR . $name;
        $np = @fopen($newpkgfile, 'wb');
        if (!$np) {
            return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: unable to save ' .
               "$name as $newpkgfile");
        }
        fwrite($np, $this->toXml($state));
        fclose($np);
        return $newpkgfile;
    }

    function &toV2()
    {
        return $this->_packagefile;
    }

    /**
     * Return an XML document based on the package info (as returned
     * by the PEAR_Common::infoFrom* methods).
     *
     * @return string XML data
     */
    function toXml($state = PEAR_VALIDATE_NORMAL, $options = array())
    {
        $this->_packagefile->setDate(date('Y-m-d'));
        $this->_packagefile->setTime(date('H:i:s'));
        if (!$this->_packagefile->validate($state)) {
            return false;
        }

        if (is_array($options)) {
            $this->options = array_merge($this->_defaultOptions, $options);
        } else {
            $this->options = $this->_defaultOptions;
        }

        $arr = $this->_packagefile->getArray();
        if (isset($arr['filelist'])) {
            unset($arr['filelist']);
        }

        if (isset($arr['_lastversion'])) {
            unset($arr['_lastversion']);
        }

        // Fix the notes a little bit
        if (isset($arr['notes'])) {
            // This trims out the indenting, needs fixing
            $arr['notes'] = "\n" . trim($arr['notes']) . "\n";
        }

        if (isset($arr['changelog']) && !empty($arr['changelog'])) {
            // Fix for inconsistency how the array is filled depending on the changelog release amount
            if (!isset($arr['changelog']['release'][0])) {
                $release = $arr['changelog']['release'];
                unset($arr['changelog']['release']);

                $arr['changelog']['release']    = array();
                $arr['changelog']['release'][0] = $release;
            }

            foreach (array_keys($arr['changelog']['release']) as $key) {
                $c =& $arr['changelog']['release'][$key];
                if (isset($c['notes'])) {
                    // This trims out the indenting, needs fixing
                    $c['notes'] = "\n" . trim($c['notes']) . "\n";
                }
            }
        }

        if ($state ^ PEAR_VALIDATE_PACKAGING && !isset($arr['bundle'])) {
            $use = $this->_recursiveXmlFilelist($arr['contents']['dir']['file']);
            unset($arr['contents']['dir']['file']);
            if (isset($use['dir'])) {
                $arr['contents']['dir']['dir'] = $use['dir'];
            }
            if (isset($use['file'])) {
                $arr['contents']['dir']['file'] = $use['file'];
            }
            $this->options['beautifyFilelist'] = true;
        }

        $arr['attribs']['packagerversion'] = '1.10.16';
        if ($this->serialize($arr, $options)) {
            return $this->_serializedData . "\n";
        }

        return false;
    }


    function _recursiveXmlFilelist($list)
    {
        $dirs = array();
        if (isset($list['attribs'])) {
            $file = $list['attribs']['name'];
            unset($list['attribs']['name']);
            $attributes = $list['attribs'];
            $this->_addDir($dirs, explode('/', dirname($file)), $file, $attributes);
        } else {
            foreach ($list as $a) {
                $file = $a['attribs']['name'];
                $attributes = $a['attribs'];
                unset($a['attribs']);
                $this->_addDir($dirs, explode('/', dirname($file)), $file, $attributes, $a);
            }
        }
        $this->_formatDir($dirs);
        $this->_deFormat($dirs);
        return $dirs;
    }

    function _addDir(&$dirs, $dir, $file = null, $attributes = null, $tasks = null)
    {
        if (!$tasks) {
            $tasks = array();
        }
        if ($dir == array() || $dir == array('.')) {
            $dirs['file'][basename($file)] = $tasks;
            $attributes['name'] = basename($file);
            $dirs['file'][basename($file)]['attribs'] = $attributes;
            return;
        }
        $curdir = array_shift($dir);
        if (!isset($dirs['dir'][$curdir])) {
            $dirs['dir'][$curdir] = array();
        }
        $this->_addDir($dirs['dir'][$curdir], $dir, $file, $attributes, $tasks);
    }

    function _formatDir(&$dirs)
    {
        if (!count($dirs)) {
            return array();
        }
        $newdirs = array();
        if (isset($dirs['dir'])) {
            $newdirs['dir'] = $dirs['dir'];
        }
        if (isset($dirs['file'])) {
            $newdirs['file'] = $dirs['file'];
        }
        $dirs = $newdirs;
        if (isset($dirs['dir'])) {
            uksort($dirs['dir'], 'strnatcasecmp');
            foreach ($dirs['dir'] as $dir => $contents) {
                $this->_formatDir($dirs['dir'][$dir]);
            }
        }
        if (isset($dirs['file'])) {
            uksort($dirs['file'], 'strnatcasecmp');
        };
    }

    function _deFormat(&$dirs)
    {
        if (!count($dirs)) {
            return array();
        }
        $newdirs = array();
        if (isset($dirs['dir'])) {
            foreach ($dirs['dir'] as $dir => $contents) {
                $newdir = array();
                $newdir['attribs']['name'] = $dir;
                $this->_deFormat($contents);
                foreach ($contents as $tag => $val) {
                    $newdir[$tag] = $val;
                }
                $newdirs['dir'][] = $newdir;
            }
            if (count($newdirs['dir']) == 1) {
                $newdirs['dir'] = $newdirs['dir'][0];
            }
        }
        if (isset($dirs['file'])) {
            foreach ($dirs['file'] as $name => $file) {
                $newdirs['file'][] = $file;
            }
            if (count($newdirs['file']) == 1) {
                $newdirs['file'] = $newdirs['file'][0];
            }
        }
        $dirs = $newdirs;
    }

    /**
    * reset all options to default options
    *
    * @access   public
    * @see      setOption(), XML_Unserializer()
    */
    function resetOptions()
    {
        $this->options = $this->_defaultOptions;
    }

   /**
    * set an option
    *
    * You can use this method if you do not want to set all options in the constructor
    *
    * @access   public
    * @see      resetOption(), XML_Serializer()
    */
    function setOption($name, $value)
    {
        $this->options[$name] = $value;
    }

   /**
    * sets several options at once
    *
    * You can use this method if you do not want to set all options in the constructor
    *
    * @access   public
    * @see      resetOption(), XML_Unserializer(), setOption()
    */
    function setOptions($options)
    {
        $this->options = array_merge($this->options, $options);
    }

   /**
    * serialize data
    *
    * @access   public
    * @param    mixed    $data data to serialize
    * @return   boolean  true on success, pear error on failure
    */
    function serialize($data, $options = null)
    {
        // if options have been specified, use them instead
        // of the previously defined ones
        if (is_array($options)) {
            $optionsBak = $this->options;
            if (isset($options['overrideOptions']) && $options['overrideOptions'] == true) {
                $this->options = array_merge($this->_defaultOptions, $options);
            } else {
                $this->options = array_merge($this->options, $options);
            }
        } else {
            $optionsBak = null;
        }

        //  start depth is zero
        $this->_tagDepth = 0;
        $this->_serializedData = '';
        // serialize an array
        if (is_array($data)) {
            $tagName = isset($this->options['rootName']) ? $this->options['rootName'] : 'array';
            $this->_serializedData .= $this->_serializeArray($data, $tagName, $this->options['rootAttributes']);
        }

        // add doctype declaration
        if ($this->options['addDoctype'] === true) {
            $this->_serializedData = XML_Util::getDoctypeDeclaration($tagName, $this->options['doctype'])
                                   . $this->options['linebreak']
                                   . $this->_serializedData;
        }

        //  build xml declaration
        if ($this->options['addDecl']) {
            $atts = array();
            $encoding = isset($this->options['encoding']) ? $this->options['encoding'] : null;
            $this->_serializedData = XML_Util::getXMLDeclaration('1.0', $encoding)
                                   . $this->options['linebreak']
                                   . $this->_serializedData;
        }


        if ($optionsBak !== null) {
            $this->options = $optionsBak;
        }

        return  true;
    }

   /**
    * get the result of the serialization
    *
    * @access public
    * @return string serialized XML
    */
    function getSerializedData()
    {
        if ($this->_serializedData === null) {
            return  $this->raiseError('No serialized data available. Use XML_Serializer::serialize() first.', XML_SERIALIZER_ERROR_NO_SERIALIZATION);
        }
        return $this->_serializedData;
    }

   /**
    * serialize any value
    *
    * This method checks for the type of the value and calls the appropriate method
    *
    * @access private
    * @param  mixed     $value
    * @param  string    $tagName
    * @param  array     $attributes
    * @return string
    */
    function _serializeValue($value, $tagName = null, $attributes = array())
    {
        if (is_array($value)) {
            $xml = $this->_serializeArray($value, $tagName, $attributes);
        } elseif (is_object($value)) {
            $xml = $this->_serializeObject($value, $tagName);
        } else {
            $tag = array(
                          'qname'      => $tagName,
                          'attributes' => $attributes,
                          'content'    => $value
                        );
            $xml = $this->_createXMLTag($tag);
        }
        return $xml;
    }

   /**
    * serialize an array
    *
    * @access   private
    * @param    array   $array       array to serialize
    * @param    string  $tagName     name of the root tag
    * @param    array   $attributes  attributes for the root tag
    * @return   string  $string      serialized data
    * @uses     XML_Util::isValidName() to check, whether key has to be substituted
    */
    function _serializeArray(&$array, $tagName = null, $attributes = array())
    {
        $_content = null;

        /**
         * check for special attributes
         */
        if ($this->options['attributesArray'] !== null) {
            if (isset($array[$this->options['attributesArray']])) {
                $attributes = $array[$this->options['attributesArray']];
                unset($array[$this->options['attributesArray']]);
            }
            /**
             * check for special content
             */
            if ($this->options['contentName'] !== null) {
                if (isset($array[$this->options['contentName']])) {
                    $_content = $array[$this->options['contentName']];
                    unset($array[$this->options['contentName']]);
                }
            }
        }

        /*
        * if mode is set to simpleXML, check whether
        * the array is associative or indexed
        */
        if (is_array($array) && $this->options['mode'] == 'simplexml') {
            $indexed = true;
            if (!count($array)) {
                $indexed = false;
            }
            foreach ($array as $key => $val) {
                if (!is_int($key)) {
                    $indexed = false;
                    break;
                }
            }

            if ($indexed && $this->options['mode'] == 'simplexml') {
                $string = '';
                foreach ($array as $key => $val) {
                    if ($this->options['beautifyFilelist'] && $tagName == 'dir') {
                        if (!isset($this->_curdir)) {
                            $this->_curdir = '';
                        }
                        $savedir = $this->_curdir;
                        if (isset($val['attribs'])) {
                            if ($val['attribs']['name'] == '/') {
                                $this->_curdir = '/';
                            } else {
                                if ($this->_curdir == '/') {
                                    $this->_curdir = '';
                                }
                                $this->_curdir .= '/' . $val['attribs']['name'];
                            }
                        }
                    }
                    $string .= $this->_serializeValue( $val, $tagName, $attributes);
                    if ($this->options['beautifyFilelist'] && $tagName == 'dir') {
                        $string .= ' <!-- ' . $this->_curdir . ' -->';
                        if (empty($savedir)) {
                            unset($this->_curdir);
                        } else {
                            $this->_curdir = $savedir;
                        }
                    }

                    $string .= $this->options['linebreak'];
                    // do indentation
                    if ($this->options['indent'] !== null && $this->_tagDepth > 0) {
                        $string .= str_repeat($this->options['indent'], $this->_tagDepth);
                    }
                }
                return rtrim($string);
            }
        }

        if ($this->options['scalarAsAttributes'] === true) {
            foreach ($array as $key => $value) {
                if (is_scalar($value) && (XML_Util::isValidName($key) === true)) {
                    unset($array[$key]);
                    $attributes[$this->options['prependAttributes'].$key] = $value;
                }
            }
        }

        // check for empty array => create empty tag
        if (empty($array)) {
            $tag = array(
                            'qname'      => $tagName,
                            'content'    => $_content,
                            'attributes' => $attributes
                        );

        } else {
            $this->_tagDepth++;
            $tmp = $this->options['linebreak'];
            foreach ($array as $key => $value) {
                // do indentation
                if ($this->options['indent'] !== null && $this->_tagDepth > 0) {
                    $tmp .= str_repeat($this->options['indent'], $this->_tagDepth);
                }

                // copy key
                $origKey = $key;
                // key cannot be used as tagname => use default tag
                $valid = XML_Util::isValidName($key);
                if (PEAR::isError($valid)) {
                    if ($this->options['classAsTagName'] && is_object($value)) {
                        $key = get_class($value);
                    } else {
                        $key = $this->options['defaultTagName'];
                    }
                }
                $atts = array();
                if ($this->options['typeHints'] === true) {
                    $atts[$this->options['typeAttribute']] = gettype($value);
                    if ($key !== $origKey) {
                        $atts[$this->options['keyAttribute']] = (string)$origKey;
                    }

                }
                if ($this->options['beautifyFilelist'] && $key == 'dir') {
                    if (!isset($this->_curdir)) {
                        $this->_curdir = '';
                    }
                    $savedir = $this->_curdir;
                    if (isset($value['attribs'])) {
                        if ($value['attribs']['name'] == '/') {
                            $this->_curdir = '/';
                        } else {
                            $this->_curdir .= '/' . $value['attribs']['name'];
                        }
                    }
                }

                if (is_string($value) && $value && ($value[strlen($value) - 1] == "\n")) {
                    $value .= str_repeat($this->options['indent'], $this->_tagDepth);
                }
                $tmp .= $this->_createXMLTag(array(
                                                    'qname'      => $key,
                                                    'attributes' => $atts,
                                                    'content'    => $value )
                                            );
                if ($this->options['beautifyFilelist'] && $key == 'dir') {
                    if (isset($value['attribs'])) {
                        $tmp .= ' <!-- ' . $this->_curdir . ' -->';
                        if (empty($savedir)) {
                            unset($this->_curdir);
                        } else {
                            $this->_curdir = $savedir;
                        }
                    }
                }
                $tmp .= $this->options['linebreak'];
            }

            $this->_tagDepth--;
            if ($this->options['indent']!==null && $this->_tagDepth>0) {
                $tmp .= str_repeat($this->options['indent'], $this->_tagDepth);
            }

            if (trim($tmp) === '') {
                $tmp = null;
            }

            $tag = array(
                'qname'      => $tagName,
                'content'    => $tmp,
                'attributes' => $attributes
            );
        }
        if ($this->options['typeHints'] === true) {
            if (!isset($tag['attributes'][$this->options['typeAttribute']])) {
                $tag['attributes'][$this->options['typeAttribute']] = 'array';
            }
        }

        $string = $this->_createXMLTag($tag, false);
        return $string;
    }

   /**
    * create a tag from an array
    * this method awaits an array in the following format
    * array(
    *       'qname'        => $tagName,
    *       'attributes'   => array(),
    *       'content'      => $content,      // optional
    *       'namespace'    => $namespace     // optional
    *       'namespaceUri' => $namespaceUri  // optional
    *   )
    *
    * @access   private
    * @param    array   $tag tag definition
    * @param    boolean $replaceEntities whether to replace XML entities in content or not
    * @return   string  $string XML tag
    */
    function _createXMLTag($tag, $replaceEntities = true)
    {
        if ($this->options['indentAttributes'] !== false) {
            $multiline = true;
            $indent    = str_repeat($this->options['indent'], $this->_tagDepth);

            if ($this->options['indentAttributes'] == '_auto') {
                $indent .= str_repeat(' ', (strlen($tag['qname'])+2));

            } else {
                $indent .= $this->options['indentAttributes'];
            }
        } else {
            $indent = $multiline = false;
        }

        if (is_array($tag['content'])) {
            if (empty($tag['content'])) {
                $tag['content'] = '';
            }
        } elseif(is_scalar($tag['content']) && (string)$tag['content'] == '') {
            $tag['content'] = '';
        }

        if (is_scalar($tag['content']) || is_null($tag['content'])) {
            if ($replaceEntities === true) {
                $replaceEntities = XML_UTIL_ENTITIES_XML;
            }

            $tag = XML_Util::createTagFromArray($tag, $replaceEntities, $multiline, $indent, $this->options['linebreak']);
        } elseif (is_array($tag['content'])) {
            $tag = $this->_serializeArray($tag['content'], $tag['qname'], $tag['attributes']);
        } elseif (is_object($tag['content'])) {
            $tag = $this->_serializeObject($tag['content'], $tag['qname'], $tag['attributes']);
        } elseif (is_resource($tag['content'])) {
            settype($tag['content'], 'string');
            $tag = XML_Util::createTagFromArray($tag, $replaceEntities);
        }
        return  $tag;
    }
}
PKq�Z`�=����!PEAR/PackageFile/Generator/v1.phpnu�[���<?php
/**
 * package.xml generation class, package.xml version 1.0
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a1
 */
/**
 * needed for PEAR_VALIDATE_* constants
 */
require_once 'PEAR/Validate.php';
require_once 'System.php';
require_once 'PEAR/PackageFile/v2.php';
/**
 * This class converts a PEAR_PackageFile_v1 object into any output format.
 *
 * Supported output formats include array, XML string, and a PEAR_PackageFile_v2
 * object, for converting package.xml 1.0 into package.xml 2.0 with no sweat.
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 */
class PEAR_PackageFile_Generator_v1
{
    /**
     * @var PEAR_PackageFile_v1
     */
    var $_packagefile;
    function __construct(&$packagefile)
    {
        $this->_packagefile = &$packagefile;
    }

    function getPackagerVersion()
    {
        return '1.10.16';
    }

    /**
     * @param PEAR_Packager
     * @param bool if true, a .tgz is written, otherwise a .tar is written
     * @param string|null directory in which to save the .tgz
     * @return string|PEAR_Error location of package or error object
     */
    function toTgz(&$packager, $compress = true, $where = null)
    {
        require_once 'Archive/Tar.php';
        if ($where === null) {
            if (!($where = System::mktemp(array('-d')))) {
                return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: mktemp failed');
            }
        } elseif (!@System::mkDir(array('-p', $where))) {
            return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: "' . $where . '" could' .
                ' not be created');
        }
        if (file_exists($where . DIRECTORY_SEPARATOR . 'package.xml') &&
              !is_file($where . DIRECTORY_SEPARATOR . 'package.xml')) {
            return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: unable to save package.xml as' .
                ' "' . $where . DIRECTORY_SEPARATOR . 'package.xml"');
        }
        if (!$this->_packagefile->validate(PEAR_VALIDATE_PACKAGING)) {
            return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: invalid package file');
        }
        $pkginfo = $this->_packagefile->getArray();
        $ext = $compress ? '.tgz' : '.tar';
        $pkgver = $pkginfo['package'] . '-' . $pkginfo['version'];
        $dest_package = getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext;
        if (file_exists(getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext) &&
              !is_file(getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext)) {
            return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: cannot create tgz file "' .
                getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext . '"');
        }
        if ($pkgfile = $this->_packagefile->getPackageFile()) {
            $pkgdir = dirname(realpath($pkgfile));
            $pkgfile = basename($pkgfile);
        } else {
            return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: package file object must ' .
                'be created from a real file');
        }
        // {{{ Create the package file list
        $filelist = array();
        $i = 0;

        foreach ($this->_packagefile->getFilelist() as $fname => $atts) {
            $file = $pkgdir . DIRECTORY_SEPARATOR . $fname;
            if (!file_exists($file)) {
                return PEAR::raiseError("File does not exist: $fname");
            } else {
                $filelist[$i++] = $file;
                if (!isset($atts['md5sum'])) {
                    $this->_packagefile->setFileAttribute($fname, 'md5sum', md5_file($file));
                }
                $packager->log(2, "Adding file $fname");
            }
        }
        // }}}
        $packagexml = $this->toPackageFile($where, PEAR_VALIDATE_PACKAGING, 'package.xml', true);
        if ($packagexml) {
            $tar = new Archive_Tar($dest_package, $compress);
            $tar->setErrorHandling(PEAR_ERROR_RETURN); // XXX Don't print errors
            // ----- Creates with the package.xml file
            $ok = $tar->createModify(array($packagexml), '', $where);
            if (PEAR::isError($ok)) {
                return $ok;
            } elseif (!$ok) {
                return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: tarball creation failed');
            }
            // ----- Add the content of the package
            if (!$tar->addModify($filelist, $pkgver, $pkgdir)) {
                return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: tarball creation failed');
            }
            return $dest_package;
        }
    }

    /**
     * @param string|null directory to place the package.xml in, or null for a temporary dir
     * @param int one of the PEAR_VALIDATE_* constants
     * @param string name of the generated file
     * @param bool if true, then no analysis will be performed on role="php" files
     * @return string|PEAR_Error path to the created file on success
     */
    function toPackageFile($where = null, $state = PEAR_VALIDATE_NORMAL, $name = 'package.xml',
                           $nofilechecking = false)
    {
        if (!$this->_packagefile->validate($state, $nofilechecking)) {
            return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: invalid package.xml',
                null, null, null, $this->_packagefile->getValidationWarnings());
        }
        if ($where === null) {
            if (!($where = System::mktemp(array('-d')))) {
                return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: mktemp failed');
            }
        } elseif (!@System::mkDir(array('-p', $where))) {
            return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: "' . $where . '" could' .
                ' not be created');
        }
        $newpkgfile = $where . DIRECTORY_SEPARATOR . $name;
        $np = @fopen($newpkgfile, 'wb');
        if (!$np) {
            return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: unable to save ' .
               "$name as $newpkgfile");
        }
        fwrite($np, $this->toXml($state, true));
        fclose($np);
        return $newpkgfile;
    }

    /**
     * fix both XML encoding to be UTF8, and replace standard XML entities < > " & '
     *
     * @param string $string
     * @return string
     * @access private
     */
    function _fixXmlEncoding($string)
    {
        return strtr($string, array(
                                          '&'  => '&amp;',
                                          '>'  => '&gt;',
                                          '<'  => '&lt;',
                                          '"'  => '&quot;',
                                          '\'' => '&apos;' ));
    }

    /**
     * Return an XML document based on the package info (as returned
     * by the PEAR_Common::infoFrom* methods).
     *
     * @return string XML data
     */
    function toXml($state = PEAR_VALIDATE_NORMAL, $nofilevalidation = false)
    {
        $this->_packagefile->setDate(date('Y-m-d'));
        if (!$this->_packagefile->validate($state, $nofilevalidation)) {
            return false;
        }
        $pkginfo = $this->_packagefile->getArray();
        static $maint_map = array(
            "handle" => "user",
            "name" => "name",
            "email" => "email",
            "role" => "role",
            );
        $ret = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
        $ret .= "<!DOCTYPE package SYSTEM \"http://pear.php.net/dtd/package-1.0\">\n";
        $ret .= "<package version=\"1.0\" packagerversion=\"1.10.16\">\n" .
" <name>$pkginfo[package]</name>";
        if (isset($pkginfo['extends'])) {
            $ret .= "\n<extends>$pkginfo[extends]</extends>";
        }
        $ret .=
 "\n <summary>".$this->_fixXmlEncoding($pkginfo['summary'])."</summary>\n" .
" <description>".trim($this->_fixXmlEncoding($pkginfo['description']))."\n </description>\n" .
" <maintainers>\n";
        foreach ($pkginfo['maintainers'] as $maint) {
            $ret .= "  <maintainer>\n";
            foreach ($maint_map as $idx => $elm) {
                $ret .= "   <$elm>";
                $ret .= $this->_fixXmlEncoding($maint[$idx]);
                $ret .= "</$elm>\n";
            }
            $ret .= "  </maintainer>\n";
        }
        $ret .= "  </maintainers>\n";
        $ret .= $this->_makeReleaseXml($pkginfo, false, $state);
        if (isset($pkginfo['changelog']) && count($pkginfo['changelog']) > 0) {
            $ret .= " <changelog>\n";
            foreach ($pkginfo['changelog'] as $oldrelease) {
                $ret .= $this->_makeReleaseXml($oldrelease, true);
            }
            $ret .= " </changelog>\n";
        }
        $ret .= "</package>\n";
        return $ret;
    }

    // }}}
    // {{{ _makeReleaseXml()

    /**
     * Generate part of an XML description with release information.
     *
     * @param array  $pkginfo    array with release information
     * @param bool   $changelog  whether the result will be in a changelog element
     *
     * @return string XML data
     *
     * @access private
     */
    function _makeReleaseXml($pkginfo, $changelog = false, $state = PEAR_VALIDATE_NORMAL)
    {
        // XXX QUOTE ENTITIES IN PCDATA, OR EMBED IN CDATA BLOCKS!!
        $indent = $changelog ? "  " : "";
        $ret = "$indent <release>\n";
        if (!empty($pkginfo['version'])) {
            $ret .= "$indent  <version>$pkginfo[version]</version>\n";
        }
        if (!empty($pkginfo['release_date'])) {
            $ret .= "$indent  <date>$pkginfo[release_date]</date>\n";
        }
        if (!empty($pkginfo['release_license'])) {
            $ret .= "$indent  <license>$pkginfo[release_license]</license>\n";
        }
        if (!empty($pkginfo['release_state'])) {
            $ret .= "$indent  <state>$pkginfo[release_state]</state>\n";
        }
        if (!empty($pkginfo['release_notes'])) {
            $ret .= "$indent  <notes>".trim($this->_fixXmlEncoding($pkginfo['release_notes']))
            ."\n$indent  </notes>\n";
        }
        if (!empty($pkginfo['release_warnings'])) {
            $ret .= "$indent  <warnings>".$this->_fixXmlEncoding($pkginfo['release_warnings'])."</warnings>\n";
        }
        if (isset($pkginfo['release_deps']) && sizeof($pkginfo['release_deps']) > 0) {
            $ret .= "$indent  <deps>\n";
            foreach ($pkginfo['release_deps'] as $dep) {
                $ret .= "$indent   <dep type=\"$dep[type]\" rel=\"$dep[rel]\"";
                if (isset($dep['version'])) {
                    $ret .= " version=\"$dep[version]\"";
                }
                if (isset($dep['optional'])) {
                    $ret .= " optional=\"$dep[optional]\"";
                }
                if (isset($dep['name'])) {
                    $ret .= ">$dep[name]</dep>\n";
                } else {
                    $ret .= "/>\n";
                }
            }
            $ret .= "$indent  </deps>\n";
        }
        if (isset($pkginfo['configure_options'])) {
            $ret .= "$indent  <configureoptions>\n";
            foreach ($pkginfo['configure_options'] as $c) {
                $ret .= "$indent   <configureoption name=\"".
                    $this->_fixXmlEncoding($c['name']) . "\"";
                if (isset($c['default'])) {
                    $ret .= " default=\"" . $this->_fixXmlEncoding($c['default']) . "\"";
                }
                $ret .= " prompt=\"" . $this->_fixXmlEncoding($c['prompt']) . "\"";
                $ret .= "/>\n";
            }
            $ret .= "$indent  </configureoptions>\n";
        }
        if (isset($pkginfo['provides'])) {
            foreach ($pkginfo['provides'] as $key => $what) {
                $ret .= "$indent  <provides type=\"$what[type]\" ";
                $ret .= "name=\"$what[name]\" ";
                if (isset($what['extends'])) {
                    $ret .= "extends=\"$what[extends]\" ";
                }
                $ret .= "/>\n";
            }
        }
        if (isset($pkginfo['filelist'])) {
            $ret .= "$indent  <filelist>\n";
            if ($state ^ PEAR_VALIDATE_PACKAGING) {
                $ret .= $this->recursiveXmlFilelist($pkginfo['filelist']);
            } else {
                foreach ($pkginfo['filelist'] as $file => $fa) {
                    if (!isset($fa['role'])) {
                        $fa['role'] = '';
                    }
                    $ret .= "$indent   <file role=\"$fa[role]\"";
                    if (isset($fa['baseinstalldir'])) {
                        $ret .= ' baseinstalldir="' .
                            $this->_fixXmlEncoding($fa['baseinstalldir']) . '"';
                    }
                    if (isset($fa['md5sum'])) {
                        $ret .= " md5sum=\"$fa[md5sum]\"";
                    }
                    if (isset($fa['platform'])) {
                        $ret .= " platform=\"$fa[platform]\"";
                    }
                    if (!empty($fa['install-as'])) {
                        $ret .= ' install-as="' .
                            $this->_fixXmlEncoding($fa['install-as']) . '"';
                    }
                    $ret .= ' name="' . $this->_fixXmlEncoding($file) . '"';
                    if (empty($fa['replacements'])) {
                        $ret .= "/>\n";
                    } else {
                        $ret .= ">\n";
                        foreach ($fa['replacements'] as $r) {
                            $ret .= "$indent    <replace";
                            foreach ($r as $k => $v) {
                                $ret .= " $k=\"" . $this->_fixXmlEncoding($v) .'"';
                            }
                            $ret .= "/>\n";
                        }
                        $ret .= "$indent   </file>\n";
                    }
                }
            }
            $ret .= "$indent  </filelist>\n";
        }
        $ret .= "$indent </release>\n";
        return $ret;
    }

    /**
     * @param array
     * @access protected
     */
    function recursiveXmlFilelist($list)
    {
        $this->_dirs = array();
        foreach ($list as $file => $attributes) {
            $this->_addDir($this->_dirs, explode('/', dirname($file)), $file, $attributes);
        }
        return $this->_formatDir($this->_dirs);
    }

    /**
     * @param array
     * @param array
     * @param string|null
     * @param array|null
     * @access private
     */
    function _addDir(&$dirs, $dir, $file = null, $attributes = null)
    {
        if ($dir == array() || $dir == array('.')) {
            $dirs['files'][basename($file)] = $attributes;
            return;
        }
        $curdir = array_shift($dir);
        if (!isset($dirs['dirs'][$curdir])) {
            $dirs['dirs'][$curdir] = array();
        }
        $this->_addDir($dirs['dirs'][$curdir], $dir, $file, $attributes);
    }

    /**
     * @param array
     * @param string
     * @param string
     * @access private
     */
    function _formatDir($dirs, $indent = '', $curdir = '')
    {
        $ret = '';
        if (!count($dirs)) {
            return '';
        }
        if (isset($dirs['dirs'])) {
            uksort($dirs['dirs'], 'strnatcasecmp');
            foreach ($dirs['dirs'] as $dir => $contents) {
                $usedir = "$curdir/$dir";
                $ret .= "$indent   <dir name=\"$dir\">\n";
                $ret .= $this->_formatDir($contents, "$indent ", $usedir);
                $ret .= "$indent   </dir> <!-- $usedir -->\n";
            }
        }
        if (isset($dirs['files'])) {
            uksort($dirs['files'], 'strnatcasecmp');
            foreach ($dirs['files'] as $file => $attribs) {
                $ret .= $this->_formatFile($file, $attribs, $indent);
            }
        }
        return $ret;
    }

    /**
     * @param string
     * @param array
     * @param string
     * @access private
     */
    function _formatFile($file, $attributes, $indent)
    {
        $ret = "$indent   <file role=\"$attributes[role]\"";
        if (isset($attributes['baseinstalldir'])) {
            $ret .= ' baseinstalldir="' .
                $this->_fixXmlEncoding($attributes['baseinstalldir']) . '"';
        }
        if (isset($attributes['md5sum'])) {
            $ret .= " md5sum=\"$attributes[md5sum]\"";
        }
        if (isset($attributes['platform'])) {
            $ret .= " platform=\"$attributes[platform]\"";
        }
        if (!empty($attributes['install-as'])) {
            $ret .= ' install-as="' .
                $this->_fixXmlEncoding($attributes['install-as']) . '"';
        }
        $ret .= ' name="' . $this->_fixXmlEncoding($file) . '"';
        if (empty($attributes['replacements'])) {
            $ret .= "/>\n";
        } else {
            $ret .= ">\n";
            foreach ($attributes['replacements'] as $r) {
                $ret .= "$indent    <replace";
                foreach ($r as $k => $v) {
                    $ret .= " $k=\"" . $this->_fixXmlEncoding($v) .'"';
                }
                $ret .= "/>\n";
            }
            $ret .= "$indent   </file>\n";
        }
        return $ret;
    }

    // {{{ _unIndent()

    /**
     * Unindent given string (?)
     *
     * @param string $str The string that has to be unindented.
     * @return string
     * @access private
     */
    function _unIndent($str)
    {
        // remove leading newlines
        $str = preg_replace('/^[\r\n]+/', '', $str);
        // find whitespace at the beginning of the first line
        $indent_len = strspn($str, " \t");
        $indent = substr($str, 0, $indent_len);
        $data = '';
        // remove the same amount of whitespace from following lines
        foreach (explode("\n", $str) as $line) {
            if (substr($line, 0, $indent_len) == $indent) {
                $data .= substr($line, $indent_len) . "\n";
            }
        }
        return $data;
    }

    /**
     * @return array
     */
    function dependenciesToV2()
    {
        $arr = array();
        $this->_convertDependencies2_0($arr);
        return $arr['dependencies'];
    }

    /**
     * Convert a package.xml version 1.0 into version 2.0
     *
     * Note that this does a basic conversion, to allow more advanced
     * features like bundles and multiple releases
     * @param string the classname to instantiate and return.  This must be
     *               PEAR_PackageFile_v2 or a descendant
     * @param boolean if true, only valid, deterministic package.xml 1.0 as defined by the
     *                strictest parameters will be converted
     * @return PEAR_PackageFile_v2|PEAR_Error
     */
    function &toV2($class = 'PEAR_PackageFile_v2', $strict = false)
    {
        if ($strict) {
            if (!$this->_packagefile->validate()) {
                $a = PEAR::raiseError('invalid package.xml version 1.0 cannot be converted' .
                    ' to version 2.0', null, null, null,
                    $this->_packagefile->getValidationWarnings(true));
                return $a;
            }
        }

        $arr = array(
            'attribs' => array(
                             'version' => '2.0',
                             'xmlns' => 'http://pear.php.net/dtd/package-2.0',
                             'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0',
                             'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
                             'xsi:schemaLocation' => "http://pear.php.net/dtd/tasks-1.0\n" .
"http://pear.php.net/dtd/tasks-1.0.xsd\n" .
"http://pear.php.net/dtd/package-2.0\n" .
'http://pear.php.net/dtd/package-2.0.xsd',
                         ),
            'name' => $this->_packagefile->getPackage(),
            'channel' => 'pear.php.net',
        );
        $arr['summary'] = $this->_packagefile->getSummary();
        $arr['description'] = $this->_packagefile->getDescription();
        $maintainers = $this->_packagefile->getMaintainers();
        foreach ($maintainers as $maintainer) {
            if ($maintainer['role'] != 'lead') {
                continue;
            }
            $new = array(
                'name' => $maintainer['name'],
                'user' => $maintainer['handle'],
                'email' => $maintainer['email'],
                'active' => 'yes',
            );
            $arr['lead'][] = $new;
        }

        if (!isset($arr['lead'])) { // some people... you know?
            $arr['lead'] = array(
                'name' => 'unknown',
                'user' => 'unknown',
                'email' => 'noleadmaintainer@example.com',
                'active' => 'no',
            );
        }

        if (count($arr['lead']) == 1) {
            $arr['lead'] = $arr['lead'][0];
        }

        foreach ($maintainers as $maintainer) {
            if ($maintainer['role'] == 'lead') {
                continue;
            }
            $new = array(
                'name' => $maintainer['name'],
                'user' => $maintainer['handle'],
                'email' => $maintainer['email'],
                'active' => 'yes',
            );
            $arr[$maintainer['role']][] = $new;
        }

        if (isset($arr['developer']) && count($arr['developer']) == 1) {
            $arr['developer'] = $arr['developer'][0];
        }

        if (isset($arr['contributor']) && count($arr['contributor']) == 1) {
            $arr['contributor'] = $arr['contributor'][0];
        }

        if (isset($arr['helper']) && count($arr['helper']) == 1) {
            $arr['helper'] = $arr['helper'][0];
        }

        $arr['date'] = $this->_packagefile->getDate();
        $arr['version'] =
            array(
                'release' => $this->_packagefile->getVersion(),
                'api' => $this->_packagefile->getVersion(),
            );
        $arr['stability'] =
            array(
                'release' => $this->_packagefile->getState(),
                'api' => $this->_packagefile->getState(),
            );
        $licensemap =
            array(
                'php' => 'http://www.php.net/license',
                'php license' => 'http://www.php.net/license',
                'lgpl' => 'http://www.gnu.org/copyleft/lesser.html',
                'bsd' => 'http://www.opensource.org/licenses/bsd-license.php',
                'bsd style' => 'http://www.opensource.org/licenses/bsd-license.php',
                'bsd-style' => 'http://www.opensource.org/licenses/bsd-license.php',
                'mit' => 'http://www.opensource.org/licenses/mit-license.php',
                'gpl' => 'http://www.gnu.org/copyleft/gpl.html',
                'apache' => 'http://www.opensource.org/licenses/apache2.0.php'
            );

        if (isset($licensemap[strtolower($this->_packagefile->getLicense())])) {
            $arr['license'] = array(
                'attribs' => array('uri' =>
                    $licensemap[strtolower($this->_packagefile->getLicense())]),
                '_content' => $this->_packagefile->getLicense()
                );
        } else {
            // don't use bogus uri
            $arr['license'] = $this->_packagefile->getLicense();
        }

        $arr['notes'] = $this->_packagefile->getNotes();
        $temp = array();
        $arr['contents'] = $this->_convertFilelist2_0($temp);
        $this->_convertDependencies2_0($arr);
        $release = ($this->_packagefile->getConfigureOptions() || $this->_isExtension) ?
            'extsrcrelease' : 'phprelease';
        if ($release == 'extsrcrelease') {
            $arr['channel'] = 'pecl.php.net';
            $arr['providesextension'] = $arr['name']; // assumption
        }

        $arr[$release] = array();
        if ($this->_packagefile->getConfigureOptions()) {
            $arr[$release]['configureoption'] = $this->_packagefile->getConfigureOptions();
            foreach ($arr[$release]['configureoption'] as $i => $opt) {
                $arr[$release]['configureoption'][$i] = array('attribs' => $opt);
            }
            if (count($arr[$release]['configureoption']) == 1) {
                $arr[$release]['configureoption'] = $arr[$release]['configureoption'][0];
            }
        }

        $this->_convertRelease2_0($arr[$release], $temp);
        if ($release == 'extsrcrelease' && count($arr[$release]) > 1) {
            // multiple extsrcrelease tags added in PEAR 1.4.1
            $arr['dependencies']['required']['pearinstaller']['min'] = '1.4.1';
        }

        if ($cl = $this->_packagefile->getChangelog()) {
            foreach ($cl as $release) {
                $rel = array();
                $rel['version'] =
                    array(
                        'release' => $release['version'],
                        'api' => $release['version'],
                    );
                if (!isset($release['release_state'])) {
                    $release['release_state'] = 'stable';
                }

                $rel['stability'] =
                    array(
                        'release' => $release['release_state'],
                        'api' => $release['release_state'],
                    );
                if (isset($release['release_date'])) {
                    $rel['date'] = $release['release_date'];
                } else {
                    $rel['date'] = date('Y-m-d');
                }

                if (isset($release['release_license'])) {
                    if (isset($licensemap[strtolower($release['release_license'])])) {
                        $uri = $licensemap[strtolower($release['release_license'])];
                    } else {
                        $uri = 'http://www.example.com';
                    }
                    $rel['license'] = array(
                            'attribs' => array('uri' => $uri),
                            '_content' => $release['release_license']
                        );
                } else {
                    $rel['license'] = $arr['license'];
                }

                if (!isset($release['release_notes'])) {
                    $release['release_notes'] = 'no release notes';
                }

                $rel['notes'] = $release['release_notes'];
                $arr['changelog']['release'][] = $rel;
            }
        }

        $ret = new $class;
        $ret->setConfig($this->_packagefile->_config);
        if (isset($this->_packagefile->_logger) && is_object($this->_packagefile->_logger)) {
            $ret->setLogger($this->_packagefile->_logger);
        }

        $ret->fromArray($arr);
        return $ret;
    }

    /**
     * @param array
     * @param bool
     * @access private
     */
    function _convertDependencies2_0(&$release, $internal = false)
    {
        $peardep = array('pearinstaller' =>
            array('min' => '1.4.0b1')); // this is a lot safer
        $required = $optional = array();
        $release['dependencies'] = array('required' => array());
        if ($this->_packagefile->hasDeps()) {
            foreach ($this->_packagefile->getDeps() as $dep) {
                if (!isset($dep['optional']) || $dep['optional'] == 'no') {
                    $required[] = $dep;
                } else {
                    $optional[] = $dep;
                }
            }
            foreach (array('required', 'optional') as $arr) {
                $deps = array();
                foreach ($$arr as $dep) {
                    // organize deps by dependency type and name
                    if (!isset($deps[$dep['type']])) {
                        $deps[$dep['type']] = array();
                    }
                    if (isset($dep['name'])) {
                        $deps[$dep['type']][$dep['name']][] = $dep;
                    } else {
                        $deps[$dep['type']][] = $dep;
                    }
                }
                do {
                    if (isset($deps['php'])) {
                        $php = array();
                        if (count($deps['php']) > 1) {
                            $php = $this->_processPhpDeps($deps['php']);
                        } else {
                            if (!isset($deps['php'][0])) {
                                // Buggy versions
                                $key = key($deps['php']);
                                $info = current($deps['php']);
                                $deps['php'] = array($info[0]);
                            }
                            $php = $this->_processDep($deps['php'][0]);
                            if (!$php) {
                                break; // poor mans throw
                            }
                        }
                        $release['dependencies'][$arr]['php'] = $php;
                    }
                } while (false);
                do {
                    if (isset($deps['pkg'])) {
                        $pkg = array();
                        $pkg = $this->_processMultipleDepsName($deps['pkg']);
                        if (!$pkg) {
                            break; // poor mans throw
                        }
                        $release['dependencies'][$arr]['package'] = $pkg;
                    }
                } while (false);
                do {
                    if (isset($deps['ext'])) {
                        $pkg = array();
                        $pkg = $this->_processMultipleDepsName($deps['ext']);
                        $release['dependencies'][$arr]['extension'] = $pkg;
                    }
                } while (false);
                // skip sapi - it's not supported so nobody will have used it
                // skip os - it's not supported in 1.0
            }
        }
        if (isset($release['dependencies']['required'])) {
            $release['dependencies']['required'] =
                array_merge($peardep, $release['dependencies']['required']);
        } else {
            $release['dependencies']['required'] = $peardep;
        }
        if (!isset($release['dependencies']['required']['php'])) {
            $release['dependencies']['required']['php'] =
                array('min' => '4.0.0');
        }
        $order = array();
        $bewm = $release['dependencies']['required'];
        $order['php'] = $bewm['php'];
        $order['pearinstaller'] = $bewm['pearinstaller'];
        isset($bewm['package']) ? $order['package'] = $bewm['package'] :0;
        isset($bewm['extension']) ? $order['extension'] = $bewm['extension'] :0;
        $release['dependencies']['required'] = $order;
    }

    /**
     * @param array
     * @access private
     */
    function _convertFilelist2_0(&$package)
    {
        $ret = array('dir' =>
                    array(
                        'attribs' => array('name' => '/'),
                        'file' => array()
                        )
                    );
        $package['platform'] =
        $package['install-as'] = array();
        $this->_isExtension = false;
        foreach ($this->_packagefile->getFilelist() as $name => $file) {
            $file['name'] = $name;
            if (isset($file['role']) && $file['role'] == 'src') {
                $this->_isExtension = true;
            }
            if (isset($file['replacements'])) {
                $repl = $file['replacements'];
                unset($file['replacements']);
            } else {
                unset($repl);
            }
            if (isset($file['install-as'])) {
                $package['install-as'][$name] = $file['install-as'];
                unset($file['install-as']);
            }
            if (isset($file['platform'])) {
                $package['platform'][$name] = $file['platform'];
                unset($file['platform']);
            }
            $file = array('attribs' => $file);
            if (isset($repl)) {
                foreach ($repl as $replace ) {
                    $file['tasks:replace'][] = array('attribs' => $replace);
                }
                if (count($repl) == 1) {
                    $file['tasks:replace'] = $file['tasks:replace'][0];
                }
            }
            $ret['dir']['file'][] = $file;
        }
        return $ret;
    }

    /**
     * Post-process special files with install-as/platform attributes and
     * make the release tag.
     *
     * This complex method follows this work-flow to create the release tags:
     *
     * <pre>
     * - if any install-as/platform exist, create a generic release and fill it with
     *   o <install as=..> tags for <file name=... install-as=...>
     *   o <install as=..> tags for <file name=... platform=!... install-as=..>
     *   o <ignore> tags for <file name=... platform=...>
     *   o <ignore> tags for <file name=... platform=... install-as=..>
     * - create a release for each platform encountered and fill with
     *   o <install as..> tags for <file name=... install-as=...>
     *   o <install as..> tags for <file name=... platform=this platform install-as=..>
     *   o <install as..> tags for <file name=... platform=!other platform install-as=..>
     *   o <ignore> tags for <file name=... platform=!this platform>
     *   o <ignore> tags for <file name=... platform=other platform>
     *   o <ignore> tags for <file name=... platform=other platform install-as=..>
     *   o <ignore> tags for <file name=... platform=!this platform install-as=..>
     * </pre>
     *
     * It does this by accessing the $package parameter, which contains an array with
     * indices:
     *
     *  - platform: mapping of file => OS the file should be installed on
     *  - install-as: mapping of file => installed name
     *  - osmap: mapping of OS => list of files that should be installed
     *    on that OS
     *  - notosmap: mapping of OS => list of files that should not be
     *    installed on that OS
     *
     * @param array
     * @param array
     * @access private
     */
    function _convertRelease2_0(&$release, $package)
    {
        //- if any install-as/platform exist, create a generic release and fill it with
        if (count($package['platform']) || count($package['install-as'])) {
            $generic = array();
            $genericIgnore = array();
            foreach ($package['install-as'] as $file => $as) {
                //o <install as=..> tags for <file name=... install-as=...>
                if (!isset($package['platform'][$file])) {
                    $generic[] = $file;
                    continue;
                }
                //o <install as=..> tags for <file name=... platform=!... install-as=..>
                if (isset($package['platform'][$file]) &&
                      $package['platform'][$file][0] == '!') {
                    $generic[] = $file;
                    continue;
                }
                //o <ignore> tags for <file name=... platform=... install-as=..>
                if (isset($package['platform'][$file]) &&
                      $package['platform'][$file][0] != '!') {
                    $genericIgnore[] = $file;
                    continue;
                }
            }
            foreach ($package['platform'] as $file => $platform) {
                if (isset($package['install-as'][$file])) {
                    continue;
                }
                if ($platform[0] != '!') {
                    //o <ignore> tags for <file name=... platform=...>
                    $genericIgnore[] = $file;
                }
            }
            if (count($package['platform'])) {
                $oses = $notplatform = $platform = array();
                foreach ($package['platform'] as $file => $os) {
                    // get a list of oses
                    if ($os[0] == '!') {
                        if (isset($oses[substr($os, 1)])) {
                            continue;
                        }
                        $oses[substr($os, 1)] = count($oses);
                    } else {
                        if (isset($oses[$os])) {
                            continue;
                        }
                        $oses[$os] = count($oses);
                    }
                }
                //- create a release for each platform encountered and fill with
                foreach ($oses as $os => $releaseNum) {
                    $release[$releaseNum]['installconditions']['os']['name'] = $os;
                    $release[$releaseNum]['filelist'] = array('install' => array(),
                        'ignore' => array());
                    foreach ($package['install-as'] as $file => $as) {
                        //o <install as=..> tags for <file name=... install-as=...>
                        if (!isset($package['platform'][$file])) {
                            $release[$releaseNum]['filelist']['install'][] =
                                array(
                                    'attribs' => array(
                                        'name' => $file,
                                        'as' => $as,
                                    ),
                                );
                            continue;
                        }
                        //o <install as..> tags for
                        //  <file name=... platform=this platform install-as=..>
                        if (isset($package['platform'][$file]) &&
                              $package['platform'][$file] == $os) {
                            $release[$releaseNum]['filelist']['install'][] =
                                array(
                                    'attribs' => array(
                                        'name' => $file,
                                        'as' => $as,
                                    ),
                                );
                            continue;
                        }
                        //o <install as..> tags for
                        //  <file name=... platform=!other platform install-as=..>
                        if (isset($package['platform'][$file]) &&
                              $package['platform'][$file] != "!$os" &&
                              $package['platform'][$file][0] == '!') {
                            $release[$releaseNum]['filelist']['install'][] =
                                array(
                                    'attribs' => array(
                                        'name' => $file,
                                        'as' => $as,
                                    ),
                                );
                            continue;
                        }
                        //o <ignore> tags for
                        //  <file name=... platform=!this platform install-as=..>
                        if (isset($package['platform'][$file]) &&
                              $package['platform'][$file] == "!$os") {
                            $release[$releaseNum]['filelist']['ignore'][] =
                                array(
                                    'attribs' => array(
                                        'name' => $file,
                                    ),
                                );
                            continue;
                        }
                        //o <ignore> tags for
                        //  <file name=... platform=other platform install-as=..>
                        if (isset($package['platform'][$file]) &&
                              $package['platform'][$file][0] != '!' &&
                              $package['platform'][$file] != $os) {
                            $release[$releaseNum]['filelist']['ignore'][] =
                                array(
                                    'attribs' => array(
                                        'name' => $file,
                                    ),
                                );
                            continue;
                        }
                    }
                    foreach ($package['platform'] as $file => $platform) {
                        if (isset($package['install-as'][$file])) {
                            continue;
                        }
                        //o <ignore> tags for <file name=... platform=!this platform>
                        if ($platform == "!$os") {
                            $release[$releaseNum]['filelist']['ignore'][] =
                                array(
                                    'attribs' => array(
                                        'name' => $file,
                                    ),
                                );
                            continue;
                        }
                        //o <ignore> tags for <file name=... platform=other platform>
                        if ($platform[0] != '!' && $platform != $os) {
                            $release[$releaseNum]['filelist']['ignore'][] =
                                array(
                                    'attribs' => array(
                                        'name' => $file,
                                    ),
                                );
                        }
                    }
                    if (!count($release[$releaseNum]['filelist']['install'])) {
                        unset($release[$releaseNum]['filelist']['install']);
                    }
                    if (!count($release[$releaseNum]['filelist']['ignore'])) {
                        unset($release[$releaseNum]['filelist']['ignore']);
                    }
                }
                if (count($generic) || count($genericIgnore)) {
                    $release[count($oses)] = array();
                    if (count($generic)) {
                        foreach ($generic as $file) {
                            if (isset($package['install-as'][$file])) {
                                $installas = $package['install-as'][$file];
                            } else {
                                $installas = $file;
                            }
                            $release[count($oses)]['filelist']['install'][] =
                                array(
                                    'attribs' => array(
                                        'name' => $file,
                                        'as' => $installas,
                                    )
                                );
                        }
                    }
                    if (count($genericIgnore)) {
                        foreach ($genericIgnore as $file) {
                            $release[count($oses)]['filelist']['ignore'][] =
                                array(
                                    'attribs' => array(
                                        'name' => $file,
                                    )
                                );
                        }
                    }
                }
                // cleanup
                foreach ($release as $i => $rel) {
                    if (isset($rel['filelist']['install']) &&
                          count($rel['filelist']['install']) == 1) {
                        $release[$i]['filelist']['install'] =
                            $release[$i]['filelist']['install'][0];
                    }
                    if (isset($rel['filelist']['ignore']) &&
                          count($rel['filelist']['ignore']) == 1) {
                        $release[$i]['filelist']['ignore'] =
                            $release[$i]['filelist']['ignore'][0];
                    }
                }
                if (count($release) == 1) {
                    $release = $release[0];
                }
            } else {
                // no platform atts, but some install-as atts
                foreach ($package['install-as'] as $file => $value) {
                    $release['filelist']['install'][] =
                        array(
                            'attribs' => array(
                                'name' => $file,
                                'as' => $value
                            )
                        );
                }
                if (count($release['filelist']['install']) == 1) {
                    $release['filelist']['install'] = $release['filelist']['install'][0];
                }
            }
        }
    }

    /**
     * @param array
     * @return array
     * @access private
     */
    function _processDep($dep)
    {
        if ($dep['type'] == 'php') {
            if ($dep['rel'] == 'has') {
                // come on - everyone has php!
                return false;
            }
        }
        $php = array();
        if ($dep['type'] != 'php') {
            $php['name'] = $dep['name'];
            if ($dep['type'] == 'pkg') {
                $php['channel'] = 'pear.php.net';
            }
        }
        switch ($dep['rel']) {
            case 'gt' :
                $php['min'] = $dep['version'];
                $php['exclude'] = $dep['version'];
            break;
            case 'ge' :
                if (!isset($dep['version'])) {
                    if ($dep['type'] == 'php') {
                        if (isset($dep['name'])) {
                            $dep['version'] = $dep['name'];
                        }
                    }
                }
                $php['min'] = $dep['version'];
            break;
            case 'lt' :
                $php['max'] = $dep['version'];
                $php['exclude'] = $dep['version'];
            break;
            case 'le' :
                $php['max'] = $dep['version'];
            break;
            case 'eq' :
                $php['min'] = $dep['version'];
                $php['max'] = $dep['version'];
            break;
            case 'ne' :
                $php['exclude'] = $dep['version'];
            break;
            case 'not' :
                $php['conflicts'] = 'yes';
            break;
        }
        return $php;
    }

    /**
     * @param array
     * @return array
     */
    function _processPhpDeps($deps)
    {
        $test = array();
        foreach ($deps as $dep) {
            $test[] = $this->_processDep($dep);
        }
        $min = array();
        $max = array();
        foreach ($test as $dep) {
            if (!$dep) {
                continue;
            }
            if (isset($dep['min'])) {
                $min[$dep['min']] = count($min);
            }
            if (isset($dep['max'])) {
                $max[$dep['max']] = count($max);
            }
        }
        if (count($min) > 0) {
            uksort($min, 'version_compare');
        }
        if (count($max) > 0) {
            uksort($max, 'version_compare');
        }
        if (count($min)) {
            // get the highest minimum
            $a = array_flip($min);
            $min = array_pop($a);
        } else {
            $min = false;
        }
        if (count($max)) {
            // get the lowest maximum
            $a = array_flip($max);
            $max = array_shift($a);
        } else {
            $max = false;
        }
        if ($min) {
            $php['min'] = $min;
        }
        if ($max) {
            $php['max'] = $max;
        }
        $exclude = array();
        foreach ($test as $dep) {
            if (!isset($dep['exclude'])) {
                continue;
            }
            $exclude[] = $dep['exclude'];
        }
        if (count($exclude)) {
            $php['exclude'] = $exclude;
        }
        return $php;
    }

    /**
     * process multiple dependencies that have a name, like package deps
     * @param array
     * @return array
     * @access private
     */
    function _processMultipleDepsName($deps)
    {
        $ret = $tests = array();
        foreach ($deps as $name => $dep) {
            foreach ($dep as $d) {
                $tests[$name][] = $this->_processDep($d);
            }
        }

        foreach ($tests as $name => $test) {
            $max = $min = $php = array();
            $php['name'] = $name;
            foreach ($test as $dep) {
                if (!$dep) {
                    continue;
                }
                if (isset($dep['channel'])) {
                    $php['channel'] = 'pear.php.net';
                }
                if (isset($dep['conflicts']) && $dep['conflicts'] == 'yes') {
                    $php['conflicts'] = 'yes';
                }
                if (isset($dep['min'])) {
                    $min[$dep['min']] = count($min);
                }
                if (isset($dep['max'])) {
                    $max[$dep['max']] = count($max);
                }
            }
            if (count($min) > 0) {
                uksort($min, 'version_compare');
            }
            if (count($max) > 0) {
                uksort($max, 'version_compare');
            }
            if (count($min)) {
                // get the highest minimum
                $a = array_flip($min);
                $min = array_pop($a);
            } else {
                $min = false;
            }
            if (count($max)) {
                // get the lowest maximum
                $a = array_flip($max);
                $max = array_shift($a);
            } else {
                $max = false;
            }
            if ($min) {
                $php['min'] = $min;
            }
            if ($max) {
                $php['max'] = $max;
            }
            $exclude = array();
            foreach ($test as $dep) {
                if (!isset($dep['exclude'])) {
                    continue;
                }
                $exclude[] = $dep['exclude'];
            }
            if (count($exclude)) {
                $php['exclude'] = $exclude;
            }
            $ret[] = $php;
        }
        return $ret;
    }
}
?>
PKr�Z��OWHHPEAR/PackageFile/Parser/v2.phpnu�[���<?php
/**
 * package.xml parsing class, package.xml version 2.0
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a1
 */
/**
 * base xml parser class
 */
require_once 'PEAR/XMLParser.php';
require_once 'PEAR/PackageFile/v2.php';
/**
 * Parser for package.xml version 2.0
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: @PEAR-VER@
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 */
class PEAR_PackageFile_Parser_v2 extends PEAR_XMLParser
{
    var $_config;
    var $_logger;
    var $_registry;

    function setConfig(&$c)
    {
        $this->_config = &$c;
        $this->_registry = &$c->getRegistry();
    }

    function setLogger(&$l)
    {
        $this->_logger = &$l;
    }
    /**
     * Unindent given string
     *
     * @param string $str The string that has to be unindented.
     * @return string
     * @access private
     */
    function _unIndent($str)
    {
        // remove leading newlines
        $str = preg_replace('/^[\r\n]+/', '', $str);
        // find whitespace at the beginning of the first line
        $indent_len = strspn($str, " \t");
        $indent = substr($str, 0, $indent_len);
        $data = '';
        // remove the same amount of whitespace from following lines
        foreach (explode("\n", $str) as $line) {
            if (substr($line, 0, $indent_len) == $indent) {
                $data .= substr($line, $indent_len) . "\n";
            } else {
                $data .= $line . "\n";
            }
        }
        return $data;
    }

    /**
     * post-process data
     *
     * @param string $data
     * @param string $element element name
     */
    function postProcess($data, $element)
    {
        if ($element == 'notes') {
            return trim($this->_unIndent($data));
        }
        return trim($data);
    }

    /**
     * @param string
     * @param string file name of the package.xml
     * @param string|false name of the archive this package.xml came from, if any
     * @param string class name to instantiate and return.  This must be PEAR_PackageFile_v2 or
     *               a subclass
     * @return PEAR_PackageFile_v2
     */
    function parse($data, $file = null, $archive = false, $class = 'PEAR_PackageFile_v2')
    {
        if (PEAR::isError($err = parent::parse($data))) {
            return $err;
        }

        $ret = new $class;
        $ret->encoding = $this->encoding;
        $ret->setConfig($this->_config);
        if (isset($this->_logger)) {
            $ret->setLogger($this->_logger);
        }

        $ret->fromArray($this->_unserializedData);
        $ret->setPackagefile($file, $archive);
        return $ret;
    }
}PKr�Z�_=�@�@PEAR/PackageFile/Parser/v1.phpnu�[���<?php
/**
 * package.xml parsing class, package.xml version 1.0
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a1
 */
/**
 * package.xml abstraction class
 */
require_once 'PEAR/PackageFile/v1.php';
/**
 * Parser for package.xml version 1.0
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: @PEAR-VER@
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 */
class PEAR_PackageFile_Parser_v1
{
    var $_registry;
    var $_config;
    var $_logger;
    /**
     * BC hack to allow PEAR_Common::infoFromString() to sort of
     * work with the version 2.0 format - there's no filelist though
     * @param PEAR_PackageFile_v2
     */
    function fromV2($packagefile)
    {
        $info = $packagefile->getArray(true);
        $ret = new PEAR_PackageFile_v1;
        $ret->fromArray($info['old']);
    }

    function setConfig(&$c)
    {
        $this->_config = &$c;
        $this->_registry = &$c->getRegistry();
    }

    function setLogger(&$l)
    {
        $this->_logger = &$l;
    }

    /**
     * @param string contents of package.xml file, version 1.0
     * @return bool success of parsing
     */
    function &parse($data, $file, $archive = false)
    {
        if (!extension_loaded('xml')) {
            return PEAR::raiseError('Cannot create xml parser for parsing package.xml, no xml extension');
        }
        $xp = xml_parser_create();
        if (!$xp) {
            $a = &PEAR::raiseError('Cannot create xml parser for parsing package.xml');
            return $a;
        }
        xml_set_object($xp, $this);
        xml_set_element_handler($xp, '_element_start_1_0', '_element_end_1_0');
        xml_set_character_data_handler($xp, '_pkginfo_cdata_1_0');
        xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, false);

        $this->element_stack = array();
        $this->_packageInfo = array('provides' => array());
        $this->current_element = false;
        unset($this->dir_install);
        $this->_packageInfo['filelist'] = array();
        $this->filelist =& $this->_packageInfo['filelist'];
        $this->dir_names = array();
        $this->in_changelog = false;
        $this->d_i = 0;
        $this->cdata = '';
        $this->_isValid = true;

        if (!xml_parse($xp, $data, 1)) {
            $code = xml_get_error_code($xp);
            $line = xml_get_current_line_number($xp);
            xml_parser_free($xp);
            $a = PEAR::raiseError(sprintf("XML error: %s at line %d",
                           $str = xml_error_string($code), $line), 2);
            return $a;
        }

        xml_parser_free($xp);

        $pf = new PEAR_PackageFile_v1;
        $pf->setConfig($this->_config);
        if (isset($this->_logger)) {
            $pf->setLogger($this->_logger);
        }
        $pf->setPackagefile($file, $archive);
        $pf->fromArray($this->_packageInfo);
        return $pf;
    }
    // {{{ _unIndent()

    /**
     * Unindent given string
     *
     * @param string $str The string that has to be unindented.
     * @return string
     * @access private
     */
    function _unIndent($str)
    {
        // remove leading newlines
        $str = preg_replace('/^[\r\n]+/', '', $str);
        // find whitespace at the beginning of the first line
        $indent_len = strspn($str, " \t");
        $indent = substr($str, 0, $indent_len);
        $data = '';
        // remove the same amount of whitespace from following lines
        foreach (explode("\n", $str) as $line) {
            if (substr($line, 0, $indent_len) == $indent) {
                $data .= substr($line, $indent_len) . "\n";
            } elseif (trim(substr($line, 0, $indent_len))) {
                $data .= ltrim($line);
            }
        }
        return $data;
    }

    // Support for package DTD v1.0:
    // {{{ _element_start_1_0()

    /**
     * XML parser callback for ending elements.  Used for version 1.0
     * packages.
     *
     * @param resource  $xp    XML parser resource
     * @param string    $name  name of ending element
     *
     * @return void
     *
     * @access private
     */
    function _element_start_1_0($xp, $name, $attribs)
    {
        array_push($this->element_stack, $name);
        $this->current_element = $name;
        $spos = sizeof($this->element_stack) - 2;
        $this->prev_element = ($spos >= 0) ? $this->element_stack[$spos] : '';
        $this->current_attributes = $attribs;
        $this->cdata = '';
        switch ($name) {
            case 'dir':
                if ($this->in_changelog) {
                    break;
                }
                if (array_key_exists('name', $attribs) && $attribs['name'] != '/') {
                    $attribs['name'] = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'),
                        $attribs['name']);
                    if (strrpos($attribs['name'], '/') === strlen($attribs['name']) - 1) {
                        $attribs['name'] = substr($attribs['name'], 0,
                            strlen($attribs['name']) - 1);
                    }
                    if (strpos($attribs['name'], '/') === 0) {
                        $attribs['name'] = substr($attribs['name'], 1);
                    }
                    $this->dir_names[] = $attribs['name'];
                }
                if (isset($attribs['baseinstalldir'])) {
                    $this->dir_install = $attribs['baseinstalldir'];
                }
                if (isset($attribs['role'])) {
                    $this->dir_role = $attribs['role'];
                }
                break;
            case 'file':
                if ($this->in_changelog) {
                    break;
                }
                if (isset($attribs['name'])) {
                    $path = '';
                    if (count($this->dir_names)) {
                        foreach ($this->dir_names as $dir) {
                            $path .= $dir . '/';
                        }
                    }
                    $path .= preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'),
                        $attribs['name']);
                    unset($attribs['name']);
                    $this->current_path = $path;
                    $this->filelist[$path] = $attribs;
                    // Set the baseinstalldir only if the file don't have this attrib
                    if (!isset($this->filelist[$path]['baseinstalldir']) &&
                        isset($this->dir_install))
                    {
                        $this->filelist[$path]['baseinstalldir'] = $this->dir_install;
                    }
                    // Set the Role
                    if (!isset($this->filelist[$path]['role']) && isset($this->dir_role)) {
                        $this->filelist[$path]['role'] = $this->dir_role;
                    }
                }
                break;
            case 'replace':
                if (!$this->in_changelog) {
                    $this->filelist[$this->current_path]['replacements'][] = $attribs;
                }
                break;
            case 'maintainers':
                $this->_packageInfo['maintainers'] = array();
                $this->m_i = 0; // maintainers array index
                break;
            case 'maintainer':
                // compatibility check
                if (!isset($this->_packageInfo['maintainers'])) {
                    $this->_packageInfo['maintainers'] = array();
                    $this->m_i = 0;
                }
                $this->_packageInfo['maintainers'][$this->m_i] = array();
                $this->current_maintainer =& $this->_packageInfo['maintainers'][$this->m_i];
                break;
            case 'changelog':
                $this->_packageInfo['changelog'] = array();
                $this->c_i = 0; // changelog array index
                $this->in_changelog = true;
                break;
            case 'release':
                if ($this->in_changelog) {
                    $this->_packageInfo['changelog'][$this->c_i] = array();
                    $this->current_release = &$this->_packageInfo['changelog'][$this->c_i];
                } else {
                    $this->current_release = &$this->_packageInfo;
                }
                break;
            case 'deps':
                if (!$this->in_changelog) {
                    $this->_packageInfo['release_deps'] = array();
                }
                break;
            case 'dep':
                // dependencies array index
                if (!$this->in_changelog) {
                    $this->d_i++;
                    isset($attribs['type']) ? ($attribs['type'] = strtolower($attribs['type'])) : false;
                    $this->_packageInfo['release_deps'][$this->d_i] = $attribs;
                }
                break;
            case 'configureoptions':
                if (!$this->in_changelog) {
                    $this->_packageInfo['configure_options'] = array();
                }
                break;
            case 'configureoption':
                if (!$this->in_changelog) {
                    $this->_packageInfo['configure_options'][] = $attribs;
                }
                break;
            case 'provides':
                if (empty($attribs['type']) || empty($attribs['name'])) {
                    break;
                }
                $attribs['explicit'] = true;
                $this->_packageInfo['provides']["$attribs[type];$attribs[name]"] = $attribs;
                break;
            case 'package' :
                if (isset($attribs['version'])) {
                    $this->_packageInfo['xsdversion'] = trim($attribs['version']);
                } else {
                    $this->_packageInfo['xsdversion'] = '1.0';
                }
                if (isset($attribs['packagerversion'])) {
                    $this->_packageInfo['packagerversion'] = $attribs['packagerversion'];
                }
                break;
        }
    }

    // }}}
    // {{{ _element_end_1_0()

    /**
     * XML parser callback for ending elements.  Used for version 1.0
     * packages.
     *
     * @param resource  $xp    XML parser resource
     * @param string    $name  name of ending element
     *
     * @return void
     *
     * @access private
     */
    function _element_end_1_0($xp, $name)
    {
        $data = trim($this->cdata);
        switch ($name) {
            case 'name':
                switch ($this->prev_element) {
                    case 'package':
                        $this->_packageInfo['package'] = $data;
                        break;
                    case 'maintainer':
                        $this->current_maintainer['name'] = $data;
                        break;
                }
                break;
            case 'extends' :
                $this->_packageInfo['extends'] = $data;
                break;
            case 'summary':
                $this->_packageInfo['summary'] = $data;
                break;
            case 'description':
                $data = $this->_unIndent($this->cdata);
                $this->_packageInfo['description'] = $data;
                break;
            case 'user':
                $this->current_maintainer['handle'] = $data;
                break;
            case 'email':
                $this->current_maintainer['email'] = $data;
                break;
            case 'role':
                $this->current_maintainer['role'] = $data;
                break;
            case 'version':
                if ($this->in_changelog) {
                    $this->current_release['version'] = $data;
                } else {
                    $this->_packageInfo['version'] = $data;
                }
                break;
            case 'date':
                if ($this->in_changelog) {
                    $this->current_release['release_date'] = $data;
                } else {
                    $this->_packageInfo['release_date'] = $data;
                }
                break;
            case 'notes':
                // try to "de-indent" release notes in case someone
                // has been over-indenting their xml ;-)
                // Trim only on the right side
                $data = rtrim($this->_unIndent($this->cdata));
                if ($this->in_changelog) {
                    $this->current_release['release_notes'] = $data;
                } else {
                    $this->_packageInfo['release_notes'] = $data;
                }
                break;
            case 'warnings':
                if ($this->in_changelog) {
                    $this->current_release['release_warnings'] = $data;
                } else {
                    $this->_packageInfo['release_warnings'] = $data;
                }
                break;
            case 'state':
                if ($this->in_changelog) {
                    $this->current_release['release_state'] = $data;
                } else {
                    $this->_packageInfo['release_state'] = $data;
                }
                break;
            case 'license':
                if ($this->in_changelog) {
                    $this->current_release['release_license'] = $data;
                } else {
                    $this->_packageInfo['release_license'] = $data;
                }
                break;
            case 'dep':
                if ($data && !$this->in_changelog) {
                    $this->_packageInfo['release_deps'][$this->d_i]['name'] = $data;
                }
                break;
            case 'dir':
                if ($this->in_changelog) {
                    break;
                }
                array_pop($this->dir_names);
                break;
            case 'file':
                if ($this->in_changelog) {
                    break;
                }
                if ($data) {
                    $path = '';
                    if (count($this->dir_names)) {
                        foreach ($this->dir_names as $dir) {
                            $path .= $dir . '/';
                        }
                    }
                    $path .= $data;
                    $this->filelist[$path] = $this->current_attributes;
                    // Set the baseinstalldir only if the file don't have this attrib
                    if (!isset($this->filelist[$path]['baseinstalldir']) &&
                        isset($this->dir_install))
                    {
                        $this->filelist[$path]['baseinstalldir'] = $this->dir_install;
                    }
                    // Set the Role
                    if (!isset($this->filelist[$path]['role']) && isset($this->dir_role)) {
                        $this->filelist[$path]['role'] = $this->dir_role;
                    }
                }
                break;
            case 'maintainer':
                if (empty($this->_packageInfo['maintainers'][$this->m_i]['role'])) {
                    $this->_packageInfo['maintainers'][$this->m_i]['role'] = 'lead';
                }
                $this->m_i++;
                break;
            case 'release':
                if ($this->in_changelog) {
                    $this->c_i++;
                }
                break;
            case 'changelog':
                $this->in_changelog = false;
                break;
        }
        array_pop($this->element_stack);
        $spos = sizeof($this->element_stack) - 1;
        $this->current_element = ($spos > 0) ? $this->element_stack[$spos] : '';
        $this->cdata = '';
    }

    // }}}
    // {{{ _pkginfo_cdata_1_0()

    /**
     * XML parser callback for character data.  Used for version 1.0
     * packages.
     *
     * @param resource  $xp    XML parser resource
     * @param string    $name  character data
     *
     * @return void
     *
     * @access private
     */
    function _pkginfo_cdata_1_0($xp, $data)
    {
        if (isset($this->cdata)) {
            $this->cdata .= $data;
        }
    }

    // }}}
}
?>PKr�Zc��__PEAR/DependencyDB.phpnu�[���<?php
/**
 * PEAR_DependencyDB, advanced installed packages dependency database
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Tomas V. V. Cox <cox@idecnet.com>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a1
 */

/**
 * Needed for error handling
 */
require_once 'PEAR.php';
require_once 'PEAR/Config.php';

$GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'] = array();
/**
 * Track dependency relationships between installed packages
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @author     Tomas V.V.Cox <cox@idec.net.com>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 */
class PEAR_DependencyDB
{
    // {{{ properties

    /**
     * This is initialized by {@link setConfig()}
     * @var PEAR_Config
     * @access private
     */
    var $_config;
    /**
     * This is initialized by {@link setConfig()}
     * @var PEAR_Registry
     * @access private
     */
    var $_registry;
    /**
     * Filename of the dependency DB (usually .depdb)
     * @var string
     * @access private
     */
    var $_depdb = false;
    /**
     * File name of the lockfile (usually .depdblock)
     * @var string
     * @access private
     */
    var $_lockfile = false;
    /**
     * Open file resource for locking the lockfile
     * @var resource|false
     * @access private
     */
    var $_lockFp = false;
    /**
     * API version of this class, used to validate a file on-disk
     * @var string
     * @access private
     */
    var $_version = '1.0';
    /**
     * Cached dependency database file
     * @var array|null
     * @access private
     */
    var $_cache;

    // }}}
    // {{{ & singleton()

    /**
     * Get a raw dependency database.  Calls setConfig() and assertDepsDB()
     * @param PEAR_Config
     * @param string|false full path to the dependency database, or false to use default
     * @return PEAR_DependencyDB|PEAR_Error
     */
    public static function &singleton(&$config, $depdb = false)
    {
        $phpdir = $config->get('php_dir', null, 'pear.php.net');
        if (!isset($GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'][$phpdir])) {
            $a = new PEAR_DependencyDB;
            $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'][$phpdir] = &$a;
            $a->setConfig($config, $depdb);
            $e = $a->assertDepsDB();
            if (PEAR::isError($e)) {
                return $e;
            }
        }

        return $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'][$phpdir];
    }

    /**
     * Set up the registry/location of dependency DB
     * @param PEAR_Config|false
     * @param string|false full path to the dependency database, or false to use default
     */
    function setConfig(&$config, $depdb = false)
    {
        if (!$config) {
            $this->_config = &PEAR_Config::singleton();
        } else {
            $this->_config = &$config;
        }

        $this->_registry = &$this->_config->getRegistry();
        if (!$depdb) {
            $dir = $this->_config->get('metadata_dir', null, 'pear.php.net');
            if (!$dir) {
                $dir = $this->_config->get('php_dir', null, 'pear.php.net');
            }
            $this->_depdb =  $dir . DIRECTORY_SEPARATOR . '.depdb';
        } else {
            $this->_depdb = $depdb;
        }

        $this->_lockfile = dirname($this->_depdb) . DIRECTORY_SEPARATOR . '.depdblock';
    }
    // }}}

    function hasWriteAccess()
    {
        if (!file_exists($this->_depdb)) {
            $dir = $this->_depdb;
            while ($dir && $dir != '.') {
                $dir = dirname($dir); // cd ..
                if ($dir != '.' && file_exists($dir)) {
                    if (is_writeable($dir)) {
                        return true;
                    }

                    return false;
                }
            }

            return false;
        }

        return is_writeable($this->_depdb);
    }

    // {{{ assertDepsDB()

    /**
     * Create the dependency database, if it doesn't exist.  Error if the database is
     * newer than the code reading it.
     * @return void|PEAR_Error
     */
    function assertDepsDB()
    {
        if (!is_file($this->_depdb)) {
            $this->rebuildDB();
            return;
        }

        $depdb = $this->_getDepDB();
        // Datatype format has been changed, rebuild the Deps DB
        if ($depdb['_version'] < $this->_version) {
            $this->rebuildDB();
        }

        if ($depdb['_version'][0] > $this->_version[0]) {
            return PEAR::raiseError('Dependency database is version ' .
                $depdb['_version'] . ', and we are version ' .
                $this->_version . ', cannot continue');
        }
    }

    /**
     * Get a list of installed packages that depend on this package
     * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
     * @return array|false
     */
    function getDependentPackages(&$pkg)
    {
        $data = $this->_getDepDB();
        if (is_object($pkg)) {
            $channel = strtolower($pkg->getChannel());
            $package = strtolower($pkg->getPackage());
        } else {
            $channel = strtolower($pkg['channel']);
            $package = strtolower($pkg['package']);
        }

        if (isset($data['packages'][$channel][$package])) {
            return $data['packages'][$channel][$package];
        }

        return false;
    }

    /**
     * Get a list of the actual dependencies of installed packages that depend on
     * a package.
     * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
     * @return array|false
     */
    function getDependentPackageDependencies(&$pkg)
    {
        $data = $this->_getDepDB();
        if (is_object($pkg)) {
            $channel = strtolower($pkg->getChannel());
            $package = strtolower($pkg->getPackage());
        } else if (is_array($pkg)) {
            $channel = strtolower($pkg['channel']);
            $package = strtolower($pkg['package']);
        } else {
            return false;
        }

        $depend = $this->getDependentPackages($pkg);
        if (!$depend) {
            return false;
        }

        $dependencies = array();
        foreach ($depend as $info) {
            $temp = $this->getDependencies($info);
            foreach ($temp as $dep) {
                if (
                    isset($dep['dep'], $dep['dep']['channel'], $dep['dep']['name']) &&
                    strtolower($dep['dep']['channel']) == $channel &&
                    strtolower($dep['dep']['name']) == $package
                ) {
                    if (!isset($dependencies[$info['channel']])) {
                        $dependencies[$info['channel']] = array();
                    }

                    if (!isset($dependencies[$info['channel']][$info['package']])) {
                        $dependencies[$info['channel']][$info['package']] = array();
                    }
                    $dependencies[$info['channel']][$info['package']][] = $dep;
                }
            }
        }

        return $dependencies;
    }

    /**
     * Get a list of dependencies of this installed package
     * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
     * @return array|false
     */
    function getDependencies(&$pkg)
    {
        if (is_object($pkg)) {
            $channel = strtolower($pkg->getChannel());
            $package = strtolower($pkg->getPackage());
        } else {
            $channel = strtolower($pkg['channel']);
            $package = strtolower($pkg['package']);
        }

        $data = $this->_getDepDB();
        if (isset($data['dependencies'][$channel][$package])) {
            return $data['dependencies'][$channel][$package];
        }

        return false;
    }

    /**
     * Determine whether $parent depends on $child, near or deep
     * @param array|PEAR_PackageFile_v2|PEAR_PackageFile_v2
     * @param array|PEAR_PackageFile_v2|PEAR_PackageFile_v2
     */
    function dependsOn($parent, $child)
    {
        $c = array();
        $this->_getDepDB();
        return $this->_dependsOn($parent, $child, $c);
    }

    function _dependsOn($parent, $child, &$checked)
    {
        if (is_object($parent)) {
            $channel = strtolower($parent->getChannel());
            $package = strtolower($parent->getPackage());
        } else {
            $channel = strtolower($parent['channel']);
            $package = strtolower($parent['package']);
        }

        if (is_object($child)) {
            $depchannel = strtolower($child->getChannel());
            $deppackage = strtolower($child->getPackage());
        } else {
            $depchannel = strtolower($child['channel']);
            $deppackage = strtolower($child['package']);
        }

        if (isset($checked[$channel][$package][$depchannel][$deppackage])) {
            return false; // avoid endless recursion
        }

        $checked[$channel][$package][$depchannel][$deppackage] = true;
        if (!isset($this->_cache['dependencies'][$channel][$package])) {
            return false;
        }

        foreach ($this->_cache['dependencies'][$channel][$package] as $info) {
            if (isset($info['dep']['uri'])) {
                if (is_object($child)) {
                    if ($info['dep']['uri'] == $child->getURI()) {
                        return true;
                    }
                } elseif (isset($child['uri'])) {
                    if ($info['dep']['uri'] == $child['uri']) {
                        return true;
                    }
                }
                return false;
            }

            if (strtolower($info['dep']['channel']) == $depchannel &&
                  strtolower($info['dep']['name']) == $deppackage) {
                return true;
            }
        }

        foreach ($this->_cache['dependencies'][$channel][$package] as $info) {
            if (isset($info['dep']['uri'])) {
                if ($this->_dependsOn(array(
                        'uri' => $info['dep']['uri'],
                        'package' => $info['dep']['name']), $child, $checked)) {
                    return true;
                }
            } else {
                if ($this->_dependsOn(array(
                        'channel' => $info['dep']['channel'],
                        'package' => $info['dep']['name']), $child, $checked)) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * Register dependencies of a package that is being installed or upgraded
     * @param PEAR_PackageFile_v2|PEAR_PackageFile_v2
     */
    function installPackage(&$package)
    {
        $data = $this->_getDepDB();
        unset($this->_cache);
        $this->_setPackageDeps($data, $package);
        $this->_writeDepDB($data);
    }

    /**
     * Remove dependencies of a package that is being uninstalled, or upgraded.
     *
     * Upgraded packages first uninstall, then install
     * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array If an array, then it must have
     *        indices 'channel' and 'package'
     */
    function uninstallPackage(&$pkg)
    {
        $data = $this->_getDepDB();
        unset($this->_cache);
        if (is_object($pkg)) {
            $channel = strtolower($pkg->getChannel());
            $package = strtolower($pkg->getPackage());
        } else {
            $channel = strtolower($pkg['channel']);
            $package = strtolower($pkg['package']);
        }

        if (!isset($data['dependencies'][$channel][$package])) {
            return true;
        }

        foreach ($data['dependencies'][$channel][$package] as $dep) {
            $found      = false;
            $depchannel = isset($dep['dep']['uri']) ? '__uri' : strtolower($dep['dep']['channel']);
            $depname    = strtolower($dep['dep']['name']);
            if (isset($data['packages'][$depchannel][$depname])) {
                foreach ($data['packages'][$depchannel][$depname] as $i => $info) {
                    if ($info['channel'] == $channel && $info['package'] == $package) {
                        $found = true;
                        break;
                    }
                }
            }

            if ($found) {
                unset($data['packages'][$depchannel][$depname][$i]);
                if (!count($data['packages'][$depchannel][$depname])) {
                    unset($data['packages'][$depchannel][$depname]);
                    if (!count($data['packages'][$depchannel])) {
                        unset($data['packages'][$depchannel]);
                    }
                } else {
                    $data['packages'][$depchannel][$depname] =
                        array_values($data['packages'][$depchannel][$depname]);
                }
            }
        }

        unset($data['dependencies'][$channel][$package]);
        if (!count($data['dependencies'][$channel])) {
            unset($data['dependencies'][$channel]);
        }

        if (!count($data['dependencies'])) {
            unset($data['dependencies']);
        }

        if (!count($data['packages'])) {
            unset($data['packages']);
        }

        $this->_writeDepDB($data);
    }

    /**
     * Rebuild the dependency DB by reading registry entries.
     * @return true|PEAR_Error
     */
    function rebuildDB()
    {
        $depdb = array('_version' => $this->_version);
        if (!$this->hasWriteAccess()) {
            // allow startup for read-only with older Registry
            return $depdb;
        }

        $packages = $this->_registry->listAllPackages();
        if (PEAR::isError($packages)) {
            return $packages;
        }

        foreach ($packages as $channel => $ps) {
            foreach ($ps as $package) {
                $package = $this->_registry->getPackage($package, $channel);
                if (PEAR::isError($package)) {
                    return $package;
                }
                $this->_setPackageDeps($depdb, $package);
            }
        }

        $error = $this->_writeDepDB($depdb);
        if (PEAR::isError($error)) {
            return $error;
        }

        $this->_cache = $depdb;
        return true;
    }

    /**
     * Register usage of the dependency DB to prevent race conditions
     * @param int one of the LOCK_* constants
     * @return true|PEAR_Error
     * @access private
     */
    function _lock($mode = LOCK_EX)
    {
        if (stristr(php_uname(), 'Windows 9')) {
            return true;
        }

        if ($mode != LOCK_UN && is_resource($this->_lockFp)) {
            // XXX does not check type of lock (LOCK_SH/LOCK_EX)
            return true;
        }

        $open_mode = 'w';
        // XXX People reported problems with LOCK_SH and 'w'
        if ($mode === LOCK_SH) {
            if (!file_exists($this->_lockfile)) {
                touch($this->_lockfile);
            } elseif (!is_file($this->_lockfile)) {
                return PEAR::raiseError('could not create Dependency lock file, ' .
                    'it exists and is not a regular file');
            }
            $open_mode = 'r';
        }

        if (!is_resource($this->_lockFp)) {
            $this->_lockFp = @fopen($this->_lockfile, $open_mode);
        }

        if (!is_resource($this->_lockFp)) {
            $last_errormsg = '';
            $last_error = error_get_last();
            if (!empty($last_error['message'])) {
                $last_errormsg = $last_error['message'];
            }
            return PEAR::raiseError("could not create Dependency lock file" .
                                     (isset($last_errormsg) ? ": " . $last_errormsg : ""));
        }

        if (!(int)flock($this->_lockFp, $mode)) {
            switch ($mode) {
                case LOCK_SH: $str = 'shared';    break;
                case LOCK_EX: $str = 'exclusive'; break;
                case LOCK_UN: $str = 'unlock';    break;
                default:      $str = 'unknown';   break;
            }

            return PEAR::raiseError("could not acquire $str lock ($this->_lockfile)");
        }

        return true;
    }

    /**
     * Release usage of dependency DB
     * @return true|PEAR_Error
     * @access private
     */
    function _unlock()
    {
        $ret = $this->_lock(LOCK_UN);
        if (is_resource($this->_lockFp)) {
            fclose($this->_lockFp);
        }
        $this->_lockFp = null;
        return $ret;
    }

    /**
     * Load the dependency database from disk, or return the cache
     * @return array|PEAR_Error
     */
    function _getDepDB()
    {
        if (!$this->hasWriteAccess()) {
            return array('_version' => $this->_version);
        }

        if (isset($this->_cache)) {
            return $this->_cache;
        }

        if (!$fp = fopen($this->_depdb, 'r')) {
            $err = PEAR::raiseError("Could not open dependencies file `".$this->_depdb."'");
            return $err;
        }

        clearstatcache();
        fclose($fp);
        $data = @unserialize(file_get_contents($this->_depdb));
        $this->_cache = $data;
        return $data;
    }

    /**
     * Write out the dependency database to disk
     * @param array the database
     * @return true|PEAR_Error
     * @access private
     */
    function _writeDepDB(&$deps)
    {
        if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
            return $e;
        }

        if (!$fp = fopen($this->_depdb, 'wb')) {
            $this->_unlock();
            return PEAR::raiseError("Could not open dependencies file `".$this->_depdb."' for writing");
        }

        fwrite($fp, serialize($deps));
        fclose($fp);
        $this->_unlock();
        $this->_cache = $deps;
        return true;
    }

    /**
     * Register all dependencies from a package in the dependencies database, in essence
     * "installing" the package's dependency information
     * @param array the database
     * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
     * @access private
     */
    function _setPackageDeps(&$data, &$pkg)
    {
        $pkg->setConfig($this->_config);
        if ($pkg->getPackagexmlVersion() == '1.0') {
            $gen = &$pkg->getDefaultGenerator();
            $deps = $gen->dependenciesToV2();
        } else {
            $deps = $pkg->getDeps(true);
        }

        if (!$deps) {
            return;
        }

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

        if (!isset($data['dependencies'])) {
            $data['dependencies'] = array();
        }

        $channel = strtolower($pkg->getChannel());
        $package = strtolower($pkg->getPackage());

        if (!isset($data['dependencies'][$channel])) {
            $data['dependencies'][$channel] = array();
        }

        $data['dependencies'][$channel][$package] = array();
        if (isset($deps['required']['package'])) {
            if (!isset($deps['required']['package'][0])) {
                $deps['required']['package'] = array($deps['required']['package']);
            }

            foreach ($deps['required']['package'] as $dep) {
                $this->_registerDep($data, $pkg, $dep, 'required');
            }
        }

        if (isset($deps['optional']['package'])) {
            if (!isset($deps['optional']['package'][0])) {
                $deps['optional']['package'] = array($deps['optional']['package']);
            }

            foreach ($deps['optional']['package'] as $dep) {
                $this->_registerDep($data, $pkg, $dep, 'optional');
            }
        }

        if (isset($deps['required']['subpackage'])) {
            if (!isset($deps['required']['subpackage'][0])) {
                $deps['required']['subpackage'] = array($deps['required']['subpackage']);
            }

            foreach ($deps['required']['subpackage'] as $dep) {
                $this->_registerDep($data, $pkg, $dep, 'required');
            }
        }

        if (isset($deps['optional']['subpackage'])) {
            if (!isset($deps['optional']['subpackage'][0])) {
                $deps['optional']['subpackage'] = array($deps['optional']['subpackage']);
            }

            foreach ($deps['optional']['subpackage'] as $dep) {
                $this->_registerDep($data, $pkg, $dep, 'optional');
            }
        }

        if (isset($deps['group'])) {
            if (!isset($deps['group'][0])) {
                $deps['group'] = array($deps['group']);
            }

            foreach ($deps['group'] as $group) {
                if (isset($group['package'])) {
                    if (!isset($group['package'][0])) {
                        $group['package'] = array($group['package']);
                    }

                    foreach ($group['package'] as $dep) {
                        $this->_registerDep($data, $pkg, $dep, 'optional',
                            $group['attribs']['name']);
                    }
                }

                if (isset($group['subpackage'])) {
                    if (!isset($group['subpackage'][0])) {
                        $group['subpackage'] = array($group['subpackage']);
                    }

                    foreach ($group['subpackage'] as $dep) {
                        $this->_registerDep($data, $pkg, $dep, 'optional',
                            $group['attribs']['name']);
                    }
                }
            }
        }

        if ($data['dependencies'][$channel][$package] == array()) {
            unset($data['dependencies'][$channel][$package]);
            if (!count($data['dependencies'][$channel])) {
                unset($data['dependencies'][$channel]);
            }
        }
    }

    /**
     * @param array the database
     * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
     * @param array the specific dependency
     * @param required|optional whether this is a required or an optional dep
     * @param string|false dependency group this dependency is from, or false for ordinary dep
     */
    function _registerDep(&$data, &$pkg, $dep, $type, $group = false)
    {
        $info = array(
            'dep'   => $dep,
            'type'  => $type,
            'group' => $group
        );

        $dep  = array_map('strtolower', $dep);
        $depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri';
        if (!isset($data['dependencies'])) {
            $data['dependencies'] = array();
        }

        $channel = strtolower($pkg->getChannel());
        $package = strtolower($pkg->getPackage());

        if (!isset($data['dependencies'][$channel])) {
            $data['dependencies'][$channel] = array();
        }

        if (!isset($data['dependencies'][$channel][$package])) {
            $data['dependencies'][$channel][$package] = array();
        }

        $data['dependencies'][$channel][$package][] = $info;
        if (isset($data['packages'][$depchannel][$dep['name']])) {
            $found = false;
            foreach ($data['packages'][$depchannel][$dep['name']] as $i => $p) {
                if ($p['channel'] == $channel && $p['package'] == $package) {
                    $found = true;
                    break;
                }
            }
        } else {
            if (!isset($data['packages'])) {
                $data['packages'] = array();
            }

            if (!isset($data['packages'][$depchannel])) {
                $data['packages'][$depchannel] = array();
            }

            if (!isset($data['packages'][$depchannel][$dep['name']])) {
                $data['packages'][$depchannel][$dep['name']] = array();
            }

            $found = false;
        }

        if (!$found) {
            $data['packages'][$depchannel][$dep['name']][] = array(
                'channel' => $channel,
                'package' => $package
            );
        }
    }
}
PKr�Z�@P��PEAR/ChannelFile/Parser.phpnu�[���<?php
/**
 * PEAR_ChannelFile_Parser for parsing channel.xml
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a1
 */

/**
 * base xml parser class
 */
require_once 'PEAR/XMLParser.php';
require_once 'PEAR/ChannelFile.php';
/**
 * Parser for channel.xml
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 */
class PEAR_ChannelFile_Parser extends PEAR_XMLParser
{
    var $_config;
    var $_logger;
    var $_registry;

    function setConfig(&$c)
    {
        $this->_config = &$c;
        $this->_registry = &$c->getRegistry();
    }

    function setLogger(&$l)
    {
        $this->_logger = &$l;
    }

    function parse($data, $file)
    {
        if (PEAR::isError($err = parent::parse($data, $file))) {
            return $err;
        }

        $ret = new PEAR_ChannelFile;
        $ret->setConfig($this->_config);
        if (isset($this->_logger)) {
            $ret->setLogger($this->_logger);
        }

        $ret->fromArray($this->_unserializedData);
        // make sure the filelist is in the easy to read format needed
        $ret->flattenFilelist();
        $ret->setPackagefile($file, $archive);
        return $ret;
    }
}PKr�Z��_�0�0PEAR/Command.phpnu�[���<?php
/**
 * PEAR_Command, command pattern class
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 0.1
 */

/**
 * Needed for error handling
 */
require_once 'PEAR.php';
require_once 'PEAR/Frontend.php';
require_once 'PEAR/XMLParser.php';

/**
 * List of commands and what classes they are implemented in.
 * @var array command => implementing class
 */
$GLOBALS['_PEAR_Command_commandlist'] = array();

/**
 * List of commands and their descriptions
 * @var array command => description
 */
$GLOBALS['_PEAR_Command_commanddesc'] = array();

/**
 * List of shortcuts to common commands.
 * @var array shortcut => command
 */
$GLOBALS['_PEAR_Command_shortcuts'] = array();

/**
 * Array of command objects
 * @var array class => object
 */
$GLOBALS['_PEAR_Command_objects'] = array();

/**
 * PEAR command class, a simple factory class for administrative
 * commands.
 *
 * How to implement command classes:
 *
 * - The class must be called PEAR_Command_Nnn, installed in the
 *   "PEAR/Common" subdir, with a method called getCommands() that
 *   returns an array of the commands implemented by the class (see
 *   PEAR/Command/Install.php for an example).
 *
 * - The class must implement a run() function that is called with three
 *   params:
 *
 *    (string) command name
 *    (array)  assoc array with options, freely defined by each
 *             command, for example:
 *             array('force' => true)
 *    (array)  list of the other parameters
 *
 *   The run() function returns a PEAR_CommandResponse object.  Use
 *   these methods to get information:
 *
 *    int getStatus()   Returns PEAR_COMMAND_(SUCCESS|FAILURE|PARTIAL)
 *                      *_PARTIAL means that you need to issue at least
 *                      one more command to complete the operation
 *                      (used for example for validation steps).
 *
 *    string getMessage()  Returns a message for the user.  Remember,
 *                         no HTML or other interface-specific markup.
 *
 *   If something unexpected happens, run() returns a PEAR error.
 *
 * - DON'T OUTPUT ANYTHING! Return text for output instead.
 *
 * - DON'T USE HTML! The text you return will be used from both Gtk,
 *   web and command-line interfaces, so for now, keep everything to
 *   plain text.
 *
 * - DON'T USE EXIT OR DIE! Always use pear errors.  From static
 *   classes do PEAR::raiseError(), from other classes do
 *   $this->raiseError().
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 0.1
 */
class PEAR_Command
{
    // {{{ factory()

    /**
     * Get the right object for executing a command.
     *
     * @param string $command The name of the command
     * @param object $config  Instance of PEAR_Config object
     *
     * @return object the command object or a PEAR error
     */
    public static function &factory($command, &$config)
    {
        if (empty($GLOBALS['_PEAR_Command_commandlist'])) {
            PEAR_Command::registerCommands();
        }
        if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) {
            $command = $GLOBALS['_PEAR_Command_shortcuts'][$command];
        }
        if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) {
            $a = PEAR::raiseError("unknown command `$command'");
            return $a;
        }
        $class = $GLOBALS['_PEAR_Command_commandlist'][$command];
        if (!class_exists($class)) {
            require_once $GLOBALS['_PEAR_Command_objects'][$class];
        }
        if (!class_exists($class)) {
            $a = PEAR::raiseError("unknown command `$command'");
            return $a;
        }
        $ui =& PEAR_Command::getFrontendObject();
        $obj = new $class($ui, $config);
        return $obj;
    }

    // }}}
    // {{{ & getObject()
    public static function &getObject($command)
    {
        $class = $GLOBALS['_PEAR_Command_commandlist'][$command];
        if (!class_exists($class)) {
            require_once $GLOBALS['_PEAR_Command_objects'][$class];
        }
        if (!class_exists($class)) {
            return PEAR::raiseError("unknown command `$command'");
        }
        $ui =& PEAR_Command::getFrontendObject();
        $config = &PEAR_Config::singleton();
        $obj = new $class($ui, $config);
        return $obj;
    }

    // }}}
    // {{{ & getFrontendObject()

    /**
     * Get instance of frontend object.
     *
     * @return object|PEAR_Error
     */
    public static function &getFrontendObject()
    {
        $a = &PEAR_Frontend::singleton();
        return $a;
    }

    // }}}
    // {{{ & setFrontendClass()

    /**
     * Load current frontend class.
     *
     * @param string $uiclass Name of class implementing the frontend
     *
     * @return object the frontend object, or a PEAR error
     */
    public static function &setFrontendClass($uiclass)
    {
        $a = &PEAR_Frontend::setFrontendClass($uiclass);
        return $a;
    }

    // }}}
    // {{{ setFrontendType()

    /**
     * Set current frontend.
     *
     * @param string $uitype Name of the frontend type (for example "CLI")
     *
     * @return object the frontend object, or a PEAR error
     */
    public static function setFrontendType($uitype)
    {
        $uiclass = 'PEAR_Frontend_' . $uitype;
        return PEAR_Command::setFrontendClass($uiclass);
    }

    // }}}
    // {{{ registerCommands()

    /**
     * Scan through the Command directory looking for classes
     * and see what commands they implement.
     *
     * @param bool   (optional) if FALSE (default), the new list of
     *               commands should replace the current one.  If TRUE,
     *               new entries will be merged with old.
     *
     * @param string (optional) where (what directory) to look for
     *               classes, defaults to the Command subdirectory of
     *               the directory from where this file (__FILE__) is
     *               included.
     *
     * @return bool TRUE on success, a PEAR error on failure
     */
    public static function registerCommands($merge = false, $dir = null)
    {
        $parser = new PEAR_XMLParser;
        if ($dir === null) {
            $dir = dirname(__FILE__) . '/Command';
        }
        if (!is_dir($dir)) {
            return PEAR::raiseError("registerCommands: opendir($dir) '$dir' does not exist or is not a directory");
        }
        $dp = @opendir($dir);
        if (empty($dp)) {
            return PEAR::raiseError("registerCommands: opendir($dir) failed");
        }
        if (!$merge) {
            $GLOBALS['_PEAR_Command_commandlist'] = array();
        }

        while ($file = readdir($dp)) {
            if ($file[0] == '.' || substr($file, -4) != '.xml') {
                continue;
            }

            $f = substr($file, 0, -4);
            $class = "PEAR_Command_" . $f;
            // List of commands
            if (empty($GLOBALS['_PEAR_Command_objects'][$class])) {
                $GLOBALS['_PEAR_Command_objects'][$class] = "$dir/" . $f . '.php';
            }

            $parser->parse(file_get_contents("$dir/$file"));
            $implements = $parser->getData();
            foreach ($implements as $command => $desc) {
                if ($command == 'attribs') {
                    continue;
                }

                if (isset($GLOBALS['_PEAR_Command_commandlist'][$command])) {
                    return PEAR::raiseError('Command "' . $command . '" already registered in ' .
                        'class "' . $GLOBALS['_PEAR_Command_commandlist'][$command] . '"');
                }

                $GLOBALS['_PEAR_Command_commandlist'][$command] = $class;
                $GLOBALS['_PEAR_Command_commanddesc'][$command] = $desc['summary'];
                if (isset($desc['shortcut'])) {
                    $shortcut = $desc['shortcut'];
                    if (isset($GLOBALS['_PEAR_Command_shortcuts'][$shortcut])) {
                        return PEAR::raiseError('Command shortcut "' . $shortcut . '" already ' .
                            'registered to command "' . $command . '" in class "' .
                            $GLOBALS['_PEAR_Command_commandlist'][$command] . '"');
                    }
                    $GLOBALS['_PEAR_Command_shortcuts'][$shortcut] = $command;
                }

                if (isset($desc['options']) && $desc['options']) {
                    foreach ($desc['options'] as $oname => $option) {
                        if (isset($option['shortopt']) && strlen($option['shortopt']) > 1) {
                            return PEAR::raiseError('Option "' . $oname . '" short option "' .
                                $option['shortopt'] . '" must be ' .
                                'only 1 character in Command "' . $command . '" in class "' .
                                $class . '"');
                        }
                    }
                }
            }
        }

        ksort($GLOBALS['_PEAR_Command_shortcuts']);
        ksort($GLOBALS['_PEAR_Command_commandlist']);
        @closedir($dp);
        return true;
    }

    // }}}
    // {{{ getCommands()

    /**
     * Get the list of currently supported commands, and what
     * classes implement them.
     *
     * @return array command => implementing class
     */
    public static function getCommands()
    {
        if (empty($GLOBALS['_PEAR_Command_commandlist'])) {
            PEAR_Command::registerCommands();
        }
        return $GLOBALS['_PEAR_Command_commandlist'];
    }

    // }}}
    // {{{ getShortcuts()

    /**
     * Get the list of command shortcuts.
     *
     * @return array shortcut => command
     */
    public static function getShortcuts()
    {
        if (empty($GLOBALS['_PEAR_Command_shortcuts'])) {
            PEAR_Command::registerCommands();
        }
        return $GLOBALS['_PEAR_Command_shortcuts'];
    }

    // }}}
    // {{{ getGetoptArgs()

    /**
     * Compiles arguments for getopt.
     *
     * @param string $command     command to get optstring for
     * @param string $short_args  (reference) short getopt format
     * @param array  $long_args   (reference) long getopt format
     *
     * @return void
     */
    public static function getGetoptArgs($command, &$short_args, &$long_args)
    {
        if (empty($GLOBALS['_PEAR_Command_commandlist'])) {
            PEAR_Command::registerCommands();
        }
        if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) {
            $command = $GLOBALS['_PEAR_Command_shortcuts'][$command];
        }
        if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) {
            return null;
        }
        $obj = &PEAR_Command::getObject($command);
        return $obj->getGetoptArgs($command, $short_args, $long_args);
    }

    // }}}
    // {{{ getDescription()

    /**
     * Get description for a command.
     *
     * @param  string $command Name of the command
     *
     * @return string command description
     */
    public static function getDescription($command)
    {
        if (!isset($GLOBALS['_PEAR_Command_commanddesc'][$command])) {
            return null;
        }
        return $GLOBALS['_PEAR_Command_commanddesc'][$command];
    }

    // }}}
    // {{{ getHelp()

    /**
     * Get help for command.
     *
     * @param string $command Name of the command to return help for
     */
    public static function getHelp($command)
    {
        $cmds = PEAR_Command::getCommands();
        if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) {
            $command = $GLOBALS['_PEAR_Command_shortcuts'][$command];
        }
        if (isset($cmds[$command])) {
            $obj = &PEAR_Command::getObject($command);
            return $obj->getHelp($command);
        }
        return false;
    }
    // }}}
}PKr�Z�ٲ�=�=PEAR/PackageFile.phpnu�[���<?php
/**
 * PEAR_PackageFile, package.xml parsing utility class
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a1
 */

/**
 * needed for PEAR_VALIDATE_* constants
 */
require_once 'PEAR/Validate.php';
/**
 * Error code if the package.xml <package> tag does not contain a valid version
 */
define('PEAR_PACKAGEFILE_ERROR_NO_PACKAGEVERSION', 1);
/**
 * Error code if the package.xml <package> tag version is not supported (version 1.0 and 1.1 are the only supported versions,
 * currently
 */
define('PEAR_PACKAGEFILE_ERROR_INVALID_PACKAGEVERSION', 2);
/**
 * Abstraction for the package.xml package description file
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 */
class PEAR_PackageFile
{
    /**
     * @var PEAR_Config
     */
    var $_config;
    var $_debug;

    var $_logger = false;
    /**
     * @var boolean
     */
    var $_rawReturn = false;

    /**
     * helper for extracting Archive_Tar errors
     * @var array
     * @access private
     */
    var $_extractErrors = array();

    /**
     *
     * @param   PEAR_Config $config
     * @param   ?   $debug
     * @param   string @tmpdir Optional temporary directory for uncompressing
     *          files
     */
    function __construct(&$config, $debug = false)
    {
        $this->_config = $config;
        $this->_debug = $debug;
    }

    /**
     * Turn off validation - return a parsed package.xml without checking it
     *
     * This is used by the package-validate command
     */
    function rawReturn()
    {
        $this->_rawReturn = true;
    }

    function setLogger(&$l)
    {
        $this->_logger = &$l;
    }

    /**
     * Create a PEAR_PackageFile_Parser_v* of a given version.
     * @param   int $version
     * @return  PEAR_PackageFile_Parser_v1|PEAR_PackageFile_Parser_v1
     */
    function &parserFactory($version)
    {
        if (!in_array($version[0], array('1', '2'))) {
            $a = false;
            return $a;
        }

        include_once 'PEAR/PackageFile/Parser/v' . $version[0] . '.php';
        $version = $version[0];
        $class = "PEAR_PackageFile_Parser_v$version";
        $a = new $class;
        return $a;
    }

    /**
     * For simpler unit-testing
     * @return string
     */
    function getClassPrefix()
    {
        return 'PEAR_PackageFile_v';
    }

    /**
     * Create a PEAR_PackageFile_v* of a given version.
     * @param   int $version
     * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v1
     */
    function &factory($version)
    {
        if (!in_array($version[0], array('1', '2'))) {
            $a = false;
            return $a;
        }

        include_once 'PEAR/PackageFile/v' . $version[0] . '.php';
        $version = $version[0];
        $class = $this->getClassPrefix() . $version;
        $a = new $class;
        return $a;
    }

    /**
     * Create a PEAR_PackageFile_v* from its toArray() method
     *
     * WARNING: no validation is performed, the array is assumed to be valid,
     * always parse from xml if you want validation.
     * @param   array $arr
     * @return PEAR_PackageFileManager_v1|PEAR_PackageFileManager_v2
     * @uses    factory() to construct the returned object.
     */
    function &fromArray($arr)
    {
        if (isset($arr['xsdversion'])) {
            $obj = &$this->factory($arr['xsdversion']);
            if ($this->_logger) {
                $obj->setLogger($this->_logger);
            }

            $obj->setConfig($this->_config);
            $obj->fromArray($arr);
            return $obj;
        }

        if (isset($arr['package']['attribs']['version'])) {
            $obj = &$this->factory($arr['package']['attribs']['version']);
        } else {
            $obj = &$this->factory('1.0');
        }

        if ($this->_logger) {
            $obj->setLogger($this->_logger);
        }

        $obj->setConfig($this->_config);
        $obj->fromArray($arr);
        return $obj;
    }

    /**
     * Create a PEAR_PackageFile_v* from an XML string.
     * @access  public
     * @param   string $data contents of package.xml file
     * @param   int $state package state (one of PEAR_VALIDATE_* constants)
     * @param   string $file full path to the package.xml file (and the files
     *          it references)
     * @param   string $archive optional name of the archive that the XML was
     *          extracted from, if any
     * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v2
     * @uses    parserFactory() to construct a parser to load the package.
     */
    function &fromXmlString($data, $state, $file, $archive = false)
    {
        if (preg_match('/<package[^>]+version=[\'"]([0-9]+\.[0-9]+)[\'"]/', $data, $packageversion)) {
            if (!in_array($packageversion[1], array('1.0', '2.0', '2.1'))) {
                return PEAR::raiseError('package.xml version "' . $packageversion[1] .
                    '" is not supported, only 1.0, 2.0, and 2.1 are supported.');
            }

            $object = &$this->parserFactory($packageversion[1]);
            if ($this->_logger) {
                $object->setLogger($this->_logger);
            }

            $object->setConfig($this->_config);
            $pf = $object->parse($data, $file, $archive);
            if (PEAR::isError($pf)) {
                return $pf;
            }

            if ($this->_rawReturn) {
                return $pf;
            }

            if (!$pf->validate($state)) {;
                if ($this->_config->get('verbose') > 0
                    && $this->_logger && $pf->getValidationWarnings(false)
                ) {
                    foreach ($pf->getValidationWarnings(false) as $warning) {
                        $this->_logger->log(0, 'ERROR: ' . $warning['message']);
                    }
                }

                $a = PEAR::raiseError('Parsing of package.xml from file "' . $file . '" failed',
                    2, null, null, $pf->getValidationWarnings());
                return $a;
            }

            if ($this->_logger && $pf->getValidationWarnings(false)) {
                foreach ($pf->getValidationWarnings() as $warning) {
                    $this->_logger->log(0, 'WARNING: ' . $warning['message']);
                }
            }

            if (method_exists($pf, 'flattenFilelist')) {
                $pf->flattenFilelist(); // for v2
            }

            return $pf;
        } elseif (preg_match('/<package[^>]+version=[\'"]([^"\']+)[\'"]/', $data, $packageversion)) {
            $a = PEAR::raiseError('package.xml file "' . $file .
                '" has unsupported package.xml <package> version "' . $packageversion[1] . '"');
            return $a;
        } else {
            if (!class_exists('PEAR_ErrorStack')) {
                require_once 'PEAR/ErrorStack.php';
            }

            PEAR_ErrorStack::staticPush('PEAR_PackageFile',
                PEAR_PACKAGEFILE_ERROR_NO_PACKAGEVERSION,
                'warning', array('xml' => $data), 'package.xml "' . $file .
                    '" has no package.xml <package> version');
            $object = &$this->parserFactory('1.0');
            $object->setConfig($this->_config);
            $pf = $object->parse($data, $file, $archive);
            if (PEAR::isError($pf)) {
                return $pf;
            }

            if ($this->_rawReturn) {
                return $pf;
            }

            if (!$pf->validate($state)) {
                $a = PEAR::raiseError('Parsing of package.xml from file "' . $file . '" failed',
                    2, null, null, $pf->getValidationWarnings());
                return $a;
            }

            if ($this->_logger && $pf->getValidationWarnings(false)) {
                foreach ($pf->getValidationWarnings() as $warning) {
                    $this->_logger->log(0, 'WARNING: ' . $warning['message']);
                }
            }

            if (method_exists($pf, 'flattenFilelist')) {
                $pf->flattenFilelist(); // for v2
            }

            return $pf;
        }
    }

    /**
     * Register a temporary file or directory.  When the destructor is
     * executed, all registered temporary files and directories are
     * removed.
     *
     * @param string  $file  name of file or directory
     * @return  void
     */
    static function addTempFile($file)
    {
        $GLOBALS['_PEAR_Common_tempfiles'][] = $file;
    }

    /**
     * Create a PEAR_PackageFile_v* from a compressed Tar or Tgz file.
     * @access  public
     * @param string contents of package.xml file
     * @param int package state (one of PEAR_VALIDATE_* constants)
     * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v2
     * @using   Archive_Tar to extract the files
     * @using   fromPackageFile() to load the package after the package.xml
     *          file is extracted.
     */
    function &fromTgzFile($file, $state)
    {
        if (!class_exists('Archive_Tar')) {
            require_once 'Archive/Tar.php';
        }

        $tar = new Archive_Tar($file);
        if ($this->_debug <= 1) {
            $tar->pushErrorHandling(PEAR_ERROR_RETURN);
        }

        $content = $tar->listContent();
        if ($this->_debug <= 1) {
            $tar->popErrorHandling();
        }

        if (!is_array($content)) {
            if (is_string($file) && strlen($file) < 255 &&
                  (!file_exists($file) || !@is_file($file))) {
                $ret = PEAR::raiseError("could not open file \"$file\"");
                return $ret;
            }

            $file = realpath($file);
            $ret = PEAR::raiseError("Could not get contents of package \"$file\"".
                                     '. Invalid tgz file.');
            return $ret;
        }

        if (!count($content) && !@is_file($file)) {
            $ret = PEAR::raiseError("could not open file \"$file\"");
            return $ret;
        }

        $xml      = null;
        $origfile = $file;
        foreach ($content as $file) {
            $name = $file['filename'];
            if ($name == 'package2.xml') { // allow a .tgz to distribute both versions
                $xml = $name;
                break;
            }

            if ($name == 'package.xml') {
                $xml = $name;
                break;
            } elseif (preg_match('/package.xml$/', $name, $match)) {
                $xml = $name;
                break;
            }
        }

        $tmpdir = System::mktemp('-t "' . $this->_config->get('temp_dir') . '" -d pear');
        if ($tmpdir === false) {
            $ret = PEAR::raiseError("there was a problem with getting the configured temp directory");
            return $ret;
        }

        PEAR_PackageFile::addTempFile($tmpdir);

        $this->_extractErrors();
        PEAR::staticPushErrorHandling(PEAR_ERROR_CALLBACK, array($this, '_extractErrors'));

        if (!$xml || !$tar->extractList(array($xml), $tmpdir)) {
            $extra = implode("\n", $this->_extractErrors());
            if ($extra) {
                $extra = ' ' . $extra;
            }

            PEAR::staticPopErrorHandling();
            $ret = PEAR::raiseError('could not extract the package.xml file from "' .
                $origfile . '"' . $extra);
            return $ret;
        }

        PEAR::staticPopErrorHandling();
        $ret = &PEAR_PackageFile::fromPackageFile("$tmpdir/$xml", $state, $origfile);
        return $ret;
    }

    /**
     * helper callback for extracting Archive_Tar errors
     *
     * @param PEAR_Error|null $err
     * @return array
     * @access private
     */
    function _extractErrors($err = null)
    {
        static $errors = array();
        if ($err === null) {
            $e = $errors;
            $errors = array();
            return $e;
        }
        $errors[] = $err->getMessage();
    }

    /**
     * Create a PEAR_PackageFile_v* from a package.xml file.
     *
     * @access public
     * @param   string  $descfile  name of package xml file
     * @param   int     $state package state (one of PEAR_VALIDATE_* constants)
     * @param   string|false $archive name of the archive this package.xml came
     *          from, if any
     * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v2
     * @uses    PEAR_PackageFile::fromXmlString to create the oject after the
     *          XML is loaded from the package.xml file.
     */
    function &fromPackageFile($descfile, $state, $archive = false)
    {
        $fp = false;
        if (is_string($descfile) && strlen($descfile) < 255 &&
             (
              !file_exists($descfile) || !is_file($descfile) || !is_readable($descfile)
              || (!$fp = @fopen($descfile, 'r'))
             )
        ) {
            $a = PEAR::raiseError("Unable to open $descfile");
            return $a;
        }

        // read the whole thing so we only get one cdata callback
        // for each block of cdata
        fclose($fp);
        $data = file_get_contents($descfile);
        $ret = &PEAR_PackageFile::fromXmlString($data, $state, $descfile, $archive);
        return $ret;
    }

    /**
     * Create a PEAR_PackageFile_v* from a .tgz archive or package.xml file.
     *
     * This method is able to extract information about a package from a .tgz
     * archive or from a XML package definition file.
     *
     * @access public
     * @param   string  $info file name
     * @param   int     $state package state (one of PEAR_VALIDATE_* constants)
     * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v2
     * @uses    fromPackageFile() if the file appears to be XML
     * @uses    fromTgzFile() to load all non-XML files
     */
    function &fromAnyFile($info, $state)
    {
        if (is_dir($info)) {
            $dir_name = realpath($info);
            if (file_exists($dir_name . '/package.xml')) {
                $info = PEAR_PackageFile::fromPackageFile($dir_name .  '/package.xml', $state);
            } elseif (file_exists($dir_name .  '/package2.xml')) {
                $info = PEAR_PackageFile::fromPackageFile($dir_name .  '/package2.xml', $state);
            } else {
                $info = PEAR::raiseError("No package definition found in '$info' directory");
            }

            return $info;
        }

        $fp = false;
        if (is_string($info) && strlen($info) < 255 &&
             (file_exists($info) || ($fp = @fopen($info, 'r')))
        ) {

            if ($fp) {
                fclose($fp);
            }

            $tmp = substr($info, -4);
            if ($tmp == '.xml') {
                $info = &PEAR_PackageFile::fromPackageFile($info, $state);
            } elseif ($tmp == '.tar' || $tmp == '.tgz') {
                $info = &PEAR_PackageFile::fromTgzFile($info, $state);
            } else {
                $fp   = fopen($info, 'r');
                $test = fread($fp, 5);
                fclose($fp);
                if ($test == '<?xml') {
                    $info = &PEAR_PackageFile::fromPackageFile($info, $state);
                } else {
                    $info = &PEAR_PackageFile::fromTgzFile($info, $state);
                }
            }

            return $info;
        }

        $info = PEAR::raiseError("Cannot open '$info' for parsing");
        return $info;
    }
}
PKr�Z�JD��PEAR/Task/Replace.phpnu�[���<?php
/**
 * <tasks:replace>
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Greg Beaver <cellog@php.net>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 * @since     File available since Release 1.4.0a1
 */
/**
 * Base class
 */
require_once 'PEAR/Task/Common.php';
/**
 * Implements the replace file task.
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 */
class PEAR_Task_Replace extends PEAR_Task_Common
{
    public $type = 'simple';
    public $phase = PEAR_TASK_PACKAGEANDINSTALL;
    public $_replacements;

    /**
     * Validate the raw xml at parsing-time.
     *
     * @param  PEAR_PackageFile_v2
     * @param  array raw, parsed xml
     * @param  PEAR_Config
     */
    public static function validateXml($pkg, $xml, $config, $fileXml)
    {
        if (!isset($xml['attribs'])) {
            return array(PEAR_TASK_ERROR_NOATTRIBS);
        }
        if (!isset($xml['attribs']['type'])) {
            return array(PEAR_TASK_ERROR_MISSING_ATTRIB, 'type');
        }
        if (!isset($xml['attribs']['to'])) {
            return array(PEAR_TASK_ERROR_MISSING_ATTRIB, 'to');
        }
        if (!isset($xml['attribs']['from'])) {
            return array(PEAR_TASK_ERROR_MISSING_ATTRIB, 'from');
        }
        if ($xml['attribs']['type'] == 'pear-config') {
            if (!in_array($xml['attribs']['to'], $config->getKeys())) {
                return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'to', $xml['attribs']['to'],
                    $config->getKeys(), );
            }
        } elseif ($xml['attribs']['type'] == 'php-const') {
            if (defined($xml['attribs']['to'])) {
                return true;
            } else {
                return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'to', $xml['attribs']['to'],
                    array('valid PHP constant'), );
            }
        } elseif ($xml['attribs']['type'] == 'package-info') {
            if (in_array(
                $xml['attribs']['to'],
                array('name', 'summary', 'channel', 'notes', 'extends', 'description',
                    'release_notes', 'license', 'release-license', 'license-uri',
                    'version', 'api-version', 'state', 'api-state', 'release_date',
                    'date', 'time', )
            )) {
                return true;
            } else {
                return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'to', $xml['attribs']['to'],
                    array('name', 'summary', 'channel', 'notes', 'extends', 'description',
                    'release_notes', 'license', 'release-license', 'license-uri',
                    'version', 'api-version', 'state', 'api-state', 'release_date',
                    'date', 'time', ), );
            }
        } else {
            return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'type', $xml['attribs']['type'],
                array('pear-config', 'package-info', 'php-const'), );
        }

        return true;
    }

    /**
     * Initialize a task instance with the parameters
     * @param array raw, parsed xml
     * @param unused
     * @param unused
     */
    public function init($xml, $attribs, $lastVersion = null)
    {
        $this->_replacements = isset($xml['attribs']) ? array($xml) : $xml;
    }

    /**
     * Do a package.xml 1.0 replacement, with additional package-info fields available
     *
     * See validateXml() source for the complete list of allowed fields
     *
     * @param  PEAR_PackageFile_v1|PEAR_PackageFile_v2
     * @param  string file contents
     * @param  string the eventual final file location (informational only)
     * @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail
     *                                 (use $this->throwError), otherwise return the new contents
     */
    public function startSession($pkg, $contents, $dest)
    {
        $subst_from = $subst_to = array();
        foreach ($this->_replacements as $a) {
            $a = $a['attribs'];
            $to = '';
            if ($a['type'] == 'pear-config') {
                if ($this->installphase == PEAR_TASK_PACKAGE) {
                    return false;
                }
                if ($a['to'] == 'master_server') {
                    $chan = $this->registry->getChannel($pkg->getChannel());
                    if (!PEAR::isError($chan)) {
                        $to = $chan->getServer();
                    } else {
                        $this->logger->log(0, "$dest: invalid pear-config replacement: $a[to]");

                        return false;
                    }
                } else {
                    if ($this->config->isDefinedLayer('ftp')) {
                        // try the remote config file first
                        $to = $this->config->get($a['to'], 'ftp', $pkg->getChannel());
                        if (is_null($to)) {
                            // then default to local
                            $to = $this->config->get($a['to'], null, $pkg->getChannel());
                        }
                    } else {
                        $to = $this->config->get($a['to'], null, $pkg->getChannel());
                    }
                }
                if (is_null($to)) {
                    $this->logger->log(0, "$dest: invalid pear-config replacement: $a[to]");

                    return false;
                }
            } elseif ($a['type'] == 'php-const') {
                if ($this->installphase == PEAR_TASK_PACKAGE) {
                    return false;
                }
                if (defined($a['to'])) {
                    $to = constant($a['to']);
                } else {
                    $this->logger->log(0, "$dest: invalid php-const replacement: $a[to]");

                    return false;
                }
            } else {
                if ($t = $pkg->packageInfo($a['to'])) {
                    $to = $t;
                } else {
                    $this->logger->log(0, "$dest: invalid package-info replacement: $a[to]");

                    return false;
                }
            }
            if (!is_null($to)) {
                $subst_from[] = $a['from'];
                $subst_to[] = $to;
            }
        }
        $this->logger->log(
            3, "doing ".sizeof($subst_from).
            " substitution(s) for $dest"
        );
        if (sizeof($subst_from)) {
            $contents = str_replace($subst_from, $subst_to, $contents);
        }

        return $contents;
    }
}
PKr�Z&%75))PEAR/Task/Windowseol/rw.phpnu�[���<?php
/**
 * <tasks:windowseol> - read/write version
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Greg Beaver <cellog@php.net>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 * @since     File available since Release 1.4.0a10
 */
/**
 * Base class
 */
require_once 'PEAR/Task/Windowseol.php';
/**
 * Abstracts the windowseol task xml.
 *
 * @category  pear
 * @package   PEAR
 * @author    Greg Beaver <cellog@php.net>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @version   Release: 1.10.16
 * @link      http://pear.php.net/package/PEAR
 * @since     Class available since Release 1.4.0a10
 */
class PEAR_Task_Windowseol_rw extends PEAR_Task_Windowseol
{
    function __construct(&$pkg, &$config, &$logger, $fileXml)
    {
        parent::__construct($config, $logger, PEAR_TASK_PACKAGE);
        $this->_contents = $fileXml;
        $this->_pkg = &$pkg;
        $this->_params = array();
    }

    public function validate()
    {
        return true;
    }

    public function getName()
    {
        return 'windowseol';
    }

    public function getXml()
    {
        return '';
    }
}
?>
PKr�Z�3}PEAR/Task/Replace/rw.phpnu�[���<?php
/**
 * <tasks:replace> - read/write version
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Greg Beaver <cellog@php.net>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 * @since     File available since Release 1.4.0a10
 */
/**
 * Base class
 */
require_once 'PEAR/Task/Replace.php';
/**
 * Abstracts the replace task xml.
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a10
 */
class PEAR_Task_Replace_rw extends PEAR_Task_Replace
{
    public function __construct(&$pkg, &$config, &$logger, $fileXml)
    {
        parent::__construct($config, $logger, PEAR_TASK_PACKAGE);
        $this->_contents = $fileXml;
        $this->_pkg = &$pkg;
        $this->_params = array();
    }

    public function validate()
    {
        return $this->validateXml($this->_pkg, $this->_params, $this->config, $this->_contents);
    }

    public function setInfo($from, $to, $type)
    {
        $this->_params = array('attribs' => array('from' => $from, 'to' => $to, 'type' => $type));
    }

    public function getName()
    {
        return 'replace';
    }

    public function getXml()
    {
        return $this->_params;
    }
}
PKr�Z&
i."PEAR/Task/Postinstallscript/rw.phpnu�[���<?php
/**
 * <tasks:postinstallscript> - read/write version
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Greg Beaver <cellog@php.net>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 * @since     File available since Release 1.4.0a10
 */
/**
 * Base class
 */
require_once 'PEAR/Task/Postinstallscript.php';
/**
 * Abstracts the postinstallscript file task xml.
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a10
 */
class PEAR_Task_Postinstallscript_rw extends PEAR_Task_Postinstallscript
{
    /**
     * parent package file object
     *
     * @var PEAR_PackageFile_v2_rw
     */
    public $_pkg;
    /**
     * Enter description here...
     *
     * @param PEAR_PackageFile_v2_rw $pkg     Package
     * @param PEAR_Config            $config  Config
     * @param PEAR_Frontend          $logger  Logger
     * @param array                  $fileXml XML
     *
     * @return PEAR_Task_Postinstallscript_rw
     */
    function __construct(&$pkg, &$config, &$logger, $fileXml)
    {
        parent::__construct($config, $logger, PEAR_TASK_PACKAGE);
        $this->_contents = $fileXml;
        $this->_pkg = &$pkg;
        $this->_params = array();
    }

    public function validate()
    {
        return $this->validateXml($this->_pkg, $this->_params, $this->config, $this->_contents);
    }

    public function getName()
    {
        return 'postinstallscript';
    }

    /**
     * add a simple <paramgroup> to the post-install script
     *
     * Order is significant, so call this method in the same
     * sequence the users should see the paramgroups.  The $params
     * parameter should either be the result of a call to {@link getParam()}
     * or an array of calls to getParam().
     *
     * Use {@link addConditionTypeGroup()} to add a <paramgroup> containing
     * a <conditiontype> tag
     *
     * @param string       $id           <paramgroup> id as seen by the script
     * @param array|false  $params       array of getParam() calls, or false for no params
     * @param string|false $instructions
     */
    public function addParamGroup($id, $params = false, $instructions = false)
    {
        if ($params && isset($params[0]) && !isset($params[1])) {
            $params = $params[0];
        }
        $stuff =
            array(
                $this->_pkg->getTasksNs().':id' => $id,
            );
        if ($instructions) {
            $stuff[$this->_pkg->getTasksNs().':instructions'] = $instructions;
        }
        if ($params) {
            $stuff[$this->_pkg->getTasksNs().':param'] = $params;
        }
        $this->_params[$this->_pkg->getTasksNs().':paramgroup'][] = $stuff;
    }

    /**
     * Add a complex <paramgroup> to the post-install script with conditions
     *
     * This inserts a <paramgroup> with
     *
     * Order is significant, so call this method in the same
     * sequence the users should see the paramgroups.  The $params
     * parameter should either be the result of a call to {@link getParam()}
     * or an array of calls to getParam().
     *
     * Use {@link addParamGroup()} to add a simple <paramgroup>
     *
     * @param string       $id            <paramgroup> id as seen by the script
     * @param string       $oldgroup      <paramgroup> id of the section referenced by
     *                                    <conditiontype>
     * @param string       $param         name of the <param> from the older section referenced
     *                                    by <contitiontype>
     * @param string       $value         value to match of the parameter
     * @param string       $conditiontype one of '=', '!=', 'preg_match'
     * @param array|false  $params        array of getParam() calls, or false for no params
     * @param string|false $instructions
     */
    public function addConditionTypeGroup($id,
        $oldgroup,
        $param,
        $value,
        $conditiontype = '=',
        $params = false,
        $instructions = false
    ) {
        if ($params && isset($params[0]) && !isset($params[1])) {
            $params = $params[0];
        }
        $stuff = array(
            $this->_pkg->getTasksNs().':id' => $id,
        );
        if ($instructions) {
            $stuff[$this->_pkg->getTasksNs().':instructions'] = $instructions;
        }
        $stuff[$this->_pkg->getTasksNs().':name'] = $oldgroup.'::'.$param;
        $stuff[$this->_pkg->getTasksNs().':conditiontype'] = $conditiontype;
        $stuff[$this->_pkg->getTasksNs().':value'] = $value;
        if ($params) {
            $stuff[$this->_pkg->getTasksNs().':param'] = $params;
        }
        $this->_params[$this->_pkg->getTasksNs().':paramgroup'][] = $stuff;
    }

    public function getXml()
    {
        return $this->_params;
    }

    /**
     * Use to set up a param tag for use in creating a paramgroup
     *
     * @param mixed  $name    Name of parameter
     * @param mixed  $prompt  Prompt
     * @param string $type    Type, defaults to 'string'
     * @param mixed  $default Default value
     *
     * @return array
     */
    public function getParam(
        $name, $prompt, $type = 'string', $default = null
    ) {
        if ($default !== null) {
            return
            array(
                $this->_pkg->getTasksNs().':name' => $name,
                $this->_pkg->getTasksNs().':prompt' => $prompt,
                $this->_pkg->getTasksNs().':type' => $type,
                $this->_pkg->getTasksNs().':default' => $default,
            );
        }

        return
            array(
                $this->_pkg->getTasksNs().':name' => $name,
                $this->_pkg->getTasksNs().':prompt' => $prompt,
                $this->_pkg->getTasksNs().':type' => $type,
            );
    }
}
PKr�Z�-!PEAR/Task/Common.phpnu�[���<?php
/**
 * PEAR_Task_Common, base class for installer tasks
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Greg Beaver <cellog@php.net>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 * @since     File available since Release 1.4.0a1
 */
/**#@+
 * Error codes for task validation routines
 */
define('PEAR_TASK_ERROR_NOATTRIBS', 1);
define('PEAR_TASK_ERROR_MISSING_ATTRIB', 2);
define('PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE', 3);
define('PEAR_TASK_ERROR_INVALID', 4);
/**#@-*/
define('PEAR_TASK_PACKAGE', 1);
define('PEAR_TASK_INSTALL', 2);
define('PEAR_TASK_PACKAGEANDINSTALL', 3);
/**
 * A task is an operation that manipulates the contents of a file.
 *
 * Simple tasks operate on 1 file.  Multiple tasks are executed after all files have been
 * processed and installed, and are designed to operate on all files containing the task.
 * The Post-install script task simply takes advantage of the fact that it will be run
 * after installation, replace is a simple task.
 *
 * Combining tasks is possible, but ordering is significant.
 *
 * <file name="test.php" role="php">
 *  <tasks:replace from="@data-dir@" to="data_dir" type="pear-config"/>
 *  <tasks:postinstallscript/>
 * </file>
 *
 * This will first replace any instance of @data-dir@ in the test.php file
 * with the path to the current data directory.  Then, it will include the
 * test.php file and run the script it contains to configure the package post-installation.
 *
 * @category  pear
 * @package   PEAR
 * @author    Greg Beaver <cellog@php.net>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @version   Release: 1.10.16
 * @link      http://pear.php.net/package/PEAR
 * @since     Class available since Release 1.4.0a1
 * @abstract
 */
class PEAR_Task_Common
{
    /**
     * Valid types for this version are 'simple' and 'multiple'
     *
     * - simple tasks operate on the contents of a file and write out changes to disk
     * - multiple tasks operate on the contents of many files and write out the
     *   changes directly to disk
     *
     * Child task classes must override this property.
     *
     * @access protected
     */
    protected $type = 'simple';
    /**
     * Determines which install phase this task is executed under
     */
    public $phase = PEAR_TASK_INSTALL;
    /**
     * @access protected
     */
    protected $config;
    /**
     * @access protected
     */
    protected $registry;
    /**
     * @access protected
     */
    public $logger;
    /**
     * @access protected
     */
    protected $installphase;
    /**
     * @param PEAR_Config
     * @param PEAR_Common
     */
    function __construct(&$config, &$logger, $phase)
    {
        $this->config = &$config;
        $this->registry = &$config->getRegistry();
        $this->logger = &$logger;
        $this->installphase = $phase;
        if ($this->type == 'multiple') {
            $GLOBALS['_PEAR_TASK_POSTINSTANCES'][get_class($this)][] = &$this;
        }
    }

    /**
     * Validate the basic contents of a task tag.
     *
     * @param PEAR_PackageFile_v2
     * @param array
     * @param PEAR_Config
     * @param array the entire parsed <file> tag
     *
     * @return true|array On error, return an array in format:
     *                    array(PEAR_TASK_ERROR_???[, param1][, param2][, ...])
     *
     * For PEAR_TASK_ERROR_MISSING_ATTRIB, pass the attribute name in
     * For PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, pass the attribute name and
     * an array of legal values in
     *
     * @abstract
     */
    public static function validateXml($pkg, $xml, $config, $fileXml)
    {
    }

    /**
     * Initialize a task instance with the parameters
     *
     * @param    array raw, parsed xml
     * @param    array attributes from the <file> tag containing this task
     * @param    string|null last installed version of this package
     * @abstract
     */
    public function init($xml, $fileAttributes, $lastVersion)
    {
    }

    /**
     * Begin a task processing session.  All multiple tasks will be processed
     * after each file has been successfully installed, all simple tasks should
     * perform their task here and return any errors using the custom
     * throwError() method to allow forward compatibility
     *
     * This method MUST NOT write out any changes to disk
     *
     * @param    PEAR_PackageFile_v2
     * @param    string file contents
     * @param    string the eventual final file location (informational only)
     * @return   string|false|PEAR_Error false to skip this file, PEAR_Error to fail
     *           (use $this->throwError), otherwise return the new contents
     * @abstract
     */
    public function startSession($pkg, $contents, $dest)
    {
    }

    /**
     * This method is used to process each of the tasks for a particular
     * multiple class type.  Simple tasks need not implement this method.
     *
     * @param    array an array of tasks
     * @access   protected
     */
    public static function run($tasks)
    {
    }

    /**
     * @final
     */
    public static function hasPostinstallTasks()
    {
        return isset($GLOBALS['_PEAR_TASK_POSTINSTANCES']);
    }

     /**
      * @final
      */
    public static function runPostinstallTasks()
    {
        foreach ($GLOBALS['_PEAR_TASK_POSTINSTANCES'] as $class => $tasks) {
            $err = call_user_func(
                array($class, 'run'),
                $GLOBALS['_PEAR_TASK_POSTINSTANCES'][$class]
            );
            if ($err) {
                return PEAR_Task_Common::throwError($err);
            }
        }
        unset($GLOBALS['_PEAR_TASK_POSTINSTANCES']);
    }

    /**
     * Determines whether a role is a script
     * @return bool
     */
    public function isScript()
    {
            return $this->type == 'script';
    }

    public function throwError($msg, $code = -1)
    {
        include_once 'PEAR.php';

        return PEAR::raiseError($msg, $code);
    }
}
PKr�ZD$���PEAR/Task/Windowseol.phpnu�[���<?php
/**
 * <tasks:windowseol>
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Greg Beaver <cellog@php.net>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 * @since     File available since Release 1.4.0a1
 */
/**
 * Base class
 */
require_once 'PEAR/Task/Common.php';
/**
 * Implements the windows line endsings file task.
 *
 * @category  pear
 * @package   PEAR
 * @author    Greg Beaver <cellog@php.net>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @version   Release: 1.10.16
 * @link      http://pear.php.net/package/PEAR
 * @since     Class available since Release 1.4.0a1
 */
class PEAR_Task_Windowseol extends PEAR_Task_Common
{
    public $type = 'simple';
    public $phase = PEAR_TASK_PACKAGE;
    public $_replacements;

    /**
     * Validate the raw xml at parsing-time.
     *
     * @param  PEAR_PackageFile_v2
     * @param  array raw, parsed xml
     * @param  PEAR_Config
     */
    public static function validateXml($pkg, $xml, $config, $fileXml)
    {
        if ($xml != '') {
            return array(PEAR_TASK_ERROR_INVALID, 'no attributes allowed');
        }

        return true;
    }

    /**
     * Initialize a task instance with the parameters
     * @param array raw, parsed xml
     * @param unused
     * @param unused
     */
    public function init($xml, $attribs, $lastVersion = null)
    {
    }

    /**
     * Replace all line endings with windows line endings
     *
     * See validateXml() source for the complete list of allowed fields
     *
     * @param  PEAR_PackageFile_v1|PEAR_PackageFile_v2
     * @param  string file contents
     * @param  string the eventual final file location (informational only)
     * @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail
     *                                 (use $this->throwError), otherwise return the new contents
     */
    public function startSession($pkg, $contents, $dest)
    {
        $this->logger->log(3, "replacing all line endings with \\r\\n in $dest");

        return preg_replace("/\r\n|\n\r|\r|\n/", "\r\n", $contents);
    }
}
PKr�ZZ�E�x9x9PEAR/Task/Postinstallscript.phpnu�[���<?php
/**
 * <tasks:postinstallscript>
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Greg Beaver <cellog@php.net>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 * @since     File available since Release 1.4.0a1
 */
/**
 * Base class
 */
require_once 'PEAR/Task/Common.php';
/**
 * Implements the postinstallscript file task.
 *
 * Note that post-install scripts are handled separately from installation, by the
 * "pear run-scripts" command
 *
 * @category  pear
 * @package   PEAR
 * @author    Greg Beaver <cellog@php.net>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @version   Release: 1.10.16
 * @link      http://pear.php.net/package/PEAR
 * @since     Class available since Release 1.4.0a1
 */
class PEAR_Task_Postinstallscript extends PEAR_Task_Common
{
    public $type = 'script';
    public $_class;
    public $_params;
    public $_obj;
    /**
     *
     * @var PEAR_PackageFile_v2
     */
    public $_pkg;
    public $_contents;
    public $phase = PEAR_TASK_INSTALL;

    /**
     * Validate the raw xml at parsing-time.
     *
     * This also attempts to validate the script to make sure it meets the criteria
     * for a post-install script
     *
     * @param  PEAR_PackageFile_v2
     * @param  array The XML contents of the <postinstallscript> tag
     * @param  PEAR_Config
     * @param  array the entire parsed <file> tag
     */
    public static function validateXml($pkg, $xml, $config, $fileXml)
    {
        if ($fileXml['role'] != 'php') {
            return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
            $fileXml['name'].'" must be role="php"', );
        }
        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        $file = $pkg->getFileContents($fileXml['name']);
        if (PEAR::isError($file)) {
            PEAR::popErrorHandling();

            return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
                $fileXml['name'].'" is not valid: '.
                $file->getMessage(), );
        } elseif ($file === null) {
            return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
                $fileXml['name'].'" could not be retrieved for processing!', );
        } else {
            $analysis = $pkg->analyzeSourceCode($file, true);
            if (!$analysis) {
                PEAR::popErrorHandling();
                $warnings = '';
                foreach ($pkg->getValidationWarnings() as $warn) {
                    $warnings .= $warn['message']."\n";
                }

                return array(PEAR_TASK_ERROR_INVALID, 'Analysis of post-install script "'.
                    $fileXml['name'].'" failed: '.$warnings, );
            }
            if (count($analysis['declared_classes']) != 1) {
                PEAR::popErrorHandling();

                return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
                    $fileXml['name'].'" must declare exactly 1 class', );
            }
            $class = $analysis['declared_classes'][0];
            if ($class != str_replace(
                array('/', '.php'), array('_', ''),
                $fileXml['name']
            ).'_postinstall') {
                PEAR::popErrorHandling();

                return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
                    $fileXml['name'].'" class "'.$class.'" must be named "'.
                    str_replace(
                        array('/', '.php'), array('_', ''),
                        $fileXml['name']
                    ).'_postinstall"', );
            }
            if (!isset($analysis['declared_methods'][$class])) {
                PEAR::popErrorHandling();

                return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
                    $fileXml['name'].'" must declare methods init() and run()', );
            }
            $methods = array('init' => 0, 'run' => 1);
            foreach ($analysis['declared_methods'][$class] as $method) {
                if (isset($methods[$method])) {
                    unset($methods[$method]);
                }
            }
            if (count($methods)) {
                PEAR::popErrorHandling();

                return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
                    $fileXml['name'].'" must declare methods init() and run()', );
            }
        }
        PEAR::popErrorHandling();
        $definedparams = array();
        $tasksNamespace = $pkg->getTasksNs().':';
        if (!isset($xml[$tasksNamespace.'paramgroup']) && isset($xml['paramgroup'])) {
            // in order to support the older betas, which did not expect internal tags
            // to also use the namespace
            $tasksNamespace = '';
        }
        if (isset($xml[$tasksNamespace.'paramgroup'])) {
            $params = $xml[$tasksNamespace.'paramgroup'];
            if (!is_array($params) || !isset($params[0])) {
                $params = array($params);
            }
            foreach ($params as $param) {
                if (!isset($param[$tasksNamespace.'id'])) {
                    return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
                        $fileXml['name'].'" <paramgroup> must have '.
                        'an '.$tasksNamespace.'id> tag', );
                }
                if (isset($param[$tasksNamespace.'name'])) {
                    if (!in_array($param[$tasksNamespace.'name'], $definedparams)) {
                        return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
                            $fileXml['name'].'" '.$tasksNamespace.
                            'paramgroup> id "'.$param[$tasksNamespace.'id'].
                            '" parameter "'.$param[$tasksNamespace.'name'].
                            '" has not been previously defined', );
                    }
                    if (!isset($param[$tasksNamespace.'conditiontype'])) {
                        return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
                            $fileXml['name'].'" '.$tasksNamespace.
                            'paramgroup> id "'.$param[$tasksNamespace.'id'].
                            '" must have a '.$tasksNamespace.
                            'conditiontype> tag containing either "=", '.
                            '"!=", or "preg_match"', );
                    }
                    if (!in_array(
                        $param[$tasksNamespace.'conditiontype'],
                        array('=', '!=', 'preg_match')
                    )) {
                        return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
                            $fileXml['name'].'" '.$tasksNamespace.
                            'paramgroup> id "'.$param[$tasksNamespace.'id'].
                            '" must have a '.$tasksNamespace.
                            'conditiontype> tag containing either "=", '.
                            '"!=", or "preg_match"', );
                    }
                    if (!isset($param[$tasksNamespace.'value'])) {
                        return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
                            $fileXml['name'].'" '.$tasksNamespace.
                            'paramgroup> id "'.$param[$tasksNamespace.'id'].
                            '" must have a '.$tasksNamespace.
                            'value> tag containing expected parameter value', );
                    }
                }
                if (isset($param[$tasksNamespace.'instructions'])) {
                    if (!is_string($param[$tasksNamespace.'instructions'])) {
                        return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
                            $fileXml['name'].'" '.$tasksNamespace.
                            'paramgroup> id "'.$param[$tasksNamespace.'id'].
                            '" '.$tasksNamespace.'instructions> must be simple text', );
                    }
                }
                if (!isset($param[$tasksNamespace.'param'])) {
                    continue; // <param> is no longer required
                }
                $subparams = $param[$tasksNamespace.'param'];
                if (!is_array($subparams) || !isset($subparams[0])) {
                    $subparams = array($subparams);
                }
                foreach ($subparams as $subparam) {
                    if (!isset($subparam[$tasksNamespace.'name'])) {
                        return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
                            $fileXml['name'].'" parameter for '.
                            $tasksNamespace.'paramgroup> id "'.
                            $param[$tasksNamespace.'id'].'" must have '.
                            'a '.$tasksNamespace.'name> tag', );
                    }
                    if (!preg_match(
                        '/[a-zA-Z0-9]+/',
                        $subparam[$tasksNamespace.'name']
                    )) {
                        return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
                            $fileXml['name'].'" parameter "'.
                            $subparam[$tasksNamespace.'name'].
                            '" for '.$tasksNamespace.'paramgroup> id "'.
                            $param[$tasksNamespace.'id'].
                            '" is not a valid name.  Must contain only alphanumeric characters', );
                    }
                    if (!isset($subparam[$tasksNamespace.'prompt'])) {
                        return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
                            $fileXml['name'].'" parameter "'.
                            $subparam[$tasksNamespace.'name'].
                            '" for '.$tasksNamespace.'paramgroup> id "'.
                            $param[$tasksNamespace.'id'].
                            '" must have a '.$tasksNamespace.'prompt> tag', );
                    }
                    if (!isset($subparam[$tasksNamespace.'type'])) {
                        return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
                            $fileXml['name'].'" parameter "'.
                            $subparam[$tasksNamespace.'name'].
                            '" for '.$tasksNamespace.'paramgroup> id "'.
                            $param[$tasksNamespace.'id'].
                            '" must have a '.$tasksNamespace.'type> tag', );
                    }
                    $definedparams[] = $param[$tasksNamespace.'id'].'::'.
                    $subparam[$tasksNamespace.'name'];
                }
            }
        }

        return true;
    }

    /**
     * Initialize a task instance with the parameters
     * @param array       $xml         raw, parsed xml
     * @param array       $fileattribs attributes from the <file> tag containing
     *                                 this task
     * @param string|null $lastversion last installed version of this package,
     *                                 if any (useful for upgrades)
     */
    public function init($xml, $fileattribs, $lastversion)
    {
        $this->_class = str_replace('/', '_', $fileattribs['name']);
        $this->_filename = $fileattribs['name'];
        $this->_class = str_replace('.php', '', $this->_class).'_postinstall';
        $this->_params = $xml;
        $this->_lastversion = $lastversion;
    }

    /**
     * Strip the tasks: namespace from internal params
     *
     * @access private
     */
    public function _stripNamespace($params = null)
    {
        if ($params === null) {
            $params = array();
            if (!is_array($this->_params)) {
                return;
            }
            foreach ($this->_params as $i => $param) {
                if (is_array($param)) {
                    $param = $this->_stripNamespace($param);
                }
                $params[str_replace($this->_pkg->getTasksNs().':', '', $i)] = $param;
            }
            $this->_params = $params;
        } else {
            $newparams = array();
            foreach ($params as $i => $param) {
                if (is_array($param)) {
                    $param = $this->_stripNamespace($param);
                }
                $newparams[str_replace($this->_pkg->getTasksNs().':', '', $i)] = $param;
            }

            return $newparams;
        }
    }

    /**
     * Unlike other tasks, the installed file name is passed in instead of the
     * file contents, because this task is handled post-installation
     *
     * @param mixed  $pkg      PEAR_PackageFile_v1|PEAR_PackageFile_v2
     * @param string $contents file name
     * @param string $dest     the eventual final file location (informational only)
     *
     * @return bool|PEAR_Error false to skip this file, PEAR_Error to fail
     *                         (use $this->throwError)
     */
    public function startSession($pkg, $contents, $dest)
    {
        if ($this->installphase != PEAR_TASK_INSTALL) {
            return false;
        }
        // remove the tasks: namespace if present
        $this->_pkg = $pkg;
        $this->_stripNamespace();
        $this->logger->log(
            0, 'Including external post-installation script "'.
            $contents.'" - any errors are in this script'
        );
        include_once $contents;
        if (class_exists($this->_class)) {
            $this->logger->log(0, 'Inclusion succeeded');
        } else {
            return $this->throwError(
                'init of post-install script class "'.$this->_class
                .'" failed'
            );
        }
        $this->_obj = new $this->_class();
        $this->logger->log(1, 'running post-install script "'.$this->_class.'->init()"');
        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        $res = $this->_obj->init($this->config, $pkg, $this->_lastversion);
        PEAR::popErrorHandling();
        if ($res) {
            $this->logger->log(0, 'init succeeded');
        } else {
            return $this->throwError(
                'init of post-install script "'.$this->_class.
                '->init()" failed'
            );
        }
        $this->_contents = $contents;

        return true;
    }

    /**
     * No longer used
     *
     * @see    PEAR_PackageFile_v2::runPostinstallScripts()
     * @param  array an array of tasks
     * @param  string install or upgrade
     * @access protected
     */
    public static function run($tasks)
    {
    }
}
PKr�Z\k��PEAR/Task/Unixeol/rw.phpnu�[���<?php
/**
 * <tasks:unixeol> - read/write version
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Greg Beaver <cellog@php.net>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 * @since     File available since Release 1.4.0a10
 */
/**
 * Base class
 */
require_once 'PEAR/Task/Unixeol.php';
/**
 * Abstracts the unixeol task xml.
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a10
 */
class PEAR_Task_Unixeol_rw extends PEAR_Task_Unixeol
{
    function __construct(&$pkg, &$config, &$logger, $fileXml)
    {
        parent::__construct($config, $logger, PEAR_TASK_PACKAGE);
        $this->_contents = $fileXml;
        $this->_pkg = &$pkg;
        $this->_params = array();
    }

    public function validate()
    {
        return true;
    }

    public function getName()
    {
        return 'unixeol';
    }

    public function getXml()
    {
        return '';
    }
}
?>
PKr�Z�����PEAR/Task/Unixeol.phpnu�[���<?php
/**
 * <tasks:unixeol>
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Greg Beaver <cellog@php.net>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 * @since     File available since Release 1.4.0a1
 */
/**
 * Base class
 */
require_once 'PEAR/Task/Common.php';
/**
 * Implements the unix line endings file task.
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 */
class PEAR_Task_Unixeol extends PEAR_Task_Common
{
    public $type = 'simple';
    public $phase = PEAR_TASK_PACKAGE;
    public $_replacements;

    /**
     * Validate the raw xml at parsing-time.
     *
     * @param  PEAR_PackageFile_v2
     * @param  array raw, parsed xml
     * @param  PEAR_Config
     */
    public static function validateXml($pkg, $xml, $config, $fileXml)
    {
        if ($xml != '') {
            return array(PEAR_TASK_ERROR_INVALID, 'no attributes allowed');
        }

        return true;
    }

    /**
     * Initialize a task instance with the parameters
     * @param array raw, parsed xml
     * @param unused
     * @param unused
     */
    public function init($xml, $attribs, $lastVersion = null)
    {
    }

    /**
     * Replace all line endings with line endings customized for the current OS
     *
     * See validateXml() source for the complete list of allowed fields
     *
     * @param  PEAR_PackageFile_v1|PEAR_PackageFile_v2
     * @param  string file contents
     * @param  string the eventual final file location (informational only)
     * @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail
     *                                 (use $this->throwError), otherwise return the new contents
     */
    public function startSession($pkg, $contents, $dest)
    {
        $this->logger->log(3, "replacing all line endings with \\n in $dest");

        return preg_replace("/\r\n|\n\r|\r|\n/", "\n", $contents);
    }
}
PKr�Z�W�f��PEAR/REST/10.phpnu�[���<?php
/**
 * PEAR_REST_10
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a12
 */

/**
 * For downloading REST xml/txt files
 */
require_once 'PEAR/REST.php';

/**
 * Implement REST 1.0
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a12
 */
class PEAR_REST_10
{
    /**
     * @var PEAR_REST
     */
    var $_rest;
    function __construct($config, $options = array())
    {
        $this->_rest = new PEAR_REST($config, $options);
    }

    /**
     * Retrieve information about a remote package to be downloaded from a REST server
     *
     * @param string $base The uri to prepend to all REST calls
     * @param array $packageinfo an array of format:
     * <pre>
     *  array(
     *   'package' => 'packagename',
     *   'channel' => 'channelname',
     *  ['state' => 'alpha' (or valid state),]
     *  -or-
     *  ['version' => '1.whatever']
     * </pre>
     * @param string $prefstate Current preferred_state config variable value
     * @param bool $installed the installed version of this package to compare against
     * @return array|false|PEAR_Error see {@link _returnDownloadURL()}
     */
    function getDownloadURL($base, $packageinfo, $prefstate, $installed, $channel = false)
    {
        $states = $this->betterStates($prefstate, true);
        if (!$states) {
            return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
        }

        $channel  = $packageinfo['channel'];
        $package  = $packageinfo['package'];
        $state    = isset($packageinfo['state'])   ? $packageinfo['state']   : null;
        $version  = isset($packageinfo['version']) ? $packageinfo['version'] : null;
        $restFile = $base . 'r/' . strtolower($package) . '/allreleases.xml';

        $info = $this->_rest->retrieveData($restFile, false, false, $channel);
        if (PEAR::isError($info)) {
            return PEAR::raiseError('No releases available for package "' .
                $channel . '/' . $package . '"');
        }

        if (!isset($info['r'])) {
            return false;
        }

        $release = $found = false;
        if (!is_array($info['r']) || !isset($info['r'][0])) {
            $info['r'] = array($info['r']);
        }

        foreach ($info['r'] as $release) {
            if (!isset($this->_rest->_options['force']) && ($installed &&
                  version_compare($release['v'], $installed, '<'))) {
                continue;
            }

            if (isset($state)) {
                // try our preferred state first
                if ($release['s'] == $state) {
                    $found = true;
                    break;
                }
                // see if there is something newer and more stable
                // bug #7221
                if (in_array($release['s'], $this->betterStates($state), true)) {
                    $found = true;
                    break;
                }
            } elseif (isset($version)) {
                if ($release['v'] == $version) {
                    $found = true;
                    break;
                }
            } else {
                if (in_array($release['s'], $states)) {
                    $found = true;
                    break;
                }
            }
        }

        return $this->_returnDownloadURL($base, $package, $release, $info, $found, false, $channel);
    }

    function getDepDownloadURL($base, $xsdversion, $dependency, $deppackage,
                               $prefstate = 'stable', $installed = false, $channel = false)
    {
        $states = $this->betterStates($prefstate, true);
        if (!$states) {
            return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
        }

        $channel  = $dependency['channel'];
        $package  = $dependency['name'];
        $state    = isset($dependency['state'])   ? $dependency['state']   : null;
        $version  = isset($dependency['version']) ? $dependency['version'] : null;
        $restFile = $base . 'r/' . strtolower($package) . '/allreleases.xml';

        $info = $this->_rest->retrieveData($restFile, false, false, $channel);
        if (PEAR::isError($info)) {
            return PEAR::raiseError('Package "' . $deppackage['channel'] . '/' . $deppackage['package']
                . '" dependency "' . $channel . '/' . $package . '" has no releases');
        }

        if (!is_array($info) || !isset($info['r'])) {
            return false;
        }

        $exclude = array();
        $min = $max = $recommended = false;
        if ($xsdversion == '1.0') {
            switch ($dependency['rel']) {
                case 'ge' :
                    $min = $dependency['version'];
                break;
                case 'gt' :
                    $min = $dependency['version'];
                    $exclude = array($dependency['version']);
                break;
                case 'eq' :
                    $recommended = $dependency['version'];
                break;
                case 'lt' :
                    $max = $dependency['version'];
                    $exclude = array($dependency['version']);
                break;
                case 'le' :
                    $max = $dependency['version'];
                break;
                case 'ne' :
                    $exclude = array($dependency['version']);
                break;
            }
        } else {
            $min = isset($dependency['min']) ? $dependency['min'] : false;
            $max = isset($dependency['max']) ? $dependency['max'] : false;
            $recommended = isset($dependency['recommended']) ?
                $dependency['recommended'] : false;
            if (isset($dependency['exclude'])) {
                if (!isset($dependency['exclude'][0])) {
                    $exclude = array($dependency['exclude']);
                }
            }
        }
        $release = $found = false;
        if (!is_array($info['r']) || !isset($info['r'][0])) {
            $info['r'] = array($info['r']);
        }
        foreach ($info['r'] as $release) {
            if (!isset($this->_rest->_options['force']) && ($installed &&
                  version_compare($release['v'], $installed, '<'))) {
                continue;
            }
            if (in_array($release['v'], $exclude)) { // skip excluded versions
                continue;
            }
            // allow newer releases to say "I'm OK with the dependent package"
            if ($xsdversion == '2.0' && isset($release['co'])) {
                if (!is_array($release['co']) || !isset($release['co'][0])) {
                    $release['co'] = array($release['co']);
                }
                foreach ($release['co'] as $entry) {
                    if (isset($entry['x']) && !is_array($entry['x'])) {
                        $entry['x'] = array($entry['x']);
                    } elseif (!isset($entry['x'])) {
                        $entry['x'] = array();
                    }
                    if ($entry['c'] == $deppackage['channel'] &&
                          strtolower($entry['p']) == strtolower($deppackage['package']) &&
                          version_compare($deppackage['version'], $entry['min'], '>=') &&
                          version_compare($deppackage['version'], $entry['max'], '<=') &&
                          !in_array($release['v'], $entry['x'])) {
                        $recommended = $release['v'];
                        break;
                    }
                }
            }
            if ($recommended) {
                if ($release['v'] != $recommended) { // if we want a specific
                    // version, then skip all others
                    continue;
                } else {
                    if (!in_array($release['s'], $states)) {
                        // the stability is too low, but we must return the
                        // recommended version if possible
                        return $this->_returnDownloadURL($base, $package, $release, $info, true, false, $channel);
                    }
                }
            }
            if ($min && version_compare($release['v'], $min, 'lt')) { // skip too old versions
                continue;
            }
            if ($max && version_compare($release['v'], $max, 'gt')) { // skip too new versions
                continue;
            }
            if ($installed && version_compare($release['v'], $installed, '<')) {
                continue;
            }
            if (in_array($release['s'], $states)) { // if in the preferred state...
                $found = true; // ... then use it
                break;
            }
        }
        return $this->_returnDownloadURL($base, $package, $release, $info, $found, false, $channel);
    }

    /**
     * Take raw data and return the array needed for processing a download URL
     *
     * @param string $base REST base uri
     * @param string $package Package name
     * @param array $release an array of format array('v' => version, 's' => state)
     *                       describing the release to download
     * @param array $info list of all releases as defined by allreleases.xml
     * @param bool|null $found determines whether the release was found or this is the next
     *                    best alternative.  If null, then versions were skipped because
     *                    of PHP dependency
     * @return array|PEAR_Error
     * @access private
     */
    function _returnDownloadURL($base, $package, $release, $info, $found, $phpversion = false, $channel = false)
    {
        if (!$found) {
            $release = $info['r'][0];
        }

        $packageLower = strtolower($package);
        $pinfo = $this->_rest->retrieveCacheFirst($base . 'p/' . $packageLower . '/' .
            'info.xml', false, false, $channel);
        if (PEAR::isError($pinfo)) {
            return PEAR::raiseError('Package "' . $package .
                '" does not have REST info xml available');
        }

        $releaseinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . $packageLower . '/' .
            $release['v'] . '.xml', false, false, $channel);
        if (PEAR::isError($releaseinfo)) {
            return PEAR::raiseError('Package "' . $package . '" Version "' . $release['v'] .
                '" does not have REST xml available');
        }

        $packagexml = $this->_rest->retrieveCacheFirst($base . 'r/' . $packageLower . '/' .
            'deps.' . $release['v'] . '.txt', false, true, $channel);
        if (PEAR::isError($packagexml)) {
            return PEAR::raiseError('Package "' . $package . '" Version "' . $release['v'] .
                '" does not have REST dependency information available');
        }

        $packagexml = unserialize($packagexml);
        if (!$packagexml) {
            $packagexml = array();
        }

        $allinfo = $this->_rest->retrieveData($base . 'r/' . $packageLower .
            '/allreleases.xml', false, false, $channel);
        if (PEAR::isError($allinfo)) {
            return $allinfo;
        }

        if (!is_array($allinfo['r']) || !isset($allinfo['r'][0])) {
            $allinfo['r'] = array($allinfo['r']);
        }

        $compatible = false;
        foreach ($allinfo['r'] as $release) {
            if ($release['v'] != $releaseinfo['v']) {
                continue;
            }

            if (!isset($release['co'])) {
                break;
            }

            $compatible = array();
            if (!is_array($release['co']) || !isset($release['co'][0])) {
                $release['co'] = array($release['co']);
            }

            foreach ($release['co'] as $entry) {
                $comp = array();
                $comp['name']    = $entry['p'];
                $comp['channel'] = $entry['c'];
                $comp['min']     = $entry['min'];
                $comp['max']     = $entry['max'];
                if (isset($entry['x']) && !is_array($entry['x'])) {
                    $comp['exclude'] = $entry['x'];
                }

                $compatible[] = $comp;
            }

            if (count($compatible) == 1) {
                $compatible = $compatible[0];
            }

            break;
        }

        $deprecated = false;
        if (isset($pinfo['dc']) && isset($pinfo['dp'])) {
            if (is_array($pinfo['dp'])) {
                $deprecated = array('channel' => (string) $pinfo['dc'],
                                    'package' => trim($pinfo['dp']['_content']));
            } else {
                $deprecated = array('channel' => (string) $pinfo['dc'],
                                    'package' => trim($pinfo['dp']));
            }
        }

        $return = array(
            'version'    => $releaseinfo['v'],
            'info'       => $packagexml,
            'package'    => $releaseinfo['p']['_content'],
            'stability'  => $releaseinfo['st'],
            'compatible' => $compatible,
            'deprecated' => $deprecated,
        );

        if ($found) {
            $return['url'] = $releaseinfo['g'];
            return $return;
        }

        $return['php'] = $phpversion;
        return $return;
    }

    function listPackages($base, $channel = false)
    {
        $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
        if (PEAR::isError($packagelist)) {
            return $packagelist;
        }

        if (!is_array($packagelist) || !isset($packagelist['p'])) {
            return array();
        }

        if (!is_array($packagelist['p'])) {
            $packagelist['p'] = array($packagelist['p']);
        }

        return $packagelist['p'];
    }

    /**
     * List all categories of a REST server
     *
     * @param string $base base URL of the server
     * @return array of categorynames
     */
    function listCategories($base, $channel = false)
    {
        $categories = array();

        // c/categories.xml does not exist;
        // check for every package its category manually
        // This is SLOOOWWWW : ///
        $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
        if (PEAR::isError($packagelist)) {
            return $packagelist;
        }

        if (!is_array($packagelist) || !isset($packagelist['p'])) {
            $ret = array();
            return $ret;
        }

        if (!is_array($packagelist['p'])) {
            $packagelist['p'] = array($packagelist['p']);
        }

        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        foreach ($packagelist['p'] as $package) {
                $inf = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel);
                if (PEAR::isError($inf)) {
                    PEAR::popErrorHandling();
                    return $inf;
                }
                $cat = $inf['ca']['_content'];
                if (!isset($categories[$cat])) {
                    $categories[$cat] = $inf['ca'];
                }
        }

        return array_values($categories);
    }

    /**
     * List a category of a REST server
     *
     * @param string $base base URL of the server
     * @param string $category name of the category
     * @param boolean $info also download full package info
     * @return array of packagenames
     */
    function listCategory($base, $category, $info = false, $channel = false)
    {
        // gives '404 Not Found' error when category doesn't exist
        $packagelist = $this->_rest->retrieveData($base.'c/'.urlencode($category).'/packages.xml', false, false, $channel);
        if (PEAR::isError($packagelist)) {
            return $packagelist;
        }

        if (!is_array($packagelist) || !isset($packagelist['p'])) {
            return array();
        }

        if (!is_array($packagelist['p']) ||
            !isset($packagelist['p'][0])) { // only 1 pkg
            $packagelist = array($packagelist['p']);
        } else {
            $packagelist = $packagelist['p'];
        }

        if ($info == true) {
            // get individual package info
            PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
            foreach ($packagelist as $i => $packageitem) {
                $url = sprintf('%s'.'r/%s/latest.txt',
                        $base,
                        strtolower($packageitem['_content']));
                $version = $this->_rest->retrieveData($url, false, false, $channel);
                if (PEAR::isError($version)) {
                    break; // skipit
                }
                $url = sprintf('%s'.'r/%s/%s.xml',
                        $base,
                        strtolower($packageitem['_content']),
                        $version);
                $info = $this->_rest->retrieveData($url, false, false, $channel);
                if (PEAR::isError($info)) {
                    break; // skipit
                }
                $packagelist[$i]['info'] = $info;
            }
            PEAR::popErrorHandling();
        }

        return $packagelist;
    }


    function listAll($base, $dostable, $basic = true, $searchpackage = false, $searchsummary = false, $channel = false)
    {
        $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
        if (PEAR::isError($packagelist)) {
            return $packagelist;
        }
        if ($this->_rest->config->get('verbose') > 0) {
            $ui = &PEAR_Frontend::singleton();
            $ui->log('Retrieving data...0%', true);
        }
        $ret = array();
        if (!is_array($packagelist) || !isset($packagelist['p'])) {
            return $ret;
        }
        if (!is_array($packagelist['p'])) {
            $packagelist['p'] = array($packagelist['p']);
        }

        // only search-packagename = quicksearch !
        if ($searchpackage && (!$searchsummary || empty($searchpackage))) {
            $newpackagelist = array();
            foreach ($packagelist['p'] as $package) {
                if (!empty($searchpackage) && stristr($package, $searchpackage) !== false) {
                    $newpackagelist[] = $package;
                }
            }
            $packagelist['p'] = $newpackagelist;
        }
        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        $next = .1;
        foreach ($packagelist['p'] as $progress => $package) {
            if ($this->_rest->config->get('verbose') > 0) {
                if ($progress / count($packagelist['p']) >= $next) {
                    if ($next == .5) {
                        $ui->log('50%', false);
                    } else {
                        $ui->log('.', false);
                    }
                    $next += .1;
                }
            }

            if ($basic) { // remote-list command
                if ($dostable) {
                    $latest = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
                        '/stable.txt', false, false, $channel);
                } else {
                    $latest = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
                        '/latest.txt', false, false, $channel);
                }
                if (PEAR::isError($latest)) {
                    $latest = false;
                }
                $info = array('stable' => $latest);
            } else { // list-all command
                $inf = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel);
                if (PEAR::isError($inf)) {
                    PEAR::popErrorHandling();
                    return $inf;
                }
                if ($searchpackage) {
                    $found = (!empty($searchpackage) && stristr($package, $searchpackage) !== false);
                    if (!$found && !(isset($searchsummary) && !empty($searchsummary)
                        && (stristr($inf['s'], $searchsummary) !== false
                            || stristr($inf['d'], $searchsummary) !== false)))
                    {
                        continue;
                    };
                }
                $releases = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
                    '/allreleases.xml', false, false, $channel);
                if (PEAR::isError($releases)) {
                    continue;
                }
                if (!isset($releases['r'][0])) {
                    $releases['r'] = array($releases['r']);
                }
                unset($latest);
                unset($unstable);
                unset($stable);
                unset($state);
                foreach ($releases['r'] as $release) {
                    if (!isset($latest)) {
                        if ($dostable && $release['s'] == 'stable') {
                            $latest = $release['v'];
                            $state = 'stable';
                        }
                        if (!$dostable) {
                            $latest = $release['v'];
                            $state = $release['s'];
                        }
                    }
                    if (!isset($stable) && $release['s'] == 'stable') {
                        $stable = $release['v'];
                        if (!isset($unstable)) {
                            $unstable = $stable;
                        }
                    }
                    if (!isset($unstable) && $release['s'] != 'stable') {
                        $latest = $unstable = $release['v'];
                        $state = $release['s'];
                    }
                    if (isset($latest) && !isset($state)) {
                        $state = $release['s'];
                    }
                    if (isset($latest) && isset($stable) && isset($unstable)) {
                        break;
                    }
                }
                $deps = array();
                if (!isset($unstable)) {
                    $unstable = false;
                    $state = 'stable';
                    if (isset($stable)) {
                        $latest = $unstable = $stable;
                    }
                } else {
                    $latest = $unstable;
                }
                if (!isset($latest)) {
                    $latest = false;
                }
                if ($latest) {
                    $d = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/deps.' .
                        $latest . '.txt', false, false, $channel);
                    if (!PEAR::isError($d)) {
                        $d = unserialize($d);
                        if ($d) {
                            if (isset($d['required'])) {
                                if (!class_exists('PEAR_PackageFile_v2')) {
                                    require_once 'PEAR/PackageFile/v2.php';
                                }
                                if (!isset($pf)) {
                                    $pf = new PEAR_PackageFile_v2;
                                }
                                $pf->setDeps($d);
                                $tdeps = $pf->getDeps();
                            } else {
                                $tdeps = $d;
                            }
                            foreach ($tdeps as $dep) {
                                if ($dep['type'] !== 'pkg') {
                                    continue;
                                }
                                $deps[] = $dep;
                            }
                        }
                    }
                }
                if (!isset($stable)) {
                    $stable = '-n/a-';
                }
                if (!$searchpackage) {
                    $info = array('stable' => $latest, 'summary' => $inf['s'], 'description' =>
                        $inf['d'], 'deps' => $deps, 'category' => $inf['ca']['_content'],
                        'unstable' => $unstable, 'state' => $state);
                } else {
                    $info = array('stable' => $stable, 'summary' => $inf['s'], 'description' =>
                        $inf['d'], 'deps' => $deps, 'category' => $inf['ca']['_content'],
                        'unstable' => $unstable, 'state' => $state);
                }
            }
            $ret[$package] = $info;
        }
        PEAR::popErrorHandling();
        return $ret;
    }

    function listLatestUpgrades($base, $pref_state, $installed, $channel, &$reg)
    {
        $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
        if (PEAR::isError($packagelist)) {
            return $packagelist;
        }

        $ret = array();
        if (!is_array($packagelist) || !isset($packagelist['p'])) {
            return $ret;
        }

        if (!is_array($packagelist['p'])) {
            $packagelist['p'] = array($packagelist['p']);
        }

        foreach ($packagelist['p'] as $package) {
            if (!isset($installed[strtolower($package)])) {
                continue;
            }

            $inst_version = $reg->packageInfo($package, 'version', $channel);
            $inst_state   = $reg->packageInfo($package, 'release_state', $channel);
            PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
            $info = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
                '/allreleases.xml', false, false, $channel);
            PEAR::popErrorHandling();
            if (PEAR::isError($info)) {
                continue; // no remote releases
            }

            if (!isset($info['r'])) {
                continue;
            }

            $release = $found = false;
            if (!is_array($info['r']) || !isset($info['r'][0])) {
                $info['r'] = array($info['r']);
            }

            // $info['r'] is sorted by version number
            usort($info['r'], array($this, '_sortReleasesByVersionNumber'));
            foreach ($info['r'] as $release) {
                if ($inst_version && version_compare($release['v'], $inst_version, '<=')) {
                    // not newer than the one installed
                    break;
                }

                // new version > installed version
                if (!$pref_state) {
                    // every state is a good state
                    $found = true;
                    break;
                } else {
                    $new_state = $release['s'];
                    // if new state >= installed state: go
                    if (in_array($new_state, $this->betterStates($inst_state, true))) {
                        $found = true;
                        break;
                    } else {
                        // only allow to lower the state of package,
                        // if new state >= preferred state: go
                        if (in_array($new_state, $this->betterStates($pref_state, true))) {
                            $found = true;
                            break;
                        }
                    }
                }
            }

            if (!$found) {
                continue;
            }

            $relinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/' .
                $release['v'] . '.xml', false, false, $channel);
            if (PEAR::isError($relinfo)) {
                return $relinfo;
            }

            $ret[$package] = array(
                'version'  => $release['v'],
                'state'    => $release['s'],
                'filesize' => $relinfo['f'],
            );
        }

        return $ret;
    }

    function packageInfo($base, $package, $channel = false)
    {
        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        $pinfo = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel);
        if (PEAR::isError($pinfo)) {
            PEAR::popErrorHandling();
            return PEAR::raiseError('Unknown package: "' . $package . '" in channel "' . $channel . '"' . "\n". 'Debug: ' .
                $pinfo->getMessage());
        }

        $releases = array();
        $allreleases = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
            '/allreleases.xml', false, false, $channel);
        if (!PEAR::isError($allreleases)) {
            if (!class_exists('PEAR_PackageFile_v2')) {
                require_once 'PEAR/PackageFile/v2.php';
            }

            if (!is_array($allreleases['r']) || !isset($allreleases['r'][0])) {
                $allreleases['r'] = array($allreleases['r']);
            }

            $pf = new PEAR_PackageFile_v2;
            foreach ($allreleases['r'] as $release) {
                $ds = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/deps.' .
                    $release['v'] . '.txt', false, false, $channel);
                if (PEAR::isError($ds)) {
                    continue;
                }

                if (!isset($latest)) {
                    $latest = $release['v'];
                }

                $pf->setDeps(unserialize($ds));
                $ds = $pf->getDeps();
                $info = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package)
                    . '/' . $release['v'] . '.xml', false, false, $channel);

                if (PEAR::isError($info)) {
                    continue;
                }

                $releases[$release['v']] = array(
                    'doneby' => $info['m'],
                    'license' => $info['l'],
                    'summary' => $info['s'],
                    'description' => $info['d'],
                    'releasedate' => $info['da'],
                    'releasenotes' => $info['n'],
                    'state' => $release['s'],
                    'deps' => $ds ? $ds : array(),
                );
            }
        } else {
            $latest = '';
        }

        PEAR::popErrorHandling();
        if (isset($pinfo['dc']) && isset($pinfo['dp'])) {
            if (is_array($pinfo['dp'])) {
                $deprecated = array('channel' => (string) $pinfo['dc'],
                                    'package' => trim($pinfo['dp']['_content']));
            } else {
                $deprecated = array('channel' => (string) $pinfo['dc'],
                                    'package' => trim($pinfo['dp']));
            }
        } else {
            $deprecated = false;
        }

        if (!isset($latest)) {
            $latest = '';
        }

        return array(
            'name' => $pinfo['n'],
            'channel' => $pinfo['c'],
            'category' => $pinfo['ca']['_content'],
            'stable' => $latest,
            'license' => $pinfo['l'],
            'summary' => $pinfo['s'],
            'description' => $pinfo['d'],
            'releases' => $releases,
            'deprecated' => $deprecated,
            );
    }

    /**
     * Return an array containing all of the states that are more stable than
     * or equal to the passed in state
     *
     * @param string Release state
     * @param boolean Determines whether to include $state in the list
     * @return false|array False if $state is not a valid release state
     */
    function betterStates($state, $include = false)
    {
        static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable');
        $i = array_search($state, $states);
        if ($i === false) {
            return false;
        }

        if ($include) {
            $i--;
        }

        return array_slice($states, $i + 1);
    }

    /**
     * Sort releases by version number
     *
     * @access private
     */
    function _sortReleasesByVersionNumber($a, $b)
    {
        if (version_compare($a['v'], $b['v'], '=')) {
            return 0;
        }

        if (version_compare($a['v'], $b['v'], '>')) {
            return -1;
        }

        if (version_compare($a['v'], $b['v'], '<')) {
            return 1;
        }
    }
}
PKr�Z��Y�;;PEAR/REST/13.phpnu�[���<?php
/**
 * PEAR_REST_13
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a12
 */

/**
 * For downloading REST xml/txt files
 */
require_once 'PEAR/REST.php';
require_once 'PEAR/REST/10.php';

/**
 * Implement REST 1.3
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a12
 */
class PEAR_REST_13 extends PEAR_REST_10
{
    /**
     * Retrieve information about a remote package to be downloaded from a REST server
     *
     * This is smart enough to resolve the minimum PHP version dependency prior to download
     * @param string $base The uri to prepend to all REST calls
     * @param array $packageinfo an array of format:
     * <pre>
     *  array(
     *   'package' => 'packagename',
     *   'channel' => 'channelname',
     *  ['state' => 'alpha' (or valid state),]
     *  -or-
     *  ['version' => '1.whatever']
     * </pre>
     * @param string $prefstate Current preferred_state config variable value
     * @param bool $installed the installed version of this package to compare against
     * @return array|false|PEAR_Error see {@link _returnDownloadURL()}
     */
    function getDownloadURL($base, $packageinfo, $prefstate, $installed, $channel = false)
    {
        $states = $this->betterStates($prefstate, true);
        if (!$states) {
            return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
        }

        $channel  = $packageinfo['channel'];
        $package  = $packageinfo['package'];
        $state    = isset($packageinfo['state'])   ? $packageinfo['state']   : null;
        $version  = isset($packageinfo['version']) ? $packageinfo['version'] : null;
        $restFile = $base . 'r/' . strtolower($package) . '/allreleases2.xml';

        $info = $this->_rest->retrieveData($restFile, false, false, $channel);
        if (PEAR::isError($info)) {
            return PEAR::raiseError('No releases available for package "' .
                $channel . '/' . $package . '"');
        }

        if (!isset($info['r'])) {
            return false;
        }

        $release = $found = false;
        if (!is_array($info['r']) || !isset($info['r'][0])) {
            $info['r'] = array($info['r']);
        }

        $skippedphp = false;
        foreach ($info['r'] as $release) {
            if (!isset($this->_rest->_options['force']) && ($installed &&
                  version_compare($release['v'], $installed, '<'))) {
                continue;
            }

            if (isset($state)) {
                // try our preferred state first
                if ($release['s'] == $state) {
                    if (!isset($version) && version_compare($release['m'], phpversion(), '>')) {
                        // skip releases that require a PHP version newer than our PHP version
                        $skippedphp = $release;
                        continue;
                    }
                    $found = true;
                    break;
                }

                // see if there is something newer and more stable
                // bug #7221
                if (in_array($release['s'], $this->betterStates($state), true)) {
                    if (!isset($version) && version_compare($release['m'], phpversion(), '>')) {
                        // skip releases that require a PHP version newer than our PHP version
                        $skippedphp = $release;
                        continue;
                    }
                    $found = true;
                    break;
                }
            } elseif (isset($version)) {
                if ($release['v'] == $version) {
                    if (!isset($this->_rest->_options['force']) &&
                          !isset($version) &&
                          version_compare($release['m'], phpversion(), '>')) {
                        // skip releases that require a PHP version newer than our PHP version
                        $skippedphp = $release;
                        continue;
                    }
                    $found = true;
                    break;
                }
            } else {
                if (in_array($release['s'], $states)) {
                    if (version_compare($release['m'], phpversion(), '>')) {
                        // skip releases that require a PHP version newer than our PHP version
                        $skippedphp = $release;
                        continue;
                    }
                    $found = true;
                    break;
                }
            }
        }

        if (!$found && $skippedphp) {
            $found = null;
        }

        return $this->_returnDownloadURL($base, $package, $release, $info, $found, $skippedphp, $channel);
    }

    function getDepDownloadURL($base, $xsdversion, $dependency, $deppackage,
                               $prefstate = 'stable', $installed = false, $channel = false)
    {
        $states = $this->betterStates($prefstate, true);
        if (!$states) {
            return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
        }

        $channel  = $dependency['channel'];
        $package  = $dependency['name'];
        $state    = isset($dependency['state'])   ? $dependency['state']   : null;
        $version  = isset($dependency['version']) ? $dependency['version'] : null;
        $restFile = $base . 'r/' . strtolower($package) .'/allreleases2.xml';

        $info = $this->_rest->retrieveData($restFile, false, false, $channel);
        if (PEAR::isError($info)) {
            return PEAR::raiseError('Package "' . $deppackage['channel'] . '/' . $deppackage['package']
                . '" dependency "' . $channel . '/' . $package . '" has no releases');
        }

        if (!is_array($info) || !isset($info['r'])) {
            return false;
        }

        $exclude = array();
        $min = $max = $recommended = false;
        if ($xsdversion == '1.0') {
            $pinfo['package'] = $dependency['name'];
            $pinfo['channel'] = 'pear.php.net'; // this is always true - don't change this
            switch ($dependency['rel']) {
                case 'ge' :
                    $min = $dependency['version'];
                break;
                case 'gt' :
                    $min = $dependency['version'];
                    $exclude = array($dependency['version']);
                break;
                case 'eq' :
                    $recommended = $dependency['version'];
                break;
                case 'lt' :
                    $max = $dependency['version'];
                    $exclude = array($dependency['version']);
                break;
                case 'le' :
                    $max = $dependency['version'];
                break;
                case 'ne' :
                    $exclude = array($dependency['version']);
                break;
            }
        } else {
            $pinfo['package'] = $dependency['name'];
            $min = isset($dependency['min']) ? $dependency['min'] : false;
            $max = isset($dependency['max']) ? $dependency['max'] : false;
            $recommended = isset($dependency['recommended']) ?
                $dependency['recommended'] : false;
            if (isset($dependency['exclude'])) {
                if (!isset($dependency['exclude'][0])) {
                    $exclude = array($dependency['exclude']);
                }
            }
        }

        $skippedphp = $found = $release = false;
        if (!is_array($info['r']) || !isset($info['r'][0])) {
            $info['r'] = array($info['r']);
        }

        foreach ($info['r'] as $release) {
            if (!isset($this->_rest->_options['force']) && ($installed &&
                  version_compare($release['v'], $installed, '<'))) {
                continue;
            }

            if (in_array($release['v'], $exclude)) { // skip excluded versions
                continue;
            }

            // allow newer releases to say "I'm OK with the dependent package"
            if ($xsdversion == '2.0' && isset($release['co'])) {
                if (!is_array($release['co']) || !isset($release['co'][0])) {
                    $release['co'] = array($release['co']);
                }

                foreach ($release['co'] as $entry) {
                    if (isset($entry['x']) && !is_array($entry['x'])) {
                        $entry['x'] = array($entry['x']);
                    } elseif (!isset($entry['x'])) {
                        $entry['x'] = array();
                    }

                    if ($entry['c'] == $deppackage['channel'] &&
                          strtolower($entry['p']) == strtolower($deppackage['package']) &&
                          version_compare($deppackage['version'], $entry['min'], '>=') &&
                          version_compare($deppackage['version'], $entry['max'], '<=') &&
                          !in_array($release['v'], $entry['x'])) {
                        if (version_compare($release['m'], phpversion(), '>')) {
                            // skip dependency releases that require a PHP version
                            // newer than our PHP version
                            $skippedphp = $release;
                            continue;
                        }

                        $recommended = $release['v'];
                        break;
                    }
                }
            }

            if ($recommended) {
                if ($release['v'] != $recommended) { // if we want a specific
                    // version, then skip all others
                    continue;
                }

                if (!in_array($release['s'], $states)) {
                    // the stability is too low, but we must return the
                    // recommended version if possible
                    return $this->_returnDownloadURL($base, $package, $release, $info, true, false, $channel);
                }
            }

            if ($min && version_compare($release['v'], $min, 'lt')) { // skip too old versions
                continue;
            }

            if ($max && version_compare($release['v'], $max, 'gt')) { // skip too new versions
                continue;
            }

            if ($installed && version_compare($release['v'], $installed, '<')) {
                continue;
            }

            if (in_array($release['s'], $states)) { // if in the preferred state...
                if (version_compare($release['m'], phpversion(), '>')) {
                    // skip dependency releases that require a PHP version
                    // newer than our PHP version
                    $skippedphp = $release;
                    continue;
                }

                $found = true; // ... then use it
                break;
            }
        }

        if (!$found && $skippedphp) {
            $found = null;
        }

        return $this->_returnDownloadURL($base, $package, $release, $info, $found, $skippedphp, $channel);
    }

    /**
     * List package upgrades but take the PHP version into account.
     */
    function listLatestUpgrades($base, $pref_state, $installed, $channel, &$reg)
    {
        $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
        if (PEAR::isError($packagelist)) {
            return $packagelist;
        }

        $ret = array();
        if (!is_array($packagelist) || !isset($packagelist['p'])) {
            return $ret;
        }

        if (!is_array($packagelist['p'])) {
            $packagelist['p'] = array($packagelist['p']);
        }

        foreach ($packagelist['p'] as $package) {
            if (!isset($installed[strtolower($package)])) {
                continue;
            }

            $inst_version = $reg->packageInfo($package, 'version', $channel);
            $inst_state   = $reg->packageInfo($package, 'release_state', $channel);
            PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
            $info = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
                '/allreleases2.xml', false, false, $channel);
            PEAR::popErrorHandling();
            if (PEAR::isError($info)) {
                continue; // no remote releases
            }

            if (!isset($info['r'])) {
                continue;
            }

            $release = $found = false;
            if (!is_array($info['r']) || !isset($info['r'][0])) {
                $info['r'] = array($info['r']);
            }

            // $info['r'] is sorted by version number
            usort($info['r'], array($this, '_sortReleasesByVersionNumber'));
            foreach ($info['r'] as $release) {
                if ($inst_version && version_compare($release['v'], $inst_version, '<=')) {
                    // not newer than the one installed
                    break;
                }
                if (version_compare($release['m'], phpversion(), '>')) {
                    // skip dependency releases that require a PHP version
                    // newer than our PHP version
                    continue;
                }

                // new version > installed version
                if (!$pref_state) {
                    // every state is a good state
                    $found = true;
                    break;
                } else {
                    $new_state = $release['s'];
                    // if new state >= installed state: go
                    if (in_array($new_state, $this->betterStates($inst_state, true))) {
                        $found = true;
                        break;
                    } else {
                        // only allow to lower the state of package,
                        // if new state >= preferred state: go
                        if (in_array($new_state, $this->betterStates($pref_state, true))) {
                            $found = true;
                            break;
                        }
                    }
                }
            }

            if (!$found) {
                continue;
            }

            $relinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/' .
                $release['v'] . '.xml', false, false, $channel);
            if (PEAR::isError($relinfo)) {
                return $relinfo;
            }

            $ret[$package] = array(
                'version'  => $release['v'],
                'state'    => $release['s'],
                'filesize' => $relinfo['f'],
            );
        }

        return $ret;
    }
}PKr�Z,#y��+�+PEAR/REST/11.phpnu�[���<?php
/**
 * PEAR_REST_11 - implement faster list-all/remote-list command
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.3
 */

/**
 * For downloading REST xml/txt files
 */
require_once 'PEAR/REST.php';

/**
 * Implement REST 1.1
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.3
 */
class PEAR_REST_11
{
    /**
     * @var PEAR_REST
     */
    var $_rest;

    function __construct($config, $options = array())
    {
        $this->_rest = new PEAR_REST($config, $options);
    }

    function listAll($base, $dostable, $basic = true, $searchpackage = false, $searchsummary = false, $channel = false)
    {
        $categorylist = $this->_rest->retrieveData($base . 'c/categories.xml', false, false, $channel);
        if (PEAR::isError($categorylist)) {
            return $categorylist;
        }

        $ret = array();
        if (!is_array($categorylist['c']) || !isset($categorylist['c'][0])) {
            $categorylist['c'] = array($categorylist['c']);
        }

        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);

        foreach ($categorylist['c'] as $progress => $category) {
            $category = $category['_content'];
            $packagesinfo = $this->_rest->retrieveData($base .
                'c/' . urlencode($category) . '/packagesinfo.xml', false, false, $channel);

            if (PEAR::isError($packagesinfo)) {
                continue;
            }

            if (!is_array($packagesinfo) || !isset($packagesinfo['pi'])) {
                continue;
            }

            if (!is_array($packagesinfo['pi']) || !isset($packagesinfo['pi'][0])) {
                $packagesinfo['pi'] = array($packagesinfo['pi']);
            }

            foreach ($packagesinfo['pi'] as $packageinfo) {
                if (empty($packageinfo)) {
                    continue;
                }

                $info     = $packageinfo['p'];
                $package  = $info['n'];
                $releases = isset($packageinfo['a']) ? $packageinfo['a'] : false;
                unset($latest);
                unset($unstable);
                unset($stable);
                unset($state);

                if ($releases) {
                    if (!isset($releases['r'][0])) {
                        $releases['r'] = array($releases['r']);
                    }

                    foreach ($releases['r'] as $release) {
                        if (!isset($latest)) {
                            if ($dostable && $release['s'] == 'stable') {
                                $latest = $release['v'];
                                $state = 'stable';
                            }
                            if (!$dostable) {
                                $latest = $release['v'];
                                $state = $release['s'];
                            }
                        }

                        if (!isset($stable) && $release['s'] == 'stable') {
                            $stable = $release['v'];
                            if (!isset($unstable)) {
                                $unstable = $stable;
                            }
                        }

                        if (!isset($unstable) && $release['s'] != 'stable') {
                            $unstable = $release['v'];
                            $state = $release['s'];
                        }

                        if (isset($latest) && !isset($state)) {
                            $state = $release['s'];
                        }

                        if (isset($latest) && isset($stable) && isset($unstable)) {
                            break;
                        }
                    }
                }

                if ($basic) { // remote-list command
                    if (!isset($latest)) {
                        $latest = false;
                    }

                    if ($dostable) {
                        // $state is not set if there are no releases
                        if (isset($state) && $state == 'stable') {
                            $ret[$package] = array('stable' => $latest);
                        } else {
                            $ret[$package] = array('stable' => '-n/a-');
                        }
                    } else {
                        $ret[$package] = array('stable' => $latest);
                    }

                    continue;
                }

                // list-all command
                if (!isset($unstable)) {
                    $unstable = false;
                    $state = 'stable';
                    if (isset($stable)) {
                        $latest = $unstable = $stable;
                    }
                } else {
                    $latest = $unstable;
                }

                if (!isset($latest)) {
                    $latest = false;
                }

                $deps = array();
                if ($latest && isset($packageinfo['deps'])) {
                    if (!is_array($packageinfo['deps']) ||
                          !isset($packageinfo['deps'][0])
                    ) {
                        $packageinfo['deps'] = array($packageinfo['deps']);
                    }

                    $d = false;
                    foreach ($packageinfo['deps'] as $dep) {
                        if ($dep['v'] == $latest) {
                            $d = unserialize($dep['d']);
                        }
                    }

                    if ($d) {
                        if (isset($d['required'])) {
                            if (!class_exists('PEAR_PackageFile_v2')) {
                                require_once 'PEAR/PackageFile/v2.php';
                            }

                            if (!isset($pf)) {
                                $pf = new PEAR_PackageFile_v2;
                            }

                            $pf->setDeps($d);
                            $tdeps = $pf->getDeps();
                        } else {
                            $tdeps = $d;
                        }

                        foreach ($tdeps as $dep) {
                            if ($dep['type'] !== 'pkg') {
                                continue;
                            }

                            $deps[] = $dep;
                        }
                    }
                }

                $info = array(
                    'stable'      => $latest,
                    'summary'     => $info['s'],
                    'description' => $info['d'],
                    'deps'        => $deps,
                    'category'    => $info['ca']['_content'],
                    'unstable'    => $unstable,
                    'state'       => $state
                );
                $ret[$package] = $info;
            }
        }

        PEAR::popErrorHandling();
        return $ret;
    }

    /**
     * List all categories of a REST server
     *
     * @param string $base base URL of the server
     * @return array of categorynames
     */
    function listCategories($base, $channel = false)
    {
        $categorylist = $this->_rest->retrieveData($base . 'c/categories.xml', false, false, $channel);
        if (PEAR::isError($categorylist)) {
            return $categorylist;
        }

        if (!is_array($categorylist) || !isset($categorylist['c'])) {
            return array();
        }

        if (isset($categorylist['c']['_content'])) {
            // only 1 category
            $categorylist['c'] = array($categorylist['c']);
        }

        return $categorylist['c'];
    }

    /**
     * List packages in a category of a REST server
     *
     * @param string $base base URL of the server
     * @param string $category name of the category
     * @param boolean $info also download full package info
     * @return array of packagenames
     */
    function listCategory($base, $category, $info = false, $channel = false)
    {
        if ($info == false) {
            $url = '%s'.'c/%s/packages.xml';
        } else {
            $url = '%s'.'c/%s/packagesinfo.xml';
        }
        $url = sprintf($url,
                    $base,
                    urlencode($category));

        // gives '404 Not Found' error when category doesn't exist
        $packagelist = $this->_rest->retrieveData($url, false, false, $channel);
        if (PEAR::isError($packagelist)) {
            return $packagelist;
        }
        if (!is_array($packagelist)) {
            return array();
        }

        if ($info == false) {
            if (!isset($packagelist['p'])) {
                return array();
            }
            if (!is_array($packagelist['p']) ||
                !isset($packagelist['p'][0])) { // only 1 pkg
                $packagelist = array($packagelist['p']);
            } else {
                $packagelist = $packagelist['p'];
            }
            return $packagelist;
        }

        // info == true
        if (!isset($packagelist['pi'])) {
            return array();
        }

        if (!is_array($packagelist['pi']) ||
            !isset($packagelist['pi'][0])) { // only 1 pkg
            $packagelist_pre = array($packagelist['pi']);
        } else {
            $packagelist_pre = $packagelist['pi'];
        }

        $packagelist = array();
        foreach ($packagelist_pre as $i => $item) {
            // compatibility with r/<latest.txt>.xml
            if (isset($item['a']['r'][0])) {
                // multiple releases
                $item['p']['v'] = $item['a']['r'][0]['v'];
                $item['p']['st'] = $item['a']['r'][0]['s'];
            } elseif (isset($item['a'])) {
                // first and only release
                $item['p']['v'] = $item['a']['r']['v'];
                $item['p']['st'] = $item['a']['r']['s'];
            }

            $packagelist[$i] = array('attribs' => $item['p']['r'],
                                     '_content' => $item['p']['n'],
                                     'info' => $item['p']);
        }

        return $packagelist;
    }

    /**
     * Return an array containing all of the states that are more stable than
     * or equal to the passed in state
     *
     * @param string Release state
     * @param boolean Determines whether to include $state in the list
     * @return false|array False if $state is not a valid release state
     */
    function betterStates($state, $include = false)
    {
        static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable');
        $i = array_search($state, $states);
        if ($i === false) {
            return false;
        }
        if ($include) {
            $i--;
        }
        return array_slice($states, $i + 1);
    }
}
?>
PKr�Z��U  PEAR/Packager.phpnu�[���<?php
/**
 * PEAR_Packager for generating releases
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Tomas V. V. Cox <cox@idecnet.com>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 0.1
 */

/**
 * base class
 */
require_once 'PEAR/Common.php';
require_once 'PEAR/PackageFile.php';
require_once 'System.php';

/**
 * Administration class used to make a PEAR release tarball.
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 0.1
 */
class PEAR_Packager extends PEAR_Common
{
    /**
     * @var PEAR_Registry
     */
    var $_registry;

    function package($pkgfile = null, $compress = true, $pkg2 = null)
    {
        // {{{ validate supplied package.xml file
        if (empty($pkgfile)) {
            $pkgfile = 'package.xml';
        }

        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        $pkg  = new PEAR_PackageFile($this->config, $this->debug);
        $pf   = &$pkg->fromPackageFile($pkgfile, PEAR_VALIDATE_NORMAL);
        $main = &$pf;
        PEAR::staticPopErrorHandling();
        if (PEAR::isError($pf)) {
            if (is_array($pf->getUserInfo())) {
                foreach ($pf->getUserInfo() as $error) {
                    $this->log(0, 'Error: ' . $error['message']);
                }
            }

            $this->log(0, $pf->getMessage());
            return $this->raiseError("Cannot package, errors in package file");
        }

        foreach ($pf->getValidationWarnings() as $warning) {
            $this->log(1, 'Warning: ' . $warning['message']);
        }

        // }}}
        if ($pkg2) {
            $this->log(0, 'Attempting to process the second package file');
            PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
            $pf2 = &$pkg->fromPackageFile($pkg2, PEAR_VALIDATE_NORMAL);
            PEAR::staticPopErrorHandling();
            if (PEAR::isError($pf2)) {
                if (is_array($pf2->getUserInfo())) {
                    foreach ($pf2->getUserInfo() as $error) {
                        $this->log(0, 'Error: ' . $error['message']);
                    }
                }
                $this->log(0, $pf2->getMessage());
                return $this->raiseError("Cannot package, errors in second package file");
            }

            foreach ($pf2->getValidationWarnings() as $warning) {
                $this->log(1, 'Warning: ' . $warning['message']);
            }

            if ($pf2->getPackagexmlVersion() == '2.0' ||
                  $pf2->getPackagexmlVersion() == '2.1'
            ) {
                $main  = &$pf2;
                $other = &$pf;
            } else {
                $main  = &$pf;
                $other = &$pf2;
            }

            if ($main->getPackagexmlVersion() != '2.0' &&
                  $main->getPackagexmlVersion() != '2.1') {
                return PEAR::raiseError('Error: cannot package two package.xml version 1.0, can ' .
                    'only package together a package.xml 1.0 and package.xml 2.0');
            }

            if ($other->getPackagexmlVersion() != '1.0') {
                return PEAR::raiseError('Error: cannot package two package.xml version 2.0, can ' .
                    'only package together a package.xml 1.0 and package.xml 2.0');
            }
        }

        $main->setLogger($this);
        if (!$main->validate(PEAR_VALIDATE_PACKAGING)) {
            foreach ($main->getValidationWarnings() as $warning) {
                $this->log(0, 'Error: ' . $warning['message']);
            }
            return $this->raiseError("Cannot package, errors in package");
        }

        foreach ($main->getValidationWarnings() as $warning) {
            $this->log(1, 'Warning: ' . $warning['message']);
        }

        if ($pkg2) {
            $other->setLogger($this);
            $a = false;
            if (!$other->validate(PEAR_VALIDATE_NORMAL) || $a = !$main->isEquivalent($other)) {
                foreach ($other->getValidationWarnings() as $warning) {
                    $this->log(0, 'Error: ' . $warning['message']);
                }

                foreach ($main->getValidationWarnings() as $warning) {
                    $this->log(0, 'Error: ' . $warning['message']);
                }

                if ($a) {
                    return $this->raiseError('The two package.xml files are not equivalent!');
                }

                return $this->raiseError("Cannot package, errors in package");
            }

            foreach ($other->getValidationWarnings() as $warning) {
                $this->log(1, 'Warning: ' . $warning['message']);
            }

            $gen = &$main->getDefaultGenerator();
            $tgzfile = $gen->toTgz2($this, $other, $compress);
            if (PEAR::isError($tgzfile)) {
                return $tgzfile;
            }

            $dest_package = basename($tgzfile);
            $pkgdir       = dirname($pkgfile);

            // TAR the Package -------------------------------------------
            $this->log(1, "Package $dest_package done");
            if (file_exists("$pkgdir/CVS/Root")) {
                $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $pf->getVersion());
                $cvstag = "RELEASE_$cvsversion";
                $this->log(1, 'Tag the released code with "pear cvstag ' .
                    $main->getPackageFile() . '"');
                $this->log(1, "(or set the CVS tag $cvstag by hand)");
            } elseif (file_exists("$pkgdir/.svn")) {
                $svnversion = preg_replace('/[^a-z0-9]/i', '.', $pf->getVersion());
                $svntag = $pf->getName() . "-$svnversion";
                $this->log(1, 'Tag the released code with "pear svntag ' .
                    $main->getPackageFile() . '"');
                $this->log(1, "(or set the SVN tag $svntag by hand)");
            }
        } else { // this branch is executed for single packagefile packaging
            $gen = &$pf->getDefaultGenerator();
            $tgzfile = $gen->toTgz($this, $compress);
            if (PEAR::isError($tgzfile)) {
                $this->log(0, $tgzfile->getMessage());
                return $this->raiseError("Cannot package, errors in package");
            }

            $dest_package = basename($tgzfile);
            $pkgdir       = dirname($pkgfile);

            // TAR the Package -------------------------------------------
            $this->log(1, "Package $dest_package done");
            if (file_exists("$pkgdir/CVS/Root")) {
                $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $pf->getVersion());
                $cvstag = "RELEASE_$cvsversion";
                $this->log(1, "Tag the released code with `pear cvstag $pkgfile'");
                $this->log(1, "(or set the CVS tag $cvstag by hand)");
            } elseif (file_exists("$pkgdir/.svn")) {
                $svnversion = preg_replace('/[^a-z0-9]/i', '.', $pf->getVersion());
                $svntag = $pf->getName() . "-$svnversion";
                $this->log(1, "Tag the released code with `pear svntag $pkgfile'");
                $this->log(1, "(or set the SVN tag $svntag by hand)");
            }
        }

        return $dest_package;
    }
}PKr�ZZ�bgbgPEAR/Common.phpnu�[���<?php
/**
 * PEAR_Common, the base class for the PEAR Installer
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Tomas V. V. Cox <cox@idecnet.com>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 0.1.0
 * @deprecated File deprecated since Release 1.4.0a1
 */

/**
 * Include error handling
 */
require_once 'PEAR.php';

/**
 * PEAR_Common error when an invalid PHP file is passed to PEAR_Common::analyzeSourceCode()
 */
define('PEAR_COMMON_ERROR_INVALIDPHP', 1);
define('_PEAR_COMMON_PACKAGE_NAME_PREG', '[A-Za-z][a-zA-Z0-9_]+');
define('PEAR_COMMON_PACKAGE_NAME_PREG', '/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '\\z/');

// this should allow: 1, 1.0, 1.0RC1, 1.0dev, 1.0dev123234234234, 1.0a1, 1.0b1, 1.0pl1
define('_PEAR_COMMON_PACKAGE_VERSION_PREG', '\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?');
define('PEAR_COMMON_PACKAGE_VERSION_PREG', '/^' . _PEAR_COMMON_PACKAGE_VERSION_PREG . '\\z/i');

// XXX far from perfect :-)
define('_PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '(' . _PEAR_COMMON_PACKAGE_NAME_PREG .
    ')(-([.0-9a-zA-Z]+))?');
define('PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '/^' . _PEAR_COMMON_PACKAGE_DOWNLOAD_PREG .
    '\\z/');

define('_PEAR_CHANNELS_NAME_PREG', '[A-Za-z][a-zA-Z0-9\.]+');
define('PEAR_CHANNELS_NAME_PREG', '/^' . _PEAR_CHANNELS_NAME_PREG . '\\z/');

// this should allow any dns or IP address, plus a path - NO UNDERSCORES ALLOWED
define('_PEAR_CHANNELS_SERVER_PREG', '[a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]+)*(\/[a-zA-Z0-9\-]+)*');
define('PEAR_CHANNELS_SERVER_PREG', '/^' . _PEAR_CHANNELS_SERVER_PREG . '\\z/i');

define('_PEAR_CHANNELS_PACKAGE_PREG',  '(' ._PEAR_CHANNELS_SERVER_PREG . ')\/('
         . _PEAR_COMMON_PACKAGE_NAME_PREG . ')');
define('PEAR_CHANNELS_PACKAGE_PREG', '/^' . _PEAR_CHANNELS_PACKAGE_PREG . '\\z/i');

define('_PEAR_COMMON_CHANNEL_DOWNLOAD_PREG', '(' . _PEAR_CHANNELS_NAME_PREG . ')::('
    . _PEAR_COMMON_PACKAGE_NAME_PREG . ')(-([.0-9a-zA-Z]+))?');
define('PEAR_COMMON_CHANNEL_DOWNLOAD_PREG', '/^' . _PEAR_COMMON_CHANNEL_DOWNLOAD_PREG . '\\z/');

/**
 * List of temporary files and directories registered by
 * PEAR_Common::addTempFile().
 * @var array
 */
$GLOBALS['_PEAR_Common_tempfiles'] = array();

/**
 * Valid maintainer roles
 * @var array
 */
$GLOBALS['_PEAR_Common_maintainer_roles'] = array('lead','developer','contributor','helper');

/**
 * Valid release states
 * @var array
 */
$GLOBALS['_PEAR_Common_release_states'] = array('alpha','beta','stable','snapshot','devel');

/**
 * Valid dependency types
 * @var array
 */
$GLOBALS['_PEAR_Common_dependency_types'] = array('pkg','ext','php','prog','ldlib','rtlib','os','websrv','sapi');

/**
 * Valid dependency relations
 * @var array
 */
$GLOBALS['_PEAR_Common_dependency_relations'] = array('has','eq','lt','le','gt','ge','not', 'ne');

/**
 * Valid file roles
 * @var array
 */
$GLOBALS['_PEAR_Common_file_roles'] = array('php','ext','test','doc','data','src','script');

/**
 * Valid replacement types
 * @var array
 */
$GLOBALS['_PEAR_Common_replacement_types'] = array('php-const', 'pear-config', 'package-info');

/**
 * Valid "provide" types
 * @var array
 */
$GLOBALS['_PEAR_Common_provide_types'] = array('ext', 'prog', 'class', 'function', 'feature', 'api');

/**
 * Valid "provide" types
 * @var array
 */
$GLOBALS['_PEAR_Common_script_phases'] = array('pre-install', 'post-install', 'pre-uninstall', 'post-uninstall', 'pre-build', 'post-build', 'pre-configure', 'post-configure', 'pre-setup', 'post-setup');

/**
 * Class providing common functionality for PEAR administration classes.
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Tomas V. V. Cox <cox@idecnet.com>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 * @deprecated This class will disappear, and its components will be spread
 *             into smaller classes, like the AT&T breakup, as of Release 1.4.0a1
 */
class PEAR_Common extends PEAR
{
    /**
     * User Interface object (PEAR_Frontend_* class).  If null,
     * the log() method uses print.
     * @var object
     */
    var $ui = null;

    /**
     * Configuration object (PEAR_Config).
     * @var PEAR_Config
     */
    var $config = null;

    /** stack of elements, gives some sort of XML context */
    var $element_stack = array();

    /** name of currently parsed XML element */
    var $current_element;

    /** array of attributes of the currently parsed XML element */
    var $current_attributes = array();

    /** assoc with information about a package */
    var $pkginfo = array();

    var $current_path = null;

    /**
     * Flag variable used to mark a valid package file
     * @var boolean
     * @access private
     */
    var $_validPackageFile;

    /**
     * PEAR_Common constructor
     *
     * @access public
     */
    function __construct()
    {
        parent::__construct();
        $this->config = &PEAR_Config::singleton();
        $this->debug = $this->config->get('verbose');
    }

    /**
     * PEAR_Common destructor
     *
     * @access private
     */
    function _PEAR_Common()
    {
        // doesn't work due to bug #14744
        //$tempfiles = $this->_tempfiles;
        $tempfiles =& $GLOBALS['_PEAR_Common_tempfiles'];
        while ($file = array_shift($tempfiles)) {
            if (@is_dir($file)) {
                if (!class_exists('System')) {
                    require_once 'System.php';
                }

                System::rm(array('-rf', $file));
            } elseif (file_exists($file)) {
                unlink($file);
            }
        }
    }

    /**
     * Register a temporary file or directory.  When the destructor is
     * executed, all registered temporary files and directories are
     * removed.
     *
     * @param string  $file  name of file or directory
     *
     * @return void
     *
     * @access public
     */
    static function addTempFile($file)
    {
        if (!class_exists('PEAR_Frontend')) {
            require_once 'PEAR/Frontend.php';
        }
        PEAR_Frontend::addTempFile($file);
    }

    /**
     * Wrapper to System::mkDir(), creates a directory as well as
     * any necessary parent directories.
     *
     * @param string  $dir  directory name
     *
     * @return bool TRUE on success, or a PEAR error
     *
     * @access public
     */
    function mkDirHier($dir)
    {
        // Only used in Installer - move it there ?
        $this->log(2, "+ create dir $dir");
        if (!class_exists('System')) {
            require_once 'System.php';
        }
        return System::mkDir(array('-p', $dir));
    }

    /**
     * Logging method.
     *
     * @param int    $level  log level (0 is quiet, higher is noisier)
     * @param string $msg    message to write to the log
     *
     * @return void
     */
    public function log($level, $msg, $append_crlf = true)
    {
        if ($this->debug >= $level) {
            if (!class_exists('PEAR_Frontend')) {
                require_once 'PEAR/Frontend.php';
            }

            $ui = &PEAR_Frontend::singleton();
            if (is_a($ui, 'PEAR_Frontend')) {
                $ui->log($msg, $append_crlf);
            } else {
                print "$msg\n";
            }
        }
    }

    /**
     * Create and register a temporary directory.
     *
     * @param string $tmpdir (optional) Directory to use as tmpdir.
     *                       Will use system defaults (for example
     *                       /tmp or c:\windows\temp) if not specified
     *
     * @return string name of created directory
     *
     * @access public
     */
    function mkTempDir($tmpdir = '')
    {
        $topt = $tmpdir ? array('-t', $tmpdir) : array();
        $topt = array_merge($topt, array('-d', 'pear'));
        if (!class_exists('System')) {
            require_once 'System.php';
        }

        if (!$tmpdir = System::mktemp($topt)) {
            return false;
        }

        self::addTempFile($tmpdir);
        return $tmpdir;
    }

    /**
     * Set object that represents the frontend to be used.
     *
     * @param  object Reference of the frontend object
     * @return void
     * @access public
     */
    function setFrontendObject(&$ui)
    {
        $this->ui = &$ui;
    }

    /**
     * Return an array containing all of the states that are more stable than
     * or equal to the passed in state
     *
     * @param string Release state
     * @param boolean Determines whether to include $state in the list
     * @return false|array False if $state is not a valid release state
     */
    static function betterStates($state, $include = false)
    {
        static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable');
        $i = array_search($state, $states);
        if ($i === false) {
            return false;
        }
        if ($include) {
            $i--;
        }
        return array_slice($states, $i + 1);
    }

    /**
     * Get the valid roles for a PEAR package maintainer
     *
     * @return array
     */
    public static function getUserRoles()
    {
        return $GLOBALS['_PEAR_Common_maintainer_roles'];
    }

    /**
     * Get the valid package release states of packages
     *
     * @return array
     */
    public static function getReleaseStates()
    {
        return $GLOBALS['_PEAR_Common_release_states'];
    }

    /**
     * Get the implemented dependency types (php, ext, pkg etc.)
     *
     * @return array
     */
    public static function getDependencyTypes()
    {
        return $GLOBALS['_PEAR_Common_dependency_types'];
    }

    /**
     * Get the implemented dependency relations (has, lt, ge etc.)
     *
     * @return array
     */
    public static function getDependencyRelations()
    {
        return $GLOBALS['_PEAR_Common_dependency_relations'];
    }

    /**
     * Get the implemented file roles
     *
     * @return array
     */
    public static function getFileRoles()
    {
        return $GLOBALS['_PEAR_Common_file_roles'];
    }

    /**
     * Get the implemented file replacement types in
     *
     * @return array
     */
    public static function getReplacementTypes()
    {
        return $GLOBALS['_PEAR_Common_replacement_types'];
    }

    /**
     * Get the implemented file replacement types in
     *
     * @return array
     */
    public static function getProvideTypes()
    {
        return $GLOBALS['_PEAR_Common_provide_types'];
    }

    /**
     * Get the implemented file replacement types in
     *
     * @return array
     */
    public static function getScriptPhases()
    {
        return $GLOBALS['_PEAR_Common_script_phases'];
    }

    /**
     * Test whether a string contains a valid package name.
     *
     * @param string $name the package name to test
     *
     * @return bool
     *
     * @access public
     */
    function validPackageName($name)
    {
        return (bool)preg_match(PEAR_COMMON_PACKAGE_NAME_PREG, $name);
    }

    /**
     * Test whether a string contains a valid package version.
     *
     * @param string $ver the package version to test
     *
     * @return bool
     *
     * @access public
     */
    function validPackageVersion($ver)
    {
        return (bool)preg_match(PEAR_COMMON_PACKAGE_VERSION_PREG, $ver);
    }

    /**
     * @param string $path relative or absolute include path
     * @return boolean
     */
    public static function isIncludeable($path)
    {
        if (file_exists($path) && is_readable($path)) {
            return true;
        }

        $ipath = explode(PATH_SEPARATOR, ini_get('include_path'));
        foreach ($ipath as $include) {
            $test = realpath($include . DIRECTORY_SEPARATOR . $path);
            if (file_exists($test) && is_readable($test)) {
                return true;
            }
        }

        return false;
    }

    function _postProcessChecks($pf)
    {
        if (!PEAR::isError($pf)) {
            return $this->_postProcessValidPackagexml($pf);
        }

        $errs = $pf->getUserinfo();
        if (is_array($errs)) {
            foreach ($errs as $error) {
                $e = $this->raiseError($error['message'], $error['code'], null, null, $error);
            }
        }

        return $pf;
    }

    /**
     * Returns information about a package file.  Expects the name of
     * a gzipped tar file as input.
     *
     * @param string  $file  name of .tgz file
     *
     * @return array  array with package information
     *
     * @access public
     * @deprecated use PEAR_PackageFile->fromTgzFile() instead
     *
     */
    function infoFromTgzFile($file)
    {
        $packagefile = new PEAR_PackageFile($this->config);
        $pf = &$packagefile->fromTgzFile($file, PEAR_VALIDATE_NORMAL);
        return $this->_postProcessChecks($pf);
    }

    /**
     * Returns information about a package file.  Expects the name of
     * a package xml file as input.
     *
     * @param string  $descfile  name of package xml file
     *
     * @return array  array with package information
     *
     * @access public
     * @deprecated use PEAR_PackageFile->fromPackageFile() instead
     *
     */
    function infoFromDescriptionFile($descfile)
    {
        $packagefile = new PEAR_PackageFile($this->config);
        $pf = &$packagefile->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL);
        return $this->_postProcessChecks($pf);
    }

    /**
     * Returns information about a package file.  Expects the contents
     * of a package xml file as input.
     *
     * @param string  $data  contents of package.xml file
     *
     * @return array   array with package information
     *
     * @access public
     * @deprecated use PEAR_PackageFile->fromXmlstring() instead
     *
     */
    function infoFromString($data)
    {
        $packagefile = new PEAR_PackageFile($this->config);
        $pf = &$packagefile->fromXmlString($data, PEAR_VALIDATE_NORMAL, false);
        return $this->_postProcessChecks($pf);
    }

    /**
     * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
     * @return array
     */
    function _postProcessValidPackagexml(&$pf)
    {
        if (!is_a($pf, 'PEAR_PackageFile_v2')) {
            $this->pkginfo = $pf->toArray();
            return $this->pkginfo;
        }

        // sort of make this into a package.xml 1.0-style array
        // changelog is not converted to old format.
        $arr = $pf->toArray(true);
        $arr = array_merge($arr, $arr['old']);
        unset($arr['old'], $arr['xsdversion'], $arr['contents'], $arr['compatible'],
              $arr['channel'], $arr['uri'], $arr['dependencies'], $arr['phprelease'],
              $arr['extsrcrelease'], $arr['zendextsrcrelease'], $arr['extbinrelease'],
              $arr['zendextbinrelease'], $arr['bundle'], $arr['lead'], $arr['developer'],
              $arr['helper'], $arr['contributor']);
        $arr['filelist'] = $pf->getFilelist();
        $this->pkginfo = $arr;
        return $arr;
    }

    /**
     * Returns package information from different sources
     *
     * This method is able to extract information about a package
     * from a .tgz archive or from a XML package definition file.
     *
     * @access public
     * @param  string Filename of the source ('package.xml', '<package>.tgz')
     * @return string
     * @deprecated use PEAR_PackageFile->fromAnyFile() instead
     */
    function infoFromAny($info)
    {
        if (is_string($info) && file_exists($info)) {
            $packagefile = new PEAR_PackageFile($this->config);
            $pf = &$packagefile->fromAnyFile($info, PEAR_VALIDATE_NORMAL);
            if (PEAR::isError($pf)) {
                $errs = $pf->getUserinfo();
                if (is_array($errs)) {
                    foreach ($errs as $error) {
                        $e = $this->raiseError($error['message'], $error['code'], null, null, $error);
                    }
                }

                return $pf;
            }

            return $this->_postProcessValidPackagexml($pf);
        }

        return $info;
    }

    /**
     * Return an XML document based on the package info (as returned
     * by the PEAR_Common::infoFrom* methods).
     *
     * @param array  $pkginfo  package info
     *
     * @return string XML data
     *
     * @access public
     * @deprecated use a PEAR_PackageFile_v* object's generator instead
     */
    function xmlFromInfo($pkginfo)
    {
        $config      = &PEAR_Config::singleton();
        $packagefile = new PEAR_PackageFile($config);
        $pf = &$packagefile->fromArray($pkginfo);
        $gen = &$pf->getDefaultGenerator();
        return $gen->toXml(PEAR_VALIDATE_PACKAGING);
    }

    /**
     * Validate XML package definition file.
     *
     * @param  string $info Filename of the package archive or of the
     *                package definition file
     * @param  array $errors Array that will contain the errors
     * @param  array $warnings Array that will contain the warnings
     * @param  string $dir_prefix (optional) directory where source files
     *                may be found, or empty if they are not available
     * @access public
     * @return boolean
     * @deprecated use the validation of PEAR_PackageFile objects
     */
    function validatePackageInfo($info, &$errors, &$warnings, $dir_prefix = '')
    {
        $config      = &PEAR_Config::singleton();
        $packagefile = new PEAR_PackageFile($config);
        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        if (strpos($info, '<?xml') !== false) {
            $pf = &$packagefile->fromXmlString($info, PEAR_VALIDATE_NORMAL, '');
        } else {
            $pf = &$packagefile->fromAnyFile($info, PEAR_VALIDATE_NORMAL);
        }

        PEAR::staticPopErrorHandling();
        if (PEAR::isError($pf)) {
            $errs = $pf->getUserinfo();
            if (is_array($errs)) {
                foreach ($errs as $error) {
                    if ($error['level'] == 'error') {
                        $errors[] = $error['message'];
                    } else {
                        $warnings[] = $error['message'];
                    }
                }
            }

            return false;
        }

        return true;
    }

    /**
     * Build a "provides" array from data returned by
     * analyzeSourceCode().  The format of the built array is like
     * this:
     *
     *  array(
     *    'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'),
     *    ...
     *  )
     *
     *
     * @param array $srcinfo array with information about a source file
     * as returned by the analyzeSourceCode() method.
     *
     * @return void
     *
     * @access public
     *
     */
    function buildProvidesArray($srcinfo)
    {
        $file = basename($srcinfo['source_file']);
        $pn = '';
        if (isset($this->_packageName)) {
            $pn = $this->_packageName;
        }

        $pnl = strlen($pn);
        foreach ($srcinfo['declared_classes'] as $class) {
            $key = "class;$class";
            if (isset($this->pkginfo['provides'][$key])) {
                continue;
            }

            $this->pkginfo['provides'][$key] =
                array('file'=> $file, 'type' => 'class', 'name' => $class);
            if (isset($srcinfo['inheritance'][$class])) {
                $this->pkginfo['provides'][$key]['extends'] =
                    $srcinfo['inheritance'][$class];
            }
        }

        foreach ($srcinfo['declared_methods'] as $class => $methods) {
            foreach ($methods as $method) {
                $function = "$class::$method";
                $key = "function;$function";
                if ($method[0] == '_' || !strcasecmp($method, $class) ||
                    isset($this->pkginfo['provides'][$key])) {
                    continue;
                }

                $this->pkginfo['provides'][$key] =
                    array('file'=> $file, 'type' => 'function', 'name' => $function);
            }
        }

        foreach ($srcinfo['declared_functions'] as $function) {
            $key = "function;$function";
            if ($function[0] == '_' || isset($this->pkginfo['provides'][$key])) {
                continue;
            }

            if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) {
                $warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\"";
            }

            $this->pkginfo['provides'][$key] =
                array('file'=> $file, 'type' => 'function', 'name' => $function);
        }
    }

    /**
     * Analyze the source code of the given PHP file
     *
     * @param  string Filename of the PHP file
     * @return mixed
     * @access public
     */
    static function analyzeSourceCode($file)
    {
        if (!class_exists('PEAR_PackageFile_v2_Validator')) {
            require_once 'PEAR/PackageFile/v2/Validator.php';
        }

        $a = new PEAR_PackageFile_v2_Validator;
        return $a->analyzeSourceCode($file);
    }

    function detectDependencies($any, $status_callback = null)
    {
        if (!function_exists("token_get_all")) {
            return false;
        }

        if (PEAR::isError($info = $this->infoFromAny($any))) {
            return $this->raiseError($info);
        }

        if (!is_array($info)) {
            return false;
        }

        $deps = array();
        $used_c = $decl_c = $decl_f = $decl_m = array();
        foreach ($info['filelist'] as $file => $fa) {
            $tmp = $this->analyzeSourceCode($file);
            $used_c = @array_merge($used_c, $tmp['used_classes']);
            $decl_c = @array_merge($decl_c, $tmp['declared_classes']);
            $decl_f = @array_merge($decl_f, $tmp['declared_functions']);
            $decl_m = @array_merge($decl_m, $tmp['declared_methods']);
            $inheri = @array_merge($inheri, $tmp['inheritance']);
        }

        $used_c = array_unique($used_c);
        $decl_c = array_unique($decl_c);
        $undecl_c = array_diff($used_c, $decl_c);

        return array('used_classes' => $used_c,
                     'declared_classes' => $decl_c,
                     'declared_methods' => $decl_m,
                     'declared_functions' => $decl_f,
                     'undeclared_classes' => $undecl_c,
                     'inheritance' => $inheri,
                     );
    }

    /**
     * Download a file through HTTP.  Considers suggested file name in
     * Content-disposition: header and can run a callback function for
     * different events.  The callback will be called with two
     * parameters: the callback type, and parameters.  The implemented
     * callback types are:
     *
     *  'setup'       called at the very beginning, parameter is a UI object
     *                that should be used for all output
     *  'message'     the parameter is a string with an informational message
     *  'saveas'      may be used to save with a different file name, the
     *                parameter is the filename that is about to be used.
     *                If a 'saveas' callback returns a non-empty string,
     *                that file name will be used as the filename instead.
     *                Note that $save_dir will not be affected by this, only
     *                the basename of the file.
     *  'start'       download is starting, parameter is number of bytes
     *                that are expected, or -1 if unknown
     *  'bytesread'   parameter is the number of bytes read so far
     *  'done'        download is complete, parameter is the total number
     *                of bytes read
     *  'connfailed'  if the TCP connection fails, this callback is called
     *                with array(host,port,errno,errmsg)
     *  'writefailed' if writing to disk fails, this callback is called
     *                with array(destfile,errmsg)
     *
     * If an HTTP proxy has been configured (http_proxy PEAR_Config
     * setting), the proxy will be used.
     *
     * @param string  $url       the URL to download
     * @param object  $ui        PEAR_Frontend_* instance
     * @param object  $config    PEAR_Config instance
     * @param string  $save_dir  (optional) directory to save file in
     * @param mixed   $callback  (optional) function/method to call for status
     *                           updates
     * @param false|string|array $lastmodified header values to check against
     *                                         for caching
     *                                         use false to return the header
     *                                         values from this download
     * @param false|array        $accept       Accept headers to send
     * @param false|string       $channel      Channel to use for retrieving
     *                                         authentication
     *
     * @return mixed  Returns the full path of the downloaded file or a PEAR
     *                error on failure.  If the error is caused by
     *                socket-related errors, the error object will
     *                have the fsockopen error code available through
     *                getCode().  If caching is requested, then return the header
     *                values.
     *                If $lastmodified was given and the there are no changes,
     *                boolean false is returned.
     *
     * @access public
     */
    function downloadHttp(
        $url, &$ui, $save_dir = '.', $callback = null, $lastmodified = null,
        $accept = false, $channel = false
    ) {
        if (!class_exists('PEAR_Downloader')) {
            require_once 'PEAR/Downloader.php';
        }
        return PEAR_Downloader::_downloadHttp(
            $this, $url, $ui, $save_dir, $callback, $lastmodified,
            $accept, $channel
        );
    }
}

require_once 'PEAR/Config.php';
require_once 'PEAR/PackageFile.php';
PKr�Z$���(�(PEAR/Registry.phpnu�[���<?php
/**
 * PEAR_Registry
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Tomas V. V. Cox <cox@idecnet.com>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 0.1
 */

/**
 * for PEAR_Error
 */
require_once 'PEAR.php';
require_once 'PEAR/DependencyDB.php';

define('PEAR_REGISTRY_ERROR_LOCK',         -2);
define('PEAR_REGISTRY_ERROR_FORMAT',       -3);
define('PEAR_REGISTRY_ERROR_FILE',         -4);
define('PEAR_REGISTRY_ERROR_CONFLICT',     -5);
define('PEAR_REGISTRY_ERROR_CHANNEL_FILE', -6);

/**
 * Administration class used to maintain the installed package database.
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Tomas V. V. Cox <cox@idecnet.com>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 */
class PEAR_Registry extends PEAR
{
    /**
     * File containing all channel information.
     * @var string
     */
    var $channels = '';

    /** Directory where registry files are stored.
     * @var string
     */
    var $statedir = '';

    /** File where the file map is stored
     * @var string
     */
    var $filemap = '';

    /** Directory where registry files for channels are stored.
     * @var string
     */
    var $channelsdir = '';

    /** Name of file used for locking the registry
     * @var string
     */
    var $lockfile = '';

    /** File descriptor used during locking
     * @var resource
     */
    var $lock_fp = null;

    /** Mode used during locking
     * @var int
     */
    var $lock_mode = 0; // XXX UNUSED

    /** Cache of package information.  Structure:
     * array(
     *   'package' => array('id' => ... ),
     *   ... )
     * @var array
     */
    var $pkginfo_cache = array();

    /** Cache of file map.  Structure:
     * array( '/path/to/file' => 'package', ... )
     * @var array
     */
    var $filemap_cache = array();

    /**
     * @var false|PEAR_ChannelFile
     */
    var $_pearChannel;

    /**
     * @var false|PEAR_ChannelFile
     */
    var $_peclChannel;

    /**
     * @var false|PEAR_ChannelFile
     */
    var $_docChannel;

    /**
     * @var PEAR_DependencyDB
     */
    var $_dependencyDB;

    /**
     * @var PEAR_Config
     */
    var $_config;

    /**
     * PEAR_Registry constructor.
     *
     * @param string (optional) PEAR install directory (for .php files)
     * @param PEAR_ChannelFile PEAR_ChannelFile object representing the PEAR channel, if
     *        default values are not desired.  Only used the very first time a PEAR
     *        repository is initialized
     * @param PEAR_ChannelFile PEAR_ChannelFile object representing the PECL channel, if
     *        default values are not desired.  Only used the very first time a PEAR
     *        repository is initialized
     *
     * @access public
     */
    function __construct($pear_install_dir = PEAR_INSTALL_DIR, $pear_channel = false,
                           $pecl_channel = false, $pear_metadata_dir = '')
    {
        parent::__construct();
        $this->setInstallDir($pear_install_dir, $pear_metadata_dir);
        $this->_pearChannel = $pear_channel;
        $this->_peclChannel = $pecl_channel;
        $this->_config      = false;
    }

    function setInstallDir($pear_install_dir = PEAR_INSTALL_DIR, $pear_metadata_dir = '')
    {
        $ds = DIRECTORY_SEPARATOR;
        $this->install_dir = $pear_install_dir;
        if (!$pear_metadata_dir) {
            $pear_metadata_dir = $pear_install_dir;
        }
        $this->channelsdir = $pear_metadata_dir.$ds.'.channels';
        $this->statedir    = $pear_metadata_dir.$ds.'.registry';
        $this->filemap     = $pear_metadata_dir.$ds.'.filemap';
        $this->lockfile    = $pear_metadata_dir.$ds.'.lock';
    }

    function hasWriteAccess()
    {
        if (!file_exists($this->install_dir)) {
            $dir = $this->install_dir;
            while ($dir && $dir != '.') {
                $olddir = $dir;
                $dir    = dirname($dir);
                if ($dir != '.' && file_exists($dir)) {
                    if (is_writeable($dir)) {
                        return true;
                    }

                    return false;
                }

                if ($dir == $olddir) { // this can happen in safe mode
                    return @is_writable($dir);
                }
            }

            return false;
        }

        return is_writeable($this->install_dir);
    }

    function setConfig(&$config, $resetInstallDir = true)
    {
        $this->_config = &$config;
        if ($resetInstallDir) {
            $this->setInstallDir($config->get('php_dir'), $config->get('metadata_dir'));
        }
    }

    function _initializeChannelDirs()
    {
        static $running = false;
        if (!$running) {
            $running = true;
            $ds = DIRECTORY_SEPARATOR;
            if (!is_dir($this->channelsdir) ||
                  !file_exists($this->channelsdir . $ds . 'pear.php.net.reg') ||
                  !file_exists($this->channelsdir . $ds . 'pecl.php.net.reg') ||
                  !file_exists($this->channelsdir . $ds . 'doc.php.net.reg') ||
                  !file_exists($this->channelsdir . $ds . '__uri.reg')) {
                if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) {
                    $pear_channel = $this->_pearChannel;
                    if (!is_a($pear_channel, 'PEAR_ChannelFile') || !$pear_channel->validate()) {
                        if (!class_exists('PEAR_ChannelFile')) {
                            require_once 'PEAR/ChannelFile.php';
                        }

                        $pear_channel = new PEAR_ChannelFile;
                        $pear_channel->setAlias('pear');
                        $pear_channel->setServer('pear.php.net');
                        $pear_channel->setSummary('PHP Extension and Application Repository');
                        $pear_channel->setDefaultPEARProtocols();
                        $pear_channel->setBaseURL('REST1.0', 'http://pear.php.net/rest/');
                        $pear_channel->setBaseURL('REST1.1', 'http://pear.php.net/rest/');
                        $pear_channel->setBaseURL('REST1.3', 'http://pear.php.net/rest/');
                        //$pear_channel->setBaseURL('REST1.4', 'http://pear.php.net/rest/');
                    } else {
                        $pear_channel->setServer('pear.php.net');
                        $pear_channel->setAlias('pear');
                    }

                    $pear_channel->validate();
                    $this->_addChannel($pear_channel);
                }

                if (!file_exists($this->channelsdir . $ds . 'pecl.php.net.reg')) {
                    $pecl_channel = $this->_peclChannel;
                    if (!is_a($pecl_channel, 'PEAR_ChannelFile') || !$pecl_channel->validate()) {
                        if (!class_exists('PEAR_ChannelFile')) {
                            require_once 'PEAR/ChannelFile.php';
                        }

                        $pecl_channel = new PEAR_ChannelFile;
                        $pecl_channel->setAlias('pecl');
                        $pecl_channel->setServer('pecl.php.net');
                        $pecl_channel->setSummary('PHP Extension Community Library');
                        $pecl_channel->setDefaultPEARProtocols();
                        $pecl_channel->setBaseURL('REST1.0', 'http://pecl.php.net/rest/');
                        $pecl_channel->setBaseURL('REST1.1', 'http://pecl.php.net/rest/');
                        $pecl_channel->setValidationPackage('PEAR_Validator_PECL', '1.0');
                    } else {
                        $pecl_channel->setServer('pecl.php.net');
                        $pecl_channel->setAlias('pecl');
                    }

                    $pecl_channel->validate();
                    $this->_addChannel($pecl_channel);
                }

                if (!file_exists($this->channelsdir . $ds . 'doc.php.net.reg')) {
                    $doc_channel = $this->_docChannel;
                    if (!is_a($doc_channel, 'PEAR_ChannelFile') || !$doc_channel->validate()) {
                        if (!class_exists('PEAR_ChannelFile')) {
                            require_once 'PEAR/ChannelFile.php';
                        }

                        $doc_channel = new PEAR_ChannelFile;
                        $doc_channel->setAlias('phpdocs');
                        $doc_channel->setServer('doc.php.net');
                        $doc_channel->setSummary('PHP Documentation Team');
                        $doc_channel->setDefaultPEARProtocols();
                        $doc_channel->setBaseURL('REST1.0', 'http://doc.php.net/rest/');
                        $doc_channel->setBaseURL('REST1.1', 'http://doc.php.net/rest/');
                        $doc_channel->setBaseURL('REST1.3', 'http://doc.php.net/rest/');
                    } else {
                        $doc_channel->setServer('doc.php.net');
                        $doc_channel->setAlias('doc');
                    }

                    $doc_channel->validate();
                    $this->_addChannel($doc_channel);
                }

                if (!file_exists($this->channelsdir . $ds . '__uri.reg')) {
                    if (!class_exists('PEAR_ChannelFile')) {
                        require_once 'PEAR/ChannelFile.php';
                    }

                    $private = new PEAR_ChannelFile;
                    $private->setName('__uri');
                    $private->setDefaultPEARProtocols();
                    $private->setBaseURL('REST1.0', '****');
                    $private->setSummary('Pseudo-channel for static packages');
                    $this->_addChannel($private);
                }
                $this->_rebuildFileMap();
            }

            $running = false;
        }
    }

    function _initializeDirs()
    {
        $ds = DIRECTORY_SEPARATOR;
        // XXX Compatibility code should be removed in the future
        // rename all registry files if any to lowercase
        if (!OS_WINDOWS && file_exists($this->statedir) && is_dir($this->statedir) &&
              $handle = opendir($this->statedir)) {
            $dest = $this->statedir . $ds;
            while (false !== ($file = readdir($handle))) {
                if (preg_match('/^.*[A-Z].*\.reg\\z/', $file)) {
                    rename($dest . $file, $dest . strtolower($file));
                }
            }
            closedir($handle);
        }

        $this->_initializeChannelDirs();
        if (!file_exists($this->filemap)) {
            $this->_rebuildFileMap();
        }
        $this->_initializeDepDB();
    }

    function _initializeDepDB()
    {
        if (!isset($this->_dependencyDB)) {
            static $initializing = false;
            if (!$initializing) {
                $initializing = true;
                if (!$this->_config) { // never used?
                    $file = OS_WINDOWS ? 'pear.ini' : '.pearrc';
                    $this->_config = new PEAR_Config($this->statedir . DIRECTORY_SEPARATOR .
                        $file);
                    $this->_config->setRegistry($this);
                    $this->_config->set('php_dir', $this->install_dir);
                }

                $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->_config);
                if (PEAR::isError($this->_dependencyDB)) {
                    // attempt to recover by removing the dep db
                    if (file_exists($this->_config->get('metadata_dir', null, 'pear.php.net') .
                        DIRECTORY_SEPARATOR . '.depdb')) {
                        @unlink($this->_config->get('metadata_dir', null, 'pear.php.net') .
                            DIRECTORY_SEPARATOR . '.depdb');
                    }

                    $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->_config);
                    if (PEAR::isError($this->_dependencyDB)) {
                        echo $this->_dependencyDB->getMessage();
                        echo 'Unrecoverable error';
                        exit(1);
                    }
                }

                $initializing = false;
            }
        }
    }

    /**
     * PEAR_Registry destructor.  Makes sure no locks are forgotten.
     *
     * @access private
     */
    function _PEAR_Registry()
    {
        parent::_PEAR();
        if (is_resource($this->lock_fp)) {
            $this->_unlock();
        }
    }

    /**
     * Make sure the directory where we keep registry files exists.
     *
     * @return bool TRUE if directory exists, FALSE if it could not be
     * created
     *
     * @access private
     */
    function _assertStateDir($channel = false)
    {
        if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') {
            return $this->_assertChannelStateDir($channel);
        }

        static $init = false;
        if (!file_exists($this->statedir)) {
            if (!$this->hasWriteAccess()) {
                return false;
            }

            require_once 'System.php';
            if (!System::mkdir(array('-p', $this->statedir))) {
                return $this->raiseError("could not create directory '{$this->statedir}'");
            }
            $init = true;
        } elseif (!is_dir($this->statedir)) {
            return $this->raiseError('Cannot create directory ' . $this->statedir . ', ' .
                'it already exists and is not a directory');
        }

        $ds = DIRECTORY_SEPARATOR;
        if (!file_exists($this->channelsdir)) {
            if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg') ||
                  !file_exists($this->channelsdir . $ds . 'pecl.php.net.reg') ||
                  !file_exists($this->channelsdir . $ds . 'doc.php.net.reg') ||
                  !file_exists($this->channelsdir . $ds . '__uri.reg')) {
                $init = true;
            }
        } elseif (!is_dir($this->channelsdir)) {
            return $this->raiseError('Cannot create directory ' . $this->channelsdir . ', ' .
                'it already exists and is not a directory');
        }

        if ($init) {
            static $running = false;
            if (!$running) {
                $running = true;
                $this->_initializeDirs();
                $running = false;
                $init = false;
            }
        } else {
            $this->_initializeDepDB();
        }

        return true;
    }

    /**
     * Make sure the directory where we keep registry files exists for a non-standard channel.
     *
     * @param string channel name
     * @return bool TRUE if directory exists, FALSE if it could not be
     * created
     *
     * @access private
     */
    function _assertChannelStateDir($channel)
    {
        $ds = DIRECTORY_SEPARATOR;
        if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') {
            if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) {
                $this->_initializeChannelDirs();
            }
            return $this->_assertStateDir($channel);
        }

        $channelDir = $this->_channelDirectoryName($channel);
        if (!is_dir($this->channelsdir) ||
              !file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) {
            $this->_initializeChannelDirs();
        }

        if (!file_exists($channelDir)) {
            if (!$this->hasWriteAccess()) {
                return false;
            }

            require_once 'System.php';
            if (!System::mkdir(array('-p', $channelDir))) {
                return $this->raiseError("could not create directory '" . $channelDir .
                    "'");
            }
        } elseif (!is_dir($channelDir)) {
            return $this->raiseError("could not create directory '" . $channelDir .
                "', already exists and is not a directory");
        }

        return true;
    }

    /**
     * Make sure the directory where we keep registry files for channels exists
     *
     * @return bool TRUE if directory exists, FALSE if it could not be
     * created
     *
     * @access private
     */
    function _assertChannelDir()
    {
        if (!file_exists($this->channelsdir)) {
            if (!$this->hasWriteAccess()) {
                return false;
            }

            require_once 'System.php';
            if (!System::mkdir(array('-p', $this->channelsdir))) {
                return $this->raiseError("could not create directory '{$this->channelsdir}'");
            }
        } elseif (!is_dir($this->channelsdir)) {
            return $this->raiseError("could not create directory '{$this->channelsdir}" .
                "', it already exists and is not a directory");
        }

        if (!file_exists($this->channelsdir . DIRECTORY_SEPARATOR . '.alias')) {
            if (!$this->hasWriteAccess()) {
                return false;
            }

            require_once 'System.php';
            if (!System::mkdir(array('-p', $this->channelsdir . DIRECTORY_SEPARATOR . '.alias'))) {
                return $this->raiseError("could not create directory '{$this->channelsdir}/.alias'");
            }
        } elseif (!is_dir($this->channelsdir . DIRECTORY_SEPARATOR . '.alias')) {
            return $this->raiseError("could not create directory '{$this->channelsdir}" .
                "/.alias', it already exists and is not a directory");
        }

        return true;
    }

    /**
     * Get the name of the file where data for a given package is stored.
     *
     * @param string channel name, or false if this is a PEAR package
     * @param string package name
     *
     * @return string registry file name
     *
     * @access public
     */
    function _packageFileName($package, $channel = false)
    {
        if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') {
            return $this->_channelDirectoryName($channel) . DIRECTORY_SEPARATOR .
                strtolower($package) . '.reg';
        }

        return $this->statedir . DIRECTORY_SEPARATOR . strtolower($package) . '.reg';
    }

    /**
     * Get the name of the file where data for a given channel is stored.
     * @param string channel name
     * @return string registry file name
     */
    function _channelFileName($channel, $noaliases = false)
    {
        if (!$noaliases) {
            if (file_exists($this->_getChannelAliasFileName($channel))) {
                $channel = implode('', file($this->_getChannelAliasFileName($channel)));
            }
        }
        return $this->channelsdir . DIRECTORY_SEPARATOR . str_replace('/', '_',
            strtolower($channel)) . '.reg';
    }

    /**
     * @param string
     * @return string
     */
    function _getChannelAliasFileName($alias)
    {
        return $this->channelsdir . DIRECTORY_SEPARATOR . '.alias' .
              DIRECTORY_SEPARATOR . str_replace('/', '_', strtolower($alias)) . '.txt';
    }

    /**
     * Get the name of a channel from its alias
     */
    function _getChannelFromAlias($channel)
    {
        if (!$this->_channelExists($channel)) {
            if ($channel == 'pear.php.net') {
                return 'pear.php.net';
            }

            if ($channel == 'pecl.php.net') {
                return 'pecl.php.net';
            }

            if ($channel == 'doc.php.net') {
                return 'doc.php.net';
            }

            if ($channel == '__uri') {
                return '__uri';
            }

            return false;
        }

        $channel = strtolower($channel);
        if (file_exists($this->_getChannelAliasFileName($channel))) {
            // translate an alias to an actual channel
            return implode('', file($this->_getChannelAliasFileName($channel)));
        }

        return $channel;
    }

    /**
     * Get the alias of a channel from its alias or its name
     */
    function _getAlias($channel)
    {
        if (!$this->_channelExists($channel)) {
            if ($channel == 'pear.php.net') {
                return 'pear';
            }

            if ($channel == 'pecl.php.net') {
                return 'pecl';
            }

            if ($channel == 'doc.php.net') {
                return 'phpdocs';
            }

            return false;
        }

        $channel = $this->_getChannel($channel);
        if (PEAR::isError($channel)) {
            return $channel;
        }

        return $channel->getAlias();
    }

    /**
     * Get the name of the file where data for a given package is stored.
     *
     * @param string channel name, or false if this is a PEAR package
     * @param string package name
     *
     * @return string registry file name
     *
     * @access public
     */
    function _channelDirectoryName($channel)
    {
        if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') {
            return $this->statedir;
        }

        $ch = $this->_getChannelFromAlias($channel);
        if (!$ch) {
            $ch = $channel;
        }

        return $this->statedir . DIRECTORY_SEPARATOR . strtolower('.channel.' .
            str_replace('/', '_', $ch));
    }

    function _openPackageFile($package, $mode, $channel = false)
    {
        if (!$this->_assertStateDir($channel)) {
            return null;
        }

        if (!in_array($mode, array('r', 'rb')) && !$this->hasWriteAccess()) {
            return null;
        }

        $file = $this->_packageFileName($package, $channel);
        if (!file_exists($file) && $mode == 'r' || $mode == 'rb') {
            return null;
        }

        $fp = @fopen($file, $mode);
        if (!$fp) {
            return null;
        }

        return $fp;
    }

    function _closePackageFile($fp)
    {
        fclose($fp);
    }

    function _openChannelFile($channel, $mode)
    {
        if (!$this->_assertChannelDir()) {
            return null;
        }

        if (!in_array($mode, array('r', 'rb')) && !$this->hasWriteAccess()) {
            return null;
        }

        $file = $this->_channelFileName($channel);
        if (!file_exists($file) && $mode == 'r' || $mode == 'rb') {
            return null;
        }

        $fp = @fopen($file, $mode);
        if (!$fp) {
            return null;
        }

        return $fp;
    }

    function _closeChannelFile($fp)
    {
        fclose($fp);
    }

    function _rebuildFileMap()
    {
        if (!class_exists('PEAR_Installer_Role')) {
            require_once 'PEAR/Installer/Role.php';
        }

        $channels = $this->_listAllPackages();
        $files = array();
        foreach ($channels as $channel => $packages) {
            foreach ($packages as $package) {
                $version = $this->_packageInfo($package, 'version', $channel);
                $filelist = $this->_packageInfo($package, 'filelist', $channel);
                if (!is_array($filelist)) {
                    continue;
                }

                foreach ($filelist as $name => $attrs) {
                    if (isset($attrs['attribs'])) {
                        $attrs = $attrs['attribs'];
                    }

                    // it is possible for conflicting packages in different channels to
                    // conflict with data files/doc files
                    if ($name == 'dirtree') {
                        continue;
                    }

                    if (isset($attrs['role']) && !in_array($attrs['role'],
                          PEAR_Installer_Role::getInstallableRoles())) {
                        // these are not installed
                        continue;
                    }

                    if (isset($attrs['role']) && !in_array($attrs['role'],
                          PEAR_Installer_Role::getBaseinstallRoles())) {
                        $attrs['baseinstalldir'] = $package;
                    }

                    if (isset($attrs['baseinstalldir'])) {
                        $file = $attrs['baseinstalldir'].DIRECTORY_SEPARATOR.$name;
                    } else {
                        $file = $name;
                    }

                    $file = preg_replace(',^/+,', '', $file);
                    if ($channel != 'pear.php.net') {
                        if (!isset($files[$attrs['role']])) {
                            $files[$attrs['role']] = array();
                        }
                        $files[$attrs['role']][$file] = array(strtolower($channel),
                            strtolower($package));
                    } else {
                        if (!isset($files[$attrs['role']])) {
                            $files[$attrs['role']] = array();
                        }
                        $files[$attrs['role']][$file] = strtolower($package);
                    }
                }
            }
        }


        $this->_assertStateDir();
        if (!$this->hasWriteAccess()) {
            return false;
        }

        $fp = @fopen($this->filemap, 'wb');
        if (!$fp) {
            return false;
        }

        $this->filemap_cache = $files;
        fwrite($fp, serialize($files));
        fclose($fp);
        return true;
    }

    function _readFileMap()
    {
        if (!file_exists($this->filemap)) {
            return array();
        }

        $fp = @fopen($this->filemap, 'r');
        if (!$fp) {
            $last_errormsg = '';
            $last_error = error_get_last();
            if (!empty($last_error['message'])) {
                $last_errormsg = $last_error['message'];
            }
            return $this->raiseError('PEAR_Registry: could not open filemap "' . $this->filemap . '"', PEAR_REGISTRY_ERROR_FILE, null, null, $last_errormsg);
        }

        clearstatcache();
        $fsize = filesize($this->filemap);
        fclose($fp);
        $data = file_get_contents($this->filemap);
        $tmp = unserialize($data);
        if (!$tmp && $fsize > 7) {
            return $this->raiseError('PEAR_Registry: invalid filemap data', PEAR_REGISTRY_ERROR_FORMAT, null, null, $data);
        }

        $this->filemap_cache = $tmp;
        return true;
    }

    /**
     * Lock the registry.
     *
     * @param integer lock mode, one of LOCK_EX, LOCK_SH or LOCK_UN.
     *                See flock manual for more information.
     *
     * @return bool TRUE on success, FALSE if locking failed, or a
     *              PEAR error if some other error occurs (such as the
     *              lock file not being writable).
     *
     * @access private
     */
    function _lock($mode = LOCK_EX)
    {
        if (stristr(php_uname(), 'Windows 9')) {
            return true;
        }

        if ($mode != LOCK_UN && is_resource($this->lock_fp)) {
            // XXX does not check type of lock (LOCK_SH/LOCK_EX)
            return true;
        }

        if (!$this->_assertStateDir()) {
            if ($mode == LOCK_EX) {
                return $this->raiseError('Registry directory is not writeable by the current user');
            }

            return true;
        }

        $open_mode = 'w';
        // XXX People reported problems with LOCK_SH and 'w'
        if ($mode === LOCK_SH || $mode === LOCK_UN) {
            if (!file_exists($this->lockfile)) {
                touch($this->lockfile);
            }
            $open_mode = 'r';
        }

        if (!is_resource($this->lock_fp)) {
            $this->lock_fp = @fopen($this->lockfile, $open_mode);
        }

        if (!is_resource($this->lock_fp)) {
            $this->lock_fp = null;
            return $this->raiseError("could not create lock file" .
                                     (isset($php_errormsg) ? ": " . $php_errormsg : ""));
        }

        if (!(int)flock($this->lock_fp, $mode)) {
            switch ($mode) {
                case LOCK_SH: $str = 'shared';    break;
                case LOCK_EX: $str = 'exclusive'; break;
                case LOCK_UN: $str = 'unlock';    break;
                default:      $str = 'unknown';   break;
            }

            //is resource at this point, close it on error.
            fclose($this->lock_fp);
            $this->lock_fp = null;
            return $this->raiseError("could not acquire $str lock ($this->lockfile)",
                                     PEAR_REGISTRY_ERROR_LOCK);
        }

        return true;
    }

    function _unlock()
    {
        $ret = $this->_lock(LOCK_UN);
        if (is_resource($this->lock_fp)) {
            fclose($this->lock_fp);
        }

        $this->lock_fp = null;
        return $ret;
    }

    function _packageExists($package, $channel = false)
    {
        return file_exists($this->_packageFileName($package, $channel));
    }

    /**
     * Determine whether a channel exists in the registry
     *
     * @param string Channel name
     * @param bool if true, then aliases will be ignored
     * @return boolean
     */
    function _channelExists($channel, $noaliases = false)
    {
        $a = file_exists($this->_channelFileName($channel, $noaliases));
        if (!$a && $channel == 'pear.php.net') {
            return true;
        }

        if (!$a && $channel == 'pecl.php.net') {
            return true;
        }

        if (!$a && $channel == 'doc.php.net') {
            return true;
        }

        return $a;
    }

    /**
     * Determine whether a mirror exists within the default channel in the registry
     *
     * @param string Channel name
     * @param string Mirror name
     *
     * @return boolean
     */
    function _mirrorExists($channel, $mirror)
    {
        $data = $this->_channelInfo($channel);
        if (!isset($data['servers']['mirror'])) {
            return false;
        }

        foreach ($data['servers']['mirror'] as $m) {
            if ($m['attribs']['host'] == $mirror) {
                return true;
            }
        }

        return false;
    }

    /**
     * @param PEAR_ChannelFile Channel object
     * @param donotuse
     * @param string Last-Modified HTTP tag from remote request
     * @return boolean|PEAR_Error True on creation, false if it already exists
     */
    function _addChannel($channel, $update = false, $lastmodified = false)
    {
        if (!is_a($channel, 'PEAR_ChannelFile')) {
            return false;
        }

        if (!$channel->validate()) {
            return false;
        }

        if (file_exists($this->_channelFileName($channel->getName()))) {
            if (!$update) {
                return false;
            }

            $checker = $this->_getChannel($channel->getName());
            if (PEAR::isError($checker)) {
                return $checker;
            }

            if ($channel->getAlias() != $checker->getAlias()) {
                if (file_exists($this->_getChannelAliasFileName($checker->getAlias()))) {
                    @unlink($this->_getChannelAliasFileName($checker->getAlias()));
                }
            }
        } else {
            if ($update && !in_array($channel->getName(), array('pear.php.net', 'pecl.php.net', 'doc.php.net'))) {
                return false;
            }
        }

        $ret = $this->_assertChannelDir();
        if (PEAR::isError($ret)) {
            return $ret;
        }

        $ret = $this->_assertChannelStateDir($channel->getName());
        if (PEAR::isError($ret)) {
            return $ret;
        }

        if ($channel->getAlias() != $channel->getName()) {
            if (file_exists($this->_getChannelAliasFileName($channel->getAlias())) &&
                  $this->_getChannelFromAlias($channel->getAlias()) != $channel->getName()) {
                $channel->setAlias($channel->getName());
            }

            if (!$this->hasWriteAccess()) {
                return false;
            }

            $fp = @fopen($this->_getChannelAliasFileName($channel->getAlias()), 'w');
            if (!$fp) {
                return false;
            }

            fwrite($fp, $channel->getName());
            fclose($fp);
        }

        if (!$this->hasWriteAccess()) {
            return false;
        }

        $fp = @fopen($this->_channelFileName($channel->getName()), 'wb');
        if (!$fp) {
            return false;
        }

        $info = $channel->toArray();
        if ($lastmodified) {
            $info['_lastmodified'] = $lastmodified;
        } else {
            $info['_lastmodified'] = self::getSourceDateEpoch();
        }

        fwrite($fp, serialize($info));
        fclose($fp);
        return true;
    }

    /**
     * Deletion fails if there are any packages installed from the channel
     * @param string|PEAR_ChannelFile channel name
     * @return boolean|PEAR_Error True on deletion, false if it doesn't exist
     */
    function _deleteChannel($channel)
    {
        if (!is_string($channel)) {
            if (!is_a($channel, 'PEAR_ChannelFile')) {
                return false;
            }

            if (!$channel->validate()) {
                return false;
            }
            $channel = $channel->getName();
        }

        if ($this->_getChannelFromAlias($channel) == '__uri') {
            return false;
        }

        if ($this->_getChannelFromAlias($channel) == 'pecl.php.net') {
            return false;
        }

        if ($this->_getChannelFromAlias($channel) == 'doc.php.net') {
            return false;
        }

        if (!$this->_channelExists($channel)) {
            return false;
        }

        if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') {
            return false;
        }

        $channel = $this->_getChannelFromAlias($channel);
        if ($channel == 'pear.php.net') {
            return false;
        }

        $test = $this->_listChannelPackages($channel);
        if (count($test)) {
            return false;
        }

        $test = @rmdir($this->_channelDirectoryName($channel));
        if (!$test) {
            return false;
        }

        $file = $this->_getChannelAliasFileName($this->_getAlias($channel));
        if (file_exists($file)) {
            $test = @unlink($file);
            if (!$test) {
                return false;
            }
        }

        $file = $this->_channelFileName($channel);
        $ret = true;
        if (file_exists($file)) {
            $ret = @unlink($file);
        }

        return $ret;
    }

    /**
     * Determine whether a channel exists in the registry
     * @param string Channel Alias
     * @return boolean
     */
    function _isChannelAlias($alias)
    {
        return file_exists($this->_getChannelAliasFileName($alias));
    }

    /**
     * @param string|null
     * @param string|null
     * @param string|null
     * @return array|null
     * @access private
     */
    function _packageInfo($package = null, $key = null, $channel = 'pear.php.net')
    {
        if ($package === null) {
            if ($channel === null) {
                $channels = $this->_listChannels();
                $ret = array();
                foreach ($channels as $channel) {
                    $channel = strtolower($channel);
                    $ret[$channel] = array();
                    $packages = $this->_listPackages($channel);
                    foreach ($packages as $package) {
                        $ret[$channel][] = $this->_packageInfo($package, null, $channel);
                    }
                }

                return $ret;
            }

            $ps = $this->_listPackages($channel);
            if (!count($ps)) {
                return array();
            }
            return array_map(array(&$this, '_packageInfo'),
                             $ps, array_fill(0, count($ps), null),
                             array_fill(0, count($ps), $channel));
        }

        $fp = $this->_openPackageFile($package, 'r', $channel);
        if ($fp === null) {
            return null;
        }

        clearstatcache();
        $this->_closePackageFile($fp);
        $data = file_get_contents($this->_packageFileName($package, $channel));
        $data = @unserialize($data);
        if ($key === null) {
            return $data;
        }

        // compatibility for package.xml version 2.0
        if (isset($data['old'][$key])) {
            return $data['old'][$key];
        }

        if (isset($data[$key])) {
            return $data[$key];
        }

        return null;
    }

    /**
     * @param string Channel name
     * @param bool whether to strictly retrieve info of channels, not just aliases
     * @return array|null
     */
    function _channelInfo($channel, $noaliases = false)
    {
        if (!$this->_channelExists($channel, $noaliases)) {
            return null;
        }

        $fp = $this->_openChannelFile($channel, 'r');
        if ($fp === null) {
            return null;
        }

        clearstatcache();
        $this->_closeChannelFile($fp);
        $data = file_get_contents($this->_channelFileName($channel));
        $data = unserialize($data);
        return $data;
    }

    function _listChannels()
    {
        $channellist = array();
        if (!file_exists($this->channelsdir) || !is_dir($this->channelsdir)) {
            return array('pear.php.net', 'pecl.php.net', 'doc.php.net', '__uri');
        }

        $dp = opendir($this->channelsdir);
        while ($ent = readdir($dp)) {
            if ($ent[0] == '.' || substr($ent, -4) != '.reg') {
                continue;
            }

            if ($ent == '__uri.reg') {
                $channellist[] = '__uri';
                continue;
            }

            $channellist[] = str_replace('_', '/', substr($ent, 0, -4));
        }

        closedir($dp);
        if (!in_array('pear.php.net', $channellist)) {
            $channellist[] = 'pear.php.net';
        }

        if (!in_array('pecl.php.net', $channellist)) {
            $channellist[] = 'pecl.php.net';
        }

        if (!in_array('doc.php.net', $channellist)) {
            $channellist[] = 'doc.php.net';
        }


        if (!in_array('__uri', $channellist)) {
            $channellist[] = '__uri';
        }

        natsort($channellist);
        return $channellist;
    }

    function _listPackages($channel = false)
    {
        if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') {
            return $this->_listChannelPackages($channel);
        }

        if (!file_exists($this->statedir) || !is_dir($this->statedir)) {
            return array();
        }

        $pkglist = array();
        $dp = opendir($this->statedir);
        if (!$dp) {
            return $pkglist;
        }

        while ($ent = readdir($dp)) {
            if ($ent[0] == '.' || substr($ent, -4) != '.reg') {
                continue;
            }

            $pkglist[] = substr($ent, 0, -4);
        }
        closedir($dp);
        sort($pkglist);
        return $pkglist;
    }

    function _listChannelPackages($channel)
    {
        $pkglist = array();
        if (!file_exists($this->_channelDirectoryName($channel)) ||
              !is_dir($this->_channelDirectoryName($channel))) {
            return array();
        }

        $dp = opendir($this->_channelDirectoryName($channel));
        if (!$dp) {
            return $pkglist;
        }

        while ($ent = readdir($dp)) {
            if ($ent[0] == '.' || substr($ent, -4) != '.reg') {
                continue;
            }
            $pkglist[] = substr($ent, 0, -4);
        }

        closedir($dp);
        return $pkglist;
    }

    function _listAllPackages()
    {
        $ret = array();
        foreach ($this->_listChannels() as $channel) {
            $ret[$channel] = $this->_listPackages($channel);
        }

        return $ret;
    }

    /**
     * Add an installed package to the registry
     * @param string package name
     * @param array package info (parsed by PEAR_Common::infoFrom*() methods)
     * @return bool success of saving
     * @access private
     */
    function _addPackage($package, $info)
    {
        if ($this->_packageExists($package)) {
            return false;
        }

        $fp = $this->_openPackageFile($package, 'wb');
        if ($fp === null) {
            return false;
        }

        $info['_lastmodified'] = self::getSourceDateEpoch();
        fwrite($fp, serialize($info));
        $this->_closePackageFile($fp);
        if (isset($info['filelist'])) {
            $this->_rebuildFileMap();
        }

        return true;
    }

    /**
     * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
     * @return bool
     * @access private
     */
    function _addPackage2($info)
    {
        if (!is_a($info, 'PEAR_PackageFile_v1') && !is_a($info, 'PEAR_PackageFile_v2')) {
            return false;
        }

        if (!$info->validate()) {
            if (class_exists('PEAR_Common')) {
                $ui = PEAR_Frontend::singleton();
                if ($ui) {
                    foreach ($info->getValidationWarnings() as $err) {
                        $ui->log($err['message'], true);
                    }
                }
            }
            return false;
        }

        $channel = $info->getChannel();
        $package = $info->getPackage();
        $save = $info;
        if ($this->_packageExists($package, $channel)) {
            return false;
        }

        if (!$this->_channelExists($channel, true)) {
            return false;
        }

        $info = $info->toArray(true);
        if (!$info) {
            return false;
        }

        $fp = $this->_openPackageFile($package, 'wb', $channel);
        if ($fp === null) {
            return false;
        }

        $info['_lastmodified'] = self::getSourceDateEpoch();
        fwrite($fp, serialize($info));
        $this->_closePackageFile($fp);
        $this->_rebuildFileMap();
        return true;
    }

    /**
     * @param string Package name
     * @param array parsed package.xml 1.0
     * @param bool this parameter is only here for BC.  Don't use it.
     * @access private
     */
    function _updatePackage($package, $info, $merge = true)
    {
        $oldinfo = $this->_packageInfo($package);
        if (empty($oldinfo)) {
            return false;
        }

        $fp = $this->_openPackageFile($package, 'w');
        if ($fp === null) {
            return false;
        }

        if (is_object($info)) {
            $info = $info->toArray();
        }
        $info['_lastmodified'] = self::getSourceDateEpoch();

        $newinfo = $info;
        if ($merge) {
            $info = array_merge($oldinfo, $info);
        } else {
            $diff = $info;
        }

        fwrite($fp, serialize($info));
        $this->_closePackageFile($fp);
        if (isset($newinfo['filelist'])) {
            $this->_rebuildFileMap();
        }

        return true;
    }

    /**
     * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
     * @return bool
     * @access private
     */
    function _updatePackage2($info)
    {
        if (!$this->_packageExists($info->getPackage(), $info->getChannel())) {
            return false;
        }

        $fp = $this->_openPackageFile($info->getPackage(), 'w', $info->getChannel());
        if ($fp === null) {
            return false;
        }

        $save = $info;
        $info = $save->getArray(true);
        $info['_lastmodified'] = self::getSourceDateEpoch();
        fwrite($fp, serialize($info));
        $this->_closePackageFile($fp);
        $this->_rebuildFileMap();
        return true;
    }

    /**
     * @param string Package name
     * @param string Channel name
     * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|null
     * @access private
     */
    function &_getPackage($package, $channel = 'pear.php.net')
    {
        $info = $this->_packageInfo($package, null, $channel);
        if ($info === null) {
            return $info;
        }

        $a = $this->_config;
        if (!$a) {
            $this->_config = new PEAR_Config;
            $this->_config->set('php_dir', $this->statedir);
        }

        if (!class_exists('PEAR_PackageFile')) {
            require_once 'PEAR/PackageFile.php';
        }

        $pkg = new PEAR_PackageFile($this->_config);
        $pf = &$pkg->fromArray($info);
        return $pf;
    }

    /**
     * @param string channel name
     * @param bool whether to strictly retrieve channel names
     * @return PEAR_ChannelFile|PEAR_Error
     * @access private
     */
    function &_getChannel($channel, $noaliases = false)
    {
        $ch = false;
        if ($this->_channelExists($channel, $noaliases)) {
            $chinfo = $this->_channelInfo($channel, $noaliases);
            if ($chinfo) {
                if (!class_exists('PEAR_ChannelFile')) {
                    require_once 'PEAR/ChannelFile.php';
                }

                $ch = &PEAR_ChannelFile::fromArrayWithErrors($chinfo);
            }
        }

        if ($ch) {
            if ($ch->validate()) {
                return $ch;
            }

            foreach ($ch->getErrors(true) as $err) {
                $message = $err['message'] . "\n";
            }

            $ch = PEAR::raiseError($message);
            return $ch;
        }

        if ($this->_getChannelFromAlias($channel) == 'pear.php.net') {
            // the registry is not properly set up, so use defaults
            if (!class_exists('PEAR_ChannelFile')) {
                require_once 'PEAR/ChannelFile.php';
            }

            $pear_channel = new PEAR_ChannelFile;
            $pear_channel->setServer('pear.php.net');
            $pear_channel->setAlias('pear');
            $pear_channel->setSummary('PHP Extension and Application Repository');
            $pear_channel->setDefaultPEARProtocols();
            $pear_channel->setBaseURL('REST1.0', 'http://pear.php.net/rest/');
            $pear_channel->setBaseURL('REST1.1', 'http://pear.php.net/rest/');
            $pear_channel->setBaseURL('REST1.3', 'http://pear.php.net/rest/');
            return $pear_channel;
        }

        if ($this->_getChannelFromAlias($channel) == 'pecl.php.net') {
            // the registry is not properly set up, so use defaults
            if (!class_exists('PEAR_ChannelFile')) {
                require_once 'PEAR/ChannelFile.php';
            }
            $pear_channel = new PEAR_ChannelFile;
            $pear_channel->setServer('pecl.php.net');
            $pear_channel->setAlias('pecl');
            $pear_channel->setSummary('PHP Extension Community Library');
            $pear_channel->setDefaultPEARProtocols();
            $pear_channel->setBaseURL('REST1.0', 'http://pecl.php.net/rest/');
            $pear_channel->setBaseURL('REST1.1', 'http://pecl.php.net/rest/');
            $pear_channel->setValidationPackage('PEAR_Validator_PECL', '1.0');
            return $pear_channel;
        }

        if ($this->_getChannelFromAlias($channel) == 'doc.php.net') {
            // the registry is not properly set up, so use defaults
            if (!class_exists('PEAR_ChannelFile')) {
                require_once 'PEAR/ChannelFile.php';
            }

            $doc_channel = new PEAR_ChannelFile;
            $doc_channel->setServer('doc.php.net');
            $doc_channel->setAlias('phpdocs');
            $doc_channel->setSummary('PHP Documentation Team');
            $doc_channel->setDefaultPEARProtocols();
            $doc_channel->setBaseURL('REST1.0', 'http://doc.php.net/rest/');
            $doc_channel->setBaseURL('REST1.1', 'http://doc.php.net/rest/');
            $doc_channel->setBaseURL('REST1.3', 'http://doc.php.net/rest/');
            return $doc_channel;
        }


        if ($this->_getChannelFromAlias($channel) == '__uri') {
            // the registry is not properly set up, so use defaults
            if (!class_exists('PEAR_ChannelFile')) {
                require_once 'PEAR/ChannelFile.php';
            }

            $private = new PEAR_ChannelFile;
            $private->setName('__uri');
            $private->setDefaultPEARProtocols();
            $private->setBaseURL('REST1.0', '****');
            $private->setSummary('Pseudo-channel for static packages');
            return $private;
        }

        return $ch;
    }

    /**
     * @param string Package name
     * @param string Channel name
     * @return bool
     */
    function packageExists($package, $channel = 'pear.php.net')
    {
        if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
            return $e;
        }
        $ret = $this->_packageExists($package, $channel);
        $this->_unlock();
        return $ret;
    }

    // }}}

    // {{{ channelExists()

    /**
     * @param string channel name
     * @param bool if true, then aliases will be ignored
     * @return bool
     */
    function channelExists($channel, $noaliases = false)
    {
        if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
            return $e;
        }
        $ret = $this->_channelExists($channel, $noaliases);
        $this->_unlock();
        return $ret;
    }

    // }}}

    /**
     * @param string channel name mirror is in
     * @param string mirror name
     *
     * @return bool
     */
    function mirrorExists($channel, $mirror)
    {
        if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
            return $e;
        }

        $ret = $this->_mirrorExists($channel, $mirror);
        $this->_unlock();
        return $ret;
    }

    // {{{ isAlias()

    /**
     * Determines whether the parameter is an alias of a channel
     * @param string
     * @return bool
     */
    function isAlias($alias)
    {
        if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
            return $e;
        }
        $ret = $this->_isChannelAlias($alias);
        $this->_unlock();
        return $ret;
    }

    // }}}
    // {{{ packageInfo()

    /**
     * @param string|null
     * @param string|null
     * @param string
     * @return array|null
     */
    function packageInfo($package = null, $key = null, $channel = 'pear.php.net')
    {
        if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
            return $e;
        }
        $ret = $this->_packageInfo($package, $key, $channel);
        $this->_unlock();
        return $ret;
    }

    // }}}
    // {{{ channelInfo()

    /**
     * Retrieve a raw array of channel data.
     *
     * Do not use this, instead use {@link getChannel()} for normal
     * operations.  Array structure is undefined in this method
     * @param string channel name
     * @param bool whether to strictly retrieve information only on non-aliases
     * @return array|null|PEAR_Error
     */
    function channelInfo($channel = null, $noaliases = false)
    {
        if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
            return $e;
        }
        $ret = $this->_channelInfo($channel, $noaliases);
        $this->_unlock();
        return $ret;
    }

    // }}}

    /**
     * @param string
     */
    function channelName($channel)
    {
        if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
            return $e;
        }
        $ret = $this->_getChannelFromAlias($channel);
        $this->_unlock();
        return $ret;
    }

    /**
     * @param string
     */
    function channelAlias($channel)
    {
        if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
            return $e;
        }
        $ret = $this->_getAlias($channel);
        $this->_unlock();
        return $ret;
    }
    // {{{ listPackages()

    function listPackages($channel = false)
    {
        if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
            return $e;
        }
        $ret = $this->_listPackages($channel);
        $this->_unlock();
        return $ret;
    }

    // }}}
    // {{{ listAllPackages()

    function listAllPackages()
    {
        if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
            return $e;
        }
        $ret = $this->_listAllPackages();
        $this->_unlock();
        return $ret;
    }

    // }}}
    // {{{ listChannel()

    function listChannels()
    {
        if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
            return $e;
        }
        $ret = $this->_listChannels();
        $this->_unlock();
        return $ret;
    }

    // }}}
    // {{{ addPackage()

    /**
     * Add an installed package to the registry
     * @param string|PEAR_PackageFile_v1|PEAR_PackageFile_v2 package name or object
     *               that will be passed to {@link addPackage2()}
     * @param array package info (parsed by PEAR_Common::infoFrom*() methods)
     * @return bool success of saving
     */
    function addPackage($package, $info)
    {
        if (is_object($info)) {
            return $this->addPackage2($info);
        }
        if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
            return $e;
        }
        $ret = $this->_addPackage($package, $info);
        $this->_unlock();
        if ($ret) {
            if (!class_exists('PEAR_PackageFile_v1')) {
                require_once 'PEAR/PackageFile/v1.php';
            }
            $pf = new PEAR_PackageFile_v1;
            $pf->setConfig($this->_config);
            $pf->fromArray($info);
            $this->_dependencyDB->uninstallPackage($pf);
            $this->_dependencyDB->installPackage($pf);
        }
        return $ret;
    }

    // }}}
    // {{{ addPackage2()

    function addPackage2($info)
    {
        if (!is_object($info)) {
            return $this->addPackage($info['package'], $info);
        }
        if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
            return $e;
        }
        $ret = $this->_addPackage2($info);
        $this->_unlock();
        if ($ret) {
            $this->_dependencyDB->uninstallPackage($info);
            $this->_dependencyDB->installPackage($info);
        }
        return $ret;
    }

    // }}}
    // {{{ updateChannel()

    /**
     * For future expandibility purposes, separate this
     * @param PEAR_ChannelFile
     */
    function updateChannel($channel, $lastmodified = null)
    {
        if ($channel->getName() == '__uri') {
            return false;
        }
        return $this->addChannel($channel, $lastmodified, true);
    }

    // }}}
    // {{{ deleteChannel()

    /**
     * Deletion fails if there are any packages installed from the channel
     * @param string|PEAR_ChannelFile channel name
     * @return boolean|PEAR_Error True on deletion, false if it doesn't exist
     */
    function deleteChannel($channel)
    {
        if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
            return $e;
        }

        $ret = $this->_deleteChannel($channel);
        $this->_unlock();
        if ($ret && is_a($this->_config, 'PEAR_Config')) {
            $this->_config->setChannels($this->listChannels());
        }

        return $ret;
    }

    // }}}
    // {{{ addChannel()

    /**
     * @param PEAR_ChannelFile Channel object
     * @param string Last-Modified header from HTTP for caching
     * @return boolean|PEAR_Error True on creation, false if it already exists
     */
    function addChannel($channel, $lastmodified = false, $update = false)
    {
        if (!is_a($channel, 'PEAR_ChannelFile') || !$channel->validate()) {
            return false;
        }

        if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
            return $e;
        }

        $ret = $this->_addChannel($channel, $update, $lastmodified);
        $this->_unlock();
        if (!$update && $ret && is_a($this->_config, 'PEAR_Config')) {
            $this->_config->setChannels($this->listChannels());
        }

        return $ret;
    }

    // }}}
    // {{{ deletePackage()

    function deletePackage($package, $channel = 'pear.php.net')
    {
        if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
            return $e;
        }

        $file = $this->_packageFileName($package, $channel);
        $ret  = file_exists($file) ? @unlink($file) : false;
        $this->_rebuildFileMap();
        $this->_unlock();
        $p = array('channel' => $channel, 'package' => $package);
        $this->_dependencyDB->uninstallPackage($p);
        return $ret;
    }

    // }}}
    // {{{ updatePackage()

    function updatePackage($package, $info, $merge = true)
    {
        if (is_object($info)) {
            return $this->updatePackage2($info, $merge);
        }
        if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
            return $e;
        }
        $ret = $this->_updatePackage($package, $info, $merge);
        $this->_unlock();
        if ($ret) {
            if (!class_exists('PEAR_PackageFile_v1')) {
                require_once 'PEAR/PackageFile/v1.php';
            }
            $pf = new PEAR_PackageFile_v1;
            $pf->setConfig($this->_config);
            $pf->fromArray($this->packageInfo($package));
            $this->_dependencyDB->uninstallPackage($pf);
            $this->_dependencyDB->installPackage($pf);
        }
        return $ret;
    }

    // }}}
    // {{{ updatePackage2()

    function updatePackage2($info)
    {

        if (!is_object($info)) {
            return $this->updatePackage($info['package'], $info, $merge);
        }

        if (!$info->validate(PEAR_VALIDATE_DOWNLOADING)) {
            return false;
        }

        if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
            return $e;
        }

        $ret = $this->_updatePackage2($info);
        $this->_unlock();
        if ($ret) {
            $this->_dependencyDB->uninstallPackage($info);
            $this->_dependencyDB->installPackage($info);
        }

        return $ret;
    }

    // }}}
    // {{{ getChannel()
    /**
     * @param string channel name
     * @param bool whether to strictly return raw channels (no aliases)
     * @return PEAR_ChannelFile|PEAR_Error
     */
    function getChannel($channel, $noaliases = false)
    {
        if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
            return $e;
        }
        $ret = $this->_getChannel($channel, $noaliases);
        $this->_unlock();
        if (!$ret) {
            return PEAR::raiseError('Unknown channel: ' . $channel);
        }
        return $ret;
    }

    // }}}
    // {{{ getPackage()
    /**
     * @param string package name
     * @param string channel name
     * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|null
     */
    function &getPackage($package, $channel = 'pear.php.net')
    {
        if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
            return $e;
        }
        $pf = &$this->_getPackage($package, $channel);
        $this->_unlock();
        return $pf;
    }

    // }}}

    /**
     * Get PEAR_PackageFile_v[1/2] objects representing the contents of
     * a dependency group that are installed.
     *
     * This is used at uninstall-time
     * @param array
     * @return array|false
     */
    function getInstalledGroup($group)
    {
        $ret = array();
        if (isset($group['package'])) {
            if (!isset($group['package'][0])) {
                $group['package'] = array($group['package']);
            }
            foreach ($group['package'] as $package) {
                $depchannel = isset($package['channel']) ? $package['channel'] : '__uri';
                $p = &$this->getPackage($package['name'], $depchannel);
                if ($p) {
                    $save = &$p;
                    $ret[] = &$save;
                }
            }
        }
        if (isset($group['subpackage'])) {
            if (!isset($group['subpackage'][0])) {
                $group['subpackage'] = array($group['subpackage']);
            }
            foreach ($group['subpackage'] as $package) {
                $depchannel = isset($package['channel']) ? $package['channel'] : '__uri';
                $p = &$this->getPackage($package['name'], $depchannel);
                if ($p) {
                    $save = &$p;
                    $ret[] = &$save;
                }
            }
        }
        if (!count($ret)) {
            return false;
        }
        return $ret;
    }

    // {{{ getChannelValidator()
    /**
     * @param string channel name
     * @return PEAR_Validate|false
     */
    function &getChannelValidator($channel)
    {
        $chan = $this->getChannel($channel);
        if (PEAR::isError($chan)) {
            return $chan;
        }
        $val = $chan->getValidationObject();
        return $val;
    }
    // }}}
    // {{{ getChannels()
    /**
     * @param string channel name
     * @return array an array of PEAR_ChannelFile objects representing every installed channel
     */
    function &getChannels()
    {
        $ret = array();
        if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
            return $e;
        }
        foreach ($this->_listChannels() as $channel) {
            $e = &$this->_getChannel($channel);
            if (!$e || PEAR::isError($e)) {
                continue;
            }
            $ret[] = $e;
        }
        $this->_unlock();
        return $ret;
    }

    // }}}
    // {{{ checkFileMap()

    /**
     * Test whether a file or set of files belongs to a package.
     *
     * If an array is passed in
     * @param string|array file path, absolute or relative to the pear
     *                     install dir
     * @param string|array name of PEAR package or array('package' => name, 'channel' =>
     *                     channel) of a package that will be ignored
     * @param string API version - 1.1 will exclude any files belonging to a package
     * @param array private recursion variable
     * @return array|false which package and channel the file belongs to, or an empty
     *                     string if the file does not belong to an installed package,
     *                     or belongs to the second parameter's package
     */
    function checkFileMap($path, $package = false, $api = '1.0', $attrs = false)
    {
        if (is_array($path)) {
            static $notempty;
            if (empty($notempty)) {
                if (!class_exists('PEAR_Installer_Role')) {
                    require_once 'PEAR/Installer/Role.php';
                }
                $notempty = function($a) { return !empty($a); };
            }
            $package = is_array($package) ? array(strtolower($package[0]), strtolower($package[1]))
                : strtolower($package);
            $pkgs = array();
            foreach ($path as $name => $attrs) {
                if (is_array($attrs)) {
                    if (isset($attrs['install-as'])) {
                        $name = $attrs['install-as'];
                    }
                    if (!in_array($attrs['role'], PEAR_Installer_Role::getInstallableRoles())) {
                        // these are not installed
                        continue;
                    }
                    if (!in_array($attrs['role'], PEAR_Installer_Role::getBaseinstallRoles())) {
                        $attrs['baseinstalldir'] = is_array($package) ? $package[1] : $package;
                    }
                    if (isset($attrs['baseinstalldir'])) {
                        $name = $attrs['baseinstalldir'] . DIRECTORY_SEPARATOR . $name;
                    }
                }
                $pkgs[$name] = $this->checkFileMap($name, $package, $api, $attrs);
                if (PEAR::isError($pkgs[$name])) {
                    return $pkgs[$name];
                }
            }
            return array_filter($pkgs, $notempty);
        }
        if (empty($this->filemap_cache)) {
            if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                return $e;
            }
            $err = $this->_readFileMap();
            $this->_unlock();
            if (PEAR::isError($err)) {
                return $err;
            }
        }
        if (!$attrs) {
            $attrs = array('role' => 'php'); // any old call would be for PHP role only
        }
        if (isset($this->filemap_cache[$attrs['role']][$path])) {
            if ($api >= '1.1' && $this->filemap_cache[$attrs['role']][$path] == $package) {
                return false;
            }
            return $this->filemap_cache[$attrs['role']][$path];
        }
        $l = strlen($this->install_dir);
        if (substr($path, 0, $l) == $this->install_dir) {
            $path = preg_replace('!^'.DIRECTORY_SEPARATOR.'+!', '', substr($path, $l));
        }
        if (isset($this->filemap_cache[$attrs['role']][$path])) {
            if ($api >= '1.1' && $this->filemap_cache[$attrs['role']][$path] == $package) {
                return false;
            }
            return $this->filemap_cache[$attrs['role']][$path];
        }
        return false;
    }

    // }}}
    // {{{ flush()
    /**
     * Force a reload of the filemap
     * @since 1.5.0RC3
     */
    function flushFileMap()
    {
        $this->filemap_cache = null;
        clearstatcache(); // ensure that the next read gets the full, current filemap
    }

    // }}}
    // {{{ apiVersion()
    /**
     * Get the expected API version.  Channels API is version 1.1, as it is backwards
     * compatible with 1.0
     * @return string
     */
    function apiVersion()
    {
        return '1.1';
    }
    // }}}


    /**
     * Parse a package name, or validate a parsed package name array
     * @param string|array pass in an array of format
     *                     array(
     *                      'package' => 'pname',
     *                     ['channel' => 'channame',]
     *                     ['version' => 'version',]
     *                     ['state' => 'state',]
     *                     ['group' => 'groupname'])
     *                     or a string of format
     *                     [channel://][channame/]pname[-version|-state][/group=groupname]
     * @return array|PEAR_Error
     */
    function parsePackageName($param, $defaultchannel = 'pear.php.net')
    {
        $saveparam = $param;
        if (is_array($param)) {
            // convert to string for error messages
            $saveparam = $this->parsedPackageNameToString($param);
            // process the array
            if (!isset($param['package'])) {
                return PEAR::raiseError('parsePackageName(): array $param ' .
                    'must contain a valid package name in index "param"',
                    'package', null, null, $param);
            }
            if (!isset($param['uri'])) {
                if (!isset($param['channel'])) {
                    $param['channel'] = $defaultchannel;
                }
            } else {
                $param['channel'] = '__uri';
            }
        } else {
            $components = @parse_url((string) $param);
            if (isset($components['scheme'])) {
                if ($components['scheme'] == 'http') {
                    // uri package
                    $param = array('uri' => $param, 'channel' => '__uri');
                } elseif($components['scheme'] != 'channel') {
                    return PEAR::raiseError('parsePackageName(): only channel:// uris may ' .
                        'be downloaded, not "' . $param . '"', 'invalid', null, null, $param);
                }
            }
            if (!isset($components['path'])) {
                return PEAR::raiseError('parsePackageName(): array $param ' .
                    'must contain a valid package name in "' . $param . '"',
                    'package', null, null, $param);
            }
            if (isset($components['host'])) {
                // remove the leading "/"
                $components['path'] = substr($components['path'], 1);
            }
            if (!isset($components['scheme'])) {
                if (strpos($components['path'], '/') !== false) {
                    if ($components['path'][0] == '/') {
                        return PEAR::raiseError('parsePackageName(): this is not ' .
                            'a package name, it begins with "/" in "' . $param . '"',
                            'invalid', null, null, $param);
                    }
                    $parts = explode('/', $components['path']);
                    $components['host'] = array_shift($parts);
                    if (count($parts) > 1) {
                        $components['path'] = array_pop($parts);
                        $components['host'] .= '/' . implode('/', $parts);
                    } else {
                        $components['path'] = implode('/', $parts);
                    }
                } else {
                    $components['host'] = $defaultchannel;
                }
            } else {
                if (strpos($components['path'], '/')) {
                    $parts = explode('/', $components['path']);
                    $components['path'] = array_pop($parts);
                    $components['host'] .= '/' . implode('/', $parts);
                }
            }

            if (is_array($param)) {
                $param['package'] = $components['path'];
            } else {
                $param = array(
                    'package' => $components['path']
                    );
                if (isset($components['host'])) {
                    $param['channel'] = $components['host'];
                }
            }
            if (isset($components['fragment'])) {
                $param['group'] = $components['fragment'];
            }
            if (isset($components['user'])) {
                $param['user'] = $components['user'];
            }
            if (isset($components['pass'])) {
                $param['pass'] = $components['pass'];
            }
            if (isset($components['query'])) {
                parse_str($components['query'], $param['opts']);
            }
            // check for extension
            $pathinfo = pathinfo($param['package']);
            if (isset($pathinfo['extension']) &&
                  in_array(strtolower($pathinfo['extension']), array('tgz', 'tar'))) {
                $param['extension'] = $pathinfo['extension'];
                $param['package'] = substr($pathinfo['basename'], 0,
                    strlen($pathinfo['basename']) - 4);
            }
            // check for version
            if (strpos($param['package'], '-')) {
                $test = explode('-', $param['package']);
                if (count($test) != 2) {
                    return PEAR::raiseError('parsePackageName(): only one version/state ' .
                        'delimiter "-" is allowed in "' . $saveparam . '"',
                        'version', null, null, $param);
                }
                list($param['package'], $param['version']) = $test;
            }
        }
        // validation
        $info = $this->channelExists($param['channel']);
        if (PEAR::isError($info)) {
            return $info;
        }
        if (!$info) {
            return PEAR::raiseError('unknown channel "' . $param['channel'] .
                '" in "' . $saveparam . '"', 'channel', null, null, $param);
        }
        $chan = $this->getChannel($param['channel']);
        if (PEAR::isError($chan)) {
            return $chan;
        }
        if (!$chan) {
            return PEAR::raiseError("Exception: corrupt registry, could not " .
                "retrieve channel " . $param['channel'] . " information",
                'registry', null, null, $param);
        }
        $param['channel'] = $chan->getName();
        $validate = $chan->getValidationObject();
        $vpackage = $chan->getValidationPackage();
        // validate package name
        if (!$validate->validPackageName($param['package'], $vpackage['_content'])) {
            return PEAR::raiseError('parsePackageName(): invalid package name "' .
                $param['package'] . '" in "' . $saveparam . '"',
                'package', null, null, $param);
        }
        if (isset($param['group'])) {
            if (!PEAR_Validate::validGroupName($param['group'])) {
                return PEAR::raiseError('parsePackageName(): dependency group "' . $param['group'] .
                    '" is not a valid group name in "' . $saveparam . '"', 'group', null, null,
                    $param);
            }
        }
        if (isset($param['state'])) {
            if (!in_array(strtolower($param['state']), $validate->getValidStates())) {
                return PEAR::raiseError('parsePackageName(): state "' . $param['state']
                    . '" is not a valid state in "' . $saveparam . '"',
                    'state', null, null, $param);
            }
        }
        if (isset($param['version'])) {
            if (isset($param['state'])) {
                return PEAR::raiseError('parsePackageName(): cannot contain both ' .
                    'a version and a stability (state) in "' . $saveparam . '"',
                    'version/state', null, null, $param);
            }
            // check whether version is actually a state
            if (in_array(strtolower($param['version']), $validate->getValidStates())) {
                $param['state'] = strtolower($param['version']);
                unset($param['version']);
            } else {
                if (!$validate->validVersion($param['version'])) {
                    return PEAR::raiseError('parsePackageName(): "' . $param['version'] .
                        '" is neither a valid version nor a valid state in "' .
                        $saveparam . '"', 'version/state', null, null, $param);
                }
            }
        }
        return $param;
    }

    /**
     * @param array
     * @return string
     */
    function parsedPackageNameToString($parsed, $brief = false)
    {
        if (is_string($parsed)) {
            return $parsed;
        }
        if (is_object($parsed)) {
            $p = $parsed;
            $parsed = array(
                'package' => $p->getPackage(),
                'channel' => $p->getChannel(),
                'version' => $p->getVersion(),
            );
        }
        if (isset($parsed['uri'])) {
            return $parsed['uri'];
        }
        if ($brief) {
            if ($channel = $this->channelAlias($parsed['channel'])) {
                return $channel . '/' . $parsed['package'];
            }
        }
        $upass = '';
        if (isset($parsed['user'])) {
            $upass = $parsed['user'];
            if (isset($parsed['pass'])) {
                $upass .= ':' . $parsed['pass'];
            }
            $upass = "$upass@";
        }
        $ret = 'channel://' . $upass . $parsed['channel'] . '/' . $parsed['package'];
        if (isset($parsed['version']) || isset($parsed['state'])) {
            $ver = isset($parsed['version']) ? $parsed['version'] : '';
            $ver .= isset($parsed['state']) ? $parsed['state'] : '';
            $ret .= '-' . $ver;
        }
        if (isset($parsed['extension'])) {
            $ret .= '.' . $parsed['extension'];
        }
        if (isset($parsed['opts'])) {
            $ret .= '?';
            foreach ($parsed['opts'] as $name => $value) {
                $parsed['opts'][$name] = "$name=$value";
            }
            $ret .= implode('&', $parsed['opts']);
        }
        if (isset($parsed['group'])) {
            $ret .= '#' . $parsed['group'];
        }
        return $ret;
    }
}
PKr�Z��	MdMdPEAR/Frontend/CLI.phpnu�[���<?php
/**
 * PEAR_Frontend_CLI
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 0.1
 */
/**
 * base class
 */
require_once 'PEAR/Frontend.php';

/**
 * Command-line Frontend for the PEAR Installer
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 0.1
 */
class PEAR_Frontend_CLI extends PEAR_Frontend
{
    /**
     * What type of user interface this frontend is for.
     * @var string
     * @access public
     */
    var $type = 'CLI';
    var $lp = ''; // line prefix

    var $params = array();
    var $term = array(
        'bold'   => '',
        'normal' => '',
    );

    function __construct()
    {
        parent::__construct();
        $term = getenv('TERM'); //(cox) $_ENV is empty for me in 4.1.1
        if (function_exists('posix_isatty') && !posix_isatty(1)) {
            // output is being redirected to a file or through a pipe
        } elseif ($term) {
            if (preg_match('/^(xterm|vt220|linux)/', $term)) {
                $this->term['bold']   = sprintf("%c%c%c%c", 27, 91, 49, 109);
                $this->term['normal'] = sprintf("%c%c%c", 27, 91, 109);
            } elseif (preg_match('/^vt100/', $term)) {
                $this->term['bold']   = sprintf("%c%c%c%c%c%c", 27, 91, 49, 109, 0, 0);
                $this->term['normal'] = sprintf("%c%c%c%c%c", 27, 91, 109, 0, 0);
            }
        } elseif (OS_WINDOWS) {
            // XXX add ANSI codes here
        }
    }

    /**
     * @param object PEAR_Error object
     */
    function displayError($e)
    {
        return $this->_displayLine($e->getMessage());
    }

    /**
     * @param object PEAR_Error object
     */
    function displayFatalError($eobj)
    {
        $this->displayError($eobj);
        if (class_exists('PEAR_Config')) {
            $config = &PEAR_Config::singleton();
            if ($config->get('verbose') > 5) {
                if (function_exists('debug_print_backtrace')) {
                    debug_print_backtrace();
                    exit(1);
                }

                $raised = false;
                foreach (debug_backtrace() as $i => $frame) {
                    if (!$raised) {
                        if (isset($frame['class'])
                            && strtolower($frame['class']) == 'pear'
                            && strtolower($frame['function']) == 'raiseerror'
                        ) {
                            $raised = true;
                        } else {
                            continue;
                        }
                    }

                    $frame['class']    = !isset($frame['class'])    ? '' : $frame['class'];
                    $frame['type']     = !isset($frame['type'])     ? '' : $frame['type'];
                    $frame['function'] = !isset($frame['function']) ? '' : $frame['function'];
                    $frame['line']     = !isset($frame['line'])     ? '' : $frame['line'];
                    $this->_displayLine("#$i: $frame[class]$frame[type]$frame[function] $frame[line]");
                }
            }
        }

        exit(1);
    }

    /**
     * Instruct the runInstallScript method to skip a paramgroup that matches the
     * id value passed in.
     *
     * This method is useful for dynamically configuring which sections of a post-install script
     * will be run based on the user's setup, which is very useful for making flexible
     * post-install scripts without losing the cross-Frontend ability to retrieve user input
     * @param string
     */
    function skipParamgroup($id)
    {
        $this->_skipSections[$id] = true;
    }

    function runPostinstallScripts(&$scripts)
    {
        foreach ($scripts as $i => $script) {
            $this->runInstallScript($scripts[$i]->_params, $scripts[$i]->_obj);
        }
    }

    /**
     * @param array $xml contents of postinstallscript tag
     * @param object $script post-installation script
     * @param string install|upgrade
     */
    function runInstallScript($xml, &$script)
    {
        $this->_skipSections = array();
        if (!is_array($xml) || !isset($xml['paramgroup'])) {
            $script->run(array(), '_default');
            return;
        }

        $completedPhases = array();
        if (!isset($xml['paramgroup'][0])) {
            $xml['paramgroup'] = array($xml['paramgroup']);
        }

        foreach ($xml['paramgroup'] as $group) {
            if (isset($this->_skipSections[$group['id']])) {
                // the post-install script chose to skip this section dynamically
                continue;
            }

            if (isset($group['name'])) {
                $paramname = explode('::', $group['name']);
                if ($lastgroup['id'] != $paramname[0]) {
                    continue;
                }

                $group['name'] = $paramname[1];
                if (!isset($answers)) {
                    return;
                }

                if (isset($answers[$group['name']])) {
                    switch ($group['conditiontype']) {
                        case '=' :
                            if ($answers[$group['name']] != $group['value']) {
                                continue 2;
                            }
                        break;
                        case '!=' :
                            if ($answers[$group['name']] == $group['value']) {
                                continue 2;
                            }
                        break;
                        case 'preg_match' :
                            if (!@preg_match('/' . $group['value'] . '/',
                                  $answers[$group['name']])) {
                                continue 2;
                            }
                        break;
                        default :
                        return;
                    }
                }
            }

            $lastgroup = $group;
            if (isset($group['instructions'])) {
                $this->_display($group['instructions']);
            }

            if (!isset($group['param'][0])) {
                $group['param'] = array($group['param']);
            }

            if (isset($group['param'])) {
                if (method_exists($script, 'postProcessPrompts')) {
                    $prompts = $script->postProcessPrompts($group['param'], $group['id']);
                    if (!is_array($prompts) || count($prompts) != count($group['param'])) {
                        $this->outputData('postinstall', 'Error: post-install script did not ' .
                            'return proper post-processed prompts');
                        $prompts = $group['param'];
                    } else {
                        foreach ($prompts as $i => $var) {
                            if (!is_array($var) || !isset($var['prompt']) ||
                                  !isset($var['name']) ||
                                  ($var['name'] != $group['param'][$i]['name']) ||
                                  ($var['type'] != $group['param'][$i]['type'])
                            ) {
                                $this->outputData('postinstall', 'Error: post-install script ' .
                                    'modified the variables or prompts, severe security risk. ' .
                                    'Will instead use the defaults from the package.xml');
                                $prompts = $group['param'];
                            }
                        }
                    }

                    $answers = $this->confirmDialog($prompts);
                } else {
                    $answers = $this->confirmDialog($group['param']);
                }
            }

            if ((isset($answers) && $answers) || !isset($group['param'])) {
                if (!isset($answers)) {
                    $answers = array();
                }

                array_unshift($completedPhases, $group['id']);
                if (!$script->run($answers, $group['id'])) {
                    $script->run($completedPhases, '_undoOnError');
                    return;
                }
            } else {
                $script->run($completedPhases, '_undoOnError');
                return;
            }
        }
    }

    /**
     * Ask for user input, confirm the answers and continue until the user is satisfied
     * @param array an array of arrays, format array('name' => 'paramname', 'prompt' =>
     *              'text to display', 'type' => 'string'[, default => 'default value'])
     * @return array
     */
    function confirmDialog($params)
    {
        $answers = $prompts = $types = array();
        foreach ($params as $param) {
            $prompts[$param['name']] = $param['prompt'];
            $types[$param['name']]   = $param['type'];
            $answers[$param['name']] = isset($param['default']) ? $param['default'] : '';
        }

        $tried = false;
        do {
            if ($tried) {
                $i = 1;
                foreach ($answers as $var => $value) {
                    if (!strlen($value)) {
                        echo $this->bold("* Enter an answer for #" . $i . ": ({$prompts[$var]})\n");
                    }
                    $i++;
                }
            }

            $answers = $this->userDialog('', $prompts, $types, $answers);
            $tried   = true;
        } while (is_array($answers) && count(array_filter($answers)) != count($prompts));

        return $answers;
    }

    function userDialog($command, $prompts, $types = array(), $defaults = array(), $screensize = 20)
    {
        if (!is_array($prompts)) {
            return array();
        }

        $testprompts = array_keys($prompts);
        $result      = $defaults;

        reset($prompts);
        if (count($prompts) === 1) {
            foreach ($prompts as $key => $prompt) {
                $type    = $types[$key];
                $default = @$defaults[$key];
                print "$prompt ";
                if ($default) {
                    print "[$default] ";
                }
                print ": ";

                $line         = fgets(STDIN, 2048);
                $result[$key] =  ($default && trim($line) == '') ? $default : trim($line);
            }

            return $result;
        }

        $first_run = true;
        while (true) {
            $descLength = max(array_map('strlen', $prompts));
            $descFormat = "%-{$descLength}s";
            $last       = count($prompts);

            $i = 0;
            foreach ($prompts as $n => $var) {
                $res = isset($result[$n]) ? $result[$n] : null;
                printf("%2d. $descFormat : %s\n", ++$i, $prompts[$n], $res);
            }
            print "\n1-$last, 'all', 'abort', or Enter to continue: ";

            $tmp = trim(fgets(STDIN, 1024));
            if (empty($tmp)) {
                break;
            }

            if ($tmp == 'abort') {
                return false;
            }

            if (isset($testprompts[(int)$tmp - 1])) {
                $var     = $testprompts[(int)$tmp - 1];
                $desc    = $prompts[$var];
                $current = @$result[$var];
                print "$desc [$current] : ";
                $tmp = trim(fgets(STDIN, 1024));
                if ($tmp !== '') {
                    $result[$var] = $tmp;
                }
            } elseif ($tmp == 'all') {
                foreach ($prompts as $var => $desc) {
                    $current = $result[$var];
                    print "$desc [$current] : ";
                    $tmp = trim(fgets(STDIN, 1024));
                    if (trim($tmp) !== '') {
                        $result[$var] = trim($tmp);
                    }
                }
            }

            $first_run = false;
        }

        return $result;
    }

    function userConfirm($prompt, $default = 'yes')
    {
        trigger_error("PEAR_Frontend_CLI::userConfirm not yet converted", E_USER_ERROR);
        static $positives = array('y', 'yes', 'on', '1');
        static $negatives = array('n', 'no', 'off', '0');
        print "$this->lp$prompt [$default] : ";
        $fp = fopen("php://stdin", "r");
        $line = fgets($fp, 2048);
        fclose($fp);
        $answer = strtolower(trim($line));
        if (empty($answer)) {
            $answer = $default;
        }
        if (in_array($answer, $positives)) {
            return true;
        }
        if (in_array($answer, $negatives)) {
            return false;
        }
        if (in_array($default, $positives)) {
            return true;
        }
        return false;
    }

    function outputData($data, $command = '_default')
    {
        switch ($command) {
            case 'channel-info':
                foreach ($data as $type => $section) {
                    if ($type == 'main') {
                        $section['data'] = array_values($section['data']);
                    }

                    $this->outputData($section);
                }
                break;
            case 'install':
            case 'upgrade':
            case 'upgrade-all':
                if (is_array($data) && isset($data['release_warnings'])) {
                    $this->_displayLine('');
                    $this->_startTable(array(
                        'border' => false,
                        'caption' => 'Release Warnings'
                    ));
                    $this->_tableRow(array($data['release_warnings']), null, array(1 => array('wrap' => 55)));
                    $this->_endTable();
                    $this->_displayLine('');
                }

                $this->_displayLine(is_array($data) ? $data['data'] : $data);
                break;
            case 'search':
                $this->_startTable($data);
                if (isset($data['headline']) && is_array($data['headline'])) {
                    $this->_tableRow($data['headline'], array('bold' => true), array(1 => array('wrap' => 55)));
                }

                $packages = array();
                foreach($data['data'] as $category) {
                    foreach($category as $name => $pkg) {
                        $packages[$pkg[0]] = $pkg;
                    }
                }

                $p = array_keys($packages);
                natcasesort($p);
                foreach ($p as $name) {
                    $this->_tableRow($packages[$name], null, array(1 => array('wrap' => 55)));
                }

                $this->_endTable();
                break;
            case 'list-all':
                if (!isset($data['data'])) {
                      $this->_displayLine('No packages in channel');
                      break;
                }

                $this->_startTable($data);
                if (isset($data['headline']) && is_array($data['headline'])) {
                    $this->_tableRow($data['headline'], array('bold' => true), array(1 => array('wrap' => 55)));
                }

                $packages = array();
                foreach($data['data'] as $category) {
                    foreach($category as $name => $pkg) {
                        $packages[$pkg[0]] = $pkg;
                    }
                }

                $p = array_keys($packages);
                natcasesort($p);
                foreach ($p as $name) {
                    $pkg = $packages[$name];
                    unset($pkg[4], $pkg[5]);
                    $this->_tableRow($pkg, null, array(1 => array('wrap' => 55)));
                }

                $this->_endTable();
                break;
            case 'config-show':
                $data['border'] = false;
                $opts = array(
                    0 => array('wrap' => 30),
                    1 => array('wrap' => 20),
                    2 => array('wrap' => 35)
                );

                $this->_startTable($data);
                if (isset($data['headline']) && is_array($data['headline'])) {
                    $this->_tableRow($data['headline'], array('bold' => true), $opts);
                }

                foreach ($data['data'] as $group) {
                    foreach ($group as $value) {
                        if ($value[2] == '') {
                            $value[2] = "<not set>";
                        }

                        $this->_tableRow($value, null, $opts);
                    }
                }

                $this->_endTable();
                break;
            case 'remote-info':
                $d = $data;
                $data = array(
                    'caption' => 'Package details:',
                    'border'  => false,
                    'data'    => array(
                        array("Latest",      $data['stable']),
                        array("Installed",   $data['installed']),
                        array("Package",     $data['name']),
                        array("License",     $data['license']),
                        array("Category",    $data['category']),
                        array("Summary",     $data['summary']),
                        array("Description", $data['description']),
                    ),
                );

                if (isset($d['deprecated']) && $d['deprecated']) {
                    $conf = &PEAR_Config::singleton();
                    $reg = $conf->getRegistry();
                    $name = $reg->parsedPackageNameToString($d['deprecated'], true);
                    $data['data'][] = array('Deprecated! use', $name);
                }
            default: {
                if (is_array($data)) {
                    $this->_startTable($data);
                    $count = count($data['data'][0]);
                    if ($count == 2) {
                        $opts = array(0 => array('wrap' => 25),
                                      1 => array('wrap' => 48)
                        );
                    } elseif ($count == 3) {
                        $opts = array(0 => array('wrap' => 30),
                                      1 => array('wrap' => 20),
                                      2 => array('wrap' => 35)
                        );
                    } else {
                        $opts = null;
                    }
                    if (isset($data['headline']) && is_array($data['headline'])) {
                        $this->_tableRow($data['headline'],
                                         array('bold' => true),
                                         $opts);
                    }

                    if (is_array($data['data'])) {
                        foreach($data['data'] as $row) {
                            $this->_tableRow($row, null, $opts);
                        }
                    } else {
                        $this->_tableRow(array($data['data']), null, $opts);
                     }
                    $this->_endTable();
                } else {
                    $this->_displayLine($data);
                }
            }
        }
    }

    function log($text, $append_crlf = true)
    {
        if ($append_crlf) {
            return $this->_displayLine($text);
        }

        return $this->_display($text);
    }

    function bold($text)
    {
        if (empty($this->term['bold'])) {
            return strtoupper($text);
        }

        return $this->term['bold'] . $text . $this->term['normal'];
    }

    function _displayHeading($title)
    {
        print $this->lp.$this->bold($title)."\n";
        print $this->lp.str_repeat("=", strlen($title))."\n";
    }

    function _startTable($params = array())
    {
        $params['table_data'] = array();
        $params['widest']     = array();  // indexed by column
        $params['highest']    = array(); // indexed by row
        $params['ncols']      = 0;
        $this->params         = $params;
    }

    function _tableRow($columns, $rowparams = array(), $colparams = array())
    {
        $highest = 1;
        for ($i = 0; $i < count($columns); $i++) {
            $col = &$columns[$i];
            if (isset($colparams[$i]) && !empty($colparams[$i]['wrap'])) {
                $col = wordwrap($col, $colparams[$i]['wrap']);
            }

            if (strpos($col, "\n") !== false) {
                $multiline = explode("\n", $col);
                $w = 0;
                foreach ($multiline as $n => $line) {
                    $len = strlen($line);
                    if ($len > $w) {
                        $w = $len;
                    }
                }
                $lines = count($multiline);
            } else {
                $w = strlen($col);
            }

            if (isset($this->params['widest'][$i])) {
                if ($w > $this->params['widest'][$i]) {
                    $this->params['widest'][$i] = $w;
                }
            } else {
                $this->params['widest'][$i] = $w;
            }

            $tmp = count_chars($columns[$i], 1);
            // handle unix, mac and windows formats
            $lines = (isset($tmp[10]) ? $tmp[10] : (isset($tmp[13]) ? $tmp[13] : 0)) + 1;
            if ($lines > $highest) {
                $highest = $lines;
            }
        }

        if (count($columns) > $this->params['ncols']) {
            $this->params['ncols'] = count($columns);
        }

        $new_row = array(
            'data'      => $columns,
            'height'    => $highest,
            'rowparams' => $rowparams,
            'colparams' => $colparams,
        );
        $this->params['table_data'][] = $new_row;
    }

    function _endTable()
    {
        extract($this->params);
        if (!empty($caption)) {
            $this->_displayHeading($caption);
        }

        if (count($table_data) === 0) {
            return;
        }

        if (!isset($width)) {
            $width = $widest;
        } else {
            for ($i = 0; $i < $ncols; $i++) {
                if (!isset($width[$i])) {
                    $width[$i] = $widest[$i];
                }
            }
        }

        $border = false;
        if (empty($border)) {
            $cellstart  = '';
            $cellend    = ' ';
            $rowend     = '';
            $padrowend  = false;
            $borderline = '';
        } else {
            $cellstart  = '| ';
            $cellend    = ' ';
            $rowend     = '|';
            $padrowend  = true;
            $borderline = '+';
            foreach ($width as $w) {
                $borderline .= str_repeat('-', $w + strlen($cellstart) + strlen($cellend) - 1);
                $borderline .= '+';
            }
        }

        if ($borderline) {
            $this->_displayLine($borderline);
        }

        for ($i = 0; $i < count($table_data); $i++) {
            extract($table_data[$i]);
            if (!is_array($rowparams)) {
                $rowparams = array();
            }

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

            $rowlines = array();
            if ($height > 1) {
                for ($c = 0; $c < count($data); $c++) {
                    $rowlines[$c] = preg_split('/(\r?\n|\r)/', $data[$c]);
                    if (count($rowlines[$c]) < $height) {
                        $rowlines[$c] = array_pad($rowlines[$c], $height, '');
                    }
                }
            } else {
                for ($c = 0; $c < count($data); $c++) {
                    $rowlines[$c] = array($data[$c]);
                }
            }

            for ($r = 0; $r < $height; $r++) {
                $rowtext = '';
                for ($c = 0; $c < count($data); $c++) {
                    if (isset($colparams[$c])) {
                        $attribs = array_merge($rowparams, $colparams);
                    } else {
                        $attribs = $rowparams;
                    }

                    $w = isset($width[$c]) ? $width[$c] : 0;
                    //$cell = $data[$c];
                    $cell = $rowlines[$c][$r];
                    $l = strlen($cell);
                    if ($l > $w) {
                        $cell = substr($cell, 0, $w);
                    }

                    if (isset($attribs['bold'])) {
                        $cell = $this->bold($cell);
                    }

                    if ($l < $w) {
                        // not using str_pad here because we may
                        // add bold escape characters to $cell
                        $cell .= str_repeat(' ', $w - $l);
                    }

                    $rowtext .= $cellstart . $cell . $cellend;
                }

                if (!$border) {
                    $rowtext = rtrim($rowtext);
                }

                $rowtext .= $rowend;
                $this->_displayLine($rowtext);
            }
        }

        if ($borderline) {
            $this->_displayLine($borderline);
        }
    }

    function _displayLine($text)
    {
        print "$this->lp$text\n";
    }

    function _display($text)
    {
        print $text;
    }
}
PKr�Z��

PEAR/Installer/Role/Doc.phpnu�[���<?php
/**
 * PEAR_Installer_Role_Doc
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a1
 */

/**
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 */
class PEAR_Installer_Role_Doc extends PEAR_Installer_Role_Common {}
?>PKr�Z��/��PEAR/Installer/Role/Cfg.xmlnu�[���<role version="1.0">
 <releasetypes>php</releasetypes>
 <releasetypes>extsrc</releasetypes>
 <releasetypes>extbin</releasetypes>
 <releasetypes>zendextsrc</releasetypes>
 <releasetypes>zendextbin</releasetypes>
 <installable>1</installable>
 <locationconfig>cfg_dir</locationconfig>
 <honorsbaseinstall />
 <unusualbaseinstall>1</unusualbaseinstall>
 <phpfile />
 <executable />
 <phpextension />
 <config_vars />
</role>PKr�Z>1H���PEAR/Installer/Role/Www.xmlnu�[���<role version="1.0">
 <releasetypes>php</releasetypes>
 <releasetypes>extsrc</releasetypes>
 <releasetypes>extbin</releasetypes>
 <releasetypes>zendextsrc</releasetypes>
 <releasetypes>zendextbin</releasetypes>
 <installable>1</installable>
 <locationconfig>www_dir</locationconfig>
 <honorsbaseinstall>1</honorsbaseinstall>
 <unusualbaseinstall />
 <phpfile />
 <executable />
 <phpextension />
 <config_vars />
</role>PKr�Z�?m

PEAR/Installer/Role/Php.phpnu�[���<?php
/**
 * PEAR_Installer_Role_Php
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a1
 */

/**
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 */
class PEAR_Installer_Role_Php extends PEAR_Installer_Role_Common {}
?>PKr�Z*Y|	%%PEAR/Installer/Role/Man.phpnu�[���<?php
/**
 * PEAR_Installer_Role_Man
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Hannes Magnusson <bjori@php.net>
 * @copyright  2011 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    SVN: $Id: $
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.10.0
 */

/**
 * @category   pear
 * @package    PEAR
 * @author     Hannes Magnusson <bjori@php.net>
 * @copyright  2011 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.10.0
 */
class PEAR_Installer_Role_Man extends PEAR_Installer_Role_Common {}
?>
PKr�Z���BBPEAR/Installer/Role/Ext.xmlnu�[���<role version="1.0">
 <releasetypes>extbin</releasetypes>
 <releasetypes>zendextbin</releasetypes>
 <installable>1</installable>
 <locationconfig>ext_dir</locationconfig>
 <honorsbaseinstall>1</honorsbaseinstall>
 <unusualbaseinstall />
 <phpfile />
 <executable />
 <phpextension>1</phpextension>
 <config_vars />
</role>PKr�Zp��""PEAR/Installer/Role/Src.xmlnu�[���<role version="1.0">
 <releasetypes>extsrc</releasetypes>
 <releasetypes>zendextsrc</releasetypes>
 <installable>1</installable>
 <locationconfig>temp_dir</locationconfig>
 <honorsbaseinstall />
 <unusualbaseinstall />
 <phpfile />
 <executable />
 <phpextension />
 <config_vars />
</role>PKr�Zh&P*��PEAR/Installer/Role/Doc.xmlnu�[���<role version="1.0">
 <releasetypes>php</releasetypes>
 <releasetypes>extsrc</releasetypes>
 <releasetypes>extbin</releasetypes>
 <releasetypes>zendextsrc</releasetypes>
 <releasetypes>zendextbin</releasetypes>
 <installable>1</installable>
 <locationconfig>doc_dir</locationconfig>
 <honorsbaseinstall />
 <unusualbaseinstall />
 <phpfile />
 <executable />
 <phpextension />
 <config_vars />
</role>PKr�ZB] ��PEAR/Installer/Role/Test.xmlnu�[���<role version="1.0">
 <releasetypes>php</releasetypes>
 <releasetypes>extsrc</releasetypes>
 <releasetypes>extbin</releasetypes>
 <releasetypes>zendextsrc</releasetypes>
 <releasetypes>zendextbin</releasetypes>
 <installable>1</installable>
 <locationconfig>test_dir</locationconfig>
 <honorsbaseinstall />
 <unusualbaseinstall />
 <phpfile />
 <executable />
 <phpextension />
 <config_vars />
</role>PKr�Zz�q���PEAR/Installer/Role/Php.xmlnu�[���<role version="1.0">
 <releasetypes>php</releasetypes>
 <releasetypes>extsrc</releasetypes>
 <releasetypes>extbin</releasetypes>
 <releasetypes>zendextsrc</releasetypes>
 <releasetypes>zendextbin</releasetypes>
 <installable>1</installable>
 <locationconfig>php_dir</locationconfig>
 <honorsbaseinstall>1</honorsbaseinstall>
 <unusualbaseinstall />
 <phpfile>1</phpfile>
 <executable />
 <phpextension />
 <config_vars />
</role>PKr�Z	��
PEAR/Installer/Role/Data.phpnu�[���<?php
/**
 * PEAR_Installer_Role_Data
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a1
 */

/**
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 */
class PEAR_Installer_Role_Data extends PEAR_Installer_Role_Common {}
?>PKs�Z�0�c��PEAR/Installer/Role/Man.xmlnu�[���<role version="1.0">
 <releasetypes>php</releasetypes>
 <releasetypes>extsrc</releasetypes>
 <releasetypes>extbin</releasetypes>
 <releasetypes>zendextsrc</releasetypes>
 <releasetypes>zendextbin</releasetypes>
 <installable>1</installable>
 <locationconfig>man_dir</locationconfig>
 <honorsbaseinstall>1</honorsbaseinstall>
 <unusualbaseinstall />
 <phpfile />
 <executable />
 <phpextension />
 <config_vars />
</role>
PKs�Z��K

PEAR/Installer/Role/Ext.phpnu�[���<?php
/**
 * PEAR_Installer_Role_Ext
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a1
 */

/**
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 */
class PEAR_Installer_Role_Ext extends PEAR_Installer_Role_Common {}
?>PKs�ZY���PEAR/Installer/Role/Test.phpnu�[���<?php
/**
 * PEAR_Installer_Role_Test
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a1
 */

/**
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 */
class PEAR_Installer_Role_Test extends PEAR_Installer_Role_Common {}
?>PKs�Z@v�а�PEAR/Installer/Role/Script.xmlnu�[���<role version="1.0">
 <releasetypes>php</releasetypes>
 <releasetypes>extsrc</releasetypes>
 <releasetypes>extbin</releasetypes>
 <releasetypes>zendextsrc</releasetypes>
 <releasetypes>zendextbin</releasetypes>
 <installable>1</installable>
 <locationconfig>bin_dir</locationconfig>
 <honorsbaseinstall>1</honorsbaseinstall>
 <unusualbaseinstall />
 <phpfile />
 <executable>1</executable>
 <phpextension />
 <config_vars />
</role>PKs�Zf�sz��PEAR/Installer/Role/Data.xmlnu�[���<role version="1.0">
 <releasetypes>php</releasetypes>
 <releasetypes>extsrc</releasetypes>
 <releasetypes>extbin</releasetypes>
 <releasetypes>zendextsrc</releasetypes>
 <releasetypes>zendextbin</releasetypes>
 <installable>1</installable>
 <locationconfig>data_dir</locationconfig>
 <honorsbaseinstall />
 <unusualbaseinstall />
 <phpfile />
 <executable />
 <phpextension />
 <config_vars />
</role>PKs�Z?���GGPEAR/Installer/Role/Common.phpnu�[���<?php
/**
 * Base class for all installation roles.
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2006 The PHP Group
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a1
 */
/**
 * Base class for all installation roles.
 *
 * This class allows extensibility of file roles.  Packages with complex
 * customization can now provide custom file roles along with the possibility of
 * adding configuration values to match.
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2006 The PHP Group
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 */
class PEAR_Installer_Role_Common
{
    /**
     * @var PEAR_Config
     * @access protected
     */
    var $config;

    /**
     * @param PEAR_Config
     */
    function __construct(&$config)
    {
        $this->config = $config;
    }

    /**
     * Retrieve configuration information about a file role from its XML info
     *
     * @param string $role Role Classname, as in "PEAR_Installer_Role_Data"
     * @return array
     */
    function getInfo($role)
    {
        if (empty($GLOBALS['_PEAR_INSTALLER_ROLES'][$role])) {
            return PEAR::raiseError('Unknown Role class: "' . $role . '"');
        }
        return $GLOBALS['_PEAR_INSTALLER_ROLES'][$role];
    }

    /**
     * This is called for each file to set up the directories and files
     * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
     * @param array attributes from the <file> tag
     * @param string file name
     * @return array an array consisting of:
     *
     *    1 the original, pre-baseinstalldir installation directory
     *    2 the final installation directory
     *    3 the full path to the final location of the file
     *    4 the location of the pre-installation file
     */
    function processInstallation($pkg, $atts, $file, $tmp_path, $layer = null)
    {
        $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . 
            ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
        if (PEAR::isError($roleInfo)) {
            return $roleInfo;
        }
        if (!$roleInfo['locationconfig']) {
            return false;
        }
        if ($roleInfo['honorsbaseinstall']) {
            $dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'], $layer,
                $pkg->getChannel());
            if (!empty($atts['baseinstalldir'])) {
                $dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir'];
            }
        } elseif ($roleInfo['unusualbaseinstall']) {
            $dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'],
                    $layer, $pkg->getChannel()) . DIRECTORY_SEPARATOR . $pkg->getPackage();
            if (!empty($atts['baseinstalldir'])) {
                $dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir'];
            }
        } else {
            $dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'],
                    $layer, $pkg->getChannel()) . DIRECTORY_SEPARATOR . $pkg->getPackage();
        }
        if (dirname($file) != '.' && empty($atts['install-as'])) {
            $dest_dir .= DIRECTORY_SEPARATOR . dirname($file);
        }
        if (empty($atts['install-as'])) {
            $dest_file = $dest_dir . DIRECTORY_SEPARATOR . basename($file);
        } else {
            $dest_file = $dest_dir . DIRECTORY_SEPARATOR . $atts['install-as'];
        }
        $orig_file = $tmp_path . DIRECTORY_SEPARATOR . $file;

        // Clean up the DIRECTORY_SEPARATOR mess
        $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
        
        list($dest_dir, $dest_file, $orig_file) = preg_replace(array('!\\\\+!', '!/!', "!$ds2+!"),
                                                    array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR,
                                                          DIRECTORY_SEPARATOR),
                                                    array($dest_dir, $dest_file, $orig_file));
        return array($save_destdir, $dest_dir, $dest_file, $orig_file);
    }

    /**
     * Get the name of the configuration variable that specifies the location of this file
     * @return string|false
     */
    function getLocationConfig()
    {
        $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . 
            ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
        if (PEAR::isError($roleInfo)) {
            return $roleInfo;
        }
        return $roleInfo['locationconfig'];
    }

    /**
     * Do any unusual setup here
     * @param PEAR_Installer
     * @param PEAR_PackageFile_v2
     * @param array file attributes
     * @param string file name
     */
    function setup(&$installer, $pkg, $atts, $file)
    {
    }

    function isExecutable()
    {
        $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . 
            ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
        if (PEAR::isError($roleInfo)) {
            return $roleInfo;
        }
        return $roleInfo['executable'];
    }

    function isInstallable()
    {
        $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . 
            ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
        if (PEAR::isError($roleInfo)) {
            return $roleInfo;
        }
        return $roleInfo['installable'];
    }

    function isExtension()
    {
        $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . 
            ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
        if (PEAR::isError($roleInfo)) {
            return $roleInfo;
        }
        return $roleInfo['phpextension'];
    }
}
?>
PKs�Z�^D{		PEAR/Installer/Role/Www.phpnu�[���<?php
/**
 * PEAR_Installer_Role_Www
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  2007-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.7.0
 */

/**
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  2007-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.7.0
 */
class PEAR_Installer_Role_Www extends PEAR_Installer_Role_Common {}
?>PKs�Z�ƤPEAR/Installer/Role/Cfg.phpnu�[���<?php
/**
 * PEAR_Installer_Role_Cfg
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  2007-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.7.0
 */

/**
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  2007-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.7.0
 */
class PEAR_Installer_Role_Cfg extends PEAR_Installer_Role_Common
{
    /**
     * @var PEAR_Installer
     */
    var $installer;

    /**
     * the md5 of the original file
     *
     * @var unknown_type
     */
    var $md5 = null;

    /**
     * Do any unusual setup here
     * @param PEAR_Installer
     * @param PEAR_PackageFile_v2
     * @param array file attributes
     * @param string file name
     */
    function setup(&$installer, $pkg, $atts, $file)
    {
        $this->installer = &$installer;
        $reg = &$this->installer->config->getRegistry();
        $package = $reg->getPackage($pkg->getPackage(), $pkg->getChannel());
        if ($package) {
            $filelist = $package->getFilelist();
            if (isset($filelist[$file]) && isset($filelist[$file]['md5sum'])) {
                $this->md5 = $filelist[$file]['md5sum'];
            }
        }
    }

    function processInstallation($pkg, $atts, $file, $tmp_path, $layer = null)
    {
        $test = parent::processInstallation($pkg, $atts, $file, $tmp_path, $layer);
        if (@file_exists($test[2]) && @file_exists($test[3])) {
            $md5 = md5_file($test[2]);
            // configuration has already been installed, check for mods
            if ($md5 !== $this->md5 && $md5 !== md5_file($test[3])) {
                // configuration has been modified, so save our version as
                // configfile-version
                $old = $test[2];
                $test[2] .= '.new-' . $pkg->getVersion();
                // backup original and re-install it
                PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                $tmpcfg = $this->config->get('temp_dir');
                $newloc = System::mkdir(array('-p', $tmpcfg));
                if (!$newloc) {
                    // try temp_dir
                    $newloc = System::mktemp(array('-d'));
                    if (!$newloc || PEAR::isError($newloc)) {
                        PEAR::popErrorHandling();
                        return PEAR::raiseError('Could not save existing configuration file '.
                            $old . ', unable to install.  Please set temp_dir ' .
                            'configuration variable to a writeable location and try again');
                    }
                } else {
                    $newloc = $tmpcfg;
                }

                $temp_file = $newloc . DIRECTORY_SEPARATOR . uniqid('savefile');
                if (!@copy($old, $temp_file)) {
                    PEAR::popErrorHandling();
                    return PEAR::raiseError('Could not save existing configuration file '.
                        $old . ', unable to install.  Please set temp_dir ' .
                        'configuration variable to a writeable location and try again');
                }

                PEAR::popErrorHandling();
                $this->installer->log(0, "WARNING: configuration file $old is being installed as $test[2], you should manually merge in changes to the existing configuration file");
                $this->installer->addFileOperation('rename', array($temp_file, $old, false));
                $this->installer->addFileOperation('delete', array($temp_file));
            }
        }

        return $test;
    }
}PKs�Z��[�PEAR/Installer/Role/Script.phpnu�[���<?php
/**
 * PEAR_Installer_Role_Script
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a1
 */

/**
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 */
class PEAR_Installer_Role_Script extends PEAR_Installer_Role_Common {}
?>PKs�Z��srrPEAR/Installer/Role/Src.phpnu�[���<?php
/**
 * PEAR_Installer_Role_Src
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a1
 */

/**
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 */
class PEAR_Installer_Role_Src extends PEAR_Installer_Role_Common
{
    function setup(&$installer, $pkg, $atts, $file)
    {
        $installer->source_files++;
    }
}
?>PKs�ZV�Z���PEAR/Installer/Role.phpnu�[���<?php
/**
 * PEAR_Installer_Role
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a1
 */

/**
 * base class for installer roles
 */
require_once 'PEAR/Installer/Role/Common.php';
require_once 'PEAR/XMLParser.php';
/**
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 */
class PEAR_Installer_Role
{
    /**
     * Set up any additional configuration variables that file roles require
     *
     * Never call this directly, it is called by the PEAR_Config constructor
     * @param PEAR_Config
     */
    public static function initializeConfig(&$config)
    {
        if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
            PEAR_Installer_Role::registerRoles();
        }

        foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $class => $info) {
            if (!$info['config_vars']) {
                continue;
            }

            $config->_addConfigVars($class, $info['config_vars']);
        }
    }

    /**
     * @param PEAR_PackageFile_v2
     * @param string role name
     * @param PEAR_Config
     * @return PEAR_Installer_Role_Common
     */
    public static function &factory($pkg, $role, &$config)
    {
        if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
            PEAR_Installer_Role::registerRoles();
        }

        if (!in_array($role, PEAR_Installer_Role::getValidRoles($pkg->getPackageType()))) {
            $a = false;
            return $a;
        }

        $a = 'PEAR_Installer_Role_' . ucfirst($role);
        if (!class_exists($a)) {
            require_once str_replace('_', '/', $a) . '.php';
        }

        $b = new $a($config);
        return $b;
    }

    /**
     * Get a list of file roles that are valid for the particular release type.
     *
     * For instance, src files serve no purpose in regular php releases.
     * @param string
     * @param bool clear cache
     * @return array
     */
    public static function getValidRoles($release, $clear = false)
    {
        if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
            PEAR_Installer_Role::registerRoles();
        }

        static $ret = array();
        if ($clear) {
            $ret = array();
        }

        if (isset($ret[$release])) {
            return $ret[$release];
        }

        $ret[$release] = array();
        foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) {
            if (in_array($release, $okreleases['releasetypes'])) {
                $ret[$release][] = strtolower(str_replace('PEAR_Installer_Role_', '', $role));
            }
        }

        return $ret[$release];
    }

    /**
     * Get a list of roles that require their files to be installed
     *
     * Most roles must be installed, but src and package roles, for instance
     * are pseudo-roles.  src files are compiled into a new extension.  Package
     * roles are actually fully bundled releases of a package
     * @param bool clear cache
     * @return array
     */
    public static function getInstallableRoles($clear = false)
    {
        if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
            PEAR_Installer_Role::registerRoles();
        }

        static $ret;
        if ($clear) {
            unset($ret);
        }

        if (isset($ret)) {
            return $ret;
        }

        $ret = array();
        foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) {
            if ($okreleases['installable']) {
                $ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role));
            }
        }

        return $ret;
    }

    /**
     * Return an array of roles that are affected by the baseinstalldir attribute
     *
     * Most roles ignore this attribute, and instead install directly into:
     * PackageName/filepath
     * so a tests file tests/file.phpt is installed into PackageName/tests/filepath.php
     * @param bool clear cache
     * @return array
     */
    public static function getBaseinstallRoles($clear = false)
    {
        if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
            PEAR_Installer_Role::registerRoles();
        }

        static $ret;
        if ($clear) {
            unset($ret);
        }

        if (isset($ret)) {
            return $ret;
        }

        $ret = array();
        foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) {
            if ($okreleases['honorsbaseinstall']) {
                $ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role));
            }
        }

        return $ret;
    }

    /**
     * Return an array of file roles that should be analyzed for PHP content at package time,
     * like the "php" role.
     * @param bool clear cache
     * @return array
     */
    public static function getPhpRoles($clear = false)
    {
        if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
            PEAR_Installer_Role::registerRoles();
        }

        static $ret;
        if ($clear) {
            unset($ret);
        }

        if (isset($ret)) {
            return $ret;
        }

        $ret = array();
        foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) {
            if ($okreleases['phpfile']) {
                $ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role));
            }
        }

        return $ret;
    }

    /**
     * Scan through the Command directory looking for classes
     * and see what commands they implement.
     * @param string which directory to look for classes, defaults to
     *               the Installer/Roles subdirectory of
     *               the directory from where this file (__FILE__) is
     *               included.
     *
     * @return bool TRUE on success, a PEAR error on failure
     */
    public static function registerRoles($dir = null)
    {
        $GLOBALS['_PEAR_INSTALLER_ROLES'] = array();
        $parser = new PEAR_XMLParser;
        if ($dir === null) {
            $dir = dirname(__FILE__) . '/Role';
        }

        if (!file_exists($dir) || !is_dir($dir)) {
            return PEAR::raiseError("registerRoles: opendir($dir) failed: does not exist/is not directory");
        }

        $dp = @opendir($dir);
        if (empty($dp)) {
            return PEAR::raiseError("registerRoles: opendir($dir) failed: $php_errmsg");
        }

        while ($entry = readdir($dp)) {
            if ($entry[0] == '.' || substr($entry, -4) != '.xml') {
                continue;
            }

            $class = "PEAR_Installer_Role_".substr($entry, 0, -4);
            // List of roles
            if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'][$class])) {
                $file = "$dir/$entry";
                $parser->parse(file_get_contents($file));
                $data = $parser->getData();
                if (!is_array($data['releasetypes'])) {
                    $data['releasetypes'] = array($data['releasetypes']);
                }

                $GLOBALS['_PEAR_INSTALLER_ROLES'][$class] = $data;
            }
        }

        closedir($dp);
        ksort($GLOBALS['_PEAR_INSTALLER_ROLES']);
        PEAR_Installer_Role::getBaseinstallRoles(true);
        PEAR_Installer_Role::getInstallableRoles(true);
        PEAR_Installer_Role::getPhpRoles(true);
        PEAR_Installer_Role::getValidRoles('****', true);
        return true;
    }
}PKs�Z�{�	�)�)PEAR/Downloader/Package.phpnu�[���<?php
/**
 * PEAR_Downloader_Package
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a1
 */

/**
 * Error code when parameter initialization fails because no releases
 * exist within preferred_state, but releases do exist
 */
define('PEAR_DOWNLOADER_PACKAGE_STATE', -1003);
/**
 * Error code when parameter initialization fails because no releases
 * exist that will work with the existing PHP version
 */
define('PEAR_DOWNLOADER_PACKAGE_PHPVERSION', -1004);

/**
 * Coordinates download parameters and manages their dependencies
 * prior to downloading them.
 *
 * Input can come from three sources:
 *
 * - local files (archives or package.xml)
 * - remote files (downloadable urls)
 * - abstract package names
 *
 * The first two elements are handled cleanly by PEAR_PackageFile, but the third requires
 * accessing pearweb's xml-rpc interface to determine necessary dependencies, and the
 * format returned of dependencies is slightly different from that used in package.xml.
 *
 * This class hides the differences between these elements, and makes automatic
 * dependency resolution a piece of cake.  It also manages conflicts when
 * two classes depend on incompatible dependencies, or differing versions of the same
 * package dependency.  In addition, download will not be attempted if the php version is
 * not supported, PEAR installer version is not supported, or non-PECL extensions are not
 * installed.
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 */
class PEAR_Downloader_Package
{
    /**
     * @var PEAR_Downloader
     */
    var $_downloader;
    /**
     * @var PEAR_Config
     */
    var $_config;
    /**
     * @var PEAR_Registry
     */
    var $_registry;
    /**
     * Used to implement packagingroot properly
     * @var PEAR_Registry
     */
    var $_installRegistry;
    /**
     * @var PEAR_PackageFile_v1|PEAR_PackageFile|v2
     */
    var $_packagefile;
    /**
     * @var array
     */
    var $_parsedname;
    /**
     * @var array
     */
    var $_downloadURL;
    /**
     * @var array
     */
    var $_downloadDeps = array();
    /**
     * @var boolean
     */
    var $_valid = false;
    /**
     * @var boolean
     */
    var $_analyzed = false;
    /**
     * if this or a parent package was invoked with Package-state, this is set to the
     * state variable.
     *
     * This allows temporary reassignment of preferred_state for a parent package and all of
     * its dependencies.
     * @var string|false
     */
    var $_explicitState = false;
    /**
     * If this package is invoked with Package#group, this variable will be true
     */
    var $_explicitGroup = false;
    /**
     * Package type local|url
     * @var string
     */
    var $_type;
    /**
     * Contents of package.xml, if downloaded from a remote channel
     * @var string|false
     * @access private
     */
    var $_rawpackagefile;
    /**
     * @var boolean
     * @access private
     */
    var $_validated = false;

    /**
     * @param PEAR_Downloader
     */
    function __construct(&$downloader)
    {
        $this->_downloader = &$downloader;
        $this->_config = &$this->_downloader->config;
        $this->_registry = &$this->_config->getRegistry();
        $options = $downloader->getOptions();
        if (isset($options['packagingroot'])) {
            $this->_config->setInstallRoot($options['packagingroot']);
            $this->_installRegistry = &$this->_config->getRegistry();
            $this->_config->setInstallRoot(false);
        } else {
            $this->_installRegistry = &$this->_registry;
        }
        $this->_valid = $this->_analyzed = false;
    }

    /**
     * Parse the input and determine whether this is a local file, a remote uri, or an
     * abstract package name.
     *
     * This is the heart of the PEAR_Downloader_Package(), and is used in
     * {@link PEAR_Downloader::download()}
     * @param string
     * @return bool|PEAR_Error
     */
    function initialize($param)
    {
        $origErr = $this->_fromFile($param);
        if ($this->_valid) {
            return true;
        }

        $options = $this->_downloader->getOptions();
        if (isset($options['offline'])) {
            if (PEAR::isError($origErr) && !isset($options['soft'])) {
                foreach ($origErr->getUserInfo() as $userInfo) {
                    if (isset($userInfo['message'])) {
                        $this->_downloader->log(0, $userInfo['message']);
                    }
                }

                $this->_downloader->log(0, $origErr->getMessage());
            }

            return PEAR::raiseError('Cannot download non-local package "' . $param . '"');
        }

        $err = $this->_fromUrl($param);
        if (PEAR::isError($err) || !$this->_valid) {
            if ($this->_type == 'url') {
                if (PEAR::isError($err) && !isset($options['soft'])) {
                    $this->_downloader->log(0, $err->getMessage());
                }

                return PEAR::raiseError("Invalid or missing remote package file");
            }

            $err = $this->_fromString($param);
            if (PEAR::isError($err) || !$this->_valid) {
                if (PEAR::isError($err) && $err->getCode() == PEAR_DOWNLOADER_PACKAGE_STATE) {
                    return false; // instruct the downloader to silently skip
                }

                if (isset($this->_type) && $this->_type == 'local' && PEAR::isError($origErr)) {
                    if (is_array($origErr->getUserInfo())) {
                        foreach ($origErr->getUserInfo() as $err) {
                            if (is_array($err)) {
                                $err = $err['message'];
                            }

                            if (!isset($options['soft'])) {
                                $this->_downloader->log(0, $err);
                            }
                        }
                    }

                    if (!isset($options['soft'])) {
                        $this->_downloader->log(0, $origErr->getMessage());
                    }

                    if (is_array($param)) {
                        $param = $this->_registry->parsedPackageNameToString($param, true);
                    }

                    if (!isset($options['soft'])) {
                        $this->_downloader->log(2, "Cannot initialize '$param', invalid or missing package file");
                    }

                    // Passing no message back - already logged above
                    return PEAR::raiseError();
                }

                if (PEAR::isError($err) && !isset($options['soft'])) {
                    $this->_downloader->log(0, $err->getMessage());
                }

                if (is_array($param)) {
                    $param = $this->_registry->parsedPackageNameToString($param, true);
                }

                if (!isset($options['soft'])) {
                    $this->_downloader->log(2, "Cannot initialize '$param', invalid or missing package file");
                }

                // Passing no message back - already logged above
                return PEAR::raiseError();
            }
        }

        return true;
    }

    /**
     * Retrieve any non-local packages
     * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|PEAR_Error
     */
    function &download()
    {
        if (isset($this->_packagefile)) {
            return $this->_packagefile;
        }

        if (isset($this->_downloadURL['url'])) {
            $this->_isvalid = false;
            $info = $this->getParsedPackage();
            foreach ($info as $i => $p) {
                $info[$i] = strtolower($p);
            }

            $err = $this->_fromUrl($this->_downloadURL['url'],
                $this->_registry->parsedPackageNameToString($this->_parsedname, true));
            $newinfo = $this->getParsedPackage();
            foreach ($newinfo as $i => $p) {
                $newinfo[$i] = strtolower($p);
            }

            if ($info != $newinfo) {
                do {
                    if ($info['channel'] == 'pecl.php.net' && $newinfo['channel'] == 'pear.php.net') {
                        $info['channel'] = 'pear.php.net';
                        if ($info == $newinfo) {
                            // skip the channel check if a pecl package says it's a PEAR package
                            break;
                        }
                    }
                    if ($info['channel'] == 'pear.php.net' && $newinfo['channel'] == 'pecl.php.net') {
                        $info['channel'] = 'pecl.php.net';
                        if ($info == $newinfo) {
                            // skip the channel check if a pecl package says it's a PEAR package
                            break;
                        }
                    }

                    return PEAR::raiseError('CRITICAL ERROR: We are ' .
                        $this->_registry->parsedPackageNameToString($info) . ', but the file ' .
                        'downloaded claims to be ' .
                        $this->_registry->parsedPackageNameToString($this->getParsedPackage()));
                } while (false);
            }

            if (PEAR::isError($err) || !$this->_valid) {
                return $err;
            }
        }

        $this->_type = 'local';
        return $this->_packagefile;
    }

    function &getPackageFile()
    {
        return $this->_packagefile;
    }

    function &getDownloader()
    {
        return $this->_downloader;
    }

    function getType()
    {
        return $this->_type;
    }

    /**
     * Like {@link initialize()}, but operates on a dependency
     */
    function fromDepURL($dep)
    {
        $this->_downloadURL = $dep;
        if (isset($dep['uri'])) {
            $options = $this->_downloader->getOptions();
            if (!extension_loaded("zlib") || isset($options['nocompress'])) {
                $ext = '.tar';
            } else {
                $ext = '.tgz';
            }

            PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
            $err = $this->_fromUrl($dep['uri'] . $ext);
            PEAR::popErrorHandling();
            if (PEAR::isError($err)) {
                if (!isset($options['soft'])) {
                    $this->_downloader->log(0, $err->getMessage());
                }

                return PEAR::raiseError('Invalid uri dependency "' . $dep['uri'] . $ext . '", ' .
                    'cannot download');
            }
        } else {
            $this->_parsedname =
                array(
                    'package' => $dep['info']->getPackage(),
                    'channel' => $dep['info']->getChannel(),
                    'version' => $dep['version']
                );
            if (!isset($dep['nodefault'])) {
                $this->_parsedname['group'] = 'default'; // download the default dependency group
                $this->_explicitGroup = false;
            }

            $this->_rawpackagefile = $dep['raw'];
        }
    }

    function detectDependencies($params)
    {
        $options = $this->_downloader->getOptions();
        if (isset($options['downloadonly'])) {
            return;
        }

        if (isset($options['offline'])) {
            $this->_downloader->log(3, 'Skipping dependency download check, --offline specified');
            return;
        }

        $pname = $this->getParsedPackage();
        if (!$pname) {
            return;
        }

        $deps = $this->getDeps();
        if (!$deps) {
            return;
        }

        if (isset($deps['required'])) { // package.xml 2.0
            return $this->_detect2($deps, $pname, $options, $params);
        }

        return $this->_detect1($deps, $pname, $options, $params);
    }

    function setValidated()
    {
        $this->_validated = true;
    }

    function alreadyValidated()
    {
        return $this->_validated;
    }

    /**
     * Remove packages to be downloaded that are already installed
     * @param array of PEAR_Downloader_Package objects
     */
    public static function removeInstalled(&$params)
    {
        if (!isset($params[0])) {
            return;
        }

        $options = $params[0]->_downloader->getOptions();
        if (!isset($options['downloadonly'])) {
            foreach ($params as $i => $param) {
                $package = $param->getPackage();
                $channel = $param->getChannel();
                // remove self if already installed with this version
                // this does not need any pecl magic - we only remove exact matches
                if ($param->_installRegistry->packageExists($package, $channel)) {
                    $packageVersion = $param->_installRegistry->packageInfo($package, 'version', $channel);
                    if (version_compare($packageVersion, $param->getVersion(), '==')) {
                        if (!isset($options['force']) && !isset($options['packagingroot'])) {
                            $info = $param->getParsedPackage();
                            unset($info['version']);
                            unset($info['state']);
                            if (!isset($options['soft'])) {
                                $param->_downloader->log(1, 'Skipping package "' .
                                    $param->getShortName() .
                                    '", already installed as version ' . $packageVersion);
                            }
                            $params[$i] = false;
                        }
                    } elseif (!isset($options['force']) && !isset($options['upgrade']) &&
                          !isset($options['soft']) && !isset($options['packagingroot'])) {
                        $info = $param->getParsedPackage();
                        $param->_downloader->log(1, 'Skipping package "' .
                            $param->getShortName() .
                            '", already installed as version ' . $packageVersion);
                        $params[$i] = false;
                    }
                }
            }
        }

        PEAR_Downloader_Package::removeDuplicates($params);
    }

    function _detect2($deps, $pname, $options, $params)
    {
        $this->_downloadDeps = array();
        $groupnotfound = false;
        foreach (array('package', 'subpackage') as $packagetype) {
            // get required dependency group
            if (isset($deps['required'][$packagetype])) {
                if (isset($deps['required'][$packagetype][0])) {
                    foreach ($deps['required'][$packagetype] as $dep) {
                        if (isset($dep['conflicts'])) {
                            // skip any package that this package conflicts with
                            continue;
                        }
                        $ret = $this->_detect2Dep($dep, $pname, 'required', $params);
                        if (is_array($ret)) {
                            $this->_downloadDeps[] = $ret;
                        } elseif (PEAR::isError($ret) && !isset($options['soft'])) {
                            $this->_downloader->log(0, $ret->getMessage());
                        }
                    }
                } else {
                    $dep = $deps['required'][$packagetype];
                    if (!isset($dep['conflicts'])) {
                        // skip any package that this package conflicts with
                        $ret = $this->_detect2Dep($dep, $pname, 'required', $params);
                        if (is_array($ret)) {
                            $this->_downloadDeps[] = $ret;
                        } elseif (PEAR::isError($ret) && !isset($options['soft'])) {
                            $this->_downloader->log(0, $ret->getMessage());
                        }
                    }
                }
            }

            // get optional dependency group, if any
            if (isset($deps['optional'][$packagetype])) {
                $skipnames = array();
                if (!isset($deps['optional'][$packagetype][0])) {
                    $deps['optional'][$packagetype] = array($deps['optional'][$packagetype]);
                }

                foreach ($deps['optional'][$packagetype] as $dep) {
                    $skip = false;
                    if (!isset($options['alldeps'])) {
                        $dep['package'] = $dep['name'];
                        if (!isset($options['soft'])) {
                            $this->_downloader->log(3, 'Notice: package "' .
                              $this->_registry->parsedPackageNameToString($this->getParsedPackage(),
                                    true) . '" optional dependency "' .
                                $this->_registry->parsedPackageNameToString(array('package' =>
                                    $dep['name'], 'channel' => 'pear.php.net'), true) .
                                '" will not be automatically downloaded');
                        }
                        $skipnames[] = $this->_registry->parsedPackageNameToString($dep, true);
                        $skip = true;
                        unset($dep['package']);
                    }

                    $ret = $this->_detect2Dep($dep, $pname, 'optional', $params);
                    if (PEAR::isError($ret) && !isset($options['soft'])) {
                        $this->_downloader->log(0, $ret->getMessage());
                    }

                    if (!$ret) {
                        $dep['package'] = $dep['name'];
                        $skip = count($skipnames) ?
                            $skipnames[count($skipnames) - 1] : '';
                        if ($skip ==
                              $this->_registry->parsedPackageNameToString($dep, true)) {
                            array_pop($skipnames);
                        }
                    }

                    if (!$skip && is_array($ret)) {
                        $this->_downloadDeps[] = $ret;
                    }
                }

                if (count($skipnames)) {
                    if (!isset($options['soft'])) {
                        $this->_downloader->log(1, 'Did not download optional dependencies: ' .
                            implode(', ', $skipnames) .
                            ', use --alldeps to download automatically');
                    }
                }
            }

            // get requested dependency group, if any
            $groupname = $this->getGroup();
            $explicit  = $this->_explicitGroup;
            if (!$groupname) {
                if (!$this->canDefault()) {
                    continue;
                }

                $groupname = 'default'; // try the default dependency group
            }

            if ($groupnotfound) {
                continue;
            }

            if (isset($deps['group'])) {
                if (isset($deps['group']['attribs'])) {
                    if (strtolower($deps['group']['attribs']['name']) == strtolower($groupname)) {
                        $group = $deps['group'];
                    } elseif ($explicit) {
                        if (!isset($options['soft'])) {
                            $this->_downloader->log(0, 'Warning: package "' .
                                $this->_registry->parsedPackageNameToString($pname, true) .
                                '" has no dependency ' . 'group named "' . $groupname . '"');
                        }

                        $groupnotfound = true;
                        continue;
                    }
                } else {
                    $found = false;
                    foreach ($deps['group'] as $group) {
                        if (strtolower($group['attribs']['name']) == strtolower($groupname)) {
                            $found = true;
                            break;
                        }
                    }

                    if (!$found) {
                        if ($explicit) {
                            if (!isset($options['soft'])) {
                                $this->_downloader->log(0, 'Warning: package "' .
                                    $this->_registry->parsedPackageNameToString($pname, true) .
                                    '" has no dependency ' . 'group named "' . $groupname . '"');
                            }
                        }

                        $groupnotfound = true;
                        continue;
                    }
                }
            }

            if (isset($group) && isset($group[$packagetype])) {
                if (isset($group[$packagetype][0])) {
                    foreach ($group[$packagetype] as $dep) {
                        $ret = $this->_detect2Dep($dep, $pname, 'dependency group "' .
                            $group['attribs']['name'] . '"', $params);
                        if (is_array($ret)) {
                            $this->_downloadDeps[] = $ret;
                        } elseif (PEAR::isError($ret) && !isset($options['soft'])) {
                            $this->_downloader->log(0, $ret->getMessage());
                        }
                    }
                } else {
                    $ret = $this->_detect2Dep($group[$packagetype], $pname,
                        'dependency group "' .
                        $group['attribs']['name'] . '"', $params);
                    if (is_array($ret)) {
                        $this->_downloadDeps[] = $ret;
                    } elseif (PEAR::isError($ret) && !isset($options['soft'])) {
                        $this->_downloader->log(0, $ret->getMessage());
                    }
                }
            }
        }
    }

    function _detect2Dep($dep, $pname, $group, $params)
    {
        if (isset($dep['conflicts'])) {
            return true;
        }

        $options = $this->_downloader->getOptions();
        if (isset($dep['uri'])) {
            return array('uri' => $dep['uri'], 'dep' => $dep);;
        }

        $testdep = $dep;
        $testdep['package'] = $dep['name'];
        if (PEAR_Downloader_Package::willDownload($testdep, $params)) {
            $dep['package'] = $dep['name'];
            if (!isset($options['soft'])) {
                $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group .
                    ' dependency "' .
                    $this->_registry->parsedPackageNameToString($dep, true) .
                    '", will be installed');
            }
            return false;
        }

        $options = $this->_downloader->getOptions();
        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        if ($this->_explicitState) {
            $pname['state'] = $this->_explicitState;
        }

        $url = $this->_downloader->_getDepPackageDownloadUrl($dep, $pname);
        if (PEAR::isError($url)) {
            PEAR::popErrorHandling();
            return $url;
        }

        $dep['package'] = $dep['name'];
        $ret = $this->_analyzeDownloadURL($url, 'dependency', $dep, $params, $group == 'optional' &&
            !isset($options['alldeps']), true);
        PEAR::popErrorHandling();
        if (PEAR::isError($ret)) {
            if (!isset($options['soft'])) {
                $this->_downloader->log(0, $ret->getMessage());
            }

            return false;
        }

        // check to see if a dep is already installed and is the same or newer
        if (!isset($dep['min']) && !isset($dep['max']) && !isset($dep['recommended'])) {
            $oper = 'has';
        } else {
            $oper = 'gt';
        }

        // do not try to move this before getDepPackageDownloadURL
        // we can't determine whether upgrade is necessary until we know what
        // version would be downloaded
        if (!isset($options['force']) && $this->isInstalled($ret, $oper)) {
            $version = $this->_installRegistry->packageInfo($dep['name'], 'version', $dep['channel']);
            $dep['package'] = $dep['name'];
            if (!isset($options['soft'])) {
                $this->_downloader->log(3, $this->getShortName() . ': Skipping ' . $group .
                    ' dependency "' .
                $this->_registry->parsedPackageNameToString($dep, true) .
                    '" version ' . $url['version'] . ', already installed as version ' .
                    $version);
            }

            return false;
        }

        if (isset($dep['nodefault'])) {
            $ret['nodefault'] = true;
        }

        return $ret;
    }

    function _detect1($deps, $pname, $options, $params)
    {
        $this->_downloadDeps = array();
        $skipnames = array();
        foreach ($deps as $dep) {
            $nodownload = false;
            if (isset ($dep['type']) && $dep['type'] === 'pkg') {
                $dep['channel'] = 'pear.php.net';
                $dep['package'] = $dep['name'];
                switch ($dep['rel']) {
                    case 'not' :
                        continue 2;
                    case 'ge' :
                    case 'eq' :
                    case 'gt' :
                    case 'has' :
                        $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ?
                            'required' :
                            'optional';
                        if (PEAR_Downloader_Package::willDownload($dep, $params)) {
                            $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group
                                . ' dependency "' .
                                $this->_registry->parsedPackageNameToString($dep, true) .
                                '", will be installed');
                            continue 2;
                        }
                        $fakedp = new PEAR_PackageFile_v1;
                        $fakedp->setPackage($dep['name']);
                        // skip internet check if we are not upgrading (bug #5810)
                        if (!isset($options['upgrade']) && $this->isInstalled(
                              $fakedp, $dep['rel'])) {
                            $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group
                                . ' dependency "' .
                                $this->_registry->parsedPackageNameToString($dep, true) .
                                '", is already installed');
                            continue 2;
                        }
                }

                PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                if ($this->_explicitState) {
                    $pname['state'] = $this->_explicitState;
                }

                $url = $this->_downloader->_getDepPackageDownloadUrl($dep, $pname);
                $chan = 'pear.php.net';
                if (PEAR::isError($url)) {
                    // check to see if this is a pecl package that has jumped
                    // from pear.php.net to pecl.php.net channel
                    if (!class_exists('PEAR_Dependency2')) {
                        require_once 'PEAR/Dependency2.php';
                    }

                    $newdep = PEAR_Dependency2::normalizeDep($dep);
                    $newdep = $newdep[0];
                    $newdep['channel'] = 'pecl.php.net';
                    $chan = 'pecl.php.net';
                    $url = $this->_downloader->_getDepPackageDownloadUrl($newdep, $pname);
                    $obj = &$this->_installRegistry->getPackage($dep['name']);
                    if (PEAR::isError($url)) {
                        PEAR::popErrorHandling();
                        if ($obj !== null && $this->isInstalled($obj, $dep['rel'])) {
                            $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ?
                                'required' :
                                'optional';
                            $dep['package'] = $dep['name'];
                            if (!isset($options['soft'])) {
                                $this->_downloader->log(3, $this->getShortName() .
                                    ': Skipping ' . $group . ' dependency "' .
                                    $this->_registry->parsedPackageNameToString($dep, true) .
                                    '", already installed as version ' . $obj->getVersion());
                            }
                            $skip = count($skipnames) ?
                                $skipnames[count($skipnames) - 1] : '';
                            if ($skip ==
                                  $this->_registry->parsedPackageNameToString($dep, true)) {
                                array_pop($skipnames);
                            }
                            continue;
                        } else {
                            if (isset($dep['optional']) && $dep['optional'] == 'yes') {
                                $this->_downloader->log(2, $this->getShortName() .
                                    ': Skipping optional dependency "' .
                                    $this->_registry->parsedPackageNameToString($dep, true) .
                                    '", no releases exist');
                                continue;
                            } else {
                                return $url;
                            }
                        }
                    }
                }

                PEAR::popErrorHandling();
                if (!isset($options['alldeps'])) {
                    if (isset($dep['optional']) && $dep['optional'] == 'yes') {
                        if (!isset($options['soft'])) {
                            $this->_downloader->log(3, 'Notice: package "' .
                                $this->getShortName() .
                                '" optional dependency "' .
                                $this->_registry->parsedPackageNameToString(
                                    array('channel' => $chan, 'package' =>
                                    $dep['name']), true) .
                                '" will not be automatically downloaded');
                        }
                        $skipnames[] = $this->_registry->parsedPackageNameToString(
                                array('channel' => $chan, 'package' =>
                                $dep['name']), true);
                        $nodownload = true;
                    }
                }

                if (!isset($options['alldeps']) && !isset($options['onlyreqdeps'])) {
                    if (!isset($dep['optional']) || $dep['optional'] == 'no') {
                        if (!isset($options['soft'])) {
                            $this->_downloader->log(3, 'Notice: package "' .
                                $this->getShortName() .
                                '" required dependency "' .
                                $this->_registry->parsedPackageNameToString(
                                    array('channel' => $chan, 'package' =>
                                    $dep['name']), true) .
                                '" will not be automatically downloaded');
                        }
                        $skipnames[] = $this->_registry->parsedPackageNameToString(
                                array('channel' => $chan, 'package' =>
                                $dep['name']), true);
                        $nodownload = true;
                    }
                }

                // check to see if a dep is already installed
                // do not try to move this before getDepPackageDownloadURL
                // we can't determine whether upgrade is necessary until we know what
                // version would be downloaded
                if (!isset($options['force']) && $this->isInstalled(
                        $url, $dep['rel'])) {
                    $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ?
                        'required' :
                        'optional';
                    $dep['package'] = $dep['name'];
                    if (isset($newdep)) {
                        $version = $this->_installRegistry->packageInfo($newdep['name'], 'version', $newdep['channel']);
                    } else {
                        $version = $this->_installRegistry->packageInfo($dep['name'], 'version');
                    }

                    $dep['version'] = $url['version'];
                    if (!isset($options['soft'])) {
                        $this->_downloader->log(3, $this->getShortName() . ': Skipping ' . $group .
                            ' dependency "' .
                            $this->_registry->parsedPackageNameToString($dep, true) .
                            '", already installed as version ' . $version);
                    }

                    $skip = count($skipnames) ?
                        $skipnames[count($skipnames) - 1] : '';
                    if ($skip ==
                          $this->_registry->parsedPackageNameToString($dep, true)) {
                        array_pop($skipnames);
                    }

                    continue;
                }

                if ($nodownload) {
                    continue;
                }

                PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                if (isset($newdep)) {
                    $dep = $newdep;
                }

                $dep['package'] = $dep['name'];
                $ret = $this->_analyzeDownloadURL($url, 'dependency', $dep, $params,
                    isset($dep['optional']) && $dep['optional'] == 'yes' &&
                    !isset($options['alldeps']), true);
                PEAR::popErrorHandling();
                if (PEAR::isError($ret)) {
                    if (!isset($options['soft'])) {
                        $this->_downloader->log(0, $ret->getMessage());
                    }
                    continue;
                }

                $this->_downloadDeps[] = $ret;
            }
        }

        if (count($skipnames)) {
            if (!isset($options['soft'])) {
                $this->_downloader->log(1, 'Did not download dependencies: ' .
                    implode(', ', $skipnames) .
                    ', use --alldeps or --onlyreqdeps to download automatically');
            }
        }
    }

    function setDownloadURL($pkg)
    {
        $this->_downloadURL = $pkg;
    }

    /**
     * Set the package.xml object for this downloaded package
     *
     * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 $pkg
     */
    function setPackageFile(&$pkg)
    {
        $this->_packagefile = &$pkg;
    }

    function getShortName()
    {
        return $this->_registry->parsedPackageNameToString(array('channel' => $this->getChannel(),
            'package' => $this->getPackage()), true);
    }

    function getParsedPackage()
    {
        if (isset($this->_packagefile) || isset($this->_parsedname)) {
            return array('channel' => $this->getChannel(),
                'package' => $this->getPackage(),
                'version' => $this->getVersion());
        }

        return false;
    }

    function getDownloadURL()
    {
        return $this->_downloadURL;
    }

    function canDefault()
    {
        if (isset($this->_downloadURL) && isset($this->_downloadURL['nodefault'])) {
            return false;
        }

        return true;
    }

    function getPackage()
    {
        if (isset($this->_packagefile)) {
            return $this->_packagefile->getPackage();
        } elseif (isset($this->_downloadURL['info'])) {
            return $this->_downloadURL['info']->getPackage();
        }

        return false;
    }

    /**
     * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
     */
    function isSubpackage(&$pf)
    {
        if (isset($this->_packagefile)) {
            return $this->_packagefile->isSubpackage($pf);
        } elseif (isset($this->_downloadURL['info'])) {
            return $this->_downloadURL['info']->isSubpackage($pf);
        }

        return false;
    }

    function getPackageType()
    {
        if (isset($this->_packagefile)) {
            return $this->_packagefile->getPackageType();
        } elseif (isset($this->_downloadURL['info'])) {
            return $this->_downloadURL['info']->getPackageType();
        }

        return false;
    }

    function isBundle()
    {
        if (isset($this->_packagefile)) {
            return $this->_packagefile->getPackageType() == 'bundle';
        }

        return false;
    }

    function getPackageXmlVersion()
    {
        if (isset($this->_packagefile)) {
            return $this->_packagefile->getPackagexmlVersion();
        } elseif (isset($this->_downloadURL['info'])) {
            return $this->_downloadURL['info']->getPackagexmlVersion();
        }

        return '1.0';
    }

    function getChannel()
    {
        if (isset($this->_packagefile)) {
            return $this->_packagefile->getChannel();
        } elseif (isset($this->_downloadURL['info'])) {
            return $this->_downloadURL['info']->getChannel();
        }

        return false;
    }

    function getURI()
    {
        if (isset($this->_packagefile)) {
            return $this->_packagefile->getURI();
        } elseif (isset($this->_downloadURL['info'])) {
            return $this->_downloadURL['info']->getURI();
        }

        return false;
    }

    function getVersion()
    {
        if (isset($this->_packagefile)) {
            return $this->_packagefile->getVersion();
        } elseif (isset($this->_downloadURL['version'])) {
            return $this->_downloadURL['version'];
        }

        return false;
    }

    function isCompatible($pf)
    {
        if (isset($this->_packagefile)) {
            return $this->_packagefile->isCompatible($pf);
        } elseif (isset($this->_downloadURL['info'])) {
            return $this->_downloadURL['info']->isCompatible($pf);
        }

        return true;
    }

    function setGroup($group)
    {
        $this->_parsedname['group'] = $group;
    }

    function getGroup()
    {
        if (isset($this->_parsedname['group'])) {
            return $this->_parsedname['group'];
        }

        return '';
    }

    function isExtension($name)
    {
        if (isset($this->_packagefile)) {
            return $this->_packagefile->isExtension($name);
        } elseif (isset($this->_downloadURL['info'])) {
            if ($this->_downloadURL['info']->getPackagexmlVersion() == '2.0') {
                return $this->_downloadURL['info']->getProvidesExtension() == $name;
            }

            return false;
        }

        return false;
    }

    function getDeps()
    {
        if (isset($this->_packagefile)) {
            $ver = $this->_packagefile->getPackagexmlVersion();
            if (version_compare($ver, '2.0', '>=')) {
                return $this->_packagefile->getDeps(true);
            }

            return $this->_packagefile->getDeps();
        } elseif (isset($this->_downloadURL['info'])) {
            $ver = $this->_downloadURL['info']->getPackagexmlVersion();
            if (version_compare($ver, '2.0', '>=')) {
                return $this->_downloadURL['info']->getDeps(true);
            }

            return $this->_downloadURL['info']->getDeps();
        }

        return array();
    }

    /**
     * @param array Parsed array from {@link PEAR_Registry::parsePackageName()} or a dependency
     *                     returned from getDepDownloadURL()
     */
    function isEqual($param)
    {
        if (is_object($param)) {
            $channel = $param->getChannel();
            $package = $param->getPackage();
            if ($param->getURI()) {
                $param = array(
                    'channel' => $param->getChannel(),
                    'package' => $param->getPackage(),
                    'version' => $param->getVersion(),
                    'uri' => $param->getURI(),
                );
            } else {
                $param = array(
                    'channel' => $param->getChannel(),
                    'package' => $param->getPackage(),
                    'version' => $param->getVersion(),
                );
            }
        } else {
            if (isset($param['uri'])) {
                if ($this->getChannel() != '__uri') {
                    return false;
                }
                return $param['uri'] == $this->getURI();
            }

            $package = isset($param['package']) ? $param['package'] : $param['info']->getPackage();
            $channel = isset($param['channel']) ? $param['channel'] : $param['info']->getChannel();
            if (isset($param['rel'])) {
                if (!class_exists('PEAR_Dependency2')) {
                    require_once 'PEAR/Dependency2.php';
                }

                $newdep = PEAR_Dependency2::normalizeDep($param);
                $newdep = $newdep[0];
            } elseif (isset($param['min'])) {
                $newdep = $param;
            }
        }

        if (isset($newdep)) {
            if (!isset($newdep['min'])) {
                $newdep['min'] = '0';
            }

            if (!isset($newdep['max'])) {
                $newdep['max'] = '100000000000000000000';
            }

            // use magic to support pecl packages suddenly jumping to the pecl channel
            // we need to support both dependency possibilities
            if ($channel == 'pear.php.net' && $this->getChannel() == 'pecl.php.net') {
                if ($package == $this->getPackage()) {
                    $channel = 'pecl.php.net';
                }
            }
            if ($channel == 'pecl.php.net' && $this->getChannel() == 'pear.php.net') {
                if ($package == $this->getPackage()) {
                    $channel = 'pear.php.net';
                }
            }

            return (strtolower($package) == strtolower($this->getPackage()) &&
                $channel == $this->getChannel() &&
                version_compare($newdep['min'], $this->getVersion(), '<=') &&
                version_compare($newdep['max'], $this->getVersion(), '>='));
        }

        // use magic to support pecl packages suddenly jumping to the pecl channel
        if ($channel == 'pecl.php.net' && $this->getChannel() == 'pear.php.net') {
            if (strtolower($package) == strtolower($this->getPackage())) {
                $channel = 'pear.php.net';
            }
        }

        if (isset($param['version'])) {
            return (strtolower($package) == strtolower($this->getPackage()) &&
                $channel == $this->getChannel() &&
                $param['version'] == $this->getVersion());
        }

        return strtolower($package) == strtolower($this->getPackage()) &&
            $channel == $this->getChannel();
    }

    function isInstalled($dep, $oper = '==')
    {
        if (!$dep) {
            return false;
        }

        if ($oper != 'ge' && $oper != 'gt' && $oper != 'has' && $oper != '==') {
            return false;
        }

        if (is_object($dep)) {
            $package = $dep->getPackage();
            $channel = $dep->getChannel();
            if ($dep->getURI()) {
                $dep = array(
                    'uri' => $dep->getURI(),
                    'version' => $dep->getVersion(),
                );
            } else {
                $dep = array(
                    'version' => $dep->getVersion(),
                );
            }
        } else {
            if (isset($dep['uri'])) {
                $channel = '__uri';
                $package = $dep['dep']['name'];
            } else {
                $channel = $dep['info']->getChannel();
                $package = $dep['info']->getPackage();
            }
        }

        $options = $this->_downloader->getOptions();
        $test    = $this->_installRegistry->packageExists($package, $channel);
        if (!$test && $channel == 'pecl.php.net') {
            // do magic to allow upgrading from old pecl packages to new ones
            $test = $this->_installRegistry->packageExists($package, 'pear.php.net');
            $channel = 'pear.php.net';
        }

        if ($test) {
            if (isset($dep['uri'])) {
                if ($this->_installRegistry->packageInfo($package, 'uri', '__uri') == $dep['uri']) {
                    return true;
                }
            }

            if (isset($options['upgrade'])) {
                $packageVersion = $this->_installRegistry->packageInfo($package, 'version', $channel);
                if (version_compare($packageVersion, $dep['version'], '>=')) {
                    return true;
                }

                return false;
            }

            return true;
        }

        return false;
    }

    /**
     * Detect duplicate package names with differing versions
     *
     * If a user requests to install Date 1.4.6 and Date 1.4.7,
     * for instance, this is a logic error.  This method
     * detects this situation.
     *
     * @param array $params array of PEAR_Downloader_Package objects
     * @param array $errorparams empty array
     * @return array array of stupid duplicated packages in PEAR_Downloader_Package obejcts
     */
    public static function detectStupidDuplicates($params, &$errorparams)
    {
        $existing = array();
        foreach ($params as $i => $param) {
            $package = $param->getPackage();
            $channel = $param->getChannel();
            $group   = $param->getGroup();
            if (!isset($existing[$channel . '/' . $package])) {
                $existing[$channel . '/' . $package] = array();
            }

            if (!isset($existing[$channel . '/' . $package][$group])) {
                $existing[$channel . '/' . $package][$group] = array();
            }

            $existing[$channel . '/' . $package][$group][] = $i;
        }

        $indices = array();
        foreach ($existing as $package => $groups) {
            foreach ($groups as $group => $dupes) {
                if (count($dupes) > 1) {
                    $indices = $indices + $dupes;
                }
            }
        }

        $indices = array_unique($indices);
        foreach ($indices as $index) {
            $errorparams[] = $params[$index];
        }

        return count($errorparams);
    }

    /**
     * @param array
     * @param bool ignore install groups - for final removal of dupe packages
     */
    public static function removeDuplicates(&$params, $ignoreGroups = false)
    {
        $pnames = array();
        foreach ($params as $i => $param) {
            if (!$param) {
                continue;
            }

            if ($param->getPackage()) {
                $group = $ignoreGroups ? '' : $param->getGroup();
                $pnames[$i] = $param->getChannel() . '/' .
                    $param->getPackage() . '-' . $param->getVersion() . '#' . $group;
            }
        }

        $pnames = array_unique($pnames);
        $unset  = array_diff(array_keys($params), array_keys($pnames));
        $testp  = array_flip($pnames);
        foreach ($params as $i => $param) {
            if (!$param) {
                $unset[] = $i;
                continue;
            }

            if (!is_a($param, 'PEAR_Downloader_Package')) {
                $unset[] = $i;
                continue;
            }

            $group = $ignoreGroups ? '' : $param->getGroup();
            if (!isset($testp[$param->getChannel() . '/' . $param->getPackage() . '-' .
                  $param->getVersion() . '#' . $group])) {
                $unset[] = $i;
            }
        }

        foreach ($unset as $i) {
            unset($params[$i]);
        }

        $ret = array();
        foreach ($params as $i => $param) {
            $ret[] = &$params[$i];
        }

        $params = array();
        foreach ($ret as $i => $param) {
            $params[] = &$ret[$i];
        }
    }

    function explicitState()
    {
        return $this->_explicitState;
    }

    function setExplicitState($s)
    {
        $this->_explicitState = $s;
    }

    /**
     */
    public static function mergeDependencies(&$params)
    {
        $bundles = $newparams = array();
        foreach ($params as $i => $param) {
            if (!$param->isBundle()) {
                continue;
            }

            $bundles[] = $i;
            $pf = &$param->getPackageFile();
            $newdeps = array();
            $contents = $pf->getBundledPackages();
            if (!is_array($contents)) {
                $contents = array($contents);
            }

            foreach ($contents as $file) {
                $filecontents = $pf->getFileContents($file);
                $dl = &$param->getDownloader();
                $options = $dl->getOptions();
                if (PEAR::isError($dir = $dl->getDownloadDir())) {
                    return $dir;
                }

                $fp = @fopen($dir . DIRECTORY_SEPARATOR . $file, 'wb');
                if (!$fp) {
                    continue;
                }

                // FIXME do symlink check

                fwrite($fp, $filecontents, strlen($filecontents));
                fclose($fp);
                if ($s = $params[$i]->explicitState()) {
                    $obj->setExplicitState($s);
                }

                $obj = new PEAR_Downloader_Package($params[$i]->getDownloader());
                PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                if (PEAR::isError($dir = $dl->getDownloadDir())) {
                    PEAR::popErrorHandling();
                    return $dir;
                }
                $a = $dir . DIRECTORY_SEPARATOR . $file;
                $e = $obj->_fromFile($a);
                PEAR::popErrorHandling();
                if (PEAR::isError($e)) {
                    if (!isset($options['soft'])) {
                        $dl->log(0, $e->getMessage());
                    }
                    continue;
                }

                if (!PEAR_Downloader_Package::willDownload($obj,
                      array_merge($params, $newparams)) && !$param->isInstalled($obj)) {
                    $newparams[] = $obj;
                }
            }
        }

        foreach ($bundles as $i) {
            unset($params[$i]); // remove bundles - only their contents matter for installation
        }

        PEAR_Downloader_Package::removeDuplicates($params); // strip any unset indices
        if (count($newparams)) { // add in bundled packages for install
            foreach ($newparams as $i => $unused) {
                $params[] = &$newparams[$i];
            }
            $newparams = array();
        }

        foreach ($params as $i => $param) {
            $newdeps = array();
            foreach ($param->_downloadDeps as $dep) {
                $merge = array_merge($params, $newparams);
                if (!PEAR_Downloader_Package::willDownload($dep, $merge)
                    && !$param->isInstalled($dep)
                ) {
                    $newdeps[] = $dep;
                } else {
                    //var_dump($dep);
                    // detect versioning conflicts here
                }
            }

            // convert the dependencies into PEAR_Downloader_Package objects for the next time around
            $params[$i]->_downloadDeps = array();
            foreach ($newdeps as $dep) {
                $obj = new PEAR_Downloader_Package($params[$i]->getDownloader());
                if ($s = $params[$i]->explicitState()) {
                    $obj->setExplicitState($s);
                }

                PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                $e = $obj->fromDepURL($dep);
                PEAR::popErrorHandling();
                if (PEAR::isError($e)) {
                    if (!isset($options['soft'])) {
                        $obj->_downloader->log(0, $e->getMessage());
                    }
                    continue;
                }

                $e = $obj->detectDependencies($params);
                if (PEAR::isError($e)) {
                    if (!isset($options['soft'])) {
                        $obj->_downloader->log(0, $e->getMessage());
                    }
                }

                $newparams[] = $obj;
            }
        }

        if (count($newparams)) {
            foreach ($newparams as $i => $unused) {
                $params[] = &$newparams[$i];
            }
            return true;
        }

        return false;
    }


    /**
     */
    public static function willDownload($param, $params)
    {
        if (!is_array($params)) {
            return false;
        }

        foreach ($params as $obj) {
            if ($obj->isEqual($param)) {
                return true;
            }
        }

        return false;
    }

    /**
     * For simpler unit-testing
     * @param PEAR_Config
     * @param int
     * @param string
     */
    function &getPackagefileObject(&$c, $d)
    {
        $a = new PEAR_PackageFile($c, $d);
        return $a;
    }

    /**
     * This will retrieve from a local file if possible, and parse out
     * a group name as well.  The original parameter will be modified to reflect this.
     * @param string|array can be a parsed package name as well
     * @access private
     */
    function _fromFile(&$param)
    {
        $saveparam = $param;
        if (is_string($param) && substr($param, 0, 10) !== 'channel://') {
            if (!@file_exists($param)) {
                $test = explode('#', $param);
                $group = array_pop($test);
                if (@file_exists(implode('#', $test))) {
                    $this->setGroup($group);
                    $param = implode('#', $test);
                    $this->_explicitGroup = true;
                }
            }

            if (@is_file($param)) {
                $this->_type = 'local';
                $options = $this->_downloader->getOptions();
                $pkg = &$this->getPackagefileObject($this->_config, $this->_downloader->_debug);
                PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                $pf = &$pkg->fromAnyFile($param, PEAR_VALIDATE_INSTALLING);
                PEAR::popErrorHandling();
                if (PEAR::isError($pf)) {
                    $this->_valid = false;
                    $param = $saveparam;
                    return $pf;
                }
                $this->_packagefile = &$pf;
                if (!$this->getGroup()) {
                    $this->setGroup('default'); // install the default dependency group
                }
                return $this->_valid = true;
            }
        }
        $param = $saveparam;
        return $this->_valid = false;
    }

    function _fromUrl($param, $saveparam = '')
    {
        if (!is_array($param) && (preg_match('#^(http|https|ftp)://#', $param))) {
            $options = $this->_downloader->getOptions();
            $this->_type = 'url';
            $callback = $this->_downloader->ui ?
                array(&$this->_downloader, '_downloadCallback') : null;
            $this->_downloader->pushErrorHandling(PEAR_ERROR_RETURN);
            if (PEAR::isError($dir = $this->_downloader->getDownloadDir())) {
                $this->_downloader->popErrorHandling();
                return $dir;
            }

            $this->_downloader->log(3, 'Downloading "' . $param . '"');
            $file = $this->_downloader->downloadHttp($param, $this->_downloader->ui,
                $dir, $callback, null, false, $this->getChannel());
            $this->_downloader->popErrorHandling();
            if (PEAR::isError($file)) {
                if (!empty($saveparam)) {
                    $saveparam = ", cannot download \"$saveparam\"";
                }
                $err = PEAR::raiseError('Could not download from "' . $param .
                    '"' . $saveparam . ' (' . $file->getMessage() . ')');
                    return $err;
            }

            if ($this->_rawpackagefile) {
                require_once 'Archive/Tar.php';
                $tar = new Archive_Tar($file);
                $packagexml = $tar->extractInString('package2.xml');
                if (!$packagexml) {
                    $packagexml = $tar->extractInString('package.xml');
                }

                if (str_replace(array("\n", "\r"), array('',''), $packagexml) !=
                      str_replace(array("\n", "\r"), array('',''), $this->_rawpackagefile)) {
                    if ($this->getChannel() != 'pear.php.net') {
                        return PEAR::raiseError('CRITICAL ERROR: package.xml downloaded does ' .
                            'not match value returned from xml-rpc');
                    }

                    // be more lax for the existing PEAR packages that have not-ok
                    // characters in their package.xml
                    $this->_downloader->log(0, 'CRITICAL WARNING: The "' .
                        $this->getPackage() . '" package has invalid characters in its ' .
                        'package.xml.  The next version of PEAR may not be able to install ' .
                        'this package for security reasons.  Please open a bug report at ' .
                        'http://pear.php.net/package/' . $this->getPackage() . '/bugs');
                }
            }

            // whew, download worked!
            $pkg = &$this->getPackagefileObject($this->_config, $this->_downloader->debug);

            PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
            $pf = &$pkg->fromAnyFile($file, PEAR_VALIDATE_INSTALLING);
            PEAR::popErrorHandling();
            if (PEAR::isError($pf)) {
                if (is_array($pf->getUserInfo())) {
                    foreach ($pf->getUserInfo() as $err) {
                        if (is_array($err)) {
                            $err = $err['message'];
                        }

                        if (!isset($options['soft'])) {
                            $this->_downloader->log(0, "Validation Error: $err");
                        }
                    }
                }

                if (!isset($options['soft'])) {
                    $this->_downloader->log(0, $pf->getMessage());
                }

                ///FIXME need to pass back some error code that we can use to match with to cancel all further operations
                /// At least stop all deps of this package from being installed
                $out = $saveparam ? $saveparam : $param;
                $err = PEAR::raiseError('Download of "' . $out . '" succeeded, but it is not a valid package archive');
                $this->_valid = false;
                return $err;
            }

            $this->_packagefile = &$pf;
            $this->setGroup('default'); // install the default dependency group
            return $this->_valid = true;
        }

        return $this->_valid = false;
    }

    /**
     *
     * @param string|array pass in an array of format
     *                     array(
     *                      'package' => 'pname',
     *                     ['channel' => 'channame',]
     *                     ['version' => 'version',]
     *                     ['state' => 'state',])
     *                     or a string of format [channame/]pname[-version|-state]
     */
    function _fromString($param)
    {
        $options = $this->_downloader->getOptions();
        $channel = $this->_config->get('default_channel');
        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        $pname = $this->_registry->parsePackageName($param, $channel);
        PEAR::popErrorHandling();
        if (PEAR::isError($pname)) {
            if ($pname->getCode() == 'invalid') {
                $this->_valid = false;
                return false;
            }

            if ($pname->getCode() == 'channel') {
                $parsed = $pname->getUserInfo();
                if ($this->_downloader->discover($parsed['channel'])) {
                    if ($this->_config->get('auto_discover')) {
                        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                        $pname = $this->_registry->parsePackageName($param, $channel);
                        PEAR::popErrorHandling();
                    } else {
                        if (!isset($options['soft'])) {
                            $this->_downloader->log(0, 'Channel "' . $parsed['channel'] .
                                '" is not initialized, use ' .
                                '"pear channel-discover ' . $parsed['channel'] . '" to initialize' .
                                'or pear config-set auto_discover 1');
                        }
                    }
                }

                if (PEAR::isError($pname)) {
                    if (!isset($options['soft'])) {
                        $this->_downloader->log(0, $pname->getMessage());
                    }

                    if (is_array($param)) {
                        $param = $this->_registry->parsedPackageNameToString($param);
                    }

                    $err = PEAR::raiseError('invalid package name/package file "' . $param . '"');
                    $this->_valid = false;
                    return $err;
                }
            } else {
                if (!isset($options['soft'])) {
                    $this->_downloader->log(0, $pname->getMessage());
                }

                $err = PEAR::raiseError('invalid package name/package file "' . $param . '"');
                $this->_valid = false;
                return $err;
            }
        }

        if (!isset($this->_type)) {
            $this->_type = 'rest';
        }

        $this->_parsedname    = $pname;
        $this->_explicitState = isset($pname['state']) ? $pname['state'] : false;
        $this->_explicitGroup = isset($pname['group']) ? true : false;

        $info = $this->_downloader->_getPackageDownloadUrl($pname);
        if (PEAR::isError($info)) {
            if ($info->getCode() != -976 && $pname['channel'] == 'pear.php.net') {
                // try pecl
                $pname['channel'] = 'pecl.php.net';
                if ($test = $this->_downloader->_getPackageDownloadUrl($pname)) {
                    if (!PEAR::isError($test)) {
                        $info = PEAR::raiseError($info->getMessage() . ' - package ' .
                            $this->_registry->parsedPackageNameToString($pname, true) .
                            ' can be installed with "pecl install ' . $pname['package'] .
                            '"');
                    } else {
                        $pname['channel'] = 'pear.php.net';
                    }
                } else {
                    $pname['channel'] = 'pear.php.net';
                }
            }

            return $info;
        }

        $this->_rawpackagefile = $info['raw'];
        $ret = $this->_analyzeDownloadURL($info, $param, $pname);
        if (PEAR::isError($ret)) {
            return $ret;
        }

        if ($ret) {
            $this->_downloadURL = $ret;
            return $this->_valid = (bool) $ret;
        }
    }

    /**
     * @param array output of package.getDownloadURL
     * @param string|array|object information for detecting packages to be downloaded, and
     *                            for errors
     * @param array name information of the package
     * @param array|null packages to be downloaded
     * @param bool is this an optional dependency?
     * @param bool is this any kind of dependency?
     * @access private
     */
    function _analyzeDownloadURL($info, $param, $pname, $params = null, $optional = false,
                                 $isdependency = false)
    {
        if (!is_string($param) && PEAR_Downloader_Package::willDownload($param, $params)) {
            return false;
        }

        if ($info === false) {
            $saveparam = !is_string($param) ? ", cannot download \"$param\"" : '';

            // no releases exist
            return PEAR::raiseError('No releases for package "' .
                $this->_registry->parsedPackageNameToString($pname, true) . '" exist' . $saveparam);
        }

        if (strtolower($info['info']->getChannel()) != strtolower($pname['channel'])) {
            $err = false;
            if ($pname['channel'] == 'pecl.php.net') {
                if ($info['info']->getChannel() != 'pear.php.net') {
                    $err = true;
                }
            } elseif ($info['info']->getChannel() == 'pecl.php.net') {
                if ($pname['channel'] != 'pear.php.net') {
                    $err = true;
                }
            } else {
                $err = true;
            }

            if ($err) {
                return PEAR::raiseError('SECURITY ERROR: package in channel "' . $pname['channel'] .
                    '" retrieved another channel\'s name for download! ("' .
                    $info['info']->getChannel() . '")');
            }
        }

        $preferred_state = $this->_config->get('preferred_state');
        if (!isset($info['url'])) {
            $package_version = $this->_registry->packageInfo($info['info']->getPackage(),
            'version', $info['info']->getChannel());
            if ($this->isInstalled($info)) {
                if ($isdependency && version_compare($info['version'], $package_version, '<=')) {
                    // ignore bogus errors of "failed to download dependency"
                    // if it is already installed and the one that would be
                    // downloaded is older or the same version (Bug #7219)
                    return false;
                }
            }

            if ($info['version'] === $package_version) {
                if (!isset($options['soft'])) {
                    $this->_downloader->log(1, 'WARNING: failed to download ' . $pname['channel'] .
                        '/' . $pname['package'] . '-' . $package_version. ', additionally the suggested version' .
                        ' (' . $package_version . ') is the same as the locally installed one.');
                }

                return false;
            }

            if (version_compare($info['version'], $package_version, '<=')) {
                if (!isset($options['soft'])) {
                    $this->_downloader->log(1, 'WARNING: failed to download ' . $pname['channel'] .
                        '/' . $pname['package'] . '-' . $package_version . ', additionally the suggested version' .
                        ' (' . $info['version'] . ') is a lower version than the locally installed one (' . $package_version . ').');
                }

                return false;
            }

            $instead =  ', will instead download version ' . $info['version'] .
                        ', stability "' . $info['info']->getState() . '"';
            // releases exist, but we failed to get any
            if (isset($this->_downloader->_options['force'])) {
                if (isset($pname['version'])) {
                    $vs = ', version "' . $pname['version'] . '"';
                } elseif (isset($pname['state'])) {
                    $vs = ', stability "' . $pname['state'] . '"';
                } elseif ($param == 'dependency') {
                    if (!class_exists('PEAR_Common')) {
                        require_once 'PEAR/Common.php';
                    }

                    if (!in_array($info['info']->getState(),
                          PEAR_Common::betterStates($preferred_state, true))) {
                        if ($optional) {
                            // don't spit out confusing error message
                            return $this->_downloader->_getPackageDownloadUrl(
                                array('package' => $pname['package'],
                                      'channel' => $pname['channel'],
                                      'version' => $info['version']));
                        }
                        $vs = ' within preferred state "' . $preferred_state .
                            '"';
                    } else {
                        if (!class_exists('PEAR_Dependency2')) {
                            require_once 'PEAR/Dependency2.php';
                        }

                        if ($optional) {
                            // don't spit out confusing error message
                            return $this->_downloader->_getPackageDownloadUrl(
                                array('package' => $pname['package'],
                                      'channel' => $pname['channel'],
                                      'version' => $info['version']));
                        }
                        $vs = PEAR_Dependency2::_getExtraString($pname);
                        $instead = '';
                    }
                } else {
                    $vs = ' within preferred state "' . $preferred_state . '"';
                }

                if (!isset($options['soft'])) {
                    $this->_downloader->log(1, 'WARNING: failed to download ' . $pname['channel'] .
                        '/' . $pname['package'] . $vs . $instead);
                }

                // download the latest release
                return $this->_downloader->_getPackageDownloadUrl(
                    array('package' => $pname['package'],
                          'channel' => $pname['channel'],
                          'version' => $info['version']));
            } else {
                if (isset($info['php']) && $info['php']) {
                    $err = PEAR::raiseError('Failed to download ' .
                        $this->_registry->parsedPackageNameToString(
                            array('channel' => $pname['channel'],
                                  'package' => $pname['package']),
                                true) .
                        ', latest release is version ' . $info['php']['v'] .
                        ', but it requires PHP version "' .
                        $info['php']['m'] . '", use "' .
                        $this->_registry->parsedPackageNameToString(
                            array('channel' => $pname['channel'], 'package' => $pname['package'],
                            'version' => $info['php']['v'])) . '" to install',
                            PEAR_DOWNLOADER_PACKAGE_PHPVERSION);
                    return $err;
                }

                // construct helpful error message
                if (isset($pname['version'])) {
                    $vs = ', version "' . $pname['version'] . '"';
                } elseif (isset($pname['state'])) {
                    $vs = ', stability "' . $pname['state'] . '"';
                } elseif ($param == 'dependency') {
                    if (!class_exists('PEAR_Common')) {
                        require_once 'PEAR/Common.php';
                    }

                    if (!in_array($info['info']->getState(),
                          PEAR_Common::betterStates($preferred_state, true))) {
                        if ($optional) {
                            // don't spit out confusing error message, and don't die on
                            // optional dep failure!
                            return $this->_downloader->_getPackageDownloadUrl(
                                array('package' => $pname['package'],
                                      'channel' => $pname['channel'],
                                      'version' => $info['version']));
                        }
                        $vs = ' within preferred state "' . $preferred_state . '"';
                    } else {
                        if (!class_exists('PEAR_Dependency2')) {
                            require_once 'PEAR/Dependency2.php';
                        }

                        if ($optional) {
                            // don't spit out confusing error message, and don't die on
                            // optional dep failure!
                            return $this->_downloader->_getPackageDownloadUrl(
                                array('package' => $pname['package'],
                                      'channel' => $pname['channel'],
                                      'version' => $info['version']));
                        }
                        $vs = PEAR_Dependency2::_getExtraString($pname);
                    }
                } else {
                    $vs = ' within preferred state "' . $this->_downloader->config->get('preferred_state') . '"';
                }

                $options = $this->_downloader->getOptions();
                // this is only set by the "download-all" command
                if (isset($options['ignorepreferred_state'])) {
                    $err = PEAR::raiseError(
                        'Failed to download ' . $this->_registry->parsedPackageNameToString(
                            array('channel' => $pname['channel'], 'package' => $pname['package']),
                                true)
                         . $vs .
                        ', latest release is version ' . $info['version'] .
                        ', stability "' . $info['info']->getState() . '", use "' .
                        $this->_registry->parsedPackageNameToString(
                            array('channel' => $pname['channel'], 'package' => $pname['package'],
                            'version' => $info['version'])) . '" to install',
                            PEAR_DOWNLOADER_PACKAGE_STATE);
                    return $err;
                }

                // Checks if the user has a package installed already and checks the release against
                // the state against the installed package, this allows upgrades for packages
                // with lower stability than the preferred_state
                $stability = $this->_registry->packageInfo($pname['package'], 'stability', $pname['channel']);
                if (!$this->isInstalled($info)
                    || !in_array($info['info']->getState(), PEAR_Common::betterStates($stability['release'], true))
                ) {
                    $err = PEAR::raiseError(
                        'Failed to download ' . $this->_registry->parsedPackageNameToString(
                            array('channel' => $pname['channel'], 'package' => $pname['package']),
                                true)
                         . $vs .
                        ', latest release is version ' . $info['version'] .
                        ', stability "' . $info['info']->getState() . '", use "' .
                        $this->_registry->parsedPackageNameToString(
                            array('channel' => $pname['channel'], 'package' => $pname['package'],
                            'version' => $info['version'])) . '" to install');
                    return $err;
                }
            }
        }

        if (isset($info['deprecated']) && $info['deprecated']) {
            $this->_downloader->log(0,
                'WARNING: "' .
                    $this->_registry->parsedPackageNameToString(
                            array('channel' => $info['info']->getChannel(),
                                  'package' => $info['info']->getPackage()), true) .
                '" is deprecated in favor of "' .
                    $this->_registry->parsedPackageNameToString($info['deprecated'], true) .
                '"');
        }

        return $info;
    }
}
PKs�Z.�4���PEAR/Frontend.phpnu�[���<?php
/**
 * PEAR_Frontend, the singleton-based frontend for user input/output
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.4.0a1
 */

/**
 * Include error handling
 */
//require_once 'PEAR.php';

/**
 * Which user interface class is being used.
 * @var string class name
 */
$GLOBALS['_PEAR_FRONTEND_CLASS'] = 'PEAR_Frontend_CLI';

/**
 * Instance of $_PEAR_Command_uiclass.
 * @var object
 */
$GLOBALS['_PEAR_FRONTEND_SINGLETON'] = null;

/**
 * Singleton-based frontend for PEAR user input/output
 *
 * @category   pear
 * @package    PEAR
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.4.0a1
 */
class PEAR_Frontend extends PEAR
{
    /**
     * Retrieve the frontend object
     * @return PEAR_Frontend_CLI|PEAR_Frontend_Web|PEAR_Frontend_Gtk
     */
    public static function &singleton($type = null)
    {
        if ($type === null) {
            if (!isset($GLOBALS['_PEAR_FRONTEND_SINGLETON'])) {
                $a = false;
                return $a;
            }
            return $GLOBALS['_PEAR_FRONTEND_SINGLETON'];
        }

        $a = PEAR_Frontend::setFrontendClass($type);
        return $a;
    }

    /**
     * Set the frontend class that will be used by calls to {@link singleton()}
     *
     * Frontends are expected to conform to the PEAR naming standard of
     * _ => DIRECTORY_SEPARATOR (PEAR_Frontend_CLI is in PEAR/Frontend/CLI.php)
     * @param string $uiclass full class name
     * @return PEAR_Frontend
     */
    public static function &setFrontendClass($uiclass)
    {
        if (is_object($GLOBALS['_PEAR_FRONTEND_SINGLETON']) &&
              is_a($GLOBALS['_PEAR_FRONTEND_SINGLETON'], $uiclass)) {
            return $GLOBALS['_PEAR_FRONTEND_SINGLETON'];
        }

        if (!class_exists($uiclass)) {
            $file = str_replace('_', '/', $uiclass) . '.php';
            if (PEAR_Frontend::isIncludeable($file)) {
                include_once $file;
            }
        }

        if (class_exists($uiclass)) {
            $obj = new $uiclass;
            // quick test to see if this class implements a few of the most
            // important frontend methods
            if (is_a($obj, 'PEAR_Frontend')) {
                $GLOBALS['_PEAR_FRONTEND_SINGLETON'] = &$obj;
                $GLOBALS['_PEAR_FRONTEND_CLASS'] = $uiclass;
                return $obj;
            }

            $err = PEAR::raiseError("not a frontend class: $uiclass");
            return $err;
        }

        $err = PEAR::raiseError("no such class: $uiclass");
        return $err;
    }

    /**
     * Set the frontend class that will be used by calls to {@link singleton()}
     *
     * Frontends are expected to be a descendant of PEAR_Frontend
     * @param PEAR_Frontend
     * @return PEAR_Frontend
     */
    public static function &setFrontendObject($uiobject)
    {
        if (is_object($GLOBALS['_PEAR_FRONTEND_SINGLETON']) &&
              is_a($GLOBALS['_PEAR_FRONTEND_SINGLETON'], get_class($uiobject))) {
            return $GLOBALS['_PEAR_FRONTEND_SINGLETON'];
        }

        if (!is_a($uiobject, 'PEAR_Frontend')) {
            $err = PEAR::raiseError('not a valid frontend class: (' .
                get_class($uiobject) . ')');
            return $err;
        }

        $GLOBALS['_PEAR_FRONTEND_SINGLETON'] = &$uiobject;
        $GLOBALS['_PEAR_FRONTEND_CLASS'] = get_class($uiobject);
        return $uiobject;
    }

    /**
     * @param string $path relative or absolute include path
     * @return boolean
     */
    public static function isIncludeable($path)
    {
        if (file_exists($path) && is_readable($path)) {
            return true;
        }

        $fp = @fopen($path, 'r', true);
        if ($fp) {
            fclose($fp);
            return true;
        }

        return false;
    }

    /**
     * @param PEAR_Config
     */
    function setConfig(&$config)
    {
    }

    /**
     * This can be overridden to allow session-based temporary file management
     *
     * By default, all files are deleted at the end of a session.  The web installer
     * needs to be able to sustain a list over many sessions in order to support
     * user interaction with install scripts
     */
    static function addTempFile($file)
    {
        $GLOBALS['_PEAR_Common_tempfiles'][] = $file;
    }

    /**
     * Log an action
     *
     * @param string $msg the message to log
     * @param boolean $append_crlf
     * @return boolean true
     * @abstract
     */
    function log($msg, $append_crlf = true)
    {
    }

    /**
     * Run a post-installation script
     *
     * @param array $scripts array of post-install scripts
     * @abstract
     */
    function runPostinstallScripts(&$scripts)
    {
    }

    /**
     * Display human-friendly output formatted depending on the
     * $command parameter.
     *
     * This should be able to handle basic output data with no command
     * @param mixed  $data    data structure containing the information to display
     * @param string $command command from which this method was called
     * @abstract
     */
    function outputData($data, $command = '_default')
    {
    }

    /**
     * Display a modal form dialog and return the given input
     *
     * A frontend that requires multiple requests to retrieve and process
     * data must take these needs into account, and implement the request
     * handling code.
     * @param string $command  command from which this method was called
     * @param array  $prompts  associative array. keys are the input field names
     *                         and values are the description
     * @param array  $types    array of input field types (text, password,
     *                         etc.) keys have to be the same like in $prompts
     * @param array  $defaults array of default values. again keys have
     *                         to be the same like in $prompts.  Do not depend
     *                         on a default value being set.
     * @return array input sent by the user
     * @abstract
     */
    function userDialog($command, $prompts, $types = array(), $defaults = array())
    {
    }
}
PKs�Z،�w��PEAR/Installer.phpnu�[���<?php
/**
 * PEAR_Installer
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Tomas V.V. Cox <cox@idecnet.com>
 * @author     Martin Jansen <mj@php.net>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 0.1
 */

/**
 * Used for installation groups in package.xml 2.0 and platform exceptions
 */
require_once 'OS/Guess.php';
require_once 'PEAR/Downloader.php';

define('PEAR_INSTALLER_NOBINARY', -240);
/**
 * Administration class used to install PEAR packages and maintain the
 * installed package database.
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Tomas V.V. Cox <cox@idecnet.com>
 * @author     Martin Jansen <mj@php.net>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 0.1
 */
class PEAR_Installer extends PEAR_Downloader
{
    // {{{ properties

    /** name of the package directory, for example Foo-1.0
     * @var string
     */
    var $pkgdir;

    /** directory where PHP code files go
     * @var string
     */
    var $phpdir;

    /** directory where PHP extension files go
     * @var string
     */
    var $extdir;

    /** directory where documentation goes
     * @var string
     */
    var $docdir;

    /** installation root directory (ala PHP's INSTALL_ROOT or
     * automake's DESTDIR
     * @var string
     */
    var $installroot = '';

    /** debug level
     * @var int
     */
    var $debug = 1;

    /** temporary directory
     * @var string
     */
    var $tmpdir;

    /**
     * PEAR_Registry object used by the installer
     * @var PEAR_Registry
     */
    var $registry;

    /**
     * array of PEAR_Downloader_Packages
     * @var array
     */
    var $_downloadedPackages;

    /** List of file transactions queued for an install/upgrade/uninstall.
     *
     *  Format:
     *    array(
     *      0 => array("rename => array("from-file", "to-file")),
     *      1 => array("delete" => array("file-to-delete")),
     *      ...
     *    )
     *
     * @var array
     */
    var $file_operations = array();

    // }}}

    // {{{ constructor

    /**
     * PEAR_Installer constructor.
     *
     * @param object $ui user interface object (instance of PEAR_Frontend_*)
     *
     * @access public
     */
    function __construct(&$ui)
    {
        parent::__construct($ui, array(), null);
        $this->setFrontendObject($ui);
        $this->debug = $this->config->get('verbose');
    }

    function setOptions($options)
    {
        $this->_options = $options;
    }

    function setConfig(&$config)
    {
        $this->config    = &$config;
        $this->_registry = &$config->getRegistry();
    }

    // }}}

    function _removeBackups($files)
    {
        foreach ($files as $path) {
            $this->addFileOperation('removebackup', array($path));
        }
    }

    // {{{ _deletePackageFiles()

    /**
     * Delete a package's installed files, does not remove empty directories.
     *
     * @param string package name
     * @param string channel name
     * @param bool if true, then files are backed up first
     * @return bool TRUE on success, or a PEAR error on failure
     * @access protected
     */
    function _deletePackageFiles($package, $channel = false, $backup = false)
    {
        if (!$channel) {
            $channel = 'pear.php.net';
        }

        if (!strlen($package)) {
            return $this->raiseError("No package to uninstall given");
        }

        if (strtolower($package) == 'pear' && $channel == 'pear.php.net') {
            // to avoid race conditions, include all possible needed files
            require_once 'PEAR/Task/Common.php';
            require_once 'PEAR/Task/Replace.php';
            require_once 'PEAR/Task/Unixeol.php';
            require_once 'PEAR/Task/Windowseol.php';
            require_once 'PEAR/PackageFile/v1.php';
            require_once 'PEAR/PackageFile/v2.php';
            require_once 'PEAR/PackageFile/Generator/v1.php';
            require_once 'PEAR/PackageFile/Generator/v2.php';
        }

        $filelist = $this->_registry->packageInfo($package, 'filelist', $channel);
        if ($filelist == null) {
            return $this->raiseError("$channel/$package not installed");
        }

        $ret = array();
        foreach ($filelist as $file => $props) {
            if (empty($props['installed_as'])) {
                continue;
            }

            $path = $props['installed_as'];
            if ($backup) {
                $this->addFileOperation('backup', array($path));
                $ret[] = $path;
            }

            $this->addFileOperation('delete', array($path));
        }

        if ($backup) {
            return $ret;
        }

        return true;
    }

    // }}}
    // {{{ _installFile()

    /**
     * @param string filename
     * @param array attributes from <file> tag in package.xml
     * @param string path to install the file in
     * @param array options from command-line
     * @access private
     */
    function _installFile($file, $atts, $tmp_path, $options)
    {
        // {{{ return if this file is meant for another platform
        static $os;
        if (!isset($this->_registry)) {
            $this->_registry = &$this->config->getRegistry();
        }

        if (isset($atts['platform'])) {
            if (empty($os)) {
                $os = new OS_Guess();
            }

            if (strlen($atts['platform']) && $atts['platform'][0] == '!') {
                $negate   = true;
                $platform = substr($atts['platform'], 1);
            } else {
                $negate    = false;
                $platform = $atts['platform'];
            }

            if ((bool) $os->matchSignature($platform) === $negate) {
                $this->log(3, "skipped $file (meant for $atts[platform], we are ".$os->getSignature().")");
                return PEAR_INSTALLER_SKIPPED;
            }
        }
        // }}}

        $channel = $this->pkginfo->getChannel();
        // {{{ assemble the destination paths
        switch ($atts['role']) {
            case 'src':
            case 'extsrc':
                $this->source_files++;
                return;
            case 'doc':
            case 'data':
            case 'test':
                $dest_dir = $this->config->get($atts['role'] . '_dir', null, $channel) .
                            DIRECTORY_SEPARATOR . $this->pkginfo->getPackage();
                unset($atts['baseinstalldir']);
                break;
            case 'ext':
            case 'php':
                $dest_dir = $this->config->get($atts['role'] . '_dir', null, $channel);
                break;
            case 'script':
                $dest_dir = $this->config->get('bin_dir', null, $channel);
                break;
            default:
                return $this->raiseError("Invalid role `$atts[role]' for file $file");
        }

        $save_destdir = $dest_dir;
        if (!empty($atts['baseinstalldir'])) {
            $dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir'];
        }

        if (dirname($file) != '.' && empty($atts['install-as'])) {
            $dest_dir .= DIRECTORY_SEPARATOR . dirname($file);
        }

        if (empty($atts['install-as'])) {
            $dest_file = $dest_dir . DIRECTORY_SEPARATOR . basename($file);
        } else {
            $dest_file = $dest_dir . DIRECTORY_SEPARATOR . $atts['install-as'];
        }
        $orig_file = $tmp_path . DIRECTORY_SEPARATOR . $file;

        // Clean up the DIRECTORY_SEPARATOR mess
        $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
        list($dest_file, $orig_file) = preg_replace(array('!\\\\+!', '!/!', "!$ds2+!"),
                                                    array(DIRECTORY_SEPARATOR,
                                                          DIRECTORY_SEPARATOR,
                                                          DIRECTORY_SEPARATOR),
                                                    array($dest_file, $orig_file));
        $final_dest_file = $installed_as = $dest_file;
        if (isset($this->_options['packagingroot'])) {
            $installedas_dest_dir  = dirname($final_dest_file);
            $installedas_dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file);
            $final_dest_file = $this->_prependPath($final_dest_file, $this->_options['packagingroot']);
        } else {
            $installedas_dest_dir  = dirname($final_dest_file);
            $installedas_dest_file = $installedas_dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file);
        }

        $dest_dir  = dirname($final_dest_file);
        $dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file);
        if (preg_match('~/\.\.(/|\\z)|^\.\./~', str_replace('\\', '/', $dest_file))) {
            return $this->raiseError("SECURITY ERROR: file $file (installed to $dest_file) contains parent directory reference ..", PEAR_INSTALLER_FAILED);
        }
        // }}}

        if (empty($this->_options['register-only']) &&
              (!file_exists($dest_dir) || !is_dir($dest_dir))) {
            if (!$this->mkDirHier($dest_dir)) {
                return $this->raiseError("failed to mkdir $dest_dir",
                                         PEAR_INSTALLER_FAILED);
            }
            $this->log(3, "+ mkdir $dest_dir");
        }

        // pretty much nothing happens if we are only registering the install
        if (empty($this->_options['register-only'])) {
            if (empty($atts['replacements'])) {
                if (!file_exists($orig_file)) {
                    return $this->raiseError("file $orig_file does not exist",
                                             PEAR_INSTALLER_FAILED);
                }

                if (!@copy($orig_file, $dest_file)) {
                    return $this->raiseError(
                        "failed to write $dest_file: " . error_get_last()["message"],
                        PEAR_INSTALLER_FAILED);
                }

                $this->log(3, "+ cp $orig_file $dest_file");
                if (isset($atts['md5sum'])) {
                    $md5sum = md5_file($dest_file);
                }
            } else {
                // {{{ file with replacements
                if (!file_exists($orig_file)) {
                    return $this->raiseError("file does not exist",
                                             PEAR_INSTALLER_FAILED);
                }

                $contents = file_get_contents($orig_file);
                if ($contents === false) {
                    $contents = '';
                }

                if (isset($atts['md5sum'])) {
                    $md5sum = md5($contents);
                }

                $subst_from = $subst_to = array();
                foreach ($atts['replacements'] as $a) {
                    $to = '';
                    if ($a['type'] == 'php-const') {
                        if (preg_match('/^[a-z0-9_]+\\z/i', $a['to'])) {
                            eval("\$to = $a[to];");
                        } else {
                            if (!isset($options['soft'])) {
                                $this->log(0, "invalid php-const replacement: $a[to]");
                            }
                            continue;
                        }
                    } elseif ($a['type'] == 'pear-config') {
                        if ($a['to'] == 'master_server') {
                            $chan = $this->_registry->getChannel($channel);
                            if (!PEAR::isError($chan)) {
                                $to = $chan->getServer();
                            } else {
                                $to = $this->config->get($a['to'], null, $channel);
                            }
                        } else {
                            $to = $this->config->get($a['to'], null, $channel);
                        }
                        if (is_null($to)) {
                            if (!isset($options['soft'])) {
                                $this->log(0, "invalid pear-config replacement: $a[to]");
                            }
                            continue;
                        }
                    } elseif ($a['type'] == 'package-info') {
                        if ($t = $this->pkginfo->packageInfo($a['to'])) {
                            $to = $t;
                        } else {
                            if (!isset($options['soft'])) {
                                $this->log(0, "invalid package-info replacement: $a[to]");
                            }
                            continue;
                        }
                    }
                    if (!is_null($to)) {
                        $subst_from[] = $a['from'];
                        $subst_to[] = $to;
                    }
                }

                $this->log(3, "doing ".sizeof($subst_from)." substitution(s) for $final_dest_file");
                if (sizeof($subst_from)) {
                    $contents = str_replace($subst_from, $subst_to, $contents);
                }

                $wp = @fopen($dest_file, "wb");
                if (!is_resource($wp)) {
                    return $this->raiseError(
                        "failed to create $dest_file: " . error_get_last()["message"],
                        PEAR_INSTALLER_FAILED);
                }

                if (@fwrite($wp, $contents) === false) {
                    return $this->raiseError(
                        "failed writing to $dest_file: " . error_get_last()["message"],
                        PEAR_INSTALLER_FAILED);
                }

                fclose($wp);
                // }}}
            }

            // {{{ check the md5
            if (isset($md5sum)) {
                if (strtolower($md5sum) === strtolower($atts['md5sum'])) {
                    $this->log(2, "md5sum ok: $final_dest_file");
                } else {
                    if (empty($options['force'])) {
                        // delete the file
                        if (file_exists($dest_file)) {
                            unlink($dest_file);
                        }

                        if (!isset($options['ignore-errors'])) {
                            return $this->raiseError("bad md5sum for file $final_dest_file",
                                                 PEAR_INSTALLER_FAILED);
                        }

                        if (!isset($options['soft'])) {
                            $this->log(0, "warning : bad md5sum for file $final_dest_file");
                        }
                    } else {
                        if (!isset($options['soft'])) {
                            $this->log(0, "warning : bad md5sum for file $final_dest_file");
                        }
                    }
                }
            }
            // }}}
            // {{{ set file permissions
            if (!OS_WINDOWS) {
                if ($atts['role'] == 'script') {
                    $mode = 0777 & ~(int)octdec($this->config->get('umask'));
                    $this->log(3, "+ chmod +x $dest_file");
                } else {
                    $mode = 0666 & ~(int)octdec($this->config->get('umask'));
                }

                if ($atts['role'] != 'src') {
                    $this->addFileOperation("chmod", array($mode, $dest_file));
                    if (!@chmod($dest_file, $mode)) {
                        if (!isset($options['soft'])) {
                            $this->log(0, "failed to change mode of $dest_file: " .
                                          error_get_last()["message"]);
                        }
                    }
                }
            }
            // }}}

            if ($atts['role'] == 'src') {
                rename($dest_file, $final_dest_file);
                $this->log(2, "renamed source file $dest_file to $final_dest_file");
            } else {
                $this->addFileOperation("rename", array($dest_file, $final_dest_file,
                    $atts['role'] == 'ext'));
            }
        }

        // Store the full path where the file was installed for easy unistall
        if ($atts['role'] != 'script') {
            $loc = $this->config->get($atts['role'] . '_dir');
        } else {
            $loc = $this->config->get('bin_dir');
        }

        if ($atts['role'] != 'src') {
            $this->addFileOperation("installed_as", array($file, $installed_as,
                                    $loc,
                                    dirname(substr($installedas_dest_file, strlen($loc)))));
        }

        //$this->log(2, "installed: $dest_file");
        return PEAR_INSTALLER_OK;
    }

    // }}}
    // {{{ _installFile2()

    /**
     * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
     * @param string filename
     * @param array attributes from <file> tag in package.xml
     * @param string path to install the file in
     * @param array options from command-line
     * @access private
     */
    function _installFile2(&$pkg, $file, &$real_atts, $tmp_path, $options)
    {
        $atts = $real_atts;
        if (!isset($this->_registry)) {
            $this->_registry = &$this->config->getRegistry();
        }

        $channel = $pkg->getChannel();
        // {{{ assemble the destination paths
        if (!in_array($atts['attribs']['role'],
              PEAR_Installer_Role::getValidRoles($pkg->getPackageType()))) {
            return $this->raiseError('Invalid role `' . $atts['attribs']['role'] .
                    "' for file $file");
        }

        $role = &PEAR_Installer_Role::factory($pkg, $atts['attribs']['role'], $this->config);
        $err  = $role->setup($this, $pkg, $atts['attribs'], $file);
        if (PEAR::isError($err)) {
            return $err;
        }

        if (!$role->isInstallable()) {
            return;
        }

        $info = $role->processInstallation($pkg, $atts['attribs'], $file, $tmp_path);
        if (PEAR::isError($info)) {
            return $info;
        }

        list($save_destdir, $dest_dir, $dest_file, $orig_file) = $info;
        if (preg_match('~/\.\.(/|\\z)|^\.\./~', str_replace('\\', '/', $dest_file))) {
            return $this->raiseError("SECURITY ERROR: file $file (installed to $dest_file) contains parent directory reference ..", PEAR_INSTALLER_FAILED);
        }

        $final_dest_file = $installed_as = $dest_file;
        if (isset($this->_options['packagingroot'])) {
            $final_dest_file = $this->_prependPath($final_dest_file,
                $this->_options['packagingroot']);
        }

        $dest_dir  = dirname($final_dest_file);
        $dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file);
        // }}}

        if (empty($this->_options['register-only'])) {
            if (!file_exists($dest_dir) || !is_dir($dest_dir)) {
                if (!$this->mkDirHier($dest_dir)) {
                    return $this->raiseError("failed to mkdir $dest_dir",
                                             PEAR_INSTALLER_FAILED);
                }
                $this->log(3, "+ mkdir $dest_dir");
            }
        }

        $attribs = $atts['attribs'];
        unset($atts['attribs']);
        // pretty much nothing happens if we are only registering the install
        if (empty($this->_options['register-only'])) {
            if (!count($atts)) { // no tasks
                if (!file_exists($orig_file)) {
                    return $this->raiseError("file $orig_file does not exist",
                                             PEAR_INSTALLER_FAILED);
                }

                if (!@copy($orig_file, $dest_file)) {
                    return $this->raiseError(
                        "failed to write $dest_file: " . error_get_last()["message"],
                        PEAR_INSTALLER_FAILED);
                }

                $this->log(3, "+ cp $orig_file $dest_file");
                if (isset($attribs['md5sum'])) {
                    $md5sum = md5_file($dest_file);
                }
            } else { // file with tasks
                if (!file_exists($orig_file)) {
                    return $this->raiseError("file $orig_file does not exist",
                                             PEAR_INSTALLER_FAILED);
                }

                $contents = file_get_contents($orig_file);
                if ($contents === false) {
                    $contents = '';
                }

                if (isset($attribs['md5sum'])) {
                    $md5sum = md5($contents);
                }

                foreach ($atts as $tag => $raw) {
                    $tag = str_replace(array($pkg->getTasksNs() . ':', '-'), array('', '_'), $tag);
                    $task = "PEAR_Task_$tag";
                    $task = new $task($this->config, $this, PEAR_TASK_INSTALL);
                    if (!$task->isScript()) { // scripts are only handled after installation
                        $task->init($raw, $attribs, $pkg->getLastInstalledVersion());
                        $res = $task->startSession($pkg, $contents, $final_dest_file);
                        if ($res === false) {
                            continue; // skip this file
                        }

                        if (PEAR::isError($res)) {
                            return $res;
                        }

                        $contents = $res; // save changes
                    }

                    $wp = @fopen($dest_file, "wb");
                    if (!is_resource($wp)) {
                        return $this->raiseError(
                            "failed to create $dest_file: " . error_get_last()["message"],
                            PEAR_INSTALLER_FAILED);
                    }

                    if (fwrite($wp, $contents) === false) {
                        return $this->raiseError(
                            "failed writing to $dest_file: " . error_get_last()["message"],
                            PEAR_INSTALLER_FAILED);
                    }

                    fclose($wp);
                }
            }

            // {{{ check the md5
            if (isset($md5sum)) {
                // Make sure the original md5 sum matches with expected
                if (strtolower($md5sum) === strtolower($attribs['md5sum'])) {
                    $this->log(2, "md5sum ok: $final_dest_file");

                    if (isset($contents)) {
                        // set md5 sum based on $content in case any tasks were run.
                        $real_atts['attribs']['md5sum'] = md5($contents);
                    }
                } else {
                    if (empty($options['force'])) {
                        // delete the file
                        if (file_exists($dest_file)) {
                            unlink($dest_file);
                        }

                        if (!isset($options['ignore-errors'])) {
                            return $this->raiseError("bad md5sum for file $final_dest_file",
                                                     PEAR_INSTALLER_FAILED);
                        }

                        if (!isset($options['soft'])) {
                            $this->log(0, "warning : bad md5sum for file $final_dest_file");
                        }
                    } else {
                        if (!isset($options['soft'])) {
                            $this->log(0, "warning : bad md5sum for file $final_dest_file");
                        }
                    }
                }
            } else {
                $real_atts['attribs']['md5sum'] = md5_file($dest_file);
            }

            // }}}
            // {{{ set file permissions
            if (!OS_WINDOWS) {
                if ($role->isExecutable()) {
                    $mode = 0777 & ~(int)octdec($this->config->get('umask'));
                    $this->log(3, "+ chmod +x $dest_file");
                } else {
                    $mode = 0666 & ~(int)octdec($this->config->get('umask'));
                }

                if ($attribs['role'] != 'src') {
                    $this->addFileOperation("chmod", array($mode, $dest_file));
                    if (!@chmod($dest_file, $mode)) {
                        if (!isset($options['soft'])) {
                            $this->log(0, "failed to change mode of $dest_file: " .
                                          error_get_last()["message"]);
                        }
                    }
                }
            }
            // }}}

            if ($attribs['role'] == 'src') {
                rename($dest_file, $final_dest_file);
                $this->log(2, "renamed source file $dest_file to $final_dest_file");
            } else {
                $this->addFileOperation("rename", array($dest_file, $final_dest_file, $role->isExtension()));
            }
        }

        // Store the full path where the file was installed for easy uninstall
        if ($attribs['role'] != 'src') {
            $loc = $this->config->get($role->getLocationConfig(), null, $channel);
            $this->addFileOperation('installed_as', array($file, $installed_as,
                                $loc,
                                dirname(substr($installed_as, strlen($loc)))));
        }

        //$this->log(2, "installed: $dest_file");
        return PEAR_INSTALLER_OK;
    }

    // }}}
    // {{{ addFileOperation()

    /**
     * Add a file operation to the current file transaction.
     *
     * @see startFileTransaction()
     * @param string $type This can be one of:
     *    - rename:  rename a file ($data has 3 values)
     *    - backup:  backup an existing file ($data has 1 value)
     *    - removebackup:  clean up backups created during install ($data has 1 value)
     *    - chmod:   change permissions on a file ($data has 2 values)
     *    - delete:  delete a file ($data has 1 value)
     *    - rmdir:   delete a directory if empty ($data has 1 value)
     *    - installed_as: mark a file as installed ($data has 4 values).
     * @param array $data For all file operations, this array must contain the
     *    full path to the file or directory that is being operated on.  For
     *    the rename command, the first parameter must be the file to rename,
     *    the second its new name, the third whether this is a PHP extension.
     *
     *    The installed_as operation contains 4 elements in this order:
     *    1. Filename as listed in the filelist element from package.xml
     *    2. Full path to the installed file
     *    3. Full path from the php_dir configuration variable used in this
     *       installation
     *    4. Relative path from the php_dir that this file is installed in
     */
    function addFileOperation($type, $data)
    {
        if (!is_array($data)) {
            return $this->raiseError('Internal Error: $data in addFileOperation'
                . ' must be an array, was ' . gettype($data));
        }

        if ($type == 'chmod') {
            $octmode = decoct($data[0]);
            $this->log(3, "adding to transaction: $type $octmode $data[1]");
        } else {
            $this->log(3, "adding to transaction: $type " . implode(" ", $data));
        }
        $this->file_operations[] = array($type, $data);
    }

    // }}}
    // {{{ startFileTransaction()

    function startFileTransaction($rollback_in_case = false)
    {
        if (count($this->file_operations) && $rollback_in_case) {
            $this->rollbackFileTransaction();
        }
        $this->file_operations = array();
    }

    // }}}
    // {{{ commitFileTransaction()

    function commitFileTransaction()
    {
        // {{{ first, check permissions and such manually
        $errors = array();
        foreach ($this->file_operations as $key => $tr) {
            list($type, $data) = $tr;
            switch ($type) {
                case 'rename':
                    if (!file_exists($data[0])) {
                        $errors[] = "cannot rename file $data[0], doesn't exist";
                    }

                    // check that dest dir. is writable
                    if (!is_writable(dirname($data[1]))) {
                        $errors[] = "permission denied ($type): $data[1]";
                    }
                    break;
                case 'chmod':
                    // check that file is writable
                    if (!is_writable($data[1])) {
                        $errors[] = "permission denied ($type): $data[1] " . decoct($data[0]);
                    }
                    break;
                case 'delete':
                    if (!file_exists($data[0])) {
                        $this->log(2, "warning: file $data[0] doesn't exist, can't be deleted");
                    }
                    // check that directory is writable
                    if (file_exists($data[0])) {
                        if (!is_writable(dirname($data[0]))) {
                            $errors[] = "permission denied ($type): $data[0]";
                        } else {
                            // make sure the file to be deleted can be opened for writing
                            $fp = false;
                            if (!is_dir($data[0]) &&
                                  (!is_writable($data[0]) || !($fp = @fopen($data[0], 'a')))) {
                                $errors[] = "permission denied ($type): $data[0]";
                            } elseif ($fp) {
                                fclose($fp);
                            }
                        }

                        /* Verify we are not deleting a file owned by another package
                         * This can happen when a file moves from package A to B in
                         * an upgrade ala http://pear.php.net/17986
                         */
                        $info = array(
                            'package' => strtolower($this->pkginfo->getName()),
                            'channel' => strtolower($this->pkginfo->getChannel()),
                        );
                        $result = $this->_registry->checkFileMap($data[0], $info, '1.1');
                        if (is_array($result)) {
                            $res = array_diff($result, $info);
                            if (!empty($res)) {
                                $new = $this->_registry->getPackage($result[1], $result[0]);
                                $this->file_operations[$key] = false;
                                $pkginfoName = $this->pkginfo->getName();
                                $newChannel  = $new->getChannel();
                                $newPackage  = $new->getName();
                                $this->log(3, "file $data[0] was scheduled for removal from $pkginfoName but is owned by $newChannel/$newPackage, removal has been cancelled.");
                            }
                        }
                    }
                    break;
            }

        }
        // }}}

        $n = count($this->file_operations);
        $this->log(2, "about to commit $n file operations for " . $this->pkginfo->getName());

        $m = count($errors);
        if ($m > 0) {
            foreach ($errors as $error) {
                if (!isset($this->_options['soft'])) {
                    $this->log(1, $error);
                }
            }

            if (!isset($this->_options['ignore-errors'])) {
                return false;
            }
        }

        $this->_dirtree = array();
        // {{{ really commit the transaction
        foreach ($this->file_operations as $i => $tr) {
            if (!$tr) {
                // support removal of non-existing backups
                continue;
            }

            list($type, $data) = $tr;
            switch ($type) {
                case 'backup':
                    if (!file_exists($data[0])) {
                        $this->file_operations[$i] = false;
                        break;
                    }

                    if (!@copy($data[0], $data[0] . '.bak')) {
                        $this->log(1, 'Could not copy ' . $data[0] . ' to ' . $data[0] .
                            '.bak ' . error_get_last()["message"]);
                        return false;
                    }
                    $this->log(3, "+ backup $data[0] to $data[0].bak");
                    break;
                case 'removebackup':
                    if (file_exists($data[0] . '.bak') && is_writable($data[0] . '.bak')) {
                        unlink($data[0] . '.bak');
                        $this->log(3, "+ rm backup of $data[0] ($data[0].bak)");
                    }
                    break;
                case 'rename':
                    $test = file_exists($data[1]) ? @unlink($data[1]) : null;
                    if (!$test && file_exists($data[1])) {
                        if ($data[2]) {
                            $extra = ', this extension must be installed manually.  Rename to "' .
                                basename($data[1]) . '"';
                        } else {
                            $extra = '';
                        }

                        if (!isset($this->_options['soft'])) {
                            $this->log(1, 'Could not delete ' . $data[1] . ', cannot rename ' .
                                $data[0] . $extra);
                        }

                        if (!isset($this->_options['ignore-errors'])) {
                            return false;
                        }
                    }

                    // permissions issues with rename - copy() is far superior
                    $perms = @fileperms($data[0]);
                    if (!@copy($data[0], $data[1])) {
                        $this->log(1, 'Could not rename ' . $data[0] . ' to ' . $data[1] .
                            ' ' . error_get_last()["message"]);
                        return false;
                    }

                    // copy over permissions, otherwise they are lost
                    @chmod($data[1], $perms);
                    @unlink($data[0]);
                    $this->log(3, "+ mv $data[0] $data[1]");
                    break;
                case 'chmod':
                    if (!@chmod($data[1], $data[0])) {
                        $this->log(1, 'Could not chmod ' . $data[1] . ' to ' .
                            decoct($data[0]) . ' ' . error_get_last()["message"]);
                        return false;
                    }

                    $octmode = decoct($data[0]);
                    $this->log(3, "+ chmod $octmode $data[1]");
                    break;
                case 'delete':
                    if (file_exists($data[0])) {
                        if (!@unlink($data[0])) {
                            $this->log(1, 'Could not delete ' . $data[0] . ' ' .
                                error_get_last()["message"]);
                            return false;
                        }
                        $this->log(3, "+ rm $data[0]");
                    }
                    break;
                case 'rmdir':
                    if (file_exists($data[0])) {
                        do {
                            $testme = opendir($data[0]);
                            while (false !== ($entry = readdir($testme))) {
                                if ($entry == '.' || $entry == '..') {
                                    continue;
                                }
                                closedir($testme);
                                break 2; // this directory is not empty and can't be
                                         // deleted
                            }

                            closedir($testme);
                            if (!@rmdir($data[0])) {
                                $this->log(1, 'Could not rmdir ' . $data[0] . ' ' .
                                    error_get_last()["message"]);
                                return false;
                            }
                            $this->log(3, "+ rmdir $data[0]");
                        } while (false);
                    }
                    break;
                case 'installed_as':
                    $this->pkginfo->setInstalledAs($data[0], $data[1]);
                    if (!isset($this->_dirtree[dirname($data[1])])) {
                        $this->_dirtree[dirname($data[1])] = true;
                        $this->pkginfo->setDirtree(dirname($data[1]));

                        while(!empty($data[3]) && dirname($data[3]) != $data[3] &&
                                $data[3] != '/' && $data[3] != '\\') {
                            $this->pkginfo->setDirtree($pp =
                                $this->_prependPath($data[3], $data[2]));
                            $this->_dirtree[$pp] = true;
                            $data[3] = dirname($data[3]);
                        }
                    }
                    break;
            }
        }
        // }}}
        $this->log(2, "successfully committed $n file operations");
        $this->file_operations = array();
        return true;
    }

    // }}}
    // {{{ rollbackFileTransaction()

    function rollbackFileTransaction()
    {
        $n = count($this->file_operations);
        $this->log(2, "rolling back $n file operations");
        foreach ($this->file_operations as $tr) {
            list($type, $data) = $tr;
            switch ($type) {
                case 'backup':
                    if (file_exists($data[0] . '.bak')) {
                        if (file_exists($data[0] && is_writable($data[0]))) {
                            unlink($data[0]);
                        }
                        @copy($data[0] . '.bak', $data[0]);
                        $this->log(3, "+ restore $data[0] from $data[0].bak");
                    }
                    break;
                case 'removebackup':
                    if (file_exists($data[0] . '.bak') && is_writable($data[0] . '.bak')) {
                        unlink($data[0] . '.bak');
                        $this->log(3, "+ rm backup of $data[0] ($data[0].bak)");
                    }
                    break;
                case 'rename':
                    @unlink($data[0]);
                    $this->log(3, "+ rm $data[0]");
                    break;
                case 'mkdir':
                    @rmdir($data[0]);
                    $this->log(3, "+ rmdir $data[0]");
                    break;
                case 'chmod':
                    break;
                case 'delete':
                    break;
                case 'installed_as':
                    $this->pkginfo->setInstalledAs($data[0], false);
                    break;
            }
        }
        $this->pkginfo->resetDirtree();
        $this->file_operations = array();
    }

    // }}}
    // {{{ mkDirHier($dir)

    function mkDirHier($dir)
    {
        $this->addFileOperation('mkdir', array($dir));
        return parent::mkDirHier($dir);
    }

    // }}}
    // {{{ _parsePackageXml()

    function _parsePackageXml(&$descfile)
    {
        // Parse xml file -----------------------------------------------
        $pkg = new PEAR_PackageFile($this->config, $this->debug);
        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        $p = &$pkg->fromAnyFile($descfile, PEAR_VALIDATE_INSTALLING);
        PEAR::staticPopErrorHandling();
        if (PEAR::isError($p)) {
            if (is_array($p->getUserInfo())) {
                foreach ($p->getUserInfo() as $err) {
                    $loglevel = $err['level'] == 'error' ? 0 : 1;
                    if (!isset($this->_options['soft'])) {
                        $this->log($loglevel, ucfirst($err['level']) . ': ' . $err['message']);
                    }
                }
            }
            return $this->raiseError('Installation failed: invalid package file');
        }

        $descfile = $p->getPackageFile();
        return $p;
    }

    // }}}
    /**
     * Set the list of PEAR_Downloader_Package objects to allow more sane
     * dependency validation
     * @param array
     */
    function setDownloadedPackages(&$pkgs)
    {
        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        $err = $this->analyzeDependencies($pkgs);
        PEAR::popErrorHandling();
        if (PEAR::isError($err)) {
            return $err;
        }
        $this->_downloadedPackages = &$pkgs;
    }

    /**
     * Set the list of PEAR_Downloader_Package objects to allow more sane
     * dependency validation
     * @param array
     */
    function setUninstallPackages(&$pkgs)
    {
        $this->_downloadedPackages = &$pkgs;
    }

    function getInstallPackages()
    {
        return $this->_downloadedPackages;
    }

    // {{{ install()

    /**
     * Installs the files within the package file specified.
     *
     * @param string|PEAR_Downloader_Package $pkgfile path to the package file,
     *        or a pre-initialized packagefile object
     * @param array $options
     * recognized options:
     * - installroot   : optional prefix directory for installation
     * - force         : force installation
     * - register-only : update registry but don't install files
     * - upgrade       : upgrade existing install
     * - soft          : fail silently
     * - nodeps        : ignore dependency conflicts/missing dependencies
     * - alldeps       : install all dependencies
     * - onlyreqdeps   : install only required dependencies
     *
     * @return array|PEAR_Error package info if successful
     */
    function install($pkgfile, $options = array())
    {
        $this->_options = $options;
        $this->_registry = &$this->config->getRegistry();
        if (is_object($pkgfile)) {
            $dlpkg    = &$pkgfile;
            $pkg      = $pkgfile->getPackageFile();
            $pkgfile  = $pkg->getArchiveFile();
            $descfile = $pkg->getPackageFile();
        } else {
            $descfile = $pkgfile;
            $pkg      = $this->_parsePackageXml($descfile);
            if (PEAR::isError($pkg)) {
                return $pkg;
            }
        }

        $tmpdir = dirname($descfile);
        if (realpath($descfile) != realpath($pkgfile)) {
            // Use the temp_dir since $descfile can contain the download dir path
            $tmpdir = $this->config->get('temp_dir', null, 'pear.php.net');
            $tmpdir = System::mktemp('-d -t "' . $tmpdir . '"');

            $tar = new Archive_Tar($pkgfile);
            if (!$tar->extract($tmpdir)) {
                return $this->raiseError("unable to unpack $pkgfile");
            }
        }

        $pkgname = $pkg->getName();
        $channel = $pkg->getChannel();

        if (isset($options['installroot'])) {
            $this->config->setInstallRoot($options['installroot']);
            $this->_registry = &$this->config->getRegistry();
            $installregistry = &$this->_registry;
            $this->installroot = ''; // all done automagically now
            $php_dir = $this->config->get('php_dir', null, $channel);
        } else {
            $this->config->setInstallRoot(false);
            $this->_registry = &$this->config->getRegistry();
            if (isset($this->_options['packagingroot'])) {
                $regdir = $this->_prependPath(
                    $this->config->get('php_dir', null, 'pear.php.net'),
                    $this->_options['packagingroot']);

                $metadata_dir = $this->config->get('metadata_dir', null, 'pear.php.net');
                if ($metadata_dir) {
                    $metadata_dir = $this->_prependPath(
                        $metadata_dir,
                        $this->_options['packagingroot']);
                }
                $packrootphp_dir = $this->_prependPath(
                    $this->config->get('php_dir', null, $channel),
                    $this->_options['packagingroot']);

                $installregistry = new PEAR_Registry($regdir, false, false, $metadata_dir);
                if (!$installregistry->channelExists($channel, true)) {
                    // we need to fake a channel-discover of this channel
                    $chanobj = $this->_registry->getChannel($channel, true);
                    $installregistry->addChannel($chanobj);
                }
                $php_dir = $packrootphp_dir;
            } else {
                $installregistry = &$this->_registry;
                $php_dir = $this->config->get('php_dir', null, $channel);
            }
            $this->installroot = '';
        }

        // {{{ checks to do when not in "force" mode
        if (empty($options['force']) &&
              (file_exists($this->config->get('php_dir')) &&
               is_dir($this->config->get('php_dir')))) {
            $testp = $channel == 'pear.php.net' ? $pkgname : array($channel, $pkgname);
            $instfilelist = $pkg->getInstallationFileList(true);
            if (PEAR::isError($instfilelist)) {
                return $instfilelist;
            }

            // ensure we have the most accurate registry
            $installregistry->flushFileMap();
            $test = $installregistry->checkFileMap($instfilelist, $testp, '1.1');
            if (PEAR::isError($test)) {
                return $test;
            }

            if (sizeof($test)) {
                $pkgs = $this->getInstallPackages();
                $found = false;
                foreach ($pkgs as $param) {
                    if ($pkg->isSubpackageOf($param)) {
                        $found = true;
                        break;
                    }
                }

                if ($found) {
                    // subpackages can conflict with earlier versions of parent packages
                    $parentreg = $installregistry->packageInfo($param->getPackage(), null, $param->getChannel());
                    $tmp = $test;
                    foreach ($tmp as $file => $info) {
                        if (is_array($info)) {
                            if (strtolower($info[1]) == strtolower($param->getPackage()) &&
                                  strtolower($info[0]) == strtolower($param->getChannel())
                            ) {
                                if (isset($parentreg['filelist'][$file])) {
                                    unset($parentreg['filelist'][$file]);
                                } else{
                                    $pos     = strpos($file, '/');
                                    $basedir = substr($file, 0, $pos);
                                    $file2   = substr($file, $pos + 1);
                                    if (isset($parentreg['filelist'][$file2]['baseinstalldir'])
                                        && $parentreg['filelist'][$file2]['baseinstalldir'] === $basedir
                                    ) {
                                        unset($parentreg['filelist'][$file2]);
                                    }
                                }

                                unset($test[$file]);
                            }
                        } else {
                            if (strtolower($param->getChannel()) != 'pear.php.net') {
                                continue;
                            }

                            if (strtolower($info) == strtolower($param->getPackage())) {
                                if (isset($parentreg['filelist'][$file])) {
                                    unset($parentreg['filelist'][$file]);
                                } else{
                                    $pos     = strpos($file, '/');
                                    $basedir = substr($file, 0, $pos);
                                    $file2   = substr($file, $pos + 1);
                                    if (isset($parentreg['filelist'][$file2]['baseinstalldir'])
                                        && $parentreg['filelist'][$file2]['baseinstalldir'] === $basedir
                                    ) {
                                        unset($parentreg['filelist'][$file2]);
                                    }
                                }

                                unset($test[$file]);
                            }
                        }
                    }

                    $pfk = new PEAR_PackageFile($this->config);
                    $parentpkg = &$pfk->fromArray($parentreg);
                    $installregistry->updatePackage2($parentpkg);
                }

                if ($param->getChannel() == 'pecl.php.net' && isset($options['upgrade'])) {
                    $tmp = $test;
                    foreach ($tmp as $file => $info) {
                        if (is_string($info)) {
                            // pear.php.net packages are always stored as strings
                            if (strtolower($info) == strtolower($param->getPackage())) {
                                // upgrading existing package
                                unset($test[$file]);
                            }
                        }
                    }
                }

                if (count($test)) {
                    $msg = "$channel/$pkgname: conflicting files found:\n";
                    $longest = max(array_map("strlen", array_keys($test)));
                    $fmt = "%{$longest}s (%s)\n";
                    foreach ($test as $file => $info) {
                        if (!is_array($info)) {
                            $info = array('pear.php.net', $info);
                        }
                        $info = $info[0] . '/' . $info[1];
                        $msg .= sprintf($fmt, $file, $info);
                    }

                    if (!isset($options['ignore-errors'])) {
                        return $this->raiseError($msg);
                    }

                    if (!isset($options['soft'])) {
                        $this->log(0, "WARNING: $msg");
                    }
                }
            }
        }
        // }}}

        $this->startFileTransaction();

        $usechannel = $channel;
        if ($channel == 'pecl.php.net') {
            $test = $installregistry->packageExists($pkgname, $channel);
            if (!$test) {
                $test = $installregistry->packageExists($pkgname, 'pear.php.net');
                $usechannel = 'pear.php.net';
            }
        } else {
            $test = $installregistry->packageExists($pkgname, $channel);
        }

        if (empty($options['upgrade']) && empty($options['soft'])) {
            // checks to do only when installing new packages
            if (empty($options['force']) && $test) {
                return $this->raiseError("$channel/$pkgname is already installed");
            }
        } else {
            // Upgrade
            if ($test) {
                $v1 = $installregistry->packageInfo($pkgname, 'version', $usechannel);
                $v2 = $pkg->getVersion();
                $cmp = version_compare("$v1", "$v2", 'gt');
                if (empty($options['force']) && !version_compare("$v2", "$v1", 'gt')) {
                    return $this->raiseError("upgrade to a newer version ($v2 is not newer than $v1)");
                }
            }
        }

        // Do cleanups for upgrade and install, remove old release's files first
        if ($test && empty($options['register-only'])) {
            // when upgrading, remove old release's files first:
            if (PEAR::isError($err = $this->_deletePackageFiles($pkgname, $usechannel,
                  true))) {
                if (!isset($options['ignore-errors'])) {
                    return $this->raiseError($err);
                }

                if (!isset($options['soft'])) {
                    $this->log(0, 'WARNING: ' . $err->getMessage());
                }
            } else {
                $backedup = $err;
            }
        }

        // {{{ Copy files to dest dir ---------------------------------------

        // info from the package it self we want to access from _installFile
        $this->pkginfo = &$pkg;
        // used to determine whether we should build any C code
        $this->source_files = 0;

        $savechannel = $this->config->get('default_channel');
        if (empty($options['register-only']) && !is_dir($php_dir)) {
            if (PEAR::isError(System::mkdir(array('-p'), $php_dir))) {
                return $this->raiseError("no installation destination directory '$php_dir'\n");
            }
        }

        if (substr($pkgfile, -4) != '.xml') {
            $tmpdir .= DIRECTORY_SEPARATOR . $pkgname . '-' . $pkg->getVersion();
        }

        $this->configSet('default_channel', $channel);
        // {{{ install files

        $ver = $pkg->getPackagexmlVersion();
        if (version_compare($ver, '2.0', '>=')) {
            $filelist = $pkg->getInstallationFilelist();
        } else {
            $filelist = $pkg->getFileList();
        }

        if (PEAR::isError($filelist)) {
            return $filelist;
        }

        $p = &$installregistry->getPackage($pkgname, $channel);
        $dirtree = (empty($options['register-only']) && $p) ? $p->getDirTree() : false;

        $pkg->resetFilelist();
        $pkg->setLastInstalledVersion($installregistry->packageInfo($pkg->getPackage(),
            'version', $pkg->getChannel()));
        foreach ($filelist as $file => $atts) {
            $this->expectError(PEAR_INSTALLER_FAILED);
            if ($pkg->getPackagexmlVersion() == '1.0') {
                $res = $this->_installFile($file, $atts, $tmpdir, $options);
            } else {
                $res = $this->_installFile2($pkg, $file, $atts, $tmpdir, $options);
            }
            $this->popExpect();

            if (PEAR::isError($res)) {
                if (empty($options['ignore-errors'])) {
                    $this->rollbackFileTransaction();
                    if ($res->getMessage() == "file does not exist") {
                        $this->raiseError("file $file in package.xml does not exist");
                    }

                    return $this->raiseError($res);
                }

                if (!isset($options['soft'])) {
                    $this->log(0, "Warning: " . $res->getMessage());
                }
            }

            $real = isset($atts['attribs']) ? $atts['attribs'] : $atts;
            if ($res == PEAR_INSTALLER_OK && $real['role'] != 'src') {
                // Register files that were installed
                $pkg->installedFile($file, $atts);
            }
        }
        // }}}

        // {{{ compile and install source files
        if ($this->source_files > 0 && empty($options['nobuild'])) {
            $configureoptions = empty($options['configureoptions']) ? '' : $options['configureoptions'];
            if (PEAR::isError($err =
                  $this->_compileSourceFiles($savechannel, $pkg, $configureoptions))) {
                return $err;
            }
        }
        // }}}

        if (isset($backedup)) {
            $this->_removeBackups($backedup);
        }

        if (!$this->commitFileTransaction()) {
            $this->rollbackFileTransaction();
            $this->configSet('default_channel', $savechannel);
            return $this->raiseError("commit failed", PEAR_INSTALLER_FAILED);
        }
        // }}}

        $ret          = false;
        $installphase = 'install';
        $oldversion   = false;
        // {{{ Register that the package is installed -----------------------
        if (empty($options['upgrade'])) {
            // if 'force' is used, replace the info in registry
            $usechannel = $channel;
            if ($channel == 'pecl.php.net') {
                $test = $installregistry->packageExists($pkgname, $channel);
                if (!$test) {
                    $test = $installregistry->packageExists($pkgname, 'pear.php.net');
                    $usechannel = 'pear.php.net';
                }
            } else {
                $test = $installregistry->packageExists($pkgname, $channel);
            }

            if (!empty($options['force']) && $test) {
                $oldversion = $installregistry->packageInfo($pkgname, 'version', $usechannel);
                $installregistry->deletePackage($pkgname, $usechannel);
            }
            $ret = $installregistry->addPackage2($pkg);
        } else {
            if ($dirtree) {
                $this->startFileTransaction();
                // attempt to delete empty directories
                uksort($dirtree, array($this, '_sortDirs'));
                foreach($dirtree as $dir => $notused) {
                    $this->addFileOperation('rmdir', array($dir));
                }
                $this->commitFileTransaction();
            }

            $usechannel = $channel;
            if ($channel == 'pecl.php.net') {
                $test = $installregistry->packageExists($pkgname, $channel);
                if (!$test) {
                    $test = $installregistry->packageExists($pkgname, 'pear.php.net');
                    $usechannel = 'pear.php.net';
                }
            } else {
                $test = $installregistry->packageExists($pkgname, $channel);
            }

            // new: upgrade installs a package if it isn't installed
            if (!$test) {
                $ret = $installregistry->addPackage2($pkg);
            } else {
                if ($usechannel != $channel) {
                    $installregistry->deletePackage($pkgname, $usechannel);
                    $ret = $installregistry->addPackage2($pkg);
                } else {
                    $ret = $installregistry->updatePackage2($pkg);
                }
                $installphase = 'upgrade';
            }
        }

        if (!$ret) {
            $this->configSet('default_channel', $savechannel);
            return $this->raiseError("Adding package $channel/$pkgname to registry failed");
        }
        // }}}

        $this->configSet('default_channel', $savechannel);
        if (class_exists('PEAR_Task_Common')) { // this is auto-included if any tasks exist
            if (PEAR_Task_Common::hasPostinstallTasks()) {
                PEAR_Task_Common::runPostinstallTasks($installphase);
            }
        }

        return $pkg->toArray(true);
    }

    // }}}

    // {{{ _compileSourceFiles()
    /**
     * @param string
     * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
     * @param mixed[] $configureoptions
     */
    function _compileSourceFiles($savechannel, &$filelist, $configureoptions)
    {
        require_once 'PEAR/Builder.php';
        $this->log(1, "$this->source_files source files, building");
        $bob = new PEAR_Builder($configureoptions, $this->ui);
        $bob->debug = $this->debug;
        $built = $bob->build($filelist, array(&$this, '_buildCallback'));
        if (PEAR::isError($built)) {
            $this->rollbackFileTransaction();
            $this->configSet('default_channel', $savechannel);
            return $built;
        }

        $this->log(1, "\nBuild process completed successfully");
        foreach ($built as $ext) {
            $bn = basename($ext['file']);
            list($_ext_name, $_ext_suff) = explode('.', $bn);
            if ($_ext_suff == 'so' || $_ext_suff == 'dll') {
                if (extension_loaded($_ext_name)) {
                    return $this->raiseError("Extension '$_ext_name' already loaded. " .
                                             'Please unload it in your php.ini file ' .
                                             'prior to install or upgrade');
                }
                $role = 'ext';
            } else {
                $role = 'src';
            }

            $dest = $ext['dest'];
            $packagingroot = '';
            if (isset($this->_options['packagingroot'])) {
                $packagingroot = $this->_options['packagingroot'];
            }

            $copyto = $this->_prependPath($dest, $packagingroot);
            $extra  = $copyto != $dest ? " as '$copyto'" : '';
            $this->log(1, "Installing '$dest'$extra");

            $copydir = dirname($copyto);
            // pretty much nothing happens if we are only registering the install
            if (empty($this->_options['register-only'])) {
                if (!file_exists($copydir) || !is_dir($copydir)) {
                    if (!$this->mkDirHier($copydir)) {
                        return $this->raiseError("failed to mkdir $copydir",
                            PEAR_INSTALLER_FAILED);
                    }

                    $this->log(3, "+ mkdir $copydir");
                }

                if (!@copy($ext['file'], $copyto)) {
                    return $this->raiseError(
                        "failed to write $copyto (" . error_get_last()["message"] . ")",
                        PEAR_INSTALLER_FAILED);
                }

                $this->log(3, "+ cp $ext[file] $copyto");
                $this->addFileOperation('rename', array($ext['file'], $copyto));
                if (!OS_WINDOWS) {
                    $mode = 0666 & ~(int)octdec($this->config->get('umask'));
                    $this->addFileOperation('chmod', array($mode, $copyto));
                    if (!@chmod($copyto, $mode)) {
                        $this->log(0, "failed to change mode of $copyto (" .
                                      error_get_last()["message"] . ")");
                    }
                }
            }


            $data = array(
                'role'         => $role,
                'name'         => $bn,
                'installed_as' => $dest,
                'php_api'      => $ext['php_api'],
                'zend_mod_api' => $ext['zend_mod_api'],
                'zend_ext_api' => $ext['zend_ext_api'],
            );

            if ($filelist->getPackageXmlVersion() == '1.0') {
                $filelist->installedFile($bn, $data);
            } else {
                $filelist->installedFile($bn, array('attribs' => $data));
            }
        }
    }

    // }}}
    function &getUninstallPackages()
    {
        return $this->_downloadedPackages;
    }
    // {{{ uninstall()

    /**
     * Uninstall a package
     *
     * This method removes all files installed by the application, and then
     * removes any empty directories.
     * @param string package name
     * @param array Command-line options.  Possibilities include:
     *
     *              - installroot: base installation dir, if not the default
     *              - register-only : update registry but don't remove files
     *              - nodeps: do not process dependencies of other packages to ensure
     *                        uninstallation does not break things
     */
    function uninstall($package, $options = array())
    {
        $installRoot = isset($options['installroot']) ? $options['installroot'] : '';
        $this->config->setInstallRoot($installRoot);

        $this->installroot = '';
        $this->_registry = &$this->config->getRegistry();
        if (is_object($package)) {
            $channel = $package->getChannel();
            $pkg     = $package;
            $package = $pkg->getPackage();
        } else {
            $pkg = false;
            $info = $this->_registry->parsePackageName($package,
                $this->config->get('default_channel'));
            $channel = $info['channel'];
            $package = $info['package'];
        }

        $savechannel = $this->config->get('default_channel');
        $this->configSet('default_channel', $channel);
        if (!is_object($pkg)) {
            $pkg = $this->_registry->getPackage($package, $channel);
        }

        if (!$pkg) {
            $this->configSet('default_channel', $savechannel);
            return $this->raiseError($this->_registry->parsedPackageNameToString(
                array(
                    'channel' => $channel,
                    'package' => $package
                ), true) . ' not installed');
        }

        if ($pkg->getInstalledBinary()) {
            // this is just an alias for a binary package
            return $this->_registry->deletePackage($package, $channel);
        }

        $filelist = $pkg->getFilelist();
        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        if (!class_exists('PEAR_Dependency2')) {
            require_once 'PEAR/Dependency2.php';
        }

        $depchecker = new PEAR_Dependency2($this->config, $options,
            array('channel' => $channel, 'package' => $package),
            PEAR_VALIDATE_UNINSTALLING);
        $e = $depchecker->validatePackageUninstall($this);
        PEAR::staticPopErrorHandling();
        if (PEAR::isError($e)) {
            if (!isset($options['ignore-errors'])) {
                return $this->raiseError($e);
            }

            if (!isset($options['soft'])) {
                $this->log(0, 'WARNING: ' . $e->getMessage());
            }
        } elseif (is_array($e)) {
            if (!isset($options['soft'])) {
                $this->log(0, $e[0]);
            }
        }

        $this->pkginfo = &$pkg;
        // pretty much nothing happens if we are only registering the uninstall
        if (empty($options['register-only'])) {
            // {{{ Delete the files
            $this->startFileTransaction();
            PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
            if (PEAR::isError($err = $this->_deletePackageFiles($package, $channel))) {
                PEAR::popErrorHandling();
                $this->rollbackFileTransaction();
                $this->configSet('default_channel', $savechannel);
                if (!isset($options['ignore-errors'])) {
                    return $this->raiseError($err);
                }

                if (!isset($options['soft'])) {
                    $this->log(0, 'WARNING: ' . $err->getMessage());
                }
            } else {
                PEAR::popErrorHandling();
            }

            if (!$this->commitFileTransaction()) {
                $this->rollbackFileTransaction();
                if (!isset($options['ignore-errors'])) {
                    return $this->raiseError("uninstall failed");
                }

                if (!isset($options['soft'])) {
                    $this->log(0, 'WARNING: uninstall failed');
                }
            } else {
                $this->startFileTransaction();
                $dirtree = $pkg->getDirTree();
                if ($dirtree === false) {
                    $this->configSet('default_channel', $savechannel);
                    return $this->_registry->deletePackage($package, $channel);
                }

                // attempt to delete empty directories
                uksort($dirtree, array($this, '_sortDirs'));
                foreach($dirtree as $dir => $notused) {
                    $this->addFileOperation('rmdir', array($dir));
                }

                if (!$this->commitFileTransaction()) {
                    $this->rollbackFileTransaction();
                    if (!isset($options['ignore-errors'])) {
                        return $this->raiseError("uninstall failed");
                    }

                    if (!isset($options['soft'])) {
                        $this->log(0, 'WARNING: uninstall failed');
                    }
                }
            }
            // }}}
        }

        $this->configSet('default_channel', $savechannel);
        // Register that the package is no longer installed
        return $this->_registry->deletePackage($package, $channel);
    }

    /**
     * Sort a list of arrays of array(downloaded packagefilename) by dependency.
     *
     * It also removes duplicate dependencies
     * @param array an array of PEAR_PackageFile_v[1/2] objects
     * @return array|PEAR_Error array of array(packagefilename, package.xml contents)
     */
    function sortPackagesForUninstall(&$packages)
    {
        $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->config);
        if (PEAR::isError($this->_dependencyDB)) {
            return $this->_dependencyDB;
        }
        usort($packages, array(&$this, '_sortUninstall'));
    }

    function _sortUninstall($a, $b)
    {
        if (!$a->getDeps() && !$b->getDeps()) {
            return 0; // neither package has dependencies, order is insignificant
        }
        if ($a->getDeps() && !$b->getDeps()) {
            return -1; // $a must be installed after $b because $a has dependencies
        }
        if (!$a->getDeps() && $b->getDeps()) {
            return 1; // $b must be installed after $a because $b has dependencies
        }
        // both packages have dependencies
        if ($this->_dependencyDB->dependsOn($a, $b)) {
            return -1;
        }
        if ($this->_dependencyDB->dependsOn($b, $a)) {
            return 1;
        }
        return 0;
    }

    // }}}
    // {{{ _sortDirs()
    function _sortDirs($a, $b)
    {
        if (strnatcmp($a, $b) == -1) return 1;
        if (strnatcmp($a, $b) == 1) return -1;
        return 0;
    }

    // }}}

    // {{{ _buildCallback()

    function _buildCallback($what, $data)
    {
        if (($what == 'cmdoutput' && $this->debug > 1) ||
            ($what == 'output' && $this->debug > 0)) {
            $this->ui->outputData(rtrim($data), 'build');
        }
    }

    // }}}
}
PKs�ZXxo��-Symfony/Bridge/Doctrine/Logger/DbalLogger.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Logger;

use Psr\Log\LoggerInterface;
use Symfony\Component\Stopwatch\Stopwatch;
use Doctrine\DBAL\Logging\SQLLogger;

/**
 * DbalLogger.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class DbalLogger implements SQLLogger
{
    const MAX_STRING_LENGTH = 32;
    const BINARY_DATA_VALUE = '(binary value)';

    protected $logger;
    protected $stopwatch;

    /**
     * Constructor.
     *
     * @param LoggerInterface $logger    A LoggerInterface instance
     * @param Stopwatch       $stopwatch A Stopwatch instance
     */
    public function __construct(LoggerInterface $logger = null, Stopwatch $stopwatch = null)
    {
        $this->logger = $logger;
        $this->stopwatch = $stopwatch;
    }

    /**
     * {@inheritdoc}
     */
    public function startQuery($sql, array $params = null, array $types = null)
    {
        if (null !== $this->stopwatch) {
            $this->stopwatch->start('doctrine', 'doctrine');
        }

        if (is_array($params)) {
            foreach ($params as $index => $param) {
                if (!is_string($params[$index])) {
                    continue;
                }

                // non utf-8 strings break json encoding
                if (!preg_match('#[\p{L}\p{N} ]#u', $params[$index])) {
                    $params[$index] = self::BINARY_DATA_VALUE;
                    continue;
                }

                // detect if the too long string must be shorten
                if (function_exists('mb_detect_encoding') && false !== $encoding = mb_detect_encoding($params[$index])) {
                    if (self::MAX_STRING_LENGTH < mb_strlen($params[$index], $encoding)) {
                        $params[$index] = mb_substr($params[$index], 0, self::MAX_STRING_LENGTH - 6, $encoding).' [...]';
                        continue;
                    }
                } else {
                    if (self::MAX_STRING_LENGTH < strlen($params[$index])) {
                        $params[$index] = substr($params[$index], 0, self::MAX_STRING_LENGTH - 6).' [...]';
                        continue;
                    }
                }
            }
        }

        if (null !== $this->logger) {
            $this->log($sql, null === $params ? array() : $params);
        }
    }

    /**
     * {@inheritdoc}
     */
    public function stopQuery()
    {
        if (null !== $this->stopwatch) {
            $this->stopwatch->stop('doctrine');
        }
    }

    /**
     * Logs a message.
     *
     * @param string $message A message to log
     * @param array  $params  The context
     */
    protected function log($message, array $params)
    {
        $this->logger->debug($message, $params);
    }
}
PKs�Ze�OO&Symfony/Bridge/Doctrine/autoloader.phpnu�[���<?php

spl_autoload_register(function ($class) {
    if ('\\' == $class[0]) {
        $class = substr($class, 1);
    }

    if (
        0 === strpos($class, 'Symfony\\Bridge\\Doctrine\\')
        &&
        file_exists($file = __DIR__.'/../../../'.str_replace('\\', '/', $class).'.php')
    ) {
        require_once $file;
    }
});
PKs�Z��X+��8Symfony/Bridge/Doctrine/CacheWarmer/ProxyCacheWarmer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\CacheWarmer;

use Doctrine\Common\Persistence\ManagerRegistry;
use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;

/**
 * The proxy generator cache warmer generates all entity proxies.
 *
 * In the process of generating proxies the cache for all the metadata is primed also,
 * since this information is necessary to build the proxies in the first place.
 *
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 */
class ProxyCacheWarmer implements CacheWarmerInterface
{
    private $registry;

    /**
     * Constructor.
     *
     * @param ManagerRegistry $registry A ManagerRegistry instance
     */
    public function __construct(ManagerRegistry $registry)
    {
        $this->registry = $registry;
    }

    /**
     * This cache warmer is not optional, without proxies fatal error occurs!
     *
     * @return false
     */
    public function isOptional()
    {
        return false;
    }

    /**
     * {@inheritdoc}
     */
    public function warmUp($cacheDir)
    {
        foreach ($this->registry->getManagers() as $em) {
            // we need the directory no matter the proxy cache generation strategy
            if (!is_dir($proxyCacheDir = $em->getConfiguration()->getProxyDir())) {
                if (false === @mkdir($proxyCacheDir, 0777, true)) {
                    throw new \RuntimeException(sprintf('Unable to create the Doctrine Proxy directory "%s".', $proxyCacheDir));
                }
            } elseif (!is_writable($proxyCacheDir)) {
                throw new \RuntimeException(sprintf('The Doctrine Proxy directory "%s" is not writeable for the current system user.', $proxyCacheDir));
            }

            // if proxies are autogenerated we don't need to generate them in the cache warmer
            if ($em->getConfiguration()->getAutoGenerateProxyClasses()) {
                continue;
            }

            $classes = $em->getMetadataFactory()->getAllMetadata();

            $em->getProxyFactory()->generateProxyClasses($classes);
        }
    }
}
PKs�Z	�9,��5Symfony/Bridge/Doctrine/Form/DoctrineOrmExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Form;

use Doctrine\Common\Persistence\ManagerRegistry;
use Symfony\Component\Form\AbstractExtension;
use Symfony\Component\PropertyAccess\PropertyAccess;

class DoctrineOrmExtension extends AbstractExtension
{
    protected $registry;

    public function __construct(ManagerRegistry $registry)
    {
        $this->registry = $registry;
    }

    protected function loadTypes()
    {
        return array(
            new Type\EntityType($this->registry, PropertyAccess::createPropertyAccessor()),
        );
    }

    protected function loadTypeGuesser()
    {
        return new DoctrineOrmTypeGuesser($this->registry);
    }
}
PKs�Z�0���NSymfony/Bridge/Doctrine/Form/EventListener/MergeDoctrineCollectionListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Form\EventListener;

use Doctrine\Common\Collections\Collection;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Merge changes from the request to a Doctrine\Common\Collections\Collection instance.
 *
 * This works with ORM, MongoDB and CouchDB instances of the collection interface.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @see    Doctrine\Common\Collections\Collection
 */
class MergeDoctrineCollectionListener implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        // Higher priority than core MergeCollectionListener so that this one
        // is called before
        return array(FormEvents::SUBMIT => array('onBind', 10));
    }

    public function onBind(FormEvent $event)
    {
        $collection = $event->getForm()->getData();
        $data = $event->getData();

        // If all items were removed, call clear which has a higher
        // performance on persistent collections
        if ($collection instanceof Collection && count($data) === 0) {
            $collection->clear();
        }
    }
}
PKs�Z!%d==ASymfony/Bridge/Doctrine/Form/ChoiceList/EntityLoaderInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Form\ChoiceList;

/**
 * Custom loader for entities in the choice list.
 *
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 */
interface EntityLoaderInterface
{
    /**
     * Returns an array of entities that are valid choices in the corresponding choice list.
     *
     * @return array The entities.
     */
    public function getEntities();

    /**
     * Returns an array of entities matching the given identifiers.
     *
     * @param string $identifier The identifier field of the object. This method
     *                           is not applicable for fields with multiple
     *                           identifiers.
     * @param array $values The values of the identifiers.
     *
     * @return array The entities.
     */
    public function getEntitiesByIds($identifier, array $values);
}
PKs�Z�	?x�7�7<Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Form\ChoiceList;

use Symfony\Component\Form\Exception\RuntimeException;
use Symfony\Component\Form\Exception\StringCastException;
use Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;

/**
 * A choice list presenting a list of Doctrine entities as choices
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class EntityChoiceList extends ObjectChoiceList
{
    /**
     * @var ObjectManager
     */
    private $em;

    /**
     * @var string
     */
    private $class;

    /**
     * @var \Doctrine\Common\Persistence\Mapping\ClassMetadata
     */
    private $classMetadata;

    /**
     * Contains the query builder that builds the query for fetching the
     * entities
     *
     * This property should only be accessed through queryBuilder.
     *
     * @var EntityLoaderInterface
     */
    private $entityLoader;

    /**
     * The identifier field, if the identifier is not composite
     *
     * @var array
     */
    private $idField = null;

    /**
     * Whether to use the identifier for index generation
     *
     * @var Boolean
     */
    private $idAsIndex = false;

    /**
     * Whether to use the identifier for value generation
     *
     * @var Boolean
     */
    private $idAsValue = false;

    /**
     * Whether the entities have already been loaded.
     *
     * @var Boolean
     */
    private $loaded = false;

    /**
     * The preferred entities.
     *
     * @var array
     */
    private $preferredEntities = array();

    /**
     * Creates a new entity choice list.
     *
     * @param ObjectManager             $manager           An EntityManager instance
     * @param string                    $class             The class name
     * @param string                    $labelPath         The property path used for the label
     * @param EntityLoaderInterface     $entityLoader      An optional query builder
     * @param array                     $entities          An array of choices
     * @param array                     $preferredEntities An array of preferred choices
     * @param string                    $groupPath         A property path pointing to the property used
     *                                                     to group the choices. Only allowed if
     *                                                     the choices are given as flat array.
     * @param PropertyAccessorInterface $propertyAccessor  The reflection graph for reading property paths.
     */
    public function __construct(ObjectManager $manager, $class, $labelPath = null, EntityLoaderInterface $entityLoader = null, $entities = null,  array $preferredEntities = array(), $groupPath = null, PropertyAccessorInterface $propertyAccessor = null)
    {
        $this->em = $manager;
        $this->entityLoader = $entityLoader;
        $this->classMetadata = $manager->getClassMetadata($class);
        $this->class = $this->classMetadata->getName();
        $this->loaded = is_array($entities) || $entities instanceof \Traversable;
        $this->preferredEntities = $preferredEntities;

        $identifier = $this->classMetadata->getIdentifierFieldNames();

        if (1 === count($identifier)) {
            $this->idField = $identifier[0];
            $this->idAsValue = true;

            if (in_array($this->classMetadata->getTypeOfField($this->idField), array('integer', 'smallint', 'bigint'))) {
                $this->idAsIndex = true;
            }
        }

        if (!$this->loaded) {
            // Make sure the constraints of the parent constructor are
            // fulfilled
            $entities = array();
        }

        parent::__construct($entities, $labelPath, $preferredEntities, $groupPath, null, $propertyAccessor);
    }

    /**
     * Returns the list of entities
     *
     * @return array
     *
     * @see Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface
     */
    public function getChoices()
    {
        if (!$this->loaded) {
            $this->load();
        }

        return parent::getChoices();
    }

    /**
     * Returns the values for the entities
     *
     * @return array
     *
     * @see Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface
     */
    public function getValues()
    {
        if (!$this->loaded) {
            $this->load();
        }

        return parent::getValues();
    }

    /**
     * Returns the choice views of the preferred choices as nested array with
     * the choice groups as top-level keys.
     *
     * @return array
     *
     * @see Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface
     */
    public function getPreferredViews()
    {
        if (!$this->loaded) {
            $this->load();
        }

        return parent::getPreferredViews();
    }

    /**
     * Returns the choice views of the choices that are not preferred as nested
     * array with the choice groups as top-level keys.
     *
     * @return array
     *
     * @see Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface
     */
    public function getRemainingViews()
    {
        if (!$this->loaded) {
            $this->load();
        }

        return parent::getRemainingViews();
    }

    /**
     * Returns the entities corresponding to the given values.
     *
     * @param array $values
     *
     * @return array
     *
     * @see Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface
     */
    public function getChoicesForValues(array $values)
    {
        // Performance optimization
        // Also prevents the generation of "WHERE id IN ()" queries through the
        // entity loader. At least with MySQL and on the development machine
        // this was tested on, no exception was thrown for such invalid
        // statements, consequently no test fails when this code is removed.
        // https://github.com/symfony/symfony/pull/8981#issuecomment-24230557
        if (empty($values)) {
            return array();
        }

        if (!$this->loaded) {
            // Optimize performance in case we have an entity loader and
            // a single-field identifier
            if ($this->idAsValue && $this->entityLoader) {
                $unorderedEntities = $this->entityLoader->getEntitiesByIds($this->idField, $values);
                $entitiesByValue = array();
                $entities = array();

                // Maintain order and indices from the given $values
                // An alternative approach to the following loop is to add the
                // "INDEX BY" clause to the Doctrine query in the loader,
                // but I'm not sure whether that's doable in a generic fashion.
                foreach ($unorderedEntities as $entity) {
                    $value = $this->fixValue(current($this->getIdentifierValues($entity)));
                    $entitiesByValue[$value] = $entity;
                }

                foreach ($values as $i => $value) {
                    if (isset($entitiesByValue[$value])) {
                        $entities[$i] = $entitiesByValue[$value];
                    }
                }

                return $entities;
            }

            $this->load();
        }

        return parent::getChoicesForValues($values);
    }

    /**
     * Returns the values corresponding to the given entities.
     *
     * @param array $entities
     *
     * @return array
     *
     * @see Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface
     */
    public function getValuesForChoices(array $entities)
    {
        // Performance optimization
        if (empty($entities)) {
            return array();
        }

        if (!$this->loaded) {
            // Optimize performance for single-field identifiers. We already
            // know that the IDs are used as values

            // Attention: This optimization does not check choices for existence
            if ($this->idAsValue) {
                $values = array();

                foreach ($entities as $i => $entity) {
                    if ($entity instanceof $this->class) {
                        // Make sure to convert to the right format
                        $values[$i] = $this->fixValue(current($this->getIdentifierValues($entity)));
                    }
                }

                return $values;
            }

            $this->load();
        }

        return parent::getValuesForChoices($entities);
    }

    /**
     * Returns the indices corresponding to the given entities.
     *
     * @param array $entities
     *
     * @return array
     *
     * @see Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface
     *
     * @deprecated Deprecated since version 2.4, to be removed in 3.0.
     */
    public function getIndicesForChoices(array $entities)
    {
        // Performance optimization
        if (empty($entities)) {
            return array();
        }

        if (!$this->loaded) {
            // Optimize performance for single-field identifiers. We already
            // know that the IDs are used as indices

            // Attention: This optimization does not check choices for existence
            if ($this->idAsIndex) {
                $indices = array();

                foreach ($entities as $i => $entity) {
                    if ($entity instanceof $this->class) {
                        // Make sure to convert to the right format
                        $indices[$i] = $this->fixIndex(current($this->getIdentifierValues($entity)));
                    }
                }

                return $indices;
            }

            $this->load();
        }

        return parent::getIndicesForChoices($entities);
    }

    /**
     * Returns the entities corresponding to the given values.
     *
     * @param array $values
     *
     * @return array
     *
     * @see Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface
     *
     * @deprecated Deprecated since version 2.4, to be removed in 3.0.
     */
    public function getIndicesForValues(array $values)
    {
        // Performance optimization
        if (empty($values)) {
            return array();
        }

        if (!$this->loaded) {
            // Optimize performance for single-field identifiers.

            // Attention: This optimization does not check values for existence
            if ($this->idAsIndex && $this->idAsValue) {
                return $this->fixIndices($values);
            }

            $this->load();
        }

        return parent::getIndicesForValues($values);
    }

    /**
     * Creates a new unique index for this entity.
     *
     * If the entity has a single-field identifier, this identifier is used.
     *
     * Otherwise a new integer is generated.
     *
     * @param mixed $entity The choice to create an index for
     *
     * @return integer|string A unique index containing only ASCII letters,
     *                        digits and underscores.
     */
    protected function createIndex($entity)
    {
        if ($this->idAsIndex) {
            return $this->fixIndex(current($this->getIdentifierValues($entity)));
        }

        return parent::createIndex($entity);
    }

    /**
     * Creates a new unique value for this entity.
     *
     * If the entity has a single-field identifier, this identifier is used.
     *
     * Otherwise a new integer is generated.
     *
     * @param mixed $entity The choice to create a value for
     *
     * @return integer|string A unique value without character limitations.
     */
    protected function createValue($entity)
    {
        if ($this->idAsValue) {
            return (string) current($this->getIdentifierValues($entity));
        }

        return parent::createValue($entity);
    }

    /**
     * {@inheritdoc}
     */
    protected function fixIndex($index)
    {
        $index = parent::fixIndex($index);

        // If the ID is a single-field integer identifier, it is used as
        // index. Replace any leading minus by underscore to make it a valid
        // form name.
        if ($this->idAsIndex && $index < 0) {
            $index = strtr($index, '-', '_');
        }

        return $index;
    }

    /**
     * Loads the list with entities.
     */
    private function load()
    {
        if ($this->entityLoader) {
            $entities = $this->entityLoader->getEntities();
        } else {
            $entities = $this->em->getRepository($this->class)->findAll();
        }

        try {
            // The second parameter $labels is ignored by ObjectChoiceList
            parent::initialize($entities, array(), $this->preferredEntities);
        } catch (StringCastException $e) {
            throw new StringCastException(str_replace('argument $labelPath', 'option "property"', $e->getMessage()), null, $e);
        }

        $this->loaded = true;
    }

    /**
     * Returns the values of the identifier fields of an entity.
     *
     * Doctrine must know about this entity, that is, the entity must already
     * be persisted or added to the identity map before. Otherwise an
     * exception is thrown.
     *
     * @param object $entity The entity for which to get the identifier
     *
     * @return array          The identifier values
     *
     * @throws RuntimeException If the entity does not exist in Doctrine's identity map
     */
    private function getIdentifierValues($entity)
    {
        if (!$this->em->contains($entity)) {
            throw new RuntimeException(
                'Entities passed to the choice field must be managed. Maybe ' .
                'persist them in the entity manager?'
            );
        }

        $this->em->initializeObject($entity);

        return $this->classMetadata->getIdentifierValues($entity);
    }
}
PKs�ZGC�t��ASymfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Form\ChoiceList;

use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Doctrine\ORM\QueryBuilder;
use Doctrine\DBAL\Connection;
use Doctrine\ORM\EntityManager;

/**
 * Getting Entities through the ORM QueryBuilder
 */
class ORMQueryBuilderLoader implements EntityLoaderInterface
{
    /**
     * Contains the query builder that builds the query for fetching the
     * entities
     *
     * This property should only be accessed through queryBuilder.
     *
     * @var QueryBuilder
     */
    private $queryBuilder;

    /**
     * Construct an ORM Query Builder Loader
     *
     * @param QueryBuilder|\Closure $queryBuilder
     * @param EntityManager         $manager
     * @param string                $class
     *
     * @throws UnexpectedTypeException
     */
    public function __construct($queryBuilder, $manager = null, $class = null)
    {
        // If a query builder was passed, it must be a closure or QueryBuilder
        // instance
        if (!($queryBuilder instanceof QueryBuilder || $queryBuilder instanceof \Closure)) {
            throw new UnexpectedTypeException($queryBuilder, 'Doctrine\ORM\QueryBuilder or \Closure');
        }

        if ($queryBuilder instanceof \Closure) {
            if (!$manager instanceof EntityManager) {
                throw new UnexpectedTypeException($manager, 'Doctrine\ORM\EntityManager');
            }

            $queryBuilder = $queryBuilder($manager->getRepository($class));

            if (!$queryBuilder instanceof QueryBuilder) {
                throw new UnexpectedTypeException($queryBuilder, 'Doctrine\ORM\QueryBuilder');
            }
        }

        $this->queryBuilder = $queryBuilder;
    }

    /**
     * {@inheritDoc}
     */
    public function getEntities()
    {
        return $this->queryBuilder->getQuery()->execute();
    }

    /**
     * {@inheritDoc}
     */
    public function getEntitiesByIds($identifier, array $values)
    {
        $qb = clone ($this->queryBuilder);
        $alias = current($qb->getRootAliases());
        $parameter = 'ORMQueryBuilderLoader_getEntitiesByIds_'.$identifier;
        $where = $qb->expr()->in($alias.'.'.$identifier, ':'.$parameter);

        // Guess type
        $entity = current($qb->getRootEntities());
        $metadata = $qb->getEntityManager()->getClassMetadata($entity);
        if (in_array($metadata->getTypeOfField($identifier), array('integer', 'bigint', 'smallint'))) {
            $parameterType = Connection::PARAM_INT_ARRAY;
        } else {
            $parameterType = Connection::PARAM_STR_ARRAY;
        }

        return $qb->andWhere($where)
                  ->getQuery()
                  ->setParameter($parameter, $values, $parameterType)
                  ->getResult();
    }
}
PKs�Z`.
qpp7Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Form;

use Doctrine\Common\Persistence\ManagerRegistry;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Doctrine\Common\Persistence\Mapping\MappingException;
use Doctrine\ORM\Mapping\MappingException as LegacyMappingException;
use Symfony\Component\Form\FormTypeGuesserInterface;
use Symfony\Component\Form\Guess\Guess;
use Symfony\Component\Form\Guess\TypeGuess;
use Symfony\Component\Form\Guess\ValueGuess;
use Doctrine\Common\Util\ClassUtils;

class DoctrineOrmTypeGuesser implements FormTypeGuesserInterface
{
    protected $registry;

    private $cache = array();

    public function __construct(ManagerRegistry $registry)
    {
        $this->registry = $registry;
    }

    /**
     * {@inheritDoc}
     */
    public function guessType($class, $property)
    {
        if (!$ret = $this->getMetadata($class)) {
            return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE);
        }

        list($metadata, $name) = $ret;

        if ($metadata->hasAssociation($property)) {
            $multiple = $metadata->isCollectionValuedAssociation($property);
            $mapping = $metadata->getAssociationMapping($property);

            return new TypeGuess('entity', array('em' => $name, 'class' => $mapping['targetEntity'], 'multiple' => $multiple), Guess::HIGH_CONFIDENCE);
        }

        switch ($metadata->getTypeOfField($property)) {
            case 'array':
                return new TypeGuess('collection', array(), Guess::MEDIUM_CONFIDENCE);
            case 'boolean':
                return new TypeGuess('checkbox', array(), Guess::HIGH_CONFIDENCE);
            case 'datetime':
            case 'vardatetime':
            case 'datetimetz':
                return new TypeGuess('datetime', array(), Guess::HIGH_CONFIDENCE);
            case 'date':
                return new TypeGuess('date', array(), Guess::HIGH_CONFIDENCE);
            case 'time':
                return new TypeGuess('time', array(), Guess::HIGH_CONFIDENCE);
            case 'decimal':
            case 'float':
                return new TypeGuess('number', array(), Guess::MEDIUM_CONFIDENCE);
            case 'integer':
            case 'bigint':
            case 'smallint':
                return new TypeGuess('integer', array(), Guess::MEDIUM_CONFIDENCE);
            case 'string':
                return new TypeGuess('text', array(), Guess::MEDIUM_CONFIDENCE);
            case 'text':
                return new TypeGuess('textarea', array(), Guess::MEDIUM_CONFIDENCE);
            default:
                return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE);
        }
    }

    /**
     * {@inheritDoc}
     */
    public function guessRequired($class, $property)
    {
        $classMetadatas = $this->getMetadata($class);

        if (!$classMetadatas) {
            return null;
        }

        /** @var ClassMetadataInfo $classMetadata */
        $classMetadata = $classMetadatas[0];

        // Check whether the field exists and is nullable or not
        if ($classMetadata->hasField($property)) {
            if (!$classMetadata->isNullable($property)) {
                return new ValueGuess(true, Guess::HIGH_CONFIDENCE);
            }

            return new ValueGuess(false, Guess::MEDIUM_CONFIDENCE);
        }

        // Check whether the association exists, is a to-one association and its
        // join column is nullable or not
        if ($classMetadata->isAssociationWithSingleJoinColumn($property)) {
            $mapping = $classMetadata->getAssociationMapping($property);

            if (!isset($mapping['joinColumns'][0]['nullable'])) {
                // The "nullable" option defaults to true, in that case the
                // field should not be required.
                return new ValueGuess(false, Guess::HIGH_CONFIDENCE);
            }

            return new ValueGuess(!$mapping['joinColumns'][0]['nullable'], Guess::HIGH_CONFIDENCE);
        }

        return null;
    }

    /**
     * {@inheritDoc}
     */
    public function guessMaxLength($class, $property)
    {
        $ret = $this->getMetadata($class);
        if ($ret && $ret[0]->hasField($property) && !$ret[0]->hasAssociation($property)) {
            $mapping = $ret[0]->getFieldMapping($property);

            if (isset($mapping['length'])) {
                return new ValueGuess($mapping['length'], Guess::HIGH_CONFIDENCE);
            }

            if (in_array($ret[0]->getTypeOfField($property), array('decimal', 'float'))) {
                return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE);
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    public function guessPattern($class, $property)
    {
        $ret = $this->getMetadata($class);
        if ($ret && $ret[0]->hasField($property) && !$ret[0]->hasAssociation($property)) {
            if (in_array($ret[0]->getTypeOfField($property), array('decimal', 'float'))) {
                return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE);
            }
        }
    }

    protected function getMetadata($class)
    {
        // normalize class name
        $class = ClassUtils::getRealClass(ltrim($class, '\\'));

        if (array_key_exists($class, $this->cache)) {
            return $this->cache[$class];
        }

        $this->cache[$class] = null;
        foreach ($this->registry->getManagers() as $name => $em) {
            try {
                return $this->cache[$class] = array($em->getClassMetadata($class), $name);
            } catch (MappingException $e) {
                // not an entity or mapped super class
            } catch (LegacyMappingException $e) {
                // not an entity or mapped super class, using Doctrine ORM 2.2
            }
        }
    }
}
PKs�ZCi�PPMSymfony/Bridge/Doctrine/Form/DataTransformer/CollectionToArrayTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Form\DataTransformer;

use Symfony\Component\Form\Exception\TransformationFailedException;
use Symfony\Component\Form\DataTransformerInterface;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class CollectionToArrayTransformer implements DataTransformerInterface
{
    /**
     * Transforms a collection into an array.
     *
     * @param Collection $collection A collection of entities
     *
     * @return mixed An array of entities
     *
     * @throws TransformationFailedException
     */
    public function transform($collection)
    {
        if (null === $collection) {
            return array();
        }

        // For cases when the collection getter returns $collection->toArray()
        // in order to prevent modifications of the returned collection
        if (is_array($collection)) {
            return $collection;
        }

        if (!$collection instanceof Collection) {
            throw new TransformationFailedException('Expected a Doctrine\Common\Collections\Collection object.');
        }

        return $collection->toArray();
    }

    /**
     * Transforms choice keys into entities.
     *
     * @param mixed $array An array of entities
     *
     * @return Collection   A collection of entities
     */
    public function reverseTransform($array)
    {
        if ('' === $array || null === $array) {
            $array = array();
        } else {
            $array = (array) $array;
        }

        return new ArrayCollection($array);
    }
}
PKs�Z憝��0Symfony/Bridge/Doctrine/Form/Type/EntityType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Form\Type;

use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader;

class EntityType extends DoctrineType
{
    /**
     * Return the default loader object.
     *
     * @param ObjectManager $manager
     * @param mixed         $queryBuilder
     * @param string        $class
     * @return ORMQueryBuilderLoader
     */
    public function getLoader(ObjectManager $manager, $queryBuilder, $class)
    {
        return new ORMQueryBuilderLoader(
            $queryBuilder,
            $manager,
            $class
        );
    }

    public function getName()
    {
        return 'entity';
    }
}
PKs�ZS;,:��2Symfony/Bridge/Doctrine/Form/Type/DoctrineType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Form\Type;

use Doctrine\Common\Persistence\ManagerRegistry;
use Symfony\Component\Form\Exception\RuntimeException;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Bridge\Doctrine\Form\ChoiceList\EntityChoiceList;
use Symfony\Bridge\Doctrine\Form\ChoiceList\EntityLoaderInterface;
use Symfony\Bridge\Doctrine\Form\EventListener\MergeDoctrineCollectionListener;
use Symfony\Bridge\Doctrine\Form\DataTransformer\CollectionToArrayTransformer;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;

abstract class DoctrineType extends AbstractType
{
    /**
     * @var ManagerRegistry
     */
    protected $registry;

    /**
     * @var array
     */
    private $choiceListCache = array();

    /**
     * @var PropertyAccessorInterface
     */
    private $propertyAccessor;

    public function __construct(ManagerRegistry $registry, PropertyAccessorInterface $propertyAccessor = null)
    {
        $this->registry = $registry;
        $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor();
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        if ($options['multiple']) {
            $builder
                ->addEventSubscriber(new MergeDoctrineCollectionListener())
                ->addViewTransformer(new CollectionToArrayTransformer(), true)
            ;
        }
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $choiceListCache =& $this->choiceListCache;
        $registry = $this->registry;
        $propertyAccessor = $this->propertyAccessor;
        $type = $this;

        $loader = function (Options $options) use ($type) {
            if (null !== $options['query_builder']) {
                return $type->getLoader($options['em'], $options['query_builder'], $options['class']);
            }

            return null;
        };

        $choiceList = function (Options $options) use (&$choiceListCache, $propertyAccessor) {
            // Support for closures
            $propertyHash = is_object($options['property'])
                ? spl_object_hash($options['property'])
                : $options['property'];

            $choiceHashes = $options['choices'];

            // Support for recursive arrays
            if (is_array($choiceHashes)) {
                // A second parameter ($key) is passed, so we cannot use
                // spl_object_hash() directly (which strictly requires
                // one parameter)
                array_walk_recursive($choiceHashes, function (&$value) {
                    $value = spl_object_hash($value);
                });
            } elseif ($choiceHashes instanceof \Traversable) {
                $hashes = array();
                foreach ($choiceHashes as $value) {
                    $hashes[] = spl_object_hash($value);
                }

                $choiceHashes = $hashes;
            }

            $preferredChoiceHashes = $options['preferred_choices'];

            if (is_array($preferredChoiceHashes)) {
                array_walk_recursive($preferredChoiceHashes, function (&$value) {
                    $value = spl_object_hash($value);
                });
            }

            // Support for custom loaders (with query builders)
            $loaderHash = is_object($options['loader'])
                ? spl_object_hash($options['loader'])
                : $options['loader'];

            // Support for closures
            $groupByHash = is_object($options['group_by'])
                ? spl_object_hash($options['group_by'])
                : $options['group_by'];

            $hash = hash('sha256', json_encode(array(
                spl_object_hash($options['em']),
                $options['class'],
                $propertyHash,
                $loaderHash,
                $choiceHashes,
                $preferredChoiceHashes,
                $groupByHash
            )));

            if (!isset($choiceListCache[$hash])) {
                $choiceListCache[$hash] = new EntityChoiceList(
                    $options['em'],
                    $options['class'],
                    $options['property'],
                    $options['loader'],
                    $options['choices'],
                    $options['preferred_choices'],
                    $options['group_by'],
                    $propertyAccessor
                );
            }

            return $choiceListCache[$hash];
        };

        $emNormalizer = function (Options $options, $em) use ($registry) {
            /* @var ManagerRegistry $registry */
            if (null !== $em) {
                return $registry->getManager($em);
            }

            $em = $registry->getManagerForClass($options['class']);

            if (null === $em) {
                throw new RuntimeException(sprintf(
                    'Class "%s" seems not to be a managed Doctrine entity. ' .
                    'Did you forget to map it?',
                    $options['class']
                ));
            }

            return $em;
        };

        $resolver->setDefaults(array(
            'em'                => null,
            'property'          => null,
            'query_builder'     => null,
            'loader'            => $loader,
            'choices'           => null,
            'choice_list'       => $choiceList,
            'group_by'          => null,
        ));

        $resolver->setRequired(array('class'));

        $resolver->setNormalizers(array(
            'em' => $emNormalizer,
        ));

        $resolver->setAllowedTypes(array(
            'loader' => array('null', 'Symfony\Bridge\Doctrine\Form\ChoiceList\EntityLoaderInterface'),
        ));
    }

    /**
     * Return the default loader object.
     *
     * @param ObjectManager $manager
     * @param mixed         $queryBuilder
     * @param string        $class
     *
     * @return EntityLoaderInterface
     */
    abstract public function getLoader(ObjectManager $manager, $queryBuilder, $class);

    public function getParent()
    {
        return 'choice';
    }
}
PKs�ZW&v��<Symfony/Bridge/Doctrine/Security/User/EntityUserProvider.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Security\User;

use Doctrine\Common\Persistence\ManagerRegistry;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserInterface;

/**
 * Wrapper around a Doctrine ObjectManager.
 *
 * Provides easy to use provisioning for Doctrine entity users.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class EntityUserProvider implements UserProviderInterface
{
    private $class;
    private $repository;
    private $property;
    private $metadata;

    public function __construct(ManagerRegistry $registry, $class, $property = null, $managerName = null)
    {
        $em = $registry->getManager($managerName);
        $this->class = $class;
        $this->metadata = $em->getClassMetadata($class);

        if (false !== strpos($this->class, ':')) {
            $this->class = $this->metadata->getName();
        }

        $this->repository = $em->getRepository($class);
        $this->property = $property;
    }

    /**
     * {@inheritdoc}
     */
    public function loadUserByUsername($username)
    {
        if (null !== $this->property) {
            $user = $this->repository->findOneBy(array($this->property => $username));
        } else {
            if (!$this->repository instanceof UserProviderInterface) {
                throw new \InvalidArgumentException(sprintf('The Doctrine repository "%s" must implement UserProviderInterface.', get_class($this->repository)));
            }

            $user = $this->repository->loadUserByUsername($username);
        }

        if (null === $user) {
            throw new UsernameNotFoundException(sprintf('User "%s" not found.', $username));
        }

        return $user;
    }

    /**
     * {@inheritDoc}
     */
    public function refreshUser(UserInterface $user)
    {
        if (!$user instanceof $this->class) {
            throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user)));
        }

        if ($this->repository instanceof UserProviderInterface) {
            $refreshedUser = $this->repository->refreshUser($user);
        } else {
            // The user must be reloaded via the primary key as all other data
            // might have changed without proper persistence in the database.
            // That's the case when the user has been changed by a form with
            // validation errors.
            if (!$id = $this->metadata->getIdentifierValues($user)) {
                throw new \InvalidArgumentException("You cannot refresh a user ".
                    "from the EntityUserProvider that does not contain an identifier. ".
                    "The user object has to be serialized with its own identifier " .
                    "mapped by Doctrine."
                );
            }

            $refreshedUser = $this->repository->find($id);
            if (null === $refreshedUser) {
                throw new UsernameNotFoundException(sprintf('User with id %s not found', json_encode($id)));
            }
        }

        return $refreshedUser;
    }

    /**
     * {@inheritDoc}
     */
    public function supportsClass($class)
    {
        return $class === $this->class || is_subclass_of($class, $this->class);
    }
}
PKs�Z�����ESymfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Security\RememberMe;

use Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface;
use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentTokenInterface;
use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken;
use Symfony\Component\Security\Core\Exception\TokenNotFoundException;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Types\Type as DoctrineType;
use PDO, DateTime;

/**
 * This class provides storage for the tokens that is set in "remember me"
 * cookies. This way no password secrets will be stored in the cookies on
 * the client machine, and thus the security is improved.
 *
 * This depends only on doctrine in order to get a database connection
 * and to do the conversion of the datetime column.
 *
 * In order to use this class, you need the following table in your database:
 * CREATE TABLE `rememberme_token` (
 *  `series`   char(88)     UNIQUE PRIMARY KEY NOT NULL,
 *  `value`    char(88)     NOT NULL,
 *  `lastUsed` datetime     NOT NULL,
 *  `class`    varchar(100) NOT NULL,
 *  `username` varchar(200) NOT NULL
 * );
 */
class DoctrineTokenProvider implements TokenProviderInterface
{
    /**
     * Doctrine DBAL database connection
     * F.ex. service id: doctrine.dbal.default_connection
     *
     * @var \Doctrine\DBAL\Connection
     */
    private $conn;

    /**
     * new DoctrineTokenProvider for the RememberMe authentication service
     *
     * @param \Doctrine\DBAL\Connection $conn
     */
    public function __construct(Connection $conn)
    {
        $this->conn = $conn;
    }

    /**
     * {@inheritdoc}
     */
    public function loadTokenBySeries($series)
    {
        $sql = 'SELECT class, username, value, lastUsed'
            . ' FROM rememberme_token WHERE series=:series';
        $paramValues = array('series' => $series);
        $paramTypes  = array('series' => PDO::PARAM_STR);
        $stmt = $this->conn->executeQuery($sql, $paramValues, $paramTypes);
        $row =  $stmt->fetch(PDO::FETCH_ASSOC);
        if ($row) {
            return new PersistentToken($row['class'],
                                       $row['username'],
                                       $series,
                                       $row['value'],
                                       new DateTime($row['lastUsed'])
                                       );
        }

        throw new TokenNotFoundException('No token found.');
    }

    /**
     * {@inheritdoc}
     */
    public function deleteTokenBySeries($series)
    {
        $sql = 'DELETE FROM rememberme_token WHERE series=:series';
        $paramValues = array('series' => $series);
        $paramTypes  = array('series' => PDO::PARAM_STR);
        $this->conn->executeUpdate($sql, $paramValues, $paramTypes);
    }

    /**
     * {@inheritdoc}
     */
    public function updateToken($series, $tokenValue, DateTime $lastUsed)
    {
        $sql = 'UPDATE rememberme_token SET value=:value, lastUsed=:lastUsed'
            . ' WHERE series=:series';
        $paramValues = array('value'    => $tokenValue,
                             'lastUsed' => $lastUsed,
                             'series'   => $series);
        $paramTypes =  array('value'    => PDO::PARAM_STR,
                             'lastUsed' => DoctrineType::DATETIME,
                             'series'   => PDO::PARAM_STR);
        $updated = $this->conn->executeUpdate($sql, $paramValues, $paramTypes);
        if ($updated < 1) {
            throw new TokenNotFoundException('No token found.');
        }
    }

    /**
     * {@inheritdoc}
     */
    public function createNewToken(PersistentTokenInterface $token)
    {
        $sql = 'INSERT INTO rememberme_token'
            .        ' (class, username, series, value, lastUsed)'
            . ' VALUES (:class, :username, :series, :value, :lastUsed)';
        $paramValues = array('class'    => $token->getClass(),
                             'username' => $token->getUsername(),
                             'series'   => $token->getSeries(),
                             'value'    => $token->getTokenValue(),
                             'lastUsed' => $token->getLastUsed());
        $paramTypes  = array('class'    => PDO::PARAM_STR,
                             'username' => PDO::PARAM_STR,
                             'series'   => PDO::PARAM_STR,
                             'value'    => PDO::PARAM_STR,
                             'lastUsed' => DoctrineType::DATETIME);
        $this->conn->executeUpdate($sql, $paramValues, $paramTypes);
    }
}
PKs�Z(��y��9Symfony/Bridge/Doctrine/Validator/DoctrineInitializer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Validator;

use Doctrine\Common\Persistence\ManagerRegistry;
use Symfony\Component\Validator\ObjectInitializerInterface;

/**
 * Automatically loads proxy object before validation.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class DoctrineInitializer implements ObjectInitializerInterface
{
    protected $registry;

    public function __construct(ManagerRegistry $registry)
    {
        $this->registry = $registry;
    }

    public function initialize($object)
    {
        $manager = $this->registry->getManagerForClass(get_class($object));
        if (null !== $manager) {
            $manager->initializeObject($object);
        }
    }
}
PKs�ZQ��>Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * Constraint for the Unique Entity validator
 *
 * @Annotation
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 */
class UniqueEntity extends Constraint
{
    public $message = 'This value is already used.';
    public $service = 'doctrine.orm.validator.unique';
    public $em = null;
    public $repositoryMethod = 'findBy';
    public $fields = array();
    public $errorPath = null;
    public $ignoreNull = true;

    public function getRequiredOptions()
    {
        return array('fields');
    }

    /**
     * The validator must be defined as a service with this name.
     *
     * @return string
     */
    public function validatedBy()
    {
        return $this->service;
    }

    /**
     * {@inheritDoc}
     */
    public function getTargets()
    {
        return self::CLASS_CONSTRAINT;
    }

    public function getDefaultOption()
    {
        return 'fields';
    }
}
PKs�Z:�d�GSymfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Validator\Constraints;

use Doctrine\Common\Persistence\ManagerRegistry;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
use Symfony\Component\Validator\ConstraintValidator;

/**
 * Unique Entity Validator checks if one or a set of fields contain unique values.
 *
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 */
class UniqueEntityValidator extends ConstraintValidator
{
    /**
     * @var ManagerRegistry
     */
    private $registry;

    /**
     * @param ManagerRegistry $registry
     */
    public function __construct(ManagerRegistry $registry)
    {
        $this->registry = $registry;
    }

    /**
     * @param object     $entity
     * @param Constraint $constraint
     *
     * @throws UnexpectedTypeException
     * @throws ConstraintDefinitionException
     */
    public function validate($entity, Constraint $constraint)
    {
        if (!is_array($constraint->fields) && !is_string($constraint->fields)) {
            throw new UnexpectedTypeException($constraint->fields, 'array');
        }

        if (null !== $constraint->errorPath && !is_string($constraint->errorPath)) {
            throw new UnexpectedTypeException($constraint->errorPath, 'string or null');
        }

        $fields = (array) $constraint->fields;

        if (0 === count($fields)) {
            throw new ConstraintDefinitionException('At least one field has to be specified.');
        }

        if ($constraint->em) {
            $em = $this->registry->getManager($constraint->em);

            if (!$em) {
               throw new ConstraintDefinitionException(sprintf('Object manager "%s" does not exist.', $constraint->em));
            }
        } else {
            $em = $this->registry->getManagerForClass(get_class($entity));

            if (!$em) {
                throw new ConstraintDefinitionException(sprintf('Unable to find the object manager associated with an entity of class "%s".', get_class($entity)));
            }
        }

        $class = $em->getClassMetadata(get_class($entity));
        /* @var $class \Doctrine\Common\Persistence\Mapping\ClassMetadata */

        $criteria = array();
        foreach ($fields as $fieldName) {
            if (!$class->hasField($fieldName) && !$class->hasAssociation($fieldName)) {
                throw new ConstraintDefinitionException(sprintf("The field '%s' is not mapped by Doctrine, so it cannot be validated for uniqueness.", $fieldName));
            }

            $criteria[$fieldName] = $class->reflFields[$fieldName]->getValue($entity);

            if ($constraint->ignoreNull && null === $criteria[$fieldName]) {
                return;
            }

            if (null !== $criteria[$fieldName] && $class->hasAssociation($fieldName)) {
                /* Ensure the Proxy is initialized before using reflection to
                 * read its identifiers. This is necessary because the wrapped
                 * getter methods in the Proxy are being bypassed.
                 */
                $em->initializeObject($criteria[$fieldName]);

                $relatedClass = $em->getClassMetadata($class->getAssociationTargetClass($fieldName));
                $relatedId = $relatedClass->getIdentifierValues($criteria[$fieldName]);

                if (count($relatedId) > 1) {
                    throw new ConstraintDefinitionException(
                        "Associated entities are not allowed to have more than one identifier field to be " .
                        "part of a unique constraint in: ".$class->getName()."#".$fieldName
                    );
                }
                $criteria[$fieldName] = array_pop($relatedId);
            }
        }

        $repository = $em->getRepository(get_class($entity));
        $result = $repository->{$constraint->repositoryMethod}($criteria);

        /* If the result is a MongoCursor, it must be advanced to the first
         * element. Rewinding should have no ill effect if $result is another
         * iterator implementation.
         */
        if ($result instanceof \Iterator) {
            $result->rewind();
        } elseif (is_array($result)) {
            reset($result);
        }

        /* If no entity matched the query criteria or a single entity matched,
         * which is the same as the entity being validated, the criteria is
         * unique.
         */
        if (0 === count($result) || (1 === count($result) && $entity === ($result instanceof \Iterator ? $result->current() : current($result)))) {
            return;
        }

        $errorPath = null !== $constraint->errorPath ? $constraint->errorPath : $fields[0];

        $this->context->addViolationAt($errorPath, $constraint->message, array(), $criteria[$fields[0]]);
    }
}
PKs�Z�Ta�==BSymfony/Bridge/Doctrine/ExpressionLanguage/DoctrineParserCache.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\ExpressionLanguage;

use Doctrine\Common\Cache\Cache;
use Symfony\Component\ExpressionLanguage\ParsedExpression;
use Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface;

/**
 * @author Adrien Brault <adrien.brault@gmail.com>
 */
class DoctrineParserCache implements ParserCacheInterface
{
    /**
     * @var Cache
     */
    private $cache;

    public function __construct(Cache $cache)
    {
        $this->cache = $cache;
    }

    /**
     * {@inheritdoc}
     */
    public function fetch($key)
    {
        if (false === $value = $this->cache->fetch($key)) {
            return null;
        }

        return $value;
    }

    /**
     * {@inheritdoc}
     */
    public function save($key, ParsedExpression $expression)
    {
        $this->cache->save($key, $expression);
    }
}
PKs�Z��qm
m
-Symfony/Bridge/Doctrine/RegistryInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine;

use Doctrine\Common\Persistence\ManagerRegistry as ManagerRegistryInterface;
use Doctrine\ORM\Configuration;
use Doctrine\ORM\EntityManager;

/**
 * References Doctrine connections and entity managers.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface RegistryInterface extends ManagerRegistryInterface
{
    /**
     * Gets the default entity manager name.
     *
     * @return string The default entity manager name
     */
    public function getDefaultEntityManagerName();

    /**
     * Gets a named entity manager.
     *
     * @param string $name The entity manager name (null for the default one)
     *
     * @return EntityManager
     */
    public function getEntityManager($name = null);

    /**
     * Gets an array of all registered entity managers
     *
     * @return array An array of EntityManager instances
     */
    public function getEntityManagers();

    /**
     * Resets a named entity manager.
     *
     * This method is useful when an entity manager has been closed
     * because of a rollbacked transaction AND when you think that
     * it makes sense to get a new one to replace the closed one.
     *
     * Be warned that you will get a brand new entity manager as
     * the existing one is not useable anymore. This means that any
     * other object with a dependency on this entity manager will
     * hold an obsolete reference. You can inject the registry instead
     * to avoid this problem.
     *
     * @param string $name The entity manager name (null for the default one)
     *
     * @return EntityManager
     */
    public function resetEntityManager($name = null);

    /**
     * Resolves a registered namespace alias to the full namespace.
     *
     * This method looks for the alias in all registered entity managers.
     *
     * @param string $alias The alias
     *
     * @return string The full namespace
     *
     * @see Configuration::getEntityNamespace
     */
    public function getEntityNamespace($alias);

    /**
     * Gets all connection names.
     *
     * @return array An array of connection names
     */
    public function getEntityManagerNames();

    /**
     * Gets the entity manager associated with a given class.
     *
     * @param string $class A Doctrine Entity class name
     *
     * @return EntityManager|null
     */
    public function getEntityManagerForClass($class);
}
PKs�Zlf/�qq=Symfony/Bridge/Doctrine/DataFixtures/ContainerAwareLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\DataFixtures;

use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\DataFixtures\Loader;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Doctrine data fixtures loader that injects the service container into
 * fixture objects that implement ContainerAwareInterface.
 *
 * Note: Use of this class requires the Doctrine data fixtures extension, which
 * is a suggested dependency for Symfony.
 */
class ContainerAwareLoader extends Loader
{
    /**
     * @var ContainerInterface
     */
    private $container;

    /**
     * Constructor.
     *
     * @param ContainerInterface $container A ContainerInterface instance
     */
    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    /**
     * {@inheritdoc}
     */
    public function addFixture(FixtureInterface $fixture)
    {
        if ($fixture instanceof ContainerAwareInterface) {
            $fixture->setContainer($this->container);
        }

        parent::addFixture($fixture);
    }
}
PKs�Z����=Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\HttpFoundation;

use Doctrine\DBAL\Platforms\MySqlPlatform;
use Doctrine\DBAL\Driver\Connection;

/**
 * DBAL based session storage.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class DbalSessionHandler implements \SessionHandlerInterface
{
    /**
     * @var Connection
     */
    private $con;

    /**
     * @var string
     */
    private $tableName;

    /**
     * Constructor.
     *
     * @param Connection $con       An instance of Connection.
     * @param string     $tableName Table name.
     */
    public function __construct(Connection $con, $tableName = 'sessions')
    {
        $this->con = $con;
        $this->tableName = $tableName;
    }

    /**
     * {@inheritdoc}
     */
    public function open($path = null, $name = null)
    {
        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function close()
    {
        // do nothing
        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function destroy($id)
    {
        try {
            $this->con->executeQuery("DELETE FROM {$this->tableName} WHERE sess_id = :id", array(
                'id' => $id,
            ));
        } catch (\PDOException $e) {
            throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data: %s', $e->getMessage()), 0, $e);
        }

        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function gc($lifetime)
    {
        try {
            $this->con->executeQuery("DELETE FROM {$this->tableName} WHERE sess_time < :time", array(
                'time' => time() - $lifetime,
            ));
        } catch (\PDOException $e) {
            throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data: %s', $e->getMessage()), 0, $e);
        }

        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function read($id)
    {
        try {
            $data = $this->con->executeQuery("SELECT sess_data FROM {$this->tableName} WHERE sess_id = :id", array(
                'id' => $id,
            ))->fetchColumn();

            if (false !== $data) {
                return base64_decode($data);
            }

            // session does not exist, create it
            $this->createNewSession($id);

            return '';
        } catch (\PDOException $e) {
            throw new \RuntimeException(sprintf('PDOException was thrown when trying to read the session data: %s', $e->getMessage()), 0, $e);
        }
    }

    /**
     * {@inheritdoc}
     */
    public function write($id, $data)
    {
        $platform = $this->con->getDatabasePlatform();

        // this should maybe be abstracted in Doctrine DBAL
        if ($platform instanceof MySqlPlatform) {
            $sql = "INSERT INTO {$this->tableName} (sess_id, sess_data, sess_time) VALUES (%1\$s, %2\$s, %3\$d) "
                  ."ON DUPLICATE KEY UPDATE sess_data = VALUES(sess_data), sess_time = CASE WHEN sess_time = %3\$d THEN (VALUES(sess_time) + 1) ELSE VALUES(sess_time) END";
        } else {
            $sql = "UPDATE {$this->tableName} SET sess_data = %2\$s, sess_time = %3\$d WHERE sess_id = %1\$s";
        }

        try {
            $rowCount = $this->con->exec(sprintf(
                $sql,
                $this->con->quote($id),
                //session data can contain non binary safe characters so we need to encode it
                $this->con->quote(base64_encode($data)),
                time()
            ));

            if (!$rowCount) {
                // No session exists in the database to update. This happens when we have called
                // session_regenerate_id()
                $this->createNewSession($id, $data);
            }
        } catch (\PDOException $e) {
            throw new \RuntimeException(sprintf('PDOException was thrown when trying to write the session data: %s', $e->getMessage()), 0, $e);
        }

        return true;
    }

   /**
    * Creates a new session with the given $id and $data
    *
    * @param string $id
    * @param string $data
    *
    * @return Boolean
    */
    private function createNewSession($id, $data = '')
    {
        $this->con->exec(sprintf("INSERT INTO {$this->tableName} (sess_id, sess_data, sess_time) VALUES (%s, %s, %d)",
            $this->con->quote($id),
            //session data can contain non binary safe characters so we need to encode it
            $this->con->quote(base64_encode($data)),
            time()
        ));

        return true;
    }
}
PKs�Z�����CSymfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerSchema.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\HttpFoundation;

use Doctrine\DBAL\Schema\Schema;

/**
 * DBAL Session Storage Schema.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
final class DbalSessionHandlerSchema extends Schema
{
    private $tableName;

    public function __construct($tableName = 'sessions')
    {
        parent::__construct();

        $this->tableName = $tableName;
        $this->addSessionTable();
    }

    public function addToSchema(Schema $schema)
    {
        foreach ($this->getTables() as $table) {
            $schema->_addTable($table);
        }
    }

    private function addSessionTable()
    {
        $table = $this->createTable($this->tableName);
        $table->addColumn('sess_id', 'string');
        $table->addColumn('sess_data', 'text')->setNotNull(true);
        $table->addColumn('sess_time', 'integer')->setNotNull(true)->setUnsigned(true);
        $table->setPrimaryKey(array('sess_id'));
    }
}
PKs�ZOlQ�996Symfony/Bridge/Doctrine/ContainerAwareEventManager.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine;

use Doctrine\Common\EventArgs;
use Doctrine\Common\EventManager;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Allows lazy loading of listener services.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ContainerAwareEventManager extends EventManager
{
    /**
     * Map of registered listeners.
     * <event> => <listeners>
     *
     * @var array
     */
    private $listeners = array();
    private $initialized = array();
    private $container;

    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    /**
     * Dispatches an event to all registered listeners.
     *
     * @param string $eventName The name of the event to dispatch. The name of the event is
     *                          the name of the method that is invoked on listeners.
     * @param EventArgs $eventArgs The event arguments to pass to the event handlers/listeners.
     *                             If not supplied, the single empty EventArgs instance is used.
     * @return boolean
     */
    public function dispatchEvent($eventName, EventArgs $eventArgs = null)
    {
        if (isset($this->listeners[$eventName])) {
            $eventArgs = $eventArgs === null ? EventArgs::getEmptyInstance() : $eventArgs;

            $initialized = isset($this->initialized[$eventName]);

            foreach ($this->listeners[$eventName] as $hash => $listener) {
                if (!$initialized && is_string($listener)) {
                    $this->listeners[$eventName][$hash] = $listener = $this->container->get($listener);
                }

                $listener->$eventName($eventArgs);
            }
            $this->initialized[$eventName] = true;
        }
    }

    /**
     * Gets the listeners of a specific event or all listeners.
     *
     * @param string $event The name of the event.
     *
     * @return array The event listeners for the specified event, or all event listeners.
     */
    public function getListeners($event = null)
    {
        return $event ? $this->listeners[$event] : $this->listeners;
    }

    /**
     * Checks whether an event has any registered listeners.
     *
     * @param string $event
     *
     * @return boolean TRUE if the specified event has any listeners, FALSE otherwise.
     */
    public function hasListeners($event)
    {
        return isset($this->listeners[$event]) && $this->listeners[$event];
    }

    /**
     * Adds an event listener that listens on the specified events.
     *
     * @param string|array  $events   The event(s) to listen on.
     * @param object|string $listener The listener object.
     *
     * @throws \RuntimeException
     */
    public function addEventListener($events, $listener)
    {
        if (is_string($listener)) {
            if ($this->initialized) {
                throw new \RuntimeException('Adding lazy-loading listeners after construction is not supported.');
            }

            $hash = '_service_'.$listener;
        } else {
            // Picks the hash code related to that listener
            $hash = spl_object_hash($listener);
        }

        foreach ((array) $events as $event) {
            // Overrides listener if a previous one was associated already
            // Prevents duplicate listeners on same event (same instance only)
            $this->listeners[$event][$hash] = $listener;
        }
    }

    /**
     * Removes an event listener from the specified events.
     *
     * @param string|array  $events
     * @param object|string $listener
     */
    public function removeEventListener($events, $listener)
    {
        if (is_string($listener)) {
            $hash = '_service_'.$listener;
        } else {
            // Picks the hash code related to that listener
            $hash = spl_object_hash($listener);
        }

        foreach ((array) $events as $event) {
            // Check if actually have this listener associated
            if (isset($this->listeners[$event][$hash])) {
                unset($this->listeners[$event][$hash]);
            }
        }
    }
}
PKs�Z؈����3Symfony/Bridge/Doctrine/Test/DoctrineTestHelper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Test;

use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
use Doctrine\ORM\EntityManager;

/**
 * Provides utility functions needed in tests.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class DoctrineTestHelper
{
    /**
     * Returns an entity manager for testing.
     *
     * @return EntityManager
     */
    public static function createTestEntityManager()
    {
        if (!class_exists('PDO') || !in_array('sqlite', \PDO::getAvailableDrivers())) {
            \PHPUnit_Framework_TestCase::markTestSkipped('This test requires SQLite support in your environment');
        }

        $config = new \Doctrine\ORM\Configuration();
        $config->setEntityNamespaces(array('SymfonyTestsDoctrine' => 'Symfony\Bridge\Doctrine\Tests\Fixtures'));
        $config->setAutoGenerateProxyClasses(true);
        $config->setProxyDir(\sys_get_temp_dir());
        $config->setProxyNamespace('SymfonyTests\Doctrine');
        $config->setMetadataDriverImpl(new AnnotationDriver(new AnnotationReader()));
        $config->setQueryCacheImpl(new \Doctrine\Common\Cache\ArrayCache());
        $config->setMetadataCacheImpl(new \Doctrine\Common\Cache\ArrayCache());

        $params = array(
            'driver' => 'pdo_sqlite',
            'memory' => true,
        );

        return EntityManager::create($params, $config);
    }

    /**
     * This class cannot be instantiated.
     */
    private function __construct()
    {
    }
}
PKs�Z̳֨�+Symfony/Bridge/Doctrine/ManagerRegistry.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine;

use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Doctrine\Common\Persistence\AbstractManagerRegistry;

/**
 * References Doctrine connections and entity/document managers.
 *
 * @author  Lukas Kahwe Smith <smith@pooteeweet.org>
 */
abstract class ManagerRegistry extends AbstractManagerRegistry implements ContainerAwareInterface
{
    /**
     * @var ContainerInterface
     */
    protected $container;

    /**
     * @inheritdoc
     */
    protected function getService($name)
    {
        return $this->container->get($name);
    }

    /**
     * @inheritdoc
     */
    protected function resetService($name)
    {
        $this->container->set($name, null);
    }

    /**
     * @inheritdoc
     */
    public function setContainer(ContainerInterface $container = null)
    {
        $this->container = $container;
    }
}
PKs�Z+çxAA?Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\DataCollector;

use Doctrine\Common\Persistence\ManagerRegistry;
use Doctrine\DBAL\Logging\DebugStack;
use Doctrine\DBAL\Types\Type;
use Symfony\Component\HttpKernel\DataCollector\DataCollector;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * DoctrineDataCollector.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class DoctrineDataCollector extends DataCollector
{
    private $registry;
    private $connections;
    private $managers;
    private $loggers = array();

    public function __construct(ManagerRegistry $registry)
    {
        $this->registry = $registry;
        $this->connections = $registry->getConnectionNames();
        $this->managers = $registry->getManagerNames();
    }

    /**
     * Adds the stack logger for a connection.
     *
     * @param string     $name
     * @param DebugStack $logger
     */
    public function addLogger($name, DebugStack $logger)
    {
        $this->loggers[$name] = $logger;
    }

    /**
     * {@inheritdoc}
     */
    public function collect(Request $request, Response $response, \Exception $exception = null)
    {
        $queries = array();
        foreach ($this->loggers as $name => $logger) {
            $queries[$name] = $this->sanitizeQueries($name, $logger->queries);
        }

        $this->data = array(
            'queries'     => $queries,
            'connections' => $this->connections,
            'managers'    => $this->managers,
        );
    }

    public function getManagers()
    {
        return $this->data['managers'];
    }

    public function getConnections()
    {
        return $this->data['connections'];
    }

    public function getQueryCount()
    {
        return array_sum(array_map('count', $this->data['queries']));
    }

    public function getQueries()
    {
        return $this->data['queries'];
    }

    public function getTime()
    {
        $time = 0;
        foreach ($this->data['queries'] as $queries) {
            foreach ($queries as $query) {
                $time += $query['executionMS'];
            }
        }

        return $time;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'db';
    }

    private function sanitizeQueries($connectionName, $queries)
    {
        foreach ($queries as $i => $query) {
            $queries[$i] = $this->sanitizeQuery($connectionName, $query);
        }

        return $queries;
    }

    private function sanitizeQuery($connectionName, $query)
    {
        $query['explainable'] = true;
        $query['params'] = (array) $query['params'];
        foreach ($query['params'] as $j => &$param) {
            if (isset($query['types'][$j])) {
                // Transform the param according to the type
                $type = $query['types'][$j];
                if (is_string($type)) {
                    $type = Type::getType($type);
                }
                if ($type instanceof Type) {
                    $query['types'][$j] = $type->getBindingType();
                    $param = $type->convertToDatabaseValue($param, $this->registry->getConnection($connectionName)->getDatabasePlatform());
                }
            }

            list($param, $explainable) = $this->sanitizeParam($param);
            if (!$explainable) {
                $query['explainable'] = false;
            }
        }

        return $query;
    }

    /**
     * Sanitizes a param.
     *
     * The return value is an array with the sanitized value and a boolean
     * indicating if the original value was kept (allowing to use the sanitized
     * value to explain the query).
     *
     * @param mixed $var
     *
     * @return array
     */
    private function sanitizeParam($var)
    {
        if (is_object($var)) {
            return array(sprintf('Object(%s)', get_class($var)), false);
        }

        if (is_array($var)) {
            $a = array();
            $original = true;
            foreach ($var as $k => $v) {
                list($value, $orig) = $this->sanitizeParam($v);
                $original = $original && $orig;
                $a[$k] = $value;
            }

            return array($a, $original);
        }

        if (is_resource($var)) {
            return array(sprintf('Resource(%s)', get_resource_type($var)), false);
        }

        return array($var, true);
    }
}
PKs�Z*�+��J�JISymfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\DependencyInjection;

use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\Config\Resource\FileResource;

/**
 * This abstract classes groups common code that Doctrine Object Manager extensions (ORM, MongoDB, CouchDB) need.
 *
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 */
abstract class AbstractDoctrineExtension extends Extension
{
    /**
     * Used inside metadata driver method to simplify aggregation of data.
     *
     * @var array
     */
    protected $aliasMap = array();

    /**
     * Used inside metadata driver method to simplify aggregation of data.
     *
     * @var array
     */
    protected $drivers = array();

    /**
     * @param array            $objectManager A configured object manager.
     * @param ContainerBuilder $container     A ContainerBuilder instance
     *
     * @throws \InvalidArgumentException
     */
    protected function loadMappingInformation(array $objectManager, ContainerBuilder $container)
    {
        if ($objectManager['auto_mapping']) {
            // automatically register bundle mappings
            foreach (array_keys($container->getParameter('kernel.bundles')) as $bundle) {
                if (!isset($objectManager['mappings'][$bundle])) {
                    $objectManager['mappings'][$bundle] = array(
                        'mapping'   => true,
                        'is_bundle' => true,
                    );
                }
            }
        }

        foreach ($objectManager['mappings'] as $mappingName => $mappingConfig) {
            if (null !== $mappingConfig && false === $mappingConfig['mapping']) {
                continue;
            }

            $mappingConfig = array_replace(array(
                'dir'    => false,
                'type'   => false,
                'prefix' => false,
            ), (array) $mappingConfig);

            $mappingConfig['dir'] = $container->getParameterBag()->resolveValue($mappingConfig['dir']);
            // a bundle configuration is detected by realizing that the specified dir is not absolute and existing
            if (!isset($mappingConfig['is_bundle'])) {
                $mappingConfig['is_bundle'] = !is_dir($mappingConfig['dir']);
            }

            if ($mappingConfig['is_bundle']) {
                $bundle = null;
                foreach ($container->getParameter('kernel.bundles') as $name => $class) {
                    if ($mappingName === $name) {
                        $bundle = new \ReflectionClass($class);

                        break;
                    }
                }

                if (null === $bundle) {
                    throw new \InvalidArgumentException(sprintf('Bundle "%s" does not exist or it is not enabled.', $mappingName));
                }

                $mappingConfig = $this->getMappingDriverBundleConfigDefaults($mappingConfig, $bundle, $container);
                if (!$mappingConfig) {
                    continue;
                }
            }

            $this->assertValidMappingConfiguration($mappingConfig, $objectManager['name']);
            $this->setMappingDriverConfig($mappingConfig, $mappingName);
            $this->setMappingDriverAlias($mappingConfig, $mappingName);
        }
    }

    /**
     * Register the alias for this mapping driver.
     *
     * Aliases can be used in the Query languages of all the Doctrine object managers to simplify writing tasks.
     *
     * @param array  $mappingConfig
     * @param string $mappingName
     */
    protected function setMappingDriverAlias($mappingConfig, $mappingName)
    {
        if (isset($mappingConfig['alias'])) {
            $this->aliasMap[$mappingConfig['alias']] = $mappingConfig['prefix'];
        } else {
            $this->aliasMap[$mappingName] = $mappingConfig['prefix'];
        }
    }

    /**
     * Register the mapping driver configuration for later use with the object managers metadata driver chain.
     *
     * @param array  $mappingConfig
     * @param string $mappingName
     *
     * @throws \InvalidArgumentException
     */
    protected function setMappingDriverConfig(array $mappingConfig, $mappingName)
    {
        if (is_dir($mappingConfig['dir'])) {
            $this->drivers[$mappingConfig['type']][$mappingConfig['prefix']] = realpath($mappingConfig['dir']);
        } else {
            throw new \InvalidArgumentException(sprintf('Invalid Doctrine mapping path given. Cannot load Doctrine mapping/bundle named "%s".', $mappingName));
        }
    }

    /**
     * If this is a bundle controlled mapping all the missing information can be autodetected by this method.
     *
     * Returns false when autodetection failed, an array of the completed information otherwise.
     *
     * @param array            $bundleConfig
     * @param \ReflectionClass $bundle
     * @param ContainerBuilder $container    A ContainerBuilder instance
     *
     * @return array|false
     */
    protected function getMappingDriverBundleConfigDefaults(array $bundleConfig, \ReflectionClass $bundle, ContainerBuilder $container)
    {
        $bundleDir = dirname($bundle->getFilename());

        if (!$bundleConfig['type']) {
            $bundleConfig['type'] = $this->detectMetadataDriver($bundleDir, $container);
        }

        if (!$bundleConfig['type']) {
            // skip this bundle, no mapping information was found.
            return false;
        }

        if (!$bundleConfig['dir']) {
            if (in_array($bundleConfig['type'], array('annotation', 'staticphp'))) {
                $bundleConfig['dir'] = $bundleDir.'/'.$this->getMappingObjectDefaultName();
            } else {
                $bundleConfig['dir'] = $bundleDir.'/'.$this->getMappingResourceConfigDirectory();
            }
        } else {
            $bundleConfig['dir'] = $bundleDir.'/'.$bundleConfig['dir'];
        }

        if (!$bundleConfig['prefix']) {
            $bundleConfig['prefix'] = $bundle->getNamespaceName().'\\'.$this->getMappingObjectDefaultName();
        }

        return $bundleConfig;
    }

    /**
     * Register all the collected mapping information with the object manager by registering the appropriate mapping drivers.
     *
     * @param array            $objectManager
     * @param ContainerBuilder $container     A ContainerBuilder instance
     */
    protected function registerMappingDrivers($objectManager, ContainerBuilder $container)
    {
        // configure metadata driver for each bundle based on the type of mapping files found
        if ($container->hasDefinition($this->getObjectManagerElementName($objectManager['name'].'_metadata_driver'))) {
            $chainDriverDef = $container->getDefinition($this->getObjectManagerElementName($objectManager['name'].'_metadata_driver'));
        } else {
            $chainDriverDef = new Definition('%'.$this->getObjectManagerElementName('metadata.driver_chain.class%'));
            $chainDriverDef->setPublic(false);
        }

        foreach ($this->drivers as $driverType => $driverPaths) {
            $mappingService = $this->getObjectManagerElementName($objectManager['name'].'_'.$driverType.'_metadata_driver');
            if ($container->hasDefinition($mappingService)) {
                $mappingDriverDef = $container->getDefinition($mappingService);
                $args = $mappingDriverDef->getArguments();
                if ($driverType == 'annotation') {
                    $args[1] = array_merge(array_values($driverPaths), $args[1]);
                } else {
                    $args[0] = array_merge(array_values($driverPaths), $args[0]);
                }
                $mappingDriverDef->setArguments($args);
            } elseif ($driverType == 'annotation') {
                $mappingDriverDef = new Definition('%'.$this->getObjectManagerElementName('metadata.'.$driverType.'.class%'), array(
                    new Reference($this->getObjectManagerElementName('metadata.annotation_reader')),
                    array_values($driverPaths)
                ));
            } else {
                $mappingDriverDef = new Definition('%'.$this->getObjectManagerElementName('metadata.'.$driverType.'.class%'), array(
                    array_values($driverPaths)
                ));
            }
            $mappingDriverDef->setPublic(false);
            if (false !== strpos($mappingDriverDef->getClass(), 'yml') || false !== strpos($mappingDriverDef->getClass(), 'xml')) {
                $mappingDriverDef->setArguments(array(array_flip($driverPaths)));
                $mappingDriverDef->addMethodCall('setGlobalBasename', array('mapping'));
            }

            $container->setDefinition($mappingService, $mappingDriverDef);

            foreach ($driverPaths as $prefix => $driverPath) {
                $chainDriverDef->addMethodCall('addDriver', array(new Reference($mappingService), $prefix));
            }
        }

        $container->setDefinition($this->getObjectManagerElementName($objectManager['name'].'_metadata_driver'), $chainDriverDef);
    }

    /**
     * Assertion if the specified mapping information is valid.
     *
     * @param array  $mappingConfig
     * @param string $objectManagerName
     *
     * @throws \InvalidArgumentException
     */
    protected function assertValidMappingConfiguration(array $mappingConfig, $objectManagerName)
    {
        if (!$mappingConfig['type'] || !$mappingConfig['dir'] || !$mappingConfig['prefix']) {
            throw new \InvalidArgumentException(sprintf('Mapping definitions for Doctrine manager "%s" require at least the "type", "dir" and "prefix" options.', $objectManagerName));
        }

        if (!is_dir($mappingConfig['dir'])) {
            throw new \InvalidArgumentException(sprintf('Specified non-existing directory "%s" as Doctrine mapping source.', $mappingConfig['dir']));
        }

        if (!in_array($mappingConfig['type'], array('xml', 'yml', 'annotation', 'php', 'staticphp'))) {
            throw new \InvalidArgumentException(sprintf('Can only configure "xml", "yml", "annotation", "php" or '.
                '"staticphp" through the DoctrineBundle. Use your own bundle to configure other metadata drivers. '.
                'You can register them by adding a new driver to the '.
                '"%s" service definition.', $this->getObjectManagerElementName($objectManagerName.'.metadata_driver')
            ));
        }
    }

    /**
     * Detects what metadata driver to use for the supplied directory.
     *
     * @param string           $dir       A directory path
     * @param ContainerBuilder $container A ContainerBuilder instance
     *
     * @return string|null A metadata driver short name, if one can be detected
     */
    protected function detectMetadataDriver($dir, ContainerBuilder $container)
    {
        // add the closest existing directory as a resource
        $configPath = $this->getMappingResourceConfigDirectory();
        $resource = $dir.'/'.$configPath;
        while (!is_dir($resource)) {
            $resource = dirname($resource);
        }

        $container->addResource(new FileResource($resource));

        $extension = $this->getMappingResourceExtension();
        if (($files = glob($dir.'/'.$configPath.'/*.'.$extension.'.xml')) && count($files)) {
            return 'xml';
        } elseif (($files = glob($dir.'/'.$configPath.'/*.'.$extension.'.yml')) && count($files)) {
            return 'yml';
        } elseif (($files = glob($dir.'/'.$configPath.'/*.'.$extension.'.php')) && count($files)) {
            return 'php';
        }

        // add the directory itself as a resource
        $container->addResource(new FileResource($dir));

        if (is_dir($dir.'/'.$this->getMappingObjectDefaultName())) {
            return 'annotation';
        }

        return null;
    }

    /**
     * Loads a configured object manager metadata, query or result cache driver.
     *
     * @param array            $objectManager A configured object manager.
     * @param ContainerBuilder $container     A ContainerBuilder instance.
     * @param string           $cacheName
     *
     * @throws \InvalidArgumentException In case of unknown driver type.
     */
    protected function loadObjectManagerCacheDriver(array $objectManager, ContainerBuilder $container, $cacheName)
    {
        $cacheDriver = $objectManager[$cacheName.'_driver'];
        $cacheDriverService = $this->getObjectManagerElementName($objectManager['name'].'_'.$cacheName);

        switch ($cacheDriver['type']) {
            case 'service':
                $container->setAlias($cacheDriverService, new Alias($cacheDriver['id'], false));

                return;
            case 'memcache':
                $memcacheClass = !empty($cacheDriver['class']) ? $cacheDriver['class'] : '%'.$this->getObjectManagerElementName('cache.memcache.class').'%';
                $memcacheInstanceClass = !empty($cacheDriver['instance_class']) ? $cacheDriver['instance_class'] : '%'.$this->getObjectManagerElementName('cache.memcache_instance.class').'%';
                $memcacheHost = !empty($cacheDriver['host']) ? $cacheDriver['host'] : '%'.$this->getObjectManagerElementName('cache.memcache_host').'%';
                $memcachePort = !empty($cacheDriver['port']) || (isset($cacheDriver['port']) && $cacheDriver['port'] === 0)  ? $cacheDriver['port'] : '%'.$this->getObjectManagerElementName('cache.memcache_port').'%';
                $cacheDef = new Definition($memcacheClass);
                $memcacheInstance = new Definition($memcacheInstanceClass);
                $memcacheInstance->addMethodCall('connect', array(
                    $memcacheHost, $memcachePort
                ));
                $container->setDefinition($this->getObjectManagerElementName(sprintf('%s_memcache_instance', $objectManager['name'])), $memcacheInstance);
                $cacheDef->addMethodCall('setMemcache', array(new Reference($this->getObjectManagerElementName(sprintf('%s_memcache_instance', $objectManager['name'])))));
                break;
            case 'memcached':
                $memcachedClass = !empty($cacheDriver['class']) ? $cacheDriver['class'] : '%'.$this->getObjectManagerElementName('cache.memcached.class').'%';
                $memcachedInstanceClass = !empty($cacheDriver['instance_class']) ? $cacheDriver['instance_class'] : '%'.$this->getObjectManagerElementName('cache.memcached_instance.class').'%';
                $memcachedHost = !empty($cacheDriver['host']) ? $cacheDriver['host'] : '%'.$this->getObjectManagerElementName('cache.memcached_host').'%';
                $memcachedPort = !empty($cacheDriver['port']) ? $cacheDriver['port'] : '%'.$this->getObjectManagerElementName('cache.memcached_port').'%';
                $cacheDef = new Definition($memcachedClass);
                $memcachedInstance = new Definition($memcachedInstanceClass);
                $memcachedInstance->addMethodCall('addServer', array(
                    $memcachedHost, $memcachedPort
                ));
                $container->setDefinition($this->getObjectManagerElementName(sprintf('%s_memcached_instance', $objectManager['name'])), $memcachedInstance);
                $cacheDef->addMethodCall('setMemcached', array(new Reference($this->getObjectManagerElementName(sprintf('%s_memcached_instance', $objectManager['name'])))));
                break;
             case 'redis':
                $redisClass = !empty($cacheDriver['class']) ? $cacheDriver['class'] : '%'.$this->getObjectManagerElementName('cache.redis.class').'%';
                $redisInstanceClass = !empty($cacheDriver['instance_class']) ? $cacheDriver['instance_class'] : '%'.$this->getObjectManagerElementName('cache.redis_instance.class').'%';
                $redisHost = !empty($cacheDriver['host']) ? $cacheDriver['host'] : '%'.$this->getObjectManagerElementName('cache.redis_host').'%';
                $redisPort = !empty($cacheDriver['port']) ? $cacheDriver['port'] : '%'.$this->getObjectManagerElementName('cache.redis_port').'%';
                $cacheDef = new Definition($redisClass);
                $redisInstance = new Definition($redisInstanceClass);
                $redisInstance->addMethodCall('connect', array(
                    $redisHost, $redisPort
                ));
                $container->setDefinition($this->getObjectManagerElementName(sprintf('%s_redis_instance', $objectManager['name'])), $redisInstance);
                $cacheDef->addMethodCall('setRedis', array(new Reference($this->getObjectManagerElementName(sprintf('%s_redis_instance', $objectManager['name'])))));
                break;
            case 'apc':
            case 'array':
            case 'xcache':
            case 'wincache':
            case 'zenddata':
                $cacheDef = new Definition('%'.$this->getObjectManagerElementName(sprintf('cache.%s.class', $cacheDriver['type'])).'%');
                break;
            default:
                throw new \InvalidArgumentException(sprintf('"%s" is an unrecognized Doctrine cache driver.', $cacheDriver['type']));
        }

        $cacheDef->setPublic(false);

        if (!isset($cacheDriver['namespace'])) {
            // generate a unique namespace for the given application
            $cacheDriver['namespace'] = 'sf2'.$this->getMappingResourceExtension().'_'.$objectManager['name'].'_'.hash('sha256',($container->getParameter('kernel.root_dir').$container->getParameter('kernel.environment')));
        }

        $cacheDef->addMethodCall('setNamespace', array($cacheDriver['namespace']));

        $container->setDefinition($cacheDriverService, $cacheDef);
    }

    /**
     * Prefixes the relative dependency injection container path with the object manager prefix.
     *
     * @example $name is 'entity_manager' then the result would be 'doctrine.orm.entity_manager'
     *
     * @param string $name
     *
     * @return string
     */
    abstract protected function getObjectManagerElementName($name);

    /**
     * Noun that describes the mapped objects such as Entity or Document.
     *
     * Will be used for autodetection of persistent objects directory.
     *
     * @return string
     */
    abstract protected function getMappingObjectDefaultName();

    /**
     * Relative path from the bundle root to the directory where mapping files reside.
     *
     * @return string
     */
    abstract protected function getMappingResourceConfigDirectory();

    /**
     * Extension used by the mapping files.
     *
     * @return string
     */
    abstract protected function getMappingResourceExtension();
}
PKs�Z���*��SSymfony/Bridge/Doctrine/DependencyInjection/Security/UserProvider/EntityFactory.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\DependencyInjection\Security\UserProvider;

use Symfony\Component\Config\Definition\Builder\NodeDefinition;

use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\UserProviderFactoryInterface;
use Symfony\Component\DependencyInjection\DefinitionDecorator;
use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * EntityFactory creates services for Doctrine user provider.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Christophe Coevoet <stof@notk.org>
 */
class EntityFactory implements UserProviderFactoryInterface
{
    private $key;
    private $providerId;

    public function __construct($key, $providerId)
    {
        $this->key = $key;
        $this->providerId = $providerId;
    }

    public function create(ContainerBuilder $container, $id, $config)
    {
        $container
            ->setDefinition($id, new DefinitionDecorator($this->providerId))
            ->addArgument($config['class'])
            ->addArgument($config['property'])
            ->addArgument($config['manager_name'])
        ;
    }

    public function getKey()
    {
        return $this->key;
    }

    public function addConfiguration(NodeDefinition $node)
    {
        $node
            ->children()
                ->scalarNode('class')->isRequired()->cannotBeEmpty()->end()
                ->scalarNode('property')->defaultNull()->end()
                ->scalarNode('manager_name')->defaultNull()->end()
            ->end()
        ;
    }
}
PKs�Z��㛕�QSymfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterMappingsPass.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass;

use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;

/**
 * Base class for the doctrine bundles to provide a compiler pass class that
 * helps to register doctrine mappings.
 *
 * The compiler pass is meant to register the mappings with the metadata
 * chain driver corresponding to one of the object managers.
 *
 * For concrete implementations that are easy to use, see the
 * RegisterXyMappingsPass classes in the DoctrineBundle resp.
 * DoctrineMongodbBundle, DoctrineCouchdbBundle and DoctrinePhpcrBundle.
 *
 * @author David Buchmann <david@liip.ch>
 */
abstract class RegisterMappingsPass implements CompilerPassInterface
{
    /**
     * DI object for the driver to use, either a service definition for a
     * private service or a reference for a public service.
     * @var Definition|Reference
     */
    protected $driver;

    /**
     * List of namespaces handled by the driver
     * @var string[]
     */
    protected $namespaces;

    /**
     * List of potential container parameters that hold the object manager name
     * to register the mappings with the correct metadata driver, for example
     * array('acme.manager', 'doctrine.default_entity_manager')
     * @var string[]
     */
    protected $managerParameters;

    /**
     * Naming pattern of the metadata chain driver service ids, for example
     * 'doctrine.orm.%s_metadata_driver'
     * @var string
     */
    protected $driverPattern;

    /**
     * A name for a parameter in the container. If set, this compiler pass will
     * only do anything if the parameter is present. (But regardless of the
     * value of that parameter.
     * @var string
     */
    protected $enabledParameter;

    /**
     * @param Definition|Reference $driver            driver DI definition or reference
     * @param string[]             $namespaces        list of namespaces handled by $driver
     * @param string[]             $managerParameters list of container parameters
     *                                                that could hold the manager name
     * @param string               $driverPattern     pattern to get the metadata driver service names
     * @param string               $enabledParameter  service container parameter that must be
     *                                                present to enable the mapping. Set to false
     *                                                to not do any check, optional.
     */
    public function __construct($driver, array $namespaces, array $managerParameters, $driverPattern, $enabledParameter = false)
    {
        $this->driver = $driver;
        $this->namespaces = $namespaces;
        $this->managerParameters = $managerParameters;
        $this->driverPattern = $driverPattern;
        $this->enabledParameter = $enabledParameter;
    }

    /**
     * Register mappings with the metadata drivers.
     *
     * @param ContainerBuilder $container
     */
    public function process(ContainerBuilder $container)
    {
        if (!$this->enabled($container)) {
            return;
        }

        $mappingDriverDef = $this->getDriver($container);

        $chainDriverDefService = $this->getChainDriverServiceName($container);
        $chainDriverDef = $container->getDefinition($chainDriverDefService);
        foreach ($this->namespaces as $namespace) {
            $chainDriverDef->addMethodCall('addDriver', array($mappingDriverDef, $namespace));
        }
    }

    /**
     * Get the service name of the metadata chain driver that the mappings
     * should be registered with. The default implementation loops over the
     * managerParameters and applies the first non-empty parameter it finds to
     * the driverPattern.
     *
     * @param ContainerBuilder $container
     *
     * @return string a service definition name
     *
     * @throws ParameterNotFoundException if non of the managerParameters has a
     *      non-empty value.
     */
    protected function getChainDriverServiceName(ContainerBuilder $container)
    {
        foreach ($this->managerParameters as $param) {
            if ($container->hasParameter($param)) {
                $name = $container->getParameter($param);
                if ($name) {
                    return sprintf($this->driverPattern, $name);
                }
            }
        }

        throw new ParameterNotFoundException('None of the managerParameters resulted in a valid name');
    }

    /**
     * Create the service definition for the metadata driver.
     *
     * @param ContainerBuilder $container passed on in case an extending class
     *      needs access to the container.
     *
     * @return Definition|Reference the metadata driver to add to all chain drivers
     */
    protected function getDriver(ContainerBuilder $container)
    {
        return $this->driver;
    }

    /**
     * Determine whether this mapping should be activated or not. This allows
     * to take this decision with the container builder available.
     *
     * This default implementation checks if the class has the enabledParameter
     * configured and if so if that parameter is present in the container.
     *
     * @param ContainerBuilder $container
     *
     * @return boolean whether this compiler pass really should register the mappings
     */
    protected function enabled(ContainerBuilder $container)
    {
        return !$this->enabledParameter || $container->hasParameter($this->enabledParameter);
    }
}
PKs�Z~�YAAeSymfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;

/**
 * Registers event listeners and subscribers to the available doctrine connections.
 *
 * @author Jeremy Mikola <jmikola@gmail.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class RegisterEventListenersAndSubscribersPass implements CompilerPassInterface
{
    private $connections;
    private $container;
    private $eventManagers;
    private $managerTemplate;
    private $tagPrefix;

    /**
     * Constructor.
     *
     * @param string $connections     Parameter ID for connections
     * @param string $managerTemplate sprintf() template for generating the event
     *                                manager's service ID for a connection name
     * @param string $tagPrefix Tag prefix for listeners and subscribers
     */
    public function __construct($connections, $managerTemplate, $tagPrefix)
    {
        $this->connections = $connections;
        $this->managerTemplate = $managerTemplate;
        $this->tagPrefix = $tagPrefix;
    }

    /**
     * {@inheritDoc}
     */
    public function process(ContainerBuilder $container)
    {
        if (!$container->hasParameter($this->connections)) {
            return;
        }

        $taggedSubscribers = $container->findTaggedServiceIds($this->tagPrefix.'.event_subscriber');
        $taggedListeners = $container->findTaggedServiceIds($this->tagPrefix.'.event_listener');

        if (empty($taggedSubscribers) && empty($taggedListeners)) {
            return;
        }

        $this->container = $container;
        $this->connections = $container->getParameter($this->connections);
        $sortFunc = function ($a, $b) {
            $a = isset($a['priority']) ? $a['priority'] : 0;
            $b = isset($b['priority']) ? $b['priority'] : 0;

            return $a > $b ? -1 : 1;
        };


        if (!empty($taggedSubscribers)) {
            $subscribersPerCon = $this->groupByConnection($taggedSubscribers);
            foreach ($subscribersPerCon as $con => $subscribers) {
                $em = $this->getEventManager($con);

                uasort($subscribers, $sortFunc);
                foreach ($subscribers as $id => $instance) {
                    $em->addMethodCall('addEventSubscriber', array(new Reference($id)));
                }
            }
        }

        if (!empty($taggedListeners)) {
            $listenersPerCon = $this->groupByConnection($taggedListeners, true);
            foreach ($listenersPerCon as $con => $listeners) {
                $em = $this->getEventManager($con);

                uasort($listeners, $sortFunc);
                foreach ($listeners as $id => $instance) {
                    $em->addMethodCall('addEventListener', array(
                        array_unique($instance['event']),
                        isset($instance['lazy']) && $instance['lazy'] ? $id : new Reference($id),
                    ));
                }
            }
        }
    }

    private function groupByConnection(array $services, $isListener = false)
    {
        $grouped = array();
        foreach ($allCons = array_keys($this->connections) as $con) {
            $grouped[$con] = array();
        }

        foreach ($services as $id => $instances) {
            foreach ($instances as $instance) {
                if ($isListener) {
                    if (!isset($instance['event'])) {
                        throw new \InvalidArgumentException(sprintf('Doctrine event listener "%s" must specify the "event" attribute.', $id));
                    }
                    $instance['event'] = array($instance['event']);

                    if (isset($instance['lazy']) && $instance['lazy']) {
                        $this->container->getDefinition($id)->setPublic(true);
                    }
                }

                $cons = isset($instance['connection']) ? array($instance['connection']) : $allCons;
                foreach ($cons as $con) {
                    if (!isset($grouped[$con])) {
                        throw new \RuntimeException(sprintf('The Doctrine connection "%s" referenced in service "%s" does not exist. Available connections names: %s', $con, $id, implode(', ', array_keys($this->connections))));
                    }

                    if ($isListener && isset($grouped[$con][$id])) {
                        $grouped[$con][$id]['event'] = array_merge($grouped[$con][$id]['event'], $instance['event']);
                    } else {
                        $grouped[$con][$id] = $instance;
                    }
                }
            }
        }

        return $grouped;
    }

    private function getEventManager($name)
    {
        if (null === $this->eventManagers) {
            $this->eventManagers = array();
            foreach ($this->connections as $n => $id) {
                $this->eventManagers[$n] = $this->container->getDefinition(sprintf($this->managerTemplate, $n));
            }
        }

        return $this->eventManagers[$name];
    }
}
PKs�Z��,���SSymfony/Bridge/Doctrine/DependencyInjection/CompilerPass/DoctrineValidationPass.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\Config\Resource\FileResource;

/**
 * Registers additional validators
 *
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 */
class DoctrineValidationPass implements CompilerPassInterface
{
    /**
     * @var string
     */
    private $managerType;

    public function __construct($managerType)
    {
        $this->managerType = $managerType;
    }

    /**
     * {@inheritDoc}
     */
    public function process(ContainerBuilder $container)
    {
        $this->updateValidatorMappingFiles($container, 'xml', 'xml');
        $this->updateValidatorMappingFiles($container, 'yaml', 'yml');
    }

    /**
     * Gets the validation mapping files for the format and extends them with
     * files matching a doctrine search pattern (Resources/config/validation.orm.xml)
     *
     * @param ContainerBuilder $container
     * @param string           $mapping
     * @param string           $extension
     */
    private function updateValidatorMappingFiles(ContainerBuilder $container, $mapping, $extension)
    {
        if (!$container->hasParameter('validator.mapping.loader.'.$mapping.'_files_loader.mapping_files')) {
            return;
        }

        $files = $container->getParameter('validator.mapping.loader.'.$mapping.'_files_loader.mapping_files');
        $validationPath = 'Resources/config/validation.'.$this->managerType.'.'.$extension;

        foreach ($container->getParameter('kernel.bundles') as $bundle) {
            $reflection = new \ReflectionClass($bundle);
            if (is_file($file = dirname($reflection->getFilename()).'/'.$validationPath)) {
                $files[] = realpath($file);
                $container->addResource(new FileResource($file));
            }
        }

        $container->setParameter('validator.mapping.loader.'.$mapping.'_files_loader.mapping_files', $files);
    }
}
PKs�Z��4NN%Symfony/Bridge/Monolog/autoloader.phpnu�[���<?php

spl_autoload_register(function ($class) {
    if ('\\' == $class[0]) {
        $class = substr($class, 1);
    }

    if (
        0 === strpos($class, 'Symfony\\Bridge\\Monolog\\')
        &&
        file_exists($file = __DIR__.'/../../../'.str_replace('\\', '/', $class).'.php')
    ) {
        require_once $file;
    }
});
PKs�Z��մ��1Symfony/Bridge/Monolog/Handler/FirePHPHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Monolog\Handler;

use Monolog\Handler\FirePHPHandler as BaseFirePHPHandler;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpFoundation\Response;

/**
 * FirePHPHandler.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class FirePHPHandler extends BaseFirePHPHandler
{
    /**
     * @var array
     */
    private $headers = array();

    /**
     * @var Response
     */
    private $response;

    /**
     * Adds the headers to the response once it's created
     */
    public function onKernelResponse(FilterResponseEvent $event)
    {
        if (!$event->isMasterRequest()) {
            return;
        }

        if (!preg_match('{\bFirePHP/\d+\.\d+\b}', $event->getRequest()->headers->get('User-Agent'))
            && !$event->getRequest()->headers->has('X-FirePHP-Version')) {

            $this->sendHeaders = false;
            $this->headers = array();

            return;
        }

        $this->response = $event->getResponse();
        foreach ($this->headers as $header => $content) {
            $this->response->headers->set($header, $content);
        }
        $this->headers = array();
    }

    /**
     * {@inheritDoc}
     */
    protected function sendHeader($header, $content)
    {
        if (!$this->sendHeaders) {
            return;
        }

        if ($this->response) {
            $this->response->headers->set($header, $content);
        } else {
            $this->headers[$header] = $content;
        }
    }

    /**
     * Override default behavior since we check the user agent in onKernelResponse
     */
    protected function headersAccepted()
    {
        return true;
    }
}
PKs�Z��Zv��/Symfony/Bridge/Monolog/Handler/DebugHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Monolog\Handler;

use Monolog\Logger;
use Monolog\Handler\TestHandler;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;

/**
 * DebugLogger.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class DebugHandler extends TestHandler implements DebugLoggerInterface
{
    /**
     * {@inheritdoc}
     */
    public function getLogs()
    {
        $records = array();
        foreach ($this->records as $record) {
            $records[] = array(
                'timestamp'    => $record['datetime']->getTimestamp(),
                'message'      => $record['message'],
                'priority'     => $record['level'],
                'priorityName' => $record['level_name'],
                'context'      => $record['context'],
            );
        }

        return $records;
    }

    /**
     * {@inheritdoc}
     */
    public function countErrors()
    {
        $cnt = 0;
        $levels = array(Logger::ERROR, Logger::CRITICAL, Logger::ALERT, Logger::EMERGENCY);
        foreach ($levels as $level) {
            if (isset($this->recordsByLevel[$level])) {
                $cnt += count($this->recordsByLevel[$level]);
            }
        }

        return $cnt;
    }
}
PKs�Z�y���1Symfony/Bridge/Monolog/Handler/ConsoleHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Monolog\Handler;

use Monolog\Handler\AbstractProcessingHandler;
use Monolog\Logger;
use Symfony\Bridge\Monolog\Formatter\ConsoleFormatter;
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Writes logs to the console output depending on its verbosity setting.
 *
 * It is disabled by default and gets activated as soon as a command is executed.
 * Instead of listening to the console events, the output can also be set manually.
 *
 * The minimum logging level at which this handler will be triggered depends on the
 * verbosity setting of the console output. The default mapping is:
 * - OutputInterface::VERBOSITY_NORMAL will show all WARNING and higher logs
 * - OutputInterface::VERBOSITY_VERBOSE (-v) will show all NOTICE and higher logs
 * - OutputInterface::VERBOSITY_VERY_VERBOSE (-vv) will show all INFO and higher logs
 * - OutputInterface::VERBOSITY_DEBUG (-vvv) will show all DEBUG and higher logs, i.e. all logs
 *
 * This mapping can be customized with the $verbosityLevelMap constructor parameter.
 *
 * @author Tobias Schultze <http://tobion.de>
 */
class ConsoleHandler extends AbstractProcessingHandler implements EventSubscriberInterface
{
    /**
     * @var OutputInterface|null
     */
    private $output;

    /**
     * @var array
     */
    private $verbosityLevelMap = array(
        OutputInterface::VERBOSITY_NORMAL => Logger::WARNING,
        OutputInterface::VERBOSITY_VERBOSE => Logger::NOTICE,
        OutputInterface::VERBOSITY_VERY_VERBOSE => Logger::INFO,
        OutputInterface::VERBOSITY_DEBUG => Logger::DEBUG
    );

    /**
     * Constructor.
     *
     * @param OutputInterface|null $output            The console output to use (the handler remains disabled when passing null
     *                                                until the output is set, e.g. by using console events)
     * @param Boolean              $bubble            Whether the messages that are handled can bubble up the stack
     * @param array                $verbosityLevelMap Array that maps the OutputInterface verbosity to a minimum logging
     *                                                level (leave empty to use the default mapping)
     */
    public function __construct(OutputInterface $output = null, $bubble = true, array $verbosityLevelMap = array())
    {
        parent::__construct(Logger::DEBUG, $bubble);
        $this->output = $output;

        if ($verbosityLevelMap) {
            $this->verbosityLevelMap = $verbosityLevelMap;
        }
    }

    /**
     * {@inheritdoc}
     */
    public function isHandling(array $record)
    {
        return $this->updateLevel() && parent::isHandling($record);
    }

    /**
     * {@inheritdoc}
     */
    public function handle(array $record)
    {
        // we have to update the logging level each time because the verbosity of the
        // console output might have changed in the meantime (it is not immutable)
        return $this->updateLevel() && parent::handle($record);
    }

    /**
     * Sets the console output to use for printing logs.
     *
     * @param OutputInterface $output The console output to use
     */
    public function setOutput(OutputInterface $output)
    {
        $this->output = $output;
    }

    /**
     * Disables the output.
     */
    public function close()
    {
        $this->output = null;

        parent::close();
    }

    /**
     * Before a command is executed, the handler gets activated and the console output
     * is set in order to know where to write the logs.
     *
     * @param ConsoleCommandEvent $event
     */
    public function onCommand(ConsoleCommandEvent $event)
    {
        $this->setOutput($event->getOutput());
    }

    /**
     * After a command has been executed, it disables the output.
     *
     * @param ConsoleTerminateEvent $event
     */
    public function onTerminate(ConsoleTerminateEvent $event)
    {
        $this->close();
    }

    /**
     * {@inheritdoc}
     */
    public static function getSubscribedEvents()
    {
        return array(
            ConsoleEvents::COMMAND => 'onCommand',
            ConsoleEvents::TERMINATE => 'onTerminate'
        );
    }

    /**
     * {@inheritdoc}
     */
    protected function write(array $record)
    {
        if ($record['level'] >= Logger::ERROR && $this->output instanceof ConsoleOutputInterface) {
            $this->output->getErrorOutput()->write((string) $record['formatted']);
        } else {
            $this->output->write((string) $record['formatted']);
        }
    }

    /**
     * {@inheritdoc}
     */
    protected function getDefaultFormatter()
    {
        return new ConsoleFormatter();
    }

    /**
     * Updates the logging level based on the verbosity setting of the console output.
     *
     * @return Boolean Whether the handler is enabled and verbosity is not set to quiet.
     */
    private function updateLevel()
    {
        if (null === $this->output || OutputInterface::VERBOSITY_QUIET === $verbosity = $this->output->getVerbosity()) {
            return false;
        }

        if (isset($this->verbosityLevelMap[$verbosity])) {
            $this->setLevel($this->verbosityLevelMap[$verbosity]);
        } else {
            $this->setLevel(Logger::DEBUG);
        }

        return true;
    }
}
PKs�Z��*vv5Symfony/Bridge/Monolog/Handler/SwiftMailerHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Monolog\Handler;

use Monolog\Handler\SwiftMailerHandler as BaseSwiftMailerHandler;
use Symfony\Component\HttpKernel\Event\PostResponseEvent;

/**
 * Extended SwiftMailerHandler that flushes mail queue if necessary
 *
 * @author Philipp Kräutli <pkraeutli@astina.ch>
 */
class SwiftMailerHandler extends BaseSwiftMailerHandler
{
    protected $transport;

    protected $instantFlush = false;

    /**
     * @param \Swift_Transport $transport
     */
    public function setTransport(\Swift_Transport $transport)
    {
        $this->transport = $transport;
    }

    /**
     * After the kernel has been terminated we will always flush messages
     *
     * @param PostResponseEvent $event
     */
    public function onKernelTerminate(PostResponseEvent $event)
    {
        $this->instantFlush = true;
    }

    /**
     * {@inheritdoc}
     */
    protected function send($content, array $records)
    {
        parent::send($content, $records);

        if ($this->instantFlush) {
            $this->flushMemorySpool();
        }
    }

    /**
     * Flushes the mail queue if a memory spool is used
     */
    private function flushMemorySpool()
    {
        $mailerTransport = $this->mailer->getTransport();
        if (!$mailerTransport instanceof \Swift_Transport_SpoolTransport) {
            return;
        }

        $spool = $mailerTransport->getSpool();
        if (!$spool instanceof \Swift_MemorySpool) {
            return;
        }

        if (null === $this->transport) {
            throw new \Exception('No transport available to flush mail queue');
        }

        $spool->flushQueue($this->transport);
    }
}
PKs�Z���"II3Symfony/Bridge/Monolog/Handler/ChromePhpHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Monolog\Handler;

use Monolog\Handler\ChromePHPHandler as BaseChromePhpHandler;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;

/**
 * ChromePhpHandler.
 *
 * @author Christophe Coevoet <stof@notk.org>
 */
class ChromePhpHandler extends BaseChromePhpHandler
{
    /**
     * @var array
     */
    private $headers = array();

    /**
     * @var Response
     */
    private $response;

    /**
     * Adds the headers to the response once it's created
     */
    public function onKernelResponse(FilterResponseEvent $event)
    {
        if (!$event->isMasterRequest()) {
            return;
        }

        if (!preg_match('{\bChrome/\d+[\.\d+]*\b}', $event->getRequest()->headers->get('User-Agent'))) {

            $this->sendHeaders = false;
            $this->headers = array();

            return;
        }

        $this->response = $event->getResponse();
        foreach ($this->headers as $header => $content) {
            $this->response->headers->set($header, $content);
        }
        $this->headers = array();
    }

    /**
     * {@inheritDoc}
     */
    protected function sendHeader($header, $content)
    {
        if (!$this->sendHeaders) {
            return;
        }

        if ($this->response) {
            $this->response->headers->set($header, $content);
        } else {
            $this->headers[$header] = $content;
        }
    }

    /**
     * Override default behavior since we check it in onKernelResponse
     */
    protected function headersAccepted()
    {
        return true;
    }
}
PKs�Z��;��	�	!Symfony/Bridge/Monolog/Logger.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Monolog;

use Monolog\Logger as BaseLogger;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;

/**
 * Logger.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Logger extends BaseLogger implements LoggerInterface, DebugLoggerInterface
{
    /**
     * @deprecated since 2.2, to be removed in 3.0. Use emergency() which is PSR-3 compatible.
     */
    public function emerg($message, array $context = array())
    {
        return parent::addRecord(BaseLogger::EMERGENCY, $message, $context);
    }

    /**
     * @deprecated since 2.2, to be removed in 3.0. Use critical() which is PSR-3 compatible.
     */
    public function crit($message, array $context = array())
    {
        return parent::addRecord(BaseLogger::CRITICAL, $message, $context);
    }

    /**
     * @deprecated since 2.2, to be removed in 3.0. Use error() which is PSR-3 compatible.
     */
    public function err($message, array $context = array())
    {
        return parent::addRecord(BaseLogger::ERROR, $message, $context);
    }

    /**
     * @deprecated since 2.2, to be removed in 3.0. Use warning() which is PSR-3 compatible.
     */
    public function warn($message, array $context = array())
    {
        return parent::addRecord(BaseLogger::WARNING, $message, $context);
    }

    /**
     * @see Symfony\Component\HttpKernel\Log\DebugLoggerInterface
     */
    public function getLogs()
    {
        if ($logger = $this->getDebugLogger()) {
            return $logger->getLogs();
        }

        return array();
    }

    /**
     * @see Symfony\Component\HttpKernel\Log\DebugLoggerInterface
     */
    public function countErrors()
    {
        if ($logger = $this->getDebugLogger()) {
            return $logger->countErrors();
        }

        return 0;
    }

    /**
     * Returns a DebugLoggerInterface instance if one is registered with this logger.
     *
     * @return DebugLoggerInterface|null A DebugLoggerInterface instance or null if none is registered
     */
    private function getDebugLogger()
    {
        foreach ($this->handlers as $handler) {
            if ($handler instanceof DebugLoggerInterface) {
                return $handler;
            }
        }
    }
}
PKs�Z��b115Symfony/Bridge/Monolog/Formatter/ConsoleFormatter.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Monolog\Formatter;

use Monolog\Formatter\LineFormatter;
use Monolog\Logger;

/**
 * Formats incoming records for console output by coloring them depending on log level.
 *
 * @author Tobias Schultze <http://tobion.de>
 */
class ConsoleFormatter extends LineFormatter
{
    const SIMPLE_FORMAT = "%start_tag%[%datetime%] %channel%.%level_name%:%end_tag% %message% %context% %extra%\n";

    /**
     * {@inheritdoc}
     */
    public function format(array $record)
    {
        if ($record['level'] >= Logger::ERROR) {
            $record['start_tag'] = '<error>';
            $record['end_tag']   = '</error>';
        } elseif ($record['level'] >= Logger::NOTICE) {
            $record['start_tag'] = '<comment>';
            $record['end_tag']   = '</comment>';
        } elseif ($record['level'] >= Logger::INFO) {
            $record['start_tag'] = '<info>';
            $record['end_tag']   = '</info>';
        } else {
            $record['start_tag'] = '';
            $record['end_tag']   = '';
        }

        return parent::format($record);
    }
}
PKt�Z�,��1Symfony/Bridge/Monolog/Processor/WebProcessor.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Monolog\Processor;

use Monolog\Processor\WebProcessor as BaseWebProcessor;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;

/**
 * WebProcessor override to read from the HttpFoundation's Request
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class WebProcessor extends BaseWebProcessor
{
    public function __construct()
    {
        // Pass an empty array as the default null value would access $_SERVER
        parent::__construct(array());
    }

    public function onKernelRequest(GetResponseEvent $event)
    {
        if ($event->isMasterRequest()) {
            $this->serverData = $event->getRequest()->server->all();
        }
    }
}
PKt�Z�$�KK"Symfony/Bridge/Twig/autoloader.phpnu�[���<?php

spl_autoload_register(function ($class) {
    if ('\\' == $class[0]) {
        $class = substr($class, 1);
    }

    if (
        0 === strpos($class, 'Symfony\\Bridge\\Twig\\')
        &&
        file_exists($file = __DIR__.'/../../../'.str_replace('\\', '/', $class).'.php')
    ) {
        require_once $file;
    }
});
PKt�Z�)�UU1Symfony/Bridge/Twig/Translation/TwigExtractor.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Translation;

use Symfony\Component\Finder\Finder;
use Symfony\Component\Translation\Extractor\ExtractorInterface;
use Symfony\Component\Translation\MessageCatalogue;

/**
 * TwigExtractor extracts translation messages from a twig template.
 *
 * @author Michel Salib <michelsalib@hotmail.com>
 * @author Fabien Potencier <fabien@symfony.com>
 */
class TwigExtractor implements ExtractorInterface
{
    /**
     * Default domain for found messages.
     *
     * @var string
     */
    private $defaultDomain = 'messages';

    /**
     * Prefix for found message.
     *
     * @var string
     */
    private $prefix = '';

    /**
     * The twig environment.
     *
     * @var \Twig_Environment
     */
    private $twig;

    public function __construct(\Twig_Environment $twig)
    {
        $this->twig = $twig;
    }

    /**
     * {@inheritDoc}
     */
    public function extract($directory, MessageCatalogue $catalogue)
    {
        // load any existing translation files
        $finder = new Finder();
        $files = $finder->files()->name('*.twig')->sortByName()->in($directory);
        foreach ($files as $file) {
            $this->extractTemplate(file_get_contents($file->getPathname()), $catalogue);
        }
    }

    /**
     * {@inheritDoc}
     */
    public function setPrefix($prefix)
    {
        $this->prefix = $prefix;
    }

    protected function extractTemplate($template, MessageCatalogue $catalogue)
    {
        $visitor = $this->twig->getExtension('translator')->getTranslationNodeVisitor();
        $visitor->enable();

        $this->twig->parse($this->twig->tokenize($template));

        foreach ($visitor->getMessages() as $message) {
            $catalogue->set(trim($message[0]), $this->prefix.trim($message[0]), $message[1] ? $message[1] : $this->defaultDomain);
        }

        $visitor->disable();
    }
}
PKt�Z6DZ77*Symfony/Bridge/Twig/Node/StopwatchNode.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Node;

/**
 * Represents a stopwatch node.
 *
 * @author Wouter J <wouter@wouterj.nl>
 */
class StopwatchNode extends \Twig_Node
{
    public function __construct(\Twig_NodeInterface $name, $body, \Twig_Node_Expression_AssignName $var, $lineno = 0, $tag = null)
    {
        parent::__construct(array('body' => $body, 'name' => $name, 'var' => $var), array(), $lineno, $tag);
    }

    public function compile(\Twig_Compiler $compiler)
    {
        $compiler
            ->addDebugInfo($this)
            ->write('')
            ->subcompile($this->getNode('var'))
            ->raw(' = ')
            ->subcompile($this->getNode('name'))
            ->write(";\n")
            ->write("\$this->env->getExtension('stopwatch')->getStopwatch()->start(")
            ->subcompile($this->getNode('var'))
            ->raw(", 'template');\n")
            ->subcompile($this->getNode('body'))
            ->write("\$this->env->getExtension('stopwatch')->getStopwatch()->stop(")
            ->subcompile($this->getNode('var'))
            ->raw(");\n")
        ;
    }
}
PKt�Z,
�@��5Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Node;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class SearchAndRenderBlockNode extends \Twig_Node_Expression_Function
{
    public function compile(\Twig_Compiler $compiler)
    {
        $compiler->addDebugInfo($this);
        $compiler->raw('$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(');

        preg_match('/_([^_]+)$/', $this->getAttribute('name'), $matches);

        $label = null;
        $arguments = iterator_to_array($this->getNode('arguments'));
        $blockNameSuffix = $matches[1];

        if (isset($arguments[0])) {
            $compiler->subcompile($arguments[0]);
            $compiler->raw(', \''.$blockNameSuffix.'\'');

            if (isset($arguments[1])) {
                if ('label' === $blockNameSuffix) {
                    // The "label" function expects the label in the second and
                    // the variables in the third argument
                    $label = $arguments[1];
                    $variables = isset($arguments[2]) ? $arguments[2] : null;
                    $lineno = $label->getLine();

                    if ($label instanceof \Twig_Node_Expression_Constant) {
                        // If the label argument is given as a constant, we can either
                        // strip it away if it is empty, or integrate it into the array
                        // of variables at compile time.
                        $labelIsExpression = false;

                        // Only insert the label into the array if it is not empty
                        if (!twig_test_empty($label->getAttribute('value'))) {
                            $originalVariables = $variables;
                            $variables = new \Twig_Node_Expression_Array(array(), $lineno);
                            $labelKey = new \Twig_Node_Expression_Constant('label', $lineno);

                            if (null !== $originalVariables) {
                                foreach ($originalVariables->getKeyValuePairs() as $pair) {
                                    // Don't copy the original label attribute over if it exists
                                    if ((string) $labelKey !== (string) $pair['key']) {
                                        $variables->addElement($pair['value'], $pair['key']);
                                    }
                                }
                            }

                            // Insert the label argument into the array
                            $variables->addElement($label, $labelKey);
                        }
                    } else {
                        // The label argument is not a constant, but some kind of
                        // expression. This expression needs to be evaluated at runtime.
                        // Depending on the result (whether it is null or not), the
                        // label in the arguments should take precedence over the label
                        // in the attributes or not.
                        $labelIsExpression = true;
                    }
                } else {
                    // All other functions than "label" expect the variables
                    // in the second argument
                    $label = null;
                    $variables = $arguments[1];
                    $labelIsExpression = false;
                }

                if (null !== $variables || $labelIsExpression) {
                    $compiler->raw(', ');

                    if (null !== $variables) {
                        $compiler->subcompile($variables);
                    }

                    if ($labelIsExpression) {
                        if (null !== $variables) {
                            $compiler->raw(' + ');
                        }

                        // Check at runtime whether the label is empty.
                        // If not, add it to the array at runtime.
                        $compiler->raw('(twig_test_empty($_label_ = ');
                        $compiler->subcompile($label);
                        $compiler->raw(') ? array() : array("label" => $_label_))');
                    }
                }
            }
        }

        $compiler->raw(")");
    }
}
PKt�Z�
�s>>*Symfony/Bridge/Twig/Node/FormThemeNode.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Node;

/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FormThemeNode extends \Twig_Node
{
    public function __construct(\Twig_NodeInterface $form, \Twig_NodeInterface $resources, $lineno, $tag = null)
    {
        parent::__construct(array('form' => $form, 'resources' => $resources), array(), $lineno, $tag);
    }

    /**
     * Compiles the node to PHP.
     *
     * @param \Twig_Compiler $compiler A Twig_Compiler instance
     */
    public function compile(\Twig_Compiler $compiler)
    {
        $compiler
            ->addDebugInfo($this)
            ->write('$this->env->getExtension(\'form\')->renderer->setTheme(')
            ->subcompile($this->getNode('form'))
            ->raw(', ')
            ->subcompile($this->getNode('resources'))
            ->raw(");\n");
        ;
    }
}
PKt�ZP�IAA3Symfony/Bridge/Twig/Node/TransDefaultDomainNode.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Node;

/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
class TransDefaultDomainNode extends \Twig_Node
{
    public function __construct(\Twig_Node_Expression $expr, $lineno = 0, $tag = null)
    {
        parent::__construct(array('expr' => $expr), array(), $lineno, $tag);
    }

    /**
     * Compiles the node to PHP.
     *
     * @param \Twig_Compiler $compiler A Twig_Compiler instance
     */
    public function compile(\Twig_Compiler $compiler)
    {
        // noop as this node is just a marker for TranslationDefaultDomainNodeVisitor
    }
}
PKt�Z�U,tt,Symfony/Bridge/Twig/Node/FormEnctypeNode.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Node;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
 *             the helper "form_start()" instead.
 */
class FormEnctypeNode extends SearchAndRenderBlockNode
{
    public function compile(\Twig_Compiler $compiler)
    {
        parent::compile($compiler);

        // Uncomment this as soon as the deprecation note should be shown
        // $compiler->write('trigger_error(\'The helper form_enctype(form) is deprecated since version 2.3 and will be removed in 3.0. Use form_start(form) instead.\', E_USER_DEPRECATED)');
    }
}
PKt�Zʦ\�G
G
&Symfony/Bridge/Twig/Node/TransNode.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Node;

/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
class TransNode extends \Twig_Node
{
    public function __construct(\Twig_NodeInterface $body, \Twig_NodeInterface $domain = null, \Twig_Node_Expression $count = null, \Twig_Node_Expression $vars = null, \Twig_Node_Expression $locale = null, $lineno = 0, $tag = null)
    {
        parent::__construct(array('count' => $count, 'body' => $body, 'domain' => $domain, 'vars' => $vars, 'locale' => $locale), array(), $lineno, $tag);
    }

    /**
     * Compiles the node to PHP.
     *
     * @param \Twig_Compiler $compiler A Twig_Compiler instance
     */
    public function compile(\Twig_Compiler $compiler)
    {
        $compiler->addDebugInfo($this);

        $vars = $this->getNode('vars');
        $defaults = new \Twig_Node_Expression_Array(array(), -1);
        if ($vars instanceof \Twig_Node_Expression_Array) {
            $defaults = $this->getNode('vars');
            $vars = null;
        }
        list($msg, $defaults) = $this->compileString($this->getNode('body'), $defaults);

        $method = null === $this->getNode('count') ? 'trans' : 'transChoice';

        $compiler
            ->write('echo $this->env->getExtension(\'translator\')->getTranslator()->'.$method.'(')
            ->subcompile($msg)
        ;

        $compiler->raw(', ');

        if (null !== $this->getNode('count')) {
            $compiler
                ->subcompile($this->getNode('count'))
                ->raw(', ')
            ;
        }

        if (null !== $vars) {
            $compiler
                ->raw('array_merge(')
                ->subcompile($defaults)
                ->raw(', ')
                ->subcompile($this->getNode('vars'))
                ->raw(')')
            ;
        } else {
            $compiler->subcompile($defaults);
        }

        $compiler->raw(', ');

        if (null === $this->getNode('domain')) {
            $compiler->repr('messages');
        } else {
            $compiler->subcompile($this->getNode('domain'));
        }

        if (null !== $this->getNode('locale')) {
            $compiler
                ->raw(', ')
                ->subcompile($this->getNode('locale'))
            ;
        }
        $compiler->raw(");\n");
    }

    protected function compileString(\Twig_NodeInterface $body, \Twig_Node_Expression_Array $vars)
    {
        if ($body instanceof \Twig_Node_Expression_Constant) {
            $msg = $body->getAttribute('value');
        } elseif ($body instanceof \Twig_Node_Text) {
            $msg = $body->getAttribute('data');
        } else {
            return array($body, $vars);
        }

        preg_match_all('/(?<!%)%([^%]+)%/', $msg, $matches);

        foreach ($matches[1] as $var) {
            $key = new \Twig_Node_Expression_Constant('%'.$var.'%', $body->getLine());
            if (!$vars->hasElement($key)) {
                $vars->addElement(new \Twig_Node_Expression_Name($var, $body->getLine()), $key);
            }
        }

        return array(new \Twig_Node_Expression_Constant(str_replace('%%', '%', trim($msg)), $body->getLine()), $vars);
    }
}
PKt�Z���^��,Symfony/Bridge/Twig/Node/RenderBlockNode.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Node;

/**
 * Compiles a call to {@link FormRendererInterface::renderBlock()}.
 *
 * The function name is used as block name. For example, if the function name
 * is "foo", the block "foo" will be rendered.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class RenderBlockNode extends \Twig_Node_Expression_Function
{
    public function compile(\Twig_Compiler $compiler)
    {
        $compiler->addDebugInfo($this);
        $arguments = iterator_to_array($this->getNode('arguments'));
        $compiler->write('$this->env->getExtension(\'form\')->renderer->renderBlock(');

        if (isset($arguments[0])) {
            $compiler->subcompile($arguments[0]);
            $compiler->raw(', \'' . $this->getAttribute('name') . '\'');

            if (isset($arguments[1])) {
                $compiler->raw(', ');
                $compiler->subcompile($arguments[1]);
            }
        }

        $compiler->raw(')');
    }
}
PKt�Z�vq�)Symfony/Bridge/Twig/Form/TwigRenderer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Form;

use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter;
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
use Symfony\Component\Form\FormRenderer;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class TwigRenderer extends FormRenderer implements TwigRendererInterface
{
    /**
     * @var TwigRendererEngineInterface
     */
    private $engine;

    public function __construct(TwigRendererEngineInterface $engine, $csrfTokenManager = null)
    {
        if ($csrfTokenManager instanceof CsrfProviderInterface) {
            $csrfTokenManager = new CsrfProviderAdapter($csrfTokenManager);
        } elseif (null !== $csrfTokenManager && !$csrfTokenManager instanceof CsrfTokenManagerInterface) {
            throw new UnexpectedTypeException($csrfTokenManager, 'CsrfProviderInterface or CsrfTokenManagerInterface');
        }

        parent::__construct($engine, $csrfTokenManager);

        $this->engine = $engine;
    }

    /**
     * {@inheritdoc}
     */
    public function setEnvironment(\Twig_Environment $environment)
    {
        $this->engine->setEnvironment($environment);
    }
}
PKt�Zb�3�}}8Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Form;

use Symfony\Component\Form\FormRendererEngineInterface;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface TwigRendererEngineInterface extends FormRendererEngineInterface
{
    /**
     * Sets Twig's environment.
     *
     * @param \Twig_Environment $environment
     */
    public function setEnvironment(\Twig_Environment $environment);
}
PKt�Z��Qkk2Symfony/Bridge/Twig/Form/TwigRendererInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Form;

use Symfony\Component\Form\FormRendererInterface;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface TwigRendererInterface extends FormRendererInterface
{
    /**
     * Sets Twig's environment.
     *
     * @param \Twig_Environment $environment
     */
    public function setEnvironment(\Twig_Environment $environment);
}
PKt�Z��<��/Symfony/Bridge/Twig/Form/TwigRendererEngine.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Form;

use Symfony\Component\Form\AbstractRendererEngine;
use Symfony\Component\Form\FormView;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class TwigRendererEngine extends AbstractRendererEngine implements TwigRendererEngineInterface
{
    /**
     * @var \Twig_Environment
     */
    private $environment;

    /**
     * @var \Twig_Template
     */
    private $template;

    /**
     * {@inheritdoc}
     */
    public function setEnvironment(\Twig_Environment $environment)
    {
        $this->environment = $environment;
    }

    /**
     * {@inheritdoc}
     */
    public function renderBlock(FormView $view, $resource, $blockName, array $variables = array())
    {
        $cacheKey = $view->vars[self::CACHE_KEY_VAR];

        $context = $this->environment->mergeGlobals($variables);

        ob_start();

        // By contract,This method can only be called after getting the resource
        // (which is passed to the method). Getting a resource for the first time
        // (with an empty cache) is guaranteed to invoke loadResourcesFromTheme(),
        // where the property $template is initialized.

        // We do not call renderBlock here to avoid too many nested level calls
        // (XDebug limits the level to 100 by default)
        $this->template->displayBlock($blockName, $context, $this->resources[$cacheKey]);

        return ob_get_clean();
    }

    /**
     * Loads the cache with the resource for a given block name.
     *
     * This implementation eagerly loads all blocks of the themes assigned to the given view
     * and all of its ancestors views. This is necessary, because Twig receives the
     * list of blocks later. At that point, all blocks must already be loaded, for the
     * case that the function "block()" is used in the Twig template.
     *
     * @see getResourceForBlock()
     *
     * @param string   $cacheKey  The cache key of the form view.
     * @param FormView $view      The form view for finding the applying themes.
     * @param string   $blockName The name of the block to load.
     *
     * @return Boolean True if the resource could be loaded, false otherwise.
     */
    protected function loadResourceForBlockName($cacheKey, FormView $view, $blockName)
    {
        // The caller guarantees that $this->resources[$cacheKey][$block] is
        // not set, but it doesn't have to check whether $this->resources[$cacheKey]
        // is set. If $this->resources[$cacheKey] is set, all themes for this
        // $cacheKey are already loaded (due to the eager population, see doc comment).
        if (isset($this->resources[$cacheKey])) {
            // As said in the previous, the caller guarantees that
            // $this->resources[$cacheKey][$block] is not set. Since the themes are
            // already loaded, it can only be a non-existing block.
            $this->resources[$cacheKey][$blockName] = false;

            return false;
        }

        // Recursively try to find the block in the themes assigned to $view,
        // then of its parent view, then of the parent view of the parent and so on.
        // When the root view is reached in this recursion, also the default
        // themes are taken into account.

        // Check each theme whether it contains the searched block
        if (isset($this->themes[$cacheKey])) {
            for ($i = count($this->themes[$cacheKey]) - 1; $i >= 0; --$i) {
                $this->loadResourcesFromTheme($cacheKey, $this->themes[$cacheKey][$i]);
                // CONTINUE LOADING (see doc comment)
            }
        }

        // Check the default themes once we reach the root view without success
        if (!$view->parent) {
            for ($i = count($this->defaultThemes) - 1; $i >= 0; --$i) {
                $this->loadResourcesFromTheme($cacheKey, $this->defaultThemes[$i]);
                // CONTINUE LOADING (see doc comment)
            }
        }

        // Proceed with the themes of the parent view
        if ($view->parent) {
            $parentCacheKey = $view->parent->vars[self::CACHE_KEY_VAR];

            if (!isset($this->resources[$parentCacheKey])) {
                $this->loadResourceForBlockName($parentCacheKey, $view->parent, $blockName);
            }

            // EAGER CACHE POPULATION (see doc comment)
            foreach ($this->resources[$parentCacheKey] as $nestedBlockName => $resource) {
                if (!isset($this->resources[$cacheKey][$nestedBlockName])) {
                    $this->resources[$cacheKey][$nestedBlockName] = $resource;
                }
            }
        }

        // Even though we loaded the themes, it can happen that none of them
        // contains the searched block
        if (!isset($this->resources[$cacheKey][$blockName])) {
            // Cache that we didn't find anything to speed up further accesses
            $this->resources[$cacheKey][$blockName] = false;
        }

        return false !== $this->resources[$cacheKey][$blockName];
    }

    /**
     * Loads the resources for all blocks in a theme.
     *
     * @param string $cacheKey The cache key for storing the resource.
     * @param mixed  $theme    The theme to load the block from. This parameter
     *                         is passed by reference, because it might be necessary
     *                         to initialize the theme first. Any changes made to
     *                         this variable will be kept and be available upon
     *                         further calls to this method using the same theme.
     */
    protected function loadResourcesFromTheme($cacheKey, &$theme)
    {
        if (!$theme instanceof \Twig_Template) {
            /* @var \Twig_Template $theme */
            $theme = $this->environment->loadTemplate($theme);
        }

        if (null === $this->template) {
            // Store the first \Twig_Template instance that we find so that
            // we can call displayBlock() later on. It doesn't matter *which*
            // template we use for that, since we pass the used blocks manually
            // anyway.
            $this->template = $theme;
        }

        // Use a separate variable for the inheritance traversal, because
        // theme is a reference and we don't want to change it.
        $currentTheme = $theme;

        $context = $this->environment->mergeGlobals(array());

        // The do loop takes care of template inheritance.
        // Add blocks from all templates in the inheritance tree, but avoid
        // overriding blocks already set.
        do {
            foreach ($currentTheme->getBlocks() as $block => $blockData) {
                if (!isset($this->resources[$cacheKey][$block])) {
                    // The resource given back is the key to the bucket that
                    // contains this block.
                    $this->resources[$cacheKey][$block] = $blockData;
                }
            }
        } while (false !== $currentTheme = $currentTheme->getParent($context));
    }
}
PKt�Z�GSymfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\NodeVisitor;

use Symfony\Bridge\Twig\Node\TransNode;
use Symfony\Bridge\Twig\Node\TransDefaultDomainNode;

/**
 * TranslationDefaultDomainNodeVisitor.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class TranslationDefaultDomainNodeVisitor implements \Twig_NodeVisitorInterface
{
    /**
     * @var Scope
     */
    private $scope;

    /**
     * Constructor.
     */
    public function __construct()
    {
        $this->scope = new Scope();
    }

    /**
     * {@inheritdoc}
     */
    public function enterNode(\Twig_NodeInterface $node, \Twig_Environment $env)
    {
        if ($node instanceof \Twig_Node_Block || $node instanceof \Twig_Node_Module) {
            $this->scope = $this->scope->enter();
        }

        if ($node instanceof TransDefaultDomainNode) {
            if ($node->getNode('expr') instanceof \Twig_Node_Expression_Constant) {
                $this->scope->set('domain', $node->getNode('expr'));

                return $node;
            } else {
                $var = $env->getParser()->getVarName();
                $name = new \Twig_Node_Expression_AssignName($var, $node->getLine());
                $this->scope->set('domain', new \Twig_Node_Expression_Name($var, $node->getLine()));

                return new \Twig_Node_Set(false, new \Twig_Node(array($name)), new \Twig_Node(array($node->getNode('expr'))), $node->getLine());
            }
        }

        if (!$this->scope->has('domain')) {
            return $node;
        }

        if ($node instanceof \Twig_Node_Expression_Filter && in_array($node->getNode('filter')->getAttribute('value'), array('trans', 'transchoice'))) {
            $ind = 'trans' === $node->getNode('filter')->getAttribute('value') ? 1 : 2;
            $arguments = $node->getNode('arguments');
            if (!$arguments->hasNode($ind)) {
                if (!$arguments->hasNode($ind - 1)) {
                    $arguments->setNode($ind - 1, new \Twig_Node_Expression_Array(array(), $node->getLine()));
                }

                $arguments->setNode($ind, $this->scope->get('domain'));
            }
        } elseif ($node instanceof TransNode) {
            if (null === $node->getNode('domain')) {
                $node->setNode('domain', $this->scope->get('domain'));
            }
        }

        return $node;
    }

    /**
     * {@inheritdoc}
     */
    public function leaveNode(\Twig_NodeInterface $node, \Twig_Environment $env)
    {
        if ($node instanceof TransDefaultDomainNode) {
            return false;
        }

        if ($node instanceof \Twig_Node_Block || $node instanceof \Twig_Node_Module) {
            $this->scope = $this->scope->leave();
        }

        return $node;
    }

    /**
     * {@inheritdoc}
     */
    public function getPriority()
    {
        return -10;
    }
}
PKt�Z�)�[n	n	)Symfony/Bridge/Twig/NodeVisitor/Scope.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\NodeVisitor;

/**
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class Scope
{
    /**
     * @var Scope|null
     */
    private $parent;

    /**
     * @var Scope[]
     */
    private $children;

    /**
     * @var array
     */
    private $data = array();

    /**
     * @var boolean
     */
    private $left = false;

    /**
     * @param Scope $parent
     */
    public function __construct(Scope $parent = null)
    {
        $this->parent = $parent;
    }

    /**
     * Opens a new child scope.
     *
     * @return Scope
     */
    public function enter()
    {
        $child = new self($this);
        $this->children[] = $child;

        return $child;
    }

    /**
     * Closes current scope and returns parent one.
     *
     * @return Scope|null
     */
    public function leave()
    {
        $this->left = true;

        return $this->parent;
    }

    /**
     * Stores data into current scope.
     *
     * @param string $key
     * @param mixed  $value
     *
     * @throws \LogicException
     *
     * @return Scope Current scope
     */
    public function set($key, $value)
    {
        if ($this->left) {
            throw new \LogicException('Left scope is not mutable.');
        }

        $this->data[$key] = $value;

        return $this;
    }

    /**
     * Tests if a data is visible from current scope.
     *
     * @param string $key
     *
     * @return boolean
     */
    public function has($key)
    {
        if (array_key_exists($key, $this->data)) {
            return true;
        }

        if (null === $this->parent) {
            return false;
        }

        return $this->parent->has($key);
    }

    /**
     * Returns data visible from current scope.
     *
     * @param string $key
     * @param mixed  $default
     *
     * @return mixed
     */
    public function get($key, $default = null)
    {
        if (array_key_exists($key, $this->data)) {
            return $this->data[$key];
        }

        if (null === $this->parent) {
            return $default;
        }

        return $this->parent->get($key, $default);
    }
}
PKt�Z�tA�:Symfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\NodeVisitor;

use Symfony\Bridge\Twig\Node\TransNode;

/**
 * TranslationNodeVisitor extracts translation messages.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class TranslationNodeVisitor implements \Twig_NodeVisitorInterface
{
    const UNDEFINED_DOMAIN = '_undefined';

    private $enabled = false;
    private $messages = array();

    public function enable()
    {
        $this->enabled = true;
        $this->messages = array();
    }

    public function disable()
    {
        $this->enabled = false;
        $this->messages = array();
    }

    public function getMessages()
    {
        return $this->messages;
    }

    /**
     * {@inheritdoc}
     */
    public function enterNode(\Twig_NodeInterface $node, \Twig_Environment $env)
    {
        if (!$this->enabled) {
            return $node;
        }

        if (
            $node instanceof \Twig_Node_Expression_Filter &&
            'trans' === $node->getNode('filter')->getAttribute('value') &&
            $node->getNode('node') instanceof \Twig_Node_Expression_Constant
        ) {
            // extract constant nodes with a trans filter
            $this->messages[] = array(
                $node->getNode('node')->getAttribute('value'),
                $this->getReadDomainFromArguments($node->getNode('arguments'), 1),
            );
        } elseif (
            $node instanceof \Twig_Node_Expression_Filter &&
            'transchoice' === $node->getNode('filter')->getAttribute('value') &&
            $node->getNode('node') instanceof \Twig_Node_Expression_Constant
        ) {
            // extract constant nodes with a trans filter
            $this->messages[] = array(
                $node->getNode('node')->getAttribute('value'),
                $this->getReadDomainFromArguments($node->getNode('arguments'), 2),
            );
        } elseif ($node instanceof TransNode) {
            // extract trans nodes
            $this->messages[] = array(
                $node->getNode('body')->getAttribute('data'),
                $this->getReadDomainFromNode($node->getNode('domain')),
            );
        }

        return $node;
    }

    /**
     * {@inheritdoc}
     */
    public function leaveNode(\Twig_NodeInterface $node, \Twig_Environment $env)
    {
        return $node;
    }

    /**
     * {@inheritdoc}
     */
    public function getPriority()
    {
        return 0;
    }

    /**
     * @param \Twig_Node $arguments
     * @param int        $index
     *
     * @return string|null
     */
    private function getReadDomainFromArguments(\Twig_Node $arguments, $index)
    {
        if ($arguments->hasNode('domain')) {
            $argument = $arguments->getNode('domain');
        } elseif ($arguments->hasNode($index)) {
            $argument = $arguments->getNode($index);
        } else {
            return null;
        }

        return $this->getReadDomainFromNode($argument);
    }

    /**
     * @param \Twig_Node $node
     *
     * @return string|null
     */
    private function getReadDomainFromNode(\Twig_Node $node = null)
    {
        if (null === $node) {
            return null;
        }

        if ($node instanceof \Twig_Node_Expression_Constant) {
            return $node->getAttribute('value');
        }

        return self::UNDEFINED_DOMAIN;
    }
}
PKt�Z��9292BSymfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twignu�[���{# Widgets #}

{% block form_widget %}
{% spaceless %}
    {% if compound %}
        {{ block('form_widget_compound') }}
    {% else %}
        {{ block('form_widget_simple') }}
    {% endif %}
{% endspaceless %}
{% endblock form_widget %}

{% block form_widget_simple %}
{% spaceless %}
    {% set type = type|default('text') %}
    <input type="{{ type }}" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value }}" {% endif %}/>
{% endspaceless %}
{% endblock form_widget_simple %}

{% block form_widget_compound %}
{% spaceless %}
    <div {{ block('widget_container_attributes') }}>
        {% if form.parent is empty %}
            {{ form_errors(form) }}
        {% endif %}
        {{ block('form_rows') }}
        {{ form_rest(form) }}
    </div>
{% endspaceless %}
{% endblock form_widget_compound %}

{% block collection_widget %}
{% spaceless %}
    {% if prototype is defined %}
        {% set attr = attr|merge({'data-prototype': form_row(prototype) }) %}
    {% endif %}
    {{ block('form_widget') }}
{% endspaceless %}
{% endblock collection_widget %}

{% block textarea_widget %}
{% spaceless %}
    <textarea {{ block('widget_attributes') }}>{{ value }}</textarea>
{% endspaceless %}
{% endblock textarea_widget %}

{% block choice_widget %}
{% spaceless %}
    {% if expanded %}
        {{ block('choice_widget_expanded') }}
    {% else %}
        {{ block('choice_widget_collapsed') }}
    {% endif %}
{% endspaceless %}
{% endblock choice_widget %}

{% block choice_widget_expanded %}
{% spaceless %}
    <div {{ block('widget_container_attributes') }}>
    {% for child in form %}
        {{ form_widget(child) }}
        {{ form_label(child) }}
    {% endfor %}
    </div>
{% endspaceless %}
{% endblock choice_widget_expanded %}

{% block choice_widget_collapsed %}
{% spaceless %}
    {% if required and empty_value is none and not empty_value_in_choices and not multiple %}
        {% set required = false %}
    {% endif %}
    <select {{ block('widget_attributes') }}{% if multiple %} multiple="multiple"{% endif %}>
        {% if empty_value is not none %}
            <option value=""{% if required and value is empty %} selected="selected"{% endif %}>{{ empty_value|trans({}, translation_domain) }}</option>
        {% endif %}
        {% if preferred_choices|length > 0 %}
            {% set options = preferred_choices %}
            {{ block('choice_widget_options') }}
            {% if choices|length > 0 and separator is not none %}
                <option disabled="disabled">{{ separator }}</option>
            {% endif %}
        {% endif %}
        {% set options = choices %}
        {{ block('choice_widget_options') }}
    </select>
{% endspaceless %}
{% endblock choice_widget_collapsed %}

{% block choice_widget_options %}
{% spaceless %}
    {% for group_label, choice in options %}
        {% if choice is iterable %}
            <optgroup label="{{ group_label|trans({}, translation_domain) }}">
                {% set options = choice %}
                {{ block('choice_widget_options') }}
            </optgroup>
        {% else %}
            <option value="{{ choice.value }}"{% if choice is selectedchoice(value) %} selected="selected"{% endif %}>{{ choice.label|trans({}, translation_domain) }}</option>
        {% endif %}
    {% endfor %}
{% endspaceless %}
{% endblock choice_widget_options %}

{% block checkbox_widget %}
{% spaceless %}
    <input type="checkbox" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} />
{% endspaceless %}
{% endblock checkbox_widget %}

{% block radio_widget %}
{% spaceless %}
    <input type="radio" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} />
{% endspaceless %}
{% endblock radio_widget %}

{% block datetime_widget %}
{% spaceless %}
    {% if widget == 'single_text' %}
        {{ block('form_widget_simple') }}
    {% else %}
        <div {{ block('widget_container_attributes') }}>
            {{ form_errors(form.date) }}
            {{ form_errors(form.time) }}
            {{ form_widget(form.date) }}
            {{ form_widget(form.time) }}
        </div>
    {% endif %}
{% endspaceless %}
{% endblock datetime_widget %}

{% block date_widget %}
{% spaceless %}
    {% if widget == 'single_text' %}
        {{ block('form_widget_simple') }}
    {% else %}
        <div {{ block('widget_container_attributes') }}>
            {{ date_pattern|replace({
                '{{ year }}':  form_widget(form.year),
                '{{ month }}': form_widget(form.month),
                '{{ day }}':   form_widget(form.day),
            })|raw }}
        </div>
    {% endif %}
{% endspaceless %}
{% endblock date_widget %}

{% block time_widget %}
{% spaceless %}
    {% if widget == 'single_text' %}
        {{ block('form_widget_simple') }}
    {% else %}
        {% set vars = widget == 'text' ? { 'attr': { 'size': 1 }} : {} %}
        <div {{ block('widget_container_attributes') }}>
            {{ form_widget(form.hour, vars) }}{% if with_minutes %}:{{ form_widget(form.minute, vars) }}{% endif %}{% if with_seconds %}:{{ form_widget(form.second, vars) }}{% endif %}
        </div>
    {% endif %}
{% endspaceless %}
{% endblock time_widget %}

{% block number_widget %}
{% spaceless %}
    {# type="number" doesn't work with floats #}
    {% set type = type|default('text') %}
    {{ block('form_widget_simple') }}
{% endspaceless %}
{% endblock number_widget %}

{% block integer_widget %}
{% spaceless %}
    {% set type = type|default('number') %}
    {{ block('form_widget_simple') }}
{% endspaceless %}
{% endblock integer_widget %}

{% block money_widget %}
{% spaceless %}
    {{ money_pattern|replace({ '{{ widget }}': block('form_widget_simple') })|raw }}
{% endspaceless %}
{% endblock money_widget %}

{% block url_widget %}
{% spaceless %}
    {% set type = type|default('url') %}
    {{ block('form_widget_simple') }}
{% endspaceless %}
{% endblock url_widget %}

{% block search_widget %}
{% spaceless %}
    {% set type = type|default('search') %}
    {{ block('form_widget_simple') }}
{% endspaceless %}
{% endblock search_widget %}

{% block percent_widget %}
{% spaceless %}
    {% set type = type|default('text') %}
    {{ block('form_widget_simple') }} %
{% endspaceless %}
{% endblock percent_widget %}

{% block password_widget %}
{% spaceless %}
    {% set type = type|default('password') %}
    {{ block('form_widget_simple') }}
{% endspaceless %}
{% endblock password_widget %}

{% block hidden_widget %}
{% spaceless %}
    {% set type = type|default('hidden') %}
    {{ block('form_widget_simple') }}
{% endspaceless %}
{% endblock hidden_widget %}

{% block email_widget %}
{% spaceless %}
    {% set type = type|default('email') %}
    {{ block('form_widget_simple') }}
{% endspaceless %}
{% endblock email_widget %}

{% block button_widget %}
{% spaceless %}
    {% if label is empty %}
        {% set label = name|humanize %}
    {% endif %}
    <button type="{{ type|default('button') }}" {{ block('button_attributes') }}>{{ label|trans({}, translation_domain) }}</button>
{% endspaceless %}
{% endblock button_widget %}

{% block submit_widget %}
{% spaceless %}
    {% set type = type|default('submit') %}
    {{ block('button_widget') }}
{% endspaceless %}
{% endblock submit_widget %}

{% block reset_widget %}
{% spaceless %}
    {% set type = type|default('reset') %}
    {{ block('button_widget') }}
{% endspaceless %}
{% endblock reset_widget %}

{# Labels #}

{% block form_label %}
{% spaceless %}
    {% if label is not sameas(false) %}
        {% if not compound %}
            {% set label_attr = label_attr|merge({'for': id}) %}
        {% endif %}
        {% if required %}
            {% set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' required')|trim}) %}
        {% endif %}
        {% if label is empty %}
            {% set label = name|humanize %}
        {% endif %}
        <label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}>{{ label|trans({}, translation_domain) }}</label>
    {% endif %}
{% endspaceless %}
{% endblock form_label %}

{% block button_label %}{% endblock %}

{# Rows #}

{% block repeated_row %}
{% spaceless %}
    {#
    No need to render the errors here, as all errors are mapped
    to the first child (see RepeatedTypeValidatorExtension).
    #}
    {{ block('form_rows') }}
{% endspaceless %}
{% endblock repeated_row %}

{% block form_row %}
{% spaceless %}
    <div>
        {{ form_label(form) }}
        {{ form_errors(form) }}
        {{ form_widget(form) }}
    </div>
{% endspaceless %}
{% endblock form_row %}

{% block button_row %}
{% spaceless %}
    <div>
        {{ form_widget(form) }}
    </div>
{% endspaceless %}
{% endblock button_row %}

{% block hidden_row %}
    {{ form_widget(form) }}
{% endblock hidden_row %}

{# Misc #}

{% block form %}
{% spaceless %}
    {{ form_start(form) }}
        {{ form_widget(form) }}
    {{ form_end(form) }}
{% endspaceless %}
{% endblock form %}

{% block form_start %}
{% spaceless %}
    {% set method = method|upper %}
    {% if method in ["GET", "POST"] %}
        {% set form_method = method %}
    {% else %}
        {% set form_method = "POST" %}
    {% endif %}
    <form name="{{ form.vars.name }}" method="{{ form_method|lower }}" action="{{ action }}"{% for attrname, attrvalue in attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}{% if multipart %} enctype="multipart/form-data"{% endif %}>
    {% if form_method != method %}
        <input type="hidden" name="_method" value="{{ method }}" />
    {% endif %}
{% endspaceless %}
{% endblock form_start %}

{% block form_end %}
{% spaceless %}
    {% if not render_rest is defined or render_rest %}
        {{ form_rest(form) }}
    {% endif %}
    </form>
{% endspaceless %}
{% endblock form_end %}

{% block form_enctype %}
{% spaceless %}
    {% if multipart %}enctype="multipart/form-data"{% endif %}
{% endspaceless %}
{% endblock form_enctype %}

{% block form_errors %}
{% spaceless %}
    {% if errors|length > 0 %}
    <ul>
        {% for error in errors %}
            <li>{{ error.message }}</li>
        {% endfor %}
    </ul>
    {% endif %}
{% endspaceless %}
{% endblock form_errors %}

{% block form_rest %}
{% spaceless %}
    {% for child in form %}
        {% if not child.rendered %}
            {{ form_row(child) }}
        {% endif %}
    {% endfor %}
{% endspaceless %}
{% endblock form_rest %}

{# Support #}

{% block form_rows %}
{% spaceless %}
    {% for child in form %}
        {{ form_row(child) }}
    {% endfor %}
{% endspaceless %}
{% endblock form_rows %}

{% block widget_attributes %}
{% spaceless %}
    id="{{ id }}" name="{{ full_name }}"
    {%- if read_only %} readonly="readonly"{% endif -%}
    {%- if disabled %} disabled="disabled"{% endif -%}
    {%- if required %} required="required"{% endif -%}
    {%- if max_length %} maxlength="{{ max_length }}"{% endif -%}
    {%- if pattern %} pattern="{{ pattern }}"{% endif -%}
    {%- for attrname, attrvalue in attr -%}
        {{- " " -}}
        {%- if attrname in ['placeholder', 'title'] -%}
            {{- attrname }}="{{ attrvalue|trans({}, translation_domain) }}"
        {%- elseif attrvalue is sameas(true) -%}
            {{- attrname }}="{{ attrname }}"
        {%- elseif attrvalue is not sameas(false) -%}
            {{- attrname }}="{{ attrvalue }}"
        {%- endif -%}
    {%- endfor -%}
{% endspaceless %}
{% endblock widget_attributes %}

{% block widget_container_attributes %}
{% spaceless %}
    {%- if id is not empty %}id="{{ id }}"{% endif -%}
    {%- for attrname, attrvalue in attr -%}
        {{- " " -}}
        {%- if attrname in ['placeholder', 'title'] -%}
            {{- attrname }}="{{ attrvalue|trans({}, translation_domain) }}"
        {%- elseif attrvalue is sameas(true) -%}
            {{- attrname }}="{{ attrname }}"
        {%- elseif attrvalue is not sameas(false) -%}
            {{- attrname }}="{{ attrvalue }}"
        {%- endif -%}
    {%- endfor -%}
{% endspaceless %}
{% endblock widget_container_attributes %}

{% block button_attributes %}
{% spaceless %}
    id="{{ id }}" name="{{ full_name }}"{% if disabled %} disabled="disabled"{% endif -%}
    {%- for attrname, attrvalue in attr -%}
        {{- " " -}}
        {%- if attrname in ['placeholder', 'title'] -%}
            {{- attrname }}="{{ attrvalue|trans({}, translation_domain) }}"
        {%- elseif attrvalue is sameas(true) -%}
            {{- attrname }}="{{ attrname }}"
        {%- elseif attrvalue is not sameas(false) -%}
            {{- attrname }}="{{ attrvalue }}"
        {%- endif -%}
    {%- endfor -%}
{% endspaceless %}
{% endblock button_attributes %}
PKt�Z��[[DSymfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twignu�[���{% use "form_div_layout.html.twig" %}

{% block form_row %}
{% spaceless %}
    <tr>
        <td>
            {{ form_label(form) }}
        </td>
        <td>
            {{ form_errors(form) }}
            {{ form_widget(form) }}
        </td>
    </tr>
{% endspaceless %}
{% endblock form_row %}

{% block button_row %}
{% spaceless %}
    <tr>
        <td></td>
        <td>
            {{ form_widget(form) }}
        </td>
    </tr>
{% endspaceless %}
{% endblock button_row %}

{% block hidden_row %}
{% spaceless %}
    <tr style="display: none">
        <td colspan="2">
            {{ form_widget(form) }}
        </td>
    </tr>
{% endspaceless %}
{% endblock hidden_row %}

{% block form_widget_compound %}
{% spaceless %}
    <table {{ block('widget_container_attributes') }}>
        {% if form.parent is empty and errors|length > 0 %}
        <tr>
            <td colspan="2">
                {{ form_errors(form) }}
            </td>
        </tr>
        {% endif %}
        {{ block('form_rows') }}
        {{ form_rest(form) }}
    </table>
{% endspaceless %}
{% endblock form_widget_compound %}
PKt�Z.��8Symfony/Bridge/Twig/TokenParser/StopwatchTokenParser.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\TokenParser;

use Symfony\Bridge\Twig\Node\StopwatchNode;

/**
 * Token Parser for the stopwatch tag.
 *
 * @author Wouter J <wouter@wouterj.nl>
 */
class StopwatchTokenParser extends \Twig_TokenParser
{
    protected $stopwatchIsAvailable;

    public function __construct($stopwatchIsAvailable)
    {
        $this->stopwatchIsAvailable = $stopwatchIsAvailable;
    }

    public function parse(\Twig_Token $token)
    {
        $lineno = $token->getLine();
        $stream = $this->parser->getStream();

        // {% stopwatch 'bar' %}
        $name = $this->parser->getExpressionParser()->parseExpression();

        $stream->expect(\Twig_Token::BLOCK_END_TYPE);

        // {% endstopwatch %}
        $body = $this->parser->subparse(array($this, 'decideStopwatchEnd'), true);
        $stream->expect(\Twig_Token::BLOCK_END_TYPE);

        if ($this->stopwatchIsAvailable) {
            return new StopwatchNode($name, $body, new \Twig_Node_Expression_AssignName($this->parser->getVarName(), $token->getLine()), $lineno, $this->getTag());
        }

        return $body;
    }

    public function decideStopwatchEnd(\Twig_Token $token)
    {
        return $token->test('endstopwatch');
    }

    public function getTag()
    {
        return 'stopwatch';
    }
}
PKt�Z�%]�
�
4Symfony/Bridge/Twig/TokenParser/TransTokenParser.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\TokenParser;

use Symfony\Bridge\Twig\Node\TransNode;

/**
 * Token Parser for the 'trans' tag.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class TransTokenParser extends \Twig_TokenParser
{
    /**
     * Parses a token and returns a node.
     *
     * @param \Twig_Token $token A Twig_Token instance
     *
     * @return \Twig_NodeInterface A Twig_NodeInterface instance
     *
     * @throws \Twig_Error_Syntax
     */
    public function parse(\Twig_Token $token)
    {
        $lineno = $token->getLine();
        $stream = $this->parser->getStream();

        $vars = new \Twig_Node_Expression_Array(array(), $lineno);
        $domain = null;
        $locale = null;
        if (!$stream->test(\Twig_Token::BLOCK_END_TYPE)) {
            if ($stream->test('with')) {
                // {% trans with vars %}
                $stream->next();
                $vars = $this->parser->getExpressionParser()->parseExpression();
            }

            if ($stream->test('from')) {
                // {% trans from "messages" %}
                $stream->next();
                $domain = $this->parser->getExpressionParser()->parseExpression();
            }

            if ($stream->test('into')) {
                // {% trans into "fr" %}
                $stream->next();
                $locale =  $this->parser->getExpressionParser()->parseExpression();
            } elseif (!$stream->test(\Twig_Token::BLOCK_END_TYPE)) {
                throw new \Twig_Error_Syntax('Unexpected token. Twig was looking for the "with", "from", or "into" keyword.', $stream->getCurrent()->getLine(), $stream->getFilename());
            }
        }

        // {% trans %}message{% endtrans %}
        $stream->expect(\Twig_Token::BLOCK_END_TYPE);
        $body = $this->parser->subparse(array($this, 'decideTransFork'), true);

        if (!$body instanceof \Twig_Node_Text && !$body instanceof \Twig_Node_Expression) {
            throw new \Twig_Error_Syntax('A message inside a trans tag must be a simple text.', $body->getLine(), $stream->getFilename());
        }

        $stream->expect(\Twig_Token::BLOCK_END_TYPE);

        return new TransNode($body, $domain, null, $vars, $locale, $lineno, $this->getTag());
    }

    public function decideTransFork($token)
    {
        return $token->test(array('endtrans'));
    }

    /**
     * Gets the tag name associated with this token parser.
     *
     * @return string The tag name
     */
    public function getTag()
    {
        return 'trans';
    }
}
PKt�Z�/�	�	:Symfony/Bridge/Twig/TokenParser/TransChoiceTokenParser.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\TokenParser;

use Symfony\Bridge\Twig\Node\TransNode;

/**
 * Token Parser for the 'transchoice' tag.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class TransChoiceTokenParser extends TransTokenParser
{
    /**
     * Parses a token and returns a node.
     *
     * @param \Twig_Token $token A Twig_Token instance
     *
     * @return \Twig_NodeInterface A Twig_NodeInterface instance
     *
     * @throws \Twig_Error_Syntax
     */
    public function parse(\Twig_Token $token)
    {
        $lineno = $token->getLine();
        $stream = $this->parser->getStream();

        $vars = new \Twig_Node_Expression_Array(array(), $lineno);

        $count = $this->parser->getExpressionParser()->parseExpression();

        $domain = null;
        $locale = null;

        if ($stream->test('with')) {
            // {% transchoice count with vars %}
            $stream->next();
            $vars = $this->parser->getExpressionParser()->parseExpression();
        }

        if ($stream->test('from')) {
            // {% transchoice count from "messages" %}
            $stream->next();
            $domain = $this->parser->getExpressionParser()->parseExpression();
        }

        if ($stream->test('into')) {
            // {% transchoice count into "fr" %}
            $stream->next();
            $locale =  $this->parser->getExpressionParser()->parseExpression();
        }

        $stream->expect(\Twig_Token::BLOCK_END_TYPE);

        $body = $this->parser->subparse(array($this, 'decideTransChoiceFork'), true);

        if (!$body instanceof \Twig_Node_Text && !$body instanceof \Twig_Node_Expression) {
            throw new \Twig_Error_Syntax('A message inside a transchoice tag must be a simple text.', $body->getLine(), $stream->getFilename());
        }

        $stream->expect(\Twig_Token::BLOCK_END_TYPE);

        return new TransNode($body, $domain, $count, $vars, $locale, $lineno, $this->getTag());
    }

    public function decideTransChoiceFork($token)
    {
        return $token->test(array('endtranschoice'));
    }

    /**
     * Gets the tag name associated with this token parser.
     *
     * @return string The tag name
     */
    public function getTag()
    {
        return 'transchoice';
    }
}
PKt�Z>����8Symfony/Bridge/Twig/TokenParser/FormThemeTokenParser.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\TokenParser;

use Symfony\Bridge\Twig\Node\FormThemeNode;

/**
 * Token Parser for the 'form_theme' tag.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FormThemeTokenParser extends \Twig_TokenParser
{
    /**
     * Parses a token and returns a node.
     *
     * @param \Twig_Token $token A Twig_Token instance
     *
     * @return \Twig_NodeInterface A Twig_NodeInterface instance
     */
    public function parse(\Twig_Token $token)
    {
        $lineno = $token->getLine();
        $stream = $this->parser->getStream();

        $form = $this->parser->getExpressionParser()->parseExpression();

        if ($this->parser->getStream()->test(\Twig_Token::NAME_TYPE, 'with')) {
            $this->parser->getStream()->next();
            $resources = $this->parser->getExpressionParser()->parseExpression();
        } else {
            $resources = new \Twig_Node_Expression_Array(array(), $stream->getCurrent()->getLine());
            do {
                $resources->addElement($this->parser->getExpressionParser()->parseExpression());
            } while (!$stream->test(\Twig_Token::BLOCK_END_TYPE));
        }

        $stream->expect(\Twig_Token::BLOCK_END_TYPE);

        return new FormThemeNode($form, $resources, $lineno, $this->getTag());
    }

    /**
     * Gets the tag name associated with this token parser.
     *
     * @return string The tag name
     */
    public function getTag()
    {
        return 'form_theme';
    }
}
PKt�Zʶ�̭�ASymfony/Bridge/Twig/TokenParser/TransDefaultDomainTokenParser.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\TokenParser;

use Symfony\Bridge\Twig\Node\TransDefaultDomainNode;

/**
 * Token Parser for the 'trans_default_domain' tag.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class TransDefaultDomainTokenParser extends \Twig_TokenParser
{
    /**
     * Parses a token and returns a node.
     *
     * @param \Twig_Token $token A Twig_Token instance
     *
     * @return \Twig_NodeInterface A Twig_NodeInterface instance
     */
    public function parse(\Twig_Token $token)
    {
        $expr = $this->parser->getExpressionParser()->parseExpression();

        $this->parser->getStream()->expect(\Twig_Token::BLOCK_END_TYPE);

        return new TransDefaultDomainNode($expr, $token->getLine(), $this->getTag());
    }

    /**
     * Gets the tag name associated with this token parser.
     *
     * @return string The tag name
     */
    public function getTag()
    {
        return 'trans_default_domain';
    }
}
PKt�Z�9�=KK/Symfony/Bridge/Twig/Extension/FormExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Extension;

use Symfony\Bridge\Twig\TokenParser\FormThemeTokenParser;
use Symfony\Bridge\Twig\Form\TwigRendererInterface;
use Symfony\Component\Form\Extension\Core\View\ChoiceView;

/**
 * FormExtension extends Twig with form capabilities.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class FormExtension extends \Twig_Extension
{
    /**
     * This property is public so that it can be accessed directly from compiled
     * templates without having to call a getter, which slightly decreases performance.
     *
     * @var TwigRendererInterface
     */
    public $renderer;

    public function __construct(TwigRendererInterface $renderer)
    {
        $this->renderer = $renderer;
    }

    /**
     * {@inheritdoc}
     */
    public function initRuntime(\Twig_Environment $environment)
    {
        $this->renderer->setEnvironment($environment);
    }

    /**
     * {@inheritdoc}
     */
    public function getTokenParsers()
    {
        return array(
            // {% form_theme form "SomeBundle::widgets.twig" %}
            new FormThemeTokenParser(),
        );
    }

    /**
     * {@inheritdoc}
     */
    public function getFunctions()
    {
        return array(
            'form_enctype' => new \Twig_Function_Node('Symfony\Bridge\Twig\Node\FormEnctypeNode', array('is_safe' => array('html'))),
            'form_widget'  => new \Twig_Function_Node('Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', array('is_safe' => array('html'))),
            'form_errors'  => new \Twig_Function_Node('Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', array('is_safe' => array('html'))),
            'form_label'   => new \Twig_Function_Node('Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', array('is_safe' => array('html'))),
            'form_row'     => new \Twig_Function_Node('Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', array('is_safe' => array('html'))),
            'form_rest'    => new \Twig_Function_Node('Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', array('is_safe' => array('html'))),
            'form'         => new \Twig_Function_Node('Symfony\Bridge\Twig\Node\RenderBlockNode', array('is_safe' => array('html'))),
            'form_start'   => new \Twig_Function_Node('Symfony\Bridge\Twig\Node\RenderBlockNode', array('is_safe' => array('html'))),
            'form_end'     => new \Twig_Function_Node('Symfony\Bridge\Twig\Node\RenderBlockNode', array('is_safe' => array('html'))),
            'csrf_token'   => new \Twig_Function_Method($this, 'renderer->renderCsrfToken'),
        );
    }

    /**
     * {@inheritdoc}
     */
    public function getFilters()
    {
        return array(
            new \Twig_SimpleFilter('humanize', array($this->renderer, 'humanize')),
        );
    }

    /**
     * {@inheritdoc}
     */
    public function getTests()
    {
        return array(
            new \Twig_SimpleTest('selectedchoice', array($this, 'isSelectedChoice')),
        );
    }

    /**
     * Returns whether a choice is selected for a given form value.
     *
     * Unfortunately Twig does not support an efficient way to execute the
     * "is_selected" closure passed to the template by ChoiceType. It is faster
     * to implement the logic here (around 65ms for a specific form).
     *
     * Directly implementing the logic here is also faster than doing so in
     * ChoiceView (around 30ms).
     *
     * The worst option tested so far is to implement the logic in ChoiceView
     * and access the ChoiceView method directly in the template. Doing so is
     * around 220ms slower than doing the method call here in the filter. Twig
     * seems to be much more efficient at executing filters than at executing
     * methods of an object.
     *
     * @param ChoiceView   $choice        The choice to check.
     * @param string|array $selectedValue The selected value to compare.
     *
     * @return Boolean Whether the choice is selected.
     *
     * @see ChoiceView::isSelected()
     */
    public function isSelectedChoice(ChoiceView $choice, $selectedValue)
    {
        if (is_array($selectedValue)) {
            return false !== array_search($choice->value, $selectedValue, true);
        }

        return $choice->value === $selectedValue;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'form';
    }
}
PKt�Z��|/Symfony/Bridge/Twig/Extension/YamlExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Extension;

use Symfony\Component\Yaml\Dumper as YamlDumper;

/**
 * Provides integration of the Yaml component with Twig.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class YamlExtension extends \Twig_Extension
{
    /**
     * {@inheritdoc}
     */
    public function getFilters()
    {
        return array(
            new \Twig_SimpleFilter('yaml_encode', array($this, 'encode')),
            new \Twig_SimpleFilter('yaml_dump', array($this, 'dump')),
        );
    }

    public function encode($input, $inline = 0, $dumpObjects = false)
    {
        static $dumper;

        if (null === $dumper) {
            $dumper = new YamlDumper();
        }

        return $dumper->dump($input, $inline, false, $dumpObjects);
    }

    public function dump($value, $inline = 0, $dumpObjects = false)
    {
        if (is_resource($value)) {
            return '%Resource%';
        }

        if (is_array($value) || is_object($value)) {
            return '%'.gettype($value).'% '.$this->encode($value, $inline, $dumpObjects);
        }

        return $this->encode($value, $inline, $dumpObjects);
    }

    /**
     * Returns the name of the extension.
     *
     * @return string The extension name
     */
    public function getName()
    {
        return 'yaml';
    }
}
PKt�Z��&�a
a
5Symfony/Bridge/Twig/Extension/HttpKernelExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Extension;

use Symfony\Component\HttpKernel\Fragment\FragmentHandler;
use Symfony\Component\HttpKernel\Controller\ControllerReference;

/**
 * Provides integration with the HttpKernel component.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class HttpKernelExtension extends \Twig_Extension
{
    private $handler;

    /**
     * Constructor.
     *
     * @param FragmentHandler $handler A FragmentHandler instance
     */
    public function __construct(FragmentHandler $handler)
    {
        $this->handler = $handler;
    }

    public function getFunctions()
    {
        return array(
            new \Twig_SimpleFunction('render',array($this, 'renderFragment'), array('is_safe' => array('html'))),
            new \Twig_SimpleFunction('render_*', array($this, 'renderFragmentStrategy'), array('is_safe' => array('html'))),
            new \Twig_SimpleFunction('controller', array($this, 'controller')),
        );
    }

    /**
     * Renders a fragment.
     *
     * @param string|ControllerReference $uri      A URI as a string or a ControllerReference instance
     * @param array                      $options  An array of options
     *
     * @return string The fragment content
     *
     * @see Symfony\Component\HttpKernel\Fragment\FragmentHandler::render()
     */
    public function renderFragment($uri, $options = array())
    {
        $strategy = isset($options['strategy']) ? $options['strategy'] : 'inline';
        unset($options['strategy']);

        return $this->handler->render($uri, $strategy, $options);
    }

    /**
     * Renders a fragment.
     *
     * @param string                     $strategy A strategy name
     * @param string|ControllerReference $uri      A URI as a string or a ControllerReference instance
     * @param array                      $options  An array of options
     *
     * @return string The fragment content
     *
     * @see Symfony\Component\HttpKernel\Fragment\FragmentHandler::render()
     */
    public function renderFragmentStrategy($strategy, $uri, $options = array())
    {
        return $this->handler->render($uri, $strategy, $options);
    }

    public function controller($controller, $attributes = array(), $query = array())
    {
        return new ControllerReference($controller, $attributes, $query);
    }

    public function getName()
    {
        return 'http_kernel';
    }
}
PKt�ZK���5Symfony/Bridge/Twig/Extension/ExpressionExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Extension;

use Symfony\Component\ExpressionLanguage\Expression;

/**
 * ExpressionExtension gives a way to create Expressions from a template.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ExpressionExtension extends \Twig_Extension
{
    /**
     * {@inheritdoc}
     */
    public function getFunctions()
    {
        return array(
            new \Twig_SimpleFunction('expression', array($this, 'createExpression')),
        );
    }

    public function createExpression($expression)
    {
        return new Expression($expression);
    }

    /**
     * Returns the name of the extension.
     *
     * @return string The extension name
     */
    public function getName()
    {
        return 'expression';
    }
}
PKt�Z`�fS..2Symfony/Bridge/Twig/Extension/RoutingExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Extension;

use Symfony\Component\Routing\Generator\UrlGeneratorInterface;

/**
 * Provides integration of the Routing component with Twig.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class RoutingExtension extends \Twig_Extension
{
    private $generator;

    public function __construct(UrlGeneratorInterface $generator)
    {
        $this->generator = $generator;
    }

    /**
     * Returns a list of functions to add to the existing list.
     *
     * @return array An array of functions
     */
    public function getFunctions()
    {
        return array(
            new \Twig_SimpleFunction('url', array($this, 'getUrl'), array('is_safe_callback' => array($this, 'isUrlGenerationSafe'))),
            new \Twig_SimpleFunction('path', array($this, 'getPath'), array('is_safe_callback' => array($this, 'isUrlGenerationSafe'))),
        );
    }

    public function getPath($name, $parameters = array(), $relative = false)
    {
        return $this->generator->generate($name, $parameters, $relative ? UrlGeneratorInterface::RELATIVE_PATH : UrlGeneratorInterface::ABSOLUTE_PATH);
    }

    public function getUrl($name, $parameters = array(), $schemeRelative = false)
    {
        return $this->generator->generate($name, $parameters, $schemeRelative ? UrlGeneratorInterface::NETWORK_PATH : UrlGeneratorInterface::ABSOLUTE_URL);
    }

    /**
     * Determines at compile time whether the generated URL will be safe and thus
     * saving the unneeded automatic escaping for performance reasons.
     *
     * The URL generation process percent encodes non-alphanumeric characters. So there is no risk
     * that malicious/invalid characters are part of the URL. The only character within an URL that
     * must be escaped in html is the ampersand ("&") which separates query params. So we cannot mark
     * the URL generation as always safe, but only when we are sure there won't be multiple query
     * params. This is the case when there are none or only one constant parameter given.
     * E.g. we know beforehand this will be safe:
     * - path('route')
     * - path('route', {'param': 'value'})
     * But the following may not:
     * - path('route', var)
     * - path('route', {'param': ['val1', 'val2'] }) // a sub-array
     * - path('route', {'param1': 'value1', 'param2': 'value2'})
     * If param1 and param2 reference placeholder in the route, it would still be safe. But we don't know.
     *
     * @param \Twig_Node $argsNode The arguments of the path/url function
     *
     * @return array An array with the contexts the URL is safe
     */
    public function isUrlGenerationSafe(\Twig_Node $argsNode)
    {
        // support named arguments
        $paramsNode = $argsNode->hasNode('parameters') ? $argsNode->getNode('parameters') : (
            $argsNode->hasNode(1) ? $argsNode->getNode(1) : null
        );

        if (null === $paramsNode || $paramsNode instanceof \Twig_Node_Expression_Array && count($paramsNode) <= 2 &&
            (!$paramsNode->hasNode(1) || $paramsNode->getNode(1) instanceof \Twig_Node_Expression_Constant)
        ) {
            return array('html');
        }

        return array();
    }

    /**
     * Returns the name of the extension.
     *
     * @return string The extension name
     */
    public function getName()
    {
        return 'routing';
    }
}
PKt�Z�5��mm4Symfony/Bridge/Twig/Extension/StopwatchExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Extension;

use Symfony\Component\Stopwatch\Stopwatch;
use Symfony\Bridge\Twig\TokenParser\StopwatchTokenParser;

/**
 * Twig extension for the stopwatch helper.
 *
 * @author Wouter J <wouter@wouterj.nl>
 */
class StopwatchExtension extends \Twig_Extension
{
    private $stopwatch;

    public function __construct(Stopwatch $stopwatch = null)
    {
        $this->stopwatch = $stopwatch;
    }

    public function getStopwatch()
    {
        return $this->stopwatch;
    }

    public function getTokenParsers()
    {
        return array(
            /*
             * {% stopwatch foo %}
             * Some stuff which will be recorded on the timeline
             * {% endstopwatch %}
             */
            new StopwatchTokenParser($this->stopwatch !== null),
        );
    }

    public function getName()
    {
        return 'stopwatch';
    }
}
PKt�Z�?���6Symfony/Bridge/Twig/Extension/TranslationExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Extension;

use Symfony\Bridge\Twig\TokenParser\TransTokenParser;
use Symfony\Bridge\Twig\TokenParser\TransChoiceTokenParser;
use Symfony\Bridge\Twig\TokenParser\TransDefaultDomainTokenParser;
use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Bridge\Twig\NodeVisitor\TranslationNodeVisitor;
use Symfony\Bridge\Twig\NodeVisitor\TranslationDefaultDomainNodeVisitor;

/**
 * Provides integration of the Translation component with Twig.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class TranslationExtension extends \Twig_Extension
{
    private $translator;
    private $translationNodeVisitor;

    public function __construct(TranslatorInterface $translator, \Twig_NodeVisitorInterface $translationNodeVisitor = null)
    {
        if (!$translationNodeVisitor) {
            $translationNodeVisitor = new TranslationNodeVisitor();
        }

        $this->translator = $translator;
        $this->translationNodeVisitor = $translationNodeVisitor;
    }

    public function getTranslator()
    {
        return $this->translator;
    }

    /**
     * {@inheritdoc}
     */
    public function getFilters()
    {
        return array(
            new \Twig_SimpleFilter('trans', array($this, 'trans')),
            new \Twig_SimpleFilter('transchoice', array($this, 'transchoice')),
        );
    }

    /**
     * Returns the token parser instance to add to the existing list.
     *
     * @return array An array of Twig_TokenParser instances
     */
    public function getTokenParsers()
    {
        return array(
            // {% trans %}Symfony is great!{% endtrans %}
            new TransTokenParser(),

            // {% transchoice count %}
            //     {0} There is no apples|{1} There is one apple|]1,Inf] There is {{ count }} apples
            // {% endtranschoice %}
            new TransChoiceTokenParser(),

            // {% trans_default_domain "foobar" %}
            new TransDefaultDomainTokenParser(),
        );
    }

    /**
     * {@inheritdoc}
     */
    public function getNodeVisitors()
    {
        return array($this->translationNodeVisitor, new TranslationDefaultDomainNodeVisitor());
    }

    public function getTranslationNodeVisitor()
    {
        return $this->translationNodeVisitor;
    }

    public function trans($message, array $arguments = array(), $domain = null, $locale = null)
    {
        if (null === $domain) {
            $domain = 'messages';
        }

        return $this->translator->trans($message, $arguments, $domain, $locale);
    }

    public function transchoice($message, $count, array $arguments = array(), $domain = null, $locale = null)
    {
        if (null === $domain) {
            $domain = 'messages';
        }

        return $this->translator->transChoice($message, $count, array_merge(array('%count%' => $count), $arguments), $domain, $locale);
    }

    /**
     * Returns the name of the extension.
     *
     * @return string The extension name
     */
    public function getName()
    {
        return 'translator';
    }
}
PKt�Zd���oo3Symfony/Bridge/Twig/Extension/SecurityExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Extension;

use Symfony\Component\Security\Acl\Voter\FieldVote;
use Symfony\Component\Security\Core\SecurityContextInterface;

/**
 * SecurityExtension exposes security context features.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class SecurityExtension extends \Twig_Extension
{
    private $context;

    public function __construct(SecurityContextInterface $context = null)
    {
        $this->context = $context;
    }

    public function isGranted($role, $object = null, $field = null)
    {
        if (null === $this->context) {
            return false;
        }

        if (null !== $field) {
            $object = new FieldVote($object, $field);
        }

        return $this->context->isGranted($role, $object);
    }

    /**
     * {@inheritdoc}
     */
    public function getFunctions()
    {
        return array(
            new \Twig_SimpleFunction('is_granted', array($this, 'isGranted')),
        );
    }

    /**
     * Returns the name of the extension.
     *
     * @return string The extension name
     */
    public function getName()
    {
        return 'security';
    }
}
PKt�Z�����/Symfony/Bridge/Twig/Extension/CodeExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Extension;

if (!defined('ENT_SUBSTITUTE')) {
    define('ENT_SUBSTITUTE', 8);
}

/**
 * Twig extension relate to PHP code and used by the profiler and the default exception templates.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class CodeExtension extends \Twig_Extension
{
    private $fileLinkFormat;
    private $rootDir;
    private $charset;

    /**
     * Constructor.
     *
     * @param string $fileLinkFormat The format for links to source files
     * @param string $rootDir        The project root directory
     * @param string $charset        The charset
     */
    public function __construct($fileLinkFormat, $rootDir, $charset)
    {
        $this->fileLinkFormat = empty($fileLinkFormat) ? ini_get('xdebug.file_link_format') : $fileLinkFormat;
        $this->rootDir = str_replace('\\', '/', $rootDir).'/';
        $this->charset = $charset;
    }

    /**
     * {@inheritdoc}
     */
    public function getFilters()
    {
        return array(
            new \Twig_SimpleFilter('abbr_class', array($this, 'abbrClass'), array('is_safe' => array('html'))),
            new \Twig_SimpleFilter('abbr_method', array($this, 'abbrMethod'), array('is_safe' => array('html'))),
            new \Twig_SimpleFilter('format_args', array($this, 'formatArgs'), array('is_safe' => array('html'))),
            new \Twig_SimpleFilter('format_args_as_text', array($this, 'formatArgsAsText')),
            new \Twig_SimpleFilter('file_excerpt', array($this, 'fileExcerpt'), array('is_safe' => array('html'))),
            new \Twig_SimpleFilter('format_file', array($this, 'formatFile'), array('is_safe' => array('html'))),
            new \Twig_SimpleFilter('format_file_from_text', array($this, 'formatFileFromText'), array('is_safe' => array('html'))),
            new \Twig_SimpleFilter('file_link', array($this, 'getFileLink'), array('is_safe' => array('html'))),
        );
    }

    public function abbrClass($class)
    {
        $parts = explode('\\', $class);
        $short = array_pop($parts);

        return sprintf("<abbr title=\"%s\">%s</abbr>", $class, $short);
    }

    public function abbrMethod($method)
    {
        if (false !== strpos($method, '::')) {
            list($class, $method) = explode('::', $method, 2);
            $result = sprintf("%s::%s()", $this->abbrClass($class), $method);
        } elseif ('Closure' === $method) {
            $result = sprintf("<abbr title=\"%s\">%s</abbr>", $method, $method);
        } else {
            $result = sprintf("<abbr title=\"%s\">%s</abbr>()", $method, $method);
        }

        return $result;
    }

    /**
     * Formats an array as a string.
     *
     * @param array $args The argument array
     *
     * @return string
     */
    public function formatArgs($args)
    {
        $result = array();
        foreach ($args as $key => $item) {
            if ('object' === $item[0]) {
                $parts = explode('\\', $item[1]);
                $short = array_pop($parts);
                $formattedValue = sprintf("<em>object</em>(<abbr title=\"%s\">%s</abbr>)", $item[1], $short);
            } elseif ('array' === $item[0]) {
                $formattedValue = sprintf("<em>array</em>(%s)", is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]);
            } elseif ('string'  === $item[0]) {
                $formattedValue = sprintf("'%s'", htmlspecialchars($item[1], ENT_QUOTES, $this->charset));
            } elseif ('null' === $item[0]) {
                $formattedValue = '<em>null</em>';
            } elseif ('boolean' === $item[0]) {
                $formattedValue = '<em>'.strtolower(var_export($item[1], true)).'</em>';
            } elseif ('resource' === $item[0]) {
                $formattedValue = '<em>resource</em>';
            } else {
                $formattedValue = str_replace("\n", '', var_export(htmlspecialchars((string) $item[1], ENT_QUOTES, $this->charset), true));
            }

            $result[] = is_int($key) ? $formattedValue : sprintf("'%s' => %s", $key, $formattedValue);
        }

        return implode(', ', $result);
    }

    /**
     * Formats an array as a string.
     *
     * @param array $args The argument array
     *
     * @return string
     */
    public function formatArgsAsText($args)
    {
        return strip_tags($this->formatArgs($args));
    }

    /**
     * Returns an excerpt of a code file around the given line number.
     *
     * @param string $file A file path
     * @param int    $line The selected line number
     *
     * @return string An HTML string
     */
    public function fileExcerpt($file, $line)
    {
        if (is_readable($file)) {
            // highlight_file could throw warnings
            // see https://bugs.php.net/bug.php?id=25725
            $code = @highlight_file($file, true);
            // remove main code/span tags
            $code = preg_replace('#^<code.*?>\s*<span.*?>(.*)</span>\s*</code>#s', '\\1', $code);
            $content = preg_split('#<br />#', $code);

            $lines = array();
            for ($i = max($line - 3, 1), $max = min($line + 3, count($content)); $i <= $max; $i++) {
                $lines[] = '<li'.($i == $line ? ' class="selected"' : '').'><code>'.self::fixCodeMarkup($content[$i - 1]).'</code></li>';
            }

            return '<ol start="'.max($line - 3, 1).'">'.implode("\n", $lines).'</ol>';
        }
    }

    /**
     * Formats a file path.
     *
     * @param string  $file An absolute file path
     * @param integer $line The line number
     * @param string  $text Use this text for the link rather than the file path
     *
     * @return string
     */
    public function formatFile($file, $line, $text = null)
    {
        if (null === $text) {
            $file = trim($file);
            $text = $file;
            if (0 === strpos($text, $this->rootDir)) {
                $text = str_replace($this->rootDir, '', str_replace('\\', '/', $text));
                $text = sprintf('<abbr title="%s">kernel.root_dir</abbr>/%s', $this->rootDir, $text);
            }
        }

        $text = "$text at line $line";

        if (false !== $link = $this->getFileLink($file, $line)) {
            return sprintf('<a href="%s" title="Click to open this file" class="file_link">%s</a>', htmlspecialchars($link, ENT_QUOTES | ENT_SUBSTITUTE, $this->charset), $text);
        }

        return $text;
    }

    /**
     * Returns the link for a given file/line pair.
     *
     * @param string  $file An absolute file path
     * @param integer $line The line number
     *
     * @return string A link of false
     */
    public function getFileLink($file, $line)
    {
        if ($this->fileLinkFormat && is_file($file)) {
            return strtr($this->fileLinkFormat, array('%f' => $file, '%l' => $line));
        }

        return false;
    }

    public function formatFileFromText($text)
    {
        $that = $this;

        return preg_replace_callback('/in ("|&quot;)?(.+?)\1(?: +(?:on|at))? +line (\d+)/s', function ($match) use ($that) {
            return 'in '.$that->formatFile($match[2], $match[3]);
        }, $text);
    }

    public function getName()
    {
        return 'code';
    }

    protected static function fixCodeMarkup($line)
    {
        // </span> ending tag from previous line
        $opening = strpos($line, '<span');
        $closing = strpos($line, '</span>');
        if (false !== $closing && (false === $opening || $closing < $opening)) {
            $line = substr_replace($line, '', $closing, 7);
        }

        // missing </span> tag at the end of line
        $opening = strpos($line, '<span');
        $closing = strpos($line, '</span>');
        if (false !== $opening && (false === $closing || $closing > $opening)) {
            $line .= '</span>';
        }

        return $line;
    }
}
PKu�Z^D��dd"Symfony/Bridge/Twig/TwigEngine.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig;

use Symfony\Component\Templating\EngineInterface;
use Symfony\Component\Templating\StreamingEngineInterface;
use Symfony\Component\Templating\TemplateNameParserInterface;
use Symfony\Component\Templating\TemplateReferenceInterface;

/**
 * This engine knows how to render Twig templates.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class TwigEngine implements EngineInterface, StreamingEngineInterface
{
    protected $environment;
    protected $parser;

    /**
     * Constructor.
     *
     * @param \Twig_Environment           $environment A \Twig_Environment instance
     * @param TemplateNameParserInterface $parser      A TemplateNameParserInterface instance
     */
    public function __construct(\Twig_Environment $environment, TemplateNameParserInterface $parser)
    {
        $this->environment = $environment;
        $this->parser = $parser;
    }

    /**
     * {@inheritdoc}
     *
     * It also supports \Twig_Template as name parameter.
     *
     * @throws \Twig_Error if something went wrong like a thrown exception while rendering the template
     */
    public function render($name, array $parameters = array())
    {
        return $this->load($name)->render($parameters);
    }

    /**
     * {@inheritdoc}
     *
     * It also supports \Twig_Template as name parameter.
     *
     * @throws \Twig_Error if something went wrong like a thrown exception while rendering the template
     */
    public function stream($name, array $parameters = array())
    {
        $this->load($name)->display($parameters);
    }

    /**
     * {@inheritdoc}
     *
     * It also supports \Twig_Template as name parameter.
     */
    public function exists($name)
    {
        if ($name instanceof \Twig_Template) {
            return true;
        }

        $loader = $this->environment->getLoader();

        if ($loader instanceof \Twig_ExistsLoaderInterface) {
            return $loader->exists((string) $name);
        }

        try {
            // cast possible TemplateReferenceInterface to string because the
            // EngineInterface supports them but Twig_LoaderInterface does not
            $loader->getSource((string) $name);
        } catch (\Twig_Error_Loader $e) {
            return false;
        }

        return true;
    }

    /**
     * {@inheritdoc}
     *
     * It also supports \Twig_Template as name parameter.
     */
    public function supports($name)
    {
        if ($name instanceof \Twig_Template) {
            return true;
        }

        $template = $this->parser->parse($name);

        return 'twig' === $template->get('engine');
    }

    /**
     * Loads the given template.
     *
     * @param string|TemplateReferenceInterface|\Twig_Template $name A template name or an instance of
     *                                                               TemplateReferenceInterface or \Twig_Template
     *
     * @return \Twig_TemplateInterface A \Twig_TemplateInterface instance
     *
     * @throws \InvalidArgumentException if the template does not exist
     */
    protected function load($name)
    {
        if ($name instanceof \Twig_Template) {
            return $name;
        }

        try {
            return $this->environment->loadTemplate((string) $name);
        } catch (\Twig_Error_Loader $e) {
            throw new \InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
        }
    }
}
PKu�Z�4˵��(Symfony/Component/Finder/Shell/Shell.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Shell;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class Shell
{
    const TYPE_UNIX    = 1;
    const TYPE_DARWIN  = 2;
    const TYPE_CYGWIN  = 3;
    const TYPE_WINDOWS = 4;
    const TYPE_BSD     = 5;

    /**
     * @var string|null
     */
    private $type;

    /**
     * Returns guessed OS type.
     *
     * @return int
     */
    public function getType()
    {
        if (null === $this->type) {
            $this->type = $this->guessType();
        }

        return $this->type;
    }

    /**
     * Tests if a command is available.
     *
     * @param string $command
     *
     * @return bool
     */
    public function testCommand($command)
    {
        if (self::TYPE_WINDOWS === $this->type) {
            // todo: find a way to test if Windows command exists
            return false;
        }

        if (!function_exists('exec')) {
            return false;
        }

        // todo: find a better way (command could not be available)
        exec('command -v '.$command, $output, $code);

        return 0 === $code && count($output) > 0;
    }

    /**
     * Guesses OS type.
     *
     * @return int
     */
    private function guessType()
    {
        $os = strtolower(PHP_OS);

        if (false !== strpos($os, 'cygwin')) {
            return self::TYPE_CYGWIN;
        }

        if (false !== strpos($os, 'darwin')) {
            return self::TYPE_DARWIN;
        }

        if (false !== strpos($os, 'bsd')) {
            return self::TYPE_BSD;
        }

        if (0 === strpos($os, 'win')) {
            return self::TYPE_WINDOWS;
        }

        return self::TYPE_UNIX;
    }
}
PKu�Z5��K��*Symfony/Component/Finder/Shell/Command.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Shell;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class Command
{
    /**
     * @var Command|null
     */
    private $parent;

    /**
     * @var array
     */
    private $bits = array();

    /**
     * @var array
     */
    private $labels = array();

    /**
     * @var \Closure|null
     */
    private $errorHandler;

    /**
     * Constructor.
     *
     * @param Command|null $parent Parent command
     */
    public function __construct(Command $parent = null)
    {
        $this->parent = $parent;
    }

    /**
     * Returns command as string.
     *
     * @return string
     */
    public function __toString()
    {
        return $this->join();
    }

    /**
     * Creates a new Command instance.
     *
     * @param Command|null $parent Parent command
     *
     * @return Command New Command instance
     */
    public static function create(Command $parent = null)
    {
        return new self($parent);
    }

    /**
     * Escapes special chars from input.
     *
     * @param string $input A string to escape
     *
     * @return string The escaped string
     */
    public static function escape($input)
    {
        return escapeshellcmd($input);
    }

    /**
     * Quotes input.
     *
     * @param string $input An argument string
     *
     * @return string The quoted string
     */
    public static function quote($input)
    {
        return escapeshellarg($input);
    }

    /**
     * Appends a string or a Command instance.
     *
     * @param string|Command $bit
     *
     * @return Command The current Command instance
     */
    public function add($bit)
    {
        $this->bits[] = $bit;

        return $this;
    }

    /**
     * Prepends a string or a command instance.
     *
     * @param string|Command $bit
     *
     * @return Command The current Command instance
     */
    public function top($bit)
    {
        array_unshift($this->bits, $bit);

        foreach ($this->labels as $label => $index) {
            $this->labels[$label] += 1;
        }

        return $this;
    }

    /**
     * Appends an argument, will be quoted.
     *
     * @param string $arg
     *
     * @return Command The current Command instance
     */
    public function arg($arg)
    {
        $this->bits[] = self::quote($arg);

        return $this;
    }

    /**
     * Appends escaped special command chars.
     *
     * @param string $esc
     *
     * @return Command The current Command instance
     */
    public function cmd($esc)
    {
        $this->bits[] = self::escape($esc);

        return $this;
    }

    /**
     * Inserts a labeled command to feed later.
     *
     * @param string $label The unique label
     *
     * @return Command The current Command instance
     *
     * @throws \RuntimeException If label already exists
     */
    public function ins($label)
    {
        if (isset($this->labels[$label])) {
            throw new \RuntimeException(sprintf('Label "%s" already exists.', $label));
        }

        $this->bits[] = self::create($this);
        $this->labels[$label] = count($this->bits)-1;

        return $this->bits[$this->labels[$label]];
    }

    /**
     * Retrieves a previously labeled command.
     *
     * @param string $label
     *
     * @return Command The labeled command
     *
     * @throws \RuntimeException
     */
    public function get($label)
    {
        if (!isset($this->labels[$label])) {
            throw new \RuntimeException(sprintf('Label "%s" does not exist.', $label));
        }

        return $this->bits[$this->labels[$label]];
    }

    /**
     * Returns parent command (if any).
     *
     * @return Command Parent command
     *
     * @throws \RuntimeException If command has no parent
     */
    public function end()
    {
        if (null === $this->parent) {
            throw new \RuntimeException('Calling end on root command doesn\'t make sense.');
        }

        return $this->parent;
    }

    /**
     * Counts bits stored in command.
     *
     * @return int The bits count
     */
    public function length()
    {
        return count($this->bits);
    }

    /**
     * @param \Closure $errorHandler
     *
     * @return Command
     */
    public function setErrorHandler(\Closure $errorHandler)
    {
        $this->errorHandler = $errorHandler;

        return $this;
    }

    /**
     * @return \Closure|null
     */
    public function getErrorHandler()
    {
        return $this->errorHandler;
    }

    /**
     * Executes current command.
     *
     * @return array The command result
     *
     * @throws \RuntimeException
     */
    public function execute()
    {
        if (null === $this->errorHandler) {
            exec($this->join(), $output);
        } else {
            $process = proc_open($this->join(), array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $pipes);
            $output = preg_split('~(\r\n|\r|\n)~', stream_get_contents($pipes[1]), -1, PREG_SPLIT_NO_EMPTY);

            if ($error = stream_get_contents($pipes[2])) {
                call_user_func($this->errorHandler, $error);
            }

            proc_close($process);
        }

        return $output ?: array();
    }

    /**
     * Joins bits.
     *
     * @return string
     */
    public function join()
    {
        return implode(' ', array_filter(
            array_map(function ($bit) {
                return $bit instanceof Command ? $bit->join() : ($bit ?: null);
            }, $this->bits),
            function ($bit) { return null !== $bit; }
        ));
    }

    /**
     * Insert a string or a Command instance before the bit at given position $index (index starts from 0).
     *
     * @param string|Command $bit
     * @param integer        $index
     *
     * @return Command The current Command instance
     */
    public function addAtIndex($bit, $index)
    {
        array_splice($this->bits, $index, 0, $bit);

        return $this;
    }
}
PKu�Z�5�9(Symfony/Component/Finder/SplFileInfo.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder;

/**
 * Extends \SplFileInfo to support relative paths
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class SplFileInfo extends \SplFileInfo
{
    private $relativePath;
    private $relativePathname;

    /**
     * Constructor
     *
     * @param string $file             The file name
     * @param string $relativePath     The relative path
     * @param string $relativePathname The relative path name
     */
    public function __construct($file, $relativePath, $relativePathname)
    {
        parent::__construct($file);
        $this->relativePath = $relativePath;
        $this->relativePathname = $relativePathname;
    }

    /**
     * Returns the relative path
     *
     * @return string the relative path
     */
    public function getRelativePath()
    {
        return $this->relativePath;
    }

    /**
     * Returns the relative path name
     *
     * @return string the relative path name
     */
    public function getRelativePathname()
    {
        return $this->relativePathname;
    }

    /**
     * Returns the contents of the file
     *
     * @return string the contents of the file
     *
     * @throws \RuntimeException
     */
    public function getContents()
    {
        $level = error_reporting(0);
        $content = file_get_contents($this->getPathname());
        error_reporting($level);
        if (false === $content) {
            $error = error_get_last();
            throw new \RuntimeException($error['message']);
        }

        return $content;
    }
}
PKu�Z%uM�PP'Symfony/Component/Finder/autoloader.phpnu�[���<?php

spl_autoload_register(function ($class) {
    if ('\\' == $class[0]) {
        $class = substr($class, 1);
    }

    if (
        0 === strpos($class, 'Symfony\\Component\\Finder\\')
        &&
        file_exists($file = __DIR__.'/../../../'.str_replace('\\', '/', $class).'.php')
    ) {
        require_once $file;
    }
});
PKu�Z��99CSymfony/Component/Finder/Exception/ShellCommandFailureException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Exception;

use Symfony\Component\Finder\Adapter\AdapterInterface;
use Symfony\Component\Finder\Shell\Command;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class ShellCommandFailureException extends AdapterFailureException
{
    /**
     * @var Command
     */
    private $command;

    /**
     * @param AdapterInterface $adapter
     * @param Command          $command
     * @param \Exception|null  $previous
     */
    public function __construct(AdapterInterface $adapter, Command $command, \Exception $previous = null)
    {
        $this->command = $command;
        parent::__construct($adapter, 'Shell command failed: "'.$command->join().'".', $previous);
    }

    /**
     * @return Command
     */
    public function getCommand()
    {
        return $this->command;
    }
}
PKu�Z�7��9Symfony/Component/Finder/Exception/ExceptionInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Exception;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
interface ExceptionInterface
{
    /**
     * @return \Symfony\Component\Finder\Adapter\AdapterInterface
     */
    public function getAdapter();
}
PKu�Z�cWޫ�<Symfony/Component/Finder/Exception/AccessDeniedException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Exception;

/**
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class AccessDeniedException extends \UnexpectedValueException
{
}
PKu�Z>�@��>Symfony/Component/Finder/Exception/AdapterFailureException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Exception;

use Symfony\Component\Finder\Adapter\AdapterInterface;

/**
 * Base exception for all adapter failures.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class AdapterFailureException extends \RuntimeException implements ExceptionInterface
{
    /**
     * @var \Symfony\Component\Finder\Adapter\AdapterInterface
     */
    private $adapter;

    /**
     * @param AdapterInterface $adapter
     * @param string|null      $message
     * @param \Exception|null  $previous
     */
    public function __construct(AdapterInterface $adapter, $message = null, \Exception $previous = null)
    {
        $this->adapter = $adapter;
        parent::__construct($message ?: 'Search failed with "'.$adapter->getName().'" adapter.', $previous);
    }

    /**
     * {@inheritdoc}
     */
    public function getAdapter()
    {
        return $this->adapter;
    }
}
PKu�ZP�����DSymfony/Component/Finder/Exception/OperationNotPermitedException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Exception;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class OperationNotPermitedException extends AdapterFailureException
{
}
PKu�Z��� ��6Symfony/Component/Finder/Comparator/DateComparator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Comparator;

/**
 * DateCompare compiles date comparisons.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class DateComparator extends Comparator
{

    /**
     * Constructor.
     *
     * @param string $test A comparison string
     *
     * @throws \InvalidArgumentException If the test is not understood
     */
    public function __construct($test)
    {
        if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) {
            throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a date test.', $test));
        }

        try {
            $date = new \DateTime($matches[2]);
            $target = $date->format('U');
        } catch (\Exception $e) {
            throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2]));
        }

        $operator = isset($matches[1]) ? $matches[1] : '==';
        if ('since' === $operator || 'after' === $operator) {
            $operator = '>';
        }

        if ('until' === $operator || 'before' === $operator) {
            $operator = '<';
        }

        $this->setOperator($operator);
        $this->setTarget($target);
    }
}
PKu�Z|F�z

2Symfony/Component/Finder/Comparator/Comparator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Comparator;

/**
 * Comparator.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Comparator
{
    private $target;
    private $operator = '==';

    /**
     * Gets the target value.
     *
     * @return string The target value
     */
    public function getTarget()
    {
        return $this->target;
    }

    /**
     * Sets the target value.
     *
     * @param string $target The target value
     */
    public function setTarget($target)
    {
        $this->target = $target;
    }

    /**
     * Gets the comparison operator.
     *
     * @return string The operator
     */
    public function getOperator()
    {
        return $this->operator;
    }

    /**
     * Sets the comparison operator.
     *
     * @param string $operator A valid operator
     *
     * @throws \InvalidArgumentException
     */
    public function setOperator($operator)
    {
        if (!$operator) {
            $operator = '==';
        }

        if (!in_array($operator, array('>', '<', '>=', '<=', '==', '!='))) {
            throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator));
        }

        $this->operator = $operator;
    }

    /**
     * Tests against the target.
     *
     * @param mixed $test A test value
     *
     * @return Boolean
     */
    public function test($test)
    {
        switch ($this->operator) {
            case '>':
                return $test > $this->target;
            case '>=':
                return $test >= $this->target;
            case '<':
                return $test < $this->target;
            case '<=':
                return $test <= $this->target;
            case '!=':
                return $test != $this->target;
        }

        return $test == $this->target;
    }
}
PKu�Z�P�

8Symfony/Component/Finder/Comparator/NumberComparator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Comparator;

/**
 * NumberComparator compiles a simple comparison to an anonymous
 * subroutine, which you can call with a value to be tested again.
 *
 * Now this would be very pointless, if NumberCompare didn't understand
 * magnitudes.
 *
 * The target value may use magnitudes of kilobytes (k, ki),
 * megabytes (m, mi), or gigabytes (g, gi).  Those suffixed
 * with an i use the appropriate 2**n version in accordance with the
 * IEC standard: http://physics.nist.gov/cuu/Units/binary.html
 *
 * Based on the Perl Number::Compare module.
 *
 * @author    Fabien Potencier <fabien@symfony.com> PHP port
 * @author    Richard Clamp <richardc@unixbeard.net> Perl version
 *
 * @copyright 2004-2005 Fabien Potencier <fabien@symfony.com>
 * @copyright 2002 Richard Clamp <richardc@unixbeard.net>
 *
 * @see       http://physics.nist.gov/cuu/Units/binary.html
 */
class NumberComparator extends Comparator
{
    /**
     * Constructor.
     *
     * @param string $test A comparison string
     *
     * @throws \InvalidArgumentException If the test is not understood
     */
    public function __construct($test)
    {
        if (!preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) {
            throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test));
        }

        $target = $matches[2];
        if (!is_numeric($target)) {
            throw new \InvalidArgumentException(sprintf('Invalid number "%s".', $target));
        }
        if (isset($matches[3])) {
            // magnitude
            switch (strtolower($matches[3])) {
                case 'k':
                    $target *= 1000;
                    break;
                case 'ki':
                    $target *= 1024;
                    break;
                case 'm':
                    $target *= 1000000;
                    break;
                case 'mi':
                    $target *= 1024*1024;
                    break;
                case 'g':
                    $target *= 1000000000;
                    break;
                case 'gi':
                    $target *= 1024*1024*1024;
                    break;
            }
        }

        $this->setTarget($target);
        $this->setOperator(isset($matches[1]) ? $matches[1] : '==');
    }
}
PKu�Z�g@Mbb!Symfony/Component/Finder/Glob.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder;

/**
 * Glob matches globbing patterns against text.
 *
 *   if match_glob("foo.*", "foo.bar") echo "matched\n";
 *
 * // prints foo.bar and foo.baz
 * $regex = glob_to_regex("foo.*");
 * for (array('foo.bar', 'foo.baz', 'foo', 'bar') as $t)
 * {
 *   if (/$regex/) echo "matched: $car\n";
 * }
 *
 * Glob implements glob(3) style matching that can be used to match
 * against text, rather than fetching names from a filesystem.
 *
 * Based on the Perl Text::Glob module.
 *
 * @author Fabien Potencier <fabien@symfony.com> PHP port
 * @author     Richard Clamp <richardc@unixbeard.net> Perl version
 * @copyright  2004-2005 Fabien Potencier <fabien@symfony.com>
 * @copyright  2002 Richard Clamp <richardc@unixbeard.net>
 */
class Glob
{
    /**
     * Returns a regexp which is the equivalent of the glob pattern.
     *
     * @param string  $glob                The glob pattern
     * @param Boolean $strictLeadingDot
     * @param Boolean $strictWildcardSlash
     *
     * @return string regex The regexp
     */
    public static function toRegex($glob, $strictLeadingDot = true, $strictWildcardSlash = true)
    {
        $firstByte = true;
        $escaping = false;
        $inCurlies = 0;
        $regex = '';
        $sizeGlob = strlen($glob);
        for ($i = 0; $i < $sizeGlob; $i++) {
            $car = $glob[$i];
            if ($firstByte) {
                if ($strictLeadingDot && '.' !== $car) {
                    $regex .= '(?=[^\.])';
                }

                $firstByte = false;
            }

            if ('/' === $car) {
                $firstByte = true;
            }

            if ('.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) {
                $regex .= "\\$car";
            } elseif ('*' === $car) {
                $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*');
            } elseif ('?' === $car) {
                $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.');
            } elseif ('{' === $car) {
                $regex .= $escaping ? '\\{' : '(';
                if (!$escaping) {
                    ++$inCurlies;
                }
            } elseif ('}' === $car && $inCurlies) {
                $regex .= $escaping ? '}' : ')';
                if (!$escaping) {
                    --$inCurlies;
                }
            } elseif (',' === $car && $inCurlies) {
                $regex .= $escaping ? ',' : '|';
            } elseif ('\\' === $car) {
                if ($escaping) {
                    $regex .= '\\\\';
                    $escaping = false;
                } else {
                    $escaping = true;
                }

                continue;
            } else {
                $regex .= $car;
            }
            $escaping = false;
        }

        return '#^'.$regex.'$#';
    }
}
PKu�Z�d�V�V#Symfony/Component/Finder/Finder.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder;

use Symfony\Component\Finder\Adapter\AdapterInterface;
use Symfony\Component\Finder\Adapter\GnuFindAdapter;
use Symfony\Component\Finder\Adapter\BsdFindAdapter;
use Symfony\Component\Finder\Adapter\PhpAdapter;
use Symfony\Component\Finder\Exception\ExceptionInterface;

/**
 * Finder allows to build rules to find files and directories.
 *
 * It is a thin wrapper around several specialized iterator classes.
 *
 * All rules may be invoked several times.
 *
 * All methods return the current Finder object to allow easy chaining:
 *
 * $finder = Finder::create()->files()->name('*.php')->in(__DIR__);
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class Finder implements \IteratorAggregate, \Countable
{
    const IGNORE_VCS_FILES = 1;
    const IGNORE_DOT_FILES = 2;

    private $mode        = 0;
    private $names       = array();
    private $notNames    = array();
    private $exclude     = array();
    private $filters     = array();
    private $depths      = array();
    private $sizes       = array();
    private $followLinks = false;
    private $sort        = false;
    private $ignore      = 0;
    private $dirs        = array();
    private $dates       = array();
    private $iterators   = array();
    private $contains    = array();
    private $notContains = array();
    private $adapters    = array();
    private $paths       = array();
    private $notPaths    = array();
    private $ignoreUnreadableDirs = false;

    private static $vcsPatterns = array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg');

    /**
     * Constructor.
     */
    public function __construct()
    {
        $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES;

        $this
            ->addAdapter(new GnuFindAdapter())
            ->addAdapter(new BsdFindAdapter())
            ->addAdapter(new PhpAdapter(), -50)
            ->setAdapter('php')
        ;
    }

    /**
     * Creates a new Finder.
     *
     * @return Finder A new Finder instance
     *
     * @api
     */
    public static function create()
    {
        return new static();
    }

    /**
     * Registers a finder engine implementation.
     *
     * @param AdapterInterface $adapter  An adapter instance
     * @param integer          $priority Highest is selected first
     *
     * @return Finder The current Finder instance
     */
    public function addAdapter(Adapter\AdapterInterface $adapter, $priority = 0)
    {
        $this->adapters[$adapter->getName()] = array(
            'adapter'  => $adapter,
            'priority' => $priority,
            'selected' => false,
        );

        return $this->sortAdapters();
    }

    /**
     * Sets the selected adapter to the best one according to the current platform the code is run on.
     *
     * @return Finder The current Finder instance
     */
    public function useBestAdapter()
    {
        $this->resetAdapterSelection();

        return $this->sortAdapters();
    }

    /**
     * Selects the adapter to use.
     *
     * @param string $name
     *
     * @throws \InvalidArgumentException
     *
     * @return Finder The current Finder instance
     */
    public function setAdapter($name)
    {
        if (!isset($this->adapters[$name])) {
            throw new \InvalidArgumentException(sprintf('Adapter "%s" does not exist.', $name));
        }

        $this->resetAdapterSelection();
        $this->adapters[$name]['selected'] = true;

        return $this->sortAdapters();
    }

    /**
     * Removes all adapters registered in the finder.
     *
     * @return Finder The current Finder instance
     */
    public function removeAdapters()
    {
        $this->adapters = array();

        return $this;
    }

    /**
     * Returns registered adapters ordered by priority without extra information.
     *
     * @return AdapterInterface[]
     */
    public function getAdapters()
    {
        return array_values(array_map(function (array $adapter) {
            return $adapter['adapter'];
        }, $this->adapters));
    }

    /**
     * Restricts the matching to directories only.
     *
     * @return Finder The current Finder instance
     *
     * @api
     */
    public function directories()
    {
        $this->mode = Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES;

        return $this;
    }

    /**
     * Restricts the matching to files only.
     *
     * @return Finder The current Finder instance
     *
     * @api
     */
    public function files()
    {
        $this->mode = Iterator\FileTypeFilterIterator::ONLY_FILES;

        return $this;
    }

    /**
     * Adds tests for the directory depth.
     *
     * Usage:
     *
     *   $finder->depth('> 1') // the Finder will start matching at level 1.
     *   $finder->depth('< 3') // the Finder will descend at most 3 levels of directories below the starting point.
     *
     * @param int $level The depth level expression
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\DepthRangeFilterIterator
     * @see Symfony\Component\Finder\Comparator\NumberComparator
     *
     * @api
     */
    public function depth($level)
    {
        $this->depths[] = new Comparator\NumberComparator($level);

        return $this;
    }

    /**
     * Adds tests for file dates (last modified).
     *
     * The date must be something that strtotime() is able to parse:
     *
     *   $finder->date('since yesterday');
     *   $finder->date('until 2 days ago');
     *   $finder->date('> now - 2 hours');
     *   $finder->date('>= 2005-10-15');
     *
     * @param string $date A date rage string
     *
     * @return Finder The current Finder instance
     *
     * @see strtotime
     * @see Symfony\Component\Finder\Iterator\DateRangeFilterIterator
     * @see Symfony\Component\Finder\Comparator\DateComparator
     *
     * @api
     */
    public function date($date)
    {
        $this->dates[] = new Comparator\DateComparator($date);

        return $this;
    }

    /**
     * Adds rules that files must match.
     *
     * You can use patterns (delimited with / sign), globs or simple strings.
     *
     * $finder->name('*.php')
     * $finder->name('/\.php$/') // same as above
     * $finder->name('test.php')
     *
     * @param string $pattern A pattern (a regexp, a glob, or a string)
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\FilenameFilterIterator
     *
     * @api
     */
    public function name($pattern)
    {
        $this->names[] = $pattern;

        return $this;
    }

    /**
     * Adds rules that files must not match.
     *
     * @param string $pattern A pattern (a regexp, a glob, or a string)
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\FilenameFilterIterator
     *
     * @api
     */
    public function notName($pattern)
    {
        $this->notNames[] = $pattern;

        return $this;
    }

    /**
     * Adds tests that file contents must match.
     *
     * Strings or PCRE patterns can be used:
     *
     * $finder->contains('Lorem ipsum')
     * $finder->contains('/Lorem ipsum/i')
     *
     * @param string $pattern A pattern (string or regexp)
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\FilecontentFilterIterator
     */
    public function contains($pattern)
    {
        $this->contains[] = $pattern;

        return $this;
    }

    /**
     * Adds tests that file contents must not match.
     *
     * Strings or PCRE patterns can be used:
     *
     * $finder->notContains('Lorem ipsum')
     * $finder->notContains('/Lorem ipsum/i')
     *
     * @param string $pattern A pattern (string or regexp)
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\FilecontentFilterIterator
     */
    public function notContains($pattern)
    {
        $this->notContains[] = $pattern;

        return $this;
    }

    /**
     * Adds rules that filenames must match.
     *
     * You can use patterns (delimited with / sign) or simple strings.
     *
     * $finder->path('some/special/dir')
     * $finder->path('/some\/special\/dir/') // same as above
     *
     * Use only / as dirname separator.
     *
     * @param string $pattern A pattern (a regexp or a string)
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\FilenameFilterIterator
     */
    public function path($pattern)
    {
        $this->paths[] = $pattern;

        return $this;
    }

    /**
     * Adds rules that filenames must not match.
     *
     * You can use patterns (delimited with / sign) or simple strings.
     *
     * $finder->notPath('some/special/dir')
     * $finder->notPath('/some\/special\/dir/') // same as above
     *
     * Use only / as dirname separator.
     *
     * @param string $pattern A pattern (a regexp or a string)
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\FilenameFilterIterator
     */
    public function notPath($pattern)
    {
        $this->notPaths[] = $pattern;

        return $this;
    }

    /**
     * Adds tests for file sizes.
     *
     * $finder->size('> 10K');
     * $finder->size('<= 1Ki');
     * $finder->size(4);
     *
     * @param string $size A size range string
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\SizeRangeFilterIterator
     * @see Symfony\Component\Finder\Comparator\NumberComparator
     *
     * @api
     */
    public function size($size)
    {
        $this->sizes[] = new Comparator\NumberComparator($size);

        return $this;
    }

    /**
     * Excludes directories.
     *
     * @param string|array $dirs A directory path or an array of directories
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator
     *
     * @api
     */
    public function exclude($dirs)
    {
        $this->exclude = array_merge($this->exclude, (array) $dirs);

        return $this;
    }

    /**
     * Excludes "hidden" directories and files (starting with a dot).
     *
     * @param Boolean $ignoreDotFiles Whether to exclude "hidden" files or not
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator
     *
     * @api
     */
    public function ignoreDotFiles($ignoreDotFiles)
    {
        if ($ignoreDotFiles) {
            $this->ignore = $this->ignore | static::IGNORE_DOT_FILES;
        } else {
            $this->ignore = $this->ignore & ~static::IGNORE_DOT_FILES;
        }

        return $this;
    }

    /**
     * Forces the finder to ignore version control directories.
     *
     * @param Boolean $ignoreVCS Whether to exclude VCS files or not
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator
     *
     * @api
     */
    public function ignoreVCS($ignoreVCS)
    {
        if ($ignoreVCS) {
            $this->ignore = $this->ignore | static::IGNORE_VCS_FILES;
        } else {
            $this->ignore = $this->ignore & ~static::IGNORE_VCS_FILES;
        }

        return $this;
    }

    /**
     * Adds VCS patterns.
     *
     * @see ignoreVCS
     *
     * @param string|string[] $pattern VCS patterns to ignore
     */
    public static function addVCSPattern($pattern)
    {
        foreach ((array) $pattern as $p) {
            self::$vcsPatterns[] = $p;
        }

        self::$vcsPatterns = array_unique(self::$vcsPatterns);
    }

    /**
     * Sorts files and directories by an anonymous function.
     *
     * The anonymous function receives two \SplFileInfo instances to compare.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @param \Closure $closure An anonymous function
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\SortableIterator
     *
     * @api
     */
    public function sort(\Closure $closure)
    {
        $this->sort = $closure;

        return $this;
    }

    /**
     * Sorts files and directories by name.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\SortableIterator
     *
     * @api
     */
    public function sortByName()
    {
        $this->sort = Iterator\SortableIterator::SORT_BY_NAME;

        return $this;
    }

    /**
     * Sorts files and directories by type (directories before files), then by name.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\SortableIterator
     *
     * @api
     */
    public function sortByType()
    {
        $this->sort = Iterator\SortableIterator::SORT_BY_TYPE;

        return $this;
    }

    /**
     * Sorts files and directories by the last accessed time.
     *
     * This is the time that the file was last accessed, read or written to.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\SortableIterator
     *
     * @api
     */
    public function sortByAccessedTime()
    {
        $this->sort = Iterator\SortableIterator::SORT_BY_ACCESSED_TIME;

        return $this;
    }

    /**
     * Sorts files and directories by the last inode changed time.
     *
     * This is the time that the inode information was last modified (permissions, owner, group or other metadata).
     *
     * On Windows, since inode is not available, changed time is actually the file creation time.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\SortableIterator
     *
     * @api
     */
    public function sortByChangedTime()
    {
        $this->sort = Iterator\SortableIterator::SORT_BY_CHANGED_TIME;

        return $this;
    }

    /**
     * Sorts files and directories by the last modified time.
     *
     * This is the last time the actual contents of the file were last modified.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\SortableIterator
     *
     * @api
     */
    public function sortByModifiedTime()
    {
        $this->sort = Iterator\SortableIterator::SORT_BY_MODIFIED_TIME;

        return $this;
    }

    /**
     * Filters the iterator with an anonymous function.
     *
     * The anonymous function receives a \SplFileInfo and must return false
     * to remove files.
     *
     * @param \Closure $closure An anonymous function
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\CustomFilterIterator
     *
     * @api
     */
    public function filter(\Closure $closure)
    {
        $this->filters[] = $closure;

        return $this;
    }

    /**
     * Forces the following of symlinks.
     *
     * @return Finder The current Finder instance
     *
     * @api
     */
    public function followLinks()
    {
        $this->followLinks = true;

        return $this;
    }

    /**
     * Tells finder to ignore unreadable directories.
     *
     * By default, scanning unreadable directories content throws an AccessDeniedException.
     *
     * @param boolean $ignore
     *
     * @return Finder The current Finder instance
     */
    public function ignoreUnreadableDirs($ignore = true)
    {
        $this->ignoreUnreadableDirs = (Boolean) $ignore;

        return $this;
    }

    /**
     * Searches files and directories which match defined rules.
     *
     * @param string|array $dirs A directory path or an array of directories
     *
     * @return Finder The current Finder instance
     *
     * @throws \InvalidArgumentException if one of the directories does not exist
     *
     * @api
     */
    public function in($dirs)
    {
        $resolvedDirs = array();

        foreach ((array) $dirs as $dir) {
            if (is_dir($dir)) {
                $resolvedDirs[] = $dir;
            } elseif ($glob = glob($dir, GLOB_ONLYDIR)) {
                $resolvedDirs = array_merge($resolvedDirs, $glob);
            } else {
                throw new \InvalidArgumentException(sprintf('The "%s" directory does not exist.', $dir));
            }
        }

        $this->dirs = array_merge($this->dirs, $resolvedDirs);

        return $this;
    }

    /**
     * Returns an Iterator for the current Finder configuration.
     *
     * This method implements the IteratorAggregate interface.
     *
     * @return \Iterator An iterator
     *
     * @throws \LogicException if the in() method has not been called
     */
    public function getIterator()
    {
        if (0 === count($this->dirs) && 0 === count($this->iterators)) {
            throw new \LogicException('You must call one of in() or append() methods before iterating over a Finder.');
        }

        if (1 === count($this->dirs) && 0 === count($this->iterators)) {
            return $this->searchInDirectory($this->dirs[0]);
        }

        $iterator = new \AppendIterator();
        foreach ($this->dirs as $dir) {
            $iterator->append($this->searchInDirectory($dir));
        }

        foreach ($this->iterators as $it) {
            $iterator->append($it);
        }

        return $iterator;
    }

    /**
     * Appends an existing set of files/directories to the finder.
     *
     * The set can be another Finder, an Iterator, an IteratorAggregate, or even a plain array.
     *
     * @param mixed $iterator
     *
     * @return Finder The finder
     *
     * @throws \InvalidArgumentException When the given argument is not iterable.
     */
    public function append($iterator)
    {
        if ($iterator instanceof \IteratorAggregate) {
            $this->iterators[] = $iterator->getIterator();
        } elseif ($iterator instanceof \Iterator) {
            $this->iterators[] = $iterator;
        } elseif ($iterator instanceof \Traversable || is_array($iterator)) {
            $it = new \ArrayIterator();
            foreach ($iterator as $file) {
                $it->append($file instanceof \SplFileInfo ? $file : new \SplFileInfo($file));
            }
            $this->iterators[] = $it;
        } else {
            throw new \InvalidArgumentException('Finder::append() method wrong argument type.');
        }

        return $this;
    }

    /**
     * Counts all the results collected by the iterators.
     *
     * @return int
     */
    public function count()
    {
        return iterator_count($this->getIterator());
    }

    /**
     * @return Finder The current Finder instance
     */
    private function sortAdapters()
    {
        uasort($this->adapters, function (array $a, array $b) {
            if ($a['selected'] || $b['selected']) {
                return $a['selected'] ? -1 : 1;
            }

            return $a['priority'] > $b['priority'] ? -1 : 1;
        });

        return $this;
    }

    /**
     * @param $dir
     *
     * @return \Iterator
     *
     * @throws \RuntimeException When none of the adapters are supported
     */
    private function searchInDirectory($dir)
    {
        if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) {
            $this->exclude = array_merge($this->exclude, self::$vcsPatterns);
        }

        if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) {
            $this->notPaths[] = '#(^|/)\..+(/|$)#';
        }

        foreach ($this->adapters as $adapter) {
            if ($adapter['adapter']->isSupported()) {
                try {
                    return $this
                        ->buildAdapter($adapter['adapter'])
                        ->searchInDirectory($dir);
                } catch (ExceptionInterface $e) {}
            }
        }

        throw new \RuntimeException('No supported adapter found.');
    }

    /**
     * @param AdapterInterface $adapter
     *
     * @return AdapterInterface
     */
    private function buildAdapter(AdapterInterface $adapter)
    {
        return $adapter
            ->setFollowLinks($this->followLinks)
            ->setDepths($this->depths)
            ->setMode($this->mode)
            ->setExclude($this->exclude)
            ->setNames($this->names)
            ->setNotNames($this->notNames)
            ->setContains($this->contains)
            ->setNotContains($this->notContains)
            ->setSizes($this->sizes)
            ->setDates($this->dates)
            ->setFilters($this->filters)
            ->setSort($this->sort)
            ->setPath($this->paths)
            ->setNotPath($this->notPaths)
            ->ignoreUnreadableDirs($this->ignoreUnreadableDirs);
    }

    /**
     * Unselects all adapters.
     */
    private function resetAdapterSelection()
    {
        $this->adapters = array_map(function (array $properties) {
            $properties['selected'] = false;

            return $properties;
        }, $this->adapters);
    }
}
PKu�Zils_��>Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

/**
 * DepthRangeFilterIterator limits the directory depth.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class DepthRangeFilterIterator extends FilterIterator
{
    private $minDepth = 0;

    /**
     * Constructor.
     *
     * @param \RecursiveIteratorIterator $iterator    The Iterator to filter
     * @param int                        $minDepth    The min depth
     * @param int                        $maxDepth    The max depth
     */
    public function __construct(\RecursiveIteratorIterator $iterator, $minDepth = 0, $maxDepth = PHP_INT_MAX)
    {
        $this->minDepth = $minDepth;
        $iterator->setMaxDepth(PHP_INT_MAX === $maxDepth ? -1 : $maxDepth);

        parent::__construct($iterator);
    }

    /**
     * Filters the iterator values.
     *
     * @return Boolean true if the value should be kept, false otherwise
     */
    public function accept()
    {
        return $this->getInnerIterator()->getDepth() >= $this->minDepth;
    }
}
PKu�Z��ɔ�
�
7Symfony/Component/Finder/Iterator/FilePathsIterator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

use Symfony\Component\Finder\SplFileInfo;

/**
 * Iterate over shell command result.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class FilePathsIterator extends \ArrayIterator
{
    /**
     * @var string
     */
    private $baseDir;

    /**
     * @var int
     */
    private $baseDirLength;

    /**
     * @var string
     */
    private $subPath;

    /**
     * @var string
     */
    private $subPathname;

    /**
     * @var SplFileInfo
     */
    private $current;

    /**
     * @param array  $paths   List of paths returned by shell command
     * @param string $baseDir Base dir for relative path building
     */
    public function __construct(array $paths, $baseDir)
    {
        $this->baseDir       = $baseDir;
        $this->baseDirLength = strlen($baseDir);

        parent::__construct($paths);
    }

    /**
     * @param string $name
     * @param array  $arguments
     *
     * @return mixed
     */
    public function __call($name, array $arguments)
    {
        return call_user_func_array(array($this->current(), $name), $arguments);
    }

    /**
     * Return an instance of SplFileInfo with support for relative paths.
     *
     * @return SplFileInfo File information
     */
    public function current()
    {
        return $this->current;
    }

    /**
     * @return string
     */
    public function key()
    {
        return $this->current->getPathname();
    }

    public function next()
    {
        parent::next();
        $this->buildProperties();
    }

    public function rewind()
    {
        parent::rewind();
        $this->buildProperties();
    }

    /**
     * @return string
     */
    public function getSubPath()
    {
        return $this->subPath;
    }

    /**
     * @return string
     */
    public function getSubPathname()
    {
        return $this->subPathname;
    }

    private function buildProperties()
    {
        $absolutePath = parent::current();

        if ($this->baseDir === substr($absolutePath, 0, $this->baseDirLength)) {
            $this->subPathname = ltrim(substr($absolutePath, $this->baseDirLength), '/\\');
            $dir = dirname($this->subPathname);
            $this->subPath = '.' === $dir ? '' : $dir;
        } else {
            $this->subPath = $this->subPathname = '';
        }

        $this->current = new SplFileInfo(parent::current(), $this->subPath, $this->subPathname);
    }
}
PKu�Z�,G��4Symfony/Component/Finder/Iterator/FilterIterator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

/**
 * This iterator just overrides the rewind method in order to correct a PHP bug.
 *
 * @see https://bugs.php.net/bug.php?id=49104
 *
 * @author Alex Bogomazov
 */
abstract class FilterIterator extends \FilterIterator
{
    /**
     * This is a workaround for the problem with \FilterIterator leaving inner \FilesystemIterator in wrong state after
     * rewind in some cases.
     *
     * @see FilterIterator::rewind()
     */
    public function rewind()
    {
        $iterator = $this;
        while ($iterator instanceof \OuterIterator) {
            $innerIterator = $iterator->getInnerIterator();

            if ($innerIterator instanceof RecursiveDirectoryIterator) {
                if ($innerIterator->isRewindable()) {
                    $innerIterator->next();
                    $innerIterator->rewind();
                }
            } elseif ($iterator->getInnerIterator() instanceof \FilesystemIterator) {
                $iterator->getInnerIterator()->next();
                $iterator->getInnerIterator()->rewind();
            }
            $iterator = $iterator->getInnerIterator();
        }

        parent::rewind();
    }
}
PKu�Z�ʽ���?Symfony/Component/Finder/Iterator/FilecontentFilterIterator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

/**
 * FilecontentFilterIterator filters files by their contents using patterns (regexps or strings).
 *
 * @author Fabien Potencier  <fabien@symfony.com>
 * @author Włodzimierz Gajda <gajdaw@gajdaw.pl>
 */
class FilecontentFilterIterator extends MultiplePcreFilterIterator
{
    /**
     * Filters the iterator values.
     *
     * @return Boolean true if the value should be kept, false otherwise
     */
    public function accept()
    {
        if (!$this->matchRegexps && !$this->noMatchRegexps) {
            return true;
        }

        $fileinfo = $this->current();

        if ($fileinfo->isDir() || !$fileinfo->isReadable()) {
            return false;
        }

        $content = $fileinfo->getContents();
        if (!$content) {
            return false;
        }

        // should at least not match one rule to exclude
        foreach ($this->noMatchRegexps as $regex) {
            if (preg_match($regex, $content)) {
                return false;
            }
        }

        // should at least match one rule
        $match = true;
        if ($this->matchRegexps) {
            $match = false;
            foreach ($this->matchRegexps as $regex) {
                if (preg_match($regex, $content)) {
                    return true;
                }
            }
        }

        return $match;
    }

    /**
     * Converts string to regexp if necessary.
     *
     * @param string $str Pattern: string or regexp
     *
     * @return string regexp corresponding to a given string or regexp
     */
    protected function toRegex($str)
    {
        return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
    }
}
PKu�Z�

���@Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

use Symfony\Component\Finder\Expression\Expression;

/**
 * MultiplePcreFilterIterator filters files using patterns (regexps, globs or strings).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class MultiplePcreFilterIterator extends FilterIterator
{
    protected $matchRegexps = array();
    protected $noMatchRegexps = array();

    /**
     * Constructor.
     *
     * @param \Iterator $iterator        The Iterator to filter
     * @param array     $matchPatterns   An array of patterns that need to match
     * @param array     $noMatchPatterns An array of patterns that need to not match
     */
    public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns)
    {
        foreach ($matchPatterns as $pattern) {
            $this->matchRegexps[] = $this->toRegex($pattern);
        }

        foreach ($noMatchPatterns as $pattern) {
            $this->noMatchRegexps[] = $this->toRegex($pattern);
        }

        parent::__construct($iterator);
    }

    /**
     * Checks whether the string is a regex.
     *
     * @param string $str
     *
     * @return Boolean Whether the given string is a regex
     */
    protected function isRegex($str)
    {
        return Expression::create($str)->isRegex();
    }

    /**
     * Converts string into regexp.
     *
     * @param string $str Pattern
     *
     * @return string regexp corresponding to a given string
     */
    abstract protected function toRegex($str);
}
PKu�Z��z":Symfony/Component/Finder/Iterator/CustomFilterIterator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

/**
 * CustomFilterIterator filters files by applying anonymous functions.
 *
 * The anonymous function receives a \SplFileInfo and must return false
 * to remove files.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class CustomFilterIterator extends FilterIterator
{
    private $filters = array();

    /**
     * Constructor.
     *
     * @param \Iterator $iterator The Iterator to filter
     * @param array     $filters  An array of PHP callbacks
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(\Iterator $iterator, array $filters)
    {
        foreach ($filters as $filter) {
            if (!is_callable($filter)) {
                throw new \InvalidArgumentException('Invalid PHP callback.');
            }
        }
        $this->filters = $filters;

        parent::__construct($iterator);
    }

    /**
     * Filters the iterator values.
     *
     * @return Boolean true if the value should be kept, false otherwise
     */
    public function accept()
    {
        $fileinfo = $this->current();

        foreach ($this->filters as $filter) {
            if (false === call_user_func($filter, $fileinfo)) {
                return false;
            }
        }

        return true;
    }
}
PKu�Z{�^ǽ�<Symfony/Component/Finder/Iterator/FilenameFilterIterator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

use Symfony\Component\Finder\Expression\Expression;

/**
 * FilenameFilterIterator filters files by patterns (a regexp, a glob, or a string).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FilenameFilterIterator extends MultiplePcreFilterIterator
{

    /**
     * Filters the iterator values.
     *
     * @return Boolean true if the value should be kept, false otherwise
     */
    public function accept()
    {
        $filename = $this->current()->getFilename();

        // should at least not match one rule to exclude
        foreach ($this->noMatchRegexps as $regex) {
            if (preg_match($regex, $filename)) {
                return false;
            }
        }

        // should at least match one rule
        $match = true;
        if ($this->matchRegexps) {
            $match = false;
            foreach ($this->matchRegexps as $regex) {
                if (preg_match($regex, $filename)) {
                    return true;
                }
            }
        }

        return $match;
    }

    /**
     * Converts glob to regexp.
     *
     * PCRE patterns are left unchanged.
     * Glob strings are transformed with Glob::toRegex().
     *
     * @param string $str Pattern: glob or regexp
     *
     * @return string regexp corresponding to a given glob or regexp
     */
    protected function toRegex($str)
    {
        return Expression::create($str)->getRegex()->render();
    }
}
PKu�Z�d����DSymfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

/**
 * ExcludeDirectoryFilterIterator filters out directories.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ExcludeDirectoryFilterIterator extends FilterIterator
{
    private $patterns = array();

    /**
     * Constructor.
     *
     * @param \Iterator $iterator    The Iterator to filter
     * @param array     $directories An array of directories to exclude
     */
    public function __construct(\Iterator $iterator, array $directories)
    {
        foreach ($directories as $directory) {
            $this->patterns[] = '#(^|/)'.preg_quote($directory, '#').'(/|$)#';
        }

        parent::__construct($iterator);
    }

    /**
     * Filters the iterator values.
     *
     * @return Boolean true if the value should be kept, false otherwise
     */
    public function accept()
    {
        $path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath();
        $path = strtr($path, '\\', '/');
        foreach ($this->patterns as $pattern) {
            if (preg_match($pattern, $path)) {
                return false;
            }
        }

        return true;
    }
}
PKu�Zx�P���=Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

use Symfony\Component\Finder\Comparator\NumberComparator;

/**
 * SizeRangeFilterIterator filters out files that are not in the given size range.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class SizeRangeFilterIterator extends FilterIterator
{
    private $comparators = array();

    /**
     * Constructor.
     *
     * @param \Iterator          $iterator    The Iterator to filter
     * @param NumberComparator[] $comparators An array of NumberComparator instances
     */
    public function __construct(\Iterator $iterator, array $comparators)
    {
        $this->comparators = $comparators;

        parent::__construct($iterator);
    }

    /**
     * Filters the iterator values.
     *
     * @return Boolean true if the value should be kept, false otherwise
     */
    public function accept()
    {
        $fileinfo = $this->current();
        if (!$fileinfo->isFile()) {
            return true;
        }

        $filesize = $fileinfo->getSize();
        foreach ($this->comparators as $compare) {
            if (!$compare->test($filesize)) {
                return false;
            }
        }

        return true;
    }
}
PKu�Z ��U��=Symfony/Component/Finder/Iterator/DateRangeFilterIterator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

use Symfony\Component\Finder\Comparator\DateComparator;

/**
 * DateRangeFilterIterator filters out files that are not in the given date range (last modified dates).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class DateRangeFilterIterator extends FilterIterator
{
    private $comparators = array();

    /**
     * Constructor.
     *
     * @param \Iterator        $iterator    The Iterator to filter
     * @param DateComparator[] $comparators An array of DateComparator instances
     */
    public function __construct(\Iterator $iterator, array $comparators)
    {
        $this->comparators = $comparators;

        parent::__construct($iterator);
    }

    /**
     * Filters the iterator values.
     *
     * @return Boolean true if the value should be kept, false otherwise
     */
    public function accept()
    {
        $fileinfo = $this->current();

        if (!$fileinfo->isFile()) {
            return true;
        }

        $filedate = $fileinfo->getMTime();
        foreach ($this->comparators as $compare) {
            if (!$compare->test($filedate)) {
                return false;
            }
        }

        return true;
    }
}
PKu�Z�n bb<Symfony/Component/Finder/Iterator/FileTypeFilterIterator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

/**
 * FileTypeFilterIterator only keeps files, directories, or both.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FileTypeFilterIterator extends FilterIterator
{
    const ONLY_FILES       = 1;
    const ONLY_DIRECTORIES = 2;

    private $mode;

    /**
     * Constructor.
     *
     * @param \Iterator $iterator The Iterator to filter
     * @param integer   $mode     The mode (self::ONLY_FILES or self::ONLY_DIRECTORIES)
     */
    public function __construct(\Iterator $iterator, $mode)
    {
        $this->mode = $mode;

        parent::__construct($iterator);
    }

    /**
     * Filters the iterator values.
     *
     * @return Boolean true if the value should be kept, false otherwise
     */
    public function accept()
    {
        $fileinfo = $this->current();
        if (self::ONLY_DIRECTORIES === (self::ONLY_DIRECTORIES & $this->mode) && $fileinfo->isFile()) {
            return false;
        } elseif (self::ONLY_FILES === (self::ONLY_FILES & $this->mode) && $fileinfo->isDir()) {
            return false;
        }

        return true;
    }
}
PKu�Z��j��	�	6Symfony/Component/Finder/Iterator/SortableIterator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

/**
 * SortableIterator applies a sort on a given Iterator.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class SortableIterator implements \IteratorAggregate
{
    const SORT_BY_NAME = 1;
    const SORT_BY_TYPE = 2;
    const SORT_BY_ACCESSED_TIME = 3;
    const SORT_BY_CHANGED_TIME = 4;
    const SORT_BY_MODIFIED_TIME = 5;

    private $iterator;
    private $sort;

    /**
     * Constructor.
     *
     * @param \Traversable     $iterator The Iterator to filter
     * @param integer|callback $sort     The sort type (SORT_BY_NAME, SORT_BY_TYPE, or a PHP callback)
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(\Traversable $iterator, $sort)
    {
        $this->iterator = $iterator;

        if (self::SORT_BY_NAME === $sort) {
            $this->sort = function ($a, $b) {
                return strcmp($a->getRealpath(), $b->getRealpath());
            };
        } elseif (self::SORT_BY_TYPE === $sort) {
            $this->sort = function ($a, $b) {
                if ($a->isDir() && $b->isFile()) {
                    return -1;
                } elseif ($a->isFile() && $b->isDir()) {
                    return 1;
                }

                return strcmp($a->getRealpath(), $b->getRealpath());
            };
        } elseif (self::SORT_BY_ACCESSED_TIME === $sort) {
            $this->sort = function ($a, $b) {
                return ($a->getATime() > $b->getATime());
            };
        } elseif (self::SORT_BY_CHANGED_TIME === $sort) {
            $this->sort = function ($a, $b) {
                return ($a->getCTime() > $b->getCTime());
            };
        } elseif (self::SORT_BY_MODIFIED_TIME === $sort) {
            $this->sort = function ($a, $b) {
                return ($a->getMTime() > $b->getMTime());
            };
        } elseif (is_callable($sort)) {
            $this->sort = $sort;
        } else {
            throw new \InvalidArgumentException('The SortableIterator takes a PHP callback or a valid built-in sort algorithm as an argument.');
        }
    }

    public function getIterator()
    {
        $array = iterator_to_array($this->iterator, true);
        uasort($array, $this->sort);

        return new \ArrayIterator($array);
    }
}
PKu�Z���)��8Symfony/Component/Finder/Iterator/PathFilterIterator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

/**
 * PathFilterIterator filters files by path patterns (e.g. some/special/dir).
 *
 * @author Fabien Potencier  <fabien@symfony.com>
 * @author Włodzimierz Gajda <gajdaw@gajdaw.pl>
 */
class PathFilterIterator extends MultiplePcreFilterIterator
{

    /**
     * Filters the iterator values.
     *
     * @return Boolean true if the value should be kept, false otherwise
     */
    public function accept()
    {
        $filename = $this->current()->getRelativePathname();

        if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
            $filename = strtr($filename, '\\', '/');
        }

        // should at least not match one rule to exclude
        foreach ($this->noMatchRegexps as $regex) {
            if (preg_match($regex, $filename)) {
                return false;
            }
        }

        // should at least match one rule
        $match = true;
        if ($this->matchRegexps) {
            $match = false;
            foreach ($this->matchRegexps as $regex) {
                if (preg_match($regex, $filename)) {
                    return true;
                }
            }
        }

        return $match;
    }

    /**
     * Converts strings to regexp.
     *
     * PCRE patterns are left unchanged.
     *
     * Default conversion:
     *     'lorem/ipsum/dolor'  ==>  'lorem\/ipsum\/dolor/'
     *
     * Use only / as directory separator (on Windows also).
     *
     * @param string $str Pattern: regexp or dirname.
     *
     * @return string regexp corresponding to a given string or regexp
     */
    protected function toRegex($str)
    {
        return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
    }
}
PKu�Z�6s��@Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

use Symfony\Component\Finder\Exception\AccessDeniedException;
use Symfony\Component\Finder\SplFileInfo;

/**
 * Extends the \RecursiveDirectoryIterator to support relative paths
 *
 * @author Victor Berchet <victor@suumit.com>
 */
class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
{
    /**
     * @var boolean
     */
    private $ignoreUnreadableDirs;

    /**
     * @var Boolean
     */
    private $rewindable;

    /**
     * Constructor.
     *
     * @param string  $path
     * @param int     $flags
     * @param boolean $ignoreUnreadableDirs
     *
     * @throws \RuntimeException
     */
    public function __construct($path, $flags, $ignoreUnreadableDirs = false)
    {
        if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) {
            throw new \RuntimeException('This iterator only support returning current as fileinfo.');
        }

        parent::__construct($path, $flags);
        $this->ignoreUnreadableDirs = $ignoreUnreadableDirs;
    }

    /**
     * Return an instance of SplFileInfo with support for relative paths
     *
     * @return SplFileInfo File information
     */
    public function current()
    {
        return new SplFileInfo(parent::current()->getPathname(), $this->getSubPath(), $this->getSubPathname());
    }

    /**
     * @return \RecursiveIterator
     *
     * @throws AccessDeniedException
     */
    public function getChildren()
    {
        try {
            return parent::getChildren();
        } catch (\UnexpectedValueException $e) {
            if ($this->ignoreUnreadableDirs) {
                // If directory is unreadable and finder is set to ignore it, a fake empty content is returned.
                return new \RecursiveArrayIterator(array());
            } else {
                throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e);
            }
        }
    }

    /**
     * Do nothing for non rewindable stream
     */
    public function rewind()
    {
        if (false === $this->isRewindable()) {
            return;
        }

        // @see https://bugs.php.net/bug.php?id=49104
        parent::next();

        parent::rewind();
    }

    /**
     * Checks if the stream is rewindable.
     *
     * @return Boolean true when the stream is rewindable, false otherwise
     */
    public function isRewindable()
    {
        if (null !== $this->rewindable) {
            return $this->rewindable;
        }

        if (false !== $stream = @opendir($this->getPath())) {
            $infos = stream_get_meta_data($stream);
            closedir($stream);

            if ($infos['seekable']) {
                return $this->rewindable = true;
            }
        }

        return $this->rewindable = false;
    }
}
PKu�Z��&
&
2Symfony/Component/Finder/Expression/Expression.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Expression;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class Expression implements ValueInterface
{
    const TYPE_REGEX = 1;
    const TYPE_GLOB  = 2;

    /**
     * @var ValueInterface
     */
    private $value;

    /**
     * @param string $expr
     *
     * @return Expression
     */
    public static function create($expr)
    {
        return new self($expr);
    }

    /**
     * @param string $expr
     */
    public function __construct($expr)
    {
        try {
            $this->value = Regex::create($expr);
        } catch (\InvalidArgumentException $e) {
            $this->value = new Glob($expr);
        }
    }

    /**
     * @return string
     */
    public function __toString()
    {
        return $this->render();
    }

    /**
     * {@inheritdoc}
     */
    public function render()
    {
        return $this->value->render();
    }

    /**
     * {@inheritdoc}
     */
    public function renderPattern()
    {
        return $this->value->renderPattern();
    }

    /**
     * @return bool
     */
    public function isCaseSensitive()
    {
        return $this->value->isCaseSensitive();
    }

    /**
     * @return int
     */
    public function getType()
    {
        return $this->value->getType();
    }

    /**
     * {@inheritdoc}
     */
    public function prepend($expr)
    {
        $this->value->prepend($expr);

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function append($expr)
    {
        $this->value->append($expr);

        return $this;
    }

    /**
     * @return bool
     */
    public function isRegex()
    {
        return self::TYPE_REGEX === $this->value->getType();
    }

    /**
     * @return bool
     */
    public function isGlob()
    {
        return self::TYPE_GLOB === $this->value->getType();
    }

    /**
     * @throws \LogicException
     *
     * @return Glob
     */
    public function getGlob()
    {
        if (self::TYPE_GLOB !== $this->value->getType()) {
            throw new \LogicException('Regex can\'t be transformed to glob.');
        }

        return $this->value;
    }

    /**
     * @return Regex
     */
    public function getRegex()
    {
        return self::TYPE_REGEX === $this->value->getType() ? $this->value : $this->value->toRegex();
    }
}
PKu�Z�"HH6Symfony/Component/Finder/Expression/ValueInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Expression;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
interface ValueInterface
{
    /**
     * Renders string representation of expression.
     *
     * @return string
     */
    public function render();

    /**
     * Renders string representation of pattern.
     *
     * @return string
     */
    public function renderPattern();

    /**
     * Returns value case sensitivity.
     *
     * @return bool
     */
    public function isCaseSensitive();

    /**
     * Returns expression type.
     *
     * @return int
     */
    public function getType();

    /**
     * @param string $expr
     *
     * @return ValueInterface
     */
    public function prepend($expr);

    /**
     * @param string $expr
     *
     * @return ValueInterface
     */
    public function append($expr);
}
PKu�Z�E�,Symfony/Component/Finder/Expression/Glob.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Expression;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class Glob implements ValueInterface
{
    /**
     * @var string
     */
    private $pattern;

    /**
     * @param string $pattern
     */
    public function __construct($pattern)
    {
        $this->pattern = $pattern;
    }

    /**
     * {@inheritdoc}
     */
    public function render()
    {
        return $this->pattern;
    }

    /**
     * {@inheritdoc}
     */
    public function renderPattern()
    {
        return $this->pattern;
    }

    /**
     * {@inheritdoc}
     */
    public function getType()
    {
        return Expression::TYPE_GLOB;
    }

    /**
     * {@inheritdoc}
     */
    public function isCaseSensitive()
    {
        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function prepend($expr)
    {
        $this->pattern = $expr.$this->pattern;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function append($expr)
    {
        $this->pattern .= $expr;

        return $this;
    }

    /**
     * Tests if glob is expandable ("*.{a,b}" syntax).
     *
     * @return bool
     */
    public function isExpandable()
    {
        return false !== strpos($this->pattern, '{')
            && false !== strpos($this->pattern, '}');
    }

    /**
     * @param bool $strictLeadingDot
     * @param bool $strictWildcardSlash
     *
     * @return Regex
     */
    public function toRegex($strictLeadingDot = true, $strictWildcardSlash = true)
    {
        $firstByte = true;
        $escaping = false;
        $inCurlies = 0;
        $regex = '';
        $sizeGlob = strlen($this->pattern);
        for ($i = 0; $i < $sizeGlob; $i++) {
            $car = $this->pattern[$i];
            if ($firstByte) {
                if ($strictLeadingDot && '.' !== $car) {
                    $regex .= '(?=[^\.])';
                }

                $firstByte = false;
            }

            if ('/' === $car) {
                $firstByte = true;
            }

            if ('.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) {
                $regex .= "\\$car";
            } elseif ('*' === $car) {
                $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*');
            } elseif ('?' === $car) {
                $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.');
            } elseif ('{' === $car) {
                $regex .= $escaping ? '\\{' : '(';
                if (!$escaping) {
                    ++$inCurlies;
                }
            } elseif ('}' === $car && $inCurlies) {
                $regex .= $escaping ? '}' : ')';
                if (!$escaping) {
                    --$inCurlies;
                }
            } elseif (',' === $car && $inCurlies) {
                $regex .= $escaping ? ',' : '|';
            } elseif ('\\' === $car) {
                if ($escaping) {
                    $regex .= '\\\\';
                    $escaping = false;
                } else {
                    $escaping = true;
                }

                continue;
            } else {
                $regex .= $car;
            }
            $escaping = false;
        }

        return new Regex('^'.$regex.'$');
    }
}
PKu�Z��(�-Symfony/Component/Finder/Expression/Regex.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Expression;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class Regex implements ValueInterface
{
    const START_FLAG = '^';
    const END_FLAG   = '$';
    const BOUNDARY   = '~';
    const JOKER      = '.*';
    const ESCAPING   = '\\';

    /**
     * @var string
     */
    private $pattern;

    /**
     * @var array
     */
    private $options;

    /**
     * @var bool
     */
    private $startFlag;

    /**
     * @var bool
     */
    private $endFlag;

    /**
     * @var bool
     */
    private $startJoker;

    /**
     * @var bool
     */
    private $endJoker;

    /**
     * @param string $expr
     *
     * @return Regex
     *
     * @throws \InvalidArgumentException
     */
    public static function create($expr)
    {
        if (preg_match('/^(.{3,}?)([imsxuADU]*)$/', $expr, $m)) {
            $start = substr($m[1], 0, 1);
            $end   = substr($m[1], -1);

            if (
                ($start === $end && !preg_match('/[*?[:alnum:] \\\\]/', $start))
                || ($start === '{' && $end === '}')
                || ($start === '(' && $end === ')')
            ) {
                return new self(substr($m[1], 1, -1), $m[2], $end);
            }
        }

        throw new \InvalidArgumentException('Given expression is not a regex.');
    }

    /**
     * @param string $pattern
     * @param string $options
     * @param string $delimiter
     */
    public function __construct($pattern, $options = '', $delimiter = null)
    {
        if (null !== $delimiter) {
            // removes delimiter escaping
            $pattern = str_replace('\\'.$delimiter, $delimiter, $pattern);
        }

        $this->parsePattern($pattern);
        $this->options = $options;
    }

    /**
     * @return string
     */
    public function __toString()
    {
        return $this->render();
    }

    /**
     * {@inheritdoc}
     */
    public function render()
    {
        return self::BOUNDARY
            .$this->renderPattern()
            .self::BOUNDARY
            .$this->options;
    }

    /**
     * {@inheritdoc}
     */
    public function renderPattern()
    {
        return ($this->startFlag ? self::START_FLAG : '')
            .($this->startJoker ? self::JOKER : '')
            .str_replace(self::BOUNDARY, '\\'.self::BOUNDARY, $this->pattern)
            .($this->endJoker ? self::JOKER : '')
            .($this->endFlag ? self::END_FLAG : '');
    }

    /**
     * {@inheritdoc}
     */
    public function isCaseSensitive()
    {
        return !$this->hasOption('i');
    }

    /**
     * {@inheritdoc}
     */
    public function getType()
    {
        return Expression::TYPE_REGEX;
    }

    /**
     * {@inheritdoc}
     */
    public function prepend($expr)
    {
        $this->pattern = $expr.$this->pattern;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function append($expr)
    {
        $this->pattern .= $expr;

        return $this;
    }

    /**
     * @param string $option
     *
     * @return bool
     */
    public function hasOption($option)
    {
        return false !== strpos($this->options, $option);
    }

    /**
     * @param string $option
     *
     * @return Regex
     */
    public function addOption($option)
    {
        if (!$this->hasOption($option)) {
            $this->options.= $option;
        }

        return $this;
    }

    /**
     * @param string $option
     *
     * @return Regex
     */
    public function removeOption($option)
    {
        $this->options = str_replace($option, '', $this->options);

        return $this;
    }

    /**
     * @param bool $startFlag
     *
     * @return Regex
     */
    public function setStartFlag($startFlag)
    {
        $this->startFlag = $startFlag;

        return $this;
    }

    /**
     * @return bool
     */
    public function hasStartFlag()
    {
        return $this->startFlag;
    }

    /**
     * @param bool $endFlag
     *
     * @return Regex
     */
    public function setEndFlag($endFlag)
    {
        $this->endFlag = (bool) $endFlag;

        return $this;
    }

    /**
     * @return bool
     */
    public function hasEndFlag()
    {
        return $this->endFlag;
    }

    /**
     * @param bool $startJoker
     *
     * @return Regex
     */
    public function setStartJoker($startJoker)
    {
        $this->startJoker = $startJoker;

        return $this;
    }

    /**
     * @return bool
     */
    public function hasStartJoker()
    {
        return $this->startJoker;
    }

    /**
     * @param bool $endJoker
     *
     * @return Regex
     */
    public function setEndJoker($endJoker)
    {
        $this->endJoker = (bool) $endJoker;

        return $this;
    }

    /**
     * @return bool
     */
    public function hasEndJoker()
    {
        return $this->endJoker;
    }

    /**
     * @param array $replacement
     *
     * @return Regex
     */
    public function replaceJokers($replacement)
    {
        $replace = function ($subject) use ($replacement) {
            $subject = $subject[0];
            $replace = 0 === substr_count($subject, '\\') % 2;

            return $replace ? str_replace('.', $replacement, $subject) : $subject;
        };

        $this->pattern = preg_replace_callback('~[\\\\]*\\.~', $replace, $this->pattern);

        return $this;
    }

    /**
     * @param string $pattern
     */
    private function parsePattern($pattern)
    {
        if ($this->startFlag = self::START_FLAG === substr($pattern, 0, 1)) {
            $pattern = substr($pattern, 1);
        }

        if ($this->startJoker = self::JOKER === substr($pattern, 0, 2)) {
            $pattern = substr($pattern, 2);
        }

        if ($this->endFlag = (self::END_FLAG === substr($pattern, -1) && self::ESCAPING !== substr($pattern, -2, -1))) {
            $pattern = substr($pattern, 0, -1);
        }

        if ($this->endJoker = (self::JOKER === substr($pattern, -2) && self::ESCAPING !== substr($pattern, -3, -2))) {
            $pattern = substr($pattern, 0, -2);
        }

        $this->pattern = $pattern;
    }
}
PKu�Z9!�2{
{
/Symfony/Component/Finder/Adapter/PhpAdapter.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Adapter;

use Symfony\Component\Finder\Iterator;

/**
 * PHP finder engine implementation.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class PhpAdapter extends AbstractAdapter
{
    /**
     * {@inheritdoc}
     */
    public function searchInDirectory($dir)
    {
        $flags = \RecursiveDirectoryIterator::SKIP_DOTS;

        if ($this->followLinks) {
            $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
        }

        $iterator = new \RecursiveIteratorIterator(
            new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs),
            \RecursiveIteratorIterator::SELF_FIRST
        );

        if ($this->minDepth > 0 || $this->maxDepth < PHP_INT_MAX) {
            $iterator = new Iterator\DepthRangeFilterIterator($iterator, $this->minDepth, $this->maxDepth);
        }

        if ($this->mode) {
            $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
        }

        if ($this->exclude) {
            $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
        }

        if ($this->names || $this->notNames) {
            $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames);
        }

        if ($this->contains || $this->notContains) {
            $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
        }

        if ($this->sizes) {
            $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes);
        }

        if ($this->dates) {
            $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates);
        }

        if ($this->filters) {
            $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
        }

        if ($this->sort) {
            $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
            $iterator = $iteratorAggregate->getIterator();
        }

        if ($this->paths || $this->notPaths) {
            $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths);
        }

        return $iterator;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'php';
    }

    /**
     * {@inheritdoc}
     */
    protected function canBeUsed()
    {
        return true;
    }
}
PKu�Z����5Symfony/Component/Finder/Adapter/AdapterInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Adapter;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
interface AdapterInterface
{
    /**
     * @param Boolean $followLinks
     *
     * @return AdapterInterface Current instance
     */
    public function setFollowLinks($followLinks);

    /**
     * @param integer $mode
     *
     * @return AdapterInterface Current instance
     */
    public function setMode($mode);

    /**
     * @param array $exclude
     *
     * @return AdapterInterface Current instance
     */
    public function setExclude(array $exclude);

    /**
     * @param array $depths
     *
     * @return AdapterInterface Current instance
     */
    public function setDepths(array $depths);

    /**
     * @param array $names
     *
     * @return AdapterInterface Current instance
     */
    public function setNames(array $names);

    /**
     * @param array $notNames
     *
     * @return AdapterInterface Current instance
     */
    public function setNotNames(array $notNames);

    /**
     * @param array $contains
     *
     * @return AdapterInterface Current instance
     */
    public function setContains(array $contains);

    /**
     * @param array $notContains
     *
     * @return AdapterInterface Current instance
     */
    public function setNotContains(array $notContains);

    /**
     * @param array $sizes
     *
     * @return AdapterInterface Current instance
     */
    public function setSizes(array $sizes);

    /**
     * @param array $dates
     *
     * @return AdapterInterface Current instance
     */
    public function setDates(array $dates);

    /**
     * @param array $filters
     *
     * @return AdapterInterface Current instance
     */
    public function setFilters(array $filters);

    /**
     * @param \Closure|integer $sort
     *
     * @return AdapterInterface Current instance
     */
    public function setSort($sort);

    /**
     * @param array $paths
     *
     * @return AdapterInterface Current instance
     */
    public function setPath(array $paths);

    /**
     * @param array $notPaths
     *
     * @return AdapterInterface Current instance
     */
    public function setNotPath(array $notPaths);

    /**
     * @param boolean $ignore
     *
     * @return AdapterInterface Current instance
     */
    public function ignoreUnreadableDirs($ignore = true);

    /**
     * @param string $dir
     *
     * @return \Iterator Result iterator
     */
    public function searchInDirectory($dir);

    /**
     * Tests adapter support for current platform.
     *
     * @return Boolean
     */
    public function isSupported();

    /**
     * Returns adapter name.
     *
     * @return string
     */
    public function getName();
}
PKu�Z��kA�
�
3Symfony/Component/Finder/Adapter/BsdFindAdapter.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Adapter;

use Symfony\Component\Finder\Shell\Shell;
use Symfony\Component\Finder\Shell\Command;
use Symfony\Component\Finder\Iterator\SortableIterator;
use Symfony\Component\Finder\Expression\Expression;

/**
 * Shell engine implementation using BSD find command.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class BsdFindAdapter extends AbstractFindAdapter
{
    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'bsd_find';
    }

    /**
     * {@inheritdoc}
     */
    protected function canBeUsed()
    {
        return in_array($this->shell->getType(), array(Shell::TYPE_BSD, Shell::TYPE_DARWIN)) && parent::canBeUsed();
    }

    /**
     * {@inheritdoc}
     */
    protected function buildFormatSorting(Command $command, $sort)
    {
        switch ($sort) {
            case SortableIterator::SORT_BY_NAME:
                $command->ins('sort')->add('| sort');

                return;
            case SortableIterator::SORT_BY_TYPE:
                $format = '%HT';
                break;
            case SortableIterator::SORT_BY_ACCESSED_TIME:
                $format = '%a';
                break;
            case SortableIterator::SORT_BY_CHANGED_TIME:
                $format = '%c';
                break;
            case SortableIterator::SORT_BY_MODIFIED_TIME:
                $format = '%m';
                break;
            default:
                throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort));
        }

        $command
            ->add('-print0 | xargs -0 stat -f')
            ->arg($format.'%t%N')
            ->add('| sort | cut -f 2');
    }

    /**
     * {@inheritdoc}
     */
    protected function buildFindCommand(Command $command, $dir)
    {
        parent::buildFindCommand($command, $dir)->addAtIndex('-E', 1);

        return $command;
    }

    /**
     * {@inheritdoc}
     */
    protected function buildContentFiltering(Command $command, array $contains, $not = false)
    {
        foreach ($contains as $contain) {
            $expr = Expression::create($contain);

            // todo: avoid forking process for each $pattern by using multiple -e options
            $command
                ->add('| grep -v \'^$\'')
                ->add('| xargs -I{} grep -I')
                ->add($expr->isCaseSensitive() ? null : '-i')
                ->add($not ? '-L' : '-l')
                ->add('-Ee')->arg($expr->renderPattern())
                ->add('{}')
            ;
        }
    }
}
PKu�Z�}]�
�
3Symfony/Component/Finder/Adapter/GnuFindAdapter.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Adapter;

use Symfony\Component\Finder\Shell\Shell;
use Symfony\Component\Finder\Shell\Command;
use Symfony\Component\Finder\Iterator\SortableIterator;
use Symfony\Component\Finder\Expression\Expression;

/**
 * Shell engine implementation using GNU find command.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class GnuFindAdapter extends AbstractFindAdapter
{
    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'gnu_find';
    }

    /**
     * {@inheritdoc}
     */
    protected function buildFormatSorting(Command $command, $sort)
    {
        switch ($sort) {
            case SortableIterator::SORT_BY_NAME:
                $command->ins('sort')->add('| sort');

                return;
            case SortableIterator::SORT_BY_TYPE:
                $format = '%y';
                break;
            case SortableIterator::SORT_BY_ACCESSED_TIME:
                $format = '%A@';
                break;
            case SortableIterator::SORT_BY_CHANGED_TIME:
                $format = '%C@';
                break;
            case SortableIterator::SORT_BY_MODIFIED_TIME:
                $format = '%T@';
                break;
            default:
                throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort));
        }

        $command
            ->get('find')
            ->add('-printf')
            ->arg($format.' %h/%f\\n')
            ->add('| sort | cut')
            ->arg('-d ')
            ->arg('-f2-')
        ;
    }

    /**
     * {@inheritdoc}
     */
    protected function canBeUsed()
    {
        return $this->shell->getType() === Shell::TYPE_UNIX && parent::canBeUsed();
    }

    /**
     * {@inheritdoc}
     */
    protected function buildFindCommand(Command $command, $dir)
    {
      return parent::buildFindCommand($command, $dir)->add('-regextype posix-extended');
    }

    /**
     * {@inheritdoc}
     */
    protected function buildContentFiltering(Command $command, array $contains, $not = false)
    {
        foreach ($contains as $contain) {
            $expr = Expression::create($contain);

            // todo: avoid forking process for each $pattern by using multiple -e options
            $command
                ->add('| xargs -I{} -r grep -I')
                ->add($expr->isCaseSensitive() ? null : '-i')
                ->add($not ? '-L' : '-l')
                ->add('-Ee')->arg($expr->renderPattern())
                ->add('{}')
            ;
        }
    }
}
PKu�ZQJ)�)8Symfony/Component/Finder/Adapter/AbstractFindAdapter.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Adapter;

use Symfony\Component\Finder\Exception\AccessDeniedException;
use Symfony\Component\Finder\Iterator;
use Symfony\Component\Finder\Shell\Shell;
use Symfony\Component\Finder\Expression\Expression;
use Symfony\Component\Finder\Shell\Command;
use Symfony\Component\Finder\Iterator\SortableIterator;
use Symfony\Component\Finder\Comparator\NumberComparator;
use Symfony\Component\Finder\Comparator\DateComparator;

/**
 * Shell engine implementation using GNU find command.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
abstract class AbstractFindAdapter extends AbstractAdapter
{
    /**
     * @var Shell
     */
    protected $shell;

    /**
     * Constructor.
     */
    public function __construct()
    {
        $this->shell = new Shell();
    }

    /**
     * {@inheritdoc}
     */
    public function searchInDirectory($dir)
    {
        // having "/../" in path make find fail
        $dir = realpath($dir);

        // searching directories containing or not containing strings leads to no result
        if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode && ($this->contains || $this->notContains)) {
            return new Iterator\FilePathsIterator(array(), $dir);
        }

        $command = Command::create();
        $find = $this->buildFindCommand($command, $dir);

        if ($this->followLinks) {
            $find->add('-follow');
        }

        $find->add('-mindepth')->add($this->minDepth + 1);

        if (PHP_INT_MAX !== $this->maxDepth) {
            $find->add('-maxdepth')->add($this->maxDepth + 1);
        }

        if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode) {
            $find->add('-type d');
        } elseif (Iterator\FileTypeFilterIterator::ONLY_FILES === $this->mode) {
            $find->add('-type f');
        }

        $this->buildNamesFiltering($find, $this->names);
        $this->buildNamesFiltering($find, $this->notNames, true);
        $this->buildPathsFiltering($find, $dir, $this->paths);
        $this->buildPathsFiltering($find, $dir, $this->notPaths, true);
        $this->buildSizesFiltering($find, $this->sizes);
        $this->buildDatesFiltering($find, $this->dates);

        $useGrep = $this->shell->testCommand('grep') && $this->shell->testCommand('xargs');
        $useSort = is_int($this->sort) && $this->shell->testCommand('sort') && $this->shell->testCommand('cut');

        if ($useGrep && ($this->contains || $this->notContains)) {
            $grep = $command->ins('grep');
            $this->buildContentFiltering($grep, $this->contains);
            $this->buildContentFiltering($grep, $this->notContains, true);
        }

        if ($useSort) {
            $this->buildSorting($command, $this->sort);
        }

        $command->setErrorHandler(
            $this->ignoreUnreadableDirs
                // If directory is unreadable and finder is set to ignore it, `stderr` is ignored.
                ? function ($stderr) { return; }
                : function ($stderr) { throw new AccessDeniedException($stderr); }
        );

        $paths = $this->shell->testCommand('uniq') ? $command->add('| uniq')->execute() : array_unique($command->execute());
        $iterator = new Iterator\FilePathsIterator($paths, $dir);

        if ($this->exclude) {
            $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
        }

        if (!$useGrep && ($this->contains || $this->notContains)) {
            $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
        }

        if ($this->filters) {
            $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
        }

        if (!$useSort && $this->sort) {
            $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
            $iterator = $iteratorAggregate->getIterator();
        }

        return $iterator;
    }

    /**
     * {@inheritdoc}
     */
    protected function canBeUsed()
    {
        return $this->shell->testCommand('find');
    }

    /**
     * @param Command $command
     * @param string  $dir
     *
     * @return Command
     */
    protected function buildFindCommand(Command $command, $dir)
    {
        return $command
            ->ins('find')
            ->add('find ')
            ->arg($dir)
            ->add('-noleaf'); // the -noleaf option is required for filesystems that don't follow the '.' and '..' conventions
    }

    /**
     * @param Command  $command
     * @param string[] $names
     * @param Boolean  $not
     */
    private function buildNamesFiltering(Command $command, array $names, $not = false)
    {
        if (0 === count($names)) {
            return;
        }

        $command->add($not ? '-not' : null)->cmd('(');

        foreach ($names as $i => $name) {
            $expr = Expression::create($name);

            // Find does not support expandable globs ("*.{a,b}" syntax).
            if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
                $expr = Expression::create($expr->getGlob()->toRegex(false));
            }

            // Fixes 'not search' and 'full path matching' regex problems.
            // - Jokers '.' are replaced by [^/].
            // - We add '[^/]*' before and after regex (if no ^|$ flags are present).
            if ($expr->isRegex()) {
                $regex = $expr->getRegex();
                $regex->prepend($regex->hasStartFlag() ? '/' : '/[^/]*')
                    ->setStartFlag(false)
                    ->setStartJoker(true)
                    ->replaceJokers('[^/]');
                if (!$regex->hasEndFlag() || $regex->hasEndJoker()) {
                    $regex->setEndJoker(false)->append('[^/]*');
                }
            }

            $command
                ->add($i > 0 ? '-or' : null)
                ->add($expr->isRegex()
                    ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
                    : ($expr->isCaseSensitive() ? '-name' : '-iname')
                )
                ->arg($expr->renderPattern());
        }

        $command->cmd(')');
    }

    /**
     * @param Command  $command
     * @param string   $dir
     * @param string[] $paths
     * @param Boolean  $not
     */
    private function buildPathsFiltering(Command $command, $dir, array $paths, $not = false)
    {
        if (0 === count($paths)) {
            return;
        }

        $command->add($not ? '-not' : null)->cmd('(');

        foreach ($paths as $i => $path) {
            $expr = Expression::create($path);

            // Find does not support expandable globs ("*.{a,b}" syntax).
            if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
                $expr = Expression::create($expr->getGlob()->toRegex(false));
            }

            // Fixes 'not search' regex problems.
            if ($expr->isRegex()) {
                $regex = $expr->getRegex();
                $regex->prepend($regex->hasStartFlag() ? $dir.DIRECTORY_SEPARATOR : '.*')->setEndJoker(!$regex->hasEndFlag());
            } else {
                $expr->prepend('*')->append('*');
            }

            $command
                ->add($i > 0 ? '-or' : null)
                ->add($expr->isRegex()
                    ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
                    : ($expr->isCaseSensitive() ? '-path' : '-ipath')
                )
                ->arg($expr->renderPattern());
        }

        $command->cmd(')');
    }

    /**
     * @param Command            $command
     * @param NumberComparator[] $sizes
     */
    private function buildSizesFiltering(Command $command, array $sizes)
    {
        foreach ($sizes as $i => $size) {
            $command->add($i > 0 ? '-and' : null);

            switch ($size->getOperator()) {
                case '<=':
                    $command->add('-size -'.($size->getTarget() + 1).'c');
                    break;
                case '>=':
                    $command->add('-size +'. ($size->getTarget() - 1).'c');
                    break;
                case '>':
                    $command->add('-size +'.$size->getTarget().'c');
                    break;
                case '!=':
                    $command->add('-size -'.$size->getTarget().'c');
                    $command->add('-size +'.$size->getTarget().'c');
                case '<':
                default:
                    $command->add('-size -'.$size->getTarget().'c');
            }
        }
    }

    /**
     * @param Command          $command
     * @param DateComparator[] $dates
     */
    private function buildDatesFiltering(Command $command, array $dates)
    {
        foreach ($dates as $i => $date) {
            $command->add($i > 0 ? '-and' : null);

            $mins = (int) round((time()-$date->getTarget()) / 60);

            if (0 > $mins) {
                // mtime is in the future
                $command->add(' -mmin -0');
                // we will have no result so we don't need to continue
                return;
            }

            switch ($date->getOperator()) {
                case '<=':
                    $command->add('-mmin +'.($mins - 1));
                    break;
                case '>=':
                    $command->add('-mmin -'.($mins + 1));
                    break;
                case '>':
                    $command->add('-mmin -'.$mins);
                    break;
                case '!=':
                    $command->add('-mmin +'.$mins.' -or -mmin -'.$mins);
                    break;
                case '<':
                default:
                    $command->add('-mmin +'.$mins);
            }
        }
    }

    /**
     * @param Command $command
     * @param string  $sort
     *
     * @throws \InvalidArgumentException
     */
    private function buildSorting(Command $command, $sort)
    {
        $this->buildFormatSorting($command, $sort);
    }

    /**
     * @param Command $command
     * @param string  $sort
     */
    abstract protected function buildFormatSorting(Command $command, $sort);

    /**
     * @param Command $command
     * @param array   $contains
     * @param Boolean $not
     */
    abstract protected function buildContentFiltering(Command $command, array $contains, $not = false);
}
PKu�Z�	4Symfony/Component/Finder/Adapter/AbstractAdapter.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Adapter;

/**
 * Interface for finder engine implementations.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
abstract class AbstractAdapter implements AdapterInterface
{
    protected $followLinks = false;
    protected $mode        = 0;
    protected $minDepth    = 0;
    protected $maxDepth    = PHP_INT_MAX;
    protected $exclude     = array();
    protected $names       = array();
    protected $notNames    = array();
    protected $contains    = array();
    protected $notContains = array();
    protected $sizes       = array();
    protected $dates       = array();
    protected $filters     = array();
    protected $sort        = false;
    protected $paths       = array();
    protected $notPaths    = array();
    protected $ignoreUnreadableDirs = false;

    private static $areSupported = array();

    /**
     * {@inheritDoc}
     */
    public function isSupported()
    {
        $name = $this->getName();

        if (!array_key_exists($name, self::$areSupported)) {
            self::$areSupported[$name] = $this->canBeUsed();
        }

        return self::$areSupported[$name];
    }

    /**
     * {@inheritdoc}
     */
    public function setFollowLinks($followLinks)
    {
        $this->followLinks = $followLinks;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setMode($mode)
    {
        $this->mode = $mode;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setDepths(array $depths)
    {
        $this->minDepth = 0;
        $this->maxDepth = PHP_INT_MAX;

        foreach ($depths as $comparator) {
            switch ($comparator->getOperator()) {
                case '>':
                    $this->minDepth = $comparator->getTarget() + 1;
                    break;
                case '>=':
                    $this->minDepth = $comparator->getTarget();
                    break;
                case '<':
                    $this->maxDepth = $comparator->getTarget() - 1;
                    break;
                case '<=':
                    $this->maxDepth = $comparator->getTarget();
                    break;
                default:
                    $this->minDepth = $this->maxDepth = $comparator->getTarget();
            }
        }

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setExclude(array $exclude)
    {
        $this->exclude = $exclude;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setNames(array $names)
    {
        $this->names = $names;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setNotNames(array $notNames)
    {
        $this->notNames = $notNames;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setContains(array $contains)
    {
        $this->contains = $contains;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setNotContains(array $notContains)
    {
        $this->notContains = $notContains;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setSizes(array $sizes)
    {
        $this->sizes = $sizes;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setDates(array $dates)
    {
        $this->dates = $dates;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setFilters(array $filters)
    {
        $this->filters = $filters;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setSort($sort)
    {
        $this->sort = $sort;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setPath(array $paths)
    {
        $this->paths = $paths;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setNotPath(array $notPaths)
    {
        $this->notPaths = $notPaths;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function ignoreUnreadableDirs($ignore = true)
    {
        $this->ignoreUnreadableDirs = (Boolean) $ignore;

        return $this;
    }

    /**
     * Returns whether the adapter is supported in the current environment.
     *
     * This method should be implemented in all adapters. Do not implement
     * isSupported in the adapters as the generic implementation provides a cache
     * layer.
     *
     * @see isSupported
     *
     * @return Boolean Whether the adapter is supported
     */
    abstract protected function canBeUsed();
}
PKu�Z����:Symfony/Component/Translation/Extractor/ChainExtractor.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Extractor;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * ChainExtractor extracts translation messages from template files.
 *
 * @author Michel Salib <michelsalib@hotmail.com>
 */
class ChainExtractor implements ExtractorInterface
{
    /**
     * The extractors.
     *
     * @var ExtractorInterface[]
     */
    private $extractors = array();

    /**
     * Adds a loader to the translation extractor.
     *
     * @param string             $format    The format of the loader
     * @param ExtractorInterface $extractor The loader
     */
    public function addExtractor($format, ExtractorInterface $extractor)
    {
        $this->extractors[$format] = $extractor;
    }

    /**
     * {@inheritDoc}
     */
    public function setPrefix($prefix)
    {
        foreach ($this->extractors as $extractor) {
            $extractor->setPrefix($prefix);
        }
    }

    /**
     * {@inheritDoc}
     */
    public function extract($directory, MessageCatalogue $catalogue)
    {
        foreach ($this->extractors as $extractor) {
            $extractor->extract($directory, $catalogue);
        }
    }
}
PKu�ZArP�>Symfony/Component/Translation/Extractor/ExtractorInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Extractor;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * Extracts translation messages from a template directory to the catalogue.
 * New found messages are injected to the catalogue using the prefix.
 *
 * @author Michel Salib <michelsalib@hotmail.com>
 */
interface ExtractorInterface
{
    /**
     * Extracts translation messages from a template directory to the catalogue.
     *
     * @param string           $directory The path to look into
     * @param MessageCatalogue $catalogue The catalogue
     */
    public function extract($directory, MessageCatalogue $catalogue);

    /**
     * Sets the prefix that should be used for new found messages.
     *
     * @param string $prefix The prefix
     */
    public function setPrefix($prefix);
}
PKu�Zb*0�oo4Symfony/Component/Translation/PluralizationRules.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

/**
 * Returns the plural rules for a given locale.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class PluralizationRules
{
    // @codeCoverageIgnoreStart
    private static $rules = array();

    /**
     * Returns the plural position to use for the given locale and number.
     *
     * @param integer $number The number
     * @param string  $locale The locale
     *
     * @return integer The plural position
     */
    public static function get($number, $locale)
    {
        if ('pt_BR' === $locale) {
            // temporary set a locale for brazilian
            $locale = 'xbr';
        }

        if (strlen($locale) > 3) {
            $locale = substr($locale, 0, -strlen(strrchr($locale, '_')));
        }

        if (isset(self::$rules[$locale])) {
            $return = call_user_func(self::$rules[$locale], $number);

            if (!is_int($return) || $return < 0) {
                return 0;
            }

            return $return;
        }

        /*
         * The plural rules are derived from code of the Zend Framework (2010-09-25),
         * which is subject to the new BSD license (http://framework.zend.com/license/new-bsd).
         * Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
         */
        switch ($locale) {
            case 'bo':
            case 'dz':
            case 'id':
            case 'ja':
            case 'jv':
            case 'ka':
            case 'km':
            case 'kn':
            case 'ko':
            case 'ms':
            case 'th':
            case 'tr':
            case 'vi':
            case 'zh':
                return 0;
                break;

            case 'af':
            case 'az':
            case 'bn':
            case 'bg':
            case 'ca':
            case 'da':
            case 'de':
            case 'el':
            case 'en':
            case 'eo':
            case 'es':
            case 'et':
            case 'eu':
            case 'fa':
            case 'fi':
            case 'fo':
            case 'fur':
            case 'fy':
            case 'gl':
            case 'gu':
            case 'ha':
            case 'he':
            case 'hu':
            case 'is':
            case 'it':
            case 'ku':
            case 'lb':
            case 'ml':
            case 'mn':
            case 'mr':
            case 'nah':
            case 'nb':
            case 'ne':
            case 'nl':
            case 'nn':
            case 'no':
            case 'om':
            case 'or':
            case 'pa':
            case 'pap':
            case 'ps':
            case 'pt':
            case 'so':
            case 'sq':
            case 'sv':
            case 'sw':
            case 'ta':
            case 'te':
            case 'tk':
            case 'ur':
            case 'zu':
                return ($number == 1) ? 0 : 1;

            case 'am':
            case 'bh':
            case 'fil':
            case 'fr':
            case 'gun':
            case 'hi':
            case 'ln':
            case 'mg':
            case 'nso':
            case 'xbr':
            case 'ti':
            case 'wa':
                return (($number == 0) || ($number == 1)) ? 0 : 1;

            case 'be':
            case 'bs':
            case 'hr':
            case 'ru':
            case 'sr':
            case 'uk':
                return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);

            case 'cs':
            case 'sk':
                return ($number == 1) ? 0 : ((($number >= 2) && ($number <= 4)) ? 1 : 2);

            case 'ga':
                return ($number == 1) ? 0 : (($number == 2) ? 1 : 2);

            case 'lt':
                return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);

            case 'sl':
                return ($number % 100 == 1) ? 0 : (($number % 100 == 2) ? 1 : ((($number % 100 == 3) || ($number % 100 == 4)) ? 2 : 3));

            case 'mk':
                return ($number % 10 == 1) ? 0 : 1;

            case 'mt':
                return ($number == 1) ? 0 : ((($number == 0) || (($number % 100 > 1) && ($number % 100 < 11))) ? 1 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 2 : 3));

            case 'lv':
                return ($number == 0) ? 0 : ((($number % 10 == 1) && ($number % 100 != 11)) ? 1 : 2);

            case 'pl':
                return ($number == 1) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 1 : 2);

            case 'cy':
                return ($number == 1) ? 0 : (($number == 2) ? 1 : ((($number == 8) || ($number == 11)) ? 2 : 3));

            case 'ro':
                return ($number == 1) ? 0 : ((($number == 0) || (($number % 100 > 0) && ($number % 100 < 20))) ? 1 : 2);

            case 'ar':
                return ($number == 0) ? 0 : (($number == 1) ? 1 : (($number == 2) ? 2 : ((($number >= 3) && ($number <= 10)) ? 3 : ((($number >= 11) && ($number <= 99)) ? 4 : 5))));

            default:
                return 0;
        }
    }

    /**
     * Overrides the default plural rule for a given locale.
     *
     * @param string $rule   A PHP callable
     * @param string $locale The locale
     *
     * @throws \LogicException
     */
    public static function set($rule, $locale)
    {
        if ('pt_BR' === $locale) {
            // temporary set a locale for brazilian
            $locale = 'xbr';
        }

        if (strlen($locale) > 3) {
            $locale = substr($locale, 0, -strlen(strrchr($locale, '_')));
        }

        if (!is_callable($rule)) {
            throw new \LogicException('The given rule can not be called');
        }

        self::$rules[$locale] = $rule;
    }

    // @codeCoverageIgnoreEnd
}
PKu�Z�q��UU,Symfony/Component/Translation/autoloader.phpnu�[���<?php

spl_autoload_register(function ($class) {
    if ('\\' == $class[0]) {
        $class = substr($class, 1);
    }

    if (
        0 === strpos($class, 'Symfony\\Component\\Translation\\')
        &&
        file_exists($file = __DIR__.'/../../../'.str_replace('\\', '/', $class).'.php')
    ) {
        require_once $file;
    }
});
PKu�Z�<qNN1Symfony/Component/Translation/MessageSelector.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

/**
 * MessageSelector.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class MessageSelector
{
    /**
     * Given a message with different plural translations separated by a
     * pipe (|), this method returns the correct portion of the message based
     * on the given number, locale and the pluralization rules in the message
     * itself.
     *
     * The message supports two different types of pluralization rules:
     *
     * interval: {0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples
     * indexed:  There is one apple|There are %count% apples
     *
     * The indexed solution can also contain labels (e.g. one: There is one apple).
     * This is purely for making the translations more clear - it does not
     * affect the functionality.
     *
     * The two methods can also be mixed:
     *     {0} There are no apples|one: There is one apple|more: There are %count% apples
     *
     * @param string  $message The message being translated
     * @param integer $number  The number of items represented for the message
     * @param string  $locale  The locale to use for choosing
     *
     * @return string
     *
     * @throws \InvalidArgumentException
     *
     * @api
     */
    public function choose($message, $number, $locale)
    {
        $parts = explode('|', $message);
        $explicitRules = array();
        $standardRules = array();
        foreach ($parts as $part) {
            $part = trim($part);

            if (preg_match('/^(?P<interval>'.Interval::getIntervalRegexp().')\s*(?P<message>.*?)$/x', $part, $matches)) {
                $explicitRules[$matches['interval']] = $matches['message'];
            } elseif (preg_match('/^\w+\:\s*(.*?)$/', $part, $matches)) {
                $standardRules[] = $matches[1];
            } else {
                $standardRules[] = $part;
            }
        }

        // try to match an explicit rule, then fallback to the standard ones
        foreach ($explicitRules as $interval => $m) {
            if (Interval::test($number, $interval)) {
                return $m;
            }
        }

        $position = PluralizationRules::get($number, $locale);

        if (!isset($standardRules[$position])) {
            // when there's exactly one rule given, and that rule is a standard
            // rule, use this rule
            if (1 === count($parts) && isset($standardRules[0])) {
                return $standardRules[0];
            }

            throw new \InvalidArgumentException(sprintf('Unable to choose a translation for "%s" with locale "%s". Double check that this translation has the correct plural options (e.g. "There is one apple|There are %%count%% apples").', $message, $locale));
        }

        return $standardRules[$position];
    }
}
PKu�Z�س��:Symfony/Component/Translation/Catalogue/MergeOperation.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Catalogue;

/**
 * Merge operation between two catalogues.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class MergeOperation extends AbstractOperation
{
    /**
     * {@inheritdoc}
     */
    protected function processDomain($domain)
    {
        $this->messages[$domain] = array(
            'all'      => array(),
            'new'      => array(),
            'obsolete' => array(),
        );

        foreach ($this->source->all($domain) as $id => $message) {
            $this->messages[$domain]['all'][$id] = $message;
            $this->result->add(array($id => $message), $domain);
        }

        foreach ($this->target->all($domain) as $id => $message) {
            if (!$this->source->has($id, $domain)) {
                $this->messages[$domain]['all'][$id] = $message;
                $this->messages[$domain]['new'][$id] = $message;
                $this->result->add(array($id => $message), $domain);
            }
        }
    }
}
PKu�ZY[�>Symfony/Component/Translation/Catalogue/OperationInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Catalogue;

use Symfony\Component\Translation\MessageCatalogueInterface;

/**
 * Represents an operation on catalogue(s).
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
interface OperationInterface
{
    /**
     * Returns domains affected by operation.
     *
     * @return array
     */
    public function getDomains();

    /**
     * Returns all valid messages after operation.
     *
     * @param string $domain
     *
     * @return array
     */
    public function getMessages($domain);

    /**
     * Returns new messages after operation.
     *
     * @param string $domain
     *
     * @return array
     */
    public function getNewMessages($domain);

    /**
     * Returns obsolete messages after operation.
     *
     * @param string $domain
     *
     * @return array
     */
    public function getObsoleteMessages($domain);

    /**
     * Returns resulting catalogue.
     *
     * @return MessageCatalogueInterface
     */
    public function getResult();
}
PKu�Z��fb�
�
=Symfony/Component/Translation/Catalogue/AbstractOperation.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Catalogue;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\MessageCatalogueInterface;

/**
 * Base catalogues binary operation class.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
abstract class AbstractOperation implements OperationInterface
{
    /**
     * @var MessageCatalogueInterface
     */
    protected $source;

    /**
     * @var MessageCatalogueInterface
     */
    protected $target;

    /**
     * @var MessageCatalogue
     */
    protected $result;

    /**
     * @var null|array
     */
    private $domains;

    /**
     * @var array
     */
    protected $messages;

    /**
     * @param MessageCatalogueInterface $source
     * @param MessageCatalogueInterface $target
     *
     * @throws \LogicException
     */
    public function __construct(MessageCatalogueInterface $source, MessageCatalogueInterface $target)
    {
        if ($source->getLocale() !== $target->getLocale()) {
            throw new \LogicException('Operated catalogues must belong to the same locale.');
        }

        $this->source = $source;
        $this->target = $target;
        $this->result = new MessageCatalogue($source->getLocale());
        $this->domains = null;
        $this->messages = array();
    }

    /**
     * {@inheritdoc}
     */
    public function getDomains()
    {
        if (null === $this->domains) {
            $this->domains = array_values(array_unique(array_merge($this->source->getDomains(), $this->target->getDomains())));
        }

        return $this->domains;
    }

    /**
     * {@inheritdoc}
     */
    public function getMessages($domain)
    {
        if (!in_array($domain, $this->getDomains())) {
            throw new \InvalidArgumentException(sprintf('Invalid domain: %s.', $domain));
        }

        if (!isset($this->messages[$domain]['all'])) {
            $this->processDomain($domain);
        }

        return $this->messages[$domain]['all'];
    }

    /**
     * {@inheritdoc}
     */
    public function getNewMessages($domain)
    {
        if (!in_array($domain, $this->getDomains())) {
            throw new \InvalidArgumentException(sprintf('Invalid domain: %s.', $domain));
        }

        if (!isset($this->messages[$domain]['new'])) {
            $this->processDomain($domain);
        }

        return $this->messages[$domain]['new'];
    }

    /**
     * {@inheritdoc}
     */
    public function getObsoleteMessages($domain)
    {
        if (!in_array($domain, $this->getDomains())) {
            throw new \InvalidArgumentException(sprintf('Invalid domain: %s.', $domain));
        }

        if (!isset($this->messages[$domain]['obsolete'])) {
            $this->processDomain($domain);
        }

        return $this->messages[$domain]['obsolete'];
    }

    /**
     * {@inheritdoc}
     */
    public function getResult()
    {
        foreach ($this->getDomains() as $domain) {
            if (!isset($this->messages[$domain])) {
                $this->processDomain($domain);
            }
        }

        return $this->result;
    }

    /**
     * @param string $domain
     */
    abstract protected function processDomain($domain);
}
PKu�Z��ӄ�9Symfony/Component/Translation/Catalogue/DiffOperation.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Catalogue;

/**
 * Diff operation between two catalogues.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class DiffOperation extends AbstractOperation
{
    /**
     * {@inheritdoc}
     */
    protected function processDomain($domain)
    {
        $this->messages[$domain] = array(
            'all'      => array(),
            'new'      => array(),
            'obsolete' => array(),
        );

        foreach ($this->source->all($domain) as $id => $message) {
            if ($this->target->has($id, $domain)) {
                $this->messages[$domain]['all'][$id] = $message;
                $this->result->add(array($id => $message), $domain);
            } else {
                $this->messages[$domain]['obsolete'][$id] = $message;
            }
        }

        foreach ($this->target->all($domain) as $id => $message) {
            if (!$this->source->has($id, $domain)) {
                $this->messages[$domain]['all'][$id] = $message;
                $this->messages[$domain]['new'][$id] = $message;
                $this->result->add(array($id => $message), $domain);
            }
        }
    }
}
PKu�Z�6�"��>Symfony/Component/Translation/Exception/ExceptionInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Exception;

/**
 * Exception interface for all exceptions thrown by the component.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface ExceptionInterface
{
}
PKu�ZD���DSymfony/Component/Translation/Exception/InvalidResourceException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Exception;

/**
 * Thrown when a resource cannot be loaded.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class InvalidResourceException extends \InvalidArgumentException implements ExceptionInterface
{
}
PKv�Z�2B��ESymfony/Component/Translation/Exception/NotFoundResourceException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Exception;

/**
 * Thrown when a resource does not exist.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class NotFoundResourceException extends \InvalidArgumentException implements ExceptionInterface
{
}
PKv�Z�y4��2Symfony/Component/Translation/MessageCatalogue.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

use Symfony\Component\Config\Resource\ResourceInterface;

/**
 * MessageCatalogue.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class MessageCatalogue implements MessageCatalogueInterface, MetadataAwareInterface
{
    private $messages = array();
    private $metadata = array();
    private $resources = array();
    private $locale;
    private $fallbackCatalogue;
    private $parent;

    /**
     * Constructor.
     *
     * @param string $locale   The locale
     * @param array  $messages An array of messages classified by domain
     *
     * @api
     */
    public function __construct($locale, array $messages = array())
    {
        $this->locale = $locale;
        $this->messages = $messages;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function getLocale()
    {
        return $this->locale;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function getDomains()
    {
        return array_keys($this->messages);
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function all($domain = null)
    {
        if (null === $domain) {
            return $this->messages;
        }

        return isset($this->messages[$domain]) ? $this->messages[$domain] : array();
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function set($id, $translation, $domain = 'messages')
    {
        $this->add(array($id => $translation), $domain);
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function has($id, $domain = 'messages')
    {
        if (isset($this->messages[$domain][$id])) {
            return true;
        }

        if (null !== $this->fallbackCatalogue) {
            return $this->fallbackCatalogue->has($id, $domain);
        }

        return false;
    }

    /**
     * {@inheritdoc}
     */
    public function defines($id, $domain = 'messages')
    {
        return isset($this->messages[$domain][$id]);
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function get($id, $domain = 'messages')
    {
        if (isset($this->messages[$domain][$id])) {
            return $this->messages[$domain][$id];
        }

        if (null !== $this->fallbackCatalogue) {
            return $this->fallbackCatalogue->get($id, $domain);
        }

        return $id;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function replace($messages, $domain = 'messages')
    {
        $this->messages[$domain] = array();

        $this->add($messages, $domain);
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function add($messages, $domain = 'messages')
    {
        if (!isset($this->messages[$domain])) {
            $this->messages[$domain] = $messages;
        } else {
            $this->messages[$domain] = array_replace($this->messages[$domain], $messages);
        }
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function addCatalogue(MessageCatalogueInterface $catalogue)
    {
        if ($catalogue->getLocale() !== $this->locale) {
            throw new \LogicException(sprintf('Cannot add a catalogue for locale "%s" as the current locale for this catalogue is "%s"', $catalogue->getLocale(), $this->locale));
        }

        foreach ($catalogue->all() as $domain => $messages) {
            $this->add($messages, $domain);
        }

        foreach ($catalogue->getResources() as $resource) {
            $this->addResource($resource);
        }

        if ($catalogue instanceof MetadataAwareInterface) {
            $metadata = $catalogue->getMetadata('', '');
            $this->addMetadata($metadata);
        }
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function addFallbackCatalogue(MessageCatalogueInterface $catalogue)
    {
        // detect circular references
        $c = $this;
        do {
            if ($c->getLocale() === $catalogue->getLocale()) {
                throw new \LogicException(sprintf('Circular reference detected when adding a fallback catalogue for locale "%s".', $catalogue->getLocale()));
            }
        } while ($c = $c->parent);

        $catalogue->parent = $this;
        $this->fallbackCatalogue = $catalogue;

        foreach ($catalogue->getResources() as $resource) {
            $this->addResource($resource);
        }
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function getFallbackCatalogue()
    {
        return $this->fallbackCatalogue;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function getResources()
    {
        return array_values($this->resources);
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function addResource(ResourceInterface $resource)
    {
        $this->resources[$resource->__toString()] = $resource;
    }

    /**
     * {@inheritdoc}
     */
    public function getMetadata($key = '', $domain = 'messages')
    {
        if ('' == $domain) {
            return $this->metadata;
        }

        if (isset($this->metadata[$domain])) {
            if ('' == $key) {
                return $this->metadata[$domain];
            }

            if (isset($this->metadata[$domain][$key])) {
                return $this->metadata[$domain][$key];
            }
        }

        return null;
    }

    /**
     * {@inheritdoc}
     */
    public function setMetadata($key, $value, $domain = 'messages')
    {
        $this->metadata[$domain][$key] = $value;
    }

    /**
     * {@inheritdoc}
     */
    public function deleteMetadata($key = '', $domain = 'messages')
    {
        if ('' == $domain) {
            $this->metadata = array();
        } elseif ('' == $key) {
            unset($this->metadata[$domain]);
        } else {
            unset($this->metadata[$domain][$key]);
        }
    }

    /**
     * Adds current values with the new values.
     *
     * @param array $values Values to add
     */
    private function addMetadata(array $values)
    {
        foreach ($values as $domain => $keys) {
            foreach ($keys as $key => $value) {
                $this->setMetadata($key, $value, $domain);
            }
        }
    }
}
PKv�Z%�Mt8Symfony/Component/Translation/MetadataAwareInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

/**
 * MetadataAwareInterface.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface MetadataAwareInterface
{
    /**
     * Gets metadata for the given domain and key.
     *
     * Passing an empty domain will return an array with all metadata indexed by
     * domain and then by key. Passing an empty key will return an array with all
     * metadata for the given domain.
     *
     * @param string $domain The domain name
     * @param string $key    The key
     *
     * @return mixed The value that was set or an array with the domains/keys or null
     */
    public function getMetadata($key = '', $domain = 'messages');

    /**
     * Adds metadata to a message domain.
     *
     * @param string $key    The key
     * @param mixed  $value  The value
     * @param string $domain The domain name
     */
    public function setMetadata($key, $value, $domain = 'messages');

    /**
     * Deletes metadata for the given key and domain.
     *
     * Passing an empty domain will delete all metadata. Passing an empty key will
     * delete all metadata for the given domain.
     *
     * @param string $domain The domain name
     * @param string $key    The key
     */
    public function deleteMetadata($key = '', $domain = 'messages');
}
PKv�Z�d�<<4Symfony/Component/Translation/IdentityTranslator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

/**
 * IdentityTranslator does not translate anything.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class IdentityTranslator implements TranslatorInterface
{
    private $selector;
    private $locale;

    /**
     * Constructor.
     *
     * @param MessageSelector|null $selector The message selector for pluralization
     *
     * @api
     */
    public function __construct(MessageSelector $selector = null)
    {
        $this->selector = $selector ?: new MessageSelector();
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function setLocale($locale)
    {
        $this->locale = $locale;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function getLocale()
    {
        return $this->locale ?: \Locale::getDefault();
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function trans($id, array $parameters = array(), $domain = null, $locale = null)
    {
        return strtr((string) $id, $parameters);
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
    {
        return strtr($this->selector->choose((string) $id, (int) $number, $locale ?: $this->getLocale()), $parameters);
    }
}
PKv�Z�e�G��,Symfony/Component/Translation/Translator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

use Symfony\Component\Translation\Loader\LoaderInterface;
use Symfony\Component\Translation\Exception\NotFoundResourceException;

/**
 * Translator.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class Translator implements TranslatorInterface
{
    /**
     * @var MessageCatalogueInterface[]
     */
    protected $catalogues = array();

    /**
     * @var string
     */
    protected $locale;

    /**
     * @var array
     */
    private $fallbackLocales = array();

    /**
     * @var LoaderInterface[]
     */
    private $loaders = array();

    /**
     * @var array
     */
    private $resources = array();

    /**
     * @var MessageSelector
     */
    private $selector;

    /**
     * Constructor.
     *
     * @param string               $locale   The locale
     * @param MessageSelector|null $selector The message selector for pluralization
     *
     * @api
     */
    public function __construct($locale, MessageSelector $selector = null)
    {
        $this->locale = $locale;
        $this->selector = $selector ?: new MessageSelector();
    }

    /**
     * Adds a Loader.
     *
     * @param string          $format The name of the loader (@see addResource())
     * @param LoaderInterface $loader A LoaderInterface instance
     *
     * @api
     */
    public function addLoader($format, LoaderInterface $loader)
    {
        $this->loaders[$format] = $loader;
    }

    /**
     * Adds a Resource.
     *
     * @param string $format   The name of the loader (@see addLoader())
     * @param mixed  $resource The resource name
     * @param string $locale   The locale
     * @param string $domain   The domain
     *
     * @api
     */
    public function addResource($format, $resource, $locale, $domain = null)
    {
        if (null === $domain) {
            $domain = 'messages';
        }

        $this->resources[$locale][] = array($format, $resource, $domain);

        if (in_array($locale, $this->fallbackLocales)) {
            $this->catalogues = array();
        } else {
            unset($this->catalogues[$locale]);
        }
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function setLocale($locale)
    {
        $this->locale = $locale;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function getLocale()
    {
        return $this->locale;
    }

    /**
     * Sets the fallback locale(s).
     *
     * @param string|array $locales The fallback locale(s)
     *
     * @deprecated since 2.3, to be removed in 3.0. Use setFallbackLocales() instead.
     *
     * @api
     */
    public function setFallbackLocale($locales)
    {
        $this->setFallbackLocales(is_array($locales) ? $locales : array($locales));
    }

    /**
     * Sets the fallback locales.
     *
     * @param array $locales The fallback locales
     *
     * @api
     */
    public function setFallbackLocales(array $locales)
    {
        // needed as the fallback locales are linked to the already loaded catalogues
        $this->catalogues = array();

        $this->fallbackLocales = $locales;
    }

    /**
     * Gets the fallback locales.
     *
     * @return array $locales The fallback locales
     *
     * @api
     */
    public function getFallbackLocales()
    {
        return $this->fallbackLocales;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function trans($id, array $parameters = array(), $domain = null, $locale = null)
    {
        if (null === $locale) {
            $locale = $this->getLocale();
        }

        if (null === $domain) {
            $domain = 'messages';
        }

        if (!isset($this->catalogues[$locale])) {
            $this->loadCatalogue($locale);
        }

        return strtr($this->catalogues[$locale]->get((string) $id, $domain), $parameters);
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
    {
        if (null === $locale) {
            $locale = $this->getLocale();
        }

        if (null === $domain) {
            $domain = 'messages';
        }

        if (!isset($this->catalogues[$locale])) {
            $this->loadCatalogue($locale);
        }

        $id = (string) $id;

        $catalogue = $this->catalogues[$locale];
        while (!$catalogue->defines($id, $domain)) {
            if ($cat = $catalogue->getFallbackCatalogue()) {
                $catalogue = $cat;
                $locale = $catalogue->getLocale();
            } else {
                break;
            }
        }

        return strtr($this->selector->choose($catalogue->get($id, $domain), (int) $number, $locale), $parameters);
    }

    /**
     * Gets the loaders.
     *
     * @return array LoaderInterface[]
     */
    protected function getLoaders()
    {
        return $this->loaders;
    }

    protected function loadCatalogue($locale)
    {
        try {
            $this->doLoadCatalogue($locale);
        } catch (NotFoundResourceException $e) {
            if (!$this->computeFallbackLocales($locale)) {
                throw $e;
            }
        }
        $this->loadFallbackCatalogues($locale);
    }

    private function doLoadCatalogue($locale)
    {
        $this->catalogues[$locale] = new MessageCatalogue($locale);

        if (isset($this->resources[$locale])) {
            foreach ($this->resources[$locale] as $resource) {
                if (!isset($this->loaders[$resource[0]])) {
                    throw new \RuntimeException(sprintf('The "%s" translation loader is not registered.', $resource[0]));
                }
                $this->catalogues[$locale]->addCatalogue($this->loaders[$resource[0]]->load($resource[1], $locale, $resource[2]));
            }
        }
    }

    private function loadFallbackCatalogues($locale)
    {
        $current = $this->catalogues[$locale];

        foreach ($this->computeFallbackLocales($locale) as $fallback) {
            if (!isset($this->catalogues[$fallback])) {
                $this->doLoadCatalogue($fallback);
            }

            $current->addFallbackCatalogue($this->catalogues[$fallback]);
            $current = $this->catalogues[$fallback];
        }
    }

    protected function computeFallbackLocales($locale)
    {
        $locales = array();
        foreach ($this->fallbackLocales as $fallback) {
            if ($fallback === $locale) {
                continue;
            }

            $locales[] = $fallback;
        }

        if (strrchr($locale, '_') !== false) {
            array_unshift($locales, substr($locale, 0, -strlen(strrchr($locale, '_'))));
        }

        return array_unique($locales);
    }
}
PKv�Z��֛�;Symfony/Component/Translation/MessageCatalogueInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

use Symfony\Component\Config\Resource\ResourceInterface;

/**
 * MessageCatalogueInterface.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface MessageCatalogueInterface
{
    /**
     * Gets the catalogue locale.
     *
     * @return string The locale
     *
     * @api
     */
    public function getLocale();

    /**
     * Gets the domains.
     *
     * @return array An array of domains
     *
     * @api
     */
    public function getDomains();

    /**
     * Gets the messages within a given domain.
     *
     * If $domain is null, it returns all messages.
     *
     * @param string $domain The domain name
     *
     * @return array An array of messages
     *
     * @api
     */
    public function all($domain = null);

    /**
     * Sets a message translation.
     *
     * @param string $id          The message id
     * @param string $translation The messages translation
     * @param string $domain      The domain name
     *
     * @api
     */
    public function set($id, $translation, $domain = 'messages');

    /**
     * Checks if a message has a translation.
     *
     * @param string $id     The message id
     * @param string $domain The domain name
     *
     * @return Boolean true if the message has a translation, false otherwise
     *
     * @api
     */
    public function has($id, $domain = 'messages');

    /**
     * Checks if a message has a translation (it does not take into account the fallback mechanism).
     *
     * @param string $id     The message id
     * @param string $domain The domain name
     *
     * @return Boolean true if the message has a translation, false otherwise
     *
     * @api
     */
    public function defines($id, $domain = 'messages');

    /**
     * Gets a message translation.
     *
     * @param string $id     The message id
     * @param string $domain The domain name
     *
     * @return string The message translation
     *
     * @api
     */
    public function get($id, $domain = 'messages');

    /**
     * Sets translations for a given domain.
     *
     * @param array  $messages An array of translations
     * @param string $domain   The domain name
     *
     * @api
     */
    public function replace($messages, $domain = 'messages');

    /**
     * Adds translations for a given domain.
     *
     * @param array  $messages An array of translations
     * @param string $domain   The domain name
     *
     * @api
     */
    public function add($messages, $domain = 'messages');

    /**
     * Merges translations from the given Catalogue into the current one.
     *
     * The two catalogues must have the same locale.
     *
     * @param MessageCatalogueInterface $catalogue A MessageCatalogueInterface instance
     *
     * @api
     */
    public function addCatalogue(MessageCatalogueInterface $catalogue);

    /**
     * Merges translations from the given Catalogue into the current one
     * only when the translation does not exist.
     *
     * This is used to provide default translations when they do not exist for the current locale.
     *
     * @param MessageCatalogueInterface $catalogue A MessageCatalogueInterface instance
     *
     * @api
     */
    public function addFallbackCatalogue(MessageCatalogueInterface $catalogue);

    /**
     * Gets the fallback catalogue.
     *
     * @return MessageCatalogueInterface|null A MessageCatalogueInterface instance or null when no fallback has been set
     *
     * @api
     */
    public function getFallbackCatalogue();

    /**
     * Returns an array of resources loaded to build this collection.
     *
     * @return ResourceInterface[] An array of resources
     *
     * @api
     */
    public function getResources();

    /**
     * Adds a resource for this collection.
     *
     * @param ResourceInterface $resource A resource instance
     *
     * @api
     */
    public function addResource(ResourceInterface $resource);
}
PKv�ZM�
���9Symfony/Component/Translation/Dumper/IcuResFileDumper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * IcuResDumper generates an ICU ResourceBundle formatted string representation of a message catalogue.
 *
 * @author Stealth35
 */
class IcuResFileDumper implements DumperInterface
{
    /**
     * {@inheritDoc}
     */
    public function dump(MessageCatalogue $messages, $options = array())
    {
        if (!array_key_exists('path', $options)) {
            throw new \InvalidArgumentException('The file dumper need a path options.');
        }

        // save a file for each domain
        foreach ($messages->getDomains() as $domain) {
            $file = $messages->getLocale().'.'.$this->getExtension();
            $path = $options['path'].'/'.$domain.'/';

            if (!file_exists($path)) {
                mkdir($path);
            }

            // backup
            if (file_exists($path.$file)) {
                copy($path.$file, $path.$file.'~');
            }

            // save file
            file_put_contents($path.$file, $this->format($messages, $domain));
        }
    }

    /**
     * {@inheritDoc}
     */
    public function format(MessageCatalogue $messages, $domain = 'messages')
    {
        $data = $indexes = $resources = '';

        foreach ($messages->all($domain) as $source => $target) {
            $indexes .= pack('v', strlen($data) + 28);
            $data    .= $source."\0";
        }

        $data .= $this->writePadding($data);

        $keyTop = $this->getPosition($data);

        foreach ($messages->all($domain) as $source => $target) {
            $resources .= pack('V', $this->getPosition($data));

            $data .= pack('V', strlen($target))
                .mb_convert_encoding($target."\0", 'UTF-16LE', 'UTF-8')
                .$this->writePadding($data)
                  ;
        }

        $resOffset = $this->getPosition($data);

        $data .= pack('v', count($messages))
            .$indexes
            .$this->writePadding($data)
            .$resources
              ;

        $bundleTop = $this->getPosition($data);

        $root = pack('V7',
            $resOffset + (2 << 28), // Resource Offset + Resource Type
            6,                      // Index length
            $keyTop,                // Index keys top
            $bundleTop,             // Index resources top
            $bundleTop,             // Index bundle top
            count($messages),       // Index max table length
            0                       // Index attributes
        );

        $header = pack('vC2v4C12@32',
            32,                     // Header size
            0xDA, 0x27,             // Magic number 1 and 2
            20, 0, 0, 2,            // Rest of the header, ..., Size of a char
            0x52, 0x65, 0x73, 0x42, // Data format identifier
            1, 2, 0, 0,             // Data version
            1, 4, 0, 0              // Unicode version
        );

        $output = $header
               .$root
               .$data;

        return $output;
    }

    private function writePadding($data)
    {
        $padding = strlen($data) % 4;

        if ($padding) {
            return str_repeat("\xAA", 4 - $padding);
        }
    }

    private function getPosition($data)
    {
        $position = (strlen($data) + 28) / 4;

        return $position;
    }

    /**
     * {@inheritDoc}
     */
    protected function getExtension()
    {
        return 'res';
    }
}
PKv�Zਪ(5Symfony/Component/Translation/Dumper/PoFileDumper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * PoFileDumper generates a gettext formatted string representation of a message catalogue.
 *
 * @author Stealth35
 */
class PoFileDumper extends FileDumper
{
    /**
     * {@inheritDoc}
     */
    public function format(MessageCatalogue $messages, $domain = 'messages')
    {
        $output = 'msgid ""'."\n";
        $output .= 'msgstr ""'."\n";
        $output .= '"Content-Type: text/plain; charset=UTF-8\n"'."\n";
        $output .= '"Content-Transfer-Encoding: 8bit\n"'."\n";
        $output .= '"Language: '.$messages->getLocale().'\n"'."\n";
        $output .= "\n";

        $newLine = false;
        foreach ($messages->all($domain) as $source => $target) {
            if ($newLine) {
              $output .= "\n";
            } else {
              $newLine = true;
            }
            $output .= sprintf('msgid "%s"'."\n", $this->escape($source));
            $output .= sprintf('msgstr "%s"', $this->escape($target));
        }

        return $output;
    }

    /**
     * {@inheritDoc}
     */
    protected function getExtension()
    {
        return 'po';
    }

    private function escape($str)
    {
        return addcslashes($str, "\0..\37\42\134");
    }
}
PKv�Z���%LL6Symfony/Component/Translation/Dumper/PhpFileDumper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * PhpFileDumper generates PHP files from a message catalogue.
 *
 * @author Michel Salib <michelsalib@hotmail.com>
 */
class PhpFileDumper extends FileDumper
{
    /**
     * {@inheritDoc}
     */
    protected function format(MessageCatalogue $messages, $domain)
    {
        $output = "<?php\n\nreturn ".var_export($messages->all($domain), true).";\n";

        return $output;
    }

    /**
     * {@inheritDoc}
     */
    protected function getExtension()
    {
        return 'php';
    }
}
PKv�Z�<̧��8Symfony/Component/Translation/Dumper/XliffFileDumper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * XliffFileDumper generates xliff files from a message catalogue.
 *
 * @author Michel Salib <michelsalib@hotmail.com>
 */
class XliffFileDumper extends FileDumper
{
    /**
     * {@inheritDoc}
     */
    protected function format(MessageCatalogue $messages, $domain)
    {
        $dom = new \DOMDocument('1.0', 'utf-8');
        $dom->formatOutput = true;

        $xliff = $dom->appendChild($dom->createElement('xliff'));
        $xliff->setAttribute('version', '1.2');
        $xliff->setAttribute('xmlns', 'urn:oasis:names:tc:xliff:document:1.2');

        $xliffFile = $xliff->appendChild($dom->createElement('file'));
        $xliffFile->setAttribute('source-language', $messages->getLocale());
        $xliffFile->setAttribute('datatype', 'plaintext');
        $xliffFile->setAttribute('original', 'file.ext');

        $xliffBody = $xliffFile->appendChild($dom->createElement('body'));
        foreach ($messages->all($domain) as $source => $target) {
            $translation = $dom->createElement('trans-unit');

            $translation->setAttribute('id', md5($source));
            $translation->setAttribute('resname', $source);

            $s = $translation->appendChild($dom->createElement('source'));
            $s->appendChild($dom->createTextNode($source));

            $t = $translation->appendChild($dom->createElement('target'));
            $t->appendChild($dom->createTextNode($target));

            $xliffBody->appendChild($translation);
        }

        return $dom->saveXML();
    }

    /**
     * {@inheritDoc}
     */
    protected function getExtension()
    {
        return 'xlf';
    }
}
PKv�Z>{GG5Symfony/Component/Translation/Dumper/QtFileDumper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * QtFileDumper generates ts files from a message catalogue.
 *
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 */
class QtFileDumper extends FileDumper
{
    /**
     * {@inheritDoc}
     */
    public function format(MessageCatalogue $messages, $domain)
    {
        $dom = new \DOMDocument('1.0', 'utf-8');
        $dom->formatOutput = true;
        $ts = $dom->appendChild($dom->createElement('TS'));
        $context = $ts->appendChild($dom->createElement('context'));
        $context->appendChild($dom->createElement('name', $domain));

        foreach ($messages->all($domain) as $source => $target) {
            $message = $context->appendChild($dom->createElement('message'));
            $message->appendChild($dom->createElement('source', $source));
            $message->appendChild($dom->createElement('translation', $target));
        }

        return $dom->saveXML();
    }

    /**
     * {@inheritDoc}
     */
    protected function getExtension()
    {
        return 'ts';
    }
}
PKv�Z���667Symfony/Component/Translation/Dumper/YamlFileDumper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Yaml\Yaml;

/**
 * YamlFileDumper generates yaml files from a message catalogue.
 *
 * @author Michel Salib <michelsalib@hotmail.com>
 */
class YamlFileDumper extends FileDumper
{
    /**
     * {@inheritDoc}
     */
    protected function format(MessageCatalogue $messages, $domain)
    {
         return Yaml::dump($messages->all($domain));
    }

    /**
     * {@inheritDoc}
     */
    protected function getExtension()
    {
        return 'yml';
    }
}
PKv�ZoB���6Symfony/Component/Translation/Dumper/CsvFileDumper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * CsvFileDumper generates a csv formatted string representation of a message catalogue.
 *
 * @author Stealth35
 */
class CsvFileDumper extends FileDumper
{
    private $delimiter = ';';
    private $enclosure = '"';

    /**
     * {@inheritDoc}
     */
    public function format(MessageCatalogue $messages, $domain = 'messages')
    {
        $handle = fopen('php://memory', 'rb+');

        foreach ($messages->all($domain) as $source => $target) {
            fputcsv($handle, array($source, $target), $this->delimiter, $this->enclosure);
        }

        rewind($handle);
        $output = stream_get_contents($handle);
        fclose($handle);

        return $output;
    }

    /**
     * Sets the delimiter and escape character for CSV.
     *
     * @param string $delimiter delimiter character
     * @param string $enclosure enclosure character
     */
    public function setCsvControl($delimiter = ';', $enclosure = '"')
    {
        $this->delimiter = $delimiter;
        $this->enclosure = $enclosure;
    }

    /**
     * {@inheritDoc}
     */
    protected function getExtension()
    {
        return 'csv';
    }
}
PKv�ZB^�[[3Symfony/Component/Translation/Dumper/FileDumper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * FileDumper is an implementation of DumperInterface that dump a message catalogue to file(s).
 * Performs backup of already existing files.
 *
 * Options:
 * - path (mandatory): the directory where the files should be saved
 *
 * @author Michel Salib <michelsalib@hotmail.com>
 */
abstract class FileDumper implements DumperInterface
{
    /**
     * {@inheritDoc}
     */
    public function dump(MessageCatalogue $messages, $options = array())
    {
        if (!array_key_exists('path', $options)) {
            throw new \InvalidArgumentException('The file dumper needs a path option.');
        }

        // save a file for each domain
        foreach ($messages->getDomains() as $domain) {
            $file = $domain.'.'.$messages->getLocale().'.'.$this->getExtension();
            // backup
            $fullpath = $options['path'].'/'.$file;
            if (file_exists($fullpath)) {
                copy($fullpath, $fullpath.'~');
            }
            // save file
            file_put_contents($fullpath, $this->format($messages, $domain));
        }
    }

    /**
     * Transforms a domain of a message catalogue to its string representation.
     *
     * @param MessageCatalogue $messages
     * @param string           $domain
     *
     * @return string representation
     */
    abstract protected function format(MessageCatalogue $messages, $domain);

    /**
     * Gets the file extension of the dumper.
     *
     * @return string file extension
     */
    abstract protected function getExtension();
}
PKv�Z�:$}}7Symfony/Component/Translation/Dumper/JsonFileDumper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;

if (!defined('JSON_PRETTY_PRINT')) {
    define('JSON_PRETTY_PRINT', 128);
}

/**
 * JsonFileDumper generates an json formatted string representation of a message catalogue.
 *
 * @author singles
 */
class JsonFileDumper extends FileDumper
{
    /**
     * {@inheritDoc}
     */
    public function format(MessageCatalogue $messages, $domain = 'messages')
    {
        return json_encode($messages->all($domain), JSON_PRETTY_PRINT);
    }

    /**
     * {@inheritDoc}
     */
    protected function getExtension()
    {
        return 'json';
    }
}
PKv�Z&X����6Symfony/Component/Translation/Dumper/IniFileDumper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * IniFileDumper generates an ini formatted string representation of a message catalogue.
 *
 * @author Stealth35
 */
class IniFileDumper extends FileDumper
{
    /**
     * {@inheritDoc}
     */
    public function format(MessageCatalogue $messages, $domain = 'messages')
    {
        $output = '';

        foreach ($messages->all($domain) as $source => $target) {
            $escapeTarget = str_replace('"', '\"', $target);
            $output .= $source.'="'.$escapeTarget."\"\n";
        }

        return $output;
    }

    /**
     * {@inheritDoc}
     */
    protected function getExtension()
    {
        return 'ini';
    }
}
PKv�Z��<**8Symfony/Component/Translation/Dumper/DumperInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * DumperInterface is the interface implemented by all translation dumpers.
 * There is no common option.
 *
 * @author Michel Salib <michelsalib@hotmail.com>
 */
interface DumperInterface
{
    /**
     * Dumps the message catalogue.
     *
     * @param MessageCatalogue $messages The message catalogue
     * @param array            $options  Options that are used by the dumper
     */
    public function dump(MessageCatalogue $messages, $options = array());
}
PKv�Z����A	A	5Symfony/Component/Translation/Dumper/MoFileDumper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Loader\MoFileLoader;

/**
 * MoFileDumper generates a gettext formatted string representation of a message catalogue.
 *
 * @author Stealth35
 */
class MoFileDumper extends FileDumper
{
    /**
     * {@inheritDoc}
     */
    public function format(MessageCatalogue $messages, $domain = 'messages')
    {
        $output = $sources = $targets = $sourceOffsets = $targetOffsets = '';
        $offsets = array();
        $size = 0;

        foreach ($messages->all($domain) as $source => $target) {
            $offsets[] = array_map('strlen', array($sources, $source, $targets, $target));
            $sources .= "\0".$source;
            $targets .= "\0".$target;
            ++$size;
        }

        $header = array(
            'magicNumber'      => MoFileLoader::MO_LITTLE_ENDIAN_MAGIC,
            'formatRevision'   => 0,
            'count'            => $size,
            'offsetId'         => MoFileLoader::MO_HEADER_SIZE,
            'offsetTranslated' => MoFileLoader::MO_HEADER_SIZE + (8 * $size),
            'sizeHashes'       => 0,
            'offsetHashes'     => MoFileLoader::MO_HEADER_SIZE + (16 * $size),
        );

        $sourcesSize  = strlen($sources);
        $sourcesStart = $header['offsetHashes'] + 1;

        foreach ($offsets as $offset) {
            $sourceOffsets .= $this->writeLong($offset[1])
                          .$this->writeLong($offset[0] + $sourcesStart);
            $targetOffsets .= $this->writeLong($offset[3])
                          .$this->writeLong($offset[2] + $sourcesStart + $sourcesSize);
        }

        $output = implode(array_map(array($this, 'writeLong'), $header))
               .$sourceOffsets
               .$targetOffsets
               .$sources
               .$targets
                ;

        return $output;
    }

    /**
     * {@inheritDoc}
     */
    protected function getExtension()
    {
        return 'mo';
    }

    private function writeLong($str)
    {
        return pack('V*', $str);
    }
}
PKv�Zg�?Z�
�
*Symfony/Component/Translation/Interval.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

/**
 * Tests if a given number belongs to a given math interval.
 *
 * An interval can represent a finite set of numbers:
 *
 *  {1,2,3,4}
 *
 * An interval can represent numbers between two numbers:
 *
 *  [1, +Inf]
 *  ]-1,2[
 *
 * The left delimiter can be [ (inclusive) or ] (exclusive).
 * The right delimiter can be [ (exclusive) or ] (inclusive).
 * Beside numbers, you can use -Inf and +Inf for the infinite.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @see    http://en.wikipedia.org/wiki/Interval_%28mathematics%29#The_ISO_notation
 */
class Interval
{
    /**
     * Tests if the given number is in the math interval.
     *
     * @param integer $number   A number
     * @param string  $interval An interval
     *
     * @return Boolean
     *
     * @throws \InvalidArgumentException
     */
    public static function test($number, $interval)
    {
        $interval = trim($interval);

        if (!preg_match('/^'.self::getIntervalRegexp().'$/x', $interval, $matches)) {
            throw new \InvalidArgumentException(sprintf('"%s" is not a valid interval.', $interval));
        }

        if ($matches[1]) {
            foreach (explode(',', $matches[2]) as $n) {
                if ($number == $n) {
                    return true;
                }
            }
        } else {
            $leftNumber = self::convertNumber($matches['left']);
            $rightNumber = self::convertNumber($matches['right']);

            return
                ('[' === $matches['left_delimiter'] ? $number >= $leftNumber : $number > $leftNumber)
                && (']' === $matches['right_delimiter'] ? $number <= $rightNumber : $number < $rightNumber)
            ;
        }

        return false;
    }

    /**
     * Returns a Regexp that matches valid intervals.
     *
     * @return string A Regexp (without the delimiters)
     */
    public static function getIntervalRegexp()
    {
        return <<<EOF
        ({\s*
            (\-?\d+(\.\d+)?[\s*,\s*\-?\d+(\.\d+)?]*)
        \s*})

            |

        (?P<left_delimiter>[\[\]])
            \s*
            (?P<left>-Inf|\-?\d+(\.\d+)?)
            \s*,\s*
            (?P<right>\+?Inf|\-?\d+(\.\d+)?)
            \s*
        (?P<right_delimiter>[\[\]])
EOF;
    }

    private static function convertNumber($number)
    {
        if ('-Inf' === $number) {
            return log(0);
        } elseif ('+Inf' === $number || 'Inf' === $number) {
            return -log(0);
        }

        return (float) $number;
    }
}
PKv�Z�3����5Symfony/Component/Translation/TranslatorInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

/**
 * TranslatorInterface.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface TranslatorInterface
{
    /**
     * Translates the given message.
     *
     * @param string      $id         The message id (may also be an object that can be cast to string)
     * @param array       $parameters An array of parameters for the message
     * @param string|null $domain     The domain for the message or null to use the default
     * @param string|null $locale     The locale or null to use the default
     *
     * @return string The translated string
     *
     * @api
     */
    public function trans($id, array $parameters = array(), $domain = null, $locale = null);

    /**
     * Translates the given choice message by choosing a translation according to a number.
     *
     * @param string      $id         The message id (may also be an object that can be cast to string)
     * @param integer     $number     The number to use to find the indice of the message
     * @param array       $parameters An array of parameters for the message
     * @param string|null $domain     The domain for the message or null to use the default
     * @param string|null $locale     The locale or null to use the default
     *
     * @return string The translated string
     *
     * @api
     */
    public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null);

    /**
     * Sets the current locale.
     *
     * @param string $locale The locale
     *
     * @api
     */
    public function setLocale($locale);

    /**
     * Returns the current locale.
     *
     * @return string The locale
     *
     * @api
     */
    public function getLocale();
}
PKv�ZP�?�}}:Symfony/Component/Translation/Writer/TranslationWriter.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Writer;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Dumper\DumperInterface;

/**
 * TranslationWriter writes translation messages.
 *
 * @author Michel Salib <michelsalib@hotmail.com>
 */
class TranslationWriter
{
    /**
     * Dumpers used for export.
     *
     * @var array
     */
    private $dumpers = array();

    /**
     * Adds a dumper to the writer.
     *
     * @param string          $format The format of the dumper
     * @param DumperInterface $dumper The dumper
     */
    public function addDumper($format, DumperInterface $dumper)
    {
        $this->dumpers[$format] = $dumper;
    }

    /**
     * Obtains the list of supported formats.
     *
     * @return array
     */
    public function getFormats()
    {
        return array_keys($this->dumpers);
    }

    /**
     * Writes translation from the catalogue according to the selected format.
     *
     * @param MessageCatalogue $catalogue The message catalogue to dump
     * @param string           $format    The format to use to dump the messages
     * @param array            $options   Options that are passed to the dumper
     *
     * @throws \InvalidArgumentException
     */
    public function writeTranslations(MessageCatalogue $catalogue, $format, $options = array())
    {
        if (!isset($this->dumpers[$format])) {
            throw new \InvalidArgumentException(sprintf('There is no dumper associated with format "%s".', $format));
        }

        // get the right dumper
        $dumper = $this->dumpers[$format];

        // save
        $dumper->dump($catalogue, $options);
    }
}
PKv�ZN@���6Symfony/Component/Translation/Loader/IniFileLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Config\Resource\FileResource;

/**
 * IniFileLoader loads translations from an ini file.
 *
 * @author stealth35
 */
class IniFileLoader extends ArrayLoader implements LoaderInterface
{
    /**
     * {@inheritdoc}
     */
    public function load($resource, $locale, $domain = 'messages')
    {
        if (!stream_is_local($resource)) {
            throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
        }

        if (!file_exists($resource)) {
            throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
        }

        $messages = parse_ini_file($resource, true);

        $catalogue = parent::load($messages, $locale, $domain);
        $catalogue->addResource(new FileResource($resource));

        return $catalogue;
    }
}
PKv�Z�T�9Symfony/Component/Translation/Loader/IcuDatFileLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Config\Resource\FileResource;

/**
 * IcuResFileLoader loads translations from a resource bundle.
 *
 * @author stealth35
 */
class IcuDatFileLoader extends IcuResFileLoader
{
    /**
     * {@inheritdoc}
     */
    public function load($resource, $locale, $domain = 'messages')
    {
        if (!stream_is_local($resource.'.dat')) {
            throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
        }

        if (!file_exists($resource.'.dat')) {
            throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
        }

        $rb = new \ResourceBundle($locale, $resource);

        if (!$rb) {
            throw new InvalidResourceException(sprintf('Cannot load resource "%s"', $resource));
        } elseif (intl_is_failure($rb->getErrorCode())) {
            throw new InvalidResourceException($rb->getErrorMessage(), $rb->getErrorCode());
        }

        $messages = $this->flatten($rb);
        $catalogue = new MessageCatalogue($locale);
        $catalogue->add($messages, $domain);
        $catalogue->addResource(new FileResource($resource.'.dat'));

        return $catalogue;
    }
}
PKv�ZCS�z
z
9Symfony/Component/Translation/Loader/IcuResFileLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Config\Resource\DirectoryResource;

/**
 * IcuResFileLoader loads translations from a resource bundle.
 *
 * @author stealth35
 */
class IcuResFileLoader implements LoaderInterface
{
    /**
     * {@inheritdoc}
     */
    public function load($resource, $locale, $domain = 'messages')
    {
        if (!stream_is_local($resource)) {
            throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
        }

        if (!is_dir($resource)) {
            throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
        }

        $rb = new \ResourceBundle($locale, $resource);

        if (!$rb) {
            throw new InvalidResourceException(sprintf('Cannot load resource "%s"', $resource));
        } elseif (intl_is_failure($rb->getErrorCode())) {
            throw new InvalidResourceException($rb->getErrorMessage(), $rb->getErrorCode());
        }

        $messages = $this->flatten($rb);
        $catalogue = new MessageCatalogue($locale);
        $catalogue->add($messages, $domain);
        $catalogue->addResource(new DirectoryResource($resource));

        return $catalogue;
    }

    /**
     * Flattens an ResourceBundle
     *
     * The scheme used is:
     *   key { key2 { key3 { "value" } } }
     * Becomes:
     *   'key.key2.key3' => 'value'
     *
     * This function takes an array by reference and will modify it
     *
     * @param \ResourceBundle $rb       the ResourceBundle that will be flattened
     * @param array           $messages used internally for recursive calls
     * @param string          $path     current path being parsed, used internally for recursive calls
     *
     * @return array the flattened ResourceBundle
     */
    protected function flatten(\ResourceBundle $rb, array &$messages = array(), $path = null)
    {
        foreach ($rb as $key => $value) {
            $nodePath = $path ? $path.'.'.$key : $key;
            if ($value instanceof \ResourceBundle) {
                $this->flatten($value, $messages, $nodePath);
            } else {
                $messages[$nodePath] = $value;
            }
        }

        return $messages;
    }
}
PKv�Z��v���5Symfony/Component/Translation/Loader/MoFileLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Config\Resource\FileResource;

/**
 * @copyright Copyright (c) 2010, Union of RAD http://union-of-rad.org (http://lithify.me/)
 */
class MoFileLoader extends ArrayLoader implements LoaderInterface
{
    /**
     * Magic used for validating the format of a MO file as well as
     * detecting if the machine used to create that file was little endian.
     *
     * @var float
     */
    const MO_LITTLE_ENDIAN_MAGIC = 0x950412de;

    /**
     * Magic used for validating the format of a MO file as well as
     * detecting if the machine used to create that file was big endian.
     *
     * @var float
     */
    const MO_BIG_ENDIAN_MAGIC = 0xde120495;

    /**
     * The size of the header of a MO file in bytes.
     *
     * @var integer Number of bytes.
     */
    const MO_HEADER_SIZE = 28;

    public function load($resource, $locale, $domain = 'messages')
    {
        if (!stream_is_local($resource)) {
            throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
        }

        if (!file_exists($resource)) {
            throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
        }

        $messages = $this->parse($resource);

        // empty file
        if (null === $messages) {
            $messages = array();
        }

        // not an array
        if (!is_array($messages)) {
            throw new InvalidResourceException(sprintf('The file "%s" must contain a valid mo file.', $resource));
        }

        $catalogue = parent::load($messages, $locale, $domain);
        $catalogue->addResource(new FileResource($resource));

        return $catalogue;
    }

    /**
     * Parses machine object (MO) format, independent of the machine's endian it
     * was created on. Both 32bit and 64bit systems are supported.
     *
     * @param resource $resource
     *
     * @return array
     * @throws InvalidResourceException If stream content has an invalid format.
     */
    private function parse($resource)
    {
        $stream = fopen($resource, 'r');

        $stat = fstat($stream);

        if ($stat['size'] < self::MO_HEADER_SIZE) {
            throw new InvalidResourceException("MO stream content has an invalid format.");
        }
        $magic = unpack('V1', fread($stream, 4));
        $magic = hexdec(substr(dechex(current($magic)), -8));

        if ($magic == self::MO_LITTLE_ENDIAN_MAGIC) {
            $isBigEndian = false;
        } elseif ($magic == self::MO_BIG_ENDIAN_MAGIC) {
            $isBigEndian = true;
        } else {
            throw new InvalidResourceException("MO stream content has an invalid format.");
        }

        // formatRevision
        $this->readLong($stream, $isBigEndian);
        $count = $this->readLong($stream, $isBigEndian);
        $offsetId = $this->readLong($stream, $isBigEndian);
        $offsetTranslated = $this->readLong($stream, $isBigEndian);
        // sizeHashes
        $this->readLong($stream, $isBigEndian);
        // offsetHashes
        $this->readLong($stream, $isBigEndian);

        $messages = array();

        for ($i = 0; $i < $count; $i++) {
            $singularId = $pluralId = null;
            $translated = null;

            fseek($stream, $offsetId + $i * 8);

            $length = $this->readLong($stream, $isBigEndian);
            $offset = $this->readLong($stream, $isBigEndian);

            if ($length < 1) {
                continue;
            }

            fseek($stream, $offset);
            $singularId = fread($stream, $length);

            if (strpos($singularId, "\000") !== false) {
                list($singularId, $pluralId) = explode("\000", $singularId);
            }

            fseek($stream, $offsetTranslated + $i * 8);
            $length = $this->readLong($stream, $isBigEndian);
            $offset = $this->readLong($stream, $isBigEndian);

            fseek($stream, $offset);
            $translated = fread($stream, $length);

            if (strpos($translated, "\000") !== false) {
                $translated = explode("\000", $translated);
            }

            $ids = array('singular' => $singularId, 'plural' => $pluralId);
            $item = compact('ids', 'translated');

            if (is_array($item['translated'])) {
                $messages[$item['ids']['singular']] = stripcslashes($item['translated'][0]);
                if (isset($item['ids']['plural'])) {
                    $plurals = array();
                    foreach ($item['translated'] as $plural => $translated) {
                        $plurals[] = sprintf('{%d} %s', $plural, $translated);
                    }
                    $messages[$item['ids']['plural']] = stripcslashes(implode('|', $plurals));
                }
            } elseif (!empty($item['ids']['singular'])) {
                $messages[$item['ids']['singular']] = stripcslashes($item['translated']);
            }
        }

        fclose($stream);

        return array_filter($messages);
    }

    /**
     * Reads an unsigned long from stream respecting endianess.
     *
     * @param  resource $stream
     * @param  boolean  $isBigEndian
     * @return integer
     */
    private function readLong($stream, $isBigEndian)
    {
        $result = unpack($isBigEndian ? 'N1' : 'V1', fread($stream, 4));
        $result = current($result);

        return (integer) substr($result, -8);
    }
}
PKv�ZR����4Symfony/Component/Translation/Loader/ArrayLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * ArrayLoader loads translations from a PHP array.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class ArrayLoader implements LoaderInterface
{
    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function load($resource, $locale, $domain = 'messages')
    {
        $this->flatten($resource);
        $catalogue = new MessageCatalogue($locale);
        $catalogue->add($resource, $domain);

        return $catalogue;
    }

    /**
     * Flattens an nested array of translations
     *
     * The scheme used is:
     *   'key' => array('key2' => array('key3' => 'value'))
     * Becomes:
     *   'key.key2.key3' => 'value'
     *
     * This function takes an array by reference and will modify it
     *
     * @param array  &$messages The array that will be flattened
     * @param array  $subnode Current subnode being parsed, used internally for recursive calls
     * @param string $path    Current path being parsed, used internally for recursive calls
     */
    private function flatten(array &$messages, array $subnode = null, $path = null)
    {
        if (null === $subnode) {
            $subnode =& $messages;
        }
        foreach ($subnode as $key => $value) {
            if (is_array($value)) {
                $nodePath = $path ? $path.'.'.$key : $key;
                $this->flatten($messages, $value, $nodePath);
                if (null === $path) {
                    unset($messages[$key]);
                }
            } elseif (null !== $path) {
                $messages[$path.'.'.$key] = $value;
            }
        }
    }
}
PKv�Z�'s�u	u	7Symfony/Component/Translation/Loader/JsonFileLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Config\Resource\FileResource;

/**
 * JsonFileLoader loads translations from an json file.
 *
 * @author singles
 */
class JsonFileLoader extends ArrayLoader implements LoaderInterface
{
    /**
     * {@inheritdoc}
     */
    public function load($resource, $locale, $domain = 'messages')
    {
        if (!stream_is_local($resource)) {
            throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
        }

        if (!file_exists($resource)) {
            throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
        }

        $messages = json_decode(file_get_contents($resource), true);

        if (0 < $errorCode = json_last_error()) {
            throw new InvalidResourceException(sprintf('Error parsing JSON - %s', $this->getJSONErrorMessage($errorCode)));
        }

        if (null === $messages) {
            $messages = array();
        }

        $catalogue = parent::load($messages, $locale, $domain);
        $catalogue->addResource(new FileResource($resource));

        return $catalogue;
    }

    /**
     * Translates JSON_ERROR_* constant into meaningful message.
     *
     * @param  integer $errorCode Error code returned by json_last_error() call
     *
     * @return string  Message string
     */
    private function getJSONErrorMessage($errorCode)
    {
        switch ($errorCode) {
            case JSON_ERROR_DEPTH:
                return 'Maximum stack depth exceeded';
            case JSON_ERROR_STATE_MISMATCH:
                return 'Underflow or the modes mismatch';
            case JSON_ERROR_CTRL_CHAR:
                return 'Unexpected control character found';
            case JSON_ERROR_SYNTAX:
                return 'Syntax error, malformed JSON';
            case JSON_ERROR_UTF8:
                return 'Malformed UTF-8 characters, possibly incorrectly encoded';
            default:
                return 'Unknown error';
        }
    }
}
PKv�Z�i�3"
"
6Symfony/Component/Translation/Loader/CsvFileLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Config\Resource\FileResource;

/**
 * CsvFileLoader loads translations from CSV files.
 *
 * @author Saša Stamenković <umpirsky@gmail.com>
 *
 * @api
 */
class CsvFileLoader extends ArrayLoader implements LoaderInterface
{
    private $delimiter = ';';
    private $enclosure = '"';
    private $escape    = '\\';

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function load($resource, $locale, $domain = 'messages')
    {
        if (!stream_is_local($resource)) {
            throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
        }

        if (!file_exists($resource)) {
            throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
        }

        $messages = array();

        try {
            $file = new \SplFileObject($resource, 'rb');
        } catch (\RuntimeException $e) {
            throw new NotFoundResourceException(sprintf('Error opening file "%s".', $resource), 0, $e);
        }

        $file->setFlags(\SplFileObject::READ_CSV | \SplFileObject::SKIP_EMPTY);
        $file->setCsvControl($this->delimiter, $this->enclosure, $this->escape);

        foreach ($file as $data) {
            if (substr($data[0], 0, 1) === '#') {
                continue;
            }

            if (!isset($data[1])) {
                continue;
            }

            if (count($data) == 2) {
                $messages[$data[0]] = $data[1];
            } else {
                 continue;
            }
        }

        $catalogue = parent::load($messages, $locale, $domain);
        $catalogue->addResource(new FileResource($resource));

        return $catalogue;
    }

    /**
     * Sets the delimiter, enclosure, and escape character for CSV.
     *
     * @param string $delimiter delimiter character
     * @param string $enclosure enclosure character
     * @param string $escape    escape character
     */
    public function setCsvControl($delimiter = ';', $enclosure = '"', $escape = '\\')
    {
        $this->delimiter = $delimiter;
        $this->enclosure = $enclosure;
        $this->escape    = $escape;
    }
}
PKv�Z_��BB8Symfony/Component/Translation/Loader/XliffFileLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Config\Util\XmlUtils;
use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Config\Resource\FileResource;

/**
 * XliffFileLoader loads translations from XLIFF files.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class XliffFileLoader implements LoaderInterface
{
    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function load($resource, $locale, $domain = 'messages')
    {
        if (!stream_is_local($resource)) {
            throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
        }

        if (!file_exists($resource)) {
            throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
        }

        list($xml, $encoding) = $this->parseFile($resource);
        $xml->registerXPathNamespace('xliff', 'urn:oasis:names:tc:xliff:document:1.2');

        $catalogue = new MessageCatalogue($locale);
        foreach ($xml->xpath('//xliff:trans-unit') as $translation) {
            $attributes = $translation->attributes();

            if (!(isset($attributes['resname']) || isset($translation->source)) || !isset($translation->target)) {
                continue;
            }

            $source = isset($attributes['resname']) && $attributes['resname'] ? $attributes['resname'] : $translation->source;
            $target = (string) $translation->target;

            // If the xlf file has another encoding specified, try to convert it because
            // simple_xml will always return utf-8 encoded values
            if ('UTF-8' !== $encoding && !empty($encoding)) {
                if (function_exists('mb_convert_encoding')) {
                    $target = mb_convert_encoding($target, $encoding, 'UTF-8');
                } elseif (function_exists('iconv')) {
                    $target = iconv('UTF-8', $encoding, $target);
                } else {
                    throw new \RuntimeException('No suitable convert encoding function (use UTF-8 as your encoding or install the iconv or mbstring extension).');
                }
            }

            $catalogue->set((string) $source, $target, $domain);
        }
        $catalogue->addResource(new FileResource($resource));

        return $catalogue;
    }

    /**
     * Validates and parses the given file into a SimpleXMLElement
     *
     * @param string $file
     *
     * @throws \RuntimeException
     *
     * @return \SimpleXMLElement
     *
     * @throws InvalidResourceException
     */
    private function parseFile($file)
    {
        try {
            $dom = XmlUtils::loadFile($file);
        } catch (\InvalidArgumentException $e) {
            throw new InvalidResourceException(sprintf('Unable to load "%s": %s', $file, $e->getMessage()), $e->getCode(), $e);
        }

        $internalErrors = libxml_use_internal_errors(true);

        $location = str_replace('\\', '/', __DIR__).'/schema/dic/xliff-core/xml.xsd';
        $parts = explode('/', $location);
        if (0 === stripos($location, 'phar://')) {
            $tmpfile = tempnam(sys_get_temp_dir(), 'sf2');
            if ($tmpfile) {
                copy($location, $tmpfile);
                $parts = explode('/', str_replace('\\', '/', $tmpfile));
            }
        }
        $drive = '\\' === DIRECTORY_SEPARATOR ? array_shift($parts).'/' : '';
        $location = 'file:///'.$drive.implode('/', array_map('rawurlencode', $parts));

        $source = file_get_contents(__DIR__.'/schema/dic/xliff-core/xliff-core-1.2-strict.xsd');
        $source = str_replace('http://www.w3.org/2001/xml.xsd', $location, $source);

        if (!@$dom->schemaValidateSource($source)) {
            throw new InvalidResourceException(implode("\n", $this->getXmlErrors($internalErrors)));
        }

        $dom->normalizeDocument();

        libxml_use_internal_errors($internalErrors);

        return array(simplexml_import_dom($dom), strtoupper($dom->encoding));
    }

    /**
     * Returns the XML errors of the internal XML parser
     *
     * @param Boolean $internalErrors
     *
     * @return array An array of errors
     */
    private function getXmlErrors($internalErrors)
    {
        $errors = array();
        foreach (libxml_get_errors() as $error) {
            $errors[] = sprintf('[%s %s] %s (in %s - line %d, column %d)',
                LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR',
                $error->code,
                trim($error->message),
                $error->file ? $error->file : 'n/a',
                $error->line,
                $error->column
            );
        }

        libxml_clear_errors();
        libxml_use_internal_errors($internalErrors);

        return $errors;
    }
}
PKv�Zl#�tt8Symfony/Component/Translation/Loader/LoaderInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\NotFoundResourceException;

/**
 * LoaderInterface is the interface implemented by all translation loaders.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface LoaderInterface
{
    /**
     * Loads a locale.
     *
     * @param mixed  $resource A resource
     * @param string $locale   A locale
     * @param string $domain   The domain
     *
     * @return MessageCatalogue A MessageCatalogue instance
     *
     * @api
     *
     * @throws NotFoundResourceException when the resource cannot be found
     * @throws InvalidResourceException  when the resource cannot be loaded
     */
    public function load($resource, $locale, $domain = 'messages');
}
PKv�Z�*���5Symfony/Component/Translation/Loader/PoFileLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Config\Resource\FileResource;

/**
 * @copyright Copyright (c) 2010, Union of RAD http://union-of-rad.org (http://lithify.me/)
 * @copyright Copyright (c) 2012, Clemens Tolboom
 */
class PoFileLoader extends ArrayLoader implements LoaderInterface
{
    public function load($resource, $locale, $domain = 'messages')
    {
        if (!stream_is_local($resource)) {
            throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
        }

        if (!file_exists($resource)) {
            throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
        }

        $messages = $this->parse($resource);

        // empty file
        if (null === $messages) {
            $messages = array();
        }

        // not an array
        if (!is_array($messages)) {
            throw new InvalidResourceException(sprintf('The file "%s" must contain a valid po file.', $resource));
        }

        $catalogue = parent::load($messages, $locale, $domain);
        $catalogue->addResource(new FileResource($resource));

        return $catalogue;
    }

    /**
     * Parses portable object (PO) format.
     *
     * From http://www.gnu.org/software/gettext/manual/gettext.html#PO-Files
     * we should be able to parse files having:
     *
     * white-space
     * #  translator-comments
     * #. extracted-comments
     * #: reference...
     * #, flag...
     * #| msgid previous-untranslated-string
     * msgid untranslated-string
     * msgstr translated-string
     *
     * extra or different lines are:
     *
     * #| msgctxt previous-context
     * #| msgid previous-untranslated-string
     * msgctxt context
     *
     * #| msgid previous-untranslated-string-singular
     * #| msgid_plural previous-untranslated-string-plural
     * msgid untranslated-string-singular
     * msgid_plural untranslated-string-plural
     * msgstr[0] translated-string-case-0
     * ...
     * msgstr[N] translated-string-case-n
     *
     * The definition states:
     * - white-space and comments are optional.
     * - msgid "" that an empty singleline defines a header.
     *
     * This parser sacrifices some features of the reference implementation the
     * differences to that implementation are as follows.
     * - No support for comments spanning multiple lines.
     * - Translator and extracted comments are treated as being the same type.
     * - Message IDs are allowed to have other encodings as just US-ASCII.
     *
     * Items with an empty id are ignored.
     *
     * @param resource $resource
     *
     * @return array
     */
    private function parse($resource)
    {
        $stream = fopen($resource, 'r');

        $defaults = array(
            'ids' => array(),
            'translated' => null,
        );

        $messages = array();
        $item = $defaults;

        while ($line = fgets($stream)) {
            $line = trim($line);

            if ($line === '') {
                // Whitespace indicated current item is done
                $this->addMessage($messages, $item);
                $item = $defaults;
            } elseif (substr($line, 0, 7) === 'msgid "') {
                // We start a new msg so save previous
                // TODO: this fails when comments or contexts are added
                $this->addMessage($messages, $item);
                $item = $defaults;
                $item['ids']['singular'] = substr($line, 7, -1);
            } elseif (substr($line, 0, 8) === 'msgstr "') {
                $item['translated'] = substr($line, 8, -1);
            } elseif ($line[0] === '"') {
                $continues = isset($item['translated']) ? 'translated' : 'ids';

                if (is_array($item[$continues])) {
                    end($item[$continues]);
                    $item[$continues][key($item[$continues])] .= substr($line, 1, -1);
                } else {
                    $item[$continues] .= substr($line, 1, -1);
                }
            } elseif (substr($line, 0, 14) === 'msgid_plural "') {
                $item['ids']['plural'] = substr($line, 14, -1);
            } elseif (substr($line, 0, 7) === 'msgstr[') {
                $size = strpos($line, ']');
                $item['translated'][(integer) substr($line, 7, 1)] = substr($line, $size + 3, -1);
            }

        }
        // save last item
        $this->addMessage($messages, $item);
        fclose($stream);

        return $messages;
    }

    /**
     * Save a translation item to the messages.
     *
     * A .po file could contain by error missing plural indexes. We need to
     * fix these before saving them.
     *
     * @param array $messages
     * @param array $item
     */
    private function addMessage(array &$messages, array $item)
    {
        if (is_array($item['translated'])) {
            $messages[$item['ids']['singular']] = stripslashes($item['translated'][0]);
            if (isset($item['ids']['plural'])) {
                $plurals = $item['translated'];
                // PO are by definition indexed so sort by index.
                ksort($plurals);
                // Make sure every index is filled.
                end($plurals);
                $count = key($plurals);
                // Fill missing spots with '-'.
                $empties = array_fill(0, $count+1, '-');
                $plurals += $empties;
                ksort($plurals);
                $messages[$item['ids']['plural']] = stripcslashes(implode('|', $plurals));
            }
        } elseif (!empty($item['ids']['singular'])) {
              $messages[$item['ids']['singular']] = stripslashes($item['translated']);
        }
    }
}
PKv�Z�r��;;6Symfony/Component/Translation/Loader/PhpFileLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Config\Resource\FileResource;

/**
 * PhpFileLoader loads translations from PHP files returning an array of translations.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class PhpFileLoader extends ArrayLoader implements LoaderInterface
{
    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function load($resource, $locale, $domain = 'messages')
    {
        if (!stream_is_local($resource)) {
            throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
        }

        if (!file_exists($resource)) {
            throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
        }

        $messages = require($resource);

        $catalogue = parent::load($messages, $locale, $domain);
        $catalogue->addResource(new FileResource($resource));

        return $catalogue;
    }
}
PKv�Z:�	Z�"�"BSymfony/Component/Translation/Loader/schema/dic/xliff-core/xml.xsdnu�[���<?xml version='1.0'?>
<?xml-stylesheet href="../2008/09/xsd.xsl" type="text/xsl"?>
<xs:schema targetNamespace="http://www.w3.org/XML/1998/namespace" 
  xmlns:xs="http://www.w3.org/2001/XMLSchema" 
  xmlns   ="http://www.w3.org/1999/xhtml"
  xml:lang="en">

 <xs:annotation>
  <xs:documentation>
   <div>
    <h1>About the XML namespace</h1>

    <div class="bodytext">
     <p>

      This schema document describes the XML namespace, in a form
      suitable for import by other schema documents.
     </p>
     <p>
      See <a href="http://www.w3.org/XML/1998/namespace.html">
      http://www.w3.org/XML/1998/namespace.html</a> and
      <a href="http://www.w3.org/TR/REC-xml">
      http://www.w3.org/TR/REC-xml</a> for information 
      about this namespace.
     </p>

     <p>
      Note that local names in this namespace are intended to be
      defined only by the World Wide Web Consortium or its subgroups.
      The names currently defined in this namespace are listed below.
      They should not be used with conflicting semantics by any Working
      Group, specification, or document instance.
     </p>
     <p>   
      See further below in this document for more information about <a
      href="#usage">how to refer to this schema document from your own
      XSD schema documents</a> and about <a href="#nsversioning">the
      namespace-versioning policy governing this schema document</a>.
     </p>
    </div>
   </div>

  </xs:documentation>
 </xs:annotation>

 <xs:attribute name="lang">
  <xs:annotation>
   <xs:documentation>
    <div>
     
      <h3>lang (as an attribute name)</h3>
      <p>

       denotes an attribute whose value
       is a language code for the natural language of the content of
       any element; its value is inherited.  This name is reserved
       by virtue of its definition in the XML specification.</p>
     
    </div>
    <div>
     <h4>Notes</h4>
     <p>
      Attempting to install the relevant ISO 2- and 3-letter
      codes as the enumerated possible values is probably never
      going to be a realistic possibility.  
     </p>
     <p>

      See BCP 47 at <a href="http://www.rfc-editor.org/rfc/bcp/bcp47.txt">
       http://www.rfc-editor.org/rfc/bcp/bcp47.txt</a>
      and the IANA language subtag registry at
      <a href="http://www.iana.org/assignments/language-subtag-registry">
       http://www.iana.org/assignments/language-subtag-registry</a>
      for further information.
     </p>
     <p>

      The union allows for the 'un-declaration' of xml:lang with
      the empty string.
     </p>
    </div>
   </xs:documentation>
  </xs:annotation>
  <xs:simpleType>
   <xs:union memberTypes="xs:language">
    <xs:simpleType>    
     <xs:restriction base="xs:string">
      <xs:enumeration value=""/>

     </xs:restriction>
    </xs:simpleType>
   </xs:union>
  </xs:simpleType>
 </xs:attribute>

 <xs:attribute name="space">
  <xs:annotation>
   <xs:documentation>

    <div>
     
      <h3>space (as an attribute name)</h3>
      <p>
       denotes an attribute whose
       value is a keyword indicating what whitespace processing
       discipline is intended for the content of the element; its
       value is inherited.  This name is reserved by virtue of its
       definition in the XML specification.</p>
     
    </div>
   </xs:documentation>
  </xs:annotation>
  <xs:simpleType>

   <xs:restriction base="xs:NCName">
    <xs:enumeration value="default"/>
    <xs:enumeration value="preserve"/>
   </xs:restriction>
  </xs:simpleType>
 </xs:attribute>
 
 <xs:attribute name="base" type="xs:anyURI"> <xs:annotation>
   <xs:documentation>

    <div>
     
      <h3>base (as an attribute name)</h3>
      <p>
       denotes an attribute whose value
       provides a URI to be used as the base for interpreting any
       relative URIs in the scope of the element on which it
       appears; its value is inherited.  This name is reserved
       by virtue of its definition in the XML Base specification.</p>
     
     <p>
      See <a
      href="http://www.w3.org/TR/xmlbase/">http://www.w3.org/TR/xmlbase/</a>
      for information about this attribute.
     </p>

    </div>
   </xs:documentation>
  </xs:annotation>
 </xs:attribute>
 
 <xs:attribute name="id" type="xs:ID">
  <xs:annotation>
   <xs:documentation>
    <div>
     
      <h3>id (as an attribute name)</h3> 
      <p>

       denotes an attribute whose value
       should be interpreted as if declared to be of type ID.
       This name is reserved by virtue of its definition in the
       xml:id specification.</p>
     
     <p>
      See <a
      href="http://www.w3.org/TR/xml-id/">http://www.w3.org/TR/xml-id/</a>
      for information about this attribute.
     </p>
    </div>
   </xs:documentation>
  </xs:annotation>

 </xs:attribute>

 <xs:attributeGroup name="specialAttrs">
  <xs:attribute ref="xml:base"/>
  <xs:attribute ref="xml:lang"/>
  <xs:attribute ref="xml:space"/>
  <xs:attribute ref="xml:id"/>
 </xs:attributeGroup>

 <xs:annotation>

  <xs:documentation>
   <div>
   
    <h3>Father (in any context at all)</h3> 

    <div class="bodytext">
     <p>
      denotes Jon Bosak, the chair of 
      the original XML Working Group.  This name is reserved by 
      the following decision of the W3C XML Plenary and 
      XML Coordination groups:
     </p>
     <blockquote>
       <p>

	In appreciation for his vision, leadership and
	dedication the W3C XML Plenary on this 10th day of
	February, 2000, reserves for Jon Bosak in perpetuity
	the XML name "xml:Father".
       </p>
     </blockquote>
    </div>
   </div>
  </xs:documentation>
 </xs:annotation>

 <xs:annotation>
  <xs:documentation>

   <div xml:id="usage" id="usage">
    <h2><a name="usage">About this schema document</a></h2>

    <div class="bodytext">
     <p>
      This schema defines attributes and an attribute group suitable
      for use by schemas wishing to allow <code>xml:base</code>,
      <code>xml:lang</code>, <code>xml:space</code> or
      <code>xml:id</code> attributes on elements they define.
     </p>

     <p>
      To enable this, such a schema must import this schema for
      the XML namespace, e.g. as follows:
     </p>
     <pre>
          &lt;schema.. .>
          .. .
           &lt;import namespace="http://www.w3.org/XML/1998/namespace"
                      schemaLocation="http://www.w3.org/2001/xml.xsd"/>
     </pre>
     <p>
      or
     </p>
     <pre>

           &lt;import namespace="http://www.w3.org/XML/1998/namespace"
                      schemaLocation="http://www.w3.org/2009/01/xml.xsd"/>
     </pre>
     <p>
      Subsequently, qualified reference to any of the attributes or the
      group defined below will have the desired effect, e.g.
     </p>
     <pre>
          &lt;type.. .>
          .. .
           &lt;attributeGroup ref="xml:specialAttrs"/>
     </pre>
     <p>
      will define a type which will schema-validate an instance element
      with any of those attributes.
     </p>

    </div>
   </div>
  </xs:documentation>
 </xs:annotation>

 <xs:annotation>
  <xs:documentation>
   <div id="nsversioning" xml:id="nsversioning">
    <h2><a name="nsversioning">Versioning policy for this schema document</a></h2>

    <div class="bodytext">
     <p>
      In keeping with the XML Schema WG's standard versioning
      policy, this schema document will persist at
      <a href="http://www.w3.org/2009/01/xml.xsd">
       http://www.w3.org/2009/01/xml.xsd</a>.
     </p>
     <p>
      At the date of issue it can also be found at
      <a href="http://www.w3.org/2001/xml.xsd">
       http://www.w3.org/2001/xml.xsd</a>.
     </p>

     <p>
      The schema document at that URI may however change in the future,
      in order to remain compatible with the latest version of XML
      Schema itself, or with the XML namespace itself.  In other words,
      if the XML Schema or XML namespaces change, the version of this
      document at <a href="http://www.w3.org/2001/xml.xsd">
       http://www.w3.org/2001/xml.xsd 
      </a> 
      will change accordingly; the version at 
      <a href="http://www.w3.org/2009/01/xml.xsd">
       http://www.w3.org/2009/01/xml.xsd 
      </a> 
      will not change.
     </p>
     <p>

      Previous dated (and unchanging) versions of this schema 
      document are at:
     </p>
     <ul>
      <li><a href="http://www.w3.org/2009/01/xml.xsd">
	http://www.w3.org/2009/01/xml.xsd</a></li>
      <li><a href="http://www.w3.org/2007/08/xml.xsd">
	http://www.w3.org/2007/08/xml.xsd</a></li>
      <li><a href="http://www.w3.org/2004/10/xml.xsd">

	http://www.w3.org/2004/10/xml.xsd</a></li>
      <li><a href="http://www.w3.org/2001/03/xml.xsd">
	http://www.w3.org/2001/03/xml.xsd</a></li>
     </ul>
    </div>
   </div>
  </xs:documentation>
 </xs:annotation>

</xs:schema>
PKv�Z�xO��TSymfony/Component/Translation/Loader/schema/dic/xliff-core/xliff-core-1.2-strict.xsdnu�[���<?xml version="1.0" encoding="UTF-8"?>

<!--

May-19-2004:
- Changed the <choice> for ElemType_header, moving minOccurs="0" maxOccurs="unbounded" from its elements 
to <choice> itself.
- Added <choice> for ElemType_trans-unit to allow "any order" for <context-group>, <count-group>, <prop-group>, <note>, and
<alt-trans>.

Oct-2005
- updated version info to 1.2
- equiv-trans attribute to <trans-unit> element 
- merged-trans attribute for <group> element
- Add the <seg-source> element as optional in the <trans-unit> and <alt-trans> content models, at the same level as <source> 
- Create a new value "seg" for the mtype attribute of the <mrk> element
- Add mid as an optional attribute for the <alt-trans> element

Nov-14-2005
- Changed name attribute for <context-group> from required to optional
- Added extension point at <xliff>

Jan-9-2006
- Added alttranstype type attribute to <alt-trans>, and values

Jan-10-2006
- Corrected error with overwritten purposeValueList
- Corrected name="AttrType_Version",  attribute should have been "name"

-->
<xsd:schema xmlns:xlf="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="urn:oasis:names:tc:xliff:document:1.2" xml:lang="en">
  <!-- Import for xml:lang and xml:space -->
  <xsd:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/xml.xsd"/>
  <!-- Attributes Lists -->
  <xsd:simpleType name="XTend">
    <xsd:restriction base="xsd:string">
      <xsd:pattern value="x-[^\s]+"/>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="context-typeValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'context-type'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="database">
        <xsd:annotation>
          <xsd:documentation>Indicates a database content.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="element">
        <xsd:annotation>
          <xsd:documentation>Indicates the content of an element within an XML document.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="elementtitle">
        <xsd:annotation>
          <xsd:documentation>Indicates the name of an element within an XML document.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="linenumber">
        <xsd:annotation>
          <xsd:documentation>Indicates the line number from the sourcefile (see context-type="sourcefile") where the &lt;source&gt; is found.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="numparams">
        <xsd:annotation>
          <xsd:documentation>Indicates a the number of parameters contained within the &lt;source&gt;.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="paramnotes">
        <xsd:annotation>
          <xsd:documentation>Indicates notes pertaining to the parameters in the &lt;source&gt;.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="record">
        <xsd:annotation>
          <xsd:documentation>Indicates the content of a record within a database.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="recordtitle">
        <xsd:annotation>
          <xsd:documentation>Indicates the name of a record within a database.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="sourcefile">
        <xsd:annotation>
          <xsd:documentation>Indicates the original source file in the case that multiple files are merged to form the original file from which the XLIFF file is created. This differs from the original &lt;file&gt; attribute in that this sourcefile is one of many that make up that file.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="count-typeValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'count-type'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="num-usages">
        <xsd:annotation>
          <xsd:documentation>Indicates the count units are items that are used X times in a certain context; example: this is a reusable text unit which is used 42 times in other texts.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="repetition">
        <xsd:annotation>
          <xsd:documentation>Indicates the count units are translation units existing already in the same document.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="total">
        <xsd:annotation>
          <xsd:documentation>Indicates a total count.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="InlineDelimitersValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'ctype' when used other elements than &lt;ph&gt; or &lt;x&gt;.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="bold">
        <xsd:annotation>
          <xsd:documentation>Indicates a run of bolded text.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="italic">
        <xsd:annotation>
          <xsd:documentation>Indicates a run of text in italics.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="underlined">
        <xsd:annotation>
          <xsd:documentation>Indicates a run of underlined text.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="link">
        <xsd:annotation>
          <xsd:documentation>Indicates a run of hyper-text.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="InlinePlaceholdersValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'ctype' when used with &lt;ph&gt; or &lt;x&gt;.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="image">
        <xsd:annotation>
          <xsd:documentation>Indicates a inline image.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="pb">
        <xsd:annotation>
          <xsd:documentation>Indicates a page break.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="lb">
        <xsd:annotation>
          <xsd:documentation>Indicates a line break.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="mime-typeValueList">
    <xsd:restriction base="xsd:string">
      <xsd:pattern value="(text|multipart|message|application|image|audio|video|model)(/.+)*"/>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="datatypeValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'datatype'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="asp">
        <xsd:annotation>
          <xsd:documentation>Indicates Active Server Page data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="c">
        <xsd:annotation>
          <xsd:documentation>Indicates C source file data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="cdf">
        <xsd:annotation>
          <xsd:documentation>Indicates Channel Definition Format (CDF) data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="cfm">
        <xsd:annotation>
          <xsd:documentation>Indicates ColdFusion data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="cpp">
        <xsd:annotation>
          <xsd:documentation>Indicates C++ source file data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="csharp">
        <xsd:annotation>
          <xsd:documentation>Indicates C-Sharp data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="cstring">
        <xsd:annotation>
          <xsd:documentation>Indicates strings from C, ASM, and driver files data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="csv">
        <xsd:annotation>
          <xsd:documentation>Indicates comma-separated values data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="database">
        <xsd:annotation>
          <xsd:documentation>Indicates database data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="documentfooter">
        <xsd:annotation>
          <xsd:documentation>Indicates portions of document that follows data and contains metadata.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="documentheader">
        <xsd:annotation>
          <xsd:documentation>Indicates portions of document that precedes data and contains metadata.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="filedialog">
        <xsd:annotation>
          <xsd:documentation>Indicates data from standard UI file operations dialogs (e.g., Open, Save, Save As, Export, Import).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="form">
        <xsd:annotation>
          <xsd:documentation>Indicates standard user input screen data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="html">
        <xsd:annotation>
          <xsd:documentation>Indicates HyperText Markup Language (HTML) data - document instance.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="htmlbody">
        <xsd:annotation>
          <xsd:documentation>Indicates content within an HTML document’s &lt;body&gt; element.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="ini">
        <xsd:annotation>
          <xsd:documentation>Indicates Windows INI file data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="interleaf">
        <xsd:annotation>
          <xsd:documentation>Indicates Interleaf data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="javaclass">
        <xsd:annotation>
          <xsd:documentation>Indicates Java source file data (extension '.java').</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="javapropertyresourcebundle">
        <xsd:annotation>
          <xsd:documentation>Indicates Java property resource bundle data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="javalistresourcebundle">
        <xsd:annotation>
          <xsd:documentation>Indicates Java list resource bundle data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="javascript">
        <xsd:annotation>
          <xsd:documentation>Indicates JavaScript source file data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="jscript">
        <xsd:annotation>
          <xsd:documentation>Indicates JScript source file data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="layout">
        <xsd:annotation>
          <xsd:documentation>Indicates information relating to formatting.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="lisp">
        <xsd:annotation>
          <xsd:documentation>Indicates LISP source file data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="margin">
        <xsd:annotation>
          <xsd:documentation>Indicates information relating to margin formats.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="menufile">
        <xsd:annotation>
          <xsd:documentation>Indicates a file containing menu.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="messagefile">
        <xsd:annotation>
          <xsd:documentation>Indicates numerically identified string table.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="mif">
        <xsd:annotation>
          <xsd:documentation>Indicates Maker Interchange Format (MIF) data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="mimetype">
        <xsd:annotation>
          <xsd:documentation>Indicates that the datatype attribute value is a MIME Type value and is defined in the mime-type attribute.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="mo">
        <xsd:annotation>
          <xsd:documentation>Indicates GNU Machine Object data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="msglib">
        <xsd:annotation>
          <xsd:documentation>Indicates Message Librarian strings created by Novell's Message Librarian Tool.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="pagefooter">
        <xsd:annotation>
          <xsd:documentation>Indicates information to be displayed at the bottom of each page of a document.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="pageheader">
        <xsd:annotation>
          <xsd:documentation>Indicates information to be displayed at the top of each page of a document.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="parameters">
        <xsd:annotation>
          <xsd:documentation>Indicates a list of property values (e.g., settings within INI files or preferences dialog).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="pascal">
        <xsd:annotation>
          <xsd:documentation>Indicates Pascal source file data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="php">
        <xsd:annotation>
          <xsd:documentation>Indicates Hypertext Preprocessor data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="plaintext">
        <xsd:annotation>
          <xsd:documentation>Indicates plain text file (no formatting other than, possibly, wrapping).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="po">
        <xsd:annotation>
          <xsd:documentation>Indicates GNU Portable Object file.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="report">
        <xsd:annotation>
          <xsd:documentation>Indicates dynamically generated user defined document. e.g. Oracle Report, Crystal Report, etc.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="resources">
        <xsd:annotation>
          <xsd:documentation>Indicates Windows .NET binary resources.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="resx">
        <xsd:annotation>
          <xsd:documentation>Indicates Windows .NET Resources.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="rtf">
        <xsd:annotation>
          <xsd:documentation>Indicates Rich Text Format (RTF) data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="sgml">
        <xsd:annotation>
          <xsd:documentation>Indicates Standard Generalized Markup Language (SGML) data - document instance.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="sgmldtd">
        <xsd:annotation>
          <xsd:documentation>Indicates Standard Generalized Markup Language (SGML) data - Document Type Definition (DTD).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="svg">
        <xsd:annotation>
          <xsd:documentation>Indicates Scalable Vector Graphic (SVG) data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="vbscript">
        <xsd:annotation>
          <xsd:documentation>Indicates VisualBasic Script source file.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="warning">
        <xsd:annotation>
          <xsd:documentation>Indicates warning message.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="winres">
        <xsd:annotation>
          <xsd:documentation>Indicates Windows (Win32) resources (i.e. resources extracted from an RC script, a message file, or a compiled file).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="xhtml">
        <xsd:annotation>
          <xsd:documentation>Indicates Extensible HyperText Markup Language (XHTML) data - document instance.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="xml">
        <xsd:annotation>
          <xsd:documentation>Indicates Extensible Markup Language (XML) data - document instance.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="xmldtd">
        <xsd:annotation>
          <xsd:documentation>Indicates Extensible Markup Language (XML) data - Document Type Definition (DTD).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="xsl">
        <xsd:annotation>
          <xsd:documentation>Indicates Extensible Stylesheet Language (XSL) data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="xul">
        <xsd:annotation>
          <xsd:documentation>Indicates XUL elements.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="mtypeValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'mtype'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="abbrev">
        <xsd:annotation>
          <xsd:documentation>Indicates the marked text is an abbreviation.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="abbreviated-form">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.8: A term resulting from the omission of any part of the full term while designating the same concept.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="abbreviation">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.8.1: An abbreviated form of a simple term resulting from the omission of some of its letters (e.g. 'adj.' for 'adjective').</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="acronym">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.8.4: An abbreviated form of a term made up of letters from the full form of a multiword term strung together into a sequence pronounced only syllabically (e.g. 'radar' for 'radio detecting and ranging').</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="appellation">
        <xsd:annotation>
          <xsd:documentation>ISO-12620: A proper-name term, such as the name of an agency or other proper entity.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="collocation">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.18.1: A recurrent word combination characterized by cohesion in that the components of the collocation must co-occur within an utterance or series of utterances, even though they do not necessarily have to maintain immediate proximity to one another.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="common-name">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.5: A synonym for an international scientific term that is used in general discourse in a given language.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="datetime">
        <xsd:annotation>
          <xsd:documentation>Indicates the marked text is a date and/or time.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="equation">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.15: An expression used to represent a concept based on a statement that two mathematical expressions are, for instance, equal as identified by the equal sign (=), or assigned to one another by a similar sign.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="expanded-form">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.7: The complete representation of a term for which there is an abbreviated form.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="formula">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.14: Figures, symbols or the like used to express a concept briefly, such as a mathematical or chemical formula.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="head-term">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.1: The concept designation that has been chosen to head a terminological record.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="initialism">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.8.3: An abbreviated form of a term consisting of some of the initial letters of the words making up a multiword term or the term elements making up a compound term when these letters are pronounced individually (e.g. 'BSE' for 'bovine spongiform encephalopathy').</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="international-scientific-term">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.4: A term that is part of an international scientific nomenclature as adopted by an appropriate scientific body.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="internationalism">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.6: A term that has the same or nearly identical orthographic or phonemic form in many languages.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="logical-expression">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.16: An expression used to represent a concept based on mathematical or logical relations, such as statements of inequality, set relationships, Boolean operations, and the like.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="materials-management-unit">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.17: A unit to track object.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="name">
        <xsd:annotation>
          <xsd:documentation>Indicates the marked text is a name.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="near-synonym">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.3: A term that represents the same or a very similar concept as another term in the same language, but for which interchangeability is limited to some contexts and inapplicable in others.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="part-number">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.17.2: A unique alphanumeric designation assigned to an object in a manufacturing system.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="phrase">
        <xsd:annotation>
          <xsd:documentation>Indicates the marked text is a phrase.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="phraseological-unit">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.18: Any group of two or more words that form a unit, the meaning of which frequently cannot be deduced based on the combined sense of the words making up the phrase.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="protected">
        <xsd:annotation>
          <xsd:documentation>Indicates the marked text should not be translated.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="romanized-form">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.12: A form of a term resulting from an operation whereby non-Latin writing systems are converted to the Latin alphabet.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="seg">
        <xsd:annotation>
          <xsd:documentation>Indicates that the marked text represents a segment.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="set-phrase">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.18.2: A fixed, lexicalized phrase.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="short-form">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.8.2: A variant of a multiword term that includes fewer words than the full form of the term (e.g. 'Group of Twenty-four' for 'Intergovernmental Group of Twenty-four on International Monetary Affairs').</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="sku">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.17.1: Stock keeping unit, an inventory item identified by a unique alphanumeric designation assigned to an object in an inventory control system.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="standard-text">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.19: A fixed chunk of recurring text.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="symbol">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.13: A designation of a concept by letters, numerals, pictograms or any combination thereof.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="synonym">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.2: Any term that represents the same or a very similar concept as the main entry term in a term entry.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="synonymous-phrase">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.18.3: Phraseological unit in a language that expresses the same semantic content as another phrase in that same language.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="term">
        <xsd:annotation>
          <xsd:documentation>Indicates the marked text is a term.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="transcribed-form">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.11: A form of a term resulting from an operation whereby the characters of one writing system are represented by characters from another writing system, taking into account the pronunciation of the characters converted.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="transliterated-form">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.10: A form of a term resulting from an operation whereby the characters of an alphabetic writing system are represented by characters from another alphabetic writing system.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="truncated-term">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.8.5: An abbreviated form of a term resulting from the omission of one or more term elements or syllables (e.g. 'flu' for 'influenza').</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="variant">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.9: One of the alternate forms of a term.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="restypeValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'restype'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="auto3state">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC AUTO3STATE control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="autocheckbox">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC AUTOCHECKBOX control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="autoradiobutton">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC AUTORADIOBUTTON control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="bedit">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC BEDIT control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="bitmap">
        <xsd:annotation>
          <xsd:documentation>Indicates a bitmap, for example a BITMAP resource in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="button">
        <xsd:annotation>
          <xsd:documentation>Indicates a button object, for example a BUTTON control Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="caption">
        <xsd:annotation>
          <xsd:documentation>Indicates a caption, such as the caption of a dialog box.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="cell">
        <xsd:annotation>
          <xsd:documentation>Indicates the cell in a table, for example the content of the &lt;td&gt; element in HTML.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="checkbox">
        <xsd:annotation>
          <xsd:documentation>Indicates check box object, for example a CHECKBOX control in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="checkboxmenuitem">
        <xsd:annotation>
          <xsd:documentation>Indicates a menu item with an associated checkbox.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="checkedlistbox">
        <xsd:annotation>
          <xsd:documentation>Indicates a list box, but with a check-box for each item.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="colorchooser">
        <xsd:annotation>
          <xsd:documentation>Indicates a color selection dialog.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="combobox">
        <xsd:annotation>
          <xsd:documentation>Indicates a combination of edit box and listbox object, for example a COMBOBOX control in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="comboboxexitem">
        <xsd:annotation>
          <xsd:documentation>Indicates an initialization entry of an extended combobox DLGINIT resource block. (code 0x1234).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="comboboxitem">
        <xsd:annotation>
          <xsd:documentation>Indicates an initialization entry of a combobox DLGINIT resource block (code 0x0403).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="component">
        <xsd:annotation>
          <xsd:documentation>Indicates a UI base class element that cannot be represented by any other element.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="contextmenu">
        <xsd:annotation>
          <xsd:documentation>Indicates a context menu.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="ctext">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC CTEXT control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="cursor">
        <xsd:annotation>
          <xsd:documentation>Indicates a cursor, for example a CURSOR resource in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="datetimepicker">
        <xsd:annotation>
          <xsd:documentation>Indicates a date/time picker.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="defpushbutton">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC DEFPUSHBUTTON control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="dialog">
        <xsd:annotation>
          <xsd:documentation>Indicates a dialog box.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="dlginit">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC DLGINIT resource block.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="edit">
        <xsd:annotation>
          <xsd:documentation>Indicates an edit box object, for example an EDIT control in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="file">
        <xsd:annotation>
          <xsd:documentation>Indicates a filename.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="filechooser">
        <xsd:annotation>
          <xsd:documentation>Indicates a file dialog.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="fn">
        <xsd:annotation>
          <xsd:documentation>Indicates a footnote.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="font">
        <xsd:annotation>
          <xsd:documentation>Indicates a font name.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="footer">
        <xsd:annotation>
          <xsd:documentation>Indicates a footer.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="frame">
        <xsd:annotation>
          <xsd:documentation>Indicates a frame object.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="grid">
        <xsd:annotation>
          <xsd:documentation>Indicates a XUL grid element.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="groupbox">
        <xsd:annotation>
          <xsd:documentation>Indicates a groupbox object, for example a GROUPBOX control in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="header">
        <xsd:annotation>
          <xsd:documentation>Indicates a header item.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="heading">
        <xsd:annotation>
          <xsd:documentation>Indicates a heading, such has the content of &lt;h1&gt;, &lt;h2&gt;, etc. in HTML.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="hedit">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC HEDIT control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="hscrollbar">
        <xsd:annotation>
          <xsd:documentation>Indicates a horizontal scrollbar.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="icon">
        <xsd:annotation>
          <xsd:documentation>Indicates an icon, for example an ICON resource in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="iedit">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC IEDIT control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="keywords">
        <xsd:annotation>
          <xsd:documentation>Indicates keyword list, such as the content of the Keywords meta-data in HTML, or a K footnote in WinHelp RTF.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="label">
        <xsd:annotation>
          <xsd:documentation>Indicates a label object.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="linklabel">
        <xsd:annotation>
          <xsd:documentation>Indicates a label that is also a HTML link (not necessarily a URL).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="list">
        <xsd:annotation>
          <xsd:documentation>Indicates a list (a group of list-items, for example an &lt;ol&gt; or &lt;ul&gt; element in HTML).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="listbox">
        <xsd:annotation>
          <xsd:documentation>Indicates a listbox object, for example an LISTBOX control in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="listitem">
        <xsd:annotation>
          <xsd:documentation>Indicates an list item (an entry in a list).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="ltext">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC LTEXT control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="menu">
        <xsd:annotation>
          <xsd:documentation>Indicates a menu (a group of menu-items).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="menubar">
        <xsd:annotation>
          <xsd:documentation>Indicates a toolbar containing one or more tope level menus.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="menuitem">
        <xsd:annotation>
          <xsd:documentation>Indicates a menu item (an entry in a menu).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="menuseparator">
        <xsd:annotation>
          <xsd:documentation>Indicates a XUL menuseparator element.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="message">
        <xsd:annotation>
          <xsd:documentation>Indicates a message, for example an entry in a MESSAGETABLE resource in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="monthcalendar">
        <xsd:annotation>
          <xsd:documentation>Indicates a calendar control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="numericupdown">
        <xsd:annotation>
          <xsd:documentation>Indicates an edit box beside a spin control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="panel">
        <xsd:annotation>
          <xsd:documentation>Indicates a catch all for rectangular areas.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="popupmenu">
        <xsd:annotation>
          <xsd:documentation>Indicates a standalone menu not necessarily associated with a menubar.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="pushbox">
        <xsd:annotation>
          <xsd:documentation>Indicates a pushbox object, for example a PUSHBOX control in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="pushbutton">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC PUSHBUTTON control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="radio">
        <xsd:annotation>
          <xsd:documentation>Indicates a radio button object.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="radiobuttonmenuitem">
        <xsd:annotation>
          <xsd:documentation>Indicates a menuitem with associated radio button.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="rcdata">
        <xsd:annotation>
          <xsd:documentation>Indicates raw data resources for an application.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="row">
        <xsd:annotation>
          <xsd:documentation>Indicates a row in a table.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="rtext">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC RTEXT control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="scrollpane">
        <xsd:annotation>
          <xsd:documentation>Indicates a user navigable container used to show a portion of a document.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="separator">
        <xsd:annotation>
          <xsd:documentation>Indicates a generic divider object (e.g. menu group separator).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="shortcut">
        <xsd:annotation>
          <xsd:documentation>Windows accelerators, shortcuts in resource or property files.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="spinner">
        <xsd:annotation>
          <xsd:documentation>Indicates a UI control to indicate process activity but not progress.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="splitter">
        <xsd:annotation>
          <xsd:documentation>Indicates a splitter bar.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="state3">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC STATE3 control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="statusbar">
        <xsd:annotation>
          <xsd:documentation>Indicates a window for providing feedback to the users, like 'read-only', etc.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="string">
        <xsd:annotation>
          <xsd:documentation>Indicates a string, for example an entry in a STRINGTABLE resource in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="tabcontrol">
        <xsd:annotation>
          <xsd:documentation>Indicates a layers of controls with a tab to select layers.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="table">
        <xsd:annotation>
          <xsd:documentation>Indicates a display and edits regular two-dimensional tables of cells.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="textbox">
        <xsd:annotation>
          <xsd:documentation>Indicates a XUL textbox element.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="togglebutton">
        <xsd:annotation>
          <xsd:documentation>Indicates a UI button that can be toggled to on or off state.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="toolbar">
        <xsd:annotation>
          <xsd:documentation>Indicates an array of controls, usually buttons.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="tooltip">
        <xsd:annotation>
          <xsd:documentation>Indicates a pop up tool tip text.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="trackbar">
        <xsd:annotation>
          <xsd:documentation>Indicates a bar with a pointer indicating a position within a certain range.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="tree">
        <xsd:annotation>
          <xsd:documentation>Indicates a control that displays a set of hierarchical data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="uri">
        <xsd:annotation>
          <xsd:documentation>Indicates a URI (URN or URL).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="userbutton">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC USERBUTTON control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="usercontrol">
        <xsd:annotation>
          <xsd:documentation>Indicates a user-defined control like CONTROL control in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="var">
        <xsd:annotation>
          <xsd:documentation>Indicates the text of a variable.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="versioninfo">
        <xsd:annotation>
          <xsd:documentation>Indicates version information about a resource like VERSIONINFO in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="vscrollbar">
        <xsd:annotation>
          <xsd:documentation>Indicates a vertical scrollbar.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="window">
        <xsd:annotation>
          <xsd:documentation>Indicates a graphical window.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="size-unitValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'size-unit'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="byte">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in 8-bit bytes.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="char">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in Unicode characters.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="col">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in columns. Used for HTML text area.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="cm">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in centimeters.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="dlgunit">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in dialog units, as defined in Windows resources.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="em">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in 'font-size' units (as defined in CSS).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="ex">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in 'x-height' units (as defined in CSS).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="glyph">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in glyphs. A glyph is considered to be one or more combined Unicode characters that represent a single displayable text character. Sometimes referred to as a 'grapheme cluster'</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="in">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in inches.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="mm">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in millimeters.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="percent">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in percentage.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="pixel">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in pixels.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="point">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in point.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="row">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in rows. Used for HTML text area.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="stateValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'state'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="final">
        <xsd:annotation>
          <xsd:documentation>Indicates the terminating state.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="needs-adaptation">
        <xsd:annotation>
          <xsd:documentation>Indicates only non-textual information needs adaptation.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="needs-l10n">
        <xsd:annotation>
          <xsd:documentation>Indicates both text and non-textual information needs adaptation.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="needs-review-adaptation">
        <xsd:annotation>
          <xsd:documentation>Indicates only non-textual information needs review.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="needs-review-l10n">
        <xsd:annotation>
          <xsd:documentation>Indicates both text and non-textual information needs review.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="needs-review-translation">
        <xsd:annotation>
          <xsd:documentation>Indicates that only the text of the item needs to be reviewed.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="needs-translation">
        <xsd:annotation>
          <xsd:documentation>Indicates that the item needs to be translated.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="new">
        <xsd:annotation>
          <xsd:documentation>Indicates that the item is new. For example, translation units that were not in a previous version of the document.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="signed-off">
        <xsd:annotation>
          <xsd:documentation>Indicates that changes are reviewed and approved.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="translated">
        <xsd:annotation>
          <xsd:documentation>Indicates that the item has been translated.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="state-qualifierValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'state-qualifier'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="exact-match">
        <xsd:annotation>
          <xsd:documentation>Indicates an exact match. An exact match occurs when a source text of a segment is exactly the same as the source text of a segment that was translated previously.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="fuzzy-match">
        <xsd:annotation>
          <xsd:documentation>Indicates a fuzzy match. A fuzzy match occurs when a source text of a segment is very similar to the source text of a segment that was translated previously (e.g. when the difference is casing, a few changed words, white-space discripancy, etc.).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="id-match">
        <xsd:annotation>
          <xsd:documentation>Indicates a match based on matching IDs (in addition to matching text).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="leveraged-glossary">
        <xsd:annotation>
          <xsd:documentation>Indicates a translation derived from a glossary.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="leveraged-inherited">
        <xsd:annotation>
          <xsd:documentation>Indicates a translation derived from existing translation.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="leveraged-mt">
        <xsd:annotation>
          <xsd:documentation>Indicates a translation derived from machine translation.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="leveraged-repository">
        <xsd:annotation>
          <xsd:documentation>Indicates a translation derived from a translation repository.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="leveraged-tm">
        <xsd:annotation>
          <xsd:documentation>Indicates a translation derived from a translation memory.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="mt-suggestion">
        <xsd:annotation>
          <xsd:documentation>Indicates the translation is suggested by machine translation.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="rejected-grammar">
        <xsd:annotation>
          <xsd:documentation>Indicates that the item has been rejected because of incorrect grammar.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="rejected-inaccurate">
        <xsd:annotation>
          <xsd:documentation>Indicates that the item has been rejected because it is incorrect.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="rejected-length">
        <xsd:annotation>
          <xsd:documentation>Indicates that the item has been rejected because it is too long or too short.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="rejected-spelling">
        <xsd:annotation>
          <xsd:documentation>Indicates that the item has been rejected because of incorrect spelling.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="tm-suggestion">
        <xsd:annotation>
          <xsd:documentation>Indicates the translation is suggested by translation memory.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="unitValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'unit'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="word">
        <xsd:annotation>
          <xsd:documentation>Refers to words.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="page">
        <xsd:annotation>
          <xsd:documentation>Refers to pages.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="trans-unit">
        <xsd:annotation>
          <xsd:documentation>Refers to &lt;trans-unit&gt; elements.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="bin-unit">
        <xsd:annotation>
          <xsd:documentation>Refers to &lt;bin-unit&gt; elements.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="glyph">
        <xsd:annotation>
          <xsd:documentation>Refers to glyphs.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="item">
        <xsd:annotation>
          <xsd:documentation>Refers to &lt;trans-unit&gt; and/or &lt;bin-unit&gt; elements.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="instance">
        <xsd:annotation>
          <xsd:documentation>Refers to the occurrences of instances defined by the count-type value.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="character">
        <xsd:annotation>
          <xsd:documentation>Refers to characters.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="line">
        <xsd:annotation>
          <xsd:documentation>Refers to lines.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="sentence">
        <xsd:annotation>
          <xsd:documentation>Refers to sentences.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="paragraph">
        <xsd:annotation>
          <xsd:documentation>Refers to paragraphs.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="segment">
        <xsd:annotation>
          <xsd:documentation>Refers to segments.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="placeable">
        <xsd:annotation>
          <xsd:documentation>Refers to placeables (inline elements).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="priorityValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'priority'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:positiveInteger">
      <xsd:enumeration value="1">
        <xsd:annotation>
          <xsd:documentation>Highest priority.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="2">
        <xsd:annotation>
          <xsd:documentation>High priority.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="3">
        <xsd:annotation>
          <xsd:documentation>High priority, but not as important as 2.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="4">
        <xsd:annotation>
          <xsd:documentation>High priority, but not as important as 3.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="5">
        <xsd:annotation>
          <xsd:documentation>Medium priority, but more important than 6.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="6">
        <xsd:annotation>
          <xsd:documentation>Medium priority, but less important than 5.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="7">
        <xsd:annotation>
          <xsd:documentation>Low priority, but more important than 8.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="8">
        <xsd:annotation>
          <xsd:documentation>Low priority, but more important than 9.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="9">
        <xsd:annotation>
          <xsd:documentation>Low priority.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="10">
        <xsd:annotation>
          <xsd:documentation>Lowest priority.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="reformatValueYesNo">
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="yes">
        <xsd:annotation>
          <xsd:documentation>This value indicates that all properties can be reformatted. This value must be used alone.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="no">
        <xsd:annotation>
          <xsd:documentation>This value indicates that no properties should be reformatted. This value must be used alone.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="reformatValueList">
    <xsd:list>
      <xsd:simpleType>
        <xsd:union memberTypes="xlf:XTend">
          <xsd:simpleType>
            <xsd:restriction base="xsd:string">
              <xsd:enumeration value="coord">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that all information in the coord attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="coord-x">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that the x information in the coord attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="coord-y">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that the y information in the coord attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="coord-cx">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that the cx information in the coord attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="coord-cy">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that the cy information in the coord attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="font">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that all the information in the font attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="font-name">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that the name information in the font attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="font-size">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that the size information in the font attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="font-weight">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that the weight information in the font attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="css-style">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that the information in the css-style attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="style">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that the information in the style attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="ex-style">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that the information in the exstyle attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
            </xsd:restriction>
          </xsd:simpleType>
        </xsd:union>
      </xsd:simpleType>
    </xsd:list>
  </xsd:simpleType>
  <xsd:simpleType name="purposeValueList">
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="information">
        <xsd:annotation>
          <xsd:documentation>Indicates that the context is informational in nature, specifying for example, how a term should be translated. Thus, should be displayed to anyone editing the XLIFF document.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="location">
        <xsd:annotation>
          <xsd:documentation>Indicates that the context-group is used to specify where the term was found in the translatable source. Thus, it is not displayed.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="match">
        <xsd:annotation>
          <xsd:documentation>Indicates that the context information should be used during translation memory lookups. Thus, it is not displayed.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="alttranstypeValueList">
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="proposal">
        <xsd:annotation>
          <xsd:documentation>Represents a translation proposal from a translation memory or other resource.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="previous-version">
        <xsd:annotation>
          <xsd:documentation>Represents a previous version of the target element.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="rejected">
        <xsd:annotation>
          <xsd:documentation>Represents a rejected version of the target element.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="reference">
        <xsd:annotation>
          <xsd:documentation>Represents a translation to be used for reference purposes only, for example from a related product or a different language.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="accepted">
        <xsd:annotation>
          <xsd:documentation>Represents a proposed translation that was used for the translation of the trans-unit, possibly modified.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <!-- Other Types -->
  <xsd:complexType name="ElemType_ExternalReference">
    <xsd:choice>
      <xsd:element ref="xlf:internal-file"/>
      <xsd:element ref="xlf:external-file"/>
    </xsd:choice>
  </xsd:complexType>
  <xsd:simpleType name="AttrType_purpose">
    <xsd:list>
      <xsd:simpleType>
        <xsd:union memberTypes="xlf:purposeValueList xlf:XTend"/>
      </xsd:simpleType>
    </xsd:list>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_datatype">
    <xsd:union memberTypes="xlf:datatypeValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_restype">
    <xsd:union memberTypes="xlf:restypeValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_alttranstype">
    <xsd:union memberTypes="xlf:alttranstypeValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_context-type">
    <xsd:union memberTypes="xlf:context-typeValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_state">
    <xsd:union memberTypes="xlf:stateValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_state-qualifier">
    <xsd:union memberTypes="xlf:state-qualifierValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_count-type">
    <xsd:union memberTypes="xlf:restypeValueList xlf:count-typeValueList xlf:datatypeValueList xlf:stateValueList xlf:state-qualifierValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_InlineDelimiters">
    <xsd:union memberTypes="xlf:InlineDelimitersValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_InlinePlaceholders">
    <xsd:union memberTypes="xlf:InlinePlaceholdersValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_size-unit">
    <xsd:union memberTypes="xlf:size-unitValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_mtype">
    <xsd:union memberTypes="xlf:mtypeValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_unit">
    <xsd:union memberTypes="xlf:unitValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_priority">
    <xsd:union memberTypes="xlf:priorityValueList"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_reformat">
    <xsd:union memberTypes="xlf:reformatValueYesNo xlf:reformatValueList"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_YesNo">
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="yes"/>
      <xsd:enumeration value="no"/>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_Position">
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="open"/>
      <xsd:enumeration value="close"/>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_assoc">
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="preceding"/>
      <xsd:enumeration value="following"/>
      <xsd:enumeration value="both"/>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_annotates">
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="source"/>
      <xsd:enumeration value="target"/>
      <xsd:enumeration value="general"/>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_Coordinates">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'coord'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:string">
      <xsd:pattern value="(-?\d+|#);(-?\d+|#);(-?\d+|#);(-?\d+|#)"/>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_Version">
    <xsd:annotation>
      <xsd:documentation>Version values: 1.0 and 1.1 are allowed for backward compatibility.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="1.2"/>
      <xsd:enumeration value="1.1"/>
      <xsd:enumeration value="1.0"/>
    </xsd:restriction>
  </xsd:simpleType>
  <!-- Groups -->
  <xsd:group name="ElemGroup_TextContent">
    <xsd:choice>
      <xsd:element ref="xlf:g"/>
      <xsd:element ref="xlf:bpt"/>
      <xsd:element ref="xlf:ept"/>
      <xsd:element ref="xlf:ph"/>
      <xsd:element ref="xlf:it"/>
      <xsd:element ref="xlf:mrk"/>
      <xsd:element ref="xlf:x"/>
      <xsd:element ref="xlf:bx"/>
      <xsd:element ref="xlf:ex"/>
    </xsd:choice>
  </xsd:group>
  <xsd:attributeGroup name="AttrGroup_TextContent">
    <xsd:attribute name="id" type="xsd:string" use="required"/>
    <xsd:attribute name="xid" type="xsd:string" use="optional"/>
    <xsd:attribute name="equiv-text" type="xsd:string" use="optional"/>
    <xsd:anyAttribute namespace="##other" processContents="strict"/>
  </xsd:attributeGroup>
  <!-- XLIFF Structure -->
  <xsd:element name="xliff">
    <xsd:complexType>
      <xsd:sequence maxOccurs="unbounded">
        <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
        <xsd:element ref="xlf:file"/>
      </xsd:sequence>
      <xsd:attribute name="version" type="xlf:AttrType_Version" use="required"/>
      <xsd:attribute ref="xml:lang" use="optional"/>
      <xsd:anyAttribute namespace="##other" processContents="strict"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="file">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element minOccurs="0" ref="xlf:header"/>
        <xsd:element ref="xlf:body"/>
      </xsd:sequence>
      <xsd:attribute name="original" type="xsd:string" use="required"/>
      <xsd:attribute name="source-language" type="xsd:language" use="required"/>
      <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="required"/>
      <xsd:attribute name="tool-id" type="xsd:string" use="optional"/>
      <xsd:attribute name="date" type="xsd:dateTime" use="optional"/>
      <xsd:attribute ref="xml:space" use="optional"/>
      <xsd:attribute name="category" type="xsd:string" use="optional"/>
      <xsd:attribute name="target-language" type="xsd:language" use="optional"/>
      <xsd:attribute name="product-name" type="xsd:string" use="optional"/>
      <xsd:attribute name="product-version" type="xsd:string" use="optional"/>
      <xsd:attribute name="build-num" type="xsd:string" use="optional"/>
      <xsd:anyAttribute namespace="##other" processContents="strict"/>
    </xsd:complexType>
    <xsd:unique name="U_group_id">
      <xsd:selector xpath=".//xlf:group"/>
      <xsd:field xpath="@id"/>
    </xsd:unique>
    <xsd:key name="K_unit_id">
      <xsd:selector xpath=".//xlf:trans-unit|.//xlf:bin-unit"/>
      <xsd:field xpath="@id"/>
    </xsd:key>
    <xsd:keyref name="KR_unit_id" refer="xlf:K_unit_id">
      <xsd:selector xpath=".//bpt|.//ept|.//it|.//ph|.//g|.//x|.//bx|.//ex|.//sub"/>
      <xsd:field xpath="@xid"/>
    </xsd:keyref>
    <xsd:key name="K_tool-id">
      <xsd:selector xpath="xlf:header/xlf:tool"/>
      <xsd:field xpath="@tool-id"/>
    </xsd:key>
    <xsd:keyref name="KR_file_tool-id" refer="xlf:K_tool-id">
      <xsd:selector xpath="."/>
      <xsd:field xpath="@tool-id"/>
    </xsd:keyref>
    <xsd:keyref name="KR_phase_tool-id" refer="xlf:K_tool-id">
      <xsd:selector xpath="xlf:header/xlf:phase-group/xlf:phase"/>
      <xsd:field xpath="@tool-id"/>
    </xsd:keyref>
    <xsd:keyref name="KR_alt-trans_tool-id" refer="xlf:K_tool-id">
      <xsd:selector xpath=".//xlf:trans-unit/xlf:alt-trans"/>
      <xsd:field xpath="@tool-id"/>
    </xsd:keyref>
    <xsd:key name="K_count-group_name">
      <xsd:selector xpath=".//xlf:count-group"/>
      <xsd:field xpath="@name"/>
    </xsd:key>
    <xsd:unique name="U_context-group_name">
      <xsd:selector xpath=".//xlf:context-group"/>
      <xsd:field xpath="@name"/>
    </xsd:unique>
    <xsd:key name="K_phase-name">
      <xsd:selector xpath="xlf:header/xlf:phase-group/xlf:phase"/>
      <xsd:field xpath="@phase-name"/>
    </xsd:key>
    <xsd:keyref name="KR_phase-name" refer="xlf:K_phase-name">
      <xsd:selector xpath=".//xlf:count|.//xlf:trans-unit|.//xlf:target|.//bin-unit|.//bin-target"/>
      <xsd:field xpath="@phase-name"/>
    </xsd:keyref>
    <xsd:unique name="U_uid">
      <xsd:selector xpath=".//xlf:external-file"/>
      <xsd:field xpath="@uid"/>
    </xsd:unique>
  </xsd:element>
  <xsd:element name="header">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element minOccurs="0" name="skl" type="xlf:ElemType_ExternalReference"/>
        <xsd:element minOccurs="0" ref="xlf:phase-group"/>
        <xsd:choice maxOccurs="unbounded" minOccurs="0">
          <xsd:element name="glossary" type="xlf:ElemType_ExternalReference"/>
          <xsd:element name="reference" type="xlf:ElemType_ExternalReference"/>
          <xsd:element ref="xlf:count-group"/>
          <xsd:element ref="xlf:note"/>
          <xsd:element ref="xlf:tool"/>
        </xsd:choice>
        <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="internal-file">
    <xsd:complexType>
      <xsd:simpleContent>
        <xsd:extension base="xsd:string">
          <xsd:attribute name="form" type="xsd:string"/>
          <xsd:attribute name="crc" type="xsd:NMTOKEN"/>
        </xsd:extension>
      </xsd:simpleContent>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="external-file">
    <xsd:complexType>
      <xsd:attribute name="href" type="xsd:string" use="required"/>
      <xsd:attribute name="crc" type="xsd:NMTOKEN"/>
      <xsd:attribute name="uid" type="xsd:NMTOKEN"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="note">
    <xsd:complexType>
      <xsd:simpleContent>
        <xsd:extension base="xsd:string">
          <xsd:attribute ref="xml:lang" use="optional"/>
          <xsd:attribute default="1" name="priority" type="xlf:AttrType_priority" use="optional"/>
          <xsd:attribute name="from" type="xsd:string" use="optional"/>
          <xsd:attribute default="general" name="annotates" type="xlf:AttrType_annotates" use="optional"/>
        </xsd:extension>
      </xsd:simpleContent>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="phase-group">
    <xsd:complexType>
      <xsd:sequence maxOccurs="unbounded">
        <xsd:element ref="xlf:phase"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="phase">
    <xsd:complexType>
      <xsd:sequence maxOccurs="unbounded" minOccurs="0">
        <xsd:element ref="xlf:note"/>
      </xsd:sequence>
      <xsd:attribute name="phase-name" type="xsd:string" use="required"/>
      <xsd:attribute name="process-name" type="xsd:string" use="required"/>
      <xsd:attribute name="company-name" type="xsd:string" use="optional"/>
      <xsd:attribute name="tool-id" type="xsd:string" use="optional"/>
      <xsd:attribute name="date" type="xsd:dateTime" use="optional"/>
      <xsd:attribute name="job-id" type="xsd:string" use="optional"/>
      <xsd:attribute name="contact-name" type="xsd:string" use="optional"/>
      <xsd:attribute name="contact-email" type="xsd:string" use="optional"/>
      <xsd:attribute name="contact-phone" type="xsd:string" use="optional"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="count-group">
    <xsd:complexType>
      <xsd:sequence maxOccurs="unbounded" minOccurs="0">
        <xsd:element ref="xlf:count"/>
      </xsd:sequence>
      <xsd:attribute name="name" type="xsd:string" use="required"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="count">
    <xsd:complexType>
      <xsd:simpleContent>
        <xsd:extension base="xsd:string">
          <xsd:attribute name="count-type" type="xlf:AttrType_count-type" use="optional"/>
          <xsd:attribute name="phase-name" type="xsd:string" use="optional"/>
          <xsd:attribute default="word" name="unit" type="xlf:AttrType_unit" use="optional"/>
        </xsd:extension>
      </xsd:simpleContent>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="context-group">
    <xsd:complexType>
      <xsd:sequence maxOccurs="unbounded">
        <xsd:element ref="xlf:context"/>
      </xsd:sequence>
      <xsd:attribute name="name" type="xsd:string" use="optional"/>
      <xsd:attribute name="crc" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="purpose" type="xlf:AttrType_purpose" use="optional"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="context">
    <xsd:complexType>
      <xsd:simpleContent>
        <xsd:extension base="xsd:string">
          <xsd:attribute name="context-type" type="xlf:AttrType_context-type" use="required"/>
          <xsd:attribute default="no" name="match-mandatory" type="xlf:AttrType_YesNo" use="optional"/>
          <xsd:attribute name="crc" type="xsd:NMTOKEN" use="optional"/>
        </xsd:extension>
      </xsd:simpleContent>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="tool">
    <xsd:complexType mixed="true">
      <xsd:sequence>
        <xsd:any namespace="##any" processContents="strict" minOccurs="0" maxOccurs="unbounded"/>
      </xsd:sequence>
      <xsd:attribute name="tool-id" type="xsd:string" use="required"/>
      <xsd:attribute name="tool-name" type="xsd:string" use="required"/>
      <xsd:attribute name="tool-version" type="xsd:string" use="optional"/>
      <xsd:attribute name="tool-company" type="xsd:string" use="optional"/>
      <xsd:anyAttribute namespace="##other" processContents="strict"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="body">
    <xsd:complexType>
      <xsd:choice maxOccurs="unbounded" minOccurs="0">
        <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:group"/>
        <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:trans-unit"/>
        <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:bin-unit"/>
      </xsd:choice>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="group">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:sequence>
          <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:context-group"/>
          <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:count-group"/>
          <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:note"/>
          <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
        </xsd:sequence>
        <xsd:choice maxOccurs="unbounded">
          <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:group"/>
          <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:trans-unit"/>
          <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:bin-unit"/>
        </xsd:choice>
      </xsd:sequence>
      <xsd:attribute name="id" type="xsd:string" use="optional"/>
      <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>
      <xsd:attribute default="default" ref="xml:space" use="optional"/>
      <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
      <xsd:attribute name="resname" type="xsd:string" use="optional"/>
      <xsd:attribute name="extradata" type="xsd:string" use="optional"/>
      <xsd:attribute name="extype" type="xsd:string" use="optional"/>
      <xsd:attribute name="help-id" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="menu" type="xsd:string" use="optional"/>
      <xsd:attribute name="menu-option" type="xsd:string" use="optional"/>
      <xsd:attribute name="menu-name" type="xsd:string" use="optional"/>
      <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>
      <xsd:attribute name="font" type="xsd:string" use="optional"/>
      <xsd:attribute name="css-style" type="xsd:string" use="optional"/>
      <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute default="yes" name="translate" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:attribute default="yes" name="reformat" type="xlf:AttrType_reformat" use="optional"/>
      <xsd:attribute default="pixel" name="size-unit" type="xlf:AttrType_size-unit" use="optional"/>
      <xsd:attribute name="maxwidth" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="minwidth" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="maxheight" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="minheight" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="maxbytes" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="minbytes" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="charclass" type="xsd:string" use="optional"/>
      <xsd:attribute default="no" name="merged-trans" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:anyAttribute namespace="##other" processContents="strict"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="trans-unit">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element ref="xlf:source"/>
        <xsd:element minOccurs="0" ref="xlf:seg-source"/>
        <xsd:element minOccurs="0" ref="xlf:target"/>
        <xsd:choice maxOccurs="unbounded" minOccurs="0">
          <xsd:element ref="xlf:context-group"/>
          <xsd:element ref="xlf:count-group"/>
          <xsd:element ref="xlf:note"/>
          <xsd:element ref="xlf:alt-trans"/>
        </xsd:choice>
        <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
      </xsd:sequence>
      <xsd:attribute name="id" type="xsd:string" use="required"/>
      <xsd:attribute name="approved" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:attribute default="yes" name="translate" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:attribute default="yes" name="reformat" type="xlf:AttrType_reformat" use="optional"/>
      <xsd:attribute default="default" ref="xml:space" use="optional"/>
      <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>
      <xsd:attribute name="phase-name" type="xsd:string" use="optional"/>
      <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
      <xsd:attribute name="resname" type="xsd:string" use="optional"/>
      <xsd:attribute name="extradata" type="xsd:string" use="optional"/>
      <xsd:attribute name="extype" type="xsd:string" use="optional"/>
      <xsd:attribute name="help-id" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="menu" type="xsd:string" use="optional"/>
      <xsd:attribute name="menu-option" type="xsd:string" use="optional"/>
      <xsd:attribute name="menu-name" type="xsd:string" use="optional"/>
      <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>
      <xsd:attribute name="font" type="xsd:string" use="optional"/>
      <xsd:attribute name="css-style" type="xsd:string" use="optional"/>
      <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute default="pixel" name="size-unit" type="xlf:AttrType_size-unit" use="optional"/>
      <xsd:attribute name="maxwidth" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="minwidth" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="maxheight" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="minheight" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="maxbytes" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="minbytes" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="charclass" type="xsd:string" use="optional"/>
      <xsd:attribute default="yes" name="merged-trans" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:anyAttribute namespace="##other" processContents="strict"/>
    </xsd:complexType>
    <xsd:unique name="U_tu_segsrc_mid">
      <xsd:selector xpath="./xlf:seg-source/xlf:mrk"/>
      <xsd:field xpath="@mid"/>
    </xsd:unique>
    <xsd:keyref name="KR_tu_segsrc_mid" refer="xlf:U_tu_segsrc_mid">
      <xsd:selector xpath="./xlf:target/xlf:mrk|./xlf:alt-trans"/>
      <xsd:field xpath="@mid"/>
    </xsd:keyref>
  </xsd:element>
  <xsd:element name="source">
    <xsd:complexType mixed="true">
      <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
      <xsd:attribute ref="xml:lang" use="optional"/>
      <xsd:anyAttribute namespace="##other" processContents="strict"/>
    </xsd:complexType>
    <xsd:unique name="U_source_bpt_rid">
      <xsd:selector xpath=".//xlf:bpt"/>
      <xsd:field xpath="@rid"/>
    </xsd:unique>
    <xsd:keyref name="KR_source_ept_rid" refer="xlf:U_source_bpt_rid">
      <xsd:selector xpath=".//xlf:ept"/>
      <xsd:field xpath="@rid"/>
    </xsd:keyref>
    <xsd:unique name="U_source_bx_rid">
      <xsd:selector xpath=".//xlf:bx"/>
      <xsd:field xpath="@rid"/>
    </xsd:unique>
    <xsd:keyref name="KR_source_ex_rid" refer="xlf:U_source_bx_rid">
      <xsd:selector xpath=".//xlf:ex"/>
      <xsd:field xpath="@rid"/>
    </xsd:keyref>
  </xsd:element>
  <xsd:element name="seg-source">
    <xsd:complexType mixed="true">
      <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
      <xsd:attribute ref="xml:lang" use="optional"/>
      <xsd:anyAttribute namespace="##other" processContents="strict"/>
    </xsd:complexType>
    <xsd:unique name="U_segsrc_bpt_rid">
      <xsd:selector xpath=".//xlf:bpt"/>
      <xsd:field xpath="@rid"/>
    </xsd:unique>
    <xsd:keyref name="KR_segsrc_ept_rid" refer="xlf:U_segsrc_bpt_rid">
      <xsd:selector xpath=".//xlf:ept"/>
      <xsd:field xpath="@rid"/>
    </xsd:keyref>
    <xsd:unique name="U_segsrc_bx_rid">
      <xsd:selector xpath=".//xlf:bx"/>
      <xsd:field xpath="@rid"/>
    </xsd:unique>
    <xsd:keyref name="KR_segsrc_ex_rid" refer="xlf:U_segsrc_bx_rid">
      <xsd:selector xpath=".//xlf:ex"/>
      <xsd:field xpath="@rid"/>
    </xsd:keyref>
  </xsd:element>
  <xsd:element name="target">
    <xsd:complexType mixed="true">
      <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
      <xsd:attribute name="state" type="xlf:AttrType_state" use="optional"/>
      <xsd:attribute name="state-qualifier" type="xlf:AttrType_state-qualifier" use="optional"/>
      <xsd:attribute name="phase-name" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute ref="xml:lang" use="optional"/>
      <xsd:attribute name="resname" type="xsd:string" use="optional"/>
      <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>
      <xsd:attribute name="font" type="xsd:string" use="optional"/>
      <xsd:attribute name="css-style" type="xsd:string" use="optional"/>
      <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute default="yes" name="equiv-trans" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:anyAttribute namespace="##other" processContents="strict"/>
    </xsd:complexType>
    <xsd:unique name="U_target_bpt_rid">
      <xsd:selector xpath=".//xlf:bpt"/>
      <xsd:field xpath="@rid"/>
    </xsd:unique>
    <xsd:keyref name="KR_target_ept_rid" refer="xlf:U_target_bpt_rid">
      <xsd:selector xpath=".//xlf:ept"/>
      <xsd:field xpath="@rid"/>
    </xsd:keyref>
    <xsd:unique name="U_target_bx_rid">
      <xsd:selector xpath=".//xlf:bx"/>
      <xsd:field xpath="@rid"/>
    </xsd:unique>
    <xsd:keyref name="KR_target_ex_rid" refer="xlf:U_target_bx_rid">
      <xsd:selector xpath=".//xlf:ex"/>
      <xsd:field xpath="@rid"/>
    </xsd:keyref>
  </xsd:element>
  <xsd:element name="alt-trans">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element minOccurs="0" ref="xlf:source"/>
        <xsd:element minOccurs="0" ref="xlf:seg-source"/>
        <xsd:element maxOccurs="1" ref="xlf:target"/>
        <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:context-group"/>
        <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:note"/>
        <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
      </xsd:sequence>
      <xsd:attribute name="match-quality" type="xsd:string" use="optional"/>
      <xsd:attribute name="tool-id" type="xsd:string" use="optional"/>
      <xsd:attribute name="crc" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute ref="xml:lang" use="optional"/>
      <xsd:attribute name="origin" type="xsd:string" use="optional"/>
      <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>
      <xsd:attribute default="default" ref="xml:space" use="optional"/>
      <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
      <xsd:attribute name="resname" type="xsd:string" use="optional"/>
      <xsd:attribute name="extradata" type="xsd:string" use="optional"/>
      <xsd:attribute name="extype" type="xsd:string" use="optional"/>
      <xsd:attribute name="help-id" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="menu" type="xsd:string" use="optional"/>
      <xsd:attribute name="menu-option" type="xsd:string" use="optional"/>
      <xsd:attribute name="menu-name" type="xsd:string" use="optional"/>
      <xsd:attribute name="mid" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>
      <xsd:attribute name="font" type="xsd:string" use="optional"/>
      <xsd:attribute name="css-style" type="xsd:string" use="optional"/>
      <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="phase-name" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute default="proposal" name="alttranstype" type="xlf:AttrType_alttranstype" use="optional"/>
      <xsd:anyAttribute namespace="##other" processContents="strict"/>
    </xsd:complexType>
    <xsd:unique name="U_at_segsrc_mid">
      <xsd:selector xpath="./xlf:seg-source/xlf:mrk"/>
      <xsd:field xpath="@mid"/>
    </xsd:unique>
    <xsd:keyref name="KR_at_segsrc_mid" refer="xlf:U_at_segsrc_mid">
      <xsd:selector xpath="./xlf:target/xlf:mrk"/>
      <xsd:field xpath="@mid"/>
    </xsd:keyref>
  </xsd:element>
  <xsd:element name="bin-unit">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element ref="xlf:bin-source"/>
        <xsd:element minOccurs="0" ref="xlf:bin-target"/>
        <xsd:choice maxOccurs="unbounded" minOccurs="0">
          <xsd:element ref="xlf:context-group"/>
          <xsd:element ref="xlf:count-group"/>
          <xsd:element ref="xlf:note"/>
          <xsd:element ref="xlf:trans-unit"/>
        </xsd:choice>
        <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
      </xsd:sequence>
      <xsd:attribute name="id" type="xsd:string" use="required"/>
      <xsd:attribute name="mime-type" type="xlf:mime-typeValueList" use="required"/>
      <xsd:attribute name="approved" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:attribute default="yes" name="translate" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:attribute default="yes" name="reformat" type="xlf:AttrType_reformat" use="optional"/>
      <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
      <xsd:attribute name="resname" type="xsd:string" use="optional"/>
      <xsd:attribute name="phase-name" type="xsd:string" use="optional"/>
      <xsd:anyAttribute namespace="##other" processContents="strict"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="bin-source">
    <xsd:complexType>
      <xsd:choice>
        <xsd:element ref="xlf:internal-file"/>
        <xsd:element ref="xlf:external-file"/>
      </xsd:choice>
      <xsd:anyAttribute namespace="##other" processContents="strict"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="bin-target">
    <xsd:complexType>
      <xsd:choice>
        <xsd:element ref="xlf:internal-file"/>
        <xsd:element ref="xlf:external-file"/>
      </xsd:choice>
      <xsd:attribute name="mime-type" type="xlf:mime-typeValueList" use="optional"/>
      <xsd:attribute name="state" type="xlf:AttrType_state" use="optional"/>
      <xsd:attribute name="state-qualifier" type="xlf:AttrType_state-qualifier" use="optional"/>
      <xsd:attribute name="phase-name" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
      <xsd:attribute name="resname" type="xsd:string" use="optional"/>
      <xsd:anyAttribute namespace="##other" processContents="strict"/>
    </xsd:complexType>
  </xsd:element>
  <!-- Element for inline codes -->
  <xsd:element name="g">
    <xsd:complexType mixed="true">
      <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
      <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
      <xsd:attribute default="yes" name="clone" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="x">
    <xsd:complexType>
      <xsd:attribute name="ctype" type="xlf:AttrType_InlinePlaceholders" use="optional"/>
      <xsd:attribute default="yes" name="clone" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="bx">
    <xsd:complexType>
      <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
      <xsd:attribute default="yes" name="clone" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="ex">
    <xsd:complexType>
      <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="ph">
    <xsd:complexType mixed="true">
      <xsd:sequence maxOccurs="unbounded" minOccurs="0">
        <xsd:element ref="xlf:sub"/>
      </xsd:sequence>
      <xsd:attribute name="ctype" type="xlf:AttrType_InlinePlaceholders" use="optional"/>
      <xsd:attribute name="crc" type="xsd:string" use="optional"/>
      <xsd:attribute name="assoc" type="xlf:AttrType_assoc" use="optional"/>
      <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="bpt">
    <xsd:complexType mixed="true">
      <xsd:sequence maxOccurs="unbounded" minOccurs="0">
        <xsd:element ref="xlf:sub"/>
      </xsd:sequence>
      <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
      <xsd:attribute name="crc" type="xsd:string" use="optional"/>
      <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="ept">
    <xsd:complexType mixed="true">
      <xsd:sequence maxOccurs="unbounded" minOccurs="0">
        <xsd:element ref="xlf:sub"/>
      </xsd:sequence>
      <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="crc" type="xsd:string" use="optional"/>
      <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="it">
    <xsd:complexType mixed="true">
      <xsd:sequence maxOccurs="unbounded" minOccurs="0">
        <xsd:element ref="xlf:sub"/>
      </xsd:sequence>
      <xsd:attribute name="pos" type="xlf:AttrType_Position" use="required"/>
      <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
      <xsd:attribute name="crc" type="xsd:string" use="optional"/>
      <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="sub">
    <xsd:complexType mixed="true">
      <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
      <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>
      <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
      <xsd:attribute name="xid" type="xsd:string" use="optional"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="mrk">
    <xsd:complexType mixed="true">
      <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
      <xsd:attribute name="mtype" type="xlf:AttrType_mtype" use="required"/>
      <xsd:attribute name="mid" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="comment" type="xsd:string" use="optional"/>
      <xsd:anyAttribute namespace="##other" processContents="strict"/>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>
PKv�Z)-d+�	�	5Symfony/Component/Translation/Loader/QtFileLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Config\Util\XmlUtils;
use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Config\Resource\FileResource;

/**
 * QtFileLoader loads translations from QT Translations XML files.
 *
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 *
 * @api
 */
class QtFileLoader implements LoaderInterface
{
    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function load($resource, $locale, $domain = 'messages')
    {
        if (!stream_is_local($resource)) {
            throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
        }

        if (!file_exists($resource)) {
            throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
        }

        try {
            $dom = XmlUtils::loadFile($resource);
        } catch (\InvalidArgumentException $e) {
            throw new InvalidResourceException(sprintf('Unable to load "%s".', $resource), $e->getCode(), $e);
        }

        $internalErrors = libxml_use_internal_errors(true);
        libxml_clear_errors();

        $xpath = new \DOMXPath($dom);
        $nodes = $xpath->evaluate('//TS/context/name[text()="'.$domain.'"]');

        $catalogue = new MessageCatalogue($locale);
        if ($nodes->length == 1) {
            $translations = $nodes->item(0)->nextSibling->parentNode->parentNode->getElementsByTagName('message');
            foreach ($translations as $translation) {
                $translationValue = (string) $translation->getElementsByTagName('translation')->item(0)->nodeValue;

                if (!empty($translationValue)) {
                    $catalogue->set(
                        (string) $translation->getElementsByTagName('source')->item(0)->nodeValue,
                        $translationValue,
                        $domain
                    );
                }
                $translation = $translation->nextSibling;
            }
            $catalogue->addResource(new FileResource($resource));
        }

        libxml_use_internal_errors($internalErrors);

        return $catalogue;
    }
}
PKv�Z:����7Symfony/Component/Translation/Loader/YamlFileLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\Yaml\Parser as YamlParser;
use Symfony\Component\Yaml\Exception\ParseException;

/**
 * YamlFileLoader loads translations from Yaml files.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class YamlFileLoader extends ArrayLoader implements LoaderInterface
{
    private $yamlParser;

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function load($resource, $locale, $domain = 'messages')
    {
        if (!stream_is_local($resource)) {
            throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
        }

        if (!file_exists($resource)) {
            throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
        }

        if (null === $this->yamlParser) {
            $this->yamlParser = new YamlParser();
        }

        try {
            $messages = $this->yamlParser->parse(file_get_contents($resource));
        } catch (ParseException $e) {
            throw new InvalidResourceException('Error parsing YAML.', 0, $e);
        }

        // empty file
        if (null === $messages) {
            $messages = array();
        }

        // not an array
        if (!is_array($messages)) {
            throw new InvalidResourceException(sprintf('The file "%s" must contain a YAML array.', $resource));
        }

        $catalogue = parent::load($messages, $locale, $domain);
        $catalogue->addResource(new FileResource($resource));

        return $catalogue;
    }
}
PKw�Z�V�˽�.Symfony/Component/Routing/Annotation/Route.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Annotation;

/**
 * Annotation class for @Route().
 *
 * @Annotation
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Route
{
    private $path;
    private $name;
    private $requirements = array();
    private $options = array();
    private $defaults = array();
    private $host;
    private $methods = array();
    private $schemes = array();
    private $condition;

    /**
     * Constructor.
     *
     * @param array $data An array of key/value parameters.
     *
     * @throws \BadMethodCallException
     */
    public function __construct(array $data)
    {
        if (isset($data['value'])) {
            $data['path'] = $data['value'];
            unset($data['value']);
        }

        foreach ($data as $key => $value) {
            $method = 'set'.str_replace('_', '', $key);
            if (!method_exists($this, $method)) {
                throw new \BadMethodCallException(sprintf("Unknown property '%s' on annotation '%s'.", $key, get_class($this)));
            }
            $this->$method($value);
        }
    }

    /**
     * @deprecated Deprecated in 2.2, to be removed in 3.0. Use setPath instead.
     */
    public function setPattern($pattern)
    {
        $this->path = $pattern;
    }

    /**
     * @deprecated Deprecated in 2.2, to be removed in 3.0. Use getPath instead.
     */
    public function getPattern()
    {
        return $this->path;
    }

    public function setPath($path)
    {
        $this->path = $path;
    }

    public function getPath()
    {
        return $this->path;
    }

    public function setHost($pattern)
    {
        $this->host = $pattern;
    }

    public function getHost()
    {
        return $this->host;
    }

    public function setName($name)
    {
        $this->name = $name;
    }

    public function getName()
    {
        return $this->name;
    }

    public function setRequirements($requirements)
    {
        $this->requirements = $requirements;
    }

    public function getRequirements()
    {
        return $this->requirements;
    }

    public function setOptions($options)
    {
        $this->options = $options;
    }

    public function getOptions()
    {
        return $this->options;
    }

    public function setDefaults($defaults)
    {
        $this->defaults = $defaults;
    }

    public function getDefaults()
    {
        return $this->defaults;
    }

    public function setSchemes($schemes)
    {
        $this->schemes = is_array($schemes) ? $schemes : array($schemes);
    }

    public function getSchemes()
    {
        return $this->schemes;
    }

    public function setMethods($methods)
    {
        $this->methods = is_array($methods) ? $methods : array($methods);
    }

    public function getMethods()
    {
        return $this->methods;
    }

    public function setCondition($condition)
    {
        $this->condition = $condition;
    }

    public function getCondition()
    {
        return $this->condition;
    }
}
PKw�Z�<ѹ�+Symfony/Component/Routing/CompiledRoute.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing;

/**
 * CompiledRoutes are returned by the RouteCompiler class.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class CompiledRoute
{
    private $variables;
    private $tokens;
    private $staticPrefix;
    private $regex;
    private $pathVariables;
    private $hostVariables;
    private $hostRegex;
    private $hostTokens;

    /**
     * Constructor.
     *
     * @param string      $staticPrefix       The static prefix of the compiled route
     * @param string      $regex              The regular expression to use to match this route
     * @param array       $tokens             An array of tokens to use to generate URL for this route
     * @param array       $pathVariables      An array of path variables
     * @param string|null $hostRegex          Host regex
     * @param array       $hostTokens         Host tokens
     * @param array       $hostVariables      An array of host variables
     * @param array       $variables          An array of variables (variables defined in the path and in the host patterns)
     */
    public function __construct($staticPrefix, $regex, array $tokens, array $pathVariables, $hostRegex = null, array $hostTokens = array(), array $hostVariables = array(), array $variables = array())
    {
        $this->staticPrefix = (string) $staticPrefix;
        $this->regex = $regex;
        $this->tokens = $tokens;
        $this->pathVariables = $pathVariables;
        $this->hostRegex = $hostRegex;
        $this->hostTokens = $hostTokens;
        $this->hostVariables = $hostVariables;
        $this->variables = $variables;
    }

    /**
     * Returns the static prefix.
     *
     * @return string The static prefix
     */
    public function getStaticPrefix()
    {
        return $this->staticPrefix;
    }

    /**
     * Returns the regex.
     *
     * @return string The regex
     */
    public function getRegex()
    {
        return $this->regex;
    }

    /**
     * Returns the host regex
     *
     * @return string|null The host regex or null
     */
    public function getHostRegex()
    {
        return $this->hostRegex;
    }

    /**
     * Returns the tokens.
     *
     * @return array The tokens
     */
    public function getTokens()
    {
        return $this->tokens;
    }

    /**
     * Returns the host tokens.
     *
     * @return array The tokens
     */
    public function getHostTokens()
    {
        return $this->hostTokens;
    }

    /**
     * Returns the variables.
     *
     * @return array The variables
     */
    public function getVariables()
    {
        return $this->variables;
    }

    /**
     * Returns the path variables.
     *
     * @return array The variables
     */
    public function getPathVariables()
    {
        return $this->pathVariables;
    }

    /**
     * Returns the host variables.
     *
     * @return array The variables
     */
    public function getHostVariables()
    {
        return $this->hostVariables;
    }

}
PKw�ZU8���-Symfony/Component/Routing/RouterInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing;

use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\Matcher\UrlMatcherInterface;

/**
 * RouterInterface is the interface that all Router classes must implement.
 *
 * This interface is the concatenation of UrlMatcherInterface and UrlGeneratorInterface.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface RouterInterface extends UrlMatcherInterface, UrlGeneratorInterface
{
    /**
     * Gets the RouteCollection instance associated with this Router.
     *
     * @return RouteCollection A RouteCollection instance
     */
    public function getRouteCollection();
}
PKw�ZU�cQQ(Symfony/Component/Routing/autoloader.phpnu�[���<?php

spl_autoload_register(function ($class) {
    if ('\\' == $class[0]) {
        $class = substr($class, 1);
    }

    if (
        0 === strpos($class, 'Symfony\\Component\\Routing\\')
        &&
        file_exists($file = __DIR__.'/../../../'.str_replace('\\', '/', $class).'.php')
    ) {
        require_once $file;
    }
});
PKw�Z����'�'+Symfony/Component/Routing/RouteCompiler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing;

/**
 * RouteCompiler compiles Route instances to CompiledRoute instances.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Tobias Schultze <http://tobion.de>
 */
class RouteCompiler implements RouteCompilerInterface
{
    const REGEX_DELIMITER = '#';

    /**
     * This string defines the characters that are automatically considered separators in front of
     * optional placeholders (with default and no static text following). Such a single separator
     * can be left out together with the optional placeholder from matching and generating URLs.
     */
    const SEPARATORS = '/,;.:-_~+*=@|';

    /**
     * {@inheritDoc}
     *
     * @throws \LogicException  If a variable is referenced more than once
     * @throws \DomainException If a variable name is numeric because PHP raises an error for such
     *                          subpatterns in PCRE and thus would break matching, e.g. "(?P<123>.+)".
     */
    public static function compile(Route $route)
    {
        $staticPrefix = null;
        $hostVariables = array();
        $pathVariables = array();
        $variables = array();
        $tokens = array();
        $regex = null;
        $hostRegex = null;
        $hostTokens = array();

        if ('' !== $host = $route->getHost()) {
            $result = self::compilePattern($route, $host, true);

            $hostVariables = $result['variables'];
            $variables = array_merge($variables, $hostVariables);

            $hostTokens = $result['tokens'];
            $hostRegex = $result['regex'];
        }

        $path = $route->getPath();

        $result = self::compilePattern($route, $path, false);

        $staticPrefix = $result['staticPrefix'];

        $pathVariables = $result['variables'];
        $variables = array_merge($variables, $pathVariables);

        $tokens = $result['tokens'];
        $regex = $result['regex'];

        return new CompiledRoute(
            $staticPrefix,
            $regex,
            $tokens,
            $pathVariables,
            $hostRegex,
            $hostTokens,
            $hostVariables,
            array_unique($variables)
        );
    }

    private static function compilePattern(Route $route, $pattern, $isHost)
    {
        $tokens = array();
        $variables = array();
        $matches = array();
        $pos = 0;
        $defaultSeparator = $isHost ? '.' : '/';

        // Match all variables enclosed in "{}" and iterate over them. But we only want to match the innermost variable
        // in case of nested "{}", e.g. {foo{bar}}. This in ensured because \w does not match "{" or "}" itself.
        preg_match_all('#\{\w+\}#', $pattern, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
        foreach ($matches as $match) {
            $varName = substr($match[0][0], 1, -1);
            // get all static text preceding the current variable
            $precedingText = substr($pattern, $pos, $match[0][1] - $pos);
            $pos = $match[0][1] + strlen($match[0][0]);
            $precedingChar = strlen($precedingText) > 0 ? substr($precedingText, -1) : '';
            $isSeparator = '' !== $precedingChar && false !== strpos(static::SEPARATORS, $precedingChar);

            if (is_numeric($varName)) {
                throw new \DomainException(sprintf('Variable name "%s" cannot be numeric in route pattern "%s". Please use a different name.', $varName, $pattern));
            }
            if (in_array($varName, $variables)) {
                throw new \LogicException(sprintf('Route pattern "%s" cannot reference variable name "%s" more than once.', $pattern, $varName));
            }

            if ($isSeparator && strlen($precedingText) > 1) {
                $tokens[] = array('text', substr($precedingText, 0, -1));
            } elseif (!$isSeparator && strlen($precedingText) > 0) {
                $tokens[] = array('text', $precedingText);
            }

            $regexp = $route->getRequirement($varName);
            if (null === $regexp) {
                $followingPattern = (string) substr($pattern, $pos);
                // Find the next static character after the variable that functions as a separator. By default, this separator and '/'
                // are disallowed for the variable. This default requirement makes sure that optional variables can be matched at all
                // and that the generating-matching-combination of URLs unambiguous, i.e. the params used for generating the URL are
                // the same that will be matched. Example: new Route('/{page}.{_format}', array('_format' => 'html'))
                // If {page} would also match the separating dot, {_format} would never match as {page} will eagerly consume everything.
                // Also even if {_format} was not optional the requirement prevents that {page} matches something that was originally
                // part of {_format} when generating the URL, e.g. _format = 'mobile.html'.
                $nextSeparator = self::findNextSeparator($followingPattern);
                $regexp = sprintf(
                    '[^%s%s]+',
                    preg_quote($defaultSeparator, self::REGEX_DELIMITER),
                    $defaultSeparator !== $nextSeparator && '' !== $nextSeparator ? preg_quote($nextSeparator, self::REGEX_DELIMITER) : ''
                );
                if (('' !== $nextSeparator && !preg_match('#^\{\w+\}#', $followingPattern)) || '' === $followingPattern) {
                    // When we have a separator, which is disallowed for the variable, we can optimize the regex with a possessive
                    // quantifier. This prevents useless backtracking of PCRE and improves performance by 20% for matching those patterns.
                    // Given the above example, there is no point in backtracking into {page} (that forbids the dot) when a dot must follow
                    // after it. This optimization cannot be applied when the next char is no real separator or when the next variable is
                    // directly adjacent, e.g. '/{x}{y}'.
                    $regexp .= '+';
                }
            }

            $tokens[] = array('variable', $isSeparator ? $precedingChar : '', $regexp, $varName);
            $variables[] = $varName;
        }

        if ($pos < strlen($pattern)) {
            $tokens[] = array('text', substr($pattern, $pos));
        }

        // find the first optional token
        $firstOptional = PHP_INT_MAX;
        if (!$isHost) {
            for ($i = count($tokens) - 1; $i >= 0; $i--) {
                $token = $tokens[$i];
                if ('variable' === $token[0] && $route->hasDefault($token[3])) {
                    $firstOptional = $i;
                } else {
                    break;
                }
            }
        }

        // compute the matching regexp
        $regexp = '';
        for ($i = 0, $nbToken = count($tokens); $i < $nbToken; $i++) {
            $regexp .= self::computeRegexp($tokens, $i, $firstOptional);
        }

        return array(
            'staticPrefix' => 'text' === $tokens[0][0] ? $tokens[0][1] : '',
            'regex' => self::REGEX_DELIMITER.'^'.$regexp.'$'.self::REGEX_DELIMITER.'s',
            'tokens' => array_reverse($tokens),
            'variables' => $variables,
        );
    }

    /**
     * Returns the next static character in the Route pattern that will serve as a separator.
     *
     * @param string $pattern The route pattern
     *
     * @return string The next static character that functions as separator (or empty string when none available)
     */
    private static function findNextSeparator($pattern)
    {
        if ('' == $pattern) {
            // return empty string if pattern is empty or false (false which can be returned by substr)
            return '';
        }
        // first remove all placeholders from the pattern so we can find the next real static character
        $pattern = preg_replace('#\{\w+\}#', '', $pattern);

        return isset($pattern[0]) && false !== strpos(static::SEPARATORS, $pattern[0]) ? $pattern[0] : '';
    }

    /**
     * Computes the regexp used to match a specific token. It can be static text or a subpattern.
     *
     * @param array   $tokens        The route tokens
     * @param integer $index         The index of the current token
     * @param integer $firstOptional The index of the first optional token
     *
     * @return string The regexp pattern for a single token
     */
    private static function computeRegexp(array $tokens, $index, $firstOptional)
    {
        $token = $tokens[$index];
        if ('text' === $token[0]) {
            // Text tokens
            return preg_quote($token[1], self::REGEX_DELIMITER);
        } else {
            // Variable tokens
            if (0 === $index && 0 === $firstOptional) {
                // When the only token is an optional variable token, the separator is required
                return sprintf('%s(?P<%s>%s)?', preg_quote($token[1], self::REGEX_DELIMITER), $token[3], $token[2]);
            } else {
                $regexp = sprintf('%s(?P<%s>%s)', preg_quote($token[1], self::REGEX_DELIMITER), $token[3], $token[2]);
                if ($index >= $firstOptional) {
                    // Enclose each optional token in a subpattern to make it optional.
                    // "?:" means it is non-capturing, i.e. the portion of the subject string that
                    // matched the optional subpattern is not passed back.
                    $regexp = "(?:$regexp";
                    $nbTokens = count($tokens);
                    if ($nbTokens - 1 == $index) {
                        // Close the optional subpatterns
                        $regexp .= str_repeat(")?", $nbTokens - $firstOptional - (0 === $firstOptional ? 1 : 0));
                    }
                }

                return $regexp;
            }
        }
    }
}
PKw�Z��%�%$Symfony/Component/Routing/Router.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing;

use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\Config\ConfigCache;
use Psr\Log\LoggerInterface;
use Symfony\Component\Routing\Generator\ConfigurableRequirementsInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\Generator\Dumper\GeneratorDumperInterface;
use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
use Symfony\Component\Routing\Matcher\Dumper\MatcherDumperInterface;
use Symfony\Component\HttpFoundation\Request;

/**
 * The Router class is an example of the integration of all pieces of the
 * routing system for easier use.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Router implements RouterInterface, RequestMatcherInterface
{
    /**
     * @var UrlMatcherInterface|null
     */
    protected $matcher;

    /**
     * @var UrlGeneratorInterface|null
     */
    protected $generator;

    /**
     * @var RequestContext
     */
    protected $context;

    /**
     * @var LoaderInterface
     */
    protected $loader;

    /**
     * @var RouteCollection|null
     */
    protected $collection;

    /**
     * @var mixed
     */
    protected $resource;

    /**
     * @var array
     */
    protected $options = array();

    /**
     * @var LoggerInterface|null
     */
    protected $logger;

    /**
     * Constructor.
     *
     * @param LoaderInterface $loader   A LoaderInterface instance
     * @param mixed           $resource The main resource to load
     * @param array           $options  An array of options
     * @param RequestContext  $context  The context
     * @param LoggerInterface $logger   A logger instance
     */
    public function __construct(LoaderInterface $loader, $resource, array $options = array(), RequestContext $context = null, LoggerInterface $logger = null)
    {
        $this->loader = $loader;
        $this->resource = $resource;
        $this->logger = $logger;
        $this->context = $context ?: new RequestContext();
        $this->setOptions($options);
    }

    /**
     * Sets options.
     *
     * Available options:
     *
     *   * cache_dir:     The cache directory (or null to disable caching)
     *   * debug:         Whether to enable debugging or not (false by default)
     *   * resource_type: Type hint for the main resource (optional)
     *
     * @param array $options An array of options
     *
     * @throws \InvalidArgumentException When unsupported option is provided
     */
    public function setOptions(array $options)
    {
        $this->options = array(
            'cache_dir'              => null,
            'debug'                  => false,
            'generator_class'        => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator',
            'generator_base_class'   => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator',
            'generator_dumper_class' => 'Symfony\\Component\\Routing\\Generator\\Dumper\\PhpGeneratorDumper',
            'generator_cache_class'  => 'ProjectUrlGenerator',
            'matcher_class'          => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher',
            'matcher_base_class'     => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher',
            'matcher_dumper_class'   => 'Symfony\\Component\\Routing\\Matcher\\Dumper\\PhpMatcherDumper',
            'matcher_cache_class'    => 'ProjectUrlMatcher',
            'resource_type'          => null,
            'strict_requirements'    => true,
        );

        // check option names and live merge, if errors are encountered Exception will be thrown
        $invalid = array();
        foreach ($options as $key => $value) {
            if (array_key_exists($key, $this->options)) {
                $this->options[$key] = $value;
            } else {
                $invalid[] = $key;
            }
        }

        if ($invalid) {
            throw new \InvalidArgumentException(sprintf('The Router does not support the following options: "%s".', implode('", "', $invalid)));
        }
    }

    /**
     * Sets an option.
     *
     * @param string $key   The key
     * @param mixed  $value The value
     *
     * @throws \InvalidArgumentException
     */
    public function setOption($key, $value)
    {
        if (!array_key_exists($key, $this->options)) {
            throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key));
        }

        $this->options[$key] = $value;
    }

    /**
     * Gets an option value.
     *
     * @param string $key The key
     *
     * @return mixed The value
     *
     * @throws \InvalidArgumentException
     */
    public function getOption($key)
    {
        if (!array_key_exists($key, $this->options)) {
            throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key));
        }

        return $this->options[$key];
    }

    /**
     * {@inheritdoc}
     */
    public function getRouteCollection()
    {
        if (null === $this->collection) {
            $this->collection = $this->loader->load($this->resource, $this->options['resource_type']);
        }

        return $this->collection;
    }

    /**
     * {@inheritdoc}
     */
    public function setContext(RequestContext $context)
    {
        $this->context = $context;

        if (null !== $this->matcher) {
            $this->getMatcher()->setContext($context);
        }
        if (null !== $this->generator) {
            $this->getGenerator()->setContext($context);
        }
    }

    /**
     * {@inheritdoc}
     */
    public function getContext()
    {
        return $this->context;
    }

    /**
     * {@inheritdoc}
     */
    public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH)
    {
        return $this->getGenerator()->generate($name, $parameters, $referenceType);
    }

    /**
     * {@inheritdoc}
     */
    public function match($pathinfo)
    {
        return $this->getMatcher()->match($pathinfo);
    }

    /**
     * {@inheritdoc}
     */
    public function matchRequest(Request $request)
    {
        $matcher = $this->getMatcher();
        if (!$matcher instanceof RequestMatcherInterface) {
            // fallback to the default UrlMatcherInterface
            return $matcher->match($request->getPathInfo());
        }

        return $matcher->matchRequest($request);
    }

    /**
     * Gets the UrlMatcher instance associated with this Router.
     *
     * @return UrlMatcherInterface A UrlMatcherInterface instance
     */
    public function getMatcher()
    {
        if (null !== $this->matcher) {
            return $this->matcher;
        }

        if (null === $this->options['cache_dir'] || null === $this->options['matcher_cache_class']) {
            return $this->matcher = new $this->options['matcher_class']($this->getRouteCollection(), $this->context);
        }

        $class = $this->options['matcher_cache_class'];
        $cache = new ConfigCache($this->options['cache_dir'].'/'.$class.'.php', $this->options['debug']);
        if (!$cache->isFresh()) {
            $dumper = $this->getMatcherDumperInstance();

            $options = array(
                'class'      => $class,
                'base_class' => $this->options['matcher_base_class'],
            );

            $cache->write($dumper->dump($options), $this->getRouteCollection()->getResources());
        }

        require_once $cache;

        return $this->matcher = new $class($this->context);
    }

    /**
     * Gets the UrlGenerator instance associated with this Router.
     *
     * @return UrlGeneratorInterface A UrlGeneratorInterface instance
     */
    public function getGenerator()
    {
        if (null !== $this->generator) {
            return $this->generator;
        }

        if (null === $this->options['cache_dir'] || null === $this->options['generator_cache_class']) {
            $this->generator = new $this->options['generator_class']($this->getRouteCollection(), $this->context, $this->logger);
        } else {
            $class = $this->options['generator_cache_class'];
            $cache = new ConfigCache($this->options['cache_dir'].'/'.$class.'.php', $this->options['debug']);
            if (!$cache->isFresh()) {
                $dumper = $this->getGeneratorDumperInstance();

                $options = array(
                    'class'      => $class,
                    'base_class' => $this->options['generator_base_class'],
                );

                $cache->write($dumper->dump($options), $this->getRouteCollection()->getResources());
            }

            require_once $cache;

            $this->generator = new $class($this->context, $this->logger);
        }

        if ($this->generator instanceof ConfigurableRequirementsInterface) {
            $this->generator->setStrictRequirements($this->options['strict_requirements']);
        }

        return $this->generator;
    }

    /**
     * @return GeneratorDumperInterface
     */
    protected function getGeneratorDumperInstance()
    {
        return new $this->options['generator_dumper_class']($this->getRouteCollection());
    }

    /**
     * @return MatcherDumperInterface
     */
    protected function getMatcherDumperInstance()
    {
        return new $this->options['matcher_dumper_class']($this->getRouteCollection());
    }
}
PKw�Z���q
q
6Symfony/Component/Routing/Matcher/ApacheUrlMatcher.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Matcher;

use Symfony\Component\Routing\Exception\MethodNotAllowedException;

/**
 * ApacheUrlMatcher matches URL based on Apache mod_rewrite matching (see ApacheMatcherDumper).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Arnaud Le Blanc <arnaud.lb@gmail.com>
 */
class ApacheUrlMatcher extends UrlMatcher
{
    /**
     * Tries to match a URL based on Apache mod_rewrite matching.
     *
     * Returns false if no route matches the URL.
     *
     * @param string $pathinfo The pathinfo to be parsed
     *
     * @return array An array of parameters
     *
     * @throws MethodNotAllowedException If the current method is not allowed
     */
    public function match($pathinfo)
    {
        $parameters = array();
        $defaults = array();
        $allow = array();
        $route = null;

        foreach ($this->denormalizeValues($_SERVER) as $key => $value) {
            $name = $key;

            // skip non-routing variables
            // this improves performance when $_SERVER contains many usual
            // variables like HTTP_*, DOCUMENT_ROOT, REQUEST_URI, ...
            if (false === strpos($name, '_ROUTING_')) {
                continue;
            }

            while (0 === strpos($name, 'REDIRECT_')) {
                $name = substr($name, 9);
            }

            // expect _ROUTING_<type>_<name>
            // or _ROUTING_<type>

            if (0 !== strpos($name, '_ROUTING_')) {
                continue;
            }
            if (false !== $pos = strpos($name, '_', 9)) {
                $type = substr($name, 9, $pos-9);
                $name = substr($name, $pos+1);
            } else {
                $type = substr($name, 9);
            }

            if ('param' === $type) {
                if ('' !== $value) {
                    $parameters[$name] = $value;
                }
            } elseif ('default' === $type) {
                $defaults[$name] = $value;
            } elseif ('route' === $type) {
                $route = $value;
            } elseif ('allow' === $type) {
                $allow[] = $name;
            }

            unset($_SERVER[$key]);
        }

        if (null !== $route) {
            $parameters['_route'] = $route;

            return $this->mergeDefaults($parameters, $defaults);
        } elseif (0 < count($allow)) {
            throw new MethodNotAllowedException($allow);
        } else {
            return parent::match($pathinfo);
        }
    }

    /**
     * Denormalizes an array of values.
     *
     * @param string[] $values
     *
     * @return array
     */
    private function denormalizeValues(array $values)
    {
        $normalizedValues = array();
        foreach ($values as $key => $value) {
            if (preg_match('~^(.*)\[(\d+)\]$~', $key, $matches)) {
                if (!isset($normalizedValues[$matches[1]])) {
                    $normalizedValues[$matches[1]] = array();
                }
                $normalizedValues[$matches[1]][(int) $matches[2]] = $value;
            } else {
                $normalizedValues[$key] = $value;
            }
        }

        return $normalizedValues;
    }
}
PKw�Z	�ڗ9Symfony/Component/Routing/Matcher/UrlMatcherInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Matcher;

use Symfony\Component\Routing\RequestContextAwareInterface;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\Exception\MethodNotAllowedException;

/**
 * UrlMatcherInterface is the interface that all URL matcher classes must implement.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface UrlMatcherInterface extends RequestContextAwareInterface
{
    /**
     * Tries to match a URL path with a set of routes.
     *
     * If the matcher can not find information, it must throw one of the exceptions documented
     * below.
     *
     * @param string $pathinfo The path info to be parsed (raw format, i.e. not urldecoded)
     *
     * @return array An array of parameters
     *
     * @throws ResourceNotFoundException If the resource could not be found
     * @throws MethodNotAllowedException If the resource was found but the request method is not allowed
     *
     * @api
     */
    public function match($pathinfo);
}
PKw�Z`�u���=Symfony/Component/Routing/Matcher/RequestMatcherInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Matcher;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\Exception\MethodNotAllowedException;

/**
 * RequestMatcherInterface is the interface that all request matcher classes must implement.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface RequestMatcherInterface
{
    /**
     * Tries to match a request with a set of routes.
     *
     * If the matcher can not find information, it must throw one of the exceptions documented
     * below.
     *
     * @param Request $request The request to match
     *
     * @return array An array of parameters
     *
     * @throws ResourceNotFoundException If no matching resource could be found
     * @throws MethodNotAllowedException If a matching resource was found but the request method is not allowed
     */
    public function matchRequest(Request $request);
}
PKw�Z[z�dd<Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Matcher;

use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\Route;

/**
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
abstract class RedirectableUrlMatcher extends UrlMatcher implements RedirectableUrlMatcherInterface
{
    /**
     * {@inheritdoc}
     */
    public function match($pathinfo)
    {
        try {
            $parameters = parent::match($pathinfo);
        } catch (ResourceNotFoundException $e) {
            if ('/' === substr($pathinfo, -1) || !in_array($this->context->getMethod(), array('HEAD', 'GET'))) {
                throw $e;
            }

            try {
                parent::match($pathinfo.'/');

                return $this->redirect($pathinfo.'/', null);
            } catch (ResourceNotFoundException $e2) {
                throw $e;
            }
        }

        return $parameters;
    }

    /**
     * {@inheritDoc}
     */
    protected function handleRouteRequirements($pathinfo, $name, Route $route)
    {
        // expression condition
        if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request))) {
            return array(self::REQUIREMENT_MISMATCH, null);
        }

        // check HTTP scheme requirement
        $scheme = $route->getRequirement('_scheme');
        if ($scheme && $this->context->getScheme() !== $scheme) {
            return array(self::ROUTE_MATCH, $this->redirect($pathinfo, $name, $scheme));
        }

        return array(self::REQUIREMENT_MATCH, null);
    }
}
PKw�Z?�|{��:Symfony/Component/Routing/Matcher/Dumper/MatcherDumper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Matcher\Dumper;

use Symfony\Component\Routing\RouteCollection;

/**
 * MatcherDumper is the abstract class for all built-in matcher dumpers.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class MatcherDumper implements MatcherDumperInterface
{
    /**
     * @var RouteCollection
     */
    private $routes;

    /**
     * Constructor.
     *
     * @param RouteCollection $routes The RouteCollection to dump
     */
    public function __construct(RouteCollection $routes)
    {
        $this->routes = $routes;
    }

    /**
     * {@inheritdoc}
     */
    public function getRoutes()
    {
        return $this->routes;
    }
}
PKw�Z�x}�44=Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Matcher\Dumper;

use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;

/**
 * PhpMatcherDumper creates a PHP class able to match URLs for a given set of routes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Tobias Schultze <http://tobion.de>
 * @author Arnaud Le Blanc <arnaud.lb@gmail.com>
 */
class PhpMatcherDumper extends MatcherDumper
{
    private $expressionLanguage;

    /**
     * Dumps a set of routes to a PHP class.
     *
     * Available options:
     *
     *  * class:      The class name
     *  * base_class: The base class name
     *
     * @param array $options An array of options
     *
     * @return string A PHP class representing the matcher class
     */
    public function dump(array $options = array())
    {
        $options = array_replace(array(
            'class'      => 'ProjectUrlMatcher',
            'base_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher',
        ), $options);

        // trailing slash support is only enabled if we know how to redirect the user
        $interfaces = class_implements($options['base_class']);
        $supportsRedirections = isset($interfaces['Symfony\\Component\\Routing\\Matcher\\RedirectableUrlMatcherInterface']);

        return <<<EOF
<?php

use Symfony\Component\Routing\Exception\MethodNotAllowedException;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\RequestContext;

/**
 * {$options['class']}
 *
 * This class has been auto-generated
 * by the Symfony Routing Component.
 */
class {$options['class']} extends {$options['base_class']}
{
    /**
     * Constructor.
     */
    public function __construct(RequestContext \$context)
    {
        \$this->context = \$context;
    }

{$this->generateMatchMethod($supportsRedirections)}
}

EOF;
    }

    /**
     * Generates the code for the match method implementing UrlMatcherInterface.
     *
     * @param Boolean $supportsRedirections Whether redirections are supported by the base class
     *
     * @return string Match method as PHP code
     */
    private function generateMatchMethod($supportsRedirections)
    {
        $code = rtrim($this->compileRoutes($this->getRoutes(), $supportsRedirections), "\n");

        return <<<EOF
    public function match(\$pathinfo)
    {
        \$allow = array();
        \$pathinfo = rawurldecode(\$pathinfo);
        \$context = \$this->context;
        \$request = \$this->request;

$code

        throw 0 < count(\$allow) ? new MethodNotAllowedException(array_unique(\$allow)) : new ResourceNotFoundException();
    }
EOF;
    }

    /**
     * Generates PHP code to match a RouteCollection with all its routes.
     *
     * @param RouteCollection $routes               A RouteCollection instance
     * @param Boolean         $supportsRedirections Whether redirections are supported by the base class
     *
     * @return string PHP code
     */
    private function compileRoutes(RouteCollection $routes, $supportsRedirections)
    {
        $fetchedHost = false;

        $groups = $this->groupRoutesByHostRegex($routes);
        $code = '';

        foreach ($groups as $collection) {
            if (null !== $regex = $collection->getAttribute('host_regex')) {
                if (!$fetchedHost) {
                    $code .= "        \$host = \$this->context->getHost();\n\n";
                    $fetchedHost = true;
                }

                $code .= sprintf("        if (preg_match(%s, \$host, \$hostMatches)) {\n", var_export($regex, true));
            }

            $tree = $this->buildPrefixTree($collection);
            $groupCode = $this->compilePrefixRoutes($tree, $supportsRedirections);

            if (null !== $regex) {
                // apply extra indention at each line (except empty ones)
                $groupCode = preg_replace('/^.{2,}$/m', '    $0', $groupCode);
                $code .= $groupCode;
                $code .= "        }\n\n";
            } else {
                $code .= $groupCode;
            }
        }

        return $code;
    }

    /**
     * Generates PHP code recursively to match a tree of routes
     *
     * @param DumperPrefixCollection $collection           A DumperPrefixCollection instance
     * @param Boolean                $supportsRedirections Whether redirections are supported by the base class
     * @param string                 $parentPrefix         Prefix of the parent collection
     *
     * @return string PHP code
     */
    private function compilePrefixRoutes(DumperPrefixCollection $collection, $supportsRedirections, $parentPrefix = '')
    {
        $code = '';
        $prefix = $collection->getPrefix();
        $optimizable = 1 < strlen($prefix) && 1 < count($collection->all());
        $optimizedPrefix = $parentPrefix;

        if ($optimizable) {
            $optimizedPrefix = $prefix;

            $code .= sprintf("    if (0 === strpos(\$pathinfo, %s)) {\n", var_export($prefix, true));
        }

        foreach ($collection as $route) {
            if ($route instanceof DumperCollection) {
                $code .= $this->compilePrefixRoutes($route, $supportsRedirections, $optimizedPrefix);
            } else {
                $code .= $this->compileRoute($route->getRoute(), $route->getName(), $supportsRedirections, $optimizedPrefix)."\n";
            }
        }

        if ($optimizable) {
            $code .= "    }\n\n";
            // apply extra indention at each line (except empty ones)
            $code = preg_replace('/^.{2,}$/m', '    $0', $code);
        }

        return $code;
    }

    /**
     * Compiles a single Route to PHP code used to match it against the path info.
     *
     * @param Route       $route                A Route instance
     * @param string      $name                 The name of the Route
     * @param Boolean     $supportsRedirections Whether redirections are supported by the base class
     * @param string|null $parentPrefix         The prefix of the parent collection used to optimize the code
     *
     * @return string PHP code
     *
     * @throws \LogicException
     */
    private function compileRoute(Route $route, $name, $supportsRedirections, $parentPrefix = null)
    {
        $code = '';
        $compiledRoute = $route->compile();
        $conditions = array();
        $hasTrailingSlash = false;
        $matches = false;
        $hostMatches = false;
        $methods = array();

        if ($req = $route->getRequirement('_method')) {
            $methods = explode('|', strtoupper($req));
            // GET and HEAD are equivalent
            if (in_array('GET', $methods) && !in_array('HEAD', $methods)) {
                $methods[] = 'HEAD';
            }
        }

        $supportsTrailingSlash = $supportsRedirections && (!$methods || in_array('HEAD', $methods));

        if (!count($compiledRoute->getPathVariables()) && false !== preg_match('#^(.)\^(?P<url>.*?)\$\1#', $compiledRoute->getRegex(), $m)) {
            if ($supportsTrailingSlash && substr($m['url'], -1) === '/') {
                $conditions[] = sprintf("rtrim(\$pathinfo, '/') === %s", var_export(rtrim(str_replace('\\', '', $m['url']), '/'), true));
                $hasTrailingSlash = true;
            } else {
                $conditions[] = sprintf("\$pathinfo === %s", var_export(str_replace('\\', '', $m['url']), true));
            }
        } else {
            if ($compiledRoute->getStaticPrefix() && $compiledRoute->getStaticPrefix() !== $parentPrefix) {
                $conditions[] = sprintf("0 === strpos(\$pathinfo, %s)", var_export($compiledRoute->getStaticPrefix(), true));
            }

            $regex = $compiledRoute->getRegex();
            if ($supportsTrailingSlash && $pos = strpos($regex, '/$')) {
                $regex = substr($regex, 0, $pos).'/?$'.substr($regex, $pos + 2);
                $hasTrailingSlash = true;
            }
            $conditions[] = sprintf("preg_match(%s, \$pathinfo, \$matches)", var_export($regex, true));

            $matches = true;
        }

        if ($compiledRoute->getHostVariables()) {
            $hostMatches = true;
        }

        if ($route->getCondition()) {
            $conditions[] = $this->getExpressionLanguage()->compile($route->getCondition(), array('context', 'request'));
        }

        $conditions = implode(' && ', $conditions);

        $code .= <<<EOF
        // $name
        if ($conditions) {

EOF;

        $gotoname = 'not_'.preg_replace('/[^A-Za-z0-9_]/', '', $name);
        if ($methods) {
            if (1 === count($methods)) {
                $code .= <<<EOF
            if (\$this->context->getMethod() != '$methods[0]') {
                \$allow[] = '$methods[0]';
                goto $gotoname;
            }


EOF;
            } else {
                $methods = implode("', '", $methods);
                $code .= <<<EOF
            if (!in_array(\$this->context->getMethod(), array('$methods'))) {
                \$allow = array_merge(\$allow, array('$methods'));
                goto $gotoname;
            }


EOF;
            }
        }

        if ($hasTrailingSlash) {
            $code .= <<<EOF
            if (substr(\$pathinfo, -1) !== '/') {
                return \$this->redirect(\$pathinfo.'/', '$name');
            }


EOF;
        }

        if ($scheme = $route->getRequirement('_scheme')) {
            if (!$supportsRedirections) {
                throw new \LogicException('The "_scheme" requirement is only supported for URL matchers that implement RedirectableUrlMatcherInterface.');
            }

            $code .= <<<EOF
            if (\$this->context->getScheme() !== '$scheme') {
                return \$this->redirect(\$pathinfo, '$name', '$scheme');
            }


EOF;
        }

        // optimize parameters array
        if ($matches || $hostMatches) {
            $vars = array();
            if ($hostMatches) {
                $vars[] = '$hostMatches';
            }
            if ($matches) {
                $vars[] = '$matches';
            }
            $vars[] = "array('_route' => '$name')";

            $code .= sprintf("            return \$this->mergeDefaults(array_replace(%s), %s);\n"
                , implode(', ', $vars), str_replace("\n", '', var_export($route->getDefaults(), true)));

        } elseif ($route->getDefaults()) {
            $code .= sprintf("            return %s;\n", str_replace("\n", '', var_export(array_replace($route->getDefaults(), array('_route' => $name)), true)));
        } else {
            $code .= sprintf("            return array('_route' => '%s');\n", $name);
        }
        $code .= "        }\n";

        if ($methods) {
            $code .= "        $gotoname:\n";
        }

        return $code;
    }

    /**
     * Groups consecutive routes having the same host regex.
     *
     * The result is a collection of collections of routes having the same host regex.
     *
     * @param RouteCollection $routes A flat RouteCollection
     *
     * @return DumperCollection A collection with routes grouped by host regex in sub-collections
     */
    private function groupRoutesByHostRegex(RouteCollection $routes)
    {
        $groups = new DumperCollection();

        $currentGroup = new DumperCollection();
        $currentGroup->setAttribute('host_regex', null);
        $groups->add($currentGroup);

        foreach ($routes as $name => $route) {
            $hostRegex = $route->compile()->getHostRegex();
            if ($currentGroup->getAttribute('host_regex') !== $hostRegex) {
                $currentGroup = new DumperCollection();
                $currentGroup->setAttribute('host_regex', $hostRegex);
                $groups->add($currentGroup);
            }
            $currentGroup->add(new DumperRoute($name, $route));
        }

        return $groups;
    }

    /**
     * Organizes the routes into a prefix tree.
     *
     * Routes order is preserved such that traversing the tree will traverse the
     * routes in the origin order.
     *
     * @param DumperCollection $collection A collection of routes
     *
     * @return DumperPrefixCollection
     */
    private function buildPrefixTree(DumperCollection $collection)
    {
        $tree = new DumperPrefixCollection();
        $current = $tree;

        foreach ($collection as $route) {
            $current = $current->addPrefixRoute($route);
        }

        $tree->mergeSlashNodes();

        return $tree;
    }

    private function getExpressionLanguage()
    {
        if (null === $this->expressionLanguage) {
            if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
                throw new \RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
            }
            $this->expressionLanguage = new ExpressionLanguage();
        }

        return $this->expressionLanguage;
    }
}
PKw�Z�bz#z#@Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Matcher\Dumper;

use Symfony\Component\Routing\Route;

/**
 * Dumps a set of Apache mod_rewrite rules.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Kris Wallsmith <kris@symfony.com>
 */
class ApacheMatcherDumper extends MatcherDumper
{
    /**
     * Dumps a set of Apache mod_rewrite rules.
     *
     * Available options:
     *
     *  * script_name: The script name (app.php by default)
     *  * base_uri:    The base URI ("" by default)
     *
     * @param array $options An array of options
     *
     * @return string A string to be used as Apache rewrite rules
     *
     * @throws \LogicException When the route regex is invalid
     */
    public function dump(array $options = array())
    {
        $options = array_merge(array(
            'script_name' => 'app.php',
            'base_uri'    => '',
        ), $options);

        $options['script_name'] = self::escape($options['script_name'], ' ', '\\');

        $rules = array("# skip \"real\" requests\nRewriteCond %{REQUEST_FILENAME} -f\nRewriteRule .* - [QSA,L]");
        $methodVars = array();
        $hostRegexUnique = 0;
        $prevHostRegex = '';

        foreach ($this->getRoutes()->all() as $name => $route) {
            if ($route->getCondition()) {
                throw new \LogicException(sprintf('Unable to dump the routes for Apache as route "%s" has a condition.', $name));
            }

            $compiledRoute = $route->compile();
            $hostRegex = $compiledRoute->getHostRegex();

            if (null !== $hostRegex && $prevHostRegex !== $hostRegex) {
                $prevHostRegex = $hostRegex;
                $hostRegexUnique++;

                $rule = array();

                $regex = $this->regexToApacheRegex($hostRegex);
                $regex = self::escape($regex, ' ', '\\');

                $rule[] = sprintf('RewriteCond %%{HTTP:Host} %s', $regex);

                $variables = array();
                $variables[] = sprintf('E=__ROUTING_host_%s:1', $hostRegexUnique);

                foreach ($compiledRoute->getHostVariables() as $i => $variable) {
                    $variables[] = sprintf('E=__ROUTING_host_%s_%s:%%%d', $hostRegexUnique, $variable, $i+1);
                }

                $variables = implode(',', $variables);

                $rule[] = sprintf('RewriteRule .? - [%s]', $variables);

                $rules[] = implode("\n", $rule);
            }

            $rules[] = $this->dumpRoute($name, $route, $options, $hostRegexUnique);

            if ($req = $route->getRequirement('_method')) {
                $methods = explode('|', strtoupper($req));
                $methodVars = array_merge($methodVars, $methods);
            }
        }
        if (0 < count($methodVars)) {
            $rule = array('# 405 Method Not Allowed');
            $methodVars = array_values(array_unique($methodVars));
            if (in_array('GET', $methodVars) && !in_array('HEAD', $methodVars)) {
                $methodVars[] = 'HEAD';
            }
            foreach ($methodVars as $i => $methodVar) {
                $rule[] = sprintf('RewriteCond %%{ENV:_ROUTING__allow_%s} =1%s', $methodVar, isset($methodVars[$i + 1]) ? ' [OR]' : '');
            }
            $rule[] = sprintf('RewriteRule .* %s [QSA,L]', $options['script_name']);

            $rules[] = implode("\n", $rule);
        }

        return implode("\n\n", $rules)."\n";
    }

    /**
     * Dumps a single route
     *
     * @param  string $name Route name
     * @param  Route  $route The route
     * @param  array  $options Options
     * @param  bool   $hostRegexUnique Unique identifier for the host regex
     *
     * @return string The compiled route
     */
    private function dumpRoute($name, $route, array $options, $hostRegexUnique)
    {
        $compiledRoute = $route->compile();

        // prepare the apache regex
        $regex = $this->regexToApacheRegex($compiledRoute->getRegex());
        $regex = '^'.self::escape(preg_quote($options['base_uri']).substr($regex, 1), ' ', '\\');

        $methods = $this->getRouteMethods($route);

        $hasTrailingSlash = (!$methods || in_array('HEAD', $methods)) && '/$' === substr($regex, -2) && '^/$' !== $regex;

        $variables = array('E=_ROUTING_route:'.$name);
        foreach ($compiledRoute->getHostVariables() as $variable) {
            $variables[] = sprintf('E=_ROUTING_param_%s:%%{ENV:__ROUTING_host_%s_%s}', $variable, $hostRegexUnique, $variable);
        }
        foreach ($compiledRoute->getPathVariables() as $i => $variable) {
            $variables[] = 'E=_ROUTING_param_'.$variable.':%'.($i + 1);
        }
        foreach ($this->normalizeValues($route->getDefaults()) as $key => $value) {
            $variables[] = 'E=_ROUTING_default_'.$key.':'.strtr($value, array(
                ':'  => '\\:',
                '='  => '\\=',
                '\\' => '\\\\',
                ' '  => '\\ ',
            ));
        }
        $variables = implode(',', $variables);

        $rule = array("# $name");

        // method mismatch
        if (0 < count($methods)) {
            $allow = array();
            foreach ($methods as $method) {
                $allow[] = 'E=_ROUTING_allow_'.$method.':1';
            }

            if ($compiledRoute->getHostRegex()) {
                $rule[] = sprintf("RewriteCond %%{ENV:__ROUTING_host_%s} =1", $hostRegexUnique);
            }

            $rule[] = "RewriteCond %{REQUEST_URI} $regex";
            $rule[] = sprintf("RewriteCond %%{REQUEST_METHOD} !^(%s)$ [NC]", implode('|', $methods));
            $rule[] = sprintf('RewriteRule .* - [S=%d,%s]', $hasTrailingSlash ? 2 : 1, implode(',', $allow));
        }

        // redirect with trailing slash appended
        if ($hasTrailingSlash) {
            if ($compiledRoute->getHostRegex()) {
                $rule[] = sprintf("RewriteCond %%{ENV:__ROUTING_host_%s} =1", $hostRegexUnique);
            }

            $rule[] = 'RewriteCond %{REQUEST_URI} '.substr($regex, 0, -2).'$';
            $rule[] = 'RewriteRule .* $0/ [QSA,L,R=301]';
        }

        // the main rule

        if ($compiledRoute->getHostRegex()) {
            $rule[] = sprintf("RewriteCond %%{ENV:__ROUTING_host_%s} =1", $hostRegexUnique);
        }

        $rule[] = "RewriteCond %{REQUEST_URI} $regex";
        $rule[] = "RewriteRule .* {$options['script_name']} [QSA,L,$variables]";

        return implode("\n", $rule);
    }

    /**
     * Returns methods allowed for a route
     *
     * @param Route  $route The route
     *
     * @return array The methods
     */
    private function getRouteMethods(Route $route)
    {
        $methods = array();
        if ($req = $route->getRequirement('_method')) {
            $methods = explode('|', strtoupper($req));
            // GET and HEAD are equivalent
            if (in_array('GET', $methods) && !in_array('HEAD', $methods)) {
                $methods[] = 'HEAD';
            }
        }

        return $methods;
    }

    /**
     * Converts a regex to make it suitable for mod_rewrite
     *
     * @param string  $regex The regex
     *
     * @return string The converted regex
     */
    private function regexToApacheRegex($regex)
    {
        $regexPatternEnd = strrpos($regex, $regex[0]);

        return preg_replace('/\?P<.+?>/', '', substr($regex, 1, $regexPatternEnd - 1));
    }

    /**
     * Escapes a string.
     *
     * @param string $string The string to be escaped
     * @param string $char   The character to be escaped
     * @param string $with   The character to be used for escaping
     *
     * @return string The escaped string
     */
    private static function escape($string, $char, $with)
    {
        $escaped = false;
        $output = '';
        foreach (str_split($string) as $symbol) {
            if ($escaped) {
                $output .= $symbol;
                $escaped = false;
                continue;
            }
            if ($symbol === $char) {
                $output .= $with.$char;
                continue;
            }
            if ($symbol === $with) {
                $escaped = true;
            }
            $output .= $symbol;
        }

        return $output;
    }

    /**
     * Normalizes an array of values.
     *
     * @param array $values
     *
     * @return string[]
     */
    private function normalizeValues(array $values)
    {
        $normalizedValues = array();
        foreach ($values as $key => $value) {
            if (is_array($value)) {
                foreach ($value as $index => $bit) {
                    $normalizedValues[sprintf('%s[%s]', $key, $index)] = $bit;
                }
            } else {
                $normalizedValues[$key] = (string) $value;
            }
        }

        return $normalizedValues;
    }
}
PKw�Z�`=Symfony/Component/Routing/Matcher/Dumper/DumperCollection.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Matcher\Dumper;

/**
 * Collection of routes.
 *
 * @author Arnaud Le Blanc <arnaud.lb@gmail.com>
 */
class DumperCollection implements \IteratorAggregate
{
    /**
     * @var DumperCollection|null
     */
    private $parent;

    /**
     * @var (DumperCollection|DumperRoute)[]
     */
    private $children = array();

    /**
     * @var array
     */
    private $attributes = array();

    /**
     * Returns the children routes and collections.
     *
     * @return (DumperCollection|DumperRoute)[] Array of DumperCollection|DumperRoute
     */
    public function all()
    {
        return $this->children;
    }

    /**
     * Adds a route or collection
     *
     * @param DumperRoute|DumperCollection The route or collection
     */
    public function add($child)
    {
        if ($child instanceof DumperCollection) {
            $child->setParent($this);
        }
        $this->children[] = $child;
    }

    /**
     * Sets children.
     *
     * @param array $children The children
     */
    public function setAll(array $children)
    {
        foreach ($children as $child) {
            if ($child instanceof DumperCollection) {
                $child->setParent($this);
            }
        }
        $this->children = $children;
    }

    /**
     * Returns an iterator over the children.
     *
     * @return \Iterator The iterator
     */
    public function getIterator()
    {
        return new \ArrayIterator($this->children);
    }

    /**
     * Returns the root of the collection.
     *
     * @return DumperCollection The root collection
     */
    public function getRoot()
    {
        return (null !== $this->parent) ? $this->parent->getRoot() : $this;
    }

    /**
     * Returns the parent collection.
     *
     * @return DumperCollection|null The parent collection or null if the collection has no parent
     */
    protected function getParent()
    {
        return $this->parent;
    }

    /**
     * Sets the parent collection.
     *
     * @param DumperCollection $parent The parent collection
     */
    protected function setParent(DumperCollection $parent)
    {
        $this->parent = $parent;
    }

    /**
     * Returns true if the attribute is defined.
     *
     * @param string $name The attribute name
     *
     * @return Boolean true if the attribute is defined, false otherwise
     */
    public function hasAttribute($name)
    {
        return array_key_exists($name, $this->attributes);
    }

    /**
     * Returns an attribute by name.
     *
     * @param string $name    The attribute name
     * @param mixed  $default Default value is the attribute doesn't exist
     *
     * @return mixed The attribute value
     */
    public function getAttribute($name, $default = null)
    {
        return $this->hasAttribute($name) ? $this->attributes[$name] : $default;
    }

    /**
     * Sets an attribute by name.
     *
     * @param string $name  The attribute name
     * @param mixed  $value The attribute value
     */
    public function setAttribute($name, $value)
    {
        $this->attributes[$name] = $value;
    }

    /**
     * Sets multiple attributes.
     *
     * @param array $attributes The attributes
     */
    public function setAttributes($attributes)
    {
        $this->attributes = $attributes;
    }
}
PKw�Z�N�
�
CSymfony/Component/Routing/Matcher/Dumper/DumperPrefixCollection.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Matcher\Dumper;

/**
 * Prefix tree of routes preserving routes order.
 *
 * @author Arnaud Le Blanc <arnaud.lb@gmail.com>
 */
class DumperPrefixCollection extends DumperCollection
{
    /**
     * @var string
     */
    private $prefix = '';

    /**
     * Returns the prefix.
     *
     * @return string The prefix
     */
    public function getPrefix()
    {
        return $this->prefix;
    }

    /**
     * Sets the prefix.
     *
     * @param string $prefix The prefix
     */
    public function setPrefix($prefix)
    {
        $this->prefix = $prefix;
    }

    /**
     * Adds a route in the tree.
     *
     * @param DumperRoute $route The route
     *
     * @return DumperPrefixCollection The node the route was added to
     *
     * @throws \LogicException
     */
    public function addPrefixRoute(DumperRoute $route)
    {
        $prefix = $route->getRoute()->compile()->getStaticPrefix();

        for ($collection = $this; null !== $collection; $collection = $collection->getParent()) {

            // Same prefix, add to current leave
            if ($collection->prefix === $prefix) {
                $collection->add($route);

                return $collection;
            }

            // Prefix starts with route's prefix
            if ('' === $collection->prefix || 0 === strpos($prefix, $collection->prefix)) {
                $child = new DumperPrefixCollection();
                $child->setPrefix(substr($prefix, 0, strlen($collection->prefix)+1));
                $collection->add($child);

                return $child->addPrefixRoute($route);
            }
        }

        // Reached only if the root has a non empty prefix
        throw new \LogicException("The collection root must not have a prefix");
    }

    /**
     * Merges nodes whose prefix ends with a slash
     *
     * Children of a node whose prefix ends with a slash are moved to the parent node
     */
    public function mergeSlashNodes()
    {
        $children = array();

        foreach ($this as $child) {
            if ($child instanceof self) {
                $child->mergeSlashNodes();
                if ('/' === substr($child->prefix, -1)) {
                    $children = array_merge($children, $child->all());
                } else {
                    $children[] = $child;
                }
            } else {
                $children[] = $child;
            }
        }

        $this->setAll($children);
    }
}
PKw�Z(� ���CSymfony/Component/Routing/Matcher/Dumper/MatcherDumperInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Matcher\Dumper;

use Symfony\Component\Routing\RouteCollection;

/**
 * MatcherDumperInterface is the interface that all matcher dumper classes must implement.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface MatcherDumperInterface
{
    /**
     * Dumps a set of routes to a string representation of executable code
     * that can then be used to match a request against these routes.
     *
     * @param array $options An array of options
     *
     * @return string Executable code
     */
    public function dump(array $options = array());

    /**
     * Gets the routes to dump.
     *
     * @return RouteCollection A RouteCollection instance
     */
    public function getRoutes();
}
PKw�ZY�IWW8Symfony/Component/Routing/Matcher/Dumper/DumperRoute.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Matcher\Dumper;

use Symfony\Component\Routing\Route;

/**
 * Container for a Route.
 *
 * @author Arnaud Le Blanc <arnaud.lb@gmail.com>
 */
class DumperRoute
{
    /**
     * @var string
     */
    private $name;

    /**
     * @var Route
     */
    private $route;

    /**
     * Constructor.
     *
     * @param string $name  The route name
     * @param Route  $route The route
     */
    public function __construct($name, Route $route)
    {
        $this->name = $name;
        $this->route = $route;
    }

    /**
     * Returns the route name.
     *
     * @return string The route name
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Returns the route.
     *
     * @return Route The route
     */
    public function getRoute()
    {
        return $this->route;
    }
}
PKw�Z�'��9Symfony/Component/Routing/Matcher/TraceableUrlMatcher.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Matcher;

use Symfony\Component\Routing\Exception\ExceptionInterface;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;

/**
 * TraceableUrlMatcher helps debug path info matching by tracing the match.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class TraceableUrlMatcher extends UrlMatcher
{
    const ROUTE_DOES_NOT_MATCH = 0;
    const ROUTE_ALMOST_MATCHES = 1;
    const ROUTE_MATCHES        = 2;

    protected $traces;

    public function getTraces($pathinfo)
    {
        $this->traces = array();

        try {
            $this->match($pathinfo);
        } catch (ExceptionInterface $e) {
        }

        return $this->traces;
    }

    protected function matchCollection($pathinfo, RouteCollection $routes)
    {
        foreach ($routes as $name => $route) {
            $compiledRoute = $route->compile();

            if (!preg_match($compiledRoute->getRegex(), $pathinfo, $matches)) {
                // does it match without any requirements?
                $r = new Route($route->getPath(), $route->getDefaults(), array(), $route->getOptions());
                $cr = $r->compile();
                if (!preg_match($cr->getRegex(), $pathinfo)) {
                    $this->addTrace(sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route);

                    continue;
                }

                foreach ($route->getRequirements() as $n => $regex) {
                    $r = new Route($route->getPath(), $route->getDefaults(), array($n => $regex), $route->getOptions());
                    $cr = $r->compile();

                    if (in_array($n, $cr->getVariables()) && !preg_match($cr->getRegex(), $pathinfo)) {
                        $this->addTrace(sprintf('Requirement for "%s" does not match (%s)', $n, $regex), self::ROUTE_ALMOST_MATCHES, $name, $route);

                        continue 2;
                    }
                }

                continue;
            }

            // check host requirement
            $hostMatches = array();
            if ($compiledRoute->getHostRegex() && !preg_match($compiledRoute->getHostRegex(), $this->context->getHost(), $hostMatches)) {
                $this->addTrace(sprintf('Host "%s" does not match the requirement ("%s")', $this->context->getHost(), $route->getHost()), self::ROUTE_ALMOST_MATCHES, $name, $route);

                continue;
            }

            // check HTTP method requirement
            if ($req = $route->getRequirement('_method')) {
                // HEAD and GET are equivalent as per RFC
                if ('HEAD' === $method = $this->context->getMethod()) {
                    $method = 'GET';
                }

                if (!in_array($method, $req = explode('|', strtoupper($req)))) {
                    $this->allow = array_merge($this->allow, $req);

                    $this->addTrace(sprintf('Method "%s" does not match the requirement ("%s")', $this->context->getMethod(), implode(', ', $req)), self::ROUTE_ALMOST_MATCHES, $name, $route);

                    continue;
                }
            }

            // check condition
            if ($condition = $route->getCondition()) {
                if (!$this->getExpressionLanguage()->evaluate($condition, array('context' => $this->context, 'request' => $this->request))) {
                    $this->addTrace(sprintf('Condition "%s" does not evaluate to "true"', $condition), self::ROUTE_ALMOST_MATCHES, $name, $route);

                    continue;
                }
            }

            // check HTTP scheme requirement
            if ($scheme = $route->getRequirement('_scheme')) {
                if ($this->context->getScheme() !== $scheme) {
                    $this->addTrace(sprintf('Scheme "%s" does not match the requirement ("%s"); the user will be redirected', $this->context->getScheme(), $scheme), self::ROUTE_ALMOST_MATCHES, $name, $route);

                    return true;
                }
            }

            $this->addTrace('Route matches!', self::ROUTE_MATCHES, $name, $route);

            return true;
        }
    }

    private function addTrace($log, $level = self::ROUTE_DOES_NOT_MATCH, $name = null, $route = null)
    {
        $this->traces[] = array(
            'log'   => $log,
            'name'  => $name,
            'level' => $level,
            'path'  => null !== $route ? $route->getPath() : null,
        );
    }
}
PKw�ZGj�C""0Symfony/Component/Routing/Matcher/UrlMatcher.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Matcher;

use Symfony\Component\Routing\Exception\MethodNotAllowedException;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\Route;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;

/**
 * UrlMatcher matches URL based on a set of routes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
{
    const REQUIREMENT_MATCH     = 0;
    const REQUIREMENT_MISMATCH  = 1;
    const ROUTE_MATCH           = 2;

    /**
     * @var RequestContext
     */
    protected $context;

    /**
     * @var array
     */
    protected $allow = array();

    /**
     * @var RouteCollection
     */
    protected $routes;

    protected $request;
    protected $expressionLanguage;

    /**
     * Constructor.
     *
     * @param RouteCollection $routes  A RouteCollection instance
     * @param RequestContext  $context The context
     *
     * @api
     */
    public function __construct(RouteCollection $routes, RequestContext $context)
    {
        $this->routes = $routes;
        $this->context = $context;
    }

    /**
     * {@inheritdoc}
     */
    public function setContext(RequestContext $context)
    {
        $this->context = $context;
    }

    /**
     * {@inheritdoc}
     */
    public function getContext()
    {
        return $this->context;
    }

    /**
     * {@inheritdoc}
     */
    public function match($pathinfo)
    {
        $this->allow = array();

        if ($ret = $this->matchCollection(rawurldecode($pathinfo), $this->routes)) {
            return $ret;
        }

        throw 0 < count($this->allow)
            ? new MethodNotAllowedException(array_unique(array_map('strtoupper', $this->allow)))
            : new ResourceNotFoundException();
    }

    /**
     * {@inheritdoc}
     */
    public function matchRequest(Request $request)
    {
        $this->request = $request;

        $ret = $this->match($request->getPathInfo());

        $this->request = null;

        return $ret;
    }

    /**
     * Tries to match a URL with a set of routes.
     *
     * @param string          $pathinfo The path info to be parsed
     * @param RouteCollection $routes   The set of routes
     *
     * @return array An array of parameters
     *
     * @throws ResourceNotFoundException If the resource could not be found
     * @throws MethodNotAllowedException If the resource was found but the request method is not allowed
     */
    protected function matchCollection($pathinfo, RouteCollection $routes)
    {
        foreach ($routes as $name => $route) {
            $compiledRoute = $route->compile();

            // check the static prefix of the URL first. Only use the more expensive preg_match when it matches
            if ('' !== $compiledRoute->getStaticPrefix() && 0 !== strpos($pathinfo, $compiledRoute->getStaticPrefix())) {
                continue;
            }

            if (!preg_match($compiledRoute->getRegex(), $pathinfo, $matches)) {
                continue;
            }

            $hostMatches = array();
            if ($compiledRoute->getHostRegex() && !preg_match($compiledRoute->getHostRegex(), $this->context->getHost(), $hostMatches)) {
                continue;
            }

            // check HTTP method requirement
            if ($req = $route->getRequirement('_method')) {
                // HEAD and GET are equivalent as per RFC
                if ('HEAD' === $method = $this->context->getMethod()) {
                    $method = 'GET';
                }

                if (!in_array($method, $req = explode('|', strtoupper($req)))) {
                    $this->allow = array_merge($this->allow, $req);

                    continue;
                }
            }

            $status = $this->handleRouteRequirements($pathinfo, $name, $route);

            if (self::ROUTE_MATCH === $status[0]) {
                return $status[1];
            }

            if (self::REQUIREMENT_MISMATCH === $status[0]) {
                continue;
            }

            return $this->getAttributes($route, $name, array_replace($matches, $hostMatches));
        }
    }

    /**
     * Returns an array of values to use as request attributes.
     *
     * As this method requires the Route object, it is not available
     * in matchers that do not have access to the matched Route instance
     * (like the PHP and Apache matcher dumpers).
     *
     * @param Route  $route      The route we are matching against
     * @param string $name       The name of the route
     * @param array  $attributes An array of attributes from the matcher
     *
     * @return array An array of parameters
     */
    protected function getAttributes(Route $route, $name, array $attributes)
    {
        $attributes['_route'] = $name;

        return $this->mergeDefaults($attributes, $route->getDefaults());
    }

    /**
     * Handles specific route requirements.
     *
     * @param string $pathinfo The path
     * @param string $name     The route name
     * @param Route  $route    The route
     *
     * @return array The first element represents the status, the second contains additional information
     */
    protected function handleRouteRequirements($pathinfo, $name, Route $route)
    {
        // expression condition
        if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request))) {
            return array(self::REQUIREMENT_MISMATCH, null);
        }

        // check HTTP scheme requirement
        $scheme = $route->getRequirement('_scheme');
        $status = $scheme && $scheme !== $this->context->getScheme() ? self::REQUIREMENT_MISMATCH : self::REQUIREMENT_MATCH;

        return array($status, null);
    }

    /**
     * Get merged default parameters.
     *
     * @param array $params   The parameters
     * @param array $defaults The defaults
     *
     * @return array Merged default parameters
     */
    protected function mergeDefaults($params, $defaults)
    {
        foreach ($params as $key => $value) {
            if (!is_int($key)) {
                $defaults[$key] = $value;
            }
        }

        return $defaults;
    }

    protected function getExpressionLanguage()
    {
        if (null === $this->expressionLanguage) {
            if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
                throw new \RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
            }
            $this->expressionLanguage = new ExpressionLanguage();
        }

        return $this->expressionLanguage;
    }
}
PKw�Z� ��ffESymfony/Component/Routing/Matcher/RedirectableUrlMatcherInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Matcher;

/**
 * RedirectableUrlMatcherInterface knows how to redirect the user.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface RedirectableUrlMatcherInterface
{
    /**
     * Redirects the user to another URL.
     *
     * @param string      $path   The path info to redirect to.
     * @param string      $route  The route name that matched
     * @param string|null $scheme The URL scheme (null to keep the current one)
     *
     * @return array An array of parameters
     *
     * @api
     */
    public function redirect($path, $route, $scheme = null);
}
PKw�Z����==KSymfony/Component/Routing/Exception/MissingMandatoryParametersException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Exception;

/**
 * Exception thrown when a route cannot be generated because of missing
 * mandatory parameters.
 *
 * @author Alexandre Salomé <alexandre.salome@gmail.com>
 *
 * @api
 */
class MissingMandatoryParametersException extends \InvalidArgumentException implements ExceptionInterface
{
}
PKw�Zj`j�ASymfony/Component/Routing/Exception/InvalidParameterException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Exception;

/**
 * Exception thrown when a parameter is not valid
 *
 * @author Alexandre Salomé <alexandre.salome@gmail.com>
 *
 * @api
 */
class InvalidParameterException extends \InvalidArgumentException implements ExceptionInterface
{
}
PKw�Znj�W��>Symfony/Component/Routing/Exception/RouteNotFoundException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Exception;

/**
 * Exception thrown when a route does not exist
 *
 * @author Alexandre Salomé <alexandre.salome@gmail.com>
 *
 * @api
 */
class RouteNotFoundException extends \InvalidArgumentException implements ExceptionInterface
{
}
PKw�Z��)���:Symfony/Component/Routing/Exception/ExceptionInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Exception;

/**
 * ExceptionInterface
 *
 * @author Alexandre Salomé <alexandre.salome@gmail.com>
 *
 * @api
 */
interface ExceptionInterface
{
}
PKw�Z����JJASymfony/Component/Routing/Exception/MethodNotAllowedException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Exception;

/**
 * The resource was found but the request method is not allowed.
 *
 * This exception should trigger an HTTP 405 response in your application code.
 *
 * @author Kris Wallsmith <kris@symfony.com>
 *
 * @api
 */
class MethodNotAllowedException extends \RuntimeException implements ExceptionInterface
{
    /**
     * @var array
     */
    protected $allowedMethods = array();

    public function __construct(array $allowedMethods, $message = null, $code = 0, \Exception $previous = null)
    {
        $this->allowedMethods = array_map('strtoupper', $allowedMethods);

        parent::__construct($message, $code, $previous);
    }

    /**
     * Gets the allowed HTTP methods.
     *
     * @return array
     */
    public function getAllowedMethods()
    {
        return $this->allowedMethods;
    }
}
PKw�Z?�]�//ASymfony/Component/Routing/Exception/ResourceNotFoundException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Exception;

/**
 * The resource was not found.
 *
 * This exception should trigger an HTTP 404 response in your application code.
 *
 * @author Kris Wallsmith <kris@symfony.com>
 *
 * @api
 */
class ResourceNotFoundException extends \RuntimeException implements ExceptionInterface
{
}
PKw�Z��^�==#Symfony/Component/Routing/Route.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing;

/**
 * A Route describes a route and its parameters.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Tobias Schultze <http://tobion.de>
 *
 * @api
 */
class Route implements \Serializable
{
    /**
     * @var string
     */
    private $path = '/';

    /**
     * @var string
     */
    private $host = '';

    /**
     * @var array
     */
    private $schemes = array();

    /**
     * @var array
     */
    private $methods = array();

    /**
     * @var array
     */
    private $defaults = array();

    /**
     * @var array
     */
    private $requirements = array();

    /**
     * @var array
     */
    private $options = array();

    /**
     * @var null|CompiledRoute
     */
    private $compiled;

    private $condition;

    /**
     * Constructor.
     *
     * Available options:
     *
     *  * compiler_class: A class name able to compile this route instance (RouteCompiler by default)
     *
     * @param string       $path         The path pattern to match
     * @param array        $defaults     An array of default parameter values
     * @param array        $requirements An array of requirements for parameters (regexes)
     * @param array        $options      An array of options
     * @param string       $host         The host pattern to match
     * @param string|array $schemes      A required URI scheme or an array of restricted schemes
     * @param string|array $methods      A required HTTP method or an array of restricted methods
     * @param string       $condition    A condition that should evaluate to true for the route to match
     *
     * @api
     */
    public function __construct($path, array $defaults = array(), array $requirements = array(), array $options = array(), $host = '', $schemes = array(), $methods = array(), $condition = null)
    {
        $this->setPath($path);
        $this->setDefaults($defaults);
        $this->setRequirements($requirements);
        $this->setOptions($options);
        $this->setHost($host);
        // The conditions make sure that an initial empty $schemes/$methods does not override the corresponding requirement.
        // They can be removed when the BC layer is removed.
        if ($schemes) {
            $this->setSchemes($schemes);
        }
        if ($methods) {
            $this->setMethods($methods);
        }
        $this->setCondition($condition);
    }

    public function serialize()
    {
        return serialize(array(
            'path'         => $this->path,
            'host'         => $this->host,
            'defaults'     => $this->defaults,
            'requirements' => $this->requirements,
            'options'      => $this->options,
            'schemes'      => $this->schemes,
            'methods'      => $this->methods,
            'condition'    => $this->condition,
        ));
    }

    public function unserialize($data)
    {
        $data = unserialize($data);
        $this->path = $data['path'];
        $this->host = $data['host'];
        $this->defaults = $data['defaults'];
        $this->requirements = $data['requirements'];
        $this->options = $data['options'];
        $this->schemes = $data['schemes'];
        $this->methods = $data['methods'];
        $this->condition = $data['condition'];
    }

    /**
     * Returns the pattern for the path.
     *
     * @return string The pattern
     *
     * @deprecated Deprecated in 2.2, to be removed in 3.0. Use getPath instead.
     */
    public function getPattern()
    {
        return $this->path;
    }

    /**
     * Sets the pattern for the path.
     *
     * This method implements a fluent interface.
     *
     * @param string $pattern The path pattern
     *
     * @return Route The current Route instance
     *
     * @deprecated Deprecated in 2.2, to be removed in 3.0. Use setPath instead.
     */
    public function setPattern($pattern)
    {
        return $this->setPath($pattern);
    }

    /**
     * Returns the pattern for the path.
     *
     * @return string The path pattern
     */
    public function getPath()
    {
        return $this->path;
    }

    /**
     * Sets the pattern for the path.
     *
     * This method implements a fluent interface.
     *
     * @param string $pattern The path pattern
     *
     * @return Route The current Route instance
     */
    public function setPath($pattern)
    {
        // A pattern must start with a slash and must not have multiple slashes at the beginning because the
        // generated path for this route would be confused with a network path, e.g. '//domain.com/path'.
        $this->path = '/'.ltrim(trim($pattern), '/');
        $this->compiled = null;

        return $this;
    }

    /**
     * Returns the pattern for the host.
     *
     * @return string The host pattern
     */
    public function getHost()
    {
        return $this->host;
    }

    /**
     * Sets the pattern for the host.
     *
     * This method implements a fluent interface.
     *
     * @param string $pattern The host pattern
     *
     * @return Route The current Route instance
     */
    public function setHost($pattern)
    {
        $this->host = (string) $pattern;
        $this->compiled = null;

        return $this;
    }

    /**
     * Returns the lowercased schemes this route is restricted to.
     * So an empty array means that any scheme is allowed.
     *
     * @return array The schemes
     */
    public function getSchemes()
    {
        return $this->schemes;
    }

    /**
     * Sets the schemes (e.g. 'https') this route is restricted to.
     * So an empty array means that any scheme is allowed.
     *
     * This method implements a fluent interface.
     *
     * @param string|array $schemes The scheme or an array of schemes
     *
     * @return Route The current Route instance
     */
    public function setSchemes($schemes)
    {
        $this->schemes = array_map('strtolower', (array) $schemes);

        // this is to keep BC and will be removed in a future version
        if ($this->schemes) {
            $this->requirements['_scheme'] = implode('|', $this->schemes);
        } else {
            unset($this->requirements['_scheme']);
        }

        $this->compiled = null;

        return $this;
    }

    /**
     * Returns the uppercased HTTP methods this route is restricted to.
     * So an empty array means that any method is allowed.
     *
     * @return array The schemes
     */
    public function getMethods()
    {
        return $this->methods;
    }

    /**
     * Sets the HTTP methods (e.g. 'POST') this route is restricted to.
     * So an empty array means that any method is allowed.
     *
     * This method implements a fluent interface.
     *
     * @param string|array $methods The method or an array of methods
     *
     * @return Route The current Route instance
     */
    public function setMethods($methods)
    {
        $this->methods = array_map('strtoupper', (array) $methods);

        // this is to keep BC and will be removed in a future version
        if ($this->methods) {
            $this->requirements['_method'] = implode('|', $this->methods);
        } else {
            unset($this->requirements['_method']);
        }

        $this->compiled = null;

        return $this;
    }

    /**
     * Returns the options.
     *
     * @return array The options
     */
    public function getOptions()
    {
        return $this->options;
    }

    /**
     * Sets the options.
     *
     * This method implements a fluent interface.
     *
     * @param array $options The options
     *
     * @return Route The current Route instance
     */
    public function setOptions(array $options)
    {
        $this->options = array(
            'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler',
        );

        return $this->addOptions($options);
    }

    /**
     * Adds options.
     *
     * This method implements a fluent interface.
     *
     * @param array $options The options
     *
     * @return Route The current Route instance
     */
    public function addOptions(array $options)
    {
        foreach ($options as $name => $option) {
            $this->options[$name] = $option;
        }
        $this->compiled = null;

        return $this;
    }

    /**
     * Sets an option value.
     *
     * This method implements a fluent interface.
     *
     * @param string $name  An option name
     * @param mixed  $value The option value
     *
     * @return Route The current Route instance
     *
     * @api
     */
    public function setOption($name, $value)
    {
        $this->options[$name] = $value;
        $this->compiled = null;

        return $this;
    }

    /**
     * Get an option value.
     *
     * @param string $name An option name
     *
     * @return mixed The option value or null when not given
     */
    public function getOption($name)
    {
        return isset($this->options[$name]) ? $this->options[$name] : null;
    }

    /**
     * Checks if an option has been set
     *
     * @param string $name An option name
     *
     * @return Boolean true if the option is set, false otherwise
     */
    public function hasOption($name)
    {
        return array_key_exists($name, $this->options);
    }

    /**
     * Returns the defaults.
     *
     * @return array The defaults
     */
    public function getDefaults()
    {
        return $this->defaults;
    }

    /**
     * Sets the defaults.
     *
     * This method implements a fluent interface.
     *
     * @param array $defaults The defaults
     *
     * @return Route The current Route instance
     */
    public function setDefaults(array $defaults)
    {
        $this->defaults = array();

        return $this->addDefaults($defaults);
    }

    /**
     * Adds defaults.
     *
     * This method implements a fluent interface.
     *
     * @param array $defaults The defaults
     *
     * @return Route The current Route instance
     */
    public function addDefaults(array $defaults)
    {
        foreach ($defaults as $name => $default) {
            $this->defaults[$name] = $default;
        }
        $this->compiled = null;

        return $this;
    }

    /**
     * Gets a default value.
     *
     * @param string $name A variable name
     *
     * @return mixed The default value or null when not given
     */
    public function getDefault($name)
    {
        return isset($this->defaults[$name]) ? $this->defaults[$name] : null;
    }

    /**
     * Checks if a default value is set for the given variable.
     *
     * @param string $name A variable name
     *
     * @return Boolean true if the default value is set, false otherwise
     */
    public function hasDefault($name)
    {
        return array_key_exists($name, $this->defaults);
    }

    /**
     * Sets a default value.
     *
     * @param string $name    A variable name
     * @param mixed  $default The default value
     *
     * @return Route The current Route instance
     *
     * @api
     */
    public function setDefault($name, $default)
    {
        $this->defaults[$name] = $default;
        $this->compiled = null;

        return $this;
    }

    /**
     * Returns the requirements.
     *
     * @return array The requirements
     */
    public function getRequirements()
    {
        return $this->requirements;
    }

    /**
     * Sets the requirements.
     *
     * This method implements a fluent interface.
     *
     * @param array $requirements The requirements
     *
     * @return Route The current Route instance
     */
    public function setRequirements(array $requirements)
    {
        $this->requirements = array();

        return $this->addRequirements($requirements);
    }

    /**
     * Adds requirements.
     *
     * This method implements a fluent interface.
     *
     * @param array $requirements The requirements
     *
     * @return Route The current Route instance
     */
    public function addRequirements(array $requirements)
    {
        foreach ($requirements as $key => $regex) {
            $this->requirements[$key] = $this->sanitizeRequirement($key, $regex);
        }
        $this->compiled = null;

        return $this;
    }

    /**
     * Returns the requirement for the given key.
     *
     * @param string $key The key
     *
     * @return string|null The regex or null when not given
     */
    public function getRequirement($key)
    {
        return isset($this->requirements[$key]) ? $this->requirements[$key] : null;
    }

    /**
     * Checks if a requirement is set for the given key.
     *
     * @param string $key A variable name
     *
     * @return Boolean true if a requirement is specified, false otherwise
     */
    public function hasRequirement($key)
    {
        return array_key_exists($key, $this->requirements);
    }

    /**
     * Sets a requirement for the given key.
     *
     * @param string $key   The key
     * @param string $regex The regex
     *
     * @return Route The current Route instance
     *
     * @api
     */
    public function setRequirement($key, $regex)
    {
        $this->requirements[$key] = $this->sanitizeRequirement($key, $regex);
        $this->compiled = null;

        return $this;
    }

    /**
     * Returns the condition.
     *
     * @return string The condition
     */
    public function getCondition()
    {
        return $this->condition;
    }

    /**
     * Sets the condition.
     *
     * This method implements a fluent interface.
     *
     * @param string $condition The condition
     *
     * @return Route The current Route instance
     */
    public function setCondition($condition)
    {
        $this->condition = (string) $condition;
        $this->compiled = null;

        return $this;
    }

    /**
     * Compiles the route.
     *
     * @return CompiledRoute A CompiledRoute instance
     *
     * @throws \LogicException If the Route cannot be compiled because the
     *                         path or host pattern is invalid
     *
     * @see RouteCompiler which is responsible for the compilation process
     */
    public function compile()
    {
        if (null !== $this->compiled) {
            return $this->compiled;
        }

        $class = $this->getOption('compiler_class');

        return $this->compiled = $class::compile($this);
    }

    private function sanitizeRequirement($key, $regex)
    {
        if (!is_string($regex)) {
            throw new \InvalidArgumentException(sprintf('Routing requirement for "%s" must be a string.', $key));
        }

        if ('' !== $regex && '^' === $regex[0]) {
            $regex = (string) substr($regex, 1); // returns false for a single character
        }

        if ('$' === substr($regex, -1)) {
            $regex = substr($regex, 0, -1);
        }

        if ('' === $regex) {
            throw new \InvalidArgumentException(sprintf('Routing requirement for "%s" cannot be empty.', $key));
        }

        // this is to keep BC and will be removed in a future version
        if ('_scheme' === $key) {
            $this->setSchemes(explode('|', $regex));
        } elseif ('_method' === $key) {
            $this->setMethods(explode('|', $regex));
        }

        return $regex;
    }
}
PKw�Zr�����:Symfony/Component/Routing/RequestContextAwareInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing;

/**
 * @api
 */
interface RequestContextAwareInterface
{
    /**
     * Sets the request context.
     *
     * @param RequestContext $context The context
     *
     * @api
     */
    public function setContext(RequestContext $context);

    /**
     * Gets the request context.
     *
     * @return RequestContext The context
     *
     * @api
     */
    public function getContext();
}
PKw�Z|,{Ȫ�-Symfony/Component/Routing/RouteCollection.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing;

use Symfony\Component\Config\Resource\ResourceInterface;

/**
 * A RouteCollection represents a set of Route instances.
 *
 * When adding a route at the end of the collection, an existing route
 * with the same name is removed first. So there can only be one route
 * with a given name.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Tobias Schultze <http://tobion.de>
 *
 * @api
 */
class RouteCollection implements \IteratorAggregate, \Countable
{
    /**
     * @var Route[]
     */
    private $routes = array();

    /**
     * @var array
     */
    private $resources = array();

    public function __clone()
    {
        foreach ($this->routes as $name => $route) {
            $this->routes[$name] = clone $route;
        }
    }

    /**
     * Gets the current RouteCollection as an Iterator that includes all routes.
     *
     * It implements \IteratorAggregate.
     *
     * @see all()
     *
     * @return \ArrayIterator An \ArrayIterator object for iterating over routes
     */
    public function getIterator()
    {
        return new \ArrayIterator($this->routes);
    }

    /**
     * Gets the number of Routes in this collection.
     *
     * @return int The number of routes
     */
    public function count()
    {
        return count($this->routes);
    }

    /**
     * Adds a route.
     *
     * @param string $name  The route name
     * @param Route  $route A Route instance
     *
     * @api
     */
    public function add($name, Route $route)
    {
        unset($this->routes[$name]);

        $this->routes[$name] = $route;
    }

    /**
     * Returns all routes in this collection.
     *
     * @return Route[] An array of routes
     */
    public function all()
    {
        return $this->routes;
    }

    /**
     * Gets a route by name.
     *
     * @param string $name The route name
     *
     * @return Route|null A Route instance or null when not found
     */
    public function get($name)
    {
        return isset($this->routes[$name]) ? $this->routes[$name] : null;
    }

    /**
     * Removes a route or an array of routes by name from the collection
     *
     * @param string|array $name The route name or an array of route names
     */
    public function remove($name)
    {
        foreach ((array) $name as $n) {
            unset($this->routes[$n]);
        }
    }

    /**
     * Adds a route collection at the end of the current set by appending all
     * routes of the added collection.
     *
     * @param RouteCollection $collection      A RouteCollection instance
     *
     * @api
     */
    public function addCollection(RouteCollection $collection)
    {
        // we need to remove all routes with the same names first because just replacing them
        // would not place the new route at the end of the merged array
        foreach ($collection->all() as $name => $route) {
            unset($this->routes[$name]);
            $this->routes[$name] = $route;
        }

        $this->resources = array_merge($this->resources, $collection->getResources());
    }

    /**
     * Adds a prefix to the path of all child routes.
     *
     * @param string $prefix       An optional prefix to add before each pattern of the route collection
     * @param array  $defaults     An array of default values
     * @param array  $requirements An array of requirements
     *
     * @api
     */
    public function addPrefix($prefix, array $defaults = array(), array $requirements = array())
    {
        $prefix = trim(trim($prefix), '/');

        if ('' === $prefix) {
            return;
        }

        foreach ($this->routes as $route) {
            $route->setPath('/'.$prefix.$route->getPath());
            $route->addDefaults($defaults);
            $route->addRequirements($requirements);
        }
    }

    /**
     * Sets the host pattern on all routes.
     *
     * @param string $pattern      The pattern
     * @param array  $defaults     An array of default values
     * @param array  $requirements An array of requirements
     */
    public function setHost($pattern, array $defaults = array(), array $requirements = array())
    {
        foreach ($this->routes as $route) {
            $route->setHost($pattern);
            $route->addDefaults($defaults);
            $route->addRequirements($requirements);
        }
    }

    /**
     * Sets a condition on all routes.
     *
     * Existing conditions will be overridden.
     *
     * @param string $condition The condition
     */
    public function setCondition($condition)
    {
        foreach ($this->routes as $route) {
            $route->setCondition($condition);
        }
    }

    /**
     * Adds defaults to all routes.
     *
     * An existing default value under the same name in a route will be overridden.
     *
     * @param array $defaults An array of default values
     */
    public function addDefaults(array $defaults)
    {
        if ($defaults) {
            foreach ($this->routes as $route) {
                $route->addDefaults($defaults);
            }
        }
    }

    /**
     * Adds requirements to all routes.
     *
     * An existing requirement under the same name in a route will be overridden.
     *
     * @param array $requirements An array of requirements
     */
    public function addRequirements(array $requirements)
    {
        if ($requirements) {
            foreach ($this->routes as $route) {
                $route->addRequirements($requirements);
            }
        }
    }

    /**
     * Adds options to all routes.
     *
     * An existing option value under the same name in a route will be overridden.
     *
     * @param array $options An array of options
     */
    public function addOptions(array $options)
    {
        if ($options) {
            foreach ($this->routes as $route) {
                $route->addOptions($options);
            }
        }
    }

    /**
     * Sets the schemes (e.g. 'https') all child routes are restricted to.
     *
     * @param string|array $schemes The scheme or an array of schemes
     */
    public function setSchemes($schemes)
    {
        foreach ($this->routes as $route) {
            $route->setSchemes($schemes);
        }
    }

    /**
     * Sets the HTTP methods (e.g. 'POST') all child routes are restricted to.
     *
     * @param string|array $methods The method or an array of methods
     */
    public function setMethods($methods)
    {
        foreach ($this->routes as $route) {
            $route->setMethods($methods);
        }
    }

    /**
     * Returns an array of resources loaded to build this collection.
     *
     * @return ResourceInterface[] An array of resources
     */
    public function getResources()
    {
        return array_unique($this->resources);
    }

    /**
     * Adds a resource for this collection.
     *
     * @param ResourceInterface $resource A resource instance
     */
    public function addResource(ResourceInterface $resource)
    {
        $this->resources[] = $resource;
    }
}
PKw�Z�h�,Symfony/Component/Routing/RequestContext.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing;

use Symfony\Component\HttpFoundation\Request;

/**
 * Holds information about the current request.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class RequestContext
{
    private $baseUrl;
    private $pathInfo;
    private $method;
    private $host;
    private $scheme;
    private $httpPort;
    private $httpsPort;
    private $queryString;

    /**
     * @var array
     */
    private $parameters = array();

    /**
     * Constructor.
     *
     * @param string  $baseUrl      The base URL
     * @param string  $method       The HTTP method
     * @param string  $host         The HTTP host name
     * @param string  $scheme       The HTTP scheme
     * @param integer $httpPort     The HTTP port
     * @param integer $httpsPort    The HTTPS port
     * @param string  $path         The path
     * @param string  $queryString  The query string
     *
     * @api
     */
    public function __construct($baseUrl = '', $method = 'GET', $host = 'localhost', $scheme = 'http', $httpPort = 80, $httpsPort = 443, $path = '/', $queryString = '')
    {
        $this->baseUrl = $baseUrl;
        $this->method = strtoupper($method);
        $this->host = $host;
        $this->scheme = strtolower($scheme);
        $this->httpPort = $httpPort;
        $this->httpsPort = $httpsPort;
        $this->pathInfo = $path;
        $this->queryString = $queryString;
    }

    public function fromRequest(Request $request)
    {
        $this->setBaseUrl($request->getBaseUrl());
        $this->setPathInfo($request->getPathInfo());
        $this->setMethod($request->getMethod());
        $this->setHost($request->getHost());
        $this->setScheme($request->getScheme());
        $this->setHttpPort($request->isSecure() ? $this->httpPort : $request->getPort());
        $this->setHttpsPort($request->isSecure() ? $request->getPort() : $this->httpsPort);
        $this->setQueryString($request->server->get('QUERY_STRING'));
    }

    /**
     * Gets the base URL.
     *
     * @return string The base URL
     */
    public function getBaseUrl()
    {
        return $this->baseUrl;
    }

    /**
     * Sets the base URL.
     *
     * @param string $baseUrl The base URL
     *
     * @api
     */
    public function setBaseUrl($baseUrl)
    {
        $this->baseUrl = $baseUrl;
    }

    /**
     * Gets the path info.
     *
     * @return string The path info
     */
    public function getPathInfo()
    {
        return $this->pathInfo;
    }

    /**
     * Sets the path info.
     *
     * @param string $pathInfo The path info
     */
    public function setPathInfo($pathInfo)
    {
        $this->pathInfo = $pathInfo;
    }

    /**
     * Gets the HTTP method.
     *
     * The method is always an uppercased string.
     *
     * @return string The HTTP method
     */
    public function getMethod()
    {
        return $this->method;
    }

    /**
     * Sets the HTTP method.
     *
     * @param string $method The HTTP method
     *
     * @api
     */
    public function setMethod($method)
    {
        $this->method = strtoupper($method);
    }

    /**
     * Gets the HTTP host.
     *
     * @return string The HTTP host
     */
    public function getHost()
    {
        return $this->host;
    }

    /**
     * Sets the HTTP host.
     *
     * @param string $host The HTTP host
     *
     * @api
     */
    public function setHost($host)
    {
        $this->host = $host;
    }

    /**
     * Gets the HTTP scheme.
     *
     * @return string The HTTP scheme
     */
    public function getScheme()
    {
        return $this->scheme;
    }

    /**
     * Sets the HTTP scheme.
     *
     * @param string $scheme The HTTP scheme
     *
     * @api
     */
    public function setScheme($scheme)
    {
        $this->scheme = strtolower($scheme);
    }

    /**
     * Gets the HTTP port.
     *
     * @return string The HTTP port
     */
    public function getHttpPort()
    {
        return $this->httpPort;
    }

    /**
     * Sets the HTTP port.
     *
     * @param string $httpPort The HTTP port
     *
     * @api
     */
    public function setHttpPort($httpPort)
    {
        $this->httpPort = $httpPort;
    }

    /**
     * Gets the HTTPS port.
     *
     * @return string The HTTPS port
     */
    public function getHttpsPort()
    {
        return $this->httpsPort;
    }

    /**
     * Sets the HTTPS port.
     *
     * @param string $httpsPort The HTTPS port
     *
     * @api
     */
    public function setHttpsPort($httpsPort)
    {
        $this->httpsPort = $httpsPort;
    }

    /**
     * Gets the query string.
     *
     * @return string The query string
     */
    public function getQueryString()
    {
        return $this->queryString;
    }

    /**
     * Sets the query string.
     *
     * @param string $queryString The query string
     *
     * @api
     */
    public function setQueryString($queryString)
    {
        $this->queryString = $queryString;
    }

    /**
     * Returns the parameters.
     *
     * @return array The parameters
     */
    public function getParameters()
    {
        return $this->parameters;
    }

    /**
     * Sets the parameters.
     *
     * This method implements a fluent interface.
     *
     * @param array $parameters The parameters
     *
     * @return Route The current Route instance
     */
    public function setParameters(array $parameters)
    {
        $this->parameters = $parameters;

        return $this;
    }

    /**
     * Gets a parameter value.
     *
     * @param string $name A parameter name
     *
     * @return mixed The parameter value
     */
    public function getParameter($name)
    {
        return isset($this->parameters[$name]) ? $this->parameters[$name] : null;
    }

    /**
     * Checks if a parameter value is set for the given parameter.
     *
     * @param string $name A parameter name
     *
     * @return Boolean true if the parameter value is set, false otherwise
     */
    public function hasParameter($name)
    {
        return array_key_exists($name, $this->parameters);
    }

    /**
     * Sets a parameter value.
     *
     * @param string $name      A parameter name
     * @param mixed  $parameter The parameter value
     *
     * @api
     */
    public function setParameter($name, $parameter)
    {
        $this->parameters[$name] = $parameter;
    }
}
PKw�Zմ���ISymfony/Component/Routing/Generator/ConfigurableRequirementsInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Generator;

/**
 * ConfigurableRequirementsInterface must be implemented by URL generators that
 * can be configured whether an exception should be generated when the parameters
 * do not match the requirements. It is also possible to disable the requirements
 * check for URL generation completely.
 *
 * The possible configurations and use-cases:
 * - setStrictRequirements(true): Throw an exception for mismatching requirements. This
 *   is mostly useful in development environment.
 * - setStrictRequirements(false): Don't throw an exception but return null as URL for
 *   mismatching requirements and log the problem. Useful when you cannot control all
 *   params because they come from third party libs but don't want to have a 404 in
 *   production environment. It should log the mismatch so one can review it.
 * - setStrictRequirements(null): Return the URL with the given parameters without
 *   checking the requirements at all. When generating a URL you should either trust
 *   your params or you validated them beforehand because otherwise it would break your
 *   link anyway. So in production environment you should know that params always pass
 *   the requirements. Thus this option allows to disable the check on URL generation for
 *   performance reasons (saving a preg_match for each requirement every time a URL is
 *   generated).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Tobias Schultze <http://tobion.de>
 */
interface ConfigurableRequirementsInterface
{
    /**
     * Enables or disables the exception on incorrect parameters.
     * Passing null will deactivate the requirements check completely.
     *
     * @param Boolean|null $enabled
     */
    public function setStrictRequirements($enabled);

    /**
     * Returns whether to throw an exception on incorrect parameters.
     * Null means the requirements check is deactivated completely.
     *
     * @return Boolean|null
     */
    public function isStrictRequirements();
}
PKw�Z�
��1�14Symfony/Component/Routing/Generator/UrlGenerator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Generator;

use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\Exception\InvalidParameterException;
use Symfony\Component\Routing\Exception\RouteNotFoundException;
use Symfony\Component\Routing\Exception\MissingMandatoryParametersException;
use Psr\Log\LoggerInterface;

/**
 * UrlGenerator can generate a URL or a path for any route in the RouteCollection
 * based on the passed parameters.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Tobias Schultze <http://tobion.de>
 *
 * @api
 */
class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInterface
{
    /**
     * @var RouteCollection
     */
    protected $routes;

    /**
     * @var RequestContext
     */
    protected $context;

    /**
     * @var Boolean|null
     */
    protected $strictRequirements = true;

    /**
     * @var LoggerInterface|null
     */
    protected $logger;

    /**
     * This array defines the characters (besides alphanumeric ones) that will not be percent-encoded in the path segment of the generated URL.
     *
     * PHP's rawurlencode() encodes all chars except "a-zA-Z0-9-._~" according to RFC 3986. But we want to allow some chars
     * to be used in their literal form (reasons below). Other chars inside the path must of course be encoded, e.g.
     * "?" and "#" (would be interpreted wrongly as query and fragment identifier),
     * "'" and """ (are used as delimiters in HTML).
     */
    protected $decodedChars = array(
        // the slash can be used to designate a hierarchical structure and we want allow using it with this meaning
        // some webservers don't allow the slash in encoded form in the path for security reasons anyway
        // see http://stackoverflow.com/questions/4069002/http-400-if-2f-part-of-get-url-in-jboss
        '%2F' => '/',
        // the following chars are general delimiters in the URI specification but have only special meaning in the authority component
        // so they can safely be used in the path in unencoded form
        '%40' => '@',
        '%3A' => ':',
        // these chars are only sub-delimiters that have no predefined meaning and can therefore be used literally
        // so URI producing applications can use these chars to delimit subcomponents in a path segment without being encoded for better readability
        '%3B' => ';',
        '%2C' => ',',
        '%3D' => '=',
        '%2B' => '+',
        '%21' => '!',
        '%2A' => '*',
        '%7C' => '|',
    );

    /**
     * Constructor.
     *
     * @param RouteCollection      $routes  A RouteCollection instance
     * @param RequestContext       $context The context
     * @param LoggerInterface|null $logger  A logger instance
     *
     * @api
     */
    public function __construct(RouteCollection $routes, RequestContext $context, LoggerInterface $logger = null)
    {
        $this->routes = $routes;
        $this->context = $context;
        $this->logger = $logger;
    }

    /**
     * {@inheritdoc}
     */
    public function setContext(RequestContext $context)
    {
        $this->context = $context;
    }

    /**
     * {@inheritdoc}
     */
    public function getContext()
    {
        return $this->context;
    }

    /**
     * {@inheritdoc}
     */
    public function setStrictRequirements($enabled)
    {
        $this->strictRequirements = null === $enabled ? null : (Boolean) $enabled;
    }

    /**
     * {@inheritdoc}
     */
    public function isStrictRequirements()
    {
        return $this->strictRequirements;
    }

    /**
     * {@inheritDoc}
     */
    public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH)
    {
        if (null === $route = $this->routes->get($name)) {
            throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name));
        }

        // the Route has a cache of its own and is not recompiled as long as it does not get modified
        $compiledRoute = $route->compile();

        return $this->doGenerate($compiledRoute->getVariables(), $route->getDefaults(), $route->getRequirements(), $compiledRoute->getTokens(), $parameters, $name, $referenceType, $compiledRoute->getHostTokens());
    }

    /**
     * @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route
     * @throws InvalidParameterException           When a parameter value for a placeholder is not correct because
     *                                             it does not match the requirement
     */
    protected function doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens)
    {
        $variables = array_flip($variables);
        $mergedParams = array_replace($defaults, $this->context->getParameters(), $parameters);

        // all params must be given
        if ($diff = array_diff_key($variables, $mergedParams)) {
            throw new MissingMandatoryParametersException(sprintf('Some mandatory parameters are missing ("%s") to generate a URL for route "%s".', implode('", "', array_keys($diff)), $name));
        }

        $url = '';
        $optional = true;
        foreach ($tokens as $token) {
            if ('variable' === $token[0]) {
                if (!$optional || !array_key_exists($token[3], $defaults) || null !== $mergedParams[$token[3]] && (string) $mergedParams[$token[3]] !== (string) $defaults[$token[3]]) {
                    // check requirement
                    if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#', $mergedParams[$token[3]])) {
                        $message = sprintf('Parameter "%s" for route "%s" must match "%s" ("%s" given) to generate a corresponding URL.', $token[3], $name, $token[2], $mergedParams[$token[3]]);
                        if ($this->strictRequirements) {
                            throw new InvalidParameterException($message);
                        }

                        if ($this->logger) {
                            $this->logger->error($message);
                        }

                        return null;
                    }

                    $url = $token[1].$mergedParams[$token[3]].$url;
                    $optional = false;
                }
            } else {
                // static text
                $url = $token[1].$url;
                $optional = false;
            }
        }

        if ('' === $url) {
            $url = '/';
        }

        // the contexts base URL is already encoded (see Symfony\Component\HttpFoundation\Request)
        $url = strtr(rawurlencode($url), $this->decodedChars);

        // the path segments "." and ".." are interpreted as relative reference when resolving a URI; see http://tools.ietf.org/html/rfc3986#section-3.3
        // so we need to encode them as they are not used for this purpose here
        // otherwise we would generate a URI that, when followed by a user agent (e.g. browser), does not match this route
        $url = strtr($url, array('/../' => '/%2E%2E/', '/./' => '/%2E/'));
        if ('/..' === substr($url, -3)) {
            $url = substr($url, 0, -2).'%2E%2E';
        } elseif ('/.' === substr($url, -2)) {
            $url = substr($url, 0, -1).'%2E';
        }

        $schemeAuthority = '';
        if ($host = $this->context->getHost()) {
            $scheme = $this->context->getScheme();
            if (isset($requirements['_scheme']) && ($req = strtolower($requirements['_scheme'])) && $scheme !== $req) {
                $referenceType = self::ABSOLUTE_URL;
                $scheme = $req;
            }

            if ($hostTokens) {
                $routeHost = '';
                foreach ($hostTokens as $token) {
                    if ('variable' === $token[0]) {
                        if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#', $mergedParams[$token[3]])) {
                            $message = sprintf('Parameter "%s" for route "%s" must match "%s" ("%s" given) to generate a corresponding URL.', $token[3], $name, $token[2], $mergedParams[$token[3]]);

                            if ($this->strictRequirements) {
                                throw new InvalidParameterException($message);
                            }

                            if ($this->logger) {
                                $this->logger->error($message);
                            }

                            return null;
                        }

                        $routeHost = $token[1].$mergedParams[$token[3]].$routeHost;
                    } else {
                        $routeHost = $token[1].$routeHost;
                    }
                }

                if ($routeHost !== $host) {
                    $host = $routeHost;
                    if (self::ABSOLUTE_URL !== $referenceType) {
                        $referenceType = self::NETWORK_PATH;
                    }
                }
            }

            if (self::ABSOLUTE_URL === $referenceType || self::NETWORK_PATH === $referenceType) {
                $port = '';
                if ('http' === $scheme && 80 != $this->context->getHttpPort()) {
                    $port = ':'.$this->context->getHttpPort();
                } elseif ('https' === $scheme && 443 != $this->context->getHttpsPort()) {
                    $port = ':'.$this->context->getHttpsPort();
                }

                $schemeAuthority = self::NETWORK_PATH === $referenceType ? '//' : "$scheme://";
                $schemeAuthority .= $host.$port;
            }
        }

        if (self::RELATIVE_PATH === $referenceType) {
            $url = self::getRelativePath($this->context->getPathInfo(), $url);
        } else {
            $url = $schemeAuthority.$this->context->getBaseUrl().$url;
        }

        // add a query string if needed
        $extra = array_diff_key($parameters, $variables, $defaults);
        if ($extra && $query = http_build_query($extra, '', '&')) {
            $url .= '?'.$query;
        }

        return $url;
    }

    /**
     * Returns the target path as relative reference from the base path.
     *
     * Only the URIs path component (no schema, host etc.) is relevant and must be given, starting with a slash.
     * Both paths must be absolute and not contain relative parts.
     * Relative URLs from one resource to another are useful when generating self-contained downloadable document archives.
     * Furthermore, they can be used to reduce the link size in documents.
     *
     * Example target paths, given a base path of "/a/b/c/d":
     * - "/a/b/c/d"     -> ""
     * - "/a/b/c/"      -> "./"
     * - "/a/b/"        -> "../"
     * - "/a/b/c/other" -> "other"
     * - "/a/x/y"       -> "../../x/y"
     *
     * @param string $basePath   The base path
     * @param string $targetPath The target path
     *
     * @return string The relative target path
     */
    public static function getRelativePath($basePath, $targetPath)
    {
        if ($basePath === $targetPath) {
            return '';
        }

        $sourceDirs = explode('/', isset($basePath[0]) && '/' === $basePath[0] ? substr($basePath, 1) : $basePath);
        $targetDirs = explode('/', isset($targetPath[0]) && '/' === $targetPath[0] ? substr($targetPath, 1) : $targetPath);
        array_pop($sourceDirs);
        $targetFile = array_pop($targetDirs);

        foreach ($sourceDirs as $i => $dir) {
            if (isset($targetDirs[$i]) && $dir === $targetDirs[$i]) {
                unset($sourceDirs[$i], $targetDirs[$i]);
            } else {
                break;
            }
        }

        $targetDirs[] = $targetFile;
        $path = str_repeat('../', count($sourceDirs)).implode('/', $targetDirs);

        // A reference to the same base directory or an empty subdirectory must be prefixed with "./".
        // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used
        // as the first segment of a relative-path reference, as it would be mistaken for a scheme name
        // (see http://tools.ietf.org/html/rfc3986#section-4.2).
        return '' === $path || '/' === $path[0]
            || false !== ($colonPos = strpos($path, ':')) && ($colonPos < ($slashPos = strpos($path, '/')) || false === $slashPos)
            ? "./$path" : $path;
    }
}
PKw�Z�1O�
�
ASymfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Generator\Dumper;

/**
 * PhpGeneratorDumper creates a PHP class able to generate URLs for a given set of routes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Tobias Schultze <http://tobion.de>
 *
 * @api
 */
class PhpGeneratorDumper extends GeneratorDumper
{
    /**
     * Dumps a set of routes to a PHP class.
     *
     * Available options:
     *
     *  * class:      The class name
     *  * base_class: The base class name
     *
     * @param array $options An array of options
     *
     * @return string A PHP class representing the generator class
     *
     * @api
     */
    public function dump(array $options = array())
    {
        $options = array_merge(array(
            'class'      => 'ProjectUrlGenerator',
            'base_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator',
        ), $options);

        return <<<EOF
<?php

use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\Exception\RouteNotFoundException;
use Psr\Log\LoggerInterface;

/**
 * {$options['class']}
 *
 * This class has been auto-generated
 * by the Symfony Routing Component.
 */
class {$options['class']} extends {$options['base_class']}
{
    private static \$declaredRoutes = {$this->generateDeclaredRoutes()};

    /**
     * Constructor.
     */
    public function __construct(RequestContext \$context, LoggerInterface \$logger = null)
    {
        \$this->context = \$context;
        \$this->logger = \$logger;
    }

{$this->generateGenerateMethod()}
}

EOF;
    }

    /**
     * Generates PHP code representing an array of defined routes
     * together with the routes properties (e.g. requirements).
     *
     * @return string PHP code
     */
    private function generateDeclaredRoutes()
    {
        $routes = "array(\n";
        foreach ($this->getRoutes()->all() as $name => $route) {
            $compiledRoute = $route->compile();

            $properties = array();
            $properties[] = $compiledRoute->getVariables();
            $properties[] = $route->getDefaults();
            $properties[] = $route->getRequirements();
            $properties[] = $compiledRoute->getTokens();
            $properties[] = $compiledRoute->getHostTokens();

            $routes .= sprintf("        '%s' => %s,\n", $name, str_replace("\n", '', var_export($properties, true)));
        }
        $routes .= '    )';

        return $routes;
    }

    /**
     * Generates PHP code representing the `generate` method that implements the UrlGeneratorInterface.
     *
     * @return string PHP code
     */
    private function generateGenerateMethod()
    {
        return <<<EOF
    public function generate(\$name, \$parameters = array(), \$referenceType = self::ABSOLUTE_PATH)
    {
        if (!isset(self::\$declaredRoutes[\$name])) {
            throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', \$name));
        }

        list(\$variables, \$defaults, \$requirements, \$tokens, \$hostTokens) = self::\$declaredRoutes[\$name];

        return \$this->doGenerate(\$variables, \$defaults, \$requirements, \$tokens, \$parameters, \$name, \$referenceType, \$hostTokens);
    }
EOF;
    }
}
PKw�Zu�'��>Symfony/Component/Routing/Generator/Dumper/GeneratorDumper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Generator\Dumper;

use Symfony\Component\Routing\RouteCollection;

/**
 * GeneratorDumper is the base class for all built-in generator dumpers.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class GeneratorDumper implements GeneratorDumperInterface
{
    /**
     * @var RouteCollection
     */
    private $routes;

    /**
     * Constructor.
     *
     * @param RouteCollection $routes The RouteCollection to dump
     */
    public function __construct(RouteCollection $routes)
    {
        $this->routes = $routes;
    }

    /**
     * {@inheritdoc}
     */
    public function getRoutes()
    {
        return $this->routes;
    }
}
PKw�Z�4��GSymfony/Component/Routing/Generator/Dumper/GeneratorDumperInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Generator\Dumper;

use Symfony\Component\Routing\RouteCollection;

/**
 * GeneratorDumperInterface is the interface that all generator dumper classes must implement.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface GeneratorDumperInterface
{
    /**
     * Dumps a set of routes to a string representation of executable code
     * that can then be used to generate a URL of such a route.
     *
     * @param array $options An array of options
     *
     * @return string Executable code
     */
    public function dump(array $options = array());

    /**
     * Gets the routes to dump.
     *
     * @return RouteCollection A RouteCollection instance
     */
    public function getRoutes();
}
PKw�Z����@@=Symfony/Component/Routing/Generator/UrlGeneratorInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Generator;

use Symfony\Component\Routing\Exception\InvalidParameterException;
use Symfony\Component\Routing\Exception\MissingMandatoryParametersException;
use Symfony\Component\Routing\Exception\RouteNotFoundException;
use Symfony\Component\Routing\RequestContextAwareInterface;

/**
 * UrlGeneratorInterface is the interface that all URL generator classes must implement.
 *
 * The constants in this interface define the different types of resource references that
 * are declared in RFC 3986: http://tools.ietf.org/html/rfc3986
 * We are using the term "URL" instead of "URI" as this is more common in web applications
 * and we do not need to distinguish them as the difference is mostly semantical and
 * less technical. Generating URIs, i.e. representation-independent resource identifiers,
 * is also possible.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Tobias Schultze <http://tobion.de>
 *
 * @api
 */
interface UrlGeneratorInterface extends RequestContextAwareInterface
{
    /**
     * Generates an absolute URL, e.g. "http://example.com/dir/file".
     */
    const ABSOLUTE_URL = true;

    /**
     * Generates an absolute path, e.g. "/dir/file".
     */
    const ABSOLUTE_PATH = false;

    /**
     * Generates a relative path based on the current request path, e.g. "../parent-file".
     * @see UrlGenerator::getRelativePath()
     */
    const RELATIVE_PATH = 'relative';

    /**
     * Generates a network path, e.g. "//example.com/dir/file".
     * Such reference reuses the current scheme but specifies the host.
     */
    const NETWORK_PATH = 'network';

    /**
     * Generates a URL or path for a specific route based on the given parameters.
     *
     * Parameters that reference placeholders in the route pattern will substitute them in the
     * path or host. Extra params are added as query string to the URL.
     *
     * When the passed reference type cannot be generated for the route because it requires a different
     * host or scheme than the current one, the method will return a more comprehensive reference
     * that includes the required params. For example, when you call this method with $referenceType = ABSOLUTE_PATH
     * but the route requires the https scheme whereas the current scheme is http, it will instead return an
     * ABSOLUTE_URL with the https scheme and the current host. This makes sure the generated URL matches
     * the route in any case.
     *
     * If there is no route with the given name, the generator must throw the RouteNotFoundException.
     *
     * @param string         $name          The name of the route
     * @param mixed          $parameters    An array of parameters
     * @param Boolean|string $referenceType The type of reference to be generated (one of the constants)
     *
     * @return string The generated URL
     *
     * @throws RouteNotFoundException              If the named route doesn't exist
     * @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route
     * @throws InvalidParameterException           When a parameter value for a placeholder is not correct because
     *                                             it does not match the requirement
     *
     * @api
     */
    public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH);
}
PKw�Zn���hh2Symfony/Component/Routing/Loader/ClosureLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Loader;

use Symfony\Component\Config\Loader\Loader;
use Symfony\Component\Routing\RouteCollection;

/**
 * ClosureLoader loads routes from a PHP closure.
 *
 * The Closure must return a RouteCollection instance.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class ClosureLoader extends Loader
{
    /**
     * Loads a Closure.
     *
     * @param \Closure    $closure A Closure
     * @param string|null $type    The resource type
     *
     * @return RouteCollection A RouteCollection instance
     *
     * @api
     */
    public function load($closure, $type = null)
    {
        return call_user_func($closure);
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function supports($resource, $type = null)
    {
        return $resource instanceof \Closure && (!$type || 'closure' === $type);
    }
}
PKw�Z��?�		>Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Loader;

use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Config\Resource\DirectoryResource;

/**
 * AnnotationDirectoryLoader loads routing information from annotations set
 * on PHP classes and methods.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class AnnotationDirectoryLoader extends AnnotationFileLoader
{
    /**
     * Loads from annotations from a directory.
     *
     * @param string      $path A directory path
     * @param string|null $type The resource type
     *
     * @return RouteCollection A RouteCollection instance
     *
     * @throws \InvalidArgumentException When the directory does not exist or its routes cannot be parsed
     */
    public function load($path, $type = null)
    {
        $dir = $this->locator->locate($path);

        $collection = new RouteCollection();
        $collection->addResource(new DirectoryResource($dir, '/\.php$/'));
        $files = iterator_to_array(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir), \RecursiveIteratorIterator::LEAVES_ONLY));
        usort($files, function (\SplFileInfo $a, \SplFileInfo $b) {
            return (string) $a > (string) $b ? 1 : -1;
        });

        foreach ($files as $file) {
            if (!$file->isFile() || '.php' !== substr($file->getFilename(), -4)) {
                continue;
            }

            if ($class = $this->findClass($file)) {
                $refl = new \ReflectionClass($class);
                if ($refl->isAbstract()) {
                    continue;
                }

                $collection->addCollection($this->loader->load($class, $type));
            }
        }

        return $collection;
    }

    /**
     * {@inheritdoc}
     */
    public function supports($resource, $type = null)
    {
        try {
            $path = $this->locator->locate($resource);
        } catch (\Exception $e) {
            return false;
        }

        return is_string($resource) && is_dir($path) && (!$type || 'annotation' === $type);
    }
}
PKw�Z~ޟ
�
9Symfony/Component/Routing/Loader/AnnotationFileLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Loader;

use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\Config\Loader\FileLoader;
use Symfony\Component\Config\FileLocatorInterface;

/**
 * AnnotationFileLoader loads routing information from annotations set
 * on a PHP class and its methods.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class AnnotationFileLoader extends FileLoader
{
    protected $loader;

    /**
     * Constructor.
     *
     * @param FileLocatorInterface  $locator A FileLocator instance
     * @param AnnotationClassLoader $loader  An AnnotationClassLoader instance
     *
     * @throws \RuntimeException
     */
    public function __construct(FileLocatorInterface $locator, AnnotationClassLoader $loader)
    {
        if (!function_exists('token_get_all')) {
            throw new \RuntimeException('The Tokenizer extension is required for the routing annotation loaders.');
        }

        parent::__construct($locator);

        $this->loader = $loader;
    }

    /**
     * Loads from annotations from a file.
     *
     * @param string      $file A PHP file path
     * @param string|null $type The resource type
     *
     * @return RouteCollection A RouteCollection instance
     *
     * @throws \InvalidArgumentException When the file does not exist or its routes cannot be parsed
     */
    public function load($file, $type = null)
    {
        $path = $this->locator->locate($file);

        $collection = new RouteCollection();
        if ($class = $this->findClass($path)) {
            $collection->addResource(new FileResource($path));
            $collection->addCollection($this->loader->load($class, $type));
        }

        return $collection;
    }

    /**
     * {@inheritdoc}
     */
    public function supports($resource, $type = null)
    {
        return is_string($resource) && 'php' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'annotation' === $type);
    }

    /**
     * Returns the full class name for the first class in the file.
     *
     * @param string $file A PHP file path
     *
     * @return string|false Full class name if found, false otherwise
     */
    protected function findClass($file)
    {
        $class = false;
        $namespace = false;
        $tokens = token_get_all(file_get_contents($file));
        for ($i = 0, $count = count($tokens); $i < $count; $i++) {
            $token = $tokens[$i];

            if (!is_array($token)) {
                continue;
            }

            if (true === $class && T_STRING === $token[0]) {
                return $namespace.'\\'.$token[1];
            }

            if (true === $namespace && T_STRING === $token[0]) {
                $namespace = '';
                do {
                    $namespace .= $token[1];
                    $token = $tokens[++$i];
                } while ($i < $count && is_array($token) && in_array($token[0], array(T_NS_SEPARATOR, T_STRING)));
            }

            if (T_CLASS === $token[0]) {
                $class = true;
            }

            if (T_NAMESPACE === $token[0]) {
                $namespace = true;
            }
        }

        return false;
    }
}
PKw�Z~L�W��:Symfony/Component/Routing/Loader/AnnotationClassLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Loader;

use Doctrine\Common\Annotations\Reader;
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\Config\Loader\LoaderResolverInterface;

/**
 * AnnotationClassLoader loads routing information from a PHP class and its methods.
 *
 * You need to define an implementation for the getRouteDefaults() method. Most of the
 * time, this method should define some PHP callable to be called for the route
 * (a controller in MVC speak).
 *
 * The @Route annotation can be set on the class (for global parameters),
 * and on each method.
 *
 * The @Route annotation main value is the route path. The annotation also
 * recognizes several parameters: requirements, options, defaults, schemes,
 * methods, host, and name. The name parameter is mandatory.
 * Here is an example of how you should be able to use it:
 *
 *     /**
 *      * @Route("/Blog")
 *      * /
 *     class Blog
 *     {
 *         /**
 *          * @Route("/", name="blog_index")
 *          * /
 *         public function index()
 *         {
 *         }
 *
 *         /**
 *          * @Route("/{id}", name="blog_post", requirements = {"id" = "\d+"})
 *          * /
 *         public function show()
 *         {
 *         }
 *     }
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class AnnotationClassLoader implements LoaderInterface
{
    /**
     * @var Reader
     */
    protected $reader;

    /**
     * @var string
     */
    protected $routeAnnotationClass = 'Symfony\\Component\\Routing\\Annotation\\Route';

    /**
     * @var integer
     */
    protected $defaultRouteIndex = 0;

    /**
     * Constructor.
     *
     * @param Reader $reader
     */
    public function __construct(Reader $reader)
    {
        $this->reader = $reader;
    }

    /**
     * Sets the annotation class to read route properties from.
     *
     * @param string $class A fully-qualified class name
     */
    public function setRouteAnnotationClass($class)
    {
        $this->routeAnnotationClass = $class;
    }

    /**
     * Loads from annotations from a class.
     *
     * @param string      $class A class name
     * @param string|null $type  The resource type
     *
     * @return RouteCollection A RouteCollection instance
     *
     * @throws \InvalidArgumentException When route can't be parsed
     */
    public function load($class, $type = null)
    {
        if (!class_exists($class)) {
            throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class));
        }

        $globals = array(
            'path'         => '',
            'requirements' => array(),
            'options'      => array(),
            'defaults'     => array(),
            'schemes'      => array(),
            'methods'      => array(),
            'host'         => '',
            'condition'    => '',
        );

        $class = new \ReflectionClass($class);
        if ($class->isAbstract()) {
            throw new \InvalidArgumentException(sprintf('Annotations from class "%s" cannot be read as it is abstract.', $class));
        }

        if ($annot = $this->reader->getClassAnnotation($class, $this->routeAnnotationClass)) {
            // for BC reasons
            if (null !== $annot->getPath()) {
                $globals['path'] = $annot->getPath();
            } elseif (null !== $annot->getPattern()) {
                $globals['path'] = $annot->getPattern();
            }

            if (null !== $annot->getRequirements()) {
                $globals['requirements'] = $annot->getRequirements();
            }

            if (null !== $annot->getOptions()) {
                $globals['options'] = $annot->getOptions();
            }

            if (null !== $annot->getDefaults()) {
                $globals['defaults'] = $annot->getDefaults();
            }

            if (null !== $annot->getSchemes()) {
                $globals['schemes'] = $annot->getSchemes();
            }

            if (null !== $annot->getMethods()) {
                $globals['methods'] = $annot->getMethods();
            }

            if (null !== $annot->getHost()) {
                $globals['host'] = $annot->getHost();
            }

            if (null !== $annot->getCondition()) {
                $globals['condition'] = $annot->getCondition();
            }
        }

        $collection = new RouteCollection();
        $collection->addResource(new FileResource($class->getFileName()));

        foreach ($class->getMethods() as $method) {
            $this->defaultRouteIndex = 0;
            foreach ($this->reader->getMethodAnnotations($method) as $annot) {
                if ($annot instanceof $this->routeAnnotationClass) {
                    $this->addRoute($collection, $annot, $globals, $class, $method);
                }
            }
        }

        return $collection;
    }

    protected function addRoute(RouteCollection $collection, $annot, $globals, \ReflectionClass $class, \ReflectionMethod $method)
    {
        $name = $annot->getName();
        if (null === $name) {
            $name = $this->getDefaultRouteName($class, $method);
        }

        $defaults = array_replace($globals['defaults'], $annot->getDefaults());
        foreach ($method->getParameters() as $param) {
            if (!isset($defaults[$param->getName()]) && $param->isOptional()) {
                $defaults[$param->getName()] = $param->getDefaultValue();
            }
        }
        $requirements = array_replace($globals['requirements'], $annot->getRequirements());
        $options = array_replace($globals['options'], $annot->getOptions());
        $schemes = array_replace($globals['schemes'], $annot->getSchemes());
        $methods = array_replace($globals['methods'], $annot->getMethods());

        $host = $annot->getHost();
        if (null === $host) {
            $host = $globals['host'];
        }

        $condition = $annot->getCondition();
        if (null === $condition) {
            $condition = $globals['condition'];
        }

        $route = new Route($globals['path'].$annot->getPath(), $defaults, $requirements, $options, $host, $schemes, $methods, $condition);

        $this->configureRoute($route, $class, $method, $annot);

        $collection->add($name, $route);
    }

    /**
     * {@inheritdoc}
     */
    public function supports($resource, $type = null)
    {
        return is_string($resource) && preg_match('/^(?:\\\\?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)+$/', $resource) && (!$type || 'annotation' === $type);
    }

    /**
     * {@inheritdoc}
     */
    public function setResolver(LoaderResolverInterface $resolver)
    {
    }

    /**
     * {@inheritdoc}
     */
    public function getResolver()
    {
    }

    /**
     * Gets the default route name for a class method.
     *
     * @param \ReflectionClass  $class
     * @param \ReflectionMethod $method
     *
     * @return string
     */
    protected function getDefaultRouteName(\ReflectionClass $class, \ReflectionMethod $method)
    {
        $name = strtolower(str_replace('\\', '_', $class->name).'_'.$method->name);
        if ($this->defaultRouteIndex > 0) {
            $name .= '_'.$this->defaultRouteIndex;
        }
        $this->defaultRouteIndex++;

        return $name;
    }

    abstract protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, $annot);
}
PKw�ZP�i{��2Symfony/Component/Routing/Loader/PhpFileLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Loader;

use Symfony\Component\Config\Loader\FileLoader;
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\Routing\RouteCollection;

/**
 * PhpFileLoader loads routes from a PHP file.
 *
 * The file must return a RouteCollection instance.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class PhpFileLoader extends FileLoader
{
    /**
     * Loads a PHP file.
     *
     * @param string      $file A PHP file path
     * @param string|null $type The resource type
     *
     * @return RouteCollection A RouteCollection instance
     *
     * @api
     */
    public function load($file, $type = null)
    {
        // the loader variable is exposed to the included file below
        $loader = $this;

        $path = $this->locator->locate($file);
        $this->setCurrentDir(dirname($path));

        $collection = include $path;
        $collection->addResource(new FileResource($path));

        return $collection;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function supports($resource, $type = null)
    {
        return is_string($resource) && 'php' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'php' === $type);
    }
}
PKw�Z?-[��	�	?Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsdnu�[���<?xml version="1.0" encoding="UTF-8" ?>

<xsd:schema xmlns="http://symfony.com/schema/routing"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://symfony.com/schema/routing"
    elementFormDefault="qualified">

  <xsd:annotation>
    <xsd:documentation><![CDATA[
      Symfony XML Routing Schema, version 1.0
      Authors: Fabien Potencier, Tobias Schultze

      This scheme defines the elements and attributes that can be used to define
      routes. A route maps an HTTP request to a set of configuration variables.
    ]]></xsd:documentation>
  </xsd:annotation>

  <xsd:element name="routes" type="routes" />

  <xsd:complexType name="routes">
    <xsd:choice minOccurs="0" maxOccurs="unbounded">
      <xsd:element name="import" type="import" />
      <xsd:element name="route" type="route" />
    </xsd:choice>
  </xsd:complexType>

  <xsd:group name="configs">
    <xsd:choice>
      <xsd:element name="default" nillable="true" type="element" />
      <xsd:element name="requirement" type="element" />
      <xsd:element name="option" type="element" />
      <xsd:element name="condition" type="condition" />
    </xsd:choice>
  </xsd:group>

  <xsd:complexType name="route">
    <xsd:group ref="configs" minOccurs="0" maxOccurs="unbounded" />

    <xsd:attribute name="id" type="xsd:string" use="required" />
    <xsd:attribute name="path" type="xsd:string" />
    <xsd:attribute name="pattern" type="xsd:string" />
    <xsd:attribute name="host" type="xsd:string" />
    <xsd:attribute name="schemes" type="xsd:string" />
    <xsd:attribute name="methods" type="xsd:string" />
  </xsd:complexType>

  <xsd:complexType name="import">
    <xsd:group ref="configs" minOccurs="0" maxOccurs="unbounded" />

    <xsd:attribute name="resource" type="xsd:string" use="required" />
    <xsd:attribute name="type" type="xsd:string" />
    <xsd:attribute name="prefix" type="xsd:string" />
    <xsd:attribute name="host" type="xsd:string" />
    <xsd:attribute name="schemes" type="xsd:string" />
    <xsd:attribute name="methods" type="xsd:string" />
  </xsd:complexType>

  <xsd:complexType name="element">
    <xsd:simpleContent>
      <xsd:extension base="xsd:string">
        <xsd:attribute name="key" type="xsd:string" use="required" />
      </xsd:extension>
    </xsd:simpleContent>
  </xsd:complexType>

  <xsd:simpleType name="condition">
    <xsd:restriction base="xsd:string">
    </xsd:restriction>
  </xsd:simpleType>
</xsd:schema>
PKw�Zأ2D$D$2Symfony/Component/Routing/Loader/XmlFileLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Loader;

use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\Config\Loader\FileLoader;
use Symfony\Component\Config\Util\XmlUtils;

/**
 * XmlFileLoader loads XML routing files.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Tobias Schultze <http://tobion.de>
 *
 * @api
 */
class XmlFileLoader extends FileLoader
{
    const NAMESPACE_URI = 'http://symfony.com/schema/routing';
    const SCHEME_PATH = '/schema/routing/routing-1.0.xsd';

    /**
     * Loads an XML file.
     *
     * @param string      $file An XML file path
     * @param string|null $type The resource type
     *
     * @return RouteCollection A RouteCollection instance
     *
     * @throws \InvalidArgumentException When the file cannot be loaded or when the XML cannot be
     *                                   parsed because it does not validate against the scheme.
     *
     * @api
     */
    public function load($file, $type = null)
    {
        $path = $this->locator->locate($file);

        $xml = $this->loadFile($path);

        $collection = new RouteCollection();
        $collection->addResource(new FileResource($path));

        // process routes and imports
        foreach ($xml->documentElement->childNodes as $node) {
            if (!$node instanceof \DOMElement) {
                continue;
            }

            $this->parseNode($collection, $node, $path, $file);
        }

        return $collection;
    }

    /**
     * Parses a node from a loaded XML file.
     *
     * @param RouteCollection $collection Collection to associate with the node
     * @param \DOMElement     $node       Element to parse
     * @param string          $path       Full path of the XML file being processed
     * @param string          $file       Loaded file name
     *
     * @throws \InvalidArgumentException When the XML is invalid
     */
    protected function parseNode(RouteCollection $collection, \DOMElement $node, $path, $file)
    {
        if (self::NAMESPACE_URI !== $node->namespaceURI) {
            return;
        }

        switch ($node->localName) {
            case 'route':
                $this->parseRoute($collection, $node, $path);
                break;
            case 'import':
                $this->parseImport($collection, $node, $path, $file);
                break;
            default:
                throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "route" or "import".', $node->localName, $path));
        }
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function supports($resource, $type = null)
    {
        return is_string($resource) && 'xml' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'xml' === $type);
    }

    /**
     * Parses a route and adds it to the RouteCollection.
     *
     * @param RouteCollection $collection RouteCollection instance
     * @param \DOMElement     $node       Element to parse that represents a Route
     * @param string          $path       Full path of the XML file being processed
     *
     * @throws \InvalidArgumentException When the XML is invalid
     */
    protected function parseRoute(RouteCollection $collection, \DOMElement $node, $path)
    {
        if ('' === ($id = $node->getAttribute('id')) || (!$node->hasAttribute('pattern') && !$node->hasAttribute('path'))) {
            throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" must have an "id" and a "path" attribute.', $path));
        }

        if ($node->hasAttribute('pattern')) {
            if ($node->hasAttribute('path')) {
                throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" cannot define both a "path" and a "pattern" attribute. Use only "path".', $path));
            }

            $node->setAttribute('path', $node->getAttribute('pattern'));
            $node->removeAttribute('pattern');
        }

        $schemes = preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, PREG_SPLIT_NO_EMPTY);
        $methods = preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, PREG_SPLIT_NO_EMPTY);

        list($defaults, $requirements, $options, $condition) = $this->parseConfigs($node, $path);

        $route = new Route($node->getAttribute('path'), $defaults, $requirements, $options, $node->getAttribute('host'), $schemes, $methods, $condition);
        $collection->add($id, $route);
    }

    /**
     * Parses an import and adds the routes in the resource to the RouteCollection.
     *
     * @param RouteCollection $collection RouteCollection instance
     * @param \DOMElement     $node       Element to parse that represents a Route
     * @param string          $path       Full path of the XML file being processed
     * @param string          $file       Loaded file name
     *
     * @throws \InvalidArgumentException When the XML is invalid
     */
    protected function parseImport(RouteCollection $collection, \DOMElement $node, $path, $file)
    {
        if ('' === $resource = $node->getAttribute('resource')) {
            throw new \InvalidArgumentException(sprintf('The <import> element in file "%s" must have a "resource" attribute.', $path));
        }

        $type = $node->getAttribute('type');
        $prefix = $node->getAttribute('prefix');
        $host = $node->hasAttribute('host') ? $node->getAttribute('host') : null;
        $schemes = $node->hasAttribute('schemes') ? preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, PREG_SPLIT_NO_EMPTY) : null;
        $methods = $node->hasAttribute('methods') ? preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, PREG_SPLIT_NO_EMPTY) : null;

        list($defaults, $requirements, $options, $condition) = $this->parseConfigs($node, $path);

        $this->setCurrentDir(dirname($path));

        $subCollection = $this->import($resource, ('' !== $type ? $type : null), false, $file);
        /* @var $subCollection RouteCollection */
        $subCollection->addPrefix($prefix);
        if (null !== $host) {
            $subCollection->setHost($host);
        }
        if (null !== $condition) {
            $subCollection->setCondition($condition);
        }
        if (null !== $schemes) {
            $subCollection->setSchemes($schemes);
        }
        if (null !== $methods) {
            $subCollection->setMethods($methods);
        }
        $subCollection->addDefaults($defaults);
        $subCollection->addRequirements($requirements);
        $subCollection->addOptions($options);

        $collection->addCollection($subCollection);
    }

    /**
     * Loads an XML file.
     *
     * @param string $file An XML file path
     *
     * @return \DOMDocument
     *
     * @throws \InvalidArgumentException When loading of XML file fails because of syntax errors
     *                                   or when the XML structure is not as expected by the scheme -
     *                                   see validate()
     */
    protected function loadFile($file)
    {
        return XmlUtils::loadFile($file, __DIR__.static::SCHEME_PATH);
    }

    /**
     * Parses the config elements (default, requirement, option).
     *
     * @param \DOMElement $node Element to parse that contains the configs
     * @param string      $path Full path of the XML file being processed
     *
     * @return array An array with the defaults as first item, requirements as second and options as third.
     *
     * @throws \InvalidArgumentException When the XML is invalid
     */
    private function parseConfigs(\DOMElement $node, $path)
    {
        $defaults = array();
        $requirements = array();
        $options = array();
        $condition = null;

        foreach ($node->getElementsByTagNameNS(self::NAMESPACE_URI, '*') as $n) {
            switch ($n->localName) {
                case 'default':
                    if ($n->hasAttribute('xsi:nil') && 'true' == $n->getAttribute('xsi:nil')) {
                        $defaults[$n->getAttribute('key')] = null;
                    } else {
                        $defaults[$n->getAttribute('key')] = trim($n->textContent);
                    }

                    break;
                case 'requirement':
                    $requirements[$n->getAttribute('key')] = trim($n->textContent);
                    break;
                case 'option':
                    $options[$n->getAttribute('key')] = trim($n->textContent);
                    break;
                case 'condition':
                    $condition = trim($n->textContent);
                    break;
                default:
                    throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "default", "requirement" or "option".', $n->localName, $path));
            }
        }

        return array($defaults, $requirements, $options, $condition);
    }
}
PKw�ZpB�Q Q 3Symfony/Component/Routing/Loader/YamlFileLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Loader;

use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\Yaml\Parser as YamlParser;
use Symfony\Component\Config\Loader\FileLoader;

/**
 * YamlFileLoader loads Yaml routing files.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Tobias Schultze <http://tobion.de>
 *
 * @api
 */
class YamlFileLoader extends FileLoader
{
    private static $availableKeys = array(
        'resource', 'type', 'prefix', 'pattern', 'path', 'host', 'schemes', 'methods', 'defaults', 'requirements', 'options', 'condition'
    );
    private $yamlParser;

    /**
     * Loads a Yaml file.
     *
     * @param string      $file A Yaml file path
     * @param string|null $type The resource type
     *
     * @return RouteCollection A RouteCollection instance
     *
     * @throws \InvalidArgumentException When a route can't be parsed because YAML is invalid
     *
     * @api
     */
    public function load($file, $type = null)
    {
        $path = $this->locator->locate($file);

        if (!stream_is_local($path)) {
            throw new \InvalidArgumentException(sprintf('This is not a local file "%s".', $path));
        }

        if (!file_exists($path)) {
            throw new \InvalidArgumentException(sprintf('File "%s" not found.', $path));
        }

        if (null === $this->yamlParser) {
            $this->yamlParser = new YamlParser();
        }

        $config = $this->yamlParser->parse(file_get_contents($path));

        $collection = new RouteCollection();
        $collection->addResource(new FileResource($path));

        // empty file
        if (null === $config) {
            return $collection;
        }

        // not an array
        if (!is_array($config)) {
            throw new \InvalidArgumentException(sprintf('The file "%s" must contain a YAML array.', $path));
        }

        foreach ($config as $name => $config) {
            if (isset($config['pattern'])) {
                if (isset($config['path'])) {
                    throw new \InvalidArgumentException(sprintf('The file "%s" cannot define both a "path" and a "pattern" attribute. Use only "path".', $path));
                }

                $config['path'] = $config['pattern'];
                unset($config['pattern']);
            }

            $this->validate($config, $name, $path);

            if (isset($config['resource'])) {
                $this->parseImport($collection, $config, $path, $file);
            } else {
                $this->parseRoute($collection, $name, $config, $path);
            }
        }

        return $collection;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function supports($resource, $type = null)
    {
        return is_string($resource) && 'yml' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'yaml' === $type);
    }

    /**
     * Parses a route and adds it to the RouteCollection.
     *
     * @param RouteCollection $collection A RouteCollection instance
     * @param string          $name       Route name
     * @param array           $config     Route definition
     * @param string          $path       Full path of the YAML file being processed
     */
    protected function parseRoute(RouteCollection $collection, $name, array $config, $path)
    {
        $defaults = isset($config['defaults']) ? $config['defaults'] : array();
        $requirements = isset($config['requirements']) ? $config['requirements'] : array();
        $options = isset($config['options']) ? $config['options'] : array();
        $host = isset($config['host']) ? $config['host'] : '';
        $schemes = isset($config['schemes']) ? $config['schemes'] : array();
        $methods = isset($config['methods']) ? $config['methods'] : array();
        $condition = isset($config['condition']) ? $config['condition'] : null;

        $route = new Route($config['path'], $defaults, $requirements, $options, $host, $schemes, $methods, $condition);

        $collection->add($name, $route);
    }

    /**
     * Parses an import and adds the routes in the resource to the RouteCollection.
     *
     * @param RouteCollection $collection A RouteCollection instance
     * @param array           $config     Route definition
     * @param string          $path       Full path of the YAML file being processed
     * @param string          $file       Loaded file name
     */
    protected function parseImport(RouteCollection $collection, array $config, $path, $file)
    {
        $type = isset($config['type']) ? $config['type'] : null;
        $prefix = isset($config['prefix']) ? $config['prefix'] : '';
        $defaults = isset($config['defaults']) ? $config['defaults'] : array();
        $requirements = isset($config['requirements']) ? $config['requirements'] : array();
        $options = isset($config['options']) ? $config['options'] : array();
        $host = isset($config['host']) ? $config['host'] : null;
        $condition = isset($config['condition']) ? $config['condition'] : null;
        $schemes = isset($config['schemes']) ? $config['schemes'] : null;
        $methods = isset($config['methods']) ? $config['methods'] : null;

        $this->setCurrentDir(dirname($path));

        $subCollection = $this->import($config['resource'], $type, false, $file);
        /* @var $subCollection RouteCollection */
        $subCollection->addPrefix($prefix);
        if (null !== $host) {
            $subCollection->setHost($host);
        }
        if (null !== $condition) {
            $subCollection->setCondition($condition);
        }
        if (null !== $schemes) {
            $subCollection->setSchemes($schemes);
        }
        if (null !== $methods) {
            $subCollection->setMethods($methods);
        }
        $subCollection->addDefaults($defaults);
        $subCollection->addRequirements($requirements);
        $subCollection->addOptions($options);

        $collection->addCollection($subCollection);
    }

    /**
     * Validates the route configuration.
     *
     * @param array  $config A resource config
     * @param string $name   The config key
     * @param string $path   The loaded file path
     *
     * @throws \InvalidArgumentException If one of the provided config keys is not supported,
     *                                   something is missing or the combination is nonsense
     */
    protected function validate($config, $name, $path)
    {
        if (!is_array($config)) {
            throw new \InvalidArgumentException(sprintf('The definition of "%s" in "%s" must be a YAML array.', $name, $path));
        }
        if ($extraKeys = array_diff(array_keys($config), self::$availableKeys)) {
            throw new \InvalidArgumentException(sprintf(
                'The routing file "%s" contains unsupported keys for "%s": "%s". Expected one of: "%s".',
                $path, $name, implode('", "', $extraKeys), implode('", "', self::$availableKeys)
            ));
        }
        if (isset($config['resource']) && isset($config['path'])) {
            throw new \InvalidArgumentException(sprintf(
                'The routing file "%s" must not specify both the "resource" key and the "path" key for "%s". Choose between an import and a route definition.',
                $path, $name
            ));
        }
        if (!isset($config['resource']) && isset($config['type'])) {
            throw new \InvalidArgumentException(sprintf(
                'The "type" key for the route definition "%s" in "%s" is unsupported. It is only available for imports in combination with the "resource" key.',
                $name, $path
            ));
        }
        if (!isset($config['resource']) && !isset($config['path'])) {
            throw new \InvalidArgumentException(sprintf(
                'You must define a "path" for the route "%s" in file "%s".',
                $name, $path
            ));
        }
    }
}
PKx�ZqF��>>4Symfony/Component/Routing/RouteCompilerInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing;

/**
 * RouteCompilerInterface is the interface that all RouteCompiler classes must implement.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface RouteCompilerInterface
{
    /**
     * Compiles the current route instance.
     *
     * @param Route $route A Route instance
     *
     * @return CompiledRoute A CompiledRoute instance
     *
     * @throws \LogicException If the Route cannot be compiled because the
     *                         path or host pattern is invalid
     */
    public static function compile(Route $route);
}
PKx�Z0���QQ(Symfony/Component/Process/autoloader.phpnu�[���<?php

spl_autoload_register(function ($class) {
    if ('\\' == $class[0]) {
        $class = substr($class, 1);
    }

    if (
        0 === strpos($class, 'Symfony\\Component\\Process\\')
        &&
        file_exists($file = __DIR__.'/../../../'.str_replace('\\', '/', $class).'.php')
    ) {
        require_once $file;
    }
});
PKx�Zg��'�'*Symfony/Component/Process/ProcessPipes.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process;

use Symfony\Component\Process\Exception\RuntimeException;

/**
 * ProcessPipes manages descriptors and pipes for the use of proc_open.
 */
class ProcessPipes
{
    /** @var array */
    public $pipes = array();
    /** @var array */
    private $files = array();
    /** @var array */
    private $fileHandles = array();
    /** @var array */
    private $readBytes = array();
    /** @var Boolean */
    private $useFiles;
    /** @var Boolean */
    private $ttyMode;

    const CHUNK_SIZE = 16384;

    public function __construct($useFiles, $ttyMode)
    {
        $this->useFiles = (Boolean) $useFiles;
        $this->ttyMode = (Boolean) $ttyMode;

        // Fix for PHP bug #51800: reading from STDOUT pipe hangs forever on Windows if the output is too big.
        // Workaround for this problem is to use temporary files instead of pipes on Windows platform.
        //
        // @see https://bugs.php.net/bug.php?id=51800
        if ($this->useFiles) {
            $this->files = array(
                Process::STDOUT => tempnam(sys_get_temp_dir(), 'sf_proc_stdout'),
                Process::STDERR => tempnam(sys_get_temp_dir(), 'sf_proc_stderr'),
            );
            foreach ($this->files as $offset => $file) {
                $this->fileHandles[$offset] = fopen($this->files[$offset], 'rb');
                if (false === $this->fileHandles[$offset]) {
                    throw new RuntimeException('A temporary file could not be opened to write the process output to, verify that your TEMP environment variable is writable');
                }
            }
            $this->readBytes = array(
                Process::STDOUT => 0,
                Process::STDERR => 0,
            );
        }
    }

    public function __destruct()
    {
        $this->close();
        $this->removeFiles();
    }

    /**
     * Sets non-blocking mode on pipes.
     */
    public function unblock()
    {
        foreach ($this->pipes as $pipe) {
            stream_set_blocking($pipe, 0);
        }
    }

    /**
     * Closes file handles and pipes.
     */
    public function close()
    {
        $this->closeUnixPipes();
        foreach ($this->fileHandles as $handle) {
            fclose($handle);
        }
        $this->fileHandles = array();
    }

    /**
     * Closes Unix pipes.
     *
     * Nothing happens in case file handles are used.
     */
    public function closeUnixPipes()
    {
        foreach ($this->pipes as $pipe) {
            fclose($pipe);
        }
        $this->pipes = array();
    }

    /**
     * Returns an array of descriptors for the use of proc_open.
     *
     * @return array
     */
    public function getDescriptors()
    {
        if ($this->useFiles) {
            // We're not using pipe on Windows platform as it hangs (https://bugs.php.net/bug.php?id=51800)
            // We're not using file handles as it can produce corrupted output https://bugs.php.net/bug.php?id=65650
            // So we redirect output within the commandline and pass the nul device to the process
            return array(
                array('pipe', 'r'),
                array('file', 'NUL', 'w'),
                array('file', 'NUL', 'w'),
            );
        }

        if ($this->ttyMode) {
            return array(
                array('file', '/dev/tty', 'r'),
                array('file', '/dev/tty', 'w'),
                array('file', '/dev/tty', 'w'),
            );
        }

        return array(
            array('pipe', 'r'), // stdin
            array('pipe', 'w'), // stdout
            array('pipe', 'w'), // stderr
        );
    }

    /**
     * Returns an array of filenames indexed by their related stream in case these pipes use temporary files.
     *
     * @return array
     */
    public function getFiles()
    {
        if ($this->useFiles) {
            return $this->files;
        }

        return array();
    }

    /**
     * Reads data in file handles and pipes.
     *
     * @param Boolean $blocking Whether to use blocking calls or not.
     *
     * @return array An array of read data indexed by their fd.
     */
    public function read($blocking)
    {
        return array_replace($this->readStreams($blocking), $this->readFileHandles());
    }

    /**
     * Reads data in file handles and pipes, closes them if EOF is reached.
     *
     * @param Boolean $blocking Whether to use blocking calls or not.
     *
     * @return array An array of read data indexed by their fd.
     */
    public function readAndCloseHandles($blocking)
    {
        return array_replace($this->readStreams($blocking, true), $this->readFileHandles(true));
    }

    /**
     * Returns if the current state has open file handles or pipes.
     *
     * @return Boolean
     */
    public function hasOpenHandles()
    {
        if (!$this->useFiles) {
            return (Boolean) $this->pipes;
        }

        return (Boolean) $this->pipes && (Boolean) $this->fileHandles;
    }

    /**
     * Writes stdin data.
     *
     * @param Boolean     $blocking Whether to use blocking calls or not.
     * @param string|null $stdin    The data to write.
     */
    public function write($blocking, $stdin)
    {
        if (null === $stdin) {
            fclose($this->pipes[0]);
            unset($this->pipes[0]);

            return;
        }

        $writePipes = array($this->pipes[0]);
        unset($this->pipes[0]);
        $stdinLen = strlen($stdin);
        $stdinOffset = 0;

        while ($writePipes) {
            $r = null;
            $w = $writePipes;
            $e = null;

            if (false === $n = @stream_select($r, $w, $e, 0, $blocking ? ceil(Process::TIMEOUT_PRECISION * 1E6) : 0)) {
                // if a system call has been interrupted, forget about it, let's try again
                if ($this->hasSystemCallBeenInterrupted()) {
                    continue;
                }
                break;
            }

            // nothing has changed, let's wait until the process is ready
            if (0 === $n) {
                continue;
            }

            if ($w) {
                $written = fwrite($writePipes[0], (binary) substr($stdin, $stdinOffset), 8192);
                if (false !== $written) {
                    $stdinOffset += $written;
                }
                if ($stdinOffset >= $stdinLen) {
                    fclose($writePipes[0]);
                    $writePipes = null;
                }
            }
        }
    }

    /**
     * Reads data in file handles.
     *
     * @param Boolean $close Whether to close file handles or not.
     *
     * @return array An array of read data indexed by their fd.
     */
    private function readFileHandles($close = false)
    {
        $read = array();
        $fh = $this->fileHandles;
        foreach ($fh as $type => $fileHandle) {
            if (0 !== fseek($fileHandle, $this->readBytes[$type])) {
                continue;
            }
            $data = '';
            $dataread = null;
            while (!feof($fileHandle)) {
                if (false !== $dataread = fread($fileHandle, self::CHUNK_SIZE)) {
                    $data .= $dataread;
                }
            }
            if (0 < $length = strlen($data)) {
                $this->readBytes[$type] += $length;
                $read[$type] = $data;
            }

            if (false === $dataread || (true === $close && feof($fileHandle) && '' === $data)) {
                fclose($this->fileHandles[$type]);
                unset($this->fileHandles[$type]);
            }
        }

        return $read;
    }

    /**
     * Reads data in file pipes streams.
     *
     * @param Boolean $blocking Whether to use blocking calls or not.
     * @param Boolean $close    Whether to close file handles or not.
     *
     * @return array An array of read data indexed by their fd.
     */
    private function readStreams($blocking, $close = false)
    {
        if (empty($this->pipes)) {
            return array();
        }

        $read = array();

        $r = $this->pipes;
        $w = null;
        $e = null;

        // let's have a look if something changed in streams
        if (false === $n = @stream_select($r, $w, $e, 0, $blocking ? ceil(Process::TIMEOUT_PRECISION * 1E6) : 0)) {
            // if a system call has been interrupted, forget about it, let's try again
            // otherwise, an error occurred, let's reset pipes
            if (!$this->hasSystemCallBeenInterrupted()) {
                $this->pipes = array();
            }

            return $read;
        }

        // nothing has changed
        if (0 === $n) {
            return $read;
        }

        foreach ($r as $pipe) {
            $type = array_search($pipe, $this->pipes);

            $data = '';
            while ($dataread = fread($pipe, self::CHUNK_SIZE)) {
                $data .= $dataread;
            }

            if ($data) {
                $read[$type] = $data;
            }

            if (false === $data || (true === $close && feof($pipe) && '' === $data)) {
                fclose($this->pipes[$type]);
                unset($this->pipes[$type]);
            }
        }

        return $read;
    }

    /**
     * Returns true if a system call has been interrupted.
     *
     * @return Boolean
     */
    private function hasSystemCallBeenInterrupted()
    {
        $lastError = error_get_last();

        // stream_select returns false when the `select` system call is interrupted by an incoming signal
        return isset($lastError['message']) && false !== stripos($lastError['message'], 'interrupted system call');
    }

    /**
     * Removes temporary files
     */
    private function removeFiles()
    {
        foreach ($this->files as $filename) {
            if (file_exists($filename)) {
                @unlink($filename);
            }
        }
        $this->files = array();
    }
}
PKx�Z��2�{{@Symfony/Component/Process/Exception/ProcessTimedOutException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Exception;

use Symfony\Component\Process\Process;

/**
 * Exception that is thrown when a process times out.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ProcessTimedOutException extends RuntimeException
{
    const TYPE_GENERAL = 1;
    const TYPE_IDLE = 2;

    private $process;
    private $timeoutType;

    public function __construct(Process $process, $timeoutType)
    {
        $this->process = $process;
        $this->timeoutType = $timeoutType;

        parent::__construct(sprintf(
            'The process "%s" exceeded the timeout of %s seconds.',
            $process->getCommandLine(),
            $this->getExceededTimeout()
        ));
    }

    public function getProcess()
    {
        return $this->process;
    }

    public function isGeneralTimeout()
    {
        return $this->timeoutType === self::TYPE_GENERAL;
    }

    public function isIdleTimeout()
    {
        return $this->timeoutType === self::TYPE_IDLE;
    }

    public function getExceededTimeout()
    {
        switch ($this->timeoutType) {
            case self::TYPE_GENERAL:
                return $this->process->getTimeout();

            case self::TYPE_IDLE:
                return $this->process->getIdleTimeout();

            default:
                throw new \LogicException(sprintf('Unknown timeout type "%d".', $this->timeoutType));
        }
    }
}
PKx�Z�<���:Symfony/Component/Process/Exception/ExceptionInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Exception;

/**
 * Marker Interface for the Process Component.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface ExceptionInterface
{
}
PKx�Z>H����8Symfony/Component/Process/Exception/RuntimeException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Exception;

/**
 * RuntimeException for the Process Component.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
PKx�Z��W��6Symfony/Component/Process/Exception/LogicException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Exception;

/**
 * LogicException for the Process Component.
 *
 * @author Romain Neutron <imprec@gmail.com>
 */
class LogicException extends \LogicException implements ExceptionInterface
{
}
PKx�Z˅����@Symfony/Component/Process/Exception/InvalidArgumentException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Exception;

/**
 * InvalidArgumentException for the Process Component.
 *
 * @author Romain Neutron <imprec@gmail.com>
 */
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
PKx�Z��_��>Symfony/Component/Process/Exception/ProcessFailedException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Exception;

use Symfony\Component\Process\Process;

/**
 * Exception for failed processes.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ProcessFailedException extends RuntimeException
{
    private $process;

    public function __construct(Process $process)
    {
        if ($process->isSuccessful()) {
            throw new InvalidArgumentException('Expected a failed process, but the given process was successful.');
        }

        parent::__construct(
            sprintf(
                'The command "%s" failed.'."\nExit Code: %s(%s)\n\nOutput:\n================\n%s\n\nError Output:\n================\n%s",
                $process->getCommandLine(),
                $process->getExitCode(),
                $process->getExitCodeText(),
                $process->getOutput(),
                $process->getErrorOutput()
            )
        );

        $this->process = $process;
    }

    public function getProcess()
    {
        return $this->process;
    }
}
PKx�Z@s�(Symfony/Component/Process/PhpProcess.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process;

use Symfony\Component\Process\Exception\RuntimeException;

/**
 * PhpProcess runs a PHP script in an independent process.
 *
 * $p = new PhpProcess('<?php echo "foo"; ?>');
 * $p->run();
 * print $p->getOutput()."\n";
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class PhpProcess extends Process
{
    private $executableFinder;

    /**
     * Constructor.
     *
     * @param string  $script  The PHP script to run (as a string)
     * @param string  $cwd     The working directory
     * @param array   $env     The environment variables
     * @param integer $timeout The timeout in seconds
     * @param array   $options An array of options for proc_open
     *
     * @api
     */
    public function __construct($script, $cwd = null, array $env = array(), $timeout = 60, array $options = array())
    {
        parent::__construct(null, $cwd, $env, $script, $timeout, $options);

        $this->executableFinder = new PhpExecutableFinder();
    }

    /**
     * Sets the path to the PHP binary to use.
     *
     * @api
     */
    public function setPhpBinary($php)
    {
        $this->setCommandLine($php);
    }

    /**
     * {@inheritdoc}
     */
    public function start($callback = null)
    {
        if (null === $this->getCommandLine()) {
            if (false === $php = $this->executableFinder->find()) {
                throw new RuntimeException('Unable to find the PHP executable.');
            }
            $this->setCommandLine($php);
        }

        parent::start($callback);
    }
}
PKx�Z�nL	L	*Symfony/Component/Process/ProcessUtils.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process;

/**
 * ProcessUtils is a bunch of utility methods.
 *
 * This class contains static methods only and is not meant to be instantiated.
 *
 * @author Martin Hasoň <martin.hason@gmail.com>
 */
class ProcessUtils
{
    /**
     * This class should not be instantiated
     */
    private function __construct()
    {
    }

    /**
     * Escapes a string to be used as a shell argument.
     *
     * @param string $argument The argument that will be escaped
     *
     * @return string The escaped argument
     */
    public static function escapeArgument($argument)
    {
        //Fix for PHP bug #43784 escapeshellarg removes % from given string
        //Fix for PHP bug #49446 escapeshellarg doesn't work on Windows
        //@see https://bugs.php.net/bug.php?id=43784
        //@see https://bugs.php.net/bug.php?id=49446
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            if ('' === $argument) {
                return escapeshellarg($argument);
            }

            $escapedArgument = '';
            $quote =  false;
            foreach (preg_split('/(")/i', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) {
                if ('"' === $part) {
                    $escapedArgument .= '\\"';
                } elseif (self::isSurroundedBy($part, '%')) {
                    // Avoid environment variable expansion
                    $escapedArgument .= '^%"'.substr($part, 1, -1).'"^%';
                } else {
                    // escape trailing backslash
                    if ('\\' === substr($part, -1)) {
                        $part .= '\\';
                    }
                    $quote = true;
                    $escapedArgument .= $part;
                }
            }
            if ($quote) {
                $escapedArgument = '"'.$escapedArgument.'"';
            }

            return $escapedArgument;
        }

        return escapeshellarg($argument);
    }

    private static function isSurroundedBy($arg, $char)
    {
        return 2 < strlen($arg) && $char === $arg[0] && $char === $arg[strlen($arg) - 1];
    }
}
PKy�Z�!,$

.Symfony/Component/Process/ExecutableFinder.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process;

/**
 * Generic executable finder.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ExecutableFinder
{
    private $suffixes = array('.exe', '.bat', '.cmd', '.com');

    /**
     * Replaces default suffixes of executable.
     *
     * @param array $suffixes
     */
    public function setSuffixes(array $suffixes)
    {
        $this->suffixes = $suffixes;
    }

    /**
     * Adds new possible suffix to check for executable.
     *
     * @param string $suffix
     */
    public function addSuffix($suffix)
    {
        $this->suffixes[] = $suffix;
    }

    /**
     * Finds an executable by name.
     *
     * @param string $name      The executable name (without the extension)
     * @param string $default   The default to return if no executable is found
     * @param array  $extraDirs Additional dirs to check into
     *
     * @return string The executable path or default value
     */
    public function find($name, $default = null, array $extraDirs = array())
    {
        if (ini_get('open_basedir')) {
            $searchPath = explode(PATH_SEPARATOR, getenv('open_basedir'));
            $dirs = array();
            foreach ($searchPath as $path) {
                if (is_dir($path)) {
                    $dirs[] = $path;
                } else {
                    $file = str_replace(dirname($path), '', $path);
                    if ($file == $name && is_executable($path)) {
                        return $path;
                    }
                }
            }
        } else {
            $dirs = array_merge(
                explode(PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')),
                $extraDirs
            );
        }

        $suffixes = array('');
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $pathExt = getenv('PATHEXT');
            $suffixes = $pathExt ? explode(PATH_SEPARATOR, $pathExt) : $this->suffixes;
        }
        foreach ($suffixes as $suffix) {
            foreach ($dirs as $dir) {
                if (is_file($file = $dir.DIRECTORY_SEPARATOR.$name.$suffix) && (defined('PHP_WINDOWS_VERSION_BUILD') || is_executable($file))) {
                    return $file;
                }
            }
        }

        return $default;
    }
}
PKy�Z!/���,Symfony/Component/Process/ProcessBuilder.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process;

use Symfony\Component\Process\Exception\InvalidArgumentException;
use Symfony\Component\Process\Exception\LogicException;

/**
 * Process builder.
 *
 * @author Kris Wallsmith <kris@symfony.com>
 */
class ProcessBuilder
{
    private $arguments;
    private $cwd;
    private $env = array();
    private $stdin;
    private $timeout = 60;
    private $options = array();
    private $inheritEnv = true;
    private $prefix = array();

    public function __construct(array $arguments = array())
    {
        $this->arguments = $arguments;
    }

    public static function create(array $arguments = array())
    {
        return new static($arguments);
    }

    /**
     * Adds an unescaped argument to the command string.
     *
     * @param string $argument A command argument
     *
     * @return ProcessBuilder
     */
    public function add($argument)
    {
        $this->arguments[] = $argument;

        return $this;
    }

    /**
     * Adds an unescaped prefix to the command string.
     *
     * The prefix is preserved when resetting arguments.
     *
     * @param string|array $prefix A command prefix or an array of command prefixes
     *
     * @return ProcessBuilder
     */
    public function setPrefix($prefix)
    {
        $this->prefix = is_array($prefix) ? $prefix : array($prefix);

        return $this;
    }

    /**
     * @param array $arguments
     *
     * @return ProcessBuilder
     */
    public function setArguments(array $arguments)
    {
        $this->arguments = $arguments;

        return $this;
    }

    public function setWorkingDirectory($cwd)
    {
        $this->cwd = $cwd;

        return $this;
    }

    public function inheritEnvironmentVariables($inheritEnv = true)
    {
        $this->inheritEnv = $inheritEnv;

        return $this;
    }

    public function setEnv($name, $value)
    {
        $this->env[$name] = $value;

        return $this;
    }

    public function addEnvironmentVariables(array $variables)
    {
        $this->env = array_replace($this->env, $variables);

        return $this;
    }

    public function setInput($stdin)
    {
        $this->stdin = $stdin;

        return $this;
    }

    /**
     * Sets the process timeout.
     *
     * To disable the timeout, set this value to null.
     *
     * @param float|null
     *
     * @return ProcessBuilder
     *
     * @throws InvalidArgumentException
     */
    public function setTimeout($timeout)
    {
        if (null === $timeout) {
            $this->timeout = null;

            return $this;
        }

        $timeout = (float) $timeout;

        if ($timeout < 0) {
            throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
        }

        $this->timeout = $timeout;

        return $this;
    }

    public function setOption($name, $value)
    {
        $this->options[$name] = $value;

        return $this;
    }

    public function getProcess()
    {
        if (0 === count($this->prefix) && 0 === count($this->arguments)) {
            throw new LogicException('You must add() command arguments before calling getProcess().');
        }

        $options = $this->options;

        $arguments = array_merge($this->prefix, $this->arguments);
        $script = implode(' ', array_map(array(__NAMESPACE__.'\\ProcessUtils', 'escapeArgument'), $arguments));

        if ($this->inheritEnv) {
            // include $_ENV for BC purposes
            $env = array_replace($_ENV, $_SERVER, $this->env);
        } else {
            $env = $this->env;
        }

        return new Process($script, $this->cwd, $env, $this->stdin, $this->timeout, $options);
    }
}
PKy�Zy>�8��1Symfony/Component/Process/PhpExecutableFinder.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process;

/**
 * An executable finder specifically designed for the PHP executable.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class PhpExecutableFinder
{
    private $executableFinder;

    public function __construct()
    {
        $this->executableFinder = new ExecutableFinder();
    }

    /**
     * Finds The PHP executable.
     *
     * @return string|false The PHP executable path or false if it cannot be found
     */
    public function find()
    {
        // HHVM support
        if (defined('HHVM_VERSION') && false !== $hhvm = getenv('PHP_BINARY')) {
            return $hhvm;
        }

        // PHP_BINARY return the current sapi executable
        if (defined('PHP_BINARY') && PHP_BINARY && in_array(PHP_SAPI, array('cli', 'cli-server')) && is_file(PHP_BINARY)) {
            return PHP_BINARY;
        }

        if ($php = getenv('PHP_PATH')) {
            if (!is_executable($php)) {
                return false;
            }

            return $php;
        }

        if ($php = getenv('PHP_PEAR_PHP_BIN')) {
            if (is_executable($php)) {
                return $php;
            }
        }

        $dirs = array(PHP_BINDIR);
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $dirs[] = 'C:\xampp\php\\';
        }

        return $this->executableFinder->find('php', false, $dirs);
    }
}
PKy�Z��M��%Symfony/Component/Process/Process.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process;

use Symfony\Component\Process\Exception\InvalidArgumentException;
use Symfony\Component\Process\Exception\LogicException;
use Symfony\Component\Process\Exception\ProcessTimedOutException;
use Symfony\Component\Process\Exception\RuntimeException;

/**
 * Process is a thin wrapper around proc_* functions to easily
 * start independent PHP processes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class Process
{
    const ERR = 'err';
    const OUT = 'out';

    const STATUS_READY = 'ready';
    const STATUS_STARTED = 'started';
    const STATUS_TERMINATED = 'terminated';

    const STDIN = 0;
    const STDOUT = 1;
    const STDERR = 2;

    // Timeout Precision in seconds.
    const TIMEOUT_PRECISION = 0.2;

    private $callback;
    private $commandline;
    private $cwd;
    private $env;
    private $stdin;
    private $starttime;
    private $lastOutputTime;
    private $timeout;
    private $idleTimeout;
    private $options;
    private $exitcode;
    private $fallbackExitcode;
    private $processInformation;
    private $stdout;
    private $stderr;
    private $enhanceWindowsCompatibility;
    private $enhanceSigchildCompatibility;
    private $process;
    private $status = self::STATUS_READY;
    private $incrementalOutputOffset = 0;
    private $incrementalErrorOutputOffset = 0;
    private $tty;

    private $useFileHandles = false;
    /** @var ProcessPipes */
    private $processPipes;

    private static $sigchild;

    /**
     * Exit codes translation table.
     *
     * User-defined errors must use exit codes in the 64-113 range.
     *
     * @var array
     */
    public static $exitCodes = array(
        0 => 'OK',
        1 => 'General error',
        2 => 'Misuse of shell builtins',

        126 => 'Invoked command cannot execute',
        127 => 'Command not found',
        128 => 'Invalid exit argument',

        // signals
        129 => 'Hangup',
        130 => 'Interrupt',
        131 => 'Quit and dump core',
        132 => 'Illegal instruction',
        133 => 'Trace/breakpoint trap',
        134 => 'Process aborted',
        135 => 'Bus error: "access to undefined portion of memory object"',
        136 => 'Floating point exception: "erroneous arithmetic operation"',
        137 => 'Kill (terminate immediately)',
        138 => 'User-defined 1',
        139 => 'Segmentation violation',
        140 => 'User-defined 2',
        141 => 'Write to pipe with no one reading',
        142 => 'Signal raised by alarm',
        143 => 'Termination (request to terminate)',
        // 144 - not defined
        145 => 'Child process terminated, stopped (or continued*)',
        146 => 'Continue if stopped',
        147 => 'Stop executing temporarily',
        148 => 'Terminal stop signal',
        149 => 'Background process attempting to read from tty ("in")',
        150 => 'Background process attempting to write to tty ("out")',
        151 => 'Urgent data available on socket',
        152 => 'CPU time limit exceeded',
        153 => 'File size limit exceeded',
        154 => 'Signal raised by timer counting virtual time: "virtual timer expired"',
        155 => 'Profiling timer expired',
        // 156 - not defined
        157 => 'Pollable event',
        // 158 - not defined
        159 => 'Bad syscall',
    );

    /**
     * Constructor.
     *
     * @param string             $commandline The command line to run
     * @param string|null        $cwd         The working directory or null to use the working dir of the current PHP process
     * @param array|null         $env         The environment variables or null to inherit
     * @param string|null        $stdin       The STDIN content
     * @param integer|float|null $timeout     The timeout in seconds or null to disable
     * @param array              $options     An array of options for proc_open
     *
     * @throws RuntimeException When proc_open is not installed
     *
     * @api
     */
    public function __construct($commandline, $cwd = null, array $env = null, $stdin = null, $timeout = 60, array $options = array())
    {
        if (!function_exists('proc_open')) {
            throw new RuntimeException('The Process class relies on proc_open, which is not available on your PHP installation.');
        }

        $this->commandline = $commandline;
        $this->cwd = $cwd;

        // on Windows, if the cwd changed via chdir(), proc_open defaults to the dir where PHP was started
        // on Gnu/Linux, PHP builds with --enable-maintainer-zts are also affected
        // @see : https://bugs.php.net/bug.php?id=51800
        // @see : https://bugs.php.net/bug.php?id=50524

        if (null === $this->cwd && (defined('ZEND_THREAD_SAFE') || defined('PHP_WINDOWS_VERSION_BUILD'))) {
            $this->cwd = getcwd();
        }
        if (null !== $env) {
            $this->setEnv($env);
        } else {
            $this->env = null;
        }
        $this->stdin = $stdin;
        $this->setTimeout($timeout);
        $this->useFileHandles = defined('PHP_WINDOWS_VERSION_BUILD');
        $this->enhanceWindowsCompatibility = true;
        $this->enhanceSigchildCompatibility = !defined('PHP_WINDOWS_VERSION_BUILD') && $this->isSigchildEnabled();
        $this->options = array_replace(array('suppress_errors' => true, 'binary_pipes' => true), $options);
    }

    public function __destruct()
    {
        // stop() will check if we have a process running.
        $this->stop();
    }

    public function __clone()
    {
        $this->resetProcessData();
    }

    /**
     * Runs the process.
     *
     * The callback receives the type of output (out or err) and
     * some bytes from the output in real-time. It allows to have feedback
     * from the independent process during execution.
     *
     * The STDOUT and STDERR are also available after the process is finished
     * via the getOutput() and getErrorOutput() methods.
     *
     * @param callable|null $callback A PHP callback to run whenever there is some
     *                                output available on STDOUT or STDERR
     *
     * @return integer The exit status code
     *
     * @throws RuntimeException When process can't be launched
     * @throws RuntimeException When process stopped after receiving signal
     *
     * @api
     */
    public function run($callback = null)
    {
        $this->start($callback);

        return $this->wait();
    }

    /**
     * Starts the process and returns after sending the STDIN.
     *
     * This method blocks until all STDIN data is sent to the process then it
     * returns while the process runs in the background.
     *
     * The termination of the process can be awaited with wait().
     *
     * The callback receives the type of output (out or err) and some bytes from
     * the output in real-time while writing the standard input to the process.
     * It allows to have feedback from the independent process during execution.
     * If there is no callback passed, the wait() method can be called
     * with true as a second parameter then the callback will get all data occurred
     * in (and since) the start call.
     *
     * @param callable|null $callback A PHP callback to run whenever there is some
     *                                output available on STDOUT or STDERR
     *
     * @return Process The process itself
     *
     * @throws RuntimeException When process can't be launched
     * @throws RuntimeException When process is already running
     */
    public function start($callback = null)
    {
        if ($this->isRunning()) {
            throw new RuntimeException('Process is already running');
        }

        $this->resetProcessData();
        $this->starttime = $this->lastOutputTime = microtime(true);
        $this->callback = $this->buildCallback($callback);
        $descriptors = $this->getDescriptors();

        $commandline = $this->commandline;

        if (defined('PHP_WINDOWS_VERSION_BUILD') && $this->enhanceWindowsCompatibility) {
            $commandline = 'cmd /V:ON /E:ON /C "('.$commandline.')"';
            foreach ($this->processPipes->getFiles() as $offset => $filename) {
                $commandline .= ' '.$offset.'>'.$filename;
            }

            if (!isset($this->options['bypass_shell'])) {
                $this->options['bypass_shell'] = true;
            }
        }

        $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $this->env, $this->options);

        if (!is_resource($this->process)) {
            throw new RuntimeException('Unable to launch a new process.');
        }
        $this->status = self::STATUS_STARTED;

        $this->processPipes->unblock();

        if ($this->tty) {
            return;
        }

        $this->processPipes->write(false, $this->stdin);
        $this->updateStatus(false);
        $this->checkTimeout();
    }

    /**
     * Restarts the process.
     *
     * Be warned that the process is cloned before being started.
     *
     * @param callable|null $callback A PHP callback to run whenever there is some
     *                                output available on STDOUT or STDERR
     *
     * @return Process The new process
     *
     * @throws RuntimeException When process can't be launched
     * @throws RuntimeException When process is already running
     *
     * @see start()
     */
    public function restart($callback = null)
    {
        if ($this->isRunning()) {
            throw new RuntimeException('Process is already running');
        }

        $process = clone $this;
        $process->start($callback);

        return $process;
    }

    /**
     * Waits for the process to terminate.
     *
     * The callback receives the type of output (out or err) and some bytes
     * from the output in real-time while writing the standard input to the process.
     * It allows to have feedback from the independent process during execution.
     *
     * @param callable|null $callback A valid PHP callback
     *
     * @return integer The exitcode of the process
     *
     * @throws RuntimeException When process timed out
     * @throws RuntimeException When process stopped after receiving signal
     * @throws LogicException   When process is not yet started
     */
    public function wait($callback = null)
    {
        $this->requireProcessIsStarted(__FUNCTION__);

        $this->updateStatus(false);
        if (null !== $callback) {
            $this->callback = $this->buildCallback($callback);
        }

        do {
            $this->checkTimeout();
            $running = defined('PHP_WINDOWS_VERSION_BUILD') ? $this->isRunning() : $this->processPipes->hasOpenHandles();
            $close = !defined('PHP_WINDOWS_VERSION_BUILD') || !$running;;
            $this->readPipes(true, $close);
        } while ($running);

        while ($this->isRunning()) {
            usleep(1000);
        }

        if ($this->processInformation['signaled']) {
            throw new RuntimeException(sprintf('The process has been signaled with signal "%s".', $this->processInformation['termsig']));
        }

        return $this->exitcode;
    }

    /**
     * Returns the Pid (process identifier), if applicable.
     *
     * @return integer|null The process id if running, null otherwise
     *
     * @throws RuntimeException In case --enable-sigchild is activated
     */
    public function getPid()
    {
        if ($this->isSigchildEnabled()) {
            throw new RuntimeException('This PHP has been compiled with --enable-sigchild. The process identifier can not be retrieved.');
        }

        $this->updateStatus(false);

        return $this->isRunning() ? $this->processInformation['pid'] : null;
    }

    /**
     * Sends a POSIX signal to the process.
     *
     * @param  integer $signal A valid POSIX signal (see http://www.php.net/manual/en/pcntl.constants.php)
     *
     * @return Process
     *
     * @throws LogicException   In case the process is not running
     * @throws RuntimeException In case --enable-sigchild is activated
     * @throws RuntimeException In case of failure
     */
    public function signal($signal)
    {
        $this->doSignal($signal, true);

        return $this;
    }

    /**
     * Returns the current output of the process (STDOUT).
     *
     * @return string The process output
     *
     * @throws LogicException In case the process is not started
     *
     * @api
     */
    public function getOutput()
    {
        $this->requireProcessIsStarted(__FUNCTION__);

        $this->readPipes(false, defined('PHP_WINDOWS_VERSION_BUILD') ? !$this->processInformation['running'] : true);

        return $this->stdout;
    }

    /**
     * Returns the output incrementally.
     *
     * In comparison with the getOutput method which always return the whole
     * output, this one returns the new output since the last call.
     *
     * @throws LogicException In case the process is not started
     *
     * @return string The process output since the last call
     */
    public function getIncrementalOutput()
    {
        $this->requireProcessIsStarted(__FUNCTION__);

        $data = $this->getOutput();

        $latest = substr($data, $this->incrementalOutputOffset);
        $this->incrementalOutputOffset = strlen($data);

        return $latest;
    }

    /**
     * Clears the process output.
     *
     * @return Process
     */
    public function clearOutput()
    {
        $this->stdout = '';
        $this->incrementalOutputOffset = 0;

        return $this;
    }

    /**
     * Returns the current error output of the process (STDERR).
     *
     * @return string The process error output
     *
     * @throws LogicException In case the process is not started
     *
     * @api
     */
    public function getErrorOutput()
    {
        $this->requireProcessIsStarted(__FUNCTION__);

        $this->readPipes(false, defined('PHP_WINDOWS_VERSION_BUILD') ? !$this->processInformation['running'] : true);

        return $this->stderr;
    }

    /**
     * Returns the errorOutput incrementally.
     *
     * In comparison with the getErrorOutput method which always return the
     * whole error output, this one returns the new error output since the last
     * call.
     *
     * @throws LogicException In case the process is not started
     *
     * @return string The process error output since the last call
     */
    public function getIncrementalErrorOutput()
    {
        $this->requireProcessIsStarted(__FUNCTION__);

        $data = $this->getErrorOutput();

        $latest = substr($data, $this->incrementalErrorOutputOffset);
        $this->incrementalErrorOutputOffset = strlen($data);

        return $latest;
    }

    /**
     * Clears the process output.
     *
     * @return Process
     */
    public function clearErrorOutput()
    {
        $this->stderr = '';
        $this->incrementalErrorOutputOffset = 0;

        return $this;
    }

    /**
     * Returns the exit code returned by the process.
     *
     * @return null|integer The exit status code, null if the Process is not terminated
     *
     * @throws RuntimeException In case --enable-sigchild is activated and the sigchild compatibility mode is disabled
     *
     * @api
     */
    public function getExitCode()
    {
        if ($this->isSigchildEnabled() && !$this->enhanceSigchildCompatibility) {
            throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.');
        }

        $this->updateStatus(false);

        return $this->exitcode;
    }

    /**
     * Returns a string representation for the exit code returned by the process.
     *
     * This method relies on the Unix exit code status standardization
     * and might not be relevant for other operating systems.
     *
     * @return null|string A string representation for the exit status code, null if the Process is not terminated.
     *
     * @throws RuntimeException In case --enable-sigchild is activated and the sigchild compatibility mode is disabled
     *
     * @see http://tldp.org/LDP/abs/html/exitcodes.html
     * @see http://en.wikipedia.org/wiki/Unix_signal
     */
    public function getExitCodeText()
    {
        if (null === $exitcode = $this->getExitCode()) {
            return;
        }

        return isset(self::$exitCodes[$exitcode]) ? self::$exitCodes[$exitcode] : 'Unknown error';
    }

    /**
     * Checks if the process ended successfully.
     *
     * @return Boolean true if the process ended successfully, false otherwise
     *
     * @api
     */
    public function isSuccessful()
    {
        return 0 === $this->getExitCode();
    }

    /**
     * Returns true if the child process has been terminated by an uncaught signal.
     *
     * It always returns false on Windows.
     *
     * @return Boolean
     *
     * @throws RuntimeException In case --enable-sigchild is activated
     * @throws LogicException   In case the process is not terminated
     *
     * @api
     */
    public function hasBeenSignaled()
    {
        $this->requireProcessIsTerminated(__FUNCTION__);

        if ($this->isSigchildEnabled()) {
            throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.');
        }

        $this->updateStatus(false);

        return $this->processInformation['signaled'];
    }

    /**
     * Returns the number of the signal that caused the child process to terminate its execution.
     *
     * It is only meaningful if hasBeenSignaled() returns true.
     *
     * @return integer
     *
     * @throws RuntimeException In case --enable-sigchild is activated
     * @throws LogicException   In case the process is not terminated
     *
     * @api
     */
    public function getTermSignal()
    {
        $this->requireProcessIsTerminated(__FUNCTION__);

        if ($this->isSigchildEnabled()) {
            throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.');
        }

        $this->updateStatus(false);

        return $this->processInformation['termsig'];
    }

    /**
     * Returns true if the child process has been stopped by a signal.
     *
     * It always returns false on Windows.
     *
     * @return Boolean
     *
     * @throws LogicException In case the process is not terminated
     *
     * @api
     */
    public function hasBeenStopped()
    {
        $this->requireProcessIsTerminated(__FUNCTION__);

        $this->updateStatus(false);

        return $this->processInformation['stopped'];
    }

    /**
     * Returns the number of the signal that caused the child process to stop its execution.
     *
     * It is only meaningful if hasBeenStopped() returns true.
     *
     * @return integer
     *
     * @throws LogicException In case the process is not terminated
     *
     * @api
     */
    public function getStopSignal()
    {
        $this->requireProcessIsTerminated(__FUNCTION__);

        $this->updateStatus(false);

        return $this->processInformation['stopsig'];
    }

    /**
     * Checks if the process is currently running.
     *
     * @return Boolean true if the process is currently running, false otherwise
     */
    public function isRunning()
    {
        if (self::STATUS_STARTED !== $this->status) {
            return false;
        }

        $this->updateStatus(false);

        return $this->processInformation['running'];
    }

    /**
     * Checks if the process has been started with no regard to the current state.
     *
     * @return Boolean true if status is ready, false otherwise
     */
    public function isStarted()
    {
        return $this->status != self::STATUS_READY;
    }

    /**
     * Checks if the process is terminated.
     *
     * @return Boolean true if process is terminated, false otherwise
     */
    public function isTerminated()
    {
        $this->updateStatus(false);

        return $this->status == self::STATUS_TERMINATED;
    }

    /**
     * Gets the process status.
     *
     * The status is one of: ready, started, terminated.
     *
     * @return string The current process status
     */
    public function getStatus()
    {
        $this->updateStatus(false);

        return $this->status;
    }

    /**
     * Stops the process.
     *
     * @param integer|float $timeout The timeout in seconds
     * @param integer       $signal  A POSIX signal to send in case the process has not stop at timeout, default is SIGKILL
     *
     * @return integer The exit-code of the process
     *
     * @throws RuntimeException if the process got signaled
     */
    public function stop($timeout = 10, $signal = null)
    {
        $timeoutMicro = microtime(true) + $timeout;
        if ($this->isRunning()) {
            if (defined('PHP_WINDOWS_VERSION_BUILD') && !$this->isSigchildEnabled()) {
                exec(sprintf("taskkill /F /T /PID %d 2>&1", $this->getPid()), $output, $exitCode);
                if ($exitCode > 0) {
                    throw new RuntimeException('Unable to kill the process');
                }
            }
            proc_terminate($this->process);
            do {
                usleep(1000);
            } while ($this->isRunning() && microtime(true) < $timeoutMicro);

            if ($this->isRunning() && !$this->isSigchildEnabled()) {
                if (null !== $signal || defined('SIGKILL')) {
                    // avoid exception here :
                    // process is supposed to be running, but it might have stop
                    // just after this line.
                    // in any case, let's silently discard the error, we can not do anything
                    $this->doSignal($signal ?: SIGKILL, false);
                }
            }
        }

        $this->updateStatus(false);
        if ($this->processInformation['running']) {
            $this->close();
        }

        return $this->exitcode;
    }

    /**
     * Adds a line to the STDOUT stream.
     *
     * @param string $line The line to append
     */
    public function addOutput($line)
    {
        $this->lastOutputTime = microtime(true);
        $this->stdout .= $line;
    }

    /**
     * Adds a line to the STDERR stream.
     *
     * @param string $line The line to append
     */
    public function addErrorOutput($line)
    {
        $this->lastOutputTime = microtime(true);
        $this->stderr .= $line;
    }

    /**
     * Gets the command line to be executed.
     *
     * @return string The command to execute
     */
    public function getCommandLine()
    {
        return $this->commandline;
    }

    /**
     * Sets the command line to be executed.
     *
     * @param string $commandline The command to execute
     *
     * @return self The current Process instance
     */
    public function setCommandLine($commandline)
    {
        $this->commandline = $commandline;

        return $this;
    }

    /**
     * Gets the process timeout (max. runtime).
     *
     * @return float|null The timeout in seconds or null if it's disabled
     */
    public function getTimeout()
    {
        return $this->timeout;
    }

    /**
     * Gets the process idle timeout (max. time since last output).
     *
     * @return float|null The timeout in seconds or null if it's disabled
     */
    public function getIdleTimeout()
    {
        return $this->idleTimeout;
    }

    /**
     * Sets the process timeout (max. runtime).
     *
     * To disable the timeout, set this value to null.
     *
     * @param integer|float|null $timeout The timeout in seconds
     *
     * @return self The current Process instance
     *
     * @throws InvalidArgumentException if the timeout is negative
     */
    public function setTimeout($timeout)
    {
        $this->timeout = $this->validateTimeout($timeout);

        return $this;
    }

    /**
     * Sets the process idle timeout (max. time since last output).
     *
     * To disable the timeout, set this value to null.
     *
     * @param integer|float|null $timeout The timeout in seconds
     *
     * @return self The current Process instance.
     *
     * @throws InvalidArgumentException if the timeout is negative
     */
    public function setIdleTimeout($timeout)
    {
        $this->idleTimeout = $this->validateTimeout($timeout);

        return $this;
    }

    /**
     * Enables or disables the TTY mode.
     *
     * @param boolean $tty True to enabled and false to disable
     *
     * @return self The current Process instance
     */
    public function setTty($tty)
    {
        $this->tty = (Boolean) $tty;

        return $this;
    }

    /**
     * Checks if the TTY mode is enabled.
     *
     * @return Boolean true if the TTY mode is enabled, false otherwise
     */
    public function isTty()
    {
        return $this->tty;
    }

    /**
     * Gets the working directory.
     *
     * @return string|null The current working directory or null on failure
     */
    public function getWorkingDirectory()
    {
        if (null === $this->cwd) {
            // getcwd() will return false if any one of the parent directories does not have
            // the readable or search mode set, even if the current directory does
            return getcwd() ?: null;
        }

        return $this->cwd;
    }

    /**
     * Sets the current working directory.
     *
     * @param string $cwd The new working directory
     *
     * @return self The current Process instance
     */
    public function setWorkingDirectory($cwd)
    {
        $this->cwd = $cwd;

        return $this;
    }

    /**
     * Gets the environment variables.
     *
     * @return array The current environment variables
     */
    public function getEnv()
    {
        return $this->env;
    }

    /**
     * Sets the environment variables.
     *
     * An environment variable value should be a string.
     * If it is an array, the variable is ignored.
     *
     * That happens in PHP when 'argv' is registered into
     * the $_ENV array for instance.
     *
     * @param array $env The new environment variables
     *
     * @return self The current Process instance
     */
    public function setEnv(array $env)
    {
        // Process can not handle env values that are arrays
        $env = array_filter($env, function ($value) {
            return !is_array($value);
        });

        $this->env = array();
        foreach ($env as $key => $value) {
            $this->env[(binary) $key] = (binary) $value;
        }

        return $this;
    }

    /**
     * Gets the contents of STDIN.
     *
     * @return string|null The current contents
     */
    public function getStdin()
    {
        return $this->stdin;
    }

    /**
     * Sets the contents of STDIN.
     *
     * @param string|null $stdin The new contents
     *
     * @return self The current Process instance
     */
    public function setStdin($stdin)
    {
        $this->stdin = $stdin;

        return $this;
    }

    /**
     * Gets the options for proc_open.
     *
     * @return array The current options
     */
    public function getOptions()
    {
        return $this->options;
    }

    /**
     * Sets the options for proc_open.
     *
     * @param array $options The new options
     *
     * @return self The current Process instance
     */
    public function setOptions(array $options)
    {
        $this->options = $options;

        return $this;
    }

    /**
     * Gets whether or not Windows compatibility is enabled.
     *
     * This is true by default.
     *
     * @return Boolean
     */
    public function getEnhanceWindowsCompatibility()
    {
        return $this->enhanceWindowsCompatibility;
    }

    /**
     * Sets whether or not Windows compatibility is enabled.
     *
     * @param Boolean $enhance
     *
     * @return self The current Process instance
     */
    public function setEnhanceWindowsCompatibility($enhance)
    {
        $this->enhanceWindowsCompatibility = (Boolean) $enhance;

        return $this;
    }

    /**
     * Returns whether sigchild compatibility mode is activated or not.
     *
     * @return Boolean
     */
    public function getEnhanceSigchildCompatibility()
    {
        return $this->enhanceSigchildCompatibility;
    }

    /**
     * Activates sigchild compatibility mode.
     *
     * Sigchild compatibility mode is required to get the exit code and
     * determine the success of a process when PHP has been compiled with
     * the --enable-sigchild option
     *
     * @param Boolean $enhance
     *
     * @return self The current Process instance
     */
    public function setEnhanceSigchildCompatibility($enhance)
    {
        $this->enhanceSigchildCompatibility = (Boolean) $enhance;

        return $this;
    }

    /**
     * Performs a check between the timeout definition and the time the process started.
     *
     * In case you run a background process (with the start method), you should
     * trigger this method regularly to ensure the process timeout
     *
     * @throws ProcessTimedOutException In case the timeout was reached
     */
    public function checkTimeout()
    {
        if ($this->status !== self::STATUS_STARTED) {
            return;
        }

        if (null !== $this->timeout && $this->timeout < microtime(true) - $this->starttime) {
            $this->stop(0);

            throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_GENERAL);
        }

        if (null !== $this->idleTimeout && $this->idleTimeout < microtime(true) - $this->lastOutputTime) {
            $this->stop(0);

            throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_IDLE);
        }
    }

    /**
     * Creates the descriptors needed by the proc_open.
     *
     * @return array
     */
    private function getDescriptors()
    {
        $this->processPipes = new ProcessPipes($this->useFileHandles, $this->tty);
        $descriptors = $this->processPipes->getDescriptors();

        if (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
            // last exit code is output on the fourth pipe and caught to work around --enable-sigchild
            $descriptors = array_merge($descriptors, array(array('pipe', 'w')));

            $this->commandline = '('.$this->commandline.') 3>/dev/null; code=$?; echo $code >&3; exit $code';
        }

        return $descriptors;
    }

    /**
     * Builds up the callback used by wait().
     *
     * The callbacks adds all occurred output to the specific buffer and calls
     * the user callback (if present) with the received output.
     *
     * @param callable|null $callback The user defined PHP callback
     *
     * @return callable A PHP callable
     */
    protected function buildCallback($callback)
    {
        $that = $this;
        $out = self::OUT;
        $err = self::ERR;
        $callback = function ($type, $data) use ($that, $callback, $out, $err) {
            if ($out == $type) {
                $that->addOutput($data);
            } else {
                $that->addErrorOutput($data);
            }

            if (null !== $callback) {
                call_user_func($callback, $type, $data);
            }
        };

        return $callback;
    }

    /**
     * Updates the status of the process, reads pipes.
     *
     * @param Boolean $blocking Whether to use a blocking read call.
     */
    protected function updateStatus($blocking)
    {
        if (self::STATUS_STARTED !== $this->status) {
            return;
        }

        $this->processInformation = proc_get_status($this->process);
        $this->captureExitCode();

        $this->readPipes($blocking, defined('PHP_WINDOWS_VERSION_BUILD') ? !$this->processInformation['running'] : true);

        if (!$this->processInformation['running']) {
            $this->close();
        }
    }

    /**
     * Returns whether PHP has been compiled with the '--enable-sigchild' option or not.
     *
     * @return Boolean
     */
    protected function isSigchildEnabled()
    {
        if (null !== self::$sigchild) {
            return self::$sigchild;
        }

        if (!function_exists('phpinfo')) {
            return self::$sigchild = false;
        }

        ob_start();
        phpinfo(INFO_GENERAL);

        return self::$sigchild = false !== strpos(ob_get_clean(), '--enable-sigchild');
    }

    /**
     * Validates and returns the filtered timeout.
     *
     * @param integer|float|null $timeout
     *
     * @return float|null
     */
    private function validateTimeout($timeout)
    {
        $timeout = (float) $timeout;

        if (0.0 === $timeout) {
            $timeout = null;
        } elseif ($timeout < 0) {
            throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
        }

        return $timeout;
    }

    /**
     * Reads pipes, executes callback.
     *
     * @param Boolean $blocking Whether to use blocking calls or not.
     * @param Boolean $close    Whether to close file handles or not.
     */
    private function readPipes($blocking, $close)
    {
        if ($close) {
            $result = $this->processPipes->readAndCloseHandles($blocking);
        } else {
            $result = $this->processPipes->read($blocking);
        }

        foreach ($result as $type => $data) {
            if (3 == $type) {
                $this->fallbackExitcode = (int) $data;
            } else {
                call_user_func($this->callback, $type === self::STDOUT ? self::OUT : self::ERR, $data);
            }
        }
    }

    /**
     * Captures the exitcode if mentioned in the process information.
     */
    private function captureExitCode()
    {
        if (isset($this->processInformation['exitcode']) && -1 != $this->processInformation['exitcode']) {
            $this->exitcode = $this->processInformation['exitcode'];
        }
    }

    /**
     * Closes process resource, closes file handles, sets the exitcode.
     *
     * @return Integer The exitcode
     */
    private function close()
    {
        $this->processPipes->close();
        if (is_resource($this->process)) {
            $exitcode = proc_close($this->process);
        } else {
            $exitcode = -1;
        }

        $this->exitcode = -1 !== $exitcode ? $exitcode : (null !== $this->exitcode ? $this->exitcode : -1);
        $this->status = self::STATUS_TERMINATED;

        if (-1 === $this->exitcode && null !== $this->fallbackExitcode) {
            $this->exitcode = $this->fallbackExitcode;
        } elseif (-1 === $this->exitcode && $this->processInformation['signaled'] && 0 < $this->processInformation['termsig']) {
            // if process has been signaled, no exitcode but a valid termsig, apply Unix convention
            $this->exitcode = 128 + $this->processInformation['termsig'];
        }

        return $this->exitcode;
    }

    /**
     * Resets data related to the latest run of the process.
     */
    private function resetProcessData()
    {
        $this->starttime = null;
        $this->callback = null;
        $this->exitcode = null;
        $this->fallbackExitcode = null;
        $this->processInformation = null;
        $this->stdout = null;
        $this->stderr = null;
        $this->process = null;
        $this->status = self::STATUS_READY;
        $this->incrementalOutputOffset = 0;
        $this->incrementalErrorOutputOffset = 0;
    }

    /**
     * Sends a POSIX signal to the process.
     *
     * @param  integer $signal         A valid POSIX signal (see http://www.php.net/manual/en/pcntl.constants.php)
     * @param  Boolean $throwException Whether to throw exception in case signal failed
     *
     * @return Boolean True if the signal was sent successfully, false otherwise
     *
     * @throws LogicException   In case the process is not running
     * @throws RuntimeException In case --enable-sigchild is activated
     * @throws RuntimeException In case of failure
     */
    private function doSignal($signal, $throwException)
    {
        if (!$this->isRunning()) {
            if ($throwException) {
                throw new LogicException('Can not send signal on a non running process.');
            }

            return false;
        }

        if ($this->isSigchildEnabled()) {
            if ($throwException) {
                throw new RuntimeException('This PHP has been compiled with --enable-sigchild. The process can not be signaled.');
            }

            return false;
        }

        if (true !== @proc_terminate($this->process, $signal)) {
            if ($throwException) {
                throw new RuntimeException(sprintf('Error while sending signal `%s`.', $signal));
            }

            return false;
        }

        return true;
    }

    /**
     * Ensures the process is running or terminated, throws a LogicException if the process has a not started.
     *
     * @param $functionName The function name that was called.
     *
     * @throws LogicException If the process has not run.
     */
    private function requireProcessIsStarted($functionName)
    {
        if (!$this->isStarted()) {
            throw new LogicException(sprintf('Process must be started before calling %s.', $functionName));
        }
    }

    /**
     * Ensures the process is terminated, throws a LogicException if the process has a status different than `terminated`.
     *
     * @param $functionName The function name that was called.
     *
     * @throws LogicException If the process is not yet terminated.
     */
    private function requireProcessIsTerminated($functionName)
    {
        if (!$this->isTerminated()) {
            throw new LogicException(sprintf('Process must be terminated before calling %s.', $functionName));
        }
    }
}
PKy�Z[i55ESymfony/Component/Serializer/Normalizer/SerializerAwareNormalizer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Normalizer;

use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Component\Serializer\SerializerAwareInterface;

/**
 * SerializerAware Normalizer implementation
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
abstract class SerializerAwareNormalizer implements SerializerAwareInterface
{
    /**
     * @var SerializerInterface
     */
    protected $serializer;

    /**
     * {@inheritdoc}
     */
    public function setSerializer(SerializerInterface $serializer)
    {
        $this->serializer = $serializer;
    }
}
PKy�Z=Vxe::ASymfony/Component/Serializer/Normalizer/NormalizableInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Normalizer;

/**
 * Defines the most basic interface a class must implement to be normalizable
 *
 * If a normalizer is registered for the class and it doesn't implement
 * the Normalizable interfaces, the normalizer will be used instead
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface NormalizableInterface
{
    /**
     * Normalizes the object into an array of scalars|arrays.
     *
     * It is important to understand that the normalize() call should normalize
     * recursively all child objects of the implementor.
     *
     * @param NormalizerInterface $normalizer The normalizer is given so that you
     *   can use it to normalize objects contained within this object.
     * @param string|null $format The format is optionally given to be able to normalize differently
     *   based on different output formats.
     * @param array $context Options for normalizing this object
     *
     * @return array|scalar
     */
    public function normalize(NormalizerInterface $normalizer, $format = null, array $context = array());
}
PKy�Z��SVV<Symfony/Component/Serializer/Normalizer/CustomNormalizer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Normalizer;

/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class CustomNormalizer extends SerializerAwareNormalizer implements NormalizerInterface, DenormalizerInterface
{
    /**
     * {@inheritdoc}
     */
    public function normalize($object, $format = null, array $context = array())
    {
        return $object->normalize($this->serializer, $format, $context);
    }

    /**
     * {@inheritdoc}
     */
    public function denormalize($data, $class, $format = null, array $context = array())
    {
        $object = new $class();
        $object->denormalize($this->serializer, $data, $format, $context);

        return $object;
    }

    /**
     * Checks if the given class implements the NormalizableInterface.
     *
     * @param mixed  $data   Data to normalize.
     * @param string $format The format being (de-)serialized from or into.
     *
     * @return Boolean
     */
    public function supportsNormalization($data, $format = null)
    {
        return $data instanceof NormalizableInterface;
    }

    /**
     * Checks if the given class implements the NormalizableInterface.
     *
     * @param mixed  $data   Data to denormalize from.
     * @param string $type   The class to which the data should be denormalized.
     * @param string $format The format being deserialized from.
     *
     * @return Boolean
     */
    public function supportsDenormalization($data, $type, $format = null)
    {
        $class = new \ReflectionClass($type);

        return $class->isSubclassOf('Symfony\Component\Serializer\Normalizer\DenormalizableInterface');
    }
}
PKy�Z��,,BSymfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Normalizer;

use Symfony\Component\Serializer\Exception\InvalidArgumentException;
use Symfony\Component\Serializer\Exception\RuntimeException;

/**
 * Converts between objects with getter and setter methods and arrays.
 *
 * The normalization process looks at all public methods and calls the ones
 * which have a name starting with get and take no parameters. The result is a
 * map from property names (method name stripped of the get prefix and converted
 * to lower case) to property values. Property values are normalized through the
 * serializer.
 *
 * The denormalization first looks at the constructor of the given class to see
 * if any of the parameters have the same name as one of the properties. The
 * constructor is then called with all parameters or an exception is thrown if
 * any required parameters were not present as properties. Then the denormalizer
 * walks through the given map of property names to property values to see if a
 * setter method exists for any of the properties. If a setter exists it is
 * called with the property value. No automatic denormalization of the value
 * takes place.
 *
 * @author Nils Adermann <naderman@naderman.de>
 */
class GetSetMethodNormalizer extends SerializerAwareNormalizer implements NormalizerInterface, DenormalizerInterface
{
    protected $callbacks = array();
    protected $ignoredAttributes = array();
    protected $camelizedAttributes = array();

    /**
     * Set normalization callbacks.
     *
     * @param callable[] $callbacks help normalize the result
     *
     * @throws InvalidArgumentException if a non-callable callback is set
     */
    public function setCallbacks(array $callbacks)
    {
        foreach ($callbacks as $attribute => $callback) {
            if (!is_callable($callback)) {
                throw new InvalidArgumentException(sprintf('The given callback for attribute "%s" is not callable.', $attribute));
            }
        }
        $this->callbacks = $callbacks;
    }

    /**
     * Set ignored attributes for normalization
     *
     * @param array $ignoredAttributes
     */
    public function setIgnoredAttributes(array $ignoredAttributes)
    {
        $this->ignoredAttributes = $ignoredAttributes;
    }

    /**
     * Set attributes to be camelized on denormalize
     *
     * @param array $camelizedAttributes
     */
    public function setCamelizedAttributes(array $camelizedAttributes)
    {
        $this->camelizedAttributes = $camelizedAttributes;
    }

    /**
     * {@inheritdoc}
     */
    public function normalize($object, $format = null, array $context = array())
    {
        $reflectionObject = new \ReflectionObject($object);
        $reflectionMethods = $reflectionObject->getMethods(\ReflectionMethod::IS_PUBLIC);

        $attributes = array();
        foreach ($reflectionMethods as $method) {
            if ($this->isGetMethod($method)) {
                $attributeName = lcfirst(substr($method->name, 3));

                if (in_array($attributeName, $this->ignoredAttributes)) {
                    continue;
                }

                $attributeValue = $method->invoke($object);
                if (array_key_exists($attributeName, $this->callbacks)) {
                    $attributeValue = call_user_func($this->callbacks[$attributeName], $attributeValue);
                }
                if (null !== $attributeValue && !is_scalar($attributeValue)) {
                    if (!$this->serializer instanceof NormalizerInterface) {
                        throw new \LogicException(sprintf('Cannot normalize attribute "%s" because injected serializer is not a normalizer', $attributeName));
                    }
                    $attributeValue = $this->serializer->normalize($attributeValue, $format);
                }

                $attributes[$attributeName] = $attributeValue;
            }
        }

        return $attributes;
    }

    /**
     * {@inheritdoc}
     */
    public function denormalize($data, $class, $format = null, array $context = array())
    {
        $reflectionClass = new \ReflectionClass($class);
        $constructor = $reflectionClass->getConstructor();

        if ($constructor) {
            $constructorParameters = $constructor->getParameters();

            $params = array();
            foreach ($constructorParameters as $constructorParameter) {
                $paramName = lcfirst($this->formatAttribute($constructorParameter->name));

                if (isset($data[$paramName])) {
                    $params[] = $data[$paramName];
                    // don't run set for a parameter passed to the constructor
                    unset($data[$paramName]);
                } elseif (!$constructorParameter->isOptional()) {
                    throw new RuntimeException(
                        'Cannot create an instance of '.$class.
                        ' from serialized data because its constructor requires '.
                        'parameter "'.$constructorParameter->name.
                        '" to be present.');
                }
            }

            $object = $reflectionClass->newInstanceArgs($params);
        } else {
            $object = new $class;
        }

        foreach ($data as $attribute => $value) {
            $setter = 'set'.$this->formatAttribute($attribute);

            if (method_exists($object, $setter)) {
                $object->$setter($value);
            }
        }

        return $object;
    }

    /**
     * Format attribute name to access parameters or methods
     * As option, if attribute name is found on camelizedAttributes array
     * returns attribute name in camelcase format
     *
     * @param string $attributeName
     * @return string
     */
    protected function formatAttribute($attributeName)
    {
        if (in_array($attributeName, $this->camelizedAttributes)) {
            return preg_replace_callback(
                '/(^|_|\.)+(.)/', function ($match) {
                    return ('.' === $match[1] ? '_' : '').strtoupper($match[2]);
                }, $attributeName
            );
        }

        return $attributeName;
    }

    /**
     * {@inheritDoc}
     */
    public function supportsNormalization($data, $format = null)
    {
        return is_object($data) && $this->supports(get_class($data));
    }

    /**
     * {@inheritDoc}
     */
    public function supportsDenormalization($data, $type, $format = null)
    {
        return $this->supports($type);
    }

    /**
     * Checks if the given class has any get{Property} method.
     *
     * @param string $class
     *
     * @return Boolean
     */
    private function supports($class)
    {
        $class = new \ReflectionClass($class);
        $methods = $class->getMethods(\ReflectionMethod::IS_PUBLIC);
        foreach ($methods as $method) {
            if ($this->isGetMethod($method)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Checks if a method's name is get.* and can be called without parameters.
     *
     * @param \ReflectionMethod $method the method to check
     *
     * @return Boolean whether the method is a getter.
     */
    private function isGetMethod(\ReflectionMethod $method)
    {
        return (
            0 === strpos($method->name, 'get') &&
            3 < strlen($method->name) &&
            0 === $method->getNumberOfRequiredParameters()
        );
    }
}
PKy�Z"p�yy?Symfony/Component/Serializer/Normalizer/NormalizerInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Normalizer;

/**
 * Defines the interface of normalizers.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface NormalizerInterface
{
    /**
     * Normalizes an object into a set of arrays/scalars
     *
     * @param object $object object to normalize
     * @param string $format format the normalization result will be encoded as
     * @param array $context Context options for the normalizer
     *
     * @return array|scalar
     */
    public function normalize($object, $format = null, array $context = array());

    /**
     * Checks whether the given class is supported for normalization by this normalizer
     *
     * @param mixed  $data   Data to normalize.
     * @param string $format The format being (de-)serialized from or into.
     *
     * @return Boolean
     */
    public function supportsNormalization($data, $format = null);
}
PKy�Z�qU���CSymfony/Component/Serializer/Normalizer/DenormalizableInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Normalizer;

/**
 * Defines the most basic interface a class must implement to be denormalizable
 *
 * If a denormalizer is registered for the class and it doesn't implement
 * the Denormalizable interfaces, the normalizer will be used instead
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface DenormalizableInterface
{
    /**
     * Denormalizes the object back from an array of scalars|arrays.
     *
     * It is important to understand that the denormalize() call should denormalize
     * recursively all child objects of the implementor.
     *
     * @param DenormalizerInterface $denormalizer The denormalizer is given so that you
     *   can use it to denormalize objects contained within this object.
     * @param array|scalar $data   The data from which to re-create the object.
     * @param string|null  $format The format is optionally given to be able to denormalize differently
     *   based on different input formats.
     * @param array        $context options for denormalizing
     */
    public function denormalize(DenormalizerInterface $denormalizer, $data, $format = null, array $context = array());
}
PKz�Z���ASymfony/Component/Serializer/Normalizer/DenormalizerInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Normalizer;

/**
 * Defines the interface of denormalizers.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface DenormalizerInterface
{
    /**
     * Denormalizes data back into an object of the given class
     *
     * @param mixed  $data   data to restore
     * @param string $class  the expected class to instantiate
     * @param string $format format the given data was extracted from
     * @param array  $context options available to the denormalizer
     *
     * @return object
     */
    public function denormalize($data, $class, $format = null, array $context = array());

    /**
     * Checks whether the given class is supported for denormalization by this normalizer
     *
     * @param mixed  $data   Data to denormalize from.
     * @param string $type   The class to which the data should be denormalized.
     * @param string $format The format being deserialized from.
     *
     * @return Boolean
     */
    public function supportsDenormalization($data, $type, $format = null);
}
PKz�Z���OO9Symfony/Component/Serializer/SerializerAwareInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer;

/**
 * Defines the interface of encoders
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface SerializerAwareInterface
{
    /**
     * Sets the owning Serializer object
     *
     * @param SerializerInterface $serializer
     */
    public function setSerializer(SerializerInterface $serializer);
}
PKz�Z��TT+Symfony/Component/Serializer/autoloader.phpnu�[���<?php

spl_autoload_register(function ($class) {
    if ('\\' == $class[0]) {
        $class = substr($class, 1);
    }

    if (
        0 === strpos($class, 'Symfony\\Component\\Serializer\\')
        &&
        file_exists($file = __DIR__.'/../../../'.str_replace('\\', '/', $class).'.php')
    ) {
        require_once $file;
    }
});
PKz�Zx蕰

4Symfony/Component/Serializer/SerializerInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer;

/**
 * Defines the interface of the Serializer
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface SerializerInterface
{
    /**
     * Serializes data in the appropriate format
     *
     * @param mixed  $data    any data
     * @param string $format  format name
     * @param array  $context options normalizers/encoders have access to
     *
     * @return string
     */
    public function serialize($data, $format, array $context = array());

    /**
     * Deserializes data into the given type.
     *
     * @param mixed  $data
     * @param string $type
     * @param string $format
     * @param array  $context
     *
     * @return object
     */
    public function deserialize($data, $type, $format, array $context = array());
}
PKz�Z,�c��9Symfony/Component/Serializer/Encoder/EncoderInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Encoder;

/**
 * Defines the interface of encoders
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface EncoderInterface
{
    /**
     * Encodes data into the given format
     *
     * @param mixed  $data   Data to encode
     * @param string $format Format name
     * @param array  $context options that normalizers/encoders have access to.
     *
     * @return scalar
     */
    public function encode($data, $format, array $context = array());

    /**
     * Checks whether the serializer can encode to given format
     *
     * @param string $format format name
     *
     * @return Boolean
     */
    public function supportsEncoding($format);
}
PKz�Z��[�5�53Symfony/Component/Serializer/Encoder/XmlEncoder.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Encoder;

use Symfony\Component\Serializer\Exception\UnexpectedValueException;

/**
 * Encodes XML data
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author John Wards <jwards@whiteoctober.co.uk>
 * @author Fabian Vogler <fabian@equivalence.ch>
 */
class XmlEncoder extends SerializerAwareEncoder implements EncoderInterface, DecoderInterface, NormalizationAwareInterface
{
    private $dom;
    private $format;
    private $context;
    private $rootNodeName = 'response';

    /**
     * Construct new XmlEncoder and allow to change the root node element name.
     *
     * @param string $rootNodeName
     */
    public function __construct($rootNodeName = 'response')
    {
        $this->rootNodeName = $rootNodeName;
    }

    /**
     * {@inheritdoc}
     */
    public function encode($data, $format, array $context = array())
    {
        if ($data instanceof \DOMDocument) {
            return $data->saveXML();
        }

        $xmlRootNodeName = $this->resolveXmlRootName($context);

        $this->dom = $this->createDomDocument($context);
        $this->format = $format;
        $this->context = $context;

        if (null !== $data && !is_scalar($data)) {
            $root = $this->dom->createElement($xmlRootNodeName);
            $this->dom->appendChild($root);
            $this->buildXml($root, $data, $xmlRootNodeName);
        } else {
            $this->appendNode($this->dom, $data, $xmlRootNodeName);
        }

        return $this->dom->saveXML();
    }

    /**
     * {@inheritdoc}
     */
    public function decode($data, $format, array $context = array())
    {
        if ('' === trim($data)) {
            throw new UnexpectedValueException('Invalid XML data, it can not be empty.');
        }

        $internalErrors = libxml_use_internal_errors(true);
        $disableEntities = libxml_disable_entity_loader(true);
        libxml_clear_errors();

        $dom = new \DOMDocument();
        $dom->loadXML($data, LIBXML_NONET);

        libxml_use_internal_errors($internalErrors);
        libxml_disable_entity_loader($disableEntities);

        if ($error = libxml_get_last_error()) {
            libxml_clear_errors();

            throw new UnexpectedValueException($error->message);
        }

        foreach ($dom->childNodes as $child) {
            if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) {
                throw new UnexpectedValueException('Document types are not allowed.');
            }
        }

        $xml = simplexml_import_dom($dom);

        if ($error = libxml_get_last_error()) {
            throw new UnexpectedValueException($error->message);
        }

        if (!$xml->count()) {
            if (!$xml->attributes()) {
                return (string) $xml;
            }
            $data = array();
            foreach ($xml->attributes() as $attrkey => $attr) {
                $data['@'.$attrkey] = (string) $attr;
            }
            $data['#'] = (string) $xml;

            return $data;
        }

        return $this->parseXml($xml);
    }

    /**
     * {@inheritdoc}
     */
     public function supportsEncoding($format)
     {
         return 'xml' === $format;
     }

     /**
     * {@inheritdoc}
     */
     public function supportsDecoding($format)
     {
         return 'xml' === $format;
     }

    /**
     * Sets the root node name
     *
     * @param string $name root node name
     */
    public function setRootNodeName($name)
    {
        $this->rootNodeName = $name;
    }

    /**
     * Returns the root node name
     * @return string
     */
    public function getRootNodeName()
    {
        return $this->rootNodeName;
    }

    /**
     * @param \DOMNode $node
     * @param string   $val
     *
     * @return Boolean
     */
    final protected function appendXMLString(\DOMNode $node, $val)
    {
        if (strlen($val) > 0) {
            $frag = $this->dom->createDocumentFragment();
            $frag->appendXML($val);
            $node->appendChild($frag);

            return true;
        }

        return false;
    }

    /**
     * @param \DOMNode $node
     * @param string   $val
     *
     * @return Boolean
     */
    final protected function appendText(\DOMNode $node, $val)
    {
        $nodeText = $this->dom->createTextNode($val);
        $node->appendChild($nodeText);

        return true;
    }

    /**
     * @param \DOMNode $node
     * @param string   $val
     *
     * @return Boolean
     */
    final protected function appendCData(\DOMNode $node, $val)
    {
        $nodeText = $this->dom->createCDATASection($val);
        $node->appendChild($nodeText);

        return true;
    }

    /**
     * @param \DOMNode             $node
     * @param \DOMDocumentFragment $fragment
     *
     * @return Boolean
     */
    final protected function appendDocumentFragment(\DOMNode $node, $fragment)
    {
        if ($fragment instanceof \DOMDocumentFragment) {
            $node->appendChild($fragment);

            return true;
        }

        return false;
    }

    /**
     * Checks the name is a valid xml element name
     *
     * @param string $name
     *
     * @return Boolean
     */
    final protected function isElementNameValid($name)
    {
        return $name &&
            false === strpos($name, ' ') &&
            preg_match('#^[\pL_][\pL0-9._-]*$#ui', $name);
    }

    /**
     * Parse the input SimpleXmlElement into an array.
     *
     * @param \SimpleXmlElement $node xml to parse
     *
     * @return array
     */
    private function parseXml(\SimpleXmlElement $node)
    {
        $data = array();
        if ($node->attributes()) {
            foreach ($node->attributes() as $attrkey => $attr) {
                $data['@'.$attrkey] = (string) $attr;
            }
        }
        foreach ($node->children() as $key => $subnode) {
            if ($subnode->count()) {
                $value = $this->parseXml($subnode);
            } elseif ($subnode->attributes()) {
                $value = array();
                foreach ($subnode->attributes() as $attrkey => $attr) {
                    $value['@'.$attrkey] = (string) $attr;
                }
                $value['#'] = (string) $subnode;
            } else {
                $value = (string) $subnode;
            }

            if ($key === 'item') {
                if (isset($value['@key'])) {
                    if (isset($value['#'])) {
                        $data[$value['@key']] = $value['#'];
                    } else {
                        $data[$value['@key']] = $value;
                    }
                } else {
                    $data['item'][] = $value;
                }
            } elseif (array_key_exists($key, $data) || $key == "entry") {
                if ((false === is_array($data[$key]))  || (false === isset($data[$key][0]))) {
                    $data[$key] = array($data[$key]);
                }
                $data[$key][] = $value;
            } else {
                $data[$key] = $value;
            }
        }

        return $data;
    }

    /**
     * Parse the data and convert it to DOMElements
     *
     * @param \DOMNode     $parentNode
     * @param array|object $data
     * @param string|null  $xmlRootNodeName
     *
     * @return Boolean
     *
     * @throws UnexpectedValueException
     */
    private function buildXml(\DOMNode $parentNode, $data, $xmlRootNodeName = null)
    {
        $append = true;

        if (is_array($data) || $data instanceof \Traversable) {
            foreach ($data as $key => $data) {
                //Ah this is the magic @ attribute types.
                if (0 === strpos($key, "@") && is_scalar($data) && $this->isElementNameValid($attributeName = substr($key, 1))) {
                    $parentNode->setAttribute($attributeName, $data);
                } elseif ($key === '#') {
                    $append = $this->selectNodeType($parentNode, $data);
                } elseif (is_array($data) && false === is_numeric($key)) {
                    /**
                     * Is this array fully numeric keys?
                     */
                    if (ctype_digit(implode('', array_keys($data)))) {
                        /**
                         * Create nodes to append to $parentNode based on the $key of this array
                         * Produces <xml><item>0</item><item>1</item></xml>
                         * From array("item" => array(0,1));
                         */
                        foreach ($data as $subData) {
                            $append = $this->appendNode($parentNode, $subData, $key);
                        }
                    } else {
                        $append = $this->appendNode($parentNode, $data, $key);
                    }
                } elseif (is_numeric($key) || !$this->isElementNameValid($key)) {
                    $append = $this->appendNode($parentNode, $data, "item", $key);
                } else {
                    $append = $this->appendNode($parentNode, $data, $key);
                }
            }

            return $append;
        }

        if (is_object($data)) {
            $data = $this->serializer->normalize($data, $this->format, $this->context);
            if (null !== $data && !is_scalar($data)) {
                return $this->buildXml($parentNode, $data, $xmlRootNodeName);
            }

            // top level data object was normalized into a scalar
            if (!$parentNode->parentNode->parentNode) {
                $root = $parentNode->parentNode;
                $root->removeChild($parentNode);

                return $this->appendNode($root, $data, $xmlRootNodeName);
            }

            return $this->appendNode($parentNode, $data, 'data');
        }

        throw new UnexpectedValueException(sprintf('An unexpected value could not be serialized: %s', var_export($data, true)));
    }

    /**
     * Selects the type of node to create and appends it to the parent.
     *
     * @param \DOMNode     $parentNode
     * @param array|object $data
     * @param string       $nodeName
     * @param string       $key
     *
     * @return Boolean
     */
    private function appendNode(\DOMNode $parentNode, $data, $nodeName, $key = null)
    {
        $node = $this->dom->createElement($nodeName);
        if (null !== $key) {
            $node->setAttribute('key', $key);
        }
        $appendNode = $this->selectNodeType($node, $data);
        // we may have decided not to append this node, either in error or if its $nodeName is not valid
        if ($appendNode) {
            $parentNode->appendChild($node);
        }

        return $appendNode;
    }

    /**
     * Checks if a value contains any characters which would require CDATA wrapping.
     *
     * @param string $val
     *
     * @return Boolean
     */
    private function needsCdataWrapping($val)
    {
        return preg_match('/[<>&]/', $val);
    }

    /**
     * Tests the value being passed and decide what sort of element to create
     *
     * @param \DOMNode $node
     * @param mixed    $val
     *
     * @return Boolean
     */
    private function selectNodeType(\DOMNode $node, $val)
    {
        if (is_array($val)) {
            return $this->buildXml($node, $val);
        } elseif ($val instanceof \SimpleXMLElement) {
            $child = $this->dom->importNode(dom_import_simplexml($val), true);
            $node->appendChild($child);
        } elseif ($val instanceof \Traversable) {
            $this->buildXml($node, $val);
        } elseif (is_object($val)) {
            return $this->buildXml($node, $this->serializer->normalize($val, $this->format, $this->context));
        } elseif (is_numeric($val)) {
            return $this->appendText($node, (string) $val);
        } elseif (is_string($val) && $this->needsCdataWrapping($val)) {
            return $this->appendCData($node, $val);
        } elseif (is_string($val)) {
            return $this->appendText($node, $val);
        } elseif (is_bool($val)) {
            return $this->appendText($node, (int) $val);
        } elseif ($val instanceof \DOMNode) {
            $child = $this->dom->importNode($val, true);
            $node->appendChild($child);
        }

        return true;
    }

    /**
     * Get real XML root node name, taking serializer options into account.
     */
    private function resolveXmlRootName(array $context = array())
    {
        return isset($context['xml_root_node_name'])
            ? $context['xml_root_node_name']
            : $this->rootNodeName;
    }

    /**
     * Create a DOM document, taking serializer options into account.
     *
     * @param array $context options that the encoder has access to.
     *
     * @return \DOMDocument
     */
    private function createDomDocument(array $context)
    {
        $document = new \DOMDocument();

        // Set an attribute on the DOM document specifying, as part of the XML declaration,
        $xmlOptions = array(
            // the version number of the document
            'xml_version' => 'xmlVersion',
            // the encoding of the document
            'xml_encoding' => 'encoding',
            // whether the document is standalone
            'xml_standalone' => 'xmlStandalone',
        );
        foreach ($xmlOptions as $xmlOption => $documentProperty) {
            if (isset($context[$xmlOption])) {
                $document->$documentProperty = $context[$xmlOption];
            }
        }

        return $document;
    }
}
PKz�Z�<=ggDSymfony/Component/Serializer/Encoder/NormalizationAwareInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Encoder;

/**
 * Defines the interface of encoders that will normalize data themselves
 *
 * Implementing this interface essentially just tells the Serializer that the
 * data should not be pre-normalized before being passed to this Encoder.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface NormalizationAwareInterface
{
}
PKz�ZV��O��5Symfony/Component/Serializer/Encoder/ChainDecoder.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Encoder;

use Symfony\Component\Serializer\Exception\RuntimeException;

/**
 * Decoder delegating the decoding to a chain of decoders.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Lukas Kahwe Smith <smith@pooteeweet.org>
 */
class ChainDecoder implements DecoderInterface
{
    protected $decoders = array();
    protected $decoderByFormat = array();

    public function __construct(array $decoders = array())
    {
        $this->decoders = $decoders;
    }

    /**
     * {@inheritdoc}
     */
    final public function decode($data, $format, array $context = array())
    {
        return $this->getDecoder($format)->decode($data, $format, $context);
    }

    /**
     * {@inheritdoc}
     */
    public function supportsDecoding($format)
    {
        try {
            $this->getDecoder($format);
        } catch (RuntimeException $e) {
            return false;
        }

        return true;
    }

    /**
     * Gets the decoder supporting the format.
     *
     * @param string $format
     *
     * @return DecoderInterface
     * @throws RuntimeException if no decoder is found
     */
    private function getDecoder($format)
    {
        if (isset($this->decoderByFormat[$format])
            && isset($this->decoders[$this->decoderByFormat[$format]])
        ) {
            return $this->decoders[$this->decoderByFormat[$format]];
        }

        foreach ($this->decoders as $i => $decoder) {
            if ($decoder->supportsDecoding($format)) {
                $this->decoderByFormat[$format] = $i;

                return $decoder;
            }
        }

        throw new RuntimeException(sprintf('No decoder found for format "%s".', $format));
    }
}
PKz�Z�=��?Symfony/Component/Serializer/Encoder/SerializerAwareEncoder.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Encoder;

use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Component\Serializer\SerializerAwareInterface;

/**
 * SerializerAware Encoder implementation
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
abstract class SerializerAwareEncoder implements SerializerAwareInterface
{
    protected $serializer;

    /**
     * {@inheritdoc}
     */
    public function setSerializer(SerializerInterface $serializer)
    {
        $this->serializer = $serializer;
    }
}
PKz�Zv:�hh3Symfony/Component/Serializer/Encoder/JsonEncode.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Encoder;

/**
 * Encodes JSON data
 *
 * @author Sander Coolen <sander@jibber.nl>
 */
class JsonEncode implements EncoderInterface
{
    private $options ;
    private $lastError = JSON_ERROR_NONE;

    public function __construct($bitmask = 0)
    {
        $this->options = $bitmask;
    }

    /**
     * Returns the last encoding error (if any)
     *
     * @return integer
     *
     * @see http://php.net/manual/en/function.json-last-error.php json_last_error
     */
    public function getLastError()
    {
        return $this->lastError;
    }

    /**
     * Encodes PHP data to a JSON string
     *
     * {@inheritdoc}
     */
    public function encode($data, $format, array $context = array())
    {
        $context = $this->resolveContext($context);

        $encodedJson = json_encode($data, $context['json_encode_options']);
        $this->lastError = json_last_error();

        return $encodedJson;
    }

    /**
     * {@inheritdoc}
     */
    public function supportsEncoding($format)
    {
        return JsonEncoder::FORMAT === $format;
    }

    /**
     * Merge default json encode options with context.
     *
     * @param array $context
     * @return array
     */
    private function resolveContext(array $context = array())
    {
        return array_merge(array('json_encode_options' => $this->options), $context);
    }
}
PKz�Z��@���3Symfony/Component/Serializer/Encoder/JsonDecode.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Encoder;

/**
 * Decodes JSON data
 *
 * @author Sander Coolen <sander@jibber.nl>
 */
class JsonDecode implements DecoderInterface
{
    /**
     * Specifies if the returned result should be an associative array or a nested stdClass object hierarchy.
     *
     * @var Boolean
     */
    private $associative;

    /**
     * Specifies the recursion depth.
     *
     * @var integer
     */
    private $recursionDepth;

    private $lastError = JSON_ERROR_NONE;
    protected $serializer;

    /**
     * Constructs a new JsonDecode instance.
     *
     * @param Boolean  $associative True to return the result associative array, false for a nested stdClass hierarchy
     * @param integer  $depth       Specifies the recursion depth
     */
    public function __construct($associative = false, $depth = 512)
    {
        $this->associative = $associative;
        $this->recursionDepth = (int) $depth;
    }

    /**
     * Returns the last decoding error (if any).
     *
     * @return integer
     *
     * @see http://php.net/manual/en/function.json-last-error.php json_last_error
     */
    public function getLastError()
    {
        return $this->lastError;
    }

    /**
     * Decodes data.
     *
     * @param string $data    The encoded JSON string to decode
     * @param string $format  Must be set to JsonEncoder::FORMAT
     * @param array  $context An optional set of options for the JSON decoder; see below
     *
     * The $context array is a simple key=>value array, with the following supported keys:
     *
     * json_decode_associative: boolean
     *      If true, returns the object as associative array.
     *      If false, returns the object as nested stdClass
     *      If not specified, this method will use the default set in JsonDecode::__construct
     *
     * json_decode_recursion_depth: integer
     *      Specifies the maximum recursion depth
     *      If not specified, this method will use the default set in JsonDecode::__construct
     *
     * json_decode_options: integer
     *      Specifies additional options as per documentation for json_decode. Only supported with PHP 5.4.0 and higher
     *
     * @return mixed
     *
     * @see http://php.net/json_decode json_decode
     */
    public function decode($data, $format, array $context = array())
    {
        $context = $this->resolveContext($context);

        $associative    = $context['json_decode_associative'];
        $recursionDepth = $context['json_decode_recursion_depth'];
        $options        = $context['json_decode_options'];

        if (version_compare(PHP_VERSION, '5.4.0') >= 0) {
            $decodedData = json_decode($data, $associative, $recursionDepth, $options);
        } else {
            $decodedData = json_decode($data, $associative, $recursionDepth);
        }

        $this->lastError = json_last_error();

        return $decodedData;
    }

    /**
     * {@inheritdoc}
     */
    public function supportsDecoding($format)
    {
        return JsonEncoder::FORMAT === $format;
    }

    /**
     * Merges the default options of the Json Decoder with the passed context.
     *
     * @param array $context
     *
     * @return array
     */
    private function resolveContext(array $context)
    {
        $defaultOptions = array(
            'json_decode_associative' => $this->associative,
            'json_decode_recursion_depth' => $this->recursionDepth,
            'json_decode_options' => 0
        );

        return array_merge($defaultOptions, $context);
    }
}
PKz�ZS R�	�	5Symfony/Component/Serializer/Encoder/ChainEncoder.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Encoder;

use Symfony\Component\Serializer\Exception\RuntimeException;

/**
 * Encoder delegating the decoding to a chain of encoders.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Lukas Kahwe Smith <smith@pooteeweet.org>
 */
class ChainEncoder implements EncoderInterface
{
    protected $encoders = array();
    protected $encoderByFormat = array();

    public function __construct(array $encoders = array())
    {
        $this->encoders = $encoders;
    }

    /**
     * {@inheritdoc}
     */
    final public function encode($data, $format, array $context = array())
    {
        return $this->getEncoder($format)->encode($data, $format, $context);
    }

    /**
     * {@inheritdoc}
     */
    public function supportsEncoding($format)
    {
        try {
            $this->getEncoder($format);
        } catch (RuntimeException $e) {
            return false;
        }

        return true;
    }

    /**
     * Checks whether the normalization is needed for the given format.
     *
     * @param string $format
     *
     * @return Boolean
     */
    public function needsNormalization($format)
    {
        $encoder = $this->getEncoder($format);

        if (!$encoder instanceof NormalizationAwareInterface) {
            return true;
        }

        if ($encoder instanceof self) {
            return $encoder->needsNormalization($format);
        }

        return false;
    }

    /**
     * Gets the encoder supporting the format.
     *
     * @param string $format
     *
     * @return EncoderInterface
     * @throws RuntimeException if no encoder is found
     */
    private function getEncoder($format)
    {
        if (isset($this->encoderByFormat[$format])
            && isset($this->encoders[$this->encoderByFormat[$format]])
        ) {
            return $this->encoders[$this->encoderByFormat[$format]];
        }

        foreach ($this->encoders as $i => $encoder) {
            if ($encoder->supportsEncoding($format)) {
                $this->encoderByFormat[$format] = $i;

                return $encoder;
            }
        }

        throw new RuntimeException(sprintf('No encoder found for format "%s".', $format));
    }
}
PKz�Z�o�vv4Symfony/Component/Serializer/Encoder/JsonEncoder.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Encoder;

/**
 * Encodes JSON data
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class JsonEncoder implements EncoderInterface, DecoderInterface
{
    const FORMAT = 'json';

    /**
     * @var JsonEncode
     */
    protected $encodingImpl;

    /**
     * @var JsonDecode
     */
    protected $decodingImpl;

    public function __construct(JsonEncode $encodingImpl = null, JsonDecode $decodingImpl = null)
    {
        $this->encodingImpl = $encodingImpl ?: new JsonEncode();
        $this->decodingImpl = $decodingImpl ?: new JsonDecode(true);
    }

    /**
     * Returns the last encoding error (if any)
     *
     * @return integer
     */
    public function getLastEncodingError()
    {
        return $this->encodingImpl->getLastError();
    }

    /**
     * Returns the last decoding error (if any)
     *
     * @return integer
     */
    public function getLastDecodingError()
    {
        return $this->decodingImpl->getLastError();
    }

    /**
     * {@inheritdoc}
     */
    public function encode($data, $format, array $context = array())
    {
        return $this->encodingImpl->encode($data, self::FORMAT, $context);
    }

    /**
     * {@inheritdoc}
     */
    public function decode($data, $format, array $context = array())
    {
        return $this->decodingImpl->decode($data, self::FORMAT, $context);
    }

    /**
     * {@inheritdoc}
     */
    public function supportsEncoding($format)
    {
        return self::FORMAT === $format;
    }

    /**
     * {@inheritdoc}
     */
    public function supportsDecoding($format)
    {
        return self::FORMAT === $format;
    }
}
PKz�Z|ͼ���9Symfony/Component/Serializer/Encoder/DecoderInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Encoder;

/**
 * Defines the interface of decoders
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface DecoderInterface
{
    /**
     * Decodes a string into PHP data.
     *
     * @param scalar $data      Data to decode
     * @param string $format    Format name
     * @param array  $context   options that decoders have access to.
     *
     * The format parameter specifies which format the data is in; valid values
     * depend on the specific implementation. Authors implementing this interface
     * are encouraged to document which formats they support in a non-inherited
     * phpdoc comment.
     *
     * @return mixed
     */
    public function decode($data, $format, array $context = array());

    /**
     * Checks whether the deserializer can decode from given format.
     *
     * @param string $format format name
     *
     * @return Boolean
     */
    public function supportsDecoding($format);
}
PKz�ZA�A
��4Symfony/Component/Serializer/Exception/Exception.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Exception;

/**
 * Base exception
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface Exception
{
}
PKz�Z�^L��?Symfony/Component/Serializer/Exception/UnsupportedException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Exception;

/**
 * UnsupportedException
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class UnsupportedException extends InvalidArgumentException
{
}
PKz�Z�h=��;Symfony/Component/Serializer/Exception/RuntimeException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Exception;

/**
 * RuntimeException
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class RuntimeException extends \RuntimeException implements Exception
{
}
PKz�ZJ���9Symfony/Component/Serializer/Exception/LogicException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Exception;

/**
 * LogicException
 *
 * @author Lukas Kahwe Smith <smith@pooteeweet.org>
 */
class LogicException extends \LogicException implements Exception
{
}
PKz�ZT��Y��CSymfony/Component/Serializer/Exception/InvalidArgumentException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Exception;

/**
 * InvalidArgumentException
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class InvalidArgumentException extends \InvalidArgumentException implements Exception
{
}
PKz�Z[�����CSymfony/Component/Serializer/Exception/UnexpectedValueException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Exception;

/**
 * UnexpectedValueException
 *
 * @author Lukas Kahwe Smith <smith@pooteeweet.org>
 */
class UnexpectedValueException extends \UnexpectedValueException implements Exception
{
}
PKz�Zʪ2/&/&+Symfony/Component/Serializer/Serializer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer;

use Symfony\Component\Serializer\Encoder\ChainDecoder;
use Symfony\Component\Serializer\Encoder\ChainEncoder;
use Symfony\Component\Serializer\Encoder\EncoderInterface;
use Symfony\Component\Serializer\Encoder\DecoderInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Exception\RuntimeException;
use Symfony\Component\Serializer\Exception\LogicException;
use Symfony\Component\Serializer\Exception\UnexpectedValueException;

/**
 * Serializer serializes and deserializes data
 *
 * objects are turned into arrays by normalizers
 * arrays are turned into various output formats by encoders
 *
 * $serializer->serialize($obj, 'xml')
 * $serializer->decode($data, 'xml')
 * $serializer->denormalize($data, 'Class', 'xml')
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Lukas Kahwe Smith <smith@pooteeweet.org>
 */
class Serializer implements SerializerInterface, NormalizerInterface, DenormalizerInterface, EncoderInterface, DecoderInterface
{
    protected $encoder;
    protected $decoder;
    protected $normalizers       = array();
    protected $normalizerCache   = array();
    protected $denormalizerCache = array();

    public function __construct(array $normalizers = array(), array $encoders = array())
    {
        foreach ($normalizers as $normalizer) {
            if ($normalizer instanceof SerializerAwareInterface) {
                $normalizer->setSerializer($this);
            }
        }
        $this->normalizers = $normalizers;

        $decoders = array();
        $realEncoders = array();
        foreach ($encoders as $encoder) {
            if ($encoder instanceof SerializerAwareInterface) {
                $encoder->setSerializer($this);
            }
            if ($encoder instanceof DecoderInterface) {
                $decoders[] = $encoder;
            }
            if ($encoder instanceof EncoderInterface) {
                $realEncoders[] = $encoder;
            }
        }
        $this->encoder = new ChainEncoder($realEncoders);
        $this->decoder = new ChainDecoder($decoders);
    }

    /**
     * {@inheritdoc}
     */
    final public function serialize($data, $format, array $context = array())
    {
        if (!$this->supportsEncoding($format)) {
            throw new UnexpectedValueException(sprintf('Serialization for the format %s is not supported', $format));
        }

        if ($this->encoder->needsNormalization($format)) {
            $data = $this->normalize($data, $format, $context);
        }

        return $this->encode($data, $format, $context);
    }

    /**
     * {@inheritdoc}
     */
    final public function deserialize($data, $type, $format, array $context = array())
    {
        if (!$this->supportsDecoding($format)) {
            throw new UnexpectedValueException(sprintf('Deserialization for the format %s is not supported', $format));
        }

        $data = $this->decode($data, $format, $context);

        return $this->denormalize($data, $type, $format, $context);
    }

    /**
     * {@inheritdoc}
     */
    public function normalize($data, $format = null, array $context = array())
    {
        if (null === $data || is_scalar($data)) {
            return $data;
        }
        if (is_object($data) && $this->supportsNormalization($data, $format)) {
            return $this->normalizeObject($data, $format, $context);
        }
        if ($data instanceof \Traversable) {
            $normalized = array();
            foreach ($data as $key => $val) {
                $normalized[$key] = $this->normalize($val, $format, $context);
            }

            return $normalized;
        }
        if (is_object($data)) {
            return $this->normalizeObject($data, $format, $context);
        }
        if (is_array($data)) {
            foreach ($data as $key => $val) {
                $data[$key] = $this->normalize($val, $format, $context);
            }

            return $data;
        }
        throw new UnexpectedValueException(sprintf('An unexpected value could not be normalized: %s', var_export($data, true)));
    }

    /**
     * {@inheritdoc}
     */
    public function denormalize($data, $type, $format = null, array $context = array())
    {
        return $this->denormalizeObject($data, $type, $format, $context);
    }

    /**
     * {@inheritdoc}
     */
    public function supportsNormalization($data, $format = null)
    {
        try {
            $this->getNormalizer($data, $format);
        } catch (RuntimeException $e) {
            return false;
        }

        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function supportsDenormalization($data, $type, $format = null)
    {
        try {
            $this->getDenormalizer($data, $type, $format = null);
        } catch (RuntimeException $e) {
            return false;
        }

        return true;
    }

    /**
     * {@inheritdoc}
     */
    private function getNormalizer($data, $format = null)
    {
        foreach ($this->normalizers as $normalizer) {
            if ($normalizer instanceof NormalizerInterface && $normalizer->supportsNormalization($data, $format)) {
                return $normalizer;
            }
        }

        throw new RuntimeException(sprintf('No normalizer found for format "%s".', $format));
    }

    /**
     * {@inheritdoc}
     */
    private function getDenormalizer($data, $type, $format = null)
    {
        foreach ($this->normalizers as $normalizer) {
            if ($normalizer instanceof DenormalizerInterface && $normalizer->supportsDenormalization($data, $type, $format)) {
                return $normalizer;
            }
        }

        throw new RuntimeException(sprintf('No denormalizer found for format "%s".', $format));
    }

    /**
     * {@inheritdoc}
     */
    final public function encode($data, $format, array $context = array())
    {
        return $this->encoder->encode($data, $format, $context);
    }

    /**
     * {@inheritdoc}
     */
    final public function decode($data, $format, array $context = array())
    {
        return $this->decoder->decode($data, $format, $context);
    }

    /**
     * Normalizes an object into a set of arrays/scalars
     *
     * @param object $object object to normalize
     * @param string $format format name, present to give the option to normalizers to act differently based on formats
     * @param array $context The context data for this particular normalization
     *
     * @return array|scalar
     *
     * @throws LogicException
     * @throws UnexpectedValueException
     */
    private function normalizeObject($object, $format = null, array $context = array())
    {
        if (!$this->normalizers) {
            throw new LogicException('You must register at least one normalizer to be able to normalize objects.');
        }

        $class = get_class($object);
        if (isset($this->normalizerCache[$class][$format])) {
            return $this->normalizerCache[$class][$format]->normalize($object, $format, $context);
        }

        foreach ($this->normalizers as $normalizer) {
            if ($normalizer instanceof NormalizerInterface
                && $normalizer->supportsNormalization($object, $format)) {
                $this->normalizerCache[$class][$format] = $normalizer;

                return $normalizer->normalize($object, $format, $context);
            }
        }

        throw new UnexpectedValueException(sprintf('Could not normalize object of type %s, no supporting normalizer found.', $class));
    }

    /**
     * Denormalizes data back into an object of the given class
     *
     * @param mixed  $data   data to restore
     * @param string $class  the expected class to instantiate
     * @param string $format format name, present to give the option to normalizers to act differently based on formats
     * @param array $context The context data for this particular denormalization
     *
     * @return object
     *
     * @throws LogicException
     * @throws UnexpectedValueException
     */
    private function denormalizeObject($data, $class, $format = null, array $context = array())
    {
        if (!$this->normalizers) {
            throw new LogicException('You must register at least one normalizer to be able to denormalize objects.');
        }

        if (isset($this->denormalizerCache[$class][$format])) {
            return $this->denormalizerCache[$class][$format]->denormalize($data, $class, $format, $context);
        }

        foreach ($this->normalizers as $normalizer) {
            if ($normalizer instanceof DenormalizerInterface
                && $normalizer->supportsDenormalization($data, $class, $format)) {
                $this->denormalizerCache[$class][$format] = $normalizer;

                return $normalizer->denormalize($data, $class, $format, $context);
            }
        }

        throw new UnexpectedValueException(sprintf('Could not denormalize object of type %s, no supporting normalizer found.', $class));
    }

    /**
     * {@inheritdoc}
     */
    public function supportsEncoding($format)
    {
        return $this->encoder->supportsEncoding($format);
    }

    /**
     * {@inheritdoc}
     */
    public function supportsDecoding($format)
    {
        return $this->decoder->supportsDecoding($format);
    }
}
PKz�ZFP�PP'Symfony/Component/Locale/autoloader.phpnu�[���<?php

spl_autoload_register(function ($class) {
    if ('\\' == $class[0]) {
        $class = substr($class, 1);
    }

    if (
        0 === strpos($class, 'Symfony\\Component\\Locale\\')
        &&
        file_exists($file = __DIR__.'/../../../'.str_replace('\\', '/', $class).'.php')
    ) {
        require_once $file;
    }
});
PKz�Z�Q�UULSymfony/Component/Locale/Exception/MethodArgumentNotImplementedException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Locale\Exception;

use Symfony\Component\Intl\Exception\MethodArgumentNotImplementedException as BaseMethodArgumentNotImplementedException;

/**
 * Alias of {@link \Symfony\Component\Intl\Exception\MethodArgumentNotImplementedException}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
 *             {@link \Symfony\Component\Intl\Exception\MethodArgumentNotImplementedException}
 *             instead.
 */
class MethodArgumentNotImplementedException extends BaseMethodArgumentNotImplementedException
{
}
PKz�Z��E>Symfony/Component/Locale/Exception/NotImplementedException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Locale\Exception;

use Symfony\Component\Intl\Exception\NotImplementedException as BaseNotImplementedException;

/**
 * Alias of {@link \Symfony\Component\Intl\Exception\NotImplementedException}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
 *             {@link \Symfony\Component\Intl\Exception\NotImplementedException}
 *             instead.
 */
class NotImplementedException extends BaseNotImplementedException
{
}
PKz�ZS�?a%%DSymfony/Component/Locale/Exception/MethodNotImplementedException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Locale\Exception;

use Symfony\Component\Intl\Exception\MethodNotImplementedException as BaseMethodNotImplementedException;

/**
 * Alias of {@link \Symfony\Component\Intl\Exception\MethodNotImplementedException}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
 *             {@link \Symfony\Component\Intl\Exception\MethodNotImplementedException}
 *             instead.
 */
class MethodNotImplementedException extends BaseMethodNotImplementedException
{
}
PKz�Z���ssQSymfony/Component/Locale/Exception/MethodArgumentValueNotImplementedException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Locale\Exception;

use Symfony\Component\Intl\Exception\MethodArgumentValueNotImplementedException as BaseMethodArgumentValueNotImplementedException;

/**
 * Alias of {@link \Symfony\Component\Intl\Exception\MethodArgumentValueNotImplementedException}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
 *             {@link \Symfony\Component\Intl\Exception\MethodArgumentValueNotImplementedException}
 *             instead.
 */
class MethodArgumentValueNotImplementedException extends BaseMethodArgumentValueNotImplementedException
{
}
PKz�Z�C��*Symfony/Component/Locale/Stub/StubIntl.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Locale\Stub;

use Symfony\Component\Intl\Globals\IntlGlobals;

/**
 * Alias of {@link \Symfony\Component\Intl\Globals\IntlGlobals}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
 *             {@link \Symfony\Component\Intl\Globals\IntlGlobals} instead.
 */
abstract class StubIntl extends IntlGlobals
{
}
PKz�Z&�����5Symfony/Component/Locale/Stub/StubNumberFormatter.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Locale\Stub;

use Symfony\Component\Intl\NumberFormatter\NumberFormatter;

/**
 * Alias of {@link \Symfony\Component\Intl\NumberFormatter\NumberFormatter}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
 *             {@link \Symfony\Component\Intl\NumberFormatter\NumberFormatter}
 *             instead.
 */
class StubNumberFormatter extends NumberFormatter
{
}
PKz�Zv/�@Symfony/Component/Locale/Stub/DateFormat/Hour2401Transformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Locale\Stub\DateFormat;

use Symfony\Component\Intl\DateFormatter\DateFormat\Hour2401Transformer as BaseHour2401Transformer;

/**
 * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\Hour2401Transformer}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
 *             {@link \Symfony\Component\Intl\DateFormatter\DateFormat\Hour2401Transformer}
 *             instead.
 */
class Hour2401Transformer extends BaseHour2401Transformer
{
}
PKz�Z��S@Symfony/Component/Locale/Stub/DateFormat/TimeZoneTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Locale\Stub\DateFormat;

use Symfony\Component\Intl\DateFormatter\DateFormat\TimeZoneTransformer as BaseTimeZoneTransformer;

/**
 * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\TimeZoneTransformer}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
 *             {@link \Symfony\Component\Intl\DateFormatter\DateFormat\TimeZoneTransformer}
 *             instead.
 */
class TimeZoneTransformer extends BaseTimeZoneTransformer
{
}
PKz�Z}��""ASymfony/Component/Locale/Stub/DateFormat/DayOfYearTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Locale\Stub\DateFormat;

use Symfony\Component\Intl\DateFormatter\DateFormat\DayOfYearTransformer as BaseDayOfYearTransformer;

/**
 * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\DayOfYearTransformer}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
 *             {@link \Symfony\Component\Intl\DateFormatter\DateFormat\DayOfYearTransformer}
 *             instead.
 */
class DayOfYearTransformer extends BaseDayOfYearTransformer
{
}
PKz�Z�X�<Symfony/Component/Locale/Stub/DateFormat/AmPmTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Locale\Stub\DateFormat;

use Symfony\Component\Intl\DateFormatter\DateFormat\AmPmTransformer as BaseAmPmTransformer;

/**
 * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\AmPmTransformer}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
 *             {@link \Symfony\Component\Intl\DateFormatter\DateFormat\AmPmTransformer}
 *             instead.
 */
class AmPmTransformer extends BaseAmPmTransformer
{
}
PKz�Z���<Symfony/Component/Locale/Stub/DateFormat/YearTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Locale\Stub\DateFormat;

use Symfony\Component\Intl\DateFormatter\DateFormat\YearTransformer as BaseYearTransformer;

/**
 * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\YearTransformer}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
 *             {@link \Symfony\Component\Intl\DateFormatter\DateFormat\YearTransformer}
 *             instead.
 */
class YearTransformer extends BaseYearTransformer
{
}
PKz�Zmў?Symfony/Component/Locale/Stub/DateFormat/QuarterTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Locale\Stub\DateFormat;

use Symfony\Component\Intl\DateFormatter\DateFormat\QuarterTransformer as BaseQuarterTransformer;

/**
 * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\QuarterTransformer}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
 *             {@link \Symfony\Component\Intl\DateFormatter\DateFormat\QuarterTransformer}
 *             instead.
 */
class QuarterTransformer extends BaseQuarterTransformer
{
}
PKz�Zg[ep>Symfony/Component/Locale/Stub/DateFormat/MinuteTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Locale\Stub\DateFormat;

use Symfony\Component\Intl\DateFormatter\DateFormat\MinuteTransformer as BaseMinuteTransformer;

/**
 * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\MinuteTransformer}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
 *             {@link \Symfony\Component\Intl\DateFormatter\DateFormat\MinuteTransformer}
 *             instead.
 */
class MinuteTransformer extends BaseMinuteTransformer
{
}
PKz�Z:6""ASymfony/Component/Locale/Stub/DateFormat/DayOfWeekTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Locale\Stub\DateFormat;

use Symfony\Component\Intl\DateFormatter\DateFormat\DayOfWeekTransformer as BaseDayOfWeekTransformer;

/**
 * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\DayOfWeekTransformer}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
 *             {@link \Symfony\Component\Intl\DateFormatter\DateFormat\DayOfWeekTransformer}
 *             instead.
 */
class DayOfWeekTransformer extends BaseDayOfWeekTransformer
{
}
PKz�Z9�u@Symfony/Component/Locale/Stub/DateFormat/Hour1200Transformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Locale\Stub\DateFormat;

use Symfony\Component\Intl\DateFormatter\DateFormat\Hour1200Transformer as BaseHour1200Transformer;

/**
 * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\Hour1200Transformer}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
 *             {@link \Symfony\Component\Intl\DateFormatter\DateFormat\Hour1200Transformer}
 *             instead.
 */
class Hour1200Transformer extends BaseHour1200Transformer
{
}
PKz�Zk&"M@Symfony/Component/Locale/Stub/DateFormat/Hour1201Transformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Locale\Stub\DateFormat;

use Symfony\Component\Intl\DateFormatter\DateFormat\Hour1201Transformer as BaseHour1201Transformer;

/**
 * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\Hour1201Transformer}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
 *             {@link \Symfony\Component\Intl\DateFormatter\DateFormat\Hour1201Transformer}
 *             instead.
 */
class Hour1201Transformer extends BaseHour1201Transformer
{
}
PKz�Z�����;Symfony/Component/Locale/Stub/DateFormat/DayTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Locale\Stub\DateFormat;

use Symfony\Component\Intl\DateFormatter\DateFormat\DayTransformer as BaseDayTransformer;

/**
 * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\DayTransformer}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
 *             {@link \Symfony\Component\Intl\DateFormatter\DateFormat\DayTransformer}
 *             instead.
 */
class DayTransformer extends BaseDayTransformer
{
}
PKz�Z��@Symfony/Component/Locale/Stub/DateFormat/Hour2400Transformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Locale\Stub\DateFormat;

use Symfony\Component\Intl\DateFormatter\DateFormat\Hour2400Transformer as BaseHour2400Transformer;

/**
 * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\Hour2400Transformer}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
 *             {@link \Symfony\Component\Intl\DateFormatter\DateFormat\Hour2400Transformer}
 *             instead.
 */
class Hour2400Transformer extends BaseHour2400Transformer
{
}
PKz�Z�Ed��8Symfony/Component/Locale/Stub/DateFormat/Transformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Locale\Stub\DateFormat;

use Symfony\Component\Intl\DateFormatter\DateFormat\Transformer as BaseTransformer;

/**
 * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\Transformer}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
 *             {@link \Symfony\Component\Intl\DateFormatter\DateFormat\Transformer}
 *             instead.
 */
abstract class Transformer extends BaseTransformer
{
}
PKz�Zt�z

=Symfony/Component/Locale/Stub/DateFormat/MonthTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Locale\Stub\DateFormat;

use Symfony\Component\Intl\DateFormatter\DateFormat\MonthTransformer as BaseMonthTransformer;

/**
 * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\MonthTransformer}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
 *             {@link \Symfony\Component\Intl\DateFormatter\DateFormat\MonthTransformer}
 *             instead.
 */
class MonthTransformer extends BaseMonthTransformer
{
}
PKz�Zk�H<Symfony/Component/Locale/Stub/DateFormat/FullTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Locale\Stub\DateFormat;

use Symfony\Component\Intl\DateFormatter\DateFormat\FullTransformer as BaseFullTransformer;

/**
 * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\FullTransformer}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
 *             {@link \Symfony\Component\Intl\DateFormatter\DateFormat\FullTransformer}
 *             instead.
 */
class FullTransformer extends BaseFullTransformer
{
}
PKz�Z�3�X>Symfony/Component/Locale/Stub/DateFormat/SecondTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Locale\Stub\DateFormat;

use Symfony\Component\Intl\DateFormatter\DateFormat\SecondTransformer as BaseSecondTransformer;

/**
 * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\SecondTransformer}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
 *             {@link \Symfony\Component\Intl\DateFormatter\DateFormat\SecondTransformer}
 *             instead.
 */
class SecondTransformer extends BaseSecondTransformer
{
}
PKz�Z�
�

<Symfony/Component/Locale/Stub/DateFormat/HourTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Locale\Stub\DateFormat;

use Symfony\Component\Intl\DateFormatter\DateFormat\HourTransformer as BaseHourTransformer;

/**
 * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\HourTransformer}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
 *             {@link \Symfony\Component\Intl\DateFormatter\DateFormat\HourTransformer}
 *             instead.
 */
abstract class HourTransformer extends BaseHourTransformer
{
}
PKz�Z���?��.Symfony/Component/Locale/Stub/StubCollator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Locale\Stub;

use Symfony\Component\Intl\Collator\Collator;

/**
 * Alias of {@link \Symfony\Component\Intl\Collator\Collator}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
 *             {@link \Symfony\Component\Intl\Collator\Collator} instead.
 */
class StubCollator extends Collator
{
}
PK{�Zq��*((,Symfony/Component/Locale/Stub/StubLocale.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Locale\Stub;

use Symfony\Component\Icu\IcuData;
use Symfony\Component\Intl\Intl;
use Symfony\Component\Intl\Locale\Locale;

/**
 * Alias of {@link \Symfony\Component\Intl\Locale\Locale}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
 *             {@link \Symfony\Component\Intl\Locale\Locale} and
 *             {@link \Symfony\Component\Intl\Intl} instead.
 */
class StubLocale extends Locale
{
    /**
     * Caches the currencies
     *
     * @var array
     */
    protected static $currencies;

    /**
     * Caches the currencies names
     *
     * @var array
     */
    protected static $currenciesNames;

    /**
     * Returns the currencies data
     *
     * @param string $locale
     *
     * @return array  The currencies data
     */
    public static function getCurrenciesData($locale)
    {
        if (null === self::$currencies) {
            self::prepareCurrencies($locale);
        }

        return self::$currencies;
    }

    /**
     *  Returns the currencies names for a locale
     *
     * @param string $locale The locale to use for the currencies names
     *
     * @return array                     The currencies names with their codes as keys
     *
     * @throws \InvalidArgumentException  When the locale is different than 'en'
     */
    public static function getDisplayCurrencies($locale)
    {
        if (null === self::$currenciesNames) {
            self::prepareCurrencies($locale);
        }

        return self::$currenciesNames;
    }

    /**
     * Returns all available currencies codes
     *
     * @return array  The currencies codes
     */
    public static function getCurrencies()
    {
        return array_keys(self::getCurrenciesData(self::getDefault()));
    }

    public static function getDataDirectory()
    {
        return IcuData::getResourceDirectory();
    }

    private static function prepareCurrencies($locale)
    {
        self::$currencies = array();
        self::$currenciesNames = array();

        $bundle = Intl::getCurrencyBundle();

        foreach ($bundle->getCurrencyNames($locale) as $currency => $name) {
            self::$currencies[$currency] = array(
                'name' => $name,
                'symbol' => $bundle->getCurrencySymbol($currency, $locale),
                'fractionDigits' => $bundle->getFractionDigits($currency),
                'roundingIncrement' => $bundle->getRoundingIncrement($currency)
            );
            self::$currenciesNames[$currency] = $name;
        }
    }
}
PK{�Z� S���7Symfony/Component/Locale/Stub/StubIntlDateFormatter.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Locale\Stub;

use Symfony\Component\Intl\DateFormatter\IntlDateFormatter;

/**
 * Alias of {@link \Symfony\Component\Intl\DateFormatter\IntlDateFormatter}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
 *             {@link \Symfony\Component\Intl\DateFormatter\IntlDateFormatter}
 *             instead.
 */
class StubIntlDateFormatter extends IntlDateFormatter
{
}
PK{�Zl�l��#Symfony/Component/Locale/Locale.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Locale;

use Symfony\Component\Icu\IcuData;
use Symfony\Component\Intl\Intl;

/**
 * Helper class for dealing with locale strings.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
 *             {@link \Locale} and {@link \Symfony\Component\Intl\Intl} instead.
 */
class Locale extends \Locale
{
    /**
     * Caches the countries in different locales
     * @var array
     */
    protected static $countries = array();

    /**
     * Caches the languages in different locales
     * @var array
     */
    protected static $languages = array();

    /**
     * Caches the different locales
     * @var array
     */
    protected static $locales = array();

    /**
     * Returns the country names for a locale
     *
     * @param string $locale The locale to use for the country names
     *
     * @return array              The country names with their codes as keys
     *
     * @throws \RuntimeException  When the resource bundles cannot be loaded
     */
    public static function getDisplayCountries($locale)
    {
        if (!isset(self::$countries[$locale])) {
            self::$countries[$locale] = Intl::getRegionBundle()->getCountryNames($locale);
        }

        return self::$countries[$locale];
    }

    /**
     * Returns all available country codes
     *
     * @return array              The country codes
     *
     * @throws \RuntimeException  When the resource bundles cannot be loaded
     */
    public static function getCountries()
    {
        return array_keys(self::getDisplayCountries(self::getDefault()));
    }

    /**
     * Returns the language names for a locale
     *
     * @param string $locale The locale to use for the language names
     *
     * @return array              The language names with their codes as keys
     *
     * @throws \RuntimeException  When the resource bundles cannot be loaded
     */
    public static function getDisplayLanguages($locale)
    {
        if (!isset(self::$languages[$locale])) {
            self::$languages[$locale] = Intl::getLanguageBundle()->getLanguageNames($locale);
        }

        return self::$languages[$locale];
    }

    /**
     * Returns all available language codes
     *
     * @return array              The language codes
     *
     * @throws \RuntimeException  When the resource bundles cannot be loaded
     */
    public static function getLanguages()
    {
        return array_keys(self::getDisplayLanguages(self::getDefault()));
    }

    /**
     * Returns the locale names for a locale
     *
     * @param string $locale The locale to use for the locale names
     *
     * @return array              The locale names with their codes as keys
     *
     * @throws \RuntimeException  When the resource bundles cannot be loaded
     */
    public static function getDisplayLocales($locale)
    {
        if (!isset(self::$locales[$locale])) {
            self::$locales[$locale] = Intl::getLocaleBundle()->getLocaleNames($locale);
        }

        return self::$locales[$locale];
    }

    /**
     * Returns all available locale codes
     *
     * @return array              The locale codes
     *
     * @throws \RuntimeException  When the resource bundles cannot be loaded
     */
    public static function getLocales()
    {
        return array_keys(self::getDisplayLocales(self::getDefault()));
    }

    /**
     * Returns the ICU version as defined by the intl extension
     *
     * @return string|null The ICU version
     */
    public static function getIntlIcuVersion()
    {
        return Intl::getIcuVersion();
    }

    /**
     * Returns the ICU Data version as defined by the intl extension
     *
     * @return string|null The ICU Data version
     */
    public static function getIntlIcuDataVersion()
    {
        return Intl::getIcuDataVersion();
    }

    /**
     * Returns the ICU data version that ships with Symfony. If the environment variable USE_INTL_ICU_DATA_VERSION is
     * defined, it will try use the ICU data version as defined by the intl extension, if available.
     *
     * @return string The ICU data version that ships with Symfony
     */
    public static function getIcuDataVersion()
    {
        return Intl::getIcuDataVersion();
    }

    /**
     * Returns the directory path of the ICU data that ships with Symfony
     *
     * @return string The path to the ICU data directory
     */
    public static function getIcuDataDirectory()
    {
        return IcuData::getResourceDirectory();
    }

    /**
     * Returns the fallback locale for a given locale, if any
     *
     * @param string $locale The locale to find the fallback for.
     *
     * @return string|null The fallback locale, or null if no parent exists
     */
    protected static function getFallbackLocale($locale)
    {
        if (false === $pos = strrpos($locale, '_')) {
            return null;
        }

        return substr($locale, 0, $pos);
    }
}
PK{�Z�t�TT+Symfony/Component/Filesystem/autoloader.phpnu�[���<?php

spl_autoload_register(function ($class) {
    if ('\\' == $class[0]) {
        $class = substr($class, 1);
    }

    if (
        0 === strpos($class, 'Symfony\\Component\\Filesystem\\')
        &&
        file_exists($file = __DIR__.'/../../../'.str_replace('\\', '/', $class).'.php')
    ) {
        require_once $file;
    }
});
PK{�Z��dP��@Symfony/Component/Filesystem/Exception/FileNotFoundException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Filesystem\Exception;

/**
 * Exception class thrown when a file couldn't be found
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Christian Gärtner <christiangaertner.film@googlemail.com>
 */
class FileNotFoundException extends IOException
{
    public function __construct($message = null, $code = 0, \Exception $previous = null, $path = null)
    {
        if (null === $message) {
            if (null === $path) {
                $message = 'File could not be found.';
            } else {
                $message = sprintf('File "%s" could not be found.', $path);
            }
        }

        parent::__construct($message, $code, $previous, $path);
    }
}
PK{�Z3{����=Symfony/Component/Filesystem/Exception/ExceptionInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Filesystem\Exception;

/**
 * Exception interface for all exceptions thrown by the component.
 *
 * @author Romain Neutron <imprec@gmail.com>
 *
 * @api
 */
interface ExceptionInterface
{
}
PK{�ZoC�~��?Symfony/Component/Filesystem/Exception/IOExceptionInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Filesystem\Exception;

/**
 * IOException interface for file and input/output stream related exceptions thrown by the component.
 *
 * @author Christian Gärtner <christiangaertner.film@googlemail.com>
 */
interface IOExceptionInterface extends ExceptionInterface
{
    /**
     * Returns the associated path for the exception
     *
     * @return string The path.
     */
    public function getPath();
}
PK{�Z;�{��6Symfony/Component/Filesystem/Exception/IOException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Filesystem\Exception;

/**
 * Exception class thrown when a filesystem operation failure happens
 *
 * @author Romain Neutron <imprec@gmail.com>
 * @author Christian Gärtner <christiangaertner.film@googlemail.com>
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class IOException extends \RuntimeException implements IOExceptionInterface
{
    private $path;

    public function __construct($message, $code = 0, \Exception $previous = null, $path = null)
    {
        $this->path = $path;

        parent::__construct($message, $code, $previous);
    }

    /**
     * {@inheritdoc}
     */
    public function getPath()
    {
        return $this->path;
    }
}
PK{�ZOظ�GG+Symfony/Component/Filesystem/Filesystem.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Filesystem;

use Symfony\Component\Filesystem\Exception\IOException;
use Symfony\Component\Filesystem\Exception\FileNotFoundException;

/**
 * Provides basic utility to manipulate the file system.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Filesystem
{
    /**
     * Copies a file.
     *
     * This method only copies the file if the origin file is newer than the target file.
     *
     * By default, if the target already exists, it is not overridden.
     *
     * @param string  $originFile The original filename
     * @param string  $targetFile The target filename
     * @param boolean $override   Whether to override an existing file or not
     *
     * @throws FileNotFoundException    When originFile doesn't exist
     * @throws IOException              When copy fails
     */
    public function copy($originFile, $targetFile, $override = false)
    {
        if (stream_is_local($originFile) && !is_file($originFile)) {
            throw new FileNotFoundException(sprintf('Failed to copy "%s" because file does not exist.', $originFile), 0, null, $originFile);
        }

        $this->mkdir(dirname($targetFile));

        if (!$override && is_file($targetFile) && null === parse_url($originFile, PHP_URL_HOST)) {
            $doCopy = filemtime($originFile) > filemtime($targetFile);
        } else {
            $doCopy = true;
        }

        if ($doCopy) {
            // https://bugs.php.net/bug.php?id=64634
            $source = fopen($originFile, 'r');
            $target = fopen($targetFile, 'w');
            stream_copy_to_stream($source, $target);
            fclose($source);
            fclose($target);
            unset($source, $target);

            if (!is_file($targetFile)) {
                throw new IOException(sprintf('Failed to copy "%s" to "%s".', $originFile, $targetFile), 0, null, $originFile);
            }
        }
    }

    /**
     * Creates a directory recursively.
     *
     * @param string|array|\Traversable $dirs The directory path
     * @param integer                   $mode The directory mode
     *
     * @throws IOException On any directory creation failure
     */
    public function mkdir($dirs, $mode = 0777)
    {
        foreach ($this->toIterator($dirs) as $dir) {
            if (is_dir($dir)) {
                continue;
            }

            if (true !== @mkdir($dir, $mode, true)) {
                throw new IOException(sprintf('Failed to create "%s".', $dir), 0, null, $dir);
            }
        }
    }

    /**
     * Checks the existence of files or directories.
     *
     * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to check
     *
     * @return Boolean true if the file exists, false otherwise
     */
    public function exists($files)
    {
        foreach ($this->toIterator($files) as $file) {
            if (!file_exists($file)) {
                return false;
            }
        }

        return true;
    }

    /**
     * Sets access and modification time of file.
     *
     * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to create
     * @param integer                   $time  The touch time as a Unix timestamp
     * @param integer                   $atime The access time as a Unix timestamp
     *
     * @throws IOException When touch fails
     */
    public function touch($files, $time = null, $atime = null)
    {
        foreach ($this->toIterator($files) as $file) {
            $touch = $time ? @touch($file, $time, $atime) : @touch($file);
            if (true !== $touch) {
                throw new IOException(sprintf('Failed to touch "%s".', $file), 0, null, $file);
            }
        }
    }

    /**
     * Removes files or directories.
     *
     * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to remove
     *
     * @throws IOException When removal fails
     */
    public function remove($files)
    {
        $files = iterator_to_array($this->toIterator($files));
        $files = array_reverse($files);
        foreach ($files as $file) {
            if (!file_exists($file) && !is_link($file)) {
                continue;
            }

            if (is_dir($file) && !is_link($file)) {
                $this->remove(new \FilesystemIterator($file));

                if (true !== @rmdir($file)) {
                    throw new IOException(sprintf('Failed to remove directory "%s".', $file), 0, null, $file);
                }
            } else {
                // https://bugs.php.net/bug.php?id=52176
                if (defined('PHP_WINDOWS_VERSION_MAJOR') && is_dir($file)) {
                    if (true !== @rmdir($file)) {
                        throw new IOException(sprintf('Failed to remove file "%s".', $file), 0, null, $file);
                    }
                } else {
                    if (true !== @unlink($file)) {
                        throw new IOException(sprintf('Failed to remove file "%s".', $file), 0, null, $file);
                    }
                }
            }
        }
    }

    /**
     * Change mode for an array of files or directories.
     *
     * @param string|array|\Traversable $files     A filename, an array of files, or a \Traversable instance to change mode
     * @param integer                   $mode      The new mode (octal)
     * @param integer                   $umask     The mode mask (octal)
     * @param Boolean                   $recursive Whether change the mod recursively or not
     *
     * @throws IOException When the change fail
     */
    public function chmod($files, $mode, $umask = 0000, $recursive = false)
    {
        foreach ($this->toIterator($files) as $file) {
            if ($recursive && is_dir($file) && !is_link($file)) {
                $this->chmod(new \FilesystemIterator($file), $mode, $umask, true);
            }
            if (true !== @chmod($file, $mode & ~$umask)) {
                throw new IOException(sprintf('Failed to chmod file "%s".', $file), 0, null, $file);
            }
        }
    }

    /**
     * Change the owner of an array of files or directories
     *
     * @param string|array|\Traversable $files     A filename, an array of files, or a \Traversable instance to change owner
     * @param string                    $user      The new owner user name
     * @param Boolean                   $recursive Whether change the owner recursively or not
     *
     * @throws IOException When the change fail
     */
    public function chown($files, $user, $recursive = false)
    {
        foreach ($this->toIterator($files) as $file) {
            if ($recursive && is_dir($file) && !is_link($file)) {
                $this->chown(new \FilesystemIterator($file), $user, true);
            }
            if (is_link($file) && function_exists('lchown')) {
                if (true !== @lchown($file, $user)) {
                    throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file);
                }
            } else {
                if (true !== @chown($file, $user)) {
                    throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file);
                }
            }
        }
    }

    /**
     * Change the group of an array of files or directories
     *
     * @param string|array|\Traversable $files     A filename, an array of files, or a \Traversable instance to change group
     * @param string                    $group     The group name
     * @param Boolean                   $recursive Whether change the group recursively or not
     *
     * @throws IOException When the change fail
     */
    public function chgrp($files, $group, $recursive = false)
    {
        foreach ($this->toIterator($files) as $file) {
            if ($recursive && is_dir($file) && !is_link($file)) {
                $this->chgrp(new \FilesystemIterator($file), $group, true);
            }
            if (is_link($file) && function_exists('lchgrp')) {
                if (true !== @lchgrp($file, $group)) {
                    throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file);
                }
            } else {
                if (true !== @chgrp($file, $group)) {
                    throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file);
                }
            }
        }
    }

    /**
     * Renames a file or a directory.
     *
     * @param string  $origin    The origin filename or directory
     * @param string  $target    The new filename or directory
     * @param Boolean $overwrite Whether to overwrite the target if it already exists
     *
     * @throws IOException When target file or directory already exists
     * @throws IOException When origin cannot be renamed
     */
    public function rename($origin, $target, $overwrite = false)
    {
        // we check that target does not exist
        if (!$overwrite && is_readable($target)) {
            throw new IOException(sprintf('Cannot rename because the target "%s" already exists.', $target), 0, null, $target);
        }

        if (true !== @rename($origin, $target)) {
            throw new IOException(sprintf('Cannot rename "%s" to "%s".', $origin, $target), 0, null, $target);
        }
    }

    /**
     * Creates a symbolic link or copy a directory.
     *
     * @param string  $originDir     The origin directory path
     * @param string  $targetDir     The symbolic link name
     * @param Boolean $copyOnWindows Whether to copy files if on Windows
     *
     * @throws IOException When symlink fails
     */
    public function symlink($originDir, $targetDir, $copyOnWindows = false)
    {
        if (!function_exists('symlink') && $copyOnWindows) {
            $this->mirror($originDir, $targetDir);

            return;
        }

        $this->mkdir(dirname($targetDir));

        $ok = false;
        if (is_link($targetDir)) {
            if (readlink($targetDir) != $originDir) {
                $this->remove($targetDir);
            } else {
                $ok = true;
            }
        }

        if (!$ok) {
            if (true !== @symlink($originDir, $targetDir)) {
                $report = error_get_last();
                if (is_array($report)) {
                    if (defined('PHP_WINDOWS_VERSION_MAJOR') && false !== strpos($report['message'], 'error code(1314)')) {
                        throw new IOException('Unable to create symlink due to error code 1314: \'A required privilege is not held by the client\'. Do you have the required Administrator-rights?');
                    }
                }

                throw new IOException(sprintf('Failed to create symbolic link from "%s" to "%s".', $originDir, $targetDir), 0, null, $targetDir);
            }
        }
    }

    /**
     * Given an existing path, convert it to a path relative to a given starting path
     *
     * @param string $endPath   Absolute path of target
     * @param string $startPath Absolute path where traversal begins
     *
     * @return string Path of target relative to starting path
     */
    public function makePathRelative($endPath, $startPath)
    {
        // Normalize separators on Windows
        if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
            $endPath = strtr($endPath, '\\', '/');
            $startPath = strtr($startPath, '\\', '/');
        }

        // Split the paths into arrays
        $startPathArr = explode('/', trim($startPath, '/'));
        $endPathArr = explode('/', trim($endPath, '/'));

        // Find for which directory the common path stops
        $index = 0;
        while (isset($startPathArr[$index]) && isset($endPathArr[$index]) && $startPathArr[$index] === $endPathArr[$index]) {
            $index++;
        }

        // Determine how deep the start path is relative to the common path (ie, "web/bundles" = 2 levels)
        $depth = count($startPathArr) - $index;

        // Repeated "../" for each level need to reach the common path
        $traverser = str_repeat('../', $depth);

        $endPathRemainder = implode('/', array_slice($endPathArr, $index));

        // Construct $endPath from traversing to the common path, then to the remaining $endPath
        $relativePath = $traverser.(strlen($endPathRemainder) > 0 ? $endPathRemainder.'/' : '');

        return (strlen($relativePath) === 0) ? './' : $relativePath;
    }

    /**
     * Mirrors a directory to another.
     *
     * @param string       $originDir The origin directory
     * @param string       $targetDir The target directory
     * @param \Traversable $iterator  A Traversable instance
     * @param array        $options   An array of boolean options
     *                               Valid options are:
     *                                 - $options['override'] Whether to override an existing file on copy or not (see copy())
     *                                 - $options['copy_on_windows'] Whether to copy files instead of links on Windows (see symlink())
     *                                 - $options['delete'] Whether to delete files that are not in the source directory (defaults to false)
     *
     * @throws IOException When file type is unknown
     */
    public function mirror($originDir, $targetDir, \Traversable $iterator = null, $options = array())
    {
        $targetDir = rtrim($targetDir, '/\\');
        $originDir = rtrim($originDir, '/\\');

        // Iterate in destination folder to remove obsolete entries
        if ($this->exists($targetDir) && isset($options['delete']) && $options['delete']) {
            $deleteIterator = $iterator;
            if (null === $deleteIterator) {
                $flags = \FilesystemIterator::SKIP_DOTS;
                $deleteIterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($targetDir, $flags), \RecursiveIteratorIterator::CHILD_FIRST);
            }
            foreach ($deleteIterator as $file) {
                $origin = str_replace($targetDir, $originDir, $file->getPathname());
                if (!$this->exists($origin)) {
                    $this->remove($file);
                }
            }
        }

        $copyOnWindows = false;
        if (isset($options['copy_on_windows']) && !function_exists('symlink')) {
            $copyOnWindows = $options['copy_on_windows'];
        }

        if (null === $iterator) {
            $flags = $copyOnWindows ? \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS : \FilesystemIterator::SKIP_DOTS;
            $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($originDir, $flags), \RecursiveIteratorIterator::SELF_FIRST);
        }

        foreach ($iterator as $file) {
            $target = str_replace($originDir, $targetDir, $file->getPathname());

            if ($copyOnWindows) {
                if (is_link($file) || is_file($file)) {
                    $this->copy($file, $target, isset($options['override']) ? $options['override'] : false);
                } elseif (is_dir($file)) {
                    $this->mkdir($target);
                } else {
                    throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file);
                }
            } else {
                if (is_link($file)) {
                    $this->symlink($file->getLinkTarget(), $target);
                } elseif (is_dir($file)) {
                    $this->mkdir($target);
                } elseif (is_file($file)) {
                    $this->copy($file, $target, isset($options['override']) ? $options['override'] : false);
                } else {
                    throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file);
                }
            }
        }
    }

    /**
     * Returns whether the file path is an absolute path.
     *
     * @param string $file A file path
     *
     * @return Boolean
     */
    public function isAbsolutePath($file)
    {
        if (strspn($file, '/\\', 0, 1)
            || (strlen($file) > 3 && ctype_alpha($file[0])
                && substr($file, 1, 1) === ':'
                && (strspn($file, '/\\', 2, 1))
            )
            || null !== parse_url($file, PHP_URL_SCHEME)
        ) {
            return true;
        }

        return false;
    }

    /**
     * Atomically dumps content into a file.
     *
     * @param  string       $filename The file to be written to.
     * @param  string       $content  The data to write into the file.
     * @param  null|integer $mode     The file mode (octal). If null, file permissions are not modified
     *                                Deprecated since version 2.3.12, to be removed in 3.0.
     * @throws IOException            If the file cannot be written to.
     */
    public function dumpFile($filename, $content, $mode = 0666)
    {
        $dir = dirname($filename);

        if (!is_dir($dir)) {
            $this->mkdir($dir);
        } elseif (!is_writable($dir)) {
            throw new IOException(sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir);
        }

        $tmpFile = tempnam($dir, basename($filename));

        if (false === @file_put_contents($tmpFile, $content)) {
            throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename);
        }

        $this->rename($tmpFile, $filename, true);
        if (null !== $mode) {
            $this->chmod($filename, $mode);
        }
    }

    /**
     * @param mixed $files
     *
     * @return \Traversable
     */
    private function toIterator($files)
    {
        if (!$files instanceof \Traversable) {
            $files = new \ArrayObject(is_array($files) ? $files : array($files));
        }

        return $files;
    }
}
PK{�Z)��.�.'Symfony/Component/Form/FormRenderer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

use Symfony\Component\Form\Exception\LogicException;
use Symfony\Component\Form\Exception\BadMethodCallException;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter;
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;

/**
 * Renders a form into HTML using a rendering engine.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class FormRenderer implements FormRendererInterface
{
    const CACHE_KEY_VAR = 'unique_block_prefix';

    /**
     * @var FormRendererEngineInterface
     */
    private $engine;

    /**
     * @var CsrfTokenManagerInterface
     */
    private $csrfTokenManager;

    /**
     * @var array
     */
    private $blockNameHierarchyMap = array();

    /**
     * @var array
     */
    private $hierarchyLevelMap = array();

    /**
     * @var array
     */
    private $variableStack = array();

    /**
     * Constructor.
     *
     * @param FormRendererEngineInterface    $engine
     * @param CsrfTokenManagerInterface|null $csrfTokenManager
     *
     * @throws UnexpectedTypeException
     */
    public function __construct(FormRendererEngineInterface $engine, $csrfTokenManager = null)
    {
        if ($csrfTokenManager instanceof CsrfProviderInterface) {
            $csrfTokenManager = new CsrfProviderAdapter($csrfTokenManager);
        } elseif (null !== $csrfTokenManager && !$csrfTokenManager instanceof CsrfTokenManagerInterface) {
            throw new UnexpectedTypeException($csrfTokenManager, 'CsrfProviderInterface or CsrfTokenManagerInterface or null');
        }

        $this->engine = $engine;
        $this->csrfTokenManager = $csrfTokenManager;
    }

    /**
     * {@inheritdoc}
     */
    public function getEngine()
    {
        return $this->engine;
    }

    /**
     * {@inheritdoc}
     */
    public function setTheme(FormView $view, $themes)
    {
        $this->engine->setTheme($view, $themes);
    }

    /**
     * {@inheritdoc}
     */
    public function renderCsrfToken($tokenId)
    {
        if (null === $this->csrfTokenManager) {
            throw new BadMethodCallException('CSRF tokens can only be generated if a CsrfTokenManagerInterface is injected in FormRenderer::__construct().');
        }

        return $this->csrfTokenManager->getToken($tokenId)->getValue();
    }

    /**
     * {@inheritdoc}
     */
    public function renderBlock(FormView $view, $blockName, array $variables = array())
    {
        $resource = $this->engine->getResourceForBlockName($view, $blockName);

        if (!$resource) {
            throw new LogicException(sprintf('No block "%s" found while rendering the form.', $blockName));
        }

        $viewCacheKey = $view->vars[self::CACHE_KEY_VAR];

        // The variables are cached globally for a view (instead of for the
        // current suffix)
        if (!isset($this->variableStack[$viewCacheKey])) {
            $this->variableStack[$viewCacheKey] = array();

            // The default variable scope contains all view variables, merged with
            // the variables passed explicitly to the helper
            $scopeVariables = $view->vars;

            $varInit = true;
        } else {
            // Reuse the current scope and merge it with the explicitly passed variables
            $scopeVariables = end($this->variableStack[$viewCacheKey]);

            $varInit = false;
        }

        // Merge the passed with the existing attributes
        if (isset($variables['attr']) && isset($scopeVariables['attr'])) {
            $variables['attr'] = array_replace($scopeVariables['attr'], $variables['attr']);
        }

        // Merge the passed with the exist *label* attributes
        if (isset($variables['label_attr']) && isset($scopeVariables['label_attr'])) {
            $variables['label_attr'] = array_replace($scopeVariables['label_attr'], $variables['label_attr']);
        }

        // Do not use array_replace_recursive(), otherwise array variables
        // cannot be overwritten
        $variables = array_replace($scopeVariables, $variables);

        $this->variableStack[$viewCacheKey][] = $variables;

        // Do the rendering
        $html = $this->engine->renderBlock($view, $resource, $blockName, $variables);

        // Clear the stack
        array_pop($this->variableStack[$viewCacheKey]);

        if ($varInit) {
            unset($this->variableStack[$viewCacheKey]);
        }

        return $html;
    }

    /**
     * {@inheritdoc}
     */
    public function searchAndRenderBlock(FormView $view, $blockNameSuffix, array $variables = array())
    {
        $renderOnlyOnce = 'row' === $blockNameSuffix || 'widget' === $blockNameSuffix;

        if ($renderOnlyOnce && $view->isRendered()) {
            return '';
        }

        // The cache key for storing the variables and types
        $viewCacheKey = $view->vars[self::CACHE_KEY_VAR];
        $viewAndSuffixCacheKey = $viewCacheKey.$blockNameSuffix;

        // In templates, we have to deal with two kinds of block hierarchies:
        //
        //   +---------+          +---------+
        //   | Theme B | -------> | Theme A |
        //   +---------+          +---------+
        //
        //   form_widget -------> form_widget
        //       ^
        //       |
        //  choice_widget -----> choice_widget
        //
        // The first kind of hierarchy is the theme hierarchy. This allows to
        // override the block "choice_widget" from Theme A in the extending
        // Theme B. This kind of inheritance needs to be supported by the
        // template engine and, for example, offers "parent()" or similar
        // functions to fall back from the custom to the parent implementation.
        //
        // The second kind of hierarchy is the form type hierarchy. This allows
        // to implement a custom "choice_widget" block (no matter in which theme),
        // or to fallback to the block of the parent type, which would be
        // "form_widget" in this example (again, no matter in which theme).
        // If the designer wants to explicitly fallback to "form_widget" in his
        // custom "choice_widget", for example because he only wants to wrap
        // a <div> around the original implementation, he can simply call the
        // widget() function again to render the block for the parent type.
        //
        // The second kind is implemented in the following blocks.
        if (!isset($this->blockNameHierarchyMap[$viewAndSuffixCacheKey])) {
            // INITIAL CALL
            // Calculate the hierarchy of template blocks and start on
            // the bottom level of the hierarchy (= "_<id>_<section>" block)
            $blockNameHierarchy = array();
            foreach ($view->vars['block_prefixes'] as $blockNamePrefix) {
                $blockNameHierarchy[] = $blockNamePrefix.'_'.$blockNameSuffix;
            }
            $hierarchyLevel = count($blockNameHierarchy) - 1;

            $hierarchyInit = true;
        } else {
            // RECURSIVE CALL
            // If a block recursively calls searchAndRenderBlock() again, resume rendering
            // using the parent type in the hierarchy.
            $blockNameHierarchy = $this->blockNameHierarchyMap[$viewAndSuffixCacheKey];
            $hierarchyLevel = $this->hierarchyLevelMap[$viewAndSuffixCacheKey] - 1;

            $hierarchyInit = false;
        }

        // The variables are cached globally for a view (instead of for the
        // current suffix)
        if (!isset($this->variableStack[$viewCacheKey])) {
            $this->variableStack[$viewCacheKey] = array();

            // The default variable scope contains all view variables, merged with
            // the variables passed explicitly to the helper
            $scopeVariables = $view->vars;

            $varInit = true;
        } else {
            // Reuse the current scope and merge it with the explicitly passed variables
            $scopeVariables = end($this->variableStack[$viewCacheKey]);

            $varInit = false;
        }

        // Load the resource where this block can be found
        $resource = $this->engine->getResourceForBlockNameHierarchy($view, $blockNameHierarchy, $hierarchyLevel);

        // Update the current hierarchy level to the one at which the resource was
        // found. For example, if looking for "choice_widget", but only a resource
        // is found for its parent "form_widget", then the level is updated here
        // to the parent level.
        $hierarchyLevel = $this->engine->getResourceHierarchyLevel($view, $blockNameHierarchy, $hierarchyLevel);

        // The actually existing block name in $resource
        $blockName = $blockNameHierarchy[$hierarchyLevel];

        // Escape if no resource exists for this block
        if (!$resource) {
            throw new LogicException(sprintf(
                'Unable to render the form as none of the following blocks exist: "%s".',
                implode('", "', array_reverse($blockNameHierarchy))
            ));
        }

        // Merge the passed with the existing attributes
        if (isset($variables['attr']) && isset($scopeVariables['attr'])) {
            $variables['attr'] = array_replace($scopeVariables['attr'], $variables['attr']);
        }

        // Merge the passed with the exist *label* attributes
        if (isset($variables['label_attr']) && isset($scopeVariables['label_attr'])) {
            $variables['label_attr'] = array_replace($scopeVariables['label_attr'], $variables['label_attr']);
        }

        // Do not use array_replace_recursive(), otherwise array variables
        // cannot be overwritten
        $variables = array_replace($scopeVariables, $variables);

        // In order to make recursive calls possible, we need to store the block hierarchy,
        // the current level of the hierarchy and the variables so that this method can
        // resume rendering one level higher of the hierarchy when it is called recursively.
        //
        // We need to store these values in maps (associative arrays) because within a
        // call to widget() another call to widget() can be made, but for a different view
        // object. These nested calls should not override each other.
        $this->blockNameHierarchyMap[$viewAndSuffixCacheKey] = $blockNameHierarchy;
        $this->hierarchyLevelMap[$viewAndSuffixCacheKey] = $hierarchyLevel;

        // We also need to store the variables for the view so that we can render other
        // blocks for the same view using the same variables as in the outer block.
        $this->variableStack[$viewCacheKey][] = $variables;

        // Do the rendering
        $html = $this->engine->renderBlock($view, $resource, $blockName, $variables);

        // Clear the stack
        array_pop($this->variableStack[$viewCacheKey]);

        // Clear the caches if they were filled for the first time within
        // this function call
        if ($hierarchyInit) {
            unset($this->blockNameHierarchyMap[$viewAndSuffixCacheKey]);
            unset($this->hierarchyLevelMap[$viewAndSuffixCacheKey]);
        }

        if ($varInit) {
            unset($this->variableStack[$viewCacheKey]);
        }

        if ($renderOnlyOnce) {
            $view->setRendered();
        }

        return $html;
    }

    /**
     * {@inheritdoc}
     */
    public function humanize($text)
    {
        return ucfirst(trim(strtolower(preg_replace(array('/([A-Z])/', '/[_\s]+/'), array('_$1', ' '), $text))));
    }
}
PK{�Z�C����.Symfony/Component/Form/ButtonTypeInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

/**
 * A type that should be converted into a {@link Button} instance.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface ButtonTypeInterface extends FormTypeInterface
{
}
PK{�ZK'�$��&Symfony/Component/Form/FormBuilder.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

use Symfony\Component\Form\Exception\BadMethodCallException;
use Symfony\Component\Form\Exception\InvalidArgumentException;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

/**
 * A builder for creating {@link Form} instances.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class FormBuilder extends FormConfigBuilder implements \IteratorAggregate, FormBuilderInterface
{
    /**
     * The children of the form builder.
     *
     * @var FormBuilderInterface[]
     */
    private $children = array();

    /**
     * The data of children who haven't been converted to form builders yet.
     *
     * @var array
     */
    private $unresolvedChildren = array();

    /**
     * Creates a new form builder.
     *
     * @param string                   $name
     * @param string                   $dataClass
     * @param EventDispatcherInterface $dispatcher
     * @param FormFactoryInterface     $factory
     * @param array                    $options
     */
    public function __construct($name, $dataClass, EventDispatcherInterface $dispatcher, FormFactoryInterface $factory, array $options = array())
    {
        parent::__construct($name, $dataClass, $dispatcher, $options);

        $this->setFormFactory($factory);
    }

    /**
     * {@inheritdoc}
     */
    public function add($child, $type = null, array $options = array())
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        if ($child instanceof self) {
            $this->children[$child->getName()] = $child;

            // In case an unresolved child with the same name exists
            unset($this->unresolvedChildren[$child->getName()]);

            return $this;
        }

        if (!is_string($child) && !is_int($child)) {
            throw new UnexpectedTypeException($child, 'string, integer or Symfony\Component\Form\FormBuilder');
        }

        if (null !== $type && !is_string($type) && !$type instanceof FormTypeInterface) {
            throw new UnexpectedTypeException($type, 'string or Symfony\Component\Form\FormTypeInterface');
        }

        // Add to "children" to maintain order
        $this->children[$child] = null;
        $this->unresolvedChildren[$child] = array(
            'type'    => $type,
            'options' => $options,
        );

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function create($name, $type = null, array $options = array())
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        if (null === $type && null === $this->getDataClass()) {
            $type = 'text';
        }

        if (null !== $type) {
            return $this->getFormFactory()->createNamedBuilder($name, $type, null, $options);
        }

        return $this->getFormFactory()->createBuilderForProperty($this->getDataClass(), $name, null, $options);
    }

    /**
     * {@inheritdoc}
     */
    public function get($name)
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        if (isset($this->unresolvedChildren[$name])) {
            return $this->resolveChild($name);
        }

        if (isset($this->children[$name])) {
            return $this->children[$name];
        }

        throw new InvalidArgumentException(sprintf('The child with the name "%s" does not exist.', $name));
    }

    /**
     * {@inheritdoc}
     */
    public function remove($name)
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        unset($this->unresolvedChildren[$name]);

        if (array_key_exists($name, $this->children)) {
            unset($this->children[$name]);
        }

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function has($name)
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        if (isset($this->unresolvedChildren[$name])) {
            return true;
        }

        if (isset($this->children[$name])) {
            return true;
        }

        return false;
    }

    /**
     * {@inheritdoc}
     */
    public function all()
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        $this->resolveChildren();

        return $this->children;
    }

    /**
     * {@inheritdoc}
     */
    public function count()
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        return count($this->children);
    }

    /**
     * {@inheritdoc}
     */
    public function getFormConfig()
    {
        $config = parent::getFormConfig();

        $config->children = array();
        $config->unresolvedChildren = array();

        return $config;
    }

    /**
     * {@inheritdoc}
     */
    public function getForm()
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        $this->resolveChildren();

        $form = new Form($this->getFormConfig());

        foreach ($this->children as $child) {
            // Automatic initialization is only supported on root forms
            $form->add($child->setAutoInitialize(false)->getForm());
        }

        if ($this->getAutoInitialize()) {
            // Automatically initialize the form if it is configured so
            $form->initialize();
        }

        return $form;
    }

    /**
     * {@inheritdoc}
     */
    public function getIterator()
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        return new \ArrayIterator($this->children);
    }

    /**
     * Converts an unresolved child into a {@link FormBuilder} instance.
     *
     * @param  string $name The name of the unresolved child.
     *
     * @return FormBuilder The created instance.
     */
    private function resolveChild($name)
    {
        $info = $this->unresolvedChildren[$name];
        $child = $this->create($name, $info['type'], $info['options']);
        $this->children[$name] = $child;
        unset($this->unresolvedChildren[$name]);

        return $child;
    }

    /**
     * Converts all unresolved children into {@link FormBuilder} instances.
     */
    private function resolveChildren()
    {
        foreach ($this->unresolvedChildren as $name => $info) {
            $this->children[$name] = $this->create($name, $info['type'], $info['options']);
        }

        $this->unresolvedChildren = array();
    }
}
PK{�Z&�"̰T�T,Symfony/Component/Form/FormConfigBuilder.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

use Symfony\Component\Form\Exception\BadMethodCallException;
use Symfony\Component\Form\Exception\InvalidArgumentException;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\PropertyAccess\PropertyPath;
use Symfony\Component\PropertyAccess\PropertyPathInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\EventDispatcher\ImmutableEventDispatcher;

/**
 * A basic form configuration.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class FormConfigBuilder implements FormConfigBuilderInterface
{
    /**
     * Caches a globally unique {@link NativeRequestHandler} instance.
     *
     * @var NativeRequestHandler
     */
    private static $nativeRequestProcessor;

    /**
     * The accepted request methods.
     *
     * @var array
     */
    private static $allowedMethods = array(
        'GET',
        'PUT',
        'POST',
        'DELETE',
        'PATCH'
    );

    /**
     * @var Boolean
     */
    protected $locked = false;

    /**
     * @var EventDispatcherInterface
     */
    private $dispatcher;

    /**
     * @var string
     */
    private $name;

    /**
     * @var PropertyPathInterface
     */
    private $propertyPath;

    /**
     * @var Boolean
     */
    private $mapped = true;

    /**
     * @var Boolean
     */
    private $byReference = true;

    /**
     * @var Boolean
     */
    private $inheritData = false;

    /**
     * @var Boolean
     */
    private $compound = false;

    /**
     * @var ResolvedFormTypeInterface
     */
    private $type;

    /**
     * @var array
     */
    private $viewTransformers = array();

    /**
     * @var array
     */
    private $modelTransformers = array();

    /**
     * @var DataMapperInterface
     */
    private $dataMapper;

    /**
     * @var Boolean
     */
    private $required = true;

    /**
     * @var Boolean
     */
    private $disabled = false;

    /**
     * @var Boolean
     */
    private $errorBubbling = false;

    /**
     * @var mixed
     */
    private $emptyData;

    /**
     * @var array
     */
    private $attributes = array();

    /**
     * @var mixed
     */
    private $data;

    /**
     * @var string
     */
    private $dataClass;

    /**
     * @var Boolean
     */
    private $dataLocked;

    /**
     * @var FormFactoryInterface
     */
    private $formFactory;

    /**
     * @var string
     */
    private $action;

    /**
     * @var string
     */
    private $method = 'POST';

    /**
     * @var RequestHandlerInterface
     */
    private $requestHandler;

    /**
     * @var Boolean
     */
    private $autoInitialize = false;

    /**
     * @var array
     */
    private $options;

    /**
     * Creates an empty form configuration.
     *
     * @param string|integer           $name       The form name
     * @param string                   $dataClass  The class of the form's data
     * @param EventDispatcherInterface $dispatcher The event dispatcher
     * @param array                    $options    The form options
     *
     * @throws InvalidArgumentException If the data class is not a valid class or if
     *                                   the name contains invalid characters.
     */
    public function __construct($name, $dataClass, EventDispatcherInterface $dispatcher, array $options = array())
    {
        self::validateName($name);

        if (null !== $dataClass && !class_exists($dataClass)) {
            throw new InvalidArgumentException(sprintf('The data class "%s" is not a valid class.', $dataClass));
        }

        $this->name = (string) $name;
        $this->dataClass = $dataClass;
        $this->dispatcher = $dispatcher;
        $this->options = $options;
    }

    /**
     * {@inheritdoc}
     */
    public function addEventListener($eventName, $listener, $priority = 0)
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        $this->dispatcher->addListener($eventName, $listener, $priority);

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function addEventSubscriber(EventSubscriberInterface $subscriber)
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        $this->dispatcher->addSubscriber($subscriber);

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function addViewTransformer(DataTransformerInterface $viewTransformer, $forcePrepend = false)
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        if ($forcePrepend) {
            array_unshift($this->viewTransformers, $viewTransformer);
        } else {
            $this->viewTransformers[] = $viewTransformer;
        }

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function resetViewTransformers()
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        $this->viewTransformers = array();

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function addModelTransformer(DataTransformerInterface $modelTransformer, $forceAppend = false)
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        if ($forceAppend) {
            $this->modelTransformers[] = $modelTransformer;
        } else {
            array_unshift($this->modelTransformers, $modelTransformer);
        }

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function resetModelTransformers()
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        $this->modelTransformers = array();

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function getEventDispatcher()
    {
        if ($this->locked && !$this->dispatcher instanceof ImmutableEventDispatcher) {
            $this->dispatcher = new ImmutableEventDispatcher($this->dispatcher);
        }

        return $this->dispatcher;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * {@inheritdoc}
     */
    public function getPropertyPath()
    {
        return $this->propertyPath;
    }

    /**
     * {@inheritdoc}
     */
    public function getMapped()
    {
        return $this->mapped;
    }

    /**
     * {@inheritdoc}
     */
    public function getByReference()
    {
        return $this->byReference;
    }

    /**
     * {@inheritdoc}
     */
    public function getInheritData()
    {
        return $this->inheritData;
    }

    /**
     * Alias of {@link getInheritData()}.
     *
     * @return FormConfigBuilder The configuration object.
     *
     * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
     *             {@link getInheritData()} instead.
     */
    public function getVirtual()
    {
        // Uncomment this as soon as the deprecation note should be shown
        // trigger_error('getVirtual() is deprecated since version 2.3 and will be removed in 3.0. Use getInheritData() instead.', E_USER_DEPRECATED);
        return $this->getInheritData();
    }

    /**
     * {@inheritdoc}
     */
    public function getCompound()
    {
        return $this->compound;
    }

    /**
     * {@inheritdoc}
     */
    public function getType()
    {
        return $this->type;
    }

    /**
     * {@inheritdoc}
     */
    public function getViewTransformers()
    {
        return $this->viewTransformers;
    }

    /**
     * {@inheritdoc}
     */
    public function getModelTransformers()
    {
        return $this->modelTransformers;
    }

    /**
     * {@inheritdoc}
     */
    public function getDataMapper()
    {
        return $this->dataMapper;
    }

    /**
     * {@inheritdoc}
     */
    public function getRequired()
    {
        return $this->required;
    }

    /**
     * {@inheritdoc}
     */
    public function getDisabled()
    {
        return $this->disabled;
    }

    /**
     * {@inheritdoc}
     */
    public function getErrorBubbling()
    {
        return $this->errorBubbling;
    }

    /**
     * {@inheritdoc}
     */
    public function getEmptyData()
    {
        return $this->emptyData;
    }

    /**
     * {@inheritdoc}
     */
    public function getAttributes()
    {
        return $this->attributes;
    }

    /**
     * {@inheritdoc}
     */
    public function hasAttribute($name)
    {
        return array_key_exists($name, $this->attributes);
    }

    /**
     * {@inheritdoc}
     */
    public function getAttribute($name, $default = null)
    {
        return array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default;
    }

    /**
     * {@inheritdoc}
     */
    public function getData()
    {
        return $this->data;
    }

    /**
     * {@inheritdoc}
     */
    public function getDataClass()
    {
        return $this->dataClass;
    }

    /**
     * {@inheritdoc}
     */
    public function getDataLocked()
    {
        return $this->dataLocked;
    }

    /**
     * {@inheritdoc}
     */
    public function getFormFactory()
    {
        return $this->formFactory;
    }

    /**
     * {@inheritdoc}
     */
    public function getAction()
    {
        return $this->action;
    }

    /**
     * {@inheritdoc}
     */
    public function getMethod()
    {
        return $this->method;
    }

    /**
     * {@inheritdoc}
     */
    public function getRequestHandler()
    {
        if (null === $this->requestHandler) {
            if (null === self::$nativeRequestProcessor) {
                self::$nativeRequestProcessor = new NativeRequestHandler();
            }
            $this->requestHandler = self::$nativeRequestProcessor;
        }

        return $this->requestHandler;
    }

    /**
     * {@inheritdoc}
     */
    public function getAutoInitialize()
    {
        return $this->autoInitialize;
    }

    /**
     * {@inheritdoc}
     */
    public function getOptions()
    {
        return $this->options;
    }

    /**
     * {@inheritdoc}
     */
    public function hasOption($name)
    {
        return array_key_exists($name, $this->options);
    }

    /**
     * {@inheritdoc}
     */
    public function getOption($name, $default = null)
    {
        return array_key_exists($name, $this->options) ? $this->options[$name] : $default;
    }

    /**
     * {@inheritdoc}
     */
    public function setAttribute($name, $value)
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        $this->attributes[$name] = $value;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setAttributes(array $attributes)
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        $this->attributes = $attributes;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setDataMapper(DataMapperInterface $dataMapper = null)
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        $this->dataMapper = $dataMapper;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setDisabled($disabled)
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        $this->disabled = (Boolean) $disabled;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setEmptyData($emptyData)
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        $this->emptyData = $emptyData;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setErrorBubbling($errorBubbling)
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        $this->errorBubbling = null === $errorBubbling ? null : (Boolean) $errorBubbling;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setRequired($required)
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        $this->required = (Boolean) $required;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setPropertyPath($propertyPath)
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        if (null !== $propertyPath && !$propertyPath instanceof PropertyPathInterface) {
            $propertyPath = new PropertyPath($propertyPath);
        }

        $this->propertyPath = $propertyPath;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setMapped($mapped)
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        $this->mapped = $mapped;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setByReference($byReference)
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        $this->byReference = $byReference;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setInheritData($inheritData)
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        $this->inheritData = $inheritData;

        return $this;
    }

    /**
     * Alias of {@link setInheritData()}.
     *
     * @param Boolean $inheritData Whether the form should inherit its parent's data.
     *
     * @return FormConfigBuilder The configuration object.
     *
     * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
     *             {@link setInheritData()} instead.
     */
    public function setVirtual($inheritData)
    {
        // Uncomment this as soon as the deprecation note should be shown
        // trigger_error('setVirtual() is deprecated since version 2.3 and will be removed in 3.0. Use setInheritData() instead.', E_USER_DEPRECATED);

        $this->setInheritData($inheritData);
    }

    /**
     * {@inheritdoc}
     */
    public function setCompound($compound)
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        $this->compound = $compound;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setType(ResolvedFormTypeInterface $type)
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        $this->type = $type;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setData($data)
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        $this->data = $data;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setDataLocked($locked)
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        $this->dataLocked = $locked;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setFormFactory(FormFactoryInterface $formFactory)
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        $this->formFactory = $formFactory;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setAction($action)
    {
        if ($this->locked) {
            throw new BadMethodCallException('The config builder cannot be modified anymore.');
        }

        $this->action = $action;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setMethod($method)
    {
        if ($this->locked) {
            throw new BadMethodCallException('The config builder cannot be modified anymore.');
        }

        $upperCaseMethod = strtoupper($method);

        if (!in_array($upperCaseMethod, self::$allowedMethods)) {
            throw new InvalidArgumentException(sprintf(
                'The form method is "%s", but should be one of "%s".',
                $method,
                implode('", "', self::$allowedMethods)
            ));
        }

        $this->method = $upperCaseMethod;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setRequestHandler(RequestHandlerInterface $requestHandler)
    {
        if ($this->locked) {
            throw new BadMethodCallException('The config builder cannot be modified anymore.');
        }

        $this->requestHandler = $requestHandler;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setAutoInitialize($initialize)
    {
        $this->autoInitialize = (Boolean) $initialize;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function getFormConfig()
    {
        if ($this->locked) {
            throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
        }

        // This method should be idempotent, so clone the builder
        $config = clone $this;
        $config->locked = true;

        return $config;
    }

    /**
     * Validates whether the given variable is a valid form name.
     *
     * @param string|integer $name The tested form name.
     *
     * @throws UnexpectedTypeException   If the name is not a string or an integer.
     * @throws InvalidArgumentException If the name contains invalid characters.
     */
    public static function validateName($name)
    {
        if (null !== $name && !is_string($name) && !is_int($name)) {
            throw new UnexpectedTypeException($name, 'string, integer or null');
        }

        if (!self::isValidName($name)) {
            throw new InvalidArgumentException(sprintf(
                'The name "%s" contains illegal characters. Names should start with a letter, digit or underscore and only contain letters, digits, numbers, underscores ("_"), hyphens ("-") and colons (":").',
                $name
            ));
        }
    }

    /**
     * Returns whether the given variable contains a valid form name.
     *
     * A name is accepted if it
     *
     *   * is empty
     *   * starts with a letter, digit or underscore
     *   * contains only letters, digits, numbers, underscores ("_"),
     *     hyphens ("-") and colons (":")
     *
     * @param string $name The tested form name.
     *
     * @return Boolean Whether the name is valid.
     */
    public static function isValidName($name)
    {
        return '' === $name || null === $name || preg_match('/^[a-zA-Z0-9_][a-zA-Z0-9_\-:]*$/D', $name);
    }
}
PK{�ZE1�'��4Symfony/Component/Form/SubmitButtonTypeInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

/**
 * A type that should be converted into a {@link SubmitButton} instance.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface SubmitButtonTypeInterface extends FormTypeInterface
{
}
PK{�Z�d��'Symfony/Component/Form/FormRegistry.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

use Symfony\Component\Form\Exception\ExceptionInterface;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\Form\Exception\InvalidArgumentException;

/**
 * The central registry of the Form component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class FormRegistry implements FormRegistryInterface
{
    /**
     * Extensions
     *
     * @var FormExtensionInterface[] An array of FormExtensionInterface
     */
    private $extensions = array();

    /**
     * @var array
     */
    private $types = array();

    /**
     * @var FormTypeGuesserInterface|false|null
     */
    private $guesser = false;

    /**
     * @var ResolvedFormTypeFactoryInterface
     */
    private $resolvedTypeFactory;

    /**
     * Constructor.
     *
     * @param FormExtensionInterface[]         $extensions          An array of FormExtensionInterface
     * @param ResolvedFormTypeFactoryInterface $resolvedTypeFactory The factory for resolved form types.
     *
     * @throws UnexpectedTypeException if any extension does not implement FormExtensionInterface
     */
    public function __construct(array $extensions, ResolvedFormTypeFactoryInterface $resolvedTypeFactory)
    {
        foreach ($extensions as $extension) {
            if (!$extension instanceof FormExtensionInterface) {
                throw new UnexpectedTypeException($extension, 'Symfony\Component\Form\FormExtensionInterface');
            }
        }

        $this->extensions = $extensions;
        $this->resolvedTypeFactory = $resolvedTypeFactory;
    }

    /**
     * {@inheritdoc}
     */
    public function getType($name)
    {
        if (!is_string($name)) {
            throw new UnexpectedTypeException($name, 'string');
        }

        if (!isset($this->types[$name])) {
            /** @var FormTypeInterface $type */
            $type = null;

            foreach ($this->extensions as $extension) {
                /* @var FormExtensionInterface $extension */
                if ($extension->hasType($name)) {
                    $type = $extension->getType($name);
                    break;
                }
            }

            if (!$type) {
                throw new InvalidArgumentException(sprintf('Could not load type "%s"', $name));
            }

            $this->resolveAndAddType($type);
        }

        return $this->types[$name];
    }

    /**
     * Wraps a type into a ResolvedFormTypeInterface implementation and connects
     * it with its parent type.
     *
     * @param FormTypeInterface $type The type to resolve.
     *
     * @return ResolvedFormTypeInterface The resolved type.
     */
    private function resolveAndAddType(FormTypeInterface $type)
    {
        $parentType = $type->getParent();

        if ($parentType instanceof FormTypeInterface) {
            $this->resolveAndAddType($parentType);
            $parentType = $parentType->getName();
        }

        $typeExtensions = array();

        foreach ($this->extensions as $extension) {
            /* @var FormExtensionInterface $extension */
            $typeExtensions = array_merge(
                $typeExtensions,
                $extension->getTypeExtensions($type->getName())
            );
        }

        $this->types[$type->getName()] = $this->resolvedTypeFactory->createResolvedType(
            $type,
            $typeExtensions,
            $parentType ? $this->getType($parentType) : null
        );
    }

    /**
     * {@inheritdoc}
     */
    public function hasType($name)
    {
        if (isset($this->types[$name])) {
            return true;
        }

        try {
            $this->getType($name);
        } catch (ExceptionInterface $e) {
            return false;
        }

        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function getTypeGuesser()
    {
        if (false === $this->guesser) {
            $guessers = array();

            foreach ($this->extensions as $extension) {
                /* @var FormExtensionInterface $extension */
                $guesser = $extension->getTypeGuesser();

                if ($guesser) {
                    $guessers[] = $guesser;
                }
            }

            $this->guesser = !empty($guessers) ? new FormTypeGuesserChain($guessers) : null;
        }

        return $this->guesser;
    }

    /**
     * {@inheritdoc}
     */
    public function getExtensions()
    {
        return $this->extensions;
    }
}
PK{�ZÊM'%%.Symfony/Component/Form/FormConfigInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

/**
 * The configuration of a {@link Form} object.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface FormConfigInterface
{
    /**
     * Returns the event dispatcher used to dispatch form events.
     *
     * @return \Symfony\Component\EventDispatcher\EventDispatcherInterface The dispatcher.
     */
    public function getEventDispatcher();

    /**
     * Returns the name of the form used as HTTP parameter.
     *
     * @return string The form name.
     */
    public function getName();

    /**
     * Returns the property path that the form should be mapped to.
     *
     * @return null|\Symfony\Component\PropertyAccess\PropertyPathInterface The property path.
     */
    public function getPropertyPath();

    /**
     * Returns whether the form should be mapped to an element of its
     * parent's data.
     *
     * @return Boolean Whether the form is mapped.
     */
    public function getMapped();

    /**
     * Returns whether the form's data should be modified by reference.
     *
     * @return Boolean Whether to modify the form's data by reference.
     */
    public function getByReference();

    /**
     * Returns whether the form should read and write the data of its parent.
     *
     * @return Boolean Whether the form should inherit its parent's data.
     */
    public function getInheritData();

    /**
     * Returns whether the form is compound.
     *
     * This property is independent of whether the form actually has
     * children. A form can be compound and have no children at all, like
     * for example an empty collection form.
     *
     * @return Boolean Whether the form is compound.
     */
    public function getCompound();

    /**
     * Returns the form types used to construct the form.
     *
     * @return ResolvedFormTypeInterface The form's type.
     */
    public function getType();

    /**
     * Returns the view transformers of the form.
     *
     * @return DataTransformerInterface[] An array of {@link DataTransformerInterface} instances.
     */
    public function getViewTransformers();

    /**
     * Returns the model transformers of the form.
     *
     * @return DataTransformerInterface[] An array of {@link DataTransformerInterface} instances.
     */
    public function getModelTransformers();

    /**
     * Returns the data mapper of the form.
     *
     * @return DataMapperInterface The data mapper.
     */
    public function getDataMapper();

    /**
     * Returns whether the form is required.
     *
     * @return Boolean Whether the form is required.
     */
    public function getRequired();

    /**
     * Returns whether the form is disabled.
     *
     * @return Boolean Whether the form is disabled.
     */
    public function getDisabled();

    /**
     * Returns whether errors attached to the form will bubble to its parent.
     *
     * @return Boolean Whether errors will bubble up.
     */
    public function getErrorBubbling();

    /**
     * Returns the data that should be returned when the form is empty.
     *
     * @return mixed The data returned if the form is empty.
     */
    public function getEmptyData();

    /**
     * Returns additional attributes of the form.
     *
     * @return array An array of key-value combinations.
     */
    public function getAttributes();

    /**
     * Returns whether the attribute with the given name exists.
     *
     * @param  string $name The attribute name.
     *
     * @return Boolean Whether the attribute exists.
     */
    public function hasAttribute($name);

    /**
     * Returns the value of the given attribute.
     *
     * @param  string $name    The attribute name.
     * @param  mixed  $default The value returned if the attribute does not exist.
     *
     * @return mixed The attribute value.
     */
    public function getAttribute($name, $default = null);

    /**
     * Returns the initial data of the form.
     *
     * @return mixed The initial form data.
     */
    public function getData();

    /**
     * Returns the class of the form data or null if the data is scalar or an array.
     *
     * @return string The data class or null.
     */
    public function getDataClass();

    /**
     * Returns whether the form's data is locked.
     *
     * A form with locked data is restricted to the data passed in
     * this configuration. The data can only be modified then by
     * submitting the form.
     *
     * @return Boolean Whether the data is locked.
     */
    public function getDataLocked();

    /**
     * Returns the form factory used for creating new forms.
     *
     * @return FormFactoryInterface The form factory.
     */
    public function getFormFactory();

    /**
     * Returns the target URL of the form.
     *
     * @return string The target URL of the form.
     */
    public function getAction();

    /**
     * Returns the HTTP method used by the form.
     *
     * @return string The HTTP method of the form.
     */
    public function getMethod();

    /**
     * Returns the request handler used by the form.
     *
     * @return RequestHandlerInterface The request handler.
     */
    public function getRequestHandler();

    /**
     * Returns whether the form should be initialized upon creation.
     *
     * @return Boolean Returns true if the form should be initialized
     *                 when created, false otherwise.
     */
    public function getAutoInitialize();

    /**
     * Returns all options passed during the construction of the form.
     *
     * @return array The passed options.
     */
    public function getOptions();

    /**
     * Returns whether a specific option exists.
     *
     * @param  string $name The option name,
     *
     * @return Boolean Whether the option exists.
     */
    public function hasOption($name);

    /**
     * Returns the value of a specific option.
     *
     * @param  string $name    The option name.
     * @param  mixed  $default The value returned if the option does not exist.
     *
     * @return mixed The option value.
     */
    public function getOption($name, $default = null);
}
PK{�Z��@@/Symfony/Component/Form/FormTypeGuesserChain.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

use Symfony\Component\Form\Guess\Guess;
use Symfony\Component\Form\Exception\UnexpectedTypeException;

class FormTypeGuesserChain implements FormTypeGuesserInterface
{
    private $guessers = array();

    /**
     * Constructor.
     *
     * @param FormTypeGuesserInterface[] $guessers Guessers as instances of FormTypeGuesserInterface
     *
     * @throws UnexpectedTypeException if any guesser does not implement FormTypeGuesserInterface
     */
    public function __construct(array $guessers)
    {
        foreach ($guessers as $guesser) {
            if (!$guesser instanceof FormTypeGuesserInterface) {
                throw new UnexpectedTypeException($guesser, 'Symfony\Component\Form\FormTypeGuesserInterface');
            }

            if ($guesser instanceof self) {
                $this->guessers = array_merge($this->guessers, $guesser->guessers);
            } else {
                $this->guessers[] = $guesser;
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    public function guessType($class, $property)
    {
        return $this->guess(function ($guesser) use ($class, $property) {
            return $guesser->guessType($class, $property);
        });
    }

    /**
     * {@inheritDoc}
     */
    public function guessRequired($class, $property)
    {
        return $this->guess(function ($guesser) use ($class, $property) {
            return $guesser->guessRequired($class, $property);
        });
    }

    /**
     * {@inheritDoc}
     */
    public function guessMaxLength($class, $property)
    {
        return $this->guess(function ($guesser) use ($class, $property) {
            return $guesser->guessMaxLength($class, $property);
        });
    }

    /**
     * {@inheritDoc}
     */
    public function guessPattern($class, $property)
    {
        return $this->guess(function ($guesser) use ($class, $property) {
            return $guesser->guessPattern($class, $property);
        });
    }

    /**
     * Executes a closure for each guesser and returns the best guess from the
     * return values
     *
     * @param \Closure $closure The closure to execute. Accepts a guesser
     *                            as argument and should return a Guess instance
     *
     * @return Guess|null The guess with the highest confidence
     */
    private function guess(\Closure $closure)
    {
        $guesses = array();

        foreach ($this->guessers as $guesser) {
            if ($guess = $closure($guesser)) {
                $guesses[] = $guess;
            }
        }

        return Guess::getBestGuess($guesses);
    }
}
PK{�ZR����+Symfony/Component/Form/Guess/ValueGuess.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Guess;

/**
 * Contains a guessed value
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ValueGuess extends Guess
{
    /**
     * The guessed value
     * @var array
     */
    private $value;

    /**
     * Constructor
     *
     * @param string  $value      The guessed value
     * @param integer $confidence The confidence that the guessed class name
     *                              is correct
     */
    public function __construct($value, $confidence)
    {
        parent::__construct($confidence);

        $this->value = $value;
    }

    /**
     * Returns the guessed value
     *
     * @return mixed
     */
    public function getValue()
    {
        return $this->value;
    }
}
PK{�Z�511&Symfony/Component/Form/Guess/Guess.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Guess;

use Symfony\Component\Form\Exception\InvalidArgumentException;

/**
 * Base class for guesses made by TypeGuesserInterface implementation
 *
 * Each instance contains a confidence value about the correctness of the guess.
 * Thus an instance with confidence HIGH_CONFIDENCE is more likely to be
 * correct than an instance with confidence LOW_CONFIDENCE.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
abstract class Guess
{
    /**
     * Marks an instance with a value that is extremely likely to be correct
     * @var integer
     */
    const VERY_HIGH_CONFIDENCE = 3;

    /**
     * Marks an instance with a value that is very likely to be correct
     * @var integer
     */
    const HIGH_CONFIDENCE = 2;

    /**
     * Marks an instance with a value that is likely to be correct
     * @var integer
     */
    const MEDIUM_CONFIDENCE = 1;

    /**
     * Marks an instance with a value that may be correct
     * @var integer
     */
    const LOW_CONFIDENCE = 0;

    /**
     * The confidence about the correctness of the value
     *
     * One of VERY_HIGH_CONFIDENCE, HIGH_CONFIDENCE, MEDIUM_CONFIDENCE
     * and LOW_CONFIDENCE.
     *
     * @var integer
     */
    private $confidence;

    /**
     * Returns the guess most likely to be correct from a list of guesses.
     *
     * If there are multiple guesses with the same, highest confidence, the
     * returned guess is any of them.
     *
     * @param Guess[] $guesses An array of guesses
     *
     * @return Guess|null The guess with the highest confidence
     */
    public static function getBestGuess(array $guesses)
    {
        $result = null;
        $maxConfidence = -1;

        foreach ($guesses as $guess) {
            if ($maxConfidence < $confidence = $guess->getConfidence()) {
                $maxConfidence = $confidence;
                $result = $guess;
            }
        }

        return $result;
    }

    /**
     * Constructor.
     *
     * @param integer $confidence The confidence
     *
     * @throws InvalidArgumentException if the given value of confidence is unknown
     */
    public function __construct($confidence)
    {
        if (self::VERY_HIGH_CONFIDENCE !== $confidence && self::HIGH_CONFIDENCE !== $confidence &&
            self::MEDIUM_CONFIDENCE !== $confidence && self::LOW_CONFIDENCE !== $confidence) {
            throw new InvalidArgumentException('The confidence should be one of the constants defined in Guess.');
        }

        $this->confidence = $confidence;
    }

    /**
     * Returns the confidence that the guessed value is correct.
     *
     * @return integer One of the constants VERY_HIGH_CONFIDENCE,
     *                 HIGH_CONFIDENCE, MEDIUM_CONFIDENCE and LOW_CONFIDENCE
     */
    public function getConfidence()
    {
        return $this->confidence;
    }
}
PK{�Z���  *Symfony/Component/Form/Guess/TypeGuess.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Guess;

/**
 * Contains a guessed class name and a list of options for creating an instance
 * of that class
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class TypeGuess extends Guess
{
    /**
     * The guessed field type
     * @var string
     */
    private $type;

    /**
     * The guessed options for creating an instance of the guessed class
     * @var array
     */
    private $options;

    /**
     * Constructor
     *
     * @param string $type    The guessed field type
     * @param array  $options The options for creating instances of the
     *                              guessed class
     * @param integer $confidence The confidence that the guessed class name
     *                              is correct
     */
    public function __construct($type, array $options, $confidence)
    {
        parent::__construct($confidence);

        $this->type = $type;
        $this->options = $options;
    }

    /**
     * Returns the guessed field type
     *
     * @return string
     */
    public function getType()
    {
        return $this->type;
    }

    /**
     * Returns the guessed options for creating instances of the guessed type
     *
     * @return array
     */
    public function getOptions()
    {
        return $this->options;
    }
}
PK{�Z�0\ZZ.Symfony/Component/Form/CallbackTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\Form\Exception\TransformationFailedException;

class CallbackTransformer implements DataTransformerInterface
{
    /**
     * The callback used for forward transform
     * @var \Closure
     */
    private $transform;

    /**
     * The callback used for reverse transform
     * @var \Closure
     */
    private $reverseTransform;

    /**
     * Constructor.
     *
     * @param \Closure $transform        The forward transform callback
     * @param \Closure $reverseTransform The reverse transform callback
     */
    public function __construct(\Closure $transform, \Closure $reverseTransform)
    {
        $this->transform = $transform;
        $this->reverseTransform = $reverseTransform;
    }

    /**
     * Transforms a value from the original representation to a transformed representation.
     *
     * @param mixed $data The value in the original representation
     *
     * @return mixed The value in the transformed representation
     *
     * @throws UnexpectedTypeException   when the argument is not a string
     * @throws TransformationFailedException  when the transformation fails
     */
    public function transform($data)
    {
        return call_user_func($this->transform, $data);
    }

    /**
     * Transforms a value from the transformed representation to its original
     * representation.
     *
     * @param mixed $data The value in the transformed representation
     *
     * @return mixed The value in the original representation
     *
     * @throws UnexpectedTypeException   when the argument is not of the expected type
     * @throws TransformationFailedException  when the transformation fails
     */
    public function reverseTransform($data)
    {
        return call_user_func($this->reverseTransform, $data);
    }
}
PK{�Z4�Nz"z"!Symfony/Component/Form/Button.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

use Symfony\Component\Form\Exception\AlreadySubmittedException;
use Symfony\Component\Form\Exception\BadMethodCallException;

/**
 * A form button.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class Button implements \IteratorAggregate, FormInterface
{
    /**
     * @var FormInterface|null
     */
    private $parent;

    /**
     * @var FormConfigInterface
     */
    private $config;

    /**
     * @var Boolean
     */
    private $submitted = false;

    /**
     * Creates a new button from a form configuration.
     *
     * @param FormConfigInterface $config The button's configuration.
     */
    public function __construct(FormConfigInterface $config)
    {
        $this->config = $config;
    }

    /**
     * Unsupported method.
     *
     * @param mixed $offset
     *
     * @return Boolean Always returns false.
     */
    public function offsetExists($offset)
    {
        return false;
    }

    /**
     * Unsupported method.
     *
     * This method should not be invoked.
     *
     * @param mixed $offset
     *
     * @throws BadMethodCallException
     */
    public function offsetGet($offset)
    {
        throw new BadMethodCallException('Buttons cannot have children.');
    }

    /**
     * Unsupported method.
     *
     * This method should not be invoked.
     *
     * @param mixed $offset
     * @param mixed $value
     *
     * @throws BadMethodCallException
     */
    public function offsetSet($offset, $value)
    {
        throw new BadMethodCallException('Buttons cannot have children.');
    }

    /**
     * Unsupported method.
     *
     * This method should not be invoked.
     *
     * @param mixed $offset
     *
     * @throws BadMethodCallException
     */
    public function offsetUnset($offset)
    {
        throw new BadMethodCallException('Buttons cannot have children.');
    }

    /**
     * {@inheritdoc}
     */
    public function setParent(FormInterface $parent = null)
    {
        $this->parent = $parent;
    }

    /**
     * {@inheritdoc}
     */
    public function getParent()
    {
        return $this->parent;
    }

    /**
     * Unsupported method.
     *
     * This method should not be invoked.
     *
     * @param int|string|FormInterface $child
     * @param null                     $type
     * @param array                    $options
     *
     * @throws BadMethodCallException
     */
    public function add($child, $type = null, array $options = array())
    {
        throw new BadMethodCallException('Buttons cannot have children.');
    }

    /**
     * Unsupported method.
     *
     * This method should not be invoked.
     *
     * @param string $name
     *
     * @throws BadMethodCallException
     */
    public function get($name)
    {
        throw new BadMethodCallException('Buttons cannot have children.');
    }

    /**
     * Unsupported method.
     *
     * @param string $name
     *
     * @return Boolean Always returns false.
     */
    public function has($name)
    {
        return false;
    }

    /**
     * Unsupported method.
     *
     * This method should not be invoked.
     *
     * @param string $name
     *
     * @throws BadMethodCallException
     */
    public function remove($name)
    {
        throw new BadMethodCallException('Buttons cannot have children.');
    }

    /**
     * {@inheritdoc}
     */
    public function all()
    {
        return array();
    }

    /**
     * {@inheritdoc}
     */
    public function getErrors()
    {
        return array();
    }

    /**
     * Unsupported method.
     *
     * This method should not be invoked.
     *
     * @param string $modelData
     *
     * @throws BadMethodCallException
     */
    public function setData($modelData)
    {
        // called during initialization of the form tree
        // noop
    }

    /**
     * Unsupported method.
     *
     * @return null Always returns null.
     */
    public function getData()
    {
        return null;
    }

    /**
     * Unsupported method.
     *
     * @return null Always returns null.
     */
    public function getNormData()
    {
        return null;
    }

    /**
     * Unsupported method.
     *
     * @return null Always returns null.
     */
    public function getViewData()
    {
        return null;
    }

    /**
     * Unsupported method.
     *
     * @return array Always returns an empty array.
     */
    public function getExtraData()
    {
        return array();
    }

    /**
     * Returns the button's configuration.
     *
     * @return FormConfigInterface The configuration.
     */
    public function getConfig()
    {
        return $this->config;
    }

    /**
     * Returns whether the button is submitted.
     *
     * @return Boolean true if the button was submitted.
     */
    public function isSubmitted()
    {
        return $this->submitted;
    }

    /**
     * Returns the name by which the button is identified in forms.
     *
     * @return string The name of the button.
     */
    public function getName()
    {
        return $this->config->getName();
    }

    /**
     * Unsupported method.
     *
     * @return null Always returns null.
     */
    public function getPropertyPath()
    {
        return null;
    }

    /**
     * Unsupported method.
     *
     * @param FormError $error
     *
     * @throws BadMethodCallException
     */
    public function addError(FormError $error)
    {
        throw new BadMethodCallException('Buttons cannot have errors.');
    }

    /**
     * Unsupported method.
     *
     * @return Boolean Always returns true.
     */
    public function isValid()
    {
        return true;
    }

    /**
     * Unsupported method.
     *
     * @return Boolean Always returns false.
     */
    public function isRequired()
    {
        return false;
    }

    /**
     * {@inheritdoc}
     */
    public function isDisabled()
    {
        return $this->config->getDisabled();
    }

    /**
     * Unsupported method.
     *
     * @return Boolean Always returns true.
     */
    public function isEmpty()
    {
        return true;
    }

    /**
     * Unsupported method.
     *
     * @return Boolean Always returns true.
     */
    public function isSynchronized()
    {
        return true;
    }

    /**
     * Unsupported method.
     *
     * @throws BadMethodCallException
     */
    public function initialize()
    {
        throw new BadMethodCallException('Buttons cannot be initialized. Call initialize() on the root form instead.');
    }

    /**
     * Unsupported method.
     *
     * @param mixed $request
     *
     * @throws BadMethodCallException
     */
    public function handleRequest($request = null)
    {
        throw new BadMethodCallException('Buttons cannot handle requests. Call handleRequest() on the root form instead.');
    }

    /**
     * Submits data to the button.
     *
     * @param null|string $submittedData The data.
     * @param Boolean     $clearMissing  Not used.
     *
     * @return Button The button instance
     *
     * @throws Exception\AlreadySubmittedException If the button has already been submitted.
     */
    public function submit($submittedData, $clearMissing = true)
    {
        if ($this->submitted) {
            throw new AlreadySubmittedException('A form can only be submitted once');
        }

        $this->submitted = true;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function getRoot()
    {
        return $this->parent ? $this->parent->getRoot() : $this;
    }

    /**
     * {@inheritdoc}
     */
    public function isRoot()
    {
        return null === $this->parent;
    }

    /**
     * {@inheritdoc}
     */
    public function createView(FormView $parent = null)
    {
        if (null === $parent && $this->parent) {
            $parent = $this->parent->createView();
        }

        $type = $this->config->getType();
        $options = $this->config->getOptions();

        $view = $type->createView($this, $parent);

        $type->buildView($view, $this, $options);
        $type->finishView($view, $this, $options);

        return $view;
    }

    /**
     * Unsupported method.
     *
     * @return integer Always returns 0.
     */
    public function count()
    {
        return 0;
    }

    /**
     * Unsupported method.
     *
     * @return \EmptyIterator Always returns an empty iterator.
     */
    public function getIterator()
    {
        return new \EmptyIterator();
    }
}
PK{�Z-�9NN%Symfony/Component/Form/autoloader.phpnu�[���<?php

spl_autoload_register(function ($class) {
    if ('\\' == $class[0]) {
        $class = substr($class, 1);
    }

    if (
        0 === strpos($class, 'Symfony\\Component\\Form\\')
        &&
        file_exists($file = __DIR__.'/../../../'.str_replace('\\', '/', $class).'.php')
    ) {
        require_once $file;
    }
});
PK{�Z�/��tt%Symfony/Component/Form/FormEvents.phpnu�[���<?php
/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
final class FormEvents
{
    const PRE_SUBMIT = 'form.pre_bind';

    const SUBMIT = 'form.bind';

    const POST_SUBMIT = 'form.post_bind';

    const PRE_SET_DATA = 'form.pre_set_data';

    const POST_SET_DATA = 'form.post_set_data';

    /**
     * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
     *             {@link PRE_SUBMIT} instead.
     */
    const PRE_BIND = 'form.pre_bind';

    /**
     * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
     *             {@link SUBMIT} instead.
     */
    const BIND = 'form.bind';

    /**
     * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
     *             {@link POST_SUBMIT} instead.
     */
    const POST_BIND = 'form.post_bind';

    private function __construct()
    {
    }
}
PK{�Z�����,Symfony/Component/Form/FormTypeInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

use Symfony\Component\OptionsResolver\OptionsResolverInterface;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface FormTypeInterface
{
    /**
     * Builds the form.
     *
     * This method is called for each type in the hierarchy starting form the
     * top most type. Type extensions can further modify the form.
     *
     * @see FormTypeExtensionInterface::buildForm()
     *
     * @param FormBuilderInterface $builder The form builder
     * @param array                $options The options
     */
    public function buildForm(FormBuilderInterface $builder, array $options);

    /**
     * Builds the form view.
     *
     * This method is called for each type in the hierarchy starting form the
     * top most type. Type extensions can further modify the view.
     *
     * A view of a form is built before the views of the child forms are built.
     * This means that you cannot access child views in this method. If you need
     * to do so, move your logic to {@link finishView()} instead.
     *
     * @see FormTypeExtensionInterface::buildView()
     *
     * @param FormView $view    The view
     * @param FormInterface     $form    The form
     * @param array             $options The options
     */
    public function buildView(FormView $view, FormInterface $form, array $options);

    /**
     * Finishes the form view.
     *
     * This method gets called for each type in the hierarchy starting form the
     * top most type. Type extensions can further modify the view.
     *
     * When this method is called, views of the form's children have already
     * been built and finished and can be accessed. You should only implement
     * such logic in this method that actually accesses child views. For everything
     * else you are recommended to implement {@link buildView()} instead.
     *
     * @see FormTypeExtensionInterface::finishView()
     *
     * @param FormView $view    The view
     * @param FormInterface     $form    The form
     * @param array             $options The options
     */
    public function finishView(FormView $view, FormInterface $form, array $options);

    /**
     * Sets the default options for this type.
     *
     * @param OptionsResolverInterface $resolver The resolver for the options.
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver);

    /**
     * Returns the name of the parent type.
     *
     * You can also return a type instance from this method, although doing so
     * is discouraged because it leads to a performance penalty. The support
     * for returning type instances may be dropped from future releases.
     *
     * @return string|null|FormTypeInterface The name of the parent type if any, null otherwise.
     */
    public function getParent();

    /**
     * Returns the name of this type.
     *
     * @return string The name of this type
     */
    public function getName();
}
PK{�Z�>���0Symfony/Component/Form/FormRegistryInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

/**
 * The central registry of the Form component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface FormRegistryInterface
{
    /**
     * Returns a form type by name.
     *
     * This methods registers the type extensions from the form extensions.
     *
     * @param string $name The name of the type
     *
     * @return ResolvedFormTypeInterface The type
     *
     * @throws Exception\UnexpectedTypeException  if the passed name is not a string
     * @throws Exception\InvalidArgumentException if the type can not be retrieved from any extension
     */
    public function getType($name);

    /**
     * Returns whether the given form type is supported.
     *
     * @param string $name The name of the type
     *
     * @return Boolean Whether the type is supported
     */
    public function hasType($name);

    /**
     * Returns the guesser responsible for guessing types.
     *
     * @return FormTypeGuesserInterface|null
     */
    public function getTypeGuesser();

    /**
     * Returns the extensions loaded by the framework.
     *
     * @return FormExtensionInterface[]
     */
    public function getExtensions();
}
PK{�Z��?zz3Symfony/Component/Form/FormTypeGuesserInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface FormTypeGuesserInterface
{
    /**
     * Returns a field guess for a property name of a class
     *
     * @param string $class    The fully qualified class name
     * @param string $property The name of the property to guess for
     *
     * @return Guess\TypeGuess|null A guess for the field's type and options
     */
    public function guessType($class, $property);

    /**
     * Returns a guess whether a property of a class is required
     *
     * @param string $class    The fully qualified class name
     * @param string $property The name of the property to guess for
     *
     * @return Guess\ValueGuess A guess for the field's required setting
     */
    public function guessRequired($class, $property);

    /**
     * Returns a guess about the field's maximum length
     *
     * @param string $class    The fully qualified class name
     * @param string $property The name of the property to guess for
     *
     * @return Guess\ValueGuess|null A guess for the field's maximum length
     */
    public function guessMaxLength($class, $property);

    /**
     * Returns a guess about the field's pattern
     *
     * - When you have a min value, you guess a min length of this min (LOW_CONFIDENCE) , lines below
     * - If this value is a float type, this is wrong so you guess null with MEDIUM_CONFIDENCE to override the previous guess.
     * Example:
     *  You want a float greater than 5, 4.512313 is not valid but length(4.512314) > length(5)
     * @link https://github.com/symfony/symfony/pull/3927
     *
     * @param string $class    The fully qualified class name
     * @param string $property The name of the property to guess for
     *
     * @return Guess\ValueGuess|null A guess for the field's required pattern
     */
    public function guessPattern($class, $property);
}
PK{�Z��*��+Symfony/Component/Form/ResolvedFormType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

use Symfony\Component\Form\Exception\InvalidArgumentException;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\OptionsResolver\OptionsResolver;

/**
 * A wrapper for a form type and its extensions.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ResolvedFormType implements ResolvedFormTypeInterface
{
    /**
     * @var FormTypeInterface
     */
    private $innerType;

    /**
     * @var FormTypeExtensionInterface[]
     */
    private $typeExtensions;

    /**
     * @var ResolvedFormTypeInterface|null
     */
    private $parent;

    /**
     * @var OptionsResolver
     */
    private $optionsResolver;

    public function __construct(FormTypeInterface $innerType, array $typeExtensions = array(), ResolvedFormTypeInterface $parent = null)
    {
        if (!preg_match('/^[a-z0-9_]*$/i', $innerType->getName())) {
            throw new InvalidArgumentException(sprintf(
                'The "%s" form type name ("%s") is not valid. Names must only contain letters, numbers, and "_".',
                get_class($innerType),
                $innerType->getName()
            ));
        }

        foreach ($typeExtensions as $extension) {
            if (!$extension instanceof FormTypeExtensionInterface) {
                throw new UnexpectedTypeException($extension, 'Symfony\Component\Form\FormTypeExtensionInterface');
            }
        }

        $this->innerType = $innerType;
        $this->typeExtensions = $typeExtensions;
        $this->parent = $parent;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return $this->innerType->getName();
    }

    /**
     * {@inheritdoc}
     */
    public function getParent()
    {
        return $this->parent;
    }

    /**
     * {@inheritdoc}
     */
    public function getInnerType()
    {
        return $this->innerType;
    }

    /**
     * {@inheritdoc}
     */
    public function getTypeExtensions()
    {
        // BC
        if ($this->innerType instanceof AbstractType) {
            return $this->innerType->getExtensions();
        }

        return $this->typeExtensions;
    }

    /**
     * {@inheritdoc}
     */
    public function createBuilder(FormFactoryInterface $factory, $name, array $options = array())
    {
        $options = $this->getOptionsResolver()->resolve($options);

        // Should be decoupled from the specific option at some point
        $dataClass = isset($options['data_class']) ? $options['data_class'] : null;

        $builder = $this->newBuilder($name, $dataClass, $factory, $options);
        $builder->setType($this);

        return $builder;
    }

    /**
     * {@inheritdoc}
     */
    public function createView(FormInterface $form, FormView $parent = null)
    {
        return $this->newView($parent);
    }

    /**
     * Configures a form builder for the type hierarchy.
     *
     * @param FormBuilderInterface $builder The builder to configure.
     * @param array                $options The options used for the configuration.
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        if (null !== $this->parent) {
            $this->parent->buildForm($builder, $options);
        }

        $this->innerType->buildForm($builder, $options);

        foreach ($this->typeExtensions as $extension) {
            /* @var FormTypeExtensionInterface $extension */
            $extension->buildForm($builder, $options);
        }
    }

    /**
     * Configures a form view for the type hierarchy.
     *
     * This method is called before the children of the view are built.
     *
     * @param FormView      $view    The form view to configure.
     * @param FormInterface $form    The form corresponding to the view.
     * @param array         $options The options used for the configuration.
     */
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        if (null !== $this->parent) {
            $this->parent->buildView($view, $form, $options);
        }

        $this->innerType->buildView($view, $form, $options);

        foreach ($this->typeExtensions as $extension) {
            /* @var FormTypeExtensionInterface $extension */
            $extension->buildView($view, $form, $options);
        }
    }

    /**
     * Finishes a form view for the type hierarchy.
     *
     * This method is called after the children of the view have been built.
     *
     * @param FormView      $view    The form view to configure.
     * @param FormInterface $form    The form corresponding to the view.
     * @param array         $options The options used for the configuration.
     */
    public function finishView(FormView $view, FormInterface $form, array $options)
    {
        if (null !== $this->parent) {
            $this->parent->finishView($view, $form, $options);
        }

        $this->innerType->finishView($view, $form, $options);

        foreach ($this->typeExtensions as $extension) {
            /* @var FormTypeExtensionInterface $extension */
            $extension->finishView($view, $form, $options);
        }
    }

    /**
     * Returns the configured options resolver used for this type.
     *
     * @return \Symfony\Component\OptionsResolver\OptionsResolverInterface The options resolver.
     */
    public function getOptionsResolver()
    {
        if (null === $this->optionsResolver) {
            if (null !== $this->parent) {
                $this->optionsResolver = clone $this->parent->getOptionsResolver();
            } else {
                $this->optionsResolver = new OptionsResolver();
            }

            $this->innerType->setDefaultOptions($this->optionsResolver);

            foreach ($this->typeExtensions as $extension) {
                /* @var FormTypeExtensionInterface $extension */
                $extension->setDefaultOptions($this->optionsResolver);
            }
        }

        return $this->optionsResolver;
    }

    /**
     * Creates a new builder instance.
     *
     * Override this method if you want to customize the builder class.
     *
     * @param string               $name      The name of the builder.
     * @param string               $dataClass The data class.
     * @param FormFactoryInterface $factory   The current form factory.
     * @param array                $options   The builder options.
     *
     * @return FormBuilderInterface The new builder instance.
     */
    protected function newBuilder($name, $dataClass, FormFactoryInterface $factory, array $options)
    {
        if ($this->innerType instanceof ButtonTypeInterface) {
            return new ButtonBuilder($name, $options);
        }

        if ($this->innerType instanceof SubmitButtonTypeInterface) {
            return new SubmitButtonBuilder($name, $options);
        }

        return new FormBuilder($name, $dataClass, new EventDispatcher(), $factory, $options);
    }

    /**
     * Creates a new view instance.
     *
     * Override this method if you want to customize the view class.
     *
     * @param FormView|null $parent The parent view, if available.
     *
     * @return FormView A new view instance.
     */
    protected function newView(FormView $parent = null)
    {
        return new FormView($parent);
    }
}
PK{�ZObX�qq'Symfony/Component/Form/SubmitButton.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

/**
 * A button that submits the form.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class SubmitButton extends Button implements ClickableInterface
{
    /**
     * @var Boolean
     */
    private $clicked = false;

    /**
     * {@inheritdoc}
     */
    public function isClicked()
    {
        return $this->clicked;
    }

    /**
     * Submits data to the button.
     *
     * @param null|string $submittedData The data.
     * @param Boolean     $clearMissing  Not used.
     *
     * @return SubmitButton The button instance
     *
     * @throws Exception\AlreadySubmittedException If the form has already been submitted.
     */
    public function submit($submittedData, $clearMissing = true)
    {
        parent::submit($submittedData, $clearMissing);

        $this->clicked = null !== $submittedData;

        return $this;
    }
}
PK|�Z�p��1Symfony/Component/Form/AbstractRendererEngine.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

/**
 * Default implementation of {@link FormRendererEngineInterface}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
abstract class AbstractRendererEngine implements FormRendererEngineInterface
{
    /**
     * The variable in {@link FormView} used as cache key.
     */
    const CACHE_KEY_VAR = 'cache_key';

    /**
     * @var array
     */
    protected $defaultThemes;

    /**
     * @var array
     */
    protected $themes = array();

    /**
     * @var array
     */
    protected $resources = array();

    /**
     * @var array
     */
    private $resourceHierarchyLevels = array();

    /**
     * Creates a new renderer engine.
     *
     * @param array $defaultThemes The default themes. The type of these
     *                             themes is open to the implementation.
     */
    public function __construct(array $defaultThemes = array())
    {
        $this->defaultThemes = $defaultThemes;
    }

    /**
     * {@inheritdoc}
     */
    public function setTheme(FormView $view, $themes)
    {
        $cacheKey = $view->vars[self::CACHE_KEY_VAR];

        // Do not cast, as casting turns objects into arrays of properties
        $this->themes[$cacheKey] = is_array($themes) ? $themes : array($themes);

        // Unset instead of resetting to an empty array, in order to allow
        // implementations (like TwigRendererEngine) to check whether $cacheKey
        // is set at all.
        unset($this->resources[$cacheKey]);
        unset($this->resourceHierarchyLevels[$cacheKey]);
    }

    /**
     * {@inheritdoc}
     */
    public function getResourceForBlockName(FormView $view, $blockName)
    {
        $cacheKey = $view->vars[self::CACHE_KEY_VAR];

        if (!isset($this->resources[$cacheKey][$blockName])) {
            $this->loadResourceForBlockName($cacheKey, $view, $blockName);
        }

        return $this->resources[$cacheKey][$blockName];
    }

    /**
     * {@inheritdoc}
     */
    public function getResourceForBlockNameHierarchy(FormView $view, array $blockNameHierarchy, $hierarchyLevel)
    {
        $cacheKey = $view->vars[self::CACHE_KEY_VAR];
        $blockName = $blockNameHierarchy[$hierarchyLevel];

        if (!isset($this->resources[$cacheKey][$blockName])) {
            $this->loadResourceForBlockNameHierarchy($cacheKey, $view, $blockNameHierarchy, $hierarchyLevel);
        }

        return $this->resources[$cacheKey][$blockName];
    }

    /**
     * {@inheritdoc}
     */
    public function getResourceHierarchyLevel(FormView $view, array $blockNameHierarchy, $hierarchyLevel)
    {
        $cacheKey = $view->vars[self::CACHE_KEY_VAR];
        $blockName = $blockNameHierarchy[$hierarchyLevel];

        if (!isset($this->resources[$cacheKey][$blockName])) {
            $this->loadResourceForBlockNameHierarchy($cacheKey, $view, $blockNameHierarchy, $hierarchyLevel);
        }

        // If $block was previously rendered loaded with loadTemplateForBlock(), the template
        // is cached but the hierarchy level is not. In this case, we know that the  block
        // exists at this very hierarchy level, so we can just set it.
        if (!isset($this->resourceHierarchyLevels[$cacheKey][$blockName])) {
            $this->resourceHierarchyLevels[$cacheKey][$blockName] = $hierarchyLevel;
        }

        return $this->resourceHierarchyLevels[$cacheKey][$blockName];
    }

    /**
     * Loads the cache with the resource for a given block name.
     *
     * @see getResourceForBlock()
     *
     * @param string   $cacheKey  The cache key of the form view.
     * @param FormView $view      The form view for finding the applying themes.
     * @param string   $blockName The name of the block to load.
     *
     * @return Boolean True if the resource could be loaded, false otherwise.
     */
    abstract protected function loadResourceForBlockName($cacheKey, FormView $view, $blockName);

    /**
     * Loads the cache with the resource for a specific level of a block hierarchy.
     *
     * @see getResourceForBlockHierarchy()
     *
     * @param string   $cacheKey           The cache key used for storing the
     *                                     resource.
     * @param FormView $view               The form view for finding the applying
     *                                     themes.
     * @param array    $blockNameHierarchy The block hierarchy, with the most
     *                                     specific block name at the end.
     * @param integer  $hierarchyLevel     The level in the block hierarchy that
     *                                     should be loaded.
     *
     * @return Boolean True if the resource could be loaded, false otherwise.
     */
    private function loadResourceForBlockNameHierarchy($cacheKey, FormView $view, array $blockNameHierarchy, $hierarchyLevel)
    {
        $blockName = $blockNameHierarchy[$hierarchyLevel];

        // Try to find a template for that block
        if ($this->loadResourceForBlockName($cacheKey, $view, $blockName)) {
            // If loadTemplateForBlock() returns true, it was able to populate the
            // cache. The only missing thing is to set the hierarchy level at which
            // the template was found.
            $this->resourceHierarchyLevels[$cacheKey][$blockName] = $hierarchyLevel;

            return true;
        }

        if ($hierarchyLevel > 0) {
            $parentLevel = $hierarchyLevel - 1;
            $parentBlockName = $blockNameHierarchy[$parentLevel];

            // The next two if statements contain slightly duplicated code. This is by intention
            // and tries to avoid execution of unnecessary checks in order to increase performance.

            if (isset($this->resources[$cacheKey][$parentBlockName])) {
                // It may happen that the parent block is already loaded, but its level is not.
                // In this case, the parent block must have been loaded by loadResourceForBlock(),
                // which does not check the hierarchy of the block. Subsequently the block must have
                // been found directly on the parent level.
                if (!isset($this->resourceHierarchyLevels[$cacheKey][$parentBlockName])) {
                    $this->resourceHierarchyLevels[$cacheKey][$parentBlockName] = $parentLevel;
                }

                // Cache the shortcuts for further accesses
                $this->resources[$cacheKey][$blockName] = $this->resources[$cacheKey][$parentBlockName];
                $this->resourceHierarchyLevels[$cacheKey][$blockName] = $this->resourceHierarchyLevels[$cacheKey][$parentBlockName];

                return true;
            }

            if ($this->loadResourceForBlockNameHierarchy($cacheKey, $view, $blockNameHierarchy, $parentLevel)) {
                // Cache the shortcuts for further accesses
                $this->resources[$cacheKey][$blockName] = $this->resources[$cacheKey][$parentBlockName];
                $this->resourceHierarchyLevels[$cacheKey][$blockName] = $this->resourceHierarchyLevels[$cacheKey][$parentBlockName];

                return true;
            }
        }

        // Cache the result for further accesses
        $this->resources[$cacheKey][$blockName] = false;
        $this->resourceHierarchyLevels[$cacheKey][$blockName] = false;

        return false;
    }
}
PK|�ZDjN,Symfony/Component/Form/AbstractExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

use Symfony\Component\Form\Exception\InvalidArgumentException;
use Symfony\Component\Form\Exception\UnexpectedTypeException;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
abstract class AbstractExtension implements FormExtensionInterface
{
    /**
     * The types provided by this extension
     * @var FormTypeInterface[] An array of FormTypeInterface
     */
    private $types;

    /**
     * The type extensions provided by this extension
     * @var FormTypeExtensionInterface[] An array of FormTypeExtensionInterface
     */
    private $typeExtensions;

    /**
     * The type guesser provided by this extension
     * @var FormTypeGuesserInterface
     */
    private $typeGuesser;

    /**
     * Whether the type guesser has been loaded
     * @var Boolean
     */
    private $typeGuesserLoaded = false;

    /**
     * {@inheritdoc}
     */
    public function getType($name)
    {
        if (null === $this->types) {
            $this->initTypes();
        }

        if (!isset($this->types[$name])) {
            throw new InvalidArgumentException(sprintf('The type "%s" can not be loaded by this extension', $name));
        }

        return $this->types[$name];
    }

    /**
     * {@inheritdoc}
     */
    public function hasType($name)
    {
        if (null === $this->types) {
            $this->initTypes();
        }

        return isset($this->types[$name]);
    }

    /**
     * {@inheritdoc}
     */
    public function getTypeExtensions($name)
    {
        if (null === $this->typeExtensions) {
            $this->initTypeExtensions();
        }

        return isset($this->typeExtensions[$name])
            ? $this->typeExtensions[$name]
            : array();
    }

    /**
     * {@inheritdoc}
     */
    public function hasTypeExtensions($name)
    {
        if (null === $this->typeExtensions) {
            $this->initTypeExtensions();
        }

        return isset($this->typeExtensions[$name]) && count($this->typeExtensions[$name]) > 0;
    }

    /**
     * {@inheritdoc}
     */
    public function getTypeGuesser()
    {
        if (!$this->typeGuesserLoaded) {
            $this->initTypeGuesser();
        }

        return $this->typeGuesser;
    }

    /**
     * Registers the types.
     *
     * @return FormTypeInterface[] An array of FormTypeInterface instances
     */
    protected function loadTypes()
    {
        return array();
    }

    /**
     * Registers the type extensions.
     *
     * @return FormTypeExtensionInterface[] An array of FormTypeExtensionInterface instances
     */
    protected function loadTypeExtensions()
    {
        return array();
    }

    /**
     * Registers the type guesser.
     *
     * @return FormTypeGuesserInterface|null A type guesser
     */
    protected function loadTypeGuesser()
    {
        return null;
    }

    /**
     * Initializes the types.
     *
     * @throws UnexpectedTypeException if any registered type is not an instance of FormTypeInterface
     */
    private function initTypes()
    {
        $this->types = array();

        foreach ($this->loadTypes() as $type) {
            if (!$type instanceof FormTypeInterface) {
                throw new UnexpectedTypeException($type, 'Symfony\Component\Form\FormTypeInterface');
            }

            $this->types[$type->getName()] = $type;
        }
    }

    /**
     * Initializes the type extensions.
     *
     * @throws UnexpectedTypeException if any registered type extension is not
     *                                 an instance of FormTypeExtensionInterface
     */
    private function initTypeExtensions()
    {
        $this->typeExtensions = array();

        foreach ($this->loadTypeExtensions() as $extension) {
            if (!$extension instanceof FormTypeExtensionInterface) {
                throw new UnexpectedTypeException($extension, 'Symfony\Component\Form\FormTypeExtensionInterface');
            }

            $type = $extension->getExtendedType();

            $this->typeExtensions[$type][] = $extension;
        }
    }

    /**
     * Initializes the type guesser.
     *
     * @throws UnexpectedTypeException if the type guesser is not an instance of FormTypeGuesserInterface
     */
    private function initTypeGuesser()
    {
        $this->typeGuesserLoaded = true;

        $this->typeGuesser = $this->loadTypeGuesser();
        if (null !== $this->typeGuesser && !$this->typeGuesser instanceof FormTypeGuesserInterface) {
            throw new UnexpectedTypeException($this->typeGuesser, 'Symfony\Component\Form\FormTypeGuesserInterface');
        }
    }
}
PK|�Zf#jK��6Symfony/Component/Form/FormRendererEngineInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

/**
 * Adapter for rendering form templates with a specific templating engine.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface FormRendererEngineInterface
{
    /**
     * Sets the theme(s) to be used for rendering a view and its children.
     *
     * @param FormView $view   The view to assign the theme(s) to.
     * @param mixed    $themes The theme(s). The type of these themes
     *                         is open to the implementation.
     */
    public function setTheme(FormView $view, $themes);

    /**
     * Returns the resource for a block name.
     *
     * The resource is first searched in the themes attached to $view, then
     * in the themes of its parent view and so on, until a resource was found.
     *
     * The type of the resource is decided by the implementation. The resource
     * is later passed to {@link renderBlock()} by the rendering algorithm.
     *
     * @param FormView $view      The view for determining the used themes.
     *                            First the themes attached directly to the
     *                            view with {@link setTheme()} are considered,
     *                            then the ones of its parent etc.
     * @param string   $blockName The name of the block to render.
     *
     * @return mixed The renderer resource or false, if none was found.
     */
    public function getResourceForBlockName(FormView $view, $blockName);

    /**
     * Returns the resource for a block hierarchy.
     *
     * A block hierarchy is an array which starts with the root of the hierarchy
     * and continues with the child of that root, the child of that child etc.
     * The following is an example for a block hierarchy:
     *
     * <code>
     * form_widget
     * text_widget
     * url_widget
     * </code>
     *
     * In this example, "url_widget" is the most specific block, while the other
     * blocks are its ancestors in the hierarchy.
     *
     * The second parameter $hierarchyLevel determines the level of the hierarchy
     * that should be rendered. For example, if $hierarchyLevel is 2 for the
     * above hierarchy, the engine will first look for the block "url_widget",
     * then, if that does not exist, for the block "text_widget" etc.
     *
     * The type of the resource is decided by the implementation. The resource
     * is later passed to {@link renderBlock()} by the rendering algorithm.
     *
     * @param FormView          $view               The view for determining the
     *                                              used themes. First the themes
     *                                              attached directly to the view
     *                                              with {@link setTheme()} are
     *                                              considered, then the ones of
     *                                              its parent etc.
     * @param array             $blockNameHierarchy The block name hierarchy, with
     *                                              the root block at the beginning.
     * @param integer           $hierarchyLevel     The level in the hierarchy at
     *                                              which to start looking. Level 0
     *                                              indicates the root block, i.e.
     *                                              the first element of
     *                                              $blockNameHierarchy.
     *
     * @return mixed The renderer resource or false, if none was found.
     */
    public function getResourceForBlockNameHierarchy(FormView $view, array $blockNameHierarchy, $hierarchyLevel);

    /**
     * Returns the hierarchy level at which a resource can be found.
     *
     * A block hierarchy is an array which starts with the root of the hierarchy
     * and continues with the child of that root, the child of that child etc.
     * The following is an example for a block hierarchy:
     *
     * <code>
     * form_widget
     * text_widget
     * url_widget
     * </code>
     *
     * The second parameter $hierarchyLevel determines the level of the hierarchy
     * that should be rendered.
     *
     * If we call this method with the hierarchy level 2, the engine will first
     * look for a resource for block "url_widget". If such a resource exists,
     * the method returns 2. Otherwise it tries to find a resource for block
     * "text_widget" (at level 1) and, again, returns 1 if a resource was found.
     * The method continues to look for resources until the root level was
     * reached and nothing was found. In this case false is returned.
     *
     * The type of the resource is decided by the implementation. The resource
     * is later passed to {@link renderBlock()} by the rendering algorithm.
     *
     * @param FormView          $view               The view for determining the
     *                                              used themes. First the themes
     *                                              attached directly to the view
     *                                              with {@link setTheme()} are
     *                                              considered, then the ones of
     *                                              its parent etc.
     * @param array             $blockNameHierarchy The block name hierarchy, with
     *                                              the root block at the beginning.
     * @param integer           $hierarchyLevel     The level in the hierarchy at
     *                                              which to start looking. Level 0
     *                                              indicates the root block, i.e.
     *                                              the first element of
     *                                              $blockNameHierarchy.
     *
     * @return integer|Boolean The hierarchy level or false, if no resource was found.
     */
    public function getResourceHierarchyLevel(FormView $view, array $blockNameHierarchy, $hierarchyLevel);

    /**
     * Renders a block in the given renderer resource.
     *
     * The resource can be obtained by calling {@link getResourceForBlock()}
     * or {@link getResourceForBlockHierarchy()}. The type of the resource is
     * decided by the implementation.
     *
     * @param FormView          $view      The view to render.
     * @param mixed             $resource  The renderer resource.
     * @param string            $blockName The name of the block to render.
     * @param array             $variables The variables to pass to the template.
     *
     * @return string The HTML markup.
     */
    public function renderBlock(FormView $view, $resource, $blockName, array $variables = array());
}
PK|�Z���1�1�Symfony/Component/Form/Form.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

use Symfony\Component\Form\Exception\RuntimeException;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\Form\Exception\AlreadySubmittedException;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Symfony\Component\Form\Exception\LogicException;
use Symfony\Component\Form\Exception\OutOfBoundsException;
use Symfony\Component\Form\Util\FormUtil;
use Symfony\Component\Form\Util\InheritDataAwareIterator;
use Symfony\Component\Form\Util\OrderedHashMap;
use Symfony\Component\PropertyAccess\PropertyPath;

/**
 * Form represents a form.
 *
 * To implement your own form fields, you need to have a thorough understanding
 * of the data flow within a form. A form stores its data in three different
 * representations:
 *
 *   (1) the "model" format required by the form's object
 *   (2) the "normalized" format for internal processing
 *   (3) the "view" format used for display
 *
 * A date field, for example, may store a date as "Y-m-d" string (1) in the
 * object. To facilitate processing in the field, this value is normalized
 * to a DateTime object (2). In the HTML representation of your form, a
 * localized string (3) is presented to and modified by the user.
 *
 * In most cases, format (1) and format (2) will be the same. For example,
 * a checkbox field uses a Boolean value for both internal processing and
 * storage in the object. In these cases you simply need to set a value
 * transformer to convert between formats (2) and (3). You can do this by
 * calling addViewTransformer().
 *
 * In some cases though it makes sense to make format (1) configurable. To
 * demonstrate this, let's extend our above date field to store the value
 * either as "Y-m-d" string or as timestamp. Internally we still want to
 * use a DateTime object for processing. To convert the data from string/integer
 * to DateTime you can set a normalization transformer by calling
 * addNormTransformer(). The normalized data is then converted to the displayed
 * data as described before.
 *
 * The conversions (1) -> (2) -> (3) use the transform methods of the transformers.
 * The conversions (3) -> (2) -> (1) use the reverseTransform methods of the transformers.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class Form implements \IteratorAggregate, FormInterface
{
    /**
     * The form's configuration
     * @var FormConfigInterface
     */
    private $config;

    /**
     * The parent of this form
     * @var FormInterface
     */
    private $parent;

    /**
     * The children of this form
     * @var FormInterface[] A map of FormInterface instances
     */
    private $children;

    /**
     * The errors of this form
     * @var FormError[] An array of FormError instances
     */
    private $errors = array();

    /**
     * Whether this form was submitted
     * @var Boolean
     */
    private $submitted = false;

    /**
     * The button that was used to submit the form
     * @var Button
     */
    private $clickedButton;

    /**
     * The form data in model format
     * @var mixed
     */
    private $modelData;

    /**
     * The form data in normalized format
     * @var mixed
     */
    private $normData;

    /**
     * The form data in view format
     * @var mixed
     */
    private $viewData;

    /**
     * The submitted values that don't belong to any children
     * @var array
     */
    private $extraData = array();

    /**
     * Whether the data in model, normalized and view format is
     * synchronized. Data may not be synchronized if transformation errors
     * occur.
     * @var Boolean
     */
    private $synchronized = true;

    /**
     * Whether the form's data has been initialized.
     *
     * When the data is initialized with its default value, that default value
     * is passed through the transformer chain in order to synchronize the
     * model, normalized and view format for the first time. This is done
     * lazily in order to save performance when {@link setData()} is called
     * manually, making the initialization with the configured default value
     * superfluous.
     *
     * @var Boolean
     */
    private $defaultDataSet = false;

    /**
     * Whether setData() is currently being called.
     * @var Boolean
     */
    private $lockSetData = false;

    /**
     * Creates a new form based on the given configuration.
     *
     * @param FormConfigInterface $config The form configuration.
     *
     * @throws LogicException if a data mapper is not provided for a compound form
     */
    public function __construct(FormConfigInterface $config)
    {
        // Compound forms always need a data mapper, otherwise calls to
        // `setData` and `add` will not lead to the correct population of
        // the child forms.
        if ($config->getCompound() && !$config->getDataMapper()) {
            throw new LogicException('Compound forms need a data mapper');
        }

        // If the form inherits the data from its parent, it is not necessary
        // to call setData() with the default data.
        if ($config->getInheritData()) {
            $this->defaultDataSet = true;
        }

        $this->config = $config;
        $this->children = new OrderedHashMap();
    }

    public function __clone()
    {
        $this->children = clone $this->children;

        foreach ($this->children as $key => $child) {
            $this->children[$key] = clone $child;
        }
    }

    /**
     * {@inheritdoc}
     */
    public function getConfig()
    {
        return $this->config;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return $this->config->getName();
    }

    /**
     * {@inheritdoc}
     */
    public function getPropertyPath()
    {
        if (null !== $this->config->getPropertyPath()) {
            return $this->config->getPropertyPath();
        }

        if (null === $this->getName() || '' === $this->getName()) {
            return null;
        }

        $parent = $this->parent;

        while ($parent && $parent->getConfig()->getInheritData()) {
            $parent = $parent->getParent();
        }

        if ($parent && null === $parent->getConfig()->getDataClass()) {
            return new PropertyPath('['.$this->getName().']');
        }

        return new PropertyPath($this->getName());
    }

    /**
     * {@inheritdoc}
     */
    public function isRequired()
    {
        if (null === $this->parent || $this->parent->isRequired()) {
            return $this->config->getRequired();
        }

        return false;
    }

    /**
     * {@inheritDoc}
     */
    public function isDisabled()
    {
        if (null === $this->parent || !$this->parent->isDisabled()) {
            return $this->config->getDisabled();
        }

        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function setParent(FormInterface $parent = null)
    {
        if ($this->submitted) {
            throw new AlreadySubmittedException('You cannot set the parent of a submitted form');
        }

        if (null !== $parent && '' === $this->config->getName()) {
            throw new LogicException('A form with an empty name cannot have a parent form.');
        }

        $this->parent = $parent;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function getParent()
    {
        return $this->parent;
    }

    /**
     * {@inheritdoc}
     */
    public function getRoot()
    {
        return $this->parent ? $this->parent->getRoot() : $this;
    }

    /**
     * {@inheritdoc}
     */
    public function isRoot()
    {
        return null === $this->parent;
    }

    /**
     * {@inheritdoc}
     */
    public function setData($modelData)
    {
        // If the form is submitted while disabled, it is set to submitted, but the data is not
        // changed. In such cases (i.e. when the form is not initialized yet) don't
        // abort this method.
        if ($this->submitted && $this->defaultDataSet) {
            throw new AlreadySubmittedException('You cannot change the data of a submitted form.');
        }

        // If the form inherits its parent's data, disallow data setting to
        // prevent merge conflicts
        if ($this->config->getInheritData()) {
            throw new RuntimeException('You cannot change the data of a form inheriting its parent data.');
        }

        // Don't allow modifications of the configured data if the data is locked
        if ($this->config->getDataLocked() && $modelData !== $this->config->getData()) {
            return $this;
        }

        if (is_object($modelData) && !$this->config->getByReference()) {
            $modelData = clone $modelData;
        }

        if ($this->lockSetData) {
            throw new RuntimeException('A cycle was detected. Listeners to the PRE_SET_DATA event must not call setData(). You should call setData() on the FormEvent object instead.');
        }

        $this->lockSetData = true;
        $dispatcher = $this->config->getEventDispatcher();

        // Hook to change content of the data
        if ($dispatcher->hasListeners(FormEvents::PRE_SET_DATA)) {
            $event = new FormEvent($this, $modelData);
            $dispatcher->dispatch(FormEvents::PRE_SET_DATA, $event);
            $modelData = $event->getData();
        }

        // Treat data as strings unless a value transformer exists
        if (!$this->config->getViewTransformers() && !$this->config->getModelTransformers() && is_scalar($modelData)) {
            $modelData = (string) $modelData;
        }

        // Synchronize representations - must not change the content!
        $normData = $this->modelToNorm($modelData);
        $viewData = $this->normToView($normData);

        // Validate if view data matches data class (unless empty)
        if (!FormUtil::isEmpty($viewData)) {
            $dataClass = $this->config->getDataClass();

            $actualType = is_object($viewData) ? 'an instance of class '.get_class($viewData) : ' a(n) '.gettype($viewData);

            if (null === $dataClass && is_object($viewData) && !$viewData instanceof \ArrayAccess) {
                $expectedType = 'scalar, array or an instance of \ArrayAccess';

                throw new LogicException(
                    'The form\'s view data is expected to be of type '.$expectedType.', ' .
                    'but is '.$actualType.'. You ' .
                    'can avoid this error by setting the "data_class" option to ' .
                    '"'.get_class($viewData).'" or by adding a view transformer ' .
                    'that transforms '.$actualType.' to '.$expectedType.'.'
                );
            }

            if (null !== $dataClass && !$viewData instanceof $dataClass) {
                throw new LogicException(
                    'The form\'s view data is expected to be an instance of class ' .
                    $dataClass.', but is '. $actualType.'. You can avoid this error ' .
                    'by setting the "data_class" option to null or by adding a view ' .
                    'transformer that transforms '.$actualType.' to an instance of ' .
                    $dataClass.'.'
                );
            }
        }

        $this->modelData = $modelData;
        $this->normData = $normData;
        $this->viewData = $viewData;
        $this->defaultDataSet = true;
        $this->lockSetData = false;

        // It is not necessary to invoke this method if the form doesn't have children,
        // even if the form is compound.
        if (count($this->children) > 0) {
            // Update child forms from the data
            $iterator = new InheritDataAwareIterator($this->children);
            $iterator = new \RecursiveIteratorIterator($iterator);
            $this->config->getDataMapper()->mapDataToForms($viewData, $iterator);
        }

        if ($dispatcher->hasListeners(FormEvents::POST_SET_DATA)) {
            $event = new FormEvent($this, $modelData);
            $dispatcher->dispatch(FormEvents::POST_SET_DATA, $event);
        }

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function getData()
    {
        if ($this->config->getInheritData()) {
            if (!$this->parent) {
                throw new RuntimeException('The form is configured to inherit its parent\'s data, but does not have a parent.');
            }

            return $this->parent->getData();
        }

        if (!$this->defaultDataSet) {
            $this->setData($this->config->getData());
        }

        return $this->modelData;
    }

    /**
     * {@inheritdoc}
     */
    public function getNormData()
    {
        if ($this->config->getInheritData()) {
            if (!$this->parent) {
                throw new RuntimeException('The form is configured to inherit its parent\'s data, but does not have a parent.');
            }

            return $this->parent->getNormData();
        }

        if (!$this->defaultDataSet) {
            $this->setData($this->config->getData());
        }

        return $this->normData;
    }

    /**
     * {@inheritdoc}
     */
    public function getViewData()
    {
        if ($this->config->getInheritData()) {
            if (!$this->parent) {
                throw new RuntimeException('The form is configured to inherit its parent\'s data, but does not have a parent.');
            }

            return $this->parent->getViewData();
        }

        if (!$this->defaultDataSet) {
            $this->setData($this->config->getData());
        }

        return $this->viewData;
    }

    /**
     * {@inheritdoc}
     */
    public function getExtraData()
    {
        return $this->extraData;
    }

    /**
     * {@inheritdoc}
     */
    public function initialize()
    {
        if (null !== $this->parent) {
            throw new RuntimeException('Only root forms should be initialized.');
        }

        // Guarantee that the *_SET_DATA events have been triggered once the
        // form is initialized. This makes sure that dynamically added or
        // removed fields are already visible after initialization.
        if (!$this->defaultDataSet) {
            $this->setData($this->config->getData());
        }

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function handleRequest($request = null)
    {
        $this->config->getRequestHandler()->handleRequest($this, $request);

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function submit($submittedData, $clearMissing = true)
    {
        if ($this->submitted) {
            throw new AlreadySubmittedException('A form can only be submitted once');
        }

        // Initialize errors in the very beginning so that we don't lose any
        // errors added during listeners
        $this->errors = array();

        // Obviously, a disabled form should not change its data upon submission.
        if ($this->isDisabled()) {
            $this->submitted = true;

            return $this;
        }

        // The data must be initialized if it was not initialized yet.
        // This is necessary to guarantee that the *_SET_DATA listeners
        // are always invoked before submit() takes place.
        if (!$this->defaultDataSet) {
            $this->setData($this->config->getData());
        }

        // Treat false as NULL to support binding false to checkboxes.
        // Don't convert NULL to a string here in order to determine later
        // whether an empty value has been submitted or whether no value has
        // been submitted at all. This is important for processing checkboxes
        // and radio buttons with empty values.
        if (false === $submittedData) {
            $submittedData = null;
        } elseif (is_scalar($submittedData)) {
            $submittedData = (string) $submittedData;
        }

        $dispatcher = $this->config->getEventDispatcher();

        $modelData = null;
        $normData = null;
        $viewData = null;

        try {
            // Hook to change content of the data submitted by the browser
            if ($dispatcher->hasListeners(FormEvents::PRE_SUBMIT)) {
                $event = new FormEvent($this, $submittedData);
                $dispatcher->dispatch(FormEvents::PRE_SUBMIT, $event);
                $submittedData = $event->getData();
            }

            // Check whether the form is compound.
            // This check is preferable over checking the number of children,
            // since forms without children may also be compound.
            // (think of empty collection forms)
            if ($this->config->getCompound()) {
                if (null === $submittedData) {
                    $submittedData = array();
                }

                if (!is_array($submittedData)) {
                    throw new TransformationFailedException('Compound forms expect an array or NULL on submission.');
                }

                foreach ($this->children as $name => $child) {
                    if (array_key_exists($name, $submittedData) || $clearMissing) {
                        $child->submit(isset($submittedData[$name]) ? $submittedData[$name] : null, $clearMissing);
                        unset($submittedData[$name]);

                        if (null !== $this->clickedButton) {
                            continue;
                        }

                        if ($child instanceof ClickableInterface && $child->isClicked()) {
                            $this->clickedButton = $child;

                            continue;
                        }

                        if (method_exists($child, 'getClickedButton') && null !== $child->getClickedButton()) {
                            $this->clickedButton = $child->getClickedButton();
                        }
                    }
                }

                $this->extraData = $submittedData;
            }

            // Forms that inherit their parents' data also are not processed,
            // because then it would be too difficult to merge the changes in
            // the child and the parent form. Instead, the parent form also takes
            // changes in the grandchildren (i.e. children of the form that inherits
            // its parent's data) into account.
            // (see InheritDataAwareIterator below)
            if (!$this->config->getInheritData()) {
                // If the form is compound, the default data in view format
                // is reused. The data of the children is merged into this
                // default data using the data mapper.
                // If the form is not compound, the submitted data is also the data in view format.
                $viewData = $this->config->getCompound() ? $this->viewData : $submittedData;

                if (FormUtil::isEmpty($viewData)) {
                    $emptyData = $this->config->getEmptyData();

                    if ($emptyData instanceof \Closure) {
                        /* @var \Closure $emptyData */
                        $emptyData = $emptyData($this, $viewData);
                    }

                    $viewData = $emptyData;
                }

                // Merge form data from children into existing view data
                // It is not necessary to invoke this method if the form has no children,
                // even if it is compound.
                if (count($this->children) > 0) {
                    // Use InheritDataAwareIterator to process children of
                    // descendants that inherit this form's data.
                    // These descendants will not be submitted normally (see the check
                    // for $this->config->getInheritData() above)
                    $childrenIterator = new InheritDataAwareIterator($this->children);
                    $childrenIterator = new \RecursiveIteratorIterator($childrenIterator);
                    $this->config->getDataMapper()->mapFormsToData($childrenIterator, $viewData);
                }

                // Normalize data to unified representation
                $normData = $this->viewToNorm($viewData);

                // Hook to change content of the data in the normalized
                // representation
                if ($dispatcher->hasListeners(FormEvents::SUBMIT)) {
                    $event = new FormEvent($this, $normData);
                    $dispatcher->dispatch(FormEvents::SUBMIT, $event);
                    $normData = $event->getData();
                }

                // Synchronize representations - must not change the content!
                $modelData = $this->normToModel($normData);
                $viewData = $this->normToView($normData);
            }
        } catch (TransformationFailedException $e) {
            $this->synchronized = false;

            // If $viewData was not yet set, set it to $submittedData so that
            // the erroneous data is accessible on the form.
            // Forms that inherit data never set any data, because the getters
            // forward to the parent form's getters anyway.
            if (null === $viewData && !$this->config->getInheritData()) {
                $viewData = $submittedData;
            }
        }

        $this->submitted = true;
        $this->modelData = $modelData;
        $this->normData = $normData;
        $this->viewData = $viewData;

        if ($dispatcher->hasListeners(FormEvents::POST_SUBMIT)) {
            $event = new FormEvent($this, $viewData);
            $dispatcher->dispatch(FormEvents::POST_SUBMIT, $event);
        }

        return $this;
    }

    /**
     * Alias of {@link submit()}.
     *
     * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
     *             {@link submit()} instead.
     */
    public function bind($submittedData)
    {
        return $this->submit($submittedData);
    }

    /**
     * {@inheritdoc}
     */
    public function addError(FormError $error)
    {
        if ($this->parent && $this->config->getErrorBubbling()) {
            $this->parent->addError($error);
        } else {
            $this->errors[] = $error;
        }

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function isSubmitted()
    {
        return $this->submitted;
    }

    /**
     * Alias of {@link isSubmitted()}.
     *
     * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
     *             {@link isSubmitted()} instead.
     */
    public function isBound()
    {
        return $this->submitted;
    }

    /**
     * {@inheritdoc}
     */
    public function isSynchronized()
    {
        return $this->synchronized;
    }

    /**
     * {@inheritdoc}
     */
    public function isEmpty()
    {
        foreach ($this->children as $child) {
            if (!$child->isEmpty()) {
                return false;
            }
        }

        return FormUtil::isEmpty($this->modelData) ||
            // arrays, countables
            0 === count($this->modelData) ||
            // traversables that are not countable
            ($this->modelData instanceof \Traversable && 0 === iterator_count($this->modelData));
    }

    /**
     * {@inheritdoc}
     */
    public function isValid()
    {
        if (!$this->submitted) {
            return false;
        }

        if (count($this->errors) > 0) {
            return false;
        }

        if ($this->isDisabled()) {
            return true;
        }

        foreach ($this->children as $child) {
            if ($child->isSubmitted() && !$child->isValid()) {
                return false;
            }
        }

        return true;
    }

    /**
     * Returns the button that was used to submit the form.
     *
     * @return Button|null The clicked button or NULL if the form was not
     *                     submitted
     */
    public function getClickedButton()
    {
        if ($this->clickedButton) {
            return $this->clickedButton;
        }

        if ($this->parent && method_exists($this->parent, 'getClickedButton')) {
            return $this->parent->getClickedButton();
        }

        return null;
    }

    /**
     * {@inheritdoc}
     */
    public function getErrors()
    {
        return $this->errors;
    }

    /**
     * Returns a string representation of all form errors (including children errors).
     *
     * This method should only be used to help debug a form.
     *
     * @param integer $level The indentation level (used internally)
     *
     * @return string A string representation of all errors
     */
    public function getErrorsAsString($level = 0)
    {
        $errors = '';
        foreach ($this->errors as $error) {
            $errors .= str_repeat(' ', $level).'ERROR: '.$error->getMessage()."\n";
        }

        foreach ($this->children as $key => $child) {
            $errors .= str_repeat(' ', $level).$key.":\n";
            if ($child instanceof self && $err = $child->getErrorsAsString($level + 4)) {
                $errors .= $err;
            } else {
                $errors .= str_repeat(' ', $level + 4)."No errors\n";
            }
        }

        return $errors;
    }

    /**
     * {@inheritdoc}
     */
    public function all()
    {
        return iterator_to_array($this->children);
    }

    /**
     * {@inheritdoc}
     */
    public function add($child, $type = null, array $options = array())
    {
        if ($this->submitted) {
            throw new AlreadySubmittedException('You cannot add children to a submitted form');
        }

        if (!$this->config->getCompound()) {
            throw new LogicException('You cannot add children to a simple form. Maybe you should set the option "compound" to true?');
        }

        // Obtain the view data
        $viewData = null;

        // If setData() is currently being called, there is no need to call
        // mapDataToForms() here, as mapDataToForms() is called at the end
        // of setData() anyway. Not doing this check leads to an endless
        // recursion when initializing the form lazily and an event listener
        // (such as ResizeFormListener) adds fields depending on the data:
        //
        //  * setData() is called, the form is not initialized yet
        //  * add() is called by the listener (setData() is not complete, so
        //    the form is still not initialized)
        //  * getViewData() is called
        //  * setData() is called since the form is not initialized yet
        //  * ... endless recursion ...
        //
        // Also skip data mapping if setData() has not been called yet.
        // setData() will be called upon form initialization and data mapping
        // will take place by then.
        if (!$this->lockSetData && $this->defaultDataSet && !$this->config->getInheritData()) {
            $viewData = $this->getViewData();
        }

        if (!$child instanceof FormInterface) {
            if (!is_string($child) && !is_int($child)) {
                throw new UnexpectedTypeException($child, 'string, integer or Symfony\Component\Form\FormInterface');
            }

            if (null !== $type && !is_string($type) && !$type instanceof FormTypeInterface) {
                throw new UnexpectedTypeException($type, 'string or Symfony\Component\Form\FormTypeInterface');
            }

            // Never initialize child forms automatically
            $options['auto_initialize'] = false;

            if (null === $type) {
                $child = $this->config->getFormFactory()->createForProperty($this->config->getDataClass(), $child, null, $options);
            } else {
                $child = $this->config->getFormFactory()->createNamed($child, $type, null, $options);
            }
        } elseif ($child->getConfig()->getAutoInitialize()) {
            throw new RuntimeException(sprintf(
                'Automatic initialization is only supported on root forms. You '.
                'should set the "auto_initialize" option to false on the field "%s".',
                $child->getName()
            ));
        }

        $this->children[$child->getName()] = $child;

        $child->setParent($this);

        if (!$this->lockSetData && $this->defaultDataSet && !$this->config->getInheritData()) {
            $iterator = new InheritDataAwareIterator(new \ArrayIterator(array($child)));
            $iterator = new \RecursiveIteratorIterator($iterator);
            $this->config->getDataMapper()->mapDataToForms($viewData, $iterator);
        }

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function remove($name)
    {
        if ($this->submitted) {
            throw new AlreadySubmittedException('You cannot remove children from a submitted form');
        }

        if (isset($this->children[$name])) {
            $this->children[$name]->setParent(null);

            unset($this->children[$name]);
        }

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function has($name)
    {
        return isset($this->children[$name]);
    }

    /**
     * {@inheritdoc}
     */
    public function get($name)
    {
        if (isset($this->children[$name])) {
            return $this->children[$name];
        }

        throw new OutOfBoundsException(sprintf('Child "%s" does not exist.', $name));
    }

    /**
     * Returns whether a child with the given name exists (implements the \ArrayAccess interface).
     *
     * @param string $name The name of the child
     *
     * @return Boolean
     */
    public function offsetExists($name)
    {
        return $this->has($name);
    }

    /**
     * Returns the child with the given name (implements the \ArrayAccess interface).
     *
     * @param string $name The name of the child
     *
     * @return FormInterface The child form
     *
     * @throws \OutOfBoundsException If the named child does not exist.
     */
    public function offsetGet($name)
    {
        return $this->get($name);
    }

    /**
     * Adds a child to the form (implements the \ArrayAccess interface).
     *
     * @param string        $name  Ignored. The name of the child is used.
     * @param FormInterface $child The child to be added.
     *
     * @throws AlreadySubmittedException If the form has already been submitted.
     * @throws LogicException            When trying to add a child to a non-compound form.
     *
     * @see self::add()
     */
    public function offsetSet($name, $child)
    {
        $this->add($child);
    }

    /**
     * Removes the child with the given name from the form (implements the \ArrayAccess interface).
     *
     * @param string $name The name of the child to remove
     *
     * @throws AlreadySubmittedException If the form has already been submitted.
     */
    public function offsetUnset($name)
    {
        $this->remove($name);
    }

    /**
     * Returns the iterator for this group.
     *
     * @return \Traversable
     */
    public function getIterator()
    {
        return $this->children;
    }

    /**
     * Returns the number of form children (implements the \Countable interface).
     *
     * @return integer The number of embedded form children
     */
    public function count()
    {
        return count($this->children);
    }

    /**
     * {@inheritdoc}
     */
    public function createView(FormView $parent = null)
    {
        if (null === $parent && $this->parent) {
            $parent = $this->parent->createView();
        }

        $type = $this->config->getType();
        $options = $this->config->getOptions();

        // The methods createView(), buildView() and finishView() are called
        // explicitly here in order to be able to override either of them
        // in a custom resolved form type.
        $view = $type->createView($this, $parent);

        $type->buildView($view, $this, $options);

        foreach ($this->children as $name => $child) {
            $view->children[$name] = $child->createView($view);
        }

        $type->finishView($view, $this, $options);

        return $view;
    }

    /**
     * Normalizes the value if a normalization transformer is set.
     *
     * @param mixed $value The value to transform
     *
     * @return mixed
     */
    private function modelToNorm($value)
    {
        foreach ($this->config->getModelTransformers() as $transformer) {
            $value = $transformer->transform($value);
        }

        return $value;
    }

    /**
     * Reverse transforms a value if a normalization transformer is set.
     *
     * @param string $value The value to reverse transform
     *
     * @return mixed
     */
    private function normToModel($value)
    {
        $transformers = $this->config->getModelTransformers();

        for ($i = count($transformers) - 1; $i >= 0; --$i) {
            $value = $transformers[$i]->reverseTransform($value);
        }

        return $value;
    }

    /**
     * Transforms the value if a value transformer is set.
     *
     * @param mixed $value The value to transform
     *
     * @return mixed
     */
    private function normToView($value)
    {
        // Scalar values should  be converted to strings to
        // facilitate differentiation between empty ("") and zero (0).
        // Only do this for simple forms, as the resulting value in
        // compound forms is passed to the data mapper and thus should
        // not be converted to a string before.
        if (!$this->config->getViewTransformers() && !$this->config->getCompound()) {
            return null === $value || is_scalar($value) ? (string) $value : $value;
        }

        foreach ($this->config->getViewTransformers() as $transformer) {
            $value = $transformer->transform($value);
        }

        return $value;
    }

    /**
     * Reverse transforms a value if a value transformer is set.
     *
     * @param string $value The value to reverse transform
     *
     * @return mixed
     */
    private function viewToNorm($value)
    {
        $transformers = $this->config->getViewTransformers();

        if (!$transformers) {
            return '' === $value ? null : $value;
        }

        for ($i = count($transformers) - 1; $i >= 0; --$i) {
            $value = $transformers[$i]->reverseTransform($value);
        }

        return $value;
    }
}
PK|�Z�di���;Symfony/Component/Form/Exception/BadMethodCallException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Exception;

/**
 * Base BadMethodCallException for the Form component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface
{
}
PK|�Z�W�

:Symfony/Component/Form/Exception/AlreadyBoundException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Exception;

/**
 * Alias of {@link AlreadySubmittedException}.
 *
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
 *             {@link AlreadySubmittedException} instead.
 */
class AlreadyBoundException extends LogicException
{
}
PK|�Z(ddBSymfony/Component/Form/Exception/InvalidConfigurationException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Exception;

class InvalidConfigurationException extends InvalidArgumentException
{
}
PK|�Z�_c==<Symfony/Component/Form/Exception/UnexpectedTypeException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Exception;

class UnexpectedTypeException extends InvalidArgumentException
{
    public function __construct($value, $expectedType)
    {
        parent::__construct(sprintf('Expected argument of type "%s", "%s" given', $expectedType, is_object($value) ? get_class($value) : gettype($value)));
    }
}
PK|�Z�S�D��BSymfony/Component/Form/Exception/TransformationFailedException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Exception;

/**
 * Indicates a value transformation error.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class TransformationFailedException extends RuntimeException
{
}
PK|�Z��9Symfony/Component/Form/Exception/OutOfBoundsException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Exception;

/**
 * Base OutOfBoundsException for Form component.
 *
 * @author Alexander Kotynia <aleksander.kot@gmail.com>
 */
class OutOfBoundsException extends \OutOfBoundsException implements ExceptionInterface
{
}
PK}�Z�y�u��7Symfony/Component/Form/Exception/ExceptionInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Exception;

/**
 * Base ExceptionInterface for the Form component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface ExceptionInterface
{
}
PK}�ZN����5Symfony/Component/Form/Exception/RuntimeException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Exception;

/**
 * Base RuntimeException for the Form component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
PK}�ZK�9���>Symfony/Component/Form/Exception/AlreadySubmittedException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Exception;

/**
 * Thrown when an operation is called that is not acceptable after submitting
 * a form.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class AlreadySubmittedException extends AlreadyBoundException
{
}
PK}�Z1�;TT:Symfony/Component/Form/Exception/ErrorMappingException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Exception;

class ErrorMappingException extends RuntimeException
{
}
PK}�Z��+RR8Symfony/Component/Form/Exception/StringCastException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Exception;

class StringCastException extends RuntimeException
{
}
PK}�Z��X��3Symfony/Component/Form/Exception/LogicException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Exception;

/**
 * Base LogicException for Form component.
 *
 * @author Alexander Kotynia <aleksander.kot@gmail.com>
 */
class LogicException extends \LogicException implements ExceptionInterface
{
}
PK}�Z�gBz��=Symfony/Component/Form/Exception/InvalidArgumentException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Exception;

/**
 * Base InvalidArgumentException for the Form component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
PK}�Z�1��88'Symfony/Component/Form/AbstractType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

use Symfony\Component\OptionsResolver\OptionsResolverInterface;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
abstract class AbstractType implements FormTypeInterface
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
    }

    /**
     * {@inheritdoc}
     */
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
    }

    /**
     * {@inheritdoc}
     */
    public function finishView(FormView $view, FormInterface $form, array $options)
    {
    }

    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
    }

    /**
     * {@inheritdoc}
     */
    public function getParent()
    {
        return 'form';
    }
}
PK}�Z�I	�66.Symfony/Component/Form/Util/OrderedHashMap.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Util;

/**
 * A hash map which keeps track of deletions and additions.
 *
 * Like in associative arrays, elements can be mapped to integer or string keys.
 * Unlike associative arrays, the map keeps track of the order in which keys
 * were added and removed. This order is reflected during iteration.
 *
 * The map supports concurrent modification during iteration. That means that
 * you can insert and remove elements from within a foreach loop and the
 * iterator will reflect those changes accordingly.
 *
 * While elements that are added during the loop are recognized by the iterator,
 * changed elements are not. Otherwise the loop could be infinite if each loop
 * changes the current element:
 *
 *     $map = new OrderedHashMap();
 *     $map[1] = 1;
 *     $map[2] = 2;
 *     $map[3] = 3;
 *
 *     foreach ($map as $index => $value) {
 *         echo "$index: $value\n"
 *         if (1 === $index) {
 *             $map[1] = 4;
 *             $map[] = 5;
 *         }
 *     }
 *
 *     print_r(iterator_to_array($map));
 *
 *     // => 1: 1
 *     //    2: 2
 *     //    3: 3
 *     //    4: 5
 *     //    Array
 *     //    (
 *     //        [1] => 4
 *     //        [2] => 2
 *     //        [3] => 3
 *     //        [4] => 5
 *     //    )
 *
 * The map also supports multiple parallel iterators. That means that you can
 * nest foreach loops without affecting each other's iteration:
 *
 *     foreach ($map as $index => $value) {
 *         foreach ($map as $index2 => $value2) {
 *             // ...
 *         }
 *     }
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @since 2.2.6
 */
class OrderedHashMap implements \ArrayAccess, \IteratorAggregate, \Countable
{
    /**
     * The elements of the map, indexed by their keys.
     *
     * @var array
     */
    private $elements = array();

    /**
     * The keys of the map in the order in which they were inserted or changed.
     *
     * @var array
     */
    private $orderedKeys = array();

    /**
     * References to the cursors of all open iterators.
     *
     * @var array
     */
    private $managedCursors = array();

    /**
     * Creates a new map.
     *
     * @param array $elements The elements to insert initially.
     *
     * @since 2.2.6
     */
    public function __construct(array $elements = array())
    {
        $this->elements = $elements;
        $this->orderedKeys = array_keys($elements);
    }

    /**
     * {@inheritdoc}
     *
     * @since 2.2.6
     */
    public function offsetExists($key)
    {
        return isset($this->elements[$key]);
    }

    /**
     * {@inheritdoc}
     *
     * @since 2.2.6
     */
    public function offsetGet($key)
    {
        if (!isset($this->elements[$key])) {
            throw new \OutOfBoundsException('The offset "' . $key . '" does not exist.');
        }

        return $this->elements[$key];
    }

    /**
     * {@inheritdoc}
     *
     * @since 2.2.6
     */
    public function offsetSet($key, $value)
    {
        if (null === $key || !isset($this->elements[$key])) {
            if (null === $key) {
                $key = array() === $this->orderedKeys
                    // If the array is empty, use 0 as key
                    ? 0
                    // Imitate PHP's behavior of generating a key that equals
                    // the highest existing integer key + 1
                    : max($this->orderedKeys) + 1;
            }

            $this->orderedKeys[] = $key;
        }

        $this->elements[$key] = $value;
    }

    /**
     * {@inheritdoc}
     *
     * @since 2.2.6
     */
    public function offsetUnset($key)
    {
        if (false !== ($position = array_search($key, $this->orderedKeys))) {
            array_splice($this->orderedKeys, $position, 1);
            unset($this->elements[$key]);

            foreach ($this->managedCursors as $i => $cursor) {
                if ($cursor >= $position) {
                    --$this->managedCursors[$i];
                }
            }
        }
    }

    /**
     * {@inheritdoc}
     *
     * @since 2.2.6
     */
    public function getIterator()
    {
        return new OrderedHashMapIterator($this->elements, $this->orderedKeys, $this->managedCursors);
    }

    /**
     * {@inheritdoc}
     *
     * @since 2.2.6
     */
    public function count()
    {
        return count($this->elements);
    }
}
PK}�Z�h��''6Symfony/Component/Form/Util/OrderedHashMapIterator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Util;

/**
 * Iterator for {@link OrderedHashMap} objects.
 *
 * This class is internal and should not be used.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @since 2.2.6
 */
class OrderedHashMapIterator implements \Iterator
{
    /**
     * @var array
     */
    private $elements;

    /**
     * @var array
     */
    private $orderedKeys;

    /**
     * @var integer
     */
    private $cursor;

    /**
     * @var integer
     */
    private $cursorId;

    /**
     * @var array
     */
    private $managedCursors;

    /**
     * @var string|integer|null
     */
    private $key;

    /**
     * @var mixed
     */
    private $current;

    /**
     * Creates a new iterator.
     *
     * @param array $elements       The elements of the map, indexed by their
     *                              keys.
     * @param array $orderedKeys    The keys of the map in the order in which
     *                              they should be iterated.
     * @param array $managedCursors An array from which to reference the
     *                              iterator's cursor as long as it is alive.
     *                              This array is managed by the corresponding
     *                              {@link OrderedHashMap} instance to support
     *                              recognizing the deletion of elements.
     *
     * @since 2.2.6
     */
    public function __construct(array &$elements, array &$orderedKeys, array &$managedCursors)
    {
        $this->elements = &$elements;
        $this->orderedKeys = &$orderedKeys;
        $this->managedCursors = &$managedCursors;
        $this->cursorId = count($managedCursors);

        $this->managedCursors[$this->cursorId] = &$this->cursor;
    }

    /**
     * Removes the iterator's cursors from the managed cursors of the
     * corresponding {@link OrderedHashMap} instance.
     *
     * @since 2.2.6
     */
    public function __destruct()
    {
        // Use array_splice() instead of isset() to prevent holes in the
        // array indices, which would break the initialization of $cursorId
        array_splice($this->managedCursors, $this->cursorId, 1);
    }

    /**
     *{@inheritdoc}
     *
     * @since 2.2.6
     */
    public function current()
    {
        return $this->current;
    }

    /**
     * {@inheritdoc}
     *
     * @since 2.2.6
     */
    public function next()
    {
        ++$this->cursor;

        if (isset($this->orderedKeys[$this->cursor])) {
            $this->key = $this->orderedKeys[$this->cursor];
            $this->current = $this->elements[$this->key];
        } else {
            $this->key = null;
            $this->current = null;
        }
    }

    /**
     *{@inheritdoc}
     *
     * @since 2.2.6
     */
    public function key()
    {
        return $this->key;
    }

    /**
     *{@inheritdoc}
     *
     * @since 2.2.6
     */
    public function valid()
    {
        return null !== $this->key;
    }

    /**
     *{@inheritdoc}
     *
     * @since 2.2.6
     */
    public function rewind()
    {
        $this->cursor = 0;

        if (isset($this->orderedKeys[0])) {
            $this->key = $this->orderedKeys[0];
            $this->current = $this->elements[$this->key];
        } else {
            $this->key = null;
            $this->current = null;
        }
    }
}
PK}�Z��F228Symfony/Component/Form/Util/VirtualFormAwareIterator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Util;

/**
 * Iterator that traverses an array of forms.
 *
 * You can wrap the iterator into a {@link \RecursiveIterator} in order to
 * enter any child form that inherits its parent's data and iterate the children
 * of that form as well.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
 *             {@link InheritDataAwareIterator} instead.
 */
class VirtualFormAwareIterator extends \IteratorIterator implements \RecursiveIterator
{
    /**
     * {@inheritdoc}
     */
    public function getChildren()
    {
        return new static($this->current());
    }

    /**
     *{@inheritdoc}
     */
    public function hasChildren()
    {
        return (bool) $this->current()->getConfig()->getInheritData();
    }
}
PK}�Zy���$$(Symfony/Component/Form/Util/FormUtil.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Util;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class FormUtil
{
    /**
     * This class should not be instantiated
     */
    private function __construct() {}

    /**
     * Returns whether the given data is empty.
     *
     * This logic is reused multiple times throughout the processing of
     * a form and needs to be consistent. PHP's keyword `empty` cannot
     * be used as it also considers 0 and "0" to be empty.
     *
     * @param  mixed $data
     *
     * @return Boolean
     */
    public static function isEmpty($data)
    {
        // Should not do a check for array() === $data!!!
        // This method is used in occurrences where arrays are
        // not considered to be empty, ever.
        return null === $data || '' === $data;
    }
}
PK}�Z<����8Symfony/Component/Form/Util/InheritDataAwareIterator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Util;

/**
 * Iterator that traverses an array of forms.
 *
 * Contrary to \ArrayIterator, this iterator recognizes changes in the original
 * array during iteration.
 *
 * You can wrap the iterator into a {@link \RecursiveIterator} in order to
 * enter any child form that inherits its parent's data and iterate the children
 * of that form as well.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class InheritDataAwareIterator extends VirtualFormAwareIterator
{
}
PK}�Z�QT�pp.Symfony/Component/Form/SubmitButtonBuilder.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

/**
 * A builder for {@link SubmitButton} instances.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class SubmitButtonBuilder extends ButtonBuilder
{
    /**
     * Creates the button.
     *
     * @return SubmitButton The button
     */
    public function getForm()
    {
        return new SubmitButton($this->getFormConfig());
    }
}
PK}�Z�z5���2Symfony/Component/Form/ResolvedFormTypeFactory.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ResolvedFormTypeFactory implements ResolvedFormTypeFactoryInterface
{
    /**
     * {@inheritdoc}
     */
    public function createResolvedType(FormTypeInterface $type, array $typeExtensions, ResolvedFormTypeInterface $parent = null)
    {
        return new ResolvedFormType($type, $typeExtensions, $parent);
    }
}
PK}�ZSf��
	
	-Symfony/Component/Form/PreloadedExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

use Symfony\Component\Form\Exception\InvalidArgumentException;

/**
 * A form extension with preloaded types, type exceptions and type guessers.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class PreloadedExtension implements FormExtensionInterface
{
    /**
     * @var array
     */
    private $types = array();

    /**
     * @var array
     */
    private $typeExtensions = array();

    /**
     * @var FormTypeGuesserInterface
     */
    private $typeGuesser;

    /**
     * Creates a new preloaded extension.
     *
     * @param FormTypeInterface[]                 $types         The types that the extension should support.
     * @param array[FormTypeExtensionInterface[]] typeExtensions The type extensions that the extension should support.
     * @param FormTypeGuesserInterface|null       $typeGuesser   The guesser that the extension should support.
     */
    public function __construct(array $types, array $typeExtensions, FormTypeGuesserInterface $typeGuesser = null)
    {
        $this->types = $types;
        $this->typeExtensions = $typeExtensions;
        $this->typeGuesser = $typeGuesser;
    }

    /**
     * {@inheritdoc}
     */
    public function getType($name)
    {
        if (!isset($this->types[$name])) {
            throw new InvalidArgumentException(sprintf('The type "%s" can not be loaded by this extension', $name));
        }

        return $this->types[$name];
    }

    /**
     * {@inheritdoc}
     */
    public function hasType($name)
    {
        return isset($this->types[$name]);
    }

    /**
     * {@inheritdoc}
     */
    public function getTypeExtensions($name)
    {
        return isset($this->typeExtensions[$name])
            ? $this->typeExtensions[$name]
            : array();
    }

    /**
     * {@inheritdoc}
     */
    public function hasTypeExtensions($name)
    {
        return !empty($this->typeExtensions[$name]);
    }

    /**
     * {@inheritdoc}
     */
    public function getTypeGuesser()
    {
        return $this->typeGuesser;
    }
}
PK}�Z>��*ii&Symfony/Component/Form/FormFactory.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

use Symfony\Component\Form\Exception\UnexpectedTypeException;

class FormFactory implements FormFactoryInterface
{
    /**
     * @var FormRegistryInterface
     */
    private $registry;

    /**
     * @var ResolvedFormTypeFactoryInterface
     */
    private $resolvedTypeFactory;

    public function __construct(FormRegistryInterface $registry, ResolvedFormTypeFactoryInterface $resolvedTypeFactory)
    {
        $this->registry = $registry;
        $this->resolvedTypeFactory = $resolvedTypeFactory;
    }

    /**
     * {@inheritdoc}
     */
    public function create($type = 'form', $data = null, array $options = array())
    {
        return $this->createBuilder($type, $data, $options)->getForm();
    }

    /**
     * {@inheritdoc}
     */
    public function createNamed($name, $type = 'form', $data = null, array $options = array())
    {
        return $this->createNamedBuilder($name, $type, $data, $options)->getForm();
    }

    /**
     * {@inheritdoc}
     */
    public function createForProperty($class, $property, $data = null, array $options = array())
    {
        return $this->createBuilderForProperty($class, $property, $data, $options)->getForm();
    }

    /**
     * {@inheritdoc}
     */
    public function createBuilder($type = 'form', $data = null, array $options = array())
    {
        $name = $type instanceof FormTypeInterface || $type instanceof ResolvedFormTypeInterface
            ? $type->getName()
            : $type;

        return $this->createNamedBuilder($name, $type, $data, $options);
    }

    /**
     * {@inheritdoc}
     */
    public function createNamedBuilder($name, $type = 'form', $data = null, array $options = array())
    {
        if (null !== $data && !array_key_exists('data', $options)) {
            $options['data'] = $data;
        }

        if ($type instanceof FormTypeInterface) {
            $type = $this->resolveType($type);
        } elseif (is_string($type)) {
            $type = $this->registry->getType($type);
        } elseif (!$type instanceof ResolvedFormTypeInterface) {
            throw new UnexpectedTypeException($type, 'string, Symfony\Component\Form\ResolvedFormTypeInterface or Symfony\Component\Form\FormTypeInterface');
        }

        $builder = $type->createBuilder($this, $name, $options);

        // Explicitly call buildForm() in order to be able to override either
        // createBuilder() or buildForm() in the resolved form type
        $type->buildForm($builder, $builder->getOptions());

        return $builder;
    }

    /**
     * {@inheritdoc}
     */
    public function createBuilderForProperty($class, $property, $data = null, array $options = array())
    {
        if (null === $guesser = $this->registry->getTypeGuesser()) {
            return $this->createNamedBuilder($property, 'text', $data, $options);
        }

        $typeGuess = $guesser->guessType($class, $property);
        $maxLengthGuess = $guesser->guessMaxLength($class, $property);
        $requiredGuess = $guesser->guessRequired($class, $property);
        $patternGuess = $guesser->guessPattern($class, $property);

        $type = $typeGuess ? $typeGuess->getType() : 'text';

        $maxLength = $maxLengthGuess ? $maxLengthGuess->getValue() : null;
        $pattern   = $patternGuess ? $patternGuess->getValue() : null;

        if (null !== $pattern) {
            $options = array_merge(array('pattern' => $pattern), $options);
        }

        if (null !== $maxLength) {
            $options = array_merge(array('max_length' => $maxLength), $options);
        }

        if ($requiredGuess) {
            $options = array_merge(array('required' => $requiredGuess->getValue()), $options);
        }

        // user options may override guessed options
        if ($typeGuess) {
            $options = array_merge($typeGuess->getOptions(), $options);
        }

        return $this->createNamedBuilder($property, $type, $data, $options);
    }

    /**
     * Wraps a type into a ResolvedFormTypeInterface implementation and connects
     * it with its parent type.
     *
     * @param FormTypeInterface $type The type to resolve.
     *
     * @return ResolvedFormTypeInterface The resolved type.
     */
    private function resolveType(FormTypeInterface $type)
    {
        $parentType = $type->getParent();

        if ($parentType instanceof FormTypeInterface) {
            $parentType = $this->resolveType($parentType);
        } elseif (null !== $parentType) {
            $parentType = $this->registry->getType($parentType);
        }

        return $this->resolvedTypeFactory->createResolvedType(
            $type,
            // Type extensions are not supported for unregistered type instances,
            // i.e. type instances that are passed to the FormFactory directly,
            // nor for their parents, if getParent() also returns a type instance.
            array(),
            $parentType
        );
    }
}
PK}�Z�\�g��2Symfony/Component/Form/RequestHandlerInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

/**
 * Submits forms if they were submitted.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface RequestHandlerInterface
{
    /**
     * Submits a form if it was submitted.
     *
     * @param FormInterface $form    The form to submit.
     * @param mixed         $request The current request.
     */
    public function handleRequest(FormInterface $form, $request = null);
}
PK}�Z+q�DAA7Symfony/Component/Form/Test/FormPerformanceTestCase.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Test;

/**
 * Base class for performance tests.
 *
 * Copied from Doctrine 2's OrmPerformanceTestCase.
 *
 * @author robo
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
abstract class FormPerformanceTestCase extends FormIntegrationTestCase
{
    /**
     * @var    integer
     */
    protected $maxRunningTime = 0;

    /**
     */
    protected function runTest()
    {
        $s = microtime(true);
        parent::runTest();
        $time = microtime(true) - $s;

        if ($this->maxRunningTime != 0 && $time > $this->maxRunningTime) {
            $this->fail(
                sprintf(
                    'expected running time: <= %s but was: %s',

                    $this->maxRunningTime,
                    $time
                )
            );
        }
    }

    /**
     * @param  integer $maxRunningTime
     * @throws \InvalidArgumentException
     */
    public function setMaxRunningTime($maxRunningTime)
    {
        if (is_integer($maxRunningTime) && $maxRunningTime >= 0) {
            $this->maxRunningTime = $maxRunningTime;
        } else {
            throw new \InvalidArgumentException();
        }
    }

    /**
     * @return integer
     * @since  Method available since Release 2.3.0
     */
    public function getMaxRunningTime()
    {
        return $this->maxRunningTime;
    }
}
PK}�Zs�,Symfony/Component/Form/Test/TypeTestCase.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Test;

use Symfony\Component\Form\FormBuilder;
use Symfony\Component\EventDispatcher\EventDispatcher;

abstract class TypeTestCase extends FormIntegrationTestCase
{
    /**
     * @var FormBuilder
     */
    protected $builder;

    /**
     * @var EventDispatcher
     */
    protected $dispatcher;

    protected function setUp()
    {
        parent::setUp();

        $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
        $this->builder = new FormBuilder(null, null, $this->dispatcher, $this->factory);
    }

    public static function assertDateTimeEquals(\DateTime $expected, \DateTime $actual)
    {
        self::assertEquals($expected->format('c'), $actual->format('c'));
    }
}
PK}�Z�,�7//7Symfony/Component/Form/Test/DeprecationErrorHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Test;

use Symfony\Component\Form\FormEvent;

class DeprecationErrorHandler
{
    public static function handle($errorNumber, $message, $file, $line, $context)
    {
        if ($errorNumber & E_USER_DEPRECATED) {
            return true;
        }

        return \PHPUnit_Util_ErrorHandler::handleError($errorNumber, $message, $file, $line);
    }

    public static function handleBC($errorNumber, $message, $file, $line, $context)
    {
        if ($errorNumber & E_USER_DEPRECATED) {
            return true;
        }

        return false;
    }

    public static function preBind($listener, FormEvent $event)
    {
        set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle'));
        $listener->preBind($event);
        restore_error_handler();
    }
}
PK}�ZB�4I++7Symfony/Component/Form/Test/FormIntegrationTestCase.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Test;

use Symfony\Component\Form\Forms;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
abstract class FormIntegrationTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * @var \Symfony\Component\Form\FormFactoryInterface
     */
    protected $factory;

    protected function setUp()
    {
        $this->factory = Forms::createFormFactoryBuilder()
            ->addExtensions($this->getExtensions())
            ->getFormFactory();
    }

    protected function getExtensions()
    {
        return array();
    }
}
PK}�Z��m�yy4Symfony/Component/Form/Test/FormBuilderInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Test;

interface FormBuilderInterface extends \Iterator, \Symfony\Component\Form\FormBuilderInterface
{
}
PK}�Za(0kk-Symfony/Component/Form/Test/FormInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Test;

interface FormInterface extends \Iterator, \Symfony\Component\Form\FormInterface
{
}
PK}�Z�n����1Symfony/Component/Form/FormExtensionInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

/**
 * Interface for extensions which provide types, type extensions and a guesser.
 */
interface FormExtensionInterface
{
    /**
     * Returns a type by name.
     *
     * @param string $name The name of the type
     *
     * @return FormTypeInterface The type
     *
     * @throws Exception\InvalidArgumentException if the given type is not supported by this extension
     */
    public function getType($name);

    /**
     * Returns whether the given type is supported.
     *
     * @param string $name The name of the type
     *
     * @return Boolean Whether the type is supported by this extension
     */
    public function hasType($name);

    /**
     * Returns the extensions for the given type.
     *
     * @param string $name The name of the type
     *
     * @return FormTypeExtensionInterface[] An array of extensions as FormTypeExtensionInterface instances
     */
    public function getTypeExtensions($name);

    /**
     * Returns whether this extension provides type extensions for the given type.
     *
     * @param string $name The name of the type
     *
     * @return Boolean Whether the given type has extensions
     */
    public function hasTypeExtensions($name);

    /**
     * Returns the type guesser provided by this extension.
     *
     * @return FormTypeGuesserInterface|null The type guesser
     */
    public function getTypeGuesser();
}
PK}�Z|G����4Symfony/Component/Form/ResolvedFormTypeInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

/**
 * A wrapper for a form type and its extensions.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface ResolvedFormTypeInterface
{
    /**
     * Returns the name of the type.
     *
     * @return string The type name.
     */
    public function getName();

    /**
     * Returns the parent type.
     *
     * @return ResolvedFormTypeInterface|null The parent type or null.
     */
    public function getParent();

    /**
     * Returns the wrapped form type.
     *
     * @return FormTypeInterface The wrapped form type.
     */
    public function getInnerType();

    /**
     * Returns the extensions of the wrapped form type.
     *
     * @return FormTypeExtensionInterface[] An array of {@link FormTypeExtensionInterface} instances.
     */
    public function getTypeExtensions();

    /**
     * Creates a new form builder for this type.
     *
     * @param FormFactoryInterface $factory The form factory.
     * @param string               $name    The name for the builder.
     * @param array                $options The builder options.
     *
     * @return FormBuilderInterface The created form builder.
     */
    public function createBuilder(FormFactoryInterface $factory, $name, array $options = array());

    /**
     * Creates a new form view for a form of this type.
     *
     * @param FormInterface     $form   The form to create a view for.
     * @param FormView $parent The parent view or null.
     *
     * @return FormView The created form view.
     */
    public function createView(FormInterface $form, FormView $parent = null);

    /**
     * Configures a form builder for the type hierarchy.
     *
     * @param FormBuilderInterface $builder The builder to configure.
     * @param array                $options The options used for the configuration.
     */
    public function buildForm(FormBuilderInterface $builder, array $options);

    /**
     * Configures a form view for the type hierarchy.
     *
     * It is called before the children of the view are built.
     *
     * @param FormView      $view    The form view to configure.
     * @param FormInterface $form    The form corresponding to the view.
     * @param array         $options The options used for the configuration.
     */
    public function buildView(FormView $view, FormInterface $form, array $options);

    /**
     * Finishes a form view for the type hierarchy.
     *
     * It is called after the children of the view have been built.
     *
     * @param FormView      $view    The form view to configure.
     * @param FormInterface $form    The form corresponding to the view.
     * @param array         $options The options used for the configuration.
     */
    public function finishView(FormView $view, FormInterface $form, array $options);

    /**
     * Returns the configured options resolver used for this type.
     *
     * @return \Symfony\Component\OptionsResolver\OptionsResolverInterface The options resolver.
     */
    public function getOptionsResolver();
}
PK}�Z{d���!�!5Symfony/Component/Form/FormConfigBuilderInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface FormConfigBuilderInterface extends FormConfigInterface
{
    /**
     * Adds an event listener to an event on this form.
     *
     * @param string   $eventName The name of the event to listen to.
     * @param callable $listener  The listener to execute.
     * @param integer  $priority  The priority of the listener. Listeners
     *                            with a higher priority are called before
     *                            listeners with a lower priority.
     *
     * @return self The configuration object.
     */
    public function addEventListener($eventName, $listener, $priority = 0);

    /**
     * Adds an event subscriber for events on this form.
     *
     * @param EventSubscriberInterface $subscriber The subscriber to attach.
     *
     * @return self The configuration object.
     */
    public function addEventSubscriber(EventSubscriberInterface $subscriber);

    /**
     * Appends / prepends a transformer to the view transformer chain.
     *
     * The transform method of the transformer is used to convert data from the
     * normalized to the view format.
     * The reverseTransform method of the transformer is used to convert from the
     * view to the normalized format.
     *
     * @param DataTransformerInterface $viewTransformer
     * @param Boolean                  $forcePrepend if set to true, prepend instead of appending
     *
     * @return self The configuration object.
     */
    public function addViewTransformer(DataTransformerInterface $viewTransformer, $forcePrepend = false);

    /**
     * Clears the view transformers.
     *
     * @return self The configuration object.
     */
    public function resetViewTransformers();

    /**
     * Prepends / appends a transformer to the normalization transformer chain.
     *
     * The transform method of the transformer is used to convert data from the
     * model to the normalized format.
     * The reverseTransform method of the transformer is used to convert from the
     * normalized to the model format.
     *
     * @param DataTransformerInterface $modelTransformer
     * @param Boolean                  $forceAppend if set to true, append instead of prepending
     *
     * @return self The configuration object.
     */
    public function addModelTransformer(DataTransformerInterface $modelTransformer, $forceAppend = false);

    /**
     * Clears the normalization transformers.
     *
     * @return self The configuration object.
     */
    public function resetModelTransformers();

    /**
     * Sets the value for an attribute.
     *
     * @param string $name  The name of the attribute
     * @param string $value The value of the attribute
     *
     * @return self The configuration object.
     */
    public function setAttribute($name, $value);

    /**
     * Sets the attributes.
     *
     * @param array $attributes The attributes.
     *
     * @return self The configuration object.
     */
    public function setAttributes(array $attributes);

    /**
     * Sets the data mapper used by the form.
     *
     * @param DataMapperInterface $dataMapper
     *
     * @return self The configuration object.
     */
    public function setDataMapper(DataMapperInterface $dataMapper = null);

    /**
     * Set whether the form is disabled.
     *
     * @param Boolean $disabled Whether the form is disabled
     *
     * @return self The configuration object.
     */
    public function setDisabled($disabled);

    /**
     * Sets the data used for the client data when no value is submitted.
     *
     * @param mixed $emptyData The empty data.
     *
     * @return self The configuration object.
     */
    public function setEmptyData($emptyData);

    /**
     * Sets whether errors bubble up to the parent.
     *
     * @param Boolean $errorBubbling
     *
     * @return self The configuration object.
     */
    public function setErrorBubbling($errorBubbling);

    /**
     * Sets whether this field is required to be filled out when submitted.
     *
     * @param Boolean $required
     *
     * @return self The configuration object.
     */
    public function setRequired($required);

    /**
     * Sets the property path that the form should be mapped to.
     *
     * @param null|string|\Symfony\Component\PropertyAccess\PropertyPathInterface $propertyPath
     *             The property path or null if the path should be set
     *             automatically based on the form's name.
     *
     * @return self The configuration object.
     */
    public function setPropertyPath($propertyPath);

    /**
     * Sets whether the form should be mapped to an element of its
     * parent's data.
     *
     * @param Boolean $mapped Whether the form should be mapped.
     *
     * @return self The configuration object.
     */
    public function setMapped($mapped);

    /**
     * Sets whether the form's data should be modified by reference.
     *
     * @param Boolean $byReference Whether the data should be
     *                              modified by reference.
     *
     * @return self The configuration object.
     */
    public function setByReference($byReference);

    /**
     * Sets whether the form should read and write the data of its parent.
     *
     * @param Boolean $inheritData Whether the form should inherit its parent's data.
     *
     * @return self The configuration object.
     */
    public function setInheritData($inheritData);

    /**
     * Sets whether the form should be compound.
     *
     * @param Boolean $compound Whether the form should be compound.
     *
     * @return self The configuration object.
     *
     * @see FormConfigInterface::getCompound()
     */
    public function setCompound($compound);

    /**
     * Set the types.
     *
     * @param ResolvedFormTypeInterface $type The type of the form.
     *
     * @return self The configuration object.
     */
    public function setType(ResolvedFormTypeInterface $type);

    /**
     * Sets the initial data of the form.
     *
     * @param array $data The data of the form in application format.
     *
     * @return self The configuration object.
     */
    public function setData($data);

    /**
     * Locks the form's data to the data passed in the configuration.
     *
     * A form with locked data is restricted to the data passed in
     * this configuration. The data can only be modified then by
     * submitting the form.
     *
     * @param Boolean $locked Whether to lock the default data.
     *
     * @return self The configuration object.
     */
    public function setDataLocked($locked);

    /**
     * Sets the form factory used for creating new forms.
     *
     * @param FormFactoryInterface $formFactory The form factory.
     */
    public function setFormFactory(FormFactoryInterface $formFactory);

    /**
     * Sets the target URL of the form.
     *
     * @param string $action The target URL of the form.
     *
     * @return self The configuration object.
     */
    public function setAction($action);

    /**
     * Sets the HTTP method used by the form.
     *
     * @param string $method The HTTP method of the form.
     *
     * @return self The configuration object.
     */
    public function setMethod($method);

    /**
     * Sets the request handler used by the form.
     *
     * @param RequestHandlerInterface $requestHandler
     *
     * @return self The configuration object.
     */
    public function setRequestHandler(RequestHandlerInterface $requestHandler);

    /**
     * Sets whether the form should be initialized automatically.
     *
     * Should be set to true only for root forms.
     *
     * @param Boolean $initialize True to initialize the form automatically,
     *                            false to suppress automatic initialization.
     *                            In the second case, you need to call
     *                            {@link FormInterface::initialize()} manually.
     *
     * @return self The configuration object.
     */
    public function setAutoInitialize($initialize);

    /**
     * Builds and returns the form configuration.
     *
     * @return FormConfigInterface
     */
    public function getFormConfig();
}
PK}�ZɃT���6Symfony/Component/Form/FormFactoryBuilderInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

/**
 * A builder for FormFactoryInterface objects.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface FormFactoryBuilderInterface
{
    /**
     * Sets the factory for creating ResolvedFormTypeInterface instances.
     *
     * @param ResolvedFormTypeFactoryInterface $resolvedTypeFactory
     *
     * @return FormFactoryBuilderInterface The builder.
     */
    public function setResolvedTypeFactory(ResolvedFormTypeFactoryInterface $resolvedTypeFactory);

    /**
     * Adds an extension to be loaded by the factory.
     *
     * @param FormExtensionInterface $extension The extension.
     *
     * @return FormFactoryBuilderInterface The builder.
     */
    public function addExtension(FormExtensionInterface $extension);

    /**
     * Adds a list of extensions to be loaded by the factory.
     *
     * @param FormExtensionInterface[] $extensions The extensions.
     *
     * @return FormFactoryBuilderInterface The builder.
     */
    public function addExtensions(array $extensions);

    /**
     * Adds a form type to the factory.
     *
     * @param FormTypeInterface $type The form type.
     *
     * @return FormFactoryBuilderInterface The builder.
     */
    public function addType(FormTypeInterface $type);

    /**
     * Adds a list of form types to the factory.
     *
     * @param FormTypeInterface[] $types The form types.
     *
     * @return FormFactoryBuilderInterface The builder.
     */
    public function addTypes(array $types);

    /**
     * Adds a form type extension to the factory.
     *
     * @param FormTypeExtensionInterface $typeExtension The form type extension.
     *
     * @return FormFactoryBuilderInterface The builder.
     */
    public function addTypeExtension(FormTypeExtensionInterface $typeExtension);

    /**
     * Adds a list of form type extensions to the factory.
     *
     * @param FormTypeExtensionInterface[] $typeExtensions The form type extensions.
     *
     * @return FormFactoryBuilderInterface The builder.
     */
    public function addTypeExtensions(array $typeExtensions);

    /**
     * Adds a type guesser to the factory.
     *
     * @param FormTypeGuesserInterface $typeGuesser The type guesser.
     *
     * @return FormFactoryBuilderInterface The builder.
     */
    public function addTypeGuesser(FormTypeGuesserInterface $typeGuesser);

    /**
     * Adds a list of type guessers to the factory.
     *
     * @param FormTypeGuesserInterface[] $typeGuessers The type guessers.
     *
     * @return FormFactoryBuilderInterface The builder.
     */
    public function addTypeGuessers(array $typeGuessers);

    /**
     * Builds and returns the factory.
     *
     * @return FormFactoryInterface The form factory.
     */
    public function getFormFactory();
}
PK}�Z�N̷;Symfony/Component/Form/ResolvedFormTypeFactoryInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

/**
 * Creates ResolvedFormTypeInterface instances.
 *
 * This interface allows you to use your custom ResolvedFormTypeInterface
 * implementation, within which you can customize the concrete FormBuilderInterface
 * implementations or FormView subclasses that are used by the framework.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface ResolvedFormTypeFactoryInterface
{
    /**
     * Resolves a form type.
     *
     * @param FormTypeInterface              $type
     * @param FormTypeExtensionInterface[]   $typeExtensions
     * @param ResolvedFormTypeInterface|null $parent
     *
     * @return ResolvedFormTypeInterface
     *
     * @throws Exception\UnexpectedTypeException  if the types parent {@link FormTypeInterface::getParent()} is not a string
     * @throws Exception\InvalidArgumentException if the types parent can not be retrieved from any extension
     */
    public function createResolvedType(FormTypeInterface $type, array $typeExtensions, ResolvedFormTypeInterface $parent = null);
}
PK}�Z2��-Symfony/Component/Form/FormFactoryBuilder.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

/**
 * The default implementation of FormFactoryBuilderInterface.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class FormFactoryBuilder implements FormFactoryBuilderInterface
{
    /**
     * @var ResolvedFormTypeFactoryInterface
     */
    private $resolvedTypeFactory;

    /**
     * @var array
     */
    private $extensions = array();

    /**
     * @var array
     */
    private $types = array();

    /**
     * @var array
     */
    private $typeExtensions = array();

    /**
     * @var array
     */
    private $typeGuessers = array();

    /**
     * {@inheritdoc}
     */
    public function setResolvedTypeFactory(ResolvedFormTypeFactoryInterface $resolvedTypeFactory)
    {
        $this->resolvedTypeFactory = $resolvedTypeFactory;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function addExtension(FormExtensionInterface $extension)
    {
        $this->extensions[] = $extension;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function addExtensions(array $extensions)
    {
        $this->extensions = array_merge($this->extensions, $extensions);

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function addType(FormTypeInterface $type)
    {
        $this->types[$type->getName()] = $type;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function addTypes(array $types)
    {
        foreach ($types as $type) {
            $this->types[$type->getName()] = $type;
        }

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function addTypeExtension(FormTypeExtensionInterface $typeExtension)
    {
        $this->typeExtensions[$typeExtension->getExtendedType()][] = $typeExtension;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function addTypeExtensions(array $typeExtensions)
    {
        foreach ($typeExtensions as $typeExtension) {
            $this->typeExtensions[$typeExtension->getExtendedType()][] = $typeExtension;
        }

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function addTypeGuesser(FormTypeGuesserInterface $typeGuesser)
    {
        $this->typeGuessers[] = $typeGuesser;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function addTypeGuessers(array $typeGuessers)
    {
        $this->typeGuessers = array_merge($this->typeGuessers, $typeGuessers);

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function getFormFactory()
    {
        $extensions = $this->extensions;

        if (count($this->types) > 0 || count($this->typeExtensions) > 0 || count($this->typeGuessers) > 0) {
            if (count($this->typeGuessers) > 1) {
                $typeGuesser = new FormTypeGuesserChain($this->typeGuessers);
            } else {
                $typeGuesser = isset($this->typeGuessers[0]) ? $this->typeGuessers[0] : null;
            }

            $extensions[] = new PreloadedExtension($this->types, $this->typeExtensions, $typeGuesser);
        }

        $resolvedTypeFactory = $this->resolvedTypeFactory ?: new ResolvedFormTypeFactory();
        $registry = new FormRegistry($extensions, $resolvedTypeFactory);

        return new FormFactory($registry, $resolvedTypeFactory);
    }
}
PK}�Z���C��0Symfony/Component/Form/AbstractTypeExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

use Symfony\Component\OptionsResolver\OptionsResolverInterface;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
abstract class AbstractTypeExtension implements FormTypeExtensionInterface
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
    }

    /**
     * {@inheritdoc}
     */
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
    }

    /**
     * {@inheritdoc}
     */
    public function finishView(FormView $view, FormInterface $form, array $options)
    {
    }

    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
    }
}
PK}�Z�E���0Symfony/Component/Form/FormRendererInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

/**
 * Renders a form into HTML.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface FormRendererInterface
{
    /**
     * Returns the engine used by this renderer.
     *
     * @return FormRendererEngineInterface The renderer engine.
     */
    public function getEngine();

    /**
     * Sets the theme(s) to be used for rendering a view and its children.
     *
     * @param FormView $view   The view to assign the theme(s) to.
     * @param mixed             $themes The theme(s). The type of these themes
     *                                  is open to the implementation.
     */
    public function setTheme(FormView $view, $themes);

    /**
     * Renders a named block of the form theme.
     *
     * @param FormView $view      The view for which to render the block.
     * @param string   $blockName The name of the block.
     * @param array    $variables The variables to pass to the template.
     *
     * @return string The HTML markup
     */
    public function renderBlock(FormView $view, $blockName, array $variables = array());

    /**
     * Searches and renders a block for a given name suffix.
     *
     * The block is searched by combining the block names stored in the
     * form view with the given suffix. If a block name is found, that
     * block is rendered.
     *
     * If this method is called recursively, the block search is continued
     * where a block was found before.
     *
     * @param FormView $view            The view for which to render the block.
     * @param string   $blockNameSuffix The suffix of the block name.
     * @param array    $variables       The variables to pass to the template.
     *
     * @return string The HTML markup
     */
    public function searchAndRenderBlock(FormView $view, $blockNameSuffix, array $variables = array());

    /**
     * Renders a CSRF token.
     *
     * Use this helper for CSRF protection without the overhead of creating a
     * form.
     *
     * <code>
     * <input type="hidden" name="token" value="<?php $renderer->renderCsrfToken('rm_user_'.$user->getId()) ?>">
     * </code>
     *
     * Check the token in your action using the same token ID.
     *
     * <code>
     * $csrfProvider = $this->get('security.csrf.token_generator');
     * if (!$csrfProvider->isCsrfTokenValid('rm_user_'.$user->getId(), $token)) {
     *     throw new \RuntimeException('CSRF attack detected.');
     * }
     * </code>
     *
     * @param string $tokenId The ID of the CSRF token
     *
     * @return string A CSRF token
     */
    public function renderCsrfToken($tokenId);

    /**
     * Makes a technical name human readable.
     *
     * Sequences of underscores are replaced by single spaces. The first letter
     * of the resulting string is capitalized, while all other letters are
     * turned to lowercase.
     *
     * @param string $text The text to humanize.
     *
     * @return string The humanized text.
     */
    public function humanize($text);
}
PK}�Z�:		/Symfony/Component/Form/FormBuilderInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface FormBuilderInterface extends \Traversable, \Countable, FormConfigBuilderInterface
{
    /**
     * Adds a new field to this group. A field must have a unique name within
     * the group. Otherwise the existing field is overwritten.
     *
     * If you add a nested group, this group should also be represented in the
     * object hierarchy.
     *
     * @param string|integer|FormBuilderInterface $child
     * @param string|FormTypeInterface            $type
     * @param array                               $options
     *
     * @return FormBuilderInterface The builder object.
     */
    public function add($child, $type = null, array $options = array());

    /**
     * Creates a form builder.
     *
     * @param string                   $name    The name of the form or the name of the property
     * @param string|FormTypeInterface $type    The type of the form or null if name is a property
     * @param array                    $options The options
     *
     * @return FormBuilderInterface The created builder.
     */
    public function create($name, $type = null, array $options = array());

    /**
     * Returns a child by name.
     *
     * @param string $name The name of the child
     *
     * @return FormBuilderInterface The builder for the child
     *
     * @throws Exception\InvalidArgumentException if the given child does not exist
     */
    public function get($name);

    /**
     * Removes the field with the given name.
     *
     * @param string $name
     *
     * @return FormBuilderInterface The builder object.
     */
    public function remove($name);

    /**
     * Returns whether a field with the given name exists.
     *
     * @param string $name
     *
     * @return Boolean
     */
    public function has($name);

    /**
     * Returns the children.
     *
     * @return array
     */
    public function all();

    /**
     * Creates the form.
     *
     * @return Form The form
     */
    public function getForm();
}
PK}�Z��Z)��/Symfony/Component/Form/FormFactoryInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface FormFactoryInterface
{
    /**
     * Returns a form.
     *
     * @see createBuilder()
     *
     * @param string|FormTypeInterface $type    The type of the form
     * @param mixed                    $data    The initial data
     * @param array                    $options The options
     *
     * @return FormInterface The form named after the type
     *
     * @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException if any given option is not applicable to the given type
     */
    public function create($type = 'form', $data = null, array $options = array());

    /**
     * Returns a form.
     *
     * @see createNamedBuilder()
     *
     * @param string|integer           $name    The name of the form
     * @param string|FormTypeInterface $type    The type of the form
     * @param mixed                    $data    The initial data
     * @param array                    $options The options
     *
     * @return FormInterface The form
     *
     * @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException if any given option is not applicable to the given type
     */
    public function createNamed($name, $type = 'form', $data = null, array $options = array());

    /**
     * Returns a form for a property of a class.
     *
     * @see createBuilderForProperty()
     *
     * @param string $class    The fully qualified class name
     * @param string $property The name of the property to guess for
     * @param mixed  $data     The initial data
     * @param array  $options  The options for the builder
     *
     * @return FormInterface The form named after the property
     *
     * @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException if any given option is not applicable to the form type
     */
    public function createForProperty($class, $property, $data = null, array $options = array());

    /**
     * Returns a form builder.
     *
     * @param string|FormTypeInterface $type    The type of the form
     * @param mixed                    $data    The initial data
     * @param array                    $options The options
     *
     * @return FormBuilderInterface The form builder
     *
     * @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException if any given option is not applicable to the given type
     */
    public function createBuilder($type = 'form', $data = null, array $options = array());

    /**
     * Returns a form builder.
     *
     * @param string|integer           $name    The name of the form
     * @param string|FormTypeInterface $type    The type of the form
     * @param mixed                    $data    The initial data
     * @param array                    $options The options
     *
     * @return FormBuilderInterface The form builder
     *
     * @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException if any given option is not applicable to the given type
     */
    public function createNamedBuilder($name, $type = 'form', $data = null, array $options = array());

    /**
     * Returns a form builder for a property of a class.
     *
     * If any of the 'max_length', 'required' and type options can be guessed,
     * and are not provided in the options argument, the guessed value is used.
     *
     * @param string $class    The fully qualified class name
     * @param string $property The name of the property to guess for
     * @param mixed  $data     The initial data
     * @param array  $options  The options for the builder
     *
     * @return FormBuilderInterface The form builder named after the property
     *
     * @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException if any given option is not applicable to the form type
     */
    public function createBuilderForProperty($class, $property, $data = null, array $options = array());
}
PK}�Z�YB���.Symfony/Component/Form/ReversedTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

/**
 * Reverses a transformer
 *
 * When the transform() method is called, the reversed transformer's
 * reverseTransform() method is called and vice versa.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ReversedTransformer implements DataTransformerInterface
{
    /**
     * The reversed transformer
     * @var DataTransformerInterface
     */
    protected $reversedTransformer;

    /**
     * Reverses this transformer
     *
     * @param DataTransformerInterface $reversedTransformer
     */
    public function __construct(DataTransformerInterface $reversedTransformer)
    {
        $this->reversedTransformer = $reversedTransformer;
    }

    /**
     * {@inheritDoc}
     */
    public function transform($value)
    {
        return $this->reversedTransformer->reverseTransform($value);
    }

    /**
     * {@inheritDoc}
     */
    public function reverseTransform($value)
    {
        return $this->reversedTransformer->transform($value);
    }
}
PK}�Z�r�WW3Symfony/Component/Form/DataTransformerInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

use Symfony\Component\Form\Exception\TransformationFailedException;

/**
 * Transforms a value between different representations.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface DataTransformerInterface
{
    /**
     * Transforms a value from the original representation to a transformed representation.
     *
     * This method is called on two occasions inside a form field:
     *
     * 1. When the form field is initialized with the data attached from the datasource (object or array).
     * 2. When data from a request is submitted using {@link Form::submit()} to transform the new input data
     *    back into the renderable format. For example if you have a date field and submit '2009-10-10'
     *    you might accept this value because its easily parsed, but the transformer still writes back
     *    "2009/10/10" onto the form field (for further displaying or other purposes).
     *
     * This method must be able to deal with empty values. Usually this will
     * be NULL, but depending on your implementation other empty values are
     * possible as well (such as empty strings). The reasoning behind this is
     * that value transformers must be chainable. If the transform() method
     * of the first value transformer outputs NULL, the second value transformer
     * must be able to process that value.
     *
     * By convention, transform() should return an empty string if NULL is
     * passed.
     *
     * @param mixed $value The value in the original representation
     *
     * @return mixed The value in the transformed representation
     *
     * @throws TransformationFailedException When the transformation fails.
     */
    public function transform($value);

    /**
     * Transforms a value from the transformed representation to its original
     * representation.
     *
     * This method is called when {@link Form::submit()} is called to transform the requests tainted data
     * into an acceptable format for your data processing/model layer.
     *
     * This method must be able to deal with empty values. Usually this will
     * be an empty string, but depending on your implementation other empty
     * values are possible as well (such as empty strings). The reasoning behind
     * this is that value transformers must be chainable. If the
     * reverseTransform() method of the first value transformer outputs an
     * empty string, the second value transformer must be able to process that
     * value.
     *
     * By convention, reverseTransform() should return NULL if an empty string
     * is passed.
     *
     * @param mixed $value The value in the transformed representation
     *
     * @return mixed The value in the original representation
     *
     * @throws TransformationFailedException When the transformation fails.
     */
    public function reverseTransform($value);
}
PK}�ZW�b�[H[H(Symfony/Component/Form/ButtonBuilder.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\Exception\InvalidArgumentException;
use Symfony\Component\Form\Exception\BadMethodCallException;

/**
 * A builder for {@link Button} instances.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface
{
    /**
     * @var Boolean
     */
    protected $locked = false;

    /**
     * @var Boolean
     */
    private $disabled;

    /**
     * @var ResolvedFormTypeInterface
     */
    private $type;

    /**
     * @var string
     */
    private $name;

    /**
     * @var array
     */
    private $attributes = array();

    /**
     * @var array
     */
    private $options;

    /**
     * Creates a new button builder.
     *
     * @param string $name    The name of the button.
     * @param array  $options The button's options.
     *
     * @throws InvalidArgumentException If the name is empty.
     */
    public function __construct($name, array $options = array())
    {
        if (empty($name) && 0 != $name) {
            throw new InvalidArgumentException('Buttons cannot have empty names.');
        }

        $this->name = (string) $name;
        $this->options = $options;
    }

    /**
     * Unsupported method.
     *
     * This method should not be invoked.
     *
     * @param string|integer|FormBuilderInterface $child
     * @param string|FormTypeInterface            $type
     * @param array                               $options
     *
     * @throws BadMethodCallException
     */
    public function add($child, $type = null, array $options = array())
    {
        throw new BadMethodCallException('Buttons cannot have children.');
    }

    /**
     * Unsupported method.
     *
     * This method should not be invoked.
     *
     * @param string                   $name
     * @param string|FormTypeInterface $type
     * @param array                    $options
     *
     * @throws BadMethodCallException
     */
    public function create($name, $type = null, array $options = array())
    {
        throw new BadMethodCallException('Buttons cannot have children.');
    }

    /**
     * Unsupported method.
     *
     * This method should not be invoked.
     *
     * @param string $name
     *
     * @throws BadMethodCallException
     */
    public function get($name)
    {
        throw new BadMethodCallException('Buttons cannot have children.');
    }

    /**
     * Unsupported method.
     *
     * This method should not be invoked.
     *
     * @param string $name
     *
     * @throws BadMethodCallException
     */
    public function remove($name)
    {
        throw new BadMethodCallException('Buttons cannot have children.');
    }

    /**
     * Unsupported method.
     *
     * @param string $name
     *
     * @return Boolean Always returns false.
     */
    public function has($name)
    {
        return false;
    }

    /**
     * Returns the children.
     *
     * @return array Always returns an empty array.
     */
    public function all()
    {
        return array();
    }

    /**
     * Creates the button.
     *
     * @return Button The button
     */
    public function getForm()
    {
        return new Button($this->getFormConfig());
    }

    /**
     * Unsupported method.
     *
     * This method should not be invoked.
     *
     * @param string   $eventName
     * @param callable $listener
     * @param integer  $priority
     *
     * @throws BadMethodCallException
     */
    public function addEventListener($eventName, $listener, $priority = 0)
    {
        throw new BadMethodCallException('Buttons do not support event listeners.');
    }

    /**
     * Unsupported method.
     *
     * This method should not be invoked.
     *
     * @param EventSubscriberInterface $subscriber
     *
     * @throws BadMethodCallException
     */
    public function addEventSubscriber(EventSubscriberInterface $subscriber)
    {
        throw new BadMethodCallException('Buttons do not support event subscribers.');
    }

    /**
     * Unsupported method.
     *
     * This method should not be invoked.
     *
     * @param DataTransformerInterface $viewTransformer
     * @param Boolean                  $forcePrepend
     *
     * @throws BadMethodCallException
     */
    public function addViewTransformer(DataTransformerInterface $viewTransformer, $forcePrepend = false)
    {
        throw new BadMethodCallException('Buttons do not support data transformers.');
    }

    /**
     * Unsupported method.
     *
     * This method should not be invoked.
     *
     * @throws BadMethodCallException
     */
    public function resetViewTransformers()
    {
        throw new BadMethodCallException('Buttons do not support data transformers.');
    }

    /**
     * Unsupported method.
     *
     * This method should not be invoked.
     *
     * @param DataTransformerInterface $modelTransformer
     * @param Boolean                  $forceAppend
     *
     * @throws BadMethodCallException
     */
    public function addModelTransformer(DataTransformerInterface $modelTransformer, $forceAppend = false)
    {
        throw new BadMethodCallException('Buttons do not support data transformers.');
    }

    /**
     * Unsupported method.
     *
     * This method should not be invoked.
     *
     * @throws BadMethodCallException
     */
    public function resetModelTransformers()
    {
        throw new BadMethodCallException('Buttons do not support data transformers.');
    }

    /**
     * {@inheritdoc}
     */
    public function setAttribute($name, $value)
    {
        $this->attributes[$name] = $value;
    }

    /**
     * {@inheritdoc}
     */
    public function setAttributes(array $attributes)
    {
        $this->attributes = $attributes;
    }

    /**
     * Unsupported method.
     *
     * This method should not be invoked.
     *
     * @param DataMapperInterface $dataMapper
     *
     * @throws BadMethodCallException
     */
    public function setDataMapper(DataMapperInterface $dataMapper = null)
    {
        throw new BadMethodCallException('Buttons do not support data mappers.');
    }

    /**
     * Set whether the button is disabled.
     *
     * @param Boolean $disabled Whether the button is disabled
     *
     * @return ButtonBuilder The button builder.
     */
    public function setDisabled($disabled)
    {
        $this->disabled = $disabled;
    }

    /**
     * Unsupported method.
     *
     * This method should not be invoked.
     *
     * @param mixed $emptyData
     *
     * @throws BadMethodCallException
     */
    public function setEmptyData($emptyData)
    {
        throw new BadMethodCallException('Buttons do not support empty data.');
    }

    /**
     * Unsupported method.
     *
     * This method should not be invoked.
     *
     * @param Boolean $errorBubbling
     *
     * @throws BadMethodCallException
     */
    public function setErrorBubbling($errorBubbling)
    {
        throw new BadMethodCallException('Buttons do not support error bubbling.');
    }

    /**
     * Unsupported method.
     *
     * This method should not be invoked.
     *
     * @param Boolean $required
     *
     * @throws BadMethodCallException
     */
    public function setRequired($required)
    {
        throw new BadMethodCallException('Buttons cannot be required.');
    }

    /**
     * Unsupported method.
     *
     * This method should not be invoked.
     *
     * @param null $propertyPath
     *
     * @throws BadMethodCallException
     */
    public function setPropertyPath($propertyPath)
    {
        throw new BadMethodCallException('Buttons do not support property paths.');
    }

    /**
     * Unsupported method.
     *
     * This method should not be invoked.
     *
     * @param Boolean $mapped
     *
     * @throws BadMethodCallException
     */
    public function setMapped($mapped)
    {
        throw new BadMethodCallException('Buttons do not support data mapping.');
    }

    /**
     * Unsupported method.
     *
     * This method should not be invoked.
     *
     * @param Boolean $byReference
     *
     * @throws BadMethodCallException
     */
    public function setByReference($byReference)
    {
        throw new BadMethodCallException('Buttons do not support data mapping.');
    }

    /**
     * Unsupported method.
     *
     * This method should not be invoked.
     *
     * @param Boolean $virtual
     *
     * @throws BadMethodCallException
     */
    public function setVirtual($virtual)
    {
        throw new BadMethodCallException('Buttons cannot be virtual.');
    }

    /**
     * Unsupported method.
     *
     * This method should not be invoked.
     *
     * @param Boolean $compound
     *
     * @throws BadMethodCallException
     */
    public function setCompound($compound)
    {
        throw new BadMethodCallException('Buttons cannot be compound.');
    }

    /**
     * Sets the type of the button.
     *
     * @param ResolvedFormTypeInterface $type The type of the button.
     *
     * @return ButtonBuilder The button builder.
     */
    public function setType(ResolvedFormTypeInterface $type)
    {
        $this->type = $type;
    }

    /**
     * Unsupported method.
     *
     * This method should not be invoked.
     *
     * @param array $data
     *
     * @throws BadMethodCallException
     */
    public function setData($data)
    {
        throw new BadMethodCallException('Buttons do not support data.');
    }

    /**
     * Unsupported method.
     *
     * This method should not be invoked.
     *
     * @param Boolean $locked
     *
     * @throws BadMethodCallException
     */
    public function setDataLocked($locked)
    {
        throw new BadMethodCallException('Buttons do not support data locking.');
    }

    /**
     * Unsupported method.
     *
     * This method should not be invoked.
     *
     * @param FormFactoryInterface $formFactory
     *
     * @return void
     *
     * @throws BadMethodCallException
     */
    public function setFormFactory(FormFactoryInterface $formFactory)
    {
        throw new BadMethodCallException('Buttons do not support form factories.');
    }

    /**
     * Unsupported method.
     *
     * @param string $action
     *
     * @throws BadMethodCallException
     */
    public function setAction($action)
    {
        throw new BadMethodCallException('Buttons do not support actions.');
    }

    /**
     * Unsupported method.
     *
     * @param string $method
     *
     * @throws BadMethodCallException
     */
    public function setMethod($method)
    {
        throw new BadMethodCallException('Buttons do not support methods.');
    }

    /**
     * Unsupported method.
     *
     * @param RequestHandlerInterface $requestHandler
     *
     * @throws BadMethodCallException
     */
    public function setRequestHandler(RequestHandlerInterface $requestHandler)
    {
        throw new BadMethodCallException('Buttons do not support form processors.');
    }

    /**
     * Unsupported method.
     *
     * @param Boolean $initialize
     *
     * @throws BadMethodCallException
     */
    public function setAutoInitialize($initialize)
    {
        if (true === $initialize) {
            throw new BadMethodCallException('Buttons do not support automatic initialization.');
        }

        return $this;
    }

    /**
     * Unsupported method.
     *
     * @param Boolean $inheritData
     *
     * @throws BadMethodCallException
     */
    public function setInheritData($inheritData)
    {
        throw new BadMethodCallException('Buttons do not support data inheritance.');
    }

    /**
     * Builds and returns the button configuration.
     *
     * @return FormConfigInterface
     */
    public function getFormConfig()
    {
        // This method should be idempotent, so clone the builder
        $config = clone $this;
        $config->locked = true;

        return $config;
    }

    /**
     * Unsupported method.
     *
     * @return null Always returns null.
     */
    public function getEventDispatcher()
    {
        return null;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Unsupported method.
     *
     * @return null Always returns null.
     */
    public function getPropertyPath()
    {
        return null;
    }

    /**
     * Unsupported method.
     *
     * @return Boolean Always returns false.
     */
    public function getMapped()
    {
        return false;
    }

    /**
     * Unsupported method.
     *
     * @return Boolean Always returns false.
     */
    public function getByReference()
    {
        return false;
    }

    /**
     * Unsupported method.
     *
     * @return Boolean Always returns false.
     */
    public function getVirtual()
    {
        return false;
    }

    /**
     * Unsupported method.
     *
     * @return Boolean Always returns false.
     */
    public function getCompound()
    {
        return false;
    }

    /**
     * Returns the form type used to construct the button.
     *
     * @return ResolvedFormTypeInterface The button's type.
     */
    public function getType()
    {
        return $this->type;
    }

    /**
     * Unsupported method.
     *
     * @return array Always returns an empty array.
     */
    public function getViewTransformers()
    {
        return array();
    }

    /**
     * Unsupported method.
     *
     * @return array Always returns an empty array.
     */
    public function getModelTransformers()
    {
        return array();
    }

    /**
     * Unsupported method.
     *
     * @return null Always returns null.
     */
    public function getDataMapper()
    {
        return null;
    }

    /**
     * Unsupported method.
     *
     * @return Boolean Always returns false.
     */
    public function getRequired()
    {
        return false;
    }

    /**
     * Returns whether the button is disabled.
     *
     * @return Boolean Whether the button is disabled.
     */
    public function getDisabled()
    {
        return $this->disabled;
    }

    /**
     * Unsupported method.
     *
     * @return Boolean Always returns false.
     */
    public function getErrorBubbling()
    {
        return false;
    }

    /**
     * Unsupported method.
     *
     * @return null Always returns null.
     */
    public function getEmptyData()
    {
        return null;
    }

    /**
     * Returns additional attributes of the button.
     *
     * @return array An array of key-value combinations.
     */
    public function getAttributes()
    {
        return $this->attributes;
    }

    /**
     * Returns whether the attribute with the given name exists.
     *
     * @param string $name The attribute name.
     *
     * @return Boolean Whether the attribute exists.
     */
    public function hasAttribute($name)
    {
        return array_key_exists($name, $this->attributes);
    }

    /**
     * Returns the value of the given attribute.
     *
     * @param string $name    The attribute name.
     * @param mixed  $default The value returned if the attribute does not exist.
     *
     * @return mixed The attribute value.
     */
    public function getAttribute($name, $default = null)
    {
        return array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default;
    }

    /**
     * Unsupported method.
     *
     * @return null Always returns null.
     */
    public function getData()
    {
        return null;
    }

    /**
     * Unsupported method.
     *
     * @return null Always returns null.
     */
    public function getDataClass()
    {
        return null;
    }

    /**
     * Unsupported method.
     *
     * @return Boolean Always returns false.
     */
    public function getDataLocked()
    {
        return false;
    }

    /**
     * Unsupported method.
     *
     * @return null Always returns null.
     */
    public function getFormFactory()
    {
        return null;
    }

    /**
     * Unsupported method.
     *
     * @return null Always returns null.
     */
    public function getAction()
    {
        return null;
    }

    /**
     * Unsupported method.
     *
     * @return null Always returns null.
     */
    public function getMethod()
    {
        return null;
    }

    /**
     * Unsupported method.
     *
     * @return null Always returns null.
     */
    public function getRequestHandler()
    {
        return null;
    }

    /**
     * Unsupported method.
     *
     * @return Boolean Always returns false.
     */
    public function getAutoInitialize()
    {
        return false;
    }

    /**
     * Unsupported method.
     *
     * @return Boolean Always returns false.
     */
    public function getInheritData()
    {
        return false;
    }

    /**
     * Returns all options passed during the construction of the button.
     *
     * @return array The passed options.
     */
    public function getOptions()
    {
        return $this->options;
    }

    /**
     * Returns whether a specific option exists.
     *
     * @param string $name The option name,
     *
     * @return Boolean Whether the option exists.
     */
    public function hasOption($name)
    {
        return array_key_exists($name, $this->options);
    }

    /**
     * Returns the value of a specific option.
     *
     * @param string $name    The option name.
     * @param mixed  $default The value returned if the option does not exist.
     *
     * @return mixed The option value.
     */
    public function getOption($name, $default = null)
    {
        return array_key_exists($name, $this->options) ? $this->options[$name] : $default;
    }

    /**
     * Unsupported method.
     *
     * @return integer Always returns 0.
     */
    public function count()
    {
        return 0;
    }

    /**
     * Unsupported method.
     *
     * @return \EmptyIterator Always returns an empty iterator.
     */
    public function getIterator()
    {
        return new \EmptyIterator();
    }
}
PK}�Z��n��?Symfony/Component/Form/Resources/translations/validators.en.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>This form should not contain extra fields.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>The uploaded file was too large. Please try to upload a smaller file.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>The CSRF token is invalid. Please try to resubmit the form.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK}�Z誫���?Symfony/Component/Form/Resources/translations/validators.sk.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Polia by nemali obsahovať ďalšie prvky.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>Odoslaný súbor je príliš veľký. Prosím odošlite súbor s menšou veľkosťou.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>CSRF token je neplatný. Prosím skúste znovu odoslať formulár.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK}�Z�<�yy?Symfony/Component/Form/Resources/translations/validators.uk.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Ця форма не повинна містити додаткових полів.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>Завантажений файл занадто великий. Будь-ласка, спробуйте завантажити файл меншого розміру.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>CSRF значення недопустиме. Будь-ласка, спробуйте відправити форму знову.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK}�Z:����?Symfony/Component/Form/Resources/translations/validators.pl.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Ten formularz nie powinien zawierać dodatkowych pól.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>Wgrany plik był za duży. Proszę spróbować wgrać mniejszy plik.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>Token CSRF jest nieprawidłowy. Proszę spróbować wysłać formularz ponownie.</target>
            </trans-unit>
        </body>
    </file>
</xliff>PK��Z��
���?Symfony/Component/Form/Resources/translations/validators.pt.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Este formulário não deveria conter campos extra.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>O arquivo enviado é muito grande. Por favor, tente enviar um ficheiro mais pequeno.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>O token CSRF é inválido. Por favor submeta o formulário novamente.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�%��?Symfony/Component/Form/Resources/translations/validators.lv.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Šajā veidlapā nevajadzētu būt papildus ievades laukiem.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>Augšupielādētā faila izmērs bija par lielu. Lūdzu mēģiniet augšupielādēt mazāka izmēra failu.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>Dotais CSRF talons nav derīgs. Lūdzu mēģiniet vēlreiz iesniegt veidlapu.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z္o33DSymfony/Component/Form/Resources/translations/validators.sr_Cyrl.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Овај формулар не треба да садржи додатна поља.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>Отпремљена датотека је била превелика. Молим покушајте отпремање мање датотеке.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>CSRF вредност је невалидна. Покушајте поново.</target>
            </trans-unit>
        </body>
    </file>
</xliff>PK��Z����?Symfony/Component/Form/Resources/translations/validators.fi.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This field group should not contain extra fields.</source>
                <target>Tämä kenttäryhmä ei voi sisältää ylimääräisiä kenttiä.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>Ladattu tiedosto on liian iso. Ole hyvä ja lataa pienempi tiedosto.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>CSRF tarkiste on virheellinen. Olen hyvä ja yritä lähettää lomake uudestaan.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z0h���?Symfony/Component/Form/Resources/translations/validators.es.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Este formulario no debería contener campos adicionales.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>El archivo subido es demasiado grande. Por favor, suba un archivo más pequeño.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>El token CSRF no es válido. Por favor, pruebe de enviar nuevamente el formulario.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�TI��?Symfony/Component/Form/Resources/translations/validators.de.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Dieses Formular sollte keine zusätzlichen Felder enthalten.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>Die hochgeladene Datei ist zu groß. Versuchen Sie bitte eine kleinere Datei hochzuladen.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>Der CSRF-Token ist ungültig. Versuchen Sie bitte das Formular erneut zu senden.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z!�aZ��?Symfony/Component/Form/Resources/translations/validators.it.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Questo form non dovrebbe contenere nessun campo extra.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>Il file caricato è troppo grande. Per favore caricare un file più piccolo.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>Il token CSRF non è valido. Provare a reinviare il form.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z �!���?Symfony/Component/Form/Resources/translations/validators.ca.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Aquest formulari no hauria de contenir camps addicionals.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>L'arxiu pujat és massa gran. Per favor, pugi un arxiu més petit.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>El token CSRF no és vàlid. Per favor, provi d'enviar novament el formulari.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z���?Symfony/Component/Form/Resources/translations/validators.mn.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Форм нэмэлт талбар багтаах боломжгүй.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>Upload хийсэн файл хэтэрхий том байна. Бага хэмжээтэй файл оруулна уу.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>CSRF token буруу байна. Формоо дахин илгээнэ үү.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z���-��?Symfony/Component/Form/Resources/translations/validators.ru.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Эта форма не должна содержать дополнительных полей.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>Загруженный файл слишком большой. Пожалуйста, попробуйте загрузить файл меньшего размера.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>CSRF значение недопустимо. Пожалуйста, попробуйте повторить отправку формы.</target>
            </trans-unit>
        </body>
    </file>
</xliff>PK��Z�3Ե^^?Symfony/Component/Form/Resources/translations/validators.bg.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Тази форма не трябва да съдържа допълнителни полета.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>Каченият файл е твърде голям. Моля, опитайте да качите по-малък файл.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>Невалиден CSRF токен. Моля, опитайте да изпратите формата отново.</target>
            </trans-unit>
        </body>
    </file>
</xliff>PK��ZE��d��?Symfony/Component/Form/Resources/translations/validators.ro.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Aceast formular nu ar trebui să conțină câmpuri suplimentare.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>Fișierul încărcat a fost prea mare. Vă rugăm sa încărcați un fișier mai mic.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>Token-ul CSRF este invalid. Vă rugăm să trimiteți formularul incă o dată.</target>
            </trans-unit>
        </body>
    </file>
</xliff>PK��ZO���?Symfony/Component/Form/Resources/translations/validators.nl.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Dit formulier mag geen extra velden bevatten.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>Het geüploade bestand is te groot. Probeer een kleiner bestand te uploaden.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>De CSRF-token is ongeldig. Probeer het formulier opnieuw te versturen.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��ZS�*��?Symfony/Component/Form/Resources/translations/validators.et.xlfnu�[���<?xml version='1.0'?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Väljade grupp ei tohiks sisalda lisaväljasid.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>Üleslaaditud fail oli liiga suur. Palun proovi uuesti väiksema failiga.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>CSRF-märgis on vigane. Palun proovi vormi uuesti esitada.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�V5?Symfony/Component/Form/Resources/translations/validators.fa.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>این فرم نباید فیلد اضافی داشته باشد.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>فایل بارگذاری شده بسیار بزرگ است. لطفا فایل کوچکتری را بارگزاری کنید.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>مقدار CSRF نامعتبر است. لطفا فرم را مجددا ارسال فرمایید..</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z��q��?Symfony/Component/Form/Resources/translations/validators.id.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Gabungan kolom tidak boleh mengandung kolom tambahan.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>Berkas yang di unggah terlalu besar. Silahkan coba unggah berkas yang lebih kecil.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>CSRF-Token tidak sah. Silahkan coba kirim ulang formulir.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�
���?Symfony/Component/Form/Resources/translations/validators.cs.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Tato skupina polí nesmí obsahovat další pole.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>Nahraný soubor je příliš velký. Nahrajte prosím menší soubor.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>CSRF token je neplatný. Zkuste prosím znovu odeslat formulář.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�8,:��BSymfony/Component/Form/Resources/translations/validators.zh_CN.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>该表单中不可有额外字段.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>上传文件太大, 请重新尝试上传一个较小的文件.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>CSRF 验证符无效, 请重新提交.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�H�q��?Symfony/Component/Form/Resources/translations/validators.lt.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Forma negali turėti papildomų laukų.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>Įkelta byla yra per didelė. bandykite įkelti mažesnę.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>CSRF kodas nepriimtinas. Bandykite siųsti formos užklausą dar kartą.</target>
            </trans-unit>
        </body>
    </file>
</xliff>PK��Z�_8��?Symfony/Component/Form/Resources/translations/validators.fr.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Ce formulaire ne doit pas contenir des champs supplémentaires.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>Le fichier téléchargé est trop volumineux. Merci d'essayer d'envoyer un fichier plus petit.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>Le jeton CSRF est invalide. Veuillez renvoyer le formulaire.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�A�4��?Symfony/Component/Form/Resources/translations/validators.gl.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Este formulario non debería conter campos adicionais.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>O arquivo subido é demasiado grande. Por favor, suba un arquivo máis pequeno.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>O token CSRF non é válido. Por favor, probe a enviar novamente o formulario.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z
b�8��?Symfony/Component/Form/Resources/translations/validators.hr.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Ovaj obrazac ne smije sadržavati dodatna polja.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>Prenesena datoteka je prevelika. Molim pokušajte prenijeti manju datoteku.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>CSRF vrijednost nije ispravna. Pokušajte ponovo poslati obrazac.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��ZWgUugg?Symfony/Component/Form/Resources/translations/validators.nb.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Feltgruppen må ikke inneholde ekstra felter.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>Den opplastede file var for stor. Vennligst last opp en mindre fil.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid.</source>
                <target>CSRF nøkkelen er ugyldig.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Zٻ��||?Symfony/Component/Form/Resources/translations/validators.eu.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Formulario honek ez luke aparteko eremurik eduki behar.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>Igotako fitxategia handiegia da. Mesedez saiatu fitxategi txikiago bat igotzen.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid.</source>
                <target>CSFR tokena ez da egokia.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�4@���BSymfony/Component/Form/Resources/translations/validators.pt_BR.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Este formulário não deve conter campos adicionais.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>O arquivo enviado é muito grande. Por favor, tente enviar um arquivo menor.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>O token CSRF é inválido. Por favor, tente reenviar o formulário.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z��5��?Symfony/Component/Form/Resources/translations/validators.sl.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Ta obrazec ne sme vsebovati dodatnih polj.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>Naložena datoteka je prevelika. Prosimo, poizkusite naložiti manjšo.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>CSRF vrednost je napačna. Prosimo, ponovno pošljite obrazec.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�*{���?Symfony/Component/Form/Resources/translations/validators.lb.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Dës Feldergrupp sollt keng zousätzlech Felder enthalen.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>De geschécktene Fichier ass ze grouss. Versicht wann ech gelift ee méi klenge Fichier eropzelueden.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>Den CSRF-Token ass ongëlteg. Versicht wann ech gelift de Formulaire nach eng Kéier ze schécken.</target>
            </trans-unit>
        </body>
    </file>
</xliff>PK��Zbe�@��?Symfony/Component/Form/Resources/translations/validators.hu.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Ez a mezőcsoport nem tartalmazhat extra mezőket.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>A feltöltött fájl túl nagy. Kérem próbáljon egy kisebb fájlt feltölteni.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>Érvénytelen CSRF token. Kérem próbálja újra elküldeni az űrlapot.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z_��?Symfony/Component/Form/Resources/translations/validators.el.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Αυτή η φόρμα δεν πρέπει να περιέχει επιπλέον πεδία.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>Το αρχείο είναι πολύ μεγάλο. Παρακαλούμε προσπαθήστε να ανεβάσετε ένα μικρότερο αρχείο.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>Το CSRF token δεν είναι έγκυρο. Παρακαλούμε δοκιμάστε να υποβάλετε τη φόρμα ξανά.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��ZX�����?Symfony/Component/Form/Resources/translations/validators.da.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Feltgruppen må ikke indeholde ekstra felter.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>Den oploadede fil var for stor. Opload venligst en mindre fil.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>CSRF nøglen er ugyldig.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z���?Symfony/Component/Form/Resources/translations/validators.ja.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>フィールドグループに追加のフィールドを含んではなりません。</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>アップロードされたファイルが大きすぎます。小さなファイルで再度アップロードしてください。</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid.</source>
                <target>CSRFトークンが無効です。</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Zs>�ll?Symfony/Component/Form/Resources/translations/validators.sv.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Formuläret kan inte innehålla extra fält.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>Den uppladdade filen var för stor. Försök ladda upp en mindre fil.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid.</source>
                <target>CSRF-symbolen är inte giltig.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Zy��99?Symfony/Component/Form/Resources/translations/validators.hy.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Այս ձևը չպետք է պարունակի լրացուցիչ տողեր.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>Վերբեռնված ֆայլը չափազանց մեծ է: Խնդրվում է վերբեռնել ավելի փոքր չափսի ֆայլ.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>CSRF արժեքը անթույլատրելի է: Փորձեք նորից ուղարկել ձևը.</target>
            </trans-unit>
        </body>
    </file>
</xliff>PK��Z|��C?Symfony/Component/Form/Resources/translations/validators.ar.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>هذا النموذج يجب الا يحتوى على اى حقول اضافية.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>مساحة الملف المرسل كبيرة. من فضلك حاول ارسال ملف اصغر.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>قيمة رمز الموقع غير صحيحة. من فضلك اعد ارسال النموذج.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Zr���DSymfony/Component/Form/Resources/translations/validators.sr_Latn.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>Ovaj formular ne treba da sadrži dodatna polja.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>Otpremljena datoteka je bila prevelika. Molim pokušajte otpremanje manje datoteke.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid. Please try to resubmit the form.</source>
                <target>CSRF vrednost je nevalidna. Pokušajte ponovo.</target>
            </trans-unit>
        </body>
    </file>
</xliff>PK��ZNP\��?Symfony/Component/Form/Resources/translations/validators.he.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="28">
                <source>This form should not contain extra fields.</source>
                <target>הטופס לא צריך להכיל שדות נוספים.</target>
            </trans-unit>
            <trans-unit id="29">
                <source>The uploaded file was too large. Please try to upload a smaller file.</source>
                <target>הקובץ שהועלה גדול מדי. נסה להעלות קובץ קטן יותר.</target>
            </trans-unit>
            <trans-unit id="30">
                <source>The CSRF token is invalid.</source>
                <target>אסימון CSRF אינו חוקי.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�xfh..6Symfony/Component/Form/Resources/config/validation.xmlnu�[���<?xml version="1.0" ?>

<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">

  <class name="Symfony\Component\Form\Form">
    <constraint name="Symfony\Component\Form\Extension\Validator\Constraints\Form" />
    <property name="children">
        <constraint name="Valid" />
    </property>
  </class>
</constraint-mapping>
PK��ZR}��jj.Symfony/Component/Form/DataMapperInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface DataMapperInterface
{
    /**
     * Maps properties of some data to a list of forms.
     *
     * @param mixed           $data  Structured data.
     * @param FormInterface[] $forms A list of {@link FormInterface} instances.
     *
     * @throws Exception\UnexpectedTypeException if the type of the data parameter is not supported.
     */
    public function mapDataToForms($data, $forms);

    /**
     * Maps the data of a list of forms into the properties of some data.
     *
     * @param FormInterface[] $forms A list of {@link FormInterface} instances.
     * @param mixed           $data  Structured data.
     *
     * @throws Exception\UnexpectedTypeException if the type of the data parameter is not supported.
     */
    public function mapFormsToData($forms, &$data);
}
PK��Z�s�� � (Symfony/Component/Form/FormInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

/**
 * A form group bundling multiple forms in a hierarchical structure.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface FormInterface extends \ArrayAccess, \Traversable, \Countable
{
    /**
     * Sets the parent form.
     *
     * @param  FormInterface|null $parent The parent form or null if it's the root.
     *
     * @return FormInterface The form instance
     *
     * @throws Exception\AlreadySubmittedException If the form has already been submitted.
     * @throws Exception\LogicException        When trying to set a parent for a form with
     *                                         an empty name.
     */
    public function setParent(FormInterface $parent = null);

    /**
     * Returns the parent form.
     *
     * @return FormInterface|null The parent form or null if there is none.
     */
    public function getParent();

    /**
     * Adds or replaces a child to the form.
     *
     * @param FormInterface|string|integer $child   The FormInterface instance or the name of the child.
     * @param string|null                  $type    The child's type, if a name was passed.
     * @param array                        $options The child's options, if a name was passed.
     *
     * @return FormInterface The form instance
     *
     * @throws Exception\AlreadySubmittedException   If the form has already been submitted.
     * @throws Exception\LogicException          When trying to add a child to a non-compound form.
     * @throws Exception\UnexpectedTypeException If $child or $type has an unexpected type.
     */
    public function add($child, $type = null, array $options = array());

    /**
     * Returns the child with the given name.
     *
     * @param string $name The name of the child
     *
     * @return FormInterface The child form
     *
     * @throws \OutOfBoundsException If the named child does not exist.
     */
    public function get($name);

    /**
     * Returns whether a child with the given name exists.
     *
     * @param string $name The name of the child
     *
     * @return Boolean
     */
    public function has($name);

    /**
     * Removes a child from the form.
     *
     * @param  string $name The name of the child to remove
     *
     * @return FormInterface The form instance
     *
     * @throws Exception\AlreadySubmittedException If the form has already been submitted.
     */
    public function remove($name);

    /**
     * Returns all children in this group.
     *
     * @return FormInterface[] An array of FormInterface instances
     */
    public function all();

    /**
     * Returns all errors.
     *
     * @return FormError[] An array of FormError instances that occurred during validation
     */
    public function getErrors();

    /**
     * Updates the form with default data.
     *
     * @param  mixed $modelData The data formatted as expected for the underlying object
     *
     * @return FormInterface The form instance
     *
     * @throws Exception\AlreadySubmittedException If the form has already been submitted.
     * @throws Exception\LogicException        If listeners try to call setData in a cycle. Or if
     *                                         the view data does not match the expected type
     *                                         according to {@link FormConfigInterface::getDataClass}.
     */
    public function setData($modelData);

    /**
     * Returns the data in the format needed for the underlying object.
     *
     * @return mixed
     */
    public function getData();

    /**
     * Returns the normalized data of the field.
     *
     * @return mixed When the field is not submitted, the default data is returned.
     *               When the field is submitted, the normalized submitted data is
     *               returned if the field is valid, null otherwise.
     */
    public function getNormData();

    /**
     * Returns the data transformed by the value transformer.
     *
     * @return mixed
     */
    public function getViewData();

    /**
     * Returns the extra data.
     *
     * @return array The submitted data which do not belong to a child
     */
    public function getExtraData();

    /**
     * Returns the form's configuration.
     *
     * @return FormConfigInterface The configuration.
     */
    public function getConfig();

    /**
     * Returns whether the form is submitted.
     *
     * @return Boolean true if the form is submitted, false otherwise
     */
    public function isSubmitted();

    /**
     * Returns the name by which the form is identified in forms.
     *
     * @return string The name of the form.
     */
    public function getName();

    /**
     * Returns the property path that the form is mapped to.
     *
     * @return \Symfony\Component\PropertyAccess\PropertyPathInterface The property path.
     */
    public function getPropertyPath();

    /**
     * Adds an error to this form.
     *
     * @param  FormError $error
     *
     * @return FormInterface The form instance
     */
    public function addError(FormError $error);

    /**
     * Returns whether the form and all children are valid.
     *
     * If the form is not submitted, this method always returns false.
     *
     * @return Boolean
     */
    public function isValid();

    /**
     * Returns whether the form is required to be filled out.
     *
     * If the form has a parent and the parent is not required, this method
     * will always return false. Otherwise the value set with setRequired()
     * is returned.
     *
     * @return Boolean
     */
    public function isRequired();

    /**
     * Returns whether this form is disabled.
     *
     * The content of a disabled form is displayed, but not allowed to be
     * modified. The validation of modified disabled forms should fail.
     *
     * Forms whose parents are disabled are considered disabled regardless of
     * their own state.
     *
     * @return Boolean
     */
    public function isDisabled();

    /**
     * Returns whether the form is empty.
     *
     * @return Boolean
     */
    public function isEmpty();

    /**
     * Returns whether the data in the different formats is synchronized.
     *
     * @return Boolean
     */
    public function isSynchronized();

    /**
     * Initializes the form tree.
     *
     * Should be called on the root form after constructing the tree.
     *
     * @return FormInterface The form instance.
     */
    public function initialize();

    /**
     * Inspects the given request and calls {@link submit()} if the form was
     * submitted.
     *
     * Internally, the request is forwarded to the configured
     * {@link RequestHandlerInterface} instance, which determines whether to
     * submit the form or not.
     *
     * @param mixed $request The request to handle.
     *
     * @return FormInterface The form instance.
     */
    public function handleRequest($request = null);

    /**
     * Submits data to the form, transforms and validates it.
     *
     * @param null|string|array $submittedData The submitted data.
     * @param Boolean           $clearMissing  Whether to set fields to NULL
     *                                         when they are missing in the
     *                                         submitted data.
     *
     * @return FormInterface The form instance
     *
     * @throws Exception\AlreadySubmittedException If the form has already been submitted.
     */
    public function submit($submittedData, $clearMissing = true);

    /**
     * Returns the root of the form tree.
     *
     * @return FormInterface The root of the tree
     */
    public function getRoot();

    /**
     * Returns whether the field is the root of the form tree.
     *
     * @return Boolean
     */
    public function isRoot();

    /**
     * Creates a view.
     *
     * @param FormView $parent The parent view
     *
     * @return FormView The view
     */
    public function createView(FormView $parent = null);
}
PK��Z���"��$Symfony/Component/Form/FormEvent.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

use Symfony\Component\EventDispatcher\Event;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class FormEvent extends Event
{
    private $form;
    protected $data;

    /**
     * Constructs an event.
     *
     * @param FormInterface $form The associated form
     * @param mixed         $data The data
     */
    public function __construct(FormInterface $form, $data)
    {
        $this->form = $form;
        $this->data = $data;
    }

    /**
     * Returns the form at the source of the event.
     *
     * @return FormInterface
     */
    public function getForm()
    {
        return $this->form;
    }

    /**
     * Returns the data associated with this event.
     *
     * @return mixed
     */
    public function getData()
    {
        return $this->data;
    }

    /**
     * Allows updating with some filtered data.
     *
     * @param mixed $data
     */
    public function setData($data)
    {
        $this->data = $data;
    }
}
PK��Z�=�MM5Symfony/Component/Form/FormTypeExtensionInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

use Symfony\Component\OptionsResolver\OptionsResolverInterface;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface FormTypeExtensionInterface
{
    /**
     * Builds the form.
     *
     * This method is called after the extended type has built the form to
     * further modify it.
     *
     * @see FormTypeInterface::buildForm()
     *
     * @param FormBuilderInterface $builder The form builder
     * @param array                $options The options
     */
    public function buildForm(FormBuilderInterface $builder, array $options);

    /**
     * Builds the view.
     *
     * This method is called after the extended type has built the view to
     * further modify it.
     *
     * @see FormTypeInterface::buildView()
     *
     * @param FormView $view    The view
     * @param FormInterface     $form    The form
     * @param array             $options The options
     */
    public function buildView(FormView $view, FormInterface $form, array $options);

    /**
     * Finishes the view.
     *
     * This method is called after the extended type has finished the view to
     * further modify it.
     *
     * @see FormTypeInterface::finishView()
     *
     * @param FormView $view    The view
     * @param FormInterface     $form    The form
     * @param array             $options The options
     */
    public function finishView(FormView $view, FormInterface $form, array $options);

    /**
     * Overrides the default options from the extended type.
     *
     * @param OptionsResolverInterface $resolver The resolver for the options.
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver);

    /**
     * Returns the name of the type being extended.
     *
     * @return string The name of the type being extended
     */
    public function getExtendedType();
}
PK��Z�}p�

$Symfony/Component/Form/FormError.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

/**
 * Wraps errors in forms
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class FormError
{
    /**
     * @var string
     */
    private $message;

    /**
     * The template for the error message
     * @var string
     */
    protected $messageTemplate;

    /**
     * The parameters that should be substituted in the message template
     * @var array
     */
    protected $messageParameters;

    /**
     * The value for error message pluralization
     * @var integer|null
     */
    protected $messagePluralization;

    /**
     * Constructor
     *
     * Any array key in $messageParameters will be used as a placeholder in
     * $messageTemplate.
     *
     * @param string       $message              The translated error message
     * @param string|null  $messageTemplate      The template for the error message
     * @param array        $messageParameters    The parameters that should be
     *                                           substituted in the message template.
     * @param integer|null $messagePluralization The value for error message pluralization
     *
     * @see \Symfony\Component\Translation\Translator
     */
    public function __construct($message, $messageTemplate = null, array $messageParameters = array(), $messagePluralization = null)
    {
        $this->message = $message;
        $this->messageTemplate = $messageTemplate ?: $message;
        $this->messageParameters = $messageParameters;
        $this->messagePluralization = $messagePluralization;
    }

    /**
     * Returns the error message
     *
     * @return string
     */
    public function getMessage()
    {
        return $this->message;
    }

    /**
     * Returns the error message template
     *
     * @return string
     */
    public function getMessageTemplate()
    {
        return $this->messageTemplate;
    }

    /**
     * Returns the parameters to be inserted in the message template
     *
     * @return array
     */
    public function getMessageParameters()
    {
        return $this->messageParameters;
    }

    /**
     * Returns the value for error message pluralization.
     *
     * @return integer|null
     */
    public function getMessagePluralization()
    {
        return $this->messagePluralization;
    }
}
PK��Z�	���/Symfony/Component/Form/NativeRequestHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

use Symfony\Component\Form\Exception\UnexpectedTypeException;

/**
 * A request handler using PHP's super globals $_GET, $_POST and $_SERVER.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class NativeRequestHandler implements RequestHandlerInterface
{
    /**
     * The allowed keys of the $_FILES array.
     *
     * @var array
     */
    private static $fileKeys = array(
        'error',
        'name',
        'size',
        'tmp_name',
        'type',
    );

    /**
     * {@inheritdoc}
     */
    public function handleRequest(FormInterface $form, $request = null)
    {
        if (null !== $request) {
            throw new UnexpectedTypeException($request, 'null');
        }

        $name = $form->getName();
        $method = $form->getConfig()->getMethod();

        if ($method !== self::getRequestMethod()) {
            return;
        }

        if ('GET' === $method) {
            if ('' === $name) {
                $data = $_GET;
            } else {
                // Don't submit GET requests if the form's name does not exist
                // in the request
                if (!isset($_GET[$name])) {
                    return;
                }

                $data = $_GET[$name];
            }
        } else {
            $fixedFiles = array();
            foreach ($_FILES as $name => $file) {
                $fixedFiles[$name] = self::stripEmptyFiles(self::fixPhpFilesArray($file));
            }

            if ('' === $name) {
                $params = $_POST;
                $files = $fixedFiles;
            } elseif (array_key_exists($name, $_POST) || array_key_exists($name, $fixedFiles)) {
                $default = $form->getConfig()->getCompound() ? array() : null;
                $params = array_key_exists($name, $_POST) ? $_POST[$name] : $default;
                $files = array_key_exists($name, $fixedFiles) ? $fixedFiles[$name] : $default;
            } else {
                // Don't submit the form if it is not present in the request
                return;
            }

            if (is_array($params) && is_array($files)) {
                $data = array_replace_recursive($params, $files);
            } else {
                $data = $params ?: $files;
            }
        }

        // Don't auto-submit the form unless at least one field is present.
        if ('' === $name && count(array_intersect_key($data, $form->all())) <= 0) {
            return;
        }

        $form->submit($data, 'PATCH' !== $method);
    }

    /**
     * Returns the method used to submit the request to the server.
     *
     * @return string The request method.
     */
    private static function getRequestMethod()
    {
        $method = isset($_SERVER['REQUEST_METHOD'])
            ? strtoupper($_SERVER['REQUEST_METHOD'])
            : 'GET';

        if ('POST' === $method && isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])) {
            $method = strtoupper($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']);
        }

        return $method;
    }

    /**
     * Fixes a malformed PHP $_FILES array.
     *
     * PHP has a bug that the format of the $_FILES array differs, depending on
     * whether the uploaded file fields had normal field names or array-like
     * field names ("normal" vs. "parent[child]").
     *
     * This method fixes the array to look like the "normal" $_FILES array.
     *
     * It's safe to pass an already converted array, in which case this method
     * just returns the original array unmodified.
     *
     * This method is identical to {@link Symfony\Component\HttpFoundation\FileBag::fixPhpFilesArray}
     * and should be kept as such in order to port fixes quickly and easily.
     *
     * @param array $data
     *
     * @return array
     */
    private static function fixPhpFilesArray($data)
    {
        if (!is_array($data)) {
            return $data;
        }

        $keys = array_keys($data);
        sort($keys);

        if (self::$fileKeys !== $keys || !isset($data['name']) || !is_array($data['name'])) {
            return $data;
        }

        $files = $data;
        foreach (self::$fileKeys as $k) {
            unset($files[$k]);
        }

        foreach (array_keys($data['name']) as $key) {
            $files[$key] = self::fixPhpFilesArray(array(
                'error'    => $data['error'][$key],
                'name'     => $data['name'][$key],
                'type'     => $data['type'][$key],
                'tmp_name' => $data['tmp_name'][$key],
                'size'     => $data['size'][$key]
            ));
        }

        return $files;
    }

    /**
     * Sets empty uploaded files to NULL in the given uploaded files array.
     *
     * @param mixed $data The file upload data.
     *
     * @return array|null Returns the stripped upload data.
     */
    private static function stripEmptyFiles($data)
    {
        if (!is_array($data)) {
            return $data;
        }

        $keys = array_keys($data);
        sort($keys);

        if (self::$fileKeys === $keys) {
            if (UPLOAD_ERR_NO_FILE === $data['error']) {
                return null;
            }

            return $data;
        }

        foreach ($data as $key => $value) {
            $data[$key] = self::stripEmptyFiles($value);
        }

        return $data;
    }
}
PK��Z���*��OSymfony/Component/Form/Extension/Validator/EventListener/ValidationListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Validator\EventListener;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapperInterface;
use Symfony\Component\Validator\ValidatorInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\Extension\Validator\Constraints\Form;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ValidationListener implements EventSubscriberInterface
{
    private $validator;

    private $violationMapper;

    /**
     * {@inheritdoc}
     */
    public static function getSubscribedEvents()
    {
        return array(FormEvents::POST_SUBMIT => 'validateForm');
    }

    public function __construct(ValidatorInterface $validator, ViolationMapperInterface $violationMapper)
    {
        $this->validator = $validator;
        $this->violationMapper = $violationMapper;
    }

    /**
     * Validates the form and its domain object.
     *
     * @param FormEvent $event The event object
     */
    public function validateForm(FormEvent $event)
    {
        $form = $event->getForm();

        if ($form->isRoot()) {
            // Validate the form in group "Default"
            $violations = $this->validator->validate($form);

            foreach ($violations as $violation) {
                // Allow the "invalid" constraint to be put onto
                // non-synchronized forms
                $allowNonSynchronized = Form::ERR_INVALID === $violation->getCode();

                $this->violationMapper->mapViolation($violation, $form, $allowNonSynchronized);
            }
        }
    }
}
PK��Z��Ck��@Symfony/Component/Form/Extension/Validator/Util/ServerParams.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Validator\Util;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ServerParams
{
    /**
     * Returns maximum post size in bytes.
     *
     * @return null|integer The maximum post size in bytes
     */
    public function getPostMaxSize()
    {
        $iniMax = strtolower($this->getNormalizedIniPostMaxSize());

        if ('' === $iniMax) {
            return null;
        }

        $max = ltrim($iniMax, '+');
        if (0 === strpos($max, '0x')) {
            $max = intval($max, 16);
        } elseif (0 === strpos($max, '0')) {
            $max = intval($max, 8);
        } else {
            $max = intval($max);
        }

        switch (substr($iniMax, -1)) {
            case 't': $max *= 1024;
            case 'g': $max *= 1024;
            case 'm': $max *= 1024;
            case 'k': $max *= 1024;
        }

        return $max;
    }

    /**
     * Returns the normalized "post_max_size" ini setting.
     *
     * @return string
     */
    public function getNormalizedIniPostMaxSize()
    {
        return strtoupper(trim(ini_get('post_max_size')));
    }

    /**
     * Returns the content length of the request.
     *
     * @return mixed The request content length.
     */
    public function getContentLength()
    {
        return isset($_SERVER['CONTENT_LENGTH'])
            ? (int) $_SERVER['CONTENT_LENGTH']
            : null;
    }

}
PK��Z2=[<((ASymfony/Component/Form/Extension/Validator/ValidatorExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Validator;

use Symfony\Component\Form\Extension\Validator\Constraints\Form;
use Symfony\Component\Form\AbstractExtension;
use Symfony\Component\Validator\ValidatorInterface;
use Symfony\Component\Validator\Constraints\Valid;

/**
 * Extension supporting the Symfony2 Validator component in forms.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ValidatorExtension extends AbstractExtension
{
    private $validator;

    public function __construct(ValidatorInterface $validator)
    {
        $this->validator = $validator;

        // Register the form constraints in the validator programmatically.
        // This functionality is required when using the Form component without
        // the DIC, where the XML file is loaded automatically. Thus the following
        // code must be kept synchronized with validation.xml

        /** @var \Symfony\Component\Validator\Mapping\ClassMetadata $metadata */
        $metadata = $this->validator->getMetadataFactory()->getMetadataFor('Symfony\Component\Form\Form');
        $metadata->addConstraint(new Form());
        $metadata->addPropertyConstraint('children', new Valid());
    }

    public function loadTypeGuesser()
    {
        return new ValidatorTypeGuesser($this->validator->getMetadataFactory());
    }

    protected function loadTypeExtensions()
    {
        return array(
            new Type\FormTypeValidatorExtension($this->validator),
            new Type\RepeatedTypeValidatorExtension(),
            new Type\SubmitTypeValidatorExtension(),
        );
    }
}
PK��Z}>�ُ�?Symfony/Component/Form/Extension/Validator/Constraints/Form.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class Form extends Constraint
{
    /**
     * Violation code marking an invalid form.
     */
    const ERR_INVALID = 1;

    /**
     * {@inheritdoc}
     */
    public function getTargets()
    {
        return self::CLASS_CONSTRAINT;
    }
}
PK��Z�-�P��HSymfony/Component/Form/Extension/Validator/Constraints/FormValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Validator\Constraints;

use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\Extension\Validator\Util\ServerParams;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class FormValidator extends ConstraintValidator
{
    /**
     * @var ServerParams
     */
    private $serverParams;

    /**
     * Creates a validator with the given server parameters.
     *
     * @param ServerParams $params The server parameters. Default
     *                             parameters are created if null.
     */
    public function __construct(ServerParams $params = null)
    {
        $this->serverParams = $params ?: new ServerParams();
    }

    /**
     * {@inheritdoc}
     */
    public function validate($form, Constraint $constraint)
    {
        if (!$form instanceof FormInterface) {
            return;
        }

        /* @var FormInterface $form */
        $config = $form->getConfig();

        if ($form->isSynchronized()) {
            // Validate the form data only if transformation succeeded
            $groups = self::getValidationGroups($form);

            // Validate the data against its own constraints
            if (self::allowDataWalking($form)) {
                foreach ($groups as $group) {
                    $this->context->validate($form->getData(), 'data', $group, true);
                }
            }

            // Validate the data against the constraints defined
            // in the form
            $constraints = $config->getOption('constraints');
            foreach ($constraints as $constraint) {
                foreach ($groups as $group) {
                    if (in_array($group, $constraint->groups)) {
                        $this->context->validateValue($form->getData(), $constraint, 'data', $group);

                        // Prevent duplicate validation
                        continue 2;
                    }
                }
            }
        } else {
            $childrenSynchronized = true;

            foreach ($form as $child) {
                if (!$child->isSynchronized()) {
                    $childrenSynchronized = false;
                    break;
                }
            }

            // Mark the form with an error if it is not synchronized BUT all
            // of its children are synchronized. If any child is not
            // synchronized, an error is displayed there already and showing
            // a second error in its parent form is pointless, or worse, may
            // lead to duplicate errors if error bubbling is enabled on the
            // child.
            // See also https://github.com/symfony/symfony/issues/4359
            if ($childrenSynchronized) {
                $clientDataAsString = is_scalar($form->getViewData())
                    ? (string) $form->getViewData()
                    : gettype($form->getViewData());

                $this->context->addViolation(
                    $config->getOption('invalid_message'),
                    array_replace(array('{{ value }}' => $clientDataAsString), $config->getOption('invalid_message_parameters')),
                    $form->getViewData(),
                    null,
                    Form::ERR_INVALID
                );
            }
        }

        // Mark the form with an error if it contains extra fields
        if (count($form->getExtraData()) > 0) {
            $this->context->addViolation(
                $config->getOption('extra_fields_message'),
                array('{{ extra_fields }}' => implode('", "', array_keys($form->getExtraData()))),
                $form->getExtraData()
            );
        }

        // Mark the form with an error if the uploaded size was too large
        $length = $this->serverParams->getContentLength();

        if ($form->isRoot() && null !== $length) {
            $max = $this->serverParams->getPostMaxSize();

            if (!empty($max) && $length > $max) {
                $this->context->addViolation(
                    $config->getOption('post_max_size_message'),
                    array('{{ max }}' => $this->serverParams->getNormalizedIniPostMaxSize()),
                    $length
                );
            }
        }
    }

    /**
     * Returns whether the data of a form may be walked.
     *
     * @param  FormInterface $form The form to test.
     *
     * @return Boolean Whether the graph walker may walk the data.
     */
    private static function allowDataWalking(FormInterface $form)
    {
        $data = $form->getData();

        // Scalar values cannot have mapped constraints
        if (!is_object($data) && !is_array($data)) {
            return false;
        }

        // Root forms are always validated
        if ($form->isRoot()) {
            return true;
        }

        // Non-root forms are validated if validation cascading
        // is enabled in all ancestor forms
        while (null !== ($form = $form->getParent())) {
            if (!$form->getConfig()->getOption('cascade_validation')) {
                return false;
            }
        }

        return true;
    }

    /**
     * Returns the validation groups of the given form.
     *
     * @param  FormInterface $form The form.
     *
     * @return array The validation groups.
     */
    private static function getValidationGroups(FormInterface $form)
    {
        // Determine the clicked button of the complete form tree
        $clickedButton = null;

        if (method_exists($form, 'getClickedButton')) {
            $clickedButton = $form->getClickedButton();
        }

        if (null !== $clickedButton) {
            $groups = $clickedButton->getConfig()->getOption('validation_groups');

            if (null !== $groups) {
                return self::resolveValidationGroups($groups, $form);
            }
        }

        do {
            $groups = $form->getConfig()->getOption('validation_groups');

            if (null !== $groups) {
                return self::resolveValidationGroups($groups, $form);
            }

            $form = $form->getParent();
        } while (null !== $form);

        return array(Constraint::DEFAULT_GROUP);
    }

    /**
     * Post-processes the validation groups option for a given form.
     *
     * @param array|callable $groups The validation groups.
     * @param FormInterface  $form   The validated form.
     *
     * @return array The validation groups.
     */
    private static function resolveValidationGroups($groups, FormInterface $form)
    {
        if (!is_string($groups) && is_callable($groups)) {
            $groups = call_user_func($groups, $form);
        }

        return (array) $groups;
    }
}
PK��Zl�Ct*t*CSymfony/Component/Form/Extension/Validator/ValidatorTypeGuesser.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Validator;

use Symfony\Component\Form\FormTypeGuesserInterface;
use Symfony\Component\Form\Guess\Guess;
use Symfony\Component\Form\Guess\TypeGuess;
use Symfony\Component\Form\Guess\ValueGuess;
use Symfony\Component\Validator\MetadataFactoryInterface;
use Symfony\Component\Validator\Constraint;

class ValidatorTypeGuesser implements FormTypeGuesserInterface
{
    private $metadataFactory;

    public function __construct(MetadataFactoryInterface $metadataFactory)
    {
        $this->metadataFactory = $metadataFactory;
    }

    /**
     * {@inheritDoc}
     */
    public function guessType($class, $property)
    {
        $guesser = $this;

        return $this->guess($class, $property, function (Constraint $constraint) use ($guesser) {
            return $guesser->guessTypeForConstraint($constraint);
        });
    }

    /**
     * {@inheritDoc}
     */
    public function guessRequired($class, $property)
    {
        $guesser = $this;

        return $this->guess($class, $property, function (Constraint $constraint) use ($guesser) {
            return $guesser->guessRequiredForConstraint($constraint);
        // If we don't find any constraint telling otherwise, we can assume
        // that a field is not required (with LOW_CONFIDENCE)
        }, false);
    }

    /**
     * {@inheritDoc}
     */
    public function guessMaxLength($class, $property)
    {
        $guesser = $this;

        return $this->guess($class, $property, function (Constraint $constraint) use ($guesser) {
            return $guesser->guessMaxLengthForConstraint($constraint);
        });
    }

    /**
     * {@inheritDoc}
     */
    public function guessPattern($class, $property)
    {
        $guesser = $this;

        return $this->guess($class, $property, function (Constraint $constraint) use ($guesser) {
            return $guesser->guessPatternForConstraint($constraint);
        });
    }

    /**
     * Guesses a field class name for a given constraint
     *
     * @param Constraint $constraint The constraint to guess for
     *
     * @return TypeGuess|null The guessed field class and options
     */
    public function guessTypeForConstraint(Constraint $constraint)
    {
        switch (get_class($constraint)) {
            case 'Symfony\Component\Validator\Constraints\Type':
                switch ($constraint->type) {
                    case 'array':
                        return new TypeGuess('collection', array(), Guess::MEDIUM_CONFIDENCE);
                    case 'boolean':
                    case 'bool':
                        return new TypeGuess('checkbox', array(), Guess::MEDIUM_CONFIDENCE);

                    case 'double':
                    case 'float':
                    case 'numeric':
                    case 'real':
                        return new TypeGuess('number', array(), Guess::MEDIUM_CONFIDENCE);

                    case 'integer':
                    case 'int':
                    case 'long':
                        return new TypeGuess('integer', array(), Guess::MEDIUM_CONFIDENCE);

                    case '\DateTime':
                        return new TypeGuess('date', array(), Guess::MEDIUM_CONFIDENCE);

                    case 'string':
                        return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE);
                }
                break;

            case 'Symfony\Component\Validator\Constraints\Country':
                return new TypeGuess('country', array(), Guess::HIGH_CONFIDENCE);

            case 'Symfony\Component\Validator\Constraints\Date':
                return new TypeGuess('date', array('input' => 'string'), Guess::HIGH_CONFIDENCE);

            case 'Symfony\Component\Validator\Constraints\DateTime':
                return new TypeGuess('datetime', array('input' => 'string'), Guess::HIGH_CONFIDENCE);

            case 'Symfony\Component\Validator\Constraints\Email':
                return new TypeGuess('email', array(), Guess::HIGH_CONFIDENCE);

            case 'Symfony\Component\Validator\Constraints\File':
            case 'Symfony\Component\Validator\Constraints\Image':
                return new TypeGuess('file', array(), Guess::HIGH_CONFIDENCE);

            case 'Symfony\Component\Validator\Constraints\Language':
                return new TypeGuess('language', array(), Guess::HIGH_CONFIDENCE);

            case 'Symfony\Component\Validator\Constraints\Locale':
                return new TypeGuess('locale', array(), Guess::HIGH_CONFIDENCE);

            case 'Symfony\Component\Validator\Constraints\Time':
                return new TypeGuess('time', array('input' => 'string'), Guess::HIGH_CONFIDENCE);

            case 'Symfony\Component\Validator\Constraints\Url':
                return new TypeGuess('url', array(), Guess::HIGH_CONFIDENCE);

            case 'Symfony\Component\Validator\Constraints\Ip':
                return new TypeGuess('text', array(), Guess::MEDIUM_CONFIDENCE);

            case 'Symfony\Component\Validator\Constraints\Length':
            case 'Symfony\Component\Validator\Constraints\Regex':
                return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE);

            case 'Symfony\Component\Validator\Constraints\Range':
                return new TypeGuess('number', array(), Guess::LOW_CONFIDENCE);

            case 'Symfony\Component\Validator\Constraints\Count':
                return new TypeGuess('collection', array(), Guess::LOW_CONFIDENCE);

            case 'Symfony\Component\Validator\Constraints\True':
            case 'Symfony\Component\Validator\Constraints\False':
                return new TypeGuess('checkbox', array(), Guess::MEDIUM_CONFIDENCE);
        }

        return null;
    }

    /**
     * Guesses whether a field is required based on the given constraint
     *
     * @param Constraint $constraint The constraint to guess for
     *
     * @return ValueGuess|null The guess whether the field is required
     */
    public function guessRequiredForConstraint(Constraint $constraint)
    {
        switch (get_class($constraint)) {
            case 'Symfony\Component\Validator\Constraints\NotNull':
            case 'Symfony\Component\Validator\Constraints\NotBlank':
            case 'Symfony\Component\Validator\Constraints\True':
                return new ValueGuess(true, Guess::HIGH_CONFIDENCE);
        }

        return null;
    }

    /**
     * Guesses a field's maximum length based on the given constraint
     *
     * @param Constraint $constraint The constraint to guess for
     *
     * @return ValueGuess|null The guess for the maximum length
     */
    public function guessMaxLengthForConstraint(Constraint $constraint)
    {
        switch (get_class($constraint)) {
            case 'Symfony\Component\Validator\Constraints\Length':
                if (is_numeric($constraint->max)) {
                    return new ValueGuess($constraint->max, Guess::HIGH_CONFIDENCE);
                }
                break;

            case 'Symfony\Component\Validator\Constraints\Type':
                if (in_array($constraint->type, array('double', 'float', 'numeric', 'real'))) {
                        return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE);
                }
                break;

            case 'Symfony\Component\Validator\Constraints\Range':
                if (is_numeric($constraint->max)) {
                    return new ValueGuess(strlen((string) $constraint->max), Guess::LOW_CONFIDENCE);
                }
                break;
        }

        return null;
    }

    /**
     * Guesses a field's pattern based on the given constraint
     *
     * @param Constraint $constraint The constraint to guess for
     *
     * @return ValueGuess|null The guess for the pattern
     */
    public function guessPatternForConstraint(Constraint $constraint)
    {
        switch (get_class($constraint)) {
            case 'Symfony\Component\Validator\Constraints\Length':
                if (is_numeric($constraint->min)) {
                    return new ValueGuess(sprintf('.{%s,}', (string) $constraint->min), Guess::LOW_CONFIDENCE);
                }
                break;

            case 'Symfony\Component\Validator\Constraints\Regex':
                $htmlPattern = $constraint->getHtmlPattern();

                if (null !== $htmlPattern) {
                    return new ValueGuess($htmlPattern, Guess::HIGH_CONFIDENCE);
                }
                break;

            case 'Symfony\Component\Validator\Constraints\Range':
                if (is_numeric($constraint->min)) {
                    return new ValueGuess(sprintf('.{%s,}', strlen((string) $constraint->min)), Guess::LOW_CONFIDENCE);
                }
                break;

            case 'Symfony\Component\Validator\Constraints\Type':
                if (in_array($constraint->type, array('double', 'float', 'numeric', 'real'))) {
                    return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE);
                }
                break;
        }

        return null;
    }

    /**
     * Iterates over the constraints of a property, executes a constraints on
     * them and returns the best guess
     *
     * @param string   $class        The class to read the constraints from
     * @param string   $property     The property for which to find constraints
     * @param \Closure $closure      The closure that returns a guess
     *                               for a given constraint
     * @param mixed    $defaultValue The default value assumed if no other value
     *                               can be guessed.
     *
     * @return Guess|null The guessed value with the highest confidence
     */
    protected function guess($class, $property, \Closure $closure, $defaultValue = null)
    {
        $guesses = array();
        $classMetadata = $this->metadataFactory->getMetadataFor($class);

        if ($classMetadata->hasMemberMetadatas($property)) {
            $memberMetadatas = $classMetadata->getMemberMetadatas($property);

            foreach ($memberMetadatas as $memberMetadata) {
                $constraints = $memberMetadata->getConstraints();

                foreach ($constraints as $constraint) {
                    if ($guess = $closure($constraint)) {
                        $guesses[] = $guess;
                    }
                }
            }

            if (null !== $defaultValue) {
                $guesses[] = new ValueGuess($defaultValue, Guess::LOW_CONFIDENCE);
            }
        }

        return Guess::getBestGuess($guesses);
    }
}
PK��ZɥS��TSymfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPathIterator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Validator\ViolationMapper;

use Symfony\Component\PropertyAccess\PropertyPathIterator;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ViolationPathIterator extends PropertyPathIterator
{
    public function __construct(ViolationPath $violationPath)
    {
        parent::__construct($violationPath);
    }

    public function mapsForm()
    {
        return $this->path->mapsForm($this->key());
    }
}
PK��Z�\T��KSymfony/Component/Form/Extension/Validator/ViolationMapper/RelativePath.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Validator\ViolationMapper;

use Symfony\Component\Form\FormInterface;
use Symfony\Component\PropertyAccess\PropertyPath;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class RelativePath extends PropertyPath
{
    /**
     * @var FormInterface
     */
    private $root;

    /**
     * @param FormInterface $root
     * @param string        $propertyPath
     */
    public function __construct(FormInterface $root, $propertyPath)
    {
        parent::__construct($propertyPath);

        $this->root = $root;
    }

    /**
     * @return FormInterface
     */
    public function getRoot()
    {
        return $this->root;
    }
}
PK��ZC_�hU+U+NSymfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Validator\ViolationMapper;

use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\Util\InheritDataAwareIterator;
use Symfony\Component\PropertyAccess\PropertyPathIterator;
use Symfony\Component\PropertyAccess\PropertyPathBuilder;
use Symfony\Component\PropertyAccess\PropertyPathIteratorInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\Validator\ConstraintViolation;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ViolationMapper implements ViolationMapperInterface
{
    /**
     * @var Boolean
     */
    private $allowNonSynchronized;

    /**
     * {@inheritdoc}
     */
    public function mapViolation(ConstraintViolation $violation, FormInterface $form, $allowNonSynchronized = false)
    {
        $this->allowNonSynchronized = $allowNonSynchronized;

        // The scope is the currently found most specific form that
        // an error should be mapped to. After setting the scope, the
        // mapper will try to continue to find more specific matches in
        // the children of scope. If it cannot, the error will be
        // mapped to this scope.
        $scope = null;

        $violationPath = null;
        $relativePath = null;
        $match = false;

        // Don't create a ViolationPath instance for empty property paths
        if (strlen($violation->getPropertyPath()) > 0) {
            $violationPath = new ViolationPath($violation->getPropertyPath());
            $relativePath = $this->reconstructPath($violationPath, $form);
        }

        // This case happens if the violation path is empty and thus
        // the violation should be mapped to the root form
        if (null === $violationPath) {
            $scope = $form;
        }

        // In general, mapping happens from the root form to the leaf forms
        // First, the rules of the root form are applied to determine
        // the subsequent descendant. The rules of this descendant are then
        // applied to find the next and so on, until we have found the
        // most specific form that matches the violation.

        // If any of the forms found in this process is not synchronized,
        // mapping is aborted. Non-synchronized forms could not reverse
        // transform the value entered by the user, thus any further violations
        // caused by the (invalid) reverse transformed value should be
        // ignored.

        if (null !== $relativePath) {
            // Set the scope to the root of the relative path
            // This root will usually be $form. If the path contains
            // an unmapped form though, the last unmapped form found
            // will be the root of the path.
            $scope = $relativePath->getRoot();
            $it = new PropertyPathIterator($relativePath);

            while ($this->acceptsErrors($scope) && null !== ($child = $this->matchChild($scope, $it))) {
                $scope = $child;
                $it->next();
                $match = true;
            }
        }

        // This case happens if an error happened in the data under a
        // form inheriting its parent data that does not match any of the
        // children of that form.
        if (null !== $violationPath && !$match) {
            // If we could not map the error to anything more specific
            // than the root element, map it to the innermost directly
            // mapped form of the violation path
            // e.g. "children[foo].children[bar].data.baz"
            // Here the innermost directly mapped child is "bar"

            $scope = $form;
            $it = new ViolationPathIterator($violationPath);

            // Note: acceptsErrors() will always return true for forms inheriting
            // their parent data, because these forms can never be non-synchronized
            // (they don't do any data transformation on their own)
            while ($this->acceptsErrors($scope) && $it->valid() && $it->mapsForm()) {
                if (!$scope->has($it->current())) {
                    // Break if we find a reference to a non-existing child
                    break;
                }

                $scope = $scope->get($it->current());
                $it->next();
            }
        }

        // Follow dot rules until we have the final target
        $mapping = $scope->getConfig()->getOption('error_mapping');

        while ($this->acceptsErrors($scope) && isset($mapping['.'])) {
            $dotRule = new MappingRule($scope, '.', $mapping['.']);
            $scope = $dotRule->getTarget();
            $mapping = $scope->getConfig()->getOption('error_mapping');
        }

        // Only add the error if the form is synchronized
        if ($this->acceptsErrors($scope)) {
            $scope->addError(new FormError(
                $violation->getMessage(),
                $violation->getMessageTemplate(),
                $violation->getMessageParameters(),
                $violation->getMessagePluralization()
            ));
        }
    }

    /**
     * Tries to match the beginning of the property path at the
     * current position against the children of the scope.
     *
     * If a matching child is found, it is returned. Otherwise
     * null is returned.
     *
     * @param FormInterface                 $form The form to search.
     * @param PropertyPathIteratorInterface $it   The iterator at its current position.
     *
     * @return null|FormInterface The found match or null.
     */
    private function matchChild(FormInterface $form, PropertyPathIteratorInterface $it)
    {
        // Remember at what property path underneath "data"
        // we are looking. Check if there is a child with that
        // path, otherwise increase path by one more piece
        $chunk = '';
        $foundChild = null;
        $foundAtIndex = 0;

        // Construct mapping rules for the given form
        $rules = array();

        foreach ($form->getConfig()->getOption('error_mapping') as $propertyPath => $targetPath) {
            // Dot rules are considered at the very end
            if ('.' !== $propertyPath) {
                $rules[] = new MappingRule($form, $propertyPath, $targetPath);
            }
        }

        // Skip forms inheriting their parent data when iterating the children
        $childIterator = new \RecursiveIteratorIterator(
            new InheritDataAwareIterator($form)
        );

        // Make the path longer until we find a matching child
        while (true) {
            if (!$it->valid()) {
                return null;
            }

            if ($it->isIndex()) {
                $chunk .= '['.$it->current().']';
            } else {
                $chunk .= ('' === $chunk ? '' : '.').$it->current();
            }

            // Test mapping rules as long as we have any
            foreach ($rules as $key => $rule) {
                /* @var MappingRule $rule */

                // Mapping rule matches completely, terminate.
                if (null !== ($form = $rule->match($chunk))) {
                    return $form;
                }

                // Keep only rules that have $chunk as prefix
                if (!$rule->isPrefix($chunk)) {
                    unset($rules[$key]);
                }
            }

            // Test children unless we already found one
            if (null === $foundChild) {
                foreach ($childIterator as $child) {
                    /* @var FormInterface $child */
                    $childPath = (string) $child->getPropertyPath();

                    // Child found, mark as return value
                    if ($chunk === $childPath) {
                        $foundChild = $child;
                        $foundAtIndex = $it->key();
                    }
                }
            }

            // Add element to the chunk
            $it->next();

            // If we reached the end of the path or if there are no
            // more matching mapping rules, return the found child
            if (null !== $foundChild && (!$it->valid() || count($rules) === 0)) {
                // Reset index in case we tried to find mapping
                // rules further down the path
                $it->seek($foundAtIndex);

                return $foundChild;
            }
        }

        return null;
    }

    /**
     * Reconstructs a property path from a violation path and a form tree.
     *
     * @param  ViolationPath $violationPath The violation path.
     * @param  FormInterface $origin        The root form of the tree.
     *
     * @return RelativePath The reconstructed path.
     */
    private function reconstructPath(ViolationPath $violationPath, FormInterface $origin)
    {
        $propertyPathBuilder = new PropertyPathBuilder($violationPath);
        $it = $violationPath->getIterator();
        $scope = $origin;

        // Remember the current index in the builder
        $i = 0;

        // Expand elements that map to a form (like "children[address]")
        for ($it->rewind(); $it->valid() && $it->mapsForm(); $it->next()) {
            if (!$scope->has($it->current())) {
                // Scope relates to a form that does not exist
                // Bail out
                break;
            }

            // Process child form
            $scope = $scope->get($it->current());

            if ($scope->getConfig()->getInheritData()) {
                // Form inherits its parent data
                // Cut the piece out of the property path and proceed
                $propertyPathBuilder->remove($i);
            } elseif (!$scope->getConfig()->getMapped()) {
                // Form is not mapped
                // Set the form as new origin and strip everything
                // we have so far in the path
                $origin = $scope;
                $propertyPathBuilder->remove(0, $i + 1);
                $i = 0;
            } else {
                /* @var \Symfony\Component\PropertyAccess\PropertyPathInterface $propertyPath */
                $propertyPath = $scope->getPropertyPath();

                if (null === $propertyPath) {
                    // Property path of a mapped form is null
                    // Should not happen, bail out
                    break;
                }

                $propertyPathBuilder->replace($i, 1, $propertyPath);
                $i += $propertyPath->getLength();
            }
        }

        $finalPath = $propertyPathBuilder->getPropertyPath();

        return null !== $finalPath ? new RelativePath($origin, $finalPath) : null;
    }

    /**
     * @param FormInterface $form
     *
     * @return Boolean
     */
    private function acceptsErrors(FormInterface $form)
    {
        return $this->allowNonSynchronized || $form->isSynchronized();
    }
}
PK��Z�k�t==WSymfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapperInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Validator\ViolationMapper;

use Symfony\Component\Form\FormInterface;
use Symfony\Component\Validator\ConstraintViolation;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface ViolationMapperInterface
{
    /**
     * Maps a constraint violation to a form in the form tree under
     * the given form.
     *
     * @param ConstraintViolation $violation The violation to map.
     * @param FormInterface       $form      The root form of the tree
     *                                       to map it to.
     * @param Boolean             $allowNonSynchronized Whether to allow
     *                                       mapping to non-synchronized forms.
     */
    public function mapViolation(ConstraintViolation $violation, FormInterface $form, $allowNonSynchronized = false);
}
PK��Z�-��!!LSymfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPath.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Validator\ViolationMapper;

use Symfony\Component\Form\Exception\OutOfBoundsException;
use Symfony\Component\PropertyAccess\PropertyPath;
use Symfony\Component\PropertyAccess\PropertyPathInterface;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ViolationPath implements \IteratorAggregate, PropertyPathInterface
{
    /**
     * @var array
     */
    private $elements = array();

    /**
     * @var array
     */
    private $isIndex = array();

    /**
     * @var array
     */
    private $mapsForm = array();

    /**
     * @var string
     */
    private $pathAsString = '';

    /**
     * @var integer
     */
    private $length = 0;

    /**
     * Creates a new violation path from a string.
     *
     * @param string $violationPath The property path of a {@link ConstraintViolation}
     *                              object.
     */
    public function __construct($violationPath)
    {
        $path = new PropertyPath($violationPath);
        $elements = $path->getElements();
        $data = false;

        for ($i = 0, $l = count($elements); $i < $l; ++$i) {
            if (!$data) {
                // The element "data" has not yet been passed
                if ('children' === $elements[$i] && $path->isProperty($i)) {
                    // Skip element "children"
                    ++$i;

                    // Next element must exist and must be an index
                    // Otherwise consider this the end of the path
                    if ($i >= $l || !$path->isIndex($i)) {
                        break;
                    }

                    $this->elements[] = $elements[$i];
                    $this->isIndex[] = true;
                    $this->mapsForm[] = true;
                } elseif ('data' === $elements[$i] && $path->isProperty($i)) {
                    // Skip element "data"
                    ++$i;

                    // End of path
                    if ($i >= $l) {
                        break;
                    }

                    $this->elements[] = $elements[$i];
                    $this->isIndex[] = $path->isIndex($i);
                    $this->mapsForm[] = false;
                    $data = true;
                } else {
                    // Neither "children" nor "data" property found
                    // Consider this the end of the path
                    break;
                }
            } else {
                // Already after the "data" element
                // Pick everything as is
                $this->elements[] = $elements[$i];
                $this->isIndex[] = $path->isIndex($i);
                $this->mapsForm[] = false;
            }
        }

        $this->length = count($this->elements);

        $this->buildString();
    }

    /**
     * {@inheritdoc}
     */
    public function __toString()
    {
        return $this->pathAsString;
    }

    /**
     * {@inheritdoc}
     */
    public function getLength()
    {
        return $this->length;
    }

    /**
     * {@inheritdoc}
     */
    public function getParent()
    {
        if ($this->length <= 1) {
            return null;
        }

        $parent = clone $this;

        --$parent->length;
        array_pop($parent->elements);
        array_pop($parent->isIndex);
        array_pop($parent->mapsForm);

        $parent->buildString();

        return $parent;
    }

    /**
     * {@inheritdoc}
     */
    public function getElements()
    {
        return $this->elements;
    }

    /**
     * {@inheritdoc}
     */
    public function getElement($index)
    {
        if (!isset($this->elements[$index])) {
            throw new OutOfBoundsException(sprintf('The index %s is not within the violation path', $index));
        }

        return $this->elements[$index];
    }

    /**
     * {@inheritdoc}
     */
    public function isProperty($index)
    {
        if (!isset($this->isIndex[$index])) {
            throw new OutOfBoundsException(sprintf('The index %s is not within the violation path', $index));
        }

        return !$this->isIndex[$index];
    }

    /**
     * {@inheritdoc}
     */
    public function isIndex($index)
    {
        if (!isset($this->isIndex[$index])) {
            throw new OutOfBoundsException(sprintf('The index %s is not within the violation path', $index));
        }

        return $this->isIndex[$index];
    }

    /**
     * Returns whether an element maps directly to a form.
     *
     * Consider the following violation path:
     *
     * <code>
     * children[address].children[office].data.street
     * </code>
     *
     * In this example, "address" and "office" map to forms, while
     * "street does not.
     *
     * @param  integer $index The element index.
     *
     * @return Boolean Whether the element maps to a form.
     *
     * @throws OutOfBoundsException If the offset is invalid.
     */
    public function mapsForm($index)
    {
        if (!isset($this->mapsForm[$index])) {
            throw new OutOfBoundsException(sprintf('The index %s is not within the violation path', $index));
        }

        return $this->mapsForm[$index];
    }

    /**
     * Returns a new iterator for this path
     *
     * @return ViolationPathIterator
     */
    public function getIterator()
    {
        return new ViolationPathIterator($this);
    }

    /**
     * Builds the string representation from the elements.
     */
    private function buildString()
    {
        $this->pathAsString = '';
        $data = false;

        foreach ($this->elements as $index => $element) {
            if ($this->mapsForm[$index]) {
                $this->pathAsString .= ".children[$element]";
            } elseif (!$data) {
                $this->pathAsString .= '.data'.($this->isIndex[$index] ? "[$element]" : ".$element");
                $data = true;
            } else {
                $this->pathAsString .= $this->isIndex[$index] ? "[$element]" : ".$element";
            }
        }

        if ('' !== $this->pathAsString) {
            // remove leading dot
            $this->pathAsString = substr($this->pathAsString, 1);
        }
    }
}
PK��Zf����
�
JSymfony/Component/Form/Extension/Validator/ViolationMapper/MappingRule.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Validator\ViolationMapper;

use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\Exception\ErrorMappingException;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class MappingRule
{
    /**
     * @var FormInterface
     */
    private $origin;

    /**
     * @var string
     */
    private $propertyPath;

    /**
     * @var string
     */
    private $targetPath;

    public function __construct(FormInterface $origin, $propertyPath, $targetPath)
    {
        $this->origin = $origin;
        $this->propertyPath = $propertyPath;
        $this->targetPath = $targetPath;
    }

    /**
     * @return FormInterface
     */
    public function getOrigin()
    {
        return $this->origin;
    }

    /**
     * Matches a property path against the rule path.
     *
     * If the rule matches, the form mapped by the rule is returned.
     * Otherwise this method returns false.
     *
     * @param  string $propertyPath The property path to match against the rule.
     *
     * @return null|FormInterface The mapped form or null.
     */
    public function match($propertyPath)
    {
        if ($propertyPath === (string) $this->propertyPath) {
            return $this->getTarget();
        }

        return null;
    }

    /**
     * Matches a property path against a prefix of the rule path.
     *
     * @param string $propertyPath The property path to match against the rule.
     *
     * @return Boolean Whether the property path is a prefix of the rule or not.
     */
    public function isPrefix($propertyPath)
    {
        $length = strlen($propertyPath);
        $prefix = substr($this->propertyPath, 0, $length);
        $next = isset($this->propertyPath[$length]) ? $this->propertyPath[$length] : null;

        return $prefix === $propertyPath && ('[' === $next || '.' === $next);
    }

    /**
     * @return FormInterface
     *
     * @throws ErrorMappingException
     */
    public function getTarget()
    {
        $childNames = explode('.', $this->targetPath);
        $target = $this->origin;

        foreach ($childNames as $childName) {
            if (!$target->has($childName)) {
                throw new ErrorMappingException(sprintf('The child "%s" of "%s" mapped by the rule "%s" in "%s" does not exist.', $childName, $target->getName(), $this->targetPath, $this->origin->getName()));
            }
            $target = $target->get($childName);
        }

        return $target;
    }
}
PK��Z�����JSymfony/Component/Form/Extension/Validator/Type/BaseValidatorExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Validator\Type;

use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

/**
 * Encapsulates common logic of {@link FormTypeValidatorExtension} and
 * {@link SubmitTypeValidatorExtension}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
abstract class BaseValidatorExtension extends AbstractTypeExtension
{
    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        // Make sure that validation groups end up as null, closure or array
        $validationGroupsNormalizer = function (Options $options, $groups) {
            if (false === $groups) {
                return array();
            }

            if (empty($groups)) {
                return null;
            }

            if (is_callable($groups)) {
                return $groups;
            }

            return (array) $groups;
        };

        $resolver->setDefaults(array(
            'validation_groups' => null,
        ));

        $resolver->setNormalizers(array(
            'validation_groups' => $validationGroupsNormalizer,
        ));
    }
}
PK��ZeBR�	�	NSymfony/Component/Form/Extension/Validator/Type/FormTypeValidatorExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Validator\Type;

use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapper;
use Symfony\Component\Form\Extension\Validator\EventListener\ValidationListener;
use Symfony\Component\Validator\ValidatorInterface;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class FormTypeValidatorExtension extends BaseValidatorExtension
{
    /**
     * @var ValidatorInterface
     */
    private $validator;

    /**
     * @var ViolationMapper
     */
    private $violationMapper;

    public function __construct(ValidatorInterface $validator)
    {
        $this->validator = $validator;
        $this->violationMapper = new ViolationMapper();
    }

    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->addEventSubscriber(new ValidationListener($this->validator, $this->violationMapper));
    }

    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        parent::setDefaultOptions($resolver);

        // Constraint should always be converted to an array
        $constraintsNormalizer = function (Options $options, $constraints) {
            return is_object($constraints) ? array($constraints) : (array) $constraints;
        };

        $resolver->setDefaults(array(
            'error_mapping'              => array(),
            'constraints'                => array(),
            'cascade_validation'         => false,
            'invalid_message'            => 'This value is not valid.',
            'invalid_message_parameters' => array(),
            'extra_fields_message'       => 'This form should not contain extra fields.',
            'post_max_size_message'      => 'The uploaded file was too large. Please try to upload a smaller file.',
        ));

        $resolver->setNormalizers(array(
            'constraints'       => $constraintsNormalizer,
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getExtendedType()
    {
        return 'form';
    }
}
PK��Z͚>�@@RSymfony/Component/Form/Extension/Validator/Type/RepeatedTypeValidatorExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Validator\Type;

use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class RepeatedTypeValidatorExtension extends AbstractTypeExtension
{
    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        // Map errors to the first field
        $errorMapping = function (Options $options) {
            return array('.' => $options['first_name']);
        };

        $resolver->setDefaults(array(
            'error_mapping' => $errorMapping,
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getExtendedType()
    {
        return 'repeated';
    }
}
PK��Z1���PSymfony/Component/Form/Extension/Validator/Type/SubmitTypeValidatorExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Validator\Type;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class SubmitTypeValidatorExtension extends BaseValidatorExtension
{
    /**
     * {@inheritdoc}
     */
    public function getExtendedType()
    {
        return 'submit';
    }
}
PK��Z���,QQCSymfony/Component/Form/Extension/Templating/TemplatingExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Templating;

use Symfony\Component\Form\AbstractExtension;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter;
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
use Symfony\Component\Form\FormRenderer;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Templating\PhpEngine;
use Symfony\Bundle\FrameworkBundle\Templating\Helper\FormHelper;

/**
 * Integrates the Templating component with the Form library.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class TemplatingExtension extends AbstractExtension
{
    public function __construct(PhpEngine $engine, $csrfTokenManager = null, array $defaultThemes = array())
    {
        if ($csrfTokenManager instanceof CsrfProviderInterface) {
            $csrfTokenManager = new CsrfProviderAdapter($csrfTokenManager);
        } elseif (null !== $csrfTokenManager && !$csrfTokenManager instanceof CsrfTokenManagerInterface) {
            throw new UnexpectedTypeException($csrfTokenManager, 'CsrfProviderInterface or CsrfTokenManagerInterface');
        }

        $engine->addHelpers(array(
            new FormHelper(new FormRenderer(new TemplatingRendererEngine($engine, $defaultThemes), $csrfTokenManager))
        ));
    }
}
PK��Zզ�Y��HSymfony/Component/Form/Extension/Templating/TemplatingRendererEngine.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Templating;

use Symfony\Component\Form\AbstractRendererEngine;
use Symfony\Component\Form\FormView;
use Symfony\Component\Templating\EngineInterface;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class TemplatingRendererEngine extends AbstractRendererEngine
{
    /**
     * @var EngineInterface
     */
    private $engine;

    public function __construct(EngineInterface $engine, array $defaultThemes = array())
    {
        parent::__construct($defaultThemes);

        $this->engine = $engine;
    }

    /**
     * {@inheritdoc}
     */
    public function renderBlock(FormView $view, $resource, $blockName, array $variables = array())
    {
        return trim($this->engine->render($resource, $variables));
    }

    /**
     * Loads the cache with the resource for a given block name.
     *
     * This implementation tries to load as few blocks as possible, since each block
     * is represented by a template on the file system.
     *
     * @see getResourceForBlock()
     *
     * @param string   $cacheKey  The cache key of the form view.
     * @param FormView $view      The form view for finding the applying themes.
     * @param string   $blockName The name of the block to load.
     *
     * @return Boolean True if the resource could be loaded, false otherwise.
     */
    protected function loadResourceForBlockName($cacheKey, FormView $view, $blockName)
    {
        // Recursively try to find the block in the themes assigned to $view,
        // then of its parent form, then of the parent form of the parent and so on.
        // When the root form is reached in this recursion, also the default
        // themes are taken into account.

        // Check each theme whether it contains the searched block
        if (isset($this->themes[$cacheKey])) {
            for ($i = count($this->themes[$cacheKey]) - 1; $i >= 0; --$i) {
                if ($this->loadResourceFromTheme($cacheKey, $blockName, $this->themes[$cacheKey][$i])) {
                    return true;
                }
            }
        }

        // Check the default themes once we reach the root form without success
        if (!$view->parent) {
            for ($i = count($this->defaultThemes) - 1; $i >= 0; --$i) {
                if ($this->loadResourceFromTheme($cacheKey, $blockName, $this->defaultThemes[$i])) {
                    return true;
                }
            }
        }

        // If we did not find anything in the themes of the current view, proceed
        // with the themes of the parent view
        if ($view->parent) {
            $parentCacheKey = $view->parent->vars[self::CACHE_KEY_VAR];

            if (!isset($this->resources[$parentCacheKey][$blockName])) {
                $this->loadResourceForBlockName($parentCacheKey, $view->parent, $blockName);
            }

            // If a template exists in the parent themes, cache that template
            // for the current theme as well to speed up further accesses
            if ($this->resources[$parentCacheKey][$blockName]) {
                $this->resources[$cacheKey][$blockName] = $this->resources[$parentCacheKey][$blockName];

                return true;
            }
        }

        // Cache that we didn't find anything to speed up further accesses
        $this->resources[$cacheKey][$blockName] = false;

        return false;
    }

    /**
     * Tries to load the resource for a block from a theme.
     *
     * @param string $cacheKey  The cache key for storing the resource.
     * @param string $blockName The name of the block to load a resource for.
     * @param mixed  $theme     The theme to load the block from.
     *
     * @return Boolean True if the resource could be loaded, false otherwise.
     */
    protected function loadResourceFromTheme($cacheKey, $blockName, $theme)
    {
        if ($this->engine->exists($templateName = $theme.':'.$blockName.'.html.php')) {
            $this->resources[$cacheKey][$blockName] = $templateName;

            return true;
        }

        return false;
    }
}
PK��Z䋧��USymfony/Component/Form/Extension/HttpFoundation/EventListener/BindRequestListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\HttpFoundation\EventListener;

use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\Exception\LogicException;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Pass the
 *             Request instance to {@link Form::handleRequest()} instead.
 */
class BindRequestListener implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        // High priority in order to supersede other listeners
        return array(FormEvents::PRE_BIND => array('preBind', 128));
    }

    public function preBind(FormEvent $event)
    {
        $form = $event->getForm();

        /* @var Request $request */
        $request = $event->getData();

        // Only proceed if we actually deal with a Request
        if (!$request instanceof Request) {
            return;
        }

        // Uncomment this as soon as the deprecation note should be shown
        // trigger_error('Passing a Request instance to Form::submit() is deprecated since version 2.3 and will be disabled in 3.0. Call Form::process($request) instead.', E_USER_DEPRECATED);

        $name = $form->getConfig()->getName();
        $default = $form->getConfig()->getCompound() ? array() : null;

        // Store the bound data in case of a post request
        switch ($request->getMethod()) {
            case 'POST':
            case 'PUT':
            case 'DELETE':
            case 'PATCH':
                if ('' === $name) {
                    // Form bound without name
                    $params = $request->request->all();
                    $files = $request->files->all();
                } else {
                    $params = $request->request->get($name, $default);
                    $files = $request->files->get($name, $default);
                }

                if (is_array($params) && is_array($files)) {
                    $data = array_replace_recursive($params, $files);
                } else {
                    $data = $params ?: $files;
                }

                break;

            case 'GET':
                $data = '' === $name
                    ? $request->query->all()
                    : $request->query->get($name, $default);

                break;

            default:
                throw new LogicException(sprintf(
                    'The request method "%s" is not supported',
                    $request->getMethod()
                ));
        }

        $event->setData($data);
    }
}
PK��Z�j��=
=
PSymfony/Component/Form/Extension/HttpFoundation/HttpFoundationRequestHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\HttpFoundation;

use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\RequestHandlerInterface;
use Symfony\Component\HttpFoundation\Request;

/**
 * A request processor using the {@link Request} class of the HttpFoundation
 * component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class HttpFoundationRequestHandler implements RequestHandlerInterface
{
    /**
     * {@inheritdoc}
     */
    public function handleRequest(FormInterface $form, $request = null)
    {
        if (!$request instanceof Request) {
            throw new UnexpectedTypeException($request, 'Symfony\Component\HttpFoundation\Request');
        }

        $name = $form->getName();
        $method = $form->getConfig()->getMethod();

        if ($method !== $request->getMethod()) {
            return;
        }

        if ('GET' === $method) {
            if ('' === $name) {
                $data = $request->query->all();
            } else {
                // Don't submit GET requests if the form's name does not exist
                // in the request
                if (!$request->query->has($name)) {
                    return;
                }

                $data = $request->query->get($name);
            }
        } else {
            if ('' === $name) {
                $params = $request->request->all();
                $files = $request->files->all();
            } elseif ($request->request->has($name) || $request->files->has($name)) {
                $default = $form->getConfig()->getCompound() ? array() : null;
                $params = $request->request->get($name, $default);
                $files = $request->files->get($name, $default);
            } else {
                // Don't submit the form if it is not present in the request
                return;
            }

            if (is_array($params) && is_array($files)) {
                $data = array_replace_recursive($params, $files);
            } else {
                $data = $params ?: $files;
            }
        }

        // Don't auto-submit the form unless at least one field is present.
        if ('' === $name && count(array_intersect_key($data, $form->all())) <= 0) {
            return;
        }

        $form->submit($data, 'PATCH' !== $method);
    }
}
PK��Z��Q��KSymfony/Component/Form/Extension/HttpFoundation/HttpFoundationExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\HttpFoundation;

use Symfony\Component\Form\AbstractExtension;

/**
 * Integrates the HttpFoundation component with the Form library.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class HttpFoundationExtension extends AbstractExtension
{
    protected function loadTypeExtensions()
    {
        return array(
            new Type\FormTypeHttpFoundationExtension(),
        );
    }
}
PK��Z�PffXSymfony/Component/Form/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\HttpFoundation\Type;

use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Extension\HttpFoundation\EventListener\BindRequestListener;
use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler;
use Symfony\Component\Form\FormBuilderInterface;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class FormTypeHttpFoundationExtension extends AbstractTypeExtension
{
    /**
     * @var BindRequestListener
     */
    private $listener;

    /**
     * @var HttpFoundationRequestHandler
     */
    private $requestHandler;

    public function __construct()
    {
        $this->listener = new BindRequestListener();
        $this->requestHandler = new HttpFoundationRequestHandler();
    }

    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->addEventSubscriber($this->listener);
        $builder->setRequestHandler($this->requestHandler);
    }

    /**
     * {@inheritdoc}
     */
    public function getExtendedType()
    {
        return 'form';
    }
}
PK��Z"�q���7Symfony/Component/Form/Extension/Csrf/CsrfExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Csrf;

use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter;
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
use Symfony\Component\Form\AbstractExtension;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Translation\TranslatorInterface;

/**
 * This extension protects forms by using a CSRF token.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class CsrfExtension extends AbstractExtension
{
    /**
     * @var CsrfTokenManagerInterface
     */
    private $tokenManager;

    /**
     * @var TranslatorInterface
     */
    private $translator;

    /**
     * @var null|string
     */
    private $translationDomain;

    /**
     * Constructor.
     *
     * @param CsrfTokenManagerInterface $tokenManager      The CSRF token manager
     * @param TranslatorInterface       $translator        The translator for translating error messages
     * @param null|string               $translationDomain The translation domain for translating
     */
    public function __construct($tokenManager, TranslatorInterface $translator = null, $translationDomain = null)
    {
        if ($tokenManager instanceof CsrfProviderInterface) {
            $tokenManager = new CsrfProviderAdapter($tokenManager);
        } elseif (!$tokenManager instanceof CsrfTokenManagerInterface) {
            throw new UnexpectedTypeException($tokenManager, 'CsrfProviderInterface or CsrfTokenManagerInterface');
        }

        $this->tokenManager = $tokenManager;
        $this->translator = $translator;
        $this->translationDomain = $translationDomain;
    }

    /**
     * {@inheritDoc}
     */
    protected function loadTypeExtensions()
    {
        return array(
            new Type\FormTypeCsrfExtension($this->tokenManager, true, '_token', $this->translator, $this->translationDomain),
        );
    }
}
PK��Z�C���JSymfony/Component/Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider;

/**
 * Default implementation of CsrfProviderInterface.
 *
 * This provider uses the session ID returned by session_id() as well as a
 * user-defined secret value to secure the CSRF token.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0. Use
 *             {@link \Symfony\Component\Security\Csrf\CsrfTokenManager} in
 *             combination with {@link \Symfony\Component\Security\Csrf\TokenStorage\NativeSessionTokenStorage}
 *             instead.
 */
class DefaultCsrfProvider implements CsrfProviderInterface
{
    /**
     * A secret value used for generating the CSRF token
     * @var string
     */
    protected $secret;

    /**
     * Initializes the provider with a secret value
     *
     * A recommended value for the secret is a generated value with at least
     * 32 characters and mixed letters, digits and special characters.
     *
     * @param string $secret A secret value included in the CSRF token
     */
    public function __construct($secret)
    {
        $this->secret = $secret;
    }

    /**
     * {@inheritDoc}
     */
    public function generateCsrfToken($intention)
    {
        return sha1($this->secret.$intention.$this->getSessionId());
    }

    /**
     * {@inheritDoc}
     */
    public function isCsrfTokenValid($intention, $token)
    {
        return $token === $this->generateCsrfToken($intention);
    }

    /**
     * Returns the ID of the user session.
     *
     * Automatically starts the session if necessary.
     *
     * @return string The session ID
     */
    protected function getSessionId()
    {
        if (version_compare(PHP_VERSION, '5.4', '>=')) {
            if (PHP_SESSION_NONE === session_status()) {
                session_start();
            }
        } elseif (!session_id()) {
            session_start();
        }

        return session_id();
    }
}
PK��Z[^����JSymfony/Component/Form/Extension/Csrf/CsrfProvider/SessionCsrfProvider.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider;

use Symfony\Component\HttpFoundation\Session\Session;

/**
 * This provider uses a Symfony2 Session object to retrieve the user's
 * session ID.
 *
 * @see DefaultCsrfProvider
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0. Use
 *             {@link \Symfony\Component\Security\Csrf\CsrfTokenManager} in
 *             combination with {@link \Symfony\Component\Security\Csrf\TokenStorage\SessionTokenStorage}
 *             instead.
 */
class SessionCsrfProvider extends DefaultCsrfProvider
{
    /**
     * The user session from which the session ID is returned
     * @var Session
     */
    protected $session;

    /**
     * Initializes the provider with a Session object and a secret value.
     *
     * A recommended value for the secret is a generated value with at least
     * 32 characters and mixed letters, digits and special characters.
     *
     * @param Session $session The user session
     * @param string  $secret  A secret value included in the CSRF token
     */
    public function __construct(Session $session, $secret)
    {
        parent::__construct($secret);

        $this->session = $session;
    }

    /**
     * {@inheritdoc}
     */
    protected function getSessionId()
    {
        $this->session->start();

        return $this->session->getId();
    }
}
PK��Z%�G���LSymfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider;

/**
 * Marks classes able to provide CSRF protection
 *
 * You can generate a CSRF token by using the method generateCsrfToken(). To
 * this method you should pass a value that is unique to the page that should
 * be secured against CSRF attacks. This value doesn't necessarily have to be
 * secret. Implementations of this interface are responsible for adding more
 * secret information.
 *
 * If you want to secure a form submission against CSRF attacks, you could
 * supply an "intention" string. This way you make sure that the form can only
 * be submitted to pages that are designed to handle the form, that is, that use
 * the same intention string to validate the CSRF token with isCsrfTokenValid().
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0. Use
 *             {@link \Symfony\Component\Security\Csrf\CsrfTokenManagerInterface}
 *             instead.
 */
interface CsrfProviderInterface
{
    /**
     * Generates a CSRF token for a page of your application.
     *
     * @param string $intention Some value that identifies the action intention
     *                          (i.e. "authenticate"). Doesn't have to be a secret value.
     *
     * @return string The generated token
     */
    public function generateCsrfToken($intention);

    /**
     * Validates a CSRF token.
     *
     * @param string $intention The intention used when generating the CSRF token
     * @param string $token     The token supplied by the browser
     *
     * @return Boolean Whether the token supplied by the browser is correct
     */
    public function isCsrfTokenValid($intention, $token);
}
PK��Z�����JSymfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderAdapter.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider;

use Symfony\Component\Form\Exception\BadMethodCallException;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;

/**
 * Adapter for using old CSRF providers where the new {@link CsrfTokenManagerInterface}
 * is expected.
 *
 * @since  2.4
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0.
 */
class CsrfProviderAdapter implements CsrfTokenManagerInterface
{
    /**
     * @var CsrfProviderInterface
     */
    private $csrfProvider;

    public function __construct(CsrfProviderInterface $csrfProvider)
    {
        $this->csrfProvider = $csrfProvider;
    }

    public function getCsrfProvider()
    {
        return $this->csrfProvider;
    }

    /**
     * {@inheritdoc}
     */
    public function getToken($tokenId)
    {
        return new CsrfToken($tokenId, $this->csrfProvider->generateCsrfToken($tokenId));
    }

    /**
     * {@inheritdoc}
     */
    public function refreshToken($tokenId)
    {
        throw new BadMethodCallException('Not supported');
    }

    /**
     * {@inheritdoc}
     */
    public function removeToken($tokenId)
    {
        throw new BadMethodCallException('Not supported');
    }

    /**
     * {@inheritdoc}
     */
    public function isTokenValid(CsrfToken $token)
    {
        return $this->csrfProvider->isCsrfTokenValid($token->getId(), $token->getValue());
    }
}
PK��ZR�'WTTNSymfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfTokenManagerAdapter.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider;

use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;

/**
 * Adapter for using the new token generator with the old interface.
 *
 * @since  2.4
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0.
 */
class CsrfTokenManagerAdapter implements CsrfProviderInterface
{
    /**
     * @var CsrfTokenManagerInterface
     */
    private $tokenManager;

    public function __construct(CsrfTokenManagerInterface $tokenManager)
    {
        $this->tokenManager = $tokenManager;
    }

    public function getTokenManager()
    {
        return $this->tokenManager;
    }

    /**
     * {@inheritdoc}
     */
    public function generateCsrfToken($intention)
    {
        return $this->tokenManager->getToken($intention)->getValue();
    }

    /**
     * {@inheritdoc}
     */
    public function isCsrfTokenValid($intention, $token)
    {
        return $this->tokenManager->isTokenValid(new CsrfToken($intention, $token));
    }
}
PK��Z�?�ooNSymfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Csrf\EventListener;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter;
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Translation\TranslatorInterface;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class CsrfValidationListener implements EventSubscriberInterface
{
    /**
     * The name of the CSRF field
     * @var string
     */
    private $fieldName;

    /**
     * The generator for CSRF tokens
     * @var CsrfTokenManagerInterface
     */
    private $tokenManager;

    /**
     * A text mentioning the tokenId of the CSRF token
     *
     * Validation of the token will only succeed if it was generated in the
     * same session and with the same tokenId.
     *
     * @var string
     */
    private $tokenId;

    /**
     * The message displayed in case of an error.
     * @var string
     */
    private $errorMessage;

    /**
     * @var TranslatorInterface
     */
    private $translator;

    /**
     * @var null|string
     */
    private $translationDomain;

    public static function getSubscribedEvents()
    {
        return array(
            FormEvents::PRE_SUBMIT => 'preSubmit',
        );
    }

    public function __construct($fieldName, $tokenManager, $tokenId, $errorMessage, TranslatorInterface $translator = null, $translationDomain = null)
    {
        if ($tokenManager instanceof CsrfProviderInterface) {
            $tokenManager = new CsrfProviderAdapter($tokenManager);
        } elseif (!$tokenManager instanceof CsrfTokenManagerInterface) {
            throw new UnexpectedTypeException($tokenManager, 'CsrfProviderInterface or CsrfTokenManagerInterface');
        }

        $this->fieldName = $fieldName;
        $this->tokenManager = $tokenManager;
        $this->tokenId = $tokenId;
        $this->errorMessage = $errorMessage;
        $this->translator = $translator;
        $this->translationDomain = $translationDomain;
    }

    public function preSubmit(FormEvent $event)
    {
        $form = $event->getForm();
        $data = $event->getData();

        if ($form->isRoot() && $form->getConfig()->getOption('compound')) {
            if (!isset($data[$this->fieldName]) || !$this->tokenManager->isTokenValid(new CsrfToken($this->tokenId, $data[$this->fieldName]))) {
                $errorMessage = $this->errorMessage;

                if (null !== $this->translator) {
                    $errorMessage = $this->translator->trans($errorMessage, array(), $this->translationDomain);
                }

                $form->addError(new FormError($errorMessage));
            }

            if (is_array($data)) {
                unset($data[$this->fieldName]);
            }
        }

        $event->setData($data);
    }

    /**
     * Alias of {@link preSubmit()}.
     *
     * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
     *             {@link preSubmit()} instead.
     */
    public function preBind(FormEvent $event)
    {
        $this->preSubmit($event);
    }
}
PK��Z��
f��DSymfony/Component/Form/Extension/Csrf/Type/FormTypeCsrfExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Csrf\Type;

use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter;
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfTokenManagerAdapter;
use Symfony\Component\Form\Extension\Csrf\EventListener\CsrfValidationListener;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Translation\TranslatorInterface;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class FormTypeCsrfExtension extends AbstractTypeExtension
{
    /**
     * @var CsrfTokenManagerInterface
     */
    private $defaultTokenManager;

    /**
     * @var Boolean
     */
    private $defaultEnabled;

    /**
     * @var string
     */
    private $defaultFieldName;

    /**
     * @var TranslatorInterface
     */
    private $translator;

    /**
     * @var null|string
     */
    private $translationDomain;

    public function __construct($defaultTokenManager, $defaultEnabled = true, $defaultFieldName = '_token', TranslatorInterface $translator = null, $translationDomain = null)
    {
        if ($defaultTokenManager instanceof CsrfProviderInterface) {
            $defaultTokenManager = new CsrfProviderAdapter($defaultTokenManager);
        } elseif (!$defaultTokenManager instanceof CsrfTokenManagerInterface) {
            throw new UnexpectedTypeException($defaultTokenManager, 'CsrfProviderInterface or CsrfTokenManagerInterface');
        }

        $this->defaultTokenManager = $defaultTokenManager;
        $this->defaultEnabled = $defaultEnabled;
        $this->defaultFieldName = $defaultFieldName;
        $this->translator = $translator;
        $this->translationDomain = $translationDomain;
    }

    /**
     * Adds a CSRF field to the form when the CSRF protection is enabled.
     *
     * @param FormBuilderInterface $builder The form builder
     * @param array                $options The options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        if (!$options['csrf_protection']) {
            return;
        }

        $builder
            ->addEventSubscriber(new CsrfValidationListener(
                $options['csrf_field_name'],
                $options['csrf_token_manager'],
                $options['csrf_token_id'] ?: ($builder->getName() ?: get_class($builder->getType()->getInnerType())),
                $options['csrf_message'],
                $this->translator,
                $this->translationDomain
            ))
        ;
    }

    /**
     * Adds a CSRF field to the root form view.
     *
     * @param FormView      $view    The form view
     * @param FormInterface $form    The form
     * @param array         $options The options
     */
    public function finishView(FormView $view, FormInterface $form, array $options)
    {
        if ($options['csrf_protection'] && !$view->parent && $options['compound']) {
            $factory = $form->getConfig()->getFormFactory();
            $tokenId = $options['csrf_token_id'] ?: ($form->getName() ?: get_class($form->getConfig()->getType()->getInnerType()));
            $data = (string) $options['csrf_token_manager']->getToken($tokenId);

            $csrfForm = $factory->createNamed($options['csrf_field_name'], 'hidden', $data, array(
                'mapped' => false,
            ));

            $view->children[$options['csrf_field_name']] = $csrfForm->createView($view);
        }
    }

    /**
     * {@inheritDoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        // BC clause for the "intention" option
        $csrfTokenId = function (Options $options) {
            return $options['intention'];
        };

        // BC clause for the "csrf_provider" option
        $csrfTokenManager = function (Options $options) {
            return $options['csrf_provider'] instanceof CsrfTokenManagerAdapter
                ? $options['csrf_provider']->getTokenManager()
                : new CsrfProviderAdapter($options['csrf_provider']);
        };

        $resolver->setDefaults(array(
            'csrf_protection'    => $this->defaultEnabled,
            'csrf_field_name'    => $this->defaultFieldName,
            'csrf_message'       => 'The CSRF token is invalid. Please try to resubmit the form.',
            'csrf_token_manager' => $csrfTokenManager,
            'csrf_token_id'      => $csrfTokenId,
            'csrf_provider'      => new CsrfTokenManagerAdapter($this->defaultTokenManager),
            'intention'          => null,
        ));
    }

    /**
     * {@inheritDoc}
     */
    public function getExtendedType()
    {
        return 'form';
    }
}
PK��ZC�W���7Symfony/Component/Form/Extension/Core/CoreExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core;

use Symfony\Component\Form\AbstractExtension;
use Symfony\Component\PropertyAccess\PropertyAccess;

/**
 * Represents the main form extension, which loads the core functionality.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class CoreExtension extends AbstractExtension
{
    protected function loadTypes()
    {
        return array(
            new Type\FormType(PropertyAccess::createPropertyAccessor()),
            new Type\BirthdayType(),
            new Type\CheckboxType(),
            new Type\ChoiceType(),
            new Type\CollectionType(),
            new Type\CountryType(),
            new Type\DateType(),
            new Type\DateTimeType(),
            new Type\EmailType(),
            new Type\HiddenType(),
            new Type\IntegerType(),
            new Type\LanguageType(),
            new Type\LocaleType(),
            new Type\MoneyType(),
            new Type\NumberType(),
            new Type\PasswordType(),
            new Type\PercentType(),
            new Type\RadioType(),
            new Type\RepeatedType(),
            new Type\SearchType(),
            new Type\TextareaType(),
            new Type\TextType(),
            new Type\TimeType(),
            new Type\TimezoneType(),
            new Type\UrlType(),
            new Type\FileType(),
            new Type\ButtonType(),
            new Type\SubmitType(),
            new Type\ResetType(),
            new Type\CurrencyType(),
        );
    }
}
PK��Z�:AADSymfony/Component/Form/Extension/Core/EventListener/TrimListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\EventListener;

use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Trims string data
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class TrimListener implements EventSubscriberInterface
{
    public function preSubmit(FormEvent $event)
    {
        $data = $event->getData();

        if (!is_string($data)) {
            return;
        }

        if (null !== $result = @preg_replace('/^[\pZ\p{Cc}]+|[\pZ\p{Cc}]+$/u', '', $data)) {
            $event->setData($result);
        } else {
            $event->setData(trim($data));
        }
    }

    /**
     * Alias of {@link preSubmit()}.
     *
     * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
     *             {@link preSubmit()} instead.
     */
    public function preBind(FormEvent $event)
    {
        $this->preSubmit($event);
    }

    public static function getSubscribedEvents()
    {
        return array(FormEvents::PRE_SUBMIT => 'preSubmit');
    }
}
PK��Zõe��OSymfony/Component/Form/Extension/Core/EventListener/MergeCollectionListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\EventListener;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\Exception\UnexpectedTypeException;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class MergeCollectionListener implements EventSubscriberInterface
{
    /**
     * Whether elements may be added to the collection
     * @var Boolean
     */
    private $allowAdd;

    /**
     * Whether elements may be removed from the collection
     * @var Boolean
     */
    private $allowDelete;

    /**
     * Creates a new listener.
     *
     * @param Boolean $allowAdd Whether values might be added to the
     *                                collection.
     * @param Boolean $allowDelete Whether values might be removed from the
     *                                collection.
     */
    public function __construct($allowAdd = false, $allowDelete = false)
    {
        $this->allowAdd = $allowAdd;
        $this->allowDelete = $allowDelete;
    }

    public static function getSubscribedEvents()
    {
        return array(
            FormEvents::SUBMIT => 'onSubmit',
        );
    }

    public function onSubmit(FormEvent $event)
    {
        $dataToMergeInto = $event->getForm()->getNormData();
        $data = $event->getData();

        if (null === $data) {
            $data = array();
        }

        if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) {
            throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)');
        }

        if (null !== $dataToMergeInto && !is_array($dataToMergeInto) && !($dataToMergeInto instanceof \Traversable && $dataToMergeInto instanceof \ArrayAccess)) {
            throw new UnexpectedTypeException($dataToMergeInto, 'array or (\Traversable and \ArrayAccess)');
        }

        // If we are not allowed to change anything, return immediately
        if ((!$this->allowAdd && !$this->allowDelete) || $data === $dataToMergeInto) {
            $event->setData($dataToMergeInto);

            return;
        }

        if (!$dataToMergeInto) {
            // No original data was set. Set it if allowed
            if ($this->allowAdd) {
                $dataToMergeInto = $data;
            }
        } else {
            // Calculate delta
            $itemsToAdd = is_object($data) ? clone $data : $data;
            $itemsToDelete = array();

            foreach ($dataToMergeInto as $beforeKey => $beforeItem) {
                foreach ($data as $afterKey => $afterItem) {
                    if ($afterItem === $beforeItem) {
                        // Item found, next original item
                        unset($itemsToAdd[$afterKey]);
                        continue 2;
                    }
                }

                // Item not found, remember for deletion
                $itemsToDelete[] = $beforeKey;
            }

            // Remove deleted items before adding to free keys that are to be
            // replaced
            if ($this->allowDelete) {
                foreach ($itemsToDelete as $key) {
                    unset($dataToMergeInto[$key]);
                }
            }

            // Add remaining items
            if ($this->allowAdd) {
                foreach ($itemsToAdd as $key => $item) {
                    if (!isset($dataToMergeInto[$key])) {
                        $dataToMergeInto[$key] = $item;
                    } else {
                        $dataToMergeInto[] = $item;
                    }
                }
            }
        }

        $event->setData($dataToMergeInto);
    }

    /**
     * Alias of {@link onSubmit()}.
     *
     * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
     *             {@link onSubmit()} instead.
     */
    public function onBind(FormEvent $event)
    {
        $this->onSubmit($event);
    }
}
PK��Z>Q?��NSymfony/Component/Form/Extension/Core/EventListener/FixUrlProtocolListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\EventListener;

use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Adds a protocol to a URL if it doesn't already have one.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class FixUrlProtocolListener implements EventSubscriberInterface
{
    private $defaultProtocol;

    public function __construct($defaultProtocol = 'http')
    {
        $this->defaultProtocol = $defaultProtocol;
    }

    public function onSubmit(FormEvent $event)
    {
        $data = $event->getData();

        if ($this->defaultProtocol && $data && !preg_match('~^\w+://~', $data)) {
            $event->setData($this->defaultProtocol.'://'.$data);
        }
    }

    /**
     * Alias of {@link onSubmit()}.
     *
     * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
     *             {@link onSubmit()} instead.
     */
    public function onBind(FormEvent $event)
    {
        $this->onSubmit($event);
    }

    public static function getSubscribedEvents()
    {
        return array(FormEvents::SUBMIT => 'onSubmit');
    }
}
PK��Zb����PSymfony/Component/Form/Extension/Core/EventListener/FixCheckboxInputListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\EventListener;

use Symfony\Component\Form\Exception\TransformationFailedException;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface;

/**
 * Takes care of converting the input from a list of checkboxes to a correctly
 * indexed array.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class FixCheckboxInputListener implements EventSubscriberInterface
{
    private $choiceList;

    /**
     * Constructor.
     *
     * @param ChoiceListInterface $choiceList
     */
    public function __construct(ChoiceListInterface $choiceList)
    {
        $this->choiceList = $choiceList;
    }

    public function preSubmit(FormEvent $event)
    {
        $data = $event->getData();

        if (is_array($data)) {
            // Flip the submitted values for faster lookup
            // It's better to flip this array than $existingValues because
            // $submittedValues is generally smaller.
            $submittedValues = array_flip($data);

            // Since expanded choice fields are completely loaded anyway, we
            // can just as well get the values again without losing performance.
            $existingValues = $this->choiceList->getValues();

            // Clear the data array and fill it with correct indices
            $data = array();

            foreach ($existingValues as $index => $value) {
                if (isset($submittedValues[$value])) {
                    // Value was submitted
                    $data[$index] = $value;
                    unset($submittedValues[$value]);
                }
            }

            if (count($submittedValues) > 0) {
                throw new TransformationFailedException(sprintf(
                    'The following choices were not found: "%s"',
                    implode('", "', array_keys($submittedValues))
                ));
            }
        } elseif ('' === $data || null === $data) {
            // Empty values are always accepted.
            $data = array();
        }

        // Else leave the data unchanged to provoke an error during submission

        $event->setData($data);
    }

    /**
     * Alias of {@link preSubmit()}.
     *
     * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
     *             {@link preSubmit()} instead.
     */
    public function preBind(FormEvent $event)
    {
        $this->preSubmit($event);
    }

    public static function getSubscribedEvents()
    {
        return array(FormEvents::PRE_SUBMIT => 'preSubmit');
    }
}
PK��Z\��//JSymfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\EventListener;

use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Resize a collection form element based on the data sent from the client.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ResizeFormListener implements EventSubscriberInterface
{
    /**
     * @var string
     */
    protected $type;

    /**
     * @var array
     */
    protected $options;

    /**
     * Whether children could be added to the group
     * @var Boolean
     */
    protected $allowAdd;

    /**
     * Whether children could be removed from the group
     * @var Boolean
     */
    protected $allowDelete;

    public function __construct($type, array $options = array(), $allowAdd = false, $allowDelete = false)
    {
        $this->type = $type;
        $this->allowAdd = $allowAdd;
        $this->allowDelete = $allowDelete;
        $this->options = $options;
    }

    public static function getSubscribedEvents()
    {
        return array(
            FormEvents::PRE_SET_DATA => 'preSetData',
            FormEvents::PRE_SUBMIT => 'preSubmit',
            // (MergeCollectionListener, MergeDoctrineCollectionListener)
            FormEvents::SUBMIT => array('onSubmit', 50),
        );
    }

    public function preSetData(FormEvent $event)
    {
        $form = $event->getForm();
        $data = $event->getData();

        if (null === $data) {
            $data = array();
        }

        if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) {
            throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)');
        }

        // First remove all rows
        foreach ($form as $name => $child) {
            $form->remove($name);
        }

        // Then add all rows again in the correct order
        foreach ($data as $name => $value) {
            $form->add($name, $this->type, array_replace(array(
                'property_path' => '['.$name.']',
            ), $this->options));
        }
    }

    public function preSubmit(FormEvent $event)
    {
        $form = $event->getForm();
        $data = $event->getData();

        if (null === $data || '' === $data) {
            $data = array();
        }

        if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) {
            throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)');
        }

        // Remove all empty rows
        if ($this->allowDelete) {
            foreach ($form as $name => $child) {
                if (!isset($data[$name])) {
                    $form->remove($name);
                }
            }
        }

        // Add all additional rows
        if ($this->allowAdd) {
            foreach ($data as $name => $value) {
                if (!$form->has($name)) {
                    $form->add($name, $this->type, array_replace(array(
                        'property_path' => '['.$name.']',
                    ), $this->options));
                }
            }
        }
    }

    public function onSubmit(FormEvent $event)
    {
        $form = $event->getForm();
        $data = $event->getData();

        if (null === $data) {
            $data = array();
        }

        if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) {
            throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)');
        }

        // The data mapper only adds, but does not remove items, so do this
        // here
        if ($this->allowDelete) {
            $toDelete = array();

            foreach ($data as $name => $child) {
                if (!$form->has($name)) {
                    $toDelete[] = $name;
                }
            }

            foreach ($toDelete as $name) {
                unset($data[$name]);
            }
        }

        $event->setData($data);
    }

    /**
     * Alias of {@link preSubmit()}.
     *
     * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
     *             {@link preSubmit()} instead.
     */
    public function preBind(FormEvent $event)
    {
        $this->preSubmit($event);
    }

    /**
     * Alias of {@link onSubmit()}.
     *
     * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
     *             {@link onSubmit()} instead.
     */
    public function onBind(FormEvent $event)
    {
        $this->onSubmit($event);
    }
}
PK��Z?D���MSymfony/Component/Form/Extension/Core/EventListener/FixRadioInputListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\EventListener;

use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface;

/**
 * Takes care of converting the input from a single radio button
 * to an array.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class FixRadioInputListener implements EventSubscriberInterface
{
    private $choiceList;

    private $placeholderPresent;

    /**
     * Constructor.
     *
     * @param ChoiceListInterface $choiceList
     * @param Boolean             $placeholderPresent
     */
    public function __construct(ChoiceListInterface $choiceList, $placeholderPresent)
    {
        $this->choiceList = $choiceList;
        $this->placeholderPresent = $placeholderPresent;
    }

    public function preSubmit(FormEvent $event)
    {
        $data = $event->getData();

        // Since expanded choice fields are completely loaded anyway, we
        // can just as well get the values again without losing performance.
        $existingValues = $this->choiceList->getValues();

        if (false !== ($index = array_search($data, $existingValues, true))) {
            $data = array($index => $data);
        } elseif ('' === $data || null === $data) {
            // Empty values are always accepted.
            $data = $this->placeholderPresent ? array('placeholder' => '') : array();
        }

        // Else leave the data unchanged to provoke an error during submission

        $event->setData($data);
    }

    /**
     * Alias of {@link preSubmit()}.
     *
     * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
     *             {@link preSubmit()} instead.
     */
    public function preBind(FormEvent $event)
    {
        $this->preSubmit($event);
    }

    public static function getSubscribedEvents()
    {
        return array(FormEvents::PRE_SUBMIT => 'preSubmit');
    }
}
PK��Z�jю��ESymfony/Component/Form/Extension/Core/ChoiceList/SimpleChoiceList.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\ChoiceList;

/**
 * A choice list for choices of type string or integer.
 *
 * Choices and their associated labels can be passed in a single array. Since
 * choices are passed as array keys, only strings or integer choices are
 * allowed. Choices may also be given as hierarchy of unlimited depth by
 * creating nested arrays. The title of the sub-hierarchy can be stored in the
 * array key pointing to the nested array.
 *
 * <code>
 * $choiceList = new SimpleChoiceList(array(
 *     'creditcard' => 'Credit card payment',
 *     'cash' => 'Cash payment',
 * ));
 * </code>
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class SimpleChoiceList extends ChoiceList
{
    /**
     * Creates a new simple choice list.
     *
     * @param array $choices The array of choices with the choices as keys and
     *                       the labels as values. Choices may also be given
     *                       as hierarchy of unlimited depth by creating nested
     *                       arrays. The title of the sub-hierarchy is stored
     *                       in the array key pointing to the nested array.
     * @param array $preferredChoices A flat array of choices that should be
     *                                presented to the user with priority.
     */
    public function __construct(array $choices, array $preferredChoices = array())
    {
        // Flip preferred choices to speed up lookup
        parent::__construct($choices, $choices, array_flip($preferredChoices));
    }

    /**
     * {@inheritdoc}
     */
    public function getChoicesForValues(array $values)
    {
        $values = $this->fixValues($values);

        // The values are identical to the choices, so we can just return them
        // to improve performance a little bit
        return $this->fixChoices(array_intersect($values, $this->getValues()));
    }

    /**
     * {@inheritdoc}
     */
    public function getValuesForChoices(array $choices)
    {
        $choices = $this->fixChoices($choices);

        // The choices are identical to the values, so we can just return them
        // to improve performance a little bit
        return $this->fixValues(array_intersect($choices, $this->getValues()));
    }

    /**
     * Recursively adds the given choices to the list.
     *
     * Takes care of splitting the single $choices array passed in the
     * constructor into choices and labels.
     *
     * @param array              $bucketForPreferred The bucket where to store the preferred
     *                                               view objects.
     * @param array              $bucketForRemaining The bucket where to store the
     *                                               non-preferred view objects.
     * @param array|\Traversable $choices            The list of choices.
     * @param array              $labels             Ignored.
     * @param array              $preferredChoices   The preferred choices.
     */
    protected function addChoices(array &$bucketForPreferred, array &$bucketForRemaining, $choices, array $labels, array $preferredChoices)
    {
        // Add choices to the nested buckets
        foreach ($choices as $choice => $label) {
            if (is_array($label)) {
                // Don't do the work if the array is empty
                if (count($label) > 0) {
                    $this->addChoiceGroup(
                        $choice,
                        $bucketForPreferred,
                        $bucketForRemaining,
                        $label,
                        $label,
                        $preferredChoices
                    );
                }
            } else {
                $this->addChoice(
                    $bucketForPreferred,
                    $bucketForRemaining,
                    $choice,
                    $label,
                    $preferredChoices
                );
            }
        }
    }

    /**
     * Returns whether the given choice should be preferred judging by the
     * given array of preferred choices.
     *
     * Optimized for performance by treating the preferred choices as array
     * where choices are stored in the keys.
     *
     * @param mixed $choice           The choice to test.
     * @param array $preferredChoices An array of preferred choices.
     *
     * @return Boolean Whether the choice is preferred.
     */
    protected function isPreferred($choice, array $preferredChoices)
    {
        // Optimize performance over the default implementation
        return isset($preferredChoices[$choice]);
    }

    /**
     * Converts the choice to a valid PHP array key.
     *
     * @param mixed $choice The choice
     *
     * @return string|integer A valid PHP array key
     */
    protected function fixChoice($choice)
    {
        return $this->fixIndex($choice);
    }

    /**
     * {@inheritdoc}
     */
    protected function fixChoices(array $choices)
    {
        return $this->fixIndices($choices);
    }

    /**
     * {@inheritdoc}
     */
    protected function createValue($choice)
    {
        // Choices are guaranteed to be unique and scalar, so we can simply
        // convert them to strings
        return (string) $choice;
    }
}
PK��Z�
�##ESymfony/Component/Form/Extension/Core/ChoiceList/ObjectChoiceList.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Form\Extension\Core\ChoiceList;

use Symfony\Component\Form\Exception\StringCastException;
use Symfony\Component\Form\Exception\InvalidArgumentException;
use Symfony\Component\PropertyAccess\PropertyPath;
use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;

/**
 * A choice list for object choices.
 *
 * Supports generation of choice labels, choice groups and choice values
 * by calling getters of the object (or associated objects).
 *
 * <code>
 * $choices = array($user1, $user2);
 *
 * // call getName() to determine the choice labels
 * $choiceList = new ObjectChoiceList($choices, 'name');
 * </code>
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ObjectChoiceList extends ChoiceList
{
    /**
     * @var PropertyAccessorInterface
     */
    private $propertyAccessor;

    /**
     * The property path used to obtain the choice label.
     *
     * @var PropertyPath
     */
    private $labelPath;

    /**
     * The property path used for object grouping.
     *
     * @var PropertyPath
     */
    private $groupPath;

    /**
     * The property path used to obtain the choice value.
     *
     * @var PropertyPath
     */
    private $valuePath;

    /**
     * Creates a new object choice list.
     *
     * @param array|\Traversable       $choices           The array of choices. Choices may also be given
     *                                                    as hierarchy of unlimited depth by creating nested
     *                                                    arrays. The title of the sub-hierarchy can be
     *                                                    stored in the array key pointing to the nested
     *                                                    array. The topmost level of the hierarchy may also
     *                                                    be a \Traversable.
     * @param string                   $labelPath         A property path pointing to the property used
     *                                                    for the choice labels. The value is obtained
             *                                            by calling the getter on the object. If the
     *                                                    path is NULL, the object's __toString() method
     *                                                    is used instead.
     * @param array                    $preferredChoices  A flat array of choices that should be
     *                                                    presented to the user with priority.
     * @param string                   $groupPath         A property path pointing to the property used
     *                                                    to group the choices. Only allowed if
     *                                                    the choices are given as flat array.
     * @param string                   $valuePath         A property path pointing to the property used
     *                                                    for the choice values. If not given, integers
     *                                                    are generated instead.
     * @param PropertyAccessorInterface $propertyAccessor The reflection graph for reading property paths.
     */
    public function __construct($choices, $labelPath = null, array $preferredChoices = array(), $groupPath = null, $valuePath = null, PropertyAccessorInterface $propertyAccessor = null)
    {
        $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor();
        $this->labelPath = null !== $labelPath ? new PropertyPath($labelPath) : null;
        $this->groupPath = null !== $groupPath ? new PropertyPath($groupPath) : null;
        $this->valuePath = null !== $valuePath ? new PropertyPath($valuePath) : null;

        parent::__construct($choices, array(), $preferredChoices);
    }

    /**
     * Initializes the list with choices.
     *
     * Safe to be called multiple times. The list is cleared on every call.
     *
     * @param array|\Traversable $choices          The choices to write into the list.
     * @param array              $labels           Ignored.
     * @param array              $preferredChoices The choices to display with priority.
     *
     * @throws InvalidArgumentException When passing a hierarchy of choices and using
     *                                   the "groupPath" option at the same time.
     */
    protected function initialize($choices, array $labels, array $preferredChoices)
    {
        if (null !== $this->groupPath) {
            $groupedChoices = array();

            foreach ($choices as $i => $choice) {
                if (is_array($choice)) {
                    throw new InvalidArgumentException('You should pass a plain object array (without groups) when using the "groupPath" option.');
                }

                try {
                    $group = $this->propertyAccessor->getValue($choice, $this->groupPath);
                } catch (NoSuchPropertyException $e) {
                    // Don't group items whose group property does not exist
                    // see https://github.com/symfony/symfony/commit/d9b7abb7c7a0f28e0ce970afc5e305dce5dccddf
                    $group = null;
                }

                if (null === $group) {
                    $groupedChoices[$i] = $choice;
                } else {
                    $groupName = (string) $group;

                    if (!isset($groupedChoices[$groupName])) {
                        $groupedChoices[$groupName] = array();
                    }

                    $groupedChoices[$groupName][$i] = $choice;
                }
            }

            $choices = $groupedChoices;
        }

        $labels = array();

        $this->extractLabels($choices, $labels);

        parent::initialize($choices, $labels, $preferredChoices);
    }

    /**
     * Creates a new unique value for this choice.
     *
     * If a property path for the value was given at object creation,
     * the getter behind that path is now called to obtain a new value.
     * Otherwise a new integer is generated.
     *
     * @param mixed $choice The choice to create a value for
     *
     * @return integer|string A unique value without character limitations.
     */
    protected function createValue($choice)
    {
        if ($this->valuePath) {
            return (string) $this->propertyAccessor->getValue($choice, $this->valuePath);
        }

        return parent::createValue($choice);
    }

    private function extractLabels($choices, array &$labels)
    {
        foreach ($choices as $i => $choice) {
            if (is_array($choice)) {
                $labels[$i] = array();
                $this->extractLabels($choice, $labels[$i]);
            } elseif ($this->labelPath) {
                $labels[$i] = $this->propertyAccessor->getValue($choice, $this->labelPath);
            } elseif (method_exists($choice, '__toString')) {
                $labels[$i] = (string) $choice;
            } else {
                throw new StringCastException(sprintf('A "__toString()" method was not found on the objects of type "%s" passed to the choice field. To read a custom getter instead, set the argument $labelPath to the desired property path.', get_class($choice)));
            }
        }
    }
}
PK��Zl_R(HSymfony/Component/Form/Extension/Core/ChoiceList/ChoiceListInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\ChoiceList;

/**
 * Contains choices that can be selected in a form field.
 *
 * Each choice has three different properties:
 *
 *    - Choice: The choice that should be returned to the application by the
 *              choice field. Can be any scalar value or an object, but no
 *              array.
 *    - Label:  A text representing the choice that is displayed to the user.
 *    - Value:  A uniquely identifying value that can contain arbitrary
 *              characters, but no arrays or objects. This value is displayed
 *              in the HTML "value" attribute.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface ChoiceListInterface
{
    /**
     * Returns the list of choices
     *
     * @return array The choices with their indices as keys
     */
    public function getChoices();

    /**
     * Returns the values for the choices
     *
     * @return array The values with the corresponding choice indices as keys
     */
    public function getValues();

    /**
     * Returns the choice views of the preferred choices as nested array with
     * the choice groups as top-level keys.
     *
     * Example:
     *
     * <source>
     * array(
     *     'Group 1' => array(
     *         10 => ChoiceView object,
     *         20 => ChoiceView object,
     *     ),
     *     'Group 2' => array(
     *         30 => ChoiceView object,
     *     ),
     * )
     * </source>
     *
     * @return array A nested array containing the views with the corresponding
     *               choice indices as keys on the lowest levels and the choice
     *               group names in the keys of the higher levels
     */
    public function getPreferredViews();

    /**
     * Returns the choice views of the choices that are not preferred as nested
     * array with the choice groups as top-level keys.
     *
     * Example:
     *
     * <source>
     * array(
     *     'Group 1' => array(
     *         10 => ChoiceView object,
     *         20 => ChoiceView object,
     *     ),
     *     'Group 2' => array(
     *         30 => ChoiceView object,
     *     ),
     * )
     * </source>
     *
     * @return array A nested array containing the views with the corresponding
     *               choice indices as keys on the lowest levels and the choice
     *               group names in the keys of the higher levels
     *
     * @see getPreferredValues
     */
    public function getRemainingViews();

    /**
     * Returns the choices corresponding to the given values.
     *
     * The choices can have any data type.
     *
     * The choices must be returned with the same keys and in the same order
     * as the corresponding values in the given array.
     *
     * @param array $values An array of choice values. Not existing values in
     *                      this array are ignored
     *
     * @return array An array of choices with ascending, 0-based numeric keys
     */
    public function getChoicesForValues(array $values);

    /**
     * Returns the values corresponding to the given choices.
     *
     * The values must be strings.
     *
     * The values must be returned with the same keys and in the same order
     * as the corresponding choices in the given array.
     *
     * @param array $choices An array of choices. Not existing choices in this
     *                       array are ignored
     *
     * @return array An array of choice values with ascending, 0-based numeric
     *               keys
     */
    public function getValuesForChoices(array $choices);

    /**
     * Returns the indices corresponding to the given choices.
     *
     * The indices must be positive integers or strings accepted by
     * {@link FormConfigBuilder::validateName()}.
     *
     * The index "placeholder" is internally reserved.
     *
     * The indices must be returned with the same keys and in the same order
     * as the corresponding choices in the given array.
     *
     * @param array $choices An array of choices. Not existing choices in this
     *                       array are ignored
     *
     * @return array An array of indices with ascending, 0-based numeric keys
     *
     * @deprecated Deprecated since version 2.4, to be removed in 3.0.
     */
    public function getIndicesForChoices(array $choices);

    /**
     * Returns the indices corresponding to the given values.
     *
     * The indices must be positive integers or strings accepted by
     * {@link FormConfigBuilder::validateName()}.
     *
     * The index "placeholder" is internally reserved.
     *
     * The indices must be returned with the same keys and in the same order
     * as the corresponding values in the given array.
     *
     * @param array $values An array of choice values. Not existing values in
     *                      this array are ignored
     *
     * @return array An array of indices with ascending, 0-based numeric keys
     *
     * @deprecated Deprecated since version 2.4, to be removed in 3.0.
     */
    public function getIndicesForValues(array $values);
}
PK��Z�В4
4
CSymfony/Component/Form/Extension/Core/ChoiceList/LazyChoiceList.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\ChoiceList;

use Symfony\Component\Form\Exception\InvalidArgumentException;

/**
 * A choice list that is loaded lazily
 *
 * This list loads itself as soon as any of the getters is accessed for the
 * first time. You should implement loadChoiceList() in your child classes,
 * which should return a ChoiceListInterface instance.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
abstract class LazyChoiceList implements ChoiceListInterface
{
    /**
     * The loaded choice list
     *
     * @var ChoiceListInterface
     */
    private $choiceList;

    /**
     * {@inheritdoc}
     */
    public function getChoices()
    {
        if (!$this->choiceList) {
            $this->load();
        }

        return $this->choiceList->getChoices();
    }

    /**
     * {@inheritdoc}
     */
    public function getValues()
    {
        if (!$this->choiceList) {
            $this->load();
        }

        return $this->choiceList->getValues();
    }

    /**
     * {@inheritdoc}
     */
    public function getPreferredViews()
    {
        if (!$this->choiceList) {
            $this->load();
        }

        return $this->choiceList->getPreferredViews();
    }

    /**
     * {@inheritdoc}
     */
    public function getRemainingViews()
    {
        if (!$this->choiceList) {
            $this->load();
        }

        return $this->choiceList->getRemainingViews();
    }

    /**
     * {@inheritdoc}
     */
    public function getChoicesForValues(array $values)
    {
        if (!$this->choiceList) {
            $this->load();
        }

        return $this->choiceList->getChoicesForValues($values);
    }

    /**
     * {@inheritdoc}
     */
    public function getValuesForChoices(array $choices)
    {
        if (!$this->choiceList) {
            $this->load();
        }

        return $this->choiceList->getValuesForChoices($choices);
    }

    /**
     * {@inheritdoc}
     *
     * @deprecated Deprecated since version 2.4, to be removed in 3.0.
     */
    public function getIndicesForChoices(array $choices)
    {
        if (!$this->choiceList) {
            $this->load();
        }

        return $this->choiceList->getIndicesForChoices($choices);
    }

    /**
     * {@inheritdoc}
     *
     * @deprecated Deprecated since version 2.4, to be removed in 3.0.
     */
    public function getIndicesForValues(array $values)
    {
        if (!$this->choiceList) {
            $this->load();
        }

        return $this->choiceList->getIndicesForValues($values);
    }

    /**
     * Loads the choice list
     *
     * Should be implemented by child classes.
     *
     * @return ChoiceListInterface The loaded choice list
     */
    abstract protected function loadChoiceList();

    private function load()
    {
        $choiceList = $this->loadChoiceList();

        if (!$choiceList instanceof ChoiceListInterface) {
            throw new InvalidArgumentException(sprintf('loadChoiceList() should return a ChoiceListInterface instance. Got %s', gettype($choiceList)));
        }

        $this->choiceList = $choiceList;
    }
}
PK��Z'���??Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceList.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\ChoiceList;

use Symfony\Component\Form\FormConfigBuilder;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\Form\Exception\InvalidConfigurationException;
use Symfony\Component\Form\Exception\InvalidArgumentException;
use Symfony\Component\Form\Extension\Core\View\ChoiceView;

/**
 * A choice list for choices of arbitrary data types.
 *
 * Choices and labels are passed in two arrays. The indices of the choices
 * and the labels should match. Choices may also be given as hierarchy of
 * unlimited depth by creating nested arrays. The title of the sub-hierarchy
 * can be stored in the array key pointing to the nested array. The topmost
 * level of the hierarchy may also be a \Traversable.
 *
 * <code>
 * $choices = array(true, false);
 * $labels = array('Agree', 'Disagree');
 * $choiceList = new ChoiceList($choices, $labels);
 * </code>
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ChoiceList implements ChoiceListInterface
{
    /**
     * The choices with their indices as keys.
     *
     * @var array
     */
    private $choices = array();

    /**
     * The choice values with the indices of the matching choices as keys.
     *
     * @var array
     */
    private $values = array();

    /**
     * The preferred view objects as hierarchy containing also the choice groups
     * with the indices of the matching choices as bottom-level keys.
     *
     * @var array
     */
    private $preferredViews = array();

    /**
     * The non-preferred view objects as hierarchy containing also the choice
     * groups with the indices of the matching choices as bottom-level keys.
     *
     * @var array
     */
    private $remainingViews = array();

    /**
     * Creates a new choice list.
     *
     * @param array|\Traversable $choices The array of choices. Choices may also be given
     *                                    as hierarchy of unlimited depth. Hierarchies are
     *                                    created by creating nested arrays. The title of
     *                                    the sub-hierarchy can be stored in the array
     *                                    key pointing to the nested array. The topmost
     *                                    level of the hierarchy may also be a \Traversable.
     * @param array $labels The array of labels. The structure of this array
     *                      should match the structure of $choices.
     * @param array $preferredChoices A flat array of choices that should be
     *                                presented to the user with priority.
     *
     * @throws UnexpectedTypeException If the choices are not an array or \Traversable.
     */
    public function __construct($choices, array $labels, array $preferredChoices = array())
    {
        if (!is_array($choices) && !$choices instanceof \Traversable) {
            throw new UnexpectedTypeException($choices, 'array or \Traversable');
        }

        $this->initialize($choices, $labels, $preferredChoices);
    }

    /**
     * Initializes the list with choices.
     *
     * Safe to be called multiple times. The list is cleared on every call.
     *
     * @param array|\Traversable $choices          The choices to write into the list.
     * @param array              $labels           The labels belonging to the choices.
     * @param array              $preferredChoices The choices to display with priority.
     */
    protected function initialize($choices, array $labels, array $preferredChoices)
    {
        $this->choices = array();
        $this->values = array();
        $this->preferredViews = array();
        $this->remainingViews = array();

        $this->addChoices(
            $this->preferredViews,
            $this->remainingViews,
            $choices,
            $labels,
            $preferredChoices
        );
    }

    /**
     * {@inheritdoc}
     */
    public function getChoices()
    {
        return $this->choices;
    }

    /**
     * {@inheritdoc}
     */
    public function getValues()
    {
        return $this->values;
    }

    /**
     * {@inheritdoc}
     */
    public function getPreferredViews()
    {
        return $this->preferredViews;
    }

    /**
     * {@inheritdoc}
     */
    public function getRemainingViews()
    {
        return $this->remainingViews;
    }

    /**
     * {@inheritdoc}
     */
    public function getChoicesForValues(array $values)
    {
        $values = $this->fixValues($values);
        $choices = array();

        foreach ($values as $i => $givenValue) {
            foreach ($this->values as $j => $value) {
                if ($value === $givenValue) {
                    $choices[$i] = $this->choices[$j];
                    unset($values[$i]);

                    if (0 === count($values)) {
                        break 2;
                    }
                }
            }
        }

        return $choices;
    }

    /**
     * {@inheritdoc}
     */
    public function getValuesForChoices(array $choices)
    {
        $choices = $this->fixChoices($choices);
        $values = array();

        foreach ($choices as $i => $givenChoice) {
            foreach ($this->choices as $j => $choice) {
                if ($choice === $givenChoice) {
                    $values[$i] = $this->values[$j];
                    unset($choices[$i]);

                    if (0 === count($choices)) {
                        break 2;
                    }
                }
            }
        }

        return $values;
    }

    /**
     * {@inheritdoc}
     *
     * @deprecated Deprecated since version 2.4, to be removed in 3.0.
     */
    public function getIndicesForChoices(array $choices)
    {
        $choices = $this->fixChoices($choices);
        $indices = array();

        foreach ($choices as $i => $givenChoice) {
            foreach ($this->choices as $j => $choice) {
                if ($choice === $givenChoice) {
                    $indices[$i] = $j;
                    unset($choices[$i]);

                    if (0 === count($choices)) {
                        break 2;
                    }
                }
            }
        }

        return $indices;
    }

    /**
     * {@inheritdoc}
     *
     * @deprecated Deprecated since version 2.4, to be removed in 3.0.
     */
    public function getIndicesForValues(array $values)
    {
        $values = $this->fixValues($values);
        $indices = array();

        foreach ($values as $i => $givenValue) {
            foreach ($this->values as $j => $value) {
                if ($value === $givenValue) {
                    $indices[$i] = $j;
                    unset($values[$i]);

                    if (0 === count($values)) {
                        break 2;
                    }
                }
            }
        }

        return $indices;
    }

    /**
     * Recursively adds the given choices to the list.
     *
     * @param array              $bucketForPreferred The bucket where to store the preferred
     *                                               view objects.
     * @param array              $bucketForRemaining The bucket where to store the
     *                                               non-preferred view objects.
     * @param array|\Traversable $choices            The list of choices.
     * @param array              $labels             The labels corresponding to the choices.
     * @param array              $preferredChoices   The preferred choices.
     *
     * @throws InvalidArgumentException     If the structures of the choices and labels array do not match.
     * @throws InvalidConfigurationException If no valid value or index could be created for a choice.
     */
    protected function addChoices(array &$bucketForPreferred, array &$bucketForRemaining, $choices, array $labels, array $preferredChoices)
    {
        // Add choices to the nested buckets
        foreach ($choices as $group => $choice) {
            if (!array_key_exists($group, $labels)) {
                throw new InvalidArgumentException('The structures of the choices and labels array do not match.');
            }

            if (is_array($choice)) {
                // Don't do the work if the array is empty
                if (count($choice) > 0) {
                    $this->addChoiceGroup(
                        $group,
                        $bucketForPreferred,
                        $bucketForRemaining,
                        $choice,
                        $labels[$group],
                        $preferredChoices
                    );
                }
            } else {
                $this->addChoice(
                    $bucketForPreferred,
                    $bucketForRemaining,
                    $choice,
                    $labels[$group],
                    $preferredChoices
                );
            }
        }
    }

    /**
     * Recursively adds a choice group.
     *
     * @param string $group              The name of the group.
     * @param array  $bucketForPreferred The bucket where to store the preferred
     *                                   view objects.
     * @param array  $bucketForRemaining The bucket where to store the
     *                                   non-preferred view objects.
     * @param array  $choices            The list of choices in the group.
     * @param array  $labels             The labels corresponding to the choices in the group.
     * @param array  $preferredChoices   The preferred choices.
     *
     * @throws InvalidConfigurationException If no valid value or index could be created for a choice.
     */
    protected function addChoiceGroup($group, array &$bucketForPreferred, array &$bucketForRemaining, array $choices, array $labels, array $preferredChoices)
    {
        // If this is a choice group, create a new level in the choice
        // key hierarchy
        $bucketForPreferred[$group] = array();
        $bucketForRemaining[$group] = array();

        $this->addChoices(
            $bucketForPreferred[$group],
            $bucketForRemaining[$group],
            $choices,
            $labels,
            $preferredChoices
        );

        // Remove child levels if empty
        if (empty($bucketForPreferred[$group])) {
            unset($bucketForPreferred[$group]);
        }
        if (empty($bucketForRemaining[$group])) {
            unset($bucketForRemaining[$group]);
        }
    }

    /**
     * Adds a new choice.
     *
     * @param array  $bucketForPreferred The bucket where to store the preferred
     *                                   view objects.
     * @param array  $bucketForRemaining The bucket where to store the
     *                                   non-preferred view objects.
     * @param mixed  $choice             The choice to add.
     * @param string $label              The label for the choice.
     * @param array  $preferredChoices   The preferred choices.
     *
     * @throws InvalidConfigurationException If no valid value or index could be created.
     */
    protected function addChoice(array &$bucketForPreferred, array &$bucketForRemaining, $choice, $label, array $preferredChoices)
    {
        $index = $this->createIndex($choice);

        if ('' === $index || null === $index || !FormConfigBuilder::isValidName((string) $index)) {
            throw new InvalidConfigurationException(sprintf('The index "%s" created by the choice list is invalid. It should be a valid, non-empty Form name.', $index));
        }

        $value = $this->createValue($choice);

        if (!is_string($value)) {
            throw new InvalidConfigurationException(sprintf('The value created by the choice list is of type "%s", but should be a string.', gettype($value)));
        }

        $view = new ChoiceView($choice, $value, $label);

        $this->choices[$index] = $this->fixChoice($choice);
        $this->values[$index] = $value;

        if ($this->isPreferred($choice, $preferredChoices)) {
            $bucketForPreferred[$index] = $view;
        } else {
            $bucketForRemaining[$index] = $view;
        }
    }

    /**
     * Returns whether the given choice should be preferred judging by the
     * given array of preferred choices.
     *
     * Extension point to optimize performance by changing the structure of the
     * $preferredChoices array.
     *
     * @param mixed $choice           The choice to test.
     * @param array $preferredChoices An array of preferred choices.
     *
     * @return Boolean Whether the choice is preferred.
     */
    protected function isPreferred($choice, array $preferredChoices)
    {
        return false !== array_search($choice, $preferredChoices, true);
    }

    /**
     * Creates a new unique index for this choice.
     *
     * Extension point to change the indexing strategy.
     *
     * @param mixed $choice The choice to create an index for
     *
     * @return integer|string A unique index containing only ASCII letters,
     *                        digits and underscores.
     */
    protected function createIndex($choice)
    {
        return count($this->choices);
    }

    /**
     * Creates a new unique value for this choice.
     *
     * By default, an integer is generated since it cannot be guaranteed that
     * all values in the list are convertible to (unique) strings. Subclasses
     * can override this behaviour if they can guarantee this property.
     *
     * @param mixed $choice The choice to create a value for
     *
     * @return string A unique string.
     */
    protected function createValue($choice)
    {
        return (string) count($this->values);
    }

    /**
     * Fixes the data type of the given choice value to avoid comparison
     * problems.
     *
     * @param mixed $value The choice value.
     *
     * @return string The value as string.
     */
    protected function fixValue($value)
    {
        return (string) $value;
    }

    /**
     * Fixes the data types of the given choice values to avoid comparison
     * problems.
     *
     * @param array $values The choice values.
     *
     * @return array The values as strings.
     */
    protected function fixValues(array $values)
    {
        foreach ($values as $i => $value) {
            $values[$i] = $this->fixValue($value);
        }

        return $values;
    }

    /**
     * Fixes the data type of the given choice index to avoid comparison
     * problems.
     *
     * @param mixed $index The choice index.
     *
     * @return integer|string The index as PHP array key.
     */
    protected function fixIndex($index)
    {
        if (is_bool($index) || (string) (int) $index === (string) $index) {
            return (int) $index;
        }

        return (string) $index;
    }

    /**
     * Fixes the data types of the given choice indices to avoid comparison
     * problems.
     *
     * @param array $indices The choice indices.
     *
     * @return array The indices as strings.
     */
    protected function fixIndices(array $indices)
    {
        foreach ($indices as $i => $index) {
            $indices[$i] = $this->fixIndex($index);
        }

        return $indices;
    }

    /**
     * Fixes the data type of the given choice to avoid comparison problems.
     *
     * Extension point. In this implementation, choices are guaranteed to
     * always maintain their type and thus can be typesafely compared.
     *
     * @param mixed $choice The choice
     *
     * @return mixed The fixed choice
     */
    protected function fixChoice($choice)
    {
        return $choice;
    }

    /**
     * Fixes the data type of the given choices to avoid comparison problems.
     *
     * @param array $choices The choices.
     *
     * @return array The fixed choices.
     *
     * @see fixChoice
     */
    protected function fixChoices(array $choices)
    {
        return $choices;
    }
}
PK��Z��&PP9Symfony/Component/Form/Extension/Core/View/ChoiceView.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\View;

/**
 * Represents a choice in templates.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ChoiceView
{
    /**
     * The original choice value.
     *
     * @var mixed
     */
    public $data;

    /**
     * The view representation of the choice.
     *
     * @var string
     */
    public $value;

    /**
     * The label displayed to humans.
     *
     * @var string
     */
    public $label;

    /**
     * Creates a new ChoiceView.
     *
     * @param mixed  $data  The original choice.
     * @param string $value The view representation of the choice.
     * @param string $label The label displayed to humans.
     */
    public function __construct($data, $value, $label)
    {
        $this->data = $data;
        $this->value = $value;
        $this->label = $label;
    }
}
PK��Z��

GSymfony/Component/Form/Extension/Core/DataMapper/PropertyPathMapper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\DataMapper;

use Symfony\Component\Form\DataMapperInterface;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;

/**
 * A data mapper using property paths to read/write data.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class PropertyPathMapper implements DataMapperInterface
{
    /**
     * @var PropertyAccessorInterface
     */
    private $propertyAccessor;

    /**
     * Creates a new property path mapper.
     *
     * @param PropertyAccessorInterface $propertyAccessor
     */
    public function __construct(PropertyAccessorInterface $propertyAccessor = null)
    {
        $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor();
    }

    /**
     * {@inheritdoc}
     */
    public function mapDataToForms($data, $forms)
    {
        $empty = null === $data || array() === $data;

        if (!$empty && !is_array($data) && !is_object($data)) {
            throw new UnexpectedTypeException($data, 'object, array or empty');
        }

        foreach ($forms as $form) {
            $propertyPath = $form->getPropertyPath();
            $config = $form->getConfig();

            if (!$empty && null !== $propertyPath && $config->getMapped()) {
                $form->setData($this->propertyAccessor->getValue($data, $propertyPath));
            } else {
                $form->setData($form->getConfig()->getData());
            }
        }
    }

    /**
     * {@inheritdoc}
     */
    public function mapFormsToData($forms, &$data)
    {
        if (null === $data) {
            return;
        }

        if (!is_array($data) && !is_object($data)) {
            throw new UnexpectedTypeException($data, 'object, array or empty');
        }

        foreach ($forms as $form) {
            $propertyPath = $form->getPropertyPath();
            $config = $form->getConfig();

            // Write-back is disabled if the form is not synchronized (transformation failed),
            // if the form was not submitted and if the form is disabled (modification not allowed)
            if (null !== $propertyPath && $config->getMapped() && $form->isSubmitted() && $form->isSynchronized() && !$form->isDisabled()) {

                // If the field is of type DateTime and the data is the same skip the update to
                // keep the original object hash
                if ($form->getData() instanceof \DateTime && $form->getData() == $this->propertyAccessor->getValue($data, $propertyPath)) {
                    continue;
                }

                // If the data is identical to the value in $data, we are
                // dealing with a reference
                if (!is_object($data) || !$config->getByReference() || $form->getData() !== $this->propertyAccessor->getValue($data, $propertyPath)) {
                    $this->propertyAccessor->setValue($data, $propertyPath, $form->getData());
                }
            }
        }
    }
}
PK��ZO�#�#�#\Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\DataTransformer;

use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;

/**
 * Transforms between a number type and a localized number with grouping
 * (each thousand) and comma separators.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 * @author Florian Eckerstorfer <florian@eckerstorfer.org>
 */
class NumberToLocalizedStringTransformer implements DataTransformerInterface
{
    /**
     * Rounds a number towards positive infinity.
     *
     * Rounds 1.4 to 2 and -1.4 to -1.
     */
    const ROUND_CEILING = \NumberFormatter::ROUND_CEILING;

    /**
     * Rounds a number towards negative infinity.
     *
     * Rounds 1.4 to 1 and -1.4 to -2.
     */
    const ROUND_FLOOR = \NumberFormatter::ROUND_FLOOR;

    /**
     * Rounds a number away from zero.
     *
     * Rounds 1.4 to 2 and -1.4 to -2.
     */
    const ROUND_UP = \NumberFormatter::ROUND_UP;

    /**
     * Rounds a number towards zero.
     *
     * Rounds 1.4 to 1 and -1.4 to -1.
     */
    const ROUND_DOWN = \NumberFormatter::ROUND_DOWN;

    /**
     * Rounds to the nearest number and halves to the next even number.
     *
     * Rounds 2.5, 1.6 and 1.5 to 2 and 1.4 to 1.
     */
    const ROUND_HALF_EVEN = \NumberFormatter::ROUND_HALFEVEN;

    /**
     * Rounds to the nearest number and halves away from zero.
     *
     * Rounds 2.5 to 3, 1.6 and 1.5 to 2 and 1.4 to 1.
     */
    const ROUND_HALF_UP = \NumberFormatter::ROUND_HALFUP;

    /**
     * Rounds to the nearest number and halves towards zero.
     *
     * Rounds 2.5 and 1.6 to 2, 1.5 and 1.4 to 1.
     */
    const ROUND_HALF_DOWN = \NumberFormatter::ROUND_HALFDOWN;

    /**
     * Alias for {@link self::ROUND_HALF_EVEN}.
     *
     * @deprecated Deprecated as of Symfony 2.4, to be removed in Symfony 3.0.
     */
    const ROUND_HALFEVEN = self::ROUND_HALF_EVEN;

    /**
     * Alias for {@link self::ROUND_HALF_UP}.
     *
     * @deprecated Deprecated as of Symfony 2.4, to be removed in Symfony 3.0.
     */
    const ROUND_HALFUP = self::ROUND_HALF_UP;

    /**
     * Alias for {@link self::ROUND_HALF_DOWN}.
     *
     * @deprecated Deprecated as of Symfony 2.4, to be removed in Symfony 3.0.
     */
    const ROUND_HALFDOWN = self::ROUND_HALF_DOWN;

    protected $precision;

    protected $grouping;

    protected $roundingMode;

    public function __construct($precision = null, $grouping = false, $roundingMode = self::ROUND_HALF_UP)
    {
        if (null === $grouping) {
            $grouping = false;
        }

        if (null === $roundingMode) {
            $roundingMode = self::ROUND_HALF_UP;
        }

        $this->precision = $precision;
        $this->grouping = $grouping;
        $this->roundingMode = $roundingMode;
    }

    /**
     * Transforms a number type into localized number.
     *
     * @param integer|float $value Number value.
     *
     * @return string Localized value.
     *
     * @throws TransformationFailedException If the given value is not numeric
     *                                       or if the value can not be transformed.
     */
    public function transform($value)
    {
        if (null === $value) {
            return '';
        }

        if (!is_numeric($value)) {
            throw new TransformationFailedException('Expected a numeric.');
        }

        $formatter = $this->getNumberFormatter();
        $value = $formatter->format($value);

        if (intl_is_failure($formatter->getErrorCode())) {
            throw new TransformationFailedException($formatter->getErrorMessage());
        }

        // Convert fixed spaces to normal ones
        $value = str_replace("\xc2\xa0", ' ', $value);

        return $value;
    }

    /**
     * Transforms a localized number into an integer or float
     *
     * @param string $value The localized value
     *
     * @return integer|float The numeric value
     *
     * @throws TransformationFailedException If the given value is not a string
     *                                       or if the value can not be transformed.
     */
    public function reverseTransform($value)
    {
        if (!is_string($value)) {
            throw new TransformationFailedException('Expected a string.');
        }

        if ('' === $value) {
            return null;
        }

        if ('NaN' === $value) {
            throw new TransformationFailedException('"NaN" is not a valid number');
        }

        $position = 0;
        $formatter = $this->getNumberFormatter();
        $groupSep = $formatter->getSymbol(\NumberFormatter::GROUPING_SEPARATOR_SYMBOL);
        $decSep = $formatter->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL);

        if ('.' !== $decSep && (!$this->grouping || '.' !== $groupSep)) {
            $value = str_replace('.', $decSep, $value);
        }

        if (',' !== $decSep && (!$this->grouping || ',' !== $groupSep)) {
            $value = str_replace(',', $decSep, $value);
        }

        $result = $formatter->parse($value, \NumberFormatter::TYPE_DOUBLE, $position);

        if (intl_is_failure($formatter->getErrorCode())) {
            throw new TransformationFailedException($formatter->getErrorMessage());
        }

        if ($result >= PHP_INT_MAX || $result <= -PHP_INT_MAX) {
            throw new TransformationFailedException('I don\'t have a clear idea what infinity looks like');
        }

        if (function_exists('mb_detect_encoding') && false !== $encoding = mb_detect_encoding($value)) {
            $strlen = function ($string) use ($encoding) {
                return mb_strlen($string, $encoding);
            };
            $substr = function ($string, $offset, $length) use ($encoding) {
                return mb_substr($string, $offset, $length, $encoding);
            };
        } else {
            $strlen = 'strlen';
            $substr = 'substr';
        }

        $length = $strlen($value);

        // After parsing, position holds the index of the character where the
        // parsing stopped
        if ($position < $length) {
            // Check if there are unrecognized characters at the end of the
            // number (excluding whitespace characters)
            $remainder = trim($substr($value, $position, $length), " \t\n\r\0\x0b\xc2\xa0");

            if ('' !== $remainder) {
                throw new TransformationFailedException(
                    sprintf('The number contains unrecognized characters: "%s"', $remainder)
                );
            }
        }

        // NumberFormatter::parse() does not round
        return $this->round($result);
    }

    /**
     * Returns a preconfigured \NumberFormatter instance
     *
     * @return \NumberFormatter
     */
    protected function getNumberFormatter()
    {
        $formatter = new \NumberFormatter(\Locale::getDefault(), \NumberFormatter::DECIMAL);

        if (null !== $this->precision) {
            $formatter->setAttribute(\NumberFormatter::FRACTION_DIGITS, $this->precision);
            $formatter->setAttribute(\NumberFormatter::ROUNDING_MODE, $this->roundingMode);
        }

        $formatter->setAttribute(\NumberFormatter::GROUPING_USED, $this->grouping);

        return $formatter;
    }

    /**
     * Rounds a number according to the configured precision and rounding mode.
     *
     * @param integer|float $number A number.
     *
     * @return integer|float The rounded number.
     */
    private function round($number)
    {
        if (null !== $this->precision && null !== $this->roundingMode) {
            // shift number to maintain the correct precision during rounding
            $roundingCoef = pow(10, $this->precision);
            $number *= $roundingCoef;

            switch ($this->roundingMode) {
                case self::ROUND_CEILING:
                    $number = ceil($number);
                    break;
                case self::ROUND_FLOOR:
                    $number = floor($number);
                    break;
                case self::ROUND_UP:
                    $number = $number > 0 ? ceil($number) : floor($number);
                    break;
                case self::ROUND_DOWN:
                    $number = $number > 0 ? floor($number) : ceil($number);
                    break;
                case self::ROUND_HALF_EVEN:
                    $number = round($number, 0, PHP_ROUND_HALF_EVEN);
                    break;
                case self::ROUND_HALF_UP:
                    $number = round($number, 0, PHP_ROUND_HALF_UP);
                    break;
                case self::ROUND_HALF_DOWN:
                    $number = round($number, 0, PHP_ROUND_HALF_DOWN);
                    break;
            }

            $number /= $roundingCoef;
        }

        return $number;
    }
}
PK��Z)b�""^Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\DataTransformer;

use Symfony\Component\Form\Exception\TransformationFailedException;
use Symfony\Component\Form\Exception\UnexpectedTypeException;

/**
 * Transforms between a normalized time and a localized time string
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 * @author Florian Eckerstorfer <florian@eckerstorfer.org>
 */
class DateTimeToLocalizedStringTransformer extends BaseDateTimeTransformer
{
    private $dateFormat;
    private $timeFormat;
    private $pattern;
    private $calendar;

    /**
     * Constructor.
     *
     * @see BaseDateTimeTransformer::formats for available format options
     *
     * @param string  $inputTimezone  The name of the input timezone
     * @param string  $outputTimezone The name of the output timezone
     * @param integer $dateFormat     The date format
     * @param integer $timeFormat     The time format
     * @param integer $calendar       One of the \IntlDateFormatter calendar constants
     * @param string  $pattern        A pattern to pass to \IntlDateFormatter
     *
     * @throws UnexpectedTypeException If a format is not supported or if a timezone is not a string
     */
    public function __construct($inputTimezone = null, $outputTimezone = null, $dateFormat = null, $timeFormat = null, $calendar = \IntlDateFormatter::GREGORIAN, $pattern = null)
    {
        parent::__construct($inputTimezone, $outputTimezone);

        if (null === $dateFormat) {
            $dateFormat = \IntlDateFormatter::MEDIUM;
        }

        if (null === $timeFormat) {
            $timeFormat = \IntlDateFormatter::SHORT;
        }

        if (!in_array($dateFormat, self::$formats, true)) {
            throw new UnexpectedTypeException($dateFormat, implode('", "', self::$formats));
        }

        if (!in_array($timeFormat, self::$formats, true)) {
            throw new UnexpectedTypeException($timeFormat, implode('", "', self::$formats));
        }

        $this->dateFormat = $dateFormat;
        $this->timeFormat = $timeFormat;
        $this->calendar = $calendar;
        $this->pattern = $pattern;
    }

    /**
     * Transforms a normalized date into a localized date string/array.
     *
     * @param \DateTime $dateTime Normalized date.
     *
     * @return string|array Localized date string/array.
     *
     * @throws TransformationFailedException If the given value is not an instance
     *                                       of \DateTime or if the date could not
     *                                       be transformed.
     */
    public function transform($dateTime)
    {
        if (null === $dateTime) {
            return '';
        }

        if (!$dateTime instanceof \DateTime) {
            throw new TransformationFailedException('Expected a \DateTime.');
        }

        // convert time to UTC before passing it to the formatter
        $dateTime = clone $dateTime;
        if ('UTC' !== $this->inputTimezone) {
            $dateTime->setTimezone(new \DateTimeZone('UTC'));
        }

        $value = $this->getIntlDateFormatter()->format((int) $dateTime->format('U'));

        if (intl_get_error_code() != 0) {
            throw new TransformationFailedException(intl_get_error_message());
        }

        return $value;
    }

    /**
     * Transforms a localized date string/array into a normalized date.
     *
     * @param string|array $value Localized date string/array
     *
     * @return \DateTime Normalized date
     *
     * @throws TransformationFailedException if the given value is not a string,
     *                                       if the date could not be parsed or
     *                                       if the input timezone is not supported
     */
    public function reverseTransform($value)
    {
        if (!is_string($value)) {
            throw new TransformationFailedException('Expected a string.');
        }

        if ('' === $value) {
            return null;
        }

        $timestamp = $this->getIntlDateFormatter()->parse($value);

        if (intl_get_error_code() != 0) {
            throw new TransformationFailedException(intl_get_error_message());
        }

        try {
            // read timestamp into DateTime object - the formatter delivers in UTC
            $dateTime = new \DateTime(sprintf('@%s UTC', $timestamp));
        } catch (\Exception $e) {
            throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
        }

        if ('UTC' !== $this->inputTimezone) {
            try {
                $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone));
            } catch (\Exception $e) {
                throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
            }
        }

        return $dateTime;
    }

    /**
     * Returns a preconfigured IntlDateFormatter instance
     *
     * @return \IntlDateFormatter
     */
    protected function getIntlDateFormatter()
    {
        $dateFormat = $this->dateFormat;
        $timeFormat = $this->timeFormat;
        $timezone = $this->outputTimezone;
        $calendar = $this->calendar;
        $pattern = $this->pattern;

        $intlDateFormatter = new \IntlDateFormatter(\Locale::getDefault(), $dateFormat, $timeFormat, $timezone, $calendar, $pattern);
        $intlDateFormatter->setLenient(false);

        return $intlDateFormatter;
    }
}
PK��Ze�^�		VSymfony/Component/Form/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\DataTransformer;

use Symfony\Component\Form\Exception\TransformationFailedException;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class DateTimeToRfc3339Transformer extends BaseDateTimeTransformer
{
    /**
     * {@inheritDoc}
     */
    public function transform($dateTime)
    {
        if (null === $dateTime) {
            return '';
        }

        if (!$dateTime instanceof \DateTime) {
            throw new TransformationFailedException('Expected a \DateTime.');
        }

        if ($this->inputTimezone !== $this->outputTimezone) {
            $dateTime = clone $dateTime;
            $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone));
        }

        return preg_replace('/\+00:00$/', 'Z', $dateTime->format('c'));
    }

    /**
     * {@inheritDoc}
     */
    public function reverseTransform($rfc3339)
    {
        if (!is_string($rfc3339)) {
            throw new TransformationFailedException('Expected a string.');
        }

        if ('' === $rfc3339) {
            return null;
        }

        try {
            $dateTime = new \DateTime($rfc3339);
        } catch (\Exception $e) {
            throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
        }

        if ($this->outputTimezone !== $dateTime->getTimezone()->getName()) {
            try {
                $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone));
            } catch (\Exception $e) {
                throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
            }
        }

        if (preg_match('/(\d{4})-(\d{2})-(\d{2})/', $rfc3339, $matches)) {
            if (!checkdate($matches[2], $matches[3], $matches[1])) {
                throw new TransformationFailedException(sprintf(
                    'The date "%s-%s-%s" is not a valid date.',
                    $matches[1],
                    $matches[2],
                    $matches[3]
                ));
            }
        }

        return $dateTime;
    }
}
PK��Z���Þ
�
XSymfony/Component/Form/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\DataTransformer;

use Symfony\Component\Form\Exception\TransformationFailedException;

/**
 * Transforms between a timestamp and a DateTime object
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 * @author Florian Eckerstorfer <florian@eckerstorfer.org>
 */
class DateTimeToTimestampTransformer extends BaseDateTimeTransformer
{
    /**
     * Transforms a DateTime object into a timestamp in the configured timezone.
     *
     * @param \DateTime $value A \DateTime object
     *
     * @return integer A timestamp
     *
     * @throws TransformationFailedException If the given value is not an instance
     *                                       of \DateTime or if the output
     *                                       timezone is not supported.
     */
    public function transform($value)
    {
        if (null === $value) {
            return null;
        }

        if (!$value instanceof \DateTime) {
            throw new TransformationFailedException('Expected a \DateTime.');
        }

        $value = clone $value;
        try {
            $value->setTimezone(new \DateTimeZone($this->outputTimezone));
        } catch (\Exception $e) {
            throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
        }

        return (int) $value->format('U');
    }

    /**
     * Transforms a timestamp in the configured timezone into a DateTime object
     *
     * @param string $value A timestamp
     *
     * @return \DateTime A \DateTime object
     *
     * @throws TransformationFailedException If the given value is not a timestamp
     *                                       or if the given timestamp is invalid.
     */
    public function reverseTransform($value)
    {
        if (null === $value) {
            return null;
        }

        if (!is_numeric($value)) {
            throw new TransformationFailedException('Expected a numeric.');
        }

        try {
            $dateTime = new \DateTime();
            $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone));
            $dateTime->setTimestamp($value);

            if ($this->inputTimezone !== $this->outputTimezone) {
                $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone));
            }
        } catch (\Exception $e) {
            throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
        }

        return $dateTime;
    }
}
PK��Zc�8V�	�	NSymfony/Component/Form/Extension/Core/DataTransformer/DataTransformerChain.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\DataTransformer;

use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;

/**
 * Passes a value through multiple value transformers
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class DataTransformerChain implements DataTransformerInterface
{
    /**
     * The value transformers
     * @var DataTransformerInterface[]
     */
    protected $transformers;

    /**
     * Uses the given value transformers to transform values
     *
     * @param array $transformers
     */
    public function __construct(array $transformers)
    {
        $this->transformers = $transformers;
    }

    /**
     * Passes the value through the transform() method of all nested transformers
     *
     * The transformers receive the value in the same order as they were passed
     * to the constructor. Each transformer receives the result of the previous
     * transformer as input. The output of the last transformer is returned
     * by this method.
     *
     * @param mixed $value The original value
     *
     * @return mixed The transformed value
     *
     * @throws TransformationFailedException
     */
    public function transform($value)
    {
        foreach ($this->transformers as $transformer) {
            $value = $transformer->transform($value);
        }

        return $value;
    }

    /**
     * Passes the value through the reverseTransform() method of all nested
     * transformers
     *
     * The transformers receive the value in the reverse order as they were passed
     * to the constructor. Each transformer receives the result of the previous
     * transformer as input. The output of the last transformer is returned
     * by this method.
     *
     * @param mixed $value The transformed value
     *
     * @return mixed The reverse-transformed value
     *
     * @throws TransformationFailedException
     */
    public function reverseTransform($value)
    {
        for ($i = count($this->transformers) - 1; $i >= 0; --$i) {
            $value = $this->transformers[$i]->reverseTransform($value);
        }

        return $value;
    }
}
PK��Z�;�dd]Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\DataTransformer;

use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Symfony\Component\Form\Exception\UnexpectedTypeException;

/**
 * Transforms between a normalized format (integer or float) and a percentage value.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 * @author Florian Eckerstorfer <florian@eckerstorfer.org>
 */
class PercentToLocalizedStringTransformer implements DataTransformerInterface
{
    const FRACTIONAL = 'fractional';
    const INTEGER = 'integer';

    protected static $types = array(
        self::FRACTIONAL,
        self::INTEGER,
    );

    private $type;

    private $precision;

    /**
     * Constructor.
     *
     * @see self::$types for a list of supported types
     *
     * @param integer $precision The precision
     * @param string  $type      One of the supported types
     *
     * @throws UnexpectedTypeException if the given value of type is unknown
     */
    public function __construct($precision = null, $type = null)
    {
        if (null === $precision) {
            $precision = 0;
        }

        if (null === $type) {
            $type = self::FRACTIONAL;
        }

        if (!in_array($type, self::$types, true)) {
            throw new UnexpectedTypeException($type, implode('", "', self::$types));
        }

        $this->type = $type;
        $this->precision = $precision;
    }

    /**
     * Transforms between a normalized format (integer or float) into a percentage value.
     *
     * @param number $value Normalized value
     *
     * @return number Percentage value
     *
     * @throws TransformationFailedException If the given value is not numeric or
     *                                       if the value could not be transformed.
     */
    public function transform($value)
    {
        if (null === $value) {
            return '';
        }

        if (!is_numeric($value)) {
            throw new TransformationFailedException('Expected a numeric.');
        }

        if (self::FRACTIONAL == $this->type) {
            $value *= 100;
        }

        $formatter = $this->getNumberFormatter();
        $value = $formatter->format($value);

        if (intl_is_failure($formatter->getErrorCode())) {
            throw new TransformationFailedException($formatter->getErrorMessage());
        }

        // replace the UTF-8 non break spaces
        return $value;
    }

    /**
     * Transforms between a percentage value into a normalized format (integer or float).
     *
     * @param number $value Percentage value.
     *
     * @return number Normalized value.
     *
     * @throws TransformationFailedException If the given value is not a string or
     *                                       if the value could not be transformed.
     */
    public function reverseTransform($value)
    {
        if (!is_string($value)) {
            throw new TransformationFailedException('Expected a string.');
        }

        if ('' === $value) {
            return null;
        }

        $formatter = $this->getNumberFormatter();
        // replace normal spaces so that the formatter can read them
        $value = $formatter->parse(str_replace(' ', ' ', $value));

        if (intl_is_failure($formatter->getErrorCode())) {
            throw new TransformationFailedException($formatter->getErrorMessage());
        }

        if (self::FRACTIONAL == $this->type) {
            $value /= 100;
        }

        return $value;
    }

    /**
     * Returns a preconfigured \NumberFormatter instance
     *
     * @return \NumberFormatter
     */
    protected function getNumberFormatter()
    {
        $formatter = new \NumberFormatter(\Locale::getDefault(), \NumberFormatter::DECIMAL);

        $formatter->setAttribute(\NumberFormatter::FRACTION_DIGITS, $this->precision);

        return $formatter;
    }
}
PK��Z�Z�eTSymfony/Component/Form/Extension/Core/DataTransformer/DateTimeToArrayTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\DataTransformer;

use Symfony\Component\Form\Exception\TransformationFailedException;
use Symfony\Component\Form\Exception\UnexpectedTypeException;

/**
 * Transforms between a normalized time and a localized time string/array.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 * @author Florian Eckerstorfer <florian@eckerstorfer.org>
 */
class DateTimeToArrayTransformer extends BaseDateTimeTransformer
{
    private $pad;

    private $fields;

    /**
     * Constructor.
     *
     * @param string  $inputTimezone  The input timezone
     * @param string  $outputTimezone The output timezone
     * @param array   $fields         The date fields
     * @param Boolean $pad            Whether to use padding
     *
     * @throws UnexpectedTypeException if a timezone is not a string
     */
    public function __construct($inputTimezone = null, $outputTimezone = null, array $fields = null, $pad = false)
    {
        parent::__construct($inputTimezone, $outputTimezone);

        if (null === $fields) {
            $fields = array('year', 'month', 'day', 'hour', 'minute', 'second');
        }

        $this->fields = $fields;
        $this->pad = (Boolean) $pad;
    }

    /**
     * Transforms a normalized date into a localized date.
     *
     * @param \DateTime $dateTime Normalized date.
     *
     * @return array Localized date.
     *
     * @throws TransformationFailedException If the given value is not an
     *                                       instance of \DateTime or if the
     *                                       output timezone is not supported.
     */
    public function transform($dateTime)
    {
        if (null === $dateTime) {
            return array_intersect_key(array(
                'year'    => '',
                'month'   => '',
                'day'     => '',
                'hour'    => '',
                'minute'  => '',
                'second'  => '',
            ), array_flip($this->fields));
        }

        if (!$dateTime instanceof \DateTime) {
            throw new TransformationFailedException('Expected a \DateTime.');
        }

        $dateTime = clone $dateTime;
        if ($this->inputTimezone !== $this->outputTimezone) {
            try {
                $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone));
            } catch (\Exception $e) {
                throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
            }
        }

        $result = array_intersect_key(array(
            'year'    => $dateTime->format('Y'),
            'month'   => $dateTime->format('m'),
            'day'     => $dateTime->format('d'),
            'hour'    => $dateTime->format('H'),
            'minute'  => $dateTime->format('i'),
            'second'  => $dateTime->format('s'),
        ), array_flip($this->fields));

        if (!$this->pad) {
            foreach ($result as &$entry) {
                // remove leading zeros
                $entry = (string) (int) $entry;
            }
        }

        return $result;
    }

    /**
     * Transforms a localized date into a normalized date.
     *
     * @param array $value Localized date
     *
     * @return \DateTime Normalized date
     *
     * @throws TransformationFailedException If the given value is not an array,
     *                                       if the value could not be transformed
     *                                       or if the input timezone is not
     *                                       supported.
     */
    public function reverseTransform($value)
    {
        if (null === $value) {
            return null;
        }

        if (!is_array($value)) {
            throw new TransformationFailedException('Expected an array.');
        }

        if ('' === implode('', $value)) {
            return null;
        }

        $emptyFields = array();

        foreach ($this->fields as $field) {
            if (!isset($value[$field])) {
                $emptyFields[] = $field;
            }
        }

        if (count($emptyFields) > 0) {
            throw new TransformationFailedException(
                sprintf('The fields "%s" should not be empty', implode('", "', $emptyFields)
            ));
        }

        if (isset($value['month']) && !ctype_digit((string) $value['month'])) {
            throw new TransformationFailedException('This month is invalid');
        }

        if (isset($value['day']) && !ctype_digit((string) $value['day'])) {
            throw new TransformationFailedException('This day is invalid');
        }

        if (isset($value['year']) && !ctype_digit((string) $value['year'])) {
            throw new TransformationFailedException('This year is invalid');
        }

        if (!empty($value['month']) && !empty($value['day']) && !empty($value['year']) && false === checkdate($value['month'], $value['day'], $value['year'])) {
            throw new TransformationFailedException('This is an invalid date');
        }

        if (isset($value['hour']) && !ctype_digit((string) $value['hour'])) {
            throw new TransformationFailedException('This hour is invalid');
        }

        if (isset($value['minute']) && !ctype_digit((string) $value['minute'])) {
            throw new TransformationFailedException('This minute is invalid');
        }

        if (isset($value['second']) && !ctype_digit((string) $value['second'])) {
            throw new TransformationFailedException('This second is invalid');
        }

        try {
            $dateTime = new \DateTime(sprintf(
                '%s-%s-%s %s:%s:%s %s',
                empty($value['year']) ? '1970' : $value['year'],
                empty($value['month']) ? '1' : $value['month'],
                empty($value['day']) ? '1' : $value['day'],
                empty($value['hour']) ? '0' : $value['hour'],
                empty($value['minute']) ? '0' : $value['minute'],
                empty($value['second']) ? '0' : $value['second'],
                $this->outputTimezone
            ));

            if ($this->inputTimezone !== $this->outputTimezone) {
                $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone));
            }
        } catch (\Exception $e) {
            throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
        }

        return $dateTime;
    }
}
PK��ZL�px&&YSymfony/Component/Form/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\DataTransformer;

use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ChoiceToBooleanArrayTransformer implements DataTransformerInterface
{
    private $choiceList;

    private $placeholderPresent;

    /**
     * Constructor.
     *
     * @param ChoiceListInterface $choiceList
     * @param Boolean             $placeholderPresent
     */
    public function __construct(ChoiceListInterface $choiceList, $placeholderPresent)
    {
        $this->choiceList = $choiceList;
        $this->placeholderPresent = $placeholderPresent;
    }

    /**
     * Transforms a single choice to a format appropriate for the nested
     * checkboxes/radio buttons.
     *
     * The result is an array with the options as keys and true/false as values,
     * depending on whether a given option is selected. If this field is rendered
     * as select tag, the value is not modified.
     *
     * @param mixed $choice An array if "multiple" is set to true, a scalar
     *                      value otherwise.
     *
     * @return mixed An array
     *
     * @throws TransformationFailedException If the given value is not scalar or
     *                                       if the choices can not be retrieved.
     */
    public function transform($choice)
    {
        try {
            $values = $this->choiceList->getValues();
        } catch (\Exception $e) {
            throw new TransformationFailedException('Can not get the choice list', $e->getCode(), $e);
        }

        $valueMap = array_flip($this->choiceList->getValuesForChoices(array($choice)));

        foreach ($values as $i => $value) {
            $values[$i] = isset($valueMap[$value]);
        }

        if ($this->placeholderPresent) {
            $values['placeholder'] = 0 === count($valueMap);
        }

        return $values;
    }

    /**
     * Transforms a checkbox/radio button array to a single choice.
     *
     * The input value is an array with the choices as keys and true/false as
     * values, depending on whether a given choice is selected. The output
     * is the selected choice.
     *
     * @param array $values An array of values
     *
     * @return mixed A scalar value
     *
     * @throws TransformationFailedException If the given value is not an array,
     *                                       if the recuperation of the choices
     *                                       fails or if some choice can't be
     *                                       found.
     */
    public function reverseTransform($values)
    {
        if (!is_array($values)) {
            throw new TransformationFailedException('Expected an array.');
        }

        try {
            $choices = $this->choiceList->getChoices();
        } catch (\Exception $e) {
            throw new TransformationFailedException('Can not get the choice list', $e->getCode(), $e);
        }

        foreach ($values as $i => $selected) {
            if ($selected) {
                if (isset($choices[$i])) {
                    return $choices[$i] === '' ? null : $choices[$i];
                } elseif ($this->placeholderPresent && 'placeholder' === $i) {
                    return null;
                } else {
                    throw new TransformationFailedException(sprintf('The choice "%s" does not exist', $i));
                }
            }
        }

        return null;
    }
}
PK��Z����		VSymfony/Component/Form/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\DataTransformer;

use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ValueToDuplicatesTransformer implements DataTransformerInterface
{
    private $keys;

    public function __construct(array $keys)
    {
        $this->keys = $keys;
    }

    /**
     * Duplicates the given value through the array.
     *
     * @param mixed $value The value
     *
     * @return array The array
     */
    public function transform($value)
    {
        $result = array();

        foreach ($this->keys as $key) {
            $result[$key] = $value;
        }

        return $result;
    }

    /**
     * Extracts the duplicated value from an array.
     *
     * @param array $array
     *
     * @return mixed The value
     *
     * @throws TransformationFailedException If the given value is not an array or
     *                                       if the given array can not be transformed.
     */
    public function reverseTransform($array)
    {
        if (!is_array($array)) {
            throw new TransformationFailedException('Expected an array.');
        }

        $result = current($array);
        $emptyKeys = array();

        foreach ($this->keys as $key) {
            if (!empty($array[$key])) {
                if ($array[$key] !== $result) {
                    throw new TransformationFailedException(
                        'All values in the array should be the same'
                    );
                }
            } else {
                $emptyKeys[] = $key;
            }
        }

        if (count($emptyKeys) > 0) {
            if (count($emptyKeys) == count($this->keys)) {
                // All keys empty
                return null;
            }

            throw new TransformationFailedException(
                 sprintf('The keys "%s" should not be empty', implode('", "', $emptyKeys)
            ));
        }

        return $result;
    }
}
PK��Z'tqk55ZSymfony/Component/Form/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\DataTransformer;

use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ChoicesToBooleanArrayTransformer implements DataTransformerInterface
{
    private $choiceList;

    public function __construct(ChoiceListInterface $choiceList)
    {
        $this->choiceList = $choiceList;
    }

    /**
     * Transforms an array of choices to a format appropriate for the nested
     * checkboxes/radio buttons.
     *
     * The result is an array with the options as keys and true/false as values,
     * depending on whether a given option is selected. If this field is rendered
     * as select tag, the value is not modified.
     *
     * @param mixed $array An array
     *
     * @return mixed An array
     *
     * @throws TransformationFailedException If the given value is not an array
     *                                       or if the choices can not be retrieved.
     */
    public function transform($array)
    {
        if (null === $array) {
            return array();
        }

        if (!is_array($array)) {
            throw new TransformationFailedException('Expected an array.');
        }

        try {
            $values = $this->choiceList->getValues();
        } catch (\Exception $e) {
            throw new TransformationFailedException('Can not get the choice list', $e->getCode(), $e);
        }

        $valueMap = array_flip($this->choiceList->getValuesForChoices($array));

        foreach ($values as $i => $value) {
            $values[$i] = isset($valueMap[$value]);
        }

        return $values;
    }

    /**
     * Transforms a checkbox/radio button array to an array of choices.
     *
     * The input value is an array with the choices as keys and true/false as
     * values, depending on whether a given choice is selected. The output
     * is an array with the selected choices.
     *
     * @param mixed $values An array
     *
     * @return mixed An array
     *
     * @throws TransformationFailedException If the given value is not an array,
     *                                       if the recuperation of the choices
     *                                       fails or if some choice can't be
     *                                       found.
     */
    public function reverseTransform($values)
    {
        if (!is_array($values)) {
            throw new TransformationFailedException('Expected an array.');
        }

        try {
            $choices = $this->choiceList->getChoices();
        } catch (\Exception $e) {
            throw new TransformationFailedException('Can not get the choice list', $e->getCode(), $e);
        }

        $result = array();
        $unknown = array();

        foreach ($values as $i => $selected) {
            if ($selected) {
                if (isset($choices[$i])) {
                    $result[] = $choices[$i];
                } else {
                    $unknown[] = $i;
                }
            }
        }

        if (count($unknown) > 0) {
            throw new TransformationFailedException(sprintf('The choices "%s" were not found', implode('", "', $unknown)));
        }

        return $result;
    }
}
PK��Z���ggTSymfony/Component/Form/Extension/Core/DataTransformer/ChoicesToValuesTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\DataTransformer;

use Symfony\Component\Form\Exception\TransformationFailedException;

use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ChoicesToValuesTransformer implements DataTransformerInterface
{
    private $choiceList;

    /**
     * Constructor.
     *
     * @param ChoiceListInterface $choiceList
     */
    public function __construct(ChoiceListInterface $choiceList)
    {
        $this->choiceList = $choiceList;
    }

    /**
     * @param array $array
     *
     * @return array
     *
     * @throws TransformationFailedException If the given value is not an array.
     */
    public function transform($array)
    {
        if (null === $array) {
            return array();
        }

        if (!is_array($array)) {
            throw new TransformationFailedException('Expected an array.');
        }

        return $this->choiceList->getValuesForChoices($array);
    }

    /**
     * @param array $array
     *
     * @return array
     *
     * @throws TransformationFailedException If the given value is not an array
     *                                       or if no matching choice could be
     *                                       found for some given value.
     */
    public function reverseTransform($array)
    {
        if (null === $array) {
            return array();
        }

        if (!is_array($array)) {
            throw new TransformationFailedException('Expected an array.');
        }

        $choices = $this->choiceList->getChoicesForValues($array);

        if (count($choices) !== count($array)) {
            throw new TransformationFailedException('Could not find all matching choices for the given values');
        }

        return $choices;
    }
}
PK��ZUd�q]Symfony/Component/Form/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\DataTransformer;

/**
 * Transforms between an integer and a localized number with grouping
 * (each thousand) and comma separators.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class IntegerToLocalizedStringTransformer extends NumberToLocalizedStringTransformer
{
    /**
     * Constructs a transformer.
     *
     * @param integer $precision    Unused.
     * @param Boolean $grouping     Whether thousands should be grouped.
     * @param integer $roundingMode One of the ROUND_ constants in this class.
     */
    public function __construct($precision = 0, $grouping = false, $roundingMode = self::ROUND_DOWN)
    {
        if (null === $roundingMode) {
            $roundingMode = self::ROUND_DOWN;
        }

        parent::__construct(0, $grouping, $roundingMode);
    }

    /**
     * {@inheritDoc}
     */
    public function reverseTransform($value)
    {
        $result = parent::reverseTransform($value);

        return null !== $result ? (int) $result : null;
    }
}
PK��ZΎgW� � USymfony/Component/Form/Extension/Core/DataTransformer/DateTimeToStringTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\DataTransformer;

use Symfony\Component\Form\Exception\TransformationFailedException;
use Symfony\Component\Form\Exception\UnexpectedTypeException;

/**
 * Transforms between a date string and a DateTime object
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 * @author Florian Eckerstorfer <florian@eckerstorfer.org>
 */
class DateTimeToStringTransformer extends BaseDateTimeTransformer
{
    /**
     * Format used for generating strings
     * @var string
     */
    private $generateFormat;

    /**
     * Format used for parsing strings
     *
     * Different than the {@link $generateFormat} because formats for parsing
     * support additional characters in PHP that are not supported for
     * generating strings.
     *
     * @var string
     */
    private $parseFormat;

    /**
     * Whether to parse by appending a pipe "|" to the parse format.
     *
     * This only works as of PHP 5.3.7.
     *
     * @var Boolean
     */
    private $parseUsingPipe;

    /**
     * Transforms a \DateTime instance to a string
     *
     * @see \DateTime::format() for supported formats
     *
     * @param string  $inputTimezone  The name of the input timezone
     * @param string  $outputTimezone The name of the output timezone
     * @param string  $format         The date format
     * @param Boolean $parseUsingPipe Whether to parse by appending a pipe "|" to the parse format
     *
     * @throws UnexpectedTypeException if a timezone is not a string
     */
    public function __construct($inputTimezone = null, $outputTimezone = null, $format = 'Y-m-d H:i:s', $parseUsingPipe = null)
    {
        parent::__construct($inputTimezone, $outputTimezone);

        $this->generateFormat = $this->parseFormat = $format;

        // The pipe in the parser pattern only works as of PHP 5.3.7
        // See http://bugs.php.net/54316
        $this->parseUsingPipe = null === $parseUsingPipe
            ? version_compare(phpversion(), '5.3.7', '>=')
            : $parseUsingPipe;

        // See http://php.net/manual/en/datetime.createfromformat.php
        // The character "|" in the format makes sure that the parts of a date
        // that are *not* specified in the format are reset to the corresponding
        // values from 1970-01-01 00:00:00 instead of the current time.
        // Without "|" and "Y-m-d", "2010-02-03" becomes "2010-02-03 12:32:47",
        // where the time corresponds to the current server time.
        // With "|" and "Y-m-d", "2010-02-03" becomes "2010-02-03 00:00:00",
        // which is at least deterministic and thus used here.
        if ($this->parseUsingPipe && false === strpos($this->parseFormat, '|')) {
            $this->parseFormat .= '|';
        }
    }

    /**
     * Transforms a DateTime object into a date string with the configured format
     * and timezone
     *
     * @param \DateTime $value A DateTime object
     *
     * @return string A value as produced by PHP's date() function
     *
     * @throws TransformationFailedException If the given value is not a \DateTime
     *                                       instance or if the output timezone
     *                                       is not supported.
     */
    public function transform($value)
    {
        if (null === $value) {
            return '';
        }

        if (!$value instanceof \DateTime) {
            throw new TransformationFailedException('Expected a \DateTime.');
        }

        $value = clone $value;
        try {
            $value->setTimezone(new \DateTimeZone($this->outputTimezone));
        } catch (\Exception $e) {
            throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
        }

        return $value->format($this->generateFormat);
    }

    /**
     * Transforms a date string in the configured timezone into a DateTime object.
     *
     * @param string $value A value as produced by PHP's date() function
     *
     * @return \DateTime An instance of \DateTime
     *
     * @throws TransformationFailedException If the given value is not a string,
     *                                       if the date could not be parsed or
     *                                       if the input timezone is not supported.
     */
    public function reverseTransform($value)
    {
        if (empty($value)) {
            return null;
        }

        if (!is_string($value)) {
            throw new TransformationFailedException('Expected a string.');
        }

        try {
            $outputTz = new \DateTimeZone($this->outputTimezone);
            $dateTime = \DateTime::createFromFormat($this->parseFormat, $value, $outputTz);

            $lastErrors = \DateTime::getLastErrors();

            if (0 < $lastErrors['warning_count'] || 0 < $lastErrors['error_count']) {
                throw new TransformationFailedException(
                    implode(', ', array_merge(
                        array_values($lastErrors['warnings']),
                        array_values($lastErrors['errors'])
                    ))
                );
            }

            // On PHP versions < 5.3.7 we need to emulate the pipe operator
            // and reset parts not given in the format to their equivalent
            // of the UNIX base timestamp.
            if (!$this->parseUsingPipe) {
                list($year, $month, $day, $hour, $minute, $second) = explode('-', $dateTime->format('Y-m-d-H-i-s'));

                // Check which of the date parts are present in the pattern
                preg_match(
                    '/(' .
                    '(?P<day>[djDl])|' .
                    '(?P<month>[FMmn])|' .
                    '(?P<year>[Yy])|' .
                    '(?P<hour>[ghGH])|' .
                    '(?P<minute>i)|' .
                    '(?P<second>s)|' .
                    '(?P<dayofyear>z)|' .
                    '(?P<timestamp>U)|' .
                    '[^djDlFMmnYyghGHiszU]' .
                    ')*/',
                    $this->parseFormat,
                    $matches
                );

                // preg_match() does not guarantee to set all indices, so
                // set them unless given
                $matches = array_merge(array(
                    'day' => false,
                    'month' => false,
                    'year' => false,
                    'hour' => false,
                    'minute' => false,
                    'second' => false,
                    'dayofyear' => false,
                    'timestamp' => false,
                ), $matches);

                // Reset all parts that don't exist in the format to the
                // corresponding part of the UNIX base timestamp
                if (!$matches['timestamp']) {
                    if (!$matches['dayofyear']) {
                        if (!$matches['day']) {
                            $day = 1;
                        }
                        if (!$matches['month']) {
                            $month = 1;
                        }
                    }
                    if (!$matches['year']) {
                        $year = 1970;
                    }
                    if (!$matches['hour']) {
                        $hour = 0;
                    }
                    if (!$matches['minute']) {
                        $minute = 0;
                    }
                    if (!$matches['second']) {
                        $second = 0;
                    }
                    $dateTime->setDate($year, $month, $day);
                    $dateTime->setTime($hour, $minute, $second);
                }
            }

            if ($this->inputTimezone !== $this->outputTimezone) {
                $dateTime->setTimeZone(new \DateTimeZone($this->inputTimezone));
            }
        } catch (TransformationFailedException $e) {
            throw $e;
        } catch (\Exception $e) {
            throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
        }

        return $dateTime;
    }
}
PK��Z�"h���RSymfony/Component/Form/Extension/Core/DataTransformer/ChoiceToValueTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\DataTransformer;

use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ChoiceToValueTransformer implements DataTransformerInterface
{
    private $choiceList;

    /**
     * Constructor.
     *
     * @param ChoiceListInterface $choiceList
     */
    public function __construct(ChoiceListInterface $choiceList)
    {
        $this->choiceList = $choiceList;
    }

    public function transform($choice)
    {
        return (string) current($this->choiceList->getValuesForChoices(array($choice)));
    }

    public function reverseTransform($value)
    {
        if (null !== $value && !is_scalar($value)) {
            throw new TransformationFailedException('Expected a scalar.');
        }

        // These are now valid ChoiceList values, so we can return null
        // right away
        if ('' === $value || null === $value) {
            return null;
        }

        $choices = $this->choiceList->getChoicesForValues(array($value));

        if (1 !== count($choices)) {
            throw new TransformationFailedException(sprintf('The choice "%s" does not exist or is not unique', $value));
        }

        $choice = current($choices);

        return '' === $choice ? null : $choice;
    }
}
PK��Z�H��		QSymfony/Component/Form/Extension/Core/DataTransformer/ArrayToPartsTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\DataTransformer;

use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ArrayToPartsTransformer implements DataTransformerInterface
{
    private $partMapping;

    public function __construct(array $partMapping)
    {
        $this->partMapping = $partMapping;
    }

    public function transform($array)
    {
        if (null === $array) {
            $array = array();
        }

        if (!is_array($array) ) {
            throw new TransformationFailedException('Expected an array.');
        }

        $result = array();

        foreach ($this->partMapping as $partKey => $originalKeys) {
            if (empty($array)) {
                $result[$partKey] = null;
            } else {
                $result[$partKey] = array_intersect_key($array, array_flip($originalKeys));
            }
        }

        return $result;
    }

    public function reverseTransform($array)
    {
        if (!is_array($array) ) {
            throw new TransformationFailedException('Expected an array.');
        }

        $result = array();
        $emptyKeys = array();

        foreach ($this->partMapping as $partKey => $originalKeys) {
            if (!empty($array[$partKey])) {
                foreach ($originalKeys as $originalKey) {
                    if (isset($array[$partKey][$originalKey])) {
                        $result[$originalKey] = $array[$partKey][$originalKey];
                    }
                }
            } else {
                $emptyKeys[] = $partKey;
            }
        }

        if (count($emptyKeys) > 0) {
            if (count($emptyKeys) === count($this->partMapping)) {
                // All parts empty
                return null;
            }

            throw new TransformationFailedException(
                sprintf('The keys "%s" should not be empty', implode('", "', $emptyKeys)
            ));
        }

        return $result;
    }
}
PK��Z/C���QSymfony/Component/Form/Extension/Core/DataTransformer/BaseDateTimeTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\DataTransformer;

use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\InvalidArgumentException;
use Symfony\Component\Form\Exception\UnexpectedTypeException;

abstract class BaseDateTimeTransformer implements DataTransformerInterface
{
    protected static $formats = array(
        \IntlDateFormatter::NONE,
        \IntlDateFormatter::FULL,
        \IntlDateFormatter::LONG,
        \IntlDateFormatter::MEDIUM,
        \IntlDateFormatter::SHORT,
    );

    protected $inputTimezone;

    protected $outputTimezone;

    /**
     * Constructor.
     *
     * @param string $inputTimezone  The name of the input timezone
     * @param string $outputTimezone The name of the output timezone
     *
     * @throws UnexpectedTypeException if a timezone is not a string
     * @throws InvalidArgumentException if a timezone is not valid
     */
    public function __construct($inputTimezone = null, $outputTimezone = null)
    {
        if (!is_string($inputTimezone) && null !== $inputTimezone) {
            throw new UnexpectedTypeException($inputTimezone, 'string');
        }

        if (!is_string($outputTimezone) && null !== $outputTimezone) {
            throw new UnexpectedTypeException($outputTimezone, 'string');
        }

        $this->inputTimezone = $inputTimezone ?: date_default_timezone_get();
        $this->outputTimezone = $outputTimezone ?: date_default_timezone_get();

        // Check if input and output timezones are valid
        try {
            new \DateTimeZone($this->inputTimezone);
        } catch (\Exception $e) {
            throw new InvalidArgumentException(sprintf('Input timezone is invalid: %s.', $this->inputTimezone), $e->getCode(), $e);
        }

        try {
            new \DateTimeZone($this->outputTimezone);
        } catch (\Exception $e) {
            throw new InvalidArgumentException(sprintf('Output timezone is invalid: %s.', $this->outputTimezone), $e->getCode(), $e);
        }
    }
}
PK��Z���T��TSymfony/Component/Form/Extension/Core/DataTransformer/BooleanToStringTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\DataTransformer;

use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;

/**
 * Transforms between a Boolean and a string.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 * @author Florian Eckerstorfer <florian@eckerstorfer.org>
 */
class BooleanToStringTransformer implements DataTransformerInterface
{
    /**
     * The value emitted upon transform if the input is true
     * @var string
     */
    private $trueValue;

    /**
     * Sets the value emitted upon transform if the input is true.
     *
     * @param string $trueValue
     */
    public function __construct($trueValue)
    {
        $this->trueValue = $trueValue;
    }

    /**
     * Transforms a Boolean into a string.
     *
     * @param Boolean $value Boolean value.
     *
     * @return string String value.
     *
     * @throws TransformationFailedException If the given value is not a Boolean.
     */
    public function transform($value)
    {
        if (null === $value) {
            return null;
        }

        if (!is_bool($value)) {
            throw new TransformationFailedException('Expected a Boolean.');
        }

        return $value ? $this->trueValue : null;
    }

    /**
     * Transforms a string into a Boolean.
     *
     * @param string $value String value.
     *
     * @return Boolean Boolean value.
     *
     * @throws TransformationFailedException If the given value is not a string.
     */
    public function reverseTransform($value)
    {
        if (null === $value) {
            return false;
        }

        if (!is_string($value)) {
            throw new TransformationFailedException('Expected a string.');
        }

        return true;
    }

}
PK��Z]��yD	D	[Symfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\DataTransformer;

use Symfony\Component\Form\Exception\TransformationFailedException;

/**
 * Transforms between a normalized format and a localized money string.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 * @author Florian Eckerstorfer <florian@eckerstorfer.org>
 */
class MoneyToLocalizedStringTransformer extends NumberToLocalizedStringTransformer
{
    private $divisor;

    public function __construct($precision = 2, $grouping = true, $roundingMode = self::ROUND_HALF_UP, $divisor = 1)
    {
        if (null === $grouping) {
            $grouping = true;
        }

        if (null === $precision) {
            $precision = 2;
        }

        parent::__construct($precision, $grouping, $roundingMode);

        if (null === $divisor) {
            $divisor = 1;
        }

        $this->divisor = $divisor;
    }

    /**
     * Transforms a normalized format into a localized money string.
     *
     * @param number $value Normalized number
     *
     * @return string Localized money string.
     *
     * @throws TransformationFailedException If the given value is not numeric or
     *                                       if the value can not be transformed.
     */
    public function transform($value)
    {
        if (null !== $value) {
            if (!is_numeric($value)) {
                throw new TransformationFailedException('Expected a numeric.');
            }

            $value /= $this->divisor;
        }

        return parent::transform($value);
    }

    /**
     * Transforms a localized money string into a normalized format.
     *
     * @param string $value Localized money string
     *
     * @return number Normalized number
     *
     * @throws TransformationFailedException If the given value is not a string
     *                                       or if the value can not be transformed.
     */
    public function reverseTransform($value)
    {
        $value = parent::reverseTransform($value);

        if (null !== $value) {
            $value *= $this->divisor;
        }

        return $value;
    }

}
PK��Z���/�+�+9Symfony/Component/Form/Extension/Core/Type/ChoiceType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\View\ChoiceView;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\Exception\LogicException;
use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList;
use Symfony\Component\Form\Extension\Core\EventListener\FixRadioInputListener;
use Symfony\Component\Form\Extension\Core\EventListener\FixCheckboxInputListener;
use Symfony\Component\Form\Extension\Core\EventListener\MergeCollectionListener;
use Symfony\Component\Form\Extension\Core\DataTransformer\ChoiceToValueTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\ChoiceToBooleanArrayTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\ChoicesToValuesTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\ChoicesToBooleanArrayTransformer;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class ChoiceType extends AbstractType
{
    /**
     * Caches created choice lists.
     * @var array
     */
    private $choiceListCache = array();

    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        if (!$options['choice_list'] && !is_array($options['choices']) && !$options['choices'] instanceof \Traversable) {
            throw new LogicException('Either the option "choices" or "choice_list" must be set.');
        }

        if ($options['expanded']) {
            // Initialize all choices before doing the index check below.
            // This helps in cases where index checks are optimized for non
            // initialized choice lists. For example, when using an SQL driver,
            // the index check would read in one SQL query and the initialization
            // requires another SQL query. When the initialization is done first,
            // one SQL query is sufficient.
            $preferredViews = $options['choice_list']->getPreferredViews();
            $remainingViews = $options['choice_list']->getRemainingViews();

            // Check if the choices already contain the empty value
            // Only add the empty value option if this is not the case
            if (null !== $options['empty_value'] && 0 === count($options['choice_list']->getChoicesForValues(array('')))) {
                $placeholderView = new ChoiceView(null, '', $options['empty_value']);

                // "placeholder" is a reserved index
                // see also ChoiceListInterface::getIndicesForChoices()
                $this->addSubForms($builder, array('placeholder' => $placeholderView), $options);
            }

            $this->addSubForms($builder, $preferredViews, $options);
            $this->addSubForms($builder, $remainingViews, $options);

            if ($options['multiple']) {
                $builder->addViewTransformer(new ChoicesToBooleanArrayTransformer($options['choice_list']));
                $builder->addEventSubscriber(new FixCheckboxInputListener($options['choice_list']), 10);
            } else {
                $builder->addViewTransformer(new ChoiceToBooleanArrayTransformer($options['choice_list'], $builder->has('placeholder')));
                $builder->addEventSubscriber(new FixRadioInputListener($options['choice_list'], $builder->has('placeholder')), 10);
            }
        } else {
            if ($options['multiple']) {
                $builder->addViewTransformer(new ChoicesToValuesTransformer($options['choice_list']));
            } else {
                $builder->addViewTransformer(new ChoiceToValueTransformer($options['choice_list']));
            }
        }

        if ($options['multiple'] && $options['by_reference']) {
            // Make sure the collection created during the client->norm
            // transformation is merged back into the original collection
            $builder->addEventSubscriber(new MergeCollectionListener(true, true));
        }
    }

    /**
     * {@inheritdoc}
     */
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        $view->vars = array_replace($view->vars, array(
            'multiple'          => $options['multiple'],
            'expanded'          => $options['expanded'],
            'preferred_choices' => $options['choice_list']->getPreferredViews(),
            'choices'           => $options['choice_list']->getRemainingViews(),
            'separator'         => '-------------------',
            'empty_value'       => null,
        ));

        // The decision, whether a choice is selected, is potentially done
        // thousand of times during the rendering of a template. Provide a
        // closure here that is optimized for the value of the form, to
        // avoid making the type check inside the closure.
        if ($options['multiple']) {
            $view->vars['is_selected'] = function ($choice, array $values) {
                return false !== array_search($choice, $values, true);
            };
        } else {
            $view->vars['is_selected'] = function ($choice, $value) {
                return $choice === $value;
            };
        }

        // Check if the choices already contain the empty value
        $view->vars['empty_value_in_choices'] = 0 !== count($options['choice_list']->getChoicesForValues(array('')));

        // Only add the empty value option if this is not the case
        if (null !== $options['empty_value'] && !$view->vars['empty_value_in_choices']) {
            $view->vars['empty_value'] = $options['empty_value'];
        }

        if ($options['multiple'] && !$options['expanded']) {
            // Add "[]" to the name in case a select tag with multiple options is
            // displayed. Otherwise only one of the selected options is sent in the
            // POST request.
            $view->vars['full_name'] = $view->vars['full_name'].'[]';
        }
    }

    /**
     * {@inheritdoc}
     */
    public function finishView(FormView $view, FormInterface $form, array $options)
    {
        if ($options['expanded']) {
            // Radio buttons should have the same name as the parent
            $childName = $view->vars['full_name'];

            // Checkboxes should append "[]" to allow multiple selection
            if ($options['multiple']) {
                $childName .= '[]';
            }

            foreach ($view as $childView) {
                $childView->vars['full_name'] = $childName;
            }
        }
    }

    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $choiceListCache =& $this->choiceListCache;

        $choiceList = function (Options $options) use (&$choiceListCache) {
            // Harden against NULL values (like in EntityType and ModelType)
            $choices = null !== $options['choices'] ? $options['choices'] : array();

            // Reuse existing choice lists in order to increase performance
            $hash = hash('sha256', json_encode(array($choices, $options['preferred_choices'])));

            if (!isset($choiceListCache[$hash])) {
                $choiceListCache[$hash] = new SimpleChoiceList($choices, $options['preferred_choices']);
            }

            return $choiceListCache[$hash];
        };

        $emptyData = function (Options $options) {
            if ($options['multiple'] || $options['expanded']) {
                return array();
            }

            return '';
        };

        $emptyValue = function (Options $options) {
            return $options['required'] ? null : '';
        };

        $emptyValueNormalizer = function (Options $options, $emptyValue) {
            if ($options['multiple']) {
                // never use an empty value for this case
                return null;
            } elseif (false === $emptyValue) {
                // an empty value should be added but the user decided otherwise
                return null;
            } elseif ($options['expanded'] && '' === $emptyValue) {
                // never use an empty label for radio buttons
                return 'None';
            }

            // empty value has been set explicitly
            return $emptyValue;
        };

        $compound = function (Options $options) {
            return $options['expanded'];
        };

        $resolver->setDefaults(array(
            'multiple'          => false,
            'expanded'          => false,
            'choice_list'       => $choiceList,
            'choices'           => array(),
            'preferred_choices' => array(),
            'empty_data'        => $emptyData,
            'empty_value'       => $emptyValue,
            'error_bubbling'    => false,
            'compound'          => $compound,
            // The view data is always a string, even if the "data" option
            // is manually set to an object.
            // See https://github.com/symfony/symfony/pull/5582
            'data_class'        => null,
        ));

        $resolver->setNormalizers(array(
            'empty_value' => $emptyValueNormalizer,
        ));

        $resolver->setAllowedTypes(array(
            'choice_list' => array('null', 'Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface'),
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'choice';
    }

    /**
     * Adds the sub fields for an expanded choice field.
     *
     * @param FormBuilderInterface $builder     The form builder.
     * @param array                $choiceViews The choice view objects.
     * @param array                $options     The build options.
     */
    private function addSubForms(FormBuilderInterface $builder, array $choiceViews, array $options)
    {
        foreach ($choiceViews as $i => $choiceView) {
            if (is_array($choiceView)) {
                // Flatten groups
                $this->addSubForms($builder, $choiceView, $options);
            } else {
                $choiceOpts = array(
                    'value' => $choiceView->value,
                    'label' => $choiceView->label,
                    'translation_domain' => $options['translation_domain'],
                );

                if ($options['multiple']) {
                    $choiceType = 'checkbox';
                    // The user can check 0 or more checkboxes. If required
                    // is true, he is required to check all of them.
                    $choiceOpts['required'] = false;
                } else {
                    $choiceType = 'radio';
                }

                $builder->add($i, $choiceType, $choiceOpts);
            }
        }
    }
}
PK��Z��h��9Symfony/Component/Form/Extension/Core/Type/ButtonType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\ButtonTypeInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

/**
 * A form button.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ButtonType extends BaseType implements ButtonTypeInterface
{
    /**
     * {@inheritdoc}
     */
    public function getParent()
    {
        return null;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'button';
    }

    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        parent::setDefaultOptions($resolver);

        $resolver->setDefaults(array(
            'auto_initialize' => false,
        ));
    }
}
PK��ZD�U��9Symfony/Component/Form/Extension/Core/Type/SubmitType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\SubmitButtonTypeInterface;

/**
 * A submit button.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class SubmitType extends AbstractType implements SubmitButtonTypeInterface
{
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        $view->vars['clicked'] = $form->isClicked();
    }

    /**
     * {@inheritdoc}
     */
    public function getParent()
    {
        return 'button';
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'submit';
    }
}
PK��Z񍢸��;Symfony/Component/Form/Extension/Core/Type/CurrencyType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Intl\Intl;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class CurrencyType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'choices' => Intl::getCurrencyBundle()->getCurrencyNames(),
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getParent()
    {
        return 'choice';
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'currency';
    }
}
PK��Z�Ѝ'��9Symfony/Component/Form/Extension/Core/Type/HiddenType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class HiddenType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            // hidden fields cannot have a required attribute
            'required'       => false,
            // Pass errors to the parent
            'error_bubbling' => true,
            'compound'       => false,
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'hidden';
    }
}
PK��Z���D��9Symfony/Component/Form/Extension/Core/Type/LocaleType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Intl\Intl;
use Symfony\Component\Locale\Locale;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class LocaleType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'choices' => Intl::getLocaleBundle()->getLocaleNames(),
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getParent()
    {
        return 'choice';
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'locale';
    }
}
PK��ZuƵ�``:Symfony/Component/Form/Extension/Core/Type/IntegerType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\DataTransformer\IntegerToLocalizedStringTransformer;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class IntegerType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->addViewTransformer(
            new IntegerToLocalizedStringTransformer(
                $options['precision'],
                $options['grouping'],
                $options['rounding_mode']
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            // default precision is locale specific (usually around 3)
            'precision'     => null,
            'grouping'      => false,
            // Integer cast rounds towards 0, so do the same when displaying fractions
            'rounding_mode' => IntegerToLocalizedStringTransformer::ROUND_DOWN,
            'compound'      => false,
        ));

        $resolver->setAllowedValues(array(
            'rounding_mode' => array(
                IntegerToLocalizedStringTransformer::ROUND_FLOOR,
                IntegerToLocalizedStringTransformer::ROUND_DOWN,
                IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN,
                IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN,
                IntegerToLocalizedStringTransformer::ROUND_HALF_UP,
                IntegerToLocalizedStringTransformer::ROUND_UP,
                IntegerToLocalizedStringTransformer::ROUND_CEILING,
            ),
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'integer';
    }
}
PK��Za����8Symfony/Component/Form/Extension/Core/Type/ResetType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\ButtonTypeInterface;

/**
 * A reset button.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ResetType extends AbstractType implements ButtonTypeInterface
{
    /**
     * {@inheritdoc}
     */
    public function getParent()
    {
        return 'button';
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'reset';
    }
}
PK��Z옇���;Symfony/Component/Form/Extension/Core/Type/PasswordType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class PasswordType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        if ($options['always_empty'] || !$form->isSubmitted()) {
            $view->vars['value'] = '';
        }
    }

    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'always_empty' => true,
            'trim'         => false,
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getParent()
    {
        return 'text';
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'password';
    }
}
PK��Zٝ��GG7Symfony/Component/Form/Extension/Core/Type/BaseType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

/**
 * Encapsulates common logic of {@link FormType} and {@link ButtonType}.
 *
 * This type does not appear in the form's type inheritance chain and as such
 * cannot be extended (via {@link FormTypeExtension}s) nor themed.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
abstract class BaseType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->setDisabled($options['disabled']);
        $builder->setAutoInitialize($options['auto_initialize']);
    }

    /**
     * {@inheritdoc}
     */
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        $name = $form->getName();
        $blockName = $options['block_name'] ?: $form->getName();
        $translationDomain = $options['translation_domain'];

        if ($view->parent) {
            if ('' !== ($parentFullName = $view->parent->vars['full_name'])) {
                $id = sprintf('%s_%s', $view->parent->vars['id'], $name);
                $fullName = sprintf('%s[%s]', $parentFullName, $name);
                $uniqueBlockPrefix = sprintf('%s_%s', $view->parent->vars['unique_block_prefix'], $blockName);
            } else {
                $id = $name;
                $fullName = $name;
                $uniqueBlockPrefix = '_'.$blockName;
            }

            if (!$translationDomain) {
                $translationDomain = $view->parent->vars['translation_domain'];
            }
        } else {
            $id = $name;
            $fullName = $name;
            $uniqueBlockPrefix = '_'.$blockName;

            // Strip leading underscores and digits. These are allowed in
            // form names, but not in HTML4 ID attributes.
            // http://www.w3.org/TR/html401/struct/global.html#adef-id
            $id = ltrim($id, '_0123456789');
        }

        $blockPrefixes = array();
        for ($type = $form->getConfig()->getType(); null !== $type; $type = $type->getParent()) {
            array_unshift($blockPrefixes, $type->getName());
        }
        $blockPrefixes[] = $uniqueBlockPrefix;

        if (!$translationDomain) {
            $translationDomain = 'messages';
        }

        $view->vars = array_replace($view->vars, array(
            'form'                => $view,
            'id'                  => $id,
            'name'                => $name,
            'full_name'           => $fullName,
            'disabled'            => $form->isDisabled(),
            'label'               => $options['label'],
            'multipart'           => false,
            'attr'                => $options['attr'],
            'block_prefixes'      => $blockPrefixes,
            'unique_block_prefix' => $uniqueBlockPrefix,
            'translation_domain'  => $translationDomain,
            // Using the block name here speeds up performance in collection
            // forms, where each entry has the same full block name.
            // Including the type is important too, because if rows of a
            // collection form have different types (dynamically), they should
            // be rendered differently.
            // https://github.com/symfony/symfony/issues/5038
            'cache_key'           => $uniqueBlockPrefix.'_'.$form->getConfig()->getType()->getName(),
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'block_name'         => null,
            'disabled'           => false,
            'label'              => null,
            'attr'               => array(),
            'translation_domain' => null,
            'auto_initialize'    => true,
        ));

        $resolver->setAllowedTypes(array(
            'attr'       => 'array',
        ));
    }
}
PK��ZZ���^^:Symfony/Component/Form/Extension/Core/Type/PercentType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\DataTransformer\PercentToLocalizedStringTransformer;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class PercentType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->addViewTransformer(new PercentToLocalizedStringTransformer($options['precision'], $options['type']));
    }

    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'precision' => 0,
            'type'      => 'fractional',
            'compound'  => false,
        ));

        $resolver->setAllowedValues(array(
            'type' => array(
                'fractional',
                'integer',
            ),
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'percent';
    }
}
PK��Z��TT;Symfony/Component/Form/Extension/Core/Type/CheckboxType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\Extension\Core\DataTransformer\BooleanToStringTransformer;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class CheckboxType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        // Unlike in other types, where the data is NULL by default, it
        // needs to be a Boolean here. setData(null) is not acceptable
        // for checkboxes and radio buttons (unless a custom model
        // transformer handles this case).
        // We cannot solve this case via overriding the "data" option, because
        // doing so also calls setDataLocked(true).
        $builder->setData(isset($options['data']) ? $options['data'] : false);
        $builder->addViewTransformer(new BooleanToStringTransformer($options['value']));
    }

    /**
     * {@inheritdoc}
     */
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        $view->vars = array_replace($view->vars, array(
            'value'   => $options['value'],
            'checked' => null !== $form->getViewData(),
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $emptyData = function (FormInterface $form, $viewData) {
            return $viewData;
        };

        $resolver->setDefaults(array(
            'value'      => '1',
            'empty_data' => $emptyData,
            'compound'   => false,
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'checkbox';
    }
}
PK��Z&ߏ�vv;Symfony/Component/Form/Extension/Core/Type/BirthdayType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class BirthdayType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'years' => range(date('Y') - 120, date('Y')),
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getParent()
    {
        return 'date';
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'birthday';
    }
}
PK��Z7pO�LL8Symfony/Component/Form/Extension/Core/Type/RadioType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;

class RadioType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function getParent()
    {
        return 'checkbox';
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'radio';
    }
}
PK��Z�G�oo7Symfony/Component/Form/Extension/Core/Type/FileType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class FileType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        $view->vars = array_replace($view->vars, array(
            'type'  => 'file',
            'value' => '',
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function finishView(FormView $view, FormInterface $form, array $options)
    {
        $view
            ->vars['multipart'] = true
        ;
    }

    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'compound' => false,
            'data_class' => 'Symfony\Component\HttpFoundation\File\File',
            'empty_data' => null,
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'file';
    }
}
PK��Z�8��JJ9Symfony/Component/Form/Extension/Core/Type/SearchType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;

class SearchType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function getParent()
    {
        return 'text';
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'search';
    }
}
PK��Z�_��LL;Symfony/Component/Form/Extension/Core/Type/TimezoneType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class TimezoneType extends AbstractType
{
    /**
     * Stores the available timezone choices
     * @var array
     */
    private static $timezones;

    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'choices' => self::getTimezones(),
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getParent()
    {
        return 'choice';
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'timezone';
    }

    /**
     * Returns the timezone choices.
     *
     * The choices are generated from the ICU function
     * \DateTimeZone::listIdentifiers(). They are cached during a single request,
     * so multiple timezone fields on the same page don't lead to unnecessary
     * overhead.
     *
     * @return array The timezone choices
     */
    public static function getTimezones()
    {
        if (null === static::$timezones) {
            static::$timezones = array();

            foreach (\DateTimeZone::listIdentifiers() as $timezone) {
                $parts = explode('/', $timezone);

                if (count($parts) > 2) {
                    $region = $parts[0];
                    $name = $parts[1].' - '.$parts[2];
                } elseif (count($parts) > 1) {
                    $region = $parts[0];
                    $name = $parts[1];
                } else {
                    $region = 'Other';
                    $name = $parts[0];
                }

                static::$timezones[$region][$timezone] = str_replace('_', ' ', $name);
            }
        }

        return static::$timezones;
    }
}
PK��Z���HH8Symfony/Component/Form/Extension/Core/Type/EmailType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;

class EmailType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function getParent()
    {
        return 'text';
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'email';
    }
}
PK��Z[Gԃ��=Symfony/Component/Form/Extension/Core/Type/CollectionType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\Extension\Core\EventListener\ResizeFormListener;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class CollectionType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        if ($options['allow_add'] && $options['prototype']) {
            $prototype = $builder->create($options['prototype_name'], $options['type'], array_replace(array(
                'label' => $options['prototype_name'].'label__',
            ), $options['options']));
            $builder->setAttribute('prototype', $prototype->getForm());
        }

        $resizeListener = new ResizeFormListener(
            $options['type'],
            $options['options'],
            $options['allow_add'],
            $options['allow_delete']
        );

        $builder->addEventSubscriber($resizeListener);
    }

    /**
     * {@inheritdoc}
     */
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        $view->vars = array_replace($view->vars, array(
            'allow_add'    => $options['allow_add'],
            'allow_delete' => $options['allow_delete'],
        ));

        if ($form->getConfig()->hasAttribute('prototype')) {
            $view->vars['prototype'] = $form->getConfig()->getAttribute('prototype')->createView($view);
        }
    }

    /**
     * {@inheritdoc}
     */
    public function finishView(FormView $view, FormInterface $form, array $options)
    {
        if ($form->getConfig()->hasAttribute('prototype') && $view->vars['prototype']->vars['multipart']) {
            $view->vars['multipart'] = true;
        }
    }

    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $optionsNormalizer = function (Options $options, $value) {
            $value['block_name'] = 'entry';

            return $value;
        };

        $resolver->setDefaults(array(
            'allow_add'      => false,
            'allow_delete'   => false,
            'prototype'      => true,
            'prototype_name' => '__name__',
            'type'           => 'text',
            'options'        => array(),
        ));

        $resolver->setNormalizers(array(
            'options' => $optionsNormalizer,
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'collection';
    }
}
PK��Z�t�II;Symfony/Component/Form/Extension/Core/Type/TextareaType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormInterface;

class TextareaType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        $view->vars['pattern'] = null;
    }

    /**
     * {@inheritdoc}
     */
    public function getParent()
    {
        return 'text';
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'textarea';
    }
}
PK��Z����;Symfony/Component/Form/Extension/Core/Type/LanguageType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Intl\Intl;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class LanguageType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'choices' => Intl::getLanguageBundle()->getLanguageNames(),
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getParent()
    {
        return 'choice';
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'language';
    }
}
PK��ZT;���7Symfony/Component/Form/Extension/Core/Type/TextType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class TextType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'compound' => false,
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'text';
    }
}
PK��ZH?!a��7Symfony/Component/Form/Extension/Core/Type/TimeType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\ReversedTransformer;
use Symfony\Component\Form\Exception\InvalidConfigurationException;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class TimeType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $parts  = array('hour');
        $format = 'H';

        if ($options['with_seconds'] && !$options['with_minutes']) {
            throw new InvalidConfigurationException('You can not disable minutes if you have enabled seconds.');
        }

        if ($options['with_minutes']) {
            $format .= ':i';
            $parts[] = 'minute';
        }

        if ($options['with_seconds']) {
            $format .= ':s';
            $parts[] = 'second';
        }

        if ('single_text' === $options['widget']) {
            $builder->addViewTransformer(new DateTimeToStringTransformer($options['model_timezone'], $options['view_timezone'], $format));
        } else {
            $hourOptions = $minuteOptions = $secondOptions = array(
                'error_bubbling' => true,
            );

            if ('choice' === $options['widget']) {
                $hours = $minutes = array();

                foreach ($options['hours'] as $hour) {
                    $hours[$hour] = str_pad($hour, 2, '0', STR_PAD_LEFT);
                }

                // Only pass a subset of the options to children
                $hourOptions['choices'] = $hours;
                $hourOptions['empty_value'] = $options['empty_value']['hour'];

                if ($options['with_minutes']) {
                    foreach ($options['minutes'] as $minute) {
                        $minutes[$minute] = str_pad($minute, 2, '0', STR_PAD_LEFT);
                    }

                    $minuteOptions['choices'] = $minutes;
                    $minuteOptions['empty_value'] = $options['empty_value']['minute'];
                }

                if ($options['with_seconds']) {
                    $seconds = array();

                    foreach ($options['seconds'] as $second) {
                        $seconds[$second] = str_pad($second, 2, '0', STR_PAD_LEFT);
                    }

                    $secondOptions['choices'] = $seconds;
                    $secondOptions['empty_value'] = $options['empty_value']['second'];
                }

                // Append generic carry-along options
                foreach (array('required', 'translation_domain') as $passOpt) {
                    $hourOptions[$passOpt] = $options[$passOpt];

                    if ($options['with_minutes']) {
                        $minuteOptions[$passOpt] = $options[$passOpt];
                    }

                    if ($options['with_seconds']) {
                        $secondOptions[$passOpt] = $options[$passOpt];
                    }
                }
            }

            $builder->add('hour', $options['widget'], $hourOptions);

            if ($options['with_minutes']) {
                $builder->add('minute', $options['widget'], $minuteOptions);
            }

            if ($options['with_seconds']) {
                $builder->add('second', $options['widget'], $secondOptions);
            }

            $builder->addViewTransformer(new DateTimeToArrayTransformer($options['model_timezone'], $options['view_timezone'], $parts, 'text' === $options['widget']));
        }

        if ('string' === $options['input']) {
            $builder->addModelTransformer(new ReversedTransformer(
                new DateTimeToStringTransformer($options['model_timezone'], $options['model_timezone'], 'H:i:s')
            ));
        } elseif ('timestamp' === $options['input']) {
            $builder->addModelTransformer(new ReversedTransformer(
                new DateTimeToTimestampTransformer($options['model_timezone'], $options['model_timezone'])
            ));
        } elseif ('array' === $options['input']) {
            $builder->addModelTransformer(new ReversedTransformer(
                new DateTimeToArrayTransformer($options['model_timezone'], $options['model_timezone'], $parts)
            ));
        }
    }

    /**
     * {@inheritdoc}
     */
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        $view->vars = array_replace($view->vars, array(
            'widget'       => $options['widget'],
            'with_minutes' => $options['with_minutes'],
            'with_seconds' => $options['with_seconds'],
        ));

        if ('single_text' === $options['widget']) {
            $view->vars['type'] = 'time';
        }
    }

    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $compound = function (Options $options) {
            return $options['widget'] !== 'single_text';
        };

        $emptyValue = $emptyValueDefault = function (Options $options) {
            return $options['required'] ? null : '';
        };

        $emptyValueNormalizer = function (Options $options, $emptyValue) use ($emptyValueDefault) {
            if (is_array($emptyValue)) {
                $default = $emptyValueDefault($options);

                return array_merge(
                    array('hour' => $default, 'minute' => $default, 'second' => $default),
                    $emptyValue
                );
            }

            return array(
                'hour' => $emptyValue,
                'minute' => $emptyValue,
                'second' => $emptyValue
            );
        };

        $resolver->setDefaults(array(
            'hours'          => range(0, 23),
            'minutes'        => range(0, 59),
            'seconds'        => range(0, 59),
            'widget'         => 'choice',
            'input'          => 'datetime',
            'with_minutes'   => true,
            'with_seconds'   => false,
            'model_timezone' => null,
            'view_timezone'  => null,
            'empty_value'    => $emptyValue,
            // Don't modify \DateTime classes by reference, we treat
            // them like immutable value objects
            'by_reference'   => false,
            'error_bubbling' => false,
            // If initialized with a \DateTime object, FormType initializes
            // this option to "\DateTime". Since the internal, normalized
            // representation is not \DateTime, but an array, we need to unset
            // this option.
            'data_class'     => null,
            'compound'       => $compound,
        ));

        $resolver->setNormalizers(array(
            'empty_value' => $emptyValueNormalizer,
        ));

        $resolver->setAllowedValues(array(
            'input' => array(
                'datetime',
                'string',
                'timestamp',
                'array',
            ),
            'widget' => array(
                'single_text',
                'text',
                'choice',
            ),
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'time';
    }
}
PK��Z�� &�'�';Symfony/Component/Form/Extension/Core/Type/DateTimeType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\ReversedTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\DataTransformerChain;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToLocalizedStringTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToRfc3339Transformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\ArrayToPartsTransformer;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class DateTimeType extends AbstractType
{
    const DEFAULT_DATE_FORMAT = \IntlDateFormatter::MEDIUM;

    const DEFAULT_TIME_FORMAT = \IntlDateFormatter::MEDIUM;

    /**
     * This is not quite the HTML5 format yet, because ICU lacks the
     * capability of parsing and generating RFC 3339 dates, which
     * are like the below pattern but with a timezone suffix. The
     * timezone suffix is
     *
     *  * "Z" for UTC
     *  * "(-|+)HH:mm" for other timezones (note the colon!)
     *
     * For more information see:
     *
     * http://userguide.icu-project.org/formatparse/datetime#TOC-Date-Time-Format-Syntax
     * http://www.w3.org/TR/html-markup/input.datetime.html
     * http://tools.ietf.org/html/rfc3339
     *
     * An ICU ticket was created:
     * http://icu-project.org/trac/ticket/9421
     *
     * It was supposedly fixed, but is not available in all PHP installations
     * yet. To temporarily circumvent this issue, DateTimeToRfc3339Transformer
     * is used when the format matches this constant.
     */
    const HTML5_FORMAT = "yyyy-MM-dd'T'HH:mm:ssZZZZZ";

    private static $acceptedFormats = array(
        \IntlDateFormatter::FULL,
        \IntlDateFormatter::LONG,
        \IntlDateFormatter::MEDIUM,
        \IntlDateFormatter::SHORT,
    );

    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $parts = array('year', 'month', 'day', 'hour');
        $dateParts = array('year', 'month', 'day');
        $timeParts = array('hour');

        if ($options['with_minutes']) {
            $parts[] = 'minute';
            $timeParts[] = 'minute';
        }

        if ($options['with_seconds']) {
            $parts[] = 'second';
            $timeParts[] = 'second';
        }

        $dateFormat = is_int($options['date_format']) ? $options['date_format'] : self::DEFAULT_DATE_FORMAT;
        $timeFormat = self::DEFAULT_TIME_FORMAT;
        $calendar = \IntlDateFormatter::GREGORIAN;
        $pattern = is_string($options['format']) ? $options['format'] : null;

        if (!in_array($dateFormat, self::$acceptedFormats, true)) {
            throw new InvalidOptionsException('The "date_format" option must be one of the IntlDateFormatter constants (FULL, LONG, MEDIUM, SHORT) or a string representing a custom format.');
        }

        if ('single_text' === $options['widget']) {
            if (self::HTML5_FORMAT === $pattern) {
                $builder->addViewTransformer(new DateTimeToRfc3339Transformer(
                    $options['model_timezone'],
                    $options['view_timezone']
                ));
            } else {
                $builder->addViewTransformer(new DateTimeToLocalizedStringTransformer(
                    $options['model_timezone'],
                    $options['view_timezone'],
                    $dateFormat,
                    $timeFormat,
                    $calendar,
                    $pattern
                ));
            }
        } else {
            // Only pass a subset of the options to children
            $dateOptions = array_intersect_key($options, array_flip(array(
                'years',
                'months',
                'days',
                'empty_value',
                'required',
                'translation_domain',
            )));

            $timeOptions = array_intersect_key($options, array_flip(array(
                'hours',
                'minutes',
                'seconds',
                'with_minutes',
                'with_seconds',
                'empty_value',
                'required',
                'translation_domain',
            )));

            if (null !== $options['date_widget']) {
                $dateOptions['widget'] = $options['date_widget'];
            }

            if (null !== $options['time_widget']) {
                $timeOptions['widget'] = $options['time_widget'];
            }

            if (null !== $options['date_format']) {
                $dateOptions['format'] = $options['date_format'];
            }

            $dateOptions['input'] = $timeOptions['input'] = 'array';
            $dateOptions['error_bubbling'] = $timeOptions['error_bubbling'] = true;

            $builder
                ->addViewTransformer(new DataTransformerChain(array(
                    new DateTimeToArrayTransformer($options['model_timezone'], $options['view_timezone'], $parts),
                    new ArrayToPartsTransformer(array(
                        'date' => $dateParts,
                        'time' => $timeParts,
                    )),
                )))
                ->add('date', 'date', $dateOptions)
                ->add('time', 'time', $timeOptions)
            ;
        }

        if ('string' === $options['input']) {
            $builder->addModelTransformer(new ReversedTransformer(
                new DateTimeToStringTransformer($options['model_timezone'], $options['model_timezone'])
            ));
        } elseif ('timestamp' === $options['input']) {
            $builder->addModelTransformer(new ReversedTransformer(
                new DateTimeToTimestampTransformer($options['model_timezone'], $options['model_timezone'])
            ));
        } elseif ('array' === $options['input']) {
            $builder->addModelTransformer(new ReversedTransformer(
                new DateTimeToArrayTransformer($options['model_timezone'], $options['model_timezone'], $parts)
            ));
        }
    }

    /**
     * {@inheritdoc}
     */
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        $view->vars['widget'] = $options['widget'];

        // Change the input to a HTML5 date input if
        //  * the widget is set to "single_text"
        //  * the format matches the one expected by HTML5
        if ('single_text' === $options['widget'] && self::HTML5_FORMAT === $options['format']) {
            $view->vars['type'] = 'datetime';
        }
    }

    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $compound = function (Options $options) {
            return $options['widget'] !== 'single_text';
        };

        // Defaults to the value of "widget"
        $dateWidget = function (Options $options) {
            return $options['widget'];
        };

        // Defaults to the value of "widget"
        $timeWidget = function (Options $options) {
            return $options['widget'];
        };

        $resolver->setDefaults(array(
            'input'          => 'datetime',
            'model_timezone' => null,
            'view_timezone'  => null,
            'format'         => self::HTML5_FORMAT,
            'date_format'    => null,
            'widget'         => null,
            'date_widget'    => $dateWidget,
            'time_widget'    => $timeWidget,
            'with_minutes'   => true,
            'with_seconds'   => false,
            // Don't modify \DateTime classes by reference, we treat
            // them like immutable value objects
            'by_reference'   => false,
            'error_bubbling' => false,
            // If initialized with a \DateTime object, FormType initializes
            // this option to "\DateTime". Since the internal, normalized
            // representation is not \DateTime, but an array, we need to unset
            // this option.
            'data_class'     => null,
            'compound'       => $compound,
        ));

        // Don't add some defaults in order to preserve the defaults
        // set in DateType and TimeType
        $resolver->setOptional(array(
            'empty_value',
            'years',
            'months',
            'days',
            'hours',
            'minutes',
            'seconds',
        ));

        $resolver->setAllowedValues(array(
            'input'       => array(
                'datetime',
                'string',
                'timestamp',
                'array',
            ),
            'date_widget' => array(
                null, // inherit default from DateType
                'single_text',
                'text',
                'choice',
            ),
            'time_widget' => array(
                null, // inherit default from TimeType
                'single_text',
                'text',
                'choice',
            ),
            // This option will overwrite "date_widget" and "time_widget" options
            'widget'     => array(
                null, // default, don't overwrite options
                'single_text',
                'text',
                'choice',
            ),
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'datetime';
    }
}
PK��Z�q���6Symfony/Component/Form/Extension/Core/Type/UrlType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\EventListener\FixUrlProtocolListener;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class UrlType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->addEventSubscriber(new FixUrlProtocolListener($options['default_protocol']));
    }

    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'default_protocol' => 'http',
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getParent()
    {
        return 'text';
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'url';
    }
}
PK��Z9�;Symfony/Component/Form/Extension/Core/Type/RepeatedType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\DataTransformer\ValueToDuplicatesTransformer;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class RepeatedType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        // Overwrite required option for child fields
        $options['first_options']['required']  = $options['required'];
        $options['second_options']['required'] = $options['required'];

        if (!isset($options['options']['error_bubbling'])) {
            $options['options']['error_bubbling'] = $options['error_bubbling'];
        }

        $builder
            ->addViewTransformer(new ValueToDuplicatesTransformer(array(
                $options['first_name'],
                $options['second_name'],
            )))
            ->add($options['first_name'], $options['type'], array_merge($options['options'], $options['first_options']))
            ->add($options['second_name'], $options['type'], array_merge($options['options'], $options['second_options']))
        ;
    }

    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'type'           => 'text',
            'options'        => array(),
            'first_options'  => array(),
            'second_options' => array(),
            'first_name'     => 'first',
            'second_name'    => 'second',
            'error_bubbling' => false,
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'repeated';
    }
}
PK��ZM2\3,3,7Symfony/Component/Form/Extension/Core/Type/DateType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToLocalizedStringTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer;
use Symfony\Component\Form\ReversedTransformer;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;

class DateType extends AbstractType
{
    const DEFAULT_FORMAT = \IntlDateFormatter::MEDIUM;

    const HTML5_FORMAT = 'yyyy-MM-dd';

    private static $acceptedFormats = array(
        \IntlDateFormatter::FULL,
        \IntlDateFormatter::LONG,
        \IntlDateFormatter::MEDIUM,
        \IntlDateFormatter::SHORT,
    );

    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $dateFormat = is_int($options['format']) ? $options['format'] : self::DEFAULT_FORMAT;
        $timeFormat = \IntlDateFormatter::NONE;
        $calendar = \IntlDateFormatter::GREGORIAN;
        $pattern = is_string($options['format']) ? $options['format'] : null;

        if (!in_array($dateFormat, self::$acceptedFormats, true)) {
            throw new InvalidOptionsException('The "format" option must be one of the IntlDateFormatter constants (FULL, LONG, MEDIUM, SHORT) or a string representing a custom format.');
        }

        if (null !== $pattern && (false === strpos($pattern, 'y') || false === strpos($pattern, 'M') || false === strpos($pattern, 'd'))) {
            throw new InvalidOptionsException(sprintf('The "format" option should contain the letters "y", "M" and "d". Its current value is "%s".', $pattern));
        }

        if ('single_text' === $options['widget']) {
            $builder->addViewTransformer(new DateTimeToLocalizedStringTransformer(
                $options['model_timezone'],
                $options['view_timezone'],
                $dateFormat,
                $timeFormat,
                $calendar,
                $pattern
            ));
        } else {
            $yearOptions = $monthOptions = $dayOptions = array(
                'error_bubbling' => true,
            );

            $formatter = new \IntlDateFormatter(
                \Locale::getDefault(),
                $dateFormat,
                $timeFormat,
                'UTC',
                $calendar,
                $pattern
            );
            $formatter->setLenient(false);

            if ('choice' === $options['widget']) {
                // Only pass a subset of the options to children
                $yearOptions['choices'] = $this->formatTimestamps($formatter, '/y+/', $this->listYears($options['years']));
                $yearOptions['empty_value'] = $options['empty_value']['year'];
                $monthOptions['choices'] = $this->formatTimestamps($formatter, '/[M|L]+/', $this->listMonths($options['months']));
                $monthOptions['empty_value'] = $options['empty_value']['month'];
                $dayOptions['choices'] = $this->formatTimestamps($formatter, '/d+/', $this->listDays($options['days']));
                $dayOptions['empty_value'] = $options['empty_value']['day'];
            }

            // Append generic carry-along options
            foreach (array('required', 'translation_domain') as $passOpt) {
                $yearOptions[$passOpt] = $monthOptions[$passOpt] = $dayOptions[$passOpt] = $options[$passOpt];
            }

            $builder
                ->add('year', $options['widget'], $yearOptions)
                ->add('month', $options['widget'], $monthOptions)
                ->add('day', $options['widget'], $dayOptions)
                ->addViewTransformer(new DateTimeToArrayTransformer(
                    $options['model_timezone'], $options['view_timezone'], array('year', 'month', 'day')
                ))
                ->setAttribute('formatter', $formatter)
            ;
        }

        if ('string' === $options['input']) {
            $builder->addModelTransformer(new ReversedTransformer(
                new DateTimeToStringTransformer($options['model_timezone'], $options['model_timezone'], 'Y-m-d')
            ));
        } elseif ('timestamp' === $options['input']) {
            $builder->addModelTransformer(new ReversedTransformer(
                new DateTimeToTimestampTransformer($options['model_timezone'], $options['model_timezone'])
            ));
        } elseif ('array' === $options['input']) {
            $builder->addModelTransformer(new ReversedTransformer(
                new DateTimeToArrayTransformer($options['model_timezone'], $options['model_timezone'], array('year', 'month', 'day'))
            ));
        }
    }

    /**
     * {@inheritdoc}
     */
    public function finishView(FormView $view, FormInterface $form, array $options)
    {
        $view->vars['widget'] = $options['widget'];

        // Change the input to a HTML5 date input if
        //  * the widget is set to "single_text"
        //  * the format matches the one expected by HTML5
        if ('single_text' === $options['widget'] && self::HTML5_FORMAT === $options['format']) {
            $view->vars['type'] = 'date';
        }

        if ($form->getConfig()->hasAttribute('formatter')) {
            $pattern = $form->getConfig()->getAttribute('formatter')->getPattern();

            // remove special characters unless the format was explicitly specified
            if (!is_string($options['format'])) {
                $pattern = preg_replace('/[^yMd]+/', '', $pattern);
            }

            // set right order with respect to locale (e.g.: de_DE=dd.MM.yy; en_US=M/d/yy)
            // lookup various formats at http://userguide.icu-project.org/formatparse/datetime
            if (preg_match('/^([yMd]+)[^yMd]*([yMd]+)[^yMd]*([yMd]+)$/', $pattern)) {
                $pattern = preg_replace(array('/y+/', '/M+/', '/d+/'), array('{{ year }}', '{{ month }}', '{{ day }}'), $pattern);
            } else {
                // default fallback
                $pattern = '{{ year }}{{ month }}{{ day }}';
            }

            $view->vars['date_pattern'] = $pattern;
        }
    }

    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $compound = function (Options $options) {
            return $options['widget'] !== 'single_text';
        };

        $emptyValue = $emptyValueDefault = function (Options $options) {
            return $options['required'] ? null : '';
        };

        $emptyValueNormalizer = function (Options $options, $emptyValue) use ($emptyValueDefault) {
            if (is_array($emptyValue)) {
                $default = $emptyValueDefault($options);

                return array_merge(
                    array('year' => $default, 'month' => $default, 'day' => $default),
                    $emptyValue
                );
            }

            return array(
                'year' => $emptyValue,
                'month' => $emptyValue,
                'day' => $emptyValue
            );
        };

        $format = function (Options $options) {
            return $options['widget'] === 'single_text' ? DateType::HTML5_FORMAT : DateType::DEFAULT_FORMAT;
        };

        $resolver->setDefaults(array(
            'years'          => range(date('Y') - 5, date('Y') + 5),
            'months'         => range(1, 12),
            'days'           => range(1, 31),
            'widget'         => 'choice',
            'input'          => 'datetime',
            'format'         => $format,
            'model_timezone' => null,
            'view_timezone'  => null,
            'empty_value'    => $emptyValue,
            // Don't modify \DateTime classes by reference, we treat
            // them like immutable value objects
            'by_reference'   => false,
            'error_bubbling' => false,
            // If initialized with a \DateTime object, FormType initializes
            // this option to "\DateTime". Since the internal, normalized
            // representation is not \DateTime, but an array, we need to unset
            // this option.
            'data_class'     => null,
            'compound'       => $compound,
        ));

        $resolver->setNormalizers(array(
            'empty_value' => $emptyValueNormalizer,
        ));

        $resolver->setAllowedValues(array(
            'input'     => array(
                'datetime',
                'string',
                'timestamp',
                'array',
            ),
            'widget'    => array(
                'single_text',
                'text',
                'choice',
            ),
        ));

        $resolver->setAllowedTypes(array(
            'format' => array('int', 'string'),
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'date';
    }

    private function formatTimestamps(\IntlDateFormatter $formatter, $regex, array $timestamps)
    {
        $pattern = $formatter->getPattern();
        $timezone = $formatter->getTimezoneId();

        if ($setTimeZone = method_exists($formatter, 'setTimeZone')) {
            $formatter->setTimeZone('UTC');
        } else {
            $formatter->setTimeZoneId('UTC');
        }

        if (preg_match($regex, $pattern, $matches)) {
            $formatter->setPattern($matches[0]);

            foreach ($timestamps as $key => $timestamp) {
                $timestamps[$key] = $formatter->format($timestamp);
            }

            // I'd like to clone the formatter above, but then we get a
            // segmentation fault, so let's restore the old state instead
            $formatter->setPattern($pattern);
        }

        if ($setTimeZone) {
            $formatter->setTimeZone($timezone);
        } else {
            $formatter->setTimeZoneId($timezone);
        }

        return $timestamps;
    }

    private function listYears(array $years)
    {
        $result = array();

        foreach ($years as $year) {
            if (false !== $y = gmmktime(0, 0, 0, 6, 15, $year)) {
                $result[$year] = $y;
            }
        }

        return $result;
    }

    private function listMonths(array $months)
    {
        $result = array();

        foreach ($months as $month) {
            $result[$month] = gmmktime(0, 0, 0, $month, 15);
        }

        return $result;
    }

    private function listDays(array $days)
    {
        $result = array();

        foreach ($days as $day) {
            $result[$day] = gmmktime(0, 0, 0, 5, $day);
        }

        return $result;
    }
}
PK��Za�L�:Symfony/Component/Form/Extension/Core/Type/CountryType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Intl\Intl;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class CountryType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'choices' => Intl::getRegionBundle()->getCountryNames(),
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getParent()
    {
        return 'choice';
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'country';
    }
}
PK��ZC�i���9Symfony/Component/Form/Extension/Core/Type/NumberType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\DataTransformer\NumberToLocalizedStringTransformer;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class NumberType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->addViewTransformer(new NumberToLocalizedStringTransformer(
            $options['precision'],
            $options['grouping'],
            $options['rounding_mode']
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            // default precision is locale specific (usually around 3)
            'precision'     => null,
            'grouping'      => false,
            'rounding_mode' => NumberToLocalizedStringTransformer::ROUND_HALF_UP,
            'compound'      => false,
        ));

        $resolver->setAllowedValues(array(
            'rounding_mode' => array(
                NumberToLocalizedStringTransformer::ROUND_FLOOR,
                NumberToLocalizedStringTransformer::ROUND_DOWN,
                NumberToLocalizedStringTransformer::ROUND_HALF_DOWN,
                NumberToLocalizedStringTransformer::ROUND_HALF_EVEN,
                NumberToLocalizedStringTransformer::ROUND_HALF_UP,
                NumberToLocalizedStringTransformer::ROUND_UP,
                NumberToLocalizedStringTransformer::ROUND_CEILING,
            ),
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'number';
    }
}
PK��Z:�y�

7Symfony/Component/Form/Extension/Core/Type/FormType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\Extension\Core\EventListener\TrimListener;
use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;
use Symfony\Component\Form\Exception\LogicException;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;

class FormType extends BaseType
{
    /**
     * @var PropertyAccessorInterface
     */
    private $propertyAccessor;

    public function __construct(PropertyAccessorInterface $propertyAccessor = null)
    {
        $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor();
    }

    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        parent::buildForm($builder, $options);

        $isDataOptionSet = array_key_exists('data', $options);

        $builder
            ->setRequired($options['required'])
            ->setErrorBubbling($options['error_bubbling'])
            ->setEmptyData($options['empty_data'])
            ->setPropertyPath($options['property_path'])
            ->setMapped($options['mapped'])
            ->setByReference($options['by_reference'])
            ->setInheritData($options['inherit_data'])
            ->setCompound($options['compound'])
            ->setData($isDataOptionSet ? $options['data'] : null)
            ->setDataLocked($isDataOptionSet)
            ->setDataMapper($options['compound'] ? new PropertyPathMapper($this->propertyAccessor) : null)
            ->setMethod($options['method'])
            ->setAction($options['action'])
        ;

        if ($options['trim']) {
            $builder->addEventSubscriber(new TrimListener());
        }
    }

    /**
     * {@inheritdoc}
     */
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        parent::buildView($view, $form, $options);

        $name = $form->getName();
        $readOnly = $options['read_only'];

        if ($view->parent) {
            if ('' === $name) {
                throw new LogicException('Form node with empty name can be used only as root form node.');
            }

            // Complex fields are read-only if they themselves or their parents are.
            if (!$readOnly) {
                $readOnly = $view->parent->vars['read_only'];
            }
        }

        $view->vars = array_replace($view->vars, array(
            'read_only'  => $readOnly,
            'errors'     => $form->getErrors(),
            'valid'      => $form->isSubmitted() ? $form->isValid() : true,
            'value'      => $form->getViewData(),
            'data'       => $form->getNormData(),
            'required'   => $form->isRequired(),
            'max_length' => $options['max_length'],
            'pattern'    => $options['pattern'],
            'size'       => null,
            'label_attr' => $options['label_attr'],
            'compound'   => $form->getConfig()->getCompound(),
            'method'     => $form->getConfig()->getMethod(),
            'action'     => $form->getConfig()->getAction(),
            'submitted'  => $form->isSubmitted(),
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function finishView(FormView $view, FormInterface $form, array $options)
    {
        $multipart = false;

        foreach ($view->children as $child) {
            if ($child->vars['multipart']) {
                $multipart = true;
                break;
            }
        }

        $view->vars['multipart'] = $multipart;
    }

    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        parent::setDefaultOptions($resolver);

        // Derive "data_class" option from passed "data" object
        $dataClass = function (Options $options) {
            return isset($options['data']) && is_object($options['data']) ? get_class($options['data']) : null;
        };

        // Derive "empty_data" closure from "data_class" option
        $emptyData = function (Options $options) {
            $class = $options['data_class'];

            if (null !== $class) {
                return function (FormInterface $form) use ($class) {
                    return $form->isEmpty() && !$form->isRequired() ? null : new $class();
                };
            }

            return function (FormInterface $form) {
                return $form->getConfig()->getCompound() ? array() : '';
            };
        };

        // For any form that is not represented by a single HTML control,
        // errors should bubble up by default
        $errorBubbling = function (Options $options) {
            return $options['compound'];
        };

        // BC with old "virtual" option
        $inheritData = function (Options $options) {
            if (null !== $options['virtual']) {
                // Uncomment this as soon as the deprecation note should be shown
                // trigger_error('The form option "virtual" is deprecated since version 2.3 and will be removed in 3.0. Use "inherit_data" instead.', E_USER_DEPRECATED);
                return $options['virtual'];
            }

            return false;
        };

        // If data is given, the form is locked to that data
        // (independent of its value)
        $resolver->setOptional(array(
            'data',
        ));

        $resolver->setDefaults(array(
            'data_class'         => $dataClass,
            'empty_data'         => $emptyData,
            'trim'               => true,
            'required'           => true,
            'read_only'          => false,
            'max_length'         => null,
            'pattern'            => null,
            'property_path'      => null,
            'mapped'             => true,
            'by_reference'       => true,
            'error_bubbling'     => $errorBubbling,
            'label_attr'         => array(),
            'virtual'            => null,
            'inherit_data'       => $inheritData,
            'compound'           => true,
            'method'             => 'POST',
            // According to RFC 2396 (http://www.ietf.org/rfc/rfc2396.txt)
            // section 4.2., empty URIs are considered same-document references
            'action'             => '',
        ));

        $resolver->setAllowedTypes(array(
            'label_attr' => 'array',
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getParent()
    {
        return null;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'form';
    }
}
PK��Z5�S
��8Symfony/Component/Form/Extension/Core/Type/MoneyType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\DataTransformer\MoneyToLocalizedStringTransformer;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class MoneyType extends AbstractType
{
    protected static $patterns = array();

    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->addViewTransformer(new MoneyToLocalizedStringTransformer(
                $options['precision'],
                $options['grouping'],
                null,
                $options['divisor']
            ))
        ;
    }

    /**
     * {@inheritdoc}
     */
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        $view->vars['money_pattern'] = self::getPattern($options['currency']);
    }

    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'precision' => 2,
            'grouping'  => false,
            'divisor'   => 1,
            'currency'  => 'EUR',
            'compound'  => false,
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'money';
    }

    /**
     * Returns the pattern for this locale
     *
     * The pattern contains the placeholder "{{ widget }}" where the HTML tag should
     * be inserted
     */
    protected static function getPattern($currency)
    {
        if (!$currency) {
            return '{{ widget }}';
        }

        $locale = \Locale::getDefault();

        if (!isset(self::$patterns[$locale])) {
            self::$patterns[$locale] = array();
        }

        if (!isset(self::$patterns[$locale][$currency])) {
            $format = new \NumberFormatter($locale, \NumberFormatter::CURRENCY);
            $pattern = $format->formatCurrency('123', $currency);

            // the spacings between currency symbol and number are ignored, because
            // a single space leads to better readability in combination with input
            // fields

            // the regex also considers non-break spaces (0xC2 or 0xA0 in UTF-8)

            preg_match('/^([^\s\xc2\xa0]*)[\s\xc2\xa0]*123(?:[,.]0+)?[\s\xc2\xa0]*([^\s\xc2\xa0]*)$/u', $pattern, $matches);

            if (!empty($matches[1])) {
                self::$patterns[$locale][$currency] = $matches[1].' {{ widget }}';
            } elseif (!empty($matches[2])) {
                self::$patterns[$locale][$currency] = '{{ widget }} '.$matches[2];
            } else {
                self::$patterns[$locale][$currency] = '{{ widget }}';
            }
        }

        return self::$patterns[$locale][$currency];
    }
}
PK��Z6s���DSymfony/Component/Form/Extension/DataCollector/FormDataCollector.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\DataCollector;

use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\DataCollector\DataCollector;

/**
 * Data collector for {@link \Symfony\Component\Form\FormInterface} instances.
 *
 * @since  2.4
 * @author Robert Schönthal <robert.schoenthal@gmail.com>
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class FormDataCollector extends DataCollector implements FormDataCollectorInterface
{
    /**
     * @var FormDataExtractor
     */
    private $dataExtractor;

    /**
     * Stores the collected data per {@link FormInterface} instance.
     *
     * Uses the hashes of the forms as keys. This is preferable over using
     * {@link \SplObjectStorage}, because in this way no references are kept
     * to the {@link FormInterface} instances.
     *
     * @var array
     */
    private $dataByForm;

    /**
     * Stores the collected data per {@link FormView} instance.
     *
     * Uses the hashes of the views as keys. This is preferable over using
     * {@link \SplObjectStorage}, because in this way no references are kept
     * to the {@link FormView} instances.
     *
     * @var array
     */
    private $dataByView;

    /**
     * Connects {@link FormView} with {@link FormInterface} instances.
     *
     * Uses the hashes of the views as keys and the hashes of the forms as
     * values. This is preferable over storing the objects directly, because
     * this way they can safely be discarded by the GC.
     *
     * @var array
     */
    private $formsByView;

    public function __construct(FormDataExtractorInterface $dataExtractor)
    {
        $this->dataExtractor = $dataExtractor;
        $this->data = array(
            'forms' => array(),
            'nb_errors' => 0,
        );
    }

    /**
     * Does nothing. The data is collected during the form event listeners.
     */
    public function collect(Request $request, Response $response, \Exception $exception = null)
    {
    }

    /**
     * {@inheritdoc}
     */
    public function associateFormWithView(FormInterface $form, FormView $view)
    {
        $this->formsByView[spl_object_hash($view)] = spl_object_hash($form);
    }

    /**
     * {@inheritdoc}
     */
    public function collectConfiguration(FormInterface $form)
    {
        $hash = spl_object_hash($form);

        if (!isset($this->dataByForm[$hash])) {
            $this->dataByForm[$hash] = array();
        }

        $this->dataByForm[$hash] = array_replace(
            $this->dataByForm[$hash],
            $this->dataExtractor->extractConfiguration($form)
        );

        foreach ($form as $child) {
            $this->collectConfiguration($child);
        }
    }

    /**
     * {@inheritdoc}
     */
    public function collectDefaultData(FormInterface $form)
    {
        $hash = spl_object_hash($form);

        if (!isset($this->dataByForm[$hash])) {
            $this->dataByForm[$hash] = array();
        }

        $this->dataByForm[$hash] = array_replace(
            $this->dataByForm[$hash],
            $this->dataExtractor->extractDefaultData($form)
        );

        foreach ($form as $child) {
            $this->collectDefaultData($child);
        }
    }

    /**
     * {@inheritdoc}
     */
    public function collectSubmittedData(FormInterface $form)
    {
        $hash = spl_object_hash($form);

        if (!isset($this->dataByForm[$hash])) {
            $this->dataByForm[$hash] = array();
        }

        $this->dataByForm[$hash] = array_replace(
            $this->dataByForm[$hash],
            $this->dataExtractor->extractSubmittedData($form)
        );

        // Count errors
        if (isset($this->dataByForm[$hash]['errors'])) {
            $this->data['nb_errors'] += count($this->dataByForm[$hash]['errors']);
        }

        foreach ($form as $child) {
            $this->collectSubmittedData($child);
        }
    }

    /**
     * {@inheritdoc}
     */
    public function collectViewVariables(FormView $view)
    {
        $hash = spl_object_hash($view);

        if (!isset($this->dataByView[$hash])) {
            $this->dataByView[$hash] = array();
        }

        $this->dataByView[$hash] = array_replace(
            $this->dataByView[$hash],
            $this->dataExtractor->extractViewVariables($view)
        );

        foreach ($view->children as $child) {
            $this->collectViewVariables($child);
        }
    }

    /**
     * {@inheritdoc}
     */
    public function buildPreliminaryFormTree(FormInterface $form)
    {
        $this->data['forms'][$form->getName()] = array();

        $this->recursiveBuildPreliminaryFormTree($form, $this->data['forms'][$form->getName()]);
    }

    /**
     * {@inheritdoc}
     */
    public function buildFinalFormTree(FormInterface $form, FormView $view)
    {
        $this->data['forms'][$form->getName()] = array();

        $this->recursiveBuildFinalFormTree($form, $view, $this->data['forms'][$form->getName()]);
    }

    /**
     * {@inheritDoc}
     */
    public function getName()
    {
        return 'form';
    }

    /**
     * {@inheritdoc}
     */
    public function getData()
    {
        return $this->data;
    }

    private function recursiveBuildPreliminaryFormTree(FormInterface $form, &$output = null)
    {
        $hash = spl_object_hash($form);

        $output = isset($this->dataByForm[$hash])
            ? $this->dataByForm[$hash]
            : array();

        $output['children'] = array();

        foreach ($form as $name => $child) {
            $output['children'][$name] = array();

            $this->recursiveBuildPreliminaryFormTree($child, $output['children'][$name]);
        }
    }

    private function recursiveBuildFinalFormTree(FormInterface $form = null, FormView $view, &$output = null)
    {
        $viewHash = spl_object_hash($view);
        $formHash = null;

        if (null !== $form) {
            $formHash = spl_object_hash($form);
        } elseif (isset($this->formsByView[$viewHash])) {
            // The FormInterface instance of the CSRF token is never contained in
            // the FormInterface tree of the form, so we need to get the
            // corresponding FormInterface instance for its view in a different way
            $formHash = $this->formsByView[$viewHash];
        }

        $output = isset($this->dataByView[$viewHash])
            ? $this->dataByView[$viewHash]
            : array();

        if (null !== $formHash) {
            $output = array_replace(
                $output,
                isset($this->dataByForm[$formHash])
                    ? $this->dataByForm[$formHash]
                    : array()
            );
        }

        $output['children'] = array();

        foreach ($view->children as $name => $childView) {
            // The CSRF token, for example, is never added to the form tree.
            // It is only present in the view.
            $childForm = null !== $form && $form->has($name)
                ? $form->get($name)
                : null;

            $output['children'][$name] = array();

            $this->recursiveBuildFinalFormTree($childForm, $childView, $output['children'][$name]);
        }
    }
}
PK��ZI��2

VSymfony/Component/Form/Extension/DataCollector/EventListener/DataCollectorListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\DataCollector\EventListener;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\Extension\DataCollector\FormDataCollectorInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;

/**
 * Listener that invokes a data collector for the {@link FormEvents::POST_SET_DATA}
 * and {@link FormEvents::POST_SUBMIT} events.
 *
 * @since  2.4
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class DataCollectorListener implements EventSubscriberInterface
{
    /**
     * @var FormDataCollectorInterface
     */
    private $dataCollector;

    public function __construct(FormDataCollectorInterface $dataCollector)
    {
        $this->dataCollector = $dataCollector;
    }

    /**
     * {@inheritDoc}
     */
    public static function getSubscribedEvents()
    {
        return array(
            // High priority in order to be called as soon as possible
            FormEvents::POST_SET_DATA => array('postSetData', 255),
            // Low priority in order to be called as late as possible
            FormEvents::POST_SUBMIT => array('postSubmit', -255),
        );
    }

    /**
     * Listener for the {@link FormEvents::POST_SET_DATA} event.
     *
     * @param FormEvent $event The event object
     */
    public function postSetData(FormEvent $event)
    {
        if ($event->getForm()->isRoot()) {
            // Collect basic information about each form
            $this->dataCollector->collectConfiguration($event->getForm());

            // Collect the default data
            $this->dataCollector->collectDefaultData($event->getForm());
        }
    }

    /**
     * Listener for the {@link FormEvents::POST_SUBMIT} event.
     *
     * @param FormEvent $event The event object
     */
    public function postSubmit(FormEvent $event)
    {
        if ($event->getForm()->isRoot()) {
            // Collect the submitted data of each form
            $this->dataCollector->collectSubmittedData($event->getForm());

            // Assemble a form tree
            // This is done again in collectViewVariables(), but that method
            // is not guaranteed to be called (i.e. when no view is created)
            $this->dataCollector->buildPreliminaryFormTree($event->getForm());
        }
    }

}
PK��Z�T���MSymfony/Component/Form/Extension/DataCollector/FormDataCollectorInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\DataCollector;

use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface;

/**
 * Collects and structures information about forms.
 *
 * @since  2.4
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface FormDataCollectorInterface extends DataCollectorInterface
{
    /**
     * Stores configuration data of the given form and its children.
     *
     * @param FormInterface $form A root form
     */
    public function collectConfiguration(FormInterface $form);

    /**
     * Stores the default data of the given form and its children.
     *
     * @param FormInterface $form A root form
     */
    public function collectDefaultData(FormInterface $form);

    /**
     * Stores the submitted data of the given form and its children.
     *
     * @param FormInterface $form A root form
     */
    public function collectSubmittedData(FormInterface $form);

    /**
     * Stores the view variables of the given form view and its children.
     *
     * @param FormView $view A root form view
     */
    public function collectViewVariables(FormView $view);

    /**
     * Specifies that the given objects represent the same conceptual form.
     *
     * @param FormInterface $form A form object
     * @param FormView      $view A view object
     */
    public function associateFormWithView(FormInterface $form, FormView $view);

    /**
     * Assembles the data collected about the given form and its children as
     * a tree-like data structure.
     *
     * The result can be queried using {@link getData()}.
     *
     * @param FormInterface $form A root form
     */
    public function buildPreliminaryFormTree(FormInterface $form);

    /**
     * Assembles the data collected about the given form and its children as
     * a tree-like data structure.
     *
     * The result can be queried using {@link getData()}.
     *
     * Contrary to {@link buildPreliminaryFormTree()}, a {@link FormView}
     * object has to be passed. The tree structure of this view object will be
     * used for structuring the resulting data. That means, if a child is
     * present in the view, but not in the form, it will be present in the final
     * data array anyway.
     *
     * When {@link FormView} instances are present in the view tree, for which
     * no corresponding {@link FormInterface} objects can be found in the form
     * tree, only the view data will be included in the result. If a
     * corresponding {@link FormInterface} exists otherwise, call
     * {@link associateFormWithView()} before calling this method.
     *
     * @param FormInterface $form A root form
     * @param FormView      $view A root view
     */
    public function buildFinalFormTree(FormInterface $form, FormView $view);

    /**
     * Returns all collected data.
     *
     * @return array
     */
    public function getData();

}
PK��Z����MSymfony/Component/Form/Extension/DataCollector/FormDataExtractorInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\DataCollector;

use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;

/**
 * Extracts arrays of information out of forms.
 *
 * @since  2.4
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface FormDataExtractorInterface
{
    /**
     * Extracts the configuration data of a form.
     *
     * @param FormInterface $form The form
     *
     * @return array Information about the form's configuration
     */
    public function extractConfiguration(FormInterface $form);

    /**
     * Extracts the default data of a form.
     *
     * @param FormInterface $form The form
     *
     * @return array Information about the form's default data
     */
    public function extractDefaultData(FormInterface $form);

    /**
     * Extracts the submitted data of a form.
     *
     * @param FormInterface $form The form
     *
     * @return array Information about the form's submitted data
     */
    public function extractSubmittedData(FormInterface $form);

    /**
     * Extracts the view variables of a form.
     *
     * @param FormView $view The form view
     *
     * @return array Information about the view's variables
     */
    public function extractViewVariables(FormView $view);
}
PK��Z|�
]��WSymfony/Component/Form/Extension/DataCollector/Proxy/ResolvedTypeDataCollectorProxy.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\DataCollector\Proxy;

use Symfony\Component\Form\Extension\DataCollector\FormDataCollectorInterface;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\ResolvedFormTypeInterface;

/**
 * Proxy that invokes a data collector when creating a form and its view.
 *
 * @since  2.4
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ResolvedTypeDataCollectorProxy implements ResolvedFormTypeInterface
{
    /**
     * @var ResolvedFormTypeInterface
     */
    private $proxiedType;

    /**
     * @var FormDataCollectorInterface
     */
    private $dataCollector;

    public function __construct(ResolvedFormTypeInterface $proxiedType, FormDataCollectorInterface $dataCollector)
    {
        $this->proxiedType = $proxiedType;
        $this->dataCollector = $dataCollector;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return $this->proxiedType->getName();
    }

    /**
     * {@inheritdoc}
     */
    public function getParent()
    {
        return $this->proxiedType->getParent();
    }

    /**
     * {@inheritdoc}
     */
    public function getInnerType()
    {
        return $this->proxiedType->getInnerType();
    }

    /**
     * {@inheritdoc}
     */
    public function getTypeExtensions()
    {
        return $this->proxiedType->getTypeExtensions();
    }

    /**
     * {@inheritdoc}
     */
    public function createBuilder(FormFactoryInterface $factory, $name, array $options = array())
    {
        $builder = $this->proxiedType->createBuilder($factory, $name, $options);

        $builder->setAttribute('data_collector/passed_options', $options);
        $builder->setType($this);

        return $builder;
    }

    /**
     * {@inheritdoc}
     */
    public function createView(FormInterface $form, FormView $parent = null)
    {
        return $this->proxiedType->createView($form, $parent);
    }

    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $this->proxiedType->buildForm($builder, $options);
    }

    /**
     * {@inheritdoc}
     */
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        $this->proxiedType->buildView($view, $form, $options);
    }

    /**
     * {@inheritdoc}
     */
    public function finishView(FormView $view, FormInterface $form, array $options)
    {
        $this->proxiedType->finishView($view, $form, $options);

        // Remember which view belongs to which form instance, so that we can
        // get the collected data for a view when its form instance is not
        // available (e.g. CSRF token)
        $this->dataCollector->associateFormWithView($form, $view);

        // Since the CSRF token is only present in the FormView tree, we also
        // need to check the FormView tree instead of calling isRoot() on the
        // FormInterface tree
        if (null === $view->parent) {
            $this->dataCollector->collectViewVariables($view);

            // Re-assemble data, in case FormView instances were added, for
            // which no FormInterface instances were present (e.g. CSRF token).
            // Since finishView() is called after finishing the views of all
            // children, we can safely assume that information has been
            // collected about the complete form tree.
            $this->dataCollector->buildFinalFormTree($form, $view);
        }
    }

    /**
     * {@inheritdoc}
     */
    public function getOptionsResolver()
    {
        return $this->proxiedType->getOptionsResolver();
    }
}
PK��Z�((^Symfony/Component/Form/Extension/DataCollector/Proxy/ResolvedTypeFactoryDataCollectorProxy.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\DataCollector\Proxy;

use Symfony\Component\Form\Extension\DataCollector\FormDataCollectorInterface;
use Symfony\Component\Form\FormTypeInterface;
use Symfony\Component\Form\ResolvedFormTypeFactoryInterface;
use Symfony\Component\Form\ResolvedFormTypeInterface;

/**
 * Proxy that wraps resolved types into {@link ResolvedTypeDataCollectorProxy}
 * instances.
 *
 * @since  2.4
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ResolvedTypeFactoryDataCollectorProxy implements ResolvedFormTypeFactoryInterface
{
    /**
     * @var ResolvedFormTypeFactoryInterface
     */
    private $proxiedFactory;

    /**
     * @var FormDataCollectorInterface
     */
    private $dataCollector;

    public function __construct(ResolvedFormTypeFactoryInterface $proxiedFactory, FormDataCollectorInterface $dataCollector)
    {
        $this->proxiedFactory = $proxiedFactory;
        $this->dataCollector = $dataCollector;
    }

    /**
     * {@inheritdoc}
     */
    public function createResolvedType(FormTypeInterface $type, array $typeExtensions, ResolvedFormTypeInterface $parent = null)
    {
        return new ResolvedTypeDataCollectorProxy(
            $this->proxiedFactory->createResolvedType($type, $typeExtensions, $parent),
            $this->dataCollector
        );
    }
}
PK��Z��#�11ISymfony/Component/Form/Extension/DataCollector/DataCollectorExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\DataCollector;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\AbstractExtension;

/**
 * Extension for collecting data of the forms on a page.
 *
 * @since  2.4
 * @author Robert Schönthal <robert.schoenthal@gmail.com>
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class DataCollectorExtension extends AbstractExtension
{
    /**
     * @var EventSubscriberInterface
     */
    private $dataCollector;

    public function __construct(FormDataCollectorInterface $dataCollector)
    {
        $this->dataCollector = $dataCollector;
    }

    /**
     * {@inheritDoc}
     */
    protected function loadTypeExtensions()
    {
        return array(
            new Type\DataCollectorTypeExtension($this->dataCollector)
        );
    }
}
PK��Z%�`��DSymfony/Component/Form/Extension/DataCollector/FormDataExtractor.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\DataCollector;

use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter;

/**
 * Default implementation of {@link FormDataExtractorInterface}.
 *
 * @since  2.4
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class FormDataExtractor implements FormDataExtractorInterface
{
    /**
     * @var ValueExporter
     */
    private $valueExporter;

    /**
     * Constructs a new data extractor.
     */
    public function __construct(ValueExporter $valueExporter = null)
    {
        $this->valueExporter = $valueExporter ?: new ValueExporter();
    }

    /**
     * {@inheritdoc}
     */
    public function extractConfiguration(FormInterface $form)
    {
        $data = array(
            'id' => $this->buildId($form),
            'type' => $form->getConfig()->getType()->getName(),
            'type_class' => get_class($form->getConfig()->getType()->getInnerType()),
            'synchronized' => $this->valueExporter->exportValue($form->isSynchronized()),
            'passed_options' => array(),
            'resolved_options' => array(),
        );

        foreach ($form->getConfig()->getAttribute('data_collector/passed_options', array()) as $option => $value) {
            $data['passed_options'][$option] = $this->valueExporter->exportValue($value);
        }

        foreach ($form->getConfig()->getOptions() as $option => $value) {
            $data['resolved_options'][$option] = $this->valueExporter->exportValue($value);
        }

        ksort($data['passed_options']);
        ksort($data['resolved_options']);

        return $data;
    }

    /**
     * {@inheritdoc}
     */
    public function extractDefaultData(FormInterface $form)
    {
        $data = array(
            'default_data' => array(
                'norm' => $this->valueExporter->exportValue($form->getNormData()),
            ),
            'submitted_data' => array(),
        );

        if ($form->getData() !== $form->getNormData()) {
            $data['default_data']['model'] = $this->valueExporter->exportValue($form->getData());
        }

        if ($form->getViewData() !== $form->getNormData()) {
            $data['default_data']['view'] = $this->valueExporter->exportValue($form->getViewData());
        }

        return $data;
    }

    /**
     * {@inheritdoc}
     */
    public function extractSubmittedData(FormInterface $form)
    {
        $data = array(
            'submitted_data' => array(
                'norm' => $this->valueExporter->exportValue($form->getNormData()),
            ),
            'errors' => array(),
        );

        if ($form->getViewData() !== $form->getNormData()) {
            $data['submitted_data']['view'] = $this->valueExporter->exportValue($form->getViewData());
        }

        if ($form->getData() !== $form->getNormData()) {
            $data['submitted_data']['model'] = $this->valueExporter->exportValue($form->getData());
        }

        foreach ($form->getErrors() as $error) {
            $data['errors'][] = array(
                'message' => $error->getMessage(),
            );
        }

        $data['synchronized'] = $this->valueExporter->exportValue($form->isSynchronized());

        return $data;
    }

    /**
     * {@inheritdoc}
     */
    public function extractViewVariables(FormView $view)
    {
        $data = array();

        // Set the ID in case no FormInterface object was collected for this
        // view
        if (isset($view->vars['id'])) {
            $data['id'] = $view->vars['id'];
        }

        foreach ($view->vars as $varName => $value) {
            $data['view_vars'][$varName] = $this->valueExporter->exportValue($value);
        }

        ksort($data['view_vars']);

        return $data;
    }

    /**
     * Recursively builds an HTML ID for a form.
     *
     * @param FormInterface $form The form
     *
     * @return string The HTML ID
     */
    private function buildId(FormInterface $form)
    {
        $id = $form->getName();

        if (null !== $form->getParent()) {
            $id = $this->buildId($form->getParent()).'_'.$id;
        }

        return $id;
    }
}
PK��Z�1�
uuRSymfony/Component/Form/Extension/DataCollector/Type/DataCollectorTypeExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\DataCollector\Type;

use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Extension\DataCollector\EventListener\DataCollectorListener;
use Symfony\Component\Form\Extension\DataCollector\FormDataCollectorInterface;
use Symfony\Component\Form\FormBuilderInterface;

/**
 * Type extension for collecting data of a form with this type.
 *
 * @since  2.4
 * @author Robert Schönthal <robert.schoenthal@gmail.com>
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class DataCollectorTypeExtension extends AbstractTypeExtension
{
    /**
     * @var \Symfony\Component\EventDispatcher\EventSubscriberInterface
     */
    private $listener;

    public function __construct(FormDataCollectorInterface $dataCollector)
    {
        $this->listener = new DataCollectorListener($dataCollector);
    }

    /**
     * {@inheritDoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->addEventSubscriber($this->listener);
    }

    /**
     * {@inheritDoc}
     */
    public function getExtendedType()
    {
        return 'form';
    }
}
PK��ZuUS�WWUSymfony/Component/Form/Extension/DependencyInjection/DependencyInjectionExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Extension\DependencyInjection;

use Symfony\Component\Form\FormExtensionInterface;
use Symfony\Component\Form\FormTypeGuesserChain;
use Symfony\Component\Form\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\ContainerInterface;

class DependencyInjectionExtension implements FormExtensionInterface
{
    private $container;
    private $typeServiceIds;
    private $typeExtensionServiceIds;
    private $guesserServiceIds;
    private $guesser;
    private $guesserLoaded = false;

    public function __construct(ContainerInterface $container,
        array $typeServiceIds, array $typeExtensionServiceIds,
        array $guesserServiceIds)
    {
        $this->container = $container;
        $this->typeServiceIds = $typeServiceIds;
        $this->typeExtensionServiceIds = $typeExtensionServiceIds;
        $this->guesserServiceIds = $guesserServiceIds;
    }

    public function getType($name)
    {
        if (!isset($this->typeServiceIds[$name])) {
            throw new InvalidArgumentException(sprintf('The field type "%s" is not registered with the service container.', $name));
        }

        $type = $this->container->get($this->typeServiceIds[$name]);

        if ($type->getName() !== $name) {
            throw new InvalidArgumentException(
                sprintf('The type name specified for the service "%s" does not match the actual name. Expected "%s", given "%s"',
                    $this->typeServiceIds[$name],
                    $name,
                    $type->getName()
                ));
        }

        return $type;
    }

    public function hasType($name)
    {
        return isset($this->typeServiceIds[$name]);
    }

    public function getTypeExtensions($name)
    {
        $extensions = array();

        if (isset($this->typeExtensionServiceIds[$name])) {
            foreach ($this->typeExtensionServiceIds[$name] as $serviceId) {
                $extensions[] = $this->container->get($serviceId);
            }
        }

        return $extensions;
    }

    public function hasTypeExtensions($name)
    {
        return isset($this->typeExtensionServiceIds[$name]);
    }

    public function getTypeGuesser()
    {
        if (!$this->guesserLoaded) {
            $this->guesserLoaded = true;
            $guessers = array();

            foreach ($this->guesserServiceIds as $serviceId) {
                $guessers[] = $this->container->get($serviceId);
            }

            if (count($guessers) > 0) {
                $this->guesser = new FormTypeGuesserChain($guessers);
            }
        }

        return $this->guesser;
    }
}
PK��Z(s
//-Symfony/Component/Form/ClickableInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

/**
 * A clickable form element.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface ClickableInterface
{
    /**
     * Returns whether this element was clicked.
     *
     * @return Boolean Whether this element was clicked.
     */
    public function isClicked();
}
PK��ZH��
�
#Symfony/Component/Form/FormView.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

use Symfony\Component\Form\Exception\BadMethodCallException;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class FormView implements \ArrayAccess, \IteratorAggregate, \Countable
{
    /**
     * The variables assigned to this view.
     * @var array
     */
    public $vars = array(
        'value' => null,
        'attr'  => array(),
    );

    /**
     * The parent view.
     * @var FormView
     */
    public $parent;

    /**
     * The child views.
     * @var array
     */
    public $children = array();

    /**
     * Is the form attached to this renderer rendered?
     *
     * Rendering happens when either the widget or the row method was called.
     * Row implicitly includes widget, however certain rendering mechanisms
     * have to skip widget rendering when a row is rendered.
     *
     * @var Boolean
     */
    private $rendered = false;

    public function __construct(FormView $parent = null)
    {
        $this->parent = $parent;
    }

    /**
     * Returns whether the view was already rendered.
     *
     * @return Boolean Whether this view's widget is rendered.
     */
    public function isRendered()
    {
        $hasChildren = 0 < count($this->children);

        if (true === $this->rendered || !$hasChildren) {
            return $this->rendered;
        }

        if ($hasChildren) {
            foreach ($this->children as $child) {
                if (!$child->isRendered()) {
                    return false;
                }
            }

            return $this->rendered = true;
        }

        return false;
    }

    /**
     * Marks the view as rendered.
     *
     * @return FormView The view object.
     */
    public function setRendered()
    {
        $this->rendered = true;

        return $this;
    }

    /**
     * Returns a child by name (implements \ArrayAccess).
     *
     * @param string $name The child name
     *
     * @return FormView The child view
     */
    public function offsetGet($name)
    {
        return $this->children[$name];
    }

    /**
     * Returns whether the given child exists (implements \ArrayAccess).
     *
     * @param string $name The child name
     *
     * @return Boolean Whether the child view exists
     */
    public function offsetExists($name)
    {
        return isset($this->children[$name]);
    }

    /**
     * Implements \ArrayAccess.
     *
     * @throws BadMethodCallException always as setting a child by name is not allowed
     */
    public function offsetSet($name, $value)
    {
        throw new BadMethodCallException('Not supported');
    }

    /**
     * Removes a child (implements \ArrayAccess).
     *
     * @param string $name The child name
     */
    public function offsetUnset($name)
    {
        unset($this->children[$name]);
    }

    /**
     * Returns an iterator to iterate over children (implements \IteratorAggregate)
     *
     * @return \ArrayIterator The iterator
     */
    public function getIterator()
    {
        return new \ArrayIterator($this->children);
    }

    /**
     * Implements \Countable.
     *
     * @return integer The number of children views
     */
    public function count()
    {
        return count($this->children);
    }
}
PK��Z
�͋ Symfony/Component/Form/Forms.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form;

use Symfony\Component\Form\Extension\Core\CoreExtension;

/**
 * Entry point of the Form component.
 *
 * Use this class to conveniently create new form factories:
 *
 * <code>
 * use Symfony\Component\Form\Forms;
 *
 * $formFactory = Forms::createFormFactory();
 *
 * $form = $formFactory->createBuilder()
 *     ->add('firstName', 'text')
 *     ->add('lastName', 'text')
 *     ->add('age', 'integer')
 *     ->add('gender', 'choice', array(
 *         'choices' => array('m' => 'Male', 'f' => 'Female'),
 *     ))
 *     ->getForm();
 * </code>
 *
 * You can also add custom extensions to the form factory:
 *
 * <code>
 * $formFactory = Forms::createFormFactoryBuilder()
 *     ->addExtension(new AcmeExtension())
 *     ->getFormFactory();
 * </code>
 *
 * If you create custom form types or type extensions, it is
 * generally recommended to create your own extensions that lazily
 * load these types and type extensions. In projects where performance
 * does not matter that much, you can also pass them directly to the
 * form factory:
 *
 * <code>
 * $formFactory = Forms::createFormFactoryBuilder()
 *     ->addType(new PersonType())
 *     ->addType(new PhoneNumberType())
 *     ->addTypeExtension(new FormTypeHelpTextExtension())
 *     ->getFormFactory();
 * </code>
 *
 * Support for CSRF protection is provided by the CsrfExtension.
 * This extension needs a CSRF provider with a strong secret
 * (e.g. a 20 character long random string). The default
 * implementation for this is DefaultCsrfProvider:
 *
 * <code>
 * use Symfony\Component\Form\Extension\Csrf\CsrfExtension;
 * use Symfony\Component\Form\Extension\Csrf\CsrfProvider\DefaultCsrfProvider;
 *
 * $secret = 'V8a5Z97e...';
 * $formFactory = Forms::createFormFactoryBuilder()
 *     ->addExtension(new CsrfExtension(new DefaultCsrfProvider($secret)))
 *     ->getFormFactory();
 * </code>
 *
 * Support for the HttpFoundation is provided by the
 * HttpFoundationExtension. You are also advised to load the CSRF
 * extension with the driver for HttpFoundation's Session class:
 *
 * <code>
 * use Symfony\Component\HttpFoundation\Session\Session;
 * use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationExtension;
 * use Symfony\Component\Form\Extension\Csrf\CsrfExtension;
 * use Symfony\Component\Form\Extension\Csrf\CsrfProvider\SessionCsrfProvider;
 *
 * $session = new Session();
 * $secret = 'V8a5Z97e...';
 * $formFactory = Forms::createFormFactoryBuilder()
 *     ->addExtension(new HttpFoundationExtension())
 *     ->addExtension(new CsrfExtension(new SessionCsrfProvider($session, $secret)))
 *     ->getFormFactory();
 * </code>
 *
 * Support for the Validator component is provided by ValidatorExtension.
 * This extension needs a validator object to function properly:
 *
 * <code>
 * use Symfony\Component\Validator\Validation;
 * use Symfony\Component\Form\Extension\Validator\ValidatorExtension;
 *
 * $validator = Validation::createValidator();
 * $formFactory = Forms::createFormFactoryBuilder()
 *     ->addExtension(new ValidatorExtension($validator))
 *     ->getFormFactory();
 * </code>
 *
 * Support for the Templating component is provided by TemplatingExtension.
 * This extension needs a PhpEngine object for rendering forms. As second
 * argument you should pass the names of the default themes. Here is an
 * example for using the default layout with "<div>" tags:
 *
 * <code>
 * use Symfony\Component\Form\Extension\Templating\TemplatingExtension;
 *
 * $formFactory = Forms::createFormFactoryBuilder()
 *     ->addExtension(new TemplatingExtension($engine, null, array(
 *         'FrameworkBundle:Form',
 *     )))
 *     ->getFormFactory();
 * </code>
 *
 * The next example shows how to include the "<table>" layout:
 *
 * <code>
 * use Symfony\Component\Form\Extension\Templating\TemplatingExtension;
 *
 * $formFactory = Forms::createFormFactoryBuilder()
 *     ->addExtension(new TemplatingExtension($engine, null, array(
 *         'FrameworkBundle:Form',
 *         'FrameworkBundle:FormTable',
 *     )))
 *     ->getFormFactory();
 * </code>
 *
 * If you also loaded the CsrfExtension, you should pass the CSRF provider
 * to the extension so that you can render CSRF tokens in your templates
 * more easily:
 *
 * <code>
 * use Symfony\Component\Form\Extension\Csrf\CsrfExtension;
 * use Symfony\Component\Form\Extension\Csrf\CsrfProvider\DefaultCsrfProvider;
 * use Symfony\Component\Form\Extension\Templating\TemplatingExtension;
 *
 *
 * $secret = 'V8a5Z97e...';
 * $csrfProvider = new DefaultCsrfProvider($secret);
 * $formFactory = Forms::createFormFactoryBuilder()
 *     ->addExtension(new CsrfExtension($csrfProvider))
 *     ->addExtension(new TemplatingExtension($engine, $csrfProvider, array(
 *         'FrameworkBundle:Form',
 *     )))
 *     ->getFormFactory();
 * </code>
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
final class Forms
{
    /**
     * Creates a form factory with the default configuration.
     *
     * @return FormFactoryInterface The form factory.
     */
    public static function createFormFactory()
    {
        return self::createFormFactoryBuilder()->getFormFactory();
    }

    /**
     * Creates a form factory builder with the default configuration.
     *
     * @return FormFactoryBuilderInterface The form factory builder.
     */
    public static function createFormFactoryBuilder()
    {
        $builder = new FormFactoryBuilder();
        $builder->addExtension(new CoreExtension());

        return $builder;
    }

    /**
     * This class cannot be instantiated.
     */
    private function __construct()
    {
    }
}
PK��Z\�F1Symfony/Component/Security/Acl/Voter/AclVoter.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Voter;

use Psr\Log\LoggerInterface;
use Symfony\Component\Security\Acl\Exception\NoAceFoundException;
use Symfony\Component\Security\Acl\Exception\AclNotFoundException;
use Symfony\Component\Security\Acl\Model\AclProviderInterface;
use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface;
use Symfony\Component\Security\Acl\Permission\PermissionMapInterface;
use Symfony\Component\Security\Acl\Model\SecurityIdentityRetrievalStrategyInterface;
use Symfony\Component\Security\Acl\Model\ObjectIdentityRetrievalStrategyInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;

/**
 * This voter can be used as a base class for implementing your own permissions.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class AclVoter implements VoterInterface
{
    private $aclProvider;
    private $permissionMap;
    private $objectIdentityRetrievalStrategy;
    private $securityIdentityRetrievalStrategy;
    private $allowIfObjectIdentityUnavailable;
    private $logger;

    public function __construct(AclProviderInterface $aclProvider, ObjectIdentityRetrievalStrategyInterface $oidRetrievalStrategy, SecurityIdentityRetrievalStrategyInterface $sidRetrievalStrategy, PermissionMapInterface $permissionMap, LoggerInterface $logger = null, $allowIfObjectIdentityUnavailable = true)
    {
        $this->aclProvider = $aclProvider;
        $this->permissionMap = $permissionMap;
        $this->objectIdentityRetrievalStrategy = $oidRetrievalStrategy;
        $this->securityIdentityRetrievalStrategy = $sidRetrievalStrategy;
        $this->logger = $logger;
        $this->allowIfObjectIdentityUnavailable = $allowIfObjectIdentityUnavailable;
    }

    public function supportsAttribute($attribute)
    {
        return $this->permissionMap->contains($attribute);
    }

    public function vote(TokenInterface $token, $object, array $attributes)
    {
        foreach ($attributes as $attribute) {
            if (null === $masks = $this->permissionMap->getMasks($attribute, $object)) {
                continue;
            }

            if (null === $object) {
                if (null !== $this->logger) {
                    $this->logger->debug(sprintf('Object identity unavailable. Voting to %s', $this->allowIfObjectIdentityUnavailable? 'grant access' : 'abstain'));
                }

                return $this->allowIfObjectIdentityUnavailable ? self::ACCESS_GRANTED : self::ACCESS_ABSTAIN;
            } elseif ($object instanceof FieldVote) {
                $field = $object->getField();
                $object = $object->getDomainObject();
            } else {
                $field = null;
            }

            if ($object instanceof ObjectIdentityInterface) {
                $oid = $object;
            } elseif (null === $oid = $this->objectIdentityRetrievalStrategy->getObjectIdentity($object)) {
                if (null !== $this->logger) {
                    $this->logger->debug(sprintf('Object identity unavailable. Voting to %s', $this->allowIfObjectIdentityUnavailable? 'grant access' : 'abstain'));
                }

                return $this->allowIfObjectIdentityUnavailable ? self::ACCESS_GRANTED : self::ACCESS_ABSTAIN;
            }

            if (!$this->supportsClass($oid->getType())) {
                return self::ACCESS_ABSTAIN;
            }

            $sids = $this->securityIdentityRetrievalStrategy->getSecurityIdentities($token);

            try {
                $acl = $this->aclProvider->findAcl($oid, $sids);

                if (null === $field && $acl->isGranted($masks, $sids, false)) {
                    if (null !== $this->logger) {
                        $this->logger->debug('ACL found, permission granted. Voting to grant access');
                    }

                    return self::ACCESS_GRANTED;
                } elseif (null !== $field && $acl->isFieldGranted($field, $masks, $sids, false)) {
                    if (null !== $this->logger) {
                        $this->logger->debug('ACL found, permission granted. Voting to grant access');
                    }

                    return self::ACCESS_GRANTED;
                }

                if (null !== $this->logger) {
                    $this->logger->debug('ACL found, insufficient permissions. Voting to deny access.');
                }

                return self::ACCESS_DENIED;
            } catch (AclNotFoundException $noAcl) {
                if (null !== $this->logger) {
                    $this->logger->debug('No ACL found for the object identity. Voting to deny access.');
                }

                return self::ACCESS_DENIED;
            } catch (NoAceFoundException $noAce) {
                if (null !== $this->logger) {
                    $this->logger->debug('ACL found, no ACE applicable. Voting to deny access.');
                }

                return self::ACCESS_DENIED;
            }
        }

        // no attribute was supported
        return self::ACCESS_ABSTAIN;
    }

    /**
     * You can override this method when writing a voter for a specific domain
     * class.
     *
     * @param string $class The class name
     *
     * @return Boolean
     */
    public function supportsClass($class)
    {
        return true;
    }
}
PK��Z\!�	HH2Symfony/Component/Security/Acl/Voter/FieldVote.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Voter;

/**
 * This class is a lightweight wrapper around field vote requests which does
 * not violate any interface contracts.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class FieldVote
{
    private $domainObject;
    private $field;

    public function __construct($domainObject, $field)
    {
        $this->domainObject = $domainObject;
        $this->field = $field;
    }

    public function getDomainObject()
    {
        return $this->domainObject;
    }

    public function getField()
    {
        return $this->field;
    }
}
PK��ZP͡��ASymfony/Component/Security/Acl/Exception/AclNotFoundException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Exception;

/**
 * This exception is thrown when we cannot locate an ACL for a passed
 * ObjectIdentity implementation.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class AclNotFoundException extends Exception
{
}
PK��Z�k�q��6Symfony/Component/Security/Acl/Exception/Exception.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Exception;

/**
 * Base ACL exception
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class Exception extends \Exception
{
}
PK��Z�W�LSymfony/Component/Security/Acl/Exception/ConcurrentModificationException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Exception;

/**
 * This exception is thrown whenever you change shared properties of more than
 * one ACL of the same class type concurrently.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ConcurrentModificationException extends Exception
{
}
PK��Z���OISymfony/Component/Security/Acl/Exception/InvalidDomainObjectException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Exception;

/**
 * This exception is thrown when ObjectIdentity fails to construct an object
 * identity from the passed domain object.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class InvalidDomainObjectException extends Exception
{
}
PK��Z]��_""ESymfony/Component/Security/Acl/Exception/NotAllAclsFoundException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Exception;

/**
 * This exception is thrown when you have requested ACLs for multiple object
 * identities, but the AclProvider implementation failed to find ACLs for all
 * identities.
 *
 * This exception contains the partial result.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class NotAllAclsFoundException extends AclNotFoundException
{
    private $partialResult;

    /**
     * Sets the partial result
     *
     * @param \SplObjectStorage $result
     */
    public function setPartialResult(\SplObjectStorage $result)
    {
        $this->partialResult = $result;
    }

    /**
     * Returns the partial result
     *
     * @return \SplObjectStorage
     */
    public function getPartialResult()
    {
        return $this->partialResult;
    }
}
PK��Z�B�l��@Symfony/Component/Security/Acl/Exception/NoAceFoundException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Exception;

/**
 * This exception is thrown when we cannot locate an ACE that matches the
 * combination of permission masks and security identities.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class NoAceFoundException extends Exception
{
    public function __construct()
    {
        parent::__construct('No applicable ACE was found.');
    }
}
PK��Z[�z�BSymfony/Component/Security/Acl/Exception/SidNotLoadedException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Exception;

/**
 * This exception is thrown when ACEs for an SID are requested which has not
 * been loaded from the database.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class SidNotLoadedException extends Exception
{
}
PK��Z��5�

FSymfony/Component/Security/Acl/Exception/AclAlreadyExistsException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Exception;

/**
 * This exception is thrown when someone tries to create an ACL for an object
 * identity that already has one.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class AclAlreadyExistsException extends Exception
{
}
PK��Zt��:Symfony/Component/Security/Acl/Dbal/MutableAclProvider.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Dbal;

use Doctrine\Common\PropertyChangedListener;
use Doctrine\DBAL\Driver\Connection;
use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity;
use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity;
use Symfony\Component\Security\Acl\Exception\AclAlreadyExistsException;
use Symfony\Component\Security\Acl\Exception\ConcurrentModificationException;
use Symfony\Component\Security\Acl\Model\AclCacheInterface;
use Symfony\Component\Security\Acl\Model\AclInterface;
use Symfony\Component\Security\Acl\Model\EntryInterface;
use Symfony\Component\Security\Acl\Model\MutableAclInterface;
use Symfony\Component\Security\Acl\Model\MutableAclProviderInterface;
use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface;
use Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface;
use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface;

/**
 * An implementation of the MutableAclProviderInterface using Doctrine DBAL.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class MutableAclProvider extends AclProvider implements MutableAclProviderInterface, PropertyChangedListener
{
    private $propertyChanges;

    /**
     * {@inheritDoc}
     */
    public function __construct(Connection $connection, PermissionGrantingStrategyInterface $permissionGrantingStrategy, array $options, AclCacheInterface $cache = null)
    {
        parent::__construct($connection, $permissionGrantingStrategy, $options, $cache);

        $this->propertyChanges = new \SplObjectStorage();
    }

    /**
     * {@inheritDoc}
     */
    public function createAcl(ObjectIdentityInterface $oid)
    {
        if (false !== $this->retrieveObjectIdentityPrimaryKey($oid)) {
            throw new AclAlreadyExistsException(sprintf('%s is already associated with an ACL.', $oid));
        }

        $this->connection->beginTransaction();
        try {
            $this->createObjectIdentity($oid);

            $pk = $this->retrieveObjectIdentityPrimaryKey($oid);
            $this->connection->executeQuery($this->getInsertObjectIdentityRelationSql($pk, $pk));

            $this->connection->commit();
        } catch (\Exception $failed) {
            $this->connection->rollBack();

            throw $failed;
        }

        // re-read the ACL from the database to ensure proper caching, etc.
        return $this->findAcl($oid);
    }

    /**
     * {@inheritDoc}
     */
    public function deleteAcl(ObjectIdentityInterface $oid)
    {
        $this->connection->beginTransaction();
        try {
            foreach ($this->findChildren($oid, true) as $childOid) {
                $this->deleteAcl($childOid);
            }

            $oidPK = $this->retrieveObjectIdentityPrimaryKey($oid);

            $this->deleteAccessControlEntries($oidPK);
            $this->deleteObjectIdentityRelations($oidPK);
            $this->deleteObjectIdentity($oidPK);

            $this->connection->commit();
        } catch (\Exception $failed) {
            $this->connection->rollBack();

            throw $failed;
        }

        // evict the ACL from the in-memory identity map
        if (isset($this->loadedAcls[$oid->getType()][$oid->getIdentifier()])) {
            $this->propertyChanges->offsetUnset($this->loadedAcls[$oid->getType()][$oid->getIdentifier()]);
            unset($this->loadedAcls[$oid->getType()][$oid->getIdentifier()]);
        }

        // evict the ACL from any caches
        if (null !== $this->cache) {
            $this->cache->evictFromCacheByIdentity($oid);
        }
    }

    /**
     * {@inheritDoc}
     */
    public function findAcls(array $oids, array $sids = array())
    {
        $result = parent::findAcls($oids, $sids);

        foreach ($result as $oid) {
            $acl = $result->offsetGet($oid);

            if (false === $this->propertyChanges->contains($acl) && $acl instanceof MutableAclInterface) {
                $acl->addPropertyChangedListener($this);
                $this->propertyChanges->attach($acl, array());
            }

            $parentAcl = $acl->getParentAcl();
            while (null !== $parentAcl) {
                if (false === $this->propertyChanges->contains($parentAcl) && $acl instanceof MutableAclInterface) {
                    $parentAcl->addPropertyChangedListener($this);
                    $this->propertyChanges->attach($parentAcl, array());
                }

                $parentAcl = $parentAcl->getParentAcl();
            }
        }

        return $result;
    }

    /**
     * Implementation of PropertyChangedListener
     *
     * This allows us to keep track of which values have been changed, so we don't
     * have to do a full introspection when ->updateAcl() is called.
     *
     * @param mixed  $sender
     * @param string $propertyName
     * @param mixed  $oldValue
     * @param mixed  $newValue
     *
     * @throws \InvalidArgumentException
     */
    public function propertyChanged($sender, $propertyName, $oldValue, $newValue)
    {
        if (!$sender instanceof MutableAclInterface && !$sender instanceof EntryInterface) {
            throw new \InvalidArgumentException('$sender must be an instance of MutableAclInterface, or EntryInterface.');
        }

        if ($sender instanceof EntryInterface) {
            if (null === $sender->getId()) {
                return;
            }

            $ace = $sender;
            $sender = $ace->getAcl();
        } else {
            $ace = null;
        }

        if (false === $this->propertyChanges->contains($sender)) {
            throw new \InvalidArgumentException('$sender is not being tracked by this provider.');
        }

        $propertyChanges = $this->propertyChanges->offsetGet($sender);
        if (null === $ace) {
            if (isset($propertyChanges[$propertyName])) {
                $oldValue = $propertyChanges[$propertyName][0];
                if ($oldValue === $newValue) {
                    unset($propertyChanges[$propertyName]);
                } else {
                    $propertyChanges[$propertyName] = array($oldValue, $newValue);
                }
            } else {
                $propertyChanges[$propertyName] = array($oldValue, $newValue);
            }
        } else {
            if (!isset($propertyChanges['aces'])) {
                $propertyChanges['aces'] = new \SplObjectStorage();
            }

            $acePropertyChanges = $propertyChanges['aces']->contains($ace)? $propertyChanges['aces']->offsetGet($ace) : array();

            if (isset($acePropertyChanges[$propertyName])) {
                $oldValue = $acePropertyChanges[$propertyName][0];
                if ($oldValue === $newValue) {
                    unset($acePropertyChanges[$propertyName]);
                } else {
                    $acePropertyChanges[$propertyName] = array($oldValue, $newValue);
                }
            } else {
                $acePropertyChanges[$propertyName] = array($oldValue, $newValue);
            }

            if (count($acePropertyChanges) > 0) {
                $propertyChanges['aces']->offsetSet($ace, $acePropertyChanges);
            } else {
                $propertyChanges['aces']->offsetUnset($ace);

                if (0 === count($propertyChanges['aces'])) {
                    unset($propertyChanges['aces']);
                }
            }
        }

        $this->propertyChanges->offsetSet($sender, $propertyChanges);
    }

    /**
     * {@inheritDoc}
     */
    public function updateAcl(MutableAclInterface $acl)
    {
        if (!$this->propertyChanges->contains($acl)) {
            throw new \InvalidArgumentException('$acl is not tracked by this provider.');
        }

        $propertyChanges = $this->propertyChanges->offsetGet($acl);
        // check if any changes were made to this ACL
        if (0 === count($propertyChanges)) {
            return;
        }

        $sets = $sharedPropertyChanges = array();

        $this->connection->beginTransaction();
        try {
            if (isset($propertyChanges['entriesInheriting'])) {
                $sets[] = 'entries_inheriting = '.$this->connection->getDatabasePlatform()->convertBooleans($propertyChanges['entriesInheriting'][1]);
            }

            if (isset($propertyChanges['parentAcl'])) {
                if (null === $propertyChanges['parentAcl'][1]) {
                    $sets[] = 'parent_object_identity_id = NULL';
                } else {
                    $sets[] = 'parent_object_identity_id = '.intval($propertyChanges['parentAcl'][1]->getId());
                }

                $this->regenerateAncestorRelations($acl);
                $childAcls = $this->findAcls($this->findChildren($acl->getObjectIdentity(), false));
                foreach ($childAcls as $childOid) {
                    $this->regenerateAncestorRelations($childAcls[$childOid]);
                }
            }

            // check properties for deleted, and created ACEs, and perform deletions
            // we need to perfom deletions before updating existing ACEs, in order to
            // preserve uniqueness of the order field
            if (isset($propertyChanges['classAces'])) {
                $this->updateOldAceProperty('classAces', $propertyChanges['classAces']);
            }
            if (isset($propertyChanges['classFieldAces'])) {
                $this->updateOldFieldAceProperty('classFieldAces', $propertyChanges['classFieldAces']);
            }
            if (isset($propertyChanges['objectAces'])) {
                $this->updateOldAceProperty('objectAces', $propertyChanges['objectAces']);
            }
            if (isset($propertyChanges['objectFieldAces'])) {
                $this->updateOldFieldAceProperty('objectFieldAces', $propertyChanges['objectFieldAces']);
            }

            // this includes only updates of existing ACEs, but neither the creation, nor
            // the deletion of ACEs; these are tracked by changes to the ACL's respective
            // properties (classAces, classFieldAces, objectAces, objectFieldAces)
            if (isset($propertyChanges['aces'])) {
                $this->updateAces($propertyChanges['aces']);
            }

            // check properties for deleted, and created ACEs, and perform creations
            if (isset($propertyChanges['classAces'])) {
                $this->updateNewAceProperty('classAces', $propertyChanges['classAces']);
                $sharedPropertyChanges['classAces'] = $propertyChanges['classAces'];
            }
            if (isset($propertyChanges['classFieldAces'])) {
                $this->updateNewFieldAceProperty('classFieldAces', $propertyChanges['classFieldAces']);
                $sharedPropertyChanges['classFieldAces'] = $propertyChanges['classFieldAces'];
            }
            if (isset($propertyChanges['objectAces'])) {
                $this->updateNewAceProperty('objectAces', $propertyChanges['objectAces']);
            }
            if (isset($propertyChanges['objectFieldAces'])) {
                $this->updateNewFieldAceProperty('objectFieldAces', $propertyChanges['objectFieldAces']);
            }

            // if there have been changes to shared properties, we need to synchronize other
            // ACL instances for object identities of the same type that are already in-memory
            if (count($sharedPropertyChanges) > 0) {
                $classAcesProperty = new \ReflectionProperty('Symfony\Component\Security\Acl\Domain\Acl', 'classAces');
                $classAcesProperty->setAccessible(true);
                $classFieldAcesProperty = new \ReflectionProperty('Symfony\Component\Security\Acl\Domain\Acl', 'classFieldAces');
                $classFieldAcesProperty->setAccessible(true);

                foreach ($this->loadedAcls[$acl->getObjectIdentity()->getType()] as $sameTypeAcl) {
                    if (isset($sharedPropertyChanges['classAces'])) {
                        if ($acl !== $sameTypeAcl && $classAcesProperty->getValue($sameTypeAcl) !== $sharedPropertyChanges['classAces'][0]) {
                            throw new ConcurrentModificationException('The "classAces" property has been modified concurrently.');
                        }

                        $classAcesProperty->setValue($sameTypeAcl, $sharedPropertyChanges['classAces'][1]);
                    }

                    if (isset($sharedPropertyChanges['classFieldAces'])) {
                        if ($acl !== $sameTypeAcl && $classFieldAcesProperty->getValue($sameTypeAcl) !== $sharedPropertyChanges['classFieldAces'][0]) {
                            throw new ConcurrentModificationException('The "classFieldAces" property has been modified concurrently.');
                        }

                        $classFieldAcesProperty->setValue($sameTypeAcl, $sharedPropertyChanges['classFieldAces'][1]);
                    }
                }
            }

            // persist any changes to the acl_object_identities table
            if (count($sets) > 0) {
                $this->connection->executeQuery($this->getUpdateObjectIdentitySql($acl->getId(), $sets));
            }

            $this->connection->commit();
        } catch (\Exception $failed) {
            $this->connection->rollBack();

            throw $failed;
        }

        $this->propertyChanges->offsetSet($acl, array());

        if (null !== $this->cache) {
            if (count($sharedPropertyChanges) > 0) {
                // FIXME: Currently, there is no easy way to clear the cache for ACLs
                //        of a certain type. The problem here is that we need to make
                //        sure to clear the cache of all child ACLs as well, and these
                //        child ACLs might be of a different class type.
                $this->cache->clearCache();
            } else {
                // if there are no shared property changes, it's sufficient to just delete
                // the cache for this ACL
                $this->cache->evictFromCacheByIdentity($acl->getObjectIdentity());

                foreach ($this->findChildren($acl->getObjectIdentity()) as $childOid) {
                    $this->cache->evictFromCacheByIdentity($childOid);
                }
            }
        }
    }

    /**
     * Constructs the SQL for deleting access control entries.
     *
     * @param integer $oidPK
     * @return string
     */
    protected function getDeleteAccessControlEntriesSql($oidPK)
    {
        return sprintf(
              'DELETE FROM %s WHERE object_identity_id = %d',
            $this->options['entry_table_name'],
            $oidPK
        );
    }

    /**
     * Constructs the SQL for deleting a specific ACE.
     *
     * @param integer $acePK
     * @return string
     */
    protected function getDeleteAccessControlEntrySql($acePK)
    {
        return sprintf(
            'DELETE FROM %s WHERE id = %d',
            $this->options['entry_table_name'],
            $acePK
        );
    }

    /**
     * Constructs the SQL for deleting an object identity.
     *
     * @param integer $pk
     * @return string
     */
    protected function getDeleteObjectIdentitySql($pk)
    {
        return sprintf(
            'DELETE FROM %s WHERE id = %d',
            $this->options['oid_table_name'],
            $pk
        );
    }

    /**
     * Constructs the SQL for deleting relation entries.
     *
     * @param integer $pk
     * @return string
     */
    protected function getDeleteObjectIdentityRelationsSql($pk)
    {
        return sprintf(
            'DELETE FROM %s WHERE object_identity_id = %d',
            $this->options['oid_ancestors_table_name'],
            $pk
        );
    }

    /**
     * Constructs the SQL for inserting an ACE.
     *
     * @param integer      $classId
     * @param integer|null $objectIdentityId
     * @param string|null  $field
     * @param integer      $aceOrder
     * @param integer      $securityIdentityId
     * @param string       $strategy
     * @param integer      $mask
     * @param Boolean      $granting
     * @param Boolean      $auditSuccess
     * @param Boolean      $auditFailure
     * @return string
     */
    protected function getInsertAccessControlEntrySql($classId, $objectIdentityId, $field, $aceOrder, $securityIdentityId, $strategy, $mask, $granting, $auditSuccess, $auditFailure)
    {
        $query = <<<QUERY
            INSERT INTO %s (
                class_id,
                object_identity_id,
                field_name,
                ace_order,
                security_identity_id,
                mask,
                granting,
                granting_strategy,
                audit_success,
                audit_failure
            )
            VALUES (%d, %s, %s, %d, %d, %d, %s, %s, %s, %s)
QUERY;

        return sprintf(
            $query,
            $this->options['entry_table_name'],
            $classId,
            null === $objectIdentityId? 'NULL' : intval($objectIdentityId),
            null === $field? 'NULL' : $this->connection->quote($field),
            $aceOrder,
            $securityIdentityId,
            $mask,
            $this->connection->getDatabasePlatform()->convertBooleans($granting),
            $this->connection->quote($strategy),
            $this->connection->getDatabasePlatform()->convertBooleans($auditSuccess),
            $this->connection->getDatabasePlatform()->convertBooleans($auditFailure)
        );
    }

    /**
     * Constructs the SQL for inserting a new class type.
     *
     * @param string $classType
     * @return string
     */
    protected function getInsertClassSql($classType)
    {
        return sprintf(
            'INSERT INTO %s (class_type) VALUES (%s)',
            $this->options['class_table_name'],
            $this->connection->quote($classType)
        );
    }

    /**
     * Constructs the SQL for inserting a relation entry.
     *
     * @param integer $objectIdentityId
     * @param integer $ancestorId
     * @return string
     */
    protected function getInsertObjectIdentityRelationSql($objectIdentityId, $ancestorId)
    {
        return sprintf(
            'INSERT INTO %s (object_identity_id, ancestor_id) VALUES (%d, %d)',
            $this->options['oid_ancestors_table_name'],
            $objectIdentityId,
            $ancestorId
        );
    }

    /**
     * Constructs the SQL for inserting an object identity.
     *
     * @param string  $identifier
     * @param integer $classId
     * @param Boolean $entriesInheriting
     * @return string
     */
    protected function getInsertObjectIdentitySql($identifier, $classId, $entriesInheriting)
    {
        $query = <<<QUERY
              INSERT INTO %s (class_id, object_identifier, entries_inheriting)
              VALUES (%d, %s, %s)
QUERY;

        return sprintf(
            $query,
            $this->options['oid_table_name'],
            $classId,
            $this->connection->quote($identifier),
            $this->connection->getDatabasePlatform()->convertBooleans($entriesInheriting)
        );
    }

    /**
     * Constructs the SQL for inserting a security identity.
     *
     * @param SecurityIdentityInterface $sid
     * @throws \InvalidArgumentException
     * @return string
     */
    protected function getInsertSecurityIdentitySql(SecurityIdentityInterface $sid)
    {
        if ($sid instanceof UserSecurityIdentity) {
            $identifier = $sid->getClass().'-'.$sid->getUsername();
            $username = true;
        } elseif ($sid instanceof RoleSecurityIdentity) {
            $identifier = $sid->getRole();
            $username = false;
        } else {
            throw new \InvalidArgumentException('$sid must either be an instance of UserSecurityIdentity, or RoleSecurityIdentity.');
        }

        return sprintf(
            'INSERT INTO %s (identifier, username) VALUES (%s, %s)',
            $this->options['sid_table_name'],
            $this->connection->quote($identifier),
            $this->connection->getDatabasePlatform()->convertBooleans($username)
        );
    }

    /**
     * Constructs the SQL for selecting an ACE.
     *
     * @param integer $classId
     * @param integer $oid
     * @param string  $field
     * @param integer $order
     * @return string
     */
    protected function getSelectAccessControlEntryIdSql($classId, $oid, $field, $order)
    {
        return sprintf(
            'SELECT id FROM %s WHERE class_id = %d AND %s AND %s AND ace_order = %d',
            $this->options['entry_table_name'],
            $classId,
            null === $oid ?
                $this->connection->getDatabasePlatform()->getIsNullExpression('object_identity_id')
                : 'object_identity_id = '.intval($oid),
            null === $field ?
                $this->connection->getDatabasePlatform()->getIsNullExpression('field_name')
                : 'field_name = '.$this->connection->quote($field),
            $order
        );
    }

    /**
     * Constructs the SQL for selecting the primary key associated with
     * the passed class type.
     *
     * @param string $classType
     * @return string
     */
    protected function getSelectClassIdSql($classType)
    {
        return sprintf(
            'SELECT id FROM %s WHERE class_type = %s',
            $this->options['class_table_name'],
            $this->connection->quote($classType)
        );
    }

    /**
     * Constructs the SQL for selecting the primary key of a security identity.
     *
     * @param SecurityIdentityInterface $sid
     * @throws \InvalidArgumentException
     * @return string
     */
    protected function getSelectSecurityIdentityIdSql(SecurityIdentityInterface $sid)
    {
        if ($sid instanceof UserSecurityIdentity) {
            $identifier = $sid->getClass().'-'.$sid->getUsername();
            $username = true;
        } elseif ($sid instanceof RoleSecurityIdentity) {
            $identifier = $sid->getRole();
            $username = false;
        } else {
            throw new \InvalidArgumentException('$sid must either be an instance of UserSecurityIdentity, or RoleSecurityIdentity.');
        }

        return sprintf(
            'SELECT id FROM %s WHERE identifier = %s AND username = %s',
            $this->options['sid_table_name'],
            $this->connection->quote($identifier),
            $this->connection->getDatabasePlatform()->convertBooleans($username)
        );
    }

    /**
     * Constructs the SQL for updating an object identity.
     *
     * @param integer $pk
     * @param array   $changes
     * @throws \InvalidArgumentException
     * @return string
     */
    protected function getUpdateObjectIdentitySql($pk, array $changes)
    {
        if (0 === count($changes)) {
            throw new \InvalidArgumentException('There are no changes.');
        }

        return sprintf(
            'UPDATE %s SET %s WHERE id = %d',
            $this->options['oid_table_name'],
            implode(', ', $changes),
            $pk
        );
    }

    /**
     * Constructs the SQL for updating an ACE.
     *
     * @param integer $pk
     * @param array   $sets
     * @throws \InvalidArgumentException
     * @return string
     */
    protected function getUpdateAccessControlEntrySql($pk, array $sets)
    {
        if (0 === count($sets)) {
            throw new \InvalidArgumentException('There are no changes.');
        }

        return sprintf(
            'UPDATE %s SET %s WHERE id = %d',
            $this->options['entry_table_name'],
            implode(', ', $sets),
            $pk
        );
    }

    /**
     * Creates the ACL for the passed object identity
     *
     * @param ObjectIdentityInterface $oid
     */
    private function createObjectIdentity(ObjectIdentityInterface $oid)
    {
        $classId = $this->createOrRetrieveClassId($oid->getType());

        $this->connection->executeQuery($this->getInsertObjectIdentitySql($oid->getIdentifier(), $classId, true));
    }

    /**
     * Returns the primary key for the passed class type.
     *
     * If the type does not yet exist in the database, it will be created.
     *
     * @param string $classType
     * @return integer
     */
    private function createOrRetrieveClassId($classType)
    {
        if (false !== $id = $this->connection->executeQuery($this->getSelectClassIdSql($classType))->fetchColumn()) {
            return $id;
        }

        $this->connection->executeQuery($this->getInsertClassSql($classType));

        return $this->connection->executeQuery($this->getSelectClassIdSql($classType))->fetchColumn();
    }

    /**
     * Returns the primary key for the passed security identity.
     *
     * If the security identity does not yet exist in the database, it will be
     * created.
     *
     * @param SecurityIdentityInterface $sid
     * @return integer
     */
    private function createOrRetrieveSecurityIdentityId(SecurityIdentityInterface $sid)
    {
        if (false !== $id = $this->connection->executeQuery($this->getSelectSecurityIdentityIdSql($sid))->fetchColumn()) {
            return $id;
        }

        $this->connection->executeQuery($this->getInsertSecurityIdentitySql($sid));

        return $this->connection->executeQuery($this->getSelectSecurityIdentityIdSql($sid))->fetchColumn();
    }

    /**
     * Deletes all ACEs for the given object identity primary key.
     *
     * @param integer $oidPK
     */
    private function deleteAccessControlEntries($oidPK)
    {
        $this->connection->executeQuery($this->getDeleteAccessControlEntriesSql($oidPK));
    }

    /**
     * Deletes the object identity from the database.
     *
     * @param integer $pk
     */
    private function deleteObjectIdentity($pk)
    {
        $this->connection->executeQuery($this->getDeleteObjectIdentitySql($pk));
    }

    /**
     * Deletes all entries from the relations table from the database.
     *
     * @param integer $pk
     */
    private function deleteObjectIdentityRelations($pk)
    {
        $this->connection->executeQuery($this->getDeleteObjectIdentityRelationsSql($pk));
    }

    /**
     * This regenerates the ancestor table which is used for fast read access.
     *
     * @param AclInterface $acl
     */
    private function regenerateAncestorRelations(AclInterface $acl)
    {
        $pk = $acl->getId();
        $this->connection->executeQuery($this->getDeleteObjectIdentityRelationsSql($pk));
        $this->connection->executeQuery($this->getInsertObjectIdentityRelationSql($pk, $pk));

        $parentAcl = $acl->getParentAcl();
        while (null !== $parentAcl) {
            $this->connection->executeQuery($this->getInsertObjectIdentityRelationSql($pk, $parentAcl->getId()));

            $parentAcl = $parentAcl->getParentAcl();
        }
    }

    /**
     * This processes new entries changes on an ACE related property (classFieldAces, or objectFieldAces).
     *
     * @param string $name
     * @param array  $changes
     */
    private function updateNewFieldAceProperty($name, array $changes)
    {
        $sids = new \SplObjectStorage();
        $classIds = new \SplObjectStorage();
        $currentIds = array();
        foreach ($changes[1] as $field => $new) {
            for ($i=0,$c=count($new); $i<$c; $i++) {
                $ace = $new[$i];

                if (null === $ace->getId()) {
                    if ($sids->contains($ace->getSecurityIdentity())) {
                        $sid = $sids->offsetGet($ace->getSecurityIdentity());
                    } else {
                        $sid = $this->createOrRetrieveSecurityIdentityId($ace->getSecurityIdentity());
                    }

                    $oid = $ace->getAcl()->getObjectIdentity();
                    if ($classIds->contains($oid)) {
                        $classId = $classIds->offsetGet($oid);
                    } else {
                        $classId = $this->createOrRetrieveClassId($oid->getType());
                    }

                    $objectIdentityId = $name === 'classFieldAces' ? null : $ace->getAcl()->getId();

                    $this->connection->executeQuery($this->getInsertAccessControlEntrySql($classId, $objectIdentityId, $field, $i, $sid, $ace->getStrategy(), $ace->getMask(), $ace->isGranting(), $ace->isAuditSuccess(), $ace->isAuditFailure()));
                    $aceId = $this->connection->executeQuery($this->getSelectAccessControlEntryIdSql($classId, $objectIdentityId, $field, $i))->fetchColumn();
                    $this->loadedAces[$aceId] = $ace;

                    $aceIdProperty = new \ReflectionProperty('Symfony\Component\Security\Acl\Domain\Entry', 'id');
                    $aceIdProperty->setAccessible(true);
                    $aceIdProperty->setValue($ace, intval($aceId));
                } else {
                    $currentIds[$ace->getId()] = true;
                }
            }
        }
    }

    /**
     * This process old entries changes on an ACE related property (classFieldAces, or objectFieldAces).
     *
     * @param string $name
     * @param array $changes
     */
    private function updateOldFieldAceProperty($ane, array $changes)
    {
        $currentIds = array();
        foreach ($changes[1] as $field => $new) {
            for ($i = 0, $c = count($new); $i < $c; $i++) {
                $ace = $new[$i];

                if (null !== $ace->getId()) {
                    $currentIds[$ace->getId()] = true;
                }
            }
        }

        foreach ($changes[0] as $old) {
            for ($i = 0, $c = count($old); $i < $c; $i++) {
                $ace = $old[$i];

                if (!isset($currentIds[$ace->getId()])) {
                    $this->connection->executeQuery($this->getDeleteAccessControlEntrySql($ace->getId()));
                    unset($this->loadedAces[$ace->getId()]);
                }
            }
        }
    }

    /**
     * This processes new entries changes on an ACE related property (classAces, or objectAces).
     *
     * @param string $name
     * @param array  $changes
     */
    private function updateNewAceProperty($name, array $changes)
    {
        list($old, $new) = $changes;

        $sids = new \SplObjectStorage();
        $classIds = new \SplObjectStorage();
        $currentIds = array();
        for ($i=0,$c=count($new); $i<$c; $i++) {
            $ace = $new[$i];

            if (null === $ace->getId()) {
                if ($sids->contains($ace->getSecurityIdentity())) {
                    $sid = $sids->offsetGet($ace->getSecurityIdentity());
                } else {
                    $sid = $this->createOrRetrieveSecurityIdentityId($ace->getSecurityIdentity());
                }

                $oid = $ace->getAcl()->getObjectIdentity();
                if ($classIds->contains($oid)) {
                    $classId = $classIds->offsetGet($oid);
                } else {
                    $classId = $this->createOrRetrieveClassId($oid->getType());
                }

                $objectIdentityId = $name === 'classAces' ? null : $ace->getAcl()->getId();

                $this->connection->executeQuery($this->getInsertAccessControlEntrySql($classId, $objectIdentityId, null, $i, $sid, $ace->getStrategy(), $ace->getMask(), $ace->isGranting(), $ace->isAuditSuccess(), $ace->isAuditFailure()));
                $aceId = $this->connection->executeQuery($this->getSelectAccessControlEntryIdSql($classId, $objectIdentityId, null, $i))->fetchColumn();
                $this->loadedAces[$aceId] = $ace;

                $aceIdProperty = new \ReflectionProperty($ace, 'id');
                $aceIdProperty->setAccessible(true);
                $aceIdProperty->setValue($ace, intval($aceId));
            } else {
                $currentIds[$ace->getId()] = true;
            }
        }
    }

    /**
     * This processes old entries changes on an ACE related property (classAces, or objectAces).
     *
     * @param string $name
     * @param array  $changes
     */
    private function updateOldAceProperty($name, array $changes)
    {
        list($old, $new) = $changes;
        $currentIds = array();

        for ($i=0,$c=count($new); $i<$c; $i++) {
            $ace = $new[$i];

            if (null !== $ace->getId()) {
                $currentIds[$ace->getId()] = true;
            }
        }

        for ($i = 0, $c = count($old); $i < $c; $i++) {
            $ace = $old[$i];

            if (!isset($currentIds[$ace->getId()])) {
                $this->connection->executeQuery($this->getDeleteAccessControlEntrySql($ace->getId()));
                unset($this->loadedAces[$ace->getId()]);
            }
        }
    }

    /**
     * Persists the changes which were made to ACEs to the database.
     *
     * @param \SplObjectStorage $aces
     */
    private function updateAces(\SplObjectStorage $aces)
    {
        foreach ($aces as $ace) {
            $this->updateAce($aces, $ace);
        }
    }

    private function updateAce(\SplObjectStorage $aces, $ace)
    {
        $propertyChanges = $aces->offsetGet($ace);
        $sets = array();

        if (isset($propertyChanges['aceOrder'])
            && $propertyChanges['aceOrder'][1] > $propertyChanges['aceOrder'][0]
            && $propertyChanges == $aces->offsetGet($ace)) {
                $aces->next();
                if ($aces->valid()) {
                    $this->updateAce($aces, $aces->current());
                }
            }

        if (isset($propertyChanges['mask'])) {
            $sets[] = sprintf('mask = %d', $propertyChanges['mask'][1]);
        }
        if (isset($propertyChanges['strategy'])) {
            $sets[] = sprintf('granting_strategy = %s', $this->connection->quote($propertyChanges['strategy']));
        }
        if (isset($propertyChanges['aceOrder'])) {
            $sets[] = sprintf('ace_order = %d', $propertyChanges['aceOrder'][1]);
        }
        if (isset($propertyChanges['auditSuccess'])) {
            $sets[] = sprintf('audit_success = %s', $this->connection->getDatabasePlatform()->convertBooleans($propertyChanges['auditSuccess'][1]));
        }
        if (isset($propertyChanges['auditFailure'])) {
            $sets[] = sprintf('audit_failure = %s', $this->connection->getDatabasePlatform()->convertBooleans($propertyChanges['auditFailure'][1]));
        }

        $this->connection->executeQuery($this->getUpdateAccessControlEntrySql($ace->getId(), $sets));
    }

}
PK��Z�^�+f+f3Symfony/Component/Security/Acl/Dbal/AclProvider.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Dbal;

use Doctrine\DBAL\Driver\Connection;
use Doctrine\DBAL\Driver\Statement;
use Symfony\Component\Security\Acl\Model\AclInterface;
use Symfony\Component\Security\Acl\Domain\Acl;
use Symfony\Component\Security\Acl\Domain\Entry;
use Symfony\Component\Security\Acl\Domain\FieldEntry;
use Symfony\Component\Security\Acl\Domain\ObjectIdentity;
use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity;
use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity;
use Symfony\Component\Security\Acl\Exception\AclNotFoundException;
use Symfony\Component\Security\Acl\Exception\NotAllAclsFoundException;
use Symfony\Component\Security\Acl\Model\AclCacheInterface;
use Symfony\Component\Security\Acl\Model\AclProviderInterface;
use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface;
use Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface;

/**
 * An ACL provider implementation.
 *
 * This provider assumes that all ACLs share the same PermissionGrantingStrategy.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class AclProvider implements AclProviderInterface
{
    const MAX_BATCH_SIZE = 30;

    protected $cache;
    protected $connection;
    protected $loadedAces = array();
    protected $loadedAcls = array();
    protected $options;
    private $permissionGrantingStrategy;

    /**
     * Constructor.
     *
     * @param Connection                          $connection
     * @param PermissionGrantingStrategyInterface $permissionGrantingStrategy
     * @param array                               $options
     * @param AclCacheInterface                   $cache
     */
    public function __construct(Connection $connection, PermissionGrantingStrategyInterface $permissionGrantingStrategy, array $options, AclCacheInterface $cache = null)
    {
        $this->cache = $cache;
        $this->connection = $connection;
        $this->options = $options;
        $this->permissionGrantingStrategy = $permissionGrantingStrategy;
    }

    /**
     * {@inheritDoc}
     */
    public function findChildren(ObjectIdentityInterface $parentOid, $directChildrenOnly = false)
    {
        $sql = $this->getFindChildrenSql($parentOid, $directChildrenOnly);

        $children = array();
        foreach ($this->connection->executeQuery($sql)->fetchAll() as $data) {
            $children[] = new ObjectIdentity($data['object_identifier'], $data['class_type']);
        }

        return $children;
    }

    /**
     * {@inheritDoc}
     */
    public function findAcl(ObjectIdentityInterface $oid, array $sids = array())
    {
        return $this->findAcls(array($oid), $sids)->offsetGet($oid);
    }

    /**
     * {@inheritDoc}
     */
    public function findAcls(array $oids, array $sids = array())
    {
        $result = new \SplObjectStorage();
        $currentBatch = array();
        $oidLookup = array();

        for ($i=0,$c=count($oids); $i<$c; $i++) {
            $oid = $oids[$i];
            $oidLookupKey = $oid->getIdentifier().$oid->getType();
            $oidLookup[$oidLookupKey] = $oid;
            $aclFound = false;

            // check if result already contains an ACL
            if ($result->contains($oid)) {
                $aclFound = true;
            }

            // check if this ACL has already been hydrated
            if (!$aclFound && isset($this->loadedAcls[$oid->getType()][$oid->getIdentifier()])) {
                $acl = $this->loadedAcls[$oid->getType()][$oid->getIdentifier()];

                if (!$acl->isSidLoaded($sids)) {
                    // FIXME: we need to load ACEs for the missing SIDs. This is never
                    //        reached by the default implementation, since we do not
                    //        filter by SID
                    throw new \RuntimeException('This is not supported by the default implementation.');
                } else {
                    $result->attach($oid, $acl);
                    $aclFound = true;
                }
            }

            // check if we can locate the ACL in the cache
            if (!$aclFound && null !== $this->cache) {
                $acl = $this->cache->getFromCacheByIdentity($oid);

                if (null !== $acl) {
                    if ($acl->isSidLoaded($sids)) {
                        // check if any of the parents has been loaded since we need to
                        // ensure that there is only ever one ACL per object identity
                        $parentAcl = $acl->getParentAcl();
                        while (null !== $parentAcl) {
                            $parentOid = $parentAcl->getObjectIdentity();

                            if (isset($this->loadedAcls[$parentOid->getType()][$parentOid->getIdentifier()])) {
                                $acl->setParentAcl($this->loadedAcls[$parentOid->getType()][$parentOid->getIdentifier()]);
                                break;
                            } else {
                                $this->loadedAcls[$parentOid->getType()][$parentOid->getIdentifier()] = $parentAcl;
                                $this->updateAceIdentityMap($parentAcl);
                            }

                            $parentAcl = $parentAcl->getParentAcl();
                        }

                        $this->loadedAcls[$oid->getType()][$oid->getIdentifier()] = $acl;
                        $this->updateAceIdentityMap($acl);
                        $result->attach($oid, $acl);
                        $aclFound = true;
                    } else {
                        $this->cache->evictFromCacheByIdentity($oid);

                        foreach ($this->findChildren($oid) as $childOid) {
                            $this->cache->evictFromCacheByIdentity($childOid);
                        }
                    }
                }
            }

            // looks like we have to load the ACL from the database
            if (!$aclFound) {
                $currentBatch[] = $oid;
            }

            // Is it time to load the current batch?
            if ((self::MAX_BATCH_SIZE === count($currentBatch) || ($i + 1) === $c) && count($currentBatch) > 0) {
                try {
                    $loadedBatch = $this->lookupObjectIdentities($currentBatch, $sids, $oidLookup);
                } catch (AclNotFoundException $aclNotFoundexception) {
                    if ($result->count()) {
                        $partialResultException = new NotAllAclsFoundException('The provider could not find ACLs for all object identities.');
                        $partialResultException->setPartialResult($result);
                        throw $partialResultException;
                    } else {
                        throw $aclNotFoundexception;
                    }
                }
                foreach ($loadedBatch as $loadedOid) {
                    $loadedAcl = $loadedBatch->offsetGet($loadedOid);

                    if (null !== $this->cache) {
                        $this->cache->putInCache($loadedAcl);
                    }

                    if (isset($oidLookup[$loadedOid->getIdentifier().$loadedOid->getType()])) {
                        $result->attach($loadedOid, $loadedAcl);
                    }
                }

                $currentBatch = array();
            }
        }

        // check that we got ACLs for all the identities
        foreach ($oids as $oid) {
            if (!$result->contains($oid)) {
                if (1 === count($oids)) {
                    throw new AclNotFoundException(sprintf('No ACL found for %s.', $oid));
                }

                $partialResultException = new NotAllAclsFoundException('The provider could not find ACLs for all object identities.');
                $partialResultException->setPartialResult($result);

                throw $partialResultException;
            }
        }

        return $result;
    }

    /**
     * Constructs the query used for looking up object identities and associated
     * ACEs, and security identities.
     *
     * @param array $ancestorIds
     * @return string
     */
    protected function getLookupSql(array $ancestorIds)
    {
        // FIXME: add support for filtering by sids (right now we select all sids)

        $sql = <<<SELECTCLAUSE
            SELECT
                o.id as acl_id,
                o.object_identifier,
                o.parent_object_identity_id,
                o.entries_inheriting,
                c.class_type,
                e.id as ace_id,
                e.object_identity_id,
                e.field_name,
                e.ace_order,
                e.mask,
                e.granting,
                e.granting_strategy,
                e.audit_success,
                e.audit_failure,
                s.username,
                s.identifier as security_identifier
            FROM
                {$this->options['oid_table_name']} o
            INNER JOIN {$this->options['class_table_name']} c ON c.id = o.class_id
            LEFT JOIN {$this->options['entry_table_name']} e ON (
                e.class_id = o.class_id AND (e.object_identity_id = o.id OR {$this->connection->getDatabasePlatform()->getIsNullExpression('e.object_identity_id')})
            )
            LEFT JOIN {$this->options['sid_table_name']} s ON (
                s.id = e.security_identity_id
            )

            WHERE (o.id =
SELECTCLAUSE;

        $sql .= implode(' OR o.id = ', $ancestorIds).')';

        return $sql;
    }

    protected function getAncestorLookupSql(array $batch)
    {
        $sql = <<<SELECTCLAUSE
            SELECT a.ancestor_id
            FROM
                {$this->options['oid_table_name']} o
            INNER JOIN {$this->options['class_table_name']} c ON c.id = o.class_id
            INNER JOIN {$this->options['oid_ancestors_table_name']} a ON a.object_identity_id = o.id
               WHERE (
SELECTCLAUSE;

        $types = array();
        $count = count($batch);
        for ($i = 0; $i < $count; $i++) {
            if (!isset($types[$batch[$i]->getType()])) {
                $types[$batch[$i]->getType()] = true;

                // if there is more than one type we can safely break out of the
                // loop, because it is the differentiator factor on whether to
                // query for only one or more class types
                if (count($types) > 1) {
                    break;
                }
            }
        }

        if (1 === count($types)) {
            $ids = array();
            for ($i = 0; $i < $count; $i++) {
                $ids[] = $this->connection->quote($batch[$i]->getIdentifier());
            }

            $sql .= sprintf(
                '(o.object_identifier IN (%s) AND c.class_type = %s)',
                implode(',', $ids),
                $this->connection->quote($batch[0]->getType())
            );
        } else {
            $where = '(o.object_identifier = %s AND c.class_type = %s)';
            for ($i = 0; $i < $count; $i++) {
                $sql .= sprintf(
                    $where,
                    $this->connection->quote($batch[$i]->getIdentifier()),
                    $this->connection->quote($batch[$i]->getType())
                );

                if ($i+1 < $count) {
                    $sql .= ' OR ';
                }
            }
        }

        $sql .= ')';

        return $sql;
    }

    /**
     * Constructs the SQL for retrieving child object identities for the given
     * object identities.
     *
     * @param ObjectIdentityInterface $oid
     * @param Boolean                 $directChildrenOnly
     * @return string
     */
    protected function getFindChildrenSql(ObjectIdentityInterface $oid, $directChildrenOnly)
    {
        if (false === $directChildrenOnly) {
            $query = <<<FINDCHILDREN
                SELECT o.object_identifier, c.class_type
                FROM
                    {$this->options['oid_table_name']} as o
                INNER JOIN {$this->options['class_table_name']} as c ON c.id = o.class_id
                INNER JOIN {$this->options['oid_ancestors_table_name']} as a ON a.object_identity_id = o.id
                WHERE
                    a.ancestor_id = %d AND a.object_identity_id != a.ancestor_id
FINDCHILDREN;
        } else {
            $query = <<<FINDCHILDREN
                SELECT o.object_identifier, c.class_type
                FROM {$this->options['oid_table_name']} as o
                INNER JOIN {$this->options['class_table_name']} as c ON c.id = o.class_id
                WHERE o.parent_object_identity_id = %d
FINDCHILDREN;
        }

        return sprintf($query, $this->retrieveObjectIdentityPrimaryKey($oid));
    }

    /**
     * Constructs the SQL for retrieving the primary key of the given object
     * identity.
     *
     * @param ObjectIdentityInterface $oid
     * @return string
     */
    protected function getSelectObjectIdentityIdSql(ObjectIdentityInterface $oid)
    {
        $query = <<<QUERY
            SELECT o.id
            FROM %s o
            INNER JOIN %s c ON c.id = o.class_id
            WHERE o.object_identifier = %s AND c.class_type = %s
QUERY;

        return sprintf(
            $query,
            $this->options['oid_table_name'],
            $this->options['class_table_name'],
            $this->connection->quote($oid->getIdentifier()),
            $this->connection->quote($oid->getType())
        );
    }

    /**
     * Returns the primary key of the passed object identity.
     *
     * @param ObjectIdentityInterface $oid
     * @return integer
     */
    final protected function retrieveObjectIdentityPrimaryKey(ObjectIdentityInterface $oid)
    {
        return $this->connection->executeQuery($this->getSelectObjectIdentityIdSql($oid))->fetchColumn();
    }

    /**
     * This method is called when an ACL instance is retrieved from the cache.
     *
     * @param AclInterface $acl
     */
    private function updateAceIdentityMap(AclInterface $acl)
    {
        foreach (array('classAces', 'classFieldAces', 'objectAces', 'objectFieldAces') as $property) {
            $reflection = new \ReflectionProperty($acl, $property);
            $reflection->setAccessible(true);
            $value = $reflection->getValue($acl);

            if ('classAces' === $property || 'objectAces' === $property) {
                $this->doUpdateAceIdentityMap($value);
            } else {
                foreach ($value as $field => $aces) {
                    $this->doUpdateAceIdentityMap($value[$field]);
                }
            }

            $reflection->setValue($acl, $value);
            $reflection->setAccessible(false);
        }
    }

    /**
     * Retrieves all the ids which need to be queried from the database
     * including the ids of parent ACLs.
     *
     * @param array $batch
     *
     * @return array
     */
    private function getAncestorIds(array $batch)
    {
        $sql = $this->getAncestorLookupSql($batch);

        $ancestorIds = array();
        foreach ($this->connection->executeQuery($sql)->fetchAll() as $data) {
            // FIXME: skip ancestors which are cached

            $ancestorIds[] = $data['ancestor_id'];
        }

        return $ancestorIds;
    }

    /**
     * Does either overwrite the passed ACE, or saves it in the global identity
     * map to ensure every ACE only gets instantiated once.
     *
     * @param array &$aces
     */
    private function doUpdateAceIdentityMap(array &$aces)
    {
        foreach ($aces as $index => $ace) {
            if (isset($this->loadedAces[$ace->getId()])) {
                $aces[$index] = $this->loadedAces[$ace->getId()];
            } else {
                $this->loadedAces[$ace->getId()] = $ace;
            }
        }
    }

    /**
     * This method is called for object identities which could not be retrieved
     * from the cache, and for which thus a database query is required.
     *
     * @param array $batch
     * @param array $sids
     * @param array $oidLookup
     *
     * @return \SplObjectStorage mapping object identities to ACL instances
     *
     * @throws AclNotFoundException
     */
    private function lookupObjectIdentities(array $batch, array $sids, array $oidLookup)
    {
        $ancestorIds = $this->getAncestorIds($batch);
        if (!$ancestorIds) {
            throw new AclNotFoundException('There is no ACL for the given object identity.');
        }

        $sql = $this->getLookupSql($ancestorIds);
        $stmt = $this->connection->executeQuery($sql);

        return $this->hydrateObjectIdentities($stmt, $oidLookup, $sids);
    }

    /**
     * This method is called to hydrate ACLs and ACEs.
     *
     * This method was designed for performance; thus, a lot of code has been
     * inlined at the cost of readability, and maintainability.
     *
     * Keep in mind that changes to this method might severely reduce the
     * performance of the entire ACL system.
     *
     * @param Statement $stmt
     * @param array     $oidLookup
     * @param array     $sids
     * @throws \RuntimeException
     * @return \SplObjectStorage
     */
    private function hydrateObjectIdentities(Statement $stmt, array $oidLookup, array $sids)
    {
        $parentIdToFill = new \SplObjectStorage();
        $acls = $aces = $emptyArray = array();
        $oidCache = $oidLookup;
        $result = new \SplObjectStorage();
        $loadedAces =& $this->loadedAces;
        $loadedAcls =& $this->loadedAcls;
        $permissionGrantingStrategy = $this->permissionGrantingStrategy;

        // we need these to set protected properties on hydrated objects
        $aclReflection = new \ReflectionClass('Symfony\Component\Security\Acl\Domain\Acl');
        $aclClassAcesProperty = $aclReflection->getProperty('classAces');
        $aclClassAcesProperty->setAccessible(true);
        $aclClassFieldAcesProperty = $aclReflection->getProperty('classFieldAces');
        $aclClassFieldAcesProperty->setAccessible(true);
        $aclObjectAcesProperty = $aclReflection->getProperty('objectAces');
        $aclObjectAcesProperty->setAccessible(true);
        $aclObjectFieldAcesProperty = $aclReflection->getProperty('objectFieldAces');
        $aclObjectFieldAcesProperty->setAccessible(true);
        $aclParentAclProperty = $aclReflection->getProperty('parentAcl');
        $aclParentAclProperty->setAccessible(true);

        // fetchAll() consumes more memory than consecutive calls to fetch(),
        // but it is faster
        foreach ($stmt->fetchAll(\PDO::FETCH_NUM) as $data) {
            list($aclId,
                 $objectIdentifier,
                 $parentObjectIdentityId,
                 $entriesInheriting,
                 $classType,
                 $aceId,
                 $objectIdentityId,
                 $fieldName,
                 $aceOrder,
                 $mask,
                 $granting,
                 $grantingStrategy,
                 $auditSuccess,
                 $auditFailure,
                 $username,
                 $securityIdentifier) = $data;

            // has the ACL been hydrated during this hydration cycle?
            if (isset($acls[$aclId])) {
                $acl = $acls[$aclId];
            // has the ACL been hydrated during any previous cycle, or was possibly loaded
            // from cache?
            } elseif (isset($loadedAcls[$classType][$objectIdentifier])) {
                $acl = $loadedAcls[$classType][$objectIdentifier];

                // keep reference in local array (saves us some hash calculations)
                $acls[$aclId] = $acl;

                // attach ACL to the result set; even though we do not enforce that every
                // object identity has only one instance, we must make sure to maintain
                // referential equality with the oids passed to findAcls()
                if (!isset($oidCache[$objectIdentifier.$classType])) {
                    $oidCache[$objectIdentifier.$classType] = $acl->getObjectIdentity();
                }
                $result->attach($oidCache[$objectIdentifier.$classType], $acl);
            // so, this hasn't been hydrated yet
            } else {
                // create object identity if we haven't done so yet
                $oidLookupKey = $objectIdentifier.$classType;
                if (!isset($oidCache[$oidLookupKey])) {
                    $oidCache[$oidLookupKey] = new ObjectIdentity($objectIdentifier, $classType);
                }

                $acl = new Acl((integer) $aclId, $oidCache[$oidLookupKey], $permissionGrantingStrategy, $emptyArray, !!$entriesInheriting);

                // keep a local, and global reference to this ACL
                $loadedAcls[$classType][$objectIdentifier] = $acl;
                $acls[$aclId] = $acl;

                // try to fill in parent ACL, or defer until all ACLs have been hydrated
                if (null !== $parentObjectIdentityId) {
                    if (isset($acls[$parentObjectIdentityId])) {
                        $aclParentAclProperty->setValue($acl, $acls[$parentObjectIdentityId]);
                    } else {
                        $parentIdToFill->attach($acl, $parentObjectIdentityId);
                    }
                }

                $result->attach($oidCache[$oidLookupKey], $acl);
            }

            // check if this row contains an ACE record
            if (null !== $aceId) {
                // have we already hydrated ACEs for this ACL?
                if (!isset($aces[$aclId])) {
                    $aces[$aclId] = array($emptyArray, $emptyArray, $emptyArray, $emptyArray);
                }

                // has this ACE already been hydrated during a previous cycle, or
                // possible been loaded from cache?
                // It is important to only ever have one ACE instance per actual row since
                // some ACEs are shared between ACL instances
                if (!isset($loadedAces[$aceId])) {
                    if (!isset($sids[$key = ($username?'1':'0').$securityIdentifier])) {
                        if ($username) {
                            $sids[$key] = new UserSecurityIdentity(
                                substr($securityIdentifier, 1 + $pos = strpos($securityIdentifier, '-')),
                                substr($securityIdentifier, 0, $pos)
                            );
                        } else {
                            $sids[$key] = new RoleSecurityIdentity($securityIdentifier);
                        }
                    }

                    if (null === $fieldName) {
                        $loadedAces[$aceId] = new Entry((integer) $aceId, $acl, $sids[$key], $grantingStrategy, (integer) $mask, !!$granting, !!$auditFailure, !!$auditSuccess);
                    } else {
                        $loadedAces[$aceId] = new FieldEntry((integer) $aceId, $acl, $fieldName, $sids[$key], $grantingStrategy, (integer) $mask, !!$granting, !!$auditFailure, !!$auditSuccess);
                    }
                }
                $ace = $loadedAces[$aceId];

                // assign ACE to the correct property
                if (null === $objectIdentityId) {
                    if (null === $fieldName) {
                        $aces[$aclId][0][$aceOrder] = $ace;
                    } else {
                        $aces[$aclId][1][$fieldName][$aceOrder] = $ace;
                    }
                } else {
                    if (null === $fieldName) {
                        $aces[$aclId][2][$aceOrder] = $ace;
                    } else {
                        $aces[$aclId][3][$fieldName][$aceOrder] = $ace;
                    }
                }
            }
        }

        // We do not sort on database level since we only want certain subsets to be sorted,
        // and we are going to read the entire result set anyway.
        // Sorting on DB level increases query time by an order of magnitude while it is
        // almost negligible when we use PHPs array sort functions.
        foreach ($aces as $aclId => $aceData) {
            $acl = $acls[$aclId];

            ksort($aceData[0]);
            $aclClassAcesProperty->setValue($acl, $aceData[0]);

            foreach (array_keys($aceData[1]) as $fieldName) {
                ksort($aceData[1][$fieldName]);
            }
            $aclClassFieldAcesProperty->setValue($acl, $aceData[1]);

            ksort($aceData[2]);
            $aclObjectAcesProperty->setValue($acl, $aceData[2]);

            foreach (array_keys($aceData[3]) as $fieldName) {
                ksort($aceData[3][$fieldName]);
            }
            $aclObjectFieldAcesProperty->setValue($acl, $aceData[3]);
        }

        // fill-in parent ACLs where this hasn't been done yet cause the parent ACL was not
        // yet available
        $processed = 0;
        foreach ($parentIdToFill as $acl) {
            $parentId = $parentIdToFill->offsetGet($acl);

            // let's see if we have already hydrated this
            if (isset($acls[$parentId])) {
                $aclParentAclProperty->setValue($acl, $acls[$parentId]);
                $processed += 1;

                continue;
            }
        }

        // reset reflection changes
        $aclClassAcesProperty->setAccessible(false);
        $aclClassFieldAcesProperty->setAccessible(false);
        $aclObjectAcesProperty->setAccessible(false);
        $aclObjectFieldAcesProperty->setAccessible(false);
        $aclParentAclProperty->setAccessible(false);

        // this should never be true if the database integrity hasn't been compromised
        if ($processed < count($parentIdToFill)) {
            throw new \RuntimeException('Not all parent ids were populated. This implies an integrity problem.');
        }

        return $result;
    }
}
PK��ZK� V��.Symfony/Component/Security/Acl/Dbal/Schema.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Dbal;

use Doctrine\DBAL\Schema\Schema as BaseSchema;
use Doctrine\DBAL\Connection;

/**
 * The schema used for the ACL system.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
final class Schema extends BaseSchema
{
    protected $options;

    /**
     * Constructor
     *
     * @param array      $options    the names for tables
     * @param Connection $connection
     */
    public function __construct(array $options, Connection $connection = null)
    {
        $schemaConfig = null === $connection ? null : $connection->getSchemaManager()->createSchemaConfig();

        parent::__construct(array(), array(), $schemaConfig);

        $this->options = $options;

        $this->addClassTable();
        $this->addSecurityIdentitiesTable();
        $this->addObjectIdentitiesTable();
        $this->addObjectIdentityAncestorsTable();
        $this->addEntryTable();
    }

    /**
     * Merges ACL schema with the given schema.
     *
     * @param BaseSchema $schema
     */
    public function addToSchema(BaseSchema $schema)
    {
        foreach ($this->getTables() as $table) {
            $schema->_addTable($table);
        }

        foreach ($this->getSequences() as $sequence) {
            $schema->_addSequence($sequence);
        }
    }

    /**
     * Adds the class table to the schema
     */
    protected function addClassTable()
    {
        $table = $this->createTable($this->options['class_table_name']);
        $table->addColumn('id', 'integer', array('unsigned' => true, 'autoincrement' => 'auto'));
        $table->addColumn('class_type', 'string', array('length' => 200));
        $table->setPrimaryKey(array('id'));
        $table->addUniqueIndex(array('class_type'));
    }

    /**
     * Adds the entry table to the schema
     */
    protected function addEntryTable()
    {
        $table = $this->createTable($this->options['entry_table_name']);

        $table->addColumn('id', 'integer', array('unsigned' => true, 'autoincrement' => 'auto'));
        $table->addColumn('class_id', 'integer', array('unsigned' => true));
        $table->addColumn('object_identity_id', 'integer', array('unsigned' => true, 'notnull' => false));
        $table->addColumn('field_name', 'string', array('length' => 50, 'notnull' => false));
        $table->addColumn('ace_order', 'smallint', array('unsigned' => true));
        $table->addColumn('security_identity_id', 'integer', array('unsigned' => true));
        $table->addColumn('mask', 'integer');
        $table->addColumn('granting', 'boolean');
        $table->addColumn('granting_strategy', 'string', array('length' => 30));
        $table->addColumn('audit_success', 'boolean');
        $table->addColumn('audit_failure', 'boolean');

        $table->setPrimaryKey(array('id'));
        $table->addUniqueIndex(array('class_id', 'object_identity_id', 'field_name', 'ace_order'));
        $table->addIndex(array('class_id', 'object_identity_id', 'security_identity_id'));

        $table->addForeignKeyConstraint($this->getTable($this->options['class_table_name']), array('class_id'), array('id'), array('onDelete' => 'CASCADE', 'onUpdate' => 'CASCADE'));
        $table->addForeignKeyConstraint($this->getTable($this->options['oid_table_name']), array('object_identity_id'), array('id'), array('onDelete' => 'CASCADE', 'onUpdate' => 'CASCADE'));
        $table->addForeignKeyConstraint($this->getTable($this->options['sid_table_name']), array('security_identity_id'), array('id'), array('onDelete' => 'CASCADE', 'onUpdate' => 'CASCADE'));
    }

    /**
     * Adds the object identity table to the schema
     */
    protected function addObjectIdentitiesTable()
    {
        $table = $this->createTable($this->options['oid_table_name']);

        $table->addColumn('id', 'integer', array('unsigned' => true, 'autoincrement' => 'auto'));
        $table->addColumn('class_id', 'integer', array('unsigned' => true));
        $table->addColumn('object_identifier', 'string', array('length' => 100));
        $table->addColumn('parent_object_identity_id', 'integer', array('unsigned' => true, 'notnull' => false));
        $table->addColumn('entries_inheriting', 'boolean');

        $table->setPrimaryKey(array('id'));
        $table->addUniqueIndex(array('object_identifier', 'class_id'));
        $table->addIndex(array('parent_object_identity_id'));

        $table->addForeignKeyConstraint($table, array('parent_object_identity_id'), array('id'));
    }

    /**
     * Adds the object identity relation table to the schema
     */
    protected function addObjectIdentityAncestorsTable()
    {
        $table = $this->createTable($this->options['oid_ancestors_table_name']);

        $table->addColumn('object_identity_id', 'integer', array('unsigned' => true));
        $table->addColumn('ancestor_id', 'integer', array('unsigned' => true));

        $table->setPrimaryKey(array('object_identity_id', 'ancestor_id'));

        $oidTable = $this->getTable($this->options['oid_table_name']);
        $table->addForeignKeyConstraint($oidTable, array('object_identity_id'), array('id'), array('onDelete' => 'CASCADE', 'onUpdate' => 'CASCADE'));
        $table->addForeignKeyConstraint($oidTable, array('ancestor_id'), array('id'), array('onDelete' => 'CASCADE', 'onUpdate' => 'CASCADE'));
    }

    /**
     * Adds the security identity table to the schema
     */
    protected function addSecurityIdentitiesTable()
    {
        $table = $this->createTable($this->options['sid_table_name']);

        $table->addColumn('id', 'integer', array('unsigned' => true, 'autoincrement' => 'auto'));
        $table->addColumn('identifier', 'string', array('length' => 200));
        $table->addColumn('username', 'boolean');

        $table->setPrimaryKey(array('id'));
        $table->addUniqueIndex(array('identifier', 'username'));
    }
}
PK��ZNTA�]]5Symfony/Component/Security/Acl/Domain/AuditLogger.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Domain;

use Symfony\Component\Security\Acl\Model\AuditableEntryInterface;
use Symfony\Component\Security\Acl\Model\EntryInterface;
use Symfony\Component\Security\Acl\Model\AuditLoggerInterface;

/**
 * Base audit logger implementation
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
abstract class AuditLogger implements AuditLoggerInterface
{
    /**
     * Performs some checks if logging was requested
     *
     * @param Boolean        $granted
     * @param EntryInterface $ace
     */
    public function logIfNeeded($granted, EntryInterface $ace)
    {
        if (!$ace instanceof AuditableEntryInterface) {
            return;
        }

        if ($granted && $ace->isAuditSuccess()) {
            $this->doLog($granted, $ace);
        } elseif (!$granted && $ace->isAuditFailure()) {
            $this->doLog($granted, $ace);
        }
    }

    /**
     * This method is only called when logging is needed
     *
     * @param Boolean        $granted
     * @param EntryInterface $ace
     */
    abstract protected function doLog($granted, EntryInterface $ace);
}
PK��Z�.��**>Symfony/Component/Security/Acl/Domain/UserSecurityIdentity.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Domain;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Util\ClassUtils;
use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface;

/**
 * A SecurityIdentity implementation used for actual users
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
final class UserSecurityIdentity implements SecurityIdentityInterface
{
    private $username;
    private $class;

    /**
     * Constructor
     *
     * @param string $username the username representation
     * @param string $class    the user's fully qualified class name
     *
     * @throws \InvalidArgumentException
     */
    public function __construct($username, $class)
    {
        if (empty($username)) {
            throw new \InvalidArgumentException('$username must not be empty.');
        }
        if (empty($class)) {
            throw new \InvalidArgumentException('$class must not be empty.');
        }

        $this->username = (string) $username;
        $this->class = $class;
    }

    /**
     * Creates a user security identity from a UserInterface
     *
     * @param UserInterface $user
     * @return UserSecurityIdentity
     */
    public static function fromAccount(UserInterface $user)
    {
        return new self($user->getUsername(), ClassUtils::getRealClass($user));
    }

    /**
     * Creates a user security identity from a TokenInterface
     *
     * @param TokenInterface $token
     * @return UserSecurityIdentity
     */
    public static function fromToken(TokenInterface $token)
    {
        $user = $token->getUser();

        if ($user instanceof UserInterface) {
            return self::fromAccount($user);
        }

        return new self((string) $user, is_object($user) ? ClassUtils::getRealClass($user) : ClassUtils::getRealClass($token));
    }

    /**
     * Returns the username
     *
     * @return string
     */
    public function getUsername()
    {
        return $this->username;
    }

    /**
     * Returns the user's class name
     *
     * @return string
     */
    public function getClass()
    {
        return $this->class;
    }

    /**
     * {@inheritDoc}
     */
    public function equals(SecurityIdentityInterface $sid)
    {
        if (!$sid instanceof UserSecurityIdentity) {
            return false;
        }

        return $this->username === $sid->getUsername()
               && $this->class === $sid->getClass();
    }

    /**
     * A textual representation of this security identity.
     *
     * This is not used for equality comparison, but only for debugging.
     *
     * @return string
     */
    public function __toString()
    {
        return sprintf('UserSecurityIdentity(%s, %s)', $this->username, $this->class);
    }
}
PK��Z��C3��:Symfony/Component/Security/Acl/Domain/DoctrineAclCache.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Domain;

use Doctrine\Common\Cache\Cache;
use Symfony\Component\Security\Acl\Model\AclCacheInterface;
use Symfony\Component\Security\Acl\Model\AclInterface;
use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface;
use Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface;

/**
 * This class is a wrapper around the actual cache implementation.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class DoctrineAclCache implements AclCacheInterface
{
    const PREFIX = 'sf2_acl_';

    private $cache;
    private $prefix;
    private $permissionGrantingStrategy;

    /**
     * Constructor
     *
     * @param Cache                               $cache
     * @param PermissionGrantingStrategyInterface $permissionGrantingStrategy
     * @param string                              $prefix
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(Cache $cache, PermissionGrantingStrategyInterface $permissionGrantingStrategy, $prefix = self::PREFIX)
    {
        if (0 === strlen($prefix)) {
            throw new \InvalidArgumentException('$prefix cannot be empty.');
        }

        $this->cache = $cache;
        $this->permissionGrantingStrategy = $permissionGrantingStrategy;
        $this->prefix = $prefix;
    }

    /**
     * {@inheritDoc}
     */
    public function clearCache()
    {
        $this->cache->deleteByPrefix($this->prefix);
    }

    /**
     * {@inheritDoc}
     */
    public function evictFromCacheById($aclId)
    {
        $lookupKey = $this->getAliasKeyForIdentity($aclId);
        if (!$this->cache->contains($lookupKey)) {
            return;
        }

        $key = $this->cache->fetch($lookupKey);
        if ($this->cache->contains($key)) {
            $this->cache->delete($key);
        }

        $this->cache->delete($lookupKey);
    }

    /**
     * {@inheritDoc}
     */
    public function evictFromCacheByIdentity(ObjectIdentityInterface $oid)
    {
        $key = $this->getDataKeyByIdentity($oid);
        if (!$this->cache->contains($key)) {
            return;
        }

        $this->cache->delete($key);
    }

    /**
     * {@inheritDoc}
     */
    public function getFromCacheById($aclId)
    {
        $lookupKey = $this->getAliasKeyForIdentity($aclId);
        if (!$this->cache->contains($lookupKey)) {
            return null;
        }

        $key = $this->cache->fetch($lookupKey);
        if (!$this->cache->contains($key)) {
            $this->cache->delete($lookupKey);

            return null;
        }

        return $this->unserializeAcl($this->cache->fetch($key));
    }

    /**
     * {@inheritDoc}
     */
    public function getFromCacheByIdentity(ObjectIdentityInterface $oid)
    {
        $key = $this->getDataKeyByIdentity($oid);
        if (!$this->cache->contains($key)) {
            return null;
        }

        return $this->unserializeAcl($this->cache->fetch($key));
    }

    /**
     * {@inheritDoc}
     */
    public function putInCache(AclInterface $acl)
    {
        if (null === $acl->getId()) {
            throw new \InvalidArgumentException('Transient ACLs cannot be cached.');
        }

        if (null !== $parentAcl = $acl->getParentAcl()) {
            $this->putInCache($parentAcl);
        }

        $key = $this->getDataKeyByIdentity($acl->getObjectIdentity());
        $this->cache->save($key, serialize($acl));
        $this->cache->save($this->getAliasKeyForIdentity($acl->getId()), $key);
    }

    /**
     * Unserializes the ACL.
     *
     * @param string $serialized
     * @return AclInterface
     */
    private function unserializeAcl($serialized)
    {
        $acl = unserialize($serialized);

        if (null !== $parentId = $acl->getParentAcl()) {
            $parentAcl = $this->getFromCacheById($parentId);

            if (null === $parentAcl) {
                return null;
            }

            $acl->setParentAcl($parentAcl);
        }

        $reflectionProperty = new \ReflectionProperty($acl, 'permissionGrantingStrategy');
        $reflectionProperty->setAccessible(true);
        $reflectionProperty->setValue($acl, $this->permissionGrantingStrategy);
        $reflectionProperty->setAccessible(false);

        $aceAclProperty = new \ReflectionProperty('Symfony\Component\Security\Acl\Domain\Entry', 'acl');
        $aceAclProperty->setAccessible(true);

        foreach ($acl->getObjectAces() as $ace) {
            $aceAclProperty->setValue($ace, $acl);
        }
        foreach ($acl->getClassAces() as $ace) {
            $aceAclProperty->setValue($ace, $acl);
        }

        $aceClassFieldProperty = new \ReflectionProperty($acl, 'classFieldAces');
        $aceClassFieldProperty->setAccessible(true);
        foreach ($aceClassFieldProperty->getValue($acl) as $aces) {
            foreach ($aces as $ace) {
                $aceAclProperty->setValue($ace, $acl);
            }
        }
        $aceClassFieldProperty->setAccessible(false);

        $aceObjectFieldProperty = new \ReflectionProperty($acl, 'objectFieldAces');
        $aceObjectFieldProperty->setAccessible(true);
        foreach ($aceObjectFieldProperty->getValue($acl) as $aces) {
            foreach ($aces as $ace) {
                $aceAclProperty->setValue($ace, $acl);
            }
        }
        $aceObjectFieldProperty->setAccessible(false);

        $aceAclProperty->setAccessible(false);

        return $acl;
    }

    /**
     * Returns the key for the object identity
     *
     * @param ObjectIdentityInterface $oid
     * @return string
     */
    private function getDataKeyByIdentity(ObjectIdentityInterface $oid)
    {
        return $this->prefix.md5($oid->getType()).sha1($oid->getType())
               .'_'.md5($oid->getIdentifier()).sha1($oid->getIdentifier());
    }

    /**
     * Returns the alias key for the object identity key
     *
     * @param string $aclId
     * @return string
     */
    private function getAliasKeyForIdentity($aclId)
    {
        return $this->prefix.$aclId;
    }
}
PK��Z(]���DSymfony/Component/Security/Acl/Domain/PermissionGrantingStrategy.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Domain;

use Symfony\Component\Security\Acl\Exception\NoAceFoundException;
use Symfony\Component\Security\Acl\Model\AclInterface;
use Symfony\Component\Security\Acl\Model\AuditLoggerInterface;
use Symfony\Component\Security\Acl\Model\EntryInterface;
use Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface;
use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface;

/**
 * The permission granting strategy to apply to the access control list.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class PermissionGrantingStrategy implements PermissionGrantingStrategyInterface
{
    const EQUAL = 'equal';
    const ALL   = 'all';
    const ANY   = 'any';

    private $auditLogger;

    /**
     * Sets the audit logger
     *
     * @param AuditLoggerInterface $auditLogger
     */
    public function setAuditLogger(AuditLoggerInterface $auditLogger)
    {
        $this->auditLogger = $auditLogger;
    }

    /**
     * {@inheritDoc}
     */
    public function isGranted(AclInterface $acl, array $masks, array $sids, $administrativeMode = false)
    {
        try {
            try {
                $aces = $acl->getObjectAces();

                if (!$aces) {
                    throw new NoAceFoundException();
                }

                return $this->hasSufficientPermissions($acl, $aces, $masks, $sids, $administrativeMode);
            } catch (NoAceFoundException $noObjectAce) {
                $aces = $acl->getClassAces();

                if (!$aces) {
                    throw $noObjectAce;
                }

                return $this->hasSufficientPermissions($acl, $aces, $masks, $sids, $administrativeMode);
            }
        } catch (NoAceFoundException $noClassAce) {
            if ($acl->isEntriesInheriting() && null !== $parentAcl = $acl->getParentAcl()) {
                return $parentAcl->isGranted($masks, $sids, $administrativeMode);
            }

            throw $noClassAce;
        }
    }

    /**
     * {@inheritDoc}
     */
    public function isFieldGranted(AclInterface $acl, $field, array $masks, array $sids, $administrativeMode = false)
    {
        try {
            try {
                $aces = $acl->getObjectFieldAces($field);
                if (!$aces) {
                    throw new NoAceFoundException();
                }

                return $this->hasSufficientPermissions($acl, $aces, $masks, $sids, $administrativeMode);
            } catch (NoAceFoundException $noObjectAces) {
                $aces = $acl->getClassFieldAces($field);
                if (!$aces) {
                    throw $noObjectAces;
                }

                return $this->hasSufficientPermissions($acl, $aces, $masks, $sids, $administrativeMode);
            }
        } catch (NoAceFoundException $noClassAces) {
            if ($acl->isEntriesInheriting() && null !== $parentAcl = $acl->getParentAcl()) {
                return $parentAcl->isFieldGranted($field, $masks, $sids, $administrativeMode);
            }

            throw $noClassAces;
        }
    }

    /**
     * Makes an authorization decision.
     *
     * The order of ACEs, and SIDs is significant; the order of permission masks
     * not so much. It is important to note that the more specific security
     * identities should be at the beginning of the SIDs array in order for this
     * strategy to produce intuitive authorization decisions.
     *
     * First, we will iterate over permissions, then over security identities.
     * For each combination of permission, and identity we will test the
     * available ACEs until we find one which is applicable.
     *
     * The first applicable ACE will make the ultimate decision for the
     * permission/identity combination. If it is granting, this method will return
     * true, if it is denying, the method will continue to check the next
     * permission/identity combination.
     *
     * This process is repeated until either a granting ACE is found, or no
     * permission/identity combinations are left. Finally, we will either throw
     * an NoAceFoundException, or deny access.
     *
     * @param AclInterface                $acl
     * @param EntryInterface[]            $aces               An array of ACE to check against
     * @param array                       $masks              An array of permission masks
     * @param SecurityIdentityInterface[] $sids               An array of SecurityIdentityInterface implementations
     * @param Boolean                     $administrativeMode True turns off audit logging
     *
     * @return Boolean true, or false; either granting, or denying access respectively.
     *
     * @throws NoAceFoundException
     */
    private function hasSufficientPermissions(AclInterface $acl, array $aces, array $masks, array $sids, $administrativeMode)
    {
        $firstRejectedAce  = null;

        foreach ($masks as $requiredMask) {
            foreach ($sids as $sid) {
                foreach ($aces as $ace) {
                    if ($sid->equals($ace->getSecurityIdentity()) && $this->isAceApplicable($requiredMask, $ace)) {
                        if ($ace->isGranting()) {
                            if (!$administrativeMode && null !== $this->auditLogger) {
                                $this->auditLogger->logIfNeeded(true, $ace);
                            }

                            return true;
                        }

                        if (null === $firstRejectedAce) {
                            $firstRejectedAce = $ace;
                        }

                        break 2;
                    }
                }
            }
        }

        if (null !== $firstRejectedAce) {
            if (!$administrativeMode && null !== $this->auditLogger) {
                $this->auditLogger->logIfNeeded(false, $firstRejectedAce);
            }

            return false;
        }

        throw new NoAceFoundException();
    }

    /**
     * Determines whether the ACE is applicable to the given permission/security
     * identity combination.
     *
     * Per default, we support three different comparison strategies.
     *
     * Strategy ALL:
     * The ACE will be considered applicable when all the turned-on bits in the
     * required mask are also turned-on in the ACE mask.
     *
     * Strategy ANY:
     * The ACE will be considered applicable when any of the turned-on bits in
     * the required mask is also turned-on the in the ACE mask.
     *
     * Strategy EQUAL:
     * The ACE will be considered applicable when the bitmasks are equal.
     *
     * @param integer        $requiredMask
     * @param EntryInterface $ace
     *
     * @return Boolean
     *
     * @throws \RuntimeException if the ACE strategy is not supported
     */
    private function isAceApplicable($requiredMask, EntryInterface $ace)
    {
        $strategy = $ace->getStrategy();
        if (self::ALL === $strategy) {
            return $requiredMask === ($ace->getMask() & $requiredMask);
        } elseif (self::ANY === $strategy) {
            return 0 !== ($ace->getMask() & $requiredMask);
        } elseif (self::EQUAL === $strategy) {
            return $requiredMask === $ace->getMask();
        }

        throw new \RuntimeException(sprintf('The strategy "%s" is not supported.', $strategy));
    }
}
PK��Z%�}`M`M-Symfony/Component/Security/Acl/Domain/Acl.phpnu�[���<?php
/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Domain;

use Doctrine\Common\NotifyPropertyChanged;
use Doctrine\Common\PropertyChangedListener;
use Symfony\Component\Security\Acl\Model\AclInterface;
use Symfony\Component\Security\Acl\Model\AuditableAclInterface;
use Symfony\Component\Security\Acl\Model\EntryInterface;
use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface;
use Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface;
use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface;

/**
 * An ACL implementation.
 *
 * Each object identity has exactly one associated ACL. Each ACL can have four
 * different types of ACEs (class ACEs, object ACEs, class field ACEs, object field
 * ACEs).
 *
 * You should not iterate over the ACEs yourself, but instead use isGranted(),
 * or isFieldGranted(). These will utilize an implementation of PermissionGrantingStrategy
 * internally.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class Acl implements AuditableAclInterface, NotifyPropertyChanged
{
    private $parentAcl;
    private $permissionGrantingStrategy;
    private $objectIdentity;
    private $classAces = array();
    private $classFieldAces = array();
    private $objectAces = array();
    private $objectFieldAces = array();
    private $id;
    private $loadedSids;
    private $entriesInheriting;
    private $listeners = array();

    /**
     * Constructor
     *
     * @param integer                             $id
     * @param ObjectIdentityInterface             $objectIdentity
     * @param PermissionGrantingStrategyInterface $permissionGrantingStrategy
     * @param array                               $loadedSids
     * @param Boolean                             $entriesInheriting
     */
    public function __construct($id, ObjectIdentityInterface $objectIdentity, PermissionGrantingStrategyInterface $permissionGrantingStrategy, array $loadedSids = array(), $entriesInheriting)
    {
        $this->id = $id;
        $this->objectIdentity = $objectIdentity;
        $this->permissionGrantingStrategy = $permissionGrantingStrategy;
        $this->loadedSids = $loadedSids;
        $this->entriesInheriting = $entriesInheriting;
    }

    /**
     * Adds a property changed listener
     *
     * @param PropertyChangedListener $listener
     */
    public function addPropertyChangedListener(PropertyChangedListener $listener)
    {
        $this->listeners[] = $listener;
    }

    /**
     * {@inheritDoc}
     */
    public function deleteClassAce($index)
    {
        $this->deleteAce('classAces', $index);
    }

    /**
     * {@inheritDoc}
     */
    public function deleteClassFieldAce($index, $field)
    {
        $this->deleteFieldAce('classFieldAces', $index, $field);
    }

    /**
     * {@inheritDoc}
     */
    public function deleteObjectAce($index)
    {
        $this->deleteAce('objectAces', $index);
    }

    /**
     * {@inheritDoc}
     */
    public function deleteObjectFieldAce($index, $field)
    {
        $this->deleteFieldAce('objectFieldAces', $index, $field);
    }

    /**
     * {@inheritDoc}
     */
    public function getClassAces()
    {
        return $this->classAces;
    }

    /**
     * {@inheritDoc}
     */
    public function getClassFieldAces($field)
    {
        return isset($this->classFieldAces[$field])? $this->classFieldAces[$field] : array();
    }

    /**
     * {@inheritDoc}
     */
    public function getObjectAces()
    {
        return $this->objectAces;
    }

    /**
     * {@inheritDoc}
     */
    public function getObjectFieldAces($field)
    {
        return isset($this->objectFieldAces[$field]) ? $this->objectFieldAces[$field] : array();
    }

    /**
     * {@inheritDoc}
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * {@inheritDoc}
     */
    public function getObjectIdentity()
    {
        return $this->objectIdentity;
    }

    /**
     * {@inheritDoc}
     */
    public function getParentAcl()
    {
        return $this->parentAcl;
    }

    /**
     * {@inheritDoc}
     */
    public function insertClassAce(SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null)
    {
        $this->insertAce('classAces', $index, $mask, $sid, $granting, $strategy);
    }

    /**
     * {@inheritDoc}
     */
    public function insertClassFieldAce($field, SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null)
    {
        $this->insertFieldAce('classFieldAces', $index, $field, $mask, $sid, $granting, $strategy);
    }

    /**
     * {@inheritDoc}
     */
    public function insertObjectAce(SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null)
    {
        $this->insertAce('objectAces', $index, $mask, $sid, $granting, $strategy);
    }

    /**
     * {@inheritDoc}
     */
    public function insertObjectFieldAce($field, SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null)
    {
        $this->insertFieldAce('objectFieldAces', $index, $field, $mask, $sid, $granting, $strategy);
    }

    /**
     * {@inheritDoc}
     */
    public function isEntriesInheriting()
    {
        return $this->entriesInheriting;
    }

    /**
     * {@inheritDoc}
     */
    public function isFieldGranted($field, array $masks, array $securityIdentities, $administrativeMode = false)
    {
        return $this->permissionGrantingStrategy->isFieldGranted($this, $field, $masks, $securityIdentities, $administrativeMode);
    }

    /**
     * {@inheritDoc}
     */
    public function isGranted(array $masks, array $securityIdentities, $administrativeMode = false)
    {
        return $this->permissionGrantingStrategy->isGranted($this, $masks, $securityIdentities, $administrativeMode);
    }

    /**
     * {@inheritDoc}
     */
    public function isSidLoaded($sids)
    {
        if (!$this->loadedSids) {
            return true;
        }

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

        foreach ($sids as $sid) {
            if (!$sid instanceof SecurityIdentityInterface) {
                throw new \InvalidArgumentException(
                    '$sid must be an instance of SecurityIdentityInterface.');
            }

            foreach ($this->loadedSids as $loadedSid) {
                if ($loadedSid->equals($sid)) {
                    continue 2;
                }
            }

            return false;
        }

        return true;
    }

    /**
     * Implementation for the \Serializable interface
     *
     * @return string
     */
    public function serialize()
    {
        return serialize(array(
            null === $this->parentAcl ? null : $this->parentAcl->getId(),
            $this->objectIdentity,
            $this->classAces,
            $this->classFieldAces,
            $this->objectAces,
            $this->objectFieldAces,
            $this->id,
            $this->loadedSids,
            $this->entriesInheriting,
        ));
    }

    /**
     * Implementation for the \Serializable interface
     *
     * @param string $serialized
     */
    public function unserialize($serialized)
    {
        list($this->parentAcl,
             $this->objectIdentity,
             $this->classAces,
             $this->classFieldAces,
             $this->objectAces,
             $this->objectFieldAces,
             $this->id,
             $this->loadedSids,
             $this->entriesInheriting
        ) = unserialize($serialized);

        $this->listeners = array();
    }

    /**
     * {@inheritDoc}
     */
    public function setEntriesInheriting($boolean)
    {
        if ($this->entriesInheriting !== $boolean) {
            $this->onPropertyChanged('entriesInheriting', $this->entriesInheriting, $boolean);
            $this->entriesInheriting = $boolean;
        }
    }

    /**
     * {@inheritDoc}
     */
    public function setParentAcl(AclInterface $acl = null)
    {
        if (null !== $acl && null === $acl->getId()) {
            throw new \InvalidArgumentException('$acl must have an ID.');
        }

        if ($this->parentAcl !== $acl) {
            $this->onPropertyChanged('parentAcl', $this->parentAcl, $acl);
            $this->parentAcl = $acl;
        }
    }

    /**
     * {@inheritDoc}
     */
    public function updateClassAce($index, $mask, $strategy = null)
    {
        $this->updateAce('classAces', $index, $mask, $strategy);
    }

    /**
     * {@inheritDoc}
     */
    public function updateClassFieldAce($index, $field, $mask, $strategy = null)
    {
        $this->updateFieldAce('classFieldAces', $index, $field, $mask, $strategy);
    }

    /**
     * {@inheritDoc}
     */
    public function updateObjectAce($index, $mask, $strategy = null)
    {
        $this->updateAce('objectAces', $index, $mask, $strategy);
    }

    /**
     * {@inheritDoc}
     */
    public function updateObjectFieldAce($index, $field, $mask, $strategy = null)
    {
        $this->updateFieldAce('objectFieldAces', $index, $field, $mask, $strategy);
    }

    /**
     * {@inheritDoc}
     */
    public function updateClassAuditing($index, $auditSuccess, $auditFailure)
    {
        $this->updateAuditing($this->classAces, $index, $auditSuccess, $auditFailure);
    }

    /**
     * {@inheritDoc}
     */
    public function updateClassFieldAuditing($index, $field, $auditSuccess, $auditFailure)
    {
        if (!isset($this->classFieldAces[$field])) {
            throw new \InvalidArgumentException(sprintf('There are no ACEs for field "%s".', $field));
        }

        $this->updateAuditing($this->classFieldAces[$field], $index, $auditSuccess, $auditFailure);
    }

    /**
     * {@inheritDoc}
     */
    public function updateObjectAuditing($index, $auditSuccess, $auditFailure)
    {
        $this->updateAuditing($this->objectAces, $index, $auditSuccess, $auditFailure);
    }

    /**
     * {@inheritDoc}
     */
    public function updateObjectFieldAuditing($index, $field, $auditSuccess, $auditFailure)
    {
        if (!isset($this->objectFieldAces[$field])) {
            throw new \InvalidArgumentException(sprintf('There are no ACEs for field "%s".', $field));
        }

        $this->updateAuditing($this->objectFieldAces[$field], $index, $auditSuccess, $auditFailure);
    }

    /**
     * Deletes an ACE
     *
     * @param string  $property
     * @param integer $index
     * @throws \OutOfBoundsException
     */
    private function deleteAce($property, $index)
    {
        $aces =& $this->$property;
        if (!isset($aces[$index])) {
            throw new \OutOfBoundsException(sprintf('The index "%d" does not exist.', $index));
        }

        $oldValue = $this->$property;
        unset($aces[$index]);
        $this->$property = array_values($this->$property);
        $this->onPropertyChanged($property, $oldValue, $this->$property);

        for ($i=$index,$c=count($this->$property); $i<$c; $i++) {
            $this->onEntryPropertyChanged($aces[$i], 'aceOrder', $i+1, $i);
        }
    }

    /**
     * Deletes a field-based ACE
     *
     * @param string  $property
     * @param integer $index
     * @param string  $field
     * @throws \OutOfBoundsException
     */
    private function deleteFieldAce($property, $index, $field)
    {
        $aces =& $this->$property;
        if (!isset($aces[$field][$index])) {
            throw new \OutOfBoundsException(sprintf('The index "%d" does not exist.', $index));
        }

        $oldValue = $this->$property;
        unset($aces[$field][$index]);
        $aces[$field] = array_values($aces[$field]);
        $this->onPropertyChanged($property, $oldValue, $this->$property);

        for ($i=$index,$c=count($aces[$field]); $i<$c; $i++) {
            $this->onEntryPropertyChanged($aces[$field][$i], 'aceOrder', $i+1, $i);
        }
    }

    /**
     * Inserts an ACE
     *
     * @param string                    $property
     * @param integer                   $index
     * @param integer                   $mask
     * @param SecurityIdentityInterface $sid
     * @param Boolean                   $granting
     * @param string                    $strategy
     * @throws \OutOfBoundsException
     * @throws \InvalidArgumentException
     */
    private function insertAce($property, $index, $mask, SecurityIdentityInterface $sid, $granting, $strategy = null)
    {
        if ($index < 0 || $index > count($this->$property)) {
            throw new \OutOfBoundsException(sprintf('The index must be in the interval [0, %d].', count($this->$property)));
        }

        if (!is_int($mask)) {
            throw new \InvalidArgumentException('$mask must be an integer.');
        }

        if (null === $strategy) {
            if (true === $granting) {
                $strategy = PermissionGrantingStrategy::ALL;
            } else {
                $strategy = PermissionGrantingStrategy::ANY;
            }
        }

        $aces =& $this->$property;
        $oldValue = $this->$property;
        if (isset($aces[$index])) {
            $this->$property = array_merge(
                array_slice($this->$property, 0, $index),
                array(true),
                array_slice($this->$property, $index)
            );

            for ($i=$index,$c=count($this->$property)-1; $i<$c; $i++) {
                $this->onEntryPropertyChanged($aces[$i+1], 'aceOrder', $i, $i+1);
            }
        }

        $aces[$index] = new Entry(null, $this, $sid, $strategy, $mask, $granting, false, false);
        $this->onPropertyChanged($property, $oldValue, $this->$property);
    }

    /**
     * Inserts a field-based ACE
     *
     * @param string                    $property
     * @param integer                   $index
     * @param string                    $field
     * @param integer                   $mask
     * @param SecurityIdentityInterface $sid
     * @param Boolean                   $granting
     * @param string                    $strategy
     * @throws \InvalidArgumentException
     * @throws \OutOfBoundsException
     */
    private function insertFieldAce($property, $index, $field, $mask, SecurityIdentityInterface $sid, $granting, $strategy = null)
    {
        if (0 === strlen($field)) {
            throw new \InvalidArgumentException('$field cannot be empty.');
        }

        if (!is_int($mask)) {
            throw new \InvalidArgumentException('$mask must be an integer.');
        }

        if (null === $strategy) {
            if (true === $granting) {
                $strategy = PermissionGrantingStrategy::ALL;
            } else {
                $strategy = PermissionGrantingStrategy::ANY;
            }
        }

        $aces =& $this->$property;
        if (!isset($aces[$field])) {
            $aces[$field] = array();
        }

        if ($index < 0 || $index > count($aces[$field])) {
            throw new \OutOfBoundsException(sprintf('The index must be in the interval [0, %d].', count($this->$property)));
        }

        $oldValue = $aces;
        if (isset($aces[$field][$index])) {
            $aces[$field] = array_merge(
                array_slice($aces[$field], 0, $index),
                array(true),
                array_slice($aces[$field], $index)
            );

            for ($i=$index,$c=count($aces[$field])-1; $i<$c; $i++) {
                $this->onEntryPropertyChanged($aces[$field][$i+1], 'aceOrder', $i, $i+1);
            }
        }

        $aces[$field][$index] = new FieldEntry(null, $this, $field, $sid, $strategy, $mask, $granting, false, false);
        $this->onPropertyChanged($property, $oldValue, $this->$property);
    }

    /**
     * Updates an ACE
     *
     * @param string  $property
     * @param integer $index
     * @param integer $mask
     * @param string  $strategy
     * @throws \OutOfBoundsException
     */
    private function updateAce($property, $index, $mask, $strategy = null)
    {
        $aces =& $this->$property;
        if (!isset($aces[$index])) {
            throw new \OutOfBoundsException(sprintf('The index "%d" does not exist.', $index));
        }

        $ace = $aces[$index];
        if ($mask !== $oldMask = $ace->getMask()) {
            $this->onEntryPropertyChanged($ace, 'mask', $oldMask, $mask);
            $ace->setMask($mask);
        }
        if (null !== $strategy && $strategy !== $oldStrategy = $ace->getStrategy()) {
            $this->onEntryPropertyChanged($ace, 'strategy', $oldStrategy, $strategy);
            $ace->setStrategy($strategy);
        }
    }

    /**
     * Updates auditing for an ACE
     *
     * @param array   &$aces
     * @param integer $index
     * @param Boolean $auditSuccess
     * @param Boolean $auditFailure
     * @throws \OutOfBoundsException
     */
    private function updateAuditing(array &$aces, $index, $auditSuccess, $auditFailure)
    {
        if (!isset($aces[$index])) {
            throw new \OutOfBoundsException(sprintf('The index "%d" does not exist.', $index));
        }

        if ($auditSuccess !== $aces[$index]->isAuditSuccess()) {
            $this->onEntryPropertyChanged($aces[$index], 'auditSuccess', !$auditSuccess, $auditSuccess);
            $aces[$index]->setAuditSuccess($auditSuccess);
        }

        if ($auditFailure !== $aces[$index]->isAuditFailure()) {
            $this->onEntryPropertyChanged($aces[$index], 'auditFailure', !$auditFailure, $auditFailure);
            $aces[$index]->setAuditFailure($auditFailure);
        }
    }

    /**
     * Updates a field-based ACE
     *
     * @param string  $property
     * @param integer $index
     * @param string  $field
     * @param integer $mask
     * @param string  $strategy
     * @throws \InvalidArgumentException
     * @throws \OutOfBoundsException
     */
    private function updateFieldAce($property, $index, $field, $mask, $strategy = null)
    {
        if (0 === strlen($field)) {
            throw new \InvalidArgumentException('$field cannot be empty.');
        }

        $aces =& $this->$property;
        if (!isset($aces[$field][$index])) {
            throw new \OutOfBoundsException(sprintf('The index "%d" does not exist.', $index));
        }

        $ace = $aces[$field][$index];
        if ($mask !== $oldMask = $ace->getMask()) {
            $this->onEntryPropertyChanged($ace, 'mask', $oldMask, $mask);
            $ace->setMask($mask);
        }
        if (null !== $strategy && $strategy !== $oldStrategy = $ace->getStrategy()) {
            $this->onEntryPropertyChanged($ace, 'strategy', $oldStrategy, $strategy);
            $ace->setStrategy($strategy);
        }
    }

    /**
     * Called when a property of the ACL changes
     *
     * @param string $name
     * @param mixed  $oldValue
     * @param mixed  $newValue
     */
    private function onPropertyChanged($name, $oldValue, $newValue)
    {
        foreach ($this->listeners as $listener) {
            $listener->propertyChanged($this, $name, $oldValue, $newValue);
        }
    }

    /**
     * Called when a property of an ACE associated with this ACL changes
     *
     * @param EntryInterface $entry
     * @param string         $name
     * @param mixed          $oldValue
     * @param mixed          $newValue
     */
    private function onEntryPropertyChanged(EntryInterface $entry, $name, $oldValue, $newValue)
    {
        foreach ($this->listeners as $listener) {
            $listener->propertyChanged($entry, $name, $oldValue, $newValue);
        }
    }
}
PK��Z����KSymfony/Component/Security/Acl/Domain/SecurityIdentityRetrievalStrategy.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Domain;

use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Acl\Model\SecurityIdentityRetrievalStrategyInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver;
use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
use Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter;

/**
 * Strategy for retrieving security identities
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class SecurityIdentityRetrievalStrategy implements SecurityIdentityRetrievalStrategyInterface
{
    private $roleHierarchy;
    private $authenticationTrustResolver;

    /**
     * Constructor
     *
     * @param RoleHierarchyInterface      $roleHierarchy
     * @param AuthenticationTrustResolver $authenticationTrustResolver
     */
    public function __construct(RoleHierarchyInterface $roleHierarchy, AuthenticationTrustResolver $authenticationTrustResolver)
    {
        $this->roleHierarchy = $roleHierarchy;
        $this->authenticationTrustResolver = $authenticationTrustResolver;
    }

    /**
     * {@inheritDoc}
     */
    public function getSecurityIdentities(TokenInterface $token)
    {
        $sids = array();

        // add user security identity
        if (!$token instanceof AnonymousToken) {
            try {
                $sids[] = UserSecurityIdentity::fromToken($token);
            } catch (\InvalidArgumentException $invalid) {
                // ignore, user has no user security identity
            }
        }

        // add all reachable roles
        foreach ($this->roleHierarchy->getReachableRoles($token->getRoles()) as $role) {
            $sids[] = new RoleSecurityIdentity($role);
        }

        // add built-in special roles
        if ($this->authenticationTrustResolver->isFullFledged($token)) {
            $sids[] = new RoleSecurityIdentity(AuthenticatedVoter::IS_AUTHENTICATED_FULLY);
            $sids[] = new RoleSecurityIdentity(AuthenticatedVoter::IS_AUTHENTICATED_REMEMBERED);
            $sids[] = new RoleSecurityIdentity(AuthenticatedVoter::IS_AUTHENTICATED_ANONYMOUSLY);
        } elseif ($this->authenticationTrustResolver->isRememberMe($token)) {
            $sids[] = new RoleSecurityIdentity(AuthenticatedVoter::IS_AUTHENTICATED_REMEMBERED);
            $sids[] = new RoleSecurityIdentity(AuthenticatedVoter::IS_AUTHENTICATED_ANONYMOUSLY);
        } elseif ($this->authenticationTrustResolver->isAnonymous($token)) {
            $sids[] = new RoleSecurityIdentity(AuthenticatedVoter::IS_AUTHENTICATED_ANONYMOUSLY);
        }

        return $sids;
    }
}
PK��Z�X�
/	/	<Symfony/Component/Security/Acl/Domain/AclCollectionCache.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Domain;

use Symfony\Component\Security\Acl\Model\AclProviderInterface;
use Symfony\Component\Security\Acl\Model\ObjectIdentityRetrievalStrategyInterface;
use Symfony\Component\Security\Acl\Model\SecurityIdentityRetrievalStrategyInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;

/**
 * This service caches ACLs for an entire collection of objects.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class AclCollectionCache
{
    private $aclProvider;
    private $objectIdentityRetrievalStrategy;
    private $securityIdentityRetrievalStrategy;

    /**
     * Constructor.
     *
     * @param AclProviderInterface                       $aclProvider
     * @param ObjectIdentityRetrievalStrategyInterface   $oidRetrievalStrategy
     * @param SecurityIdentityRetrievalStrategyInterface $sidRetrievalStrategy
     */
    public function __construct(AclProviderInterface $aclProvider, ObjectIdentityRetrievalStrategyInterface $oidRetrievalStrategy, SecurityIdentityRetrievalStrategyInterface $sidRetrievalStrategy)
    {
        $this->aclProvider = $aclProvider;
        $this->objectIdentityRetrievalStrategy = $oidRetrievalStrategy;
        $this->securityIdentityRetrievalStrategy = $sidRetrievalStrategy;
    }

    /**
     * Batch loads ACLs for an entire collection; thus, it reduces the number
     * of required queries considerably.
     *
     * @param mixed            $collection anything that can be passed to foreach()
     * @param TokenInterface[] $tokens     an array of TokenInterface implementations
     */
    public function cache($collection, array $tokens = array())
    {
        $sids = array();
        foreach ($tokens as $token) {
            $sids = array_merge($sids, $this->securityIdentityRetrievalStrategy->getSecurityIdentities($token));
        }

        $oids = array();
        foreach ($collection as $domainObject) {
            $oids[] = $this->objectIdentityRetrievalStrategy->getObjectIdentity($domainObject);
        }

        $this->aclProvider->findAcls($oids, $sids);
    }
}
PK��Z5D�[/Symfony/Component/Security/Acl/Domain/Entry.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Domain;

use Symfony\Component\Security\Acl\Model\AclInterface;
use Symfony\Component\Security\Acl\Model\AuditableEntryInterface;
use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface;

/**
 * Auditable ACE implementation
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class Entry implements AuditableEntryInterface
{
    private $acl;
    private $mask;
    private $id;
    private $securityIdentity;
    private $strategy;
    private $auditFailure;
    private $auditSuccess;
    private $granting;

    /**
     * Constructor
     *
     * @param integer                   $id
     * @param AclInterface              $acl
     * @param SecurityIdentityInterface $sid
     * @param string                    $strategy
     * @param integer                   $mask
     * @param Boolean                   $granting
     * @param Boolean                   $auditFailure
     * @param Boolean                   $auditSuccess
     */
    public function __construct($id, AclInterface $acl, SecurityIdentityInterface $sid, $strategy, $mask, $granting, $auditFailure, $auditSuccess)
    {
        $this->id = $id;
        $this->acl = $acl;
        $this->securityIdentity = $sid;
        $this->strategy = $strategy;
        $this->mask = $mask;
        $this->granting = $granting;
        $this->auditFailure = $auditFailure;
        $this->auditSuccess = $auditSuccess;
    }

    /**
     * {@inheritDoc}
     */
    public function getAcl()
    {
        return $this->acl;
    }

    /**
     * {@inheritDoc}
     */
    public function getMask()
    {
        return $this->mask;
    }

    /**
     * {@inheritDoc}
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * {@inheritDoc}
     */
    public function getSecurityIdentity()
    {
        return $this->securityIdentity;
    }

    /**
     * {@inheritDoc}
     */
    public function getStrategy()
    {
        return $this->strategy;
    }

    /**
     * {@inheritDoc}
     */
    public function isAuditFailure()
    {
        return $this->auditFailure;
    }

    /**
     * {@inheritDoc}
     */
    public function isAuditSuccess()
    {
        return $this->auditSuccess;
    }

    /**
     * {@inheritDoc}
     */
    public function isGranting()
    {
        return $this->granting;
    }

    /**
     * Turns on/off auditing on permissions denials.
     *
     * Do never call this method directly. Use the respective methods on the
     * AclInterface instead.
     *
     * @param Boolean $boolean
     */
    public function setAuditFailure($boolean)
    {
        $this->auditFailure = $boolean;
    }

    /**
     * Turns on/off auditing on permission grants.
     *
     * Do never call this method directly. Use the respective methods on the
     * AclInterface instead.
     *
     * @param Boolean $boolean
     */
    public function setAuditSuccess($boolean)
    {
        $this->auditSuccess = $boolean;
    }

    /**
     * Sets the permission mask
     *
     * Do never call this method directly. Use the respective methods on the
     * AclInterface instead.
     *
     * @param integer $mask
     */
    public function setMask($mask)
    {
        $this->mask = $mask;
    }

    /**
     * Sets the mask comparison strategy
     *
     * Do never call this method directly. Use the respective methods on the
     * AclInterface instead.
     *
     * @param string $strategy
     */
    public function setStrategy($strategy)
    {
        $this->strategy = $strategy;
    }

    /**
     * Implementation of \Serializable
     *
     * @return string
     */
    public function serialize()
    {
        return serialize(array(
            $this->mask,
            $this->id,
            $this->securityIdentity,
            $this->strategy,
            $this->auditFailure,
            $this->auditSuccess,
            $this->granting,
        ));
    }

    /**
     * Implementation of \Serializable
     *
     * @param string $serialized
     */
    public function unserialize($serialized)
    {
        list($this->mask,
             $this->id,
             $this->securityIdentity,
             $this->strategy,
             $this->auditFailure,
             $this->auditSuccess,
             $this->granting
        ) = unserialize($serialized);
    }
}
PK��Z�pU���4Symfony/Component/Security/Acl/Domain/FieldEntry.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Domain;

use Symfony\Component\Security\Acl\Model\AclInterface;
use Symfony\Component\Security\Acl\Model\FieldEntryInterface;
use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface;

/**
 * Field-aware ACE implementation which is auditable
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class FieldEntry extends Entry implements FieldEntryInterface
{
    private $field;

    /**
     * Constructor
     *
     * @param integer                   $id
     * @param AclInterface              $acl
     * @param string                    $field
     * @param SecurityIdentityInterface $sid
     * @param string                    $strategy
     * @param integer                   $mask
     * @param Boolean                   $granting
     * @param Boolean                   $auditFailure
     * @param Boolean                   $auditSuccess
     */
    public function __construct($id, AclInterface $acl, $field, SecurityIdentityInterface $sid, $strategy, $mask, $granting, $auditFailure, $auditSuccess)
    {
        parent::__construct($id, $acl, $sid, $strategy, $mask, $granting, $auditFailure, $auditSuccess);

        $this->field = $field;
    }

    /**
     * {@inheritDoc}
     */
    public function getField()
    {
        return $this->field;
    }

    /**
     * {@inheritDoc}
     */
    public function serialize()
    {
        return serialize(array(
            $this->field,
            parent::serialize(),
        ));
    }

    /**
     * {@inheritDoc}
     */
    public function unserialize($serialized)
    {
        list($this->field, $parentStr) = unserialize($serialized);
        parent::unserialize($parentStr);
    }
}
PK��Z^@�.YY8Symfony/Component/Security/Acl/Domain/ObjectIdentity.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Domain;

use Symfony\Component\Security\Core\Util\ClassUtils;
use Symfony\Component\Security\Acl\Exception\InvalidDomainObjectException;
use Symfony\Component\Security\Acl\Model\DomainObjectInterface;
use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface;

/**
 * ObjectIdentity implementation
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
final class ObjectIdentity implements ObjectIdentityInterface
{
    private $identifier;
    private $type;

    /**
     * Constructor.
     *
     * @param string $identifier
     * @param string $type
     *
     * @throws \InvalidArgumentException
     */
    public function __construct($identifier, $type)
    {
        if (empty($identifier)) {
            throw new \InvalidArgumentException('$identifier cannot be empty.');
        }
        if (empty($type)) {
            throw new \InvalidArgumentException('$type cannot be empty.');
        }

        $this->identifier = $identifier;
        $this->type = $type;
    }

    /**
     * Constructs an ObjectIdentity for the given domain object
     *
     * @param object $domainObject
     * @throws InvalidDomainObjectException
     * @return ObjectIdentity
     */
    public static function fromDomainObject($domainObject)
    {
        if (!is_object($domainObject)) {
            throw new InvalidDomainObjectException('$domainObject must be an object.');
        }

        try {
            if ($domainObject instanceof DomainObjectInterface) {
                return new self($domainObject->getObjectIdentifier(), ClassUtils::getRealClass($domainObject));
            } elseif (method_exists($domainObject, 'getId')) {
                return new self($domainObject->getId(), ClassUtils::getRealClass($domainObject));
            }
        } catch (\InvalidArgumentException $invalid) {
            throw new InvalidDomainObjectException($invalid->getMessage(), 0, $invalid);
        }

        throw new InvalidDomainObjectException('$domainObject must either implement the DomainObjectInterface, or have a method named "getId".');
    }

    /**
     * {@inheritDoc}
     */
    public function getIdentifier()
    {
        return $this->identifier;
    }

    /**
     * {@inheritDoc}
     */
    public function getType()
    {
        return $this->type;
    }

    /**
     * {@inheritDoc}
     */
    public function equals(ObjectIdentityInterface $identity)
    {
        // comparing the identifier with === might lead to problems, so we
        // waive this restriction
        return $this->identifier == $identity->getIdentifier()
               && $this->type === $identity->getType();
    }

    /**
     * Returns a textual representation of this object identity
     *
     * @return string
     */
    public function __toString()
    {
        return sprintf('ObjectIdentity(%s, %s)', $this->identifier, $this->type);
    }
}
PK��Z0F���ISymfony/Component/Security/Acl/Domain/ObjectIdentityRetrievalStrategy.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Domain;

use Symfony\Component\Security\Acl\Exception\InvalidDomainObjectException;
use Symfony\Component\Security\Acl\Model\ObjectIdentityRetrievalStrategyInterface;

/**
 * Strategy to be used for retrieving object identities from domain objects
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ObjectIdentityRetrievalStrategy implements ObjectIdentityRetrievalStrategyInterface
{
    /**
     * {@inheritDoc}
     */
    public function getObjectIdentity($domainObject)
    {
        try {
            return ObjectIdentity::fromDomainObject($domainObject);
        } catch (InvalidDomainObjectException $failed) {
            return null;
        }
    }
}
PK��ZtA)�==>Symfony/Component/Security/Acl/Domain/RoleSecurityIdentity.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Domain;

use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface;
use Symfony\Component\Security\Core\Role\Role;

/**
 * A SecurityIdentity implementation for roles
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
final class RoleSecurityIdentity implements SecurityIdentityInterface
{
    private $role;

    /**
     * Constructor
     *
     * @param mixed $role a Role instance, or its string representation
     */
    public function __construct($role)
    {
        if ($role instanceof Role) {
            $role = $role->getRole();
        }

        $this->role = $role;
    }

    /**
     * Returns the role name
     *
     * @return string
     */
    public function getRole()
    {
        return $this->role;
    }

    /**
     * {@inheritDoc}
     */
    public function equals(SecurityIdentityInterface $sid)
    {
        if (!$sid instanceof RoleSecurityIdentity) {
            return false;
        }

        return $this->role === $sid->getRole();
    }

    /**
     * Returns a textual representation of this security identity.
     *
     * This is solely used for debugging purposes, not to make an equality decision.
     *
     * @return string
     */
    public function __toString()
    {
        return sprintf('RoleSecurityIdentity(%s)', $this->role);
    }
}
PK��Z�#��~~<Symfony/Component/Security/Acl/Resources/bin/generateSql.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

require_once __DIR__.'/../../../../ClassLoader/ClassLoader.php';

use Symfony\Component\ClassLoader\ClassLoader;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Security\Acl\Dbal\Schema;

$loader = new ClassLoader();
$loader->addPrefixes(array(
    'Symfony'                    => __DIR__.'/../../../../../..',
    'Doctrine\\Common'           => __DIR__.'/../../../../../../../vendor/doctrine-common/lib',
    'Doctrine\\DBAL\\Migrations' => __DIR__.'/../../../../../../../vendor/doctrine-migrations/lib',
    'Doctrine\\DBAL'             => __DIR__.'/../../../../../../../vendor/doctrine-dbal/lib',
    'Doctrine'                   => __DIR__.'/../../../../../../../vendor/doctrine/lib',
));
$loader->register();

$schema = new Schema(array(
    'class_table_name'         => 'acl_classes',
    'entry_table_name'         => 'acl_entries',
    'oid_table_name'           => 'acl_object_identities',
    'oid_ancestors_table_name' => 'acl_object_identity_ancestors',
    'sid_table_name'           => 'acl_security_identities',
));

$reflection = new ReflectionClass('Doctrine\\DBAL\\Platforms\\AbstractPlatform');
$finder = new Finder();
$finder->name('*Platform.php')->in(dirname($reflection->getFileName()));
foreach ($finder as $file) {
    require_once $file->getPathName();
    $className = 'Doctrine\\DBAL\\Platforms\\'.$file->getBasename('.php');

    $reflection = new ReflectionClass($className);
    if ($reflection->isAbstract()) {
        continue;
    }

    $platform = $reflection->newInstance();
    $targetFile = sprintf(__DIR__.'/../schema/%s.sql', $platform->name);
    file_put_contents($targetFile, implode("\n\n", $schema->toSql($platform)));
}
PK��Zj~	cFF7Symfony/Component/Security/Acl/Resources/schema/db2.sqlnu�[���CREATE TABLE acl_classes (id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL, class_type VARCHAR(200) NOT NULL, PRIMARY KEY(id))

CREATE UNIQUE INDEX UNIQ_69DD750638A36066 ON acl_classes (class_type)

CREATE TABLE acl_security_identities (id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL, identifier VARCHAR(200) NOT NULL, username SMALLINT NOT NULL, PRIMARY KEY(id))

CREATE UNIQUE INDEX UNIQ_8835EE78772E836AF85E0677 ON acl_security_identities (identifier, username)

CREATE TABLE acl_object_identities (id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL, parent_object_identity_id INTEGER DEFAULT NULL, class_id INTEGER NOT NULL, object_identifier VARCHAR(100) NOT NULL, entries_inheriting SMALLINT NOT NULL, PRIMARY KEY(id))

CREATE UNIQUE INDEX UNIQ_9407E5494B12AD6EA000B10 ON acl_object_identities (object_identifier, class_id)

CREATE INDEX IDX_9407E54977FA751A ON acl_object_identities (parent_object_identity_id)

CREATE TABLE acl_object_identity_ancestors (object_identity_id INTEGER NOT NULL, ancestor_id INTEGER NOT NULL, PRIMARY KEY(object_identity_id, ancestor_id))

CREATE INDEX IDX_825DE2993D9AB4A6 ON acl_object_identity_ancestors (object_identity_id)

CREATE INDEX IDX_825DE299C671CEA1 ON acl_object_identity_ancestors (ancestor_id)

CREATE TABLE acl_entries (id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL, class_id INTEGER NOT NULL, object_identity_id INTEGER DEFAULT NULL, security_identity_id INTEGER NOT NULL, field_name VARCHAR(50) DEFAULT NULL, ace_order SMALLINT NOT NULL, mask INTEGER NOT NULL, granting SMALLINT NOT NULL, granting_strategy VARCHAR(30) NOT NULL, audit_success SMALLINT NOT NULL, audit_failure SMALLINT NOT NULL, PRIMARY KEY(id))

CREATE UNIQUE INDEX UNIQ_46C8B806EA000B103D9AB4A64DEF17BCE4289BF4 ON acl_entries (class_id, object_identity_id, field_name, ace_order)

CREATE INDEX IDX_46C8B806EA000B103D9AB4A6DF9183C9 ON acl_entries (class_id, object_identity_id, security_identity_id)

CREATE INDEX IDX_46C8B806EA000B10 ON acl_entries (class_id)

CREATE INDEX IDX_46C8B8063D9AB4A6 ON acl_entries (object_identity_id)

CREATE INDEX IDX_46C8B806DF9183C9 ON acl_entries (security_identity_id)

ALTER TABLE acl_object_identities ADD CONSTRAINT FK_9407E54977FA751A FOREIGN KEY (parent_object_identity_id) REFERENCES acl_object_identities (id)

ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE2993D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE

ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE299C671CEA1 FOREIGN KEY (ancestor_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE

ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806EA000B10 FOREIGN KEY (class_id) REFERENCES acl_classes (id) ON UPDATE CASCADE ON DELETE CASCADE

ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B8063D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE

ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806DF9183C9 FOREIGN KEY (security_identity_id) REFERENCES acl_security_identities (id) ON UPDATE CASCADE ON DELETE CASCADEPK��ZT��skk>Symfony/Component/Security/Acl/Resources/schema/postgresql.sqlnu�[���CREATE TABLE acl_classes (id SERIAL NOT NULL, class_type VARCHAR(200) NOT NULL, PRIMARY KEY(id))

CREATE UNIQUE INDEX UNIQ_69DD750638A36066 ON acl_classes (class_type)

CREATE TABLE acl_security_identities (id SERIAL NOT NULL, identifier VARCHAR(200) NOT NULL, username BOOLEAN NOT NULL, PRIMARY KEY(id))

CREATE UNIQUE INDEX UNIQ_8835EE78772E836AF85E0677 ON acl_security_identities (identifier, username)

CREATE TABLE acl_object_identities (id SERIAL NOT NULL, parent_object_identity_id INT DEFAULT NULL, class_id INT NOT NULL, object_identifier VARCHAR(100) NOT NULL, entries_inheriting BOOLEAN NOT NULL, PRIMARY KEY(id))

CREATE UNIQUE INDEX UNIQ_9407E5494B12AD6EA000B10 ON acl_object_identities (object_identifier, class_id)

CREATE INDEX IDX_9407E54977FA751A ON acl_object_identities (parent_object_identity_id)

CREATE TABLE acl_object_identity_ancestors (object_identity_id INT NOT NULL, ancestor_id INT NOT NULL, PRIMARY KEY(object_identity_id, ancestor_id))

CREATE INDEX IDX_825DE2993D9AB4A6 ON acl_object_identity_ancestors (object_identity_id)

CREATE INDEX IDX_825DE299C671CEA1 ON acl_object_identity_ancestors (ancestor_id)

CREATE TABLE acl_entries (id SERIAL NOT NULL, class_id INT NOT NULL, object_identity_id INT DEFAULT NULL, security_identity_id INT NOT NULL, field_name VARCHAR(50) DEFAULT NULL, ace_order SMALLINT NOT NULL, mask INT NOT NULL, granting BOOLEAN NOT NULL, granting_strategy VARCHAR(30) NOT NULL, audit_success BOOLEAN NOT NULL, audit_failure BOOLEAN NOT NULL, PRIMARY KEY(id))

CREATE UNIQUE INDEX UNIQ_46C8B806EA000B103D9AB4A64DEF17BCE4289BF4 ON acl_entries (class_id, object_identity_id, field_name, ace_order)

CREATE INDEX IDX_46C8B806EA000B103D9AB4A6DF9183C9 ON acl_entries (class_id, object_identity_id, security_identity_id)

CREATE INDEX IDX_46C8B806EA000B10 ON acl_entries (class_id)

CREATE INDEX IDX_46C8B8063D9AB4A6 ON acl_entries (object_identity_id)

CREATE INDEX IDX_46C8B806DF9183C9 ON acl_entries (security_identity_id)

ALTER TABLE acl_object_identities ADD CONSTRAINT FK_9407E54977FA751A FOREIGN KEY (parent_object_identity_id) REFERENCES acl_object_identities (id) NOT DEFERRABLE INITIALLY IMMEDIATE

ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE2993D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE

ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE299C671CEA1 FOREIGN KEY (ancestor_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE

ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806EA000B10 FOREIGN KEY (class_id) REFERENCES acl_classes (id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE

ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B8063D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE

ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806DF9183C9 FOREIGN KEY (security_identity_id) REFERENCES acl_security_identities (id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATEPK��ZJx�.

9Symfony/Component/Security/Acl/Resources/schema/mssql.sqlnu�[���CREATE TABLE acl_classes (id INT UNSIGNED IDENTITY NOT NULL, class_type NVARCHAR(200) NOT NULL, PRIMARY KEY (id))

CREATE UNIQUE INDEX UNIQ_69DD750638A36066 ON acl_classes (class_type) WHERE class_type IS NOT NULL

CREATE TABLE acl_security_identities (id INT UNSIGNED IDENTITY NOT NULL, identifier NVARCHAR(200) NOT NULL, username BIT NOT NULL, PRIMARY KEY (id))

CREATE UNIQUE INDEX UNIQ_8835EE78772E836AF85E0677 ON acl_security_identities (identifier, username) WHERE identifier IS NOT NULL AND username IS NOT NULL

CREATE TABLE acl_object_identities (id INT UNSIGNED IDENTITY NOT NULL, parent_object_identity_id INT UNSIGNED DEFAULT NULL, class_id INT UNSIGNED NOT NULL, object_identifier NVARCHAR(100) NOT NULL, entries_inheriting BIT NOT NULL, PRIMARY KEY (id))

CREATE UNIQUE INDEX UNIQ_9407E5494B12AD6EA000B10 ON acl_object_identities (object_identifier, class_id) WHERE object_identifier IS NOT NULL AND class_id IS NOT NULL

CREATE INDEX IDX_9407E54977FA751A ON acl_object_identities (parent_object_identity_id)

CREATE TABLE acl_object_identity_ancestors (object_identity_id INT UNSIGNED NOT NULL, ancestor_id INT UNSIGNED NOT NULL, PRIMARY KEY (object_identity_id, ancestor_id))

CREATE INDEX IDX_825DE2993D9AB4A6 ON acl_object_identity_ancestors (object_identity_id)

CREATE INDEX IDX_825DE299C671CEA1 ON acl_object_identity_ancestors (ancestor_id)

CREATE TABLE acl_entries (id INT UNSIGNED IDENTITY NOT NULL, class_id INT UNSIGNED NOT NULL, object_identity_id INT UNSIGNED DEFAULT NULL, security_identity_id INT UNSIGNED NOT NULL, field_name NVARCHAR(50) DEFAULT NULL, ace_order SMALLINT UNSIGNED NOT NULL, mask INT NOT NULL, granting BIT NOT NULL, granting_strategy NVARCHAR(30) NOT NULL, audit_success BIT NOT NULL, audit_failure BIT NOT NULL, PRIMARY KEY (id))

CREATE UNIQUE INDEX UNIQ_46C8B806EA000B103D9AB4A64DEF17BCE4289BF4 ON acl_entries (class_id, object_identity_id, field_name, ace_order) WHERE class_id IS NOT NULL AND object_identity_id IS NOT NULL AND field_name IS NOT NULL AND ace_order IS NOT NULL

CREATE INDEX IDX_46C8B806EA000B103D9AB4A6DF9183C9 ON acl_entries (class_id, object_identity_id, security_identity_id)

CREATE INDEX IDX_46C8B806EA000B10 ON acl_entries (class_id)

CREATE INDEX IDX_46C8B8063D9AB4A6 ON acl_entries (object_identity_id)

CREATE INDEX IDX_46C8B806DF9183C9 ON acl_entries (security_identity_id)

ALTER TABLE acl_object_identities ADD CONSTRAINT FK_9407E54977FA751A FOREIGN KEY (parent_object_identity_id) REFERENCES acl_object_identities (id)

ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE2993D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE

ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE299C671CEA1 FOREIGN KEY (ancestor_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE

ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806EA000B10 FOREIGN KEY (class_id) REFERENCES acl_classes (id) ON UPDATE CASCADE ON DELETE CASCADE

ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B8063D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE

ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806DF9183C9 FOREIGN KEY (security_identity_id) REFERENCES acl_security_identities (id) ON UPDATE CASCADE ON DELETE CASCADEPK��ZfZ��^^9Symfony/Component/Security/Acl/Resources/schema/mysql.sqlnu�[���CREATE TABLE acl_classes (id INT UNSIGNED AUTO_INCREMENT NOT NULL, class_type VARCHAR(200) NOT NULL, UNIQUE INDEX UNIQ_69DD750638A36066 (class_type), PRIMARY KEY(id)) ENGINE = InnoDB

CREATE TABLE acl_security_identities (id INT UNSIGNED AUTO_INCREMENT NOT NULL, identifier VARCHAR(200) NOT NULL, username TINYINT(1) NOT NULL, UNIQUE INDEX UNIQ_8835EE78772E836AF85E0677 (identifier, username), PRIMARY KEY(id)) ENGINE = InnoDB

CREATE TABLE acl_object_identities (id INT UNSIGNED AUTO_INCREMENT NOT NULL, parent_object_identity_id INT UNSIGNED DEFAULT NULL, class_id INT UNSIGNED NOT NULL, object_identifier VARCHAR(100) NOT NULL, entries_inheriting TINYINT(1) NOT NULL, UNIQUE INDEX UNIQ_9407E5494B12AD6EA000B10 (object_identifier, class_id), INDEX IDX_9407E54977FA751A (parent_object_identity_id), PRIMARY KEY(id)) ENGINE = InnoDB

CREATE TABLE acl_object_identity_ancestors (object_identity_id INT UNSIGNED NOT NULL, ancestor_id INT UNSIGNED NOT NULL, INDEX IDX_825DE2993D9AB4A6 (object_identity_id), INDEX IDX_825DE299C671CEA1 (ancestor_id), PRIMARY KEY(object_identity_id, ancestor_id)) ENGINE = InnoDB

CREATE TABLE acl_entries (id INT UNSIGNED AUTO_INCREMENT NOT NULL, class_id INT UNSIGNED NOT NULL, object_identity_id INT UNSIGNED DEFAULT NULL, security_identity_id INT UNSIGNED NOT NULL, field_name VARCHAR(50) DEFAULT NULL, ace_order SMALLINT UNSIGNED NOT NULL, mask INT NOT NULL, granting TINYINT(1) NOT NULL, granting_strategy VARCHAR(30) NOT NULL, audit_success TINYINT(1) NOT NULL, audit_failure TINYINT(1) NOT NULL, UNIQUE INDEX UNIQ_46C8B806EA000B103D9AB4A64DEF17BCE4289BF4 (class_id, object_identity_id, field_name, ace_order), INDEX IDX_46C8B806EA000B103D9AB4A6DF9183C9 (class_id, object_identity_id, security_identity_id), INDEX IDX_46C8B806EA000B10 (class_id), INDEX IDX_46C8B8063D9AB4A6 (object_identity_id), INDEX IDX_46C8B806DF9183C9 (security_identity_id), PRIMARY KEY(id)) ENGINE = InnoDB

ALTER TABLE acl_object_identities ADD CONSTRAINT FK_9407E54977FA751A FOREIGN KEY (parent_object_identity_id) REFERENCES acl_object_identities (id)

ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE2993D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE

ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE299C671CEA1 FOREIGN KEY (ancestor_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE

ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806EA000B10 FOREIGN KEY (class_id) REFERENCES acl_classes (id) ON UPDATE CASCADE ON DELETE CASCADE

ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B8063D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE

ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806DF9183C9 FOREIGN KEY (security_identity_id) REFERENCES acl_security_identities (id) ON UPDATE CASCADE ON DELETE CASCADEPK��Z��c�
�
;Symfony/Component/Security/Acl/Resources/schema/drizzle.sqlnu�[���CREATE TABLE acl_classes (id INT AUTO_INCREMENT NOT NULL, class_type VARCHAR(200) NOT NULL, PRIMARY KEY(id), UNIQUE INDEX UNIQ_69DD750638A36066 (class_type))

CREATE TABLE acl_security_identities (id INT AUTO_INCREMENT NOT NULL, identifier VARCHAR(200) NOT NULL, username BOOLEAN NOT NULL, PRIMARY KEY(id), UNIQUE INDEX UNIQ_8835EE78772E836AF85E0677 (identifier, username))

CREATE TABLE acl_object_identities (id INT AUTO_INCREMENT NOT NULL, parent_object_identity_id INT DEFAULT NULL, class_id INT NOT NULL, object_identifier VARCHAR(100) NOT NULL, entries_inheriting BOOLEAN NOT NULL, PRIMARY KEY(id), UNIQUE INDEX UNIQ_9407E5494B12AD6EA000B10 (object_identifier, class_id), INDEX IDX_9407E54977FA751A (parent_object_identity_id))

CREATE TABLE acl_object_identity_ancestors (object_identity_id INT NOT NULL, ancestor_id INT NOT NULL, PRIMARY KEY(object_identity_id, ancestor_id), INDEX IDX_825DE2993D9AB4A6 (object_identity_id), INDEX IDX_825DE299C671CEA1 (ancestor_id))

CREATE TABLE acl_entries (id INT AUTO_INCREMENT NOT NULL, class_id INT NOT NULL, object_identity_id INT DEFAULT NULL, security_identity_id INT NOT NULL, field_name VARCHAR(50) DEFAULT NULL, ace_order INT NOT NULL, mask INT NOT NULL, granting BOOLEAN NOT NULL, granting_strategy VARCHAR(30) NOT NULL, audit_success BOOLEAN NOT NULL, audit_failure BOOLEAN NOT NULL, PRIMARY KEY(id), UNIQUE INDEX UNIQ_46C8B806EA000B103D9AB4A64DEF17BCE4289BF4 (class_id, object_identity_id, field_name, ace_order), INDEX IDX_46C8B806EA000B103D9AB4A6DF9183C9 (class_id, object_identity_id, security_identity_id), INDEX IDX_46C8B806EA000B10 (class_id), INDEX IDX_46C8B8063D9AB4A6 (object_identity_id), INDEX IDX_46C8B806DF9183C9 (security_identity_id))

ALTER TABLE acl_object_identities ADD CONSTRAINT FK_9407E54977FA751A FOREIGN KEY (parent_object_identity_id) REFERENCES acl_object_identities (id)

ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE2993D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE

ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE299C671CEA1 FOREIGN KEY (ancestor_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE

ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806EA000B10 FOREIGN KEY (class_id) REFERENCES acl_classes (id) ON UPDATE CASCADE ON DELETE CASCADE

ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B8063D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE

ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806DF9183C9 FOREIGN KEY (security_identity_id) REFERENCES acl_security_identities (id) ON UPDATE CASCADE ON DELETE CASCADEPK��Z�C� ;;:Symfony/Component/Security/Acl/Resources/schema/oracle.sqlnu�[���CREATE TABLE acl_classes (id NUMBER(10) NOT NULL, class_type VARCHAR2(200) NOT NULL, PRIMARY KEY(id))

DECLARE
  constraints_Count NUMBER;
BEGIN
  SELECT COUNT(CONSTRAINT_NAME) INTO constraints_Count FROM USER_CONSTRAINTS WHERE TABLE_NAME = 'ACL_CLASSES' AND CONSTRAINT_TYPE = 'P';
  IF constraints_Count = 0 OR constraints_Count = '' THEN
    EXECUTE IMMEDIATE 'ALTER TABLE ACL_CLASSES ADD CONSTRAINT ACL_CLASSES_AI_PK PRIMARY KEY (id)';
  END IF;
END;

CREATE SEQUENCE ACL_CLASSES_SEQ START WITH 1 MINVALUE 1 INCREMENT BY 1

CREATE TRIGGER ACL_CLASSES_AI_PK
   BEFORE INSERT
   ON ACL_CLASSES
   FOR EACH ROW
DECLARE
   last_Sequence NUMBER;
   last_InsertID NUMBER;
BEGIN
   SELECT ACL_CLASSES_SEQ.NEXTVAL INTO :NEW.id FROM DUAL;
   IF (:NEW.id IS NULL OR :NEW.id = 0) THEN
      SELECT ACL_CLASSES_SEQ.NEXTVAL INTO :NEW.id FROM DUAL;
   ELSE
      SELECT NVL(Last_Number, 0) INTO last_Sequence
        FROM User_Sequences
       WHERE Sequence_Name = 'ACL_CLASSES_SEQ';
      SELECT :NEW.id INTO last_InsertID FROM DUAL;
      WHILE (last_InsertID > last_Sequence) LOOP
         SELECT ACL_CLASSES_SEQ.NEXTVAL INTO last_Sequence FROM DUAL;
      END LOOP;
   END IF;
END;

CREATE UNIQUE INDEX UNIQ_69DD750638A36066 ON acl_classes (class_type)

CREATE TABLE acl_security_identities (id NUMBER(10) NOT NULL, identifier VARCHAR2(200) NOT NULL, username NUMBER(1) NOT NULL, PRIMARY KEY(id))

DECLARE
  constraints_Count NUMBER;
BEGIN
  SELECT COUNT(CONSTRAINT_NAME) INTO constraints_Count FROM USER_CONSTRAINTS WHERE TABLE_NAME = 'ACL_SECURITY_IDENTITIES' AND CONSTRAINT_TYPE = 'P';
  IF constraints_Count = 0 OR constraints_Count = '' THEN
    EXECUTE IMMEDIATE 'ALTER TABLE ACL_SECURITY_IDENTITIES ADD CONSTRAINT ACL_SECURITY_IDENTITIES_AI_PK PRIMARY KEY (id)';
  END IF;
END;

CREATE SEQUENCE ACL_SECURITY_IDENTITIES_SEQ START WITH 1 MINVALUE 1 INCREMENT BY 1

CREATE TRIGGER ACL_SECURITY_IDENTITIES_AI_PK
   BEFORE INSERT
   ON ACL_SECURITY_IDENTITIES
   FOR EACH ROW
DECLARE
   last_Sequence NUMBER;
   last_InsertID NUMBER;
BEGIN
   SELECT ACL_SECURITY_IDENTITIES_SEQ.NEXTVAL INTO :NEW.id FROM DUAL;
   IF (:NEW.id IS NULL OR :NEW.id = 0) THEN
      SELECT ACL_SECURITY_IDENTITIES_SEQ.NEXTVAL INTO :NEW.id FROM DUAL;
   ELSE
      SELECT NVL(Last_Number, 0) INTO last_Sequence
        FROM User_Sequences
       WHERE Sequence_Name = 'ACL_SECURITY_IDENTITIES_SEQ';
      SELECT :NEW.id INTO last_InsertID FROM DUAL;
      WHILE (last_InsertID > last_Sequence) LOOP
         SELECT ACL_SECURITY_IDENTITIES_SEQ.NEXTVAL INTO last_Sequence FROM DUAL;
      END LOOP;
   END IF;
END;

CREATE UNIQUE INDEX UNIQ_8835EE78772E836AF85E0677 ON acl_security_identities (identifier, username)

CREATE TABLE acl_object_identities (id NUMBER(10) NOT NULL, parent_object_identity_id NUMBER(10) DEFAULT NULL, class_id NUMBER(10) NOT NULL, object_identifier VARCHAR2(100) NOT NULL, entries_inheriting NUMBER(1) NOT NULL, PRIMARY KEY(id))

DECLARE
  constraints_Count NUMBER;
BEGIN
  SELECT COUNT(CONSTRAINT_NAME) INTO constraints_Count FROM USER_CONSTRAINTS WHERE TABLE_NAME = 'ACL_OBJECT_IDENTITIES' AND CONSTRAINT_TYPE = 'P';
  IF constraints_Count = 0 OR constraints_Count = '' THEN
    EXECUTE IMMEDIATE 'ALTER TABLE ACL_OBJECT_IDENTITIES ADD CONSTRAINT ACL_OBJECT_IDENTITIES_AI_PK PRIMARY KEY (id)';
  END IF;
END;

CREATE SEQUENCE ACL_OBJECT_IDENTITIES_SEQ START WITH 1 MINVALUE 1 INCREMENT BY 1

CREATE TRIGGER ACL_OBJECT_IDENTITIES_AI_PK
   BEFORE INSERT
   ON ACL_OBJECT_IDENTITIES
   FOR EACH ROW
DECLARE
   last_Sequence NUMBER;
   last_InsertID NUMBER;
BEGIN
   SELECT ACL_OBJECT_IDENTITIES_SEQ.NEXTVAL INTO :NEW.id FROM DUAL;
   IF (:NEW.id IS NULL OR :NEW.id = 0) THEN
      SELECT ACL_OBJECT_IDENTITIES_SEQ.NEXTVAL INTO :NEW.id FROM DUAL;
   ELSE
      SELECT NVL(Last_Number, 0) INTO last_Sequence
        FROM User_Sequences
       WHERE Sequence_Name = 'ACL_OBJECT_IDENTITIES_SEQ';
      SELECT :NEW.id INTO last_InsertID FROM DUAL;
      WHILE (last_InsertID > last_Sequence) LOOP
         SELECT ACL_OBJECT_IDENTITIES_SEQ.NEXTVAL INTO last_Sequence FROM DUAL;
      END LOOP;
   END IF;
END;

CREATE UNIQUE INDEX UNIQ_9407E5494B12AD6EA000B10 ON acl_object_identities (object_identifier, class_id)

CREATE INDEX IDX_9407E54977FA751A ON acl_object_identities (parent_object_identity_id)

CREATE TABLE acl_object_identity_ancestors (object_identity_id NUMBER(10) NOT NULL, ancestor_id NUMBER(10) NOT NULL, PRIMARY KEY(object_identity_id, ancestor_id))

CREATE INDEX IDX_825DE2993D9AB4A6 ON acl_object_identity_ancestors (object_identity_id)

CREATE INDEX IDX_825DE299C671CEA1 ON acl_object_identity_ancestors (ancestor_id)

CREATE TABLE acl_entries (id NUMBER(10) NOT NULL, class_id NUMBER(10) NOT NULL, object_identity_id NUMBER(10) DEFAULT NULL, security_identity_id NUMBER(10) NOT NULL, field_name VARCHAR2(50) DEFAULT NULL, ace_order NUMBER(5) NOT NULL, mask NUMBER(10) NOT NULL, granting NUMBER(1) NOT NULL, granting_strategy VARCHAR2(30) NOT NULL, audit_success NUMBER(1) NOT NULL, audit_failure NUMBER(1) NOT NULL, PRIMARY KEY(id))

DECLARE
  constraints_Count NUMBER;
BEGIN
  SELECT COUNT(CONSTRAINT_NAME) INTO constraints_Count FROM USER_CONSTRAINTS WHERE TABLE_NAME = 'ACL_ENTRIES' AND CONSTRAINT_TYPE = 'P';
  IF constraints_Count = 0 OR constraints_Count = '' THEN
    EXECUTE IMMEDIATE 'ALTER TABLE ACL_ENTRIES ADD CONSTRAINT ACL_ENTRIES_AI_PK PRIMARY KEY (id)';
  END IF;
END;

CREATE SEQUENCE ACL_ENTRIES_SEQ START WITH 1 MINVALUE 1 INCREMENT BY 1

CREATE TRIGGER ACL_ENTRIES_AI_PK
   BEFORE INSERT
   ON ACL_ENTRIES
   FOR EACH ROW
DECLARE
   last_Sequence NUMBER;
   last_InsertID NUMBER;
BEGIN
   SELECT ACL_ENTRIES_SEQ.NEXTVAL INTO :NEW.id FROM DUAL;
   IF (:NEW.id IS NULL OR :NEW.id = 0) THEN
      SELECT ACL_ENTRIES_SEQ.NEXTVAL INTO :NEW.id FROM DUAL;
   ELSE
      SELECT NVL(Last_Number, 0) INTO last_Sequence
        FROM User_Sequences
       WHERE Sequence_Name = 'ACL_ENTRIES_SEQ';
      SELECT :NEW.id INTO last_InsertID FROM DUAL;
      WHILE (last_InsertID > last_Sequence) LOOP
         SELECT ACL_ENTRIES_SEQ.NEXTVAL INTO last_Sequence FROM DUAL;
      END LOOP;
   END IF;
END;

CREATE UNIQUE INDEX UNIQ_46C8B806EA000B103D9AB4A64DEF17BCE4289BF4 ON acl_entries (class_id, object_identity_id, field_name, ace_order)

CREATE INDEX IDX_46C8B806EA000B103D9AB4A6DF9183C9 ON acl_entries (class_id, object_identity_id, security_identity_id)

CREATE INDEX IDX_46C8B806EA000B10 ON acl_entries (class_id)

CREATE INDEX IDX_46C8B8063D9AB4A6 ON acl_entries (object_identity_id)

CREATE INDEX IDX_46C8B806DF9183C9 ON acl_entries (security_identity_id)

ALTER TABLE acl_object_identities ADD CONSTRAINT FK_9407E54977FA751A FOREIGN KEY (parent_object_identity_id) REFERENCES acl_object_identities (id)

ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE2993D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON DELETE CASCADE

ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE299C671CEA1 FOREIGN KEY (ancestor_id) REFERENCES acl_object_identities (id) ON DELETE CASCADE

ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806EA000B10 FOREIGN KEY (class_id) REFERENCES acl_classes (id) ON DELETE CASCADE

ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B8063D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON DELETE CASCADE

ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806DF9183C9 FOREIGN KEY (security_identity_id) REFERENCES acl_security_identities (id) ON DELETE CASCADEPK��Z��d��:Symfony/Component/Security/Acl/Resources/schema/sqlite.sqlnu�[���CREATE TABLE acl_classes (id INTEGER NOT NULL, class_type VARCHAR(200) NOT NULL, PRIMARY KEY("id"))

CREATE UNIQUE INDEX UNIQ_69DD750638A36066 ON acl_classes (class_type)

CREATE TABLE acl_security_identities (id INTEGER NOT NULL, identifier VARCHAR(200) NOT NULL, username BOOLEAN NOT NULL, PRIMARY KEY("id"))

CREATE UNIQUE INDEX UNIQ_8835EE78772E836AF85E0677 ON acl_security_identities (identifier, username)

CREATE TABLE acl_object_identities (id INTEGER NOT NULL, parent_object_identity_id INTEGER DEFAULT NULL, class_id INTEGER NOT NULL, object_identifier VARCHAR(100) NOT NULL, entries_inheriting BOOLEAN NOT NULL, PRIMARY KEY("id"))

CREATE UNIQUE INDEX UNIQ_9407E5494B12AD6EA000B10 ON acl_object_identities (object_identifier, class_id)

CREATE INDEX IDX_9407E54977FA751A ON acl_object_identities (parent_object_identity_id)

CREATE TABLE acl_object_identity_ancestors (object_identity_id INTEGER NOT NULL, ancestor_id INTEGER NOT NULL, PRIMARY KEY("object_identity_id", "ancestor_id"))

CREATE INDEX IDX_825DE2993D9AB4A6 ON acl_object_identity_ancestors (object_identity_id)

CREATE INDEX IDX_825DE299C671CEA1 ON acl_object_identity_ancestors (ancestor_id)

CREATE TABLE acl_entries (id INTEGER NOT NULL, class_id INTEGER NOT NULL, object_identity_id INTEGER DEFAULT NULL, security_identity_id INTEGER NOT NULL, field_name VARCHAR(50) DEFAULT NULL, ace_order INTEGER NOT NULL, mask INTEGER NOT NULL, granting BOOLEAN NOT NULL, granting_strategy VARCHAR(30) NOT NULL, audit_success BOOLEAN NOT NULL, audit_failure BOOLEAN NOT NULL, PRIMARY KEY("id"))

CREATE UNIQUE INDEX UNIQ_46C8B806EA000B103D9AB4A64DEF17BCE4289BF4 ON acl_entries (class_id, object_identity_id, field_name, ace_order)

CREATE INDEX IDX_46C8B806EA000B103D9AB4A6DF9183C9 ON acl_entries (class_id, object_identity_id, security_identity_id)

CREATE INDEX IDX_46C8B806EA000B10 ON acl_entries (class_id)

CREATE INDEX IDX_46C8B8063D9AB4A6 ON acl_entries (object_identity_id)

CREATE INDEX IDX_46C8B806DF9183C9 ON acl_entries (security_identity_id)PK��Zw���DSymfony/Component/Security/Acl/Permission/PermissionMapInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Permission;

/**
 * This is the interface that must be implemented by permission maps.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface PermissionMapInterface
{
    /**
     * Returns an array of bitmasks.
     *
     * The security identity must have been granted access to at least one of
     * these bitmasks.
     *
     * @param string $permission
     * @param object $object
     * @return array may return null if permission/object combination is not supported
     */
    public function getMasks($permission, $object);

    /**
     * Whether this map contains the given permission
     *
     * @param string $permission
     * @return Boolean
     */
    public function contains($permission);
}
PK��Z�ep�gg9Symfony/Component/Security/Acl/Permission/MaskBuilder.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Permission;

/**
 * This class allows you to build cumulative permissions easily, or convert
 * masks to a human-readable format.
 *
 * <code>
 *       $builder = new MaskBuilder();
 *       $builder
 *           ->add('view')
 *           ->add('create')
 *           ->add('edit')
 *       ;
 *       var_dump($builder->get());        // int(7)
 *       var_dump($builder->getPattern()); // string(32) ".............................ECV"
 * </code>
 *
 * We have defined some commonly used base permissions which you can use:
 * - VIEW: the SID is allowed to view the domain object / field
 * - CREATE: the SID is allowed to create new instances of the domain object / fields
 * - EDIT: the SID is allowed to edit existing instances of the domain object / field
 * - DELETE: the SID is allowed to delete domain objects
 * - UNDELETE: the SID is allowed to recover domain objects from trash
 * - OPERATOR: the SID is allowed to perform any action on the domain object
 *             except for granting others permissions
 * - MASTER: the SID is allowed to perform any action on the domain object,
 *           and is allowed to grant other SIDs any permission except for
 *           MASTER and OWNER permissions
 * - OWNER: the SID is owning the domain object in question and can perform any
 *          action on the domain object as well as grant any permission
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class MaskBuilder
{
    const MASK_VIEW         = 1;          // 1 << 0
    const MASK_CREATE       = 2;          // 1 << 1
    const MASK_EDIT         = 4;          // 1 << 2
    const MASK_DELETE       = 8;          // 1 << 3
    const MASK_UNDELETE     = 16;         // 1 << 4
    const MASK_OPERATOR     = 32;         // 1 << 5
    const MASK_MASTER       = 64;         // 1 << 6
    const MASK_OWNER        = 128;        // 1 << 7
    const MASK_IDDQD        = 1073741823; // 1 << 0 | 1 << 1 | ... | 1 << 30

    const CODE_VIEW         = 'V';
    const CODE_CREATE       = 'C';
    const CODE_EDIT         = 'E';
    const CODE_DELETE       = 'D';
    const CODE_UNDELETE     = 'U';
    const CODE_OPERATOR     = 'O';
    const CODE_MASTER       = 'M';
    const CODE_OWNER        = 'N';

    const ALL_OFF           = '................................';
    const OFF               = '.';
    const ON                = '*';

    private $mask;

    /**
     * Constructor
     *
     * @param integer $mask optional; defaults to 0
     *
     * @throws \InvalidArgumentException
     */
    public function __construct($mask = 0)
    {
        if (!is_int($mask)) {
            throw new \InvalidArgumentException('$mask must be an integer.');
        }

        $this->mask = $mask;
    }

    /**
     * Adds a mask to the permission
     *
     * @param mixed $mask
     *
     * @return MaskBuilder
     *
     * @throws \InvalidArgumentException
     */
    public function add($mask)
    {
        if (is_string($mask) && defined($name = 'static::MASK_'.strtoupper($mask))) {
            $mask = constant($name);
        } elseif (!is_int($mask)) {
            throw new \InvalidArgumentException('$mask must be an integer.');
        }

        $this->mask |= $mask;

        return $this;
    }

    /**
     * Returns the mask of this permission
     *
     * @return integer
     */
    public function get()
    {
        return $this->mask;
    }

    /**
     * Returns a human-readable representation of the permission
     *
     * @return string
     */
    public function getPattern()
    {
        $pattern = self::ALL_OFF;
        $length = strlen($pattern);
        $bitmask = str_pad(decbin($this->mask), $length, '0', STR_PAD_LEFT);

        for ($i=$length-1; $i>=0; $i--) {
            if ('1' === $bitmask[$i]) {
                try {
                    $pattern[$i] = self::getCode(1 << ($length - $i - 1));
                } catch (\Exception $notPredefined) {
                    $pattern[$i] = self::ON;
                }
            }
        }

        return $pattern;
    }

    /**
     * Removes a mask from the permission
     *
     * @param mixed $mask
     *
     * @return MaskBuilder
     *
     * @throws \InvalidArgumentException
     */
    public function remove($mask)
    {
        if (is_string($mask) && defined($name = 'static::MASK_'.strtoupper($mask))) {
            $mask = constant($name);
        } elseif (!is_int($mask)) {
            throw new \InvalidArgumentException('$mask must be an integer.');
        }

        $this->mask &= ~$mask;

        return $this;
    }

    /**
     * Resets the PermissionBuilder
     *
     * @return MaskBuilder
     */
    public function reset()
    {
        $this->mask = 0;

        return $this;
    }

    /**
     * Returns the code for the passed mask
     *
     * @param integer $mask
     * @throws \InvalidArgumentException
     * @throws \RuntimeException
     * @return string
     */
    public static function getCode($mask)
    {
        if (!is_int($mask)) {
            throw new \InvalidArgumentException('$mask must be an integer.');
        }

        $reflection = new \ReflectionClass(get_called_class());
        foreach ($reflection->getConstants() as $name => $cMask) {
            if (0 !== strpos($name, 'MASK_')) {
                continue;
            }

            if ($mask === $cMask) {
                if (!defined($cName = 'static::CODE_'.substr($name, 5))) {
                    throw new \RuntimeException('There was no code defined for this mask.');
                }

                return constant($cName);
            }
        }

        throw new \InvalidArgumentException(sprintf('The mask "%d" is not supported.', $mask));
    }
}
PK��Z� c0��@Symfony/Component/Security/Acl/Permission/BasicPermissionMap.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Permission;

/**
 * This is basic permission map complements the masks which have been defined
 * on the standard implementation of the MaskBuilder.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class BasicPermissionMap implements PermissionMapInterface
{
    const PERMISSION_VIEW        = 'VIEW';
    const PERMISSION_EDIT        = 'EDIT';
    const PERMISSION_CREATE      = 'CREATE';
    const PERMISSION_DELETE      = 'DELETE';
    const PERMISSION_UNDELETE    = 'UNDELETE';
    const PERMISSION_OPERATOR    = 'OPERATOR';
    const PERMISSION_MASTER      = 'MASTER';
    const PERMISSION_OWNER       = 'OWNER';

    protected $map;

    public function __construct()
    {
        $this->map = array(
            self::PERMISSION_VIEW => array(
                MaskBuilder::MASK_VIEW,
                MaskBuilder::MASK_EDIT,
                MaskBuilder::MASK_OPERATOR,
                MaskBuilder::MASK_MASTER,
                MaskBuilder::MASK_OWNER,
            ),

            self::PERMISSION_EDIT => array(
                MaskBuilder::MASK_EDIT,
                MaskBuilder::MASK_OPERATOR,
                MaskBuilder::MASK_MASTER,
                MaskBuilder::MASK_OWNER,
            ),

            self::PERMISSION_CREATE => array(
                MaskBuilder::MASK_CREATE,
                MaskBuilder::MASK_OPERATOR,
                MaskBuilder::MASK_MASTER,
                MaskBuilder::MASK_OWNER,
            ),

            self::PERMISSION_DELETE => array(
                MaskBuilder::MASK_DELETE,
                MaskBuilder::MASK_OPERATOR,
                MaskBuilder::MASK_MASTER,
                MaskBuilder::MASK_OWNER,
            ),

            self::PERMISSION_UNDELETE => array(
                MaskBuilder::MASK_UNDELETE,
                MaskBuilder::MASK_OPERATOR,
                MaskBuilder::MASK_MASTER,
                MaskBuilder::MASK_OWNER,
            ),

            self::PERMISSION_OPERATOR => array(
                MaskBuilder::MASK_OPERATOR,
                MaskBuilder::MASK_MASTER,
                MaskBuilder::MASK_OWNER,
            ),

            self::PERMISSION_MASTER => array(
                MaskBuilder::MASK_MASTER,
                MaskBuilder::MASK_OWNER,
            ),

            self::PERMISSION_OWNER => array(
                MaskBuilder::MASK_OWNER,
            ),
        );
    }

    /**
     * {@inheritDoc}
     */
    public function getMasks($permission, $object)
    {
        if (!isset($this->map[$permission])) {
            return null;
        }

        return $this->map[$permission];
    }

    /**
     * {@inheritDoc}
     */
    public function contains($permission)
    {
        return isset($this->map[$permission]);
    }
}
PK��Z6����<Symfony/Component/Security/Acl/Model/MutableAclInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Model;

/**
 * This interface adds mutators for the AclInterface.
 *
 * All changes to Access Control Entries must go through this interface. Access
 * Control Entries must never be modified directly.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface MutableAclInterface extends AclInterface
{
    /**
     * Deletes a class-based ACE
     *
     * @param integer $index
     */
    public function deleteClassAce($index);

    /**
     * Deletes a class-field-based ACE
     *
     * @param integer $index
     * @param string  $field
     */
    public function deleteClassFieldAce($index, $field);

    /**
     * Deletes an object-based ACE
     *
     * @param integer $index
     */
    public function deleteObjectAce($index);

    /**
     * Deletes an object-field-based ACE
     *
     * @param integer $index
     * @param string  $field
     */
    public function deleteObjectFieldAce($index, $field);

    /**
     * Returns the primary key of this ACL
     *
     * @return integer
     */
    public function getId();

    /**
     * Inserts a class-based ACE
     *
     * @param SecurityIdentityInterface $sid
     * @param integer                   $mask
     * @param integer                   $index
     * @param Boolean                   $granting
     * @param string                    $strategy
     */
    public function insertClassAce(SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null);

    /**
     * Inserts a class-field-based ACE
     *
     * @param string                    $field
     * @param SecurityIdentityInterface $sid
     * @param integer                   $mask
     * @param integer                   $index
     * @param Boolean                   $granting
     * @param string                    $strategy
     */
    public function insertClassFieldAce($field, SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null);

    /**
     * Inserts an object-based ACE
     *
     * @param SecurityIdentityInterface $sid
     * @param integer                   $mask
     * @param integer                   $index
     * @param Boolean                   $granting
     * @param string                    $strategy
     */
    public function insertObjectAce(SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null);

    /**
     * Inserts an object-field-based ACE
     *
     * @param string                    $field
     * @param SecurityIdentityInterface $sid
     * @param integer                   $mask
     * @param integer                   $index
     * @param Boolean                   $granting
     * @param string                    $strategy
     */
    public function insertObjectFieldAce($field, SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null);

    /**
     * Sets whether entries are inherited
     *
     * @param Boolean $boolean
     */
    public function setEntriesInheriting($boolean);

    /**
     * Sets the parent ACL
     *
     * @param AclInterface|null $acl
     */
    public function setParentAcl(AclInterface $acl = null);

    /**
     * Updates a class-based ACE
     *
     * @param integer $index
     * @param integer $mask
     * @param string  $strategy if null the strategy should not be changed
     */
    public function updateClassAce($index, $mask, $strategy = null);

    /**
     * Updates a class-field-based ACE
     *
     * @param integer $index
     * @param string  $field
     * @param integer $mask
     * @param string  $strategy if null the strategy should not be changed
     */
    public function updateClassFieldAce($index, $field, $mask, $strategy = null);

    /**
     * Updates an object-based ACE
     *
     * @param integer $index
     * @param integer $mask
     * @param string  $strategy if null the strategy should not be changed
     */
    public function updateObjectAce($index, $mask, $strategy = null);

    /**
     * Updates an object-field-based ACE
     *
     * @param integer $index
     * @param string  $field
     * @param integer $mask
     * @param string  $strategy if null the strategy should not be changed
     */
    public function updateObjectFieldAce($index, $field, $mask, $strategy = null);
}
PK��Z[Ob3SSymfony/Component/Security/Acl/Model/SecurityIdentityRetrievalStrategyInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Model;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;

/**
 * Interface for retrieving security identities from tokens
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface SecurityIdentityRetrievalStrategyInterface
{
    /**
     * Retrieves the available security identities for the given token
     *
     * The order in which the security identities are returned is significant.
     * Typically, security identities should be ordered from most specific to
     * least specific.
     *
     * @param TokenInterface $token
     *
     * @return SecurityIdentityInterface[] An array of SecurityIdentityInterface implementations
     */
    public function getSecurityIdentities(TokenInterface $token);
}
PK��ZX	��>Symfony/Component/Security/Acl/Model/DomainObjectInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Model;

/**
 * This method can be implemented by domain objects which you want to store
 * ACLs for if they do not have a getId() method, or getId() does not return
 * a unique identifier.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface DomainObjectInterface
{
    /**
     * Returns a unique identifier for this domain object.
     *
     * @return string
     */
    public function getObjectIdentifier();
}
PK��Z�5Ayy@Symfony/Component/Security/Acl/Model/ObjectIdentityInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Model;

/**
 * Represents the identity of an individual domain object instance.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface ObjectIdentityInterface
{
    /**
     * We specifically require this method so we can check for object equality
     * explicitly, and do not have to rely on referencial equality instead.
     *
     * Though in most cases, both checks should result in the same outcome.
     *
     * Referential Equality: $object1 === $object2
     * Example for Object Equality: $object1->getId() === $object2->getId()
     *
     * @param ObjectIdentityInterface $identity
     * @return Boolean
     */
    public function equals(ObjectIdentityInterface $identity);

    /**
     * Obtains a unique identifier for this object. The identifier must not be
     * re-used for other objects with the same type.
     *
     * @return string cannot return null
     */
    public function getIdentifier();

    /**
     * Returns a type for the domain object. Typically, this is the PHP class name.
     *
     * @return string cannot return null
     */
    public function getType();
}
PK��Zt��@Symfony/Component/Security/Acl/Model/AuditableEntryInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Model;

/**
 * ACEs can implement this interface if they support auditing capabilities.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface AuditableEntryInterface extends EntryInterface
{
    /**
     * Whether auditing for successful grants is turned on
     *
     * @return Boolean
     */
    public function isAuditFailure();

    /**
     * Whether auditing for successful denies is turned on
     *
     * @return Boolean
     */
    public function isAuditSuccess();
}
PK��Z-癥��LSymfony/Component/Security/Acl/Model/PermissionGrantingStrategyInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Model;

/**
 * Interface used by permission granting implementations.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface PermissionGrantingStrategyInterface
{
    /**
     * Determines whether access to a domain object is to be granted
     *
     * @param AclInterface $acl
     * @param array        $masks
     * @param array        $sids
     * @param Boolean      $administrativeMode
     * @return Boolean
     */
    public function isGranted(AclInterface $acl, array $masks, array $sids, $administrativeMode = false);

    /**
     * Determines whether access to a domain object's field is to be granted
     *
     * @param AclInterface $acl
     * @param string       $field
     * @param array        $masks
     * @param array        $sids
     * @param Boolean      $administrativeMode
     *
     * @return Boolean
     */
    public function isFieldGranted(AclInterface $acl, $field, array $masks, array $sids, $administrativeMode = false);
}
PK��Z�����=Symfony/Component/Security/Acl/Model/AclProviderInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Model;

use Symfony\Component\Security\Acl\Exception\AclNotFoundException;

/**
 * Provides a common interface for retrieving ACLs.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface AclProviderInterface
{
    /**
     * Retrieves all child object identities from the database
     *
     * @param ObjectIdentityInterface $parentOid
     * @param Boolean                 $directChildrenOnly
     *
     * @return array returns an array of child 'ObjectIdentity's
     */
    public function findChildren(ObjectIdentityInterface $parentOid, $directChildrenOnly = false);

    /**
     * Returns the ACL that belongs to the given object identity
     *
     * @param ObjectIdentityInterface     $oid
     * @param SecurityIdentityInterface[] $sids
     *
     * @return AclInterface
     *
     * @throws AclNotFoundException when there is no ACL
     */
    public function findAcl(ObjectIdentityInterface $oid, array $sids = array());

    /**
     * Returns the ACLs that belong to the given object identities
     *
     * @param ObjectIdentityInterface[]   $oids an array of ObjectIdentityInterface implementations
     * @param SecurityIdentityInterface[] $sids an array of SecurityIdentityInterface implementations
     *
     * @return \SplObjectStorage mapping the passed object identities to ACLs
     *
     * @throws AclNotFoundException when we cannot find an ACL for all identities
     */
    public function findAcls(array $oids, array $sids = array());
}
PK��Z�#���:Symfony/Component/Security/Acl/Model/AclCacheInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Model;

/**
 * AclCache Interface
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface AclCacheInterface
{
    /**
     * Removes an ACL from the cache
     *
     * @param string $primaryKey a serialized primary key
     */
    public function evictFromCacheById($primaryKey);

    /**
     * Removes an ACL from the cache
     *
     * The ACL which is returned, must reference the passed object identity.
     *
     * @param ObjectIdentityInterface $oid
     */
    public function evictFromCacheByIdentity(ObjectIdentityInterface $oid);

    /**
     * Retrieves an ACL for the given object identity primary key from the cache
     *
     * @param integer $primaryKey
     * @return AclInterface
     */
    public function getFromCacheById($primaryKey);

    /**
     * Retrieves an ACL for the given object identity from the cache
     *
     * @param ObjectIdentityInterface $oid
     * @return AclInterface
     */
    public function getFromCacheByIdentity(ObjectIdentityInterface $oid);

    /**
     * Stores a new ACL in the cache
     *
     * @param AclInterface $acl
     */
    public function putInCache(AclInterface $acl);

    /**
     * Removes all ACLs from the cache
     */
    public function clearCache();
}
PK��Zӗ&1>Symfony/Component/Security/Acl/Model/AuditableAclInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Model;

/**
 * This interface adds auditing capabilities to the ACL.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface AuditableAclInterface extends MutableAclInterface
{
    /**
     * Updates auditing for class-based ACE
     *
     * @param integer $index
     * @param Boolean $auditSuccess
     * @param Boolean $auditFailure
     */
    public function updateClassAuditing($index, $auditSuccess, $auditFailure);

    /**
     * Updates auditing for class-field-based ACE
     *
     * @param integer $index
     * @param string  $field
     * @param Boolean $auditSuccess
     * @param Boolean $auditFailure
     */
    public function updateClassFieldAuditing($index, $field, $auditSuccess, $auditFailure);

    /**
     * Updates auditing for object-based ACE
     *
     * @param integer $index
     * @param Boolean $auditSuccess
     * @param Boolean $auditFailure
     */
    public function updateObjectAuditing($index, $auditSuccess, $auditFailure);

    /**
     * Updates auditing for object-field-based ACE
     *
     * @param integer $index
     * @param string  $field
     * @param Boolean $auditSuccess
     * @param Boolean $auditFailure
     */
    public function updateObjectFieldAuditing($index, $field, $auditSuccess, $auditFailure);
}
PK��Z�ݤUU<Symfony/Component/Security/Acl/Model/FieldEntryInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Model;

/**
 * Interface for entries which are restricted to specific fields
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface FieldEntryInterface extends EntryInterface
{
    /**
     * Returns the field used for this entry.
     *
     * @return string
     */
    public function getField();
}
PK��Z�
�8FF7Symfony/Component/Security/Acl/Model/EntryInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Model;

/**
 * This class represents an individual entry in the ACL list.
 *
 * Instances MUST be immutable, as they are returned by the ACL and should not
 * allow client modification.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface EntryInterface extends \Serializable
{
    /**
     * The ACL this ACE is associated with.
     *
     * @return AclInterface
     */
    public function getAcl();

    /**
     * The primary key of this ACE
     *
     * @return integer
     */
    public function getId();

    /**
     * The permission mask of this ACE
     *
     * @return integer
     */
    public function getMask();

    /**
     * The security identity associated with this ACE
     *
     * @return SecurityIdentityInterface
     */
    public function getSecurityIdentity();

    /**
     * The strategy for comparing masks
     *
     * @return string
     */
    public function getStrategy();

    /**
     * Returns whether this ACE is granting, or denying
     *
     * @return Boolean
     */
    public function isGranting();
}
PK��ZH<J��=Symfony/Component/Security/Acl/Model/AuditLoggerInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Model;

/**
 * Interface for audit loggers
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface AuditLoggerInterface
{
    /**
     * This method is called whenever access is granted, or denied, and
     * administrative mode is turned off.
     *
     * @param Boolean        $granted
     * @param EntryInterface $ace
     */
    public function logIfNeeded($granted, EntryInterface $ace);
}
PK��Z���77BSymfony/Component/Security/Acl/Model/SecurityIdentityInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Model;

/**
 * This interface provides an additional level of indirection, so that
 * we can work with abstracted versions of security objects and do
 * not have to save the entire objects.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface SecurityIdentityInterface
{
    /**
     * This method is used to compare two security identities in order to
     * not rely on referential equality.
     *
     * @param SecurityIdentityInterface $identity
     */
    public function equals(SecurityIdentityInterface $identity);
}
PK��Z�𕛼�5Symfony/Component/Security/Acl/Model/AclInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Model;

use Symfony\Component\Security\Acl\Exception\NoAceFoundException;

/**
 * This interface represents an access control list (ACL) for a domain object.
 * Each domain object can have exactly one associated ACL.
 *
 * An ACL contains all access control entries (ACE) for a given domain object.
 * In order to avoid needing references to the domain object itself, implementations
 * use ObjectIdentity implementations as an additional level of indirection.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface AclInterface extends \Serializable
{
    /**
     * Returns all class-based ACEs associated with this ACL
     *
     * @return array
     */
    public function getClassAces();

    /**
     * Returns all class-field-based ACEs associated with this ACL
     *
     * @param string $field
     * @return array
     */
    public function getClassFieldAces($field);

    /**
     * Returns all object-based ACEs associated with this ACL
     *
     * @return array
     */
    public function getObjectAces();

    /**
     * Returns all object-field-based ACEs associated with this ACL
     *
     * @param string $field
     * @return array
     */
    public function getObjectFieldAces($field);

    /**
     * Returns the object identity associated with this ACL
     *
     * @return ObjectIdentityInterface
     */
    public function getObjectIdentity();

    /**
     * Returns the parent ACL, or null if there is none.
     *
     * @return AclInterface|null
     */
    public function getParentAcl();

    /**
     * Whether this ACL is inheriting ACEs from a parent ACL.
     *
     * @return Boolean
     */
    public function isEntriesInheriting();

    /**
     * Determines whether field access is granted
     *
     * @param string  $field
     * @param array   $masks
     * @param array   $securityIdentities
     * @param Boolean $administrativeMode
     * @return Boolean
     */
    public function isFieldGranted($field, array $masks, array $securityIdentities, $administrativeMode = false);

    /**
     * Determines whether access is granted
     *
     * @throws NoAceFoundException when no ACE was applicable for this request
     * @param array   $masks
     * @param array   $securityIdentities
     * @param Boolean $administrativeMode
     * @return Boolean
     */
    public function isGranted(array $masks, array $securityIdentities, $administrativeMode = false);

    /**
     * Whether the ACL has loaded ACEs for all of the passed security identities
     *
     * @param mixed $securityIdentities an implementation of SecurityIdentityInterface, or an array thereof
     * @return Boolean
     */
    public function isSidLoaded($securityIdentities);
}
PK��Z�W}��QSymfony/Component/Security/Acl/Model/ObjectIdentityRetrievalStrategyInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Model;

/**
 * Retrieves the object identity for a given domain object
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface ObjectIdentityRetrievalStrategyInterface
{
    /**
     * Retrieves the object identity from a domain object
     *
     * @param object $domainObject
     * @return ObjectIdentityInterface
     */
    public function getObjectIdentity($domainObject);
}
PK��Zj���DSymfony/Component/Security/Acl/Model/MutableAclProviderInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Model;

/**
 * Provides support for creating and storing ACL instances.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface MutableAclProviderInterface extends AclProviderInterface
{
    /**
     * Creates a new ACL for the given object identity.
     *
     * @throws AclAlreadyExistsException when there already is an ACL for the given
     *                                   object identity
     * @param ObjectIdentityInterface $oid
     * @return MutableAclInterface
     */
    public function createAcl(ObjectIdentityInterface $oid);

    /**
     * Deletes the ACL for a given object identity.
     *
     * This will automatically trigger a delete for any child ACLs. If you don't
     * want child ACLs to be deleted, you will have to set their parent ACL to null.
     *
     * @param ObjectIdentityInterface $oid
     */
    public function deleteAcl(ObjectIdentityInterface $oid);

    /**
     * Persists any changes which were made to the ACL, or any associated
     * access control entries.
     *
     * Changes to parent ACLs are not persisted.
     *
     * @param MutableAclInterface $acl
     */
    public function updateAcl(MutableAclInterface $acl);
}
PK��Z��W"RR)Symfony/Component/Security/autoloader.phpnu�[���<?php

spl_autoload_register(function ($class) {
    if ('\\' == $class[0]) {
        $class = substr($class, 1);
    }

    if (
        0 === strpos($class, 'Symfony\\Component\\Security\\')
        &&
        file_exists($file = __DIR__.'/../../../'.str_replace('\\', '/', $class).'.php')
    ) {
        require_once $file;
    }
});
PK��Z�DXVV,Symfony/Component/Security/Http/Firewall.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http;

use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Firewall uses a FirewallMap to register security listeners for the given
 * request.
 *
 * It allows for different security strategies within the same application
 * (a Basic authentication for the /api, and a web based authentication for
 * everything else for instance).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Firewall implements EventSubscriberInterface
{
    private $map;
    private $dispatcher;
    private $exceptionListeners;

    /**
     * Constructor.
     *
     * @param FirewallMapInterface     $map        A FirewallMapInterface instance
     * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance
     */
    public function __construct(FirewallMapInterface $map, EventDispatcherInterface $dispatcher)
    {
        $this->map = $map;
        $this->dispatcher = $dispatcher;
        $this->exceptionListeners = new \SplObjectStorage();
    }

    /**
     * Handles security.
     *
     * @param GetResponseEvent $event An GetResponseEvent instance
     */
    public function onKernelRequest(GetResponseEvent $event)
    {
        if (!$event->isMasterRequest()) {
            return;
        }

        // register listeners for this firewall
        list($listeners, $exceptionListener) = $this->map->getListeners($event->getRequest());
        if (null !== $exceptionListener) {
            $this->exceptionListeners[$event->getRequest()] = $exceptionListener;
            $exceptionListener->register($this->dispatcher);
        }

        // initiate the listener chain
        foreach ($listeners as $listener) {
            $listener->handle($event);

            if ($event->hasResponse()) {
                break;
            }
        }
    }

    public function onKernelFinishRequest(FinishRequestEvent $event)
    {
        $request = $event->getRequest();

        if (isset($this->exceptionListeners[$request])) {
            $this->exceptionListeners[$request]->unregister($this->dispatcher);
            unset($this->exceptionListeners[$request]);
        }
    }

    /**
     * {@inheritDoc}
     */
    public static function getSubscribedEvents()
    {
        return array(
            KernelEvents::REQUEST => array('onKernelRequest', 8),
            KernelEvents::FINISH_REQUEST => 'onKernelFinishRequest',
        );
    }
}
PK��Z"�C��/Symfony/Component/Security/Http/FirewallMap.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http;

use Symfony\Component\HttpFoundation\RequestMatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Http\Firewall\ExceptionListener;

/**
 * FirewallMap allows configuration of different firewalls for specific parts
 * of the website.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FirewallMap implements FirewallMapInterface
{
    private $map = array();

    /**
     * @param RequestMatcherInterface $requestMatcher
     * @param array                   $listeners
     * @param ExceptionListener       $exceptionListener
     */
    public function add(RequestMatcherInterface $requestMatcher = null, array $listeners = array(), ExceptionListener $exceptionListener = null)
    {
        $this->map[] = array($requestMatcher, $listeners, $exceptionListener);
    }

    /**
     * {@inheritDoc}
     */
    public function getListeners(Request $request)
    {
        foreach ($this->map as $elements) {
            if (null === $elements[0] || $elements[0]->matches($request)) {
                return array($elements[1], $elements[2]);
            }
        }

        return array(array(), null);
    }
}
PK��Z�יKSymfony/Component/Security/Http/EntryPoint/FormAuthenticationEntryPoint.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\EntryPoint;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\HttpUtils;
use Symfony\Component\HttpKernel\HttpKernelInterface;

/**
 * FormAuthenticationEntryPoint starts an authentication via a login form.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FormAuthenticationEntryPoint implements AuthenticationEntryPointInterface
{
    private $loginPath;
    private $useForward;
    private $httpKernel;
    private $httpUtils;

    /**
     * Constructor.
     *
     * @param HttpKernelInterface $kernel
     * @param HttpUtils           $httpUtils  An HttpUtils instance
     * @param string              $loginPath  The path to the login form
     * @param Boolean             $useForward Whether to forward or redirect to the login form
     */
    public function __construct(HttpKernelInterface $kernel, HttpUtils $httpUtils, $loginPath, $useForward = false)
    {
        $this->httpKernel = $kernel;
        $this->httpUtils = $httpUtils;
        $this->loginPath = $loginPath;
        $this->useForward = (Boolean) $useForward;
    }

    /**
     * {@inheritdoc}
     */
    public function start(Request $request, AuthenticationException $authException = null)
    {
        if ($this->useForward) {
            $subRequest = $this->httpUtils->createRequest($request, $this->loginPath);

            $response = $this->httpKernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
            if (200 === $response->getStatusCode()) {
                $response->headers->set('X-Status-Code', 401);
            }

            return $response;
        }

        return $this->httpUtils->createRedirectResponse($request, $this->loginPath);
    }
}
PK��Z�<ݐppLSymfony/Component/Security/Http/EntryPoint/BasicAuthenticationEntryPoint.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\EntryPoint;

use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;

/**
 * BasicAuthenticationEntryPoint starts an HTTP Basic authentication.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class BasicAuthenticationEntryPoint implements AuthenticationEntryPointInterface
{
    private $realmName;

    public function __construct($realmName)
    {
        $this->realmName = $realmName;
    }

    /**
     * {@inheritdoc}
     */
    public function start(Request $request, AuthenticationException $authException = null)
    {
        $response = new Response();
        $response->headers->set('WWW-Authenticate', sprintf('Basic realm="%s"', $this->realmName));
        $response->setStatusCode(401);

        return $response;
    }
}
PK��Z)'_++PSymfony/Component/Security/Http/EntryPoint/AuthenticationEntryPointInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\EntryPoint;

use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * AuthenticationEntryPointInterface is the interface used to start the
 * authentication scheme.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface AuthenticationEntryPointInterface
{
    /**
     * Starts the authentication scheme.
     *
     * @param Request                 $request       The request that resulted in an AuthenticationException
     * @param AuthenticationException $authException The exception that started the authentication process
     *
     * @return Response
     */
    public function start(Request $request, AuthenticationException $authException = null);
}
PK��ZtZ�)K	K	MSymfony/Component/Security/Http/EntryPoint/DigestAuthenticationEntryPoint.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\EntryPoint;

use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\NonceExpiredException;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Psr\Log\LoggerInterface;

/**
 * DigestAuthenticationEntryPoint starts an HTTP Digest authentication.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class DigestAuthenticationEntryPoint implements AuthenticationEntryPointInterface
{
    private $key;
    private $realmName;
    private $nonceValiditySeconds;
    private $logger;

    public function __construct($realmName, $key, $nonceValiditySeconds = 300, LoggerInterface $logger = null)
    {
        $this->realmName = $realmName;
        $this->key = $key;
        $this->nonceValiditySeconds = $nonceValiditySeconds;
        $this->logger = $logger;
    }

    /**
     * {@inheritdoc}
     */
    public function start(Request $request, AuthenticationException $authException = null)
    {
        $expiryTime = microtime(true) + $this->nonceValiditySeconds * 1000;
        $signatureValue = md5($expiryTime.':'.$this->key);
        $nonceValue = $expiryTime.':'.$signatureValue;
        $nonceValueBase64 = base64_encode($nonceValue);

        $authenticateHeader = sprintf('Digest realm="%s", qop="auth", nonce="%s"', $this->realmName, $nonceValueBase64);

        if ($authException instanceof NonceExpiredException) {
            $authenticateHeader = $authenticateHeader.', stale="true"';
        }

        if (null !== $this->logger) {
            $this->logger->debug(sprintf('WWW-Authenticate header sent to user agent: "%s"', $authenticateHeader));
        }

        $response = new Response();
        $response->headers->set('WWW-Authenticate', $authenticateHeader);
        $response->setStatusCode(401);

        return $response;
    }

    /**
     * @return string
     */
    public function getKey()
    {
        return $this->key;
    }

    /**
     * @return string
     */
    public function getRealmName()
    {
        return $this->realmName;
    }
}
PK��Z�����LSymfony/Component/Security/Http/EntryPoint/RetryAuthenticationEntryPoint.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\EntryPoint;

use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;

/**
 * RetryAuthenticationEntryPoint redirects URL based on the configured scheme.
 *
 * This entry point is not intended to work with HTTP post requests.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class RetryAuthenticationEntryPoint implements AuthenticationEntryPointInterface
{
    private $httpPort;
    private $httpsPort;

    public function __construct($httpPort = 80, $httpsPort = 443)
    {
        $this->httpPort = $httpPort;
        $this->httpsPort = $httpsPort;
    }

    /**
     * {@inheritdoc}
     */
    public function start(Request $request, AuthenticationException $authException = null)
    {
        $scheme = $request->isSecure() ? 'http' : 'https';
        if ('http' === $scheme && 80 != $this->httpPort) {
            $port = ':'.$this->httpPort;
        } elseif ('https' === $scheme && 443 != $this->httpsPort) {
            $port = ':'.$this->httpsPort;
        } else {
            $port = '';
        }

        $qs = $request->getQueryString();
        if (null !== $qs) {
            $qs = '?'.$qs;
        }

        $url = $scheme.'://'.$request->getHost().$port.$request->getBaseUrl().$request->getPathInfo().$qs;

        return new RedirectResponse($url, 301);
    }
}
PK��Z��`C��-Symfony/Component/Security/Http/HttpUtils.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http;

use Symfony\Component\Security\Core\SecurityContextInterface;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;

/**
 * Encapsulates the logic needed to create sub-requests, redirect the user, and match URLs.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class HttpUtils
{
    private $urlGenerator;
    private $urlMatcher;

    /**
     * Constructor.
     *
     * @param UrlGeneratorInterface                       $urlGenerator A UrlGeneratorInterface instance
     * @param UrlMatcherInterface|RequestMatcherInterface $urlMatcher   The URL or Request matcher
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(UrlGeneratorInterface $urlGenerator = null, $urlMatcher = null)
    {
        $this->urlGenerator = $urlGenerator;
        if ($urlMatcher !== null && !$urlMatcher instanceof UrlMatcherInterface && !$urlMatcher instanceof RequestMatcherInterface) {
            throw new \InvalidArgumentException('Matcher must either implement UrlMatcherInterface or RequestMatcherInterface.');
        }
        $this->urlMatcher = $urlMatcher;
    }

    /**
     * Creates a redirect Response.
     *
     * @param Request $request A Request instance
     * @param string  $path    A path (an absolute path (/foo), an absolute URL (http://...), or a route name (foo))
     * @param integer $status  The status code
     *
     * @return RedirectResponse A RedirectResponse instance
     */
    public function createRedirectResponse(Request $request, $path, $status = 302)
    {
        return new RedirectResponse($this->generateUri($request, $path), $status);
    }

    /**
     * Creates a Request.
     *
     * @param Request $request The current Request instance
     * @param string  $path    A path (an absolute path (/foo), an absolute URL (http://...), or a route name (foo))
     *
     * @return Request A Request instance
     */
    public function createRequest(Request $request, $path)
    {
        $newRequest = Request::create($this->generateUri($request, $path), 'get', array(), $request->cookies->all(), array(), $request->server->all());
        if ($request->hasSession()) {
            $newRequest->setSession($request->getSession());
        }

        if ($request->attributes->has(SecurityContextInterface::AUTHENTICATION_ERROR)) {
            $newRequest->attributes->set(SecurityContextInterface::AUTHENTICATION_ERROR, $request->attributes->get(SecurityContextInterface::AUTHENTICATION_ERROR));
        }
        if ($request->attributes->has(SecurityContextInterface::ACCESS_DENIED_ERROR)) {
            $newRequest->attributes->set(SecurityContextInterface::ACCESS_DENIED_ERROR, $request->attributes->get(SecurityContextInterface::ACCESS_DENIED_ERROR));
        }
        if ($request->attributes->has(SecurityContextInterface::LAST_USERNAME)) {
            $newRequest->attributes->set(SecurityContextInterface::LAST_USERNAME, $request->attributes->get(SecurityContextInterface::LAST_USERNAME));
        }

        return $newRequest;
    }

    /**
     * Checks that a given path matches the Request.
     *
     * @param Request $request A Request instance
     * @param string  $path    A path (an absolute path (/foo), an absolute URL (http://...), or a route name (foo))
     *
     * @return Boolean true if the path is the same as the one from the Request, false otherwise
     */
    public function checkRequestPath(Request $request, $path)
    {
        if ('/' !== $path[0]) {
            try {
                // matching a request is more powerful than matching a URL path + context, so try that first
                if ($this->urlMatcher instanceof RequestMatcherInterface) {
                    $parameters = $this->urlMatcher->matchRequest($request);
                } else {
                    $parameters = $this->urlMatcher->match($request->getPathInfo());
                }

                return $path === $parameters['_route'];
            } catch (MethodNotAllowedException $e) {
                return false;
            } catch (ResourceNotFoundException $e) {
                return false;
            }
        }

        return $path === rawurldecode($request->getPathInfo());
    }

    /**
     * Generates a URI, based on the given path or absolute URL.
     *
     * @param Request $request A Request instance
     * @param string  $path    A path (an absolute path (/foo), an absolute URL (http://...), or a route name (foo))
     *
     * @return string An absolute URL
     *
     * @throws \LogicException
     */
    public function generateUri($request, $path)
    {
        if (0 === strpos($path, 'http') || !$path) {
            return $path;
        }

        if ('/' === $path[0]) {
            return $request->getUriForPath($path);
        }

        if (null === $this->urlGenerator) {
            throw new \LogicException('You must provide a UrlGeneratorInterface instance to be able to use routes.');
        }

        $url = $this->urlGenerator->generate($path, $request->attributes->all(), UrlGeneratorInterface::ABSOLUTE_URL);

        // unnecessary query string parameters must be removed from URL
        // (ie. query parameters that are presents in $attributes)
        // fortunately, they all are, so we have to remove entire query string
        $position = strpos($url, '?');
        if (false !== $position) {
            $url = substr($url, 0, $position);
        }

        return $url;
    }
}
PK��Z^�V��NSymfony/Component/Security/Http/Authorization/AccessDeniedHandlerInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Authorization;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;

/**
 * This is used by the ExceptionListener to translate an AccessDeniedException
 * to a Response object.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface AccessDeniedHandlerInterface
{
    /**
     * Handles an access denied failure.
     *
     * @param Request               $request
     * @param AccessDeniedException $accessDeniedException
     *
     * @return Response may return null
     */
    public function handle(Request $request, AccessDeniedException $accessDeniedException);
}
PK��Z��̗��WSymfony/Component/Security/Http/Firewall/UsernamePasswordFormAuthenticationListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Firewall;

use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter;
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
use Symfony\Component\HttpFoundation\Request;
use Psr\Log\LoggerInterface;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
use Symfony\Component\Security\Http\HttpUtils;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\InvalidArgumentException;
use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

/**
 * UsernamePasswordFormAuthenticationListener is the default implementation of
 * an authentication via a simple form composed of a username and a password.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class UsernamePasswordFormAuthenticationListener extends AbstractAuthenticationListener
{
    private $csrfTokenManager;

    /**
     * {@inheritdoc}
     */
    public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, HttpUtils $httpUtils, $providerKey, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options = array(), LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, $csrfTokenManager = null)
    {
        if ($csrfTokenManager instanceof CsrfProviderInterface) {
            $csrfTokenManager = new CsrfProviderAdapter($csrfTokenManager);
        } elseif (null !== $csrfTokenManager && !$csrfTokenManager instanceof CsrfTokenManagerInterface) {
            throw new InvalidArgumentException('The CSRF token manager should be an instance of CsrfProviderInterface or CsrfTokenManagerInterface.');
        }

        parent::__construct($securityContext, $authenticationManager, $sessionStrategy, $httpUtils, $providerKey, $successHandler, $failureHandler, array_merge(array(
            'username_parameter' => '_username',
            'password_parameter' => '_password',
            'csrf_parameter'     => '_csrf_token',
            'intention'          => 'authenticate',
            'post_only'          => true,
        ), $options), $logger, $dispatcher);

        $this->csrfTokenManager = $csrfTokenManager;
    }

    /**
     * {@inheritdoc}
     */
    protected function requiresAuthentication(Request $request)
    {
        if ($this->options['post_only'] && !$request->isMethod('POST')) {
            return false;
        }

        return parent::requiresAuthentication($request);
    }

    /**
     * {@inheritdoc}
     */
    protected function attemptAuthentication(Request $request)
    {
        if (null !== $this->csrfTokenManager) {
            $csrfToken = $request->get($this->options['csrf_parameter'], null, true);

            if (false === $this->csrfTokenManager->isTokenValid(new CsrfToken($this->options['intention'], $csrfToken))) {
                throw new InvalidCsrfTokenException('Invalid CSRF token.');
            }
        }

        if ($this->options['post_only']) {
            $username = trim($request->request->get($this->options['username_parameter'], null, true));
            $password = $request->request->get($this->options['password_parameter'], null, true);
        } else {
            $username = trim($request->get($this->options['username_parameter'], null, true));
            $password = $request->get($this->options['password_parameter'], null, true);
        }

        $request->getSession()->set(SecurityContextInterface::LAST_USERNAME, $username);

        return $this->authenticationManager->authenticate(new UsernamePasswordToken($username, $password, $this->providerKey));
    }
}
PK��Znz+S�
�
?Symfony/Component/Security/Http/Firewall/RememberMeListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Firewall;

use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\SecurityEvents;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

/**
 * RememberMeListener implements authentication capabilities via a cookie
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class RememberMeListener implements ListenerInterface
{
    private $securityContext;
    private $rememberMeServices;
    private $authenticationManager;
    private $logger;
    private $dispatcher;

    /**
     * Constructor.
     *
     * @param SecurityContextInterface       $securityContext
     * @param RememberMeServicesInterface    $rememberMeServices
     * @param AuthenticationManagerInterface $authenticationManager
     * @param LoggerInterface                $logger
     * @param EventDispatcherInterface       $dispatcher
     */
    public function __construct(SecurityContextInterface $securityContext, RememberMeServicesInterface $rememberMeServices, AuthenticationManagerInterface $authenticationManager, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null)
    {
        $this->securityContext = $securityContext;
        $this->rememberMeServices = $rememberMeServices;
        $this->authenticationManager = $authenticationManager;
        $this->logger = $logger;
        $this->dispatcher = $dispatcher;
    }

    /**
     * Handles remember-me cookie based authentication.
     *
     * @param GetResponseEvent $event A GetResponseEvent instance
     */
    public function handle(GetResponseEvent $event)
    {
        if (null !== $this->securityContext->getToken()) {
            return;
        }

        $request = $event->getRequest();
        if (null === $token = $this->rememberMeServices->autoLogin($request)) {
            return;
        }

        try {
            $token = $this->authenticationManager->authenticate($token);
            $this->securityContext->setToken($token);

            if (null !== $this->dispatcher) {
                $loginEvent = new InteractiveLoginEvent($request, $token);
                $this->dispatcher->dispatch(SecurityEvents::INTERACTIVE_LOGIN, $loginEvent);
            }

            if (null !== $this->logger) {
                $this->logger->debug('SecurityContext populated with remember-me token.');
            }
        } catch (AuthenticationException $failed) {
            if (null !== $this->logger) {
                $this->logger->warning(
                    'SecurityContext not populated with remember-me token as the'
                   .' AuthenticationManager rejected the AuthenticationToken returned'
                   .' by the RememberMeServices: '.$failed->getMessage()
                );
            }

            $this->rememberMeServices->loginFail($request);
        }
    }
}
PK��Zlٯ��LSymfony/Component/Security/Http/Firewall/AnonymousAuthenticationListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Firewall;

use Symfony\Component\Security\Core\SecurityContextInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;

/**
 * AnonymousAuthenticationListener automatically adds a Token if none is
 * already present.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class AnonymousAuthenticationListener implements ListenerInterface
{
    private $context;
    private $key;
    private $logger;

    public function __construct(SecurityContextInterface $context, $key, LoggerInterface $logger = null)
    {
        $this->context = $context;
        $this->key     = $key;
        $this->logger  = $logger;
    }

    /**
     * Handles anonymous authentication.
     *
     * @param GetResponseEvent $event A GetResponseEvent instance
     */
    public function handle(GetResponseEvent $event)
    {
        if (null !== $this->context->getToken()) {
            return;
        }

        $this->context->setToken(new AnonymousToken($this->key, 'anon.', array()));

        if (null !== $this->logger) {
            $this->logger->info('Populated SecurityContext with an anonymous Token');
        }
    }
}
PK��Z�����>Symfony/Component/Security/Http/Firewall/ListenerInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Firewall;

use Symfony\Component\HttpKernel\Event\GetResponseEvent;

/**
 * Interface that must be implemented by firewall listeners
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface ListenerInterface
{
    /**
     * This interface must be implemented by firewall listeners.
     *
     * @param GetResponseEvent $event
     */
    public function handle(GetResponseEvent $event);
}
PK��Z�|L@**;Symfony/Component/Security/Http/Firewall/LogoutListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Firewall;

use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter;
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Exception\InvalidArgumentException;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Exception\LogoutException;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Security\Http\HttpUtils;
use Symfony\Component\Security\Http\Logout\LogoutHandlerInterface;
use Symfony\Component\Security\Http\Logout\LogoutSuccessHandlerInterface;

/**
 * LogoutListener logout users.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class LogoutListener implements ListenerInterface
{
    private $securityContext;
    private $options;
    private $handlers;
    private $successHandler;
    private $httpUtils;
    private $csrfTokenManager;

    /**
     * Constructor.
     *
     * @param SecurityContextInterface      $securityContext
     * @param HttpUtils                     $httpUtils        An HttpUtilsInterface instance
     * @param LogoutSuccessHandlerInterface $successHandler   A LogoutSuccessHandlerInterface instance
     * @param array                         $options          An array of options to process a logout attempt
     * @param CsrfTokenManagerInterface     $csrfTokenManager A CsrfTokenManagerInterface instance
     */
    public function __construct(SecurityContextInterface $securityContext, HttpUtils $httpUtils, LogoutSuccessHandlerInterface $successHandler, array $options = array(), $csrfTokenManager = null)
    {
        if ($csrfTokenManager instanceof CsrfProviderInterface) {
            $csrfTokenManager = new CsrfProviderAdapter($csrfTokenManager);
        } elseif (null !== $csrfTokenManager && !$csrfTokenManager instanceof CsrfTokenManagerInterface) {
            throw new InvalidArgumentException('The CSRF token manager should be an instance of CsrfProviderInterface or CsrfTokenManagerInterface.');
        }

        $this->securityContext = $securityContext;
        $this->httpUtils = $httpUtils;
        $this->options = array_merge(array(
            'csrf_parameter' => '_csrf_token',
            'intention'      => 'logout',
            'logout_path'    => '/logout',
        ), $options);
        $this->successHandler = $successHandler;
        $this->csrfTokenManager = $csrfTokenManager;
        $this->handlers = array();
    }

    /**
     * Adds a logout handler
     *
     * @param LogoutHandlerInterface $handler
     */
    public function addHandler(LogoutHandlerInterface $handler)
    {
        $this->handlers[] = $handler;
    }

    /**
     * Performs the logout if requested
     *
     * If a CsrfTokenManagerInterface instance is available, it will be used to
     * validate the request.
     *
     * @param GetResponseEvent $event A GetResponseEvent instance
     *
     * @throws LogoutException if the CSRF token is invalid
     * @throws \RuntimeException if the LogoutSuccessHandlerInterface instance does not return a response
     */
    public function handle(GetResponseEvent $event)
    {
        $request = $event->getRequest();

        if (!$this->requiresLogout($request)) {
            return;
        }

        if (null !== $this->csrfTokenManager) {
            $csrfToken = $request->get($this->options['csrf_parameter'], null, true);

            if (false === $this->csrfTokenManager->isTokenValid(new CsrfToken($this->options['intention'], $csrfToken))) {
                throw new LogoutException('Invalid CSRF token.');
            }
        }

        $response = $this->successHandler->onLogoutSuccess($request);
        if (!$response instanceof Response) {
            throw new \RuntimeException('Logout Success Handler did not return a Response.');
        }

        // handle multiple logout attempts gracefully
        if ($token = $this->securityContext->getToken()) {
            foreach ($this->handlers as $handler) {
                $handler->logout($request, $response, $token);
            }
        }

        $this->securityContext->setToken(null);

        $event->setResponse($response);
    }

    /**
     * Whether this request is asking for logout.
     *
     * The default implementation only processed requests to a specific path,
     * but a subclass could change this to logout requests where
     * certain parameters is present.
     *
     * @param Request $request
     *
     * @return Boolean
     */
    protected function requiresLogout(Request $request)
    {
        return $this->httpUtils->checkRequestPath($request, $this->options['logout_path']);
    }
}
PK��Z�Bb

?Symfony/Component/Security/Http/Firewall/SwitchUserListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Firewall;

use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Role\SwitchUserRole;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Http\Event\SwitchUserEvent;
use Symfony\Component\Security\Http\SecurityEvents;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

/**
 * SwitchUserListener allows a user to impersonate another one temporarily
 * (like the Unix su command).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class SwitchUserListener implements ListenerInterface
{
    private $securityContext;
    private $provider;
    private $userChecker;
    private $providerKey;
    private $accessDecisionManager;
    private $usernameParameter;
    private $role;
    private $logger;
    private $dispatcher;

    /**
     * Constructor.
     */
    public function __construct(SecurityContextInterface $securityContext, UserProviderInterface $provider, UserCheckerInterface $userChecker, $providerKey, AccessDecisionManagerInterface $accessDecisionManager, LoggerInterface $logger = null, $usernameParameter = '_switch_user', $role = 'ROLE_ALLOWED_TO_SWITCH', EventDispatcherInterface $dispatcher = null)
    {
        if (empty($providerKey)) {
            throw new \InvalidArgumentException('$providerKey must not be empty.');
        }

        $this->securityContext = $securityContext;
        $this->provider = $provider;
        $this->userChecker = $userChecker;
        $this->providerKey = $providerKey;
        $this->accessDecisionManager = $accessDecisionManager;
        $this->usernameParameter = $usernameParameter;
        $this->role = $role;
        $this->logger = $logger;
        $this->dispatcher = $dispatcher;
    }

    /**
     * Handles the switch to another user.
     *
     * @param GetResponseEvent $event A GetResponseEvent instance
     *
     * @throws \LogicException if switching to a user failed
     */
    public function handle(GetResponseEvent $event)
    {
        $request = $event->getRequest();

        if (!$request->get($this->usernameParameter)) {
            return;
        }

        if ('_exit' === $request->get($this->usernameParameter)) {
            $this->securityContext->setToken($this->attemptExitUser($request));
        } else {
            try {
                $this->securityContext->setToken($this->attemptSwitchUser($request));
            } catch (AuthenticationException $e) {
                throw new \LogicException(sprintf('Switch User failed: "%s"', $e->getMessage()));
            }
        }

        $request->query->remove($this->usernameParameter);
        $request->server->set('QUERY_STRING', http_build_query($request->query->all()));

        $response = new RedirectResponse($request->getUri(), 302);

        $event->setResponse($response);
    }

    /**
     * Attempts to switch to another user.
     *
     * @param Request $request A Request instance
     *
     * @return TokenInterface|null The new TokenInterface if successfully switched, null otherwise
     *
     * @throws \LogicException
     * @throws AccessDeniedException
     */
    private function attemptSwitchUser(Request $request)
    {
        $token = $this->securityContext->getToken();
        $originalToken = $this->getOriginalToken($token);

        if (false !== $originalToken) {
            if ($token->getUsername() === $request->get($this->usernameParameter)) {
                return $token;
            } else {
                throw new \LogicException(sprintf('You are already switched to "%s" user.', $token->getUsername()));
            }
        }

        if (false === $this->accessDecisionManager->decide($token, array($this->role))) {
            throw new AccessDeniedException();
        }

        $username = $request->get($this->usernameParameter);

        if (null !== $this->logger) {
            $this->logger->info(sprintf('Attempt to switch to user "%s"', $username));
        }

        $user = $this->provider->loadUserByUsername($username);
        $this->userChecker->checkPostAuth($user);

        $roles = $user->getRoles();
        $roles[] = new SwitchUserRole('ROLE_PREVIOUS_ADMIN', $this->securityContext->getToken());

        $token = new UsernamePasswordToken($user, $user->getPassword(), $this->providerKey, $roles);

        if (null !== $this->dispatcher) {
            $switchEvent = new SwitchUserEvent($request, $token->getUser());
            $this->dispatcher->dispatch(SecurityEvents::SWITCH_USER, $switchEvent);
        }

        return $token;
    }

    /**
     * Attempts to exit from an already switched user.
     *
     * @param Request $request A Request instance
     *
     * @return TokenInterface The original TokenInterface instance
     *
     * @throws AuthenticationCredentialsNotFoundException
     */
    private function attemptExitUser(Request $request)
    {
        if (false === $original = $this->getOriginalToken($this->securityContext->getToken())) {
            throw new AuthenticationCredentialsNotFoundException('Could not find original Token object.');
        }

        if (null !== $this->dispatcher) {
            $switchEvent = new SwitchUserEvent($request, $original->getUser());
            $this->dispatcher->dispatch(SecurityEvents::SWITCH_USER, $switchEvent);
        }

        return $original;
    }

    /**
     * Gets the original Token from a switched one.
     *
     * @param TokenInterface $token A switched TokenInterface instance
     *
     * @return TokenInterface|false The original TokenInterface instance, false if the current TokenInterface is not switched
     */
    private function getOriginalToken(TokenInterface $token)
    {
        foreach ($token->getRoles() as $role) {
            if ($role instanceof SwitchUserRole) {
                return $role->getSource();
            }
        }

        return false;
    }
}
PK��Z(�T	b!b!>Symfony/Component/Security/Http/Firewall/ExceptionListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Firewall;

use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Http\Authorization\AccessDeniedHandlerInterface;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use Symfony\Component\Security\Core\Exception\AccountStatusException;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Core\Exception\InsufficientAuthenticationException;
use Symfony\Component\Security\Core\Exception\LogoutException;
use Symfony\Component\Security\Http\HttpUtils;
use Symfony\Component\HttpFoundation\Request;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

/**
 * ExceptionListener catches authentication exception and converts them to
 * Response instances.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ExceptionListener
{
    private $context;
    private $providerKey;
    private $accessDeniedHandler;
    private $authenticationEntryPoint;
    private $authenticationTrustResolver;
    private $errorPage;
    private $logger;
    private $httpUtils;

    public function __construct(SecurityContextInterface $context, AuthenticationTrustResolverInterface $trustResolver, HttpUtils $httpUtils, $providerKey, AuthenticationEntryPointInterface $authenticationEntryPoint = null, $errorPage = null, AccessDeniedHandlerInterface $accessDeniedHandler = null, LoggerInterface $logger = null)
    {
        $this->context = $context;
        $this->accessDeniedHandler = $accessDeniedHandler;
        $this->httpUtils = $httpUtils;
        $this->providerKey = $providerKey;
        $this->authenticationEntryPoint = $authenticationEntryPoint;
        $this->authenticationTrustResolver = $trustResolver;
        $this->errorPage = $errorPage;
        $this->logger = $logger;
    }

    /**
     * Registers a onKernelException listener to take care of security exceptions.
     *
     * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance
     */
    public function register(EventDispatcherInterface $dispatcher)
    {
        $dispatcher->addListener(KernelEvents::EXCEPTION, array($this, 'onKernelException'));
    }

    /**
     * Unregisters the dispatcher.
     *
     * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance
     */
    public function unregister(EventDispatcherInterface $dispatcher)
    {
        $dispatcher->removeListener(KernelEvents::EXCEPTION, array($this, 'onKernelException'));
    }

    /**
     * Handles security related exceptions.
     *
     * @param GetResponseForExceptionEvent $event An GetResponseForExceptionEvent instance
     */
    public function onKernelException(GetResponseForExceptionEvent $event)
    {
        $exception = $event->getException();
        do {
            if ($exception instanceof AuthenticationException) {
                return $this->handleAuthenticationException($event, $exception);
            } elseif ($exception instanceof AccessDeniedException) {
                return $this->handleAccessDeniedException($event, $exception);
            } elseif ($exception instanceof LogoutException) {
                return $this->handleLogoutException($event, $exception);
            }
        } while (null !== $exception = $exception->getPrevious());
    }

    private function handleAuthenticationException(GetResponseForExceptionEvent $event, AuthenticationException $exception)
    {
        if (null !== $this->logger) {
            $this->logger->info(sprintf('Authentication exception occurred; redirecting to authentication entry point (%s)', $exception->getMessage()));
        }

        try {
            $event->setResponse($this->startAuthentication($event->getRequest(), $exception));
        } catch (\Exception $e) {
            $event->setException($e);
        }
    }

    private function handleAccessDeniedException(GetResponseForExceptionEvent $event, AccessDeniedException $exception)
    {
        $event->setException(new AccessDeniedHttpException($exception->getMessage(), $exception));

        $token = $this->context->getToken();
        if (!$this->authenticationTrustResolver->isFullFledged($token)) {
            if (null !== $this->logger) {
                $this->logger->debug(sprintf('Access is denied (user is not fully authenticated) by "%s" at line %s; redirecting to authentication entry point', $exception->getFile(), $exception->getLine()));
            }

            try {
                $insufficientAuthenticationException = new InsufficientAuthenticationException('Full authentication is required to access this resource.', 0, $exception);
                $insufficientAuthenticationException->setToken($token);

                $event->setResponse($this->startAuthentication($event->getRequest(), $insufficientAuthenticationException));
            } catch (\Exception $e) {
                $event->setException($e);
            }

            return;
        }

        if (null !== $this->logger) {
            $this->logger->debug(sprintf('Access is denied (and user is neither anonymous, nor remember-me) by "%s" at line %s', $exception->getFile(), $exception->getLine()));
        }

        try {
            if (null !== $this->accessDeniedHandler) {
                $response = $this->accessDeniedHandler->handle($event->getRequest(), $exception);

                if ($response instanceof Response) {
                    $event->setResponse($response);
                }
            } elseif (null !== $this->errorPage) {
                $subRequest = $this->httpUtils->createRequest($event->getRequest(), $this->errorPage);
                $subRequest->attributes->set(SecurityContextInterface::ACCESS_DENIED_ERROR, $exception);

                $event->setResponse($event->getKernel()->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true));
            }
        } catch (\Exception $e) {
            if (null !== $this->logger) {
                $this->logger->error(sprintf('Exception thrown when handling an exception (%s: %s)', get_class($e), $e->getMessage()));
            }

            $event->setException(new \RuntimeException('Exception thrown when handling an exception.', 0, $e));
        }
    }

    private function handleLogoutException(GetResponseForExceptionEvent $event, LogoutException $exception)
    {
        if (null !== $this->logger) {
            $this->logger->info(sprintf('Logout exception occurred; wrapping with AccessDeniedHttpException (%s)', $exception->getMessage()));
        }
    }

    /**
     * @param Request                 $request
     * @param AuthenticationException $authException
     *
     * @return Response
     * @throws AuthenticationException
     */
    private function startAuthentication(Request $request, AuthenticationException $authException)
    {
        if (null === $this->authenticationEntryPoint) {
            throw $authException;
        }

        if (null !== $this->logger) {
            $this->logger->debug('Calling Authentication entry point');
        }

        $this->setTargetPath($request);

        if ($authException instanceof AccountStatusException) {
            // remove the security token to prevent infinite redirect loops
            $this->context->setToken(null);
        }

        return $this->authenticationEntryPoint->start($request, $authException);
    }

    /**
     * @param Request $request
     */
    protected function setTargetPath(Request $request)
    {
        // session isn't required when using HTTP basic authentication mechanism for example
        if ($request->hasSession() && $request->isMethodSafe()) {
            $request->getSession()->set('_security.'.$this->providerKey.'.target_path', $request->getUri());
        }
    }
}
PK��Z׺�=��GSymfony/Component/Security/Http/Firewall/X509AuthenticationListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Firewall;

use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

/**
 * X509 authentication listener.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class X509AuthenticationListener extends AbstractPreAuthenticatedListener
{
    private $userKey;
    private $credentialKey;

    public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, $providerKey, $userKey = 'SSL_CLIENT_S_DN_Email', $credentialKey = 'SSL_CLIENT_S_DN', LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null)
    {
        parent::__construct($securityContext, $authenticationManager, $providerKey, $logger, $dispatcher);

        $this->userKey = $userKey;
        $this->credentialKey = $credentialKey;
    }

    /**
     * {@inheritdoc}
     */
    protected function getPreAuthenticatedData(Request $request)
    {
        if (!$request->server->has($this->userKey)) {
            throw new BadCredentialsException(sprintf('SSL key was not found: %s', $this->userKey));
        }

        return array($request->server->get($this->userKey), $request->server->get($this->credentialKey, ''));
    }
}
PK��Z׿ͼ� � ISymfony/Component/Security/Http/Firewall/DigestAuthenticationListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Firewall;

use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Http\EntryPoint\DigestAuthenticationEntryPoint;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Exception\AuthenticationServiceException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\NonceExpiredException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Exception\AuthenticationException;

/**
 * DigestAuthenticationListener implements Digest HTTP authentication.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class DigestAuthenticationListener implements ListenerInterface
{
    private $securityContext;
    private $provider;
    private $providerKey;
    private $authenticationEntryPoint;
    private $logger;

    public function __construct(SecurityContextInterface $securityContext, UserProviderInterface $provider, $providerKey, DigestAuthenticationEntryPoint $authenticationEntryPoint, LoggerInterface $logger = null)
    {
        if (empty($providerKey)) {
            throw new \InvalidArgumentException('$providerKey must not be empty.');
        }

        $this->securityContext = $securityContext;
        $this->provider = $provider;
        $this->providerKey = $providerKey;
        $this->authenticationEntryPoint = $authenticationEntryPoint;
        $this->logger = $logger;
    }

    /**
     * Handles digest authentication.
     *
     * @param GetResponseEvent $event A GetResponseEvent instance
     *
     * @throws AuthenticationServiceException
     */
    public function handle(GetResponseEvent $event)
    {
        $request = $event->getRequest();

        if (!$header = $request->server->get('PHP_AUTH_DIGEST')) {
            return;
        }

        $digestAuth = new DigestData($header);

        if (null !== $token = $this->securityContext->getToken()) {
            if ($token instanceof UsernamePasswordToken && $token->isAuthenticated() && $token->getUsername() === $digestAuth->getUsername()) {
                return;
            }
        }

        if (null !== $this->logger) {
            $this->logger->debug(sprintf('Digest Authorization header received from user agent: %s', $header));
        }

        try {
            $digestAuth->validateAndDecode($this->authenticationEntryPoint->getKey(), $this->authenticationEntryPoint->getRealmName());
        } catch (BadCredentialsException $e) {
            $this->fail($event, $request, $e);

            return;
        }

        try {
            $user = $this->provider->loadUserByUsername($digestAuth->getUsername());

            if (null === $user) {
                throw new AuthenticationServiceException('AuthenticationDao returned null, which is an interface contract violation');
            }

            $serverDigestMd5 = $digestAuth->calculateServerDigest($user->getPassword(), $request->getMethod());
        } catch (UsernameNotFoundException $notFound) {
            $this->fail($event, $request, new BadCredentialsException(sprintf('Username %s not found.', $digestAuth->getUsername())));

            return;
        }

        if ($serverDigestMd5 !== $digestAuth->getResponse()) {
            if (null !== $this->logger) {
                $this->logger->debug(sprintf("Expected response: '%s' but received: '%s'; is AuthenticationDao returning clear text passwords?", $serverDigestMd5, $digestAuth->getResponse()));
            }

            $this->fail($event, $request, new BadCredentialsException('Incorrect response'));

            return;
        }

        if ($digestAuth->isNonceExpired()) {
            $this->fail($event, $request, new NonceExpiredException('Nonce has expired/timed out.'));

            return;
        }

        if (null !== $this->logger) {
            $this->logger->info(sprintf('Authentication success for user "%s" with response "%s"', $digestAuth->getUsername(), $digestAuth->getResponse()));
        }

        $this->securityContext->setToken(new UsernamePasswordToken($user, $user->getPassword(), $this->providerKey));
    }

    private function fail(GetResponseEvent $event, Request $request, AuthenticationException $authException)
    {
        $token = $this->securityContext->getToken();
        if ($token instanceof UsernamePasswordToken && $this->providerKey === $token->getProviderKey()) {
            $this->securityContext->setToken(null);
        }

        if (null !== $this->logger) {
            $this->logger->info($authException);
        }

        $event->setResponse($this->authenticationEntryPoint->start($request, $authException));
    }
}

class DigestData
{
    private $elements = array();
    private $header;
    private $nonceExpiryTime;

    public function __construct($header)
    {
        $this->header = $header;
        preg_match_all('/(\w+)=("((?:[^"\\\\]|\\\\.)+)"|([^\s,$]+))/', $header, $matches, PREG_SET_ORDER);
        foreach ($matches as $match) {
            if (isset($match[1]) && isset($match[3])) {
                $this->elements[$match[1]] = isset($match[4]) ? $match[4] : $match[3];
            }
        }
    }

    public function getResponse()
    {
        return $this->elements['response'];
    }

    public function getUsername()
    {
        return strtr($this->elements['username'], array("\\\"" => "\"", "\\\\" => "\\"));
    }

    public function validateAndDecode($entryPointKey, $expectedRealm)
    {
        if ($keys = array_diff(array('username', 'realm', 'nonce', 'uri', 'response'), array_keys($this->elements))) {
            throw new BadCredentialsException(sprintf('Missing mandatory digest value; received header "%s" (%s)', $this->header, implode(', ', $keys)));
        }

        if ('auth' === $this->elements['qop']) {
            if (!isset($this->elements['nc']) || !isset($this->elements['cnonce'])) {
                throw new BadCredentialsException(sprintf('Missing mandatory digest value; received header "%s"', $this->header));
            }
        }

        if ($expectedRealm !== $this->elements['realm']) {
            throw new BadCredentialsException(sprintf('Response realm name "%s" does not match system realm name of "%s".', $this->elements['realm'], $expectedRealm));
        }

        if (false === $nonceAsPlainText = base64_decode($this->elements['nonce'])) {
            throw new BadCredentialsException(sprintf('Nonce is not encoded in Base64; received nonce "%s".', $this->elements['nonce']));
        }

        $nonceTokens = explode(':', $nonceAsPlainText);

        if (2 !== count($nonceTokens)) {
            throw new BadCredentialsException(sprintf('Nonce should have yielded two tokens but was "%s".', $nonceAsPlainText));
        }

        $this->nonceExpiryTime = $nonceTokens[0];

        if (md5($this->nonceExpiryTime.':'.$entryPointKey) !== $nonceTokens[1]) {
            throw new BadCredentialsException(sprintf('Nonce token compromised "%s".', $nonceAsPlainText));
        }
    }

    public function calculateServerDigest($password, $httpMethod)
    {
        $a2Md5 = md5(strtoupper($httpMethod).':'.$this->elements['uri']);
        $a1Md5 = md5($this->elements['username'].':'.$this->elements['realm'].':'.$password);

        $digest = $a1Md5.':'.$this->elements['nonce'];
        if (!isset($this->elements['qop'])) {
        } elseif ('auth' === $this->elements['qop']) {
            $digest .= ':'.$this->elements['nc'].':'.$this->elements['cnonce'].':'.$this->elements['qop'];
        } else {
            throw new \InvalidArgumentException('This method does not support a qop: "%s".', $this->elements['qop']);
        }
        $digest .= ':'.$a2Md5;

        return md5($digest);
    }

    public function isNonceExpired()
    {
        return $this->nonceExpiryTime < microtime(true);
    }
}
PK��Z~�k��<Symfony/Component/Security/Http/Firewall/ChannelListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Firewall;

use Symfony\Component\Security\Http\AccessMapInterface;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;

/**
 * ChannelListener switches the HTTP protocol based on the access control
 * configuration.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ChannelListener implements ListenerInterface
{
    private $map;
    private $authenticationEntryPoint;
    private $logger;

    public function __construct(AccessMapInterface $map, AuthenticationEntryPointInterface $authenticationEntryPoint, LoggerInterface $logger = null)
    {
        $this->map = $map;
        $this->authenticationEntryPoint = $authenticationEntryPoint;
        $this->logger = $logger;
    }

    /**
     * Handles channel management.
     *
     * @param GetResponseEvent $event A GetResponseEvent instance
     */
    public function handle(GetResponseEvent $event)
    {
        $request = $event->getRequest();

        list($attributes, $channel) = $this->map->getPatterns($request);

        if ('https' === $channel && !$request->isSecure()) {
            if (null !== $this->logger) {
                $this->logger->info('Redirecting to HTTPS');
            }

            $response = $this->authenticationEntryPoint->start($request);

            $event->setResponse($response);

            return;
        }

        if ('http' === $channel && $request->isSecure()) {
            if (null !== $this->logger) {
                $this->logger->info('Redirecting to HTTP');
            }

            $response = $this->authenticationEntryPoint->start($request);

            $event->setResponse($response);
        }
    }
}
PK��Z��6'6'KSymfony/Component/Security/Http/Firewall/AbstractAuthenticationListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Firewall;

use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\SessionUnavailableException;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\SecurityEvents;
use Symfony\Component\Security\Http\HttpUtils;

/**
 * The AbstractAuthenticationListener is the preferred base class for all
 * browser-/HTTP-based authentication requests.
 *
 * Subclasses likely have to implement the following:
 * - an TokenInterface to hold authentication related data
 * - an AuthenticationProvider to perform the actual authentication of the
 *   token, retrieve the UserInterface implementation from a database, and
 *   perform the specific account checks using the UserChecker
 *
 * By default, this listener only is active for a specific path, e.g.
 * /login_check. If you want to change this behavior, you can overwrite the
 * requiresAuthentication() method.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
abstract class AbstractAuthenticationListener implements ListenerInterface
{
    protected $options;
    protected $logger;
    protected $authenticationManager;
    protected $providerKey;
    protected $httpUtils;

    private $securityContext;
    private $sessionStrategy;
    private $dispatcher;
    private $successHandler;
    private $failureHandler;
    private $rememberMeServices;

    /**
     * Constructor.
     *
     * @param SecurityContextInterface               $securityContext       A SecurityContext instance
     * @param AuthenticationManagerInterface         $authenticationManager An AuthenticationManagerInterface instance
     * @param SessionAuthenticationStrategyInterface $sessionStrategy
     * @param HttpUtils                              $httpUtils             An HttpUtilsInterface instance
     * @param string                                 $providerKey
     * @param AuthenticationSuccessHandlerInterface  $successHandler
     * @param AuthenticationFailureHandlerInterface  $failureHandler
     * @param array                                  $options               An array of options for the processing of a
     *                                                                      successful, or failed authentication attempt
     * @param LoggerInterface                        $logger                A LoggerInterface instance
     * @param EventDispatcherInterface               $dispatcher            An EventDispatcherInterface instance
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, HttpUtils $httpUtils, $providerKey, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options = array(), LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null)
    {
        if (empty($providerKey)) {
            throw new \InvalidArgumentException('$providerKey must not be empty.');
        }

        $this->securityContext = $securityContext;
        $this->authenticationManager = $authenticationManager;
        $this->sessionStrategy = $sessionStrategy;
        $this->providerKey = $providerKey;
        $this->successHandler = $successHandler;
        $this->failureHandler = $failureHandler;
        $this->options = array_merge(array(
            'check_path'                     => '/login_check',
            'login_path'                     => '/login',
            'always_use_default_target_path' => false,
            'default_target_path'            => '/',
            'target_path_parameter'          => '_target_path',
            'use_referer'                    => false,
            'failure_path'                   => null,
            'failure_forward'                => false,
            'require_previous_session'       => true,
        ), $options);
        $this->logger = $logger;
        $this->dispatcher = $dispatcher;
        $this->httpUtils = $httpUtils;
    }

    /**
     * Sets the RememberMeServices implementation to use
     *
     * @param RememberMeServicesInterface $rememberMeServices
     */
    public function setRememberMeServices(RememberMeServicesInterface $rememberMeServices)
    {
        $this->rememberMeServices = $rememberMeServices;
    }

    /**
     * Handles form based authentication.
     *
     * @param GetResponseEvent $event A GetResponseEvent instance
     *
     * @throws \RuntimeException
     * @throws SessionUnavailableException
     */
    final public function handle(GetResponseEvent $event)
    {
        $request = $event->getRequest();

        if (!$this->requiresAuthentication($request)) {
            return;
        }

        if (!$request->hasSession()) {
            throw new \RuntimeException('This authentication method requires a session.');
        }

        try {
            if ($this->options['require_previous_session'] && !$request->hasPreviousSession()) {
                throw new SessionUnavailableException('Your session has timed out, or you have disabled cookies.');
            }

            if (null === $returnValue = $this->attemptAuthentication($request)) {
                return;
            }

            if ($returnValue instanceof TokenInterface) {
                $this->sessionStrategy->onAuthentication($request, $returnValue);

                $response = $this->onSuccess($event, $request, $returnValue);
            } elseif ($returnValue instanceof Response) {
                $response = $returnValue;
            } else {
                throw new \RuntimeException('attemptAuthentication() must either return a Response, an implementation of TokenInterface, or null.');
            }
        } catch (AuthenticationException $e) {
            $response = $this->onFailure($event, $request, $e);
        }

        $event->setResponse($response);
    }

    /**
     * Whether this request requires authentication.
     *
     * The default implementation only processes requests to a specific path,
     * but a subclass could change this to only authenticate requests where a
     * certain parameters is present.
     *
     * @param Request $request
     *
     * @return Boolean
     */
    protected function requiresAuthentication(Request $request)
    {
        return $this->httpUtils->checkRequestPath($request, $this->options['check_path']);
    }

    /**
     * Performs authentication.
     *
     * @param Request $request A Request instance
     *
     * @return TokenInterface|Response|null The authenticated token, null if full authentication is not possible, or a Response
     *
     * @throws AuthenticationException if the authentication fails
     */
    abstract protected function attemptAuthentication(Request $request);

    private function onFailure(GetResponseEvent $event, Request $request, AuthenticationException $failed)
    {
        if (null !== $this->logger) {
            $this->logger->info(sprintf('Authentication request failed: %s', $failed->getMessage()));
        }

        $token = $this->securityContext->getToken();
        if ($token instanceof UsernamePasswordToken && $this->providerKey === $token->getProviderKey()) {
            $this->securityContext->setToken(null);
        }

        $response = $this->failureHandler->onAuthenticationFailure($request, $failed);

        if (!$response instanceof Response) {
            throw new \RuntimeException('Authentication Failure Handler did not return a Response.');
        }

        return $response;
    }

    private function onSuccess(GetResponseEvent $event, Request $request, TokenInterface $token)
    {
        if (null !== $this->logger) {
            $this->logger->info(sprintf('User "%s" has been authenticated successfully', $token->getUsername()));
        }

        $this->securityContext->setToken($token);

        $session = $request->getSession();
        $session->remove(SecurityContextInterface::AUTHENTICATION_ERROR);
        $session->remove(SecurityContextInterface::LAST_USERNAME);

        if (null !== $this->dispatcher) {
            $loginEvent = new InteractiveLoginEvent($request, $token);
            $this->dispatcher->dispatch(SecurityEvents::INTERACTIVE_LOGIN, $loginEvent);
        }

        $response = $this->successHandler->onAuthenticationSuccess($request, $token);

        if (!$response instanceof Response) {
            throw new \RuntimeException('Authentication Success Handler did not return a Response.');
        }

        if (null !== $this->rememberMeServices) {
            $this->rememberMeServices->loginSuccess($request, $response, $token);
        }

        return $response;
    }
}
PK��Z�"?���<Symfony/Component/Security/Http/Firewall/ContextListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Firewall;

use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

/**
 * ContextListener manages the SecurityContext persistence through a session.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ContextListener implements ListenerInterface
{
    private $context;
    private $contextKey;
    private $logger;
    private $userProviders;
    private $dispatcher;
    private $registered;

    public function __construct(SecurityContextInterface $context, array $userProviders, $contextKey, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null)
    {
        if (empty($contextKey)) {
            throw new \InvalidArgumentException('$contextKey must not be empty.');
        }

        foreach ($userProviders as $userProvider) {
            if (!$userProvider instanceof UserProviderInterface) {
                throw new \InvalidArgumentException(sprintf('User provider "%s" must implement "Symfony\Component\Security\Core\User\UserProviderInterface".', get_class($userProvider)));
            }
        }

        $this->context = $context;
        $this->userProviders = $userProviders;
        $this->contextKey = $contextKey;
        $this->logger = $logger;
        $this->dispatcher = $dispatcher;
    }

    /**
     * Reads the SecurityContext from the session.
     *
     * @param GetResponseEvent $event A GetResponseEvent instance
     */
    public function handle(GetResponseEvent $event)
    {
        if (!$this->registered && null !== $this->dispatcher && $event->isMasterRequest()) {
            $this->dispatcher->addListener(KernelEvents::RESPONSE, array($this, 'onKernelResponse'));
            $this->registered = true;
        }

        $request = $event->getRequest();
        $session = $request->hasPreviousSession() ? $request->getSession() : null;

        if (null === $session || null === $token = $session->get('_security_'.$this->contextKey)) {
            $this->context->setToken(null);

            return;
        }

        $token = unserialize($token);

        if (null !== $this->logger) {
            $this->logger->debug('Read SecurityContext from the session');
        }

        if ($token instanceof TokenInterface) {
            $token = $this->refreshUser($token);
        } elseif (null !== $token) {
            if (null !== $this->logger) {
                $this->logger->warning(sprintf('Session includes a "%s" where a security token is expected', is_object($token) ? get_class($token) : gettype($token)));
            }

            $token = null;
        }

        $this->context->setToken($token);
    }

    /**
     * Writes the SecurityContext to the session.
     *
     * @param FilterResponseEvent $event A FilterResponseEvent instance
     */
    public function onKernelResponse(FilterResponseEvent $event)
    {
        if (!$event->isMasterRequest()) {
            return;
        }

        if (!$event->getRequest()->hasSession()) {
            return;
        }

        if (null !== $this->logger) {
            $this->logger->debug('Write SecurityContext in the session');
        }

        $request = $event->getRequest();
        $session = $request->getSession();

        if (null === $session) {
            return;
        }

        if ((null === $token = $this->context->getToken()) || ($token instanceof AnonymousToken)) {
            if ($request->hasPreviousSession()) {
                $session->remove('_security_'.$this->contextKey);
            }
        } else {
            $session->set('_security_'.$this->contextKey, serialize($token));
        }
    }

    /**
     * Refreshes the user by reloading it from the user provider
     *
     * @param TokenInterface $token
     *
     * @return TokenInterface|null
     *
     * @throws \RuntimeException
     */
    private function refreshUser(TokenInterface $token)
    {
        $user = $token->getUser();
        if (!$user instanceof UserInterface) {
            return $token;
        }

        if (null !== $this->logger) {
            $this->logger->debug(sprintf('Reloading user from user provider.'));
        }

        foreach ($this->userProviders as $provider) {
            try {
                $refreshedUser = $provider->refreshUser($user);
                $token->setUser($refreshedUser);

                if (null !== $this->logger) {
                    $this->logger->debug(sprintf('Username "%s" was reloaded from user provider.', $refreshedUser->getUsername()));
                }

                return $token;
            } catch (UnsupportedUserException $unsupported) {
                // let's try the next user provider
            } catch (UsernameNotFoundException $notFound) {
                if (null !== $this->logger) {
                    $this->logger->warning(sprintf('Username "%s" could not be found.', $notFound->getUsername()));
                }

                return null;
            }
        }

        throw new \RuntimeException(sprintf('There is no user provider for user "%s".', get_class($user)));
    }
}
PK��Z�����MSymfony/Component/Security/Http/Firewall/SimpleFormAuthenticationListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Firewall;

use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter;
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Exception\InvalidArgumentException;
use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Authentication\SimpleFormAuthenticatorInterface;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Http\HttpUtils;
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
use Psr\Log\LoggerInterface;

/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class SimpleFormAuthenticationListener extends AbstractAuthenticationListener
{
    private $simpleAuthenticator;
    private $csrfTokenManager;

    /**
     * Constructor.
     *
     * @param SecurityContextInterface               $securityContext       A SecurityContext instance
     * @param AuthenticationManagerInterface         $authenticationManager An AuthenticationManagerInterface instance
     * @param SessionAuthenticationStrategyInterface $sessionStrategy
     * @param HttpUtils                              $httpUtils             An HttpUtilsInterface instance
     * @param string                                 $providerKey
     * @param AuthenticationSuccessHandlerInterface  $successHandler
     * @param AuthenticationFailureHandlerInterface  $failureHandler
     * @param array                                  $options               An array of options for the processing of a
     *                                                                      successful, or failed authentication attempt
     * @param LoggerInterface                        $logger                A LoggerInterface instance
     * @param EventDispatcherInterface               $dispatcher            An EventDispatcherInterface instance
     * @param SimpleFormAuthenticatorInterface       $simpleAuthenticator   A SimpleFormAuthenticatorInterface instance
     * @param CsrfTokenManagerInterface              $csrfTokenManager      A CsrfTokenManagerInterface instance
     */
    public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, HttpUtils $httpUtils, $providerKey, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options = array(), LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, CsrfTokenManagerInterface $csrfTokenManager = null, SimpleFormAuthenticatorInterface $simpleAuthenticator = null)
    {
        if (!$simpleAuthenticator) {
            throw new \InvalidArgumentException('Missing simple authenticator');
        }

        if ($csrfTokenManager instanceof CsrfProviderInterface) {
            $csrfTokenManager = new CsrfProviderAdapter($csrfTokenManager);
        } elseif (null !== $csrfTokenManager && !$csrfTokenManager instanceof CsrfTokenManagerInterface) {
            throw new InvalidArgumentException('The CSRF token manager should be an instance of CsrfProviderInterface or CsrfTokenManagerInterface.');
        }

        $this->simpleAuthenticator = $simpleAuthenticator;
        $this->csrfTokenManager = $csrfTokenManager;

        $options = array_merge(array(
            'username_parameter' => '_username',
            'password_parameter' => '_password',
            'csrf_parameter'     => '_csrf_token',
            'intention'          => 'authenticate',
            'post_only'          => true,
        ), $options);
        parent::__construct($securityContext, $authenticationManager, $sessionStrategy, $httpUtils, $providerKey, $successHandler, $failureHandler, $options, $logger, $dispatcher);
    }

    /**
     * {@inheritdoc}
     */
    protected function requiresAuthentication(Request $request)
    {
        if ($this->options['post_only'] && !$request->isMethod('POST')) {
            return false;
        }

        return parent::requiresAuthentication($request);
    }

    /**
     * {@inheritdoc}
     */
    protected function attemptAuthentication(Request $request)
    {
        if (null !== $this->csrfTokenManager) {
            $csrfToken = $request->get($this->options['csrf_parameter'], null, true);

            if (false === $this->csrfTokenManager->isTokenValid(new CsrfToken($this->options['intention'], $csrfToken))) {
                throw new InvalidCsrfTokenException('Invalid CSRF token.');
            }
        }

        if ($this->options['post_only']) {
            $username = trim($request->request->get($this->options['username_parameter'], null, true));
            $password = $request->request->get($this->options['password_parameter'], null, true);
        } else {
            $username = trim($request->get($this->options['username_parameter'], null, true));
            $password = $request->get($this->options['password_parameter'], null, true);
        }

        $request->getSession()->set(SecurityContextInterface::LAST_USERNAME, $username);

        $token = $this->simpleAuthenticator->createToken($request, $username, $password, $this->providerKey);

        return $this->authenticationManager->authenticate($token);
    }
}
PK��Z+/��Z	Z	;Symfony/Component/Security/Http/Firewall/AccessListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Firewall;

use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
use Symfony\Component\Security\Http\AccessMapInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;

/**
 * AccessListener enforces access control rules.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class AccessListener implements ListenerInterface
{
    private $context;
    private $accessDecisionManager;
    private $map;
    private $authManager;

    public function __construct(SecurityContextInterface $context, AccessDecisionManagerInterface $accessDecisionManager, AccessMapInterface $map, AuthenticationManagerInterface $authManager)
    {
        $this->context = $context;
        $this->accessDecisionManager = $accessDecisionManager;
        $this->map = $map;
        $this->authManager = $authManager;
    }

    /**
     * Handles access authorization.
     *
     * @param GetResponseEvent $event A GetResponseEvent instance
     *
     * @throws AccessDeniedException
     * @throws AuthenticationCredentialsNotFoundException
     */
    public function handle(GetResponseEvent $event)
    {
        if (null === $token = $this->context->getToken()) {
            throw new AuthenticationCredentialsNotFoundException('A Token was not found in the SecurityContext.');
        }

        $request = $event->getRequest();

        list($attributes, $channel) = $this->map->getPatterns($request);

        if (null === $attributes) {
            return;
        }

        if (!$token->isAuthenticated()) {
            $token = $this->authManager->authenticate($token);
            $this->context->setToken($token);
        }

        if (!$this->accessDecisionManager->decide($token, $attributes, $request)) {
            throw new AccessDeniedException();
        }
    }
}
PK��Z�Z���MSymfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Firewall;

use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\SecurityEvents;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;

/**
 * AbstractPreAuthenticatedListener is the base class for all listener that
 * authenticates users based on a pre-authenticated request (like a certificate
 * for instance).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class AbstractPreAuthenticatedListener implements ListenerInterface
{
    protected $logger;
    private $securityContext;
    private $authenticationManager;
    private $providerKey;
    private $dispatcher;

    public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, $providerKey, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null)
    {
        $this->securityContext = $securityContext;
        $this->authenticationManager = $authenticationManager;
        $this->providerKey = $providerKey;
        $this->logger = $logger;
        $this->dispatcher = $dispatcher;
    }

    /**
     * Handles pre-authentication.
     *
     * @param GetResponseEvent $event A GetResponseEvent instance
     */
    final public function handle(GetResponseEvent $event)
    {
        $request = $event->getRequest();

        if (null !== $this->logger) {
            $this->logger->debug(sprintf('Checking secure context token: %s', $this->securityContext->getToken()));
        }

        try {
            list($user, $credentials) = $this->getPreAuthenticatedData($request);
        } catch (BadCredentialsException $exception) {
            $this->clearToken($exception);

            return;
        }

        if (null !== $token = $this->securityContext->getToken()) {
            if ($token instanceof PreAuthenticatedToken && $this->providerKey == $token->getProviderKey() && $token->isAuthenticated() && $token->getUsername() === $user) {
                return;
            }
        }

        if (null !== $this->logger) {
            $this->logger->debug(sprintf('Trying to pre-authenticate user "%s"', $user));
        }

        try {
            $token = $this->authenticationManager->authenticate(new PreAuthenticatedToken($user, $credentials, $this->providerKey));

            if (null !== $this->logger) {
                $this->logger->info(sprintf('Authentication success: %s', $token));
            }
            $this->securityContext->setToken($token);

            if (null !== $this->dispatcher) {
                $loginEvent = new InteractiveLoginEvent($request, $token);
                $this->dispatcher->dispatch(SecurityEvents::INTERACTIVE_LOGIN, $loginEvent);
            }
        } catch (AuthenticationException $failed) {
            $this->clearToken($failed);
        }
    }

    /**
     * Clears a PreAuthenticatedToken for this provider (if present)
     *
     * @param AuthenticationException $exception
     */
    private function clearToken(AuthenticationException $exception)
    {
        $token = $this->securityContext->getToken();
        if ($token instanceof PreAuthenticatedToken && $this->providerKey === $token->getProviderKey()) {
            $this->securityContext->setToken(null);

            if (null !== $this->logger) {
                $this->logger->info(sprintf("Cleared security context due to exception: %s", $exception->getMessage()));
            }
        }
    }

    /**
     * Gets the user and credentials from the Request.
     *
     * @param Request $request A Request instance
     *
     * @return array An array composed of the user and the credentials
     */
    abstract protected function getPreAuthenticatedData(Request $request);
}
PK��Zn��LSymfony/Component/Security/Http/Firewall/SimplePreAuthenticationListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Firewall;

use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Authentication\SimplePreAuthenticatorInterface;
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;

/**
 * SimplePreAuthenticationListener implements simple proxying to an authenticator.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class SimplePreAuthenticationListener implements ListenerInterface
{
    private $securityContext;
    private $authenticationManager;
    private $providerKey;
    private $simpleAuthenticator;
    private $logger;

    /**
     * Constructor.
     *
     * @param SecurityContextInterface         $securityContext       A SecurityContext instance
     * @param AuthenticationManagerInterface   $authenticationManager An AuthenticationManagerInterface instance
     * @param string                           $providerKey
     * @param SimplePreAuthenticatorInterface  $simpleAuthenticator   A SimplePreAuthenticatorInterface instance
     * @param LoggerInterface                  $logger                A LoggerInterface instance
     */
    public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, $providerKey, SimplePreAuthenticatorInterface $simpleAuthenticator, LoggerInterface $logger = null)
    {
        if (empty($providerKey)) {
            throw new \InvalidArgumentException('$providerKey must not be empty.');
        }

        $this->securityContext = $securityContext;
        $this->authenticationManager = $authenticationManager;
        $this->providerKey = $providerKey;
        $this->simpleAuthenticator = $simpleAuthenticator;
        $this->logger = $logger;
    }

    /**
     * Handles basic authentication.
     *
     * @param GetResponseEvent $event A GetResponseEvent instance
     */
    public function handle(GetResponseEvent $event)
    {
        $request = $event->getRequest();

        if (null !== $this->logger) {
            $this->logger->info(sprintf('Attempting simple pre-authorization %s', $this->providerKey));
        }

        if (null !== $this->securityContext->getToken() && !$this->securityContext->getToken() instanceof AnonymousToken) {
            return;
        }

        try {
            $token = $this->simpleAuthenticator->createToken($request, $this->providerKey);
            $token = $this->authenticationManager->authenticate($token);
            $this->securityContext->setToken($token);
        } catch (AuthenticationException $e) {
            $this->securityContext->setToken(null);

            if (null !== $this->logger) {
                $this->logger->info(sprintf('Authentication request failed: %s', $e->getMessage()));
            }

            if ($this->simpleAuthenticator instanceof AuthenticationFailureHandlerInterface) {
                $response = $this->simpleAuthenticator->onAuthenticationFailure($request, $e);
                if ($response instanceof Response) {
                    $event->setResponse($response);
                } elseif (null !== $response) {
                    throw new \UnexpectedValueException(sprintf('The %s::onAuthenticationFailure method must return null or a Response object', get_class($this->simpleAuthenticator)));
                }
            }

            return;
        }

        if ($this->simpleAuthenticator instanceof AuthenticationSuccessHandlerInterface) {
            $response = $this->simpleAuthenticator->onAuthenticationSuccess($request, $token);
            if ($response instanceof Response) {
                $event->setResponse($response);
            } elseif (null !== $response) {
                throw new \UnexpectedValueException(sprintf('The %s::onAuthenticationSuccess method must return null or a Response object', get_class($this->simpleAuthenticator)));
            }
        }
    }
}
PK��Z�&!�
�
HSymfony/Component/Security/Http/Firewall/BasicAuthenticationListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Firewall;

use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\AuthenticationException;

/**
 * BasicAuthenticationListener implements Basic HTTP authentication.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class BasicAuthenticationListener implements ListenerInterface
{
    private $securityContext;
    private $authenticationManager;
    private $providerKey;
    private $authenticationEntryPoint;
    private $logger;
    private $ignoreFailure;

    public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, $providerKey, AuthenticationEntryPointInterface $authenticationEntryPoint, LoggerInterface $logger = null)
    {
        if (empty($providerKey)) {
            throw new \InvalidArgumentException('$providerKey must not be empty.');
        }

        $this->securityContext = $securityContext;
        $this->authenticationManager = $authenticationManager;
        $this->providerKey = $providerKey;
        $this->authenticationEntryPoint = $authenticationEntryPoint;
        $this->logger = $logger;
        $this->ignoreFailure = false;
    }

    /**
     * Handles basic authentication.
     *
     * @param GetResponseEvent $event A GetResponseEvent instance
     */
    public function handle(GetResponseEvent $event)
    {
        $request = $event->getRequest();

        if (false === $username = $request->headers->get('PHP_AUTH_USER', false)) {
            return;
        }

        if (null !== $token = $this->securityContext->getToken()) {
            if ($token instanceof UsernamePasswordToken && $token->isAuthenticated() && $token->getUsername() === $username) {
                return;
            }
        }

        if (null !== $this->logger) {
            $this->logger->info(sprintf('Basic Authentication Authorization header found for user "%s"', $username));
        }

        try {
            $token = $this->authenticationManager->authenticate(new UsernamePasswordToken($username, $request->headers->get('PHP_AUTH_PW'), $this->providerKey));
            $this->securityContext->setToken($token);
        } catch (AuthenticationException $failed) {
            $token = $this->securityContext->getToken();
            if ($token instanceof UsernamePasswordToken && $this->providerKey === $token->getProviderKey()) {
                $this->securityContext->setToken(null);
            }

            if (null !== $this->logger) {
                $this->logger->info(sprintf('Authentication request failed for user "%s": %s', $username, $failed->getMessage()));
            }

            if ($this->ignoreFailure) {
                return;
            }

            $event->setResponse($this->authenticationEntryPoint->start($request, $failed));
        }
    }
}
PK��Z2j���-Symfony/Component/Security/Http/AccessMap.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http;

use Symfony\Component\HttpFoundation\RequestMatcherInterface;
use Symfony\Component\HttpFoundation\Request;

/**
 * AccessMap allows configuration of different access control rules for
 * specific parts of the website.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class AccessMap implements AccessMapInterface
{
    private $map = array();

    /**
     * Constructor.
     *
     * @param RequestMatcherInterface $requestMatcher A RequestMatcherInterface instance
     * @param array                   $attributes     An array of attributes to pass to the access decision manager (like roles)
     * @param string|null             $channel        The channel to enforce (http, https, or null)
     */
    public function add(RequestMatcherInterface $requestMatcher, array $attributes = array(), $channel = null)
    {
        $this->map[] = array($requestMatcher, $attributes, $channel);
    }

    /**
     * {@inheritDoc}
     */
    public function getPatterns(Request $request)
    {
        foreach ($this->map as $elements) {
            if (null === $elements[0] || $elements[0]->matches($request)) {
                return array($elements[1], $elements[2]);
            }
        }

        return array(null, null);
    }
}
PK��Z/�``6Symfony/Component/Security/Http/AccessMapInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http;

use Symfony\Component\HttpFoundation\Request;

/**
 * AccessMap allows configuration of different access control rules for
 * specific parts of the website.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Kris Wallsmith <kris@symfony.com>
 */
interface AccessMapInterface
{
    /**
     * Returns security attributes and required channel for the supplied request.
     *
     * @param Request $request The current request
     *
     * @return array A tuple of security attributes and the required channel
     */
    public function getPatterns(Request $request);
}
PK��Z��\\��8Symfony/Component/Security/Http/FirewallMapInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http;

use Symfony\Component\HttpFoundation\Request;

/**
 * This interface must be implemented by firewall maps.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface FirewallMapInterface
{
    /**
     * Returns the authentication listeners, and the exception listener to use
     * for the given request.
     *
     * If there are no authentication listeners, the first inner array must be
     * empty.
     *
     * If there is no exception listener, the second element of the outer array
     * must be null.
     *
     * @param Request $request
     *
     * @return array of the format array(array(AuthenticationListener), ExceptionListener)
     */
    public function getListeners(Request $request);
}
PK��Z	z��JSymfony/Component/Security/Http/RememberMe/RememberMeServicesInterface.phpnu�[���<?php
namespace Symfony\Component\Security\Http\RememberMe;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Interface that needs to be implemented by classes which provide remember-me
 * capabilities.
 *
 * We provide two implementations out-of-the-box:
 * - TokenBasedRememberMeServices (does not require a TokenProvider)
 * - PersistentTokenBasedRememberMeServices (requires a TokenProvider)
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface RememberMeServicesInterface
{
    /**
     * This attribute name can be used by the implementation if it needs to set
     * a cookie on the Request when there is no actual Response, yet.
     *
     * @var string
     */
    const COOKIE_ATTR_NAME = '_security_remember_me_cookie';

    /**
     * This method will be called whenever the SecurityContext does not contain
     * an TokenInterface object and the framework wishes to provide an implementation
     * with an opportunity to authenticate the request using remember-me capabilities.
     *
     * No attempt whatsoever is made to determine whether the browser has requested
     * remember-me services or presented a valid cookie. Any and all such determinations
     * are left to the implementation of this method.
     *
     * If a browser has presented an unauthorised cookie for whatever reason,
     * make sure to throw an AuthenticationException as this will consequentially
     * result in a call to loginFail() and therefore an invalidation of the cookie.
     *
     * @param Request $request
     *
     * @return TokenInterface
     */
    public function autoLogin(Request $request);

    /**
     * Called whenever an interactive authentication attempt was made, but the
     * credentials supplied by the user were missing or otherwise invalid.
     *
     * This method needs to take care of invalidating the cookie.
     *
     * @param Request $request
     */
    public function loginFail(Request $request);

    /**
     * Called whenever an interactive authentication attempt is successful
     * (e.g. a form login).
     *
     * An implementation may always set a remember-me cookie in the Response,
     * although this is not recommended.
     *
     * Instead, implementations should typically look for a request parameter
     * (such as a HTTP POST parameter) that indicates the browser has explicitly
     * requested for the authentication to be remembered.
     *
     * @param Request        $request
     * @param Response       $response
     * @param TokenInterface $token
     */
    public function loginSuccess(Request $request, Response $response, TokenInterface $token);
}
PK��ZP�ڕ��?Symfony/Component/Security/Http/RememberMe/ResponseListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\RememberMe;

use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Adds remember-me cookies to the Response.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ResponseListener implements EventSubscriberInterface
{
    /**
     * @param FilterResponseEvent $event
     */
    public function onKernelResponse(FilterResponseEvent $event)
    {
        $request = $event->getRequest();
        $response = $event->getResponse();

        if ($request->attributes->has(RememberMeServicesInterface::COOKIE_ATTR_NAME)) {
            $response->headers->setCookie($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME));
        }
    }

    /**
     * {@inheritDoc}
     */
    public static function getSubscribedEvents()
    {
        return array(KernelEvents::RESPONSE => 'onKernelResponse');
    }
}
PK��Z���s44USymfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\RememberMe;

use Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\CookieTheftException;
use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Util\SecureRandomInterface;
use Psr\Log\LoggerInterface;

/**
 * Concrete implementation of the RememberMeServicesInterface which needs
 * an implementation of TokenProviderInterface for providing remember-me
 * capabilities.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class PersistentTokenBasedRememberMeServices extends AbstractRememberMeServices
{
    private $tokenProvider;
    private $secureRandom;

    /**
     * Constructor.
     *
     * @param array                 $userProviders
     * @param string                $key
     * @param string                $providerKey
     * @param array                 $options
     * @param LoggerInterface       $logger
     * @param SecureRandomInterface $secureRandom
     */
    public function __construct(array $userProviders, $key, $providerKey, array $options = array(), LoggerInterface $logger = null, SecureRandomInterface $secureRandom)
    {
        parent::__construct($userProviders, $key, $providerKey, $options, $logger);

        $this->secureRandom = $secureRandom;
    }

    /**
     * Sets the token provider
     *
     * @param TokenProviderInterface $tokenProvider
     */
    public function setTokenProvider(TokenProviderInterface $tokenProvider)
    {
        $this->tokenProvider = $tokenProvider;
    }

    /**
     * {@inheritDoc}
     */
    protected function cancelCookie(Request $request)
    {
        // Delete cookie on the client
        parent::cancelCookie($request);

        // Delete cookie from the tokenProvider
        if (null !== ($cookie = $request->cookies->get($this->options['name']))
            && count($parts = $this->decodeCookie($cookie)) === 2
        ) {
            list($series, $tokenValue) = $parts;
            $this->tokenProvider->deleteTokenBySeries($series);
        }
    }

    /**
     * {@inheritDoc}
     */
    protected function processAutoLoginCookie(array $cookieParts, Request $request)
    {
        if (count($cookieParts) !== 2) {
            throw new AuthenticationException('The cookie is invalid.');
        }

        list($series, $tokenValue) = $cookieParts;
        $persistentToken = $this->tokenProvider->loadTokenBySeries($series);

        if ($persistentToken->getTokenValue() !== $tokenValue) {
            throw new CookieTheftException('This token was already used. The account is possibly compromised.');
        }

        if ($persistentToken->getLastUsed()->getTimestamp() + $this->options['lifetime'] < time()) {
            throw new AuthenticationException('The cookie has expired.');
        }

        $series = $persistentToken->getSeries();
        $tokenValue = base64_encode($this->secureRandom->nextBytes(64));
        $this->tokenProvider->updateToken($series, $tokenValue, new \DateTime());
        $request->attributes->set(self::COOKIE_ATTR_NAME,
            new Cookie(
                $this->options['name'],
                $this->encodeCookie(array($series, $tokenValue)),
                time() + $this->options['lifetime'],
                $this->options['path'],
                $this->options['domain'],
                $this->options['secure'],
                $this->options['httponly']
            )
        );

        return $this->getUserProvider($persistentToken->getClass())->loadUserByUsername($persistentToken->getUsername());
    }

    /**
     * {@inheritDoc}
     */
    protected function onLoginSuccess(Request $request, Response $response, TokenInterface $token)
    {
        $series = base64_encode($this->secureRandom->nextBytes(64));
        $tokenValue = base64_encode($this->secureRandom->nextBytes(64));

        $this->tokenProvider->createNewToken(
            new PersistentToken(
                get_class($user = $token->getUser()),
                $user->getUsername(),
                $series,
                $tokenValue,
                new \DateTime()
            )
        );

        $response->headers->setCookie(
            new Cookie(
                $this->options['name'],
                $this->encodeCookie(array($series, $tokenValue)),
                time() + $this->options['lifetime'],
                $this->options['path'],
                $this->options['domain'],
                $this->options['secure'],
                $this->options['httponly']
            )
        );
    }
}
PK��Z�*�b�&�&ISymfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\RememberMe;

use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken;
use Symfony\Component\Security\Http\Logout\LogoutHandlerInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\CookieTheftException;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Cookie;
use Psr\Log\LoggerInterface;

/**
 * Base class implementing the RememberMeServicesInterface
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
abstract class AbstractRememberMeServices implements RememberMeServicesInterface, LogoutHandlerInterface
{
    const COOKIE_DELIMITER = ':';

    protected $logger;
    protected $options;
    private $providerKey;
    private $key;
    private $userProviders;

    /**
     * Constructor.
     *
     * @param array           $userProviders
     * @param string          $key
     * @param string          $providerKey
     * @param array           $options
     * @param LoggerInterface $logger
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(array $userProviders, $key, $providerKey, array $options = array(), LoggerInterface $logger = null)
    {
        if (empty($key)) {
            throw new \InvalidArgumentException('$key must not be empty.');
        }
        if (empty($providerKey)) {
            throw new \InvalidArgumentException('$providerKey must not be empty.');
        }
        if (0 === count($userProviders)) {
            throw new \InvalidArgumentException('You must provide at least one user provider.');
        }

        $this->userProviders = $userProviders;
        $this->key = $key;
        $this->providerKey = $providerKey;
        $this->options = $options;
        $this->logger = $logger;
    }

    /**
     * Returns the parameter that is used for checking whether remember-me
     * services have been requested.
     *
     * @return string
     */
    public function getRememberMeParameter()
    {
        return $this->options['remember_me_parameter'];
    }

    /**
     * @return string
     */
    public function getKey()
    {
        return $this->key;
    }

    /**
     * Implementation of RememberMeServicesInterface. Detects whether a remember-me
     * cookie was set, decodes it, and hands it to subclasses for further processing.
     *
     * @param Request $request
     *
     * @return TokenInterface|null
     *
     * @throws CookieTheftException
     * @throws \RuntimeException
     */
    final public function autoLogin(Request $request)
    {
        if (null === $cookie = $request->cookies->get($this->options['name'])) {
            return;
        }

        if (null !== $this->logger) {
            $this->logger->debug('Remember-me cookie detected.');
        }

        $cookieParts = $this->decodeCookie($cookie);

        try {
            $user = $this->processAutoLoginCookie($cookieParts, $request);

            if (!$user instanceof UserInterface) {
                throw new \RuntimeException('processAutoLoginCookie() must return a UserInterface implementation.');
            }

            if (null !== $this->logger) {
                $this->logger->info('Remember-me cookie accepted.');
            }

            return new RememberMeToken($user, $this->providerKey, $this->key);
        } catch (CookieTheftException $theft) {
            $this->cancelCookie($request);

            throw $theft;
        } catch (UsernameNotFoundException $notFound) {
            if (null !== $this->logger) {
                $this->logger->info('User for remember-me cookie not found.');
            }
        } catch (UnsupportedUserException $unSupported) {
            if (null !== $this->logger) {
                $this->logger->warning('User class for remember-me cookie not supported.');
            }
        } catch (AuthenticationException $invalid) {
            if (null !== $this->logger) {
                $this->logger->debug('Remember-Me authentication failed: '.$invalid->getMessage());
            }
        }

        $this->cancelCookie($request);

        return null;
    }

    /**
     * Implementation for LogoutHandlerInterface. Deletes the cookie.
     *
     * @param Request        $request
     * @param Response       $response
     * @param TokenInterface $token
     */
    public function logout(Request $request, Response $response, TokenInterface $token)
    {
        $this->cancelCookie($request);
    }

    /**
     * Implementation for RememberMeServicesInterface. Deletes the cookie when
     * an attempted authentication fails.
     *
     * @param Request $request
     */
    final public function loginFail(Request $request)
    {
        $this->cancelCookie($request);
        $this->onLoginFail($request);
    }

    /**
     * Implementation for RememberMeServicesInterface. This is called when an
     * authentication is successful.
     *
     * @param Request        $request
     * @param Response       $response
     * @param TokenInterface $token    The token that resulted in a successful authentication
     */
    final public function loginSuccess(Request $request, Response $response, TokenInterface $token)
    {
        // Make sure any old remember-me cookies are cancelled
        $this->cancelCookie($request);

        if (!$token->getUser() instanceof UserInterface) {
            if (null !== $this->logger) {
                $this->logger->debug('Remember-me ignores token since it does not contain a UserInterface implementation.');
            }

            return;
        }

        if (!$this->isRememberMeRequested($request)) {
            if (null !== $this->logger) {
                $this->logger->debug('Remember-me was not requested.');
            }

            return;
        }

        if (null !== $this->logger) {
            $this->logger->debug('Remember-me was requested; setting cookie.');
        }

        // Remove attribute from request that sets a NULL cookie.
        // It was set by $this->cancelCookie()
        // (cancelCookie does other things too for some RememberMeServices
        // so we should still call it at the start of this method)
        $request->attributes->remove(self::COOKIE_ATTR_NAME);

        $this->onLoginSuccess($request, $response, $token);
    }

    /**
     * Subclasses should validate the cookie and do any additional processing
     * that is required. This is called from autoLogin().
     *
     * @param array   $cookieParts
     * @param Request $request
     *
     * @return TokenInterface
     */
    abstract protected function processAutoLoginCookie(array $cookieParts, Request $request);

    /**
     * @param Request $request
     */
    protected function onLoginFail(Request $request)
    {
    }

    /**
     * This is called after a user has been logged in successfully, and has
     * requested remember-me capabilities. The implementation usually sets a
     * cookie and possibly stores a persistent record of it.
     *
     * @param Request        $request
     * @param Response       $response
     * @param TokenInterface $token
     */
    abstract protected function onLoginSuccess(Request $request, Response $response, TokenInterface $token);

    final protected function getUserProvider($class)
    {
        foreach ($this->userProviders as $provider) {
            if ($provider->supportsClass($class)) {
                return $provider;
            }
        }

        throw new UnsupportedUserException(sprintf('There is no user provider that supports class "%s".', $class));
    }

    /**
     * Decodes the raw cookie value
     *
     * @param string $rawCookie
     *
     * @return array
     */
    protected function decodeCookie($rawCookie)
    {
        return explode(self::COOKIE_DELIMITER, base64_decode($rawCookie));
    }

    /**
     * Encodes the cookie parts
     *
     * @param array $cookieParts
     *
     * @return string
     */
    protected function encodeCookie(array $cookieParts)
    {
        return base64_encode(implode(self::COOKIE_DELIMITER, $cookieParts));
    }

    /**
     * Deletes the remember-me cookie
     *
     * @param Request $request
     */
    protected function cancelCookie(Request $request)
    {
        if (null !== $this->logger) {
            $this->logger->debug(sprintf('Clearing remember-me cookie "%s"', $this->options['name']));
        }

        $request->attributes->set(self::COOKIE_ATTR_NAME, new Cookie($this->options['name'], null, 1, $this->options['path'], $this->options['domain']));
    }

    /**
     * Checks whether remember-me capabilities were requested
     *
     * @param Request $request
     *
     * @return Boolean
     */
    protected function isRememberMeRequested(Request $request)
    {
        if (true === $this->options['always_remember_me']) {
            return true;
        }

        $parameter = $request->get($this->options['remember_me_parameter'], null, true);

        if ($parameter === null && null !== $this->logger) {
            $this->logger->debug(sprintf('Did not send remember-me cookie (remember-me parameter "%s" was not sent).', $this->options['remember_me_parameter']));
        }

        return $parameter === 'true' || $parameter === 'on' || $parameter === '1' || $parameter === 'yes';
    }
}
PK��Z�a�$��KSymfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\RememberMe;

use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserInterface;

/**
 * Concrete implementation of the RememberMeServicesInterface providing
 * remember-me capabilities without requiring a TokenProvider.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class TokenBasedRememberMeServices extends AbstractRememberMeServices
{
    /**
     * {@inheritDoc}
     */
    protected function processAutoLoginCookie(array $cookieParts, Request $request)
    {
        if (count($cookieParts) !== 4) {
            throw new AuthenticationException('The cookie is invalid.');
        }

        list($class, $username, $expires, $hash) = $cookieParts;
        if (false === $username = base64_decode($username, true)) {
            throw new AuthenticationException('$username contains a character from outside the base64 alphabet.');
        }
        try {
            $user = $this->getUserProvider($class)->loadUserByUsername($username);
        } catch (\Exception $ex) {
            if (!$ex instanceof AuthenticationException) {
                $ex = new AuthenticationException($ex->getMessage(), $ex->getCode(), $ex);
            }

            throw $ex;
        }

        if (!$user instanceof UserInterface) {
            throw new \RuntimeException(sprintf('The UserProviderInterface implementation must return an instance of UserInterface, but returned "%s".', get_class($user)));
        }

        if (true !== $this->compareHashes($hash, $this->generateCookieHash($class, $username, $expires, $user->getPassword()))) {
            throw new AuthenticationException('The cookie\'s hash is invalid.');
        }

        if ($expires < time()) {
            throw new AuthenticationException('The cookie has expired.');
        }

        return $user;
    }

    /**
     * Compares two hashes using a constant-time algorithm to avoid (remote)
     * timing attacks.
     *
     * This is the same implementation as used in the BasePasswordEncoder.
     *
     * @param string $hash1 The first hash
     * @param string $hash2 The second hash
     *
     * @return Boolean true if the two hashes are the same, false otherwise
     */
    private function compareHashes($hash1, $hash2)
    {
        if (strlen($hash1) !== $c = strlen($hash2)) {
            return false;
        }

        $result = 0;
        for ($i = 0; $i < $c; $i++) {
            $result |= ord($hash1[$i]) ^ ord($hash2[$i]);
        }

        return 0 === $result;
    }

    /**
     * {@inheritDoc}
     */
    protected function onLoginSuccess(Request $request, Response $response, TokenInterface $token)
    {
        $user = $token->getUser();
        $expires = time() + $this->options['lifetime'];
        $value = $this->generateCookieValue(get_class($user), $user->getUsername(), $expires, $user->getPassword());

        $response->headers->setCookie(
            new Cookie(
                $this->options['name'],
                $value,
                $expires,
                $this->options['path'],
                $this->options['domain'],
                $this->options['secure'],
                $this->options['httponly']
            )
        );
    }

    /**
     * Generates the cookie value.
     *
     * @param string  $class
     * @param string  $username The username
     * @param integer $expires  The Unix timestamp when the cookie expires
     * @param string  $password The encoded password
     *
     * @throws \RuntimeException if username contains invalid chars
     *
     * @return string
     */
    protected function generateCookieValue($class, $username, $expires, $password)
    {
        return $this->encodeCookie(array(
            $class,
            base64_encode($username),
            $expires,
            $this->generateCookieHash($class, $username, $expires, $password)
        ));
    }

    /**
     * Generates a hash for the cookie to ensure it is not being tempered with
     *
     * @param string  $class
     * @param string  $username The username
     * @param integer $expires  The Unix timestamp when the cookie expires
     * @param string  $password The encoded password
     *
     * @throws \RuntimeException when the private key is empty
     *
     * @return string
     */
    protected function generateCookieHash($class, $username, $expires, $password)
    {
        return hash_hmac('sha256', $class.$username.$expires.$password, $this->getKey());
    }
}
PK��Z:�&�GGRSymfony/Component/Security/Http/Session/SessionAuthenticationStrategyInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Session;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\HttpFoundation\Request;

/**
 * SessionAuthenticationStrategyInterface
 *
 * Implementation are responsible for updating the session after an interactive
 * authentication attempt was successful.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface SessionAuthenticationStrategyInterface
{
    /**
     * This performs any necessary changes to the session.
     *
     * This method is called before the SecurityContext is populated with a
     * Token, and only by classes inheriting from AbstractAuthenticationListener.
     *
     * @param Request        $request
     * @param TokenInterface $token
     */
    public function onAuthentication(Request $request, TokenInterface $token);
}
PK��Z��La[[ISymfony/Component/Security/Http/Session/SessionAuthenticationStrategy.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Session;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\HttpFoundation\Request;

/**
 * The default session strategy implementation.
 *
 * Supports the following strategies:
 * NONE: the session is not changed
 * MIGRATE: the session id is updated, attributes are kept
 * INVALIDATE: the session id is updated, attributes are lost
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class SessionAuthenticationStrategy implements SessionAuthenticationStrategyInterface
{
    const NONE         = 'none';
    const MIGRATE      = 'migrate';
    const INVALIDATE   = 'invalidate';

    private $strategy;

    public function __construct($strategy)
    {
        $this->strategy = $strategy;
    }

    /**
     * {@inheritDoc}
     */
    public function onAuthentication(Request $request, TokenInterface $token)
    {
        switch ($this->strategy) {
            case self::NONE:
                return;

            case self::MIGRATE:
                $request->getSession()->migrate();

                return;

            case self::INVALIDATE:
                $request->getSession()->invalidate();

                return;

            default:
                throw new \RuntimeException(sprintf('Invalid session authentication strategy "%s"', $this->strategy));
        }
    }
}
PK��Za7�llFSymfony/Component/Security/Http/Logout/DefaultLogoutSuccessHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Logout;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Http\HttpUtils;

/**
 * Default logout success handler will redirect users to a configured path.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class DefaultLogoutSuccessHandler implements LogoutSuccessHandlerInterface
{
    protected $httpUtils;
    protected $targetUrl;

    /**
     * @param HttpUtils $httpUtils
     * @param string    $targetUrl
     */
    public function __construct(HttpUtils $httpUtils, $targetUrl = '/')
    {
        $this->httpUtils = $httpUtils;

        $this->targetUrl = $targetUrl;
    }

    /**
     * {@inheritDoc}
     */
    public function onLogoutSuccess(Request $request)
    {
        return $this->httpUtils->createRedirectResponse($request, $this->targetUrl);
    }
}
PK��Z1��d��HSymfony/Component/Security/Http/Logout/LogoutSuccessHandlerInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Logout;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * LogoutSuccesshandlerInterface.
 *
 * In contrast to the LogoutHandlerInterface, this interface can return a response
 * which is then used instead of the default behavior.
 *
 * If you want to only perform some logout related clean-up task, use the
 * LogoutHandlerInterface instead.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface LogoutSuccessHandlerInterface
{
    /**
     * Creates a Response object to send upon a successful logout.
     *
     * @param Request $request
     *
     * @return Response never null
     */
    public function onLogoutSuccess(Request $request);
}
PK��Z\ü���?Symfony/Component/Security/Http/Logout/SessionLogoutHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Logout;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;

/**
 * Handler for clearing invalidating the current session.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class SessionLogoutHandler implements LogoutHandlerInterface
{
    /**
     * Invalidate the current session
     *
     * @param Request        $request
     * @param Response       $response
     * @param TokenInterface $token
     */
    public function logout(Request $request, Response $response, TokenInterface $token)
    {
        $request->getSession()->invalidate();
    }
}
PK��Z6O����ASymfony/Component/Security/Http/Logout/LogoutHandlerInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Logout;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;

/**
 * Interface that needs to be implemented by LogoutHandlers.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface LogoutHandlerInterface
{
    /**
     * This method is called by the LogoutListener when a user has requested
     * to be logged out. Usually, you would unset session variables, or remove
     * cookies, etc.
     *
     * @param Request        $request
     * @param Response       $response
     * @param TokenInterface $token
     */
    public function logout(Request $request, Response $response, TokenInterface $token);
}
PK��Z�ddFSymfony/Component/Security/Http/Logout/CookieClearingLogoutHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Logout;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;

/**
 * This handler clears the passed cookies when a user logs out.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class CookieClearingLogoutHandler implements LogoutHandlerInterface
{
    private $cookies;

    /**
     * Constructor.
     *
     * @param array $cookies An array of cookie names to unset
     */
    public function __construct(array $cookies)
    {
        $this->cookies = $cookies;
    }

    /**
     * Implementation for the LogoutHandlerInterface. Deletes all requested cookies.
     *
     * @param Request        $request
     * @param Response       $response
     * @param TokenInterface $token
     */
    public function logout(Request $request, Response $response, TokenInterface $token)
    {
        foreach ($this->cookies as $cookieName => $cookieData) {
            $response->headers->clearCookie($cookieName, $cookieData['path'], $cookieData['domain']);
        }
    }
}
PK��Z/ sG��2Symfony/Component/Security/Http/SecurityEvents.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http;

final class SecurityEvents
{
    /**
     * The INTERACTIVE_LOGIN event occurs after a user is logged in
     * interactively for authentication based on http, cookies or X509.
     *
     * The event listener method receives a
     * Symfony\Component\Security\Http\Event\InteractiveLoginEvent instance.
     *
     * @var string
     */
    const INTERACTIVE_LOGIN = 'security.interactive_login';

    /**
     * The SWITCH_USER event occurs before switch to another user and
     * before exit from an already switched user.
     *
     * The event listener method receives a
     * Symfony\Component\Security\Http\Event\SwitchUserEvent instance.
     *
     * @var string
     */
    const SWITCH_USER = 'security.switch_user';
}
PK��Z�NA��XSymfony/Component/Security/Http/Authentication/AuthenticationSuccessHandlerInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Authentication;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * Interface for a custom authentication success handler
 *
 * If you want to customize the success handling process, instead of
 * overwriting the respective listener globally, you can set a custom success
 * handler which implements this interface.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface AuthenticationSuccessHandlerInterface
{
    /**
     * This is called when an interactive authentication attempt succeeds. This
     * is called by authentication listeners inheriting from
     * AbstractAuthenticationListener.
     *
     * @param Request        $request
     * @param TokenInterface $token
     *
     * @return Response never null
     */
    public function onAuthenticationSuccess(Request $request, TokenInterface $token);
}
PK��Z������VSymfony/Component/Security/Http/Authentication/DefaultAuthenticationFailureHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Authentication;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Http\HttpUtils;

/**
 * Class with the default authentication failure handling logic.
 *
 * Can be optionally be extended from by the developer to alter the behaviour
 * while keeping the default behaviour.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class DefaultAuthenticationFailureHandler implements AuthenticationFailureHandlerInterface
{
    protected $httpKernel;
    protected $httpUtils;
    protected $logger;
    protected $options;

    /**
     * Constructor.
     *
     * @param HttpKernelInterface $httpKernel
     * @param HttpUtils           $httpUtils
     * @param array               $options    Options for processing a failed authentication attempt.
     * @param LoggerInterface     $logger     Optional logger
     */
    public function __construct(HttpKernelInterface $httpKernel, HttpUtils $httpUtils, array $options, LoggerInterface $logger = null)
    {
        $this->httpKernel = $httpKernel;
        $this->httpUtils  = $httpUtils;
        $this->logger     = $logger;

        $this->options = array_merge(array(
            'failure_path'           => null,
            'failure_forward'        => false,
            'login_path'             => '/login',
            'failure_path_parameter' => '_failure_path'
        ), $options);
    }

    /**
     * {@inheritDoc}
     */
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
    {
        if ($failureUrl = $request->get($this->options['failure_path_parameter'], null, true)) {
             $this->options['failure_path'] = $failureUrl;
        }

        if (null === $this->options['failure_path']) {
            $this->options['failure_path'] = $this->options['login_path'];
        }

        if ($this->options['failure_forward']) {
            if (null !== $this->logger) {
                $this->logger->debug(sprintf('Forwarding to %s', $this->options['failure_path']));
            }

            $subRequest = $this->httpUtils->createRequest($request, $this->options['failure_path']);
            $subRequest->attributes->set(SecurityContextInterface::AUTHENTICATION_ERROR, $exception);

            return $this->httpKernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
        }

        if (null !== $this->logger) {
            $this->logger->debug(sprintf('Redirecting to %s', $this->options['failure_path']));
        }

        $request->getSession()->set(SecurityContextInterface::AUTHENTICATION_ERROR, $exception);

        return $this->httpUtils->createRedirectResponse($request, $this->options['failure_path']);
    }
}
PK��Z��H]XSymfony/Component/Security/Http/Authentication/AuthenticationFailureHandlerInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Authentication;

use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * Interface for custom authentication failure handlers.
 *
 * If you want to customize the failure handling process, instead of
 * overwriting the respective listener globally, you can set a custom failure
 * handler which implements this interface.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface AuthenticationFailureHandlerInterface
{
    /**
     * This is called when an interactive authentication attempt fails. This is
     * called by authentication listeners inheriting from
     * AbstractAuthenticationListener.
     *
     * @param Request                 $request
     * @param AuthenticationException $exception
     *
     * @return Response The response to return, never null
     */
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception);
}
PK��Z�xGAAVSymfony/Component/Security/Http/Authentication/DefaultAuthenticationSuccessHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Authentication;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Http\HttpUtils;

/**
 * Class with the default authentication success handling logic.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class DefaultAuthenticationSuccessHandler implements AuthenticationSuccessHandlerInterface
{
    protected $httpUtils;
    protected $options;
    protected $providerKey;

    /**
     * Constructor.
     *
     * @param HttpUtils $httpUtils
     * @param array     $options   Options for processing a successful authentication attempt.
     */
    public function __construct(HttpUtils $httpUtils, array $options)
    {
        $this->httpUtils   = $httpUtils;

        $this->options = array_merge(array(
            'always_use_default_target_path' => false,
            'default_target_path'            => '/',
            'login_path'                     => '/login',
            'target_path_parameter'          => '_target_path',
            'use_referer'                    => false,
        ), $options);
    }

    /**
     * {@inheritDoc}
     */
    public function onAuthenticationSuccess(Request $request, TokenInterface $token)
    {
        return $this->httpUtils->createRedirectResponse($request, $this->determineTargetUrl($request));
    }

    /**
     * Get the provider key.
     *
     * @return string
     */
    public function getProviderKey()
    {
        return $this->providerKey;
    }

    /**
     * Set the provider key.
     *
     * @param string $providerKey
     */
    public function setProviderKey($providerKey)
    {
        $this->providerKey = $providerKey;
    }

    /**
     * Builds the target URL according to the defined options.
     *
     * @param Request $request
     *
     * @return string
     */
    protected function determineTargetUrl(Request $request)
    {
        if ($this->options['always_use_default_target_path']) {
            return $this->options['default_target_path'];
        }

        if ($targetUrl = $request->get($this->options['target_path_parameter'], null, true)) {
            return $targetUrl;
        }

        if (null !== $this->providerKey && $targetUrl = $request->getSession()->get('_security.'.$this->providerKey.'.target_path')) {
            $request->getSession()->remove('_security.'.$this->providerKey.'.target_path');

            return $targetUrl;
        }

        if ($this->options['use_referer'] && ($targetUrl = $request->headers->get('Referer')) && $targetUrl !== $this->httpUtils->generateUri($request, $this->options['login_path'])) {
            return $targetUrl;
        }

        return $this->options['default_target_path'];
    }
}
PK��ZAH\ݞ�NSymfony/Component/Security/Http/Authentication/SimpleAuthenticationHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Authentication;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Psr\Log\LoggerInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface;

/**
 * Class to proxy authentication success/failure handlers
 *
 * Events are sent to the SimpleAuthenticatorInterface if it implements
 * the right interface, otherwise (or if it fails to return a Response)
 * the default handlers are triggered.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class SimpleAuthenticationHandler implements AuthenticationFailureHandlerInterface, AuthenticationSuccessHandlerInterface
{
    protected $successHandler;
    protected $failureHandler;
    protected $simpleAuthenticator;
    protected $logger;

    /**
     * Constructor.
     *
     * @param SimpleAuthenticatorInterface          $authenticator  SimpleAuthenticatorInterface instance
     * @param AuthenticationSuccessHandlerInterface $successHandler Default success handler
     * @param AuthenticationFailureHandlerInterface $failureHandler Default failure handler
     * @param LoggerInterface                       $logger         Optional logger
     */
    public function __construct(SimpleAuthenticatorInterface $authenticator, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, LoggerInterface $logger = null)
    {
        $this->simpleAuthenticator = $authenticator;
        $this->successHandler = $successHandler;
        $this->failureHandler = $failureHandler;
        $this->logger = $logger;
    }

    /**
     * {@inheritDoc}
     */
    public function onAuthenticationSuccess(Request $request, TokenInterface $token)
    {
        if ($this->simpleAuthenticator instanceof AuthenticationSuccessHandlerInterface) {
            if ($this->logger) {
                $this->logger->debug(sprintf('Using the %s object as authentication success handler', get_class($this->simpleAuthenticator)));
            }

            $response = $this->simpleAuthenticator->onAuthenticationSuccess($request, $token);
            if ($response instanceof Response) {
                return $response;
            }

            if (null !== $response) {
                throw new \UnexpectedValueException(sprintf('The %s::onAuthenticationSuccess method must return null to use the default success handler, or a Response object', get_class($this->simpleAuthenticator)));
            }
        }

        if ($this->logger) {
            $this->logger->debug('Fallback to the default authentication success handler');
        }

        return $this->successHandler->onAuthenticationSuccess($request, $token);
    }

    /**
     * {@inheritDoc}
     */
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
    {
        if ($this->simpleAuthenticator instanceof AuthenticationFailureHandlerInterface) {
            if ($this->logger) {
                $this->logger->debug(sprintf('Using the %s object as authentication failure handler', get_class($this->simpleAuthenticator)));
            }

            $response = $this->simpleAuthenticator->onAuthenticationFailure($request, $exception);
            if ($response instanceof Response) {
                return $response;
            }

            if (null !== $response) {
                throw new \UnexpectedValueException(sprintf('The %s::onAuthenticationFailure method must return null to use the default failure handler, or a Response object', get_class($this->simpleAuthenticator)));
            }
        }

        if ($this->logger) {
            $this->logger->debug('Fallback to the default authentication failure handler');
        }

        return $this->failureHandler->onAuthenticationFailure($request, $exception);
    }
}
PK��Z�D����9Symfony/Component/Security/Http/Event/SwitchUserEvent.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Event;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\EventDispatcher\Event;

/**
 * SwitchUserEvent
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class SwitchUserEvent extends Event
{
    private $request;
    private $targetUser;

    public function __construct(Request $request, UserInterface $targetUser)
    {
        $this->request = $request;
        $this->targetUser = $targetUser;
    }

    /**
     * @return Request
     */
    public function getRequest()
    {
        return $this->request;
    }

    /**
     * @return UserInterface
     */
    public function getTargetUser()
    {
        return $this->targetUser;
    }
}
PK��ZZ�v}?Symfony/Component/Security/Http/Event/InteractiveLoginEvent.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Event;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;

/**
 * InteractiveLoginEvent
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class InteractiveLoginEvent extends Event
{
    private $request;
    private $authenticationToken;

    /**
     * Constructor.
     *
     * @param Request        $request             A Request instance
     * @param TokenInterface $authenticationToken A TokenInterface instance
     */
    public function __construct(Request $request, TokenInterface $authenticationToken)
    {
        $this->request = $request;
        $this->authenticationToken = $authenticationToken;
    }

    /**
     * Gets the request.
     *
     * @return Request A Request instance
     */
    public function getRequest()
    {
        return $this->request;
    }

    /**
     * Gets the authentication token.
     *
     * @return TokenInterface A TokenInterface instance
     */
    public function getAuthenticationToken()
    {
        return $this->authenticationToken;
    }
}
PK��Z��VǴ�=Symfony/Component/Security/Csrf/CsrfTokenManagerInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Csrf;

/**
 * Manages CSRF tokens.
 *
 * @since  2.4
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface CsrfTokenManagerInterface
{
    /**
     * Returns a CSRF token for the given ID.
     *
     * If previously no token existed for the given ID, a new token is
     * generated. Otherwise the existing token is returned (with the same value,
     * not the same instance).
     *
     * @param string $tokenId The token ID. You may choose an arbitrary value
     *                        for the ID
     *
     * @return CsrfToken The CSRF token
     */
    public function getToken($tokenId);

    /**
     * Generates a new token value for the given ID.
     *
     * This method will generate a new token for the given token ID, independent
     * of whether a token value previously existed or not. It can be used to
     * enforce once-only tokens in environments with high security needs.
     *
     * @param string $tokenId The token ID. You may choose an arbitrary value
     *                        for the ID
     *
     * @return CsrfToken The CSRF token
     */
    public function refreshToken($tokenId);

    /**
     * Invalidates the CSRF token with the given ID, if one exists.
     *
     * @param string $tokenId The token ID
     *
     * @return string|null Returns the removed token value if one existed, NULL
     *                     otherwise
     */
    public function removeToken($tokenId);

    /**
     * Returns whether the given CSRF token is valid.
     *
     * @param CsrfToken $token A CSRF token
     *
     * @return Boolean Returns true if the token is valid, false otherwise
     */
    public function isTokenValid(CsrfToken $token);
}
PK��Z&%�L
L
4Symfony/Component/Security/Csrf/CsrfTokenManager.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Csrf;

use Symfony\Component\Security\Core\Util\StringUtils;
use Symfony\Component\Security\Csrf\TokenGenerator\UriSafeTokenGenerator;
use Symfony\Component\Security\Csrf\TokenGenerator\TokenGeneratorInterface;
use Symfony\Component\Security\Csrf\TokenStorage\NativeSessionTokenStorage;
use Symfony\Component\Security\Csrf\TokenStorage\TokenStorageInterface;

/**
 * Default implementation of {@link CsrfTokenManagerInterface}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class CsrfTokenManager implements CsrfTokenManagerInterface
{
    /**
     * @var TokenGeneratorInterface
     */
    private $generator;

    /**
     * @var TokenStorageInterface
     */
    private $storage;

    /**
     * Creates a new CSRF provider using PHP's native session storage.
     *
     * @param TokenGeneratorInterface|null $generator The token generator
     * @param TokenStorageInterface|null   $storage   The storage for storing
     *                                                generated CSRF tokens
     */
    public function __construct(TokenGeneratorInterface $generator = null, TokenStorageInterface $storage = null)
    {
        $this->generator = $generator ?: new UriSafeTokenGenerator();
        $this->storage = $storage ?: new NativeSessionTokenStorage();
    }

    /**
     * {@inheritdoc}
     */
    public function getToken($tokenId)
    {
        if ($this->storage->hasToken($tokenId)) {
            $value = $this->storage->getToken($tokenId);
        } else {
            $value = $this->generator->generateToken();

            $this->storage->setToken($tokenId, $value);
        }

        return new CsrfToken($tokenId, $value);
    }

    /**
     * {@inheritdoc}
     */
    public function refreshToken($tokenId)
    {
        $value = $this->generator->generateToken();

        $this->storage->setToken($tokenId, $value);

        return new CsrfToken($tokenId, $value);
    }

    /**
     * {@inheritdoc}
     */
    public function removeToken($tokenId)
    {
        return $this->storage->removeToken($tokenId);
    }

    /**
     * {@inheritdoc}
     */
    public function isTokenValid(CsrfToken $token)
    {
        if (!$this->storage->hasToken($token->getId())) {
            return false;
        }

        return StringUtils::equals($this->storage->getToken($token->getId()), $token->getValue());
    }
}
PK��Z�����
�
JSymfony/Component/Security/Csrf/TokenStorage/NativeSessionTokenStorage.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Csrf\TokenStorage;

use Symfony\Component\Security\Csrf\Exception\TokenNotFoundException;

/**
 * Token storage that uses PHP's native session handling.
 *
 * @since  2.4
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class NativeSessionTokenStorage implements TokenStorageInterface
{
    /**
     * The namespace used to store values in the session.
     * @var string
     */
    const SESSION_NAMESPACE = '_csrf';

    /**
     * @var Boolean
     */
    private $sessionStarted = false;

    /**
     * @var string
     */
    private $namespace;

    /**
     * Initializes the storage with a session namespace.
     *
     * @param string  $namespace The namespace under which the token is stored
     *                           in the session
     */
    public function __construct($namespace = self::SESSION_NAMESPACE)
    {
        $this->namespace = $namespace;
    }

    /**
     * {@inheritdoc}
     */
    public function getToken($tokenId)
    {
        if (!$this->sessionStarted) {
            $this->startSession();
        }

        if (!isset($_SESSION[$this->namespace][$tokenId])) {
            throw new TokenNotFoundException('The CSRF token with ID '.$tokenId.' does not exist.');
        }

        return (string) $_SESSION[$this->namespace][$tokenId];
    }

    /**
     * {@inheritdoc}
     */
    public function setToken($tokenId, $token)
    {
        if (!$this->sessionStarted) {
            $this->startSession();
        }

        $_SESSION[$this->namespace][$tokenId] = (string) $token;
    }

    /**
     * {@inheritdoc}
     */
    public function hasToken($tokenId)
    {
        if (!$this->sessionStarted) {
            $this->startSession();
        }

        return isset($_SESSION[$this->namespace][$tokenId]);
    }

    /**
     * {@inheritdoc}
     */
    public function removeToken($tokenId)
    {
        if (!$this->sessionStarted) {
            $this->startSession();
        }

        $token = isset($_SESSION[$this->namespace][$tokenId])
            ? (string) $_SESSION[$this->namespace][$tokenId]
            : null;

        unset($_SESSION[$this->namespace][$tokenId]);

        return $token;
    }

    private function startSession()
    {
        if (version_compare(PHP_VERSION, '5.4', '>=')) {
            if (PHP_SESSION_NONE === session_status()) {
                session_start();
            }
        } elseif (!session_id()) {
            session_start();
        }

        $this->sessionStarted = true;
    }
}
PK��Z�����FSymfony/Component/Security/Csrf/TokenStorage/TokenStorageInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Csrf\TokenStorage;

/**
 * Stores CSRF tokens.
 *
 * @since  2.4
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface TokenStorageInterface
{
    /**
     * Reads a stored CSRF token.
     *
     * @param string $tokenId The token ID
     *
     * @return string The stored token
     *
     * @throws \Symfony\Component\Security\Csrf\Exception\TokenNotFoundException If the token ID does not exist
     */
    public function getToken($tokenId);

    /**
     * Stores a CSRF token.
     *
     * @param string $tokenId The token ID
     * @param string $token   The CSRF token
     */
    public function setToken($tokenId, $token);

    /**
     * Removes a CSRF token.
     *
     * @param string $tokenId The token ID
     *
     * @return string|null Returns the removed token if one existed, NULL
     *                     otherwise
     */
    public function removeToken($tokenId);

    /**
     * Checks whether a token with the given token ID exists.
     *
     * @param string $tokenId The token ID
     *
     * @return Boolean Whether a token exists with the given ID
     */
    public function hasToken($tokenId);
}
PK��Z��]N
N
DSymfony/Component/Security/Csrf/TokenStorage/SessionTokenStorage.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Csrf\TokenStorage;

use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Security\Csrf\Exception\TokenNotFoundException;

/**
 * Token storage that uses a Symfony2 Session object.
 *
 * @since  2.4
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class SessionTokenStorage implements TokenStorageInterface
{
    /**
     * The namespace used to store values in the session.
     * @var string
     */
    const SESSION_NAMESPACE = '_csrf';

    /**
     * The user session from which the session ID is returned
     * @var SessionInterface
     */
    private $session;

    /**
     * @var string
     */
    private $namespace;

    /**
     * Initializes the storage with a Session object and a session namespace.
     *
     * @param SessionInterface $session   The user session
     * @param string           $namespace The namespace under which the token
     *                                    is stored in the session
     */
    public function __construct(SessionInterface $session, $namespace = self::SESSION_NAMESPACE)
    {
        $this->session = $session;
        $this->namespace = $namespace;
    }

    /**
     * {@inheritdoc}
     */
    public function getToken($tokenId)
    {
        if (!$this->session->isStarted()) {
            $this->session->start();
        }

        if (!$this->session->has($this->namespace.'/'.$tokenId)) {
            throw new TokenNotFoundException('The CSRF token with ID '.$tokenId.' does not exist.');
        }

        return (string) $this->session->get($this->namespace.'/'.$tokenId);
    }

    /**
     * {@inheritdoc}
     */
    public function setToken($tokenId, $token)
    {
        if (!$this->session->isStarted()) {
            $this->session->start();
        }

        $this->session->set($this->namespace.'/'.$tokenId, (string) $token);
    }

    /**
     * {@inheritdoc}
     */
    public function hasToken($tokenId)
    {
        if (!$this->session->isStarted()) {
            $this->session->start();
        }

        return $this->session->has($this->namespace.'/'.$tokenId);
    }

    /**
     * {@inheritdoc}
     */
    public function removeToken($tokenId)
    {
        if (!$this->session->isStarted()) {
            $this->session->start();
        }

        return $this->session->remove($this->namespace.'/'.$tokenId);
    }
}
PK��ZeI����DSymfony/Component/Security/Csrf/Exception/TokenNotFoundException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Csrf\Exception;

use Symfony\Component\Security\Core\Exception\RuntimeException;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class TokenNotFoundException extends RuntimeException
{
}
PK��Z��=HSymfony/Component/Security/Csrf/TokenGenerator/UriSafeTokenGenerator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Csrf\TokenGenerator;

use Symfony\Component\Security\Core\Util\SecureRandomInterface;
use Symfony\Component\Security\Core\Util\SecureRandom;

/**
 * Generates CSRF tokens.
 *
 * @since  2.4
 * @author Bernhard Schussek <bernhard.schussek@symfony.com>
 */
class UriSafeTokenGenerator implements TokenGeneratorInterface
{
    /**
     * The generator for random values.
     *
     * @var SecureRandomInterface
     */
    private $random;

    /**
     * The amount of entropy collected for each token (in bits).
     *
     * @var integer
     */
    private $entropy;

    /**
     * Generates URI-safe CSRF tokens.
     *
     * @param SecureRandomInterface|null $random  The random value generator used for
     *                                            generating entropy
     * @param integer                    $entropy The amount of entropy collected for
     *                                            each token (in bits)
     */
    public function __construct(SecureRandomInterface $random = null, $entropy = 256)
    {
        $this->random = $random ?: new SecureRandom();
        $this->entropy = $entropy;
    }

    /**
     * {@inheritdoc}
     */
    public function generateToken()
    {
        // Generate an URI safe base64 encoded string that does not contain "+",
        // "/" or "=" which need to be URL encoded and make URLs unnecessarily
        // longer.
        $bytes = $this->random->nextBytes($this->entropy / 8);

        return rtrim(strtr(base64_encode($bytes), '+/', '-_'), '=');
    }
}
PK��ZJ,p���JSymfony/Component/Security/Csrf/TokenGenerator/TokenGeneratorInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Csrf\TokenGenerator;

/**
 * Generates and validates CSRF tokens.
 *
 * You can generate a CSRF token by using the method {@link generateCsrfToken()}.
 * This method expects a unique token ID as argument. The token ID can later be
 * used to validate a token provided by the user.
 *
 * Token IDs do not necessarily have to be secret, but they should NEVER be
 * created from data provided by the client. A good practice is to hard-code the
 * token IDs for the various CSRF tokens used by your application.
 *
 * You should use the method {@link isCsrfTokenValid()} to check a CSRF token
 * submitted by the client. This method will return true if the CSRF token is
 * valid.
 *
 * @since  2.4
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface TokenGeneratorInterface
{
    /**
     * Generates a CSRF token.
     *
     * @return string The generated CSRF token
     */
    public function generateToken();
}
PK��Z���O-Symfony/Component/Security/Csrf/CsrfToken.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Csrf;

/**
 * A CSRF token.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class CsrfToken
{
    /**
     * @var string
     */
    private $id;

    /**
     * @var string
     */
    private $value;

    /**
     * Constructor.
     *
     * @param string $id    The token ID
     * @param string $value The actual token value
     */
    public function __construct($id, $value)
    {
        $this->id = (string) $id;
        $this->value = (string) $value;
    }

    /**
     * Returns the ID of the CSRF token.
     *
     * @return string The token ID
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Returns the value of the CSRF token.
     *
     * @return string The token value
     */
    public function getValue()
    {
        return $this->value;
    }

    /**
     * Returns the value of the CSRF token.
     *
     * @return string The token value
     */
    public function __toString()
    {
        return $this->value;
    }
}
PK��Z��S��<Symfony/Component/Security/Core/SecurityContextInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;

/**
 * The SecurityContextInterface.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface SecurityContextInterface
{
    const ACCESS_DENIED_ERROR  = '_security.403_error';
    const AUTHENTICATION_ERROR = '_security.last_error';
    const LAST_USERNAME        = '_security.last_username';

    /**
     * Returns the current security token.
     *
     * @return TokenInterface|null A TokenInterface instance or null if no authentication information is available
     */
    public function getToken();

    /**
     * Sets the authentication token.
     *
     * @param TokenInterface $token A TokenInterface token, or null if no further authentication information should be stored
     */
    public function setToken(TokenInterface $token = null);

    /**
     * Checks if the attributes are granted against the current authentication token and optionally supplied object.
     *
     * @param mixed $attributes
     * @param mixed $object
     *
     * @return Boolean
     */
    public function isGranted($attributes, $object = null);
}
PK��Z�}�ww?Symfony/Component/Security/Core/Role/RoleHierarchyInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Role;

/**
 * RoleHierarchyInterface is the interface for a role hierarchy.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface RoleHierarchyInterface
{
    /**
     * Returns an array of all reachable roles by the given ones.
     *
     * Reachable roles are the roles directly assigned but also all roles that
     * are transitively reachable from them in the role hierarchy.
     *
     * @param RoleInterface[] $roles An array of directly assigned roles
     *
     * @return RoleInterface[] An array of all reachable roles
     */
    public function getReachableRoles(array $roles);
}
PK��Z� �w??6Symfony/Component/Security/Core/Role/RoleHierarchy.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Role;

/**
 * RoleHierarchy defines a role hierarchy.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class RoleHierarchy implements RoleHierarchyInterface
{
    private $hierarchy;
    private $map;

    /**
     * Constructor.
     *
     * @param array $hierarchy An array defining the hierarchy
     */
    public function __construct(array $hierarchy)
    {
        $this->hierarchy = $hierarchy;

        $this->buildRoleMap();
    }

    /**
     * {@inheritdoc}
     */
    public function getReachableRoles(array $roles)
    {
        $reachableRoles = $roles;
        foreach ($roles as $role) {
            if (!isset($this->map[$role->getRole()])) {
                continue;
            }

            foreach ($this->map[$role->getRole()] as $r) {
                $reachableRoles[] = new Role($r);
            }
        }

        return $reachableRoles;
    }

    private function buildRoleMap()
    {
        $this->map = array();
        foreach ($this->hierarchy as $main => $roles) {
            $this->map[$main] = $roles;
            $visited = array();
            $additionalRoles = $roles;
            while ($role = array_shift($additionalRoles)) {
                if (!isset($this->hierarchy[$role])) {
                    continue;
                }

                $visited[] = $role;
                $this->map[$main] = array_unique(array_merge($this->map[$main], $this->hierarchy[$role]));
                $additionalRoles = array_merge($additionalRoles, array_diff($this->hierarchy[$role], $visited));
            }
        }
    }
}
PK��Z�Ħ-Symfony/Component/Security/Core/Role/Role.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Role;

/**
 * Role is a simple implementation of a RoleInterface where the role is a
 * string.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Role implements RoleInterface
{
    private $role;

    /**
     * Constructor.
     *
     * @param string $role The role name
     */
    public function __construct($role)
    {
        $this->role = (string) $role;
    }

    /**
     * {@inheritdoc}
     */
    public function getRole()
    {
        return $this->role;
    }
}
PK��ZX�S�007Symfony/Component/Security/Core/Role/SwitchUserRole.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Role;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;

/**
 * SwitchUserRole is used when the current user temporarily impersonates
 * another one.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class SwitchUserRole extends Role
{
    private $source;

    /**
     * Constructor.
     *
     * @param string         $role   The role as a string
     * @param TokenInterface $source The original token
     */
    public function __construct($role, TokenInterface $source)
    {
        parent::__construct($role);

        $this->source = $source;
    }

    /**
     * Returns the original Token.
     *
     * @return TokenInterface The original TokenInterface instance
     */
    public function getSource()
    {
        return $this->source;
    }
}
PK��Z�'c��6Symfony/Component/Security/Core/Role/RoleInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Role;

/**
 * RoleInterface represents a role granted to a user.
 *
 * A role must either have a string representation or it needs to be explicitly
 * supported by at least one AccessDecisionManager.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface RoleInterface
{
    /**
     * Returns the role.
     *
     * This method returns a string representation whenever possible.
     *
     * When the role cannot be represented with sufficient precision by a
     * string, it should return null.
     *
     * @return string|null A string representation of the role, or null
     */
    public function getRole();
}
PK��ZE� �DSymfony/Component/Security/Core/Encoder/PasswordEncoderInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Encoder;

/**
 * PasswordEncoderInterface is the interface for all encoders.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface PasswordEncoderInterface
{
    /**
     * Encodes the raw password.
     *
     * @param string $raw  The password to encode
     * @param string $salt The salt
     *
     * @return string The encoded password
     */
    public function encodePassword($raw, $salt);

    /**
     * Checks a raw password against an encoded password.
     *
     * @param string $encoded An encoded password
     * @param string $raw     A raw password
     * @param string $salt    The salt
     *
     * @return Boolean true if the password is valid, false otherwise
     */
    public function isPasswordValid($encoded, $raw, $salt);
}
PK��Z��	�	ASymfony/Component/Security/Core/Encoder/BCryptPasswordEncoder.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Encoder;

use Symfony\Component\Security\Core\Exception\BadCredentialsException;

/**
 * @author Elnur Abdurrakhimov <elnur@elnur.pro>
 * @author Terje Bråten <terje@braten.be>
 */
class BCryptPasswordEncoder extends BasePasswordEncoder
{
    /**
     * @var string
     */
    private $cost;

    /**
     * Constructor.
     *
     * @param integer $cost The algorithmic cost that should be used
     *
     * @throws \RuntimeException When no BCrypt encoder is available
     * @throws \InvalidArgumentException if cost is out of range
     */
    public function __construct($cost)
    {
        if (!function_exists('password_hash')) {
            throw new \RuntimeException('To use the BCrypt encoder, you need to upgrade to PHP 5.5 or install the "ircmaxell/password-compat" via Composer.');
        }

        $cost = (int) $cost;
        if ($cost < 4 || $cost > 31) {
            throw new \InvalidArgumentException('Cost must be in the range of 4-31.');
        }

        $this->cost = $cost;
    }

    /**
     * Encodes the raw password.
     *
     * It doesn't work with PHP versions lower than 5.3.7, since
     * the password compat library uses CRYPT_BLOWFISH hash type with
     * the "$2y$" salt prefix (which is not available in the early PHP versions).
     * @see https://github.com/ircmaxell/password_compat/issues/10#issuecomment-11203833
     *
     * It is almost best to **not** pass a salt and let PHP generate one for you.
     *
     * @param string $raw  The password to encode
     * @param string $salt The salt
     *
     * @return string The encoded password
     *
     * @link http://lxr.php.net/xref/PHP_5_5/ext/standard/password.c#111
     */
    public function encodePassword($raw, $salt)
    {
        if ($this->isPasswordTooLong($raw)) {
            throw new BadCredentialsException('Invalid password.');
        }

        $options = array('cost' => $this->cost);

        if ($salt) {
            $options['salt'] = $salt;
        }

        return password_hash($raw, PASSWORD_BCRYPT, $options);
    }

    /**
     * {@inheritdoc}
     */
    public function isPasswordValid($encoded, $raw, $salt)
    {
        return !$this->isPasswordTooLong($raw) && password_verify($raw, $encoded);
    }
}
PK��Z��^��HSymfony/Component/Security/Core/Encoder/MessageDigestPasswordEncoder.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Encoder;

use Symfony\Component\Security\Core\Exception\BadCredentialsException;

/**
 * MessageDigestPasswordEncoder uses a message digest algorithm.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class MessageDigestPasswordEncoder extends BasePasswordEncoder
{
    private $algorithm;
    private $encodeHashAsBase64;
    private $iterations;

    /**
     * Constructor.
     *
     * @param string  $algorithm          The digest algorithm to use
     * @param Boolean $encodeHashAsBase64 Whether to base64 encode the password hash
     * @param integer $iterations         The number of iterations to use to stretch the password hash
     */
    public function __construct($algorithm = 'sha512', $encodeHashAsBase64 = true, $iterations = 5000)
    {
        $this->algorithm = $algorithm;
        $this->encodeHashAsBase64 = $encodeHashAsBase64;
        $this->iterations = $iterations;
    }

    /**
     * {@inheritdoc}
     */
    public function encodePassword($raw, $salt)
    {
        if ($this->isPasswordTooLong($raw)) {
            throw new BadCredentialsException('Invalid password.');
        }

        if (!in_array($this->algorithm, hash_algos(), true)) {
            throw new \LogicException(sprintf('The algorithm "%s" is not supported.', $this->algorithm));
        }

        $salted = $this->mergePasswordAndSalt($raw, $salt);
        $digest = hash($this->algorithm, $salted, true);

        // "stretch" hash
        for ($i = 1; $i < $this->iterations; $i++) {
            $digest = hash($this->algorithm, $digest.$salted, true);
        }

        return $this->encodeHashAsBase64 ? base64_encode($digest) : bin2hex($digest);
    }

    /**
     * {@inheritdoc}
     */
    public function isPasswordValid($encoded, $raw, $salt)
    {
        return !$this->isPasswordTooLong($raw) && $this->comparePasswords($encoded, $this->encodePassword($raw, $salt));
    }
}
PK��Z,>"�DSymfony/Component/Security/Core/Encoder/PlaintextPasswordEncoder.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Encoder;

use Symfony\Component\Security\Core\Exception\BadCredentialsException;

/**
 * PlaintextPasswordEncoder does not do any encoding.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class PlaintextPasswordEncoder extends BasePasswordEncoder
{
    private $ignorePasswordCase;

    /**
     * Constructor.
     *
     * @param Boolean $ignorePasswordCase Compare password case-insensitive
     */
    public function __construct($ignorePasswordCase = false)
    {
        $this->ignorePasswordCase = $ignorePasswordCase;
    }

    /**
     * {@inheritdoc}
     */
    public function encodePassword($raw, $salt)
    {
        if ($this->isPasswordTooLong($raw)) {
            throw new BadCredentialsException('Invalid password.');
        }

        return $this->mergePasswordAndSalt($raw, $salt);
    }

    /**
     * {@inheritdoc}
     */
    public function isPasswordValid($encoded, $raw, $salt)
    {
        if ($this->isPasswordTooLong($raw)) {
            return false;
        }

        $pass2 = $this->mergePasswordAndSalt($raw, $salt);

        if (!$this->ignorePasswordCase) {
            return $this->comparePasswords($encoded, $pass2);
        }

        return $this->comparePasswords(strtolower($encoded), strtolower($pass2));
    }
}
PK��Z�;D��:Symfony/Component/Security/Core/Encoder/EncoderFactory.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Encoder;

/**
 * A generic encoder factory implementation
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class EncoderFactory implements EncoderFactoryInterface
{
    private $encoders;

    public function __construct(array $encoders)
    {
        $this->encoders = $encoders;
    }

    /**
     * {@inheritDoc}
     */
    public function getEncoder($user)
    {
        foreach ($this->encoders as $class => $encoder) {
            if ((is_object($user) && !$user instanceof $class) || (!is_object($user) && !is_subclass_of($user, $class) && $user != $class)) {
                continue;
            }

            if (!$encoder instanceof PasswordEncoderInterface) {
                return $this->encoders[$class] = $this->createEncoder($encoder);
            }

            return $this->encoders[$class];
        }

        throw new \RuntimeException(sprintf('No encoder has been configured for account "%s".', is_object($user) ? get_class($user) : $user));
    }

    /**
     * Creates the actual encoder instance
     *
     * @param array $config
     *
     * @return PasswordEncoderInterface
     *
     * @throws \InvalidArgumentException
     */
    private function createEncoder(array $config)
    {
        if (!isset($config['class'])) {
            throw new \InvalidArgumentException(sprintf('"class" must be set in %s.', json_encode($config)));
        }
        if (!isset($config['arguments'])) {
            throw new \InvalidArgumentException(sprintf('"arguments" must be set in %s.', json_encode($config)));
        }

        $reflection = new \ReflectionClass($config['class']);

        return $reflection->newInstanceArgs($config['arguments']);
    }
}
PK��Z!�@

ASymfony/Component/Security/Core/Encoder/Pbkdf2PasswordEncoder.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Encoder;

use Symfony\Component\Security\Core\Exception\BadCredentialsException;

/**
 * Pbkdf2PasswordEncoder uses the PBKDF2 (Password-Based Key Derivation Function 2).
 *
 * Providing a high level of Cryptographic security,
 *  PBKDF2 is recommended by the National Institute of Standards and Technology (NIST).
 *
 * But also warrants a warning, using PBKDF2 (with a high number of iterations) slows down the process.
 * PBKDF2 should be used with caution and care.
 *
 * @author Sebastiaan Stok <s.stok@rollerscapes.net>
 * @author Andrew Johnson
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Pbkdf2PasswordEncoder extends BasePasswordEncoder
{
    private $algorithm;
    private $encodeHashAsBase64;
    private $iterations;
    private $length;

    /**
     * Constructor.
     *
     * @param string  $algorithm          The digest algorithm to use
     * @param Boolean $encodeHashAsBase64 Whether to base64 encode the password hash
     * @param integer $iterations         The number of iterations to use to stretch the password hash
     * @param integer $length             Length of derived key to create
     */
    public function __construct($algorithm = 'sha512', $encodeHashAsBase64 = true, $iterations = 1000, $length = 40)
    {
        $this->algorithm = $algorithm;
        $this->encodeHashAsBase64 = $encodeHashAsBase64;
        $this->iterations = $iterations;
        $this->length = $length;
    }

    /**
     * {@inheritdoc}
     *
     * @throws \LogicException when the algorithm is not supported
     */
    public function encodePassword($raw, $salt)
    {
        if ($this->isPasswordTooLong($raw)) {
            throw new BadCredentialsException('Invalid password.');
        }

        if (!in_array($this->algorithm, hash_algos(), true)) {
            throw new \LogicException(sprintf('The algorithm "%s" is not supported.', $this->algorithm));
        }

        if (function_exists('hash_pbkdf2')) {
            $digest = hash_pbkdf2($this->algorithm, $raw, $salt, $this->iterations, $this->length, true);
        } else {
            $digest = $this->hashPbkdf2($this->algorithm, $raw, $salt, $this->iterations, $this->length);
        }

        return $this->encodeHashAsBase64 ? base64_encode($digest) : bin2hex($digest);
    }

    /**
     * {@inheritdoc}
     */
    public function isPasswordValid($encoded, $raw, $salt)
    {
        return !$this->isPasswordTooLong($raw) && $this->comparePasswords($encoded, $this->encodePassword($raw, $salt));
    }

    private function hashPbkdf2($algorithm, $password, $salt, $iterations, $length = 0)
    {
        // Number of blocks needed to create the derived key
        $blocks = ceil($length / strlen(hash($algorithm, null, true)));
        $digest = '';

        for ($i = 1; $i <= $blocks; $i++) {
            $ib = $block = hash_hmac($algorithm, $salt.pack('N', $i), $password, true);

            // Iterations
            for ($j = 1; $j < $iterations; $j++) {
                $ib ^= ($block = hash_hmac($algorithm, $block, $password, true));
            }

            $digest .= $ib;
        }

        return substr($digest, 0, $this->length);
    }
}
PK��Z#�MMqqCSymfony/Component/Security/Core/Encoder/EncoderFactoryInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Encoder;

use Symfony\Component\Security\Core\User\UserInterface;

/**
 * EncoderFactoryInterface to support different encoders for different accounts.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface EncoderFactoryInterface
{
    /**
     * Returns the password encoder to use for the given account.
     *
     * @param UserInterface|string $user A UserInterface instance or a class name
     *
     * @return PasswordEncoderInterface
     *
     * @throws \RuntimeException when no password encoder could be found for the user
     */
    public function getEncoder($user);
}
PK��Z�7���
�
?Symfony/Component/Security/Core/Encoder/BasePasswordEncoder.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Encoder;

use Symfony\Component\Security\Core\Util\StringUtils;

/**
 * BasePasswordEncoder is the base class for all password encoders.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class BasePasswordEncoder implements PasswordEncoderInterface
{
    const MAX_PASSWORD_LENGTH = 4096;

    /**
     * Demerges a merge password and salt string.
     *
     * @param string $mergedPasswordSalt The merged password and salt string
     *
     * @return array An array where the first element is the password and the second the salt
     */
    protected function demergePasswordAndSalt($mergedPasswordSalt)
    {
        if (empty($mergedPasswordSalt)) {
            return array('', '');
        }

        $password = $mergedPasswordSalt;
        $salt = '';
        $saltBegins = strrpos($mergedPasswordSalt, '{');

        if (false !== $saltBegins && $saltBegins + 1 < strlen($mergedPasswordSalt)) {
            $salt = substr($mergedPasswordSalt, $saltBegins + 1, -1);
            $password = substr($mergedPasswordSalt, 0, $saltBegins);
        }

        return array($password, $salt);
    }

    /**
     * Merges a password and a salt.
     *
     * @param string $password the password to be used
     * @param string $salt     the salt to be used
     *
     * @return string a merged password and salt
     *
     * @throws \InvalidArgumentException
     */
    protected function mergePasswordAndSalt($password, $salt)
    {
        if (empty($salt)) {
            return $password;
        }

        if (false !== strrpos($salt, '{') || false !== strrpos($salt, '}')) {
            throw new \InvalidArgumentException('Cannot use { or } in salt.');
        }

        return $password.'{'.$salt.'}';
    }

    /**
     * Compares two passwords.
     *
     * This method implements a constant-time algorithm to compare passwords to
     * avoid (remote) timing attacks.
     *
     * @param string $password1 The first password
     * @param string $password2 The second password
     *
     * @return Boolean true if the two passwords are the same, false otherwise
     */
    protected function comparePasswords($password1, $password2)
    {
        return StringUtils::equals($password1, $password2);
    }

    /**
     * Checks if the password is too long.
     *
     * @return Boolean true if the password is too long, false otherwise
     */
    protected function isPasswordTooLong($password)
    {
        return strlen($password) > self::MAX_PASSWORD_LENGTH;
    }
}
PK��Z��
�77OSymfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Validator\Constraints;

use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;

class UserPasswordValidator extends ConstraintValidator
{
    private $securityContext;
    private $encoderFactory;

    public function __construct(SecurityContextInterface $securityContext, EncoderFactoryInterface $encoderFactory)
    {
        $this->securityContext = $securityContext;
        $this->encoderFactory = $encoderFactory;
    }

    /**
     * {@inheritdoc}
     */
    public function validate($password, Constraint $constraint)
    {
        $user = $this->securityContext->getToken()->getUser();

        if (!$user instanceof UserInterface) {
            throw new ConstraintDefinitionException('The User object must implement the UserInterface interface.');
        }

        $encoder = $this->encoderFactory->getEncoder($user);

        if (!$encoder->isPasswordValid($user->getPassword(), $password, $user->getSalt())) {
            $this->context->addViolation($constraint->message);
        }
    }
}
PK��Z��i��FSymfony/Component/Security/Core/Validator/Constraints/UserPassword.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 */
class UserPassword extends Constraint
{
    public $message = 'This value should be the user current password.';
    public $service = 'security.validator.user_password';

    /**
     * {@inheritdoc}
     */
    public function validatedBy()
    {
        return $this->service;
    }
}
PK��Z����ESymfony/Component/Security/Core/Exception/BadCredentialsException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Exception;

/**
 * BadCredentialsException is thrown when the user credentials are invalid.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class BadCredentialsException extends AuthenticationException
{
    /**
     * {@inheritDoc}
     */
    public function getMessageKey()
    {
        return 'Invalid credentials.';
    }
}
PK��Z���zz=Symfony/Component/Security/Core/Exception/LockedException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Exception;

/**
 * LockedException is thrown if the user account is locked.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class LockedException extends AccountStatusException
{
    /**
     * {@inheritDoc}
     */
    public function getMessageKey()
    {
        return 'Account is locked.';
    }
}
PK��Zb��M<<FSymfony/Component/Security/Core/Exception/UnsupportedUserException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Exception;

/**
 * This exception is thrown when an account is reloaded from a provider which
 * doesn't support the passed implementation of UserInterface.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class UnsupportedUserException extends AuthenticationServiceException
{
}
PK��Z�z�&��ISymfony/Component/Security/Core/Exception/CredentialsExpiredException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Exception;

/**
 * CredentialsExpiredException is thrown when the user account credentials have expired.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class CredentialsExpiredException extends AccountStatusException
{
    /**
     * {@inheritDoc}
     */
    public function getMessageKey()
    {
        return 'Credentials have expired.';
    }
}
PK��Z��Xss=Symfony/Component/Security/Core/Exception/LogoutException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Exception;

/**
 * LogoutException is thrown when the account cannot be logged out.
 *
 * @author Jeremy Mikola <jmikola@gmail.com>
 */
class LogoutException extends \RuntimeException
{
    public function __construct($message = 'Logout Exception', \Exception $previous = null)
    {
        parent::__construct($message, 403, $previous);
    }
}
PK��Z
�04}}GSymfony/Component/Security/Core/Exception/UsernameNotFoundException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Exception;

/**
 * UsernameNotFoundException is thrown if a User cannot be found by its username.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class UsernameNotFoundException extends AuthenticationException
{
    private $username;

    /**
     * {@inheritDoc}
     */
    public function getMessageKey()
    {
        return 'Username could not be found.';
    }

    /**
     * Get the username.
     *
     * @return string
     */
    public function getUsername()
    {
        return $this->username;
    }

    /**
     * Set the username.
     *
     * @param string $username
     */
    public function setUsername($username)
    {
        $this->username = $username;
    }

    /**
     * {@inheritDoc}
     */
    public function serialize()
    {
        return serialize(array(
            $this->username,
            parent::serialize(),
        ));
    }

    /**
     * {@inheritDoc}
     */
    public function unserialize($str)
    {
        list($this->username, $parentData) = unserialize($str);

        parent::unserialize($parentData);
    }
}
PK��Z#��q44QSymfony/Component/Security/Core/Exception/InsufficientAuthenticationException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Exception;

/**
 * InsufficientAuthenticationException is thrown if the user credentials are not sufficiently trusted.
 *
 * This is the case when a user is anonymous and the resource to be displayed has an access role.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class InsufficientAuthenticationException extends AuthenticationException
{
    /**
     * {@inheritDoc}
     */
    public function getMessageKey()
    {
        return 'Not privileged to request the resource.';
    }
}
PK��Z�5]���ISymfony/Component/Security/Core/Exception/SessionUnavailableException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Exception;

/**
 * This exception is thrown when no session is available.
 *
 * Possible reasons for this are:
 *
 *     a) The session timed out because the user waited too long.
 *     b) The user has disabled cookies, and a new session is started on each
 *        request.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class SessionUnavailableException extends AuthenticationException
{
    /**
     * {@inheritDoc}
     */
    public function getMessageKey()
    {
        return 'No session available, it either timed out or cookies are not enabled.';
    }
}
PK��ZD��9��DSymfony/Component/Security/Core/Exception/TokenNotFoundException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Exception;

/**
 * TokenNotFoundException is thrown if a Token cannot be found.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class TokenNotFoundException extends AuthenticationException
{
    /**
     * {@inheritDoc}
     */
    public function getMessageKey()
    {
        return 'No token could be found.';
    }
}
PK��Zh�c��BSymfony/Component/Security/Core/Exception/CookieTheftException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Exception;

/**
 * This exception is thrown when the RememberMeServices implementation
 * detects that a presented cookie has already been used by someone else.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class CookieTheftException extends AuthenticationException
{
    /**
     * {@inheritDoc}
     */
    public function getMessageKey()
    {
        return 'Cookie has already been used by someone else.';
    }
}
PK��Z��A���@Symfony/Component/Security/Core/Exception/ExceptionInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Exception;

/**
 * Base ExceptionInterface for the Security component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface ExceptionInterface
{
}
PK��ZqUSą�CSymfony/Component/Security/Core/Exception/AccessDeniedException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Exception;

/**
 * AccessDeniedException is thrown when the account has not the required role.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class AccessDeniedException extends \RuntimeException
{
    public function __construct($message = 'Access Denied', \Exception $previous = null)
    {
        parent::__construct($message, 403, $previous);
    }
}
PK��Z�'��ESymfony/Component/Security/Core/Exception/AuthenticationException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Exception;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;

/**
 * AuthenticationException is the base class for all authentication exceptions.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class AuthenticationException extends \RuntimeException implements \Serializable
{
    private $token;

    /**
     * Get the token.
     *
     * @return TokenInterface
     */
    public function getToken()
    {
        return $this->token;
    }

    /**
     * Set the token.
     *
     * @param TokenInterface $token
     */
    public function setToken(TokenInterface $token)
    {
        $this->token = $token;
    }

    public function serialize()
    {
        return serialize(array(
            $this->token,
            $this->code,
            $this->message,
            $this->file,
            $this->line,
        ));
    }

    public function unserialize($str)
    {
        list(
            $this->token,
            $this->code,
            $this->message,
            $this->file,
            $this->line
        ) = unserialize($str);
    }

    /**
     * Message key to be used by the translation component.
     *
     * @return string
     */
    public function getMessageKey()
    {
        return 'An authentication exception occurred.';
    }

    /**
     * Message data to be used by the translation component.
     *
     * @return array
     */
    public function getMessageData()
    {
        return array();
    }
}
PK��Z�
	��>Symfony/Component/Security/Core/Exception/RuntimeException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Exception;

/**
 * Base RuntimeException for the Security component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
PK��Z@�	���GSymfony/Component/Security/Core/Exception/ProviderNotFoundException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Exception;

/**
 * ProviderNotFoundException is thrown when no AuthenticationProviderInterface instance
 * supports an authentication Token.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class ProviderNotFoundException extends AuthenticationException
{
    /**
     * {@inheritDoc}
     */
    public function getMessageKey()
    {
        return 'No authentication provider found to support the authentication token.';
    }
}
PK��Z�ĸ���XSymfony/Component/Security/Core/Exception/AuthenticationCredentialsNotFoundException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Exception;

/**
 * AuthenticationCredentialsNotFoundException is thrown when an authentication is rejected
 * because no Token is available.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class AuthenticationCredentialsNotFoundException extends AuthenticationException
{
    /**
     * {@inheritDoc}
     */
    public function getMessageKey()
    {
        return 'Authentication credentials could not be found.';
    }
}
PK��Z:���AADSymfony/Component/Security/Core/Exception/AccountStatusException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Exception;

use Symfony\Component\Security\Core\User\UserInterface;

/**
 * AccountStatusException is the base class for authentication exceptions
 * caused by the user account status.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
abstract class AccountStatusException extends AuthenticationException
{
    private $user;

    /**
     * Get the user.
     *
     * @return UserInterface
     */
    public function getUser()
    {
        return $this->user;
    }

    /**
     * Set the user.
     *
     * @param UserInterface $user
     */
    public function setUser(UserInterface $user)
    {
        $this->user = $user;
    }

    /**
     * {@inheritDoc}
     */
    public function serialize()
    {
        return serialize(array(
            $this->user,
            parent::serialize(),
        ));
    }

    /**
     * {@inheritDoc}
     */
    public function unserialize($str)
    {
        list($this->user, $parentData) = unserialize($str);

        parent::unserialize($parentData);
    }
}
PK��Z7w�-��LSymfony/Component/Security/Core/Exception/AuthenticationServiceException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Exception;

/**
 * AuthenticationServiceException is thrown when an authentication request could not be processed due to a system problem.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class AuthenticationServiceException extends AuthenticationException
{
    /**
     * {@inheritDoc}
     */
    public function getMessageKey()
    {
        return 'Authentication request could not be processed due to a system problem.';
    }
}
PK��ZxB��ESymfony/Component/Security/Core/Exception/AccountExpiredException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Exception;

/**
 * AccountExpiredException is thrown when the user account has expired.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class AccountExpiredException extends AccountStatusException
{
    /**
     * {@inheritDoc}
     */
    public function getMessageKey()
    {
        return 'Account has expired.';
    }
}
PK��Z�և��?Symfony/Component/Security/Core/Exception/DisabledException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Exception;

/**
 * DisabledException is thrown when the user account is disabled.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class DisabledException extends AccountStatusException
{
    /**
     * {@inheritDoc}
     */
    public function getMessageKey()
    {
        return 'Account is disabled.';
    }
}
PK��Ze���CSymfony/Component/Security/Core/Exception/NonceExpiredException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Exception;

/**
 * NonceExpiredException is thrown when an authentication is rejected because
 * the digest nonce has expired.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class NonceExpiredException extends AuthenticationException
{
    /**
     * {@inheritDoc}
     */
    public function getMessageKey()
    {
        return 'Digest nonce has expired.';
    }
}
PK��Zʝ�9FSymfony/Component/Security/Core/Exception/InvalidArgumentException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Exception;

/**
 * Base InvalidArgumentException for the Security component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
PK��Z�O���GSymfony/Component/Security/Core/Exception/InvalidCsrfTokenException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Exception;

/**
 * This exception is thrown when the csrf token is invalid.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class InvalidCsrfTokenException extends AuthenticationException
{
    /**
     * {@inheritDoc}
     */
    public function getMessageKey()
    {
        return 'Invalid CSRF token.';
    }
}
PK��Z��

5Symfony/Component/Security/Core/Util/SecureRandom.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Util;

use Psr\Log\LoggerInterface;

/**
 * A secure random number generator implementation.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
final class SecureRandom implements SecureRandomInterface
{
    private $logger;
    private $useOpenSsl;
    private $seed;
    private $seedUpdated;
    private $seedLastUpdatedAt;
    private $seedFile;

    /**
     * Constructor.
     *
     * Be aware that a guessable seed will severely compromise the PRNG
     * algorithm that is employed.
     *
     * @param string          $seedFile
     * @param LoggerInterface $logger
     */
    public function __construct($seedFile = null, LoggerInterface $logger = null)
    {
        $this->seedFile = $seedFile;
        $this->logger = $logger;

        // determine whether to use OpenSSL
        if (defined('PHP_WINDOWS_VERSION_BUILD') && version_compare(PHP_VERSION, '5.3.4', '<')) {
            $this->useOpenSsl = false;
        } elseif (!function_exists('openssl_random_pseudo_bytes')) {
            if (null !== $this->logger) {
                $this->logger->notice('It is recommended that you enable the "openssl" extension for random number generation.');
            }
            $this->useOpenSsl = false;
        } else {
            $this->useOpenSsl = true;
        }
    }

    /**
     * {@inheritdoc}
     */
    public function nextBytes($nbBytes)
    {
        // try OpenSSL
        if ($this->useOpenSsl) {
            $bytes = openssl_random_pseudo_bytes($nbBytes, $strong);

            if (false !== $bytes && true === $strong) {
                return $bytes;
            }

            if (null !== $this->logger) {
                $this->logger->info('OpenSSL did not produce a secure random number.');
            }
        }

        // initialize seed
        if (null === $this->seed) {
            if (null === $this->seedFile) {
                throw new \RuntimeException('You need to specify a file path to store the seed.');
            }

            if (is_file($this->seedFile)) {
                list($this->seed, $this->seedLastUpdatedAt) = $this->readSeed();
            } else {
                $this->seed = uniqid(mt_rand(), true);
                $this->updateSeed();
            }
        }

        $bytes = '';
        while (strlen($bytes) < $nbBytes) {
            static $incr = 1;
            $bytes .= hash('sha512', $incr++.$this->seed.uniqid(mt_rand(), true).$nbBytes, true);
            $this->seed = base64_encode(hash('sha512', $this->seed.$bytes.$nbBytes, true));
            $this->updateSeed();
        }

        return substr($bytes, 0, $nbBytes);
    }

    private function readSeed()
    {
        return json_decode(file_get_contents($this->seedFile));
    }

    private function updateSeed()
    {
        if (!$this->seedUpdated && $this->seedLastUpdatedAt < time() - mt_rand(1, 10)) {
            file_put_contents($this->seedFile, json_encode(array($this->seed, microtime(true))));
        }

        $this->seedUpdated = true;
    }
}
PK��ZU��a��4Symfony/Component/Security/Core/Util/StringUtils.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Util;

/**
 * String utility functions.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class StringUtils
{
    /**
     * This class should not be instantiated
     */
    private function __construct() {}

    /**
     * Compares two strings.
     *
     * This method implements a constant-time algorithm to compare strings.
     *
     * @param string $knownString The string of known length to compare against
     * @param string $userInput   The string that the user can control
     *
     * @return Boolean true if the two strings are the same, false otherwise
     */
    public static function equals($knownString, $userInput)
    {
        // Prevent issues if string length is 0
        $knownString .= chr(0);
        $userInput .= chr(0);

        $knownLen = strlen($knownString);
        $userLen = strlen($userInput);

        // Set the result to the difference between the lengths
        $result = $knownLen - $userLen;

        // Note that we ALWAYS iterate over the user-supplied length
        // This is to prevent leaking length information
        for ($i = 0; $i < $userLen; $i++) {
            // Using % here is a trick to prevent notices
            // It's safe, since if the lengths are different
            // $result is already non-0
            $result |= (ord($knownString[$i % $knownLen]) ^ ord($userInput[$i]));
        }

        // They are only identical strings if $result is exactly 0...
        return 0 === $result;
    }
}
PK��Z��T�,,3Symfony/Component/Security/Core/Util/ClassUtils.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Util;

/**
 * Class related functionality for objects that
 * might or might not be proxy objects at the moment.
 *
 * @see Doctrine\Common\Util\ClassUtils
 *
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 * @author Johannes Schmitt <schmittjoh@gmail.com>
 */
class ClassUtils
{
    /**
     * Marker for Proxy class names.
     *
     * @var string
     */
    const MARKER = '__CG__';

    /**
     * Length of the proxy marker
     *
     * @var int
     */
    const MARKER_LENGTH = 6;

    /**
     * This class should not be instantiated
     */
    private function __construct() {}

    /**
     * Gets the real class name of a class name that could be a proxy.
     *
     * @param string|object
     * @return string
     */
    public static function getRealClass($object)
    {
        $class = is_object($object) ? get_class($object) : $object;

        if (false === $pos = strrpos($class, '\\'.self::MARKER.'\\')) {
            return $class;
        }

        return substr($class, $pos + self::MARKER_LENGTH + 2);
    }
}
PK��Z�	���>Symfony/Component/Security/Core/Util/SecureRandomInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Util;

/**
 * Interface that needs to be implemented by all secure random number generators.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface SecureRandomInterface
{
    /**
     * Generates the specified number of secure random bytes.
     *
     * @param integer $nbBytes
     *
     * @return string
     */
    public function nextBytes($nbBytes);
}
PK��Z�m2���GSymfony/Component/Security/Core/Authorization/AccessDecisionManager.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authorization;

use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;

/**
 * AccessDecisionManager is the base class for all access decision managers
 * that use decision voters.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class AccessDecisionManager implements AccessDecisionManagerInterface
{
    private $voters;
    private $strategy;
    private $allowIfAllAbstainDecisions;
    private $allowIfEqualGrantedDeniedDecisions;

    /**
     * Constructor.
     *
     * @param VoterInterface[] $voters                             An array of VoterInterface instances
     * @param string           $strategy                           The vote strategy
     * @param Boolean          $allowIfAllAbstainDecisions         Whether to grant access if all voters abstained or not
     * @param Boolean          $allowIfEqualGrantedDeniedDecisions Whether to grant access if result are equals
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(array $voters, $strategy = 'affirmative', $allowIfAllAbstainDecisions = false, $allowIfEqualGrantedDeniedDecisions = true)
    {
        if (!$voters) {
            throw new \InvalidArgumentException('You must at least add one voter.');
        }

        $strategyMethod = 'decide'.ucfirst($strategy);
        if (!is_callable(array($this, $strategyMethod))) {
            throw new \InvalidArgumentException(sprintf('The strategy "%s" is not supported.', $strategy));
        }

        $this->voters = $voters;
        $this->strategy = $strategyMethod;
        $this->allowIfAllAbstainDecisions = (Boolean) $allowIfAllAbstainDecisions;
        $this->allowIfEqualGrantedDeniedDecisions = (Boolean) $allowIfEqualGrantedDeniedDecisions;
    }

    /**
     * {@inheritdoc}
     */
    public function decide(TokenInterface $token, array $attributes, $object = null)
    {
        return $this->{$this->strategy}($token, $attributes, $object);
    }

    /**
     * {@inheritdoc}
     */
    public function supportsAttribute($attribute)
    {
        foreach ($this->voters as $voter) {
            if ($voter->supportsAttribute($attribute)) {
                return true;
            }
        }

        return false;
    }

    /**
     * {@inheritdoc}
     */
    public function supportsClass($class)
    {
        foreach ($this->voters as $voter) {
            if ($voter->supportsClass($class)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Grants access if any voter returns an affirmative response.
     *
     * If all voters abstained from voting, the decision will be based on the
     * allowIfAllAbstainDecisions property value (defaults to false).
     */
    private function decideAffirmative(TokenInterface $token, array $attributes, $object = null)
    {
        $deny = 0;
        foreach ($this->voters as $voter) {
            $result = $voter->vote($token, $object, $attributes);
            switch ($result) {
                case VoterInterface::ACCESS_GRANTED:
                    return true;

                case VoterInterface::ACCESS_DENIED:
                    ++$deny;

                    break;

                default:
                    break;
            }
        }

        if ($deny > 0) {
            return false;
        }

        return $this->allowIfAllAbstainDecisions;
    }

    /**
     * Grants access if there is consensus of granted against denied responses.
     *
     * Consensus means majority-rule (ignoring abstains) rather than unanimous
     * agreement (ignoring abstains). If you require unanimity, see
     * UnanimousBased.
     *
     * If there were an equal number of grant and deny votes, the decision will
     * be based on the allowIfEqualGrantedDeniedDecisions property value
     * (defaults to true).
     *
     * If all voters abstained from voting, the decision will be based on the
     * allowIfAllAbstainDecisions property value (defaults to false).
     */
    private function decideConsensus(TokenInterface $token, array $attributes, $object = null)
    {
        $grant = 0;
        $deny = 0;
        $abstain = 0;
        foreach ($this->voters as $voter) {
            $result = $voter->vote($token, $object, $attributes);

            switch ($result) {
                case VoterInterface::ACCESS_GRANTED:
                    ++$grant;

                    break;

                case VoterInterface::ACCESS_DENIED:
                    ++$deny;

                    break;

                default:
                    ++$abstain;

                    break;
            }
        }

        if ($grant > $deny) {
            return true;
        }

        if ($deny > $grant) {
            return false;
        }

        if ($grant == $deny && $grant != 0) {
            return $this->allowIfEqualGrantedDeniedDecisions;
        }

        return $this->allowIfAllAbstainDecisions;
    }

    /**
     * Grants access if only grant (or abstain) votes were received.
     *
     * If all voters abstained from voting, the decision will be based on the
     * allowIfAllAbstainDecisions property value (defaults to false).
     */
    private function decideUnanimous(TokenInterface $token, array $attributes, $object = null)
    {
        $grant = 0;
        foreach ($attributes as $attribute) {
            foreach ($this->voters as $voter) {
                $result = $voter->vote($token, $object, array($attribute));

                switch ($result) {
                    case VoterInterface::ACCESS_GRANTED:
                        ++$grant;

                        break;

                    case VoterInterface::ACCESS_DENIED:
                        return false;

                    default:
                        break;
                }
            }
        }

        // no deny votes
        if ($grant > 0) {
            return true;
        }

        return $this->allowIfAllAbstainDecisions;
    }
}
PK��Z�З~��ASymfony/Component/Security/Core/Authorization/Voter/RoleVoter.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authorization\Voter;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;

/**
 * RoleVoter votes if any attribute starts with a given prefix.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class RoleVoter implements VoterInterface
{
    private $prefix;

    /**
     * Constructor.
     *
     * @param string $prefix The role prefix
     */
    public function __construct($prefix = 'ROLE_')
    {
        $this->prefix = $prefix;
    }

    /**
     * {@inheritdoc}
     */
    public function supportsAttribute($attribute)
    {
        return 0 === strpos($attribute, $this->prefix);
    }

    /**
     * {@inheritdoc}
     */
    public function supportsClass($class)
    {
        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function vote(TokenInterface $token, $object, array $attributes)
    {
        $result = VoterInterface::ACCESS_ABSTAIN;
        $roles = $this->extractRoles($token);

        foreach ($attributes as $attribute) {
            if (!$this->supportsAttribute($attribute)) {
                continue;
            }

            $result = VoterInterface::ACCESS_DENIED;
            foreach ($roles as $role) {
                if ($attribute === $role->getRole()) {
                    return VoterInterface::ACCESS_GRANTED;
                }
            }
        }

        return $result;
    }

    protected function extractRoles(TokenInterface $token)
    {
        return $token->getRoles();
    }
}
PK��Z~f�JSymfony/Component/Security/Core/Authorization/Voter/RoleHierarchyVoter.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authorization\Voter;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;

/**
 * RoleHierarchyVoter uses a RoleHierarchy to determine the roles granted to
 * the user before voting.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class RoleHierarchyVoter extends RoleVoter
{
    private $roleHierarchy;

    public function __construct(RoleHierarchyInterface $roleHierarchy, $prefix = 'ROLE_')
    {
        $this->roleHierarchy = $roleHierarchy;

        parent::__construct($prefix);
    }

    /**
     * {@inheritdoc}
     */
    protected function extractRoles(TokenInterface $token)
    {
        return $this->roleHierarchy->getReachableRoles($token->getRoles());
    }
}
PK��Z��`c��GSymfony/Component/Security/Core/Authorization/Voter/ExpressionVoter.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authorization\Voter;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface;
use Symfony\Component\Security\Core\Authorization\ExpressionLanguage;
use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
use Symfony\Component\ExpressionLanguage\Expression;
use Symfony\Component\HttpFoundation\Request;

/**
 * ExpressionVoter votes based on the evaluation of an expression.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ExpressionVoter implements VoterInterface
{
    private $expressionLanguage;
    private $trustResolver;
    private $roleHierarchy;

    /**
     * Constructor.
     *
     * @param ExpressionLanguage $expressionLanguage
     */
    public function __construct(ExpressionLanguage $expressionLanguage, AuthenticationTrustResolverInterface $trustResolver, RoleHierarchyInterface $roleHierarchy = null)
    {
        $this->expressionLanguage = $expressionLanguage;
        $this->trustResolver = $trustResolver;
        $this->roleHierarchy = $roleHierarchy;
    }

    /**
     * {@inheritdoc}
     */
    public function supportsAttribute($attribute)
    {
        return $attribute instanceof Expression;
    }

    /**
     * {@inheritdoc}
     */
    public function supportsClass($class)
    {
        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function vote(TokenInterface $token, $object, array $attributes)
    {
        $result = VoterInterface::ACCESS_ABSTAIN;
        $variables = null;
        foreach ($attributes as $attribute) {
            if (!$this->supportsAttribute($attribute)) {
                continue;
            }

            if (null === $variables) {
                $variables = $this->getVariables($token, $object);
            }

            $result = VoterInterface::ACCESS_DENIED;
            if ($this->expressionLanguage->evaluate($attribute, $variables)) {
                return VoterInterface::ACCESS_GRANTED;
            }
        }

        return $result;
    }

    private function getVariables(TokenInterface $token, $object)
    {
        if (null !== $this->roleHierarchy) {
            $roles = $this->roleHierarchy->getReachableRoles($token->getRoles());
        } else {
            $roles = $token->getRoles();
        }

        $variables = array(
            'token' => $token,
            'user' => $token->getUser(),
            'object' => $object,
            'roles' => array_map(function ($role) { return $role->getRole(); }, $roles),
            'trust_resolver' => $this->trustResolver,
        );

        // this is mainly to propose a better experience when the expression is used
        // in an access control rule, as the developer does not know that it's going
        // to be handled by this voter
        if ($object instanceof Request) {
            $variables['request'] = $object;
        }

        return $variables;
    }
}
PK��Z�X,mJSymfony/Component/Security/Core/Authorization/Voter/AuthenticatedVoter.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authorization\Voter;

use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;

/**
 * AuthenticatedVoter votes if an attribute like IS_AUTHENTICATED_FULLY,
 * IS_AUTHENTICATED_REMEMBERED, or IS_AUTHENTICATED_ANONYMOUSLY is present.
 *
 * This list is most restrictive to least restrictive checking.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class AuthenticatedVoter implements VoterInterface
{
    const IS_AUTHENTICATED_FULLY = 'IS_AUTHENTICATED_FULLY';
    const IS_AUTHENTICATED_REMEMBERED = 'IS_AUTHENTICATED_REMEMBERED';
    const IS_AUTHENTICATED_ANONYMOUSLY = 'IS_AUTHENTICATED_ANONYMOUSLY';

    private $authenticationTrustResolver;

    /**
     * Constructor.
     *
     * @param AuthenticationTrustResolverInterface $authenticationTrustResolver
     */
    public function __construct(AuthenticationTrustResolverInterface $authenticationTrustResolver)
    {
        $this->authenticationTrustResolver = $authenticationTrustResolver;
    }

    /**
     * {@inheritdoc}
     */
    public function supportsAttribute($attribute)
    {
        return null !== $attribute && (self::IS_AUTHENTICATED_FULLY === $attribute || self::IS_AUTHENTICATED_REMEMBERED === $attribute || self::IS_AUTHENTICATED_ANONYMOUSLY === $attribute);
    }

    /**
     * {@inheritdoc}
     */
    public function supportsClass($class)
    {
        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function vote(TokenInterface $token, $object, array $attributes)
    {
        $result = VoterInterface::ACCESS_ABSTAIN;
        foreach ($attributes as $attribute) {
            if (!$this->supportsAttribute($attribute)) {
                continue;
            }

            $result = VoterInterface::ACCESS_DENIED;

            if (self::IS_AUTHENTICATED_FULLY === $attribute
                && $this->authenticationTrustResolver->isFullFledged($token)) {
                return VoterInterface::ACCESS_GRANTED;
            }

            if (self::IS_AUTHENTICATED_REMEMBERED === $attribute
                && ($this->authenticationTrustResolver->isRememberMe($token)
                    || $this->authenticationTrustResolver->isFullFledged($token))) {
                return VoterInterface::ACCESS_GRANTED;
            }

            if (self::IS_AUTHENTICATED_ANONYMOUSLY === $attribute
                && ($this->authenticationTrustResolver->isAnonymous($token)
                    || $this->authenticationTrustResolver->isRememberMe($token)
                    || $this->authenticationTrustResolver->isFullFledged($token))) {
                return VoterInterface::ACCESS_GRANTED;
            }
        }

        return $result;
    }
}
PK��Z�>��FSymfony/Component/Security/Core/Authorization/Voter/VoterInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authorization\Voter;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;

/**
 * VoterInterface is the interface implemented by all voters.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface VoterInterface
{
    const ACCESS_GRANTED = 1;
    const ACCESS_ABSTAIN = 0;
    const ACCESS_DENIED  = -1;

    /**
     * Checks if the voter supports the given attribute.
     *
     * @param string $attribute An attribute
     *
     * @return Boolean true if this Voter supports the attribute, false otherwise
     */
    public function supportsAttribute($attribute);

    /**
     * Checks if the voter supports the given class.
     *
     * @param string $class A class name
     *
     * @return Boolean true if this Voter can process the class
     */
    public function supportsClass($class);

    /**
     * Returns the vote for the given parameters.
     *
     * This method must return one of the following constants:
     * ACCESS_GRANTED, ACCESS_DENIED, or ACCESS_ABSTAIN.
     *
     * @param TokenInterface $token      A TokenInterface instance
     * @param object         $object     The object to secure
     * @param array          $attributes An array of attributes associated with the method being invoked
     *
     * @return integer either ACCESS_GRANTED, ACCESS_ABSTAIN, or ACCESS_DENIED
     */
    public function vote(TokenInterface $token, $object, array $attributes);
}
PK��Z�:22PSymfony/Component/Security/Core/Authorization/AccessDecisionManagerInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authorization;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;

/**
 * AccessDecisionManagerInterface makes authorization decisions.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface AccessDecisionManagerInterface
{
    /**
     * Decides whether the access is possible or not.
     *
     * @param TokenInterface $token      A TokenInterface instance
     * @param array          $attributes An array of attributes associated with the method being invoked
     * @param object         $object     The object to secure
     *
     * @return Boolean true if the access is granted, false otherwise
     */
    public function decide(TokenInterface $token, array $attributes, $object = null);

    /**
     * Checks if the access decision manager supports the given attribute.
     *
     * @param string $attribute An attribute
     *
     * @return Boolean true if this decision manager supports the attribute, false otherwise
     */
    public function supportsAttribute($attribute);

    /**
     * Checks if the access decision manager supports the given class.
     *
     * @param string $class A class name
     *
     * @return true if this decision manager can process the class
     */
    public function supportsClass($class);
}
PK��Zѵ^��DSymfony/Component/Security/Core/Authorization/ExpressionLanguage.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authorization;

use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage;

/**
 * Adds some function to the default ExpressionLanguage.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ExpressionLanguage extends BaseExpressionLanguage
{
    protected function registerFunctions()
    {
        parent::registerFunctions();

        $this->register('is_anonymous', function () {
            return '$trust_resolver->isAnonymous($token)';
        }, function (array $variables) {
            return $variables['trust_resolver']->isAnonymous($variables['token']);
        });

        $this->register('is_authenticated', function () {
            return '$token && !$trust_resolver->isAnonymous($token)';
        }, function (array $variables) {
            return $variables['token'] && !$variables['trust_resolver']->isAnonymous($variables['token']);
        });

        $this->register('is_fully_authenticated', function () {
            return '$trust_resolver->isFullFledged($token)';
        }, function (array $variables) {
            return $variables['trust_resolver']->isFullFledged($variables['token']);
        });

        $this->register('is_remember_me', function () {
            return '$trust_resolver->isRememberMe($token)';
        }, function (array $variables) {
            return $variables['trust_resolver']->isRememberMe($variables['token']);
        });

        $this->register('has_role', function ($role) {
            return sprintf('in_array(%s, $roles)', $role);
        }, function (array $variables, $role) {
            return in_array($role, $variables['roles']);
        });
    }
}
PK��Z����=Symfony/Component/Security/Core/User/UserCheckerInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\User;

/**
 * UserCheckerInterface checks user account when authentication occurs.
 *
 * This should not be used to make authentication decisions.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface UserCheckerInterface
{
    /**
     * Checks the user account before authentication.
     *
     * @param UserInterface $user a UserInterface instance
     */
    public function checkPreAuth(UserInterface $user);

    /**
     * Checks the user account after authentication.
     *
     * @param UserInterface $user a UserInterface instance
     */
    public function checkPostAuth(UserInterface $user);
}
PK��Z��^ 
 
:Symfony/Component/Security/Core/User/ChainUserProvider.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\User;

use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;

/**
 * Chain User Provider.
 *
 * This provider calls several leaf providers in a chain until one is able to
 * handle the request.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ChainUserProvider implements UserProviderInterface
{
    private $providers;

    public function __construct(array $providers)
    {
        $this->providers = $providers;
    }

    /**
     * @return array
     */
    public function getProviders()
    {
        return $this->providers;
    }

    /**
     * {@inheritDoc}
     */
    public function loadUserByUsername($username)
    {
        foreach ($this->providers as $provider) {
            try {
                return $provider->loadUserByUsername($username);
            } catch (UsernameNotFoundException $notFound) {
                // try next one
            }
        }

        $ex = new UsernameNotFoundException(sprintf('There is no user with name "%s".', $username));
        $ex->setUsername($username);
        throw $ex;
    }

    /**
     * {@inheritDoc}
     */
    public function refreshUser(UserInterface $user)
    {
        $supportedUserFound = false;

        foreach ($this->providers as $provider) {
            try {
                return $provider->refreshUser($user);
            } catch (UnsupportedUserException $unsupported) {
                // try next one
            } catch (UsernameNotFoundException $notFound) {
                $supportedUserFound = true;
                // try next one
            }
        }

        if ($supportedUserFound) {
            $ex = new UsernameNotFoundException(sprintf('There is no user with name "%s".', $user->getUsername()));
            $ex->setUsername($user->getUsername());
            throw $ex;
        } else {
            throw new UnsupportedUserException(sprintf('The account "%s" is not supported.', get_class($user)));
        }
    }

    /**
     * {@inheritDoc}
     */
    public function supportsClass($class)
    {
        foreach ($this->providers as $provider) {
            if ($provider->supportsClass($class)) {
                return true;
            }
        }

        return false;
    }
}
PK��ZD�$..4Symfony/Component/Security/Core/User/UserChecker.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\User;

use Symfony\Component\Security\Core\Exception\CredentialsExpiredException;
use Symfony\Component\Security\Core\Exception\LockedException;
use Symfony\Component\Security\Core\Exception\DisabledException;
use Symfony\Component\Security\Core\Exception\AccountExpiredException;

/**
 * UserChecker checks the user account flags.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class UserChecker implements UserCheckerInterface
{
    /**
     * {@inheritdoc}
     */
    public function checkPreAuth(UserInterface $user)
    {
        if (!$user instanceof AdvancedUserInterface) {
            return;
        }

        if (!$user->isAccountNonLocked()) {
            $ex = new LockedException('User account is locked.');
            $ex->setUser($user);
            throw $ex;
        }

        if (!$user->isEnabled()) {
            $ex = new DisabledException('User account is disabled.');
            $ex->setUser($user);
            throw $ex;
        }

        if (!$user->isAccountNonExpired()) {
            $ex = new AccountExpiredException('User account has expired.');
            $ex->setUser($user);
            throw $ex;
        }
    }

    /**
     * {@inheritdoc}
     */
    public function checkPostAuth(UserInterface $user)
    {
        if (!$user instanceof AdvancedUserInterface) {
            return;
        }

        if (!$user->isCredentialsNonExpired()) {
            $ex = new CredentialsExpiredException('User credentials have expired.');
            $ex->setUser($user);
            throw $ex;
        }
    }
}
PK��Z��6bYY>Symfony/Component/Security/Core/User/AdvancedUserInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\User;

use Symfony\Component\Security\Core\Exception\AccountStatusException;
use Symfony\Component\Security\Core\Exception\AccountExpiredException;
use Symfony\Component\Security\Core\Exception\LockedException;
use Symfony\Component\Security\Core\Exception\CredentialsExpiredException;
use Symfony\Component\Security\Core\Exception\DisabledException;

/**
 * Adds extra features to a user class related to account status flags.
 *
 * This interface can be implemented in place of UserInterface if you'd like
 * the authentication system to consider different account status flags
 * during authentication. If any of the methods in this interface return
 * false, authentication will fail.
 *
 * If you need to perform custom logic for any of these situations, then
 * you will need to register an exception listener and watch for the specific
 * exception instances thrown in each case. All exceptions are a subclass
 * of AccountStatusException
 *
 * @see UserInterface
 * @see AccountStatusException
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface AdvancedUserInterface extends UserInterface
{
    /**
     * Checks whether the user's account has expired.
     *
     * Internally, if this method returns false, the authentication system
     * will throw an AccountExpiredException and prevent login.
     *
     * @return Boolean true if the user's account is non expired, false otherwise
     *
     * @see AccountExpiredException
     */
    public function isAccountNonExpired();

    /**
     * Checks whether the user is locked.
     *
     * Internally, if this method returns false, the authentication system
     * will throw a LockedException and prevent login.
     *
     * @return Boolean true if the user is not locked, false otherwise
     *
     * @see LockedException
     */
    public function isAccountNonLocked();

    /**
     * Checks whether the user's credentials (password) has expired.
     *
     * Internally, if this method returns false, the authentication system
     * will throw a CredentialsExpiredException and prevent login.
     *
     * @return Boolean true if the user's credentials are non expired, false otherwise
     *
     * @see CredentialsExpiredException
     */
    public function isCredentialsNonExpired();

    /**
     * Checks whether the user is enabled.
     *
     * Internally, if this method returns false, the authentication system
     * will throw a DisabledException and prevent login.
     *
     * @return Boolean true if the user is enabled, false otherwise
     *
     * @see DisabledException
     */
    public function isEnabled();
}
PK��Z����	�	6Symfony/Component/Security/Core/User/UserInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\User;

use Symfony\Component\Security\Core\Role\Role;

/**
 * Represents the interface that all user classes must implement.
 *
 * This interface is useful because the authentication layer can deal with
 * the object through its lifecycle, using the object to get the encoded
 * password (for checking against a submitted password), assigning roles
 * and so on.
 *
 * Regardless of how your user are loaded or where they come from (a database,
 * configuration, web service, etc), you will have a class that implements
 * this interface. Objects that implement this interface are created and
 * loaded by different objects that implement UserProviderInterface
 *
 * @see UserProviderInterface
 * @see AdvancedUserInterface
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface UserInterface
{
    /**
     * Returns the roles granted to the user.
     *
     * <code>
     * public function getRoles()
     * {
     *     return array('ROLE_USER');
     * }
     * </code>
     *
     * Alternatively, the roles might be stored on a ``roles`` property,
     * and populated in any number of different ways when the user object
     * is created.
     *
     * @return Role[] The user roles
     */
    public function getRoles();

    /**
     * Returns the password used to authenticate the user.
     *
     * This should be the encoded password. On authentication, a plain-text
     * password will be salted, encoded, and then compared to this value.
     *
     * @return string The password
     */
    public function getPassword();

    /**
     * Returns the salt that was originally used to encode the password.
     *
     * This can return null if the password was not encoded using a salt.
     *
     * @return string|null The salt
     */
    public function getSalt();

    /**
     * Returns the username used to authenticate the user.
     *
     * @return string The username
     */
    public function getUsername();

    /**
     * Removes sensitive data from the user.
     *
     * This is important if, at any given point, sensitive information like
     * the plain-text password is stored on this object.
     */
    public function eraseCredentials();
}
PK��Z/!�=Symfony/Component/Security/Core/User/InMemoryUserProvider.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\User;

use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;

/**
 * InMemoryUserProvider is a simple non persistent user provider.
 *
 * Useful for testing, demonstration, prototyping, and for simple needs
 * (a backend with a unique admin for instance)
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class InMemoryUserProvider implements UserProviderInterface
{
    private $users;

    /**
     * Constructor.
     *
     * The user array is a hash where the keys are usernames and the values are
     * an array of attributes: 'password', 'enabled', and 'roles'.
     *
     * @param array $users An array of users
     */
    public function __construct(array $users = array())
    {
        foreach ($users as $username => $attributes) {
            $password = isset($attributes['password']) ? $attributes['password'] : null;
            $enabled = isset($attributes['enabled']) ? $attributes['enabled'] : true;
            $roles = isset($attributes['roles']) ? $attributes['roles'] : array();
            $user = new User($username, $password, $roles, $enabled, true, true, true);

            $this->createUser($user);
        }
    }

    /**
     * Adds a new User to the provider.
     *
     * @param UserInterface $user A UserInterface instance
     *
     * @throws \LogicException
     */
    public function createUser(UserInterface $user)
    {
        if (isset($this->users[strtolower($user->getUsername())])) {
            throw new \LogicException('Another user with the same username already exists.');
        }

        $this->users[strtolower($user->getUsername())] = $user;
    }

    /**
     * {@inheritdoc}
     */
    public function loadUserByUsername($username)
    {
        if (!isset($this->users[strtolower($username)])) {
            $ex = new UsernameNotFoundException(sprintf('Username "%s" does not exist.', $username));
            $ex->setUsername($username);

            throw $ex;
        }

        $user = $this->users[strtolower($username)];

        return new User($user->getUsername(), $user->getPassword(), $user->getRoles(), $user->isEnabled(), $user->isAccountNonExpired(),
                $user->isCredentialsNonExpired(), $user->isAccountNonLocked());
    }

    /**
     * {@inheritDoc}
     */
    public function refreshUser(UserInterface $user)
    {
        if (!$user instanceof User) {
            throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user)));
        }

        return $this->loadUserByUsername($user->getUsername());
    }

    /**
     * {@inheritDoc}
     */
    public function supportsClass($class)
    {
        return $class === 'Symfony\Component\Security\Core\User\User';
    }
}
PK��Z��//;Symfony/Component/Security/Core/User/EquatableInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\User;

/**
 * EquatableInterface used to test if two objects are equal in security
 * and re-authentication context.
 *
 * @author Dariusz Górecki <darek.krk@gmail.com>
 */
interface EquatableInterface
{
    /**
     * The equality comparison should neither be done by referential equality
     * nor by comparing identities (i.e. getId() === getId()).
     *
     * However, you do not need to compare every attribute, but only those that
     * are relevant for assessing whether re-authentication is required.
     *
     * Also implementation should consider that $user instance may implement
     * the extended user interface `AdvancedUserInterface`.
     *
     * @param UserInterface $user
     *
     * @return Boolean
     */
    public function isEqualTo(UserInterface $user);
}
PK��Zs�v�W	W	>Symfony/Component/Security/Core/User/UserProviderInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\User;

use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;

/**
 * Represents a class that loads UserInterface objects from some source for the authentication system.
 *
 * In a typical authentication configuration, a username (i.e. some unique
 * user identifier) credential enters the system (via form login, or any
 * method). The user provider that is configured with that authentication
 * method is asked to load the UserInterface object for the given username
 * (via loadUserByUsername) so that the rest of the process can continue.
 *
 * Internally, a user provider can load users from any source (databases,
 * configuration, web service). This is totally independent of how the authentication
 * information is submitted or what the UserInterface object looks like.
 *
 * @see UserInterface
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface UserProviderInterface
{
    /**
     * Loads the user for the given username.
     *
     * This method must throw UsernameNotFoundException if the user is not
     * found.
     *
     * @param string $username The username
     *
     * @return UserInterface
     *
     * @see UsernameNotFoundException
     *
     * @throws UsernameNotFoundException if the user is not found
     *
     */
    public function loadUserByUsername($username);

    /**
     * Refreshes the user for the account interface.
     *
     * It is up to the implementation to decide if the user data should be
     * totally reloaded (e.g. from the database), or if the UserInterface
     * object can just be merged into some internal array of users / identity
     * map.
     * @param UserInterface $user
     *
     * @return UserInterface
     *
     * @throws UnsupportedUserException if the account is not supported
     */
    public function refreshUser(UserInterface $user);

    /**
     * Whether this provider supports the given user class
     *
     * @param string $class
     *
     * @return Boolean
     */
    public function supportsClass($class);
}
PK��Z��1G	G	-Symfony/Component/Security/Core/User/User.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\User;

/**
 * User is the user implementation used by the in-memory user provider.
 *
 * This should not be used for anything else.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
final class User implements AdvancedUserInterface
{
    private $username;
    private $password;
    private $enabled;
    private $accountNonExpired;
    private $credentialsNonExpired;
    private $accountNonLocked;
    private $roles;

    public function __construct($username, $password, array $roles = array(), $enabled = true, $userNonExpired = true, $credentialsNonExpired = true, $userNonLocked = true)
    {
        if (empty($username)) {
            throw new \InvalidArgumentException('The username cannot be empty.');
        }

        $this->username = $username;
        $this->password = $password;
        $this->enabled = $enabled;
        $this->accountNonExpired = $userNonExpired;
        $this->credentialsNonExpired = $credentialsNonExpired;
        $this->accountNonLocked = $userNonLocked;
        $this->roles = $roles;
    }

    /**
     * {@inheritdoc}
     */
    public function getRoles()
    {
        return $this->roles;
    }

    /**
     * {@inheritdoc}
     */
    public function getPassword()
    {
        return $this->password;
    }

    /**
     * {@inheritdoc}
     */
    public function getSalt()
    {
        return null;
    }

    /**
     * {@inheritdoc}
     */
    public function getUsername()
    {
        return $this->username;
    }

    /**
     * {@inheritdoc}
     */
    public function isAccountNonExpired()
    {
        return $this->accountNonExpired;
    }

    /**
     * {@inheritdoc}
     */
    public function isAccountNonLocked()
    {
        return $this->accountNonLocked;
    }

    /**
     * {@inheritdoc}
     */
    public function isCredentialsNonExpired()
    {
        return $this->credentialsNonExpired;
    }

    /**
     * {@inheritdoc}
     */
    public function isEnabled()
    {
        return $this->enabled;
    }

    /**
     * {@inheritdoc}
     */
    public function eraseCredentials()
    {
    }
}
PK��Z'�za!!3Symfony/Component/Security/Core/SecurityContext.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core;

use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;

/**
 * SecurityContext is the main entry point of the Security component.
 *
 * It gives access to the token representing the current user authentication.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class SecurityContext implements SecurityContextInterface
{
    private $token;
    private $accessDecisionManager;
    private $authenticationManager;
    private $alwaysAuthenticate;

    /**
     * Constructor.
     *
     * @param AuthenticationManagerInterface      $authenticationManager An AuthenticationManager instance
     * @param AccessDecisionManagerInterface|null $accessDecisionManager An AccessDecisionManager instance
     * @param Boolean                             $alwaysAuthenticate
     */
    public function __construct(AuthenticationManagerInterface $authenticationManager, AccessDecisionManagerInterface $accessDecisionManager, $alwaysAuthenticate = false)
    {
        $this->authenticationManager = $authenticationManager;
        $this->accessDecisionManager = $accessDecisionManager;
        $this->alwaysAuthenticate = $alwaysAuthenticate;
    }

    /**
     * {@inheritdoc}
     *
     * @throws AuthenticationCredentialsNotFoundException when the security context has no authentication token.
     */
    final public function isGranted($attributes, $object = null)
    {
        if (null === $this->token) {
            throw new AuthenticationCredentialsNotFoundException('The security context contains no authentication token. One possible reason may be that there is no firewall configured for this URL.');
        }

        if ($this->alwaysAuthenticate || !$this->token->isAuthenticated()) {
            $this->token = $this->authenticationManager->authenticate($this->token);
        }

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

        return $this->accessDecisionManager->decide($this->token, $attributes, $object);
    }

    /**
     * {@inheritdoc}
     */
    public function getToken()
    {
        return $this->token;
    }

    /**
     * {@inheritdoc}
     */
    public function setToken(TokenInterface $token = null)
    {
        $this->token = $token;
    }
}
PK��Z��l�8Symfony/Component/Security/Core/AuthenticationEvents.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core;

final class AuthenticationEvents
{
    /**
     * The AUTHENTICATION_SUCCESS event occurs after a user is authenticated
     * by one provider.
     *
     * The event listener method receives a
     * Symfony\Component\Security\Core\Event\AuthenticationEvent instance.
     *
     * @var string
     */
    const AUTHENTICATION_SUCCESS = 'security.authentication.success';

    /**
     * The AUTHENTICATION_FAILURE event occurs after a user cannot be
     * authenticated by any of the providers.
     *
     * The event listener method receives a
     * Symfony\Component\Security\Core\Event\AuthenticationFailureEvent
     * instance.
     *
     * @var string
     */
    const AUTHENTICATION_FAILURE = 'security.authentication.failure';
}
PK��Zx��$ccPSymfony/Component/Security/Core/Authentication/AuthenticationProviderManager.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authentication;

use Symfony\Component\Security\Core\Event\AuthenticationFailureEvent;
use Symfony\Component\Security\Core\Event\AuthenticationEvent;
use Symfony\Component\Security\Core\AuthenticationEvents;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Security\Core\Exception\AccountStatusException;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\ProviderNotFoundException;
use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;

/**
 * AuthenticationProviderManager uses a list of AuthenticationProviderInterface
 * instances to authenticate a Token.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class AuthenticationProviderManager implements AuthenticationManagerInterface
{
    private $providers;
    private $eraseCredentials;
    private $eventDispatcher;

    /**
     * Constructor.
     *
     * @param AuthenticationProviderInterface[] $providers        An array of AuthenticationProviderInterface instances
     * @param Boolean                           $eraseCredentials Whether to erase credentials after authentication or not
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(array $providers, $eraseCredentials = true)
    {
        if (!$providers) {
            throw new \InvalidArgumentException('You must at least add one authentication provider.');
        }

        $this->providers = $providers;
        $this->eraseCredentials = (Boolean) $eraseCredentials;
    }

    public function setEventDispatcher(EventDispatcherInterface $dispatcher)
    {
        $this->eventDispatcher = $dispatcher;
    }

    /**
     * {@inheritdoc}
     */
    public function authenticate(TokenInterface $token)
    {
        $lastException = null;
        $result = null;

        foreach ($this->providers as $provider) {
            if (!$provider->supports($token)) {
                continue;
            }

            try {
                $result = $provider->authenticate($token);

                if (null !== $result) {
                    break;
                }
            } catch (AccountStatusException $e) {
                $e->setToken($token);

                throw $e;
            } catch (AuthenticationException $e) {
                $lastException = $e;
            }
        }

        if (null !== $result) {
            if (true === $this->eraseCredentials) {
                $result->eraseCredentials();
            }

            if (null !== $this->eventDispatcher) {
                $this->eventDispatcher->dispatch(AuthenticationEvents::AUTHENTICATION_SUCCESS, new AuthenticationEvent($result));
            }

            return $result;
        }

        if (null === $lastException) {
            $lastException = new ProviderNotFoundException(sprintf('No Authentication Provider found for token of class "%s".', get_class($token)));
        }

        if (null !== $this->eventDispatcher) {
            $this->eventDispatcher->dispatch(AuthenticationEvents::AUTHENTICATION_FAILURE, new AuthenticationFailureEvent($token, $lastException));
        }

        $lastException->setToken($token);

        throw $lastException;
    }
}
PK��Z¬>
##RSymfony/Component/Security/Core/Authentication/SimplePreAuthenticatorInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authentication;

use Symfony\Component\HttpFoundation\Request;

/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface SimplePreAuthenticatorInterface extends SimpleAuthenticatorInterface
{
    public function createToken(Request $request, $providerKey);
}
PK��Z��W��OSymfony/Component/Security/Core/Authentication/SimpleAuthenticatorInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authentication;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;

/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface SimpleAuthenticatorInterface
{
    public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey);

    public function supportsToken(TokenInterface $token, $providerKey);
}
PK��Z>,�vvXSymfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authentication\Provider;

use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;

/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class SimpleAuthenticationProvider implements AuthenticationProviderInterface
{
    private $simpleAuthenticator;
    private $userProvider;
    private $providerKey;

    public function __construct(SimpleAuthenticatorInterface $simpleAuthenticator, UserProviderInterface $userProvider, $providerKey)
    {
        $this->simpleAuthenticator = $simpleAuthenticator;
        $this->userProvider = $userProvider;
        $this->providerKey = $providerKey;
    }

    public function authenticate(TokenInterface $token)
    {
        $authToken = $this->simpleAuthenticator->authenticateToken($token, $this->userProvider, $this->providerKey);

        if ($authToken instanceof TokenInterface) {
            return $authToken;
        }

        throw new AuthenticationException('Simple authenticator failed to return an authenticated token.');
    }

    public function supports(TokenInterface $token)
    {
        return $this->simpleAuthenticator->supportsToken($token, $this->providerKey);
    }
}
PK��Z�USymfony/Component/Security/Core/Authentication/Provider/DaoAuthenticationProvider.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authentication\Provider;

use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\AuthenticationServiceException;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;

/**
 * DaoAuthenticationProvider uses a UserProviderInterface to retrieve the user
 * for a UsernamePasswordToken.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class DaoAuthenticationProvider extends UserAuthenticationProvider
{
    private $encoderFactory;
    private $userProvider;

    /**
     * Constructor.
     *
     * @param UserProviderInterface   $userProvider               An UserProviderInterface instance
     * @param UserCheckerInterface    $userChecker                An UserCheckerInterface instance
     * @param string                  $providerKey                The provider key
     * @param EncoderFactoryInterface $encoderFactory             An EncoderFactoryInterface instance
     * @param Boolean                 $hideUserNotFoundExceptions Whether to hide user not found exception or not
     */
    public function __construct(UserProviderInterface $userProvider, UserCheckerInterface $userChecker, $providerKey, EncoderFactoryInterface $encoderFactory, $hideUserNotFoundExceptions = true)
    {
        parent::__construct($userChecker, $providerKey, $hideUserNotFoundExceptions);

        $this->encoderFactory = $encoderFactory;
        $this->userProvider = $userProvider;
    }

    /**
     * {@inheritdoc}
     */
    protected function checkAuthentication(UserInterface $user, UsernamePasswordToken $token)
    {
        $currentUser = $token->getUser();
        if ($currentUser instanceof UserInterface) {
            if ($currentUser->getPassword() !== $user->getPassword()) {
                throw new BadCredentialsException('The credentials were changed from another session.');
            }
        } else {
            if ("" === ($presentedPassword = $token->getCredentials())) {
                throw new BadCredentialsException('The presented password cannot be empty.');
            }

            if (!$this->encoderFactory->getEncoder($user)->isPasswordValid($user->getPassword(), $presentedPassword, $user->getSalt())) {
                throw new BadCredentialsException('The presented password is invalid.');
            }
        }
    }

    /**
     * {@inheritdoc}
     */
    protected function retrieveUser($username, UsernamePasswordToken $token)
    {
        $user = $token->getUser();
        if ($user instanceof UserInterface) {
            return $user;
        }

        try {
            $user = $this->userProvider->loadUserByUsername($username);

            if (!$user instanceof UserInterface) {
                throw new AuthenticationServiceException('The user provider must return a UserInterface object.');
            }

            return $user;
        } catch (UsernameNotFoundException $notFound) {
            $notFound->setUsername($username);
            throw $notFound;
        } catch (\Exception $repositoryProblem) {
            $ex = new AuthenticationServiceException($repositoryProblem->getMessage(), 0, $repositoryProblem);
            $ex->setToken($token);
            throw $ex;
        }
    }
}
PK��Z�b�yyVSymfony/Component/Security/Core/Authentication/Provider/UserAuthenticationProvider.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authentication\Provider;

use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Exception\AuthenticationServiceException;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Role\SwitchUserRole;

/**
 * UserProviderInterface retrieves users for UsernamePasswordToken tokens.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class UserAuthenticationProvider implements AuthenticationProviderInterface
{
    private $hideUserNotFoundExceptions;
    private $userChecker;
    private $providerKey;

    /**
     * Constructor.
     *
     * @param UserCheckerInterface $userChecker                An UserCheckerInterface interface
     * @param string               $providerKey                A provider key
     * @param Boolean              $hideUserNotFoundExceptions Whether to hide user not found exception or not
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(UserCheckerInterface $userChecker, $providerKey, $hideUserNotFoundExceptions = true)
    {
        if (empty($providerKey)) {
            throw new \InvalidArgumentException('$providerKey must not be empty.');
        }

        $this->userChecker = $userChecker;
        $this->providerKey = $providerKey;
        $this->hideUserNotFoundExceptions = $hideUserNotFoundExceptions;
    }

    /**
     * {@inheritdoc}
     */
    public function authenticate(TokenInterface $token)
    {
        if (!$this->supports($token)) {
            return null;
        }

        $username = $token->getUsername();
        if (empty($username)) {
            $username = 'NONE_PROVIDED';
        }

        try {
            $user = $this->retrieveUser($username, $token);
        } catch (UsernameNotFoundException $notFound) {
            if ($this->hideUserNotFoundExceptions) {
                throw new BadCredentialsException('Bad credentials', 0, $notFound);
            }
            $notFound->setUsername($username);

            throw $notFound;
        }

        if (!$user instanceof UserInterface) {
            throw new AuthenticationServiceException('retrieveUser() must return a UserInterface.');
        }

        try {
            $this->userChecker->checkPreAuth($user);
            $this->checkAuthentication($user, $token);
            $this->userChecker->checkPostAuth($user);
        } catch (BadCredentialsException $e) {
            if ($this->hideUserNotFoundExceptions) {
                throw new BadCredentialsException('Bad credentials', 0, $e);
            }

            throw $e;
        }

        $authenticatedToken = new UsernamePasswordToken($user, $token->getCredentials(), $this->providerKey, $this->getRoles($user, $token));
        $authenticatedToken->setAttributes($token->getAttributes());

        return $authenticatedToken;
    }

    /**
     * {@inheritdoc}
     */
    public function supports(TokenInterface $token)
    {
        return $token instanceof UsernamePasswordToken && $this->providerKey === $token->getProviderKey();
    }

    /**
     * Retrieves roles from user and appends SwitchUserRole if original token contained one.
     *
     * @param UserInterface  $user  The user
     * @param TokenInterface $token The token
     *
     * @return Role[] The user roles
     */
    private function getRoles(UserInterface $user, TokenInterface $token)
    {
        $roles = $user->getRoles();

        foreach ($token->getRoles() as $role) {
            if ($role instanceof SwitchUserRole) {
                $roles[] = $role;

                break;
            }
        }

        return $roles;
    }

    /**
     * Retrieves the user from an implementation-specific location.
     *
     * @param string                $username The username to retrieve
     * @param UsernamePasswordToken $token    The Token
     *
     * @return UserInterface The user
     *
     * @throws AuthenticationException if the credentials could not be validated
     */
    abstract protected function retrieveUser($username, UsernamePasswordToken $token);

    /**
     * Does additional checks on the user and token (like validating the
     * credentials).
     *
     * @param UserInterface         $user  The retrieved UserInterface instance
     * @param UsernamePasswordToken $token The UsernamePasswordToken token to be authenticated
     *
     * @throws AuthenticationException if the credentials could not be validated
     */
    abstract protected function checkAuthentication(UserInterface $user, UsernamePasswordToken $token);
}
PK��Z�J�A��\Symfony/Component/Security/Core/Authentication/Provider/RememberMeAuthenticationProvider.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authentication\Provider;

use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;

class RememberMeAuthenticationProvider implements AuthenticationProviderInterface
{
    private $userChecker;
    private $key;
    private $providerKey;

    /**
     * Constructor.
     *
     * @param UserCheckerInterface $userChecker An UserCheckerInterface interface
     * @param string               $key         A key
     * @param string               $providerKey A provider key
     */
    public function __construct(UserCheckerInterface $userChecker, $key, $providerKey)
    {
        $this->userChecker = $userChecker;
        $this->key = $key;
        $this->providerKey = $providerKey;
    }

    /**
     * {@inheritdoc}
     */
    public function authenticate(TokenInterface $token)
    {
        if (!$this->supports($token)) {
            return;
        }

        if ($this->key !== $token->getKey()) {
            throw new BadCredentialsException('The presented key does not match.');
        }

        $user = $token->getUser();
        $this->userChecker->checkPostAuth($user);

        $authenticatedToken = new RememberMeToken($user, $this->providerKey, $this->key);
        $authenticatedToken->setAttributes($token->getAttributes());

        return $authenticatedToken;
    }

    /**
     * {@inheritdoc}
     */
    public function supports(TokenInterface $token)
    {
        return $token instanceof RememberMeToken && $token->getProviderKey() === $this->providerKey;
    }
}
PK��Z��X���[Symfony/Component/Security/Core/Authentication/Provider/AnonymousAuthenticationProvider.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authentication\Provider;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;

/**
 * AnonymousAuthenticationProvider validates AnonymousToken instances.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class AnonymousAuthenticationProvider implements AuthenticationProviderInterface
{
    private $key;

    /**
     * Constructor.
     *
     * @param string $key The key shared with the authentication token
     */
    public function __construct($key)
    {
        $this->key = $key;
    }

    /**
     * {@inheritdoc}
     */
    public function authenticate(TokenInterface $token)
    {
        if (!$this->supports($token)) {
            return null;
        }

        if ($this->key !== $token->getKey()) {
            throw new BadCredentialsException('The Token does not contain the expected key.');
        }

        return $token;
    }

    /**
     * {@inheritdoc}
     */
    public function supports(TokenInterface $token)
    {
        return $token instanceof AnonymousToken;
    }
}
PK��Z��a�""[Symfony/Component/Security/Core/Authentication/Provider/AuthenticationProviderInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authentication\Provider;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;

/**
 * AuthenticationProviderInterface is the interface for all authentication
 * providers.
 *
 * Concrete implementations processes specific Token instances.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface AuthenticationProviderInterface extends AuthenticationManagerInterface
{
    /**
     * Checks whether this provider supports the given token.
     *
     * @param TokenInterface $token A TokenInterface instance
     *
     * @return Boolean true if the implementation supports the Token, false otherwise
     */
     public function supports(TokenInterface $token);
}
PK��Zun\�
�
bSymfony/Component/Security/Core/Authentication/Provider/PreAuthenticatedAuthenticationProvider.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authentication\Provider;

use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;

/**
 * Processes a pre-authenticated authentication request.
 *
 * This authentication provider will not perform any checks on authentication
 * requests, as they should already be pre-authenticated. However, the
 * UserProviderInterface implementation may still throw a
 * UsernameNotFoundException, for example.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class PreAuthenticatedAuthenticationProvider implements AuthenticationProviderInterface
{
    private $userProvider;
    private $userChecker;
    private $providerKey;

    /**
     * Constructor.
     *
     * @param UserProviderInterface $userProvider An UserProviderInterface instance
     * @param UserCheckerInterface  $userChecker  An UserCheckerInterface instance
     * @param string                $providerKey  The provider key
     */
    public function __construct(UserProviderInterface $userProvider, UserCheckerInterface $userChecker, $providerKey)
    {
        $this->userProvider = $userProvider;
        $this->userChecker = $userChecker;
        $this->providerKey = $providerKey;
    }

     /**
      * {@inheritdoc}
      */
     public function authenticate(TokenInterface $token)
     {
         if (!$this->supports($token)) {
             return null;
         }

        if (!$user = $token->getUser()) {
            throw new BadCredentialsException('No pre-authenticated principal found in request.');
        }
/*
        if (null === $token->getCredentials()) {
            throw new BadCredentialsException('No pre-authenticated credentials found in request.');
        }
*/
        $user = $this->userProvider->loadUserByUsername($user);

        $this->userChecker->checkPostAuth($user);

        $authenticatedToken = new PreAuthenticatedToken($user, $token->getCredentials(), $this->providerKey, $user->getRoles());
        $authenticatedToken->setAttributes($token->getAttributes());

        return $authenticatedToken;
    }

    /**
     * {@inheritdoc}
     */
    public function supports(TokenInterface $token)
    {
        return $token instanceof PreAuthenticatedToken && $this->providerKey === $token->getProviderKey();
    }
}
PK��Z��r3WWWSymfony/Component/Security/Core/Authentication/AuthenticationTrustResolverInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authentication;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;

/**
 * Interface for resolving the authentication status of a given token.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface AuthenticationTrustResolverInterface
{
    /**
     * Resolves whether the passed token implementation is authenticated
     * anonymously.
     *
     * If null is passed, the method must return false.
     *
     * @param TokenInterface $token
     *
     * @return Boolean
     */
    public function isAnonymous(TokenInterface $token = null);

    /**
     * Resolves whether the passed token implementation is authenticated
     * using remember-me capabilities.
     *
     * @param TokenInterface $token
     *
     * @return Boolean
     */
    public function isRememberMe(TokenInterface $token = null);

    /**
     * Resolves whether the passed token implementation is fully authenticated.
     *
     * @param TokenInterface $token
     *
     * @return Boolean
     */
    public function isFullFledged(TokenInterface $token = null);
}
PK��Z�Zvm��SSymfony/Component/Security/Core/Authentication/RememberMe/InMemoryTokenProvider.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authentication\RememberMe;

use Symfony\Component\Security\Core\Exception\TokenNotFoundException;

/**
 * This class is used for testing purposes, and is not really suited for production.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class InMemoryTokenProvider implements TokenProviderInterface
{
    private $tokens = array();

    /**
     * {@inheritdoc}
     */
    public function loadTokenBySeries($series)
    {
        if (!isset($this->tokens[$series])) {
            throw new TokenNotFoundException('No token found.');
        }

        return $this->tokens[$series];
    }

    /**
     * {@inheritdoc}
     */
    public function updateToken($series, $tokenValue, \DateTime $lastUsed)
    {
        if (!isset($this->tokens[$series])) {
            throw new TokenNotFoundException('No token found.');
        }

        $token = new PersistentToken(
            $this->tokens[$series]->getClass(),
            $this->tokens[$series]->getUsername(),
            $series,
            $tokenValue,
            $lastUsed
        );
        $this->tokens[$series] = $token;
    }

    /**
     * {@inheritdoc}
     */
    public function deleteTokenBySeries($series)
    {
        unset($this->tokens[$series]);
    }

    /**
     * {@inheritdoc}
     */
    public function createNewToken(PersistentTokenInterface $token)
    {
        $this->tokens[$token->getSeries()] = $token;
    }
}
PK��Z���QZZVSymfony/Component/Security/Core/Authentication/RememberMe/PersistentTokenInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authentication\RememberMe;

/**
 * Interface to be implemented by persistent token classes (such as
 * Doctrine entities representing a remember-me token)
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface PersistentTokenInterface
{
    /**
     * Returns the class of the user.
     *
     * @return string
     */
    public function getClass();

    /**
     * Returns the username.
     *
     * @return string
     */
    public function getUsername();

    /**
     * Returns the series.
     *
     * @return string
     */
    public function getSeries();

    /**
     * Returns the token value.
     *
     * @return string
     */
    public function getTokenValue();

    /**
     * Returns the time the token was last used.
     *
     * @return \DateTime
     */
    public function getLastUsed();
}
PK��Z
�TO��MSymfony/Component/Security/Core/Authentication/RememberMe/PersistentToken.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authentication\RememberMe;

/**
 * This class is only used by PersistentTokenRememberMeServices internally.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
final class PersistentToken implements PersistentTokenInterface
{
    private $class;
    private $username;
    private $series;
    private $tokenValue;
    private $lastUsed;

    /**
     * Constructor
     *
     * @param string    $class
     * @param string    $username
     * @param string    $series
     * @param string    $tokenValue
     * @param \DateTime $lastUsed
     *
     * @throws \InvalidArgumentException
     */
    public function __construct($class, $username, $series, $tokenValue, \DateTime $lastUsed)
    {
        if (empty($class)) {
            throw new \InvalidArgumentException('$class must not be empty.');
        }
        if (empty($username)) {
            throw new \InvalidArgumentException('$username must not be empty.');
        }
        if (empty($series)) {
            throw new \InvalidArgumentException('$series must not be empty.');
        }
        if (empty($tokenValue)) {
            throw new \InvalidArgumentException('$tokenValue must not be empty.');
        }

        $this->class = $class;
        $this->username = $username;
        $this->series = $series;
        $this->tokenValue = $tokenValue;
        $this->lastUsed = $lastUsed;
    }

    /**
     * {@inheritdoc}
     */
    public function getClass()
    {
        return $this->class;
    }

    /**
     * {@inheritdoc}
     */
    public function getUsername()
    {
        return $this->username;
    }

    /**
     * {@inheritdoc}
     */
    public function getSeries()
    {
        return $this->series;
    }

    /**
     * {@inheritdoc}
     */
    public function getTokenValue()
    {
        return $this->tokenValue;
    }

    /**
     * {@inheritdoc}
     */
    public function getLastUsed()
    {
        return $this->lastUsed;
    }
}
PK��Z
C�f��TSymfony/Component/Security/Core/Authentication/RememberMe/TokenProviderInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authentication\RememberMe;

use Symfony\Component\Security\Core\Exception\TokenNotFoundException;

/**
 * Interface for TokenProviders
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface TokenProviderInterface
{
    /**
     * Loads the active token for the given series.
     *
     * @param string $series
     *
     * @return PersistentTokenInterface
     *
     * @throws TokenNotFoundException if the token is not found
     */
    public function loadTokenBySeries($series);

    /**
     * Deletes all tokens belonging to series.
     *
     * @param string $series
     */
    public function deleteTokenBySeries($series);

    /**
     * Updates the token according to this data.
     *
     * @param string    $series
     * @param string    $tokenValue
     * @param \DateTime $lastUsed
     * @throws TokenNotFoundException if the token is not found
     */
    public function updateToken($series, $tokenValue, \DateTime $lastUsed);

    /**
     * Creates a new token.
     *
     * @param PersistentTokenInterface $token
     */
    public function createNewToken(PersistentTokenInterface $token);
}
PK��ZJ-W;::SSymfony/Component/Security/Core/Authentication/SimpleFormAuthenticatorInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authentication;

use Symfony\Component\HttpFoundation\Request;

/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface SimpleFormAuthenticatorInterface extends SimpleAuthenticatorInterface
{
    public function createToken(Request $request, $username, $password, $providerKey);
}
PK��Z:�6��NSymfony/Component/Security/Core/Authentication/AuthenticationTrustResolver.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authentication;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;

/**
 * The default implementation of the authentication trust resolver.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class AuthenticationTrustResolver implements AuthenticationTrustResolverInterface
{
    private $anonymousClass;
    private $rememberMeClass;

    /**
     * Constructor
     *
     * @param string $anonymousClass
     * @param string $rememberMeClass
     */
    public function __construct($anonymousClass, $rememberMeClass)
    {
        $this->anonymousClass = $anonymousClass;
        $this->rememberMeClass = $rememberMeClass;
    }

    /**
     * {@inheritDoc}
     */
    public function isAnonymous(TokenInterface $token = null)
    {
        if (null === $token) {
            return false;
        }

        return $token instanceof $this->anonymousClass;
    }

    /**
     * {@inheritDoc}
     */
    public function isRememberMe(TokenInterface $token = null)
    {
        if (null === $token) {
            return false;
        }

        return $token instanceof $this->rememberMeClass;
    }

    /**
     * {@inheritDoc}
     */
    public function isFullFledged(TokenInterface $token = null)
    {
        if (null === $token) {
            return false;
        }

        return !$this->isAnonymous($token) && !$this->isRememberMe($token);
    }
}
PK��Zf�	�QSymfony/Component/Security/Core/Authentication/AuthenticationManagerInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authentication;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;

/**
 * AuthenticationManagerInterface is the interface for authentication managers,
 * which process Token authentication.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface AuthenticationManagerInterface
{
    /**
     * Attempts to authenticate a TokenInterface object.
     *
     * @param TokenInterface $token The TokenInterface instance to authenticate
     *
     * @return TokenInterface An authenticated TokenInterface instance, never null
     *
     * @throws AuthenticationException if the authentication fails
     */
    public function authenticate(TokenInterface $token);
}
PK��Zγ�__NSymfony/Component/Security/Core/Authentication/Token/PreAuthenticatedToken.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authentication\Token;

/**
 * PreAuthenticatedToken implements a pre-authenticated token.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class PreAuthenticatedToken extends AbstractToken
{
    private $credentials;
    private $providerKey;

    /**
     * Constructor.
     */
    public function __construct($user, $credentials, $providerKey, array $roles = array())
    {
        parent::__construct($roles);

        if (empty($providerKey)) {
            throw new \InvalidArgumentException('$providerKey must not be empty.');
        }

        $this->setUser($user);
        $this->credentials = $credentials;
        $this->providerKey = $providerKey;

        if ($roles) {
            $this->setAuthenticated(true);
        }
    }

    /**
     * Returns the provider key.
     *
     * @return string The provider key
     */
    public function getProviderKey()
    {
        return $this->providerKey;
    }

    /**
     * {@inheritdoc}
     */
    public function getCredentials()
    {
        return $this->credentials;
    }

    /**
     * {@inheritdoc}
     */
    public function eraseCredentials()
    {
        parent::eraseCredentials();

        $this->credentials = null;
    }

    /**
     * {@inheritdoc}
     */
    public function serialize()
    {
        return serialize(array($this->credentials, $this->providerKey, parent::serialize()));
    }

    /**
     * {@inheritdoc}
     */
    public function unserialize($str)
    {
        list($this->credentials, $this->providerKey, $parentStr) = unserialize($str);
        parent::unserialize($parentStr);
    }
}
PK��Z��4��FSymfony/Component/Security/Core/Authentication/Token/AbstractToken.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authentication\Token;

use Symfony\Component\Security\Core\Role\RoleInterface;
use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
use Symfony\Component\Security\Core\User\EquatableInterface;

/**
 * Base class for Token instances.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
abstract class AbstractToken implements TokenInterface
{
    private $user;
    private $roles = array();
    private $authenticated = false;
    private $attributes = array();

    /**
     * Constructor.
     *
     * @param RoleInterface[] $roles An array of roles
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(array $roles = array())
    {
        foreach ($roles as $role) {
            if (is_string($role)) {
                $role = new Role($role);
            } elseif (!$role instanceof RoleInterface) {
                throw new \InvalidArgumentException(sprintf('$roles must be an array of strings, or RoleInterface instances, but got %s.', gettype($role)));
            }

            $this->roles[] = $role;
        }
    }

    /**
     * {@inheritdoc}
     */
    public function getRoles()
    {
        return $this->roles;
    }

    /**
     * {@inheritdoc}
     */
    public function getUsername()
    {
        if ($this->user instanceof UserInterface) {
            return $this->user->getUsername();
        }

        return (string) $this->user;
    }

    /**
     * {@inheritdoc}
     */
    public function getUser()
    {
        return $this->user;
    }

    /**
     * Sets the user in the token.
     *
     * The user can be a UserInterface instance, or an object implementing
     * a __toString method or the username as a regular string.
     *
     * @param mixed $user The user
     * @throws \InvalidArgumentException
     */
    public function setUser($user)
    {
        if (!($user instanceof UserInterface || (is_object($user) && method_exists($user, '__toString')) || is_string($user))) {
            throw new \InvalidArgumentException('$user must be an instanceof UserInterface, an object implementing a __toString method, or a primitive string.');
        }

        if (null === $this->user) {
            $changed = false;
        } elseif ($this->user instanceof UserInterface) {
            if (!$user instanceof UserInterface) {
                $changed = true;
            } else {
                $changed = $this->hasUserChanged($user);
            }
        } elseif ($user instanceof UserInterface) {
            $changed = true;
        } else {
            $changed = (string) $this->user !== (string) $user;
        }

        if ($changed) {
            $this->setAuthenticated(false);
        }

        $this->user = $user;
    }

    /**
     * {@inheritdoc}
     */
    public function isAuthenticated()
    {
        return $this->authenticated;
    }

    /**
     * {@inheritdoc}
     */
    public function setAuthenticated($authenticated)
    {
        $this->authenticated = (Boolean) $authenticated;
    }

    /**
     * {@inheritdoc}
     */
    public function eraseCredentials()
    {
        if ($this->getUser() instanceof UserInterface) {
            $this->getUser()->eraseCredentials();
        }
    }

    /**
     * {@inheritdoc}
     */
    public function serialize()
    {
        return serialize(
            array(
                is_object($this->user) ? clone $this->user : $this->user,
                $this->authenticated,
                $this->roles,
                $this->attributes
            )
        );
    }

    /**
     * {@inheritdoc}
     */
    public function unserialize($serialized)
    {
        list($this->user, $this->authenticated, $this->roles, $this->attributes) = unserialize($serialized);
    }

    /**
     * Returns the token attributes.
     *
     * @return array The token attributes
     */
    public function getAttributes()
    {
        return $this->attributes;
    }

    /**
     * Sets the token attributes.
     *
     * @param array $attributes The token attributes
     */
    public function setAttributes(array $attributes)
    {
        $this->attributes = $attributes;
    }

    /**
     * Returns true if the attribute exists.
     *
     * @param string $name The attribute name
     *
     * @return Boolean true if the attribute exists, false otherwise
     */
    public function hasAttribute($name)
    {
        return array_key_exists($name, $this->attributes);
    }

    /**
     * Returns an attribute value.
     *
     * @param string $name The attribute name
     *
     * @return mixed The attribute value
     *
     * @throws \InvalidArgumentException When attribute doesn't exist for this token
     */
    public function getAttribute($name)
    {
        if (!array_key_exists($name, $this->attributes)) {
            throw new \InvalidArgumentException(sprintf('This token has no "%s" attribute.', $name));
        }

        return $this->attributes[$name];
    }

    /**
     * Sets an attribute.
     *
     * @param string $name  The attribute name
     * @param mixed  $value The attribute value
     */
    public function setAttribute($name, $value)
    {
        $this->attributes[$name] = $value;
    }

    /**
     * {@inheritDoc}
     */
    public function __toString()
    {
        $class = get_class($this);
        $class = substr($class, strrpos($class, '\\')+1);

        $roles = array();
        foreach ($this->roles as $role) {
            $roles[] = $role->getRole();
        }

        return sprintf('%s(user="%s", authenticated=%s, roles="%s")', $class, $this->getUsername(), json_encode($this->authenticated), implode(', ', $roles));
    }

    private function hasUserChanged(UserInterface $user)
    {
        if (!($this->user instanceof UserInterface)) {
            throw new \BadMethodCallException('Method "hasUserChanged" should be called when current user class is instance of "UserInterface".');
        }

        if ($this->user instanceof EquatableInterface) {
            return ! (Boolean) $this->user->isEqualTo($user);
        }

        if ($this->user->getPassword() !== $user->getPassword()) {
            return true;
        }

        if ($this->user->getSalt() !== $user->getSalt()) {
            return true;
        }

        if ($this->user->getUsername() !== $user->getUsername()) {
            return true;
        }

        if ($this->user instanceof AdvancedUserInterface && $user instanceof AdvancedUserInterface) {
            if ($this->user->isAccountNonExpired() !== $user->isAccountNonExpired()) {
                return true;
            }

            if ($this->user->isAccountNonLocked() !== $user->isAccountNonLocked()) {
                return true;
            }

            if ($this->user->isCredentialsNonExpired() !== $user->isCredentialsNonExpired()) {
                return true;
            }

            if ($this->user->isEnabled() !== $user->isEnabled()) {
                return true;
            }
        } elseif ($this->user instanceof AdvancedUserInterface xor $user instanceof AdvancedUserInterface) {
            return true;
        }

        return false;
    }
}
PK��Z�tC��GSymfony/Component/Security/Core/Authentication/Token/TokenInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authentication\Token;

use Symfony\Component\Security\Core\Role\RoleInterface;

/**
 * TokenInterface is the interface for the user authentication information.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface TokenInterface extends \Serializable
{
    /**
     * Returns a string representation of the Token.
     *
     * This is only to be used for debugging purposes.
     *
     * @return string
     */
    public function __toString();

    /**
     * Returns the user roles.
     *
     * @return RoleInterface[] An array of RoleInterface instances.
     */
    public function getRoles();

    /**
     * Returns the user credentials.
     *
     * @return mixed The user credentials
     */
    public function getCredentials();

    /**
     * Returns a user representation.
     *
     * @return mixed either returns an object which implements __toString(), or
     *                  a primitive string is returned.
     */
    public function getUser();

    /**
     * Sets a user.
     *
     * @param mixed $user
     */
    public function setUser($user);

    /**
     * Returns the username.
     *
     * @return string
     */
    public function getUsername();

    /**
     * Returns whether the user is authenticated or not.
     *
     * @return Boolean true if the token has been authenticated, false otherwise
     */
    public function isAuthenticated();

    /**
     * Sets the authenticated flag.
     *
     * @param Boolean $isAuthenticated The authenticated flag
     */
    public function setAuthenticated($isAuthenticated);

    /**
     * Removes sensitive information from the token.
     */
    public function eraseCredentials();

    /**
     * Returns the token attributes.
     *
     * @return array The token attributes
     */
    public function getAttributes();

    /**
     * Sets the token attributes.
     *
     * @param array $attributes The token attributes
     */
    public function setAttributes(array $attributes);

    /**
     * Returns true if the attribute exists.
     *
     * @param string $name The attribute name
     *
     * @return Boolean true if the attribute exists, false otherwise
     */
    public function hasAttribute($name);

    /**
     * Returns an attribute value.
     *
     * @param string $name The attribute name
     *
     * @return mixed The attribute value
     *
     * @throws \InvalidArgumentException When attribute doesn't exist for this token
     */
    public function getAttribute($name);

    /**
     * Sets an attribute.
     *
     * @param string $name  The attribute name
     * @param mixed  $value The attribute value
     */
    public function setAttribute($name, $value);
}
PK��Z{Z�--GSymfony/Component/Security/Core/Authentication/Token/AnonymousToken.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authentication\Token;

use Symfony\Component\Security\Core\Role\RoleInterface;

/**
 * AnonymousToken represents an anonymous token.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class AnonymousToken extends AbstractToken
{
    private $key;

    /**
     * Constructor.
     *
     * @param string          $key   The key shared with the authentication provider
     * @param string          $user  The user
     * @param RoleInterface[] $roles An array of roles
     */
    public function __construct($key, $user, array $roles = array())
    {
        parent::__construct($roles);

        $this->key = $key;
        $this->setUser($user);
        $this->setAuthenticated(true);
    }

    /**
     * {@inheritdoc}
     */
    public function getCredentials()
    {
        return '';
    }

    /**
     * Returns the key.
     *
     * @return string The Key
     */
    public function getKey()
    {
        return $this->key;
    }

    /**
     * {@inheritDoc}
     */
    public function serialize()
    {
        return serialize(array($this->key, parent::serialize()));
    }

    /**
     * {@inheritDoc}
     */
    public function unserialize($serialized)
    {
        list($this->key, $parentStr) = unserialize($serialized);
        parent::unserialize($parentStr);
    }
}
PK��Z�6��`
`
NSymfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authentication\Token;

use Symfony\Component\Security\Core\Role\RoleInterface;

/**
 * UsernamePasswordToken implements a username and password token.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class UsernamePasswordToken extends AbstractToken
{
    private $credentials;
    private $providerKey;

    /**
     * Constructor.
     *
     * @param string          $user        The username (like a nickname, email address, etc.), or a UserInterface instance or an object implementing a __toString method.
     * @param string          $credentials This usually is the password of the user
     * @param string          $providerKey The provider key
     * @param RoleInterface[] $roles       An array of roles
     *
     * @throws \InvalidArgumentException
     */
    public function __construct($user, $credentials, $providerKey, array $roles = array())
    {
        parent::__construct($roles);

        if (empty($providerKey)) {
            throw new \InvalidArgumentException('$providerKey must not be empty.');
        }

        $this->setUser($user);
        $this->credentials = $credentials;
        $this->providerKey = $providerKey;

        parent::setAuthenticated(count($roles) > 0);
    }

    /**
     * {@inheritdoc}
     */
    public function setAuthenticated($isAuthenticated)
    {
        if ($isAuthenticated) {
            throw new \LogicException('Cannot set this token to trusted after instantiation.');
        }

        parent::setAuthenticated(false);
    }

    /**
     * {@inheritdoc}
     */
    public function getCredentials()
    {
        return $this->credentials;
    }

    /**
     * Returns the provider key.
     *
     * @return string The provider key
     */
    public function getProviderKey()
    {
        return $this->providerKey;
    }

    /**
     * {@inheritdoc}
     */
    public function eraseCredentials()
    {
        parent::eraseCredentials();

        $this->credentials = null;
    }

    /**
     * {@inheritdoc}
     */
    public function serialize()
    {
        return serialize(array($this->credentials, $this->providerKey, parent::serialize()));
    }

    /**
     * {@inheritdoc}
     */
    public function unserialize($serialized)
    {
        list($this->credentials, $this->providerKey, $parentStr) = unserialize($serialized);
        parent::unserialize($parentStr);
    }
}
PK��Z��w�	�	HSymfony/Component/Security/Core/Authentication/Token/RememberMeToken.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Authentication\Token;

use Symfony\Component\Security\Core\User\UserInterface;

/**
 * Authentication Token for "Remember-Me".
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class RememberMeToken extends AbstractToken
{
    private $key;
    private $providerKey;

    /**
     * Constructor.
     *
     * @param UserInterface $user
     * @param string        $providerKey
     * @param string        $key
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(UserInterface $user, $providerKey, $key)
    {
        parent::__construct($user->getRoles());

        if (empty($key)) {
            throw new \InvalidArgumentException('$key must not be empty.');
        }

        if (empty($providerKey)) {
            throw new \InvalidArgumentException('$providerKey must not be empty.');
        }

        $this->providerKey = $providerKey;
        $this->key = $key;

        $this->setUser($user);
        parent::setAuthenticated(true);
    }

    /**
     * {@inheritdoc}
     */
    public function setAuthenticated($authenticated)
    {
        if ($authenticated) {
            throw new \LogicException('You cannot set this token to authenticated after creation.');
        }

        parent::setAuthenticated(false);
    }

    /**
     * Returns the provider key.
     *
     * @return string The provider key
     */
    public function getProviderKey()
    {
        return $this->providerKey;
    }

    /**
     * Returns the key.
     *
     * @return string The Key
     */
    public function getKey()
    {
        return $this->key;
    }

    /**
     * {@inheritdoc}
     */
    public function getCredentials()
    {
        return '';
    }

    /**
     * {@inheritdoc}
     */
    public function serialize()
    {
        return serialize(array(
            $this->key,
            $this->providerKey,
            parent::serialize(),
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function unserialize($serialized)
    {
        list($this->key, $this->providerKey, $parentStr) = unserialize($serialized);
        parent::unserialize($parentStr);
    }
}
PK��Zm�|JJKSymfony/Component/Security/Core/Resources/translations/security.sr_Cyrl.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Изузетак при аутентификацији.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Аутентификациони подаци нису пронађени.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Захтев за аутентификацију не може бити обрађен због системских проблема.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Невалидни подаци за аутентификацију.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Колачић је већ искоришћен од стране неког другог.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Немате права приступа овом ресурсу.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Невалидан CSRF токен.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Време криптографског кључа је истекло.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Аутентификациони провајдер за подршку токена није пронађен.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Сесија није доступна, истекла је или су колачићи искључени.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Токен не може бити пронађен.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Корисничко име не може бити пронађено.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Налог је истекао.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Подаци за аутентификацију су истекли.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Налог је онемогућен.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Налог је закључан.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z&MЎ�
�
FSymfony/Component/Security/Core/Resources/translations/security.es.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Ocurrió un error de autenticación.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>No se encontraron las credenciales de autenticación.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>La solicitud de autenticación no se pudo procesar debido a un problema del sistema.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Credenciales no válidas.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>La cookie ya ha sido usada por otra persona.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>No tiene privilegios para solicitar el recurso.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Token CSRF no válido.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>El vector de inicialización (digest nonce) ha expirado.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>No se encontró un proveedor de autenticación que soporte el token de autenticación.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>No hay ninguna sesión disponible, ha expirado o las cookies no están habilitados.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>No se encontró ningún token.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>No se encontró el nombre de usuario.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>La cuenta ha expirado.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Las credenciales han expirado.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>La cuenta está deshabilitada.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>La cuenta está bloqueada.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��ZM-�@FSymfony/Component/Security/Core/Resources/translations/security.fa.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>خطایی هنگام تعیین اعتبار اتفاق افتاد.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>شرایط تعیین اعتبار پیدا نشد.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>درخواست تعیین اعتبار به دلیل مشکل سیستم قابل بررسی نیست.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>شرایط نامعتبر.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>کوکی قبلا برای شخص دیگری استفاده شده است.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>دسترسی لازم برای درخواست این منبع را ندارید.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>توکن CSRF معتبر نیست.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Digest nonce منقضی شده است.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>هیچ ارایه کننده تعیین اعتباری برای ساپورت توکن تعیین اعتبار پیدا نشد.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>جلسه‌ای در دسترس نیست. این میتواند یا به دلیل پایان یافتن زمان باشد یا اینکه کوکی ها فعال نیستند.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>هیچ توکنی پیدا نشد.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>نام ‌کاربری پیدا نشد.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>حساب کاربری منقضی شده است.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>پارامترهای تعیین اعتبار منقضی شده‌اند.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>حساب کاربری غیرفعال است.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>حساب کاربری قفل شده است.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Zd�e��
�
FSymfony/Component/Security/Core/Resources/translations/security.fr.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Une exception d'authentification s'est produite.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Les droits d'authentification n'ont pas pu être trouvés.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>La requête d'authentification n'a pas pu être executée à cause d'un problème système.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Droits invalides.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Le cookie a déjà été utilisé par quelqu'un d'autre.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Pas de privilèges pour accéder à la ressource.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Jeton CSRF invalide.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Le digest nonce a expiré.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Aucun fournisseur d'authentification n'a été trouvé pour supporter le jeton d'authentification.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Pas de session disponible, celle-ci a expiré ou les cookies ne sont pas activés.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Aucun jeton n'a pu être trouvé.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Le nom d'utilisateur ne peut pas être trouvé.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Le compte a expiré.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Les droits ont expirés.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Le compte est désactivé.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Le compte est bloqué.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�)�
�
FSymfony/Component/Security/Core/Resources/translations/security.ro.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>A apărut o eroare de autentificare.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Informațiile de autentificare nu au fost găsite.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Sistemul nu a putut procesa cererea de autentificare din cauza unei erori.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Date de autentificare invalide.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookieul este folosit deja de altcineva.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Permisiuni insuficiente pentru resursa cerută.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Tokenul CSRF este invalid.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Tokenul temporar a expirat.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Nu a fost găsit nici un agent de autentificare pentru tokenul specificat.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Sesiunea nu mai este disponibilă, a expirat sau suportul pentru cookieuri nu este activat.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Tokenul nu a putut fi găsit.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Numele de utilizator nu a fost găsit.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Contul a expirat.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Datele de autentificare au expirat.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Contul este dezactivat.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Contul este blocat.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�y��
�
FSymfony/Component/Security/Core/Resources/translations/security.gl.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Ocorreu un erro de autenticación.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Non se atoparon as credenciais de autenticación.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>A solicitude de autenticación no puido ser procesada debido a un problema do sistema.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Credenciais non válidas.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>A cookie xa foi empregado por outro usuario.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Non ten privilexios para solicitar o recurso.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Token CSRF non válido.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>O vector de inicialización (digest nonce) expirou.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Non se atopou un provedor de autenticación que soporte o token de autenticación.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Non hai ningunha sesión dispoñible, expirou ou as cookies non están habilitadas.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Non se atopou ningún token.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Non se atopou o nome de usuario.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>A conta expirou.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>As credenciais expiraron.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>A conta está deshabilitada.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>A conta está bloqueada.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z��u^
^
FSymfony/Component/Security/Core/Resources/translations/security.sv.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Ett autentiseringsfel har inträffat.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Uppgifterna för autentisering kunde inte hittas.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Autentiseringen kunde inte genomföras på grund av systemfel.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Felaktiga uppgifter.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookien har redan använts av någon annan.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Saknar rättigheter för resursen.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Ogiltig CSRF-token.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Förfallen digest nonce.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Ingen leverantör för autentisering hittades för angiven autentiseringstoken.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Ingen session finns tillgänglig, antingen har den förfallit eller är cookies inte aktiverat.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Ingen token kunde hittas.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Användarnamnet kunde inte hittas.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Kontot har förfallit.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Uppgifterna har förfallit.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Kontot är inaktiverat.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Kontot är låst.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z���ţ
�
FSymfony/Component/Security/Core/Resources/translations/security.ca.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Ha succeït un error d'autenticació.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>No s'han trobat les credencials d'autenticació.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>La solicitud d'autenticació no s'ha pogut processar per un problema del sistema.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Credencials no vàlides.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>La cookie ja ha estat utilitzada per una altra persona.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>No té privilegis per solicitar el recurs.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Token CSRF no vàlid.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>El vector d'inicialització (digest nonce) ha expirat.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>No s'ha trobat un proveïdor d'autenticació que suporti el token d'autenticació.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>No hi ha sessió disponible, ha expirat o les cookies no estan habilitades.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>No s'ha trobat cap token.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>No s'ha trobat el nom d'usuari.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>El compte ha expirat.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Les credencials han expirat.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>El compte està deshabilitat.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>El compte està bloquejat.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Zo'�N�
�
FSymfony/Component/Security/Core/Resources/translations/security.de.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Es ist ein Fehler bei der Authentifikation aufgetreten.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Es konnten keine Zugangsdaten gefunden werden.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Die Authentifikation konnte wegen eines Systemproblems nicht bearbeitet werden.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Fehlerhafte Zugangsdaten.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie wurde bereits von jemand anderem verwendet.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Keine Rechte, um die Ressource anzufragen.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Ungültiges CSRF-Token.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Digest nonce ist abgelaufen.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Es wurde kein Authentifizierungs-Provider gefunden, der das Authentifizierungs-Token unterstützt.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Keine Session verfügbar, entweder ist diese abgelaufen oder Cookies sind nicht aktiviert.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Es wurde kein Token gefunden.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Der Benutzername wurde nicht gefunden.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Der Account ist abgelaufen.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Die Zugangsdaten sind abgelaufen.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Der Account ist deaktiviert.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Der Account ist gesperrt.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z.W�
�
FSymfony/Component/Security/Core/Resources/translations/security.no.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="no" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>En autentiserings feil har skjedd.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Påloggingsinformasjonen kunne ikke bli funnet.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Autentiserings forespørselen kunne ikke bli prosessert grunnet en system feil.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Ugyldig påloggingsinformasjonen.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie har allerede blitt brukt av noen andre.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Ingen tilgang til å be om gitt kilde.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Ugyldig CSRF token.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Digest nonce er utløpt.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Ingen autentiserings tilbyder funnet som støtter gitt autentiserings token.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Ingen sesjon tilgjengelig, sesjonen er enten utløpt eller cookies ikke skrudd på.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Ingen token kunne bli funnet.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Brukernavn kunne ikke bli funnet.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Brukerkonto har utgått.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Påloggingsinformasjon har utløpt.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Brukerkonto er deaktivert.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Brukerkonto er sperret.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z��ق
�
FSymfony/Component/Security/Core/Resources/translations/security.sk.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Pri overovaní došlo k chybe.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Overovacie údaje neboli nájdené.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Požiadavok na overenie nemohol byť spracovaný kvôli systémovej chybe.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Neplatné prihlasovacie údaje.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie už bolo použité niekým iným.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Nemáte oprávnenie pristupovať k prostriedku.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Neplatný CSRF token.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Platnosť inicializačného vektoru (digest nonce) skončila.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Poskytovateľ pre overovací token nebol nájdený.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Session nie je k dispozíci, vypršala jej platnosť, alebo sú zakázané cookies.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Token nebol nájdený.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Prihlasovacie meno nebolo nájdené.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Platnosť účtu skončila.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Platnosť prihlasovacích údajov skončila.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Účet je zakázaný.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Účet je zablokovaný.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�w=���FSymfony/Component/Security/Core/Resources/translations/security.ru.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Ошибка аутентификации.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Аутентификационные данные не найдены.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Запрос аутентификации не может быть обработан в связи с проблемой в системе.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Недействительные аутентификационные данные.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie уже был использован кем-то другим.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Отсутствуют права на запрос этого ресурса.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Недействительный токен CSRF.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Время действия одноразового ключа дайджеста истекло.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Не найден провайдер аутентификации, поддерживающий токен аутентификации.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Сессия не найдена, ее время истекло, либо cookies не включены.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Токен не найден.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Имя пользователя не найдено.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Время действия учетной записи истекло.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Время действия аутентификационных данных истекло.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Учетная запись отключена.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Учетная запись заблокирована.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��ZUɎd
d
FSymfony/Component/Security/Core/Resources/translations/security.sl.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Prišlo je do izjeme pri preverjanju avtentikacije.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Poverilnic za avtentikacijo ni bilo mogoče najti.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Zahteve za avtentikacijo ni bilo mogoče izvesti zaradi sistemske težave.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Neveljavne pravice.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Piškotek je uporabil že nekdo drug.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Nimate privilegijev za zahtevani vir.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Neveljaven CSRF žeton.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Začasni žeton je potekel.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Ponudnika avtentikacije za podporo prijavnega žetona ni bilo mogoče najti.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Seja ni na voljo, ali je potekla ali pa piškotki niso omogočeni.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Žetona ni bilo mogoče najti.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Uporabniškega imena ni bilo mogoče najti.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Račun je potekel.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Poverilnice so potekle.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Račun je onemogočen.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Račun je zaklenjen.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z���
�
FSymfony/Component/Security/Core/Resources/translations/security.lb.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" target-language="lb" datatype="plaintext" original="security.en.xlf">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Bei der Authentifikatioun ass e Feeler opgetrueden.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Et konnte keng Zouganksdate fonnt ginn.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>D'Ufro fir eng Authentifikatioun konnt wéinst engem Problem vum System net beaarbecht ginn.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Ongëlteg Zouganksdaten.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>De Cookie gouf scho vun engem anere benotzt.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Keng Rechter fir d'Ressource unzefroen.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Ongëltegen CSRF-Token.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Den eemolege Schlëssel ass ofgelaf.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Et gouf keen Authentifizéierungs-Provider fonnt deen den Authentifizéierungs-Token ënnerstëtzt.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Keng Sëtzung disponibel. Entweder ass se ofgelaf oder Cookies sinn net aktivéiert.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Et konnt keen Token fonnt ginn.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>De Benotzernumm konnt net fonnt ginn.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Den Account ass ofgelaf.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>D'Zouganksdate sinn ofgelaf.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>De Konto ass deaktivéiert.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>De Konto ass gespaart.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�#@�y
y
ISymfony/Component/Security/Core/Resources/translations/security.pt_PT.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Ocorreu um excepção durante a autenticação.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>As credenciais de autenticação não foram encontradas.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>O pedido de autenticação não foi concluído devido a um problema no sistema.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Credenciais inválidas.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Este cookie já esta em uso.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Não possui privilégios para aceder a este recurso.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Token CSRF inválido.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Digest nonce expirado.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Nenhum fornecedor de autenticação encontrado para suportar o token de autenticação.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Não existe sessão disponível, esta expirou ou os cookies estão desativados.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>O token não foi encontrado.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Nome de utilizador não encontrado.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>A conta expirou.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>As credenciais expiraram.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Conta desativada.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>A conta esta trancada.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��ZYW��g
g
KSymfony/Component/Security/Core/Resources/translations/security.sr_Latn.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Izuzetak pri autentifikaciji.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Autentifikacioni podaci nisu pronađeni.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Zahtev za autentifikaciju ne može biti obrađen zbog sistemskih problema.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Nevalidni podaci za autentifikaciju.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Kolačić je već iskorišćen od strane nekog drugog.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Nemate prava pristupa ovom resursu.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Nevalidan CSRF token.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Vreme kriptografskog ključa je isteklo.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Autentifikacioni provajder za podršku tokena nije pronađen.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Sesija nije dostupna, istekla je ili su kolačići isključeni.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Token ne može biti pronađen.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Korisničko ime ne može biti pronađeno.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Nalog je istekao.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Podaci za autentifikaciju su istekli.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Nalog je onemogućen.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Nalog je zaključan.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�=���
�
ISymfony/Component/Security/Core/Resources/translations/security.pt_BR.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Uma exceção ocorreu durante a autenticação.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>As credenciais de autenticação não foram encontradas.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>A autenticação não pôde ser concluída devido a um problema no sistema.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Credenciais inválidas.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Este cookie já esta em uso.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Não possui privilégios o bastante para requisitar este recurso.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Token CSRF inválido.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Digest nonce expirado.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Nenhum provedor de autenticação encontrado para suportar o token de autenticação.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Nenhuma sessão disponível, ela expirou ou cookies estão desativados.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Nenhum token foi encontrado.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Nome de usuário não encontrado.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>A conta esta expirada.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>As credenciais estão expiradas.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Conta desativada.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>A conta esta travada.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z(���
�
FSymfony/Component/Security/Core/Resources/translations/security.cs.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Při ověřování došlo k chybě.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Ověřovací údaje nebyly nalezeny.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Požadavek na ověření nemohl být zpracován kvůli systémové chybě.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Neplatné přihlašovací údaje.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie již bylo použité někým jiným.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Nemáte oprávnění přistupovat k prostředku.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Neplatný CSRF token.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Platnost inicializačního vektoru (digest nonce) vypršela.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Poskytovatel pro ověřovací token nebyl nalezen.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Session není k dispozici, vypršela její platnost, nebo jsou zakázané cookies.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Token nebyl nalezen.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Přihlašovací jméno nebylo nalezeno.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Platnost účtu vypršela.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Platnost přihlašovacích údajů vypršela.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Účet je zakázaný.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Účet je zablokovaný.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��ZO�
�
FSymfony/Component/Security/Core/Resources/translations/security.it.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Si è verificato un errore di autenticazione.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Impossibile trovare le credenziali di autenticazione.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>La richiesta di autenticazione non può essere processata a causa di un errore di sistema.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Credenziali non valide.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Il cookie è già stato usato da qualcun altro.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Non hai i privilegi per richiedere questa risorsa.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>CSRF token non valido.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Il numero di autenticazione è scaduto.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Non è stato trovato un valido fornitore di autenticazione per supportare il token.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Nessuna sessione disponibile, può essere scaduta o i cookie non sono abilitati.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Nessun token trovato.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Username non trovato.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Account scaduto.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Credenziali scadute.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>L'account è disabilitato.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>L'account è bloccato.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��ZTk�f��FSymfony/Component/Security/Core/Resources/translations/security.ar.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>حدث خطأ اثناء الدخول.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>لم استطع العثور على معلومات الدخول.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>لم يكتمل طلب الدخول نتيجه عطل فى النظام.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>معلومات الدخول خاطئة.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>ملفات تعريف الارتباط(cookies) تم استخدامها من قبل شخص اخر.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>ليست لديك الصلاحيات الكافية لهذا الطلب.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>رمز الموقع غير صحيح.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>انتهت صلاحية(digest nonce).</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>لا يوجد معرف للدخول يدعم الرمز المستخدم للدخول.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>لا يوجد صلة بينك و بين الموقع اما انها انتهت او ان متصفحك لا يدعم خاصية ملفات تعريف الارتباط (cookies).</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>لم استطع العثور على الرمز.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>لم استطع العثور على اسم الدخول.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>انتهت صلاحية الحساب.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>انتهت صلاحية معلومات الدخول.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>الحساب موقوف.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>الحساب مغلق.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z��|H�
�
FSymfony/Component/Security/Core/Resources/translations/security.hu.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Hitelesítési hiba lépett fel.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Nem találhatók hitelesítési információk.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>A hitelesítési kérést rendszerhiba miatt nem lehet feldolgozni.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Érvénytelen hitelesítési információk.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Ezt a sütit valaki más már felhasználta.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Nem rendelkezik az erőforrás eléréséhez szükséges jogosultsággal.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Érvénytelen CSRF token.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>A kivonat bélyege (nonce) lejárt.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Nem található a hitelesítési tokent támogató hitelesítési szolgáltatás.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Munkamenet nem áll rendelkezésre, túllépte az időkeretet vagy a sütik le vannak tiltva.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Nem található token.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>A felhasználónév nem található.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>A fiók lejárt.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>A hitelesítési információk lejártak.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Felfüggesztett fiók.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Zárolt fiók.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�p�U�
�
FSymfony/Component/Security/Core/Resources/translations/security.nl.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Er heeft zich een authenticatieprobleem voorgedaan.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Authenticatiegegevens konden niet worden gevonden.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Authenticatieaanvraag kon niet worden verwerkt door een technisch probleem.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Ongeldige inloggegevens.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie is al door een ander persoon gebruikt.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Onvoldoende rechten om de aanvraag te verwerken.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>CSRF-code is ongeldig.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Serverauthenticatiesleutel (digest nonce) is verlopen.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Geen authenticatieprovider gevonden die de authenticatietoken ondersteunt.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Geen sessie beschikbaar, mogelijk is deze verlopen of cookies zijn uitgeschakeld.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Er kon geen authenticatietoken worden gevonden.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Gebruikersnaam kon niet worden gevonden.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Account is verlopen.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Authenticatiegegevens zijn verlopen.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Account is gedeactiveerd.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Account is geblokkeerd.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z'���{
{
FSymfony/Component/Security/Core/Resources/translations/security.tr.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Bir yetkilendirme istisnası oluştu.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Yetkilendirme girdileri bulunamadı.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Bir sistem hatası nedeniyle yetkilendirme isteği işleme alınamıyor.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Geçersiz girdiler.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Çerez bir başkası tarafından zaten kullanılmıştı.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Kaynak talebi için imtiyaz bulunamadı.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Geçersiz CSRF fişi.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Derleme zaman aşımı gerçekleşti.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Yetkilendirme fişini destekleyecek yetkilendirme sağlayıcısı bulunamadı.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Oturum bulunamadı, zaman aşımına uğradı veya çerezler etkin değil.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Bilet bulunamadı.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Kullanıcı adı bulunamadı.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Hesap zaman aşımına uğradı.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Girdiler zaman aşımına uğradı.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Hesap devre dışı bırakılmış.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Hesap kilitlenmiş.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��ZU����FSymfony/Component/Security/Core/Resources/translations/security.el.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Συνέβη ένα σφάλμα πιστοποίησης.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Τα στοιχεία πιστοποίησης δε βρέθηκαν.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Το αίτημα πιστοποίησης δε μπορεί να επεξεργαστεί λόγω σφάλματος του συστήματος.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Λανθασμένα στοιχεία σύνδεσης.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Το Cookie έχει ήδη χρησιμοποιηθεί από κάποιον άλλο.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Δεν είστε εξουσιοδοτημένος για πρόσβαση στο συγκεκριμένο περιεχόμενο.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Μη έγκυρο CSRF token.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Το digest nonce έχει λήξει.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Δε βρέθηκε κάποιος πάροχος πιστοποίησης που να υποστηρίζει το token πιστοποίησης.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Δεν υπάρχει ενεργή σύνοδος (session), είτε έχει λήξει ή τα cookies δεν είναι ενεργοποιημένα.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Δεν ήταν δυνατόν να βρεθεί κάποιο token.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Το Username δε βρέθηκε.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Ο λογαριασμός έχει λήξει.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Τα στοιχεία σύνδεσης έχουν λήξει.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Ο λογαριασμός είναι απενεργοποιημένος.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Ο λογαριασμός είναι κλειδωμένος.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z.�X:
:
FSymfony/Component/Security/Core/Resources/translations/security.en.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>An authentication exception occurred.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Authentication credentials could not be found.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Authentication request could not be processed due to a system problem.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Invalid credentials.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie has already been used by someone else.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Not privileged to request the resource.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Invalid CSRF token.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Digest nonce has expired.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>No authentication provider found to support the authentication token.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>No session available, it either timed out or cookies are not enabled.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>No token could be found.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Username could not be found.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Account has expired.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Credentials have expired.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Account is disabled.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Account is locked.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�d
�
�
FSymfony/Component/Security/Core/Resources/translations/security.pl.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Wystąpił błąd uwierzytelniania.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Dane uwierzytelniania nie zostały znalezione.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Żądanie uwierzytelniania nie mogło zostać pomyślnie zakończone z powodu problemu z systemem.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Nieprawidłowe dane.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>To ciasteczko jest używane przez kogoś innego.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Brak uprawnień dla żądania wskazanego zasobu.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Nieprawidłowy token CSRF.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Kod dostępu wygasł.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Nie znaleziono mechanizmu uwierzytelniania zdolnego do obsługi przesłanego tokenu.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Brak danych sesji, sesja wygasła lub ciasteczka nie są włączone.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Nie znaleziono tokenu.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Użytkownik o podanej nazwie nie istnieje.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Konto wygasło.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Dane uwierzytelniania wygasły.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Konto jest wyłączone.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Konto jest zablokowane.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z5�˙��FSymfony/Component/Security/Core/Resources/translations/security.ua.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Помилка автентифікації.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Автентифікаційні дані не знайдено.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Запит на автентифікацію не може бути опрацьовано у зв’язку з проблемою в системі.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Невірні автентифікаційні дані.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Хтось інший вже використав цей сookie.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Відсутні права на запит цього ресурсу.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Невірний токен CSRF.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Закінчився термін дії одноразового ключа дайджесту.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Не знайдено провайдера автентифікації, що підтримує токен автентифікаціії.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Сесія недоступна, її час вийшов, або cookies вимкнено.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Токен не знайдено.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Ім’я користувача не знайдено.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Термін дії облікового запису вичерпано.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Термін дії автентифікаційних даних вичерпано.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Обліковий запис відключено.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Обліковий запис заблоковано.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Zz��
J
J
FSymfony/Component/Security/Core/Resources/translations/security.da.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="no" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>En fejl indtraf ved godkendelse.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Loginoplysninger kan findes.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Godkendelsesanmodning kan ikke behandles på grund af et systemfejl.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Ugyldige loginoplysninger.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie er allerede brugt af en anden.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Ingen tilladselese at anvende kilden.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Ugyldigt CSRF token.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Digest nonce er udløbet.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Ingen godkendelsesudbyder er fundet til understøttelsen af godkendelsestoken.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Ingen session tilgængelig, sessionen er enten udløbet eller cookies er ikke aktiveret.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Ingen token kan findes.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Brugernavn kan ikke findes.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Brugerkonto er udløbet.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Loginoplysninger er udløbet.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Brugerkonto er deaktiveret.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Brugerkonto er låst.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z��Eh��DSymfony/Component/Security/Core/Event/AuthenticationFailureEvent.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Event;

use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;

/**
 * This event is dispatched on authentication failure.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class AuthenticationFailureEvent extends AuthenticationEvent
{
    private $authenticationException;

    public function __construct(TokenInterface $token, AuthenticationException $ex)
    {
        parent::__construct($token);

        $this->authenticationException = $ex;
    }

    public function getAuthenticationException()
    {
        return $this->authenticationException;
    }
}
PK��Z+\�
//=Symfony/Component/Security/Core/Event/AuthenticationEvent.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Event;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\EventDispatcher\Event;

/**
 * This is a general purpose authentication event.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class AuthenticationEvent extends Event
{
    private $authenticationToken;

    public function __construct(TokenInterface $token)
    {
        $this->authenticationToken = $token;
    }

    public function getAuthenticationToken()
    {
        return $this->authenticationToken;
    }
}
PK��Z���(SSASymfony/Component/Security/Resources/translations/security.bg.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Грешка при автентикация.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Удостоверението за автентикация не е открито.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Заявката за автентикация не може да бъде обработената поради системна грешка.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Невалидно удостоверение за автентикация.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Това cookie вече се ползва от някой друг.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Нямате права за достъп до този ресурс.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Невалиден CSRF токен.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Digest nonce е изтекъл.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Не е открит провайдър, който да поддържа този токен за автентикация.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Сесията не е достъпна, или времето за достъп е изтекло, или кукитата не са разрешени.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Токена не е открит.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Потребителското име не е открито.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Акаунта е изтекъл.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Удостоверението за автентикация е изтекло.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Акаунта е деактивиран.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Акаунта е заключен.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Zm�|JJFSymfony/Component/Security/Resources/translations/security.sr_Cyrl.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Изузетак при аутентификацији.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Аутентификациони подаци нису пронађени.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Захтев за аутентификацију не може бити обрађен због системских проблема.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Невалидни подаци за аутентификацију.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Колачић је већ искоришћен од стране неког другог.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Немате права приступа овом ресурсу.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Невалидан CSRF токен.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Време криптографског кључа је истекло.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Аутентификациони провајдер за подршку токена није пронађен.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Сесија није доступна, истекла је или су колачићи искључени.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Токен не може бити пронађен.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Корисничко име не може бити пронађено.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Налог је истекао.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Подаци за аутентификацију су истекли.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Налог је онемогућен.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Налог је закључан.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z&MЎ�
�
ASymfony/Component/Security/Resources/translations/security.es.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Ocurrió un error de autenticación.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>No se encontraron las credenciales de autenticación.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>La solicitud de autenticación no se pudo procesar debido a un problema del sistema.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Credenciales no válidas.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>La cookie ya ha sido usada por otra persona.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>No tiene privilegios para solicitar el recurso.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Token CSRF no válido.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>El vector de inicialización (digest nonce) ha expirado.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>No se encontró un proveedor de autenticación que soporte el token de autenticación.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>No hay ninguna sesión disponible, ha expirado o las cookies no están habilitados.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>No se encontró ningún token.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>No se encontró el nombre de usuario.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>La cuenta ha expirado.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Las credenciales han expirado.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>La cuenta está deshabilitada.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>La cuenta está bloqueada.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��ZM-�@ASymfony/Component/Security/Resources/translations/security.fa.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>خطایی هنگام تعیین اعتبار اتفاق افتاد.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>شرایط تعیین اعتبار پیدا نشد.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>درخواست تعیین اعتبار به دلیل مشکل سیستم قابل بررسی نیست.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>شرایط نامعتبر.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>کوکی قبلا برای شخص دیگری استفاده شده است.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>دسترسی لازم برای درخواست این منبع را ندارید.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>توکن CSRF معتبر نیست.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Digest nonce منقضی شده است.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>هیچ ارایه کننده تعیین اعتباری برای ساپورت توکن تعیین اعتبار پیدا نشد.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>جلسه‌ای در دسترس نیست. این میتواند یا به دلیل پایان یافتن زمان باشد یا اینکه کوکی ها فعال نیستند.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>هیچ توکنی پیدا نشد.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>نام ‌کاربری پیدا نشد.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>حساب کاربری منقضی شده است.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>پارامترهای تعیین اعتبار منقضی شده‌اند.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>حساب کاربری غیرفعال است.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>حساب کاربری قفل شده است.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z���ASymfony/Component/Security/Resources/translations/security.vi.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Có lỗi trong quá trình xác thực.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Thông tin dùng để xác thực không tìm thấy.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Yêu cầu xác thực không thể thực hiện do lỗi của hệ thống.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Thông tin dùng để xác thực không hợp lệ.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie đã được dùng bởi người dùng khác.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Không được phép yêu cầu tài nguyên.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Mã CSRF không hợp lệ.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Mã dùng một lần đã hết hạn.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Không tìm thấy nhà cung cấp dịch vụ xác thực nào cho mã xác thực mà bạn sử dụng.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Không tìm thấy phiên làm việc. Phiên làm việc hoặc cookie có thể bị tắt.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Không tìm thấy mã token.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Không tìm thấy tên người dùng username.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Tài khoản đã hết hạn.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Thông tin xác thực đã hết hạn.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Tài khoản bị tạm ngừng.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Tài khoản bị khóa.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Zd�e��
�
ASymfony/Component/Security/Resources/translations/security.fr.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Une exception d'authentification s'est produite.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Les droits d'authentification n'ont pas pu être trouvés.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>La requête d'authentification n'a pas pu être executée à cause d'un problème système.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Droits invalides.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Le cookie a déjà été utilisé par quelqu'un d'autre.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Pas de privilèges pour accéder à la ressource.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Jeton CSRF invalide.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Le digest nonce a expiré.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Aucun fournisseur d'authentification n'a été trouvé pour supporter le jeton d'authentification.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Pas de session disponible, celle-ci a expiré ou les cookies ne sont pas activés.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Aucun jeton n'a pu être trouvé.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Le nom d'utilisateur ne peut pas être trouvé.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Le compte a expiré.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Les droits ont expirés.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Le compte est désactivé.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Le compte est bloqué.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�)�
�
ASymfony/Component/Security/Resources/translations/security.ro.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>A apărut o eroare de autentificare.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Informațiile de autentificare nu au fost găsite.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Sistemul nu a putut procesa cererea de autentificare din cauza unei erori.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Date de autentificare invalide.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookieul este folosit deja de altcineva.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Permisiuni insuficiente pentru resursa cerută.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Tokenul CSRF este invalid.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Tokenul temporar a expirat.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Nu a fost găsit nici un agent de autentificare pentru tokenul specificat.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Sesiunea nu mai este disponibilă, a expirat sau suportul pentru cookieuri nu este activat.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Tokenul nu a putut fi găsit.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Numele de utilizator nu a fost găsit.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Contul a expirat.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Datele de autentificare au expirat.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Contul este dezactivat.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Contul este blocat.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�y��
�
ASymfony/Component/Security/Resources/translations/security.gl.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Ocorreu un erro de autenticación.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Non se atoparon as credenciais de autenticación.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>A solicitude de autenticación no puido ser procesada debido a un problema do sistema.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Credenciais non válidas.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>A cookie xa foi empregado por outro usuario.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Non ten privilexios para solicitar o recurso.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Token CSRF non válido.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>O vector de inicialización (digest nonce) expirou.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Non se atopou un provedor de autenticación que soporte o token de autenticación.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Non hai ningunha sesión dispoñible, expirou ou as cookies non están habilitadas.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Non se atopou ningún token.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Non se atopou o nome de usuario.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>A conta expirou.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>As credenciais expiraron.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>A conta está deshabilitada.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>A conta está bloqueada.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z��u^
^
ASymfony/Component/Security/Resources/translations/security.sv.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Ett autentiseringsfel har inträffat.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Uppgifterna för autentisering kunde inte hittas.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Autentiseringen kunde inte genomföras på grund av systemfel.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Felaktiga uppgifter.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookien har redan använts av någon annan.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Saknar rättigheter för resursen.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Ogiltig CSRF-token.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Förfallen digest nonce.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Ingen leverantör för autentisering hittades för angiven autentiseringstoken.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Ingen session finns tillgänglig, antingen har den förfallit eller är cookies inte aktiverat.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Ingen token kunde hittas.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Användarnamnet kunde inte hittas.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Kontot har förfallit.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Uppgifterna har förfallit.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Kontot är inaktiverat.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Kontot är låst.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z���ţ
�
ASymfony/Component/Security/Resources/translations/security.ca.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Ha succeït un error d'autenticació.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>No s'han trobat les credencials d'autenticació.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>La solicitud d'autenticació no s'ha pogut processar per un problema del sistema.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Credencials no vàlides.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>La cookie ja ha estat utilitzada per una altra persona.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>No té privilegis per solicitar el recurs.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Token CSRF no vàlid.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>El vector d'inicialització (digest nonce) ha expirat.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>No s'ha trobat un proveïdor d'autenticació que suporti el token d'autenticació.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>No hi ha sessió disponible, ha expirat o les cookies no estan habilitades.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>No s'ha trobat cap token.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>No s'ha trobat el nom d'usuari.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>El compte ha expirat.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Les credencials han expirat.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>El compte està deshabilitat.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>El compte està bloquejat.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Zo'�N�
�
ASymfony/Component/Security/Resources/translations/security.de.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Es ist ein Fehler bei der Authentifikation aufgetreten.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Es konnten keine Zugangsdaten gefunden werden.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Die Authentifikation konnte wegen eines Systemproblems nicht bearbeitet werden.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Fehlerhafte Zugangsdaten.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie wurde bereits von jemand anderem verwendet.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Keine Rechte, um die Ressource anzufragen.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Ungültiges CSRF-Token.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Digest nonce ist abgelaufen.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Es wurde kein Authentifizierungs-Provider gefunden, der das Authentifizierungs-Token unterstützt.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Keine Session verfügbar, entweder ist diese abgelaufen oder Cookies sind nicht aktiviert.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Es wurde kein Token gefunden.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Der Benutzername wurde nicht gefunden.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Der Account ist abgelaufen.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Die Zugangsdaten sind abgelaufen.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Der Account ist deaktiviert.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Der Account ist gesperrt.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z����
�
ASymfony/Component/Security/Resources/translations/security.no.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>En autentiserings feil har skjedd.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Påloggingsinformasjonen kunne ikke bli funnet.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Autentiserings forespørselen kunne ikke bli prosessert grunnet en system feil.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Ugyldig påloggingsinformasjonen.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie har allerede blitt brukt av noen andre.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Ingen tilgang til å be om gitt kilde.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Ugyldig CSRF token.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Digest nonce er utløpt.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Ingen autentiserings tilbyder funnet som støtter gitt autentiserings token.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Ingen sesjon tilgjengelig, sesjonen er enten utløpt eller cookies ikke skrudd på.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Ingen token kunne bli funnet.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Brukernavn kunne ikke bli funnet.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Brukerkonto har utgått.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Påloggingsinformasjon har utløpt.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Brukerkonto er deaktivert.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Brukerkonto er sperret.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�R�wD
D
ASymfony/Component/Security/Resources/translations/security.id.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Terjadi sebuah pengecualian otentikasi.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Kredensial otentikasi tidak bisa ditemukan.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Permintaan otentikasi tidak bisa diproses karena masalah sistem.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Kredensial salah.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie sudah digunakan oleh orang lain.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Tidak berhak untuk meminta sumber daya.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Token CSRF salah.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Digest nonce telah berakhir.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Tidak ditemukan penyedia otentikasi untuk mendukung token otentikasi.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Tidak ada sesi yang tersedia, mungkin waktu sudah habis atau cookie tidak diaktifkan</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Tidak ada token yang bisa ditemukan.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Username tidak bisa ditemukan.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Akun telah berakhir.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Kredensial telah berakhir.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Akun dinonaktifkan.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Akun terkunci.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z��ق
�
ASymfony/Component/Security/Resources/translations/security.sk.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Pri overovaní došlo k chybe.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Overovacie údaje neboli nájdené.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Požiadavok na overenie nemohol byť spracovaný kvôli systémovej chybe.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Neplatné prihlasovacie údaje.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie už bolo použité niekým iným.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Nemáte oprávnenie pristupovať k prostriedku.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Neplatný CSRF token.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Platnosť inicializačného vektoru (digest nonce) skončila.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Poskytovateľ pre overovací token nebol nájdený.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Session nie je k dispozíci, vypršala jej platnosť, alebo sú zakázané cookies.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Token nebol nájdený.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Prihlasovacie meno nebolo nájdené.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Platnosť účtu skončila.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Platnosť prihlasovacích údajov skončila.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Účet je zakázaný.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Účet je zablokovaný.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�w=���ASymfony/Component/Security/Resources/translations/security.ru.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Ошибка аутентификации.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Аутентификационные данные не найдены.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Запрос аутентификации не может быть обработан в связи с проблемой в системе.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Недействительные аутентификационные данные.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie уже был использован кем-то другим.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Отсутствуют права на запрос этого ресурса.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Недействительный токен CSRF.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Время действия одноразового ключа дайджеста истекло.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Не найден провайдер аутентификации, поддерживающий токен аутентификации.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Сессия не найдена, ее время истекло, либо cookies не включены.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Токен не найден.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Имя пользователя не найдено.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Время действия учетной записи истекло.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Время действия аутентификационных данных истекло.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Учетная запись отключена.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Учетная запись заблокирована.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��ZUɎd
d
ASymfony/Component/Security/Resources/translations/security.sl.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Prišlo je do izjeme pri preverjanju avtentikacije.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Poverilnic za avtentikacijo ni bilo mogoče najti.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Zahteve za avtentikacijo ni bilo mogoče izvesti zaradi sistemske težave.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Neveljavne pravice.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Piškotek je uporabil že nekdo drug.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Nimate privilegijev za zahtevani vir.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Neveljaven CSRF žeton.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Začasni žeton je potekel.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Ponudnika avtentikacije za podporo prijavnega žetona ni bilo mogoče najti.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Seja ni na voljo, ali je potekla ali pa piškotki niso omogočeni.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Žetona ni bilo mogoče najti.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Uporabniškega imena ni bilo mogoče najti.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Račun je potekel.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Poverilnice so potekle.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Račun je onemogočen.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Račun je zaklenjen.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z]��W
W
ASymfony/Component/Security/Resources/translations/security.hr.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Dogodila se autentifikacijske iznimka.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Autentifikacijski podaci nisu pronađeni.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Autentifikacijski zahtjev nije moguće provesti uslijed sistemskog problema.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Neispravni akreditacijski podaci.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie je već netko drugi iskoristio.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Nemate privilegije zahtijevati resurs.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Neispravan CSRF token.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Digest nonce je isteko.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Nije pronađen autentifikacijski provider koji bi podržao autentifikacijski token.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Sesija nije dostupna, ili je istekla ili cookies nisu omogućeni.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Token nije pronađen.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Korisničko ime nije pronađeno.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Račun je isteko.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Akreditacijski podaci su istekli.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Račun je onemogućen.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Račun je zaključan.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z���
�
ASymfony/Component/Security/Resources/translations/security.lb.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" target-language="lb" datatype="plaintext" original="security.en.xlf">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Bei der Authentifikatioun ass e Feeler opgetrueden.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Et konnte keng Zouganksdate fonnt ginn.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>D'Ufro fir eng Authentifikatioun konnt wéinst engem Problem vum System net beaarbecht ginn.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Ongëlteg Zouganksdaten.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>De Cookie gouf scho vun engem anere benotzt.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Keng Rechter fir d'Ressource unzefroen.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Ongëltegen CSRF-Token.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Den eemolege Schlëssel ass ofgelaf.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Et gouf keen Authentifizéierungs-Provider fonnt deen den Authentifizéierungs-Token ënnerstëtzt.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Keng Sëtzung disponibel. Entweder ass se ofgelaf oder Cookies sinn net aktivéiert.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Et konnt keen Token fonnt ginn.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>De Benotzernumm konnt net fonnt ginn.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Den Account ass ofgelaf.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>D'Zouganksdate sinn ofgelaf.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>De Konto ass deaktivéiert.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>De Konto ass gespaart.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�#@�y
y
DSymfony/Component/Security/Resources/translations/security.pt_PT.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Ocorreu um excepção durante a autenticação.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>As credenciais de autenticação não foram encontradas.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>O pedido de autenticação não foi concluído devido a um problema no sistema.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Credenciais inválidas.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Este cookie já esta em uso.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Não possui privilégios para aceder a este recurso.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Token CSRF inválido.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Digest nonce expirado.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Nenhum fornecedor de autenticação encontrado para suportar o token de autenticação.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Não existe sessão disponível, esta expirou ou os cookies estão desativados.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>O token não foi encontrado.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Nome de utilizador não encontrado.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>A conta expirou.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>As credenciais expiraram.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Conta desativada.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>A conta esta trancada.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��ZYW��g
g
FSymfony/Component/Security/Resources/translations/security.sr_Latn.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Izuzetak pri autentifikaciji.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Autentifikacioni podaci nisu pronađeni.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Zahtev za autentifikaciju ne može biti obrađen zbog sistemskih problema.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Nevalidni podaci za autentifikaciju.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Kolačić je već iskorišćen od strane nekog drugog.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Nemate prava pristupa ovom resursu.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Nevalidan CSRF token.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Vreme kriptografskog ključa je isteklo.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Autentifikacioni provajder za podršku tokena nije pronađen.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Sesija nije dostupna, istekla je ili su kolačići isključeni.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Token ne može biti pronađen.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Korisničko ime ne može biti pronađeno.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Nalog je istekao.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Podaci za autentifikaciju su istekli.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Nalog je onemogućen.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Nalog je zaključan.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z���Y�
�
DSymfony/Component/Security/Resources/translations/security.pt_BR.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Uma exceção ocorreu durante a autenticação.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>As credenciais de autenticação não foram encontradas.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>A autenticação não pôde ser concluída devido a um problema no sistema.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Credenciais inválidas.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Este cookie já está em uso.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Não possui privilégios o bastante para requisitar este recurso.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Token CSRF inválido.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Digest nonce expirado.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Nenhum provedor de autenticação encontrado para suportar o token de autenticação.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Nenhuma sessão disponível, ela expirou ou os cookies estão desativados.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Nenhum token foi encontrado.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Nome de usuário não encontrado.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>A conta está expirada.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>As credenciais estão expiradas.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Conta desativada.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>A conta está travada.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z(���
�
ASymfony/Component/Security/Resources/translations/security.cs.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Při ověřování došlo k chybě.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Ověřovací údaje nebyly nalezeny.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Požadavek na ověření nemohl být zpracován kvůli systémové chybě.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Neplatné přihlašovací údaje.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie již bylo použité někým jiným.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Nemáte oprávnění přistupovat k prostředku.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Neplatný CSRF token.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Platnost inicializačního vektoru (digest nonce) vypršela.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Poskytovatel pro ověřovací token nebyl nalezen.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Session není k dispozici, vypršela její platnost, nebo jsou zakázané cookies.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Token nebyl nalezen.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Přihlašovací jméno nebylo nalezeno.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Platnost účtu vypršela.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Platnost přihlašovacích údajů vypršela.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Účet je zakázaný.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Účet je zablokovaný.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��ZO�
�
ASymfony/Component/Security/Resources/translations/security.it.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Si è verificato un errore di autenticazione.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Impossibile trovare le credenziali di autenticazione.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>La richiesta di autenticazione non può essere processata a causa di un errore di sistema.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Credenziali non valide.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Il cookie è già stato usato da qualcun altro.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Non hai i privilegi per richiedere questa risorsa.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>CSRF token non valido.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Il numero di autenticazione è scaduto.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Non è stato trovato un valido fornitore di autenticazione per supportare il token.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Nessuna sessione disponibile, può essere scaduta o i cookie non sono abilitati.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Nessun token trovato.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Username non trovato.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Account scaduto.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Credenziali scadute.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>L'account è disabilitato.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>L'account è bloccato.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��ZTk�f��ASymfony/Component/Security/Resources/translations/security.ar.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>حدث خطأ اثناء الدخول.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>لم استطع العثور على معلومات الدخول.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>لم يكتمل طلب الدخول نتيجه عطل فى النظام.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>معلومات الدخول خاطئة.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>ملفات تعريف الارتباط(cookies) تم استخدامها من قبل شخص اخر.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>ليست لديك الصلاحيات الكافية لهذا الطلب.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>رمز الموقع غير صحيح.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>انتهت صلاحية(digest nonce).</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>لا يوجد معرف للدخول يدعم الرمز المستخدم للدخول.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>لا يوجد صلة بينك و بين الموقع اما انها انتهت او ان متصفحك لا يدعم خاصية ملفات تعريف الارتباط (cookies).</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>لم استطع العثور على الرمز.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>لم استطع العثور على اسم الدخول.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>انتهت صلاحية الحساب.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>انتهت صلاحية معلومات الدخول.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>الحساب موقوف.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>الحساب مغلق.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z��|H�
�
ASymfony/Component/Security/Resources/translations/security.hu.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Hitelesítési hiba lépett fel.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Nem találhatók hitelesítési információk.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>A hitelesítési kérést rendszerhiba miatt nem lehet feldolgozni.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Érvénytelen hitelesítési információk.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Ezt a sütit valaki más már felhasználta.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Nem rendelkezik az erőforrás eléréséhez szükséges jogosultsággal.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Érvénytelen CSRF token.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>A kivonat bélyege (nonce) lejárt.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Nem található a hitelesítési tokent támogató hitelesítési szolgáltatás.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Munkamenet nem áll rendelkezésre, túllépte az időkeretet vagy a sütik le vannak tiltva.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Nem található token.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>A felhasználónév nem található.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>A fiók lejárt.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>A hitelesítési információk lejártak.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Felfüggesztett fiók.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Zárolt fiók.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�p�U�
�
ASymfony/Component/Security/Resources/translations/security.nl.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Er heeft zich een authenticatieprobleem voorgedaan.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Authenticatiegegevens konden niet worden gevonden.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Authenticatieaanvraag kon niet worden verwerkt door een technisch probleem.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Ongeldige inloggegevens.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie is al door een ander persoon gebruikt.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Onvoldoende rechten om de aanvraag te verwerken.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>CSRF-code is ongeldig.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Serverauthenticatiesleutel (digest nonce) is verlopen.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Geen authenticatieprovider gevonden die de authenticatietoken ondersteunt.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Geen sessie beschikbaar, mogelijk is deze verlopen of cookies zijn uitgeschakeld.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Er kon geen authenticatietoken worden gevonden.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Gebruikersnaam kon niet worden gevonden.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Account is verlopen.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Authenticatiegegevens zijn verlopen.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Account is gedeactiveerd.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Account is geblokkeerd.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z'���{
{
ASymfony/Component/Security/Resources/translations/security.tr.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Bir yetkilendirme istisnası oluştu.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Yetkilendirme girdileri bulunamadı.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Bir sistem hatası nedeniyle yetkilendirme isteği işleme alınamıyor.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Geçersiz girdiler.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Çerez bir başkası tarafından zaten kullanılmıştı.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Kaynak talebi için imtiyaz bulunamadı.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Geçersiz CSRF fişi.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Derleme zaman aşımı gerçekleşti.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Yetkilendirme fişini destekleyecek yetkilendirme sağlayıcısı bulunamadı.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Oturum bulunamadı, zaman aşımına uğradı veya çerezler etkin değil.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Bilet bulunamadı.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Kullanıcı adı bulunamadı.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Hesap zaman aşımına uğradı.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Girdiler zaman aşımına uğradı.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Hesap devre dışı bırakılmış.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Hesap kilitlenmiş.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��ZU����ASymfony/Component/Security/Resources/translations/security.el.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Συνέβη ένα σφάλμα πιστοποίησης.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Τα στοιχεία πιστοποίησης δε βρέθηκαν.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Το αίτημα πιστοποίησης δε μπορεί να επεξεργαστεί λόγω σφάλματος του συστήματος.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Λανθασμένα στοιχεία σύνδεσης.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Το Cookie έχει ήδη χρησιμοποιηθεί από κάποιον άλλο.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Δεν είστε εξουσιοδοτημένος για πρόσβαση στο συγκεκριμένο περιεχόμενο.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Μη έγκυρο CSRF token.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Το digest nonce έχει λήξει.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Δε βρέθηκε κάποιος πάροχος πιστοποίησης που να υποστηρίζει το token πιστοποίησης.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Δεν υπάρχει ενεργή σύνοδος (session), είτε έχει λήξει ή τα cookies δεν είναι ενεργοποιημένα.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Δεν ήταν δυνατόν να βρεθεί κάποιο token.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Το Username δε βρέθηκε.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Ο λογαριασμός έχει λήξει.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Τα στοιχεία σύνδεσης έχουν λήξει.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Ο λογαριασμός είναι απενεργοποιημένος.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Ο λογαριασμός είναι κλειδωμένος.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z��Dt��DSymfony/Component/Security/Resources/translations/security.zh_CN.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>身份验证发生异常。</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>没有找到身份验证的凭证。</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>由于系统故障,身份验证的请求无法被处理。</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>无效的凭证。</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie 已经被其他人使用。</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>没有权限请求此资源。</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>无效的 CSRF token 。</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>摘要随机串(digest nonce)已过期。</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>没有找到支持此 token 的身份验证服务提供方。</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Session 不可用。会话超时或没有启用 cookies 。</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>找不到 token 。</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>找不到用户名。</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>帐号已过期。</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>凭证已过期。</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>帐号已被禁用。</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>帐号已被锁定。</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z.�X:
:
ASymfony/Component/Security/Resources/translations/security.en.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>An authentication exception occurred.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Authentication credentials could not be found.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Authentication request could not be processed due to a system problem.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Invalid credentials.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie has already been used by someone else.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Not privileged to request the resource.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Invalid CSRF token.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Digest nonce has expired.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>No authentication provider found to support the authentication token.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>No session available, it either timed out or cookies are not enabled.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>No token could be found.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Username could not be found.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Account has expired.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Credentials have expired.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Account is disabled.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Account is locked.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�d
�
�
ASymfony/Component/Security/Resources/translations/security.pl.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Wystąpił błąd uwierzytelniania.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Dane uwierzytelniania nie zostały znalezione.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Żądanie uwierzytelniania nie mogło zostać pomyślnie zakończone z powodu problemu z systemem.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Nieprawidłowe dane.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>To ciasteczko jest używane przez kogoś innego.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Brak uprawnień dla żądania wskazanego zasobu.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Nieprawidłowy token CSRF.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Kod dostępu wygasł.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Nie znaleziono mechanizmu uwierzytelniania zdolnego do obsługi przesłanego tokenu.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Brak danych sesji, sesja wygasła lub ciasteczka nie są włączone.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Nie znaleziono tokenu.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Użytkownik o podanej nazwie nie istnieje.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Konto wygasło.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Dane uwierzytelniania wygasły.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Konto jest wyłączone.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Konto jest zablokowane.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�f488ASymfony/Component/Security/Resources/translations/security.ja.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>認証エラーが発生しました。</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>認証資格がありません。</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>システムの問題により認証要求を処理できませんでした。</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>資格が無効です。</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie が別のユーザーで使用されています。</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>リソースをリクエストする権限がありません。</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>CSRF トークンが無効です。</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Digest の nonce 値が期限切れです。</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>認証トークンをサポートする認証プロバイダーが見つかりません。</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>利用可能なセッションがありません。タイムアウトしたか、Cookie が無効になっています。</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>トークンが見つかりません。</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>ユーザー名が見つかりません。</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>アカウントが有効期限切れです。</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>資格が有効期限切れです。</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>アカウントが無効です。</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>アカウントはロックされています。</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z5�˙��ASymfony/Component/Security/Resources/translations/security.ua.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Помилка автентифікації.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Автентифікаційні дані не знайдено.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Запит на автентифікацію не може бути опрацьовано у зв’язку з проблемою в системі.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Невірні автентифікаційні дані.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Хтось інший вже використав цей сookie.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Відсутні права на запит цього ресурсу.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Невірний токен CSRF.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Закінчився термін дії одноразового ключа дайджесту.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Не знайдено провайдера автентифікації, що підтримує токен автентифікаціії.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Сесія недоступна, її час вийшов, або cookies вимкнено.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Токен не знайдено.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Ім’я користувача не знайдено.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Термін дії облікового запису вичерпано.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Термін дії автентифікаційних даних вичерпано.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Обліковий запис відключено.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Обліковий запис заблоковано.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z��J
J
ASymfony/Component/Security/Resources/translations/security.da.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>En fejl indtraf ved godkendelse.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Loginoplysninger kan findes.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Godkendelsesanmodning kan ikke behandles på grund af et systemfejl.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Ugyldige loginoplysninger.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie er allerede brugt af en anden.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Ingen tilladselese at anvende kilden.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Ugyldigt CSRF token.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>Digest nonce has expired.</source>
                <target>Digest nonce er udløbet.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Ingen godkendelsesudbyder er fundet til understøttelsen af godkendelsestoken.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Ingen session tilgængelig, sessionen er enten udløbet eller cookies er ikke aktiveret.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Ingen token kan findes.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Brugernavn kan ikke findes.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Brugerkonto er udløbet.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Loginoplysninger er udløbet.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Brugerkonto er deaktiveret.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Brugerkonto er låst.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�@V��@Symfony/Component/Validator/ConstraintViolationListInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * A list of constraint violations.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
interface ConstraintViolationListInterface extends \Traversable, \Countable, \ArrayAccess
{
    /**
     * Adds a constraint violation to this list.
     *
     * @param ConstraintViolationInterface $violation The violation to add.
     *
     * @api
     */
    public function add(ConstraintViolationInterface $violation);

    /**
     * Merges an existing violation list into this list.
     *
     * @param ConstraintViolationListInterface $otherList The list to merge.
     *
     * @api
     */
    public function addAll(ConstraintViolationListInterface $otherList);

    /**
     * Returns the violation at a given offset.
     *
     * @param  integer $offset The offset of the violation.
     *
     * @return ConstraintViolationInterface The violation.
     *
     * @throws \OutOfBoundsException If the offset does not exist.
     *
     * @api
     */
    public function get($offset);

    /**
     * Returns whether the given offset exists.
     *
     * @param  integer $offset The violation offset.
     *
     * @return Boolean Whether the offset exists.
     *
     * @api
     */
    public function has($offset);

    /**
     * Sets a violation at a given offset.
     *
     * @param integer                      $offset    The violation offset.
     * @param ConstraintViolationInterface $violation The violation.
     *
     * @api
     */
    public function set($offset, ConstraintViolationInterface $violation);

    /**
     * Removes a violation at a given offset.
     *
     * @param integer $offset The offset to remove.
     *
     * @api
     */
    public function remove($offset);
}
PK��Zz��911:Symfony/Component/Validator/ObjectInitializerInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * Prepares an object for validation.
 *
 * Concrete implementations of this interface are used by {@link ValidationVisitorInterface}
 * to initialize objects just before validating them.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
interface ObjectInitializerInterface
{
    /**
     * Initializes an object just before validation.
     *
     * @param object $object The object to validate
     *
     * @api
     */
    public function initialize($object);
}
PK��Z,�'��<Symfony/Component/Validator/ConstraintValidatorInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
interface ConstraintValidatorInterface
{
    /**
     * Initializes the constraint validator.
     *
     * @param ExecutionContextInterface $context The current validation context
     */
    public function initialize(ExecutionContextInterface $context);

    /**
     * Checks if the passed value is valid.
     *
     * @param mixed      $value      The value that should be validated
     * @param Constraint $constraint The constraint for the validation
     *
     * @api
     */
    public function validate($value, Constraint $constraint);
}
PK��ZK��}}1Symfony/Component/Validator/DefaultTranslator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

use Symfony\Component\Validator\Exception\BadMethodCallException;
use Symfony\Component\Validator\Exception\InvalidArgumentException;
use Symfony\Component\Translation\TranslatorInterface;

/**
 * Simple translator implementation that simply replaces the parameters in
 * the message IDs.
 *
 * Example usage:
 *
 *     $translator = new DefaultTranslator();
 *
 *     echo $translator->trans(
 *         'This is a {{ var }}.',
 *         array('{{ var }}' => 'donkey')
 *     );
 *
 *     // -> This is a donkey.
 *
 *     echo $translator->transChoice(
 *         'This is {{ count }} donkey.|These are {{ count }} donkeys.',
 *         3,
 *         array('{{ count }}' => 'three')
 *     );
 *
 *     // -> These are three donkeys.
 *
 * This translator does not support message catalogs, translation domains or
 * locales. Instead, it implements a subset of the capabilities of
 * {@link \Symfony\Component\Translation\Translator} and can be used in places
 * where translation is not required by default but should be optional.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class DefaultTranslator implements TranslatorInterface
{
    /**
     * Interpolates the given message.
     *
     * Parameters are replaced in the message in the same manner that
     * {@link strtr()} uses.
     *
     * Example usage:
     *
     *     $translator = new DefaultTranslator();
     *
     *     echo $translator->trans(
     *         'This is a {{ var }}.',
     *         array('{{ var }}' => 'donkey')
     *     );
     *
     *     // -> This is a donkey.
     *
     * @param string $id         The message id
     * @param array  $parameters An array of parameters for the message
     * @param string $domain     Ignored
     * @param string $locale     Ignored
     *
     * @return string The interpolated string
     */
    public function trans($id, array $parameters = array(), $domain = null, $locale = null)
    {
        return strtr($id, $parameters);
    }

    /**
     * Interpolates the given choice message by choosing a variant according to a number.
     *
     * The variants are passed in the message ID using the format
     * "<singular>|<plural>". "<singular>" is chosen if the passed $number is
     * exactly 1. "<plural>" is chosen otherwise.
     *
     * This format is consistent with the format supported by
     * {@link \Symfony\Component\Translation\Translator}, but it does not
     * have the same expressiveness. While Translator supports intervals in
     * message translations, which are needed for languages other than English,
     * this translator does not. You should use Translator or a custom
     * implementation of {@link TranslatorInterface} if you need this or similar
     * functionality.
     *
     * Example usage:
     *
     *     echo $translator->transChoice(
     *         'This is {{ count }} donkey.|These are {{ count }} donkeys.',
     *         0,
     *         array('{{ count }}' => 0)
     *     );
     *
     *     // -> These are 0 donkeys.
     *
     *     echo $translator->transChoice(
     *         'This is {{ count }} donkey.|These are {{ count }} donkeys.',
     *         1,
     *         array('{{ count }}' => 1)
     *     );
     *
     *     // -> This is 1 donkey.
     *
     *     echo $translator->transChoice(
     *         'This is {{ count }} donkey.|These are {{ count }} donkeys.',
     *         3,
     *         array('{{ count }}' => 3)
     *     );
     *
     *     // -> These are 3 donkeys.
     *
     * @param string  $id         The message id
     * @param integer $number     The number to use to find the index of the message
     * @param array   $parameters An array of parameters for the message
     * @param string  $domain     Ignored
     * @param string  $locale     Ignored
     *
     * @return string The translated string
     *
     * @throws InvalidArgumentException If the message id does not have the format
     *                                  "singular|plural".
     */
    public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
    {
        $ids = explode('|', $id);

        if (1 == $number) {
            return strtr($ids[0], $parameters);
        }

        if (!isset($ids[1])) {
            throw new InvalidArgumentException(sprintf('The message "%s" cannot be pluralized, because it is missing a plural (e.g. "There is one apple|There are %%count%% apples").', $id));
        }

        return strtr($ids[1], $parameters);
    }

    /**
     * Not supported.
     *
     * @param string $locale The locale
     *
     * @throws BadMethodCallException
     */
    public function setLocale($locale)
    {
        throw new BadMethodCallException('Unsupported method.');
    }

    /**
     * Returns the locale of the translator.
     *
     * @return string Always returns 'en'
     */
    public function getLocale()
    {
        return 'en';
    }
}
PK��Z�����3Symfony/Component/Validator/ConstraintViolation.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * Default implementation of {@ConstraintViolationInterface}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ConstraintViolation implements ConstraintViolationInterface
{
    /**
     * @var string
     */
    private $message;

    /**
     * @var string
     */
    private $messageTemplate;

    /**
     * @var array
     */
    private $messageParameters;

    /**
     * @var integer|null
     */
    private $messagePluralization;

    /**
     * @var mixed
     */
    private $root;

    /**
     * @var string
     */
    private $propertyPath;

    /**
     * @var mixed
     */
    private $invalidValue;

    /**
     * @var mixed
     */
    private $code;

    /**
     * Creates a new constraint violation.
     *
     * @param string       $message               The violation message.
     * @param string       $messageTemplate       The raw violation message.
     * @param array        $messageParameters     The parameters to substitute
     *                                            in the raw message.
     * @param mixed        $root                  The value originally passed
     *                                            to the validator.
     * @param string       $propertyPath          The property path from the
     *                                            root value to the invalid
     *                                            value.
     * @param mixed        $invalidValue          The invalid value causing the
     *                                            violation.
     * @param integer|null $messagePluralization  The pluralization parameter.
     * @param mixed        $code                  The error code of the
     *                                            violation, if any.
     */
    public function __construct($message, $messageTemplate, array $messageParameters, $root, $propertyPath, $invalidValue, $messagePluralization = null, $code = null)
    {
        $this->message = $message;
        $this->messageTemplate = $messageTemplate;
        $this->messageParameters = $messageParameters;
        $this->messagePluralization = $messagePluralization;
        $this->root = $root;
        $this->propertyPath = $propertyPath;
        $this->invalidValue = $invalidValue;
        $this->code = $code;
    }

    /**
     * Converts the violation into a string for debugging purposes.
     *
     * @return string The violation as string.
     */
    public function __toString()
    {
        if (is_object($this->root)) {
            $class = get_class($this->root);
        } elseif (is_array($this->root)) {
            $class = "Array";
        } else {
            $class = (string) $this->root;
        }

        $propertyPath = (string) $this->propertyPath;
        $code = $this->code;

        if ('' !== $propertyPath && '[' !== $propertyPath[0] && '' !== $class) {
            $class .= '.';
        }

        if (!empty($code)) {
            $code = ' (code '.$code.')';
        }

        return $class.$propertyPath.":\n    ".$this->getMessage().$code;
    }

    /**
     * {@inheritDoc}
     */
    public function getMessageTemplate()
    {
        return $this->messageTemplate;
    }

    /**
     * {@inheritDoc}
     */
    public function getMessageParameters()
    {
        return $this->messageParameters;
    }

    /**
     * {@inheritDoc}
     */
    public function getMessagePluralization()
    {
        return $this->messagePluralization;
    }

    /**
     * {@inheritDoc}
     */
    public function getMessage()
    {
        return $this->message;
    }

    /**
     * {@inheritDoc}
     */
    public function getRoot()
    {
        return $this->root;
    }

    /**
     * {@inheritDoc}
     */
    public function getPropertyPath()
    {
        return $this->propertyPath;
    }

    /**
     * {@inheritDoc}
     */
    public function getInvalidValue()
    {
        return $this->invalidValue;
    }

    /**
     * {@inheritDoc}
     */
    public function getCode()
    {
        return $this->code;
    }
}
PK��ZS�b'b'0Symfony/Component/Validator/ValidatorBuilder.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
use Symfony\Component\Validator\Mapping\ClassMetadataFactory;
use Symfony\Component\Validator\Exception\ValidatorException;
use Symfony\Component\Validator\Mapping\Loader\LoaderChain;
use Symfony\Component\Validator\Mapping\Cache\CacheInterface;
use Symfony\Component\Validator\Mapping\Loader\StaticMethodLoader;
use Symfony\Component\Validator\Mapping\Loader\YamlFileLoader;
use Symfony\Component\Validator\Mapping\Loader\AnnotationLoader;
use Symfony\Component\Validator\Mapping\Loader\YamlFilesLoader;
use Symfony\Component\Validator\Mapping\Loader\XmlFileLoader;
use Symfony\Component\Validator\Mapping\Loader\XmlFilesLoader;
use Symfony\Component\Translation\TranslatorInterface;
use Doctrine\Common\Annotations\Reader;
use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Annotations\CachedReader;
use Doctrine\Common\Cache\ArrayCache;

/**
 * The default implementation of {@link ValidatorBuilderInterface}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ValidatorBuilder implements ValidatorBuilderInterface
{
    /**
     * @var array
     */
    private $initializers = array();

    /**
     * @var array
     */
    private $xmlMappings = array();

    /**
     * @var array
     */
    private $yamlMappings = array();

    /**
     * @var array
     */
    private $methodMappings = array();

    /**
     * @var Reader
     */
    private $annotationReader = null;

    /**
     * @var MetadataFactoryInterface
     */
    private $metadataFactory;

    /**
     * @var ConstraintValidatorFactoryInterface
     */
    private $validatorFactory;

    /**
     * @var CacheInterface
     */
    private $metadataCache;

    /**
     * @var TranslatorInterface
     */
    private $translator;

    /**
     * @var null|string
     */
    private $translationDomain;

    /**
     * @var PropertyAccessorInterface
     */
    private $propertyAccessor;

    /**
     * {@inheritdoc}
     */
    public function addObjectInitializer(ObjectInitializerInterface $initializer)
    {
        $this->initializers[] = $initializer;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function addObjectInitializers(array $initializers)
    {
        $this->initializers = array_merge($this->initializers, $initializers);

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function addXmlMapping($path)
    {
        if (null !== $this->metadataFactory) {
            throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.');
        }

        $this->xmlMappings[] = $path;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function addXmlMappings(array $paths)
    {
        if (null !== $this->metadataFactory) {
            throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.');
        }

        $this->xmlMappings = array_merge($this->xmlMappings, $paths);

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function addYamlMapping($path)
    {
        if (null !== $this->metadataFactory) {
            throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.');
        }

        $this->yamlMappings[] = $path;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function addYamlMappings(array $paths)
    {
        if (null !== $this->metadataFactory) {
            throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.');
        }

        $this->yamlMappings = array_merge($this->yamlMappings, $paths);

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function addMethodMapping($methodName)
    {
        if (null !== $this->metadataFactory) {
            throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.');
        }

        $this->methodMappings[] = $methodName;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function addMethodMappings(array $methodNames)
    {
        if (null !== $this->metadataFactory) {
            throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.');
        }

        $this->methodMappings = array_merge($this->methodMappings, $methodNames);

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function enableAnnotationMapping(Reader $annotationReader = null)
    {
        if (null !== $this->metadataFactory) {
            throw new ValidatorException('You cannot enable annotation mapping after setting a custom metadata factory. Configure your metadata factory instead.');
        }

        if (null === $annotationReader) {
            if (!class_exists('Doctrine\Common\Annotations\AnnotationReader') || !class_exists('Doctrine\Common\Cache\ArrayCache')) {
                throw new \RuntimeException('Enabling annotation based constraint mapping requires the packages doctrine/annotations and doctrine/cache to be installed.');
            }

            $annotationReader = new CachedReader(new AnnotationReader(), new ArrayCache());
        }

        $this->annotationReader = $annotationReader;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function disableAnnotationMapping()
    {
        $this->annotationReader = null;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setMetadataFactory(MetadataFactoryInterface $metadataFactory)
    {
        if (count($this->xmlMappings) > 0 || count($this->yamlMappings) > 0 || count($this->methodMappings) > 0 || null !== $this->annotationReader) {
            throw new ValidatorException('You cannot set a custom metadata factory after adding custom mappings. You should do either of both.');
        }

        $this->metadataFactory = $metadataFactory;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setMetadataCache(CacheInterface $cache)
    {
        if (null !== $this->metadataFactory) {
            throw new ValidatorException('You cannot set a custom metadata cache after setting a custom metadata factory. Configure your metadata factory instead.');
        }

        $this->metadataCache = $cache;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setConstraintValidatorFactory(ConstraintValidatorFactoryInterface $validatorFactory)
    {
        if (null !== $this->propertyAccessor) {
            throw new ValidatorException('You cannot set a validator factory after setting a custom property accessor. Remove the call to setPropertyAccessor() if you want to call setConstraintValidatorFactory().');
        }

        $this->validatorFactory = $validatorFactory;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setTranslator(TranslatorInterface $translator)
    {
        $this->translator = $translator;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setTranslationDomain($translationDomain)
    {
        $this->translationDomain = $translationDomain;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setPropertyAccessor(PropertyAccessorInterface $propertyAccessor)
    {
        if (null !== $this->validatorFactory) {
            throw new ValidatorException('You cannot set a property accessor after setting a custom validator factory. Configure your validator factory instead.');
        }

        $this->propertyAccessor = $propertyAccessor;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function getValidator()
    {
        $metadataFactory = $this->metadataFactory;

        if (!$metadataFactory) {
            $loaders = array();

            if (count($this->xmlMappings) > 1) {
                $loaders[] = new XmlFilesLoader($this->xmlMappings);
            } elseif (1 === count($this->xmlMappings)) {
                $loaders[] = new XmlFileLoader($this->xmlMappings[0]);
            }

            if (count($this->yamlMappings) > 1) {
                $loaders[] = new YamlFilesLoader($this->yamlMappings);
            } elseif (1 === count($this->yamlMappings)) {
                $loaders[] = new YamlFileLoader($this->yamlMappings[0]);
            }

            foreach ($this->methodMappings as $methodName) {
                $loaders[] = new StaticMethodLoader($methodName);
            }

            if ($this->annotationReader) {
                $loaders[] = new AnnotationLoader($this->annotationReader);
            }

            $loader = null;

            if (count($loaders) > 1) {
                $loader = new LoaderChain($loaders);
            } elseif (1 === count($loaders)) {
                $loader = $loaders[0];
            }

            $metadataFactory = new ClassMetadataFactory($loader, $this->metadataCache);
        }

        $propertyAccessor = $this->propertyAccessor ?: PropertyAccess::createPropertyAccessor();
        $validatorFactory = $this->validatorFactory ?: new ConstraintValidatorFactory($propertyAccessor);
        $translator = $this->translator ?: new DefaultTranslator();

        return new Validator($metadataFactory, $validatorFactory, $translator, $this->translationDomain, $this->initializers);
    }
}
PK��Z�S�UU>Symfony/Component/Validator/GroupSequenceProviderInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * Defines the interface for a group sequence provider.
 */
interface GroupSequenceProviderInterface
{
    /**
     * Returns which validation groups should be used for a certain state
     * of the object.
     *
     * @return array An array of validation groups
     */
    public function getGroupSequence();
}
PK��Z�d�)Symfony/Component/Validator/Validator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

use Symfony\Component\Validator\Constraints\Valid;
use Symfony\Component\Validator\Exception\ValidatorException;
use Symfony\Component\Translation\TranslatorInterface;

/**
 * Default implementation of {@link ValidatorInterface}.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class Validator implements ValidatorInterface
{
    /**
     * @var MetadataFactoryInterface
     */
    private $metadataFactory;

    /**
     * @var ConstraintValidatorFactoryInterface
     */
    private $validatorFactory;

    /**
     * @var TranslatorInterface
     */
    private $translator;

    /**
     * @var null|string
     */
    private $translationDomain;

    /**
     * @var array
     */
    private $objectInitializers;

    public function __construct(
        MetadataFactoryInterface $metadataFactory,
        ConstraintValidatorFactoryInterface $validatorFactory,
        TranslatorInterface $translator,
        $translationDomain = 'validators',
        array $objectInitializers = array()
    )
    {
        $this->metadataFactory = $metadataFactory;
        $this->validatorFactory = $validatorFactory;
        $this->translator = $translator;
        $this->translationDomain = $translationDomain;
        $this->objectInitializers = $objectInitializers;
    }

    /**
     * {@inheritdoc}
     */
    public function getMetadataFactory()
    {
        return $this->metadataFactory;
    }

    /**
     * {@inheritDoc}
     */
    public function getMetadataFor($value)
    {
        return $this->metadataFactory->getMetadataFor($value);
    }

    /**
     * {@inheritDoc}
     */
    public function validate($value, $groups = null, $traverse = false, $deep = false)
    {
        $visitor = $this->createVisitor($value);

        foreach ($this->resolveGroups($groups) as $group) {
            $visitor->validate($value, $group, '', $traverse, $deep);
        }

        return $visitor->getViolations();
    }

    /**
     * {@inheritDoc}
     *
     * @throws ValidatorException If the metadata for the value does not support properties.
     */
    public function validateProperty($containingValue, $property, $groups = null)
    {
        $visitor = $this->createVisitor($containingValue);
        $metadata = $this->metadataFactory->getMetadataFor($containingValue);

        if (!$metadata instanceof PropertyMetadataContainerInterface) {
            $valueAsString = is_scalar($containingValue)
                ? '"'.$containingValue.'"'
                : 'the value of type '.gettype($containingValue);

            throw new ValidatorException(sprintf('The metadata for %s does not support properties.', $valueAsString));
        }

        foreach ($this->resolveGroups($groups) as $group) {
            if (!$metadata->hasPropertyMetadata($property)) {
                continue;
            }

            foreach ($metadata->getPropertyMetadata($property) as $propMeta) {
                $propMeta->accept($visitor, $propMeta->getPropertyValue($containingValue), $group, $property);
            }
        }

        return $visitor->getViolations();
    }

    /**
     * {@inheritDoc}
     *
     * @throws ValidatorException If the metadata for the value does not support properties.
     */
    public function validatePropertyValue($containingValue, $property, $value, $groups = null)
    {
        $visitor = $this->createVisitor($containingValue);
        $metadata = $this->metadataFactory->getMetadataFor($containingValue);

        if (!$metadata instanceof PropertyMetadataContainerInterface) {
            $valueAsString = is_scalar($containingValue)
                ? '"'.$containingValue.'"'
                : 'the value of type '.gettype($containingValue);

            throw new ValidatorException(sprintf('The metadata for '.$valueAsString.' does not support properties.'));
        }

        foreach ($this->resolveGroups($groups) as $group) {
            if (!$metadata->hasPropertyMetadata($property)) {
                continue;
            }

            foreach ($metadata->getPropertyMetadata($property) as $propMeta) {
                $propMeta->accept($visitor, $value, $group, $property);
            }
        }

        return $visitor->getViolations();
    }

    /**
     * {@inheritDoc}
     */
    public function validateValue($value, $constraints, $groups = null)
    {
        $context = new ExecutionContext($this->createVisitor($value), $this->translator, $this->translationDomain);

        $constraints = is_array($constraints) ? $constraints : array($constraints);

        foreach ($constraints as $constraint) {
            if ($constraint instanceof Valid) {
                // Why can't the Valid constraint be executed directly?
                //
                // It cannot be executed like regular other constraints, because regular
                // constraints are only executed *if they belong to the validated group*.
                // The Valid constraint, on the other hand, is always executed and propagates
                // the group to the cascaded object. The propagated group depends on
                //
                //  * Whether a group sequence is currently being executed. Then the default
                //    group is propagated.
                //
                //  * Otherwise the validated group is propagated.

                throw new ValidatorException(
                    sprintf(
                        'The constraint %s cannot be validated. Use the method validate() instead.',
                        get_class($constraint)
                    )
                );
            }

            $context->validateValue($value, $constraint, '', $groups);
        }

        return $context->getViolations();
    }

    /**
     * @param mixed $root
     *
     * @return ValidationVisitor
     */
    private function createVisitor($root)
    {
        return new ValidationVisitor(
            $root,
            $this->metadataFactory,
            $this->validatorFactory,
            $this->translator,
            $this->translationDomain,
            $this->objectInitializers
        );
    }

    /**
     * @param null|string|string[] $groups
     *
     * @return string[]
     */
    private function resolveGroups($groups)
    {
        return $groups ? (array) $groups : array(Constraint::DEFAULT_GROUP);
    }
}
PK��Z��&{{9Symfony/Component/Validator/ValidatorBuilderInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
use Symfony\Component\Validator\Mapping\Cache\CacheInterface;
use Symfony\Component\Translation\TranslatorInterface;
use Doctrine\Common\Annotations\Reader;

/**
 * A configurable builder for ValidatorInterface objects.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface ValidatorBuilderInterface
{
    /**
     * Adds an object initializer to the validator.
     *
     * @param ObjectInitializerInterface $initializer The initializer.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function addObjectInitializer(ObjectInitializerInterface $initializer);

    /**
     * Adds a list of object initializers to the validator.
     *
     * @param array $initializers The initializer.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function addObjectInitializers(array $initializers);

    /**
     * Adds an XML constraint mapping file to the validator.
     *
     * @param string $path The path to the mapping file.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function addXmlMapping($path);

    /**
     * Adds a list of XML constraint mapping files to the validator.
     *
     * @param array $paths The paths to the mapping files.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function addXmlMappings(array $paths);

    /**
     * Adds a YAML constraint mapping file to the validator.
     *
     * @param string $path The path to the mapping file.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function addYamlMapping($path);

    /**
     * Adds a list of YAML constraint mappings file to the validator.
     *
     * @param array $paths The paths to the mapping files.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function addYamlMappings(array $paths);

    /**
     * Enables constraint mapping using the given static method.
     *
     * @param string $methodName The name of the method.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function addMethodMapping($methodName);

    /**
     * Enables constraint mapping using the given static methods.
     *
     * @param array $methodNames The names of the methods.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function addMethodMappings(array $methodNames);

    /**
     * Enables annotation based constraint mapping.
     *
     * @param Reader $annotationReader The annotation reader to be used.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function enableAnnotationMapping(Reader $annotationReader = null);

    /**
     * Disables annotation based constraint mapping.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function disableAnnotationMapping();

    /**
     * Sets the class metadata factory used by the validator.
     *
     * @param MetadataFactoryInterface $metadataFactory The metadata factory.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function setMetadataFactory(MetadataFactoryInterface $metadataFactory);

    /**
     * Sets the cache for caching class metadata.
     *
     * @param CacheInterface $cache The cache instance.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function setMetadataCache(CacheInterface $cache);

    /**
     * Sets the constraint validator factory used by the validator.
     *
     * @param ConstraintValidatorFactoryInterface $validatorFactory The validator factory.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function setConstraintValidatorFactory(ConstraintValidatorFactoryInterface $validatorFactory);

    /**
     * Sets the translator used for translating violation messages.
     *
     * @param TranslatorInterface $translator The translator instance.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function setTranslator(TranslatorInterface $translator);

    /**
     * Sets the default translation domain of violation messages.
     *
     * The same message can have different translations in different domains.
     * Pass the domain that is used for violation messages by default to this
     * method.
     *
     * @param string $translationDomain The translation domain of the violation messages.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function setTranslationDomain($translationDomain);

    /**
     * Sets the property accessor for resolving property paths.
     *
     * @param PropertyAccessorInterface $propertyAccessor The property accessor.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function setPropertyAccessor(PropertyAccessorInterface $propertyAccessor);

    /**
     * Builds and returns a new validator object.
     *
     * @return ValidatorInterface The built validator.
     */
    public function getValidator();
}
PK��Zo��SS*Symfony/Component/Validator/autoloader.phpnu�[���<?php

spl_autoload_register(function ($class) {
    if ('\\' == $class[0]) {
        $class = substr($class, 1);
    }

    if (
        0 === strpos($class, 'Symfony\\Component\\Validator\\')
        &&
        file_exists($file = __DIR__.'/../../../'.str_replace('\\', '/', $class).'.php')
    ) {
        require_once $file;
    }
});
PK��Z����C0C09Symfony/Component/Validator/ExecutionContextInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * Stores the validator's state during validation.
 *
 * For example, let's validate the following object graph:
 *
 * <pre>
 * (Person)---($firstName: string)
 *      \
 *   ($address: Address)---($street: string)
 * </pre>
 *
 * We validate the <tt>Person</tt> instance, which becomes the "root" of the
 * validation run (see {@link getRoot}). The state of the context after the
 * first step will be like this:
 *
 * <pre>
 * (Person)---($firstName: string)
 *    ^ \
 *   ($address: Address)---($street: string)
 * </pre>
 *
 * The validator is stopped at the <tt>Person</tt> node, both the root and the
 * value (see {@link getValue}) of the context point to the <tt>Person</tt>
 * instance. The property path is empty at this point (see {@link getPropertyPath}).
 * The metadata of the context is the metadata of the <tt>Person</tt> node
 * (see {@link getMetadata}).
 *
 * After advancing to the property <tt>$firstName</tt> of the <tt>Person</tt>
 * instance, the state of the context looks like this:
 *
 * <pre>
 * (Person)---($firstName: string)
 *      \              ^
 *   ($address: Address)---($street: string)
 * </pre>
 *
 * The validator is stopped at the property <tt>$firstName</tt>. The root still
 * points to the <tt>Person</tt> instance, because this is where the validation
 * started. The property path is now "firstName" and the current value is the
 * value of that property.
 *
 * After advancing to the <tt>$address</tt> property and then to the
 * <tt>$street</tt> property of the <tt>Address</tt> instance, the context state
 * looks like this:
 *
 * <pre>
 * (Person)---($firstName: string)
 *      \
 *   ($address: Address)---($street: string)
 *                               ^
 * </pre>
 *
 * The validator is stopped at the property <tt>$street</tt>. The root still
 * points to the <tt>Person</tt> instance, but the property path is now
 * "address.street" and the validated value is the value of that property.
 *
 * Apart from the root, the property path and the currently validated value,
 * the execution context also knows the metadata of the current node (see
 * {@link getMetadata}) which for example returns a {@link Mapping\PropertyMetadata}
 * or a {@link Mapping\ClassMetadata} object. he context also contains the
 * validation group that is currently being validated (see {@link getGroup}) and
 * the violations that happened up until now (see {@link getViolations}).
 *
 * Apart from reading the execution context, you can also use
 * {@link addViolation} or {@link addViolationAt} to add new violations and
 * {@link validate} or {@link validateValue} to validate values that the
 * validator otherwise would not reach.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
interface ExecutionContextInterface
{
    /**
     * Adds a violation at the current node of the validation graph.
     *
     * @param string       $message       The error message.
     * @param array        $params        The parameters substituted in the error message.
     * @param mixed        $invalidValue  The invalid, validated value.
     * @param integer|null $pluralization The number to use to pluralize of the message.
     * @param integer|null $code          The violation code.
     *
     * @api
     */
    public function addViolation($message, array $params = array(), $invalidValue = null, $pluralization = null, $code = null);

    /**
     * Adds a violation at the validation graph node with the given property
     * path relative to the current property path.
     *
     * @param string       $subPath       The relative property path for the violation.
     * @param string       $message       The error message.
     * @param array        $params        The parameters substituted in the error message.
     * @param mixed        $invalidValue  The invalid, validated value.
     * @param integer|null $pluralization The number to use to pluralize of the message.
     * @param integer|null $code          The violation code.
     *
     * @api
     */
    public function addViolationAt($subPath, $message, array $params = array(), $invalidValue = null, $pluralization = null, $code = null);

    /**
     * Validates the given value within the scope of the current validation.
     *
     * The value may be any value recognized by the used metadata factory
     * (see {@link MetadataFactoryInterface::getMetadata}), or an array or a
     * traversable object of such values.
     *
     * Usually you validate a value that is not the current node of the
     * execution context. For this case, you can pass the {@link $subPath}
     * argument which is appended to the current property path when a violation
     * is created. For example, take the following object graph:
     *
     * <pre>
     * (Person)---($address: Address)---($phoneNumber: PhoneNumber)
     *                     ^
     * </pre>
     *
     * When the execution context stops at the <tt>Person</tt> instance, the
     * property path is "address". When you validate the <tt>PhoneNumber</tt>
     * instance now, pass "phoneNumber" as sub path to correct the property path
     * to "address.phoneNumber":
     *
     * <pre>
     * $context->validate($address->phoneNumber, 'phoneNumber');
     * </pre>
     *
     * Any violations generated during the validation will be added to the
     * violation list that you can access with {@link getViolations}.
     *
     * @param mixed                $value    The value to validate.
     * @param string               $subPath  The path to append to the context's property path.
     * @param null|string|string[] $groups   The groups to validate in. If you don't pass any
     *                                       groups here, the current group of the context
     *                                       will be used.
     * @param Boolean              $traverse Whether to traverse the value if it is an array
     *                                       or an instance of <tt>\Traversable</tt>.
     * @param Boolean              $deep     Whether to traverse the value recursively if
     *                                       it is a collection of collections.
     */
    public function validate($value, $subPath = '', $groups = null, $traverse = false, $deep = false);

    /**
     * Validates a value against a constraint.
     *
     * Use the parameter <tt>$subPath</tt> to adapt the property path for the
     * validated value. For example, take the following object graph:
     *
     * <pre>
     * (Person)---($address: Address)---($street: string)
     *                     ^
     * </pre>
     *
     * When the validator validates the <tt>Address</tt> instance, the
     * property path stored in the execution context is "address". When you
     * manually validate the property <tt>$street</tt> now, pass the sub path
     * "street" to adapt the full property path to "address.street":
     *
     * <pre>
     * $context->validate($address->street, new NotNull(), 'street');
     * </pre>
     *
     * @param mixed                   $value       The value to validate.
     * @param Constraint|Constraint[] $constraints The constraint(s) to validate against.
     * @param string                  $subPath     The path to append to the context's property path.
     * @param null|string|string[]    $groups      The groups to validate in. If you don't pass any
     *                                             groups here, the current group of the context
     *                                             will be used.
     */
    public function validateValue($value, $constraints, $subPath = '', $groups = null);

    /**
     * Returns the violations generated by the validator so far.
     *
     * @return ConstraintViolationListInterface The constraint violation list.
     *
     * @api
     */
    public function getViolations();

    /**
     * Returns the value at which validation was started in the object graph.
     *
     * The validator, when given an object, traverses the properties and
     * related objects and their properties. The root of the validation is the
     * object from which the traversal started.
     *
     * The current value is returned by {@link getValue}.
     *
     * @return mixed The root value of the validation.
     */
    public function getRoot();

    /**
     * Returns the value that the validator is currently validating.
     *
     * If you want to retrieve the object that was originally passed to the
     * validator, use {@link getRoot}.
     *
     * @return mixed The currently validated value.
     */
    public function getValue();

    /**
     * Returns the metadata for the currently validated value.
     *
     * With the core implementation, this method returns a
     * {@link Mapping\ClassMetadata} instance if the current value is an object,
     * a {@link Mapping\PropertyMetadata} instance if the current value is
     * the value of a property and a {@link Mapping\GetterMetadata} instance if
     * the validated value is the result of a getter method.
     *
     * If the validated value is neither of these, for example if the validator
     * has been called with a plain value and constraint, this method returns
     * null.
     *
     * @return MetadataInterface|null The metadata of the currently validated
     *                                value.
     */
    public function getMetadata();

    /**
     * Returns the used metadata factory.
     *
     * @return MetadataFactoryInterface The metadata factory.
     */
    public function getMetadataFactory();

    /**
     * Returns the validation group that is currently being validated.
     *
     * @return string The current validation group.
     */
    public function getGroup();

    /**
     * Returns the class name of the current node.
     *
     * If the metadata of the current node does not implement
     * {@link ClassBasedInterface} or if no metadata is available for the
     * current node, this method returns null.
     *
     * @return string|null The class name or null, if no class name could be found.
     */
    public function getClassName();

    /**
     * Returns the property name of the current node.
     *
     * If the metadata of the current node does not implement
     * {@link PropertyMetadataInterface} or if no metadata is available for the
     * current node, this method returns null.
     *
     * @return string|null The property name or null, if no property name could be found.
     */
    public function getPropertyName();

    /**
     * Returns the property path to the value that the validator is currently
     * validating.
     *
     * For example, take the following object graph:
     *
     * <pre>
     * (Person)---($address: Address)---($street: string)
     * </pre>
     *
     * When the <tt>Person</tt> instance is passed to the validator, the
     * property path is initially empty. When the <tt>$address</tt> property
     * of that person is validated, the property path is "address". When
     * the <tt>$street</tt> property of the related <tt>Address</tt> instance
     * is validated, the property path is "address.street".
     *
     * Properties of objects are prefixed with a dot in the property path.
     * Indices of arrays or objects implementing the {@link \ArrayAccess}
     * interface are enclosed in brackets. For example, if the property in
     * the previous example is <tt>$addresses</tt> and contains an array
     * of <tt>Address</tt> instance, the property path generated for the
     * <tt>$street</tt> property of one of these addresses is for example
     * "addresses[0].street".
     *
     * @param string $subPath Optional. The suffix appended to the current
     *                        property path.
     *
     * @return string The current property path. The result may be an empty
     *                string if the validator is currently validating the
     *                root value of the validation graph.
     */
    public function getPropertyPath($subPath = '');
}
PK��Z}`���9Symfony/Component/Validator/PropertyMetadataInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * A container for validation metadata of a property.
 *
 * What exactly you define as "property" is up to you. The validator expects
 * implementations of {@link MetadataInterface} that contain constraints and
 * optionally a list of named properties that also have constraints (and may
 * have further sub properties). Such properties are mapped by implementations
 * of this interface.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @see MetadataInterface
 */
interface PropertyMetadataInterface extends MetadataInterface
{
    /**
     * Returns the name of the property.
     *
     * @return string The property name.
     */
    public function getPropertyName();

    /**
     * Extracts the value of the property from the given container.
     *
     * @param mixed $containingValue The container to extract the property value from.
     *
     * @return mixed The value of the property.
     */
    public function getPropertyValue($containingValue);
}
PK��Z�޽/!/!0Symfony/Component/Validator/ExecutionContext.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

use Symfony\Component\Translation\TranslatorInterface;

/**
 * Default implementation of {@link ExecutionContextInterface}.
 *
 * This class is immutable by design.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ExecutionContext implements ExecutionContextInterface
{
    /**
     * @var GlobalExecutionContextInterface
     */
    private $globalContext;

    /**
     * @var TranslatorInterface
     */
    private $translator;

    /**
     * @var null|string
     */
    private $translationDomain;

    /**
     * @var MetadataInterface
     */
    private $metadata;

    /**
     * @var mixed
     */
    private $value;

    /**
     * @var string
     */
    private $group;

    /**
     * @var string
     */
    private $propertyPath;

    /**
     * Creates a new execution context.
     *
     * @param GlobalExecutionContextInterface $globalContext     The global context storing node-independent state.
     * @param TranslatorInterface             $translator        The translator for translating violation messages.
     * @param null|string                     $translationDomain The domain of the validation messages.
     * @param MetadataInterface               $metadata          The metadata of the validated node.
     * @param mixed                           $value             The value of the validated node.
     * @param string                          $group             The current validation group.
     * @param string                          $propertyPath      The property path to the current node.
     */
    public function __construct(GlobalExecutionContextInterface $globalContext, TranslatorInterface $translator, $translationDomain = null, MetadataInterface $metadata = null, $value = null, $group = null, $propertyPath = '')
    {
        if (null === $group) {
            $group = Constraint::DEFAULT_GROUP;
        }

        $this->globalContext = $globalContext;
        $this->translator = $translator;
        $this->translationDomain = $translationDomain;
        $this->metadata = $metadata;
        $this->value = $value;
        $this->propertyPath = $propertyPath;
        $this->group = $group;
    }

    /**
     * {@inheritdoc}
     */
    public function addViolation($message, array $params = array(), $invalidValue = null, $pluralization = null, $code = null)
    {
        if (null === $pluralization) {
            $translatedMessage = $this->translator->trans($message, $params, $this->translationDomain);
        } else {
            try {
                $translatedMessage = $this->translator->transChoice($message, $pluralization, $params, $this->translationDomain);
            } catch (\InvalidArgumentException $e) {
                $translatedMessage = $this->translator->trans($message, $params, $this->translationDomain);
            }
        }

        $this->globalContext->getViolations()->add(new ConstraintViolation(
            $translatedMessage,
            $message,
            $params,
            $this->globalContext->getRoot(),
            $this->propertyPath,
            // check using func_num_args() to allow passing null values
            func_num_args() >= 3 ? $invalidValue : $this->value,
            $pluralization,
            $code
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function addViolationAt($subPath, $message, array $params = array(), $invalidValue = null, $pluralization = null, $code = null)
    {
        $this->globalContext->getViolations()->add(new ConstraintViolation(
            null === $pluralization
                ? $this->translator->trans($message, $params, $this->translationDomain)
                : $this->translator->transChoice($message, $pluralization, $params, $this->translationDomain),
            $message,
            $params,
            $this->globalContext->getRoot(),
            $this->getPropertyPath($subPath),
            // check using func_num_args() to allow passing null values
            func_num_args() >= 4 ? $invalidValue : $this->value,
            $pluralization,
            $code
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getViolations()
    {
        return $this->globalContext->getViolations();
    }

    /**
     * {@inheritdoc}
     */
    public function getRoot()
    {
        return $this->globalContext->getRoot();
    }

    /**
     * {@inheritdoc}
     */
    public function getPropertyPath($subPath = '')
    {
        if ('' != $subPath && '' !== $this->propertyPath && '[' !== $subPath[0]) {
            return $this->propertyPath.'.'.$subPath;
        }

        return $this->propertyPath.$subPath;
    }

    /**
     * {@inheritdoc}
     */
    public function getClassName()
    {
        if ($this->metadata instanceof ClassBasedInterface) {
            return $this->metadata->getClassName();
        }

        return null;
    }

    /**
     * {@inheritdoc}
     */
    public function getPropertyName()
    {
        if ($this->metadata instanceof PropertyMetadataInterface) {
            return $this->metadata->getPropertyName();
        }

        return null;
    }

    /**
     * {@inheritdoc}
     */
    public function getValue()
    {
        return $this->value;
    }

    /**
     * {@inheritdoc}
     */
    public function getGroup()
    {
        return $this->group;
    }

    /**
     * {@inheritdoc}
     */
    public function getMetadata()
    {
        return $this->metadata;
    }

    /**
     * {@inheritdoc}
     */
    public function getMetadataFor($value)
    {
        return $this->globalContext->getMetadataFactory()->getMetadataFor($value);
    }

    /**
     * {@inheritdoc}
     */
    public function validate($value, $subPath = '', $groups = null, $traverse = false, $deep = false)
    {
        $propertyPath = $this->getPropertyPath($subPath);

        foreach ($this->resolveGroups($groups) as $group) {
            $this->globalContext->getVisitor()->validate($value, $group, $propertyPath, $traverse, $deep);
        }
    }

    /**
     * {@inheritdoc}
     */
    public function validateValue($value, $constraints, $subPath = '', $groups = null)
    {
        $constraints = is_array($constraints) ? $constraints : array($constraints);

        if (null === $groups && '' === $subPath) {
            $context = clone $this;
            $context->value = $value;
            $context->executeConstraintValidators($value, $constraints);

            return;
        }

        $propertyPath = $this->getPropertyPath($subPath);

        foreach ($this->resolveGroups($groups) as $group) {
            $context = clone $this;
            $context->value = $value;
            $context->group = $group;
            $context->propertyPath = $propertyPath;
            $context->executeConstraintValidators($value, $constraints);
        }
    }

    /**
     * {@inheritdoc}
     */
    public function getMetadataFactory()
    {
        return $this->globalContext->getMetadataFactory();
    }

    /**
     * Executes the validators of the given constraints for the given value.
     *
     * @param mixed        $value       The value to validate.
     * @param Constraint[] $constraints The constraints to match against.
     */
    private function executeConstraintValidators($value, array $constraints)
    {
        foreach ($constraints as $constraint) {
            $validator = $this->globalContext->getValidatorFactory()->getInstance($constraint);
            $validator->initialize($this);
            $validator->validate($value, $constraint);
        }
    }

    /**
     * Returns an array of group names.
     *
     * @param null|string|string[] $groups The groups to resolve. If a single string is
     *                                     passed, it is converted to an array. If null
     *                                     is passed, an array containing the current
     *                                     group of the context is returned.
     *
     * @return array An array of validation groups.
     */
    private function resolveGroups($groups)
    {
        return $groups ? (array) $groups : (array) $this->group;
    }
}
PK��Z+s���:Symfony/Component/Validator/ConstraintValidatorFactory.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
use Symfony\Component\Validator\Constraints\ExpressionValidator;

/**
 * Default implementation of the ConstraintValidatorFactoryInterface.
 *
 * This enforces the convention that the validatedBy() method on any
 * Constraint will return the class name of the ConstraintValidator that
 * should validate the Constraint.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ConstraintValidatorFactory implements ConstraintValidatorFactoryInterface
{
    protected $validators = array();

    /**
     * @var PropertyAccessorInterface
     */
    private $propertyAccessor;

    public function __construct(PropertyAccessorInterface $propertyAccessor = null)
    {
        $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor();
    }

    /**
     * {@inheritDoc}
     */
    public function getInstance(Constraint $constraint)
    {
        $className = $constraint->validatedBy();

        // The second condition is a hack that is needed when CollectionValidator
        // calls itself recursively (Collection constraints can be nested).
        // Since the context of the validator is overwritten when initialize()
        // is called for the nested constraint, the outer validator is
        // acting on the wrong context when the nested validation terminates.
        //
        // A better solution - which should be approached in Symfony 3.0 - is to
        // remove the initialize() method and pass the context as last argument
        // to validate() instead.
        if (!isset($this->validators[$className]) || 'Symfony\Component\Validator\Constraints\CollectionValidator' === $className) {
            $this->validators[$className] = 'validator.expression' === $className
                ? new ExpressionValidator($this->propertyAccessor)
                : new $className();
        }

        return $this->validators[$className];
    }
}
PK��Z�Sq�KK1Symfony/Component/Validator/MetadataInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * A container for validation metadata.
 *
 * The container contains constraints that may belong to different validation
 * groups. Constraints for a specific group can be fetched by calling
 * {@link findConstraints}.
 *
 * Implement this interface to add validation metadata to your own metadata
 * layer. Each metadata may have named properties. Each property can be
 * represented by one or more {@link PropertyMetadataInterface} instances that
 * are returned by {@link getPropertyMetadata}. Since
 * <tt>PropertyMetadataInterface</tt> inherits from <tt>MetadataInterface</tt>,
 * each property may be divided into further properties.
 *
 * The {@link accept} method of each metadata implements the Visitor pattern.
 * The method should forward the call to the visitor's
 * {@link ValidationVisitorInterface::visit} method and additionally call
 * <tt>accept()</tt> on all structurally related metadata instances.
 *
 * For example, to store constraints for PHP classes and their properties,
 * create a class <tt>ClassMetadata</tt> (implementing <tt>MetadataInterface</tt>)
 * and a class <tt>PropertyMetadata</tt> (implementing <tt>PropertyMetadataInterface</tt>).
 * <tt>ClassMetadata::getPropertyMetadata($property)</tt> returns all
 * <tt>PropertyMetadata</tt> instances for a property of that class. Its
 * <tt>accept()</tt>-method simply forwards to <tt>ValidationVisitorInterface::visit()</tt>
 * and calls <tt>accept()</tt> on all contained <tt>PropertyMetadata</tt>
 * instances, which themselves call <tt>ValidationVisitorInterface::visit()</tt>
 * again.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface MetadataInterface
{
    /**
     * Implementation of the Visitor design pattern.
     *
     * Calls {@link ValidationVisitorInterface::visit} and then forwards the
     * <tt>accept()</tt>-call to all property metadata instances.
     *
     * @param ValidationVisitorInterface $visitor      The visitor implementing the validation logic.
     * @param mixed                      $value        The value to validate.
     * @param string|string[]            $group        The validation group to validate in.
     * @param string                     $propertyPath The current property path in the validation graph.
     */
    public function accept(ValidationVisitorInterface $visitor, $value, $group, $propertyPath);

    /**
     * Returns all constraints for a given validation group.
     *
     * @param string $group The validation group.
     *
     * @return Constraint[] A list of constraint instances.
     */
    public function findConstraints($group);
}
PK��Z�R'<Symfony/Component/Validator/ConstraintViolationInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * A violation of a constraint that happened during validation.
 *
 * For each constraint that fails during validation one or more violations are
 * created. The violations store the violation message, the path to the failing
 * element in the validation graph and the root element that was originally
 * passed to the validator. For example, take the following graph:
 *
 * <pre>
 * (Person)---(firstName: string)
 *      \
 *   (address: Address)---(street: string)
 * </pre>
 *
 * If the <tt>Person</tt> object is validated and validation fails for the
 * "firstName" property, the generated violation has the <tt>Person</tt>
 * instance as root and the property path "firstName". If validation fails
 * for the "street" property of the related <tt>Address</tt> instance, the root
 * element is still the person, but the property path is "address.street".
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
interface ConstraintViolationInterface
{
    /**
     * Returns the violation message.
     *
     * @return string The violation message.
     *
     * @api
     */
    public function getMessage();

    /**
     * Returns the raw violation message.
     *
     * The raw violation message contains placeholders for the parameters
     * returned by {@link getMessageParameters}. Typically you'll pass the
     * message template and parameters to a translation engine.
     *
     * @return string The raw violation message.
     *
     * @api
     */
    public function getMessageTemplate();

    /**
     * Returns the parameters to be inserted into the raw violation message.
     *
     * @return array A possibly empty list of parameters indexed by the names
     *               that appear in the message template.
     *
     * @see getMessageTemplate
     *
     * @api
     */
    public function getMessageParameters();

    /**
     * Returns a number for pluralizing the violation message.
     *
     * For example, the message template could have different translation based
     * on a parameter "choices":
     *
     * <ul>
     * <li>Please select exactly one entry. (choices=1)</li>
     * <li>Please select two entries. (choices=2)</li>
     * </ul>
     *
     * This method returns the value of the parameter for choosing the right
     * pluralization form (in this case "choices").
     *
     * @return integer|null The number to use to pluralize of the message.
     */
    public function getMessagePluralization();

    /**
     * Returns the root element of the validation.
     *
     * @return mixed The value that was passed originally to the validator when
     *               the validation was started. Because the validator traverses
     *               the object graph, the value at which the violation occurs
     *               is not necessarily the value that was originally validated.
     *
     * @api
     */
    public function getRoot();

    /**
     * Returns the property path from the root element to the violation.
     *
     * @return string The property path indicates how the validator reached
     *                the invalid value from the root element. If the root
     *                element is a <tt>Person</tt> instance with a property
     *                "address" that contains an <tt>Address</tt> instance
     *                with an invalid property "street", the generated property
     *                path is "address.street". Property access is denoted by
     *                dots, while array access is denoted by square brackets,
     *                for example "addresses[1].street".
     *
     * @api
     */
    public function getPropertyPath();

    /**
     * Returns the value that caused the violation.
     *
     * @return mixed The invalid value that caused the validated constraint to
     *               fail.
     *
     * @api
     */
    public function getInvalidValue();

    /**
     * Returns a machine-digestible error code for the violation.
     *
     * @return mixed The error code.
     */
    public function getCode();
}
PK��ZƭW��*Symfony/Component/Validator/Constraint.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

use Symfony\Component\Validator\Exception\InvalidOptionsException;
use Symfony\Component\Validator\Exception\MissingOptionsException;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;

/**
 * Contains the properties of a constraint definition.
 *
 * A constraint can be defined on a class, an option or a getter method.
 * The Constraint class encapsulates all the configuration required for
 * validating this class, option or getter result successfully.
 *
 * Constraint instances are immutable and serializable.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
abstract class Constraint
{
    /**
     * The name of the group given to all constraints with no explicit group
     * @var string
     */
    const DEFAULT_GROUP = 'Default';

    /**
     * Marks a constraint that can be put onto classes
     * @var string
     */
    const CLASS_CONSTRAINT = 'class';

    /**
     * Marks a constraint that can be put onto properties
     * @var string
     */
    const PROPERTY_CONSTRAINT = 'property';

    /**
     * @var array
     */
    public $groups = array(self::DEFAULT_GROUP);

    /**
     * Initializes the constraint with options.
     *
     * You should pass an associative array. The keys should be the names of
     * existing properties in this class. The values should be the value for these
     * properties.
     *
     * Alternatively you can override the method getDefaultOption() to return the
     * name of an existing property. If no associative array is passed, this
     * property is set instead.
     *
     * You can force that certain options are set by overriding
     * getRequiredOptions() to return the names of these options. If any
     * option is not set here, an exception is thrown.
     *
     * @param mixed $options The options (as associative array)
     *                       or the value for the default
     *                       option (any other type)
     *
     * @throws InvalidOptionsException       When you pass the names of non-existing
     *                                       options
     * @throws MissingOptionsException       When you don't pass any of the options
     *                                       returned by getRequiredOptions()
     * @throws ConstraintDefinitionException When you don't pass an associative
     *                                       array, but getDefaultOption() returns
     *                                       null
     *
     * @api
     */
    public function __construct($options = null)
    {
        $invalidOptions = array();
        $missingOptions = array_flip((array) $this->getRequiredOptions());

        if (is_array($options) && count($options) >= 1 && isset($options['value']) && !property_exists($this, 'value')) {
            $options[$this->getDefaultOption()] = $options['value'];
            unset($options['value']);
        }

        if (is_array($options) && count($options) > 0 && is_string(key($options))) {
            foreach ($options as $option => $value) {
                if (property_exists($this, $option)) {
                    $this->$option = $value;
                    unset($missingOptions[$option]);
                } else {
                    $invalidOptions[] = $option;
                }
            }
        } elseif (null !== $options && ! (is_array($options) && count($options) === 0)) {
            $option = $this->getDefaultOption();

            if (null === $option) {
                throw new ConstraintDefinitionException(
                    sprintf('No default option is configured for constraint %s', get_class($this))
                );
            }

            if (property_exists($this, $option)) {
                $this->$option = $options;
                unset($missingOptions[$option]);
            } else {
                $invalidOptions[] = $option;
            }
        }

        if (count($invalidOptions) > 0) {
            throw new InvalidOptionsException(
                sprintf('The options "%s" do not exist in constraint %s', implode('", "', $invalidOptions), get_class($this)),
                $invalidOptions
            );
        }

        if (count($missingOptions) > 0) {
            throw new MissingOptionsException(
                sprintf('The options "%s" must be set for constraint %s', implode('", "', array_keys($missingOptions)), get_class($this)),
                array_keys($missingOptions)
            );
        }

        $this->groups = (array) $this->groups;
    }

    /**
     * Unsupported operation.
     */
    public function __set($option, $value)
    {
        throw new InvalidOptionsException(sprintf('The option "%s" does not exist in constraint %s', $option, get_class($this)), array($option));
    }

    /**
     * Adds the given group if this constraint is in the Default group
     *
     * @param string $group
     *
     * @api
     */
    public function addImplicitGroupName($group)
    {
        if (in_array(Constraint::DEFAULT_GROUP, $this->groups) && !in_array($group, $this->groups)) {
            $this->groups[] = $group;
        }
    }

    /**
     * Returns the name of the default option
     *
     * Override this method to define a default option.
     *
     * @return string
     * @see __construct()
     *
     * @api
     */
    public function getDefaultOption()
    {
        return null;
    }

    /**
     * Returns the name of the required options
     *
     * Override this method if you want to define required options.
     *
     * @return array
     * @see __construct()
     *
     * @api
     */
    public function getRequiredOptions()
    {
        return array();
    }

    /**
     * Returns the name of the class that validates this constraint
     *
     * By default, this is the fully qualified name of the constraint class
     * suffixed with "Validator". You can override this method to change that
     * behaviour.
     *
     * @return string
     *
     * @api
     */
    public function validatedBy()
    {
        return get_class($this).'Validator';
    }

    /**
     * Returns whether the constraint can be put onto classes, properties or
     * both
     *
     * This method should return one or more of the constants
     * Constraint::CLASS_CONSTRAINT and Constraint::PROPERTY_CONSTRAINT.
     *
     * @return string|array  One or more constant values
     *
     * @api
     */
    public function getTargets()
    {
        return self::PROPERTY_CONSTRAINT;
    }
}
PK��Z|����6Symfony/Component/Validator/Mapping/GetterMetadata.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping;

use Symfony\Component\Validator\Exception\ValidatorException;

class GetterMetadata extends MemberMetadata
{
    /**
     * Constructor.
     *
     * @param string $class    The class the getter is defined on
     * @param string $property The property which the getter returns
     *
     * @throws ValidatorException
     */
    public function __construct($class, $property)
    {
        $getMethod = 'get'.ucfirst($property);
        $isMethod = 'is'.ucfirst($property);

        if (method_exists($class, $getMethod)) {
            $method = $getMethod;
        } elseif (method_exists($class, $isMethod)) {
            $method = $isMethod;
        } else {
            throw new ValidatorException(sprintf('Neither method %s nor %s exists in class %s', $getMethod, $isMethod, $class));
        }

        parent::__construct($class, $method, $property);
    }

    /**
     * {@inheritDoc}
     */
    public function getPropertyValue($object)
    {
        return $this->newReflectionMember($object)->invoke($object);
    }

    /**
     * {@inheritDoc}
     */
    protected function newReflectionMember($objectOrClassName)
    {
        return new \ReflectionMethod($objectOrClassName, $this->getName());
    }
}
PK��Zr
���8Symfony/Component/Validator/Mapping/PropertyMetadata.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping;

use Symfony\Component\Validator\Exception\ValidatorException;

class PropertyMetadata extends MemberMetadata
{
    /**
     * Constructor.
     *
     * @param string $class The class this property is defined on
     * @param string $name  The name of this property
     *
     * @throws ValidatorException
     */
    public function __construct($class, $name)
    {
        if (!property_exists($class, $name)) {
            throw new ValidatorException(sprintf('Property %s does not exist in class %s', $name, $class));
        }

        parent::__construct($class, $name, $name);
    }

    /**
     * {@inheritDoc}
     */
    public function getPropertyValue($object)
    {
        return $this->getReflectionMember($object)->getValue($object);
    }

    /**
     * {@inheritDoc}
     */
    protected function newReflectionMember($objectOrClassName)
    {
        $class = new \ReflectionClass($objectOrClassName);
        while (!$class->hasProperty($this->getName())) {
            $class = $class->getParentClass();
        }

        $member = new \ReflectionProperty($class->getName(), $this->getName());
        $member->setAccessible(true);

        return $member;
    }
}
PK��Z�t�././5Symfony/Component/Validator/Mapping/ClassMetadata.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping;

use Symfony\Component\Validator\ValidationVisitorInterface;
use Symfony\Component\Validator\PropertyMetadataContainerInterface;
use Symfony\Component\Validator\ClassBasedInterface;
use Symfony\Component\Validator\MetadataInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
use Symfony\Component\Validator\Exception\GroupDefinitionException;

/**
 * Represents all the configured constraints on a given class.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ClassMetadata extends ElementMetadata implements MetadataInterface, ClassBasedInterface, PropertyMetadataContainerInterface
{
    /**
     * @var string
     */
    public $name;

    /**
     * @var string
     */
    public $defaultGroup;

    /**
     * @var MemberMetadata[]
     */
    public $members = array();

    /**
     * @var PropertyMetadata[]
     */
    public $properties = array();

    /**
     * @var GetterMetadata[]
     */
    public $getters = array();

    /**
     * @var array
     */
    public $groupSequence = array();

    /**
     * @var Boolean
     */
    public $groupSequenceProvider = false;

    /**
     * @var \ReflectionClass
     */
    private $reflClass;

    /**
     * Constructs a metadata for the given class
     *
     * @param string $class
     */
    public function __construct($class)
    {
        $this->name = $class;
        // class name without namespace
        if (false !== $nsSep = strrpos($class, '\\')) {
            $this->defaultGroup = substr($class, $nsSep + 1);
        } else {
            $this->defaultGroup = $class;
        }
    }

    public function accept(ValidationVisitorInterface $visitor, $value, $group, $propertyPath, $propagatedGroup = null)
    {
        if (null === $propagatedGroup && Constraint::DEFAULT_GROUP === $group
                && ($this->hasGroupSequence() || $this->isGroupSequenceProvider())) {
            if ($this->hasGroupSequence()) {
                $groups = $this->getGroupSequence();
            } else {
                $groups = $value->getGroupSequence();
            }

            foreach ($groups as $group) {
                $this->accept($visitor, $value, $group, $propertyPath, Constraint::DEFAULT_GROUP);

                if (count($visitor->getViolations()) > 0) {
                    break;
                }
            }

            return;
        }

        $visitor->visit($this, $value, $group, $propertyPath);

        if (null !== $value) {
            $pathPrefix = empty($propertyPath) ? '' : $propertyPath.'.';

            foreach ($this->getConstrainedProperties() as $property) {
                foreach ($this->getMemberMetadatas($property) as $member) {
                    $member->accept($visitor, $member->getPropertyValue($value), $group, $pathPrefix.$property, $propagatedGroup);
                }
            }
        }
    }

    /**
     * Returns the properties to be serialized
     *
     * @return array
     */
    public function __sleep()
    {
        return array_merge(parent::__sleep(), array(
            'getters',
            'groupSequence',
            'groupSequenceProvider',
            'members',
            'name',
            'properties',
            'defaultGroup'
        ));
    }

    /**
     * Returns the fully qualified name of the class
     *
     * @return string  The fully qualified class name
     */
    public function getClassName()
    {
        return $this->name;
    }

    /**
     * Returns the name of the default group for this class
     *
     * For each class, the group "Default" is an alias for the group
     * "<ClassName>", where <ClassName> is the non-namespaced name of the
     * class. All constraints implicitly or explicitly assigned to group
     * "Default" belong to both of these groups, unless the class defines
     * a group sequence.
     *
     * If a class defines a group sequence, validating the class in "Default"
     * will validate the group sequence. The constraints assigned to "Default"
     * can still be validated by validating the class in "<ClassName>".
     *
     * @return string  The name of the default group
     */
    public function getDefaultGroup()
    {
        return $this->defaultGroup;
    }

    /**
     * {@inheritDoc}
     */
    public function addConstraint(Constraint $constraint)
    {
        if (!in_array(Constraint::CLASS_CONSTRAINT, (array) $constraint->getTargets())) {
            throw new ConstraintDefinitionException(sprintf(
                'The constraint %s cannot be put on classes',
                get_class($constraint)
            ));
        }

        $constraint->addImplicitGroupName($this->getDefaultGroup());

        parent::addConstraint($constraint);
    }

    /**
     * Adds a constraint to the given property.
     *
     * @param string     $property   The name of the property
     * @param Constraint $constraint The constraint
     *
     * @return ClassMetadata This object
     */
    public function addPropertyConstraint($property, Constraint $constraint)
    {
        if (!isset($this->properties[$property])) {
            $this->properties[$property] = new PropertyMetadata($this->getClassName(), $property);

            $this->addMemberMetadata($this->properties[$property]);
        }

        $constraint->addImplicitGroupName($this->getDefaultGroup());

        $this->properties[$property]->addConstraint($constraint);

        return $this;
    }

    /**
     * Adds a constraint to the getter of the given property.
     *
     * The name of the getter is assumed to be the name of the property with an
     * uppercased first letter and either the prefix "get" or "is".
     *
     * @param string     $property   The name of the property
     * @param Constraint $constraint The constraint
     *
     * @return ClassMetadata This object
     */
    public function addGetterConstraint($property, Constraint $constraint)
    {
        if (!isset($this->getters[$property])) {
            $this->getters[$property] = new GetterMetadata($this->getClassName(), $property);

            $this->addMemberMetadata($this->getters[$property]);
        }

        $constraint->addImplicitGroupName($this->getDefaultGroup());

        $this->getters[$property]->addConstraint($constraint);

        return $this;
    }

    /**
     * Merges the constraints of the given metadata into this object.
     *
     * @param ClassMetadata $source The source metadata
     */
    public function mergeConstraints(ClassMetadata $source)
    {
        foreach ($source->getConstraints() as $constraint) {
            $this->addConstraint(clone $constraint);
        }

        foreach ($source->getConstrainedProperties() as $property) {
            foreach ($source->getMemberMetadatas($property) as $member) {
                $member = clone $member;

                foreach ($member->getConstraints() as $constraint) {
                    $constraint->addImplicitGroupName($this->getDefaultGroup());
                }

                $this->addMemberMetadata($member);

                if (!$member->isPrivate($this->name)) {
                    $property = $member->getPropertyName();

                    if ($member instanceof PropertyMetadata && !isset($this->properties[$property])) {
                        $this->properties[$property] = $member;
                    } elseif ($member instanceof GetterMetadata && !isset($this->getters[$property])) {
                        $this->getters[$property] = $member;
                    }
                }
            }
        }
    }

    /**
     * Adds a member metadata.
     *
     * @param MemberMetadata $metadata
     */
    protected function addMemberMetadata(MemberMetadata $metadata)
    {
        $property = $metadata->getPropertyName();

        $this->members[$property][] = $metadata;
    }

    /**
     * Returns true if metadatas of members is present for the given property.
     *
     * @param string $property The name of the property
     *
     * @return Boolean
     */
    public function hasMemberMetadatas($property)
    {
        return array_key_exists($property, $this->members);
    }

    /**
     * Returns all metadatas of members describing the given property.
     *
     * @param string $property The name of the property
     *
     * @return MemberMetadata[] An array of MemberMetadata
     */
    public function getMemberMetadatas($property)
    {
        return $this->members[$property];
    }

    /**
     * {@inheritdoc}
     */
    public function hasPropertyMetadata($property)
    {
        return array_key_exists($property, $this->members);
    }

    /**
     * {@inheritdoc}
     */
    public function getPropertyMetadata($property)
    {
        return $this->members[$property];
    }

    /**
     * Returns all properties for which constraints are defined.
     *
     * @return array An array of property names
     */
    public function getConstrainedProperties()
    {
        return array_keys($this->members);
    }

    /**
     * Sets the default group sequence for this class.
     *
     * @param array $groups An array of group names
     *
     * @return ClassMetadata
     *
     * @throws GroupDefinitionException
     */
    public function setGroupSequence(array $groups)
    {
        if ($this->isGroupSequenceProvider()) {
            throw new GroupDefinitionException('Defining a static group sequence is not allowed with a group sequence provider');
        }

        if (in_array(Constraint::DEFAULT_GROUP, $groups, true)) {
            throw new GroupDefinitionException(sprintf('The group "%s" is not allowed in group sequences', Constraint::DEFAULT_GROUP));
        }

        if (!in_array($this->getDefaultGroup(), $groups, true)) {
            throw new GroupDefinitionException(sprintf('The group "%s" is missing in the group sequence', $this->getDefaultGroup()));
        }

        $this->groupSequence = $groups;

        return $this;
    }

    /**
     * Returns whether this class has an overridden default group sequence.
     *
     * @return Boolean
     */
    public function hasGroupSequence()
    {
        return count($this->groupSequence) > 0;
    }

    /**
     * Returns the default group sequence for this class.
     *
     * @return array An array of group names
     */
    public function getGroupSequence()
    {
        return $this->groupSequence;
    }

    /**
     * Returns a ReflectionClass instance for this class.
     *
     * @return \ReflectionClass
     */
    public function getReflectionClass()
    {
        if (!$this->reflClass) {
            $this->reflClass = new \ReflectionClass($this->getClassName());
        }

        return $this->reflClass;
    }

    /**
     * Sets whether a group sequence provider should be used.
     *
     * @param Boolean $active
     *
     * @throws GroupDefinitionException
     */
    public function setGroupSequenceProvider($active)
    {
        if ($this->hasGroupSequence()) {
            throw new GroupDefinitionException('Defining a group sequence provider is not allowed with a static group sequence');
        }

        if (!$this->getReflectionClass()->implementsInterface('Symfony\Component\Validator\GroupSequenceProviderInterface')) {
            throw new GroupDefinitionException(sprintf('Class "%s" must implement GroupSequenceProviderInterface', $this->name));
        }

        $this->groupSequenceProvider = $active;
    }

    /**
     * Returns whether the class is a group sequence provider.
     *
     * @return Boolean
     */
    public function isGroupSequenceProvider()
    {
        return $this->groupSequenceProvider;
    }
}
PK��Z��!"	"	7Symfony/Component/Validator/Mapping/ElementMetadata.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping;

use Symfony\Component\Validator\Constraint;

abstract class ElementMetadata
{
    /**
     * @var Constraint[]
     */
    public $constraints = array();

    /**
     * @var array
     */
    public $constraintsByGroup = array();

    /**
     * Returns the names of the properties that should be serialized.
     *
     * @return array
     */
    public function __sleep()
    {
        return array(
            'constraints',
            'constraintsByGroup',
        );
    }

    /**
     * Clones this object.
     */
    public function __clone()
    {
        $constraints = $this->constraints;

        $this->constraints = array();
        $this->constraintsByGroup = array();

        foreach ($constraints as $constraint) {
            $this->addConstraint(clone $constraint);
        }
    }

    /**
     * Adds a constraint to this element.
     *
     * @param Constraint $constraint
     *
     * @return ElementMetadata
     */
    public function addConstraint(Constraint $constraint)
    {
        $this->constraints[] = $constraint;

        foreach ($constraint->groups as $group) {
            $this->constraintsByGroup[$group][] = $constraint;
        }

        return $this;
    }

    /**
     * Returns all constraints of this element.
     *
     * @return Constraint[] An array of Constraint instances
     */
    public function getConstraints()
    {
        return $this->constraints;
    }

    /**
     * Returns whether this element has any constraints.
     *
     * @return Boolean
     */
    public function hasConstraints()
    {
        return count($this->constraints) > 0;
    }

    /**
     * Returns the constraints of the given group and global ones (* group).
     *
     * @param string $group The group name
     *
     * @return array An array with all Constraint instances belonging to the group
     */
    public function findConstraints($group)
    {
        return isset($this->constraintsByGroup[$group])
                ? $this->constraintsByGroup[$group]
                : array();
    }
}
PK��Z�/�;aa6Symfony/Component/Validator/Mapping/MemberMetadata.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping;

use Symfony\Component\Validator\ValidationVisitorInterface;
use Symfony\Component\Validator\ClassBasedInterface;
use Symfony\Component\Validator\PropertyMetadataInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Constraints\Valid;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;

abstract class MemberMetadata extends ElementMetadata implements PropertyMetadataInterface, ClassBasedInterface
{
    public $class;
    public $name;
    public $property;
    public $cascaded = false;
    public $collectionCascaded = false;
    public $collectionCascadedDeeply = false;
    private $reflMember = array();

    /**
     * Constructor.
     *
     * @param string $class    The name of the class this member is defined on
     * @param string $name     The name of the member
     * @param string $property The property the member belongs to
     */
    public function __construct($class, $name, $property)
    {
        $this->class = $class;
        $this->name = $name;
        $this->property = $property;
    }

    public function accept(ValidationVisitorInterface $visitor, $value, $group, $propertyPath, $propagatedGroup = null)
    {
        $visitor->visit($this, $value, $group, $propertyPath);

        if ($this->isCascaded()) {
            $visitor->validate($value, $propagatedGroup ?: $group, $propertyPath, $this->isCollectionCascaded(), $this->isCollectionCascadedDeeply());
        }
    }

    /**
     * {@inheritDoc}
     */
    public function addConstraint(Constraint $constraint)
    {
        if (!in_array(Constraint::PROPERTY_CONSTRAINT, (array) $constraint->getTargets())) {
            throw new ConstraintDefinitionException(sprintf(
                'The constraint %s cannot be put on properties or getters',
                get_class($constraint)
            ));
        }

        if ($constraint instanceof Valid) {
            $this->cascaded = true;
            /* @var Valid $constraint */
            $this->collectionCascaded = $constraint->traverse;
            $this->collectionCascadedDeeply = $constraint->deep;
        } else {
            parent::addConstraint($constraint);
        }

        return $this;
    }

    /**
     * Returns the names of the properties that should be serialized
     *
     * @return array
     */
    public function __sleep()
    {
        return array_merge(parent::__sleep(), array(
            'class',
            'name',
            'property',
            'cascaded',
            'collectionCascaded',
            'collectionCascadedDeeply',
        ));
    }

    /**
     * Returns the name of the member
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Returns the class this member is defined on
     *
     * @return string
     */
    public function getClassName()
    {
        return $this->class;
    }

    /**
     * Returns the name of the property this member belongs to
     *
     * @return string The property name
     */
    public function getPropertyName()
    {
        return $this->property;
    }

    /**
     * Returns whether this member is public
     *
     * @param object|string $objectOrClassName The object or the class name
     *
     * @return Boolean
     */
    public function isPublic($objectOrClassName)
    {
        return $this->getReflectionMember($objectOrClassName)->isPublic();
    }

    /**
     * Returns whether this member is protected
     *
     * @param object|string $objectOrClassName The object or the class name
     *
     * @return Boolean
     */
    public function isProtected($objectOrClassName)
    {
        return $this->getReflectionMember($objectOrClassName)->isProtected();
    }

    /**
     * Returns whether this member is private
     *
     * @param object|string $objectOrClassName The object or the class name
     *
     * @return Boolean
     */
    public function isPrivate($objectOrClassName)
    {
        return $this->getReflectionMember($objectOrClassName)->isPrivate();
    }

    /**
     * Returns whether objects stored in this member should be validated
     *
     * @return Boolean
     */
    public function isCascaded()
    {
        return $this->cascaded;
    }

    /**
     * Returns whether arrays or traversable objects stored in this member
     * should be traversed and validated in each entry
     *
     * @return Boolean
     */
    public function isCollectionCascaded()
    {
        return $this->collectionCascaded;
    }

    /**
     * Returns whether arrays or traversable objects stored in this member
     * should be traversed recursively for inner arrays/traversable objects
     *
     * @return Boolean
     */
    public function isCollectionCascadedDeeply()
    {
        return $this->collectionCascadedDeeply;
    }

    /**
     * Returns the Reflection instance of the member
     *
     * @param object|string $objectOrClassName The object or the class name
     *
     * @return object
     */
    public function getReflectionMember($objectOrClassName)
    {
        $className = is_string($objectOrClassName) ? $objectOrClassName : get_class($objectOrClassName);
        if (!isset($this->reflMember[$className])) {
            $this->reflMember[$className] = $this->newReflectionMember($objectOrClassName);
        }

        return $this->reflMember[$className];
    }

    /**
     * Creates a new Reflection instance for the member
     *
     * @param object|string $objectOrClassName The object or the class name
     *
     * @return mixed Reflection class
     */
    abstract protected function newReflectionMember($objectOrClassName);
}
PK��Z+�d%%<Symfony/Component/Validator/Mapping/Cache/CacheInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping\Cache;

use Symfony\Component\Validator\Mapping\ClassMetadata;

/**
 * Persists ClassMetadata instances in a cache
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface CacheInterface
{
    /**
     * Returns whether metadata for the given class exists in the cache
     *
     * @param string $class
     */
    public function has($class);

    /**
     * Returns the metadata for the given class from the cache
     *
     * @param string $class Class Name
     *
     * @return ClassMetadata|false A ClassMetadata instance or false on miss
     */
    public function read($class);

    /**
     * Stores a class metadata in the cache
     *
     * @param ClassMetadata $metadata A Class Metadata
     */
    public function write(ClassMetadata $metadata);
}
PK��Z����6Symfony/Component/Validator/Mapping/Cache/ApcCache.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping\Cache;

use Symfony\Component\Validator\Mapping\ClassMetadata;

class ApcCache implements CacheInterface
{
    private $prefix;

    public function __construct($prefix)
    {
        if (!extension_loaded('apc')) {
            throw new \RuntimeException('Unable to use ApcCache to cache validator mappings as APC is not enabled.');
        }

        $this->prefix = $prefix;
    }

    public function has($class)
    {
        if (!function_exists('apc_exists')) {
            $exists = false;

            apc_fetch($this->prefix.$class, $exists);

            return $exists;
        }

        return apc_exists($this->prefix.$class);
    }

    public function read($class)
    {
        return apc_fetch($this->prefix.$class);
    }

    public function write(ClassMetadata $metadata)
    {
        apc_store($this->prefix.$metadata->getClassName(), $metadata);
    }
}
PK��Zd#[N��<Symfony/Component/Validator/Mapping/ClassMetadataFactory.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping;

use Symfony\Component\Validator\MetadataFactoryInterface;
use Symfony\Component\Validator\Exception\NoSuchMetadataException;
use Symfony\Component\Validator\Mapping\Loader\LoaderInterface;
use Symfony\Component\Validator\Mapping\Cache\CacheInterface;

/**
 * A factory for creating metadata for PHP classes.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ClassMetadataFactory implements MetadataFactoryInterface
{
    /**
     * The loader for loading the class metadata
     * @var LoaderInterface
     */
    protected $loader;

    /**
     * The cache for caching class metadata
     * @var CacheInterface
     */
    protected $cache;

    protected $loadedClasses = array();

    public function __construct(LoaderInterface $loader = null, CacheInterface $cache = null)
    {
        $this->loader = $loader;
        $this->cache = $cache;
    }

    /**
     * {@inheritdoc}
     */
    public function getMetadataFor($value)
    {
        if (!is_object($value) && !is_string($value)) {
            throw new NoSuchMetadataException(sprintf('Cannot create metadata for non-objects. Got: %s', gettype($value)));
        }

        $class = ltrim(is_object($value) ? get_class($value) : $value, '\\');

        if (isset($this->loadedClasses[$class])) {
            return $this->loadedClasses[$class];
        }

        if (null !== $this->cache && false !== ($this->loadedClasses[$class] = $this->cache->read($class))) {
            return $this->loadedClasses[$class];
        }

        if (!class_exists($class) && !interface_exists($class)) {
            throw new NoSuchMetadataException(sprintf('The class or interface "%s" does not exist.', $class));
        }

        $metadata = new ClassMetadata($class);

        // Include constraints from the parent class
        if ($parent = $metadata->getReflectionClass()->getParentClass()) {
            $metadata->mergeConstraints($this->getMetadataFor($parent->name));
        }

        // Include constraints from all implemented interfaces
        foreach ($metadata->getReflectionClass()->getInterfaces() as $interface) {
            if ('Symfony\Component\Validator\GroupSequenceProviderInterface' === $interface->name) {
                continue;
            }
            $metadata->mergeConstraints($this->getMetadataFor($interface->name));
        }

        if (null !== $this->loader) {
            $this->loader->loadClassMetadata($metadata);
        }

        if (null !== $this->cache) {
            $this->cache->write($metadata);
        }

        return $this->loadedClasses[$class] = $metadata;
    }

    /**
     * {@inheritdoc}
     */
    public function hasMetadataFor($value)
    {
        if (!is_object($value) && !is_string($value)) {
            return false;
        }

        $class = ltrim(is_object($value) ? get_class($value) : $value, '\\');

        if (class_exists($class) || interface_exists($class)) {
            return true;
        }

        return false;
    }
}
PK��Z��ʚ��9Symfony/Component/Validator/Mapping/Loader/FileLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping\Loader;

use Symfony\Component\Validator\Exception\MappingException;

abstract class FileLoader extends AbstractLoader
{
    protected $file;

    /**
     * Constructor.
     *
     * @param string $file The mapping file to load
     *
     * @throws MappingException if the mapping file does not exist
     * @throws MappingException if the mapping file is not readable
     */
    public function __construct($file)
    {
        if (!is_file($file)) {
            throw new MappingException(sprintf('The mapping file %s does not exist', $file));
        }

        if (!is_readable($file)) {
            throw new MappingException(sprintf('The mapping file %s is not readable', $file));
        }

        $this->file = $file;
    }
}
PK��Zk�G+��=Symfony/Component/Validator/Mapping/Loader/AbstractLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping\Loader;

use Symfony\Component\Validator\Exception\MappingException;
use Symfony\Component\Validator\Constraint;

abstract class AbstractLoader implements LoaderInterface
{
    /**
     * Contains all known namespaces indexed by their prefix
     * @var array
     */
    protected $namespaces = array();

    /**
     * Adds a namespace alias.
     *
     * @param string $alias     The alias
     * @param string $namespace The PHP namespace
     */
    protected function addNamespaceAlias($alias, $namespace)
    {
        $this->namespaces[$alias] = $namespace;
    }

    /**
     * Creates a new constraint instance for the given constraint name.
     *
     * @param string $name   The constraint name. Either a constraint relative
     *                       to the default constraint namespace, or a fully
     *                       qualified class name
     * @param mixed $options The constraint options
     *
     * @return Constraint
     *
     * @throws MappingException If the namespace prefix is undefined
     */
    protected function newConstraint($name, $options)
    {
        if (strpos($name, '\\') !== false && class_exists($name)) {
            $className = (string) $name;
        } elseif (strpos($name, ':') !== false) {
            list($prefix, $className) = explode(':', $name, 2);

            if (!isset($this->namespaces[$prefix])) {
                throw new MappingException(sprintf('Undefined namespace prefix "%s"', $prefix));
            }

            $className = $this->namespaces[$prefix].$className;
        } else {
            $className = 'Symfony\\Component\\Validator\\Constraints\\'.$name;
        }

        return new $className($options);
    }
}
PK��ZRᠯ��=Symfony/Component/Validator/Mapping/Loader/XmlFilesLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping\Loader;

/**
 * Loads multiple xml mapping files
 *
 * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
 *
 * @see    Symfony\Component\Validator\Mapping\Loader\FilesLoader
 */
class XmlFilesLoader extends FilesLoader
{
    /**
     * {@inheritDoc}
     */
    public function getFileLoaderInstance($file)
    {
        return new XmlFileLoader($file);
    }
}
PK��Z�?��>Symfony/Component/Validator/Mapping/Loader/YamlFilesLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping\Loader;

/**
 * Loads multiple yaml mapping files
 *
 * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
 *
 * @see    Symfony\Component\Validator\Mapping\Loader\FilesLoader
 */
class YamlFilesLoader extends FilesLoader
{
    /**
     * {@inheritDoc}
     */
    public function getFileLoaderInstance($file)
    {
        return new YamlFileLoader($file);
    }
}
PK��Z�����:Symfony/Component/Validator/Mapping/Loader/LoaderChain.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping\Loader;

use Symfony\Component\Validator\Exception\MappingException;
use Symfony\Component\Validator\Mapping\ClassMetadata;

/**
 * Calls multiple LoaderInterface instances in a chain
 *
 * This class accepts multiple instances of LoaderInterface to be passed to the
 * constructor. When loadClassMetadata() is called, the same method is called
 * in <em>all</em> of these loaders, regardless of whether any of them was
 * successful or not.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class LoaderChain implements LoaderInterface
{
    protected $loaders;

    /**
     * Accepts a list of LoaderInterface instances
     *
     * @param LoaderInterface[] $loaders An array of LoaderInterface instances
     *
     * @throws MappingException If any of the loaders does not implement LoaderInterface
     */
    public function __construct(array $loaders)
    {
        foreach ($loaders as $loader) {
            if (!$loader instanceof LoaderInterface) {
                throw new MappingException(sprintf('Class %s is expected to implement LoaderInterface', get_class($loader)));
            }
        }

        $this->loaders = $loaders;
    }

    /**
     * {@inheritDoc}
     */
    public function loadClassMetadata(ClassMetadata $metadata)
    {
        $success = false;

        foreach ($this->loaders as $loader) {
            $success = $loader->loadClassMetadata($metadata) || $success;
        }

        return $success;
    }
}
PK��ZT�b��ASymfony/Component/Validator/Mapping/Loader/StaticMethodLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping\Loader;

use Symfony\Component\Validator\Exception\MappingException;
use Symfony\Component\Validator\Mapping\ClassMetadata;

class StaticMethodLoader implements LoaderInterface
{
    protected $methodName;

    public function __construct($methodName = 'loadValidatorMetadata')
    {
        $this->methodName = $methodName;
    }

    /**
     * {@inheritDoc}
     */
    public function loadClassMetadata(ClassMetadata $metadata)
    {
        /** @var \ReflectionClass $reflClass */
        $reflClass = $metadata->getReflectionClass();

        if (!$reflClass->isInterface() && $reflClass->hasMethod($this->methodName)) {
            $reflMethod = $reflClass->getMethod($this->methodName);

            if ($reflMethod->isAbstract()) {
                return false;
            }

            if (!$reflMethod->isStatic()) {
                throw new MappingException(sprintf('The method %s::%s should be static', $reflClass->name, $this->methodName));
            }

            if ($reflMethod->getDeclaringClass()->name != $reflClass->name) {
                return false;
            }

            $reflMethod->invoke(null, $metadata);

            return true;
        }

        return false;
    }
}
PK��Z�>�??>Symfony/Component/Validator/Mapping/Loader/LoaderInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping\Loader;

use Symfony\Component\Validator\Mapping\ClassMetadata;

interface LoaderInterface
{
    /**
     * Load a Class Metadata.
     *
     * @param ClassMetadata $metadata A metadata
     *
     * @return Boolean
     */
    public function loadClassMetadata(ClassMetadata $metadata);
}
PK��Z���*��:Symfony/Component/Validator/Mapping/Loader/FilesLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping\Loader;

/**
 * Creates mapping loaders for array of files.
 *
 * Abstract class, used by
 *
 * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
 *
 * @see    Symfony\Component\Validator\Mapping\Loader\YamlFileLoader
 * @see    Symfony\Component\Validator\Mapping\Loader\XmlFileLoader
 */
abstract class FilesLoader extends LoaderChain
{
    /**
     * Array of mapping files.
     *
     * @param array $paths Array of file paths
     */
    public function __construct(array $paths)
    {
        parent::__construct($this->getFileLoaders($paths));
    }

    /**
     * Array of mapping files.
     *
     * @param array $paths Array of file paths
     *
     * @return LoaderInterface[] Array of metadata loaders
     */
    protected function getFileLoaders($paths)
    {
        $loaders = array();
        foreach ($paths as $path) {
            $loaders[] = $this->getFileLoaderInstance($path);
        }

        return $loaders;
    }

    /**
     * Takes mapping file path.
     *
     * @param string $file
     *
     * @return LoaderInterface
     */
    abstract protected function getFileLoaderInstance($file);
}
PK��ZTO��--cSymfony/Component/Validator/Mapping/Loader/schema/dic/constraint-mapping/constraint-mapping-1.0.xsdnu�[���<?xml version="1.0" ?>

<xsd:schema xmlns="http://symfony.com/schema/dic/constraint-mapping"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://symfony.com/schema/dic/constraint-mapping"
    elementFormDefault="qualified">

  <xsd:annotation>
    <xsd:documentation><![CDATA[
      Symfony Validator Constraint Mapping Schema, version 1.0
      Authors: Bernhard Schussek

      A constraint mapping connects classes, properties and getters with
      validation constraints.
    ]]></xsd:documentation>
  </xsd:annotation>
  
  <xsd:element name="constraint-mapping" type="constraint-mapping" />
  
  <xsd:complexType name="constraint-mapping">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        The root element of the constraint mapping definition.
      ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:sequence>
      <xsd:element name="namespace" type="namespace" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="class" type="class" maxOccurs="unbounded" />
    </xsd:sequence>
  </xsd:complexType>
  
  <xsd:complexType name="namespace">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        Contains the abbreviation for a namespace.
      ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:simpleContent>
      <xsd:extension base="xsd:string">
        <xsd:attribute name="prefix" type="xsd:string" use="required" />
      </xsd:extension>
    </xsd:simpleContent>
  </xsd:complexType>
  
  <xsd:complexType name="class">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        Contains constraints for a single class.
        
        Nested elements may be class constraints, property and/or getter 
        definitions.
      ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:choice minOccurs="0" maxOccurs="unbounded">
      <xsd:element name="group-sequence-provider" type="group-sequence-provider" minOccurs="0" maxOccurs="1" />
      <xsd:element name="group-sequence" type="group-sequence" minOccurs="0" maxOccurs="1" />
      <xsd:element name="constraint" type="constraint" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="getter" type="getter" minOccurs="0" maxOccurs="unbounded" />
    </xsd:choice>
    <xsd:attribute name="name" type="xsd:string" use="required" />
  </xsd:complexType>

  <xsd:complexType name="group-sequence">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        Contains the group sequence of a class. Each group should be written
        into a "value" tag.
      ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:sequence>
      <xsd:element name="value" type="value" minOccurs="1" maxOccurs="unbounded" />
    </xsd:sequence>
  </xsd:complexType>
  
  <xsd:complexType name="group-sequence-provider">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        Defines the name of the group sequence provider for a class.
      ]]></xsd:documentation>
    </xsd:annotation>
  </xsd:complexType>
  
  <xsd:complexType name="property">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        Contains constraints for a single property. The name of the property
        should be given in the "name" option.
      ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:sequence>
      <xsd:element name="constraint" type="constraint" maxOccurs="unbounded" />
    </xsd:sequence>
    <xsd:attribute name="name" type="xsd:string" use="required" />
  </xsd:complexType>
  
  <xsd:complexType name="getter">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        Contains constraints for a getter method. The name of the corresponding
        property should be given in the "property" option.
      ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:sequence>
      <xsd:element name="constraint" type="constraint" maxOccurs="unbounded" />
    </xsd:sequence>
    <xsd:attribute name="property" type="xsd:string" use="required" />
  </xsd:complexType>
  
  <xsd:complexType name="constraint" mixed="true">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        Contains a constraint definition. The name of the constraint should be
        given in the "name" option.
        
        May contain a single value, multiple "constraint" elements, 
        multiple "value" elements or multiple "option" elements.
      ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:choice minOccurs="0">
      <xsd:element name="constraint" type="constraint" minOccurs="1" maxOccurs="unbounded" />
      <xsd:element name="option" type="option" minOccurs="1" maxOccurs="unbounded" />
      <xsd:element name="value" type="value" minOccurs="1" maxOccurs="unbounded" />
    </xsd:choice>
    <xsd:attribute name="name" type="xsd:string" use="required" />    
  </xsd:complexType>
  
  <xsd:complexType name="option" mixed="true">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        Contains a constraint option definition. The name of the option
        should be given in the "name" option.
        
        May contain a single value, multiple "value" elements or multiple
        "constraint" elements.
      ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:choice minOccurs="0">
      <xsd:element name="constraint" type="constraint" minOccurs="1" maxOccurs="unbounded" />
      <xsd:element name="value" type="value" minOccurs="1" maxOccurs="unbounded" />
    </xsd:choice>
    <xsd:attribute name="name" type="xsd:string" use="required" />  
  </xsd:complexType>
  
  <xsd:complexType name="value" mixed="true">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        A value of an element.
        
        May contain a single value, multiple "value" elements or multiple
        "constraint" elements.
      ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:choice minOccurs="0">
      <xsd:element name="constraint" type="constraint" minOccurs="1" maxOccurs="unbounded" />
      <xsd:element name="value" type="value" minOccurs="1" maxOccurs="unbounded" />
    </xsd:choice>
    <xsd:attribute name="key" type="xsd:string" use="optional" /> 
  </xsd:complexType>
</xsd:schema>
PK��Z;Q�F11<Symfony/Component/Validator/Mapping/Loader/XmlFileLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping\Loader;

use Symfony\Component\Validator\Exception\MappingException;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Config\Util\XmlUtils;

class XmlFileLoader extends FileLoader
{
    /**
     * An array of SimpleXMLElement instances.
     *
     * @var \SimpleXMLElement[]
     */
    protected $classes = null;

    /**
     * {@inheritDoc}
     */
    public function loadClassMetadata(ClassMetadata $metadata)
    {
        if (null === $this->classes) {
            $this->classes = array();
            $xml = $this->parseFile($this->file);

            foreach ($xml->namespace as $namespace) {
                $this->addNamespaceAlias((string) $namespace['prefix'], trim((string) $namespace));
            }

            foreach ($xml->class as $class) {
                $this->classes[(string) $class['name']] = $class;
            }
        }

        if (isset($this->classes[$metadata->getClassName()])) {
            $xml = $this->classes[$metadata->getClassName()];

            foreach ($xml->{'group-sequence-provider'} as $provider) {
                $metadata->setGroupSequenceProvider(true);
            }

            foreach ($xml->{'group-sequence'} as $groupSequence) {
                if (count($groupSequence->value) > 0) {
                    $metadata->setGroupSequence($this->parseValues($groupSequence[0]->value));
                }
            }

            foreach ($this->parseConstraints($xml->constraint) as $constraint) {
                $metadata->addConstraint($constraint);
            }

            foreach ($xml->property as $property) {
                foreach ($this->parseConstraints($property->constraint) as $constraint) {
                    $metadata->addPropertyConstraint((string) $property['name'], $constraint);
                }
            }

            foreach ($xml->getter as $getter) {
                foreach ($this->parseConstraints($getter->constraint) as $constraint) {
                    $metadata->addGetterConstraint((string) $getter['property'], $constraint);
                }
            }

            return true;
        }

        return false;
    }

    /**
     * Parses a collection of "constraint" XML nodes.
     *
     * @param \SimpleXMLElement $nodes The XML nodes
     *
     * @return array The Constraint instances
     */
    protected function parseConstraints(\SimpleXMLElement $nodes)
    {
        $constraints = array();

        foreach ($nodes as $node) {
            if (count($node) > 0) {
                if (count($node->value) > 0) {
                    $options = $this->parseValues($node->value);
                } elseif (count($node->constraint) > 0) {
                    $options = $this->parseConstraints($node->constraint);
                } elseif (count($node->option) > 0) {
                    $options = $this->parseOptions($node->option);
                } else {
                    $options = array();
                }
            } elseif (strlen((string) $node) > 0) {
                $options = trim($node);
            } else {
                $options = null;
            }

            $constraints[] = $this->newConstraint((string) $node['name'], $options);
        }

        return $constraints;
    }

    /**
     * Parses a collection of "value" XML nodes.
     *
     * @param \SimpleXMLElement $nodes The XML nodes
     *
     * @return array The values
     */
    protected function parseValues(\SimpleXMLElement $nodes)
    {
        $values = array();

        foreach ($nodes as $node) {
            if (count($node) > 0) {
                if (count($node->value) > 0) {
                    $value = $this->parseValues($node->value);
                } elseif (count($node->constraint) > 0) {
                    $value = $this->parseConstraints($node->constraint);
                } else {
                    $value = array();
                }
            } else {
                $value = trim($node);
            }

            if (isset($node['key'])) {
                $values[(string) $node['key']] = $value;
            } else {
                $values[] = $value;
            }
        }

        return $values;
    }

    /**
     * Parses a collection of "option" XML nodes.
     *
     * @param \SimpleXMLElement $nodes The XML nodes
     *
     * @return array The options
     */
    protected function parseOptions(\SimpleXMLElement $nodes)
    {
        $options = array();

        foreach ($nodes as $node) {
            if (count($node) > 0) {
                if (count($node->value) > 0) {
                    $value = $this->parseValues($node->value);
                } elseif (count($node->constraint) > 0) {
                    $value = $this->parseConstraints($node->constraint);
                } else {
                    $value = array();
                }
            } else {
                $value = XmlUtils::phpize($node);
                if (is_string($value)) {
                    $value = trim($value);
                }
            }

            $options[(string) $node['name']] = $value;
        }

        return $options;
    }

    /**
     * Parse a XML File.
     *
     * @param string $file Path of file
     *
     * @return \SimpleXMLElement
     *
     * @throws MappingException
     */
    protected function parseFile($file)
    {
        try {
            $dom = XmlUtils::loadFile($file, __DIR__.'/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd');
        } catch (\Exception $e) {
            throw new MappingException($e->getMessage(), $e->getCode(), $e);
        }

        return simplexml_import_dom($dom);
    }
}
PK��Z	lw#QQ?Symfony/Component/Validator/Mapping/Loader/AnnotationLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping\Loader;

use Doctrine\Common\Annotations\Reader;
use Symfony\Component\Validator\Constraints\Callback;
use Symfony\Component\Validator\Exception\MappingException;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints\GroupSequence;
use Symfony\Component\Validator\Constraints\GroupSequenceProvider;
use Symfony\Component\Validator\Constraint;

class AnnotationLoader implements LoaderInterface
{
    protected $reader;

    public function __construct(Reader $reader)
    {
        $this->reader = $reader;
    }

    /**
     * {@inheritDoc}
     */
    public function loadClassMetadata(ClassMetadata $metadata)
    {
        $reflClass = $metadata->getReflectionClass();
        $className = $reflClass->name;
        $loaded = false;

        foreach ($this->reader->getClassAnnotations($reflClass) as $constraint) {
            if ($constraint instanceof GroupSequence) {
                $metadata->setGroupSequence($constraint->groups);
            } elseif ($constraint instanceof GroupSequenceProvider) {
                $metadata->setGroupSequenceProvider(true);
            } elseif ($constraint instanceof Constraint) {
                $metadata->addConstraint($constraint);
            }

            $loaded = true;
        }

        foreach ($reflClass->getProperties() as $property) {
            if ($property->getDeclaringClass()->name == $className) {
                foreach ($this->reader->getPropertyAnnotations($property) as $constraint) {
                    if ($constraint instanceof Constraint) {
                        $metadata->addPropertyConstraint($property->name, $constraint);
                    }

                    $loaded = true;
                }
            }
        }

        foreach ($reflClass->getMethods() as $method) {
            if ($method->getDeclaringClass()->name ==  $className) {
                foreach ($this->reader->getMethodAnnotations($method) as $constraint) {
                    if ($constraint instanceof Callback) {
                        $constraint->callback = $method->getName();
                        $constraint->methods = null;

                        $metadata->addConstraint($constraint);
                    } elseif ($constraint instanceof Constraint) {
                        if (preg_match('/^(get|is)(.+)$/i', $method->name, $matches)) {
                            $metadata->addGetterConstraint(lcfirst($matches[2]), $constraint);
                        } else {
                            throw new MappingException(sprintf('The constraint on "%s::%s" cannot be added. Constraints can only be added on methods beginning with "get" or "is".', $className, $method->name));
                        }
                    }

                    $loaded = true;
                }
            }
        }

        return $loaded;
    }
}
PK��Z'��pkk=Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping\Loader;

use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Yaml\Parser as YamlParser;

class YamlFileLoader extends FileLoader
{
    private $yamlParser;

    /**
     * An array of YAML class descriptions
     *
     * @var array
     */
    protected $classes = null;

    /**
     * {@inheritDoc}
     */
    public function loadClassMetadata(ClassMetadata $metadata)
    {
        if (null === $this->classes) {
            if (!stream_is_local($this->file)) {
                throw new \InvalidArgumentException(sprintf('This is not a local file "%s".', $this->file));
            }

            if (!file_exists($this->file)) {
                throw new \InvalidArgumentException(sprintf('File "%s" not found.', $this->file));
            }

            if (null === $this->yamlParser) {
                $this->yamlParser = new YamlParser();
            }

            $this->classes = $this->yamlParser->parse(file_get_contents($this->file));

            // empty file
            if (null === $this->classes) {
                return false;
            }

            // not an array
            if (!is_array($this->classes)) {
                throw new \InvalidArgumentException(sprintf('The file "%s" must contain a YAML array.', $this->file));
            }

            if (isset($this->classes['namespaces'])) {
                foreach ($this->classes['namespaces'] as $alias => $namespace) {
                    $this->addNamespaceAlias($alias, $namespace);
                }

                unset($this->classes['namespaces']);
            }
        }

        // TODO validation

        if (isset($this->classes[$metadata->getClassName()])) {
            $yaml = $this->classes[$metadata->getClassName()];

            if (isset($yaml['group_sequence_provider'])) {
                $metadata->setGroupSequenceProvider((bool) $yaml['group_sequence_provider']);
            }

            if (isset($yaml['group_sequence'])) {
                $metadata->setGroupSequence($yaml['group_sequence']);
            }

            if (isset($yaml['constraints']) && is_array($yaml['constraints'])) {
                foreach ($this->parseNodes($yaml['constraints']) as $constraint) {
                    $metadata->addConstraint($constraint);
                }
            }

            if (isset($yaml['properties']) && is_array($yaml['properties'])) {
                foreach ($yaml['properties'] as $property => $constraints) {
                    if (null !== $constraints) {
                        foreach ($this->parseNodes($constraints) as $constraint) {
                            $metadata->addPropertyConstraint($property, $constraint);
                        }
                    }
                }
            }

            if (isset($yaml['getters']) && is_array($yaml['getters'])) {
                foreach ($yaml['getters'] as $getter => $constraints) {
                    if (null !== $constraints) {
                        foreach ($this->parseNodes($constraints) as $constraint) {
                            $metadata->addGetterConstraint($getter, $constraint);
                        }
                    }
                }
            }

            return true;
        }

        return false;
    }

    /**
     * Parses a collection of YAML nodes
     *
     * @param array $nodes The YAML nodes
     *
     * @return array An array of values or Constraint instances
     */
    protected function parseNodes(array $nodes)
    {
        $values = array();

        foreach ($nodes as $name => $childNodes) {
            if (is_numeric($name) && is_array($childNodes) && count($childNodes) == 1) {
                $options = current($childNodes);

                if (is_array($options)) {
                    $options = $this->parseNodes($options);
                }

                $values[] = $this->newConstraint(key($childNodes), $options);
            } else {
                if (is_array($childNodes)) {
                    $childNodes = $this->parseNodes($childNodes);
                }

                $values[$name] = $childNodes;
            }
        }

        return $values;
    }
}
PK��Z�۔��@Symfony/Component/Validator/Mapping/BlackholeMetadataFactory.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping;

use Symfony\Component\Validator\MetadataFactoryInterface;

/**
 * Simple implementation of MetadataFactoryInterface that can be used when using ValidatorInterface::validateValue().
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class BlackholeMetadataFactory implements MetadataFactoryInterface
{
    /**
     * @inheritdoc
     */
    public function getMetadataFor($value)
    {
        throw new \LogicException('BlackholeClassMetadataFactory only works with ValidatorInterface::validateValue().');
    }

    /**
     * @inheritdoc
     */
    public function hasMetadataFor($value)
    {
        return false;
    }
}
PK��Z�L8��
�
:Symfony/Component/Validator/ValidationVisitorInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * Validates values against constraints defined in {@link MetadataInterface}
 * instances.
 *
 * This interface is an implementation of the Visitor design pattern. A value
 * is validated by first passing it to the {@link validate} method. That method
 * will determine the matching {@link MetadataInterface} for validating the
 * value. It then calls the {@link MetadataInterface::accept} method of that
 * metadata. <tt>accept()</tt> does two things:
 *
 * <ol>
 * <li>It calls {@link visit} to validate the value against the constraints of
 * the metadata.</li>
 * <li>It calls <tt>accept()</tt> on all nested metadata instances with the
 * corresponding values extracted from the current value. For example, if the
 * current metadata represents a class and the current value is an object of
 * that class, the metadata contains nested instances for each property of that
 * class. It forwards the call to these nested metadata with the values of the
 * corresponding properties in the original object.</li>
 * </ol>
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface ValidationVisitorInterface
{
    /**
     * Validates a value.
     *
     * If the value is an array or a traversable object, you can set the
     * parameter <tt>$traverse</tt> to <tt>true</tt> in order to run through
     * the collection and validate each element. If these elements can be
     * collections again and you want to traverse them recursively, set the
     * parameter <tt>$deep</tt> to <tt>true</tt> as well.
     *
     * If you set <tt>$traversable</tt> to <tt>true</tt>, the visitor will
     * nevertheless try to find metadata for the collection and validate its
     * constraints. If no such metadata is found, the visitor ignores that and
     * only iterates the collection.
     *
     * If you don't set <tt>$traversable</tt> to <tt>true</tt> and the visitor
     * does not find metadata for the given value, it will fail with an
     * exception.
     *
     * @param mixed   $value        The value to validate.
     * @param string  $group        The validation group to validate.
     * @param string  $propertyPath The current property path in the validation graph.
     * @param Boolean $traverse     Whether to traverse the value if it is traversable.
     * @param Boolean $deep         Whether to traverse nested traversable values recursively.
     *
     * @throws Exception\NoSuchMetadataException If no metadata can be found for
     *                                           the given value.
     */
    public function validate($value, $group, $propertyPath, $traverse = false, $deep = false);

    /**
     * Validates a value against the constraints defined in some metadata.
     *
     * This method implements the Visitor design pattern. See also
     * {@link ValidationVisitorInterface}.
     *
     * @param MetadataInterface $metadata     The metadata holding the constraints.
     * @param mixed             $value        The value to validate.
     * @param string            $group        The validation group to validate.
     * @param string            $propertyPath The current property path in the validation graph.
     */
    public function visit(MetadataInterface $metadata, $value, $group, $propertyPath);
}
PK��ZQ���VV:Symfony/Component/Validator/Exception/MappingException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Exception;

class MappingException extends ValidatorException
{
}
PK��Z��y��@Symfony/Component/Validator/Exception/BadMethodCallException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Exception;

/**
 * Base BadMethodCallException for the Validator component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface
{
}
PK��ZL�ЉRRASymfony/Component/Validator/Exception/InvalidOptionsException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Exception;

class InvalidOptionsException extends ValidatorException
{
    private $options;

    public function __construct($message, array $options)
    {
        parent::__construct($message);

        $this->options = $options;
    }

    public function getOptions()
    {
        return $this->options;
    }
}
PK��Zk1+WW<Symfony/Component/Validator/Exception/ValidatorException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Exception;

class ValidatorException extends \RuntimeException
{
}
PK��Z�b�<<ASymfony/Component/Validator/Exception/UnexpectedTypeException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Exception;

class UnexpectedTypeException extends ValidatorException
{
    public function __construct($value, $expectedType)
    {
        parent::__construct(sprintf('Expected argument of type "%s", "%s" given', $expectedType, is_object($value) ? get_class($value) : gettype($value)));
    }
}
PK��Z�1�"ccGSymfony/Component/Validator/Exception/ConstraintDefinitionException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Exception;

class ConstraintDefinitionException extends ValidatorException
{
}
PK��Z�T����<Symfony/Component/Validator/Exception/ExceptionInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Exception;

/**
 * Base ExceptionInterface for the Validator component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface ExceptionInterface
{
}
PK��Zz����:Symfony/Component/Validator/Exception/RuntimeException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Exception;

/**
 * Base RuntimeException for the Validator component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
PK��Z��x��ASymfony/Component/Validator/Exception/NoSuchMetadataException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Exception;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class NoSuchMetadataException extends ValidatorException
{
}
PK��Zu��RRASymfony/Component/Validator/Exception/MissingOptionsException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Exception;

class MissingOptionsException extends ValidatorException
{
    private $options;

    public function __construct($message, array $options)
    {
        parent::__construct($message);

        $this->options = $options;
    }

    public function getOptions()
    {
        return $this->options;
    }
}
PK��ZM��#^^BSymfony/Component/Validator/Exception/GroupDefinitionException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Exception;

class GroupDefinitionException extends ValidatorException
{
}
PK��Z�\��BSymfony/Component/Validator/Exception/InvalidArgumentException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Exception;

/**
 * Base InvalidArgumentException for the Validator component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
PK��Z�U�<<3Symfony/Component/Validator/ClassBasedInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * An object backed by a PHP class.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface ClassBasedInterface
{
    /**
     * Returns the name of the backing PHP class.
     *
     * @return string The name of the backing class.
     */
    public function getClassName();
}
PK��Z;5t��7Symfony/Component/Validator/ConstraintViolationList.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * Default implementation of {@ConstraintViolationListInterface}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ConstraintViolationList implements \IteratorAggregate, ConstraintViolationListInterface
{
    /**
     * @var ConstraintViolationInterface[]
     */
    private $violations = array();

    /**
     * Creates a new constraint violation list.
     *
     * @param ConstraintViolationInterface[] $violations The constraint violations to add to the list
     */
    public function __construct(array $violations = array())
    {
        foreach ($violations as $violation) {
            $this->add($violation);
        }
    }

    /**
     * Converts the violation into a string for debugging purposes.
     *
     * @return string The violation as string.
     */
    public function __toString()
    {
        $string = '';

        foreach ($this->violations as $violation) {
            $string .= $violation."\n";
        }

        return $string;
    }

    /**
     * {@inheritDoc}
     */
    public function add(ConstraintViolationInterface $violation)
    {
        $this->violations[] = $violation;
    }

    /**
     * {@inheritDoc}
     */
    public function addAll(ConstraintViolationListInterface $otherList)
    {
        foreach ($otherList as $violation) {
            $this->violations[] = $violation;
        }
    }

    /**
     * {@inheritDoc}
     */
    public function get($offset)
    {
        if (!isset($this->violations[$offset])) {
            throw new \OutOfBoundsException(sprintf('The offset "%s" does not exist.', $offset));
        }

        return $this->violations[$offset];
    }

    /**
     * {@inheritDoc}
     */
    public function has($offset)
    {
        return isset($this->violations[$offset]);
    }

    /**
     * {@inheritDoc}
     */
    public function set($offset, ConstraintViolationInterface $violation)
    {
        $this->violations[$offset] = $violation;
    }

    /**
     * {@inheritDoc}
     */
    public function remove($offset)
    {
        unset($this->violations[$offset]);
    }

    /**
     * {@inheritDoc}
     */
    public function getIterator()
    {
        return new \ArrayIterator($this->violations);
    }

    /**
     * {@inheritDoc}
     */
    public function count()
    {
        return count($this->violations);
    }

    /**
     * {@inheritDoc}
     */
    public function offsetExists($offset)
    {
        return $this->has($offset);
    }

    /**
     * {@inheritDoc}
     */
    public function offsetGet($offset)
    {
        return $this->get($offset);
    }

    /**
     * {@inheritDoc}
     */
    public function offsetSet($offset, $violation)
    {
        if (null === $offset) {
            $this->add($violation);
        } else {
            $this->set($offset, $violation);
        }
    }

    /**
     * {@inheritDoc}
     */
    public function offsetUnset($offset)
    {
        $this->remove($offset);
    }
}
PK��ZAbI̲�1Symfony/Component/Validator/ValidationVisitor.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

use Symfony\Component\Validator\Exception\NoSuchMetadataException;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Translation\TranslatorInterface;

/**
 * Default implementation of {@link ValidationVisitorInterface} and
 * {@link GlobalExecutionContextInterface}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ValidationVisitor implements ValidationVisitorInterface, GlobalExecutionContextInterface
{
    /**
     * @var mixed
     */
    private $root;

    /**
     * @var MetadataFactoryInterface
     */
    private $metadataFactory;

    /**
     * @var ConstraintValidatorFactoryInterface
     */
    private $validatorFactory;

    /**
     * @var TranslatorInterface
     */
    private $translator;

    /**
     * @var null|string
     */
    private $translationDomain;

    /**
     * @var array
     */
    private $objectInitializers;

    /**
     * @var ConstraintViolationList
     */
    private $violations;

    /**
     * @var array
     */
    private $validatedObjects = array();

    /**
     * Creates a new validation visitor.
     *
     * @param mixed                               $root               The value passed to the validator.
     * @param MetadataFactoryInterface            $metadataFactory    The factory for obtaining metadata instances.
     * @param ConstraintValidatorFactoryInterface $validatorFactory   The factory for creating constraint validators.
     * @param TranslatorInterface                 $translator         The translator for translating violation messages.
     * @param string|null                         $translationDomain  The domain of the translation messages.
     * @param ObjectInitializerInterface[]        $objectInitializers The initializers for preparing objects before validation.
     *
     * @throws UnexpectedTypeException If any of the object initializers is not an instance of ObjectInitializerInterface
     */
    public function __construct($root, MetadataFactoryInterface $metadataFactory, ConstraintValidatorFactoryInterface $validatorFactory, TranslatorInterface $translator, $translationDomain = null, array $objectInitializers = array())
    {
        foreach ($objectInitializers as $initializer) {
            if (!$initializer instanceof ObjectInitializerInterface) {
                throw new UnexpectedTypeException($initializer, 'Symfony\Component\Validator\ObjectInitializerInterface');
            }
        }

        $this->root = $root;
        $this->metadataFactory = $metadataFactory;
        $this->validatorFactory = $validatorFactory;
        $this->translator = $translator;
        $this->translationDomain = $translationDomain;
        $this->objectInitializers = $objectInitializers;
        $this->violations = new ConstraintViolationList();
    }

    /**
     * {@inheritdoc}
     */
    public function visit(MetadataInterface $metadata, $value, $group, $propertyPath)
    {
        $context = new ExecutionContext(
            $this,
            $this->translator,
            $this->translationDomain,
            $metadata,
            $value,
            $group,
            $propertyPath
        );

        $context->validateValue($value, $metadata->findConstraints($group));
    }

    /**
     * {@inheritdoc}
     */
    public function validate($value, $group, $propertyPath, $traverse = false, $deep = false)
    {
        if (null === $value) {
            return;
        }

        if (is_object($value)) {
            $hash = spl_object_hash($value);

            // Exit, if the object is already validated for the current group
            if (isset($this->validatedObjects[$hash][$group])) {
                return;
            }

            // Remember validating this object before starting and possibly
            // traversing the object graph
            $this->validatedObjects[$hash][$group] = true;

            foreach ($this->objectInitializers as $initializer) {
                if (!$initializer instanceof ObjectInitializerInterface) {
                    throw new \LogicException('Validator initializers must implement ObjectInitializerInterface.');
                }
                $initializer->initialize($value);
            }
        }

        // Validate arrays recursively by default, otherwise every driver needs
        // to implement special handling for arrays.
        // https://github.com/symfony/symfony/issues/6246
        if (is_array($value) || ($traverse && $value instanceof \Traversable)) {
            foreach ($value as $key => $element) {
                // Ignore any scalar values in the collection
                if (is_object($element) || is_array($element)) {
                    // Only repeat the traversal if $deep is set
                    $this->validate($element, $group, $propertyPath.'['.$key.']', $deep, $deep);
                }
            }

            try {
                $this->metadataFactory->getMetadataFor($value)->accept($this, $value, $group, $propertyPath);
            } catch (NoSuchMetadataException $e) {
                // Metadata doesn't necessarily have to exist for
                // traversable objects, because we know how to validate
                // them anyway. Optionally, additional metadata is supported.
            }
        } else {
            $this->metadataFactory->getMetadataFor($value)->accept($this, $value, $group, $propertyPath);
        }
    }

    /**
     * {@inheritdoc}
     */
    public function getViolations()
    {
        return $this->violations;
    }

    /**
     * {@inheritdoc}
     */
    public function getRoot()
    {
        return $this->root;
    }

    /**
     * {@inheritdoc}
     */
    public function getVisitor()
    {
        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function getValidatorFactory()
    {
        return $this->validatorFactory;
    }

    /**
     * {@inheritdoc}
     */
    public function getMetadataFactory()
    {
        return $this->metadataFactory;
    }
}
PK��Zbh��BSymfony/Component/Validator/PropertyMetadataContainerInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * A container for {@link PropertyMetadataInterface} instances.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface PropertyMetadataContainerInterface
{
    /**
     * Check if there's any metadata attached to the given named property.
     *
     * @param string $property The property name.
     *
     * @return Boolean
     */
    public function hasPropertyMetadata($property);

    /**
     * Returns all metadata instances for the given named property.
     *
     * If your implementation does not support properties, simply throw an
     * exception in this method (for example a <tt>BadMethodCallException</tt>).
     *
     * @param string $property The property name.
     *
     * @return PropertyMetadataInterface[] A list of metadata instances. Empty if
     *                                     no metadata exists for the property.
     */
    public function getPropertyMetadata($property);
}
PK��ZY����8Symfony/Component/Validator/MetadataFactoryInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * Returns {@link MetadataInterface} instances for values.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface MetadataFactoryInterface
{
    /**
     * Returns the metadata for the given value.
     *
     * @param mixed $value Some value.
     *
     * @return MetadataInterface The metadata for the value.
     *
     * @throws Exception\NoSuchMetadataException If no metadata exists for the value.
     */
    public function getMetadataFor($value);

    /**
     * Returns whether metadata exists for the given value.
     *
     * @param mixed $value Some value.
     *
     * @return Boolean Whether metadata exists for the value.
     */
    public function hasMetadataFor($value);
}
PK��ZD#��?�?DSymfony/Component/Validator/Resources/translations/validators.en.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>This value should be false.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>This value should be true.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>This value should be of type {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>This value should be blank.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>The value you selected is not a valid choice.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>One or more of the given values is invalid.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>The fields {{ fields }} were not expected.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>The fields {{ fields }} are missing.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>This value is not a valid date.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>This value is not a valid datetime.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>This value is not a valid email address.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>The file could not be found.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>The file is not readable.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>This value should be {{ limit }} or less.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>This value should be {{ limit }} or more.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>This value should not be blank.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>This value should not be null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>This value should be null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>This value is not valid.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>This value is not a valid time.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>This value is not a valid URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>The two values should be equal.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>The file is too large.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>The file could not be uploaded.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>This value should be a valid number.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>This file is not a valid image.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>This is not a valid IP address.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>This value is not a valid language.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>This value is not a valid locale.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>This value is not a valid country.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>This value is already used.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>The size of the image could not be detected.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>This value should be the user current password.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>The file was only partially uploaded.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>No file was uploaded.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>No temporary folder was configured in php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Cannot write temporary file to disk.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>A PHP extension caused the upload to fail.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Invalid card number.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Unsupported card type or invalid card number.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>This is not a valid International Bank Account Number (IBAN).</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>This value is not a valid ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>This value is not a valid ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>This value is neither a valid ISBN-10 nor a valid ISBN-13.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>This value is not a valid ISSN.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>This value is not a valid currency.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>This value should be equal to {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>This value should be greater than {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>This value should be greater than or equal to {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>This value should be less than {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>This value should be less than or equal to {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>This value should not be equal to {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z-���uCuCDSymfony/Component/Validator/Resources/translations/validators.sk.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Táto hodnota by mala byť nastavená na false.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Táto hodnota by mala byť nastavená na true.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Táto hodnota by mala byť typu {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Táto hodnota by mala byť prázdna.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Táto hodnota by mala byť jednou z poskytnutých možností.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Mali by ste vybrať minimálne {{ limit }} možnosť.|Mali by ste vybrať minimálne {{ limit }} možnosti.|Mali by ste vybrať minimálne {{ limit }} možností.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Mali by ste vybrať najviac {{ limit }} možnosť.|Mali by ste vybrať najviac {{ limit }} možnosti.|Mali by ste vybrať najviac {{ limit }} možností.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Niektoré z uvedených hodnôt sú neplatné.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Polia {{ fields }} neboli očakávané.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Chýbajú polia {{ fields }} .</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Tato hodnota nemá platný formát dátumu.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Táto hodnota nemá platný formát dátumu a času.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Táto hodnota nie je platná emailová adresa.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Súbor sa nenašiel.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Súbor nie je čitateľný.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Súbor je príliš veľký ({{ size }} {{ suffix }}). Maximálna povolená veľkosť je {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Súbor typu ({{ type }}) nie je podporovaný. Podporované typy sú {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Táto hodnota by mala byť {{ limit }} alebo menej.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Táto hodnota obsahuje viac znakov ako je povolené. Mala by obsahovať najviac {{ limit }} znak.|Táto hodnota obsahuje viac znakov ako je povolené. Mala by obsahovať najviac {{ limit }} znaky.|Táto hodnota obsahuje viac znakov ako je povolené. Mala by obsahovať najviac {{ limit }} znakov.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Táto hodnota by mala byť viac ako {{ limit }}.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Táto hodnota je príliš krátka. Musí obsahovať minimálne {{ limit }} znak.|Táto hodnota je príliš krátka. Musí obsahovať minimálne {{ limit }} znaky.|Táto hodnota je príliš krátka. Minimálny počet znakov je {{ limit }}.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Táto hodnota by mala byť vyplnená.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Táto hodnota by nemala byť null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Táto hodnota by mala byť null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Táto hodnota nie je platná.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Tato hodnota nemá správny formát času.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Táto hodnota nie je platnou URL adresou.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Tieto dve hodnoty by mali byť rovnaké.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Súbor je príliš veľký. Maximálna povolená veľkosť je {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Súbor je príliš veľký.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Súbor sa nepodarilo nahrať.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Táto hodnota by mala byť číslo.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Tento súbor nie je obrázok.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Toto nie je platná IP adresa.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Tento jazyk neexistuje.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Táto lokalizácia neexistuje.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Táto krajina neexistuje.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Táto hodnota sa už používa.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Nepodarilo sa zistiť rozmery obrázku.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Obrázok je príliš široký ({{ width }}px). Maximálna povolená šírka obrázku je {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Obrázok je príliš úzky ({{ width }}px). Minimálna šírka obrázku by mala byť {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>>Obrázok je príliš vysoký ({{ height }}px). Maximálna povolená výška obrázku je {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Obrázok je príliš nízky ({{ height }}px). Minimálna výška obrázku by mala byť {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Táto hodnota by mala byť aktuálne heslo používateľa.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Táto hodnota by mala mať presne {{ limit }} znak.|Táto hodnota by mala mať presne {{ limit }} znaky.|Táto hodnota by mala mať presne {{ limit }} znakov.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Bola nahraná len časť súboru.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Žiadny súbor nebol nahraný.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>V php.ini nie je nastavená cesta k adresáru pre dočasné súbory.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Dočasný súbor sa nepodarilo zapísať na disk.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Rozšírenie PHP zabránilo nahraniu súboru.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Táto kolekcia by mala obsahovať aspoň {{ limit }} prvok alebo viac.|Táto kolekcia by mala obsahovať aspoň {{ limit }} prvky alebo viac.|Táto kolekcia by mala obsahovať aspoň {{ limit }} prvkov alebo viac.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Táto kolekcia by mala maximálne {{ limit }} prvok.|Táto kolekcia by mala obsahovať maximálne {{ limit }} prvky.|Táto kolekcia by mala obsahovať maximálne {{ limit }} prvkov.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Táto kolekcia by mala obsahovať presne {{ limit }} prvok.|Táto kolekcia by mala obsahovať presne {{ limit }} prvky.|Táto kolekcia by mala obsahovať presne {{ limit }} prvkov.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Neplatné číslo karty.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Nepodporovaný typ karty alebo neplatné číslo karty.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Toto je neplatný IBAN.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Táto hodnota je neplatné ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Táto hodnota je neplatné ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Táto hodnota nie je platné ISBN-10 ani ISBN-13.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Táto hodnota nie je platné ISSN.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Táto hodnota nie je platná mena.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Táto hodnota by mala byť rovná {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Táto hodnota by mala byť väčšia ako {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Táto hodnota by mala byť väčšia alebo rovná {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Táto hodnota by mala byť typu {{ compared_value_type }} a zároveň by mala byť rovná {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Táto hodnota by mala byť menšia ako {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Táto hodnota by mala byť menšia alebo rovná {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Táto hodnota by nemala byť rovná {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Táto hodnota by nemala byť typu {{ compared_value_type }} a zároveň by nemala byť rovná {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�τ}K}KDSymfony/Component/Validator/Resources/translations/validators.uk.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Значення повинно бути Ні.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Значення повинно бути Так.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Тип значення повинен бути {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Значення повинно бути пустим.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Обране вами значення недопустиме.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Ви повинні обрати хоча б {{ limit }} варіант.|Ви повинні обрати хоча б {{ limit }} варіанти.|Ви повинні обрати хоча б {{ limit }} варіантів.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Ви повинні обрати не більше ніж {{ limit }} варіантів.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Одне або кілька заданих значень є недопустимі.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Поля {{ fields }} не очікувалися.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Поля {{ fields }} відсутні.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Дане значення не є вірною датою.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Дане значення дати та часу недопустиме.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Значення адреси электронної пошти недопустиме.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Файл не знайдено.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Файл не читається.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Файл занадто великий ({{ size }} {{ suffix }}). Дозволений максимальний розмір {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>MIME-тип файлу недопустимий ({{ type }}). Допустимі MIME-типи файлів {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Значення повинно бути {{ limit }} або менше.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Значення занадто довге. Повинно бути рівне {{ limit }} символу або менше.|Значення занадто довге. Повинно бути рівне {{ limit }} символам або менше.|Значення занадто довге. Повинно бути рівне {{ limit }} символам або менше.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Значення повинно бути {{ limit }} або більше.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Значення занадто коротке. Повинно бути рівне {{ limit }} символу або більше.|Значення занадто коротке. Повинно бути рівне {{ limit }} символам або більше.|Значення занадто коротке. Повинно бути рівне {{ limit }} символам або більше.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Значення не повинно бути пустим.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Значення не повинно бути null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Значення повинно бути null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Значення недопустиме.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Значення часу недопустиме.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Значення URL недопустиме.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Обидва занчення повинні бути одинаковими.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Файл занадто великий. Максимальний допустимий розмір {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Файл занадто великий.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Файл не можливо завантажити.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Значення має бути допустимим числом.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Цей файл не є допустимим форматом зображення.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Це некоректна IP адреса.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Це некоректна мова.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Це некоректна локалізація.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Це некоректна країна.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Це значення вже використовується.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Не вдалося визначити розмір зображення.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Ширина зображення занадто велика ({{ width }}px). Максимально допустима ширина {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Ширина зображення занадто мала ({{ width }}px). Мінімально допустима ширина {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Висота зображення занадто велика ({{ height }}px). Максимально допустима висота {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Висота зображення занадто мала ({{ height }}px). Мінімально допустима висота {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Значення має бути поточним паролем користувача.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Значення повиино бути рівним {{ limit }} символу.|Значення повиино бути рівним {{ limit }} символам.|Значення повиино бути рівним {{ limit }} символам.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Файл був завантажений лише частково.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Файл не був завантажений.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Не налаштована тимчасова директорія в php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Неможливо записати тимчасовий файл на диск.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Розширення PHP викликало помилку при завантаженні.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Ця колекція повинна містити {{ limit }} елемент чи більше.|Ця колекція повинна містити {{ limit }} елемента чи більше.|Ця колекція повинна містити {{ limit }} елементів чи більше.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Ця колекція повинна містити {{ limit }} елемент чи менше.|Ця колекція повинна містити {{ limit }} елемента чи менше.|Ця колекція повинна містити {{ limit }} елементов чи менше.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Ця колекція повинна містити рівно {{ limit }} елемент.|Ця колекція повинна містити рівно {{ limit }} елемента.|Ця колекція повинна містити рівно {{ limit }} елементів.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Невірний номер карти.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Непідтримуваний тип карти або невірний номер карти.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Це не дійсний міжнародний номер банківського рахунку (IBAN).</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Значення не у форматі ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Значення не у форматі ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Значення не відповідає форматам ISBN-10 та ISBN-13.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Значення має невірний формат ISSN.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Значення має невірний формат валюти.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Значення повинно дорівнювати {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Значення має бути більше ніж {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Значення має бути більше або дорівнювати {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Значення має бути ідентичним {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Значення повинно бути менше ніж {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Значення повинно бути менше або дорівнювати {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Значення не повинно дорівнювати  {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Значення не повинно бути ідентичним {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z��-�1�1DSymfony/Component/Validator/Resources/translations/validators.cy.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Dylid bod y gwerth hwn yn ffug.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Dylid bod y gwerth hwn yn wir.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Dylid bod y gwerth hwn bod o fath {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Dylid bod y gwerth hwn yn wag.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Nid yw'r gwerth â ddewiswyd yn ddilys.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Rhaid dewis o leiaf {{ limit }} opsiwn.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Rhaid dewis dim mwy na {{ limit }} opsiwn.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Mae un neu fwy o'r gwerthoedd a roddwyd yn annilys.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Roedd y maesydd {{ fields }} yn anisgwyl.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Roedd y maesydd {{ fields }} ar goll.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Nid yw'r gwerth yn ddyddiad dilys.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Nid yw'r gwerth yn datetime dilys.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Nid yw'r gwerth yn gyfeiriad ebost dilys.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Ni ddarganfyddwyd y ffeil.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Ni ellir darllen y ffeil.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Mae'r ffeil yn rhy fawr ({{ size }} {{ suffix }}). Yr uchafswm â ganiateir yw {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Nid yw math mime y ffeil yn ddilys ({{ type }}). Dyma'r mathau â ganiateir {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Dylai'r gwerth hwn fod yn {{ limit }} neu lai.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Mae'r gwerth hwn rhy hir. Dylai gynnwys {{ limit }} nodyn cyfrifiadurol neu lai.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Dylai'r gwerth hwn fod yn {{ limit }} neu fwy.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Mae'r gwerth hwn yn rhy fyr. Dylai gynnwys {{ limit }} nodyn cyfrifiadurol neu fwy.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Ni ddylai'r gwerth hwn fod yn wag.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Ni ddylai'r gwerth hwn fod yn null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Dylai'r gwerth fod yn null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Nid yw'r gwerth hwn yn ddilys.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Nid yw'r gwerth hwn yn amser dilys.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Nid yw'r gwerth hwn yn URL dilys.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Rhaid i'r ddau werth fod yn gyfystyr a'u gilydd.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Mae'r ffeil yn rhy fawr. Yr uchafswm â ganiateir yw {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Mae'r ffeil yn rhy fawr.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Methwyd ag uwchlwytho'r ffeil.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Dylai'r gwerth hwn fod yn rif dilys.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Nid yw'r ffeil hon yn ddelwedd dilys.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Nid yw hwn yn gyfeiriad IP dilys.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Nid yw'r gwerth hwn yn iaith ddilys.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Nid yw'r gwerth hwn yn locale dilys.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Nid yw'r gwerth hwn yn wlad dilys.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Mae'r gwerth hwn eisoes yn cael ei ddefnyddio.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Methwyd â darganfod maint y ddelwedd.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Mae lled y ddelwedd yn rhy fawr ({{ width }}px). Y lled mwyaf â ganiateir yw {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Mae lled y ddelwedd yn rhy fach ({{ width }}px). Y lled lleiaf â ganiateir yw {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Mae uchder y ddelwedd yn rhy fawr ({{ width }}px). Yr uchder mwyaf â ganiateir yw {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Mae uchder y ddelwedd yn rhy fach ({{ width }}px). Yr uchder lleiaf â ganiateir yw {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Dylaid bod y gwerth hwn yn gyfrinair presenol y defnyddiwr.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Dylai'r gwerth hwn fod yn union {{ limit }} nodyn cyfrifiadurol o hyd.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Dim ond rhan o'r ffeil ag uwchlwythwyd.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Ni uwchlwythwyd unrhyw ffeil.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Nid oes ffolder dros-dro wedi'i gosod yn php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Methwyd ag ysgrifennu'r ffeil dros-dro ar ddisg.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Methwyd ag uwchlwytho oherwydd ategyn PHP.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Dylai'r casgliad hwn gynnwys {{ limit }} elfen neu fwy.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Dylai'r casgliad hwn gynnwys {{ limit }} elfen neu lai.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Dylai'r casgliad hwn gynnwys union {{ limit }} elfen.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Nid oedd rhif y cerdyn yn ddilys.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Unai ni dderbynir y math yna o gerdyn, neu nid yw rhif y cerdyn yn ddilys.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�m�w�B�BDSymfony/Component/Validator/Resources/translations/validators.pl.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Ta wartość powinna być fałszem.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Ta wartość powinna być prawdą.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Ta wartość powinna być typu {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Ta wartość powinna być pusta.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Ta wartość powinna być jedną z podanych opcji.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Powinieneś wybrać co najmniej {{ limit }} opcję.|Powinieneś wybrać co najmniej {{ limit }} opcje.|Powinieneś wybrać co najmniej {{ limit }} opcji.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Powinieneś wybrać maksymalnie {{ limit }} opcję.|Powinieneś wybrać maksymalnie {{ limit }} opcje.|Powinieneś wybrać maksymalnie {{ limit }} opcji.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Jedna lub więcej z podanych wartości jest nieprawidłowa.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Pola {{ fields }} nie były oczekiwane.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Brakuje pól {{ fields }}.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Ta wartość nie jest prawidłową datą.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Ta wartość nie jest prawidłową datą i czasem.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Ta wartość nie jest prawidłowym adresem email.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Plik nie mógł zostać odnaleziony.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Nie można odczytać pliku.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Plik jest za duży ({{ size }} {{ suffix }}). Maksymalny dozwolony rozmiar to {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Nieprawidłowy typ mime pliku ({{ type }}). Dozwolone typy mime to {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Ta wartość powinna wynosić {{ limit }} lub mniej.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Ta wartość jest zbyt długa. Powinna mieć {{ limit }} lub mniej znaków.|Ta wartość jest zbyt długa. Powinna mieć {{ limit }} lub mniej znaków.|Ta wartość jest zbyt długa. Powinna mieć {{ limit }} lub mniej znaków.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Ta wartość powinna wynosić {{ limit }} lub więcej.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Ta wartość jest zbyt krótka. Powinna mieć {{ limit }} lub więcej znaków.|Ta wartość jest zbyt krótka. Powinna mieć {{ limit }} lub więcej znaków.|Ta wartość jest zbyt krótka. Powinna mieć {{ limit }} lub więcej znaków.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Ta wartość nie powinna być pusta.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Ta wartość nie powinna być nullem.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Ta wartość powinna być nullem.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Ta wartość jest nieprawidłowa.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Ta wartość nie jest prawidłowym czasem.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Ta wartość nie jest prawidłowym adresem URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Obie wartości powinny być równe.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Plik jest za duży. Maksymalny dozwolony rozmiar to {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Plik jest za duży.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Plik nie mógł być wgrany.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Ta wartość powinna być prawidłową liczbą.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Ten plik nie jest obrazem.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>To nie jest prawidłowy adres IP.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Ta wartość nie jest prawidłowym językiem.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Ta wartość nie jest prawidłową lokalizacją.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Ta wartość nie jest prawidłową nazwą kraju.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Ta wartość jest już wykorzystywana.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Nie można wykryć rozmiaru obrazka.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Szerokość obrazka jest zbyt duża ({{ width }}px). Maksymalna dopuszczalna szerokość to {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Szerokość obrazka jest zbyt mała ({{ width }}px). Oczekiwana minimalna szerokość to {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Wysokość obrazka jest zbyt duża ({{ height }}px). Maksymalna dopuszczalna wysokość to {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Wysokość obrazka jest zbyt mała ({{ height }}px). Oczekiwana minimalna wysokość to {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Ta wartość powinna być aktualnym hasłem użytkownika.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Ta wartość powinna mieć dokładnie {{ limit }} znak.|Ta wartość powinna mieć dokładnie {{ limit }} znaki.|Ta wartość powinna mieć dokładnie {{ limit }} znaków.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Plik został wgrany tylko częściowo.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Żaden plik nie został wgrany.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Nie skonfigurowano folderu tymczasowego w php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Nie można zapisać pliku tymczasowego na dysku.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Rozszerzenie PHP spowodowało błąd podczas wgrywania.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Ten zbiór powinien zawierać {{ limit }} lub więcej elementów.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Ten zbiór powinien zawierać {{ limit }} lub mniej elementów.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Ten zbiór powinien zawierać dokładnie {{ limit }} element.|Ten zbiór powinien zawierać dokładnie {{ limit }} elementy.|Ten zbiór powinien zawierać dokładnie {{ limit }} elementów.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Nieprawidłowy numer karty.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Nieobsługiwany rodzaj karty lub nieprawidłowy numer karty.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Nieprawidłowy międzynarodowy numer rachunku bankowego (IBAN).</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Ta wartość nie jest prawidłowym numerem ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Ta wartość nie jest prawidłowym numerem ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Ta wartość nie jest prawidłowym numerem ISBN-10 ani ISBN-13.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Ta wartość nie jest prawidłowym numerem ISSN.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Ta wartość nie jest prawidłową walutą.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Ta wartość powinna być równa {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Ta wartość powinna być większa niż {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Ta wartość powinna być większa bądź równa {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Ta wartość powinna być identycznego typu {{ compared_value_type }} oraz wartości {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Ta wartość powinna być mniejsza niż {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Ta wartość powinna być mniejsza bądź równa {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Ta wartość nie powinna być równa {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Ta wartość nie powinna być identycznego typu {{ compared_value_type }} oraz wartości {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z@T�\44DSymfony/Component/Validator/Resources/translations/validators.af.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Hierdie waarde moet vals wees.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Hierdie waarde moet waar wees.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Hierdie waarde moet van die soort {{type}} wees.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Hierdie waarde moet leeg wees.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Die waarde wat jy gekies het is nie 'n geldige keuse nie.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Jy moet ten minste {{ limit }} kies.|Jy moet ten minste {{ limit }} keuses kies.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Jy moet by die meeste {{ limit }} keuse kies.|Jy moet by die meeste {{ limit }} keuses kies.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Een of meer van die gegewe waardes is ongeldig.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Die velde {{ fields }} is nie verwag nie.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Die velde {{ fields }} ontbreek.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Hierdie waarde is nie 'n geldige datum nie.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Hierdie waarde is nie 'n geldige datum en tyd nie.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Hierdie waarde is nie 'n geldige e-pos adres nie.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Die lêer kon nie gevind word nie.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Die lêer kan nie gelees word nie.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Die lêer is te groot ({{ size }} {{ suffix }}). Toegelaat maksimum grootte is {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Die MIME-tipe van die lêer is ongeldig ({{ type }}). Toegelaat MIME-tipes is {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Hierdie waarde moet {{ limit }} of minder wees.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Hierdie waarde is te lank. Dit moet {{ limit }} karakter of minder wees.|Hierdie waarde is te lank. Dit moet {{ limit }} karakters of minder wees.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Hierdie waarde moet {{ limit }} of meer wees.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Hierdie waarde is te kort. Dit moet {{ limit }} karakter of meer wees.|Hierdie waarde is te kort. Dit moet {{ limit }} karakters of meer wees.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Hierdie waarde moet nie leeg wees nie.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Hierdie waarde moet nie nul wees nie.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Hierdie waarde moet nul wees.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Hierdie waarde is nie geldig nie.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Hierdie waarde is nie 'n geldige tyd nie.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Hierdie waarde is nie 'n geldige URL nie.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Die twee waardes moet gelyk wees.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Die lêer is te groot. Toegelaat maksimum grootte is {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Die lêer is te groot.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Die lêer kan nie opgelaai word nie.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Hierdie waarde moet 'n geldige nommer wees.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Hierdie lêer is nie 'n geldige beeld nie.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Hierdie is nie 'n geldige IP-adres nie.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Hierdie waarde is nie 'n geldige taal nie.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Hierdie waarde is nie 'n geldige land instelling nie.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Hierdie waarde is nie 'n geldige land nie.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Hierdie waarde word reeds gebruik.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Die grootte van die beeld kon nie opgespoor word nie.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Die beeld breedte is te groot ({{ width }}px). Toegelaat maksimum breedte is {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Die beeld breedte is te klein ({{ width }}px). Minimum breedte verwag is {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Die beeld hoogte is te groot ({{ height }}px). Toegelaat maksimum hoogte is {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Die beeld hoogte is te klein ({{ height }}px). Minimum hoogte verwag is {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Hierdie waarde moet die huidige wagwoord van die gebruiker wees.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Hierdie waarde moet presies {{ limit }} karakter wees.|Hierdie waarde moet presies {{ limit }} karakters wees.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Die lêer is slegs gedeeltelik opgelaai.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Geen lêer is opgelaai nie.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Geen tydelike lêer is ingestel in php.ini nie.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Kan nie tydelike lêer skryf op skyf nie.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>'n PHP-uitbreiding veroorsaak die oplaai van die lêer om te misluk.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Hierdie versameling moet {{ limit }} element of meer bevat.|Hierdie versameling moet {{ limit }} elemente of meer bevat.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Hierdie versameling moet {{ limit }} element of minder bevat.|Hierdie versameling moet {{ limit }} elemente of meer bevat.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Hierdie versameling moet presies {{ limit }} element bevat.|Hierdie versameling moet presies {{ limit }} elemente bevat.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Ongeldige kredietkaart nommer.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Nie-ondersteunde tipe kaart of ongeldige kredietkaart nommer.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�b�@�@DSymfony/Component/Validator/Resources/translations/validators.pt.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Este valor deveria ser falso.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Este valor deveria ser verdadeiro.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Este valor deveria ser do tipo {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Este valor deveria ser vazio.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>O valor selecionado não é uma opção válida.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Você deveria selecionar {{ limit }} opção no mínimo.|Você deveria selecionar {{ limit }} opções no mínimo.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Você deve selecionar, no máximo {{ limit }} opção.|Você deve selecionar, no máximo {{ limit }} opções.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Um ou mais dos valores introduzidos não são válidos.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Os campos {{ fields }} não eram esperados.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Os campos {{ fields }} estão ausentes.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Este valor não é uma data válida.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Este valor não é uma data-hora válida.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Este valor não é um endereço de e-mail válido.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>O arquivo não pôde ser encontrado.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>O arquivo não pôde ser lido.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>O arquivo é muito grande ({{ size }} {{ suffix }}). O tamanho máximo permitido é de {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>O tipo mime do arquivo é inválido ({{ type }}). Os tipos mime permitidos são {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Este valor deveria ser {{ limit }} ou menor.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>O valor é muito longo. Deveria ter {{ limit }} caracteres ou menos.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Este valor deveria ser {{ limit }} ou mais.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>O valor é muito curto. Deveria de ter {{ limit }} caractere ou mais.|O valor é muito curto. Deveria de ter {{ limit }} caracteres ou mais.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Este valor não deveria ser branco/vazio.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Este valor não deveria ser nulo.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Este valor deveria ser nulo.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Este valor não é válido.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Este valor não é uma hora válida.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Este valor não é um URL válido.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Os dois valores deveriam ser iguais.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>O arquivo é muito grande. O tamanho máximo permitido é de {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>O ficheiro é muito grande.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Não foi possível carregar o ficheiro.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Este valor deveria de ser um número válido.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Este ficheiro não é uma imagem.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Este endereço de IP não é válido.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Este valor não é uma linguagem válida.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Este valor não é um 'locale' válido.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Este valor não é um País válido.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Este valor já está a ser usado.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>O tamanho da imagem não foi detetado.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>A largura da imagem ({{ width }}px) é muito grande. A largura máxima da imagem é: {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>A largura da imagem ({{ width }}px) é muito pequena. A largura miníma da imagem é de: {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>A altura da imagem ({{ height }}px) é muito grande. A altura máxima da imagem é de: {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>A altura da imagem ({{ height }}px) é muito pequena. A altura miníma da imagem é de: {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Este valor deveria de ser a password atual do utilizador.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Este valor tem de ter exatamente {{ limit }} carateres.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Só foi enviado parte do ficheiro.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Nenhum ficheiro foi enviado.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Não existe nenhum directório temporária configurado no ficheiro php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Não foi possível escrever ficheiros temporários no disco.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Uma extensão PHP causou a falha no envio.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Esta coleção deve conter {{ limit }} elemento ou mais.|Esta coleção deve conter {{ limit }} elementos ou mais.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Esta coleção deve conter {{ limit }} elemento ou menos.|Esta coleção deve conter {{ limit }} elementos ou menos.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Esta coleção deve conter exatamente {{ limit }} elemento.|Esta coleção deve conter exatamente {{ limit }} elementos.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Número de cartão inválido.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Tipo de cartão não suportado ou número de cartão inválido.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Este não é um Número Internacional de Conta Bancária (IBAN) válido.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Este valor não é um ISBN-10 válido.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Este valor não é um ISBN-13 válido.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Este valor não é um ISBN-10 ou ISBN-13 válido.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Este valor não é um ISSN válido.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Este não é um valor monetário válido.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Este valor deve ser igual a {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Este valor deve ser superior a {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Este valor deve ser igual ou superior a {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Este valor deve ser idêntico a {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Este valor deve ser inferior a {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Este valor deve ser igual ou inferior a {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Este valor não deve ser igual a {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Este valor não deve ser idêntico a {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Ze]߭A�AISymfony/Component/Validator/Resources/translations/validators.sr_Cyrl.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Вредност треба да буде нетачна.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Вредност треба да буде тачна.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Вредност треба да буде типа {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Вредност треба да буде празна.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Вредност треба да буде једна од понуђених.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Изаберите бар {{ limit }} могућност.|Изаберите бар {{ limit }} могућности.|Изаберите бар {{ limit }} могућности.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Изаберите највише {{ limit }} могућност.|Изаберите највише {{ limit }} могућности.|Изаберите највише {{ limit }} могућности.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Једна или више вредности је невалидна.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Поља {{ fields }} нису била очекивана.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Поља {{ fields }} недостају.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Вредност није валидан датум.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Вредност није валидан датум-време.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Вредност није валидна адреса електронске поште.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Датотека не може бити пронађена.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Датотека није читљива.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Датотека је превелика ({{ size }} {{ suffix }}). Највећа дозвољена величина је {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Миме тип датотеке није валидан ({{ type }}). Дозвољени миме типови су {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Вредност треба да буде {{ limit }} или мање.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Вредност је предугачка. Треба да има {{ limit }} карактер или мање.|Вредност је предугачка. Треба да има {{ limit }} карактера или мање.|Вредност је предугачка. Треба да има {{ limit }} карактера или мање.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Вредност треба да буде {{ limit }} или више.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Вредност је прекратка. Треба да има {{ limit }} карактер или више.|Вредност је прекратка. Треба да има {{ limit }} карактера или више.|Вредност је прекратка. Треба да има {{ limit }} карактера или више.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Вредност не треба да буде празна.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Вредност не треба да буде null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Вредност треба да буде null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Вредност је невалидна.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Вредност није валидно време.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Вредност није валидан URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Обе вредности треба да буду једнаке.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Датотека је превелика. Највећа дозвољена величина је {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Датотека је превелика.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Датотека не може бити отпремљена.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Вредност треба да буде валидан број.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Ова датотека није валидна слика.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Ово није валидна ИП адреса.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Вредност није валидан језик.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Вредност није валидан локал.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Вредност није валидна земља.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Вредност је већ искоришћена.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Величина слике не може бити одређена.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Ширина слике је превелика ({{ width }}px). Најећа дозвољена ширина је {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Ширина слике је премала ({{ width }}px). Најмања дозвољена ширина је {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Висина слике је превелика ({{ height }}px). Најећа дозвољена висина је {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Висина слике је премала ({{ height }}px). Најмања дозвољена висина је {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Вредност треба да буде тренутна корисничка лозинка.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Вредност треба да има тачно {{ limit }} карактер.|Вредност треба да има тачно {{ limit }} карактера.|Вредност треба да има тачно {{ limit }} карактера.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Датотека је само парцијално отпремљена.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Датотека није отпремљена.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Привремени директоријум није конфигурисан у php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Немогуће писање привремене датотеке на диск.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>PHP екстензија је проузроковала неуспех отпремања датотеке.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Ова колекција треба да садржи {{ limit }} или више елемената.|Ова колекција треба да садржи {{ limit }} или више елемената.|Ова колекција треба да садржи {{ limit }} или више елемената.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Ова колекција треба да садржи {{ limit }} или мање елемената.|Ова колекција треба да садржи {{ limit }} или мање елемената.|Ова колекција треба да садржи {{ limit }} или мање елемената.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Ова колекција треба да садржи тачно {{ limit }} елемент.|Ова колекција треба да садржи тачно {{ limit }} елемента.|Ова колекција треба да садржи тачно {{ limit }} елемената.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Невалидан број картице.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Невалидан број картице или тип картице није подржан.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Ово није валидан међународни број банковног рачуна (IBAN).</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Ово није валидан ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Ово није валидан ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Ово није валидан ISBN-10 или ISBN-13.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Ово није валидан ISSN.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�a�2�2DSymfony/Component/Validator/Resources/translations/validators.fi.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Arvon tulee olla epätosi.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Arvon tulee olla tosi.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Arvon tulee olla tyyppiä {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Arvon tulee olla tyhjä.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Arvon tulee olla yksi annetuista vaihtoehdoista.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Sinun tulee valita vähintään {{ limit }} vaihtoehtoa.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Sinun tulee valitan enintään {{ limit }} vaihtoehtoa.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Yksi tai useampi annetuista arvoista on virheellinen.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Odottamattomia kenttiä {{ fields }}.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Kentät {{ fields }} puuttuvat.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Annettu arvo ei ole kelvollinen päivämäärä.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Annettu arvo ei ole kelvollinen päivämäärä ja kellonaika.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Annettu arvo ei ole kelvollinen sähköpostiosoite.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Tiedostoa ei löydy.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Tiedostoa ei voida lukea.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Tiedostonkoko ({{ size }} {{ suffix }}) on liian iso. Suurin sallittu tiedostonkoko on {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Tiedostotyyppi ({{ type }}) on virheellinen. Sallittuja tiedostotyyppejä ovat {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Arvon tulee olla {{ limit }} tai vähemmän.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Liian pitkä syöte. Syöte saa olla enintään {{ limit }} merkkiä.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Arvon tulee olla {{ limit }} tai enemmän.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Liian lyhyt syöte. Syötteen tulee olla vähintään {{ limit }} merkkiä.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Kenttä ei voi olla tyhjä.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Syöte ei voi olla null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Syötteen tulee olla null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Virheellinen arvo.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Annettu arvo ei ole kelvollinen kellonaika.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Annettu arvo ei ole kelvollinen URL-osoite.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Kahden annetun arvon tulee olla samat.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Annettu tiedosto on liian iso. Suurin sallittu tiedostokoko on {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Tiedosto on liian iso.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Tiedoston siirto epäonnistui.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Tämän arvon tulee olla numero.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Tämä tiedosto ei ole kelvollinen kuva.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Tämä ei ole kelvollinen IP-osoite.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Tämä arvo ei ole kelvollinen kieli.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Tämä arvo ei ole kelvollinen kieli- ja alueasetus (locale).</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Tämä arvo ei ole kelvollinen maa.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Tämä arvo on jo käytetty.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Kuvan kokoa ei voitu tunnistaa.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Kuva on liian leveä ({{ width }}px). Sallittu maksimileveys on {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Kuva on liian kapea ({{ width }}px). Leveyden tulisi olla vähintään {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Kuva on liian korkea ({{ width }}px). Sallittu maksimikorkeus on {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Kuva on liian matala ({{ height }}px). Korkeuden tulisi olla vähintään {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Tämän arvon tulisi olla käyttäjän tämänhetkinen salasana.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Tämän arvon tulisi olla tasan yhden merkin pituinen.|Tämän arvon tulisi olla tasan {{ limit }} merkkiä pitkä.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Tiedosto ladattiin vain osittain.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Tiedostoa ei ladattu.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Väliaikaishakemistoa ei ole asetettu php.ini -tiedostoon.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Väliaikaistiedostoa ei voitu kirjoittaa levylle.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>PHP-laajennoksen vuoksi tiedoston lataus epäonnistui.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Tässä ryhmässä tulisi olla yksi tai useampi elementti.|Tässä ryhmässä tulisi olla vähintään {{ limit }} elementtiä.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Tässä ryhmässä tulisi olla enintään yksi elementti.|Tässä ryhmässä tulisi olla enintään {{ limit }} elementtiä.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Tässä ryhmässä tulisi olla tasan yksi elementti.|Tässä ryhmässä tulisi olla enintään {{ limit }} elementtiä.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Virheellinen korttinumero.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Tätä korttityyppiä ei tueta tai korttinumero on virheellinen.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z��"}2A2ADSymfony/Component/Validator/Resources/translations/validators.es.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Este valor debería ser falso.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Este valor debería ser verdadero.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Este valor debería ser de tipo {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Este valor debería estar vacío.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>El valor seleccionado no es una opción válida.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Debe seleccionar al menos {{ limit }} opción.|Debe seleccionar al menos {{ limit }} opciones.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Debe seleccionar como máximo {{ limit }} opción.|Debe seleccionar como máximo {{ limit }} opciones.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Uno o más de los valores indicados no son válidos.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>No se esperaban los campos {{ fields }}.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Faltan los campos {{ fields }}.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Este valor no es una fecha válida.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Este valor no es una fecha y hora válidas.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Este valor no es una dirección de email válida.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>No se pudo encontrar el archivo.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>No se puede leer el archivo.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>El archivo es demasiado grande ({{ size }} {{ suffix }}). El tamaño máximo permitido es {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>El tipo mime del archivo no es válido ({{ type }}). Los tipos mime válidos son {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Este valor debería ser {{ limit }} o menos.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Este valor es demasiado largo. Debería tener {{ limit }} carácter o menos.|Este valor es demasiado largo. Debería tener {{ limit }} caracteres o menos.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Este valor debería ser {{ limit }} o más.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Este valor es demasiado corto. Debería tener {{ limit }} carácter o más.|Este valor es demasiado corto. Debería tener {{ limit }} caracteres o más.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Este valor no debería estar vacío.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Este valor no debería ser nulo.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Este valor debería ser nulo.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Este valor no es válido.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Este valor no es una hora válida.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Este valor no es una URL válida.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Los dos valores deberían ser iguales.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>El archivo es demasiado grande. El tamaño máximo permitido es {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>El archivo es demasiado grande.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>No se pudo subir el archivo.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Este valor debería ser un número válido.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>El archivo no es una imagen válida.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Esto no es una dirección IP válida.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Este valor no es un idioma válido.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Este valor no es una localización válida.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Este valor no es un país válido.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Este valor ya se ha utilizado.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>No se pudo determinar el tamaño de la imagen.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>La anchura de la imagen es demasiado grande ({{ width }}px). La anchura máxima permitida son {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>La anchura de la imagen es demasiado pequeña ({{ width }}px). La anchura mínima requerida son {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>La altura de la imagen es demasiado grande ({{ height }}px). La altura máxima permitida son {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>La altura de la imagen es demasiado pequeña ({{ height }}px). La altura mínima requerida son {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Este valor debería ser la contraseña actual del usuario.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Este valor debería tener exactamente {{ limit }} carácter.|Este valor debería tener exactamente {{ limit }} caracteres.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>El archivo fue sólo subido parcialmente.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Ningún archivo fue subido.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Ninguna carpeta temporal fue configurada en php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>No se pudo escribir el archivo temporal en el disco.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Una extensión de PHP hizo que la subida fallara.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Esta colección debe contener {{ limit }} elemento o más.|Esta colección debe contener {{ limit }} elementos o más.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Esta colección debe contener {{ limit }} elemento o menos.|Esta colección debe contener {{ limit }} elementos o menos.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Esta colección debe contener exactamente {{ limit }} elemento.|Esta colección debe contener exactamente {{ limit }} elementos.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Número de tarjeta inválido.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Tipo de tarjeta no soportado o número de tarjeta inválido.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Esto no es un International Bank Account Number (IBAN) válido.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Este valor no es un ISBN-10 válido.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Este valor no es un ISBN-13 válido.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Este valor no es ni un ISBN-10 válido ni un ISBN-13 válido.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Este valor no es un ISSN válido.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Este valor no es una divisa válida.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Este valor debería ser igual que {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Este valor debería ser mayor que {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Este valor debería ser mayor o igual que {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Este valor debería ser idéntico a {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Este valor debería ser menor que {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Este valor debería ser menor o igual que {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Este valor debería ser distinto de {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Este valor no debería ser idéntico a {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Zs�E#�A�ADSymfony/Component/Validator/Resources/translations/validators.de.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Dieser Wert sollte false sein.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Dieser Wert sollte true sein.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Dieser Wert sollte vom Typ {{ type }} sein.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Dieser Wert sollte leer sein.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Sie haben einen ungültigen Wert ausgewählt.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Sie müssen mindestens {{ limit }} Möglichkeit wählen.|Sie müssen mindestens {{ limit }} Möglichkeiten wählen.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Sie dürfen höchstens {{ limit }} Möglichkeit wählen.|Sie dürfen höchstens {{ limit }} Möglichkeiten wählen.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Einer oder mehrere der angegebenen Werte sind ungültig.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Die Felder {{ fields }} wurden nicht erwartet.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Die erwarteten Felder {{ fields }} fehlen.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Dieser Wert entspricht keiner gültigen Datumsangabe.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Dieser Wert entspricht keiner gültigen Datums- und Zeitangabe.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Dieser Wert ist keine gültige E-Mail-Adresse.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Die Datei wurde nicht gefunden.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Die Datei ist nicht lesbar.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Die Datei ist zu groß ({{ size }} {{ suffix }}). Die maximal zulässige Größe beträgt {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Der Dateityp ist ungültig ({{ type }}). Erlaubte Dateitypen sind {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Dieser Wert sollte kleiner oder gleich {{ limit }} sein.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Diese Zeichenkette ist zu lang. Sie sollte höchstens {{ limit }} Zeichen haben.|Diese Zeichenkette ist zu lang. Sie sollte höchstens {{ limit }} Zeichen haben.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Dieser Wert sollte größer oder gleich {{ limit }} sein.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Diese Zeichenkette ist zu kurz. Sie sollte mindestens {{ limit }} Zeichen haben.|Diese Zeichenkette ist zu kurz. Sie sollte mindestens {{ limit }} Zeichen haben.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Dieser Wert sollte nicht leer sein.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Dieser Wert sollte nicht null sein.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Dieser Wert sollte null sein.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Dieser Wert ist nicht gültig.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Dieser Wert entspricht keiner gültigen Zeitangabe.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Dieser Wert ist keine gültige URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Die beiden Werte sollten identisch sein.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Die Datei ist zu groß. Die maximal zulässige Größe beträgt {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Die Datei ist zu groß.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Die Datei konnte nicht hochgeladen werden.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Dieser Wert sollte eine gültige Zahl sein.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Diese Datei ist kein gültiges Bild.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Dies ist keine gültige IP-Adresse.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Dieser Wert entspricht keiner gültigen Sprache.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Dieser Wert entspricht keinem gültigen Gebietsschema.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Dieser Wert entspricht keinem gültigen Land.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Dieser Wert wird bereits verwendet.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Die Größe des Bildes konnte nicht ermittelt werden.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Die Bildbreite ist zu groß ({{ width }}px). Die maximal zulässige Breite beträgt {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Die Bildbreite ist zu gering ({{ width }}px). Die erwartete Mindestbreite beträgt {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Die Bildhöhe ist zu groß ({{ height }}px). Die maximal zulässige Höhe beträgt {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Die Bildhöhe ist zu gering ({{ height }}px). Die erwartete Mindesthöhe beträgt {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Dieser Wert sollte dem aktuellen Benutzerpasswort entsprechen.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Dieser Wert sollte genau {{ limit }} Zeichen lang sein.|Dieser Wert sollte genau {{ limit }} Zeichen lang sein.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Die Datei wurde nur teilweise hochgeladen.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Es wurde keine Datei hochgeladen.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Es wurde kein temporärer Ordner in der php.ini konfiguriert.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Kann die temporäre Datei nicht speichern.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Eine PHP-Erweiterung verhinderte den Upload.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Diese Sammlung sollte {{ limit }} oder mehr Elemente beinhalten.|Diese Sammlung sollte {{ limit }} oder mehr Elemente beinhalten.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Diese Sammlung sollte {{ limit }} oder weniger Elemente beinhalten.|Diese Sammlung sollte {{ limit }} oder weniger Elemente beinhalten.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Diese Sammlung sollte genau {{ limit }} Element beinhalten.|Diese Sammlung sollte genau {{ limit }} Elemente beinhalten.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Ungültige Kartennummer.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Nicht unterstützer Kartentyp oder ungültige Kartennummer.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Dieser Wert ist keine gültige IBAN-Kontonummer.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Dieser Wert entspricht keiner gültigen ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Dieser Wert entspricht keiner gültigen ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Dieser Wert ist weder eine gültige ISBN-10 noch eine gültige ISBN-13.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Dieser Wert ist keine gültige ISSN.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Dieser Wert ist keine gültige Währung.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Dieser Wert sollte gleich {{ compared_value }} sein.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Dieser Wert sollte größer als {{ compared_value }} sein.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Dieser Wert sollte größer oder gleich {{ compared_value }} sein.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Dieser Wert sollte identisch sein mit {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Dieser Wert sollte kleiner als {{ compared_value }} sein.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Dieser Wert sollte kleiner oder gleich {{ compared_value }} sein.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Dieser Wert sollte nicht {{ compared_value }} sein.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Dieser Wert sollte nicht identisch sein mit {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z=^��::DSymfony/Component/Validator/Resources/translations/validators.it.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Questo valore dovrebbe essere falso.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Questo valore dovrebbe essere vero.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Questo valore dovrebbe essere di tipo {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Questo valore dovrebbe essere vuoto.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Questo valore dovrebbe essere una delle opzioni disponibili.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Si dovrebbe selezionare almeno {{ limit }} opzione.|Si dovrebbero selezionare almeno {{ limit }} opzioni.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Si dovrebbe selezionare al massimo {{ limit }} opzione.|Si dovrebbero selezionare al massimo {{ limit }} opzioni.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Uno o più valori inseriti non sono validi.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>I campi {{ fields }} non sono validi.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>I campi {{ fields }} sono mancanti.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Questo valore non è una data valida.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Questo valore non è una data e ora valida.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Questo valore non è un indirizzo email valido.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Non è stato possibile trovare il file.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Il file non è leggibile.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Il file è troppo grande ({{ size }} {{ suffix }}). La dimensione massima consentita è {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Il mime type del file non è valido ({{ type }}). I tipi permessi sono {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Questo valore dovrebbe essere {{ limit }} o inferiore.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Questo valore è troppo lungo. Dovrebbe essere al massimo di {{ limit }} carattere.|Questo valore è troppo lungo. Dovrebbe essere al massimo di {{ limit }} caratteri.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Questo valore dovrebbe essere {{ limit }} o superiore.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Questo valore è troppo corto. Dovrebbe essere almeno di {{ limit }} carattere.|Questo valore è troppo corto. Dovrebbe essere almeno di {{ limit }} caratteri.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Questo valore non dovrebbe essere vuoto.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Questo valore non dovrebbe essere nullo.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Questo valore dovrebbe essere nullo.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Questo valore non è valido.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Questo valore non è un'ora valida.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Questo valore non è un URL valido.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>I due valori dovrebbero essere uguali.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Il file è troppo grande. La dimensione massima è {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Il file è troppo grande.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Il file non può essere caricato.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Questo valore dovrebbe essere un numero.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Questo file non è una immagine valida.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Questo valore non è un indirizzo IP valido.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Questo valore non è una lingua valida.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Questo valore non è una impostazione regionale valida.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Questo valore non è una nazione valida.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Questo valore è già stato utilizzato.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>La dimensione dell'immagine non può essere determinata.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>La larghezza dell'immagine è troppo grande ({{ width }}px). La larghezza massima è di {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>La larghezza dell'immagine è troppo piccola ({{ width }}px). La larghezza minima è di {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>L'altezza dell'immagine è troppo grande ({{ height }}px). L'altezza massima è di {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>L'altezza dell'immagine è troppo piccola ({{ height }}px). L'altezza minima è di {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Questo valore dovrebbe essere la password attuale dell'utente.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Questo valore dovrebbe contenere esattamente {{ limit }} carattere.|Questo valore dovrebbe contenere esattamente {{ limit }} caratteri.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Il file è stato caricato solo parzialmente.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Nessun file è stato caricato.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Nessuna cartella temporanea è stata configurata nel php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Impossibile scrivere il file temporaneo sul disco.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Un'estensione PHP ha causato il fallimento del caricamento.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Questa collezione dovrebbe contenere almeno {{ limit }} elemento.|Questa collezione dovrebbe contenere almeno {{ limit }} elementi.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Questa collezione dovrebbe contenere massimo {{ limit }} elemento.|Questa collezione dovrebbe contenere massimo {{ limit }} elementi.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Questa collezione dovrebbe contenere esattamente {{ limit }} elemento.|Questa collezione dovrebbe contenere esattamente {{ limit }} elementi.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Numero di carta non valido.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Tipo di carta non supportato o numero non valido.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Questo valore non è un IBAN (International Bank Account Number) valido.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Questo valore non è un codice ISBN-10 valido.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Questo valore non è un codice ISBN-13 valido.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Questo valore non è un codice ISBN-10 o ISBN-13 valido.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Questo valore non è un codice ISSN valido.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Questo valore non è una valuta valida.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z	���AADSymfony/Component/Validator/Resources/translations/validators.ca.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Aquest valor hauria de ser fals.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Aquest valor hauria de ser cert.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Aquest valor hauria de ser del tipus {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Aquest valor hauria d'estar buit.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>El valor seleccionat no és una opció vàlida.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Ha de seleccionar almenys {{ limit }} opció.|Ha de seleccionar almenys {{ limit }} opcions.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Ha de seleccionar com a màxim {{ limit }} opció.|Ha de seleccionar com a màxim {{ limit }} opcions.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Un o més dels valors facilitats són incorrectes.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>No s'esperaven els camps {{ fields }}.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Falten els camps {{ fields }}.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Aquest valor no és una data vàlida.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Aquest valor no és una data i hora vàlida.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Aquest valor no és una adreça d'email vàlida.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>No s'ha pogut trobar l'arxiu.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>No es pot llegir l'arxiu.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>L'arxiu és massa gran ({{ size }} {{ suffix }}). La grandària màxima permesa és {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>El tipus mime de l'arxiu no és vàlid ({{ type }}). Els tipus mime vàlids són {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Aquest valor hauria de ser {{ limit }} o menys.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Aquest valor és massa llarg. Hauria de tenir {{ limit }} caràcter o menys.|Aquest valor és massa llarg. Hauria de tenir {{ limit }} caràcters o menys.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Aquest valor hauria de ser {{ limit }} o més.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Aquest valor és massa curt. Hauria de tenir {{ limit }} caràcters o més.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Aquest valor no hauria d'estar buit.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Aquest valor no hauria de ser null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Aquest valor hauria de ser null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Aquest valor no és vàlid.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Aquest valor no és una hora vàlida.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Aquest valor no és una URL vàlida.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Els dos valors haurien de ser iguals.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>L'arxiu és massa gran. El tamany màxim permés és {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>L'arxiu és massa gran.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>No es pot pujar l'arxiu.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Aquest valor hauria de ser un nombre vàlid.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>L'arxiu no és una imatge vàlida.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Això no és una adreça IP vàlida.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Aquest valor no és un idioma vàlid.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Aquest valor no és una localització vàlida.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Aquest valor no és un país vàlid.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Aquest valor ja s'ha utilitzat.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>No s'ha pogut determinar la grandària de la imatge.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>L'amplària de la imatge és massa gran ({{ width }}px). L'amplària màxima permesa són {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>L'amplària de la imatge és massa petita ({{ width }}px). L'amplària mínima requerida són {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>L'altura de la imatge és massa gran ({{ height }}px). L'altura màxima permesa són {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>L'altura de la imatge és massa petita ({{ height }}px). L'altura mínima requerida són {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Aquest valor hauria de ser la contrasenya actual de l'usuari.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Aquest valor hauria de tenir exactament {{ limit }} caràcter.|Aquest valor hauria de tenir exactament {{ limit }} caràcters.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>L'arxiu va ser només pujat parcialment.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Cap arxiu va ser pujat.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Cap carpeta temporal va ser configurada en php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>No es va poder escriure l'arxiu temporal en el disc.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Una extensió de PHP va fer que la pujada fallara.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Aquesta col·lecció ha de contenir {{ limit }} element o més.|Aquesta col·lecció ha de contenir {{ limit }} elements o més.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Aquesta col·lecció ha de contenir {{ limit }} element o menys.|Aquesta col·lecció ha de contenir {{ limit }} elements o menys.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Aquesta col·lecció ha de contenir exactament {{ limit }} element.|Aquesta col·lecció ha de contenir exactament {{ limit }} elements.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Número de targeta invàlid.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Tipus de targeta no suportada o número de targeta invàlid.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Això no és un nombre de compte bancari internacional (IBAN) vàlid.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Aquest valor no és un ISBN-10 vàlid.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Aquest valor no és un ISBN-13 vàlid.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Aquest valor no és ni un ISBN-10 vàlid ni un ISBN-13 vàlid.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Aquest valor no és un ISSN vàlid.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Aquest valor no és una divisa vàlida.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Aquest valor hauria de ser igual a {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Aquest valor hauria de ser més gran a {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Aquest valor hauria de ser major o igual a {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Aquest valor hauria de ser idèntic a {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Aquest valor hauria de ser menor a {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Aquest valor hauria de ser menor o igual a {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Aquest valor no hauria de ser igual a {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Aquest valor no hauria de idèntic a {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��ZD��#"#"DSymfony/Component/Validator/Resources/translations/validators.mn.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Энэ утга буруу байх ёстой.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Энэ утга үнэн байх ёстой.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Энэ утга  {{ type }} -н төрөл байх ёстой.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Энэ утга хоосон байх ёстой.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Сонгосон утга буруу байна.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Хамгийн багадаа {{ limit }} утга сонгогдсон байх ёстой.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Хамгийн ихдээ {{ limit }} утга сонгогдох боломжтой.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Өгөгдсөн нэг эсвэл нэгээс олон утга буруу байна.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>Талбарууд {{ fields }} зөвшөөрөгдөөгүй байна.</source>
                <target>{{ fields }}.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>{{ fields }} талбарууд дутуу байна.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Энэ утга буруу date төрөл байна .</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Энэ утга буруу цаг төрөл байна.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>И-майл хаяг буруу байна.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Файл олдсонгүй.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Файл уншигдахуйц биш байна.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Файл хэтэрхий том байна ({{ size }} {{ suffix }}). Зөвшөөрөгдөх дээд хэмжээ  {{ limit }} {{ suffix }} байна.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Файлын MIME-төрөл нь буруу байна ({{ type }}). Зөвшөөрөгдөх MIME-төрлүүд {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Энэ утга  {{ limit }} юмуу эсвэл бага байна.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Энэ утга хэтэрхий урт байна. {{ limit }} тэмдэгтийн урттай юмуу эсвэл бага байна.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Энэ утга {{ limit }} юмуу эсвэл их байна.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Энэ утга хэтэрхий богино байна. {{ limit }} тэмдэгт эсвэл их байна.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Энэ утга хоосон байж болохгүй.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Энэ утга null байж болохгүй.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Энэ утга null байна.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Энэ утга буруу байна.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Энэ утга буруу цаг төрөл байна.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Энэ утга буруу URL байна .</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Хоёр утгууд ижил байх ёстой.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Файл хэтэрхий том байна. Зөвшөөрөгдөх дээд хэмжээ нь {{ limit }} {{ suffix }} байна.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Файл хэтэрхий том байна.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Файл upload хийгдсэнгүй.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Энэ утга зөвхөн тоо байна.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This value is not a valid country.</source>
                <target>Энэ утга үнэн бодит улс биш байна.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This file is not a valid image.</source>
                <target>Файл зураг биш байна.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This is not a valid IP address.</source>
                <target>IP хаяг зөв биш байна.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid language.</source>
                <target>Энэ утга үнэн зөв хэл биш байна .</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z��-tZMZMDSymfony/Component/Validator/Resources/translations/validators.ru.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Значение должно быть ложным.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Значение должно быть истинным.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Тип значения должен быть {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Значение должно быть пустым.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Выбранное Вами значение недопустимо.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Вы должны выбрать хотя бы {{ limit }} вариант.|Вы должны выбрать хотя бы {{ limit }} варианта.|Вы должны выбрать хотя бы {{ limit }} вариантов.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Вы должны выбрать не более чем {{ limit }} вариант.|Вы должны выбрать не более чем {{ limit }} варианта.|Вы должны выбрать не более чем {{ limit }} вариантов.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Одно или несколько заданных значений недопустимо.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Поля {{ fields }} не ожидались.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Поля {{ fields }} отсутствуют.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Значение не является правильной датой.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Значение даты и времени недопустимо.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Значение адреса электронной почты недопустимо.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Файл не может быть найден.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Файл не может быть прочитан.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Файл слишком большой ({{ size }} {{ suffix }}). Максимально допустимый размер {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>MIME-тип файла недопустим ({{ type }}). Допустимы MIME-типы файлов {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Значение должно быть {{ limit }} или меньше.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Значение слишком длинное. Должно быть равно {{ limit }} символу или меньше.|Значение слишком длинное. Должно быть равно {{ limit }} символам или меньше.|Значение слишком длинное. Должно быть равно {{ limit }} символам или меньше.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Значение должно быть {{ limit }} или больше.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Значение слишком короткое. Должно быть равно {{ limit }} символу или больше.|Значение слишком короткое. Должно быть равно {{ limit }} символам или больше.|Значение слишком короткое. Должно быть равно {{ limit }} символам или больше.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Значение не должно быть пустым.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Значение не должно быть null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Значение должно быть null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Значение недопустимо.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Значение времени недопустимо.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Значение не является допустимым URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Оба значения должны быть одинаковыми.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Файл слишком большой. Максимально допустимый размер {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Файл слишком большой.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Файл не может быть загружен.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Значение должно быть числом.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This value is not a valid country.</source>
                <target>Значение не является допустимой страной.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This file is not a valid image.</source>
                <target>Файл не является допустимым форматом изображения.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This is not a valid IP address.</source>
                <target>Значение не является допустимым IP адресом.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid language.</source>
                <target>Значение не является допустимым языком.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid locale.</source>
                <target>Значение не является допустимой локалью.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Это значение уже используется.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Не удалось определить размер изображения.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Ширина изображения слишком велика ({{ width }}px). Максимально допустимая ширина {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Ширина изображения слишком мала ({{ width }}px). Минимально допустимая ширина {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Высота изображения слишком велика ({{ height }}px). Максимально допустимая высота {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Высота изображения слишком мала ({{ height }}px). Минимально допустимая высота {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Значение должно быть текущим паролем пользователя.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Значение должно быть равно {{ limit }} символу.|Значение должно быть равно {{ limit }} символам.|Значение должно быть равно {{ limit }} символам.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Файл был загружен только частично.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Файл не был загружен.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Не настроена временная директория в php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Невозможно записать временный файл на диск.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Расширение PHP вызвало ошибку при загрузке.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Эта коллекция должна содержать {{ limit }} элемент или больше.|Эта коллекция должна содержать {{ limit }} элемента или больше.|Эта коллекция должна содержать {{ limit }} элементов или больше.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Эта коллекция должна содержать {{ limit }} элемент или меньше.|Эта коллекция должна содержать {{ limit }} элемента или меньше.|Эта коллекция должна содержать {{ limit }} элементов или меньше.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Эта коллекция должна содержать ровно {{ limit }} элемент.|Эта коллекция должна содержать ровно {{ limit }} элемента.|Эта коллекция должна содержать ровно {{ limit }} элементов.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Неверный номер карты.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Неподдерживаемый тип или неверный номер карты.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Значение не является допустимым международным номером банковского счета (IBAN).</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Значение имеет неверный формат ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Значение имеет неверный формат ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Значение не соответствует форматам ISBN-10 и ISBN-13.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Значение не соответствует формату ISSN.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Некорректный формат валюты.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Значение должно быть равно {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Значение должно быть больше чем {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Значение должно быть больше или равно {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Значение должно быть идентичным {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Значение должно быть меньше чем {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Значение должно быть меньше или равно {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Значение не должно быть равно {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Значение не должно быть идентичным {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z<��bKKDSymfony/Component/Validator/Resources/translations/validators.bg.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Стойността трябва да бъде лъжа (false).</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Стойността трябва да бъде истина (true).</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Стойността трябва да бъде от тип {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Стойността трябва да бъде празна.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Избраната стойност е невалидна.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Трябва да изберете поне {{ limit }} опция.|Трябва да изберете поне {{ limit }} опции.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Трябва да изберете най-много {{ limit }} опция.|Трябва да изберете най-много {{ limit }} опции.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Една или повече от зададените стойности е невалидна.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Полетата {{ fields }} не бяха очаквани.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Полетата {{ fields }} липсват.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Стойността не е валидна дата (date).</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Стойността не е валидна дата (datetime).</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Стойността не е валиден email адрес.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Файлът не беше открит.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Файлът не може да бъде прочетен.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Файлът е твърде голям ({{ size }} {{ suffix }}). Максималният размер е {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Майм типа на файла е невалиден ({{ type }}). Разрешени майм типове са {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Стойността трябва да бъде {{ limit }} или по-малко.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Стойността е твърде дълга. Трябва да съдържа най-много {{ limit }} символ.|Стойността е твърде дълга. Трябва да съдържа най-много {{ limit }} символа.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Стойността трябва да бъде {{ limit }} или повече.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Стойността е твърде кратка. Трябва да съдържа поне {{ limit }} символ.|Стойността е твърде кратка. Трябва да съдържа поне {{ limit }} символа.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Стойността не трябва да бъде празна.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Стойността не трябва да бъде null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Стойността трябва да бъде null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Стойността не е валидна.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Стойността не е валидно време (time).</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Стойността не е валиден URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Двете стойности трябва да бъдат равни.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Файлът е твърде голям. Разрешеният максимален размер е {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Файлът е твърде голям.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Файлът не може да бъде качен.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Стойността трябва да бъде валиден номер.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Файлът не е валидно изображение.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Това не е валиден IP адрес.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Стойността не е валиден език.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Стойността не е валидна локализация.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Стойността не е валидна държава.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Стойността вече е в употреба.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Размера на изображението не може да бъде определен.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Изображението е твърде широко ({{ width }}px). Широчината трябва да бъде максимум {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Изображението е с твърде малка широчина ({{ width }}px). Широчината трябва да бъде минимум {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Изображението е с твърде голяма височина ({{ height }}px). Височината трябва да бъде максимум {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Изображението е с твърде малка височина ({{ height }}px). Височина трябва да бъде минимум {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Стойността трябва да бъде текущата потребителска парола.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Стойността трябва да бъде точно {{ limit }} символ.|Стойността трябва да бъде точно {{ limit }} символа.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Файлът е качен частично.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Файлът не беше качен.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Не е посочена директория за временни файлове в php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Не може да запише временен файл на диска.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>PHP разширение предизвика прекъсване на качването.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Колекцията трябва да съдържа поне {{ limit }} елемент.|Колекцията трябва да съдържа поне {{ limit }} елемента.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Колекцията трябва да съдържа най-много {{ limit }} елемент.|Колекцията трябва да съдържа най-много {{ limit }} елемента.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Колекцията трябва да съдържа точно {{ limit }} елемент.|Колекцията трябва да съдържа точно {{ limit }} елемента.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Невалиден номер на картата.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Неподдържан тип карта или невалиден номер на картата.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Невалиден Международен номер на банкова сметка (IBAN).</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Невалиден ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Невалиден ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Невалидна стойност както за ISBN-10, така и за ISBN-13 .</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Невалиден Международен стандартен сериен номер (ISSN).</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Невалидна валута.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Стойността трябва да бъде равна на {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Стойността трябва да бъде по-голяма от {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Стойността трябва да бъде по-голяма или равна на {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Стойността трябва да бъде идентична с {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Стойността трябва да бъде по-малка {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Стойността трябва да бъде по-малка или равна на {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Стойността не трябва да бъде равна на {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Стойността не трябва да бъде идентична с {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z����A�ADSymfony/Component/Validator/Resources/translations/validators.ro.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Această valoare ar trebui să fie falsă (false).</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Această valoare ar trebui să fie adevărată (true).</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Această valoare ar trebui să fie de tipul {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Această valoare ar trebui sa fie goală.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Valoarea selectată nu este o opțiune validă.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Trebuie să selectați cel puțin {{ limit }} opțiuni.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Trebuie să selectați cel mult {{ limit }} opțiuni.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Una sau mai multe dintre valorile furnizate sunt invalide.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Câmpurile {{ fields }} nu erau așteptate.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Câmpurile {{ fields }} lipsesc.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Această valoare nu reprezintă o dată validă.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Această valoare nu reprezintă o dată și oră validă.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Această valoare nu reprezintă o adresă de e-mail validă.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Fișierul nu a putut fi găsit.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Fișierul nu poate fi citit.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Fișierul este prea mare ({{ size }} {{ suffix }}). Dimensiunea maximă permisă este {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Tipul fișierului este invalid ({{ type }}). Tipurile permise de fișiere sunt ({{ types }}).</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Această valoare ar trebui să fie cel mult {{ limit }}.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Această valoare este prea lungă. Ar trebui să aibă maxim {{ limit }} caracter.|Această valoare este prea lungă. Ar trebui să aibă maxim {{ limit }} caractere.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Această valoare ar trebui să fie cel puțin {{ limit }}.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Această valoare este prea scurtă. Ar trebui să aibă minim {{ limit }} caracter.|Această valoare este prea scurtă. Ar trebui să aibă minim {{ limit }} caractere.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Această valoare nu ar trebui să fie goală.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Această valoare nu ar trebui să fie nulă (null).</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Această valoare ar trebui să fie nulă (null).</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Această valoare nu este validă.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Această valoare nu reprezintă o oră validă.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Această valoare nu reprezintă un URL (link) valid.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Cele două valori ar trebui să fie egale.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Fișierul este prea mare. Mărimea maximă permisă este {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Fișierul este prea mare.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Fișierul nu a putut fi încărcat.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Această valoare nu reprezintă un număr valid.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Acest fișier nu este o imagine validă.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Această valoare nu este o adresă IP validă.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Această valoare nu reprezintă o limbă corectă.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Această valoare nu reprezintă un dialect (o limbă) corect.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Această valoare nu este o țară validă.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Această valoare este folosită deja.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Mărimea imaginii nu a putut fi detectată.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Lățimea imaginii este prea mare ({{ width }}px). Lățimea maximă permisă este de {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Lățimea imaginii este prea mică ({{ width }}px). Lățimea minimă permisă este de {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Înălțimea imaginii este prea mare ({{ height }}px). Înălțimea maximă permisă este de {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Înălțimea imaginii este prea mică ({{ height }}px). Înălțimea minimă permisă este de {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Această valoare trebuie să fie parola curentă a utilizatorului.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Această valoare trebuie să conțină exact {{ limit }} caracter.|Această valoare trebuie să conțină exact {{ limit }} caractere.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Fișierul a fost încărcat parțial.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Nu a fost încărcat nici un fișier.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Nu este configurat nici un director temporar in php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Nu a fost posibilă scrierea fișierului temporar pe disk.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>O extensie PHP a prevenit încărcarea cu succes a fișierului.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Această colecție trebuie să conțină cel puțin {{ limit }} elemente.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Această colecție trebuie să conțină cel mult {{ limit }} elemente.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Această colecție trebuie să conțină {{ limit }} elemente.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Numărul card invalid.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Tipul sau numărul cardului nu sunt valide.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Acesta nu este un cod IBAN (International Bank Account Number) valid.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Această valoare nu este un cod ISBN-10 valid.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Această valoare nu este un cod ISBN-13 valid.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Această valoare nu este un cod ISBN-10 sau ISBN-13 valid.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Această valoare nu este un cod ISSN valid.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Această valoare nu este o monedă validă.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Această valoare trebuie să fie egală cu {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Această valoare trebuie să fie mai mare de {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Această valoare trebuie să fie mai mare sau egală cu {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Această valoare trebuie identică cu {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Această valoare trebuie să fie mai mică de {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Această valoare trebuie să fie mai mică sau egală cu {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Această valoare nu trebuie să fie egală cu {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Această valoare nu trebuie să fie identică cu {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�ժN@@DSymfony/Component/Validator/Resources/translations/validators.nl.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Deze waarde mag niet waar zijn.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Deze waarde moet waar zijn.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Deze waarde moet van het type {{ type }} zijn.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Deze waarde moet leeg zijn.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>De geselecteerde waarde is geen geldige optie.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Selecteer ten minste {{ limit }} optie.|Selecteer ten minste {{ limit }} opties.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Selecteer maximaal {{ limit }} optie.|Selecteer maximaal {{ limit }} opties.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Eén of meer van de ingegeven waarden zijn ongeldig.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>De velden {{ fields }} werden niet verwacht.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>De velden {{ fields }} ontbreken.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Deze waarde is geen geldige datum.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Deze waarde is geen geldige datum en tijd.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Deze waarde is geen geldig e-mailadres.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Het bestand is niet gevonden.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Het bestand is niet leesbaar.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Het bestand is te groot ({{ size }} {{ suffix }}). Toegestane maximum grootte is {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Het mime type van het bestand is ongeldig ({{ type }}). Toegestane mime types zijn {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Deze waarde moet {{ limit }} of minder zijn.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Deze waarde is te lang. Hij mag maximaal {{ limit }} teken bevatten.|Deze waarde is te lang. Hij mag maximaal {{ limit }} tekens bevatten.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Deze waarde moet {{ limit }} of meer zijn.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Deze waarde is te kort. Hij moet tenminste {{ limit }} teken bevatten.|Deze waarde is te kort. Hij moet tenminste {{ limit }} tekens bevatten.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Deze waarde mag niet leeg zijn.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Deze waarde mag niet null zijn.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Deze waarde moet null zijn.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Deze waarde is ongeldig.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Deze waarde is geen geldige tijd.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Deze waarde is geen geldige URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>De twee waarden moeten gelijk zijn.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Het bestand is te groot. Toegestane maximum grootte is {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Het bestand is te groot.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Het bestand kon niet geüpload worden.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Deze waarde moet een geldig getal zijn.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Dit bestand is geen geldige afbeelding.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Dit is geen geldig IP-adres.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Deze waarde representeert geen geldige taal.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Deze waarde representeert geen geldige lokalisering.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Deze waarde representeert geen geldig land.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Deze waarde wordt al gebruikt.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>De grootte van de afbeelding kon niet bepaald worden.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>De afbeelding is te breed ({{ width }}px). De maximaal toegestane breedte is {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>De afbeelding is niet breed genoeg ({{ width }}px). De minimaal verwachte breedte is {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>De afbeelding is te hoog ({{ height }}px). De maximaal toegestane hoogte is {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>De afbeelding is niet hoog genoeg ({{ height }}px). De minimaal verwachte hoogte is {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Deze waarde moet het huidige wachtwoord van de gebruiker zijn.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Deze waarde moet exact {{ limit }} tekens lang zijn.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Het bestand is niet geheel geüpload.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Er is geen bestand geüpload.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Er is geen tijdelijke map geconfigureerd in php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Kan het tijdelijke bestand niet wegschrijven op disk.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>De upload is mislukt vanwege een PHP-extensie.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Deze collectie moet {{ limit }} element of meer bevatten.|Deze collectie moet {{ limit }} elementen of meer bevatten.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Deze collectie moet {{ limit }} element of minder bevatten.|Deze collectie moet {{ limit }} elementen of minder bevatten.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Deze collectie moet exact {{ limit }} element bevatten.|Deze collectie moet exact {{ limit }} elementen bevatten.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Ongeldig creditcardnummer.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Niet-ondersteund type creditcard of ongeldig nummer.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Dit is geen geldig internationaal bankrekeningnummer (IBAN).</target>
            </trans-unit>
             <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Deze waarde is geen geldige ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Deze waarde is geen geldige ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Deze waarde is geen geldige ISBN-10 of ISBN-13 waarde.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Deze waarde is geen geldige ISSN waarde.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Deze waarde is geen geldige valuta.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Deze waarde moet gelijk zijn aan {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Deze waarde moet groter zijn dan {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Deze waarde moet groter dan of gelijk aan {{ compared_value }} zijn.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical  to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Deze waarde moet identiek zijn aan {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Deze waarde moet minder zijn dan {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Deze waarde moet minder dan of gelijk aan {{ compared_value }} zijn.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Deze waarde mag niet gelijk zijn aan {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value }}.</source>
                <target>Deze waarde mag niet identiek zijn aan {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�%�N�=�=DSymfony/Component/Validator/Resources/translations/validators.et.xlfnu�[���<?xml version='1.0'?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Väärtus peaks olema väär.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Väärtus peaks oleme tõene.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Väärtus peaks olema {{ type }}-tüüpi.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Väärtus peaks olema tühi.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Väärtus peaks olema üks etteantud valikutest.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Valima peaks vähemalt {{ limit }} valikut.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Valima peaks mitte rohkem kui  {{ limit }} valikut.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>One or more of the given values is invalid.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Väljad {{ fields }} olid ootamatud.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Väljad {{ fields }} on puudu.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Väärtus pole korrektne kuupäev.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Väärtus pole korrektne kuupäev ja kellaeg.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Väärtus pole korrektne e-maili aadress.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Faili ei leita.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Fail ei ole loetav.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Fail on liiga suur ({{ size }} {{ suffix }}). Suurim lubatud suurus on {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Faili sisutüüp on vigane ({{ type }}). Lubatud sisutüübid on {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Väärtus peaks olema {{ limit }} või vähem.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Väärtus on liiga pikk. Pikkus peaks olema {{ limit }} tähemärki või vähem.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Väärtus peaks olema {{ limit }} või rohkem.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Väärtus on liiga lühike. Pikkus peaks  olema {{ limit }} tähemärki või rohkem.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Väärtus ei tohiks olla tühi.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Väärtus ei tohiks olla 'null'.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Väärtus peaks olema 'null'.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Väärtus on vigane.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Väärtus pole korrektne aeg.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Väärtus pole korrektne URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Väärtused peaksid olema võrdsed.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Fail on liiga suur. Maksimaalne lubatud suurus on {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Fail on liiga suur.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Faili ei saa üles laadida.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Väärtus peaks olema korrektne number.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Fail ei ole korrektne pilt.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>IP aadress pole korrektne.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Väärtus pole korrektne keel.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Väärtus pole korrektne asukohakeel.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Väärtus pole olemasolev riik.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Väärtust on juba kasutatud.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Pildi suurust polnud võimalik tuvastada.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Pilt on liiga lai ({{ width }}px). Suurim lubatud laius on {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Pilt on liiga kitsas ({{ width }}px). Vähim lubatud laius on {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Pilt on liiga pikk ({{ height }}px). Lubatud suurim pikkus on {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Pilt pole piisavalt pikk ({{ height }}px). Lubatud vähim pikkus on {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Väärtus peaks olema kasutaja kehtiv salasõna.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} characters.</source>
                <target>Väärtus peaks olema täpselt {{ limit }} tähemärk pikk.|Väärtus peaks olema täpselt {{ limit }} tähemärki pikk.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Fail ei laetud täielikult üles.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Ühtegi faili ei laetud üles.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Ühtegi ajutist kausta polnud php.ini-s seadistatud.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Ajutist faili ei saa kettale kirjutada.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>PHP laiendi tõttu ebaõnnestus faili üleslaadimine.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} elements or more.</source>
                <target>Kogumikus peaks olema vähemalt {{ limit }} element.|Kogumikus peaks olema vähemalt {{ limit }} elementi.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} elements or less.</source>
                <target>Kogumikus peaks olema ülimalt {{ limit }} element.|Kogumikus peaks olema ülimalt {{ limit }} elementi.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} elements.</source>
                <target>Kogumikus peaks olema täpselt {{ limit }} element.|Kogumikus peaks olema täpselt {{ limit }}|elementi.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Vigane kaardi number.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Kaardi tüüpi ei toetata või kaardi number on vigane.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Väärtus pole korrektne IBAN-number.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Väärtus pole korrektne ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Väärtus pole korrektne ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Väärtus pole korrektne ISBN-10 ega ISBN-13.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Väärtus pole korrektne ISSN.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Väärtus pole korrektne valuuta.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Väärtus peaks olema võrdne {{ compared_value }}-ga.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Väärtus peaks olema suurem kui {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Väärtus peaks olema suurem kui või võrduma {{ compared_value }}-ga.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Väärtus peaks olema identne väärtusega {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Väärtus peaks olema väiksem kui {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Väärtus peaks olema väiksem kui või võrduma {{ compared_value }}-ga.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Väärtus ei tohiks võrduda {{ compared_value }}-ga.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Väärtus ei tohiks olla identne väärtusega {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z
��GGDSymfony/Component/Validator/Resources/translations/validators.fa.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target state="needs-review-translation">این مقدار باید نادرست(False) باشد.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>این مقدار باید درست(True) باشد.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>این مقدار باید از نوع {{ type }} باشد.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>این فیلد باید خالی باشد.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>گزینه انتخابی معتبر نیست.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>باید حداقل {{ limit }} گزینه انتخاب کنید.|باید حداقل {{ limit }} گزینه انتخاب کنید.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>حداکثر {{ limit }} گزینه می توانید انتخاب کنید.|حداکثر {{ limit }} گزینه می توانید انتخاب کنید.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>یک یا چند مقدار نامعتبر وجود دارد.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>فیلدهای {{ fields }} اضافی هستند.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>فیلدهای {{ fields }} کم هستند.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>این مقدار یک تاریخ معتبر نیست.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>این مقدار یک تاریخ و زمان معتبر نیست.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>این یک رایانامه معتبر نیست.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>فایل پیدا نشد.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>فایل قابلیت خواندن ندارد.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>فایل بیش از اندازه بزرگ است({{ size }} {{ suffix }}). حداکثر اندازه مجاز برابر {{ limit }} {{ suffix }} است.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>این نوع فایل مجاز نیست({{ type }}). نوع های مجاز {{ types }} هستند.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>این مقدار باید کوچکتر یا مساوی {{ limit }} باشد.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>بسیار طولانی است.حداکثر تعداد حروف مجاز برابر {{ limit }} است.|بسیار طولانی است.حداکثر تعداد حروف مجاز برابر {{ limit }} است.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>این مقدار باید برابر و یا بیشتر از {{ limit }} باشد.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>بسیار کوتاه است.تعداد حروف باید حداقل {{ limit }} باشد.|بسیار کوتاه است.تعداد حروف باید حداقل {{ limit }} باشد.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>این مقدار نباید تهی باشد.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>باید مقداری داشته باشد..</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>نباید مقداری داشته باشد.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>این مقدار معتبر نیست.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>این مقدار یک زمان صحیح نیست.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>این یک URL معتبر نیست.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>دو مقدار باید برابر باشند.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>فایل بیش از اندازه بزرگ است. حداکثر اندازه مجاز برابر {{ limit }} {{ suffix }} است.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>فایل بیش از اندازه بزرگ است.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>بارگذاری فایل با شکست مواجه شد.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>این مقدار باید یک عدد معتبر باشد.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>این فایل یک تصویر نیست.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>این مقدار یک IP معتبر نیست.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>این مقدار یک زبان صحیح نیست.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>این مقدار یک محل صحیح نیست.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>این مقدار یک کشور صحیح نیست.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>این مقدار قبلا مورد استفاده قرار گرفته است.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>اندازه تصویر قابل شناسایی نیست.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>طول تصویر بسیار بزرگ است ({{ width }}px). بشینه طول مجاز {{ max_width }}px است.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>طول تصویر بسیار کوچک است ({{ width }}px). کمینه طول موردنظر {{ min_width }}px است.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>ارتفاع تصویر بسیار بزرگ است ({{ height }}px). بشینه ارتفاع مجاز {{ max_height }}px است.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>ارتفاع تصویر بسیار کوچک است ({{ height }}px). کمینه ارتفاع موردنظر {{ min_height }}px است.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>این مقدار می بایست کلمه عبور کنونی کاربر باشد.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>این مقدار می بایست دقیفا {{ limit }} کاراکتر داشته باشد.|این مقدرا می بایشت دقیقا {{ limit }} کاراکتر داشته باشد.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>فایل به صورت جزیی بارگذاری شده است.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>هیچ فایلی بارگذاری نشد.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>فولدر موقت در php.ini پیکربندی نشده است.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>فایل موقت را نمی توان در دیسک نوشت.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>اکستنشن PHP موجب شد که بارگذاری فایل با شکست مواجه شود.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>این مجموعه می بایست دارای {{ limit }} عنصر یا بیشتر باشد.|این مجموعه می بایست دارای {{ limit }} عنصر یا بیشتر باشد.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>این مجموعه می بایست دارای حداقل {{ limit }} عنصر یا کمتر باشد.|این مجموعه می بایست دارای {{ limit }} عنصر یا کمتر باشد.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>این مجموعه می بایست به طور دقیق دارا {{ limit }} عنصر باشد.|این مجموعه می بایست به طور دقیق دارای {{ limit }} قلم باشد.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>شماره کارت نامعتبر است.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>نوع کارت پشتیبانی نمی شود یا شماره کارت نامعتبر است.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>این یک شماره حساب بین المللی بانک (IBAN) درست نیست.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>این مقدار یک ISBN-10 درست نیست.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>این مقدار یک ISBN-13 درست نیست.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>این مقدار یک ISBN-10 درست یا ISBN-13 درست نیست.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>این مقدار یک ISSN درست نیست.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>این مقدار یک یکای پول درست نیست.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>این مقدار باید برابر با {{ compared_value }} باشد.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>این مقدار باید از {{ compared_value }} بیشتر باشد.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>این مقدار باید بزرگتر یا مساوی با {{ compared_value }} باشد.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>این مقدار باید با {{ compared_value_type }} {{ compared_value }} یکی باشد.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>این مقدار باید کمتر از {{ compared_value }} باشد.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>این مقدار باید کمتر یا مساوی با {{ compared_value }} باشد.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>این مقدار نباید با {{ compared_value }} برابر باشد.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>این مقدار نباید {{ compared_value_type }} {{ compared_value }} یکی باشد.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z-�L>L>DSymfony/Component/Validator/Resources/translations/validators.id.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Nilai ini harus bernilai salah.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Nilai ini harus bernilai benar.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Nilai ini harus bertipe {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Nilai ini harus kosong.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Nilai yang dipilih tidak tepat.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Anda harus memilih paling tidak {{ limit }} pilihan.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Anda harus memilih paling banyak {{ limit }} pilihan.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Satu atau lebih nilai yang diberikan tidak sah.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Kolom {{ fields }} tidak seperti yang diharapkan.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Kolom {{ fields }} hilang.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Nilai ini bukan merupakan tanggal yang sah.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Nilai ini bukan merupakan tanggal dan waktu yang sah.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Nilai ini bukan alamat email yang sah.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Berkas tidak ditemukan.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Berkas tidak bisa dibaca.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Ukuran berkas terlalu besar ({{ size }} {{ suffix }}). Ukuran maksimum yang diizinkan adalah {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Jenis berkas ({{ type }}) tidak sah. Jenis berkas yang diijinkan adalah {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Nilai ini harus {{ limit }} atau kurang.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Nilai ini terlalu panjang. Seharusnya {{ limit }} karakter atau kurang.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Nilai ini harus {{ limit }} atau lebih.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Nilai ini terlalu pendek. Seharusnya {{ limit }} karakter atau lebih.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Nilai ini tidak boleh kosong.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Nilai ini tidak boleh 'null'.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Nilai ini harus 'null'.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Nilai ini tidak sah.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Nilai ini bukan merupakan waktu yang sah.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Nilai ini bukan URL yang sah.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Isi keduanya harus sama.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Ukuran berkas terlalu besar. Ukuran maksimum yang diijinkan adalah {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Ukuran berkas terlalu besar.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Berkas tidak dapat diunggah.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Nilai ini harus angka yang sah.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Berkas ini tidak termasuk gambar.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Ini bukan alamat IP yang sah.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Nilai ini bukan bahasa yang sah.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Nilai ini bukan lokal yang sah.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Nilai ini bukan negara yang sah.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Nilai ini sudah digunakan.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Ukuran dari gambar tidak bisa dideteksi.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Lebar gambar terlalu besar ({{ width }}px). Ukuran lebar maksimum adalah {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Lebar gambar terlalu kecil ({{ width}}px). Ukuran lebar minimum yang diharapkan adalah {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Tinggi gambar terlalu besar ({{ height }}px). Ukuran tinggi maksimum adalah {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Tinggi gambar terlalu kecil ({{ height }}px). Ukuran tinggi minimum yang diharapkan adalah {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Nilai ini harus kata sandi pengguna saat ini.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Nilai ini harus memiliki tepat {{ limit }} karakter.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Berkas hanya terunggah sebagian.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Tidak ada berkas terunggah.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Direktori sementara tidak dikonfiguasi pada php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Tidak dapat menuliskan berkas sementara ke dalam media penyimpanan.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Sebuah ekstensi PHP menyebabkan kegagalan unggah.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Kumpulan ini harus memiliki {{ limit }} elemen atau lebih.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Kumpulan ini harus memiliki kurang dari {{ limit }} elemen.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Kumpulan ini harus memiliki tepat {{ limit }} elemen.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Nomor kartu tidak sah.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Jenis kartu tidak didukung atau nomor kartu tidak sah.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Ini bukan Nomor Rekening Bank Internasional (IBAN) yang sah.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Nilai ini bukan ISBN-10 yang sah.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Nilai ini bukan ISBN-13 yang sah.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Nilai ini bukan ISBN-10 maupun ISBN-13 yang sah.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Nilai ini bukan ISSN yang sah.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Nilai ini bukan mata uang yang sah.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Nilai ini seharusnya sama dengan {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Nilai ini seharusnya lebih dari {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Nilai ini seharusnya lebih dari atau sama dengan {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Nilai ini seharusnya identik dengan {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Nilai ini seharusnya kurang dari {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Nilai ini seharusnya kurang dari atau sama dengan {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Nilai ini seharusnya tidak sama dengan {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Nilai ini seharusnya tidak identik dengan {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z˺�Q1Q1DSymfony/Component/Validator/Resources/translations/validators.tr.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Bu değer olumsuz olmalıdır.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Bu değer olumlu olmalıdır.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Bu değerin tipi {{ type }} olmalıdır.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Bu değer boş olmalıdır.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Seçtiğiniz değer geçerli bir seçenek değil.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>En az {{ limit }} seçenek belirtmelisiniz.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>En çok {{ limit }} seçenek belirtmelisiniz.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Verilen değerlerden bir veya daha fazlası geçersiz.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>{{ fields }} alanları kabul edilmedi.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>{{ fields }} alanları eksik.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Bu değer doğru bir tarih biçimi değildir.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Bu değer doğru bir tarihsaat biçimi değildir.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Bu değer doğru bir e-mail adresi değildir.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Dosya bulunamadı.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Dosya okunabilir değil.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Dosya çok büyük ({{ size }} {{ suffix }}). İzin verilen en büyük dosya boyutu {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Dosyanın mime tipi geçersiz ({{ type }}). İzin verilen mime tipleri {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Bu değer {{ limit }} ve altında olmalıdır.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Bu değer çok uzun. {{ limit }} karakter veya daha az olmalıdır.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Bu değer {{ limit }} veya daha fazla olmalıdır.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Bu değer çok kısa. {{ limit }} karakter veya daha fazla olmaldır.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Bu değer boşluk olamaz.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Bu değer boş bırakılmamalıdır.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Bu değer boş bırakılmalıdır.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Bu değer geçerli değil.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Bu değer doğru bir saat değil.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Bu değer doğru bir URL değil.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>İki değer eşit olmalıdır.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Dosya çok büyük. İzin verilen en büyük dosya boyutu {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Dosya çok büyük.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Dosya yüklenemiyor.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Bu değer geçerli bir rakam olmalıdır.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Bu dosya geçerli bir resim değildir.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Bu geçerli bir IP adresi değildir.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Bu değer geçerli bir lisan değil.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Bu değer geçerli bir yer değildir.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Bu değer geçerli bir ülke değildir.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Bu değer şu anda kullanımda.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Resmin boyutu saptanamıyor.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Resmin genişliği çok büyük ({{ width }}px). İzin verilen en büyük genişlik {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Resmin genişliği çok küçük ({{ width }}px). En az {{ min_width }}px olmalıdır.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Resmin yüksekliği çok büyük ({{ height }}px). İzin verilen en büyük yükseklik {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Resmin yüksekliği çok küçük ({{ height }}px). En az {{ min_height }}px olmalıdır.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Bu değer kullanıcının şu anki şifresi olmalıdır.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Bu değer tam olarak {{ limit }} karakter olmaldır.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Dosya sadece kısmen yüklendi.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Hiçbir dosya yüklenmedi.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>php.ini içerisinde geçici dizin tanımlanmadı.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Geçici dosya diske yazılamıyor.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Bir PHP eklentisi dosyanın yüklemesini başarısız kıldı.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Bu derlem {{ limit }} veya daha çok eleman içermelidir.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Bu derlem {{ limit }} veya daha az eleman içermelidir.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Bu derlem {{ limit }} eleman içermelidir.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Geçersiz kart numarası.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Desteklenmeyen kart tipi veya geçersiz kart numarası.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z	�)�B�BDSymfony/Component/Validator/Resources/translations/validators.cs.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Tato hodnota musí být nepravdivá (false).</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Tato hodnota musí být pravdivá (true).</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Tato hodnota musí být typu {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Tato hodnota musí být prázdná.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Vybraná hodnota není platnou možností.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Musí být vybrána nejméně {{ limit }} možnost.|Musí být vybrány nejméně {{ limit }} možnosti.|Musí být vybráno nejméně {{ limit }} možností.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Musí být vybrána maximálně {{ limit }} možnost.|Musí být vybrány maximálně {{ limit }} možnosti.|Musí být vybráno maximálně {{ limit }} možností.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Některé z uvedených hodnot jsou neplatné.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Neočekávaná pole {{ fields }}.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Chybí následující pole {{ fields }}.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Tato hodnota není platné datum.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Tato hodnota není platné datum s časovým údajem.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Tato hodnota není platná e-mailová adresa.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Soubor nebyl nalezen.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Soubor je nečitelný.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Soubor je příliš velký ({{ size }} {{ suffix }}). Maximální povolená velikost souboru je {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Neplatný mime typ souboru ({{ type }}). Povolené mime typy souborů jsou {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Tato hodnota musí být {{ limit }} nebo méně.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Tato hodnota je příliš dlouhá. Musí obsahovat maximálně {{ limit }} znak.|Tato hodnota je příliš dlouhá. Musí obsahovat maximálně {{ limit }} znaky.|Tato hodnota je příliš dlouhá. Musí obsahovat maximálně {{ limit }} znaků.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Tato hodnota musí být {{ limit }} nebo více.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Tato hodnota je příliš krátká. Musí obsahovat minimálně {{ limit }} znak.|Tato hodnota je příliš krátká. Musí obsahovat minimálně {{ limit }} znaky.|Tato hodnota je příliš krátká. Musí obsahovat minimálně {{ limit }} znaků.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Tato hodnota nesmí být prázdná.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Tato hodnota nesmí být prázdná.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Tato hodnota musí být prázdná.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Tato hodnota není platná.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Tato hodnota není platný časový údaj.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Tato hodnota není platná URL adresa.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Tyto dvě hodnoty musí být stejné.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Soubor je příliš velký. Maximální povolená velikost souboru je {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Soubor je příliš velký.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Soubor se nepodařilo nahrát.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Tato hodnota musí být číslo.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Tento soubor není obrázek.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Toto není platná IP adresa.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Tento jazyk neexistuje.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Tato lokalizace neexistuje.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Tato země neexistuje.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Tato hodnota je již používána.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Nepodařily se zjistit rozměry obrázku.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Obrázek je příliš široký ({{ width }}px). Maximální povolená šířka obrázku je {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Obrázek je příliš úzký ({{ width }}px). Minimální šířka musí být {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Obrázek je příliš vysoký ({{ height }}px). Maximální povolená výška obrázku je {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Obrázek je příliš nízký ({{ height }}px). Minimální výška obrázku musí být {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Tato hodnota musí být aktuální heslo uživatele.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Tato hodnota musí mít přesně {{ limit }} znak.|Tato hodnota musí mít přesně {{ limit }} znaky.|Tato hodnota musí mít přesně {{ limit }} znaků.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Byla nahrána jen část souboru.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Žádný soubor nebyl nahrán.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>V php.ini není nastavena cesta k adresáři pro dočasné soubory.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Dočasný soubor se nepodařilo zapsat na disk.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Rozšíření PHP zabránilo nahrání souboru.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Tato kolekce musí obsahovat minimálně {{ limit }} prvek.|Tato kolekce musí obsahovat minimálně {{ limit }} prvky.|Tato kolekce musí obsahovat minimálně {{ limit }} prvků.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Tato kolekce musí obsahovat maximálně {{ limit }} prvek.|Tato kolekce musí obsahovat maximálně {{ limit }} prvky.|Tato kolekce musí obsahovat maximálně {{ limit }} prvků.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Tato kolekce musí obsahovat přesně {{ limit }} prvek.|Tato kolekce musí obsahovat přesně {{ limit }} prvky.|Tato kolekce musí obsahovat přesně {{ limit }} prvků.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Neplatné číslo karty.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Nepodporovaný typ karty nebo neplatné číslo karty.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Toto je neplatný IBAN.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Tato hodnota není platné ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Tato hodnota není platné ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Tato hodnota není platné ISBN-10 ani ISBN-13.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Tato hodnota není platné ISSN.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Tato měna neexistuje.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Tato hodnota musí být rovna {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Tato hodnota musí být větší než {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Tato hodnota musí být větší nebo rovna {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Tato hodnota musí být typu {{ compared_value_type }} a zároveň musí být rovna {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Tato hodnota musí být menší než {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Tato hodnota musí být menší nebo rovna {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Tato hodnota nesmí být rovna {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Tato hodnota nesmí být typu {{ compared_value_type }} a zároveň nesmí být rovna {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�6��%=%=GSymfony/Component/Validator/Resources/translations/validators.zh_CN.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>该变量的值应为 false 。</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>该变量的值应为 true 。</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>该变量的类型应为 {{ type }} 。</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>该变量值应为空。</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>选定变量的值不是有效的选项。</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>您至少要选择 {{ limit }} 个选项。</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>您最多能选择 {{ limit }} 个选项。</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>一个或者多个给定的值无效。</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>非预期字段 {{ fields }} 。</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>遗漏字段 {{ fields }} 。</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>该值不是一个有效的日期(date)。</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>该值不是一个有效的日期时间(datetime)。</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>该值不是一个有效的邮件地址。</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>文件未找到。</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>文件不可读。</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>文件太大 ({{ size }} {{ suffix }})。文件大小不可以超过 {{ limit }} {{ suffix }} 。</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>无效的文件类型 ({{ type }}) 。允许的文件类型有 {{ types }} 。</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>这个变量的值应该小于或等于 {{ limit }}。</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>字符串太长,长度不可超过 {{ limit }} 个字符。</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>该变量的值应该大于或等于 {{ limit }}。</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>字符串太短,长度不可少于 {{ limit }} 个字符。</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>该变量不应为空。</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>该变量不应为 null 。</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>该变量应为空 null 。</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>该变量值无效 。</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>该值不是一个有效的时间。</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>该值不是一个有效的 URL 。</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>这两个变量的值应该相等。</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>文件太大,文件大小不可以超过 {{ limit }} {{ suffix }}。 </target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>文件太大。</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>无法上传此文件。</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>该值应该为有效的数字。</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This value is not a valid country.</source>
                <target>该值不是有效的国家名。</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This file is not a valid image.</source>
                <target>该文件不是有效的图片。</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This is not a valid IP address.</source>
                <target>该值不是有效的IP地址。</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid language.</source>
                <target>该值不是有效的语言名。</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid locale.</source>
                <target>该值不是有效的区域值(locale)。</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>该值已经被使用。</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>不能解析图片大小。</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>图片太宽 ({{ width }}px),最大宽度为 {{ max_width }}px 。</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>图片宽度不够 ({{ width }}px),最小宽度为 {{ min_width }}px 。</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>图片太高 ({{ height }}px),最大高度为 {{ max_height }}px 。</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>图片高度不够 ({{ height }}px),最小高度为 {{ min_height }}px 。</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>该变量的值应为用户当前的密码。</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>该变量应为 {{ limit }} 个字符。</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>该文件的上传不完整。</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>没有上传任何文件。</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>php.ini 里没有配置临时文件目录。</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>临时文件写入磁盘失败。</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>某个 PHP 扩展造成上传失败。</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>该集合最少应包含 {{ limit }} 个元素。</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>该集合最多包含 {{ limit }} 个元素。</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>该集合应包含 {{ limit }} 个元素 element 。</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>无效的信用卡号。</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>不支持的信用卡类型或无效的信用卡号。</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>该值不是有效的国际银行帐号(IBAN)。</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>该值不是有效的10位国际标准书号(ISBN-10)。</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>该值不是有效的13位国际标准书号(ISBN-13)。</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>该值不是有效的国际标准书号(ISBN-10 或 ISBN-13)。</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>该值不是有效的国际标准期刊号(ISSN)。</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>该值不是有效的货币名(currency)。</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>该值应等于 {{ compared_value }} 。</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>该值应大于 {{ compared_value }} 。</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>该值应大于或等于 {{ compared_value }} 。</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>该值应与 {{ compared_value_type }} {{ compared_value }} 相同。</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>该值应小于 {{ compared_value }} 。</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>该值应小于或等于 {{ compared_value }} 。</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>该值不应先等于 {{ compared_value }} 。</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>该值不应与 {{ compared_value_type }} {{ compared_value }} 相同。</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�PhBhBDSymfony/Component/Validator/Resources/translations/validators.lt.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Reikšmė turi būti neigiama.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Reikšmė turi būti teigiama.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Šios reikšmės tipas turi būti {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Ši reikšmė turi būti tuščia.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Neteisingas pasirinkimas.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Turite pasirinkti bent {{ limit }} variantą.|Turite pasirinkti bent {{ limit }} variantus.|Turite pasirinkti bent {{ limit }} variantų.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Turite pasirinkti ne daugiau kaip {{ limit }} variantą.|Turite pasirinkti ne daugiau kaip {{ limit }} variantus.|Turite pasirinkti ne daugiau kaip {{ limit }} variantų.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Viena ar daugiau įvestų reikšmių yra netinkamos.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Laukai {{ fields }} yra nenumatyti.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Trūkstami laukai {{ fields }}.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Ši reikšmė nėra data.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Ši reikšmė nera data ir laikas.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Ši reikšmė nėra tinkamas el. pašto adresas.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Byla nerasta.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Negalima nuskaityti bylos.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Byla yra per didelė ({{ size }} {{ suffix }}). Maksimalus dydis {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Netinkamas bylos tipas (mime type) ({{ type }}). Galimi bylų tipai {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Reikšmė turi būti {{ limit }} arba mažiau.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Per didelis simbolių skaičius. Turi susidaryti iš {{ limit }} arba mažiau simbolių.|Per didelis simbolių skaičius. Turi susidaryti iš {{ limit }} arba mažiau simbolių.|Per didelis simbolių skaičius. Turi susidaryti iš {{ limit }} arba mažiau simbolių.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Reikšmė turi būti {{ limit }} arba daugiau.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Per mažas simbolių skaičius. Turi susidaryti iš {{ limit }} arba daugiau simbolių.|Per mažas simbolių skaičius. Turi susidaryti iš {{ limit }} arba daugiau simbolių.|Per mažas simbolių skaičius. Turi susidaryti iš {{ limit }} arba daugiau simbolių.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Ši reikšmė negali būti tuščia.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Ši reikšmė negali būti null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Ši reikšmė turi būti null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Netinkama reikšmė.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Ši reikšmė nėra laikas.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Ši reikšmė nėra tinkamas interneto adresas.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Abi reikšmės turi būti identiškos.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Byla yra per didelė. Maksimalus dydis yra {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Byla per didelė.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Byla negali būti įkelta.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Ši reikšmė turi būti skaičius.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This value is not a valid country.</source>
                <target>Ši reikšmė nėra tinkama šalis.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This file is not a valid image.</source>
                <target>Byla nėra paveikslėlis.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This is not a valid IP address.</source>
                <target>Ši reikšmė nėra tinkamas IP adresas.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid language.</source>
                <target>Ši reikšmė nėra tinkama kalba.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid locale.</source>
                <target>Ši reikšmė nėra tinkama lokalė.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Ši reikšmė jau yra naudojama.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Nepavyko nustatyti nuotraukos dydžio.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Nuotraukos plotis per didelis ({{ width }}px). Maksimalus leidžiamas plotis yra {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Nuotraukos plotis per mažas ({{ width }}px). Minimalus leidžiamas plotis yra {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Nuotraukos aukštis per didelis ({{ height }}px). Maksimalus leidžiamas aukštis yra {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Nuotraukos aukštis per mažas ({{ height }}px). Minimalus leidžiamas aukštis yra {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Ši reikšmė turi sutapti su dabartiniu naudotojo slaptažodžiu.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Ši reikšmė turi turėti lygiai {{ limit }} simbolį.|Ši reikšmė turi turėti lygiai {{ limit }} simbolius.|Ši reikšmė turi turėti lygiai {{ limit }} simbolių.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Failas buvo tik dalinai įkeltas.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Nebuvo įkelta jokių failų.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Nėra sukonfiguruoto jokio laikino katalogo php.ini faile.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Nepavyko išsaugoti laikino failo.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>PHP plėtinys sutrukdė failo įkėlimą ir jis nepavyko.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Sąraše turi būti {{ limit }} arba daugiau įrašų.|Sąraše turi būti {{ limit }} arba daugiau įrašų.|Sąraše turi būti {{ limit }} arba daugiau įrašų.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Sąraše turi būti {{ limit }} arba mažiau įrašų.|Sąraše turi būti {{ limit }} arba mažiau įrašų.|Sąraše turi būti {{ limit }} arba mažiau įrašų.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Sąraše turi būti lygiai {{ limit }} įrašas.|Sąraše turi būti lygiai {{ limit }} įrašai.|Sąraše turi būti lygiai {{ limit }} įrašų.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Klaidingas kortelės numeris.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Kortelės tipas nepalaikomas arba klaidingas kortelės numeris.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Ši reišmė neatitinka tarptautinio banko sąskaitos numerio formato (IBAN).</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Ši reikšmė neatitinka ISBN-10 formato.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Ši reikšmė neatitinka ISBN-13 formato.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Ši reikšmė neatitinka nei ISBN-10, nei ISBN-13 formato.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Ši reišmė neatitinka ISSN formato.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Netinkamas valiutos formatas.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Ši reikšmė turi būti lygi {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Ši reikšmė turi būti didesnė už {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Ši reikšmė turi būti didesnė už arba lygi {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Ši reikšmė turi būti identiška {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Ši reikšmė turi būti mažesnė už {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Ši reikšmė turi būti mažesnė už arba lygi {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Ši reikšmė neturi būti lygi {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Ši reikšmė neturi būti identiška {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z���+BBDSymfony/Component/Validator/Resources/translations/validators.fr.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Cette valeur doit être fausse.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Cette valeur doit être vraie.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Cette valeur doit être de type {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Cette valeur doit être vide.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Cette valeur doit être l'un des choix proposés.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Vous devez sélectionner au moins {{ limit }} choix.|Vous devez sélectionner au moins {{ limit }} choix.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Vous devez sélectionner au maximum {{ limit }} choix.|Vous devez sélectionner au maximum {{ limit }} choix.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Une ou plusieurs des valeurs soumises sont invalides.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Les champs {{ fields }} n'ont pas été prévus.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Les champs {{ fields }} sont manquants.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Cette valeur n'est pas une date valide.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Cette valeur n'est pas une date valide.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Cette valeur n'est pas une adresse email valide.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Le fichier n'a pas été trouvé.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Le fichier n'est pas lisible.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Le fichier est trop volumineux ({{ size }} {{ suffix }}). Sa taille ne doit pas dépasser {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Le type du fichier est invalide ({{ type }}). Les types autorisés sont {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Cette valeur doit être inférieure ou égale à {{ limit }}.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Cette chaine est trop longue. Elle doit avoir au maximum {{ limit }} caractère.|Cette chaine est trop longue. Elle doit avoir au maximum {{ limit }} caractères.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Cette valeur doit être supérieure ou égale à {{ limit }}.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Cette chaine est trop courte. Elle doit avoir au minimum {{ limit }} caractère.|Cette chaine est trop courte. Elle doit avoir au minimum {{ limit }} caractères.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Cette valeur ne doit pas être vide.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Cette valeur ne doit pas être nulle.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Cette valeur doit être nulle.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Cette valeur n'est pas valide.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Cette valeur n'est pas une heure valide.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Cette valeur n'est pas une URL valide.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Les deux valeurs doivent être identiques.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Le fichier est trop volumineux. Sa taille ne doit pas dépasser {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Le fichier est trop volumineux.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Le téléchargement de ce fichier est impossible.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Cette valeur doit être un nombre.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Ce fichier n'est pas une image valide.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Cette adresse IP n'est pas valide.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Cette langue n'est pas valide.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Ce paramètre régional n'est pas valide.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Ce pays n'est pas valide.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Cette valeur est déjà utilisée.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>La taille de l'image n'a pas pu être détectée.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>La largeur de l'image est trop grande ({{ width }}px). La largeur maximale autorisée est de {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>La largeur de l'image est trop petite ({{ width }}px). La largeur minimale attendue est de {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>La hauteur de l'image est trop grande ({{ height }}px). La hauteur maximale autorisée est de {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>La hauteur de l'image est trop petite ({{ height }}px). La hauteur minimale attendue est de {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Cette valeur doit être le mot de passe actuel de l'utilisateur.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Cette chaine doit avoir exactement {{ limit }} caractère.|Cette chaine doit avoir exactement {{ limit }} caractères.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Le fichier a été partiellement transféré.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Aucun fichier n'a été transféré.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Aucun répertoire temporaire n'a été configuré dans le php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Impossible d'écrire le fichier temporaire sur le disque.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Une extension PHP a empêché le transfert du fichier.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Cette collection doit contenir {{ limit }} élément ou plus.|Cette collection doit contenir {{ limit }} éléments ou plus.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Cette collection doit contenir {{ limit }} élément ou moins.|Cette collection doit contenir {{ limit }} éléments ou moins.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Cette collection doit contenir exactement {{ limit }} élément.|Cette collection doit contenir exactement {{ limit }} éléments.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Numéro de carte invalide.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Type de carte non supporté ou numéro invalide.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Le numéro IBAN (International Bank Account Number) saisi n'est pas valide.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Cette valeur n'est pas un code ISBN-10 valide.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Cette valeur n'est pas un code ISBN-13 valide.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Cette valeur n'est ni un code ISBN-10, ni un code ISBN-13 valide.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Cette valeur n'est pas un code ISSN valide.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Cette valeur n'est pas une devise valide.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Cette valeur doit être égale à {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Cette valeur doit être supérieure à {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Cette valeur doit être supérieure ou égale à {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Cette valeur doit être identique à {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Cette valeur doit être inférieure à {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Cette valeur doit être inférieure ou égale à {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Cette valeur ne doit pas être égale à {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Cette valeur ne doit pas être identique à {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z(��=A=ADSymfony/Component/Validator/Resources/translations/validators.gl.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Este valor debería ser falso.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Este valor debería ser verdadeiro.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Este valor debería ser de tipo {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Este valor debería estar baleiro.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>O valor seleccionado non é unha opción válida.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Debe seleccionar polo menos {{ limit }} opción.|Debe seleccionar polo menos {{ limit }} opcions.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Debe seleccionar como máximo {{ limit }} opción.|Debe seleccionar como máximo {{ limit }} opcions.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Un ou máis dos valores indicados non son válidos.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Non se esperaban os campos {{ fields }}.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Faltan os campos {{ fields }}.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Este valor non é unha data válida.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Este valor non é unha data e hora válidas.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Este valor non é unha dirección de correo electrónico válida.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Non se puido atopar o arquivo.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>O arquivo non se pode ler.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>O arquivo é demasiado grande ({{ size }} {{ suffix }}). O tamaño máximo permitido é {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>O tipo mime do arquivo non é válido ({{ type }}). Os tipos mime válidos son {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Este valor debería ser {{ limit }} ou menos.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Este valor é demasiado longo. Debería ter {{ limit }} carácter ou menos.|Este valor é demasiado longo. Debería ter {{ limit }} caracteres ou menos.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Este valor debería ser {{ limit }} ou máis.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Este valor é demasiado curto. Debería ter {{ limit }} carácter ou máis.|Este valor é demasiado corto. Debería ter {{ limit }} caracteres ou máis.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Este valor non debería estar baleiro.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Este valor non debería ser null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Este valor debería ser null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Este valor non é válido.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Este valor non é unha hora válida.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Este valor non é unha URL válida.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Os dous valores deberían ser iguais.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>O arquivo é demasiado grande. O tamaño máximo permitido é {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>O arquivo é demasiado grande.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>No se puido cargar o arquivo.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Este valor debería ser un número válido.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>O arquivo non é unha imaxe válida.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Isto non é unha dirección IP válida.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Este valor non é un idioma válido.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Este valor non é unha localización válida.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Este valor non é un país válido.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Este valor xa está a ser empregado.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Non se puido determinar o tamaño da imaxe.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>A largura da imaxe é demasiado grande ({{ width }}px). A largura máxima permitida son {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>A largura da imaxe é demasiado pequena ({{ width }}px). A largura mínima requerida son {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>A altura da imaxe é demasiado grande ({{ height }}px). A altura máxima permitida son {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>A altura da imaxe é demasiado pequena ({{ height }}px). A altura mínima requerida son {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Este valor debería ser a contrasinal actual do usuario.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Este valor debería ter exactamente {{ limit }} carácter.|Este valor debería ter exactamente {{ limit }} caracteres.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>O arquivo foi só subido parcialmente.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Non se subiu ningún arquivo.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Ningunha carpeta temporal foi configurada en php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Non se puido escribir o arquivo temporal no disco.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Unha extensión de PHP provocou que a subida fallara.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Esta colección debe conter {{ limit }} elemento ou máis.|Esta colección debe conter {{ limit }} elementos ou máis.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Esta colección debe conter {{ limit }} elemento ou menos.|Esta colección debe conter {{ limit }} elementos ou menos.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Esta colección debe conter exactamente {{ limit }} elemento.|Esta colección debe conter exactamente {{ limit }} elementos.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Número de tarxeta non válido.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Tipo de tarxeta non soportado ou número de tarxeta non válido.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Este valor non é un International Bank Account Number (IBAN) válido.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Este valor non é un ISBN-10 válido.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Este valor non é un ISBN-13 válido.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Este valor non é nin un ISBN-10 válido nin un ISBN-13 válido.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Este valor non é un ISSN válido.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Este valor non é unha moeda válida.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Este valor debería ser igual a {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Este valor debería ser maior que {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Este valor debería ser maior ou igual que {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Este valor debería ser identico a {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Este valor debería ser menor que {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Este valor debería ser menor ou igual que {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Este valor non debería ser igual a {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Este valor non debería ser identico a {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z���wX@X@DSymfony/Component/Validator/Resources/translations/validators.hr.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Ova vrijednost treba biti netočna (false).</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Ova vrijednost treba biti točna (true).</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Ova vrijednost treba biti tipa {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Ova vrijednost treba biti prazna.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Ova vrijednost treba biti jedna od ponuđenih.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Izaberite barem {{ limit }} mogućnosti.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Izaberite najviše {{ limit }} mogućnosti.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Jedna ili više danih vrijednosti nije ispravna.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Polja {{ fields }} nisu bila očekivana.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Polja {{ fields }} nedostaju.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Ova vrijednost nije ispravan datum.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Ova vrijednost nije ispravan datum-vrijeme.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Ova vrijednost nije ispravna e-mail adresa.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Datoteka ne može biti pronađena.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Datoteka nije čitljiva.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Datoteka je prevelika ({{ size }} {{ suffix }}). Najveća dozvoljena veličina je {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Mime tip datoteke nije ispravan ({{ type }}). Dozvoljeni mime tipovi su {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Ova vrijednost treba biti {{ limit }} ili manje.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Ova vrijednost je predugačka. Treba imati {{ limit }} znakova ili manje.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Ova vrijednost treba biti {{ limit }} ili više.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Ova vrijednost je prekratka. Treba imati {{ limit }} znakova ili više.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Ova vrijednost ne smije biti prazna.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Ova vrijednost ne smije biti null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Ova vrijednost treba biti null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Ova vrijednost nije ispravna.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Ova vrijednost nije ispravno vrijeme.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Ova vrijednost nije ispravan URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Obje vrijednosti trebaju biti jednake.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Ova datoteka je prevelika. Najveća dozvoljena veličina je {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Ova datoteka je prevelika.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Ova datoteka ne može biti prenesena.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Ova vrijednost treba biti ispravan broj.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Ova datoteka nije ispravna slika.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Ovo nije ispravna IP adresa.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Ova vrijednost nije ispravan jezik.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Ova vrijednost nije ispravana regionalna oznaka.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Ova vrijednost nije ispravna zemlja.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Ova vrijednost je već iskorištena.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Veličina slike se ne može odrediti.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Širina slike je prevelika ({{ width }}px). Najveća dozvoljena širina je {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Širina slike je premala ({{ width }}px). Najmanja dozvoljena širina je {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Visina slike je prevelika ({{ height }}px). Najveća dozvoljena visina je {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Visina slike je premala ({{ height }}px). Najmanja dozvoljena visina je {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Ova vrijednost treba biti trenutna korisnička lozinka.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Ova vrijednost treba imati točno {{ limit }} znakova.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Datoteka je samo djelomično prenesena.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Niti jedna datoteka nije prenesena.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>U php.ini datoteci nije konfiguriran privremeni folder.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Ne mogu zapisati privremenu datoteku na disk.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Prijenos datoteke nije uspio zbog PHP ekstenzije.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Ova kolekcija treba sadržavati {{ limit }} ili više elemenata.|Ova kolekcija treba sadržavati {{ limit }} ili više elemenata.|Ova kolekcija treba sadržavati {{ limit }} ili više elemenata.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Ova kolekcija treba sadržavati {{ limit }} ili manje elemenata.|Ova kolekcija treba sadržavati {{ limit }} ili manje elemenata.|Ova kolekcija treba sadržavati {{ limit }} ili manje elemenata.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Ova kolekcija treba sadržavati točno {{ limit }} element.|Ova kolekcija treba sadržavati točno {{ limit }} elementa.|Ova kolekcija treba sadržavati točno {{ limit }} elemenata.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Neispravan broj kartice.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Neispravan broj kartice ili tip kartice nije podržan.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Ova vrijednost nije ispravan međunarodni broj bankovnog računa (IBAN).</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Ova vrijednost nije ispravan ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Ova vrijednost nije ispravan ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Ova vrijednost nije ispravan ISBN-10 niti ISBN-13.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Ova vrijednost nije ispravan ISSN.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Ova vrijednost nije ispravna valuta.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Ova vrijednost bi trebala biti jednaka {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Ova vrijednost bi trebala biti veća od {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Ova vrijednost bi trebala biti veća ili jednaka od {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Ova vrijednost bi trebala biti {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Ova vrijednost bi trebala biti manja od {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Ova vrijednost bi trebala biti manja ili jednaka {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Ova vrijednost ne bi trebala biti {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Ova vrijednost ne bi trebala biti {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��ZY�.3�5�5DSymfony/Component/Validator/Resources/translations/validators.sq.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Kjo vlerë duhet të jetë e pavërtetë (false).</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Kjo vlerë duhet të jetë e vërtetë (true).</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Kjo vlerë duhet të jetë e llojit {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Kjo vlerë duhet të jetë e zbrazët.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Vlera që keni zgjedhur nuk është alternativë e vlefshme.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Duhet të zgjedhni së paku {{ limit }} alternativa.|Duhet të zgjedhni së paku {{ limit }} alternativa.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Duhet të zgjedhni më së shumti {{ limit }} alternativa.|Duhet të zgjedhni më së shumti {{ limit }} alternativa.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Një apo më shumë nga vlerat e dhëna nuk janë të sakta.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Fushat {{ fields }} nuk ishin të pritura.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Fushat {{ fields }} mungojnë.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Kjo vlerë nuk është datë e vlefshme.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Kjo vlerë nuk është datë-kohë e vlefshme.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Kjo vlerë nuk është e-mail adresë e vlefshme.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>File nuk mund të gjindej.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>File nuk është i lexueshëm.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>File është shumë i madh ({{ size }} {{ suffix }}). Madhësia më e madhe e lejuar është {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Lloji mime i files nuk është i vlefshëm ({{ type }}). Llojet mime të lejuara janë {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Kjo vlerë duhet të jetë {{ limit }} ose më pak.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Kjo vlerë është shumë e gjatë. Duhet t'i ketë {{ limit }} ose më pak karaktere.|Kjo vlerë është shumë e gjatë. Duhet t'i ketë {{ limit }} ose më pak karaktere.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Kjo vlerë duhet të jetë {{ limit }} ose më shumë.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Kjo vlerë është shumë e shkurtër. Duhet t'i ketë {{ limit }} ose më shumë karaktere.|Kjo vlerë është shumë e shkurtër. Duhet t'i ketë {{ limit }} ose më shumë karaktere.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Kjo vlerë nuk duhet të jetë e zbrazët.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Kjo vlerë nuk duhet të jetë null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Kjo vlerë duhet të jetë null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Kjo vlerë nuk është e vlefshme.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Kjo vlerë nuk është kohë e vlefshme.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Kjo vlerë nuk është URL e vlefshme.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Këto dy vlera duhet të jenë të barabarta.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Ky file është shumë i madh. Madhësia maksimale e lejuar është {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Ky file është shumë i madh.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Ky file nuk mund të ngarkohet.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Kjo vlerë duhet të jetë numër i vlefshëm.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Ky file nuk është imazh i vlefshëm.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Kjo vlerë nuk është IP adresë e vlefshme.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Kjo vlerë nuk është gjuhë e vlefshme.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Kjo vlerë nuk është përcaktim rajonal i vlefshëm.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Kjo vlerë nuk është shtet i vlefshëm.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Kjo vlerë është tashmë në përdorim.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Madhësia e këtij imazhi nuk mund të zbulohet.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Gjerësia e imazhit është shumë e madhe ({{ width }}px). Gjerësia maksimale e lejuar është {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Gjerësia e imazhit është shumë e vogël ({{ width }}px). Gjerësia minimale e pritur është {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Gjatësia e imazhit është shumë e madhe ({{ height }}px). Gjatësia maksimale e lejuar është {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Gjatësia e imazhit është shumë e vogël ({{ height }}px). Gjatësia minimale e pritur është {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Kjo vlerë duhet të jetë fjalëkalimi aktual i përdoruesit.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Kjo vlerë duhet të ketë saktësisht {{ limit }} karaktere.|Kjo vlerë duhet të ketë saktësisht {{ limit }} karaktere.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Ky file është ngarkuar pjesërisht.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Nuk është ngarkuar ndonjë file.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Asnjë folder i përkohshëm nuk është konfiguruar në php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Nuk mund të shkruhet file i përkohshëm në disk.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Një ekstenzion i PHP-së bëri të dështojë ngarkimi i files.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Ky kolekcion duhet të përmbajë {{ limit }} ose më shumë elemente.|Ky kolekcion duhet të përmbajë {{ limit }} ose më shumë elemente.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Ky kolekcion duhet të përmbajë {{ limit }} ose më shumë elemente.|Ky kolekcion duhet të përmbajë {{ limit }} ose më shumë elemente.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Ky kolekcion duhet të përmbajë saktësisht {{ limit }} elemente.|Ky kolekcion duhet të përmbajë saktësisht {{ limit }} elemente.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Numër kartele i pavlefshëm.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Lloj kartele i pambështetur ose numër kartele i pavlefshëm.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z(�eeDSymfony/Component/Validator/Resources/translations/validators.nb.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Verdien skal være falsk.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Verdien skal være sann.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Verdien skal være av typen {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Verdien skal være blank.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Verdien skal være en av de gitte valg.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Du skal velge minst {{ limit }} valg.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Du kan maks velge {{ limit }} valg.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>En eller flere av de oppgitte verdier er ugyldige.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Feltene {{ fields }} var ikke forventet.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Feltene {{ fields }} mangler.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Verdien er ikke en gyldig dato.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Verdien er ikke en gyldig dato og tid.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Verdien er ikke en gyldig e-mail adresse.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Filen kunne ikke finnes.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Filen kan ikke leses.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Filen er for stor ({{ size }} {{ suffix }}). Tilatte maksimale størrelse {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Mimetypen av filen er ugyldig ({{ type }}). Tilatte mimetyper er {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Verdien skal være {{ limit }} eller mindre.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Verdien er for lang. Den skal ha {{ limit }} bokstaver eller mindre.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Verdien skal være {{ limit }} eller mer.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Verdien er for kort. Den skal ha {{ limit }} tegn eller flere.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Verdien må ikke være blank.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Verdien må ikke være tom (null).</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Verdien skal være tom (null).</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Verdien er ikke gyldig.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Verdien er ikke en gyldig tid.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Verdien er ikke en gyldig URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>De to verdier skal være ens.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Filen er for stor. Den maksimale størrelse er {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Filen er for stor.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Filen kunne ikke lastes opp.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Denne verdi skal være et gyldig tall.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Denne filen er ikke et gyldig bilde.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Dette er ikke en gyldig IP adresse.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Denne verdi er ikke et gyldig språk.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Denne verdi er ikke en gyldig lokalitet.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Denne verdi er ikke et gyldig land.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z���t�A�ADSymfony/Component/Validator/Resources/translations/validators.eu.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Balio hau faltsua izan beharko litzateke.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Balio hau egia izan beharko litzateke.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Balio hau {{ type }} motakoa izan beharko litzateke.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Balio hau hutsik egon beharko litzateke.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Hautatu duzun balioa ez da aukera egoki bat.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Gutxienez aukera {{ limit }} hautatu behar duzu.|Gutxienez {{ limit }} aukera hautatu behar dituzu.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Gehienez aukera {{ limit }} hautatu behar duzu.|Gehienez {{ limit }} aukera hautatu behar dituzu.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Emandako balioetatik gutxienez bat ez da egokia.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>{{ fields }} eremuak ez ziren espero.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>{{ fields }} eremuak falta dira.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Balio hau ez da data egoki bat.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Balio hau ez da data-ordu egoki bat.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Balio hau ez da posta elektroniko egoki bat.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Ezin izan da fitxategia aurkitu.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Fitxategia ez da irakurgarria.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Fitxategia handiegia da ({{ size }} {{ suffix }}). Baimendutako tamaina handiena {{ limit }} {{ suffix }} da.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Fitxategiaren mime mota ez da egokia ({{ type }}). Hauek dira baimendutako mime motak: {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Balio hau gehienez {{ limit }} izan beharko litzateke.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Balio hau luzeegia da. Gehienez karaktere {{ limit }} eduki beharko luke.|Balio hau luzeegia da. Gehienez {{ limit }} karaktere eduki beharko lituzke.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Balio hau gutxienez {{ limit }} izan beharko litzateke.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Balio hau motzegia da. Karaktere {{ limit }} gutxienez eduki beharko luke.|Balio hau motzegia da. Gutxienez {{ limit }} karaktere eduki beharko lituzke.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Balio hau ez litzateke hutsik egon behar.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Balio hau ez litzateke nulua izan behar.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Balio hau nulua izan beharko litzateke.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Balio hau ez da egokia.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Balio hau ez da ordu egoki bat.</target>
           </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Balio hau ez da baliabideen kokatzaile uniforme (URL) egoki bat.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Bi balioak berdinak izan beharko lirateke.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Fitxategia handiegia da. Baimendutako tamaina handiena {{ limit }} {{ suffix }} da.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Fitxategia handiegia da.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Ezin izan da fitxategia igo.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Balio hau zenbaki egoki bat izan beharko litzateke.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Fitxategi hau ez da irudi egoki bat.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Honako hau ez da IP helbide egoki bat.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Balio hau ez da hizkuntza egoki bat.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Balio hau ez da kokapen egoki bat.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Balio hau ez da herrialde egoki bat.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Balio hau jadanik erabilia izan da.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Ezin izan da irudiaren tamaina detektatu.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Irudiaren zabalera handiegia da ({{ width }}px). Onartutako gehienezko zabalera {{ max_width }}px dira.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Irudiaren zabalera txikiegia da ({{ width }}px). Onartutako gutxieneko zabalera {{ min_width }}px dira.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Irudiaren altuera handiegia da ({{ height }}px). Onartutako gehienezko altuera {{ max_height }}px dira.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Irudiaren altuera txikiegia da ({{ height }}px). Onartutako gutxieneko altuera {{ min_height }}px dira.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Balio hau uneko erabiltzailearen pasahitza izan beharko litzateke.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Balio honek zehazki karaktere {{ limit }} izan beharko luke.|Balio honek zehazki {{ limit }} karaktere izan beharko lituzke.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Fitxategiaren zati bat bakarrik igo da.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Ez da fitxategirik igo.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Ez da aldi baterako karpetarik konfiguratu php.ini fitxategian.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Ezin izan da aldi baterako fitxategia diskoan idatzi.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>PHP luzapen batek igoeraren hutsa eragin du.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Bilduma honek gutxienez elementu {{ limit }} eduki beharko luke.|Bilduma honek gutxienez {{ limit }} elementu eduki beharko lituzke.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Bilduma honek gehienez elementu {{ limit }} eduki beharko luke.|Bilduma honek gehienez {{ limit }} elementu eduki beharko lituzke.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Bilduma honek zehazki elementu {{ limit }} eduki beharko luke.|Bilduma honek zehazki {{ limit }} elementu eduki beharko lituzke.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Txartel zenbaki baliogabea.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Txartel mota onartezina edo txartel zenbaki baliogabea.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Hau ez da baliozko banku internazionaleko kontu zenbaki (IBAN) bat.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Balio hau ez da onartutako ISBN-10 bat.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Balio hau ez da onartutako ISBN-13 bat.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Balio hau ez da onartutako ISBN-10 edo ISBN-13 bat.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Balio hau ez da onartutako ISSN bat.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Balio hau ez da baliozko moneta bat.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Balio hau {{ compared_value }}-(r)en berbera izan beharko litzateke.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Balio hau {{ compared_value }} baino handiagoa izan beharko litzateke.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Balio hau {{ compared_value }}-(r)en berdina edota handiagoa izan beharko litzateke.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Balio hau {{ compared_value_type }} {{ compared_value }}-(r)en berbera izan beharko litzateke.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Balio hau {{ compared_value }} baino txikiagoa izan beharko litzateke.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Balio hau {{ compared_value }}-(r)en berdina edota txikiagoa izan beharko litzateke.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Balio hau ez litzateke {{ compared_value }}-(r)en berdina izan behar.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Balio hau ez litzateke {{ compared_value_type }} {{ compared_value }}-(r)en berbera izan behar.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z1ar�==GSymfony/Component/Validator/Resources/translations/validators.zh_TW.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>該變數的值應為 false 。</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>該變數的值應為 true 。</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>該變數的類型應為 {{ type }} 。</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>該變數應為空。</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>選定變數的值不是有效的選項。</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>您至少要選擇 {{ limit }} 個選項。</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>您最多能選擇 {{ limit }} 個選項。</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>一個或者多個給定的值無效。</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>非預期的欄位 {{ fields }} 。</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>缺少的欄位 {{ fields }} 。</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>該值不是一個有效的日期(date)。</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>該值不是一個有效的日期時間(datetime)。</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>該值不是一個有效的郵件地址。</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>找不到檔案。</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>無法讀取檔案。</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>檔案太大 ({{ size }} {{ suffix }})。檔案大小不可以超過 {{ limit }} {{ suffix }} 。</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>無效的檔案類型 ({{ type }}) 。允許的檔案類型有 {{ types }} 。</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>這個變數的值應該小於或等於 {{ limit }}。</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>字串太長,長度不可超過 {{ limit }} 個字元。</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>該變數的值應該大於或等於 {{ limit }}。</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>字串太短,長度不可少於 {{ limit }} 個字元。</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>該變數不應為空白。</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>該值不應為 null 。</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>該值應為 null 。</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>無效的數值 。</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>該值不是一個有效的時間。</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>該值不是一個有效的 URL 。</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>這兩個變數的值應該相等。</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>檔案太大,檔案大小不可以超過 {{ limit }} {{ suffix }}。 </target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>檔案太大。</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>無法上傳此檔案。</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>該值應該為有效的數字。</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This value is not a valid country.</source>
                <target>該值不是有效的國家名。</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This file is not a valid image.</source>
                <target>該檔案不是有效的圖片。</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This is not a valid IP address.</source>
                <target>該值不是有效的IP地址。</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid language.</source>
                <target>該值不是有效的語言名。</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid locale.</source>
                <target>該值不是有效的區域值(locale)。</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>該值已經被使用。</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>不能解析圖片大小。</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>圖片太寬 ({{ width }}px),最大寬度為 {{ max_width }}px 。</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>圖片寬度不夠 ({{ width }}px),最小寬度為 {{ min_width }}px 。</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>圖片太高 ({{ height }}px),最大高度為 {{ max_height }}px 。</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>圖片高度不夠 ({{ height }}px),最小高度為 {{ min_height }}px 。</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>該變數的值應為用戶目前的密碼。</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>該變數應為 {{ limit }} 個字元。</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>該檔案的上傳不完整。</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>沒有上傳任何檔案。</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>php.ini 裡沒有配置臨時目錄。</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>暫存檔寫入磁碟失敗。</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>某個 PHP 擴展造成上傳失敗。</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>該集合最少應包含 {{ limit }} 個元素。</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>該集合最多包含 {{ limit }} 個元素。</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>該集合應包含 {{ limit }} 個元素 element 。</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>無效的信用卡號。</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>不支援的信用卡類型或無效的信用卡號。</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>該值不是有效的國際銀行帳號(IBAN)。</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>該值不是有效的10位國際標準書號(ISBN-10)。</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>該值不是有效的13位國際標準書號(ISBN-13)。</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>該值不是有效的國際標準書號(ISBN-10 或 ISBN-13)。</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>該值不是有效的國際標準期刊號(ISSN)。</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>該值不是有效的貨幣名(currency)。</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>該值應等於 {{ compared_value }} 。</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>該值應大於 {{ compared_value }} 。</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>該值應大於或等於 {{ compared_value }} 。</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>該值應與 {{ compared_value_type }} {{ compared_value }} 相同。</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>該值應小於 {{ compared_value }} 。</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>該值應小於或等於 {{ compared_value }} 。</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>該值應不等於 {{ compared_value }} 。</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>該值不應與 {{ compared_value_type }} {{ compared_value }} 相同。</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�T�л@�@GSymfony/Component/Validator/Resources/translations/validators.pt_BR.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Este valor deve ser falso.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Este valor deve ser verdadeiro.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Este valor deve ser do tipo {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Este valor deve ser vazio.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>O valor selecionado não é uma opção válida.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Você deve selecionar, no mínimo, {{ limit }} opção.|Você deve selecionar, no mínimo, {{ limit }} opções.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Você deve selecionar, no máximo, {{ limit }} opção.|Você deve selecionar, no máximo, {{ limit }} opções.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Um ou mais valores informados são inválidos.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Os campos {{ fields }} não são esperados.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Os campos {{ fields }} estão ausentes.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Este valor não é uma data válida.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Este valor não é uma data e hora válida.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Este valor não é um endereço de e-mail válido.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>O arquivo não foi encontrado.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>O arquivo não pode ser lido.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>O arquivo é muito grande ({{ size }} {{ suffix }}). O tamanho máximo permitido é {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>O tipo mime do arquivo é inválido ({{ type }}). Os tipos mime permitidos são {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Este valor deve ser {{ limit }} ou menos.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Este valor é muito longo. Deve ter {{ limit }} caractere ou menos.|Este valor é muito longo. Deve ter {{ limit }} caracteres ou menos.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Este valor deve ser {{ limit }} ou mais.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Este valor é muito curto. Deve ter {{ limit }} caractere ou mais.|Este valor é muito curto. Deve ter {{ limit }} caracteres ou mais.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Este valor não deve ser vazio.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Este valor não deve ser nulo.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Este valor deve ser nulo.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Este valor não é válido.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Este valor não é uma hora válida.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Este valor não é uma URL válida.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Os dois valores devem ser iguais.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>O arquivo é muito grande. O tamanho máximo permitido é de {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>O arquivo é muito grande.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>O arquivo não pode ser enviado.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Este valor deve ser um número válido.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Este arquivo não é uma imagem válida.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Este não é um endereço de IP válido.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Este valor não é um idioma válido.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Este valor não é uma localidade válida.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Este valor não é um país válido.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Este valor já está sendo usado.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>O tamanho da imagem não pode ser detectado.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>A largura da imagem é muito grande ({{ width }}px). A largura máxima permitida é de {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>A largura da imagem é muito pequena ({{ width }}px). A largura mínima esperada é de {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>A altura da imagem é muito grande ({{ height }}px). A altura máxima permitida é de {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>A altura da imagem é muito pequena ({{ height }}px). A altura mínima esperada é de {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Este valor deve ser a senha atual do usuário.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Este valor deve ter exatamente {{ limit }} caractere.|Este valor deve ter exatamente {{ limit }} caracteres.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>O arquivo foi enviado apenas parcialmente.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Nenhum arquivo foi enviado.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Nenhum diretório temporário foi configurado no php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Não foi possível escrever o arquivo temporário no disco.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Uma extensão PHP fez com que o envio falhasse.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Esta coleção deve conter {{ limit }} elemento ou mais.|Esta coleção deve conter {{ limit }} elementos ou mais.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Esta coleção deve conter {{ limit }} elemento ou menos.|Esta coleção deve conter {{ limit }} elementos ou menos.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Esta coleção deve conter exatamente {{ limit }} elemento.|Esta coleção deve conter exatamente {{ limit }} elementos.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Número de cartão inválido.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Tipo de cartão não suportado ou número de cartão inválido.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Este não é um Número Internacional de Conta Bancária (IBAN) válido.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Este valor não é um ISBN-10 válido.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Este valor não é um ISBN-13 válido.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Este valor não é um ISBN-10 e nem um ISBN-13 válido.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Este valor não é um ISSN válido.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Este não é um valor monetário válido.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Este valor deve ser igual a {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Este valor deve ser maior que {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Este valor deve ser maior ou igual a {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Este valor deve ser idêntico a {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Este valor deve ser menor que {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Este valor deve ser menor ou igual a {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Este valor não deve ser igual a {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Este valor não deve ser idêntico a {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z���1�1DSymfony/Component/Validator/Resources/translations/validators.no.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Verdien skulle ha vore tom/nei.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Verdien skulla ha vore satt/ja.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Verdien må vere av typen {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Verdien skal vere blank.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Verdien du valgte er ikkje gyldig.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Du må velge minst {{ limit }} valg.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Du kan maksimalt gjere {{ limit }} valg.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Ein eller fleire av dei opplyste verdiane er ugyldige.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Felta {{ fields }} var ikkje forventa.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Felta {{ fields }} manglar.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Verdien er ikkje ein gyldig dato.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Verdien er ikkje ein gyldig dato og tid.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Verdien er ikkje ei gyldig e-postadresse.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Fila kunne ikkje finnes.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Fila kan ikkje lesast.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Fila er for stor ({{ size }} {{ suffix }}). Tillatt maksimal størrelse er {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Mime-typen av fila er ugyldig ({{ type }}). Tillatte mime-typar er {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Verdien må vere {{ limit }} eller mindre.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Verdien er for lang. Den må vere {{ limit }} bokstavar eller mindre.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Verdien må vere {{ limit }} eller meir.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Verdien er for kort. Den må ha {{ limit }} teikn eller fleire.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Verdien må ikkje vere blank.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Verdien må ikkje vere tom (null).</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Verdien må vere tom (null).</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Verdien er ikkje gyldig.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Verdien er ikkje gyldig tidseining.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Verdien er ikkje ein gyldig URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Dei to verdiane må vere like.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Fila er for stor. Den maksimale storleik er {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Fila er for stor.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Fila kunne ikkje bli lasta opp.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Verdien må vere eit gyldig tal.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Fila er ikkje eit gyldig bilete.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Dette er ikkje ei gyldig IP-adresse.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Verdien er ikkje eit gyldig språk.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Verdien er ikkje ein gyldig lokalitet (språk/region).</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Verdien er ikkje eit gyldig land.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Verdien er allereie i bruk.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Storleiken på biletet kunne ikkje oppdagast.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Biletbreidda er for stor, ({{ width }} pikslar). Tillatt maksimumsbreidde er {{ max_width }} pikslar.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Biletbreidda er for liten, ({{ width }} pikslar). Forventa minimumsbreidde er {{ min_width }} pikslar.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Bilethøgda er for stor, ({{ height }} pikslar). Tillatt maksimumshøgde er {{ max_height }} pikslar.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Billethøgda er for låg, ({{ height }} pikslar). Forventa minimumshøgde er {{ min_height }} pikslar.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Verdien må vere brukaren sitt noverande passord.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Verdien må vere nøyaktig {{ limit }} teikn.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Fila vart kun delvis opplasta.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Inga fil vart lasta opp.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Førebels mappe (tmp) er ikkje konfigurert i php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Kan ikkje skrive førebels fil til disk.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Ei PHP-udviding forårsaka feil under opplasting.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Denne samlinga må innehalde {{ limit }} element eller meir.|Denne samlinga må innehalde {{ limit }} element eller meir.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Denne samlinga må innehalde {{ limit }} element eller færre.|Denne samlinga må innehalde {{ limit }} element eller færre.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Denne samlinga må innehalde nøyaktig {{ limit }} element.|Denne samlinga må innehalde nøyaktig {{ limit }} element.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Ugyldig kortnummer.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Korttypen er ikkje støtta eller ugyldig kortnummer.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z��n�C�CDSymfony/Component/Validator/Resources/translations/validators.sl.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Vrednost bi morala biti nepravilna (false).</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Vrednost bi morala biti pravilna (true).</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Vrednost mora biti naslednjega tipa {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Vrednost mora biti prazna.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Vrednost, ki ste jo izbrali, ni veljavna možnost.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Izbrati morate vsaj {{ limit }} možnost.|Izbrati morate vsaj {{ limit }} možnosti.|Izbrati morate vsaj {{ limit }} možnosti.|Izbrati morate vsaj {{ limit }} možnosti.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Izberete lahko največ {{ limit }} možnost.|Izberete lahko največ {{ limit }} možnosti.|Izberete lahko največ {{ limit }} možnosti.|Izberete lahko največ {{ limit }} možnosti.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Ena ali več podanih vrednosti ni veljavnih.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Polja {{ fields }} niso bila pričakovana.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Polja {{ fields }} manjkajo.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Ta vrednost ni veljaven datum.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Ta vrednost ni veljaven datum in čas.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Ta vrednost ni veljaven e-poštni naslov.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Datoteke ni mogoče najti.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Datoteke ni mogoče prebrati.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Datoteka je prevelika ({{ size }} {{ suffix }}). Največja dovoljena velikost je {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Mime tip datoteke je neveljaven ({{ type }}). Dovoljeni mime tipi so {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Ta vrednost bi morala biti {{ limit }} ali manj.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Ta vrednost je predolga. Morala bi imeti {{ limit }} znak ali manj.|Ta vrednost je predolga. Morala bi imeti {{ limit }} znaka ali manj.|Ta vrednost je predolga. Morala bi imeti {{ limit }} znake ali manj.|Ta vrednost je predolga. Morala bi imeti {{ limit }} znakov ali manj.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Ta vrednost bi morala biti {{ limit }} ali več.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Ta vrednost je prekratka. Morala bi imeti {{ limit }} znak ali več.|Ta vrednost je prekratka. Morala bi imeti {{ limit }} znaka ali več.|Ta vrednost je prekratka. Morala bi imeti {{ limit }} znake ali več.|Ta vrednost je prekratka. Morala bi imeti {{ limit }} znakov ali več.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Ta vrednost ne bi smela biti prazna.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Ta vrednost ne bi smela biti nedefinirana (null).</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Ta vrednost bi morala biti nedefinirana (null).</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Ta vrednost ni veljavna.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Ta vrednost ni veljaven čas.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Ta vrednost ni veljaven URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Ti dve vrednosti bi morali biti enaki.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Datoteka je prevelika. Največja dovoljena velikost je {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Datoteka je prevelika.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Datoteke ni bilo mogoče naložiti.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Ta vrednost bi morala biti veljavna številka.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Ta datoteka ni veljavna slika.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>To ni veljaven IP naslov.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Ta vrednost ni veljaven jezik.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Ta vrednost ni veljavna lokalnost.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Ta vrednost ni veljavna država.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Ta vrednost je že uporabljena.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Velikosti slike ni bilo mogoče zaznati.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Širina slike je preširoka ({{ width }}px). Največja dovoljena širina je {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Širina slike je premajhna ({{ width }}px). Najmanjša predvidena širina je {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Višina slike je prevelika ({{ height }}px). Največja dovoljena višina je {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Višina slike je premajhna ({{ height }}px). Najmanjša predvidena višina je {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Ta vrednost bi morala biti trenutno uporabnikovo geslo.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Ta vrednost bi morala imeti točno {{ limit }} znak.|Ta vrednost bi morala imeti točno {{ limit }} znaka.|Ta vrednost bi morala imeti točno {{ limit }} znake.|Ta vrednost bi morala imeti točno {{ limit }} znakov.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Datoteka je bila le delno naložena.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Nobena datoteka ni bila naložena.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Začasna mapa ni nastavljena v php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Začasne datoteke ni bilo mogoče zapisati na disk.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>PHP razširitev je vzrok, da nalaganje ni uspelo.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Ta zbirka bi morala vsebovati {{ limit }} element ali več.|Ta zbirka bi morala vsebovati {{ limit }} elementa ali več.|Ta zbirka bi morala vsebovati {{ limit }} elemente ali več.|Ta zbirka bi morala vsebovati {{ limit }} elementov ali več.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Ta zbirka bi morala vsebovati {{ limit }} element ali manj.|Ta zbirka bi morala vsebovati {{ limit }} elementa ali manj.|Ta zbirka bi morala vsebovati {{ limit }} elemente ali manj.|Ta zbirka bi morala vsebovati {{ limit }} elementov ali manj.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Ta zbirka bi morala vsebovati točno {{ limit }} element.|Ta zbirka bi morala vsebovati točno {{ limit }} elementa.|Ta zbirka bi morala vsebovati točno {{ limit }} elemente.|Ta zbirka bi morala vsebovati točno {{ limit }} elementov.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Neveljavna številka kartice.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Nepodprti tip kartice ali neveljavna številka kartice.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>To ni veljavna mednarodna številka bančnega računa (IBAN).</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Neveljavna vrednost po ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Neveljavna vrednost po ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Neveljavna vrednost po ISBN-10 ali po ISBN-13.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Neveljavna vrednost ISSN.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Ta vrednost ni veljavna valuta.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Ta vrednost bi morala biti enaka {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Ta vrednost bi morala biti večja od {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Ta vrednost bi morala biti večja ali enaka {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Ta vrednost bi morala biti identična {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Ta vrednost bi morala biti manjša od {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Ta vrednost bi morala biti manjša ali enaka {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Ta vrednost ne bi smela biti enaka {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Ta vrednost ne bi smela biti identična {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Zq�b�?�?DSymfony/Component/Validator/Resources/translations/validators.lb.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Dëse Wäert sollt falsch sinn.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Dëse Wäert sollt wouer sinn.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Dëse Wäert sollt vum Typ {{ type }} sinn.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Dëse Wäert sollt eidel sinn.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Dëse Wäert sollt enger vun de Wielméiglechkeeten entspriechen.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Dir sollt mindestens {{ limit }} Méiglechkeete wielen.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Dir sollt héchstens {{ limit }} Méiglechkeete wielen.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Een oder méi vun de Wäerter ass ongëlteg.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>D'Felder {{ fields }} goufen net erwaart.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>D'Felder {{ fields }} feelen.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Dëse Wäert entsprécht kenger gëlteger Datumsangab.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Dëse Wäert entsprécht kenger gëlteger Datums- an Zäitangab.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Dëse Wäert ass keng gëlteg Email-Adress.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>De Fichier gouf net fonnt.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>De Fichier ass net liesbar.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>De Fichier ass ze grouss ({{ size }} {{ suffix }}). Déi zougeloosse Maximalgréisst bedréit {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Den Typ vum Fichier ass ongëlteg ({{ type }}). Erlaabten Type sinn {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Dëse Wäert soll méi kleng oder gläich {{ limit }} sinn.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Dës Zeecheketten ass ze laang. Se sollt héchstens {{ limit }} Zeechen hunn.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Dëse Wäert sollt méi grouss oder gläich {{ limit }} sinn.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Dës Zeecheketten ass ze kuerz. Se sollt mindestens {{ limit }} Zeechen hunn.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Dëse Wäert sollt net eidel sinn.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Dëst sollt keen Null-Wäert sinn.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Dëst sollt keen Null-Wäert sinn.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Dëse Wäert ass net gëlteg.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Dëse Wäert entsprécht kenger gëlteger Zäitangab.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Dëse Wäert ass keng gëlteg URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Béid Wäerter sollten identesch sinn.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>De fichier ass ze grouss. Déi maximal Gréisst dierf {{ limit }} {{ suffix }} net depasséieren.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>De Fichier ass ze grouss.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>De Fichier konnt net eropgeluede ginn.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Dëse Wäert sollt eng gëlteg Zuel sinn.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Dëse Fichier ass kee gëltegt Bild.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Dëst ass keng gëlteg IP-Adress.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Dëse Wäert aentsprécht kenger gëlteger Sprooch.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Dëse Wäert entsprécht kengem gëltege Gebittsschema.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Dëse Wäert entsprécht kengem gëltege Land.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Dëse Wäert gëtt scho benotzt.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>D'Gréisst vum Bild konnt net detektéiert ginn.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>D'Breet vum Bild ass ze grouss ({{ width }}px). Déi erlaabte maximal Breet ass {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>D'Breet vum Bild ass ze kleng ({{ width }}px). Déi minimal Breet ass {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>D'Héicht vum Bild ass ze grouss ({{ height }}px). Déi erlaabte maximal Héicht ass {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>D'Héicht vum Bild ass ze kleng ({{ height }}px). Déi minimal Héicht ass {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Dëse Wäert sollt dem aktuelle Benotzerpasswuert entspriechen.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Dëse Wäert sollt exactly {{ limit }} Buschtaf hunn.|Dëse Wäert sollt exakt {{ limit }} Buschtawen hunn.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>De Fichier gouf just deelweis eropgelueden.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Et gouf kee Fichier eropgelueden.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Et gouf keen temporären Dossier an der php.ini konfiguréiert.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Den temporäre Fichier kann net gespäichert ginn.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Eng PHP-Erweiderung huet den Upload verhënnert.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Dës Sammlung sollt {{ limit }} oder méi Elementer hunn.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Dës Sammlung sollt {{ limit }} oder manner Elementer hunn.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Dës Sammlung sollt exakt {{ limit }} Element hunn.|Dës Sammlung sollt exakt {{ limit }} Elementer hunn.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Ongëlteg Kaartennummer.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Net ënnerstëtzte Kaartentyp oder ongëlteg Kaartennummer.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Dëst ass keng gëlteg IBAN-Kontonummer.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Dëse Wäert ass keng gëlteg ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Dëse Wäert ass keng gëlteg ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Dëse Wäert ass weder eng gëlteg ISBN-10 nach eng gëlteg ISBN-13.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Dëse Wäert ass keng gëlteg ISSN.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Dëse Wäert ass keng gëlteg Währung.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Dëse Wäert sollt {{ compared_value }} sinn.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Dëse Wäert sollt méi grouss wéi {{ compared_value }} sinn.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Dëse Wäert sollt méi grouss wéi oder gläich {{ compared_value }} sinn.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Dëse Wäert sollt identesch si mat {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Dëse Wäert sollt méi kleng wéi {{ compared_value }} sinn.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Dëse Wäert sollt méi kleng wéi oder gläich {{ compared_value }} sinn.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Dëse Wäert sollt net {{ compared_value }} sinn.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Dëse Wäert sollt net identesch si mat {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z93XaoAoADSymfony/Component/Validator/Resources/translations/validators.hu.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Ennek az értéknek hamisnak kell lennie.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Ennek az értéknek igaznak kell lennie.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Ennek az értéknek {{ type }} típusúnak kell lennie.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Ennek az értéknek üresnek kell lennie.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>A választott érték érvénytelen.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Legalább {{ limit }} értéket kell kiválasztani.|Legalább {{ limit }} értéket kell kiválasztani.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Legfeljebb {{ limit }} értéket lehet kiválasztani.|Legfeljebb {{ limit }} értéket lehet kiválasztani.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>A megadott értékek közül legalább egy érvénytelen.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Váratlan mezők: {{ fields }}.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>A következő mezők hiányoznak: {{ fields }}.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Ez az érték nem egy érvényes dátum.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Ez az érték nem egy érvényes időpont.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Ez az érték nem egy érvényes e-mail cím.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>A fájl nem található.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>A fájl nem olvasható.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>A fájl túl nagy ({{ size }} {{ suffix }}). A legnagyobb megengedett méret {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>A fájl mime típusa érvénytelen ({{ type }}). Az engedélyezett mime típusok: {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Ez az érték legfeljebb {{ limit }} lehet.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Ez az érték túl hosszú. Legfeljebb {{ limit }} karaktert tartalmazhat.|Ez az érték túl hosszú. Legfeljebb {{ limit }} karaktert tartalmazhat.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Ez az érték legalább {{ limit }} kell legyen.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Ez az érték túl rövid. Legalább {{ limit }} karaktert kell tartalmaznia.|Ez az érték túl rövid. Legalább {{ limit }} karaktert kell tartalmaznia.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Ez az érték nem lehet üres.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Ez az érték nem lehet null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Ennek az értéknek nullnak kell lennie.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Ez az érték nem érvényes.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Ez az érték nem egy érvényes időpont.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Ez az érték nem egy érvényes URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>A két értéknek azonosnak kell lennie.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>A fájl túl nagy. A megengedett maximális méret: {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>A fájl túl nagy.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>A fájl nem tölthető fel.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Ennek az értéknek érvényes számnak kell lennie.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Ez a fájl nem egy érvényes kép.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Ez az érték nem egy érvényes IP cím.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Ez az érték nem egy érvényes nyelv.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Ez az érték nem egy érvényes területi beállítás.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Ez az érték nem egy érvényes ország.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Ez az érték már használatban van.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>A kép méretét nem lehet megállapítani.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>A kép szélessége túl nagy ({{ width }}px). A megengedett legnagyobb szélesség {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>A kép szélessége túl kicsi ({{ width }}px). Az elvárt legkisebb szélesség {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>A kép magassága túl nagy ({{ height }}px). A megengedett legnagyobb magasság {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>A kép magassága túl kicsi ({{ height }}px). Az elvárt legkisebb magasság {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Ez az érték a felhasználó jelenlegi jelszavával kell megegyezzen.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Ennek az értéknek pontosan {{ limit }} karaktert kell tartalmaznia.|Ennek az értéknek pontosan {{ limit }} karaktert kell tartalmaznia.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>A fájl csak részben lett feltöltve.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Nem lett fájl feltöltve.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Nincs ideiglenes könyvtár beállítva a php.ini-ben.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Az ideiglenes fájl nem írható a lemezre.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Egy PHP bővítmény miatt a feltöltés nem sikerült.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Ennek a gyűjteménynek legalább {{ limit }} elemet kell tartalmaznia.|Ennek a gyűjteménynek legalább {{ limit }} elemet kell tartalmaznia.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Ez a gyűjtemény legfeljebb {{ limit }} elemet tartalmazhat.|Ez a gyűjtemény legfeljebb {{ limit }} elemet tartalmazhat.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Ennek a gyűjteménynek pontosan {{ limit }} elemet kell tartalmaznia.|Ennek a gyűjteménynek pontosan {{ limit }} elemet kell tartalmaznia.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Érvénytelen kártyaszám.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Nem támogatott kártyatípus vagy érvénytelen kártyaszám.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Érvénytelen nemzetközi bankszámlaszám (IBAN).</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Ez az érték nem egy érvényes ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Ez az érték nem egy érvényes ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Ez az érték nem egy érvényes ISBN-10 vagy ISBN-13.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Ez az érték nem egy érvényes ISSN.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Ez az érték nem egy érvényes pénznem.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Ez az érték legyen {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Ez az érték nagyobb legyen mint {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Ez az érték nagyobb vagy egyenlő legyen mint {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Ez az érték ugyanolyan legyen mint {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Ez az érték kisebb legyen mint {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Ez az érték kisebb vagy egyenlő legyen mint {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Ez az érték ne legyen {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Ez az érték ne legyen ugyanolyan mint {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z����M�MDSymfony/Component/Validator/Resources/translations/validators.el.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Αυτή η τιμή πρέπει να είναι ψευδής.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Αυτή η τιμή πρέπει να είναι αληθής.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Αυτή η τιμή πρέπει να είναι τύπου {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Αυτή η τιμή πρέπει να είναι κενή.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Η τιμή που επιλέχθηκε δεν αντιστοιχεί σε έγκυρη επιλογή.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Πρέπει να επιλέξετε τουλάχιστον {{ limit }} επιλογή.|Πρέπει να επιλέξετε τουλάχιστον {{ limit }} επιλογές.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Πρέπει να επιλέξετε το πολύ {{ limit }} επιλογή.|Πρέπει να επιλέξετε το πολύ {{ limit }} επιλογές.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Μια ή περισσότερες τιμές δεν είναι έγκυρες.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Τα πεδία {{ fields }} δεν ήταν αναμενόμενα.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Τα πεδία {{ fields }} απουσιάζουν.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Η τιμή δεν αντιστοιχεί σε έγκυρη ημερομηνία.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Η τιμή δεν αντιστοιχεί σε έγκυρη ημερομηνία και ώρα.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Η τιμή δεν αντιστοιχεί σε έγκυρο email.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Το αρχείο δε μπορεί να βρεθεί.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Το αρχείο δεν είναι αναγνώσιμο.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Το αρχείο είναι πολύ μεγάλο ({{ size }} {{ suffix }}). Το μέγιστο επιτρεπτό μέγεθος είναι {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Ο τύπος mime του αρχείου δεν είναι έγκυρος ({{ type }}). Οι έγκρυοι τύποι mime είναι {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Αυτή η τιμή θα έπρεπε να είναι {{ limit }} ή λιγότερο.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Αυτή η τιμή είναι πολύ μεγάλη. Θα έπρεπε να έχει {{ limit }} χαρακτήρα ή λιγότερο.|Αυτή η τιμή είναι πολύ μεγάλη. Θα έπρεπε να έχει {{ limit }} χαρακτήρες ή λιγότερο.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Αυτή η τιμή θα έπρεπε να είναι {{ limit }} ή περισσότερο.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Αυτή η τιμή είναι πολύ μικρή. Θα έπρεπε να έχει {{ limit }} χαρακτήρα ή περισσότερο.|Αυτή η τιμή είναι πολύ μικρή. Θα έπρεπε να έχει {{ limit }} χαρακτήρες ή περισσότερο.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Αυτή η τιμή δεν πρέπει να είναι κενή.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Αυτή η τιμή δεν πρέπει να είναι μηδενική.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Αυτή η τιμή πρέπει να είναι μηδενική.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Αυτή η τιμή δεν είναι έκγυρη.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Αυτή η τιμή δεν αντιστοιχεί σε έγκυρη ώρα.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Αυτή η τιμή δεν αντιστοιχεί σε έγκυρο URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Οι δύο τιμές θα πρέπει να είναι ίδιες.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Το αρχείο είναι πολύ μεγάλο. Το μέγιστο επιτρεπτό μέγεθος είναι {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Το αρχείο είναι πολύ μεγάλο.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Το αρχείο δε μπορεί να ανέβει.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Αυτή η τιμή θα πρέπει να είναι ένας έγκυρος αριθμός.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Το αρχείο δεν αποτελεί έγκυρη εικόνα.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Αυτό δεν είναι μια έκγυρη διεύθυνση IP.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Αυτή η τιμή δεν αντιστοιχεί σε μια έκγυρη γλώσσα.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Αυτή η τιμή δεν αντιστοιχεί σε έκγυρο κωδικό τοποθεσίας.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Αυτή η τιμή δεν αντιστοιχεί σε μια έκγυρη χώρα.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Αυτή η τιμή χρησιμοποιείται ήδη.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Το μέγεθος της εικόνας δεν ήταν δυνατό να ανιχνευθεί.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Το πλάτος της εικόνας είναι πολύ μεγάλο ({{ width }}px). Το μέγιστο επιτρεπτό πλάτος είναι {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Το πλάτος της εικόνας είναι πολύ μικρό ({{ width }}px). Το ελάχιστο επιτρεπτό πλάτος είναι {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Το ύψος της εικόνας είναι πολύ μεγάλο ({{ height }}px). Το μέγιστο επιτρεπτό ύψος είναι {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Το ύψος της εικόνας είναι πολύ μικρό ({{ height }}px). Το ελάχιστο επιτρεπτό ύψος είναι {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Αυτή η τιμή θα έπρεπε να είναι ο τρέχων κωδικός.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Αυτή η τιμή θα έπρεπε να έχει ακριβώς {{ limit }} χαρακτήρα.|Αυτή η τιμή θα έπρεπε να έχει ακριβώς {{ limit }} χαρακτήρες.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Το αρχείο δεν ανέβηκε ολόκληρο.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Δεν ανέβηκε κανένα αρχείο.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Κανένας προσωρινός φάκελος δεν έχει ρυθμιστεί στο php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Αδυναμία εγγραφής προσωρινού αρχείου στο δίσκο.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Μια επέκταση PHP προκάλεσε αδυναμία ανεβάσματος.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Αυτή η συλλογή θα πρέπει να περιέχει {{ limit }} στοιχείο ή περισσότερα.|Αυτή η συλλογή θα πρέπει να περιέχει {{ limit }} στοιχεία ή περισσότερα.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Αυτή η συλλογή θα πρέπει να περιέχει {{ limit }} στοιχείo ή λιγότερα.|Αυτή η συλλογή θα πρέπει να περιέχει {{ limit }} στοιχεία ή λιγότερα.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Αυτή η συλλογή θα πρέπει να περιέχει ακριβώς {{ limit }} στοιχείo.|Αυτή η συλλογή θα πρέπει να περιέχει ακριβώς {{ limit }} στοιχεία.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Μη έγκυρος αριθμός κάρτας.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Μη υποστηριζόμενος τύπος κάρτας ή μη έγκυρος αριθμός κάρτας.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Αυτό δεν αντιστοιχεί σε έκγυρο διεθνή αριθμό τραπεζικού λογαριασμού (IBAN).</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Αυτό δεν είναι έγκυρος κωδικός ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Αυτό δεν είναι έγκυρος κωδικός ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Αυτό δεν είναι ούτε έγκυρος κωδικός ISBN-10 ούτε έγκυρος κωδικός ISBN-13.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Αυτό δεν είναι έγκυρος κωδικός ISSN.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Αυτό δεν αντιστοιχεί σε έγκυρο νόμισμα.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Αυτή η τιμή θα πρέπει να είναι ίση με {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Αυτή η τιμή θα πρέπει να είναι μεγαλύτερη από {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Αυτή η τιμή θα πρέπει να είναι μεγαλύτερη ή ίση με {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Αυτή η τιμή θα πρέπει να είναι πανομοιότυπη με {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Αυτή η τιμή θα πρέπει να είναι μικρότερη από {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Αυτή η τιμή θα πρέπει να είναι μικρότερη ή ίση με {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Αυτή η τιμή δεν θα πρέπει να είναι ίση με {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Αυτή η τιμή δεν πρέπει να είναι πανομοιότυπη με {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z��9>�5�5DSymfony/Component/Validator/Resources/translations/validators.da.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Værdien skal være falsk.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Værdien skal være sand.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Værdien skal være af typen {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Værdien skal være blank.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Værdien skal være en af de givne muligheder.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Du skal vælge mindst {{ limit }} muligheder.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Du kan højest vælge {{ limit }} muligheder.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>En eller flere af de oplyste værdier er ugyldige.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Felterne {{ fields }} var ikke forventet.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Felterne {{ fields }} mangler.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Værdien er ikke en gyldig dato.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Værdien er ikke en gyldig dato og tid.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Værdien er ikke en gyldig e-mail adresse.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Filen kunne ikke findes.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Filen kan ikke læses.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Filen er for stor ({{ size }} {{ suffix }}). Tilladte maksimale størrelse {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Mimetypen af filen er ugyldig ({{ type }}). Tilladte mimetyper er {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Værdien skal være {{ limit }} eller mindre.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Værdien er for lang. Den skal have {{ limit }} bogstaver eller mindre.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Værdien skal være {{ limit }} eller mere.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Værdien er for kort. Den skal have {{ limit }} tegn eller flere.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Værdien må ikke være blank.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Værdien må ikke være tom (null).</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Værdien skal være tom (null).</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Værdien er ikke gyldig.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Værdien er ikke en gyldig tid.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Værdien er ikke en gyldig URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>De to værdier skal være ens.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Filen er for stor. Den maksimale størrelse er {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Filen er for stor.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Filen kunne ikke blive uploadet.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Værdien skal være et gyldigt tal.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Filen er ikke gyldigt billede.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Dette er ikke en gyldig IP adresse.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Værdien er ikke et gyldigt sprog.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Værdien er ikke en gyldig lokalitet.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Værdien er ikke et gyldigt land.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Værdien er allerede i brug.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Størrelsen på billedet kunne ikke detekteres.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Billedbredden er for stor ({{ width }}px). Tilladt maksimumsbredde er {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Billedebredden er for lille ({{ width }}px). Forventet minimumshøjde er {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Billedhøjden er for stor ({{ height }}px). Tilladt maksimumshøjde er {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Billedhøjden er for lille ({{ height }}px). Forventet minimumshøjde er {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Værdien skal være brugerens nuværende password.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Værdien skal have præcis {{ limit }} tegn.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Filen var kun delvis uploadet.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Ingen fil blev uploadet.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Ingen midlertidig mappe er konfigureret i php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Kan ikke skrive midlertidig fil til disk.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>En PHP udvidelse forårsagede fejl i upload.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Denne samling skal indeholde {{ limit }} element eller flere.|Denne samling skal indeholde {{ limit }} elementer eller flere.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Denne samling skal indeholde {{ limit }} element eller mindre.|Denne samling skal indeholde {{ limit }} elementer eller mindre.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Denne samling skal indeholde præcis {{ limit }} element.|Denne samling skal indeholde præcis {{ limit }} elementer.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Ugyldigt kortnummer.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Ikke-understøttet korttype eller ugyldigt kortnummer.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Det er ikke en gyldig International Bank Account Number (IBAN).</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Værdien er ikke en gyldig ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Værdien er ikke en gyldig ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Værdien er hverken en gyldig ISBN-10 eller en gyldig ISBN-13.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Værdien er ikke en gyldig ISSN.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z���AADSymfony/Component/Validator/Resources/translations/validators.ja.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>falseでなければなりません。</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>trueでなければなりません。</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>型は{{ type }}でなければなりません。</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>空でなければなりません。</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>有効な選択肢ではありません。</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>{{ limit }}個以上選択してください。</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>{{ limit }}個以内で選択してください。</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>無効な選択肢が含まれています。</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>フィールド{{ fields }}は無効です。</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>フィールド{{ fields }}は必須です。</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>有効な日付ではありません。</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>有効な日時ではありません。</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>有効なメールアドレスではありません。</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>ファイルが見つかりません。</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>ファイルを読み込めません。</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>ファイルのサイズが大きすぎます({{ size }} {{ suffix }})。有効な最大サイズは{{ limit }} {{ suffix }}です。</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>ファイルのMIMEタイプが無効です({{ type }})。有効なMIMEタイプは{{ types }}です。</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>{{ limit }}以下でなければなりません。</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>値が長すぎます。{{ limit }}文字以内でなければなりません。</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>{{ limit }}以上でなければなりません。</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>値が短すぎます。{{ limit }}文字以上でなければなりません。</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>空であってはなりません。</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>nullであってはなりません。</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>nullでなければなりません。</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>有効な値ではありません。</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>有効な時刻ではありません。</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>有効なURLではありません。</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>2つの値が同じでなければなりません。</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>ファイルのサイズが大きすぎます。有効な最大サイズは{{ limit }} {{ suffix }}です。</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>ファイルのサイズが大きすぎます。</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>ファイルをアップロードできませんでした。</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>有効な数字ではありません。</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>ファイルが画像ではありません。</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>有効なIPアドレスではありません。</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>有効な言語名ではありません。</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>有効なロケールではありません。</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>有効な国名ではありません。</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>既に使用されています。</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>画像のサイズが検出できません。</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>画像の幅が大きすぎます({{ width }}ピクセル)。{{ max_width }}ピクセルまでにしてください。</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>画像の幅が小さすぎます({{ width }}ピクセル)。{{ min_width }}ピクセル以上にしてください。</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>画像の高さが大きすぎます({{ height }}ピクセル)。{{ max_height }}ピクセルまでにしてください。</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>画像の高さが小さすぎます({{ height }}ピクセル)。{{ min_height }}ピクセル以上にしてください。</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>ユーザーの現在のパスワードでなければなりません。</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>ちょうど{{ limit }}文字でなければなりません。</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>ファイルのアップロードは完全ではありません。</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>ファイルがアップロードされていません。</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>php.iniで一時フォルダが設定されていません。</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>一時ファイルをディスクに書き込むことができません。</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>PHP拡張によってアップロードに失敗しました。</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>{{ limit }}個以上の要素を含んでなければいけません。</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>要素は{{ limit }}個までです。</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>要素はちょうど{{ limit }}個でなければなりません。</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>無効なカード番号です。</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>未対応のカード種類又は無効なカード番号です。</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>有効なIBANコードではありません。</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>有効なISBN-10コードではありません。</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>有効なISBN-13コードではありません。</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>有効なISBN-10コード又はISBN-13コードではありません。</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>有効なISSNコードではありません。</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>有効な貨幣ではありません。</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>{{ compared_value }}と等しくなければなりません。</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>{{ compared_value }}より大きくなければなりません。</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>{{ compared_value }}以上でなければなりません。</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>{{ compared_value_type }}としての{{ compared_value }}と等しくなければなりません。</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>{{ compared_value }}未満でなければなりません。</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>{{ compared_value }}以下でなければなりません。</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>{{ compared_value }}と等しくてはいけません。</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>{{ compared_value_type }}としての{{ compared_value }}と等しくてはいけません。</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�Q>�?�?DSymfony/Component/Validator/Resources/translations/validators.sv.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Värdet ska vara falskt.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Värdet ska vara sant.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Värdet ska vara av typen {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Värdet ska vara tomt.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Värdet ska vara ett av de givna valen.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Du måste välja minst {{ limit }} val.|Du måste välja minst {{ limit }} val.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Du kan som mest välja {{ limit }} val.|Du kan som mest välja {{ limit }} val.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Ett eller fler av de angivna värdena är ogiltigt.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Fälten {{ fields }} var oväntade.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Fälten {{ fields }} saknas.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Värdet är inte ett giltigt datum.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Värdet är inte ett giltigt datum med tid.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Värdet är inte en giltig epost-adress.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Filen kunde inte hittas.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Filen är inte läsbar.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Filen är för stor ({{ size }} {{ suffix }}). Största tillåtna storlek är {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Filens MIME-typ ({{ type }}) är ogiltig. De tillåtna typerna är {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Värdet ska vara {{ limit }} eller mindre.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Värdet är för långt. Det ska ha {{ limit }} tecken eller färre.|Värdet är för långt. Det ska ha {{ limit }} tecken eller färre.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Värdet ska vara {{ limit }} eller mer.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Värdet är för kort. Det ska ha {{ limit }} tecken eller mer.|Värdet är för kort. Det ska ha {{ limit }} tecken eller mer.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Värdet kan inte vara tomt.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Värdet kan inte vara null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Värdet ska vara null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Värdet är inte giltigt.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Värdet är inte en giltig tid.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Värdet är inte en giltig URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>De två värdena måste vara lika.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Filen är för stor. Tillåten maximal storlek är {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Filen är för stor.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Filen kunde inte laddas upp.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Värdet ska vara ett giltigt nummer.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Filen är ingen giltig bild.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Det här är inte en giltig IP-adress.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Värdet är inte ett giltigt språk.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Värdet är inte en giltig plats.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Värdet är inte ett giltigt land.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Värdet används redan.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Det gick inte att fastställa storleken på bilden.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Bildens bredd är för stor ({{ width }}px). Tillåten maximal bredd är {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Bildens bredd är för liten ({{ width }}px). Minsta förväntade bredd är {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Bildens höjd är för stor ({{ height }}px). Tillåten maximal bredd är {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Bildens höjd är för liten ({{ height }}px). Minsta förväntade höjd är {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Värdet ska vara användarens nuvarande lösenord.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Värdet ska ha exakt {{ limit }} tecken.|Värdet ska ha exakt {{ limit }} tecken.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Filen laddades bara upp delvis.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Ingen fil laddades upp.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Det finns ingen temporär mapp konfigurerad i php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Kan inte skriva temporär fil till disken.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>En PHP extension gjorde att uppladdningen misslyckades.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Den här samlingen ska innehålla {{ limit }} element eller mer.|Den här samlingen ska innehålla {{ limit }} element eller mer.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Den här samlingen ska innehålla {{ limit }} element eller mindre.|Den här samlingen ska innehålla {{ limit }} element eller mindre.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Den här samlingen ska innehålla exakt {{ limit }} element.|Den här samlingen ska innehålla exakt {{ limit }} element.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Ogiltigt kortnummer.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Okänd korttyp eller ogiltigt kortnummer.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Det här är inte en giltig International Bank Account Number (IBANK).</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Värdet är inte en giltig ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Värdet är inte en giltig ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Värdet är varken en giltig ISBN-10 eller en giltig ISBN-13.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Värdet är inte en giltig ISSN.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Värdet är inte en giltig valuta.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Värdet ska vara detsamma som {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Värdet ska vara större än {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Värdet ska bara större än eller detsamma som {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Värdet ska vara identiskt till {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Värdet ska vara mindre än {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Värdet ska vara mindre än eller detsamma som {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Värdet ska inte vara detsamma som {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Värdet ska inte vara identiskt med {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Zv_��w,w,DSymfony/Component/Validator/Resources/translations/validators.hy.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Արժեքը պետք է լինի կեղծ.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Արժեքը պետք է լինի ճշմարիտ.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Արժեքը պետք է լինի {{ type }} տեսակի.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Արժեքը պետք է լինի դատարկ.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Ձեր ընտրած արժեքը անթույլատրելի է.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Դուք պետք է ընտրեք ամենաքիչը {{ limit }} տարբերակներ.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Դուք պետք է ընտրեք ոչ ավելի քան {{ limit }} տարբերակներ.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Մեկ կամ ավելի տրված արժեքները անթույլատրելի են.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>{{ fields }} տողերը չէին սպասվում.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>{{ fields }} տողերը բացակայում են.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Արժեքը սխալ ամսաթիվ է.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Ամսաթվի և ժամանակի արժեքը անթույլատրելի է.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Էլ-փոստի արժեքը անթույլատրելի է.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Ֆայլը չի գտնվել.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Ֆայլը անընթեռնելի է.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Ֆայլը չափազանց մեծ է ({{ size }} {{ suffix }}): Մաքսիմալ թույլատրելի չափսը՝ {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>MIME-տեսակը անթույլատրելի է({{ type }}): Ֆայլերի թույլատրելի MIME-տեսակներն են: {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Արժեքը պետք է լինի {{ limit }} կամ փոքր.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Արժեքը չափազանց երկար է: Պետք է լինի {{ limit }} կամ ավել սիմվոլներ.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Արժեքը պետ է լինի {{ limit }} կամ շատ.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Արժեքը չափազանց կարճ է: Պետք է լինի {{ limit }} կամ ավելի սիմվոլներ.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Արժեքը չպետք է դատարկ լինի.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Արժեքը չպետք է լինի null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Արժեքը պետք է լինի null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Անթույլատրելի արժեք.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Ժամանակի արժեքը անթույլատրելի է.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Արժեքը  URL  չէ.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Երկու արժեքները պետք է նույնը լինեն.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Ֆայլը չափազանց մեծ է: Մաքսիմալ թույլատրելի չափսը {{ limit }} {{ suffix }} է.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Ֆայլը չափազանց մեծ է.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Ֆայլը չի կարող բեռնվել.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Արժեքը պետք է լինի թիվ.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This value is not a valid country.</source>
                <target>Արժեքը պետք է լինի երկիր.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This file is not a valid image.</source>
                <target>Ֆայլը նկարի թույլատրելի ֆորմատ չէ.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This is not a valid IP address.</source>
                <target>Արժեքը թույլատրելի IP հասցե չէ.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid language.</source>
                <target>Արժեքը թույլատրելի լեզու չէ.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid locale.</source>
                <target>Արժեքը չի հանդիսանում թույլատրելի տեղայնացում.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Այդ արժեքը արդեն օգտագործվում է.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Նկարի չափսերը չստացվեց որոշել.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Նկարի լայնությունը չափազանց մեծ է({{ width }}px). Մաքսիմալ չափն է {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Նկարի լայնությունը չափազանց փոքր է ({{ width }}px). Մինիմալ չափն է {{ min_ width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Նկարի բարձրությունը չափազանց մեծ է ({{ height }}px). Մաքսիմալ չափն է {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Նկարի բարձրությունը չափազանց փոքր է ({{ height }}px). Մինիմալ չափն է {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Այս արժեքը պետք է լինի օգտագործողի ներկա ծածկագիրը.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Այս արժեքը պետք է ունենա ճիշտ {{ limit }} սիմվոլներ.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z����O�ODSymfony/Component/Validator/Resources/translations/validators.ar.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>هذه القيمة يجب أن تكون خاطئة.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>هذه القيمة يجب أن تكون حقيقية.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>هذه القيمة يجب ان تكون من نوع {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>هذه القيمة يجب ان تكون فارغة.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>القيمة المختارة ليست خيارا صحيحا.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>يجب ان تختار {{ limit }} اختيار على الاقل.|يجب ان تختار {{ limit }} اختيار على الاقل.|يجب ان تختار {{ limit }} اختيارات على الاقل.|يجب ان تختار {{ limit }} اختيار على الاقل.|يجب ان تختار {{ limit }} اختيار على الاقل.|يجب ان تختار {{ limit }} اختيار على الاقل.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>يجب ان تختار {{ limit }} اختيار على الاكثر.|يجب ان تختار {{ limit }} اختيار على الاكثر.|يجب ان تختار {{ limit }} اختيارات على الاكثر.|يجب ان تختار {{ limit }} اختيار على الاكثر.|يجب ان تختار {{ limit }} اختيار على الاكثر.|يجب ان تختار {{ limit }} اختيار على الاكثر.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>واحد أو أكثر من القيم المعطاه خاطئ.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>القيم {{ fields }} لم تكن متوقعة.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>القيم {{ fields }} مفقودة.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>هذه القيمة ليست تاريخا صالحا.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>هذه القيمة ليست تاريخا و وقتا صالحا.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>هذه القيمة ليست عنوان بريد إلكتروني صحيح.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>لا يمكن العثور على الملف.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>الملف غير قابل للقراءة.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>الملف كبير جدا ({{ size }} {{ suffix }}).اقصى مساحه مسموح بها ({{ limit }} {{ suffix }}).</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>نوع الملف غير صحيح ({{ type }}). الانواع المسموح بها هى {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>هذه القيمة يجب ان تكون {{ limit }} او اقل.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حرف او اقل.|هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حرف او اقل.|هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حروف او اقل.|هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حرف او اقل.|هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حرف او اقل.|هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حرف او اقل.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>هذه القيمة يجب ان تكون {{ limit }} او اكثر.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حرف او اكثر.|هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حرف او اكثر.|هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حروف او اكثر.|هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حرف او اكثر.|هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حرف او اكثر.|هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حرف او اكثر.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>هذه القيمة يجب الا تكون فارغة.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>هذه القيمة يجب الا تكون فارغة.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>هذه القيمة يجب ان تكون فارغة.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>هذه القيمة غير صحيحة.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>هذه القيمة ليست وقت صحيح.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>هذه القيمة ليست رابط الكترونى صحيح.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>القيمتان يجب ان تكونا متساويتان.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>الملف كبير جدا. اقصى مساحه مسموح بها {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>الملف كبير جدا.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>لم استطع استقبال الملف.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>هذه القيمة يجب ان تكون رقم.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>هذا الملف ليس صورة صحيحة.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>هذه القيمة ليست عنوان رقمى صحيح.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>هذه القيمة ليست لغة صحيحة.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>هذه القيمة ليست موقع صحيح.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>هذه القيمة ليست بلدا صالحا.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>هذه القيمة مستخدمة بالفعل.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>لم استطع معرفة حجم الصورة.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>عرض الصورة كبير جدا ({{ width }}px). اقصى عرض مسموح به هو{{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>عرض الصورة صغير جدا ({{ width }}px). اقل عرض مسموح به هو{{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>طول الصورة كبير جدا ({{ height }}px). اقصى طول مسموح به هو{{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>طول الصورة صغير جدا ({{ height }}px). اقل طول مسموح به هو{{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>هذه القيمة يجب ان تكون كلمة سر المستخدم الحالية.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>هذه القيمة يجب ان تحتوى على {{ limit }} حرف فقط.|هذه القيمة يجب ان تحتوى على {{ limit }} حرف فقط.|هذه القيمة يجب ان تحتوى على {{ limit }} حروف فقط.|هذه القيمة يجب ان تحتوى على {{ limit }} حرف فقط.|هذه القيمة يجب ان تحتوى على {{ limit }} حرف فقط.|هذه القيمة يجب ان تحتوى على {{ limit }} حرف فقط.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>تم استقبال جزء من الملف فقط.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>لم يتم ارسال اى ملف.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>لم يتم تهيئة حافظة مؤقتة فى ملف php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>لم استطع كتابة الملف المؤقت.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>احد اضافات PHP تسببت فى فشل استقبال الملف.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اكثر.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اكثر.|هذه المجموعة يجب ان تحتوى على {{ limit }} عناصر او اكثر.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اكثر.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اكثر.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اكثر.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اقل.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اقل.|هذه المجموعة يجب ان تحتوى على {{ limit }} عناصر او اقل.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اقل.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اقل.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اقل.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر فقط.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر فقط.|هذه المجموعة يجب ان تحتوى على {{ limit }} عناصر فقط.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر فقط.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر فقط.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر فقط.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>رقم البطاقه غير صحيح.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>نوع البطاقه غير مدعوم او الرقم غير صحيح.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>الرقم IBAN (رقم الحساب المصرفي الدولي) الذي تم إدخاله غير صالح.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>هذه القيمة ليست ISBN-10 صالحة.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>هذه القيمة ليست ISBN-13 صالحة.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>هذه القيمة ليست ISBN-10 صالحة ولا ISBN-13 صالحة.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>هذه القيمة ليست ISSN صالحة.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>العُملة غير صحيحة.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>القيمة يجب ان تساوي {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>القيمة يجب ان تكون اعلي من {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>القيمة يجب ان تكون مساوية او اعلي من {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>القيمة يجب ان تطابق {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>القيمة يجب ان تكون اقل من {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>القيمة يجب ان تساوي او تقل عن {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>القيمة يجب ان لا تساوي {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>القيمة يجب ان لا تطابق {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z�1�^�4�4ISymfony/Component/Validator/Resources/translations/validators.sr_Latn.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Vrednost treba da bude netačna.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Vrednost treba da bude tačna.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Vrednost treba da bude tipa {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Vrednost treba da bude prazna.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Vrednost treba da bude jedna od ponuđenih.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Izaberite bar {{ limit }} mogućnost.|Izaberite bar {{ limit }} mogućnosti.|Izaberite bar {{ limit }} mogućnosti.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Izaberite najviše {{ limit }} mogućnost.|Izaberite najviše {{ limit }} mogućnosti.|Izaberite najviše {{ limit }} mogućnosti.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Jedna ili više vrednosti je nevalidna.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Polja {{ fields }} nisu bila očekivana.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Polja {{ fields }} nedostaju.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Vrednost nije validan datum.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Vrednost nije validan datum-vreme.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Vrednost nije validna adresa elektronske pošte.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Datoteka ne može biti pronađena.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Datoteka nije čitljiva.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Datoteka je prevelika ({{ size }} {{ suffix }}). Najveća dozvoljena veličina je {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Mime tip datoteke nije validan ({{ type }}). Dozvoljeni mime tipovi su {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Vrednost treba da bude {{ limit }} ili manje.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Vrednost je predugačka. Treba da ima {{ limit }} karakter ili manje.|Vrednost je predugačka. Treba da ima {{ limit }} karaktera ili manje.|Vrednost je predugačka. Treba da ima {{ limit }} karaktera ili manje.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Vrednost treba da bude {{ limit }} ili više.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Vrednost je prekratka. Treba da ima {{ limit }} karakter ili više.|Vrednost je prekratka. Treba da ima {{ limit }} karaktera ili više.|Vrednost je prekratka. Treba da ima {{ limit }} karaktera ili više.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Vrednost ne treba da bude prazna.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Vrednost ne treba da bude null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Vrednost treba da bude null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Vrednost je nevalidna.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Vrednost nije validno vreme.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Vrednost nije validan URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Obe vrednosti treba da budu jednake.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Datoteka je prevelika. Najveća dozvoljena veličina je {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Datoteka je prevelika.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Datoteka ne može biti otpremljena.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Vrednost treba da bude validan broj.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Ova datoteka nije validna slika.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Ovo nije validna IP adresa.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Vrednost nije validan jezik.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Vrednost nije validan lokal.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Vrednost nije validna zemlja.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Vrednost je već iskorišćena.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Veličina slike ne može biti određena.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Širina slike je prevelika ({{ width }}px). Najeća dozvoljena širina je {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Širina slike je premala ({{ width }}px). Najmanja dozvoljena širina je {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Visina slike je prevelika ({{ height }}px). Najeća dozvoljena visina je {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Visina slike je premala ({{ height }}px). Najmanja dozvoljena visina je {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Vrednost treba da bude trenutna korisnička lozinka.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Vrednost treba da ima tačno {{ limit }} karakter.|Vrednost treba da ima tačno {{ limit }} karaktera.|Vrednost treba da ima tačno {{ limit }} karaktera.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Datoteka je samo parcijalno otpremljena.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Datoteka nije otpremljena.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Privremeni direktorijum nije konfigurisan u php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Nemoguće pisanje privremene datoteke na disk.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>PHP ekstenzija je prouzrokovala neuspeh otpremanja datoteke.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Ova kolekcija treba da sadrži {{ limit }} ili više elemenata.|Ova kolekcija treba da sadrži {{ limit }} ili više elemenata.|Ova kolekcija treba da sadrži {{ limit }} ili više elemenata.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Ova kolekcija treba da sadrži {{ limit }} ili manje elemenata.|Ova kolekcija treba da sadrži {{ limit }} ili manje elemenata.|Ova kolekcija treba da sadrži {{ limit }} ili manje elemenata.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Ova kolekcija treba da sadrži tačno {{ limit }} element.|Ova kolekcija treba da sadrži tačno {{ limit }} elementa.|Ova kolekcija treba da sadrži tačno {{ limit }} elemenata.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Nevalidan broj kartice.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Nevalidan broj kartice ili tip kartice nije podržan.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z@T'%�B�BDSymfony/Component/Validator/Resources/translations/validators.vi.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Giá trị này phải là sai.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Giá trị này phải là đúng.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Giá trị này phải là kiểu  {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Giá trị này phải rỗng.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Giá trị bạn vừa chọn không hợp lệ.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Bạn phải chọn ít nhất {{ limit }} lựa chọn.|Bạn phải chọn ít nhất {{ limit }} lựa chọn.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Bạn phải chọn nhiều nhất {{ limit }} lựa chọn.|Bạn phải chọn nhiều  nhất {{ limit }} lựa chọn.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Một hoặc nhiều giá trị được chọn không hợp lệ.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Trường có tên {{ fields }} không được chấp nhận.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Trường có tên {{ fields }} không tìm thấy.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Giá trị không phải là ngày hợp lệ.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Giá trị không phải là ngày tháng hợp lệ.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Giá trị này không phải là email hợp lệ.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Tập tin không tìm thấy.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Tập tin không thể đọc được.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Tập tin quá lớn ({{ size }} {{ suffix }}). Kích thước tối đa cho phép {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Kiểu mime của tập tin không hợp lệ ({{ type }}). Kiểu hợp lệ là {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Giá trị phải bằng hoặc nhỏ hơn {{ limit }}.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Giá trị quá dài. Phải bằng hoặc ít hơn {{ limit }} kí tự.|Giá trị quá dài. Phải bằng hoặc ít hơn {{ limit }} kí tự.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Giá trị phải lớn hơn hoặc bằng {{ limit }}.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Giá trị quá ngắn. Phải hơn hoặc bằng {{ limit }} kí tự.|Giá trị quá ngắn. Phải hơn hoặc bằng {{ limit }} kí tự.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Giá trị không được phép để trống.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Giá trị không được phép rỗng.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Giá trị phải rỗng.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Giá trị không hợp lệ.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Giá trị không phải là thời gian hợp lệ.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Giá trị không phải là địa chỉ URL hợp lệ.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Hai giá trị phải bằng nhau.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Tập tin quá lớn. Kích thước tối đa cho phép là {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Tập tin quá lớn.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Tập tin không thể tải lên.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Giá trị phải là con số.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Tập tin không phải là hình ảnh.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Địa chỉ IP không hợp lệ.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Giá trị không phải là ngôn ngữ hợp lệ.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Giá trị không phải là một bản địa địa phương hợp lệ.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Giá trị không phải là nước hợp lệ.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Giá trị đã được sử dụng.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Kích thước của hình ảnh không thể xác định.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Chiều rộng của hình quá lớn ({{ width }}px). Chiều rộng tối đa phải là {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Chiều rộng của hình quá thấp ({{ width }}px). Chiều rộng tối thiểu phải là {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Chiều cao của hình quá cao ({{ height }}px). Chiều cao tối đa phải là {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Chiều cao của hình quá thấp ({{ height }}px). Chiều cao tối thiểu phải là {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Giá trị này phải là mật khẩu hiện tại của người dùng.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Giá trị phải có chính xác {{ limit }} kí tự.|Giá trị phải có chính xác {{ limit }} kí tự.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Tập tin chỉ được tải lên một phần.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Tập tin không được tải lên.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Thư mục tạm không được định nghĩa trong php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Không thể ghi tập tin tạm ra đĩa.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Một PHP extension đã phá hỏng quá trình tải lên của tập tin.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Danh sách phải chứa {{ limit }} hoặc nhiều hơn thành phần.|Danh sách phải chứa {{ limit }} hoặc nhiều hơn thành phần.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Danh sách phải chứa {{ limit }} hoặc ít hơn thành phần.|Danh sách phải chứa {{ limit }} hoặc ít hơn thành phần.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Danh sách phải chứa chính xác {{ limit }} thành phần.|Danh sách phải chứa chính xác {{ limit }} thành phần.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Số thẻ không hợp lệ.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Thẻ không được hỗ trợ hoặc số thẻ không hợp lệ.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Giá trị không phải là International Bank Account Number (IBAN) hợp lệ.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Giá trị không phải là ISBN-10 hợp lệ.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Giá trị không phải là ISBN-13 hợp lệ.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Giá trị không phải là ISBN-10 hoặc ISBN-13 hợp lệ.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Giá trị không là ISSN hợp lệ.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Giá trị không phải là đơn vi tiền tệ hợp lệ.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Giá trị phải bằng {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Giá trị phải lớn hơn {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Giá trị phải lớn hơn hoặc bằng {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Giá trị phải giống  {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Giá trị phải bé hơn {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Giá trị không được phép nhỏ hơn hoặc bằng {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Giá trị không được phép bằng {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Giá trị không được phép giống như {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>PK��Z��tý5�5DSymfony/Component/Validator/Resources/translations/validators.he.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>הערך צריך להיות שקר.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>הערך צריך להיות אמת.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>הערך צריך להיות מסוג {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>הערך צריך להיות ריק.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>הערך שבחרת אינו חוקי.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>אתה צריך לבחור לפחות {{ limit }} אפשרויות.|אתה צריך לבחור לפחות {{ limit }} אפשרויות.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>אתה צריך לבחור לכל היותר {{ limit }} אפשרויות.|אתה צריך לבחור לכל היותר {{ limit }} אפשרויות.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>אחד או יותר מהערכים אינו חוקי.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>השדות {{ fields }} לא היו צפויים.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>השדות {{ fields }} חסרים.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>הערך אינו תאריך חוקי.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>הערך אינו תאריך ושעה חוקיים.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>כתובת המייל אינה תקינה.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>הקובץ לא נמצא.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>לא ניתן לקרוא את הקובץ.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>הקובץ גדול מדי ({{ size }} {{ suffix }}). הגודל המרבי המותר הוא {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>סוג MIME של הקובץ אינו חוקי ({{ type }}). מותרים סוגי MIME {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>הערך צריל להכיל {{ limit }} תווים לכל היותר.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>הערך ארוך מידי. הוא צריך להכיל {{ limit }} תווים לכל היותר.|הערך ארוך מידי. הוא צריך להכיל {{ limit }} תווים לכל היותר.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>הערך צריך להכיל {{ limit }} תווים לפחות.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>הערך קצר מידיץ הוא צריך להכיל {{ limit }} תווים לפחות.|הערך קצר מידיץ הוא צריך להכיל {{ limit }} תווים לפחות.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>הערך לא אמור להיות ריק.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>הערך לא אמור להיות ריק.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>הערך צריך להיות ריק.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>הערך אינו חוקי.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>הערך אינו זמן תקין.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>זאת אינה כתובת אתר תקינה.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>שני הערכים צריכים להיות שווים.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>הקובץ גדול מדי. הגודל המרבי המותר הוא {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>הקובץ גדול מדי.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>לא ניתן לעלות את הקובץ.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>הערך צריך להיות מספר חוקי.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>הקובץ הזה אינו תמונה תקינה.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>זו אינה כתובת IP חוקית.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>הערך אינו שפה חוקית.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>הערך אינו אזור תקף.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>הערך אינו ארץ חוקית.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>הערך כבר בשימוש.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>לא ניתן לקבוע את גודל התמונה.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>רוחב התמונה גדול מדי ({{ width }}px). הרוחב המקסימלי הוא {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>רוחב התמונה קטן מדי ({{ width }}px). הרוחב המינימלי הוא {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>גובה התמונה גדול מדי ({{ height }}px). הגובה המקסימלי הוא {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>גובה התמונה קטן מדי ({{ height }}px). הגובה המינימלי הוא {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>הערך צריך להיות סיסמת המשתמש הנוכחי.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>הערך צריך להיות בדיוק {{ limit }} תווים.|הערך צריך להיות בדיוק {{ limit }} תווים.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>הקובץ הועלה באופן חלקי.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>הקובץ לא הועלה.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>לא הוגדרה תיקייה זמנית ב php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>לא ניתן לכתוב קובץ זמני לדיסק.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>סיומת PHP גרם להעלאה להיכשל.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>האוסף אמור להכיל {{ limit }} אלמנטים או יותר.|האוסף אמור להכיל {{ limit }} אלמנטים או יותר.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>האוסף אמור להכיל {{ limit }} אלמנטים או פחות.|האוסף אמור להכיל {{ limit }} אלמנטים או פחות.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>האוסף צריך להכיל בדיוק {{ limit }} אלמנטים.|האוסף צריך להכיל בדיוק {{ limit }} אלמנטים.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>מספר הכרטיס אינו חוקי.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>סוג הכרטיס אינו נתמך או לא חוקי.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z��D��<Symfony/Component/Validator/Constraints/NotNullValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class NotNullValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value) {
            $this->context->addViolation($constraint->message);
        }
    }
}
PK��ZD~�SS2Symfony/Component/Validator/Constraints/Choice.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Choice extends Constraint
{
    public $choices;
    public $callback;
    public $multiple = false;
    public $strict = false;
    public $min = null;
    public $max = null;
    public $message = 'The value you selected is not a valid choice.';
    public $multipleMessage = 'One or more of the given values is invalid.';
    public $minMessage = 'You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.';
    public $maxMessage = 'You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.';

    /**
     * {@inheritDoc}
     */
    public function getDefaultOption()
    {
        return 'choices';
    }
}
PK��Z�~%ɋ�1Symfony/Component/Validator/Constraints/Valid.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Valid extends Constraint
{
    public $traverse = true;

    public $deep = false;

    public function __construct($options = null)
    {
        if (is_array($options) && array_key_exists('groups', $options)) {
            throw new ConstraintDefinitionException(sprintf('The option "groups" is not supported by the constraint %s', __CLASS__));
        }

        parent::__construct($options);
    }
}
PK��Z�+��6Symfony/Component/Validator/Constraints/NotEqualTo.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * @Annotation
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class NotEqualTo extends AbstractComparison
{
    public $message = 'This value should not be equal to {{ compared_value }}.';
}
PK��Zm�Լ\\CSymfony/Component/Validator/Constraints/NotIdenticalToValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * Validates values aren't identical (!==).
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class NotIdenticalToValidator extends AbstractComparisonValidator
{
    /**
     * @inheritDoc
     */
    protected function compareValues($value1, $value2)
    {
        return $value1 !== $value2;
    }
}
PK��ZĿ:�KK6Symfony/Component/Validator/Constraints/Expression.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class Expression extends Constraint
{
    public $message = 'This value is not valid.';
    public $expression;

    /**
     * {@inheritDoc}
     */
    public function getDefaultOption()
    {
        return 'expression';
    }

    /**
     * {@inheritDoc}
     */
    public function getRequiredOptions()
    {
        return array('expression');
    }

    /**
     * {@inheritDoc}
     */
    public function getTargets()
    {
        return array(self::CLASS_CONSTRAINT, self::PROPERTY_CONSTRAINT);
    }

    /**
     * {@inheritDoc}
     */
    public function validatedBy()
    {
        return 'validator.expression';
    }
}
PK��Z�خ
zz?Symfony/Component/Validator/Constraints/Collection/Optional.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints\Collection;

use Symfony\Component\Validator\Constraints\Optional as BaseOptional;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated in 2.3, to be removed in 3.0. Use
 *             {@link \Symfony\Component\Validator\Constraints\Optional} instead.
 */
class Optional extends BaseOptional
{
}
PK��Z\,y�zz?Symfony/Component/Validator/Constraints/Collection/Required.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints\Collection;

use Symfony\Component\Validator\Constraints\Required as BaseRequired;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated in 2.3, to be removed in 3.0. Use
 *             {@link \Symfony\Component\Validator\Constraints\Required} instead.
 */
class Required extends BaseRequired
{
}
PK��Z
��n��?Symfony/Component/Validator/Constraints/CollectionValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class CollectionValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value) {
            return;
        }

        if (!is_array($value) && !($value instanceof \Traversable && $value instanceof \ArrayAccess)) {
            throw new UnexpectedTypeException($value, 'array or Traversable and ArrayAccess');
        }

        $group = $this->context->getGroup();

        foreach ($constraint->fields as $field => $fieldConstraint) {
            if (
                // bug fix issue #2779
                (is_array($value) && array_key_exists($field, $value)) ||
                ($value instanceof \ArrayAccess && $value->offsetExists($field))
            ) {
                foreach ($fieldConstraint->constraints as $constr) {
                    $this->context->validateValue($value[$field], $constr, '['.$field.']', $group);
                }
            } elseif (!$fieldConstraint instanceof Optional && !$constraint->allowMissingFields) {
                $this->context->addViolationAt('['.$field.']', $constraint->missingFieldsMessage, array(
                    '{{ field }}' => $field
                ), null);
            }
        }

        if (!$constraint->allowExtraFields) {
            foreach ($value as $field => $fieldValue) {
                if (!isset($constraint->fields[$field])) {
                    $this->context->addViolationAt('['.$field.']', $constraint->extraFieldsMessage, array(
                        '{{ field }}' => $field
                    ), $fieldValue);
                }
            }
        }
    }
}
PK��Z��y:Symfony/Component/Validator/Constraints/BlankValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class BlankValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if ('' !== $value && null !== $value) {
            $this->context->addViolation($constraint->message, array('{{ value }}' => $value));
        }
    }
}
PK��Z�+����0Symfony/Component/Validator/Constraints/Iban.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 */
class Iban extends Constraint
{
    public $message = 'This is not a valid International Bank Account Number (IBAN).';
}
PK��Z����	�	=Symfony/Component/Validator/Constraints/CallbackValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;

/**
 * Validator for Callback constraint
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class CallbackValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($object, Constraint $constraint)
    {
        if (null === $object) {
            return;
        }

        if (null !== $constraint->callback && null !== $constraint->methods) {
            throw new ConstraintDefinitionException(
                'The Callback constraint supports either the option "callback" ' .
                'or "methods", but not both at the same time.'
            );
        }

        // has to be an array so that we can differentiate between callables
        // and method names
        if (null !== $constraint->methods && !is_array($constraint->methods)) {
            throw new UnexpectedTypeException($constraint->methods, 'array');
        }

        $methods = $constraint->methods ?: array($constraint->callback);

        foreach ($methods as $method) {
            if (is_array($method) || $method instanceof \Closure) {
                if (!is_callable($method)) {
                    throw new ConstraintDefinitionException(sprintf('"%s::%s" targeted by Callback constraint is not a valid callable', $method[0], $method[1]));
                }

                call_user_func($method, $object, $this->context);
            } else {
                if (!method_exists($object, $method)) {
                    throw new ConstraintDefinitionException(sprintf('Method "%s" targeted by Callback constraint does not exist', $method));
                }

                $reflMethod = new \ReflectionMethod($object, $method);

                if ($reflMethod->isStatic()) {
                    $reflMethod->invoke(null, $object, $this->context);
                } else {
                    $reflMethod->invoke($object, $this->context);
                }
            }
        }
    }
}
PK��Z�}�&&2Symfony/Component/Validator/Constraints/Length.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\MissingOptionsException;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Length extends Constraint
{
    public $maxMessage = 'This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.';
    public $minMessage = 'This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.';
    public $exactMessage = 'This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.';
    public $max;
    public $min;
    public $charset = 'UTF-8';

    public function __construct($options = null)
    {
        if (null !== $options && !is_array($options)) {
            $options = array(
                'min' => $options,
                'max' => $options,
            );
        }

        parent::__construct($options);

        if (null === $this->min && null === $this->max) {
            throw new MissingOptionsException(sprintf('Either option "min" or "max" must be given for constraint %s', __CLASS__), array('min', 'max'));
        }
    }
}
PK��Z�b�=nn9Symfony/Component/Validator/Constraints/IsbnValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * Validates whether the value is a valid ISBN-10 or ISBN-13.
 *
 * @author The Whole Life To Learn <thewholelifetolearn@gmail.com>
 *
 * @see https://en.wikipedia.org/wiki/Isbn
 */
class IsbnValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
            throw new UnexpectedTypeException($value, 'string');
        }

        if (!is_numeric($value)) {
            $value = str_replace('-', '', $value);
        }

        $validation = 0;
        $value = strtoupper($value);
        $valueLength = strlen($value);

        if (10 === $valueLength && null !== $constraint->isbn10) {
            for ($i = 0; $i < 10; $i++) {
                if ($value[$i] == 'X') {
                    $validation += 10 * intval(10 - $i);
                } else {
                    $validation += intval($value[$i]) * intval(10 - $i);
                }
            }

            if ($validation % 11 != 0) {
                if (null !== $constraint->isbn13) {
                    $this->context->addViolation($constraint->bothIsbnMessage);
                } else {
                    $this->context->addViolation($constraint->isbn10Message);
                }
            }
        } elseif (13 === $valueLength && null !== $constraint->isbn13) {
            for ($i = 0; $i < 13; $i += 2) {
                $validation += intval($value[$i]);
            }
            for ($i = 1; $i < 12; $i += 2) {
                $validation += intval($value[$i]) * 3;
            }

            if ($validation % 10 != 0) {
                if (null !== $constraint->isbn10) {
                    $this->context->addViolation($constraint->bothIsbnMessage);
                } else {
                    $this->context->addViolation($constraint->isbn13Message);
                }
            }
        } else {
            if (null !== $constraint->isbn10 && null !== $constraint->isbn13) {
                $this->context->addViolation($constraint->bothIsbnMessage);
            } elseif (null !== $constraint->isbn10) {
                $this->context->addViolation($constraint->isbn10Message);
            } else {
                $this->context->addViolation($constraint->isbn13Message);
            }
        }
    }
}
PK��Z�<W���:Symfony/Component/Validator/Constraints/RegexValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * Validates whether a value match or not given regexp pattern
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 * @author Joseph Bielawski <stloyd@gmail.com>
 *
 * @api
 */
class RegexValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
            throw new UnexpectedTypeException($value, 'string');
        }

        $value = (string) $value;

        if ($constraint->match xor preg_match($constraint->pattern, $value)) {
            $this->context->addViolation($constraint->message, array('{{ value }}' => $value));
        }
    }
}
PK��Z^r��

4Symfony/Component/Validator/Constraints/Language.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Language extends Constraint
{
    public $message = 'This value is not a valid language.';
}
PK��Z���,,0Symfony/Component/Validator/Constraints/Isbn.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\MissingOptionsException;

/**
 * @Annotation
 *
 * @author The Whole Life To Learn <thewholelifetolearn@gmail.com>
 */
class Isbn extends Constraint
{
    public $isbn10Message = 'This value is not a valid ISBN-10.';
    public $isbn13Message = 'This value is not a valid ISBN-13.';
    public $bothIsbnMessage = 'This value is neither a valid ISBN-10 nor a valid ISBN-13.';
    public $isbn10;
    public $isbn13;

    public function __construct($options = null)
    {
        if (null !== $options && !is_array($options)) {
            $options = array(
                'isbn10' => $options,
                'isbn13' => $options,
            );
        }

        parent::__construct($options);

        if (null === $this->isbn10 && null === $this->isbn13) {
            throw new MissingOptionsException(sprintf('Either option "isbn10" or "isbn13" must be given for constraint "%s".', __CLASS__), array('isbn10', 'isbn13'));
        }
    }
}
PK��Z�EW^��<Symfony/Component/Validator/Constraints/CountryValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Intl\Intl;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * Validates whether a value is a valid country code
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class CountryValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
            throw new UnexpectedTypeException($value, 'string');
        }

        $value = (string) $value;
        $countries = Intl::getRegionBundle()->getCountryNames();

        if (!isset($countries[$value])) {
            $this->context->addViolation($constraint->message, array('{{ value }}' => $value));
        }
    }
}
PK��Zzet�	�	?Symfony/Component/Validator/Constraints/ExpressionValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
use Symfony\Component\PropertyAccess\PropertyPath;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use Symfony\Component\Validator\Exception\RuntimeException;

/**
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Bernhard Schussek <bschussek@symfony.com>
 */
class ExpressionValidator extends ConstraintValidator
{
    /**
     * @var PropertyAccessorInterface
     */
    private $propertyAccessor;

    /**
     * @var ExpressionLanguage
     */
    private $expressionLanguage;

    public function __construct(PropertyAccessorInterface $propertyAccessor)
    {
        $this->propertyAccessor = $propertyAccessor;
    }

    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        $variables = array();

        if (null === $this->context->getPropertyName()) {
            $variables['this'] = $value;
        } else {
            // Extract the object that the property belongs to from the object
            // graph
            $path = new PropertyPath($this->context->getPropertyPath());
            $parentPath = $path->getParent();
            $root = $this->context->getRoot();

            $variables['value'] = $value;
            $variables['this'] = $parentPath ? $this->propertyAccessor->getValue($root, $parentPath) : $root;
        }

        if (!$this->getExpressionLanguage()->evaluate($constraint->expression, $variables)) {
            $this->context->addViolation($constraint->message);
        }
    }

    private function getExpressionLanguage()
    {
        if (null === $this->expressionLanguage) {
            if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
                throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
            }
            $this->expressionLanguage = new ExpressionLanguage();
        }

        return $this->expressionLanguage;
    }
}
PK��Z�	�00/Symfony/Component/Validator/Constraints/Url.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Url extends Constraint
{
    public $message = 'This value is not a valid URL.';
    public $protocols = array('http', 'https');
}
PK��Z�V`���9Symfony/Component/Validator/Constraints/IbanValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

/**
 * @author Manuel Reinhard <manu@sprain.ch>
 * @author Michael Schummel
 * @link http://www.michael-schummel.de/2007/10/05/iban-prufung-mit-php/
 */
class IbanValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        // An IBAN without a country code is not an IBAN.
        if (0 === preg_match('/[A-Z]/', $value)) {
            $this->context->addViolation($constraint->message, array('{{ value }}' => $value));

            return;
        }

        $teststring = preg_replace('/\s+/', '', $value);

        if (strlen($teststring) < 4) {
            $this->context->addViolation($constraint->message, array('{{ value }}' => $value));

            return;
        }

        $teststring = substr($teststring, 4)
            .strval(ord($teststring{0}) - 55)
            .strval(ord($teststring{1}) - 55)
            .substr($teststring, 2, 2);

        $teststring = preg_replace_callback('/[A-Z]/', function ($letter) {
            return intval(ord(strtolower($letter[0])) - 87);
        }, $teststring);

        $rest = 0;
        $strlen = strlen($teststring);
        for ($pos = 0; $pos < $strlen; $pos += 7) {
            $part = strval($rest).substr($teststring, $pos, 7);
            $rest = intval($part) % 97;
        }

        if ($rest != 1) {
            $this->context->addViolation($constraint->message, array('{{ value }}' => $value));

            return;
        }
    }
}
PK��Z��vbb@Symfony/Component/Validator/Constraints/GreaterThanValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * Validates values are greater than the previous (>).
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class GreaterThanValidator extends AbstractComparisonValidator
{
    /**
     * @inheritDoc
     */
    protected function compareValues($value1, $value2)
    {
        return $value1 > $value2;
    }
}
PK��ZS탟0Symfony/Component/Validator/Constraints/Date.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Date extends Constraint
{
    public $message = 'This value is not a valid date.';
}
PK��Z�|4XX8Symfony/Component/Validator/Constraints/UrlValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class UrlValidator extends ConstraintValidator
{
    const PATTERN = '~^
            (%s)://                                 # protocol
            (
                ([\pL\pN\pS-]+\.)+([\pL]|xn\-\-[\pL\pN-]+)+                   # a domain name
                    |                                     #  or
                \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}      # a IP address
                    |                                     #  or
                \[
                    (?:(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){6})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:::(?:(?:(?:[0-9a-f]{1,4})):){5})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){4})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,1}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){3})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,2}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){2})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,3}(?:(?:[0-9a-f]{1,4})))?::(?:(?:[0-9a-f]{1,4})):)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,4}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,5}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,6}(?:(?:[0-9a-f]{1,4})))?::))))
                \]  # a IPv6 address
            )
            (:[0-9]+)?                              # a port (optional)
            (/?|/\S+)                               # a /, nothing or a / with something
        $~ixu';

    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
            throw new UnexpectedTypeException($value, 'string');
        }

        $value = (string) $value;

        $pattern = sprintf(static::PATTERN, implode('|', $constraint->protocols));

        if (!preg_match($pattern, $value)) {
            $this->context->addViolation($constraint->message, array('{{ value }}' => $value));
        }
    }
}
PK��Zw���3Symfony/Component/Validator/Constraints/NotNull.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class NotNull extends Constraint
{
    public $message = 'This value should not be null.';
}
PK��ZS�n���0Symfony/Component/Validator/Constraints/Null.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Null extends Constraint
{
    public $message = 'This value should be null.';
}
PK��Z�o�o��:Symfony/Component/Validator/Constraints/RangeValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class RangeValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value) {
            return;
        }

        if (!is_numeric($value)) {
            $this->context->addViolation($constraint->invalidMessage, array(
                '{{ value }}' => $value,
            ));

            return;
        }

        if (null !== $constraint->max && $value > $constraint->max) {
            $this->context->addViolation($constraint->maxMessage, array(
                '{{ value }}' => $value,
                '{{ limit }}' => $constraint->max,
            ));

            return;
        }

        if (null !== $constraint->min && $value < $constraint->min) {
            $this->context->addViolation($constraint->minMessage, array(
                '{{ value }}' => $value,
                '{{ limit }}' => $constraint->min,
            ));
        }
    }
}
PK��Z�

4Symfony/Component/Validator/Constraints/Currency.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Miha Vrhovnik <miha.vrhovnik@pagein.si>
 *
 * @api
 */
class Currency extends Constraint
{
    public $message = 'This value is not a valid currency.';
}
PK��Zrs+���4Symfony/Component/Validator/Constraints/Optional.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class Optional extends Existence
{
}
PK��Z����449Symfony/Component/Validator/Constraints/IssnValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * Validates whether the value is a valid ISSN.
 *
 * @author Antonio J. García Lagar <aj@garcialagar.es>
 *
 * @see https://en.wikipedia.org/wiki/Issn
 */
class IssnValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
            throw new UnexpectedTypeException($value, 'string');
        }

        // Compose regex pattern
        $digitsPattern = $constraint->requireHyphen ? '\d{4}-\d{3}' : '\d{4}-?\d{3}';
        $checksumPattern = $constraint->caseSensitive ? '[\d|X]' : '[\d|X|x]';
        $pattern = "/^".$digitsPattern.$checksumPattern."$/";

        if (!preg_match($pattern, $value)) {
            $this->context->addViolation($constraint->message);
        } else {
            $digits = str_split(strtoupper(str_replace('-', '', $value)));

            $sum = 0;
            for ($i = 8; $i > 1; $i--) {
                $sum += $i * (int) array_shift($digits);
            }

            $checksum = 'X' == reset($digits) ? 10 : (int) reset($digits);

            if (0 != ($sum + $checksum) % 11) {
                $this->context->addViolation($constraint->message);
            }
        }
    }
}
PK��Z�qp""0Symfony/Component/Validator/Constraints/File.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class File extends Constraint
{
    public $maxSize = null;
    public $mimeTypes = array();
    public $notFoundMessage = 'The file could not be found.';
    public $notReadableMessage = 'The file is not readable.';
    public $maxSizeMessage = 'The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.';
    public $mimeTypesMessage = 'The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.';

    public $uploadIniSizeErrorMessage   = 'The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.';
    public $uploadFormSizeErrorMessage  = 'The file is too large.';
    public $uploadPartialErrorMessage   = 'The file was only partially uploaded.';
    public $uploadNoFileErrorMessage    = 'No file was uploaded.';
    public $uploadNoTmpDirErrorMessage  = 'No temporary folder was configured in php.ini.';
    public $uploadCantWriteErrorMessage = 'Cannot write temporary file to disk.';
    public $uploadExtensionErrorMessage = 'A PHP extension caused the upload to fail.';
    public $uploadErrorMessage          = 'The file could not be uploaded.';
}
PK��Z5�ʟ��9Symfony/Component/Validator/Constraints/DateValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class DateValidator extends ConstraintValidator
{
    const PATTERN = '/^(\d{4})-(\d{2})-(\d{2})$/';

    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value || $value instanceof \DateTime) {
            return;
        }

        if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
            throw new UnexpectedTypeException($value, 'string');
        }

        $value = (string) $value;

        if (!preg_match(static::PATTERN, $value, $matches) || !checkdate($matches[2], $matches[3], $matches[1])) {
            $this->context->addViolation($constraint->message, array('{{ value }}' => $value));
        }
    }
}
PK��Z0@���9Symfony/Component/Validator/Constraints/NullValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class NullValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null !== $value) {
            if (is_object($value)) {
                $value = get_class($value);
            } elseif (is_array($value)) {
                $value = 'Array';
            }

            $this->context->addViolation($constraint->message, array('{{ value }}' => $value));
        }
    }
}
PK��Z�>
i//5Symfony/Component/Validator/Constraints/Existence.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
abstract class Existence extends Constraint
{
    public $constraints = array();

    public function getDefaultOption()
    {
        return 'constraints';
    }
}
PK��ZtUה�4Symfony/Component/Validator/Constraints/Required.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class Required extends Existence
{
}
PK��Zm��\\>Symfony/Component/Validator/Constraints/AbstractComparison.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;

/**
 * Used for the comparison of values.
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
abstract class AbstractComparison extends Constraint
{
    public $message;
    public $value;

    /**
     * {@inheritDoc}
     */
    public function __construct($options = null)
    {
        if (is_array($options) && !isset($options['value'])) {
            throw new ConstraintDefinitionException(sprintf(
                'The %s constraint requires the "value" option to be set.',
                get_class($this)
            ));
        }

        parent::__construct($options);
    }

    /**
     * {@inheritDoc}
     */
    public function getDefaultOption()
    {
        return 'value';
    }
}
PK��Zc��y

4Symfony/Component/Validator/Constraints/DateTime.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class DateTime extends Constraint
{
    public $message = 'This value is not a valid datetime.';
}
PK��Zl˘��
�
7Symfony/Component/Validator/Constraints/IpValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * Validates whether a value is a valid IP address
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 * @author Joseph Bielawski <stloyd@gmail.com>
 *
 * @api
 */
class IpValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
            throw new UnexpectedTypeException($value, 'string');
        }

        $value = (string) $value;

        switch ($constraint->version) {
            case Ip::V4:
               $flag = FILTER_FLAG_IPV4;
               break;

            case Ip::V6:
               $flag = FILTER_FLAG_IPV6;
               break;

            case Ip::V4_NO_PRIV:
               $flag = FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE;
               break;

            case Ip::V6_NO_PRIV:
               $flag = FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE;
               break;

            case Ip::ALL_NO_PRIV:
               $flag = FILTER_FLAG_NO_PRIV_RANGE;
               break;

            case Ip::V4_NO_RES:
               $flag = FILTER_FLAG_IPV4 | FILTER_FLAG_NO_RES_RANGE;
               break;

            case Ip::V6_NO_RES:
               $flag = FILTER_FLAG_IPV6 | FILTER_FLAG_NO_RES_RANGE;
               break;

            case Ip::ALL_NO_RES:
               $flag = FILTER_FLAG_NO_RES_RANGE;
               break;

            case Ip::V4_ONLY_PUBLIC:
               $flag = FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE;
               break;

            case Ip::V6_ONLY_PUBLIC:
               $flag = FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE;
               break;

            case Ip::ALL_ONLY_PUBLIC:
               $flag = FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE;
               break;

            default:
                $flag = null;
                break;
        }

        if (!filter_var($value, FILTER_VALIDATE_IP, $flag)) {
            $this->context->addViolation($constraint->message, array('{{ value }}' => $value));
        }
    }
}
PK��Z�\\=Symfony/Component/Validator/Constraints/LessThanValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * Validates values are less than the previous (<).
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class LessThanValidator extends AbstractComparisonValidator
{
    /**
     * @inheritDoc
     */
    protected function compareValues($value1, $value2)
    {
        return $value1 < $value2;
    }
}
PK��Z�U�4Symfony/Component/Validator/Constraints/NotBlank.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class NotBlank extends Constraint
{
    public $message = 'This value should not be blank.';
}
PK��Z<8�S��:Symfony/Component/Validator/Constraints/ImageValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;

/**
 * Validates whether a value is a valid image file and is valid
 * against minWidth, maxWidth, minHeight and maxHeight constraints
 *
 * @author Benjamin Dulau <benjamin.dulau@gmail.com>
 */
class ImageValidator extends FileValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        $violations = count($this->context->getViolations());

        parent::validate($value, $constraint);

        $failed = count($this->context->getViolations()) !== $violations;

        if ($failed || null === $value || '' === $value) {
            return;
        }

        if (null === $constraint->minWidth && null === $constraint->maxWidth
            && null === $constraint->minHeight && null === $constraint->maxHeight
            && null === $constraint->minRatio && null === $constraint->maxRatio
            && $constraint->allowSquare && $constraint->allowLandscape && $constraint->allowPortrait) {
            return;
        }

        $size = @getimagesize($value);
        if (empty($size) || ($size[0] === 0) || ($size[1] === 0)) {
            $this->context->addViolation($constraint->sizeNotDetectedMessage);

            return;
        }

        $width  = $size[0];
        $height = $size[1];

        if ($constraint->minWidth) {
            if (!ctype_digit((string) $constraint->minWidth)) {
                throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum width', $constraint->minWidth));
            }

            if ($width < $constraint->minWidth) {
                $this->context->addViolation($constraint->minWidthMessage, array(
                    '{{ width }}'    => $width,
                    '{{ min_width }}' => $constraint->minWidth
                ));

                return;
            }
        }

        if ($constraint->maxWidth) {
            if (!ctype_digit((string) $constraint->maxWidth)) {
                throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum width', $constraint->maxWidth));
            }

            if ($width > $constraint->maxWidth) {
                $this->context->addViolation($constraint->maxWidthMessage, array(
                    '{{ width }}'    => $width,
                    '{{ max_width }}' => $constraint->maxWidth
                ));

                return;
            }
        }

        if ($constraint->minHeight) {
            if (!ctype_digit((string) $constraint->minHeight)) {
                throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum height', $constraint->minHeight));
            }

            if ($height < $constraint->minHeight) {
                $this->context->addViolation($constraint->minHeightMessage, array(
                    '{{ height }}'    => $height,
                    '{{ min_height }}' => $constraint->minHeight
                ));

                return;
            }
        }

        if ($constraint->maxHeight) {
            if (!ctype_digit((string) $constraint->maxHeight)) {
                throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum height', $constraint->maxHeight));
            }

            if ($height > $constraint->maxHeight) {
                $this->context->addViolation($constraint->maxHeightMessage, array(
                    '{{ height }}'    => $height,
                    '{{ max_height }}' => $constraint->maxHeight
                ));
            }
        }

        $ratio = $width / $height;

        if (null !== $constraint->minRatio) {
            if (!is_numeric((string) $constraint->minRatio)) {
                throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum ratio', $constraint->minRatio));
            }

            if ($ratio < $constraint->minRatio) {
                $this->context->addViolation($constraint->minRatioMessage, array(
                    '{{ ratio }}' => $ratio,
                    '{{ min_ratio }}' => $constraint->minRatio
                ));
            }
        }

        if (null !== $constraint->maxRatio) {
            if (!is_numeric((string) $constraint->maxRatio)) {
                throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum ratio', $constraint->maxRatio));
            }

            if ($ratio > $constraint->maxRatio) {
                $this->context->addViolation($constraint->maxRatioMessage, array(
                    '{{ ratio }}' => $ratio,
                    '{{ max_ratio }}' => $constraint->maxRatio
                ));
            }
        }

        if (!$constraint->allowSquare && $width == $height) {
            $this->context->addViolation($constraint->allowSquareMessage, array(
                '{{ width }}' => $width,
                '{{ height }}' => $height
            ));
        }

        if (!$constraint->allowLandscape && $width > $height) {
            $this->context->addViolation($constraint->allowLandscapeMessage, array(
                '{{ width }}' => $width,
                '{{ height }}' => $height
            ));
        }

        if (!$constraint->allowPortrait && $width < $height) {
            $this->context->addViolation($constraint->allowPortraitMessage, array(
                '{{ width }}' => $width,
                '{{ height }}' => $height
            ));
        }

    }
}
PK��Z��Lֻ�6Symfony/Component/Validator/Constraints/CardScheme.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * Metadata for the CardSchemeValidator.
 *
 * @Annotation
 */
class CardScheme extends Constraint
{
    public $message = 'Unsupported card type or invalid card number.';
    public $schemes;

    public function getDefaultOption()
    {
        return 'schemes';
    }

    public function getRequiredOptions()
    {
        return array('schemes');
    }
}
PK��Z��"��?Symfony/Component/Validator/Constraints/CardSchemeValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

/**
 * Validates that a card number belongs to a specified scheme.
 *
 * @see http://en.wikipedia.org/wiki/Bank_card_number
 * @see http://www.regular-expressions.info/creditcard.html
 * @author Tim Nagel <t.nagel@infinite.net.au>
 */
class CardSchemeValidator extends ConstraintValidator
{
    protected $schemes = array(
        /**
         * American Express card numbers start with 34 or 37 and have 15 digits.
         */
        'AMEX' => array(
            '/^3[47][0-9]{13}$/'
        ),
        /**
         * China UnionPay cards start with 62 and have between 16 and 19 digits.
         * Please note that these cards do not follow Luhn Algorithm as a checksum.
         */
        'CHINA_UNIONPAY' => array(
            '/^62[0-9]{14,17}$/'
        ),
        /**
         * Diners Club card numbers begin with 300 through 305, 36 or 38. All have 14 digits.
         * There are Diners Club cards that begin with 5 and have 16 digits.
         * These are a joint venture between Diners Club and MasterCard, and should be processed like a MasterCard.
         */
        'DINERS' => array(
            '/^3(?:0[0-5]|[68][0-9])[0-9]{11}$/',
        ),
        /**
         * Discover card numbers begin with 6011, 622126 through 622925, 644 through 649 or 65.
         * All have 16 digits
         */
        'DISCOVER' => array(
            '/^6011[0-9]{12}$/',
            '/^64[4-9][0-9]{13}$/',
            '/^65[0-9]{14}$/',
            '/^622(12[6-9]|1[3-9][0-9]|[2-8][0-9][0-9]|91[0-9]|92[0-5])[0-9]{10}$/'
        ),
        /**
         * InstaPayment cards begin with 637 through 639 and have 16 digits
         */
        'INSTAPAYMENT' => array(
            '/^63[7-9][0-9]{13}$/'
        ),
        /**
         * JCB cards beginning with 2131 or 1800 have 15 digits.
         * JCB cards beginning with 35 have 16 digits.
         */
        'JCB' => array(
            '/^(?:2131|1800|35[0-9]{3})[0-9]{11}$/'
        ),
        /**
         * Laser cards begin with either 6304, 6706, 6709 or 6771 and have between 16 and 19 digits
         */
        'LASER' => array(
            '/^(6304|670[69]|6771)[0-9]{12,15}$/'
        ),
        /**
         * Maestro cards begin with either 5018, 5020, 5038, 5893, 6304, 6759, 6761, 6762, 6763 or 0604
         * They have between 12 and 19 digits
         */
        'MAESTRO' => array(
            '/^(5018|5020|5038|6304|6759|6761|676[23]|0604)[0-9]{8,15}$/'
        ),
        /**
         * All MasterCard numbers start with the numbers 51 through 55. All have 16 digits.
         */
        'MASTERCARD' => array(
            '/^5[1-5][0-9]{14}$/'
        ),
        /**
         * All Visa card numbers start with a 4. New cards have 16 digits. Old cards have 13.
         */
        'VISA' => array(
            '/^4([0-9]{12}|[0-9]{15})$/'
        ),
    );

    /**
     * Validates a creditcard belongs to a specified scheme.
     *
     * @param mixed $value
     * @param Constraint $constraint
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        if (!is_numeric($value)) {
            $this->context->addViolation($constraint->message);

            return;
        }

        $schemes = array_flip((array) $constraint->schemes);
        $schemeRegexes = array_intersect_key($this->schemes, $schemes);

        foreach ($schemeRegexes as $regexes) {
            foreach ($regexes as $regex) {
                if (preg_match($regex, $value)) {
                    return;
                }
            }
        }

        $this->context->addViolation($constraint->message);
    }
}
PK��ZN3�0Symfony/Component/Validator/Constraints/Type.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Type extends Constraint
{
    public $message = 'This value should be of type {{ type }}.';
    public $type;

    /**
     * {@inheritDoc}
     */
    public function getDefaultOption()
    {
        return 'type';
    }

    /**
     * {@inheritDoc}
     */
    public function getRequiredOptions()
    {
        return array('type');
    }
}
PK��Z@vqq9Symfony/Component/Validator/Constraints/FileValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\HttpFoundation\File\File as FileObject;
use Symfony\Component\HttpFoundation\File\UploadedFile;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class FileValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        if ($value instanceof UploadedFile && !$value->isValid()) {
            switch ($value->getError()) {
                case UPLOAD_ERR_INI_SIZE:
                    if ($constraint->maxSize) {
                        if (ctype_digit((string) $constraint->maxSize)) {
                            $maxSize = (int) $constraint->maxSize;
                        } elseif (preg_match('/^\d++k$/', $constraint->maxSize)) {
                            $maxSize = $constraint->maxSize * 1024;
                        } elseif (preg_match('/^\d++M$/', $constraint->maxSize)) {
                            $maxSize = $constraint->maxSize * 1048576;
                        } else {
                            throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum size', $constraint->maxSize));
                        }
                        $maxSize = min(UploadedFile::getMaxFilesize(), $maxSize);
                    } else {
                        $maxSize = UploadedFile::getMaxFilesize();
                    }

                    $this->context->addViolation($constraint->uploadIniSizeErrorMessage, array(
                        '{{ limit }}' => $maxSize,
                        '{{ suffix }}' => 'bytes',
                    ));

                    return;
                case UPLOAD_ERR_FORM_SIZE:
                    $this->context->addViolation($constraint->uploadFormSizeErrorMessage);

                    return;
                case UPLOAD_ERR_PARTIAL:
                    $this->context->addViolation($constraint->uploadPartialErrorMessage);

                    return;
                case UPLOAD_ERR_NO_FILE:
                    $this->context->addViolation($constraint->uploadNoFileErrorMessage);

                    return;
                case UPLOAD_ERR_NO_TMP_DIR:
                    $this->context->addViolation($constraint->uploadNoTmpDirErrorMessage);

                    return;
                case UPLOAD_ERR_CANT_WRITE:
                    $this->context->addViolation($constraint->uploadCantWriteErrorMessage);

                    return;
                case UPLOAD_ERR_EXTENSION:
                    $this->context->addViolation($constraint->uploadExtensionErrorMessage);

                    return;
                default:
                    $this->context->addViolation($constraint->uploadErrorMessage);

                    return;
            }
        }

        if (!is_scalar($value) && !$value instanceof FileObject && !(is_object($value) && method_exists($value, '__toString'))) {
            throw new UnexpectedTypeException($value, 'string');
        }

        $path = $value instanceof FileObject ? $value->getPathname() : (string) $value;

        if (!is_file($path)) {
            $this->context->addViolation($constraint->notFoundMessage, array('{{ file }}' => $path));

            return;
        }

        if (!is_readable($path)) {
            $this->context->addViolation($constraint->notReadableMessage, array('{{ file }}' => $path));

            return;
        }

        if ($constraint->maxSize) {
            if (ctype_digit((string) $constraint->maxSize)) {
                $size = filesize($path);
                $limit = (int) $constraint->maxSize;
                $suffix = 'bytes';
            } elseif (preg_match('/^\d++k$/', $constraint->maxSize)) {
                $size = round(filesize($path) / 1000, 2);
                $limit = (int) $constraint->maxSize;
                $suffix = 'kB';
            } elseif (preg_match('/^\d++M$/', $constraint->maxSize)) {
                $size = round(filesize($path) / 1000000, 2);
                $limit = (int) $constraint->maxSize;
                $suffix = 'MB';
            } else {
                throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum size', $constraint->maxSize));
            }

            if ($size > $limit) {
                $this->context->addViolation($constraint->maxSizeMessage, array(
                    '{{ size }}'    => $size,
                    '{{ limit }}'   => $limit,
                    '{{ suffix }}'  => $suffix,
                    '{{ file }}'    => $path,
                ));

                return;
            }
        }

        if ($constraint->mimeTypes) {
            if (!$value instanceof FileObject) {
                $value = new FileObject($value);
            }

            $mimeTypes = (array) $constraint->mimeTypes;
            $mime = $value->getMimeType();
            $valid = false;

            foreach ($mimeTypes as $mimeType) {
                if ($mimeType === $mime) {
                    $valid = true;
                    break;
                }

                if ($discrete = strstr($mimeType, '/*', true)) {
                    if (strstr($mime, '/', true) === $discrete) {
                        $valid = true;
                        break;
                    }
                }
            }

            if (false === $valid) {
                $this->context->addViolation($constraint->mimeTypesMessage, array(
                    '{{ type }}'    => '"'.$mime.'"',
                    '{{ types }}'   => '"'.implode('", "', $mimeTypes) .'"',
                    '{{ file }}'    => $path,
                ));
            }
        }
    }
}
PK��Z�'����1Symfony/Component/Validator/Constraints/Count.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\MissingOptionsException;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Count extends Constraint
{
    public $minMessage = 'This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.';
    public $maxMessage = 'This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.';
    public $exactMessage = 'This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.';
    public $min;
    public $max;

    public function __construct($options = null)
    {
        if (null !== $options && !is_array($options)) {
            $options = array(
                'min' => $options,
                'max' => $options,
            );
        }

        parent::__construct($options);

        if (null === $this->min && null === $this->max) {
            throw new MissingOptionsException(sprintf('Either option "min" or "max" must be given for constraint %s', __CLASS__), array('min', 'max'));
        }
    }
}
PK��Z�̢�VV@Symfony/Component/Validator/Constraints/IdenticalToValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * Validates values are identical (===).
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class IdenticalToValidator extends AbstractComparisonValidator
{
    /**
     * @inheritDoc
     */
    protected function compareValues($value1, $value2)
    {
        return $value1 === $value2;
    }
}
PK��Zd�X�BB0Symfony/Component/Validator/Constraints/Issn.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Antonio J. García Lagar <aj@garcialagar.es>
 */
class Issn extends Constraint
{
    public $message = 'This value is not a valid ISSN.';
    public $caseSensitive = false;
    public $requireHyphen = false;
}
PK��Z�ଏ�ASymfony/Component/Validator/Constraints/GroupSequenceProvider.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * Annotation to define a group sequence provider
 *
 * @Annotation
 */
class GroupSequenceProvider
{

}
PK��Z��}a��7Symfony/Component/Validator/Constraints/GreaterThan.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * @Annotation
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class GreaterThan extends AbstractComparison
{
    public $message = 'This value should be greater than {{ compared_value }}.';
}
PK��Z�Ǧ��3Symfony/Component/Validator/Constraints/EqualTo.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * @Annotation
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class EqualTo extends AbstractComparison
{
    public $message = 'This value should be equal to {{ compared_value }}.';
}
PK��Zb+��9Symfony/Component/Validator/Constraints/LuhnValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * Validates a PAN using the LUHN Algorithm
 *
 * For a list of example card numbers that are used to test this
 * class, please see the LuhnValidatorTest class.
 *
 * @see    http://en.wikipedia.org/wiki/Luhn_algorithm
 * @author Tim Nagel <t.nagel@infinite.net.au>
 * @author Greg Knapp http://gregk.me/2011/php-implementation-of-bank-card-luhn-algorithm/
 */
class LuhnValidator extends ConstraintValidator
{
    /**
     * Validates a creditcard number with the Luhn algorithm.
     *
     * @param mixed      $value
     * @param Constraint $constraint
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        /**
         * need to work with strings only because long numbers are treated as floats and don't work with strlen
         */
        if (!is_string($value)) {
            throw new UnexpectedTypeException($value, 'string');
        }

        if (!is_numeric($value)) {
            $this->context->addViolation($constraint->message);

            return;
        }

        $length = strlen($value);
        $oddLength = $length % 2;
        for ($sum = 0, $i = $length - 1; $i >= 0; $i--) {
            $digit = (int) $value[$i];
            $sum += (($i % 2) === $oddLength) ? array_sum(str_split($digit * 2)) : $digit;
        }

        if ($sum === 0 || ($sum % 10) !== 0) {
            $this->context->addViolation($constraint->message);
        }
    }
}
PK��Z�ٜ?��0Symfony/Component/Validator/Constraints/True.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class True extends Constraint
{
    public $message = 'This value should be true.';
}
PK��Z?����GSymfony/Component/Validator/Constraints/AbstractComparisonValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

/**
 * Provides a base class for the validation of property comparisons.
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
abstract class AbstractComparisonValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value) {
            return;
        }

        if (!$this->compareValues($value, $constraint->value)) {
            $this->context->addViolation($constraint->message, array(
                '{{ value }}' => $this->valueToString($constraint->value),
                '{{ compared_value }}' => $this->valueToString($constraint->value),
                '{{ compared_value_type }}' => $this->valueToType($constraint->value)
            ));
        }
    }

    /**
     * Returns a string representation of the type of the value.
     *
     * @param  mixed $value
     *
     * @return string
     */
    private function valueToType($value)
    {
        return is_object($value) ? get_class($value) : gettype($value);
    }

    /**
     * Returns a string representation of the value.
     *
     * @param  mixed  $value
     *
     * @return string
     */
    private function valueToString($value)
    {
        if (is_object($value) && method_exists($value, '__toString')) {
            return (string) $value;
        }

        if ($value instanceof \DateTime) {
            return $value->format('Y-m-d H:i:s');
        }

        return var_export($value, true);
    }

    /**
     * Compares the two given values to find if their relationship is valid
     *
     * @param mixed      $value1     The first value to compare
     * @param mixed      $value2     The second value to compare
     *
     * @return Boolean true if the relationship is valid, false otherwise
     */
    abstract protected function compareValues($value1, $value2);
}
PK��Z�̋	�	1Symfony/Component/Validator/Constraints/Regex.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Regex extends Constraint
{
    public $message = 'This value is not valid.';
    public $pattern;
    public $htmlPattern = null;
    public $match = true;

    /**
     * {@inheritDoc}
     */
    public function getDefaultOption()
    {
        return 'pattern';
    }

    /**
     * {@inheritDoc}
     */
    public function getRequiredOptions()
    {
        return array('pattern');
    }

    /**
     * Returns htmlPattern if exists or pattern is convertible.
     *
     * @return string|null
     */
    public function getHtmlPattern()
    {
        // If htmlPattern is specified, use it
        if (null !== $this->htmlPattern) {
            return empty($this->htmlPattern)
                ? null
                : $this->htmlPattern;
        }

        return $this->getNonDelimitedPattern();
    }

    /**
     * Converts the htmlPattern to a suitable format for HTML5 pattern.
     * Example: /^[a-z]+$/ would be converted to [a-z]+
     * However, if options are specified, it cannot be converted
     *
     * Pattern is also ignored if match=false since the pattern should
     * then be reversed before application.
     *
     * @todo reverse pattern in case match=false as per issue #5307
     *
     * @link http://dev.w3.org/html5/spec/single-page.html#the-pattern-attribute
     *
     * @return string|null
     */
    private function getNonDelimitedPattern()
    {
        // If match = false, pattern should not be added to HTML5 validation
        if (!$this->match) {
            return null;
        }

        if (preg_match('/^(.)(\^?)(.*?)(\$?)\1$/', $this->pattern, $matches)) {
            $delimiter = $matches[1];
            $start     = empty($matches[2]) ? '.*' : '';
            $pattern   = $matches[3];
            $end       = empty($matches[4]) ? '.*' : '';

            // Unescape the delimiter in pattern
            $pattern = str_replace('\\'.$delimiter, $delimiter, $pattern);

            return $start.$pattern.$end;
        }

        return null;
    }
}
PK��Z��BB1Symfony/Component/Validator/Constraints/Range.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\MissingOptionsException;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Range extends Constraint
{
    public $minMessage = 'This value should be {{ limit }} or more.';
    public $maxMessage = 'This value should be {{ limit }} or less.';
    public $invalidMessage = 'This value should be a valid number.';
    public $min;
    public $max;

    public function __construct($options = null)
    {
        parent::__construct($options);

        if (null === $this->min && null === $this->max) {
            throw new MissingOptionsException(sprintf('Either option "min" or "max" must be given for constraint %s', __CLASS__), array('min', 'max'));
        }
    }
}
PK��Z[�A���;Symfony/Component/Validator/Constraints/LessThanOrEqual.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * @Annotation
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class LessThanOrEqual extends AbstractComparison
{
    public $message = 'This value should be less than or equal to {{ compared_value }}.';
}
PK��Zq;O3Symfony/Component/Validator/Constraints/Country.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Country extends Constraint
{
    public $message = 'This value is not a valid country.';
}
PK��Z5����:Symfony/Component/Validator/Constraints/EmailValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class EmailValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
            throw new UnexpectedTypeException($value, 'string');
        }

        $value = (string) $value;
        $valid = filter_var($value, FILTER_VALIDATE_EMAIL);

        if ($valid) {
            $host = substr($value, strpos($value, '@') + 1);

            // Check for host DNS resource records
            if ($valid && $constraint->checkMX) {
                $valid = $this->checkMX($host);
            } elseif ($valid && $constraint->checkHost) {
                $valid = $this->checkHost($host);
            }
        }

        if (!$valid) {
            $this->context->addViolation($constraint->message, array('{{ value }}' => $value));
        }
    }

    /**
     * Check DNS Records for MX type.
     *
     * @param string $host Host
     *
     * @return Boolean
     */
    private function checkMX($host)
    {
        return checkdnsrr($host, 'MX');
    }

    /**
     * Check if one of MX, A or AAAA DNS RR exists.
     *
     * @param string $host Host
     *
     * @return Boolean
     */
    private function checkHost($host)
    {
        return $this->checkMX($host) || (checkdnsrr($host, "A") || checkdnsrr($host, "AAAA"));
    }
}
PK��Z�`�v��;Symfony/Component/Validator/Constraints/LocaleValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Intl\Intl;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * Validates whether a value is a valid locale code
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class LocaleValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
            throw new UnexpectedTypeException($value, 'string');
        }

        $value = (string) $value;
        $locales = Intl::getLocaleBundle()->getLocaleNames();

        if (!isset($locales[$value])) {
            $this->context->addViolation($constraint->message, array('{{ value }}' => $value));
        }
    }
}
PK��Z'㔘7Symfony/Component/Validator/Constraints/IdenticalTo.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * @Annotation
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class IdenticalTo extends AbstractComparison
{
    public $message = 'This value should be identical to {{ compared_value_type }} {{ compared_value }}.';
}
PK��Z��/Symfony/Component/Validator/Constraints/All.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class All extends Constraint
{
    public $constraints = array();

    /**
     * {@inheritDoc}
     */
    public function __construct($options = null)
    {
        parent::__construct($options);

        if (!is_array($this->constraints)) {
            $this->constraints = array($this->constraints);
        }

        foreach ($this->constraints as $constraint) {
            if (!$constraint instanceof Constraint) {
                throw new ConstraintDefinitionException(sprintf('The value %s is not an instance of Constraint in constraint %s', $constraint, __CLASS__));
            }

            if ($constraint instanceof Valid) {
                throw new ConstraintDefinitionException(sprintf('The constraint Valid cannot be nested inside constraint %s. You can only declare the Valid constraint directly on a field or method.', __CLASS__));
            }
        }
    }

    public function getDefaultOption()
    {
        return 'constraints';
    }

    public function getRequiredOptions()
    {
        return array('constraints');
    }
}
PK��Z{���UU?Symfony/Component/Validator/Constraints/NotEqualToValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * Validates values are all unequal (!=).
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class NotEqualToValidator extends AbstractComparisonValidator
{
    /**
     * @inheritDoc
     */
    protected function compareValues($value1, $value2)
    {
        return $value1 != $value2;
    }
}
PK��Z�ɑ559Symfony/Component/Validator/Constraints/TrueValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class TrueValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value) {
            return;
        }

        if (true !== $value && 1 !== $value && '1' !== $value) {
            $this->context->addViolation($constraint->message);
        }
    }
}
PK��Z�(.wwGSymfony/Component/Validator/Constraints/GreaterThanOrEqualValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * Validates values are greater than or equal to the previous (>=).
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class GreaterThanOrEqualValidator extends AbstractComparisonValidator
{
    /**
     * @inheritDoc
     */
    protected function compareValues($value1, $value2)
    {
        return $value1 >= $value2;
    }
}
PK��Z���(��9Symfony/Component/Validator/Constraints/TimeValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class TimeValidator extends ConstraintValidator
{
    const PATTERN = '/^(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/';

    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value || $value instanceof \DateTime) {
            return;
        }

        if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
            throw new UnexpectedTypeException($value, 'string');
        }

        $value = (string) $value;

        if (!preg_match(static::PATTERN, $value)) {
            $this->context->addViolation($constraint->message, array('{{ value }}' => $value));
        }
    }
}
PK��Z�Fn���8Symfony/Component/Validator/Constraints/AllValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class AllValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value) {
            return;
        }

        if (!is_array($value) && !$value instanceof \Traversable) {
            throw new UnexpectedTypeException($value, 'array or Traversable');
        }

        $group = $this->context->getGroup();

        foreach ($value as $key => $element) {
            foreach ($constraint->constraints as $constr) {
                $this->context->validateValue($element, $constr, '['.$key.']', $group);
            }
        }
    }
}
PK��Z�c����.Symfony/Component/Validator/Constraints/Ip.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
use Symfony\Component\Validator\Constraint;

/**
 * Validates that a value is a valid IP address
 *
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 * @author Joseph Bielawski <stloyd@gmail.com>
 *
 * @api
 */
class Ip extends Constraint
{
    const V4 = '4';
    const V6 = '6';
    const ALL = 'all';

    // adds FILTER_FLAG_NO_PRIV_RANGE flag (skip private ranges)
    const V4_NO_PRIV = '4_no_priv';
    const V6_NO_PRIV = '6_no_priv';
    const ALL_NO_PRIV = 'all_no_priv';

    // adds FILTER_FLAG_NO_RES_RANGE flag (skip reserved ranges)
    const V4_NO_RES = '4_no_res';
    const V6_NO_RES = '6_no_res';
    const ALL_NO_RES = 'all_no_res';

    // adds FILTER_FLAG_NO_PRIV_RANGE and FILTER_FLAG_NO_RES_RANGE flags (skip both)
    const V4_ONLY_PUBLIC = '4_public';
    const V6_ONLY_PUBLIC = '6_public';
    const ALL_ONLY_PUBLIC = 'all_public';

    protected static $versions = array(
        self::V4,
        self::V6,
        self::ALL,

        self::V4_NO_PRIV,
        self::V6_NO_PRIV,
        self::ALL_NO_PRIV,

        self::V4_NO_RES,
        self::V6_NO_RES,
        self::ALL_NO_RES,

        self::V4_ONLY_PUBLIC,
        self::V6_ONLY_PUBLIC,
        self::ALL_ONLY_PUBLIC,
    );

    public $version = self::V4;

    public $message = 'This is not a valid IP address.';

    /**
     * {@inheritDoc}
     */
    public function __construct($options = null)
    {
        parent::__construct($options);

        if (!in_array($this->version, self::$versions)) {
            throw new ConstraintDefinitionException(sprintf('The option "version" must be one of "%s"', implode('", "', self::$versions)));
        }
    }
}
PK��ZHð�2Symfony/Component/Validator/Constraints/Locale.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Locale extends Constraint
{
    public $message = 'This value is not a valid locale.';
}
PK��ZQ��=Symfony/Component/Validator/Constraints/LanguageValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Intl\Intl;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * Validates whether a value is a valid language code
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class LanguageValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
            throw new UnexpectedTypeException($value, 'string');
        }

        $value = (string) $value;
        $languages = Intl::getLanguageBundle()->getLanguageNames();

        if (!isset($languages[$value])) {
            $this->context->addViolation($constraint->message, array('{{ value }}' => $value));
        }
    }
}
PK��ZaHβ;Symfony/Component/Validator/Constraints/ChoiceValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * ChoiceValidator validates that the value is one of the expected values.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Florian Eckerstorfer <florian@eckerstorfer.org>
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class ChoiceValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (!$constraint->choices && !$constraint->callback) {
            throw new ConstraintDefinitionException('Either "choices" or "callback" must be specified on constraint Choice');
        }

        if (null === $value) {
            return;
        }

        if ($constraint->multiple && !is_array($value)) {
            throw new UnexpectedTypeException($value, 'array');
        }

        if ($constraint->callback) {
            if (is_callable(array($this->context->getClassName(), $constraint->callback))) {
                $choices = call_user_func(array($this->context->getClassName(), $constraint->callback));
            } elseif (is_callable($constraint->callback)) {
                $choices = call_user_func($constraint->callback);
            } else {
                throw new ConstraintDefinitionException('The Choice constraint expects a valid callback');
            }
        } else {
            $choices = $constraint->choices;
        }

        if ($constraint->multiple) {
            foreach ($value as $_value) {
                if (!in_array($_value, $choices, $constraint->strict)) {
                    $this->context->addViolation($constraint->multipleMessage, array('{{ value }}' => $_value));
                }
            }

            $count = count($value);

            if ($constraint->min !== null && $count < $constraint->min) {
                $this->context->addViolation($constraint->minMessage, array('{{ limit }}' => $constraint->min), null, (int) $constraint->min);

                return;
            }

            if ($constraint->max !== null && $count > $constraint->max) {
                $this->context->addViolation($constraint->maxMessage, array('{{ limit }}' => $constraint->max), null, (int) $constraint->max);

                return;
            }
        } elseif (!in_array($value, $choices, $constraint->strict)) {
            $this->context->addViolation($constraint->message, array('{{ value }}' => $value));
        }
    }
}
PK��Z�{HH1Symfony/Component/Validator/Constraints/Email.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Email extends Constraint
{
    public $message = 'This value is not a valid email address.';
    public $checkMX = false;
    public $checkHost = false;
}
PK��Zx�.`ss4Symfony/Component/Validator/Constraints/Callback.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Callback extends Constraint
{
    /**
     * @var string|callable
     *
     * @since 2.4
     */
    public $callback;

    /**
     * @var array
     *
     * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0.
     */
    public $methods;

    /**
     * {@inheritdoc}
     */
    public function __construct($options = null)
    {
        // Invocation through annotations with an array parameter only
        if (is_array($options) && 1 === count($options) && isset($options['value'])) {
            $options = $options['value'];
        }

        if (is_array($options) && !isset($options['callback']) && !isset($options['methods']) && !isset($options['groups'])) {
            if (is_callable($options)) {
                $options = array('callback' => $options);
            } else {
                // BC with Symfony < 2.4
                $options = array('methods' => $options);
            }
        }

        parent::__construct($options);
    }

    /**
     * {@inheritdoc}
     */
    public function getDefaultOption()
    {
        return 'callback';
    }

    /**
     * {@inheritdoc}
     */
    public function getTargets()
    {
        return self::CLASS_CONSTRAINT;
    }
}
PK��Z�����=Symfony/Component/Validator/Constraints/DateTimeValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class DateTimeValidator extends DateValidator
{
    const PATTERN = '/^(\d{4})-(\d{2})-(\d{2}) (0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/';
}
PK��Z�&����0Symfony/Component/Validator/Constraints/Luhn.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * Metadata for the LuhnValidator.
 *
 * @Annotation
 */
class Luhn extends Constraint
{
    public $message = 'Invalid card number.';
}
PK��Z�F���9Symfony/Component/Validator/Constraints/TypeValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class TypeValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value) {
            return;
        }

        $type = strtolower($constraint->type);
        $type = $type == 'boolean' ? 'bool' : $constraint->type;
        $isFunction = 'is_'.$type;
        $ctypeFunction = 'ctype_'.$type;

        if (function_exists($isFunction) && call_user_func($isFunction, $value)) {
            return;
        } elseif (function_exists($ctypeFunction) && call_user_func($ctypeFunction, $value)) {
            return;
        } elseif ($value instanceof $constraint->type) {
            return;
        }

        $this->context->addViolation($constraint->message, array(
            '{{ value }}' => is_object($value) ? get_class($value) : (is_array($value) ? 'Array' : (string) $value),
            '{{ type }}'  => $constraint->type,
        ));
    }
}
PK��Z���&��=Symfony/Component/Validator/Constraints/NotBlankValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class NotBlankValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (false === $value || (empty($value) && '0' != $value)) {
            $this->context->addViolation($constraint->message);
        }
    }
}
PK��Ze8�B�
�
6Symfony/Component/Validator/Constraints/Collection.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Collection extends Constraint
{
    public $fields = array();
    public $allowExtraFields = false;
    public $allowMissingFields = false;
    public $extraFieldsMessage = 'This field was not expected.';
    public $missingFieldsMessage = 'This field is missing.';

    /**
     * {@inheritDoc}
     */
    public function __construct($options = null)
    {
        // no known options set? $options is the fields array
        if (is_array($options)
            && !array_intersect(array_keys($options), array('groups', 'fields', 'allowExtraFields', 'allowMissingFields', 'extraFieldsMessage', 'missingFieldsMessage'))) {
            $options = array('fields' => $options);
        }

        parent::__construct($options);

        if (!is_array($this->fields)) {
            throw new ConstraintDefinitionException(sprintf('The option "fields" is expected to be an array in constraint %s', __CLASS__));
        }

        foreach ($this->fields as $fieldName => $field) {
            // the XmlFileLoader and YamlFileLoader pass the field Optional
            // and Required constraint as an array with exactly one element
            if (is_array($field) && count($field) == 1) {
                $this->fields[$fieldName] = $field = $field[0];
            }

            if (!$field instanceof Optional && !$field instanceof Required) {
                $this->fields[$fieldName] = $field = new Required($field);
            }

            if (!is_array($field->constraints)) {
                $field->constraints = array($field->constraints);
            }

            foreach ($field->constraints as $constraint) {
                if (!$constraint instanceof Constraint) {
                    throw new ConstraintDefinitionException(sprintf('The value %s of the field %s is not an instance of Constraint in constraint %s', $constraint, $fieldName, __CLASS__));
                }

                if ($constraint instanceof Valid) {
                    throw new ConstraintDefinitionException(sprintf('The constraint Valid cannot be nested inside constraint %s. You can only declare the Valid constraint directly on a field or method.', __CLASS__));
                }
            }
        }
    }

    public function getRequiredOptions()
    {
        return array('fields');
    }
}
PK��ZI7U���1Symfony/Component/Validator/Constraints/False.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class False extends Constraint
{
    public $message = 'This value should be false.';
}
PK��Z�Q�>Symfony/Component/Validator/Constraints/GreaterThanOrEqual.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * @Annotation
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class GreaterThanOrEqual extends AbstractComparison
{
    public $message = 'This value should be greater than or equal to {{ compared_value }}.';
}
PK��Z��l��1Symfony/Component/Validator/Constraints/Blank.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Blank extends Constraint
{
    public $message = 'This value should be blank.';
}
PK��Z�CG^LL<Symfony/Component/Validator/Constraints/EqualToValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * Validates values are equal (==).
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class EqualToValidator extends AbstractComparisonValidator
{
    /**
     * @inheritDoc
     */
    protected function compareValues($value1, $value2)
    {
        return $value1 == $value2;
    }
}
PK��Z^�T:Symfony/Component/Validator/Constraints/FalseValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class FalseValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || false === $value || 0 === $value || '0' === $value) {
            return;
        }

        $this->context->addViolation($constraint->message);
    }
}
PK��ZO��qqDSymfony/Component/Validator/Constraints/LessThanOrEqualValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * Validates values are less than or equal to the previous (<=).
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class LessThanOrEqualValidator extends AbstractComparisonValidator
{
    /**
     * @inheritDoc
     */
    protected function compareValues($value1, $value2)
    {
        return $value1 <= $value2;
    }
}
PK��Z����vv9Symfony/Component/Validator/Constraints/GroupSequence.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * Annotation for group sequences
 *
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class GroupSequence
{
    /**
     * The members of the sequence
     * @var array
     */
    public $groups;

    public function __construct(array $groups)
    {
        $this->groups = $groups['value'];
    }
}
PK��Z_��1Symfony/Component/Validator/Constraints/Image.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * @Annotation
 *
 * @api
 */
class Image extends File
{
    public $mimeTypes = 'image/*';
    public $minWidth = null;
    public $maxWidth = null;
    public $maxHeight = null;
    public $minHeight = null;
    public $maxRatio = null;
    public $minRatio = null;
    public $allowSquare = true;
    public $allowLandscape = true;
    public $allowPortrait = true;

    public $mimeTypesMessage = 'This file is not a valid image.';
    public $sizeNotDetectedMessage = 'The size of the image could not be detected.';
    public $maxWidthMessage = 'The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.';
    public $minWidthMessage = 'The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.';
    public $maxHeightMessage = 'The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.';
    public $minHeightMessage = 'The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.';
    public $maxRatioMessage = 'The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.';
    public $minRatioMessage = 'The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.';
    public $allowSquareMessage = 'The image is square ({{ width }}x{{ height }}px). Square images are not allowed.';
    public $allowLandscapeMessage = 'The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.';
    public $allowPortraitMessage = 'The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.';
}
PK��Z��F;��;Symfony/Component/Validator/Constraints/LengthValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class LengthValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
            throw new UnexpectedTypeException($value, 'string');
        }

        $stringValue = (string) $value;

        if (function_exists('grapheme_strlen') && 'UTF-8' === $constraint->charset) {
            $length = grapheme_strlen($stringValue);
        } elseif (function_exists('mb_strlen')) {
            $length = mb_strlen($stringValue, $constraint->charset);
        } else {
            $length = strlen($stringValue);
        }

        if ($constraint->min == $constraint->max && $length != $constraint->min) {
            $this->context->addViolation($constraint->exactMessage, array(
                '{{ value }}' => $stringValue,
                '{{ limit }}' => $constraint->min,
            ), $value, (int) $constraint->min);

            return;
        }

        if (null !== $constraint->max && $length > $constraint->max) {
            $this->context->addViolation($constraint->maxMessage, array(
                '{{ value }}' => $stringValue,
                '{{ limit }}' => $constraint->max,
            ), $value, (int) $constraint->max);

            return;
        }

        if (null !== $constraint->min && $length < $constraint->min) {
            $this->context->addViolation($constraint->minMessage, array(
                '{{ value }}' => $stringValue,
                '{{ limit }}' => $constraint->min,
            ), $value, (int) $constraint->min);
        }
    }
}
PK��Z!xHH:Symfony/Component/Validator/Constraints/CountValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class CountValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value) {
            return;
        }

        if (!is_array($value) && !$value instanceof \Countable) {
            throw new UnexpectedTypeException($value, 'array or \Countable');
        }

        $count = count($value);

        if ($constraint->min == $constraint->max && $count != $constraint->min) {
            $this->context->addViolation($constraint->exactMessage, array(
                '{{ count }}' => $count,
                '{{ limit }}' => $constraint->min,
            ), $value, (int) $constraint->min);

            return;
        }

        if (null !== $constraint->max && $count > $constraint->max) {
            $this->context->addViolation($constraint->maxMessage, array(
                '{{ count }}' => $count,
                '{{ limit }}' => $constraint->max,
            ), $value, (int) $constraint->max);

            return;
        }

        if (null !== $constraint->min && $count < $constraint->min) {
            $this->context->addViolation($constraint->minMessage, array(
                '{{ count }}' => $count,
                '{{ limit }}' => $constraint->min,
            ), $value, (int) $constraint->min);
        }
    }
}
PK��Z��70Symfony/Component/Validator/Constraints/Time.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Time extends Constraint
{
    public $message = 'This value is not a valid time.';
}
PK��ZN�H���4Symfony/Component/Validator/Constraints/LessThan.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * @Annotation
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class LessThan extends AbstractComparison
{
    public $message = 'This value should be less than {{ compared_value }}.';
}
PK��Ze��:Symfony/Component/Validator/Constraints/NotIdenticalTo.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * @Annotation
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class NotIdenticalTo extends AbstractComparison
{
    public $message = 'This value should not be identical to {{ compared_value_type }} {{ compared_value }}.';
}
PK��Z�Z�=Symfony/Component/Validator/Constraints/CurrencyValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Intl\Intl;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * Validates whether a value is a valid currency
 *
 * @author Miha Vrhovnik <miha.vrhovnik@pagein.si>
 *
 * @api
 */
class CurrencyValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
            throw new UnexpectedTypeException($value, 'string');
        }

        $value = (string) $value;
        $currencies = Intl::getCurrencyBundle()->getCurrencyNames();

        if (!isset($currencies[$value])) {
            $this->context->addViolation($constraint->message, array('{{ value }}' => $value));
        }
    }
}
PK��ZGk	��3Symfony/Component/Validator/ConstraintValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * Base class for constraint validators
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
abstract class ConstraintValidator implements ConstraintValidatorInterface
{
    /**
     * @var ExecutionContextInterface
     */
    protected $context;

    /**
     * {@inheritDoc}
     */
    public function initialize(ExecutionContextInterface $context)
    {
        $this->context = $context;
    }
}
PK��ZK�OCSymfony/Component/Validator/ConstraintValidatorFactoryInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * Specifies an object able to return the correct ConstraintValidatorInterface
 * instance given a Constraint object.
 */
interface ConstraintValidatorFactoryInterface
{
    /**
     * Given a Constraint, this returns the ConstraintValidatorInterface
     * object that should be used to verify its validity.
     *
     * @param Constraint $constraint The source constraint
     *
     * @return ConstraintValidatorInterface
     */
    public function getInstance(Constraint $constraint);
}
PK��Z�8Wc��?Symfony/Component/Validator/GlobalExecutionContextInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * Stores the node-independent state of a validation run.
 *
 * When the validator validates a graph of objects, it uses two classes to
 * store the state during the validation:
 *
 * <ul>
 * <li>For each node in the validation graph (objects, properties, getters) the
 * validator creates an instance of {@link ExecutionContextInterface} that
 * stores the information about that node.</li>
 * <li>One single <tt>GlobalExecutionContextInterface</tt> stores the state
 * that is independent of the current node.</li>
 * </ul>
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface GlobalExecutionContextInterface
{
    /**
     * Returns the violations generated by the validator so far.
     *
     * @return ConstraintViolationListInterface A list of constraint violations.
     */
    public function getViolations();

    /**
     * Returns the value at which validation was started in the object graph.
     *
     * @return mixed The root value.
     *
     * @see ExecutionContextInterface::getRoot
     */
    public function getRoot();

    /**
     * Returns the visitor instance used to validate the object graph nodes.
     *
     * @return ValidationVisitorInterface The validation visitor.
     */
    public function getVisitor();

    /**
     * Returns the factory for constraint validators.
     *
     * @return ConstraintValidatorFactoryInterface The constraint validator factory.
     */
    public function getValidatorFactory();

    /**
     * Returns the factory for validation metadata objects.
     *
     * @return MetadataFactoryInterface The metadata factory.
     */
    public function getMetadataFactory();
}
PK��Zxf�JJ*Symfony/Component/Validator/Validation.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * Entry point for the Validator component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
final class Validation
{
    /**
     * Creates a new validator.
     *
     * If you want to configure the validator, use
     * {@link createValidatorBuilder()} instead.
     *
     * @return ValidatorInterface The new validator.
     */
    public static function createValidator()
    {
        return self::createValidatorBuilder()->getValidator();
    }

    /**
     * Creates a configurable builder for validator objects.
     *
     * @return ValidatorBuilderInterface The new builder.
     */
    public static function createValidatorBuilder()
    {
        return new ValidatorBuilder();
    }

    /**
     * This class cannot be instantiated.
     */
    private function __construct()
    {
    }
}
PK��Zn�r�
�
2Symfony/Component/Validator/ValidatorInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * Validates values and graphs of objects and arrays.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
interface ValidatorInterface
{
    /**
     * Validates a value.
     *
     * The accepted values depend on the {@link MetadataFactoryInterface}
     * implementation.
     *
     * @param mixed      $value    The value to validate
     * @param array|null $groups   The validation groups to validate.
     * @param Boolean    $traverse Whether to traverse the value if it is traversable.
     * @param Boolean    $deep     Whether to traverse nested traversable values recursively.
     *
     * @return ConstraintViolationListInterface A list of constraint violations. If the
     *                                          list is empty, validation succeeded.
     *
     * @api
     */
    public function validate($value, $groups = null, $traverse = false, $deep = false);

    /**
     * Validates a property of a value against its current value.
     *
     * The accepted values depend on the {@link MetadataFactoryInterface}
     * implementation.
     *
     * @param mixed      $containingValue The value containing the property.
     * @param string     $property        The name of the property to validate.
     * @param array|null $groups          The validation groups to validate.
     *
     * @return ConstraintViolationListInterface A list of constraint violations. If the
     *                                          list is empty, validation succeeded.
     *
     * @api
     */
    public function validateProperty($containingValue, $property, $groups = null);

    /**
     * Validate a property of a value against a potential value.
     *
     * The accepted values depend on the {@link MetadataFactoryInterface}
     * implementation.
     *
     * @param string     $containingValue The value containing the property.
     * @param string     $property        The name of the property to validate
     * @param string     $value           The value to validate against the
     *                                    constraints of the property.
     * @param array|null $groups          The validation groups to validate.
     *
     * @return ConstraintViolationListInterface A list of constraint violations. If the
     *                                          list is empty, validation succeeded.
     *
     * @api
     */
    public function validatePropertyValue($containingValue, $property, $value, $groups = null);

    /**
     * Validates a value against a constraint or a list of constraints.
     *
     * @param mixed                   $value       The value to validate.
     * @param Constraint|Constraint[] $constraints The constraint(s) to validate against.
     * @param array|null              $groups      The validation groups to validate.
     *
     * @return ConstraintViolationListInterface A list of constraint violations. If the
     *                                          list is empty, validation succeeded.
     *
     * @api
     */
    public function validateValue($value, $constraints, $groups = null);

    /**
     * Returns the factory for metadata instances.
     *
     * @return MetadataFactoryInterface The metadata factory.
     *
     * @api
     */
    public function getMetadataFactory();
}
PK��ZC���9Symfony/Component/Templating/StreamingEngineInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating;

/**
 * StreamingEngineInterface provides a method that knows how to stream a template.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface StreamingEngineInterface
{
    /**
     * Streams a template.
     *
     * The implementation should output the content directly to the client.
     *
     * @param string|TemplateReferenceInterface $name       A template name or a TemplateReferenceInterface instance
     * @param array                             $parameters An array of parameters to pass to the template
     *
     * @throws \RuntimeException if the template cannot be rendered
     * @throws \LogicException   if the template cannot be streamed
     */
    public function stream($name, array $parameters = array());
}
PK��Z<,��}}2Symfony/Component/Templating/TemplateReference.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating;

/**
 * Internal representation of a template.
 *
 * @author Victor Berchet <victor@suumit.com>
 *
 * @api
 */
class TemplateReference implements TemplateReferenceInterface
{
    protected $parameters;

    public function __construct($name = null, $engine = null)
    {
        $this->parameters = array(
            'name'   => $name,
            'engine' => $engine,
        );
    }

    /**
     * {@inheritdoc}
     */
    public function __toString()
    {
        return $this->getLogicalName();
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function set($name, $value)
    {
        if (array_key_exists($name, $this->parameters)) {
            $this->parameters[$name] = $value;
        } else {
            throw new \InvalidArgumentException(sprintf('The template does not support the "%s" parameter.', $name));
        }

        return $this;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function get($name)
    {
        if (array_key_exists($name, $this->parameters)) {
            return $this->parameters[$name];
        }

        throw new \InvalidArgumentException(sprintf('The template does not support the "%s" parameter.', $name));
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function all()
    {
        return $this->parameters;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function getPath()
    {
        return $this->parameters['name'];
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function getLogicalName()
    {
        return $this->parameters['name'];
    }
}
PK��Z�m�tTT+Symfony/Component/Templating/autoloader.phpnu�[���<?php

spl_autoload_register(function ($class) {
    if ('\\' == $class[0]) {
        $class = substr($class, 1);
    }

    if (
        0 === strpos($class, 'Symfony\\Component\\Templating\\')
        &&
        file_exists($file = __DIR__.'/../../../'.str_replace('\\', '/', $class).'.php')
    ) {
        require_once $file;
    }
});
PK��Z����;Symfony/Component/Templating/TemplateReferenceInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating;

/**
 * Interface to be implemented by all templates.
 *
 * @author Victor Berchet <victor@suumit.com>
 *
 * @api
 */
interface TemplateReferenceInterface
{
    /**
     * Gets the template parameters.
     *
     * @return array An array of parameters
     *
     * @api
     */
    public function all();

    /**
     * Sets a template parameter.
     *
     * @param string $name  The parameter name
     * @param string $value The parameter value
     *
     * @return TemplateReferenceInterface The TemplateReferenceInterface instance
     *
     * @throws  \InvalidArgumentException if the parameter name is not supported
     *
     * @api
     */
    public function set($name, $value);

    /**
     * Gets a template parameter.
     *
     * @param string $name The parameter name
     *
     * @return string The parameter value
     *
     * @throws  \InvalidArgumentException if the parameter name is not supported
     *
     * @api
     */
    public function get($name);

    /**
     * Returns the path to the template.
     *
     * By default, it just returns the template name.
     *
     * @return string A path to the template or a resource
     *
     * @api
     */
    public function getPath();

    /**
     * Returns the "logical" template name.
     *
     * The template name acts as a unique identifier for the template.
     *
     * @return string The template name
     *
     * @api
     */
    public function getLogicalName();

    /**
     * Returns the string representation as shortcut for getLogicalName().
     *
     * Alias of getLogicalName().
     *
     * @return string The template name
     *
     * @api
     */
    public function __toString();
}
PK��ZJ� ���2Symfony/Component/Templating/DebuggerInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating;

/**
 * DebuggerInterface is the interface you need to implement
 * to debug template loader instances.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @deprecated Deprecated in 2.4, to be removed in 3.0. Use Psr\Log\LoggerInterface instead.
 */
interface DebuggerInterface
{
    /**
     * Logs a message.
     *
     * @param string $message A message to log
     */
    public function log($message);
}
PK��ZDZ�_++<Symfony/Component/Templating/TemplateNameParserInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating;

/**
 * TemplateNameParserInterface converts template names to TemplateReferenceInterface
 * instances.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface TemplateNameParserInterface
{
    /**
     * Convert a template name to a TemplateReferenceInterface instance.
     *
     * @param string|TemplateReferenceInterface $name A template name or a TemplateReferenceInterface instance
     *
     * @return TemplateReferenceInterface A template
     *
     * @api
     */
    public function parse($name);
}
PK��Z���3Symfony/Component/Templating/TemplateNameParser.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating;

/**
 * TemplateNameParser is the default implementation of TemplateNameParserInterface.
 *
 * This implementation takes everything as the template name
 * and the extension for the engine.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class TemplateNameParser implements TemplateNameParserInterface
{
    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function parse($name)
    {
        if ($name instanceof TemplateReferenceInterface) {
            return $name;
        }

        $engine = null;
        if (false !== $pos = strrpos($name, '.')) {
            $engine = substr($name, $pos + 1);
        }

        return new TemplateReference($name, $engine);
    }
}
PK��Z�����0Symfony/Component/Templating/EngineInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating;

/**
 * EngineInterface is the interface each engine must implement.
 *
 * All methods relies on a template name. A template name is a
 * "logical" name for the template, and as such it does not refer to
 * a path on the filesystem (in fact, the template can be stored
 * anywhere, like in a database).
 *
 * The methods should accept any name. If the name is not an instance of
 * TemplateReferenceInterface, a TemplateNameParserInterface should be used to
 * convert the name to a TemplateReferenceInterface instance.
 *
 * Each template loader uses the logical template name to look for
 * the template.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface EngineInterface
{
    /**
     * Renders a template.
     *
     * @param string|TemplateReferenceInterface $name       A template name or a TemplateReferenceInterface instance
     * @param array                             $parameters An array of parameters to pass to the template
     *
     * @return string The evaluated template as a string
     *
     * @throws \RuntimeException if the template cannot be rendered
     *
     * @api
     */
    public function render($name, array $parameters = array());

    /**
     * Returns true if the template exists.
     *
     * @param string|TemplateReferenceInterface $name A template name or a TemplateReferenceInterface instance
     *
     * @return Boolean true if the template exists, false otherwise
     *
     * @throws \RuntimeException if the engine cannot handle the template name
     *
     * @api
     */
    public function exists($name);

    /**
     * Returns true if this class is able to render the given template.
     *
     * @param string|TemplateReferenceInterface $name A template name or a TemplateReferenceInterface instance
     *
     * @return Boolean true if this class supports the given template, false otherwise
     *
     * @api
     */
    public function supports($name);
}
PK��Z��b�NN2Symfony/Component/Templating/Asset/PathPackage.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Asset;

/**
 * The path packages adds a version and a base path to asset URLs.
 *
 * @author Kris Wallsmith <kris@symfony.com>
 */
class PathPackage extends Package
{
    private $basePath;

    /**
     * Constructor.
     *
     * @param string $basePath The base path to be prepended to relative paths
     * @param string $version  The package version
     * @param string $format   The format used to apply the version
     */
    public function __construct($basePath = null, $version = null, $format = null)
    {
        parent::__construct($version, $format);

        if (!$basePath) {
            $this->basePath = '/';
        } else {
            if ('/' != $basePath[0]) {
                $basePath = '/'.$basePath;
            }

            $this->basePath = rtrim($basePath, '/').'/';
        }
    }

    public function getUrl($path)
    {
        if (false !== strpos($path, '://') || 0 === strpos($path, '//')) {
            return $path;
        }

        $url = $this->applyVersion($path);

        // apply the base path
        if ('/' !== substr($url, 0, 1)) {
            $url = $this->basePath.$url;
        }

        return $url;
    }

    /**
     * Returns the base path.
     *
     * @return string The base path
     */
    public function getBasePath()
    {
        return $this->basePath;
    }
}
PK��Z���TT1Symfony/Component/Templating/Asset/UrlPackage.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Asset;

/**
 * The URL packages adds a version and a base URL to asset URLs.
 *
 * @author Kris Wallsmith <kris@symfony.com>
 */
class UrlPackage extends Package
{
    private $baseUrls;

    /**
     * Constructor.
     *
     * @param string|array $baseUrls Base asset URLs
     * @param string       $version  The package version
     * @param string       $format   The format used to apply the version
     */
    public function __construct($baseUrls = array(), $version = null, $format = null)
    {
        parent::__construct($version, $format);

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

        $this->baseUrls = array();
        foreach ($baseUrls as $baseUrl) {
            $this->baseUrls[] = rtrim($baseUrl, '/');
        }
    }

    public function getUrl($path)
    {
        if (false !== strpos($path, '://') || 0 === strpos($path, '//')) {
            return $path;
        }

        $url = $this->applyVersion($path);

        if ($url && '/' != $url[0]) {
            $url = '/'.$url;
        }

        return $this->getBaseUrl($path).$url;
    }

    /**
     * Returns the base URL for a path.
     *
     * @param string $path
     *
     * @return string The base URL
     */
    public function getBaseUrl($path)
    {
        switch ($count = count($this->baseUrls)) {
            case 0:
                return '';

            case 1:
                return $this->baseUrls[0];

            default:
                return $this->baseUrls[fmod(hexdec(substr(hash('sha256', $path), 0, 10)), $count)];
        }
    }
}
PK��Z�o##.Symfony/Component/Templating/Asset/Package.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Asset;

/**
 * The basic package will add a version to asset URLs.
 *
 * @author Kris Wallsmith <kris@symfony.com>
 */
class Package implements PackageInterface
{
    private $version;
    private $format;

    /**
     * Constructor.
     *
     * @param string $version The package version
     * @param string $format  The format used to apply the version
     */
    public function __construct($version = null, $format = '')
    {
        $this->version = $version;
        $this->format = $format ?: '%s?%s';
    }

    public function getVersion()
    {
        return $this->version;
    }

    public function getUrl($path)
    {
        if (false !== strpos($path, '://') || 0 === strpos($path, '//')) {
            return $path;
        }

        return $this->applyVersion($path);
    }

    /**
     * Applies version to the supplied path.
     *
     * @param string $path A path
     *
     * @return string The versionized path
     */
    protected function applyVersion($path)
    {
        if (null === $this->version) {
            return $path;
        }

        $versionized = sprintf($this->format, ltrim($path, '/'), $this->version);

        if ($path && '/' == $path[0]) {
            $versionized = '/'.$versionized;
        }

        return $versionized;
    }
}
PK��Zp�vj��7Symfony/Component/Templating/Asset/PackageInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Asset;

/**
 * Asset package interface.
 *
 * @author Kris Wallsmith <kris@symfony.com>
 */
interface PackageInterface
{
    /**
     * Returns the asset package version.
     *
     * @return string The version string
     */
    public function getVersion();

    /**
     * Returns an absolute or root-relative public path.
     *
     * @param string $path A path
     *
     * @return string The public path
     */
    public function getUrl($path);
}
PK��Z�'��4Symfony/Component/Templating/Storage/FileStorage.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Storage;

/**
 * FileStorage represents a template stored on the filesystem.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class FileStorage extends Storage
{
    /**
     * Returns the content of the template.
     *
     * @return string The template content
     *
     * @api
     */
    public function getContent()
    {
        return file_get_contents($this->template);
    }
}
PK��Z(�"w��6Symfony/Component/Templating/Storage/StringStorage.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Storage;

/**
 * StringStorage represents a template stored in a string.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class StringStorage extends Storage
{
    /**
     * Returns the content of the template.
     *
     * @return string The template content
     *
     * @api
     */
    public function getContent()
    {
        return $this->template;
    }
}
PK��Zπ\�0Symfony/Component/Templating/Storage/Storage.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Storage;

/**
 * Storage is the base class for all storage classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
abstract class Storage
{
    protected $template;

    /**
     * Constructor.
     *
     * @param string $template The template name
     *
     * @api
     */
    public function __construct($template)
    {
        $this->template = $template;
    }

    /**
     * Returns the object string representation.
     *
     * @return string The template name
     */
    public function __toString()
    {
        return (string) $this->template;
    }

    /**
     * Returns the content of the template.
     *
     * @return string The template content
     *
     * @api
     */
    abstract public function getContent();
}
PK��Z��>3Symfony/Component/Templating/Loader/ChainLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Loader;

use Symfony\Component\Templating\Storage\Storage;
use Symfony\Component\Templating\TemplateReferenceInterface;

/**
 * ChainLoader is a loader that calls other loaders to load templates.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ChainLoader extends Loader
{
    protected $loaders = array();

    /**
     * Constructor.
     *
     * @param LoaderInterface[] $loaders An array of loader instances
     */
    public function __construct(array $loaders = array())
    {
        foreach ($loaders as $loader) {
            $this->addLoader($loader);
        }
    }

    /**
     * Adds a loader instance.
     *
     * @param LoaderInterface $loader A Loader instance
     */
    public function addLoader(LoaderInterface $loader)
    {
        $this->loaders[] = $loader;
    }

    /**
     * Loads a template.
     *
     * @param TemplateReferenceInterface $template A template
     *
     * @return Storage|Boolean false if the template cannot be loaded, a Storage instance otherwise
     */
    public function load(TemplateReferenceInterface $template)
    {
        foreach ($this->loaders as $loader) {
            if (false !== $storage = $loader->load($template)) {
                return $storage;
            }
        }

        return false;
    }

    /**
     * Returns true if the template is still fresh.
     *
     * @param TemplateReferenceInterface $template A template
     * @param integer                    $time     The last modification time of the cached template (timestamp)
     *
     * @return Boolean
     */
    public function isFresh(TemplateReferenceInterface $template, $time)
    {
        foreach ($this->loaders as $loader) {
            return $loader->isFresh($template, $time);
        }

        return false;
    }
}
PK��Z�b��8Symfony/Component/Templating/Loader/FilesystemLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Loader;

use Symfony\Component\Templating\Storage\Storage;
use Symfony\Component\Templating\Storage\FileStorage;
use Symfony\Component\Templating\TemplateReferenceInterface;

/**
 * FilesystemLoader is a loader that read templates from the filesystem.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class FilesystemLoader extends Loader
{
    protected $templatePathPatterns;

    /**
     * Constructor.
     *
     * @param array $templatePathPatterns An array of path patterns to look for templates
     *
     * @api
     */
    public function __construct($templatePathPatterns)
    {
        $this->templatePathPatterns = (array) $templatePathPatterns;
    }

    /**
     * Loads a template.
     *
     * @param TemplateReferenceInterface $template A template
     *
     * @return Storage|Boolean false if the template cannot be loaded, a Storage instance otherwise
     *
     * @api
     */
    public function load(TemplateReferenceInterface $template)
    {
        $file = $template->get('name');

        if (self::isAbsolutePath($file) && is_file($file)) {
            return new FileStorage($file);
        }

        $replacements = array();
        foreach ($template->all() as $key => $value) {
            $replacements['%'.$key.'%'] = $value;
        }

        $logs = array();
        foreach ($this->templatePathPatterns as $templatePathPattern) {
            if (is_file($file = strtr($templatePathPattern, $replacements)) && is_readable($file)) {
                if (null !== $this->logger) {
                    $this->logger->debug(sprintf('Loaded template file "%s"', $file));
                } elseif (null !== $this->debugger) {
                    // just for BC, to be removed in 3.0
                    $this->debugger->log(sprintf('Loaded template file "%s"', $file));
                }

                return new FileStorage($file);
            }

            if (null !== $this->logger || null !== $this->debugger) {
                $logs[] = sprintf('Failed loading template file "%s"', $file);
            }
        }

        foreach ($logs as $log) {
            if (null !== $this->logger) {
                $this->logger->debug($log);
            } elseif (null !== $this->debugger) {
                $this->debugger->log($log);
            }
        }

        return false;
    }

    /**
     * Returns true if the template is still fresh.
     *
     * @param TemplateReferenceInterface $template A template
     * @param integer                    $time     The last modification time of the cached template (timestamp)
     *
     * @return Boolean true if the template is still fresh, false otherwise
     *
     * @api
     */
    public function isFresh(TemplateReferenceInterface $template, $time)
    {
        if (false === $storage = $this->load($template)) {
            return false;
        }

        return filemtime((string) $storage) < $time;
    }

    /**
     * Returns true if the file is an existing absolute path.
     *
     * @param string $file A path
     *
     * @return Boolean true if the path exists and is absolute, false otherwise
     */
    protected static function isAbsolutePath($file)
    {
        if ($file[0] == '/' || $file[0] == '\\'
            || (strlen($file) > 3 && ctype_alpha($file[0])
                && $file[1] == ':'
                && ($file[2] == '\\' || $file[2] == '/')
            )
            || null !== parse_url($file, PHP_URL_SCHEME)
        ) {
            return true;
        }

        return false;
    }
}
PK��Z�g((.Symfony/Component/Templating/Loader/Loader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Loader;

use Psr\Log\LoggerInterface;
use Symfony\Component\Templating\DebuggerInterface;

/**
 * Loader is the base class for all template loader classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class Loader implements LoaderInterface
{
    /**
     * @var LoggerInterface|null
     */
    protected $logger;

    /**
     * @deprecated Deprecated in 2.4, to be removed in 3.0. Use $this->logger instead.
     */
    protected $debugger;

    /**
     * Sets the debug logger to use for this loader.
     *
     * @param LoggerInterface $logger A logger instance
     */
    public function setLogger(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }

    /**
     * Sets the debugger to use for this loader.
     *
     * @param DebuggerInterface $debugger A debugger instance
     *
     * @deprecated Deprecated in 2.4, to be removed in 3.0. Use $this->setLogger() instead.
     */
    public function setDebugger(DebuggerInterface $debugger)
    {
        $this->debugger = $debugger;
    }
}
PK��Zy�A�nn3Symfony/Component/Templating/Loader/CacheLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Loader;

use Symfony\Component\Templating\Storage\Storage;
use Symfony\Component\Templating\Storage\FileStorage;
use Symfony\Component\Templating\TemplateReferenceInterface;

/**
 * CacheLoader is a loader that caches other loaders responses
 * on the filesystem.
 *
 * This cache only caches on disk to allow PHP accelerators to cache the opcodes.
 * All other mechanism would imply the use of `eval()`.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class CacheLoader extends Loader
{
    protected $loader;
    protected $dir;

    /**
     * Constructor.
     *
     * @param LoaderInterface $loader A Loader instance
     * @param string          $dir    The directory where to store the cache files
     */
    public function __construct(LoaderInterface $loader, $dir)
    {
        $this->loader = $loader;
        $this->dir = $dir;
    }

    /**
     * Loads a template.
     *
     * @param TemplateReferenceInterface $template A template
     *
     * @return Storage|Boolean false if the template cannot be loaded, a Storage instance otherwise
     */
    public function load(TemplateReferenceInterface $template)
    {
        $key = hash('sha256', $template->getLogicalName());
        $dir = $this->dir.DIRECTORY_SEPARATOR.substr($key, 0, 2);
        $file = substr($key, 2).'.tpl';
        $path = $dir.DIRECTORY_SEPARATOR.$file;

        if (is_file($path)) {
            if (null !== $this->logger) {
                $this->logger->debug(sprintf('Fetching template "%s" from cache', $template->get('name')));
            } elseif (null !== $this->debugger) {
                // just for BC, to be removed in 3.0
                $this->debugger->log(sprintf('Fetching template "%s" from cache', $template->get('name')));
            }

            return new FileStorage($path);
        }

        if (false === $storage = $this->loader->load($template)) {
            return false;
        }

        $content = $storage->getContent();

        if (!is_dir($dir)) {
            mkdir($dir, 0777, true);
        }

        file_put_contents($path, $content);

        if (null !== $this->logger) {
            $this->logger->debug(sprintf('Storing template "%s" in cache', $template->get('name')));
        } elseif (null !== $this->debugger) {
            // just for BC, to be removed in 3.0
            $this->debugger->log(sprintf('Storing template "%s" in cache', $template->get('name')));
        }

        return new FileStorage($path);
    }

    /**
     * Returns true if the template is still fresh.
     *
     * @param TemplateReferenceInterface $template A template
     * @param integer                    $time     The last modification time of the cached template (timestamp)
     *
     * @return Boolean
     */
    public function isFresh(TemplateReferenceInterface $template, $time)
    {
        return $this->loader->isFresh($template, $time);
    }
}
PK��ZI<�D��7Symfony/Component/Templating/Loader/LoaderInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Loader;

use Symfony\Component\Templating\TemplateReferenceInterface;
use Symfony\Component\Templating\Storage\Storage;

/**
 * LoaderInterface is the interface all loaders must implement.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface LoaderInterface
{
    /**
     * Loads a template.
     *
     * @param TemplateReferenceInterface $template A template
     *
     * @return Storage|Boolean false if the template cannot be loaded, a Storage instance otherwise
     *
     * @api
     */
    public function load(TemplateReferenceInterface $template);

    /**
     * Returns true if the template is still fresh.
     *
     * @param TemplateReferenceInterface $template A template
     * @param integer                    $time     The last modification time of the cached template (timestamp)
     *
     * @return Boolean
     *
     * @api
     */
    public function isFresh(TemplateReferenceInterface $template, $time);
}
PK��Z+�r�mm3Symfony/Component/Templating/Helper/SlotsHelper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Helper;

/**
 * SlotsHelper manages template slots.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class SlotsHelper extends Helper
{
    protected $slots = array();
    protected $openSlots = array();

    /**
     * Starts a new slot.
     *
     * This method starts an output buffer that will be
     * closed when the stop() method is called.
     *
     * @param string $name The slot name
     *
     * @throws \InvalidArgumentException if a slot with the same name is already started
     *
     * @api
     */
    public function start($name)
    {
        if (in_array($name, $this->openSlots)) {
            throw new \InvalidArgumentException(sprintf('A slot named "%s" is already started.', $name));
        }

        $this->openSlots[] = $name;
        $this->slots[$name] = '';

        ob_start();
        ob_implicit_flush(0);
    }

    /**
     * Stops a slot.
     *
     * @throws \LogicException if no slot has been started
     *
     * @api
     */
    public function stop()
    {
        if (!$this->openSlots) {
            throw new \LogicException('No slot started.');
        }

        $name = array_pop($this->openSlots);

        $this->slots[$name] = ob_get_clean();
    }

    /**
     * Returns true if the slot exists.
     *
     * @param string $name The slot name
     *
     * @return Boolean
     *
     * @api
     */
    public function has($name)
    {
        return isset($this->slots[$name]);
    }

    /**
     * Gets the slot value.
     *
     * @param string         $name    The slot name
     * @param Boolean|string $default The default slot content
     *
     * @return string The slot content
     *
     * @api
     */
    public function get($name, $default = false)
    {
        return isset($this->slots[$name]) ? $this->slots[$name] : $default;
    }

    /**
     * Sets a slot value.
     *
     * @param string $name    The slot name
     * @param string $content The slot content
     *
     * @api
     */
    public function set($name, $content)
    {
        $this->slots[$name] = $content;
    }

    /**
     * Outputs a slot.
     *
     * @param string         $name    The slot name
     * @param Boolean|string $default The default slot content
     *
     * @return Boolean true if the slot is defined or if a default content has been provided, false otherwise
     *
     * @api
     */
    public function output($name, $default = false)
    {
        if (!isset($this->slots[$name])) {
            if (false !== $default) {
                echo $default;

                return true;
            }

            return false;
        }

        echo $this->slots[$name];

        return true;
    }

    /**
     * Returns the canonical name of this helper.
     *
     * @return string The canonical name
     *
     * @api
     */
    public function getName()
    {
        return 'slots';
    }
}
PK��ZV¤՟�4Symfony/Component/Templating/Helper/AssetsHelper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Helper;

use Symfony\Component\Templating\Asset\PathPackage;
use Symfony\Component\Templating\Asset\UrlPackage;

/**
 * AssetsHelper helps manage asset URLs.
 *
 * Usage:
 *
 * <code>
 *   <img src="<?php echo $view['assets']->getUrl('foo.png') ?>" />
 * </code>
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Kris Wallsmith <kris@symfony.com>
 */
class AssetsHelper extends CoreAssetsHelper
{
    /**
     * Constructor.
     *
     * @param string       $basePath      The base path
     * @param string|array $baseUrls      Base asset URLs
     * @param string       $version       The asset version
     * @param string       $format        The version format
     * @param array        $namedPackages Additional packages
     */
    public function __construct($basePath = null, $baseUrls = array(), $version = null, $format = null, $namedPackages = array())
    {
        if ($baseUrls) {
            $defaultPackage = new UrlPackage($baseUrls, $version, $format);
        } else {
            $defaultPackage = new PathPackage($basePath, $version, $format);
        }

        parent::__construct($defaultPackage, $namedPackages);
    }
}
PK��ZԷ����7Symfony/Component/Templating/Helper/HelperInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Helper;

/**
 * HelperInterface is the interface all helpers must implement.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface HelperInterface
{
    /**
     * Returns the canonical name of this helper.
     *
     * @return string The canonical name
     *
     * @api
     */
    public function getName();

    /**
     * Sets the default charset.
     *
     * @param string $charset The charset
     *
     * @api
     */
    public function setCharset($charset);

    /**
     * Gets the default charset.
     *
     * @return string The default charset
     *
     * @api
     */
    public function getCharset();
}
PK��Z����



8Symfony/Component/Templating/Helper/CoreAssetsHelper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Helper;

use Symfony\Component\Templating\Asset\PackageInterface;

/**
 * CoreAssetsHelper helps manage asset URLs.
 *
 * Usage:
 *
 * <code>
 *   <img src="<?php echo $view['assets']->getUrl('foo.png') ?>" />
 * </code>
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Kris Wallsmith <kris@symfony.com>
 */
class CoreAssetsHelper extends Helper implements PackageInterface
{
    protected $defaultPackage;
    protected $namedPackages = array();

    /**
     * Constructor.
     *
     * @param PackageInterface $defaultPackage The default package
     * @param array            $namedPackages  Additional packages indexed by name
     */
    public function __construct(PackageInterface $defaultPackage, array $namedPackages = array())
    {
        $this->defaultPackage = $defaultPackage;

        foreach ($namedPackages as $name => $package) {
            $this->addPackage($name, $package);
        }
    }

    /**
     * Sets the default package.
     *
     * @param PackageInterface $defaultPackage The default package
     */
    public function setDefaultPackage(PackageInterface $defaultPackage)
    {
        $this->defaultPackage = $defaultPackage;
    }

    /**
     * Adds an asset package to the helper.
     *
     * @param string           $name    The package name
     * @param PackageInterface $package The package
     */
    public function addPackage($name, PackageInterface $package)
    {
        $this->namedPackages[$name] = $package;
    }

    /**
     * Returns an asset package.
     *
     * @param string $name The name of the package or null for the default package
     *
     * @return PackageInterface An asset package
     *
     * @throws \InvalidArgumentException If there is no package by that name
     */
    public function getPackage($name = null)
    {
        if (null === $name) {
            return $this->defaultPackage;
        }

        if (!isset($this->namedPackages[$name])) {
            throw new \InvalidArgumentException(sprintf('There is no "%s" asset package.', $name));
        }

        return $this->namedPackages[$name];
    }

    /**
     * Gets the version to add to public URL.
     *
     * @param string $packageName A package name
     *
     * @return string The current version
     */
    public function getVersion($packageName = null)
    {
        return $this->getPackage($packageName)->getVersion();
    }

    /**
     * Returns the public path.
     *
     * Absolute paths (i.e. http://...) are returned unmodified.
     *
     * @param string $path        A public path
     * @param string $packageName The name of the asset package to use
     *
     * @return string A public path which takes into account the base path and URL path
     */
    public function getUrl($path, $packageName = null)
    {
        return $this->getPackage($packageName)->getUrl($path);
    }

    /**
     * Returns the canonical name of this helper.
     *
     * @return string The canonical name
     */
    public function getName()
    {
        return 'assets';
    }
}
PK��Z�NO��.Symfony/Component/Templating/Helper/Helper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Helper;

/**
 * Helper is the base class for all helper classes.
 *
 * Most of the time, a Helper is an adapter around an existing
 * class that exposes a read-only interface for templates.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
abstract class Helper implements HelperInterface
{
    protected $charset = 'UTF-8';

    /**
     * Sets the default charset.
     *
     * @param string $charset The charset
     *
     * @api
     */
    public function setCharset($charset)
    {
        $this->charset = $charset;
    }

    /**
     * Gets the default charset.
     *
     * @return string The default charset
     *
     * @api
     */
    public function getCharset()
    {
        return $this->charset;
    }
}
PK��Z_6H1Symfony/Component/Templating/DelegatingEngine.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating;

/**
 * DelegatingEngine selects an engine for a given template.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class DelegatingEngine implements EngineInterface, StreamingEngineInterface
{
    /**
     * @var EngineInterface[]
     */
    protected $engines = array();

    /**
     * Constructor.
     *
     * @param EngineInterface[] $engines An array of EngineInterface instances to add
     *
     * @api
     */
    public function __construct(array $engines = array())
    {
        foreach ($engines as $engine) {
            $this->addEngine($engine);
        }
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function render($name, array $parameters = array())
    {
        return $this->getEngine($name)->render($name, $parameters);
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function stream($name, array $parameters = array())
    {
        $engine = $this->getEngine($name);
        if (!$engine instanceof StreamingEngineInterface) {
            throw new \LogicException(sprintf('Template "%s" cannot be streamed as the engine supporting it does not implement StreamingEngineInterface.', $name));
        }

        $engine->stream($name, $parameters);
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function exists($name)
    {
        return $this->getEngine($name)->exists($name);
    }

    /**
     * Adds an engine.
     *
     * @param EngineInterface $engine An EngineInterface instance
     *
     * @api
     */
    public function addEngine(EngineInterface $engine)
    {
        $this->engines[] = $engine;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function supports($name)
    {
        try {
            $this->getEngine($name);
        } catch (\RuntimeException $e) {
            return false;
        }

        return true;
    }

    /**
     * Get an engine able to render the given template.
     *
     * @param string|TemplateReferenceInterface $name A template name or a TemplateReferenceInterface instance
     *
     * @return EngineInterface The engine
     *
     * @throws \RuntimeException if no engine able to work with the template is found
     *
     * @api
     */
    public function getEngine($name)
    {
        foreach ($this->engines as $engine) {
            if ($engine->supports($name)) {
                return $engine;
            }
        }

        throw new \RuntimeException(sprintf('No engine is able to work with the template "%s".', $name));
    }
}
PK��Z?w
y=y=*Symfony/Component/Templating/PhpEngine.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating;

use Symfony\Component\Templating\Storage\Storage;
use Symfony\Component\Templating\Storage\FileStorage;
use Symfony\Component\Templating\Storage\StringStorage;
use Symfony\Component\Templating\Helper\HelperInterface;
use Symfony\Component\Templating\Loader\LoaderInterface;

if (!defined('ENT_SUBSTITUTE')) {
    define('ENT_SUBSTITUTE', 8);
}

/**
 * PhpEngine is an engine able to render PHP templates.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class PhpEngine implements EngineInterface, \ArrayAccess
{
    protected $loader;
    protected $current;
    protected $helpers = array();
    protected $parents = array();
    protected $stack = array();
    protected $charset = 'UTF-8';
    protected $cache = array();
    protected $escapers = array();
    protected static $escaperCache = array();
    protected $globals = array();
    protected $parser;

    private $evalTemplate;
    private $evalParameters;

    /**
     * Constructor.
     *
     * @param TemplateNameParserInterface $parser  A TemplateNameParserInterface instance
     * @param LoaderInterface             $loader  A loader instance
     * @param HelperInterface[]           $helpers An array of helper instances
     */
    public function __construct(TemplateNameParserInterface $parser, LoaderInterface $loader, array $helpers = array())
    {
        $this->parser  = $parser;
        $this->loader  = $loader;

        $this->addHelpers($helpers);

        $this->initializeEscapers();
        foreach ($this->escapers as $context => $escaper) {
            $this->setEscaper($context, $escaper);
        }
    }

    /**
     * {@inheritdoc}
     *
     * @throws \InvalidArgumentException if the template does not exist
     *
     * @api
     */
    public function render($name, array $parameters = array())
    {
        $storage = $this->load($name);
        $key = hash('sha256', serialize($storage));
        $this->current = $key;
        $this->parents[$key] = null;

        // attach the global variables
        $parameters = array_replace($this->getGlobals(), $parameters);
        // render
        if (false === $content = $this->evaluate($storage, $parameters)) {
            throw new \RuntimeException(sprintf('The template "%s" cannot be rendered.', $this->parser->parse($name)));
        }

        // decorator
        if ($this->parents[$key]) {
            $slots = $this->get('slots');
            $this->stack[] = $slots->get('_content');
            $slots->set('_content', $content);

            $content = $this->render($this->parents[$key], $parameters);

            $slots->set('_content', array_pop($this->stack));
        }

        return $content;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function exists($name)
    {
        try {
            $this->load($name);
        } catch (\InvalidArgumentException $e) {
            return false;
        }

        return true;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function supports($name)
    {
        $template = $this->parser->parse($name);

        return 'php' === $template->get('engine');
    }

    /**
     * Evaluates a template.
     *
     * @param Storage $template   The template to render
     * @param array   $parameters An array of parameters to pass to the template
     *
     * @return string|false The evaluated template, or false if the engine is unable to render the template
     *
     * @throws \InvalidArgumentException
     */
    protected function evaluate(Storage $template, array $parameters = array())
    {
        $this->evalTemplate = $template;
        $this->evalParameters = $parameters;
        unset($template, $parameters);

        if (isset($this->evalParameters['this'])) {
            throw new \InvalidArgumentException('Invalid parameter (this)');
        }
        if (isset($this->evalParameters['view'])) {
            throw new \InvalidArgumentException('Invalid parameter (view)');
        }

        $view = $this;
        if ($this->evalTemplate instanceof FileStorage) {
            extract($this->evalParameters, EXTR_SKIP);
            $this->evalParameters = null;

            ob_start();
            require $this->evalTemplate;

            $this->evalTemplate = null;

            return ob_get_clean();
        } elseif ($this->evalTemplate instanceof StringStorage) {
            extract($this->evalParameters, EXTR_SKIP);
            $this->evalParameters = null;

            ob_start();
            eval('; ?>'.$this->evalTemplate.'<?php ;');

            $this->evalTemplate = null;

            return ob_get_clean();
        }

        return false;
    }

    /**
     * Gets a helper value.
     *
     * @param string $name The helper name
     *
     * @return HelperInterface The helper value
     *
     * @throws \InvalidArgumentException if the helper is not defined
     *
     * @api
     */
    public function offsetGet($name)
    {
        return $this->get($name);
    }

    /**
     * Returns true if the helper is defined.
     *
     * @param string $name The helper name
     *
     * @return Boolean true if the helper is defined, false otherwise
     *
     * @api
     */
    public function offsetExists($name)
    {
        return isset($this->helpers[$name]);
    }

    /**
     * Sets a helper.
     *
     * @param HelperInterface $name  The helper instance
     * @param string          $value An alias
     *
     * @api
     */
    public function offsetSet($name, $value)
    {
        $this->set($name, $value);
    }

    /**
     * Removes a helper.
     *
     * @param string $name The helper name
     *
     * @throws \LogicException
     *
     * @api
     */
    public function offsetUnset($name)
    {
        throw new \LogicException(sprintf('You can\'t unset a helper (%s).', $name));
    }

    /**
     * Adds some helpers.
     *
     * @param HelperInterface[] $helpers An array of helper
     *
     * @api
     */
    public function addHelpers(array $helpers)
    {
        foreach ($helpers as $alias => $helper) {
            $this->set($helper, is_int($alias) ? null : $alias);
        }
    }

    /**
     * Sets the helpers.
     *
     * @param HelperInterface[] $helpers An array of helper
     *
     * @api
     */
    public function setHelpers(array $helpers)
    {
        $this->helpers = array();
        $this->addHelpers($helpers);
    }

    /**
     * Sets a helper.
     *
     * @param HelperInterface $helper The helper instance
     * @param string          $alias  An alias
     *
     * @api
     */
    public function set(HelperInterface $helper, $alias = null)
    {
        $this->helpers[$helper->getName()] = $helper;
        if (null !== $alias) {
            $this->helpers[$alias] = $helper;
        }

        $helper->setCharset($this->charset);
    }

    /**
     * Returns true if the helper if defined.
     *
     * @param string $name The helper name
     *
     * @return Boolean true if the helper is defined, false otherwise
     *
     * @api
     */
    public function has($name)
    {
        return isset($this->helpers[$name]);
    }

    /**
     * Gets a helper value.
     *
     * @param string $name The helper name
     *
     * @return HelperInterface The helper instance
     *
     * @throws \InvalidArgumentException if the helper is not defined
     *
     * @api
     */
    public function get($name)
    {
        if (!isset($this->helpers[$name])) {
            throw new \InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name));
        }

        return $this->helpers[$name];
    }

    /**
     * Decorates the current template with another one.
     *
     * @param string $template The decorator logical name
     *
     * @api
     */
    public function extend($template)
    {
        $this->parents[$this->current] = $template;
    }

    /**
     * Escapes a string by using the current charset.
     *
     * @param mixed  $value   A variable to escape
     * @param string $context The context name
     *
     * @return string The escaped value
     *
     * @api
     */
    public function escape($value, $context = 'html')
    {
        if (is_numeric($value)) {
            return $value;
        }

        // If we deal with a scalar value, we can cache the result to increase
        // the performance when the same value is escaped multiple times (e.g. loops)
        if (is_scalar($value)) {
            if (!isset(self::$escaperCache[$context][$value])) {
                self::$escaperCache[$context][$value] = call_user_func($this->getEscaper($context), $value);
            }

            return self::$escaperCache[$context][$value];
        }

        return call_user_func($this->getEscaper($context), $value);
    }

    /**
     * Sets the charset to use.
     *
     * @param string $charset The charset
     *
     * @api
     */
    public function setCharset($charset)
    {
        $this->charset = $charset;
    }

    /**
     * Gets the current charset.
     *
     * @return string The current charset
     *
     * @api
     */
    public function getCharset()
    {
        return $this->charset;
    }

    /**
     * Adds an escaper for the given context.
     *
     * @param string $context The escaper context (html, js, ...)
     * @param mixed  $escaper A PHP callable
     *
     * @api
     */
    public function setEscaper($context, $escaper)
    {
        $this->escapers[$context] = $escaper;
        self::$escaperCache[$context] = array();
    }

    /**
     * Gets an escaper for a given context.
     *
     * @param string $context The context name
     *
     * @return mixed  $escaper A PHP callable
     *
     * @throws \InvalidArgumentException
     *
     * @api
     */
    public function getEscaper($context)
    {
        if (!isset($this->escapers[$context])) {
            throw new \InvalidArgumentException(sprintf('No registered escaper for context "%s".', $context));
        }

        return $this->escapers[$context];
    }

    /**
     * @param string $name
     * @param mixed  $value
     *
     * @api
     */
    public function addGlobal($name, $value)
    {
        $this->globals[$name] = $value;
    }

    /**
     * Returns the assigned globals.
     *
     * @return array
     *
     * @api
     */
    public function getGlobals()
    {
        return $this->globals;
    }

    /**
     * Initializes the built-in escapers.
     *
     * Each function specifies a way for applying a transformation to a string
     * passed to it. The purpose is for the string to be "escaped" so it is
     * suitable for the format it is being displayed in.
     *
     * For example, the string: "It's required that you enter a username & password.\n"
     * If this were to be displayed as HTML it would be sensible to turn the
     * ampersand into '&amp;' and the apostrophe into '&aps;'. However if it were
     * going to be used as a string in JavaScript to be displayed in an alert box
     * it would be right to leave the string as-is, but c-escape the apostrophe and
     * the new line.
     *
     * For each function there is a define to avoid problems with strings being
     * incorrectly specified.
     */
    protected function initializeEscapers()
    {
        $that = $this;

        $this->escapers = array(
            'html' =>
                /**
                 * Runs the PHP function htmlspecialchars on the value passed.
                 *
                 * @param string $value the value to escape
                 *
                 * @return string the escaped value
                 */
                function ($value) use ($that) {
                    // Numbers and Boolean values get turned into strings which can cause problems
                    // with type comparisons (e.g. === or is_int() etc).
                    return is_string($value) ? htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, $that->getCharset(), false) : $value;
                },

            'js' =>
                /**
                 * A function that escape all non-alphanumeric characters
                 * into their \xHH or \uHHHH representations
                 *
                 * @param string $value the value to escape
                 * @return string the escaped value
                 */
                function ($value) use ($that) {
                    if ('UTF-8' != $that->getCharset()) {
                        $value = $that->convertEncoding($value, 'UTF-8', $that->getCharset());
                    }

                    $callback = function ($matches) use ($that) {
                        $char = $matches[0];

                        // \xHH
                        if (!isset($char[1])) {
                            return '\\x'.substr('00'.bin2hex($char), -2);
                        }

                        // \uHHHH
                        $char = $that->convertEncoding($char, 'UTF-16BE', 'UTF-8');

                        return '\\u'.substr('0000'.bin2hex($char), -4);
                    };

                    if (null === $value = preg_replace_callback('#[^\p{L}\p{N} ]#u', $callback, $value)) {
                        throw new \InvalidArgumentException('The string to escape is not a valid UTF-8 string.');
                    }

                    if ('UTF-8' != $that->getCharset()) {
                        $value = $that->convertEncoding($value, $that->getCharset(), 'UTF-8');
                    }

                    return $value;
                },
        );

        self::$escaperCache = array();
    }

    /**
     * Convert a string from one encoding to another.
     *
     * @param string $string The string to convert
     * @param string $to     The input encoding
     * @param string $from   The output encoding
     *
     * @return string The string with the new encoding
     *
     * @throws \RuntimeException if no suitable encoding function is found (iconv or mbstring)
     */
    public function convertEncoding($string, $to, $from)
    {
        if (function_exists('mb_convert_encoding')) {
            return mb_convert_encoding($string, $to, $from);
        } elseif (function_exists('iconv')) {
            return iconv($from, $to, $string);
        }

        throw new \RuntimeException('No suitable convert encoding function (use UTF-8 as your encoding or install the iconv or mbstring extension).');
    }

    /**
     * Gets the loader associated with this engine.
     *
     * @return LoaderInterface A LoaderInterface instance
     */
    public function getLoader()
    {
        return $this->loader;
    }

    /**
     * Loads the given template.
     *
     * @param string|TemplateReferenceInterface $name A template name or a TemplateReferenceInterface instance
     *
     * @return Storage A Storage instance
     *
     * @throws \InvalidArgumentException if the template cannot be found
     */
    protected function load($name)
    {
        $template = $this->parser->parse($name);

        $key = $template->getLogicalName();
        if (isset($this->cache[$key])) {
            return $this->cache[$key];
        }

        $storage = $this->loader->load($template);

        if (false === $storage) {
            throw new \InvalidArgumentException(sprintf('The template "%s" does not exist.', $template));
        }

        return $this->cache[$key] = $storage;
    }
}
PK��Z6�H	��$Symfony/Component/Yaml/Unescaper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Yaml;

/**
 * Unescaper encapsulates unescaping rules for single and double-quoted
 * YAML strings.
 *
 * @author Matthew Lewinski <matthew@lewinski.org>
 */
class Unescaper
{
    // Parser and Inline assume UTF-8 encoding, so escaped Unicode characters
    // must be converted to that encoding.
    const ENCODING = 'UTF-8';

    // Regex fragment that matches an escaped character in a double quoted
    // string.
    const REGEX_ESCAPED_CHARACTER = "\\\\([0abt\tnvfre \\\"\\/\\\\N_LP]|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8})";

    /**
     * Unescapes a single quoted string.
     *
     * @param string $value A single quoted string.
     *
     * @return string The unescaped string.
     */
    public function unescapeSingleQuotedString($value)
    {
        return str_replace('\'\'', '\'', $value);
    }

    /**
     * Unescapes a double quoted string.
     *
     * @param string $value A double quoted string.
     *
     * @return string The unescaped string.
     */
    public function unescapeDoubleQuotedString($value)
    {
        $self = $this;
        $callback = function ($match) use ($self) {
            return $self->unescapeCharacter($match[0]);
        };

        // evaluate the string
        return preg_replace_callback('/'.self::REGEX_ESCAPED_CHARACTER.'/u', $callback, $value);
    }

    /**
     * Unescapes a character that was found in a double-quoted string
     *
     * @param string $value An escaped character
     *
     * @return string The unescaped character
     */
    public function unescapeCharacter($value)
    {
        switch ($value{1}) {
            case '0':
                return "\x0";
            case 'a':
                return "\x7";
            case 'b':
                return "\x8";
            case 't':
                return "\t";
            case "\t":
                return "\t";
            case 'n':
                return "\n";
            case 'v':
                return "\xb";
            case 'f':
                return "\xc";
            case 'r':
                return "\xd";
            case 'e':
                return "\x1b";
            case ' ':
                return ' ';
            case '"':
                return '"';
            case '/':
                return '/';
            case '\\':
                return '\\';
            case 'N':
                // U+0085 NEXT LINE
                return $this->convertEncoding("\x00\x85", self::ENCODING, 'UCS-2BE');
            case '_':
                // U+00A0 NO-BREAK SPACE
                return $this->convertEncoding("\x00\xA0", self::ENCODING, 'UCS-2BE');
            case 'L':
                // U+2028 LINE SEPARATOR
                return $this->convertEncoding("\x20\x28", self::ENCODING, 'UCS-2BE');
            case 'P':
                // U+2029 PARAGRAPH SEPARATOR
                return $this->convertEncoding("\x20\x29", self::ENCODING, 'UCS-2BE');
            case 'x':
                $char = pack('n', hexdec(substr($value, 2, 2)));

                return $this->convertEncoding($char, self::ENCODING, 'UCS-2BE');
            case 'u':
                $char = pack('n', hexdec(substr($value, 2, 4)));

                return $this->convertEncoding($char, self::ENCODING, 'UCS-2BE');
            case 'U':
                $char = pack('N', hexdec(substr($value, 2, 8)));

                return $this->convertEncoding($char, self::ENCODING, 'UCS-4BE');
        }
    }

    /**
     * Convert a string from one encoding to another.
     *
     * @param string $value The string to convert
     * @param string $to    The input encoding
     * @param string $from  The output encoding
     *
     * @return string The string with the new encoding
     *
     * @throws \RuntimeException if no suitable encoding function is found (iconv or mbstring)
     */
    private function convertEncoding($value, $to, $from)
    {
        if (function_exists('mb_convert_encoding')) {
            return mb_convert_encoding($value, $to, $from);
        } elseif (function_exists('iconv')) {
            return iconv($from, $to, $value);
        }

        throw new \RuntimeException('No suitable convert encoding function (install the iconv or mbstring extension).');
    }
}
PK��Z�8�n�	�	!Symfony/Component/Yaml/Dumper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Yaml;

/**
 * Dumper dumps PHP variables to YAML strings.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Dumper
{
    /**
     * The amount of spaces to use for indentation of nested nodes.
     *
     * @var integer
     */
    protected $indentation = 4;

    /**
     * Sets the indentation.
     *
     * @param integer $num The amount of spaces to use for indentation of nested nodes.
     */
    public function setIndentation($num)
    {
        $this->indentation = (int) $num;
    }

    /**
     * Dumps a PHP value to YAML.
     *
     * @param mixed   $input                  The PHP value
     * @param integer $inline                 The level where you switch to inline YAML
     * @param integer $indent                 The level of indentation (used internally)
     * @param Boolean $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise
     * @param Boolean $objectSupport          true if object support is enabled, false otherwise
     *
     * @return string  The YAML representation of the PHP value
     */
    public function dump($input, $inline = 0, $indent = 0, $exceptionOnInvalidType = false, $objectSupport = false)
    {
        $output = '';
        $prefix = $indent ? str_repeat(' ', $indent) : '';

        if ($inline <= 0 || !is_array($input) || empty($input)) {
            $output .= $prefix.Inline::dump($input, $exceptionOnInvalidType, $objectSupport);
        } else {
            $isAHash = array_keys($input) !== range(0, count($input) - 1);

            foreach ($input as $key => $value) {
                $willBeInlined = $inline - 1 <= 0 || !is_array($value) || empty($value);

                $output .= sprintf('%s%s%s%s',
                    $prefix,
                    $isAHash ? Inline::dump($key, $exceptionOnInvalidType, $objectSupport).':' : '-',
                    $willBeInlined ? ' ' : "\n",
                    $this->dump($value, $inline - 1, $willBeInlined ? 0 : $indent + $this->indentation, $exceptionOnInvalidType, $objectSupport)
                ).($willBeInlined ? "\n" : '');
            }
        }

        return $output;
    }
}
PK��Z�bNN%Symfony/Component/Yaml/autoloader.phpnu�[���<?php

spl_autoload_register(function ($class) {
    if ('\\' == $class[0]) {
        $class = substr($class, 1);
    }

    if (
        0 === strpos($class, 'Symfony\\Component\\Yaml\\')
        &&
        file_exists($file = __DIR__.'/../../../'.str_replace('\\', '/', $class).'.php')
    ) {
        require_once $file;
    }
});
PK��Z��X��[�[!Symfony/Component/Yaml/Parser.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Yaml;

use Symfony\Component\Yaml\Exception\ParseException;

/**
 * Parser parses YAML strings to convert them to PHP arrays.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Parser
{
    const FOLDED_SCALAR_PATTERN = '(?P<separator>\||>)(?P<modifiers>\+|\-|\d+|\+\d+|\-\d+|\d+\+|\d+\-)?(?P<comments> +#.*)?';

    private $offset         = 0;
    private $lines          = array();
    private $currentLineNb  = -1;
    private $currentLine    = '';
    private $refs           = array();

    /**
     * Constructor
     *
     * @param integer $offset The offset of YAML document (used for line numbers in error messages)
     */
    public function __construct($offset = 0)
    {
        $this->offset = $offset;
    }

    /**
     * Parses a YAML string to a PHP value.
     *
     * @param string  $value                  A YAML string
     * @param Boolean $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise
     * @param Boolean $objectSupport          true if object support is enabled, false otherwise
     *
     * @return mixed  A PHP value
     *
     * @throws ParseException If the YAML is not valid
     */
    public function parse($value, $exceptionOnInvalidType = false, $objectSupport = false)
    {
        $this->currentLineNb = -1;
        $this->currentLine = '';
        $this->lines = explode("\n", $this->cleanup($value));

        if (function_exists('mb_detect_encoding') && false === mb_detect_encoding($value, 'UTF-8', true)) {
            throw new ParseException('The YAML value does not appear to be valid UTF-8.');
        }

        if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) {
            $mbEncoding = mb_internal_encoding();
            mb_internal_encoding('UTF-8');
        }

        $data = array();
        $context = null;
        while ($this->moveToNextLine()) {
            if ($this->isCurrentLineEmpty()) {
                continue;
            }

            // tab?
            if ("\t" === $this->currentLine[0]) {
                throw new ParseException('A YAML file cannot contain tabs as indentation.', $this->getRealCurrentLineNb() + 1, $this->currentLine);
            }

            $isRef = $isInPlace = $isProcessed = false;
            if (preg_match('#^\-((?P<leadspaces>\s+)(?P<value>.+?))?\s*$#u', $this->currentLine, $values)) {
                if ($context && 'mapping' == $context) {
                    throw new ParseException('You cannot define a sequence item when in a mapping');
                }
                $context = 'sequence';

                if (isset($values['value']) && preg_match('#^&(?P<ref>[^ ]+) *(?P<value>.*)#u', $values['value'], $matches)) {
                    $isRef = $matches['ref'];
                    $values['value'] = $matches['value'];
                }

                // array
                if (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#')) {
                    $c = $this->getRealCurrentLineNb() + 1;
                    $parser = new Parser($c);
                    $parser->refs =& $this->refs;
                    $data[] = $parser->parse($this->getNextEmbedBlock(), $exceptionOnInvalidType, $objectSupport);
                } else {
                    if (isset($values['leadspaces'])
                        && ' ' == $values['leadspaces']
                        && preg_match('#^(?P<key>'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\{\[].*?) *\:(\s+(?P<value>.+?))?\s*$#u', $values['value'], $matches)
                    ) {
                        // this is a compact notation element, add to next block and parse
                        $c = $this->getRealCurrentLineNb();
                        $parser = new Parser($c);
                        $parser->refs =& $this->refs;

                        $block = $values['value'];
                        if ($this->isNextLineIndented()) {
                            $block .= "\n".$this->getNextEmbedBlock($this->getCurrentLineIndentation() + 2);
                        }

                        $data[] = $parser->parse($block, $exceptionOnInvalidType, $objectSupport);
                    } else {
                        $data[] = $this->parseValue($values['value'], $exceptionOnInvalidType, $objectSupport);
                    }
                }
            } elseif (preg_match('#^(?P<key>'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\[\{].*?) *\:(\s+(?P<value>.+?))?\s*$#u', $this->currentLine, $values) && false === strpos($values['key'],' #')) {
                if ($context && 'sequence' == $context) {
                    throw new ParseException('You cannot define a mapping item when in a sequence');
                }
                $context = 'mapping';

                // force correct settings
                Inline::parse(null, $exceptionOnInvalidType, $objectSupport);
                try {
                    $key = Inline::parseScalar($values['key']);
                } catch (ParseException $e) {
                    $e->setParsedLine($this->getRealCurrentLineNb() + 1);
                    $e->setSnippet($this->currentLine);

                    throw $e;
                }

                if ('<<' === $key) {
                    if (isset($values['value']) && 0 === strpos($values['value'], '*')) {
                        $isInPlace = substr($values['value'], 1);
                        if (!array_key_exists($isInPlace, $this->refs)) {
                            throw new ParseException(sprintf('Reference "%s" does not exist.', $isInPlace), $this->getRealCurrentLineNb() + 1, $this->currentLine);
                        }
                    } else {
                        if (isset($values['value']) && $values['value'] !== '') {
                            $value = $values['value'];
                        } else {
                            $value = $this->getNextEmbedBlock();
                        }
                        $c = $this->getRealCurrentLineNb() + 1;
                        $parser = new Parser($c);
                        $parser->refs =& $this->refs;
                        $parsed = $parser->parse($value, $exceptionOnInvalidType, $objectSupport);

                        $merged = array();
                        if (!is_array($parsed)) {
                            throw new ParseException('YAML merge keys used with a scalar value instead of an array.', $this->getRealCurrentLineNb() + 1, $this->currentLine);
                        } elseif (isset($parsed[0])) {
                            // Numeric array, merge individual elements
                            foreach (array_reverse($parsed) as $parsedItem) {
                                if (!is_array($parsedItem)) {
                                    throw new ParseException('Merge items must be arrays.', $this->getRealCurrentLineNb() + 1, $parsedItem);
                                }
                                $merged = array_merge($parsedItem, $merged);
                            }
                        } else {
                            // Associative array, merge
                            $merged = array_merge($merged, $parsed);
                        }

                        $isProcessed = $merged;
                    }
                } elseif (isset($values['value']) && preg_match('#^&(?P<ref>[^ ]+) *(?P<value>.*)#u', $values['value'], $matches)) {
                    $isRef = $matches['ref'];
                    $values['value'] = $matches['value'];
                }

                if ($isProcessed) {
                    // Merge keys
                    $data = $isProcessed;
                // hash
                } elseif (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#')) {
                    // if next line is less indented or equal, then it means that the current value is null
                    if (!$this->isNextLineIndented() && !$this->isNextLineUnIndentedCollection()) {
                        $data[$key] = null;
                    } else {
                        $c = $this->getRealCurrentLineNb() + 1;
                        $parser = new Parser($c);
                        $parser->refs =& $this->refs;
                        $data[$key] = $parser->parse($this->getNextEmbedBlock(), $exceptionOnInvalidType, $objectSupport);
                    }
                } else {
                    if ($isInPlace) {
                        $data = $this->refs[$isInPlace];
                    } else {
                        $data[$key] = $this->parseValue($values['value'], $exceptionOnInvalidType, $objectSupport);
                    }
                }
            } else {
                // 1-liner optionally followed by newline
                $lineCount = count($this->lines);
                if (1 === $lineCount || (2 === $lineCount && empty($this->lines[1]))) {
                    try {
                        $value = Inline::parse($this->lines[0], $exceptionOnInvalidType, $objectSupport);
                    } catch (ParseException $e) {
                        $e->setParsedLine($this->getRealCurrentLineNb() + 1);
                        $e->setSnippet($this->currentLine);

                        throw $e;
                    }

                    if (is_array($value)) {
                        $first = reset($value);
                        if (is_string($first) && 0 === strpos($first, '*')) {
                            $data = array();
                            foreach ($value as $alias) {
                                $data[] = $this->refs[substr($alias, 1)];
                            }
                            $value = $data;
                        }
                    }

                    if (isset($mbEncoding)) {
                        mb_internal_encoding($mbEncoding);
                    }

                    return $value;
                }

                switch (preg_last_error()) {
                    case PREG_INTERNAL_ERROR:
                        $error = 'Internal PCRE error.';
                        break;
                    case PREG_BACKTRACK_LIMIT_ERROR:
                        $error = 'pcre.backtrack_limit reached.';
                        break;
                    case PREG_RECURSION_LIMIT_ERROR:
                        $error = 'pcre.recursion_limit reached.';
                        break;
                    case PREG_BAD_UTF8_ERROR:
                        $error = 'Malformed UTF-8 data.';
                        break;
                    case PREG_BAD_UTF8_OFFSET_ERROR:
                        $error = 'Offset doesn\'t correspond to the begin of a valid UTF-8 code point.';
                        break;
                    default:
                        $error = 'Unable to parse.';
                }

                throw new ParseException($error, $this->getRealCurrentLineNb() + 1, $this->currentLine);
            }

            if ($isRef) {
                $this->refs[$isRef] = end($data);
            }
        }

        if (isset($mbEncoding)) {
            mb_internal_encoding($mbEncoding);
        }

        return empty($data) ? null : $data;
    }

    /**
     * Returns the current line number (takes the offset into account).
     *
     * @return integer The current line number
     */
    private function getRealCurrentLineNb()
    {
        return $this->currentLineNb + $this->offset;
    }

    /**
     * Returns the current line indentation.
     *
     * @return integer The current line indentation
     */
    private function getCurrentLineIndentation()
    {
        return strlen($this->currentLine) - strlen(ltrim($this->currentLine, ' '));
    }

    /**
     * Returns the next embed block of YAML.
     *
     * @param integer $indentation The indent level at which the block is to be read, or null for default
     *
     * @return string A YAML string
     *
     * @throws ParseException When indentation problem are detected
     */
    private function getNextEmbedBlock($indentation = null)
    {
        $this->moveToNextLine();

        if (null === $indentation) {
            $newIndent = $this->getCurrentLineIndentation();

            $unindentedEmbedBlock = $this->isStringUnIndentedCollectionItem($this->currentLine);

            if (!$this->isCurrentLineEmpty() && 0 === $newIndent && !$unindentedEmbedBlock) {
                throw new ParseException('Indentation problem.', $this->getRealCurrentLineNb() + 1, $this->currentLine);
            }
        } else {
            $newIndent = $indentation;
        }

        $data = array(substr($this->currentLine, $newIndent));

        $isItUnindentedCollection = $this->isStringUnIndentedCollectionItem($this->currentLine);

        // Comments must not be removed inside a string block (ie. after a line ending with "|")
        $removeCommentsPattern = '~'.self::FOLDED_SCALAR_PATTERN.'$~';
        $removeComments = !preg_match($removeCommentsPattern, $this->currentLine);

        while ($this->moveToNextLine()) {
            $indent = $this->getCurrentLineIndentation();

            if ($indent === $newIndent) {
                $removeComments = !preg_match($removeCommentsPattern, $this->currentLine);
            }

            if ($isItUnindentedCollection && !$this->isStringUnIndentedCollectionItem($this->currentLine)) {
                $this->moveToPreviousLine();
                break;
            }

            if ($this->isCurrentLineBlank()) {
                $data[] = substr($this->currentLine, $newIndent);
                continue;
            }

            if ($removeComments && $this->isCurrentLineComment()) {
                continue;
            }

            if ($indent >= $newIndent) {
                $data[] = substr($this->currentLine, $newIndent);
            } elseif (0 == $indent) {
                $this->moveToPreviousLine();

                break;
            } else {
                throw new ParseException('Indentation problem.', $this->getRealCurrentLineNb() + 1, $this->currentLine);
            }
        }

        return implode("\n", $data);
    }

    /**
     * Moves the parser to the next line.
     *
     * @return Boolean
     */
    private function moveToNextLine()
    {
        if ($this->currentLineNb >= count($this->lines) - 1) {
            return false;
        }

        $this->currentLine = $this->lines[++$this->currentLineNb];

        return true;
    }

    /**
     * Moves the parser to the previous line.
     */
    private function moveToPreviousLine()
    {
        $this->currentLine = $this->lines[--$this->currentLineNb];
    }

    /**
     * Parses a YAML value.
     *
     * @param string  $value                  A YAML value
     * @param Boolean $exceptionOnInvalidType True if an exception must be thrown on invalid types false otherwise
     * @param Boolean $objectSupport          True if object support is enabled, false otherwise
     *
     * @return mixed  A PHP value
     *
     * @throws ParseException When reference does not exist
     */
    private function parseValue($value, $exceptionOnInvalidType, $objectSupport)
    {
        if (0 === strpos($value, '*')) {
            if (false !== $pos = strpos($value, '#')) {
                $value = substr($value, 1, $pos - 2);
            } else {
                $value = substr($value, 1);
            }

            if (!array_key_exists($value, $this->refs)) {
                throw new ParseException(sprintf('Reference "%s" does not exist.', $value), $this->currentLine);
            }

            return $this->refs[$value];
        }

        if (preg_match('/^'.self::FOLDED_SCALAR_PATTERN.'$/', $value, $matches)) {
            $modifiers = isset($matches['modifiers']) ? $matches['modifiers'] : '';

            return $this->parseFoldedScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), intval(abs($modifiers)));
        }

        try {
            return Inline::parse($value, $exceptionOnInvalidType, $objectSupport);
        } catch (ParseException $e) {
            $e->setParsedLine($this->getRealCurrentLineNb() + 1);
            $e->setSnippet($this->currentLine);

            throw $e;
        }
    }

    /**
     * Parses a folded scalar.
     *
     * @param string  $separator   The separator that was used to begin this folded scalar (| or >)
     * @param string  $indicator   The indicator that was used to begin this folded scalar (+ or -)
     * @param integer $indentation The indentation that was used to begin this folded scalar
     *
     * @return string  The text value
     */
    private function parseFoldedScalar($separator, $indicator = '', $indentation = 0)
    {
        $notEOF = $this->moveToNextLine();
        if (!$notEOF) {
            return '';
        }

        $isCurrentLineBlank = $this->isCurrentLineBlank();
        $text = '';

        // leading blank lines are consumed before determining indentation
        while ($notEOF && $isCurrentLineBlank) {
            // newline only if not EOF
            if ($notEOF = $this->moveToNextLine()) {
                $text .= "\n";
                $isCurrentLineBlank = $this->isCurrentLineBlank();
            }
        }

        // determine indentation if not specified
        if (0 === $indentation) {
            if (preg_match('/^ +/', $this->currentLine, $matches)) {
                $indentation = strlen($matches[0]);
            }
        }

        if ($indentation > 0) {
            $pattern = sprintf('/^ {%d}(.*)$/', $indentation);

            while (
                $notEOF && (
                    $isCurrentLineBlank ||
                    preg_match($pattern, $this->currentLine, $matches)
                )
            ) {
                if ($isCurrentLineBlank) {
                    $text .= substr($this->currentLine, $indentation);
                } else {
                    $text .= $matches[1];
                }

                // newline only if not EOF
                if ($notEOF = $this->moveToNextLine()) {
                    $text .= "\n";
                    $isCurrentLineBlank = $this->isCurrentLineBlank();
                }
            }
        } elseif ($notEOF) {
            $text .= "\n";
        }

        if ($notEOF) {
            $this->moveToPreviousLine();
        }

        // replace all non-trailing single newlines with spaces in folded blocks
        if ('>' === $separator) {
            preg_match('/(\n*)$/', $text, $matches);
            $text = preg_replace('/(?<!\n)\n(?!\n)/', ' ', rtrim($text, "\n"));
            $text .= $matches[1];
        }

        // deal with trailing newlines as indicated
        if ('' === $indicator) {
            $text = preg_replace('/\n+$/s', "\n", $text);
        } elseif ('-' === $indicator) {
            $text = preg_replace('/\n+$/s', '', $text);
        }

        return $text;
    }

    /**
     * Returns true if the next line is indented.
     *
     * @return Boolean Returns true if the next line is indented, false otherwise
     */
    private function isNextLineIndented()
    {
        $currentIndentation = $this->getCurrentLineIndentation();
        $EOF = !$this->moveToNextLine();

        while (!$EOF && $this->isCurrentLineEmpty()) {
            $EOF = !$this->moveToNextLine();
        }

        if ($EOF) {
            return false;
        }

        $ret = false;
        if ($this->getCurrentLineIndentation() > $currentIndentation) {
            $ret = true;
        }

        $this->moveToPreviousLine();

        return $ret;
    }

    /**
     * Returns true if the current line is blank or if it is a comment line.
     *
     * @return Boolean Returns true if the current line is empty or if it is a comment line, false otherwise
     */
    private function isCurrentLineEmpty()
    {
        return $this->isCurrentLineBlank() || $this->isCurrentLineComment();
    }

    /**
     * Returns true if the current line is blank.
     *
     * @return Boolean Returns true if the current line is blank, false otherwise
     */
    private function isCurrentLineBlank()
    {
        return '' == trim($this->currentLine, ' ');
    }

    /**
     * Returns true if the current line is a comment line.
     *
     * @return Boolean Returns true if the current line is a comment line, false otherwise
     */
    private function isCurrentLineComment()
    {
        //checking explicitly the first char of the trim is faster than loops or strpos
        $ltrimmedLine = ltrim($this->currentLine, ' ');

        return $ltrimmedLine[0] === '#';
    }

    /**
     * Cleanups a YAML string to be parsed.
     *
     * @param string $value The input YAML string
     *
     * @return string A cleaned up YAML string
     */
    private function cleanup($value)
    {
        $value = str_replace(array("\r\n", "\r"), "\n", $value);

        // strip YAML header
        $count = 0;
        $value = preg_replace('#^\%YAML[: ][\d\.]+.*\n#su', '', $value, -1, $count);
        $this->offset += $count;

        // remove leading comments
        $trimmedValue = preg_replace('#^(\#.*?\n)+#s', '', $value, -1, $count);
        if ($count == 1) {
            // items have been removed, update the offset
            $this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n");
            $value = $trimmedValue;
        }

        // remove start of the document marker (---)
        $trimmedValue = preg_replace('#^\-\-\-.*?\n#s', '', $value, -1, $count);
        if ($count == 1) {
            // items have been removed, update the offset
            $this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n");
            $value = $trimmedValue;

            // remove end of the document marker (...)
            $value = preg_replace('#\.\.\.\s*$#s', '', $value);
        }

        return $value;
    }

    /**
     * Returns true if the next line starts unindented collection
     *
     * @return Boolean Returns true if the next line starts unindented collection, false otherwise
     */
    private function isNextLineUnIndentedCollection()
    {
        $currentIndentation = $this->getCurrentLineIndentation();
        $notEOF = $this->moveToNextLine();

        while ($notEOF && $this->isCurrentLineEmpty()) {
            $notEOF = $this->moveToNextLine();
        }

        if (false === $notEOF) {
            return false;
        }

        $ret = false;
        if (
            $this->getCurrentLineIndentation() == $currentIndentation
            &&
            $this->isStringUnIndentedCollectionItem($this->currentLine)
        ) {
            $ret = true;
        }

        $this->moveToPreviousLine();

        return $ret;
    }

    /**
     * Returns true if the string is un-indented collection item
     *
     * @return Boolean Returns true if the string is un-indented collection item, false otherwise
     */
    private function isStringUnIndentedCollectionItem()
    {
        return (0 === strpos($this->currentLine, '- '));
    }

}
PK��Z7MӺ

Symfony/Component/Yaml/Yaml.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Yaml;

use Symfony\Component\Yaml\Exception\ParseException;

/**
 * Yaml offers convenience methods to load and dump YAML.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class Yaml
{
    /**
     * Parses YAML into a PHP array.
     *
     * The parse method, when supplied with a YAML stream (string or file),
     * will do its best to convert YAML in a file into a PHP array.
     *
     *  Usage:
     *  <code>
     *   $array = Yaml::parse('config.yml');
     *   print_r($array);
     *  </code>
     *
     * As this method accepts both plain strings and file names as an input,
     * you must validate the input before calling this method. Passing a file
     * as an input is a deprecated feature and will be removed in 3.0.
     *
     * @param string  $input                  Path to a YAML file or a string containing YAML
     * @param Boolean $exceptionOnInvalidType True if an exception must be thrown on invalid types false otherwise
     * @param Boolean $objectSupport          True if object support is enabled, false otherwise
     *
     * @return array The YAML converted to a PHP array
     *
     * @throws ParseException If the YAML is not valid
     *
     * @api
     */
    public static function parse($input, $exceptionOnInvalidType = false, $objectSupport = false)
    {
        // if input is a file, process it
        $file = '';
        if (strpos($input, "\n") === false && is_file($input)) {
            if (false === is_readable($input)) {
                throw new ParseException(sprintf('Unable to parse "%s" as the file is not readable.', $input));
            }

            $file = $input;
            $input = file_get_contents($file);
        }

        $yaml = new Parser();

        try {
            return $yaml->parse($input, $exceptionOnInvalidType, $objectSupport);
        } catch (ParseException $e) {
            if ($file) {
                $e->setParsedFile($file);
            }

            throw $e;
        }
    }

    /**
     * Dumps a PHP array to a YAML string.
     *
     * The dump method, when supplied with an array, will do its best
     * to convert the array into friendly YAML.
     *
     * @param array   $array                  PHP array
     * @param integer $inline                 The level where you switch to inline YAML
     * @param integer $indent                 The amount of spaces to use for indentation of nested nodes.
     * @param Boolean $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise
     * @param Boolean $objectSupport          true if object support is enabled, false otherwise
     *
     * @return string A YAML string representing the original PHP array
     *
     * @api
     */
    public static function dump($array, $inline = 2, $indent = 4, $exceptionOnInvalidType = false, $objectSupport = false)
    {
        $yaml = new Dumper();
        $yaml->setIndentation($indent);

        return $yaml->dump($array, $inline, 0, $exceptionOnInvalidType, $objectSupport);
    }
}
PK��Z�+�l��7Symfony/Component/Yaml/Exception/ExceptionInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Yaml\Exception;

/**
 * Exception interface for all exceptions thrown by the component.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface ExceptionInterface
{
}
PK��Z�|�-��5Symfony/Component/Yaml/Exception/RuntimeException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Yaml\Exception;

/**
 * Exception class thrown when an error occurs during parsing.
 *
 * @author Romain Neutron <imprec@gmail.com>
 *
 * @api
 */
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
PK��Z�����
�
3Symfony/Component/Yaml/Exception/ParseException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Yaml\Exception;

if (!defined('JSON_UNESCAPED_UNICODE')) {
    define('JSON_UNESCAPED_SLASHES', 64);
    define('JSON_UNESCAPED_UNICODE', 256);
}

/**
 * Exception class thrown when an error occurs during parsing.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class ParseException extends RuntimeException
{
    private $parsedFile;
    private $parsedLine;
    private $snippet;
    private $rawMessage;

    /**
     * Constructor.
     *
     * @param string    $message    The error message
     * @param integer   $parsedLine The line where the error occurred
     * @param integer   $snippet    The snippet of code near the problem
     * @param string    $parsedFile The file name where the error occurred
     * @param \Exception $previous   The previous exception
     */
    public function __construct($message, $parsedLine = -1, $snippet = null, $parsedFile = null, \Exception $previous = null)
    {
        $this->parsedFile = $parsedFile;
        $this->parsedLine = $parsedLine;
        $this->snippet = $snippet;
        $this->rawMessage = $message;

        $this->updateRepr();

        parent::__construct($this->message, 0, $previous);
    }

    /**
     * Gets the snippet of code near the error.
     *
     * @return string The snippet of code
     */
    public function getSnippet()
    {
        return $this->snippet;
    }

    /**
     * Sets the snippet of code near the error.
     *
     * @param string $snippet The code snippet
     */
    public function setSnippet($snippet)
    {
        $this->snippet = $snippet;

        $this->updateRepr();
    }

    /**
     * Gets the filename where the error occurred.
     *
     * This method returns null if a string is parsed.
     *
     * @return string The filename
     */
    public function getParsedFile()
    {
        return $this->parsedFile;
    }

    /**
     * Sets the filename where the error occurred.
     *
     * @param string $parsedFile The filename
     */
    public function setParsedFile($parsedFile)
    {
        $this->parsedFile = $parsedFile;

        $this->updateRepr();
    }

    /**
     * Gets the line where the error occurred.
     *
     * @return integer The file line
     */
    public function getParsedLine()
    {
        return $this->parsedLine;
    }

    /**
     * Sets the line where the error occurred.
     *
     * @param integer $parsedLine The file line
     */
    public function setParsedLine($parsedLine)
    {
        $this->parsedLine = $parsedLine;

        $this->updateRepr();
    }

    private function updateRepr()
    {
        $this->message = $this->rawMessage;

        $dot = false;
        if ('.' === substr($this->message, -1)) {
            $this->message = substr($this->message, 0, -1);
            $dot = true;
        }

        if (null !== $this->parsedFile) {
            $this->message .= sprintf(' in %s', json_encode($this->parsedFile, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
        }

        if ($this->parsedLine >= 0) {
            $this->message .= sprintf(' at line %d', $this->parsedLine);
        }

        if ($this->snippet) {
            $this->message .= sprintf(' (near "%s")', $this->snippet);
        }

        if ($dot) {
            $this->message .= '.';
        }
    }
}
PK��Zؙ՚��2Symfony/Component/Yaml/Exception/DumpException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Yaml\Exception;

/**
 * Exception class thrown when an error occurs during dumping.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class DumpException extends RuntimeException
{
}
PK��Z)%�,m
m
"Symfony/Component/Yaml/Escaper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Yaml;

/**
 * Escaper encapsulates escaping rules for single and double-quoted
 * YAML strings.
 *
 * @author Matthew Lewinski <matthew@lewinski.org>
 */
class Escaper
{
    // Characters that would cause a dumped string to require double quoting.
    const REGEX_CHARACTER_TO_ESCAPE = "[\\x00-\\x1f]|\xc2\x85|\xc2\xa0|\xe2\x80\xa8|\xe2\x80\xa9";

    // Mapping arrays for escaping a double quoted string. The backslash is
    // first to ensure proper escaping because str_replace operates iteratively
    // on the input arrays. This ordering of the characters avoids the use of strtr,
    // which performs more slowly.
    private static $escapees = array('\\\\', '\\"', '"',
                                     "\x00",  "\x01",  "\x02",  "\x03",  "\x04",  "\x05",  "\x06",  "\x07",
                                     "\x08",  "\x09",  "\x0a",  "\x0b",  "\x0c",  "\x0d",  "\x0e",  "\x0f",
                                     "\x10",  "\x11",  "\x12",  "\x13",  "\x14",  "\x15",  "\x16",  "\x17",
                                     "\x18",  "\x19",  "\x1a",  "\x1b",  "\x1c",  "\x1d",  "\x1e",  "\x1f",
                                     "\xc2\x85", "\xc2\xa0", "\xe2\x80\xa8", "\xe2\x80\xa9");
    private static $escaped  = array('\\"', '\\\\', '\\"',
                                     "\\0",   "\\x01", "\\x02", "\\x03", "\\x04", "\\x05", "\\x06", "\\a",
                                     "\\b",   "\\t",   "\\n",   "\\v",   "\\f",   "\\r",   "\\x0e", "\\x0f",
                                     "\\x10", "\\x11", "\\x12", "\\x13", "\\x14", "\\x15", "\\x16", "\\x17",
                                     "\\x18", "\\x19", "\\x1a", "\\e",   "\\x1c", "\\x1d", "\\x1e", "\\x1f",
                                     "\\N", "\\_", "\\L", "\\P");

    /**
     * Determines if a PHP value would require double quoting in YAML.
     *
     * @param string $value A PHP value
     *
     * @return Boolean True if the value would require double quotes.
     */
    public static function requiresDoubleQuoting($value)
    {
        return preg_match('/'.self::REGEX_CHARACTER_TO_ESCAPE.'/u', $value);
    }

    /**
     * Escapes and surrounds a PHP value with double quotes.
     *
     * @param string $value A PHP value
     *
     * @return string The quoted, escaped string
     */
    public static function escapeWithDoubleQuotes($value)
    {
        return sprintf('"%s"', str_replace(self::$escapees, self::$escaped, $value));
    }

    /**
     * Determines if a PHP value would require single quoting in YAML.
     *
     * @param string $value A PHP value
     *
     * @return Boolean True if the value would require single quotes.
     */
    public static function requiresSingleQuoting($value)
    {
        return preg_match('/[ \s \' " \: \{ \} \[ \] , & \* \# \?] | \A[ \- ? | < > = ! % @ ` ]/x', $value);
    }

    /**
     * Escapes and surrounds a PHP value with single quotes.
     *
     * @param string $value A PHP value
     *
     * @return string The quoted, escaped string
     */
    public static function escapeWithSingleQuotes($value)
    {
        return sprintf("'%s'", str_replace('\'', '\'\'', $value));
    }
}
PK��Zq+�3�?�?!Symfony/Component/Yaml/Inline.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Yaml;

use Symfony\Component\Yaml\Exception\ParseException;
use Symfony\Component\Yaml\Exception\DumpException;

/**
 * Inline implements a YAML parser/dumper for the YAML inline syntax.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Inline
{
    const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\']*(?:\'\'[^\']*)*)\')';

    private static $exceptionOnInvalidType = false;
    private static $objectSupport = false;

    /**
     * Converts a YAML string to a PHP array.
     *
     * @param string  $value                  A YAML string
     * @param Boolean $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise
     * @param Boolean $objectSupport          true if object support is enabled, false otherwise
     *
     * @return array A PHP array representing the YAML string
     *
     * @throws ParseException
     */
    public static function parse($value, $exceptionOnInvalidType = false, $objectSupport = false)
    {
        self::$exceptionOnInvalidType = $exceptionOnInvalidType;
        self::$objectSupport = $objectSupport;

        $value = trim($value);

        if (0 == strlen($value)) {
            return '';
        }

        if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) {
            $mbEncoding = mb_internal_encoding();
            mb_internal_encoding('ASCII');
        }

        $i = 0;
        switch ($value[0]) {
            case '[':
                $result = self::parseSequence($value, $i);
                ++$i;
                break;
            case '{':
                $result = self::parseMapping($value, $i);
                ++$i;
                break;
            default:
                $result = self::parseScalar($value, null, array('"', "'"), $i);
        }

        // some comments are allowed at the end
        if (preg_replace('/\s+#.*$/A', '', substr($value, $i))) {
            throw new ParseException(sprintf('Unexpected characters near "%s".', substr($value, $i)));
        }

        if (isset($mbEncoding)) {
            mb_internal_encoding($mbEncoding);
        }

        return $result;
    }

    /**
     * Dumps a given PHP variable to a YAML string.
     *
     * @param mixed   $value                  The PHP variable to convert
     * @param Boolean $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise
     * @param Boolean $objectSupport          true if object support is enabled, false otherwise
     *
     * @return string The YAML string representing the PHP array
     *
     * @throws DumpException When trying to dump PHP resource
     */
    public static function dump($value, $exceptionOnInvalidType = false, $objectSupport = false)
    {
        switch (true) {
            case is_resource($value):
                if ($exceptionOnInvalidType) {
                    throw new DumpException(sprintf('Unable to dump PHP resources in a YAML file ("%s").', get_resource_type($value)));
                }

                return 'null';
            case is_object($value):
                if ($objectSupport) {
                    return '!!php/object:'.serialize($value);
                }

                if ($exceptionOnInvalidType) {
                    throw new DumpException('Object support when dumping a YAML file has been disabled.');
                }

                return 'null';
            case is_array($value):
                return self::dumpArray($value, $exceptionOnInvalidType, $objectSupport);
            case null === $value:
                return 'null';
            case true === $value:
                return 'true';
            case false === $value:
                return 'false';
            case ctype_digit($value):
                return is_string($value) ? "'$value'" : (int) $value;
            case is_numeric($value):
                $locale = setlocale(LC_NUMERIC, 0);
                if (false !== $locale) {
                    setlocale(LC_NUMERIC, 'C');
                }
                $repr = is_string($value) ? "'$value'" : (is_infinite($value) ? str_ireplace('INF', '.Inf', strval($value)) : strval($value));

                if (false !== $locale) {
                    setlocale(LC_NUMERIC, $locale);
                }

                return $repr;
            case Escaper::requiresDoubleQuoting($value):
                return Escaper::escapeWithDoubleQuotes($value);
            case Escaper::requiresSingleQuoting($value):
                return Escaper::escapeWithSingleQuotes($value);
            case '' == $value:
                return "''";
            case preg_match(self::getTimestampRegex(), $value):
            case in_array(strtolower($value), array('null', '~', 'true', 'false')):
                return "'$value'";
            default:
                return $value;
        }
    }

    /**
     * Dumps a PHP array to a YAML string.
     *
     * @param array   $value                  The PHP array to dump
     * @param Boolean $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise
     * @param Boolean $objectSupport          true if object support is enabled, false otherwise
     *
     * @return string The YAML string representing the PHP array
     */
    private static function dumpArray($value, $exceptionOnInvalidType, $objectSupport)
    {
        // array
        $keys = array_keys($value);
        if ((1 == count($keys) && '0' == $keys[0])
            || (count($keys) > 1 && array_reduce($keys, function ($v, $w) { return (integer) $v + $w; }, 0) == count($keys) * (count($keys) - 1) / 2)
        ) {
            $output = array();
            foreach ($value as $val) {
                $output[] = self::dump($val, $exceptionOnInvalidType, $objectSupport);
            }

            return sprintf('[%s]', implode(', ', $output));
        }

        // mapping
        $output = array();
        foreach ($value as $key => $val) {
            $output[] = sprintf('%s: %s', self::dump($key, $exceptionOnInvalidType, $objectSupport), self::dump($val, $exceptionOnInvalidType, $objectSupport));
        }

        return sprintf('{ %s }', implode(', ', $output));
    }

    /**
     * Parses a scalar to a YAML string.
     *
     * @param scalar $scalar
     * @param string $delimiters
     * @param array  $stringDelimiters
     * @param integer &$i
     * @param Boolean $evaluate
     *
     * @return string A YAML string
     *
     * @throws ParseException When malformed inline YAML string is parsed
     */
    public static function parseScalar($scalar, $delimiters = null, $stringDelimiters = array('"', "'"), &$i = 0, $evaluate = true)
    {
        if (in_array($scalar[$i], $stringDelimiters)) {
            // quoted scalar
            $output = self::parseQuotedScalar($scalar, $i);

            if (null !== $delimiters) {
                $tmp = ltrim(substr($scalar, $i), ' ');
                if (!in_array($tmp[0], $delimiters)) {
                    throw new ParseException(sprintf('Unexpected characters (%s).', substr($scalar, $i)));
                }
            }
        } else {
            // "normal" string
            if (!$delimiters) {
                $output = substr($scalar, $i);
                $i += strlen($output);

                // remove comments
                if (false !== $strpos = strpos($output, ' #')) {
                    $output = rtrim(substr($output, 0, $strpos));
                }
            } elseif (preg_match('/^(.+?)('.implode('|', $delimiters).')/', substr($scalar, $i), $match)) {
                $output = $match[1];
                $i += strlen($output);
            } else {
                throw new ParseException(sprintf('Malformed inline YAML string (%s).', $scalar));
            }

            if ($evaluate) {
                $output = self::evaluateScalar($output);
            }
        }

        return $output;
    }

    /**
     * Parses a quoted scalar to YAML.
     *
     * @param string $scalar
     * @param integer &$i
     *
     * @return string A YAML string
     *
     * @throws ParseException When malformed inline YAML string is parsed
     */
    private static function parseQuotedScalar($scalar, &$i)
    {
        if (!preg_match('/'.self::REGEX_QUOTED_STRING.'/Au', substr($scalar, $i), $match)) {
            throw new ParseException(sprintf('Malformed inline YAML string (%s).', substr($scalar, $i)));
        }

        $output = substr($match[0], 1, strlen($match[0]) - 2);

        $unescaper = new Unescaper();
        if ('"' == $scalar[$i]) {
            $output = $unescaper->unescapeDoubleQuotedString($output);
        } else {
            $output = $unescaper->unescapeSingleQuotedString($output);
        }

        $i += strlen($match[0]);

        return $output;
    }

    /**
     * Parses a sequence to a YAML string.
     *
     * @param string $sequence
     * @param integer &$i
     *
     * @return string A YAML string
     *
     * @throws ParseException When malformed inline YAML string is parsed
     */
    private static function parseSequence($sequence, &$i = 0)
    {
        $output = array();
        $len = strlen($sequence);
        $i += 1;

        // [foo, bar, ...]
        while ($i < $len) {
            switch ($sequence[$i]) {
                case '[':
                    // nested sequence
                    $output[] = self::parseSequence($sequence, $i);
                    break;
                case '{':
                    // nested mapping
                    $output[] = self::parseMapping($sequence, $i);
                    break;
                case ']':
                    return $output;
                case ',':
                case ' ':
                    break;
                default:
                    $isQuoted = in_array($sequence[$i], array('"', "'"));
                    $value = self::parseScalar($sequence, array(',', ']'), array('"', "'"), $i);

                    if (!$isQuoted && false !== strpos($value, ': ')) {
                        // embedded mapping?
                        try {
                            $value = self::parseMapping('{'.$value.'}');
                        } catch (\InvalidArgumentException $e) {
                            // no, it's not
                        }
                    }

                    $output[] = $value;

                    --$i;
            }

            ++$i;
        }

        throw new ParseException(sprintf('Malformed inline YAML string %s', $sequence));
    }

    /**
     * Parses a mapping to a YAML string.
     *
     * @param string $mapping
     * @param integer &$i
     *
     * @return string A YAML string
     *
     * @throws ParseException When malformed inline YAML string is parsed
     */
    private static function parseMapping($mapping, &$i = 0)
    {
        $output = array();
        $len = strlen($mapping);
        $i += 1;

        // {foo: bar, bar:foo, ...}
        while ($i < $len) {
            switch ($mapping[$i]) {
                case ' ':
                case ',':
                    ++$i;
                    continue 2;
                case '}':
                    return $output;
            }

            // key
            $key = self::parseScalar($mapping, array(':', ' '), array('"', "'"), $i, false);

            // value
            $done = false;
            while ($i < $len) {
                switch ($mapping[$i]) {
                    case '[':
                        // nested sequence
                        $output[$key] = self::parseSequence($mapping, $i);
                        $done = true;
                        break;
                    case '{':
                        // nested mapping
                        $output[$key] = self::parseMapping($mapping, $i);
                        $done = true;
                        break;
                    case ':':
                    case ' ':
                        break;
                    default:
                        $output[$key] = self::parseScalar($mapping, array(',', '}'), array('"', "'"), $i);
                        $done = true;
                        --$i;
                }

                ++$i;

                if ($done) {
                    continue 2;
                }
            }
        }

        throw new ParseException(sprintf('Malformed inline YAML string %s', $mapping));
    }

    /**
     * Evaluates scalars and replaces magic values.
     *
     * @param string $scalar
     *
     * @return string A YAML string
     */
    private static function evaluateScalar($scalar)
    {
        $scalar = trim($scalar);
        $scalarLower = strtolower($scalar);
        switch (true) {
            case 'null' === $scalarLower:
            case '' === $scalar:
            case '~' === $scalar:
                return null;
            case 'true' === $scalarLower:
                return true;
            case 'false' === $scalarLower:
                return false;
            // Optimise for returning strings.
            case $scalar[0] === '+' || $scalar[0] === '-' || $scalar[0] === '.' || $scalar[0] === '!' || is_numeric($scalar[0]):
                switch (true) {
                    case 0 === strpos($scalar, '!str'):
                        return (string) substr($scalar, 5);
                    case 0 === strpos($scalar, '! '):
                        return intval(self::parseScalar(substr($scalar, 2)));
                    case 0 === strpos($scalar, '!!php/object:'):
                        if (self::$objectSupport) {
                            return unserialize(substr($scalar, 13));
                        }

                        if (self::$exceptionOnInvalidType) {
                            throw new ParseException('Object support when parsing a YAML file has been disabled.');
                        }

                        return null;
                    case ctype_digit($scalar):
                        $raw = $scalar;
                        $cast = intval($scalar);

                        return '0' == $scalar[0] ? octdec($scalar) : (((string) $raw == (string) $cast) ? $cast : $raw);
                    case '-' === $scalar[0] && ctype_digit(substr($scalar, 1)):
                        $raw = $scalar;
                        $cast = intval($scalar);

                        return '0' == $scalar[1] ? octdec($scalar) : (((string) $raw == (string) $cast) ? $cast : $raw);
                    case is_numeric($scalar):
                        return '0x' == $scalar[0].$scalar[1] ? hexdec($scalar) : floatval($scalar);
                    case '.inf' === $scalarLower:
                    case '.nan' === $scalarLower:
                        return -log(0);
                    case '-.inf' === $scalarLower:
                        return log(0);
                    case preg_match('/^(-|\+)?[0-9,]+(\.[0-9]+)?$/', $scalar):
                        return floatval(str_replace(',', '', $scalar));
                    case preg_match(self::getTimestampRegex(), $scalar):
                        return strtotime($scalar);
                }
            default:
                return (string) $scalar;
        }
    }

    /**
     * Gets a regex that matches a YAML date.
     *
     * @return string The regular expression
     *
     * @see http://www.yaml.org/spec/1.2/spec.html#id2761573
     */
    private static function getTimestampRegex()
    {
        return <<<EOF
        ~^
        (?P<year>[0-9][0-9][0-9][0-9])
        -(?P<month>[0-9][0-9]?)
        -(?P<day>[0-9][0-9]?)
        (?:(?:[Tt]|[ \t]+)
        (?P<hour>[0-9][0-9]?)
        :(?P<minute>[0-9][0-9])
        :(?P<second>[0-9][0-9])
        (?:\.(?P<fraction>[0-9]*))?
        (?:[ \t]*(?P<tz>Z|(?P<tz_sign>[-+])(?P<tz_hour>[0-9][0-9]?)
        (?::(?P<tz_minute>[0-9][0-9]))?))?)?
        $~x
EOF;
    }
}
PK��Z�ݣ�"�"6Symfony/Component/HttpFoundation/ResponseHeaderBag.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation;

/**
 * ResponseHeaderBag is a container for Response HTTP headers.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class ResponseHeaderBag extends HeaderBag
{
    const COOKIES_FLAT           = 'flat';
    const COOKIES_ARRAY          = 'array';

    const DISPOSITION_ATTACHMENT = 'attachment';
    const DISPOSITION_INLINE     = 'inline';

    /**
     * @var array
     */
    protected $computedCacheControl = array();

    /**
     * @var array
     */
    protected $cookies              = array();

    /**
     * @var array
     */
    protected $headerNames          = array();

    /**
     * Constructor.
     *
     * @param array $headers An array of HTTP headers
     *
     * @api
     */
    public function __construct(array $headers = array())
    {
        parent::__construct($headers);

        if (!isset($this->headers['cache-control'])) {
            $this->set('Cache-Control', '');
        }
    }

    /**
     * {@inheritdoc}
     */
    public function __toString()
    {
        $cookies = '';
        foreach ($this->getCookies() as $cookie) {
            $cookies .= 'Set-Cookie: '.$cookie."\r\n";
        }

        ksort($this->headerNames);

        return parent::__toString().$cookies;
    }

    /**
     * Returns the headers, with original capitalizations.
     *
     * @return array An array of headers
     */
    public function allPreserveCase()
    {
        return array_combine($this->headerNames, $this->headers);
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function replace(array $headers = array())
    {
        $this->headerNames = array();

        parent::replace($headers);

        if (!isset($this->headers['cache-control'])) {
            $this->set('Cache-Control', '');
        }
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function set($key, $values, $replace = true)
    {
        parent::set($key, $values, $replace);

        $uniqueKey = strtr(strtolower($key), '_', '-');
        $this->headerNames[$uniqueKey] = $key;

        // ensure the cache-control header has sensible defaults
        if (in_array($uniqueKey, array('cache-control', 'etag', 'last-modified', 'expires'))) {
            $computed = $this->computeCacheControlValue();
            $this->headers['cache-control'] = array($computed);
            $this->headerNames['cache-control'] = 'Cache-Control';
            $this->computedCacheControl = $this->parseCacheControl($computed);
        }
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function remove($key)
    {
        parent::remove($key);

        $uniqueKey = strtr(strtolower($key), '_', '-');
        unset($this->headerNames[$uniqueKey]);

        if ('cache-control' === $uniqueKey) {
            $this->computedCacheControl = array();
        }
    }

    /**
     * {@inheritdoc}
     */
    public function hasCacheControlDirective($key)
    {
        return array_key_exists($key, $this->computedCacheControl);
    }

    /**
     * {@inheritdoc}
     */
    public function getCacheControlDirective($key)
    {
        return array_key_exists($key, $this->computedCacheControl) ? $this->computedCacheControl[$key] : null;
    }

    /**
     * Sets a cookie.
     *
     * @param Cookie $cookie
     *
     * @api
     */
    public function setCookie(Cookie $cookie)
    {
        $this->cookies[$cookie->getDomain()][$cookie->getPath()][$cookie->getName()] = $cookie;
    }

    /**
     * Removes a cookie from the array, but does not unset it in the browser
     *
     * @param string $name
     * @param string $path
     * @param string $domain
     *
     * @api
     */
    public function removeCookie($name, $path = '/', $domain = null)
    {
        if (null === $path) {
            $path = '/';
        }

        unset($this->cookies[$domain][$path][$name]);

        if (empty($this->cookies[$domain][$path])) {
            unset($this->cookies[$domain][$path]);

            if (empty($this->cookies[$domain])) {
                unset($this->cookies[$domain]);
            }
        }
    }

    /**
     * Returns an array with all cookies
     *
     * @param string $format
     *
     * @throws \InvalidArgumentException When the $format is invalid
     *
     * @return array
     *
     * @api
     */
    public function getCookies($format = self::COOKIES_FLAT)
    {
        if (!in_array($format, array(self::COOKIES_FLAT, self::COOKIES_ARRAY))) {
            throw new \InvalidArgumentException(sprintf('Format "%s" invalid (%s).', $format, implode(', ', array(self::COOKIES_FLAT, self::COOKIES_ARRAY))));
        }

        if (self::COOKIES_ARRAY === $format) {
            return $this->cookies;
        }

        $flattenedCookies = array();
        foreach ($this->cookies as $path) {
            foreach ($path as $cookies) {
                foreach ($cookies as $cookie) {
                    $flattenedCookies[] = $cookie;
                }
            }
        }

        return $flattenedCookies;
    }

    /**
     * Clears a cookie in the browser
     *
     * @param string $name
     * @param string $path
     * @param string $domain
     *
     * @api
     */
    public function clearCookie($name, $path = '/', $domain = null)
    {
        $this->setCookie(new Cookie($name, null, 1, $path, $domain));
    }

    /**
     * Generates a HTTP Content-Disposition field-value.
     *
     * @param string $disposition      One of "inline" or "attachment"
     * @param string $filename         A unicode string
     * @param string $filenameFallback A string containing only ASCII characters that
     *                                 is semantically equivalent to $filename. If the filename is already ASCII,
     *                                 it can be omitted, or just copied from $filename
     *
     * @return string A string suitable for use as a Content-Disposition field-value.
     *
     * @throws \InvalidArgumentException
     * @see RFC 6266
     */
    public function makeDisposition($disposition, $filename, $filenameFallback = '')
    {
        if (!in_array($disposition, array(self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE))) {
            throw new \InvalidArgumentException(sprintf('The disposition must be either "%s" or "%s".', self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE));
        }

        if ('' == $filenameFallback) {
            $filenameFallback = $filename;
        }

        // filenameFallback is not ASCII.
        if (!preg_match('/^[\x20-\x7e]*$/', $filenameFallback)) {
            throw new \InvalidArgumentException('The filename fallback must only contain ASCII characters.');
        }

        // percent characters aren't safe in fallback.
        if (false !== strpos($filenameFallback, '%')) {
            throw new \InvalidArgumentException('The filename fallback cannot contain the "%" character.');
        }

        // path separators aren't allowed in either.
        if (false !== strpos($filename, '/') || false !== strpos($filename, '\\') || false !== strpos($filenameFallback, '/') || false !== strpos($filenameFallback, '\\')) {
            throw new \InvalidArgumentException('The filename and the fallback cannot contain the "/" and "\\" characters.');
        }

        $output = sprintf('%s; filename="%s"', $disposition, str_replace('"', '\\"', $filenameFallback));

        if ($filename !== $filenameFallback) {
            $output .= sprintf("; filename*=utf-8''%s", rawurlencode($filename));
        }

        return $output;
    }

    /**
     * Returns the calculated value of the cache-control header.
     *
     * This considers several other headers and calculates or modifies the
     * cache-control header to a sensible, conservative value.
     *
     * @return string
     */
    protected function computeCacheControlValue()
    {
        if (!$this->cacheControl && !$this->has('ETag') && !$this->has('Last-Modified') && !$this->has('Expires')) {
            return 'no-cache';
        }

        if (!$this->cacheControl) {
            // conservative by default
            return 'private, must-revalidate';
        }

        $header = $this->getCacheControlHeader();
        if (isset($this->cacheControl['public']) || isset($this->cacheControl['private'])) {
            return $header;
        }

        // public if s-maxage is defined, private otherwise
        if (!isset($this->cacheControl['s-maxage'])) {
            return $header.', private';
        }

        return $header;
    }
}
PK��Z�}��xx.Symfony/Component/HttpFoundation/ServerBag.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation;

/**
 * ServerBag is a container for HTTP headers from the $_SERVER variable.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
 * @author Robert Kiss <kepten@gmail.com>
 */
class ServerBag extends ParameterBag
{
    /**
     * Gets the HTTP headers.
     *
     * @return array
     */
    public function getHeaders()
    {
        $headers = array();
        $contentHeaders = array('CONTENT_LENGTH' => true, 'CONTENT_MD5' => true, 'CONTENT_TYPE' => true);
        foreach ($this->parameters as $key => $value) {
            if (0 === strpos($key, 'HTTP_')) {
                $headers[substr($key, 5)] = $value;
            }
            // CONTENT_* are not prefixed with HTTP_
            elseif (isset($contentHeaders[$key])) {
                $headers[$key] = $value;
            }
        }

        if (isset($this->parameters['PHP_AUTH_USER'])) {
            $headers['PHP_AUTH_USER'] = $this->parameters['PHP_AUTH_USER'];
            $headers['PHP_AUTH_PW'] = isset($this->parameters['PHP_AUTH_PW']) ? $this->parameters['PHP_AUTH_PW'] : '';
        } else {
            /*
             * php-cgi under Apache does not pass HTTP Basic user/pass to PHP by default
             * For this workaround to work, add these lines to your .htaccess file:
             * RewriteCond %{HTTP:Authorization} ^(.+)$
             * RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
             *
             * A sample .htaccess file:
             * RewriteEngine On
             * RewriteCond %{HTTP:Authorization} ^(.+)$
             * RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
             * RewriteCond %{REQUEST_FILENAME} !-f
             * RewriteRule ^(.*)$ app.php [QSA,L]
             */

            $authorizationHeader = null;
            if (isset($this->parameters['HTTP_AUTHORIZATION'])) {
                $authorizationHeader = $this->parameters['HTTP_AUTHORIZATION'];
            } elseif (isset($this->parameters['REDIRECT_HTTP_AUTHORIZATION'])) {
                $authorizationHeader = $this->parameters['REDIRECT_HTTP_AUTHORIZATION'];
            }

            if (null !== $authorizationHeader) {
                if (0 === stripos($authorizationHeader, 'basic')) {
                    // Decode AUTHORIZATION header into PHP_AUTH_USER and PHP_AUTH_PW when authorization header is basic
                    $exploded = explode(':', base64_decode(substr($authorizationHeader, 6)));
                    if (count($exploded) == 2) {
                        list($headers['PHP_AUTH_USER'], $headers['PHP_AUTH_PW']) = $exploded;
                    }
                } elseif (empty($this->parameters['PHP_AUTH_DIGEST']) && (0 === stripos($authorizationHeader, 'digest'))) {
                    // In some circumstances PHP_AUTH_DIGEST needs to be set
                    $headers['PHP_AUTH_DIGEST'] = $authorizationHeader;
                    $this->parameters['PHP_AUTH_DIGEST'] = $authorizationHeader;
                }
            }
        }

        // PHP_AUTH_USER/PHP_AUTH_PW
        if (isset($headers['PHP_AUTH_USER'])) {
            $headers['AUTHORIZATION'] = 'Basic '.base64_encode($headers['PHP_AUTH_USER'].':'.$headers['PHP_AUTH_PW']);
        } elseif (isset($headers['PHP_AUTH_DIGEST'])) {
            $headers['AUTHORIZATION'] = $headers['PHP_AUTH_DIGEST'];
        }

        return $headers;
    }
}
PK��Z�_DK�
�
5Symfony/Component/HttpFoundation/RedirectResponse.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation;

/**
 * RedirectResponse represents an HTTP response doing a redirect.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class RedirectResponse extends Response
{
    protected $targetUrl;

    /**
     * Creates a redirect response so that it conforms to the rules defined for a redirect status code.
     *
     * @param string  $url     The URL to redirect to
     * @param integer $status  The status code (302 by default)
     * @param array   $headers The headers (Location is always set to the given URL)
     *
     * @throws \InvalidArgumentException
     *
     * @see http://tools.ietf.org/html/rfc2616#section-10.3
     *
     * @api
     */
    public function __construct($url, $status = 302, $headers = array())
    {
        if (empty($url)) {
            throw new \InvalidArgumentException('Cannot redirect to an empty URL.');
        }

        parent::__construct('', $status, $headers);

        $this->setTargetUrl($url);

        if (!$this->isRedirect()) {
            throw new \InvalidArgumentException(sprintf('The HTTP status code is not a redirect ("%s" given).', $status));
        }
    }

    /**
     * {@inheritDoc}
     */
    public static function create($url = '', $status = 302, $headers = array())
    {
        return new static($url, $status, $headers);
    }

    /**
     * Returns the target URL.
     *
     * @return string target URL
     */
    public function getTargetUrl()
    {
        return $this->targetUrl;
    }

    /**
     * Sets the redirect target of this response.
     *
     * @param string  $url     The URL to redirect to
     *
     * @return RedirectResponse The current response.
     *
     * @throws \InvalidArgumentException
     */
    public function setTargetUrl($url)
    {
        if (empty($url)) {
            throw new \InvalidArgumentException('Cannot redirect to an empty URL.');
        }

        $this->targetUrl = $url;

        $this->setContent(
            sprintf('<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <meta http-equiv="refresh" content="1;url=%1$s" />

        <title>Redirecting to %1$s</title>
    </head>
    <body>
        Redirecting to <a href="%1$s">%1$s</a>.
    </body>
</html>', htmlspecialchars($url, ENT_QUOTES, 'UTF-8')));

        $this->headers->set('Location', $url);

        return $this;
    }
}
PK��Z�s
��5Symfony/Component/HttpFoundation/StreamedResponse.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation;

/**
 * StreamedResponse represents a streamed HTTP response.
 *
 * A StreamedResponse uses a callback for its content.
 *
 * The callback should use the standard PHP functions like echo
 * to stream the response back to the client. The flush() method
 * can also be used if needed.
 *
 * @see flush()
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class StreamedResponse extends Response
{
    protected $callback;
    protected $streamed;

    /**
     * Constructor.
     *
     * @param callable|null $callback A valid PHP callback or null to set it later
     * @param integer       $status   The response status code
     * @param array         $headers  An array of response headers
     *
     * @api
     */
    public function __construct($callback = null, $status = 200, $headers = array())
    {
        parent::__construct(null, $status, $headers);

        if (null !== $callback) {
            $this->setCallback($callback);
        }
        $this->streamed = false;
    }

    /**
     * Factory method for chainability
     *
     * @param callable|null $callback A valid PHP callback or null to set it later
     * @param integer       $status   The response status code
     * @param array         $headers  An array of response headers
     *
     * @return StreamedResponse
     */
    public static function create($callback = null, $status = 200, $headers = array())
    {
        return new static($callback, $status, $headers);
    }

    /**
     * Sets the PHP callback associated with this Response.
     *
     * @param callable $callback A valid PHP callback
     *
     * @throws \LogicException
     */
    public function setCallback($callback)
    {
        if (!is_callable($callback)) {
            throw new \LogicException('The Response callback must be a valid PHP callable.');
        }
        $this->callback = $callback;
    }

    /**
     * {@inheritdoc}
     */
    public function prepare(Request $request)
    {
        $this->headers->set('Cache-Control', 'no-cache');

        return parent::prepare($request);
    }

    /**
     * {@inheritdoc}
     *
     * This method only sends the content once.
     */
    public function sendContent()
    {
        if ($this->streamed) {
            return;
        }

        $this->streamed = true;

        if (null === $this->callback) {
            throw new \LogicException('The Response callback must not be null.');
        }

        call_user_func($this->callback);
    }

    /**
     * {@inheritdoc}
     *
     * @throws \LogicException when the content is not null
     */
    public function setContent($content)
    {
        if (null !== $content) {
            throw new \LogicException('The content cannot be set on a StreamedResponse instance.');
        }
    }

    /**
     * {@inheritdoc}
     *
     * @return false
     */
    public function getContent()
    {
        return false;
    }
}
PK��Z��F��+Symfony/Component/HttpFoundation/Cookie.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation;

/**
 * Represents a cookie
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @api
 */
class Cookie
{
    protected $name;
    protected $value;
    protected $domain;
    protected $expire;
    protected $path;
    protected $secure;
    protected $httpOnly;

    /**
     * Constructor.
     *
     * @param string                   $name     The name of the cookie
     * @param string                   $value    The value of the cookie
     * @param integer|string|\DateTime $expire   The time the cookie expires
     * @param string                   $path     The path on the server in which the cookie will be available on
     * @param string                   $domain   The domain that the cookie is available to
     * @param Boolean                  $secure   Whether the cookie should only be transmitted over a secure HTTPS connection from the client
     * @param Boolean                  $httpOnly Whether the cookie will be made accessible only through the HTTP protocol
     *
     * @throws \InvalidArgumentException
     *
     * @api
     */
    public function __construct($name, $value = null, $expire = 0, $path = '/', $domain = null, $secure = false, $httpOnly = true)
    {
        // from PHP source code
        if (preg_match("/[=,; \t\r\n\013\014]/", $name)) {
            throw new \InvalidArgumentException(sprintf('The cookie name "%s" contains invalid characters.', $name));
        }

        if (empty($name)) {
            throw new \InvalidArgumentException('The cookie name cannot be empty.');
        }

        // convert expiration time to a Unix timestamp
        if ($expire instanceof \DateTime) {
            $expire = $expire->format('U');
        } elseif (!is_numeric($expire)) {
            $expire = strtotime($expire);

            if (false === $expire || -1 === $expire) {
                throw new \InvalidArgumentException('The cookie expiration time is not valid.');
            }
        }

        $this->name = $name;
        $this->value = $value;
        $this->domain = $domain;
        $this->expire = $expire;
        $this->path = empty($path) ? '/' : $path;
        $this->secure = (Boolean) $secure;
        $this->httpOnly = (Boolean) $httpOnly;
    }

    /**
     * Returns the cookie as a string.
     *
     * @return string The cookie
     */
    public function __toString()
    {
        $str = urlencode($this->getName()).'=';

        if ('' === (string) $this->getValue()) {
            $str .= 'deleted; expires='.gmdate("D, d-M-Y H:i:s T", time() - 31536001);
        } else {
            $str .= urlencode($this->getValue());

            if ($this->getExpiresTime() !== 0) {
                $str .= '; expires='.gmdate("D, d-M-Y H:i:s T", $this->getExpiresTime());
            }
        }

        if ($this->path) {
            $str .= '; path='.$this->path;
        }

        if ($this->getDomain()) {
            $str .= '; domain='.$this->getDomain();
        }

        if (true === $this->isSecure()) {
            $str .= '; secure';
        }

        if (true === $this->isHttpOnly()) {
            $str .= '; httponly';
        }

        return $str;
    }

    /**
     * Gets the name of the cookie.
     *
     * @return string
     *
     * @api
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Gets the value of the cookie.
     *
     * @return string
     *
     * @api
     */
    public function getValue()
    {
        return $this->value;
    }

    /**
     * Gets the domain that the cookie is available to.
     *
     * @return string
     *
     * @api
     */
    public function getDomain()
    {
        return $this->domain;
    }

    /**
     * Gets the time the cookie expires.
     *
     * @return integer
     *
     * @api
     */
    public function getExpiresTime()
    {
        return $this->expire;
    }

    /**
     * Gets the path on the server in which the cookie will be available on.
     *
     * @return string
     *
     * @api
     */
    public function getPath()
    {
        return $this->path;
    }

    /**
     * Checks whether the cookie should only be transmitted over a secure HTTPS connection from the client.
     *
     * @return Boolean
     *
     * @api
     */
    public function isSecure()
    {
        return $this->secure;
    }

    /**
     * Checks whether the cookie will be made accessible only through the HTTP protocol.
     *
     * @return Boolean
     *
     * @api
     */
    public function isHttpOnly()
    {
        return $this->httpOnly;
    }

    /**
     * Whether this cookie is about to be cleared
     *
     * @return Boolean
     *
     * @api
     */
    public function isCleared()
    {
        return $this->expire < time();
    }
}
PK��Z�6=��
�
,Symfony/Component/HttpFoundation/IpUtils.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation;

/**
 * Http utility functions.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class IpUtils
{
    /**
     * This class should not be instantiated
     */
    private function __construct() {}

    /**
     * Checks if an IPv4 or IPv6 address is contained in the list of given IPs or subnets
     *
     * @param string       $requestIp   IP to check
     * @param string|array $ips         List of IPs or subnets (can be a string if only a single one)
     *
     * @return boolean Whether the IP is valid
     */
    public static function checkIp($requestIp, $ips)
    {
        if (!is_array($ips)) {
            $ips = array($ips);
        }

        $method = false !== strpos($requestIp, ':') ? 'checkIp6': 'checkIp4';

        foreach ($ips as $ip) {
            if (self::$method($requestIp, $ip)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Compares two IPv4 addresses.
     * In case a subnet is given, it checks if it contains the request IP.
     *
     * @param string $requestIp IPv4 address to check
     * @param string $ip        IPv4 address or subnet in CIDR notation
     *
     * @return boolean Whether the IP is valid
     */
    public static function checkIp4($requestIp, $ip)
    {
        if (false !== strpos($ip, '/')) {
            list($address, $netmask) = explode('/', $ip, 2);

            if ($netmask < 1 || $netmask > 32) {
                return false;
            }
        } else {
            $address = $ip;
            $netmask = 32;
        }

        return 0 === substr_compare(sprintf('%032b', ip2long($requestIp)), sprintf('%032b', ip2long($address)), 0, $netmask);
    }

    /**
     * Compares two IPv6 addresses.
     * In case a subnet is given, it checks if it contains the request IP.
     *
     * @author David Soria Parra <dsp at php dot net>
     * @see https://github.com/dsp/v6tools
     *
     * @param string $requestIp IPv6 address to check
     * @param string $ip        IPv6 address or subnet in CIDR notation
     *
     * @return boolean Whether the IP is valid
     *
     * @throws \RuntimeException When IPV6 support is not enabled
     */
    public static function checkIp6($requestIp, $ip)
    {
        if (!((extension_loaded('sockets') && defined('AF_INET6')) || @inet_pton('::1'))) {
            throw new \RuntimeException('Unable to check Ipv6. Check that PHP was not compiled with option "disable-ipv6".');
        }

        if (false !== strpos($ip, '/')) {
            list($address, $netmask) = explode('/', $ip, 2);

            if ($netmask < 1 || $netmask > 128) {
                return false;
            }
        } else {
            $address = $ip;
            $netmask = 128;
        }

        $bytesAddr = unpack("n*", inet_pton($address));
        $bytesTest = unpack("n*", inet_pton($requestIp));

        for ($i = 1, $ceil = ceil($netmask / 16); $i <= $ceil; $i++) {
            $left = $netmask - 16 * ($i-1);
            $left = ($left <= 16) ? $left : 16;
            $mask = ~(0xffff >> $left) & 0xffff;
            if (($bytesAddr[$i] & $mask) != ($bytesTest[$i] & $mask)) {
                return false;
            }
        }

        return true;
    }
}
PK��ZP�i���,Symfony/Component/HttpFoundation/FileBag.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation;

use Symfony\Component\HttpFoundation\File\UploadedFile;

/**
 * FileBag is a container for uploaded files.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
 *
 * @api
 */
class FileBag extends ParameterBag
{
    private static $fileKeys = array('error', 'name', 'size', 'tmp_name', 'type');

    /**
     * Constructor.
     *
     * @param array $parameters An array of HTTP files
     *
     * @api
     */
    public function __construct(array $parameters = array())
    {
        $this->replace($parameters);
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function replace(array $files = array())
    {
        $this->parameters = array();
        $this->add($files);
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function set($key, $value)
    {
        if (!is_array($value) && !$value instanceof UploadedFile) {
            throw new \InvalidArgumentException('An uploaded file must be an array or an instance of UploadedFile.');
        }

        parent::set($key, $this->convertFileInformation($value));
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function add(array $files = array())
    {
        foreach ($files as $key => $file) {
            $this->set($key, $file);
        }
    }

    /**
     * Converts uploaded files to UploadedFile instances.
     *
     * @param array|UploadedFile $file A (multi-dimensional) array of uploaded file information
     *
     * @return array A (multi-dimensional) array of UploadedFile instances
     */
    protected function convertFileInformation($file)
    {
        if ($file instanceof UploadedFile) {
            return $file;
        }

        $file = $this->fixPhpFilesArray($file);
        if (is_array($file)) {
            $keys = array_keys($file);
            sort($keys);

            if ($keys == self::$fileKeys) {
                if (UPLOAD_ERR_NO_FILE == $file['error']) {
                    $file = null;
                } else {
                    $file = new UploadedFile($file['tmp_name'], $file['name'], $file['type'], $file['size'], $file['error']);
                }
            } else {
                $file = array_map(array($this, 'convertFileInformation'), $file);
            }
        }

        return $file;
    }

    /**
     * Fixes a malformed PHP $_FILES array.
     *
     * PHP has a bug that the format of the $_FILES array differs, depending on
     * whether the uploaded file fields had normal field names or array-like
     * field names ("normal" vs. "parent[child]").
     *
     * This method fixes the array to look like the "normal" $_FILES array.
     *
     * It's safe to pass an already converted array, in which case this method
     * just returns the original array unmodified.
     *
     * @param array $data
     *
     * @return array
     */
    protected function fixPhpFilesArray($data)
    {
        if (!is_array($data)) {
            return $data;
        }

        $keys = array_keys($data);
        sort($keys);

        if (self::$fileKeys != $keys || !isset($data['name']) || !is_array($data['name'])) {
            return $data;
        }

        $files = $data;
        foreach (self::$fileKeys as $k) {
            unset($files[$k]);
        }

        foreach (array_keys($data['name']) as $key) {
            $files[$key] = $this->fixPhpFilesArray(array(
                'error'    => $data['error'][$key],
                'name'     => $data['name'][$key],
                'type'     => $data['type'][$key],
                'tmp_name' => $data['tmp_name'][$key],
                'size'     => $data['size'][$key]
            ));
        }

        return $files;
    }
}
PK��Z1y��<Symfony/Component/HttpFoundation/RequestMatcherInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation;

/**
 * RequestMatcherInterface is an interface for strategies to match a Request.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface RequestMatcherInterface
{
    /**
     * Decides whether the rule(s) implemented by the strategy matches the supplied request.
     *
     * @param Request $request The request to check for a match
     *
     * @return Boolean true if the request matches, false otherwise
     *
     * @api
     */
    public function matches(Request $request);
}
PK��ZPE�
XX/Symfony/Component/HttpFoundation/autoloader.phpnu�[���<?php

spl_autoload_register(function ($class) {
    if ('\\' == $class[0]) {
        $class = substr($class, 1);
    }

    if (
        0 === strpos($class, 'Symfony\\Component\\HttpFoundation\\')
        &&
        file_exists($file = __DIR__.'/../../../'.str_replace('\\', '/', $class).'.php')
    ) {
        require_once $file;
    }
});
PK��Z8{?���3Symfony/Component/HttpFoundation/RequestMatcher.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation;

/**
 * RequestMatcher compares a pre-defined set of checks against a Request instance.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class RequestMatcher implements RequestMatcherInterface
{
    /**
     * @var string
     */
    private $path;

    /**
     * @var string
     */
    private $host;

    /**
     * @var array
     */
    private $methods = array();

    /**
     * @var string
     */
    private $ips = array();

    /**
     * @var array
     */
    private $attributes = array();

    /**
     * @param string|null          $path
     * @param string|null          $host
     * @param string|string[]|null $methods
     * @param string|string[]|null $ips
     * @param array                $attributes
     */
    public function __construct($path = null, $host = null, $methods = null, $ips = null, array $attributes = array())
    {
        $this->matchPath($path);
        $this->matchHost($host);
        $this->matchMethod($methods);
        $this->matchIps($ips);
        foreach ($attributes as $k => $v) {
            $this->matchAttribute($k, $v);
        }
    }

    /**
     * Adds a check for the URL host name.
     *
     * @param string $regexp A Regexp
     */
    public function matchHost($regexp)
    {
        $this->host = $regexp;
    }

    /**
     * Adds a check for the URL path info.
     *
     * @param string $regexp A Regexp
     */
    public function matchPath($regexp)
    {
        $this->path = $regexp;
    }

    /**
     * Adds a check for the client IP.
     *
     * @param string $ip A specific IP address or a range specified using IP/netmask like 192.168.1.0/24
     */
    public function matchIp($ip)
    {
        $this->matchIps($ip);
    }

    /**
     * Adds a check for the client IP.
     *
     * @param string|string[] $ips A specific IP address or a range specified using IP/netmask like 192.168.1.0/24
     */
    public function matchIps($ips)
    {
        $this->ips = (array) $ips;
    }

    /**
     * Adds a check for the HTTP method.
     *
     * @param string|string[]|null $method An HTTP method or an array of HTTP methods
     */
    public function matchMethod($method)
    {
        $this->methods = array_map('strtoupper', (array) $method);
    }

    /**
     * Adds a check for request attribute.
     *
     * @param string $key    The request attribute name
     * @param string $regexp A Regexp
     */
    public function matchAttribute($key, $regexp)
    {
        $this->attributes[$key] = $regexp;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function matches(Request $request)
    {
        if ($this->methods && !in_array($request->getMethod(), $this->methods)) {
            return false;
        }

        foreach ($this->attributes as $key => $pattern) {
            if (!preg_match('{'.$pattern.'}', $request->attributes->get($key))) {
                return false;
            }
        }

        if (null !== $this->path && !preg_match('{'.$this->path.'}', rawurldecode($request->getPathInfo()))) {
            return false;
        }

        if (null !== $this->host && !preg_match('{'.$this->host.'}i', $request->getHost())) {
            return false;
        }

        if (IpUtils::checkIp($request->getClientIp(), $this->ips)) {
            return true;
        }

        // Note to future implementors: add additional checks above the
        // foreach above or else your check might not be run!
        return count($this->ips) === 0;
    }
}
PK��Z�͢|1Symfony/Component/HttpFoundation/JsonResponse.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation;

/**
 * Response represents an HTTP response in JSON format.
 *
 * Note that this class does not force the returned JSON content to be an
 * object. It is however recommended that you do return an object as it
 * protects yourself against XSSI and JSON-JavaScript Hijacking.
 *
 * @see https://www.owasp.org/index.php/OWASP_AJAX_Security_Guidelines#Always_return_JSON_with_an_Object_on_the_outside
 *
 * @author Igor Wiedler <igor@wiedler.ch>
 */
class JsonResponse extends Response
{
    protected $data;
    protected $callback;

    /**
     * Constructor.
     *
     * @param mixed   $data    The response data
     * @param integer $status  The response status code
     * @param array   $headers An array of response headers
     */
    public function __construct($data = null, $status = 200, $headers = array())
    {
        parent::__construct('', $status, $headers);

        if (null === $data) {
            $data = new \ArrayObject();
        }
        $this->setData($data);
    }

    /**
     * {@inheritDoc}
     */
    public static function create($data = null, $status = 200, $headers = array())
    {
        return new static($data, $status, $headers);
    }

    /**
     * Sets the JSONP callback.
     *
     * @param string|null $callback The JSONP callback or null to use none
     *
     * @return JsonResponse
     *
     * @throws \InvalidArgumentException When the callback name is not valid
     */
    public function setCallback($callback = null)
    {
        if (null !== $callback) {
            // taken from http://www.geekality.net/2011/08/03/valid-javascript-identifier/
            $pattern = '/^[$_\p{L}][$_\p{L}\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]*+$/u';
            $parts = explode('.', $callback);
            foreach ($parts as $part) {
                if (!preg_match($pattern, $part)) {
                    throw new \InvalidArgumentException('The callback name is not valid.');
                }
            }
        }

        $this->callback = $callback;

        return $this->update();
    }

    /**
     * Sets the data to be sent as json.
     *
     * @param mixed $data
     *
     * @return JsonResponse
     *
     * @throws \InvalidArgumentException
     */
    public function setData($data = array())
    {
        // Encode <, >, ', &, and " for RFC4627-compliant JSON, which may also be embedded into HTML.
        $this->data = json_encode($data, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT);

        if (JSON_ERROR_NONE !== json_last_error()) {
            throw new \InvalidArgumentException($this->transformJsonError());
        }

        return $this->update();
    }

    /**
     * Updates the content and headers according to the json data and callback.
     *
     * @return JsonResponse
     */
    protected function update()
    {
        if (null !== $this->callback) {
            // Not using application/javascript for compatibility reasons with older browsers.
            $this->headers->set('Content-Type', 'text/javascript');

            return $this->setContent(sprintf('%s(%s);', $this->callback, $this->data));
        }

        // Only set the header when there is none or when it equals 'text/javascript' (from a previous update with callback)
        // in order to not overwrite a custom definition.
        if (!$this->headers->has('Content-Type') || 'text/javascript' === $this->headers->get('Content-Type')) {
            $this->headers->set('Content-Type', 'application/json');
        }

        return $this->setContent($this->data);
    }

    private function transformJsonError()
    {
        if (function_exists('json_last_error_msg')) {
            return json_last_error_msg();
        }

        switch (json_last_error()) {
            case JSON_ERROR_DEPTH:
                return 'Maximum stack depth exceeded.';

            case JSON_ERROR_STATE_MISMATCH:
                return 'Underflow or the modes mismatch.';

            case JSON_ERROR_CTRL_CHAR:
                return 'Unexpected control character found.';

            case JSON_ERROR_SYNTAX:
                return 'Syntax error, malformed JSON.';

            case JSON_ERROR_UTF8:
                return 'Malformed UTF-8 characters, possibly incorrectly encoded.';

            default:
                return 'Unknown error.';
        }
    }
}
PK��ZVk�b335Symfony/Component/HttpFoundation/AcceptHeaderItem.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation;

/**
 * Represents an Accept-* header item.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class AcceptHeaderItem
{
    /**
     * @var string
     */
    private $value;

    /**
     * @var float
     */
    private $quality = 1.0;

    /**
     * @var int
     */
    private $index = 0;

    /**
     * @var array
     */
    private $attributes = array();

    /**
     * Constructor.
     *
     * @param string $value
     * @param array  $attributes
     */
    public function __construct($value, array $attributes = array())
    {
        $this->value = $value;
        foreach ($attributes as $name => $value) {
            $this->setAttribute($name, $value);
        }
    }

    /**
     * Builds an AcceptHeaderInstance instance from a string.
     *
     * @param string $itemValue
     *
     * @return AcceptHeaderItem
     */
    public static function fromString($itemValue)
    {
        $bits = preg_split('/\s*(?:;*("[^"]+");*|;*(\'[^\']+\');*|;+)\s*/', $itemValue, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
        $value = array_shift($bits);
        $attributes = array();

        $lastNullAttribute = null;
        foreach ($bits as $bit) {
            if (($start = substr($bit, 0, 1)) === ($end = substr($bit, -1)) && ($start === '"' || $start === '\'')) {
                $attributes[$lastNullAttribute] = substr($bit, 1, -1);
            } elseif ('=' === $end) {
                $lastNullAttribute = $bit = substr($bit, 0, -1);
                $attributes[$bit] = null;
            } else {
                $parts = explode('=', $bit);
                $attributes[$parts[0]] = isset($parts[1]) && strlen($parts[1]) > 0 ? $parts[1] : '';
            }
        }

        return new self(($start = substr($value, 0, 1)) === ($end = substr($value, -1)) && ($start === '"' || $start === '\'') ? substr($value, 1, -1) : $value, $attributes);
    }

    /**
     * Returns header  value's string representation.
     *
     * @return string
     */
    public function __toString()
    {
        $string = $this->value.($this->quality < 1 ? ';q='.$this->quality : '');
        if (count($this->attributes) > 0) {
            $string .= ';'.implode(';', array_map(function ($name, $value) {
                return sprintf(preg_match('/[,;=]/', $value) ? '%s="%s"' : '%s=%s', $name, $value);
            }, array_keys($this->attributes), $this->attributes));
        }

        return $string;
    }

    /**
     * Set the item value.
     *
     * @param string $value
     *
     * @return AcceptHeaderItem
     */
    public function setValue($value)
    {
        $this->value = $value;

        return $this;
    }

    /**
     * Returns the item value.
     *
     * @return string
     */
    public function getValue()
    {
        return $this->value;
    }

    /**
     * Set the item quality.
     *
     * @param float $quality
     *
     * @return AcceptHeaderItem
     */
    public function setQuality($quality)
    {
        $this->quality = $quality;

        return $this;
    }

    /**
     * Returns the item quality.
     *
     * @return float
     */
    public function getQuality()
    {
        return $this->quality;
    }

    /**
     * Set the item index.
     *
     * @param int $index
     *
     * @return AcceptHeaderItem
     */
    public function setIndex($index)
    {
        $this->index = $index;

        return $this;
    }

    /**
     * Returns the item index.
     *
     * @return int
     */
    public function getIndex()
    {
        return $this->index;
    }

    /**
     * Tests if an attribute exists.
     *
     * @param string $name
     *
     * @return Boolean
     */
    public function hasAttribute($name)
    {
        return isset($this->attributes[$name]);
    }

    /**
     * Returns an attribute by its name.
     *
     * @param string $name
     * @param mixed  $default
     *
     * @return mixed
     */
    public function getAttribute($name, $default = null)
    {
        return isset($this->attributes[$name]) ? $this->attributes[$name] : $default;
    }

    /**
     * Returns all attributes.
     *
     * @return array
     */
    public function getAttributes()
    {
        return $this->attributes;
    }

    /**
     * Set an attribute.
     *
     * @param string $name
     * @param string $value
     *
     * @return AcceptHeaderItem
     */
    public function setAttribute($name, $value)
    {
        if ('q' === $name) {
            $this->quality = (float) $value;
        } else {
            $this->attributes[$name] = (string) $value;
        }

        return $this;
    }
}
PK��Zn��OO=Symfony/Component/HttpFoundation/ExpressionRequestMatcher.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation;

use Symfony\Component\ExpressionLanguage\ExpressionLanguage;

/**
 * ExpressionRequestMatcher uses an expression to match a Request.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ExpressionRequestMatcher extends RequestMatcher
{
    private $language;
    private $expression;

    public function setExpression(ExpressionLanguage $language, $expression)
    {
        $this->language = $language;
        $this->expression = $expression;
    }

    public function matches(Request $request)
    {
        if (!$this->language) {
            throw new \LogicException('Unable to match the request as the expression language is not available.');
        }

        return $this->language->evaluate($this->expression, array(
            'request' => $request,
            'method' => $request->getMethod(),
            'path' => rawurldecode($request->getPathInfo()),
            'host' => $request->getHost(),
            'ip' => $request->getClientIp(),
            'attributes' => $request->attributes->all(),
        )) && parent::matches($request);
    }
}
PK��Z�a.1Symfony/Component/HttpFoundation/AcceptHeader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation;

/**
 * Represents an Accept-* header.
 *
 * An accept header is compound with a list of items,
 * sorted by descending quality.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class AcceptHeader
{
    /**
     * @var AcceptHeaderItem[]
     */
    private $items = array();

    /**
     * @var bool
     */
    private $sorted = true;

    /**
     * Constructor.
     *
     * @param AcceptHeaderItem[] $items
     */
    public function __construct(array $items)
    {
        foreach ($items as $item) {
            $this->add($item);
        }
    }

    /**
     * Builds an AcceptHeader instance from a string.
     *
     * @param string $headerValue
     *
     * @return AcceptHeader
     */
    public static function fromString($headerValue)
    {
        $index = 0;

        return new self(array_map(function ($itemValue) use (&$index) {
            $item = AcceptHeaderItem::fromString($itemValue);
            $item->setIndex($index++);

            return $item;
        }, preg_split('/\s*(?:,*("[^"]+"),*|,*(\'[^\']+\'),*|,+)\s*/', $headerValue, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE)));
    }

    /**
     * Returns header value's string representation.
     *
     * @return string
     */
    public function __toString()
    {
        return implode(',', $this->items);
    }

    /**
     * Tests if header has given value.
     *
     * @param string $value
     *
     * @return Boolean
     */
    public function has($value)
    {
        return isset($this->items[$value]);
    }

    /**
     * Returns given value's item, if exists.
     *
     * @param string $value
     *
     * @return AcceptHeaderItem|null
     */
    public function get($value)
    {
        return isset($this->items[$value]) ? $this->items[$value] : null;
    }

    /**
     * Adds an item.
     *
     * @param AcceptHeaderItem $item
     *
     * @return AcceptHeader
     */
    public function add(AcceptHeaderItem $item)
    {
        $this->items[$item->getValue()] = $item;
        $this->sorted = false;

        return $this;
    }

    /**
     * Returns all items.
     *
     * @return AcceptHeaderItem[]
     */
    public function all()
    {
        $this->sort();

        return $this->items;
    }

    /**
     * Filters items on their value using given regex.
     *
     * @param string $pattern
     *
     * @return AcceptHeader
     */
    public function filter($pattern)
    {
        return new self(array_filter($this->items, function (AcceptHeaderItem $item) use ($pattern) {
            return preg_match($pattern, $item->getValue());
        }));
    }

    /**
     * Returns first item.
     *
     * @return AcceptHeaderItem|null
     */
    public function first()
    {
        $this->sort();

        return !empty($this->items) ? reset($this->items) : null;
    }

    /**
     * Sorts items by descending quality
     */
    private function sort()
    {
        if (!$this->sorted) {
            uasort($this->items, function ($a, $b) {
                $qA = $a->getQuality();
                $qB = $b->getQuality();

                if ($qA === $qB) {
                    return $a->getIndex() > $b->getIndex() ? 1 : -1;
                }

                return $qA > $qB ? -1 : 1;
            });

            $this->sorted = true;
        }
    }
}
PK��Z\�8��1Symfony/Component/HttpFoundation/ParameterBag.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation;

/**
 * ParameterBag is a container for key/value pairs.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class ParameterBag implements \IteratorAggregate, \Countable
{
    /**
     * Parameter storage.
     *
     * @var array
     */
    protected $parameters;

    /**
     * Constructor.
     *
     * @param array $parameters An array of parameters
     *
     * @api
     */
    public function __construct(array $parameters = array())
    {
        $this->parameters = $parameters;
    }

    /**
     * Returns the parameters.
     *
     * @return array An array of parameters
     *
     * @api
     */
    public function all()
    {
        return $this->parameters;
    }

    /**
     * Returns the parameter keys.
     *
     * @return array An array of parameter keys
     *
     * @api
     */
    public function keys()
    {
        return array_keys($this->parameters);
    }

    /**
     * Replaces the current parameters by a new set.
     *
     * @param array $parameters An array of parameters
     *
     * @api
     */
    public function replace(array $parameters = array())
    {
        $this->parameters = $parameters;
    }

    /**
     * Adds parameters.
     *
     * @param array $parameters An array of parameters
     *
     * @api
     */
    public function add(array $parameters = array())
    {
        $this->parameters = array_replace($this->parameters, $parameters);
    }

    /**
     * Returns a parameter by name.
     *
     * @param string  $path    The key
     * @param mixed   $default The default value if the parameter key does not exist
     * @param boolean $deep    If true, a path like foo[bar] will find deeper items
     *
     * @return mixed
     *
     * @throws \InvalidArgumentException
     *
     * @api
     */
    public function get($path, $default = null, $deep = false)
    {
        if (!$deep || false === $pos = strpos($path, '[')) {
            return array_key_exists($path, $this->parameters) ? $this->parameters[$path] : $default;
        }

        $root = substr($path, 0, $pos);
        if (!array_key_exists($root, $this->parameters)) {
            return $default;
        }

        $value = $this->parameters[$root];
        $currentKey = null;
        for ($i = $pos, $c = strlen($path); $i < $c; $i++) {
            $char = $path[$i];

            if ('[' === $char) {
                if (null !== $currentKey) {
                    throw new \InvalidArgumentException(sprintf('Malformed path. Unexpected "[" at position %d.', $i));
                }

                $currentKey = '';
            } elseif (']' === $char) {
                if (null === $currentKey) {
                    throw new \InvalidArgumentException(sprintf('Malformed path. Unexpected "]" at position %d.', $i));
                }

                if (!is_array($value) || !array_key_exists($currentKey, $value)) {
                    return $default;
                }

                $value = $value[$currentKey];
                $currentKey = null;
            } else {
                if (null === $currentKey) {
                    throw new \InvalidArgumentException(sprintf('Malformed path. Unexpected "%s" at position %d.', $char, $i));
                }

                $currentKey .= $char;
            }
        }

        if (null !== $currentKey) {
            throw new \InvalidArgumentException(sprintf('Malformed path. Path must end with "]".'));
        }

        return $value;
    }

    /**
     * Sets a parameter by name.
     *
     * @param string $key   The key
     * @param mixed  $value The value
     *
     * @api
     */
    public function set($key, $value)
    {
        $this->parameters[$key] = $value;
    }

    /**
     * Returns true if the parameter is defined.
     *
     * @param string $key The key
     *
     * @return Boolean true if the parameter exists, false otherwise
     *
     * @api
     */
    public function has($key)
    {
        return array_key_exists($key, $this->parameters);
    }

    /**
     * Removes a parameter.
     *
     * @param string $key The key
     *
     * @api
     */
    public function remove($key)
    {
        unset($this->parameters[$key]);
    }

    /**
     * Returns the alphabetic characters of the parameter value.
     *
     * @param string  $key     The parameter key
     * @param mixed   $default The default value if the parameter key does not exist
     * @param boolean $deep    If true, a path like foo[bar] will find deeper items
     *
     * @return string The filtered value
     *
     * @api
     */
    public function getAlpha($key, $default = '', $deep = false)
    {
        return preg_replace('/[^[:alpha:]]/', '', $this->get($key, $default, $deep));
    }

    /**
     * Returns the alphabetic characters and digits of the parameter value.
     *
     * @param string  $key     The parameter key
     * @param mixed   $default The default value if the parameter key does not exist
     * @param boolean $deep    If true, a path like foo[bar] will find deeper items
     *
     * @return string The filtered value
     *
     * @api
     */
    public function getAlnum($key, $default = '', $deep = false)
    {
        return preg_replace('/[^[:alnum:]]/', '', $this->get($key, $default, $deep));
    }

    /**
     * Returns the digits of the parameter value.
     *
     * @param string  $key     The parameter key
     * @param mixed   $default The default value if the parameter key does not exist
     * @param boolean $deep    If true, a path like foo[bar] will find deeper items
     *
     * @return string The filtered value
     *
     * @api
     */
    public function getDigits($key, $default = '', $deep = false)
    {
        // we need to remove - and + because they're allowed in the filter
        return str_replace(array('-', '+'), '', $this->filter($key, $default, $deep, FILTER_SANITIZE_NUMBER_INT));
    }

    /**
     * Returns the parameter value converted to integer.
     *
     * @param string  $key     The parameter key
     * @param mixed   $default The default value if the parameter key does not exist
     * @param boolean $deep    If true, a path like foo[bar] will find deeper items
     *
     * @return integer The filtered value
     *
     * @api
     */
    public function getInt($key, $default = 0, $deep = false)
    {
        return (int) $this->get($key, $default, $deep);
    }

    /**
     * Filter key.
     *
     * @param string  $key     Key.
     * @param mixed   $default Default = null.
     * @param boolean $deep    Default = false.
     * @param integer $filter  FILTER_* constant.
     * @param mixed   $options Filter options.
     *
     * @see http://php.net/manual/en/function.filter-var.php
     *
     * @return mixed
     */
    public function filter($key, $default = null, $deep = false, $filter = FILTER_DEFAULT, $options = array())
    {
        $value = $this->get($key, $default, $deep);

        // Always turn $options into an array - this allows filter_var option shortcuts.
        if (!is_array($options) && $options) {
            $options = array('flags' => $options);
        }

        // Add a convenience check for arrays.
        if (is_array($value) && !isset($options['flags'])) {
            $options['flags'] = FILTER_REQUIRE_ARRAY;
        }

        return filter_var($value, $filter, $options);
    }

    /**
     * Returns an iterator for parameters.
     *
     * @return \ArrayIterator An \ArrayIterator instance
     */
    public function getIterator()
    {
        return new \ArrayIterator($this->parameters);
    }

    /**
     * Returns the number of parameters.
     *
     * @return int The number of parameters
     */
    public function count()
    {
        return count($this->parameters);
    }
}
PK��Z��6��BSymfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\File\MimeType;

use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException;

/**
 * A singleton mime type guesser.
 *
 * By default, all mime type guessers provided by the framework are installed
 * (if available on the current OS/PHP setup).
 *
 * You can register custom guessers by calling the register() method on the
 * singleton instance. Custom guessers are always called before any default ones.
 *
 *     $guesser = MimeTypeGuesser::getInstance();
 *     $guesser->register(new MyCustomMimeTypeGuesser());
 *
 * If you want to change the order of the default guessers, just re-register your
 * preferred one as a custom one. The last registered guesser is preferred over
 * previously registered ones.
 *
 * Re-registering a built-in guesser also allows you to configure it:
 *
 *     $guesser = MimeTypeGuesser::getInstance();
 *     $guesser->register(new FileinfoMimeTypeGuesser('/path/to/magic/file'));
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class MimeTypeGuesser implements MimeTypeGuesserInterface
{
    /**
     * The singleton instance
     *
     * @var MimeTypeGuesser
     */
    private static $instance = null;

    /**
     * All registered MimeTypeGuesserInterface instances
     *
     * @var array
     */
    protected $guessers = array();

    /**
     * Returns the singleton instance
     *
     * @return MimeTypeGuesser
     */
    public static function getInstance()
    {
        if (null === self::$instance) {
            self::$instance = new self();
        }

        return self::$instance;
    }

    /**
     * Registers all natively provided mime type guessers
     */
    private function __construct()
    {
        if (FileBinaryMimeTypeGuesser::isSupported()) {
            $this->register(new FileBinaryMimeTypeGuesser());
        }

        if (FileinfoMimeTypeGuesser::isSupported()) {
            $this->register(new FileinfoMimeTypeGuesser());
        }
    }

    /**
     * Registers a new mime type guesser
     *
     * When guessing, this guesser is preferred over previously registered ones.
     *
     * @param MimeTypeGuesserInterface $guesser
     */
    public function register(MimeTypeGuesserInterface $guesser)
    {
        array_unshift($this->guessers, $guesser);
    }

    /**
     * Tries to guess the mime type of the given file
     *
     * The file is passed to each registered mime type guesser in reverse order
     * of their registration (last registered is queried first). Once a guesser
     * returns a value that is not NULL, this method terminates and returns the
     * value.
     *
     * @param string $path The path to the file
     *
     * @return string         The mime type or NULL, if none could be guessed
     *
     * @throws \LogicException
     * @throws FileNotFoundException
     * @throws AccessDeniedException
     */
    public function guess($path)
    {
        if (!is_file($path)) {
            throw new FileNotFoundException($path);
        }

        if (!is_readable($path)) {
            throw new AccessDeniedException($path);
        }

        if (!$this->guessers) {
            throw new \LogicException('Unable to guess the mime type as no guessers are available (Did you enable the php_fileinfo extension?)');
        }

        foreach ($this->guessers as $guesser) {
            if (null !== $mimeType = $guesser->guess($path)) {
                return $mimeType;
            }
        }
    }
}
PK��Z5p1��JSymfony/Component/HttpFoundation/File/MimeType/FileinfoMimeTypeGuesser.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\File\MimeType;

use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException;

/**
 * Guesses the mime type using the PECL extension FileInfo.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class FileinfoMimeTypeGuesser implements MimeTypeGuesserInterface
{
    private $magicFile;

    /**
     * Constructor.
     *
     * @param string $magicFile A magic file to use with the finfo instance
     *
     * @link http://www.php.net/manual/en/function.finfo-open.php
     */
    public function __construct($magicFile = null)
    {
        $this->magicFile = $magicFile;
    }

    /**
     * Returns whether this guesser is supported on the current OS/PHP setup
     *
     * @return Boolean
     */
    public static function isSupported()
    {
        return function_exists('finfo_open');
    }

    /**
     * {@inheritdoc}
     */
    public function guess($path)
    {
        if (!is_file($path)) {
            throw new FileNotFoundException($path);
        }

        if (!is_readable($path)) {
            throw new AccessDeniedException($path);
        }

        if (!self::isSupported()) {
            return null;
        }

        if (!$finfo = new \finfo(FILEINFO_MIME_TYPE, $this->magicFile)) {
            return null;
        }

        return $finfo->file($path);
    }
}
PK��Z�qx��LSymfony/Component/HttpFoundation/File/MimeType/ExtensionGuesserInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\File\MimeType;

/**
 * Guesses the file extension corresponding to a given mime type
 */
interface ExtensionGuesserInterface
{
    /**
     * Makes a best guess for a file extension, given a mime type
     *
     * @param string $mimeType The mime type
     * @return string          The guessed extension or NULL, if none could be guessed
     */
    public function guess($mimeType);
}
PK��Z�J��LSymfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\File\MimeType;

use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException;

/**
 * Guesses the mime type with the binary "file" (only available on *nix)
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class FileBinaryMimeTypeGuesser implements MimeTypeGuesserInterface
{
    private $cmd;

    /**
     * Constructor.
     *
     * The $cmd pattern must contain a "%s" string that will be replaced
     * with the file name to guess.
     *
     * The command output must start with the mime type of the file.
     *
     * @param string $cmd The command to run to get the mime type of a file
     */
    public function __construct($cmd = 'file -b --mime %s 2>/dev/null')
    {
        $this->cmd = $cmd;
    }

    /**
     * Returns whether this guesser is supported on the current OS
     *
     * @return Boolean
     */
    public static function isSupported()
    {
        return !defined('PHP_WINDOWS_VERSION_BUILD') && function_exists('passthru') && function_exists('escapeshellarg');
    }

    /**
     * {@inheritdoc}
     */
    public function guess($path)
    {
        if (!is_file($path)) {
            throw new FileNotFoundException($path);
        }

        if (!is_readable($path)) {
            throw new AccessDeniedException($path);
        }

        if (!self::isSupported()) {
            return null;
        }

        ob_start();

        // need to use --mime instead of -i. see #6641
        passthru(sprintf($this->cmd, escapeshellarg($path)), $return);
        if ($return > 0) {
            ob_end_clean();

            return null;
        }

        $type = trim(ob_get_clean());

        if (!preg_match('#^([a-z0-9\-]+/[a-z0-9\-\.]+)#i', $type, $match)) {
            // it's not a type, but an error message
            return null;
        }

        return $match[1];
    }
}
PK��Z2�k�	�	CSymfony/Component/HttpFoundation/File/MimeType/ExtensionGuesser.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\File\MimeType;

/**
 * A singleton mime type to file extension guesser.
 *
 * A default guesser is provided.
 * You can register custom guessers by calling the register()
 * method on the singleton instance:
 *
 *     $guesser = ExtensionGuesser::getInstance();
 *     $guesser->register(new MyCustomExtensionGuesser());
 *
 * The last registered guesser is preferred over previously registered ones.
 */
class ExtensionGuesser implements ExtensionGuesserInterface
{
    /**
     * The singleton instance
     *
     * @var ExtensionGuesser
     */
    private static $instance = null;

    /**
     * All registered ExtensionGuesserInterface instances
     *
     * @var array
     */
    protected $guessers = array();

    /**
     * Returns the singleton instance
     *
     * @return ExtensionGuesser
     */
    public static function getInstance()
    {
        if (null === self::$instance) {
            self::$instance = new self();
        }

        return self::$instance;
    }

    /**
     * Registers all natively provided extension guessers
     */
    private function __construct()
    {
        $this->register(new MimeTypeExtensionGuesser());
    }

    /**
     * Registers a new extension guesser
     *
     * When guessing, this guesser is preferred over previously registered ones.
     *
     * @param ExtensionGuesserInterface $guesser
     */
    public function register(ExtensionGuesserInterface $guesser)
    {
        array_unshift($this->guessers, $guesser);
    }

    /**
     * Tries to guess the extension
     *
     * The mime type is passed to each registered mime type guesser in reverse order
     * of their registration (last registered is queried first). Once a guesser
     * returns a value that is not NULL, this method terminates and returns the
     * value.
     *
     * @param string $mimeType The mime type
     *
     * @return string          The guessed extension or NULL, if none could be guessed
     */
    public function guess($mimeType)
    {
        foreach ($this->guessers as $guesser) {
            if (null !== $extension = $guesser->guess($mimeType)) {
                return $extension;
            }
        }
    }
}
PK��Z�w�nM�M�KSymfony/Component/HttpFoundation/File/MimeType/MimeTypeExtensionGuesser.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\File\MimeType;

/**
 * Provides a best-guess mapping of mime type to file extension.
 */
class MimeTypeExtensionGuesser implements ExtensionGuesserInterface
{
    /**
     * A map of mime types and their default extensions.
     *
     * This list has been placed under the public domain by the Apache HTTPD project.
     * This list has been updated from upstream on 2013-04-23.
     *
     * @see http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
     *
     * @var array
     */
    protected $defaultExtensions = array(
        'application/andrew-inset' => 'ez',
        'application/applixware' => 'aw',
        'application/atom+xml' => 'atom',
        'application/atomcat+xml' => 'atomcat',
        'application/atomsvc+xml' => 'atomsvc',
        'application/ccxml+xml' => 'ccxml',
        'application/cdmi-capability' => 'cdmia',
        'application/cdmi-container' => 'cdmic',
        'application/cdmi-domain' => 'cdmid',
        'application/cdmi-object' => 'cdmio',
        'application/cdmi-queue' => 'cdmiq',
        'application/cu-seeme' => 'cu',
        'application/davmount+xml' => 'davmount',
        'application/docbook+xml' => 'dbk',
        'application/dssc+der' => 'dssc',
        'application/dssc+xml' => 'xdssc',
        'application/ecmascript' => 'ecma',
        'application/emma+xml' => 'emma',
        'application/epub+zip' => 'epub',
        'application/exi' => 'exi',
        'application/font-tdpfr' => 'pfr',
        'application/gml+xml' => 'gml',
        'application/gpx+xml' => 'gpx',
        'application/gxf' => 'gxf',
        'application/hyperstudio' => 'stk',
        'application/inkml+xml' => 'ink',
        'application/ipfix' => 'ipfix',
        'application/java-archive' => 'jar',
        'application/java-serialized-object' => 'ser',
        'application/java-vm' => 'class',
        'application/javascript' => 'js',
        'application/json' => 'json',
        'application/jsonml+json' => 'jsonml',
        'application/lost+xml' => 'lostxml',
        'application/mac-binhex40' => 'hqx',
        'application/mac-compactpro' => 'cpt',
        'application/mads+xml' => 'mads',
        'application/marc' => 'mrc',
        'application/marcxml+xml' => 'mrcx',
        'application/mathematica' => 'ma',
        'application/mathml+xml' => 'mathml',
        'application/mbox' => 'mbox',
        'application/mediaservercontrol+xml' => 'mscml',
        'application/metalink+xml' => 'metalink',
        'application/metalink4+xml' => 'meta4',
        'application/mets+xml' => 'mets',
        'application/mods+xml' => 'mods',
        'application/mp21' => 'm21',
        'application/mp4' => 'mp4s',
        'application/msword' => 'doc',
        'application/mxf' => 'mxf',
        'application/octet-stream' => 'bin',
        'application/oda' => 'oda',
        'application/oebps-package+xml' => 'opf',
        'application/ogg' => 'ogx',
        'application/omdoc+xml' => 'omdoc',
        'application/onenote' => 'onetoc',
        'application/oxps' => 'oxps',
        'application/patch-ops-error+xml' => 'xer',
        'application/pdf' => 'pdf',
        'application/pgp-encrypted' => 'pgp',
        'application/pgp-signature' => 'asc',
        'application/pics-rules' => 'prf',
        'application/pkcs10' => 'p10',
        'application/pkcs7-mime' => 'p7m',
        'application/pkcs7-signature' => 'p7s',
        'application/pkcs8' => 'p8',
        'application/pkix-attr-cert' => 'ac',
        'application/pkix-cert' => 'cer',
        'application/pkix-crl' => 'crl',
        'application/pkix-pkipath' => 'pkipath',
        'application/pkixcmp' => 'pki',
        'application/pls+xml' => 'pls',
        'application/postscript' => 'ai',
        'application/prs.cww' => 'cww',
        'application/pskc+xml' => 'pskcxml',
        'application/rdf+xml' => 'rdf',
        'application/reginfo+xml' => 'rif',
        'application/relax-ng-compact-syntax' => 'rnc',
        'application/resource-lists+xml' => 'rl',
        'application/resource-lists-diff+xml' => 'rld',
        'application/rls-services+xml' => 'rs',
        'application/rpki-ghostbusters' => 'gbr',
        'application/rpki-manifest' => 'mft',
        'application/rpki-roa' => 'roa',
        'application/rsd+xml' => 'rsd',
        'application/rss+xml' => 'rss',
        'application/rtf' => 'rtf',
        'application/sbml+xml' => 'sbml',
        'application/scvp-cv-request' => 'scq',
        'application/scvp-cv-response' => 'scs',
        'application/scvp-vp-request' => 'spq',
        'application/scvp-vp-response' => 'spp',
        'application/sdp' => 'sdp',
        'application/set-payment-initiation' => 'setpay',
        'application/set-registration-initiation' => 'setreg',
        'application/shf+xml' => 'shf',
        'application/smil+xml' => 'smi',
        'application/sparql-query' => 'rq',
        'application/sparql-results+xml' => 'srx',
        'application/srgs' => 'gram',
        'application/srgs+xml' => 'grxml',
        'application/sru+xml' => 'sru',
        'application/ssdl+xml' => 'ssdl',
        'application/ssml+xml' => 'ssml',
        'application/tei+xml' => 'tei',
        'application/thraud+xml' => 'tfi',
        'application/timestamped-data' => 'tsd',
        'application/vnd.3gpp.pic-bw-large' => 'plb',
        'application/vnd.3gpp.pic-bw-small' => 'psb',
        'application/vnd.3gpp.pic-bw-var' => 'pvb',
        'application/vnd.3gpp2.tcap' => 'tcap',
        'application/vnd.3m.post-it-notes' => 'pwn',
        'application/vnd.accpac.simply.aso' => 'aso',
        'application/vnd.accpac.simply.imp' => 'imp',
        'application/vnd.acucobol' => 'acu',
        'application/vnd.acucorp' => 'atc',
        'application/vnd.adobe.air-application-installer-package+zip' => 'air',
        'application/vnd.adobe.formscentral.fcdt' => 'fcdt',
        'application/vnd.adobe.fxp' => 'fxp',
        'application/vnd.adobe.xdp+xml' => 'xdp',
        'application/vnd.adobe.xfdf' => 'xfdf',
        'application/vnd.ahead.space' => 'ahead',
        'application/vnd.airzip.filesecure.azf' => 'azf',
        'application/vnd.airzip.filesecure.azs' => 'azs',
        'application/vnd.amazon.ebook' => 'azw',
        'application/vnd.americandynamics.acc' => 'acc',
        'application/vnd.amiga.ami' => 'ami',
        'application/vnd.android.package-archive' => 'apk',
        'application/vnd.anser-web-certificate-issue-initiation' => 'cii',
        'application/vnd.anser-web-funds-transfer-initiation' => 'fti',
        'application/vnd.antix.game-component' => 'atx',
        'application/vnd.apple.installer+xml' => 'mpkg',
        'application/vnd.apple.mpegurl' => 'm3u8',
        'application/vnd.aristanetworks.swi' => 'swi',
        'application/vnd.astraea-software.iota' => 'iota',
        'application/vnd.audiograph' => 'aep',
        'application/vnd.blueice.multipass' => 'mpm',
        'application/vnd.bmi' => 'bmi',
        'application/vnd.businessobjects' => 'rep',
        'application/vnd.chemdraw+xml' => 'cdxml',
        'application/vnd.chipnuts.karaoke-mmd' => 'mmd',
        'application/vnd.cinderella' => 'cdy',
        'application/vnd.claymore' => 'cla',
        'application/vnd.cloanto.rp9' => 'rp9',
        'application/vnd.clonk.c4group' => 'c4g',
        'application/vnd.cluetrust.cartomobile-config' => 'c11amc',
        'application/vnd.cluetrust.cartomobile-config-pkg' => 'c11amz',
        'application/vnd.commonspace' => 'csp',
        'application/vnd.contact.cmsg' => 'cdbcmsg',
        'application/vnd.cosmocaller' => 'cmc',
        'application/vnd.crick.clicker' => 'clkx',
        'application/vnd.crick.clicker.keyboard' => 'clkk',
        'application/vnd.crick.clicker.palette' => 'clkp',
        'application/vnd.crick.clicker.template' => 'clkt',
        'application/vnd.crick.clicker.wordbank' => 'clkw',
        'application/vnd.criticaltools.wbs+xml' => 'wbs',
        'application/vnd.ctc-posml' => 'pml',
        'application/vnd.cups-ppd' => 'ppd',
        'application/vnd.curl.car' => 'car',
        'application/vnd.curl.pcurl' => 'pcurl',
        'application/vnd.dart' => 'dart',
        'application/vnd.data-vision.rdz' => 'rdz',
        'application/vnd.dece.data' => 'uvf',
        'application/vnd.dece.ttml+xml' => 'uvt',
        'application/vnd.dece.unspecified' => 'uvx',
        'application/vnd.dece.zip' => 'uvz',
        'application/vnd.denovo.fcselayout-link' => 'fe_launch',
        'application/vnd.dna' => 'dna',
        'application/vnd.dolby.mlp' => 'mlp',
        'application/vnd.dpgraph' => 'dpg',
        'application/vnd.dreamfactory' => 'dfac',
        'application/vnd.ds-keypoint' => 'kpxx',
        'application/vnd.dvb.ait' => 'ait',
        'application/vnd.dvb.service' => 'svc',
        'application/vnd.dynageo' => 'geo',
        'application/vnd.ecowin.chart' => 'mag',
        'application/vnd.enliven' => 'nml',
        'application/vnd.epson.esf' => 'esf',
        'application/vnd.epson.msf' => 'msf',
        'application/vnd.epson.quickanime' => 'qam',
        'application/vnd.epson.salt' => 'slt',
        'application/vnd.epson.ssf' => 'ssf',
        'application/vnd.eszigno3+xml' => 'es3',
        'application/vnd.ezpix-album' => 'ez2',
        'application/vnd.ezpix-package' => 'ez3',
        'application/vnd.fdf' => 'fdf',
        'application/vnd.fdsn.mseed' => 'mseed',
        'application/vnd.fdsn.seed' => 'seed',
        'application/vnd.flographit' => 'gph',
        'application/vnd.fluxtime.clip' => 'ftc',
        'application/vnd.framemaker' => 'fm',
        'application/vnd.frogans.fnc' => 'fnc',
        'application/vnd.frogans.ltf' => 'ltf',
        'application/vnd.fsc.weblaunch' => 'fsc',
        'application/vnd.fujitsu.oasys' => 'oas',
        'application/vnd.fujitsu.oasys2' => 'oa2',
        'application/vnd.fujitsu.oasys3' => 'oa3',
        'application/vnd.fujitsu.oasysgp' => 'fg5',
        'application/vnd.fujitsu.oasysprs' => 'bh2',
        'application/vnd.fujixerox.ddd' => 'ddd',
        'application/vnd.fujixerox.docuworks' => 'xdw',
        'application/vnd.fujixerox.docuworks.binder' => 'xbd',
        'application/vnd.fuzzysheet' => 'fzs',
        'application/vnd.genomatix.tuxedo' => 'txd',
        'application/vnd.geogebra.file' => 'ggb',
        'application/vnd.geogebra.tool' => 'ggt',
        'application/vnd.geometry-explorer' => 'gex',
        'application/vnd.geonext' => 'gxt',
        'application/vnd.geoplan' => 'g2w',
        'application/vnd.geospace' => 'g3w',
        'application/vnd.gmx' => 'gmx',
        'application/vnd.google-earth.kml+xml' => 'kml',
        'application/vnd.google-earth.kmz' => 'kmz',
        'application/vnd.grafeq' => 'gqf',
        'application/vnd.groove-account' => 'gac',
        'application/vnd.groove-help' => 'ghf',
        'application/vnd.groove-identity-message' => 'gim',
        'application/vnd.groove-injector' => 'grv',
        'application/vnd.groove-tool-message' => 'gtm',
        'application/vnd.groove-tool-template' => 'tpl',
        'application/vnd.groove-vcard' => 'vcg',
        'application/vnd.hal+xml' => 'hal',
        'application/vnd.handheld-entertainment+xml' => 'zmm',
        'application/vnd.hbci' => 'hbci',
        'application/vnd.hhe.lesson-player' => 'les',
        'application/vnd.hp-hpgl' => 'hpgl',
        'application/vnd.hp-hpid' => 'hpid',
        'application/vnd.hp-hps' => 'hps',
        'application/vnd.hp-jlyt' => 'jlt',
        'application/vnd.hp-pcl' => 'pcl',
        'application/vnd.hp-pclxl' => 'pclxl',
        'application/vnd.hydrostatix.sof-data' => 'sfd-hdstx',
        'application/vnd.ibm.minipay' => 'mpy',
        'application/vnd.ibm.modcap' => 'afp',
        'application/vnd.ibm.rights-management' => 'irm',
        'application/vnd.ibm.secure-container' => 'sc',
        'application/vnd.iccprofile' => 'icc',
        'application/vnd.igloader' => 'igl',
        'application/vnd.immervision-ivp' => 'ivp',
        'application/vnd.immervision-ivu' => 'ivu',
        'application/vnd.insors.igm' => 'igm',
        'application/vnd.intercon.formnet' => 'xpw',
        'application/vnd.intergeo' => 'i2g',
        'application/vnd.intu.qbo' => 'qbo',
        'application/vnd.intu.qfx' => 'qfx',
        'application/vnd.ipunplugged.rcprofile' => 'rcprofile',
        'application/vnd.irepository.package+xml' => 'irp',
        'application/vnd.is-xpr' => 'xpr',
        'application/vnd.isac.fcs' => 'fcs',
        'application/vnd.jam' => 'jam',
        'application/vnd.jcp.javame.midlet-rms' => 'rms',
        'application/vnd.jisp' => 'jisp',
        'application/vnd.joost.joda-archive' => 'joda',
        'application/vnd.kahootz' => 'ktz',
        'application/vnd.kde.karbon' => 'karbon',
        'application/vnd.kde.kchart' => 'chrt',
        'application/vnd.kde.kformula' => 'kfo',
        'application/vnd.kde.kivio' => 'flw',
        'application/vnd.kde.kontour' => 'kon',
        'application/vnd.kde.kpresenter' => 'kpr',
        'application/vnd.kde.kspread' => 'ksp',
        'application/vnd.kde.kword' => 'kwd',
        'application/vnd.kenameaapp' => 'htke',
        'application/vnd.kidspiration' => 'kia',
        'application/vnd.kinar' => 'kne',
        'application/vnd.koan' => 'skp',
        'application/vnd.kodak-descriptor' => 'sse',
        'application/vnd.las.las+xml' => 'lasxml',
        'application/vnd.llamagraphics.life-balance.desktop' => 'lbd',
        'application/vnd.llamagraphics.life-balance.exchange+xml' => 'lbe',
        'application/vnd.lotus-1-2-3' => '123',
        'application/vnd.lotus-approach' => 'apr',
        'application/vnd.lotus-freelance' => 'pre',
        'application/vnd.lotus-notes' => 'nsf',
        'application/vnd.lotus-organizer' => 'org',
        'application/vnd.lotus-screencam' => 'scm',
        'application/vnd.lotus-wordpro' => 'lwp',
        'application/vnd.macports.portpkg' => 'portpkg',
        'application/vnd.mcd' => 'mcd',
        'application/vnd.medcalcdata' => 'mc1',
        'application/vnd.mediastation.cdkey' => 'cdkey',
        'application/vnd.mfer' => 'mwf',
        'application/vnd.mfmp' => 'mfm',
        'application/vnd.micrografx.flo' => 'flo',
        'application/vnd.micrografx.igx' => 'igx',
        'application/vnd.mif' => 'mif',
        'application/vnd.mobius.daf' => 'daf',
        'application/vnd.mobius.dis' => 'dis',
        'application/vnd.mobius.mbk' => 'mbk',
        'application/vnd.mobius.mqy' => 'mqy',
        'application/vnd.mobius.msl' => 'msl',
        'application/vnd.mobius.plc' => 'plc',
        'application/vnd.mobius.txf' => 'txf',
        'application/vnd.mophun.application' => 'mpn',
        'application/vnd.mophun.certificate' => 'mpc',
        'application/vnd.mozilla.xul+xml' => 'xul',
        'application/vnd.ms-artgalry' => 'cil',
        'application/vnd.ms-cab-compressed' => 'cab',
        'application/vnd.ms-excel' => 'xls',
        'application/vnd.ms-excel.addin.macroenabled.12' => 'xlam',
        'application/vnd.ms-excel.sheet.binary.macroenabled.12' => 'xlsb',
        'application/vnd.ms-excel.sheet.macroenabled.12' => 'xlsm',
        'application/vnd.ms-excel.template.macroenabled.12' => 'xltm',
        'application/vnd.ms-fontobject' => 'eot',
        'application/vnd.ms-htmlhelp' => 'chm',
        'application/vnd.ms-ims' => 'ims',
        'application/vnd.ms-lrm' => 'lrm',
        'application/vnd.ms-officetheme' => 'thmx',
        'application/vnd.ms-pki.seccat' => 'cat',
        'application/vnd.ms-pki.stl' => 'stl',
        'application/vnd.ms-powerpoint' => 'ppt',
        'application/vnd.ms-powerpoint.addin.macroenabled.12' => 'ppam',
        'application/vnd.ms-powerpoint.presentation.macroenabled.12' => 'pptm',
        'application/vnd.ms-powerpoint.slide.macroenabled.12' => 'sldm',
        'application/vnd.ms-powerpoint.slideshow.macroenabled.12' => 'ppsm',
        'application/vnd.ms-powerpoint.template.macroenabled.12' => 'potm',
        'application/vnd.ms-project' => 'mpp',
        'application/vnd.ms-word.document.macroenabled.12' => 'docm',
        'application/vnd.ms-word.template.macroenabled.12' => 'dotm',
        'application/vnd.ms-works' => 'wps',
        'application/vnd.ms-wpl' => 'wpl',
        'application/vnd.ms-xpsdocument' => 'xps',
        'application/vnd.mseq' => 'mseq',
        'application/vnd.musician' => 'mus',
        'application/vnd.muvee.style' => 'msty',
        'application/vnd.mynfc' => 'taglet',
        'application/vnd.neurolanguage.nlu' => 'nlu',
        'application/vnd.nitf' => 'ntf',
        'application/vnd.noblenet-directory' => 'nnd',
        'application/vnd.noblenet-sealer' => 'nns',
        'application/vnd.noblenet-web' => 'nnw',
        'application/vnd.nokia.n-gage.data' => 'ngdat',
        'application/vnd.nokia.n-gage.symbian.install' => 'n-gage',
        'application/vnd.nokia.radio-preset' => 'rpst',
        'application/vnd.nokia.radio-presets' => 'rpss',
        'application/vnd.novadigm.edm' => 'edm',
        'application/vnd.novadigm.edx' => 'edx',
        'application/vnd.novadigm.ext' => 'ext',
        'application/vnd.oasis.opendocument.chart' => 'odc',
        'application/vnd.oasis.opendocument.chart-template' => 'otc',
        'application/vnd.oasis.opendocument.database' => 'odb',
        'application/vnd.oasis.opendocument.formula' => 'odf',
        'application/vnd.oasis.opendocument.formula-template' => 'odft',
        'application/vnd.oasis.opendocument.graphics' => 'odg',
        'application/vnd.oasis.opendocument.graphics-template' => 'otg',
        'application/vnd.oasis.opendocument.image' => 'odi',
        'application/vnd.oasis.opendocument.image-template' => 'oti',
        'application/vnd.oasis.opendocument.presentation' => 'odp',
        'application/vnd.oasis.opendocument.presentation-template' => 'otp',
        'application/vnd.oasis.opendocument.spreadsheet' => 'ods',
        'application/vnd.oasis.opendocument.spreadsheet-template' => 'ots',
        'application/vnd.oasis.opendocument.text' => 'odt',
        'application/vnd.oasis.opendocument.text-master' => 'odm',
        'application/vnd.oasis.opendocument.text-template' => 'ott',
        'application/vnd.oasis.opendocument.text-web' => 'oth',
        'application/vnd.olpc-sugar' => 'xo',
        'application/vnd.oma.dd2+xml' => 'dd2',
        'application/vnd.openofficeorg.extension' => 'oxt',
        'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'pptx',
        'application/vnd.openxmlformats-officedocument.presentationml.slide' => 'sldx',
        'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => 'ppsx',
        'application/vnd.openxmlformats-officedocument.presentationml.template' => 'potx',
        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'xlsx',
        'application/vnd.openxmlformats-officedocument.spreadsheetml.template' => 'xltx',
        'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'docx',
        'application/vnd.openxmlformats-officedocument.wordprocessingml.template' => 'dotx',
        'application/vnd.osgeo.mapguide.package' => 'mgp',
        'application/vnd.osgi.dp' => 'dp',
        'application/vnd.osgi.subsystem' => 'esa',
        'application/vnd.palm' => 'pdb',
        'application/vnd.pawaafile' => 'paw',
        'application/vnd.pg.format' => 'str',
        'application/vnd.pg.osasli' => 'ei6',
        'application/vnd.picsel' => 'efif',
        'application/vnd.pmi.widget' => 'wg',
        'application/vnd.pocketlearn' => 'plf',
        'application/vnd.powerbuilder6' => 'pbd',
        'application/vnd.previewsystems.box' => 'box',
        'application/vnd.proteus.magazine' => 'mgz',
        'application/vnd.publishare-delta-tree' => 'qps',
        'application/vnd.pvi.ptid1' => 'ptid',
        'application/vnd.quark.quarkxpress' => 'qxd',
        'application/vnd.realvnc.bed' => 'bed',
        'application/vnd.recordare.musicxml' => 'mxl',
        'application/vnd.recordare.musicxml+xml' => 'musicxml',
        'application/vnd.rig.cryptonote' => 'cryptonote',
        'application/vnd.rim.cod' => 'cod',
        'application/vnd.rn-realmedia' => 'rm',
        'application/vnd.rn-realmedia-vbr' => 'rmvb',
        'application/vnd.route66.link66+xml' => 'link66',
        'application/vnd.sailingtracker.track' => 'st',
        'application/vnd.seemail' => 'see',
        'application/vnd.sema' => 'sema',
        'application/vnd.semd' => 'semd',
        'application/vnd.semf' => 'semf',
        'application/vnd.shana.informed.formdata' => 'ifm',
        'application/vnd.shana.informed.formtemplate' => 'itp',
        'application/vnd.shana.informed.interchange' => 'iif',
        'application/vnd.shana.informed.package' => 'ipk',
        'application/vnd.simtech-mindmapper' => 'twd',
        'application/vnd.smaf' => 'mmf',
        'application/vnd.smart.teacher' => 'teacher',
        'application/vnd.solent.sdkm+xml' => 'sdkm',
        'application/vnd.spotfire.dxp' => 'dxp',
        'application/vnd.spotfire.sfs' => 'sfs',
        'application/vnd.stardivision.calc' => 'sdc',
        'application/vnd.stardivision.draw' => 'sda',
        'application/vnd.stardivision.impress' => 'sdd',
        'application/vnd.stardivision.math' => 'smf',
        'application/vnd.stardivision.writer' => 'sdw',
        'application/vnd.stardivision.writer-global' => 'sgl',
        'application/vnd.stepmania.package' => 'smzip',
        'application/vnd.stepmania.stepchart' => 'sm',
        'application/vnd.sun.xml.calc' => 'sxc',
        'application/vnd.sun.xml.calc.template' => 'stc',
        'application/vnd.sun.xml.draw' => 'sxd',
        'application/vnd.sun.xml.draw.template' => 'std',
        'application/vnd.sun.xml.impress' => 'sxi',
        'application/vnd.sun.xml.impress.template' => 'sti',
        'application/vnd.sun.xml.math' => 'sxm',
        'application/vnd.sun.xml.writer' => 'sxw',
        'application/vnd.sun.xml.writer.global' => 'sxg',
        'application/vnd.sun.xml.writer.template' => 'stw',
        'application/vnd.sus-calendar' => 'sus',
        'application/vnd.svd' => 'svd',
        'application/vnd.symbian.install' => 'sis',
        'application/vnd.syncml+xml' => 'xsm',
        'application/vnd.syncml.dm+wbxml' => 'bdm',
        'application/vnd.syncml.dm+xml' => 'xdm',
        'application/vnd.tao.intent-module-archive' => 'tao',
        'application/vnd.tcpdump.pcap' => 'pcap',
        'application/vnd.tmobile-livetv' => 'tmo',
        'application/vnd.trid.tpt' => 'tpt',
        'application/vnd.triscape.mxs' => 'mxs',
        'application/vnd.trueapp' => 'tra',
        'application/vnd.ufdl' => 'ufd',
        'application/vnd.uiq.theme' => 'utz',
        'application/vnd.umajin' => 'umj',
        'application/vnd.unity' => 'unityweb',
        'application/vnd.uoml+xml' => 'uoml',
        'application/vnd.vcx' => 'vcx',
        'application/vnd.visio' => 'vsd',
        'application/vnd.visionary' => 'vis',
        'application/vnd.vsf' => 'vsf',
        'application/vnd.wap.wbxml' => 'wbxml',
        'application/vnd.wap.wmlc' => 'wmlc',
        'application/vnd.wap.wmlscriptc' => 'wmlsc',
        'application/vnd.webturbo' => 'wtb',
        'application/vnd.wolfram.player' => 'nbp',
        'application/vnd.wordperfect' => 'wpd',
        'application/vnd.wqd' => 'wqd',
        'application/vnd.wt.stf' => 'stf',
        'application/vnd.xara' => 'xar',
        'application/vnd.xfdl' => 'xfdl',
        'application/vnd.yamaha.hv-dic' => 'hvd',
        'application/vnd.yamaha.hv-script' => 'hvs',
        'application/vnd.yamaha.hv-voice' => 'hvp',
        'application/vnd.yamaha.openscoreformat' => 'osf',
        'application/vnd.yamaha.openscoreformat.osfpvg+xml' => 'osfpvg',
        'application/vnd.yamaha.smaf-audio' => 'saf',
        'application/vnd.yamaha.smaf-phrase' => 'spf',
        'application/vnd.yellowriver-custom-menu' => 'cmp',
        'application/vnd.zul' => 'zir',
        'application/vnd.zzazz.deck+xml' => 'zaz',
        'application/voicexml+xml' => 'vxml',
        'application/widget' => 'wgt',
        'application/winhlp' => 'hlp',
        'application/wsdl+xml' => 'wsdl',
        'application/wspolicy+xml' => 'wspolicy',
        'application/x-7z-compressed' => '7z',
        'application/x-abiword' => 'abw',
        'application/x-ace-compressed' => 'ace',
        'application/x-apple-diskimage' => 'dmg',
        'application/x-authorware-bin' => 'aab',
        'application/x-authorware-map' => 'aam',
        'application/x-authorware-seg' => 'aas',
        'application/x-bcpio' => 'bcpio',
        'application/x-bittorrent' => 'torrent',
        'application/x-blorb' => 'blb',
        'application/x-bzip' => 'bz',
        'application/x-bzip2' => 'bz2',
        'application/x-cbr' => 'cbr',
        'application/x-cdlink' => 'vcd',
        'application/x-cfs-compressed' => 'cfs',
        'application/x-chat' => 'chat',
        'application/x-chess-pgn' => 'pgn',
        'application/x-conference' => 'nsc',
        'application/x-cpio' => 'cpio',
        'application/x-csh' => 'csh',
        'application/x-debian-package' => 'deb',
        'application/x-dgc-compressed' => 'dgc',
        'application/x-director' => 'dir',
        'application/x-doom' => 'wad',
        'application/x-dtbncx+xml' => 'ncx',
        'application/x-dtbook+xml' => 'dtb',
        'application/x-dtbresource+xml' => 'res',
        'application/x-dvi' => 'dvi',
        'application/x-envoy' => 'evy',
        'application/x-eva' => 'eva',
        'application/x-font-bdf' => 'bdf',
        'application/x-font-ghostscript' => 'gsf',
        'application/x-font-linux-psf' => 'psf',
        'application/x-font-otf' => 'otf',
        'application/x-font-pcf' => 'pcf',
        'application/x-font-snf' => 'snf',
        'application/x-font-ttf' => 'ttf',
        'application/x-font-type1' => 'pfa',
        'application/x-font-woff' => 'woff',
        'application/x-freearc' => 'arc',
        'application/x-futuresplash' => 'spl',
        'application/x-gca-compressed' => 'gca',
        'application/x-glulx' => 'ulx',
        'application/x-gnumeric' => 'gnumeric',
        'application/x-gramps-xml' => 'gramps',
        'application/x-gtar' => 'gtar',
        'application/x-hdf' => 'hdf',
        'application/x-install-instructions' => 'install',
        'application/x-iso9660-image' => 'iso',
        'application/x-java-jnlp-file' => 'jnlp',
        'application/x-latex' => 'latex',
        'application/x-lzh-compressed' => 'lzh',
        'application/x-mie' => 'mie',
        'application/x-mobipocket-ebook' => 'prc',
        'application/x-ms-application' => 'application',
        'application/x-ms-shortcut' => 'lnk',
        'application/x-ms-wmd' => 'wmd',
        'application/x-ms-wmz' => 'wmz',
        'application/x-ms-xbap' => 'xbap',
        'application/x-msaccess' => 'mdb',
        'application/x-msbinder' => 'obd',
        'application/x-mscardfile' => 'crd',
        'application/x-msclip' => 'clp',
        'application/x-msdownload' => 'exe',
        'application/x-msmediaview' => 'mvb',
        'application/x-msmetafile' => 'wmf',
        'application/x-msmoney' => 'mny',
        'application/x-mspublisher' => 'pub',
        'application/x-msschedule' => 'scd',
        'application/x-msterminal' => 'trm',
        'application/x-mswrite' => 'wri',
        'application/x-netcdf' => 'nc',
        'application/x-nzb' => 'nzb',
        'application/x-pkcs12' => 'p12',
        'application/x-pkcs7-certificates' => 'p7b',
        'application/x-pkcs7-certreqresp' => 'p7r',
        'application/x-rar-compressed' => 'rar',
        'application/x-rar' => 'rar',
        'application/x-research-info-systems' => 'ris',
        'application/x-sh' => 'sh',
        'application/x-shar' => 'shar',
        'application/x-shockwave-flash' => 'swf',
        'application/x-silverlight-app' => 'xap',
        'application/x-sql' => 'sql',
        'application/x-stuffit' => 'sit',
        'application/x-stuffitx' => 'sitx',
        'application/x-subrip' => 'srt',
        'application/x-sv4cpio' => 'sv4cpio',
        'application/x-sv4crc' => 'sv4crc',
        'application/x-t3vm-image' => 't3',
        'application/x-tads' => 'gam',
        'application/x-tar' => 'tar',
        'application/x-tcl' => 'tcl',
        'application/x-tex' => 'tex',
        'application/x-tex-tfm' => 'tfm',
        'application/x-texinfo' => 'texinfo',
        'application/x-tgif' => 'obj',
        'application/x-ustar' => 'ustar',
        'application/x-wais-source' => 'src',
        'application/x-x509-ca-cert' => 'der',
        'application/x-xfig' => 'fig',
        'application/x-xliff+xml' => 'xlf',
        'application/x-xpinstall' => 'xpi',
        'application/x-xz' => 'xz',
        'application/x-zmachine' => 'z1',
        'application/xaml+xml' => 'xaml',
        'application/xcap-diff+xml' => 'xdf',
        'application/xenc+xml' => 'xenc',
        'application/xhtml+xml' => 'xhtml',
        'application/xml' => 'xml',
        'application/xml-dtd' => 'dtd',
        'application/xop+xml' => 'xop',
        'application/xproc+xml' => 'xpl',
        'application/xslt+xml' => 'xslt',
        'application/xspf+xml' => 'xspf',
        'application/xv+xml' => 'mxml',
        'application/yang' => 'yang',
        'application/yin+xml' => 'yin',
        'application/zip' => 'zip',
        'audio/adpcm' => 'adp',
        'audio/basic' => 'au',
        'audio/midi' => 'mid',
        'audio/mp4' => 'mp4a',
        'audio/mpeg' => 'mpga',
        'audio/ogg' => 'oga',
        'audio/s3m' => 's3m',
        'audio/silk' => 'sil',
        'audio/vnd.dece.audio' => 'uva',
        'audio/vnd.digital-winds' => 'eol',
        'audio/vnd.dra' => 'dra',
        'audio/vnd.dts' => 'dts',
        'audio/vnd.dts.hd' => 'dtshd',
        'audio/vnd.lucent.voice' => 'lvp',
        'audio/vnd.ms-playready.media.pya' => 'pya',
        'audio/vnd.nuera.ecelp4800' => 'ecelp4800',
        'audio/vnd.nuera.ecelp7470' => 'ecelp7470',
        'audio/vnd.nuera.ecelp9600' => 'ecelp9600',
        'audio/vnd.rip' => 'rip',
        'audio/webm' => 'weba',
        'audio/x-aac' => 'aac',
        'audio/x-aiff' => 'aif',
        'audio/x-caf' => 'caf',
        'audio/x-flac' => 'flac',
        'audio/x-matroska' => 'mka',
        'audio/x-mpegurl' => 'm3u',
        'audio/x-ms-wax' => 'wax',
        'audio/x-ms-wma' => 'wma',
        'audio/x-pn-realaudio' => 'ram',
        'audio/x-pn-realaudio-plugin' => 'rmp',
        'audio/x-wav' => 'wav',
        'audio/xm' => 'xm',
        'chemical/x-cdx' => 'cdx',
        'chemical/x-cif' => 'cif',
        'chemical/x-cmdf' => 'cmdf',
        'chemical/x-cml' => 'cml',
        'chemical/x-csml' => 'csml',
        'chemical/x-xyz' => 'xyz',
        'image/bmp' => 'bmp',
        'image/cgm' => 'cgm',
        'image/g3fax' => 'g3',
        'image/gif' => 'gif',
        'image/ief' => 'ief',
        'image/jpeg' => 'jpeg',
        'image/ktx' => 'ktx',
        'image/png' => 'png',
        'image/prs.btif' => 'btif',
        'image/sgi' => 'sgi',
        'image/svg+xml' => 'svg',
        'image/tiff' => 'tiff',
        'image/vnd.adobe.photoshop' => 'psd',
        'image/vnd.dece.graphic' => 'uvi',
        'image/vnd.dvb.subtitle' => 'sub',
        'image/vnd.djvu' => 'djvu',
        'image/vnd.dwg' => 'dwg',
        'image/vnd.dxf' => 'dxf',
        'image/vnd.fastbidsheet' => 'fbs',
        'image/vnd.fpx' => 'fpx',
        'image/vnd.fst' => 'fst',
        'image/vnd.fujixerox.edmics-mmr' => 'mmr',
        'image/vnd.fujixerox.edmics-rlc' => 'rlc',
        'image/vnd.ms-modi' => 'mdi',
        'image/vnd.ms-photo' => 'wdp',
        'image/vnd.net-fpx' => 'npx',
        'image/vnd.wap.wbmp' => 'wbmp',
        'image/vnd.xiff' => 'xif',
        'image/webp' => 'webp',
        'image/x-3ds' => '3ds',
        'image/x-cmu-raster' => 'ras',
        'image/x-cmx' => 'cmx',
        'image/x-freehand' => 'fh',
        'image/x-icon' => 'ico',
        'image/x-mrsid-image' => 'sid',
        'image/x-pcx' => 'pcx',
        'image/x-pict' => 'pic',
        'image/x-portable-anymap' => 'pnm',
        'image/x-portable-bitmap' => 'pbm',
        'image/x-portable-graymap' => 'pgm',
        'image/x-portable-pixmap' => 'ppm',
        'image/x-rgb' => 'rgb',
        'image/x-tga' => 'tga',
        'image/x-xbitmap' => 'xbm',
        'image/x-xpixmap' => 'xpm',
        'image/x-xwindowdump' => 'xwd',
        'message/rfc822' => 'eml',
        'model/iges' => 'igs',
        'model/mesh' => 'msh',
        'model/vnd.collada+xml' => 'dae',
        'model/vnd.dwf' => 'dwf',
        'model/vnd.gdl' => 'gdl',
        'model/vnd.gtw' => 'gtw',
        'model/vnd.mts' => 'mts',
        'model/vnd.vtu' => 'vtu',
        'model/vrml' => 'wrl',
        'model/x3d+binary' => 'x3db',
        'model/x3d+vrml' => 'x3dv',
        'model/x3d+xml' => 'x3d',
        'text/cache-manifest' => 'appcache',
        'text/calendar' => 'ics',
        'text/css' => 'css',
        'text/csv' => 'csv',
        'text/html' => 'html',
        'text/n3' => 'n3',
        'text/plain' => 'txt',
        'text/prs.lines.tag' => 'dsc',
        'text/richtext' => 'rtx',
        'text/sgml' => 'sgml',
        'text/tab-separated-values' => 'tsv',
        'text/troff' => 't',
        'text/turtle' => 'ttl',
        'text/uri-list' => 'uri',
        'text/vcard' => 'vcard',
        'text/vnd.curl' => 'curl',
        'text/vnd.curl.dcurl' => 'dcurl',
        'text/vnd.curl.scurl' => 'scurl',
        'text/vnd.curl.mcurl' => 'mcurl',
        'text/vnd.dvb.subtitle' => 'sub',
        'text/vnd.fly' => 'fly',
        'text/vnd.fmi.flexstor' => 'flx',
        'text/vnd.graphviz' => 'gv',
        'text/vnd.in3d.3dml' => '3dml',
        'text/vnd.in3d.spot' => 'spot',
        'text/vnd.sun.j2me.app-descriptor' => 'jad',
        'text/vnd.wap.wml' => 'wml',
        'text/vnd.wap.wmlscript' => 'wmls',
        'text/x-asm' => 's',
        'text/x-c' => 'c',
        'text/x-fortran' => 'f',
        'text/x-pascal' => 'p',
        'text/x-java-source' => 'java',
        'text/x-opml' => 'opml',
        'text/x-nfo' => 'nfo',
        'text/x-setext' => 'etx',
        'text/x-sfv' => 'sfv',
        'text/x-uuencode' => 'uu',
        'text/x-vcalendar' => 'vcs',
        'text/x-vcard' => 'vcf',
        'video/3gpp' => '3gp',
        'video/3gpp2' => '3g2',
        'video/h261' => 'h261',
        'video/h263' => 'h263',
        'video/h264' => 'h264',
        'video/jpeg' => 'jpgv',
        'video/jpm' => 'jpm',
        'video/mj2' => 'mj2',
        'video/mp4' => 'mp4',
        'video/mpeg' => 'mpeg',
        'video/ogg' => 'ogv',
        'video/quicktime' => 'qt',
        'video/vnd.dece.hd' => 'uvh',
        'video/vnd.dece.mobile' => 'uvm',
        'video/vnd.dece.pd' => 'uvp',
        'video/vnd.dece.sd' => 'uvs',
        'video/vnd.dece.video' => 'uvv',
        'video/vnd.dvb.file' => 'dvb',
        'video/vnd.fvt' => 'fvt',
        'video/vnd.mpegurl' => 'mxu',
        'video/vnd.ms-playready.media.pyv' => 'pyv',
        'video/vnd.uvvu.mp4' => 'uvu',
        'video/vnd.vivo' => 'viv',
        'video/webm' => 'webm',
        'video/x-f4v' => 'f4v',
        'video/x-fli' => 'fli',
        'video/x-flv' => 'flv',
        'video/x-m4v' => 'm4v',
        'video/x-matroska' => 'mkv',
        'video/x-mng' => 'mng',
        'video/x-ms-asf' => 'asf',
        'video/x-ms-vob' => 'vob',
        'video/x-ms-wm' => 'wm',
        'video/x-ms-wmv' => 'wmv',
        'video/x-ms-wmx' => 'wmx',
        'video/x-ms-wvx' => 'wvx',
        'video/x-msvideo' => 'avi',
        'video/x-sgi-movie' => 'movie',
        'video/x-smv' => 'smv',
        'x-conference/x-cooltalk' => 'ice',
    );

    /**
     * {@inheritdoc}
     */
    public function guess($mimeType)
    {
        return isset($this->defaultExtensions[$mimeType]) ? $this->defaultExtensions[$mimeType] : null;
    }
}
PK��Z�	�L��KSymfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesserInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\File\MimeType;

use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException;

/**
 * Guesses the mime type of a file
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface MimeTypeGuesserInterface
{
    /**
     * Guesses the mime type of the file with the given path.
     *
     * @param string $path The path to the file
     *
     * @return string         The mime type or NULL, if none could be guessed
     *
     * @throws FileNotFoundException  If the file does not exist
     * @throws AccessDeniedException  If the file could not be read
     */
    public function guess($path);
}
PK��Z�)���.Symfony/Component/HttpFoundation/File/File.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\File;

use Symfony\Component\HttpFoundation\File\Exception\FileException;
use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser;
use Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesser;

/**
 * A file in the file system.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class File extends \SplFileInfo
{
    /**
     * Constructs a new file from the given path.
     *
     * @param string  $path      The path to the file
     * @param Boolean $checkPath Whether to check the path or not
     *
     * @throws FileNotFoundException If the given path is not a file
     *
     * @api
     */
    public function __construct($path, $checkPath = true)
    {
        if ($checkPath && !is_file($path)) {
            throw new FileNotFoundException($path);
        }

        parent::__construct($path);
    }

    /**
     * Returns the extension based on the mime type.
     *
     * If the mime type is unknown, returns null.
     *
     * This method uses the mime type as guessed by getMimeType()
     * to guess the file extension.
     *
     * @return string|null The guessed extension or null if it cannot be guessed
     *
     * @api
     *
     * @see ExtensionGuesser
     * @see getMimeType()
     */
    public function guessExtension()
    {
        $type = $this->getMimeType();
        $guesser = ExtensionGuesser::getInstance();

        return $guesser->guess($type);
    }

    /**
     * Returns the mime type of the file.
     *
     * The mime type is guessed using a MimeTypeGuesser instance, which uses finfo(),
     * mime_content_type() and the system binary "file" (in this order), depending on
     * which of those are available.
     *
     * @return string|null The guessed mime type (i.e. "application/pdf")
     *
     * @see MimeTypeGuesser
     *
     * @api
     */
    public function getMimeType()
    {
        $guesser = MimeTypeGuesser::getInstance();

        return $guesser->guess($this->getPathname());
    }

    /**
     * Returns the extension of the file.
     *
     * \SplFileInfo::getExtension() is not available before PHP 5.3.6
     *
     * @return string The extension
     *
     * @api
     */
    public function getExtension()
    {
        return pathinfo($this->getBasename(), PATHINFO_EXTENSION);
    }

    /**
     * Moves the file to a new location.
     *
     * @param string $directory The destination folder
     * @param string $name      The new file name
     *
     * @return File A File object representing the new file
     *
     * @throws FileException if the target file could not be created
     *
     * @api
     */
    public function move($directory, $name = null)
    {
        $target = $this->getTargetFile($directory, $name);

        if (!@rename($this->getPathname(), $target)) {
            $error = error_get_last();
            throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error['message'])));
        }

        @chmod($target, 0666 & ~umask());

        return $target;
    }

    protected function getTargetFile($directory, $name = null)
    {
        if (!is_dir($directory)) {
            if (false === @mkdir($directory, 0777, true)) {
                throw new FileException(sprintf('Unable to create the "%s" directory', $directory));
            }
        } elseif (!is_writable($directory)) {
            throw new FileException(sprintf('Unable to write in the "%s" directory', $directory));
        }

        $target = rtrim($directory, '/\\').DIRECTORY_SEPARATOR.(null === $name ? $this->getBasename() : $this->getName($name));

        return new File($target, false);
    }

    /**
     * Returns locale independent base name of the given path.
     *
     * @param string $name The new file name
     *
     * @return string containing
     */
    protected function getName($name)
    {
        $originalName = str_replace('\\', '/', $name);
        $pos = strrpos($originalName, '/');
        $originalName = false === $pos ? $originalName : substr($originalName, $pos + 1);

        return $originalName;
    }
}
PK��Z�s�-��ISymfony/Component/HttpFoundation/File/Exception/FileNotFoundException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\File\Exception;

/**
 * Thrown when a file was not found
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class FileNotFoundException extends FileException
{
    /**
     * Constructor.
     *
     * @param string $path The path to the file that was not found
     */
    public function __construct($path)
    {
        parent::__construct(sprintf('The file "%s" does not exist', $path));
    }
}
PK��Z�S��==KSymfony/Component/HttpFoundation/File/Exception/UnexpectedTypeException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\File\Exception;

class UnexpectedTypeException extends FileException
{
    public function __construct($value, $expectedType)
    {
        parent::__construct(sprintf('Expected argument of type %s, %s given', $expectedType, is_object($value) ? get_class($value) : gettype($value)));
    }
}
PK��Z�1�e��ISymfony/Component/HttpFoundation/File/Exception/AccessDeniedException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\File\Exception;

/**
 * Thrown when the access on a file was denied.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class AccessDeniedException extends FileException
{
    /**
     * Constructor.
     *
     * @param string $path The path to the accessed file
     */
    public function __construct($path)
    {
        parent::__construct(sprintf('The file %s could not be accessed', $path));
    }
}
PK��Z�gr��CSymfony/Component/HttpFoundation/File/Exception/UploadException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\File\Exception;

/**
 * Thrown when an error occurred during file upload
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class UploadException extends FileException
{
}
PK��Zo�����ASymfony/Component/HttpFoundation/File/Exception/FileException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\File\Exception;

/**
 * Thrown when an error occurred in the component File
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class FileException extends \RuntimeException
{
}
PK��Z��ގ�#�#6Symfony/Component/HttpFoundation/File/UploadedFile.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\File;

use Symfony\Component\HttpFoundation\File\Exception\FileException;
use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
use Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesser;

/**
 * A file uploaded through a form.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 * @author Florian Eckerstorfer <florian@eckerstorfer.org>
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class UploadedFile extends File
{
    /**
     * Whether the test mode is activated.
     *
     * Local files are used in test mode hence the code should not enforce HTTP uploads.
     *
     * @var Boolean
     */
    private $test = false;

    /**
     * The original name of the uploaded file.
     *
     * @var string
     */
    private $originalName;

    /**
     * The mime type provided by the uploader.
     *
     * @var string
     */
    private $mimeType;

    /**
     * The file size provided by the uploader.
     *
     * @var string
     */
    private $size;

    /**
     * The UPLOAD_ERR_XXX constant provided by the uploader.
     *
     * @var integer
     */
    private $error;

    /**
     * Accepts the information of the uploaded file as provided by the PHP global $_FILES.
     *
     * The file object is only created when the uploaded file is valid (i.e. when the
     * isValid() method returns true). Otherwise the only methods that could be called
     * on an UploadedFile instance are:
     *
     *   * getClientOriginalName,
     *   * getClientMimeType,
     *   * isValid,
     *   * getError.
     *
     * Calling any other method on an non-valid instance will cause an unpredictable result.
     *
     * @param string  $path         The full temporary path to the file
     * @param string  $originalName The original file name
     * @param string  $mimeType     The type of the file as provided by PHP
     * @param integer $size         The file size
     * @param integer $error        The error constant of the upload (one of PHP's UPLOAD_ERR_XXX constants)
     * @param Boolean $test         Whether the test mode is active
     *
     * @throws FileException         If file_uploads is disabled
     * @throws FileNotFoundException If the file does not exist
     *
     * @api
     */
    public function __construct($path, $originalName, $mimeType = null, $size = null, $error = null, $test = false)
    {
        $this->originalName = $this->getName($originalName);
        $this->mimeType = $mimeType ?: 'application/octet-stream';
        $this->size = $size;
        $this->error = $error ?: UPLOAD_ERR_OK;
        $this->test = (Boolean) $test;

        parent::__construct($path, UPLOAD_ERR_OK === $this->error);
    }

    /**
     * Returns the original file name.
     *
     * It is extracted from the request from which the file has been uploaded.
     * Then it should not be considered as a safe value.
     *
     * @return string|null The original name
     *
     * @api
     */
    public function getClientOriginalName()
    {
        return $this->originalName;
    }

    /**
     * Returns the original file extension
     *
     * It is extracted from the original file name that was uploaded.
     * Then it should not be considered as a safe value.
     *
     * @return string The extension
     */
    public function getClientOriginalExtension()
    {
        return pathinfo($this->originalName, PATHINFO_EXTENSION);
    }

    /**
     * Returns the file mime type.
     *
     * The client mime type is extracted from the request from which the file
     * was uploaded, so it should not be considered as a safe value.
     *
     * For a trusted mime type, use getMimeType() instead (which guesses the mime
     * type based on the file content).
     *
     * @return string|null The mime type
     *
     * @see getMimeType
     *
     * @api
     */
    public function getClientMimeType()
    {
        return $this->mimeType;
    }

    /**
     * Returns the extension based on the client mime type.
     *
     * If the mime type is unknown, returns null.
     *
     * This method uses the mime type as guessed by getClientMimeType()
     * to guess the file extension. As such, the extension returned
     * by this method cannot be trusted.
     *
     * For a trusted extension, use guessExtension() instead (which guesses
     * the extension based on the guessed mime type for the file).
     *
     * @return string|null The guessed extension or null if it cannot be guessed
     *
     * @see guessExtension()
     * @see getClientMimeType()
     */
    public function guessClientExtension()
    {
        $type = $this->getClientMimeType();
        $guesser = ExtensionGuesser::getInstance();

        return $guesser->guess($type);
    }

    /**
     * Returns the file size.
     *
     * It is extracted from the request from which the file has been uploaded.
     * Then it should not be considered as a safe value.
     *
     * @return integer|null The file size
     *
     * @api
     */
    public function getClientSize()
    {
        return $this->size;
    }

    /**
     * Returns the upload error.
     *
     * If the upload was successful, the constant UPLOAD_ERR_OK is returned.
     * Otherwise one of the other UPLOAD_ERR_XXX constants is returned.
     *
     * @return integer The upload error
     *
     * @api
     */
    public function getError()
    {
        return $this->error;
    }

    /**
     * Returns whether the file was uploaded successfully.
     *
     * @return Boolean True if the file has been uploaded with HTTP and no error occurred.
     *
     * @api
     */
    public function isValid()
    {
        $isOk = $this->error === UPLOAD_ERR_OK;

        return $this->test ? $isOk : $isOk && is_uploaded_file($this->getPathname());
    }

    /**
     * Moves the file to a new location.
     *
     * @param string $directory The destination folder
     * @param string $name      The new file name
     *
     * @return File A File object representing the new file
     *
     * @throws FileException if, for any reason, the file could not have been moved
     *
     * @api
     */
    public function move($directory, $name = null)
    {
        if ($this->isValid()) {
            if ($this->test) {
                return parent::move($directory, $name);
            }

            $target = $this->getTargetFile($directory, $name);

            if (!@move_uploaded_file($this->getPathname(), $target)) {
                $error = error_get_last();
                throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error['message'])));
            }

            @chmod($target, 0666 & ~umask());

            return $target;
        }

        throw new FileException($this->getErrorMessage());
    }

    /**
     * Returns the maximum size of an uploaded file as configured in php.ini
     *
     * @return int The maximum size of an uploaded file in bytes
     */
    public static function getMaxFilesize()
    {
        $iniMax = strtolower(ini_get('upload_max_filesize'));

        if ('' === $iniMax) {
            return PHP_INT_MAX;
        }

        $max = ltrim($iniMax, '+');
        if (0 === strpos($max, '0x')) {
            $max = intval($max, 16);
        } elseif (0 === strpos($max, '0')) {
            $max = intval($max, 8);
        } else {
            $max = intval($max);
        }

        switch (substr($iniMax, -1)) {
            case 't': $max *= 1024;
            case 'g': $max *= 1024;
            case 'm': $max *= 1024;
            case 'k': $max *= 1024;
        }

        return $max;
    }

    /**
     * Returns an informative upload error message.
     *
     * @return string The error message regarding the specified error code
     */
    public function getErrorMessage()
    {
        static $errors = array(
            UPLOAD_ERR_INI_SIZE   => 'The file "%s" exceeds your upload_max_filesize ini directive (limit is %d kb).',
            UPLOAD_ERR_FORM_SIZE  => 'The file "%s" exceeds the upload limit defined in your form.',
            UPLOAD_ERR_PARTIAL    => 'The file "%s" was only partially uploaded.',
            UPLOAD_ERR_NO_FILE    => 'No file was uploaded.',
            UPLOAD_ERR_CANT_WRITE => 'The file "%s" could not be written on disk.',
            UPLOAD_ERR_NO_TMP_DIR => 'File could not be uploaded: missing temporary directory.',
            UPLOAD_ERR_EXTENSION  => 'File upload was stopped by a PHP extension.',
        );

        $errorCode = $this->error;
        $maxFilesize = $errorCode === UPLOAD_ERR_INI_SIZE ? self::getMaxFilesize() / 1024 : 0;
        $message = isset($errors[$errorCode]) ? $errors[$errorCode] : 'The file "%s" was not uploaded due to an unknown error.';

        return sprintf($message, $this->getClientOriginalName(), $maxFilesize);
    }
}
PK��Z�7�E	E	1Symfony/Component/HttpFoundation/RequestStack.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation;

/**
 * Request stack that controls the lifecycle of requests.
 *
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 */
class RequestStack
{
    /**
     * @var Request[]
     */
    private $requests = array();

    /**
     * Pushes a Request on the stack.
     *
     * This method should generally not be called directly as the stack
     * management should be taken care of by the application itself.
     */
    public function push(Request $request)
    {
        $this->requests[] = $request;
    }

    /**
     * Pops the current request from the stack.
     *
     * This operation lets the current request go out of scope.
     *
     * This method should generally not be called directly as the stack
     * management should be taken care of by the application itself.
     *
     * @return Request|null
     */
    public function pop()
    {
        if (!$this->requests) {
            return null;
        }

        return array_pop($this->requests);
    }

    /**
     * @return Request|null
     */
    public function getCurrentRequest()
    {
        return end($this->requests) ?: null;
    }

    /**
     * Gets the master Request.
     *
     * Be warned that making your code aware of the master request
     * might make it un-compatible with other features of your framework
     * like ESI support.
     *
     * @return Request|null
     */
    public function getMasterRequest()
    {
        if (!$this->requests) {
            return null;
        }

        return $this->requests[0];
    }

    /**
     * Returns the parent request of the current.
     *
     * Be warned that making your code aware of the parent request
     * might make it un-compatible with other features of your framework
     * like ESI support.
     *
     * If current Request is the master request, it returns null.
     *
     * @return Request|null
     */
    public function getParentRequest()
    {
        $pos = count($this->requests) - 2;

        if (!isset($this->requests[$pos])) {
            return null;
        }

        return $this->requests[$pos];
    }
}
PK��Z��W���;Symfony/Component/HttpFoundation/Session/Flash/FlashBag.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Session\Flash;

/**
 * FlashBag flash message container.
 *
 * \IteratorAggregate implementation is deprecated and will be removed in 3.0.
 *
 * @author Drak <drak@zikula.org>
 */
class FlashBag implements FlashBagInterface, \IteratorAggregate
{
    private $name = 'flashes';

    /**
     * Flash messages.
     *
     * @var array
     */
    private $flashes = array();

    /**
     * The storage key for flashes in the session
     *
     * @var string
     */
    private $storageKey;

    /**
     * Constructor.
     *
     * @param string $storageKey The key used to store flashes in the session.
     */
    public function __construct($storageKey = '_sf2_flashes')
    {
        $this->storageKey = $storageKey;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return $this->name;
    }

    public function setName($name)
    {
        $this->name = $name;
    }

    /**
     * {@inheritdoc}
     */
    public function initialize(array &$flashes)
    {
        $this->flashes = &$flashes;
    }

    /**
     * {@inheritdoc}
     */
    public function add($type, $message)
    {
        $this->flashes[$type][] = $message;
    }

    /**
     * {@inheritdoc}
     */
    public function peek($type, array $default = array())
    {
        return $this->has($type) ? $this->flashes[$type] : $default;
    }

    /**
     * {@inheritdoc}
     */
    public function peekAll()
    {
        return $this->flashes;
    }

    /**
     * {@inheritdoc}
     */
    public function get($type, array $default = array())
    {
        if (!$this->has($type)) {
            return $default;
        }

        $return = $this->flashes[$type];

        unset($this->flashes[$type]);

        return $return;
    }

    /**
     * {@inheritdoc}
     */
    public function all()
    {
        $return = $this->peekAll();
        $this->flashes = array();

        return $return;
    }

    /**
     * {@inheritdoc}
     */
    public function set($type, $messages)
    {
        $this->flashes[$type] = (array) $messages;
    }

    /**
     * {@inheritdoc}
     */
    public function setAll(array $messages)
    {
        $this->flashes = $messages;
    }

    /**
     * {@inheritdoc}
     */
    public function has($type)
    {
        return array_key_exists($type, $this->flashes) && $this->flashes[$type];
    }

    /**
     * {@inheritdoc}
     */
    public function keys()
    {
        return array_keys($this->flashes);
    }

    /**
     * {@inheritdoc}
     */
    public function getStorageKey()
    {
        return $this->storageKey;
    }

    /**
     * {@inheritdoc}
     */
    public function clear()
    {
        return $this->all();
    }

    /**
     * Returns an iterator for flashes.
     *
     * @deprecated Will be removed in 3.0.
     *
     * @return \ArrayIterator An \ArrayIterator instance
     */
    public function getIterator()
    {
        return new \ArrayIterator($this->all());
    }
}
PK��Z�@��WWESymfony/Component/HttpFoundation/Session/Flash/AutoExpireFlashBag.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Session\Flash;

/**
 * AutoExpireFlashBag flash message container.
 *
 * @author Drak <drak@zikula.org>
 */
class AutoExpireFlashBag implements FlashBagInterface
{
    private $name = 'flashes';

    /**
     * Flash messages.
     *
     * @var array
     */
    private $flashes = array('display' => array(), 'new' => array());

    /**
     * The storage key for flashes in the session
     *
     * @var string
     */
    private $storageKey;

    /**
     * Constructor.
     *
     * @param string $storageKey The key used to store flashes in the session.
     */
    public function __construct($storageKey = '_sf2_flashes')
    {
        $this->storageKey = $storageKey;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return $this->name;
    }

    public function setName($name)
    {
        $this->name = $name;
    }

    /**
     * {@inheritdoc}
     */
    public function initialize(array &$flashes)
    {
        $this->flashes = &$flashes;

        // The logic: messages from the last request will be stored in new, so we move them to previous
        // This request we will show what is in 'display'.  What is placed into 'new' this time round will
        // be moved to display next time round.
        $this->flashes['display'] = array_key_exists('new', $this->flashes) ? $this->flashes['new'] : array();
        $this->flashes['new'] = array();
    }

    /**
     * {@inheritdoc}
     */
    public function add($type, $message)
    {
        $this->flashes['new'][$type][] = $message;
    }

    /**
     * {@inheritdoc}
     */
    public function peek($type, array $default = array())
    {
        return $this->has($type) ? $this->flashes['display'][$type] : $default;
    }

    /**
     * {@inheritdoc}
     */
    public function peekAll()
    {
        return array_key_exists('display', $this->flashes) ? (array) $this->flashes['display'] : array();
    }

    /**
     * {@inheritdoc}
     */
    public function get($type, array $default = array())
    {
        $return = $default;

        if (!$this->has($type)) {
            return $return;
        }

        if (isset($this->flashes['display'][$type])) {
            $return = $this->flashes['display'][$type];
            unset($this->flashes['display'][$type]);
        }

        return $return;
    }

    /**
     * {@inheritdoc}
     */
    public function all()
    {
        $return = $this->flashes['display'];
        $this->flashes = array('new' => array(), 'display' => array());

        return $return;
    }

    /**
     * {@inheritdoc}
     */
    public function setAll(array $messages)
    {
        $this->flashes['new'] = $messages;
    }

    /**
     * {@inheritdoc}
     */
    public function set($type, $messages)
    {
        $this->flashes['new'][$type] = (array) $messages;
    }

    /**
     * {@inheritdoc}
     */
    public function has($type)
    {
        return array_key_exists($type, $this->flashes['display']) && $this->flashes['display'][$type];
    }

    /**
     * {@inheritdoc}
     */
    public function keys()
    {
        return array_keys($this->flashes['display']);
    }

    /**
     * {@inheritdoc}
     */
    public function getStorageKey()
    {
        return $this->storageKey;
    }

    /**
     * {@inheritdoc}
     */
    public function clear()
    {
        return $this->all();
    }
}
PK��Za����DSymfony/Component/HttpFoundation/Session/Flash/FlashBagInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Session\Flash;

use Symfony\Component\HttpFoundation\Session\SessionBagInterface;

/**
 * FlashBagInterface.
 *
 * @author Drak <drak@zikula.org>
 */
interface FlashBagInterface extends SessionBagInterface
{
    /**
     * Adds a flash message for type.
     *
     * @param string $type
     * @param string $message
     */
    public function add($type, $message);

    /**
     * Registers a message for a given type.
     *
     * @param string       $type
     * @param string|array $message
     */
    public function set($type, $message);

    /**
     * Gets flash messages for a given type.
     *
     * @param string $type    Message category type.
     * @param array  $default Default value if $type does not exist.
     *
     * @return array
     */
    public function peek($type, array $default = array());

    /**
     * Gets all flash messages.
     *
     * @return array
     */
    public function peekAll();

    /**
     * Gets and clears flash from the stack.
     *
     * @param string $type
     * @param array  $default Default value if $type does not exist.
     *
     * @return array
     */
    public function get($type, array $default = array());

    /**
     * Gets and clears flashes from the stack.
     *
     * @return array
     */
    public function all();

    /**
     * Sets all flash messages.
     */
    public function setAll(array $messages);

    /**
     * Has flash messages for a given type?
     *
     * @param string $type
     *
     * @return boolean
     */
    public function has($type);

    /**
     * Returns a list of all defined types.
     *
     * @return array
     */
    public function keys();
}
PK��Z�=�\\=Symfony/Component/HttpFoundation/Session/SessionInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Session;

use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag;

/**
 * Interface for the session.
 *
 * @author Drak <drak@zikula.org>
 */
interface SessionInterface
{
    /**
     * Starts the session storage.
     *
     * @return Boolean True if session started.
     *
     * @throws \RuntimeException If session fails to start.
     *
     * @api
     */
    public function start();

    /**
     * Returns the session ID.
     *
     * @return string The session ID.
     *
     * @api
     */
    public function getId();

    /**
     * Sets the session ID
     *
     * @param string $id
     *
     * @api
     */
    public function setId($id);

    /**
     * Returns the session name.
     *
     * @return mixed The session name.
     *
     * @api
     */
    public function getName();

    /**
     * Sets the session name.
     *
     * @param string $name
     *
     * @api
     */
    public function setName($name);

    /**
     * Invalidates the current session.
     *
     * Clears all session attributes and flashes and regenerates the
     * session and deletes the old session from persistence.
     *
     * @param integer $lifetime Sets the cookie lifetime for the session cookie. A null value
     *                          will leave the system settings unchanged, 0 sets the cookie
     *                          to expire with browser session. Time is in seconds, and is
     *                          not a Unix timestamp.
     *
     * @return Boolean True if session invalidated, false if error.
     *
     * @api
     */
    public function invalidate($lifetime = null);

    /**
     * Migrates the current session to a new session id while maintaining all
     * session attributes.
     *
     * @param Boolean $destroy  Whether to delete the old session or leave it to garbage collection.
     * @param integer $lifetime Sets the cookie lifetime for the session cookie. A null value
     *                          will leave the system settings unchanged, 0 sets the cookie
     *                          to expire with browser session. Time is in seconds, and is
     *                          not a Unix timestamp.
     *
     * @return Boolean True if session migrated, false if error.
     *
     * @api
     */
    public function migrate($destroy = false, $lifetime = null);

    /**
     * Force the session to be saved and closed.
     *
     * This method is generally not required for real sessions as
     * the session will be automatically saved at the end of
     * code execution.
     */
    public function save();

    /**
     * Checks if an attribute is defined.
     *
     * @param string $name The attribute name
     *
     * @return Boolean true if the attribute is defined, false otherwise
     *
     * @api
     */
    public function has($name);

    /**
     * Returns an attribute.
     *
     * @param string $name    The attribute name
     * @param mixed  $default The default value if not found.
     *
     * @return mixed
     *
     * @api
     */
    public function get($name, $default = null);

    /**
     * Sets an attribute.
     *
     * @param string $name
     * @param mixed  $value
     *
     * @api
     */
    public function set($name, $value);

    /**
     * Returns attributes.
     *
     * @return array Attributes
     *
     * @api
     */
    public function all();

    /**
     * Sets attributes.
     *
     * @param array $attributes Attributes
     */
    public function replace(array $attributes);

    /**
     * Removes an attribute.
     *
     * @param string $name
     *
     * @return mixed The removed value or null when it does not exist
     *
     * @api
     */
    public function remove($name);

    /**
     * Clears all attributes.
     *
     * @api
     */
    public function clear();

    /**
     * Checks if the session was started.
     *
     * @return Boolean
     */
    public function isStarted();

    /**
     * Registers a SessionBagInterface with the session.
     *
     * @param SessionBagInterface $bag
     */
    public function registerBag(SessionBagInterface $bag);

    /**
     * Gets a bag instance by name.
     *
     * @param string $name
     *
     * @return SessionBagInterface
     */
    public function getBag($name);

    /**
     * Gets session meta.
     *
     * @return MetadataBag
     */
    public function getMetadataBag();
}
PK��Z�:au774Symfony/Component/HttpFoundation/Session/Session.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Session;

use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface;
use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag;
use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface;
use Symfony\Component\HttpFoundation\Session\Flash\FlashBag;
use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;

/**
 * Session.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Drak <drak@zikula.org>
 *
 * @api
 */
class Session implements SessionInterface, \IteratorAggregate, \Countable
{
    /**
     * Storage driver.
     *
     * @var SessionStorageInterface
     */
    protected $storage;

    /**
     * @var string
     */
    private $flashName;

    /**
     * @var string
     */
    private $attributeName;

    /**
     * Constructor.
     *
     * @param SessionStorageInterface $storage    A SessionStorageInterface instance.
     * @param AttributeBagInterface   $attributes An AttributeBagInterface instance, (defaults null for default AttributeBag)
     * @param FlashBagInterface       $flashes    A FlashBagInterface instance (defaults null for default FlashBag)
     */
    public function __construct(SessionStorageInterface $storage = null, AttributeBagInterface $attributes = null, FlashBagInterface $flashes = null)
    {
        $this->storage = $storage ?: new NativeSessionStorage();

        $attributes = $attributes ?: new AttributeBag();
        $this->attributeName = $attributes->getName();
        $this->registerBag($attributes);

        $flashes = $flashes ?: new FlashBag();
        $this->flashName = $flashes->getName();
        $this->registerBag($flashes);
    }

    /**
     * {@inheritdoc}
     */
    public function start()
    {
        return $this->storage->start();
    }

    /**
     * {@inheritdoc}
     */
    public function has($name)
    {
        return $this->storage->getBag($this->attributeName)->has($name);
    }

    /**
     * {@inheritdoc}
     */
    public function get($name, $default = null)
    {
        return $this->storage->getBag($this->attributeName)->get($name, $default);
    }

    /**
     * {@inheritdoc}
     */
    public function set($name, $value)
    {
        $this->storage->getBag($this->attributeName)->set($name, $value);
    }

    /**
     * {@inheritdoc}
     */
    public function all()
    {
        return $this->storage->getBag($this->attributeName)->all();
    }

    /**
     * {@inheritdoc}
     */
    public function replace(array $attributes)
    {
        $this->storage->getBag($this->attributeName)->replace($attributes);
    }

    /**
     * {@inheritdoc}
     */
    public function remove($name)
    {
        return $this->storage->getBag($this->attributeName)->remove($name);
    }

    /**
     * {@inheritdoc}
     */
    public function clear()
    {
        $this->storage->getBag($this->attributeName)->clear();
    }

    /**
     * {@inheritdoc}
     */
    public function isStarted()
    {
        return $this->storage->isStarted();
    }

    /**
     * Returns an iterator for attributes.
     *
     * @return \ArrayIterator An \ArrayIterator instance
     */
    public function getIterator()
    {
        return new \ArrayIterator($this->storage->getBag($this->attributeName)->all());
    }

    /**
     * Returns the number of attributes.
     *
     * @return int The number of attributes
     */
    public function count()
    {
        return count($this->storage->getBag($this->attributeName)->all());
    }

    /**
     * {@inheritdoc}
     */
    public function invalidate($lifetime = null)
    {
        $this->storage->clear();

        return $this->migrate(true, $lifetime);
    }

    /**
     * {@inheritdoc}
     */
    public function migrate($destroy = false, $lifetime = null)
    {
        return $this->storage->regenerate($destroy, $lifetime);
    }

    /**
     * {@inheritdoc}
     */
    public function save()
    {
        $this->storage->save();
    }

    /**
     * {@inheritdoc}
     */
    public function getId()
    {
        return $this->storage->getId();
    }

    /**
     * {@inheritdoc}
     */
    public function setId($id)
    {
        $this->storage->setId($id);
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return $this->storage->getName();
    }

    /**
     * {@inheritdoc}
     */
    public function setName($name)
    {
        $this->storage->setName($name);
    }

    /**
     * {@inheritdoc}
     */
    public function getMetadataBag()
    {
        return $this->storage->getMetadataBag();
    }

    /**
     * {@inheritdoc}
     */
    public function registerBag(SessionBagInterface $bag)
    {
        $this->storage->registerBag($bag);
    }

    /**
     * {@inheritdoc}
     */
    public function getBag($name)
    {
        return $this->storage->getBag($name);
    }

    /**
     * Gets the flashbag interface.
     *
     * @return FlashBagInterface
     */
    public function getFlashBag()
    {
        return $this->getBag($this->flashName);
    }
}
PK��ZM&z�rr@Symfony/Component/HttpFoundation/Session/SessionBagInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Session;

/**
 * Session Bag store.
 *
 * @author Drak <drak@zikula.org>
 */
interface SessionBagInterface
{
    /**
     * Gets this bag's name
     *
     * @return string
     */
    public function getName();

    /**
     * Initializes the Bag
     *
     * @param array $array
     */
    public function initialize(array &$array);

    /**
     * Gets the storage key for this bag.
     *
     * @return string
     */
    public function getStorageKey();

    /**
     * Clears out data from bag.
     *
     * @return mixed Whatever data was contained.
     */
    public function clear();
}
PK��Z��eLSymfony/Component/HttpFoundation/Session/Attribute/AttributeBagInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Session\Attribute;

use Symfony\Component\HttpFoundation\Session\SessionBagInterface;

/**
 * Attributes store.
 *
 * @author Drak <drak@zikula.org>
 */
interface AttributeBagInterface extends SessionBagInterface
{
    /**
     * Checks if an attribute is defined.
     *
     * @param string $name The attribute name
     *
     * @return Boolean true if the attribute is defined, false otherwise
     */
    public function has($name);

    /**
     * Returns an attribute.
     *
     * @param string $name    The attribute name
     * @param mixed  $default The default value if not found
     *
     * @return mixed
     */
    public function get($name, $default = null);

    /**
     * Sets an attribute.
     *
     * @param string $name
     * @param mixed  $value
     */
    public function set($name, $value);

    /**
     * Returns attributes.
     *
     * @return array Attributes
     */
    public function all();

    /**
     * Sets attributes.
     *
     * @param array $attributes Attributes
     */
    public function replace(array $attributes);

    /**
     * Removes an attribute.
     *
     * @param string $name
     *
     * @return mixed The removed value or null when it does not exist
     */
    public function remove($name);
}
PK��Z��(���CSymfony/Component/HttpFoundation/Session/Attribute/AttributeBag.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Session\Attribute;

/**
 * This class relates to session attribute storage
 */
class AttributeBag implements AttributeBagInterface, \IteratorAggregate, \Countable
{
    private $name = 'attributes';

    /**
     * @var string
     */
    private $storageKey;

    /**
     * @var array
     */
    protected $attributes = array();

    /**
     * Constructor.
     *
     * @param string $storageKey The key used to store attributes in the session
     */
    public function __construct($storageKey = '_sf2_attributes')
    {
        $this->storageKey = $storageKey;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return $this->name;
    }

    public function setName($name)
    {
        $this->name = $name;
    }

    /**
     * {@inheritdoc}
     */
    public function initialize(array &$attributes)
    {
        $this->attributes = &$attributes;
    }

    /**
     * {@inheritdoc}
     */
    public function getStorageKey()
    {
        return $this->storageKey;
    }

    /**
     * {@inheritdoc}
     */
    public function has($name)
    {
        return array_key_exists($name, $this->attributes);
    }

    /**
     * {@inheritdoc}
     */
    public function get($name, $default = null)
    {
        return array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default;
    }

    /**
     * {@inheritdoc}
     */
    public function set($name, $value)
    {
        $this->attributes[$name] = $value;
    }

    /**
     * {@inheritdoc}
     */
    public function all()
    {
        return $this->attributes;
    }

    /**
     * {@inheritdoc}
     */
    public function replace(array $attributes)
    {
        $this->attributes = array();
        foreach ($attributes as $key => $value) {
            $this->set($key, $value);
        }
    }

    /**
     * {@inheritdoc}
     */
    public function remove($name)
    {
        $retval = null;
        if (array_key_exists($name, $this->attributes)) {
            $retval = $this->attributes[$name];
            unset($this->attributes[$name]);
        }

        return $retval;
    }

    /**
     * {@inheritdoc}
     */
    public function clear()
    {
        $return = $this->attributes;
        $this->attributes = array();

        return $return;
    }

    /**
     * Returns an iterator for attributes.
     *
     * @return \ArrayIterator An \ArrayIterator instance
     */
    public function getIterator()
    {
        return new \ArrayIterator($this->attributes);
    }

    /**
     * Returns the number of attributes.
     *
     * @return integer The number of attributes
     */
    public function count()
    {
        return count($this->attributes);
    }
}
PK��Z�0�H66MSymfony/Component/HttpFoundation/Session/Attribute/NamespacedAttributeBag.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Session\Attribute;

/**
 * This class provides structured storage of session attributes using
 * a name spacing character in the key.
 *
 * @author Drak <drak@zikula.org>
 */
class NamespacedAttributeBag extends AttributeBag
{
    /**
     * Namespace character.
     *
     * @var string
     */
    private $namespaceCharacter;

    /**
     * Constructor.
     *
     * @param string $storageKey         Session storage key.
     * @param string $namespaceCharacter Namespace character to use in keys.
     */
    public function __construct($storageKey = '_sf2_attributes', $namespaceCharacter = '/')
    {
        $this->namespaceCharacter = $namespaceCharacter;
        parent::__construct($storageKey);
    }

    /**
     * {@inheritdoc}
     */
    public function has($name)
    {
        $attributes = $this->resolveAttributePath($name);
        $name = $this->resolveKey($name);

        if (null === $attributes) {
            return false;
        }

        return array_key_exists($name, $attributes);
    }

    /**
     * {@inheritdoc}
     */
    public function get($name, $default = null)
    {
        $attributes = $this->resolveAttributePath($name);
        $name = $this->resolveKey($name);

        if (null === $attributes) {
            return $default;
        }

        return array_key_exists($name, $attributes) ? $attributes[$name] : $default;
    }

    /**
     * {@inheritdoc}
     */
    public function set($name, $value)
    {
        $attributes = & $this->resolveAttributePath($name, true);
        $name = $this->resolveKey($name);
        $attributes[$name] = $value;
    }

    /**
     * {@inheritdoc}
     */
    public function remove($name)
    {
        $retval = null;
        $attributes = & $this->resolveAttributePath($name);
        $name = $this->resolveKey($name);
        if (null !== $attributes && array_key_exists($name, $attributes)) {
            $retval = $attributes[$name];
            unset($attributes[$name]);
        }

        return $retval;
    }

    /**
     * Resolves a path in attributes property and returns it as a reference.
     *
     * This method allows structured namespacing of session attributes.
     *
     * @param string  $name         Key name
     * @param boolean $writeContext Write context, default false
     *
     * @return array
     */
    protected function &resolveAttributePath($name, $writeContext = false)
    {
        $array = & $this->attributes;
        $name = (strpos($name, $this->namespaceCharacter) === 0) ? substr($name, 1) : $name;

        // Check if there is anything to do, else return
        if (!$name) {
            return $array;
        }

        $parts = explode($this->namespaceCharacter, $name);
        if (count($parts) < 2) {
            if (!$writeContext) {
                return $array;
            }

            $array[$parts[0]] = array();

            return $array;
        }

        unset($parts[count($parts)-1]);

        foreach ($parts as $part) {
            if (null !== $array && !array_key_exists($part, $array)) {
                $array[$part] = $writeContext ? array() : null;
            }

            $array = & $array[$part];
        }

        return $array;
    }

    /**
     * Resolves the key from the name.
     *
     * This is the last part in a dot separated string.
     *
     * @param string $name
     *
     * @return string
     */
    protected function resolveKey($name)
    {
        if (false !== $pos = strrpos($name, $this->namespaceCharacter)) {
            $name = substr($name, $pos+1);
        }

        return $name;
    }
}
PK��Z�t�3�3ISymfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Session\Storage;

use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler;
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy;
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy;

/**
 * This provides a base class for session attribute storage.
 *
 * @author Drak <drak@zikula.org>
 */
class NativeSessionStorage implements SessionStorageInterface
{
    /**
     * Array of SessionBagInterface
     *
     * @var SessionBagInterface[]
     */
    protected $bags;

    /**
     * @var Boolean
     */
    protected $started = false;

    /**
     * @var Boolean
     */
    protected $closed = false;

    /**
     * @var AbstractProxy
     */
    protected $saveHandler;

    /**
     * @var MetadataBag
     */
    protected $metadataBag;

    /**
     * Constructor.
     *
     * Depending on how you want the storage driver to behave you probably
     * want to override this constructor entirely.
     *
     * List of options for $options array with their defaults.
     * @see http://php.net/session.configuration for options
     * but we omit 'session.' from the beginning of the keys for convenience.
     *
     * ("auto_start", is not supported as it tells PHP to start a session before
     * PHP starts to execute user-land code. Setting during runtime has no effect).
     *
     * cache_limiter, "nocache" (use "0" to prevent headers from being sent entirely).
     * cookie_domain, ""
     * cookie_httponly, ""
     * cookie_lifetime, "0"
     * cookie_path, "/"
     * cookie_secure, ""
     * entropy_file, ""
     * entropy_length, "0"
     * gc_divisor, "100"
     * gc_maxlifetime, "1440"
     * gc_probability, "1"
     * hash_bits_per_character, "4"
     * hash_function, "0"
     * name, "PHPSESSID"
     * referer_check, ""
     * serialize_handler, "php"
     * use_cookies, "1"
     * use_only_cookies, "1"
     * use_trans_sid, "0"
     * upload_progress.enabled, "1"
     * upload_progress.cleanup, "1"
     * upload_progress.prefix, "upload_progress_"
     * upload_progress.name, "PHP_SESSION_UPLOAD_PROGRESS"
     * upload_progress.freq, "1%"
     * upload_progress.min-freq, "1"
     * url_rewriter.tags, "a=href,area=href,frame=src,form=,fieldset="
     *
     * @param array                                                            $options Session configuration options.
     * @param AbstractProxy|NativeSessionHandler|\SessionHandlerInterface|null $handler
     * @param MetadataBag                                                      $metaBag MetadataBag.
     */
    public function __construct(array $options = array(), $handler = null, MetadataBag $metaBag = null)
    {
        session_cache_limiter(''); // disable by default because it's managed by HeaderBag (if used)
        ini_set('session.use_cookies', 1);

        if (version_compare(phpversion(), '5.4.0', '>=')) {
            session_register_shutdown();
        } else {
            register_shutdown_function('session_write_close');
        }

        $this->setMetadataBag($metaBag);
        $this->setOptions($options);
        $this->setSaveHandler($handler);
    }

    /**
     * Gets the save handler instance.
     *
     * @return AbstractProxy
     */
    public function getSaveHandler()
    {
        return $this->saveHandler;
    }

    /**
     * {@inheritdoc}
     */
    public function start()
    {
        if ($this->started && !$this->closed) {
            return true;
        }

        if (version_compare(phpversion(), '5.4.0', '>=') && \PHP_SESSION_ACTIVE === session_status()) {
            throw new \RuntimeException('Failed to start the session: already started by PHP.');
        }

        if (version_compare(phpversion(), '5.4.0', '<') && isset($_SESSION) && session_id()) {
            // not 100% fool-proof, but is the most reliable way to determine if a session is active in PHP 5.3
            throw new \RuntimeException('Failed to start the session: already started by PHP ($_SESSION is set).');
        }

        if (ini_get('session.use_cookies') && headers_sent($file, $line)) {
            throw new \RuntimeException(sprintf('Failed to start the session because headers have already been sent by "%s" at line %d.', $file, $line));
        }

        // ok to try and start the session
        if (!session_start()) {
            throw new \RuntimeException('Failed to start the session');
        }

        $this->loadSession();
        if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) {
            // This condition matches only PHP 5.3 with internal save handlers
            $this->saveHandler->setActive(true);
        }

        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function getId()
    {
        if (!$this->started && !$this->closed) {
            return ''; // returning empty is consistent with session_id() behaviour
        }

        return $this->saveHandler->getId();
    }

    /**
     * {@inheritdoc}
     */
    public function setId($id)
    {
        $this->saveHandler->setId($id);
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return $this->saveHandler->getName();
    }

    /**
     * {@inheritdoc}
     */
    public function setName($name)
    {
        $this->saveHandler->setName($name);
    }

    /**
     * {@inheritdoc}
     */
    public function regenerate($destroy = false, $lifetime = null)
    {
        if (null !== $lifetime) {
            ini_set('session.cookie_lifetime', $lifetime);
        }

        if ($destroy) {
            $this->metadataBag->stampNew();
        }

        $ret = session_regenerate_id($destroy);

        // workaround for https://bugs.php.net/bug.php?id=61470 as suggested by David Grudl
        if ('files' === $this->getSaveHandler()->getSaveHandlerName()) {
            session_write_close();
            if (isset($_SESSION)) {
                $backup = $_SESSION;
                session_start();
                $_SESSION = $backup;
            } else {
                session_start();
            }

            $this->loadSession();
        }

        return $ret;
    }

    /**
     * {@inheritdoc}
     */
    public function save()
    {
        session_write_close();

        if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) {
            // This condition matches only PHP 5.3 with internal save handlers
            $this->saveHandler->setActive(false);
        }

        $this->closed = true;
        $this->started = false;
    }

    /**
     * {@inheritdoc}
     */
    public function clear()
    {
        // clear out the bags
        foreach ($this->bags as $bag) {
            $bag->clear();
        }

        // clear out the session
        $_SESSION = array();

        // reconnect the bags to the session
        $this->loadSession();
    }

    /**
     * {@inheritdoc}
     */
    public function registerBag(SessionBagInterface $bag)
    {
        $this->bags[$bag->getName()] = $bag;
    }

    /**
     * {@inheritdoc}
     */
    public function getBag($name)
    {
        if (!isset($this->bags[$name])) {
            throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name));
        }

        if ($this->saveHandler->isActive() && !$this->started) {
            $this->loadSession();
        } elseif (!$this->started) {
            $this->start();
        }

        return $this->bags[$name];
    }

    /**
     * Sets the MetadataBag.
     *
     * @param MetadataBag $metaBag
     */
    public function setMetadataBag(MetadataBag $metaBag = null)
    {
        if (null === $metaBag) {
            $metaBag = new MetadataBag();
        }

        $this->metadataBag = $metaBag;
    }

    /**
     * Gets the MetadataBag.
     *
     * @return MetadataBag
     */
    public function getMetadataBag()
    {
        return $this->metadataBag;
    }

    /**
     * {@inheritdoc}
     */
    public function isStarted()
    {
        return $this->started;
    }

    /**
     * Sets session.* ini variables.
     *
     * For convenience we omit 'session.' from the beginning of the keys.
     * Explicitly ignores other ini keys.
     *
     * @param array $options Session ini directives array(key => value).
     *
     * @see http://php.net/session.configuration
     */
    public function setOptions(array $options)
    {
        $validOptions = array_flip(array(
            'cache_limiter', 'cookie_domain', 'cookie_httponly',
            'cookie_lifetime', 'cookie_path', 'cookie_secure',
            'entropy_file', 'entropy_length', 'gc_divisor',
            'gc_maxlifetime', 'gc_probability', 'hash_bits_per_character',
            'hash_function', 'name', 'referer_check',
            'serialize_handler', 'use_cookies',
            'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled',
            'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name',
            'upload_progress.freq', 'upload_progress.min-freq', 'url_rewriter.tags',
        ));

        foreach ($options as $key => $value) {
            if (isset($validOptions[$key])) {
                ini_set('session.'.$key, $value);
            }
        }
    }

    /**
     * Registers session save handler as a PHP session handler.
     *
     * To use internal PHP session save handlers, override this method using ini_set with
     * session.save_handler and session.save_path e.g.
     *
     *     ini_set('session.save_handler', 'files');
     *     ini_set('session.save_path', /tmp');
     *
     * or pass in a NativeSessionHandler instance which configures session.save_handler in the
     * constructor, for a template see NativeFileSessionHandler or use handlers in
     * composer package drak/native-session
     *
     * @see http://php.net/session-set-save-handler
     * @see http://php.net/sessionhandlerinterface
     * @see http://php.net/sessionhandler
     * @see http://github.com/drak/NativeSession
     *
     * @param AbstractProxy|NativeSessionHandler|\SessionHandlerInterface|null $saveHandler
     *
     * @throws \InvalidArgumentException
     */
    public function setSaveHandler($saveHandler = null)
    {
        if (!$saveHandler instanceof AbstractProxy &&
            !$saveHandler instanceof NativeSessionHandler &&
            !$saveHandler instanceof \SessionHandlerInterface &&
            null !== $saveHandler) {
            throw new \InvalidArgumentException('Must be instance of AbstractProxy or NativeSessionHandler; implement \SessionHandlerInterface; or be null.');
        }

        // Wrap $saveHandler in proxy and prevent double wrapping of proxy
        if (!$saveHandler instanceof AbstractProxy && $saveHandler instanceof \SessionHandlerInterface) {
            $saveHandler = new SessionHandlerProxy($saveHandler);
        } elseif (!$saveHandler instanceof AbstractProxy) {
            $saveHandler = version_compare(phpversion(), '5.4.0', '>=') ?
                new SessionHandlerProxy(new \SessionHandler()) : new NativeProxy();
        }
        $this->saveHandler = $saveHandler;

        if ($this->saveHandler instanceof \SessionHandlerInterface) {
            if (version_compare(phpversion(), '5.4.0', '>=')) {
                session_set_save_handler($this->saveHandler, false);
            } else {
                session_set_save_handler(
                    array($this->saveHandler, 'open'),
                    array($this->saveHandler, 'close'),
                    array($this->saveHandler, 'read'),
                    array($this->saveHandler, 'write'),
                    array($this->saveHandler, 'destroy'),
                    array($this->saveHandler, 'gc')
                );
            }
        }
    }

    /**
     * Load the session with attributes.
     *
     * After starting the session, PHP retrieves the session from whatever handlers
     * are set to (either PHP's internal, or a custom save handler set with session_set_save_handler()).
     * PHP takes the return value from the read() handler, unserializes it
     * and populates $_SESSION with the result automatically.
     *
     * @param array|null $session
     */
    protected function loadSession(array &$session = null)
    {
        if (null === $session) {
            $session = &$_SESSION;
        }

        $bags = array_merge($this->bags, array($this->metadataBag));

        foreach ($bags as $bag) {
            $key = $bag->getStorageKey();
            $session[$key] = isset($session[$key]) ? $session[$key] : array();
            $bag->initialize($session[$key]);
        }

        $this->started = true;
        $this->closed = false;
    }
}
PK��Zގ�!LSymfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Session\Storage;

use Symfony\Component\HttpFoundation\Session\SessionBagInterface;

/**
 * MockArraySessionStorage mocks the session for unit tests.
 *
 * No PHP session is actually started since a session can be initialized
 * and shutdown only once per PHP execution cycle.
 *
 * When doing functional testing, you should use MockFileSessionStorage instead.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
 * @author Drak <drak@zikula.org>
 */
class MockArraySessionStorage implements SessionStorageInterface
{
    /**
     * @var string
     */
    protected $id = '';

    /**
     * @var string
     */
    protected $name;

    /**
     * @var boolean
     */
    protected $started = false;

    /**
     * @var boolean
     */
    protected $closed = false;

    /**
     * @var array
     */
    protected $data = array();

    /**
     * @var MetadataBag
     */
    protected $metadataBag;

    /**
     * @var array
     */
    protected $bags;

    /**
     * Constructor.
     *
     * @param string      $name    Session name
     * @param MetadataBag $metaBag MetadataBag instance.
     */
    public function __construct($name = 'MOCKSESSID', MetadataBag $metaBag = null)
    {
        $this->name = $name;
        $this->setMetadataBag($metaBag);
    }

    /**
     * Sets the session data.
     *
     * @param array $array
     */
    public function setSessionData(array $array)
    {
        $this->data = $array;
    }

    /**
     * {@inheritdoc}
     */
    public function start()
    {
        if ($this->started && !$this->closed) {
            return true;
        }

        if (empty($this->id)) {
            $this->id = $this->generateId();
        }

        $this->loadSession();

        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function regenerate($destroy = false, $lifetime = null)
    {
        if (!$this->started) {
            $this->start();
        }

        $this->metadataBag->stampNew($lifetime);
        $this->id = $this->generateId();

        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * {@inheritdoc}
     */
    public function setId($id)
    {
        if ($this->started) {
            throw new \LogicException('Cannot set session ID after the session has started.');
        }

        $this->id = $id;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * {@inheritdoc}
     */
    public function setName($name)
    {
        $this->name = $name;
    }

    /**
     * {@inheritdoc}
     */
    public function save()
    {
        if (!$this->started || $this->closed) {
            throw new \RuntimeException("Trying to save a session that was not started yet or was already closed");
        }
        // nothing to do since we don't persist the session data
        $this->closed = false;
        $this->started = false;
    }

    /**
     * {@inheritdoc}
     */
    public function clear()
    {
        // clear out the bags
        foreach ($this->bags as $bag) {
            $bag->clear();
        }

        // clear out the session
        $this->data = array();

        // reconnect the bags to the session
        $this->loadSession();
    }

    /**
     * {@inheritdoc}
     */
    public function registerBag(SessionBagInterface $bag)
    {
        $this->bags[$bag->getName()] = $bag;
    }

    /**
     * {@inheritdoc}
     */
    public function getBag($name)
    {
        if (!isset($this->bags[$name])) {
            throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name));
        }

        if (!$this->started) {
            $this->start();
        }

        return $this->bags[$name];
    }

    /**
     * {@inheritdoc}
     */
    public function isStarted()
    {
        return $this->started;
    }

    /**
     * Sets the MetadataBag.
     *
     * @param MetadataBag $bag
     */
    public function setMetadataBag(MetadataBag $bag = null)
    {
        if (null === $bag) {
            $bag = new MetadataBag();
        }

        $this->metadataBag = $bag;
    }

    /**
     * Gets the MetadataBag.
     *
     * @return MetadataBag
     */
    public function getMetadataBag()
    {
        return $this->metadataBag;
    }

    /**
     * Generates a session ID.
     *
     * This doesn't need to be particularly cryptographically secure since this is just
     * a mock.
     *
     * @return string
     */
    protected function generateId()
    {
        return hash('sha256', uniqid(mt_rand()));
    }

    protected function loadSession()
    {
        $bags = array_merge($this->bags, array($this->metadataBag));

        foreach ($bags as $bag) {
            $key = $bag->getStorageKey();
            $this->data[$key] = isset($this->data[$key]) ? $this->data[$key] : array();
            $bag->initialize($this->data[$key]);
        }

        $this->started = true;
        $this->closed = false;
    }
}
PK��Z��$�

KSymfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Session\Storage;

/**
 * MockFileSessionStorage is used to mock sessions for
 * functional testing when done in a single PHP process.
 *
 * No PHP session is actually started since a session can be initialized
 * and shutdown only once per PHP execution cycle and this class does
 * not pollute any session related globals, including session_*() functions
 * or session.* PHP ini directives.
 *
 * @author Drak <drak@zikula.org>
 */
class MockFileSessionStorage extends MockArraySessionStorage
{
    /**
     * @var string
     */
    private $savePath;

    /**
     * Constructor.
     *
     * @param string      $savePath Path of directory to save session files.
     * @param string      $name     Session name.
     * @param MetadataBag $metaBag  MetadataBag instance.
     */
    public function __construct($savePath = null, $name = 'MOCKSESSID', MetadataBag $metaBag = null)
    {
        if (null === $savePath) {
            $savePath = sys_get_temp_dir();
        }

        if (!is_dir($savePath)) {
            mkdir($savePath, 0777, true);
        }

        $this->savePath = $savePath;

        parent::__construct($name, $metaBag);
    }

    /**
     * {@inheritdoc}
     */
    public function start()
    {
        if ($this->started) {
            return true;
        }

        if (!$this->id) {
            $this->id = $this->generateId();
        }

        $this->read();

        $this->started = true;

        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function regenerate($destroy = false, $lifetime = null)
    {
        if (!$this->started) {
            $this->start();
        }

        if ($destroy) {
            $this->destroy();
        }

        return parent::regenerate($destroy, $lifetime);
    }

    /**
     * {@inheritdoc}
     */
    public function save()
    {
        if (!$this->started) {
            throw new \RuntimeException("Trying to save a session that was not started yet or was already closed");
        }

        file_put_contents($this->getFilePath(), serialize($this->data));

        // this is needed for Silex, where the session object is re-used across requests
        // in functional tests. In Symfony, the container is rebooted, so we don't have
        // this issue
        $this->started = false;
    }

    /**
     * Deletes a session from persistent storage.
     * Deliberately leaves session data in memory intact.
     */
    private function destroy()
    {
        if (is_file($this->getFilePath())) {
            unlink($this->getFilePath());
        }
    }

    /**
     * Calculate path to file.
     *
     * @return string File path
     */
    private function getFilePath()
    {
        return $this->savePath.'/'.$this->id.'.mocksess';
    }

    /**
     * Reads session from storage and loads session.
     */
    private function read()
    {
        $filePath = $this->getFilePath();
        $this->data = is_readable($filePath) && is_file($filePath) ? unserialize(file_get_contents($filePath)) : array();

        $this->loadSession();
    }
}
PK��Z����33QSymfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;

/**
 * Adds SessionHandler functionality if available.
 *
 * @see http://php.net/sessionhandler
 */

if (version_compare(phpversion(), '5.4.0', '>=')) {
    class NativeSessionHandler extends \SessionHandler {}
} else {
    class NativeSessionHandler {}
}
PK��Z�>�q��OSymfony/Component/HttpFoundation/Session/Storage/Handler/NullSessionHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;

/**
 * NullSessionHandler.
 *
 * Can be used in unit testing or in a situations where persisted sessions are not desired.
 *
 * @author Drak <drak@zikula.org>
 *
 * @api
 */
class NullSessionHandler implements \SessionHandlerInterface
{
    /**
     * {@inheritdoc}
     */
    public function open($savePath, $sessionName)
    {
        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function close()
    {
        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function read($sessionId)
    {
        return '';
    }

    /**
     * {@inheritdoc}
     */
    public function write($sessionId, $data)
    {
        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function destroy($sessionId)
    {
        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function gc($lifetime)
    {
        return true;
    }
}
PK��Zi����RSymfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;

/**
 * MongoDB session handler
 *
 * @author Markus Bachmann <markus.bachmann@bachi.biz>
 */
class MongoDbSessionHandler implements \SessionHandlerInterface
{
    /**
     * @var \Mongo
     */
    private $mongo;

    /**
     * @var \MongoCollection
     */
    private $collection;

    /**
     * @var array
     */
    private $options;

    /**
     * Constructor.
     *
     * List of available options:
     *  * database: The name of the database [required]
     *  * collection: The name of the collection [required]
     *  * id_field: The field name for storing the session id [default: _id]
     *  * data_field: The field name for storing the session data [default: data]
     *  * time_field: The field name for storing the timestamp [default: time]
     *
     * @param \Mongo|\MongoClient $mongo   A MongoClient or Mongo instance
     * @param array               $options An associative array of field options
     *
     * @throws \InvalidArgumentException When MongoClient or Mongo instance not provided
     * @throws \InvalidArgumentException When "database" or "collection" not provided
     */
    public function __construct($mongo, array $options)
    {
        if (!($mongo instanceof \MongoClient || $mongo instanceof \Mongo)) {
            throw new \InvalidArgumentException('MongoClient or Mongo instance required');
        }

        if (!isset($options['database']) || !isset($options['collection'])) {
            throw new \InvalidArgumentException('You must provide the "database" and "collection" option for MongoDBSessionHandler');
        }

        $this->mongo = $mongo;

        $this->options = array_merge(array(
            'id_field'   => '_id',
            'data_field' => 'data',
            'time_field' => 'time',
        ), $options);
    }

    /**
     * {@inheritDoc}
     */
    public function open($savePath, $sessionName)
    {
        return true;
    }

    /**
     * {@inheritDoc}
     */
    public function close()
    {
        return true;
    }

    /**
     * {@inheritDoc}
     */
    public function destroy($sessionId)
    {
        $this->getCollection()->remove(array(
            $this->options['id_field'] => $sessionId
        ));

        return true;
    }

    /**
     * {@inheritDoc}
     */
    public function gc($lifetime)
    {
        /* Note: MongoDB 2.2+ supports TTL collections, which may be used in
         * place of this method by indexing the "time_field" field with an
         * "expireAfterSeconds" option. Regardless of whether TTL collections
         * are used, consider indexing this field to make the remove query more
         * efficient.
         *
         * See: http://docs.mongodb.org/manual/tutorial/expire-data/
         */
        $time = new \MongoDate(time() - $lifetime);

        $this->getCollection()->remove(array(
            $this->options['time_field'] => array('$lt' => $time),
        ));

        return true;
    }

    /**
     * {@inheritDoc]
     */
    public function write($sessionId, $data)
    {
        $this->getCollection()->update(
            array($this->options['id_field'] => $sessionId),
            array('$set' => array(
                $this->options['data_field'] => new \MongoBinData($data, \MongoBinData::BYTE_ARRAY),
                $this->options['time_field'] => new \MongoDate(),
            )),
            array('upsert' => true, 'multiple' => false)
        );

        return true;
    }

    /**
     * {@inheritDoc}
     */
    public function read($sessionId)
    {
        $dbData = $this->getCollection()->findOne(array(
            $this->options['id_field'] => $sessionId,
        ));

        return null === $dbData ? '' : $dbData[$this->options['data_field']]->bin;
    }

    /**
     * Return a "MongoCollection" instance
     *
     * @return \MongoCollection
     */
    private function getCollection()
    {
        if (null === $this->collection) {
            $this->collection = $this->mongo->selectCollection($this->options['database'], $this->options['collection']);
        }

        return $this->collection;
    }

    /**
     * Return a Mongo instance
     *
     * @return \Mongo
     */
    protected function getMongo()
    {
        return $this->mongo;
    }
}
PK��ZOZ�P""NSymfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;

/**
 * PdoSessionHandler.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Michael Williams <michael.williams@funsational.com>
 */
class PdoSessionHandler implements \SessionHandlerInterface
{
    /**
     * @var \PDO PDO instance.
     */
    private $pdo;

    /**
     * @var array Database options.
     */
    private $dbOptions;

    /**
     * Constructor.
     *
     * List of available options:
     *  * db_table: The name of the table [required]
     *  * db_id_col: The column where to store the session id [default: sess_id]
     *  * db_data_col: The column where to store the session data [default: sess_data]
     *  * db_time_col: The column where to store the timestamp [default: sess_time]
     *
     * @param \PDO  $pdo       A \PDO instance
     * @param array $dbOptions An associative array of DB options
     *
     * @throws \InvalidArgumentException When "db_table" option is not provided
     */
    public function __construct(\PDO $pdo, array $dbOptions = array())
    {
        if (!array_key_exists('db_table', $dbOptions)) {
            throw new \InvalidArgumentException('You must provide the "db_table" option for a PdoSessionStorage.');
        }
        if (\PDO::ERRMODE_EXCEPTION !== $pdo->getAttribute(\PDO::ATTR_ERRMODE)) {
            throw new \InvalidArgumentException(sprintf('"%s" requires PDO error mode attribute be set to throw Exceptions (i.e. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION))', __CLASS__));
        }
        $this->pdo = $pdo;
        $this->dbOptions = array_merge(array(
            'db_id_col'   => 'sess_id',
            'db_data_col' => 'sess_data',
            'db_time_col' => 'sess_time',
        ), $dbOptions);
    }

    /**
     * {@inheritDoc}
     */
    public function open($path, $name)
    {
        return true;
    }

    /**
     * {@inheritDoc}
     */
    public function close()
    {
        return true;
    }

    /**
     * {@inheritDoc}
     */
    public function destroy($id)
    {
        // get table/column
        $dbTable = $this->dbOptions['db_table'];
        $dbIdCol = $this->dbOptions['db_id_col'];

        // delete the record associated with this id
        $sql = "DELETE FROM $dbTable WHERE $dbIdCol = :id";

        try {
            $stmt = $this->pdo->prepare($sql);
            $stmt->bindParam(':id', $id, \PDO::PARAM_STR);
            $stmt->execute();
        } catch (\PDOException $e) {
            throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data: %s', $e->getMessage()), 0, $e);
        }

        return true;
    }

    /**
     * {@inheritDoc}
     */
    public function gc($lifetime)
    {
        // get table/column
        $dbTable   = $this->dbOptions['db_table'];
        $dbTimeCol = $this->dbOptions['db_time_col'];

        // delete the session records that have expired
        $sql = "DELETE FROM $dbTable WHERE $dbTimeCol < :time";

        try {
            $stmt = $this->pdo->prepare($sql);
            $stmt->bindValue(':time', time() - $lifetime, \PDO::PARAM_INT);
            $stmt->execute();
        } catch (\PDOException $e) {
            throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data: %s', $e->getMessage()), 0, $e);
        }

        return true;
    }

    /**
     * {@inheritDoc}
     */
    public function read($id)
    {
        // get table/columns
        $dbTable   = $this->dbOptions['db_table'];
        $dbDataCol = $this->dbOptions['db_data_col'];
        $dbIdCol   = $this->dbOptions['db_id_col'];

        try {
            $sql = "SELECT $dbDataCol FROM $dbTable WHERE $dbIdCol = :id";

            $stmt = $this->pdo->prepare($sql);
            $stmt->bindParam(':id', $id, \PDO::PARAM_STR);

            $stmt->execute();
            // it is recommended to use fetchAll so that PDO can close the DB cursor
            // we anyway expect either no rows, or one row with one column. fetchColumn, seems to be buggy #4777
            $sessionRows = $stmt->fetchAll(\PDO::FETCH_NUM);

            if (count($sessionRows) == 1) {
                return base64_decode($sessionRows[0][0]);
            }

            // session does not exist, create it
            $this->createNewSession($id);

            return '';
        } catch (\PDOException $e) {
            throw new \RuntimeException(sprintf('PDOException was thrown when trying to read the session data: %s', $e->getMessage()), 0, $e);
        }
    }

    /**
     * {@inheritDoc}
     */
    public function write($id, $data)
    {
        // get table/column
        $dbTable   = $this->dbOptions['db_table'];
        $dbDataCol = $this->dbOptions['db_data_col'];
        $dbIdCol   = $this->dbOptions['db_id_col'];
        $dbTimeCol = $this->dbOptions['db_time_col'];

        //session data can contain non binary safe characters so we need to encode it
        $encoded = base64_encode($data);

        try {
            $driver = $this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME);

            if ('mysql' === $driver) {
                // MySQL would report $stmt->rowCount() = 0 on UPDATE when the data is left unchanged
                // it could result in calling createNewSession() whereas the session already exists in
                // the DB which would fail as the id is unique
                $stmt = $this->pdo->prepare(
                    "INSERT INTO $dbTable ($dbIdCol, $dbDataCol, $dbTimeCol) VALUES (:id, :data, :time) " .
                    "ON DUPLICATE KEY UPDATE $dbDataCol = VALUES($dbDataCol), $dbTimeCol = VALUES($dbTimeCol)"
                );
                $stmt->bindParam(':id', $id, \PDO::PARAM_STR);
                $stmt->bindParam(':data', $encoded, \PDO::PARAM_STR);
                $stmt->bindValue(':time', time(), \PDO::PARAM_INT);
                $stmt->execute();
            } elseif ('oci' === $driver) {
                $stmt = $this->pdo->prepare("MERGE INTO $dbTable USING DUAL ON($dbIdCol = :id) ".
                       "WHEN NOT MATCHED THEN INSERT ($dbIdCol, $dbDataCol, $dbTimeCol) VALUES (:id, :data, sysdate) " .
                       "WHEN MATCHED THEN UPDATE SET $dbDataCol = :data WHERE $dbIdCol = :id");

                $stmt->bindParam(':id', $id, \PDO::PARAM_STR);
                $stmt->bindParam(':data', $encoded, \PDO::PARAM_STR);
                $stmt->execute();
            } else {
                $stmt = $this->pdo->prepare("UPDATE $dbTable SET $dbDataCol = :data, $dbTimeCol = :time WHERE $dbIdCol = :id");
                $stmt->bindParam(':id', $id, \PDO::PARAM_STR);
                $stmt->bindParam(':data', $encoded, \PDO::PARAM_STR);
                $stmt->bindValue(':time', time(), \PDO::PARAM_INT);
                $stmt->execute();

                if (!$stmt->rowCount()) {
                    // No session exists in the database to update. This happens when we have called
                    // session_regenerate_id()
                    $this->createNewSession($id, $data);
                }
            }
        } catch (\PDOException $e) {
                throw new \RuntimeException(sprintf('PDOException was thrown when trying to write the session data: %s', $e->getMessage()), 0, $e);
        }

        return true;
    }

    /**
     * Creates a new session with the given $id and $data
     *
     * @param string $id
     * @param string $data
     *
     * @return boolean True.
     */
    private function createNewSession($id, $data = '')
    {
        // get table/column
        $dbTable   = $this->dbOptions['db_table'];
        $dbDataCol = $this->dbOptions['db_data_col'];
        $dbIdCol   = $this->dbOptions['db_id_col'];
        $dbTimeCol = $this->dbOptions['db_time_col'];

        $sql = "INSERT INTO $dbTable ($dbIdCol, $dbDataCol, $dbTimeCol) VALUES (:id, :data, :time)";

        //session data can contain non binary safe characters so we need to encode it
        $encoded = base64_encode($data);
        $stmt = $this->pdo->prepare($sql);
        $stmt->bindParam(':id', $id, \PDO::PARAM_STR);
        $stmt->bindParam(':data', $encoded, \PDO::PARAM_STR);
        $stmt->bindValue(':time', time(), \PDO::PARAM_INT);
        $stmt->execute();

        return true;
    }

    /**
     * Return a PDO instance
     *
     * @return \PDO
     */
    protected function getConnection()
    {
        return $this->pdo;
    }
}
PK��Zk��4{{TSymfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;

/**
 * MemcachedSessionHandler.
 *
 * Memcached based session storage handler based on the Memcached class
 * provided by the PHP memcached extension.
 *
 * @see http://php.net/memcached
 *
 * @author Drak <drak@zikula.org>
 */
class MemcachedSessionHandler implements \SessionHandlerInterface
{
    /**
     * @var \Memcached Memcached driver.
     */
    private $memcached;

    /**
     * @var integer Time to live in seconds
     */
    private $ttl;

    /**
     * @var string Key prefix for shared environments.
     */
    private $prefix;

    /**
     * Constructor.
     *
     * List of available options:
     *  * prefix: The prefix to use for the memcached keys in order to avoid collision
     *  * expiretime: The time to live in seconds
     *
     * @param \Memcached $memcached A \Memcached instance
     * @param array      $options   An associative array of Memcached options
     *
     * @throws \InvalidArgumentException When unsupported options are passed
     */
    public function __construct(\Memcached $memcached, array $options = array())
    {
        $this->memcached = $memcached;

        if ($diff = array_diff(array_keys($options), array('prefix', 'expiretime'))) {
            throw new \InvalidArgumentException(sprintf(
                'The following options are not supported "%s"', implode(', ', $diff)
            ));
        }

        $this->ttl = isset($options['expiretime']) ? (int) $options['expiretime'] : 86400;
        $this->prefix = isset($options['prefix']) ? $options['prefix'] : 'sf2s';
    }

    /**
     * {@inheritDoc}
     */
    public function open($savePath, $sessionName)
    {
        return true;
    }

    /**
     * {@inheritDoc}
     */
    public function close()
    {
        return true;
    }

    /**
     * {@inheritDoc}
     */
    public function read($sessionId)
    {
        return $this->memcached->get($this->prefix.$sessionId) ?: '';
    }

    /**
     * {@inheritDoc}
     */
    public function write($sessionId, $data)
    {
        return $this->memcached->set($this->prefix.$sessionId, $data, time() + $this->ttl);
    }

    /**
     * {@inheritDoc}
     */
    public function destroy($sessionId)
    {
        return $this->memcached->delete($this->prefix.$sessionId);
    }

    /**
     * {@inheritDoc}
     */
    public function gc($lifetime)
    {
        // not required here because memcached will auto expire the records anyhow.
        return true;
    }

    /**
     * Return a Memcached instance
     *
     * @return \Memcached
     */
    protected function getMemcached()
    {
        return $this->memcached;
    }
}
PK��Zu�Y0��USymfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;

/**
 * NativeFileSessionHandler.
 *
 * Native session handler using PHP's built in file storage.
 *
 * @author Drak <drak@zikula.org>
 */
class NativeFileSessionHandler extends NativeSessionHandler
{
    /**
     * Constructor.
     *
     * @param string $savePath Path of directory to save session files.
     *                         Default null will leave setting as defined by PHP.
     *                         '/path', 'N;/path', or 'N;octal-mode;/path
     *
     * @see http://php.net/session.configuration.php#ini.session.save-path for further details.
     *
     * @throws \InvalidArgumentException On invalid $savePath
     */
    public function __construct($savePath = null)
    {
        if (null === $savePath) {
            $savePath = ini_get('session.save_path');
        }

        $baseDir = $savePath;

        if ($count = substr_count($savePath, ';')) {
            if ($count > 2) {
                throw new \InvalidArgumentException(sprintf('Invalid argument $savePath \'%s\'', $savePath));
            }

            // characters after last ';' are the path
            $baseDir = ltrim(strrchr($savePath, ';'), ';');
        }

        if ($baseDir && !is_dir($baseDir)) {
            mkdir($baseDir, 0777, true);
        }

        ini_set('session.save_path', $savePath);
        ini_set('session.save_handler', 'files');
    }
}
PK��Zڏ۹�
�
SSymfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;

/**
 * MemcacheSessionHandler.
 *
 * @author Drak <drak@zikula.org>
 */
class MemcacheSessionHandler implements \SessionHandlerInterface
{
    /**
     * @var \Memcache Memcache driver.
     */
    private $memcache;

    /**
     * @var integer Time to live in seconds
     */
    private $ttl;

    /**
     * @var string Key prefix for shared environments.
     */
    private $prefix;

    /**
     * Constructor.
     *
     * List of available options:
     *  * prefix: The prefix to use for the memcache keys in order to avoid collision
     *  * expiretime: The time to live in seconds
     *
     * @param \Memcache $memcache A \Memcache instance
     * @param array     $options  An associative array of Memcache options
     *
     * @throws \InvalidArgumentException When unsupported options are passed
     */
    public function __construct(\Memcache $memcache, array $options = array())
    {
        if ($diff = array_diff(array_keys($options), array('prefix', 'expiretime'))) {
            throw new \InvalidArgumentException(sprintf(
                'The following options are not supported "%s"', implode(', ', $diff)
            ));
        }

        $this->memcache = $memcache;
        $this->ttl = isset($options['expiretime']) ? (int) $options['expiretime'] : 86400;
        $this->prefix = isset($options['prefix']) ? $options['prefix'] : 'sf2s';
    }

    /**
     * {@inheritDoc}
     */
    public function open($savePath, $sessionName)
    {
        return true;
    }

    /**
     * {@inheritDoc}
     */
    public function close()
    {
        return $this->memcache->close();
    }

    /**
     * {@inheritDoc}
     */
    public function read($sessionId)
    {
        return $this->memcache->get($this->prefix.$sessionId) ?: '';
    }

    /**
     * {@inheritDoc}
     */
    public function write($sessionId, $data)
    {
        return $this->memcache->set($this->prefix.$sessionId, $data, 0, time() + $this->ttl);
    }

    /**
     * {@inheritDoc}
     */
    public function destroy($sessionId)
    {
        return $this->memcache->delete($this->prefix.$sessionId);
    }

    /**
     * {@inheritDoc}
     */
    public function gc($lifetime)
    {
        // not required here because memcache will auto expire the records anyhow.
        return true;
    }

    /**
     * Return a Memcache instance
     *
     * @return \Memcache
     */
    protected function getMemcache()
    {
        return $this->memcache;
    }
}
PK��Z�����USymfony/Component/HttpFoundation/Session/Storage/Handler/WriteCheckSessionHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;

/**
 * Wraps another SessionHandlerInterface to only write the session when it has been modified.
 *
 * @author Adrien Brault <adrien.brault@gmail.com>
 */
class WriteCheckSessionHandler implements \SessionHandlerInterface
{
    /**
     * @var \SessionHandlerInterface
     */
    private $wrappedSessionHandler;

    /**
     * @var array sessionId => session
     */
    private $readSessions;

    public function __construct(\SessionHandlerInterface $wrappedSessionHandler)
    {
        $this->wrappedSessionHandler = $wrappedSessionHandler;
    }

    /**
     * {@inheritdoc}
     */
    public function close()
    {
        return $this->wrappedSessionHandler->close();
    }

    /**
     * {@inheritdoc}
     */
    public function destroy($sessionId)
    {
        return $this->wrappedSessionHandler->destroy($sessionId);
    }

    /**
     * {@inheritdoc}
     */
    public function gc($maxLifetime)
    {
        return $this->wrappedSessionHandler->gc($maxLifetime);
    }

    /**
     * {@inheritdoc}
     */
    public function open($savePath, $sessionId)
    {
        return $this->wrappedSessionHandler->open($savePath, $sessionId);
    }

    /**
     * {@inheritdoc}
     */
    public function read($sessionId)
    {
        $session = $this->wrappedSessionHandler->read($sessionId);

        $this->readSessions[$sessionId] = $session;

        return $session;
    }

    /**
     * {@inheritdoc}
     */
    public function write($sessionId, $sessionData)
    {
        if (isset($this->readSessions[$sessionId]) && $sessionData === $this->readSessions[$sessionId]) {
            return true;
        }

        return $this->wrappedSessionHandler->write($sessionId, $sessionData);
    }
}
PK��Z�zu00LSymfony/Component/HttpFoundation/Session/Storage/PhpBridgeSessionStorage.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Session\Storage;

use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;
use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler;

/**
 * Allows session to be started by PHP and managed by Symfony2
 *
 * @author Drak <drak@zikula.org>
 */
class PhpBridgeSessionStorage extends NativeSessionStorage
{
    /**
     * Constructor.
     *
     * @param AbstractProxy|NativeSessionHandler|\SessionHandlerInterface|null $handler
     * @param MetadataBag                                                      $metaBag MetadataBag
     */
    public function __construct($handler = null, MetadataBag $metaBag = null)
    {
        $this->setMetadataBag($metaBag);
        $this->setSaveHandler($handler);
    }

    /**
     * {@inheritdoc}
     */
    public function start()
    {
        if ($this->started && !$this->closed) {
            return true;
        }

        $this->loadSession();
        if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) {
            // This condition matches only PHP 5.3 + internal save handlers
            $this->saveHandler->setActive(true);
        }

        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function clear()
    {
        // clear out the bags and nothing else that may be set
        // since the purpose of this driver is to share a handler
        foreach ($this->bags as $bag) {
            $bag->clear();
        }

        // reconnect the bags to the session
        $this->loadSession();
    }
}
PK��Zmwȡ��NSymfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy;

/**
 * SessionHandler proxy.
 *
 * @author Drak <drak@zikula.org>
 */
class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterface
{
    /**
     * @var \SessionHandlerInterface
     */
    protected $handler;

    /**
     * Constructor.
     *
     * @param \SessionHandlerInterface $handler
     */
    public function __construct(\SessionHandlerInterface $handler)
    {
        $this->handler = $handler;
        $this->wrapper = ($handler instanceof \SessionHandler);
        $this->saveHandlerName = $this->wrapper ? ini_get('session.save_handler') : 'user';
    }

    // \SessionHandlerInterface

    /**
     * {@inheritdoc}
     */
    public function open($savePath, $sessionName)
    {
        $return = (bool) $this->handler->open($savePath, $sessionName);

        if (true === $return) {
            $this->active = true;
        }

        return $return;
    }

    /**
     * {@inheritdoc}
     */
    public function close()
    {
        $this->active = false;

        return (bool) $this->handler->close();
    }

    /**
     * {@inheritdoc}
     */
    public function read($id)
    {
        return (string) $this->handler->read($id);
    }

    /**
     * {@inheritdoc}
     */
    public function write($id, $data)
    {
        return (bool) $this->handler->write($id, $data);
    }

    /**
     * {@inheritdoc}
     */
    public function destroy($id)
    {
        return (bool) $this->handler->destroy($id);
    }

    /**
     * {@inheritdoc}
     */
    public function gc($maxlifetime)
    {
        return (bool) $this->handler->gc($maxlifetime);
    }
}
PK��Z�2�]��HSymfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy;

/**
 * AbstractProxy.
 *
 * @author Drak <drak@zikula.org>
 */
abstract class AbstractProxy
{
    /**
     * Flag if handler wraps an internal PHP session handler (using \SessionHandler).
     *
     * @var boolean
     */
    protected $wrapper = false;

    /**
     * @var boolean
     */
    protected $active = false;

    /**
     * @var string
     */
    protected $saveHandlerName;

    /**
     * Gets the session.save_handler name.
     *
     * @return string
     */
    public function getSaveHandlerName()
    {
        return $this->saveHandlerName;
    }

    /**
     * Is this proxy handler and instance of \SessionHandlerInterface.
     *
     * @return boolean
     */
    public function isSessionHandlerInterface()
    {
        return ($this instanceof \SessionHandlerInterface);
    }

    /**
     * Returns true if this handler wraps an internal PHP session save handler using \SessionHandler.
     *
     * @return Boolean
     */
    public function isWrapper()
    {
        return $this->wrapper;
    }

    /**
     * Has a session started?
     *
     * @return Boolean
     */
    public function isActive()
    {
        if (version_compare(phpversion(), '5.4.0', '>=')) {
            return $this->active = \PHP_SESSION_ACTIVE === session_status();
        }

        return $this->active;
    }

    /**
     * Sets the active flag.
     *
     * Has no effect under PHP 5.4+ as status is detected
     * automatically in isActive()
     *
     * @internal
     *
     * @param Boolean $flag
     *
     * @throws \LogicException
     */
    public function setActive($flag)
    {
        if (version_compare(phpversion(), '5.4.0', '>=')) {
            throw new \LogicException('This method is disabled in PHP 5.4.0+');
        }

        $this->active = (bool) $flag;
    }

    /**
     * Gets the session ID.
     *
     * @return string
     */
    public function getId()
    {
        return session_id();
    }

    /**
     * Sets the session ID.
     *
     * @param string $id
     *
     * @throws \LogicException
     */
    public function setId($id)
    {
        if ($this->isActive()) {
            throw new \LogicException('Cannot change the ID of an active session');
        }

        session_id($id);
    }

    /**
     * Gets the session name.
     *
     * @return string
     */
    public function getName()
    {
        return session_name();
    }

    /**
     * Sets the session name.
     *
     * @param string $name
     *
     * @throws \LogicException
     */
    public function setName($name)
    {
        if ($this->isActive()) {
            throw new \LogicException('Cannot change the name of an active session');
        }

        session_name($name);
    }
}
PK��Z�A��FSymfony/Component/HttpFoundation/Session/Storage/Proxy/NativeProxy.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy;

/**
 * NativeProxy.
 *
 * This proxy is built-in session handlers in PHP 5.3.x
 *
 * @author Drak <drak@zikula.org>
 */
class NativeProxy extends AbstractProxy
{
    /**
     * Constructor.
     */
    public function __construct()
    {
        // this makes an educated guess as to what the handler is since it should already be set.
        $this->saveHandlerName = ini_get('session.save_handler');
    }

    /**
     * Returns true if this handler wraps an internal PHP session save handler using \SessionHandler.
     *
     * @return Boolean False.
     */
    public function isWrapper()
    {
        return false;
    }
}
PK��Z��g_��@Symfony/Component/HttpFoundation/Session/Storage/MetadataBag.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Session\Storage;

use Symfony\Component\HttpFoundation\Session\SessionBagInterface;

/**
 * Metadata container.
 *
 * Adds metadata to the session.
 *
 * @author Drak <drak@zikula.org>
 */
class MetadataBag implements SessionBagInterface
{
    const CREATED = 'c';
    const UPDATED = 'u';
    const LIFETIME = 'l';

    /**
     * @var string
     */
    private $name = '__metadata';

    /**
     * @var string
     */
    private $storageKey;

    /**
     * @var array
     */
    protected $meta = array(self::CREATED => 0, self::UPDATED => 0, self::LIFETIME => 0);

    /**
     * Unix timestamp.
     *
     * @var integer
     */
    private $lastUsed;

    /**
     * @var integer
     */
    private $updateThreshold;

    /**
     * Constructor.
     *
     * @param string  $storageKey      The key used to store bag in the session.
     * @param integer $updateThreshold The time to wait between two UPDATED updates
     */
    public function __construct($storageKey = '_sf2_meta', $updateThreshold = 0)
    {
        $this->storageKey = $storageKey;
        $this->updateThreshold = $updateThreshold;
    }

    /**
     * {@inheritdoc}
     */
    public function initialize(array &$array)
    {
        $this->meta = &$array;

        if (isset($array[self::CREATED])) {
            $this->lastUsed = $this->meta[self::UPDATED];

            $timeStamp = time();
            if ($timeStamp - $array[self::UPDATED] >= $this->updateThreshold) {
                $this->meta[self::UPDATED] = $timeStamp;
            }
        } else {
            $this->stampCreated();
        }
    }

    /**
     * Gets the lifetime that the session cookie was set with.
     *
     * @return integer
     */
    public function getLifetime()
    {
        return $this->meta[self::LIFETIME];
    }

    /**
     * Stamps a new session's metadata.
     *
     * @param integer $lifetime Sets the cookie lifetime for the session cookie. A null value
     *                          will leave the system settings unchanged, 0 sets the cookie
     *                          to expire with browser session. Time is in seconds, and is
     *                          not a Unix timestamp.
     */
    public function stampNew($lifetime = null)
    {
        $this->stampCreated($lifetime);
    }

    /**
     * {@inheritdoc}
     */
    public function getStorageKey()
    {
        return $this->storageKey;
    }

    /**
     * Gets the created timestamp metadata.
     *
     * @return integer Unix timestamp
     */
    public function getCreated()
    {
        return $this->meta[self::CREATED];
    }

    /**
     * Gets the last used metadata.
     *
     * @return integer Unix timestamp
     */
    public function getLastUsed()
    {
        return $this->lastUsed;
    }

    /**
     * {@inheritdoc}
     */
    public function clear()
    {
        // nothing to do
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Sets name.
     *
     * @param string $name
     */
    public function setName($name)
    {
        $this->name = $name;
    }

    private function stampCreated($lifetime = null)
    {
        $timeStamp = time();
        $this->meta[self::CREATED] = $this->meta[self::UPDATED] = $this->lastUsed = $timeStamp;
        $this->meta[self::LIFETIME] = (null === $lifetime) ? ini_get('session.cookie_lifetime') : $lifetime;
    }
}
PK��Z��?�yyLSymfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Session\Storage;

use Symfony\Component\HttpFoundation\Session\SessionBagInterface;

/**
 * StorageInterface.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Drak <drak@zikula.org>
 *
 * @api
 */
interface SessionStorageInterface
{
    /**
     * Starts the session.
     *
     * @throws \RuntimeException If something goes wrong starting the session.
     *
     * @return boolean True if started.
     *
     * @api
     */
    public function start();

    /**
     * Checks if the session is started.
     *
     * @return boolean True if started, false otherwise.
     */
    public function isStarted();

    /**
     * Returns the session ID
     *
     * @return string The session ID or empty.
     *
     * @api
     */
    public function getId();

    /**
     * Sets the session ID
     *
     * @param string $id
     *
     * @api
     */
    public function setId($id);

    /**
     * Returns the session name
     *
     * @return mixed The session name.
     *
     * @api
     */
    public function getName();

    /**
     * Sets the session name
     *
     * @param string $name
     *
     * @api
     */
    public function setName($name);

    /**
     * Regenerates id that represents this storage.
     *
     * This method must invoke session_regenerate_id($destroy) unless
     * this interface is used for a storage object designed for unit
     * or functional testing where a real PHP session would interfere
     * with testing.
     *
     * Note regenerate+destroy should not clear the session data in memory
     * only delete the session data from persistent storage.
     *
     * @param Boolean $destroy  Destroy session when regenerating?
     * @param integer $lifetime Sets the cookie lifetime for the session cookie. A null value
     *                          will leave the system settings unchanged, 0 sets the cookie
     *                          to expire with browser session. Time is in seconds, and is
     *                          not a Unix timestamp.
     *
     * @return Boolean True if session regenerated, false if error
     *
     * @throws \RuntimeException If an error occurs while regenerating this storage
     *
     * @api
     */
    public function regenerate($destroy = false, $lifetime = null);

    /**
     * Force the session to be saved and closed.
     *
     * This method must invoke session_write_close() unless this interface is
     * used for a storage object design for unit or functional testing where
     * a real PHP session would interfere with testing, in which case it
     * it should actually persist the session data if required.
     *
     * @throws \RuntimeException If the session is saved without being started, or if the session
     *                           is already closed.
     */
    public function save();

    /**
     * Clear all session data in memory.
     */
    public function clear();

    /**
     * Gets a SessionBagInterface by name.
     *
     * @param string $name
     *
     * @return SessionBagInterface
     *
     * @throws \InvalidArgumentException If the bag does not exist
     */
    public function getBag($name);

    /**
     * Registers a SessionBagInterface for use.
     *
     * @param SessionBagInterface $bag
     */
    public function registerBag(SessionBagInterface $bag);

    /**
     * @return MetadataBag
     */
    public function getMetadataBag();
}
PK��Z�K>��2Symfony/Component/HttpFoundation/ApacheRequest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation;

/**
 * Request represents an HTTP request from an Apache server.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ApacheRequest extends Request
{
    /**
     * {@inheritdoc}
     */
    protected function prepareRequestUri()
    {
        return $this->server->get('REQUEST_URI');
    }

    /**
     * {@inheritdoc}
     */
    protected function prepareBaseUrl()
    {
        $baseUrl = $this->server->get('SCRIPT_NAME');

        if (false === strpos($this->server->get('REQUEST_URI'), $baseUrl)) {
            // assume mod_rewrite
            return rtrim(dirname($baseUrl), '/\\');
        }

        return $baseUrl;
    }
}
PK��Zq�ugd�d�,Symfony/Component/HttpFoundation/Request.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation;

use Symfony\Component\HttpFoundation\Session\SessionInterface;

/**
 * Request represents an HTTP request.
 *
 * The methods dealing with URL accept / return a raw path (% encoded):
 *   * getBasePath
 *   * getBaseUrl
 *   * getPathInfo
 *   * getRequestUri
 *   * getUri
 *   * getUriForPath
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class Request
{
    const HEADER_CLIENT_IP    = 'client_ip';
    const HEADER_CLIENT_HOST  = 'client_host';
    const HEADER_CLIENT_PROTO = 'client_proto';
    const HEADER_CLIENT_PORT  = 'client_port';

    protected static $trustedProxies = array();

    /**
     * @var string[]
     */
    protected static $trustedHostPatterns = array();

    /**
     * @var string[]
     */
    protected static $trustedHosts = array();

    /**
     * Names for headers that can be trusted when
     * using trusted proxies.
     *
     * The default names are non-standard, but widely used
     * by popular reverse proxies (like Apache mod_proxy or Amazon EC2).
     */
    protected static $trustedHeaders = array(
        self::HEADER_CLIENT_IP    => 'X_FORWARDED_FOR',
        self::HEADER_CLIENT_HOST  => 'X_FORWARDED_HOST',
        self::HEADER_CLIENT_PROTO => 'X_FORWARDED_PROTO',
        self::HEADER_CLIENT_PORT  => 'X_FORWARDED_PORT',
    );

    protected static $httpMethodParameterOverride = false;

    /**
     * Custom parameters
     *
     * @var \Symfony\Component\HttpFoundation\ParameterBag
     *
     * @api
     */
    public $attributes;

    /**
     * Request body parameters ($_POST)
     *
     * @var \Symfony\Component\HttpFoundation\ParameterBag
     *
     * @api
     */
    public $request;

    /**
     * Query string parameters ($_GET)
     *
     * @var \Symfony\Component\HttpFoundation\ParameterBag
     *
     * @api
     */
    public $query;

    /**
     * Server and execution environment parameters ($_SERVER)
     *
     * @var \Symfony\Component\HttpFoundation\ServerBag
     *
     * @api
     */
    public $server;

    /**
     * Uploaded files ($_FILES)
     *
     * @var \Symfony\Component\HttpFoundation\FileBag
     *
     * @api
     */
    public $files;

    /**
     * Cookies ($_COOKIE)
     *
     * @var \Symfony\Component\HttpFoundation\ParameterBag
     *
     * @api
     */
    public $cookies;

    /**
     * Headers (taken from the $_SERVER)
     *
     * @var \Symfony\Component\HttpFoundation\HeaderBag
     *
     * @api
     */
    public $headers;

    /**
     * @var string
     */
    protected $content;

    /**
     * @var array
     */
    protected $languages;

    /**
     * @var array
     */
    protected $charsets;

    /**
     * @var array
     */
    protected $encodings;

    /**
     * @var array
     */
    protected $acceptableContentTypes;

    /**
     * @var string
     */
    protected $pathInfo;

    /**
     * @var string
     */
    protected $requestUri;

    /**
     * @var string
     */
    protected $baseUrl;

    /**
     * @var string
     */
    protected $basePath;

    /**
     * @var string
     */
    protected $method;

    /**
     * @var string
     */
    protected $format;

    /**
     * @var \Symfony\Component\HttpFoundation\Session\SessionInterface
     */
    protected $session;

    /**
     * @var string
     */
    protected $locale;

    /**
     * @var string
     */
    protected $defaultLocale = 'en';

    /**
     * @var array
     */
    protected static $formats;

    protected static $requestFactory;

    /**
     * Constructor.
     *
     * @param array  $query      The GET parameters
     * @param array  $request    The POST parameters
     * @param array  $attributes The request attributes (parameters parsed from the PATH_INFO, ...)
     * @param array  $cookies    The COOKIE parameters
     * @param array  $files      The FILES parameters
     * @param array  $server     The SERVER parameters
     * @param string $content    The raw body data
     *
     * @api
     */
    public function __construct(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null)
    {
        $this->initialize($query, $request, $attributes, $cookies, $files, $server, $content);
    }

    /**
     * Sets the parameters for this request.
     *
     * This method also re-initializes all properties.
     *
     * @param array  $query      The GET parameters
     * @param array  $request    The POST parameters
     * @param array  $attributes The request attributes (parameters parsed from the PATH_INFO, ...)
     * @param array  $cookies    The COOKIE parameters
     * @param array  $files      The FILES parameters
     * @param array  $server     The SERVER parameters
     * @param string $content    The raw body data
     *
     * @api
     */
    public function initialize(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null)
    {
        $this->request = new ParameterBag($request);
        $this->query = new ParameterBag($query);
        $this->attributes = new ParameterBag($attributes);
        $this->cookies = new ParameterBag($cookies);
        $this->files = new FileBag($files);
        $this->server = new ServerBag($server);
        $this->headers = new HeaderBag($this->server->getHeaders());

        $this->content = $content;
        $this->languages = null;
        $this->charsets = null;
        $this->encodings = null;
        $this->acceptableContentTypes = null;
        $this->pathInfo = null;
        $this->requestUri = null;
        $this->baseUrl = null;
        $this->basePath = null;
        $this->method = null;
        $this->format = null;
    }

    /**
     * Creates a new request with values from PHP's super globals.
     *
     * @return Request A new request
     *
     * @api
     */
    public static function createFromGlobals()
    {
        $request = self::createRequestFromFactory($_GET, $_POST, array(), $_COOKIE, $_FILES, $_SERVER);

        if (0 === strpos($request->headers->get('CONTENT_TYPE'), 'application/x-www-form-urlencoded')
            && in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), array('PUT', 'DELETE', 'PATCH'))
        ) {
            parse_str($request->getContent(), $data);
            $request->request = new ParameterBag($data);
        }

        return $request;
    }

    /**
     * Creates a Request based on a given URI and configuration.
     *
     * The information contained in the URI always take precedence
     * over the other information (server and parameters).
     *
     * @param string $uri        The URI
     * @param string $method     The HTTP method
     * @param array  $parameters The query (GET) or request (POST) parameters
     * @param array  $cookies    The request cookies ($_COOKIE)
     * @param array  $files      The request files ($_FILES)
     * @param array  $server     The server parameters ($_SERVER)
     * @param string $content    The raw body data
     *
     * @return Request A Request instance
     *
     * @api
     */
    public static function create($uri, $method = 'GET', $parameters = array(), $cookies = array(), $files = array(), $server = array(), $content = null)
    {
        $server = array_replace(array(
            'SERVER_NAME'          => 'localhost',
            'SERVER_PORT'          => 80,
            'HTTP_HOST'            => 'localhost',
            'HTTP_USER_AGENT'      => 'Symfony/2.X',
            'HTTP_ACCEPT'          => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
            'HTTP_ACCEPT_LANGUAGE' => 'en-us,en;q=0.5',
            'HTTP_ACCEPT_CHARSET'  => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
            'REMOTE_ADDR'          => '127.0.0.1',
            'SCRIPT_NAME'          => '',
            'SCRIPT_FILENAME'      => '',
            'SERVER_PROTOCOL'      => 'HTTP/1.1',
            'REQUEST_TIME'         => time(),
        ), $server);

        $server['PATH_INFO'] = '';
        $server['REQUEST_METHOD'] = strtoupper($method);

        $components = parse_url($uri);
        if (isset($components['host'])) {
            $server['SERVER_NAME'] = $components['host'];
            $server['HTTP_HOST'] = $components['host'];
        }

        if (isset($components['scheme'])) {
            if ('https' === $components['scheme']) {
                $server['HTTPS'] = 'on';
                $server['SERVER_PORT'] = 443;
            } else {
                unset($server['HTTPS']);
                $server['SERVER_PORT'] = 80;
            }
        }

        if (isset($components['port'])) {
            $server['SERVER_PORT'] = $components['port'];
            $server['HTTP_HOST'] = $server['HTTP_HOST'].':'.$components['port'];
        }

        if (isset($components['user'])) {
            $server['PHP_AUTH_USER'] = $components['user'];
        }

        if (isset($components['pass'])) {
            $server['PHP_AUTH_PW'] = $components['pass'];
        }

        if (!isset($components['path'])) {
            $components['path'] = '/';
        }

        switch (strtoupper($method)) {
            case 'POST':
            case 'PUT':
            case 'DELETE':
                if (!isset($server['CONTENT_TYPE'])) {
                    $server['CONTENT_TYPE'] = 'application/x-www-form-urlencoded';
                }
            case 'PATCH':
                $request = $parameters;
                $query = array();
                break;
            default:
                $request = array();
                $query = $parameters;
                break;
        }

        $queryString = '';
        if (isset($components['query'])) {
            parse_str(html_entity_decode($components['query']), $qs);

            if ($query) {
                $query = array_replace($qs, $query);
                $queryString = http_build_query($query, '', '&');
            } else {
                $query = $qs;
                $queryString = $components['query'];
            }
        } elseif ($query) {
            $queryString = http_build_query($query, '', '&');
        }

        $server['REQUEST_URI'] = $components['path'].('' !== $queryString ? '?'.$queryString : '');
        $server['QUERY_STRING'] = $queryString;

        return self::createRequestFromFactory($query, $request, array(), $cookies, $files, $server, $content);
    }

    /**
     * Sets a callable able to create a Request instance.
     *
     * This is mainly useful when you need to override the Request class
     * to keep BC with an existing system. It should not be used for any
     * other purpose.
     *
     * @param callable|null $callable A PHP callable
     */
    public static function setFactory($callable)
    {
        self::$requestFactory = $callable;
    }

    /**
     * Clones a request and overrides some of its parameters.
     *
     * @param array $query      The GET parameters
     * @param array $request    The POST parameters
     * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...)
     * @param array $cookies    The COOKIE parameters
     * @param array $files      The FILES parameters
     * @param array $server     The SERVER parameters
     *
     * @return Request The duplicated request
     *
     * @api
     */
    public function duplicate(array $query = null, array $request = null, array $attributes = null, array $cookies = null, array $files = null, array $server = null)
    {
        $dup = clone $this;
        if ($query !== null) {
            $dup->query = new ParameterBag($query);
        }
        if ($request !== null) {
            $dup->request = new ParameterBag($request);
        }
        if ($attributes !== null) {
            $dup->attributes = new ParameterBag($attributes);
        }
        if ($cookies !== null) {
            $dup->cookies = new ParameterBag($cookies);
        }
        if ($files !== null) {
            $dup->files = new FileBag($files);
        }
        if ($server !== null) {
            $dup->server = new ServerBag($server);
            $dup->headers = new HeaderBag($dup->server->getHeaders());
        }
        $dup->languages = null;
        $dup->charsets = null;
        $dup->encodings = null;
        $dup->acceptableContentTypes = null;
        $dup->pathInfo = null;
        $dup->requestUri = null;
        $dup->baseUrl = null;
        $dup->basePath = null;
        $dup->method = null;
        $dup->format = null;

        if (!$dup->get('_format') && $this->get('_format')) {
            $dup->attributes->set('_format', $this->get('_format'));
        }

        if (!$dup->getRequestFormat(null)) {
            $dup->setRequestFormat($format = $this->getRequestFormat(null));
        }

        return $dup;
    }

    /**
     * Clones the current request.
     *
     * Note that the session is not cloned as duplicated requests
     * are most of the time sub-requests of the main one.
     */
    public function __clone()
    {
        $this->query      = clone $this->query;
        $this->request    = clone $this->request;
        $this->attributes = clone $this->attributes;
        $this->cookies    = clone $this->cookies;
        $this->files      = clone $this->files;
        $this->server     = clone $this->server;
        $this->headers    = clone $this->headers;
    }

    /**
     * Returns the request as a string.
     *
     * @return string The request
     */
    public function __toString()
    {
        return
            sprintf('%s %s %s', $this->getMethod(), $this->getRequestUri(), $this->server->get('SERVER_PROTOCOL'))."\r\n".
            $this->headers."\r\n".
            $this->getContent();
    }

    /**
     * Overrides the PHP global variables according to this request instance.
     *
     * It overrides $_GET, $_POST, $_REQUEST, $_SERVER, $_COOKIE.
     * $_FILES is never override, see rfc1867
     *
     * @api
     */
    public function overrideGlobals()
    {
        $_GET = $this->query->all();
        $_POST = $this->request->all();
        $_SERVER = $this->server->all();
        $_COOKIE = $this->cookies->all();

        foreach ($this->headers->all() as $key => $value) {
            $key = strtoupper(str_replace('-', '_', $key));
            if (in_array($key, array('CONTENT_TYPE', 'CONTENT_LENGTH'))) {
                $_SERVER[$key] = implode(', ', $value);
            } else {
                $_SERVER['HTTP_'.$key] = implode(', ', $value);
            }
        }

        $request = array('g' => $_GET, 'p' => $_POST, 'c' => $_COOKIE);

        $requestOrder = ini_get('request_order') ?: ini_get('variables_order');
        $requestOrder = preg_replace('#[^cgp]#', '', strtolower($requestOrder)) ?: 'gp';

        $_REQUEST = array();
        foreach (str_split($requestOrder) as $order) {
            $_REQUEST = array_merge($_REQUEST, $request[$order]);
        }
    }

    /**
     * Sets a list of trusted proxies.
     *
     * You should only list the reverse proxies that you manage directly.
     *
     * @param array $proxies A list of trusted proxies
     *
     * @api
     */
    public static function setTrustedProxies(array $proxies)
    {
        self::$trustedProxies = $proxies;
    }

    /**
     * Gets the list of trusted proxies.
     *
     * @return array An array of trusted proxies.
     */
    public static function getTrustedProxies()
    {
        return self::$trustedProxies;
    }

    /**
     * Sets a list of trusted host patterns.
     *
     * You should only list the hosts you manage using regexs.
     *
     * @param array $hostPatterns A list of trusted host patterns
     */
    public static function setTrustedHosts(array $hostPatterns)
    {
        self::$trustedHostPatterns = array_map(function ($hostPattern) {
            return sprintf('{%s}i', str_replace('}', '\\}', $hostPattern));
        }, $hostPatterns);
        // we need to reset trusted hosts on trusted host patterns change
        self::$trustedHosts = array();
    }

    /**
     * Gets the list of trusted host patterns.
     *
     * @return array An array of trusted host patterns.
     */
    public static function getTrustedHosts()
    {
        return self::$trustedHostPatterns;
    }

    /**
     * Sets the name for trusted headers.
     *
     * The following header keys are supported:
     *
     *  * Request::HEADER_CLIENT_IP:    defaults to X-Forwarded-For   (see getClientIp())
     *  * Request::HEADER_CLIENT_HOST:  defaults to X-Forwarded-Host  (see getClientHost())
     *  * Request::HEADER_CLIENT_PORT:  defaults to X-Forwarded-Port  (see getClientPort())
     *  * Request::HEADER_CLIENT_PROTO: defaults to X-Forwarded-Proto (see getScheme() and isSecure())
     *
     * Setting an empty value allows to disable the trusted header for the given key.
     *
     * @param string $key   The header key
     * @param string $value The header name
     *
     * @throws \InvalidArgumentException
     */
    public static function setTrustedHeaderName($key, $value)
    {
        if (!array_key_exists($key, self::$trustedHeaders)) {
            throw new \InvalidArgumentException(sprintf('Unable to set the trusted header name for key "%s".', $key));
        }

        self::$trustedHeaders[$key] = $value;
    }

    /**
     * Gets the trusted proxy header name.
     *
     * @param string $key The header key
     *
     * @return string The header name
     *
     * @throws \InvalidArgumentException
     */
    public static function getTrustedHeaderName($key)
    {
        if (!array_key_exists($key, self::$trustedHeaders)) {
            throw new \InvalidArgumentException(sprintf('Unable to get the trusted header name for key "%s".', $key));
        }

        return self::$trustedHeaders[$key];
    }

    /**
     * Normalizes a query string.
     *
     * It builds a normalized query string, where keys/value pairs are alphabetized,
     * have consistent escaping and unneeded delimiters are removed.
     *
     * @param string $qs Query string
     *
     * @return string A normalized query string for the Request
     */
    public static function normalizeQueryString($qs)
    {
        if ('' == $qs) {
            return '';
        }

        $parts = array();
        $order = array();

        foreach (explode('&', $qs) as $param) {
            if ('' === $param || '=' === $param[0]) {
                // Ignore useless delimiters, e.g. "x=y&".
                // Also ignore pairs with empty key, even if there was a value, e.g. "=value", as such nameless values cannot be retrieved anyway.
                // PHP also does not include them when building _GET.
                continue;
            }

            $keyValuePair = explode('=', $param, 2);

            // GET parameters, that are submitted from a HTML form, encode spaces as "+" by default (as defined in enctype application/x-www-form-urlencoded).
            // PHP also converts "+" to spaces when filling the global _GET or when using the function parse_str. This is why we use urldecode and then normalize to
            // RFC 3986 with rawurlencode.
            $parts[] = isset($keyValuePair[1]) ?
                rawurlencode(urldecode($keyValuePair[0])).'='.rawurlencode(urldecode($keyValuePair[1])) :
                rawurlencode(urldecode($keyValuePair[0]));
            $order[] = urldecode($keyValuePair[0]);
        }

        array_multisort($order, SORT_ASC, $parts);

        return implode('&', $parts);
    }

    /**
     * Enables support for the _method request parameter to determine the intended HTTP method.
     *
     * Be warned that enabling this feature might lead to CSRF issues in your code.
     * Check that you are using CSRF tokens when required.
     *
     * The HTTP method can only be overridden when the real HTTP method is POST.
     */
    public static function enableHttpMethodParameterOverride()
    {
        self::$httpMethodParameterOverride = true;
    }

    /**
     * Checks whether support for the _method request parameter is enabled.
     *
     * @return Boolean True when the _method request parameter is enabled, false otherwise
     */
    public static function getHttpMethodParameterOverride()
    {
        return self::$httpMethodParameterOverride;
    }

    /**
     * Gets a "parameter" value.
     *
     * This method is mainly useful for libraries that want to provide some flexibility.
     *
     * Order of precedence: GET, PATH, POST
     *
     * Avoid using this method in controllers:
     *
     *  * slow
     *  * prefer to get from a "named" source
     *
     * It is better to explicitly get request parameters from the appropriate
     * public property instead (query, attributes, request).
     *
     * @param string  $key     the key
     * @param mixed   $default the default value
     * @param Boolean $deep    is parameter deep in multidimensional array
     *
     * @return mixed
     */
    public function get($key, $default = null, $deep = false)
    {
        return $this->query->get($key, $this->attributes->get($key, $this->request->get($key, $default, $deep), $deep), $deep);
    }

    /**
     * Gets the Session.
     *
     * @return SessionInterface|null The session
     *
     * @api
     */
    public function getSession()
    {
        return $this->session;
    }

    /**
     * Whether the request contains a Session which was started in one of the
     * previous requests.
     *
     * @return Boolean
     *
     * @api
     */
    public function hasPreviousSession()
    {
        // the check for $this->session avoids malicious users trying to fake a session cookie with proper name
        return $this->hasSession() && $this->cookies->has($this->session->getName());
    }

    /**
     * Whether the request contains a Session object.
     *
     * This method does not give any information about the state of the session object,
     * like whether the session is started or not. It is just a way to check if this Request
     * is associated with a Session instance.
     *
     * @return Boolean true when the Request contains a Session object, false otherwise
     *
     * @api
     */
    public function hasSession()
    {
        return null !== $this->session;
    }

    /**
     * Sets the Session.
     *
     * @param SessionInterface $session The Session
     *
     * @api
     */
    public function setSession(SessionInterface $session)
    {
        $this->session = $session;
    }

    /**
     * Returns the client IP addresses.
     *
     * In the returned array the most trusted IP address is first, and the
     * least trusted one last. The "real" client IP address is the last one,
     * but this is also the least trusted one. Trusted proxies are stripped.
     *
     * Use this method carefully; you should use getClientIp() instead.
     *
     * @return array The client IP addresses
     *
     * @see getClientIp()
     */
    public function getClientIps()
    {
        $ip = $this->server->get('REMOTE_ADDR');

        if (!self::$trustedProxies) {
            return array($ip);
        }

        if (!self::$trustedHeaders[self::HEADER_CLIENT_IP] || !$this->headers->has(self::$trustedHeaders[self::HEADER_CLIENT_IP])) {
            return array($ip);
        }

        $clientIps = array_map('trim', explode(',', $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_IP])));
        $clientIps[] = $ip; // Complete the IP chain with the IP the request actually came from

        $ip = $clientIps[0]; // Fallback to this when the client IP falls into the range of trusted proxies

        // Eliminate all IPs from the forwarded IP chain which are trusted proxies
        foreach ($clientIps as $key => $clientIp) {
            if (IpUtils::checkIp($clientIp, self::$trustedProxies)) {
                unset($clientIps[$key]);
            }
        }

        // Now the IP chain contains only untrusted proxies and the client IP
        return $clientIps ? array_reverse($clientIps) : array($ip);
    }

    /**
     * Returns the client IP address.
     *
     * This method can read the client IP address from the "X-Forwarded-For" header
     * when trusted proxies were set via "setTrustedProxies()". The "X-Forwarded-For"
     * header value is a comma+space separated list of IP addresses, the left-most
     * being the original client, and each successive proxy that passed the request
     * adding the IP address where it received the request from.
     *
     * If your reverse proxy uses a different header name than "X-Forwarded-For",
     * ("Client-Ip" for instance), configure it via "setTrustedHeaderName()" with
     * the "client-ip" key.
     *
     * @return string The client IP address
     *
     * @see getClientIps()
     * @see http://en.wikipedia.org/wiki/X-Forwarded-For
     *
     * @api
     */
    public function getClientIp()
    {
        $ipAddresses = $this->getClientIps();

        return $ipAddresses[0];
    }

    /**
     * Returns current script name.
     *
     * @return string
     *
     * @api
     */
    public function getScriptName()
    {
        return $this->server->get('SCRIPT_NAME', $this->server->get('ORIG_SCRIPT_NAME', ''));
    }

    /**
     * Returns the path being requested relative to the executed script.
     *
     * The path info always starts with a /.
     *
     * Suppose this request is instantiated from /mysite on localhost:
     *
     *  * http://localhost/mysite              returns an empty string
     *  * http://localhost/mysite/about        returns '/about'
     *  * http://localhost/mysite/enco%20ded   returns '/enco%20ded'
     *  * http://localhost/mysite/about?var=1  returns '/about'
     *
     * @return string The raw path (i.e. not urldecoded)
     *
     * @api
     */
    public function getPathInfo()
    {
        if (null === $this->pathInfo) {
            $this->pathInfo = $this->preparePathInfo();
        }

        return $this->pathInfo;
    }

    /**
     * Returns the root path from which this request is executed.
     *
     * Suppose that an index.php file instantiates this request object:
     *
     *  * http://localhost/index.php         returns an empty string
     *  * http://localhost/index.php/page    returns an empty string
     *  * http://localhost/web/index.php     returns '/web'
     *  * http://localhost/we%20b/index.php  returns '/we%20b'
     *
     * @return string The raw path (i.e. not urldecoded)
     *
     * @api
     */
    public function getBasePath()
    {
        if (null === $this->basePath) {
            $this->basePath = $this->prepareBasePath();
        }

        return $this->basePath;
    }

    /**
     * Returns the root URL from which this request is executed.
     *
     * The base URL never ends with a /.
     *
     * This is similar to getBasePath(), except that it also includes the
     * script filename (e.g. index.php) if one exists.
     *
     * @return string The raw URL (i.e. not urldecoded)
     *
     * @api
     */
    public function getBaseUrl()
    {
        if (null === $this->baseUrl) {
            $this->baseUrl = $this->prepareBaseUrl();
        }

        return $this->baseUrl;
    }

    /**
     * Gets the request's scheme.
     *
     * @return string
     *
     * @api
     */
    public function getScheme()
    {
        return $this->isSecure() ? 'https' : 'http';
    }

    /**
     * Returns the port on which the request is made.
     *
     * This method can read the client port from the "X-Forwarded-Port" header
     * when trusted proxies were set via "setTrustedProxies()".
     *
     * The "X-Forwarded-Port" header must contain the client port.
     *
     * If your reverse proxy uses a different header name than "X-Forwarded-Port",
     * configure it via "setTrustedHeaderName()" with the "client-port" key.
     *
     * @return string
     *
     * @api
     */
    public function getPort()
    {
        if (self::$trustedProxies) {
            if (self::$trustedHeaders[self::HEADER_CLIENT_PORT] && $port = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PORT])) {
                return $port;
            }

            if (self::$trustedHeaders[self::HEADER_CLIENT_PROTO] && 'https' === $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PROTO], 'http')) {
                return 443;
            }
        }

        if ($host = $this->headers->get('HOST')) {
            if (false !== $pos = strrpos($host, ':')) {
                return intval(substr($host, $pos + 1));
            }

            return 'https' === $this->getScheme() ? 443 : 80;
        }

        return $this->server->get('SERVER_PORT');
    }

    /**
     * Returns the user.
     *
     * @return string|null
     */
    public function getUser()
    {
        return $this->server->get('PHP_AUTH_USER');
    }

    /**
     * Returns the password.
     *
     * @return string|null
     */
    public function getPassword()
    {
        return $this->server->get('PHP_AUTH_PW');
    }

    /**
     * Gets the user info.
     *
     * @return string A user name and, optionally, scheme-specific information about how to gain authorization to access the server
     */
    public function getUserInfo()
    {
        $userinfo = $this->getUser();

        $pass = $this->getPassword();
        if ('' != $pass) {
            $userinfo .= ":$pass";
        }

        return $userinfo;
    }

    /**
     * Returns the HTTP host being requested.
     *
     * The port name will be appended to the host if it's non-standard.
     *
     * @return string
     *
     * @api
     */
    public function getHttpHost()
    {
        $scheme = $this->getScheme();
        $port   = $this->getPort();

        if (('http' == $scheme && $port == 80) || ('https' == $scheme && $port == 443)) {
            return $this->getHost();
        }

        return $this->getHost().':'.$port;
    }

    /**
     * Returns the requested URI.
     *
     * @return string The raw URI (i.e. not urldecoded)
     *
     * @api
     */
    public function getRequestUri()
    {
        if (null === $this->requestUri) {
            $this->requestUri = $this->prepareRequestUri();
        }

        return $this->requestUri;
    }

    /**
     * Gets the scheme and HTTP host.
     *
     * If the URL was called with basic authentication, the user
     * and the password are not added to the generated string.
     *
     * @return string The scheme and HTTP host
     */
    public function getSchemeAndHttpHost()
    {
        return $this->getScheme().'://'.$this->getHttpHost();
    }

    /**
     * Generates a normalized URI for the Request.
     *
     * @return string A normalized URI for the Request
     *
     * @see getQueryString()
     *
     * @api
     */
    public function getUri()
    {
        if (null !== $qs = $this->getQueryString()) {
            $qs = '?'.$qs;
        }

        return $this->getSchemeAndHttpHost().$this->getBaseUrl().$this->getPathInfo().$qs;
    }

    /**
     * Generates a normalized URI for the given path.
     *
     * @param string $path A path to use instead of the current one
     *
     * @return string The normalized URI for the path
     *
     * @api
     */
    public function getUriForPath($path)
    {
        return $this->getSchemeAndHttpHost().$this->getBaseUrl().$path;
    }

    /**
     * Generates the normalized query string for the Request.
     *
     * It builds a normalized query string, where keys/value pairs are alphabetized
     * and have consistent escaping.
     *
     * @return string|null A normalized query string for the Request
     *
     * @api
     */
    public function getQueryString()
    {
        $qs = static::normalizeQueryString($this->server->get('QUERY_STRING'));

        return '' === $qs ? null : $qs;
    }

    /**
     * Checks whether the request is secure or not.
     *
     * This method can read the client port from the "X-Forwarded-Proto" header
     * when trusted proxies were set via "setTrustedProxies()".
     *
     * The "X-Forwarded-Proto" header must contain the protocol: "https" or "http".
     *
     * If your reverse proxy uses a different header name than "X-Forwarded-Proto"
     * ("SSL_HTTPS" for instance), configure it via "setTrustedHeaderName()" with
     * the "client-proto" key.
     *
     * @return Boolean
     *
     * @api
     */
    public function isSecure()
    {
        if (self::$trustedProxies && self::$trustedHeaders[self::HEADER_CLIENT_PROTO] && $proto = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PROTO])) {
            return in_array(strtolower(current(explode(',', $proto))), array('https', 'on', 'ssl', '1'));
        }

        return 'on' == strtolower($this->server->get('HTTPS')) || 1 == $this->server->get('HTTPS');
    }

    /**
     * Returns the host name.
     *
     * This method can read the client port from the "X-Forwarded-Host" header
     * when trusted proxies were set via "setTrustedProxies()".
     *
     * The "X-Forwarded-Host" header must contain the client host name.
     *
     * If your reverse proxy uses a different header name than "X-Forwarded-Host",
     * configure it via "setTrustedHeaderName()" with the "client-host" key.
     *
     * @return string
     *
     * @throws \UnexpectedValueException when the host name is invalid
     *
     * @api
     */
    public function getHost()
    {
        if (self::$trustedProxies && self::$trustedHeaders[self::HEADER_CLIENT_HOST] && $host = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_HOST])) {
            $elements = explode(',', $host);

            $host = $elements[count($elements) - 1];
        } elseif (!$host = $this->headers->get('HOST')) {
            if (!$host = $this->server->get('SERVER_NAME')) {
                $host = $this->server->get('SERVER_ADDR', '');
            }
        }

        // trim and remove port number from host
        // host is lowercase as per RFC 952/2181
        $host = strtolower(preg_replace('/:\d+$/', '', trim($host)));

        // as the host can come from the user (HTTP_HOST and depending on the configuration, SERVER_NAME too can come from the user)
        // check that it does not contain forbidden characters (see RFC 952 and RFC 2181)
        if ($host && !preg_match('/^\[?(?:[a-zA-Z0-9-:\]_]+\.?)+$/', $host)) {
            throw new \UnexpectedValueException(sprintf('Invalid Host "%s"', $host));
        }

        if (count(self::$trustedHostPatterns) > 0) {
            // to avoid host header injection attacks, you should provide a list of trusted host patterns

            if (in_array($host, self::$trustedHosts)) {
                return $host;
            }

            foreach (self::$trustedHostPatterns as $pattern) {
                if (preg_match($pattern, $host)) {
                    self::$trustedHosts[] = $host;

                    return $host;
                }
            }

            throw new \UnexpectedValueException(sprintf('Untrusted Host "%s"', $host));
        }

        return $host;
    }

    /**
     * Sets the request method.
     *
     * @param string $method
     *
     * @api
     */
    public function setMethod($method)
    {
        $this->method = null;
        $this->server->set('REQUEST_METHOD', $method);
    }

    /**
     * Gets the request "intended" method.
     *
     * If the X-HTTP-Method-Override header is set, and if the method is a POST,
     * then it is used to determine the "real" intended HTTP method.
     *
     * The _method request parameter can also be used to determine the HTTP method,
     * but only if enableHttpMethodParameterOverride() has been called.
     *
     * The method is always an uppercased string.
     *
     * @return string The request method
     *
     * @api
     *
     * @see getRealMethod
     */
    public function getMethod()
    {
        if (null === $this->method) {
            $this->method = strtoupper($this->server->get('REQUEST_METHOD', 'GET'));

            if ('POST' === $this->method) {
                if ($method = $this->headers->get('X-HTTP-METHOD-OVERRIDE')) {
                    $this->method = strtoupper($method);
                } elseif (self::$httpMethodParameterOverride) {
                    $this->method = strtoupper($this->request->get('_method', $this->query->get('_method', 'POST')));
                }
            }
        }

        return $this->method;
    }

    /**
     * Gets the "real" request method.
     *
     * @return string The request method
     *
     * @see getMethod
     */
    public function getRealMethod()
    {
        return strtoupper($this->server->get('REQUEST_METHOD', 'GET'));
    }

    /**
     * Gets the mime type associated with the format.
     *
     * @param string $format The format
     *
     * @return string The associated mime type (null if not found)
     *
     * @api
     */
    public function getMimeType($format)
    {
        if (null === static::$formats) {
            static::initializeFormats();
        }

        return isset(static::$formats[$format]) ? static::$formats[$format][0] : null;
    }

    /**
     * Gets the format associated with the mime type.
     *
     * @param string $mimeType The associated mime type
     *
     * @return string|null The format (null if not found)
     *
     * @api
     */
    public function getFormat($mimeType)
    {
        if (false !== $pos = strpos($mimeType, ';')) {
            $mimeType = substr($mimeType, 0, $pos);
        }

        if (null === static::$formats) {
            static::initializeFormats();
        }

        foreach (static::$formats as $format => $mimeTypes) {
            if (in_array($mimeType, (array) $mimeTypes)) {
                return $format;
            }
        }

        return null;
    }

    /**
     * Associates a format with mime types.
     *
     * @param string       $format    The format
     * @param string|array $mimeTypes The associated mime types (the preferred one must be the first as it will be used as the content type)
     *
     * @api
     */
    public function setFormat($format, $mimeTypes)
    {
        if (null === static::$formats) {
            static::initializeFormats();
        }

        static::$formats[$format] = is_array($mimeTypes) ? $mimeTypes : array($mimeTypes);
    }

    /**
     * Gets the request format.
     *
     * Here is the process to determine the format:
     *
     *  * format defined by the user (with setRequestFormat())
     *  * _format request parameter
     *  * $default
     *
     * @param string $default The default format
     *
     * @return string The request format
     *
     * @api
     */
    public function getRequestFormat($default = 'html')
    {
        if (null === $this->format) {
            $this->format = $this->get('_format', $default);
        }

        return $this->format;
    }

    /**
     * Sets the request format.
     *
     * @param string $format The request format.
     *
     * @api
     */
    public function setRequestFormat($format)
    {
        $this->format = $format;
    }

    /**
     * Gets the format associated with the request.
     *
     * @return string|null The format (null if no content type is present)
     *
     * @api
     */
    public function getContentType()
    {
        return $this->getFormat($this->headers->get('CONTENT_TYPE'));
    }

    /**
     * Sets the default locale.
     *
     * @param string $locale
     *
     * @api
     */
    public function setDefaultLocale($locale)
    {
        $this->defaultLocale = $locale;

        if (null === $this->locale) {
            $this->setPhpDefaultLocale($locale);
        }
    }

    /**
     * Sets the locale.
     *
     * @param string $locale
     *
     * @api
     */
    public function setLocale($locale)
    {
        $this->setPhpDefaultLocale($this->locale = $locale);
    }

    /**
     * Get the locale.
     *
     * @return string
     */
    public function getLocale()
    {
        return null === $this->locale ? $this->defaultLocale : $this->locale;
    }

    /**
     * Checks if the request method is of specified type.
     *
     * @param string $method Uppercase request method (GET, POST etc).
     *
     * @return Boolean
     */
    public function isMethod($method)
    {
        return $this->getMethod() === strtoupper($method);
    }

    /**
     * Checks whether the method is safe or not.
     *
     * @return Boolean
     *
     * @api
     */
    public function isMethodSafe()
    {
        return in_array($this->getMethod(), array('GET', 'HEAD'));
    }

    /**
     * Returns the request body content.
     *
     * @param Boolean $asResource If true, a resource will be returned
     *
     * @return string|resource The request body content or a resource to read the body stream.
     *
     * @throws \LogicException
     */
    public function getContent($asResource = false)
    {
        if (false === $this->content || (true === $asResource && null !== $this->content)) {
            throw new \LogicException('getContent() can only be called once when using the resource return type.');
        }

        if (true === $asResource) {
            $this->content = false;

            return fopen('php://input', 'rb');
        }

        if (null === $this->content) {
            $this->content = file_get_contents('php://input');
        }

        return $this->content;
    }

    /**
     * Gets the Etags.
     *
     * @return array The entity tags
     */
    public function getETags()
    {
        return preg_split('/\s*,\s*/', $this->headers->get('if_none_match'), null, PREG_SPLIT_NO_EMPTY);
    }

    /**
     * @return Boolean
     */
    public function isNoCache()
    {
        return $this->headers->hasCacheControlDirective('no-cache') || 'no-cache' == $this->headers->get('Pragma');
    }

    /**
     * Returns the preferred language.
     *
     * @param array $locales An array of ordered available locales
     *
     * @return string|null The preferred locale
     *
     * @api
     */
    public function getPreferredLanguage(array $locales = null)
    {
        $preferredLanguages = $this->getLanguages();

        if (empty($locales)) {
            return isset($preferredLanguages[0]) ? $preferredLanguages[0] : null;
        }

        if (!$preferredLanguages) {
            return $locales[0];
        }

        $extendedPreferredLanguages = array();
        foreach ($preferredLanguages as $language) {
            $extendedPreferredLanguages[] = $language;
            if (false !== $position = strpos($language, '_')) {
                $superLanguage = substr($language, 0, $position);
                if (!in_array($superLanguage, $preferredLanguages)) {
                    $extendedPreferredLanguages[] = $superLanguage;
                }
            }
        }

        $preferredLanguages = array_values(array_intersect($extendedPreferredLanguages, $locales));

        return isset($preferredLanguages[0]) ? $preferredLanguages[0] : $locales[0];
    }

    /**
     * Gets a list of languages acceptable by the client browser.
     *
     * @return array Languages ordered in the user browser preferences
     *
     * @api
     */
    public function getLanguages()
    {
        if (null !== $this->languages) {
            return $this->languages;
        }

        $languages = AcceptHeader::fromString($this->headers->get('Accept-Language'))->all();
        $this->languages = array();
        foreach (array_keys($languages) as $lang) {
            if (strstr($lang, '-')) {
                $codes = explode('-', $lang);
                if ($codes[0] == 'i') {
                    // Language not listed in ISO 639 that are not variants
                    // of any listed language, which can be registered with the
                    // i-prefix, such as i-cherokee
                    if (count($codes) > 1) {
                        $lang = $codes[1];
                    }
                } else {
                    for ($i = 0, $max = count($codes); $i < $max; $i++) {
                        if ($i == 0) {
                            $lang = strtolower($codes[0]);
                        } else {
                            $lang .= '_'.strtoupper($codes[$i]);
                        }
                    }
                }
            }

            $this->languages[] = $lang;
        }

        return $this->languages;
    }

    /**
     * Gets a list of charsets acceptable by the client browser.
     *
     * @return array List of charsets in preferable order
     *
     * @api
     */
    public function getCharsets()
    {
        if (null !== $this->charsets) {
            return $this->charsets;
        }

        return $this->charsets = array_keys(AcceptHeader::fromString($this->headers->get('Accept-Charset'))->all());
    }

    /**
     * Gets a list of encodings acceptable by the client browser.
     *
     * @return array List of encodings in preferable order
     */
    public function getEncodings()
    {
        if (null !== $this->encodings) {
            return $this->encodings;
        }

        return $this->encodings = array_keys(AcceptHeader::fromString($this->headers->get('Accept-Encoding'))->all());
    }

    /**
     * Gets a list of content types acceptable by the client browser
     *
     * @return array List of content types in preferable order
     *
     * @api
     */
    public function getAcceptableContentTypes()
    {
        if (null !== $this->acceptableContentTypes) {
            return $this->acceptableContentTypes;
        }

        return $this->acceptableContentTypes = array_keys(AcceptHeader::fromString($this->headers->get('Accept'))->all());
    }

    /**
     * Returns true if the request is a XMLHttpRequest.
     *
     * It works if your JavaScript library set an X-Requested-With HTTP header.
     * It is known to work with common JavaScript frameworks:
     * @link http://en.wikipedia.org/wiki/List_of_Ajax_frameworks#JavaScript
     *
     * @return Boolean true if the request is an XMLHttpRequest, false otherwise
     *
     * @api
     */
    public function isXmlHttpRequest()
    {
        return 'XMLHttpRequest' == $this->headers->get('X-Requested-With');
    }

    /*
     * The following methods are derived from code of the Zend Framework (1.10dev - 2010-01-24)
     *
     * Code subject to the new BSD license (http://framework.zend.com/license/new-bsd).
     *
     * Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
     */

    protected function prepareRequestUri()
    {
        $requestUri = '';

        if ($this->headers->has('X_ORIGINAL_URL')) {
            // IIS with Microsoft Rewrite Module
            $requestUri = $this->headers->get('X_ORIGINAL_URL');
            $this->headers->remove('X_ORIGINAL_URL');
            $this->server->remove('HTTP_X_ORIGINAL_URL');
            $this->server->remove('UNENCODED_URL');
            $this->server->remove('IIS_WasUrlRewritten');
        } elseif ($this->headers->has('X_REWRITE_URL')) {
            // IIS with ISAPI_Rewrite
            $requestUri = $this->headers->get('X_REWRITE_URL');
            $this->headers->remove('X_REWRITE_URL');
        } elseif ($this->server->get('IIS_WasUrlRewritten') == '1' && $this->server->get('UNENCODED_URL') != '') {
            // IIS7 with URL Rewrite: make sure we get the unencoded URL (double slash problem)
            $requestUri = $this->server->get('UNENCODED_URL');
            $this->server->remove('UNENCODED_URL');
            $this->server->remove('IIS_WasUrlRewritten');
        } elseif ($this->server->has('REQUEST_URI')) {
            $requestUri = $this->server->get('REQUEST_URI');
            // HTTP proxy reqs setup request URI with scheme and host [and port] + the URL path, only use URL path
            $schemeAndHttpHost = $this->getSchemeAndHttpHost();
            if (strpos($requestUri, $schemeAndHttpHost) === 0) {
                $requestUri = substr($requestUri, strlen($schemeAndHttpHost));
            }
        } elseif ($this->server->has('ORIG_PATH_INFO')) {
            // IIS 5.0, PHP as CGI
            $requestUri = $this->server->get('ORIG_PATH_INFO');
            if ('' != $this->server->get('QUERY_STRING')) {
                $requestUri .= '?'.$this->server->get('QUERY_STRING');
            }
            $this->server->remove('ORIG_PATH_INFO');
        }

        // normalize the request URI to ease creating sub-requests from this request
        $this->server->set('REQUEST_URI', $requestUri);

        return $requestUri;
    }

    /**
     * Prepares the base URL.
     *
     * @return string
     */
    protected function prepareBaseUrl()
    {
        $filename = basename($this->server->get('SCRIPT_FILENAME'));

        if (basename($this->server->get('SCRIPT_NAME')) === $filename) {
            $baseUrl = $this->server->get('SCRIPT_NAME');
        } elseif (basename($this->server->get('PHP_SELF')) === $filename) {
            $baseUrl = $this->server->get('PHP_SELF');
        } elseif (basename($this->server->get('ORIG_SCRIPT_NAME')) === $filename) {
            $baseUrl = $this->server->get('ORIG_SCRIPT_NAME'); // 1and1 shared hosting compatibility
        } else {
            // Backtrack up the script_filename to find the portion matching
            // php_self
            $path    = $this->server->get('PHP_SELF', '');
            $file    = $this->server->get('SCRIPT_FILENAME', '');
            $segs    = explode('/', trim($file, '/'));
            $segs    = array_reverse($segs);
            $index   = 0;
            $last    = count($segs);
            $baseUrl = '';
            do {
                $seg     = $segs[$index];
                $baseUrl = '/'.$seg.$baseUrl;
                ++$index;
            } while ($last > $index && (false !== $pos = strpos($path, $baseUrl)) && 0 != $pos);
        }

        // Does the baseUrl have anything in common with the request_uri?
        $requestUri = $this->getRequestUri();

        if ($baseUrl && false !== $prefix = $this->getUrlencodedPrefix($requestUri, $baseUrl)) {
            // full $baseUrl matches
            return $prefix;
        }

        if ($baseUrl && false !== $prefix = $this->getUrlencodedPrefix($requestUri, dirname($baseUrl))) {
            // directory portion of $baseUrl matches
            return rtrim($prefix, '/');
        }

        $truncatedRequestUri = $requestUri;
        if (false !== $pos = strpos($requestUri, '?')) {
            $truncatedRequestUri = substr($requestUri, 0, $pos);
        }

        $basename = basename($baseUrl);
        if (empty($basename) || !strpos(rawurldecode($truncatedRequestUri), $basename)) {
            // no match whatsoever; set it blank
            return '';
        }

        // If using mod_rewrite or ISAPI_Rewrite strip the script filename
        // out of baseUrl. $pos !== 0 makes sure it is not matching a value
        // from PATH_INFO or QUERY_STRING
        if (strlen($requestUri) >= strlen($baseUrl) && (false !== $pos = strpos($requestUri, $baseUrl)) && $pos !== 0) {
            $baseUrl = substr($requestUri, 0, $pos + strlen($baseUrl));
        }

        return rtrim($baseUrl, '/');
    }

    /**
     * Prepares the base path.
     *
     * @return string base path
     */
    protected function prepareBasePath()
    {
        $filename = basename($this->server->get('SCRIPT_FILENAME'));
        $baseUrl = $this->getBaseUrl();
        if (empty($baseUrl)) {
            return '';
        }

        if (basename($baseUrl) === $filename) {
            $basePath = dirname($baseUrl);
        } else {
            $basePath = $baseUrl;
        }

        if ('\\' === DIRECTORY_SEPARATOR) {
            $basePath = str_replace('\\', '/', $basePath);
        }

        return rtrim($basePath, '/');
    }

    /**
     * Prepares the path info.
     *
     * @return string path info
     */
    protected function preparePathInfo()
    {
        $baseUrl = $this->getBaseUrl();

        if (null === ($requestUri = $this->getRequestUri())) {
            return '/';
        }

        $pathInfo = '/';

        // Remove the query string from REQUEST_URI
        if ($pos = strpos($requestUri, '?')) {
            $requestUri = substr($requestUri, 0, $pos);
        }

        if (null !== $baseUrl && false === $pathInfo = substr($requestUri, strlen($baseUrl))) {
            // If substr() returns false then PATH_INFO is set to an empty string
            return '/';
        } elseif (null === $baseUrl) {
            return $requestUri;
        }

        return (string) $pathInfo;
    }

    /**
     * Initializes HTTP request formats.
     */
    protected static function initializeFormats()
    {
        static::$formats = array(
            'html' => array('text/html', 'application/xhtml+xml'),
            'txt'  => array('text/plain'),
            'js'   => array('application/javascript', 'application/x-javascript', 'text/javascript'),
            'css'  => array('text/css'),
            'json' => array('application/json', 'application/x-json'),
            'xml'  => array('text/xml', 'application/xml', 'application/x-xml'),
            'rdf'  => array('application/rdf+xml'),
            'atom' => array('application/atom+xml'),
            'rss'  => array('application/rss+xml'),
        );
    }

    /**
     * Sets the default PHP locale.
     *
     * @param string $locale
     */
    private function setPhpDefaultLocale($locale)
    {
        // if either the class Locale doesn't exist, or an exception is thrown when
        // setting the default locale, the intl module is not installed, and
        // the call can be ignored:
        try {
            if (class_exists('Locale', false)) {
                \Locale::setDefault($locale);
            }
        } catch (\Exception $e) {
        }
    }

    /*
     * Returns the prefix as encoded in the string when the string starts with
     * the given prefix, false otherwise.
     *
     * @param string $string The urlencoded string
     * @param string $prefix The prefix not encoded
     *
     * @return string|false The prefix as it is encoded in $string, or false
     */
    private function getUrlencodedPrefix($string, $prefix)
    {
        if (0 !== strpos(rawurldecode($string), $prefix)) {
            return false;
        }

        $len = strlen($prefix);

        if (preg_match("#^(%[[:xdigit:]]{2}|.){{$len}}#", $string, $match)) {
            return $match[0];
        }

        return false;
    }

    private static function createRequestFromFactory(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null)
    {
        if (self::$requestFactory) {
            $request = call_user_func(self::$requestFactory, $query, $request, $attributes, $cookies, $files, $server, $content);

            if (!$request instanceof Request) {
                throw new \LogicException('The Request factory must return an instance of Symfony\Component\HttpFoundation\Request.');
            }

            return $request;
        }

        return new static($query, $request, $attributes, $cookies, $files, $server, $content);
    }
}
PK��Zd�}޷%�%7Symfony/Component/HttpFoundation/BinaryFileResponse.phpnu�[���<?php

/**
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation;

use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\Exception\FileException;

/**
 * BinaryFileResponse represents an HTTP response delivering a file.
 *
 * @author Niklas Fiekas <niklas.fiekas@tu-clausthal.de>
 * @author stealth35 <stealth35-php@live.fr>
 * @author Igor Wiedler <igor@wiedler.ch>
 * @author Jordan Alliot <jordan.alliot@gmail.com>
 * @author Sergey Linnik <linniksa@gmail.com>
 */
class BinaryFileResponse extends Response
{
    protected static $trustXSendfileTypeHeader = false;

    protected $file;
    protected $offset;
    protected $maxlen;

    /**
     * Constructor.
     *
     * @param \SplFileInfo|string $file               The file to stream
     * @param integer             $status             The response status code
     * @param array               $headers            An array of response headers
     * @param boolean             $public             Files are public by default
     * @param null|string         $contentDisposition The type of Content-Disposition to set automatically with the filename
     * @param boolean             $autoEtag           Whether the ETag header should be automatically set
     * @param boolean             $autoLastModified   Whether the Last-Modified header should be automatically set
     */
    public function __construct($file, $status = 200, $headers = array(), $public = true, $contentDisposition = null, $autoEtag = false, $autoLastModified = true)
    {
        parent::__construct(null, $status, $headers);

        $this->setFile($file, $contentDisposition, $autoEtag, $autoLastModified);

        if ($public) {
            $this->setPublic();
        }
    }

    /**
     * @param \SplFileInfo|string $file               The file to stream
     * @param integer             $status             The response status code
     * @param array               $headers            An array of response headers
     * @param boolean             $public             Files are public by default
     * @param null|string         $contentDisposition The type of Content-Disposition to set automatically with the filename
     * @param boolean             $autoEtag           Whether the ETag header should be automatically set
     * @param boolean             $autoLastModified   Whether the Last-Modified header should be automatically set
     */
    public static function create($file = null, $status = 200, $headers = array(), $public = true, $contentDisposition = null, $autoEtag = false, $autoLastModified = true)
    {
        return new static($file, $status, $headers, $public, $contentDisposition, $autoEtag, $autoLastModified);
    }

    /**
     * Sets the file to stream.
     *
     * @param \SplFileInfo|string $file The file to stream
     * @param string              $contentDisposition
     * @param Boolean             $autoEtag
     * @param Boolean             $autoLastModified
     *
     * @return BinaryFileResponse
     *
     * @throws FileException
     */
    public function setFile($file, $contentDisposition = null, $autoEtag = false, $autoLastModified = true)
    {
        $file = new File((string) $file);

        if (!$file->isReadable()) {
            throw new FileException('File must be readable.');
        }

        $this->file = $file;

        if ($autoEtag) {
            $this->setAutoEtag();
        }

        if ($autoLastModified) {
            $this->setAutoLastModified();
        }

        if ($contentDisposition) {
            $this->setContentDisposition($contentDisposition);
        }

        return $this;
    }

    /**
     * Gets the file.
     *
     * @return File The file to stream
     */
    public function getFile()
    {
        return $this->file;
    }

    /**
     * Automatically sets the Last-Modified header according the file modification date.
     */
    public function setAutoLastModified()
    {
        $this->setLastModified(\DateTime::createFromFormat('U', $this->file->getMTime()));

        return $this;
    }

    /**
     * Automatically sets the ETag header according to the checksum of the file.
     */
    public function setAutoEtag()
    {
        $this->setEtag(sha1_file($this->file->getPathname()));

        return $this;
    }

    /**
     * Sets the Content-Disposition header with the given filename.
     *
     * @param string $disposition      ResponseHeaderBag::DISPOSITION_INLINE or ResponseHeaderBag::DISPOSITION_ATTACHMENT
     * @param string $filename         Optionally use this filename instead of the real name of the file
     * @param string $filenameFallback A fallback filename, containing only ASCII characters. Defaults to an automatically encoded filename
     *
     * @return BinaryFileResponse
     */
    public function setContentDisposition($disposition, $filename = '', $filenameFallback = '')
    {
        if ($filename === '') {
            $filename = $this->file->getFilename();
        }

        $dispositionHeader = $this->headers->makeDisposition($disposition, $filename, $filenameFallback);
        $this->headers->set('Content-Disposition', $dispositionHeader);

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function prepare(Request $request)
    {
        $this->headers->set('Content-Length', $this->file->getSize());
        $this->headers->set('Accept-Ranges', 'bytes');
        $this->headers->set('Content-Transfer-Encoding', 'binary');

        if (!$this->headers->has('Content-Type')) {
            $this->headers->set('Content-Type', $this->file->getMimeType() ?: 'application/octet-stream');
        }

        if ('HTTP/1.0' != $request->server->get('SERVER_PROTOCOL')) {
            $this->setProtocolVersion('1.1');
        }

        $this->ensureIEOverSSLCompatibility($request);

        $this->offset = 0;
        $this->maxlen = -1;

        if (self::$trustXSendfileTypeHeader && $request->headers->has('X-Sendfile-Type')) {
            // Use X-Sendfile, do not send any content.
            $type = $request->headers->get('X-Sendfile-Type');
            $path = $this->file->getRealPath();
            if (strtolower($type) == 'x-accel-redirect') {
                // Do X-Accel-Mapping substitutions.
                foreach (explode(',', $request->headers->get('X-Accel-Mapping', '')) as $mapping) {
                    $mapping = explode('=', $mapping, 2);

                    if (2 == count($mapping)) {
                        $location = trim($mapping[0]);
                        $pathPrefix = trim($mapping[1]);

                        if (substr($path, 0, strlen($pathPrefix)) == $pathPrefix) {
                            $path = $location.substr($path, strlen($pathPrefix));
                            break;
                        }
                    }
                }
            }
            $this->headers->set($type, $path);
            $this->maxlen = 0;
        } elseif ($request->headers->has('Range')) {
            // Process the range headers.
            if (!$request->headers->has('If-Range') || $this->getEtag() == $request->headers->get('If-Range')) {
                $range = $request->headers->get('Range');
                $fileSize = $this->file->getSize();

                list($start, $end) = explode('-', substr($range, 6), 2) + array(0);

                $end = ('' === $end) ? $fileSize - 1 : (int) $end;

                if ('' === $start) {
                    $start = $fileSize - $end;
                    $end = $fileSize - 1;
                } else {
                    $start = (int) $start;
                }

                if ($start <= $end) {
                    if ($start < 0 || $end > $fileSize - 1) {
                        $this->setStatusCode(416);
                    } elseif ($start !== 0 || $end !== $fileSize - 1) {
                        $this->maxlen = $end < $fileSize ? $end - $start + 1 : -1;
                        $this->offset = $start;

                        $this->setStatusCode(206);
                        $this->headers->set('Content-Range', sprintf('bytes %s-%s/%s', $start, $end, $fileSize));
                        $this->headers->set('Content-Length', $end - $start + 1);
                    }
                }
            }
        }

        return $this;
    }

    /**
     * Sends the file.
     */
    public function sendContent()
    {
        if (!$this->isSuccessful()) {
            parent::sendContent();

            return;
        }

        if (0 === $this->maxlen) {
            return;
        }

        $out = fopen('php://output', 'wb');
        $file = fopen($this->file->getPathname(), 'rb');

        stream_copy_to_stream($file, $out, $this->maxlen, $this->offset);

        fclose($out);
        fclose($file);
    }

    /**
     * {@inheritdoc}
     *
     * @throws \LogicException when the content is not null
     */
    public function setContent($content)
    {
        if (null !== $content) {
            throw new \LogicException('The content cannot be set on a BinaryFileResponse instance.');
        }
    }

    /**
     * {@inheritdoc}
     *
     * @return false
     */
    public function getContent()
    {
        return false;
    }

    /**
     * Trust X-Sendfile-Type header.
     */
    public static function trustXSendfileTypeHeader()
    {
        self::$trustXSendfileTypeHeader = true;
    }
}
PK��Z���pߋߋ-Symfony/Component/HttpFoundation/Response.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation;

/**
 * Response represents an HTTP response.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class Response
{
    const HTTP_CONTINUE = 100;
    const HTTP_SWITCHING_PROTOCOLS = 101;
    const HTTP_PROCESSING = 102;            // RFC2518
    const HTTP_OK = 200;
    const HTTP_CREATED = 201;
    const HTTP_ACCEPTED = 202;
    const HTTP_NON_AUTHORITATIVE_INFORMATION = 203;
    const HTTP_NO_CONTENT = 204;
    const HTTP_RESET_CONTENT = 205;
    const HTTP_PARTIAL_CONTENT = 206;
    const HTTP_MULTI_STATUS = 207;          // RFC4918
    const HTTP_ALREADY_REPORTED = 208;      // RFC5842
    const HTTP_IM_USED = 226;               // RFC3229
    const HTTP_MULTIPLE_CHOICES = 300;
    const HTTP_MOVED_PERMANENTLY = 301;
    const HTTP_FOUND = 302;
    const HTTP_SEE_OTHER = 303;
    const HTTP_NOT_MODIFIED = 304;
    const HTTP_USE_PROXY = 305;
    const HTTP_RESERVED = 306;
    const HTTP_TEMPORARY_REDIRECT = 307;
    const HTTP_PERMANENTLY_REDIRECT = 308;  // RFC-reschke-http-status-308-07
    const HTTP_BAD_REQUEST = 400;
    const HTTP_UNAUTHORIZED = 401;
    const HTTP_PAYMENT_REQUIRED = 402;
    const HTTP_FORBIDDEN = 403;
    const HTTP_NOT_FOUND = 404;
    const HTTP_METHOD_NOT_ALLOWED = 405;
    const HTTP_NOT_ACCEPTABLE = 406;
    const HTTP_PROXY_AUTHENTICATION_REQUIRED = 407;
    const HTTP_REQUEST_TIMEOUT = 408;
    const HTTP_CONFLICT = 409;
    const HTTP_GONE = 410;
    const HTTP_LENGTH_REQUIRED = 411;
    const HTTP_PRECONDITION_FAILED = 412;
    const HTTP_REQUEST_ENTITY_TOO_LARGE = 413;
    const HTTP_REQUEST_URI_TOO_LONG = 414;
    const HTTP_UNSUPPORTED_MEDIA_TYPE = 415;
    const HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
    const HTTP_EXPECTATION_FAILED = 417;
    const HTTP_I_AM_A_TEAPOT = 418;                                               // RFC2324
    const HTTP_UNPROCESSABLE_ENTITY = 422;                                        // RFC4918
    const HTTP_LOCKED = 423;                                                      // RFC4918
    const HTTP_FAILED_DEPENDENCY = 424;                                           // RFC4918
    const HTTP_RESERVED_FOR_WEBDAV_ADVANCED_COLLECTIONS_EXPIRED_PROPOSAL = 425;   // RFC2817
    const HTTP_UPGRADE_REQUIRED = 426;                                            // RFC2817
    const HTTP_PRECONDITION_REQUIRED = 428;                                       // RFC6585
    const HTTP_TOO_MANY_REQUESTS = 429;                                           // RFC6585
    const HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431;                             // RFC6585
    const HTTP_INTERNAL_SERVER_ERROR = 500;
    const HTTP_NOT_IMPLEMENTED = 501;
    const HTTP_BAD_GATEWAY = 502;
    const HTTP_SERVICE_UNAVAILABLE = 503;
    const HTTP_GATEWAY_TIMEOUT = 504;
    const HTTP_VERSION_NOT_SUPPORTED = 505;
    const HTTP_VARIANT_ALSO_NEGOTIATES_EXPERIMENTAL = 506;                        // RFC2295
    const HTTP_INSUFFICIENT_STORAGE = 507;                                        // RFC4918
    const HTTP_LOOP_DETECTED = 508;                                               // RFC5842
    const HTTP_NOT_EXTENDED = 510;                                                // RFC2774
    const HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511;                             // RFC6585

    /**
     * @var \Symfony\Component\HttpFoundation\ResponseHeaderBag
     */
    public $headers;

    /**
     * @var string
     */
    protected $content;

    /**
     * @var string
     */
    protected $version;

    /**
     * @var integer
     */
    protected $statusCode;

    /**
     * @var string
     */
    protected $statusText;

    /**
     * @var string
     */
    protected $charset;

    /**
     * Status codes translation table.
     *
     * The list of codes is complete according to the
     * {@link http://www.iana.org/assignments/http-status-codes/ Hypertext Transfer Protocol (HTTP) Status Code Registry}
     * (last updated 2012-02-13).
     *
     * Unless otherwise noted, the status code is defined in RFC2616.
     *
     * @var array
     */
    public static $statusTexts = array(
        100 => 'Continue',
        101 => 'Switching Protocols',
        102 => 'Processing',            // RFC2518
        200 => 'OK',
        201 => 'Created',
        202 => 'Accepted',
        203 => 'Non-Authoritative Information',
        204 => 'No Content',
        205 => 'Reset Content',
        206 => 'Partial Content',
        207 => 'Multi-Status',          // RFC4918
        208 => 'Already Reported',      // RFC5842
        226 => 'IM Used',               // RFC3229
        300 => 'Multiple Choices',
        301 => 'Moved Permanently',
        302 => 'Found',
        303 => 'See Other',
        304 => 'Not Modified',
        305 => 'Use Proxy',
        306 => 'Reserved',
        307 => 'Temporary Redirect',
        308 => 'Permanent Redirect',    // RFC-reschke-http-status-308-07
        400 => 'Bad Request',
        401 => 'Unauthorized',
        402 => 'Payment Required',
        403 => 'Forbidden',
        404 => 'Not Found',
        405 => 'Method Not Allowed',
        406 => 'Not Acceptable',
        407 => 'Proxy Authentication Required',
        408 => 'Request Timeout',
        409 => 'Conflict',
        410 => 'Gone',
        411 => 'Length Required',
        412 => 'Precondition Failed',
        413 => 'Request Entity Too Large',
        414 => 'Request-URI Too Long',
        415 => 'Unsupported Media Type',
        416 => 'Requested Range Not Satisfiable',
        417 => 'Expectation Failed',
        418 => 'I\'m a teapot',                                               // RFC2324
        422 => 'Unprocessable Entity',                                        // RFC4918
        423 => 'Locked',                                                      // RFC4918
        424 => 'Failed Dependency',                                           // RFC4918
        425 => 'Reserved for WebDAV advanced collections expired proposal',   // RFC2817
        426 => 'Upgrade Required',                                            // RFC2817
        428 => 'Precondition Required',                                       // RFC6585
        429 => 'Too Many Requests',                                           // RFC6585
        431 => 'Request Header Fields Too Large',                             // RFC6585
        500 => 'Internal Server Error',
        501 => 'Not Implemented',
        502 => 'Bad Gateway',
        503 => 'Service Unavailable',
        504 => 'Gateway Timeout',
        505 => 'HTTP Version Not Supported',
        506 => 'Variant Also Negotiates (Experimental)',                      // RFC2295
        507 => 'Insufficient Storage',                                        // RFC4918
        508 => 'Loop Detected',                                               // RFC5842
        510 => 'Not Extended',                                                // RFC2774
        511 => 'Network Authentication Required',                             // RFC6585
    );

    /**
     * Constructor.
     *
     * @param mixed   $content The response content, see setContent()
     * @param integer $status  The response status code
     * @param array   $headers An array of response headers
     *
     * @throws \InvalidArgumentException When the HTTP status code is not valid
     *
     * @api
     */
    public function __construct($content = '', $status = 200, $headers = array())
    {
        $this->headers = new ResponseHeaderBag($headers);
        $this->setContent($content);
        $this->setStatusCode($status);
        $this->setProtocolVersion('1.0');
        if (!$this->headers->has('Date')) {
            $this->setDate(new \DateTime(null, new \DateTimeZone('UTC')));
        }
    }

    /**
     * Factory method for chainability
     *
     * Example:
     *
     *     return Response::create($body, 200)
     *         ->setSharedMaxAge(300);
     *
     * @param mixed   $content The response content, see setContent()
     * @param integer $status  The response status code
     * @param array   $headers An array of response headers
     *
     * @return Response
     */
    public static function create($content = '', $status = 200, $headers = array())
    {
        return new static($content, $status, $headers);
    }

    /**
     * Returns the Response as an HTTP string.
     *
     * The string representation of the Response is the same as the
     * one that will be sent to the client only if the prepare() method
     * has been called before.
     *
     * @return string The Response as an HTTP string
     *
     * @see prepare()
     */
    public function __toString()
    {
        return
            sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText)."\r\n".
            $this->headers."\r\n".
            $this->getContent();
    }

    /**
     * Clones the current Response instance.
     */
    public function __clone()
    {
        $this->headers = clone $this->headers;
    }

    /**
     * Prepares the Response before it is sent to the client.
     *
     * This method tweaks the Response to ensure that it is
     * compliant with RFC 2616. Most of the changes are based on
     * the Request that is "associated" with this Response.
     *
     * @param Request $request A Request instance
     *
     * @return Response The current response.
     */
    public function prepare(Request $request)
    {
        $headers = $this->headers;

        if ($this->isInformational() || in_array($this->statusCode, array(204, 304))) {
            $this->setContent(null);
        }

        // Content-type based on the Request
        if (!$headers->has('Content-Type')) {
            $format = $request->getRequestFormat();
            if (null !== $format && $mimeType = $request->getMimeType($format)) {
                $headers->set('Content-Type', $mimeType);
            }
        }

        // Fix Content-Type
        $charset = $this->charset ?: 'UTF-8';
        if (!$headers->has('Content-Type')) {
            $headers->set('Content-Type', 'text/html; charset='.$charset);
        } elseif (0 === stripos($headers->get('Content-Type'), 'text/') && false === stripos($headers->get('Content-Type'), 'charset')) {
            // add the charset
            $headers->set('Content-Type', $headers->get('Content-Type').'; charset='.$charset);
        }

        // Fix Content-Length
        if ($headers->has('Transfer-Encoding')) {
            $headers->remove('Content-Length');
        }

        if ($request->isMethod('HEAD')) {
            // cf. RFC2616 14.13
            $length = $headers->get('Content-Length');
            $this->setContent(null);
            if ($length) {
                $headers->set('Content-Length', $length);
            }
        }

        // Fix protocol
        if ('HTTP/1.0' != $request->server->get('SERVER_PROTOCOL')) {
            $this->setProtocolVersion('1.1');
        }

        // Check if we need to send extra expire info headers
        if ('1.0' == $this->getProtocolVersion() && 'no-cache' == $this->headers->get('Cache-Control')) {
            $this->headers->set('pragma', 'no-cache');
            $this->headers->set('expires', -1);
        }

        $this->ensureIEOverSSLCompatibility($request);

        return $this;
    }

    /**
     * Sends HTTP headers.
     *
     * @return Response
     */
    public function sendHeaders()
    {
        // headers have already been sent by the developer
        if (headers_sent()) {
            return $this;
        }

        // status
        header(sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText), true, $this->statusCode);

        // headers
        foreach ($this->headers->allPreserveCase() as $name => $values) {
            foreach ($values as $value) {
                header($name.': '.$value, false, $this->statusCode);
            }
        }

        // cookies
        foreach ($this->headers->getCookies() as $cookie) {
            setcookie($cookie->getName(), $cookie->getValue(), $cookie->getExpiresTime(), $cookie->getPath(), $cookie->getDomain(), $cookie->isSecure(), $cookie->isHttpOnly());
        }

        return $this;
    }

    /**
     * Sends content for the current web response.
     *
     * @return Response
     */
    public function sendContent()
    {
        echo $this->content;

        return $this;
    }

    /**
     * Sends HTTP headers and content.
     *
     * @return Response
     *
     * @api
     */
    public function send()
    {
        $this->sendHeaders();
        $this->sendContent();

        if (function_exists('fastcgi_finish_request')) {
            fastcgi_finish_request();
        } elseif ('cli' !== PHP_SAPI) {
            // ob_get_level() never returns 0 on some Windows configurations, so if
            // the level is the same two times in a row, the loop should be stopped.
            $previous = null;
            $obStatus = ob_get_status(1);
            while (($level = ob_get_level()) > 0 && $level !== $previous) {
                $previous = $level;
                if ($obStatus[$level - 1]) {
                    if (version_compare(PHP_VERSION, '5.4', '>=')) {
                        if (isset($obStatus[$level - 1]['flags']) && ($obStatus[$level - 1]['flags'] & PHP_OUTPUT_HANDLER_REMOVABLE)) {
                            ob_end_flush();
                        }
                    } else {
                        if (isset($obStatus[$level - 1]['del']) && $obStatus[$level - 1]['del']) {
                            ob_end_flush();
                        }
                    }
                }
            }
            flush();
        }

        return $this;
    }

    /**
     * Sets the response content.
     *
     * Valid types are strings, numbers, null, and objects that implement a __toString() method.
     *
     * @param mixed $content Content that can be cast to string
     *
     * @return Response
     *
     * @throws \UnexpectedValueException
     *
     * @api
     */
    public function setContent($content)
    {
        if (null !== $content && !is_string($content) && !is_numeric($content) && !is_callable(array($content, '__toString'))) {
            throw new \UnexpectedValueException(sprintf('The Response content must be a string or object implementing __toString(), "%s" given.', gettype($content)));
        }

        $this->content = (string) $content;

        return $this;
    }

    /**
     * Gets the current response content.
     *
     * @return string Content
     *
     * @api
     */
    public function getContent()
    {
        return $this->content;
    }

    /**
     * Sets the HTTP protocol version (1.0 or 1.1).
     *
     * @param string $version The HTTP protocol version
     *
     * @return Response
     *
     * @api
     */
    public function setProtocolVersion($version)
    {
        $this->version = $version;

        return $this;
    }

    /**
     * Gets the HTTP protocol version.
     *
     * @return string The HTTP protocol version
     *
     * @api
     */
    public function getProtocolVersion()
    {
        return $this->version;
    }

    /**
     * Sets the response status code.
     *
     * @param integer $code HTTP status code
     * @param mixed   $text HTTP status text
     *
     * If the status text is null it will be automatically populated for the known
     * status codes and left empty otherwise.
     *
     * @return Response
     *
     * @throws \InvalidArgumentException When the HTTP status code is not valid
     *
     * @api
     */
    public function setStatusCode($code, $text = null)
    {
        $this->statusCode = $code = (int) $code;
        if ($this->isInvalid()) {
            throw new \InvalidArgumentException(sprintf('The HTTP status code "%s" is not valid.', $code));
        }

        if (null === $text) {
            $this->statusText = isset(self::$statusTexts[$code]) ? self::$statusTexts[$code] : '';

            return $this;
        }

        if (false === $text) {
            $this->statusText = '';

            return $this;
        }

        $this->statusText = $text;

        return $this;
    }

    /**
     * Retrieves the status code for the current web response.
     *
     * @return integer Status code
     *
     * @api
     */
    public function getStatusCode()
    {
        return $this->statusCode;
    }

    /**
     * Sets the response charset.
     *
     * @param string $charset Character set
     *
     * @return Response
     *
     * @api
     */
    public function setCharset($charset)
    {
        $this->charset = $charset;

        return $this;
    }

    /**
     * Retrieves the response charset.
     *
     * @return string Character set
     *
     * @api
     */
    public function getCharset()
    {
        return $this->charset;
    }

    /**
     * Returns true if the response is worth caching under any circumstance.
     *
     * Responses marked "private" with an explicit Cache-Control directive are
     * considered uncacheable.
     *
     * Responses with neither a freshness lifetime (Expires, max-age) nor cache
     * validator (Last-Modified, ETag) are considered uncacheable.
     *
     * @return Boolean true if the response is worth caching, false otherwise
     *
     * @api
     */
    public function isCacheable()
    {
        if (!in_array($this->statusCode, array(200, 203, 300, 301, 302, 404, 410))) {
            return false;
        }

        if ($this->headers->hasCacheControlDirective('no-store') || $this->headers->getCacheControlDirective('private')) {
            return false;
        }

        return $this->isValidateable() || $this->isFresh();
    }

    /**
     * Returns true if the response is "fresh".
     *
     * Fresh responses may be served from cache without any interaction with the
     * origin. A response is considered fresh when it includes a Cache-Control/max-age
     * indicator or Expires header and the calculated age is less than the freshness lifetime.
     *
     * @return Boolean true if the response is fresh, false otherwise
     *
     * @api
     */
    public function isFresh()
    {
        return $this->getTtl() > 0;
    }

    /**
     * Returns true if the response includes headers that can be used to validate
     * the response with the origin server using a conditional GET request.
     *
     * @return Boolean true if the response is validateable, false otherwise
     *
     * @api
     */
    public function isValidateable()
    {
        return $this->headers->has('Last-Modified') || $this->headers->has('ETag');
    }

    /**
     * Marks the response as "private".
     *
     * It makes the response ineligible for serving other clients.
     *
     * @return Response
     *
     * @api
     */
    public function setPrivate()
    {
        $this->headers->removeCacheControlDirective('public');
        $this->headers->addCacheControlDirective('private');

        return $this;
    }

    /**
     * Marks the response as "public".
     *
     * It makes the response eligible for serving other clients.
     *
     * @return Response
     *
     * @api
     */
    public function setPublic()
    {
        $this->headers->addCacheControlDirective('public');
        $this->headers->removeCacheControlDirective('private');

        return $this;
    }

    /**
     * Returns true if the response must be revalidated by caches.
     *
     * This method indicates that the response must not be served stale by a
     * cache in any circumstance without first revalidating with the origin.
     * When present, the TTL of the response should not be overridden to be
     * greater than the value provided by the origin.
     *
     * @return Boolean true if the response must be revalidated by a cache, false otherwise
     *
     * @api
     */
    public function mustRevalidate()
    {
        return $this->headers->hasCacheControlDirective('must-revalidate') || $this->headers->has('proxy-revalidate');
    }

    /**
     * Returns the Date header as a DateTime instance.
     *
     * @return \DateTime A \DateTime instance
     *
     * @throws \RuntimeException When the header is not parseable
     *
     * @api
     */
    public function getDate()
    {
        return $this->headers->getDate('Date', new \DateTime());
    }

    /**
     * Sets the Date header.
     *
     * @param \DateTime $date A \DateTime instance
     *
     * @return Response
     *
     * @api
     */
    public function setDate(\DateTime $date)
    {
        $date->setTimezone(new \DateTimeZone('UTC'));
        $this->headers->set('Date', $date->format('D, d M Y H:i:s').' GMT');

        return $this;
    }

    /**
     * Returns the age of the response.
     *
     * @return integer The age of the response in seconds
     */
    public function getAge()
    {
        if (null !== $age = $this->headers->get('Age')) {
            return (int) $age;
        }

        return max(time() - $this->getDate()->format('U'), 0);
    }

    /**
     * Marks the response stale by setting the Age header to be equal to the maximum age of the response.
     *
     * @return Response
     *
     * @api
     */
    public function expire()
    {
        if ($this->isFresh()) {
            $this->headers->set('Age', $this->getMaxAge());
        }

        return $this;
    }

    /**
     * Returns the value of the Expires header as a DateTime instance.
     *
     * @return \DateTime|null A DateTime instance or null if the header does not exist
     *
     * @api
     */
    public function getExpires()
    {
        try {
            return $this->headers->getDate('Expires');
        } catch (\RuntimeException $e) {
            // according to RFC 2616 invalid date formats (e.g. "0" and "-1") must be treated as in the past
            return \DateTime::createFromFormat(DATE_RFC2822, 'Sat, 01 Jan 00 00:00:00 +0000');
        }
    }

    /**
     * Sets the Expires HTTP header with a DateTime instance.
     *
     * Passing null as value will remove the header.
     *
     * @param \DateTime|null $date A \DateTime instance or null to remove the header
     *
     * @return Response
     *
     * @api
     */
    public function setExpires(\DateTime $date = null)
    {
        if (null === $date) {
            $this->headers->remove('Expires');
        } else {
            $date = clone $date;
            $date->setTimezone(new \DateTimeZone('UTC'));
            $this->headers->set('Expires', $date->format('D, d M Y H:i:s').' GMT');
        }

        return $this;
    }

    /**
     * Returns the number of seconds after the time specified in the response's Date
     * header when the response should no longer be considered fresh.
     *
     * First, it checks for a s-maxage directive, then a max-age directive, and then it falls
     * back on an expires header. It returns null when no maximum age can be established.
     *
     * @return integer|null Number of seconds
     *
     * @api
     */
    public function getMaxAge()
    {
        if ($this->headers->hasCacheControlDirective('s-maxage')) {
            return (int) $this->headers->getCacheControlDirective('s-maxage');
        }

        if ($this->headers->hasCacheControlDirective('max-age')) {
            return (int) $this->headers->getCacheControlDirective('max-age');
        }

        if (null !== $this->getExpires()) {
            return $this->getExpires()->format('U') - $this->getDate()->format('U');
        }

        return null;
    }

    /**
     * Sets the number of seconds after which the response should no longer be considered fresh.
     *
     * This methods sets the Cache-Control max-age directive.
     *
     * @param integer $value Number of seconds
     *
     * @return Response
     *
     * @api
     */
    public function setMaxAge($value)
    {
        $this->headers->addCacheControlDirective('max-age', $value);

        return $this;
    }

    /**
     * Sets the number of seconds after which the response should no longer be considered fresh by shared caches.
     *
     * This methods sets the Cache-Control s-maxage directive.
     *
     * @param integer $value Number of seconds
     *
     * @return Response
     *
     * @api
     */
    public function setSharedMaxAge($value)
    {
        $this->setPublic();
        $this->headers->addCacheControlDirective('s-maxage', $value);

        return $this;
    }

    /**
     * Returns the response's time-to-live in seconds.
     *
     * It returns null when no freshness information is present in the response.
     *
     * When the responses TTL is <= 0, the response may not be served from cache without first
     * revalidating with the origin.
     *
     * @return integer|null The TTL in seconds
     *
     * @api
     */
    public function getTtl()
    {
        if (null !== $maxAge = $this->getMaxAge()) {
            return $maxAge - $this->getAge();
        }

        return null;
    }

    /**
     * Sets the response's time-to-live for shared caches.
     *
     * This method adjusts the Cache-Control/s-maxage directive.
     *
     * @param integer $seconds Number of seconds
     *
     * @return Response
     *
     * @api
     */
    public function setTtl($seconds)
    {
        $this->setSharedMaxAge($this->getAge() + $seconds);

        return $this;
    }

    /**
     * Sets the response's time-to-live for private/client caches.
     *
     * This method adjusts the Cache-Control/max-age directive.
     *
     * @param integer $seconds Number of seconds
     *
     * @return Response
     *
     * @api
     */
    public function setClientTtl($seconds)
    {
        $this->setMaxAge($this->getAge() + $seconds);

        return $this;
    }

    /**
     * Returns the Last-Modified HTTP header as a DateTime instance.
     *
     * @return \DateTime|null A DateTime instance or null if the header does not exist
     *
     * @throws \RuntimeException When the HTTP header is not parseable
     *
     * @api
     */
    public function getLastModified()
    {
        return $this->headers->getDate('Last-Modified');
    }

    /**
     * Sets the Last-Modified HTTP header with a DateTime instance.
     *
     * Passing null as value will remove the header.
     *
     * @param \DateTime|null $date A \DateTime instance or null to remove the header
     *
     * @return Response
     *
     * @api
     */
    public function setLastModified(\DateTime $date = null)
    {
        if (null === $date) {
            $this->headers->remove('Last-Modified');
        } else {
            $date = clone $date;
            $date->setTimezone(new \DateTimeZone('UTC'));
            $this->headers->set('Last-Modified', $date->format('D, d M Y H:i:s').' GMT');
        }

        return $this;
    }

    /**
     * Returns the literal value of the ETag HTTP header.
     *
     * @return string|null The ETag HTTP header or null if it does not exist
     *
     * @api
     */
    public function getEtag()
    {
        return $this->headers->get('ETag');
    }

    /**
     * Sets the ETag value.
     *
     * @param string|null $etag The ETag unique identifier or null to remove the header
     * @param Boolean     $weak Whether you want a weak ETag or not
     *
     * @return Response
     *
     * @api
     */
    public function setEtag($etag = null, $weak = false)
    {
        if (null === $etag) {
            $this->headers->remove('Etag');
        } else {
            if (0 !== strpos($etag, '"')) {
                $etag = '"'.$etag.'"';
            }

            $this->headers->set('ETag', (true === $weak ? 'W/' : '').$etag);
        }

        return $this;
    }

    /**
     * Sets the response's cache headers (validation and/or expiration).
     *
     * Available options are: etag, last_modified, max_age, s_maxage, private, and public.
     *
     * @param array $options An array of cache options
     *
     * @return Response
     *
     * @throws \InvalidArgumentException
     *
     * @api
     */
    public function setCache(array $options)
    {
        if ($diff = array_diff(array_keys($options), array('etag', 'last_modified', 'max_age', 's_maxage', 'private', 'public'))) {
            throw new \InvalidArgumentException(sprintf('Response does not support the following options: "%s".', implode('", "', array_values($diff))));
        }

        if (isset($options['etag'])) {
            $this->setEtag($options['etag']);
        }

        if (isset($options['last_modified'])) {
            $this->setLastModified($options['last_modified']);
        }

        if (isset($options['max_age'])) {
            $this->setMaxAge($options['max_age']);
        }

        if (isset($options['s_maxage'])) {
            $this->setSharedMaxAge($options['s_maxage']);
        }

        if (isset($options['public'])) {
            if ($options['public']) {
                $this->setPublic();
            } else {
                $this->setPrivate();
            }
        }

        if (isset($options['private'])) {
            if ($options['private']) {
                $this->setPrivate();
            } else {
                $this->setPublic();
            }
        }

        return $this;
    }

    /**
     * Modifies the response so that it conforms to the rules defined for a 304 status code.
     *
     * This sets the status, removes the body, and discards any headers
     * that MUST NOT be included in 304 responses.
     *
     * @return Response
     *
     * @see http://tools.ietf.org/html/rfc2616#section-10.3.5
     *
     * @api
     */
    public function setNotModified()
    {
        $this->setStatusCode(304);
        $this->setContent(null);

        // remove headers that MUST NOT be included with 304 Not Modified responses
        foreach (array('Allow', 'Content-Encoding', 'Content-Language', 'Content-Length', 'Content-MD5', 'Content-Type', 'Last-Modified') as $header) {
            $this->headers->remove($header);
        }

        return $this;
    }

    /**
     * Returns true if the response includes a Vary header.
     *
     * @return Boolean true if the response includes a Vary header, false otherwise
     *
     * @api
     */
    public function hasVary()
    {
        return null !== $this->headers->get('Vary');
    }

    /**
     * Returns an array of header names given in the Vary header.
     *
     * @return array An array of Vary names
     *
     * @api
     */
    public function getVary()
    {
        if (!$vary = $this->headers->get('Vary', null, false)) {
            return array();
        }

        $ret = array();
        foreach ($vary as $item) {
            $ret = array_merge($ret, preg_split('/[\s,]+/', $item));
        }

        return $ret;
    }

    /**
     * Sets the Vary header.
     *
     * @param string|array $headers
     * @param Boolean      $replace Whether to replace the actual value of not (true by default)
     *
     * @return Response
     *
     * @api
     */
    public function setVary($headers, $replace = true)
    {
        $this->headers->set('Vary', $headers, $replace);

        return $this;
    }

    /**
     * Determines if the Response validators (ETag, Last-Modified) match
     * a conditional value specified in the Request.
     *
     * If the Response is not modified, it sets the status code to 304 and
     * removes the actual content by calling the setNotModified() method.
     *
     * @param Request $request A Request instance
     *
     * @return Boolean true if the Response validators match the Request, false otherwise
     *
     * @api
     */
    public function isNotModified(Request $request)
    {
        if (!$request->isMethodSafe()) {
            return false;
        }

        $lastModified = $request->headers->get('If-Modified-Since');
        $notModified = false;
        if ($etags = $request->getEtags()) {
            $notModified = (in_array($this->getEtag(), $etags) || in_array('*', $etags)) && (!$lastModified || $this->headers->get('Last-Modified') == $lastModified);
        } elseif ($lastModified) {
            $notModified = $lastModified == $this->headers->get('Last-Modified');
        }

        if ($notModified) {
            $this->setNotModified();
        }

        return $notModified;
    }

    // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
    /**
     * Is response invalid?
     *
     * @return Boolean
     *
     * @api
     */
    public function isInvalid()
    {
        return $this->statusCode < 100 || $this->statusCode >= 600;
    }

    /**
     * Is response informative?
     *
     * @return Boolean
     *
     * @api
     */
    public function isInformational()
    {
        return $this->statusCode >= 100 && $this->statusCode < 200;
    }

    /**
     * Is response successful?
     *
     * @return Boolean
     *
     * @api
     */
    public function isSuccessful()
    {
        return $this->statusCode >= 200 && $this->statusCode < 300;
    }

    /**
     * Is the response a redirect?
     *
     * @return Boolean
     *
     * @api
     */
    public function isRedirection()
    {
        return $this->statusCode >= 300 && $this->statusCode < 400;
    }

    /**
     * Is there a client error?
     *
     * @return Boolean
     *
     * @api
     */
    public function isClientError()
    {
        return $this->statusCode >= 400 && $this->statusCode < 500;
    }

    /**
     * Was there a server side error?
     *
     * @return Boolean
     *
     * @api
     */
    public function isServerError()
    {
        return $this->statusCode >= 500 && $this->statusCode < 600;
    }

    /**
     * Is the response OK?
     *
     * @return Boolean
     *
     * @api
     */
    public function isOk()
    {
        return 200 === $this->statusCode;
    }

    /**
     * Is the response forbidden?
     *
     * @return Boolean
     *
     * @api
     */
    public function isForbidden()
    {
        return 403 === $this->statusCode;
    }

    /**
     * Is the response a not found error?
     *
     * @return Boolean
     *
     * @api
     */
    public function isNotFound()
    {
        return 404 === $this->statusCode;
    }

    /**
     * Is the response a redirect of some form?
     *
     * @param string $location
     *
     * @return Boolean
     *
     * @api
     */
    public function isRedirect($location = null)
    {
        return in_array($this->statusCode, array(201, 301, 302, 303, 307, 308)) && (null === $location ?: $location == $this->headers->get('Location'));
    }

    /**
     * Is the response empty?
     *
     * @return Boolean
     *
     * @api
     */
    public function isEmpty()
    {
        return in_array($this->statusCode, array(201, 204, 304));
    }

    /**
     * Check if we need to remove Cache-Control for SSL encrypted downloads when using IE < 9
     *
     * @link http://support.microsoft.com/kb/323308
     */
    protected function ensureIEOverSSLCompatibility(Request $request)
    {
        if (false !== stripos($this->headers->get('Content-Disposition'), 'attachment') && preg_match('/MSIE (.*?);/i', $request->server->get('HTTP_USER_AGENT'), $match) == 1 && true === $request->isSecure()) {
            if (intval(preg_replace("/(MSIE )(.*?);/", "$2", $match[0])) < 9) {
                $this->headers->remove('Cache-Control');
            }
        }
    }
}
PK��Z?`
�y	y	LSymfony/Component/HttpFoundation/Resources/stubs/SessionHandlerInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * SessionHandlerInterface
 *
 * Provides forward compatibility with PHP 5.4
 *
 * Extensive documentation can be found at php.net, see links:
 *
 * @see http://php.net/sessionhandlerinterface
 * @see http://php.net/session.customhandler
 * @see http://php.net/session-set-save-handler
 *
 * @author Drak <drak@zikula.org>
 */
interface SessionHandlerInterface
{
    /**
     * Open session.
     *
     * @see http://php.net/sessionhandlerinterface.open
     *
     * @param string $savePath    Save path.
     * @param string $sessionName Session Name.
     *
     * @throws \RuntimeException If something goes wrong starting the session.
     *
     * @return boolean
     */
    public function open($savePath, $sessionName);

    /**
     * Close session.
     *
     * @see http://php.net/sessionhandlerinterface.close
     *
     * @return boolean
     */
    public function close();

    /**
     * Read session.
     *
     * @param string $sessionId
     *
     * @see http://php.net/sessionhandlerinterface.read
     *
     * @throws \RuntimeException On fatal error but not "record not found".
     *
     * @return string String as stored in persistent storage or empty string in all other cases.
     */
    public function read($sessionId);

    /**
     * Commit session to storage.
     *
     * @see http://php.net/sessionhandlerinterface.write
     *
     * @param string $sessionId Session ID.
     * @param string $data      Session serialized data to save.
     *
     * @return boolean
     */
    public function write($sessionId, $data);

    /**
     * Destroys this session.
     *
     * @see http://php.net/sessionhandlerinterface.destroy
     *
     * @param string $sessionId Session ID.
     *
     * @throws \RuntimeException On fatal error.
     *
     * @return boolean
     */
    public function destroy($sessionId);

    /**
     * Garbage collection for storage.
     *
     * @see http://php.net/sessionhandlerinterface.gc
     *
     * @param integer $lifetime Max lifetime in seconds to keep sessions stored.
     *
     * @throws \RuntimeException On fatal error.
     *
     * @return boolean
     */
    public function gc($lifetime);
}
PK��ZEY���.Symfony/Component/HttpFoundation/HeaderBag.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation;

/**
 * HeaderBag is a container for HTTP headers.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class HeaderBag implements \IteratorAggregate, \Countable
{
    protected $headers = array();
    protected $cacheControl = array();

    /**
     * Constructor.
     *
     * @param array $headers An array of HTTP headers
     *
     * @api
     */
    public function __construct(array $headers = array())
    {
        foreach ($headers as $key => $values) {
            $this->set($key, $values);
        }
    }

    /**
     * Returns the headers as a string.
     *
     * @return string The headers
     */
    public function __toString()
    {
        if (!$this->headers) {
            return '';
        }

        $max = max(array_map('strlen', array_keys($this->headers))) + 1;
        $content = '';
        ksort($this->headers);
        foreach ($this->headers as $name => $values) {
            $name = implode('-', array_map('ucfirst', explode('-', $name)));
            foreach ($values as $value) {
                $content .= sprintf("%-{$max}s %s\r\n", $name.':', $value);
            }
        }

        return $content;
    }

    /**
     * Returns the headers.
     *
     * @return array An array of headers
     *
     * @api
     */
    public function all()
    {
        return $this->headers;
    }

    /**
     * Returns the parameter keys.
     *
     * @return array An array of parameter keys
     *
     * @api
     */
    public function keys()
    {
        return array_keys($this->headers);
    }

    /**
     * Replaces the current HTTP headers by a new set.
     *
     * @param array $headers An array of HTTP headers
     *
     * @api
     */
    public function replace(array $headers = array())
    {
        $this->headers = array();
        $this->add($headers);
    }

    /**
     * Adds new headers the current HTTP headers set.
     *
     * @param array $headers An array of HTTP headers
     *
     * @api
     */
    public function add(array $headers)
    {
        foreach ($headers as $key => $values) {
            $this->set($key, $values);
        }
    }

    /**
     * Returns a header value by name.
     *
     * @param string  $key     The header name
     * @param mixed   $default The default value
     * @param Boolean $first   Whether to return the first value or all header values
     *
     * @return string|array The first header value if $first is true, an array of values otherwise
     *
     * @api
     */
    public function get($key, $default = null, $first = true)
    {
        $key = strtr(strtolower($key), '_', '-');

        if (!array_key_exists($key, $this->headers)) {
            if (null === $default) {
                return $first ? null : array();
            }

            return $first ? $default : array($default);
        }

        if ($first) {
            return count($this->headers[$key]) ? $this->headers[$key][0] : $default;
        }

        return $this->headers[$key];
    }

    /**
     * Sets a header by name.
     *
     * @param string       $key     The key
     * @param string|array $values  The value or an array of values
     * @param Boolean      $replace Whether to replace the actual value or not (true by default)
     *
     * @api
     */
    public function set($key, $values, $replace = true)
    {
        $key = strtr(strtolower($key), '_', '-');

        $values = array_values((array) $values);

        if (true === $replace || !isset($this->headers[$key])) {
            $this->headers[$key] = $values;
        } else {
            $this->headers[$key] = array_merge($this->headers[$key], $values);
        }

        if ('cache-control' === $key) {
            $this->cacheControl = $this->parseCacheControl($values[0]);
        }
    }

    /**
     * Returns true if the HTTP header is defined.
     *
     * @param string $key The HTTP header
     *
     * @return Boolean true if the parameter exists, false otherwise
     *
     * @api
     */
    public function has($key)
    {
        return array_key_exists(strtr(strtolower($key), '_', '-'), $this->headers);
    }

    /**
     * Returns true if the given HTTP header contains the given value.
     *
     * @param string $key   The HTTP header name
     * @param string $value The HTTP value
     *
     * @return Boolean true if the value is contained in the header, false otherwise
     *
     * @api
     */
    public function contains($key, $value)
    {
        return in_array($value, $this->get($key, null, false));
    }

    /**
     * Removes a header.
     *
     * @param string $key The HTTP header name
     *
     * @api
     */
    public function remove($key)
    {
        $key = strtr(strtolower($key), '_', '-');

        unset($this->headers[$key]);

        if ('cache-control' === $key) {
            $this->cacheControl = array();
        }
    }

    /**
     * Returns the HTTP header value converted to a date.
     *
     * @param string    $key     The parameter key
     * @param \DateTime $default The default value
     *
     * @return null|\DateTime The parsed DateTime or the default value if the header does not exist
     *
     * @throws \RuntimeException When the HTTP header is not parseable
     *
     * @api
     */
    public function getDate($key, \DateTime $default = null)
    {
        if (null === $value = $this->get($key)) {
            return $default;
        }

        if (false === $date = \DateTime::createFromFormat(DATE_RFC2822, $value)) {
            throw new \RuntimeException(sprintf('The %s HTTP header is not parseable (%s).', $key, $value));
        }

        return $date;
    }

    public function addCacheControlDirective($key, $value = true)
    {
        $this->cacheControl[$key] = $value;

        $this->set('Cache-Control', $this->getCacheControlHeader());
    }

    public function hasCacheControlDirective($key)
    {
        return array_key_exists($key, $this->cacheControl);
    }

    public function getCacheControlDirective($key)
    {
        return array_key_exists($key, $this->cacheControl) ? $this->cacheControl[$key] : null;
    }

    public function removeCacheControlDirective($key)
    {
        unset($this->cacheControl[$key]);

        $this->set('Cache-Control', $this->getCacheControlHeader());
    }

    /**
     * Returns an iterator for headers.
     *
     * @return \ArrayIterator An \ArrayIterator instance
     */
    public function getIterator()
    {
        return new \ArrayIterator($this->headers);
    }

    /**
     * Returns the number of headers.
     *
     * @return int The number of headers
     */
    public function count()
    {
        return count($this->headers);
    }

    protected function getCacheControlHeader()
    {
        $parts = array();
        ksort($this->cacheControl);
        foreach ($this->cacheControl as $key => $value) {
            if (true === $value) {
                $parts[] = $key;
            } else {
                if (preg_match('#[^a-zA-Z0-9._-]#', $value)) {
                    $value = '"'.$value.'"';
                }

                $parts[] = "$key=$value";
            }
        }

        return implode(', ', $parts);
    }

    /**
     * Parses a Cache-Control HTTP header.
     *
     * @param string $header The value of the Cache-Control HTTP header
     *
     * @return array An array representing the attribute values
     */
    protected function parseCacheControl($header)
    {
        $cacheControl = array();
        preg_match_all('#([a-zA-Z][a-zA-Z_-]*)\s*(?:=(?:"([^"]*)"|([^ \t",;]*)))?#', $header, $matches, PREG_SET_ORDER);
        foreach ($matches as $match) {
            $cacheControl[strtolower($match[1])] = isset($match[3]) ? $match[3] : (isset($match[2]) ? $match[2] : true);
        }

        return $cacheControl;
    }
}
PK��Z9�;""'Symfony/Component/BrowserKit/Cookie.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\BrowserKit;

/**
 * Cookie represents an HTTP cookie.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class Cookie
{
    /**
     * Handles dates as defined by RFC 2616 section 3.3.1, and also some other
     * non-standard, but common formats.
     *
     * @var array
     */
    private static $dateFormats = array(
        'D, d M Y H:i:s T',
        'D, d-M-y H:i:s T',
        'D, d-M-Y H:i:s T',
        'D, d-m-y H:i:s T',
        'D, d-m-Y H:i:s T',
        'D M j G:i:s Y',
        'D M d H:i:s Y T',
    );

    protected $name;
    protected $value;
    protected $expires;
    protected $path;
    protected $domain;
    protected $secure;
    protected $httponly;
    protected $rawValue;

    /**
     * Sets a cookie.
     *
     * @param string  $name         The cookie name
     * @param string  $value        The value of the cookie
     * @param string  $expires      The time the cookie expires
     * @param string  $path         The path on the server in which the cookie will be available on
     * @param string  $domain       The domain that the cookie is available
     * @param Boolean $secure       Indicates that the cookie should only be transmitted over a secure HTTPS connection from the client
     * @param Boolean $httponly     The cookie httponly flag
     * @param Boolean $encodedValue Whether the value is encoded or not
     *
     * @api
     */
    public function __construct($name, $value, $expires = null, $path = null, $domain = '', $secure = false, $httponly = true, $encodedValue = false)
    {
        if ($encodedValue) {
            $this->value    = urldecode($value);
            $this->rawValue = $value;
        } else {
            $this->value    = $value;
            $this->rawValue = urlencode($value);
        }
        $this->name     = $name;
        $this->expires  = null === $expires ? null : (integer) $expires;
        $this->path     = empty($path) ? '/' : $path;
        $this->domain   = $domain;
        $this->secure   = (Boolean) $secure;
        $this->httponly = (Boolean) $httponly;
    }

    /**
     * Returns the HTTP representation of the Cookie.
     *
     * @return string The HTTP representation of the Cookie
     *
     * @throws \UnexpectedValueException
     *
     * @api
     */
    public function __toString()
    {
        $cookie = sprintf('%s=%s', $this->name, $this->rawValue);

        if (null !== $this->expires) {
            $dateTime = \DateTime::createFromFormat('U', $this->expires, new \DateTimeZone('GMT'));

            if ($dateTime === false) {
                throw new \UnexpectedValueException(sprintf('The cookie expiration time "%s" is not valid.'), $this->expires);
            }

            $cookie .= '; expires='.str_replace('+0000', '', $dateTime->format(self::$dateFormats[0]));
        }

        if ('' !== $this->domain) {
            $cookie .= '; domain='.$this->domain;
        }

        if ($this->path) {
            $cookie .= '; path='.$this->path;
        }

        if ($this->secure) {
            $cookie .= '; secure';
        }

        if ($this->httponly) {
            $cookie .= '; httponly';
        }

        return $cookie;
    }

    /**
     * Creates a Cookie instance from a Set-Cookie header value.
     *
     * @param string $cookie A Set-Cookie header value
     * @param string $url    The base URL
     *
     * @return Cookie A Cookie instance
     *
     * @throws \InvalidArgumentException
     *
     * @api
     */
    public static function fromString($cookie, $url = null)
    {
        $parts = explode(';', $cookie);

        if (false === strpos($parts[0], '=')) {
            throw new \InvalidArgumentException(sprintf('The cookie string "%s" is not valid.', $parts[0]));
        }

        list($name, $value) = explode('=', array_shift($parts), 2);

        $values = array(
            'name'     => trim($name),
            'value'    => trim($value),
            'expires'  => null,
            'path'     => '/',
            'domain'   => '',
            'secure'   => false,
            'httponly' => false,
            'passedRawValue' => true,
        );

        if (null !== $url) {
            if ((false === $urlParts = parse_url($url)) || !isset($urlParts['host']) || !isset($urlParts['path'])) {
                throw new \InvalidArgumentException(sprintf('The URL "%s" is not valid.', $url));
            }

            $values['domain'] = $urlParts['host'];
            $values['path'] = substr($urlParts['path'], 0, strrpos($urlParts['path'], '/'));
        }

        foreach ($parts as $part) {
            $part = trim($part);

            if ('secure' === strtolower($part)) {
                // Ignore the secure flag if the original URI is not given or is not HTTPS
                if (!$url || !isset($urlParts['scheme']) || 'https' != $urlParts['scheme']) {
                    continue;
                }

                $values['secure'] = true;

                continue;
            }

            if ('httponly' === strtolower($part)) {
                $values['httponly'] = true;

                continue;
            }

            if (2 === count($elements = explode('=', $part, 2))) {
                if ('expires' === strtolower($elements[0])) {
                    $elements[1] = self::parseDate($elements[1]);
                }

                $values[strtolower($elements[0])] = $elements[1];
            }
        }

        return new static(
            $values['name'],
            $values['value'],
            $values['expires'],
            $values['path'],
            $values['domain'],
            $values['secure'],
            $values['httponly'],
            $values['passedRawValue']
        );
    }

    private static function parseDate($dateValue)
    {
        // trim single quotes around date if present
        if (($length = strlen($dateValue)) > 1 && "'" === $dateValue[0] && "'" === $dateValue[$length-1]) {
            $dateValue = substr($dateValue, 1, -1);
        }

        foreach (self::$dateFormats as $dateFormat) {
            if (false !== $date = \DateTime::createFromFormat($dateFormat, $dateValue, new \DateTimeZone('GMT'))) {
                return $date->getTimestamp();
            }
        }

        // attempt a fallback for unusual formatting
        if (false !== $date = date_create($dateValue, new \DateTimeZone('GMT'))) {
            return $date->getTimestamp();
        }

        throw new \InvalidArgumentException(sprintf('Could not parse date "%s".', $dateValue));
    }

    /**
     * Gets the name of the cookie.
     *
     * @return string The cookie name
     *
     * @api
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Gets the value of the cookie.
     *
     * @return string The cookie value
     *
     * @api
     */
    public function getValue()
    {
        return $this->value;
    }

    /**
     * Gets the raw value of the cookie.
     *
     * @return string The cookie value
     *
     * @api
     */
    public function getRawValue()
    {
        return $this->rawValue;
    }

    /**
     * Gets the expires time of the cookie.
     *
     * @return string The cookie expires time
     *
     * @api
     */
    public function getExpiresTime()
    {
        return $this->expires;
    }

    /**
     * Gets the path of the cookie.
     *
     * @return string The cookie path
     *
     * @api
     */
    public function getPath()
    {
        return $this->path;
    }

    /**
     * Gets the domain of the cookie.
     *
     * @return string The cookie domain
     *
     * @api
     */
    public function getDomain()
    {
        return $this->domain;
    }

    /**
     * Returns the secure flag of the cookie.
     *
     * @return Boolean The cookie secure flag
     *
     * @api
     */
    public function isSecure()
    {
        return $this->secure;
    }

    /**
     * Returns the httponly flag of the cookie.
     *
     * @return Boolean The cookie httponly flag
     *
     * @api
     */
    public function isHttpOnly()
    {
        return $this->httponly;
    }

    /**
     * Returns true if the cookie has expired.
     *
     * @return Boolean true if the cookie has expired, false otherwise
     *
     * @api
     */
    public function isExpired()
    {
        return null !== $this->expires && 0 !== $this->expires && $this->expires < time();
    }
}
PK��Z.�TT+Symfony/Component/BrowserKit/autoloader.phpnu�[���<?php

spl_autoload_register(function ($class) {
    if ('\\' == $class[0]) {
        $class = substr($class, 1);
    }

    if (
        0 === strpos($class, 'Symfony\\Component\\BrowserKit\\')
        &&
        file_exists($file = __DIR__.'/../../../'.str_replace('\\', '/', $class).'.php')
    ) {
        require_once $file;
    }
});
PK��Z�����*Symfony/Component/BrowserKit/CookieJar.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\BrowserKit;

/**
 * CookieJar.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class CookieJar
{
    protected $cookieJar = array();

    /**
     * Sets a cookie.
     *
     * @param Cookie $cookie A Cookie instance
     *
     * @api
     */
    public function set(Cookie $cookie)
    {
        $this->cookieJar[$cookie->getDomain()][$cookie->getPath()][$cookie->getName()] = $cookie;
    }

    /**
     * Gets a cookie by name.
     *
     * You should never use an empty domain, but if you do so,
     * this method returns the first cookie for the given name/path
     * (this behavior ensures a BC behavior with previous versions of
     * Symfony).
     *
     * @param string $name   The cookie name
     * @param string $path   The cookie path
     * @param string $domain The cookie domain
     *
     * @return Cookie|null A Cookie instance or null if the cookie does not exist
     *
     * @api
     */
    public function get($name, $path = '/', $domain = null)
    {
        $this->flushExpiredCookies();

        if (!empty($domain)) {
            foreach ($this->cookieJar as $cookieDomain => $pathCookies) {
                if ($cookieDomain) {
                    $cookieDomain = '.'.ltrim($cookieDomain, '.');
                    if ($cookieDomain != substr('.'.$domain, -strlen($cookieDomain))) {
                        continue;
                    }
                }

                foreach ($pathCookies as $cookiePath => $namedCookies) {
                    if ($cookiePath != substr($path, 0, strlen($cookiePath))) {
                        continue;
                    }
                    if (isset($namedCookies[$name])) {
                        return $namedCookies[$name];
                    }
                }
            }

            return null;
        }

        // avoid relying on this behavior that is mainly here for BC reasons
        foreach ($this->cookieJar as $cookies) {
            if (isset($cookies[$path][$name])) {
                return $cookies[$path][$name];
            }
        }

        return null;
    }

    /**
     * Removes a cookie by name.
     *
     * You should never use an empty domain, but if you do so,
     * all cookies for the given name/path expire (this behavior
     * ensures a BC behavior with previous versions of Symfony).
     *
     * @param string $name   The cookie name
     * @param string $path   The cookie path
     * @param string $domain The cookie domain
     *
     * @api
     */
    public function expire($name, $path = '/', $domain = null)
    {
        if (null === $path) {
            $path = '/';
        }

        if (empty($domain)) {
            // an empty domain means any domain
            // this should never happen but it allows for a better BC
            $domains = array_keys($this->cookieJar);
        } else {
            $domains = array($domain);
        }

        foreach ($domains as $domain) {
            unset($this->cookieJar[$domain][$path][$name]);

            if (empty($this->cookieJar[$domain][$path])) {
                unset($this->cookieJar[$domain][$path]);

                if (empty($this->cookieJar[$domain])) {
                    unset($this->cookieJar[$domain]);
                }
            }
        }
    }

    /**
     * Removes all the cookies from the jar.
     *
     * @api
     */
    public function clear()
    {
        $this->cookieJar = array();
    }

    /**
     * Updates the cookie jar from a response Set-Cookie headers.
     *
     * @param array  $setCookies Set-Cookie headers from an HTTP response
     * @param string $uri        The base URL
     */
    public function updateFromSetCookie(array $setCookies, $uri = null)
    {
        $cookies = array();

        foreach ($setCookies as $cookie) {
            foreach (explode(',', $cookie) as $i => $part) {
                if (0 === $i || preg_match('/^(?P<token>\s*[0-9A-Za-z!#\$%\&\'\*\+\-\.^_`\|~]+)=/', $part)) {
                    $cookies[] = ltrim($part);
                } else {
                    $cookies[count($cookies) - 1] .= ','.$part;
                }
            }
        }

        foreach ($cookies as $cookie) {
            try {
                $this->set(Cookie::fromString($cookie, $uri));
            } catch (\InvalidArgumentException $e) {
                // invalid cookies are just ignored
            }
        }
    }

    /**
     * Updates the cookie jar from a Response object.
     *
     * @param Response $response A Response object
     * @param string   $uri      The base URL
     */
    public function updateFromResponse(Response $response, $uri = null)
    {
        $this->updateFromSetCookie($response->getHeader('Set-Cookie', false), $uri);
    }

    /**
     * Returns not yet expired cookies.
     *
     * @return Cookie[] An array of cookies
     */
    public function all()
    {
        $this->flushExpiredCookies();

        $flattenedCookies = array();
        foreach ($this->cookieJar as $path) {
            foreach ($path as $cookies) {
                foreach ($cookies as $cookie) {
                    $flattenedCookies[] = $cookie;
                }
            }
        }

        return $flattenedCookies;
    }

    /**
     * Returns not yet expired cookie values for the given URI.
     *
     * @param string  $uri             A URI
     * @param Boolean $returnsRawValue Returns raw value or urldecoded value
     *
     * @return array An array of cookie values
     */
    public function allValues($uri, $returnsRawValue = false)
    {
        $this->flushExpiredCookies();

        $parts = array_replace(array('path' => '/'), parse_url($uri));
        $cookies = array();
        foreach ($this->cookieJar as $domain => $pathCookies) {
            if ($domain) {
                $domain = '.'.ltrim($domain, '.');
                if ($domain != substr('.'.$parts['host'], -strlen($domain))) {
                    continue;
                }
            }

            foreach ($pathCookies as $path => $namedCookies) {
                if ($path != substr($parts['path'], 0, strlen($path))) {
                    continue;
                }

                foreach ($namedCookies as $cookie) {
                    if ($cookie->isSecure() && 'https' != $parts['scheme']) {
                        continue;
                    }

                    $cookies[$cookie->getName()] = $returnsRawValue ? $cookie->getRawValue() : $cookie->getValue();
                }
            }
        }

        return $cookies;
    }

    /**
     * Returns not yet expired raw cookie values for the given URI.
     *
     * @param string $uri A URI
     *
     * @return array An array of cookie values
     */
    public function allRawValues($uri)
    {
        return $this->allValues($uri, true);
    }

    /**
     * Removes all expired cookies.
     */
    public function flushExpiredCookies()
    {
        foreach ($this->cookieJar as $domain => $pathCookies) {
            foreach ($pathCookies as $path => $namedCookies) {
                foreach ($namedCookies as $name => $cookie) {
                    if ($cookie->isExpired()) {
                        unset($this->cookieJar[$domain][$path][$name]);
                    }
                }
            }
        }
    }
}
PK��Z����
�
(Symfony/Component/BrowserKit/Request.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\BrowserKit;

/**
 * Request object.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class Request
{
    protected $uri;
    protected $method;
    protected $parameters;
    protected $files;
    protected $cookies;
    protected $server;
    protected $content;

    /**
     * Constructor.
     *
     * @param string $uri        The request URI
     * @param string $method     The HTTP method request
     * @param array  $parameters The request parameters
     * @param array  $files      An array of uploaded files
     * @param array  $cookies    An array of cookies
     * @param array  $server     An array of server parameters
     * @param string $content    The raw body data
     *
     * @api
     */
    public function __construct($uri, $method, array $parameters = array(), array $files = array(), array $cookies = array(), array $server = array(), $content = null)
    {
        $this->uri = $uri;
        $this->method = $method;
        $this->parameters = $parameters;
        $this->files = $files;
        $this->cookies = $cookies;
        $this->server = $server;
        $this->content = $content;
    }

    /**
     * Gets the request URI.
     *
     * @return string The request URI
     *
     * @api
     */
    public function getUri()
    {
        return $this->uri;
    }

    /**
     * Gets the request HTTP method.
     *
     * @return string The request HTTP method
     *
     * @api
     */
    public function getMethod()
    {
        return $this->method;
    }

    /**
     * Gets the request parameters.
     *
     * @return array The request parameters
     *
     * @api
     */
    public function getParameters()
    {
        return $this->parameters;
    }

    /**
     * Gets the request server files.
     *
     * @return array The request files
     *
     * @api
     */
    public function getFiles()
    {
        return $this->files;
    }

    /**
     * Gets the request cookies.
     *
     * @return array The request cookies
     *
     * @api
     */
    public function getCookies()
    {
        return $this->cookies;
    }

    /**
     * Gets the request server parameters.
     *
     * @return array The request server parameters
     *
     * @api
     */
    public function getServer()
    {
        return $this->server;
    }

    /**
     * Gets the request raw body data.
     *
     * @return string The request raw body data.
     *
     * @api
     */
    public function getContent()
    {
        return $this->content;
    }
}
PK��Zl�-
-
)Symfony/Component/BrowserKit/Response.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\BrowserKit;

/**
 * Response object.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class Response
{
    protected $content;
    protected $status;
    protected $headers;

    /**
     * Constructor.
     *
     * The headers array is a set of key/value pairs. If a header is present multiple times
     * then the value is an array of all the values.
     *
     * @param string  $content The content of the response
     * @param integer $status  The response status code
     * @param array   $headers An array of headers
     *
     * @api
     */
    public function __construct($content = '', $status = 200, array $headers = array())
    {
        $this->content = $content;
        $this->status  = $status;
        $this->headers = $headers;
    }

    /**
     * Converts the response object to string containing all headers and the response content.
     *
     * @return string The response with headers and content
     */
    public function __toString()
    {
        $headers = '';
        foreach ($this->headers as $name => $value) {
            if (is_string($value)) {
                $headers .= $this->buildHeader($name, $value);
            } else {
                foreach ($value as $headerValue) {
                    $headers .= $this->buildHeader($name, $headerValue);
                }
            }
        }

        return $headers."\n".$this->content;
    }

    /**
     * Returns the build header line.
     *
     * @param string $name  The header name
     * @param string $value The header value
     *
     * @return string The built header line
     */
    protected function buildHeader($name, $value)
    {
        return sprintf("%s: %s\n", $name, $value);
    }

    /**
     * Gets the response content.
     *
     * @return string The response content
     *
     * @api
     */
    public function getContent()
    {
        return $this->content;
    }

    /**
     * Gets the response status code.
     *
     * @return integer The response status code
     *
     * @api
     */
    public function getStatus()
    {
        return $this->status;
    }

    /**
     * Gets the response headers.
     *
     * @return array The response headers
     *
     * @api
     */
    public function getHeaders()
    {
        return $this->headers;
    }

    /**
     * Gets a response header.
     *
     * @param string  $header The header name
     * @param Boolean $first  Whether to return the first value or all header values
     *
     * @return string|array The first header value if $first is true, an array of values otherwise
     */
    public function getHeader($header, $first = true)
    {
        foreach ($this->headers as $key => $value) {
            if (str_replace('-', '_', strtolower($key)) == str_replace('-', '_', strtolower($header))) {
                if ($first) {
                    return is_array($value) ? (count($value) ? $value[0] : '') : $value;
                }

                return is_array($value) ? $value : array($value);
            }
        }

        return $first ? null : array();
    }
}
PK��Z㩑eCC'Symfony/Component/BrowserKit/Client.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\BrowserKit;

use Symfony\Component\DomCrawler\Crawler;
use Symfony\Component\DomCrawler\Link;
use Symfony\Component\DomCrawler\Form;
use Symfony\Component\Process\PhpProcess;

/**
 * Client simulates a browser.
 *
 * To make the actual request, you need to implement the doRequest() method.
 *
 * If you want to be able to run requests in their own process (insulated flag),
 * you need to also implement the getScript() method.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
abstract class Client
{
    protected $history;
    protected $cookieJar;
    protected $server = array();
    protected $internalRequest;
    protected $request;
    protected $internalResponse;
    protected $response;
    protected $crawler;
    protected $insulated = false;
    protected $redirect;
    protected $followRedirects = true;

    private $maxRedirects = -1;
    private $redirectCount = 0;
    private $isMainRequest = true;

    /**
     * Constructor.
     *
     * @param array     $server    The server parameters (equivalent of $_SERVER)
     * @param History   $history   A History instance to store the browser history
     * @param CookieJar $cookieJar A CookieJar instance to store the cookies
     *
     * @api
     */
    public function __construct(array $server = array(), History $history = null, CookieJar $cookieJar = null)
    {
        $this->setServerParameters($server);
        $this->history = $history ?: new History();
        $this->cookieJar = $cookieJar ?: new CookieJar();
    }

    /**
     * Sets whether to automatically follow redirects or not.
     *
     * @param Boolean $followRedirect Whether to follow redirects
     *
     * @api
     */
    public function followRedirects($followRedirect = true)
    {
        $this->followRedirects = (Boolean) $followRedirect;
    }

    /**
     * Sets the maximum number of requests that crawler can follow.
     *
     * @param integer $maxRedirects
     */
    public function setMaxRedirects($maxRedirects)
    {
        $this->maxRedirects = $maxRedirects < 0 ? -1 : $maxRedirects;
        $this->followRedirects = -1 != $this->maxRedirects;
    }

    /**
     * Sets the insulated flag.
     *
     * @param Boolean $insulated Whether to insulate the requests or not
     *
     * @throws \RuntimeException When Symfony Process Component is not installed
     *
     * @api
     */
    public function insulate($insulated = true)
    {
        if ($insulated && !class_exists('Symfony\\Component\\Process\\Process')) {
            // @codeCoverageIgnoreStart
            throw new \RuntimeException('Unable to isolate requests as the Symfony Process Component is not installed.');
            // @codeCoverageIgnoreEnd
        }

        $this->insulated = (Boolean) $insulated;
    }

    /**
     * Sets server parameters.
     *
     * @param array $server An array of server parameters
     *
     * @api
     */
    public function setServerParameters(array $server)
    {
        $this->server = array_merge(array(
            'HTTP_HOST'       => 'localhost',
            'HTTP_USER_AGENT' => 'Symfony2 BrowserKit',
        ), $server);
    }

    /**
     * Sets single server parameter.
     *
     * @param string $key   A key of the parameter
     * @param string $value A value of the parameter
     */
    public function setServerParameter($key, $value)
    {
        $this->server[$key] = $value;
    }

    /**
     * Gets single server parameter for specified key.
     *
     * @param string $key     A key of the parameter to get
     * @param string $default A default value when key is undefined
     *
     * @return string A value of the parameter
     */
    public function getServerParameter($key, $default = '')
    {
        return (isset($this->server[$key])) ? $this->server[$key] : $default;
    }

    /**
     * Returns the History instance.
     *
     * @return History A History instance
     *
     * @api
     */
    public function getHistory()
    {
        return $this->history;
    }

    /**
     * Returns the CookieJar instance.
     *
     * @return CookieJar A CookieJar instance
     *
     * @api
     */
    public function getCookieJar()
    {
        return $this->cookieJar;
    }

    /**
     * Returns the current Crawler instance.
     *
     * @return Crawler|null A Crawler instance
     *
     * @api
     */
    public function getCrawler()
    {
        return $this->crawler;
    }

    /**
     * Returns the current BrowserKit Response instance.
     *
     * @return Response|null A BrowserKit Response instance
     *
     * @api
     */
    public function getInternalResponse()
    {
        return $this->internalResponse;
    }

    /**
     * Returns the current origin response instance.
     *
     * The origin response is the response instance that is returned
     * by the code that handles requests.
     *
     * @return object|null A response instance
     *
     * @see doRequest
     *
     * @api
     */
    public function getResponse()
    {
        return $this->response;
    }

    /**
     * Returns the current BrowserKit Request instance.
     *
     * @return Request|null A BrowserKit Request instance
     *
     * @api
     */
    public function getInternalRequest()
    {
        return $this->internalRequest;
    }

    /**
     * Returns the current origin Request instance.
     *
     * The origin request is the request instance that is sent
     * to the code that handles requests.
     *
     * @return object|null A Request instance
     *
     * @see doRequest
     *
     * @api
     */
    public function getRequest()
    {
        return $this->request;
    }

    /**
     * Clicks on a given link.
     *
     * @param Link $link A Link instance
     *
     * @return Crawler
     *
     * @api
     */
    public function click(Link $link)
    {
        if ($link instanceof Form) {
            return $this->submit($link);
        }

        return $this->request($link->getMethod(), $link->getUri());
    }

    /**
     * Submits a form.
     *
     * @param Form  $form   A Form instance
     * @param array $values An array of form field values
     *
     * @return Crawler
     *
     * @api
     */
    public function submit(Form $form, array $values = array())
    {
        $form->setValues($values);

        return $this->request($form->getMethod(), $form->getUri(), $form->getPhpValues(), $form->getPhpFiles());
    }

    /**
     * Calls a URI.
     *
     * @param string  $method        The request method
     * @param string  $uri           The URI to fetch
     * @param array   $parameters    The Request parameters
     * @param array   $files         The files
     * @param array   $server        The server parameters (HTTP headers are referenced with a HTTP_ prefix as PHP does)
     * @param string  $content       The raw body data
     * @param Boolean $changeHistory Whether to update the history or not (only used internally for back(), forward(), and reload())
     *
     * @return Crawler
     *
     * @api
     */
    public function request($method, $uri, array $parameters = array(), array $files = array(), array $server = array(), $content = null, $changeHistory = true)
    {
        if ($this->isMainRequest) {
            $this->redirectCount = 0;
        } else {
            ++$this->redirectCount;
        }

        $uri = $this->getAbsoluteUri($uri);

        if (isset($server['HTTP_HOST'])) {
            $uri = preg_replace('{^(https?\://)'.parse_url($uri, PHP_URL_HOST).'}', '\\1'.$server['HTTP_HOST'], $uri);
        }

        if (isset($server['HTTPS'])) {
            $uri = preg_replace('{^'.parse_url($uri, PHP_URL_SCHEME).'}', $server['HTTPS'] ? 'https' : 'http', $uri);
        }

        $server = array_merge($this->server, $server);

        if (!$this->history->isEmpty()) {
            $server['HTTP_REFERER'] = $this->history->current()->getUri();
        }

        $server['HTTP_HOST'] = parse_url($uri, PHP_URL_HOST);

        if ($port = parse_url($uri, PHP_URL_PORT)) {
            $server['HTTP_HOST'] .= ':'.$port;
        }

        $server['HTTPS'] = 'https' == parse_url($uri, PHP_URL_SCHEME);

        $this->internalRequest = new Request($uri, $method, $parameters, $files, $this->cookieJar->allValues($uri), $server, $content);

        $this->request = $this->filterRequest($this->internalRequest);

        if (true === $changeHistory) {
            $this->history->add($this->internalRequest);
        }

        if ($this->insulated) {
            $this->response = $this->doRequestInProcess($this->request);
        } else {
            $this->response = $this->doRequest($this->request);
        }

        $this->internalResponse = $this->filterResponse($this->response);

        $this->cookieJar->updateFromResponse($this->internalResponse, $uri);

        $status = $this->internalResponse->getStatus();

        if ($status >= 300 && $status < 400) {
            $this->redirect = $this->internalResponse->getHeader('Location');
        } else {
            $this->redirect = null;
        }

        if ($this->followRedirects && $this->redirect) {
            return $this->crawler = $this->followRedirect();
        }

        return $this->crawler = $this->createCrawlerFromContent($this->internalRequest->getUri(), $this->internalResponse->getContent(), $this->internalResponse->getHeader('Content-Type'));
    }

    /**
     * Makes a request in another process.
     *
     * @param object $request An origin request instance
     *
     * @return object An origin response instance
     *
     * @throws \RuntimeException When processing returns exit code
     */
    protected function doRequestInProcess($request)
    {
        // We set the TMPDIR (for Macs) and TEMP (for Windows), because on these platforms the temp directory changes based on the user.
        $process = new PhpProcess($this->getScript($request), null, array('TMPDIR' => sys_get_temp_dir(), 'TEMP' => sys_get_temp_dir()));
        $process->run();

        if (!$process->isSuccessful() || !preg_match('/^O\:\d+\:/', $process->getOutput())) {
            throw new \RuntimeException(sprintf('OUTPUT: %s ERROR OUTPUT: %s', $process->getOutput(), $process->getErrorOutput()));
        }

        return unserialize($process->getOutput());
    }

    /**
     * Makes a request.
     *
     * @param object $request An origin request instance
     *
     * @return object An origin response instance
     */
    abstract protected function doRequest($request);

    /**
     * Returns the script to execute when the request must be insulated.
     *
     * @param object $request An origin request instance
     *
     * @throws \LogicException When this abstract class is not implemented
     */
    protected function getScript($request)
    {
        // @codeCoverageIgnoreStart
        throw new \LogicException('To insulate requests, you need to override the getScript() method.');
        // @codeCoverageIgnoreEnd
    }

    /**
     * Filters the BrowserKit request to the origin one.
     *
     * @param Request $request The BrowserKit Request to filter
     *
     * @return object An origin request instance
     */
    protected function filterRequest(Request $request)
    {
        return $request;
    }

    /**
     * Filters the origin response to the BrowserKit one.
     *
     * @param object $response The origin response to filter
     *
     * @return Response An BrowserKit Response instance
     */
    protected function filterResponse($response)
    {
        return $response;
    }

    /**
     * Creates a crawler.
     *
     * This method returns null if the DomCrawler component is not available.
     *
     * @param string $uri     A URI
     * @param string $content Content for the crawler to use
     * @param string $type    Content type
     *
     * @return Crawler|null
     */
    protected function createCrawlerFromContent($uri, $content, $type)
    {
        if (!class_exists('Symfony\Component\DomCrawler\Crawler')) {
            return null;
        }

        $crawler = new Crawler(null, $uri);
        $crawler->addContent($content, $type);

        return $crawler;
    }

    /**
     * Goes back in the browser history.
     *
     * @return Crawler
     *
     * @api
     */
    public function back()
    {
        return $this->requestFromRequest($this->history->back(), false);
    }

    /**
     * Goes forward in the browser history.
     *
     * @return Crawler
     *
     * @api
     */
    public function forward()
    {
        return $this->requestFromRequest($this->history->forward(), false);
    }

    /**
     * Reloads the current browser.
     *
     * @return Crawler
     *
     * @api
     */
    public function reload()
    {
        return $this->requestFromRequest($this->history->current(), false);
    }

    /**
     * Follow redirects?
     *
     * @return Crawler
     *
     * @throws \LogicException If request was not a redirect
     *
     * @api
     */
    public function followRedirect()
    {
        if (empty($this->redirect)) {
            throw new \LogicException('The request was not redirected.');
        }

        if (-1 !== $this->maxRedirects) {
            if ($this->redirectCount > $this->maxRedirects) {
                throw new \LogicException(sprintf('The maximum number (%d) of redirections was reached.', $this->maxRedirects));
            }
        }

        $request = $this->internalRequest;

        if (in_array($this->internalResponse->getStatus(), array(302, 303))) {
            $method = 'get';
            $files = array();
            $content = null;
        } else {
            $method = $request->getMethod();
            $files = $request->getFiles();
            $content = $request->getContent();
        }

        if ('get' === strtolower($method)) {
            // Don't forward parameters for GET request as it should reach the redirection URI
            $parameters = array();
        } else {
            $parameters = $request->getParameters();
        }

        $server = $request->getServer();
        $server = $this->updateServerFromUri($server, $this->redirect);

        $this->isMainRequest = false;

        $response = $this->request($method, $this->redirect, $parameters, $files, $server, $content);

        $this->isMainRequest = true;

        return $response;
    }

    /**
     * Restarts the client.
     *
     * It flushes history and all cookies.
     *
     * @api
     */
    public function restart()
    {
        $this->cookieJar->clear();
        $this->history->clear();
    }

    /**
     * Takes a URI and converts it to absolute if it is not already absolute.
     *
     * @param string $uri A URI
     *
     * @return string An absolute URI
     */
    protected function getAbsoluteUri($uri)
    {
        // already absolute?
        if (0 === strpos($uri, 'http')) {
            return $uri;
        }

        if (!$this->history->isEmpty()) {
            $currentUri = $this->history->current()->getUri();
        } else {
            $currentUri = sprintf('http%s://%s/',
                isset($this->server['HTTPS']) ? 's' : '',
                isset($this->server['HTTP_HOST']) ? $this->server['HTTP_HOST'] : 'localhost'
            );
        }

        // protocol relative URL
        if (0 === strpos($uri, '//')) {
            return parse_url($currentUri, PHP_URL_SCHEME).':'.$uri;
        }

        // anchor?
        if (!$uri || '#' == $uri[0]) {
            return preg_replace('/#.*?$/', '', $currentUri).$uri;
        }

        if ('/' !== $uri[0]) {
            $path = parse_url($currentUri, PHP_URL_PATH);

            if ('/' !== substr($path, -1)) {
                $path = substr($path, 0, strrpos($path, '/') + 1);
            }

            $uri = $path.$uri;
        }

        return preg_replace('#^(.*?//[^/]+)\/.*$#', '$1', $currentUri).$uri;
    }

    /**
     * Makes a request from a Request object directly.
     *
     * @param Request $request       A Request instance
     * @param Boolean $changeHistory Whether to update the history or not (only used internally for back(), forward(), and reload())
     *
     * @return Crawler
     */
    protected function requestFromRequest(Request $request, $changeHistory = true)
    {
        return $this->request($request->getMethod(), $request->getUri(), $request->getParameters(), $request->getFiles(), $request->getServer(), $request->getContent(), $changeHistory);
    }

    private function updateServerFromUri($server, $uri)
    {
        $server['HTTP_HOST'] = parse_url($uri, PHP_URL_HOST);
        $scheme = parse_url($uri, PHP_URL_SCHEME);
        $server['HTTPS'] = null === $scheme ? $server['HTTPS'] : 'https' == $scheme;
        unset($server['HTTP_IF_NONE_MATCH'], $server['HTTP_IF_MODIFIED_SINCE']);

        return $server;
    }
}
PK��Z��/		(Symfony/Component/BrowserKit/History.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\BrowserKit;

/**
 * History.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class History
{
    protected $stack = array();
    protected $position = -1;

    /**
     * Clears the history.
     */
    public function clear()
    {
        $this->stack = array();
        $this->position = -1;
    }

    /**
     * Adds a Request to the history.
     *
     * @param Request $request A Request instance
     */
    public function add(Request $request)
    {
        $this->stack = array_slice($this->stack, 0, $this->position + 1);
        $this->stack[] = clone $request;
        $this->position = count($this->stack) - 1;
    }

    /**
     * Returns true if the history is empty.
     *
     * @return Boolean true if the history is empty, false otherwise
     */
    public function isEmpty()
    {
        return count($this->stack) == 0;
    }

    /**
     * Goes back in the history.
     *
     * @return Request A Request instance
     *
     * @throws \LogicException if the stack is already on the first page
     */
    public function back()
    {
        if ($this->position < 1) {
            throw new \LogicException('You are already on the first page.');
        }

        return clone $this->stack[--$this->position];
    }

    /**
     * Goes forward in the history.
     *
     * @return Request A Request instance
     *
     * @throws \LogicException if the stack is already on the last page
     */
    public function forward()
    {
        if ($this->position > count($this->stack) - 2) {
            throw new \LogicException('You are already on the last page.');
        }

        return clone $this->stack[++$this->position];
    }

    /**
     * Returns the current element in the history.
     *
     * @return Request A Request instance
     *
     * @throws \LogicException if the stack is empty
     */
    public function current()
    {
        if (-1 == $this->position) {
            throw new \LogicException('The page history is empty.');
        }

        return clone $this->stack[$this->position];
    }
}
PK��Z��V<nn2Symfony/Component/DomCrawler/FormFieldRegistry.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DomCrawler;

use Symfony\Component\DomCrawler\Field\FormField;

/**
 * This is an internal class that must not be used directly.
 */
class FormFieldRegistry
{
    private $fields = array();

    private $base;

    /**
     * Adds a field to the registry.
     *
     * @param FormField $field The field
     *
     * @throws \InvalidArgumentException when the name is malformed
     */
    public function add(FormField $field)
    {
        $segments = $this->getSegments($field->getName());

        $target =& $this->fields;
        while ($segments) {
            if (!is_array($target)) {
                $target = array();
            }
            $path = array_shift($segments);
            if ('' === $path) {
                $target =& $target[];
            } else {
                $target =& $target[$path];
            }
        }
        $target = $field;
    }

    /**
     * Removes a field and its children from the registry.
     *
     * @param string $name The fully qualified name of the base field
     *
     * @throws \InvalidArgumentException when the name is malformed
     */
    public function remove($name)
    {
        $segments = $this->getSegments($name);
        $target =& $this->fields;
        while (count($segments) > 1) {
            $path = array_shift($segments);
            if (!array_key_exists($path, $target)) {
                return;
            }
            $target =& $target[$path];
        }
        unset($target[array_shift($segments)]);
    }

    /**
     * Returns the value of the field and its children.
     *
     * @param string $name The fully qualified name of the field
     *
     * @return mixed The value of the field
     *
     * @throws \InvalidArgumentException when the name is malformed
     * @throws \InvalidArgumentException if the field does not exist
     */
    public function &get($name)
    {
        $segments = $this->getSegments($name);
        $target =& $this->fields;
        while ($segments) {
            $path = array_shift($segments);
            if (!array_key_exists($path, $target)) {
                throw new \InvalidArgumentException(sprintf('Unreachable field "%s"', $path));
            }
            $target =& $target[$path];
        }

        return $target;
    }

    /**
     * Tests whether the form has the given field.
     *
     * @param string $name The fully qualified name of the field
     *
     * @return Boolean Whether the form has the given field
     */
    public function has($name)
    {
        try {
            $this->get($name);

            return true;
        } catch (\InvalidArgumentException $e) {
            return false;
        }
    }

    /**
     * Set the value of a field and its children.
     *
     * @param string $name  The fully qualified name of the field
     * @param mixed  $value The value
     *
     * @throws \InvalidArgumentException when the name is malformed
     * @throws \InvalidArgumentException if the field does not exist
     */
    public function set($name, $value)
    {
        $target =& $this->get($name);
        if (!is_array($value) || $target instanceof Field\ChoiceFormField) {
            $target->setValue($value);
        } else {
            $fields = self::create($name, $value);
            foreach ($fields->all() as $k => $v) {
                $this->set($k, $v);
            }
        }
    }

    /**
     * Returns the list of field with their value.
     *
     * @return array The list of fields as array((string) Fully qualified name => (mixed) value)
     */
    public function all()
    {
        return $this->walk($this->fields, $this->base);
    }

    /**
     * Creates an instance of the class.
     *
     * This function is made private because it allows overriding the $base and
     * the $values properties without any type checking.
     *
     * @param string $base   The fully qualified name of the base field
     * @param array  $values The values of the fields
     *
     * @return FormFieldRegistry
     */
    private static function create($base, array $values)
    {
        $registry = new static();
        $registry->base = $base;
        $registry->fields = $values;

        return $registry;
    }

    /**
     * Transforms a PHP array in a list of fully qualified name / value.
     *
     * @param array  $array  The PHP array
     * @param string $base   The name of the base field
     * @param array  $output The initial values
     *
     * @return array The list of fields as array((string) Fully qualified name => (mixed) value)
     */
    private function walk(array $array, $base = '', array &$output = array())
    {
        foreach ($array as $k => $v) {
            $path = empty($base) ? $k : sprintf("%s[%s]", $base, $k);
            if (is_array($v)) {
                $this->walk($v, $path, $output);
            } else {
                $output[$path] = $v;
            }
        }

        return $output;
    }

    /**
     * Splits a field name into segments as a web browser would do.
     *
     * <code>
     *     getSegments('base[foo][3][]') = array('base', 'foo, '3', '');
     * </code>
     *
     * @param string $name The name of the field
     *
     * @return array The list of segments
     *
     * @throws \InvalidArgumentException when the name is malformed
     */
    private function getSegments($name)
    {
        if (preg_match('/^(?P<base>[^[]+)(?P<extra>(\[.*)|$)/', $name, $m)) {
            $segments = array($m['base']);
            while (!empty($m['extra'])) {
                if (preg_match('/^\[(?P<segment>.*?)\](?P<extra>.*)$/', $m['extra'], $m)) {
                    $segments[] = $m['segment'];
                } else {
                    throw new \InvalidArgumentException(sprintf('Malformed field path "%s"', $name));
                }
            }

            return $segments;
        }

        throw new \InvalidArgumentException(sprintf('Malformed field path "%s"', $name));
    }
}
PK��ZLo�TT+Symfony/Component/DomCrawler/autoloader.phpnu�[���<?php

spl_autoload_register(function ($class) {
    if ('\\' == $class[0]) {
        $class = substr($class, 1);
    }

    if (
        0 === strpos($class, 'Symfony\\Component\\DomCrawler\\')
        &&
        file_exists($file = __DIR__.'/../../../'.str_replace('\\', '/', $class).'.php')
    ) {
        require_once $file;
    }
});
PK��Z���%Symfony/Component/DomCrawler/Link.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DomCrawler;

/**
 * Link represents an HTML link (an HTML a or area tag).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class Link
{
    /**
     * @var \DOMNode A \DOMNode instance
     */
    protected $node;
    /**
     * @var string The method to use for the link
     */
    protected $method;
    /**
     * @var string The URI of the page where the link is embedded (or the base href)
     */
    protected $currentUri;

    /**
     * Constructor.
     *
     * @param \DOMNode $node       A \DOMNode instance
     * @param string   $currentUri The URI of the page where the link is embedded (or the base href)
     * @param string   $method     The method to use for the link (get by default)
     *
     * @throws \InvalidArgumentException if the node is not a link
     *
     * @api
     */
    public function __construct(\DOMNode $node, $currentUri, $method = 'GET')
    {
        if (!in_array(strtolower(substr($currentUri, 0, 4)), array('http', 'file'))) {
            throw new \InvalidArgumentException(sprintf('Current URI must be an absolute URL ("%s").', $currentUri));
        }

        $this->setNode($node);
        $this->method = $method ? strtoupper($method) : null;
        $this->currentUri = $currentUri;
    }

    /**
     * Gets the node associated with this link.
     *
     * @return \DOMNode A \DOMNode instance
     */
    public function getNode()
    {
        return $this->node;
    }

    /**
     * Gets the method associated with this link.
     *
     * @return string The method
     *
     * @api
     */
    public function getMethod()
    {
        return $this->method;
    }

    /**
     * Gets the URI associated with this link.
     *
     * @return string The URI
     *
     * @api
     */
    public function getUri()
    {
        $uri = trim($this->getRawUri());

        // absolute URL?
        if (null !== parse_url($uri, PHP_URL_SCHEME)) {
            return $uri;
        }

        // empty URI
        if (!$uri) {
            return $this->currentUri;
        }

        // only an anchor
        if ('#' === $uri[0]) {
            $baseUri = $this->currentUri;
            if (false !== $pos = strpos($baseUri, '#')) {
                $baseUri = substr($baseUri, 0, $pos);
            }

            return $baseUri.$uri;
        }

        // only a query string
        if ('?' === $uri[0]) {
            $baseUri = $this->currentUri;

            // remove the query string from the current URI
            if (false !== $pos = strpos($baseUri, '?')) {
                $baseUri = substr($baseUri, 0, $pos);
            }

            return $baseUri.$uri;
        }

        // absolute URL with relative schema
        if (0 === strpos($uri, '//')) {
            return preg_replace('#^([^/]*)//.*$#', '$1', $this->currentUri).$uri;
        }

        $baseUri = preg_replace('#^(.*?//[^/]*)(?:\/.*)?$#', '$1', $this->currentUri);

        // absolute path
        if ('/' === $uri[0]) {
            return $baseUri.$uri;
        }

        // relative path
        $path = parse_url(substr($this->currentUri, strlen($baseUri)), PHP_URL_PATH);
        $path = $this->canonicalizePath(substr($path, 0, strrpos($path, '/')).'/'.$uri);

        return $baseUri.('' === $path || '/' !== $path[0] ? '/' : '').$path;
    }

    /**
     * Returns raw URI data.
     *
     * @return string
     */
    protected function getRawUri()
    {
        return $this->node->getAttribute('href');
    }

    /**
     * Returns the canonicalized URI path (see RFC 3986, section 5.2.4)
     *
     * @param string $path URI path
     *
     * @return string
     */
    protected function canonicalizePath($path)
    {
        if ('' === $path || '/' === $path) {
            return $path;
        }

        if ('.' === substr($path, -1)) {
            $path = $path.'/';
        }

        $output = array();

        foreach (explode('/', $path) as $segment) {
            if ('..' === $segment) {
                array_pop($output);
            } elseif ('.' !== $segment) {
                array_push($output, $segment);
            }
        }

        return implode('/', $output);
    }

    /**
     * Sets current \DOMNode instance.
     *
     * @param \DOMNode $node A \DOMNode instance
     *
     * @throws \LogicException If given node is not an anchor
     */
    protected function setNode(\DOMNode $node)
    {
        if ('a' != $node->nodeName && 'area' != $node->nodeName) {
            throw new \LogicException(sprintf('Unable to click on a "%s" tag.', $node->nodeName));
        }

        $this->node = $node;
    }
}
PK��Z\Ud��	�	0Symfony/Component/DomCrawler/Field/FormField.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DomCrawler\Field;

/**
 * FormField is the abstract class for all form fields.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class FormField
{
    /**
     * @var \DOMNode
     */
    protected $node;
    /**
     * @var string
     */
    protected $name;
    /**
     * @var string
     */
    protected $value;
    /**
     * @var \DOMDocument
     */
    protected $document;
    /**
     * @var \DOMXPath
     */
    protected $xpath;
    /**
     * @var Boolean
     */
    protected $disabled;

    /**
     * Constructor.
     *
     * @param \DOMNode $node The node associated with this field
     */
    public function __construct(\DOMNode $node)
    {
        $this->node = $node;
        $this->name = $node->getAttribute('name');

        $this->document = new \DOMDocument('1.0', 'UTF-8');
        $this->node = $this->document->importNode($this->node, true);

        $root = $this->document->appendChild($this->document->createElement('_root'));
        $root->appendChild($this->node);
        $this->xpath = new \DOMXPath($this->document);

        $this->initialize();
    }

    /**
     * Returns the name of the field.
     *
     * @return string The name of the field
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Gets the value of the field.
     *
     * @return string|array The value of the field
     */
    public function getValue()
    {
        return $this->value;
    }

    /**
     * Sets the value of the field.
     *
     * @param string $value The value of the field
     *
     * @api
     */
    public function setValue($value)
    {
        $this->value = (string) $value;
    }

    /**
     * Returns true if the field should be included in the submitted values.
     *
     * @return Boolean true if the field should be included in the submitted values, false otherwise
     */
    public function hasValue()
    {
        return true;
    }

    /**
     * Check if the current field is disabled
     *
     * @return Boolean
     */
    public function isDisabled()
    {
        return $this->node->hasAttribute('disabled');
    }

    /**
     * Initializes the form field.
     */
    abstract protected function initialize();
}
PK��ZbڋvB
B
4Symfony/Component/DomCrawler/Field/FileFormField.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DomCrawler\Field;

/**
 * FileFormField represents a file form field (an HTML file input tag).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class FileFormField extends FormField
{
    /**
     * Sets the PHP error code associated with the field.
     *
     * @param integer $error The error code (one of UPLOAD_ERR_INI_SIZE, UPLOAD_ERR_FORM_SIZE, UPLOAD_ERR_PARTIAL, UPLOAD_ERR_NO_FILE, UPLOAD_ERR_NO_TMP_DIR, UPLOAD_ERR_CANT_WRITE, or UPLOAD_ERR_EXTENSION)
     *
     * @throws \InvalidArgumentException When error code doesn't exist
     */
    public function setErrorCode($error)
    {
        $codes = array(UPLOAD_ERR_INI_SIZE, UPLOAD_ERR_FORM_SIZE, UPLOAD_ERR_PARTIAL, UPLOAD_ERR_NO_FILE, UPLOAD_ERR_NO_TMP_DIR, UPLOAD_ERR_CANT_WRITE, UPLOAD_ERR_EXTENSION);
        if (!in_array($error, $codes)) {
            throw new \InvalidArgumentException(sprintf('The error code %s is not valid.', $error));
        }

        $this->value = array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => $error, 'size' => 0);
    }

    /**
     * Sets the value of the field.
     *
     * @param string $value The value of the field
     *
     * @api
     */
    public function upload($value)
    {
        $this->setValue($value);
    }

    /**
     * Sets the value of the field.
     *
     * @param string $value The value of the field
     */
    public function setValue($value)
    {
        if (null !== $value && is_readable($value)) {
            $error = UPLOAD_ERR_OK;
            $size = filesize($value);
            $info = pathinfo($value);
            $name = $info['basename'];

            // copy to a tmp location
            $tmp = sys_get_temp_dir().'/'.sha1(uniqid(mt_rand(), true));
            if (array_key_exists('extension', $info)) {
                $tmp .= '.'.$info['extension'];
            }
            if (is_file($tmp)) {
                unlink($tmp);
            }
            copy($value, $tmp);
            $value = $tmp;
        } else {
            $error = UPLOAD_ERR_NO_FILE;
            $size = 0;
            $name = '';
            $value = '';
        }

        $this->value = array('name' => $name, 'type' => '', 'tmp_name' => $value, 'error' => $error, 'size' => $size);
    }

    /**
     * Sets path to the file as string for simulating HTTP request
     *
     * @param string $path The path to the file
     */
    public function setFilePath($path)
    {
        parent::setValue($path);
    }

    /**
     * Initializes the form field.
     *
     * @throws \LogicException When node type is incorrect
     */
    protected function initialize()
    {
        if ('input' != $this->node->nodeName) {
            throw new \LogicException(sprintf('A FileFormField can only be created from an input tag (%s given).', $this->node->nodeName));
        }

        if ('file' != $this->node->getAttribute('type')) {
            throw new \LogicException(sprintf('A FileFormField can only be created from an input tag with a type of file (given type is %s).', $this->node->getAttribute('type')));
        }

        $this->setValue(null);
    }
}
PK��Z�	Y[$[$6Symfony/Component/DomCrawler/Field/ChoiceFormField.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DomCrawler\Field;

/**
 * ChoiceFormField represents a choice form field.
 *
 * It is constructed from a HTML select tag, or a HTML checkbox, or radio inputs.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class ChoiceFormField extends FormField
{
    /**
     * @var string
     */
    private $type;
    /**
     * @var Boolean
     */
    private $multiple;
    /**
     * @var array
     */
    private $options;
    /**
     * @var boolean
     */
    private $validationDisabled = false;

    /**
     * Returns true if the field should be included in the submitted values.
     *
     * @return Boolean true if the field should be included in the submitted values, false otherwise
     */
    public function hasValue()
    {
        // don't send a value for unchecked checkboxes
        if (in_array($this->type, array('checkbox', 'radio')) && null === $this->value) {
            return false;
        }

        return true;
    }

    /**
     * Check if the current selected option is disabled
     *
     * @return Boolean
     */
    public function isDisabled()
    {
        foreach ($this->options as $option) {
            if ($option['value'] == $this->value && $option['disabled']) {
                return true;
            }
        }

        return false;
    }

    /**
     * Sets the value of the field.
     *
     * @param string $value The value of the field
     *
     * @api
     */
    public function select($value)
    {
        $this->setValue($value);
    }

    /**
     * Ticks a checkbox.
     *
     * @throws \LogicException When the type provided is not correct
     *
     * @api
     */
    public function tick()
    {
        if ('checkbox' !== $this->type) {
            throw new \LogicException(sprintf('You cannot tick "%s" as it is not a checkbox (%s).', $this->name, $this->type));
        }

        $this->setValue(true);
    }

    /**
     * Ticks a checkbox.
     *
     * @throws \LogicException When the type provided is not correct
     *
     * @api
     */
    public function untick()
    {
        if ('checkbox' !== $this->type) {
            throw new \LogicException(sprintf('You cannot tick "%s" as it is not a checkbox (%s).', $this->name, $this->type));
        }

        $this->setValue(false);
    }

    /**
     * Sets the value of the field.
     *
     * @param string $value The value of the field
     *
     * @throws \InvalidArgumentException When value type provided is not correct
     */
    public function setValue($value)
    {
        if ('checkbox' == $this->type && false === $value) {
            // uncheck
            $this->value = null;
        } elseif ('checkbox' == $this->type && true === $value) {
            // check
            $this->value = $this->options[0]['value'];
        } else {
            if (is_array($value)) {
                if (!$this->multiple) {
                    throw new \InvalidArgumentException(sprintf('The value for "%s" cannot be an array.', $this->name));
                }

                foreach ($value as $v) {
                    if (!$this->containsOption($v, $this->options)) {
                        throw new \InvalidArgumentException(sprintf('Input "%s" cannot take "%s" as a value (possible values: %s).', $this->name, $v, implode(', ', $this->availableOptionValues())));
                    }
                }
            } elseif (!$this->containsOption($value, $this->options)) {
                throw new \InvalidArgumentException(sprintf('Input "%s" cannot take "%s" as a value (possible values: %s).', $this->name, $value, implode(', ', $this->availableOptionValues())));
            }

            if ($this->multiple) {
                $value = (array) $value;
            }

            if (is_array($value)) {
                $this->value = $value;
            } else {
                parent::setValue($value);
            }
        }
    }

    /**
     * Adds a choice to the current ones.
     *
     * This method should only be used internally.
     *
     * @param \DOMNode $node A \DOMNode
     *
     * @throws \LogicException When choice provided is not multiple nor radio
     */
    public function addChoice(\DOMNode $node)
    {
        if (!$this->multiple && 'radio' != $this->type) {
            throw new \LogicException(sprintf('Unable to add a choice for "%s" as it is not multiple or is not a radio button.', $this->name));
        }

        $option = $this->buildOptionValue($node);
        $this->options[] = $option;

        if ($node->getAttribute('checked')) {
            $this->value = $option['value'];
        }
    }

    /**
     * Returns the type of the choice field (radio, select, or checkbox).
     *
     * @return string The type
     */
    public function getType()
    {
        return $this->type;
    }

    /**
     * Returns true if the field accepts multiple values.
     *
     * @return Boolean true if the field accepts multiple values, false otherwise
     */
    public function isMultiple()
    {
        return $this->multiple;
    }

    /**
     * Initializes the form field.
     *
     * @throws \LogicException When node type is incorrect
     */
    protected function initialize()
    {
        if ('input' != $this->node->nodeName && 'select' != $this->node->nodeName) {
            throw new \LogicException(sprintf('A ChoiceFormField can only be created from an input or select tag (%s given).', $this->node->nodeName));
        }

        if ('input' == $this->node->nodeName && 'checkbox' != $this->node->getAttribute('type') && 'radio' != $this->node->getAttribute('type')) {
            throw new \LogicException(sprintf('A ChoiceFormField can only be created from an input tag with a type of checkbox or radio (given type is %s).', $this->node->getAttribute('type')));
        }

        $this->value = null;
        $this->options = array();
        $this->multiple = false;

        if ('input' == $this->node->nodeName) {
            $this->type = $this->node->getAttribute('type');
            $optionValue = $this->buildOptionValue($this->node);
            $this->options[] = $optionValue;

            if ($this->node->getAttribute('checked')) {
                $this->value = $optionValue['value'];
            }
        } else {
            $this->type = 'select';
            if ($this->node->hasAttribute('multiple')) {
                $this->multiple = true;
                $this->value = array();
                $this->name = str_replace('[]', '', $this->name);
            }

            $found = false;
            foreach ($this->xpath->query('descendant::option', $this->node) as $option) {
                $this->options[] = $this->buildOptionValue($option);

                if ($option->getAttribute('selected')) {
                    $found = true;
                    if ($this->multiple) {
                        $this->value[] = $option->getAttribute('value');
                    } else {
                        $this->value = $option->getAttribute('value');
                    }
                }
            }

            // if no option is selected and if it is a simple select box, take the first option as the value
            $option = $this->xpath->query('descendant::option', $this->node)->item(0);
            if (!$found && !$this->multiple && $option instanceof \DOMElement) {
                $this->value = $option->getAttribute('value');
            }
        }
    }

    /**
     * Returns option value with associated disabled flag
     *
     * @param \DOMNode $node
     *
     * @return array
     */
    private function buildOptionValue($node)
    {
        $option = array();

        $defaultValue = (isset($node->nodeValue) && !empty($node->nodeValue)) ? $node->nodeValue : '1';
        $option['value'] = $node->hasAttribute('value') ? $node->getAttribute('value') : $defaultValue;
        $option['disabled'] = ($node->hasAttribute('disabled') && $node->getAttribute('disabled') == 'disabled');

        return $option;
    }

    /**
     * Checks whether given vale is in the existing options
     *
     * @param string $optionValue
     * @param array  $options
     *
     * @return bool
     */
    public function containsOption($optionValue, $options)
    {
        if ($this->validationDisabled) {
            return true;
        }

        foreach ($options as $option) {
            if ($option['value'] == $optionValue) {
                return true;
            }
        }

        return false;
    }

    /**
     * Returns list of available field options
     *
     * @return array
     */
    public function availableOptionValues()
    {
        $values = array();

        foreach ($this->options as $option) {
            $values[] = $option['value'];
        }

        return $values;
    }

    /**
     * Disables the internal validation of the field.
     *
     * @return self
     */
    public function disableValidation()
    {
        $this->validationDisabled = true;

        return $this;
    }
}
PK��Z
ʀ���8Symfony/Component/DomCrawler/Field/TextareaFormField.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DomCrawler\Field;

/**
 * TextareaFormField represents a textarea form field (an HTML textarea tag).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class TextareaFormField extends FormField
{
    /**
     * Initializes the form field.
     *
     * @throws \LogicException When node type is incorrect
     */
    protected function initialize()
    {
        if ('textarea' != $this->node->nodeName) {
            throw new \LogicException(sprintf('A TextareaFormField can only be created from a textarea tag (%s given).', $this->node->nodeName));
        }

        $this->value = null;
        foreach ($this->node->childNodes as $node) {
            $this->value .= $node->wholeText;
        }
    }
}
PK��Z�����5Symfony/Component/DomCrawler/Field/InputFormField.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DomCrawler\Field;

/**
 * InputFormField represents an input form field (an HTML input tag).
 *
 * For inputs with type of file, checkbox, or radio, there are other more
 * specialized classes (cf. FileFormField and ChoiceFormField).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class InputFormField extends FormField
{
    /**
     * Initializes the form field.
     *
     * @throws \LogicException When node type is incorrect
     */
    protected function initialize()
    {
        if ('input' != $this->node->nodeName && 'button' != $this->node->nodeName) {
            throw new \LogicException(sprintf('An InputFormField can only be created from an input or button tag (%s given).', $this->node->nodeName));
        }

        if ('checkbox' == $this->node->getAttribute('type')) {
            throw new \LogicException('Checkboxes should be instances of ChoiceFormField.');
        }

        if ('file' == $this->node->getAttribute('type')) {
            throw new \LogicException('File inputs should be instances of FileFormField.');
        }

        $this->value = $this->node->getAttribute('value');
    }
}
PK��Z<�4{bb(Symfony/Component/DomCrawler/Crawler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DomCrawler;

use Symfony\Component\CssSelector\CssSelector;

/**
 * Crawler eases navigation of a list of \DOMNode objects.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class Crawler extends \SplObjectStorage
{
    /**
     * @var string The current URI or the base href value
     */
    protected $uri;

    /**
     * @var string The default namespace prefix to be used with XPath and CSS expressions
     */
    private $defaultNamespacePrefix = 'default';

    /**
     * @var array A map of manually registered namespaces
     */
    private $namespaces = array();

    /**
     * Constructor.
     *
     * @param mixed  $node A Node to use as the base for the crawling
     * @param string $uri  The current URI or the base href value
     *
     * @api
     */
    public function __construct($node = null, $uri = null)
    {
        $this->uri = $uri;

        $this->add($node);
    }

    /**
     * Removes all the nodes.
     *
     * @api
     */
    public function clear()
    {
        $this->removeAll($this);
    }

    /**
     * Adds a node to the current list of nodes.
     *
     * This method uses the appropriate specialized add*() method based
     * on the type of the argument.
     *
     * @param \DOMNodeList|\DOMNode|array|string|null $node A node
     *
     * @throws \InvalidArgumentException When node is not the expected type.
     *
     * @api
     */
    public function add($node)
    {
        if ($node instanceof \DOMNodeList) {
            $this->addNodeList($node);
        } elseif ($node instanceof \DOMNode) {
            $this->addNode($node);
        } elseif (is_array($node)) {
            $this->addNodes($node);
        } elseif (is_string($node)) {
            $this->addContent($node);
        } elseif (null !== $node) {
            throw new \InvalidArgumentException(sprintf('Expecting a DOMNodeList or DOMNode instance, an array, a string, or null, but got "%s".', is_object($node) ? get_class($node) : gettype($node)));
        }
    }

    /**
     * Adds HTML/XML content.
     *
     * If the charset is not set via the content type, it is assumed
     * to be ISO-8859-1, which is the default charset defined by the
     * HTTP 1.1 specification.
     *
     * @param string      $content A string to parse as HTML/XML
     * @param null|string $type    The content type of the string
     */
    public function addContent($content, $type = null)
    {
        if (empty($type)) {
            $type = 0 === strpos($content, '<?xml') ? 'application/xml' : 'text/html';
        }

        // DOM only for HTML/XML content
        if (!preg_match('/(x|ht)ml/i', $type, $xmlMatches)) {
            return null;
        }

        $charset = null;
        if (false !== $pos = stripos($type, 'charset=')) {
            $charset = substr($type, $pos + 8);
            if (false !== $pos = strpos($charset, ';')) {
                $charset = substr($charset, 0, $pos);
            }
        }

        if (null === $charset &&
            preg_match('/\<meta[^\>]+charset *= *["\']?([a-zA-Z\-0-9]+)/i', $content, $matches)) {
            $charset = $matches[1];
        }

        if (null === $charset) {
            $charset = 'ISO-8859-1';
        }

        if ('x' === $xmlMatches[1]) {
            $this->addXmlContent($content, $charset);
        } else {
            $this->addHtmlContent($content, $charset);
        }
    }

    /**
     * Adds an HTML content to the list of nodes.
     *
     * The libxml errors are disabled when the content is parsed.
     *
     * If you want to get parsing errors, be sure to enable
     * internal errors via libxml_use_internal_errors(true)
     * and then, get the errors via libxml_get_errors(). Be
     * sure to clear errors with libxml_clear_errors() afterward.
     *
     * @param string $content The HTML content
     * @param string $charset The charset
     *
     * @api
     */
    public function addHtmlContent($content, $charset = 'UTF-8')
    {
        $internalErrors = libxml_use_internal_errors(true);
        $disableEntities = libxml_disable_entity_loader(true);

        $dom = new \DOMDocument('1.0', $charset);
        $dom->validateOnParse = true;

        if (function_exists('mb_convert_encoding')) {
            $hasError = false;
            set_error_handler(function () use (&$hasError) {
                $hasError = true;
            });
            $tmpContent = @mb_convert_encoding($content, 'HTML-ENTITIES', $charset);

            restore_error_handler();

            if (!$hasError) {
                $content = $tmpContent;
            }
        }

        if ('' !== trim($content)) {
            @$dom->loadHTML($content);
        }

        libxml_use_internal_errors($internalErrors);
        libxml_disable_entity_loader($disableEntities);

        $this->addDocument($dom);

        $base = $this->filterXPath('descendant-or-self::base')->extract(array('href'));

        $baseHref = current($base);
        if (count($base) && !empty($baseHref)) {
            if ($this->uri) {
                $linkNode = $dom->createElement('a');
                $linkNode->setAttribute('href', $baseHref);
                $link = new Link($linkNode, $this->uri);
                $this->uri = $link->getUri();
            } else {
                $this->uri = $baseHref;
            }
        }
    }

    /**
     * Adds an XML content to the list of nodes.
     *
     * The libxml errors are disabled when the content is parsed.
     *
     * If you want to get parsing errors, be sure to enable
     * internal errors via libxml_use_internal_errors(true)
     * and then, get the errors via libxml_get_errors(). Be
     * sure to clear errors with libxml_clear_errors() afterward.
     *
     * @param string $content The XML content
     * @param string $charset The charset
     *
     * @api
     */
    public function addXmlContent($content, $charset = 'UTF-8')
    {
        // remove the default namespace if it's the only namespace to make XPath expressions simpler
        if (!preg_match('/xmlns:/', $content)) {
            $content = str_replace('xmlns', 'ns', $content);
        }

        $internalErrors = libxml_use_internal_errors(true);
        $disableEntities = libxml_disable_entity_loader(true);

        $dom = new \DOMDocument('1.0', $charset);
        $dom->validateOnParse = true;

        if ('' !== trim($content)) {
            @$dom->loadXML($content, LIBXML_NONET);
        }

        libxml_use_internal_errors($internalErrors);
        libxml_disable_entity_loader($disableEntities);

        $this->addDocument($dom);
    }

    /**
     * Adds a \DOMDocument to the list of nodes.
     *
     * @param \DOMDocument $dom A \DOMDocument instance
     *
     * @api
     */
    public function addDocument(\DOMDocument $dom)
    {
        if ($dom->documentElement) {
            $this->addNode($dom->documentElement);
        }
    }

    /**
     * Adds a \DOMNodeList to the list of nodes.
     *
     * @param \DOMNodeList $nodes A \DOMNodeList instance
     *
     * @api
     */
    public function addNodeList(\DOMNodeList $nodes)
    {
        foreach ($nodes as $node) {
            $this->addNode($node);
        }
    }

    /**
     * Adds an array of \DOMNode instances to the list of nodes.
     *
     * @param \DOMNode[] $nodes An array of \DOMNode instances
     *
     * @api
     */
    public function addNodes(array $nodes)
    {
        foreach ($nodes as $node) {
            $this->add($node);
        }
    }

    /**
     * Adds a \DOMNode instance to the list of nodes.
     *
     * @param \DOMNode $node A \DOMNode instance
     *
     * @api
     */
    public function addNode(\DOMNode $node)
    {
        if ($node instanceof \DOMDocument) {
            $this->attach($node->documentElement);
        } else {
            $this->attach($node);
        }
    }

    /**
     * Returns a node given its position in the node list.
     *
     * @param integer $position The position
     *
     * @return Crawler A new instance of the Crawler with the selected node, or an empty Crawler if it does not exist.
     *
     * @api
     */
    public function eq($position)
    {
        foreach ($this as $i => $node) {
            if ($i == $position) {
                return new static($node, $this->uri);
            }
        }

        return new static(null, $this->uri);
    }

    /**
     * Calls an anonymous function on each node of the list.
     *
     * The anonymous function receives the position and the node wrapped
     * in a Crawler instance as arguments.
     *
     * Example:
     *
     *     $crawler->filter('h1')->each(function ($node, $i) {
     *         return $node->text();
     *     });
     *
     * @param \Closure $closure An anonymous function
     *
     * @return array An array of values returned by the anonymous function
     *
     * @api
     */
    public function each(\Closure $closure)
    {
        $data = array();
        foreach ($this as $i => $node) {
            $data[] = $closure(new static($node, $this->uri), $i);
        }

        return $data;
    }

    /**
     * Reduces the list of nodes by calling an anonymous function.
     *
     * To remove a node from the list, the anonymous function must return false.
     *
     * @param \Closure $closure An anonymous function
     *
     * @return Crawler A Crawler instance with the selected nodes.
     *
     * @api
     */
    public function reduce(\Closure $closure)
    {
        $nodes = array();
        foreach ($this as $i => $node) {
            if (false !== $closure(new static($node, $this->uri), $i)) {
                $nodes[] = $node;
            }
        }

        return new static($nodes, $this->uri);
    }

    /**
     * Returns the first node of the current selection
     *
     * @return Crawler A Crawler instance with the first selected node
     *
     * @api
     */
    public function first()
    {
        return $this->eq(0);
    }

    /**
     * Returns the last node of the current selection
     *
     * @return Crawler A Crawler instance with the last selected node
     *
     * @api
     */
    public function last()
    {
        return $this->eq(count($this) - 1);
    }

    /**
     * Returns the siblings nodes of the current selection
     *
     * @return Crawler A Crawler instance with the sibling nodes
     *
     * @throws \InvalidArgumentException When current node is empty
     *
     * @api
     */
    public function siblings()
    {
        if (!count($this)) {
            throw new \InvalidArgumentException('The current node list is empty.');
        }

        return new static($this->sibling($this->getNode(0)->parentNode->firstChild), $this->uri);
    }

    /**
     * Returns the next siblings nodes of the current selection
     *
     * @return Crawler A Crawler instance with the next sibling nodes
     *
     * @throws \InvalidArgumentException When current node is empty
     *
     * @api
     */
    public function nextAll()
    {
        if (!count($this)) {
            throw new \InvalidArgumentException('The current node list is empty.');
        }

        return new static($this->sibling($this->getNode(0)), $this->uri);
    }

    /**
     * Returns the previous sibling nodes of the current selection
     *
     * @return Crawler A Crawler instance with the previous sibling nodes
     *
     * @throws \InvalidArgumentException
     *
     * @api
     */
    public function previousAll()
    {
        if (!count($this)) {
            throw new \InvalidArgumentException('The current node list is empty.');
        }

        return new static($this->sibling($this->getNode(0), 'previousSibling'), $this->uri);
    }

    /**
     * Returns the parents nodes of the current selection
     *
     * @return Crawler A Crawler instance with the parents nodes of the current selection
     *
     * @throws \InvalidArgumentException When current node is empty
     *
     * @api
     */
    public function parents()
    {
        if (!count($this)) {
            throw new \InvalidArgumentException('The current node list is empty.');
        }

        $node = $this->getNode(0);
        $nodes = array();

        while ($node = $node->parentNode) {
            if (1 === $node->nodeType && '_root' !== $node->nodeName) {
                $nodes[] = $node;
            }
        }

        return new static($nodes, $this->uri);
    }

    /**
     * Returns the children nodes of the current selection
     *
     * @return Crawler A Crawler instance with the children nodes
     *
     * @throws \InvalidArgumentException When current node is empty
     *
     * @api
     */
    public function children()
    {
        if (!count($this)) {
            throw new \InvalidArgumentException('The current node list is empty.');
        }

        $node = $this->getNode(0)->firstChild;

        return new static($node ? $this->sibling($node) : array(), $this->uri);
    }

    /**
     * Returns the attribute value of the first node of the list.
     *
     * @param string $attribute The attribute name
     *
     * @return string|null The attribute value or null if the attribute does not exist
     *
     * @throws \InvalidArgumentException When current node is empty
     *
     * @api
     */
    public function attr($attribute)
    {
        if (!count($this)) {
            throw new \InvalidArgumentException('The current node list is empty.');
        }

        $node = $this->getNode(0);

        return $node->hasAttribute($attribute) ? $node->getAttribute($attribute) : null;
    }

    /**
     * Returns the node value of the first node of the list.
     *
     * @return string The node value
     *
     * @throws \InvalidArgumentException When current node is empty
     *
     * @api
     */
    public function text()
    {
        if (!count($this)) {
            throw new \InvalidArgumentException('The current node list is empty.');
        }

        return $this->getNode(0)->nodeValue;
    }

    /**
     * Returns the first node of the list as HTML.
     *
     * @return string The node html
     *
     * @throws \InvalidArgumentException When current node is empty
     */
    public function html()
    {
        if (!count($this)) {
            throw new \InvalidArgumentException('The current node list is empty.');
        }

        $html = '';
        foreach ($this->getNode(0)->childNodes as $child) {
            if (version_compare(PHP_VERSION, '5.3.6', '>=')) {
                // node parameter was added to the saveHTML() method in PHP 5.3.6
                // @see http://php.net/manual/en/domdocument.savehtml.php
                $html .= $child->ownerDocument->saveHTML($child);
            } else {
                $document = new \DOMDocument('1.0', 'UTF-8');
                $document->appendChild($document->importNode($child, true));
                $html .= rtrim($document->saveHTML());
            }
        }

        return $html;
    }

    /**
     * Extracts information from the list of nodes.
     *
     * You can extract attributes or/and the node value (_text).
     *
     * Example:
     *
     * $crawler->filter('h1 a')->extract(array('_text', 'href'));
     *
     * @param array $attributes An array of attributes
     *
     * @return array An array of extracted values
     *
     * @api
     */
    public function extract($attributes)
    {
        $attributes = (array) $attributes;
        $count = count($attributes);

        $data = array();
        foreach ($this as $node) {
            $elements = array();
            foreach ($attributes as $attribute) {
                if ('_text' === $attribute) {
                    $elements[] = $node->nodeValue;
                } else {
                    $elements[] = $node->getAttribute($attribute);
                }
            }

            $data[] = $count > 1 ? $elements : $elements[0];
        }

        return $data;
    }

    /**
     * Filters the list of nodes with an XPath expression.
     *
     * @param string $xpath An XPath expression
     *
     * @return Crawler A new instance of Crawler with the filtered list of nodes
     *
     * @api
     */
    public function filterXPath($xpath)
    {
        $document = new \DOMDocument('1.0', 'UTF-8');
        $root = $document->appendChild($document->createElement('_root'));
        foreach ($this as $node) {
            $root->appendChild($document->importNode($node, true));
        }

        $prefixes = $this->findNamespacePrefixes($xpath);
        $domxpath = $this->createDOMXPath($document, $prefixes);

        return new static($domxpath->query($xpath), $this->uri);
    }

    /**
     * Filters the list of nodes with a CSS selector.
     *
     * This method only works if you have installed the CssSelector Symfony Component.
     *
     * @param string $selector A CSS selector
     *
     * @return Crawler A new instance of Crawler with the filtered list of nodes
     *
     * @throws \RuntimeException if the CssSelector Component is not available
     *
     * @api
     */
    public function filter($selector)
    {
        if (!class_exists('Symfony\\Component\\CssSelector\\CssSelector')) {
            // @codeCoverageIgnoreStart
            throw new \RuntimeException('Unable to filter with a CSS selector as the Symfony CssSelector is not installed (you can use filterXPath instead).');
            // @codeCoverageIgnoreEnd
        }

        return $this->filterXPath(CssSelector::toXPath($selector));
    }

    /**
     * Selects links by name or alt value for clickable images.
     *
     * @param string $value The link text
     *
     * @return Crawler A new instance of Crawler with the filtered list of nodes
     *
     * @api
     */
    public function selectLink($value)
    {
        $xpath = sprintf('//a[contains(concat(\' \', normalize-space(string(.)), \' \'), %s)] ', static::xpathLiteral(' '.$value.' ')).
                            sprintf('| //a/img[contains(concat(\' \', normalize-space(string(@alt)), \' \'), %s)]/ancestor::a', static::xpathLiteral(' '.$value.' '));

        return $this->filterXPath($xpath);
    }

    /**
     * Selects a button by name or alt value for images.
     *
     * @param string $value The button text
     *
     * @return Crawler A new instance of Crawler with the filtered list of nodes
     *
     * @api
     */
    public function selectButton($value)
    {
        $xpath = sprintf('//input[((@type="submit" or @type="button") and contains(concat(\' \', normalize-space(string(@value)), \' \'), %s)) ', static::xpathLiteral(' '.$value.' ')).
                         sprintf('or (@type="image" and contains(concat(\' \', normalize-space(string(@alt)), \' \'), %s)) or @id="%s" or @name="%s"] ', static::xpathLiteral(' '.$value.' '), $value, $value).
                         sprintf('| //button[contains(concat(\' \', normalize-space(string(.)), \' \'), %s) or @id="%s" or @name="%s"]', static::xpathLiteral(' '.$value.' '), $value, $value);

        return $this->filterXPath($xpath);
    }

    /**
     * Returns a Link object for the first node in the list.
     *
     * @param string $method The method for the link (get by default)
     *
     * @return Link A Link instance
     *
     * @throws \InvalidArgumentException If the current node list is empty
     *
     * @api
     */
    public function link($method = 'get')
    {
        if (!count($this)) {
            throw new \InvalidArgumentException('The current node list is empty.');
        }

        $node = $this->getNode(0);

        return new Link($node, $this->uri, $method);
    }

    /**
     * Returns an array of Link objects for the nodes in the list.
     *
     * @return Link[] An array of Link instances
     *
     * @api
     */
    public function links()
    {
        $links = array();
        foreach ($this as $node) {
            $links[] = new Link($node, $this->uri, 'get');
        }

        return $links;
    }

    /**
     * Returns a Form object for the first node in the list.
     *
     * @param array  $values An array of values for the form fields
     * @param string $method The method for the form
     *
     * @return Form A Form instance
     *
     * @throws \InvalidArgumentException If the current node list is empty
     *
     * @api
     */
    public function form(array $values = null, $method = null)
    {
        if (!count($this)) {
            throw new \InvalidArgumentException('The current node list is empty.');
        }

        $form = new Form($this->getNode(0), $this->uri, $method);

        if (null !== $values) {
            $form->setValues($values);
        }

        return $form;
    }

    /**
     * Overloads a default namespace prefix to be used with XPath and CSS expressions.
     *
     * @param string $prefix
     */
    public function setDefaultNamespacePrefix($prefix)
    {
        $this->defaultNamespacePrefix = $prefix;
    }

    /**
     * @param string $prefix
     * @param string $namespace
     */
    public function registerNamespace($prefix, $namespace)
    {
        $this->namespaces[$prefix] = $namespace;
    }

    /**
     * Converts string for XPath expressions.
     *
     * Escaped characters are: quotes (") and apostrophe (').
     *
     *  Examples:
     *  <code>
     *     echo Crawler::xpathLiteral('foo " bar');
     *     //prints 'foo " bar'
     *
     *     echo Crawler::xpathLiteral("foo ' bar");
     *     //prints "foo ' bar"
     *
     *     echo Crawler::xpathLiteral('a\'b"c');
     *     //prints concat('a', "'", 'b"c')
     *  </code>
     *
     * @param string $s String to be escaped
     *
     * @return string Converted string
     */
    public static function xpathLiteral($s)
    {
        if (false === strpos($s, "'")) {
            return sprintf("'%s'", $s);
        }

        if (false === strpos($s, '"')) {
            return sprintf('"%s"', $s);
        }

        $string = $s;
        $parts = array();
        while (true) {
            if (false !== $pos = strpos($string, "'")) {
                $parts[] = sprintf("'%s'", substr($string, 0, $pos));
                $parts[] = "\"'\"";
                $string = substr($string, $pos + 1);
            } else {
                $parts[] = "'$string'";
                break;
            }
        }

        return sprintf("concat(%s)", implode($parts, ', '));
    }

    /**
     * @param integer $position
     *
     * @return \DOMElement|null
     */
    public function getNode($position)
    {
        foreach ($this as $i => $node) {
            if ($i == $position) {
                return $node;
            }
        // @codeCoverageIgnoreStart
        }

        return null;
        // @codeCoverageIgnoreEnd
    }

    /**
     * @param \DOMElement $node
     * @param string      $siblingDir
     *
     * @return array
     */
    protected function sibling($node, $siblingDir = 'nextSibling')
    {
        $nodes = array();

        do {
            if ($node !== $this->getNode(0) && $node->nodeType === 1) {
                $nodes[] = $node;
            }
        } while ($node = $node->$siblingDir);

        return $nodes;
    }

    /**
     * @param \DOMDocument $document
     * @param array        $prefixes
     *
     * @return \DOMXPath
     *
     * @throws \InvalidArgumentException
     */
    private function createDOMXPath(\DOMDocument $document, array $prefixes = array())
    {
        $domxpath = new \DOMXPath($document);

        foreach ($prefixes as $prefix) {
            $namespace = $this->discoverNamespace($domxpath, $prefix);
            if (null !== $namespace) {
                $domxpath->registerNamespace($prefix, $namespace);
            }
        }

        return $domxpath;
    }

    /**
     * @param \DOMXPath $domxpath
     * @param string    $prefix
     *
     * @return string
     *
     * @throws \InvalidArgumentException
     */
    private function discoverNamespace(\DOMXPath $domxpath, $prefix)
    {
        if (isset($this->namespaces[$prefix])) {
            return $this->namespaces[$prefix];
        }

        // ask for one namespace, otherwise we'd get a collection with an item for each node
        $namespaces = $domxpath->query(sprintf('(//namespace::*[name()="%s"])[last()]', $this->defaultNamespacePrefix === $prefix ? '' : $prefix));

        if ($node = $namespaces->item(0)) {
            return $node->nodeValue;
        }
    }

    /**
     * @param $xpath
     *
     * @return array
     */
    private function findNamespacePrefixes($xpath)
    {
        if (preg_match_all('/(?P<prefix>[a-z_][a-z_0-9\-\.]*):[^"\/]/i', $xpath, $matches)) {
            return array_unique($matches['prefix']);
        }

        return array();
    }
}
PK��Z�
�H7H7%Symfony/Component/DomCrawler/Form.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DomCrawler;

use Symfony\Component\DomCrawler\Field\FormField;

/**
 * Form represents an HTML form.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class Form extends Link implements \ArrayAccess
{
    /**
     * @var \DOMNode
     */
    private $button;

    /**
     * @var Field\FormField[]
     */
    private $fields;

    /**
     * Constructor.
     *
     * @param \DOMNode $node       A \DOMNode instance
     * @param string   $currentUri The URI of the page where the form is embedded
     * @param string   $method     The method to use for the link (if null, it defaults to the method defined by the form)
     *
     * @throws \LogicException if the node is not a button inside a form tag
     *
     * @api
     */
    public function __construct(\DOMNode $node, $currentUri, $method = null)
    {
        parent::__construct($node, $currentUri, $method);

        $this->initialize();
    }

    /**
     * Gets the form node associated with this form.
     *
     * @return \DOMNode A \DOMNode instance
     */
    public function getFormNode()
    {
        return $this->node;
    }

    /**
     * Sets the value of the fields.
     *
     * @param array $values An array of field values
     *
     * @return Form
     *
     * @api
     */
    public function setValues(array $values)
    {
        foreach ($values as $name => $value) {
            $this->fields->set($name, $value);
        }

        return $this;
    }

    /**
     * Gets the field values.
     *
     * The returned array does not include file fields (@see getFiles).
     *
     * @return array An array of field values.
     *
     * @api
     */
    public function getValues()
    {
        $values = array();
        foreach ($this->fields->all() as $name => $field) {
            if ($field->isDisabled()) {
                continue;
            }

            if (!$field instanceof Field\FileFormField && $field->hasValue()) {
                $values[$name] = $field->getValue();
            }
        }

        return $values;
    }

    /**
     * Gets the file field values.
     *
     * @return array An array of file field values.
     *
     * @api
     */
    public function getFiles()
    {
        if (!in_array($this->getMethod(), array('POST', 'PUT', 'DELETE', 'PATCH'))) {
            return array();
        }

        $files = array();

        foreach ($this->fields->all() as $name => $field) {
            if ($field->isDisabled()) {
                continue;
            }

            if ($field instanceof Field\FileFormField) {
                $files[$name] = $field->getValue();
            }
        }

        return $files;
    }

    /**
     * Gets the field values as PHP.
     *
     * This method converts fields with the array notation
     * (like foo[bar] to arrays) like PHP does.
     *
     * @return array An array of field values.
     *
     * @api
     */
    public function getPhpValues()
    {
        $values = array();
        foreach ($this->getValues() as $name => $value) {
            $qs = http_build_query(array($name => $value), '', '&');
            parse_str($qs, $expandedValue);
            $varName = substr($name, 0, strlen(key($expandedValue)));
            $values = array_replace_recursive($values, array($varName => current($expandedValue)));
        }

        return $values;
    }

    /**
     * Gets the file field values as PHP.
     *
     * This method converts fields with the array notation
     * (like foo[bar] to arrays) like PHP does.
     *
     * @return array An array of field values.
     *
     * @api
     */
    public function getPhpFiles()
    {
        $values = array();
        foreach ($this->getFiles() as $name => $value) {
            $qs = http_build_query(array($name => $value), '', '&');
            parse_str($qs, $expandedValue);
            $varName = substr($name, 0, strlen(key($expandedValue)));
            $values = array_replace_recursive($values, array($varName => current($expandedValue)));
        }

        return $values;
    }

    /**
     * Gets the URI of the form.
     *
     * The returned URI is not the same as the form "action" attribute.
     * This method merges the value if the method is GET to mimics
     * browser behavior.
     *
     * @return string The URI
     *
     * @api
     */
    public function getUri()
    {
        $uri = parent::getUri();

        if (!in_array($this->getMethod(), array('POST', 'PUT', 'DELETE', 'PATCH')) && $queryString = http_build_query($this->getValues(), null, '&')) {
            $sep = false === strpos($uri, '?') ? '?' : '&';
            $uri .= $sep.$queryString;
        }

        return $uri;
    }

    protected function getRawUri()
    {
        return $this->node->getAttribute('action');
    }

    /**
     * Gets the form method.
     *
     * If no method is defined in the form, GET is returned.
     *
     * @return string The method
     *
     * @api
     */
    public function getMethod()
    {
        if (null !== $this->method) {
            return $this->method;
        }

        return $this->node->getAttribute('method') ? strtoupper($this->node->getAttribute('method')) : 'GET';
    }

    /**
     * Returns true if the named field exists.
     *
     * @param string $name The field name
     *
     * @return Boolean true if the field exists, false otherwise
     *
     * @api
     */
    public function has($name)
    {
        return $this->fields->has($name);
    }

    /**
     * Removes a field from the form.
     *
     * @param string $name The field name
     *
     * @throws \InvalidArgumentException when the name is malformed
     *
     * @api
     */
    public function remove($name)
    {
        $this->fields->remove($name);
    }

    /**
     * Gets a named field.
     *
     * @param string $name The field name
     *
     * @return FormField The field instance
     *
     * @throws \InvalidArgumentException When field is not present in this form
     *
     * @api
     */
    public function get($name)
    {
        return $this->fields->get($name);
    }

    /**
     * Sets a named field.
     *
     * @param FormField $field The field
     *
     * @api
     */
    public function set(FormField $field)
    {
        $this->fields->add($field);
    }

    /**
     * Gets all fields.
     *
     * @return FormField[] An array of fields
     *
     * @api
     */
    public function all()
    {
        return $this->fields->all();
    }

    /**
     * Returns true if the named field exists.
     *
     * @param string $name The field name
     *
     * @return Boolean true if the field exists, false otherwise
     */
    public function offsetExists($name)
    {
        return $this->has($name);
    }

    /**
     * Gets the value of a field.
     *
     * @param string $name The field name
     *
     * @return FormField The associated Field instance
     *
     * @throws \InvalidArgumentException if the field does not exist
     */
    public function offsetGet($name)
    {
        return $this->fields->get($name);
    }

    /**
     * Sets the value of a field.
     *
     * @param string       $name  The field name
     * @param string|array $value The value of the field
     *
     * @throws \InvalidArgumentException if the field does not exist
     */
    public function offsetSet($name, $value)
    {
        $this->fields->set($name, $value);
    }

    /**
     * Removes a field from the form.
     *
     * @param string $name The field name
     */
    public function offsetUnset($name)
    {
        $this->fields->remove($name);
    }

    /**
     * Disables validation
     *
     * @return self
     */
    public function disableValidation()
    {
        foreach ($this->fields->all() as $field) {
            if ($field instanceof Field\ChoiceFormField) {
                $field->disableValidation();
            }
        }

        return $this;
    }

    /**
     * Sets the node for the form.
     *
     * Expects a 'submit' button \DOMNode and finds the corresponding form element.
     *
     * @param \DOMNode $node A \DOMNode instance
     *
     * @throws \LogicException If given node is not a button or input or does not have a form ancestor
     */
    protected function setNode(\DOMNode $node)
    {
        $this->button = $node;
        if ('button' == $node->nodeName || ('input' == $node->nodeName && in_array($node->getAttribute('type'), array('submit', 'button', 'image')))) {
            if ($node->hasAttribute('form')) {
                // if the node has the HTML5-compliant 'form' attribute, use it
                $formId = $node->getAttribute('form');
                $form = $node->ownerDocument->getElementById($formId);
                if (null === $form) {
                    throw new \LogicException(sprintf('The selected node has an invalid form attribute (%s).', $formId));
                }
                $this->node = $form;

                return;
            }
            // we loop until we find a form ancestor
            do {
                if (null === $node = $node->parentNode) {
                    throw new \LogicException('The selected node does not have a form ancestor.');
                }
            } while ('form' != $node->nodeName);
        } elseif ('form' != $node->nodeName) {
            throw new \LogicException(sprintf('Unable to submit on a "%s" tag.', $node->nodeName));
        }

        $this->node = $node;
    }

    /**
     * Adds form elements related to this form.
     *
     * Creates an internal copy of the submitted 'button' element and
     * the form node or the entire document depending on whether we need
     * to find non-descendant elements through HTML5 'form' attribute.
     */
    private function initialize()
    {
        $this->fields = new FormFieldRegistry();

        $document = new \DOMDocument('1.0', 'UTF-8');
        $xpath = new \DOMXPath($document);
        $root = $document->appendChild($document->createElement('_root'));

        // add submitted button if it has a valid name
        if ('form' !== $this->button->nodeName && $this->button->hasAttribute('name') && $this->button->getAttribute('name')) {
            if ('input' == $this->button->nodeName && 'image' == $this->button->getAttribute('type')) {
                $name = $this->button->getAttribute('name');
                $this->button->setAttribute('value', '0');

                // temporarily change the name of the input node for the x coordinate
                $this->button->setAttribute('name', $name.'.x');
                $this->set(new Field\InputFormField($document->importNode($this->button, true)));

                // temporarily change the name of the input node for the y coordinate
                $this->button->setAttribute('name', $name.'.y');
                $this->set(new Field\InputFormField($document->importNode($this->button, true)));

                // restore the original name of the input node
                $this->button->setAttribute('name', $name);
            } else {
                $this->set(new Field\InputFormField($document->importNode($this->button, true)));
            }
        }

        // find form elements corresponding to the current form
        if ($this->node->hasAttribute('id')) {
            // traverse through the whole document
            $node = $document->importNode($this->node->ownerDocument->documentElement, true);
            $root->appendChild($node);

            // corresponding elements are either descendants or have a matching HTML5 form attribute
            $formId = Crawler::xpathLiteral($this->node->getAttribute('id'));
            $fieldNodes = $xpath->query(sprintf('descendant::input[@form=%s] | descendant::button[@form=%s] | descendant::textarea[@form=%s] | descendant::select[@form=%s] | //form[@id=%s]//input[not(@form)] | //form[@id=%s]//button[not(@form)] | //form[@id=%s]//textarea[not(@form)] | //form[@id=%s]//select[not(@form)]', $formId, $formId, $formId, $formId, $formId, $formId, $formId, $formId), $root);
            foreach ($fieldNodes as $node) {
                $this->addField($node);
            }
        } else {
            // parent form has no id, add descendant elements only
            $node = $document->importNode($this->node, true);
            $root->appendChild($node);

            // descendant elements with form attribute are not part of this form
            $fieldNodes = $xpath->query('descendant::input[not(@form)] | descendant::button[not(@form)] | descendant::textarea[not(@form)] | descendant::select[not(@form)]', $root);
            foreach ($fieldNodes as $node) {
                $this->addField($node);
            }
        }
    }

    private function addField(\DOMNode $node)
    {
        if (!$node->hasAttribute('name') || !$node->getAttribute('name')) {
            return;
        }

        $nodeName = $node->nodeName;
        if ('select' == $nodeName || 'input' == $nodeName && 'checkbox' == $node->getAttribute('type')) {
            $this->set(new Field\ChoiceFormField($node));
        } elseif ('input' == $nodeName && 'radio' == $node->getAttribute('type')) {
            if ($this->has($node->getAttribute('name'))) {
                $this->get($node->getAttribute('name'))->addChoice($node);
            } else {
                $this->set(new Field\ChoiceFormField($node));
            }
        } elseif ('input' == $nodeName && 'file' == $node->getAttribute('type')) {
            $this->set(new Field\FileFormField($node));
        } elseif ('input' == $nodeName && !in_array($node->getAttribute('type'), array('submit', 'button', 'image'))) {
            $this->set(new Field\InputFormField($node));
        } elseif ('textarea' == $nodeName) {
            $this->set(new Field\TextareaFormField($node));
        }
    }
}
PK��Z�����!�!2Symfony/Component/CssSelector/XPath/Translator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\XPath;

use Symfony\Component\CssSelector\Exception\ExpressionErrorException;
use Symfony\Component\CssSelector\Node\FunctionNode;
use Symfony\Component\CssSelector\Node\NodeInterface;
use Symfony\Component\CssSelector\Node\SelectorNode;
use Symfony\Component\CssSelector\Parser\Parser;
use Symfony\Component\CssSelector\Parser\ParserInterface;

/**
 * XPath expression translator interface.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class Translator implements TranslatorInterface
{
    /**
     * @var ParserInterface
     */
    private $mainParser;

    /**
     * @var ParserInterface[]
     */
    private $shortcutParsers = array();

    /**
     * @var Extension\ExtensionInterface
     */
    private $extensions = array();

    /**
     * @var array
     */
    private $nodeTranslators = array();

    /**
     * @var array
     */
    private $combinationTranslators = array();

    /**
     * @var array
     */
    private $functionTranslators = array();

    /**
     * @var array
     */
    private $pseudoClassTranslators = array();

    /**
     * @var array
     */
    private $attributeMatchingTranslators = array();

    /**
     * Constructor.
     */
    public function __construct(ParserInterface $parser = null)
    {
        $this->mainParser = $parser ?: new Parser();

        $this
            ->registerExtension(new Extension\NodeExtension($this))
            ->registerExtension(new Extension\CombinationExtension())
            ->registerExtension(new Extension\FunctionExtension())
            ->registerExtension(new Extension\PseudoClassExtension())
            ->registerExtension(new Extension\AttributeMatchingExtension())
        ;
    }

    /**
     * @param string $element
     *
     * @return string
     */
    public static function getXpathLiteral($element)
    {
        if (false === strpos($element, "'")) {
            return "'".$element."'";
        }

        if (false === strpos($element, '"')) {
            return '"'.$element.'"';
        }

        $string = $element;
        $parts = array();
        while (true) {
            if (false !== $pos = strpos($string, "'")) {
                $parts[] = sprintf("'%s'", substr($string, 0, $pos));
                $parts[] = "\"'\"";
                $string = substr($string, $pos + 1);
            } else {
                $parts[] = "'$string'";
                break;
            }
        }

        return sprintf('concat(%s)', implode($parts, ', '));
    }

    /**
     * {@inheritdoc}
     */
    public function cssToXPath($cssExpr, $prefix = 'descendant-or-self::')
    {
        $selectors = $this->parseSelectors($cssExpr);

        /** @var SelectorNode $selector */
        foreach ($selectors as $selector) {
            if (null !== $selector->getPseudoElement()) {
                throw new ExpressionErrorException('Pseudo-elements are not supported.');
            }
        }

        $translator = $this;

        return implode(' | ', array_map(function (SelectorNode $selector) use ($translator, $prefix) {
            return $translator->selectorToXPath($selector, $prefix);
        }, $selectors));
    }

    /**
     * {@inheritdoc}
     */
    public function selectorToXPath(SelectorNode $selector, $prefix = 'descendant-or-self::')
    {
        return ($prefix ?: '').$this->nodeToXPath($selector);
    }

    /**
     * Registers an extension.
     *
     * @param Extension\ExtensionInterface $extension
     *
     * @return Translator
     */
    public function registerExtension(Extension\ExtensionInterface $extension)
    {
        $this->extensions[$extension->getName()] = $extension;

        $this->nodeTranslators = array_merge($this->nodeTranslators, $extension->getNodeTranslators());
        $this->combinationTranslators = array_merge($this->combinationTranslators, $extension->getCombinationTranslators());
        $this->functionTranslators = array_merge($this->functionTranslators, $extension->getFunctionTranslators());
        $this->pseudoClassTranslators = array_merge($this->pseudoClassTranslators, $extension->getPseudoClassTranslators());
        $this->attributeMatchingTranslators = array_merge($this->attributeMatchingTranslators, $extension->getAttributeMatchingTranslators());

        return $this;
    }

    /**
     * @param string $name
     *
     * @return Extension\ExtensionInterface
     *
     * @throws ExpressionErrorException
     */
    public function getExtension($name)
    {
        if (!isset($this->extensions[$name])) {
            throw new ExpressionErrorException(sprintf('Extension "%s" not registered.', $name));
        }

        return $this->extensions[$name];
    }

    /**
     * Registers a shortcut parser.
     *
     * @param ParserInterface $shortcut
     *
     * @return Translator
     */
    public function registerParserShortcut(ParserInterface $shortcut)
    {
        $this->shortcutParsers[] = $shortcut;

        return $this;
    }

    /**
     * @param NodeInterface $node
     *
     * @return XPathExpr
     *
     * @throws ExpressionErrorException
     */
    public function nodeToXPath(NodeInterface $node)
    {
        if (!isset($this->nodeTranslators[$node->getNodeName()])) {
            throw new ExpressionErrorException(sprintf('Node "%s" not supported.', $node->getNodeName()));
        }

        return call_user_func($this->nodeTranslators[$node->getNodeName()], $node);
    }

    /**
     * @param string        $combiner
     * @param NodeInterface $xpath
     * @param NodeInterface $combinedXpath
     *
     * @return XPathExpr
     *
     * @throws ExpressionErrorException
     */
    public function addCombination($combiner, NodeInterface $xpath, NodeInterface $combinedXpath)
    {
        if (!isset($this->combinationTranslators[$combiner])) {
            throw new ExpressionErrorException(sprintf('Combiner "%s" not supported.', $combiner));
        }

        return call_user_func($this->combinationTranslators[$combiner], $this->nodeToXPath($xpath), $this->nodeToXPath($combinedXpath));
    }

    /**
     * @param XPathExpr $xpath
     * @param FunctionNode $function
     *
     * @return XPathExpr
     *
     * @throws ExpressionErrorException
     */
    public function addFunction(XPathExpr $xpath, FunctionNode $function)
    {
        if (!isset($this->functionTranslators[$function->getName()])) {
            throw new ExpressionErrorException(sprintf('Function "%s" not supported.', $function->getName()));
        }

        return call_user_func($this->functionTranslators[$function->getName()], $xpath, $function);
    }

    /**
     * @param XPathExpr $xpath
     * @param string    $pseudoClass
     *
     * @return XPathExpr
     *
     * @throws ExpressionErrorException
     */
    public function addPseudoClass(XPathExpr $xpath, $pseudoClass)
    {
        if (!isset($this->pseudoClassTranslators[$pseudoClass])) {
            throw new ExpressionErrorException(sprintf('Pseudo-class "%s" not supported.', $pseudoClass));
        }

        return call_user_func($this->pseudoClassTranslators[$pseudoClass], $xpath);
    }

    /**
     * @param XPathExpr $xpath
     * @param string    $operator
     * @param string    $attribute
     * @param string    $value
     *
     * @throws ExpressionErrorException
     *
     * @return XPathExpr
     */
    public function addAttributeMatching(XPathExpr $xpath, $operator, $attribute, $value)
    {
        if (!isset($this->attributeMatchingTranslators[$operator])) {
            throw new ExpressionErrorException(sprintf('Attribute matcher operator "%s" not supported.', $operator));
        }

        return call_user_func($this->attributeMatchingTranslators[$operator], $xpath, $attribute, $value);
    }

    /**
     * @param string $css
     *
     * @return SelectorNode[]
     */
    private function parseSelectors($css)
    {
        foreach ($this->shortcutParsers as $shortcut) {
            $tokens = $shortcut->parse($css);

            if (!empty($tokens)) {
                return $tokens;
            }
        }

        return $this->mainParser->parse($css);
    }
}
PK��Z��r771Symfony/Component/CssSelector/XPath/XPathExpr.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\XPath;

/**
 * XPath expression translator interface.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class XPathExpr
{
    /**
     * @var string
     */
    private $path;

    /**
     * @var string
     */
    private $element;

    /**
     * @var string
     */
    private $condition;

    /**
     * @param string  $path
     * @param string  $element
     * @param string  $condition
     * @param boolean $starPrefix
     */
    public function __construct($path = '', $element = '*', $condition = '', $starPrefix = false)
    {
        $this->path = $path;
        $this->element = $element;
        $this->condition = $condition;

        if ($starPrefix) {
            $this->addStarPrefix();
        }
    }

    /**
     * @return string
     */
    public function getElement()
    {
        return $this->element;
    }

    /**
     * @param $condition
     *
     * @return XPathExpr
     */
    public function addCondition($condition)
    {
        $this->condition = $this->condition ? sprintf('%s and (%s)', $this->condition, $condition) : $condition;

        return $this;
    }

    /**
     * @return string
     */
    public function getCondition()
    {
        return $this->condition;
    }

    /**
     * @return XPathExpr
     */
    public function addNameTest()
    {
        if ('*' !== $this->element) {
            $this->addCondition('name() = '.Translator::getXpathLiteral($this->element));
            $this->element = '*';
        }

        return $this;
    }

    /**
     * @return XPathExpr
     */
    public function addStarPrefix()
    {
        $this->path .= '*/';

        return $this;
    }

    /**
     * Joins another XPathExpr with a combiner.
     *
     * @param string    $combiner
     * @param XPathExpr $expr
     *
     * @return XPathExpr
     */
    public function join($combiner, XPathExpr $expr)
    {
        $path = $this->__toString().$combiner;

        if ('*/' !== $expr->path) {
            $path .= $expr->path;
        }

        $this->path = $path;
        $this->element = $expr->element;
        $this->condition = $expr->condition;

        return $this;
    }

    /**
     * @return string
     */
    public function __toString()
    {
        $path = $this->path.$this->element;
        $condition = null === $this->condition || '' === $this->condition ? '' : '['.$this->condition.']';

        return $path.$condition;
    }
}
PK��Z
���;Symfony/Component/CssSelector/XPath/TranslatorInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\XPath;

use Symfony\Component\CssSelector\Node\SelectorNode;

/**
 * XPath expression translator interface.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
interface TranslatorInterface
{
    /**
     * Translates a CSS selector to an XPath expression.
     *
     * @param string $cssExpr
     * @param string $prefix
     *
     * @return XPathExpr
     */
    public function cssToXPath($cssExpr, $prefix = 'descendant-or-self::');

    /**
     * Translates a parsed selector node to an XPath expression
     *
     * @param SelectorNode $selector
     * @param string       $prefix
     *
     * @return XPathExpr
     */
    public function selectorToXPath(SelectorNode $selector, $prefix = 'descendant-or-self::');
}
PK��Z��u��CSymfony/Component/CssSelector/XPath/Extension/FunctionExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\XPath\Extension;

use Symfony\Component\CssSelector\Exception\ExpressionErrorException;
use Symfony\Component\CssSelector\Exception\SyntaxErrorException;
use Symfony\Component\CssSelector\Node\FunctionNode;
use Symfony\Component\CssSelector\Parser\Parser;
use Symfony\Component\CssSelector\XPath\Translator;
use Symfony\Component\CssSelector\XPath\XPathExpr;

/**
 * XPath expression translator function extension.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class FunctionExtension extends AbstractExtension
{
    /**
     * {@inheritdoc}
     */
    public function getFunctionTranslators()
    {
        return array(
            'nth-child'        => array($this, 'translateNthChild'),
            'nth-last-child'   => array($this, 'translateNthLastChild'),
            'nth-of-type'      => array($this, 'translateNthOfType'),
            'nth-last-of-type' => array($this, 'translateNthLastOfType'),
            'contains'         => array($this, 'translateContains'),
            'lang'             => array($this, 'translateLang'),
        );
    }

    /**
     * @param XPathExpr    $xpath
     * @param FunctionNode $function
     * @param boolean      $last
     * @param boolean      $addNameTest
     *
     * @return XPathExpr
     *
     * @throws ExpressionErrorException
     */
    public function translateNthChild(XPathExpr $xpath, FunctionNode $function, $last = false, $addNameTest = true)
    {
        try {
            list($a, $b) = Parser::parseSeries($function->getArguments());
        } catch (SyntaxErrorException $e) {
            throw new ExpressionErrorException(sprintf('Invalid series: %s', implode(', ', $function->getArguments())), 0, $e);
        }

        $xpath->addStarPrefix();
        if ($addNameTest) {
            $xpath->addNameTest();
        }

        if (0 === $a) {
            return $xpath->addCondition('position() = '.($last ? 'last() - '.($b - 1) : $b));
        }

        if ($a < 0) {
            if ($b < 1) {
                return $xpath->addCondition('false()');
            }

            $sign = '<=';
        } else {
            $sign = '>=';
        }

        $expr = 'position()';

        if ($last) {
            $expr = 'last() - '.$expr;
            $b--;
        }

        if (0 !== $b) {
            $expr .= ' - '.$b;
        }

        $conditions = array(sprintf('%s %s 0', $expr, $sign));

        if (1 !== $a && -1 !== $a) {
            $conditions[] = sprintf('(%s) mod %d = 0', $expr, $a);
        }

        return $xpath->addCondition(implode(' and ', $conditions));

        // todo: handle an+b, odd, even
        // an+b means every-a, plus b, e.g., 2n+1 means odd
        // 0n+b means b
        // n+0 means a=1, i.e., all elements
        // an means every a elements, i.e., 2n means even
        // -n means -1n
        // -1n+6 means elements 6 and previous
    }

    /**
     * @param XPathExpr    $xpath
     * @param FunctionNode $function
     *
     * @return XPathExpr
     */
    public function translateNthLastChild(XPathExpr $xpath, FunctionNode $function)
    {
        return $this->translateNthChild($xpath, $function, true);
    }

    /**
     * @param XPathExpr    $xpath
     * @param FunctionNode $function
     *
     * @return XPathExpr
     */
    public function translateNthOfType(XPathExpr $xpath, FunctionNode $function)
    {
        return $this->translateNthChild($xpath, $function, false, false);
    }

    /**
     * @param XPathExpr    $xpath
     * @param FunctionNode $function
     *
     * @return XPathExpr
     *
     * @throws ExpressionErrorException
     */
    public function translateNthLastOfType(XPathExpr $xpath, FunctionNode $function)
    {
        if ('*' === $xpath->getElement()) {
            throw new ExpressionErrorException('"*:nth-of-type()" is not implemented.');
        }

        return $this->translateNthChild($xpath, $function, true, false);
    }

    /**
     * @param XPathExpr    $xpath
     * @param FunctionNode $function
     *
     * @return XPathExpr
     *
     * @throws ExpressionErrorException
     */
    public function translateContains(XPathExpr $xpath, FunctionNode $function)
    {
        $arguments = $function->getArguments();
        foreach ($arguments as $token) {
            if (!($token->isString() || $token->isIdentifier())) {
                throw new ExpressionErrorException(
                    'Expected a single string or identifier for :contains(), got '
                    .implode(', ', $arguments)
                );
            }
        }

        return $xpath->addCondition(sprintf(
            'contains(string(.), %s)',
            Translator::getXpathLiteral($arguments[0]->getValue())
        ));
    }

    /**
     * @param XPathExpr    $xpath
     * @param FunctionNode $function
     *
     * @return XPathExpr
     *
     * @throws ExpressionErrorException
     */
    public function translateLang(XPathExpr $xpath, FunctionNode $function)
    {
        $arguments = $function->getArguments();
        foreach ($arguments as $token) {
            if (!($token->isString() || $token->isIdentifier())) {
                throw new ExpressionErrorException(
                    'Expected a single string or identifier for :lang(), got '
                    .implode(', ', $arguments)
                );
            }
        }

        return $xpath->addCondition(sprintf(
            'lang(%s)',
            Translator::getXpathLiteral($arguments[0]->getValue())
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'function';
    }
}
PK��Z�܍��LSymfony/Component/CssSelector/XPath/Extension/AttributeMatchingExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\XPath\Extension;

use Symfony\Component\CssSelector\XPath\Translator;
use Symfony\Component\CssSelector\XPath\XPathExpr;

/**
 * XPath expression translator attribute extension.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class AttributeMatchingExtension extends AbstractExtension
{
    /**
     * {@inheritdoc}
     */
    public function getAttributeMatchingTranslators()
    {
        return array(
            'exists' => array($this, 'translateExists'),
            '='      => array($this, 'translateEquals'),
            '~='     => array($this, 'translateIncludes'),
            '|='     => array($this, 'translateDashMatch'),
            '^='     => array($this, 'translatePrefixMatch'),
            '$='     => array($this, 'translateSuffixMatch'),
            '*='     => array($this, 'translateSubstringMatch'),
            '!='     => array($this, 'translateDifferent'),
        );
    }

    /**
     * @param XPathExpr $xpath
     * @param string    $attribute
     * @param string    $value
     *
     * @return XPathExpr
     */
    public function translateExists(XPathExpr $xpath, $attribute, $value)
    {
        return $xpath->addCondition($attribute);
    }

    /**
     * @param XPathExpr $xpath
     * @param string    $attribute
     * @param string    $value
     *
     * @return XPathExpr
     */
    public function translateEquals(XPathExpr $xpath, $attribute, $value)
    {
        return $xpath->addCondition(sprintf('%s = %s', $attribute, Translator::getXpathLiteral($value)));
    }

    /**
     * @param XPathExpr $xpath
     * @param string    $attribute
     * @param string    $value
     *
     * @return XPathExpr
     */
    public function translateIncludes(XPathExpr $xpath, $attribute, $value)
    {
        return $xpath->addCondition($value ? sprintf(
            '%1$s and contains(concat(\' \', normalize-space(%1$s), \' \'), %2$s)',
            $attribute,
            Translator::getXpathLiteral(' '.$value.' ')
        ) : '0');
    }

    /**
     * @param XPathExpr $xpath
     * @param string    $attribute
     * @param string    $value
     *
     * @return XPathExpr
     */
    public function translateDashMatch(XPathExpr $xpath, $attribute, $value)
    {
        return $xpath->addCondition(sprintf(
            '%1$s and (%1$s = %2$s or starts-with(%1$s, %3$s))',
            $attribute,
            Translator::getXpathLiteral($value),
            Translator::getXpathLiteral($value.'-')
        ));
    }

    /**
     * @param XPathExpr $xpath
     * @param string    $attribute
     * @param string    $value
     *
     * @return XPathExpr
     */
    public function translatePrefixMatch(XPathExpr $xpath, $attribute, $value)
    {
        return $xpath->addCondition($value ? sprintf(
            '%1$s and starts-with(%1$s, %2$s)',
            $attribute,
            Translator::getXpathLiteral($value)
        ) : '0');
    }

    /**
     * @param XPathExpr $xpath
     * @param string    $attribute
     * @param string    $value
     *
     * @return XPathExpr
     */
    public function translateSuffixMatch(XPathExpr $xpath, $attribute, $value)
    {
        return $xpath->addCondition($value ? sprintf(
            '%1$s and substring(%1$s, string-length(%1$s)-%2$s) = %3$s',
            $attribute,
            strlen($value) - 1,
            Translator::getXpathLiteral($value)
        ) : '0');
    }

    /**
     * @param XPathExpr $xpath
     * @param string    $attribute
     * @param string    $value
     *
     * @return XPathExpr
     */
    public function translateSubstringMatch(XPathExpr $xpath, $attribute, $value)
    {
        return $xpath->addCondition($value ? sprintf(
            '%1$s and contains(%1$s, %2$s)',
            $attribute,
            Translator::getXpathLiteral($value)
        ) : '0');
    }

    /**
     * @param XPathExpr $xpath
     * @param string    $attribute
     * @param string    $value
     *
     * @return XPathExpr
     */
    public function translateDifferent(XPathExpr $xpath, $attribute, $value)
    {
        return $xpath->addCondition(sprintf(
            $value ? 'not(%1$s) or %1$s != %2$s' : '%s != %s',
            $attribute,
            Translator::getXpathLiteral($value)
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'attribute-matching';
    }
}
PK��Z�Ѽ`PP?Symfony/Component/CssSelector/XPath/Extension/NodeExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\XPath\Extension;

use Symfony\Component\CssSelector\Node;
use Symfony\Component\CssSelector\XPath\Translator;
use Symfony\Component\CssSelector\XPath\XPathExpr;

/**
 * XPath expression translator node extension.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class NodeExtension extends AbstractExtension
{
    const ELEMENT_NAME_IN_LOWER_CASE    = 1;
    const ATTRIBUTE_NAME_IN_LOWER_CASE  = 2;
    const ATTRIBUTE_VALUE_IN_LOWER_CASE = 4;

    /**
     * @var Translator
     */
    private $translator;

    /**
     * @var int
     */
    private $flags;

    /**
     * Constructor.
     *
     * @param Translator $translator
     * @param int        $flags
     */
    public function __construct(Translator $translator, $flags = 0)
    {
        $this->translator = $translator;
        $this->flags = $flags;
    }

    /**
     * @param int     $flag
     * @param boolean $on
     *
     * @return NodeExtension
     */
    public function setFlag($flag, $on)
    {
        if ($on && !$this->hasFlag($flag)) {
            $this->flags += $flag;
        }

        if (!$on && $this->hasFlag($flag)) {
            $this->flags -= $flag;
        }

        return $this;
    }

    /**
     * @param int $flag
     *
     * @return boolean
     */
    public function hasFlag($flag)
    {
        return $this->flags & $flag;
    }

    /**
     * {@inheritdoc}
     */
    public function getNodeTranslators()
    {
        return array(
            'Selector'         => array($this, 'translateSelector'),
            'CombinedSelector' => array($this, 'translateCombinedSelector'),
            'Negation'         => array($this, 'translateNegation'),
            'Function'         => array($this, 'translateFunction'),
            'Pseudo'           => array($this, 'translatePseudo'),
            'Attribute'        => array($this, 'translateAttribute'),
            'Class'            => array($this, 'translateClass'),
            'Hash'             => array($this, 'translateHash'),
            'Element'          => array($this, 'translateElement'),
        );
    }

    /**
     * @param Node\SelectorNode $node
     *
     * @return XPathExpr
     */
    public function translateSelector(Node\SelectorNode $node)
    {
        return $this->translator->nodeToXPath($node->getTree());
    }

    /**
     * @param Node\CombinedSelectorNode $node
     *
     * @return XPathExpr
     */
    public function translateCombinedSelector(Node\CombinedSelectorNode $node)
    {
        return $this->translator->addCombination($node->getCombinator(), $node->getSelector(), $node->getSubSelector());
    }

    /**
     * @param Node\NegationNode $node
     *
     * @return XPathExpr
     */
    public function translateNegation(Node\NegationNode $node)
    {
        $xpath = $this->translator->nodeToXPath($node->getSelector());
        $subXpath = $this->translator->nodeToXPath($node->getSubSelector());
        $subXpath->addNameTest();

        if ($subXpath->getCondition()) {
            return $xpath->addCondition(sprintf('not(%s)', $subXpath->getCondition()));
        }

        return $xpath->addCondition('0');
    }

    /**
     * @param Node\FunctionNode $node
     *
     * @return XPathExpr
     */
    public function translateFunction(Node\FunctionNode $node)
    {
        $xpath = $this->translator->nodeToXPath($node->getSelector());

        return $this->translator->addFunction($xpath, $node);
    }

    /**
     * @param Node\PseudoNode $node
     *
     * @return XPathExpr
     */
    public function translatePseudo(Node\PseudoNode $node)
    {
        $xpath = $this->translator->nodeToXPath($node->getSelector());

        return $this->translator->addPseudoClass($xpath, $node->getIdentifier());
    }

    /**
     * @param Node\AttributeNode $node
     *
     * @return XPathExpr
     */
    public function translateAttribute(Node\AttributeNode $node)
    {
        $name = $node->getAttribute();
        $safe = $this->isSafeName($name);

        if ($this->hasFlag(self::ATTRIBUTE_NAME_IN_LOWER_CASE)) {
            $name = strtolower($name);
        }

        if ($node->getNamespace()) {
            $name = sprintf('%s:%s', $node->getNamespace(), $name);
            $safe = $safe && $this->isSafeName($node->getNamespace());
        }

        $attribute = $safe ? '@'.$name : sprintf('attribute::*[name() = %s]', Translator::getXpathLiteral($name));
        $value = $node->getValue();
        $xpath = $this->translator->nodeToXPath($node->getSelector());

        if ($this->hasFlag(self::ATTRIBUTE_VALUE_IN_LOWER_CASE)) {
            $value = strtolower($value);
        }

        return $this->translator->addAttributeMatching($xpath, $node->getOperator(), $attribute, $value);
    }

    /**
     * @param Node\ClassNode $node
     *
     * @return XPathExpr
     */
    public function translateClass(Node\ClassNode $node)
    {
        $xpath = $this->translator->nodeToXPath($node->getSelector());

        return $this->translator->addAttributeMatching($xpath, '~=', '@class', $node->getName());
    }

    /**
     * @param Node\HashNode $node
     *
     * @return XPathExpr
     */
    public function translateHash(Node\HashNode $node)
    {
        $xpath = $this->translator->nodeToXPath($node->getSelector());

        return $this->translator->addAttributeMatching($xpath, '=', '@id', $node->getId());
    }

    /**
     * @param Node\ElementNode $node
     *
     * @return XPathExpr
     */
    public function translateElement(Node\ElementNode $node)
    {
        $element = $node->getElement();

        if ($this->hasFlag(self::ELEMENT_NAME_IN_LOWER_CASE)) {
            $element = strtolower($element);
        }

        if ($element) {
            $safe = $this->isSafeName($element);
        } else {
            $element = '*';
            $safe = true;
        }

        if ($node->getNamespace()) {
            $element = sprintf('%s:%s', $node->getNamespace(), $element);
            $safe = $safe && $this->isSafeName($node->getNamespace());
        }

        $xpath = new XPathExpr('', $element);

        if (!$safe) {
            $xpath->addNameTest();
        }

        return $xpath;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'node';
    }

    /**
     * Tests if given name is safe.
     *
     * @param string $name
     *
     * @return boolean
     */
    private function isSafeName($name)
    {
        return 0 < preg_match('~^[a-zA-Z_][a-zA-Z0-9_.-]*$~', $name);
    }
}
PK��Z$p��BB?Symfony/Component/CssSelector/XPath/Extension/HtmlExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\XPath\Extension;

use Symfony\Component\CssSelector\Exception\ExpressionErrorException;
use Symfony\Component\CssSelector\Node\FunctionNode;
use Symfony\Component\CssSelector\XPath\Translator;
use Symfony\Component\CssSelector\XPath\XPathExpr;

/**
 * XPath expression translator HTML extension.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class HtmlExtension extends AbstractExtension
{
    /**
     * Constructor.
     *
     * @param Translator $translator
     */
    public function __construct(Translator $translator)
    {
        $translator
            ->getExtension('node')
            ->setFlag(NodeExtension::ELEMENT_NAME_IN_LOWER_CASE, true)
            ->setFlag(NodeExtension::ATTRIBUTE_NAME_IN_LOWER_CASE, true);
    }

    /**
     * {@inheritdoc}
     */
    public function getPseudoClassTranslators()
    {
        return array(
            'checked'  => array($this, 'translateChecked'),
            'link'     => array($this, 'translateLink'),
            'disabled' => array($this, 'translateDisabled'),
            'enabled'  => array($this, 'translateEnabled'),
            'selected' => array($this, 'translateSelected'),
            'invalid'  => array($this, 'translateInvalid'),
            'hover'    => array($this, 'translateHover'),
            'visited'  => array($this, 'translateVisited'),
        );
    }

    /**
     * {@inheritdoc}
     */
    public function getFunctionTranslators()
    {
        return array(
            'lang' => array($this, 'translateLang'),
        );
    }

    /**
     * @param XPathExpr $xpath
     *
     * @return XPathExpr
     */
    public function translateChecked(XPathExpr $xpath)
    {
        return $xpath->addCondition(
            '(@checked '
            ."and (name(.) = 'input' or name(.) = 'command')"
            ."and (@type = 'checkbox' or @type = 'radio'))"
        );
    }

    /**
     * @param XPathExpr $xpath
     *
     * @return XPathExpr
     */
    public function translateLink(XPathExpr $xpath)
    {
        return $xpath->addCondition("@href and (name(.) = 'a' or name(.) = 'link' or name(.) = 'area')");
    }

    /**
     * @param XPathExpr $xpath
     *
     * @return XPathExpr
     */
    public function translateDisabled(XPathExpr $xpath)
    {
        return $xpath->addCondition(
            "("
                ."@disabled and"
                ."("
                    ."(name(.) = 'input' and @type != 'hidden')"
                    ." or name(.) = 'button'"
                    ." or name(.) = 'select'"
                    ." or name(.) = 'textarea'"
                    ." or name(.) = 'command'"
                    ." or name(.) = 'fieldset'"
                    ." or name(.) = 'optgroup'"
                    ." or name(.) = 'option'"
                .")"
            .") or ("
                ."(name(.) = 'input' and @type != 'hidden')"
                ." or name(.) = 'button'"
                ." or name(.) = 'select'"
                ." or name(.) = 'textarea'"
            .")"
            ." and ancestor::fieldset[@disabled]"
        );
        // todo: in the second half, add "and is not a descendant of that fieldset element's first legend element child, if any."
    }

    /**
     * @param XPathExpr $xpath
     *
     * @return XPathExpr
     */
    public function translateEnabled(XPathExpr $xpath)
    {
        return $xpath->addCondition(
            '('
                .'@href and ('
                    ."name(.) = 'a'"
                    ." or name(.) = 'link'"
                    ." or name(.) = 'area'"
                .')'
            .') or ('
                .'('
                    ."name(.) = 'command'"
                    ." or name(.) = 'fieldset'"
                    ." or name(.) = 'optgroup'"
                .')'
                .' and not(@disabled)'
            .') or ('
                .'('
                    ."(name(.) = 'input' and @type != 'hidden')"
                    ." or name(.) = 'button'"
                    ." or name(.) = 'select'"
                    ." or name(.) = 'textarea'"
                    ." or name(.) = 'keygen'"
                .')'
                ." and not (@disabled or ancestor::fieldset[@disabled])"
            .') or ('
                ."name(.) = 'option' and not("
                    ."@disabled or ancestor::optgroup[@disabled]"
                .')'
            .')'
        );
    }

    /**
     * @param XPathExpr    $xpath
     * @param FunctionNode $function
     *
     * @return XPathExpr
     *
     * @throws ExpressionErrorException
     */
    public function translateLang(XPathExpr $xpath, FunctionNode $function)
    {
        $arguments = $function->getArguments();
        foreach ($arguments as $token) {
            if (!($token->isString() || $token->isIdentifier())) {
                throw new ExpressionErrorException(
                    'Expected a single string or identifier for :lang(), got '
                    .implode(', ', $arguments)
                );
            }
        }

        return $xpath->addCondition(sprintf(
            'ancestor-or-self::*[@lang][1][starts-with(concat('
            ."translate(@%s, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), '-')"
            .', %s)]',
            'lang',
            Translator::getXpathLiteral(strtolower($arguments[0]->getValue()).'-')
        ));
    }

    /**
     * @param XPathExpr $xpath
     *
     * @return XPathExpr
     */
    public function translateSelected(XPathExpr $xpath)
    {
        return $xpath->addCondition("(@selected and name(.) = 'option')");
    }

    /**
     * @param XPathExpr $xpath
     *
     * @return XPathExpr
     */
    public function translateInvalid(XPathExpr $xpath)
    {
        return $xpath->addCondition('0');
    }

    /**
     * @param XPathExpr $xpath
     *
     * @return XPathExpr
     */
    public function translateHover(XPathExpr $xpath)
    {
        return $xpath->addCondition('0');
    }

    /**
     * @param XPathExpr $xpath
     *
     * @return XPathExpr
     */
    public function translateVisited(XPathExpr $xpath)
    {
        return $xpath->addCondition('0');
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'html';
    }
}
PK��Zc�-��CSymfony/Component/CssSelector/XPath/Extension/AbstractExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\XPath\Extension;

/**
 * XPath expression translator abstract extension.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
abstract class AbstractExtension implements ExtensionInterface
{
    /**
     * {@inheritdoc}
     */
    public function getNodeTranslators()
    {
        return array();
    }

    /**
     * {@inheritdoc}
     */
    public function getCombinationTranslators()
    {
        return array();
    }

    /**
     * {@inheritdoc}
     */
    public function getFunctionTranslators()
    {
        return array();
    }

    /**
     * {@inheritdoc}
     */
    public function getPseudoClassTranslators()
    {
        return array();
    }

    /**
     * {@inheritdoc}
     */
    public function getAttributeMatchingTranslators()
    {
        return array();
    }
}
PK��Z��x=	=	FSymfony/Component/CssSelector/XPath/Extension/CombinationExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\XPath\Extension;

use Symfony\Component\CssSelector\XPath\XPathExpr;

/**
 * XPath expression translator combination extension.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class CombinationExtension extends AbstractExtension
{
    /**
     * {@inheritdoc}
     */
    public function getCombinationTranslators()
    {
        return array(
            ' ' => array($this, 'translateDescendant'),
            '>' => array($this, 'translateChild'),
            '+' => array($this, 'translateDirectAdjacent'),
            '~' => array($this, 'translateIndirectAdjacent'),
        );
    }

    /**
     * @param XPathExpr $xpath
     * @param XPathExpr $combinedXpath
     *
     * @return XPathExpr
     */
    public function translateDescendant(XPathExpr $xpath, XPathExpr $combinedXpath)
    {
        return $xpath->join('/descendant-or-self::*/', $combinedXpath);
    }

    /**
     * @param XPathExpr $xpath
     * @param XPathExpr $combinedXpath
     *
     * @return XPathExpr
     */
    public function translateChild(XPathExpr $xpath, XPathExpr $combinedXpath)
    {
        return $xpath->join('/', $combinedXpath);
    }

    /**
     * @param XPathExpr $xpath
     * @param XPathExpr $combinedXpath
     *
     * @return XPathExpr
     */
    public function translateDirectAdjacent(XPathExpr $xpath, XPathExpr $combinedXpath)
    {
        return $xpath
            ->join('/following-sibling::', $combinedXpath)
            ->addNameTest()
            ->addCondition('position() = 1');
    }

    /**
     * @param XPathExpr $xpath
     * @param XPathExpr $combinedXpath
     *
     * @return XPathExpr
     */
    public function translateIndirectAdjacent(XPathExpr $xpath, XPathExpr $combinedXpath)
    {
        return $xpath->join('/following-sibling::', $combinedXpath);
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'combination';
    }
}
PK��Z ����FSymfony/Component/CssSelector/XPath/Extension/PseudoClassExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\XPath\Extension;

use Symfony\Component\CssSelector\Exception\ExpressionErrorException;
use Symfony\Component\CssSelector\XPath\XPathExpr;

/**
 * XPath expression translator pseudo-class extension.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class PseudoClassExtension extends AbstractExtension
{
    /**
     * {@inheritdoc}
     */
    public function getPseudoClassTranslators()
    {
        return array(
            'root'          => array($this, 'translateRoot'),
            'first-child'   => array($this, 'translateFirstChild'),
            'last-child'    => array($this, 'translateLastChild'),
            'first-of-type' => array($this, 'translateFirstOfType'),
            'last-of-type'  => array($this, 'translateLastOfType'),
            'only-child'    => array($this, 'translateOnlyChild'),
            'only-of-type'  => array($this, 'translateOnlyOfType'),
            'empty'         => array($this, 'translateEmpty'),
        );
    }

    /**
     * @param XPathExpr $xpath
     *
     * @return XPathExpr
     */
    public function translateRoot(XPathExpr $xpath)
    {
        return $xpath->addCondition('not(parent::*)');
    }

    /**
     * @param XPathExpr $xpath
     *
     * @return XPathExpr
     */
    public function translateFirstChild(XPathExpr $xpath)
    {
        return $xpath
            ->addStarPrefix()
            ->addNameTest()
            ->addCondition('position() = 1');
    }

    /**
     * @param XPathExpr $xpath
     *
     * @return XPathExpr
     */
    public function translateLastChild(XPathExpr $xpath)
    {
        return $xpath
            ->addStarPrefix()
            ->addNameTest()
            ->addCondition('position() = last()');
    }

    /**
     * @param XPathExpr $xpath
     *
     * @return XPathExpr
     *
     * @throws ExpressionErrorException
     */
    public function translateFirstOfType(XPathExpr $xpath)
    {
        if ('*' === $xpath->getElement()) {
            throw new ExpressionErrorException('"*:first-of-type" is not implemented.');
        }

        return $xpath
            ->addStarPrefix()
            ->addCondition('position() = 1');
    }

    /**
     * @param XPathExpr $xpath
     *
     * @return XPathExpr
     *
     * @throws ExpressionErrorException
     */
    public function translateLastOfType(XPathExpr $xpath)
    {
        if ('*' === $xpath->getElement()) {
            throw new ExpressionErrorException('"*:last-of-type" is not implemented.');
        }

        return $xpath
            ->addStarPrefix()
            ->addCondition('position() = last()');
    }

    /**
     * @param XPathExpr $xpath
     *
     * @return XPathExpr
     */
    public function translateOnlyChild(XPathExpr $xpath)
    {
        return $xpath
            ->addStarPrefix()
            ->addNameTest()
            ->addCondition('last() = 1');
    }

    /**
     * @param XPathExpr $xpath
     *
     * @return XPathExpr
     *
     * @throws ExpressionErrorException
     */
    public function translateOnlyOfType(XPathExpr $xpath)
    {
        if ('*' === $xpath->getElement()) {
            throw new ExpressionErrorException('"*:only-of-type" is not implemented.');
        }

        return $xpath->addCondition('last() = 1');
    }

    /**
     * @param XPathExpr $xpath
     *
     * @return XPathExpr
     */
    public function translateEmpty(XPathExpr $xpath)
    {
        return $xpath->addCondition('not(*) and not(string-length())');
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'pseudo-class';
    }
}
PK��Z���||DSymfony/Component/CssSelector/XPath/Extension/ExtensionInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\XPath\Extension;

/**
 * XPath expression translator extension interface.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
interface ExtensionInterface
{
    /**
     * Returns node translators.
     *
     * @return callable[]
     */
    public function getNodeTranslators();

    /**
     * Returns combination translators.
     *
     * @return callable[]
     */
    public function getCombinationTranslators();

    /**
     * Returns function translators.
     *
     * @return callable[]
     */
    public function getFunctionTranslators();

    /**
     * Returns pseudo-class translators.
     *
     * @return callable[]
     */
    public function getPseudoClassTranslators();

    /**
     * Returns attribute operation translators.
     *
     * @return callable[]
     */
    public function getAttributeMatchingTranslators();

    /**
     * Returns extension name.
     *
     * @return string
     */
    public function getName();
}
PK��Zu�UU,Symfony/Component/CssSelector/autoloader.phpnu�[���<?php

spl_autoload_register(function ($class) {
    if ('\\' == $class[0]) {
        $class = substr($class, 1);
    }

    if (
        0 === strpos($class, 'Symfony\\Component\\CssSelector\\')
        &&
        file_exists($file = __DIR__.'/../../../'.str_replace('\\', '/', $class).'.php')
    ) {
        require_once $file;
    }
});
PK��Z,+?��;Symfony/Component/CssSelector/Node/CombinedSelectorNode.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Node;

/**
 * Represents a combined node.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class CombinedSelectorNode extends AbstractNode
{
    /**
     * @var NodeInterface
     */
    private $selector;

    /**
     * @var string
     */
    private $combinator;

    /**
     * @var NodeInterface
     */
    private $subSelector;

    /**
     * @param NodeInterface $selector
     * @param string        $combinator
     * @param NodeInterface $subSelector
     */
    public function __construct(NodeInterface $selector, $combinator, NodeInterface $subSelector)
    {
        $this->selector = $selector;
        $this->combinator = $combinator;
        $this->subSelector = $subSelector;
    }

    /**
     * @return NodeInterface
     */
    public function getSelector()
    {
        return $this->selector;
    }

    /**
     * @return string
     */
    public function getCombinator()
    {
        return $this->combinator;
    }

    /**
     * @return NodeInterface
     */
    public function getSubSelector()
    {
        return $this->subSelector;
    }

    /**
     * {@inheritdoc}
     */
    public function getSpecificity()
    {
        return $this->selector->getSpecificity()->plus($this->subSelector->getSpecificity());
    }

    /**
     * {@inheritdoc}
     */
    public function __toString()
    {
        $combinator = ' ' === $this->combinator ? '<followed>' : $this->combinator;

        return sprintf('%s[%s %s %s]', $this->getNodeName(), $this->selector, $combinator, $this->subSelector);
    }
}
PK��Z�r�I��4Symfony/Component/CssSelector/Node/NodeInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Node;

/**
 * Interface for nodes.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
interface NodeInterface
{
    /**
     * Returns node's name.
     *
     * @return string
     */
    public function getNodeName();

    /**
     * Returns node's specificity.
     *
     * @return Specificity
     */
    public function getSpecificity();

    /**
     * Returns node's string representation.
     *
     * @return string
     */
    public function __toString();
}
PK��Z����3Symfony/Component/CssSelector/Node/SelectorNode.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Node;

/**
 * Represents a "<selector>(::|:)<pseudoElement>" node.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class SelectorNode extends AbstractNode
{
    /**
     * @var NodeInterface
     */
    private $tree;

    /**
     * @var null|string
     */
    private $pseudoElement;

    /**
     * @param NodeInterface $tree
     * @param null|string   $pseudoElement
     */
    public function __construct(NodeInterface $tree, $pseudoElement = null)
    {
        $this->tree = $tree;
        $this->pseudoElement = $pseudoElement ? strtolower($pseudoElement) : null;
    }

    /**
     * @return NodeInterface
     */
    public function getTree()
    {
        return $this->tree;
    }

    /**
     * @return null|string
     */
    public function getPseudoElement()
    {
        return $this->pseudoElement;
    }

    /**
     * {@inheritdoc}
     */
    public function getSpecificity()
    {
        return $this->tree->getSpecificity()->plus(new Specificity(0, 0, $this->pseudoElement ? 1 : 0));
    }

    /**
     * {@inheritdoc}
     */
    public function __toString()
    {
        return sprintf('%s[%s%s]', $this->getNodeName(), $this->tree, $this->pseudoElement ? '::'.$this->pseudoElement : '');
    }
}
PK��Z�pM2��3Symfony/Component/CssSelector/Node/AbstractNode.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Node;

/**
 * Abstract base node class.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
abstract class AbstractNode implements NodeInterface
{
    /**
     * @var string
     */
    private $nodeName;

    /**
     * @return string
     */
    public function getNodeName()
    {
        if (null === $this->nodeName) {
            $this->nodeName = preg_replace('~.*\\\\([^\\\\]+)Node$~', '$1', get_called_class());
        }

        return $this->nodeName;
    }
}
PK��Z�Г^FF2Symfony/Component/CssSelector/Node/ElementNode.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Node;

/**
 * Represents a "<namespace>|<element>" node.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class ElementNode extends AbstractNode
{
    /**
     * @var string|null
     */
    private $namespace;

    /**
     * @var string|null
     */
    private $element;

    /**
     * @param string|null $namespace
     * @param string|null $element
     */
    public function __construct($namespace = null, $element = null)
    {
        $this->namespace = $namespace;
        $this->element = $element;
    }

    /**
     * @return null|string
     */
    public function getNamespace()
    {
        return $this->namespace;
    }

    /**
     * @return null|string
     */
    public function getElement()
    {
        return $this->element;
    }

    /**
     * {@inheritdoc}
     */
    public function getSpecificity()
    {
        return new Specificity(0, 0, $this->element ? 1 : 0);
    }

    /**
     * {@inheritdoc}
     */
    public function __toString()
    {
        $element = $this->element ?: '*';

        return sprintf('%s[%s]', $this->getNodeName(), $this->namespace ? $this->namespace.'|'.$element : $element);
    }
}
PK��Z�.��221Symfony/Component/CssSelector/Node/PseudoNode.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Node;

/**
 * Represents a "<selector>:<identifier>" node.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class PseudoNode extends AbstractNode
{
    /**
     * @var NodeInterface
     */
    private $selector;

    /**
     * @var string
     */
    private $identifier;

    /**
     * @param NodeInterface $selector
     * @param string        $identifier
     */
    public function __construct(NodeInterface $selector, $identifier)
    {
        $this->selector = $selector;
        $this->identifier = strtolower($identifier);
    }

    /**
     * @return NodeInterface
     */
    public function getSelector()
    {
        return $this->selector;
    }

    /**
     * @return string
     */
    public function getIdentifier()
    {
        return $this->identifier;
    }

    /**
     * {@inheritdoc}
     */
    public function getSpecificity()
    {
        return $this->selector->getSpecificity()->plus(new Specificity(0, 1, 0));
    }

    /**
     * {@inheritdoc}
     */
    public function __toString()
    {
        return sprintf('%s[%s:%s]', $this->getNodeName(), $this->selector, $this->identifier);
    }
}
PK��Z	�i���0Symfony/Component/CssSelector/Node/ClassNode.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Node;

/**
 * Represents a "<selector>.<name>" node.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class ClassNode extends AbstractNode
{
    /**
     * @var NodeInterface
     */
    private $selector;

    /**
     * @var string
     */
    private $name;

    /**
     * @param NodeInterface $selector
     * @param string        $name
     */
    public function __construct(NodeInterface $selector, $name)
    {
        $this->selector = $selector;
        $this->name = $name;
    }

    /**
     * @return NodeInterface
     */
    public function getSelector()
    {
        return $this->selector;
    }

    /**
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * {@inheritdoc}
     */
    public function getSpecificity()
    {
        return $this->selector->getSpecificity()->plus(new Specificity(0, 1, 0));
    }

    /**
     * {@inheritdoc}
     */
    public function __toString()
    {
        return sprintf('%s[%s.%s]', $this->getNodeName(), $this->selector, $this->name);
    }
}
PK��Z����bb3Symfony/Component/CssSelector/Node/NegationNode.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Node;

/**
 * Represents a "<selector>:not(<identifier>)" node.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class NegationNode extends AbstractNode
{
    /**
     * @var NodeInterface
     */
    private $selector;

    /**
     * @var NodeInterface
     */
    private $subSelector;

    /**
     * @param NodeInterface $selector
     * @param NodeInterface $subSelector
     */
    public function __construct(NodeInterface $selector, NodeInterface $subSelector)
    {
        $this->selector = $selector;
        $this->subSelector = $subSelector;
    }

    /**
     * @return NodeInterface
     */
    public function getSelector()
    {
        return $this->selector;
    }

    /**
     * @return NodeInterface
     */
    public function getSubSelector()
    {
        return $this->subSelector;
    }

    /**
     * {@inheritdoc}
     */
    public function getSpecificity()
    {
        return $this->selector->getSpecificity()->plus($this->subSelector->getSpecificity());
    }

    /**
     * {@inheritdoc}
     */
    public function __toString()
    {
        return sprintf('%s[%s:not(%s)]', $this->getNodeName(), $this->selector, $this->subSelector);
    }
}
PK��Z�x�2Symfony/Component/CssSelector/Node/Specificity.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Node;

/**
 * Represents a node specificity.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @see http://www.w3.org/TR/selectors/#specificity
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class Specificity
{
    const A_FACTOR = 100;
    const B_FACTOR = 10;
    const C_FACTOR = 1;

    /**
     * @var int
     */
    private $a;

    /**
     * @var int
     */
    private $b;

    /**
     * @var int
     */
    private $c;

    /**
     * Constructor.
     *
     * @param int $a
     * @param int $b
     * @param int $c
     */
    public function __construct($a, $b, $c)
    {
        $this->a = $a;
        $this->b = $b;
        $this->c = $c;
    }

    /**
     * @param Specificity $specificity
     *
     * @return Specificity
     */
    public function plus(Specificity $specificity)
    {
        return new self($this->a + $specificity->a, $this->b + $specificity->b, $this->c + $specificity->c);
    }

    /**
     * Returns global specificity value.
     *
     * @return int
     */
    public function getValue()
    {
        return $this->a * self::A_FACTOR + $this->b * self::B_FACTOR + $this->c * self::C_FACTOR;
    }
}
PK��Z�#^[��/Symfony/Component/CssSelector/Node/HashNode.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Node;

/**
 * Represents a "<selector>#<id>" node.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class HashNode extends AbstractNode
{
    /**
     * @var NodeInterface
     */
    private $selector;

    /**
     * @var string
     */
    private $id;

    /**
     * @param NodeInterface $selector
     * @param string        $id
     */
    public function __construct(NodeInterface $selector, $id)
    {
        $this->selector = $selector;
        $this->id = $id;
    }

    /**
     * @return NodeInterface
     */
    public function getSelector()
    {
        return $this->selector;
    }

    /**
     * @return string
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * {@inheritdoc}
     */
    public function getSpecificity()
    {
        return $this->selector->getSpecificity()->plus(new Specificity(1, 0, 0));
    }

    /**
     * {@inheritdoc}
     */
    public function __toString()
    {
        return sprintf('%s[%s#%s]', $this->getNodeName(), $this->selector, $this->id);
    }
}
PK��ZF��K
K
4Symfony/Component/CssSelector/Node/AttributeNode.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Node;

/**
 * Represents a "<selector>[<namespace>|<attribute> <operator> <value>]" node.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class AttributeNode extends AbstractNode
{
    /**
     * @var NodeInterface
     */
    private $selector;

    /**
     * @var string
     */
    private $namespace;

    /**
     * @var string
     */
    private $attribute;

    /**
     * @var string
     */
    private $operator;

    /**
     * @var string
     */
    private $value;

    /**
     * @param NodeInterface $selector
     * @param string        $namespace
     * @param string        $attribute
     * @param string        $operator
     * @param string        $value
     */
    public function __construct(NodeInterface $selector, $namespace, $attribute, $operator, $value)
    {
        $this->selector = $selector;
        $this->namespace = $namespace;
        $this->attribute = $attribute;
        $this->operator = $operator;
        $this->value = $value;
    }

    /**
     * @return NodeInterface
     */
    public function getSelector()
    {
        return $this->selector;
    }

    /**
     * @return string
     */
    public function getNamespace()
    {
        return $this->namespace;
    }

    /**
     * @return string
     */
    public function getAttribute()
    {
        return $this->attribute;
    }

    /**
     * @return string
     */
    public function getOperator()
    {
        return $this->operator;
    }

    /**
     * @return string
     */
    public function getValue()
    {
        return $this->value;
    }

    /**
     * {@inheritdoc}
     */
    public function getSpecificity()
    {
        return $this->selector->getSpecificity()->plus(new Specificity(0, 1, 0));
    }

    /**
     * {@inheritdoc}
     */
    public function __toString()
    {
        $attribute = $this->namespace ? $this->namespace.'|'.$this->attribute : $this->attribute;

        return 'exists' === $this->operator
            ? sprintf('%s[%s[%s]]', $this->getNodeName(), $this->selector, $attribute)
            : sprintf("%s[%s[%s %s '%s']]", $this->getNodeName(), $this->selector, $attribute, $this->operator, $this->value);
    }
}
PK��Z�x�3Symfony/Component/CssSelector/Node/FunctionNode.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Node;

use Symfony\Component\CssSelector\Parser\Token;

/**
 * Represents a "<selector>:<name>(<arguments>)" node.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class FunctionNode extends AbstractNode
{
    /**
     * @var NodeInterface
     */
    private $selector;

    /**
     * @var string
     */
    private $name;

    /**
     * @var Token[]
     */
    private $arguments;

    /**
     * @param NodeInterface $selector
     * @param string        $name
     * @param Token[]       $arguments
     */
    public function __construct(NodeInterface $selector, $name, array $arguments = array())
    {
        $this->selector = $selector;
        $this->name = strtolower($name);
        $this->arguments = $arguments;
    }

    /**
     * @return NodeInterface
     */
    public function getSelector()
    {
        return $this->selector;
    }

    /**
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @return Token[]
     */
    public function getArguments()
    {
        return $this->arguments;
    }

    /**
     * {@inheritdoc}
     */
    public function getSpecificity()
    {
        return $this->selector->getSpecificity()->plus(new Specificity(0, 1, 0));
    }

    /**
     * {@inheritdoc}
     */
    public function __toString()
    {
        $arguments = implode(', ', array_map(function (Token $token) {
            return "'".$token->getValue()."'";
        }, $this->arguments));

        return sprintf('%s[%s:%s(%s)]', $this->getNodeName(), $this->selector, $this->name, $arguments ? '['.$arguments.']' : '');
    }
}
PK��Zm��c��BSymfony/Component/CssSelector/Exception/InternalErrorException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Exception;

/**
 * ParseException is thrown when a CSS selector syntax is not valid.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class InternalErrorException extends ParseException implements ExceptionInterface
{
}
PK��Z��מ�@Symfony/Component/CssSelector/Exception/SyntaxErrorException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Exception;

use Symfony\Component\CssSelector\Parser\Token;

/**
 * ParseException is thrown when a CSS selector syntax is not valid.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class SyntaxErrorException extends ParseException implements ExceptionInterface
{
    /**
     * @param string $expectedValue
     * @param Token  $foundToken
     *
     * @return SyntaxErrorException
     */
    public static function unexpectedToken($expectedValue, Token $foundToken)
    {
        return new self(sprintf('Expected %s, but %s found.', $expectedValue, $foundToken));
    }

    /**
     * @param string $pseudoElement
     * @param string $unexpectedLocation
     *
     * @return SyntaxErrorException
     */
    public static function pseudoElementFound($pseudoElement, $unexpectedLocation)
    {
        return new self(sprintf('Unexpected pseudo-element "::%s" found %s.', $pseudoElement, $unexpectedLocation));
    }

    /**
     * @param int $position
     *
     * @return SyntaxErrorException
     */
    public static function unclosedString($position)
    {
        return new self(sprintf('Unclosed/invalid string at %s.', $position));
    }

    /**
     * @return SyntaxErrorException
     */
    public static function nestedNot()
    {
        return new self('Got nested ::not().');
    }

    /**
     * @return SyntaxErrorException
     */
    public static function stringAsFunctionArgument()
    {
        return new self('String not allowed as function argument.');
    }
}
PK��Z/pT�DSymfony/Component/CssSelector/Exception/ExpressionErrorException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Exception;

/**
 * ParseException is thrown when a CSS selector syntax is not valid.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class ExpressionErrorException extends ParseException implements ExceptionInterface
{
}
PK��Zgf�GBB>Symfony/Component/CssSelector/Exception/ExceptionInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Exception;

/**
 * Interface for exceptions.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
interface ExceptionInterface
{
}
PK��Z'[|ɀ�:Symfony/Component/CssSelector/Exception/ParseException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Exception;

/**
 * ParseException is thrown when a CSS selector syntax is not valid.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ParseException extends \Exception implements ExceptionInterface
{
}
PK��Z^�}		-Symfony/Component/CssSelector/CssSelector.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector;

use Symfony\Component\CssSelector\Parser\Shortcut\ClassParser;
use Symfony\Component\CssSelector\Parser\Shortcut\ElementParser;
use Symfony\Component\CssSelector\Parser\Shortcut\EmptyStringParser;
use Symfony\Component\CssSelector\Parser\Shortcut\HashParser;
use Symfony\Component\CssSelector\XPath\Extension\HtmlExtension;
use Symfony\Component\CssSelector\XPath\Translator;

/**
 * CssSelector is the main entry point of the component and can convert CSS
 * selectors to XPath expressions.
 *
 * $xpath = CssSelector::toXpath('h1.foo');
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class CssSelector
{
    private static $html = true;

    /**
     * Translates a CSS expression to its XPath equivalent.
     * Optionally, a prefix can be added to the resulting XPath
     * expression with the $prefix parameter.
     *
     * @param mixed   $cssExpr The CSS expression.
     * @param string  $prefix  An optional prefix for the XPath expression.
     *
     * @return string
     *
     * @api
     */
    public static function toXPath($cssExpr, $prefix = 'descendant-or-self::')
    {
        $translator = new Translator();

        if (self::$html) {
            $translator->registerExtension(new HtmlExtension($translator));
        }

        $translator
            ->registerParserShortcut(new EmptyStringParser())
            ->registerParserShortcut(new ElementParser())
            ->registerParserShortcut(new ClassParser())
            ->registerParserShortcut(new HashParser())
        ;

        return $translator->cssToXPath($cssExpr, $prefix);
    }

    /**
     * Enables the HTML extension.
     */
    public static function enableHtmlExtension()
    {
        self::$html = true;
    }

    /**
     * Disables the HTML extension.
     */
    public static function disableHtmlExtension()
    {
        self::$html = false;
    }
}
PK��Z5#� HH<Symfony/Component/CssSelector/Parser/Shortcut/HashParser.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Parser\Shortcut;

use Symfony\Component\CssSelector\Node\ElementNode;
use Symfony\Component\CssSelector\Node\HashNode;
use Symfony\Component\CssSelector\Node\SelectorNode;
use Symfony\Component\CssSelector\Parser\ParserInterface;

/**
 * CSS selector hash parser shortcut.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class HashParser implements ParserInterface
{
    /**
     * {@inheritdoc}
     */
    public function parse($source)
    {
        // Matches an optional namespace, optional element, and required id
        // $source = 'test|input#ab6bd_field';
        // $matches = array (size=5)
        //     0 => string 'test:input#ab6bd_field' (length=22)
        //     1 => string 'test:' (length=5)
        //     2 => string 'test' (length=4)
        //     3 => string 'input' (length=5)
        //     4 => string 'ab6bd_field' (length=11)
        if (preg_match('/^(([a-z]+)\|)?([\w-]+|\*)?#([\w-]+)$/i', trim($source), $matches)) {
            return array(
                new SelectorNode(new HashNode(new ElementNode($matches[2] ?: null, $matches[3] ?: null), $matches[4]))
            );
        }

        return array();
    }
}
PK��Zҵܗ��CSymfony/Component/CssSelector/Parser/Shortcut/EmptyStringParser.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Parser\Shortcut;

use Symfony\Component\CssSelector\Node\ElementNode;
use Symfony\Component\CssSelector\Node\SelectorNode;
use Symfony\Component\CssSelector\Parser\ParserInterface;

/**
 * CSS selector class parser shortcut.
 *
 * This shortcut ensure compatibility with previous version.
 * - The parser fails to parse an empty string.
 * - In the previous version, an empty string matches each tags.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class EmptyStringParser implements ParserInterface
{
    /**
     * {@inheritdoc}
     */
    public function parse($source)
    {
        // Matches an empty string
        if ($source == '') {
            return array(new SelectorNode(new ElementNode(null, '*')));
        }

        return array();
    }
}
PK��ZTR#[PP=Symfony/Component/CssSelector/Parser/Shortcut/ClassParser.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Parser\Shortcut;

use Symfony\Component\CssSelector\Node\ClassNode;
use Symfony\Component\CssSelector\Node\ElementNode;
use Symfony\Component\CssSelector\Node\SelectorNode;
use Symfony\Component\CssSelector\Parser\ParserInterface;

/**
 * CSS selector class parser shortcut.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class ClassParser implements ParserInterface
{
    /**
     * {@inheritdoc}
     */
    public function parse($source)
    {
        // Matches an optional namespace, optional element, and required class
        // $source = 'test|input.ab6bd_field';
        // $matches = array (size=5)
        //     0 => string 'test:input.ab6bd_field' (length=22)
        //     1 => string 'test:' (length=5)
        //     2 => string 'test' (length=4)
        //     3 => string 'input' (length=5)
        //     4 => string 'ab6bd_field' (length=11)
        if (preg_match('/^(([a-z]+)\|)?([\w-]+|\*)?\.([\w-]+)$/i', trim($source), $matches)) {
            return array(
                new SelectorNode(new ClassNode(new ElementNode($matches[2] ?: null, $matches[3] ?: null), $matches[4]))
            );
        }

        return array();
    }
}
PK��Z�Z�>��?Symfony/Component/CssSelector/Parser/Shortcut/ElementParser.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Parser\Shortcut;

use Symfony\Component\CssSelector\Node\ElementNode;
use Symfony\Component\CssSelector\Node\SelectorNode;
use Symfony\Component\CssSelector\Parser\ParserInterface;

/**
 * CSS selector element parser shortcut.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class ElementParser implements ParserInterface
{
    /**
     * {@inheritdoc}
     */
    public function parse($source)
    {
        // Matches an optional namespace, required element or `*`
        // $source = 'testns|testel';
        // $matches = array (size=4)
        //     0 => string 'testns:testel' (length=13)
        //     1 => string 'testns:' (length=7)
        //     2 => string 'testns' (length=6)
        //     3 => string 'testel' (length=6)
        if (preg_match('/^(([a-z]+)\|)?([\w-]+|\*)$/i', trim($source), $matches)) {
            return array(new SelectorNode(new ElementNode($matches[2] ?: null, $matches[3])));
        }

        return array();
    }
}
PK��Z���QQ4Symfony/Component/CssSelector/Parser/TokenStream.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Parser;

use Symfony\Component\CssSelector\Exception\InternalErrorException;
use Symfony\Component\CssSelector\Exception\SyntaxErrorException;

/**
 * CSS selector token stream.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class TokenStream
{
    /**
     * @var Token[]
     */
    private $tokens = array();

    /**
     * @var boolean
     */
    private $frozen = false;

    /**
     * @var Token[]
     */
    private $used = array();

    /**
     * @var int
     */
    private $cursor = 0;

    /**
     * @var Token|null
     */
    private $peeked = null;

    /**
     * @var boolean
     */
    private $peeking = false;

    /**
     * Pushes a token.
     *
     * @param Token $token
     *
     * @return TokenStream
     */
    public function push(Token $token)
    {
        $this->tokens[] = $token;

        return $this;
    }

    /**
     * Freezes stream.
     *
     * @return TokenStream
     */
    public function freeze()
    {
        $this->frozen = true;

        return $this;
    }

    /**
     * Returns next token.
     *
     * @throws InternalErrorException If there is no more token
     *
     * @return Token
     */
    public function getNext()
    {
        if ($this->peeking) {
            $this->peeking = false;
            $this->used[] = $this->peeked;

            return $this->peeked;
        }

        if (!isset($this->tokens[$this->cursor])) {
            throw new InternalErrorException('Unexpected token stream end.');
        }

        return $this->tokens[$this->cursor ++];
    }

    /**
     * Returns peeked token.
     *
     * @return Token
     */
    public function getPeek()
    {
        if (!$this->peeking) {
            $this->peeked = $this->getNext();
            $this->peeking = true;
        }

        return $this->peeked;
    }

    /**
     * Returns used tokens.
     *
     * @return Token[]
     */
    public function getUsed()
    {
        return $this->used;
    }

    /**
     * Returns nex identifier token.
     *
     * @throws SyntaxErrorException If next token is not an identifier
     *
     * @return string The identifier token value
     */
    public function getNextIdentifier()
    {
        $next = $this->getNext();

        if (!$next->isIdentifier()) {
            throw SyntaxErrorException::unexpectedToken('identifier', $next);
        }

        return $next->getValue();
    }

    /**
     * Returns nex identifier or star delimiter token.
     *
     * @throws SyntaxErrorException If next token is not an identifier or a star delimiter
     *
     * @return null|string The identifier token value or null if star found
     */
    public function getNextIdentifierOrStar()
    {
        $next = $this->getNext();

        if ($next->isIdentifier()) {
            return $next->getValue();
        }

        if ($next->isDelimiter(array('*'))) {
            return null;
        }

        throw SyntaxErrorException::unexpectedToken('identifier or "*"', $next);
    }

    /**
     * Skips next whitespace if any.
     */
    public function skipWhitespace()
    {
        $peek = $this->getPeek();

        if ($peek->isWhitespace()) {
            $this->getNext();
        }
    }
}
PK��Z��6\5
5
>Symfony/Component/CssSelector/Parser/Handler/StringHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Parser\Handler;

use Symfony\Component\CssSelector\Exception\InternalErrorException;
use Symfony\Component\CssSelector\Exception\SyntaxErrorException;
use Symfony\Component\CssSelector\Parser\Reader;
use Symfony\Component\CssSelector\Parser\Token;
use Symfony\Component\CssSelector\Parser\TokenStream;
use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerEscaping;
use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns;

/**
 * CSS selector comment handler.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class StringHandler implements HandlerInterface
{
    /**
     * @var TokenizerPatterns
     */
    private $patterns;

    /**
     * @var TokenizerEscaping
     */
    private $escaping;

    /**
     * @param TokenizerPatterns $patterns
     * @param TokenizerEscaping $escaping
     */
    public function __construct(TokenizerPatterns $patterns, TokenizerEscaping $escaping)
    {
        $this->patterns = $patterns;
        $this->escaping = $escaping;
    }

    /**
     * {@inheritdoc}
     */
    public function handle(Reader $reader, TokenStream $stream)
    {
        $quote = $reader->getSubstring(1);

        if (!in_array($quote, array("'", '"'))) {
            return false;
        }

        $reader->moveForward(1);
        $match = $reader->findPattern($this->patterns->getQuotedStringPattern($quote));

        if (!$match) {
            throw new InternalErrorException(sprintf('Should have found at least an empty match at %s.', $reader->getPosition()));
        }

        // check unclosed strings
        if (strlen($match[0]) === $reader->getRemainingLength()) {
            throw SyntaxErrorException::unclosedString($reader->getPosition() - 1);
        }

        // check quotes pairs validity
        if ($quote !== $reader->getSubstring(1, strlen($match[0]))) {
            throw SyntaxErrorException::unclosedString($reader->getPosition() - 1);
        }

        $string = $this->escaping->escapeUnicodeAndNewLine($match[0]);
        $stream->push(new Token(Token::TYPE_STRING, $string, $reader->getPosition()));
        $reader->moveForward(strlen($match[0]) + 1);

        return true;
    }
}
PK��Z8�D�^^?Symfony/Component/CssSelector/Parser/Handler/CommentHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Parser\Handler;

use Symfony\Component\CssSelector\Parser\Reader;
use Symfony\Component\CssSelector\Parser\TokenStream;

/**
 * CSS selector comment handler.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class CommentHandler implements HandlerInterface
{
    /**
     * {@inheritdoc}
     */
    public function handle(Reader $reader, TokenStream $stream)
    {
        if ('/*' !== $reader->getSubstring(2)) {
            return false;
        }

        $offset = $reader->getOffset('*/');

        if (false === $offset) {
            $reader->moveToEnd();
        } else {
            $reader->moveForward($offset + 2);
        }

        return true;
    }
}
PK��Z�X{��<Symfony/Component/CssSelector/Parser/Handler/HashHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Parser\Handler;

use Symfony\Component\CssSelector\Parser\Reader;
use Symfony\Component\CssSelector\Parser\Token;
use Symfony\Component\CssSelector\Parser\TokenStream;
use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerEscaping;
use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns;

/**
 * CSS selector comment handler.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class HashHandler implements HandlerInterface
{
    /**
     * @var TokenizerPatterns
     */
    private $patterns;

    /**
     * @var TokenizerEscaping
     */
    private $escaping;

    /**
     * @param TokenizerPatterns $patterns
     * @param TokenizerEscaping $escaping
     */
    public function __construct(TokenizerPatterns $patterns, TokenizerEscaping $escaping)
    {
        $this->patterns = $patterns;
        $this->escaping = $escaping;
    }

    /**
     * {@inheritdoc}
     */
    public function handle(Reader $reader, TokenStream $stream)
    {
        $match = $reader->findPattern($this->patterns->getHashPattern());

        if (!$match) {
            return false;
        }

        $value = $this->escaping->escapeUnicode($match[1]);
        $stream->push(new Token(Token::TYPE_HASH, $value, $reader->getPosition()));
        $reader->moveForward(strlen($match[0]));

        return true;
    }
}
PK��Zh��ffASymfony/Component/CssSelector/Parser/Handler/HandlerInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Parser\Handler;

use Symfony\Component\CssSelector\Parser\Reader;
use Symfony\Component\CssSelector\Parser\TokenStream;

/**
 * CSS selector handler interface.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
interface HandlerInterface
{
    /**
     * @param Reader      $reader
     * @param TokenStream $stream
     *
     * @return boolean
     */
    public function handle(Reader $reader, TokenStream $stream);
}
PK��Ze'n��>Symfony/Component/CssSelector/Parser/Handler/NumberHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Parser\Handler;

use Symfony\Component\CssSelector\Parser\Reader;
use Symfony\Component\CssSelector\Parser\Token;
use Symfony\Component\CssSelector\Parser\TokenStream;
use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns;

/**
 * CSS selector comment handler.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class NumberHandler implements HandlerInterface
{
    /**
     * @var TokenizerPatterns
     */
    private $patterns;

    /**
     * @param TokenizerPatterns $patterns
     */
    public function __construct(TokenizerPatterns $patterns)
    {
        $this->patterns = $patterns;
    }

    /**
     * {@inheritdoc}
     */
    public function handle(Reader $reader, TokenStream $stream)
    {
        $match = $reader->findPattern($this->patterns->getNumberPattern());

        if (!$match) {
            return false;
        }

        $stream->push(new Token(Token::TYPE_NUMBER, $match[0], $reader->getPosition()));
        $reader->moveForward(strlen($match[0]));

        return true;
    }
}
PK��Z�#BSymfony/Component/CssSelector/Parser/Handler/IdentifierHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Parser\Handler;

use Symfony\Component\CssSelector\Parser\Reader;
use Symfony\Component\CssSelector\Parser\Token;
use Symfony\Component\CssSelector\Parser\TokenStream;
use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerEscaping;
use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns;

/**
 * CSS selector comment handler.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class IdentifierHandler implements HandlerInterface
{
    /**
     * @var TokenizerPatterns
     */
    private $patterns;

    /**
     * @var TokenizerEscaping
     */
    private $escaping;

    /**
     * @param TokenizerPatterns $patterns
     * @param TokenizerEscaping $escaping
     */
    public function __construct(TokenizerPatterns $patterns, TokenizerEscaping $escaping)
    {
        $this->patterns = $patterns;
        $this->escaping = $escaping;
    }

    /**
     * {@inheritdoc}
     */
    public function handle(Reader $reader, TokenStream $stream)
    {
        $match = $reader->findPattern($this->patterns->getIdentifierPattern());

        if (!$match) {
            return false;
        }

        $value = $this->escaping->escapeUnicode($match[0]);
        $stream->push(new Token(Token::TYPE_IDENTIFIER, $value, $reader->getPosition()));
        $reader->moveForward(strlen($match[0]));

        return true;
    }
}
PK��Z����BSymfony/Component/CssSelector/Parser/Handler/WhitespaceHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Parser\Handler;

use Symfony\Component\CssSelector\Parser\Reader;
use Symfony\Component\CssSelector\Parser\Token;
use Symfony\Component\CssSelector\Parser\TokenStream;

/**
 * CSS selector whitespace handler.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class WhitespaceHandler implements HandlerInterface
{
    /**
     * {@inheritdoc}
     */
    public function handle(Reader $reader, TokenStream $stream)
    {
        $match = $reader->findPattern('~^[ \t\r\n\f]+~');

        if (false === $match) {
            return false;
        }

        $stream->push(new Token(Token::TYPE_WHITESPACE, $match[0], $reader->getPosition()));
        $reader->moveForward(strlen($match[0]));

        return true;
    }
}
PK��Z6N�D1D1/Symfony/Component/CssSelector/Parser/Parser.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Parser;

use Symfony\Component\CssSelector\Exception\SyntaxErrorException;
use Symfony\Component\CssSelector\Node;
use Symfony\Component\CssSelector\Parser\Tokenizer\Tokenizer;

/**
 * CSS selector parser.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class Parser implements ParserInterface
{
    /**
     * @var Tokenizer
     */
    private $tokenizer;

    /**
     * Constructor.
     *
     * @param null|Tokenizer $tokenizer
     */
    public function __construct(Tokenizer $tokenizer = null)
    {
        $this->tokenizer = $tokenizer ?: new Tokenizer();
    }

    /**
     * {@inheritdoc}
     */
    public function parse($source)
    {
        $reader = new Reader($source);
        $stream = $this->tokenizer->tokenize($reader);

        return $this->parseSelectorList($stream);
    }

    /**
     * Parses the arguments for ":nth-child()" and friends.
     *
     * @param Token[] $tokens
     *
     * @throws SyntaxErrorException
     *
     * @return array
     */
    public static function parseSeries(array $tokens)
    {
        foreach ($tokens as $token) {
            if ($token->isString()) {
                throw SyntaxErrorException::stringAsFunctionArgument();
            }
        }

        $joined = trim(implode('', array_map(function (Token $token) {
            return $token->getValue();
        }, $tokens)));

        $int = function ($string) {
            if (!is_numeric($string)) {
                throw SyntaxErrorException::stringAsFunctionArgument();
            }

            return (int) $string;
        };

        switch (true) {
            case 'odd' === $joined:
                return array(2, 1);
            case 'even' === $joined:
                return array(2, 0);
            case 'n' === $joined:
                return array(1, 0);
            case false === strpos($joined, 'n'):
                return array(0, $int($joined));
        }

        $split = explode('n', $joined);
        $first = isset($split[0]) ? $split[0] : null;

        return array(
            $first ? ('-' === $first || '+' === $first ? $int($first.'1') : $int($first)) : 1,
            isset($split[1]) && $split[1] ? $int($split[1]) : 0
        );
    }

    /**
     * Parses selector nodes.
     *
     * @param TokenStream $stream
     *
     * @return array
     */
    private function parseSelectorList(TokenStream $stream)
    {
        $stream->skipWhitespace();
        $selectors = array();

        while (true) {
            $selectors[] = $this->parserSelectorNode($stream);

            if ($stream->getPeek()->isDelimiter(array(','))) {
                $stream->getNext();
                $stream->skipWhitespace();
            } else {
                break;
            }
        }

        return $selectors;
    }

    /**
     * Parses next selector or combined node.
     *
     * @param TokenStream $stream
     *
     * @throws SyntaxErrorException
     *
     * @return Node\SelectorNode
     */
    private function parserSelectorNode(TokenStream $stream)
    {
        list($result, $pseudoElement) = $this->parseSimpleSelector($stream);

        while (true) {
            $stream->skipWhitespace();
            $peek = $stream->getPeek();

            if ($peek->isFileEnd() || $peek->isDelimiter(array(','))) {
                break;
            }

            if (null !== $pseudoElement) {
                throw SyntaxErrorException::pseudoElementFound($pseudoElement, 'not at the end of a selector');
            }

            if ($peek->isDelimiter(array('+', '>', '~'))) {
                $combinator = $stream->getNext()->getValue();
                $stream->skipWhitespace();
            } else {
                $combinator = ' ';
            }

            list($nextSelector, $pseudoElement) = $this->parseSimpleSelector($stream);
            $result = new Node\CombinedSelectorNode($result, $combinator, $nextSelector);
        }

        return new Node\SelectorNode($result, $pseudoElement);
    }

    /**
     * Parses next simple node (hash, class, pseudo, negation).
     *
     * @param TokenStream $stream
     * @param boolean     $insideNegation
     *
     * @throws SyntaxErrorException
     *
     * @return array
     */
    private function parseSimpleSelector(TokenStream $stream, $insideNegation = false)
    {
        $stream->skipWhitespace();

        $selectorStart = count($stream->getUsed());
        $result = $this->parseElementNode($stream);
        $pseudoElement = null;

        while (true) {
            $peek = $stream->getPeek();
            if ($peek->isWhitespace()
                || $peek->isFileEnd()
                || $peek->isDelimiter(array(',', '+', '>', '~'))
                || ($insideNegation && $peek->isDelimiter(array(')')))
            ) {
                break;
            }

            if (null !== $pseudoElement) {
                throw SyntaxErrorException::pseudoElementFound($pseudoElement, 'not at the end of a selector');
            }

            if ($peek->isHash()) {
                $result = new Node\HashNode($result, $stream->getNext()->getValue());
            } elseif ($peek->isDelimiter(array('.'))) {
                $stream->getNext();
                $result = new Node\ClassNode($result, $stream->getNextIdentifier());
            } elseif ($peek->isDelimiter(array('['))) {
                $stream->getNext();
                $result = $this->parseAttributeNode($result, $stream);
            } elseif ($peek->isDelimiter(array(':'))) {
                $stream->getNext();

                if ($stream->getPeek()->isDelimiter(array(':'))) {
                    $stream->getNext();
                    $pseudoElement = $stream->getNextIdentifier();

                    continue;
                }

                $identifier = $stream->getNextIdentifier();
                if (in_array(strtolower($identifier), array('first-line', 'first-letter', 'before', 'after'))) {
                    // Special case: CSS 2.1 pseudo-elements can have a single ':'.
                    // Any new pseudo-element must have two.
                    $pseudoElement = $identifier;

                    continue;
                }

                if (!$stream->getPeek()->isDelimiter(array('('))) {
                    $result = new Node\PseudoNode($result, $identifier);

                    continue;
                }

                $stream->getNext();
                $stream->skipWhitespace();

                if ('not' === strtolower($identifier)) {
                    if ($insideNegation) {
                        throw SyntaxErrorException::nestedNot();
                    }

                    list($argument, $argumentPseudoElement) = $this->parseSimpleSelector($stream, true);
                    $next = $stream->getNext();

                    if (null !== $argumentPseudoElement) {
                        throw SyntaxErrorException::pseudoElementFound($argumentPseudoElement, 'inside ::not()');
                    }

                    if (!$next->isDelimiter(array(')'))) {
                        throw SyntaxErrorException::unexpectedToken('")"', $next);
                    }

                    $result = new Node\NegationNode($result, $argument);
                } else {
                    $arguments = array();
                    $next = null;

                    while (true) {
                        $stream->skipWhitespace();
                        $next = $stream->getNext();

                        if ($next->isIdentifier()
                            || $next->isString()
                            || $next->isNumber()
                            || $next->isDelimiter(array('+', '-'))
                        ) {
                            $arguments[] = $next;
                        } elseif ($next->isDelimiter(array(')'))) {
                            break;
                        } else {
                            throw SyntaxErrorException::unexpectedToken('an argument', $next);
                        }
                    }

                    if (empty($arguments)) {
                        throw SyntaxErrorException::unexpectedToken('at least one argument', $next);
                    }

                    $result = new Node\FunctionNode($result, $identifier, $arguments);
                }
            } else {
                throw SyntaxErrorException::unexpectedToken('selector', $peek);
            }
        }

        if (count($stream->getUsed()) === $selectorStart) {
            throw SyntaxErrorException::unexpectedToken('selector', $stream->getPeek());
        }

        return array($result, $pseudoElement);
    }

    /**
     * Parses next element node.
     *
     * @param TokenStream $stream
     *
     * @return Node\ElementNode
     */
    private function parseElementNode(TokenStream $stream)
    {
        $peek = $stream->getPeek();

        if ($peek->isIdentifier() || $peek->isDelimiter(array('*'))) {
            if ($peek->isIdentifier()) {
                $namespace = $stream->getNext()->getValue();
            } else {
                $stream->getNext();
                $namespace = null;
            }

            if ($stream->getPeek()->isDelimiter(array('|'))) {
                $stream->getNext();
                $element = $stream->getNextIdentifierOrStar();
            } else {
                $element = $namespace;
                $namespace = null;
            }
        } else {
            $element = $namespace = null;
        }

        return new Node\ElementNode($namespace, $element);
    }

    /**
     * Parses next attribute node.
     *
     * @param Node\NodeInterface $selector
     * @param TokenStream        $stream
     *
     * @throws SyntaxErrorException
     *
     * @return Node\AttributeNode
     */
    private function parseAttributeNode(Node\NodeInterface $selector, TokenStream $stream)
    {
        $stream->skipWhitespace();
        $attribute = $stream->getNextIdentifierOrStar();

        if (null === $attribute && !$stream->getPeek()->isDelimiter(array('|'))) {
            throw SyntaxErrorException::unexpectedToken('"|"', $stream->getPeek());
        }

        if ($stream->getPeek()->isDelimiter(array('|'))) {
            $stream->getNext();

            if ($stream->getPeek()->isDelimiter(array('='))) {
                $namespace = null;
                $stream->getNext();
                $operator = '|=';
            } else {
                $namespace = $attribute;
                $attribute = $stream->getNextIdentifier();
                $operator = null;
            }
        } else {
            $namespace = $operator = null;
        }

        if (null === $operator) {
            $stream->skipWhitespace();
            $next = $stream->getNext();

            if ($next->isDelimiter(array(']'))) {
                return new Node\AttributeNode($selector, $namespace, $attribute, 'exists', null);
            } elseif ($next->isDelimiter(array('='))) {
                $operator = '=';
            } elseif ($next->isDelimiter(array('^', '$', '*', '~', '|', '!'))
                && $stream->getPeek()->isDelimiter(array('='))
            ) {
                $operator = $next->getValue().'=';
                $stream->getNext();
            } else {
                throw SyntaxErrorException::unexpectedToken('operator', $next);
            }
        }

        $stream->skipWhitespace();
        $value = $stream->getNext();

        if ($value->isNumber()) {
            // if the value is a number, it's casted into a string
            $value = new Token(Token::TYPE_STRING, (string) $value->getValue(), $value->getPosition());
        }

        if (!($value->isIdentifier() || $value->isString())) {
            throw SyntaxErrorException::unexpectedToken('string or identifier', $value);
        }

        $stream->skipWhitespace();
        $next = $stream->getNext();

        if (!$next->isDelimiter(array(']'))) {
            throw SyntaxErrorException::unexpectedToken('"]"', $next);
        }

        return new Node\AttributeNode($selector, $namespace, $attribute, $operator, $value->getValue());
    }
}
PK��Z;���		/Symfony/Component/CssSelector/Parser/Reader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Parser;

/**
 * CSS selector reader.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class Reader
{
    /**
     * @var string
     */
    private $source;

    /**
     * @var int
     */
    private $length;

    /**
     * @var int
     */
    private $position = 0;

    /**
     * @param string $source
     */
    public function __construct($source)
    {
        $this->source = $source;
        $this->length = strlen($source);
    }

    /**
     * @return bool
     */
    public function isEOF()
    {
        return $this->position >= $this->length;
    }

    /**
     * @return int
     */
    public function getPosition()
    {
        return $this->position;
    }

    /**
     * @return int
     */
    public function getRemainingLength()
    {
        return $this->length - $this->position;
    }

    /**
     * @param int $length
     * @param int $offset
     *
     * @return string
     */
    public function getSubstring($length, $offset = 0)
    {
        return substr($this->source, $this->position + $offset, $length);
    }

    /**
     * @param string $string
     *
     * @return int
     */
    public function getOffset($string)
    {
        $position = strpos($this->source, $string, $this->position);

        return false === $position ? false : $position - $this->position;
    }

    /**
     * @param string $pattern
     *
     * @return bool
     */
    public function findPattern($pattern)
    {
        $source = substr($this->source, $this->position);

        if (preg_match($pattern, $source, $matches)) {
            return $matches;
        }

        return false;
    }

    /**
     * @param int $length
     */
    public function moveForward($length)
    {
        $this->position += $length;
    }

    /**
     */
    public function moveToEnd()
    {
        $this->position = $this->length;
    }
}
PK��Z�AEo118Symfony/Component/CssSelector/Parser/ParserInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Parser;

use Symfony\Component\CssSelector\Node\SelectorNode;

/**
 * CSS selector parser interface.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
interface ParserInterface
{
    /**
     * Parses given selector source into an array of tokens.
     *
     * @param string $source
     *
     * @return SelectorNode[]
     */
    public function parse($source);
}
PK��Z�zZ<��.Symfony/Component/CssSelector/Parser/Token.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Parser;

/**
 * CSS selector token.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class Token
{
    const TYPE_FILE_END   = 'eof';
    const TYPE_DELIMITER  = 'delimiter';
    const TYPE_WHITESPACE = 'whitespace';
    const TYPE_IDENTIFIER = 'identifier';
    const TYPE_HASH       = 'hash';
    const TYPE_NUMBER     = 'number';
    const TYPE_STRING     = 'string';

    /**
     * @var int
     */
    private $type;

    /**
     * @var string
     */
    private $value;

    /**
     * @var int
     */
    private $position;

    /**
     * @param int    $type
     * @param string $value
     * @param int    $position
     */
    public function __construct($type, $value, $position)
    {
        $this->type = $type;
        $this->value = $value;
        $this->position = $position;
    }

    /**
     * @return int
     */
    public function getType()
    {
        return $this->type;
    }

    /**
     * @return string
     */
    public function getValue()
    {
        return $this->value;
    }

    /**
     * @return int
     */
    public function getPosition()
    {
        return $this->position;
    }

    /**
     * @return boolean
     */
    public function isFileEnd()
    {
        return self::TYPE_FILE_END === $this->type;
    }

    /**
     * @param array $values
     *
     * @return boolean
     */
    public function isDelimiter(array $values = array())
    {
        if (self::TYPE_DELIMITER !== $this->type) {
            return false;
        }

        if (empty($values)) {
            return true;
        }

        return in_array($this->value, $values);
    }

    /**
     * @return boolean
     */
    public function isWhitespace()
    {
        return self::TYPE_WHITESPACE === $this->type;
    }

    /**
     * @return boolean
     */
    public function isIdentifier()
    {
        return self::TYPE_IDENTIFIER === $this->type;
    }

    /**
     * @return boolean
     */
    public function isHash()
    {
        return self::TYPE_HASH === $this->type;
    }

    /**
     * @return boolean
     */
    public function isNumber()
    {
        return self::TYPE_NUMBER === $this->type;
    }

    /**
     * @return boolean
     */
    public function isString()
    {
        return self::TYPE_STRING === $this->type;
    }

    /**
     * @return string
     */
    public function __toString()
    {
        if ($this->value) {
            return sprintf('<%s "%s" at %s>', $this->type, $this->value, $this->position);
        }

        return sprintf('<%s at %s>', $this->type, $this->position);
    }
}
PK��Z>�<��
�
DSymfony/Component/CssSelector/Parser/Tokenizer/TokenizerPatterns.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Parser\Tokenizer;

/**
 * CSS selector tokenizer patterns builder.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class TokenizerPatterns
{
    /**
     * @var string
     */
    private $unicodeEscapePattern;

    /**
     * @var string
     */
    private $simpleEscapePattern;

    /**
     * @var string
     */
    private $newLineEscapePattern;

    /**
     * @var string
     */
    private $escapePattern;

    /**
     * @var string
     */
    private $stringEscapePattern;

    /**
     * @var string
     */
    private $nonAsciiPattern;

    /**
     * @var string
     */
    private $nmCharPattern;

    /**
     * @var string
     */
    private $nmStartPattern;

    /**
     * @var string
     */
    private $identifierPattern;

    /**
     * @var string
     */
    private $hashPattern;

    /**
     * @var string
     */
    private $numberPattern;

    /**
     * @var string
     */
    private $quotedStringPattern;

    /**
     * Constructor.
     */
    public function __construct()
    {
        $this->unicodeEscapePattern = '\\\\([0-9a-f]{1,6})(?:\r\n|[ \n\r\t\f])?';
        $this->simpleEscapePattern = '\\\\(.)';
        $this->newLineEscapePattern = '\\\\(?:\n|\r\n|\r|\f)';
        $this->escapePattern = $this->unicodeEscapePattern.'|\\\\[^\n\r\f0-9a-f]';
        $this->stringEscapePattern = $this->newLineEscapePattern.'|'.$this->escapePattern;
        $this->nonAsciiPattern = '[^\x00-\x7F]';
        $this->nmCharPattern = '[_a-z0-9-]|'.$this->escapePattern.'|'.$this->nonAsciiPattern;
        $this->nmStartPattern = '[_a-z]|'.$this->escapePattern.'|'.$this->nonAsciiPattern;
        $this->identifierPattern = '(?:'.$this->nmStartPattern.')(?:'.$this->nmCharPattern.')*';
        $this->hashPattern = '#((?:'.$this->nmCharPattern.')+)';
        $this->numberPattern = '[+-]?(?:[0-9]*\.[0-9]+|[0-9]+)';
        $this->quotedStringPattern = '([^\n\r\f%s]|'.$this->stringEscapePattern.')*';
    }

    /**
     * @return string
     */
    public function getNewLineEscapePattern()
    {
        return '~^'.$this->newLineEscapePattern.'~';
    }

    /**
     * @return string
     */
    public function getSimpleEscapePattern()
    {
        return '~^'.$this->simpleEscapePattern.'~';
    }

    /**
     * @return string
     */
    public function getUnicodeEscapePattern()
    {
        return '~^'.$this->unicodeEscapePattern.'~i';
    }

    /**
     * @return string
     */
    public function getIdentifierPattern()
    {
        return '~^'.$this->identifierPattern.'~i';
    }

    /**
     * @return string
     */
    public function getHashPattern()
    {
        return '~^'.$this->hashPattern.'~i';
    }

    /**
     * @return string
     */
    public function getNumberPattern()
    {
        return '~^'.$this->numberPattern.'~';
    }

    /**
     * @param string $quote
     *
     * @return string
     */
    public function getQuotedStringPattern($quote)
    {
        return '~^'.sprintf($this->quotedStringPattern, $quote).'~i';
    }
}
PK��Z�S�kFF<Symfony/Component/CssSelector/Parser/Tokenizer/Tokenizer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Parser\Tokenizer;

use Symfony\Component\CssSelector\Parser\Handler;
use Symfony\Component\CssSelector\Parser\Reader;
use Symfony\Component\CssSelector\Parser\Token;
use Symfony\Component\CssSelector\Parser\TokenStream;

/**
 * CSS selector tokenizer.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class Tokenizer
{
    /**
     * @var Handler\HandlerInterface[]
     */
    private $handlers;

    /**
     * Constructor.
     */
    public function __construct()
    {
        $patterns = new TokenizerPatterns();
        $escaping = new TokenizerEscaping($patterns);

        $this->handlers = array(
            new Handler\WhitespaceHandler(),
            new Handler\IdentifierHandler($patterns, $escaping),
            new Handler\HashHandler($patterns, $escaping),
            new Handler\StringHandler($patterns, $escaping),
            new Handler\NumberHandler($patterns),
            new Handler\CommentHandler(),
        );
    }

    /**
     * Tokenize selector source code.
     *
     * @param Reader $reader
     *
     * @return TokenStream
     */
    public function tokenize(Reader $reader)
    {
        $stream = new TokenStream();

        while (!$reader->isEOF()) {
            foreach ($this->handlers as $handler) {
                if ($handler->handle($reader, $stream)) {
                    continue 2;
                }
            }

            $stream->push(new Token(Token::TYPE_DELIMITER, $reader->getSubstring(1), $reader->getPosition()));
            $reader->moveForward(1);
        }

        return $stream
            ->push(new Token(Token::TYPE_FILE_END, null, $reader->getPosition()))
            ->freeze();
    }
}
PK��Z ��W55DSymfony/Component/CssSelector/Parser/Tokenizer/TokenizerEscaping.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Parser\Tokenizer;

/**
 * CSS selector tokenizer escaping applier.
 *
 * This component is a port of the Python cssselector library,
 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class TokenizerEscaping
{
    /**
     * @var TokenizerPatterns
     */
    private $patterns;

    /**
     * @param TokenizerPatterns $patterns
     */
    public function __construct(TokenizerPatterns $patterns)
    {
        $this->patterns = $patterns;
    }

    /**
     * @param string $value
     *
     * @return string
     */
    public function escapeUnicode($value)
    {
        $value = $this->replaceUnicodeSequences($value);

        return preg_replace($this->patterns->getSimpleEscapePattern(), '$1', $value);
    }

    /**
     * @param string $value
     *
     * @return string
     */
    public function escapeUnicodeAndNewLine($value)
    {
        $value = preg_replace($this->patterns->getNewLineEscapePattern(), '', $value);

        return $this->escapeUnicode($value);
    }

    /**
     * @param string $value
     *
     * @return string
     */
    private function replaceUnicodeSequences($value)
    {
        return preg_replace_callback($this->patterns->getUnicodeEscapePattern(), function (array $match) {
            $code = $match[1];

            if (bin2hex($code) > 0xFFFD) {
                $code = '\\FFFD';
            }

            return mb_convert_encoding(pack('H*', $code), 'UTF-8', 'UCS-2BE');
        }, $value);
    }
}
PK��Zb�k���+Symfony/Component/EventDispatcher/Event.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\EventDispatcher;

/**
 * Event is the base class for classes containing event data.
 *
 * This class contains no event data. It is used by events that do not pass
 * state information to an event handler when an event is raised.
 *
 * You can call the method stopPropagation() to abort the execution of
 * further listeners in your event listener.
 *
 * @author  Guilherme Blanco <guilhermeblanco@hotmail.com>
 * @author  Jonathan Wage <jonwage@gmail.com>
 * @author  Roman Borschel <roman@code-factory.org>
 * @author  Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Event
{
    /**
     * @var Boolean Whether no further event listeners should be triggered
     */
    private $propagationStopped = false;

    /**
     * @var EventDispatcher Dispatcher that dispatched this event
     */
    private $dispatcher;

    /**
     * @var string This event's name
     */
    private $name;

    /**
     * Returns whether further event listeners should be triggered.
     *
     * @see Event::stopPropagation
     * @return Boolean Whether propagation was already stopped for this event.
     *
     * @api
     */
    public function isPropagationStopped()
    {
        return $this->propagationStopped;
    }

    /**
     * Stops the propagation of the event to further event listeners.
     *
     * If multiple event listeners are connected to the same event, no
     * further event listener will be triggered once any trigger calls
     * stopPropagation().
     *
     * @api
     */
    public function stopPropagation()
    {
        $this->propagationStopped = true;
    }

    /**
     * Stores the EventDispatcher that dispatches this Event
     *
     * @param EventDispatcherInterface $dispatcher
     *
     * @deprecated Deprecated in 2.4, to be removed in 3.0. The event dispatcher is passed to the listener call.
     *
     * @api
     */
    public function setDispatcher(EventDispatcherInterface $dispatcher)
    {
        $this->dispatcher = $dispatcher;
    }

    /**
     * Returns the EventDispatcher that dispatches this Event
     *
     * @return EventDispatcherInterface
     *
     * @deprecated Deprecated in 2.4, to be removed in 3.0. The event dispatcher is passed to the listener call.
     *
     * @api
     */
    public function getDispatcher()
    {
        return $this->dispatcher;
    }

    /**
     * Gets the event's name.
     *
     * @return string
     *
     * @deprecated Deprecated in 2.4, to be removed in 3.0. The event name is passed to the listener call.
     *
     * @api
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Sets the event's name property.
     *
     * @param string $name The event name.
     *
     * @deprecated Deprecated in 2.4, to be removed in 3.0. The event name is passed to the listener call.
     *
     * @api
     */
    public function setName($name)
    {
        $this->name = $name;
    }
}
PK��Z��YY0Symfony/Component/EventDispatcher/autoloader.phpnu�[���<?php

spl_autoload_register(function ($class) {
    if ('\\' == $class[0]) {
        $class = substr($class, 1);
    }

    if (
        0 === strpos($class, 'Symfony\\Component\\EventDispatcher\\')
        &&
        file_exists($file = __DIR__.'/../../../'.str_replace('\\', '/', $class).'.php')
    ) {
        require_once $file;
    }
});
PK��Z�
���MSymfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\EventDispatcher\Debug;

/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface TraceableEventDispatcherInterface
{
    /**
     * Gets the called listeners.
     *
     * @return array An array of called listeners
     */
    public function getCalledListeners();

    /**
     * Gets the not called listeners.
     *
     * @return array An array of not called listeners
     */
    public function getNotCalledListeners();
}
PK��Z,��DD2Symfony/Component/EventDispatcher/GenericEvent.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\EventDispatcher;

/**
 * Event encapsulation class.
 *
 * Encapsulates events thus decoupling the observer from the subject they encapsulate.
 *
 * @author Drak <drak@zikula.org>
 */
class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate
{
    /**
     * Event subject.
     *
     * @var mixed usually object or callable
     */
    protected $subject;

    /**
     * Array of arguments.
     *
     * @var array
     */
    protected $arguments;

    /**
     * Encapsulate an event with $subject and $args.
     *
     * @param mixed $subject   The subject of the event, usually an object.
     * @param array $arguments Arguments to store in the event.
     */
    public function __construct($subject = null, array $arguments = array())
    {
        $this->subject = $subject;
        $this->arguments = $arguments;
    }

    /**
     * Getter for subject property.
     *
     * @return mixed $subject The observer subject.
     */
    public function getSubject()
    {
        return $this->subject;
    }

    /**
     * Get argument by key.
     *
     * @param string $key Key.
     *
     * @throws \InvalidArgumentException If key is not found.
     *
     * @return mixed Contents of array key.
     */
    public function getArgument($key)
    {
        if ($this->hasArgument($key)) {
            return $this->arguments[$key];
        }

        throw new \InvalidArgumentException(sprintf('%s not found in %s', $key, $this->getName()));
    }

    /**
     * Add argument to event.
     *
     * @param string $key   Argument name.
     * @param mixed  $value Value.
     *
     * @return GenericEvent
     */
    public function setArgument($key, $value)
    {
        $this->arguments[$key] = $value;

        return $this;
    }

    /**
     * Getter for all arguments.
     *
     * @return array
     */
    public function getArguments()
    {
        return $this->arguments;
    }

    /**
     * Set args property.
     *
     * @param array $args Arguments.
     *
     * @return GenericEvent
     */
    public function setArguments(array $args = array())
    {
        $this->arguments = $args;

        return $this;
    }

    /**
     * Has argument.
     *
     * @param string $key Key of arguments array.
     *
     * @return boolean
     */
    public function hasArgument($key)
    {
        return array_key_exists($key, $this->arguments);
    }

    /**
     * ArrayAccess for argument getter.
     *
     * @param string $key Array key.
     *
     * @throws \InvalidArgumentException If key does not exist in $this->args.
     *
     * @return mixed
     */
    public function offsetGet($key)
    {
        return $this->getArgument($key);
    }

    /**
     * ArrayAccess for argument setter.
     *
     * @param string $key   Array key to set.
     * @param mixed  $value Value.
     */
    public function offsetSet($key, $value)
    {
        $this->setArgument($key, $value);
    }

    /**
     * ArrayAccess for unset argument.
     *
     * @param string $key Array key.
     */
    public function offsetUnset($key)
    {
        if ($this->hasArgument($key)) {
            unset($this->arguments[$key]);
        }
    }

    /**
     * ArrayAccess has argument.
     *
     * @param string $key Array key.
     *
     * @return boolean
     */
    public function offsetExists($key)
    {
        return $this->hasArgument($key);
    }

    /**
     * IteratorAggregate for iterating over the object like an array
     *
     * @return \ArrayIterator
     */
    public function getIterator()
    {
        return new \ArrayIterator($this->arguments);
    }
}
PK��ZcG�11>Symfony/Component/EventDispatcher/EventSubscriberInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\EventDispatcher;

/**
 * An EventSubscriber knows himself what events he is interested in.
 * If an EventSubscriber is added to an EventDispatcherInterface, the manager invokes
 * {@link getSubscribedEvents} and registers the subscriber as a listener for all
 * returned events.
 *
 * @author  Guilherme Blanco <guilhermeblanco@hotmail.com>
 * @author  Jonathan Wage <jonwage@gmail.com>
 * @author  Roman Borschel <roman@code-factory.org>
 * @author  Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
interface EventSubscriberInterface
{
    /**
     * Returns an array of event names this subscriber wants to listen to.
     *
     * The array keys are event names and the value can be:
     *
     *  * The method name to call (priority defaults to 0)
     *  * An array composed of the method name to call and the priority
     *  * An array of arrays composed of the method names to call and respective
     *    priorities, or 0 if unset
     *
     * For instance:
     *
     *  * array('eventName' => 'methodName')
     *  * array('eventName' => array('methodName', $priority))
     *  * array('eventName' => array(array('methodName1', $priority), array('methodName2'))
     *
     * @return array The event names to listen to
     *
     * @api
     */
    public static function getSubscribedEvents();
}
PK��Zs���>Symfony/Component/EventDispatcher/ImmutableEventDispatcher.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\EventDispatcher;

/**
 * A read-only proxy for an event dispatcher.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ImmutableEventDispatcher implements EventDispatcherInterface
{
    /**
     * The proxied dispatcher.
     * @var EventDispatcherInterface
     */
    private $dispatcher;

    /**
     * Creates an unmodifiable proxy for an event dispatcher.
     *
     * @param EventDispatcherInterface $dispatcher The proxied event dispatcher.
     */
    public function __construct(EventDispatcherInterface $dispatcher)
    {
        $this->dispatcher = $dispatcher;
    }

    /**
     * {@inheritdoc}
     */
    public function dispatch($eventName, Event $event = null)
    {
        return $this->dispatcher->dispatch($eventName, $event);
    }

    /**
     * {@inheritdoc}
     */
    public function addListener($eventName, $listener, $priority = 0)
    {
        throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.');
    }

    /**
     * {@inheritdoc}
     */
    public function addSubscriber(EventSubscriberInterface $subscriber)
    {
        throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.');
    }

    /**
     * {@inheritdoc}
     */
    public function removeListener($eventName, $listener)
    {
        throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.');
    }

    /**
     * {@inheritdoc}
     */
    public function removeSubscriber(EventSubscriberInterface $subscriber)
    {
        throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.');
    }

    /**
     * {@inheritdoc}
     */
    public function getListeners($eventName = null)
    {
        return $this->dispatcher->getListeners($eventName);
    }

    /**
     * {@inheritdoc}
     */
    public function hasListeners($eventName = null)
    {
        return $this->dispatcher->hasListeners($eventName);
    }
}
PK��ZU����>Symfony/Component/EventDispatcher/EventDispatcherInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\EventDispatcher;

/**
 * The EventDispatcherInterface is the central point of Symfony's event listener system.
 * Listeners are registered on the manager and events are dispatched through the
 * manager.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
interface EventDispatcherInterface
{
    /**
     * Dispatches an event to all registered listeners.
     *
     * @param string $eventName The name of the event to dispatch. The name of
     *                          the event is the name of the method that is
     *                          invoked on listeners.
     * @param Event $event The event to pass to the event handlers/listeners.
     *                          If not supplied, an empty Event instance is created.
     *
     * @return Event
     *
     * @api
     */
    public function dispatch($eventName, Event $event = null);

    /**
     * Adds an event listener that listens on the specified events.
     *
     * @param string   $eventName The event to listen on
     * @param callable $listener  The listener
     * @param integer  $priority  The higher this value, the earlier an event
     *                            listener will be triggered in the chain (defaults to 0)
     *
     * @api
     */
    public function addListener($eventName, $listener, $priority = 0);

    /**
     * Adds an event subscriber.
     *
     * The subscriber is asked for all the events he is
     * interested in and added as a listener for these events.
     *
     * @param EventSubscriberInterface $subscriber The subscriber.
     *
     * @api
     */
    public function addSubscriber(EventSubscriberInterface $subscriber);

    /**
     * Removes an event listener from the specified events.
     *
     * @param string|array $eventName The event(s) to remove a listener from
     * @param callable     $listener  The listener to remove
     */
    public function removeListener($eventName, $listener);

    /**
     * Removes an event subscriber.
     *
     * @param EventSubscriberInterface $subscriber The subscriber
     */
    public function removeSubscriber(EventSubscriberInterface $subscriber);

    /**
     * Gets the listeners of a specific event or all listeners.
     *
     * @param string $eventName The name of the event
     *
     * @return array The event listeners for the specified event, or all event listeners by event name
     */
    public function getListeners($eventName = null);

    /**
     * Checks whether an event has any registered listeners.
     *
     * @param string $eventName The name of the event
     *
     * @return Boolean true if the specified event has any listeners, false otherwise
     */
    public function hasListeners($eventName = null);
}
PK��Z��NmCSymfony/Component/EventDispatcher/ContainerAwareEventDispatcher.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\EventDispatcher;

use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Lazily loads listeners and subscribers from the dependency injection
 * container
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Bernhard Schussek <bschussek@gmail.com>
 * @author Jordan Alliot <jordan.alliot@gmail.com>
 */
class ContainerAwareEventDispatcher extends EventDispatcher
{
    /**
     * The container from where services are loaded
     * @var ContainerInterface
     */
    private $container;

    /**
     * The service IDs of the event listeners and subscribers
     * @var array
     */
    private $listenerIds = array();

    /**
     * The services registered as listeners
     * @var array
     */
    private $listeners = array();

    /**
     * Constructor.
     *
     * @param ContainerInterface $container A ContainerInterface instance
     */
    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    /**
     * Adds a service as event listener
     *
     * @param string $eventName Event for which the listener is added
     * @param array  $callback  The service ID of the listener service & the method
     *                            name that has to be called
     * @param integer $priority The higher this value, the earlier an event listener
     *                            will be triggered in the chain.
     *                            Defaults to 0.
     *
     * @throws \InvalidArgumentException
     */
    public function addListenerService($eventName, $callback, $priority = 0)
    {
        if (!is_array($callback) || 2 !== count($callback)) {
            throw new \InvalidArgumentException('Expected an array("service", "method") argument');
        }

        $this->listenerIds[$eventName][] = array($callback[0], $callback[1], $priority);
    }

    public function removeListener($eventName, $listener)
    {
        $this->lazyLoad($eventName);

        if (isset($this->listeners[$eventName])) {
            foreach ($this->listeners[$eventName] as $key => $l) {
                foreach ($this->listenerIds[$eventName] as $i => $args) {
                    list($serviceId, $method, $priority) = $args;
                    if ($key === $serviceId.'.'.$method) {
                        if ($listener === array($l, $method)) {
                            unset($this->listeners[$eventName][$key]);
                            if (empty($this->listeners[$eventName])) {
                                unset($this->listeners[$eventName]);
                            }
                            unset($this->listenerIds[$eventName][$i]);
                            if (empty($this->listenerIds[$eventName])) {
                                unset($this->listenerIds[$eventName]);
                            }
                        }
                    }
                }
            }
        }

        parent::removeListener($eventName, $listener);
    }

    /**
     * @see EventDispatcherInterface::hasListeners
     */
    public function hasListeners($eventName = null)
    {
        if (null === $eventName) {
            return (Boolean) count($this->listenerIds) || (Boolean) count($this->listeners);
        }

        if (isset($this->listenerIds[$eventName])) {
            return true;
        }

        return parent::hasListeners($eventName);
    }

    /**
     * @see EventDispatcherInterface::getListeners
     */
    public function getListeners($eventName = null)
    {
        if (null === $eventName) {
            foreach (array_keys($this->listenerIds) as $serviceEventName) {
                $this->lazyLoad($serviceEventName);
            }
        } else {
            $this->lazyLoad($eventName);
        }

        return parent::getListeners($eventName);
    }

    /**
     * Adds a service as event subscriber
     *
     * @param string $serviceId The service ID of the subscriber service
     * @param string $class     The service's class name (which must implement EventSubscriberInterface)
     */
    public function addSubscriberService($serviceId, $class)
    {
        foreach ($class::getSubscribedEvents() as $eventName => $params) {
            if (is_string($params)) {
                $this->listenerIds[$eventName][] = array($serviceId, $params, 0);
            } elseif (is_string($params[0])) {
                $this->listenerIds[$eventName][] = array($serviceId, $params[0], isset($params[1]) ? $params[1] : 0);
            } else {
                foreach ($params as $listener) {
                    $this->listenerIds[$eventName][] = array($serviceId, $listener[0], isset($listener[1]) ? $listener[1] : 0);
                }
            }
        }
    }

    /**
     * {@inheritDoc}
     *
     * Lazily loads listeners for this event from the dependency injection
     * container.
     *
     * @throws \InvalidArgumentException if the service is not defined
     */
    public function dispatch($eventName, Event $event = null)
    {
        $this->lazyLoad($eventName);

        return parent::dispatch($eventName, $event);
    }

    public function getContainer()
    {
        return $this->container;
    }

    /**
     * Lazily loads listeners for this event from the dependency injection
     * container.
     *
     * @param string $eventName The name of the event to dispatch. The name of
     *                          the event is the name of the method that is
     *                          invoked on listeners.
     */
    protected function lazyLoad($eventName)
    {
        if (isset($this->listenerIds[$eventName])) {
            foreach ($this->listenerIds[$eventName] as $args) {
                list($serviceId, $method, $priority) = $args;
                $listener = $this->container->get($serviceId);

                $key = $serviceId.'.'.$method;
                if (!isset($this->listeners[$eventName][$key])) {
                    $this->addListener($eventName, array($listener, $method), $priority);
                } elseif ($listener !== $this->listeners[$eventName][$key]) {
                    parent::removeListener($eventName, array($this->listeners[$eventName][$key], $method));
                    $this->addListener($eventName, array($listener, $method), $priority);
                }

                $this->listeners[$eventName][$key] = $listener;
            }
        }
    }
}
PK��ZY�"��5Symfony/Component/EventDispatcher/EventDispatcher.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\EventDispatcher;

/**
 * The EventDispatcherInterface is the central point of Symfony's event listener system.
 *
 * Listeners are registered on the manager and events are dispatched through the
 * manager.
 *
 * @author  Guilherme Blanco <guilhermeblanco@hotmail.com>
 * @author  Jonathan Wage <jonwage@gmail.com>
 * @author  Roman Borschel <roman@code-factory.org>
 * @author  Bernhard Schussek <bschussek@gmail.com>
 * @author  Fabien Potencier <fabien@symfony.com>
 * @author  Jordi Boggiano <j.boggiano@seld.be>
 * @author  Jordan Alliot <jordan.alliot@gmail.com>
 *
 * @api
 */
class EventDispatcher implements EventDispatcherInterface
{
    private $listeners = array();
    private $sorted = array();

    /**
     * @see EventDispatcherInterface::dispatch
     *
     * @api
     */
    public function dispatch($eventName, Event $event = null)
    {
        if (null === $event) {
            $event = new Event();
        }

        $event->setDispatcher($this);
        $event->setName($eventName);

        if (!isset($this->listeners[$eventName])) {
            return $event;
        }

        $this->doDispatch($this->getListeners($eventName), $eventName, $event);

        return $event;
    }

    /**
     * @see EventDispatcherInterface::getListeners
     */
    public function getListeners($eventName = null)
    {
        if (null !== $eventName) {
            if (!isset($this->sorted[$eventName])) {
                $this->sortListeners($eventName);
            }

            return $this->sorted[$eventName];
        }

        foreach (array_keys($this->listeners) as $eventName) {
            if (!isset($this->sorted[$eventName])) {
                $this->sortListeners($eventName);
            }
        }

        return $this->sorted;
    }

    /**
     * @see EventDispatcherInterface::hasListeners
     */
    public function hasListeners($eventName = null)
    {
        return (Boolean) count($this->getListeners($eventName));
    }

    /**
     * @see EventDispatcherInterface::addListener
     *
     * @api
     */
    public function addListener($eventName, $listener, $priority = 0)
    {
        $this->listeners[$eventName][$priority][] = $listener;
        unset($this->sorted[$eventName]);
    }

    /**
     * @see EventDispatcherInterface::removeListener
     */
    public function removeListener($eventName, $listener)
    {
        if (!isset($this->listeners[$eventName])) {
            return;
        }

        foreach ($this->listeners[$eventName] as $priority => $listeners) {
            if (false !== ($key = array_search($listener, $listeners, true))) {
                unset($this->listeners[$eventName][$priority][$key], $this->sorted[$eventName]);
            }
        }
    }

    /**
     * @see EventDispatcherInterface::addSubscriber
     *
     * @api
     */
    public function addSubscriber(EventSubscriberInterface $subscriber)
    {
        foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
            if (is_string($params)) {
                $this->addListener($eventName, array($subscriber, $params));
            } elseif (is_string($params[0])) {
                $this->addListener($eventName, array($subscriber, $params[0]), isset($params[1]) ? $params[1] : 0);
            } else {
                foreach ($params as $listener) {
                    $this->addListener($eventName, array($subscriber, $listener[0]), isset($listener[1]) ? $listener[1] : 0);
                }
            }
        }
    }

    /**
     * @see EventDispatcherInterface::removeSubscriber
     */
    public function removeSubscriber(EventSubscriberInterface $subscriber)
    {
        foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
            if (is_array($params) && is_array($params[0])) {
                foreach ($params as $listener) {
                    $this->removeListener($eventName, array($subscriber, $listener[0]));
                }
            } else {
                $this->removeListener($eventName, array($subscriber, is_string($params) ? $params : $params[0]));
            }
        }
    }

    /**
     * Triggers the listeners of an event.
     *
     * This method can be overridden to add functionality that is executed
     * for each listener.
     *
     * @param callable[] $listeners The event listeners.
     * @param string     $eventName The name of the event to dispatch.
     * @param Event      $event     The event object to pass to the event handlers/listeners.
     */
    protected function doDispatch($listeners, $eventName, Event $event)
    {
        foreach ($listeners as $listener) {
            call_user_func($listener, $event, $eventName, $this);
            if ($event->isPropagationStopped()) {
                break;
            }
        }
    }

    /**
     * Sorts the internal list of listeners for the given event by priority.
     *
     * @param string $eventName The name of the event.
     */
    private function sortListeners($eventName)
    {
        $this->sorted[$eventName] = array();

        if (isset($this->listeners[$eventName])) {
            krsort($this->listeners[$eventName]);
            $this->sorted[$eventName] = call_user_func_array('array_merge', $this->listeners[$eventName]);
        }
    }
}
PK��Z x��
�
1Symfony/Component/Console/Command/ListCommand.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Command;

use Symfony\Component\Console\Helper\DescriptorHelper;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputDefinition;

/**
 * ListCommand displays the list of all available commands for the application.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ListCommand extends Command
{
    /**
     * {@inheritdoc}
     */
    protected function configure()
    {
        $this
            ->setName('list')
            ->setDefinition($this->createDefinition())
            ->setDescription('Lists commands')
            ->setHelp(<<<EOF
The <info>%command.name%</info> command lists all commands:

  <info>php %command.full_name%</info>

You can also display the commands for a specific namespace:

  <info>php %command.full_name% test</info>

You can also output the information in other formats by using the <comment>--format</comment> option:

  <info>php %command.full_name% --format=xml</info>

It's also possible to get raw list of commands (useful for embedding command runner):

  <info>php %command.full_name% --raw</info>
EOF
            )
        ;
    }

    /**
     * {@inheritdoc}
     */
    public function getNativeDefinition()
    {
        return $this->createDefinition();
    }

    /**
     * {@inheritdoc}
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        if ($input->getOption('xml')) {
            $input->setOption('format', 'xml');
        }

        $helper = new DescriptorHelper();
        $helper->describe($output, $this->getApplication(), array(
            'format'    => $input->getOption('format'),
            'raw_text'  => $input->getOption('raw'),
            'namespace' => $input->getArgument('namespace'),
        ));
    }

    /**
     * {@inheritdoc}
     */
    private function createDefinition()
    {
        return new InputDefinition(array(
            new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'),
            new InputOption('xml', null, InputOption::VALUE_NONE, 'To output list as XML'),
            new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'),
            new InputOption('format', null, InputOption::VALUE_REQUIRED, 'To output list in other formats', 'txt'),
        ));
    }
}
PK��Z�Ƙ�7@7@-Symfony/Component/Console/Command/Command.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Command;

use Symfony\Component\Console\Descriptor\TextDescriptor;
use Symfony\Component\Console\Descriptor\XmlDescriptor;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Helper\HelperSet;

/**
 * Base class for all commands.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class Command
{
    private $application;
    private $name;
    private $aliases = array();
    private $definition;
    private $help;
    private $description;
    private $ignoreValidationErrors = false;
    private $applicationDefinitionMerged = false;
    private $applicationDefinitionMergedWithArgs = false;
    private $code;
    private $synopsis;
    private $helperSet;

    /**
     * Constructor.
     *
     * @param string|null $name The name of the command; passing null means it must be set in configure()
     *
     * @throws \LogicException When the command name is empty
     *
     * @api
     */
    public function __construct($name = null)
    {
        $this->definition = new InputDefinition();

        if (null !== $name) {
            $this->setName($name);
        }

        $this->configure();

        if (!$this->name) {
            throw new \LogicException('The command name cannot be empty.');
        }
    }

    /**
     * Ignores validation errors.
     *
     * This is mainly useful for the help command.
     */
    public function ignoreValidationErrors()
    {
        $this->ignoreValidationErrors = true;
    }

    /**
     * Sets the application instance for this command.
     *
     * @param Application $application An Application instance
     *
     * @api
     */
    public function setApplication(Application $application = null)
    {
        $this->application = $application;
        if ($application) {
            $this->setHelperSet($application->getHelperSet());
        } else {
            $this->helperSet = null;
        }
    }

    /**
     * Sets the helper set.
     *
     * @param HelperSet $helperSet A HelperSet instance
     */
    public function setHelperSet(HelperSet $helperSet)
    {
        $this->helperSet = $helperSet;
    }

    /**
     * Gets the helper set.
     *
     * @return HelperSet A HelperSet instance
     */
    public function getHelperSet()
    {
        return $this->helperSet;
    }

    /**
     * Gets the application instance for this command.
     *
     * @return Application An Application instance
     *
     * @api
     */
    public function getApplication()
    {
        return $this->application;
    }

    /**
     * Checks whether the command is enabled or not in the current environment
     *
     * Override this to check for x or y and return false if the command can not
     * run properly under the current conditions.
     *
     * @return Boolean
     */
    public function isEnabled()
    {
        return true;
    }

    /**
     * Configures the current command.
     */
    protected function configure()
    {
    }

    /**
     * Executes the current command.
     *
     * This method is not abstract because you can use this class
     * as a concrete class. In this case, instead of defining the
     * execute() method, you set the code to execute by passing
     * a Closure to the setCode() method.
     *
     * @param InputInterface  $input  An InputInterface instance
     * @param OutputInterface $output An OutputInterface instance
     *
     * @return null|integer null or 0 if everything went fine, or an error code
     *
     * @throws \LogicException When this abstract method is not implemented
     * @see    setCode()
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        throw new \LogicException('You must override the execute() method in the concrete command class.');
    }

    /**
     * Interacts with the user.
     *
     * @param InputInterface  $input  An InputInterface instance
     * @param OutputInterface $output An OutputInterface instance
     */
    protected function interact(InputInterface $input, OutputInterface $output)
    {
    }

    /**
     * Initializes the command just after the input has been validated.
     *
     * This is mainly useful when a lot of commands extends one main command
     * where some things need to be initialized based on the input arguments and options.
     *
     * @param InputInterface  $input  An InputInterface instance
     * @param OutputInterface $output An OutputInterface instance
     */
    protected function initialize(InputInterface $input, OutputInterface $output)
    {
    }

    /**
     * Runs the command.
     *
     * The code to execute is either defined directly with the
     * setCode() method or by overriding the execute() method
     * in a sub-class.
     *
     * @param InputInterface  $input  An InputInterface instance
     * @param OutputInterface $output An OutputInterface instance
     *
     * @return integer The command exit code
     *
     * @throws \Exception
     *
     * @see setCode()
     * @see execute()
     *
     * @api
     */
    public function run(InputInterface $input, OutputInterface $output)
    {
        // force the creation of the synopsis before the merge with the app definition
        $this->getSynopsis();

        // add the application arguments and options
        $this->mergeApplicationDefinition();

        // bind the input against the command specific arguments/options
        try {
            $input->bind($this->definition);
        } catch (\Exception $e) {
            if (!$this->ignoreValidationErrors) {
                throw $e;
            }
        }

        $this->initialize($input, $output);

        if ($input->isInteractive()) {
            $this->interact($input, $output);
        }

        $input->validate();

        if ($this->code) {
            $statusCode = call_user_func($this->code, $input, $output);
        } else {
            $statusCode = $this->execute($input, $output);
        }

        return is_numeric($statusCode) ? (int) $statusCode : 0;
    }

    /**
     * Sets the code to execute when running this command.
     *
     * If this method is used, it overrides the code defined
     * in the execute() method.
     *
     * @param callable $code A callable(InputInterface $input, OutputInterface $output)
     *
     * @return Command The current instance
     *
     * @throws \InvalidArgumentException
     *
     * @see execute()
     *
     * @api
     */
    public function setCode($code)
    {
        if (!is_callable($code)) {
            throw new \InvalidArgumentException('Invalid callable provided to Command::setCode.');
        }

        $this->code = $code;

        return $this;
    }

    /**
     * Merges the application definition with the command definition.
     *
     * This method is not part of public API and should not be used directly.
     *
     * @param Boolean $mergeArgs Whether to merge or not the Application definition arguments to Command definition arguments
     */
    public function mergeApplicationDefinition($mergeArgs = true)
    {
        if (null === $this->application || (true === $this->applicationDefinitionMerged && ($this->applicationDefinitionMergedWithArgs || !$mergeArgs))) {
            return;
        }

        if ($mergeArgs) {
            $currentArguments = $this->definition->getArguments();
            $this->definition->setArguments($this->application->getDefinition()->getArguments());
            $this->definition->addArguments($currentArguments);
        }

        $this->definition->addOptions($this->application->getDefinition()->getOptions());

        $this->applicationDefinitionMerged = true;
        if ($mergeArgs) {
            $this->applicationDefinitionMergedWithArgs = true;
        }
    }

    /**
     * Sets an array of argument and option instances.
     *
     * @param array|InputDefinition $definition An array of argument and option instances or a definition instance
     *
     * @return Command The current instance
     *
     * @api
     */
    public function setDefinition($definition)
    {
        if ($definition instanceof InputDefinition) {
            $this->definition = $definition;
        } else {
            $this->definition->setDefinition($definition);
        }

        $this->applicationDefinitionMerged = false;

        return $this;
    }

    /**
     * Gets the InputDefinition attached to this Command.
     *
     * @return InputDefinition An InputDefinition instance
     *
     * @api
     */
    public function getDefinition()
    {
        return $this->definition;
    }

    /**
     * Gets the InputDefinition to be used to create XML and Text representations of this Command.
     *
     * Can be overridden to provide the original command representation when it would otherwise
     * be changed by merging with the application InputDefinition.
     *
     * This method is not part of public API and should not be used directly.
     *
     * @return InputDefinition An InputDefinition instance
     */
    public function getNativeDefinition()
    {
        return $this->getDefinition();
    }

    /**
     * Adds an argument.
     *
     * @param string  $name        The argument name
     * @param integer $mode        The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL
     * @param string  $description A description text
     * @param mixed   $default     The default value (for InputArgument::OPTIONAL mode only)
     *
     * @return Command The current instance
     *
     * @api
     */
    public function addArgument($name, $mode = null, $description = '', $default = null)
    {
        $this->definition->addArgument(new InputArgument($name, $mode, $description, $default));

        return $this;
    }

    /**
     * Adds an option.
     *
     * @param string  $name        The option name
     * @param string  $shortcut    The shortcut (can be null)
     * @param integer $mode        The option mode: One of the InputOption::VALUE_* constants
     * @param string  $description A description text
     * @param mixed   $default     The default value (must be null for InputOption::VALUE_REQUIRED or InputOption::VALUE_NONE)
     *
     * @return Command The current instance
     *
     * @api
     */
    public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null)
    {
        $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default));

        return $this;
    }

    /**
     * Sets the name of the command.
     *
     * This method can set both the namespace and the name if
     * you separate them by a colon (:)
     *
     *     $command->setName('foo:bar');
     *
     * @param string $name The command name
     *
     * @return Command The current instance
     *
     * @throws \InvalidArgumentException When the name is invalid
     *
     * @api
     */
    public function setName($name)
    {
        $this->validateName($name);

        $this->name = $name;

        return $this;
    }

    /**
     * Returns the command name.
     *
     * @return string The command name
     *
     * @api
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Sets the description for the command.
     *
     * @param string $description The description for the command
     *
     * @return Command The current instance
     *
     * @api
     */
    public function setDescription($description)
    {
        $this->description = $description;

        return $this;
    }

    /**
     * Returns the description for the command.
     *
     * @return string The description for the command
     *
     * @api
     */
    public function getDescription()
    {
        return $this->description;
    }

    /**
     * Sets the help for the command.
     *
     * @param string $help The help for the command
     *
     * @return Command The current instance
     *
     * @api
     */
    public function setHelp($help)
    {
        $this->help = $help;

        return $this;
    }

    /**
     * Returns the help for the command.
     *
     * @return string The help for the command
     *
     * @api
     */
    public function getHelp()
    {
        return $this->help;
    }

    /**
     * Returns the processed help for the command replacing the %command.name% and
     * %command.full_name% patterns with the real values dynamically.
     *
     * @return string  The processed help for the command
     */
    public function getProcessedHelp()
    {
        $name = $this->name;

        $placeholders = array(
            '%command.name%',
            '%command.full_name%'
        );
        $replacements = array(
            $name,
            $_SERVER['PHP_SELF'].' '.$name
        );

        return str_replace($placeholders, $replacements, $this->getHelp());
    }

    /**
     * Sets the aliases for the command.
     *
     * @param array $aliases An array of aliases for the command
     *
     * @return Command The current instance
     *
     * @throws \InvalidArgumentException When an alias is invalid
     *
     * @api
     */
    public function setAliases($aliases)
    {
        foreach ($aliases as $alias) {
            $this->validateName($alias);
        }

        $this->aliases = $aliases;

        return $this;
    }

    /**
     * Returns the aliases for the command.
     *
     * @return array An array of aliases for the command
     *
     * @api
     */
    public function getAliases()
    {
        return $this->aliases;
    }

    /**
     * Returns the synopsis for the command.
     *
     * @return string The synopsis
     */
    public function getSynopsis()
    {
        if (null === $this->synopsis) {
            $this->synopsis = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis()));
        }

        return $this->synopsis;
    }

    /**
     * Gets a helper instance by name.
     *
     * @param string $name The helper name
     *
     * @return mixed The helper value
     *
     * @throws \InvalidArgumentException if the helper is not defined
     *
     * @api
     */
    public function getHelper($name)
    {
        return $this->helperSet->get($name);
    }

    /**
     * Returns a text representation of the command.
     *
     * @return string A string representing the command
     *
     * @deprecated Deprecated since version 2.3, to be removed in 3.0.
     */
    public function asText()
    {
        $descriptor = new TextDescriptor();
        $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
        $descriptor->describe($output, $this, array('raw_output' => true));

        return $output->fetch();
    }

    /**
     * Returns an XML representation of the command.
     *
     * @param Boolean $asDom Whether to return a DOM or an XML string
     *
     * @return string|\DOMDocument An XML string representing the command
     *
     * @deprecated Deprecated since version 2.3, to be removed in 3.0.
     */
    public function asXml($asDom = false)
    {
        $descriptor = new XmlDescriptor();

        if ($asDom) {
            return $descriptor->getCommandDocument($this);
        }

        $output = new BufferedOutput();
        $descriptor->describe($output, $this);

        return $output->fetch();
    }

    /**
     * Validates a command name.
     *
     * It must be non-empty and parts can optionally be separated by ":".
     *
     * @param string $name
     *
     * @throws \InvalidArgumentException When the name is invalid
     */
    private function validateName($name)
    {
        if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) {
            throw new \InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name));
        }
    }
}
PK��Z�m_
_
1Symfony/Component/Console/Command/HelpCommand.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Command;

use Symfony\Component\Console\Helper\DescriptorHelper;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * HelpCommand displays the help for a given command.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class HelpCommand extends Command
{
    private $command;

    /**
     * {@inheritdoc}
     */
    protected function configure()
    {
        $this->ignoreValidationErrors();

        $this
            ->setName('help')
            ->setDefinition(array(
                new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'),
                new InputOption('xml', null, InputOption::VALUE_NONE, 'To output help as XML'),
                new InputOption('format', null, InputOption::VALUE_REQUIRED, 'To output help in other formats', 'txt'),
                new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'),
            ))
            ->setDescription('Displays help for a command')
            ->setHelp(<<<EOF
The <info>%command.name%</info> command displays help for a given command:

  <info>php %command.full_name% list</info>

You can also output the help in other formats by using the <comment>--format</comment> option:

  <info>php %command.full_name% --format=xml list</info>

To display the list of available commands, please use the <info>list</info> command.
EOF
            )
        ;
    }

    /**
     * Sets the command
     *
     * @param Command $command The command to set
     */
    public function setCommand(Command $command)
    {
        $this->command = $command;
    }

    /**
     * {@inheritdoc}
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        if (null === $this->command) {
            $this->command = $this->getApplication()->find($input->getArgument('command_name'));
        }

        if ($input->getOption('xml')) {
            $input->setOption('format', 'xml');
        }

        $helper = new DescriptorHelper();
        $helper->describe($output, $this->command, array(
            'format' => $input->getOption('format'),
            'raw'    => $input->getOption('raw'),
        ));

        $this->command = null;
    }
}
PK��Z\0�E��+Symfony/Component/Console/ConsoleEvents.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console;

/**
 * Contains all events dispatched by an Application.
 *
 * @author Francesco Levorato <git@flevour.net>
 */
final class ConsoleEvents
{
    /**
     * The COMMAND event allows you to attach listeners before any command is
     * executed by the console. It also allows you to modify the command, input and output
     * before they are handled to the command.
     *
     * The event listener method receives a Symfony\Component\Console\Event\ConsoleCommandEvent
     * instance.
     *
     * @var string
     */
    const COMMAND = 'console.command';

    /**
     * The TERMINATE event allows you to attach listeners after a command is
     * executed by the console.
     *
     * The event listener method receives a Symfony\Component\Console\Event\ConsoleTerminateEvent
     * instance.
     *
     * @var string
     */
    const TERMINATE = 'console.terminate';

    /**
     * The EXCEPTION event occurs when an uncaught exception appears.
     *
     * This event allows you to deal with the exception or
     * to modify the thrown exception. The event listener method receives
     * a Symfony\Component\Console\Event\ConsoleExceptionEvent
     * instance.
     *
     * @var string
     */
    const EXCEPTION = 'console.exception';
}
PK��Z2V��#Symfony/Component/Console/Shell.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console;

use Symfony\Component\Console\Input\StringInput;
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\Process\ProcessBuilder;
use Symfony\Component\Process\PhpExecutableFinder;

/**
 * A Shell wraps an Application to add shell capabilities to it.
 *
 * Support for history and completion only works with a PHP compiled
 * with readline support (either --with-readline or --with-libedit)
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Martin Hasoň <martin.hason@gmail.com>
 */
class Shell
{
    private $application;
    private $history;
    private $output;
    private $hasReadline;
    private $processIsolation = false;

    /**
     * Constructor.
     *
     * If there is no readline support for the current PHP executable
     * a \RuntimeException exception is thrown.
     *
     * @param Application $application An application instance
     */
    public function __construct(Application $application)
    {
        $this->hasReadline = function_exists('readline');
        $this->application = $application;
        $this->history = getenv('HOME').'/.history_'.$application->getName();
        $this->output = new ConsoleOutput();
    }

    /**
     * Runs the shell.
     */
    public function run()
    {
        $this->application->setAutoExit(false);
        $this->application->setCatchExceptions(true);

        if ($this->hasReadline) {
            readline_read_history($this->history);
            readline_completion_function(array($this, 'autocompleter'));
        }

        $this->output->writeln($this->getHeader());
        $php = null;
        if ($this->processIsolation) {
            $finder = new PhpExecutableFinder();
            $php = $finder->find();
            $this->output->writeln(<<<EOF
<info>Running with process isolation, you should consider this:</info>
  * each command is executed as separate process,
  * commands don't support interactivity, all params must be passed explicitly,
  * commands output is not colorized.

EOF
            );
        }

        while (true) {
            $command = $this->readline();

            if (false === $command) {
                $this->output->writeln("\n");

                break;
            }

            if ($this->hasReadline) {
                readline_add_history($command);
                readline_write_history($this->history);
            }

            if ($this->processIsolation) {
                $pb = new ProcessBuilder();

                $process = $pb
                    ->add($php)
                    ->add($_SERVER['argv'][0])
                    ->add($command)
                    ->inheritEnvironmentVariables(true)
                    ->getProcess()
                ;

                $output = $this->output;
                $process->run(function ($type, $data) use ($output) {
                    $output->writeln($data);
                });

                $ret = $process->getExitCode();
            } else {
                $ret = $this->application->run(new StringInput($command), $this->output);
            }

            if (0 !== $ret) {
                $this->output->writeln(sprintf('<error>The command terminated with an error status (%s)</error>', $ret));
            }
        }
    }

    /**
     * Returns the shell header.
     *
     * @return string The header string
     */
    protected function getHeader()
    {
        return <<<EOF

Welcome to the <info>{$this->application->getName()}</info> shell (<comment>{$this->application->getVersion()}</comment>).

At the prompt, type <comment>help</comment> for some help,
or <comment>list</comment> to get a list of available commands.

To exit the shell, type <comment>^D</comment>.

EOF;
    }

    /**
     * Renders a prompt.
     *
     * @return string The prompt
     */
    protected function getPrompt()
    {
        // using the formatter here is required when using readline
        return $this->output->getFormatter()->format($this->application->getName().' > ');
    }

    protected function getOutput()
    {
        return $this->output;
    }

    protected function getApplication()
    {
        return $this->application;
    }

    /**
     * Tries to return autocompletion for the current entered text.
     *
     * @param string $text The last segment of the entered text
     *
     * @return Boolean|array A list of guessed strings or true
     */
    private function autocompleter($text)
    {
        $info = readline_info();
        $text = substr($info['line_buffer'], 0, $info['end']);

        if ($info['point'] !== $info['end']) {
            return true;
        }

        // task name?
        if (false === strpos($text, ' ') || !$text) {
            return array_keys($this->application->all());
        }

        // options and arguments?
        try {
            $command = $this->application->find(substr($text, 0, strpos($text, ' ')));
        } catch (\Exception $e) {
            return true;
        }

        $list = array('--help');
        foreach ($command->getDefinition()->getOptions() as $option) {
            $list[] = '--'.$option->getName();
        }

        return $list;
    }

    /**
     * Reads a single line from standard input.
     *
     * @return string The single line from standard input
     */
    private function readline()
    {
        if ($this->hasReadline) {
            $line = readline($this->getPrompt());
        } else {
            $this->output->write($this->getPrompt());
            $line = fgets(STDIN, 1024);
            $line = (!$line && strlen($line) == 0) ? false : rtrim($line);
        }

        return $line;
    }

    public function getProcessIsolation()
    {
        return $this->processIsolation;
    }

    public function setProcessIsolation($processIsolation)
    {
        $this->processIsolation = (Boolean) $processIsolation;

        if ($this->processIsolation && !class_exists('Symfony\\Component\\Process\\Process')) {
            throw new \RuntimeException('Unable to isolate processes as the Symfony Process Component is not installed.');
        }
    }
}
PK��Z�.�QQ(Symfony/Component/Console/autoloader.phpnu�[���<?php

spl_autoload_register(function ($class) {
    if ('\\' == $class[0]) {
        $class = substr($class, 1);
    }

    if (
        0 === strpos($class, 'Symfony\\Component\\Console\\')
        &&
        file_exists($file = __DIR__.'/../../../'.str_replace('\\', '/', $class).'.php')
    ) {
        require_once $file;
    }
});
PK��Z�hr�f
f
6Symfony/Component/Console/Tester/ApplicationTester.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tester;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Output\StreamOutput;

/**
 * Eases the testing of console applications.
 *
 * When testing an application, don't forget to disable the auto exit flag:
 *
 *     $application = new Application();
 *     $application->setAutoExit(false);
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ApplicationTester
{
    private $application;
    private $input;
    private $output;
    private $statusCode;

    /**
     * Constructor.
     *
     * @param Application $application An Application instance to test.
     */
    public function __construct(Application $application)
    {
        $this->application = $application;
    }

    /**
     * Executes the application.
     *
     * Available options:
     *
     *  * interactive: Sets the input interactive flag
     *  * decorated:   Sets the output decorated flag
     *  * verbosity:   Sets the output verbosity flag
     *
     * @param array $input   An array of arguments and options
     * @param array $options An array of options
     *
     * @return integer The command exit code
     */
    public function run(array $input, $options = array())
    {
        $this->input = new ArrayInput($input);
        if (isset($options['interactive'])) {
            $this->input->setInteractive($options['interactive']);
        }

        $this->output = new StreamOutput(fopen('php://memory', 'w', false));
        if (isset($options['decorated'])) {
            $this->output->setDecorated($options['decorated']);
        }
        if (isset($options['verbosity'])) {
            $this->output->setVerbosity($options['verbosity']);
        }

        return $this->statusCode = $this->application->run($this->input, $this->output);
    }

    /**
     * Gets the display returned by the last execution of the application.
     *
     * @param Boolean $normalize Whether to normalize end of lines to \n or not
     *
     * @return string The display
     */
    public function getDisplay($normalize = false)
    {
        rewind($this->output->getStream());

        $display = stream_get_contents($this->output->getStream());

        if ($normalize) {
            $display = str_replace(PHP_EOL, "\n", $display);
        }

        return $display;
    }

    /**
     * Gets the input instance used by the last execution of the application.
     *
     * @return InputInterface The current input instance
     */
    public function getInput()
    {
        return $this->input;
    }

    /**
     * Gets the output instance used by the last execution of the application.
     *
     * @return OutputInterface The current output instance
     */
    public function getOutput()
    {
        return $this->output;
    }

    /**
     * Gets the status code returned by the last execution of the application.
     *
     * @return integer The status code
     */
    public function getStatusCode()
    {
        return $this->statusCode;
    }
}
PK��Z~H(R2Symfony/Component/Console/Tester/CommandTester.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tester;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\StreamOutput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * Eases the testing of console commands.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class CommandTester
{
    private $command;
    private $input;
    private $output;
    private $statusCode;

    /**
     * Constructor.
     *
     * @param Command $command A Command instance to test.
     */
    public function __construct(Command $command)
    {
        $this->command = $command;
    }

    /**
     * Executes the command.
     *
     * Available options:
     *
     *  * interactive: Sets the input interactive flag
     *  * decorated:   Sets the output decorated flag
     *  * verbosity:   Sets the output verbosity flag
     *
     * @param array $input   An array of arguments and options
     * @param array $options An array of options
     *
     * @return integer The command exit code
     */
    public function execute(array $input, array $options = array())
    {
        // set the command name automatically if the application requires
        // this argument and no command name was passed
        if (!isset($input['command'])
            && (null !== $application = $this->command->getApplication())
            && $application->getDefinition()->hasArgument('command')
        ) {
            $input['command'] = $this->command->getName();
        }

        $this->input = new ArrayInput($input);
        if (isset($options['interactive'])) {
            $this->input->setInteractive($options['interactive']);
        }

        $this->output = new StreamOutput(fopen('php://memory', 'w', false));
        if (isset($options['decorated'])) {
            $this->output->setDecorated($options['decorated']);
        }
        if (isset($options['verbosity'])) {
            $this->output->setVerbosity($options['verbosity']);
        }

        return $this->statusCode = $this->command->run($this->input, $this->output);
    }

    /**
     * Gets the display returned by the last execution of the command.
     *
     * @param Boolean $normalize Whether to normalize end of lines to \n or not
     *
     * @return string The display
     */
    public function getDisplay($normalize = false)
    {
        rewind($this->output->getStream());

        $display = stream_get_contents($this->output->getStream());

        if ($normalize) {
            $display = str_replace(PHP_EOL, "\n", $display);
        }

        return $display;
    }

    /**
     * Gets the input instance used by the last execution of the command.
     *
     * @return InputInterface The current input instance
     */
    public function getInput()
    {
        return $this->input;
    }

    /**
     * Gets the output instance used by the last execution of the command.
     *
     * @return OutputInterface The current output instance
     */
    public function getOutput()
    {
        return $this->output;
    }

    /**
     * Gets the status code returned by the last execution of the application.
     *
     * @return integer The status code
     */
    public function getStatusCode()
    {
        return $this->statusCode;
    }
}
PK��Z�Q�)�)-Symfony/Component/Console/Input/ArgvInput.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Input;

/**
 * ArgvInput represents an input coming from the CLI arguments.
 *
 * Usage:
 *
 *     $input = new ArgvInput();
 *
 * By default, the `$_SERVER['argv']` array is used for the input values.
 *
 * This can be overridden by explicitly passing the input values in the constructor:
 *
 *     $input = new ArgvInput($_SERVER['argv']);
 *
 * If you pass it yourself, don't forget that the first element of the array
 * is the name of the running application.
 *
 * When passing an argument to the constructor, be sure that it respects
 * the same rules as the argv one. It's almost always better to use the
 * `StringInput` when you want to provide your own input.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @see    http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html
 * @see    http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html#tag_12_02
 *
 * @api
 */
class ArgvInput extends Input
{
    private $tokens;
    private $parsed;

    /**
     * Constructor.
     *
     * @param array           $argv       An array of parameters from the CLI (in the argv format)
     * @param InputDefinition $definition A InputDefinition instance
     *
     * @api
     */
    public function __construct(array $argv = null, InputDefinition $definition = null)
    {
        if (null === $argv) {
            $argv = $_SERVER['argv'];
        }

        // strip the application name
        array_shift($argv);

        $this->tokens = $argv;

        parent::__construct($definition);
    }

    protected function setTokens(array $tokens)
    {
        $this->tokens = $tokens;
    }

    /**
     * Processes command line arguments.
     */
    protected function parse()
    {
        $parseOptions = true;
        $this->parsed = $this->tokens;
        while (null !== $token = array_shift($this->parsed)) {
            if ($parseOptions && '' == $token) {
                $this->parseArgument($token);
            } elseif ($parseOptions && '--' == $token) {
                $parseOptions = false;
            } elseif ($parseOptions && 0 === strpos($token, '--')) {
                $this->parseLongOption($token);
            } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) {
                $this->parseShortOption($token);
            } else {
                $this->parseArgument($token);
            }
        }
    }

    /**
     * Parses a short option.
     *
     * @param string $token The current token.
     */
    private function parseShortOption($token)
    {
        $name = substr($token, 1);

        if (strlen($name) > 1) {
            if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) {
                // an option with a value (with no space)
                $this->addShortOption($name[0], substr($name, 1));
            } else {
                $this->parseShortOptionSet($name);
            }
        } else {
            $this->addShortOption($name, null);
        }
    }

    /**
     * Parses a short option set.
     *
     * @param string $name The current token
     *
     * @throws \RuntimeException When option given doesn't exist
     */
    private function parseShortOptionSet($name)
    {
        $len = strlen($name);
        for ($i = 0; $i < $len; $i++) {
            if (!$this->definition->hasShortcut($name[$i])) {
                throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $name[$i]));
            }

            $option = $this->definition->getOptionForShortcut($name[$i]);
            if ($option->acceptValue()) {
                $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1));

                break;
            } else {
                $this->addLongOption($option->getName(), null);
            }
        }
    }

    /**
     * Parses a long option.
     *
     * @param string $token The current token
     */
    private function parseLongOption($token)
    {
        $name = substr($token, 2);

        if (false !== $pos = strpos($name, '=')) {
            $this->addLongOption(substr($name, 0, $pos), substr($name, $pos + 1));
        } else {
            $this->addLongOption($name, null);
        }
    }

    /**
     * Parses an argument.
     *
     * @param string $token The current token
     *
     * @throws \RuntimeException When too many arguments are given
     */
    private function parseArgument($token)
    {
        $c = count($this->arguments);

        // if input is expecting another argument, add it
        if ($this->definition->hasArgument($c)) {
            $arg = $this->definition->getArgument($c);
            $this->arguments[$arg->getName()] = $arg->isArray()? array($token) : $token;

        // if last argument isArray(), append token to last argument
        } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) {
            $arg = $this->definition->getArgument($c - 1);
            $this->arguments[$arg->getName()][] = $token;

        // unexpected argument
        } else {
            throw new \RuntimeException('Too many arguments.');
        }
    }

    /**
     * Adds a short option value.
     *
     * @param string $shortcut The short option key
     * @param mixed  $value    The value for the option
     *
     * @throws \RuntimeException When option given doesn't exist
     */
    private function addShortOption($shortcut, $value)
    {
        if (!$this->definition->hasShortcut($shortcut)) {
            throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut));
        }

        $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
    }

    /**
     * Adds a long option value.
     *
     * @param string $name  The long option key
     * @param mixed  $value The value for the option
     *
     * @throws \RuntimeException When option given doesn't exist
     */
    private function addLongOption($name, $value)
    {
        if (!$this->definition->hasOption($name)) {
            throw new \RuntimeException(sprintf('The "--%s" option does not exist.', $name));
        }

        $option = $this->definition->getOption($name);

        // Convert false values (from a previous call to substr()) to null
        if (false === $value) {
            $value = null;
        }

        if (null !== $value && !$option->acceptValue()) {
            throw new \RuntimeException(sprintf('The "--%s" option does not accept a value.', $name, $value));
        }

        if (null === $value && $option->acceptValue() && count($this->parsed)) {
            // if option accepts an optional or mandatory argument
            // let's see if there is one provided
            $next = array_shift($this->parsed);
            if (isset($next[0]) && '-' !== $next[0]) {
                $value = $next;
            } elseif (empty($next)) {
                $value = '';
            } else {
                array_unshift($this->parsed, $next);
            }
        }

        if (null === $value) {
            if ($option->isValueRequired()) {
                throw new \RuntimeException(sprintf('The "--%s" option requires a value.', $name));
            }

            if (!$option->isArray()) {
                $value = $option->isValueOptional() ? $option->getDefault() : true;
            }
        }

        if ($option->isArray()) {
            $this->options[$name][] = $value;
        } else {
            $this->options[$name] = $value;
        }
    }

    /**
     * Returns the first argument from the raw parameters (not parsed).
     *
     * @return string The value of the first argument or null otherwise
     */
    public function getFirstArgument()
    {
        foreach ($this->tokens as $token) {
            if ($token && '-' === $token[0]) {
                continue;
            }

            return $token;
        }
    }

    /**
     * Returns true if the raw parameters (not parsed) contain a value.
     *
     * This method is to be used to introspect the input parameters
     * before they have been validated. It must be used carefully.
     *
     * @param string|array $values The value(s) to look for in the raw parameters (can be an array)
     *
     * @return Boolean true if the value is contained in the raw parameters
     */
    public function hasParameterOption($values)
    {
        $values = (array) $values;

        foreach ($this->tokens as $token) {
            foreach ($values as $value) {
                if ($token === $value || 0 === strpos($token, $value.'=')) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * Returns the value of a raw option (not parsed).
     *
     * This method is to be used to introspect the input parameters
     * before they have been validated. It must be used carefully.
     *
     * @param string|array $values  The value(s) to look for in the raw parameters (can be an array)
     * @param mixed        $default The default value to return if no result is found
     *
     * @return mixed The option value
     */
    public function getParameterOption($values, $default = false)
    {
        $values = (array) $values;

        $tokens = $this->tokens;
        while ($token = array_shift($tokens)) {
            foreach ($values as $value) {
                if ($token === $value || 0 === strpos($token, $value.'=')) {
                    if (false !== $pos = strpos($token, '=')) {
                        return substr($token, $pos + 1);
                    }

                    return array_shift($tokens);
                }
            }
        }

        return $default;
    }

    /**
     * Returns a stringified representation of the args passed to the command
     *
     * @return string
     */
    public function __toString()
    {
        $self = $this;
        $tokens = array_map(function ($token) use ($self) {
            if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) {
                return $match[1] . $self->escapeToken($match[2]);
            }

            if ($token && $token[0] !== '-') {
                return $self->escapeToken($token);
            }

            return $token;
        }, $this->tokens);

        return implode(' ', $tokens);
    }
}
PK��Z��'��1Symfony/Component/Console/Input/InputArgument.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Input;

/**
 * Represents a command line argument.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class InputArgument
{
    const REQUIRED = 1;
    const OPTIONAL = 2;
    const IS_ARRAY = 4;

    private $name;
    private $mode;
    private $default;
    private $description;

    /**
     * Constructor.
     *
     * @param string  $name        The argument name
     * @param integer $mode        The argument mode: self::REQUIRED or self::OPTIONAL
     * @param string  $description A description text
     * @param mixed   $default     The default value (for self::OPTIONAL mode only)
     *
     * @throws \InvalidArgumentException When argument mode is not valid
     *
     * @api
     */
    public function __construct($name, $mode = null, $description = '', $default = null)
    {
        if (null === $mode) {
            $mode = self::OPTIONAL;
        } elseif (!is_int($mode) || $mode > 7 || $mode < 1) {
            throw new \InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode));
        }

        $this->name        = $name;
        $this->mode        = $mode;
        $this->description = $description;

        $this->setDefault($default);
    }

    /**
     * Returns the argument name.
     *
     * @return string The argument name
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Returns true if the argument is required.
     *
     * @return Boolean true if parameter mode is self::REQUIRED, false otherwise
     */
    public function isRequired()
    {
        return self::REQUIRED === (self::REQUIRED & $this->mode);
    }

    /**
     * Returns true if the argument can take multiple values.
     *
     * @return Boolean true if mode is self::IS_ARRAY, false otherwise
     */
    public function isArray()
    {
        return self::IS_ARRAY === (self::IS_ARRAY & $this->mode);
    }

    /**
     * Sets the default value.
     *
     * @param mixed $default The default value
     *
     * @throws \LogicException When incorrect default value is given
     */
    public function setDefault($default = null)
    {
        if (self::REQUIRED === $this->mode && null !== $default) {
            throw new \LogicException('Cannot set a default value except for InputArgument::OPTIONAL mode.');
        }

        if ($this->isArray()) {
            if (null === $default) {
                $default = array();
            } elseif (!is_array($default)) {
                throw new \LogicException('A default value for an array argument must be an array.');
            }
        }

        $this->default = $default;
    }

    /**
     * Returns the default value.
     *
     * @return mixed The default value
     */
    public function getDefault()
    {
        return $this->default;
    }

    /**
     * Returns the description text.
     *
     * @return string The description text
     */
    public function getDescription()
    {
        return $this->description;
    }
}
PK��Z�AM662Symfony/Component/Console/Input/InputInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Input;

/**
 * InputInterface is the interface implemented by all input classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface InputInterface
{
    /**
     * Returns the first argument from the raw parameters (not parsed).
     *
     * @return string The value of the first argument or null otherwise
     */
    public function getFirstArgument();

    /**
     * Returns true if the raw parameters (not parsed) contain a value.
     *
     * This method is to be used to introspect the input parameters
     * before they have been validated. It must be used carefully.
     *
     * @param string|array $values The values to look for in the raw parameters (can be an array)
     *
     * @return Boolean true if the value is contained in the raw parameters
     */
    public function hasParameterOption($values);

    /**
     * Returns the value of a raw option (not parsed).
     *
     * This method is to be used to introspect the input parameters
     * before they have been validated. It must be used carefully.
     *
     * @param string|array $values  The value(s) to look for in the raw parameters (can be an array)
     * @param mixed        $default The default value to return if no result is found
     *
     * @return mixed The option value
     */
    public function getParameterOption($values, $default = false);

    /**
     * Binds the current Input instance with the given arguments and options.
     *
     * @param InputDefinition $definition A InputDefinition instance
     */
    public function bind(InputDefinition $definition);

    /**
     * Validates if arguments given are correct.
     *
     * Throws an exception when not enough arguments are given.
     *
     * @throws \RuntimeException
     */
    public function validate();

    /**
     * Returns all the given arguments merged with the default values.
     *
     * @return array
     */
    public function getArguments();

    /**
     * Gets argument by name.
     *
     * @param string $name The name of the argument
     *
     * @return mixed
     */
    public function getArgument($name);

    /**
     * Sets an argument value by name.
     *
     * @param string $name  The argument name
     * @param string $value The argument value
     *
     * @throws \InvalidArgumentException When argument given doesn't exist
     */
    public function setArgument($name, $value);

    /**
     * Returns true if an InputArgument object exists by name or position.
     *
     * @param string|integer $name The InputArgument name or position
     *
     * @return Boolean true if the InputArgument object exists, false otherwise
     */
    public function hasArgument($name);

    /**
     * Returns all the given options merged with the default values.
     *
     * @return array
     */
    public function getOptions();

    /**
     * Gets an option by name.
     *
     * @param string $name The name of the option
     *
     * @return mixed
     */
    public function getOption($name);

    /**
     * Sets an option value by name.
     *
     * @param string         $name  The option name
     * @param string|boolean $value The option value
     *
     * @throws \InvalidArgumentException When option given doesn't exist
     */
    public function setOption($name, $value);

    /**
     * Returns true if an InputOption object exists by name.
     *
     * @param string $name The InputOption name
     *
     * @return Boolean true if the InputOption object exists, false otherwise
     */
    public function hasOption($name);

    /**
     * Is this input means interactive?
     *
     * @return Boolean
     */
    public function isInteractive();

    /**
     * Sets the input interactivity.
     *
     * @param Boolean $interactive If the input should be interactive
     */
    public function setInteractive($interactive);
}
PK��Z��O�VV/Symfony/Component/Console/Input/InputOption.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Input;

/**
 * Represents a command line option.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class InputOption
{
    const VALUE_NONE     = 1;
    const VALUE_REQUIRED = 2;
    const VALUE_OPTIONAL = 4;
    const VALUE_IS_ARRAY = 8;

    private $name;
    private $shortcut;
    private $mode;
    private $default;
    private $description;

    /**
     * Constructor.
     *
     * @param string       $name        The option name
     * @param string|array $shortcut    The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts
     * @param integer      $mode        The option mode: One of the VALUE_* constants
     * @param string       $description A description text
     * @param mixed        $default     The default value (must be null for self::VALUE_REQUIRED or self::VALUE_NONE)
     *
     * @throws \InvalidArgumentException If option mode is invalid or incompatible
     *
     * @api
     */
    public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null)
    {
        if (0 === strpos($name, '--')) {
            $name = substr($name, 2);
        }

        if (empty($name)) {
            throw new \InvalidArgumentException('An option name cannot be empty.');
        }

        if (empty($shortcut)) {
            $shortcut = null;
        }

        if (null !== $shortcut) {
            if (is_array($shortcut)) {
                $shortcut = implode('|', $shortcut);
            }
            $shortcuts = preg_split('{(\|)-?}', ltrim($shortcut, '-'));
            $shortcuts = array_filter($shortcuts);
            $shortcut = implode('|', $shortcuts);

            if (empty($shortcut)) {
                throw new \InvalidArgumentException('An option shortcut cannot be empty.');
            }
        }

        if (null === $mode) {
            $mode = self::VALUE_NONE;
        } elseif (!is_int($mode) || $mode > 15 || $mode < 1) {
            throw new \InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode));
        }

        $this->name        = $name;
        $this->shortcut    = $shortcut;
        $this->mode        = $mode;
        $this->description = $description;

        if ($this->isArray() && !$this->acceptValue()) {
            throw new \InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.');
        }

        $this->setDefault($default);
    }

    /**
     * Returns the option shortcut.
     *
     * @return string The shortcut
     */
    public function getShortcut()
    {
        return $this->shortcut;
    }

    /**
     * Returns the option name.
     *
     * @return string The name
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Returns true if the option accepts a value.
     *
     * @return Boolean true if value mode is not self::VALUE_NONE, false otherwise
     */
    public function acceptValue()
    {
        return $this->isValueRequired() || $this->isValueOptional();
    }

    /**
     * Returns true if the option requires a value.
     *
     * @return Boolean true if value mode is self::VALUE_REQUIRED, false otherwise
     */
    public function isValueRequired()
    {
        return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode);
    }

    /**
     * Returns true if the option takes an optional value.
     *
     * @return Boolean true if value mode is self::VALUE_OPTIONAL, false otherwise
     */
    public function isValueOptional()
    {
        return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode);
    }

    /**
     * Returns true if the option can take multiple values.
     *
     * @return Boolean true if mode is self::VALUE_IS_ARRAY, false otherwise
     */
    public function isArray()
    {
        return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode);
    }

    /**
     * Sets the default value.
     *
     * @param mixed $default The default value
     *
     * @throws \LogicException When incorrect default value is given
     */
    public function setDefault($default = null)
    {
        if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) {
            throw new \LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.');
        }

        if ($this->isArray()) {
            if (null === $default) {
                $default = array();
            } elseif (!is_array($default)) {
                throw new \LogicException('A default value for an array option must be an array.');
            }
        }

        $this->default = $this->acceptValue() ? $default : false;
    }

    /**
     * Returns the default value.
     *
     * @return mixed The default value
     */
    public function getDefault()
    {
        return $this->default;
    }

    /**
     * Returns the description text.
     *
     * @return string The description text
     */
    public function getDescription()
    {
        return $this->description;
    }

    /**
     * Checks whether the given option equals this one
     *
     * @param InputOption $option option to compare
     * @return Boolean
     */
    public function equals(InputOption $option)
    {
        return $option->getName() === $this->getName()
            && $option->getShortcut() === $this->getShortcut()
            && $option->getDefault() === $this->getDefault()
            && $option->isArray() === $this->isArray()
            && $option->isValueRequired() === $this->isValueRequired()
            && $option->isValueOptional() === $this->isValueOptional()
        ;
    }
}
PK��Z1�E(0(03Symfony/Component/Console/Input/InputDefinition.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Input;

if (!defined('JSON_UNESCAPED_UNICODE')) {
    define('JSON_UNESCAPED_SLASHES', 64);
    define('JSON_UNESCAPED_UNICODE', 256);
}

use Symfony\Component\Console\Descriptor\TextDescriptor;
use Symfony\Component\Console\Descriptor\XmlDescriptor;
use Symfony\Component\Console\Output\BufferedOutput;

/**
 * A InputDefinition represents a set of valid command line arguments and options.
 *
 * Usage:
 *
 *     $definition = new InputDefinition(array(
 *       new InputArgument('name', InputArgument::REQUIRED),
 *       new InputOption('foo', 'f', InputOption::VALUE_REQUIRED),
 *     ));
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class InputDefinition
{
    private $arguments;
    private $requiredCount;
    private $hasAnArrayArgument = false;
    private $hasOptional;
    private $options;
    private $shortcuts;

    /**
     * Constructor.
     *
     * @param array $definition An array of InputArgument and InputOption instance
     *
     * @api
     */
    public function __construct(array $definition = array())
    {
        $this->setDefinition($definition);
    }

    /**
     * Sets the definition of the input.
     *
     * @param array $definition The definition array
     *
     * @api
     */
    public function setDefinition(array $definition)
    {
        $arguments = array();
        $options = array();
        foreach ($definition as $item) {
            if ($item instanceof InputOption) {
                $options[] = $item;
            } else {
                $arguments[] = $item;
            }
        }

        $this->setArguments($arguments);
        $this->setOptions($options);
    }

    /**
     * Sets the InputArgument objects.
     *
     * @param InputArgument[] $arguments An array of InputArgument objects
     *
     * @api
     */
    public function setArguments($arguments = array())
    {
        $this->arguments          = array();
        $this->requiredCount      = 0;
        $this->hasOptional        = false;
        $this->hasAnArrayArgument = false;
        $this->addArguments($arguments);
    }

    /**
     * Adds an array of InputArgument objects.
     *
     * @param InputArgument[] $arguments An array of InputArgument objects
     *
     * @api
     */
    public function addArguments($arguments = array())
    {
        if (null !== $arguments) {
            foreach ($arguments as $argument) {
                $this->addArgument($argument);
            }
        }
    }

    /**
     * Adds an InputArgument object.
     *
     * @param InputArgument $argument An InputArgument object
     *
     * @throws \LogicException When incorrect argument is given
     *
     * @api
     */
    public function addArgument(InputArgument $argument)
    {
        if (isset($this->arguments[$argument->getName()])) {
            throw new \LogicException(sprintf('An argument with name "%s" already exists.', $argument->getName()));
        }

        if ($this->hasAnArrayArgument) {
            throw new \LogicException('Cannot add an argument after an array argument.');
        }

        if ($argument->isRequired() && $this->hasOptional) {
            throw new \LogicException('Cannot add a required argument after an optional one.');
        }

        if ($argument->isArray()) {
            $this->hasAnArrayArgument = true;
        }

        if ($argument->isRequired()) {
            ++$this->requiredCount;
        } else {
            $this->hasOptional = true;
        }

        $this->arguments[$argument->getName()] = $argument;
    }

    /**
     * Returns an InputArgument by name or by position.
     *
     * @param string|integer $name The InputArgument name or position
     *
     * @return InputArgument An InputArgument object
     *
     * @throws \InvalidArgumentException When argument given doesn't exist
     *
     * @api
     */
    public function getArgument($name)
    {
        if (!$this->hasArgument($name)) {
            throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
        }

        $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;

        return $arguments[$name];
    }

    /**
     * Returns true if an InputArgument object exists by name or position.
     *
     * @param string|integer $name The InputArgument name or position
     *
     * @return Boolean true if the InputArgument object exists, false otherwise
     *
     * @api
     */
    public function hasArgument($name)
    {
        $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;

        return isset($arguments[$name]);
    }

    /**
     * Gets the array of InputArgument objects.
     *
     * @return InputArgument[] An array of InputArgument objects
     *
     * @api
     */
    public function getArguments()
    {
        return $this->arguments;
    }

    /**
     * Returns the number of InputArguments.
     *
     * @return integer The number of InputArguments
     */
    public function getArgumentCount()
    {
        return $this->hasAnArrayArgument ? PHP_INT_MAX : count($this->arguments);
    }

    /**
     * Returns the number of required InputArguments.
     *
     * @return integer The number of required InputArguments
     */
    public function getArgumentRequiredCount()
    {
        return $this->requiredCount;
    }

    /**
     * Gets the default values.
     *
     * @return array An array of default values
     */
    public function getArgumentDefaults()
    {
        $values = array();
        foreach ($this->arguments as $argument) {
            $values[$argument->getName()] = $argument->getDefault();
        }

        return $values;
    }

    /**
     * Sets the InputOption objects.
     *
     * @param InputOption[] $options An array of InputOption objects
     *
     * @api
     */
    public function setOptions($options = array())
    {
        $this->options = array();
        $this->shortcuts = array();
        $this->addOptions($options);
    }

    /**
     * Adds an array of InputOption objects.
     *
     * @param InputOption[] $options An array of InputOption objects
     *
     * @api
     */
    public function addOptions($options = array())
    {
        foreach ($options as $option) {
            $this->addOption($option);
        }
    }

    /**
     * Adds an InputOption object.
     *
     * @param InputOption $option An InputOption object
     *
     * @throws \LogicException When option given already exist
     *
     * @api
     */
    public function addOption(InputOption $option)
    {
        if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) {
            throw new \LogicException(sprintf('An option named "%s" already exists.', $option->getName()));
        }

        if ($option->getShortcut()) {
            foreach (explode('|', $option->getShortcut()) as $shortcut) {
                if (isset($this->shortcuts[$shortcut]) && !$option->equals($this->options[$this->shortcuts[$shortcut]])) {
                    throw new \LogicException(sprintf('An option with shortcut "%s" already exists.', $shortcut));
                }
            }
        }

        $this->options[$option->getName()] = $option;
        if ($option->getShortcut()) {
            foreach (explode('|', $option->getShortcut()) as $shortcut) {
                $this->shortcuts[$shortcut] = $option->getName();
            }
        }
    }

    /**
     * Returns an InputOption by name.
     *
     * @param string $name The InputOption name
     *
     * @return InputOption A InputOption object
     *
     * @throws \InvalidArgumentException When option given doesn't exist
     *
     * @api
     */
    public function getOption($name)
    {
        if (!$this->hasOption($name)) {
            throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
        }

        return $this->options[$name];
    }

    /**
     * Returns true if an InputOption object exists by name.
     *
     * @param string $name The InputOption name
     *
     * @return Boolean true if the InputOption object exists, false otherwise
     *
     * @api
     */
    public function hasOption($name)
    {
        return isset($this->options[$name]);
    }

    /**
     * Gets the array of InputOption objects.
     *
     * @return InputOption[] An array of InputOption objects
     *
     * @api
     */
    public function getOptions()
    {
        return $this->options;
    }

    /**
     * Returns true if an InputOption object exists by shortcut.
     *
     * @param string $name The InputOption shortcut
     *
     * @return Boolean true if the InputOption object exists, false otherwise
     */
    public function hasShortcut($name)
    {
        return isset($this->shortcuts[$name]);
    }

    /**
     * Gets an InputOption by shortcut.
     *
     * @param string $shortcut the Shortcut name
     *
     * @return InputOption An InputOption object
     */
    public function getOptionForShortcut($shortcut)
    {
        return $this->getOption($this->shortcutToName($shortcut));
    }

    /**
     * Gets an array of default values.
     *
     * @return array An array of all default values
     */
    public function getOptionDefaults()
    {
        $values = array();
        foreach ($this->options as $option) {
            $values[$option->getName()] = $option->getDefault();
        }

        return $values;
    }

    /**
     * Returns the InputOption name given a shortcut.
     *
     * @param string $shortcut The shortcut
     *
     * @return string The InputOption name
     *
     * @throws \InvalidArgumentException When option given does not exist
     */
    private function shortcutToName($shortcut)
    {
        if (!isset($this->shortcuts[$shortcut])) {
            throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
        }

        return $this->shortcuts[$shortcut];
    }

    /**
     * Gets the synopsis.
     *
     * @return string The synopsis
     */
    public function getSynopsis()
    {
        $elements = array();
        foreach ($this->getOptions() as $option) {
            $shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : '';
            $elements[] = sprintf('['.($option->isValueRequired() ? '%s--%s="..."' : ($option->isValueOptional() ? '%s--%s[="..."]' : '%s--%s')).']', $shortcut, $option->getName());
        }

        foreach ($this->getArguments() as $argument) {
            $elements[] = sprintf($argument->isRequired() ? '%s' : '[%s]', $argument->getName().($argument->isArray() ? '1' : ''));

            if ($argument->isArray()) {
                $elements[] = sprintf('... [%sN]', $argument->getName());
            }
        }

        return implode(' ', $elements);
    }

    /**
     * Returns a textual representation of the InputDefinition.
     *
     * @return string A string representing the InputDefinition
     *
     * @deprecated Deprecated since version 2.3, to be removed in 3.0.
     */
    public function asText()
    {
        $descriptor = new TextDescriptor();
        $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
        $descriptor->describe($output, $this, array('raw_output' => true));

        return $output->fetch();
    }

    /**
     * Returns an XML representation of the InputDefinition.
     *
     * @param Boolean $asDom Whether to return a DOM or an XML string
     *
     * @return string|\DOMDocument An XML string representing the InputDefinition
     *
     * @deprecated Deprecated since version 2.3, to be removed in 3.0.
     */
    public function asXml($asDom = false)
    {
        $descriptor = new XmlDescriptor();

        if ($asDom) {
            return $descriptor->getInputDefinitionDocument($this);
        }

        $output = new BufferedOutput();
        $descriptor->describe($output, $this);

        return $output->fetch();
    }
}
PK��Z�΂=�
�
/Symfony/Component/Console/Input/StringInput.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Input;

/**
 * StringInput represents an input provided as a string.
 *
 * Usage:
 *
 *     $input = new StringInput('foo --bar="foobar"');
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class StringInput extends ArgvInput
{
    const REGEX_STRING = '([^\s]+?)(?:\s|(?<!\\\\)"|(?<!\\\\)\'|$)';
    const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')';

    /**
     * Constructor.
     *
     * @param string          $input      An array of parameters from the CLI (in the argv format)
     * @param InputDefinition $definition A InputDefinition instance
     *
     * @deprecated The second argument is deprecated as it does not work (will be removed in 3.0), use 'bind' method instead
     *
     * @api
     */
    public function __construct($input, InputDefinition $definition = null)
    {
        parent::__construct(array(), null);

        $this->setTokens($this->tokenize($input));

        if (null !== $definition) {
            $this->bind($definition);
        }
    }

    /**
     * Tokenizes a string.
     *
     * @param string $input The input to tokenize
     *
     * @return array An array of tokens
     *
     * @throws \InvalidArgumentException When unable to parse input (should never happen)
     */
    private function tokenize($input)
    {
        $tokens = array();
        $length = strlen($input);
        $cursor = 0;
        while ($cursor < $length) {
            if (preg_match('/\s+/A', $input, $match, null, $cursor)) {
            } elseif (preg_match('/([^="\'\s]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor)) {
                $tokens[] = $match[1].$match[2].stripcslashes(str_replace(array('"\'', '\'"', '\'\'', '""'), '', substr($match[3], 1, strlen($match[3]) - 2)));
            } elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, null, $cursor)) {
                $tokens[] = stripcslashes(substr($match[0], 1, strlen($match[0]) - 2));
            } elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, null, $cursor)) {
                $tokens[] = stripcslashes($match[1]);
            } else {
                // should never happen
                // @codeCoverageIgnoreStart
                throw new \InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10)));
                // @codeCoverageIgnoreEnd
            }

            $cursor += strlen($match[0]);
        }

        return $tokens;
    }
}
PK��Zgm()Symfony/Component/Console/Input/Input.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Input;

/**
 * Input is the base class for all concrete Input classes.
 *
 * Three concrete classes are provided by default:
 *
 *  * `ArgvInput`: The input comes from the CLI arguments (argv)
 *  * `StringInput`: The input is provided as a string
 *  * `ArrayInput`: The input is provided as an array
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class Input implements InputInterface
{
    /**
     * @var InputDefinition
     */
    protected $definition;
    protected $options = array();
    protected $arguments = array();
    protected $interactive = true;

    /**
     * Constructor.
     *
     * @param InputDefinition $definition A InputDefinition instance
     */
    public function __construct(InputDefinition $definition = null)
    {
        if (null === $definition) {
            $this->definition = new InputDefinition();
        } else {
            $this->bind($definition);
            $this->validate();
        }
    }

    /**
     * Binds the current Input instance with the given arguments and options.
     *
     * @param InputDefinition $definition A InputDefinition instance
     */
    public function bind(InputDefinition $definition)
    {
        $this->arguments = array();
        $this->options = array();
        $this->definition = $definition;

        $this->parse();
    }

    /**
     * Processes command line arguments.
     */
    abstract protected function parse();

    /**
     * Validates the input.
     *
     * @throws \RuntimeException When not enough arguments are given
     */
    public function validate()
    {
        if (count($this->arguments) < $this->definition->getArgumentRequiredCount()) {
            throw new \RuntimeException('Not enough arguments.');
        }
    }

    /**
     * Checks if the input is interactive.
     *
     * @return Boolean Returns true if the input is interactive
     */
    public function isInteractive()
    {
        return $this->interactive;
    }

    /**
     * Sets the input interactivity.
     *
     * @param Boolean $interactive If the input should be interactive
     */
    public function setInteractive($interactive)
    {
        $this->interactive = (Boolean) $interactive;
    }

    /**
     * Returns the argument values.
     *
     * @return array An array of argument values
     */
    public function getArguments()
    {
        return array_merge($this->definition->getArgumentDefaults(), $this->arguments);
    }

    /**
     * Returns the argument value for a given argument name.
     *
     * @param string $name The argument name
     *
     * @return mixed The argument value
     *
     * @throws \InvalidArgumentException When argument given doesn't exist
     */
    public function getArgument($name)
    {
        if (!$this->definition->hasArgument($name)) {
            throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
        }

        return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)->getDefault();
    }

    /**
     * Sets an argument value by name.
     *
     * @param string $name  The argument name
     * @param string $value The argument value
     *
     * @throws \InvalidArgumentException When argument given doesn't exist
     */
    public function setArgument($name, $value)
    {
        if (!$this->definition->hasArgument($name)) {
            throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
        }

        $this->arguments[$name] = $value;
    }

    /**
     * Returns true if an InputArgument object exists by name or position.
     *
     * @param string|integer $name The InputArgument name or position
     *
     * @return Boolean true if the InputArgument object exists, false otherwise
     */
    public function hasArgument($name)
    {
        return $this->definition->hasArgument($name);
    }

    /**
     * Returns the options values.
     *
     * @return array An array of option values
     */
    public function getOptions()
    {
        return array_merge($this->definition->getOptionDefaults(), $this->options);
    }

    /**
     * Returns the option value for a given option name.
     *
     * @param string $name The option name
     *
     * @return mixed The option value
     *
     * @throws \InvalidArgumentException When option given doesn't exist
     */
    public function getOption($name)
    {
        if (!$this->definition->hasOption($name)) {
            throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
        }

        return isset($this->options[$name]) ? $this->options[$name] : $this->definition->getOption($name)->getDefault();
    }

    /**
     * Sets an option value by name.
     *
     * @param string         $name  The option name
     * @param string|boolean $value The option value
     *
     * @throws \InvalidArgumentException When option given doesn't exist
     */
    public function setOption($name, $value)
    {
        if (!$this->definition->hasOption($name)) {
            throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
        }

        $this->options[$name] = $value;
    }

    /**
     * Returns true if an InputOption object exists by name.
     *
     * @param string $name The InputOption name
     *
     * @return Boolean true if the InputOption object exists, false otherwise
     */
    public function hasOption($name)
    {
        return $this->definition->hasOption($name);
    }

    /**
     * Escapes a token through escapeshellarg if it contains unsafe chars
     *
     * @param string $token
     *
     * @return string
     */
    public function escapeToken($token)
    {
        return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token);
    }
}
PK��Zp���%%.Symfony/Component/Console/Input/ArrayInput.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Input;

/**
 * ArrayInput represents an input provided as an array.
 *
 * Usage:
 *
 *     $input = new ArrayInput(array('name' => 'foo', '--bar' => 'foobar'));
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class ArrayInput extends Input
{
    private $parameters;

    /**
     * Constructor.
     *
     * @param array           $parameters An array of parameters
     * @param InputDefinition $definition A InputDefinition instance
     *
     * @api
     */
    public function __construct(array $parameters, InputDefinition $definition = null)
    {
        $this->parameters = $parameters;

        parent::__construct($definition);
    }

    /**
     * Returns the first argument from the raw parameters (not parsed).
     *
     * @return string The value of the first argument or null otherwise
     */
    public function getFirstArgument()
    {
        foreach ($this->parameters as $key => $value) {
            if ($key && '-' === $key[0]) {
                continue;
            }

            return $value;
        }
    }

    /**
     * Returns true if the raw parameters (not parsed) contain a value.
     *
     * This method is to be used to introspect the input parameters
     * before they have been validated. It must be used carefully.
     *
     * @param string|array $values The values to look for in the raw parameters (can be an array)
     *
     * @return Boolean true if the value is contained in the raw parameters
     */
    public function hasParameterOption($values)
    {
        $values = (array) $values;

        foreach ($this->parameters as $k => $v) {
            if (!is_int($k)) {
                $v = $k;
            }

            if (in_array($v, $values)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Returns the value of a raw option (not parsed).
     *
     * This method is to be used to introspect the input parameters
     * before they have been validated. It must be used carefully.
     *
     * @param string|array $values  The value(s) to look for in the raw parameters (can be an array)
     * @param mixed        $default The default value to return if no result is found
     *
     * @return mixed The option value
     */
    public function getParameterOption($values, $default = false)
    {
        $values = (array) $values;

        foreach ($this->parameters as $k => $v) {
            if (is_int($k) && in_array($v, $values)) {
                return true;
            } elseif (in_array($k, $values)) {
                return $v;
            }
        }

        return $default;
    }

    /**
     * Returns a stringified representation of the args passed to the command
     *
     * @return string
     */
    public function __toString()
    {
        $params = array();
        foreach ($this->parameters as $param => $val) {
            if ($param && '-' === $param[0]) {
                $params[] = $param . ('' != $val ? '='.$this->escapeToken($val) : '');
            } else {
                $params[] = $this->escapeToken($val);
            }
        }

        return implode(' ', $params);
    }

    /**
     * Processes command line arguments.
     */
    protected function parse()
    {
        foreach ($this->parameters as $key => $value) {
            if (0 === strpos($key, '--')) {
                $this->addLongOption(substr($key, 2), $value);
            } elseif ('-' === $key[0]) {
                $this->addShortOption(substr($key, 1), $value);
            } else {
                $this->addArgument($key, $value);
            }
        }
    }

    /**
     * Adds a short option value.
     *
     * @param string $shortcut The short option key
     * @param mixed  $value    The value for the option
     *
     * @throws \InvalidArgumentException When option given doesn't exist
     */
    private function addShortOption($shortcut, $value)
    {
        if (!$this->definition->hasShortcut($shortcut)) {
            throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
        }

        $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
    }

    /**
     * Adds a long option value.
     *
     * @param string $name  The long option key
     * @param mixed  $value The value for the option
     *
     * @throws \InvalidArgumentException When option given doesn't exist
     * @throws \InvalidArgumentException When a required value is missing
     */
    private function addLongOption($name, $value)
    {
        if (!$this->definition->hasOption($name)) {
            throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
        }

        $option = $this->definition->getOption($name);

        if (null === $value) {
            if ($option->isValueRequired()) {
                throw new \InvalidArgumentException(sprintf('The "--%s" option requires a value.', $name));
            }

            $value = $option->isValueOptional() ? $option->getDefault() : true;
        }

        $this->options[$name] = $value;
    }

    /**
     * Adds an argument value.
     *
     * @param string $name  The argument name
     * @param mixed  $value The value for the argument
     *
     * @throws \InvalidArgumentException When argument given doesn't exist
     */
    private function addArgument($name, $value)
    {
        if (!$this->definition->hasArgument($name)) {
            throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
        }

        $this->arguments[$name] = $value;
    }
}
PK��Z9K�h^^7Symfony/Component/Console/Input/InputAwareInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Input;

/**
 * InputAwareInterface should be implemented by classes that depends on the
 * Console Input.
 *
 * @author Wouter J <waldio.webdesign@gmail.com>
 */
interface InputAwareInterface
{
    /**
     * Sets the Console Input.
     *
     * @param InputInterface
     */
    public function setInput(InputInterface $input);
}
PK��Zonj�&&<Symfony/Component/Console/Formatter/OutputFormatterStyle.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Formatter;

/**
 * Formatter style class for defining styles.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 *
 * @api
 */
class OutputFormatterStyle implements OutputFormatterStyleInterface
{
    private static $availableForegroundColors = array(
        'black'     => 30,
        'red'       => 31,
        'green'     => 32,
        'yellow'    => 33,
        'blue'      => 34,
        'magenta'   => 35,
        'cyan'      => 36,
        'white'     => 37
    );
    private static $availableBackgroundColors = array(
        'black'     => 40,
        'red'       => 41,
        'green'     => 42,
        'yellow'    => 43,
        'blue'      => 44,
        'magenta'   => 45,
        'cyan'      => 46,
        'white'     => 47
    );
    private static $availableOptions = array(
        'bold'          => 1,
        'underscore'    => 4,
        'blink'         => 5,
        'reverse'       => 7,
        'conceal'       => 8
    );

    private $foreground;
    private $background;
    private $options = array();

    /**
     * Initializes output formatter style.
     *
     * @param string|null $foreground The style foreground color name
     * @param string|null $background The style background color name
     * @param array       $options    The style options
     *
     * @api
     */
    public function __construct($foreground = null, $background = null, array $options = array())
    {
        if (null !== $foreground) {
            $this->setForeground($foreground);
        }
        if (null !== $background) {
            $this->setBackground($background);
        }
        if (count($options)) {
            $this->setOptions($options);
        }
    }

    /**
     * Sets style foreground color.
     *
     * @param string|null $color The color name
     *
     * @throws \InvalidArgumentException When the color name isn't defined
     *
     * @api
     */
    public function setForeground($color = null)
    {
        if (null === $color) {
            $this->foreground = null;

            return;
        }

        if (!isset(static::$availableForegroundColors[$color])) {
            throw new \InvalidArgumentException(sprintf(
                'Invalid foreground color specified: "%s". Expected one of (%s)',
                $color,
                implode(', ', array_keys(static::$availableForegroundColors))
            ));
        }

        $this->foreground = static::$availableForegroundColors[$color];
    }

    /**
     * Sets style background color.
     *
     * @param string|null $color The color name
     *
     * @throws \InvalidArgumentException When the color name isn't defined
     *
     * @api
     */
    public function setBackground($color = null)
    {
        if (null === $color) {
            $this->background = null;

            return;
        }

        if (!isset(static::$availableBackgroundColors[$color])) {
            throw new \InvalidArgumentException(sprintf(
                'Invalid background color specified: "%s". Expected one of (%s)',
                $color,
                implode(', ', array_keys(static::$availableBackgroundColors))
            ));
        }

        $this->background = static::$availableBackgroundColors[$color];
    }

    /**
     * Sets some specific style option.
     *
     * @param string $option The option name
     *
     * @throws \InvalidArgumentException When the option name isn't defined
     *
     * @api
     */
    public function setOption($option)
    {
        if (!isset(static::$availableOptions[$option])) {
            throw new \InvalidArgumentException(sprintf(
                'Invalid option specified: "%s". Expected one of (%s)',
                $option,
                implode(', ', array_keys(static::$availableOptions))
            ));
        }

        if (false === array_search(static::$availableOptions[$option], $this->options)) {
            $this->options[] = static::$availableOptions[$option];
        }
    }

    /**
     * Unsets some specific style option.
     *
     * @param string $option The option name
     *
     * @throws \InvalidArgumentException When the option name isn't defined
     *
     */
    public function unsetOption($option)
    {
        if (!isset(static::$availableOptions[$option])) {
            throw new \InvalidArgumentException(sprintf(
                'Invalid option specified: "%s". Expected one of (%s)',
                $option,
                implode(', ', array_keys(static::$availableOptions))
            ));
        }

        $pos = array_search(static::$availableOptions[$option], $this->options);
        if (false !== $pos) {
            unset($this->options[$pos]);
        }
    }

    /**
     * Sets multiple style options at once.
     *
     * @param array $options
     */
    public function setOptions(array $options)
    {
        $this->options = array();

        foreach ($options as $option) {
            $this->setOption($option);
        }
    }

    /**
     * Applies the style to a given text.
     *
     * @param string $text The text to style
     *
     * @return string
     */
    public function apply($text)
    {
        $codes = array();

        if (null !== $this->foreground) {
            $codes[] = $this->foreground;
        }
        if (null !== $this->background) {
            $codes[] = $this->background;
        }
        if (count($this->options)) {
            $codes = array_merge($codes, $this->options);
        }

        if (0 === count($codes)) {
            return $text;
        }

        return sprintf("\033[%sm%s\033[0m", implode(';', $codes), $text);
    }
}
PK��Z��l���7Symfony/Component/Console/Formatter/OutputFormatter.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Formatter;

/**
 * Formatter class for console output.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 *
 * @api
 */
class OutputFormatter implements OutputFormatterInterface
{
    private $decorated;
    private $styles = array();
    private $styleStack;

    /**
     * Escapes "<" special char in given text.
     *
     * @param string $text Text to escape
     *
     * @return string Escaped text
     */
    public static function escape($text)
    {
        return preg_replace('/([^\\\\]?)</is', '$1\\<', $text);
    }

    /**
     * Initializes console output formatter.
     *
     * @param Boolean          $decorated Whether this formatter should actually decorate strings
     * @param OutputFormatterStyleInterface[] $styles    Array of "name => FormatterStyle" instances
     *
     * @api
     */
    public function __construct($decorated = false, array $styles = array())
    {
        $this->decorated = (Boolean) $decorated;

        $this->setStyle('error', new OutputFormatterStyle('white', 'red'));
        $this->setStyle('info', new OutputFormatterStyle('green'));
        $this->setStyle('comment', new OutputFormatterStyle('yellow'));
        $this->setStyle('question', new OutputFormatterStyle('black', 'cyan'));

        foreach ($styles as $name => $style) {
            $this->setStyle($name, $style);
        }

        $this->styleStack = new OutputFormatterStyleStack();
    }

    /**
     * Sets the decorated flag.
     *
     * @param Boolean $decorated Whether to decorate the messages or not
     *
     * @api
     */
    public function setDecorated($decorated)
    {
        $this->decorated = (Boolean) $decorated;
    }

    /**
     * Gets the decorated flag.
     *
     * @return Boolean true if the output will decorate messages, false otherwise
     *
     * @api
     */
    public function isDecorated()
    {
        return $this->decorated;
    }

    /**
     * Sets a new style.
     *
     * @param string                        $name  The style name
     * @param OutputFormatterStyleInterface $style The style instance
     *
     * @api
     */
    public function setStyle($name, OutputFormatterStyleInterface $style)
    {
        $this->styles[strtolower($name)] = $style;
    }

    /**
     * Checks if output formatter has style with specified name.
     *
     * @param string $name
     *
     * @return Boolean
     *
     * @api
     */
    public function hasStyle($name)
    {
        return isset($this->styles[strtolower($name)]);
    }

    /**
     * Gets style options from style with specified name.
     *
     * @param string $name
     *
     * @return OutputFormatterStyleInterface
     *
     * @throws \InvalidArgumentException When style isn't defined
     *
     * @api
     */
    public function getStyle($name)
    {
        if (!$this->hasStyle($name)) {
            throw new \InvalidArgumentException(sprintf('Undefined style: %s', $name));
        }

        return $this->styles[strtolower($name)];
    }

    /**
     * Formats a message according to the given styles.
     *
     * @param string $message The message to style
     *
     * @return string The styled message
     *
     * @api
     */
    public function format($message)
    {
        $offset = 0;
        $output = '';
        $tagRegex = '[a-z][a-z0-9_=;-]*';
        preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#isx", $message, $matches, PREG_OFFSET_CAPTURE);
        foreach ($matches[0] as $i => $match) {
            $pos = $match[1];
            $text = $match[0];

            // add the text up to the next tag
            $output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset));
            $offset = $pos + strlen($text);

            // opening tag?
            if ($open = '/' != $text[1]) {
                $tag = $matches[1][$i][0];
            } else {
                $tag = isset($matches[3][$i][0]) ? $matches[3][$i][0] : '';
            }

            if (!$open && !$tag) {
                // </>
                $this->styleStack->pop();
            } elseif ($pos && '\\' == $message[$pos - 1]) {
                // escaped tag
                $output .= $this->applyCurrentStyle($text);
            } elseif (false === $style = $this->createStyleFromString(strtolower($tag))) {
                $output .= $this->applyCurrentStyle($text);
            } elseif ($open) {
                $this->styleStack->push($style);
            } else {
                $this->styleStack->pop($style);
            }
        }

        $output .= $this->applyCurrentStyle(substr($message, $offset));

        return str_replace('\\<', '<', $output);
    }

    /**
     * @return OutputFormatterStyleStack
     */
    public function getStyleStack()
    {
        return $this->styleStack;
    }

    /**
     * Tries to create new style instance from string.
     *
     * @param string $string
     *
     * @return OutputFormatterStyle|Boolean false if string is not format string
     */
    private function createStyleFromString($string)
    {
        if (isset($this->styles[$string])) {
            return $this->styles[$string];
        }

        if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', strtolower($string), $matches, PREG_SET_ORDER)) {
            return false;
        }

        $style = new OutputFormatterStyle();
        foreach ($matches as $match) {
            array_shift($match);

            if ('fg' == $match[0]) {
                $style->setForeground($match[1]);
            } elseif ('bg' == $match[0]) {
                $style->setBackground($match[1]);
            } else {
                $style->setOption($match[1]);
            }
        }

        return $style;
    }

    /**
     * Applies current style from stack to text, if must be applied.
     *
     * @param string $text Input text
     *
     * @return string Styled text
     */
    private function applyCurrentStyle($text)
    {
        return $this->isDecorated() && strlen($text) > 0 ? $this->styleStack->getCurrent()->apply($text) : $text;
    }
}
PK��Z5����ESymfony/Component/Console/Formatter/OutputFormatterStyleInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Formatter;

/**
 * Formatter style interface for defining styles.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 *
 * @api
 */
interface OutputFormatterStyleInterface
{
    /**
     * Sets style foreground color.
     *
     * @param string $color The color name
     *
     * @api
     */
    public function setForeground($color = null);

    /**
     * Sets style background color.
     *
     * @param string $color The color name
     *
     * @api
     */
    public function setBackground($color = null);

    /**
     * Sets some specific style option.
     *
     * @param string $option The option name
     *
     * @api
     */
    public function setOption($option);

    /**
     * Unsets some specific style option.
     *
     * @param string $option The option name
     */
    public function unsetOption($option);

    /**
     * Sets multiple style options at once.
     *
     * @param array $options
     */
    public function setOptions(array $options);

    /**
     * Applies the style to a given text.
     *
     * @param string $text The text to style
     *
     * @return string
     */
    public function apply($text);
}
PK��Z�v��
�
ASymfony/Component/Console/Formatter/OutputFormatterStyleStack.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Formatter;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class OutputFormatterStyleStack
{
    /**
     * @var OutputFormatterStyleInterface[]
     */
    private $styles;

    /**
     * @var OutputFormatterStyleInterface
     */
    private $emptyStyle;

    /**
     * Constructor.
     *
     * @param OutputFormatterStyleInterface|null $emptyStyle
     */
    public function __construct(OutputFormatterStyleInterface $emptyStyle = null)
    {
        $this->emptyStyle = $emptyStyle ?: new OutputFormatterStyle();
        $this->reset();
    }

    /**
     * Resets stack (ie. empty internal arrays).
     */
    public function reset()
    {
        $this->styles = array();
    }

    /**
     * Pushes a style in the stack.
     *
     * @param OutputFormatterStyleInterface $style
     */
    public function push(OutputFormatterStyleInterface $style)
    {
        $this->styles[] = $style;
    }

    /**
     * Pops a style from the stack.
     *
     * @param OutputFormatterStyleInterface|null $style
     *
     * @return OutputFormatterStyleInterface
     *
     * @throws \InvalidArgumentException  When style tags incorrectly nested
     */
    public function pop(OutputFormatterStyleInterface $style = null)
    {
        if (empty($this->styles)) {
            return $this->emptyStyle;
        }

        if (null === $style) {
            return array_pop($this->styles);
        }

        foreach (array_reverse($this->styles, true) as $index => $stackedStyle) {
            if ($style->apply('') === $stackedStyle->apply('')) {
                $this->styles = array_slice($this->styles, 0, $index);

                return $stackedStyle;
            }
        }

        throw new \InvalidArgumentException('Incorrectly nested style tag found.');
    }

    /**
     * Computes current style with stacks top codes.
     *
     * @return OutputFormatterStyle
     */
    public function getCurrent()
    {
        if (empty($this->styles)) {
            return $this->emptyStyle;
        }

        return $this->styles[count($this->styles)-1];
    }

    /**
     * @param OutputFormatterStyleInterface $emptyStyle
     *
     * @return OutputFormatterStyleStack
     */
    public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle)
    {
        $this->emptyStyle = $emptyStyle;

        return $this;
    }

    /**
     * @return OutputFormatterStyleInterface
     */
    public function getEmptyStyle()
    {
        return $this->emptyStyle;
    }
}
PK��ZJp����@Symfony/Component/Console/Formatter/OutputFormatterInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Formatter;

/**
 * Formatter interface for console output.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 *
 * @api
 */
interface OutputFormatterInterface
{
    /**
     * Sets the decorated flag.
     *
     * @param Boolean $decorated Whether to decorate the messages or not
     *
     * @api
     */
    public function setDecorated($decorated);

    /**
     * Gets the decorated flag.
     *
     * @return Boolean true if the output will decorate messages, false otherwise
     *
     * @api
     */
    public function isDecorated();

    /**
     * Sets a new style.
     *
     * @param string                        $name  The style name
     * @param OutputFormatterStyleInterface $style The style instance
     *
     * @api
     */
    public function setStyle($name, OutputFormatterStyleInterface $style);

    /**
     * Checks if output formatter has style with specified name.
     *
     * @param string $name
     *
     * @return Boolean
     *
     * @api
     */
    public function hasStyle($name);

    /**
     * Gets style options from style with specified name.
     *
     * @param string $name
     *
     * @return OutputFormatterStyleInterface
     *
     * @api
     */
    public function getStyle($name);

    /**
     * Formats a message according to the given styles.
     *
     * @param string $message The message to style
     *
     * @return string The styled message
     *
     * @api
     */
    public function format($message);
}
PK��Z��0�KK;Symfony/Component/Console/Output/ConsoleOutputInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Output;

/**
 * ConsoleOutputInterface is the interface implemented by ConsoleOutput class.
 * This adds information about stderr output stream.
 *
 * @author Dariusz Górecki <darek.krk@gmail.com>
 */
interface ConsoleOutputInterface extends OutputInterface
{
    /**
     * Gets the OutputInterface for errors.
     *
     * @return OutputInterface
     */
    public function getErrorOutput();

    /**
     * Sets the OutputInterface used for errors.
     *
     * @param OutputInterface $error
     */
    public function setErrorOutput(OutputInterface $error);
}
PK��Z��ϱ}}2Symfony/Component/Console/Output/ConsoleOutput.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Output;

use Symfony\Component\Console\Formatter\OutputFormatterInterface;

/**
 * ConsoleOutput is the default class for all CLI output. It uses STDOUT.
 *
 * This class is a convenient wrapper around `StreamOutput`.
 *
 *     $output = new ConsoleOutput();
 *
 * This is equivalent to:
 *
 *     $output = new StreamOutput(fopen('php://stdout', 'w'));
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
{
    private $stderr;

    /**
     * Constructor.
     *
     * @param integer                       $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface)
     * @param Boolean|null                  $decorated Whether to decorate messages (null for auto-guessing)
     * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter)
     *
     * @api
     */
    public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
    {
        $outputStream = 'php://stdout';
        if (!$this->hasStdoutSupport()) {
            $outputStream = 'php://output';
        }

        parent::__construct(fopen($outputStream, 'w'), $verbosity, $decorated, $formatter);

        $this->stderr = new StreamOutput(fopen('php://stderr', 'w'), $verbosity, $decorated, $formatter);
    }

    /**
     * {@inheritdoc}
     */
    public function setDecorated($decorated)
    {
        parent::setDecorated($decorated);
        $this->stderr->setDecorated($decorated);
    }

    /**
     * {@inheritdoc}
     */
    public function setFormatter(OutputFormatterInterface $formatter)
    {
        parent::setFormatter($formatter);
        $this->stderr->setFormatter($formatter);
    }

    /**
     * {@inheritdoc}
     */
    public function setVerbosity($level)
    {
        parent::setVerbosity($level);
        $this->stderr->setVerbosity($level);
    }

    /**
     * {@inheritdoc}
     */
    public function getErrorOutput()
    {
        return $this->stderr;
    }

    /**
     * {@inheritdoc}
     */
    public function setErrorOutput(OutputInterface $error)
    {
        $this->stderr = $error;
    }

    /**
     * Returns true if current environment supports writing console output to
     * STDOUT.
     *
     * IBM iSeries (OS400) exhibits character-encoding issues when writing to
     * STDOUT and doesn't properly convert ASCII to EBCDIC, resulting in garbage
     * output.
     *
     * @return boolean
     */
    protected function hasStdoutSupport()
    {
        return ('OS400' != php_uname('s'));
    }
}
PK��Z��z�MM4Symfony/Component/Console/Output/OutputInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Output;

use Symfony\Component\Console\Formatter\OutputFormatterInterface;

/**
 * OutputInterface is the interface implemented by all Output classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface OutputInterface
{
    const VERBOSITY_QUIET        = 0;
    const VERBOSITY_NORMAL       = 1;
    const VERBOSITY_VERBOSE      = 2;
    const VERBOSITY_VERY_VERBOSE = 3;
    const VERBOSITY_DEBUG        = 4;

    const OUTPUT_NORMAL = 0;
    const OUTPUT_RAW    = 1;
    const OUTPUT_PLAIN  = 2;

    /**
     * Writes a message to the output.
     *
     * @param string|array $messages The message as an array of lines or a single string
     * @param Boolean      $newline  Whether to add a newline
     * @param integer      $type     The type of output (one of the OUTPUT constants)
     *
     * @throws \InvalidArgumentException When unknown output type is given
     *
     * @api
     */
    public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL);

    /**
     * Writes a message to the output and adds a newline at the end.
     *
     * @param string|array $messages The message as an array of lines of a single string
     * @param integer      $type     The type of output (one of the OUTPUT constants)
     *
     * @throws \InvalidArgumentException When unknown output type is given
     *
     * @api
     */
    public function writeln($messages, $type = self::OUTPUT_NORMAL);

    /**
     * Sets the verbosity of the output.
     *
     * @param integer $level The level of verbosity (one of the VERBOSITY constants)
     *
     * @api
     */
    public function setVerbosity($level);

    /**
     * Gets the current verbosity of the output.
     *
     * @return integer The current level of verbosity (one of the VERBOSITY constants)
     *
     * @api
     */
    public function getVerbosity();

    /**
     * Sets the decorated flag.
     *
     * @param Boolean $decorated Whether to decorate the messages
     *
     * @api
     */
    public function setDecorated($decorated);

    /**
     * Gets the decorated flag.
     *
     * @return Boolean true if the output will decorate messages, false otherwise
     *
     * @api
     */
    public function isDecorated();

    /**
     * Sets output formatter.
     *
     * @param OutputFormatterInterface $formatter
     *
     * @api
     */
    public function setFormatter(OutputFormatterInterface $formatter);

    /**
     * Returns current output formatter instance.
     *
     * @return  OutputFormatterInterface
     *
     * @api
     */
    public function getFormatter();
}
PK��ZF�$_��/Symfony/Component/Console/Output/NullOutput.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Output;

use Symfony\Component\Console\Formatter\OutputFormatter;
use Symfony\Component\Console\Formatter\OutputFormatterInterface;

/**
 * NullOutput suppresses all output.
 *
 *     $output = new NullOutput();
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Tobias Schultze <http://tobion.de>
 *
 * @api
 */
class NullOutput implements OutputInterface
{
    /**
     * {@inheritdoc}
     */
    public function setFormatter(OutputFormatterInterface $formatter)
    {
        // do nothing
    }

    /**
     * {@inheritdoc}
     */
    public function getFormatter()
    {
        // to comply with the interface we must return a OutputFormatterInterface
        return new OutputFormatter();
    }

    /**
     * {@inheritdoc}
     */
    public function setDecorated($decorated)
    {
        // do nothing
    }

    /**
     * {@inheritdoc}
     */
    public function isDecorated()
    {
        return false;
    }

    /**
     * {@inheritdoc}
     */
    public function setVerbosity($level)
    {
        // do nothing
    }

    /**
     * {@inheritdoc}
     */
    public function getVerbosity()
    {
        return self::VERBOSITY_QUIET;
    }

    /**
     * {@inheritdoc}
     */
    public function writeln($messages, $type = self::OUTPUT_NORMAL)
    {
        // do nothing
    }

    /**
     * {@inheritdoc}
     */
    public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
    {
        // do nothing
    }
}
PK��Zs�Q;;+Symfony/Component/Console/Output/Output.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Output;

use Symfony\Component\Console\Formatter\OutputFormatterInterface;
use Symfony\Component\Console\Formatter\OutputFormatter;

/**
 * Base class for output classes.
 *
 * There are five levels of verbosity:
 *
 *  * normal: no option passed (normal output)
 *  * verbose: -v (more output)
 *  * very verbose: -vv (highly extended output)
 *  * debug: -vvv (all debug output)
 *  * quiet: -q (no output)
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
abstract class Output implements OutputInterface
{
    private $verbosity;
    private $formatter;

    /**
     * Constructor.
     *
     * @param integer                       $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface)
     * @param Boolean                       $decorated Whether to decorate messages
     * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter)
     *
     * @api
     */
    public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = false, OutputFormatterInterface $formatter = null)
    {
        $this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity;
        $this->formatter = $formatter ?: new OutputFormatter();
        $this->formatter->setDecorated($decorated);
    }

    /**
     * {@inheritdoc}
     */
    public function setFormatter(OutputFormatterInterface $formatter)
    {
        $this->formatter = $formatter;
    }

    /**
     * {@inheritdoc}
     */
    public function getFormatter()
    {
        return $this->formatter;
    }

    /**
     * {@inheritdoc}
     */
    public function setDecorated($decorated)
    {
        $this->formatter->setDecorated($decorated);
    }

    /**
     * {@inheritdoc}
     */
    public function isDecorated()
    {
        return $this->formatter->isDecorated();
    }

    /**
     * {@inheritdoc}
     */
    public function setVerbosity($level)
    {
        $this->verbosity = (int) $level;
    }

    /**
     * {@inheritdoc}
     */
    public function getVerbosity()
    {
        return $this->verbosity;
    }

    public function isQuiet()
    {
        return self::VERBOSITY_QUIET === $this->verbosity;
    }

    public function isVerbose()
    {
        return self::VERBOSITY_VERBOSE <= $this->verbosity;
    }

    public function isVeryVerbose()
    {
        return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity;
    }

    public function isDebug()
    {
        return self::VERBOSITY_DEBUG <= $this->verbosity;
    }

    /**
     * {@inheritdoc}
     */
    public function writeln($messages, $type = self::OUTPUT_NORMAL)
    {
        $this->write($messages, true, $type);
    }

    /**
     * {@inheritdoc}
     */
    public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
    {
        if (self::VERBOSITY_QUIET === $this->verbosity) {
            return;
        }

        $messages = (array) $messages;

        foreach ($messages as $message) {
            switch ($type) {
                case OutputInterface::OUTPUT_NORMAL:
                    $message = $this->formatter->format($message);
                    break;
                case OutputInterface::OUTPUT_RAW:
                    break;
                case OutputInterface::OUTPUT_PLAIN:
                    $message = strip_tags($this->formatter->format($message));
                    break;
                default:
                    throw new \InvalidArgumentException(sprintf('Unknown output type given (%s)', $type));
            }

            $this->doWrite($message, $newline);
        }
    }

    /**
     * Writes a message to the output.
     *
     * @param string  $message A message to write to the output
     * @param Boolean $newline Whether to add a newline or not
     */
    abstract protected function doWrite($message, $newline);
}
PK��Z�,Q�MM1Symfony/Component/Console/Output/StreamOutput.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Output;

use Symfony\Component\Console\Formatter\OutputFormatterInterface;

/**
 * StreamOutput writes the output to a given stream.
 *
 * Usage:
 *
 * $output = new StreamOutput(fopen('php://stdout', 'w'));
 *
 * As `StreamOutput` can use any stream, you can also use a file:
 *
 * $output = new StreamOutput(fopen('/path/to/output.log', 'a', false));
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class StreamOutput extends Output
{
    private $stream;

    /**
     * Constructor.
     *
     * @param mixed                         $stream    A stream resource
     * @param integer                       $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface)
     * @param Boolean|null                  $decorated Whether to decorate messages (null for auto-guessing)
     * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter)
     *
     * @throws \InvalidArgumentException When first argument is not a real stream
     *
     * @api
     */
    public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
    {
        if (!is_resource($stream) || 'stream' !== get_resource_type($stream)) {
            throw new \InvalidArgumentException('The StreamOutput class needs a stream as its first argument.');
        }

        $this->stream = $stream;

        if (null === $decorated) {
            $decorated = $this->hasColorSupport();
        }

        parent::__construct($verbosity, $decorated, $formatter);
    }

    /**
     * Gets the stream attached to this StreamOutput instance.
     *
     * @return resource A stream resource
     */
    public function getStream()
    {
        return $this->stream;
    }

    /**
     * {@inheritdoc}
     */
    protected function doWrite($message, $newline)
    {
        if (false === @fwrite($this->stream, $message.($newline ? PHP_EOL : ''))) {
            // @codeCoverageIgnoreStart
            // should never happen
            throw new \RuntimeException('Unable to write output.');
            // @codeCoverageIgnoreEnd
        }

        fflush($this->stream);
    }

    /**
     * Returns true if the stream supports colorization.
     *
     * Colorization is disabled if not supported by the stream:
     *
     *  -  Windows without Ansicon and ConEmu
     *  -  non tty consoles
     *
     * @return Boolean true if the stream supports colorization, false otherwise
     */
    protected function hasColorSupport()
    {
        // @codeCoverageIgnoreStart
        if (DIRECTORY_SEPARATOR == '\\') {
            return false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI');
        }

        return function_exists('posix_isatty') && @posix_isatty($this->stream);
        // @codeCoverageIgnoreEnd
    }
}
PK��Zt|X4hh3Symfony/Component/Console/Output/BufferedOutput.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Output;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class BufferedOutput extends Output
{
    /**
     * @var string
     */
    private $buffer = '';

    /**
     * Empties buffer and returns its content.
     *
     * @return string
     */
    public function fetch()
    {
        $content = $this->buffer;
        $this->buffer = '';

        return $content;
    }

    /**
     * {@inheritdoc}
     */
    protected function doWrite($message, $newline)
    {
        $this->buffer .= $message;

        if ($newline) {
            $this->buffer .= "\n";
        }
    }
}
PK��Z�L�UҊҊ)Symfony/Component/Console/Application.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console;

use Symfony\Component\Console\Descriptor\TextDescriptor;
use Symfony\Component\Console\Descriptor\XmlDescriptor;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputAwareInterface;
use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Command\HelpCommand;
use Symfony\Component\Console\Command\ListCommand;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Helper\FormatterHelper;
use Symfony\Component\Console\Helper\DialogHelper;
use Symfony\Component\Console\Helper\ProgressHelper;
use Symfony\Component\Console\Helper\TableHelper;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\Console\Event\ConsoleExceptionEvent;
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

/**
 * An Application is the container for a collection of commands.
 *
 * It is the main entry point of a Console application.
 *
 * This class is optimized for a standard CLI environment.
 *
 * Usage:
 *
 *     $app = new Application('myapp', '1.0 (stable)');
 *     $app->add(new SimpleCommand());
 *     $app->run();
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class Application
{
    private $commands = array();
    private $wantHelps = false;
    private $runningCommand;
    private $name;
    private $version;
    private $catchExceptions = true;
    private $autoExit = true;
    private $definition;
    private $helperSet;
    private $dispatcher;
    private $terminalDimensions;

    /**
     * Constructor.
     *
     * @param string $name    The name of the application
     * @param string $version The version of the application
     *
     * @api
     */
    public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN')
    {
        $this->name = $name;
        $this->version = $version;
        $this->helperSet = $this->getDefaultHelperSet();
        $this->definition = $this->getDefaultInputDefinition();

        foreach ($this->getDefaultCommands() as $command) {
            $this->add($command);
        }
    }

    public function setDispatcher(EventDispatcherInterface $dispatcher)
    {
        $this->dispatcher = $dispatcher;
    }

    /**
     * Runs the current application.
     *
     * @param InputInterface  $input  An Input instance
     * @param OutputInterface $output An Output instance
     *
     * @return integer 0 if everything went fine, or an error code
     *
     * @throws \Exception When doRun returns Exception
     *
     * @api
     */
    public function run(InputInterface $input = null, OutputInterface $output = null)
    {
        if (null === $input) {
            $input = new ArgvInput();
        }

        if (null === $output) {
            $output = new ConsoleOutput();
        }

        $this->configureIO($input, $output);

        try {
            $exitCode = $this->doRun($input, $output);
        } catch (\Exception $e) {
            if (!$this->catchExceptions) {
                throw $e;
            }

            if ($output instanceof ConsoleOutputInterface) {
                $this->renderException($e, $output->getErrorOutput());
            } else {
                $this->renderException($e, $output);
            }

            $exitCode = $e->getCode();
            if (is_numeric($exitCode)) {
                $exitCode = (int) $exitCode;
                if (0 === $exitCode) {
                    $exitCode = 1;
                }
            } else {
                $exitCode = 1;
            }
        }

        if ($this->autoExit) {
            if ($exitCode > 255) {
                $exitCode = 255;
            }
            // @codeCoverageIgnoreStart
            exit($exitCode);
            // @codeCoverageIgnoreEnd
        }

        return $exitCode;
    }

    /**
     * Runs the current application.
     *
     * @param InputInterface  $input  An Input instance
     * @param OutputInterface $output An Output instance
     *
     * @return integer 0 if everything went fine, or an error code
     */
    public function doRun(InputInterface $input, OutputInterface $output)
    {
        if (true === $input->hasParameterOption(array('--version', '-V'))) {
            $output->writeln($this->getLongVersion());

            return 0;
        }

        $name = $this->getCommandName($input);
        if (true === $input->hasParameterOption(array('--help', '-h'))) {
            if (!$name) {
                $name = 'help';
                $input = new ArrayInput(array('command' => 'help'));
            } else {
                $this->wantHelps = true;
            }
        }

        if (!$name) {
            $name = 'list';
            $input = new ArrayInput(array('command' => 'list'));
        }

        // the command name MUST be the first element of the input
        $command = $this->find($name);

        $this->runningCommand = $command;
        $exitCode = $this->doRunCommand($command, $input, $output);
        $this->runningCommand = null;

        return $exitCode;
    }

    /**
     * Set a helper set to be used with the command.
     *
     * @param HelperSet $helperSet The helper set
     *
     * @api
     */
    public function setHelperSet(HelperSet $helperSet)
    {
        $this->helperSet = $helperSet;
    }

    /**
     * Get the helper set associated with the command.
     *
     * @return HelperSet The HelperSet instance associated with this command
     *
     * @api
     */
    public function getHelperSet()
    {
        return $this->helperSet;
    }

    /**
     * Set an input definition set to be used with this application
     *
     * @param InputDefinition $definition The input definition
     *
     * @api
     */
    public function setDefinition(InputDefinition $definition)
    {
        $this->definition = $definition;
    }

    /**
     * Gets the InputDefinition related to this Application.
     *
     * @return InputDefinition The InputDefinition instance
     */
    public function getDefinition()
    {
        return $this->definition;
    }

    /**
     * Gets the help message.
     *
     * @return string A help message.
     */
    public function getHelp()
    {
        $messages = array(
            $this->getLongVersion(),
            '',
            '<comment>Usage:</comment>',
            '  [options] command [arguments]',
            '',
            '<comment>Options:</comment>',
        );

        foreach ($this->getDefinition()->getOptions() as $option) {
            $messages[] = sprintf('  %-29s %s %s',
                '<info>--'.$option->getName().'</info>',
                $option->getShortcut() ? '<info>-'.$option->getShortcut().'</info>' : '  ',
                $option->getDescription()
            );
        }

        return implode(PHP_EOL, $messages);
    }

    /**
     * Sets whether to catch exceptions or not during commands execution.
     *
     * @param Boolean $boolean Whether to catch exceptions or not during commands execution
     *
     * @api
     */
    public function setCatchExceptions($boolean)
    {
        $this->catchExceptions = (Boolean) $boolean;
    }

    /**
     * Sets whether to automatically exit after a command execution or not.
     *
     * @param Boolean $boolean Whether to automatically exit after a command execution or not
     *
     * @api
     */
    public function setAutoExit($boolean)
    {
        $this->autoExit = (Boolean) $boolean;
    }

    /**
     * Gets the name of the application.
     *
     * @return string The application name
     *
     * @api
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Sets the application name.
     *
     * @param string $name The application name
     *
     * @api
     */
    public function setName($name)
    {
        $this->name = $name;
    }

    /**
     * Gets the application version.
     *
     * @return string The application version
     *
     * @api
     */
    public function getVersion()
    {
        return $this->version;
    }

    /**
     * Sets the application version.
     *
     * @param string $version The application version
     *
     * @api
     */
    public function setVersion($version)
    {
        $this->version = $version;
    }

    /**
     * Returns the long version of the application.
     *
     * @return string The long application version
     *
     * @api
     */
    public function getLongVersion()
    {
        if ('UNKNOWN' !== $this->getName() && 'UNKNOWN' !== $this->getVersion()) {
            return sprintf('<info>%s</info> version <comment>%s</comment>', $this->getName(), $this->getVersion());
        }

        return '<info>Console Tool</info>';
    }

    /**
     * Registers a new command.
     *
     * @param string $name The command name
     *
     * @return Command The newly created command
     *
     * @api
     */
    public function register($name)
    {
        return $this->add(new Command($name));
    }

    /**
     * Adds an array of command objects.
     *
     * @param Command[] $commands An array of commands
     *
     * @api
     */
    public function addCommands(array $commands)
    {
        foreach ($commands as $command) {
            $this->add($command);
        }
    }

    /**
     * Adds a command object.
     *
     * If a command with the same name already exists, it will be overridden.
     *
     * @param Command $command A Command object
     *
     * @return Command The registered command
     *
     * @api
     */
    public function add(Command $command)
    {
        $command->setApplication($this);

        if (!$command->isEnabled()) {
            $command->setApplication(null);

            return;
        }

        if (null === $command->getDefinition()) {
            throw new \LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', get_class($command)));
        }

        $this->commands[$command->getName()] = $command;

        foreach ($command->getAliases() as $alias) {
            $this->commands[$alias] = $command;
        }

        return $command;
    }

    /**
     * Returns a registered command by name or alias.
     *
     * @param string $name The command name or alias
     *
     * @return Command A Command object
     *
     * @throws \InvalidArgumentException When command name given does not exist
     *
     * @api
     */
    public function get($name)
    {
        if (!isset($this->commands[$name])) {
            throw new \InvalidArgumentException(sprintf('The command "%s" does not exist.', $name));
        }

        $command = $this->commands[$name];

        if ($this->wantHelps) {
            $this->wantHelps = false;

            $helpCommand = $this->get('help');
            $helpCommand->setCommand($command);

            return $helpCommand;
        }

        return $command;
    }

    /**
     * Returns true if the command exists, false otherwise.
     *
     * @param string $name The command name or alias
     *
     * @return Boolean true if the command exists, false otherwise
     *
     * @api
     */
    public function has($name)
    {
        return isset($this->commands[$name]);
    }

    /**
     * Returns an array of all unique namespaces used by currently registered commands.
     *
     * It does not returns the global namespace which always exists.
     *
     * @return array An array of namespaces
     */
    public function getNamespaces()
    {
        $namespaces = array();
        foreach ($this->commands as $command) {
            $namespaces[] = $this->extractNamespace($command->getName());

            foreach ($command->getAliases() as $alias) {
                $namespaces[] = $this->extractNamespace($alias);
            }
        }

        return array_values(array_unique(array_filter($namespaces)));
    }

    /**
     * Finds a registered namespace by a name or an abbreviation.
     *
     * @param string $namespace A namespace or abbreviation to search for
     *
     * @return string A registered namespace
     *
     * @throws \InvalidArgumentException When namespace is incorrect or ambiguous
     */
    public function findNamespace($namespace)
    {
        $allNamespaces = $this->getNamespaces();
        $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $namespace);
        $namespaces = preg_grep('{^'.$expr.'}', $allNamespaces);

        if (empty($namespaces)) {
            $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace);

            if ($alternatives = $this->findAlternatives($namespace, $allNamespaces, array())) {
                if (1 == count($alternatives)) {
                    $message .= "\n\nDid you mean this?\n    ";
                } else {
                    $message .= "\n\nDid you mean one of these?\n    ";
                }

                $message .= implode("\n    ", $alternatives);
            }

            throw new \InvalidArgumentException($message);
        }

        $exact = in_array($namespace, $namespaces, true);
        if (count($namespaces) > 1 && !$exact) {
            throw new \InvalidArgumentException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))));
        }

        return $exact ? $namespace : reset($namespaces);
    }

    /**
     * Finds a command by name or alias.
     *
     * Contrary to get, this command tries to find the best
     * match if you give it an abbreviation of a name or alias.
     *
     * @param string $name A command name or a command alias
     *
     * @return Command A Command instance
     *
     * @throws \InvalidArgumentException When command name is incorrect or ambiguous
     *
     * @api
     */
    public function find($name)
    {
        $allCommands = array_keys($this->commands);
        $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name);
        $commands = preg_grep('{^'.$expr.'}', $allCommands);

        if (empty($commands) || count(preg_grep('{^'.$expr.'$}', $commands)) < 1) {
            if (false !== $pos = strrpos($name, ':')) {
                // check if a namespace exists and contains commands
                $this->findNamespace(substr($name, 0, $pos));
            }

            $message = sprintf('Command "%s" is not defined.', $name);

            if ($alternatives = $this->findAlternatives($name, $allCommands, array())) {
                if (1 == count($alternatives)) {
                    $message .= "\n\nDid you mean this?\n    ";
                } else {
                    $message .= "\n\nDid you mean one of these?\n    ";
                }
                $message .= implode("\n    ", $alternatives);
            }

            throw new \InvalidArgumentException($message);
        }

        // filter out aliases for commands which are already on the list
        if (count($commands) > 1) {
            $commandList = $this->commands;
            $commands = array_filter($commands, function ($nameOrAlias) use ($commandList, $commands) {
                $commandName = $commandList[$nameOrAlias]->getName();

                return $commandName === $nameOrAlias || !in_array($commandName, $commands);
            });
        }

        $exact = in_array($name, $commands, true);
        if (count($commands) > 1 && !$exact) {
            $suggestions = $this->getAbbreviationSuggestions(array_values($commands));

            throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $name, $suggestions));
        }

        return $this->get($exact ? $name : reset($commands));
    }

    /**
     * Gets the commands (registered in the given namespace if provided).
     *
     * The array keys are the full names and the values the command instances.
     *
     * @param string $namespace A namespace name
     *
     * @return Command[] An array of Command instances
     *
     * @api
     */
    public function all($namespace = null)
    {
        if (null === $namespace) {
            return $this->commands;
        }

        $commands = array();
        foreach ($this->commands as $name => $command) {
            if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) {
                $commands[$name] = $command;
            }
        }

        return $commands;
    }

    /**
     * Returns an array of possible abbreviations given a set of names.
     *
     * @param array $names An array of names
     *
     * @return array An array of abbreviations
     */
    public static function getAbbreviations($names)
    {
        $abbrevs = array();
        foreach ($names as $name) {
            for ($len = strlen($name); $len > 0; --$len) {
                $abbrev = substr($name, 0, $len);
                $abbrevs[$abbrev][] = $name;
            }
        }

        return $abbrevs;
    }

    /**
     * Returns a text representation of the Application.
     *
     * @param string  $namespace An optional namespace name
     * @param boolean $raw       Whether to return raw command list
     *
     * @return string A string representing the Application
     *
     * @deprecated Deprecated since version 2.3, to be removed in 3.0.
     */
    public function asText($namespace = null, $raw = false)
    {
        $descriptor = new TextDescriptor();
        $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, !$raw);
        $descriptor->describe($output, $this, array('namespace' => $namespace, 'raw_output' => true));

        return $output->fetch();
    }

    /**
     * Returns an XML representation of the Application.
     *
     * @param string  $namespace An optional namespace name
     * @param Boolean $asDom     Whether to return a DOM or an XML string
     *
     * @return string|\DOMDocument An XML string representing the Application
     *
     * @deprecated Deprecated since version 2.3, to be removed in 3.0.
     */
    public function asXml($namespace = null, $asDom = false)
    {
        $descriptor = new XmlDescriptor();

        if ($asDom) {
            return $descriptor->getApplicationDocument($this, $namespace);
        }

        $output = new BufferedOutput();
        $descriptor->describe($output, $this, array('namespace' => $namespace));

        return $output->fetch();
    }

    /**
     * Renders a caught exception.
     *
     * @param \Exception       $e      An exception instance
     * @param OutputInterface $output An OutputInterface instance
     */
    public function renderException($e, $output)
    {
        $strlen = function ($string) {
            if (!function_exists('mb_strlen')) {
                return strlen($string);
            }

            if (false === $encoding = mb_detect_encoding($string)) {
                return strlen($string);
            }

            return mb_strlen($string, $encoding);
        };

        do {
            $title = sprintf('  [%s]  ', get_class($e));
            $len = $strlen($title);
            // HHVM only accepts 32 bits integer in str_split, even when PHP_INT_MAX is a 64 bit integer: https://github.com/facebook/hhvm/issues/1327
            $width = $this->getTerminalWidth() ? $this->getTerminalWidth() - 1 : (defined('HHVM_VERSION') ? 1 << 31 : PHP_INT_MAX);
            $formatter = $output->getFormatter();
            $lines = array();
            foreach (preg_split('/\r?\n/', $e->getMessage()) as $line) {
                foreach (str_split($line, $width - 4) as $line) {
                    // pre-format lines to get the right string length
                    $lineLength = $strlen(preg_replace('/\[[^m]*m/', '', $formatter->format($line))) + 4;
                    $lines[] = array($line, $lineLength);

                    $len = max($lineLength, $len);
                }
            }

            $messages = array('', '');
            $messages[] = $emptyLine = $formatter->format(sprintf('<error>%s</error>', str_repeat(' ', $len)));
            $messages[] = $formatter->format(sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - $strlen($title)))));
            foreach ($lines as $line) {
                $messages[] = $formatter->format(sprintf('<error>  %s  %s</error>', $line[0], str_repeat(' ', $len - $line[1])));
            }
            $messages[] = $emptyLine;
            $messages[] = '';
            $messages[] = '';

            $output->writeln($messages, OutputInterface::OUTPUT_RAW);

            if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
                $output->writeln('<comment>Exception trace:</comment>');

                // exception related properties
                $trace = $e->getTrace();
                array_unshift($trace, array(
                    'function' => '',
                    'file'     => $e->getFile() != null ? $e->getFile() : 'n/a',
                    'line'     => $e->getLine() != null ? $e->getLine() : 'n/a',
                    'args'     => array(),
                ));

                for ($i = 0, $count = count($trace); $i < $count; $i++) {
                    $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : '';
                    $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : '';
                    $function = $trace[$i]['function'];
                    $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a';
                    $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a';

                    $output->writeln(sprintf(' %s%s%s() at <info>%s:%s</info>', $class, $type, $function, $file, $line));
                }

                $output->writeln("");
                $output->writeln("");
            }
        } while ($e = $e->getPrevious());

        if (null !== $this->runningCommand) {
            $output->writeln(sprintf('<info>%s</info>', sprintf($this->runningCommand->getSynopsis(), $this->getName())));
            $output->writeln("");
            $output->writeln("");
        }
    }

    /**
     * Tries to figure out the terminal width in which this application runs
     *
     * @return int|null
     */
    protected function getTerminalWidth()
    {
        $dimensions = $this->getTerminalDimensions();

        return $dimensions[0];
    }

    /**
     * Tries to figure out the terminal height in which this application runs
     *
     * @return int|null
     */
    protected function getTerminalHeight()
    {
        $dimensions = $this->getTerminalDimensions();

        return $dimensions[1];
    }

    /**
     * Tries to figure out the terminal dimensions based on the current environment
     *
     * @return array Array containing width and height
     */
    public function getTerminalDimensions()
    {
        if ($this->terminalDimensions) {
            return $this->terminalDimensions;
        }

        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            // extract [w, H] from "wxh (WxH)"
            if (preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', trim(getenv('ANSICON')), $matches)) {
                return array((int) $matches[1], (int) $matches[2]);
            }
            // extract [w, h] from "wxh"
            if (preg_match('/^(\d+)x(\d+)$/', $this->getConsoleMode(), $matches)) {
                return array((int) $matches[1], (int) $matches[2]);
            }
        }

        if ($sttyString = $this->getSttyColumns()) {
            // extract [w, h] from "rows h; columns w;"
            if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) {
                return array((int) $matches[2], (int) $matches[1]);
            }
            // extract [w, h] from "; h rows; w columns"
            if (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) {
                return array((int) $matches[2], (int) $matches[1]);
            }
        }

        return array(null, null);
    }

    /**
     * Sets terminal dimensions.
     *
     * Can be useful to force terminal dimensions for functional tests.
     *
     * @param integer $width  The width
     * @param integer $height The height
     *
     * @return Application The current application
     */
    public function setTerminalDimensions($width, $height)
    {
        $this->terminalDimensions = array($width, $height);

        return $this;
    }

    /**
     * Configures the input and output instances based on the user arguments and options.
     *
     * @param InputInterface  $input  An InputInterface instance
     * @param OutputInterface $output An OutputInterface instance
     */
    protected function configureIO(InputInterface $input, OutputInterface $output)
    {
        if (true === $input->hasParameterOption(array('--ansi'))) {
            $output->setDecorated(true);
        } elseif (true === $input->hasParameterOption(array('--no-ansi'))) {
            $output->setDecorated(false);
        }

        if (true === $input->hasParameterOption(array('--no-interaction', '-n'))) {
            $input->setInteractive(false);
        } elseif (function_exists('posix_isatty') && $this->getHelperSet()->has('dialog')) {
            $inputStream = $this->getHelperSet()->get('dialog')->getInputStream();
            if (!@posix_isatty($inputStream)) {
                $input->setInteractive(false);
            }
        }

        if (true === $input->hasParameterOption(array('--quiet', '-q'))) {
            $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
        } else {
            if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || $input->getParameterOption('--verbose') === 3) {
                $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
            } elseif ($input->hasParameterOption('-vv') || $input->hasParameterOption('--verbose=2') || $input->getParameterOption('--verbose') === 2) {
                $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE);
            } elseif ($input->hasParameterOption('-v') || $input->hasParameterOption('--verbose=1') || $input->hasParameterOption('--verbose') || $input->getParameterOption('--verbose')) {
                $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
            }
        }
    }

    /**
     * Runs the current command.
     *
     * If an event dispatcher has been attached to the application,
     * events are also dispatched during the life-cycle of the command.
     *
     * @param Command         $command A Command instance
     * @param InputInterface  $input   An Input instance
     * @param OutputInterface $output  An Output instance
     *
     * @return integer 0 if everything went fine, or an error code
     */
    protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output)
    {
        foreach ($command->getHelperSet() as $helper) {
            if ($helper instanceof InputAwareInterface) {
                $helper->setInput($input);
            }
        }

        if (null === $this->dispatcher) {
            return $command->run($input, $output);
        }

        $event = new ConsoleCommandEvent($command, $input, $output);
        $this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);

        try {
            $exitCode = $command->run($input, $output);
        } catch (\Exception $e) {
            $event = new ConsoleTerminateEvent($command, $input, $output, $e->getCode());
            $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);

            $event = new ConsoleExceptionEvent($command, $input, $output, $e, $event->getExitCode());
            $this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event);

            throw $event->getException();
        }

        $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode);
        $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);

        return $event->getExitCode();
    }

    /**
     * Gets the name of the command based on input.
     *
     * @param InputInterface $input The input interface
     *
     * @return string The command name
     */
    protected function getCommandName(InputInterface $input)
    {
        return $input->getFirstArgument();
    }

    /**
     * Gets the default input definition.
     *
     * @return InputDefinition An InputDefinition instance
     */
    protected function getDefaultInputDefinition()
    {
        return new InputDefinition(array(
            new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'),

            new InputOption('--help',           '-h', InputOption::VALUE_NONE, 'Display this help message.'),
            new InputOption('--quiet',          '-q', InputOption::VALUE_NONE, 'Do not output any message.'),
            new InputOption('--verbose',        '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'),
            new InputOption('--version',        '-V', InputOption::VALUE_NONE, 'Display this application version.'),
            new InputOption('--ansi',           '',   InputOption::VALUE_NONE, 'Force ANSI output.'),
            new InputOption('--no-ansi',        '',   InputOption::VALUE_NONE, 'Disable ANSI output.'),
            new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question.'),
        ));
    }

    /**
     * Gets the default commands that should always be available.
     *
     * @return Command[] An array of default Command instances
     */
    protected function getDefaultCommands()
    {
        return array(new HelpCommand(), new ListCommand());
    }

    /**
     * Gets the default helper set with the helpers that should always be available.
     *
     * @return HelperSet A HelperSet instance
     */
    protected function getDefaultHelperSet()
    {
        return new HelperSet(array(
            new FormatterHelper(),
            new DialogHelper(),
            new ProgressHelper(),
            new TableHelper(),
        ));
    }

    /**
     * Runs and parses stty -a if it's available, suppressing any error output
     *
     * @return string
     */
    private function getSttyColumns()
    {
        if (!function_exists('proc_open')) {
            return;
        }

        $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
        $process = proc_open('stty -a | grep columns', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
        if (is_resource($process)) {
            $info = stream_get_contents($pipes[1]);
            fclose($pipes[1]);
            fclose($pipes[2]);
            proc_close($process);

            return $info;
        }
    }

    /**
     * Runs and parses mode CON if it's available, suppressing any error output
     *
     * @return string <width>x<height> or null if it could not be parsed
     */
    private function getConsoleMode()
    {
        if (!function_exists('proc_open')) {
            return;
        }

        $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
        $process = proc_open('mode CON', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
        if (is_resource($process)) {
            $info = stream_get_contents($pipes[1]);
            fclose($pipes[1]);
            fclose($pipes[2]);
            proc_close($process);

            if (preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) {
                return $matches[2].'x'.$matches[1];
            }
        }
    }

    /**
     * Returns abbreviated suggestions in string format.
     *
     * @param array $abbrevs Abbreviated suggestions to convert
     *
     * @return string A formatted string of abbreviated suggestions
     */
    private function getAbbreviationSuggestions($abbrevs)
    {
        return sprintf('%s, %s%s', $abbrevs[0], $abbrevs[1], count($abbrevs) > 2 ? sprintf(' and %d more', count($abbrevs) - 2) : '');
    }

    /**
     * Returns the namespace part of the command name.
     *
     * This method is not part of public API and should not be used directly.
     *
     * @param string $name  The full name of the command
     * @param string $limit The maximum number of parts of the namespace
     *
     * @return string The namespace of the command
     */
    public function extractNamespace($name, $limit = null)
    {
        $parts = explode(':', $name);
        array_pop($parts);

        return implode(':', null === $limit ? $parts : array_slice($parts, 0, $limit));
    }

    /**
     * Finds alternative of $name among $collection,
     * if nothing is found in $collection, try in $abbrevs
     *
     * @param string               $name       The string
     * @param array|\Traversable   $collection The collection
     *
     * @return array A sorted array of similar string
     */
    private function findAlternatives($name, $collection)
    {
        $threshold = 1e3;
        $alternatives = array();

        $collectionParts = array();
        foreach ($collection as $item) {
            $collectionParts[$item] = explode(':', $item);
        }

        foreach (explode(':', $name) as $i => $subname) {
            foreach ($collectionParts as $collectionName => $parts) {
                $exists = isset($alternatives[$collectionName]);
                if (!isset($parts[$i]) && $exists) {
                    $alternatives[$collectionName] += $threshold;
                    continue;
                } elseif (!isset($parts[$i])) {
                    continue;
                }

                $lev = levenshtein($subname, $parts[$i]);
                if ($lev <= strlen($subname) / 3 || false !== strpos($parts[$i], $subname)) {
                    $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev;
                } elseif ($exists) {
                    $alternatives[$collectionName] += $threshold;
                }
            }
        }

        foreach ($collection as $item) {
            $lev = levenshtein($name, $item);
            if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) {
                $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev;
            }
        }

        $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2*$threshold; });
        asort($alternatives);

        return array_keys($alternatives);
    }
}
PK��Z���	�	.Symfony/Component/Console/Helper/HelperSet.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Command\Command;

/**
 * HelperSet represents a set of helpers to be used with a command.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class HelperSet implements \IteratorAggregate
{
    private $helpers = array();
    private $command;

    /**
     * Constructor.
     *
     * @param Helper[] $helpers An array of helper.
     */
    public function __construct(array $helpers = array())
    {
        foreach ($helpers as $alias => $helper) {
            $this->set($helper, is_int($alias) ? null : $alias);
        }
    }

    /**
     * Sets a helper.
     *
     * @param HelperInterface $helper The helper instance
     * @param string          $alias  An alias
     */
    public function set(HelperInterface $helper, $alias = null)
    {
        $this->helpers[$helper->getName()] = $helper;
        if (null !== $alias) {
            $this->helpers[$alias] = $helper;
        }

        $helper->setHelperSet($this);
    }

    /**
     * Returns true if the helper if defined.
     *
     * @param string $name The helper name
     *
     * @return Boolean true if the helper is defined, false otherwise
     */
    public function has($name)
    {
        return isset($this->helpers[$name]);
    }

    /**
     * Gets a helper value.
     *
     * @param string $name The helper name
     *
     * @return HelperInterface The helper instance
     *
     * @throws \InvalidArgumentException if the helper is not defined
     */
    public function get($name)
    {
        if (!$this->has($name)) {
            throw new \InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name));
        }

        return $this->helpers[$name];
    }

    /**
     * Sets the command associated with this helper set.
     *
     * @param Command $command A Command instance
     */
    public function setCommand(Command $command = null)
    {
        $this->command = $command;
    }

    /**
     * Gets the command associated with this helper set.
     *
     * @return Command A Command instance
     */
    public function getCommand()
    {
        return $this->command;
    }

    public function getIterator()
    {
        return new \ArrayIterator($this->helpers);
    }
}
PK��Z�z����4Symfony/Component/Console/Helper/HelperInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

/**
 * HelperInterface is the interface all helpers must implement.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface HelperInterface
{
    /**
     * Sets the helper set associated with this helper.
     *
     * @param HelperSet $helperSet A HelperSet instance
     *
     * @api
     */
    public function setHelperSet(HelperSet $helperSet = null);

    /**
     * Gets the helper set associated with this helper.
     *
     * @return HelperSet A HelperSet instance
     *
     * @api
     */
    public function getHelperSet();

    /**
     * Returns the canonical name of this helper.
     *
     * @return string The canonical name
     *
     * @api
     */
    public function getName();
}
PK��ZZ\���+Symfony/Component/Console/Helper/Helper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

/**
 * Helper is the base class for all helper classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class Helper implements HelperInterface
{
    protected $helperSet = null;

    /**
     * Sets the helper set associated with this helper.
     *
     * @param HelperSet $helperSet A HelperSet instance
     */
    public function setHelperSet(HelperSet $helperSet = null)
    {
        $this->helperSet = $helperSet;
    }

    /**
     * Gets the helper set associated with this helper.
     *
     * @return HelperSet A HelperSet instance
     */
    public function getHelperSet()
    {
        return $this->helperSet;
    }

    /**
     * Returns the length of a string, using mb_strlen if it is available.
     *
     * @param string $string The string to check its length
     *
     * @return integer The length of the string
     */
    protected function strlen($string)
    {
        if (!function_exists('mb_strlen')) {
            return strlen($string);
        }

        if (false === $encoding = mb_detect_encoding($string)) {
            return strlen($string);
        }

        return mb_strlen($string, $encoding);
    }
}
PK��Zg�se��4Symfony/Component/Console/Helper/FormatterHelper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Formatter\OutputFormatter;

/**
 * The Formatter class provides helpers to format messages.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FormatterHelper extends Helper
{
    /**
     * Formats a message within a section.
     *
     * @param string $section The section name
     * @param string $message The message
     * @param string $style   The style to apply to the section
     *
     * @return string The format section
     */
    public function formatSection($section, $message, $style = 'info')
    {
        return sprintf('<%s>[%s]</%s> %s', $style, $section, $style, $message);
    }

    /**
     * Formats a message as a block of text.
     *
     * @param string|array $messages The message to write in the block
     * @param string       $style    The style to apply to the whole block
     * @param Boolean      $large    Whether to return a large block
     *
     * @return string The formatter message
     */
    public function formatBlock($messages, $style, $large = false)
    {
        $messages = (array) $messages;

        $len = 0;
        $lines = array();
        foreach ($messages as $message) {
            $message = OutputFormatter::escape($message);
            $lines[] = sprintf($large ? '  %s  ' : ' %s ', $message);
            $len = max($this->strlen($message) + ($large ? 4 : 2), $len);
        }

        $messages = $large ? array(str_repeat(' ', $len)) : array();
        foreach ($lines as $line) {
            $messages[] = $line.str_repeat(' ', $len - $this->strlen($line));
        }
        if ($large) {
            $messages[] = str_repeat(' ', $len);
        }

        foreach ($messages as &$message) {
            $message = sprintf('<%s>%s</%s>', $style, $message, $style);
        }

        return implode("\n", $messages);
    }

    /**
     * {@inheritDoc}
     */
    public function getName()
    {
        return 'formatter';
    }
}
PK��Z��220Symfony/Component/Console/Helper/TableHelper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Output\OutputInterface;
use InvalidArgumentException;

/**
 * Provides helpers to display table output.
 *
 * @author Саша Стаменковић <umpirsky@gmail.com>
 */
class TableHelper extends Helper
{
    const LAYOUT_DEFAULT = 0;
    const LAYOUT_BORDERLESS = 1;
    const LAYOUT_COMPACT = 2;

    /**
     * Table headers.
     *
     * @var array
     */
    private $headers = array();

    /**
     * Table rows.
     *
     * @var array
     */
    private $rows = array();

    // Rendering options
    private $paddingChar;
    private $horizontalBorderChar;
    private $verticalBorderChar;
    private $crossingChar;
    private $cellHeaderFormat;
    private $cellRowFormat;
    private $cellRowContentFormat;
    private $borderFormat;
    private $padType;

    /**
     * Column widths cache.
     *
     * @var array
     */
    private $columnWidths = array();

    /**
     * Number of columns cache.
     *
     * @var array
     */
    private $numberOfColumns;

    /**
     * @var OutputInterface
     */
    private $output;

    public function __construct()
    {
        $this->setLayout(self::LAYOUT_DEFAULT);
    }

    /**
     * Sets table layout type.
     *
     * @param int $layout self::LAYOUT_*
     *
     * @return TableHelper
     */
    public function setLayout($layout)
    {
        switch ($layout) {
            case self::LAYOUT_BORDERLESS:
                $this
                    ->setPaddingChar(' ')
                    ->setHorizontalBorderChar('=')
                    ->setVerticalBorderChar(' ')
                    ->setCrossingChar(' ')
                    ->setCellHeaderFormat('<info>%s</info>')
                    ->setCellRowFormat('%s')
                    ->setCellRowContentFormat(' %s ')
                    ->setBorderFormat('%s')
                    ->setPadType(STR_PAD_RIGHT)
                ;
                break;

            case self::LAYOUT_COMPACT:
                $this
                    ->setPaddingChar(' ')
                    ->setHorizontalBorderChar('')
                    ->setVerticalBorderChar(' ')
                    ->setCrossingChar('')
                    ->setCellHeaderFormat('<info>%s</info>')
                    ->setCellRowFormat('%s')
                    ->setCellRowContentFormat('%s')
                    ->setBorderFormat('%s')
                    ->setPadType(STR_PAD_RIGHT)
                ;
                break;

            case self::LAYOUT_DEFAULT:
                $this
                    ->setPaddingChar(' ')
                    ->setHorizontalBorderChar('-')
                    ->setVerticalBorderChar('|')
                    ->setCrossingChar('+')
                    ->setCellHeaderFormat('<info>%s</info>')
                    ->setCellRowFormat('%s')
                    ->setCellRowContentFormat(' %s ')
                    ->setBorderFormat('%s')
                    ->setPadType(STR_PAD_RIGHT)
                ;
                break;

            default:
                throw new InvalidArgumentException(sprintf('Invalid table layout "%s".', $layout));
                break;
        };

        return $this;
    }

    public function setHeaders(array $headers)
    {
        $this->headers = array_values($headers);

        return $this;
    }

    public function setRows(array $rows)
    {
        $this->rows = array();

        return $this->addRows($rows);
    }

    public function addRows(array $rows)
    {
        foreach ($rows as $row) {
            $this->addRow($row);
        }

        return $this;
    }

    public function addRow(array $row)
    {
        $this->rows[] = array_values($row);

        $keys = array_keys($this->rows);
        $rowKey = array_pop($keys);

        foreach ($row as $key => $cellValue) {
            if (!strstr($cellValue, "\n")) {
                continue;
            }

            $lines = explode("\n", $cellValue);
            $this->rows[$rowKey][$key] = $lines[0];
            unset($lines[0]);

            foreach ($lines as $lineKey => $line) {
                $nextRowKey = $rowKey + $lineKey + 1;

                if (isset($this->rows[$nextRowKey])) {
                    $this->rows[$nextRowKey][$key] = $line;
                } else {
                    $this->rows[$nextRowKey] = array($key => $line);
                }
            }
        }

        return $this;
    }

    public function setRow($column, array $row)
    {
        $this->rows[$column] = $row;

        return $this;
    }

    /**
     * Sets padding character, used for cell padding.
     *
     * @param string $paddingChar
     *
     * @return TableHelper
     */
    public function setPaddingChar($paddingChar)
    {
        if (!$paddingChar) {
            throw new \LogicException('The padding char must not be empty');
        }

        $this->paddingChar = $paddingChar;

        return $this;
    }

    /**
     * Sets horizontal border character.
     *
     * @param string $horizontalBorderChar
     *
     * @return TableHelper
     */
    public function setHorizontalBorderChar($horizontalBorderChar)
    {
        $this->horizontalBorderChar = $horizontalBorderChar;

        return $this;
    }

    /**
     * Sets vertical border character.
     *
     * @param string $verticalBorderChar
     *
     * @return TableHelper
     */
    public function setVerticalBorderChar($verticalBorderChar)
    {
        $this->verticalBorderChar = $verticalBorderChar;

        return $this;
    }

    /**
     * Sets crossing character.
     *
     * @param string $crossingChar
     *
     * @return TableHelper
     */
    public function setCrossingChar($crossingChar)
    {
        $this->crossingChar = $crossingChar;

        return $this;
    }

    /**
     * Sets header cell format.
     *
     * @param string $cellHeaderFormat
     *
     * @return TableHelper
     */
    public function setCellHeaderFormat($cellHeaderFormat)
    {
        $this->cellHeaderFormat = $cellHeaderFormat;

        return $this;
    }

    /**
     * Sets row cell format.
     *
     * @param string $cellRowFormat
     *
     * @return TableHelper
     */
    public function setCellRowFormat($cellRowFormat)
    {
        $this->cellRowFormat = $cellRowFormat;

        return $this;
    }

    /**
     * Sets row cell content format.
     *
     * @param string $cellRowContentFormat
     *
     * @return TableHelper
     */
    public function setCellRowContentFormat($cellRowContentFormat)
    {
        $this->cellRowContentFormat = $cellRowContentFormat;

        return $this;
    }

    /**
     * Sets table border format.
     *
     * @param string $borderFormat
     *
     * @return TableHelper
     */
    public function setBorderFormat($borderFormat)
    {
        $this->borderFormat = $borderFormat;

        return $this;
    }

    /**
     * Sets cell padding type.
     *
     * @param integer $padType STR_PAD_*
     *
     * @return TableHelper
     */
    public function setPadType($padType)
    {
        $this->padType = $padType;

        return $this;
    }

    /**
     * Renders table to output.
     *
     * Example:
     * +---------------+-----------------------+------------------+
     * | ISBN          | Title                 | Author           |
     * +---------------+-----------------------+------------------+
     * | 99921-58-10-7 | Divine Comedy         | Dante Alighieri  |
     * | 9971-5-0210-0 | A Tale of Two Cities  | Charles Dickens  |
     * | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien |
     * +---------------+-----------------------+------------------+
     *
     * @param OutputInterface $output
     */
    public function render(OutputInterface $output)
    {
        $this->output = $output;

        $this->renderRowSeparator();
        $this->renderRow($this->headers, $this->cellHeaderFormat);
        if (!empty($this->headers)) {
            $this->renderRowSeparator();
        }
        foreach ($this->rows as $row) {
            $this->renderRow($row, $this->cellRowFormat);
        }
        if (!empty($this->rows)) {
            $this->renderRowSeparator();
        }

        $this->cleanup();
    }

    /**
     * Renders horizontal header separator.
     *
     * Example: +-----+-----------+-------+
     */
    private function renderRowSeparator()
    {
        if (0 === $count = $this->getNumberOfColumns()) {
            return;
        }

        if (!$this->horizontalBorderChar && !$this->crossingChar) {
            return;
        }

        $markup = $this->crossingChar;
        for ($column = 0; $column < $count; $column++) {
            $markup .= str_repeat($this->horizontalBorderChar, $this->getColumnWidth($column)).$this->crossingChar;
        }

        $this->output->writeln(sprintf($this->borderFormat, $markup));
    }

    /**
     * Renders vertical column separator.
     */
    private function renderColumnSeparator()
    {
        $this->output->write(sprintf($this->borderFormat, $this->verticalBorderChar));
    }

    /**
     * Renders table row.
     *
     * Example: | 9971-5-0210-0 | A Tale of Two Cities  | Charles Dickens  |
     *
     * @param array  $row
     * @param string $cellFormat
     */
    private function renderRow(array $row, $cellFormat)
    {
        if (empty($row)) {
            return;
        }

        $this->renderColumnSeparator();
        for ($column = 0, $count = $this->getNumberOfColumns(); $column < $count; $column++) {
            $this->renderCell($row, $column, $cellFormat);
            $this->renderColumnSeparator();
        }
        $this->output->writeln('');
    }

    /**
     * Renders table cell with padding.
     *
     * @param array   $row
     * @param integer $column
     * @param string  $cellFormat
     */
    private function renderCell(array $row, $column, $cellFormat)
    {
        $cell = isset($row[$column]) ? $row[$column] : '';
        $width = $this->getColumnWidth($column);

        // str_pad won't work properly with multi-byte strings, we need to fix the padding
        if (function_exists('mb_strlen') && false !== $encoding = mb_detect_encoding($cell)) {
            $width += strlen($cell) - mb_strlen($cell, $encoding);
        }

        $width += $this->strlen($cell) - $this->computeLengthWithoutDecoration($cell);

        $content = sprintf($this->cellRowContentFormat, $cell);

        $this->output->write(sprintf($cellFormat, str_pad($content, $width, $this->paddingChar, $this->padType)));
    }

    /**
     * Gets number of columns for this table.
     *
     * @return int
     */
    private function getNumberOfColumns()
    {
        if (null !== $this->numberOfColumns) {
            return $this->numberOfColumns;
        }

        $columns = array(0);
        $columns[] = count($this->headers);
        foreach ($this->rows as $row) {
            $columns[] = count($row);
        }

        return $this->numberOfColumns = max($columns);
    }

    /**
     * Gets column width.
     *
     * @param integer $column
     *
     * @return int
     */
    private function getColumnWidth($column)
    {
        if (isset($this->columnWidths[$column])) {
            return $this->columnWidths[$column];
        }

        $lengths = array(0);
        $lengths[] = $this->getCellWidth($this->headers, $column);
        foreach ($this->rows as $row) {
            $lengths[] = $this->getCellWidth($row, $column);
        }

        return $this->columnWidths[$column] = max($lengths) + strlen($this->cellRowContentFormat) - 2;
    }

    /**
     * Gets cell width.
     *
     * @param array   $row
     * @param integer $column
     *
     * @return int
     */
    private function getCellWidth(array $row, $column)
    {
        return isset($row[$column]) ? $this->computeLengthWithoutDecoration($row[$column]) : 0;
    }

    /**
     * Called after rendering to cleanup cache data.
     */
    private function cleanup()
    {
        $this->columnWidths = array();
        $this->numberOfColumns = null;
    }

    private function computeLengthWithoutDecoration($string)
    {
        $formatter = $this->output->getFormatter();
        $isDecorated = $formatter->isDecorated();
        $formatter->setDecorated(false);

        $string = $formatter->format($string);
        $formatter->setDecorated($isDecorated);

        return $this->strlen($string);
    }

    /**
     * {@inheritDoc}
     */
    public function getName()
    {
        return 'table';
    }
}
PK��Z"U�1

5Symfony/Component/Console/Helper/DescriptorHelper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Descriptor\DescriptorInterface;
use Symfony\Component\Console\Descriptor\JsonDescriptor;
use Symfony\Component\Console\Descriptor\MarkdownDescriptor;
use Symfony\Component\Console\Descriptor\TextDescriptor;
use Symfony\Component\Console\Descriptor\XmlDescriptor;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * This class adds helper method to describe objects in various formats.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class DescriptorHelper extends Helper
{
    /**
     * @var DescriptorInterface[]
     */
    private $descriptors = array();

    /**
     * Constructor.
     */
    public function __construct()
    {
        $this
            ->register('txt',  new TextDescriptor())
            ->register('xml',  new XmlDescriptor())
            ->register('json', new JsonDescriptor())
            ->register('md',   new MarkdownDescriptor())
        ;
    }

    /**
     * Describes an object if supported.
     *
     * Available options are:
     * * format: string, the output format name
     * * raw_text: boolean, sets output type as raw
     *
     * @param OutputInterface $output
     * @param object          $object
     * @param array           $options
     *
     * @throws \InvalidArgumentException
     */
    public function describe(OutputInterface $output, $object, array $options = array())
    {
        $options = array_merge(array(
            'raw_text'  => false,
            'format'    => 'txt',
        ), $options);

        if (!isset($this->descriptors[$options['format']])) {
            throw new \InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format']));
        }

        $descriptor = $this->descriptors[$options['format']];
        $descriptor->describe($output, $object, $options);
    }

    /**
     * Registers a descriptor.
     *
     * @param string              $format
     * @param DescriptorInterface $descriptor
     *
     * @return DescriptorHelper
     */
    public function register($format, DescriptorInterface $descriptor)
    {
        $this->descriptors[$format] = $descriptor;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'descriptor';
    }
}
PK��Zs� H��5Symfony/Component/Console/Helper/InputAwareHelper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputAwareInterface;

/**
 * An implementation of InputAwareInterface for Helpers.
 *
 * @author Wouter J <waldio.webdesign@gmail.com>
 */
abstract class InputAwareHelper extends Helper implements InputAwareInterface
{
    protected $input;

    /**
     * {@inheritDoc}
     */
    public function setInput(InputInterface $input)
    {
        $this->input = $input;
    }
}
PK��Z|po.o.3Symfony/Component/Console/Helper/ProgressHelper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Output\OutputInterface;

/**
 * The Progress class provides helpers to display progress output.
 *
 * @author Chris Jones <leeked@gmail.com>
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ProgressHelper extends Helper
{
    const FORMAT_QUIET         = ' %percent%%';
    const FORMAT_NORMAL        = ' %current%/%max% [%bar%] %percent%%';
    const FORMAT_VERBOSE       = ' %current%/%max% [%bar%] %percent%% Elapsed: %elapsed%';
    const FORMAT_QUIET_NOMAX   = ' %current%';
    const FORMAT_NORMAL_NOMAX  = ' %current% [%bar%]';
    const FORMAT_VERBOSE_NOMAX = ' %current% [%bar%] Elapsed: %elapsed%';

    // options
    private $barWidth     = 28;
    private $barChar      = '=';
    private $emptyBarChar = '-';
    private $progressChar = '>';
    private $format       = null;
    private $redrawFreq   = 1;

    private $lastMessagesLength;
    private $barCharOriginal;

    /**
     * @var OutputInterface
     */
    private $output;

    /**
     * Current step
     *
     * @var integer
     */
    private $current;

    /**
     * Maximum number of steps
     *
     * @var integer
     */
    private $max;

    /**
     * Start time of the progress bar
     *
     * @var integer
     */
    private $startTime;

    /**
     * List of formatting variables
     *
     * @var array
     */
    private $defaultFormatVars = array(
        'current',
        'max',
        'bar',
        'percent',
        'elapsed',
    );

    /**
     * Available formatting variables
     *
     * @var array
     */
    private $formatVars;

    /**
     * Stored format part widths (used for padding)
     *
     * @var array
     */
    private $widths = array(
        'current' => 4,
        'max'     => 4,
        'percent' => 3,
        'elapsed' => 6,
    );

    /**
     * Various time formats
     *
     * @var array
     */
    private $timeFormats = array(
        array(0, '???'),
        array(2, '1 sec'),
        array(59, 'secs', 1),
        array(60, '1 min'),
        array(3600, 'mins', 60),
        array(5400, '1 hr'),
        array(86400, 'hrs', 3600),
        array(129600, '1 day'),
        array(604800, 'days', 86400),
    );

    /**
     * Sets the progress bar width.
     *
     * @param int $size The progress bar size
     */
    public function setBarWidth($size)
    {
        $this->barWidth = (int) $size;
    }

    /**
     * Sets the bar character.
     *
     * @param string $char A character
     */
    public function setBarCharacter($char)
    {
        $this->barChar = $char;
    }

    /**
     * Sets the empty bar character.
     *
     * @param string $char A character
     */
    public function setEmptyBarCharacter($char)
    {
        $this->emptyBarChar = $char;
    }

    /**
     * Sets the progress bar character.
     *
     * @param string $char A character
     */
    public function setProgressCharacter($char)
    {
        $this->progressChar = $char;
    }

    /**
     * Sets the progress bar format.
     *
     * @param string $format The format
     */
    public function setFormat($format)
    {
        $this->format = $format;
    }

    /**
     * Sets the redraw frequency.
     *
     * @param int $freq The frequency in steps
     */
    public function setRedrawFrequency($freq)
    {
        $this->redrawFreq = (int) $freq;
    }

    /**
     * Starts the progress output.
     *
     * @param OutputInterface $output An Output instance
     * @param integer|null    $max    Maximum steps
     */
    public function start(OutputInterface $output, $max = null)
    {
        $this->startTime = time();
        $this->current   = 0;
        $this->max       = (int) $max;
        $this->output    = $output;
        $this->lastMessagesLength = 0;
        $this->barCharOriginal = '';

        if (null === $this->format) {
            switch ($output->getVerbosity()) {
                case OutputInterface::VERBOSITY_QUIET:
                    $this->format = self::FORMAT_QUIET_NOMAX;
                    if ($this->max > 0) {
                        $this->format = self::FORMAT_QUIET;
                    }
                    break;
                case OutputInterface::VERBOSITY_VERBOSE:
                case OutputInterface::VERBOSITY_VERY_VERBOSE:
                case OutputInterface::VERBOSITY_DEBUG:
                    $this->format = self::FORMAT_VERBOSE_NOMAX;
                    if ($this->max > 0) {
                        $this->format = self::FORMAT_VERBOSE;
                    }
                    break;
                default:
                    $this->format = self::FORMAT_NORMAL_NOMAX;
                    if ($this->max > 0) {
                        $this->format = self::FORMAT_NORMAL;
                    }
                    break;
            }
        }

        $this->initialize();
    }

    /**
     * Advances the progress output X steps.
     *
     * @param integer $step   Number of steps to advance
     * @param Boolean $redraw Whether to redraw or not
     *
     * @throws \LogicException
     */
    public function advance($step = 1, $redraw = false)
    {
        $this->setCurrent($this->current + $step, $redraw);
    }

    /**
     * Sets the current progress.
     *
     * @param integer $current The current progress
     * @param Boolean $redraw  Whether to redraw or not
     *
     * @throws \LogicException
     */
    public function setCurrent($current, $redraw = false)
    {
        if (null === $this->startTime) {
            throw new \LogicException('You must start the progress bar before calling setCurrent().');
        }

        $current = (int) $current;

        if ($current < $this->current) {
            throw new \LogicException('You can\'t regress the progress bar');
        }

        if (0 === $this->current) {
            $redraw = true;
        }

        $prevPeriod = intval($this->current / $this->redrawFreq);

        $this->current = $current;

        $currPeriod = intval($this->current / $this->redrawFreq);
        if ($redraw || $prevPeriod !== $currPeriod || $this->max === $this->current) {
            $this->display();
        }
    }

    /**
     * Outputs the current progress string.
     *
     * @param Boolean $finish Forces the end result
     *
     * @throws \LogicException
     */
    public function display($finish = false)
    {
        if (null === $this->startTime) {
            throw new \LogicException('You must start the progress bar before calling display().');
        }

        $message = $this->format;
        foreach ($this->generate($finish) as $name => $value) {
            $message = str_replace("%{$name}%", $value, $message);
        }
        $this->overwrite($this->output, $message);
    }

    /**
     * Removes the progress bar from the current line.
     *
     * This is useful if you wish to write some output
     * while a progress bar is running.
     * Call display() to show the progress bar again.
     */
    public function clear()
    {
        $this->overwrite($this->output, '');
    }

    /**
     * Finishes the progress output.
     */
    public function finish()
    {
        if (null === $this->startTime) {
            throw new \LogicException('You must start the progress bar before calling finish().');
        }

        if (null !== $this->startTime) {
            if (!$this->max) {
                $this->barChar = $this->barCharOriginal;
                $this->display(true);
            }
            $this->startTime = null;
            $this->output->writeln('');
            $this->output = null;
        }
    }

    /**
     * Initializes the progress helper.
     */
    private function initialize()
    {
        $this->formatVars = array();
        foreach ($this->defaultFormatVars as $var) {
            if (false !== strpos($this->format, "%{$var}%")) {
                $this->formatVars[$var] = true;
            }
        }

        if ($this->max > 0) {
            $this->widths['max']     = $this->strlen($this->max);
            $this->widths['current'] = $this->widths['max'];
        } else {
            $this->barCharOriginal = $this->barChar;
            $this->barChar         = $this->emptyBarChar;
        }
    }

    /**
     * Generates the array map of format variables to values.
     *
     * @param Boolean $finish Forces the end result
     *
     * @return array Array of format vars and values
     */
    private function generate($finish = false)
    {
        $vars    = array();
        $percent = 0;
        if ($this->max > 0) {
            $percent = (float) $this->current / $this->max;
        }

        if (isset($this->formatVars['bar'])) {
            $completeBars = 0;

            if ($this->max > 0) {
                $completeBars = floor($percent * $this->barWidth);
            } else {
                if (!$finish) {
                    $completeBars = floor($this->current % $this->barWidth);
                } else {
                    $completeBars = $this->barWidth;
                }
            }

            $emptyBars = $this->barWidth - $completeBars - $this->strlen($this->progressChar);
            $bar = str_repeat($this->barChar, $completeBars);
            if ($completeBars < $this->barWidth) {
                $bar .= $this->progressChar;
                $bar .= str_repeat($this->emptyBarChar, $emptyBars);
            }

            $vars['bar'] = $bar;
        }

        if (isset($this->formatVars['elapsed'])) {
            $elapsed = time() - $this->startTime;
            $vars['elapsed'] = str_pad($this->humaneTime($elapsed), $this->widths['elapsed'], ' ', STR_PAD_LEFT);
        }

        if (isset($this->formatVars['current'])) {
            $vars['current'] = str_pad($this->current, $this->widths['current'], ' ', STR_PAD_LEFT);
        }

        if (isset($this->formatVars['max'])) {
            $vars['max'] = $this->max;
        }

        if (isset($this->formatVars['percent'])) {
            $vars['percent'] = str_pad(floor($percent * 100), $this->widths['percent'], ' ', STR_PAD_LEFT);
        }

        return $vars;
    }

    /**
     * Converts seconds into human-readable format.
     *
     * @param integer $secs Number of seconds
     *
     * @return string Time in readable format
     */
    private function humaneTime($secs)
    {
        $text = '';
        foreach ($this->timeFormats as $format) {
            if ($secs < $format[0]) {
                if (count($format) == 2) {
                    $text = $format[1];
                    break;
                } else {
                    $text = ceil($secs / $format[2]).' '.$format[1];
                    break;
                }
            }
        }

        return $text;
    }

    /**
     * Overwrites a previous message to the output.
     *
     * @param OutputInterface $output   An Output instance
     * @param string          $message  The message
     */
    private function overwrite(OutputInterface $output, $message)
    {
        $length = $this->strlen($message);

        // append whitespace to match the last line's length
        if (null !== $this->lastMessagesLength && $this->lastMessagesLength > $length) {
            $message = str_pad($message, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT);
        }

        // carriage return
        $output->write("\x0D");
        $output->write($message);

        $this->lastMessagesLength = $this->strlen($message);
    }

    /**
     * {@inheritDoc}
     */
    public function getName()
    {
        return 'progress';
    }
}
PK��Z&�>@>@1Symfony/Component/Console/Helper/DialogHelper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;

/**
 * The Dialog class provides helpers to interact with the user.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class DialogHelper extends InputAwareHelper
{
    private $inputStream;
    private static $shell;
    private static $stty;

    /**
     * Asks the user to select a value.
     *
     * @param OutputInterface $output       An Output instance
     * @param string|array    $question     The question to ask
     * @param array           $choices      List of choices to pick from
     * @param Boolean|string  $default      The default answer if the user enters nothing
     * @param Boolean|integer $attempts Max number of times to ask before giving up (false by default, which means infinite)
     * @param string          $errorMessage Message which will be shown if invalid value from choice list would be picked
     * @param Boolean         $multiselect  Select more than one value separated by comma
     *
     * @return integer|string|array The selected value or values (the key of the choices array)
     *
     * @throws \InvalidArgumentException
     */
    public function select(OutputInterface $output, $question, $choices, $default = null, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
    {
        $width = max(array_map('strlen', array_keys($choices)));

        $messages = (array) $question;
        foreach ($choices as $key => $value) {
            $messages[] = sprintf("  [<info>%-${width}s</info>] %s", $key, $value);
        }

        $output->writeln($messages);

        $result = $this->askAndValidate($output, '> ', function ($picked) use ($choices, $errorMessage, $multiselect) {
            // Collapse all spaces.
            $selectedChoices = str_replace(" ", "", $picked);

            if ($multiselect) {
                // Check for a separated comma values
                if (!preg_match('/^[a-zA-Z0-9_-]+(?:,[a-zA-Z0-9_-]+)*$/', $selectedChoices, $matches)) {
                    throw new \InvalidArgumentException(sprintf($errorMessage, $picked));
                }
                $selectedChoices = explode(",", $selectedChoices);
            } else {
                $selectedChoices = array($picked);
            }

            $multiselectChoices = array();

            foreach ($selectedChoices as $value) {
                if (empty($choices[$value])) {
                    throw new \InvalidArgumentException(sprintf($errorMessage, $value));
                }
                array_push($multiselectChoices, $value);
            }

            if ($multiselect) {
                return $multiselectChoices;
            }

            return $picked;
        }, $attempts, $default);

        return $result;
    }

    /**
     * Asks a question to the user.
     *
     * @param OutputInterface $output       An Output instance
     * @param string|array    $question     The question to ask
     * @param string          $default      The default answer if none is given by the user
     * @param array           $autocomplete List of values to autocomplete
     *
     * @return string The user answer
     *
     * @throws \RuntimeException If there is no data to read in the input stream
     */
    public function ask(OutputInterface $output, $question, $default = null, array $autocomplete = null)
    {
        if ($this->input && !$this->input->isInteractive()) {
            return $default;
        }

        $output->write($question);

        $inputStream = $this->inputStream ?: STDIN;

        if (null === $autocomplete || !$this->hasSttyAvailable()) {
            $ret = fgets($inputStream, 4096);
            if (false === $ret) {
                throw new \RuntimeException('Aborted');
            }
            $ret = trim($ret);
        } else {
            $ret = '';

            $i = 0;
            $ofs = -1;
            $matches = $autocomplete;
            $numMatches = count($matches);

            $sttyMode = shell_exec('stty -g');

            // Disable icanon (so we can fread each keypress) and echo (we'll do echoing here instead)
            shell_exec('stty -icanon -echo');

            // Add highlighted text style
            $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));

            // Read a keypress
            while (!feof($inputStream)) {
                $c = fread($inputStream, 1);

                // Backspace Character
                if ("\177" === $c) {
                    if (0 === $numMatches && 0 !== $i) {
                        $i--;
                        // Move cursor backwards
                        $output->write("\033[1D");
                    }

                    if ($i === 0) {
                        $ofs = -1;
                        $matches = $autocomplete;
                        $numMatches = count($matches);
                    } else {
                        $numMatches = 0;
                    }

                    // Pop the last character off the end of our string
                    $ret = substr($ret, 0, $i);
                } elseif ("\033" === $c) { // Did we read an escape sequence?
                    $c .= fread($inputStream, 2);

                    // A = Up Arrow. B = Down Arrow
                    if ('A' === $c[2] || 'B' === $c[2]) {
                        if ('A' === $c[2] && -1 === $ofs) {
                            $ofs = 0;
                        }

                        if (0 === $numMatches) {
                            continue;
                        }

                        $ofs += ('A' === $c[2]) ? -1 : 1;
                        $ofs = ($numMatches + $ofs) % $numMatches;
                    }
                } elseif (ord($c) < 32) {
                    if ("\t" === $c || "\n" === $c) {
                        if ($numMatches > 0 && -1 !== $ofs) {
                            $ret = $matches[$ofs];
                            // Echo out remaining chars for current match
                            $output->write(substr($ret, $i));
                            $i = strlen($ret);
                        }

                        if ("\n" === $c) {
                            $output->write($c);
                            break;
                        }

                        $numMatches = 0;
                    }

                    continue;
                } else {
                    $output->write($c);
                    $ret .= $c;
                    $i++;

                    $numMatches = 0;
                    $ofs = 0;

                    foreach ($autocomplete as $value) {
                        // If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle)
                        if (0 === strpos($value, $ret) && $i !== strlen($value)) {
                            $matches[$numMatches++] = $value;
                        }
                    }
                }

                // Erase characters from cursor to end of line
                $output->write("\033[K");

                if ($numMatches > 0 && -1 !== $ofs) {
                    // Save cursor position
                    $output->write("\0337");
                    // Write highlighted text
                    $output->write('<hl>'.substr($matches[$ofs], $i).'</hl>');
                    // Restore cursor position
                    $output->write("\0338");
                }
            }

            // Reset stty so it behaves normally again
            shell_exec(sprintf('stty %s', $sttyMode));
        }

        return strlen($ret) > 0 ? $ret : $default;
    }

    /**
     * Asks a confirmation to the user.
     *
     * The question will be asked until the user answers by nothing, yes, or no.
     *
     * @param OutputInterface $output   An Output instance
     * @param string|array    $question The question to ask
     * @param Boolean         $default  The default answer if the user enters nothing
     *
     * @return Boolean true if the user has confirmed, false otherwise
     */
    public function askConfirmation(OutputInterface $output, $question, $default = true)
    {
        $answer = 'z';
        while ($answer && !in_array(strtolower($answer[0]), array('y', 'n'))) {
            $answer = $this->ask($output, $question);
        }

        if (false === $default) {
            return $answer && 'y' == strtolower($answer[0]);
        }

        return !$answer || 'y' == strtolower($answer[0]);
    }

    /**
     * Asks a question to the user, the response is hidden
     *
     * @param OutputInterface $output   An Output instance
     * @param string|array    $question The question
     * @param Boolean         $fallback In case the response can not be hidden, whether to fallback on non-hidden question or not
     *
     * @return string         The answer
     *
     * @throws \RuntimeException In case the fallback is deactivated and the response can not be hidden
     */
    public function askHiddenResponse(OutputInterface $output, $question, $fallback = true)
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $exe = __DIR__.'/../Resources/bin/hiddeninput.exe';

            // handle code running from a phar
            if ('phar:' === substr(__FILE__, 0, 5)) {
                $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
                copy($exe, $tmpExe);
                $exe = $tmpExe;
            }

            $output->write($question);
            $value = rtrim(shell_exec($exe));
            $output->writeln('');

            if (isset($tmpExe)) {
                unlink($tmpExe);
            }

            return $value;
        }

        if ($this->hasSttyAvailable()) {
            $output->write($question);

            $sttyMode = shell_exec('stty -g');

            shell_exec('stty -echo');
            $value = fgets($this->inputStream ?: STDIN, 4096);
            shell_exec(sprintf('stty %s', $sttyMode));

            if (false === $value) {
                throw new \RuntimeException('Aborted');
            }

            $value = trim($value);
            $output->writeln('');

            return $value;
        }

        if (false !== $shell = $this->getShell()) {
            $output->write($question);
            $readCmd = $shell === 'csh' ? 'set mypassword = $<' : 'read -r mypassword';
            $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
            $value = rtrim(shell_exec($command));
            $output->writeln('');

            return $value;
        }

        if ($fallback) {
            return $this->ask($output, $question);
        }

        throw new \RuntimeException('Unable to hide the response');
    }

    /**
     * Asks for a value and validates the response.
     *
     * The validator receives the data to validate. It must return the
     * validated data when the data is valid and throw an exception
     * otherwise.
     *
     * @param OutputInterface $output       An Output instance
     * @param string|array    $question     The question to ask
     * @param callable        $validator    A PHP callback
     * @param integer         $attempts     Max number of times to ask before giving up (false by default, which means infinite)
     * @param string          $default      The default answer if none is given by the user
     * @param array           $autocomplete List of values to autocomplete
     *
     * @return mixed
     *
     * @throws \Exception When any of the validators return an error
     */
    public function askAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $default = null, array $autocomplete = null)
    {
        $that = $this;

        $interviewer = function () use ($output, $question, $default, $autocomplete, $that) {
            return $that->ask($output, $question, $default, $autocomplete);
        };

        return $this->validateAttempts($interviewer, $output, $validator, $attempts);
    }

    /**
     * Asks for a value, hide and validates the response.
     *
     * The validator receives the data to validate. It must return the
     * validated data when the data is valid and throw an exception
     * otherwise.
     *
     * @param OutputInterface $output    An Output instance
     * @param string|array    $question  The question to ask
     * @param callable        $validator A PHP callback
     * @param integer         $attempts  Max number of times to ask before giving up (false by default, which means infinite)
     * @param Boolean         $fallback  In case the response can not be hidden, whether to fallback on non-hidden question or not
     *
     * @return string         The response
     *
     * @throws \Exception        When any of the validators return an error
     * @throws \RuntimeException In case the fallback is deactivated and the response can not be hidden
     *
     */
    public function askHiddenResponseAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $fallback = true)
    {
        $that = $this;

        $interviewer = function () use ($output, $question, $fallback, $that) {
            return $that->askHiddenResponse($output, $question, $fallback);
        };

        return $this->validateAttempts($interviewer, $output, $validator, $attempts);
    }

    /**
     * Sets the input stream to read from when interacting with the user.
     *
     * This is mainly useful for testing purpose.
     *
     * @param resource $stream The input stream
     */
    public function setInputStream($stream)
    {
        $this->inputStream = $stream;
    }

    /**
     * Returns the helper's input stream
     *
     * @return string
     */
    public function getInputStream()
    {
        return $this->inputStream;
    }

    /**
     * {@inheritDoc}
     */
    public function getName()
    {
        return 'dialog';
    }

    /**
     * Return a valid Unix shell
     *
     * @return string|Boolean  The valid shell name, false in case no valid shell is found
     */
    private function getShell()
    {
        if (null !== self::$shell) {
            return self::$shell;
        }

        self::$shell = false;

        if (file_exists('/usr/bin/env')) {
            // handle other OSs with bash/zsh/ksh/csh if available to hide the answer
            $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
            foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) {
                if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
                    self::$shell = $sh;
                    break;
                }
            }
        }

        return self::$shell;
    }

    private function hasSttyAvailable()
    {
        if (null !== self::$stty) {
            return self::$stty;
        }

        exec('stty 2>&1', $output, $exitcode);

        return self::$stty = $exitcode === 0;
    }

    /**
     * Validate an attempt
     *
     * @param callable         $interviewer  A callable that will ask for a question and return the result
     * @param OutputInterface  $output       An Output instance
     * @param callable         $validator    A PHP callback
     * @param integer          $attempts     Max number of times to ask before giving up ; false will ask infinitely
     *
     * @return string   The validated response
     *
     * @throws \Exception In case the max number of attempts has been reached and no valid response has been given
     */
    private function validateAttempts($interviewer, OutputInterface $output, $validator, $attempts)
    {
        $error = null;
        while (false === $attempts || $attempts--) {
            if (null !== $error) {
                $output->writeln($this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error'));
            }

            try {
                return call_user_func($validator, $interviewer());
            } catch (\Exception $error) {
            }
        }

        throw $error;
    }
}
PK��ZD��uu7Symfony/Component/Console/Descriptor/JsonDescriptor.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Descriptor;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;

/**
 * JSON descriptor.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class JsonDescriptor extends Descriptor
{
    /**
     * {@inheritdoc}
     */
    protected function describeInputArgument(InputArgument $argument, array $options = array())
    {
        $this->writeData($this->getInputArgumentData($argument), $options);
    }

    /**
     * {@inheritdoc}
     */
    protected function describeInputOption(InputOption $option, array $options = array())
    {
        $this->writeData($this->getInputOptionData($option), $options);
    }

    /**
     * {@inheritdoc}
     */
    protected function describeInputDefinition(InputDefinition $definition, array $options = array())
    {
        $this->writeData($this->getInputDefinitionData($definition), $options);
    }

    /**
     * {@inheritdoc}
     */
    protected function describeCommand(Command $command, array $options = array())
    {
        $this->writeData($this->getCommandData($command), $options);
    }

    /**
     * {@inheritdoc}
     */
    protected function describeApplication(Application $application, array $options = array())
    {
        $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
        $description = new ApplicationDescription($application, $describedNamespace);
        $commands = array();

        foreach ($description->getCommands() as $command) {
            $commands[] = $this->getCommandData($command);
        }

        $data = $describedNamespace
            ? array('commands' => $commands, 'namespace' => $describedNamespace)
            : array('commands' => $commands, 'namespaces' => array_values($description->getNamespaces()));

        $this->writeData($data, $options);
    }

    /**
     * Writes data as json.
     *
     * @param array $data
     * @param array $options
     *
     * @return array|string
     */
    private function writeData(array $data, array $options)
    {
        $this->write(json_encode($data, isset($options['json_encoding']) ? $options['json_encoding'] : 0));
    }

    /**
     * @param InputArgument $argument
     *
     * @return array
     */
    private function getInputArgumentData(InputArgument $argument)
    {
        return array(
            'name'        => $argument->getName(),
            'is_required' => $argument->isRequired(),
            'is_array'    => $argument->isArray(),
            'description' => $argument->getDescription(),
            'default'     => $argument->getDefault(),
        );
    }

    /**
     * @param InputOption $option
     *
     * @return array
     */
    private function getInputOptionData(InputOption $option)
    {
        return array(
            'name'              => '--'.$option->getName(),
            'shortcut'          => $option->getShortcut() ? '-'.implode('|-', explode('|', $option->getShortcut())) : '',
            'accept_value'      => $option->acceptValue(),
            'is_value_required' => $option->isValueRequired(),
            'is_multiple'       => $option->isArray(),
            'description'       => $option->getDescription(),
            'default'           => $option->getDefault(),
        );
    }

    /**
     * @param InputDefinition $definition
     *
     * @return array
     */
    private function getInputDefinitionData(InputDefinition $definition)
    {
        $inputArguments = array();
        foreach ($definition->getArguments() as $name => $argument) {
            $inputArguments[$name] = $this->getInputArgumentData($argument);
        }

        $inputOptions = array();
        foreach ($definition->getOptions() as $name => $option) {
            $inputOptions[$name] = $this->getInputOptionData($option);
        }

        return array('arguments' => $inputArguments, 'options' => $inputOptions);
    }

    /**
     * @param Command $command
     *
     * @return array
     */
    private function getCommandData(Command $command)
    {
        $command->getSynopsis();
        $command->mergeApplicationDefinition(false);

        return array(
            'name'        => $command->getName(),
            'usage'       => $command->getSynopsis(),
            'description' => $command->getDescription(),
            'help'        => $command->getProcessedHelp(),
            'aliases'     => $command->getAliases(),
            'definition'  => $this->getInputDefinitionData($command->getNativeDefinition()),
        );
    }
}
PK��Z�m��
�
3Symfony/Component/Console/Descriptor/Descriptor.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Descriptor;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
abstract class Descriptor implements DescriptorInterface
{
    /**
     * @var OutputInterface
     */
    private $output;

    /**
     * {@inheritdoc}
     */
    public function describe(OutputInterface $output, $object, array $options = array())
    {
        $this->output = $output;

        switch (true) {
            case $object instanceof InputArgument:
                $this->describeInputArgument($object, $options);
                break;
            case $object instanceof InputOption:
                $this->describeInputOption($object, $options);
                break;
            case $object instanceof InputDefinition:
                $this->describeInputDefinition($object, $options);
                break;
            case $object instanceof Command:
                $this->describeCommand($object, $options);
                break;
            case $object instanceof Application:
                $this->describeApplication($object, $options);
                break;
            default:
                throw new \InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_class($object)));
        }
    }

    /**
     * Writes content to output.
     *
     * @param string  $content
     * @param boolean $decorated
     */
    protected function write($content, $decorated = false)
    {
        $this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW);
    }

    /**
     * Describes an InputArgument instance.
     *
     * @param InputArgument $argument
     * @param array         $options
     *
     * @return string|mixed
     */
    abstract protected function describeInputArgument(InputArgument $argument, array $options = array());

    /**
     * Describes an InputOption instance.
     *
     * @param InputOption $option
     * @param array       $options
     *
     * @return string|mixed
     */
    abstract protected function describeInputOption(InputOption $option, array $options = array());

    /**
     * Describes an InputDefinition instance.
     *
     * @param InputDefinition $definition
     * @param array           $options
     *
     * @return string|mixed
     */
    abstract protected function describeInputDefinition(InputDefinition $definition, array $options = array());

    /**
     * Describes a Command instance.
     *
     * @param Command $command
     * @param array   $options
     *
     * @return string|mixed
     */
    abstract protected function describeCommand(Command $command, array $options = array());

    /**
     * Describes an Application instance.
     *
     * @param Application $application
     * @param array       $options
     *
     * @return string|mixed
     */
    abstract protected function describeApplication(Application $application, array $options = array());
}
PK��Z�lP�..;Symfony/Component/Console/Descriptor/MarkdownDescriptor.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Descriptor;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;

/**
 * Markdown descriptor.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class MarkdownDescriptor extends Descriptor
{
    /**
     * {@inheritdoc}
     */
    protected function describeInputArgument(InputArgument $argument, array $options = array())
    {
        $this->write(
            '**'.$argument->getName().':**'."\n\n"
            .'* Name: '.($argument->getName() ?: '<none>')."\n"
            .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n"
            .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n"
            .'* Description: '.($argument->getDescription() ?: '<none>')."\n"
            .'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`'
        );
    }

    /**
     * {@inheritdoc}
     */
    protected function describeInputOption(InputOption $option, array $options = array())
    {
        $this->write(
            '**'.$option->getName().':**'."\n\n"
            .'* Name: `--'.$option->getName().'`'."\n"
            .'* Shortcut: '.($option->getShortcut() ? '`-'.implode('|-', explode('|', $option->getShortcut())).'`' : '<none>')."\n"
            .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n"
            .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n"
            .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n"
            .'* Description: '.($option->getDescription() ?: '<none>')."\n"
            .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`'
        );
    }

    /**
     * {@inheritdoc}
     */
    protected function describeInputDefinition(InputDefinition $definition, array $options = array())
    {
        if ($showArguments = count($definition->getArguments()) > 0) {
            $this->write('### Arguments:');
            foreach ($definition->getArguments() as $argument) {
                $this->write("\n\n");
                $this->write($this->describeInputArgument($argument));
            }
        }

        if (count($definition->getOptions()) > 0) {
            if ($showArguments) {
                $this->write("\n\n");
            }

            $this->write('### Options:');
            foreach ($definition->getOptions() as $option) {
                $this->write("\n\n");
                $this->write($this->describeInputOption($option));
            }
        }
    }

    /**
     * {@inheritdoc}
     */
    protected function describeCommand(Command $command, array $options = array())
    {
        $command->getSynopsis();
        $command->mergeApplicationDefinition(false);

        $this->write(
            $command->getName()."\n"
            .str_repeat('-', strlen($command->getName()))."\n\n"
            .'* Description: '.($command->getDescription() ?: '<none>')."\n"
            .'* Usage: `'.$command->getSynopsis().'`'."\n"
            .'* Aliases: '.(count($command->getAliases()) ? '`'.implode('`, `', $command->getAliases()).'`' : '<none>')
        );

        if ($help = $command->getProcessedHelp()) {
            $this->write("\n\n");
            $this->write($help);
        }

        if ($definition = $command->getNativeDefinition()) {
            $this->write("\n\n");
            $this->describeInputDefinition($command->getNativeDefinition());
        }
    }

    /**
     * {@inheritdoc}
     */
    protected function describeApplication(Application $application, array $options = array())
    {
        $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
        $description = new ApplicationDescription($application, $describedNamespace);

        $this->write($application->getName()."\n".str_repeat('=', strlen($application->getName())));

        foreach ($description->getNamespaces() as $namespace) {
            if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
                $this->write("\n\n");
                $this->write('**'.$namespace['id'].':**');
            }

            $this->write("\n\n");
            $this->write(implode("\n", array_map(function ($commandName) {
                return '* '.$commandName;
            } , $namespace['commands'])));
        }

        foreach ($description->getCommands() as $command) {
            $this->write("\n\n");
            $this->write($this->describeCommand($command));
        }
    }
}
PK��Z�s�X�
�
?Symfony/Component/Console/Descriptor/ApplicationDescription.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Descriptor;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;

/**
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class ApplicationDescription
{
    const GLOBAL_NAMESPACE = '_global';

    /**
     * @var Application
     */
    private $application;

    /**
     * @var null|string
     */
    private $namespace;

    /**
     * @var array
     */
    private $namespaces;

    /**
     * @var Command[]
     */
    private $commands;

    /**
     * @var Command[]
     */
    private $aliases;

    /**
     * Constructor.
     *
     * @param Application $application
     * @param string|null $namespace
     */
    public function __construct(Application $application, $namespace = null)
    {
        $this->application = $application;
        $this->namespace = $namespace;
    }

    /**
     * @return array
     */
    public function getNamespaces()
    {
        if (null === $this->namespaces) {
            $this->inspectApplication();
        }

        return $this->namespaces;
    }

    /**
     * @return Command[]
     */
    public function getCommands()
    {
        if (null === $this->commands) {
            $this->inspectApplication();
        }

        return $this->commands;
    }

    /**
     * @param string $name
     *
     * @return Command
     *
     * @throws \InvalidArgumentException
     */
    public function getCommand($name)
    {
        if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) {
            throw new \InvalidArgumentException(sprintf('Command %s does not exist.', $name));
        }

        return isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name];
    }

    private function inspectApplication()
    {
        $this->commands = array();
        $this->namespaces = array();

        $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null);
        foreach ($this->sortCommands($all) as $namespace => $commands) {
            $names = array();

            /** @var Command $command */
            foreach ($commands as $name => $command) {
                if (!$command->getName()) {
                    continue;
                }

                if ($command->getName() === $name) {
                    $this->commands[$name] = $command;
                } else {
                    $this->aliases[$name] = $command;
                }

                $names[] = $name;
            }

            $this->namespaces[$namespace] = array('id' => $namespace, 'commands' => $names);
        }
    }

    /**
     * @param array $commands
     *
     * @return array
     */
    private function sortCommands(array $commands)
    {
        $namespacedCommands = array();
        foreach ($commands as $name => $command) {
            $key = $this->application->extractNamespace($name, 1);
            if (!$key) {
                $key = '_global';
            }

            $namespacedCommands[$key][$name] = $command;
        }
        ksort($namespacedCommands);

        foreach ($namespacedCommands as &$commands) {
            ksort($commands);
        }

        return $namespacedCommands;
    }
}
PK��Zﶲ��%�%6Symfony/Component/Console/Descriptor/XmlDescriptor.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Descriptor;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;

/**
 * XML descriptor.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class XmlDescriptor extends Descriptor
{
    /**
     * @param InputDefinition $definition
     *
     * @return \DOMDocument
     */
    public function getInputDefinitionDocument(InputDefinition $definition)
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($definitionXML = $dom->createElement('definition'));

        $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments'));
        foreach ($definition->getArguments() as $argument) {
            $this->appendDocument($argumentsXML, $this->getInputArgumentDocument($argument));
        }

        $definitionXML->appendChild($optionsXML = $dom->createElement('options'));
        foreach ($definition->getOptions() as $option) {
            $this->appendDocument($optionsXML, $this->getInputOptionDocument($option));
        }

        return $dom;
    }

    /**
     * @param Command $command
     *
     * @return \DOMDocument
     */
    public function getCommandDocument(Command $command)
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($commandXML = $dom->createElement('command'));

        $command->getSynopsis();
        $command->mergeApplicationDefinition(false);

        $commandXML->setAttribute('id', $command->getName());
        $commandXML->setAttribute('name', $command->getName());

        $commandXML->appendChild($usageXML = $dom->createElement('usage'));
        $usageXML->appendChild($dom->createTextNode(sprintf($command->getSynopsis(), '')));

        $commandXML->appendChild($descriptionXML = $dom->createElement('description'));
        $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription())));

        $commandXML->appendChild($helpXML = $dom->createElement('help'));
        $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp())));

        $commandXML->appendChild($aliasesXML = $dom->createElement('aliases'));
        foreach ($command->getAliases() as $alias) {
            $aliasesXML->appendChild($aliasXML = $dom->createElement('alias'));
            $aliasXML->appendChild($dom->createTextNode($alias));
        }

        $definitionXML = $this->getInputDefinitionDocument($command->getNativeDefinition());
        $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0));

        return $dom;
    }

    /**
     * @param Application $application
     * @param string|null $namespace
     *
     * @return \DOMDocument
     */
    public function getApplicationDocument(Application $application, $namespace = null)
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($rootXml = $dom->createElement('symfony'));

        if ($application->getName() !== 'UNKNOWN') {
            $rootXml->setAttribute('name', $application->getName());
            if ($application->getVersion() !== 'UNKNOWN') {
                $rootXml->setAttribute('version', $application->getVersion());
            }
        }

        $rootXml->appendChild($commandsXML = $dom->createElement('commands'));

        $description = new ApplicationDescription($application, $namespace);

        if ($namespace) {
            $commandsXML->setAttribute('namespace', $namespace);
        }

        foreach ($description->getCommands() as $command) {
            $this->appendDocument($commandsXML, $this->getCommandDocument($command));
        }

        if (!$namespace) {
            $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces'));

            foreach ($description->getNamespaces() as $namespaceDescription) {
                $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace'));
                $namespaceArrayXML->setAttribute('id', $namespaceDescription['id']);

                foreach ($namespaceDescription['commands'] as $name) {
                    $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command'));
                    $commandXML->appendChild($dom->createTextNode($name));
                }
            }
        }

        return $dom;
    }

    /**
     * {@inheritdoc}
     */
    protected function describeInputArgument(InputArgument $argument, array $options = array())
    {
        $this->writeDocument($this->getInputArgumentDocument($argument));
    }

    /**
     * {@inheritdoc}
     */
    protected function describeInputOption(InputOption $option, array $options = array())
    {
        $this->writeDocument($this->getInputOptionDocument($option));
    }

    /**
     * {@inheritdoc}
     */
    protected function describeInputDefinition(InputDefinition $definition, array $options = array())
    {
        $this->writeDocument($this->getInputDefinitionDocument($definition));
    }

    /**
     * {@inheritdoc}
     */
    protected function describeCommand(Command $command, array $options = array())
    {
        $this->writeDocument($this->getCommandDocument($command));
    }

    /**
     * {@inheritdoc}
     */
    protected function describeApplication(Application $application, array $options = array())
    {
        $this->writeDocument($this->getApplicationDocument($application, isset($options['namespace']) ? $options['namespace'] : null));
    }

    /**
     * Appends document children to parent node.
     *
     * @param \DOMNode $parentNode
     * @param \DOMNode $importedParent
     */
    private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent)
    {
        foreach ($importedParent->childNodes as $childNode) {
            $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, true));
        }
    }

    /**
     * Writes DOM document.
     *
     * @param \DOMDocument $dom
     *
     * @return \DOMDocument|string
     */
    private function writeDocument(\DOMDocument $dom)
    {
        $dom->formatOutput = true;
        $this->write($dom->saveXML());
    }

    /**
     * @param InputArgument $argument
     *
     * @return \DOMDocument
     */
    private function getInputArgumentDocument(InputArgument $argument)
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');

        $dom->appendChild($objectXML = $dom->createElement('argument'));
        $objectXML->setAttribute('name', $argument->getName());
        $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0);
        $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0);
        $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
        $descriptionXML->appendChild($dom->createTextNode($argument->getDescription()));

        $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
        $defaults = is_array($argument->getDefault()) ? $argument->getDefault() : (is_bool($argument->getDefault()) ? array(var_export($argument->getDefault(), true)) : ($argument->getDefault() ? array($argument->getDefault()) : array()));
        foreach ($defaults as $default) {
            $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
            $defaultXML->appendChild($dom->createTextNode($default));
        }

        return $dom;
    }

    /**
     * @param InputOption $option
     *
     * @return \DOMDocument
     */
    private function getInputOptionDocument(InputOption $option)
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');

        $dom->appendChild($objectXML = $dom->createElement('option'));
        $objectXML->setAttribute('name', '--'.$option->getName());
        $pos = strpos($option->getShortcut(), '|');
        if (false !== $pos) {
            $objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos));
            $objectXML->setAttribute('shortcuts', '-'.implode('|-', explode('|', $option->getShortcut())));
        } else {
            $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : '');
        }
        $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0);
        $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0);
        $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0);
        $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
        $descriptionXML->appendChild($dom->createTextNode($option->getDescription()));

        if ($option->acceptValue()) {
            $defaults = is_array($option->getDefault()) ? $option->getDefault() : (is_bool($option->getDefault()) ? array(var_export($option->getDefault(), true)) : ($option->getDefault() ? array($option->getDefault()) : array()));
            $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));

            if (!empty($defaults)) {
                foreach ($defaults as $default) {
                    $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
                    $defaultXML->appendChild($dom->createTextNode($default));
                }
            }
        }

        return $dom;
    }
}
PK��Z����7Symfony/Component/Console/Descriptor/TextDescriptor.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Descriptor;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;

/**
 * Text descriptor.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class TextDescriptor extends Descriptor
{
    /**
     * {@inheritdoc}
     */
    protected function describeInputArgument(InputArgument $argument, array $options = array())
    {
        if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) {
            $default = sprintf('<comment> (default: %s)</comment>', $this->formatDefaultValue($argument->getDefault()));
        } else {
            $default = '';
        }

        $nameWidth = isset($options['name_width']) ? $options['name_width'] : strlen($argument->getName());

        $this->writeText(sprintf(" <info>%-${nameWidth}s</info> %s%s",
            $argument->getName(),
            str_replace("\n", "\n".str_repeat(' ', $nameWidth + 2), $argument->getDescription()),
            $default
        ), $options);
    }

    /**
     * {@inheritdoc}
     */
    protected function describeInputOption(InputOption $option, array $options = array())
    {
        if ($option->acceptValue() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) {
            $default = sprintf('<comment> (default: %s)</comment>', $this->formatDefaultValue($option->getDefault()));
        } else {
            $default = '';
        }

        $nameWidth = isset($options['name_width']) ? $options['name_width'] : strlen($option->getName());
        $nameWithShortcutWidth = $nameWidth - strlen($option->getName()) - 2;

        $this->writeText(sprintf(" <info>%s</info> %-${nameWithShortcutWidth}s%s%s%s",
            '--'.$option->getName(),
            $option->getShortcut() ? sprintf('(-%s) ', $option->getShortcut()) : '',
            str_replace("\n", "\n".str_repeat(' ', $nameWidth + 2), $option->getDescription()),
            $default,
            $option->isArray() ? '<comment> (multiple values allowed)</comment>' : ''
        ), $options);
    }

    /**
     * {@inheritdoc}
     */
    protected function describeInputDefinition(InputDefinition $definition, array $options = array())
    {
        $nameWidth = 0;
        foreach ($definition->getOptions() as $option) {
            $nameLength = strlen($option->getName()) + 2;
            if ($option->getShortcut()) {
                $nameLength += strlen($option->getShortcut()) + 3;
            }
            $nameWidth = max($nameWidth, $nameLength);
        }
        foreach ($definition->getArguments() as $argument) {
            $nameWidth = max($nameWidth, strlen($argument->getName()));
        }
        ++$nameWidth;

        if ($definition->getArguments()) {
            $this->writeText('<comment>Arguments:</comment>', $options);
            $this->writeText("\n");
            foreach ($definition->getArguments() as $argument) {
                $this->describeInputArgument($argument, array_merge($options, array('name_width' => $nameWidth)));
                $this->writeText("\n");
            }
        }

        if ($definition->getArguments() && $definition->getOptions()) {
            $this->writeText("\n");
        }

        if ($definition->getOptions()) {
            $this->writeText('<comment>Options:</comment>', $options);
            $this->writeText("\n");
            foreach ($definition->getOptions() as $option) {
                $this->describeInputOption($option, array_merge($options, array('name_width' => $nameWidth)));
                $this->writeText("\n");
            }
        }
    }

    /**
     * {@inheritdoc}
     */
    protected function describeCommand(Command $command, array $options = array())
    {
        $command->getSynopsis();
        $command->mergeApplicationDefinition(false);

        $this->writeText('<comment>Usage:</comment>', $options);
        $this->writeText("\n");
        $this->writeText(' '.$command->getSynopsis(), $options);
        $this->writeText("\n");

        if (count($command->getAliases()) > 0) {
            $this->writeText("\n");
            $this->writeText('<comment>Aliases:</comment> <info>'.implode(', ', $command->getAliases()).'</info>', $options);
        }

        if ($definition = $command->getNativeDefinition()) {
            $this->writeText("\n");
            $this->describeInputDefinition($definition, $options);
        }

        $this->writeText("\n");

        if ($help = $command->getProcessedHelp()) {
            $this->writeText('<comment>Help:</comment>', $options);
            $this->writeText("\n");
            $this->writeText(' '.str_replace("\n", "\n ", $help), $options);
            $this->writeText("\n");
        }
    }

    /**
     * {@inheritdoc}
     */
    protected function describeApplication(Application $application, array $options = array())
    {
        $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
        $description = new ApplicationDescription($application, $describedNamespace);

        if (isset($options['raw_text']) && $options['raw_text']) {
            $width = $this->getColumnWidth($description->getCommands());

            foreach ($description->getCommands() as $command) {
                $this->writeText(sprintf("%-${width}s %s", $command->getName(), $command->getDescription()), $options);
                $this->writeText("\n");
            }
        } else {
            $width = $this->getColumnWidth($description->getCommands());

            $this->writeText($application->getHelp(), $options);
            $this->writeText("\n\n");

            if ($describedNamespace) {
                $this->writeText(sprintf("<comment>Available commands for the \"%s\" namespace:</comment>", $describedNamespace), $options);
            } else {
                $this->writeText('<comment>Available commands:</comment>', $options);
            }

            // add commands by namespace
            foreach ($description->getNamespaces() as $namespace) {
                if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
                    $this->writeText("\n");
                    $this->writeText('<comment>'.$namespace['id'].'</comment>', $options);
                }

                foreach ($namespace['commands'] as $name) {
                    $this->writeText("\n");
                    $this->writeText(sprintf("  <info>%-${width}s</info> %s", $name, $description->getCommand($name)->getDescription()), $options);
                }
            }

            $this->writeText("\n");
        }
    }

    /**
     * {@inheritdoc}
     */
    private function writeText($content, array $options = array())
    {
        $this->write(
            isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content,
            isset($options['raw_output']) ? !$options['raw_output'] : true
        );
    }

    /**
     * Formats input option/argument default value.
     *
     * @param mixed $default
     *
     * @return string
     */
    private function formatDefaultValue($default)
    {
        if (version_compare(PHP_VERSION, '5.4', '<')) {
            return str_replace('\/', '/', json_encode($default));
        }

        return json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
    }

    /**
     * @param Command[] $commands
     *
     * @return int
     */
    private function getColumnWidth(array $commands)
    {
        $width = 0;
        foreach ($commands as $command) {
            $width = strlen($command->getName()) > $width ? strlen($command->getName()) : $width;
        }

        return $width + 2;
    }
}
PK��ZJZ0<��<Symfony/Component/Console/Descriptor/DescriptorInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Descriptor;

use Symfony\Component\Console\Output\OutputInterface;

/**
 * Descriptor interface.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
interface DescriptorInterface
{
    /**
     * Describes an InputArgument instance.
     *
     * @param OutputInterface $output
     * @param object          $object
     * @param array           $options
     */
    public function describe(OutputInterface $output, $object, array $options = array());
}
PK��Z���v$$7Symfony/Component/Console/Resources/bin/hiddeninput.exenu�[���MZ����@���	�!�L�!This program cannot be run in DOS mode.

$�,�;�B�;�B�;�B�2�מ:�B�2��-�B�2�ƞ9�B�2�ў?�B�a9�8�B�;�C��B�2�Ȟ:�B�2�֞:�B�2�Ӟ:�B�Rich;�B�PEL�MoO�	
8 @`?�@��"P@ Pp!8!@ �.text	
 `.rdata�	 
@@.data�0@�.rsrc @@@.reloc�P"@Bj$��@�xj�� @�e���E�PV� @�EЃ�PV� @�M�X @�e��E�P�5H @�L @YY�5\ @�E�P�5` @�D @YY��P @�M���M�T @3��H�;
0@u���h�@��l3@�$40@�5h3@�40@h$0@h(0@h 0@�� @���00@��}j�Y�jh"@�3ۉ]�d��p�]俀3@SVW�0 @;�t;�u3�F�u��h��4 @��3�F�|3@;�u
j�\Y�;�|3@��u,�5|3@h� @h� @�YY��t�E����������5<0@�|3@;�uh� @h� @�lYY�|3@9]�uSW�8 @9�3@th�3@�Y��t
SjS��3@�$0@�
� @��5$0@�5(0@�5 0@�������80@9,0@u7P�� @�E��	�M�PQ�YYËe�E�80@3�9,0@uP�h @9<0@u�� @�E������80@�øMZf9@t3��M�<@��@�8PEu��H��t��uՃ��v�3�9����xtv�3�9������j�,0@�p @j��l @YY��3@��3@�� @�
t3@��� @�
p3@��� @��x3@�V��=0@uh�@�� @Y�g�=0@�u	j��� @Y3���{�����U���(�H1@�
D1@�@1@�<1@�581@�=41@f�`1@f�
T1@f�01@f�,1@f�%(1@f�-$1@��X1@�E�L1@�E�P1@�E�\1@������0@�P1@�L0@�@0@	��D0@�0@������0@������ @��0@j�?Yj�  @h!@�$ @�=�0@uj�Yh	��( @P�, @�Ë�U��E��8csm�u*�xu$�@= �t=!�t="�t=@�u��3�]�hH@�  @3��%� @jh("@�b�5�3@�5� @��Y�E��u�u�� @Y�gj�Y�e��5�3@�։E�5�3@��YY�E�E�P�E�P�u�5l @��YP�U�E�u�֣�3@�u�փ���3@�E������	�E���j�YË�U��u�N��������YH]Ë�V��!@��!@W��;�s���t�Ѓ�;�r�_^Ë�V�"@�"@W��;�s���t�Ѓ�;�r�_^�%� @���̋�U��M�MZf9t3�]ËA<��8PEu�3ҹf9H�‹�]�����������̋�U��E�H<��ASV�q3�W�D��v�}�H;�r	�X�;�r
B��(;�r�3�_^[]������������̋�U��j�hH"@he@d�P��SVW�0@1E�3�P�E�d��e��E�h@�*�������tU�E-@Ph@�P�������t;�@$���Ѓ��E������M�d�
Y_^[��]ËE��3�=��‹�Ëe��E�����3��M�d�
Y_^[��]��%� @�%� @��he@d�5�D$�l$�l$+�SVW�0@1E�3�P�e�u��E��E������E��E�d�ËM�d�
Y__^[��]Q�U��u�u�u�uh�@h0@����]�Vhh3�V������t
VVVVV����^�3��U����0@�e��e�SW�N�@����;�t
��t	�У0@�`V�E�P�< @�u�3u�� @3� @3� @3�E�P� @�E�3E�3�;�u�O�@����u����50@�։50@^_[��%t @�%x @�%| @�%� @�%� @�%� @�%� @�%� @�%� @Pd�5�D$+d$SVW�(��0@3�P�E�u��E������E�d�ËM�d�
Y__^[��]QËM�3���������M�%T @�T$�B�J�3�����J�3�����l"@�s����#�#�#�)r)b)H)4))�(�(�(�(�(�(�)�#�$%�%&d&�&�$('�'�'�'�'(((6(�'H(Z(t(�('''�'�'l'^'R'F'>'>(0'�'�)�@W@�@�MoOl�!�@0@�0@bad allocationH0@�!@RSDSь���J�!���LZc:\users\seld\documents\visual studio 2010\Projects\hiddeninp\Release\hiddeninp.pdbe������������@@�����������:@������������@�@�����@"�d"@�"�# $#�&D H#(h �#�#�#�)r)b)H)4))�(�(�(�(�(�(�)�#�$%�%&d&�&�$('�'�'�'�'(((6(�'H(Z(t(�('''�'�'l'^'R'F'>'>(0'�'�)�GetConsoleMode�SetConsoleMode;GetStdHandleKERNEL32.dll??$?6DU?$char_traits@D@std@@V?$allocator@D@1@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@0@@Z�?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@AJ?cin@std@@3V?$basic_istream@DU?$char_traits@D@std@@@1@A�??$getline@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@YAAAV?$basic_istream@DU?$char_traits@D@std@@@0@AAV10@AAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@0@@Z??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z_??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ{??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ�?endl@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@@ZMSVCP90.dll_amsg_exit�__getmainargs,_cexit|_exitf_XcptFilter�exit�__initenv_initterm_initterm_e<_configthreadlocale�__setusermatherr_adjust_fdiv�__p__commode�__p__fmodej_encode_pointer�__set_app_typeK_crt_debugger_hookC?terminate@@YAXXZMSVCR90.dll�_unlock�__dllonexitv_lock_onexit`_decode_pointers_except_handler4_common_invoke_watson?_controlfp_s�InterlockedExchange!Sleep�InterlockedCompareExchange-TerminateProcess�GetCurrentProcess>UnhandledExceptionFilterSetUnhandledExceptionFilter�IsDebuggerPresentTQueryPerformanceCounterfGetTickCount�GetCurrentThreadId�GetCurrentProcessIdOGetSystemTimeAsFileTimes__CxxFrameHandler3N�@���D������������$!@ �8�P�h�	�	��@(��CV�(4VS_VERSION_INFO���StringFileInfob040904b0�QFileDescriptionReads from stdin without leaking info to the terminal and outputs back to stdout6FileVersion1, 0, 0, 08InternalNamehiddeninputPLegalCopyrightJordi Boggiano - 2012HOriginalFilenamehiddeninput.exe:
ProductNameHidden Input:ProductVersion1, 0, 0, 0DVarFileInfo$Translation	�<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
      </requestedPrivileges>
    </security>
  </trustInfo>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.21022.8" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
    </dependentAssembly>
  </dependency>
</assembly>PAPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDING@00!0/080F0L0T0^0d0n0{0�0�0�0�0�0�0�0�0�0�0�0�0�01#1-1@1J1O1T1v1{1�1�1�1�1�1�1�1�1�1�1�1�1�1�12"2*23292A2M2_2j2p2�2�2�2�2�2�2�2�2�2�2�2333%303N3T3Z3`3f3l3s3z3�3�3�3�3�3�3�3�3�3�3�3�3�3�3�3�34444%4;4B4�4�4�4�4�4�4�4�4�4�45!5^5c5�5�5�5H6M6_6}6�6�677
7*7w7|7�7�7�7�78
88=8E8P8V8\8b8h8n8t8z8�8�8�89 $�0�0�01 1t1x12 2@2\2`2h2t200PK��Z||-&��7Symfony/Component/Console/Event/ConsoleCommandEvent.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Event;

/**
 * Allows to do things before the command is executed.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ConsoleCommandEvent extends ConsoleEvent
{
}
PK��Z�Z��&&9Symfony/Component/Console/Event/ConsoleTerminateEvent.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Event;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * Allows to manipulate the exit code of a command after its execution.
 *
 * @author Francesco Levorato <git@flevour.net>
 */
class ConsoleTerminateEvent extends ConsoleEvent
{
    /**
     * The exit code of the command.
     *
     * @var integer
     */
    private $exitCode;

    public function __construct(Command $command, InputInterface $input, OutputInterface $output, $exitCode)
    {
        parent::__construct($command, $input, $output);

        $this->setExitCode($exitCode);
    }

    /**
     * Sets the exit code.
     *
     * @param integer $exitCode The command exit code
     */
    public function setExitCode($exitCode)
    {
        $this->exitCode = (int) $exitCode;
    }

    /**
     * Gets the exit code.
     *
     * @return integer The command exit code
     */
    public function getExitCode()
    {
        return $this->exitCode;
    }
}
PK��Zs�KAA9Symfony/Component/Console/Event/ConsoleExceptionEvent.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Event;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * Allows to handle exception thrown in a command.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ConsoleExceptionEvent extends ConsoleEvent
{
    private $exception;
    private $exitCode;

    public function __construct(Command $command, InputInterface $input, OutputInterface $output, \Exception $exception, $exitCode)
    {
        parent::__construct($command, $input, $output);

        $this->setException($exception);
        $this->exitCode = (int) $exitCode;
    }

    /**
     * Returns the thrown exception.
     *
     * @return \Exception The thrown exception
     */
    public function getException()
    {
        return $this->exception;
    }

    /**
     * Replaces the thrown exception.
     *
     * This exception will be thrown if no response is set in the event.
     *
     * @param \Exception $exception The thrown exception
     */
    public function setException(\Exception $exception)
    {
        $this->exception = $exception;
    }

    /**
     * Gets the exit code.
     *
     * @return integer The command exit code
     */
    public function getExitCode()
    {
        return $this->exitCode;
    }
}
PK��Z��
���0Symfony/Component/Console/Event/ConsoleEvent.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Event;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\EventDispatcher\Event;

/**
 * Allows to inspect input and output of a command.
 *
 * @author Francesco Levorato <git@flevour.net>
 */
class ConsoleEvent extends Event
{
    protected $command;

    private $input;
    private $output;

    public function __construct(Command $command, InputInterface $input, OutputInterface $output)
    {
        $this->command = $command;
        $this->input = $input;
        $this->output = $output;
    }

    /**
     * Gets the command that is executed.
     *
     * @return Command A Command instance
     */
    public function getCommand()
    {
        return $this->command;
    }

    /**
     * Gets the input instance.
     *
     * @return InputInterface An InputInterface instance
     */
    public function getInput()
    {
        return $this->input;
    }

    /**
     * Gets the output instance.
     *
     * @return OutputInterface An OutputInterface instance
     */
    public function getOutput()
    {
        return $this->output;
    }
}
PK��Z]�='YY0Symfony/Component/OptionsResolver/autoloader.phpnu�[���<?php

spl_autoload_register(function ($class) {
    if ('\\' == $class[0]) {
        $class = substr($class, 1);
    }

    if (
        0 === strpos($class, 'Symfony\\Component\\OptionsResolver\\')
        &&
        file_exists($file = __DIR__.'/../../../'.str_replace('\\', '/', $class).'.php')
    ) {
        require_once $file;
    }
});
PK��Z��sZ��GSymfony/Component/OptionsResolver/Exception/InvalidOptionsException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\OptionsResolver\Exception;

/**
 * Exception thrown when an invalid option is passed.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class InvalidOptionsException extends \InvalidArgumentException implements ExceptionInterface
{
}
PK��Z�yPH��ISymfony/Component/OptionsResolver/Exception/OptionDefinitionException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\OptionsResolver\Exception;

/**
 * Thrown when an option definition is invalid.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class OptionDefinitionException extends \RuntimeException implements ExceptionInterface
{
}
PK��ZE@�^��BSymfony/Component/OptionsResolver/Exception/ExceptionInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\OptionsResolver\Exception;

/**
 * Marker interface for the Options component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface ExceptionInterface
{
}
PK��Zp����GSymfony/Component/OptionsResolver/Exception/MissingOptionsException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\OptionsResolver\Exception;

/**
 * Exception thrown when a required option is missing.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class MissingOptionsException extends \InvalidArgumentException implements ExceptionInterface
{
}
PK��Z��G��>Symfony/Component/OptionsResolver/OptionsResolverInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\OptionsResolver;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface OptionsResolverInterface
{
    /**
     * Sets default option values.
     *
     * The options can either be values of any types or closures that
     * evaluate the option value lazily. These closures must have one
     * of the following signatures:
     *
     * <code>
     * function (Options $options)
     * function (Options $options, $value)
     * </code>
     *
     * The second parameter passed to the closure is the previously
     * set default value, in case you are overwriting an existing
     * default value.
     *
     * The closures should return the lazily created option value.
     *
     * @param array $defaultValues A list of option names as keys and default
     *                             values or closures as values.
     *
     * @return OptionsResolverInterface The resolver instance.
     */
    public function setDefaults(array $defaultValues);

    /**
     * Replaces default option values.
     *
     * Old defaults are erased, which means that closures passed here cannot
     * access the previous default value. This may be useful to improve
     * performance if the previous default value is calculated by an expensive
     * closure.
     *
     * @param array $defaultValues A list of option names as keys and default
     *                             values or closures as values.
     *
     * @return OptionsResolverInterface The resolver instance.
     */
    public function replaceDefaults(array $defaultValues);

    /**
     * Sets optional options.
     *
     * This method declares valid option names without setting default values for them.
     * If these options are not passed to {@link resolve()} and no default has been set
     * for them, they will be missing in the final options array. This can be helpful
     * if you want to determine whether an option has been set or not because otherwise
     * {@link resolve()} would trigger an exception for unknown options.
     *
     * @param array $optionNames A list of option names.
     *
     * @return OptionsResolverInterface The resolver instance.
     *
     * @throws Exception\OptionDefinitionException When trying to pass default values.
     */
    public function setOptional(array $optionNames);

    /**
     * Sets required options.
     *
     * If these options are not passed to {@link resolve()} and no default has been set for
     * them, an exception will be thrown.
     *
     * @param array $optionNames A list of option names.
     *
     * @return OptionsResolverInterface The resolver instance.
     *
     * @throws Exception\OptionDefinitionException When trying to pass default values.
     */
    public function setRequired(array $optionNames);

    /**
     * Sets allowed values for a list of options.
     *
     * @param array $allowedValues A list of option names as keys and arrays
     *                             with values acceptable for that option as
     *                             values.
     *
     * @return OptionsResolverInterface The resolver instance.
     *
     * @throws Exception\InvalidOptionsException If an option has not been defined
     *                                 (see {@link isKnown()}) for which
     *                                 an allowed value is set.
     */
    public function setAllowedValues(array $allowedValues);

    /**
     * Adds allowed values for a list of options.
     *
     * The values are merged with the allowed values defined previously.
     *
     * @param array $allowedValues A list of option names as keys and arrays
     *                             with values acceptable for that option as
     *                             values.
     *
     * @return OptionsResolverInterface The resolver instance.
     *
     * @throws Exception\InvalidOptionsException If an option has not been defined
     *                                 (see {@link isKnown()}) for which
     *                                 an allowed value is set.
     */
    public function addAllowedValues(array $allowedValues);

    /**
     * Sets allowed types for a list of options.
     *
     * @param array $allowedTypes A list of option names as keys and type
     *                            names passed as string or array as values.
     *
     * @return OptionsResolverInterface The resolver instance.
     *
     * @throws Exception\InvalidOptionsException If an option has not been defined for
     *                                           which an allowed type is set.
     */
    public function setAllowedTypes(array $allowedTypes);

    /**
     * Adds allowed types for a list of options.
     *
     * The types are merged with the allowed types defined previously.
     *
     * @param array $allowedTypes A list of option names as keys and type
     *                            names passed as string or array as values.
     *
     * @return OptionsResolverInterface The resolver instance.
     *
     * @throws Exception\InvalidOptionsException If an option has not been defined for
     *                                           which an allowed type is set.
     */
    public function addAllowedTypes(array $allowedTypes);

    /**
     * Sets normalizers that are applied on resolved options.
     *
     * The normalizers should be closures with the following signature:
     *
     * <code>
     * function (Options $options, $value)
     * </code>
     *
     * The second parameter passed to the closure is the value of
     * the option.
     *
     * The closure should return the normalized value.
     *
     * @param array $normalizers An array of closures.
     *
     * @return OptionsResolverInterface The resolver instance.
     */
    public function setNormalizers(array $normalizers);

    /**
     * Returns whether an option is known.
     *
     * An option is known if it has been passed to either {@link setDefaults()},
     * {@link setRequired()} or {@link setOptional()} before.
     *
     * @param string $option The name of the option.
     *
     * @return Boolean Whether the option is known.
     */
    public function isKnown($option);

    /**
     * Returns whether an option is required.
     *
     * An option is required if it has been passed to {@link setRequired()},
     * but not to {@link setDefaults()}. That is, the option has been declared
     * as required and no default value has been set.
     *
     * @param string $option The name of the option.
     *
     * @return Boolean Whether the option is required.
     */
    public function isRequired($option);

    /**
     * Returns the combination of the default and the passed options.
     *
     * @param array $options The custom option values.
     *
     * @return array A list of options and their values.
     *
     * @throws Exception\InvalidOptionsException   If any of the passed options has not
     *                                             been defined or does not contain an
     *                                             allowed value.
     * @throws Exception\MissingOptionsException   If a required option is missing.
     * @throws Exception\OptionDefinitionException If a cyclic dependency is detected
     *                                             between two lazy options.
     */
    public function resolve(array $options = array());
}
PK��Z^�R��<�<-Symfony/Component/OptionsResolver/Options.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\OptionsResolver;

use Symfony\Component\OptionsResolver\Exception\OptionDefinitionException;

/**
 * Container for resolving inter-dependent options.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class Options implements \ArrayAccess, \Iterator, \Countable
{
    /**
     * A list of option values.
     * @var array
     */
    private $options = array();

    /**
     * A list of normalizer closures.
     * @var array
     */
    private $normalizers = array();

    /**
     * A list of closures for evaluating lazy options.
     * @var array
     */
    private $lazy = array();

    /**
     * A list containing the currently locked options.
     * @var array
     */
    private $lock = array();

    /**
     * Whether at least one option has already been read.
     *
     * Once read, the options cannot be changed anymore. This is
     * necessary in order to avoid inconsistencies during the resolving
     * process. If any option is changed after being read, all evaluated
     * lazy options that depend on this option would become invalid.
     *
     * @var Boolean
     */
    private $reading = false;

    /**
     * Sets the value of a given option.
     *
     * You can set lazy options by passing a closure with the following
     * signature:
     *
     * <code>
     * function (Options $options)
     * </code>
     *
     * This closure will be evaluated once the option is read using
     * {@link get()}. The closure has access to the resolved values of
     * other options through the passed {@link Options} instance.
     *
     * @param string $option The name of the option.
     * @param mixed  $value  The value of the option.
     *
     * @throws OptionDefinitionException If options have already been read.
     *                                   Once options are read, the container
     *                                   becomes immutable.
     */
    public function set($option, $value)
    {
        // Setting is not possible once an option is read, because then lazy
        // options could manipulate the state of the object, leading to
        // inconsistent results.
        if ($this->reading) {
            throw new OptionDefinitionException('Options cannot be set anymore once options have been read.');
        }

        // Setting is equivalent to overloading while discarding the previous
        // option value
        unset($this->options[$option]);
        unset($this->lazy[$option]);

        $this->overload($option, $value);
    }

    /**
     * Sets the normalizer for a given option.
     *
     * Normalizers should be closures with the following signature:
     *
     * <code>
     * function (Options $options, $value)
     * </code>
     *
     * This closure will be evaluated once the option is read using
     * {@link get()}. The closure has access to the resolved values of
     * other options through the passed {@link Options} instance.
     *
     * @param string   $option     The name of the option.
     * @param \Closure $normalizer The normalizer.
     *
     * @throws OptionDefinitionException If options have already been read.
     *                                   Once options are read, the container
     *                                   becomes immutable.
     */
    public function setNormalizer($option, \Closure $normalizer)
    {
        if ($this->reading) {
            throw new OptionDefinitionException('Normalizers cannot be added anymore once options have been read.');
        }

        $this->normalizers[$option] = $normalizer;
    }

    /**
     * Replaces the contents of the container with the given options.
     *
     * This method is a shortcut for {@link clear()} with subsequent
     * calls to {@link set()}.
     *
     * @param array $options The options to set.
     *
     * @throws OptionDefinitionException If options have already been read.
     *                                   Once options are read, the container
     *                                   becomes immutable.
     */
    public function replace(array $options)
    {
        if ($this->reading) {
            throw new OptionDefinitionException('Options cannot be replaced anymore once options have been read.');
        }

        $this->options = array();
        $this->lazy = array();
        $this->normalizers = array();

        foreach ($options as $option => $value) {
            $this->overload($option, $value);
        }
    }

    /**
     * Overloads the value of a given option.
     *
     * Contrary to {@link set()}, this method keeps the previous default
     * value of the option so that you can access it if you pass a closure.
     * Passed closures should have the following signature:
     *
     * <code>
     * function (Options $options, $value)
     * </code>
     *
     * The second parameter passed to the closure is the current default
     * value of the option.
     *
     * @param string $option The option name.
     * @param mixed  $value  The option value.
     *
     * @throws OptionDefinitionException If options have already been read.
     *                                   Once options are read, the container
     *                                   becomes immutable.
     */
    public function overload($option, $value)
    {
        if ($this->reading) {
            throw new OptionDefinitionException('Options cannot be overloaded anymore once options have been read.');
        }

        // If an option is a closure that should be evaluated lazily, store it
        // in the "lazy" property.
        if ($value instanceof \Closure) {
            $reflClosure = new \ReflectionFunction($value);
            $params = $reflClosure->getParameters();

            if (isset($params[0]) && null !== ($class = $params[0]->getClass()) && __CLASS__ === $class->name) {
                // Initialize the option if no previous value exists
                if (!isset($this->options[$option])) {
                    $this->options[$option] = null;
                }

                // Ignore previous lazy options if the closure has no second parameter
                if (!isset($this->lazy[$option]) || !isset($params[1])) {
                    $this->lazy[$option] = array();
                }

                // Store closure for later evaluation
                $this->lazy[$option][] = $value;

                return;
            }
        }

        // Remove lazy options by default
        unset($this->lazy[$option]);

        $this->options[$option] = $value;
    }

    /**
     * Returns the value of the given option.
     *
     * If the option was a lazy option, it is evaluated now.
     *
     * @param string $option The option name.
     *
     * @return mixed The option value.
     *
     * @throws \OutOfBoundsException     If the option does not exist.
     * @throws OptionDefinitionException If a cyclic dependency is detected
     *                                   between two lazy options.
     */
    public function get($option)
    {
        $this->reading = true;

        if (!array_key_exists($option, $this->options)) {
            throw new \OutOfBoundsException(sprintf('The option "%s" does not exist.', $option));
        }

        if (isset($this->lazy[$option])) {
            $this->resolve($option);
        }

        if (isset($this->normalizers[$option])) {
            $this->normalize($option);
        }

        return $this->options[$option];
    }

    /**
     * Returns whether the given option exists.
     *
     * @param string $option The option name.
     *
     * @return Boolean Whether the option exists.
     */
    public function has($option)
    {
        return array_key_exists($option, $this->options);
    }

    /**
     * Removes the option with the given name.
     *
     * @param string $option The option name.
     *
     * @throws OptionDefinitionException If options have already been read.
     *                                   Once options are read, the container
     *                                   becomes immutable.
     */
    public function remove($option)
    {
        if ($this->reading) {
            throw new OptionDefinitionException('Options cannot be removed anymore once options have been read.');
        }

        unset($this->options[$option]);
        unset($this->lazy[$option]);
        unset($this->normalizers[$option]);
    }

    /**
     * Removes all options.
     *
     * @throws OptionDefinitionException If options have already been read.
     *                                   Once options are read, the container
     *                                   becomes immutable.
     */
    public function clear()
    {
        if ($this->reading) {
            throw new OptionDefinitionException('Options cannot be cleared anymore once options have been read.');
        }

        $this->options = array();
        $this->lazy = array();
        $this->normalizers = array();
    }

    /**
     * Returns the values of all options.
     *
     * Lazy options are evaluated at this point.
     *
     * @return array The option values.
     */
    public function all()
    {
        $this->reading = true;

        // Performance-wise this is slightly better than
        // while (null !== $option = key($this->lazy))
        foreach ($this->lazy as $option => $closures) {
            // Double check, in case the option has already been resolved
            // by cascade in the previous cycles
            if (isset($this->lazy[$option])) {
                $this->resolve($option);
            }
        }

        foreach ($this->normalizers as $option => $normalizer) {
            if (isset($this->normalizers[$option])) {
                $this->normalize($option);
            }
        }

        return $this->options;
    }

    /**
     * Equivalent to {@link has()}.
     *
     * @param string $option The option name.
     *
     * @return Boolean Whether the option exists.
     *
     * @see \ArrayAccess::offsetExists()
     */
    public function offsetExists($option)
    {
        return $this->has($option);
    }

    /**
     * Equivalent to {@link get()}.
     *
     * @param string $option The option name.
     *
     * @return mixed The option value.
     *
     * @throws \OutOfBoundsException     If the option does not exist.
     * @throws OptionDefinitionException If a cyclic dependency is detected
     *                                   between two lazy options.
     *
     * @see \ArrayAccess::offsetGet()
     */
    public function offsetGet($option)
    {
        return $this->get($option);
    }

    /**
     * Equivalent to {@link set()}.
     *
     * @param string $option The name of the option.
     * @param mixed  $value  The value of the option. May be a closure with a
     *                       signature as defined in DefaultOptions::add().
     *
     * @throws OptionDefinitionException If options have already been read.
     *                                   Once options are read, the container
     *                                   becomes immutable.
     *
     * @see \ArrayAccess::offsetSet()
     */
    public function offsetSet($option, $value)
    {
        $this->set($option, $value);
    }

    /**
     * Equivalent to {@link remove()}.
     *
     * @param string $option The option name.
     *
     * @throws OptionDefinitionException If options have already been read.
     *                                   Once options are read, the container
     *                                   becomes immutable.
     *
     * @see \ArrayAccess::offsetUnset()
     */
    public function offsetUnset($option)
    {
        $this->remove($option);
    }

    /**
     * {@inheritdoc}
     */
    public function current()
    {
        return $this->get($this->key());
    }

    /**
     * {@inheritdoc}
     */
    public function next()
    {
        next($this->options);
    }

    /**
     * {@inheritdoc}
     */
    public function key()
    {
        return key($this->options);
    }

    /**
     * {@inheritdoc}
     */
    public function valid()
    {
        return null !== $this->key();
    }

    /**
     * {@inheritdoc}
     */
    public function rewind()
    {
        reset($this->options);
    }

    /**
     * {@inheritdoc}
     */
    public function count()
    {
        return count($this->options);
    }

    /**
     * Evaluates the given lazy option.
     *
     * The evaluated value is written into the options array. The closure for
     * evaluating the option is discarded afterwards.
     *
     * @param string $option The option to evaluate.
     *
     * @throws OptionDefinitionException If the option has a cyclic dependency
     *                                   on another option.
     */
    private function resolve($option)
    {
        // The code duplication with normalize() exists for performance
        // reasons, in order to save a method call.
        // Remember that this method is potentially called a couple of thousand
        // times and needs to be as efficient as possible.
        if (isset($this->lock[$option])) {
            $conflicts = array();

            foreach ($this->lock as $option => $locked) {
                if ($locked) {
                    $conflicts[] = $option;
                }
            }

            throw new OptionDefinitionException(sprintf('The options "%s" have a cyclic dependency.', implode('", "', $conflicts)));
        }

        $this->lock[$option] = true;
        foreach ($this->lazy[$option] as $closure) {
            $this->options[$option] = $closure($this, $this->options[$option]);
        }
        unset($this->lock[$option]);

        // The option now isn't lazy anymore
        unset($this->lazy[$option]);
    }

    /**
     * Normalizes the given  option.
     *
     * The evaluated value is written into the options array.
     *
     * @param string $option The option to normalizer.
     *
     * @throws OptionDefinitionException If the option has a cyclic dependency
     *                                   on another option.
     */
    private function normalize($option)
    {
        // The code duplication with resolve() exists for performance
        // reasons, in order to save a method call.
        // Remember that this method is potentially called a couple of thousand
        // times and needs to be as efficient as possible.
        if (isset($this->lock[$option])) {
            $conflicts = array();

            foreach ($this->lock as $option => $locked) {
                if ($locked) {
                    $conflicts[] = $option;
                }
            }

            throw new OptionDefinitionException(sprintf('The options "%s" have a cyclic dependency.', implode('", "', $conflicts)));
        }

        /** @var \Closure $normalizer */
        $normalizer = $this->normalizers[$option];

        $this->lock[$option] = true;
        $this->options[$option] = $normalizer($this, array_key_exists($option, $this->options) ? $this->options[$option] : null);
        unset($this->lock[$option]);

        // The option is now normalized
        unset($this->normalizers[$option]);
    }
}
PK��Z}���8%8%5Symfony/Component/OptionsResolver/OptionsResolver.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\OptionsResolver;

use Symfony\Component\OptionsResolver\Exception\OptionDefinitionException;
use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
use Symfony\Component\OptionsResolver\Exception\MissingOptionsException;

/**
 * Helper for merging default and concrete option values.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 * @author Tobias Schultze <http://tobion.de>
 */
class OptionsResolver implements OptionsResolverInterface
{
    /**
     * The default option values.
     * @var Options
     */
    private $defaultOptions;

    /**
     * The options known by the resolver.
     * @var array
     */
    private $knownOptions = array();

    /**
     * The options without defaults that are required to be passed to resolve().
     * @var array
     */
    private $requiredOptions = array();

    /**
     * A list of accepted values for each option.
     * @var array
     */
    private $allowedValues = array();

    /**
     * A list of accepted types for each option.
     * @var array
     */
    private $allowedTypes = array();

    /**
     * Creates a new instance.
     */
    public function __construct()
    {
        $this->defaultOptions = new Options();
    }

    /**
     * Clones the resolver.
     */
    public function __clone()
    {
        $this->defaultOptions = clone $this->defaultOptions;
    }

    /**
     * {@inheritdoc}
     */
    public function setDefaults(array $defaultValues)
    {
        foreach ($defaultValues as $option => $value) {
            $this->defaultOptions->overload($option, $value);
            $this->knownOptions[$option] = true;
            unset($this->requiredOptions[$option]);
        }

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function replaceDefaults(array $defaultValues)
    {
        foreach ($defaultValues as $option => $value) {
            $this->defaultOptions->set($option, $value);
            $this->knownOptions[$option] = true;
            unset($this->requiredOptions[$option]);
        }

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setOptional(array $optionNames)
    {
        foreach ($optionNames as $key => $option) {
            if (!is_int($key)) {
                throw new OptionDefinitionException('You should not pass default values to setOptional()');
            }

            $this->knownOptions[$option] = true;
        }

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setRequired(array $optionNames)
    {
        foreach ($optionNames as $key => $option) {
            if (!is_int($key)) {
                throw new OptionDefinitionException('You should not pass default values to setRequired()');
            }

            $this->knownOptions[$option] = true;
            // set as required if no default has been set already
            if (!isset($this->defaultOptions[$option])) {
                $this->requiredOptions[$option] = true;
            }
        }

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setAllowedValues(array $allowedValues)
    {
        $this->validateOptionsExistence($allowedValues);

        $this->allowedValues = array_replace($this->allowedValues, $allowedValues);

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function addAllowedValues(array $allowedValues)
    {
        $this->validateOptionsExistence($allowedValues);

        $this->allowedValues = array_merge_recursive($this->allowedValues, $allowedValues);

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setAllowedTypes(array $allowedTypes)
    {
        $this->validateOptionsExistence($allowedTypes);

        $this->allowedTypes = array_replace($this->allowedTypes, $allowedTypes);

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function addAllowedTypes(array $allowedTypes)
    {
        $this->validateOptionsExistence($allowedTypes);

        $this->allowedTypes = array_merge_recursive($this->allowedTypes, $allowedTypes);

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setNormalizers(array $normalizers)
    {
        $this->validateOptionsExistence($normalizers);

        foreach ($normalizers as $option => $normalizer) {
            $this->defaultOptions->setNormalizer($option, $normalizer);
        }

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function isKnown($option)
    {
        return isset($this->knownOptions[$option]);
    }

    /**
     * {@inheritdoc}
     */
    public function isRequired($option)
    {
        return isset($this->requiredOptions[$option]);
    }

    /**
     * {@inheritdoc}
     */
    public function resolve(array $options = array())
    {
        $this->validateOptionsExistence($options);
        $this->validateOptionsCompleteness($options);

        // Make sure this method can be called multiple times
        $combinedOptions = clone $this->defaultOptions;

        // Override options set by the user
        foreach ($options as $option => $value) {
            $combinedOptions->set($option, $value);
        }

        // Resolve options
        $resolvedOptions = $combinedOptions->all();

        $this->validateOptionValues($resolvedOptions);
        $this->validateOptionTypes($resolvedOptions);

        return $resolvedOptions;
    }

    /**
     * Validates that the given option names exist and throws an exception
     * otherwise.
     *
     * @param array $options An list of option names as keys.
     *
     * @throws InvalidOptionsException If any of the options has not been defined.
     */
    private function validateOptionsExistence(array $options)
    {
        $diff = array_diff_key($options, $this->knownOptions);

        if (count($diff) > 0) {
            ksort($this->knownOptions);
            ksort($diff);

            throw new InvalidOptionsException(sprintf(
                (count($diff) > 1 ? 'The options "%s" do not exist.' : 'The option "%s" does not exist.').' Known options are: "%s"',
                implode('", "', array_keys($diff)),
                implode('", "', array_keys($this->knownOptions))
            ));
        }
    }

    /**
     * Validates that all required options are given and throws an exception
     * otherwise.
     *
     * @param array $options An list of option names as keys.
     *
     * @throws MissingOptionsException If a required option is missing.
     */
    private function validateOptionsCompleteness(array $options)
    {
        $diff = array_diff_key($this->requiredOptions, $options);

        if (count($diff) > 0) {
            ksort($diff);

            throw new MissingOptionsException(sprintf(
                count($diff) > 1 ? 'The required options "%s" are missing.' : 'The required option "%s" is missing.',
                implode('", "', array_keys($diff))
            ));
        }
    }

    /**
     * Validates that the given option values match the allowed values and
     * throws an exception otherwise.
     *
     * @param array $options A list of option values.
     *
     * @throws InvalidOptionsException If any of the values does not match the
     *                                 allowed values of the option.
     */
    private function validateOptionValues(array $options)
    {
        foreach ($this->allowedValues as $option => $allowedValues) {
            if (isset($options[$option]) && !in_array($options[$option], $allowedValues, true)) {
                throw new InvalidOptionsException(sprintf('The option "%s" has the value "%s", but is expected to be one of "%s"', $option, $options[$option], implode('", "', $allowedValues)));
            }
        }
    }

    /**
     * Validates that the given options match the allowed types and
     * throws an exception otherwise.
     *
     * @param array $options A list of options.
     *
     * @throws InvalidOptionsException If any of the types does not match the
     *                                 allowed types of the option.
     */
    private function validateOptionTypes(array $options)
    {
        foreach ($this->allowedTypes as $option => $allowedTypes) {
            if (!array_key_exists($option, $options)) {
                continue;
            }

            $value = $options[$option];
            $allowedTypes = (array) $allowedTypes;

            foreach ($allowedTypes as $type) {
                $isFunction = 'is_'.$type;

                if (function_exists($isFunction) && $isFunction($value)) {
                    continue 2;
                } elseif ($value instanceof $type) {
                    continue 2;
                }
            }

            $printableValue = is_object($value)
                ? get_class($value)
                : (is_array($value)
                    ? 'Array'
                    : (string) $value);

            throw new InvalidOptionsException(sprintf(
                'The option "%s" with value "%s" is expected to be of type "%s"',
                $option,
                $printableValue,
                implode('", "', $allowedTypes)
            ));
        }
    }
}
PK��ZfJ���5Symfony/Component/Config/Definition/NodeInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition;

/**
 * Common Interface among all nodes.
 *
 * In most cases, it is better to inherit from BaseNode instead of implementing
 * this interface yourself.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface NodeInterface
{
    /**
     * Returns the name of the node.
     *
     * @return string The name of the node
     */
    public function getName();

    /**
     * Returns the path of the node.
     *
     * @return string The node path
     */
    public function getPath();

    /**
     * Returns true when the node is required.
     *
     * @return Boolean If the node is required
     */
    public function isRequired();

    /**
     * Returns true when the node has a default value.
     *
     * @return Boolean If the node has a default value
     */
    public function hasDefaultValue();

    /**
     * Returns the default value of the node.
     *
     * @return mixed The default value
     * @throws \RuntimeException if the node has no default value
     */
    public function getDefaultValue();

    /**
     * Normalizes the supplied value.
     *
     * @param mixed $value The value to normalize
     *
     * @return mixed The normalized value
     */
    public function normalize($value);

    /**
     * Merges two values together.
     *
     * @param mixed $leftSide
     * @param mixed $rightSide
     *
     * @return mixed The merged values
     */
    public function merge($leftSide, $rightSide);

    /**
     * Finalizes a value.
     *
     * @param mixed $value The value to finalize
     *
     * @return mixed The finalized value
     */
    public function finalize($value);
}
PK��Z��jkk3Symfony/Component/Config/Definition/IntegerNode.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition;

use Symfony\Component\Config\Definition\Exception\InvalidTypeException;

/**
 * This node represents an integer value in the config tree.
 *
 * @author Jeanmonod David <david.jeanmonod@gmail.com>
 */
class IntegerNode extends NumericNode
{
    /**
     * {@inheritDoc}
     */
    protected function validateType($value)
    {
        if (!is_int($value)) {
            $ex = new InvalidTypeException(sprintf('Invalid type for path "%s". Expected int, but got %s.', $this->getPath(), gettype($value)));
            $ex->setPath($this->getPath());

            throw $ex;
        }
    }
}
PK��Za�Vp0Symfony/Component/Config/Definition/EnumNode.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition;

use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;

/**
 * Node which only allows a finite set of values.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class EnumNode extends ScalarNode
{
    private $values;

    public function __construct($name, NodeInterface $parent = null, array $values = array())
    {
        $values = array_unique($values);
        if (count($values) <= 1) {
            throw new \InvalidArgumentException('$values must contain at least two distinct elements.');
        }

        parent::__construct($name, $parent);
        $this->values = $values;
    }

    public function getValues()
    {
        return $this->values;
    }

    protected function finalizeValue($value)
    {
        $value = parent::finalizeValue($value);

        if (!in_array($value, $this->values, true)) {
            $ex = new InvalidConfigurationException(sprintf(
                'The value %s is not allowed for path "%s". Permissible values: %s',
                json_encode($value),
                $this->getPath(),
                implode(', ', array_map('json_encode', $this->values))));
            $ex->setPath($this->getPath());

            throw $ex;
        }

        return $value;
    }
}
PK��ZUn=#'#';Symfony/Component/Config/Definition/PrototypedArrayNode.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition;

use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use Symfony\Component\Config\Definition\Exception\DuplicateKeyException;
use Symfony\Component\Config\Definition\Exception\UnsetKeyException;
use Symfony\Component\Config\Definition\Exception\Exception;

/**
 * Represents a prototyped Array node in the config tree.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class PrototypedArrayNode extends ArrayNode
{
    protected $prototype;
    protected $keyAttribute;
    protected $removeKeyAttribute = false;
    protected $minNumberOfElements = 0;
    protected $defaultValue = array();
    protected $defaultChildren;

    /**
     * Sets the minimum number of elements that a prototype based node must
     * contain. By default this is zero, meaning no elements.
     *
     * @param integer $number
     */
    public function setMinNumberOfElements($number)
    {
        $this->minNumberOfElements = $number;
    }

    /**
     * Sets the attribute which value is to be used as key.
     *
     * This is useful when you have an indexed array that should be an
     * associative array. You can select an item from within the array
     * to be the key of the particular item. For example, if "id" is the
     * "key", then:
     *
     *     array(
     *         array('id' => 'my_name', 'foo' => 'bar'),
     *     );
     *
     *  becomes
     *
     *      array(
     *          'my_name' => array('foo' => 'bar'),
     *      );
     *
     * If you'd like "'id' => 'my_name'" to still be present in the resulting
     * array, then you can set the second argument of this method to false.
     *
     * @param string  $attribute The name of the attribute which value is to be used as a key
     * @param Boolean $remove    Whether or not to remove the key
     */
    public function setKeyAttribute($attribute, $remove = true)
    {
        $this->keyAttribute = $attribute;
        $this->removeKeyAttribute = $remove;
    }

    /**
     * Retrieves the name of the attribute which value should be used as key.
     *
     * @return string The name of the attribute
     */
    public function getKeyAttribute()
    {
        return $this->keyAttribute;
    }

    /**
     * Sets the default value of this node.
     *
     * @param string $value
     *
     * @throws \InvalidArgumentException if the default value is not an array
     */
    public function setDefaultValue($value)
    {
        if (!is_array($value)) {
            throw new \InvalidArgumentException($this->getPath().': the default value of an array node has to be an array.');
        }

        $this->defaultValue = $value;
    }

    /**
     * Checks if the node has a default value.
     *
     * @return Boolean
     */
    public function hasDefaultValue()
    {
        return true;
    }

    /**
     * Adds default children when none are set.
     *
     * @param integer|string|array|null $children The number of children|The child name|The children names to be added
     */
    public function setAddChildrenIfNoneSet($children = array('defaults'))
    {
        if (null === $children) {
            $this->defaultChildren = array('defaults');
        } else {
            $this->defaultChildren = is_integer($children) && $children > 0 ? range(1, $children) : (array) $children;
        }
    }

    /**
     * Retrieves the default value.
     *
     * The default value could be either explicited or derived from the prototype
     * default value.
     *
     * @return array The default value
     */
    public function getDefaultValue()
    {
        if (null !== $this->defaultChildren) {
            $default = $this->prototype->hasDefaultValue() ? $this->prototype->getDefaultValue() : array();
            $defaults = array();
            foreach (array_values($this->defaultChildren) as $i => $name) {
                $defaults[null === $this->keyAttribute ? $i : $name] = $default;
            }

            return $defaults;
        }

        return $this->defaultValue;
    }

    /**
     * Sets the node prototype.
     *
     * @param PrototypeNodeInterface $node
     */
    public function setPrototype(PrototypeNodeInterface $node)
    {
        $this->prototype = $node;
    }

    /**
     * Retrieves the prototype
     *
     * @return PrototypeNodeInterface The prototype
     */
    public function getPrototype()
    {
        return $this->prototype;
    }

    /**
     * Disable adding concrete children for prototyped nodes.
     *
     * @param NodeInterface $node The child node to add
     *
     * @throws Exception
     */
    public function addChild(NodeInterface $node)
    {
        throw new Exception('A prototyped array node can not have concrete children.');
    }

    /**
     * Finalizes the value of this node.
     *
     * @param mixed $value
     *
     * @return mixed The finalized value
     *
     * @throws UnsetKeyException
     * @throws InvalidConfigurationException if the node doesn't have enough children
     */
    protected function finalizeValue($value)
    {
        if (false === $value) {
            $msg = sprintf('Unsetting key for path "%s", value: %s', $this->getPath(), json_encode($value));
            throw new UnsetKeyException($msg);
        }

        foreach ($value as $k => $v) {
            $this->prototype->setName($k);
            try {
                $value[$k] = $this->prototype->finalize($v);
            } catch (UnsetKeyException $unset) {
                unset($value[$k]);
            }
        }

        if (count($value) < $this->minNumberOfElements) {
            $msg = sprintf('The path "%s" should have at least %d element(s) defined.', $this->getPath(), $this->minNumberOfElements);
            $ex = new InvalidConfigurationException($msg);
            $ex->setPath($this->getPath());

            throw $ex;
        }

        return $value;
    }

    /**
     * Normalizes the value.
     *
     * @param mixed $value The value to normalize
     *
     * @return mixed The normalized value
     *
     * @throws InvalidConfigurationException
     * @throws DuplicateKeyException
     */
    protected function normalizeValue($value)
    {
        if (false === $value) {
            return $value;
        }

        $value = $this->remapXml($value);

        $isAssoc = array_keys($value) !== range(0, count($value) -1);
        $normalized = array();
        foreach ($value as $k => $v) {
            if (null !== $this->keyAttribute && is_array($v)) {
                if (!isset($v[$this->keyAttribute]) && is_int($k) && !$isAssoc) {
                    $msg = sprintf('The attribute "%s" must be set for path "%s".', $this->keyAttribute, $this->getPath());
                    $ex = new InvalidConfigurationException($msg);
                    $ex->setPath($this->getPath());

                    throw $ex;
                } elseif (isset($v[$this->keyAttribute])) {
                    $k = $v[$this->keyAttribute];

                    // remove the key attribute when required
                    if ($this->removeKeyAttribute) {
                        unset($v[$this->keyAttribute]);
                    }

                    // if only "value" is left
                    if (1 == count($v) && isset($v['value'])) {
                        $v = $v['value'];
                    }
                }

                if (array_key_exists($k, $normalized)) {
                    $msg = sprintf('Duplicate key "%s" for path "%s".', $k, $this->getPath());
                    $ex = new DuplicateKeyException($msg);
                    $ex->setPath($this->getPath());

                    throw $ex;
                }
            }

            $this->prototype->setName($k);
            if (null !== $this->keyAttribute || $isAssoc) {
                $normalized[$k] = $this->prototype->normalize($v);
            } else {
                $normalized[] = $this->prototype->normalize($v);
            }
        }

        return $normalized;
    }

    /**
     * Merges values together.
     *
     * @param mixed $leftSide  The left side to merge.
     * @param mixed $rightSide The right side to merge.
     *
     * @return mixed The merged values
     *
     * @throws InvalidConfigurationException
     * @throws \RuntimeException
     */
    protected function mergeValues($leftSide, $rightSide)
    {
        if (false === $rightSide) {
            // if this is still false after the last config has been merged the
            // finalization pass will take care of removing this key entirely
            return false;
        }

        if (false === $leftSide || !$this->performDeepMerging) {
            return $rightSide;
        }

        foreach ($rightSide as $k => $v) {
            // prototype, and key is irrelevant, so simply append the element
            if (null === $this->keyAttribute) {
                $leftSide[] = $v;
                continue;
            }

            // no conflict
            if (!array_key_exists($k, $leftSide)) {
                if (!$this->allowNewKeys) {
                    $ex = new InvalidConfigurationException(sprintf(
                        'You are not allowed to define new elements for path "%s". ' .
                        'Please define all elements for this path in one config file.',
                        $this->getPath()
                    ));
                    $ex->setPath($this->getPath());

                    throw $ex;
                }

                $leftSide[$k] = $v;
                continue;
            }

            $this->prototype->setName($k);
            $leftSide[$k] = $this->prototype->merge($leftSide[$k], $v);
        }

        return $leftSide;
    }
}
PK��ZU��''1Symfony/Component/Config/Definition/Processor.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition;

/**
 * This class is the entry point for config normalization/merging/finalization.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class Processor
{
    /**
     * Processes an array of configurations.
     *
     * @param NodeInterface $configTree The node tree describing the configuration
     * @param array         $configs    An array of configuration items to process
     *
     * @return array The processed configuration
     */
    public function process(NodeInterface $configTree, array $configs)
    {
        $currentConfig = array();
        foreach ($configs as $config) {
            $config = $configTree->normalize($config);
            $currentConfig = $configTree->merge($currentConfig, $config);
        }

        return $configTree->finalize($currentConfig);
    }

    /**
     * Processes an array of configurations.
     *
     * @param ConfigurationInterface $configuration The configuration class
     * @param array                  $configs       An array of configuration items to process
     *
     * @return array The processed configuration
     */
    public function processConfiguration(ConfigurationInterface $configuration, array $configs)
    {
        return $this->process($configuration->getConfigTreeBuilder()->buildTree(), $configs);
    }

    /**
     * Normalizes a configuration entry.
     *
     * This method returns a normalize configuration array for a given key
     * to remove the differences due to the original format (YAML and XML mainly).
     *
     * Here is an example.
     *
     * The configuration in XML:
     *
     * <twig:extension>twig.extension.foo</twig:extension>
     * <twig:extension>twig.extension.bar</twig:extension>
     *
     * And the same configuration in YAML:
     *
     * extensions: ['twig.extension.foo', 'twig.extension.bar']
     *
     * @param array  $config A config array
     * @param string $key    The key to normalize
     * @param string $plural The plural form of the key if it is irregular
     *
     * @return array
     */
    public static function normalizeConfig($config, $key, $plural = null)
    {
        if (null === $plural) {
            $plural = $key.'s';
        }

        if (isset($config[$plural])) {
            return $config[$plural];
        }

        if (isset($config[$key])) {
            if (is_string($config[$key]) || !is_int(key($config[$key]))) {
                // only one
                return  array($config[$key]);
            }

            return  $config[$key];
        }

        return array();
    }
}
PK��Z�C����;Symfony/Component/Config/Definition/Exception/Exception.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Exception;

/**
 * Base exception for all configuration exceptions
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class Exception extends \RuntimeException
{
}
PK��Z5-���OSymfony/Component/Config/Definition/Exception/InvalidConfigurationException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Exception;

/**
 * A very general exception which can be thrown whenever non of the more specific
 * exceptions is suitable.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class InvalidConfigurationException extends Exception
{
    private $path;

    public function setPath($path)
    {
        $this->path = $path;
    }

    public function getPath()
    {
        return $this->path;
    }
}
PK��Z����CSymfony/Component/Config/Definition/Exception/UnsetKeyException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Exception;

/**
 * This exception is usually not encountered by the end-user, but only used
 * internally to signal the parent scope to unset a key.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class UnsetKeyException extends Exception
{
}
PK��Z��@��FSymfony/Component/Config/Definition/Exception/InvalidTypeException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Exception;

/**
 * This exception is thrown if an invalid type is encountered.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class InvalidTypeException extends InvalidConfigurationException
{
}
PK��Z]F4���LSymfony/Component/Config/Definition/Exception/InvalidDefinitionException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Exception;

/**
 * Thrown when an error is detected in a node Definition.
 *
 * @author Victor Berchet <victor.berchet@suumit.com>
 */
class InvalidDefinitionException extends Exception
{
}
PK��Z�|�EEGSymfony/Component/Config/Definition/Exception/DuplicateKeyException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Exception;

/**
 * This exception is thrown whenever the key of an array is not unique. This can
 * only be the case if the configuration is coming from an XML file.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class DuplicateKeyException extends InvalidConfigurationException
{
}
PK��Z�:2&QQMSymfony/Component/Config/Definition/Exception/ForbiddenOverwriteException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Exception;

/**
 * This exception is thrown when a configuration path is overwritten from a
 * subsequent configuration file, but the entry node specifically forbids this.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ForbiddenOverwriteException extends InvalidConfigurationException
{
}
PK��Z#
֕44DSymfony/Component/Config/Definition/Builder/NormalizationBuilder.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

/**
 * This class builds normalization conditions.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class NormalizationBuilder
{
    protected $node;
    public $before = array();
    public $remappings = array();

    /**
     * Constructor
     *
     * @param NodeDefinition $node The related node
     */
    public function __construct(NodeDefinition $node)
    {
        $this->node = $node;
    }

    /**
     * Registers a key to remap to its plural form.
     *
     * @param string $key    The key to remap
     * @param string $plural The plural of the key in case of irregular plural
     *
     * @return NormalizationBuilder
     */
    public function remap($key, $plural = null)
    {
        $this->remappings[] = array($key, null === $plural ? $key.'s' : $plural);

        return $this;
    }

    /**
     * Registers a closure to run before the normalization or an expression builder to build it if null is provided.
     *
     * @param \Closure $closure
     *
     * @return ExprBuilder|NormalizationBuilder
     */
    public function before(\Closure $closure = null)
    {
        if (null !== $closure) {
            $this->before[] = $closure;

            return $this;
        }

        return $this->before[] = new ExprBuilder($this->node);
    }
}
PK��ZV�hU��;Symfony/Component/Config/Definition/Builder/TreeBuilder.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

use Symfony\Component\Config\Definition\NodeInterface;

/**
 * This is the entry class for building a config tree.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class TreeBuilder implements NodeParentInterface
{
    protected $tree;
    protected $root;
    protected $builder;

    /**
     * Creates the root node.
     *
     * @param string      $name    The name of the root node
     * @param string      $type    The type of the root node
     * @param NodeBuilder $builder A custom node builder instance
     *
     * @return ArrayNodeDefinition|NodeDefinition The root node (as an ArrayNodeDefinition when the type is 'array')
     *
     * @throws \RuntimeException When the node type is not supported
     */
    public function root($name, $type = 'array', NodeBuilder $builder = null)
    {
        $builder = $builder ?: new NodeBuilder();

        return $this->root = $builder->node($name, $type)->setParent($this);
    }

    /**
     * Builds the tree.
     *
     * @return NodeInterface
     *
     * @throws \RuntimeException
     */
    public function buildTree()
    {
        if (null === $this->root) {
            throw new \RuntimeException('The configuration tree has no root node.');
        }
        if (null !== $this->tree) {
            return $this->tree;
        }

        return $this->tree = $this->root->getNode(true);
    }
}
PK��Z��ʍ��BSymfony/Component/Config/Definition/Builder/EnumNodeDefinition.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

use Symfony\Component\Config\Definition\EnumNode;

/**
 * Enum Node Definition.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class EnumNodeDefinition extends ScalarNodeDefinition
{
    private $values;

    public function values(array $values)
    {
        $values = array_unique($values);

        if (count($values) <= 1) {
            throw new \InvalidArgumentException('->values() must be called with at least two distinct values.');
        }

        $this->values = $values;

        return $this;
    }

    /**
     * Instantiate a Node
     *
     * @return EnumNode The node
     *
     * @throws \RuntimeException
     */
    protected function instantiateNode()
    {
        if (null === $this->values) {
            throw new \RuntimeException('You must call ->values() on enum nodes.');
        }

        return new EnumNode($this->name, $this->parent, $this->values);
    }
}
PK��Z���{{<Symfony/Component/Config/Definition/Builder/MergeBuilder.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

/**
 * This class builds merge conditions.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class MergeBuilder
{
    protected $node;
    public $allowFalse = false;
    public $allowOverwrite = true;

    /**
     * Constructor
     *
     * @param NodeDefinition $node The related node
     */
    public function __construct(NodeDefinition $node)
    {
        $this->node = $node;
    }

    /**
     * Sets whether the node can be unset.
     *
     * @param Boolean $allow
     *
     * @return MergeBuilder
     */
    public function allowUnset($allow = true)
    {
        $this->allowFalse = $allow;

        return $this;
    }

    /**
     * Sets whether the node can be overwritten.
     *
     * @param Boolean $deny Whether the overwriting is forbidden or not
     *
     * @return MergeBuilder
     */
    public function denyOverwrite($deny = true)
    {
        $this->allowOverwrite = !$deny;

        return $this;
    }

    /**
     * Returns the related node.
     *
     * @return NodeDefinition
     */
    public function end()
    {
        return $this->node;
    }
}
PK��Z,��l[[ASymfony/Component/Config/Definition/Builder/ValidationBuilder.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

/**
 * This class builds validation conditions.
 *
 * @author Christophe Coevoet <stof@notk.org>
 */
class ValidationBuilder
{
    protected $node;
    public $rules = array();

    /**
     * Constructor
     *
     * @param NodeDefinition $node The related node
     */
    public function __construct(NodeDefinition $node)
    {
        $this->node = $node;
    }

    /**
     * Registers a closure to run as normalization or an expression builder to build it if null is provided.
     *
     * @param \Closure $closure
     *
     * @return ExprBuilder|ValidationBuilder
     */
    public function rule(\Closure $closure = null)
    {
        if (null !== $closure) {
            $this->rules[] = $closure;

            return $this;
        }

        return $this->rules[] = new ExprBuilder($this->node);
    }
}
PK��ZP����ESymfony/Component/Config/Definition/Builder/BooleanNodeDefinition.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

use Symfony\Component\Config\Definition\BooleanNode;

/**
 * This class provides a fluent interface for defining a node.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class BooleanNodeDefinition extends ScalarNodeDefinition
{
    /**
     * {@inheritDoc}
     */
    public function __construct($name, NodeParentInterface $parent = null)
    {
        parent::__construct($name, $parent);

        $this->nullEquivalent = true;
    }

    /**
     * Instantiate a Node
     *
     * @return BooleanNode The node
     */
    protected function instantiateNode()
    {
        return new BooleanNode($this->name, $this->parent);
    }

}
PK��Z�e�@��FSymfony/Component/Config/Definition/Builder/VariableNodeDefinition.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

use Symfony\Component\Config\Definition\VariableNode;

/**
 * This class provides a fluent interface for defining a node.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class VariableNodeDefinition extends NodeDefinition
{
    /**
     * Instantiate a Node
     *
     * @return VariableNode The node
     */
    protected function instantiateNode()
    {
        return new VariableNode($this->name, $this->parent);
    }

    /**
     * {@inheritDoc}
     */
    protected function createNode()
    {
        $node = $this->instantiateNode();

        if (null !== $this->normalization) {
            $node->setNormalizationClosures($this->normalization->before);
        }

        if (null !== $this->merge) {
            $node->setAllowOverwrite($this->merge->allowOverwrite);
        }

        if (true === $this->default) {
            $node->setDefaultValue($this->defaultValue);
        }

        $node->setAllowEmptyValue($this->allowEmptyValue);
        $node->addEquivalentValue(null, $this->nullEquivalent);
        $node->addEquivalentValue(true, $this->trueEquivalent);
        $node->addEquivalentValue(false, $this->falseEquivalent);
        $node->setRequired($this->required);

        if (null !== $this->validation) {
            $node->setFinalValidationClosures($this->validation->rules);
        }

        return $node;
    }

}
PK��Z��8�8CSymfony/Component/Config/Definition/Builder/ArrayNodeDefinition.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

use Symfony\Component\Config\Definition\ArrayNode;
use Symfony\Component\Config\Definition\PrototypedArrayNode;
use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException;

/**
 * This class provides a fluent interface for defining an array node.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinitionInterface
{
    protected $performDeepMerging = true;
    protected $ignoreExtraKeys = false;
    protected $children = array();
    protected $prototype;
    protected $atLeastOne = false;
    protected $allowNewKeys = true;
    protected $key;
    protected $removeKeyItem;
    protected $addDefaults = false;
    protected $addDefaultChildren = false;
    protected $nodeBuilder;
    protected $normalizeKeys = true;

    /**
     * {@inheritDoc}
     */
    public function __construct($name, NodeParentInterface $parent = null)
    {
        parent::__construct($name, $parent);

        $this->nullEquivalent = array();
        $this->trueEquivalent = array();
    }

    /**
     * Sets a custom children builder.
     *
     * @param NodeBuilder $builder A custom NodeBuilder
     */
    public function setBuilder(NodeBuilder $builder)
    {
        $this->nodeBuilder = $builder;
    }

    /**
     * Returns a builder to add children nodes.
     *
     * @return NodeBuilder
     */
    public function children()
    {
        return $this->getNodeBuilder();
    }

    /**
     * Sets a prototype for child nodes.
     *
     * @param string $type the type of node
     *
     * @return NodeDefinition
     */
    public function prototype($type)
    {
        return $this->prototype = $this->getNodeBuilder()->node(null, $type)->setParent($this);
    }

    /**
     * Adds the default value if the node is not set in the configuration.
     *
     * This method is applicable to concrete nodes only (not to prototype nodes).
     * If this function has been called and the node is not set during the finalization
     * phase, it's default value will be derived from its children default values.
     *
     * @return ArrayNodeDefinition
     */
    public function addDefaultsIfNotSet()
    {
        $this->addDefaults = true;

        return $this;
    }

    /**
     * Adds children with a default value when none are defined.
     *
     * @param integer|string|array|null $children The number of children|The child name|The children names to be added
     *
     * This method is applicable to prototype nodes only.
     *
     * @return ArrayNodeDefinition
     */
    public function addDefaultChildrenIfNoneSet($children = null)
    {
        $this->addDefaultChildren = $children;

        return $this;
    }

    /**
     * Requires the node to have at least one element.
     *
     * This method is applicable to prototype nodes only.
     *
     * @return ArrayNodeDefinition
     */
    public function requiresAtLeastOneElement()
    {
        $this->atLeastOne = true;

        return $this;
    }

    /**
     * Disallows adding news keys in a subsequent configuration.
     *
     * If used all keys have to be defined in the same configuration file.
     *
     * @return ArrayNodeDefinition
     */
    public function disallowNewKeysInSubsequentConfigs()
    {
        $this->allowNewKeys = false;

        return $this;
    }

    /**
     * Sets a normalization rule for XML configurations.
     *
     * @param string $singular The key to remap
     * @param string $plural   The plural of the key for irregular plurals
     *
     * @return ArrayNodeDefinition
     */
    public function fixXmlConfig($singular, $plural = null)
    {
        $this->normalization()->remap($singular, $plural);

        return $this;
    }

    /**
     * Sets the attribute which value is to be used as key.
     *
     * This is useful when you have an indexed array that should be an
     * associative array. You can select an item from within the array
     * to be the key of the particular item. For example, if "id" is the
     * "key", then:
     *
     *     array(
     *         array('id' => 'my_name', 'foo' => 'bar'),
     *     );
     *
     *   becomes
     *
     *     array(
     *         'my_name' => array('foo' => 'bar'),
     *     );
     *
     * If you'd like "'id' => 'my_name'" to still be present in the resulting
     * array, then you can set the second argument of this method to false.
     *
     * This method is applicable to prototype nodes only.
     *
     * @param string  $name          The name of the key
     * @param Boolean $removeKeyItem Whether or not the key item should be removed.
     *
     * @return ArrayNodeDefinition
     */
    public function useAttributeAsKey($name, $removeKeyItem = true)
    {
        $this->key = $name;
        $this->removeKeyItem = $removeKeyItem;

        return $this;
    }

    /**
     * Sets whether the node can be unset.
     *
     * @param Boolean $allow
     *
     * @return ArrayNodeDefinition
     */
    public function canBeUnset($allow = true)
    {
        $this->merge()->allowUnset($allow);

        return $this;
    }

    /**
     * Adds an "enabled" boolean to enable the current section.
     *
     * By default, the section is disabled. If any configuration is specified then
     * the node will be automatically enabled:
     *
     * enableableArrayNode: {enabled: true, ...}   # The config is enabled & default values get overridden
     * enableableArrayNode: ~                      # The config is enabled & use the default values
     * enableableArrayNode: true                   # The config is enabled & use the default values
     * enableableArrayNode: {other: value, ...}    # The config is enabled & default values get overridden
     * enableableArrayNode: {enabled: false, ...}  # The config is disabled
     * enableableArrayNode: false                  # The config is disabled
     *
     * @return ArrayNodeDefinition
     */
    public function canBeEnabled()
    {
        $this
            ->addDefaultsIfNotSet()
            ->treatFalseLike(array('enabled' => false))
            ->treatTrueLike(array('enabled' => true))
            ->treatNullLike(array('enabled' => true))
            ->beforeNormalization()
                ->ifArray()
                ->then(function ($v) {
                    $v['enabled'] = isset($v['enabled']) ? $v['enabled'] : true;

                    return $v;
                })
            ->end()
            ->children()
                ->booleanNode('enabled')
                    ->defaultFalse()
        ;

        return $this;
    }

    /**
     * Adds an "enabled" boolean to enable the current section.
     *
     * By default, the section is enabled.
     *
     * @return ArrayNodeDefinition
     */
    public function canBeDisabled()
    {
        $this
            ->addDefaultsIfNotSet()
            ->treatFalseLike(array('enabled' => false))
            ->treatTrueLike(array('enabled' => true))
            ->treatNullLike(array('enabled' => true))
            ->children()
                ->booleanNode('enabled')
                    ->defaultTrue()
        ;

        return $this;
    }

    /**
     * Disables the deep merging of the node.
     *
     * @return ArrayNodeDefinition
     */
    public function performNoDeepMerging()
    {
        $this->performDeepMerging = false;

        return $this;
    }

    /**
     * Allows extra config keys to be specified under an array without
     * throwing an exception.
     *
     * Those config values are simply ignored. This should be used only
     * in special cases where you want to send an entire configuration
     * array through a special tree that processes only part of the array.
     *
     * @return ArrayNodeDefinition
     */
    public function ignoreExtraKeys()
    {
        $this->ignoreExtraKeys = true;

        return $this;
    }

    /**
     * Sets key normalization.
     *
     * @param Boolean $bool Whether to enable key normalization
     *
     * @return ArrayNodeDefinition
     */
    public function normalizeKeys($bool)
    {
        $this->normalizeKeys = (Boolean) $bool;

        return $this;
    }

    /**
     * Appends a node definition.
     *
     *     $node = new ArrayNodeDefinition()
     *         ->children()
     *             ->scalarNode('foo')->end()
     *             ->scalarNode('baz')->end()
     *         ->end()
     *         ->append($this->getBarNodeDefinition())
     *     ;
     *
     * @param NodeDefinition $node A NodeDefinition instance
     *
     * @return ArrayNodeDefinition This node
     */
    public function append(NodeDefinition $node)
    {
        $this->children[$node->name] = $node->setParent($this);

        return $this;
    }

    /**
     * Returns a node builder to be used to add children and prototype
     *
     * @return NodeBuilder The node builder
     */
    protected function getNodeBuilder()
    {
        if (null === $this->nodeBuilder) {
            $this->nodeBuilder = new NodeBuilder();
        }

        return $this->nodeBuilder->setParent($this);
    }

    /**
     * {@inheritDoc}
     */
    protected function createNode()
    {
        if (null === $this->prototype) {
            $node = new ArrayNode($this->name, $this->parent);

            $this->validateConcreteNode($node);

            $node->setAddIfNotSet($this->addDefaults);

            foreach ($this->children as $child) {
                $child->parent = $node;
                $node->addChild($child->getNode());
            }
        } else {
            $node = new PrototypedArrayNode($this->name, $this->parent);

            $this->validatePrototypeNode($node);

            if (null !== $this->key) {
                $node->setKeyAttribute($this->key, $this->removeKeyItem);
            }

            if (true === $this->atLeastOne) {
                $node->setMinNumberOfElements(1);
            }

            if ($this->default) {
                $node->setDefaultValue($this->defaultValue);
            }

            if (false !== $this->addDefaultChildren) {
                $node->setAddChildrenIfNoneSet($this->addDefaultChildren);
                if ($this->prototype instanceof static && null === $this->prototype->prototype) {
                    $this->prototype->addDefaultsIfNotSet();
                }
            }

            $this->prototype->parent = $node;
            $node->setPrototype($this->prototype->getNode());
        }

        $node->setAllowNewKeys($this->allowNewKeys);
        $node->addEquivalentValue(null, $this->nullEquivalent);
        $node->addEquivalentValue(true, $this->trueEquivalent);
        $node->addEquivalentValue(false, $this->falseEquivalent);
        $node->setPerformDeepMerging($this->performDeepMerging);
        $node->setRequired($this->required);
        $node->setIgnoreExtraKeys($this->ignoreExtraKeys);
        $node->setNormalizeKeys($this->normalizeKeys);

        if (null !== $this->normalization) {
            $node->setNormalizationClosures($this->normalization->before);
            $node->setXmlRemappings($this->normalization->remappings);
        }

        if (null !== $this->merge) {
            $node->setAllowOverwrite($this->merge->allowOverwrite);
            $node->setAllowFalse($this->merge->allowFalse);
        }

        if (null !== $this->validation) {
            $node->setFinalValidationClosures($this->validation->rules);
        }

        return $node;
    }

    /**
     * Validate the configuration of a concrete node.
     *
     * @param ArrayNode $node The related node
     *
     * @throws InvalidDefinitionException
     */
    protected function validateConcreteNode(ArrayNode $node)
    {
        $path = $node->getPath();

        if (null !== $this->key) {
            throw new InvalidDefinitionException(
                sprintf('->useAttributeAsKey() is not applicable to concrete nodes at path "%s"', $path)
            );
        }

        if (true === $this->atLeastOne) {
            throw new InvalidDefinitionException(
                sprintf('->requiresAtLeastOneElement() is not applicable to concrete nodes at path "%s"', $path)
            );
        }

        if ($this->default) {
            throw new InvalidDefinitionException(
                sprintf('->defaultValue() is not applicable to concrete nodes at path "%s"', $path)
            );
        }

        if (false !== $this->addDefaultChildren) {
            throw new InvalidDefinitionException(
                sprintf('->addDefaultChildrenIfNoneSet() is not applicable to concrete nodes at path "%s"', $path)
            );
        }
    }

    /**
     * Validate the configuration of a prototype node.
     *
     * @param PrototypedArrayNode $node The related node
     *
     * @throws InvalidDefinitionException
     */
    protected function validatePrototypeNode(PrototypedArrayNode $node)
    {
        $path = $node->getPath();

        if ($this->addDefaults) {
            throw new InvalidDefinitionException(
                sprintf('->addDefaultsIfNotSet() is not applicable to prototype nodes at path "%s"', $path)
            );
        }

        if (false !== $this->addDefaultChildren) {
            if ($this->default) {
                throw new InvalidDefinitionException(
                    sprintf('A default value and default children might not be used together at path "%s"', $path)
                );
            }

            if (null !== $this->key && (null === $this->addDefaultChildren || is_integer($this->addDefaultChildren) && $this->addDefaultChildren > 0)) {
                throw new InvalidDefinitionException(
                    sprintf('->addDefaultChildrenIfNoneSet() should set default children names as ->useAttributeAsKey() is used at path "%s"', $path)
                );
            }

            if (null === $this->key && (is_string($this->addDefaultChildren) || is_array($this->addDefaultChildren))) {
                throw new InvalidDefinitionException(
                    sprintf('->addDefaultChildrenIfNoneSet() might not set default children names as ->useAttributeAsKey() is not used at path "%s"', $path)
                );
            }
        }
    }
}
PK��Z �"�$$;Symfony/Component/Config/Definition/Builder/ExprBuilder.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

use Symfony\Component\Config\Definition\Exception\UnsetKeyException;

/**
 * This class builds an if expression.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Christophe Coevoet <stof@notk.org>
 */
class ExprBuilder
{
    protected $node;
    public $ifPart;
    public $thenPart;

    /**
     * Constructor
     *
     * @param NodeDefinition $node The related node
     */
    public function __construct(NodeDefinition $node)
    {
        $this->node = $node;
    }

    /**
     * Marks the expression as being always used.
     *
     * @param \Closure $then
     *
     * @return ExprBuilder
     */
    public function always(\Closure $then = null)
    {
        $this->ifPart = function ($v) { return true; };

        if (null !== $then) {
            $this->thenPart = $then;
        }

        return $this;
    }

    /**
     * Sets a closure to use as tests.
     *
     * The default one tests if the value is true.
     *
     * @param \Closure $closure
     *
     * @return ExprBuilder
     */
    public function ifTrue(\Closure $closure = null)
    {
        if (null === $closure) {
            $closure = function ($v) { return true === $v; };
        }

        $this->ifPart = $closure;

        return $this;
    }

    /**
     * Tests if the value is a string.
     *
     * @return ExprBuilder
     */
    public function ifString()
    {
        $this->ifPart = function ($v) { return is_string($v); };

        return $this;
    }

    /**
     * Tests if the value is null.
     *
     * @return ExprBuilder
     */
    public function ifNull()
    {
        $this->ifPart = function ($v) { return null === $v; };

        return $this;
    }

    /**
     * Tests if the value is an array.
     *
     * @return ExprBuilder
     */
    public function ifArray()
    {
        $this->ifPart = function ($v) { return is_array($v); };

        return $this;
    }

    /**
     * Tests if the value is in an array.
     *
     * @param array $array
     *
     * @return ExprBuilder
     */
    public function ifInArray(array $array)
    {
        $this->ifPart = function ($v) use ($array) { return in_array($v, $array, true); };

        return $this;
    }

    /**
     * Tests if the value is not in an array.
     *
     * @param array $array
     *
     * @return ExprBuilder
     */
    public function ifNotInArray(array $array)
    {
        $this->ifPart = function ($v) use ($array) { return !in_array($v, $array, true); };

        return $this;
    }

    /**
     * Sets the closure to run if the test pass.
     *
     * @param \Closure $closure
     *
     * @return ExprBuilder
     */
    public function then(\Closure $closure)
    {
        $this->thenPart = $closure;

        return $this;
    }

    /**
     * Sets a closure returning an empty array.
     *
     * @return ExprBuilder
     */
    public function thenEmptyArray()
    {
        $this->thenPart = function ($v) { return array(); };

        return $this;
    }

    /**
     * Sets a closure marking the value as invalid at validation time.
     *
     * if you want to add the value of the node in your message just use a %s placeholder.
     *
     * @param string $message
     *
     * @return ExprBuilder
     *
     * @throws \InvalidArgumentException
     */
    public function thenInvalid($message)
    {
        $this->thenPart = function ($v) use ($message) {throw new \InvalidArgumentException(sprintf($message, json_encode($v))); };

        return $this;
    }

    /**
     * Sets a closure unsetting this key of the array at validation time.
     *
     * @return ExprBuilder
     *
     * @throws UnsetKeyException
     */
    public function thenUnset()
    {
        $this->thenPart = function ($v) { throw new UnsetKeyException('Unsetting key'); };

        return $this;
    }

    /**
     * Returns the related node
     *
     * @return NodeDefinition
     *
     * @throws \RuntimeException
     */
    public function end()
    {
        if (null === $this->ifPart) {
            throw new \RuntimeException('You must specify an if part.');
        }
        if (null === $this->thenPart) {
            throw new \RuntimeException('You must specify a then part.');
        }

        return $this->node;
    }

    /**
     * Builds the expressions.
     *
     * @param ExprBuilder[] $expressions An array of ExprBuilder instances to build
     *
     * @return array
     */
    public static function buildExpressions(array $expressions)
    {
        foreach ($expressions as $k => $expr) {
            if ($expr instanceof ExprBuilder) {
                $expressions[$k] = function ($v) use ($expr) {
                    return call_user_func($expr->ifPart, $v) ? call_user_func($expr->thenPart, $v) : $v;
                };
            }
        }

        return $expressions;
    }
}
PK��Z�3d�__MSymfony/Component/Config/Definition/Builder/ParentNodeDefinitionInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

/**
 * An interface that must be implemented by nodes which can have children
 *
 * @author Victor Berchet <victor@suumit.com>
 */
interface ParentNodeDefinitionInterface
{
    public function children();

    public function append(NodeDefinition $node);

    public function setBuilder(NodeBuilder $builder);
}
PK��Z�mc��DSymfony/Component/Config/Definition/Builder/ScalarNodeDefinition.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

use Symfony\Component\Config\Definition\ScalarNode;

/**
 * This class provides a fluent interface for defining a node.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ScalarNodeDefinition extends VariableNodeDefinition
{
    /**
     * Instantiate a Node
     *
     * @return ScalarNode The node
     */
    protected function instantiateNode()
    {
        return new ScalarNode($this->name, $this->parent);
    }
}
PK��Z'nڭESymfony/Component/Config/Definition/Builder/IntegerNodeDefinition.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

use Symfony\Component\Config\Definition\IntegerNode;

/**
 * This class provides a fluent interface for defining an integer node.
 *
 * @author Jeanmonod David <david.jeanmonod@gmail.com>
 */
class IntegerNodeDefinition extends NumericNodeDefinition
{
    /**
     * Instantiates a Node.
     *
     * @return IntegerNode The node
     */
    protected function instantiateNode()
    {
        return new IntegerNode($this->name, $this->parent, $this->min, $this->max);
    }
}
PK��Zt�p��CSymfony/Component/Config/Definition/Builder/FloatNodeDefinition.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

use Symfony\Component\Config\Definition\FloatNode;

/**
 * This class provides a fluent interface for defining a float node.
 *
 * @author Jeanmonod David <david.jeanmonod@gmail.com>
 */
class FloatNodeDefinition extends NumericNodeDefinition
{
    /**
     * Instantiates a Node.
     *
     * @return FloatNode The node
     */
    protected function instantiateNode()
    {
        return new FloatNode($this->name, $this->parent, $this->min, $this->max);
    }
}
PK��ZU��=��CSymfony/Component/Config/Definition/Builder/NodeParentInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

/**
 * An interface that must be implemented by all node parents
 *
 * @author Victor Berchet <victor@suumit.com>
 */
interface NodeParentInterface
{
}
PK��Z �}��;Symfony/Component/Config/Definition/Builder/NodeBuilder.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

/**
 * This class provides a fluent interface for building a node.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class NodeBuilder implements NodeParentInterface
{
    protected $parent;
    protected $nodeMapping;

    /**
     * Constructor
     *
     */
    public function __construct()
    {
        $this->nodeMapping = array(
            'variable'    => __NAMESPACE__.'\\VariableNodeDefinition',
            'scalar'      => __NAMESPACE__.'\\ScalarNodeDefinition',
            'boolean'     => __NAMESPACE__.'\\BooleanNodeDefinition',
            'integer'     => __NAMESPACE__.'\\IntegerNodeDefinition',
            'float'       => __NAMESPACE__.'\\FloatNodeDefinition',
            'array'       => __NAMESPACE__.'\\ArrayNodeDefinition',
            'enum'        => __NAMESPACE__.'\\EnumNodeDefinition',
        );
    }

    /**
     * Set the parent node.
     *
     * @param ParentNodeDefinitionInterface $parent The parent node
     *
     * @return NodeBuilder This node builder
     */
    public function setParent(ParentNodeDefinitionInterface $parent = null)
    {
        $this->parent = $parent;

        return $this;
    }

    /**
     * Creates a child array node.
     *
     * @param string $name The name of the node
     *
     * @return ArrayNodeDefinition The child node
     */
    public function arrayNode($name)
    {
        return $this->node($name, 'array');
    }

    /**
     * Creates a child scalar node.
     *
     * @param string $name the name of the node
     *
     * @return ScalarNodeDefinition The child node
     */
    public function scalarNode($name)
    {
        return $this->node($name, 'scalar');
    }

    /**
     * Creates a child Boolean node.
     *
     * @param string $name The name of the node
     *
     * @return BooleanNodeDefinition The child node
     */
    public function booleanNode($name)
    {
        return $this->node($name, 'boolean');
    }

    /**
     * Creates a child integer node.
     *
     * @param string $name the name of the node
     *
     * @return IntegerNodeDefinition The child node
     */
    public function integerNode($name)
    {
        return $this->node($name, 'integer');
    }

    /**
     * Creates a child float node.
     *
     * @param string $name the name of the node
     *
     * @return FloatNodeDefinition The child node
     */
    public function floatNode($name)
    {
        return $this->node($name, 'float');
    }

    /**
     * Creates a child EnumNode.
     *
     * @param string $name
     *
     * @return EnumNodeDefinition
     */
    public function enumNode($name)
    {
        return $this->node($name, 'enum');
    }

    /**
     * Creates a child variable node.
     *
     * @param string $name The name of the node
     *
     * @return VariableNodeDefinition The builder of the child node
     */
    public function variableNode($name)
    {
        return $this->node($name, 'variable');
    }

    /**
     * Returns the parent node.
     *
     * @return ParentNodeDefinitionInterface The parent node
     */
    public function end()
    {
        return $this->parent;
    }

    /**
     * Creates a child node.
     *
     * @param string $name The name of the node
     * @param string $type The type of the node
     *
     * @return NodeDefinition The child node
     *
     * @throws \RuntimeException When the node type is not registered
     * @throws \RuntimeException When the node class is not found
     */
    public function node($name, $type)
    {
        $class = $this->getNodeClass($type);

        $node = new $class($name);

        $this->append($node);

        return $node;
    }

    /**
     * Appends a node definition.
     *
     * Usage:
     *
     *     $node = new ArrayNodeDefinition('name')
     *         ->children()
     *             ->scalarNode('foo')->end()
     *             ->scalarNode('baz')->end()
     *             ->append($this->getBarNodeDefinition())
     *         ->end()
     *     ;
     *
     * @param NodeDefinition $node
     *
     * @return NodeBuilder This node builder
     */
    public function append(NodeDefinition $node)
    {
        if ($node instanceof ParentNodeDefinitionInterface) {
            $builder = clone $this;
            $builder->setParent(null);
            $node->setBuilder($builder);
        }

        if (null !== $this->parent) {
            $this->parent->append($node);
            // Make this builder the node parent to allow for a fluid interface
            $node->setParent($this);
        }

        return $this;
    }

    /**
     * Adds or overrides a node Type.
     *
     * @param string $type  The name of the type
     * @param string $class The fully qualified name the node definition class
     *
     * @return NodeBuilder This node builder
     */
    public function setNodeClass($type, $class)
    {
        $this->nodeMapping[strtolower($type)] = $class;

        return $this;
    }

    /**
     * Returns the class name of the node definition.
     *
     * @param string $type The node type
     *
     * @return string The node definition class name
     *
     * @throws \RuntimeException When the node type is not registered
     * @throws \RuntimeException When the node class is not found
     */
    protected function getNodeClass($type)
    {
        $type = strtolower($type);

        if (!isset($this->nodeMapping[$type])) {
            throw new \RuntimeException(sprintf('The node type "%s" is not registered.', $type));
        }

        $class = $this->nodeMapping[$type];

        if (!class_exists($class)) {
            throw new \RuntimeException(sprintf('The node class "%s" does not exist.', $class));
        }

        return $class;
    }

}
PK��Z~�G�XXESymfony/Component/Config/Definition/Builder/NumericNodeDefinition.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

/**
 * Abstract class that contain common code of integer and float node definition.
 *
 * @author David Jeanmonod <david.jeanmonod@gmail.com>
 */
abstract class NumericNodeDefinition extends ScalarNodeDefinition
{
    protected $min;
    protected $max;

    /**
     * Ensures that the value is smaller than the given reference.
     *
     * @param mixed $max
     *
     * @return NumericNodeDefinition
     *
     * @throws \InvalidArgumentException when the constraint is inconsistent
     */
    public function max($max)
    {
        if (isset($this->min) && $this->min > $max) {
            throw new \InvalidArgumentException(sprintf('You cannot define a max(%s) as you already have a min(%s)', $max, $this->min));
        }
        $this->max = $max;

        return $this;
    }

    /**
     * Ensures that the value is bigger than the given reference.
     *
     * @param mixed $min
     *
     * @return NumericNodeDefinition
     *
     * @throws \InvalidArgumentException when the constraint is inconsistent
     */
    public function min($min)
    {
        if (isset($this->max) && $this->max < $min) {
            throw new \InvalidArgumentException(sprintf('You cannot define a min(%s) as you already have a max(%s)', $min, $this->max));
        }
        $this->min = $min;

        return $this;
    }
}
PK��Z��K��>Symfony/Component/Config/Definition/Builder/NodeDefinition.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

use Symfony\Component\Config\Definition\NodeInterface;
use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException;

/**
 * This class provides a fluent interface for defining a node.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
abstract class NodeDefinition implements NodeParentInterface
{
    protected $name;
    protected $normalization;
    protected $validation;
    protected $defaultValue;
    protected $default = false;
    protected $required = false;
    protected $merge;
    protected $allowEmptyValue = true;
    protected $nullEquivalent;
    protected $trueEquivalent = true;
    protected $falseEquivalent = false;

    /**
     * @var NodeParentInterface|null
     */
    protected $parent;
    protected $attributes = array();

    /**
     * Constructor
     *
     * @param string                   $name   The name of the node
     * @param NodeParentInterface|null $parent The parent
     */
    public function __construct($name, NodeParentInterface $parent = null)
    {
        $this->parent = $parent;
        $this->name = $name;
    }

    /**
     * Sets the parent node.
     *
     * @param NodeParentInterface $parent The parent
     *
     * @return NodeDefinition
     */
    public function setParent(NodeParentInterface $parent)
    {
        $this->parent = $parent;

        return $this;
    }

    /**
     * Sets info message.
     *
     * @param string $info The info text
     *
     * @return NodeDefinition
     */
    public function info($info)
    {
        return $this->attribute('info', $info);
    }

    /**
     * Sets example configuration.
     *
     * @param string|array $example
     *
     * @return NodeDefinition
     */
    public function example($example)
    {
        return $this->attribute('example', $example);
    }

    /**
     * Sets an attribute on the node.
     *
     * @param string $key
     * @param mixed $value
     *
     * @return NodeDefinition
     */
    public function attribute($key, $value)
    {
        $this->attributes[$key] = $value;

        return $this;
    }

    /**
     * Returns the parent node.
     *
     * @return NodeParentInterface|null The builder of the parent node
     */
    public function end()
    {
        return $this->parent;
    }

    /**
     * Creates the node.
     *
     * @param Boolean $forceRootNode Whether to force this node as the root node
     *
     * @return NodeInterface
     */
    public function getNode($forceRootNode = false)
    {
        if ($forceRootNode) {
            $this->parent = null;
        }

        if (null !== $this->normalization) {
            $this->normalization->before = ExprBuilder::buildExpressions($this->normalization->before);
        }

        if (null !== $this->validation) {
            $this->validation->rules = ExprBuilder::buildExpressions($this->validation->rules);
        }

        $node = $this->createNode();
        $node->setAttributes($this->attributes);

        return $node;
    }

    /**
     * Sets the default value.
     *
     * @param mixed $value The default value
     *
     * @return NodeDefinition
     */
    public function defaultValue($value)
    {
        $this->default = true;
        $this->defaultValue = $value;

        return $this;
    }

    /**
     * Sets the node as required.
     *
     * @return NodeDefinition
     */
    public function isRequired()
    {
        $this->required = true;

        return $this;
    }

    /**
     * Sets the equivalent value used when the node contains null.
     *
     * @param mixed $value
     *
     * @return NodeDefinition
     */
    public function treatNullLike($value)
    {
        $this->nullEquivalent = $value;

        return $this;
    }

    /**
     * Sets the equivalent value used when the node contains true.
     *
     * @param mixed $value
     *
     * @return NodeDefinition
     */
    public function treatTrueLike($value)
    {
        $this->trueEquivalent = $value;

        return $this;
    }

    /**
     * Sets the equivalent value used when the node contains false.
     *
     * @param mixed $value
     *
     * @return NodeDefinition
     */
    public function treatFalseLike($value)
    {
        $this->falseEquivalent = $value;

        return $this;
    }

    /**
     * Sets null as the default value.
     *
     * @return NodeDefinition
     */
    public function defaultNull()
    {
        return $this->defaultValue(null);
    }

    /**
     * Sets true as the default value.
     *
     * @return NodeDefinition
     */
    public function defaultTrue()
    {
        return $this->defaultValue(true);
    }

    /**
     * Sets false as the default value.
     *
     * @return NodeDefinition
     */
    public function defaultFalse()
    {
        return $this->defaultValue(false);
    }

    /**
     * Sets an expression to run before the normalization.
     *
     * @return ExprBuilder
     */
    public function beforeNormalization()
    {
        return $this->normalization()->before();
    }

    /**
     * Denies the node value being empty.
     *
     * @return NodeDefinition
     */
    public function cannotBeEmpty()
    {
        $this->allowEmptyValue = false;

        return $this;
    }

    /**
     * Sets an expression to run for the validation.
     *
     * The expression receives the value of the node and must return it. It can
     * modify it.
     * An exception should be thrown when the node is not valid.
     *
     * @return ExprBuilder
     */
    public function validate()
    {
        return $this->validation()->rule();
    }

    /**
     * Sets whether the node can be overwritten.
     *
     * @param Boolean $deny Whether the overwriting is forbidden or not
     *
     * @return NodeDefinition
     */
    public function cannotBeOverwritten($deny = true)
    {
        $this->merge()->denyOverwrite($deny);

        return $this;
    }

    /**
     * Gets the builder for validation rules.
     *
     * @return ValidationBuilder
     */
    protected function validation()
    {
        if (null === $this->validation) {
            $this->validation = new ValidationBuilder($this);
        }

        return $this->validation;
    }

    /**
     * Gets the builder for merging rules.
     *
     * @return MergeBuilder
     */
    protected function merge()
    {
        if (null === $this->merge) {
            $this->merge = new MergeBuilder($this);
        }

        return $this->merge;
    }

    /**
     * Gets the builder for normalization rules.
     *
     * @return NormalizationBuilder
     */
    protected function normalization()
    {
        if (null === $this->normalization) {
            $this->normalization = new NormalizationBuilder($this);
        }

        return $this->normalization;
    }

    /**
     * Instantiate and configure the node according to this definition
     *
     * @return NodeInterface $node The node instance
     *
     * @throws InvalidDefinitionException When the definition is invalid
     */
    abstract protected function createNode();

}
PK��Z����3Symfony/Component/Config/Definition/BooleanNode.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition;

use Symfony\Component\Config\Definition\Exception\InvalidTypeException;

/**
 * This node represents a Boolean value in the config tree.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class BooleanNode extends ScalarNode
{
    /**
     * {@inheritDoc}
     */
    protected function validateType($value)
    {
        if (!is_bool($value)) {
            $ex = new InvalidTypeException(sprintf(
                'Invalid type for path "%s". Expected boolean, but got %s.',
                $this->getPath(),
                gettype($value)
            ));
            $ex->setPath($this->getPath());

            throw $ex;
        }
    }
}
PK��Z�+;;2Symfony/Component/Config/Definition/ScalarNode.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition;

use Symfony\Component\Config\Definition\Exception\InvalidTypeException;

/**
 * This node represents a scalar value in the config tree.
 *
 * The following values are considered scalars:
 *   * booleans
 *   * strings
 *   * null
 *   * integers
 *   * floats
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ScalarNode extends VariableNode
{
    /**
     * {@inheritDoc}
     */
    protected function validateType($value)
    {
        if (!is_scalar($value) && null !== $value) {
            $ex = new InvalidTypeException(sprintf(
                'Invalid type for path "%s". Expected scalar, but got %s.',
                $this->getPath(),
                gettype($value)
            ));
            $ex->setPath($this->getPath());

            throw $ex;
        }
    }
}
PK��Zm�+��1Symfony/Component/Config/Definition/FloatNode.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition;

use Symfony\Component\Config\Definition\Exception\InvalidTypeException;

/**
 * This node represents a float value in the config tree.
 *
 * @author Jeanmonod David <david.jeanmonod@gmail.com>
 */
class FloatNode extends NumericNode
{
    /**
     * {@inheritDoc}
     */
    protected function validateType($value)
    {
        // Integers are also accepted, we just cast them
        if (is_int($value)) {
            $value = (float) $value;
        }

        if (!is_float($value)) {
            $ex = new InvalidTypeException(sprintf('Invalid type for path "%s". Expected float, but got %s.', $this->getPath(), gettype($value)));
            $ex->setPath($this->getPath());

            throw $ex;
        }
    }
}
PK��Zi
�>>BSymfony/Component/Config/Definition/Dumper/YamlReferenceDumper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Dumper;

use Symfony\Component\Config\Definition\ConfigurationInterface;
use Symfony\Component\Config\Definition\NodeInterface;
use Symfony\Component\Config\Definition\ArrayNode;
use Symfony\Component\Config\Definition\ScalarNode;
use Symfony\Component\Config\Definition\EnumNode;
use Symfony\Component\Config\Definition\PrototypedArrayNode;
use Symfony\Component\Yaml\Inline;

/**
 * Dumps a Yaml reference configuration for the given configuration/node instance.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 */
class YamlReferenceDumper
{
    private $reference;

    public function dump(ConfigurationInterface $configuration)
    {
        return $this->dumpNode($configuration->getConfigTreeBuilder()->buildTree());
    }

    public function dumpNode(NodeInterface $node)
    {
        $this->reference = '';
        $this->writeNode($node);
        $ref = $this->reference;
        $this->reference = null;

        return $ref;
    }

    /**
     * @param NodeInterface $node
     * @param integer       $depth
     */
    private function writeNode(NodeInterface $node, $depth = 0)
    {
        $comments = array();
        $default = '';
        $defaultArray = null;
        $children = null;
        $example = $node->getExample();

        // defaults
        if ($node instanceof ArrayNode) {
            $children = $node->getChildren();

            if ($node instanceof PrototypedArrayNode) {
                $prototype = $node->getPrototype();

                if ($prototype instanceof ArrayNode) {
                    $children = $prototype->getChildren();
                }

                // check for attribute as key
                if ($key = $node->getKeyAttribute()) {
                    $keyNodeClass = 'Symfony\Component\Config\Definition\\'.($prototype instanceof ArrayNode ? 'ArrayNode' : 'ScalarNode');
                    $keyNode = new $keyNodeClass($key, $node);
                    $keyNode->setInfo('Prototype');

                    // add children
                    foreach ($children as $childNode) {
                        $keyNode->addChild($childNode);
                    }
                    $children = array($key => $keyNode);
                }
            }

            if (!$children) {
                if ($node->hasDefaultValue() && count($defaultArray = $node->getDefaultValue())) {
                    $default = '';
                } elseif (!is_array($example)) {
                    $default = '[]';
                }
            }
        } elseif ($node instanceof EnumNode) {
            $comments[] = 'One of '.implode('; ', array_map('json_encode', $node->getValues()));
            $default = '~';
        } else {
            $default = '~';

            if ($node->hasDefaultValue()) {
                $default = $node->getDefaultValue();

                if (is_array($default)) {
                    if (count($defaultArray = $node->getDefaultValue())) {
                        $default = '';
                    } elseif (!is_array($example)) {
                        $default = '[]';
                    }
                } else {
                    $default = Inline::dump($default);
                }
            }
        }

        // required?
        if ($node->isRequired()) {
            $comments[] = 'Required';
        }

        // example
        if ($example && !is_array($example)) {
            $comments[] = 'Example: '.$example;
        }

        $default = (string) $default != '' ? ' '.$default : '';
        $comments = count($comments) ? '# '.implode(', ', $comments) : '';

        $text = rtrim(sprintf('%-20s %s %s', $node->getName().':', $default, $comments), ' ');

        if ($info = $node->getInfo()) {
            $this->writeLine('');
            // indenting multi-line info
            $info = str_replace("\n", sprintf("\n%".$depth * 4 . "s# ", ' '), $info);
            $this->writeLine('# '.$info, $depth * 4);
        }

        $this->writeLine($text, $depth * 4);

        // output defaults
        if ($defaultArray) {
            $this->writeLine('');

            $message = count($defaultArray) > 1 ? 'Defaults' : 'Default';

            $this->writeLine('# '.$message.':', $depth * 4 + 4);

            $this->writeArray($defaultArray, $depth + 1);
        }

        if (is_array($example)) {
            $this->writeLine('');

            $message = count($example) > 1 ? 'Examples' : 'Example';

            $this->writeLine('# '.$message.':', $depth * 4 + 4);

            $this->writeArray($example, $depth + 1);
        }

        if ($children) {
            foreach ($children as $childNode) {
                $this->writeNode($childNode, $depth + 1);
            }
        }
    }

    /**
     * Outputs a single config reference line
     *
     * @param string $text
     * @param int    $indent
     */
    private function writeLine($text, $indent = 0)
    {
        $indent = strlen($text) + $indent;
        $format = '%'.$indent.'s';

        $this->reference .= sprintf($format, $text)."\n";
    }

    private function writeArray(array $array, $depth)
    {
        $isIndexed = array_values($array) === $array;

        foreach ($array as $key => $value) {
            if (is_array($value)) {
                $val = '';
            } else {
                $val = $value;
            }

            if ($isIndexed) {
                $this->writeLine('- '.$val, $depth * 4);
            } else {
                $this->writeLine(sprintf('%-20s %s', $key.':', $val), $depth * 4);
            }

            if (is_array($value)) {
                $this->writeArray($value, $depth + 1);
            }
        }
    }
}
PK��Z�2��&�&ASymfony/Component/Config/Definition/Dumper/XmlReferenceDumper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Dumper;

use Symfony\Component\Config\Definition\ConfigurationInterface;
use Symfony\Component\Config\Definition\NodeInterface;
use Symfony\Component\Config\Definition\ArrayNode;
use Symfony\Component\Config\Definition\EnumNode;
use Symfony\Component\Config\Definition\PrototypedArrayNode;

/**
 * Dumps a XML reference configuration for the given configuration/node instance.
 *
 * @author Wouter J <waldio.webdesign@gmail.com>
 */
class XmlReferenceDumper
{
    private $reference;

    public function dump(ConfigurationInterface $configuration, $namespace = null)
    {
        return $this->dumpNode($configuration->getConfigTreeBuilder()->buildTree(), $namespace);
    }

    public function dumpNode(NodeInterface $node, $namespace = null)
    {
        $this->reference = '';
        $this->writeNode($node, 0, true, $namespace);
        $ref = $this->reference;
        $this->reference = null;

        return $ref;
    }

    /**
     * @param NodeInterface $node
     * @param integer       $depth
     * @param Boolean       $root      If the node is the root node
     * @param string        $namespace The namespace of the node
     */
    private function writeNode(NodeInterface $node, $depth = 0, $root = false, $namespace = null)
    {
        $rootName = ($root ? 'config' : $node->getName());
        $rootNamespace = ($namespace ?: ($root ? 'http://example.org/schema/dic/'.$node->getName() : null));

        // xml remapping
        if ($node->getParent()) {
            $remapping = array_filter($node->getParent()->getXmlRemappings(), function ($mapping) use ($rootName) {
                return $rootName === $mapping[1];
            });

            if (count($remapping)) {
                list($singular, $plural) = current($remapping);
                $rootName = $singular;
            }
        }
        $rootName = str_replace('_', '-', $rootName);

        $rootAttributes = array();
        $rootAttributeComments = array();
        $rootChildren = array();
        $rootComments = array();

        if ($node instanceof ArrayNode) {
            $children = $node->getChildren();

            // comments about the root node
            if ($rootInfo = $node->getInfo()) {
                $rootComments[] = $rootInfo;
            }

            if ($rootNamespace) {
                $rootComments[] = 'Namespace: '.$rootNamespace;
            }

            // render prototyped nodes
            if ($node instanceof PrototypedArrayNode) {
                array_unshift($rootComments, 'prototype');

                if ($key = $node->getKeyAttribute()) {
                    $rootAttributes[$key] = str_replace('-', ' ', $rootName).' '.$key;
                }

                $prototype = $node->getPrototype();

                if ($prototype instanceof ArrayNode) {
                    $children = $prototype->getChildren();
                } else {
                    if ($prototype->hasDefaultValue()) {
                        $prototypeValue = $prototype->getDefaultValue();
                    } else {
                        switch (get_class($prototype)) {
                            case 'Symfony\Component\Config\Definition\ScalarNode':
                                $prototypeValue = 'scalar value';
                                break;

                            case 'Symfony\Component\Config\Definition\FloatNode':
                            case 'Symfony\Component\Config\Definition\IntegerNode':
                                $prototypeValue = 'numeric value';
                                break;

                            case 'Symfony\Component\Config\Definition\BooleanNode':
                                $prototypeValue = 'true|false';
                                break;

                            case 'Symfony\Component\Config\Definition\EnumNode':
                                $prototypeValue = implode('|', array_map('json_encode', $prototype->getValues()));
                                break;

                            default:
                                $prototypeValue = 'value';
                        }
                    }
                }
            }

            // get attributes and elements
            foreach ($children as $child) {
                if (!$child instanceof ArrayNode) {
                    // get attributes

                    // metadata
                    $name  = str_replace('_', '-', $child->getName());
                    $value = '%%%%not_defined%%%%'; // use a string which isn't used in the normal world

                    // comments
                    $comments = array();
                    if ($info = $child->getInfo()) {
                        $comments[] = $info;
                    }

                    if ($example = $child->getExample()) {
                        $comments[] = 'Example: '.$example;
                    }

                    if ($child->isRequired()) {
                        $comments[] = 'Required';
                    }

                    if ($child instanceof EnumNode) {
                        $comments[] = 'One of '.implode('; ', array_map('json_encode', $child->getValues()));
                    }

                    if (count($comments)) {
                        $rootAttributeComments[$name] = implode(";\n", $comments);
                    }

                    // default values
                    if ($child->hasDefaultValue()) {
                        $value = $child->getDefaultValue();
                    }

                    // append attribute
                    $rootAttributes[$name] = $value;
                } else {
                    // get elements
                    $rootChildren[] = $child;
                }
            }
        }

        // render comments

        // root node comment
        if (count($rootComments)) {
            foreach ($rootComments as $comment) {
                $this->writeLine('<!-- '.$comment.' -->', $depth);
            }
        }

        // attribute comments
        if (count($rootAttributeComments)) {
            foreach ($rootAttributeComments as $attrName => $comment) {
                $commentDepth = $depth + 4 + strlen($attrName) + 2;
                $commentLines = explode("\n", $comment);
                $multiline = (count($commentLines) > 1);
                $comment = implode(PHP_EOL.str_repeat(' ', $commentDepth), $commentLines);

                if ($multiline) {
                    $this->writeLine('<!--', $depth);
                    $this->writeLine($attrName.': '.$comment, $depth + 4);
                    $this->writeLine('-->', $depth);
                } else {
                    $this->writeLine('<!-- '.$attrName.': '.$comment.' -->', $depth);
                }
            }
        }

        // render start tag + attributes
        $rootIsVariablePrototype = isset($prototypeValue);
        $rootIsEmptyTag = (0 === count($rootChildren) && !$rootIsVariablePrototype);
        $rootOpenTag = '<'.$rootName;
        if (1 >= ($attributesCount = count($rootAttributes))) {
            if (1 === $attributesCount) {
                $rootOpenTag .= sprintf(' %s="%s"', current(array_keys($rootAttributes)), $this->writeValue(current($rootAttributes)));
            }

            $rootOpenTag .= $rootIsEmptyTag ? ' />' : '>';

            if ($rootIsVariablePrototype) {
                $rootOpenTag .= $prototypeValue.'</'.$rootName.'>';
            }

            $this->writeLine($rootOpenTag, $depth);
        } else {
            $this->writeLine($rootOpenTag, $depth);

            $i = 1;

            foreach ($rootAttributes as $attrName => $attrValue) {
                $attr = sprintf('%s="%s"', $attrName, $this->writeValue($attrValue));

                $this->writeLine($attr, $depth + 4);

                if ($attributesCount === $i++) {
                    $this->writeLine($rootIsEmptyTag ? '/>' : '>', $depth);

                    if ($rootIsVariablePrototype) {
                        $rootOpenTag .= $prototypeValue.'</'.$rootName.'>';
                    }
                }
            }
        }

        // render children tags
        foreach ($rootChildren as $child) {
            $this->writeLine('');
            $this->writeNode($child, $depth + 4);
        }

        // render end tag
        if (!$rootIsEmptyTag && !$rootIsVariablePrototype) {
            $this->writeLine('');

            $rootEndTag = '</'.$rootName.'>';
            $this->writeLine($rootEndTag, $depth);
        }
    }

    /**
     * Outputs a single config reference line
     *
     * @param string $text
     * @param int    $indent
     */
    private function writeLine($text, $indent = 0)
    {
        $indent = strlen($text) + $indent;
        $format = '%'.$indent.'s';

        $this->reference .= sprintf($format, $text)."\n";
    }

    /**
     * Renders the string conversion of the value.
     *
     * @param mixed $value
     *
     * @return string
     */
    private function writeValue($value)
    {
        if ('%%%%not_defined%%%%' === $value) {
            return '';
        }

        if (is_string($value) || is_numeric($value)) {
            return $value;
        }

        if (false === $value) {
            return 'false';
        }

        if (true === $value) {
            return 'true';
        }

        if (null === $value) {
            return 'null';
        }

        if (empty($value)) {
            return '';
        }

        if (is_array($value)) {
            return implode(',', $value);
        }
    }
}
PK��Z$�¸	�	4Symfony/Component/Config/Definition/VariableNode.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition;

use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;

/**
 * This node represents a value of variable type in the config tree.
 *
 * This node is intended for values of arbitrary type.
 * Any PHP type is accepted as a value.
 *
 * @author Jeremy Mikola <jmikola@gmail.com>
 */
class VariableNode extends BaseNode implements PrototypeNodeInterface
{
    protected $defaultValueSet = false;
    protected $defaultValue;
    protected $allowEmptyValue = true;

    /**
     * {@inheritDoc}
     */
    public function setDefaultValue($value)
    {
        $this->defaultValueSet = true;
        $this->defaultValue = $value;
    }

    /**
     * {@inheritDoc}
     */
    public function hasDefaultValue()
    {
        return $this->defaultValueSet;
    }

    /**
     * {@inheritDoc}
     */
    public function getDefaultValue()
    {
        return $this->defaultValue instanceof \Closure ? call_user_func($this->defaultValue) : $this->defaultValue;
    }

    /**
     * Sets if this node is allowed to have an empty value.
     *
     * @param Boolean $boolean True if this entity will accept empty values.
     */
    public function setAllowEmptyValue($boolean)
    {
        $this->allowEmptyValue = (Boolean) $boolean;
    }

    /**
     * {@inheritDoc}
     */
    public function setName($name)
    {
        $this->name = $name;
    }

    /**
     * {@inheritDoc}
     */
    protected function validateType($value)
    {
    }

    /**
     * {@inheritDoc}
     */
    protected function finalizeValue($value)
    {
        if (!$this->allowEmptyValue && empty($value)) {
            $ex = new InvalidConfigurationException(sprintf(
                'The path "%s" cannot contain an empty value, but got %s.',
                $this->getPath(),
                json_encode($value)
            ));
            $ex->setPath($this->getPath());

            throw $ex;
        }

        return $value;
    }

    /**
     * {@inheritDoc}
     */
    protected function normalizeValue($value)
    {
        return $value;
    }

    /**
     * {@inheritDoc}
     */
    protected function mergeValues($leftSide, $rightSide)
    {
        return $rightSide;
    }
}
PK��ZG4�*�*1Symfony/Component/Config/Definition/ArrayNode.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition;

use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use Symfony\Component\Config\Definition\Exception\InvalidTypeException;
use Symfony\Component\Config\Definition\Exception\UnsetKeyException;

/**
 * Represents an Array node in the config tree.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ArrayNode extends BaseNode implements PrototypeNodeInterface
{
    protected $xmlRemappings = array();
    protected $children = array();
    protected $allowFalse = false;
    protected $allowNewKeys = true;
    protected $addIfNotSet = false;
    protected $performDeepMerging = true;
    protected $ignoreExtraKeys = false;
    protected $normalizeKeys = true;

    public function setNormalizeKeys($normalizeKeys)
    {
        $this->normalizeKeys = (Boolean) $normalizeKeys;
    }

    /**
     * Normalizes keys between the different configuration formats.
     *
     * Namely, you mostly have foo_bar in YAML while you have foo-bar in XML.
     * After running this method, all keys are normalized to foo_bar.
     *
     * If you have a mixed key like foo-bar_moo, it will not be altered.
     * The key will also not be altered if the target key already exists.
     *
     * @param mixed $value
     *
     * @return array The value with normalized keys
     */
    protected function preNormalize($value)
    {
        if (!$this->normalizeKeys || !is_array($value)) {
            return $value;
        }

        foreach ($value as $k => $v) {
            if (false !== strpos($k, '-') && false === strpos($k, '_') && !array_key_exists($normalizedKey = str_replace('-', '_', $k), $value)) {
                $value[$normalizedKey] = $v;
                unset($value[$k]);
            }
        }

        return $value;
    }

    /**
     * Retrieves the children of this node.
     *
     * @return array The children
     */
    public function getChildren()
    {
        return $this->children;
    }

    /**
     * Sets the xml remappings that should be performed.
     *
     * @param array $remappings an array of the form array(array(string, string))
     */
    public function setXmlRemappings(array $remappings)
    {
        $this->xmlRemappings = $remappings;
    }

    /**
     * Gets the xml remappings that should be performed.
     *
     * @return array $remappings an array of the form array(array(string, string))
     */
    public function getXmlRemappings()
    {
        return $this->xmlRemappings;
    }

    /**
     * Sets whether to add default values for this array if it has not been
     * defined in any of the configuration files.
     *
     * @param Boolean $boolean
     */
    public function setAddIfNotSet($boolean)
    {
        $this->addIfNotSet = (Boolean) $boolean;
    }

    /**
     * Sets whether false is allowed as value indicating that the array should be unset.
     *
     * @param Boolean $allow
     */
    public function setAllowFalse($allow)
    {
        $this->allowFalse = (Boolean) $allow;
    }

    /**
     * Sets whether new keys can be defined in subsequent configurations.
     *
     * @param Boolean $allow
     */
    public function setAllowNewKeys($allow)
    {
        $this->allowNewKeys = (Boolean) $allow;
    }

    /**
     * Sets if deep merging should occur.
     *
     * @param Boolean $boolean
     */
    public function setPerformDeepMerging($boolean)
    {
        $this->performDeepMerging = (Boolean) $boolean;
    }

    /**
     * Whether extra keys should just be ignore without an exception.
     *
     * @param Boolean $boolean To allow extra keys
     */
    public function setIgnoreExtraKeys($boolean)
    {
        $this->ignoreExtraKeys = (Boolean) $boolean;
    }

    /**
     * Sets the node Name.
     *
     * @param string $name The node's name
     */
    public function setName($name)
    {
        $this->name = $name;
    }

    /**
     * Checks if the node has a default value.
     *
     * @return Boolean
     */
    public function hasDefaultValue()
    {
        return $this->addIfNotSet;
    }

    /**
     * Retrieves the default value.
     *
     * @return array The default value
     *
     * @throws \RuntimeException if the node has no default value
     */
    public function getDefaultValue()
    {
        if (!$this->hasDefaultValue()) {
            throw new \RuntimeException(sprintf('The node at path "%s" has no default value.', $this->getPath()));
        }

        $defaults = array();
        foreach ($this->children as $name => $child) {
            if ($child->hasDefaultValue()) {
                $defaults[$name] = $child->getDefaultValue();
            }
        }

        return $defaults;
    }

    /**
     * Adds a child node.
     *
     * @param NodeInterface $node The child node to add
     *
     * @throws \InvalidArgumentException when the child node has no name
     * @throws \InvalidArgumentException when the child node's name is not unique
     */
    public function addChild(NodeInterface $node)
    {
        $name = $node->getName();
        if (!strlen($name)) {
            throw new \InvalidArgumentException('Child nodes must be named.');
        }
        if (isset($this->children[$name])) {
            throw new \InvalidArgumentException(sprintf('A child node named "%s" already exists.', $name));
        }

        $this->children[$name] = $node;
    }

    /**
     * Finalizes the value of this node.
     *
     * @param mixed $value
     *
     * @return mixed The finalised value
     *
     * @throws UnsetKeyException
     * @throws InvalidConfigurationException if the node doesn't have enough children
     */
    protected function finalizeValue($value)
    {
        if (false === $value) {
            $msg = sprintf('Unsetting key for path "%s", value: %s', $this->getPath(), json_encode($value));
            throw new UnsetKeyException($msg);
        }

        foreach ($this->children as $name => $child) {
            if (!array_key_exists($name, $value)) {
                if ($child->isRequired()) {
                    $msg = sprintf('The child node "%s" at path "%s" must be configured.', $name, $this->getPath());
                    $ex = new InvalidConfigurationException($msg);
                    $ex->setPath($this->getPath());

                    throw $ex;
                }

                if ($child->hasDefaultValue()) {
                    $value[$name] = $child->getDefaultValue();
                }

                continue;
            }

            try {
                $value[$name] = $child->finalize($value[$name]);
            } catch (UnsetKeyException $unset) {
                unset($value[$name]);
            }
        }

        return $value;
    }

    /**
     * Validates the type of the value.
     *
     * @param mixed $value
     *
     * @throws InvalidTypeException
     */
    protected function validateType($value)
    {
        if (!is_array($value) && (!$this->allowFalse || false !== $value)) {
            $ex = new InvalidTypeException(sprintf(
                'Invalid type for path "%s". Expected array, but got %s',
                $this->getPath(),
                gettype($value)
            ));
            $ex->setPath($this->getPath());

            throw $ex;
        }
    }

    /**
     * Normalizes the value.
     *
     * @param mixed $value The value to normalize
     *
     * @return mixed The normalized value
     *
     * @throws InvalidConfigurationException
     */
    protected function normalizeValue($value)
    {
        if (false === $value) {
            return $value;
        }

        $value = $this->remapXml($value);

        $normalized = array();
        foreach ($value as $name => $val) {
            if (isset($this->children[$name])) {
                $normalized[$name] = $this->children[$name]->normalize($val);
                unset($value[$name]);
            }
        }

        // if extra fields are present, throw exception
        if (count($value) && !$this->ignoreExtraKeys) {
            $msg = sprintf('Unrecognized options "%s" under "%s"', implode(', ', array_keys($value)), $this->getPath());
            $ex = new InvalidConfigurationException($msg);
            $ex->setPath($this->getPath());

            throw $ex;
        }

        return $normalized;
    }

    /**
     * Remaps multiple singular values to a single plural value.
     *
     * @param array $value The source values
     *
     * @return array The remapped values
     */
    protected function remapXml($value)
    {
        foreach ($this->xmlRemappings as $transformation) {
            list($singular, $plural) = $transformation;

            if (!isset($value[$singular])) {
                continue;
            }

            $value[$plural] = Processor::normalizeConfig($value, $singular, $plural);
            unset($value[$singular]);
        }

        return $value;
    }

    /**
     * Merges values together.
     *
     * @param mixed $leftSide  The left side to merge.
     * @param mixed $rightSide The right side to merge.
     *
     * @return mixed The merged values
     *
     * @throws InvalidConfigurationException
     * @throws \RuntimeException
     */
    protected function mergeValues($leftSide, $rightSide)
    {
        if (false === $rightSide) {
            // if this is still false after the last config has been merged the
            // finalization pass will take care of removing this key entirely
            return false;
        }

        if (false === $leftSide || !$this->performDeepMerging) {
            return $rightSide;
        }

        foreach ($rightSide as $k => $v) {
            // no conflict
            if (!array_key_exists($k, $leftSide)) {
                if (!$this->allowNewKeys) {
                    $ex = new InvalidConfigurationException(sprintf(
                        'You are not allowed to define new elements for path "%s". '
                       .'Please define all elements for this path in one config file. '
                       .'If you are trying to overwrite an element, make sure you redefine it '
                       .'with the same name.',
                        $this->getPath()
                    ));
                    $ex->setPath($this->getPath());

                    throw $ex;
                }

                $leftSide[$k] = $v;
                continue;
            }

            if (!isset($this->children[$k])) {
                throw new \RuntimeException('merge() expects a normalized config array.');
            }

            $leftSide[$k] = $this->children[$k]->merge($leftSide[$k], $v);
        }

        return $leftSide;
    }
}
PK��Z*���dd>Symfony/Component/Config/Definition/ConfigurationInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition;

/**
 * Configuration interface
 *
 * @author Victor Berchet <victor@suumit.com>
 */
interface ConfigurationInterface
{
    /**
     * Generates the configuration tree builder.
     *
     * @return \Symfony\Component\Config\Definition\Builder\TreeBuilder The tree builder
     */
    public function getConfigTreeBuilder();
}
PK��Z��eww>Symfony/Component/Config/Definition/PrototypeNodeInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition;

/**
 * This interface must be implemented by nodes which can be used as prototypes.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface PrototypeNodeInterface extends NodeInterface
{
    /**
     * Sets the name of the node.
     *
     * @param string $name The name of the node
     */
    public function setName($name);
}
PK��Z-*ҹ--3Symfony/Component/Config/Definition/NumericNode.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition;

use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;

/**
 * This node represents a numeric value in the config tree
 *
 * @author David Jeanmonod <david.jeanmonod@gmail.com>
 */
class NumericNode extends ScalarNode
{
    protected $min;
    protected $max;

    public function __construct($name, NodeInterface $parent = null, $min = null, $max = null)
    {
        parent::__construct($name, $parent);
        $this->min = $min;
        $this->max = $max;
    }

    /**
     * {@inheritDoc}
     */
    protected function finalizeValue($value)
    {
        $value = parent::finalizeValue($value);

        $errorMsg = null;
        if (isset($this->min) && $value < $this->min) {
            $errorMsg = sprintf('The value %s is too small for path "%s". Should be greater than or equal to %s', $value, $this->getPath(), $this->min);
        }
        if (isset($this->max) && $value > $this->max) {
            $errorMsg = sprintf('The value %s is too big for path "%s". Should be less than or equal to %s', $value, $this->getPath(), $this->max);
        }
        if (isset($errorMsg)) {
            $ex = new InvalidConfigurationException($errorMsg);
            $ex->setPath($this->getPath());
            throw $ex;
        }

        return $value;
    }
}
PK��Z��B�""0Symfony/Component/Config/Definition/BaseNode.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition;

use Symfony\Component\Config\Definition\Exception\Exception;
use Symfony\Component\Config\Definition\Exception\ForbiddenOverwriteException;
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;

/**
 * The base node class
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
abstract class BaseNode implements NodeInterface
{
    protected $name;
    protected $parent;
    protected $normalizationClosures = array();
    protected $finalValidationClosures = array();
    protected $allowOverwrite = true;
    protected $required = false;
    protected $equivalentValues = array();
    protected $attributes = array();

    /**
     * Constructor.
     *
     * @param string        $name   The name of the node
     * @param NodeInterface $parent The parent of this node
     *
     * @throws \InvalidArgumentException if the name contains a period.
     */
    public function __construct($name, NodeInterface $parent = null)
    {
        if (false !== strpos($name, '.')) {
            throw new \InvalidArgumentException('The name must not contain ".".');
        }

        $this->name = $name;
        $this->parent = $parent;
    }

    public function setAttribute($key, $value)
    {
        $this->attributes[$key] = $value;
    }

    public function getAttribute($key, $default = null)
    {
        return isset($this->attributes[$key]) ? $this->attributes[$key] : $default;
    }

    public function hasAttribute($key)
    {
        return isset($this->attributes[$key]);
    }

    public function getAttributes()
    {
        return $this->attributes;
    }

    public function setAttributes(array $attributes)
    {
        $this->attributes = $attributes;
    }

    public function removeAttribute($key)
    {
        unset($this->attributes[$key]);
    }

    /**
     * Sets an info message.
     *
     * @param string $info
     */
    public function setInfo($info)
    {
        $this->setAttribute('info', $info);
    }

    /**
     * Returns info message.
     *
     * @return string The info text
     */
    public function getInfo()
    {
        return $this->getAttribute('info');
    }

    /**
     * Sets the example configuration for this node.
     *
     * @param string|array $example
     */
    public function setExample($example)
    {
        $this->setAttribute('example', $example);
    }

    /**
     * Retrieves the example configuration for this node.
     *
     * @return string|array The example
     */
    public function getExample()
    {
        return $this->getAttribute('example');
    }

    /**
     * Adds an equivalent value.
     *
     * @param mixed $originalValue
     * @param mixed $equivalentValue
     */
    public function addEquivalentValue($originalValue, $equivalentValue)
    {
        $this->equivalentValues[] = array($originalValue, $equivalentValue);
    }

    /**
     * Set this node as required.
     *
     * @param Boolean $boolean Required node
     */
    public function setRequired($boolean)
    {
        $this->required = (Boolean) $boolean;
    }

    /**
     * Sets if this node can be overridden.
     *
     * @param Boolean $allow
     */
    public function setAllowOverwrite($allow)
    {
        $this->allowOverwrite = (Boolean) $allow;
    }

    /**
     * Sets the closures used for normalization.
     *
     * @param \Closure[] $closures An array of Closures used for normalization
     */
    public function setNormalizationClosures(array $closures)
    {
        $this->normalizationClosures = $closures;
    }

    /**
     * Sets the closures used for final validation.
     *
     * @param \Closure[] $closures An array of Closures used for final validation
     */
    public function setFinalValidationClosures(array $closures)
    {
        $this->finalValidationClosures = $closures;
    }

    /**
     * Checks if this node is required.
     *
     * @return Boolean
     */
    public function isRequired()
    {
        return $this->required;
    }

    /**
     * Returns the name of this node
     *
     * @return string The Node's name.
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Retrieves the path of this node.
     *
     * @return string The Node's path
     */
    public function getPath()
    {
        $path = $this->name;

        if (null !== $this->parent) {
            $path = $this->parent->getPath().'.'.$path;
        }

        return $path;
    }

    /**
     * Merges two values together.
     *
     * @param mixed $leftSide
     * @param mixed $rightSide
     *
     * @return mixed The merged value
     *
     * @throws ForbiddenOverwriteException
     */
    final public function merge($leftSide, $rightSide)
    {
        if (!$this->allowOverwrite) {
            throw new ForbiddenOverwriteException(sprintf(
                'Configuration path "%s" cannot be overwritten. You have to '
               .'define all options for this path, and any of its sub-paths in '
               .'one configuration section.',
                $this->getPath()
            ));
        }

        $this->validateType($leftSide);
        $this->validateType($rightSide);

        return $this->mergeValues($leftSide, $rightSide);
    }

    /**
     * Normalizes a value, applying all normalization closures.
     *
     * @param mixed $value Value to normalize.
     *
     * @return mixed The normalized value.
     */
    final public function normalize($value)
    {
        $value = $this->preNormalize($value);

        // run custom normalization closures
        foreach ($this->normalizationClosures as $closure) {
            $value = $closure($value);
        }

        // replace value with their equivalent
        foreach ($this->equivalentValues as $data) {
            if ($data[0] === $value) {
                $value = $data[1];
            }
        }

        // validate type
        $this->validateType($value);

        // normalize value
        return $this->normalizeValue($value);
    }

    /**
     * Normalizes the value before any other normalization is applied.
     *
     * @param $value
     *
     * @return $value The normalized array value
     */
    protected function preNormalize($value)
    {
        return $value;
    }

    /**
     * Returns parent node for this node.
     *
     * @return NodeInterface|null
     */
    public function getParent()
    {
        return $this->parent;
    }

    /**
     * Finalizes a value, applying all finalization closures.
     *
     * @param mixed $value The value to finalize
     *
     * @return mixed The finalized value
     *
     * @throws InvalidConfigurationException
     */
    final public function finalize($value)
    {
        $this->validateType($value);

        $value = $this->finalizeValue($value);

        // Perform validation on the final value if a closure has been set.
        // The closure is also allowed to return another value.
        foreach ($this->finalValidationClosures as $closure) {
            try {
                $value = $closure($value);
            } catch (Exception $correctEx) {
                throw $correctEx;
            } catch (\Exception $invalid) {
                throw new InvalidConfigurationException(sprintf(
                    'Invalid configuration for path "%s": %s',
                    $this->getPath(),
                    $invalid->getMessage()
                ), $invalid->getCode(), $invalid);
            }
        }

        return $value;
    }

    /**
     * Validates the type of a Node.
     *
     * @param mixed $value The value to validate
     *
     * @throws InvalidTypeException when the value is invalid
     */
    abstract protected function validateType($value);

    /**
     * Normalizes the value.
     *
     * @param mixed $value The value to normalize.
     *
     * @return mixed The normalized value
     */
    abstract protected function normalizeValue($value);

    /**
     * Merges two values together.
     *
     * @param mixed $leftSide
     * @param mixed $rightSide
     *
     * @return mixed The merged value
     */
    abstract protected function mergeValues($leftSide, $rightSide);

    /**
     * Finalizes a value.
     *
     * @param mixed $value The value to finalize
     *
     * @return mixed The finalized value
     */
    abstract protected function finalizeValue($value);
}
PK��Z0��007Symfony/Component/Config/Definition/ReferenceDumper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition;

use Symfony\Component\Config\Definition\Dumper\YamlReferenceDumper;

/**
 * @deprecated Deprecated since version 2.4, to be removed in 3.0. Use Symfony\Component\Config\Definition\Dumper\YamlReferenceDumper instead.
 */
class ReferenceDumper extends YamlReferenceDumper
{
}
PK��Z`�PP'Symfony/Component/Config/autoloader.phpnu�[���<?php

spl_autoload_register(function ($class) {
    if ('\\' == $class[0]) {
        $class = substr($class, 1);
    }

    if (
        0 === strpos($class, 'Symfony\\Component\\Config\\')
        &&
        file_exists($file = __DIR__.'/../../../'.str_replace('\\', '/', $class).'.php')
    ) {
        require_once $file;
    }
});
PK��ZfK�EDD7Symfony/Component/Config/Resource/ResourceInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Resource;

/**
 * ResourceInterface is the interface that must be implemented by all Resource classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface ResourceInterface
{
    /**
     * Returns a string representation of the Resource.
     *
     * @return string A string representation of the Resource
     */
    public function __toString();

    /**
     * Returns true if the resource has not been updated since the given timestamp.
     *
     * @param integer $timestamp The last time the resource was loaded
     *
     * @return Boolean true if the resource has not been updated, false otherwise
     */
    public function isFresh($timestamp);

    /**
     * Returns the resource tied to this Resource.
     *
     * @return mixed The resource
     */
    public function getResource();
}
PK��Z��T!!2Symfony/Component/Config/Resource/FileResource.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Resource;

/**
 * FileResource represents a resource stored on the filesystem.
 *
 * The resource can be a file or a directory.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FileResource implements ResourceInterface, \Serializable
{
    private $resource;

    /**
     * Constructor.
     *
     * @param string $resource The file path to the resource
     */
    public function __construct($resource)
    {
        $this->resource = realpath($resource);
    }

    /**
     * Returns a string representation of the Resource.
     *
     * @return string A string representation of the Resource
     */
    public function __toString()
    {
        return (string) $this->resource;
    }

    /**
     * Returns the resource tied to this Resource.
     *
     * @return mixed The resource
     */
    public function getResource()
    {
        return $this->resource;
    }

    /**
     * Returns true if the resource has not been updated since the given timestamp.
     *
     * @param integer $timestamp The last time the resource was loaded
     *
     * @return Boolean true if the resource has not been updated, false otherwise
     */
    public function isFresh($timestamp)
    {
        if (!file_exists($this->resource)) {
            return false;
        }

        return filemtime($this->resource) < $timestamp;
    }

    public function serialize()
    {
        return serialize($this->resource);
    }

    public function unserialize($serialized)
    {
        $this->resource = unserialize($serialized);
    }
}
PK��Z�
#�
�
7Symfony/Component/Config/Resource/DirectoryResource.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Resource;

/**
 * DirectoryResource represents a resources stored in a subdirectory tree.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class DirectoryResource implements ResourceInterface, \Serializable
{
    private $resource;
    private $pattern;

    /**
     * Constructor.
     *
     * @param string $resource The file path to the resource
     * @param string $pattern  A pattern to restrict monitored files
     */
    public function __construct($resource, $pattern = null)
    {
        $this->resource = $resource;
        $this->pattern = $pattern;
    }

    /**
     * Returns a string representation of the Resource.
     *
     * @return string A string representation of the Resource
     */
    public function __toString()
    {
        return (string) $this->resource;
    }

    /**
     * Returns the resource tied to this Resource.
     *
     * @return mixed The resource
     */
    public function getResource()
    {
        return $this->resource;
    }

    public function getPattern()
    {
        return $this->pattern;
    }

    /**
     * Returns true if the resource has not been updated since the given timestamp.
     *
     * @param integer $timestamp The last time the resource was loaded
     *
     * @return Boolean true if the resource has not been updated, false otherwise
     */
    public function isFresh($timestamp)
    {
        if (!is_dir($this->resource)) {
            return false;
        }

        $newestMTime = filemtime($this->resource);
        foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->resource), \RecursiveIteratorIterator::SELF_FIRST) as $file) {
            // if regex filtering is enabled only check matching files
            if ($this->pattern && $file->isFile() && !preg_match($this->pattern, $file->getBasename())) {
                continue;
            }

            // always monitor directories for changes, except the .. entries
            // (otherwise deleted files wouldn't get detected)
            if ($file->isDir() && '/..' === substr($file, -3)) {
                continue;
            }

            $newestMTime = max($file->getMTime(), $newestMTime);
        }

        return $newestMTime < $timestamp;
    }

    public function serialize()
    {
        return serialize(array($this->resource, $this->pattern));
    }

    public function unserialize($serialized)
    {
        list($this->resource, $this->pattern) = unserialize($serialized);
    }
}
PK��Z�C3kll1Symfony/Component/Config/FileLocatorInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config;

/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface FileLocatorInterface
{
    /**
     * Returns a full path for a given file name.
     *
     * @param mixed   $name        The file name to locate
     * @param string  $currentPath The current path
     * @param Boolean $first       Whether to return the first occurrence or an array of filenames
     *
     * @return string|array The full path to the file|An array of file paths
     *
     * @throws \InvalidArgumentException When file is not found
     */
    public function locate($name, $currentPath = null, $first = true);
}
PK��Z7�TTQSymfony/Component/Config/Exception/FileLoaderImportCircularReferenceException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Exception;

/**
 * Exception class for when a circular reference is detected when importing resources.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FileLoaderImportCircularReferenceException extends FileLoaderLoadException
{
    public function __construct(array $resources, $code = null, $previous = null)
    {
        $message = sprintf('Circular reference detected in "%s" ("%s" > "%s").', $this->varToString($resources[0]), implode('" > "', $resources), $resources[0]);

        call_user_func('Exception::__construct', $message, $code, $previous);
    }
}
PK��Z��W�	�	>Symfony/Component/Config/Exception/FileLoaderLoadException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Exception;

/**
 * Exception class for when a resource cannot be loaded or imported.
 *
 * @author Ryan Weaver <ryan@thatsquality.com>
 */
class FileLoaderLoadException extends \Exception
{
    /**
     * @param string     $resource       The resource that could not be imported
     * @param string     $sourceResource The original resource importing the new resource
     * @param integer    $code           The error code
     * @param \Exception $previous       A previous exception
     */
    public function __construct($resource, $sourceResource = null, $code = null, $previous = null)
    {
        if (null === $sourceResource) {
            $message = sprintf('Cannot load resource "%s".', $this->varToString($resource));
        } else {
            $message = sprintf('Cannot import resource "%s" from "%s".', $this->varToString($resource), $this->varToString($sourceResource));
        }

        // Is the resource located inside a bundle?
        if ('@' === $resource[0]) {
            $parts = explode(DIRECTORY_SEPARATOR, $resource);
            $bundle = substr($parts[0], 1);
            $message .= ' '.sprintf('Make sure the "%s" bundle is correctly registered and loaded in the application kernel class.', $bundle);
        } elseif ($previous) {
            // include the previous exception, to help the user see what might be the underlying cause
            $message .= ' '.sprintf('(%s)', $previous->getMessage());
        }

        parent::__construct($message, $code, $previous);
    }

    protected function varToString($var)
    {
        if (is_object($var)) {
            return sprintf('Object(%s)', get_class($var));
        }

        if (is_array($var)) {
            $a = array();
            foreach ($var as $k => $v) {
                $a[] = sprintf('%s => %s', $k, $this->varToString($v));
            }

            return sprintf("Array(%s)", implode(', ', $a));
        }

        if (is_resource($var)) {
            return sprintf('Resource(%s)', get_resource_type($var));
        }

        if (null === $var) {
            return 'null';
        }

        if (false === $var) {
            return 'false';
        }

        if (true === $var) {
            return 'true';
        }

        return (string) $var;
    }
}
PK��Z��k��*Symfony/Component/Config/Util/XmlUtils.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Util;

/**
 * XMLUtils is a bunch of utility methods to XML operations.
 *
 * This class contains static methods only and is not meant to be instantiated.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Martin Hasoň <martin.hason@gmail.com>
 */
class XmlUtils
{
    /**
     * This class should not be instantiated
     */
    private function __construct()
    {
    }

    /**
     * Loads an XML file.
     *
     * @param string               $file             An XML file path
     * @param string|callable|null $schemaOrCallable An XSD schema file path, a callable, or null to disable validation
     *
     * @return \DOMDocument
     *
     * @throws \InvalidArgumentException When loading of XML file returns error
     */
    public static function loadFile($file, $schemaOrCallable = null)
    {
        $content = @file_get_contents($file);
        if ('' === trim($content)) {
            throw new \InvalidArgumentException(sprintf('File %s does not contain valid XML, it is empty.', $file));
        }

        $internalErrors = libxml_use_internal_errors(true);
        $disableEntities = libxml_disable_entity_loader(true);
        libxml_clear_errors();

        $dom = new \DOMDocument();
        $dom->validateOnParse = true;
        if (!$dom->loadXML($content, LIBXML_NONET | (defined('LIBXML_COMPACT') ? LIBXML_COMPACT : 0))) {
            libxml_disable_entity_loader($disableEntities);

            throw new \InvalidArgumentException(implode("\n", static::getXmlErrors($internalErrors)));
        }

        $dom->normalizeDocument();

        libxml_use_internal_errors($internalErrors);
        libxml_disable_entity_loader($disableEntities);

        foreach ($dom->childNodes as $child) {
            if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) {
                throw new \InvalidArgumentException('Document types are not allowed.');
            }
        }

        if (null !== $schemaOrCallable) {
            $internalErrors = libxml_use_internal_errors(true);
            libxml_clear_errors();

            $e = null;
            if (is_callable($schemaOrCallable)) {
                try {
                    $valid = call_user_func($schemaOrCallable, $dom, $internalErrors);
                } catch (\Exception $e) {
                    $valid = false;
                }
            } elseif (!is_array($schemaOrCallable) && is_file((string) $schemaOrCallable)) {
                $valid = @$dom->schemaValidate($schemaOrCallable);
            } else {
                libxml_use_internal_errors($internalErrors);

                throw new \InvalidArgumentException('The schemaOrCallable argument has to be a valid path to XSD file or callable.');
            }

            if (!$valid) {
                $messages = static::getXmlErrors($internalErrors);
                if (empty($messages)) {
                    $messages = array(sprintf('The XML file "%s" is not valid.', $file));
                }
                throw new \InvalidArgumentException(implode("\n", $messages), 0, $e);
            }

            libxml_use_internal_errors($internalErrors);
        }

        return $dom;
    }

    /**
     * Converts a \DomElement object to a PHP array.
     *
     * The following rules applies during the conversion:
     *
     *  * Each tag is converted to a key value or an array
     *    if there is more than one "value"
     *
     *  * The content of a tag is set under a "value" key (<foo>bar</foo>)
     *    if the tag also has some nested tags
     *
     *  * The attributes are converted to keys (<foo foo="bar"/>)
     *
     *  * The nested-tags are converted to keys (<foo><foo>bar</foo></foo>)
     *
     * @param \DomElement $element     A \DomElement instance
     * @param Boolean     $checkPrefix Check prefix in an element or an attribute name
     *
     * @return array A PHP array
     */
    public static function convertDomElementToArray(\DomElement $element, $checkPrefix = true)
    {
        $prefix = (string) $element->prefix;
        $empty = true;
        $config = array();
        foreach ($element->attributes as $name => $node) {
            if ($checkPrefix && !in_array((string) $node->prefix, array('', $prefix), true)) {
                continue;
            }
            $config[$name] = static::phpize($node->value);
            $empty = false;
        }

        $nodeValue = false;
        foreach ($element->childNodes as $node) {
            if ($node instanceof \DOMText) {
                if ('' !== trim($node->nodeValue)) {
                    $nodeValue = trim($node->nodeValue);
                    $empty = false;
                }
            } elseif ($checkPrefix && $prefix != (string) $node->prefix) {
                continue;
            } elseif (!$node instanceof \DOMComment) {
                $value = static::convertDomElementToArray($node, $checkPrefix);

                $key = $node->localName;
                if (isset($config[$key])) {
                    if (!is_array($config[$key]) || !is_int(key($config[$key]))) {
                        $config[$key] = array($config[$key]);
                    }
                    $config[$key][] = $value;
                } else {
                    $config[$key] = $value;
                }

                $empty = false;
            }
        }

        if (false !== $nodeValue) {
            $value = static::phpize($nodeValue);
            if (count($config)) {
                $config['value'] = $value;
            } else {
                $config = $value;
            }
        }

        return !$empty ? $config : null;
    }

    /**
     * Converts an xml value to a PHP type.
     *
     * @param mixed $value
     *
     * @return mixed
     */
    public static function phpize($value)
    {
        $value = (string) $value;
        $lowercaseValue = strtolower($value);

        switch (true) {
            case 'null' === $lowercaseValue:
                return null;
            case ctype_digit($value):
                $raw = $value;
                $cast = intval($value);

                return '0' == $value[0] ? octdec($value) : (((string) $raw == (string) $cast) ? $cast : $raw);
            case isset($value[1]) && '-' === $value[0] && ctype_digit(substr($value, 1)):
                $raw = $value;
                $cast = intval($value);

                return '0' == $value[1] ? octdec($value) : (((string) $raw == (string) $cast) ? $cast : $raw);
            case 'true' === $lowercaseValue:
                return true;
            case 'false' === $lowercaseValue:
                return false;
            case isset($value[1]) && '0b' == $value[0].$value[1]:
                return bindec($value);
            case is_numeric($value):
                return '0x' == $value[0].$value[1] ? hexdec($value) : floatval($value);
            case preg_match('/^(-|\+)?[0-9]+(\.[0-9]+)?$/', $value):
                return floatval($value);
            default:
                return $value;
        }
    }

    protected static function getXmlErrors($internalErrors)
    {
        $errors = array();
        foreach (libxml_get_errors() as $error) {
            $errors[] = sprintf('[%s %s] %s (in %s - line %d, column %d)',
                LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR',
                $error->code,
                trim($error->message),
                $error->file ? $error->file : 'n/a',
                $error->line,
                $error->column
            );
        }

        libxml_clear_errors();
        libxml_use_internal_errors($internalErrors);

        return $errors;
    }
}
PK��ZI��(Symfony/Component/Config/FileLocator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config;

/**
 * FileLocator uses an array of pre-defined paths to find files.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FileLocator implements FileLocatorInterface
{
    protected $paths;

    /**
     * Constructor.
     *
     * @param string|array $paths A path or an array of paths where to look for resources
     */
    public function __construct($paths = array())
    {
        $this->paths = (array) $paths;
    }

    /**
     * Returns a full path for a given file name.
     *
     * @param mixed   $name        The file name to locate
     * @param string  $currentPath The current path
     * @param Boolean $first       Whether to return the first occurrence or an array of filenames
     *
     * @return string|array The full path to the file|An array of file paths
     *
     * @throws \InvalidArgumentException When file is not found
     */
    public function locate($name, $currentPath = null, $first = true)
    {
        if ($this->isAbsolutePath($name)) {
            if (!file_exists($name)) {
                throw new \InvalidArgumentException(sprintf('The file "%s" does not exist.', $name));
            }

            return $name;
        }

        $filepaths = array();
        if (null !== $currentPath && file_exists($file = $currentPath.DIRECTORY_SEPARATOR.$name)) {
            if (true === $first) {
                return $file;
            }
            $filepaths[] = $file;
        }

        foreach ($this->paths as $path) {
            if (file_exists($file = $path.DIRECTORY_SEPARATOR.$name)) {
                if (true === $first) {
                    return $file;
                }
                $filepaths[] = $file;
            }
        }

        if (!$filepaths) {
            throw new \InvalidArgumentException(sprintf('The file "%s" does not exist (in: %s%s).', $name, null !== $currentPath ? $currentPath.', ' : '', implode(', ', $this->paths)));
        }

        return array_values(array_unique($filepaths));
    }

    /**
     * Returns whether the file path is an absolute path.
     *
     * @param string $file A file path
     *
     * @return Boolean
     */
    private function isAbsolutePath($file)
    {
        if ($file[0] == '/' || $file[0] == '\\'
            || (strlen($file) > 3 && ctype_alpha($file[0])
                && $file[1] == ':'
                && ($file[2] == '\\' || $file[2] == '/')
            )
            || null !== parse_url($file, PHP_URL_SCHEME)
        ) {
            return true;
        }

        return false;
    }
}
PK��Z__wP<
<
.Symfony/Component/Config/Loader/FileLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Loader;

use Symfony\Component\Config\FileLocatorInterface;
use Symfony\Component\Config\Exception\FileLoaderLoadException;
use Symfony\Component\Config\Exception\FileLoaderImportCircularReferenceException;

/**
 * FileLoader is the abstract class used by all built-in loaders that are file based.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class FileLoader extends Loader
{
    protected static $loading = array();

    protected $locator;

    private $currentDir;

    /**
     * Constructor.
     *
     * @param FileLocatorInterface $locator A FileLocatorInterface instance
     */
    public function __construct(FileLocatorInterface $locator)
    {
        $this->locator = $locator;
    }

    public function setCurrentDir($dir)
    {
        $this->currentDir = $dir;
    }

    public function getLocator()
    {
        return $this->locator;
    }

    /**
     * Imports a resource.
     *
     * @param mixed   $resource       A Resource
     * @param string  $type           The resource type
     * @param Boolean $ignoreErrors   Whether to ignore import errors or not
     * @param string  $sourceResource The original resource importing the new resource
     *
     * @return mixed
     *
     * @throws FileLoaderLoadException
     * @throws FileLoaderImportCircularReferenceException
     */
    public function import($resource, $type = null, $ignoreErrors = false, $sourceResource = null)
    {
        try {
            $loader = $this->resolve($resource, $type);

            if ($loader instanceof FileLoader && null !== $this->currentDir) {
                // we fallback to the current locator to keep BC
                // as some some loaders do not call the parent __construct()
                // @deprecated should be removed in 3.0
                $locator = $loader->getLocator() ?: $this->locator;
                $resource = $locator->locate($resource, $this->currentDir, false);
            }

            $resources = is_array($resource) ? $resource : array($resource);
            for ($i = 0; $i < $resourcesCount = count($resources); $i++ ) {
                if (isset(self::$loading[$resources[$i]])) {
                    if ($i == $resourcesCount-1) {
                        throw new FileLoaderImportCircularReferenceException(array_keys(self::$loading));
                    }
                } else {
                    $resource = $resources[$i];
                    break;
                }
            }
            self::$loading[$resource] = true;

            $ret = $loader->load($resource, $type);

            unset(self::$loading[$resource]);

            return $ret;
        } catch (FileLoaderImportCircularReferenceException $e) {
            throw $e;
        } catch (\Exception $e) {
            if (!$ignoreErrors) {
                // prevent embedded imports from nesting multiple exceptions
                if ($e instanceof FileLoaderLoadException) {
                    throw $e;
                }

                throw new FileLoaderLoadException($resource, $sourceResource, null, $e);
            }
        }
    }
}
PK��Z���))4Symfony/Component/Config/Loader/DelegatingLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Loader;

use Symfony\Component\Config\Exception\FileLoaderLoadException;

/**
 * DelegatingLoader delegates loading to other loaders using a loader resolver.
 *
 * This loader acts as an array of LoaderInterface objects - each having
 * a chance to load a given resource (handled by the resolver)
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class DelegatingLoader extends Loader
{
    /**
     * Constructor.
     *
     * @param LoaderResolverInterface $resolver A LoaderResolverInterface instance
     */
    public function __construct(LoaderResolverInterface $resolver)
    {
        $this->resolver = $resolver;
    }

    /**
     * Loads a resource.
     *
     * @param mixed  $resource A resource
     * @param string $type     The resource type
     *
     * @return mixed
     *
     * @throws FileLoaderLoadException if no loader is found.
     */
    public function load($resource, $type = null)
    {
        if (false === $loader = $this->resolver->resolve($resource, $type)) {
            throw new FileLoaderLoadException($resource);
        }

        return $loader->load($resource, $type);
    }

    /**
     * {@inheritdoc}
     */
    public function supports($resource, $type = null)
    {
        return false !== $this->resolver->resolve($resource, $type);
    }
}
PK��Z������;Symfony/Component/Config/Loader/LoaderResolverInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Loader;

/**
 * LoaderResolverInterface selects a loader for a given resource.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface LoaderResolverInterface
{
    /**
     * Returns a loader able to load the resource.
     *
     * @param mixed  $resource A resource
     * @param string $type     The resource type
     *
     * @return LoaderInterface A LoaderInterface instance
     */
    public function resolve($resource, $type = null);
}
PK��ZHPʉ�2Symfony/Component/Config/Loader/LoaderResolver.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Loader;

/**
 * LoaderResolver selects a loader for a given resource.
 *
 * A resource can be anything (e.g. a full path to a config file or a Closure).
 * Each loader determines whether it can load a resource and how.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class LoaderResolver implements LoaderResolverInterface
{
    /**
     * @var LoaderInterface[] An array of LoaderInterface objects
     */
    private $loaders = array();

    /**
     * Constructor.
     *
     * @param LoaderInterface[] $loaders An array of loaders
     */
    public function __construct(array $loaders = array())
    {
        foreach ($loaders as $loader) {
            $this->addLoader($loader);
        }
    }

    /**
     * Returns a loader able to load the resource.
     *
     * @param mixed  $resource A resource
     * @param string $type     The resource type
     *
     * @return LoaderInterface|false A LoaderInterface instance
     */
    public function resolve($resource, $type = null)
    {
        foreach ($this->loaders as $loader) {
            if ($loader->supports($resource, $type)) {
                return $loader;
            }
        }

        return false;
    }

    /**
     * Adds a loader.
     *
     * @param LoaderInterface $loader A LoaderInterface instance
     */
    public function addLoader(LoaderInterface $loader)
    {
        $this->loaders[] = $loader;
        $loader->setResolver($this);
    }

    /**
     * Returns the registered loaders.
     *
     * @return LoaderInterface[] An array of LoaderInterface instances
     */
    public function getLoaders()
    {
        return $this->loaders;
    }
}
PK��Z�=���*Symfony/Component/Config/Loader/Loader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Loader;

use Symfony\Component\Config\Exception\FileLoaderLoadException;

/**
 * Loader is the abstract class used by all built-in loaders.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class Loader implements LoaderInterface
{
    protected $resolver;

    /**
     * Gets the loader resolver.
     *
     * @return LoaderResolverInterface A LoaderResolverInterface instance
     */
    public function getResolver()
    {
        return $this->resolver;
    }

    /**
     * Sets the loader resolver.
     *
     * @param LoaderResolverInterface $resolver A LoaderResolverInterface instance
     */
    public function setResolver(LoaderResolverInterface $resolver)
    {
        $this->resolver = $resolver;
    }

    /**
     * Imports a resource.
     *
     * @param mixed  $resource A Resource
     * @param string $type     The resource type
     *
     * @return mixed
     */
    public function import($resource, $type = null)
    {
        return $this->resolve($resource, $type)->load($resource, $type);
    }

    /**
     * Finds a loader able to load an imported resource.
     *
     * @param mixed  $resource A Resource
     * @param string $type     The resource type
     *
     * @return LoaderInterface A LoaderInterface instance
     *
     * @throws FileLoaderLoadException if no loader is found
     */
    public function resolve($resource, $type = null)
    {
        if ($this->supports($resource, $type)) {
            return $this;
        }

        $loader = null === $this->resolver ? false : $this->resolver->resolve($resource, $type);

        if (false === $loader) {
            throw new FileLoaderLoadException($resource);
        }

        return $loader;
    }
}
PK��Z���4993Symfony/Component/Config/Loader/LoaderInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Loader;

/**
 * LoaderInterface is the interface implemented by all loader classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface LoaderInterface
{
    /**
     * Loads a resource.
     *
     * @param mixed  $resource The resource
     * @param string $type     The resource type
     */
    public function load($resource, $type = null);

    /**
     * Returns true if this class supports the given resource.
     *
     * @param mixed  $resource A resource
     * @param string $type     The resource type
     *
     * @return Boolean true if this class supports the given resource, false otherwise
     */
    public function supports($resource, $type = null);

    /**
     * Gets the loader resolver.
     *
     * @return LoaderResolverInterface A LoaderResolverInterface instance
     */
    public function getResolver();

    /**
     * Sets the loader resolver.
     *
     * @param LoaderResolverInterface $resolver A LoaderResolverInterface instance
     */
    public function setResolver(LoaderResolverInterface $resolver);

}
PK��Z��:a�
�
(Symfony/Component/Config/ConfigCache.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config;

use Symfony\Component\Config\Resource\ResourceInterface;
use Symfony\Component\Filesystem\Filesystem;

/**
 * ConfigCache manages PHP cache files.
 *
 * When debug is enabled, it knows when to flush the cache
 * thanks to an array of ResourceInterface instances.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ConfigCache
{
    private $debug;
    private $file;

    /**
     * Constructor.
     *
     * @param string  $file  The absolute cache path
     * @param Boolean $debug Whether debugging is enabled or not
     */
    public function __construct($file, $debug)
    {
        $this->file = $file;
        $this->debug = (Boolean) $debug;
    }

    /**
     * Gets the cache file path.
     *
     * @return string The cache file path
     */
    public function __toString()
    {
        return $this->file;
    }

    /**
     * Checks if the cache is still fresh.
     *
     * This method always returns true when debug is off and the
     * cache file exists.
     *
     * @return Boolean true if the cache is fresh, false otherwise
     */
    public function isFresh()
    {
        if (!is_file($this->file)) {
            return false;
        }

        if (!$this->debug) {
            return true;
        }

        $metadata = $this->getMetaFile();
        if (!is_file($metadata)) {
            return false;
        }

        $time = filemtime($this->file);
        $meta = unserialize(file_get_contents($metadata));
        foreach ($meta as $resource) {
            if (!$resource->isFresh($time)) {
                return false;
            }
        }

        return true;
    }

    /**
     * Writes cache.
     *
     * @param string              $content  The content to write in the cache
     * @param ResourceInterface[] $metadata An array of ResourceInterface instances
     *
     * @throws \RuntimeException When cache file can't be wrote
     */
    public function write($content, array $metadata = null)
    {
        $mode = 0666 & ~umask();
        $filesystem = new Filesystem();
        $filesystem->dumpFile($this->file, $content, null);
        @chmod($this->file, $mode);

        if (null !== $metadata && true === $this->debug) {
            $filesystem->dumpFile($this->getMetaFile(), serialize($metadata), null);
            @chmod($this->getMetaFile(), $mode);
        }
    }

    /**
     * Gets the meta file path.
     *
     * @return string The meta file path
     */
    private function getMetaFile()
    {
        return $this->file.'.meta';
    }

}
PK��Z\�[���0Symfony/Component/HttpKernel/KernelInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
use Symfony\Component\Config\Loader\LoaderInterface;

/**
 * The Kernel is the heart of the Symfony system.
 *
 * It manages an environment made of bundles.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface KernelInterface extends HttpKernelInterface, \Serializable
{
    /**
     * Returns an array of bundles to register.
     *
     * @return BundleInterface[] An array of bundle instances.
     *
     * @api
     */
    public function registerBundles();

    /**
     * Loads the container configuration.
     *
     * @param LoaderInterface $loader A LoaderInterface instance
     *
     * @api
     */
    public function registerContainerConfiguration(LoaderInterface $loader);

    /**
     * Boots the current kernel.
     *
     * @api
     */
    public function boot();

    /**
     * Shutdowns the kernel.
     *
     * This method is mainly useful when doing functional testing.
     *
     * @api
     */
    public function shutdown();

    /**
     * Gets the registered bundle instances.
     *
     * @return BundleInterface[] An array of registered bundle instances
     *
     * @api
     */
    public function getBundles();

    /**
     * Checks if a given class name belongs to an active bundle.
     *
     * @param string $class A class name
     *
     * @return Boolean true if the class belongs to an active bundle, false otherwise
     *
     * @api
     */
    public function isClassInActiveBundle($class);

    /**
     * Returns a bundle and optionally its descendants by its name.
     *
     * @param string  $name  Bundle name
     * @param Boolean $first Whether to return the first bundle only or together with its descendants
     *
     * @return BundleInterface|BundleInterface[] A BundleInterface instance or an array of BundleInterface instances if $first is false
     *
     * @throws \InvalidArgumentException when the bundle is not enabled
     *
     * @api
     */
    public function getBundle($name, $first = true);

    /**
     * Returns the file path for a given resource.
     *
     * A Resource can be a file or a directory.
     *
     * The resource name must follow the following pattern:
     *
     *     @BundleName/path/to/a/file.something
     *
     * where BundleName is the name of the bundle
     * and the remaining part is the relative path in the bundle.
     *
     * If $dir is passed, and the first segment of the path is Resources,
     * this method will look for a file named:
     *
     *     $dir/BundleName/path/without/Resources
     *
     * @param string  $name  A resource name to locate
     * @param string  $dir   A directory where to look for the resource first
     * @param Boolean $first Whether to return the first path or paths for all matching bundles
     *
     * @return string|array The absolute path of the resource or an array if $first is false
     *
     * @throws \InvalidArgumentException if the file cannot be found or the name is not valid
     * @throws \RuntimeException         if the name contains invalid/unsafe characters
     *
     * @api
     */
    public function locateResource($name, $dir = null, $first = true);

    /**
     * Gets the name of the kernel.
     *
     * @return string The kernel name
     *
     * @api
     */
    public function getName();

    /**
     * Gets the environment.
     *
     * @return string The current environment
     *
     * @api
     */
    public function getEnvironment();

    /**
     * Checks if debug mode is enabled.
     *
     * @return Boolean true if debug mode is enabled, false otherwise
     *
     * @api
     */
    public function isDebug();

    /**
     * Gets the application root dir.
     *
     * @return string The application root dir
     *
     * @api
     */
    public function getRootDir();

    /**
     * Gets the current container.
     *
     * @return ContainerInterface A ContainerInterface instance
     *
     * @api
     */
    public function getContainer();

    /**
     * Gets the request start time (not available if debug is disabled).
     *
     * @return integer The request start timestamp
     *
     * @api
     */
    public function getStartTime();

    /**
     * Gets the cache directory.
     *
     * @return string The cache directory
     *
     * @api
     */
    public function getCacheDir();

    /**
     * Gets the log directory.
     *
     * @return string The log directory
     *
     * @api
     */
    public function getLogDir();

    /**
     * Gets the charset of the application.
     *
     * @return string The charset
     *
     * @api
     */
    public function getCharset();
}
PK��Z�?.��\�\'Symfony/Component/HttpKernel/Kernel.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel;

use Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator;
use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
use Symfony\Component\DependencyInjection\Loader\ClosureLoader;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
use Symfony\Component\HttpKernel\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass;
use Symfony\Component\HttpKernel\DependencyInjection\AddClassesToCachePass;
use Symfony\Component\Config\Loader\LoaderResolver;
use Symfony\Component\Config\Loader\DelegatingLoader;
use Symfony\Component\Config\ConfigCache;
use Symfony\Component\ClassLoader\ClassCollectionLoader;

/**
 * The Kernel is the heart of the Symfony system.
 *
 * It manages an environment made of bundles.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
abstract class Kernel implements KernelInterface, TerminableInterface
{
    /**
     * @var BundleInterface[]
     */
    protected $bundles = array();

    protected $bundleMap;
    protected $container;
    protected $rootDir;
    protected $environment;
    protected $debug;
    protected $booted = false;
    protected $name;
    protected $startTime;
    protected $loadClassCache;

    const VERSION         = '2.4.3';
    const VERSION_ID      = '20403';
    const MAJOR_VERSION   = '2';
    const MINOR_VERSION   = '4';
    const RELEASE_VERSION = '3';
    const EXTRA_VERSION   = '';

    /**
     * Constructor.
     *
     * @param string  $environment The environment
     * @param Boolean $debug       Whether to enable debugging or not
     *
     * @api
     */
    public function __construct($environment, $debug)
    {
        $this->environment = $environment;
        $this->debug = (Boolean) $debug;
        $this->rootDir = $this->getRootDir();
        $this->name = $this->getName();

        if ($this->debug) {
            $this->startTime = microtime(true);
        }

        $this->init();
    }

    /**
     * @deprecated Deprecated since version 2.3, to be removed in 3.0. Move your logic in the constructor instead.
     */
    public function init()
    {
    }

    public function __clone()
    {
        if ($this->debug) {
            $this->startTime = microtime(true);
        }

        $this->booted = false;
        $this->container = null;
    }

    /**
     * Boots the current kernel.
     *
     * @api
     */
    public function boot()
    {
        if (true === $this->booted) {
            return;
        }

        if ($this->loadClassCache) {
            $this->doLoadClassCache($this->loadClassCache[0], $this->loadClassCache[1]);
        }

        // init bundles
        $this->initializeBundles();

        // init container
        $this->initializeContainer();

        foreach ($this->getBundles() as $bundle) {
            $bundle->setContainer($this->container);
            $bundle->boot();
        }

        $this->booted = true;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function terminate(Request $request, Response $response)
    {
        if (false === $this->booted) {
            return;
        }

        if ($this->getHttpKernel() instanceof TerminableInterface) {
            $this->getHttpKernel()->terminate($request, $response);
        }
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function shutdown()
    {
        if (false === $this->booted) {
            return;
        }

        $this->booted = false;

        foreach ($this->getBundles() as $bundle) {
            $bundle->shutdown();
            $bundle->setContainer(null);
        }

        $this->container = null;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
    {
        if (false === $this->booted) {
            $this->boot();
        }

        return $this->getHttpKernel()->handle($request, $type, $catch);
    }

    /**
     * Gets a HTTP kernel from the container
     *
     * @return HttpKernel
     */
    protected function getHttpKernel()
    {
        return $this->container->get('http_kernel');
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function getBundles()
    {
        return $this->bundles;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function isClassInActiveBundle($class)
    {
        foreach ($this->getBundles() as $bundle) {
            if (0 === strpos($class, $bundle->getNamespace())) {
                return true;
            }
        }

        return false;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function getBundle($name, $first = true)
    {
        if (!isset($this->bundleMap[$name])) {
            throw new \InvalidArgumentException(sprintf('Bundle "%s" does not exist or it is not enabled. Maybe you forgot to add it in the registerBundles() method of your %s.php file?', $name, get_class($this)));
        }

        if (true === $first) {
            return $this->bundleMap[$name][0];
        }

        return $this->bundleMap[$name];
    }

    /**
     * Returns the file path for a given resource.
     *
     * A Resource can be a file or a directory.
     *
     * The resource name must follow the following pattern:
     *
     *     @<BundleName>/path/to/a/file.something
     *
     * where BundleName is the name of the bundle
     * and the remaining part is the relative path in the bundle.
     *
     * If $dir is passed, and the first segment of the path is "Resources",
     * this method will look for a file named:
     *
     *     $dir/<BundleName>/path/without/Resources
     *
     * before looking in the bundle resource folder.
     *
     * @param string  $name  A resource name to locate
     * @param string  $dir   A directory where to look for the resource first
     * @param Boolean $first Whether to return the first path or paths for all matching bundles
     *
     * @return string|array The absolute path of the resource or an array if $first is false
     *
     * @throws \InvalidArgumentException if the file cannot be found or the name is not valid
     * @throws \RuntimeException         if the name contains invalid/unsafe
     * @throws \RuntimeException         if a custom resource is hidden by a resource in a derived bundle
     *
     * @api
     */
    public function locateResource($name, $dir = null, $first = true)
    {
        if ('@' !== $name[0]) {
            throw new \InvalidArgumentException(sprintf('A resource name must start with @ ("%s" given).', $name));
        }

        if (false !== strpos($name, '..')) {
            throw new \RuntimeException(sprintf('File name "%s" contains invalid characters (..).', $name));
        }

        $bundleName = substr($name, 1);
        $path = '';
        if (false !== strpos($bundleName, '/')) {
            list($bundleName, $path) = explode('/', $bundleName, 2);
        }

        $isResource = 0 === strpos($path, 'Resources') && null !== $dir;
        $overridePath = substr($path, 9);
        $resourceBundle = null;
        $bundles = $this->getBundle($bundleName, false);
        $files = array();

        foreach ($bundles as $bundle) {
            if ($isResource && file_exists($file = $dir.'/'.$bundle->getName().$overridePath)) {
                if (null !== $resourceBundle) {
                    throw new \RuntimeException(sprintf('"%s" resource is hidden by a resource from the "%s" derived bundle. Create a "%s" file to override the bundle resource.',
                        $file,
                        $resourceBundle,
                        $dir.'/'.$bundles[0]->getName().$overridePath
                    ));
                }

                if ($first) {
                    return $file;
                }
                $files[] = $file;
            }

            if (file_exists($file = $bundle->getPath().'/'.$path)) {
                if ($first && !$isResource) {
                    return $file;
                }
                $files[] = $file;
                $resourceBundle = $bundle->getName();
            }
        }

        if (count($files) > 0) {
            return $first && $isResource ? $files[0] : $files;
        }

        throw new \InvalidArgumentException(sprintf('Unable to find file "%s".', $name));
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function getName()
    {
        if (null === $this->name) {
            $this->name = preg_replace('/[^a-zA-Z0-9_]+/', '', basename($this->rootDir));
        }

        return $this->name;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function getEnvironment()
    {
        return $this->environment;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function isDebug()
    {
        return $this->debug;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function getRootDir()
    {
        if (null === $this->rootDir) {
            $r = new \ReflectionObject($this);
            $this->rootDir = str_replace('\\', '/', dirname($r->getFileName()));
        }

        return $this->rootDir;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function getContainer()
    {
        return $this->container;
    }

    /**
     * Loads the PHP class cache.
     *
     * This methods only registers the fact that you want to load the cache classes.
     * The cache will actually only be loaded when the Kernel is booted.
     *
     * That optimization is mainly useful when using the HttpCache class in which
     * case the class cache is not loaded if the Response is in the cache.
     *
     * @param string $name      The cache name prefix
     * @param string $extension File extension of the resulting file
     */
    public function loadClassCache($name = 'classes', $extension = '.php')
    {
        $this->loadClassCache = array($name, $extension);
    }

    /**
     * Used internally.
     */
    public function setClassCache(array $classes)
    {
        file_put_contents($this->getCacheDir().'/classes.map', sprintf('<?php return %s;', var_export($classes, true)));
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function getStartTime()
    {
        return $this->debug ? $this->startTime : -INF;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function getCacheDir()
    {
        return $this->rootDir.'/cache/'.$this->environment;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function getLogDir()
    {
        return $this->rootDir.'/logs';
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function getCharset()
    {
        return 'UTF-8';
    }

    protected function doLoadClassCache($name, $extension)
    {
        if (!$this->booted && is_file($this->getCacheDir().'/classes.map')) {
            ClassCollectionLoader::load(include($this->getCacheDir().'/classes.map'), $this->getCacheDir(), $name, $this->debug, false, $extension);
        }
    }

    /**
     * Initializes the data structures related to the bundle management.
     *
     *  - the bundles property maps a bundle name to the bundle instance,
     *  - the bundleMap property maps a bundle name to the bundle inheritance hierarchy (most derived bundle first).
     *
     * @throws \LogicException if two bundles share a common name
     * @throws \LogicException if a bundle tries to extend a non-registered bundle
     * @throws \LogicException if a bundle tries to extend itself
     * @throws \LogicException if two bundles extend the same ancestor
     */
    protected function initializeBundles()
    {
        // init bundles
        $this->bundles = array();
        $topMostBundles = array();
        $directChildren = array();

        foreach ($this->registerBundles() as $bundle) {
            $name = $bundle->getName();
            if (isset($this->bundles[$name])) {
                throw new \LogicException(sprintf('Trying to register two bundles with the same name "%s"', $name));
            }
            $this->bundles[$name] = $bundle;

            if ($parentName = $bundle->getParent()) {
                if (isset($directChildren[$parentName])) {
                    throw new \LogicException(sprintf('Bundle "%s" is directly extended by two bundles "%s" and "%s".', $parentName, $name, $directChildren[$parentName]));
                }
                if ($parentName == $name) {
                    throw new \LogicException(sprintf('Bundle "%s" can not extend itself.', $name));
                }
                $directChildren[$parentName] = $name;
            } else {
                $topMostBundles[$name] = $bundle;
            }
        }

        // look for orphans
        if (!empty($directChildren) && count($diff = array_diff_key($directChildren, $this->bundles))) {
            $diff = array_keys($diff);

            throw new \LogicException(sprintf('Bundle "%s" extends bundle "%s", which is not registered.', $directChildren[$diff[0]], $diff[0]));
        }

        // inheritance
        $this->bundleMap = array();
        foreach ($topMostBundles as $name => $bundle) {
            $bundleMap = array($bundle);
            $hierarchy = array($name);

            while (isset($directChildren[$name])) {
                $name = $directChildren[$name];
                array_unshift($bundleMap, $this->bundles[$name]);
                $hierarchy[] = $name;
            }

            foreach ($hierarchy as $bundle) {
                $this->bundleMap[$bundle] = $bundleMap;
                array_pop($bundleMap);
            }
        }

    }

    /**
     * Gets the container class.
     *
     * @return string The container class
     */
    protected function getContainerClass()
    {
        return $this->name.ucfirst($this->environment).($this->debug ? 'Debug' : '').'ProjectContainer';
    }

    /**
     * Gets the container's base class.
     *
     * All names except Container must be fully qualified.
     *
     * @return string
     */
    protected function getContainerBaseClass()
    {
        return 'Container';
    }

    /**
     * Initializes the service container.
     *
     * The cached version of the service container is used when fresh, otherwise the
     * container is built.
     */
    protected function initializeContainer()
    {
        $class = $this->getContainerClass();
        $cache = new ConfigCache($this->getCacheDir().'/'.$class.'.php', $this->debug);
        $fresh = true;
        if (!$cache->isFresh()) {
            $container = $this->buildContainer();
            $container->compile();
            $this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass());

            $fresh = false;
        }

        require_once $cache;

        $this->container = new $class();
        $this->container->set('kernel', $this);

        if (!$fresh && $this->container->has('cache_warmer')) {
            $this->container->get('cache_warmer')->warmUp($this->container->getParameter('kernel.cache_dir'));
        }
    }

    /**
     * Returns the kernel parameters.
     *
     * @return array An array of kernel parameters
     */
    protected function getKernelParameters()
    {
        $bundles = array();
        foreach ($this->bundles as $name => $bundle) {
            $bundles[$name] = get_class($bundle);
        }

        return array_merge(
            array(
                'kernel.root_dir'        => $this->rootDir,
                'kernel.environment'     => $this->environment,
                'kernel.debug'           => $this->debug,
                'kernel.name'            => $this->name,
                'kernel.cache_dir'       => $this->getCacheDir(),
                'kernel.logs_dir'        => $this->getLogDir(),
                'kernel.bundles'         => $bundles,
                'kernel.charset'         => $this->getCharset(),
                'kernel.container_class' => $this->getContainerClass(),
            ),
            $this->getEnvParameters()
        );
    }

    /**
     * Gets the environment parameters.
     *
     * Only the parameters starting with "SYMFONY__" are considered.
     *
     * @return array An array of parameters
     */
    protected function getEnvParameters()
    {
        $parameters = array();
        foreach ($_SERVER as $key => $value) {
            if (0 === strpos($key, 'SYMFONY__')) {
                $parameters[strtolower(str_replace('__', '.', substr($key, 9)))] = $value;
            }
        }

        return $parameters;
    }

    /**
     * Builds the service container.
     *
     * @return ContainerBuilder The compiled service container
     *
     * @throws \RuntimeException
     */
    protected function buildContainer()
    {
        foreach (array('cache' => $this->getCacheDir(), 'logs' => $this->getLogDir()) as $name => $dir) {
            if (!is_dir($dir)) {
                if (false === @mkdir($dir, 0777, true)) {
                    throw new \RuntimeException(sprintf("Unable to create the %s directory (%s)\n", $name, $dir));
                }
            } elseif (!is_writable($dir)) {
                throw new \RuntimeException(sprintf("Unable to write in the %s directory (%s)\n", $name, $dir));
            }
        }

        $container = $this->getContainerBuilder();
        $container->addObjectResource($this);
        $this->prepareContainer($container);

        if (null !== $cont = $this->registerContainerConfiguration($this->getContainerLoader($container))) {
            $container->merge($cont);
        }

        $container->addCompilerPass(new AddClassesToCachePass($this));

        return $container;
    }

    /**
     * Prepares the ContainerBuilder before it is compiled.
     *
     * @param ContainerBuilder $container A ContainerBuilder instance
     */
    protected function prepareContainer(ContainerBuilder $container)
    {
        $extensions = array();
        foreach ($this->bundles as $bundle) {
            if ($extension = $bundle->getContainerExtension()) {
                $container->registerExtension($extension);
                $extensions[] = $extension->getAlias();
            }

            if ($this->debug) {
                $container->addObjectResource($bundle);
            }
        }
        foreach ($this->bundles as $bundle) {
            $bundle->build($container);
        }

        // ensure these extensions are implicitly loaded
        $container->getCompilerPassConfig()->setMergePass(new MergeExtensionConfigurationPass($extensions));
    }

    /**
     * Gets a new ContainerBuilder instance used to build the service container.
     *
     * @return ContainerBuilder
     */
    protected function getContainerBuilder()
    {
        $container = new ContainerBuilder(new ParameterBag($this->getKernelParameters()));

        if (class_exists('ProxyManager\Configuration')) {
            $container->setProxyInstantiator(new RuntimeInstantiator());
        }

        return $container;
    }

    /**
     * Dumps the service container to PHP code in the cache.
     *
     * @param ConfigCache      $cache     The config cache
     * @param ContainerBuilder $container The service container
     * @param string           $class     The name of the class to generate
     * @param string           $baseClass The name of the container's base class
     */
    protected function dumpContainer(ConfigCache $cache, ContainerBuilder $container, $class, $baseClass)
    {
        // cache the container
        $dumper = new PhpDumper($container);

        if (class_exists('ProxyManager\Configuration')) {
            $dumper->setProxyDumper(new ProxyDumper());
        }

        $content = $dumper->dump(array('class' => $class, 'base_class' => $baseClass));
        if (!$this->debug) {
            $content = static::stripComments($content);
        }

        $cache->write($content, $container->getResources());
    }

    /**
     * Returns a loader for the container.
     *
     * @param ContainerInterface $container The service container
     *
     * @return DelegatingLoader The loader
     */
    protected function getContainerLoader(ContainerInterface $container)
    {
        $locator = new FileLocator($this);
        $resolver = new LoaderResolver(array(
            new XmlFileLoader($container, $locator),
            new YamlFileLoader($container, $locator),
            new IniFileLoader($container, $locator),
            new PhpFileLoader($container, $locator),
            new ClosureLoader($container),
        ));

        return new DelegatingLoader($resolver);
    }

    /**
     * Removes comments from a PHP source string.
     *
     * We don't use the PHP php_strip_whitespace() function
     * as we want the content to be readable and well-formatted.
     *
     * @param string $source A PHP string
     *
     * @return string The PHP string with the comments removed
     */
    public static function stripComments($source)
    {
        if (!function_exists('token_get_all')) {
            return $source;
        }

        $rawChunk = '';
        $output = '';
        $tokens = token_get_all($source);
        $ignoreSpace = false;
        for (reset($tokens); false !== $token = current($tokens); next($tokens)) {
            if (is_string($token)) {
                $rawChunk .= $token;
            } elseif (T_START_HEREDOC === $token[0]) {
                $output .= $rawChunk.$token[1];
                do {
                    $token = next($tokens);
                    $output .= $token[1];
                } while ($token[0] !== T_END_HEREDOC);
                $rawChunk = '';
            } elseif (T_WHITESPACE === $token[0]) {
                if ($ignoreSpace) {
                    $ignoreSpace = false;

                    continue;
                }

                // replace multiple new lines with a single newline
                $rawChunk .= preg_replace(array('/\n{2,}/S'), "\n", $token[1]);
            } elseif (in_array($token[0], array(T_COMMENT, T_DOC_COMMENT))) {
                $ignoreSpace = true;
            } else {
                $rawChunk .= $token[1];

                // The PHP-open tag already has a new-line
                if (T_OPEN_TAG === $token[0]) {
                    $ignoreSpace = true;
                }
            }
        }

        $output .= $rawChunk;

        return $output;
    }

    public function serialize()
    {
        return serialize(array($this->environment, $this->debug));
    }

    public function unserialize($data)
    {
        list($environment, $debug) = unserialize($data);

        $this->__construct($environment, $debug);
    }
}
PK��Z���?Symfony/Component/HttpKernel/CacheClearer/ChainCacheClearer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\CacheClearer;

/**
 * ChainCacheClearer.
 *
 * @author Dustin Dobervich <ddobervich@gmail.com>
 */
class ChainCacheClearer implements CacheClearerInterface
{
    /**
     * @var array $clearers
     */
    protected $clearers;

    /**
     * Constructs a new instance of ChainCacheClearer.
     *
     * @param array $clearers The initial clearers.
     */
    public function __construct(array $clearers = array())
    {
        $this->clearers = $clearers;
    }

    /**
     * {@inheritDoc}
     */
    public function clear($cacheDir)
    {
        foreach ($this->clearers as $clearer) {
            $clearer->clear($cacheDir);
        }
    }

    /**
     * Adds a cache clearer to the aggregate.
     *
     * @param CacheClearerInterface $clearer
     */
    public function add(CacheClearerInterface $clearer)
    {
        $this->clearers[] = $clearer;
    }
}
PK��ZYxځ55CSymfony/Component/HttpKernel/CacheClearer/CacheClearerInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\CacheClearer;

/**
 * CacheClearerInterface.
 *
 * @author Dustin Dobervich <ddobervich@gmail.com>
 */
interface CacheClearerInterface
{
    /**
     * Clears any caches necessary.
     *
     * @param string $cacheDir The cache directory.
     */
    public function clear($cacheDir);
}
PK��Z�zTT+Symfony/Component/HttpKernel/autoloader.phpnu�[���<?php

spl_autoload_register(function ($class) {
    if ('\\' == $class[0]) {
        $class = substr($class, 1);
    }

    if (
        0 === strpos($class, 'Symfony\\Component\\HttpKernel\\')
        &&
        file_exists($file = __DIR__.'/../../../'.str_replace('\\', '/', $class).'.php')
    ) {
        require_once $file;
    }
});
PK��Z_��S77ASymfony/Component/HttpKernel/CacheWarmer/CacheWarmerInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\CacheWarmer;

/**
 * Interface for classes able to warm up the cache.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface CacheWarmerInterface extends WarmableInterface
{
    /**
     * Checks whether this warmer is optional or not.
     *
     * Optional warmers can be ignored on certain conditions.
     *
     * A warmer should return true if the cache can be
     * generated incrementally and on-demand.
     *
     * @return Boolean true if the warmer is optional, false otherwise
     */
    public function isOptional();
}
PK��Z���^FF>Symfony/Component/HttpKernel/CacheWarmer/WarmableInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\CacheWarmer;

/**
 * Interface for classes that support warming their cache.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface WarmableInterface
{
    /**
     * Warms up the cache.
     *
     * @param string $cacheDir The cache directory
     */
    public function warmUp($cacheDir);
}
PK��Z��8ee8Symfony/Component/HttpKernel/CacheWarmer/CacheWarmer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\CacheWarmer;

/**
 * Abstract cache warmer that knows how to write a file to the cache.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class CacheWarmer implements CacheWarmerInterface
{
    protected function writeCacheFile($file, $content)
    {
        $tmpFile = tempnam(dirname($file), basename($file));
        if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $file)) {
            @chmod($file, 0666 & ~umask());

            return;
        }

        throw new \RuntimeException(sprintf('Failed to write cache file "%s".', $file));
    }
}
PK��Z�R�!MMASymfony/Component/HttpKernel/CacheWarmer/CacheWarmerAggregate.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\CacheWarmer;

/**
 * Aggregates several cache warmers into a single one.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class CacheWarmerAggregate implements CacheWarmerInterface
{
    protected $warmers = array();
    protected $optionalsEnabled = false;

    public function __construct(array $warmers = array())
    {
        foreach ($warmers as $warmer) {
            $this->add($warmer);
        }
    }

    public function enableOptionalWarmers()
    {
        $this->optionalsEnabled = true;
    }

    /**
     * Warms up the cache.
     *
     * @param string $cacheDir The cache directory
     */
    public function warmUp($cacheDir)
    {
        foreach ($this->warmers as $warmer) {
            if (!$this->optionalsEnabled && $warmer->isOptional()) {
                continue;
            }

            $warmer->warmUp($cacheDir);
        }
    }

    /**
     * Checks whether this warmer is optional or not.
     *
     * @return Boolean always true
     */
    public function isOptional()
    {
        return false;
    }

    public function setWarmers(array $warmers)
    {
        $this->warmers = array();
        foreach ($warmers as $warmer) {
            $this->add($warmer);
        }
    }

    public function add(CacheWarmerInterface $warmer)
    {
        $this->warmers[] = $warmer;
    }
}
PK��Z��KK3Symfony/Component/HttpKernel/Debug/ErrorHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Debug;

use Symfony\Component\Debug\ErrorHandler as DebugErrorHandler;

/**
 * ErrorHandler.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @deprecated Deprecated in 2.3, to be removed in 3.0. Use the same class from the Debug component instead.
 */
class ErrorHandler extends DebugErrorHandler
{
}
PK��Z���9��7Symfony/Component/HttpKernel/Debug/ExceptionHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Debug;

use Symfony\Component\Debug\ExceptionHandler as DebugExceptionHandler;

/**
 * ExceptionHandler converts an exception to a Response object.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @deprecated Deprecated in 2.3, to be removed in 3.0. Use the same class from the Debug component instead.
 */
class ExceptionHandler extends DebugExceptionHandler
{
}
PK��Z�eڮ55?Symfony/Component/HttpKernel/Debug/TraceableEventDispatcher.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Debug;

use Symfony\Component\Stopwatch\Stopwatch;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Profiler\Profiler;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface;

/**
 * Collects some data about event listeners.
 *
 * This event dispatcher delegates the dispatching to another one.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class TraceableEventDispatcher implements EventDispatcherInterface, TraceableEventDispatcherInterface
{
    private $logger;
    private $called = array();
    private $stopwatch;
    private $dispatcher;
    private $wrappedListeners = array();
    private $firstCalledEvent = array();
    private $lastEventId = 0;

    /**
     * Constructor.
     *
     * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance
     * @param Stopwatch                $stopwatch  A Stopwatch instance
     * @param LoggerInterface          $logger     A LoggerInterface instance
     */
    public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $stopwatch, LoggerInterface $logger = null)
    {
        $this->dispatcher = $dispatcher;
        $this->stopwatch = $stopwatch;
        $this->logger = $logger;
    }

    /**
     * Sets the profiler.
     *
     * The traceable event dispatcher does not use the profiler anymore.
     * The job is now done directly by the Profiler listener and the
     * data collectors themselves.
     *
     * @param Profiler|null $profiler A Profiler instance
     *
     * @deprecated Deprecated since version 2.4, to be removed in 3.0.
     */
    public function setProfiler(Profiler $profiler = null)
    {
    }

    /**
     * {@inheritDoc}
     */
    public function addListener($eventName, $listener, $priority = 0)
    {
        $this->dispatcher->addListener($eventName, $listener, $priority);
    }

    /**
     * {@inheritdoc}
     */
    public function addSubscriber(EventSubscriberInterface $subscriber)
    {
        $this->dispatcher->addSubscriber($subscriber);
    }

    /**
     * {@inheritdoc}
     */
    public function removeListener($eventName, $listener)
    {
        return $this->dispatcher->removeListener($eventName, $listener);
    }

    /**
     * {@inheritdoc}
     */
    public function removeSubscriber(EventSubscriberInterface $subscriber)
    {
        return $this->dispatcher->removeSubscriber($subscriber);
    }

    /**
     * {@inheritdoc}
     */
    public function getListeners($eventName = null)
    {
        return $this->dispatcher->getListeners($eventName);
    }

    /**
     * {@inheritdoc}
     */
    public function hasListeners($eventName = null)
    {
        return $this->dispatcher->hasListeners($eventName);
    }

    /**
     * {@inheritdoc}
     */
    public function dispatch($eventName, Event $event = null)
    {
        if (null === $event) {
            $event = new Event();
        }

        $eventId = ++$this->lastEventId;

        $this->preDispatch($eventName, $eventId, $event);

        $e = $this->stopwatch->start($eventName, 'section');

        $this->firstCalledEvent[$eventName] = $this->stopwatch->start($eventName.'.loading', 'event_listener_loading');

        if (!$this->dispatcher->hasListeners($eventName)) {
            $this->firstCalledEvent[$eventName]->stop();
        }

        $this->dispatcher->dispatch($eventName, $event);

        unset($this->firstCalledEvent[$eventName]);

        if ($e->isStarted()) {
            $e->stop();
        }

        $this->postDispatch($eventName, $eventId, $event);

        return $event;
    }

    /**
     * {@inheritDoc}
     */
    public function getCalledListeners()
    {
        return $this->called;
    }

    /**
     * {@inheritDoc}
     */
    public function getNotCalledListeners()
    {
        $notCalled = array();

        foreach ($this->getListeners() as $name => $listeners) {
            foreach ($listeners as $listener) {
                $info = $this->getListenerInfo($listener, null, $name);
                if (!isset($this->called[$name.'.'.$info['pretty']])) {
                    $notCalled[$name.'.'.$info['pretty']] = $info;
                }
            }
        }

        return $notCalled;
    }

    /**
     * Proxies all method calls to the original event dispatcher.
     *
     * @param string $method    The method name
     * @param array  $arguments The method arguments
     *
     * @return mixed
     */
    public function __call($method, $arguments)
    {
        return call_user_func_array(array($this->dispatcher, $method), $arguments);
    }

    /**
     * This is a private method and must not be used.
     *
     * This method is public because it is used in a closure.
     * Whenever Symfony will require PHP 5.4, this could be changed
     * to a proper private method.
     */
    public function logSkippedListeners($eventName, $eventId, Event $event, $listener)
    {
        if (null === $this->logger) {
            return;
        }

        $info = $this->getListenerInfo($listener, $eventId, $eventName);

        $this->logger->debug(sprintf('Listener "%s" stopped propagation of the event "%s".', $info['pretty'], $eventName));

        $skippedListeners = $this->getListeners($eventName);
        $skipped = false;

        foreach ($skippedListeners as $skippedListener) {
            $skippedListener = $this->unwrapListener($skippedListener, $eventId);

            if ($skipped) {
                $info = $this->getListenerInfo($skippedListener, $eventId, $eventName);
                $this->logger->debug(sprintf('Listener "%s" was not called for event "%s".', $info['pretty'], $eventName));
            }

            if ($skippedListener === $listener) {
                $skipped = true;
            }
        }
    }

    /**
     * This is a private method.
     *
     * This method is public because it is used in a closure.
     * Whenever Symfony will require PHP 5.4, this could be changed
     * to a proper private method.
     */
    public function preListenerCall($eventName, $eventId, $listener)
    {
        // is it the first called listener?
        if (isset($this->firstCalledEvent[$eventName])) {
            $this->firstCalledEvent[$eventName]->stop();

            unset($this->firstCalledEvent[$eventName]);
        }

        $info = $this->getListenerInfo($listener, $eventId, $eventName);

        if (null !== $this->logger) {
            $this->logger->debug(sprintf('Notified event "%s" to listener "%s".', $eventName, $info['pretty']));
        }

        $this->called[$eventName.'.'.$info['pretty']] = $info;

        return $this->stopwatch->start(isset($info['class']) ? $info['class'] : $info['type'], 'event_listener');
    }

    /**
     * Returns information about the listener
     *
     * @param object $listener  The listener
     * @param string $eventName The event name
     *
     * @return array Information about the listener
     */
    private function getListenerInfo($listener, $eventId, $eventName)
    {
        $listener = $this->unwrapListener($listener, $eventId);

        $info = array(
            'event' => $eventName,
        );
        if ($listener instanceof \Closure) {
            $info += array(
                'type' => 'Closure',
                'pretty' => 'closure'
            );
        } elseif (is_string($listener)) {
            try {
                $r = new \ReflectionFunction($listener);
                $file = $r->getFileName();
                $line = $r->getStartLine();
            } catch (\ReflectionException $e) {
                $file = null;
                $line = null;
            }
            $info += array(
                'type'  => 'Function',
                'function' => $listener,
                'file'  => $file,
                'line'  => $line,
                'pretty' => $listener,
            );
        } elseif (is_array($listener) || (is_object($listener) && is_callable($listener))) {
            if (!is_array($listener)) {
                $listener = array($listener, '__invoke');
            }
            $class = is_object($listener[0]) ? get_class($listener[0]) : $listener[0];
            try {
                $r = new \ReflectionMethod($class, $listener[1]);
                $file = $r->getFileName();
                $line = $r->getStartLine();
            } catch (\ReflectionException $e) {
                $file = null;
                $line = null;
            }
            $info += array(
                'type'  => 'Method',
                'class' => $class,
                'method' => $listener[1],
                'file'  => $file,
                'line'  => $line,
                'pretty' => $class.'::'.$listener[1],
            );
        }

        return $info;
    }

    private function preDispatch($eventName, $eventId, Event $event)
    {
        // wrap all listeners before they are called
        $this->wrappedListeners[$eventId] = new \SplObjectStorage();

        $listeners = $this->dispatcher->getListeners($eventName);

        foreach ($listeners as $listener) {
            $this->dispatcher->removeListener($eventName, $listener);
            $wrapped = $this->wrapListener($eventName, $eventId, $listener);
            $this->wrappedListeners[$eventId][$wrapped] = $listener;
            $this->dispatcher->addListener($eventName, $wrapped);
        }

        switch ($eventName) {
            case KernelEvents::REQUEST:
                $this->stopwatch->openSection();
                break;
            case KernelEvents::VIEW:
            case KernelEvents::RESPONSE:
                // stop only if a controller has been executed
                if ($this->stopwatch->isStarted('controller')) {
                    $this->stopwatch->stop('controller');
                }
                break;
            case KernelEvents::TERMINATE:
                $token = $event->getResponse()->headers->get('X-Debug-Token');
                // There is a very special case when using builtin AppCache class as kernel wrapper, in the case
                // of an ESI request leading to a `stale` response [B]  inside a `fresh` cached response [A].
                // In this case, `$token` contains the [B] debug token, but the  open `stopwatch` section ID
                // is equal to the [A] debug token. Trying to reopen section with the [B] token throws an exception
                // which must be caught.
                try {
                    $this->stopwatch->openSection($token);
                } catch (\LogicException $e) {}
                break;
        }
    }

    private function postDispatch($eventName, $eventId, Event $event)
    {
        switch ($eventName) {
            case KernelEvents::CONTROLLER:
                $this->stopwatch->start('controller', 'section');
                break;
            case KernelEvents::RESPONSE:
                $token = $event->getResponse()->headers->get('X-Debug-Token');
                $this->stopwatch->stopSection($token);
                break;
            case KernelEvents::TERMINATE:
                // In the special case described in the `preDispatch` method above, the `$token` section
                // does not exist, then closing it throws an exception which must be caught.
                $token = $event->getResponse()->headers->get('X-Debug-Token');
                try {
                    $this->stopwatch->stopSection($token);
                } catch (\LogicException $e) {}
                break;
        }

        foreach ($this->wrappedListeners[$eventId] as $wrapped) {
            $this->dispatcher->removeListener($eventName, $wrapped);
            $this->dispatcher->addListener($eventName, $this->wrappedListeners[$eventId][$wrapped]);
        }

        unset($this->wrappedListeners[$eventId]);
    }

    private function wrapListener($eventName, $eventId, $listener)
    {
        $self = $this;

        return function (Event $event) use ($self, $eventName, $eventId, $listener) {
            $e = $self->preListenerCall($eventName, $eventId, $listener);

            call_user_func($listener, $event, $eventName, $self);

            if ($e->isStarted()) {
                $e->stop();
            }

            if ($event->isPropagationStopped()) {
                $self->logSkippedListeners($eventName, $eventId, $event, $listener);
            }
        };
    }

    private function unwrapListener($listener, $eventId)
    {
        // get the original listener
        if (is_object($listener)) {
            if (null === $eventId) {
                foreach (array_keys($this->wrappedListeners) as $eventId) {
                    if (isset($this->wrappedListeners[$eventId][$listener])) {
                        return $this->wrappedListeners[$eventId][$listener];
                    }
                }
            } elseif (isset($this->wrappedListeners[$eventId][$listener])) {
                return $this->wrappedListeners[$eventId][$listener];
            }
        }

        return $listener;
    }
}
PK��Z>�<���/Symfony/Component/HttpKernel/Log/NullLogger.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Log;

use Psr\Log\NullLogger as PsrNullLogger;

/**
 * NullLogger.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class NullLogger extends PsrNullLogger implements LoggerInterface
{
    /**
     * @api
     * @deprecated since 2.2, to be removed in 3.0. Use emergency() which is PSR-3 compatible.
     */
    public function emerg($message, array $context = array())
    {
    }

    /**
     * @api
     * @deprecated since 2.2, to be removed in 3.0. Use critical() which is PSR-3 compatible.
     */
    public function crit($message, array $context = array())
    {
    }

    /**
     * @api
     * @deprecated since 2.2, to be removed in 3.0. Use error() which is PSR-3 compatible.
     */
    public function err($message, array $context = array())
    {
    }

    /**
     * @api
     * @deprecated since 2.2, to be removed in 3.0. Use warning() which is PSR-3 compatible.
     */
    public function warn($message, array $context = array())
    {
    }
}
PK��Z~�[�

4Symfony/Component/HttpKernel/Log/LoggerInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Log;

use Psr\Log\LoggerInterface as PsrLogger;

/**
 * LoggerInterface.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @deprecated since 2.2, to be removed in 3.0. Type-hint \Psr\Log\LoggerInterface instead.
 * @api
 */
interface LoggerInterface extends PsrLogger
{
    /**
     * @api
     * @deprecated since 2.2, to be removed in 3.0. Use emergency() which is PSR-3 compatible.
     */
    public function emerg($message, array $context = array());

    /**
     * @api
     * @deprecated since 2.2, to be removed in 3.0. Use critical() which is PSR-3 compatible.
     */
    public function crit($message, array $context = array());

    /**
     * @api
     * @deprecated since 2.2, to be removed in 3.0. Use error() which is PSR-3 compatible.
     */
    public function err($message, array $context = array());

    /**
     * @api
     * @deprecated since 2.2, to be removed in 3.0. Use warning() which is PSR-3 compatible.
     */
    public function warn($message, array $context = array());
}
PK��ZJ��=[[9Symfony/Component/HttpKernel/Log/DebugLoggerInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Log;

/**
 * DebugLoggerInterface.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface DebugLoggerInterface
{
    /**
     * Returns an array of logs.
     *
     * A log is an array with the following mandatory keys:
     * timestamp, message, priority, and priorityName.
     * It can also have an optional context key containing an array.
     *
     * @return array An array of logs
     */
    public function getLogs();

    /**
     * Returns the number of errors.
     *
     * @return integer The number of errors
     */
    public function countErrors();
}
PK��Z���ss-Symfony/Component/HttpKernel/KernelEvents.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel;

/**
 * Contains all events thrown in the HttpKernel component
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
final class KernelEvents
{
    /**
     * The REQUEST event occurs at the very beginning of request
     * dispatching
     *
     * This event allows you to create a response for a request before any
     * other code in the framework is executed. The event listener method
     * receives a Symfony\Component\HttpKernel\Event\GetResponseEvent
     * instance.
     *
     * @var string
     *
     * @api
     */
    const REQUEST = 'kernel.request';

    /**
     * The EXCEPTION event occurs when an uncaught exception appears
     *
     * This event allows you to create a response for a thrown exception or
     * to modify the thrown exception. The event listener method receives
     * a Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent
     * instance.
     *
     * @var string
     *
     * @api
     */
    const EXCEPTION = 'kernel.exception';

    /**
     * The VIEW event occurs when the return value of a controller
     * is not a Response instance
     *
     * This event allows you to create a response for the return value of the
     * controller. The event listener method receives a
     * Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent
     * instance.
     *
     * @var string
     *
     * @api
     */
    const VIEW = 'kernel.view';

    /**
     * The CONTROLLER event occurs once a controller was found for
     * handling a request
     *
     * This event allows you to change the controller that will handle the
     * request. The event listener method receives a
     * Symfony\Component\HttpKernel\Event\FilterControllerEvent instance.
     *
     * @var string
     *
     * @api
     */
    const CONTROLLER = 'kernel.controller';

    /**
     * The RESPONSE event occurs once a response was created for
     * replying to a request
     *
     * This event allows you to modify or replace the response that will be
     * replied. The event listener method receives a
     * Symfony\Component\HttpKernel\Event\FilterResponseEvent instance.
     *
     * @var string
     *
     * @api
     */
    const RESPONSE = 'kernel.response';

    /**
     * The TERMINATE event occurs once a response was sent
     *
     * This event allows you to run expensive post-response jobs.
     * The event listener method receives a
     * Symfony\Component\HttpKernel\Event\PostResponseEvent instance.
     *
     * @var string
     */
    const TERMINATE = 'kernel.terminate';

    /**
     * The REQUEST_FINISHED event occurs when a response was generated for a request.
     *
     * This event allows you to reset the global and environmental state of
     * the application, when it was changed during the request.
     *
     * @var string
     */
    const FINISH_REQUEST = 'kernel.finish_request';
}
PK��ZE^����?Symfony/Component/HttpKernel/EventListener/ProfilerListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\EventListener;

use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Profiler\Profiler;
use Symfony\Component\HttpFoundation\RequestMatcherInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * ProfilerListener collects data for the current request by listening to the onKernelResponse event.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ProfilerListener implements EventSubscriberInterface
{
    protected $profiler;
    protected $matcher;
    protected $onlyException;
    protected $onlyMasterRequests;
    protected $exception;
    protected $requests = array();
    protected $profiles;
    protected $requestStack;
    protected $parents;

    /**
     * Constructor.
     *
     * @param Profiler                $profiler           A Profiler instance
     * @param RequestMatcherInterface $matcher            A RequestMatcher instance
     * @param Boolean                 $onlyException      true if the profiler only collects data when an exception occurs, false otherwise
     * @param Boolean                 $onlyMasterRequests true if the profiler only collects data when the request is a master request, false otherwise
     */
    public function __construct(Profiler $profiler, RequestMatcherInterface $matcher = null, $onlyException = false, $onlyMasterRequests = false, RequestStack $requestStack = null)
    {
        $this->profiler = $profiler;
        $this->matcher = $matcher;
        $this->onlyException = (Boolean) $onlyException;
        $this->onlyMasterRequests = (Boolean) $onlyMasterRequests;
        $this->profiles = new \SplObjectStorage();
        $this->parents = new \SplObjectStorage();
        $this->requestStack = $requestStack;
    }

    /**
     * Handles the onKernelException event.
     *
     * @param GetResponseForExceptionEvent $event A GetResponseForExceptionEvent instance
     */
    public function onKernelException(GetResponseForExceptionEvent $event)
    {
        if ($this->onlyMasterRequests && !$event->isMasterRequest()) {
            return;
        }

        $this->exception = $event->getException();
    }

    /**
     * @deprecated Deprecated since version 2.4, to be removed in 3.0.
     */
    public function onKernelRequest(GetResponseEvent $event)
    {
        if (null === $this->requestStack) {
            $this->requests[] = $event->getRequest();
        }
    }

    /**
     * Handles the onKernelResponse event.
     *
     * @param FilterResponseEvent $event A FilterResponseEvent instance
     */
    public function onKernelResponse(FilterResponseEvent $event)
    {
        $master = $event->isMasterRequest();
        if ($this->onlyMasterRequests && !$master) {
            return;
        }

        if ($this->onlyException && null === $this->exception) {
            return;
        }

        $request = $event->getRequest();
        $exception = $this->exception;
        $this->exception = null;

        if (null !== $this->matcher && !$this->matcher->matches($request)) {
            return;
        }

        if (!$profile = $this->profiler->collect($request, $event->getResponse(), $exception)) {
            return;
        }

        $this->profiles[$request] = $profile;

        if (null !== $this->requestStack) {
            $this->parents[$request] = $this->requestStack->getParentRequest();
        } elseif (!$master) {
            // to be removed when requestStack is required
            array_pop($this->requests);

            $this->parents[$request] = end($this->requests);
        }
    }

    public function onKernelTerminate(PostResponseEvent $event)
    {
        // attach children to parents
        foreach ($this->profiles as $request) {
            // isset call should be removed when requestStack is required
            if (isset($this->parents[$request]) && null !== $parentRequest = $this->parents[$request]) {
                if (isset($this->profiles[$parentRequest])) {
                    $this->profiles[$parentRequest]->addChild($this->profiles[$request]);
                }
            }
        }

        // save profiles
        foreach ($this->profiles as $request) {
            $this->profiler->saveProfile($this->profiles[$request]);
        }

        $this->profiles = new \SplObjectStorage();
        $this->parents = new \SplObjectStorage();
        $this->requests = array();
    }

    public static function getSubscribedEvents()
    {
        return array(
            // kernel.request must be registered as early as possible to not break
            // when an exception is thrown in any other kernel.request listener
            KernelEvents::REQUEST => array('onKernelRequest', 1024),
            KernelEvents::RESPONSE => array('onKernelResponse', -100),
            KernelEvents::EXCEPTION => 'onKernelException',
            KernelEvents::TERMINATE => array('onKernelTerminate', -1024),
        );
    }
}
PK��Z����
�
?Symfony/Component/HttpKernel/EventListener/FragmentListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\EventListener;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\IpUtils;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\UriSigner;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Handles content fragments represented by special URIs.
 *
 * All URL paths starting with /_fragment are handled as
 * content fragments by this listener.
 *
 * If the request does not come from a trusted IP, it throws an
 * AccessDeniedHttpException exception.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FragmentListener implements EventSubscriberInterface
{
    private $signer;
    private $fragmentPath;

    /**
     * Constructor.
     *
     * @param UriSigner $signer       A UriSigner instance
     * @param string    $fragmentPath The path that triggers this listener
     */
    public function __construct(UriSigner $signer, $fragmentPath = '/_fragment')
    {
        $this->signer = $signer;
        $this->fragmentPath = $fragmentPath;
    }

    /**
     * Fixes request attributes when the path is '/_fragment'.
     *
     * @param GetResponseEvent $event A GetResponseEvent instance
     *
     * @throws AccessDeniedHttpException if the request does not come from a trusted IP.
     */
    public function onKernelRequest(GetResponseEvent $event)
    {
        $request = $event->getRequest();

        if ($this->fragmentPath !== rawurldecode($request->getPathInfo())) {
            return;
        }

        $this->validateRequest($request);

        parse_str($request->query->get('_path', ''), $attributes);
        $request->attributes->add($attributes);
        $request->attributes->set('_route_params', array_replace($request->attributes->get('_route_params', array()), $attributes));
        $request->query->remove('_path');
    }

    protected function validateRequest(Request $request)
    {
        // is the Request safe?
        if (!$request->isMethodSafe()) {
            throw new AccessDeniedHttpException();
        }

        // does the Request come from a trusted IP?
        $trustedIps = array_merge($this->getLocalIpAddresses(), $request->getTrustedProxies());
        $remoteAddress = $request->server->get('REMOTE_ADDR');
        if (IpUtils::checkIp($remoteAddress, $trustedIps)) {
            return;
        }

        // is the Request signed?
        // we cannot use $request->getUri() here as we want to work with the original URI (no query string reordering)
        if ($this->signer->check($request->getSchemeAndHttpHost().$request->getBaseUrl().$request->getPathInfo().(null !== ($qs = $request->server->get('QUERY_STRING')) ? '?'.$qs : ''))) {
            return;
        }

        throw new AccessDeniedHttpException();
    }

    protected function getLocalIpAddresses()
    {
        return array('127.0.0.1', 'fe80::1', '::1');
    }

    public static function getSubscribedEvents()
    {
        return array(
            KernelEvents::REQUEST => array(array('onKernelRequest', 48)),
        );
    }
}
PK��Z@S��>Symfony/Component/HttpKernel/EventListener/SessionListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\EventListener;

use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Sets the session in the request.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
abstract class SessionListener implements EventSubscriberInterface
{
    public function onKernelRequest(GetResponseEvent $event)
    {
        if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
            return;
        }

        $request = $event->getRequest();
        $session = $this->getSession();
        if (null === $session || $request->hasSession()) {
            return;
        }

        $request->setSession($session);
    }

    public static function getSubscribedEvents()
    {
        return array(
            KernelEvents::REQUEST => array('onKernelRequest', 128),
        );
    }

    /**
     * Gets the session object.
     *
     * @return SessionInterface|null A SessionInterface instance of null if no session is available
     */
    abstract protected function getSession();
}
PK��Z�|$���CSymfony/Component/HttpKernel/EventListener/ErrorsLoggerListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\EventListener;

use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Debug\ErrorHandler;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;

/**
 * Injects the logger into the ErrorHandler, so that it can log various errors.
 *
 * @author Colin Frei <colin@colinfrei.com>
 * @author Konstantin Myakshin <koc-dp@yandex.ru>
 */
class ErrorsLoggerListener implements EventSubscriberInterface
{
    private $channel;

    private $logger;

    public function __construct($channel, LoggerInterface $logger = null)
    {
        $this->channel = $channel;
        $this->logger = $logger;
    }

    public function injectLogger()
    {
        if (null !== $this->logger) {
            ErrorHandler::setLogger($this->logger, $this->channel);
        }
    }

    public static function getSubscribedEvents()
    {
        return array(KernelEvents::REQUEST => 'injectLogger');
    }
}
PK��Z���$$GSymfony/Component/HttpKernel/EventListener/StreamedResponseListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\EventListener;

use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * StreamedResponseListener is responsible for sending the Response
 * to the client.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class StreamedResponseListener implements EventSubscriberInterface
{
    /**
     * Filters the Response.
     *
     * @param FilterResponseEvent $event A FilterResponseEvent instance
     */
    public function onKernelResponse(FilterResponseEvent $event)
    {
        if (!$event->isMasterRequest()) {
            return;
        }

        $response = $event->getResponse();

        if ($response instanceof StreamedResponse) {
            $response->send();
        }
    }

    public static function getSubscribedEvents()
    {
        return array(
            KernelEvents::RESPONSE => array('onKernelResponse', -1024),
        );
    }
}
PK��Z��	���@Symfony/Component/HttpKernel/EventListener/ExceptionListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\EventListener;

use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Exception\FlattenException;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * ExceptionListener.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ExceptionListener implements EventSubscriberInterface
{
    protected $controller;
    protected $logger;

    public function __construct($controller, LoggerInterface $logger = null)
    {
        $this->controller = $controller;
        $this->logger = $logger;
    }

    public function onKernelException(GetResponseForExceptionEvent $event)
    {
        static $handling;

        if (true === $handling) {
            return false;
        }

        $handling = true;

        $exception = $event->getException();
        $request = $event->getRequest();

        $this->logException($exception, sprintf('Uncaught PHP Exception %s: "%s" at %s line %s', get_class($exception), $exception->getMessage(), $exception->getFile(), $exception->getLine()));

        $request = $this->duplicateRequest($exception, $request);

        try {
            $response = $event->getKernel()->handle($request, HttpKernelInterface::SUB_REQUEST, true);
        } catch (\Exception $e) {
            $this->logException($exception, sprintf('Exception thrown when handling an exception (%s: %s)', get_class($e), $e->getMessage()), false);

            // set handling to false otherwise it wont be able to handle further more
            $handling = false;

            // re-throw the exception from within HttpKernel as this is a catch-all
            return;
        }

        $event->setResponse($response);

        $handling = false;
    }

    public static function getSubscribedEvents()
    {
        return array(
            KernelEvents::EXCEPTION => array('onKernelException', -128),
        );
    }

    /**
     * Logs an exception.
     *
     * @param \Exception $exception The original \Exception instance
     * @param string     $message   The error message to log
     * @param Boolean    $original  False when the handling of the exception thrown another exception
     */
    protected function logException(\Exception $exception, $message, $original = true)
    {
        $isCritical = !$exception instanceof HttpExceptionInterface || $exception->getStatusCode() >= 500;
        $context = array('exception' => $exception);
        if (null !== $this->logger) {
            if ($isCritical) {
                $this->logger->critical($message, $context);
            } else {
                $this->logger->error($message, $context);
            }
        } elseif (!$original || $isCritical) {
            error_log($message);
        }
    }

    /**
     * Clones the request for the exception.
     *
     * @param \Exception $exception The thrown exception.
     * @param Request $request The original request.
     *
     * @return Request $request The cloned request.
     */
    protected function duplicateRequest(\Exception $exception, Request $request)
    {
        $attributes = array(
            '_controller' => $this->controller,
            'exception' => FlattenException::create($exception),
            'logger' => $this->logger instanceof DebugLoggerInterface ? $this->logger : null,
            // keep for BC -- as $format can be an argument of the controller callable
            // see src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php
            // @deprecated in 2.4, to be removed in 3.0
            'format' => $request->getRequestFormat(),
        );
        $request = $request->duplicate(null, null, $attributes);
        $request->setMethod('GET');

        return $request;
    }
}
PK��ZP�C�yy?Symfony/Component/HttpKernel/EventListener/ResponseListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\EventListener;

use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * ResponseListener fixes the Response headers based on the Request.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ResponseListener implements EventSubscriberInterface
{
    private $charset;

    public function __construct($charset)
    {
        $this->charset = $charset;
    }

    /**
     * Filters the Response.
     *
     * @param FilterResponseEvent $event A FilterResponseEvent instance
     */
    public function onKernelResponse(FilterResponseEvent $event)
    {
        if (!$event->isMasterRequest()) {
            return;
        }

        $response = $event->getResponse();

        if (null === $response->getCharset()) {
            $response->setCharset($this->charset);
        }

        $response->prepare($event->getRequest());
    }

    public static function getSubscribedEvents()
    {
        return array(
            KernelEvents::RESPONSE => 'onKernelResponse',
        );
    }
}
PK��ZS
�"P
P
=Symfony/Component/HttpKernel/EventListener/LocaleListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\EventListener;

use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\RequestContextAwareInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Initializes the locale based on the current request.
 *
 * This listener works in 2 modes:
 *
 *  * 2.3 compatibility mode where you must call setRequest whenever the Request changes.
 *  * 2.4+ mode where you must pass a RequestStack instance in the constructor.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class LocaleListener implements EventSubscriberInterface
{
    private $router;
    private $defaultLocale;
    private $requestStack;

    /**
     * RequestStack will become required in 3.0.
     */
    public function __construct($defaultLocale = 'en', RequestContextAwareInterface $router = null, RequestStack $requestStack = null)
    {
        $this->defaultLocale = $defaultLocale;
        $this->requestStack = $requestStack;
        $this->router = $router;
    }

    /**
     * Sets the current Request.
     *
     * This method was used to synchronize the Request, but as the HttpKernel
     * is doing that automatically now, you should never call it directly.
     * It is kept public for BC with the 2.3 version.
     *
     * @param Request|null $request A Request instance
     *
     * @deprecated Deprecated since version 2.4, to be removed in 3.0.
     */
    public function setRequest(Request $request = null)
    {
        if (null === $request) {
            return;
        }

        $this->setLocale($request);
        $this->setRouterContext($request);
    }

    public function onKernelRequest(GetResponseEvent $event)
    {
        $request = $event->getRequest();
        $request->setDefaultLocale($this->defaultLocale);

        $this->setLocale($request);
        $this->setRouterContext($request);
    }

    public function onKernelFinishRequest(FinishRequestEvent $event)
    {
        if (null === $this->requestStack) {
            return; // removed when requestStack is required
        }

        if (null !== $parentRequest = $this->requestStack->getParentRequest()) {
            $this->setRouterContext($parentRequest);
        }
    }

    private function setLocale(Request $request)
    {
        if ($locale = $request->attributes->get('_locale')) {
            $request->setLocale($locale);
        }
    }

    private function setRouterContext(Request $request)
    {
        if (null !== $this->router) {
            $this->router->getContext()->setParameter('_locale', $request->getLocale());
        }
    }

    public static function getSubscribedEvents()
    {
        return array(
            // must be registered after the Router to have access to the _locale
            KernelEvents::REQUEST => array(array('onKernelRequest', 16)),
            KernelEvents::FINISH_REQUEST => array(array('onKernelFinishRequest', 0)),
        );
    }
}
PK��Z/�)A
A
BSymfony/Component/HttpKernel/EventListener/TestSessionListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\EventListener;

use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * TestSessionListener.
 *
 * Saves session in test environment.
 *
 * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class TestSessionListener implements EventSubscriberInterface
{
    public function onKernelRequest(GetResponseEvent $event)
    {
        if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
            return;
        }

        // bootstrap the session
        $session = $this->getSession();
        if (!$session) {
            return;
        }

        $cookies = $event->getRequest()->cookies;

        if ($cookies->has($session->getName())) {
            $session->setId($cookies->get($session->getName()));
        }
    }

    /**
     * Checks if session was initialized and saves if current request is master
     * Runs on 'kernel.response' in test environment
     *
     * @param FilterResponseEvent $event
     */
    public function onKernelResponse(FilterResponseEvent $event)
    {
        if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
            return;
        }

        $session = $event->getRequest()->getSession();
        if ($session && $session->isStarted()) {
            $session->save();
            $params = session_get_cookie_params();
            $event->getResponse()->headers->setCookie(new Cookie($session->getName(), $session->getId(), 0 === $params['lifetime'] ? 0 : time() + $params['lifetime'], $params['path'], $params['domain'], $params['secure'], $params['httponly']));
        }
    }

    public static function getSubscribedEvents()
    {
        return array(
            KernelEvents::REQUEST => array('onKernelRequest', 192),
            KernelEvents::RESPONSE => array('onKernelResponse', -128),
        );
    }

    /**
     * Gets the session object.
     *
     * @return SessionInterface|null A SessionInterface instance of null if no session is available
     */
    abstract protected function getSession();
}
PK��Z�	��--=Symfony/Component/HttpKernel/EventListener/RouterListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\EventListener;

use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\RequestContextAwareInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;

/**
 * Initializes the context from the request and sets request attributes based on a matching route.
 *
 * This listener works in 2 modes:
 *
 *  * 2.3 compatibility mode where you must call setRequest whenever the Request changes.
 *  * 2.4+ mode where you must pass a RequestStack instance in the constructor.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class RouterListener implements EventSubscriberInterface
{
    private $matcher;
    private $context;
    private $logger;
    private $request;
    private $requestStack;

    /**
     * Constructor.
     *
     * RequestStack will become required in 3.0.
     *
     * @param UrlMatcherInterface|RequestMatcherInterface $matcher The Url or Request matcher
     * @param RequestContext|null                         $context The RequestContext (can be null when $matcher implements RequestContextAwareInterface)
     * @param LoggerInterface|null                        $logger  The logger
     *
     * @throws \InvalidArgumentException
     */
    public function __construct($matcher, RequestContext $context = null, LoggerInterface $logger = null, RequestStack $requestStack = null)
    {
        if (!$matcher instanceof UrlMatcherInterface && !$matcher instanceof RequestMatcherInterface) {
            throw new \InvalidArgumentException('Matcher must either implement UrlMatcherInterface or RequestMatcherInterface.');
        }

        if (null === $context && !$matcher instanceof RequestContextAwareInterface) {
            throw new \InvalidArgumentException('You must either pass a RequestContext or the matcher must implement RequestContextAwareInterface.');
        }

        $this->matcher = $matcher;
        $this->context = $context ?: $matcher->getContext();
        $this->requestStack = $requestStack;
        $this->logger = $logger;
    }

    /**
     * Sets the current Request.
     *
     * This method was used to synchronize the Request, but as the HttpKernel
     * is doing that automatically now, you should never call it directly.
     * It is kept public for BC with the 2.3 version.
     *
     * @param Request|null $request A Request instance
     *
     * @deprecated Deprecated since version 2.4, to be moved to a private function in 3.0.
     */
    public function setRequest(Request $request = null)
    {
        if (null !== $request && $this->request !== $request) {
            $this->context->fromRequest($request);
        }
        $this->request = $request;
    }

    public function onKernelFinishRequest(FinishRequestEvent $event)
    {
        if (null === $this->requestStack) {
            return; // removed when requestStack is required
        }

        $this->setRequest($this->requestStack->getParentRequest());
    }

    public function onKernelRequest(GetResponseEvent $event)
    {
        $request = $event->getRequest();

        // initialize the context that is also used by the generator (assuming matcher and generator share the same context instance)
        // we call setRequest even if most of the time, it has already been done to keep compatibility
        // with frameworks which do not use the Symfony service container
        // when we have a RequestStack, no need to do it
        if (null !== $this->requestStack) {
            $this->setRequest($request);
        }

        if ($request->attributes->has('_controller')) {
            // routing is already done
            return;
        }

        // add attributes based on the request (routing)
        try {
            // matching a request is more powerful than matching a URL path + context, so try that first
            if ($this->matcher instanceof RequestMatcherInterface) {
                $parameters = $this->matcher->matchRequest($request);
            } else {
                $parameters = $this->matcher->match($request->getPathInfo());
            }

            if (null !== $this->logger) {
                $this->logger->info(sprintf('Matched route "%s" (parameters: %s)', $parameters['_route'], $this->parametersToString($parameters)));
            }

            $request->attributes->add($parameters);
            unset($parameters['_route']);
            unset($parameters['_controller']);
            $request->attributes->set('_route_params', $parameters);
        } catch (ResourceNotFoundException $e) {
            $message = sprintf('No route found for "%s %s"', $request->getMethod(), $request->getPathInfo());

            if ($referer = $request->headers->get('referer')) {
                $message .= sprintf(' (from "%s")', $referer);
            }

            throw new NotFoundHttpException($message, $e);
        } catch (MethodNotAllowedException $e) {
            $message = sprintf('No route found for "%s %s": Method Not Allowed (Allow: %s)', $request->getMethod(), $request->getPathInfo(), implode(', ', $e->getAllowedMethods()));

            throw new MethodNotAllowedHttpException($e->getAllowedMethods(), $message, $e);
        }
    }

    private function parametersToString(array $parameters)
    {
        $pieces = array();
        foreach ($parameters as $key => $val) {
            $pieces[] = sprintf('"%s": "%s"', $key, (is_string($val) ? $val : json_encode($val)));
        }

        return implode(', ', $pieces);
    }

    public static function getSubscribedEvents()
    {
        return array(
            KernelEvents::REQUEST => array(array('onKernelRequest', 32)),
            KernelEvents::FINISH_REQUEST => array(array('onKernelFinishRequest', 0)),
        );
    }
}
PK��Z��^��:Symfony/Component/HttpKernel/EventListener/EsiListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\EventListener;

use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\HttpCache\Esi;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * EsiListener adds a Surrogate-Control HTTP header when the Response needs to be parsed for ESI.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class EsiListener implements EventSubscriberInterface
{
    private $esi;

    /**
     * Constructor.
     *
     * @param Esi $esi An ESI instance
     */
    public function __construct(Esi $esi = null)
    {
        $this->esi = $esi;
    }

    /**
     * Filters the Response.
     *
     * @param FilterResponseEvent $event A FilterResponseEvent instance
     */
    public function onKernelResponse(FilterResponseEvent $event)
    {
        if (!$event->isMasterRequest() || null === $this->esi) {
            return;
        }

        $this->esi->addSurrogateControl($event->getResponse());
    }

    public static function getSubscribedEvents()
    {
        return array(
            KernelEvents::RESPONSE => 'onKernelResponse',
        );
    }
}
PK��ZqK-##@Symfony/Component/HttpKernel/Fragment/InlineFragmentRenderer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Fragment;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Controller\ControllerReference;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

/**
 * Implements the inline rendering strategy where the Request is rendered by the current HTTP kernel.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class InlineFragmentRenderer extends RoutableFragmentRenderer
{
    private $kernel;
    private $dispatcher;

    /**
     * Constructor.
     *
     * @param HttpKernelInterface      $kernel     A HttpKernelInterface instance
     * @param EventDispatcherInterface $dispatcher A EventDispatcherInterface instance
     */
    public function __construct(HttpKernelInterface $kernel, EventDispatcherInterface $dispatcher = null)
    {
        $this->kernel = $kernel;
        $this->dispatcher = $dispatcher;
    }

    /**
     * {@inheritdoc}
     *
     * Additional available options:
     *
     *  * alt: an alternative URI to render in case of an error
     */
    public function render($uri, Request $request, array $options = array())
    {
        $reference = null;
        if ($uri instanceof ControllerReference) {
            $reference = $uri;

            // Remove attributes from the generated URI because if not, the Symfony
            // routing system will use them to populate the Request attributes. We don't
            // want that as we want to preserve objects (so we manually set Request attributes
            // below instead)
            $attributes = $reference->attributes;
            $reference->attributes = array();

            // The request format and locale might have been overridden by the user
            foreach (array('_format', '_locale') as $key) {
                if (isset($attributes[$key])) {
                    $reference->attributes[$key] = $attributes[$key];
                }
            }

            $uri = $this->generateFragmentUri($uri, $request, false, false);

            $reference->attributes = array_merge($attributes, $reference->attributes);
        }

        $subRequest = $this->createSubRequest($uri, $request);

        // override Request attributes as they can be objects (which are not supported by the generated URI)
        if (null !== $reference) {
            $subRequest->attributes->add($reference->attributes);
        }

        $level = ob_get_level();
        try {
            return $this->kernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST, false);
        } catch (\Exception $e) {
            // we dispatch the exception event to trigger the logging
            // the response that comes back is simply ignored
            if (isset($options['ignore_errors']) && $options['ignore_errors'] && $this->dispatcher) {
                $event = new GetResponseForExceptionEvent($this->kernel, $request, HttpKernelInterface::SUB_REQUEST, $e);

                $this->dispatcher->dispatch(KernelEvents::EXCEPTION, $event);
            }

            // let's clean up the output buffers that were created by the sub-request
            while (ob_get_level() > $level) {
                ob_get_clean();
            }

            if (isset($options['alt'])) {
                $alt = $options['alt'];
                unset($options['alt']);

                return $this->render($alt, $request, $options);
            }

            if (!isset($options['ignore_errors']) || !$options['ignore_errors']) {
                throw $e;
            }

            return new Response();
        }
    }

    protected function createSubRequest($uri, Request $request)
    {
        $cookies = $request->cookies->all();
        $server = $request->server->all();

        // Override the arguments to emulate a sub-request.
        // Sub-request object will point to localhost as client ip and real client ip
        // will be included into trusted header for client ip
        try {
            if ($trustedHeaderName = Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP)) {
                $currentXForwardedFor = $request->headers->get($trustedHeaderName, '');

                $server['HTTP_'.$trustedHeaderName] = ($currentXForwardedFor ? $currentXForwardedFor.', ' : '').$request->getClientIp();
            }
        } catch (\InvalidArgumentException $e) {
            // Do nothing
        }

        $server['REMOTE_ADDR'] = '127.0.0.1';

        $subRequest = Request::create($uri, 'get', array(), $cookies, array(), $server);
        if ($request->headers->has('Surrogate-Capability')) {
            $subRequest->headers->set('Surrogate-Capability', $request->headers->get('Surrogate-Capability'));
        }

        if ($session = $request->getSession()) {
            $subRequest->setSession($session);
        }

        return $subRequest;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'inline';
    }
}
PK��Zm���33BSymfony/Component/HttpKernel/Fragment/RoutableFragmentRenderer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Fragment;

use Symfony\Component\HttpKernel\Controller\ControllerReference;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\EventListener\FragmentListener;

/**
 * Adds the possibility to generate a fragment URI for a given Controller.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class RoutableFragmentRenderer implements FragmentRendererInterface
{
    private $fragmentPath = '/_fragment';

    /**
     * Sets the fragment path that triggers the fragment listener.
     *
     * @param string $path The path
     *
     * @see FragmentListener
     */
    public function setFragmentPath($path)
    {
        $this->fragmentPath = $path;
    }

    /**
     * Generates a fragment URI for a given controller.
     *
     * @param ControllerReference  $reference A ControllerReference instance
     * @param Request              $request   A Request instance
     * @param Boolean              $absolute  Whether to generate an absolute URL or not
     * @param Boolean              $strict    Whether to allow non-scalar attributes or not
     *
     * @return string A fragment URI
     */
    protected function generateFragmentUri(ControllerReference $reference, Request $request, $absolute = false, $strict = true)
    {
        if ($strict) {
            $this->checkNonScalar($reference->attributes);
        }

        // We need to forward the current _format and _locale values as we don't have
        // a proper routing pattern to do the job for us.
        // This makes things inconsistent if you switch from rendering a controller
        // to rendering a route if the route pattern does not contain the special
        // _format and _locale placeholders.
        if (!isset($reference->attributes['_format'])) {
            $reference->attributes['_format'] = $request->getRequestFormat();
        }
        if (!isset($reference->attributes['_locale'])) {
            $reference->attributes['_locale'] = $request->getLocale();
        }

        $reference->attributes['_controller'] = $reference->controller;

        $reference->query['_path'] = http_build_query($reference->attributes, '', '&');

        $path = $this->fragmentPath.'?'.http_build_query($reference->query, '', '&');

        if ($absolute) {
            return $request->getUriForPath($path);
        }

        return $request->getBaseUrl().$path;
    }

    private function checkNonScalar($values)
    {
        foreach ($values as $key => $value) {
            if (is_array($value)) {
                $this->checkNonScalar($value);
            } elseif (!is_scalar($value) && null !== $value) {
                throw new \LogicException(sprintf('Controller attributes cannot contain non-scalar/non-null values (value for key "%s" is not a scalar or null).', $key));
            }
        }
    }
}
PK��Z�j�g�	�	=Symfony/Component/HttpKernel/Fragment/EsiFragmentRenderer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Fragment;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Controller\ControllerReference;
use Symfony\Component\HttpKernel\HttpCache\Esi;

/**
 * Implements the ESI rendering strategy.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class EsiFragmentRenderer extends RoutableFragmentRenderer
{
    private $esi;
    private $inlineStrategy;

    /**
     * Constructor.
     *
     * The "fallback" strategy when ESI is not available should always be an
     * instance of InlineFragmentRenderer.
     *
     * @param Esi                    $esi            An Esi instance
     * @param InlineFragmentRenderer $inlineStrategy The inline strategy to use when ESI is not supported
     */
    public function __construct(Esi $esi = null, InlineFragmentRenderer $inlineStrategy)
    {
        $this->esi = $esi;
        $this->inlineStrategy = $inlineStrategy;
    }

    /**
     * {@inheritdoc}
     *
     * Note that if the current Request has no ESI capability, this method
     * falls back to use the inline rendering strategy.
     *
     * Additional available options:
     *
     *  * alt: an alternative URI to render in case of an error
     *  * comment: a comment to add when returning an esi:include tag
     *
     * @see Symfony\Component\HttpKernel\HttpCache\ESI
     */
    public function render($uri, Request $request, array $options = array())
    {
        if (!$this->esi || !$this->esi->hasSurrogateEsiCapability($request)) {
            return $this->inlineStrategy->render($uri, $request, $options);
        }

        if ($uri instanceof ControllerReference) {
            $uri = $this->generateFragmentUri($uri, $request);
        }

        $alt = isset($options['alt']) ? $options['alt'] : null;
        if ($alt instanceof ControllerReference) {
            $alt = $this->generateFragmentUri($alt, $request);
        }

        $tag = $this->esi->renderIncludeTag($uri, $alt, isset($options['ignore_errors']) ? $options['ignore_errors'] : false, isset($options['comment']) ? $options['comment'] : '');

        return new Response($tag);
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'esi';
    }
}
PK��Z��R��9Symfony/Component/HttpKernel/Fragment/FragmentHandler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Fragment;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Controller\ControllerReference;

/**
 * Renders a URI that represents a resource fragment.
 *
 * This class handles the rendering of resource fragments that are included into
 * a main resource. The handling of the rendering is managed by specialized renderers.
 *
 * This listener works in 2 modes:
 *
 *  * 2.3 compatibility mode where you must call setRequest whenever the Request changes.
 *  * 2.4+ mode where you must pass a RequestStack instance in the constructor.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @see FragmentRendererInterface
 */
class FragmentHandler
{
    private $debug;
    private $renderers = array();
    private $request;
    private $requestStack;

    /**
     * Constructor.
     *
     * RequestStack will become required in 3.0.
     *
     * @param FragmentRendererInterface[] $renderers    An array of FragmentRendererInterface instances
     * @param Boolean                     $debug        Whether the debug mode is enabled or not
     * @param RequestStack|null           $requestStack The Request stack that controls the lifecycle of requests
     */
    public function __construct(array $renderers = array(), $debug = false, RequestStack $requestStack = null)
    {
        $this->requestStack = $requestStack;
        foreach ($renderers as $renderer) {
            $this->addRenderer($renderer);
        }
        $this->debug = $debug;
    }

    /**
     * Adds a renderer.
     *
     * @param FragmentRendererInterface $renderer A FragmentRendererInterface instance
     */
    public function addRenderer(FragmentRendererInterface $renderer)
    {
        $this->renderers[$renderer->getName()] = $renderer;
    }

    /**
     * Sets the current Request.
     *
     * This method was used to synchronize the Request, but as the HttpKernel
     * is doing that automatically now, you should never call it directly.
     * It is kept public for BC with the 2.3 version.
     *
     * @param Request|null $request A Request instance
     *
     * @deprecated Deprecated since version 2.4, to be removed in 3.0.
     */
    public function setRequest(Request $request = null)
    {
        $this->request = $request;
    }

    /**
     * Renders a URI and returns the Response content.
     *
     * Available options:
     *
     *  * ignore_errors: true to return an empty string in case of an error
     *
     * @param string|ControllerReference $uri      A URI as a string or a ControllerReference instance
     * @param string                     $renderer The renderer name
     * @param array                      $options  An array of options
     *
     * @return string|null The Response content or null when the Response is streamed
     *
     * @throws \InvalidArgumentException when the renderer does not exist
     * @throws \LogicException           when the Request is not successful
     */
    public function render($uri, $renderer = 'inline', array $options = array())
    {
        if (!isset($options['ignore_errors'])) {
            $options['ignore_errors'] = !$this->debug;
        }

        if (!isset($this->renderers[$renderer])) {
            throw new \InvalidArgumentException(sprintf('The "%s" renderer does not exist.', $renderer));
        }

        if (!$request = $this->getRequest()) {
            throw new \LogicException('Rendering a fragment can only be done when handling a Request.');
        }

        return $this->deliver($this->renderers[$renderer]->render($uri, $request, $options));
    }

    /**
     * Delivers the Response as a string.
     *
     * When the Response is a StreamedResponse, the content is streamed immediately
     * instead of being returned.
     *
     * @param Response $response A Response instance
     *
     * @return string|null The Response content or null when the Response is streamed
     *
     * @throws \RuntimeException when the Response is not successful
     */
    protected function deliver(Response $response)
    {
        if (!$response->isSuccessful()) {
            throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $this->getRequest()->getUri(), $response->getStatusCode()));
        }

        if (!$response instanceof StreamedResponse) {
            return $response->getContent();
        }

        $response->sendContent();
    }

    private function getRequest()
    {
        return $this->requestStack ? $this->requestStack->getCurrentRequest() : $this->request;
    }
}
PK��Z5앾��BSymfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Fragment;

if (!defined('ENT_SUBSTITUTE')) {
    define('ENT_SUBSTITUTE', 8);
}

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Templating\EngineInterface;
use Symfony\Component\HttpKernel\Controller\ControllerReference;
use Symfony\Component\HttpKernel\UriSigner;

/**
 * Implements the Hinclude rendering strategy.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class HIncludeFragmentRenderer extends RoutableFragmentRenderer
{
    private $globalDefaultTemplate;
    private $signer;
    private $templating;
    private $charset;

    /**
     * Constructor.
     *
     * @param EngineInterface|\Twig_Environment $templating            An EngineInterface or a \Twig_Environment instance
     * @param UriSigner                         $signer                A UriSigner instance
     * @param string                            $globalDefaultTemplate The global default content (it can be a template name or the content)
     * @param string                            $charset
     */
    public function __construct($templating = null, UriSigner $signer = null, $globalDefaultTemplate = null, $charset = 'utf-8')
    {
        $this->setTemplating($templating);
        $this->globalDefaultTemplate = $globalDefaultTemplate;
        $this->signer = $signer;
        $this->charset = $charset;
    }

    /**
     * Sets the templating engine to use to render the default content.
     *
     * @param EngineInterface|\Twig_Environment|null $templating An EngineInterface or a \Twig_Environment instance
     *
     * @throws \InvalidArgumentException
     */
    public function setTemplating($templating)
    {
        if (null !== $templating && !$templating instanceof EngineInterface && !$templating instanceof \Twig_Environment) {
            throw new \InvalidArgumentException('The hinclude rendering strategy needs an instance of \Twig_Environment or Symfony\Component\Templating\EngineInterface');
        }

        $this->templating = $templating;
    }

    /**
     * Checks if a templating engine has been set.
     *
     * @return Boolean true if the templating engine has been set, false otherwise
     */
    public function hasTemplating()
    {
        return null !== $this->templating;
    }

    /**
     * {@inheritdoc}
     *
     * Additional available options:
     *
     *  * default:    The default content (it can be a template name or the content)
     *  * id:         An optional hx:include tag id attribute
     *  * attributes: An optional array of hx:include tag attributes
     */
    public function render($uri, Request $request, array $options = array())
    {
        if ($uri instanceof ControllerReference) {
            if (null === $this->signer) {
                throw new \LogicException('You must use a proper URI when using the Hinclude rendering strategy or set a URL signer.');
            }

            // we need to sign the absolute URI, but want to return the path only.
            $uri = substr($this->signer->sign($this->generateFragmentUri($uri, $request, true)), strlen($request->getSchemeAndHttpHost()));
        }

        // We need to replace ampersands in the URI with the encoded form in order to return valid html/xml content.
        $uri = str_replace('&', '&amp;', $uri);

        $template = isset($options['default']) ? $options['default'] : $this->globalDefaultTemplate;
        if (null !== $this->templating && $template && $this->templateExists($template)) {
            $content = $this->templating->render($template);
        } else {
            $content = $template;
        }

        $attributes = isset($options['attributes']) && is_array($options['attributes']) ? $options['attributes'] : array();
        if (isset($options['id']) && $options['id']) {
            $attributes['id'] = $options['id'];
        }
        $renderedAttributes = '';
        if (count($attributes) > 0) {
            foreach ($attributes as $attribute => $value) {
                $renderedAttributes .= sprintf(
                    ' %s="%s"',
                    htmlspecialchars($attribute, ENT_QUOTES | ENT_SUBSTITUTE, $this->charset, false),
                    htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, $this->charset, false)
                );
            }
        }

        return new Response(sprintf('<hx:include src="%s"%s>%s</hx:include>', $uri, $renderedAttributes, $content));
    }

    /**
     * @param string $template
     *
     * @return boolean
     */
    private function templateExists($template)
    {
        if ($this->templating instanceof EngineInterface) {
            try {
                return $this->templating->exists($template);
            } catch (\InvalidArgumentException $e) {
                return false;
            }
        }

        $loader = $this->templating->getLoader();
        if ($loader instanceof \Twig_ExistsLoaderInterface) {
            return $loader->exists($template);
        }

        try {
            $loader->getSource($template);

            return true;
        } catch (\Twig_Error_Loader $e) {
        }

        return false;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'hinclude';
    }
}
PK��Zz�����CSymfony/Component/HttpKernel/Fragment/FragmentRendererInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Fragment;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ControllerReference;
use Symfony\Component\HttpFoundation\Response;

/**
 * Interface implemented by all rendering strategies.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @see Symfony\Component\HttpKernel\FragmentRenderer
 */
interface FragmentRendererInterface
{
    /**
     * Renders a URI and returns the Response content.
     *
     * @param string|ControllerReference $uri     A URI as a string or a ControllerReference instance
     * @param Request                    $request A Request instance
     * @param array                      $options An array of options
     *
     * @return Response A Response instance
     */
    public function render($uri, Request $request, array $options = array());

    /**
     * Gets the name of the strategy.
     *
     * @return string The strategy name
     */
    public function getName();
}
PK��Z�ST��;Symfony/Component/HttpKernel/Exception/FlattenException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Exception;

use Symfony\Component\Debug\Exception\FlattenException as DebugFlattenException;

/**
 * FlattenException wraps a PHP Exception to be able to serialize it.
 *
 * Basically, this class removes all objects from the trace.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @deprecated Deprecated in 2.3, to be removed in 3.0. Use the same class from the Debug component instead.
 */
class FlattenException extends DebugFlattenException
{
}
PK��Z[G�??BSymfony/Component/HttpKernel/Exception/BadRequestHttpException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Exception;

/**
 * BadRequestHttpException.
 *
 * @author Ben Ramsey <ben@benramsey.com>
 */
class BadRequestHttpException extends HttpException
{
    /**
     * Constructor.
     *
     * @param string     $message   The internal exception message
     * @param \Exception $previous  The previous exception
     * @param integer    $code      The internal exception code
     */
    public function __construct($message = null, \Exception $previous = null, $code = 0)
    {
        parent::__construct(400, $message, $previous, array(), $code);
    }
}
PK��Z��7��GSymfony/Component/HttpKernel/Exception/TooManyRequestsHttpException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Exception;

/**
 * TooManyRequestsHttpException.
 *
 * @author Ben Ramsey <ben@benramsey.com>
 * @see http://tools.ietf.org/html/rfc6585
 */
class TooManyRequestsHttpException extends HttpException
{
    /**
     * Constructor.
     *
     * @param integer|string $retryAfter The number of seconds or HTTP-date after which the request may be retried
     * @param string         $message    The internal exception message
     * @param \Exception     $previous   The previous exception
     * @param integer        $code       The internal exception code
     */
    public function __construct($retryAfter = null, $message = null, \Exception $previous = null, $code = 0)
    {
        $headers = array();
        if ($retryAfter) {
            $headers = array('Retry-After' => $retryAfter);
        }

        parent::__construct(429, $message, $previous, $headers, $code);
    }
}
PK��ZW1�d��8Symfony/Component/HttpKernel/Exception/HttpException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Exception;

/**
 * HttpException.
 *
 * @author Kris Wallsmith <kris@symfony.com>
 */
class HttpException extends \RuntimeException implements HttpExceptionInterface
{
    private $statusCode;
    private $headers;

    public function __construct($statusCode, $message = null, \Exception $previous = null, array $headers = array(), $code = 0)
    {
        $this->statusCode = $statusCode;
        $this->headers = $headers;

        parent::__construct($message, $code, $previous);
    }

    public function getStatusCode()
    {
        return $this->statusCode;
    }

    public function getHeaders()
    {
        return $this->headers;
    }
}
PK��ZN�0�;;@Symfony/Component/HttpKernel/Exception/ConflictHttpException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Exception;

/**
 * ConflictHttpException.
 *
 * @author Ben Ramsey <ben@benramsey.com>
 */
class ConflictHttpException extends HttpException
{
    /**
     * Constructor.
     *
     * @param string     $message   The internal exception message
     * @param \Exception $previous  The previous exception
     * @param integer    $code      The internal exception code
     */
    public function __construct($message = null, \Exception $previous = null, $code = 0)
    {
        parent::__construct(409, $message, $previous, array(), $code);
    }
}
PK��ZC%؝SSLSymfony/Component/HttpKernel/Exception/UnsupportedMediaTypeHttpException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Exception;

/**
 * UnsupportedMediaTypeHttpException.
 *
 * @author Ben Ramsey <ben@benramsey.com>
 */
class UnsupportedMediaTypeHttpException extends HttpException
{
    /**
     * Constructor.
     *
     * @param string     $message   The internal exception message
     * @param \Exception $previous  The previous exception
     * @param integer    $code      The internal exception code
     */
    public function __construct($message = null, \Exception $previous = null, $code = 0)
    {
        parent::__construct(415, $message, $previous, array(), $code);
    }
}
PK��Z���EEESymfony/Component/HttpKernel/Exception/NotAcceptableHttpException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Exception;

/**
 * NotAcceptableHttpException.
 *
 * @author Ben Ramsey <ben@benramsey.com>
 */
class NotAcceptableHttpException extends HttpException
{
    /**
     * Constructor.
     *
     * @param string     $message   The internal exception message
     * @param \Exception $previous  The previous exception
     * @param integer    $code      The internal exception code
     */
    public function __construct($message = null, \Exception $previous = null, $code = 0)
    {
        parent::__construct(406, $message, $previous, array(), $code);
    }
}
PK��Z�Ѕ33<Symfony/Component/HttpKernel/Exception/GoneHttpException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Exception;

/**
 * GoneHttpException.
 *
 * @author Ben Ramsey <ben@benramsey.com>
 */
class GoneHttpException extends HttpException
{
    /**
     * Constructor.
     *
     * @param string     $message   The internal exception message
     * @param \Exception $previous  The previous exception
     * @param integer    $code      The internal exception code
     */
    public function __construct($message = null, \Exception $previous = null, $code = 0)
    {
        parent::__construct(410, $message, $previous, array(), $code);
    }
}
PK��Z^���>Symfony/Component/HttpKernel/Exception/FatalErrorException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Exception;

use Symfony\Component\Debug\Exception\FatalErrorException as DebugFatalErrorException;

/**
 * Fatal Error Exception.
 *
 * @author Konstanton Myakshin <koc-dp@yandex.ru>
 *
 * @deprecated Deprecated in 2.3, to be removed in 3.0. Use the same class from the Debug component instead.
 */
class FatalErrorException extends DebugFatalErrorException
{
}
PK��Z)8*uuDSymfony/Component/HttpKernel/Exception/AccessDeniedHttpException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Exception;

/**
 * AccessDeniedHttpException.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Christophe Coevoet <stof@notk.org>
 */
class AccessDeniedHttpException extends HttpException
{
    /**
     * Constructor.
     *
     * @param string     $message  The internal exception message
     * @param \Exception $previous The previous exception
     * @param integer    $code     The internal exception code
     */
    public function __construct($message = null, \Exception $previous = null, $code = 0)
    {
        parent::__construct(403, $message, $previous, array(), $code);
    }
}
PK��Z�+�~~LSymfony/Component/HttpKernel/Exception/PreconditionRequiredHttpException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Exception;

/**
 * PreconditionRequiredHttpException.
 *
 * @author Ben Ramsey <ben@benramsey.com>
 * @see http://tools.ietf.org/html/rfc6585
 */
class PreconditionRequiredHttpException extends HttpException
{
    /**
     * Constructor.
     *
     * @param string     $message   The internal exception message
     * @param \Exception $previous  The previous exception
     * @param integer    $code      The internal exception code
     */
    public function __construct($message = null, \Exception $previous = null, $code = 0)
    {
        parent::__construct(428, $message, $previous, array(), $code);
    }
}
PK��Z+�;XXJSymfony/Component/HttpKernel/Exception/ServiceUnavailableHttpException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Exception;

/**
 * ServiceUnavailableHttpException.
 *
 * @author Ben Ramsey <ben@benramsey.com>
 */
class ServiceUnavailableHttpException extends HttpException
{
    /**
     * Constructor.
     *
     * @param int|string  $retryAfter The number of seconds or HTTP-date after which the request may be retried
     * @param string      $message    The internal exception message
     * @param \Exception  $previous   The previous exception
     * @param integer     $code       The internal exception code
     */
    public function __construct($retryAfter = null, $message = null, \Exception $previous = null, $code = 0)
    {
        $headers = array();
        if ($retryAfter) {
            $headers = array('Retry-After' => $retryAfter);
        }

        parent::__construct(503, $message, $previous, $headers, $code);
    }
}
PK��Z*���DSymfony/Component/HttpKernel/Exception/UnauthorizedHttpException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Exception;

/**
 * UnauthorizedHttpException.
 *
 * @author Ben Ramsey <ben@benramsey.com>
 */
class UnauthorizedHttpException extends HttpException
{
    /**
     * Constructor.
     *
     * @param string     $challenge WWW-Authenticate challenge string
     * @param string     $message   The internal exception message
     * @param \Exception $previous  The previous exception
     * @param integer    $code      The internal exception code
     */
    public function __construct($challenge, $message = null, \Exception $previous = null, $code = 0)
    {
        $headers = array('WWW-Authenticate' => $challenge);

        parent::__construct(401, $message, $previous, $headers, $code);
    }
}
PK��Z�瞻??@Symfony/Component/HttpKernel/Exception/NotFoundHttpException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Exception;

/**
 * NotFoundHttpException.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class NotFoundHttpException extends HttpException
{
    /**
     * Constructor.
     *
     * @param string     $message  The internal exception message
     * @param \Exception $previous The previous exception
     * @param integer    $code     The internal exception code
     */
    public function __construct($message = null, \Exception $previous = null, $code = 0)
    {
        parent::__construct(404, $message, $previous, array(), $code);
    }
}
PK��Z<��~��HSymfony/Component/HttpKernel/Exception/MethodNotAllowedHttpException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Exception;

/**
 * MethodNotAllowedHttpException.
 *
 * @author Kris Wallsmith <kris@symfony.com>
 */
class MethodNotAllowedHttpException extends HttpException
{
    /**
     * Constructor.
     *
     * @param array      $allow    An array of allowed methods
     * @param string     $message  The internal exception message
     * @param \Exception $previous The previous exception
     * @param integer    $code     The internal exception code
     */
    public function __construct(array $allow, $message = null, \Exception $previous = null, $code = 0)
    {
        $headers = array('Allow' => strtoupper(implode(', ', $allow)));

        parent::__construct(405, $message, $previous, $headers, $code);
    }
}
PK��Z�� GGFSymfony/Component/HttpKernel/Exception/LengthRequiredHttpException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Exception;

/**
 * LengthRequiredHttpException.
 *
 * @author Ben Ramsey <ben@benramsey.com>
 */
class LengthRequiredHttpException extends HttpException
{
    /**
     * Constructor.
     *
     * @param string     $message   The internal exception message
     * @param \Exception $previous  The previous exception
     * @param integer    $code      The internal exception code
     */
    public function __construct($message = null, \Exception $previous = null, $code = 0)
    {
        parent::__construct(411, $message, $previous, array(), $code);
    }
}
PK��Z�;C�OOJSymfony/Component/HttpKernel/Exception/PreconditionFailedHttpException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Exception;

/**
 * PreconditionFailedHttpException.
 *
 * @author Ben Ramsey <ben@benramsey.com>
 */
class PreconditionFailedHttpException extends HttpException
{
    /**
     * Constructor.
     *
     * @param string     $message   The internal exception message
     * @param \Exception $previous  The previous exception
     * @param integer    $code      The internal exception code
     */
    public function __construct($message = null, \Exception $previous = null, $code = 0)
    {
        parent::__construct(412, $message, $previous, array(), $code);
    }
}
PK��ZrQrW��ASymfony/Component/HttpKernel/Exception/HttpExceptionInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Exception;

/**
 * Interface for HTTP error exceptions.
 *
 * @author Kris Wallsmith <kris@symfony.com>
 */
interface HttpExceptionInterface
{
    /**
     * Returns the status code.
     *
     * @return integer An HTTP response status code
     */
    public function getStatusCode();

    /**
     * Returns response headers.
     *
     * @return array Response headers
     */
    public function getHeaders();
}
PK��Z�^t�4Symfony/Component/HttpKernel/TerminableInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * Terminable extends the Kernel request/response cycle with dispatching a post
 * response event after sending the response and before shutting down the kernel.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Pierre Minnieur <pierre.minnieur@sensiolabs.de>
 *
 * @api
 */
interface TerminableInterface
{
    /**
     * Terminates a request/response cycle.
     *
     * Should be called after sending the response and before shutting down the kernel.
     *
     * @param Request  $request  A Request instance
     * @param Response $response A Response instance
     *
     * @api
     */
    public function terminate(Request $request, Response $response);
}
PK��Z���=AA4Symfony/Component/HttpKernel/HttpKernelInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * HttpKernelInterface handles a Request to convert it to a Response.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface HttpKernelInterface
{
    const MASTER_REQUEST = 1;
    const SUB_REQUEST = 2;

    /**
     * Handles a Request to convert it to a Response.
     *
     * When $catch is true, the implementation must catch all exceptions
     * and do its best to convert them to a Response instance.
     *
     * @param Request $request A Request instance
     * @param integer $type    The type of the request
     *                          (one of HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST)
     * @param Boolean $catch Whether to catch exceptions or not
     *
     * @return Response A Response instance
     *
     * @throws \Exception When an Exception occurs during processing
     *
     * @api
     */
    public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true);
}
PK��Z�k�t$$+Symfony/Component/HttpKernel/HttpKernel.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel;

use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

/**
 * HttpKernel notifies events to convert a Request object to a Response one.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class HttpKernel implements HttpKernelInterface, TerminableInterface
{
    protected $dispatcher;
    protected $resolver;
    protected $requestStack;

    /**
     * Constructor
     *
     * @param EventDispatcherInterface    $dispatcher   An EventDispatcherInterface instance
     * @param ControllerResolverInterface $resolver     A ControllerResolverInterface instance
     * @param RequestStack                $requestStack A stack for master/sub requests
     *
     * @api
     */
    public function __construct(EventDispatcherInterface $dispatcher, ControllerResolverInterface $resolver, RequestStack $requestStack = null)
    {
        $this->dispatcher = $dispatcher;
        $this->resolver = $resolver;
        $this->requestStack = $requestStack ?: new RequestStack();
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
    {
        try {
            return $this->handleRaw($request, $type);
        } catch (\Exception $e) {
            if (false === $catch) {
                $this->finishRequest($request, $type);

                throw $e;
            }

            return $this->handleException($e, $request, $type);
        }
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function terminate(Request $request, Response $response)
    {
        $this->dispatcher->dispatch(KernelEvents::TERMINATE, new PostResponseEvent($this, $request, $response));
    }

    /**
     * Handles a request to convert it to a response.
     *
     * Exceptions are not caught.
     *
     * @param Request $request A Request instance
     * @param integer $type    The type of the request (one of HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST)
     *
     * @return Response A Response instance
     *
     * @throws \LogicException If one of the listener does not behave as expected
     * @throws NotFoundHttpException When controller cannot be found
     */
    private function handleRaw(Request $request, $type = self::MASTER_REQUEST)
    {
        $this->requestStack->push($request);

        // request
        $event = new GetResponseEvent($this, $request, $type);
        $this->dispatcher->dispatch(KernelEvents::REQUEST, $event);

        if ($event->hasResponse()) {
            return $this->filterResponse($event->getResponse(), $request, $type);
        }

        // load controller
        if (false === $controller = $this->resolver->getController($request)) {
            throw new NotFoundHttpException(sprintf('Unable to find the controller for path "%s". Maybe you forgot to add the matching route in your routing configuration?', $request->getPathInfo()));
        }

        $event = new FilterControllerEvent($this, $controller, $request, $type);
        $this->dispatcher->dispatch(KernelEvents::CONTROLLER, $event);
        $controller = $event->getController();

        // controller arguments
        $arguments = $this->resolver->getArguments($request, $controller);

        // call controller
        $response = call_user_func_array($controller, $arguments);

        // view
        if (!$response instanceof Response) {
            $event = new GetResponseForControllerResultEvent($this, $request, $type, $response);
            $this->dispatcher->dispatch(KernelEvents::VIEW, $event);

            if ($event->hasResponse()) {
                $response = $event->getResponse();
            }

            if (!$response instanceof Response) {
                $msg = sprintf('The controller must return a response (%s given).', $this->varToString($response));

                // the user may have forgotten to return something
                if (null === $response) {
                    $msg .= ' Did you forget to add a return statement somewhere in your controller?';
                }
                throw new \LogicException($msg);
            }
        }

        return $this->filterResponse($response, $request, $type);
    }

    /**
     * Filters a response object.
     *
     * @param Response $response A Response instance
     * @param Request  $request  An error message in case the response is not a Response object
     * @param integer  $type     The type of the request (one of HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST)
     *
     * @return Response The filtered Response instance
     *
     * @throws \RuntimeException if the passed object is not a Response instance
     */
    private function filterResponse(Response $response, Request $request, $type)
    {
        $event = new FilterResponseEvent($this, $request, $type, $response);

        $this->dispatcher->dispatch(KernelEvents::RESPONSE, $event);

        $this->finishRequest($request, $type);

        return $event->getResponse();
    }

    /**
     * Publishes the finish request event, then pop the request from the stack.
     *
     * Note that the order of the operations is important here, otherwise
     * operations such as {@link RequestStack::getParentRequest()} can lead to
     * weird results.
     *
     * @param Request $request
     * @param int     $type
     */
    private function finishRequest(Request $request, $type)
    {
        $this->dispatcher->dispatch(KernelEvents::FINISH_REQUEST, new FinishRequestEvent($this, $request, $type));
        $this->requestStack->pop();
    }

    /**
     * Handles an exception by trying to convert it to a Response.
     *
     * @param \Exception $e       An \Exception instance
     * @param Request    $request A Request instance
     * @param integer    $type    The type of the request
     *
     * @return Response A Response instance
     *
     * @throws \Exception
     */
    private function handleException(\Exception $e, $request, $type)
    {
        $event = new GetResponseForExceptionEvent($this, $request, $type, $e);
        $this->dispatcher->dispatch(KernelEvents::EXCEPTION, $event);

        // a listener might have replaced the exception
        $e = $event->getException();

        if (!$event->hasResponse()) {
            $this->finishRequest($request, $type);

            throw $e;
        }

        $response = $event->getResponse();

        // the developer asked for a specific status code
        if ($response->headers->has('X-Status-Code')) {
            $response->setStatusCode($response->headers->get('X-Status-Code'));

            $response->headers->remove('X-Status-Code');
        } elseif (!$response->isClientError() && !$response->isServerError() && !$response->isRedirect()) {
            // ensure that we actually have an error response
            if ($e instanceof HttpExceptionInterface) {
                // keep the HTTP status code and headers
                $response->setStatusCode($e->getStatusCode());
                $response->headers->add($e->getHeaders());
            } else {
                $response->setStatusCode(500);
            }
        }

        try {
            return $this->filterResponse($response, $request, $type);
        } catch (\Exception $e) {
            return $response;
        }
    }

    private function varToString($var)
    {
        if (is_object($var)) {
            return sprintf('Object(%s)', get_class($var));
        }

        if (is_array($var)) {
            $a = array();
            foreach ($var as $k => $v) {
                $a[] = sprintf('%s => %s', $k, $this->varToString($v));
            }

            return sprintf("Array(%s)", implode(', ', $a));
        }

        if (is_resource($var)) {
            return sprintf('Resource(%s)', get_resource_type($var));
        }

        if (null === $var) {
            return 'null';
        }

        if (false === $var) {
            return 'false';
        }

        if (true === $var) {
            return 'true';
        }

        return (string) $var;
    }
}
PK��Z����b
b
9Symfony/Component/HttpKernel/HttpCache/StoreInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * This code is partially based on the Rack-Cache library by Ryan Tomayko,
 * which is released under the MIT license.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\HttpCache;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * Interface implemented by HTTP cache stores.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface StoreInterface
{
    /**
     * Locates a cached Response for the Request provided.
     *
     * @param Request $request A Request instance
     *
     * @return Response|null A Response instance, or null if no cache entry was found
     */
    public function lookup(Request $request);

    /**
     * Writes a cache entry to the store for the given Request and Response.
     *
     * Existing entries are read and any that match the response are removed. This
     * method calls write with the new list of cache entries.
     *
     * @param Request  $request  A Request instance
     * @param Response $response A Response instance
     *
     * @return string The key under which the response is stored
     */
    public function write(Request $request, Response $response);

    /**
     * Invalidates all cache entries that match the request.
     *
     * @param Request $request A Request instance
     */
    public function invalidate(Request $request);

    /**
     * Locks the cache for a given Request.
     *
     * @param Request $request A Request instance
     *
     * @return Boolean|string true if the lock is acquired, the path to the current lock otherwise
     */
    public function lock(Request $request);

    /**
     * Releases the lock for the given Request.
     *
     * @param Request $request A Request instance
     *
     * @return Boolean False if the lock file does not exist or cannot be unlocked, true otherwise
     */
    public function unlock(Request $request);

    /**
     * Returns whether or not a lock exists.
     *
     * @param Request $request A Request instance
     *
     * @return Boolean true if lock exists, false otherwise
     */
    public function isLocked(Request $request);

    /**
     * Purges data for the given URL.
     *
     * @param string $url A URL
     *
     * @return Boolean true if the URL exists and has been purged, false otherwise
     */
    public function purge($url);

    /**
     * Cleanups storage.
     */
    public function cleanup();
}
PK��ZM~��CCLSymfony/Component/HttpKernel/HttpCache/EsiResponseCacheStrategyInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * This code is partially based on the Rack-Cache library by Ryan Tomayko,
 * which is released under the MIT license.
 * (based on commit 02d2b48d75bcb63cf1c0c7149c077ad256542801)
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\HttpCache;

use Symfony\Component\HttpFoundation\Response;

/**
 * EsiResponseCacheStrategyInterface implementations know how to compute the
 * Response cache HTTP header based on the different ESI response cache headers.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface EsiResponseCacheStrategyInterface
{
    /**
     * Adds a Response.
     *
     * @param Response $response
     */
    public function add(Response $response);

    /**
     * Updates the Response HTTP headers based on the embedded Responses.
     *
     * @param Response $response
     */
    public function update(Response $response);
}
PK��Z�w�n n .Symfony/Component/HttpKernel/HttpCache/Esi.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\HttpCache;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface;

/**
 * Esi implements the ESI capabilities to Request and Response instances.
 *
 * For more information, read the following W3C notes:
 *
 *  * ESI Language Specification 1.0 (http://www.w3.org/TR/esi-lang)
 *
 *  * Edge Architecture Specification (http://www.w3.org/TR/edge-arch)
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Esi
{
    private $contentTypes;

    /**
     * Constructor.
     *
     * @param array $contentTypes An array of content-type that should be parsed for ESI information.
     *                           (default: text/html, text/xml, application/xhtml+xml, and application/xml)
     */
    public function __construct(array $contentTypes = array('text/html', 'text/xml', 'application/xhtml+xml', 'application/xml'))
    {
        $this->contentTypes = $contentTypes;
    }

    /**
     * Returns a new cache strategy instance.
     *
     * @return EsiResponseCacheStrategyInterface A EsiResponseCacheStrategyInterface instance
     */
    public function createCacheStrategy()
    {
        return new EsiResponseCacheStrategy();
    }

    /**
     * Checks that at least one surrogate has ESI/1.0 capability.
     *
     * @param Request $request A Request instance
     *
     * @return Boolean true if one surrogate has ESI/1.0 capability, false otherwise
     */
    public function hasSurrogateEsiCapability(Request $request)
    {
        if (null === $value = $request->headers->get('Surrogate-Capability')) {
            return false;
        }

        return false !== strpos($value, 'ESI/1.0');
    }

    /**
     * Adds ESI/1.0 capability to the given Request.
     *
     * @param Request $request A Request instance
     */
    public function addSurrogateEsiCapability(Request $request)
    {
        $current = $request->headers->get('Surrogate-Capability');
        $new = 'symfony2="ESI/1.0"';

        $request->headers->set('Surrogate-Capability', $current ? $current.', '.$new : $new);
    }

    /**
     * Adds HTTP headers to specify that the Response needs to be parsed for ESI.
     *
     * This method only adds an ESI HTTP header if the Response has some ESI tags.
     *
     * @param Response $response A Response instance
     */
    public function addSurrogateControl(Response $response)
    {
        if (false !== strpos($response->getContent(), '<esi:include')) {
            $response->headers->set('Surrogate-Control', 'content="ESI/1.0"');
        }
    }

    /**
     * Checks that the Response needs to be parsed for ESI tags.
     *
     * @param Response $response A Response instance
     *
     * @return Boolean true if the Response needs to be parsed, false otherwise
     */
    public function needsEsiParsing(Response $response)
    {
        if (!$control = $response->headers->get('Surrogate-Control')) {
            return false;
        }

        return (Boolean) preg_match('#content="[^"]*ESI/1.0[^"]*"#', $control);
    }

    /**
     * Renders an ESI tag.
     *
     * @param string  $uri          A URI
     * @param string  $alt          An alternate URI
     * @param Boolean $ignoreErrors Whether to ignore errors or not
     * @param string  $comment      A comment to add as an esi:include tag
     *
     * @return string
     */
    public function renderIncludeTag($uri, $alt = null, $ignoreErrors = true, $comment = '')
    {
        $html = sprintf('<esi:include src="%s"%s%s />',
            $uri,
            $ignoreErrors ? ' onerror="continue"' : '',
            $alt ? sprintf(' alt="%s"', $alt) : ''
        );

        if (!empty($comment)) {
            return sprintf("<esi:comment text=\"%s\" />\n%s", $comment, $html);
        }

        return $html;
    }

    /**
     * Replaces a Response ESI tags with the included resource content.
     *
     * @param Request  $request  A Request instance
     * @param Response $response A Response instance
     *
     * @return Response
     */
    public function process(Request $request, Response $response)
    {
        $this->request = $request;
        $type = $response->headers->get('Content-Type');
        if (empty($type)) {
            $type = 'text/html';
        }

        $parts = explode(';', $type);
        if (!in_array($parts[0], $this->contentTypes)) {
            return $response;
        }

        // we don't use a proper XML parser here as we can have ESI tags in a plain text response
        $content = $response->getContent();
        $content = str_replace(array('<?', '<%'), array('<?php echo "<?"; ?>', '<?php echo "<%"; ?>'), $content);
        $content = preg_replace_callback('#<esi\:include\s+(.*?)\s*(?:/|</esi\:include)>#', array($this, 'handleEsiIncludeTag'), $content);
        $content = preg_replace('#<esi\:comment[^>]*(?:/|</esi\:comment)>#', '', $content);
        $content = preg_replace('#<esi\:remove>.*?</esi\:remove>#', '', $content);

        $response->setContent($content);
        $response->headers->set('X-Body-Eval', 'ESI');

        // remove ESI/1.0 from the Surrogate-Control header
        if ($response->headers->has('Surrogate-Control')) {
            $value = $response->headers->get('Surrogate-Control');
            if ('content="ESI/1.0"' == $value) {
                $response->headers->remove('Surrogate-Control');
            } elseif (preg_match('#,\s*content="ESI/1.0"#', $value)) {
                $response->headers->set('Surrogate-Control', preg_replace('#,\s*content="ESI/1.0"#', '', $value));
            } elseif (preg_match('#content="ESI/1.0",\s*#', $value)) {
                $response->headers->set('Surrogate-Control', preg_replace('#content="ESI/1.0",\s*#', '', $value));
            }
        }
    }

    /**
     * Handles an ESI from the cache.
     *
     * @param HttpCache $cache        An HttpCache instance
     * @param string    $uri          The main URI
     * @param string    $alt          An alternative URI
     * @param Boolean   $ignoreErrors Whether to ignore errors or not
     *
     * @return string
     *
     * @throws \RuntimeException
     * @throws \Exception
     */
    public function handle(HttpCache $cache, $uri, $alt, $ignoreErrors)
    {
        $subRequest = Request::create($uri, 'get', array(), $cache->getRequest()->cookies->all(), array(), $cache->getRequest()->server->all());

        try {
            $response = $cache->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true);

            if (!$response->isSuccessful()) {
                throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $subRequest->getUri(), $response->getStatusCode()));
            }

            return $response->getContent();
        } catch (\Exception $e) {
            if ($alt) {
                return $this->handle($cache, $alt, '', $ignoreErrors);
            }

            if (!$ignoreErrors) {
                throw $e;
            }
        }
    }

    /**
     * Handles an ESI include tag (called internally).
     *
     * @param array $attributes An array containing the attributes.
     *
     * @return string The response content for the include.
     *
     * @throws \RuntimeException
     */
    private function handleEsiIncludeTag($attributes)
    {
        $options = array();
        preg_match_all('/(src|onerror|alt)="([^"]*?)"/', $attributes[1], $matches, PREG_SET_ORDER);
        foreach ($matches as $set) {
            $options[$set[1]] = $set[2];
        }

        if (!isset($options['src'])) {
            throw new \RuntimeException('Unable to process an ESI tag without a "src" attribute.');
        }

        return sprintf('<?php echo $this->esi->handle($this, \'%s\', \'%s\', %s) ?>'."\n",
            $options['src'],
            isset($options['alt']) ? $options['alt'] : null,
            isset($options['onerror']) && 'continue' == $options['onerror'] ? 'true' : 'false'
        );
    }
}
PK��Z�#��[�[4Symfony/Component/HttpKernel/HttpCache/HttpCache.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * This code is partially based on the Rack-Cache library by Ryan Tomayko,
 * which is released under the MIT license.
 * (based on commit 02d2b48d75bcb63cf1c0c7149c077ad256542801)
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\HttpCache;

use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\TerminableInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * Cache provides HTTP caching.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class HttpCache implements HttpKernelInterface, TerminableInterface
{
    private $kernel;
    private $store;
    private $request;
    private $esi;
    private $esiCacheStrategy;
    private $options = array();
    private $traces = array();

    /**
     * Constructor.
     *
     * The available options are:
     *
     *   * debug:                 If true, the traces are added as a HTTP header to ease debugging
     *
     *   * default_ttl            The number of seconds that a cache entry should be considered
     *                            fresh when no explicit freshness information is provided in
     *                            a response. Explicit Cache-Control or Expires headers
     *                            override this value. (default: 0)
     *
     *   * private_headers        Set of request headers that trigger "private" cache-control behavior
     *                            on responses that don't explicitly state whether the response is
     *                            public or private via a Cache-Control directive. (default: Authorization and Cookie)
     *
     *   * allow_reload           Specifies whether the client can force a cache reload by including a
     *                            Cache-Control "no-cache" directive in the request. Set it to ``true``
     *                            for compliance with RFC 2616. (default: false)
     *
     *   * allow_revalidate       Specifies whether the client can force a cache revalidate by including
     *                            a Cache-Control "max-age=0" directive in the request. Set it to ``true``
     *                            for compliance with RFC 2616. (default: false)
     *
     *   * stale_while_revalidate Specifies the default number of seconds (the granularity is the second as the
     *                            Response TTL precision is a second) during which the cache can immediately return
     *                            a stale response while it revalidates it in the background (default: 2).
     *                            This setting is overridden by the stale-while-revalidate HTTP Cache-Control
     *                            extension (see RFC 5861).
     *
     *   * stale_if_error         Specifies the default number of seconds (the granularity is the second) during which
     *                            the cache can serve a stale response when an error is encountered (default: 60).
     *                            This setting is overridden by the stale-if-error HTTP Cache-Control extension
     *                            (see RFC 5861).
     *
     * @param HttpKernelInterface $kernel  An HttpKernelInterface instance
     * @param StoreInterface      $store   A Store instance
     * @param Esi                 $esi     An Esi instance
     * @param array               $options An array of options
     */
    public function __construct(HttpKernelInterface $kernel, StoreInterface $store, Esi $esi = null, array $options = array())
    {
        $this->store = $store;
        $this->kernel = $kernel;
        $this->esi = $esi;

        // needed in case there is a fatal error because the backend is too slow to respond
        register_shutdown_function(array($this->store, 'cleanup'));

        $this->options = array_merge(array(
            'debug'                  => false,
            'default_ttl'            => 0,
            'private_headers'        => array('Authorization', 'Cookie'),
            'allow_reload'           => false,
            'allow_revalidate'       => false,
            'stale_while_revalidate' => 2,
            'stale_if_error'         => 60,
        ), $options);
    }

    /**
     * Gets the current store.
     *
     * @return StoreInterface $store A StoreInterface instance
     */
    public function getStore()
    {
        return $this->store;
    }

    /**
     * Returns an array of events that took place during processing of the last request.
     *
     * @return array An array of events
     */
    public function getTraces()
    {
        return $this->traces;
    }

    /**
     * Returns a log message for the events of the last request processing.
     *
     * @return string A log message
     */
    public function getLog()
    {
        $log = array();
        foreach ($this->traces as $request => $traces) {
            $log[] = sprintf('%s: %s', $request, implode(', ', $traces));
        }

        return implode('; ', $log);
    }

    /**
     * Gets the Request instance associated with the master request.
     *
     * @return Request A Request instance
     */
    public function getRequest()
    {
        return $this->request;
    }

    /**
     * Gets the Kernel instance
     *
     * @return HttpKernelInterface An HttpKernelInterface instance
     */
    public function getKernel()
    {
        return $this->kernel;
    }


    /**
     * Gets the Esi instance
     *
     * @return Esi An Esi instance
     */
    public function getEsi()
    {
        return $this->esi;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
    {
        // FIXME: catch exceptions and implement a 500 error page here? -> in Varnish, there is a built-in error page mechanism
        if (HttpKernelInterface::MASTER_REQUEST === $type) {
            $this->traces = array();
            $this->request = $request;
            if (null !== $this->esi) {
                $this->esiCacheStrategy = $this->esi->createCacheStrategy();
            }
        }

        $path = $request->getPathInfo();
        if ($qs = $request->getQueryString()) {
            $path .= '?'.$qs;
        }
        $this->traces[$request->getMethod().' '.$path] = array();

        if (!$request->isMethodSafe()) {
            $response = $this->invalidate($request, $catch);
        } elseif ($request->headers->has('expect')) {
            $response = $this->pass($request, $catch);
        } else {
            $response = $this->lookup($request, $catch);
        }

        $this->restoreResponseBody($request, $response);

        $response->setDate(new \DateTime(null, new \DateTimeZone('UTC')));

        if (HttpKernelInterface::MASTER_REQUEST === $type && $this->options['debug']) {
            $response->headers->set('X-Symfony-Cache', $this->getLog());
        }

        if (null !== $this->esi) {
            if (HttpKernelInterface::MASTER_REQUEST === $type) {
                $this->esiCacheStrategy->update($response);
            } else {
                $this->esiCacheStrategy->add($response);
            }
        }

        $response->prepare($request);

        $response->isNotModified($request);

        return $response;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function terminate(Request $request, Response $response)
    {
        if ($this->getKernel() instanceof TerminableInterface) {
            $this->getKernel()->terminate($request, $response);
        }
    }

    /**
     * Forwards the Request to the backend without storing the Response in the cache.
     *
     * @param Request $request A Request instance
     * @param Boolean $catch   Whether to process exceptions
     *
     * @return Response A Response instance
     */
    protected function pass(Request $request, $catch = false)
    {
        $this->record($request, 'pass');

        return $this->forward($request, $catch);
    }

    /**
     * Invalidates non-safe methods (like POST, PUT, and DELETE).
     *
     * @param Request $request A Request instance
     * @param Boolean $catch   Whether to process exceptions
     *
     * @return Response A Response instance
     *
     * @throws \Exception
     *
     * @see RFC2616 13.10
     */
    protected function invalidate(Request $request, $catch = false)
    {
        $response = $this->pass($request, $catch);

        // invalidate only when the response is successful
        if ($response->isSuccessful() || $response->isRedirect()) {
            try {
                $this->store->invalidate($request, $catch);

                // As per the RFC, invalidate Location and Content-Location URLs if present
                foreach (array('Location', 'Content-Location') as $header) {
                    if ($uri = $response->headers->get($header)) {
                        $subRequest = Request::create($uri, 'get', array(), array(), array(), $request->server->all());

                        $this->store->invalidate($subRequest);
                    }
                }

                $this->record($request, 'invalidate');
            } catch (\Exception $e) {
                $this->record($request, 'invalidate-failed');

                if ($this->options['debug']) {
                    throw $e;
                }
            }
        }

        return $response;
    }

    /**
     * Lookups a Response from the cache for the given Request.
     *
     * When a matching cache entry is found and is fresh, it uses it as the
     * response without forwarding any request to the backend. When a matching
     * cache entry is found but is stale, it attempts to "validate" the entry with
     * the backend using conditional GET. When no matching cache entry is found,
     * it triggers "miss" processing.
     *
     * @param Request $request A Request instance
     * @param Boolean $catch   whether to process exceptions
     *
     * @return Response A Response instance
     *
     * @throws \Exception
     */
    protected function lookup(Request $request, $catch = false)
    {
        // if allow_reload and no-cache Cache-Control, allow a cache reload
        if ($this->options['allow_reload'] && $request->isNoCache()) {
            $this->record($request, 'reload');

            return $this->fetch($request, $catch);
        }

        try {
            $entry = $this->store->lookup($request);
        } catch (\Exception $e) {
            $this->record($request, 'lookup-failed');

            if ($this->options['debug']) {
                throw $e;
            }

            return $this->pass($request, $catch);
        }

        if (null === $entry) {
            $this->record($request, 'miss');

            return $this->fetch($request, $catch);
        }

        if (!$this->isFreshEnough($request, $entry)) {
            $this->record($request, 'stale');

            return $this->validate($request, $entry, $catch);
        }

        $this->record($request, 'fresh');

        $entry->headers->set('Age', $entry->getAge());

        return $entry;
    }

    /**
     * Validates that a cache entry is fresh.
     *
     * The original request is used as a template for a conditional
     * GET request with the backend.
     *
     * @param Request  $request A Request instance
     * @param Response $entry   A Response instance to validate
     * @param Boolean  $catch   Whether to process exceptions
     *
     * @return Response A Response instance
     */
    protected function validate(Request $request, Response $entry, $catch = false)
    {
        $subRequest = clone $request;

        // send no head requests because we want content
        $subRequest->setMethod('GET');

        // add our cached last-modified validator
        $subRequest->headers->set('if_modified_since', $entry->headers->get('Last-Modified'));

        // Add our cached etag validator to the environment.
        // We keep the etags from the client to handle the case when the client
        // has a different private valid entry which is not cached here.
        $cachedEtags = $entry->getEtag() ? array($entry->getEtag()) : array();
        $requestEtags = $request->getEtags();
        if ($etags = array_unique(array_merge($cachedEtags, $requestEtags))) {
            $subRequest->headers->set('if_none_match', implode(', ', $etags));
        }

        $response = $this->forward($subRequest, $catch, $entry);

        if (304 == $response->getStatusCode()) {
            $this->record($request, 'valid');

            // return the response and not the cache entry if the response is valid but not cached
            $etag = $response->getEtag();
            if ($etag && in_array($etag, $requestEtags) && !in_array($etag, $cachedEtags)) {
                return $response;
            }

            $entry = clone $entry;
            $entry->headers->remove('Date');

            foreach (array('Date', 'Expires', 'Cache-Control', 'ETag', 'Last-Modified') as $name) {
                if ($response->headers->has($name)) {
                    $entry->headers->set($name, $response->headers->get($name));
                }
            }

            $response = $entry;
        } else {
            $this->record($request, 'invalid');
        }

        if ($response->isCacheable()) {
            $this->store($request, $response);
        }

        return $response;
    }

    /**
     * Forwards the Request to the backend and determines whether the response should be stored.
     *
     * This methods is triggered when the cache missed or a reload is required.
     *
     * @param Request $request A Request instance
     * @param Boolean $catch   whether to process exceptions
     *
     * @return Response A Response instance
     */
    protected function fetch(Request $request, $catch = false)
    {
        $subRequest = clone $request;

        // send no head requests because we want content
        $subRequest->setMethod('GET');

        // avoid that the backend sends no content
        $subRequest->headers->remove('if_modified_since');
        $subRequest->headers->remove('if_none_match');

        $response = $this->forward($subRequest, $catch);

        if ($this->isPrivateRequest($request) && !$response->headers->hasCacheControlDirective('public')) {
            $response->setPrivate(true);
        } elseif ($this->options['default_ttl'] > 0 && null === $response->getTtl() && !$response->headers->getCacheControlDirective('must-revalidate')) {
            $response->setTtl($this->options['default_ttl']);
        }

        if ($response->isCacheable()) {
            $this->store($request, $response);
        }

        return $response;
    }

    /**
     * Forwards the Request to the backend and returns the Response.
     *
     * @param Request  $request A Request instance
     * @param Boolean  $catch   Whether to catch exceptions or not
     * @param Response $entry   A Response instance (the stale entry if present, null otherwise)
     *
     * @return Response A Response instance
     */
    protected function forward(Request $request, $catch = false, Response $entry = null)
    {
        if ($this->esi) {
            $this->esi->addSurrogateEsiCapability($request);
        }

        // modify the X-Forwarded-For header if needed
        $forwardedFor = $request->headers->get('X-Forwarded-For');
        if ($forwardedFor) {
            $request->headers->set('X-Forwarded-For', $forwardedFor.', '.$request->server->get('REMOTE_ADDR'));
        } else {
            $request->headers->set('X-Forwarded-For', $request->server->get('REMOTE_ADDR'));
        }

        // fix the client IP address by setting it to 127.0.0.1 as HttpCache
        // is always called from the same process as the backend.
        $request->server->set('REMOTE_ADDR', '127.0.0.1');

        // always a "master" request (as the real master request can be in cache)
        $response = $this->kernel->handle($request, HttpKernelInterface::MASTER_REQUEST, $catch);
        // FIXME: we probably need to also catch exceptions if raw === true

        // we don't implement the stale-if-error on Requests, which is nonetheless part of the RFC
        if (null !== $entry && in_array($response->getStatusCode(), array(500, 502, 503, 504))) {
            if (null === $age = $entry->headers->getCacheControlDirective('stale-if-error')) {
                $age = $this->options['stale_if_error'];
            }

            if (abs($entry->getTtl()) < $age) {
                $this->record($request, 'stale-if-error');

                return $entry;
            }
        }

        $this->processResponseBody($request, $response);

        return $response;
    }

    /**
     * Checks whether the cache entry is "fresh enough" to satisfy the Request.
     *
     * @param Request  $request A Request instance
     * @param Response $entry   A Response instance
     *
     * @return Boolean true if the cache entry if fresh enough, false otherwise
     */
    protected function isFreshEnough(Request $request, Response $entry)
    {
        if (!$entry->isFresh()) {
            return $this->lock($request, $entry);
        }

        if ($this->options['allow_revalidate'] && null !== $maxAge = $request->headers->getCacheControlDirective('max-age')) {
            return $maxAge > 0 && $maxAge >= $entry->getAge();
        }

        return true;
    }

    /**
     * Locks a Request during the call to the backend.
     *
     * @param Request  $request A Request instance
     * @param Response $entry   A Response instance
     *
     * @return Boolean true if the cache entry can be returned even if it is staled, false otherwise
     */
    protected function lock(Request $request, Response $entry)
    {
        // try to acquire a lock to call the backend
        $lock = $this->store->lock($request, $entry);

        // there is already another process calling the backend
        if (true !== $lock) {
            // check if we can serve the stale entry
            if (null === $age = $entry->headers->getCacheControlDirective('stale-while-revalidate')) {
                $age = $this->options['stale_while_revalidate'];
            }

            if (abs($entry->getTtl()) < $age) {
                $this->record($request, 'stale-while-revalidate');

                // server the stale response while there is a revalidation
                return true;
            }

            // wait for the lock to be released
            $wait = 0;
            while ($this->store->isLocked($request) && $wait < 5000000) {
                usleep(50000);
                $wait += 50000;
            }

            if ($wait < 2000000) {
                // replace the current entry with the fresh one
                $new = $this->lookup($request);
                $entry->headers = $new->headers;
                $entry->setContent($new->getContent());
                $entry->setStatusCode($new->getStatusCode());
                $entry->setProtocolVersion($new->getProtocolVersion());
                foreach ($new->headers->getCookies() as $cookie) {
                    $entry->headers->setCookie($cookie);
                }
            } else {
                // backend is slow as hell, send a 503 response (to avoid the dog pile effect)
                $entry->setStatusCode(503);
                $entry->setContent('503 Service Unavailable');
                $entry->headers->set('Retry-After', 10);
            }

            return true;
        }

        // we have the lock, call the backend
        return false;
    }

    /**
     * Writes the Response to the cache.
     *
     * @param Request  $request  A Request instance
     * @param Response $response A Response instance
     *
     * @throws \Exception
     */
    protected function store(Request $request, Response $response)
    {
        try {
            $this->store->write($request, $response);

            $this->record($request, 'store');

            $response->headers->set('Age', $response->getAge());
        } catch (\Exception $e) {
            $this->record($request, 'store-failed');

            if ($this->options['debug']) {
                throw $e;
            }
        }

        // now that the response is cached, release the lock
        $this->store->unlock($request);
    }

    /**
     * Restores the Response body.
     *
     * @param Request  $request  A Request instance
     * @param Response $response A Response instance
     *
     * @return Response A Response instance
     */
    private function restoreResponseBody(Request $request, Response $response)
    {
        if ($request->isMethod('HEAD') || 304 === $response->getStatusCode()) {
            $response->setContent(null);
            $response->headers->remove('X-Body-Eval');
            $response->headers->remove('X-Body-File');

            return;
        }

        if ($response->headers->has('X-Body-Eval')) {
            ob_start();

            if ($response->headers->has('X-Body-File')) {
                include $response->headers->get('X-Body-File');
            } else {
                eval('; ?>'.$response->getContent().'<?php ;');
            }

            $response->setContent(ob_get_clean());
            $response->headers->remove('X-Body-Eval');
            if (!$response->headers->has('Transfer-Encoding')) {
                $response->headers->set('Content-Length', strlen($response->getContent()));
            }
        } elseif ($response->headers->has('X-Body-File')) {
            $response->setContent(file_get_contents($response->headers->get('X-Body-File')));
        } else {
            return;
        }

        $response->headers->remove('X-Body-File');
    }

    protected function processResponseBody(Request $request, Response $response)
    {
        if (null !== $this->esi && $this->esi->needsEsiParsing($response)) {
            $this->esi->process($request, $response);
        }
    }

    /**
     * Checks if the Request includes authorization or other sensitive information
     * that should cause the Response to be considered private by default.
     *
     * @param Request $request A Request instance
     *
     * @return Boolean true if the Request is private, false otherwise
     */
    private function isPrivateRequest(Request $request)
    {
        foreach ($this->options['private_headers'] as $key) {
            $key = strtolower(str_replace('HTTP_', '', $key));

            if ('cookie' === $key) {
                if (count($request->cookies->all())) {
                    return true;
                }
            } elseif ($request->headers->has($key)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Records that an event took place.
     *
     * @param Request $request A Request instance
     * @param string  $event   The event name
     */
    private function record(Request $request, $event)
    {
        $path = $request->getPathInfo();
        if ($qs = $request->getQueryString()) {
            $path .= '?'.$qs;
        }
        $this->traces[$request->getMethod().' '.$path][] = $event;
    }
}
PK��Z�K:�1�10Symfony/Component/HttpKernel/HttpCache/Store.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * This code is partially based on the Rack-Cache library by Ryan Tomayko,
 * which is released under the MIT license.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\HttpCache;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * Store implements all the logic for storing cache metadata (Request and Response headers).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Store implements StoreInterface
{
    protected $root;
    private $keyCache;
    private $locks;

    /**
     * Constructor.
     *
     * @param string $root The path to the cache directory
     */
    public function __construct($root)
    {
        $this->root = $root;
        if (!is_dir($this->root)) {
            mkdir($this->root, 0777, true);
        }
        $this->keyCache = new \SplObjectStorage();
        $this->locks = array();
    }

    /**
     * Cleanups storage.
     */
    public function cleanup()
    {
        // unlock everything
        foreach ($this->locks as $lock) {
            if (file_exists($lock)) {
                @unlink($lock);
            }
        }

        $error = error_get_last();
        if (1 === $error['type'] && false === headers_sent()) {
            // send a 503
            header('HTTP/1.0 503 Service Unavailable');
            header('Retry-After: 10');
            echo '503 Service Unavailable';
        }
    }

    /**
     * Locks the cache for a given Request.
     *
     * @param Request $request A Request instance
     *
     * @return Boolean|string true if the lock is acquired, the path to the current lock otherwise
     */
    public function lock(Request $request)
    {
        $path = $this->getPath($this->getCacheKey($request).'.lck');
        if (!is_dir(dirname($path)) && false === @mkdir(dirname($path), 0777, true)) {
            return false;
        }

        $lock = @fopen($path, 'x');
        if (false !== $lock) {
            fclose($lock);

            $this->locks[] = $path;

            return true;
        }

        return !file_exists($path) ?: $path;
    }

    /**
     * Releases the lock for the given Request.
     *
     * @param Request $request A Request instance
     *
     * @return Boolean False if the lock file does not exist or cannot be unlocked, true otherwise
     */
    public function unlock(Request $request)
    {
        $file = $this->getPath($this->getCacheKey($request).'.lck');

        return is_file($file) ? @unlink($file) : false;
    }

    public function isLocked(Request $request)
    {
        return is_file($this->getPath($this->getCacheKey($request).'.lck'));
    }

    /**
     * Locates a cached Response for the Request provided.
     *
     * @param Request $request A Request instance
     *
     * @return Response|null A Response instance, or null if no cache entry was found
     */
    public function lookup(Request $request)
    {
        $key = $this->getCacheKey($request);

        if (!$entries = $this->getMetadata($key)) {
            return null;
        }

        // find a cached entry that matches the request.
        $match = null;
        foreach ($entries as $entry) {
            if ($this->requestsMatch(isset($entry[1]['vary'][0]) ? $entry[1]['vary'][0] : '', $request->headers->all(), $entry[0])) {
                $match = $entry;

                break;
            }
        }

        if (null === $match) {
            return null;
        }

        list($req, $headers) = $match;
        if (is_file($body = $this->getPath($headers['x-content-digest'][0]))) {
            return $this->restoreResponse($headers, $body);
        }

        // TODO the metaStore referenced an entity that doesn't exist in
        // the entityStore. We definitely want to return nil but we should
        // also purge the entry from the meta-store when this is detected.
        return null;
    }

    /**
     * Writes a cache entry to the store for the given Request and Response.
     *
     * Existing entries are read and any that match the response are removed. This
     * method calls write with the new list of cache entries.
     *
     * @param Request  $request  A Request instance
     * @param Response $response A Response instance
     *
     * @return string The key under which the response is stored
     *
     * @throws \RuntimeException
     */
    public function write(Request $request, Response $response)
    {
        $key = $this->getCacheKey($request);
        $storedEnv = $this->persistRequest($request);

        // write the response body to the entity store if this is the original response
        if (!$response->headers->has('X-Content-Digest')) {
            $digest = $this->generateContentDigest($response);

            if (false === $this->save($digest, $response->getContent())) {
                throw new \RuntimeException('Unable to store the entity.');
            }

            $response->headers->set('X-Content-Digest', $digest);

            if (!$response->headers->has('Transfer-Encoding')) {
                $response->headers->set('Content-Length', strlen($response->getContent()));
            }
        }

        // read existing cache entries, remove non-varying, and add this one to the list
        $entries = array();
        $vary = $response->headers->get('vary');
        foreach ($this->getMetadata($key) as $entry) {
            if (!isset($entry[1]['vary'][0])) {
                $entry[1]['vary'] = array('');
            }

            if ($vary != $entry[1]['vary'][0] || !$this->requestsMatch($vary, $entry[0], $storedEnv)) {
                $entries[] = $entry;
            }
        }

        $headers = $this->persistResponse($response);
        unset($headers['age']);

        array_unshift($entries, array($storedEnv, $headers));

        if (false === $this->save($key, serialize($entries))) {
            throw new \RuntimeException('Unable to store the metadata.');
        }

        return $key;
    }

    /**
     * Returns content digest for $response.
     *
     * @param Response $response
     *
     * @return string
     */
    protected function generateContentDigest(Response $response)
    {
        return 'en'.hash('sha256', $response->getContent());
    }

    /**
     * Invalidates all cache entries that match the request.
     *
     * @param Request $request A Request instance
     *
     * @throws \RuntimeException
     */
    public function invalidate(Request $request)
    {
        $modified = false;
        $key = $this->getCacheKey($request);

        $entries = array();
        foreach ($this->getMetadata($key) as $entry) {
            $response = $this->restoreResponse($entry[1]);
            if ($response->isFresh()) {
                $response->expire();
                $modified = true;
                $entries[] = array($entry[0], $this->persistResponse($response));
            } else {
                $entries[] = $entry;
            }
        }

        if ($modified) {
            if (false === $this->save($key, serialize($entries))) {
                throw new \RuntimeException('Unable to store the metadata.');
            }
        }
    }

    /**
     * Determines whether two Request HTTP header sets are non-varying based on
     * the vary response header value provided.
     *
     * @param string $vary A Response vary header
     * @param array  $env1 A Request HTTP header array
     * @param array  $env2 A Request HTTP header array
     *
     * @return Boolean true if the two environments match, false otherwise
     */
    private function requestsMatch($vary, $env1, $env2)
    {
        if (empty($vary)) {
            return true;
        }

        foreach (preg_split('/[\s,]+/', $vary) as $header) {
            $key = strtr(strtolower($header), '_', '-');
            $v1 = isset($env1[$key]) ? $env1[$key] : null;
            $v2 = isset($env2[$key]) ? $env2[$key] : null;
            if ($v1 !== $v2) {
                return false;
            }
        }

        return true;
    }

    /**
     * Gets all data associated with the given key.
     *
     * Use this method only if you know what you are doing.
     *
     * @param string $key The store key
     *
     * @return array An array of data associated with the key
     */
    private function getMetadata($key)
    {
        if (false === $entries = $this->load($key)) {
            return array();
        }

        return unserialize($entries);
    }

    /**
     * Purges data for the given URL.
     *
     * @param string $url A URL
     *
     * @return Boolean true if the URL exists and has been purged, false otherwise
     */
    public function purge($url)
    {
        if (is_file($path = $this->getPath($this->getCacheKey(Request::create($url))))) {
            unlink($path);

            return true;
        }

        return false;
    }

    /**
     * Loads data for the given key.
     *
     * @param string $key The store key
     *
     * @return string The data associated with the key
     */
    private function load($key)
    {
        $path = $this->getPath($key);

        return is_file($path) ? file_get_contents($path) : false;
    }

    /**
     * Save data for the given key.
     *
     * @param string $key  The store key
     * @param string $data The data to store
     *
     * @return Boolean
     */
    private function save($key, $data)
    {
        $path = $this->getPath($key);
        if (!is_dir(dirname($path)) && false === @mkdir(dirname($path), 0777, true)) {
            return false;
        }

        $tmpFile = tempnam(dirname($path), basename($path));
        if (false === $fp = @fopen($tmpFile, 'wb')) {
            return false;
        }
        @fwrite($fp, $data);
        @fclose($fp);

        if ($data != file_get_contents($tmpFile)) {
            return false;
        }

        if (false === @rename($tmpFile, $path)) {
            return false;
        }

        @chmod($path, 0666 & ~umask());
    }

    public function getPath($key)
    {
        return $this->root.DIRECTORY_SEPARATOR.substr($key, 0, 2).DIRECTORY_SEPARATOR.substr($key, 2, 2).DIRECTORY_SEPARATOR.substr($key, 4, 2).DIRECTORY_SEPARATOR.substr($key, 6);
    }

    /**
     * Generates a cache key for the given Request.
     *
     * This method should return a key that must only depend on a
     * normalized version of the request URI.
     *
     * If the same URI can have more than one representation, based on some
     * headers, use a Vary header to indicate them, and each representation will
     * be stored independently under the same cache key.
     *
     * @param Request $request A Request instance
     *
     * @return string A key for the given Request
     */
    protected function generateCacheKey(Request $request)
    {
        return 'md'.hash('sha256', $request->getUri());
    }

    /**
     * Returns a cache key for the given Request.
     *
     * @param Request $request A Request instance
     *
     * @return string A key for the given Request
     */
    private function getCacheKey(Request $request)
    {
        if (isset($this->keyCache[$request])) {
            return $this->keyCache[$request];
        }

        return $this->keyCache[$request] = $this->generateCacheKey($request);
    }

    /**
     * Persists the Request HTTP headers.
     *
     * @param Request $request A Request instance
     *
     * @return array An array of HTTP headers
     */
    private function persistRequest(Request $request)
    {
        return $request->headers->all();
    }

    /**
     * Persists the Response HTTP headers.
     *
     * @param Response $response A Response instance
     *
     * @return array An array of HTTP headers
     */
    private function persistResponse(Response $response)
    {
        $headers = $response->headers->all();
        $headers['X-Status'] = array($response->getStatusCode());

        return $headers;
    }

    /**
     * Restores a Response from the HTTP headers and body.
     *
     * @param array  $headers An array of HTTP headers for the Response
     * @param string $body    The Response body
     *
     * @return Response
     */
    private function restoreResponse($headers, $body = null)
    {
        $status = $headers['X-Status'][0];
        unset($headers['X-Status']);

        if (null !== $body) {
            $headers['X-Body-File'] = array($body);
        }

        return new Response($body, $status, $headers);
    }
}
PK��Z/��)�	�	CSymfony/Component/HttpKernel/HttpCache/EsiResponseCacheStrategy.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * This code is partially based on the Rack-Cache library by Ryan Tomayko,
 * which is released under the MIT license.
 * (based on commit 02d2b48d75bcb63cf1c0c7149c077ad256542801)
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\HttpCache;

use Symfony\Component\HttpFoundation\Response;

/**
 * EsiResponseCacheStrategy knows how to compute the Response cache HTTP header
 * based on the different ESI response cache headers.
 *
 * This implementation changes the master response TTL to the smallest TTL received
 * or force validation if one of the ESI has validation cache strategy.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class EsiResponseCacheStrategy implements EsiResponseCacheStrategyInterface
{
    private $cacheable = true;
    private $embeddedResponses = 0;
    private $ttls = array();
    private $maxAges = array();

    /**
     * {@inheritdoc}
     */
    public function add(Response $response)
    {
        if ($response->isValidateable()) {
            $this->cacheable = false;
        } else {
            $this->ttls[] = $response->getTtl();
            $this->maxAges[] = $response->getMaxAge();
        }

        $this->embeddedResponses++;
    }

    /**
     * {@inheritdoc}
     */
    public function update(Response $response)
    {
        // if we have no embedded Response, do nothing
        if (0 === $this->embeddedResponses) {
            return;
        }

        // Remove validation related headers in order to avoid browsers using
        // their own cache, because some of the response content comes from
        // at least one embedded response (which likely has a different caching strategy).
        if ($response->isValidateable()) {
            $response->setEtag(null);
            $response->setLastModified(null);
            $this->cacheable = false;
        }

        if (!$this->cacheable) {
            $response->headers->set('Cache-Control', 'no-cache, must-revalidate');

            return;
        }

        $this->ttls[] = $response->getTtl();
        $this->maxAges[] = $response->getMaxAge();

        if (null !== $maxAge = min($this->maxAges)) {
            $response->setSharedMaxAge($maxAge);
            $response->headers->set('Age', $maxAge - min($this->ttls));
        }
        $response->setMaxAge(0);
    }
}
PK��Z�J�z��*Symfony/Component/HttpKernel/UriSigner.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel;

/**
 * Signs URIs.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class UriSigner
{
    private $secret;

    /**
     * Constructor.
     *
     * @param string $secret A secret
     */
    public function __construct($secret)
    {
        $this->secret = $secret;
    }

    /**
     * Signs a URI.
     *
     * The given URI is signed by adding a _hash query string parameter
     * which value depends on the URI and the secret.
     *
     * @param string $uri A URI to sign
     *
     * @return string The signed URI
     */
    public function sign($uri)
    {
        return $uri.(false === (strpos($uri, '?')) ? '?' : '&').'_hash='.$this->computeHash($uri);
    }

    /**
     * Checks that a URI contains the correct hash.
     *
     * The _hash query string parameter must be the last one
     * (as it is generated that way by the sign() method, it should
     * never be a problem).
     *
     * @param string $uri A signed URI
     *
     * @return Boolean True if the URI is signed correctly, false otherwise
     */
    public function check($uri)
    {
        if (!preg_match('/^(.*)(?:\?|&)_hash=(.+?)$/', $uri, $matches)) {
            return false;
        }

        return $this->computeHash($matches[1]) === $matches[2];
    }

    private function computeHash($uri)
    {
        return urlencode(base64_encode(hash_hmac('sha256', $uri, $this->secret, true)));
    }
}
PK��Z��d��3Symfony/Component/HttpKernel/Config/FileLocator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Config;

use Symfony\Component\Config\FileLocator as BaseFileLocator;
use Symfony\Component\HttpKernel\KernelInterface;

/**
 * FileLocator uses the KernelInterface to locate resources in bundles.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FileLocator extends BaseFileLocator
{
    private $kernel;
    private $path;

    /**
     * Constructor.
     *
     * @param KernelInterface $kernel A KernelInterface instance
     * @param null|string     $path   The path the global resource directory
     * @param array           $paths  An array of paths where to look for resources
     */
    public function __construct(KernelInterface $kernel, $path = null, array $paths = array())
    {
        $this->kernel = $kernel;
        if (null !== $path) {
            $this->path = $path;
            $paths[] = $path;
        }

        parent::__construct($paths);
    }

    /**
     * {@inheritdoc}
     */
    public function locate($file, $currentPath = null, $first = true)
    {
        if ('@' === $file[0]) {
            return $this->kernel->locateResource($file, $this->path, $first);
        }

        return parent::locate($file, $currentPath, $first);
    }
}
PK��Z!���ll.Symfony/Component/HttpKernel/Bundle/Bundle.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Bundle;

use Symfony\Component\DependencyInjection\ContainerAware;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\Console\Application;
use Symfony\Component\Finder\Finder;
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;

/**
 * An implementation of BundleInterface that adds a few conventions
 * for DependencyInjection extensions and Console commands.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
abstract class Bundle extends ContainerAware implements BundleInterface
{
    protected $name;
    protected $extension;
    protected $path;

    /**
     * Boots the Bundle.
     */
    public function boot()
    {
    }

    /**
     * Shutdowns the Bundle.
     */
    public function shutdown()
    {
    }

    /**
     * Builds the bundle.
     *
     * It is only ever called once when the cache is empty.
     *
     * This method can be overridden to register compilation passes,
     * other extensions, ...
     *
     * @param ContainerBuilder $container A ContainerBuilder instance
     */
    public function build(ContainerBuilder $container)
    {
    }

    /**
     * Returns the bundle's container extension.
     *
     * @return ExtensionInterface|null The container extension
     *
     * @throws \LogicException
     *
     * @api
     */
    public function getContainerExtension()
    {
        if (null === $this->extension) {
            $basename = preg_replace('/Bundle$/', '', $this->getName());

            $class = $this->getNamespace().'\\DependencyInjection\\'.$basename.'Extension';
            if (class_exists($class)) {
                $extension = new $class();

                // check naming convention
                $expectedAlias = Container::underscore($basename);
                if ($expectedAlias != $extension->getAlias()) {
                    throw new \LogicException(sprintf(
                        'The extension alias for the default extension of a '.
                        'bundle must be the underscored version of the '.
                        'bundle name ("%s" instead of "%s")',
                        $expectedAlias, $extension->getAlias()
                    ));
                }

                $this->extension = $extension;
            } else {
                $this->extension = false;
            }
        }

        if ($this->extension) {
            return $this->extension;
        }
    }

    /**
     * Gets the Bundle namespace.
     *
     * @return string The Bundle namespace
     *
     * @api
     */
    public function getNamespace()
    {
        $class = get_class($this);

        return substr($class, 0, strrpos($class, '\\'));
    }

    /**
     * Gets the Bundle directory path.
     *
     * @return string The Bundle absolute path
     *
     * @api
     */
    public function getPath()
    {
        if (null === $this->path) {
            $reflected = new \ReflectionObject($this);
            $this->path = dirname($reflected->getFileName());
        }

        return $this->path;
    }

    /**
     * Returns the bundle parent name.
     *
     * @return string The Bundle parent name it overrides or null if no parent
     *
     * @api
     */
    public function getParent()
    {
        return null;
    }

    /**
     * Returns the bundle name (the class short name).
     *
     * @return string The Bundle name
     *
     * @api
     */
    final public function getName()
    {
        if (null !== $this->name) {
            return $this->name;
        }

        $name = get_class($this);
        $pos = strrpos($name, '\\');

        return $this->name = false === $pos ? $name : substr($name, $pos + 1);
    }

    /**
     * Finds and registers Commands.
     *
     * Override this method if your bundle commands do not follow the conventions:
     *
     * * Commands are in the 'Command' sub-directory
     * * Commands extend Symfony\Component\Console\Command\Command
     *
     * @param Application $application An Application instance
     */
    public function registerCommands(Application $application)
    {
        if (!is_dir($dir = $this->getPath().'/Command')) {
            return;
        }

        $finder = new Finder();
        $finder->files()->name('*Command.php')->in($dir);

        $prefix = $this->getNamespace().'\\Command';
        foreach ($finder as $file) {
            $ns = $prefix;
            if ($relativePath = $file->getRelativePath()) {
                $ns .= '\\'.strtr($relativePath, '/', '\\');
            }
            $class = $ns.'\\'.$file->getBasename('.php');
            if ($this->container) {
                $alias = 'console.command.'.strtolower(str_replace('\\', '_', $class));
                if ($this->container->has($alias)) {
                    continue;
                }
            }
            $r = new \ReflectionClass($class);
            if ($r->isSubclassOf('Symfony\\Component\\Console\\Command\\Command') && !$r->isAbstract() && !$r->getConstructor()->getNumberOfRequiredParameters()) {
                $application->add($r->newInstance());
            }
        }
    }
}
PK��Z�3�a��7Symfony/Component/HttpKernel/Bundle/BundleInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Bundle;

use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;

/**
 * BundleInterface.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface BundleInterface extends ContainerAwareInterface
{
    /**
     * Boots the Bundle.
     *
     * @api
     */
    public function boot();

    /**
     * Shutdowns the Bundle.
     *
     * @api
     */
    public function shutdown();

    /**
     * Builds the bundle.
     *
     * It is only ever called once when the cache is empty.
     *
     * @param ContainerBuilder $container A ContainerBuilder instance
     *
     * @api
     */
    public function build(ContainerBuilder $container);

    /**
     * Returns the container extension that should be implicitly loaded.
     *
     * @return ExtensionInterface|null The default extension or null if there is none
     *
     * @api
     */
    public function getContainerExtension();

    /**
     * Returns the bundle name that this bundle overrides.
     *
     * Despite its name, this method does not imply any parent/child relationship
     * between the bundles, just a way to extend and override an existing
     * bundle.
     *
     * @return string The Bundle name it overrides or null if no parent
     *
     * @api
     */
    public function getParent();

    /**
     * Returns the bundle name (the class short name).
     *
     * @return string The Bundle name
     *
     * @api
     */
    public function getName();

    /**
     * Gets the Bundle namespace.
     *
     * @return string The Bundle namespace
     *
     * @api
     */
    public function getNamespace();

    /**
     * Gets the Bundle directory path.
     *
     * The path should always be returned as a Unix path (with /).
     *
     * @return string The Bundle absolute path
     *
     * @api
     */
    public function getPath();
}
PK��ZB�Wzll@Symfony/Component/HttpKernel/Profiler/MongoDbProfilerStorage.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Profiler;

class MongoDbProfilerStorage implements ProfilerStorageInterface
{
    protected $dsn;
    protected $lifetime;
    private $mongo;

    /**
     * Constructor.
     *
     * @param string  $dsn      A data source name
     * @param string  $username Not used
     * @param string  $password Not used
     * @param integer $lifetime The lifetime to use for the purge
     */
    public function __construct($dsn, $username = '', $password = '', $lifetime = 86400)
    {
        $this->dsn = $dsn;
        $this->lifetime = (int) $lifetime;
    }

    /**
     * {@inheritdoc}
     */
    public function find($ip, $url, $limit, $method, $start = null, $end = null)
    {
        $cursor = $this->getMongo()->find($this->buildQuery($ip, $url, $method, $start, $end), array('_id', 'parent', 'ip', 'method', 'url', 'time'))->sort(array('time' => -1))->limit($limit);

        $tokens = array();
        foreach ($cursor as $profile) {
            $tokens[] = $this->getData($profile);
        }

        return $tokens;
    }

    /**
     * {@inheritdoc}
     */
    public function purge()
    {
        $this->getMongo()->remove(array());
    }

    /**
     * {@inheritdoc}
     */
    public function read($token)
    {
        $profile = $this->getMongo()->findOne(array('_id' => $token, 'data' => array('$exists' => true)));

        if (null !== $profile) {
            $profile = $this->createProfileFromData($this->getData($profile));
        }

        return $profile;
    }

    /**
     * {@inheritdoc}
     */
    public function write(Profile $profile)
    {
        $this->cleanup();

        $record = array(
            '_id' => $profile->getToken(),
            'parent' => $profile->getParentToken(),
            'data' => base64_encode(serialize($profile->getCollectors())),
            'ip' => $profile->getIp(),
            'method' => $profile->getMethod(),
            'url' => $profile->getUrl(),
            'time' => $profile->getTime()
        );

        $result = $this->getMongo()->update(array('_id' => $profile->getToken()), array_filter($record, function ($v) { return !empty($v); }), array('upsert' => true));

        return (boolean) (isset($result['ok']) ? $result['ok'] : $result);
    }

    /**
     * Internal convenience method that returns the instance of the MongoDB Collection
     *
     * @return \MongoCollection
     *
     * @throws \RuntimeException
     */
    protected function getMongo()
    {
        if (null !== $this->mongo) {
            return $this->mongo;
        }

        if (!$parsedDsn = $this->parseDsn($this->dsn)) {
            throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use MongoDB with an invalid dsn "%s". The expected format is "mongodb://[user:pass@]host/database/collection"', $this->dsn));
        }

        list($server, $database, $collection) = $parsedDsn;
        $mongoClass = version_compare(phpversion('mongo'), '1.3.0', '<') ? '\Mongo' : '\MongoClient';
        $mongo = new $mongoClass($server);

        return $this->mongo = $mongo->selectCollection($database, $collection);
    }

    /**
     * @param array $data
     *
     * @return Profile
     */
    protected function createProfileFromData(array $data)
    {
        $profile = $this->getProfile($data);

        if ($data['parent']) {
            $parent = $this->getMongo()->findOne(array('_id' => $data['parent'], 'data' => array('$exists' => true)));
            if ($parent) {
                $profile->setParent($this->getProfile($this->getData($parent)));
            }
        }

        $profile->setChildren($this->readChildren($data['token']));

        return $profile;
    }

    /**
     * @param string $token
     *
     * @return Profile[] An array of Profile instances
     */
    protected function readChildren($token)
    {
        $profiles = array();

        $cursor = $this->getMongo()->find(array('parent' => $token, 'data' => array('$exists' => true)));
        foreach ($cursor as $d) {
            $profiles[] = $this->getProfile($this->getData($d));
        }

        return $profiles;
    }

    protected function cleanup()
    {
        $this->getMongo()->remove(array('time' => array('$lt' => time() - $this->lifetime)));
    }

    /**
     * @param string $ip
     * @param string $url
     * @param string $method
     * @param int    $start
     * @param int    $end
     *
     * @return array
     */
    private function buildQuery($ip, $url, $method, $start, $end)
    {
        $query = array();

        if (!empty($ip)) {
            $query['ip'] = $ip;
        }

        if (!empty($url)) {
            $query['url'] = $url;
        }

        if (!empty($method)) {
            $query['method'] = $method;
        }

        if (!empty($start) || !empty($end)) {
            $query['time'] = array();
        }

        if (!empty($start)) {
            $query['time']['$gte'] = $start;
        }

        if (!empty($end)) {
            $query['time']['$lte'] = $end;
        }

        return $query;
    }

    /**
     * @param array $data
     *
     * @return array
     */
    private function getData(array $data)
    {
        return array(
            'token' => $data['_id'],
            'parent' => isset($data['parent']) ? $data['parent'] : null,
            'ip' => isset($data['ip']) ? $data['ip'] : null,
            'method' => isset($data['method']) ? $data['method'] : null,
            'url' => isset($data['url']) ? $data['url'] : null,
            'time' => isset($data['time']) ? $data['time'] : null,
            'data' => isset($data['data']) ? $data['data'] : null,
        );
    }

    /**
     * @param array $data
     *
     * @return Profile
     */
    private function getProfile(array $data)
    {
        $profile = new Profile($data['token']);
        $profile->setIp($data['ip']);
        $profile->setMethod($data['method']);
        $profile->setUrl($data['url']);
        $profile->setTime($data['time']);
        $profile->setCollectors(unserialize(base64_decode($data['data'])));

        return $profile;
    }

    /**
     * @param string $dsn
     *
     * @return null|array Array($server, $database, $collection)
     */
    private function parseDsn($dsn)
    {
        if (!preg_match('#^(mongodb://.*)/(.*)/(.*)$#', $dsn, $matches)) {
            return;
        }

        $server = $matches[1];
        $database = $matches[2];
        $collection = $matches[3];
        preg_match('#^mongodb://(([^:]+):?(.*)(?=@))?@?([^/]*)(.*)$#', $server, $matchesServer);

        if ('' == $matchesServer[5] && '' != $matches[2]) {
            $server .= '/'.$matches[2];
        }

        return array($server, $database, $collection);
    }
}
PK��Z���

2Symfony/Component/HttpKernel/Profiler/Profiler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Profiler;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface;
use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface;
use Psr\Log\LoggerInterface;

/**
 * Profiler.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Profiler
{
    /**
     * @var ProfilerStorageInterface
     */
    private $storage;

    /**
     * @var DataCollectorInterface[]
     */
    private $collectors = array();

    /**
     * @var LoggerInterface
     */
    private $logger;

    /**
     * @var Boolean
     */
    private $enabled = true;

    /**
     * Constructor.
     *
     * @param ProfilerStorageInterface $storage A ProfilerStorageInterface instance
     * @param LoggerInterface          $logger  A LoggerInterface instance
     */
    public function __construct(ProfilerStorageInterface $storage, LoggerInterface $logger = null)
    {
        $this->storage = $storage;
        $this->logger = $logger;
    }

    /**
     * Disables the profiler.
     */
    public function disable()
    {
        $this->enabled = false;
    }

    /**
     * Enables the profiler.
     */
    public function enable()
    {
        $this->enabled = true;
    }

    /**
     * Loads the Profile for the given Response.
     *
     * @param Response $response A Response instance
     *
     * @return Profile A Profile instance
     */
    public function loadProfileFromResponse(Response $response)
    {
        if (!$token = $response->headers->get('X-Debug-Token')) {
            return false;
        }

        return $this->loadProfile($token);
    }

    /**
     * Loads the Profile for the given token.
     *
     * @param string $token A token
     *
     * @return Profile A Profile instance
     */
    public function loadProfile($token)
    {
        return $this->storage->read($token);
    }

    /**
     * Saves a Profile.
     *
     * @param Profile $profile A Profile instance
     *
     * @return Boolean
     */
    public function saveProfile(Profile $profile)
    {
        // late collect
        foreach ($profile->getCollectors() as $collector) {
            if ($collector instanceof LateDataCollectorInterface) {
                $collector->lateCollect();
            }
        }

        if (!($ret = $this->storage->write($profile)) && null !== $this->logger) {
            $this->logger->warning('Unable to store the profiler information.');
        }

        return $ret;
    }

    /**
     * Purges all data from the storage.
     */
    public function purge()
    {
        $this->storage->purge();
    }

    /**
     * Exports the current profiler data.
     *
     * @param Profile $profile A Profile instance
     *
     * @return string The exported data
     */
    public function export(Profile $profile)
    {
        return base64_encode(serialize($profile));
    }

    /**
     * Imports data into the profiler storage.
     *
     * @param string $data A data string as exported by the export() method
     *
     * @return Profile A Profile instance
     */
    public function import($data)
    {
        $profile = unserialize(base64_decode($data));

        if ($this->storage->read($profile->getToken())) {
            return false;
        }

        $this->saveProfile($profile);

        return $profile;
    }

    /**
     * Finds profiler tokens for the given criteria.
     *
     * @param string $ip     The IP
     * @param string $url    The URL
     * @param string $limit  The maximum number of tokens to return
     * @param string $method The request method
     * @param string $start  The start date to search from
     * @param string $end    The end date to search to
     *
     * @return array An array of tokens
     *
     * @see http://fr2.php.net/manual/en/datetime.formats.php for the supported date/time formats
     */
    public function find($ip, $url, $limit, $method, $start, $end)
    {
        if ('' != $start && null !== $start) {
            $start = new \DateTime($start);
            $start = $start->getTimestamp();
        } else {
            $start = null;
        }

        if ('' != $end && null !== $end) {
            $end = new \DateTime($end);
            $end = $end->getTimestamp();
        } else {
            $end = null;
        }

        return $this->storage->find($ip, $url, $limit, $method, $start, $end);
    }

    /**
     * Collects data for the given Response.
     *
     * @param Request    $request   A Request instance
     * @param Response   $response  A Response instance
     * @param \Exception $exception An exception instance if the request threw one
     *
     * @return Profile|null A Profile instance or null if the profiler is disabled
     */
    public function collect(Request $request, Response $response, \Exception $exception = null)
    {
        if (false === $this->enabled) {
            return;
        }

        $profile = new Profile(substr(hash('sha256', uniqid(mt_rand(), true)), 0, 6));
        $profile->setTime(time());
        $profile->setUrl($request->getUri());
        $profile->setIp($request->getClientIp());
        $profile->setMethod($request->getMethod());

        $response->headers->set('X-Debug-Token', $profile->getToken());

        foreach ($this->collectors as $collector) {
            $collector->collect($request, $response, $exception);

            // we need to clone for sub-requests
            $profile->addCollector(clone $collector);
        }

        return $profile;
    }

    /**
     * Gets the Collectors associated with this profiler.
     *
     * @return array An array of collectors
     */
    public function all()
    {
        return $this->collectors;
    }

    /**
     * Sets the Collectors associated with this profiler.
     *
     * @param DataCollectorInterface[] $collectors An array of collectors
     */
    public function set(array $collectors = array())
    {
        $this->collectors = array();
        foreach ($collectors as $collector) {
            $this->add($collector);
        }
    }

    /**
     * Adds a Collector.
     *
     * @param DataCollectorInterface $collector A DataCollectorInterface instance
     */
    public function add(DataCollectorInterface $collector)
    {
        $this->collectors[$collector->getName()] = $collector;
    }

    /**
     * Returns true if a Collector for the given name exists.
     *
     * @param string $name A collector name
     *
     * @return Boolean
     */
    public function has($name)
    {
        return isset($this->collectors[$name]);
    }

    /**
     * Gets a Collector by name.
     *
     * @param string $name A collector name
     *
     * @return DataCollectorInterface A DataCollectorInterface instance
     *
     * @throws \InvalidArgumentException if the collector does not exist
     */
    public function get($name)
    {
        if (!isset($this->collectors[$name])) {
            throw new \InvalidArgumentException(sprintf('Collector "%s" does not exist.', $name));
        }

        return $this->collectors[$name];
    }
}
PK��Z$���	�	BSymfony/Component/HttpKernel/Profiler/MemcachedProfilerStorage.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Profiler;

/**
 * Memcached Profiler Storage
 *
 * @author Andrej Hudec <pulzarraider@gmail.com>
 */
class MemcachedProfilerStorage extends BaseMemcacheProfilerStorage
{
    /**
     * @var \Memcached
     */
    private $memcached;

    /**
     * Internal convenience method that returns the instance of the Memcached
     *
     * @return \Memcached
     *
     * @throws \RuntimeException
     */
    protected function getMemcached()
    {
        if (null === $this->memcached) {
            if (!preg_match('#^memcached://(?(?=\[.*\])\[(.*)\]|(.*)):(.*)$#', $this->dsn, $matches)) {
                throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use Memcached with an invalid dsn "%s". The expected format is "memcached://[host]:port".', $this->dsn));
            }

            $host = $matches[1] ?: $matches[2];
            $port = $matches[3];

            $memcached = new \Memcached();

            // disable compression to allow appending
            $memcached->setOption(\Memcached::OPT_COMPRESSION, false);

            $memcached->addServer($host, $port);

            $this->memcached = $memcached;
        }

        return $this->memcached;
    }

    /**
     * Set instance of the Memcached
     *
     * @param \Memcached $memcached
     */
    public function setMemcached($memcached)
    {
        $this->memcached = $memcached;
    }

    /**
     * {@inheritdoc}
     */
    protected function getValue($key)
    {
        return $this->getMemcached()->get($key);
    }

    /**
     * {@inheritdoc}
     */
    protected function setValue($key, $value, $expiration = 0)
    {
        return $this->getMemcached()->set($key, $value, time() + $expiration);
    }

    /**
     * {@inheritdoc}
     */
    protected function delete($key)
    {
        return $this->getMemcached()->delete($key);
    }

    /**
     * {@inheritdoc}
     */
    protected function appendValue($key, $value, $expiration = 0)
    {
        $memcached = $this->getMemcached();

        if (!$result = $memcached->append($key, $value)) {
            return $memcached->set($key, $value, $expiration);
        }

        return $result;
    }
}
PK��Z�rLU��BSymfony/Component/HttpKernel/Profiler/ProfilerStorageInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Profiler;

/**
 * ProfilerStorageInterface.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface ProfilerStorageInterface
{
    /**
     * Finds profiler tokens for the given criteria.
     *
     * @param string   $ip     The IP
     * @param string   $url    The URL
     * @param string   $limit  The maximum number of tokens to return
     * @param string   $method The request method
     * @param int|null $start  The start date to search from
     * @param int|null $end    The end date to search to
     *
     * @return array An array of tokens
     */
    public function find($ip, $url, $limit, $method, $start = null, $end = null);

    /**
     * Reads data associated with the given token.
     *
     * The method returns false if the token does not exist in the storage.
     *
     * @param string $token A token
     *
     * @return Profile The profile associated with token
     */
    public function read($token);

    /**
     * Saves a Profile.
     *
     * @param Profile $profile A Profile instance
     *
     * @return Boolean Write operation successful
     */
    public function write(Profile $profile);

    /**
     * Purges all data from the database.
     */
    public function purge();
}
PK��ZT��sX	X	>Symfony/Component/HttpKernel/Profiler/MysqlProfilerStorage.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Profiler;

/**
 * A ProfilerStorage for Mysql
 *
 * @author Jan Schumann <js@schumann-it.com>
 */
class MysqlProfilerStorage extends PdoProfilerStorage
{
    /**
     * {@inheritdoc}
     */
    protected function initDb()
    {
        if (null === $this->db) {
            if (0 !== strpos($this->dsn, 'mysql')) {
                throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use Mysql with an invalid dsn "%s". The expected format is "mysql:dbname=database_name;host=host_name".', $this->dsn));
            }

            if (!class_exists('PDO') || !in_array('mysql', \PDO::getAvailableDrivers(), true)) {
                throw new \RuntimeException('You need to enable PDO_Mysql extension for the profiler to run properly.');
            }

            $db = new \PDO($this->dsn, $this->username, $this->password);
            $db->exec('CREATE TABLE IF NOT EXISTS sf_profiler_data (token VARCHAR(255) PRIMARY KEY, data LONGTEXT, ip VARCHAR(64), method VARCHAR(6), url VARCHAR(255), time INTEGER UNSIGNED, parent VARCHAR(255), created_at INTEGER UNSIGNED, KEY (created_at), KEY (ip), KEY (method), KEY (url), KEY (parent))');

            $this->db = $db;
        }

        return $this->db;
    }

    /**
     * {@inheritdoc}
     */
    protected function buildCriteria($ip, $url, $start, $end, $limit, $method)
    {
        $criteria = array();
        $args = array();

        if ($ip = preg_replace('/[^\d\.]/', '', $ip)) {
            $criteria[] = 'ip LIKE :ip';
            $args[':ip'] = '%'.$ip.'%';
        }

        if ($url) {
            $criteria[] = 'url LIKE :url';
            $args[':url'] = '%'.addcslashes($url, '%_\\').'%';
        }

        if ($method) {
            $criteria[] = 'method = :method';
            $args[':method'] = $method;
        }

        if (!empty($start)) {
            $criteria[] = 'time >= :start';
            $args[':start'] = $start;
        }

        if (!empty($end)) {
            $criteria[] = 'time <= :end';
            $args[':end'] = $end;
        }

        return array($criteria, $args);
    }
}
PK��ZN����'�'>Symfony/Component/HttpKernel/Profiler/RedisProfilerStorage.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Profiler;

/**
 * RedisProfilerStorage stores profiling information in Redis.
 *
 * @author Andrej Hudec <pulzarraider@gmail.com>
 * @author Stephane PY <py.stephane1@gmail.com>
 */
class RedisProfilerStorage implements ProfilerStorageInterface
{
    const TOKEN_PREFIX = 'sf_profiler_';

    const REDIS_OPT_SERIALIZER = 1;
    const REDIS_OPT_PREFIX = 2;
    const REDIS_SERIALIZER_NONE = 0;
    const REDIS_SERIALIZER_PHP = 1;

    protected $dsn;
    protected $lifetime;

    /**
     * @var \Redis
     */
    private $redis;

    /**
     * Constructor.
     *
     * @param string $dsn      A data source name
     * @param string $username Not used
     * @param string $password Not used
     * @param int    $lifetime The lifetime to use for the purge
     */
    public function __construct($dsn, $username = '', $password = '', $lifetime = 86400)
    {
        $this->dsn = $dsn;
        $this->lifetime = (int) $lifetime;
    }

    /**
     * {@inheritdoc}
     */
    public function find($ip, $url, $limit, $method, $start = null, $end = null)
    {
        $indexName = $this->getIndexName();

        if (!$indexContent = $this->getValue($indexName, self::REDIS_SERIALIZER_NONE)) {
            return array();
        }

        $profileList = array_reverse(explode("\n", $indexContent));
        $result = array();

        foreach ($profileList as $item) {
            if ($limit === 0) {
                break;
            }

            if ($item == '') {
                continue;
            }

            list($itemToken, $itemIp, $itemMethod, $itemUrl, $itemTime, $itemParent) = explode("\t", $item, 6);

            $itemTime = (int) $itemTime;

            if ($ip && false === strpos($itemIp, $ip) || $url && false === strpos($itemUrl, $url) || $method && false === strpos($itemMethod, $method)) {
                continue;
            }

            if (!empty($start) && $itemTime < $start) {
                continue;
            }

            if (!empty($end) && $itemTime > $end) {
                continue;
            }

            $result[] = array(
                'token'  => $itemToken,
                'ip'     => $itemIp,
                'method' => $itemMethod,
                'url'    => $itemUrl,
                'time'   => $itemTime,
                'parent' => $itemParent,
            );
            --$limit;
        }

        return $result;
    }

    /**
     * {@inheritdoc}
     */
    public function purge()
    {
        // delete only items from index
        $indexName = $this->getIndexName();

        $indexContent = $this->getValue($indexName, self::REDIS_SERIALIZER_NONE);

        if (!$indexContent) {
            return false;
        }

        $profileList = explode("\n", $indexContent);

        $result = array();

        foreach ($profileList as $item) {
            if ($item == '') {
                continue;
            }

            if (false !== $pos = strpos($item, "\t")) {
                $result[] = $this->getItemName(substr($item, 0, $pos));
            }
        }

        $result[] = $indexName;

        return $this->delete($result);
    }

    /**
     * {@inheritdoc}
     */
    public function read($token)
    {
        if (empty($token)) {
            return false;
        }

        $profile = $this->getValue($this->getItemName($token), self::REDIS_SERIALIZER_PHP);

        if (false !== $profile) {
            $profile = $this->createProfileFromData($token, $profile);
        }

        return $profile;
    }

    /**
     * {@inheritdoc}
     */
    public function write(Profile $profile)
    {
        $data = array(
            'token'    => $profile->getToken(),
            'parent'   => $profile->getParentToken(),
            'children' => array_map(function ($p) { return $p->getToken(); }, $profile->getChildren()),
            'data'     => $profile->getCollectors(),
            'ip'       => $profile->getIp(),
            'method'   => $profile->getMethod(),
            'url'      => $profile->getUrl(),
            'time'     => $profile->getTime(),
        );

        $profileIndexed = false !== $this->getValue($this->getItemName($profile->getToken()));

        if ($this->setValue($this->getItemName($profile->getToken()), $data, $this->lifetime, self::REDIS_SERIALIZER_PHP)) {

            if (!$profileIndexed) {
                // Add to index
                $indexName = $this->getIndexName();

                $indexRow = implode("\t", array(
                    $profile->getToken(),
                    $profile->getIp(),
                    $profile->getMethod(),
                    $profile->getUrl(),
                    $profile->getTime(),
                    $profile->getParentToken(),
                ))."\n";

                return $this->appendValue($indexName, $indexRow, $this->lifetime);
            }

            return true;
        }

        return false;
    }

    /**
     * Internal convenience method that returns the instance of Redis.
     *
     * @return \Redis
     *
     * @throws \RuntimeException
     */
    protected function getRedis()
    {
        if (null === $this->redis) {
            $data = parse_url($this->dsn);

            if (false === $data || !isset($data['scheme']) || $data['scheme'] !== 'redis' || !isset($data['host']) || !isset($data['port'])) {
                throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use Redis with an invalid dsn "%s". The minimal expected format is "redis://[host]:port".', $this->dsn));
            }

            if (!extension_loaded('redis')) {
                throw new \RuntimeException('RedisProfilerStorage requires that the redis extension is loaded.');
            }

            $redis = new \Redis();
            $redis->connect($data['host'], $data['port']);

            if (isset($data['path'])) {
                $redis->select(substr($data['path'], 1));
            }

            if (isset($data['pass'])) {
                $redis->auth($data['pass']);
            }

            $redis->setOption(self::REDIS_OPT_PREFIX, self::TOKEN_PREFIX);

            $this->redis = $redis;
        }

        return $this->redis;
    }

    /**
     * Set instance of the Redis
     *
     * @param \Redis $redis
     */
    public function setRedis($redis)
    {
        $this->redis = $redis;
    }

    private function createProfileFromData($token, $data, $parent = null)
    {
        $profile = new Profile($token);
        $profile->setIp($data['ip']);
        $profile->setMethod($data['method']);
        $profile->setUrl($data['url']);
        $profile->setTime($data['time']);
        $profile->setCollectors($data['data']);

        if (!$parent && $data['parent']) {
            $parent = $this->read($data['parent']);
        }

        if ($parent) {
            $profile->setParent($parent);
        }

        foreach ($data['children'] as $token) {
            if (!$token) {
                continue;
            }

            if (!$childProfileData = $this->getValue($this->getItemName($token), self::REDIS_SERIALIZER_PHP)) {
                continue;
            }

            $profile->addChild($this->createProfileFromData($token, $childProfileData, $profile));
        }

        return $profile;
    }

    /**
     * Gets the item name.
     *
     * @param string $token
     *
     * @return string
     */
    private function getItemName($token)
    {
        $name = $token;

        if ($this->isItemNameValid($name)) {
            return $name;
        }

        return false;
    }

    /**
     * Gets the name of the index.
     *
     * @return string
     */
    private function getIndexName()
    {
        $name = 'index';

        if ($this->isItemNameValid($name)) {
            return $name;
        }

        return false;
    }

    private function isItemNameValid($name)
    {
        $length = strlen($name);

        if ($length > 2147483648) {
            throw new \RuntimeException(sprintf('The Redis item key "%s" is too long (%s bytes). Allowed maximum size is 2^31 bytes.', $name, $length));
        }

        return true;
    }

    /**
     * Retrieves an item from the Redis server.
     *
     * @param string $key
     * @param int    $serializer
     *
     * @return mixed
     */
    private function getValue($key, $serializer = self::REDIS_SERIALIZER_NONE)
    {
        $redis = $this->getRedis();
        $redis->setOption(self::REDIS_OPT_SERIALIZER, $serializer);

        return $redis->get($key);
    }

    /**
     * Stores an item on the Redis server under the specified key.
     *
     * @param string $key
     * @param mixed  $value
     * @param int    $expiration
     * @param int    $serializer
     *
     * @return Boolean
     */
    private function setValue($key, $value, $expiration = 0, $serializer = self::REDIS_SERIALIZER_NONE)
    {
        $redis = $this->getRedis();
        $redis->setOption(self::REDIS_OPT_SERIALIZER, $serializer);

        return $redis->setex($key, $expiration, $value);
    }

    /**
     * Appends data to an existing item on the Redis server.
     *
     * @param string $key
     * @param string $value
     * @param int    $expiration
     *
     * @return Boolean
     */
    private function appendValue($key, $value, $expiration = 0)
    {
        $redis = $this->getRedis();
        $redis->setOption(self::REDIS_OPT_SERIALIZER, self::REDIS_SERIALIZER_NONE);

        if ($redis->exists($key)) {
            $redis->append($key, $value);

            return $redis->setTimeout($key, $expiration);
        }

        return $redis->setex($key, $expiration, $value);
    }

    /**
     * Removes the specified keys.
     *
     * @param array $keys
     *
     * @return Boolean
     */
    private function delete(array $keys)
    {
        return (bool) $this->getRedis()->delete($keys);
    }
}
PK��Z�����<Symfony/Component/HttpKernel/Profiler/PdoProfilerStorage.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Profiler;

/**
 * Base PDO storage for profiling information in a PDO database.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Jan Schumann <js@schumann-it.com>
 */
abstract class PdoProfilerStorage implements ProfilerStorageInterface
{
    protected $dsn;
    protected $username;
    protected $password;
    protected $lifetime;
    protected $db;

    /**
     * Constructor.
     *
     * @param string  $dsn      A data source name
     * @param string  $username The username for the database
     * @param string  $password The password for the database
     * @param integer $lifetime The lifetime to use for the purge
     */
    public function __construct($dsn, $username = '', $password = '', $lifetime = 86400)
    {
        $this->dsn = $dsn;
        $this->username = $username;
        $this->password = $password;
        $this->lifetime = (int) $lifetime;
    }

    /**
     * {@inheritdoc}
     */
    public function find($ip, $url, $limit, $method, $start = null, $end = null)
    {
        if (null === $start) {
            $start = 0;
        }

        if (null === $end) {
            $end = time();
        }

        list($criteria, $args) = $this->buildCriteria($ip, $url, $start, $end, $limit, $method);

        $criteria = $criteria ? 'WHERE '.implode(' AND ', $criteria) : '';

        $db = $this->initDb();
        $tokens = $this->fetch($db, 'SELECT token, ip, method, url, time, parent FROM sf_profiler_data '.$criteria.' ORDER BY time DESC LIMIT '.((integer) $limit), $args);
        $this->close($db);

        return $tokens;
    }

    /**
     * {@inheritdoc}
     */
    public function read($token)
    {
        $db = $this->initDb();
        $args = array(':token' => $token);
        $data = $this->fetch($db, 'SELECT data, parent, ip, method, url, time FROM sf_profiler_data WHERE token = :token LIMIT 1', $args);
        $this->close($db);
        if (isset($data[0]['data'])) {
            return $this->createProfileFromData($token, $data[0]);
        }

        return null;
    }

    /**
     * {@inheritdoc}
     */
    public function write(Profile $profile)
    {
        $db = $this->initDb();
        $args = array(
            ':token'      => $profile->getToken(),
            ':parent'     => $profile->getParentToken(),
            ':data'       => base64_encode(serialize($profile->getCollectors())),
            ':ip'         => $profile->getIp(),
            ':method'     => $profile->getMethod(),
            ':url'        => $profile->getUrl(),
            ':time'       => $profile->getTime(),
            ':created_at' => time(),
        );

        try {
            if ($this->has($profile->getToken())) {
                $this->exec($db, 'UPDATE sf_profiler_data SET parent = :parent, data = :data, ip = :ip, method = :method, url = :url, time = :time, created_at = :created_at WHERE token = :token', $args);
            } else {
                $this->exec($db, 'INSERT INTO sf_profiler_data (token, parent, data, ip, method, url, time, created_at) VALUES (:token, :parent, :data, :ip, :method, :url, :time, :created_at)', $args);
            }
            $this->cleanup();
            $status = true;
        } catch (\Exception $e) {
            $status = false;
        }

        $this->close($db);

        return $status;
    }

    /**
     * {@inheritdoc}
     */
    public function purge()
    {
        $db = $this->initDb();
        $this->exec($db, 'DELETE FROM sf_profiler_data');
        $this->close($db);
    }

    /**
     * Build SQL criteria to fetch records by ip and url
     *
     * @param string $ip     The IP
     * @param string $url    The URL
     * @param string $start  The start period to search from
     * @param string $end    The end period to search to
     * @param string $limit  The maximum number of tokens to return
     * @param string $method The request method
     *
     * @return array An array with (criteria, args)
     */
    abstract protected function buildCriteria($ip, $url, $start, $end, $limit, $method);

    /**
     * Initializes the database
     *
     * @throws \RuntimeException When the requested database driver is not installed
     */
    abstract protected function initDb();

    protected function cleanup()
    {
        $db = $this->initDb();
        $this->exec($db, 'DELETE FROM sf_profiler_data WHERE created_at < :time', array(':time' => time() - $this->lifetime));
        $this->close($db);
    }

    protected function exec($db, $query, array $args = array())
    {
        $stmt = $this->prepareStatement($db, $query);

        foreach ($args as $arg => $val) {
            $stmt->bindValue($arg, $val, is_int($val) ? \PDO::PARAM_INT : \PDO::PARAM_STR);
        }
        $success = $stmt->execute();
        if (!$success) {
            throw new \RuntimeException(sprintf('Error executing query "%s"', $query));
        }
    }

    protected function prepareStatement($db, $query)
    {
        try {
            $stmt = $db->prepare($query);
        } catch (\Exception $e) {
            $stmt = false;
        }

        if (false === $stmt) {
            throw new \RuntimeException('The database cannot successfully prepare the statement');
        }

        return $stmt;
    }

    protected function fetch($db, $query, array $args = array())
    {
        $stmt = $this->prepareStatement($db, $query);

        foreach ($args as $arg => $val) {
            $stmt->bindValue($arg, $val, is_int($val) ? \PDO::PARAM_INT : \PDO::PARAM_STR);
        }
        $stmt->execute();
        $return = $stmt->fetchAll(\PDO::FETCH_ASSOC);

        return $return;
    }

    protected function close($db)
    {
    }

    protected function createProfileFromData($token, $data, $parent = null)
    {
        $profile = new Profile($token);
        $profile->setIp($data['ip']);
        $profile->setMethod($data['method']);
        $profile->setUrl($data['url']);
        $profile->setTime($data['time']);
        $profile->setCollectors(unserialize(base64_decode($data['data'])));

        if (!$parent && !empty($data['parent'])) {
            $parent = $this->read($data['parent']);
        }

        if ($parent) {
            $profile->setParent($parent);
        }

        $profile->setChildren($this->readChildren($token, $profile));

        return $profile;
    }

    /**
     * Reads the child profiles for the given token.
     *
     * @param string $token  The parent token
     * @param string $parent The parent instance
     *
     * @return Profile[] An array of Profile instance
     */
    protected function readChildren($token, $parent)
    {
        $db = $this->initDb();
        $data = $this->fetch($db, 'SELECT token, data, ip, method, url, time FROM sf_profiler_data WHERE parent = :token', array(':token' => $token));
        $this->close($db);

        if (!$data) {
            return array();
        }

        $profiles = array();
        foreach ($data as $d) {
            $profiles[] = $this->createProfileFromData($d['token'], $d, $parent);
        }

        return $profiles;
    }

    /**
     * Returns whether data for the given token already exists in storage.
     *
     * @param string $token The profile token
     *
     * @return string
     */
    protected function has($token)
    {
        $db = $this->initDb();
        $tokenExists = $this->fetch($db, 'SELECT 1 FROM sf_profiler_data WHERE token = :token LIMIT 1', array(':token' => $token));
        $this->close($db);

        return !empty($tokenExists);
    }
}
PK��ZiY~2
2
ASymfony/Component/HttpKernel/Profiler/MemcacheProfilerStorage.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Profiler;

/**
 * Memcache Profiler Storage
 *
 * @author Andrej Hudec <pulzarraider@gmail.com>
 */
class MemcacheProfilerStorage extends BaseMemcacheProfilerStorage
{
    /**
     * @var \Memcache
     */
    private $memcache;

    /**
     * Internal convenience method that returns the instance of the Memcache
     *
     * @return \Memcache
     *
     * @throws \RuntimeException
     */
    protected function getMemcache()
    {
        if (null === $this->memcache) {
            if (!preg_match('#^memcache://(?(?=\[.*\])\[(.*)\]|(.*)):(.*)$#', $this->dsn, $matches)) {
                throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use Memcache with an invalid dsn "%s". The expected format is "memcache://[host]:port".', $this->dsn));
            }

            $host = $matches[1] ?: $matches[2];
            $port = $matches[3];

            $memcache = new \Memcache();
            $memcache->addServer($host, $port);

            $this->memcache = $memcache;
        }

        return $this->memcache;
    }

    /**
     * Set instance of the Memcache
     *
     * @param \Memcache $memcache
     */
    public function setMemcache($memcache)
    {
        $this->memcache = $memcache;
    }

    /**
     * {@inheritdoc}
     */
    protected function getValue($key)
    {
        return $this->getMemcache()->get($key);
    }

    /**
     * {@inheritdoc}
     */
    protected function setValue($key, $value, $expiration = 0)
    {
        return $this->getMemcache()->set($key, $value, false, time() + $expiration);
    }

    /**
     * {@inheritdoc}
     */
    protected function delete($key)
    {
        return $this->getMemcache()->delete($key);
    }

    /**
     * {@inheritdoc}
     */
    protected function appendValue($key, $value, $expiration = 0)
    {
        $memcache = $this->getMemcache();

        if (method_exists($memcache, 'append')) {

            // Memcache v3.0
            if (!$result = $memcache->append($key, $value, false, $expiration)) {
                return $memcache->set($key, $value, false, $expiration);
            }

            return $result;
        }

        // simulate append in Memcache <3.0
        $content = $memcache->get($key);

        return $memcache->set($key, $content.$value, false, $expiration);
    }
}
PK��Z� ��1Symfony/Component/HttpKernel/Profiler/Profile.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Profiler;

use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface;

/**
 * Profile.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Profile
{
    private $token;

    /**
     * @var DataCollectorInterface[]
     */
    private $collectors = array();

    private $ip;
    private $method;
    private $url;
    private $time;

    /**
     * @var Profile
     */
    private $parent;

    /**
     * @var Profile[]
     */
    private $children = array();

    /**
     * Constructor.
     *
     * @param string $token The token
     */
    public function __construct($token)
    {
        $this->token = $token;
    }

    /**
     * Sets the token.
     *
     * @param string $token The token
     */
    public function setToken($token)
    {
        $this->token = $token;
    }

    /**
     * Gets the token.
     *
     * @return string The token
     */
    public function getToken()
    {
        return $this->token;
    }

    /**
     * Sets the parent token
     *
     * @param Profile $parent The parent Profile
     */
    public function setParent(Profile $parent)
    {
        $this->parent = $parent;
    }

    /**
     * Returns the parent profile.
     *
     * @return Profile The parent profile
     */
    public function getParent()
    {
        return $this->parent;
    }

    /**
     * Returns the parent token.
     *
     * @return null|string The parent token
     */
    public function getParentToken()
    {
        return $this->parent ? $this->parent->getToken() : null;
    }

    /**
     * Returns the IP.
     *
     * @return string The IP
     */
    public function getIp()
    {
        return $this->ip;
    }

    /**
     * Sets the IP.
     *
     * @param string $ip
     */
    public function setIp($ip)
    {
        $this->ip = $ip;
    }

    /**
     * Returns the request method.
     *
     * @return string The request method
     */
    public function getMethod()
    {
        return $this->method;
    }

    public function setMethod($method)
    {
        $this->method = $method;
    }

    /**
     * Returns the URL.
     *
     * @return string The URL
     */
    public function getUrl()
    {
        return $this->url;
    }

    public function setUrl($url)
    {
        $this->url = $url;
    }

    /**
     * Returns the time.
     *
     * @return string The time
     */
    public function getTime()
    {
        if (null === $this->time) {
            return 0;
        }

        return $this->time;
    }

    public function setTime($time)
    {
        $this->time = $time;
    }

    /**
     * Finds children profilers.
     *
     * @return Profile[] An array of Profile
     */
    public function getChildren()
    {
        return $this->children;
    }

    /**
     * Sets children profiler.
     *
     * @param Profile[] $children An array of Profile
     */
    public function setChildren(array $children)
    {
        $this->children = array();
        foreach ($children as $child) {
            $this->addChild($child);
        }
    }

    /**
     * Adds the child token
     *
     * @param Profile $child The child Profile
     */
    public function addChild(Profile $child)
    {
        $this->children[] = $child;
        $child->setParent($this);
    }

    /**
     * Gets a Collector by name.
     *
     * @param string $name A collector name
     *
     * @return DataCollectorInterface A DataCollectorInterface instance
     *
     * @throws \InvalidArgumentException if the collector does not exist
     */
    public function getCollector($name)
    {
        if (!isset($this->collectors[$name])) {
            throw new \InvalidArgumentException(sprintf('Collector "%s" does not exist.', $name));
        }

        return $this->collectors[$name];
    }

    /**
     * Gets the Collectors associated with this profile.
     *
     * @return DataCollectorInterface[]
     */
    public function getCollectors()
    {
        return $this->collectors;
    }

    /**
     * Sets the Collectors associated with this profile.
     *
     * @param DataCollectorInterface[] $collectors
     */
    public function setCollectors(array $collectors)
    {
        $this->collectors = array();
        foreach ($collectors as $collector) {
            $this->addCollector($collector);
        }
    }

    /**
     * Adds a Collector.
     *
     * @param DataCollectorInterface $collector A DataCollectorInterface instance
     */
    public function addCollector(DataCollectorInterface $collector)
    {
        $this->collectors[$collector->getName()] = $collector;
    }

    /**
     * Returns true if a Collector for the given name exists.
     *
     * @param string $name A collector name
     *
     * @return Boolean
     */
    public function hasCollector($name)
    {
        return isset($this->collectors[$name]);
    }

    public function __sleep()
    {
        return array('token', 'parent', 'children', 'collectors', 'ip', 'method', 'url', 'time');
    }
}
PK��Z�t��ESymfony/Component/HttpKernel/Profiler/BaseMemcacheProfilerStorage.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Profiler;

/**
 * Base Memcache storage for profiling information in a Memcache.
 *
 * @author Andrej Hudec <pulzarraider@gmail.com>
 */
abstract class BaseMemcacheProfilerStorage implements ProfilerStorageInterface
{
    const TOKEN_PREFIX = 'sf_profiler_';

    protected $dsn;
    protected $lifetime;

    /**
     * Constructor.
     *
     * @param string $dsn      A data source name
     * @param string $username
     * @param string $password
     * @param int    $lifetime The lifetime to use for the purge
     */
    public function __construct($dsn, $username = '', $password = '', $lifetime = 86400)
    {
        $this->dsn = $dsn;
        $this->lifetime = (int) $lifetime;
    }

    /**
     * {@inheritdoc}
     */
    public function find($ip, $url, $limit, $method, $start = null, $end = null)
    {
        $indexName = $this->getIndexName();

        $indexContent = $this->getValue($indexName);
        if (!$indexContent) {
            return array();
        }

        $profileList = explode("\n", $indexContent);
        $result = array();

        foreach ($profileList as $item) {

            if ($limit === 0) {
                break;
            }

            if ($item=='') {
                continue;
            }

            list($itemToken, $itemIp, $itemMethod, $itemUrl, $itemTime, $itemParent) = explode("\t", $item, 6);

            $itemTime = (int) $itemTime;

            if ($ip && false === strpos($itemIp, $ip) || $url && false === strpos($itemUrl, $url) || $method && false === strpos($itemMethod, $method)) {
                continue;
            }

            if (!empty($start) && $itemTime < $start) {
                continue;
            }

            if (!empty($end) && $itemTime > $end) {
                continue;
            }

            $result[$itemToken]  = array(
                'token'  => $itemToken,
                'ip'     => $itemIp,
                'method' => $itemMethod,
                'url'    => $itemUrl,
                'time'   => $itemTime,
                'parent' => $itemParent,
            );
            --$limit;
        }

        usort($result, function ($a, $b) {
            if ($a['time'] === $b['time']) {
                return 0;
            }

            return $a['time'] > $b['time'] ? -1 : 1;
        });

        return $result;
    }

    /**
     * {@inheritdoc}
     */
    public function purge()
    {
        // delete only items from index
        $indexName = $this->getIndexName();

        $indexContent = $this->getValue($indexName);

        if (!$indexContent) {
            return false;
        }

        $profileList = explode("\n", $indexContent);

        foreach ($profileList as $item) {
            if ($item == '') {
                continue;
            }

            if (false !== $pos = strpos($item, "\t")) {
                $this->delete($this->getItemName(substr($item, 0, $pos)));
            }
        }

        return $this->delete($indexName);
    }

    /**
     * {@inheritdoc}
     */
    public function read($token)
    {
        if (empty($token)) {
            return false;
        }

        $profile = $this->getValue($this->getItemName($token));

        if (false !== $profile) {
            $profile = $this->createProfileFromData($token, $profile);
        }

        return $profile;
    }

    /**
     * {@inheritdoc}
     */
    public function write(Profile $profile)
    {
        $data = array(
            'token'    => $profile->getToken(),
            'parent'   => $profile->getParentToken(),
            'children' => array_map(function ($p) { return $p->getToken(); }, $profile->getChildren()),
            'data'     => $profile->getCollectors(),
            'ip'       => $profile->getIp(),
            'method'   => $profile->getMethod(),
            'url'      => $profile->getUrl(),
            'time'     => $profile->getTime(),
        );

        $profileIndexed = false !== $this->getValue($this->getItemName($profile->getToken()));

        if ($this->setValue($this->getItemName($profile->getToken()), $data, $this->lifetime)) {

            if (!$profileIndexed) {
                // Add to index
                $indexName = $this->getIndexName();

                $indexRow = implode("\t", array(
                    $profile->getToken(),
                    $profile->getIp(),
                    $profile->getMethod(),
                    $profile->getUrl(),
                    $profile->getTime(),
                    $profile->getParentToken(),
                ))."\n";

                return $this->appendValue($indexName, $indexRow, $this->lifetime);
            }

            return true;
        }

        return false;
    }

    /**
     * Retrieve item from the memcache server
     *
     * @param string $key
     *
     * @return mixed
     */
    abstract protected function getValue($key);

    /**
     * Store an item on the memcache server under the specified key
     *
     * @param string $key
     * @param mixed  $value
     * @param int    $expiration
     *
     * @return boolean
     */
    abstract protected function setValue($key, $value, $expiration = 0);

    /**
     * Delete item from the memcache server
     *
     * @param string $key
     *
     * @return boolean
     */
    abstract protected function delete($key);

    /**
     * Append data to an existing item on the memcache server
     * @param string $key
     * @param string $value
     * @param int    $expiration
     *
     * @return boolean
     */
    abstract protected function appendValue($key, $value, $expiration = 0);

    private function createProfileFromData($token, $data, $parent = null)
    {
        $profile = new Profile($token);
        $profile->setIp($data['ip']);
        $profile->setMethod($data['method']);
        $profile->setUrl($data['url']);
        $profile->setTime($data['time']);
        $profile->setCollectors($data['data']);

        if (!$parent && $data['parent']) {
            $parent = $this->read($data['parent']);
        }

        if ($parent) {
            $profile->setParent($parent);
        }

        foreach ($data['children'] as $token) {
            if (!$token) {
                continue;
            }

            if (!$childProfileData = $this->getValue($this->getItemName($token))) {
                continue;
            }

            $profile->addChild($this->createProfileFromData($token, $childProfileData, $profile));
        }

        return $profile;
    }

    /**
     * Get item name
     *
     * @param string $token
     *
     * @return string
     */
    private function getItemName($token)
    {
        $name = self::TOKEN_PREFIX.$token;

        if ($this->isItemNameValid($name)) {
            return $name;
        }

        return false;
    }

    /**
     * Get name of index
     *
     * @return string
     */
    private function getIndexName()
    {
        $name = self::TOKEN_PREFIX.'index';

        if ($this->isItemNameValid($name)) {
            return $name;
        }

        return false;
    }

    private function isItemNameValid($name)
    {
        $length = strlen($name);

        if ($length > 250) {
            throw new \RuntimeException(sprintf('The memcache item key "%s" is too long (%s bytes). Allowed maximum size is 250 bytes.', $name, $length));
        }

        return true;
    }

}
PK��Zt}�[��?Symfony/Component/HttpKernel/Profiler/SqliteProfilerStorage.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Profiler;

/**
 * SqliteProfilerStorage stores profiling information in a SQLite database.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class SqliteProfilerStorage extends PdoProfilerStorage
{
    /**
     * @throws \RuntimeException When neither of SQLite3 or PDO_SQLite extension is enabled
     */
    protected function initDb()
    {
        if (null === $this->db || $this->db instanceof \SQLite3) {
            if (0 !== strpos($this->dsn, 'sqlite')) {
                throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use Sqlite with an invalid dsn "%s". The expected format is "sqlite:/path/to/the/db/file".', $this->dsn));
            }
            if (class_exists('SQLite3')) {
                $db = new \SQLite3(substr($this->dsn, 7, strlen($this->dsn)), \SQLITE3_OPEN_READWRITE | \SQLITE3_OPEN_CREATE);
                if (method_exists($db, 'busyTimeout')) {
                    // busyTimeout only exists for PHP >= 5.3.3
                    $db->busyTimeout(1000);
                }
            } elseif (class_exists('PDO') && in_array('sqlite', \PDO::getAvailableDrivers(), true)) {
                $db = new \PDO($this->dsn);
            } else {
                throw new \RuntimeException('You need to enable either the SQLite3 or PDO_SQLite extension for the profiler to run properly.');
            }

            $db->exec('PRAGMA temp_store=MEMORY; PRAGMA journal_mode=MEMORY;');
            $db->exec('CREATE TABLE IF NOT EXISTS sf_profiler_data (token STRING, data STRING, ip STRING, method STRING, url STRING, time INTEGER, parent STRING, created_at INTEGER)');
            $db->exec('CREATE INDEX IF NOT EXISTS data_created_at ON sf_profiler_data (created_at)');
            $db->exec('CREATE INDEX IF NOT EXISTS data_ip ON sf_profiler_data (ip)');
            $db->exec('CREATE INDEX IF NOT EXISTS data_method ON sf_profiler_data (method)');
            $db->exec('CREATE INDEX IF NOT EXISTS data_url ON sf_profiler_data (url)');
            $db->exec('CREATE INDEX IF NOT EXISTS data_parent ON sf_profiler_data (parent)');
            $db->exec('CREATE UNIQUE INDEX IF NOT EXISTS data_token ON sf_profiler_data (token)');

            $this->db = $db;
        }

        return $this->db;
    }

    protected function exec($db, $query, array $args = array())
    {
        if ($db instanceof \SQLite3) {
            $stmt = $this->prepareStatement($db, $query);
            foreach ($args as $arg => $val) {
                $stmt->bindValue($arg, $val, is_int($val) ? \SQLITE3_INTEGER : \SQLITE3_TEXT);
            }

            $res = $stmt->execute();
            if (false === $res) {
                throw new \RuntimeException(sprintf('Error executing SQLite query "%s"', $query));
            }
            $res->finalize();
        } else {
            parent::exec($db, $query, $args);
        }
    }

    protected function fetch($db, $query, array $args = array())
    {
        $return = array();

        if ($db instanceof \SQLite3) {
            $stmt = $this->prepareStatement($db, $query, true);
            foreach ($args as $arg => $val) {
                $stmt->bindValue($arg, $val, is_int($val) ? \SQLITE3_INTEGER : \SQLITE3_TEXT);
            }
            $res = $stmt->execute();
            while ($row = $res->fetchArray(\SQLITE3_ASSOC)) {
                $return[] = $row;
            }
            $res->finalize();
            $stmt->close();
        } else {
            $return = parent::fetch($db, $query, $args);
        }

        return $return;
    }

    /**
     * {@inheritdoc}
     */
    protected function buildCriteria($ip, $url, $start, $end, $limit, $method)
    {
        $criteria = array();
        $args = array();

        if ($ip = preg_replace('/[^\d\.]/', '', $ip)) {
            $criteria[] = 'ip LIKE :ip';
            $args[':ip'] = '%'.$ip.'%';
        }

        if ($url) {
            $criteria[] = 'url LIKE :url ESCAPE "\"';
            $args[':url'] = '%'.addcslashes($url, '%_\\').'%';
        }

        if ($method) {
            $criteria[] = 'method = :method';
            $args[':method'] = $method;
        }

        if (!empty($start)) {
            $criteria[] = 'time >= :start';
            $args[':start'] = $start;
        }

        if (!empty($end)) {
            $criteria[] = 'time <= :end';
            $args[':end'] = $end;
        }

        return array($criteria, $args);
    }

    protected function close($db)
    {
        if ($db instanceof \SQLite3) {
            $db->close();
        }
    }
}
PK��Z\Y�`��=Symfony/Component/HttpKernel/Profiler/FileProfilerStorage.phpnu�[���<?php
/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Profiler;

/**
 * Storage for profiler using files.
 *
 * @author Alexandre Salomé <alexandre.salome@gmail.com>
 */
class FileProfilerStorage implements ProfilerStorageInterface
{
    /**
     * Folder where profiler data are stored.
     *
     * @var string
     */
    private $folder;

    /**
     * Constructs the file storage using a "dsn-like" path.
     *
     * Example : "file:/path/to/the/storage/folder"
     *
     * @param string $dsn The DSN
     *
     * @throws \RuntimeException
     */
    public function __construct($dsn)
    {
        if (0 !== strpos($dsn, 'file:')) {
            throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use FileStorage with an invalid dsn "%s". The expected format is "file:/path/to/the/storage/folder".', $dsn));
        }
        $this->folder = substr($dsn, 5);

        if (!is_dir($this->folder)) {
            mkdir($this->folder, 0777, true);
        }
    }

    /**
     * {@inheritdoc}
     */
    public function find($ip, $url, $limit, $method, $start = null, $end = null)
    {
        $file = $this->getIndexFilename();

        if (!file_exists($file)) {
            return array();
        }

        $file = fopen($file, 'r');
        fseek($file, 0, SEEK_END);

        $result = array();
        while (count($result) < $limit && $line = $this->readLineFromFile($file)) {
            list($csvToken, $csvIp, $csvMethod, $csvUrl, $csvTime, $csvParent) = str_getcsv($line);

            $csvTime = (int) $csvTime;

            if ($ip && false === strpos($csvIp, $ip) || $url && false === strpos($csvUrl, $url) || $method && false === strpos($csvMethod, $method)) {
                continue;
            }

            if (!empty($start) && $csvTime < $start) {
                continue;
            }

            if (!empty($end) && $csvTime > $end) {
                continue;
            }

            $result[$csvToken] = array(
                'token'  => $csvToken,
                'ip'     => $csvIp,
                'method' => $csvMethod,
                'url'    => $csvUrl,
                'time'   => $csvTime,
                'parent' => $csvParent,
            );
        }

        fclose($file);

        return array_values($result);
    }

    /**
     * {@inheritdoc}
     */
    public function purge()
    {
        $flags = \FilesystemIterator::SKIP_DOTS;
        $iterator = new \RecursiveDirectoryIterator($this->folder, $flags);
        $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::CHILD_FIRST);

        foreach ($iterator as $file) {
            if (is_file($file)) {
                unlink($file);
            } else {
                rmdir($file);
            }
        }
    }

    /**
     * {@inheritdoc}
     */
    public function read($token)
    {
        if (!$token || !file_exists($file = $this->getFilename($token))) {
            return null;
        }

        return $this->createProfileFromData($token, unserialize(file_get_contents($file)));
    }

    /**
     * {@inheritdoc}
     */
    public function write(Profile $profile)
    {
        $file = $this->getFilename($profile->getToken());

        $profileIndexed = is_file($file);
        if (!$profileIndexed) {
            // Create directory
            $dir = dirname($file);
            if (!is_dir($dir)) {
                mkdir($dir, 0777, true);
            }
        }

        // Store profile
        $data = array(
            'token'    => $profile->getToken(),
            'parent'   => $profile->getParentToken(),
            'children' => array_map(function ($p) { return $p->getToken(); }, $profile->getChildren()),
            'data'     => $profile->getCollectors(),
            'ip'       => $profile->getIp(),
            'method'   => $profile->getMethod(),
            'url'      => $profile->getUrl(),
            'time'     => $profile->getTime(),
        );

        if (false === file_put_contents($file, serialize($data))) {
            return false;
        }

        if (!$profileIndexed) {
            // Add to index
            if (false === $file = fopen($this->getIndexFilename(), 'a')) {
                return false;
            }

            fputcsv($file, array(
                $profile->getToken(),
                $profile->getIp(),
                $profile->getMethod(),
                $profile->getUrl(),
                $profile->getTime(),
                $profile->getParentToken(),
            ));
            fclose($file);
        }

        return true;
    }

    /**
     * Gets filename to store data, associated to the token.
     *
     * @param string $token
     *
     * @return string The profile filename
     */
    protected function getFilename($token)
    {
        // Uses 4 last characters, because first are mostly the same.
        $folderA = substr($token, -2, 2);
        $folderB = substr($token, -4, 2);

        return $this->folder.'/'.$folderA.'/'.$folderB.'/'.$token;
    }

    /**
     * Gets the index filename.
     *
     * @return string The index filename
     */
    protected function getIndexFilename()
    {
        return $this->folder.'/index.csv';
    }

    /**
     * Reads a line in the file, backward.
     *
     * This function automatically skips the empty lines and do not include the line return in result value.
     *
     * @param resource $file The file resource, with the pointer placed at the end of the line to read
     *
     * @return mixed A string representing the line or null if beginning of file is reached
     */
    protected function readLineFromFile($file)
    {
        $line = '';
        $position = ftell($file);

        if (0 === $position) {
            return null;
        }

        while (true) {
            $chunkSize = min($position, 1024);
            $position -= $chunkSize;
            fseek($file, $position);

            if (0 === $chunkSize) {
                // bof reached
                break;
            }

            $buffer = fread($file, $chunkSize);

            if (false === ($upTo = strrpos($buffer, "\n"))) {
                $line = $buffer.$line;
                continue;
            }

            $position += $upTo;
            $line = substr($buffer, $upTo + 1).$line;
            fseek($file, max(0, $position), SEEK_SET);

            if ('' !== $line) {
                break;
            }
        }

        return '' === $line ? null : $line;
    }

    protected function createProfileFromData($token, $data, $parent = null)
    {
        $profile = new Profile($token);
        $profile->setIp($data['ip']);
        $profile->setMethod($data['method']);
        $profile->setUrl($data['url']);
        $profile->setTime($data['time']);
        $profile->setCollectors($data['data']);

        if (!$parent && $data['parent']) {
            $parent = $this->read($data['parent']);
        }

        if ($parent) {
            $profile->setParent($parent);
        }

        foreach ($data['children'] as $token) {
            if (!$token || !file_exists($file = $this->getFilename($token))) {
                continue;
            }

            $profile->addChild($this->createProfileFromData($token, unserialize(file_get_contents($file)), $profile));
        }

        return $profile;
    }
}
PK��Z��,&&8Symfony/Component/HttpKernel/Event/PostResponseEvent.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Event;

use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * Allows to execute logic after a response was sent
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class PostResponseEvent extends Event
{
    /**
     * The kernel in which this event was thrown
     * @var HttpKernelInterface
     */
    private $kernel;

    private $request;

    private $response;

    public function __construct(HttpKernelInterface $kernel, Request $request, Response $response)
    {
        $this->kernel = $kernel;
        $this->request = $request;
        $this->response = $response;
    }

    /**
     * Returns the kernel in which this event was thrown.
     *
     * @return HttpKernelInterface
     */
    public function getKernel()
    {
        return $this->kernel;
    }

    /**
     * Returns the request for which this event was thrown.
     *
     * @return Request
     */
    public function getRequest()
    {
        return $this->request;
    }

    /**
     * Returns the response for which this event was thrown.
     *
     * @return Response
     */
    public function getResponse()
    {
        return $this->response;
    }
}
PK��Z
�7���9Symfony/Component/HttpKernel/Event/FinishRequestEvent.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Event;

/**
 * Triggered whenever a request is fully processed.
 *
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 */
class FinishRequestEvent extends KernelEvent
{
}
PK��Z�`g��:Symfony/Component/HttpKernel/Event/FilterResponseEvent.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Event;

use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * Allows to filter a Response object
 *
 * You can call getResponse() to retrieve the current response. With
 * setResponse() you can set a new response that will be returned to the
 * browser.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class FilterResponseEvent extends KernelEvent
{
    /**
     * The current response object
     * @var Response
     */
    private $response;

    public function __construct(HttpKernelInterface $kernel, Request $request, $requestType, Response $response)
    {
        parent::__construct($kernel, $request, $requestType);

        $this->setResponse($response);
    }

    /**
     * Returns the current response object
     *
     * @return Response
     *
     * @api
     */
    public function getResponse()
    {
        return $this->response;
    }

    /**
     * Sets a new response object
     *
     * @param Response $response
     *
     * @api
     */
    public function setResponse(Response $response)
    {
        $this->response = $response;
    }
}
PK��Z٨�.kkJSymfony/Component/HttpKernel/Event/GetResponseForControllerResultEvent.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Event;

use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request;

/**
 * Allows to create a response for the return value of a controller
 *
 * Call setResponse() to set the response that will be returned for the
 * current request. The propagation of this event is stopped as soon as a
 * response is set.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class GetResponseForControllerResultEvent extends GetResponseEvent
{
    /**
     * The return value of the controller
     *
     * @var mixed
     */
    private $controllerResult;

    public function __construct(HttpKernelInterface $kernel, Request $request, $requestType, $controllerResult)
    {
        parent::__construct($kernel, $request, $requestType);

        $this->controllerResult = $controllerResult;
    }

    /**
     * Returns the return value of the controller.
     *
     * @return mixed The controller return value
     *
     * @api
     */
    public function getControllerResult()
    {
        return $this->controllerResult;
    }

    /**
     * Assigns the return value of the controller.
     *
     * @param mixed $controllerResult The controller return value
     *
     * @api
     */
    public function setControllerResult($controllerResult)
    {
        $this->controllerResult = $controllerResult;
    }
}
PK��Z9�I��7Symfony/Component/HttpKernel/Event/GetResponseEvent.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Event;

use Symfony\Component\HttpFoundation\Response;

/**
 * Allows to create a response for a request
 *
 * Call setResponse() to set the response that will be returned for the
 * current request. The propagation of this event is stopped as soon as a
 * response is set.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class GetResponseEvent extends KernelEvent
{
    /**
     * The response object
     * @var Response
     */
    private $response;

    /**
     * Returns the response object
     *
     * @return Response
     *
     * @api
     */
    public function getResponse()
    {
        return $this->response;
    }

    /**
     * Sets a response and stops event propagation
     *
     * @param Response $response
     *
     * @api
     */
    public function setResponse(Response $response)
    {
        $this->response = $response;

        $this->stopPropagation();
    }

    /**
     * Returns whether a response was set
     *
     * @return Boolean Whether a response was set
     *
     * @api
     */
    public function hasResponse()
    {
        return null !== $this->response;
    }
}
PK��Z�9����CSymfony/Component/HttpKernel/Event/GetResponseForExceptionEvent.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Event;

use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request;

/**
 * Allows to create a response for a thrown exception
 *
 * Call setResponse() to set the response that will be returned for the
 * current request. The propagation of this event is stopped as soon as a
 * response is set.
 *
 * You can also call setException() to replace the thrown exception. This
 * exception will be thrown if no response is set during processing of this
 * event.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class GetResponseForExceptionEvent extends GetResponseEvent
{
    /**
     * The exception object
     * @var \Exception
     */
    private $exception;

    public function __construct(HttpKernelInterface $kernel, Request $request, $requestType, \Exception $e)
    {
        parent::__construct($kernel, $request, $requestType);

        $this->setException($e);
    }

    /**
     * Returns the thrown exception
     *
     * @return \Exception  The thrown exception
     *
     * @api
     */
    public function getException()
    {
        return $this->exception;
    }

    /**
     * Replaces the thrown exception
     *
     * This exception will be thrown if no response is set in the event.
     *
     * @param \Exception $exception The thrown exception
     *
     * @api
     */
    public function setException(\Exception $exception)
    {
        $this->exception = $exception;
    }
}
PK��Z�%���	�	<Symfony/Component/HttpKernel/Event/FilterControllerEvent.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Event;

use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request;

/**
 * Allows filtering of a controller callable
 *
 * You can call getController() to retrieve the current controller. With
 * setController() you can set a new controller that is used in the processing
 * of the request.
 *
 * Controllers should be callables.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class FilterControllerEvent extends KernelEvent
{
    /**
     * The current controller
     * @var callable
     */
    private $controller;

    public function __construct(HttpKernelInterface $kernel, $controller, Request $request, $requestType)
    {
        parent::__construct($kernel, $request, $requestType);

        $this->setController($controller);
    }

    /**
     * Returns the current controller
     *
     * @return callable
     *
     * @api
     */
    public function getController()
    {
        return $this->controller;
    }

    /**
     * Sets a new controller
     *
     * @param callable $controller
     *
     * @throws \LogicException
     *
     * @api
     */
    public function setController($controller)
    {
        // controller must be a callable
        if (!is_callable($controller)) {
            throw new \LogicException(sprintf('The controller must be a callable (%s given).', $this->varToString($controller)));
        }

        $this->controller = $controller;
    }

    private function varToString($var)
    {
        if (is_object($var)) {
            return sprintf('Object(%s)', get_class($var));
        }

        if (is_array($var)) {
            $a = array();
            foreach ($var as $k => $v) {
                $a[] = sprintf('%s => %s', $k, $this->varToString($v));
            }

            return sprintf("Array(%s)", implode(', ', $a));
        }

        if (is_resource($var)) {
            return sprintf('Resource(%s)', get_resource_type($var));
        }

        if (null === $var) {
            return 'null';
        }

        if (false === $var) {
            return 'false';
        }

        if (true === $var) {
            return 'true';
        }

        return (string) $var;
    }
}
PK��Z}�x��2Symfony/Component/HttpKernel/Event/KernelEvent.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Event;

use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\EventDispatcher\Event;

/**
 * Base class for events thrown in the HttpKernel component
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class KernelEvent extends Event
{
    /**
     * The kernel in which this event was thrown
     * @var HttpKernelInterface
     */
    private $kernel;

    /**
     * The request the kernel is currently processing
     * @var Request
     */
    private $request;

    /**
     * The request type the kernel is currently processing.  One of
     * HttpKernelInterface::MASTER_REQUEST and HttpKernelInterface::SUB_REQUEST
     * @var integer
     */
    private $requestType;

    public function __construct(HttpKernelInterface $kernel, Request $request, $requestType)
    {
        $this->kernel = $kernel;
        $this->request = $request;
        $this->requestType = $requestType;
    }

    /**
     * Returns the kernel in which this event was thrown
     *
     * @return HttpKernelInterface
     *
     * @api
     */
    public function getKernel()
    {
        return $this->kernel;
    }

    /**
     * Returns the request the kernel is currently processing
     *
     * @return Request
     *
     * @api
     */
    public function getRequest()
    {
        return $this->request;
    }

    /**
     * Returns the request type the kernel is currently processing
     *
     * @return integer  One of HttpKernelInterface::MASTER_REQUEST and
     *                  HttpKernelInterface::SUB_REQUEST
     *
     * @api
     */
    public function getRequestType()
    {
        return $this->requestType;
    }

    /**
     * Checks if this is a master request.
     *
     * @return Boolean True if the request is a master request
     *
     * @api
     */
    public function isMasterRequest()
    {
        return HttpKernelInterface::MASTER_REQUEST === $this->requestType;
    }
}
PK��ZN�#�FF'Symfony/Component/HttpKernel/Client.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel;

use Symfony\Component\BrowserKit\Client as BaseClient;
use Symfony\Component\BrowserKit\Request as DomRequest;
use Symfony\Component\BrowserKit\Response as DomResponse;
use Symfony\Component\BrowserKit\Cookie as DomCookie;
use Symfony\Component\BrowserKit\History;
use Symfony\Component\BrowserKit\CookieJar;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * Client simulates a browser and makes requests to a Kernel object.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class Client extends BaseClient
{
    protected $kernel;

    /**
     * Constructor.
     *
     * @param HttpKernelInterface $kernel    An HttpKernel instance
     * @param array               $server    The server parameters (equivalent of $_SERVER)
     * @param History             $history   A History instance to store the browser history
     * @param CookieJar           $cookieJar A CookieJar instance to store the cookies
     */
    public function __construct(HttpKernelInterface $kernel, array $server = array(), History $history = null, CookieJar $cookieJar = null)
    {
        // These class properties must be set before calling the parent constructor, as it may depend on it.
        $this->kernel = $kernel;
        $this->followRedirects = false;

        parent::__construct($server, $history, $cookieJar);
    }

    /**
     * {@inheritdoc}
     *
     * @return Request|null A Request instance
     */
    public function getRequest()
    {
        return parent::getRequest();
    }

    /**
     * {@inheritdoc}
     *
     * @return Response|null A Response instance
     */
    public function getResponse()
    {
        return parent::getResponse();
    }

    /**
     * Makes a request.
     *
     * @param Request $request A Request instance
     *
     * @return Response A Response instance
     */
    protected function doRequest($request)
    {
        $response = $this->kernel->handle($request);

        if ($this->kernel instanceof TerminableInterface) {
            $this->kernel->terminate($request, $response);
        }

        return $response;
    }

    /**
     * Returns the script to execute when the request must be insulated.
     *
     * @param Request $request A Request instance
     *
     * @return string
     */
    protected function getScript($request)
    {
        $kernel = str_replace("'", "\\'", serialize($this->kernel));
        $request = str_replace("'", "\\'", serialize($request));

        $r = new \ReflectionClass('\\Symfony\\Component\\ClassLoader\\ClassLoader');
        $requirePath = str_replace("'", "\\'", $r->getFileName());
        $symfonyPath = str_replace("'", "\\'", realpath(__DIR__.'/../../..'));

        $code = <<<EOF
<?php

require_once '$requirePath';

\$loader = new Symfony\Component\ClassLoader\ClassLoader();
\$loader->addPrefix('Symfony', '$symfonyPath');
\$loader->register();

\$kernel = unserialize('$kernel');
\$request = unserialize('$request');
EOF;

        return $code.$this->getHandleScript();
    }

    protected function getHandleScript()
    {
        return <<<'EOF'
$response = $kernel->handle($request);

if ($kernel instanceof Symfony\Component\HttpKernel\TerminableInterface) {
    $kernel->terminate($request, $response);
}

echo serialize($response);
EOF;
    }

    /**
     * Converts the BrowserKit request to a HttpKernel request.
     *
     * @param DomRequest $request A DomRequest instance
     *
     * @return Request A Request instance
     */
    protected function filterRequest(DomRequest $request)
    {
        $httpRequest = Request::create($request->getUri(), $request->getMethod(), $request->getParameters(), $request->getCookies(), $request->getFiles(), $request->getServer(), $request->getContent());

        $httpRequest->files->replace($this->filterFiles($httpRequest->files->all()));

        return $httpRequest;
    }

    /**
     * Filters an array of files.
     *
     * This method created test instances of UploadedFile so that the move()
     * method can be called on those instances.
     *
     * If the size of a file is greater than the allowed size (from php.ini) then
     * an invalid UploadedFile is returned with an error set to UPLOAD_ERR_INI_SIZE.
     *
     * @see Symfony\Component\HttpFoundation\File\UploadedFile
     *
     * @param array $files An array of files
     *
     * @return array An array with all uploaded files marked as already moved
     */
    protected function filterFiles(array $files)
    {
        $filtered = array();
        foreach ($files as $key => $value) {
            if (is_array($value)) {
                $filtered[$key] = $this->filterFiles($value);
            } elseif ($value instanceof UploadedFile) {
                if ($value->isValid() && $value->getSize() > UploadedFile::getMaxFilesize()) {
                    $filtered[$key] = new UploadedFile(
                        '',
                        $value->getClientOriginalName(),
                        $value->getClientMimeType(),
                        0,
                        UPLOAD_ERR_INI_SIZE,
                        true
                    );
                } else {
                    $filtered[$key] = new UploadedFile(
                        $value->getPathname(),
                        $value->getClientOriginalName(),
                        $value->getClientMimeType(),
                        $value->getClientSize(),
                        $value->getError(),
                        true
                    );
                }
            } else {
                $filtered[$key] = $value;
            }
        }

        return $filtered;
    }

    /**
     * Converts the HttpKernel response to a BrowserKit response.
     *
     * @param Response $response A Response instance
     *
     * @return DomResponse A DomResponse instance
     */
    protected function filterResponse($response)
    {
        $headers = $response->headers->all();
        if ($response->headers->getCookies()) {
            $cookies = array();
            foreach ($response->headers->getCookies() as $cookie) {
                $cookies[] = new DomCookie($cookie->getName(), $cookie->getValue(), $cookie->getExpiresTime(), $cookie->getPath(), $cookie->getDomain(), $cookie->isSecure(), $cookie->isHttpOnly());
            }
            $headers['Set-Cookie'] = $cookies;
        }

        // this is needed to support StreamedResponse
        ob_start();
        $response->sendContent();
        $content = ob_get_clean();

        return new DomResponse($content, $response->getStatusCode(), $headers);
    }
}
PK��Z�
<ISymfony/Component/HttpKernel/DataCollector/LateDataCollectorInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\DataCollector;

/**
 * LateDataCollectorInterface.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface LateDataCollectorInterface
{
    /**
     * Collects data as late as possible.
     */
    public function lateCollect();
}
PK��Z�8���ESymfony/Component/HttpKernel/DataCollector/ExceptionDataCollector.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\DataCollector;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\FlattenException;

/**
 * ExceptionDataCollector.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ExceptionDataCollector extends DataCollector
{
    /**
     * {@inheritdoc}
     */
    public function collect(Request $request, Response $response, \Exception $exception = null)
    {
        if (null !== $exception) {
            $this->data = array(
                'exception' => FlattenException::create($exception),
            );
        }
    }

    /**
     * Checks if the exception is not null.
     *
     * @return Boolean true if the exception is not null, false otherwise
     */
    public function hasException()
    {
        return isset($this->data['exception']);
    }

    /**
     * Gets the exception.
     *
     * @return \Exception The exception
     */
    public function getException()
    {
        return $this->data['exception'];
    }

    /**
     * Gets the exception message.
     *
     * @return string The exception message
     */
    public function getMessage()
    {
        return $this->data['exception']->getMessage();
    }

    /**
     * Gets the exception code.
     *
     * @return integer The exception code
     */
    public function getCode()
    {
        return $this->data['exception']->getCode();
    }

    /**
     * Gets the status code.
     *
     * @return integer The status code
     */
    public function getStatusCode()
    {
        return $this->data['exception']->getStatusCode();
    }

    /**
     * Gets the exception trace.
     *
     * @return array The exception trace
     */
    public function getTrace()
    {
        return $this->data['exception']->getTrace();
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'exception';
    }
}
PK��Z�2��~~BSymfony/Component/HttpKernel/DataCollector/ConfigDataCollector.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\DataCollector;

use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * ConfigDataCollector.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ConfigDataCollector extends DataCollector
{
    private $kernel;
    private $name;
    private $version;

    /**
     * Constructor.
     *
     * @param string $name    The name of the application using the web profiler
     * @param string $version The version of the application using the web profiler
     */
    public function __construct($name = null, $version = null)
    {
        $this->name = $name;
        $this->version = $version;
    }

    /**
     * Sets the Kernel associated with this Request.
     *
     * @param KernelInterface $kernel A KernelInterface instance
     */
    public function setKernel(KernelInterface $kernel = null)
    {
        $this->kernel = $kernel;
    }

    /**
     * {@inheritdoc}
     */
    public function collect(Request $request, Response $response, \Exception $exception = null)
    {
        $this->data = array(
            'app_name'             => $this->name,
            'app_version'          => $this->version,
            'token'                => $response->headers->get('X-Debug-Token'),
            'symfony_version'      => Kernel::VERSION,
            'name'                 => isset($this->kernel) ? $this->kernel->getName() : 'n/a',
            'env'                  => isset($this->kernel) ? $this->kernel->getEnvironment() : 'n/a',
            'debug'                => isset($this->kernel) ? $this->kernel->isDebug() : 'n/a',
            'php_version'          => PHP_VERSION,
            'xdebug_enabled'       => extension_loaded('xdebug'),
            'eaccel_enabled'       => extension_loaded('eaccelerator') && ini_get('eaccelerator.enable'),
            'apc_enabled'          => extension_loaded('apc') && ini_get('apc.enabled'),
            'xcache_enabled'       => extension_loaded('xcache') && ini_get('xcache.cacher'),
            'wincache_enabled'     => extension_loaded('wincache') && ini_get('wincache.ocenabled'),
            'zend_opcache_enabled' => extension_loaded('Zend OPcache') && ini_get('opcache.enable'),
            'bundles'              => array(),
            'sapi_name'            => php_sapi_name()
        );

        if (isset($this->kernel)) {
            foreach ($this->kernel->getBundles() as $name => $bundle) {
                $this->data['bundles'][$name] = $bundle->getPath();
            }
        }
    }

    public function getApplicationName()
    {
        return $this->data['app_name'];
    }

    public function getApplicationVersion()
    {
        return $this->data['app_version'];
    }

    /**
     * Gets the token.
     *
     * @return string The token
     */
    public function getToken()
    {
        return $this->data['token'];
    }

    /**
     * Gets the Symfony version.
     *
     * @return string The Symfony version
     */
    public function getSymfonyVersion()
    {
        return $this->data['symfony_version'];
    }

    /**
     * Gets the PHP version.
     *
     * @return string The PHP version
     */
    public function getPhpVersion()
    {
        return $this->data['php_version'];
    }

    /**
     * Gets the application name.
     *
     * @return string The application name
     */
    public function getAppName()
    {
        return $this->data['name'];
    }

    /**
     * Gets the environment.
     *
     * @return string The environment
     */
    public function getEnv()
    {
        return $this->data['env'];
    }

    /**
     * Returns true if the debug is enabled.
     *
     * @return Boolean true if debug is enabled, false otherwise
     */
    public function isDebug()
    {
        return $this->data['debug'];
    }

    /**
     * Returns true if the XDebug is enabled.
     *
     * @return Boolean true if XDebug is enabled, false otherwise
     */
    public function hasXDebug()
    {
        return $this->data['xdebug_enabled'];
    }

    /**
     * Returns true if EAccelerator is enabled.
     *
     * @return Boolean true if EAccelerator is enabled, false otherwise
     */
    public function hasEAccelerator()
    {
        return $this->data['eaccel_enabled'];
    }

    /**
     * Returns true if APC is enabled.
     *
     * @return Boolean true if APC is enabled, false otherwise
     */
    public function hasApc()
    {
        return $this->data['apc_enabled'];
    }

    /**
     * Returns true if Zend OPcache is enabled
     *
     * @return Boolean true if Zend OPcache is enabled, false otherwise
     */
    public function hasZendOpcache()
    {
        return $this->data['zend_opcache_enabled'];
    }

    /**
     * Returns true if XCache is enabled.
     *
     * @return Boolean true if XCache is enabled, false otherwise
     */
    public function hasXCache()
    {
        return $this->data['xcache_enabled'];
    }

    /**
     * Returns true if WinCache is enabled.
     *
     * @return Boolean true if WinCache is enabled, false otherwise
     */
    public function hasWinCache()
    {
        return $this->data['wincache_enabled'];
    }

    /**
     * Returns true if any accelerator is enabled.
     *
     * @return Boolean true if any accelerator is enabled, false otherwise
     */
    public function hasAccelerator()
    {
        return $this->hasApc() || $this->hasZendOpcache() || $this->hasEAccelerator() || $this->hasXCache() || $this->hasWinCache();
    }

    public function getBundles()
    {
        return $this->data['bundles'];
    }

    /**
     * Gets the PHP SAPI name.
     *
     * @return string The environment
     */
    public function getSapiName()
    {
        return $this->data['sapi_name'];
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'config';
    }
}
PK��Z��.�ESymfony/Component/HttpKernel/DataCollector/DataCollectorInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\DataCollector;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * DataCollectorInterface.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface DataCollectorInterface
{
    /**
     * Collects data for the given Request and Response.
     *
     * @param Request    $request   A Request instance
     * @param Response   $response  A Response instance
     * @param \Exception $exception An Exception instance
     *
     * @api
     */
    public function collect(Request $request, Response $response, \Exception $exception = null);

    /**
     * Returns the name of the collector.
     *
     * @return string The collector name
     *
     * @api
     */
    public function getName();
}
PK��Z��޹�BSymfony/Component/HttpKernel/DataCollector/LoggerDataCollector.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\DataCollector;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Debug\ErrorHandler;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;

/**
 * LogDataCollector.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class LoggerDataCollector extends DataCollector implements LateDataCollectorInterface
{
    private $logger;

    public function __construct($logger = null)
    {
        if (null !== $logger && $logger instanceof DebugLoggerInterface) {
            $this->logger = $logger;
        }
    }

    /**
     * {@inheritdoc}
     */
    public function collect(Request $request, Response $response, \Exception $exception = null)
    {
        // everything is done as late as possible
    }

    /**
     * {@inheritdoc}
     */
    public function lateCollect()
    {
        if (null !== $this->logger) {
            $this->data = array(
                'error_count'       => $this->logger->countErrors(),
                'logs'              => $this->sanitizeLogs($this->logger->getLogs()),
                'deprecation_count' => $this->computeDeprecationCount()
            );
        }
    }

    /**
     * Gets the called events.
     *
     * @return array An array of called events
     *
     * @see TraceableEventDispatcherInterface
     */
    public function countErrors()
    {
        return isset($this->data['error_count']) ? $this->data['error_count'] : 0;
    }

    /**
     * Gets the logs.
     *
     * @return array An array of logs
     */
    public function getLogs()
    {
        return isset($this->data['logs']) ? $this->data['logs'] : array();
    }

    public function countDeprecations()
    {
        return isset($this->data['deprecation_count']) ? $this->data['deprecation_count'] : 0;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'logger';
    }

    private function sanitizeLogs($logs)
    {
        foreach ($logs as $i => $log) {
            $logs[$i]['context'] = $this->sanitizeContext($log['context']);
        }

        return $logs;
    }

    private function sanitizeContext($context)
    {
        if (is_array($context)) {
            foreach ($context as $key => $value) {
                $context[$key] = $this->sanitizeContext($value);
            }

            return $context;
        }

        if (is_resource($context)) {
            return sprintf('Resource(%s)', get_resource_type($context));
        }

        if (is_object($context)) {
            return sprintf('Object(%s)', get_class($context));
        }

        return $context;
    }

    private function computeDeprecationCount()
    {
        $count = 0;
        foreach ($this->logger->getLogs() as $log) {
            if (isset($log['context']['type']) && ErrorHandler::TYPE_DEPRECATION === $log['context']['type']) {
                $count++;
            }
        }

        return $count;
    }
}
PK��Z�@:o	o	BSymfony/Component/HttpKernel/DataCollector/RouterDataCollector.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\DataCollector;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;

/**
 * RouterDataCollector.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class RouterDataCollector extends DataCollector
{
    protected $controllers;

    public function __construct()
    {
        $this->controllers = new \SplObjectStorage();

        $this->data = array(
            'redirect' => false,
            'url'      => null,
            'route'    => null,
        );
    }

    /**
     * {@inheritdoc}
     */
    public function collect(Request $request, Response $response, \Exception $exception = null)
    {
        if ($response instanceof RedirectResponse) {
            $this->data['redirect'] = true;
            $this->data['url'] = $response->getTargetUrl();

            if ($this->controllers->contains($request)) {
                $this->data['route'] = $this->guessRoute($request, $this->controllers[$request]);
            }
        }

        unset($this->controllers[$request]);
    }

    protected function guessRoute(Request $request, $controller)
    {
        return 'n/a';
    }

    /**
     * Remembers the controller associated to each request.
     *
     * @param FilterControllerEvent $event The filter controller event
     */
    public function onKernelController(FilterControllerEvent $event)
    {
        $this->controllers[$event->getRequest()] = $event->getController();
    }

    /**
     * @return Boolean Whether this request will result in a redirect
     */
    public function getRedirect()
    {
        return $this->data['redirect'];
    }

    /**
     * @return string|null The target URL
     */
    public function getTargetUrl()
    {
        return $this->data['url'];
    }

    /**
     * @return string|null The target route
     */
    public function getTargetRoute()
    {
        return $this->data['route'];
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'router';
    }
}
PK��Z��+66ASymfony/Component/HttpKernel/DataCollector/Util/ValueExporter.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\DataCollector\Util;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ValueExporter
{
    /**
     * Converts a PHP value to a string.
     *
     * @param mixed $value The PHP value
     *
     * @return string The string representation of the given value
     */
    public function exportValue($value)
    {
        if (is_object($value)) {
            return sprintf('Object(%s)', get_class($value));
        }

        if (is_array($value)) {
            $a = array();
            foreach ($value as $k => $v) {
                $a[] = sprintf('%s => %s', $k, $this->exportValue($v));
            }

            return sprintf("Array(%s)", implode(', ', $a));
        }

        if (is_resource($value)) {
            return sprintf('Resource(%s)', get_resource_type($value));
        }

        if (null === $value) {
            return 'null';
        }

        if (false === $value) {
            return 'false';
        }

        if (true === $value) {
            return 'true';
        }

        return (string) $value;
    }
}
PK��ZIYz��(�(CSymfony/Component/HttpKernel/DataCollector/RequestDataCollector.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\DataCollector;

use Symfony\Component\HttpFoundation\ParameterBag;
use Symfony\Component\HttpFoundation\HeaderBag;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * RequestDataCollector.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class RequestDataCollector extends DataCollector implements EventSubscriberInterface
{
    protected $controllers;

    public function __construct()
    {
        $this->controllers = new \SplObjectStorage();
    }

    /**
     * {@inheritdoc}
     */
    public function collect(Request $request, Response $response, \Exception $exception = null)
    {
        $responseHeaders = $response->headers->all();
        $cookies = array();
        foreach ($response->headers->getCookies() as $cookie) {
            $cookies[] = $this->getCookieHeader($cookie->getName(), $cookie->getValue(), $cookie->getExpiresTime(), $cookie->getPath(), $cookie->getDomain(), $cookie->isSecure(), $cookie->isHttpOnly());
        }
        if (count($cookies) > 0) {
            $responseHeaders['Set-Cookie'] = $cookies;
        }

        $attributes = array();
        foreach ($request->attributes->all() as $key => $value) {
            if ('_route' === $key && is_object($value)) {
                $attributes['_route'] = $this->varToString($value->getPath());
            } elseif ('_route_params' === $key) {
                foreach ($value as $key => $v) {
                    $attributes['_route_params'][$key] = $this->varToString($v);
                }
            } else {
                $attributes[$key] = $this->varToString($value);
            }
        }

        $content = null;
        try {
            $content = $request->getContent();
        } catch (\LogicException $e) {
            // the user already got the request content as a resource
            $content = false;
        }

        $sessionMetadata = array();
        $sessionAttributes = array();
        $flashes = array();
        if ($request->hasSession()) {
            $session = $request->getSession();
            if ($session->isStarted()) {
                $sessionMetadata['Created'] = date(DATE_RFC822, $session->getMetadataBag()->getCreated());
                $sessionMetadata['Last used'] = date(DATE_RFC822, $session->getMetadataBag()->getLastUsed());
                $sessionMetadata['Lifetime'] = $session->getMetadataBag()->getLifetime();
                $sessionAttributes = $session->all();
                $flashes = $session->getFlashBag()->peekAll();
            }
        }

        $statusCode = $response->getStatusCode();

        $this->data = array(
            'format'             => $request->getRequestFormat(),
            'content'            => $content,
            'content_type'       => $response->headers->get('Content-Type') ? $response->headers->get('Content-Type') : 'text/html',
            'status_text'        => isset(Response::$statusTexts[$statusCode]) ? Response::$statusTexts[$statusCode] : '',
            'status_code'        => $statusCode,
            'request_query'      => $request->query->all(),
            'request_request'    => $request->request->all(),
            'request_headers'    => $request->headers->all(),
            'request_server'     => $request->server->all(),
            'request_cookies'    => $request->cookies->all(),
            'request_attributes' => $attributes,
            'response_headers'   => $responseHeaders,
            'session_metadata'   => $sessionMetadata,
            'session_attributes' => $sessionAttributes,
            'flashes'            => $flashes,
            'path_info'          => $request->getPathInfo(),
            'controller'         => 'n/a',
            'locale'             => $request->getLocale(),
        );

        if (isset($this->data['request_headers']['php-auth-pw'])) {
            $this->data['request_headers']['php-auth-pw'] = '******';
        }

        if (isset($this->data['request_server']['PHP_AUTH_PW'])) {
            $this->data['request_server']['PHP_AUTH_PW'] = '******';
        }

        if (isset($this->controllers[$request])) {
            $controller = $this->controllers[$request];
            if (is_array($controller)) {
                try {
                    $r = new \ReflectionMethod($controller[0], $controller[1]);
                    $this->data['controller'] = array(
                        'class'  => is_object($controller[0]) ? get_class($controller[0]) : $controller[0],
                        'method' => $controller[1],
                        'file'   => $r->getFilename(),
                        'line'   => $r->getStartLine(),
                    );
                } catch (\ReflectionException $re) {
                    if (is_callable($controller)) {
                        // using __call or  __callStatic
                        $this->data['controller'] = array(
                            'class'  => is_object($controller[0]) ? get_class($controller[0]) : $controller[0],
                            'method' => $controller[1],
                            'file'   => 'n/a',
                            'line'   => 'n/a',
                        );
                    }
                }
            } elseif ($controller instanceof \Closure) {
                $r = new \ReflectionFunction($controller);
                $this->data['controller'] = array(
                    'class'  => $r->getName(),
                    'method' => null,
                    'file'   => $r->getFilename(),
                    'line'   => $r->getStartLine(),
                );
            } else {
                $this->data['controller'] = (string) $controller ?: 'n/a';
            }
            unset($this->controllers[$request]);
        }
    }

    public function getPathInfo()
    {
        return $this->data['path_info'];
    }

    public function getRequestRequest()
    {
        return new ParameterBag($this->data['request_request']);
    }

    public function getRequestQuery()
    {
        return new ParameterBag($this->data['request_query']);
    }

    public function getRequestHeaders()
    {
        return new HeaderBag($this->data['request_headers']);
    }

    public function getRequestServer()
    {
        return new ParameterBag($this->data['request_server']);
    }

    public function getRequestCookies()
    {
        return new ParameterBag($this->data['request_cookies']);
    }

    public function getRequestAttributes()
    {
        return new ParameterBag($this->data['request_attributes']);
    }

    public function getResponseHeaders()
    {
        return new ResponseHeaderBag($this->data['response_headers']);
    }

    public function getSessionMetadata()
    {
        return $this->data['session_metadata'];
    }

    public function getSessionAttributes()
    {
        return $this->data['session_attributes'];
    }

    public function getFlashes()
    {
        return $this->data['flashes'];
    }

    public function getContent()
    {
        return $this->data['content'];
    }

    public function getContentType()
    {
        return $this->data['content_type'];
    }

    public function getStatusText()
    {
        return $this->data['status_text'];
    }

    public function getStatusCode()
    {
        return $this->data['status_code'];
    }

    public function getFormat()
    {
        return $this->data['format'];
    }

    public function getLocale()
    {
        return $this->data['locale'];
    }

    /**
     * Gets the route name.
     *
     * The _route request attributes is automatically set by the Router Matcher.
     *
     * @return string The route
     */
    public function getRoute()
    {
        return isset($this->data['request_attributes']['_route']) ? $this->data['request_attributes']['_route'] : '';
    }

    /**
     * Gets the route parameters.
     *
     * The _route_params request attributes is automatically set by the RouterListener.
     *
     * @return array The parameters
     */
    public function getRouteParams()
    {
        return isset($this->data['request_attributes']['_route_params']) ? $this->data['request_attributes']['_route_params'] : array();
    }

    /**
     * Gets the controller.
     *
     * @return string The controller as a string
     */
    public function getController()
    {
        return $this->data['controller'];
    }

    public function onKernelController(FilterControllerEvent $event)
    {
        $this->controllers[$event->getRequest()] = $event->getController();
    }

    public static function getSubscribedEvents()
    {
        return array(KernelEvents::CONTROLLER => 'onKernelController');
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'request';
    }

    private function getCookieHeader($name, $value, $expires, $path, $domain, $secure, $httponly)
    {
        $cookie = sprintf('%s=%s', $name, urlencode($value));

        if (0 !== $expires) {
            if (is_numeric($expires)) {
                $expires = (int) $expires;
            } elseif ($expires instanceof \DateTime) {
                $expires = $expires->getTimestamp();
            } else {
                $expires = strtotime($expires);
                if (false === $expires || -1 == $expires) {
                    throw new \InvalidArgumentException(sprintf('The "expires" cookie parameter is not valid.', $expires));
                }
            }

            $cookie .= '; expires='.str_replace('+0000', '', \DateTime::createFromFormat('U', $expires, new \DateTimeZone('GMT'))->format('D, d-M-Y H:i:s T'));
        }

        if ($domain) {
            $cookie .= '; domain='.$domain;
        }

        $cookie .= '; path='.$path;

        if ($secure) {
            $cookie .= '; secure';
        }

        if ($httponly) {
            $cookie .= '; httponly';
        }

        return $cookie;
    }
}
PK��Z����
�
ASymfony/Component/HttpKernel/DataCollector/EventDataCollector.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\DataCollector;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface;

/**
 * EventDataCollector.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class EventDataCollector extends DataCollector implements LateDataCollectorInterface
{
    protected $dispatcher;

    public function __construct(EventDispatcherInterface $dispatcher = null)
    {
        $this->dispatcher = $dispatcher;
    }

    /**
     * {@inheritdoc}
     */
    public function collect(Request $request, Response $response, \Exception $exception = null)
    {
        $this->data = array(
            'called_listeners'     => array(),
            'not_called_listeners' => array(),
        );
    }

    public function lateCollect()
    {
        if ($this->dispatcher instanceof TraceableEventDispatcherInterface) {
            $this->setCalledListeners($this->dispatcher->getCalledListeners());
            $this->setNotCalledListeners($this->dispatcher->getNotCalledListeners());
        }
    }

    /**
     * Sets the called listeners.
     *
     * @param array $listeners An array of called listeners
     *
     * @see TraceableEventDispatcherInterface
     */
    public function setCalledListeners(array $listeners)
    {
        $this->data['called_listeners'] = $listeners;
    }

    /**
     * Gets the called listeners.
     *
     * @return array An array of called listeners
     *
     * @see TraceableEventDispatcherInterface
     */
    public function getCalledListeners()
    {
        return $this->data['called_listeners'];
    }

    /**
     * Sets the not called listeners.
     *
     * @param array $listeners An array of not called listeners
     *
     * @see TraceableEventDispatcherInterface
     */
    public function setNotCalledListeners(array $listeners)
    {
        $this->data['not_called_listeners'] = $listeners;
    }

    /**
     * Gets the not called listeners.
     *
     * @return array An array of not called listeners
     *
     * @see TraceableEventDispatcherInterface
     */
    public function getNotCalledListeners()
    {
        return $this->data['not_called_listeners'];
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'events';
    }
}
PK��ZƏGV��@Symfony/Component/HttpKernel/DataCollector/TimeDataCollector.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\DataCollector;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\KernelInterface;

/**
 * TimeDataCollector.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class TimeDataCollector extends DataCollector implements LateDataCollectorInterface
{
    protected $kernel;
    protected $stopwatch;

    public function __construct(KernelInterface $kernel = null, $stopwatch = null)
    {
        $this->kernel = $kernel;
        $this->stopwatch = $stopwatch;
    }

    /**
     * {@inheritdoc}
     */
    public function collect(Request $request, Response $response, \Exception $exception = null)
    {
        if (null !== $this->kernel) {
            $startTime = $this->kernel->getStartTime();
        } else {
            $startTime = $request->server->get('REQUEST_TIME_FLOAT', $request->server->get('REQUEST_TIME'));
        }

        $this->data = array(
            'token'      => $response->headers->get('X-Debug-Token'),
            'start_time' => $startTime * 1000,
            'events'     => array(),
        );
    }

    /**
     * {@inheritdoc}
     */
    public function lateCollect()
    {
        if (null !== $this->stopwatch && isset($this->data['token'])) {
            $this->setEvents($this->stopwatch->getSectionEvents($this->data['token']));
        }
        unset($this->data['token']);
    }

    /**
     * Sets the request events.
     *
     * @param array $events The request events
     */
    public function setEvents(array $events)
    {
        foreach ($events as $event) {
            $event->ensureStopped();
        }

        $this->data['events'] = $events;
    }

    /**
     * Gets the request events.
     *
     * @return array The request events
     */
    public function getEvents()
    {
        return $this->data['events'];
    }

    /**
     * Gets the request elapsed time.
     *
     * @return float The elapsed time
     */
    public function getDuration()
    {
        if (!isset($this->data['events']['__section__'])) {
            return 0;
        }

        $lastEvent = $this->data['events']['__section__'];

        return $lastEvent->getOrigin() + $lastEvent->getDuration() - $this->getStartTime();
    }

    /**
     * Gets the initialization time.
     *
     * This is the time spent until the beginning of the request handling.
     *
     * @return float The elapsed time
     */
    public function getInitTime()
    {
        if (!isset($this->data['events']['__section__'])) {
            return 0;
        }

        return $this->data['events']['__section__']->getOrigin() - $this->getStartTime();
    }

    /**
     * Gets the request time.
     *
     * @return integer The time
     */
    public function getStartTime()
    {
        return $this->data['start_time'];
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'time';
    }
}
PK��Zn�--<Symfony/Component/HttpKernel/DataCollector/DataCollector.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\DataCollector;

use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter;

/**
 * DataCollector.
 *
 * Children of this class must store the collected data in the data property.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Bernhard Schussek <bschussek@symfony.com>
 */
abstract class DataCollector implements DataCollectorInterface, \Serializable
{
    protected $data;

    /**
     * @var ValueExporter
     */
    private $valueExporter;

    public function serialize()
    {
        return serialize($this->data);
    }

    public function unserialize($data)
    {
        $this->data = unserialize($data);
    }

    /**
     * Converts a PHP variable to a string.
     *
     * @param mixed $var A PHP variable
     *
     * @return string The string representation of the variable
     */
    protected function varToString($var)
    {
        if (null === $this->valueExporter) {
            $this->valueExporter = new ValueExporter();
        }

        return $this->valueExporter->exportValue($var);
    }
}
PK��Z(���;	;	BSymfony/Component/HttpKernel/DataCollector/MemoryDataCollector.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\DataCollector;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * MemoryDataCollector.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class MemoryDataCollector extends DataCollector implements LateDataCollectorInterface
{
    public function __construct()
    {
        $this->data = array(
            'memory'       => 0,
            'memory_limit' => $this->convertToBytes(ini_get('memory_limit')),
        );
    }

    /**
     * {@inheritdoc}
     */
    public function collect(Request $request, Response $response, \Exception $exception = null)
    {
        $this->updateMemoryUsage();
    }

    /**
     * {@inheritdoc}
     */
    public function lateCollect()
    {
        $this->updateMemoryUsage();
    }

    /**
     * Gets the memory.
     *
     * @return integer The memory
     */
    public function getMemory()
    {
        return $this->data['memory'];
    }

    /**
     * Gets the PHP memory limit.
     *
     * @return integer The memory limit
     */
    public function getMemoryLimit()
    {
        return $this->data['memory_limit'];
    }

    /**
     * Updates the memory usage data.
     */
    public function updateMemoryUsage()
    {
        $this->data['memory'] = memory_get_peak_usage(true);
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'memory';
    }

    private function convertToBytes($memoryLimit)
    {
        if ('-1' === $memoryLimit) {
            return -1;
        }

        $memoryLimit = strtolower($memoryLimit);
        $max = strtolower(ltrim($memoryLimit, '+'));
        if (0 === strpos($max, '0x')) {
            $max = intval($max, 16);
        } elseif (0 === strpos($max, '0')) {
            $max = intval($max, 8);
        } else {
            $max = intval($max);
        }

        switch (substr($memoryLimit, -1)) {
            case 't': $max *= 1024;
            case 'g': $max *= 1024;
            case 'm': $max *= 1024;
            case 'k': $max *= 1024;
        }

        return $max;
    }
}
PK��Z^/|GooGSymfony/Component/HttpKernel/Controller/ControllerResolverInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Controller;

use Symfony\Component\HttpFoundation\Request;

/**
 * A ControllerResolverInterface implementation knows how to determine the
 * controller to execute based on a Request object.
 *
 * It can also determine the arguments to pass to the Controller.
 *
 * A Controller can be any valid PHP callable.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface ControllerResolverInterface
{
    /**
     * Returns the Controller instance associated with a Request.
     *
     * As several resolvers can exist for a single application, a resolver must
     * return false when it is not able to determine the controller.
     *
     * The resolver must only throw an exception when it should be able to load
     * controller but cannot because of some errors made by the developer.
     *
     * @param Request $request A Request instance
     *
     * @return callable|false A PHP callable representing the Controller,
     *                        or false if this resolver is not able to determine the controller
     *
     * @throws \LogicException If the controller can't be found
     *
     * @api
     */
    public function getController(Request $request);

    /**
     * Returns the arguments to pass to the controller.
     *
     * @param Request  $request    A Request instance
     * @param callable $controller A PHP callable
     *
     * @return array An array of arguments to pass to the controller
     *
     * @throws \RuntimeException When value for argument given is not provided
     *
     * @api
     */
    public function getArguments(Request $request, $controller);
}
PK��Z��|�GSymfony/Component/HttpKernel/Controller/TraceableControllerResolver.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Controller;

use Symfony\Component\Stopwatch\Stopwatch;
use Symfony\Component\HttpFoundation\Request;

/**
 * TraceableControllerResolver.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class TraceableControllerResolver implements ControllerResolverInterface
{
    private $resolver;
    private $stopwatch;

    /**
     * Constructor.
     *
     * @param ControllerResolverInterface $resolver  A ControllerResolverInterface instance
     * @param Stopwatch                   $stopwatch A Stopwatch instance
     */
    public function __construct(ControllerResolverInterface $resolver, Stopwatch $stopwatch)
    {
        $this->resolver = $resolver;
        $this->stopwatch = $stopwatch;
    }

    /**
     * {@inheritdoc}
     */
    public function getController(Request $request)
    {
        $e = $this->stopwatch->start('controller.get_callable');

        $ret = $this->resolver->getController($request);

        $e->stop();

        return $ret;
    }

    /**
     * {@inheritdoc}
     */
    public function getArguments(Request $request, $controller)
    {
        $e = $this->stopwatch->start('controller.get_arguments');

        $ret = $this->resolver->getArguments($request, $controller);

        $e->stop();

        return $ret;
    }
}
PK��Z�xXX?Symfony/Component/HttpKernel/Controller/ControllerReference.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Controller;

/**
 * Acts as a marker and a data holder for a Controller.
 *
 * Some methods in Symfony accept both a URI (as a string) or a controller as
 * an argument. In the latter case, instead of passing an array representing
 * the controller, you can use an instance of this class.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @see Symfony\Component\HttpKernel\FragmentRenderer
 * @see Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface
 */
class ControllerReference
{
    public $controller;
    public $attributes = array();
    public $query = array();

    /**
     * Constructor.
     *
     * @param string $controller The controller name
     * @param array  $attributes An array of parameters to add to the Request attributes
     * @param array  $query      An array of parameters to add to the Request query string
     */
    public function __construct($controller, array $attributes = array(), array $query = array())
    {
        $this->controller = $controller;
        $this->attributes = $attributes;
        $this->query = $query;
    }
}
PK��ZNC��tt>Symfony/Component/HttpKernel/Controller/ControllerResolver.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Controller;

use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Request;

/**
 * ControllerResolver.
 *
 * This implementation uses the '_controller' request attribute to determine
 * the controller to execute and uses the request attributes to determine
 * the controller method arguments.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class ControllerResolver implements ControllerResolverInterface
{
    private $logger;

    /**
     * Constructor.
     *
     * @param LoggerInterface $logger A LoggerInterface instance
     */
    public function __construct(LoggerInterface $logger = null)
    {
        $this->logger = $logger;
    }

    /**
     * {@inheritdoc}
     *
     * This method looks for a '_controller' request attribute that represents
     * the controller name (a string like ClassName::MethodName).
     *
     * @api
     */
    public function getController(Request $request)
    {
        if (!$controller = $request->attributes->get('_controller')) {
            if (null !== $this->logger) {
                $this->logger->warning('Unable to look for the controller as the "_controller" parameter is missing');
            }

            return false;
        }

        if (is_array($controller)) {
            return $controller;
        }

        if (is_object($controller)) {
            if (method_exists($controller, '__invoke')) {
                return $controller;
            }

            throw new \InvalidArgumentException(sprintf('Controller "%s" for URI "%s" is not callable.', get_class($controller), $request->getPathInfo()));
        }

        if (false === strpos($controller, ':')) {
            if (method_exists($controller, '__invoke')) {
                return new $controller();
            } elseif (function_exists($controller)) {
                return $controller;
            }
        }

        $callable = $this->createController($controller);

        if (!is_callable($callable)) {
            throw new \InvalidArgumentException(sprintf('Controller "%s" for URI "%s" is not callable.', $controller, $request->getPathInfo()));
        }

        return $callable;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function getArguments(Request $request, $controller)
    {
        if (is_array($controller)) {
            $r = new \ReflectionMethod($controller[0], $controller[1]);
        } elseif (is_object($controller) && !$controller instanceof \Closure) {
            $r = new \ReflectionObject($controller);
            $r = $r->getMethod('__invoke');
        } else {
            $r = new \ReflectionFunction($controller);
        }

        return $this->doGetArguments($request, $controller, $r->getParameters());
    }

    protected function doGetArguments(Request $request, $controller, array $parameters)
    {
        $attributes = $request->attributes->all();
        $arguments = array();
        foreach ($parameters as $param) {
            if (array_key_exists($param->name, $attributes)) {
                $arguments[] = $attributes[$param->name];
            } elseif ($param->getClass() && $param->getClass()->isInstance($request)) {
                $arguments[] = $request;
            } elseif ($param->isDefaultValueAvailable()) {
                $arguments[] = $param->getDefaultValue();
            } else {
                if (is_array($controller)) {
                    $repr = sprintf('%s::%s()', get_class($controller[0]), $controller[1]);
                } elseif (is_object($controller)) {
                    $repr = get_class($controller);
                } else {
                    $repr = $controller;
                }

                throw new \RuntimeException(sprintf('Controller "%s" requires that you provide a value for the "$%s" argument (because there is no default value or because there is a non optional argument after this one).', $repr, $param->name));
            }
        }

        return $arguments;
    }

    /**
     * Returns a callable for the given controller.
     *
     * @param string $controller A Controller string
     *
     * @return mixed A PHP callable
     *
     * @throws \InvalidArgumentException
     */
    protected function createController($controller)
    {
        if (false === strpos($controller, '::')) {
            throw new \InvalidArgumentException(sprintf('Unable to find controller "%s".', $controller));
        }

        list($class, $method) = explode('::', $controller, 2);

        if (!class_exists($class)) {
            throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class));
        }

        return array(new $class(), $method);
    }
}
PK��Z;��M��>Symfony/Component/HttpKernel/DependencyInjection/Extension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\DependencyInjection;

use Symfony\Component\DependencyInjection\Extension\Extension as BaseExtension;

/**
 * Allow adding classes to the class cache.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class Extension extends BaseExtension
{
    private $classes = array();

    /**
     * Gets the classes to cache.
     *
     * @return array An array of classes
     */
    public function getClassesToCompile()
    {
        return $this->classes;
    }

    /**
     * Adds classes to the class cache.
     *
     * @param array $classes An array of classes
     */
    public function addClassesToCompile(array $classes)
    {
        $this->classes = array_merge($this->classes, $classes);
    }
}
PK��Z�6�V
V
MSymfony/Component/HttpKernel/DependencyInjection/ContainerAwareHttpKernel.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\DependencyInjection;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Scope;

/**
 * Adds a managed request scope.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ContainerAwareHttpKernel extends HttpKernel
{
    protected $container;

    /**
     * Constructor.
     *
     * @param EventDispatcherInterface    $dispatcher         An EventDispatcherInterface instance
     * @param ContainerInterface          $container          A ContainerInterface instance
     * @param ControllerResolverInterface $controllerResolver A ControllerResolverInterface instance
     * @param RequestStack                $requestStack       A stack for master/sub requests
     */
    public function __construct(EventDispatcherInterface $dispatcher, ContainerInterface $container, ControllerResolverInterface $controllerResolver, RequestStack $requestStack = null)
    {
        parent::__construct($dispatcher, $controllerResolver, $requestStack);

        $this->container = $container;

        // the request scope might have been created before (see FrameworkBundle)
        if (!$container->hasScope('request')) {
            $container->addScope(new Scope('request'));
        }
    }

    /**
     * {@inheritdoc}
     */
    public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
    {
        $request->headers->set('X-Php-Ob-Level', ob_get_level());

        $this->container->enterScope('request');
        $this->container->set('request', $request, 'request');

        try {
            $response = parent::handle($request, $type, $catch);
        } catch (\Exception $e) {
            $this->container->set('request', null, 'request');
            $this->container->leaveScope('request');

            throw $e;
        }

        $this->container->set('request', null, 'request');
        $this->container->leaveScope('request');

        return $response;
    }
}
PK��Z�k���JSymfony/Component/HttpKernel/DependencyInjection/RegisterListenersPass.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\DependencyInjection;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;

/**
 * Compiler pass to register tagged services for an event dispatcher.
 */
class RegisterListenersPass implements CompilerPassInterface
{
    /**
     * @var string
     */
    protected $dispatcherService;

    /**
     * @var string
     */
    protected $listenerTag;

    /**
     * @var string
     */
    protected $subscriberTag;

    /**
     * Constructor.
     *
     * @param string $dispatcherService Service name of the event dispatcher in processed container
     * @param string $listenerTag       Tag name used for listener
     * @param string $subscriberTag     Tag name used for subscribers
     */
    public function __construct($dispatcherService = 'event_dispatcher', $listenerTag = 'kernel.event_listener', $subscriberTag = 'kernel.event_subscriber')
    {
        $this->dispatcherService = $dispatcherService;
        $this->listenerTag = $listenerTag;
        $this->subscriberTag = $subscriberTag;
    }

    public function process(ContainerBuilder $container)
    {
        if (!$container->hasDefinition($this->dispatcherService) && !$container->hasAlias($this->dispatcherService)) {
            return;
        }

        $definition = $container->findDefinition($this->dispatcherService);

        foreach ($container->findTaggedServiceIds($this->listenerTag) as $id => $events) {
            $def = $container->getDefinition($id);
            if (!$def->isPublic()) {
                throw new \InvalidArgumentException(sprintf('The service "%s" must be public as event listeners are lazy-loaded.', $id));
            }

            if ($def->isAbstract()) {
                throw new \InvalidArgumentException(sprintf('The service "%s" must not be abstract as event listeners are lazy-loaded.', $id));
            }

            foreach ($events as $event) {
                $priority = isset($event['priority']) ? $event['priority'] : 0;

                if (!isset($event['event'])) {
                    throw new \InvalidArgumentException(sprintf('Service "%s" must define the "event" attribute on "%s" tags.', $id, $this->listenerTag));
                }

                if (!isset($event['method'])) {
                    $event['method'] = 'on'.preg_replace_callback(array(
                        '/(?<=\b)[a-z]/i',
                        '/[^a-z0-9]/i',
                    ), function ($matches) { return strtoupper($matches[0]); }, $event['event']);
                    $event['method'] = preg_replace('/[^a-z0-9]/i', '', $event['method']);
                }

                $definition->addMethodCall('addListenerService', array($event['event'], array($id, $event['method']), $priority));
            }
        }

        foreach ($container->findTaggedServiceIds($this->subscriberTag) as $id => $attributes) {
            $def = $container->getDefinition($id);
            if (!$def->isPublic()) {
                throw new \InvalidArgumentException(sprintf('The service "%s" must be public as event subscribers are lazy-loaded.', $id));
            }

            // We must assume that the class value has been correctly filled, even if the service is created by a factory
            $class = $def->getClass();

            $refClass = new \ReflectionClass($class);
            $interface = 'Symfony\Component\EventDispatcher\EventSubscriberInterface';
            if (!$refClass->implementsInterface($interface)) {
                throw new \InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, $interface));
            }

            $definition->addMethodCall('addSubscriberService', array($id, $class));
        }
    }
}
PK��Z���u__JSymfony/Component/HttpKernel/DependencyInjection/ConfigurableExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\DependencyInjection;

use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * This extension sub-class provides first-class integration with the
 * Config/Definition Component.
 *
 * You can use this as base class if you
 *
 *    a) use the Config/Definition component for configuration
 *    b) your configuration class is named "Configuration" and
 *    c) the configuration class resides in the DependencyInjection sub-folder
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
abstract class ConfigurableExtension extends Extension
{
    /**
     * {@inheritDoc}
     */
    final public function load(array $configs, ContainerBuilder $container)
    {
        $this->loadInternal($this->processConfiguration($this->getConfiguration($configs, $container), $configs), $container);
    }

    /**
     * Configures the passed container according to the merged configuration.
     *
     * @param array            $mergedConfig
     * @param ContainerBuilder $container
     */
    abstract protected function loadInternal(array $mergedConfig, ContainerBuilder $container);
}
PK��Z&!#ffTSymfony/Component/HttpKernel/DependencyInjection/MergeExtensionConfigurationPass.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\DependencyInjection;

use Symfony\Component\DependencyInjection\Compiler\MergeExtensionConfigurationPass as BaseMergeExtensionConfigurationPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * Ensures certain extensions are always loaded.
 *
 * @author Kris Wallsmith <kris@symfony.com>
 */
class MergeExtensionConfigurationPass extends BaseMergeExtensionConfigurationPass
{
    private $extensions;

    public function __construct(array $extensions)
    {
        $this->extensions = $extensions;
    }

    public function process(ContainerBuilder $container)
    {
        foreach ($this->extensions as $extension) {
            if (!count($container->getExtensionConfig($extension))) {
                $container->loadFromExtension($extension, array());
            }
        }

        parent::process($container);
    }
}
PK��ZQNR��JSymfony/Component/HttpKernel/DependencyInjection/AddClassesToCachePass.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\DependencyInjection;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\HttpKernel\Kernel;

/**
 * Sets the classes to compile in the cache for the container.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class AddClassesToCachePass implements CompilerPassInterface
{
    private $kernel;

    public function __construct(Kernel $kernel)
    {
        $this->kernel = $kernel;
    }

    /**
     * {@inheritDoc}
     */
    public function process(ContainerBuilder $container)
    {
        $classes = array();
        foreach ($container->getExtensions() as $extension) {
            if ($extension instanceof Extension) {
                $classes = array_merge($classes, $extension->getClassesToCompile());
            }
        }

        $this->kernel->setClassCache(array_unique($container->getParameterBag()->resolveValue($classes)));
    }
}
PK��Z���a��9Symfony/Component/ClassLoader/ApcUniversalClassLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\ClassLoader;

/**
 * ApcUniversalClassLoader implements a "universal" autoloader cached in APC for PHP 5.3.
 *
 * It is able to load classes that use either:
 *
 *  * The technical interoperability standards for PHP 5.3 namespaces and
 *    class names (https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md);
 *
 *  * The PEAR naming convention for classes (http://pear.php.net/).
 *
 * Classes from a sub-namespace or a sub-hierarchy of PEAR classes can be
 * looked for in a list of locations to ease the vendoring of a sub-set of
 * classes for large projects.
 *
 * Example usage:
 *
 *     require 'vendor/symfony/src/Symfony/Component/ClassLoader/UniversalClassLoader.php';
 *     require 'vendor/symfony/src/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php';
 *
 *     use Symfony\Component\ClassLoader\ApcUniversalClassLoader;
 *
 *     $loader = new ApcUniversalClassLoader('apc.prefix.');
 *
 *     // register classes with namespaces
 *     $loader->registerNamespaces(array(
 *         'Symfony\Component' => __DIR__.'/component',
 *         'Symfony'           => __DIR__.'/framework',
 *         'Sensio'            => array(__DIR__.'/src', __DIR__.'/vendor'),
 *     ));
 *
 *     // register a library using the PEAR naming convention
 *     $loader->registerPrefixes(array(
 *         'Swift_' => __DIR__.'/Swift',
 *     ));
 *
 *     // activate the autoloader
 *     $loader->register();
 *
 * In this example, if you try to use a class in the Symfony\Component
 * namespace or one of its children (Symfony\Component\Console for instance),
 * the autoloader will first look for the class under the component/
 * directory, and it will then fallback to the framework/ directory if not
 * found before giving up.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Kris Wallsmith <kris@symfony.com>
 *
 * @api
 */
class ApcUniversalClassLoader extends UniversalClassLoader
{
    private $prefix;

    /**
     * Constructor.
     *
     * @param string $prefix A prefix to create a namespace in APC
     *
     * @throws \RuntimeException
     *
     * @api
     */
    public function __construct($prefix)
    {
        if (!extension_loaded('apc')) {
            throw new \RuntimeException('Unable to use ApcUniversalClassLoader as APC is not enabled.');
        }

        $this->prefix = $prefix;
    }

    /**
     * Finds a file by class name while caching lookups to APC.
     *
     * @param string $class A class name to resolve to file
     *
     * @return string|null The path, if found
     */
    public function findFile($class)
    {
        if (false === $file = apc_fetch($this->prefix.$class)) {
            apc_store($this->prefix.$class, $file = parent::findFile($class));
        }

        return $file;
    }
}
PK��Z��PЩ
�
3Symfony/Component/ClassLoader/XcacheClassLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\ClassLoader;

/**
 * XcacheClassLoader implements a wrapping autoloader cached in Xcache for PHP 5.3.
 *
 * It expects an object implementing a findFile method to find the file. This
 * allows using it as a wrapper around the other loaders of the component (the
 * ClassLoader and the UniversalClassLoader for instance) but also around any
 * other autoloader following this convention (the Composer one for instance)
 *
 *     $loader = new ClassLoader();
 *
 *     // register classes with namespaces
 *     $loader->add('Symfony\Component', __DIR__.'/component');
 *     $loader->add('Symfony',           __DIR__.'/framework');
 *
 *     $cachedLoader = new XcacheClassLoader('my_prefix', $loader);
 *
 *     // activate the cached autoloader
 *     $cachedLoader->register();
 *
 *     // eventually deactivate the non-cached loader if it was registered previously
 *     // to be sure to use the cached one.
 *     $loader->unregister();
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Kris Wallsmith <kris@symfony.com>
 * @author Kim Hemsø Rasmussen <kimhemsoe@gmail.com>
 *
 * @api
 */
class XcacheClassLoader
{
    private $prefix;
    private $classFinder;

    /**
     * Constructor.
     *
     * @param string $prefix      A prefix to create a namespace in Xcache
     * @param object $classFinder An object that implements findFile() method.
     *
     * @throws \RuntimeException
     * @throws \InvalidArgumentException
     *
     * @api
     */
    public function __construct($prefix, $classFinder)
    {
        if (!extension_loaded('Xcache')) {
            throw new \RuntimeException('Unable to use XcacheClassLoader as Xcache is not enabled.');
        }

        if (!method_exists($classFinder, 'findFile')) {
            throw new \InvalidArgumentException('The class finder must implement a "findFile" method.');
        }

        $this->prefix = $prefix;
        $this->classFinder = $classFinder;
    }

    /**
     * Registers this instance as an autoloader.
     *
     * @param Boolean $prepend Whether to prepend the autoloader or not
     */
    public function register($prepend = false)
    {
        spl_autoload_register(array($this, 'loadClass'), true, $prepend);
    }

    /**
     * Unregisters this instance as an autoloader.
     */
    public function unregister()
    {
        spl_autoload_unregister(array($this, 'loadClass'));
    }

    /**
     * Loads the given class or interface.
     *
     * @param string $class The name of the class
     *
     * @return Boolean|null True, if loaded
     */
    public function loadClass($class)
    {
        if ($file = $this->findFile($class)) {
            require $file;

            return true;
        }
    }

    /**
     * Finds a file by class name while caching lookups to Xcache.
     *
     * @param string $class A class name to resolve to file
     *
     * @return string|null
     */
    public function findFile($class)
    {
        if (xcache_isset($this->prefix.$class)) {
            $file = xcache_get($this->prefix.$class);
        } else {
            $file = $this->classFinder->findFile($class);
            xcache_set($this->prefix.$class, $file);
        }

        return $file;
    }
}
PK��Z"�K�UU,Symfony/Component/ClassLoader/autoloader.phpnu�[���<?php

spl_autoload_register(function ($class) {
    if ('\\' == $class[0]) {
        $class = substr($class, 1);
    }

    if (
        0 === strpos($class, 'Symfony\\Component\\ClassLoader\\')
        &&
        file_exists($file = __DIR__.'/../../../'.str_replace('\\', '/', $class).'.php')
    ) {
        require_once $file;
    }
});
PK��Z��A���0Symfony/Component/ClassLoader/MapClassLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\ClassLoader;

/**
 * A class loader that uses a mapping file to look up paths.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class MapClassLoader
{
    private $map = array();

    /**
     * Constructor.
     *
     * @param array $map A map where keys are classes and values the absolute file path
     */
    public function __construct(array $map)
    {
        $this->map = $map;
    }

    /**
     * Registers this instance as an autoloader.
     *
     * @param Boolean $prepend Whether to prepend the autoloader or not
     */
    public function register($prepend = false)
    {
        spl_autoload_register(array($this, 'loadClass'), true, $prepend);
    }

    /**
     * Loads the given class or interface.
     *
     * @param string $class The name of the class
     */
    public function loadClass($class)
    {
        if (isset($this->map[$class])) {
            require $this->map[$class];
        }
    }

    /**
     * Finds the path to the file where the class is defined.
     *
     * @param string $class The name of the class
     *
     * @return string|null The path, if found
     */
    public function findFile($class)
    {
        if (isset($this->map[$class])) {
            return $this->map[$class];
        }
    }
}
PK��Zw�!�));Symfony/Component/ClassLoader/DebugUniversalClassLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\ClassLoader;

/**
 * Checks that the class is actually declared in the included file.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class DebugUniversalClassLoader extends UniversalClassLoader
{
    /**
     * Replaces all regular UniversalClassLoader instances by a DebugUniversalClassLoader ones.
     */
    public static function enable()
    {
        if (!is_array($functions = spl_autoload_functions())) {
            return;
        }

        foreach ($functions as $function) {
            spl_autoload_unregister($function);
        }

        foreach ($functions as $function) {
            if (is_array($function) && $function[0] instanceof UniversalClassLoader) {
                $loader = new static();
                $loader->registerNamespaceFallbacks($function[0]->getNamespaceFallbacks());
                $loader->registerPrefixFallbacks($function[0]->getPrefixFallbacks());
                $loader->registerNamespaces($function[0]->getNamespaces());
                $loader->registerPrefixes($function[0]->getPrefixes());
                $loader->useIncludePath($function[0]->getUseIncludePath());

                $function[0] = $loader;
            }

            spl_autoload_register($function);
        }
    }

    /**
     * {@inheritDoc}
     */
    public function loadClass($class)
    {
        if ($file = $this->findFile($class)) {
            require $file;

            if (!class_exists($class, false) && !interface_exists($class, false) && (!function_exists('trait_exists') || !trait_exists($class, false))) {
                throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file));
            }
        }
    }
}
PK��Z�v�	.	.7Symfony/Component/ClassLoader/ClassCollectionLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\ClassLoader;

/**
 * ClassCollectionLoader.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ClassCollectionLoader
{
    private static $loaded;
    private static $seen;
    private static $useTokenizer = true;

    /**
     * Loads a list of classes and caches them in one big file.
     *
     * @param array   $classes    An array of classes to load
     * @param string  $cacheDir   A cache directory
     * @param string  $name       The cache name prefix
     * @param Boolean $autoReload Whether to flush the cache when the cache is stale or not
     * @param Boolean $adaptive   Whether to remove already declared classes or not
     * @param string  $extension  File extension of the resulting file
     *
     * @throws \InvalidArgumentException When class can't be loaded
     */
    public static function load($classes, $cacheDir, $name, $autoReload, $adaptive = false, $extension = '.php')
    {
        // each $name can only be loaded once per PHP process
        if (isset(self::$loaded[$name])) {
            return;
        }

        self::$loaded[$name] = true;

        $declared = array_merge(get_declared_classes(), get_declared_interfaces());
        if (function_exists('get_declared_traits')) {
            $declared = array_merge($declared, get_declared_traits());
        }

        if ($adaptive) {
            // don't include already declared classes
            $classes = array_diff($classes, $declared);

            // the cache is different depending on which classes are already declared
            $name = $name.'-'.substr(hash('sha256', implode('|', $classes)), 0, 5);
        }

        $classes = array_unique($classes);

        $cache = $cacheDir.'/'.$name.$extension;

        // auto-reload
        $reload = false;
        if ($autoReload) {
            $metadata = $cache.'.meta';
            if (!is_file($metadata) || !is_file($cache)) {
                $reload = true;
            } else {
                $time = filemtime($cache);
                $meta = unserialize(file_get_contents($metadata));

                sort($meta[1]);
                sort($classes);

                if ($meta[1] != $classes) {
                    $reload = true;
                } else {
                    foreach ($meta[0] as $resource) {
                        if (!is_file($resource) || filemtime($resource) > $time) {
                            $reload = true;

                            break;
                        }
                    }
                }
            }
        }

        if (!$reload && is_file($cache)) {
            require_once $cache;

            return;
        }

        $files = array();
        $content = '';
        foreach (self::getOrderedClasses($classes) as $class) {
            if (in_array($class->getName(), $declared)) {
                continue;
            }

            $files[] = $class->getFileName();

            $c = preg_replace(array('/^\s*<\?php/', '/\?>\s*$/'), '', file_get_contents($class->getFileName()));

            // fakes namespace declaration for global code
            if (!$class->inNamespace()) {
                $c = "\nnamespace\n{\n".$c."\n}\n";
            }

            $c = self::fixNamespaceDeclarations('<?php '.$c);
            $c = preg_replace('/^\s*<\?php/', '', $c);

            $content .= $c;
        }

        // cache the core classes
        if (!is_dir(dirname($cache))) {
            mkdir(dirname($cache), 0777, true);
        }
        self::writeCacheFile($cache, '<?php '.$content);

        if ($autoReload) {
            // save the resources
            self::writeCacheFile($metadata, serialize(array($files, $classes)));
        }
    }

    /**
     * Adds brackets around each namespace if it's not already the case.
     *
     * @param string $source Namespace string
     *
     * @return string Namespaces with brackets
     */
    public static function fixNamespaceDeclarations($source)
    {
        if (!function_exists('token_get_all') || !self::$useTokenizer) {
            if (preg_match('/namespace(.*?)\s*;/', $source)) {
                $source = preg_replace('/namespace(.*?)\s*;/', "namespace$1\n{", $source)."}\n";
            }

            return $source;
        }

        $rawChunk = '';
        $output = '';
        $inNamespace = false;
        $tokens = token_get_all($source);

        for (reset($tokens); false !== $token = current($tokens); next($tokens)) {
            if (is_string($token)) {
                $rawChunk .= $token;
            } elseif (in_array($token[0], array(T_COMMENT, T_DOC_COMMENT))) {
                // strip comments
                continue;
            } elseif (T_NAMESPACE === $token[0]) {
                if ($inNamespace) {
                    $rawChunk .= "}\n";
                }
                $rawChunk .= $token[1];

                // namespace name and whitespaces
                while (($t = next($tokens)) && is_array($t) && in_array($t[0], array(T_WHITESPACE, T_NS_SEPARATOR, T_STRING))) {
                    $rawChunk .= $t[1];
                }
                if ('{' === $t) {
                    $inNamespace = false;
                    prev($tokens);
                } else {
                    $rawChunk = rtrim($rawChunk)."\n{";
                    $inNamespace = true;
                }
            } elseif (T_START_HEREDOC === $token[0]) {
                $output .= self::compressCode($rawChunk).$token[1];
                do {
                    $token = next($tokens);
                    $output .= is_string($token) ? $token : $token[1];
                } while ($token[0] !== T_END_HEREDOC);
                $output .= "\n";
                $rawChunk = '';
            } elseif (T_CONSTANT_ENCAPSED_STRING === $token[0]) {
                $output .= self::compressCode($rawChunk).$token[1];
                $rawChunk = '';
            } else {
                $rawChunk .= $token[1];
            }
        }

        if ($inNamespace) {
            $rawChunk .= "}\n";
        }

        return $output.self::compressCode($rawChunk);
    }

    /**
     * This method is only useful for testing.
     */
    public static function enableTokenizer($bool)
    {
        self::$useTokenizer = (Boolean) $bool;
    }

    /**
     * Strips leading & trailing ws, multiple EOL, multiple ws.
     *
     * @param string $code Original PHP code
     *
     * @return string compressed code
     */
    private static function compressCode($code)
    {
        return preg_replace(
            array('/^\s+/m', '/\s+$/m', '/([\n\r]+ *[\n\r]+)+/', '/[ \t]+/'),
            array('', '', "\n", ' '),
            $code
        );
    }

    /**
     * Writes a cache file.
     *
     * @param string $file    Filename
     * @param string $content Temporary file content
     *
     * @throws \RuntimeException when a cache file cannot be written
     */
    private static function writeCacheFile($file, $content)
    {
        $tmpFile = tempnam(dirname($file), basename($file));
        if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $file)) {
            @chmod($file, 0666 & ~umask());

            return;
        }

        throw new \RuntimeException(sprintf('Failed to write cache file "%s".', $file));
    }

    /**
     * Gets an ordered array of passed classes including all their dependencies.
     *
     * @param array $classes
     *
     * @return \ReflectionClass[] An array of sorted \ReflectionClass instances (dependencies added if needed)
     *
     * @throws \InvalidArgumentException When a class can't be loaded
     */
    private static function getOrderedClasses(array $classes)
    {
        $map = array();
        self::$seen = array();
        foreach ($classes as $class) {
            try {
                $reflectionClass = new \ReflectionClass($class);
            } catch (\ReflectionException $e) {
                throw new \InvalidArgumentException(sprintf('Unable to load class "%s"', $class));
            }

            $map = array_merge($map, self::getClassHierarchy($reflectionClass));
        }

        return $map;
    }

    private static function getClassHierarchy(\ReflectionClass $class)
    {
        if (isset(self::$seen[$class->getName()])) {
            return array();
        }

        self::$seen[$class->getName()] = true;

        $classes = array($class);
        $parent = $class;
        while (($parent = $parent->getParentClass()) && $parent->isUserDefined() && !isset(self::$seen[$parent->getName()])) {
            self::$seen[$parent->getName()] = true;

            array_unshift($classes, $parent);
        }

        $traits = array();

        if (function_exists('get_declared_traits')) {
            foreach ($classes as $c) {
                foreach (self::resolveDependencies(self::computeTraitDeps($c), $c) as $trait) {
                    if ($trait !== $c) {
                        $traits[] = $trait;
                    }
                }
            }
        }

        return array_merge(self::getInterfaces($class), $traits, $classes);
    }

    private static function getInterfaces(\ReflectionClass $class)
    {
        $classes = array();

        foreach ($class->getInterfaces() as $interface) {
            $classes = array_merge($classes, self::getInterfaces($interface));
        }

        if ($class->isUserDefined() && $class->isInterface() && !isset(self::$seen[$class->getName()])) {
            self::$seen[$class->getName()] = true;

            $classes[] = $class;
        }

        return $classes;
    }

    private static function computeTraitDeps(\ReflectionClass $class)
    {
        $traits = $class->getTraits();
        $deps = array($class->getName() => $traits);
        while ($trait = array_pop($traits)) {
            if ($trait->isUserDefined() && !isset(self::$seen[$trait->getName()])) {
                self::$seen[$trait->getName()] = true;
                $traitDeps = $trait->getTraits();
                $deps[$trait->getName()] = $traitDeps;
                $traits = array_merge($traits, $traitDeps);
            }
        }

        return $deps;
    }

    /**
     * Dependencies resolution.
     *
     * This function does not check for circular dependencies as it should never
     * occur with PHP traits.
     *
     * @param array             $tree       The dependency tree
     * @param \ReflectionClass  $node       The node
     * @param \ArrayObject      $resolved   An array of already resolved dependencies
     * @param \ArrayObject      $unresolved An array of dependencies to be resolved
     *
     * @return \ArrayObject The dependencies for the given node
     *
     * @throws \RuntimeException if a circular dependency is detected
     */
    private static function resolveDependencies(array $tree, $node, \ArrayObject $resolved = null, \ArrayObject $unresolved = null)
    {
        if (null === $resolved) {
            $resolved = new \ArrayObject();
        }
        if (null === $unresolved) {
            $unresolved = new \ArrayObject();
        }
        $nodeName = $node->getName();
        $unresolved[$nodeName] = $node;
        foreach ($tree[$nodeName] as $dependency) {
            if (!$resolved->offsetExists($dependency->getName())) {
                self::resolveDependencies($tree, $dependency, $resolved, $unresolved);
            }
        }
        $resolved[$nodeName] = $node;
        unset($unresolved[$nodeName]);

        return $resolved;
    }
}
PK��Z�a.e"e"6Symfony/Component/ClassLoader/UniversalClassLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\ClassLoader;

/**
 * UniversalClassLoader implements a "universal" autoloader for PHP 5.3.
 *
 * It is able to load classes that use either:
 *
 *  * The technical interoperability standards for PHP 5.3 namespaces and
 *    class names (https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md);
 *
 *  * The PEAR naming convention for classes (http://pear.php.net/).
 *
 * Classes from a sub-namespace or a sub-hierarchy of PEAR classes can be
 * looked for in a list of locations to ease the vendoring of a sub-set of
 * classes for large projects.
 *
 * Example usage:
 *
 *     $loader = new UniversalClassLoader();
 *
 *     // register classes with namespaces
 *     $loader->registerNamespaces(array(
 *         'Symfony\Component' => __DIR__.'/component',
 *         'Symfony'           => __DIR__.'/framework',
 *         'Sensio'            => array(__DIR__.'/src', __DIR__.'/vendor'),
 *     ));
 *
 *     // register a library using the PEAR naming convention
 *     $loader->registerPrefixes(array(
 *         'Swift_' => __DIR__.'/Swift',
 *     ));
 *
 *
 *     // to enable searching the include path (e.g. for PEAR packages)
 *     $loader->useIncludePath(true);
 *
 *     // activate the autoloader
 *     $loader->register();
 *
 * In this example, if you try to use a class in the Symfony\Component
 * namespace or one of its children (Symfony\Component\Console for instance),
 * the autoloader will first look for the class under the component/
 * directory, and it will then fallback to the framework/ directory if not
 * found before giving up.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class UniversalClassLoader
{
    private $namespaces = array();
    private $prefixes = array();
    private $namespaceFallbacks = array();
    private $prefixFallbacks = array();
    private $useIncludePath = false;

    /**
     * Turns on searching the include for class files. Allows easy loading
     * of installed PEAR packages
     *
     * @param Boolean $useIncludePath
     */
    public function useIncludePath($useIncludePath)
    {
        $this->useIncludePath = $useIncludePath;
    }

    /**
     * Can be used to check if the autoloader uses the include path to check
     * for classes.
     *
     * @return Boolean
     */
    public function getUseIncludePath()
    {
        return $this->useIncludePath;
    }

    /**
     * Gets the configured namespaces.
     *
     * @return array A hash with namespaces as keys and directories as values
     */
    public function getNamespaces()
    {
        return $this->namespaces;
    }

    /**
     * Gets the configured class prefixes.
     *
     * @return array A hash with class prefixes as keys and directories as values
     */
    public function getPrefixes()
    {
        return $this->prefixes;
    }

    /**
     * Gets the directory(ies) to use as a fallback for namespaces.
     *
     * @return array An array of directories
     */
    public function getNamespaceFallbacks()
    {
        return $this->namespaceFallbacks;
    }

    /**
     * Gets the directory(ies) to use as a fallback for class prefixes.
     *
     * @return array An array of directories
     */
    public function getPrefixFallbacks()
    {
        return $this->prefixFallbacks;
    }

    /**
     * Registers the directory to use as a fallback for namespaces.
     *
     * @param array $dirs An array of directories
     *
     * @api
     */
    public function registerNamespaceFallbacks(array $dirs)
    {
        $this->namespaceFallbacks = $dirs;
    }

    /**
     * Registers a directory to use as a fallback for namespaces.
     *
     * @param string $dir A directory
     */
    public function registerNamespaceFallback($dir)
    {
        $this->namespaceFallbacks[] = $dir;
    }

    /**
     * Registers directories to use as a fallback for class prefixes.
     *
     * @param array $dirs An array of directories
     *
     * @api
     */
    public function registerPrefixFallbacks(array $dirs)
    {
        $this->prefixFallbacks = $dirs;
    }

    /**
     * Registers a directory to use as a fallback for class prefixes.
     *
     * @param string $dir A directory
     */
    public function registerPrefixFallback($dir)
    {
        $this->prefixFallbacks[] = $dir;
    }

    /**
     * Registers an array of namespaces
     *
     * @param array $namespaces An array of namespaces (namespaces as keys and locations as values)
     *
     * @api
     */
    public function registerNamespaces(array $namespaces)
    {
        foreach ($namespaces as $namespace => $locations) {
            $this->namespaces[$namespace] = (array) $locations;
        }
    }

    /**
     * Registers a namespace.
     *
     * @param string       $namespace The namespace
     * @param array|string $paths     The location(s) of the namespace
     *
     * @api
     */
    public function registerNamespace($namespace, $paths)
    {
        $this->namespaces[$namespace] = (array) $paths;
    }

    /**
     * Registers an array of classes using the PEAR naming convention.
     *
     * @param array $classes An array of classes (prefixes as keys and locations as values)
     *
     * @api
     */
    public function registerPrefixes(array $classes)
    {
        foreach ($classes as $prefix => $locations) {
            $this->prefixes[$prefix] = (array) $locations;
        }
    }

    /**
     * Registers a set of classes using the PEAR naming convention.
     *
     * @param string       $prefix The classes prefix
     * @param array|string $paths  The location(s) of the classes
     *
     * @api
     */
    public function registerPrefix($prefix, $paths)
    {
        $this->prefixes[$prefix] = (array) $paths;
    }

    /**
     * Registers this instance as an autoloader.
     *
     * @param Boolean $prepend Whether to prepend the autoloader or not
     *
     * @api
     */
    public function register($prepend = false)
    {
        spl_autoload_register(array($this, 'loadClass'), true, $prepend);
    }

    /**
     * Loads the given class or interface.
     *
     * @param string $class The name of the class
     *
     * @return Boolean|null True, if loaded
     */
    public function loadClass($class)
    {
        if ($file = $this->findFile($class)) {
            require $file;

            return true;
        }
    }

    /**
     * Finds the path to the file where the class is defined.
     *
     * @param string $class The name of the class
     *
     * @return string|null The path, if found
     */
    public function findFile($class)
    {
        if (false !== $pos = strrpos($class, '\\')) {
            // namespaced class name
            $namespace = substr($class, 0, $pos);
            $className = substr($class, $pos + 1);
            $normalizedClass = str_replace('\\', DIRECTORY_SEPARATOR, $namespace).DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $className).'.php';
            foreach ($this->namespaces as $ns => $dirs) {
                if (0 !== strpos($namespace, $ns)) {
                    continue;
                }

                foreach ($dirs as $dir) {
                    $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass;
                    if (is_file($file)) {
                        return $file;
                    }
                }
            }

            foreach ($this->namespaceFallbacks as $dir) {
                $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass;
                if (is_file($file)) {
                    return $file;
                }
            }

        } else {
            // PEAR-like class name
            $normalizedClass = str_replace('_', DIRECTORY_SEPARATOR, $class).'.php';
            foreach ($this->prefixes as $prefix => $dirs) {
                if (0 !== strpos($class, $prefix)) {
                    continue;
                }

                foreach ($dirs as $dir) {
                    $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass;
                    if (is_file($file)) {
                        return $file;
                    }
                }
            }

            foreach ($this->prefixFallbacks as $dir) {
                $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass;
                if (is_file($file)) {
                    return $file;
                }
            }
        }

        if ($this->useIncludePath && $file = stream_resolve_include_path($normalizedClass)) {
            return $file;
        }
    }
}
PK��Z��S�

2Symfony/Component/ClassLoader/DebugClassLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\ClassLoader;

/**
 * Autoloader checking if the class is really defined in the file found.
 *
 * The DebugClassLoader will wrap all registered autoloaders providing a
 * findFile method and will throw an exception if a file is found but does
 * not declare the class.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Christophe Coevoet <stof@notk.org>
 *
 * @api
 *
 * @deprecated Deprecated since version 2.4, to be removed in 3.0. Use the DebugClassLoader provided by the Debug component instead.
 */
class DebugClassLoader
{
    private $classFinder;

    /**
     * Constructor.
     *
     * @param object $classFinder
     *
     * @api
     */
    public function __construct($classFinder)
    {
        $this->classFinder = $classFinder;
    }

    /**
     * Gets the wrapped class loader.
     *
     * @return object a class loader instance
     */
    public function getClassLoader()
    {
        return $this->classFinder;
    }

    /**
     * Replaces all autoloaders implementing a findFile method by a DebugClassLoader wrapper.
     */
    public static function enable()
    {
        if (!is_array($functions = spl_autoload_functions())) {
            return;
        }

        foreach ($functions as $function) {
            spl_autoload_unregister($function);
        }

        foreach ($functions as $function) {
            if (is_array($function) && !$function[0] instanceof self && method_exists($function[0], 'findFile')) {
                $function = array(new static($function[0]), 'loadClass');
            }

            spl_autoload_register($function);
        }
    }

    /**
     * Unregisters this instance as an autoloader.
     */
    public function unregister()
    {
        spl_autoload_unregister(array($this, 'loadClass'));
    }

    /**
     * Finds a file by class name
     *
     * @param string $class A class name to resolve to file
     *
     * @return string|null
     */
    public function findFile($class)
    {
        return $this->classFinder->findFile($class);
    }

    /**
     * Loads the given class or interface.
     *
     * @param string $class The name of the class
     *
     * @return Boolean|null True, if loaded
     *
     * @throws \RuntimeException
     */
    public function loadClass($class)
    {
        if ($file = $this->classFinder->findFile($class)) {
            require $file;

            if (!class_exists($class, false) && !interface_exists($class, false) && (!function_exists('trait_exists') || !trait_exists($class, false))) {
                if (false !== strpos($class, '/')) {
                    throw new \RuntimeException(sprintf('Trying to autoload a class with an invalid name "%s". Be careful that the namespace separator is "\" in PHP, not "/".', $class));
                }

                throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file));
            }

            return true;
        }
    }
}
PK��Z��O���5Symfony/Component/ClassLoader/WinCacheClassLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\ClassLoader;

/**
 * WinCacheClassLoader implements a wrapping autoloader cached in WinCache.
 *
 * It expects an object implementing a findFile method to find the file. This
 * allow using it as a wrapper around the other loaders of the component (the
 * ClassLoader and the UniversalClassLoader for instance) but also around any
 * other autoloader following this convention (the Composer one for instance)
 *
 *     $loader = new ClassLoader();
 *
 *     // register classes with namespaces
 *     $loader->add('Symfony\Component', __DIR__.'/component');
 *     $loader->add('Symfony',           __DIR__.'/framework');
 *
 *     $cachedLoader = new WinCacheClassLoader('my_prefix', $loader);
 *
 *     // activate the cached autoloader
 *     $cachedLoader->register();
 *
 *     // eventually deactivate the non-cached loader if it was registered previously
 *     // to be sure to use the cached one.
 *     $loader->unregister();
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Kris Wallsmith <kris@symfony.com>
 * @author Artem Ryzhkov <artem@smart-core.org>
 */
class WinCacheClassLoader
{
    private $prefix;

    /**
     * The class loader object being decorated.
     *
     * @var \Symfony\Component\ClassLoader\ClassLoader
     *   A class loader object that implements the findFile() method.
     */
    protected $decorated;

    /**
     * Constructor.
     *
     * @param string $prefix      The WinCache namespace prefix to use.
     * @param object $decorated   A class loader object that implements the findFile() method.
     *
     * @throws \RuntimeException
     * @throws \InvalidArgumentException
     */
    public function __construct($prefix, $decorated)
    {
        if (!extension_loaded('wincache')) {
            throw new \RuntimeException('Unable to use WinCacheClassLoader as WinCache is not enabled.');
        }

        if (!method_exists($decorated, 'findFile')) {
            throw new \InvalidArgumentException('The class finder must implement a "findFile" method.');
        }

        $this->prefix = $prefix;
        $this->decorated = $decorated;
    }

    /**
     * Registers this instance as an autoloader.
     *
     * @param Boolean $prepend Whether to prepend the autoloader or not
     */
    public function register($prepend = false)
    {
        spl_autoload_register(array($this, 'loadClass'), true, $prepend);
    }

    /**
     * Unregisters this instance as an autoloader.
     */
    public function unregister()
    {
        spl_autoload_unregister(array($this, 'loadClass'));
    }

    /**
     * Loads the given class or interface.
     *
     * @param string $class The name of the class
     *
     * @return Boolean|null True, if loaded
     */
    public function loadClass($class)
    {
        if ($file = $this->findFile($class)) {
            require $file;

            return true;
        }
    }

    /**
     * Finds a file by class name while caching lookups to WinCache.
     *
     * @param string $class A class name to resolve to file
     *
     * @return string|null
     */
    public function findFile($class)
    {
        if (false === $file = wincache_ucache_get($this->prefix.$class)) {
            wincache_ucache_set($this->prefix.$class, $file = $this->decorated->findFile($class), 0);
        }

        return $file;
    }

    /**
     * Passes through all unknown calls onto the decorated object.
     */
    public function __call($method, $args)
    {
        return call_user_func_array(array($this->decorated, $method), $args);
    }
}
PK��Z�?wy�
�
3Symfony/Component/ClassLoader/ClassMapGenerator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\ClassLoader;

/**
 * ClassMapGenerator
 *
 * @author Gyula Sallai <salla016@gmail.com>
 */
class ClassMapGenerator
{
    /**
     * Generate a class map file
     *
     * @param array|string $dirs Directories or a single path to search in
     * @param string       $file The name of the class map file
     */
    public static function dump($dirs, $file)
    {
        $dirs = (array) $dirs;
        $maps = array();

        foreach ($dirs as $dir) {
            $maps = array_merge($maps, static::createMap($dir));
        }

        file_put_contents($file, sprintf('<?php return %s;', var_export($maps, true)));
    }

    /**
     * Iterate over all files in the given directory searching for classes
     *
     * @param \Iterator|string $dir The directory to search in or an iterator
     *
     * @return array A class map array
     */
    public static function createMap($dir)
    {
        if (is_string($dir)) {
            $dir = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir));
        }

        $map = array();

        foreach ($dir as $file) {
            if (!$file->isFile()) {
                continue;
            }

            $path = $file->getRealPath();

            if (pathinfo($path, PATHINFO_EXTENSION) !== 'php') {
                continue;
            }

            $classes = self::findClasses($path);

            foreach ($classes as $class) {
                $map[$class] = $path;
            }

        }

        return $map;
    }

    /**
     * Extract the classes in the given file
     *
     * @param string $path The file to check
     *
     * @return array The found classes
     */
    private static function findClasses($path)
    {
        $contents = file_get_contents($path);
        $tokens   = token_get_all($contents);
        $T_TRAIT  = version_compare(PHP_VERSION, '5.4', '<') ? -1 : T_TRAIT;

        $classes = array();

        $namespace = '';
        for ($i = 0, $max = count($tokens); $i < $max; $i++) {
            $token = $tokens[$i];

            if (is_string($token)) {
                continue;
            }

            $class = '';

            switch ($token[0]) {
                case T_NAMESPACE:
                    $namespace = '';
                    // If there is a namespace, extract it
                    while (($t = $tokens[++$i]) && is_array($t)) {
                        if (in_array($t[0], array(T_STRING, T_NS_SEPARATOR))) {
                            $namespace .= $t[1];
                        }
                    }
                    $namespace .= '\\';
                    break;
                case T_CLASS:
                case T_INTERFACE:
                case $T_TRAIT:
                    // Find the classname
                    while (($t = $tokens[++$i]) && is_array($t)) {
                        if (T_STRING === $t[0]) {
                            $class .= $t[1];
                        } elseif ($class !== '' && T_WHITESPACE == $t[0]) {
                            break;
                        }
                    }

                    $classes[] = ltrim($namespace.$class, '\\');
                    break;
                default:
                    break;
            }
        }

        return $classes;
    }
}
PK��ZlO�ݫ�0Symfony/Component/ClassLoader/ApcClassLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\ClassLoader;

/**
 * ApcClassLoader implements a wrapping autoloader cached in APC for PHP 5.3.
 *
 * It expects an object implementing a findFile method to find the file. This
 * allow using it as a wrapper around the other loaders of the component (the
 * ClassLoader and the UniversalClassLoader for instance) but also around any
 * other autoloader following this convention (the Composer one for instance)
 *
 *     $loader = new ClassLoader();
 *
 *     // register classes with namespaces
 *     $loader->add('Symfony\Component', __DIR__.'/component');
 *     $loader->add('Symfony',           __DIR__.'/framework');
 *
 *     $cachedLoader = new ApcClassLoader('my_prefix', $loader);
 *
 *     // activate the cached autoloader
 *     $cachedLoader->register();
 *
 *     // eventually deactivate the non-cached loader if it was registered previously
 *     // to be sure to use the cached one.
 *     $loader->unregister();
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Kris Wallsmith <kris@symfony.com>
 *
 * @api
 */
class ApcClassLoader
{
    private $prefix;

    /**
     * The class loader object being decorated.
     *
     * @var \Symfony\Component\ClassLoader\ClassLoader
     *   A class loader object that implements the findFile() method.
     */
    protected $decorated;

    /**
     * Constructor.
     *
     * @param string $prefix      The APC namespace prefix to use.
     * @param object $decorated   A class loader object that implements the findFile() method.
     *
     * @throws \RuntimeException
     * @throws \InvalidArgumentException
     *
     * @api
     */
    public function __construct($prefix, $decorated)
    {
        if (!extension_loaded('apc')) {
            throw new \RuntimeException('Unable to use ApcClassLoader as APC is not enabled.');
        }

        if (!method_exists($decorated, 'findFile')) {
            throw new \InvalidArgumentException('The class finder must implement a "findFile" method.');
        }

        $this->prefix = $prefix;
        $this->decorated = $decorated;
    }

    /**
     * Registers this instance as an autoloader.
     *
     * @param Boolean $prepend Whether to prepend the autoloader or not
     */
    public function register($prepend = false)
    {
        spl_autoload_register(array($this, 'loadClass'), true, $prepend);
    }

    /**
     * Unregisters this instance as an autoloader.
     */
    public function unregister()
    {
        spl_autoload_unregister(array($this, 'loadClass'));
    }

    /**
     * Loads the given class or interface.
     *
     * @param string $class The name of the class
     *
     * @return Boolean|null True, if loaded
     */
    public function loadClass($class)
    {
        if ($file = $this->findFile($class)) {
            require $file;

            return true;
        }
    }

    /**
     * Finds a file by class name while caching lookups to APC.
     *
     * @param string $class A class name to resolve to file
     *
     * @return string|null
     */
    public function findFile($class)
    {
        if (false === $file = apc_fetch($this->prefix.$class)) {
            apc_store($this->prefix.$class, $file = $this->decorated->findFile($class));
        }

        return $file;
    }

    /**
     * Passes through all unknown calls onto the decorated object.
     */
    public function __call($method, $args)
    {
        return call_user_func_array(array($this->decorated, $method), $args);
    }

}
PK��Zv��'��-Symfony/Component/ClassLoader/ClassLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\ClassLoader;

/**
 * ClassLoader implements an PSR-0 class loader
 *
 * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
 *
 *     $loader = new ClassLoader();
 *
 *     // register classes with namespaces
 *     $loader->addPrefix('Symfony\Component', __DIR__.'/component');
 *     $loader->addPrefix('Symfony',           __DIR__.'/framework');
 *
 *     // activate the autoloader
 *     $loader->register();
 *
 *     // to enable searching the include path (e.g. for PEAR packages)
 *     $loader->setUseIncludePath(true);
 *
 * In this example, if you try to use a class in the Symfony\Component
 * namespace or one of its children (Symfony\Component\Console for instance),
 * the autoloader will first look for the class under the component/
 * directory, and it will then fallback to the framework/ directory if not
 * found before giving up.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class ClassLoader
{
    private $prefixes = array();
    private $fallbackDirs = array();
    private $useIncludePath = false;

    /**
     * Returns prefixes.
     *
     * @return array
     */
    public function getPrefixes()
    {
        return $this->prefixes;
    }

    /**
     * Returns fallback directories.
     *
     * @return array
     */
    public function getFallbackDirs()
    {
        return $this->fallbackDirs;
    }

    /**
     * Adds prefixes.
     *
     * @param array $prefixes Prefixes to add
     */
    public function addPrefixes(array $prefixes)
    {
        foreach ($prefixes as $prefix => $path) {
            $this->addPrefix($prefix, $path);
        }
    }

    /**
     * Registers a set of classes
     *
     * @param string       $prefix The classes prefix
     * @param array|string $paths  The location(s) of the classes
     */
    public function addPrefix($prefix, $paths)
    {
        if (!$prefix) {
            foreach ((array) $paths as $path) {
                $this->fallbackDirs[] = $path;
            }

            return;
        }
        if (isset($this->prefixes[$prefix])) {
            $this->prefixes[$prefix] = array_merge(
                $this->prefixes[$prefix],
                (array) $paths
            );
        } else {
            $this->prefixes[$prefix] = (array) $paths;
        }
    }

    /**
     * Turns on searching the include for class files.
     *
     * @param Boolean $useIncludePath
     */
    public function setUseIncludePath($useIncludePath)
    {
        $this->useIncludePath = $useIncludePath;
    }

    /**
     * Can be used to check if the autoloader uses the include path to check
     * for classes.
     *
     * @return Boolean
     */
    public function getUseIncludePath()
    {
        return $this->useIncludePath;
    }

    /**
     * Registers this instance as an autoloader.
     *
     * @param Boolean $prepend Whether to prepend the autoloader or not
     */
    public function register($prepend = false)
    {
        spl_autoload_register(array($this, 'loadClass'), true, $prepend);
    }

    /**
     * Unregisters this instance as an autoloader.
     */
    public function unregister()
    {
        spl_autoload_unregister(array($this, 'loadClass'));
    }

    /**
     * Loads the given class or interface.
     *
     * @param string $class The name of the class
     *
     * @return Boolean|null True, if loaded
     */
    public function loadClass($class)
    {
        if ($file = $this->findFile($class)) {
            require $file;

            return true;
        }
    }

    /**
     * Finds the path to the file where the class is defined.
     *
     * @param string $class The name of the class
     *
     * @return string|null The path, if found
     */
    public function findFile($class)
    {
        if (false !== $pos = strrpos($class, '\\')) {
            // namespaced class name
            $classPath = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, 0, $pos)).DIRECTORY_SEPARATOR;
            $className = substr($class, $pos + 1);
        } else {
            // PEAR-like class name
            $classPath = null;
            $className = $class;
        }

        $classPath .= str_replace('_', DIRECTORY_SEPARATOR, $className).'.php';

        foreach ($this->prefixes as $prefix => $dirs) {
            if ($class === strstr($class, $prefix)) {
                foreach ($dirs as $dir) {
                    if (file_exists($dir.DIRECTORY_SEPARATOR.$classPath)) {
                        return $dir.DIRECTORY_SEPARATOR.$classPath;
                    }
                }
            }
        }

        foreach ($this->fallbackDirs as $dir) {
            if (file_exists($dir.DIRECTORY_SEPARATOR.$classPath)) {
                return $dir.DIRECTORY_SEPARATOR.$classPath;
            }
        }

        if ($this->useIncludePath && $file = stream_resolve_include_path($classPath)) {
            return $file;
        }
    }
}
PK��Z��]
I
I
:Symfony/Component/DependencyInjection/SimpleXMLElement.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

use Symfony\Component\Config\Util\XmlUtils;
use Symfony\Component\ExpressionLanguage\Expression;

/**
 * SimpleXMLElement class.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class SimpleXMLElement extends \SimpleXMLElement
{
    /**
     * Converts an attribute as a PHP type.
     *
     * @param string $name
     *
     * @return mixed
     */
    public function getAttributeAsPhp($name)
    {
        return self::phpize($this[$name]);
    }

    /**
     * Returns arguments as valid PHP types.
     *
     * @param string  $name
     * @param Boolean $lowercase
     *
     * @return mixed
     */
    public function getArgumentsAsPhp($name, $lowercase = true)
    {
        $arguments = array();
        foreach ($this->$name as $arg) {
            if (isset($arg['name'])) {
                $arg['key'] = (string) $arg['name'];
            }
            $key = isset($arg['key']) ? (string) $arg['key'] : (!$arguments ? 0 : max(array_keys($arguments)) + 1);

            // parameter keys are case insensitive
            if ('parameter' == $name && $lowercase) {
                $key = strtolower($key);
            }

            // this is used by DefinitionDecorator to overwrite a specific
            // argument of the parent definition
            if (isset($arg['index'])) {
                $key = 'index_'.$arg['index'];
            }

            switch ($arg['type']) {
                case 'service':
                    $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
                    if (isset($arg['on-invalid']) && 'ignore' == $arg['on-invalid']) {
                        $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
                    } elseif (isset($arg['on-invalid']) && 'null' == $arg['on-invalid']) {
                        $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE;
                    }

                    if (isset($arg['strict'])) {
                        $strict = self::phpize($arg['strict']);
                    } else {
                        $strict = true;
                    }

                    $arguments[$key] = new Reference((string) $arg['id'], $invalidBehavior, $strict);
                    break;
                case 'expression':
                    $arguments[$key] = new Expression((string) $arg);
                    break;
                case 'collection':
                    $arguments[$key] = $arg->getArgumentsAsPhp($name, false);
                    break;
                case 'string':
                    $arguments[$key] = (string) $arg;
                    break;
                case 'constant':
                    $arguments[$key] = constant((string) $arg);
                    break;
                default:
                    $arguments[$key] = self::phpize($arg);
            }
        }

        return $arguments;
    }

    /**
     * Converts an xml value to a PHP type.
     *
     * @param mixed $value
     *
     * @return mixed
     */
    public static function phpize($value)
    {
        return XmlUtils::phpize($value);
    }
}
PK��Zl5����/Symfony/Component/DependencyInjection/Alias.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

/**
 * @api
 */
class Alias
{
    private $id;
    private $public;

    /**
     * Constructor.
     *
     * @param string  $id     Alias identifier
     * @param Boolean $public If this alias is public
     *
     * @api
     */
    public function __construct($id, $public = true)
    {
        $this->id = strtolower($id);
        $this->public = $public;
    }

    /**
     * Checks if this DI Alias should be public or not.
     *
     * @return Boolean
     *
     * @api
     */
    public function isPublic()
    {
        return $this->public;
    }

    /**
     * Sets if this Alias is public.
     *
     * @param Boolean $boolean If this Alias should be public
     *
     * @api
     */
    public function setPublic($boolean)
    {
        $this->public = (Boolean) $boolean;
    }

    /**
     * Returns the Id of this alias.
     *
     * @return string The alias id
     *
     * @api
     */
    public function __toString()
    {
        return $this->id;
    }
}
PK��Z���MSymfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\LazyProxy\PhpDumper;

use Symfony\Component\DependencyInjection\Definition;

/**
 * Lazy proxy dumper capable of generating the instantiation logic PHP code for proxied services.
 *
 * @author Marco Pivetta <ocramius@gmail.com>
 */
interface DumperInterface
{
    /**
     * Inspects whether the given definitions should produce proxy instantiation logic in the dumped container.
     *
     * @param Definition $definition
     *
     * @return bool
     */
    public function isProxyCandidate(Definition $definition);

    /**
     * Generates the code to be used to instantiate a proxy in the dumped factory code.
     *
     * @param Definition $definition
     * @param string     $id         service identifier
     *
     * @return string
     */
    public function getProxyFactoryCode(Definition $definition, $id);

    /**
     * Generates the code for the lazy proxy.
     *
     * @param Definition $definition
     *
     * @return string
     */
    public function getProxyCode(Definition $definition);
}
PK��Z��ҳ��HSymfony/Component/DependencyInjection/LazyProxy/PhpDumper/NullDumper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\LazyProxy\PhpDumper;

use Symfony\Component\DependencyInjection\Definition;

/**
 * Null dumper, negates any proxy code generation for any given service definition.
 *
 * @author Marco Pivetta <ocramius@gmail.com>
 */
class NullDumper implements DumperInterface
{
    /**
     * {@inheritDoc}
     */
    public function isProxyCandidate(Definition $definition)
    {
        return false;
    }

    /**
     * {@inheritDoc}
     */
    public function getProxyFactoryCode(Definition $definition, $id)
    {
        return '';
    }

    /**
     * {@inheritDoc}
     */
    public function getProxyCode(Definition $definition)
    {
        return '';
    }
}
PK��Z����JJVSymfony/Component/DependencyInjection/LazyProxy/Instantiator/InstantiatorInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\LazyProxy\Instantiator;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition;

/**
 * Lazy proxy instantiator, capable of instantiating a proxy given a container, the
 * service definitions and a callback that produces the real service instance.
 *
 * @author Marco Pivetta <ocramius@gmail.com>
 */
interface InstantiatorInterface
{
    /**
     * Instantiates a proxy object.
     *
     * @param ContainerInterface $container        the container from which the service is being requested
     * @param Definition         $definition       the definition of the requested service
     * @param string             $id               identifier of the requested service
     * @param callable           $realInstantiator zero-argument callback that is capable of producing the real
     *                                             service instance
     *
     * @return object
     */
    public function instantiateProxy(ContainerInterface $container, Definition $definition, $id, $realInstantiator);
}
PK��Z�i�nnXSymfony/Component/DependencyInjection/LazyProxy/Instantiator/RealServiceInstantiator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\LazyProxy\Instantiator;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition;

/**
 * {@inheritDoc}
 *
 * Noop proxy instantiator - simply produces the real service instead of a proxy instance.
 *
 * @author Marco Pivetta <ocramius@gmail.com>
 */
class RealServiceInstantiator implements InstantiatorInterface
{
    /**
     * {@inheritDoc}
     */
    public function instantiateProxy(ContainerInterface $container, Definition $definition, $id, $realInstantiator)
    {
        return call_user_func($realInstantiator);
    }
}
PK��Z$�772Symfony/Component/DependencyInjection/Variable.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

/**
 * Represents a variable.
 *
 *     $var = new Variable('a');
 *
 * will be dumped as
 *
 *     $a
 *
 * by the PHP dumper.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class Variable
{
    private $name;

    /**
     * Constructor
     *
     * @param string $name
     */
    public function __construct($name)
    {
        $this->name = $name;
    }

    /**
     * Converts the object to a string
     *
     * @return string
     */
    public function __toString()
    {
        return $this->name;
    }
}
PK��Z���U" " CSymfony/Component/DependencyInjection/ParameterBag/ParameterBag.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\ParameterBag;

use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;

/**
 * Holds parameters.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class ParameterBag implements ParameterBagInterface
{
    protected $parameters = array();
    protected $resolved = false;

    /**
     * Constructor.
     *
     * @param array $parameters An array of parameters
     *
     * @api
     */
    public function __construct(array $parameters = array())
    {
        $this->add($parameters);
    }

    /**
     * Clears all parameters.
     *
     * @api
     */
    public function clear()
    {
        $this->parameters = array();
    }

    /**
     * Adds parameters to the service container parameters.
     *
     * @param array $parameters An array of parameters
     *
     * @api
     */
    public function add(array $parameters)
    {
        foreach ($parameters as $key => $value) {
            $this->parameters[strtolower($key)] = $value;
        }
    }

    /**
     * Gets the service container parameters.
     *
     * @return array An array of parameters
     *
     * @api
     */
    public function all()
    {
        return $this->parameters;
    }

    /**
     * Gets a service container parameter.
     *
     * @param string $name The parameter name
     *
     * @return mixed  The parameter value
     *
     * @throws ParameterNotFoundException if the parameter is not defined
     *
     * @api
     */
    public function get($name)
    {
        $name = strtolower($name);

        if (!array_key_exists($name, $this->parameters)) {
            if (!$name) {
                throw new ParameterNotFoundException($name);
            }

            $alternatives = array();
            foreach (array_keys($this->parameters) as $key) {
                $lev = levenshtein($name, $key);
                if ($lev <= strlen($name) / 3 || false !== strpos($key, $name)) {
                    $alternatives[] = $key;
                }
            }

            throw new ParameterNotFoundException($name, null, null, null, $alternatives);
        }

        return $this->parameters[$name];
    }

    /**
     * Sets a service container parameter.
     *
     * @param string $name  The parameter name
     * @param mixed  $value The parameter value
     *
     * @api
     */
    public function set($name, $value)
    {
        $this->parameters[strtolower($name)] = $value;
    }

    /**
     * Returns true if a parameter name is defined.
     *
     * @param string $name The parameter name
     *
     * @return Boolean true if the parameter name is defined, false otherwise
     *
     * @api
     */
    public function has($name)
    {
        return array_key_exists(strtolower($name), $this->parameters);
    }

    /**
     * Removes a parameter.
     *
     * @param string $name The parameter name
     *
     * @api
     */
    public function remove($name)
    {
        unset($this->parameters[strtolower($name)]);
    }

    /**
     * Replaces parameter placeholders (%name%) by their values for all parameters.
     */
    public function resolve()
    {
        if ($this->resolved) {
            return;
        }

        $parameters = array();
        foreach ($this->parameters as $key => $value) {
            try {
                $value = $this->resolveValue($value);
                $parameters[$key] = $this->unescapeValue($value);
            } catch (ParameterNotFoundException $e) {
                $e->setSourceKey($key);

                throw $e;
            }
        }

        $this->parameters = $parameters;
        $this->resolved = true;
    }

    /**
     * Replaces parameter placeholders (%name%) by their values.
     *
     * @param mixed $value     A value
     * @param array $resolving An array of keys that are being resolved (used internally to detect circular references)
     *
     * @return mixed The resolved value
     *
     * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist
     * @throws ParameterCircularReferenceException if a circular reference if detected
     * @throws RuntimeException when a given parameter has a type problem.
     */
    public function resolveValue($value, array $resolving = array())
    {
        if (is_array($value)) {
            $args = array();
            foreach ($value as $k => $v) {
                $args[$this->resolveValue($k, $resolving)] = $this->resolveValue($v, $resolving);
            }

            return $args;
        }

        if (!is_string($value)) {
            return $value;
        }

        return $this->resolveString($value, $resolving);
    }

    /**
     * Resolves parameters inside a string
     *
     * @param string $value     The string to resolve
     * @param array  $resolving An array of keys that are being resolved (used internally to detect circular references)
     *
     * @return string The resolved string
     *
     * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist
     * @throws ParameterCircularReferenceException if a circular reference if detected
     * @throws RuntimeException when a given parameter has a type problem.
     */
    public function resolveString($value, array $resolving = array())
    {
        // we do this to deal with non string values (Boolean, integer, ...)
        // as the preg_replace_callback throw an exception when trying
        // a non-string in a parameter value
        if (preg_match('/^%([^%\s]+)%$/', $value, $match)) {
            $key = strtolower($match[1]);

            if (isset($resolving[$key])) {
                throw new ParameterCircularReferenceException(array_keys($resolving));
            }

            $resolving[$key] = true;

            return $this->resolved ? $this->get($key) : $this->resolveValue($this->get($key), $resolving);
        }

        $self = $this;

        return preg_replace_callback('/%%|%([^%\s]+)%/', function ($match) use ($self, $resolving, $value) {
            // skip %%
            if (!isset($match[1])) {
                return '%%';
            }

            $key = strtolower($match[1]);
            if (isset($resolving[$key])) {
                throw new ParameterCircularReferenceException(array_keys($resolving));
            }

            $resolved = $self->get($key);

            if (!is_string($resolved) && !is_numeric($resolved)) {
                throw new RuntimeException(sprintf('A string value must be composed of strings and/or numbers, but found parameter "%s" of type %s inside string value "%s".', $key, gettype($resolved), $value));
            }

            $resolved = (string) $resolved;
            $resolving[$key] = true;

            return $self->isResolved() ? $resolved : $self->resolveString($resolved, $resolving);
        }, $value);
    }

    public function isResolved()
    {
        return $this->resolved;
    }

    /**
     * {@inheritDoc}
     */
    public function escapeValue($value)
    {
        if (is_string($value)) {
            return str_replace('%', '%%', $value);
        }

        if (is_array($value)) {
            $result = array();
            foreach ($value as $k => $v) {
                $result[$k] = $this->escapeValue($v);
            }

            return $result;
        }

        return $value;
    }

    public function unescapeValue($value)
    {
        if (is_string($value)) {
            return str_replace('%%', '%', $value);
        }

        if (is_array($value)) {
            $result = array();
            foreach ($value as $k => $v) {
                $result[$k] = $this->unescapeValue($v);
            }

            return $result;
        }

        return $value;
    }
}
PK��ZܮP8�	�	LSymfony/Component/DependencyInjection/ParameterBag/ParameterBagInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\ParameterBag;

use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;

/**
 * ParameterBagInterface.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface ParameterBagInterface
{
    /**
     * Clears all parameters.
     *
     * @api
     */
    public function clear();

    /**
     * Adds parameters to the service container parameters.
     *
     * @param array $parameters An array of parameters
     *
     * @api
     */
    public function add(array $parameters);

    /**
     * Gets the service container parameters.
     *
     * @return array An array of parameters
     *
     * @api
     */
    public function all();

    /**
     * Gets a service container parameter.
     *
     * @param string $name The parameter name
     *
     * @return mixed  The parameter value
     *
     * @throws ParameterNotFoundException if the parameter is not defined
     *
     * @api
     */
    public function get($name);

    /**
     * Sets a service container parameter.
     *
     * @param string $name  The parameter name
     * @param mixed  $value The parameter value
     *
     * @api
     */
    public function set($name, $value);

    /**
     * Returns true if a parameter name is defined.
     *
     * @param string $name The parameter name
     *
     * @return Boolean true if the parameter name is defined, false otherwise
     *
     * @api
     */
    public function has($name);

    /**
     * Replaces parameter placeholders (%name%) by their values for all parameters.
     */
    public function resolve();

    /**
     * Replaces parameter placeholders (%name%) by their values.
     *
     * @param mixed $value A value
     *
     * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist
     */
    public function resolveValue($value);

    /**
     * Escape parameter placeholders %
     *
     * @param mixed $value
     *
     * @return mixed
     */
    public function escapeValue($value);

    /**
     * Unescape parameter placeholders %
     *
     * @param mixed $value
     *
     * @return mixed
     */
    public function unescapeValue($value);
}
PK��Zך�ISymfony/Component/DependencyInjection/ParameterBag/FrozenParameterBag.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\ParameterBag;

use Symfony\Component\DependencyInjection\Exception\LogicException;

/**
 * Holds read-only parameters.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class FrozenParameterBag extends ParameterBag
{
    /**
     * Constructor.
     *
     * For performance reasons, the constructor assumes that
     * all keys are already lowercased.
     *
     * This is always the case when used internally.
     *
     * @param array $parameters An array of parameters
     *
     * @api
     */
    public function __construct(array $parameters = array())
    {
        $this->parameters = $parameters;
        $this->resolved = true;
    }

    /**
     * {@inheritDoc}
     *
     * @api
     */
    public function clear()
    {
        throw new LogicException('Impossible to call clear() on a frozen ParameterBag.');
    }

    /**
     * {@inheritDoc}
     *
     * @api
     */
    public function add(array $parameters)
    {
        throw new LogicException('Impossible to call add() on a frozen ParameterBag.');
    }

    /**
     * {@inheritDoc}
     *
     * @api
     */
    public function set($name, $value)
    {
        throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
    }
}
PK��Z�,x�mm/Symfony/Component/DependencyInjection/Scope.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

/**
 * Scope class.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @api
 */
class Scope implements ScopeInterface
{
    private $name;
    private $parentName;

    /**
     * @api
     */
    public function __construct($name, $parentName = ContainerInterface::SCOPE_CONTAINER)
    {
        $this->name = $name;
        $this->parentName = $parentName;
    }

    /**
     * @api
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @api
     */
    public function getParentName()
    {
        return $this->parentName;
    }
}
PK��Z��]]4Symfony/Component/DependencyInjection/autoloader.phpnu�[���<?php

spl_autoload_register(function ($class) {
    if ('\\' == $class[0]) {
        $class = substr($class, 1);
    }

    if (
        0 === strpos($class, 'Symfony\\Component\\DependencyInjection\\')
        &&
        file_exists($file = __DIR__.'/../../../'.str_replace('\\', '/', $class).'.php')
    ) {
        require_once $file;
    }
});
PK��Z_��J8Symfony/Component/DependencyInjection/ScopeInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

/**
 * Scope Interface.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @api
 */
interface ScopeInterface
{
    /**
     * @api
     */
    public function getName();

    /**
     * @api
     */
    public function getParentName();
}
PK��Z�BtBBJSymfony/Component/DependencyInjection/IntrospectableContainerInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

/**
 * IntrospectableContainerInterface defines additional introspection functionality
 * for containers, allowing logic to be implemented based on a Container's state.
 *
 * @author Evan Villemez <evillemez@gmail.com>
 *
 */
interface IntrospectableContainerInterface extends ContainerInterface
{
    /**
     * Check for whether or not a service has been initialized.
     *
     * @param string $id
     *
     * @return Boolean true if the service has been initialized, false otherwise
     *
     */
    public function initialized($id);

}
PK��Z
O�,��JSymfony/Component/DependencyInjection/Exception/BadMethodCallException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Exception;

/**
 * Base BadMethodCallException for Dependency Injection component.
 */
class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface
{
}
PK��Z����LSymfony/Component/DependencyInjection/Exception/ServiceNotFoundException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Exception;

/**
 * This exception is thrown when a non-existent service is requested.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ServiceNotFoundException extends InvalidArgumentException
{
    private $id;
    private $sourceId;

    public function __construct($id, $sourceId = null, \Exception $previous = null, array $alternatives = array())
    {
        if (null === $sourceId) {
            $msg = sprintf('You have requested a non-existent service "%s".', $id);
        } else {
            $msg = sprintf('The service "%s" has a dependency on a non-existent service "%s".', $sourceId, $id);
        }

        if ($alternatives) {
            if (1 == count($alternatives)) {
                $msg .= ' Did you mean this: "';
            } else {
                $msg .= ' Did you mean one of these: "';
            }
            $msg .= implode('", "', $alternatives).'"?';
        }

        parent::__construct($msg, 0, $previous);

        $this->id = $id;
        $this->sourceId = $sourceId;
    }

    public function getId()
    {
        return $this->id;
    }

    public function getSourceId()
    {
        return $this->sourceId;
    }
}
PK��Z�{����HSymfony/Component/DependencyInjection/Exception/OutOfBoundsException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Exception;

/**
 * Base OutOfBoundsException for Dependency Injection component.
 */
class OutOfBoundsException extends \OutOfBoundsException implements ExceptionInterface
{
}
PK��Z��9FSymfony/Component/DependencyInjection/Exception/ExceptionInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Exception;

/**
 * Base ExceptionInterface for Dependency Injection component.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Bulat Shakirzyanov <bulat@theopenskyproject.com>
 */
interface ExceptionInterface
{
}
PK��Z�
+��DSymfony/Component/DependencyInjection/Exception/RuntimeException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Exception;

/**
 * Base RuntimeException for Dependency Injection component.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
PK��Z��\�
�
NSymfony/Component/DependencyInjection/Exception/ParameterNotFoundException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Exception;

/**
 * This exception is thrown when a non-existent parameter is used.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ParameterNotFoundException extends InvalidArgumentException
{
    private $key;
    private $sourceId;
    private $sourceKey;
    private $alternatives;

    /**
     * Constructor.
     *
     * @param string     $key          The requested parameter key
     * @param string     $sourceId     The service id that references the non-existent parameter
     * @param string     $sourceKey    The parameter key that references the non-existent parameter
     * @param \Exception $previous     The previous exception
     * @param string[]   $alternatives Some parameter name alternatives
     */
    public function __construct($key, $sourceId = null, $sourceKey = null, \Exception $previous = null, array $alternatives = array())
    {
        $this->key = $key;
        $this->sourceId = $sourceId;
        $this->sourceKey = $sourceKey;
        $this->alternatives = $alternatives;

        parent::__construct('', 0, $previous);

        $this->updateRepr();
    }

    public function updateRepr()
    {
        if (null !== $this->sourceId) {
            $this->message = sprintf('The service "%s" has a dependency on a non-existent parameter "%s".', $this->sourceId, $this->key);
        } elseif (null !== $this->sourceKey) {
            $this->message = sprintf('The parameter "%s" has a dependency on a non-existent parameter "%s".', $this->sourceKey, $this->key);
        } else {
            $this->message = sprintf('You have requested a non-existent parameter "%s".', $this->key);
        }

        if ($this->alternatives) {
            if (1 == count($this->alternatives)) {
                $this->message .= ' Did you mean this: "';
            } else {
                $this->message .= ' Did you mean one of these: "';
            }
            $this->message .= implode('", "', $this->alternatives).'"?';
        }
    }

    public function getKey()
    {
        return $this->key;
    }

    public function getSourceId()
    {
        return $this->sourceId;
    }

    public function getSourceKey()
    {
        return $this->sourceKey;
    }

    public function setSourceId($sourceId)
    {
        $this->sourceId = $sourceId;

        $this->updateRepr();
    }

    public function setSourceKey($sourceKey)
    {
        $this->sourceKey = $sourceKey;

        $this->updateRepr();
    }
}
PK��ZI_���JSymfony/Component/DependencyInjection/Exception/InactiveScopeException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Exception;

/**
 * This exception is thrown when you try to create a service of an inactive scope.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class InactiveScopeException extends RuntimeException
{
    private $serviceId;
    private $scope;

    public function __construct($serviceId, $scope, \Exception $previous = null)
    {
        parent::__construct(sprintf('You cannot create a service ("%s") of an inactive scope ("%s").', $serviceId, $scope), 0, $previous);

        $this->serviceId = $serviceId;
        $this->scope = $scope;
    }

    public function getServiceId()
    {
        return $this->serviceId;
    }

    public function getScope()
    {
        return $this->scope;
    }
}
PK��Z���z��SSymfony/Component/DependencyInjection/Exception/ScopeWideningInjectionException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Exception;

/**
 * Thrown when a scope widening injection is detected.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ScopeWideningInjectionException extends RuntimeException
{
    private $sourceServiceId;
    private $sourceScope;
    private $destServiceId;
    private $destScope;

    public function __construct($sourceServiceId, $sourceScope, $destServiceId, $destScope, \Exception $previous = null)
    {
        parent::__construct(sprintf(
            'Scope Widening Injection detected: The definition "%s" references the service "%s" which belongs to a narrower scope. '
           .'Generally, it is safer to either move "%s" to scope "%s" or alternatively rely on the provider pattern by injecting the container itself, and requesting the service "%s" each time it is needed. '
           .'In rare, special cases however that might not be necessary, then you can set the reference to strict=false to get rid of this error.',
           $sourceServiceId,
           $destServiceId,
           $sourceServiceId,
           $destScope,
           $destServiceId
        ), 0, $previous);

        $this->sourceServiceId = $sourceServiceId;
        $this->sourceScope = $sourceScope;
        $this->destServiceId = $destServiceId;
        $this->destScope = $destScope;
    }

    public function getSourceServiceId()
    {
        return $this->sourceServiceId;
    }

    public function getSourceScope()
    {
        return $this->sourceScope;
    }

    public function getDestServiceId()
    {
        return $this->destServiceId;
    }

    public function getDestScope()
    {
        return $this->destScope;
    }
}
PK��Zl.��BSymfony/Component/DependencyInjection/Exception/LogicException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Exception;

/**
 * Base LogicException for Dependency Injection component.
 */
class LogicException extends \LogicException implements ExceptionInterface
{
}
PK��Z��]���USymfony/Component/DependencyInjection/Exception/ServiceCircularReferenceException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Exception;

/**
 * This exception is thrown when a circular reference is detected.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ServiceCircularReferenceException extends RuntimeException
{
    private $serviceId;
    private $path;

    public function __construct($serviceId, array $path, \Exception $previous = null)
    {
        parent::__construct(sprintf('Circular reference detected for service "%s", path: "%s".', $serviceId, implode(' -> ', $path)), 0, $previous);

        $this->serviceId = $serviceId;
        $this->path = $path;
    }

    public function getServiceId()
    {
        return $this->serviceId;
    }

    public function getPath()
    {
        return $this->path;
    }
}
PK��Z��LSymfony/Component/DependencyInjection/Exception/InvalidArgumentException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Exception;

/**
 * Base InvalidArgumentException for Dependency Injection component.
 *
 * @author Bulat Shakirzyanov <bulat@theopenskyproject.com>
 */
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
PK��Z= ԥ�SSymfony/Component/DependencyInjection/Exception/ScopeCrossingInjectionException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Exception;

/**
 * This exception is thrown when the a scope crossing injection is detected.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ScopeCrossingInjectionException extends RuntimeException
{
    private $sourceServiceId;
    private $sourceScope;
    private $destServiceId;
    private $destScope;

    public function __construct($sourceServiceId, $sourceScope, $destServiceId, $destScope, \Exception $previous = null)
    {
        parent::__construct(sprintf(
            'Scope Crossing Injection detected: The definition "%s" references the service "%s" which belongs to another scope hierarchy. '
           .'This service might not be available consistently. Generally, it is safer to either move the definition "%s" to scope "%s", or '
           .'declare "%s" as a child scope of "%s". If you can be sure that the other scope is always active, you can set the reference to strict=false to get rid of this error.',
           $sourceServiceId,
           $destServiceId,
           $sourceServiceId,
           $destScope,
           $sourceScope,
           $destScope
        ), 0, $previous);

        $this->sourceServiceId = $sourceServiceId;
        $this->sourceScope = $sourceScope;
        $this->destServiceId = $destServiceId;
        $this->destScope = $destScope;
    }

    public function getSourceServiceId()
    {
        return $this->sourceServiceId;
    }

    public function getSourceScope()
    {
        return $this->sourceScope;
    }

    public function getDestServiceId()
    {
        return $this->destServiceId;
    }

    public function getDestScope()
    {
        return $this->destScope;
    }
}
PK��Z�qB��WSymfony/Component/DependencyInjection/Exception/ParameterCircularReferenceException.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Exception;

/**
 * This exception is thrown when a circular reference in a parameter is detected.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ParameterCircularReferenceException extends RuntimeException
{
    private $parameters;

    public function __construct($parameters, \Exception $previous = null)
    {
        parent::__construct(sprintf('Circular reference detected for parameter "%s" ("%s" > "%s").', $parameters[0], implode('" > "', $parameters), $parameters[0]), 0, $previous);

        $this->parameters = $parameters;
    }

    public function getParameters()
    {
        return $this->parameters;
    }
}
PK��Zq8I���ASymfony/Component/DependencyInjection/ContainerAwareInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

/**
 * ContainerAwareInterface should be implemented by classes that depends on a Container.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface ContainerAwareInterface
{
    /**
     * Sets the Container.
     *
     * @param ContainerInterface|null $container A ContainerInterface instance or null
     *
     * @api
     */
    public function setContainer(ContainerInterface $container = null);
}
PK��Z-&�����:Symfony/Component/DependencyInjection/ContainerBuilder.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

use Symfony\Component\DependencyInjection\Compiler\Compiler;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
use Symfony\Component\DependencyInjection\Exception\BadMethodCallException;
use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\Config\Resource\ResourceInterface;
use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\InstantiatorInterface;
use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator;
use Symfony\Component\ExpressionLanguage\Expression;

/**
 * ContainerBuilder is a DI container that provides an API to easily describe services.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class ContainerBuilder extends Container implements TaggedContainerInterface
{
    /**
     * @var ExtensionInterface[]
     */
    private $extensions = array();

    /**
     * @var ExtensionInterface[]
     */
    private $extensionsByNs = array();

    /**
     * @var Definition[]
     */
    private $definitions = array();

    /**
     * @var Definition[]
     */
    private $obsoleteDefinitions = array();

    /**
     * @var Alias[]
     */
    private $aliasDefinitions = array();

    /**
     * @var ResourceInterface[]
     */
    private $resources = array();

    private $extensionConfigs = array();

    /**
     * @var Compiler
     */
    private $compiler;

    private $trackResources = true;

    /**
     * @var InstantiatorInterface|null
     */
    private $proxyInstantiator;

    /**
     * @var ExpressionLanguage|null
     */
    private $expressionLanguage;

    /**
     * Sets the track resources flag.
     *
     * If you are not using the loaders and therefore don't want
     * to depend on the Config component, set this flag to false.
     *
     * @param Boolean $track true if you want to track resources, false otherwise
     */
    public function setResourceTracking($track)
    {
        $this->trackResources = (Boolean) $track;
    }

    /**
     * Checks if resources are tracked.
     *
     * @return Boolean true if resources are tracked, false otherwise
     */
    public function isTrackingResources()
    {
        return $this->trackResources;
    }

    /**
     * Sets the instantiator to be used when fetching proxies.
     *
     * @param InstantiatorInterface $proxyInstantiator
     */
    public function setProxyInstantiator(InstantiatorInterface $proxyInstantiator)
    {
        $this->proxyInstantiator = $proxyInstantiator;
    }

    /**
     * Registers an extension.
     *
     * @param ExtensionInterface $extension An extension instance
     *
     * @api
     */
    public function registerExtension(ExtensionInterface $extension)
    {
        $this->extensions[$extension->getAlias()] = $extension;

        if (false !== $extension->getNamespace()) {
            $this->extensionsByNs[$extension->getNamespace()] = $extension;
        }
    }

    /**
     * Returns an extension by alias or namespace.
     *
     * @param string $name An alias or a namespace
     *
     * @return ExtensionInterface An extension instance
     *
     * @throws LogicException if the extension is not registered
     *
     * @api
     */
    public function getExtension($name)
    {
        if (isset($this->extensions[$name])) {
            return $this->extensions[$name];
        }

        if (isset($this->extensionsByNs[$name])) {
            return $this->extensionsByNs[$name];
        }

        throw new LogicException(sprintf('Container extension "%s" is not registered', $name));
    }

    /**
     * Returns all registered extensions.
     *
     * @return ExtensionInterface[] An array of ExtensionInterface
     *
     * @api
     */
    public function getExtensions()
    {
        return $this->extensions;
    }

    /**
     * Checks if we have an extension.
     *
     * @param string $name The name of the extension
     *
     * @return Boolean If the extension exists
     *
     * @api
     */
    public function hasExtension($name)
    {
        return isset($this->extensions[$name]) || isset($this->extensionsByNs[$name]);
    }

    /**
     * Returns an array of resources loaded to build this configuration.
     *
     * @return ResourceInterface[] An array of resources
     *
     * @api
     */
    public function getResources()
    {
        return array_unique($this->resources);
    }

    /**
     * Adds a resource for this configuration.
     *
     * @param ResourceInterface $resource A resource instance
     *
     * @return ContainerBuilder The current instance
     *
     * @api
     */
    public function addResource(ResourceInterface $resource)
    {
        if (!$this->trackResources) {
            return $this;
        }

        $this->resources[] = $resource;

        return $this;
    }

    /**
     * Sets the resources for this configuration.
     *
     * @param ResourceInterface[] $resources An array of resources
     *
     * @return ContainerBuilder The current instance
     *
     * @api
     */
    public function setResources(array $resources)
    {
        if (!$this->trackResources) {
            return $this;
        }

        $this->resources = $resources;

        return $this;
    }

    /**
     * Adds the object class hierarchy as resources.
     *
     * @param object $object An object instance
     *
     * @return ContainerBuilder The current instance
     *
     * @api
     */
    public function addObjectResource($object)
    {
        if ($this->trackResources) {
            $this->addClassResource(new \ReflectionClass($object));
        }

        return $this;
    }

    /**
     * Adds the given class hierarchy as resources.
     *
     * @param \ReflectionClass $class
     *
     * @return ContainerBuilder The current instance
     */
    public function addClassResource(\ReflectionClass $class)
    {
        if (!$this->trackResources) {
            return $this;
        }

        do {
            $this->addResource(new FileResource($class->getFileName()));
        } while ($class = $class->getParentClass());

        return $this;
    }

    /**
     * Loads the configuration for an extension.
     *
     * @param string $extension The extension alias or namespace
     * @param array  $values    An array of values that customizes the extension
     *
     * @return ContainerBuilder The current instance
     * @throws BadMethodCallException When this ContainerBuilder is frozen
     *
     * @throws \LogicException if the container is frozen
     *
     * @api
     */
    public function loadFromExtension($extension, array $values = array())
    {
        if ($this->isFrozen()) {
            throw new BadMethodCallException('Cannot load from an extension on a frozen container.');
        }

        $namespace = $this->getExtension($extension)->getAlias();

        $this->extensionConfigs[$namespace][] = $values;

        return $this;
    }

    /**
     * Adds a compiler pass.
     *
     * @param CompilerPassInterface $pass A compiler pass
     * @param string                $type The type of compiler pass
     *
     * @return ContainerBuilder The current instance
     *
     * @api
     */
    public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION)
    {
        $this->getCompiler()->addPass($pass, $type);

        $this->addObjectResource($pass);

        return $this;
    }

    /**
     * Returns the compiler pass config which can then be modified.
     *
     * @return PassConfig The compiler pass config
     *
     * @api
     */
    public function getCompilerPassConfig()
    {
        return $this->getCompiler()->getPassConfig();
    }

    /**
     * Returns the compiler.
     *
     * @return Compiler The compiler
     *
     * @api
     */
    public function getCompiler()
    {
        if (null === $this->compiler) {
            $this->compiler = new Compiler();
        }

        return $this->compiler;
    }

    /**
     * Returns all Scopes.
     *
     * @return array An array of scopes
     *
     * @api
     */
    public function getScopes()
    {
        return $this->scopes;
    }

    /**
     * Returns all Scope children.
     *
     * @return array An array of scope children.
     *
     * @api
     */
    public function getScopeChildren()
    {
        return $this->scopeChildren;
    }

    /**
     * Sets a service.
     *
     * @param string $id      The service identifier
     * @param object $service The service instance
     * @param string $scope   The scope
     *
     * @throws BadMethodCallException When this ContainerBuilder is frozen
     *
     * @api
     */
    public function set($id, $service, $scope = self::SCOPE_CONTAINER)
    {
        $id = strtolower($id);

        if ($this->isFrozen()) {
            // setting a synthetic service on a frozen container is alright
            if (
                (!isset($this->definitions[$id]) && !isset($this->obsoleteDefinitions[$id]))
                    ||
                (isset($this->definitions[$id]) && !$this->definitions[$id]->isSynthetic())
                    ||
                (isset($this->obsoleteDefinitions[$id]) && !$this->obsoleteDefinitions[$id]->isSynthetic())
            ) {
                throw new BadMethodCallException(sprintf('Setting service "%s" on a frozen container is not allowed.', $id));
            }
        }

        if (isset($this->definitions[$id])) {
            $this->obsoleteDefinitions[$id] = $this->definitions[$id];
        }

        unset($this->definitions[$id], $this->aliasDefinitions[$id]);

        parent::set($id, $service, $scope);

        if (isset($this->obsoleteDefinitions[$id]) && $this->obsoleteDefinitions[$id]->isSynchronized()) {
            $this->synchronize($id);
        }
    }

    /**
     * Removes a service definition.
     *
     * @param string $id The service identifier
     *
     * @api
     */
    public function removeDefinition($id)
    {
        unset($this->definitions[strtolower($id)]);
    }

    /**
     * Returns true if the given service is defined.
     *
     * @param string $id The service identifier
     *
     * @return Boolean true if the service is defined, false otherwise
     *
     * @api
     */
    public function has($id)
    {
        $id = strtolower($id);

        return isset($this->definitions[$id]) || isset($this->aliasDefinitions[$id]) || parent::has($id);
    }

    /**
     * Gets a service.
     *
     * @param string  $id              The service identifier
     * @param integer $invalidBehavior The behavior when the service does not exist
     *
     * @return object The associated service
     *
     * @throws InvalidArgumentException when no definitions are available
     * @throws InactiveScopeException   when the current scope is not active
     * @throws LogicException           when a circular dependency is detected
     * @throws \Exception
     *
     * @see Reference
     *
     * @api
     */
    public function get($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE)
    {
        $id = strtolower($id);

        try {
            return parent::get($id, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE);
        } catch (InactiveScopeException $e) {
            if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) {
                return null;
            }

            throw $e;
        } catch (InvalidArgumentException $e) {
            if (isset($this->loading[$id])) {
                throw new LogicException(sprintf('The service "%s" has a circular reference to itself.', $id), 0, $e);
            }

            if (!$this->hasDefinition($id) && isset($this->aliasDefinitions[$id])) {
                return $this->get($this->aliasDefinitions[$id]);
            }

            try {
                $definition = $this->getDefinition($id);
            } catch (InvalidArgumentException $e) {
                if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) {
                    return null;
                }

                throw $e;
            }

            $this->loading[$id] = true;

            try {
                $service = $this->createService($definition, $id);
            } catch (\Exception $e) {
                unset($this->loading[$id]);

                if ($e instanceof InactiveScopeException && self::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) {
                    return null;
                }

                throw $e;
            }

            unset($this->loading[$id]);

            return $service;
        }
    }

    /**
     * Merges a ContainerBuilder with the current ContainerBuilder configuration.
     *
     * Service definitions overrides the current defined ones.
     *
     * But for parameters, they are overridden by the current ones. It allows
     * the parameters passed to the container constructor to have precedence
     * over the loaded ones.
     *
     * $container = new ContainerBuilder(array('foo' => 'bar'));
     * $loader = new LoaderXXX($container);
     * $loader->load('resource_name');
     * $container->register('foo', new stdClass());
     *
     * In the above example, even if the loaded resource defines a foo
     * parameter, the value will still be 'bar' as defined in the ContainerBuilder
     * constructor.
     *
     * @param ContainerBuilder $container The ContainerBuilder instance to merge.
     *
     *
     * @throws BadMethodCallException When this ContainerBuilder is frozen
     *
     * @api
     */
    public function merge(ContainerBuilder $container)
    {
        if ($this->isFrozen()) {
            throw new BadMethodCallException('Cannot merge on a frozen container.');
        }

        $this->addDefinitions($container->getDefinitions());
        $this->addAliases($container->getAliases());
        $this->getParameterBag()->add($container->getParameterBag()->all());

        if ($this->trackResources) {
            foreach ($container->getResources() as $resource) {
                $this->addResource($resource);
            }
        }

        foreach ($this->extensions as $name => $extension) {
            if (!isset($this->extensionConfigs[$name])) {
                $this->extensionConfigs[$name] = array();
            }

            $this->extensionConfigs[$name] = array_merge($this->extensionConfigs[$name], $container->getExtensionConfig($name));
        }
    }

    /**
     * Returns the configuration array for the given extension.
     *
     * @param string $name The name of the extension
     *
     * @return array An array of configuration
     *
     * @api
     */
    public function getExtensionConfig($name)
    {
        if (!isset($this->extensionConfigs[$name])) {
            $this->extensionConfigs[$name] = array();
        }

        return $this->extensionConfigs[$name];
    }

    /**
     * Prepends a config array to the configs of the given extension.
     *
     * @param string $name    The name of the extension
     * @param array  $config  The config to set
     */
    public function prependExtensionConfig($name, array $config)
    {
        if (!isset($this->extensionConfigs[$name])) {
            $this->extensionConfigs[$name] = array();
        }

        array_unshift($this->extensionConfigs[$name], $config);
    }

    /**
     * Compiles the container.
     *
     * This method passes the container to compiler
     * passes whose job is to manipulate and optimize
     * the container.
     *
     * The main compiler passes roughly do four things:
     *
     *  * The extension configurations are merged;
     *  * Parameter values are resolved;
     *  * The parameter bag is frozen;
     *  * Extension loading is disabled.
     *
     * @api
     */
    public function compile()
    {
        $compiler = $this->getCompiler();

        if ($this->trackResources) {
            foreach ($compiler->getPassConfig()->getPasses() as $pass) {
                $this->addObjectResource($pass);
            }
        }

        $compiler->compile($this);

        if ($this->trackResources) {
            foreach ($this->definitions as $definition) {
                if ($definition->isLazy() && ($class = $definition->getClass()) && class_exists($class)) {
                    $this->addClassResource(new \ReflectionClass($class));
                }
            }
        }

        $this->extensionConfigs = array();

        parent::compile();
    }

    /**
     * Gets all service ids.
     *
     * @return array An array of all defined service ids
     */
    public function getServiceIds()
    {
        return array_unique(array_merge(array_keys($this->getDefinitions()), array_keys($this->aliasDefinitions), parent::getServiceIds()));
    }

    /**
     * Adds the service aliases.
     *
     * @param array $aliases An array of aliases
     *
     * @api
     */
    public function addAliases(array $aliases)
    {
        foreach ($aliases as $alias => $id) {
            $this->setAlias($alias, $id);
        }
    }

    /**
     * Sets the service aliases.
     *
     * @param array $aliases An array of aliases
     *
     * @api
     */
    public function setAliases(array $aliases)
    {
        $this->aliasDefinitions = array();
        $this->addAliases($aliases);
    }

    /**
     * Sets an alias for an existing service.
     *
     * @param string        $alias The alias to create
     * @param string|Alias  $id    The service to alias
     *
     * @throws InvalidArgumentException if the id is not a string or an Alias
     * @throws InvalidArgumentException if the alias is for itself
     *
     * @api
     */
    public function setAlias($alias, $id)
    {
        $alias = strtolower($alias);

        if (is_string($id)) {
            $id = new Alias($id);
        } elseif (!$id instanceof Alias) {
            throw new InvalidArgumentException('$id must be a string, or an Alias object.');
        }

        if ($alias === strtolower($id)) {
            throw new InvalidArgumentException(sprintf('An alias can not reference itself, got a circular reference on "%s".', $alias));
        }

        unset($this->definitions[$alias]);

        $this->aliasDefinitions[$alias] = $id;
    }

    /**
     * Removes an alias.
     *
     * @param string $alias The alias to remove
     *
     * @api
     */
    public function removeAlias($alias)
    {
        unset($this->aliasDefinitions[strtolower($alias)]);
    }

    /**
     * Returns true if an alias exists under the given identifier.
     *
     * @param string $id The service identifier
     *
     * @return Boolean true if the alias exists, false otherwise
     *
     * @api
     */
    public function hasAlias($id)
    {
        return isset($this->aliasDefinitions[strtolower($id)]);
    }

    /**
     * Gets all defined aliases.
     *
     * @return Alias[] An array of aliases
     *
     * @api
     */
    public function getAliases()
    {
        return $this->aliasDefinitions;
    }

    /**
     * Gets an alias.
     *
     * @param string $id The service identifier
     *
     * @return Alias An Alias instance
     *
     * @throws InvalidArgumentException if the alias does not exist
     *
     * @api
     */
    public function getAlias($id)
    {
        $id = strtolower($id);

        if (!$this->hasAlias($id)) {
            throw new InvalidArgumentException(sprintf('The service alias "%s" does not exist.', $id));
        }

        return $this->aliasDefinitions[$id];
    }

    /**
     * Registers a service definition.
     *
     * This methods allows for simple registration of service definition
     * with a fluid interface.
     *
     * @param string $id    The service identifier
     * @param string $class The service class
     *
     * @return Definition A Definition instance
     *
     * @api
     */
    public function register($id, $class = null)
    {
        return $this->setDefinition(strtolower($id), new Definition($class));
    }

    /**
     * Adds the service definitions.
     *
     * @param Definition[] $definitions An array of service definitions
     *
     * @api
     */
    public function addDefinitions(array $definitions)
    {
        foreach ($definitions as $id => $definition) {
            $this->setDefinition($id, $definition);
        }
    }

    /**
     * Sets the service definitions.
     *
     * @param Definition[] $definitions An array of service definitions
     *
     * @api
     */
    public function setDefinitions(array $definitions)
    {
        $this->definitions = array();
        $this->addDefinitions($definitions);
    }

    /**
     * Gets all service definitions.
     *
     * @return Definition[] An array of Definition instances
     *
     * @api
     */
    public function getDefinitions()
    {
        return $this->definitions;
    }

    /**
     * Sets a service definition.
     *
     * @param string     $id         The service identifier
     * @param Definition $definition A Definition instance
     *
     * @return Definition the service definition
     *
     * @throws BadMethodCallException When this ContainerBuilder is frozen
     *
     * @api
     */
    public function setDefinition($id, Definition $definition)
    {
        if ($this->isFrozen()) {
            throw new BadMethodCallException('Adding definition to a frozen container is not allowed');
        }

        $id = strtolower($id);

        unset($this->aliasDefinitions[$id]);

        return $this->definitions[$id] = $definition;
    }

    /**
     * Returns true if a service definition exists under the given identifier.
     *
     * @param string $id The service identifier
     *
     * @return Boolean true if the service definition exists, false otherwise
     *
     * @api
     */
    public function hasDefinition($id)
    {
        return array_key_exists(strtolower($id), $this->definitions);
    }

    /**
     * Gets a service definition.
     *
     * @param string $id The service identifier
     *
     * @return Definition A Definition instance
     *
     * @throws InvalidArgumentException if the service definition does not exist
     *
     * @api
     */
    public function getDefinition($id)
    {
        $id = strtolower($id);

        if (!$this->hasDefinition($id)) {
            throw new InvalidArgumentException(sprintf('The service definition "%s" does not exist.', $id));
        }

        return $this->definitions[$id];
    }

    /**
     * Gets a service definition by id or alias.
     *
     * The method "unaliases" recursively to return a Definition instance.
     *
     * @param string $id The service identifier or alias
     *
     * @return Definition A Definition instance
     *
     * @throws InvalidArgumentException if the service definition does not exist
     *
     * @api
     */
    public function findDefinition($id)
    {
        while ($this->hasAlias($id)) {
            $id = (string) $this->getAlias($id);
        }

        return $this->getDefinition($id);
    }

    /**
     * Creates a service for a service definition.
     *
     * @param Definition $definition A service definition instance
     * @param string     $id         The service identifier
     * @param Boolean    $tryProxy   Whether to try proxying the service with a lazy proxy
     *
     * @return object The service described by the service definition
     *
     * @throws RuntimeException When the scope is inactive
     * @throws RuntimeException When the factory definition is incomplete
     * @throws RuntimeException When the service is a synthetic service
     * @throws InvalidArgumentException When configure callable is not callable
     *
     * @internal this method is public because of PHP 5.3 limitations, do not use it explicitly in your code
     */
    public function createService(Definition $definition, $id, $tryProxy = true)
    {
        if ($definition->isSynthetic()) {
            throw new RuntimeException(sprintf('You have requested a synthetic service ("%s"). The DIC does not know how to construct this service.', $id));
        }

        if ($tryProxy && $definition->isLazy()) {
            $container = $this;

            $proxy = $this
                ->getProxyInstantiator()
                ->instantiateProxy(
                    $container,
                    $definition,
                    $id, function () use ($definition, $id, $container) {
                        return $container->createService($definition, $id, false);
                    }
                );
            $this->shareService($definition, $proxy, $id);

            return $proxy;
        }

        $parameterBag = $this->getParameterBag();

        if (null !== $definition->getFile()) {
            require_once $parameterBag->resolveValue($definition->getFile());
        }

        $arguments = $this->resolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getArguments())));

        if (null !== $definition->getFactoryMethod()) {
            if (null !== $definition->getFactoryClass()) {
                $factory = $parameterBag->resolveValue($definition->getFactoryClass());
            } elseif (null !== $definition->getFactoryService()) {
                $factory = $this->get($parameterBag->resolveValue($definition->getFactoryService()));
            } else {
                throw new RuntimeException(sprintf('Cannot create service "%s" from factory method without a factory service or factory class.', $id));
            }

            $service = call_user_func_array(array($factory, $definition->getFactoryMethod()), $arguments);
        } else {
            $r = new \ReflectionClass($parameterBag->resolveValue($definition->getClass()));

            $service = null === $r->getConstructor() ? $r->newInstance() : $r->newInstanceArgs($arguments);
        }

        if ($tryProxy || !$definition->isLazy()) {
            // share only if proxying failed, or if not a proxy
            $this->shareService($definition, $service, $id);
        }

        foreach ($definition->getMethodCalls() as $call) {
            $this->callMethod($service, $call);
        }

        $properties = $this->resolveServices($parameterBag->resolveValue($definition->getProperties()));
        foreach ($properties as $name => $value) {
            $service->$name = $value;
        }

        if ($callable = $definition->getConfigurator()) {
            if (is_array($callable)) {
                $callable[0] = $callable[0] instanceof Reference ? $this->get((string) $callable[0]) : $parameterBag->resolveValue($callable[0]);
            }

            if (!is_callable($callable)) {
                throw new InvalidArgumentException(sprintf('The configure callable for class "%s" is not a callable.', get_class($service)));
            }

            call_user_func($callable, $service);
        }

        return $service;
    }

    /**
     * Replaces service references by the real service instance and evaluates expressions.
     *
     * @param mixed $value A value
     *
     * @return mixed The same value with all service references replaced by
     *               the real service instances and all expressions evaluated
     */
    public function resolveServices($value)
    {
        if (is_array($value)) {
            foreach ($value as &$v) {
                $v = $this->resolveServices($v);
            }
        } elseif ($value instanceof Reference) {
            $value = $this->get((string) $value, $value->getInvalidBehavior());
        } elseif ($value instanceof Definition) {
            $value = $this->createService($value, null);
        } elseif ($value instanceof Expression) {
            $value = $this->getExpressionLanguage()->evaluate($value, array('container' => $this));
        }

        return $value;
    }

    /**
     * Returns service ids for a given tag.
     *
     * Example:
     *
     * $container->register('foo')->addTag('my.tag', array('hello' => 'world'));
     *
     * $serviceIds = $container->findTaggedServiceIds('my.tag');
     * foreach ($serviceIds as $serviceId => $tags) {
     *     foreach ($tags as $tag) {
     *         echo $tag['hello'];
     *     }
     * }
     *
     * @param string $name The tag name
     *
     * @return array An array of tags with the tagged service as key, holding a list of attribute arrays.
     *
     * @api
     */
    public function findTaggedServiceIds($name)
    {
        $tags = array();
        foreach ($this->getDefinitions() as $id => $definition) {
            if ($definition->hasTag($name)) {
                $tags[$id] = $definition->getTag($name);
            }
        }

        return $tags;
    }

    /**
     * Returns all tags the defined services use.
     *
     * @return array An array of tags
     */
    public function findTags()
    {
        $tags = array();
        foreach ($this->getDefinitions() as $id => $definition) {
            $tags = array_merge(array_keys($definition->getTags()), $tags);
        }

        return array_unique($tags);
    }

    /**
     * Returns the Service Conditionals.
     *
     * @param mixed $value An array of conditionals to return.
     *
     * @return array An array of Service conditionals
     */
    public static function getServiceConditionals($value)
    {
        $services = array();

        if (is_array($value)) {
            foreach ($value as $v) {
                $services = array_unique(array_merge($services, self::getServiceConditionals($v)));
            }
        } elseif ($value instanceof Reference && $value->getInvalidBehavior() === ContainerInterface::IGNORE_ON_INVALID_REFERENCE) {
            $services[] = (string) $value;
        }

        return $services;
    }

    /**
     * Retrieves the currently set proxy instantiator or instantiates one.
     *
     * @return InstantiatorInterface
     */
    private function getProxyInstantiator()
    {
        if (!$this->proxyInstantiator) {
            $this->proxyInstantiator = new RealServiceInstantiator();
        }

        return $this->proxyInstantiator;
    }

    /**
     * Synchronizes a service change.
     *
     * This method updates all services that depend on the given
     * service by calling all methods referencing it.
     *
     * @param string $id A service id
     */
    private function synchronize($id)
    {
        foreach ($this->definitions as $definitionId => $definition) {
            // only check initialized services
            if (!$this->initialized($definitionId)) {
                continue;
            }

            foreach ($definition->getMethodCalls() as $call) {
                foreach ($call[1] as $argument) {
                    if ($argument instanceof Reference && $id == (string) $argument) {
                        $this->callMethod($this->get($definitionId), $call);
                    }
                }
            }
        }
    }

    private function callMethod($service, $call)
    {
        $services = self::getServiceConditionals($call[1]);

        foreach ($services as $s) {
            if (!$this->has($s)) {
                return;
            }
        }

        call_user_func_array(array($service, $call[0]), $this->resolveServices($this->getParameterBag()->resolveValue($call[1])));
    }

    /**
     * Shares a given service in the container
     *
     * @param Definition $definition
     * @param mixed      $service
     * @param string     $id
     *
     * @throws InactiveScopeException
     */
    private function shareService(Definition $definition, $service, $id)
    {
        if (self::SCOPE_PROTOTYPE !== $scope = $definition->getScope()) {
            if (self::SCOPE_CONTAINER !== $scope && !isset($this->scopedServices[$scope])) {
                throw new InactiveScopeException($id, $scope);
            }

            $this->services[$lowerId = strtolower($id)] = $service;

            if (self::SCOPE_CONTAINER !== $scope) {
                $this->scopedServices[$scope][$lowerId] = $service;
            }
        }
    }

    private function getExpressionLanguage()
    {
        if (null === $this->expressionLanguage) {
            if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
                throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
            }
            $this->expressionLanguage = new ExpressionLanguage();
        }

        return $this->expressionLanguage;
    }
}
PK��Z��c!89894Symfony/Component/DependencyInjection/Definition.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\OutOfBoundsException;

/**
 * Definition represents a service definition.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class Definition
{
    private $class;
    private $file;
    private $factoryClass;
    private $factoryMethod;
    private $factoryService;
    private $scope = ContainerInterface::SCOPE_CONTAINER;
    private $properties = array();
    private $calls = array();
    private $configurator;
    private $tags = array();
    private $public = true;
    private $synthetic = false;
    private $abstract = false;
    private $synchronized = false;
    private $lazy = false;

    protected $arguments;

    /**
     * Constructor.
     *
     * @param string|null $class     The service class
     * @param array       $arguments An array of arguments to pass to the service constructor
     *
     * @api
     */
    public function __construct($class = null, array $arguments = array())
    {
        $this->class = $class;
        $this->arguments = $arguments;
    }

    /**
     * Sets the name of the class that acts as a factory using the factory method,
     * which will be invoked statically.
     *
     * @param string $factoryClass The factory class name
     *
     * @return Definition The current instance
     *
     * @api
     */
    public function setFactoryClass($factoryClass)
    {
        $this->factoryClass = $factoryClass;

        return $this;
    }

    /**
     * Gets the factory class.
     *
     * @return string|null The factory class name
     *
     * @api
     */
    public function getFactoryClass()
    {
        return $this->factoryClass;
    }

    /**
     * Sets the factory method able to create an instance of this class.
     *
     * @param string $factoryMethod The factory method name
     *
     * @return Definition The current instance
     *
     * @api
     */
    public function setFactoryMethod($factoryMethod)
    {
        $this->factoryMethod = $factoryMethod;

        return $this;
    }

    /**
     * Gets the factory method.
     *
     * @return string|null The factory method name
     *
     * @api
     */
    public function getFactoryMethod()
    {
        return $this->factoryMethod;
    }

    /**
     * Sets the name of the service that acts as a factory using the factory method.
     *
     * @param string $factoryService The factory service id
     *
     * @return Definition The current instance
     *
     * @api
     */
    public function setFactoryService($factoryService)
    {
        $this->factoryService = $factoryService;

        return $this;
    }

    /**
     * Gets the factory service id.
     *
     * @return string|null The factory service id
     *
     * @api
     */
    public function getFactoryService()
    {
        return $this->factoryService;
    }

    /**
     * Sets the service class.
     *
     * @param string $class The service class
     *
     * @return Definition The current instance
     *
     * @api
     */
    public function setClass($class)
    {
        $this->class = $class;

        return $this;
    }

    /**
     * Gets the service class.
     *
     * @return string|null The service class
     *
     * @api
     */
    public function getClass()
    {
        return $this->class;
    }

    /**
     * Sets the arguments to pass to the service constructor/factory method.
     *
     * @param array $arguments An array of arguments
     *
     * @return Definition The current instance
     *
     * @api
     */
    public function setArguments(array $arguments)
    {
        $this->arguments = $arguments;

        return $this;
    }

    /**
     * @api
     */
    public function setProperties(array $properties)
    {
        $this->properties = $properties;

        return $this;
    }

    /**
     * @api
     */
    public function getProperties()
    {
        return $this->properties;
    }

    /**
     * @api
     */
    public function setProperty($name, $value)
    {
        $this->properties[$name] = $value;

        return $this;
    }

    /**
     * Adds an argument to pass to the service constructor/factory method.
     *
     * @param mixed $argument An argument
     *
     * @return Definition The current instance
     *
     * @api
     */
    public function addArgument($argument)
    {
        $this->arguments[] = $argument;

        return $this;
    }

    /**
     * Sets a specific argument
     *
     * @param integer $index
     * @param mixed   $argument
     *
     * @return Definition The current instance
     *
     * @throws OutOfBoundsException When the replaced argument does not exist
     *
     * @api
     */
    public function replaceArgument($index, $argument)
    {
        if ($index < 0 || $index > count($this->arguments) - 1) {
            throw new OutOfBoundsException(sprintf('The index "%d" is not in the range [0, %d].', $index, count($this->arguments) - 1));
        }

        $this->arguments[$index] = $argument;

        return $this;
    }

    /**
     * Gets the arguments to pass to the service constructor/factory method.
     *
     * @return array The array of arguments
     *
     * @api
     */
    public function getArguments()
    {
        return $this->arguments;
    }

    /**
     * Gets an argument to pass to the service constructor/factory method.
     *
     * @param integer $index
     *
     * @return mixed The argument value
     *
     * @throws OutOfBoundsException When the argument does not exist
     *
     * @api
     */
    public function getArgument($index)
    {
        if ($index < 0 || $index > count($this->arguments) - 1) {
            throw new OutOfBoundsException(sprintf('The index "%d" is not in the range [0, %d].', $index, count($this->arguments) - 1));
        }

        return $this->arguments[$index];
    }

    /**
     * Sets the methods to call after service initialization.
     *
     * @param array $calls An array of method calls
     *
     * @return Definition The current instance
     *
     * @api
     */
    public function setMethodCalls(array $calls = array())
    {
        $this->calls = array();
        foreach ($calls as $call) {
            $this->addMethodCall($call[0], $call[1]);
        }

        return $this;
    }

    /**
     * Adds a method to call after service initialization.
     *
     * @param string $method    The method name to call
     * @param array  $arguments An array of arguments to pass to the method call
     *
     * @return Definition The current instance
     *
     * @throws InvalidArgumentException on empty $method param
     *
     * @api
     */
    public function addMethodCall($method, array $arguments = array())
    {
        if (empty($method)) {
            throw new InvalidArgumentException(sprintf('Method name cannot be empty.'));
        }
        $this->calls[] = array($method, $arguments);

        return $this;
    }

    /**
     * Removes a method to call after service initialization.
     *
     * @param string $method The method name to remove
     *
     * @return Definition The current instance
     *
     * @api
     */
    public function removeMethodCall($method)
    {
        foreach ($this->calls as $i => $call) {
            if ($call[0] === $method) {
                unset($this->calls[$i]);
                break;
            }
        }

        return $this;
    }

    /**
     * Check if the current definition has a given method to call after service initialization.
     *
     * @param string $method The method name to search for
     *
     * @return Boolean
     *
     * @api
     */
    public function hasMethodCall($method)
    {
        foreach ($this->calls as $call) {
            if ($call[0] === $method) {
                return true;
            }
        }

        return false;
    }

    /**
     * Gets the methods to call after service initialization.
     *
     * @return array An array of method calls
     *
     * @api
     */
    public function getMethodCalls()
    {
        return $this->calls;
    }

    /**
     * Sets tags for this definition
     *
     * @param array $tags
     *
     * @return Definition the current instance
     *
     * @api
     */
    public function setTags(array $tags)
    {
        $this->tags = $tags;

        return $this;
    }

    /**
     * Returns all tags.
     *
     * @return array An array of tags
     *
     * @api
     */
    public function getTags()
    {
        return $this->tags;
    }

    /**
     * Gets a tag by name.
     *
     * @param string $name The tag name
     *
     * @return array An array of attributes
     *
     * @api
     */
    public function getTag($name)
    {
        return isset($this->tags[$name]) ? $this->tags[$name] : array();
    }

    /**
     * Adds a tag for this definition.
     *
     * @param string $name       The tag name
     * @param array  $attributes An array of attributes
     *
     * @return Definition The current instance
     *
     * @api
     */
    public function addTag($name, array $attributes = array())
    {
        $this->tags[$name][] = $attributes;

        return $this;
    }

    /**
     * Whether this definition has a tag with the given name
     *
     * @param string $name
     *
     * @return Boolean
     *
     * @api
     */
    public function hasTag($name)
    {
        return isset($this->tags[$name]);
    }

    /**
     * Clears all tags for a given name.
     *
     * @param string $name The tag name
     *
     * @return Definition
     */
    public function clearTag($name)
    {
        if (isset($this->tags[$name])) {
            unset($this->tags[$name]);
        }

        return $this;
    }

    /**
     * Clears the tags for this definition.
     *
     * @return Definition The current instance
     *
     * @api
     */
    public function clearTags()
    {
        $this->tags = array();

        return $this;
    }

    /**
     * Sets a file to require before creating the service.
     *
     * @param string $file A full pathname to include
     *
     * @return Definition The current instance
     *
     * @api
     */
    public function setFile($file)
    {
        $this->file = $file;

        return $this;
    }

    /**
     * Gets the file to require before creating the service.
     *
     * @return string|null The full pathname to include
     *
     * @api
     */
    public function getFile()
    {
        return $this->file;
    }

    /**
     * Sets the scope of the service
     *
     * @param string $scope Whether the service must be shared or not
     *
     * @return Definition The current instance
     *
     * @api
     */
    public function setScope($scope)
    {
        $this->scope = $scope;

        return $this;
    }

    /**
     * Returns the scope of the service
     *
     * @return string
     *
     * @api
     */
    public function getScope()
    {
        return $this->scope;
    }

    /**
     * Sets the visibility of this service.
     *
     * @param Boolean $boolean
     *
     * @return Definition The current instance
     *
     * @api
     */
    public function setPublic($boolean)
    {
        $this->public = (Boolean) $boolean;

        return $this;
    }

    /**
     * Whether this service is public facing
     *
     * @return Boolean
     *
     * @api
     */
    public function isPublic()
    {
        return $this->public;
    }

    /**
     * Sets the synchronized flag of this service.
     *
     * @param Boolean $boolean
     *
     * @return Definition The current instance
     *
     * @api
     */
    public function setSynchronized($boolean)
    {
        $this->synchronized = (Boolean) $boolean;

        return $this;
    }

    /**
     * Whether this service is synchronized.
     *
     * @return Boolean
     *
     * @api
     */
    public function isSynchronized()
    {
        return $this->synchronized;
    }

    /**
     * Sets the lazy flag of this service.
     *
     * @param Boolean $lazy
     *
     * @return Definition The current instance
     */
    public function setLazy($lazy)
    {
        $this->lazy = (Boolean) $lazy;

        return $this;
    }

    /**
     * Whether this service is lazy.
     *
     * @return Boolean
     */
    public function isLazy()
    {
        return $this->lazy;
    }

    /**
     * Sets whether this definition is synthetic, that is not constructed by the
     * container, but dynamically injected.
     *
     * @param Boolean $boolean
     *
     * @return Definition the current instance
     *
     * @api
     */
    public function setSynthetic($boolean)
    {
        $this->synthetic = (Boolean) $boolean;

        return $this;
    }

    /**
     * Whether this definition is synthetic, that is not constructed by the
     * container, but dynamically injected.
     *
     * @return Boolean
     *
     * @api
     */
    public function isSynthetic()
    {
        return $this->synthetic;
    }

    /**
     * Whether this definition is abstract, that means it merely serves as a
     * template for other definitions.
     *
     * @param Boolean $boolean
     *
     * @return Definition the current instance
     *
     * @api
     */
    public function setAbstract($boolean)
    {
        $this->abstract = (Boolean) $boolean;

        return $this;
    }

    /**
     * Whether this definition is abstract, that means it merely serves as a
     * template for other definitions.
     *
     * @return Boolean
     *
     * @api
     */
    public function isAbstract()
    {
        return $this->abstract;
    }

    /**
     * Sets a configurator to call after the service is fully initialized.
     *
     * @param callable $callable A PHP callable
     *
     * @return Definition The current instance
     *
     * @api
     */
    public function setConfigurator($callable)
    {
        $this->configurator = $callable;

        return $this;
    }

    /**
     * Gets the configurator to call after the service is fully initialized.
     *
     * @return callable|null The PHP callable to call
     *
     * @api
     */
    public function getConfigurator()
    {
        return $this->configurator;
    }
}
PK��Z�u�ii8Symfony/Component/DependencyInjection/ContainerAware.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

/**
 * A simple implementation of ContainerAwareInterface.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
abstract class ContainerAware implements ContainerAwareInterface
{
    /**
     * @var ContainerInterface
     *
     * @api
     */
    protected $container;

    /**
     * Sets the Container associated with this Controller.
     *
     * @param ContainerInterface $container A ContainerInterface instance
     *
     * @api
     */
    public function setContainer(ContainerInterface $container = null)
    {
        $this->container = $container;
    }
}
PK��Z�H8��=Symfony/Component/DependencyInjection/ContainerAwareTrait.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

/**
 * ContainerAware trait.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
trait ContainerAwareTrait
{
    /**
     * @var ContainerInterface
     */
    protected $container;

    /**
     * Sets the Container associated with this Controller.
     *
     * @param ContainerInterface $container A ContainerInterface instance
     */
    public function setContainer(ContainerInterface $container = null)
    {
        $this->container = $container;
    }
}
PK��Z����BSymfony/Component/DependencyInjection/TaggedContainerInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

/**
 * TaggedContainerInterface is the interface implemented when a container knows how to deals with tags.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface TaggedContainerInterface extends ContainerInterface
{
    /**
     * Returns service ids for a given tag.
     *
     * @param string $name The tag name
     *
     * @return array An array of tags
     *
     * @api
     */
    public function findTaggedServiceIds($name);
}
PK��Z��A�:$:$;Symfony/Component/DependencyInjection/Dumper/YamlDumper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Dumper;

use Symfony\Component\Yaml\Dumper as YmlDumper;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Parameter;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\ExpressionLanguage\Expression;

/**
 * YamlDumper dumps a service container as a YAML string.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class YamlDumper extends Dumper
{
    private $dumper;

    /**
     * Constructor.
     *
     * @param ContainerBuilder $container The service container to dump
     *
     * @api
     */
    public function __construct(ContainerBuilder $container)
    {
        parent::__construct($container);

        $this->dumper = new YmlDumper();
    }

    /**
     * Dumps the service container as an YAML string.
     *
     * @param array $options An array of options
     *
     * @return string A YAML string representing of the service container
     *
     * @api
     */
    public function dump(array $options = array())
    {
        return $this->addParameters()."\n".$this->addServices();
    }

    /**
     * Adds a service
     *
     * @param string     $id
     * @param Definition $definition
     *
     * @return string
     */
    private function addService($id, $definition)
    {
        $code = "    $id:\n";
        if ($definition->getClass()) {
            $code .= sprintf("        class: %s\n", $definition->getClass());
        }

        if (!$definition->isPublic()) {
            $code .= "        public: false\n";
        }

        $tagsCode = '';
        foreach ($definition->getTags() as $name => $tags) {
            foreach ($tags as $attributes) {
                $att = array();
                foreach ($attributes as $key => $value) {
                    $att[] = sprintf('%s: %s', $this->dumper->dump($key), $this->dumper->dump($value));
                }
                $att = $att ? ', '.implode(' ', $att) : '';

                $tagsCode .= sprintf("            - { name: %s%s }\n", $this->dumper->dump($name), $att);
            }
        }
        if ($tagsCode) {
            $code .= "        tags:\n".$tagsCode;
        }

        if ($definition->getFile()) {
            $code .= sprintf("        file: %s\n", $definition->getFile());
        }

        if ($definition->isSynthetic()) {
            $code .= sprintf("        synthetic: true\n");
        }

        if ($definition->isSynchronized()) {
            $code .= sprintf("        synchronized: true\n");
        }

        if ($definition->getFactoryClass()) {
            $code .= sprintf("        factory_class: %s\n", $definition->getFactoryClass());
        }

        if ($definition->isLazy()) {
            $code .= sprintf("        lazy: true\n");
        }

        if ($definition->getFactoryMethod()) {
            $code .= sprintf("        factory_method: %s\n", $definition->getFactoryMethod());
        }

        if ($definition->getFactoryService()) {
            $code .= sprintf("        factory_service: %s\n", $definition->getFactoryService());
        }

        if ($definition->getArguments()) {
            $code .= sprintf("        arguments: %s\n", $this->dumper->dump($this->dumpValue($definition->getArguments()), 0));
        }

        if ($definition->getProperties()) {
            $code .= sprintf("        properties: %s\n", $this->dumper->dump($this->dumpValue($definition->getProperties()), 0));
        }

        if ($definition->getMethodCalls()) {
            $code .= sprintf("        calls:\n%s\n", $this->dumper->dump($this->dumpValue($definition->getMethodCalls()), 1, 12));
        }

        if (ContainerInterface::SCOPE_CONTAINER !== $scope = $definition->getScope()) {
            $code .= sprintf("        scope: %s\n", $scope);
        }

        if ($callable = $definition->getConfigurator()) {
            if (is_array($callable)) {
                if ($callable[0] instanceof Reference) {
                    $callable = array($this->getServiceCall((string) $callable[0], $callable[0]), $callable[1]);
                } else {
                    $callable = array($callable[0], $callable[1]);
                }
            }

            $code .= sprintf("        configurator: %s\n", $this->dumper->dump($callable, 0));
        }

        return $code;
    }

    /**
     * Adds a service alias
     *
     * @param string $alias
     * @param Alias  $id
     *
     * @return string
     */
    private function addServiceAlias($alias, $id)
    {
        if ($id->isPublic()) {
            return sprintf("    %s: @%s\n", $alias, $id);
        } else {
            return sprintf("    %s:\n        alias: %s\n        public: false", $alias, $id);
        }
    }

    /**
     * Adds services
     *
     * @return string
     */
    private function addServices()
    {
        if (!$this->container->getDefinitions()) {
            return '';
        }

        $code = "services:\n";
        foreach ($this->container->getDefinitions() as $id => $definition) {
            $code .= $this->addService($id, $definition);
        }

        $aliases = $this->container->getAliases();
        foreach ($aliases as $alias => $id) {
            while (isset($aliases[(string) $id])) {
                $id = $aliases[(string) $id];
            }
            $code .= $this->addServiceAlias($alias, $id);
        }

        return $code;
    }

    /**
     * Adds parameters
     *
     * @return string
     */
    private function addParameters()
    {
        if (!$this->container->getParameterBag()->all()) {
            return '';
        }

        $parameters = $this->prepareParameters($this->container->getParameterBag()->all(), $this->container->isFrozen());

        return $this->dumper->dump(array('parameters' => $parameters), 2);
    }

    /**
     * Dumps the value to YAML format
     *
     * @param mixed $value
     *
     * @return mixed
     *
     * @throws RuntimeException When trying to dump object or resource
     */
    private function dumpValue($value)
    {
        if (is_array($value)) {
            $code = array();
            foreach ($value as $k => $v) {
                $code[$k] = $this->dumpValue($v);
            }

            return $code;
        } elseif ($value instanceof Reference) {
            return $this->getServiceCall((string) $value, $value);
        } elseif ($value instanceof Parameter) {
            return $this->getParameterCall((string) $value);
        } elseif ($value instanceof Expression) {
            return $this->getExpressionCall((string) $value);
        } elseif (is_object($value) || is_resource($value)) {
            throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.');
        }

        return $value;
    }

    /**
     * Gets the service call.
     *
     * @param string    $id
     * @param Reference $reference
     *
     * @return string
     */
    private function getServiceCall($id, Reference $reference = null)
    {
        if (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) {
            return sprintf('@?%s', $id);
        }

        return sprintf('@%s', $id);
    }

    /**
     * Gets parameter call.
     *
     * @param string $id
     *
     * @return string
     */
    private function getParameterCall($id)
    {
        return sprintf('%%%s%%', $id);
    }

    private function getExpressionCall($expression)
    {
        return sprintf('@=%s', $expression);
    }

    /**
     * Prepares parameters.
     *
     * @param array   $parameters
     * @param Boolean $escape
     *
     * @return array
     */
    private function prepareParameters($parameters, $escape = true)
    {
        $filtered = array();
        foreach ($parameters as $key => $value) {
            if (is_array($value)) {
                $value = $this->prepareParameters($value, $escape);
            } elseif ($value instanceof Reference || is_string($value) && 0 === strpos($value, '@')) {
                $value = '@'.$value;
            }

            $filtered[$key] = $value;
        }

        return $escape ? $this->escape($filtered) : $filtered;
    }

    /**
     * Escapes arguments
     *
     * @param array $arguments
     *
     * @return array
     */
    private function escape($arguments)
    {
        $args = array();
        foreach ($arguments as $k => $v) {
            if (is_array($v)) {
                $args[$k] = $this->escape($v);
            } elseif (is_string($v)) {
                $args[$k] = str_replace('%', '%%', $v);
            } else {
                $args[$k] = $v;
            }
        }

        return $args;
    }
}
PK��ZN/�++7Symfony/Component/DependencyInjection/Dumper/Dumper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Dumper;

use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * Dumper is the abstract class for all built-in dumpers.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
abstract class Dumper implements DumperInterface
{
    protected $container;

    /**
     * Constructor.
     *
     * @param ContainerBuilder $container The service container to dump
     *
     * @api
     */
    public function __construct(ContainerBuilder $container)
    {
        $this->container = $container;
    }
}
PK��Z����%�%?Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Dumper;

use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Parameter;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;

/**
 * GraphvizDumper dumps a service container as a graphviz file.
 *
 * You can convert the generated dot file with the dot utility (http://www.graphviz.org/):
 *
 *   dot -Tpng container.dot > foo.png
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class GraphvizDumper extends Dumper
{
    private $nodes;
    private $edges;
    private $options = array(
            'graph' => array('ratio' => 'compress'),
            'node'  => array('fontsize' => 11, 'fontname' => 'Arial', 'shape' => 'record'),
            'edge'  => array('fontsize' => 9, 'fontname' => 'Arial', 'color' => 'grey', 'arrowhead' => 'open', 'arrowsize' => 0.5),
            'node.instance' => array('fillcolor' => '#9999ff', 'style' => 'filled'),
            'node.definition' => array('fillcolor' => '#eeeeee'),
            'node.missing' => array('fillcolor' => '#ff9999', 'style' => 'filled'),
        );

    /**
     * Dumps the service container as a graphviz graph.
     *
     * Available options:
     *
     *  * graph: The default options for the whole graph
     *  * node: The default options for nodes
     *  * edge: The default options for edges
     *  * node.instance: The default options for services that are defined directly by object instances
     *  * node.definition: The default options for services that are defined via service definition instances
     *  * node.missing: The default options for missing services
     *
     * @param array $options An array of options
     *
     * @return string The dot representation of the service container
     */
    public function dump(array $options = array())
    {
        foreach (array('graph', 'node', 'edge', 'node.instance', 'node.definition', 'node.missing') as $key) {
            if (isset($options[$key])) {
                $this->options[$key] = array_merge($this->options[$key], $options[$key]);
            }
        }

        $this->nodes = $this->findNodes();

        $this->edges = array();
        foreach ($this->container->getDefinitions() as $id => $definition) {
            $this->edges[$id] = array_merge(
                $this->findEdges($id, $definition->getArguments(), true, ''),
                $this->findEdges($id, $definition->getProperties(), false, '')
            );

            foreach ($definition->getMethodCalls() as $call) {
                $this->edges[$id] = array_merge(
                    $this->edges[$id],
                    $this->findEdges($id, $call[1], false, $call[0].'()')
                );
            }
        }

        return $this->startDot().$this->addNodes().$this->addEdges().$this->endDot();
    }

    /**
     * Returns all nodes.
     *
     * @return string A string representation of all nodes
     */
    private function addNodes()
    {
        $code = '';
        foreach ($this->nodes as $id => $node) {
            $aliases = $this->getAliases($id);

            $code .= sprintf("  node_%s [label=\"%s\\n%s\\n\", shape=%s%s];\n", $this->dotize($id), $id.($aliases ? ' ('.implode(', ', $aliases).')' : ''), $node['class'], $this->options['node']['shape'], $this->addAttributes($node['attributes']));
        }

        return $code;
    }

    /**
     * Returns all edges.
     *
     * @return string A string representation of all edges
     */
    private function addEdges()
    {
        $code = '';
        foreach ($this->edges as $id => $edges) {
            foreach ($edges as $edge) {
                $code .= sprintf("  node_%s -> node_%s [label=\"%s\" style=\"%s\"];\n", $this->dotize($id), $this->dotize($edge['to']), $edge['name'], $edge['required'] ? 'filled' : 'dashed');
            }
        }

        return $code;
    }

    /**
     * Finds all edges belonging to a specific service id.
     *
     * @param string  $id        The service id used to find edges
     * @param array   $arguments An array of arguments
     * @param Boolean $required
     * @param string  $name
     *
     * @return array An array of edges
     */
    private function findEdges($id, $arguments, $required, $name)
    {
        $edges = array();
        foreach ($arguments as $argument) {
            if ($argument instanceof Parameter) {
                $argument = $this->container->hasParameter($argument) ? $this->container->getParameter($argument) : null;
            } elseif (is_string($argument) && preg_match('/^%([^%]+)%$/', $argument, $match)) {
                $argument = $this->container->hasParameter($match[1]) ? $this->container->getParameter($match[1]) : null;
            }

            if ($argument instanceof Reference) {
                if (!$this->container->has((string) $argument)) {
                    $this->nodes[(string) $argument] = array('name' => $name, 'required' => $required, 'class' => '', 'attributes' => $this->options['node.missing']);
                }

                $edges[] = array('name' => $name, 'required' => $required, 'to' => $argument);
            } elseif (is_array($argument)) {
                $edges = array_merge($edges, $this->findEdges($id, $argument, $required, $name));
            }
        }

        return $edges;
    }

    /**
     * Finds all nodes.
     *
     * @return array An array of all nodes
     */
    private function findNodes()
    {
        $nodes = array();

        $container = $this->cloneContainer();

        foreach ($container->getDefinitions() as $id => $definition) {
            $nodes[$id] = array('class' => str_replace('\\', '\\\\', $this->container->getParameterBag()->resolveValue($definition->getClass())), 'attributes' => array_merge($this->options['node.definition'], array('style' => ContainerInterface::SCOPE_PROTOTYPE !== $definition->getScope() ? 'filled' : 'dotted')));

            $container->setDefinition($id, new Definition('stdClass'));
        }

        foreach ($container->getServiceIds() as $id) {
            $service = $container->get($id);

            if (in_array($id, array_keys($container->getAliases()))) {
                continue;
            }

            if (!$container->hasDefinition($id)) {
                $class = ('service_container' === $id) ? get_class($this->container) : get_class($service);
                $nodes[$id] = array('class' => str_replace('\\', '\\\\', $class), 'attributes' => $this->options['node.instance']);
            }
        }

        return $nodes;
    }

    private function cloneContainer()
    {
        $parameterBag = new ParameterBag($this->container->getParameterBag()->all());

        $container = new ContainerBuilder($parameterBag);
        $container->setDefinitions($this->container->getDefinitions());
        $container->setAliases($this->container->getAliases());
        $container->setResources($this->container->getResources());
        foreach ($this->container->getScopes() as $scope) {
            $container->addScope($scope);
        }
        foreach ($this->container->getExtensions() as $extension) {
            $container->registerExtension($extension);
        }

        return $container;
    }

    /**
     * Returns the start dot.
     *
     * @return string The string representation of a start dot
     */
    private function startDot()
    {
        return sprintf("digraph sc {\n  %s\n  node [%s];\n  edge [%s];\n\n",
            $this->addOptions($this->options['graph']),
            $this->addOptions($this->options['node']),
            $this->addOptions($this->options['edge'])
        );
    }

    /**
     * Returns the end dot.
     *
     * @return string
     */
    private function endDot()
    {
        return "}\n";
    }

    /**
     * Adds attributes
     *
     * @param array $attributes An array of attributes
     *
     * @return string A comma separated list of attributes
     */
    private function addAttributes($attributes)
    {
        $code = array();
        foreach ($attributes as $k => $v) {
            $code[] = sprintf('%s="%s"', $k, $v);
        }

        return $code ? ', '.implode(', ', $code) : '';
    }

    /**
     * Adds options
     *
     * @param array $options An array of options
     *
     * @return string A space separated list of options
     */
    private function addOptions($options)
    {
        $code = array();
        foreach ($options as $k => $v) {
            $code[] = sprintf('%s="%s"', $k, $v);
        }

        return implode(' ', $code);
    }

    /**
     * Dotizes an identifier.
     *
     * @param string $id The identifier to dotize
     *
     * @return string A dotized string
     */
    private function dotize($id)
    {
        return strtolower(preg_replace('/[^\w]/i', '_', $id));
    }

    /**
     * Compiles an array of aliases for a specified service id.
     *
     * @param string $id A service id
     *
     * @return array An array of aliases
     */
    private function getAliases($id)
    {
        $aliases = array();
        foreach ($this->container->getAliases() as $alias => $origin) {
            if ($id == $origin) {
                $aliases[] = $alias;
            }
        }

        return $aliases;
    }
}
PK��Z"�^� � �:Symfony/Component/DependencyInjection/Dumper/PhpDumper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Dumper;

use Symfony\Component\DependencyInjection\Variable;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Parameter;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface as ProxyDumper;
use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper;
use Symfony\Component\DependencyInjection\ExpressionLanguage;
use Symfony\Component\ExpressionLanguage\Expression;

/**
 * PhpDumper dumps a service container as a PHP class.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @api
 */
class PhpDumper extends Dumper
{
    /**
     * Characters that might appear in the generated variable name as first character
     * @var string
     */
    const FIRST_CHARS = 'abcdefghijklmnopqrstuvwxyz';

    /**
     * Characters that might appear in the generated variable name as any but the first character
     * @var string
     */
    const NON_FIRST_CHARS = 'abcdefghijklmnopqrstuvwxyz0123456789_';

    private $inlinedDefinitions;
    private $definitionVariables;
    private $referenceVariables;
    private $variableCount;
    private $reservedVariables = array('instance', 'class');
    private $expressionLanguage;

    /**
     * @var \Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface
     */
    private $proxyDumper;

    /**
     * {@inheritDoc}
     *
     * @api
     */
    public function __construct(ContainerBuilder $container)
    {
        parent::__construct($container);

        $this->inlinedDefinitions = new \SplObjectStorage();
    }

    /**
     * Sets the dumper to be used when dumping proxies in the generated container.
     *
     * @param ProxyDumper $proxyDumper
     */
    public function setProxyDumper(ProxyDumper $proxyDumper)
    {
        $this->proxyDumper = $proxyDumper;
    }

    /**
     * Dumps the service container as a PHP class.
     *
     * Available options:
     *
     *  * class:      The class name
     *  * base_class: The base class name
     *  * namespace:  The class namespace
     *
     * @param array $options An array of options
     *
     * @return string A PHP class representing of the service container
     *
     * @api
     */
    public function dump(array $options = array())
    {
        $options = array_merge(array(
            'class'      => 'ProjectServiceContainer',
            'base_class' => 'Container',
            'namespace' => '',
        ), $options);

        $code = $this->startClass($options['class'], $options['base_class'], $options['namespace']);

        if ($this->container->isFrozen()) {
            $code .= $this->addFrozenConstructor();
        } else {
            $code .= $this->addConstructor();
        }

        $code .=
            $this->addServices().
            $this->addDefaultParametersMethod().
            $this->endClass().
            $this->addProxyClasses()
        ;

        return $code;
    }

    /**
     * Retrieves the currently set proxy dumper or instantiates one.
     *
     * @return ProxyDumper
     */
    private function getProxyDumper()
    {
        if (!$this->proxyDumper) {
            $this->proxyDumper = new NullDumper();
        }

        return $this->proxyDumper;
    }

    /**
     * Generates Service local temp variables.
     *
     * @param string $cId
     * @param string $definition
     *
     * @return string
     */
    private function addServiceLocalTempVariables($cId, $definition)
    {
        static $template = "        \$%s = %s;\n";

        $localDefinitions = array_merge(
            array($definition),
            $this->getInlinedDefinitions($definition)
        );

        $calls = $behavior = array();
        foreach ($localDefinitions as $iDefinition) {
            $this->getServiceCallsFromArguments($iDefinition->getArguments(), $calls, $behavior);
            $this->getServiceCallsFromArguments($iDefinition->getMethodCalls(), $calls, $behavior);
            $this->getServiceCallsFromArguments($iDefinition->getProperties(), $calls, $behavior);
        }

        $code = '';
        foreach ($calls as $id => $callCount) {
            if ('service_container' === $id || $id === $cId) {
                continue;
            }

            if ($callCount > 1) {
                $name = $this->getNextVariableName();
                $this->referenceVariables[$id] = new Variable($name);

                if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $behavior[$id]) {
                    $code .= sprintf($template, $name, $this->getServiceCall($id));
                } else {
                    $code .= sprintf($template, $name, $this->getServiceCall($id, new Reference($id, ContainerInterface::NULL_ON_INVALID_REFERENCE)));
                }
            }
        }

        if ('' !== $code) {
            $code .= "\n";
        }

        return $code;
    }

    /**
     * Generates code for the proxies to be attached after the container class
     *
     * @return string
     */
    private function addProxyClasses()
    {
        /* @var $definitions Definition[] */
        $definitions = array_filter(
            $this->container->getDefinitions(),
            array($this->getProxyDumper(), 'isProxyCandidate')
        );
        $code = '';

        foreach ($definitions as $definition) {
            $code .= "\n" . $this->getProxyDumper()->getProxyCode($definition);
        }

        return $code;
    }

    /**
     * Generates the require_once statement for service includes.
     *
     * @param string     $id         The service id
     * @param Definition $definition
     *
     * @return string
     */
    private function addServiceInclude($id, $definition)
    {
        $template = "        require_once %s;\n";
        $code = '';

        if (null !== $file = $definition->getFile()) {
            $code .= sprintf($template, $this->dumpValue($file));
        }

        foreach ($this->getInlinedDefinitions($definition) as $definition) {
            if (null !== $file = $definition->getFile()) {
                $code .= sprintf($template, $this->dumpValue($file));
            }
        }

        if ('' !== $code) {
            $code .= "\n";
        }

        return $code;
    }

    /**
     * Generates the inline definition of a service.
     *
     * @param string     $id
     * @param Definition $definition
     *
     * @return string
     *
     * @throws RuntimeException When the factory definition is incomplete
     * @throws ServiceCircularReferenceException When a circular reference is detected
     */
    private function addServiceInlinedDefinitions($id, $definition)
    {
        $code = '';
        $variableMap = $this->definitionVariables;
        $nbOccurrences = new \SplObjectStorage();
        $processed = new \SplObjectStorage();
        $inlinedDefinitions = $this->getInlinedDefinitions($definition);

        foreach ($inlinedDefinitions as $definition) {
            if (false === $nbOccurrences->contains($definition)) {
                $nbOccurrences->offsetSet($definition, 1);
            } else {
                $i = $nbOccurrences->offsetGet($definition);
                $nbOccurrences->offsetSet($definition, $i + 1);
            }
        }

        foreach ($inlinedDefinitions as $sDefinition) {
            if ($processed->contains($sDefinition)) {
                continue;
            }
            $processed->offsetSet($sDefinition);

            $class = $this->dumpValue($sDefinition->getClass());
            if ($nbOccurrences->offsetGet($sDefinition) > 1 || $sDefinition->getMethodCalls() || $sDefinition->getProperties() || null !== $sDefinition->getConfigurator() || false !== strpos($class, '$')) {
                $name = $this->getNextVariableName();
                $variableMap->offsetSet($sDefinition, new Variable($name));

                // a construct like:
                // $a = new ServiceA(ServiceB $b); $b = new ServiceB(ServiceA $a);
                // this is an indication for a wrong implementation, you can circumvent this problem
                // by setting up your service structure like this:
                // $b = new ServiceB();
                // $a = new ServiceA(ServiceB $b);
                // $b->setServiceA(ServiceA $a);
                if ($this->hasReference($id, $sDefinition->getArguments())) {
                    throw new ServiceCircularReferenceException($id, array($id));
                }

                $code .= $this->addNewInstance($id, $sDefinition, '$'.$name, ' = ');

                if (!$this->hasReference($id, $sDefinition->getMethodCalls(), true) && !$this->hasReference($id, $sDefinition->getProperties(), true)) {
                    $code .= $this->addServiceMethodCalls(null, $sDefinition, $name);
                    $code .= $this->addServiceProperties(null, $sDefinition, $name);
                    $code .= $this->addServiceConfigurator(null, $sDefinition, $name);
                }

                $code .= "\n";
            }
        }

        return $code;
    }

    /**
     * Adds the service return statement.
     *
     * @param string     $id         Service id
     * @param Definition $definition
     *
     * @return string
     */
    private function addServiceReturn($id, $definition)
    {
        if ($this->isSimpleInstance($id, $definition)) {
            return "    }\n";
        }

        return "\n        return \$instance;\n    }\n";
    }

    /**
     * Generates the service instance.
     *
     * @param string     $id
     * @param Definition $definition
     *
     * @return string
     *
     * @throws InvalidArgumentException
     * @throws RuntimeException
     */
    private function addServiceInstance($id, $definition)
    {
        $class = $this->dumpValue($definition->getClass());

        if (0 === strpos($class, "'") && !preg_match('/^\'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) {
            throw new InvalidArgumentException(sprintf('"%s" is not a valid class name for the "%s" service.', $class, $id));
        }

        $simple           = $this->isSimpleInstance($id, $definition);
        $isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition);
        $instantiation    = '';

        if (!$isProxyCandidate && ContainerInterface::SCOPE_CONTAINER === $definition->getScope()) {
            $instantiation = "\$this->services['$id'] = ".($simple ? '' : '$instance');
        } elseif (!$isProxyCandidate && ContainerInterface::SCOPE_PROTOTYPE !== $scope = $definition->getScope()) {
            $instantiation = "\$this->services['$id'] = \$this->scopedServices['$scope']['$id'] = ".($simple ? '' : '$instance');
        } elseif (!$simple) {
            $instantiation = '$instance';
        }

        $return = '';
        if ($simple) {
            $return = 'return ';
        } else {
            $instantiation .= ' = ';
        }

        $code = $this->addNewInstance($id, $definition, $return, $instantiation);

        if (!$simple) {
            $code .= "\n";
        }

        return $code;
    }

    /**
     * Checks if the definition is a simple instance.
     *
     * @param string     $id
     * @param Definition $definition
     *
     * @return Boolean
     */
    private function isSimpleInstance($id, $definition)
    {
        foreach (array_merge(array($definition), $this->getInlinedDefinitions($definition)) as $sDefinition) {
            if ($definition !== $sDefinition && !$this->hasReference($id, $sDefinition->getMethodCalls())) {
                continue;
            }

            if ($sDefinition->getMethodCalls() || $sDefinition->getProperties() || $sDefinition->getConfigurator()) {
                return false;
            }
        }

        return true;
    }

    /**
     * Adds method calls to a service definition.
     *
     * @param string     $id
     * @param Definition $definition
     * @param string     $variableName
     *
     * @return string
     */
    private function addServiceMethodCalls($id, $definition, $variableName = 'instance')
    {
        $calls = '';
        foreach ($definition->getMethodCalls() as $call) {
            $arguments = array();
            foreach ($call[1] as $value) {
                $arguments[] = $this->dumpValue($value);
            }

            $calls .= $this->wrapServiceConditionals($call[1], sprintf("        \$%s->%s(%s);\n", $variableName, $call[0], implode(', ', $arguments)));
        }

        return $calls;
    }

    private function addServiceProperties($id, $definition, $variableName = 'instance')
    {
        $code = '';
        foreach ($definition->getProperties() as $name => $value) {
            $code .= sprintf("        \$%s->%s = %s;\n", $variableName, $name, $this->dumpValue($value));
        }

        return $code;
    }

    /**
     * Generates the inline definition setup.
     *
     * @param string     $id
     * @param Definition $definition
     * @return string
     */
    private function addServiceInlinedDefinitionsSetup($id, $definition)
    {
        $this->referenceVariables[$id] = new Variable('instance');

        $code = '';
        $processed = new \SplObjectStorage();
        foreach ($this->getInlinedDefinitions($definition) as $iDefinition) {
            if ($processed->contains($iDefinition)) {
                continue;
            }
            $processed->offsetSet($iDefinition);

            if (!$this->hasReference($id, $iDefinition->getMethodCalls(), true) && !$this->hasReference($id, $iDefinition->getProperties(), true)) {
                continue;
            }

            // if the instance is simple, the return statement has already been generated
            // so, the only possible way to get there is because of a circular reference
            if ($this->isSimpleInstance($id, $definition)) {
                throw new ServiceCircularReferenceException($id, array($id));
            }

            $name = (string) $this->definitionVariables->offsetGet($iDefinition);
            $code .= $this->addServiceMethodCalls(null, $iDefinition, $name);
            $code .= $this->addServiceProperties(null, $iDefinition, $name);
            $code .= $this->addServiceConfigurator(null, $iDefinition, $name);
        }

        if ('' !== $code) {
            $code .= "\n";
        }

        return $code;
    }

    /**
     * Adds configurator definition
     *
     * @param string     $id
     * @param Definition $definition
     * @param string     $variableName
     *
     * @return string
     */
    private function addServiceConfigurator($id, $definition, $variableName = 'instance')
    {
        if (!$callable = $definition->getConfigurator()) {
            return '';
        }

        if (is_array($callable)) {
            if ($callable[0] instanceof Reference) {
                return sprintf("        %s->%s(\$%s);\n", $this->getServiceCall((string) $callable[0]), $callable[1], $variableName);
            }

            return sprintf("        call_user_func(array(%s, '%s'), \$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName);
        }

        return sprintf("        %s(\$%s);\n", $callable, $variableName);
    }

    /**
     * Adds a service
     *
     * @param string     $id
     * @param Definition $definition
     *
     * @return string
     */
    private function addService($id, $definition)
    {
        $this->definitionVariables = new \SplObjectStorage();
        $this->referenceVariables = array();
        $this->variableCount = 0;

        $return = array();

        if ($definition->isSynthetic()) {
            $return[] = '@throws RuntimeException always since this service is expected to be injected dynamically';
        } elseif ($class = $definition->getClass()) {
            $return[] = sprintf("@return %s A %s instance.", 0 === strpos($class, '%') ? 'object' : $class, $class);
        } elseif ($definition->getFactoryClass()) {
            $return[] = sprintf('@return object An instance returned by %s::%s().', $definition->getFactoryClass(), $definition->getFactoryMethod());
        } elseif ($definition->getFactoryService()) {
            $return[] = sprintf('@return object An instance returned by %s::%s().', $definition->getFactoryService(), $definition->getFactoryMethod());
        }

        $scope = $definition->getScope();
        if (!in_array($scope, array(ContainerInterface::SCOPE_CONTAINER, ContainerInterface::SCOPE_PROTOTYPE))) {
            if ($return && 0 === strpos($return[count($return) - 1], '@return')) {
                $return[] = '';
            }
            $return[] = sprintf("@throws InactiveScopeException when the '%s' service is requested while the '%s' scope is not active", $id, $scope);
        }

        $return = implode("\n     * ", $return);

        $doc = '';
        if (ContainerInterface::SCOPE_PROTOTYPE !== $scope) {
            $doc .= <<<EOF

     *
     * This service is shared.
     * This method always returns the same instance of the service.
EOF;
        }

        if (!$definition->isPublic()) {
            $doc .= <<<EOF

     *
     * This service is private.
     * If you want to be able to request this service from the container directly,
     * make it public, otherwise you might end up with broken code.
EOF;
        }

        if ($definition->isLazy()) {
            $lazyInitialization    = '$lazyLoad = true';
            $lazyInitializationDoc = "\n     * @param boolean \$lazyLoad whether to try lazy-loading the service with a proxy\n     *";
        } else {
            $lazyInitialization    = '';
            $lazyInitializationDoc = '';
        }

        // with proxies, for 5.3.3 compatibility, the getter must be public to be accessible to the initializer
        $isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition);
        $visibility       = $isProxyCandidate ? 'public' : 'protected';
        $code             = <<<EOF

    /**
     * Gets the '$id' service.$doc
     *$lazyInitializationDoc
     * $return
     */
    {$visibility} function get{$this->camelize($id)}Service($lazyInitialization)
    {

EOF;

        $code .= $isProxyCandidate ? $this->getProxyDumper()->getProxyFactoryCode($definition, $id) : '';

        if (!in_array($scope, array(ContainerInterface::SCOPE_CONTAINER, ContainerInterface::SCOPE_PROTOTYPE))) {
            $code .= <<<EOF
        if (!isset(\$this->scopedServices['$scope'])) {
            throw new InactiveScopeException('$id', '$scope');
        }


EOF;
        }

        if ($definition->isSynthetic()) {
            $code .= sprintf("        throw new RuntimeException('You have requested a synthetic service (\"%s\"). The DIC does not know how to construct this service.');\n    }\n", $id);
        } else {
            $code .=
                $this->addServiceInclude($id, $definition).
                $this->addServiceLocalTempVariables($id, $definition).
                $this->addServiceInlinedDefinitions($id, $definition).
                $this->addServiceInstance($id, $definition).
                $this->addServiceInlinedDefinitionsSetup($id, $definition).
                $this->addServiceMethodCalls($id, $definition).
                $this->addServiceProperties($id, $definition).
                $this->addServiceConfigurator($id, $definition).
                $this->addServiceReturn($id, $definition)
            ;
        }

        $this->definitionVariables = null;
        $this->referenceVariables = null;

        return $code;
    }

    /**
     * Adds multiple services
     *
     * @return string
     */
    private function addServices()
    {
        $publicServices = $privateServices = $synchronizers = '';
        $definitions = $this->container->getDefinitions();
        ksort($definitions);
        foreach ($definitions as $id => $definition) {
            if ($definition->isPublic()) {
                $publicServices .= $this->addService($id, $definition);
            } else {
                $privateServices .= $this->addService($id, $definition);
            }

            $synchronizers .= $this->addServiceSynchronizer($id, $definition);
        }

        return $publicServices.$synchronizers.$privateServices;
    }

    /**
     * Adds synchronizer methods.
     *
     * @param string     $id         A service identifier
     * @param Definition $definition A Definition instance
     */
    private function addServiceSynchronizer($id, Definition $definition)
    {
        if (!$definition->isSynchronized()) {
            return;
        }

        $code = '';
        foreach ($this->container->getDefinitions() as $definitionId => $definition) {
            foreach ($definition->getMethodCalls() as $call) {
                foreach ($call[1] as $argument) {
                    if ($argument instanceof Reference && $id == (string) $argument) {
                        $arguments = array();
                        foreach ($call[1] as $value) {
                            $arguments[] = $this->dumpValue($value);
                        }

                        $call = $this->wrapServiceConditionals($call[1], sprintf("\$this->get('%s')->%s(%s);", $definitionId, $call[0], implode(', ', $arguments)));

                        $code .= <<<EOF
        if (\$this->initialized('$definitionId')) {
            $call
        }

EOF;
                    }
                }
            }
        }

        if (!$code) {
            return;
        }

        return <<<EOF

    /**
     * Updates the '$id' service.
     */
    protected function synchronize{$this->camelize($id)}Service()
    {
$code    }

EOF;
    }

    private function addNewInstance($id, Definition $definition, $return, $instantiation)
    {
        $class = $this->dumpValue($definition->getClass());

        $arguments = array();
        foreach ($definition->getArguments() as $value) {
            $arguments[] = $this->dumpValue($value);
        }

        if (null !== $definition->getFactoryMethod()) {
            if (null !== $definition->getFactoryClass()) {
                return sprintf("        $return{$instantiation}call_user_func(array(%s, '%s')%s);\n", $this->dumpValue($definition->getFactoryClass()), $definition->getFactoryMethod(), $arguments ? ', '.implode(', ', $arguments) : '');
            }

            if (null !== $definition->getFactoryService()) {
                return sprintf("        $return{$instantiation}%s->%s(%s);\n", $this->getServiceCall($definition->getFactoryService()), $definition->getFactoryMethod(), implode(', ', $arguments));
            }

            throw new RuntimeException(sprintf('Factory method requires a factory service or factory class in service definition for %s', $id));
        }

        if (false !== strpos($class, '$')) {
            return sprintf("        \$class = %s;\n\n        $return{$instantiation}new \$class(%s);\n", $class, implode(', ', $arguments));
        }

        return sprintf("        $return{$instantiation}new \\%s(%s);\n", substr(str_replace('\\\\', '\\', $class), 1, -1), implode(', ', $arguments));
    }

    /**
     * Adds the class headers.
     *
     * @param string $class     Class name
     * @param string $baseClass The name of the base class
     * @param string $namespace The class namespace
     *
     * @return string
     */
    private function startClass($class, $baseClass, $namespace)
    {
        $bagClass = $this->container->isFrozen() ? 'use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;' : 'use Symfony\Component\DependencyInjection\ParameterBag\\ParameterBag;';
        $namespaceLine = $namespace ? "namespace $namespace;\n" : '';

        return <<<EOF
<?php
$namespaceLine
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
$bagClass

/**
 * $class
 *
 * This class has been auto-generated
 * by the Symfony Dependency Injection Component.
 */
class $class extends $baseClass
{
EOF;
    }

    /**
     * Adds the constructor.
     *
     * @return string
     */
    private function addConstructor()
    {
        $arguments = $this->container->getParameterBag()->all() ? 'new ParameterBag($this->getDefaultParameters())' : null;

        $code = <<<EOF

    /**
     * Constructor.
     */
    public function __construct()
    {
        parent::__construct($arguments);

EOF;

        if (count($scopes = $this->container->getScopes()) > 0) {
            $code .= "\n";
            $code .= "        \$this->scopes = ".$this->dumpValue($scopes).";\n";
            $code .= "        \$this->scopeChildren = ".$this->dumpValue($this->container->getScopeChildren()).";\n";
        }

        $code .= $this->addMethodMap();
        $code .= $this->addAliases();

        $code .= <<<EOF
    }

EOF;

        return $code;
    }

    /**
     * Adds the constructor for a frozen container.
     *
     * @return string
     */
    private function addFrozenConstructor()
    {
        $code = <<<EOF

    /**
     * Constructor.
     */
    public function __construct()
    {
EOF;

        if ($this->container->getParameterBag()->all()) {
            $code .= "\n        \$this->parameters = \$this->getDefaultParameters();\n";
        }

        $code .= <<<EOF

        \$this->services =
        \$this->scopedServices =
        \$this->scopeStacks = array();

        \$this->set('service_container', \$this);

EOF;

        $code .= "\n";
        if (count($scopes = $this->container->getScopes()) > 0) {
            $code .= "        \$this->scopes = ".$this->dumpValue($scopes).";\n";
            $code .= "        \$this->scopeChildren = ".$this->dumpValue($this->container->getScopeChildren()).";\n";
        } else {
            $code .= "        \$this->scopes = array();\n";
            $code .= "        \$this->scopeChildren = array();\n";
        }

        $code .= $this->addMethodMap();
        $code .= $this->addAliases();

        $code .= <<<EOF
    }

EOF;

        return $code;
    }

    /**
     * Adds the methodMap property definition
     *
     * @return string
     */
    private function addMethodMap()
    {
        if (!$definitions = $this->container->getDefinitions()) {
            return '';
        }

        $code = "        \$this->methodMap = array(\n";
        ksort($definitions);
        foreach ($definitions as $id => $definition) {
            $code .= '            '.var_export($id, true).' => '.var_export('get'.$this->camelize($id).'Service', true).",\n";
        }

        return $code . "        );\n";
    }

    /**
     * Adds the aliases property definition
     *
     * @return string
     */
    private function addAliases()
    {
        if (!$aliases = $this->container->getAliases()) {
            if ($this->container->isFrozen()) {
                return "\n        \$this->aliases = array();\n";
            } else {
                return '';
            }
        }

        $code = "        \$this->aliases = array(\n";
        ksort($aliases);
        foreach ($aliases as $alias => $id) {
            $id = (string) $id;
            while (isset($aliases[$id])) {
                $id = (string) $aliases[$id];
            }
            $code .= '            '.var_export($alias, true).' => '.var_export($id, true).",\n";
        }

        return $code . "        );\n";
    }

    /**
     * Adds default parameters method.
     *
     * @return string
     */
    private function addDefaultParametersMethod()
    {
        if (!$this->container->getParameterBag()->all()) {
            return '';
        }

        $parameters = $this->exportParameters($this->container->getParameterBag()->all());

        $code = '';
        if ($this->container->isFrozen()) {
            $code .= <<<EOF

    /**
     * {@inheritdoc}
     */
    public function getParameter(\$name)
    {
        \$name = strtolower(\$name);

        if (!(isset(\$this->parameters[\$name]) || array_key_exists(\$name, \$this->parameters))) {
            throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', \$name));
        }

        return \$this->parameters[\$name];
    }

    /**
     * {@inheritdoc}
     */
    public function hasParameter(\$name)
    {
        \$name = strtolower(\$name);

        return isset(\$this->parameters[\$name]) || array_key_exists(\$name, \$this->parameters);
    }

    /**
     * {@inheritdoc}
     */
    public function setParameter(\$name, \$value)
    {
        throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
    }

    /**
     * {@inheritDoc}
     */
    public function getParameterBag()
    {
        if (null === \$this->parameterBag) {
            \$this->parameterBag = new FrozenParameterBag(\$this->parameters);
        }

        return \$this->parameterBag;
    }
EOF;
        }

        $code .= <<<EOF

    /**
     * Gets the default parameters.
     *
     * @return array An array of the default parameters
     */
    protected function getDefaultParameters()
    {
        return $parameters;
    }

EOF;

        return $code;
    }

    /**
     * Exports parameters.
     *
     * @param array   $parameters
     * @param string  $path
     * @param integer $indent
     *
     * @return string
     *
     * @throws InvalidArgumentException
     */
    private function exportParameters($parameters, $path = '', $indent = 12)
    {
        $php = array();
        foreach ($parameters as $key => $value) {
            if (is_array($value)) {
                $value = $this->exportParameters($value, $path.'/'.$key, $indent + 4);
            } elseif ($value instanceof Variable) {
                throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain variable references. Variable "%s" found in "%s".', $value, $path.'/'.$key));
            } elseif ($value instanceof Definition) {
                throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain service definitions. Definition for "%s" found in "%s".', $value->getClass(), $path.'/'.$key));
            } elseif ($value instanceof Reference) {
                throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain references to other services (reference to service "%s" found in "%s").', $value, $path.'/'.$key));
            } elseif ($value instanceof Expression) {
                throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain expressions. Expression "%s" found in "%s".', $value, $path.'/'.$key));
            } else {
                $value = var_export($value, true);
            }

            $php[] = sprintf('%s%s => %s,', str_repeat(' ', $indent), var_export($key, true), $value);
        }

        return sprintf("array(\n%s\n%s)", implode("\n", $php), str_repeat(' ', $indent - 4));
    }

    /**
     * Ends the class definition.
     *
     * @return string
     */
    private function endClass()
    {
        return <<<EOF
}

EOF;
    }

    /**
     * Wraps the service conditionals.
     *
     * @param string $value
     * @param string $code
     *
     * @return string
     */
    private function wrapServiceConditionals($value, $code)
    {
        if (!$services = ContainerBuilder::getServiceConditionals($value)) {
            return $code;
        }

        $conditions = array();
        foreach ($services as $service) {
            $conditions[] = sprintf("\$this->has('%s')", $service);
        }

        // re-indent the wrapped code
        $code = implode("\n", array_map(function ($line) { return $line ? '    '.$line : $line; }, explode("\n", $code)));

        return sprintf("        if (%s) {\n%s        }\n", implode(' && ', $conditions), $code);
    }

    /**
     * Builds service calls from arguments.
     *
     * @param array  $arguments
     * @param array  &$calls    By reference
     * @param array  &$behavior By reference
     */
    private function getServiceCallsFromArguments(array $arguments, array &$calls, array &$behavior)
    {
        foreach ($arguments as $argument) {
            if (is_array($argument)) {
                $this->getServiceCallsFromArguments($argument, $calls, $behavior);
            } elseif ($argument instanceof Reference) {
                $id = (string) $argument;

                if (!isset($calls[$id])) {
                    $calls[$id] = 0;
                }
                if (!isset($behavior[$id])) {
                    $behavior[$id] = $argument->getInvalidBehavior();
                } elseif (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $behavior[$id]) {
                    $behavior[$id] = $argument->getInvalidBehavior();
                }

                $calls[$id] += 1;
            }
        }
    }

    /**
     * Returns the inline definition.
     *
     * @param Definition $definition
     *
     * @return array
     */
    private function getInlinedDefinitions(Definition $definition)
    {
        if (false === $this->inlinedDefinitions->contains($definition)) {
            $definitions = array_merge(
                $this->getDefinitionsFromArguments($definition->getArguments()),
                $this->getDefinitionsFromArguments($definition->getMethodCalls()),
                $this->getDefinitionsFromArguments($definition->getProperties())
            );

            $this->inlinedDefinitions->offsetSet($definition, $definitions);

            return $definitions;
        }

        return $this->inlinedDefinitions->offsetGet($definition);
    }

    /**
     * Gets the definition from arguments.
     *
     * @param array $arguments
     *
     * @return array
     */
    private function getDefinitionsFromArguments(array $arguments)
    {
        $definitions = array();
        foreach ($arguments as $argument) {
            if (is_array($argument)) {
                $definitions = array_merge($definitions, $this->getDefinitionsFromArguments($argument));
            } elseif ($argument instanceof Definition) {
                $definitions = array_merge(
                    $definitions,
                    $this->getInlinedDefinitions($argument),
                    array($argument)
                );
            }
        }

        return $definitions;
    }

    /**
     * Checks if a service id has a reference.
     *
     * @param string  $id
     * @param array   $arguments
     * @param Boolean $deep
     * @param array   $visited
     *
     * @return Boolean
     */
    private function hasReference($id, array $arguments, $deep = false, array $visited = array())
    {
        foreach ($arguments as $argument) {
            if (is_array($argument)) {
                if ($this->hasReference($id, $argument, $deep, $visited)) {
                    return true;
                }
            } elseif ($argument instanceof Reference) {
                $argumentId = (string) $argument;
                if ($id === $argumentId) {
                    return true;
                }

                if ($deep && !isset($visited[$argumentId])) {
                    $visited[$argumentId] = true;

                    $service = $this->container->getDefinition($argumentId);
                    $arguments = array_merge($service->getMethodCalls(), $service->getArguments(), $service->getProperties());

                    if ($this->hasReference($id, $arguments, $deep, $visited)) {
                        return true;
                    }
                }
            }
        }

        return false;
    }

    /**
     * Dumps values.
     *
     * @param array   $value
     * @param Boolean $interpolate
     *
     * @return string
     *
     * @throws RuntimeException
     */
    private function dumpValue($value, $interpolate = true)
    {
        if (is_array($value)) {
            $code = array();
            foreach ($value as $k => $v) {
                $code[] = sprintf('%s => %s', $this->dumpValue($k, $interpolate), $this->dumpValue($v, $interpolate));
            }

            return sprintf('array(%s)', implode(', ', $code));
        } elseif ($value instanceof Definition) {
            if (null !== $this->definitionVariables && $this->definitionVariables->contains($value)) {
                return $this->dumpValue($this->definitionVariables->offsetGet($value), $interpolate);
            }
            if (count($value->getMethodCalls()) > 0) {
                throw new RuntimeException('Cannot dump definitions which have method calls.');
            }
            if (null !== $value->getConfigurator()) {
                throw new RuntimeException('Cannot dump definitions which have a configurator.');
            }

            $arguments = array();
            foreach ($value->getArguments() as $argument) {
                $arguments[] = $this->dumpValue($argument);
            }
            $class = $this->dumpValue($value->getClass());

            if (false !== strpos($class, '$')) {
                throw new RuntimeException('Cannot dump definitions which have a variable class name.');
            }

            if (null !== $value->getFactoryMethod()) {
                if (null !== $value->getFactoryClass()) {
                    return sprintf("call_user_func(array(%s, '%s')%s)", $this->dumpValue($value->getFactoryClass()), $value->getFactoryMethod(), count($arguments) > 0 ? ', '.implode(', ', $arguments) : '');
                } elseif (null !== $value->getFactoryService()) {
                    return sprintf("%s->%s(%s)", $this->getServiceCall($value->getFactoryService()), $value->getFactoryMethod(), implode(', ', $arguments));
                } else {
                    throw new RuntimeException('Cannot dump definitions which have factory method without factory service or factory class.');
                }
            }

            return sprintf("new \\%s(%s)", substr(str_replace('\\\\', '\\', $class), 1, -1), implode(', ', $arguments));
        } elseif ($value instanceof Variable) {
            return '$'.$value;
        } elseif ($value instanceof Reference) {
            if (null !== $this->referenceVariables && isset($this->referenceVariables[$id = (string) $value])) {
                return $this->dumpValue($this->referenceVariables[$id], $interpolate);
            }

            return $this->getServiceCall((string) $value, $value);
        } elseif ($value instanceof Expression) {
            return $this->getExpressionLanguage()->compile((string) $value, array('container'));
        } elseif ($value instanceof Parameter) {
            return $this->dumpParameter($value);
        } elseif (true === $interpolate && is_string($value)) {
            if (preg_match('/^%([^%]+)%$/', $value, $match)) {
                // we do this to deal with non string values (Boolean, integer, ...)
                // the preg_replace_callback converts them to strings
                return $this->dumpParameter(strtolower($match[1]));
            } else {
                $that = $this;
                $replaceParameters = function ($match) use ($that) {
                    return "'.".$that->dumpParameter(strtolower($match[2])).".'";
                };

                $code = str_replace('%%', '%', preg_replace_callback('/(?<!%)(%)([^%]+)\1/', $replaceParameters, var_export($value, true)));

                return $code;
            }
        } elseif (is_object($value) || is_resource($value)) {
            throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.');
        } else {
            return var_export($value, true);
        }
    }

    /**
     * Dumps a parameter
     *
     * @param string $name
     *
     * @return string
     */
    public function dumpParameter($name)
    {
        if ($this->container->isFrozen() && $this->container->hasParameter($name)) {
            return $this->dumpValue($this->container->getParameter($name), false);
        }

        return sprintf("\$this->getParameter('%s')", strtolower($name));
    }

    /**
     * Gets a service call
     *
     * @param string    $id
     * @param Reference $reference
     *
     * @return string
     */
    private function getServiceCall($id, Reference $reference = null)
    {
        if ('service_container' === $id) {
            return '$this';
        }

        if (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) {
            return sprintf('$this->get(\'%s\', ContainerInterface::NULL_ON_INVALID_REFERENCE)', $id);
        } else {
            if ($this->container->hasAlias($id)) {
                $id = (string) $this->container->getAlias($id);
            }

            return sprintf('$this->get(\'%s\')', $id);
        }
    }

    /**
     * Convert a service id to a valid PHP method name.
     *
     * @param string $id
     *
     * @return string
     *
     * @throws InvalidArgumentException
     */
    private function camelize($id)
    {
        $name = Container::camelize($id);

        if (!preg_match('/^[a-zA-Z0-9_\x7f-\xff]+$/', $name)) {
            throw new InvalidArgumentException(sprintf('Service id "%s" cannot be converted to a valid PHP method name.', $id));
        }

        return $name;
    }

    /**
     * Returns the next name to use
     *
     * @return string
     */
    private function getNextVariableName()
    {
        $firstChars = self::FIRST_CHARS;
        $firstCharsLength = strlen($firstChars);
        $nonFirstChars = self::NON_FIRST_CHARS;
        $nonFirstCharsLength = strlen($nonFirstChars);

        while (true) {
            $name = '';
            $i = $this->variableCount;

            if ('' === $name) {
                $name .= $firstChars[$i%$firstCharsLength];
                $i = intval($i/$firstCharsLength);
            }

            while ($i > 0) {
                $i -= 1;
                $name .= $nonFirstChars[$i%$nonFirstCharsLength];
                $i = intval($i/$nonFirstCharsLength);
            }

            $this->variableCount += 1;

            // check that the name is not reserved
            if (in_array($name, $this->reservedVariables, true)) {
                continue;
            }

            return $name;
        }
    }

    private function getExpressionLanguage()
    {
        if (null === $this->expressionLanguage) {
            if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
                throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
            }
            $this->expressionLanguage = new ExpressionLanguage();
        }

        return $this->expressionLanguage;
    }
}
PK��Z}���@Symfony/Component/DependencyInjection/Dumper/DumperInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Dumper;

/**
 * DumperInterface is the interface implemented by service container dumper classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface DumperInterface
{
    /**
     * Dumps the service container.
     *
     * @param array $options An array of options
     *
     * @return string The representation of the service container
     *
     * @api
     */
    public function dump(array $options = array());
}
PK��Z���*�*:Symfony/Component/DependencyInjection/Dumper/XmlDumper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Dumper;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Parameter;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\ExpressionLanguage\Expression;

/**
 * XmlDumper dumps a service container as an XML string.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Martin Hasoň <martin.hason@gmail.com>
 *
 * @api
 */
class XmlDumper extends Dumper
{
    /**
     * @var \DOMDocument
     */
    private $document;

    /**
     * Dumps the service container as an XML string.
     *
     * @param array $options An array of options
     *
     * @return string An xml string representing of the service container
     *
     * @api
     */
    public function dump(array $options = array())
    {
        $this->document = new \DOMDocument('1.0', 'utf-8');
        $this->document->formatOutput = true;

        $container = $this->document->createElementNS('http://symfony.com/schema/dic/services', 'container');
        $container->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
        $container->setAttribute('xsi:schemaLocation', 'http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd');

        $this->addParameters($container);
        $this->addServices($container);

        $this->document->appendChild($container);
        $xml = $this->document->saveXML();
        $this->document = null;

        return $xml;
    }

    /**
     * Adds parameters.
     *
     * @param \DOMElement $parent
     */
    private function addParameters(\DOMElement $parent)
    {
        $data = $this->container->getParameterBag()->all();
        if (!$data) {
            return;
        }

        if ($this->container->isFrozen()) {
            $data = $this->escape($data);
        }

        $parameters = $this->document->createElement('parameters');
        $parent->appendChild($parameters);
        $this->convertParameters($data, 'parameter', $parameters);
    }

    /**
     * Adds method calls.
     *
     * @param array       $methodcalls
     * @param \DOMElement $parent
     */
    private function addMethodCalls(array $methodcalls, \DOMElement $parent)
    {
        foreach ($methodcalls as $methodcall) {
            $call = $this->document->createElement('call');
            $call->setAttribute('method', $methodcall[0]);
            if (count($methodcall[1])) {
                $this->convertParameters($methodcall[1], 'argument', $call);
            }
            $parent->appendChild($call);
        }
    }

    /**
     * Adds a service.
     *
     * @param Definition  $definition
     * @param string      $id
     * @param \DOMElement $parent
     */
    private function addService($definition, $id, \DOMElement $parent)
    {
        $service = $this->document->createElement('service');
        if (null !== $id) {
            $service->setAttribute('id', $id);
        }
        if ($definition->getClass()) {
            $service->setAttribute('class', $definition->getClass());
        }
        if ($definition->getFactoryMethod()) {
            $service->setAttribute('factory-method', $definition->getFactoryMethod());
        }
        if ($definition->getFactoryService()) {
            $service->setAttribute('factory-service', $definition->getFactoryService());
        }
        if (ContainerInterface::SCOPE_CONTAINER !== $scope = $definition->getScope()) {
            $service->setAttribute('scope', $scope);
        }
        if (!$definition->isPublic()) {
            $service->setAttribute('public', 'false');
        }
        if ($definition->isSynthetic()) {
            $service->setAttribute('synthetic', 'true');
        }
        if ($definition->isSynchronized()) {
            $service->setAttribute('synchronized', 'true');
        }
        if ($definition->isLazy()) {
            $service->setAttribute('lazy', 'true');
        }

        foreach ($definition->getTags() as $name => $tags) {
            foreach ($tags as $attributes) {
                $tag = $this->document->createElement('tag');
                $tag->setAttribute('name', $name);
                foreach ($attributes as $key => $value) {
                    $tag->setAttribute($key, $value);
                }
                $service->appendChild($tag);
            }
        }

        if ($definition->getFile()) {
            $file = $this->document->createElement('file');
            $file->appendChild($this->document->createTextNode($definition->getFile()));
            $service->appendChild($file);
        }

        if ($parameters = $definition->getArguments()) {
            $this->convertParameters($parameters, 'argument', $service);
        }

        if ($parameters = $definition->getProperties()) {
            $this->convertParameters($parameters, 'property', $service, 'name');
        }

        $this->addMethodCalls($definition->getMethodCalls(), $service);

        if ($callable = $definition->getConfigurator()) {
            $configurator = $this->document->createElement('configurator');
            if (is_array($callable)) {
                $configurator->setAttribute($callable[0] instanceof Reference ? 'service' : 'class', $callable[0]);
                $configurator->setAttribute('method', $callable[1]);
            } else {
                $configurator->setAttribute('function', $callable);
            }
            $service->appendChild($configurator);
        }

        $parent->appendChild($service);
    }

    /**
     * Adds a service alias.
     *
     * @param string      $alias
     * @param Alias       $id
     * @param \DOMElement $parent
     */
    private function addServiceAlias($alias, Alias $id, \DOMElement $parent)
    {
        $service = $this->document->createElement('service');
        $service->setAttribute('id', $alias);
        $service->setAttribute('alias', $id);
        if (!$id->isPublic()) {
            $service->setAttribute('public', 'false');
        }
        $parent->appendChild($service);
    }

    /**
     * Adds services.
     *
     * @param \DOMElement $parent
     */
    private function addServices(\DOMElement $parent)
    {
        $definitions = $this->container->getDefinitions();
        if (!$definitions) {
            return;
        }

        $services = $this->document->createElement('services');
        foreach ($definitions as $id => $definition) {
            $this->addService($definition, $id, $services);
        }

        $aliases = $this->container->getAliases();
        foreach ($aliases as $alias => $id) {
            while (isset($aliases[(string) $id])) {
                $id = $aliases[(string) $id];
            }
            $this->addServiceAlias($alias, $id, $services);
        }
        $parent->appendChild($services);
    }

    /**
     * Converts parameters.
     *
     * @param array       $parameters
     * @param string      $type
     * @param \DOMElement $parent
     * @param string      $keyAttribute
     */
    private function convertParameters($parameters, $type, \DOMElement $parent, $keyAttribute = 'key')
    {
        $withKeys = array_keys($parameters) !== range(0, count($parameters) - 1);
        foreach ($parameters as $key => $value) {
            $element = $this->document->createElement($type);
            if ($withKeys) {
                $element->setAttribute($keyAttribute, $key);
            }

            if (is_array($value)) {
                $element->setAttribute('type', 'collection');
                $this->convertParameters($value, $type, $element, 'key');
            } elseif ($value instanceof Reference) {
                $element->setAttribute('type', 'service');
                $element->setAttribute('id', (string) $value);
                $behaviour = $value->getInvalidBehavior();
                if ($behaviour == ContainerInterface::NULL_ON_INVALID_REFERENCE) {
                    $element->setAttribute('on-invalid', 'null');
                } elseif ($behaviour == ContainerInterface::IGNORE_ON_INVALID_REFERENCE) {
                    $element->setAttribute('on-invalid', 'ignore');
                }
                if (!$value->isStrict()) {
                    $element->setAttribute('strict', 'false');
                }
            } elseif ($value instanceof Definition) {
                $element->setAttribute('type', 'service');
                $this->addService($value, null, $element);
            } elseif ($value instanceof Expression) {
                $element->setAttribute('type', 'expression');
                $text = $this->document->createTextNode(self::phpToXml((string) $value));
                $element->appendChild($text);
            } else {
                if (in_array($value, array('null', 'true', 'false'), true)) {
                    $element->setAttribute('type', 'string');
                }
                $text = $this->document->createTextNode(self::phpToXml($value));
                $element->appendChild($text);
            }
            $parent->appendChild($element);
        }
    }

    /**
     * Escapes arguments
     *
     * @param array $arguments
     *
     * @return array
     */
    private function escape($arguments)
    {
        $args = array();
        foreach ($arguments as $k => $v) {
            if (is_array($v)) {
                $args[$k] = $this->escape($v);
            } elseif (is_string($v)) {
                $args[$k] = str_replace('%', '%%', $v);
            } else {
                $args[$k] = $v;
            }
        }

        return $args;
    }

    /**
     * Converts php types to xml types.
     *
     * @param mixed $value Value to convert
     *
     * @return string
     *
     * @throws RuntimeException When trying to dump object or resource
     */
    public static function phpToXml($value)
    {
        switch (true) {
            case null === $value:
                return 'null';
            case true === $value:
                return 'true';
            case false === $value:
                return 'false';
            case $value instanceof Parameter:
                return '%'.$value.'%';
            case is_object($value) || is_resource($value):
                throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.');
            default:
                return (string) $value;
        }
    }
}
PK��Z;Yޯ��<Symfony/Component/DependencyInjection/ExpressionLanguage.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage;

/**
 * Adds some function to the default ExpressionLanguage.
 *
 * To get a service, use service('request').
 * To get a parameter, use parameter('kernel.debug').
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ExpressionLanguage extends BaseExpressionLanguage
{
    protected function registerFunctions()
    {
        parent::registerFunctions();

        $this->register('service', function ($arg) {
            return sprintf('$this->get(%s)', $arg);
        }, function (array $variables, $value) {
            return $variables['container']->get($value);
        });

        $this->register('parameter', function ($arg) {
            return sprintf('$this->getParameter(%s)', $arg);
        }, function (array $variables, $value) {
            return $variables['container']->getParameter($value);
        });
    }
}
PK��ZU穌PP=Symfony/Component/DependencyInjection/DefinitionDecorator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\OutOfBoundsException;

/**
 * This definition decorates another definition.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @api
 */
class DefinitionDecorator extends Definition
{
    private $parent;
    private $changes = array();

    /**
     * Constructor.
     *
     * @param string $parent The id of Definition instance to decorate.
     *
     * @api
     */
    public function __construct($parent)
    {
        parent::__construct();

        $this->parent = $parent;
    }

    /**
     * Returns the Definition being decorated.
     *
     * @return string
     *
     * @api
     */
    public function getParent()
    {
        return $this->parent;
    }

    /**
     * Returns all changes tracked for the Definition object.
     *
     * @return array An array of changes for this Definition
     *
     * @api
     */
    public function getChanges()
    {
        return $this->changes;
    }

    /**
     * {@inheritDoc}
     *
     * @api
     */
    public function setClass($class)
    {
        $this->changes['class'] = true;

        return parent::setClass($class);
    }

    /**
     * {@inheritDoc}
     *
     * @api
     */
    public function setFactoryClass($class)
    {
        $this->changes['factory_class'] = true;

        return parent::setFactoryClass($class);
    }

    /**
     * {@inheritDoc}
     *
     * @api
     */
    public function setFactoryMethod($method)
    {
        $this->changes['factory_method'] = true;

        return parent::setFactoryMethod($method);
    }

    /**
     * {@inheritDoc}
     *
     * @api
     */
    public function setFactoryService($service)
    {
        $this->changes['factory_service'] = true;

        return parent::setFactoryService($service);
    }

    /**
     * {@inheritDoc}
     *
     * @api
     */
    public function setConfigurator($callable)
    {
        $this->changes['configurator'] = true;

        return parent::setConfigurator($callable);
    }

    /**
     * {@inheritDoc}
     *
     * @api
     */
    public function setFile($file)
    {
        $this->changes['file'] = true;

        return parent::setFile($file);
    }

    /**
     * {@inheritDoc}
     *
     * @api
     */
    public function setPublic($boolean)
    {
        $this->changes['public'] = true;

        return parent::setPublic($boolean);
    }

    /**
     * {@inheritDoc}
     *
     * @api
     */
    public function setLazy($boolean)
    {
        $this->changes['lazy'] = true;

        return parent::setLazy($boolean);
    }

    /**
     * Gets an argument to pass to the service constructor/factory method.
     *
     * If replaceArgument() has been used to replace an argument, this method
     * will return the replacement value.
     *
     * @param integer $index
     *
     * @return mixed The argument value
     *
     * @throws OutOfBoundsException When the argument does not exist
     *
     * @api
     */
    public function getArgument($index)
    {
        if (array_key_exists('index_'.$index, $this->arguments)) {
            return $this->arguments['index_'.$index];
        }

        $lastIndex = count(array_filter(array_keys($this->arguments), 'is_int')) - 1;

        if ($index < 0 || $index > $lastIndex) {
            throw new OutOfBoundsException(sprintf('The index "%d" is not in the range [0, %d].', $index, $lastIndex));
        }

        return $this->arguments[$index];
    }

    /**
     * You should always use this method when overwriting existing arguments
     * of the parent definition.
     *
     * If you directly call setArguments() keep in mind that you must follow
     * certain conventions when you want to overwrite the arguments of the
     * parent definition, otherwise your arguments will only be appended.
     *
     * @param integer $index
     * @param mixed   $value
     *
     * @return DefinitionDecorator the current instance
     * @throws InvalidArgumentException when $index isn't an integer
     *
     * @api
     */
    public function replaceArgument($index, $value)
    {
        if (!is_int($index)) {
            throw new InvalidArgumentException('$index must be an integer.');
        }

        $this->arguments['index_'.$index] = $value;

        return $this;
    }
}
PK��Z-R�],,3Symfony/Component/DependencyInjection/Reference.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

/**
 * Reference represents a service reference.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class Reference
{
    private $id;
    private $invalidBehavior;
    private $strict;

    /**
     * Constructor.
     *
     * @param string  $id              The service identifier
     * @param int     $invalidBehavior The behavior when the service does not exist
     * @param Boolean $strict          Sets how this reference is validated
     *
     * @see Container
     */
    public function __construct($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $strict = true)
    {
        $this->id = strtolower($id);
        $this->invalidBehavior = $invalidBehavior;
        $this->strict = $strict;
    }

    /**
     * __toString.
     *
     * @return string The service identifier
     */
    public function __toString()
    {
        return $this->id;
    }

    /**
     * Returns the behavior to be used when the service does not exist.
     *
     * @return int
     */
    public function getInvalidBehavior()
    {
        return $this->invalidBehavior;
    }

    /**
     * Returns true when this Reference is strict
     *
     * @return Boolean
     */
    public function isStrict()
    {
        return $this->strict;
    }
}
PK��ZU��a--;Symfony/Component/DependencyInjection/Loader/FileLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Loader;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\Loader\FileLoader as BaseFileLoader;
use Symfony\Component\Config\FileLocatorInterface;

/**
 * FileLoader is the abstract class used by all built-in loaders that are file based.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class FileLoader extends BaseFileLoader
{
    protected $container;

    /**
     * Constructor.
     *
     * @param ContainerBuilder $container A ContainerBuilder instance
     * @param FileLocatorInterface      $locator   A FileLocator instance
     */
    public function __construct(ContainerBuilder $container, FileLocatorInterface $locator)
    {
        $this->container = $container;

        parent::__construct($locator);
    }
}
PK��ZӸBj>Symfony/Component/DependencyInjection/Loader/IniFileLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Loader;

use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;

/**
 * IniFileLoader loads parameters from INI files.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class IniFileLoader extends FileLoader
{
    /**
     * Loads a resource.
     *
     * @param mixed  $file The resource
     * @param string $type The resource type
     *
     * @throws InvalidArgumentException When ini file is not valid
     */
    public function load($file, $type = null)
    {
        $path = $this->locator->locate($file);

        $this->container->addResource(new FileResource($path));

        $result = parse_ini_file($path, true);
        if (false === $result || array() === $result) {
            throw new InvalidArgumentException(sprintf('The "%s" file is not valid.', $file));
        }

        if (isset($result['parameters']) && is_array($result['parameters'])) {
            foreach ($result['parameters'] as $key => $value) {
                $this->container->setParameter($key, $value);
            }
        }
    }

    /**
     * Returns true if this class supports the given resource.
     *
     * @param mixed  $resource A resource
     * @param string $type     The resource type
     *
     * @return Boolean true if this class supports the given resource, false otherwise
     */
    public function supports($resource, $type = null)
    {
        return is_string($resource) && 'ini' === pathinfo($resource, PATHINFO_EXTENSION);
    }
}
PK��Z�
���>Symfony/Component/DependencyInjection/Loader/ClosureLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Loader;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\Loader\Loader;

/**
 * ClosureLoader loads service definitions from a PHP closure.
 *
 * The Closure has access to the container as its first argument.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ClosureLoader extends Loader
{
    private $container;

    /**
     * Constructor.
     *
     * @param ContainerBuilder $container A ContainerBuilder instance
     */
    public function __construct(ContainerBuilder $container)
    {
        $this->container = $container;
    }

    /**
     * Loads a Closure.
     *
     * @param \Closure $closure The resource
     * @param string   $type    The resource type
     */
    public function load($closure, $type = null)
    {
        call_user_func($closure, $this->container);
    }

    /**
     * Returns true if this class supports the given resource.
     *
     * @param mixed  $resource A resource
     * @param string $type     The resource type
     *
     * @return Boolean true if this class supports the given resource, false otherwise
     */
    public function supports($resource, $type = null)
    {
        return $resource instanceof \Closure;
    }
}
PK��Z���((>Symfony/Component/DependencyInjection/Loader/PhpFileLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Loader;

use Symfony\Component\Config\Resource\FileResource;

/**
 * PhpFileLoader loads service definitions from a PHP file.
 *
 * The PHP file is required and the $container variable can be
 * used within the file to change the container.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class PhpFileLoader extends FileLoader
{
    /**
     * Loads a PHP file.
     *
     * @param mixed  $file The resource
     * @param string $type The resource type
     */
    public function load($file, $type = null)
    {
        // the container and loader variables are exposed to the included file below
        $container = $this->container;
        $loader = $this;

        $path = $this->locator->locate($file);
        $this->setCurrentDir(dirname($path));
        $this->container->addResource(new FileResource($path));

        include $path;
    }

    /**
     * Returns true if this class supports the given resource.
     *
     * @param mixed  $resource A resource
     * @param string $type     The resource type
     *
     * @return Boolean true if this class supports the given resource, false otherwise
     */
    public function supports($resource, $type = null)
    {
        return is_string($resource) && 'php' === pathinfo($resource, PATHINFO_EXTENSION);
    }
}
PK��Z�z#aQSymfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsdnu�[���<?xml version="1.0" encoding="UTF-8" ?>

<xsd:schema xmlns="http://symfony.com/schema/dic/services"
     xmlns:xsd="http://www.w3.org/2001/XMLSchema"
     targetNamespace="http://symfony.com/schema/dic/services"
     elementFormDefault="qualified">

  <xsd:annotation>
    <xsd:documentation><![CDATA[
      Symfony XML Services Schema, version 1.0
      Authors: Fabien Potencier

      This defines a way to describe PHP objects (services) and their
      dependencies.
    ]]></xsd:documentation>
  </xsd:annotation>

  <xsd:element name="container" type="container" />

  <xsd:complexType name="container">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        The root element of a service file.
      ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:sequence>
      <xsd:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="imports" type="imports" minOccurs="0" maxOccurs="1" />
      <xsd:element name="parameters" type="parameters" minOccurs="0" maxOccurs="1" />
      <xsd:element name="services" type="services" minOccurs="0" maxOccurs="1" />
      <xsd:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded" />
    </xsd:sequence>
  </xsd:complexType>

  <xsd:complexType name="services">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        Enclosing element for the definition of all services
      ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:choice minOccurs="1" maxOccurs="unbounded">
      <xsd:element name="service" type="service" />
    </xsd:choice>
  </xsd:complexType>

  <xsd:complexType name="imports">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        Enclosing element for the import elements
      ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:choice minOccurs="1" maxOccurs="unbounded">
      <xsd:element name="import" type="import" />
    </xsd:choice>
  </xsd:complexType>

  <xsd:complexType name="import">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        Import an external resource defining other services or parameters
      ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:attribute name="resource" type="xsd:string" use="required" />
    <xsd:attribute name="ignore-errors" type="boolean" />
  </xsd:complexType>

  <xsd:complexType name="configurator">
    <xsd:attribute name="id" type="xsd:string" />
    <xsd:attribute name="service" type="xsd:string" />
    <xsd:attribute name="class" type="xsd:string" />
    <xsd:attribute name="method" type="xsd:string" />
    <xsd:attribute name="function" type="xsd:string" />
  </xsd:complexType>

  <xsd:complexType name="service">
    <xsd:choice maxOccurs="unbounded">
      <xsd:element name="file" type="xsd:string" minOccurs="0" maxOccurs="1" />
      <xsd:element name="argument" type="argument" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="configurator" type="configurator" minOccurs="0" maxOccurs="1" />
      <xsd:element name="call" type="call" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" />
    </xsd:choice>
    <xsd:attribute name="id" type="xsd:string" />
    <xsd:attribute name="class" type="xsd:string" />
    <xsd:attribute name="scope" type="xsd:string" />
    <xsd:attribute name="public" type="boolean" />
    <xsd:attribute name="synthetic" type="boolean" />
    <xsd:attribute name="synchronized" type="boolean" />
    <xsd:attribute name="lazy" type="boolean" />
    <xsd:attribute name="abstract" type="boolean" />
    <xsd:attribute name="factory-class" type="xsd:string" />
    <xsd:attribute name="factory-method" type="xsd:string" />
    <xsd:attribute name="factory-service" type="xsd:string" />
    <xsd:attribute name="alias" type="xsd:string" />
    <xsd:attribute name="parent" type="xsd:string" />
  </xsd:complexType>

  <xsd:complexType name="tag">
    <xsd:attribute name="name" type="xsd:string" />
    <xsd:anyAttribute namespace="##any" processContents="lax" />
  </xsd:complexType>

  <xsd:complexType name="parameters">
    <xsd:choice minOccurs="1" maxOccurs="unbounded">
      <xsd:element name="parameter" type="parameter" />
    </xsd:choice>
    <xsd:attribute name="type" type="parameter_type" />
    <xsd:attribute name="key" type="xsd:string" />
  </xsd:complexType>

  <xsd:complexType name="parameter" mixed="true">
    <xsd:choice minOccurs="0" maxOccurs="unbounded">
      <xsd:element name="parameter" type="parameter" />
    </xsd:choice>
    <xsd:attribute name="type" type="parameter_type" />
    <xsd:attribute name="id" type="xsd:string" />
    <xsd:attribute name="key" type="xsd:string" />
    <xsd:attribute name="on-invalid" type="invalid_sequence" />
  </xsd:complexType>

  <xsd:complexType name="property" mixed="true">
    <xsd:choice minOccurs="0" maxOccurs="1">
      <xsd:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="service" type="service" />
    </xsd:choice>
    <xsd:attribute name="type" type="argument_type" />
    <xsd:attribute name="id" type="xsd:string" />
    <xsd:attribute name="key" type="xsd:string" />
    <xsd:attribute name="name" type="xsd:string" />
    <xsd:attribute name="on-invalid" type="xsd:string" />
    <xsd:attribute name="strict" type="boolean" />
  </xsd:complexType>

  <xsd:complexType name="argument" mixed="true">
    <xsd:choice maxOccurs="unbounded">
      <xsd:element name="argument" type="argument" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="service" type="service" />
    </xsd:choice>
    <xsd:attribute name="type" type="argument_type" />
    <xsd:attribute name="id" type="xsd:string" />
    <xsd:attribute name="key" type="xsd:string" />
    <xsd:attribute name="index" type="xsd:integer" />
    <xsd:attribute name="on-invalid" type="xsd:string" />
    <xsd:attribute name="strict" type="boolean" />
  </xsd:complexType>

  <xsd:complexType name="call" mixed="true">
    <xsd:choice maxOccurs="unbounded">
      <xsd:element name="argument" type="argument" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="service" type="service" />
    </xsd:choice>
    <xsd:attribute name="method" type="xsd:string" />
  </xsd:complexType>

  <xsd:simpleType name="parameter_type">
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="collection" />
      <xsd:enumeration value="service" />
      <xsd:enumeration value="string" />
      <xsd:enumeration value="constant" />
    </xsd:restriction>
  </xsd:simpleType>

  <xsd:simpleType name="argument_type">
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="collection" />
      <xsd:enumeration value="service" />
      <xsd:enumeration value="expression" />
      <xsd:enumeration value="string" />
      <xsd:enumeration value="constant" />
    </xsd:restriction>
  </xsd:simpleType>

  <xsd:simpleType name="invalid_sequence">
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="null" />
      <xsd:enumeration value="ignore" />
      <xsd:enumeration value="exception" />
    </xsd:restriction>
  </xsd:simpleType>

  <xsd:simpleType name="boolean">
    <xsd:restriction base="xsd:string">
      <xsd:pattern value="(%.+%|true|false)" />
    </xsd:restriction>
  </xsd:simpleType>
</xsd:schema>
PK��ZL����8�8>Symfony/Component/DependencyInjection/Loader/XmlFileLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Loader;

use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\Config\Util\XmlUtils;
use Symfony\Component\DependencyInjection\DefinitionDecorator;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\SimpleXMLElement;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;

/**
 * XmlFileLoader loads XML files service definitions.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class XmlFileLoader extends FileLoader
{
    /**
     * Loads an XML file.
     *
     * @param mixed  $file The resource
     * @param string $type The resource type
     */
    public function load($file, $type = null)
    {
        $path = $this->locator->locate($file);

        $xml = $this->parseFile($path);
        $xml->registerXPathNamespace('container', 'http://symfony.com/schema/dic/services');

        $this->container->addResource(new FileResource($path));

        // anonymous services
        $this->processAnonymousServices($xml, $path);

        // imports
        $this->parseImports($xml, $path);

        // parameters
        $this->parseParameters($xml, $path);

        // extensions
        $this->loadFromExtensions($xml);

        // services
        $this->parseDefinitions($xml, $path);
    }

    /**
     * Returns true if this class supports the given resource.
     *
     * @param mixed  $resource A resource
     * @param string $type     The resource type
     *
     * @return Boolean true if this class supports the given resource, false otherwise
     */
    public function supports($resource, $type = null)
    {
        return is_string($resource) && 'xml' === pathinfo($resource, PATHINFO_EXTENSION);
    }

    /**
     * Parses parameters
     *
     * @param SimpleXMLElement $xml
     * @param string           $file
     */
    private function parseParameters(SimpleXMLElement $xml, $file)
    {
        if (!$xml->parameters) {
            return;
        }

        $this->container->getParameterBag()->add($xml->parameters->getArgumentsAsPhp('parameter'));
    }

    /**
     * Parses imports
     *
     * @param SimpleXMLElement $xml
     * @param string           $file
     */
    private function parseImports(SimpleXMLElement $xml, $file)
    {
        if (false === $imports = $xml->xpath('//container:imports/container:import')) {
            return;
        }

        foreach ($imports as $import) {
            $this->setCurrentDir(dirname($file));
            $this->import((string) $import['resource'], null, (Boolean) $import->getAttributeAsPhp('ignore-errors'), $file);
        }
    }

    /**
     * Parses multiple definitions
     *
     * @param SimpleXMLElement $xml
     * @param string           $file
     */
    private function parseDefinitions(SimpleXMLElement $xml, $file)
    {
        if (false === $services = $xml->xpath('//container:services/container:service')) {
            return;
        }

        foreach ($services as $service) {
            $this->parseDefinition((string) $service['id'], $service, $file);
        }
    }

    /**
     * Parses an individual Definition
     *
     * @param string           $id
     * @param SimpleXMLElement $service
     * @param string           $file
     */
    private function parseDefinition($id, $service, $file)
    {
        if ((string) $service['alias']) {
            $public = true;
            if (isset($service['public'])) {
                $public = $service->getAttributeAsPhp('public');
            }
            $this->container->setAlias($id, new Alias((string) $service['alias'], $public));

            return;
        }

        if (isset($service['parent'])) {
            $definition = new DefinitionDecorator((string) $service['parent']);
        } else {
            $definition = new Definition();
        }

        foreach (array('class', 'scope', 'public', 'factory-class', 'factory-method', 'factory-service', 'synthetic', 'synchronized', 'lazy', 'abstract') as $key) {
            if (isset($service[$key])) {
                $method = 'set'.str_replace('-', '', $key);
                $definition->$method((string) $service->getAttributeAsPhp($key));
            }
        }

        if ($service->file) {
            $definition->setFile((string) $service->file);
        }

        $definition->setArguments($service->getArgumentsAsPhp('argument'));
        $definition->setProperties($service->getArgumentsAsPhp('property'));

        if (isset($service->configurator)) {
            if (isset($service->configurator['function'])) {
                $definition->setConfigurator((string) $service->configurator['function']);
            } else {
                if (isset($service->configurator['service'])) {
                    $class = new Reference((string) $service->configurator['service'], ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false);
                } else {
                    $class = (string) $service->configurator['class'];
                }

                $definition->setConfigurator(array($class, (string) $service->configurator['method']));
            }
        }

        foreach ($service->call as $call) {
            $definition->addMethodCall((string) $call['method'], $call->getArgumentsAsPhp('argument'));
        }

        foreach ($service->tag as $tag) {
            $parameters = array();
            foreach ($tag->attributes() as $name => $value) {
                if ('name' === $name) {
                    continue;
                }

                if (false !== strpos($name, '-') && false === strpos($name, '_') && !array_key_exists($normalizedName = str_replace('-', '_', $name), $parameters)) {
                    $parameters[$normalizedName] = SimpleXMLElement::phpize($value);
                }
                // keep not normalized key for BC too
                $parameters[$name] = SimpleXMLElement::phpize($value);
            }

            $definition->addTag((string) $tag['name'], $parameters);
        }

        $this->container->setDefinition($id, $definition);
    }

    /**
     * Parses a XML file.
     *
     * @param string $file Path to a file
     *
     * @return SimpleXMLElement
     *
     * @throws InvalidArgumentException When loading of XML file returns error
     */
    protected function parseFile($file)
    {
        try {
            $dom = XmlUtils::loadFile($file, array($this, 'validateSchema'));
        } catch (\InvalidArgumentException $e) {
            throw new InvalidArgumentException(sprintf('Unable to parse file "%s".', $file), $e->getCode(), $e);
        }

        $this->validateExtensions($dom, $file);

        return simplexml_import_dom($dom, 'Symfony\\Component\\DependencyInjection\\SimpleXMLElement');
    }

    /**
     * Processes anonymous services
     *
     * @param SimpleXMLElement $xml
     * @param string           $file
     */
    private function processAnonymousServices(SimpleXMLElement $xml, $file)
    {
        $definitions = array();
        $count = 0;

        // anonymous services as arguments/properties
        if (false !== $nodes = $xml->xpath('//container:argument[@type="service"][not(@id)]|//container:property[@type="service"][not(@id)]')) {
            foreach ($nodes as $node) {
                // give it a unique name
                $id = sprintf('%s_%d', hash('sha256', $file), ++$count);
                $node['id'] = $id;

                $definitions[$id] = array($node->service, $file, false);
                $node->service['id'] = $id;
            }
        }

        // anonymous services "in the wild"
        if (false !== $nodes = $xml->xpath('//container:services/container:service[not(@id)]')) {
            foreach ($nodes as $node) {
                // give it a unique name
                $id = sprintf('%s_%d', hash('sha256', $file), ++$count);
                $node['id'] = $id;

                $definitions[$id] = array($node, $file, true);
                $node->service['id'] = $id;
            }
        }

        // resolve definitions
        krsort($definitions);
        foreach ($definitions as $id => $def) {
            // anonymous services are always private
            $def[0]['public'] = false;

            $this->parseDefinition($id, $def[0], $def[1]);

            $oNode = dom_import_simplexml($def[0]);
            if (true === $def[2]) {
                $nNode = new \DOMElement('_services');
                $oNode->parentNode->replaceChild($nNode, $oNode);
                $nNode->setAttribute('id', $id);
            } else {
                $oNode->parentNode->removeChild($oNode);
            }
        }
    }

    /**
     * Validates a documents XML schema.
     *
     * @param \DOMDocument $dom
     *
     * @return Boolean
     *
     * @throws RuntimeException When extension references a non-existent XSD file
     */
    public function validateSchema(\DOMDocument $dom)
    {
        $schemaLocations = array('http://symfony.com/schema/dic/services' => str_replace('\\', '/', __DIR__.'/schema/dic/services/services-1.0.xsd'));

        if ($element = $dom->documentElement->getAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'schemaLocation')) {
            $items = preg_split('/\s+/', $element);
            for ($i = 0, $nb = count($items); $i < $nb; $i += 2) {
                if (!$this->container->hasExtension($items[$i])) {
                    continue;
                }

                if (($extension = $this->container->getExtension($items[$i])) && false !== $extension->getXsdValidationBasePath()) {
                    $path = str_replace($extension->getNamespace(), str_replace('\\', '/', $extension->getXsdValidationBasePath()).'/', $items[$i + 1]);

                    if (!is_file($path)) {
                        throw new RuntimeException(sprintf('Extension "%s" references a non-existent XSD file "%s"', get_class($extension), $path));
                    }

                    $schemaLocations[$items[$i]] = $path;
                }
            }
        }

        $tmpfiles = array();
        $imports = '';
        foreach ($schemaLocations as $namespace => $location) {
            $parts = explode('/', $location);
            if (0 === stripos($location, 'phar://')) {
                $tmpfile = tempnam(sys_get_temp_dir(), 'sf2');
                if ($tmpfile) {
                    copy($location, $tmpfile);
                    $tmpfiles[] = $tmpfile;
                    $parts = explode('/', str_replace('\\', '/', $tmpfile));
                }
            }
            $drive = '\\' === DIRECTORY_SEPARATOR ? array_shift($parts).'/' : '';
            $location = 'file:///'.$drive.implode('/', array_map('rawurlencode', $parts));

            $imports .= sprintf('  <xsd:import namespace="%s" schemaLocation="%s" />'."\n", $namespace, $location);
        }

        $source = <<<EOF
<?xml version="1.0" encoding="utf-8" ?>
<xsd:schema xmlns="http://symfony.com/schema"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://symfony.com/schema"
    elementFormDefault="qualified">

    <xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
$imports
</xsd:schema>
EOF
        ;

        $valid = @$dom->schemaValidateSource($source);

        foreach ($tmpfiles as $tmpfile) {
            @unlink($tmpfile);
        }

        return $valid;
    }

    /**
     * Validates an extension.
     *
     * @param \DOMDocument $dom
     * @param string       $file
     *
     * @throws InvalidArgumentException When no extension is found corresponding to a tag
     */
    private function validateExtensions(\DOMDocument $dom, $file)
    {
        foreach ($dom->documentElement->childNodes as $node) {
            if (!$node instanceof \DOMElement || 'http://symfony.com/schema/dic/services' === $node->namespaceURI) {
                continue;
            }

            // can it be handled by an extension?
            if (!$this->container->hasExtension($node->namespaceURI)) {
                $extensionNamespaces = array_filter(array_map(function ($ext) { return $ext->getNamespace(); }, $this->container->getExtensions()));
                throw new InvalidArgumentException(sprintf(
                    'There is no extension able to load the configuration for "%s" (in %s). Looked for namespace "%s", found %s',
                    $node->tagName,
                    $file,
                    $node->namespaceURI,
                    $extensionNamespaces ? sprintf('"%s"', implode('", "', $extensionNamespaces)) : 'none'
                ));
            }
        }
    }

    /**
     * Loads from an extension.
     *
     * @param SimpleXMLElement $xml
     */
    private function loadFromExtensions(SimpleXMLElement $xml)
    {
        foreach (dom_import_simplexml($xml)->childNodes as $node) {
            if (!$node instanceof \DOMElement || $node->namespaceURI === 'http://symfony.com/schema/dic/services') {
                continue;
            }

            $values = static::convertDomElementToArray($node);
            if (!is_array($values)) {
                $values = array();
            }

            $this->container->loadFromExtension($node->namespaceURI, $values);
        }
    }

    /**
     * Converts a \DomElement object to a PHP array.
     *
     * The following rules applies during the conversion:
     *
     *  * Each tag is converted to a key value or an array
     *    if there is more than one "value"
     *
     *  * The content of a tag is set under a "value" key (<foo>bar</foo>)
     *    if the tag also has some nested tags
     *
     *  * The attributes are converted to keys (<foo foo="bar"/>)
     *
     *  * The nested-tags are converted to keys (<foo><foo>bar</foo></foo>)
     *
     * @param \DomElement $element A \DomElement instance
     *
     * @return array A PHP array
     */
    public static function convertDomElementToArray(\DomElement $element)
    {
        return XmlUtils::convertDomElementToArray($element);
    }
}
PK��Z!+���+�+?Symfony/Component/DependencyInjection/Loader/YamlFileLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Loader;

use Symfony\Component\DependencyInjection\DefinitionDecorator;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\Yaml\Parser as YamlParser;
use Symfony\Component\ExpressionLanguage\Expression;

/**
 * YamlFileLoader loads YAML files service definitions.
 *
 * The YAML format does not support anonymous services (cf. the XML loader).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class YamlFileLoader extends FileLoader
{
    private $yamlParser;

    /**
     * Loads a Yaml file.
     *
     * @param mixed  $file The resource
     * @param string $type The resource type
     */
    public function load($file, $type = null)
    {
        $path = $this->locator->locate($file);

        $content = $this->loadFile($path);

        $this->container->addResource(new FileResource($path));

        // empty file
        if (null === $content) {
            return;
        }

        // imports
        $this->parseImports($content, $path);

        // parameters
        if (isset($content['parameters'])) {
            foreach ($content['parameters'] as $key => $value) {
                $this->container->setParameter($key, $this->resolveServices($value));
            }
        }

        // extensions
        $this->loadFromExtensions($content);

        // services
        $this->parseDefinitions($content, $file);
    }

    /**
     * Returns true if this class supports the given resource.
     *
     * @param mixed  $resource A resource
     * @param string $type     The resource type
     *
     * @return Boolean true if this class supports the given resource, false otherwise
     */
    public function supports($resource, $type = null)
    {
        return is_string($resource) && 'yml' === pathinfo($resource, PATHINFO_EXTENSION);
    }

    /**
     * Parses all imports
     *
     * @param array  $content
     * @param string $file
     */
    private function parseImports($content, $file)
    {
        if (!isset($content['imports'])) {
            return;
        }

        foreach ($content['imports'] as $import) {
            $this->setCurrentDir(dirname($file));
            $this->import($import['resource'], null, isset($import['ignore_errors']) ? (Boolean) $import['ignore_errors'] : false, $file);
        }
    }

    /**
     * Parses definitions
     *
     * @param array  $content
     * @param string $file
     */
    private function parseDefinitions($content, $file)
    {
        if (!isset($content['services'])) {
            return;
        }

        foreach ($content['services'] as $id => $service) {
            $this->parseDefinition($id, $service, $file);
        }
    }

    /**
     * Parses a definition.
     *
     * @param string $id
     * @param array  $service
     * @param string $file
     *
     * @throws InvalidArgumentException When tags are invalid
     */
    private function parseDefinition($id, $service, $file)
    {
        if (is_string($service) && 0 === strpos($service, '@')) {
            $this->container->setAlias($id, substr($service, 1));

            return;
        } elseif (isset($service['alias'])) {
            $public = !array_key_exists('public', $service) || (Boolean) $service['public'];
            $this->container->setAlias($id, new Alias($service['alias'], $public));

            return;
        }

        if (isset($service['parent'])) {
            $definition = new DefinitionDecorator($service['parent']);
        } else {
            $definition = new Definition();
        }

        if (isset($service['class'])) {
            $definition->setClass($service['class']);
        }

        if (isset($service['scope'])) {
            $definition->setScope($service['scope']);
        }

        if (isset($service['synthetic'])) {
            $definition->setSynthetic($service['synthetic']);
        }

        if (isset($service['synchronized'])) {
            $definition->setSynchronized($service['synchronized']);
        }

        if (isset($service['lazy'])) {
            $definition->setLazy($service['lazy']);
        }

        if (isset($service['public'])) {
            $definition->setPublic($service['public']);
        }

        if (isset($service['abstract'])) {
            $definition->setAbstract($service['abstract']);
        }

        if (isset($service['factory_class'])) {
            $definition->setFactoryClass($service['factory_class']);
        }

        if (isset($service['factory_method'])) {
            $definition->setFactoryMethod($service['factory_method']);
        }

        if (isset($service['factory_service'])) {
            $definition->setFactoryService($service['factory_service']);
        }

        if (isset($service['file'])) {
            $definition->setFile($service['file']);
        }

        if (isset($service['arguments'])) {
            $definition->setArguments($this->resolveServices($service['arguments']));
        }

        if (isset($service['properties'])) {
            $definition->setProperties($this->resolveServices($service['properties']));
        }

        if (isset($service['configurator'])) {
            if (is_string($service['configurator'])) {
                $definition->setConfigurator($service['configurator']);
            } else {
                $definition->setConfigurator(array($this->resolveServices($service['configurator'][0]), $service['configurator'][1]));
            }
        }

        if (isset($service['calls'])) {
            foreach ($service['calls'] as $call) {
                $args = isset($call[1]) ? $this->resolveServices($call[1]) : array();
                $definition->addMethodCall($call[0], $args);
            }
        }

        if (isset($service['tags'])) {
            if (!is_array($service['tags'])) {
                throw new InvalidArgumentException(sprintf('Parameter "tags" must be an array for service "%s" in %s.', $id, $file));
            }

            foreach ($service['tags'] as $tag) {
                if (!isset($tag['name'])) {
                    throw new InvalidArgumentException(sprintf('A "tags" entry is missing a "name" key for service "%s" in %s.', $id, $file));
                }

                $name = $tag['name'];
                unset($tag['name']);

                foreach ($tag as $attribute => $value) {
                    if (!is_scalar($value) && null !== $value) {
                        throw new InvalidArgumentException(sprintf('A "tags" attribute must be of a scalar-type for service "%s", tag "%s", attribute "%s" in %s.', $id, $name, $attribute, $file));
                    }
                }

                $definition->addTag($name, $tag);
            }
        }

        $this->container->setDefinition($id, $definition);
    }

    /**
     * Loads a YAML file.
     *
     * @param string $file
     *
     * @return array The file content
     */
    protected function loadFile($file)
    {
        if (!stream_is_local($file)) {
            throw new InvalidArgumentException(sprintf('This is not a local file "%s".', $file));
        }

        if (!file_exists($file)) {
            throw new InvalidArgumentException(sprintf('The service file "%s" is not valid.', $file));
        }

        if (null === $this->yamlParser) {
            $this->yamlParser = new YamlParser();
        }

        return $this->validate($this->yamlParser->parse(file_get_contents($file)), $file);
    }

    /**
     * Validates a YAML file.
     *
     * @param mixed  $content
     * @param string $file
     *
     * @return array
     *
     * @throws InvalidArgumentException When service file is not valid
     */
    private function validate($content, $file)
    {
        if (null === $content) {
            return $content;
        }

        if (!is_array($content)) {
            throw new InvalidArgumentException(sprintf('The service file "%s" is not valid.', $file));
        }

        foreach (array_keys($content) as $namespace) {
            if (in_array($namespace, array('imports', 'parameters', 'services'))) {
                continue;
            }

            if (!$this->container->hasExtension($namespace)) {
                $extensionNamespaces = array_filter(array_map(function ($ext) { return $ext->getAlias(); }, $this->container->getExtensions()));
                throw new InvalidArgumentException(sprintf(
                    'There is no extension able to load the configuration for "%s" (in %s). Looked for namespace "%s", found %s',
                    $namespace,
                    $file,
                    $namespace,
                    $extensionNamespaces ? sprintf('"%s"', implode('", "', $extensionNamespaces)) : 'none'
                ));
            }
        }

        return $content;
    }

    /**
     * Resolves services.
     *
     * @param string $value
     *
     * @return Reference
     */
    private function resolveServices($value)
    {
        if (is_array($value)) {
            $value = array_map(array($this, 'resolveServices'), $value);
        } elseif (is_string($value) &&  0 === strpos($value, '@=')) {
            return new Expression(substr($value, 2));
        } elseif (is_string($value) &&  0 === strpos($value, '@')) {
            if (0 === strpos($value, '@@')) {
                $value = substr($value, 1);
                $invalidBehavior = null;
            } elseif (0 === strpos($value, '@?')) {
                $value = substr($value, 2);
                $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
            } else {
                $value = substr($value, 1);
                $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
            }

            if ('=' === substr($value, -1)) {
                $value = substr($value, 0, -1);
                $strict = false;
            } else {
                $strict = true;
            }

            if (null !== $invalidBehavior) {
                $value = new Reference($value, $invalidBehavior, $strict);
            }
        }

        return $value;
    }

    /**
     * Loads from Extensions
     *
     * @param array $content
     */
    private function loadFromExtensions($content)
    {
        foreach ($content as $namespace => $values) {
            if (in_array($namespace, array('imports', 'parameters', 'services'))) {
                continue;
            }

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

            $this->container->loadFromExtension($namespace, $values);
        }
    }
}
PK��Z��Gp5
5
;Symfony/Component/DependencyInjection/Compiler/Compiler.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * This class is used to remove circular dependencies between individual passes.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @api
 */
class Compiler
{
    private $passConfig;
    private $log = array();
    private $loggingFormatter;
    private $serviceReferenceGraph;

    /**
     * Constructor.
     */
    public function __construct()
    {
        $this->passConfig = new PassConfig();
        $this->serviceReferenceGraph = new ServiceReferenceGraph();
        $this->loggingFormatter = new LoggingFormatter();
    }

    /**
     * Returns the PassConfig.
     *
     * @return PassConfig The PassConfig instance
     *
     * @api
     */
    public function getPassConfig()
    {
        return $this->passConfig;
    }

    /**
     * Returns the ServiceReferenceGraph.
     *
     * @return ServiceReferenceGraph The ServiceReferenceGraph instance
     *
     * @api
     */
    public function getServiceReferenceGraph()
    {
        return $this->serviceReferenceGraph;
    }

    /**
     * Returns the logging formatter which can be used by compilation passes.
     *
     * @return LoggingFormatter
     */
    public function getLoggingFormatter()
    {
        return $this->loggingFormatter;
    }

    /**
     * Adds a pass to the PassConfig.
     *
     * @param CompilerPassInterface $pass A compiler pass
     * @param string                $type The type of the pass
     *
     * @api
     */
    public function addPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION)
    {
        $this->passConfig->addPass($pass, $type);
    }

    /**
     * Adds a log message.
     *
     * @param string $string The log message
     */
    public function addLogMessage($string)
    {
        $this->log[] = $string;
    }

    /**
     * Returns the log.
     *
     * @return array Log array
     */
    public function getLog()
    {
        return $this->log;
    }

    /**
     * Run the Compiler and process all Passes.
     *
     * @param ContainerBuilder $container
     *
     * @api
     */
    public function compile(ContainerBuilder $container)
    {
        foreach ($this->passConfig->getPasses() as $pass) {
            $pass->process($container);
        }
    }
}
PK��Z�0є##?Symfony/Component/DependencyInjection/Compiler/RepeatedPass.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;

/**
 * A pass that might be run repeatedly.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class RepeatedPass implements CompilerPassInterface
{
    /**
     * @var Boolean
     */
    private $repeat = false;

    /**
     * @var RepeatablePassInterface[]
     */
    private $passes;

    /**
     * Constructor.
     *
     * @param RepeatablePassInterface[] $passes An array of RepeatablePassInterface objects
     *
     * @throws InvalidArgumentException when the passes don't implement RepeatablePassInterface
     */
    public function __construct(array $passes)
    {
        foreach ($passes as $pass) {
            if (!$pass instanceof RepeatablePassInterface) {
                throw new InvalidArgumentException('$passes must be an array of RepeatablePassInterface.');
            }

            $pass->setRepeatedPass($this);
        }

        $this->passes = $passes;
    }

    /**
     * Process the repeatable passes that run more than once.
     *
     * @param ContainerBuilder $container
     */
    public function process(ContainerBuilder $container)
    {
        $this->repeat = false;
        foreach ($this->passes as $pass) {
            $pass->process($container);
        }

        if ($this->repeat) {
            $this->process($container);
        }
    }

    /**
     * Sets if the pass should repeat
     */
    public function setRepeat()
    {
        $this->repeat = true;
    }

    /**
     * Returns the passes
     *
     * @return RepeatablePassInterface[] An array of RepeatablePassInterface objects
     */
    public function getPasses()
    {
        return $this->passes;
    }
}
PK��ZL��FFUSymfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Reference;

/**
 * Replaces aliases with actual service definitions, effectively removing these
 * aliases.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ReplaceAliasByActualDefinitionPass implements CompilerPassInterface
{
    private $compiler;
    private $formatter;
    private $sourceId;

    /**
     * Process the Container to replace aliases with service definitions.
     *
     * @param ContainerBuilder $container
     *
     * @throws InvalidArgumentException if the service definition does not exist
     */
    public function process(ContainerBuilder $container)
    {
        $this->compiler = $container->getCompiler();
        $this->formatter = $this->compiler->getLoggingFormatter();

        foreach ($container->getAliases() as $id => $alias) {
            $aliasId = (string) $alias;

            try {
                $definition = $container->getDefinition($aliasId);
            } catch (InvalidArgumentException $e) {
                throw new InvalidArgumentException(sprintf('Unable to replace alias "%s" with "%s".', $alias, $id), null, $e);
            }

            if ($definition->isPublic()) {
                continue;
            }

            $definition->setPublic(true);
            $container->setDefinition($id, $definition);
            $container->removeDefinition($aliasId);

            $this->updateReferences($container, $aliasId, $id);

            // we have to restart the process due to concurrent modification of
            // the container
            $this->process($container);

            break;
        }
    }

    /**
     * Updates references to remove aliases.
     *
     * @param ContainerBuilder $container The container
     * @param string           $currentId The alias identifier being replaced
     * @param string           $newId     The id of the service the alias points to
     */
    private function updateReferences($container, $currentId, $newId)
    {
        foreach ($container->getAliases() as $id => $alias) {
            if ($currentId === (string) $alias) {
                $container->setAlias($id, $newId);
            }
        }

        foreach ($container->getDefinitions() as $id => $definition) {
            $this->sourceId = $id;

            $definition->setArguments(
                $this->updateArgumentReferences($definition->getArguments(), $currentId, $newId)
            );

            $definition->setMethodCalls(
                $this->updateArgumentReferences($definition->getMethodCalls(), $currentId, $newId)
            );

            $definition->setProperties(
                $this->updateArgumentReferences($definition->getProperties(), $currentId, $newId)
            );
        }
    }

    /**
     * Updates argument references.
     *
     * @param array  $arguments An array of Arguments
     * @param string $currentId The alias identifier
     * @param string $newId     The identifier the alias points to
     *
     * @return array
     */
    private function updateArgumentReferences(array $arguments, $currentId, $newId)
    {
        foreach ($arguments as $k => $argument) {
            if (is_array($argument)) {
                $arguments[$k] = $this->updateArgumentReferences($argument, $currentId, $newId);
            } elseif ($argument instanceof Reference) {
                if ($currentId === (string) $argument) {
                    $arguments[$k] = new Reference($newId, $argument->getInvalidBehavior());
                    $this->compiler->addLogMessage($this->formatter->formatUpdateReference($this, $this->sourceId, $currentId, $newId));
                }
            }
        }

        return $arguments;
    }
}
PK��ZC�\Z��=Symfony/Component/DependencyInjection/Compiler/PassConfig.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;

/**
 * Compiler Pass Configuration
 *
 * This class has a default configuration embedded.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @api
 */
class PassConfig
{
    const TYPE_AFTER_REMOVING = 'afterRemoving';
    const TYPE_BEFORE_OPTIMIZATION = 'beforeOptimization';
    const TYPE_BEFORE_REMOVING = 'beforeRemoving';
    const TYPE_OPTIMIZE = 'optimization';
    const TYPE_REMOVE = 'removing';

    private $mergePass;
    private $afterRemovingPasses = array();
    private $beforeOptimizationPasses = array();
    private $beforeRemovingPasses = array();
    private $optimizationPasses;
    private $removingPasses;

    /**
     * Constructor.
     */
    public function __construct()
    {
        $this->mergePass = new MergeExtensionConfigurationPass();

        $this->optimizationPasses = array(
            new ResolveDefinitionTemplatesPass(),
            new ResolveParameterPlaceHoldersPass(),
            new CheckDefinitionValidityPass(),
            new ResolveReferencesToAliasesPass(),
            new ResolveInvalidReferencesPass(),
            new AnalyzeServiceReferencesPass(true),
            new CheckCircularReferencesPass(),
            new CheckReferenceValidityPass(),
        );

        $this->removingPasses = array(
            new RemovePrivateAliasesPass(),
            new RemoveAbstractDefinitionsPass(),
            new ReplaceAliasByActualDefinitionPass(),
            new RepeatedPass(array(
                new AnalyzeServiceReferencesPass(),
                new InlineServiceDefinitionsPass(),
                new AnalyzeServiceReferencesPass(),
                new RemoveUnusedDefinitionsPass(),
            )),
            new CheckExceptionOnInvalidReferenceBehaviorPass(),
        );
    }

    /**
     * Returns all passes in order to be processed.
     *
     * @return array An array of all passes to process
     *
     * @api
     */
    public function getPasses()
    {
        return array_merge(
            array($this->mergePass),
            $this->beforeOptimizationPasses,
            $this->optimizationPasses,
            $this->beforeRemovingPasses,
            $this->removingPasses,
            $this->afterRemovingPasses
        );
    }

    /**
     * Adds a pass.
     *
     * @param CompilerPassInterface $pass A Compiler pass
     * @param string                $type The pass type
     *
     * @throws InvalidArgumentException when a pass type doesn't exist
     *
     * @api
     */
    public function addPass(CompilerPassInterface $pass, $type = self::TYPE_BEFORE_OPTIMIZATION)
    {
        $property = $type.'Passes';
        if (!isset($this->$property)) {
            throw new InvalidArgumentException(sprintf('Invalid type "%s".', $type));
        }

        $passes = &$this->$property;
        $passes[] = $pass;
    }

    /**
     * Gets all passes for the AfterRemoving pass.
     *
     * @return array An array of passes
     *
     * @api
     */
    public function getAfterRemovingPasses()
    {
        return $this->afterRemovingPasses;
    }

    /**
     * Gets all passes for the BeforeOptimization pass.
     *
     * @return array An array of passes
     *
     * @api
     */
    public function getBeforeOptimizationPasses()
    {
        return $this->beforeOptimizationPasses;
    }

    /**
     * Gets all passes for the BeforeRemoving pass.
     *
     * @return array An array of passes
     *
     * @api
     */
    public function getBeforeRemovingPasses()
    {
        return $this->beforeRemovingPasses;
    }

    /**
     * Gets all passes for the Optimization pass.
     *
     * @return array An array of passes
     *
     * @api
     */
    public function getOptimizationPasses()
    {
        return $this->optimizationPasses;
    }

    /**
     * Gets all passes for the Removing pass.
     *
     * @return array An array of passes
     *
     * @api
     */
    public function getRemovingPasses()
    {
        return $this->removingPasses;
    }

    /**
     * Gets all passes for the Merge pass.
     *
     * @return array An array of passes
     *
     * @api
     */
    public function getMergePass()
    {
        return $this->mergePass;
    }

    /**
     * Sets the Merge Pass.
     *
     * @param CompilerPassInterface $pass The merge pass
     *
     * @api
     */
    public function setMergePass(CompilerPassInterface $pass)
    {
        $this->mergePass = $pass;
    }

    /**
     * Sets the AfterRemoving passes.
     *
     * @param array $passes An array of passes
     *
     * @api
     */
    public function setAfterRemovingPasses(array $passes)
    {
        $this->afterRemovingPasses = $passes;
    }

    /**
     * Sets the BeforeOptimization passes.
     *
     * @param array $passes An array of passes
     *
     * @api
     */
    public function setBeforeOptimizationPasses(array $passes)
    {
        $this->beforeOptimizationPasses = $passes;
    }

    /**
     * Sets the BeforeRemoving passes.
     *
     * @param array $passes An array of passes
     *
     * @api
     */
    public function setBeforeRemovingPasses(array $passes)
    {
        $this->beforeRemovingPasses = $passes;
    }

    /**
     * Sets the Optimization passes.
     *
     * @param array $passes An array of passes
     *
     * @api
     */
    public function setOptimizationPasses(array $passes)
    {
        $this->optimizationPasses = $passes;
    }

    /**
     * Sets the Removing passes.
     *
     * @param array $passes An array of passes
     *
     * @api
     */
    public function setRemovingPasses(array $passes)
    {
        $this->removingPasses = $passes;
    }
}
PK��Zx�7���LSymfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphEdge.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

/**
 * Represents an edge in your service graph.
 *
 * Value is typically a reference.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ServiceReferenceGraphEdge
{
    private $sourceNode;
    private $destNode;
    private $value;

    /**
     * Constructor.
     *
     * @param ServiceReferenceGraphNode $sourceNode
     * @param ServiceReferenceGraphNode $destNode
     * @param string                    $value
     */
    public function __construct(ServiceReferenceGraphNode $sourceNode, ServiceReferenceGraphNode $destNode, $value = null)
    {
        $this->sourceNode = $sourceNode;
        $this->destNode = $destNode;
        $this->value = $value;
    }

    /**
     * Returns the value of the edge
     *
     * @return ServiceReferenceGraphNode
     */
    public function getValue()
    {
        return $this->value;
    }

    /**
     * Returns the source node
     *
     * @return ServiceReferenceGraphNode
     */
    public function getSourceNode()
    {
        return $this->sourceNode;
    }

    /**
     * Returns the destination node
     *
     * @return ServiceReferenceGraphNode
     */
    public function getDestNode()
    {
        return $this->destNode;
    }
}
PK��Z�� �MSymfony/Component/DependencyInjection/Compiler/CheckReferenceValidityPass.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\Exception\ScopeCrossingInjectionException;
use Symfony\Component\DependencyInjection\Exception\ScopeWideningInjectionException;

/**
 * Checks the validity of references
 *
 * The following checks are performed by this pass:
 * - target definitions are not abstract
 * - target definitions are of equal or wider scope
 * - target definitions are in the same scope hierarchy
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class CheckReferenceValidityPass implements CompilerPassInterface
{
    private $container;
    private $currentId;
    private $currentDefinition;
    private $currentScope;
    private $currentScopeAncestors;
    private $currentScopeChildren;

    /**
     * Processes the ContainerBuilder to validate References.
     *
     * @param ContainerBuilder $container
     */
    public function process(ContainerBuilder $container)
    {
        $this->container = $container;

        $children = $this->container->getScopeChildren();
        $ancestors = array();

        $scopes = $this->container->getScopes();
        foreach ($scopes as $name => $parent) {
            $ancestors[$name] = array($parent);

            while (isset($scopes[$parent])) {
                $ancestors[$name][] = $parent = $scopes[$parent];
            }
        }

        foreach ($container->getDefinitions() as $id => $definition) {
            if ($definition->isSynthetic() || $definition->isAbstract()) {
                continue;
            }

            $this->currentId = $id;
            $this->currentDefinition = $definition;
            $this->currentScope = $scope = $definition->getScope();

            if (ContainerInterface::SCOPE_CONTAINER === $scope) {
                $this->currentScopeChildren = array_keys($scopes);
                $this->currentScopeAncestors = array();
            } elseif (ContainerInterface::SCOPE_PROTOTYPE !== $scope) {
                $this->currentScopeChildren = isset($children[$scope]) ? $children[$scope] : array();
                $this->currentScopeAncestors = isset($ancestors[$scope]) ? $ancestors[$scope] : array();
            }

            $this->validateReferences($definition->getArguments());
            $this->validateReferences($definition->getMethodCalls());
            $this->validateReferences($definition->getProperties());
        }
    }

    /**
     * Validates an array of References.
     *
     * @param array $arguments An array of Reference objects
     *
     * @throws RuntimeException when there is a reference to an abstract definition.
     */
    private function validateReferences(array $arguments)
    {
        foreach ($arguments as $argument) {
            if (is_array($argument)) {
                $this->validateReferences($argument);
            } elseif ($argument instanceof Reference) {
                $targetDefinition = $this->getDefinition((string) $argument);

                if (null !== $targetDefinition && $targetDefinition->isAbstract()) {
                    throw new RuntimeException(sprintf(
                        'The definition "%s" has a reference to an abstract definition "%s". '
                       .'Abstract definitions cannot be the target of references.',
                       $this->currentId,
                       $argument
                    ));
                }

                $this->validateScope($argument, $targetDefinition);
            }
        }
    }

    /**
     * Validates the scope of a single Reference.
     *
     * @param Reference  $reference
     * @param Definition $definition
     *
     * @throws ScopeWideningInjectionException when the definition references a service of a narrower scope
     * @throws ScopeCrossingInjectionException when the definition references a service of another scope hierarchy
     */
    private function validateScope(Reference $reference, Definition $definition = null)
    {
        if (ContainerInterface::SCOPE_PROTOTYPE === $this->currentScope) {
            return;
        }

        if (!$reference->isStrict()) {
            return;
        }

        if (null === $definition) {
            return;
        }

        if ($this->currentScope === $scope = $definition->getScope()) {
            return;
        }

        $id = (string) $reference;

        if (in_array($scope, $this->currentScopeChildren, true)) {
            throw new ScopeWideningInjectionException($this->currentId, $this->currentScope, $id, $scope);
        }

        if (!in_array($scope, $this->currentScopeAncestors, true)) {
            throw new ScopeCrossingInjectionException($this->currentId, $this->currentScope, $id, $scope);
        }
    }

    /**
     * Returns the Definition given an id.
     *
     * @param string $id Definition identifier
     *
     * @return Definition
     */
    private function getDefinition($id)
    {
        if (!$this->container->hasDefinition($id)) {
            return null;
        }

        return $this->container->getDefinition($id);
    }
}
PK��Z�i�Z�
�
NSymfony/Component/DependencyInjection/Compiler/RemoveUnusedDefinitionsPass.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * Removes unused service definitions from the container.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class RemoveUnusedDefinitionsPass implements RepeatablePassInterface
{
    private $repeatedPass;

    /**
     * {@inheritDoc}
     */
    public function setRepeatedPass(RepeatedPass $repeatedPass)
    {
        $this->repeatedPass = $repeatedPass;
    }

    /**
     * Processes the ContainerBuilder to remove unused definitions.
     *
     * @param ContainerBuilder $container
     */
    public function process(ContainerBuilder $container)
    {
        $compiler = $container->getCompiler();
        $formatter = $compiler->getLoggingFormatter();
        $graph = $compiler->getServiceReferenceGraph();

        $hasChanged = false;
        foreach ($container->getDefinitions() as $id => $definition) {
            if ($definition->isPublic()) {
                continue;
            }

            if ($graph->hasNode($id)) {
                $edges = $graph->getNode($id)->getInEdges();
                $referencingAliases = array();
                $sourceIds = array();
                foreach ($edges as $edge) {
                    $node = $edge->getSourceNode();
                    $sourceIds[] = $node->getId();

                    if ($node->isAlias()) {
                        $referencingAliases[] = $node->getValue();
                    }
                }
                $isReferenced = (count(array_unique($sourceIds)) - count($referencingAliases)) > 0;
            } else {
                $referencingAliases = array();
                $isReferenced = false;
            }

            if (1 === count($referencingAliases) && false === $isReferenced) {
                $container->setDefinition((string) reset($referencingAliases), $definition);
                $definition->setPublic(true);
                $container->removeDefinition($id);
                $compiler->addLogMessage($formatter->formatRemoveService($this, $id, 'replaces alias '.reset($referencingAliases)));
            } elseif (0 === count($referencingAliases) && false === $isReferenced) {
                $container->removeDefinition($id);
                $compiler->addLogMessage($formatter->formatRemoveService($this, $id, 'unused'));
                $hasChanged = true;
            }
        }

        if ($hasChanged) {
            $this->repeatedPass->setRepeat();
        }
    }
}
PK��Z�!�?��KSymfony/Component/DependencyInjection/Compiler/RemovePrivateAliasesPass.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * Remove private aliases from the container. They were only used to establish
 * dependencies between services, and these dependencies have been resolved in
 * one of the previous passes.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class RemovePrivateAliasesPass implements CompilerPassInterface
{
    /**
     * Removes private aliases from the ContainerBuilder
     *
     * @param ContainerBuilder $container
     */
    public function process(ContainerBuilder $container)
    {
        $compiler = $container->getCompiler();
        $formatter = $compiler->getLoggingFormatter();

        foreach ($container->getAliases() as $id => $alias) {
            if ($alias->isPublic()) {
                continue;
            }

            $container->removeAlias($id);
            $compiler->addLogMessage($formatter->formatRemoveService($this, $id, 'private alias'));
        }
    }
}
PK��Z��U*''PSymfony/Component/DependencyInjection/Compiler/RemoveAbstractDefinitionsPass.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * Removes abstract Definitions
 *
 */
class RemoveAbstractDefinitionsPass implements CompilerPassInterface
{
    /**
     * Removes abstract definitions from the ContainerBuilder
     *
     * @param ContainerBuilder $container
     */
    public function process(ContainerBuilder $container)
    {
        $compiler = $container->getCompiler();
        $formatter = $compiler->getLoggingFormatter();

        foreach ($container->getDefinitions() as $id => $definition) {
            if ($definition->isAbstract()) {
                $container->removeDefinition($id);
                $compiler->addLogMessage($formatter->formatRemoveService($this, $id, 'abstract'));
            }
        }
    }
}
PK��Z��m��OSymfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * Inline service definitions where this is possible.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class InlineServiceDefinitionsPass implements RepeatablePassInterface
{
    private $repeatedPass;
    private $graph;
    private $compiler;
    private $formatter;
    private $currentId;

    /**
     * {@inheritDoc}
     */
    public function setRepeatedPass(RepeatedPass $repeatedPass)
    {
        $this->repeatedPass = $repeatedPass;
    }

    /**
     * Processes the ContainerBuilder for inline service definitions.
     *
     * @param ContainerBuilder $container
     */
    public function process(ContainerBuilder $container)
    {
        $this->compiler = $container->getCompiler();
        $this->formatter = $this->compiler->getLoggingFormatter();
        $this->graph = $this->compiler->getServiceReferenceGraph();

        foreach ($container->getDefinitions() as $id => $definition) {
            $this->currentId = $id;

            $definition->setArguments(
                $this->inlineArguments($container, $definition->getArguments())
            );

            $definition->setMethodCalls(
                $this->inlineArguments($container, $definition->getMethodCalls())
            );

            $definition->setProperties(
                $this->inlineArguments($container, $definition->getProperties())
            );
        }
    }

    /**
     * Processes inline arguments.
     *
     * @param ContainerBuilder $container The ContainerBuilder
     * @param array            $arguments An array of arguments
     *
     * @return array
     */
    private function inlineArguments(ContainerBuilder $container, array $arguments)
    {
        foreach ($arguments as $k => $argument) {
            if (is_array($argument)) {
                $arguments[$k] = $this->inlineArguments($container, $argument);
            } elseif ($argument instanceof Reference) {
                if (!$container->hasDefinition($id = (string) $argument)) {
                    continue;
                }

                if ($this->isInlineableDefinition($container, $id, $definition = $container->getDefinition($id))) {
                    $this->compiler->addLogMessage($this->formatter->formatInlineService($this, $id, $this->currentId));

                    if (ContainerInterface::SCOPE_PROTOTYPE !== $definition->getScope()) {
                        $arguments[$k] = $definition;
                    } else {
                        $arguments[$k] = clone $definition;
                    }
                }
            } elseif ($argument instanceof Definition) {
                $argument->setArguments($this->inlineArguments($container, $argument->getArguments()));
                $argument->setMethodCalls($this->inlineArguments($container, $argument->getMethodCalls()));
                $argument->setProperties($this->inlineArguments($container, $argument->getProperties()));
            }
        }

        return $arguments;
    }

    /**
     * Checks if the definition is inlineable.
     *
     * @param ContainerBuilder $container
     * @param string           $id
     * @param Definition       $definition
     *
     * @return Boolean If the definition is inlineable
     */
    private function isInlineableDefinition(ContainerBuilder $container, $id, Definition $definition)
    {
        if (ContainerInterface::SCOPE_PROTOTYPE === $definition->getScope()) {
            return true;
        }

        if ($definition->isPublic() || $definition->isLazy()) {
            return false;
        }

        if (!$this->graph->hasNode($id)) {
            return true;
        }

        if ($this->currentId == $id) {
            return false;
        }

        $ids = array();
        foreach ($this->graph->getNode($id)->getInEdges() as $edge) {
            $ids[] = $edge->getSourceNode()->getId();
        }

        if (count(array_unique($ids)) > 1) {
            return false;
        }

        return $container->getDefinition(reset($ids))->getScope() === $definition->getScope();
    }
}
PK��Z�iJT�
�
OSymfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;

/**
 * Emulates the invalid behavior if the reference is not found within the
 * container.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ResolveInvalidReferencesPass implements CompilerPassInterface
{
    private $container;

    /**
     * Process the ContainerBuilder to resolve invalid references.
     *
     * @param ContainerBuilder $container
     */
    public function process(ContainerBuilder $container)
    {
        $this->container = $container;
        foreach ($container->getDefinitions() as $definition) {
            if ($definition->isSynthetic() || $definition->isAbstract()) {
                continue;
            }

            $definition->setArguments(
                $this->processArguments($definition->getArguments())
            );

            $calls = array();
            foreach ($definition->getMethodCalls() as $call) {
                try {
                    $calls[] = array($call[0], $this->processArguments($call[1], true));
                } catch (RuntimeException $ignore) {
                    // this call is simply removed
                }
            }
            $definition->setMethodCalls($calls);

            $properties = array();
            foreach ($definition->getProperties() as $name => $value) {
                try {
                    $value = $this->processArguments(array($value), true);
                    $properties[$name] = reset($value);
                } catch (RuntimeException $ignore) {
                    // ignore property
                }
            }
            $definition->setProperties($properties);
        }
    }

    /**
     * Processes arguments to determine invalid references.
     *
     * @param array   $arguments    An array of Reference objects
     * @param Boolean $inMethodCall
     *
     * @return array
     *
     * @throws RuntimeException When the config is invalid
     */
    private function processArguments(array $arguments, $inMethodCall = false)
    {
        foreach ($arguments as $k => $argument) {
            if (is_array($argument)) {
                $arguments[$k] = $this->processArguments($argument, $inMethodCall);
            } elseif ($argument instanceof Reference) {
                $id = (string) $argument;

                $invalidBehavior = $argument->getInvalidBehavior();
                $exists = $this->container->has($id);

                // resolve invalid behavior
                if (!$exists && ContainerInterface::NULL_ON_INVALID_REFERENCE === $invalidBehavior) {
                    $arguments[$k] = null;
                } elseif (!$exists && ContainerInterface::IGNORE_ON_INVALID_REFERENCE === $invalidBehavior) {
                    if ($inMethodCall) {
                        throw new RuntimeException('Method shouldn\'t be called.');
                    }

                    $arguments[$k] = null;
                }
            }
        }

        return $arguments;
    }
}
PK��Z��PPQSymfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * Replaces all references to aliases with references to the actual service.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ResolveReferencesToAliasesPass implements CompilerPassInterface
{
    private $container;

    /**
     * Processes the ContainerBuilder to replace references to aliases with actual service references.
     *
     * @param ContainerBuilder $container
     */
    public function process(ContainerBuilder $container)
    {
        $this->container = $container;

        foreach ($container->getDefinitions() as $definition) {
            if ($definition->isSynthetic() || $definition->isAbstract()) {
                continue;
            }

            $definition->setArguments($this->processArguments($definition->getArguments()));
            $definition->setMethodCalls($this->processArguments($definition->getMethodCalls()));
            $definition->setProperties($this->processArguments($definition->getProperties()));
        }

        foreach ($container->getAliases() as $id => $alias) {
            $aliasId = (string) $alias;
            if ($aliasId !== $defId = $this->getDefinitionId($aliasId)) {
                $container->setAlias($id, new Alias($defId, $alias->isPublic()));
            }
        }
    }

    /**
     * Processes the arguments to replace aliases.
     *
     * @param array $arguments An array of References
     *
     * @return array An array of References
     */
    private function processArguments(array $arguments)
    {
        foreach ($arguments as $k => $argument) {
            if (is_array($argument)) {
                $arguments[$k] = $this->processArguments($argument);
            } elseif ($argument instanceof Reference) {
                $defId = $this->getDefinitionId($id = (string) $argument);

                if ($defId !== $id) {
                    $arguments[$k] = new Reference($defId, $argument->getInvalidBehavior(), $argument->isStrict());
                }
            }
        }

        return $arguments;
    }

    /**
     * Resolves an alias into a definition id.
     *
     * @param string $id The definition or alias id to resolve
     *
     * @return string The definition id with aliases resolved
     */
    private function getDefinitionId($id)
    {
        while ($this->container->hasAlias($id)) {
            $id = (string) $this->container->getAlias($id);
        }

        return $id;
    }
}
PK��ZV�%))HSymfony/Component/DependencyInjection/Compiler/ServiceReferenceGraph.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;

/**
 * This is a directed graph of your services.
 *
 * This information can be used by your compiler passes instead of collecting
 * it themselves which improves performance quite a lot.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ServiceReferenceGraph
{
    /**
     * @var ServiceReferenceGraphNode[]
     */
    private $nodes = array();

    /**
     * Checks if the graph has a specific node.
     *
     * @param string $id Id to check
     *
     * @return Boolean
     */
    public function hasNode($id)
    {
        return isset($this->nodes[$id]);
    }

    /**
     * Gets a node by identifier.
     *
     * @param string $id The id to retrieve
     *
     * @return ServiceReferenceGraphNode The node matching the supplied identifier
     *
     * @throws InvalidArgumentException if no node matches the supplied identifier
     */
    public function getNode($id)
    {
        if (!isset($this->nodes[$id])) {
            throw new InvalidArgumentException(sprintf('There is no node with id "%s".', $id));
        }

        return $this->nodes[$id];
    }

    /**
     * Returns all nodes.
     *
     * @return ServiceReferenceGraphNode[] An array of all ServiceReferenceGraphNode objects
     */
    public function getNodes()
    {
        return $this->nodes;
    }

    /**
     * Clears all nodes.
     */
    public function clear()
    {
        $this->nodes = array();
    }

    /**
     * Connects 2 nodes together in the Graph.
     *
     * @param string $sourceId
     * @param string $sourceValue
     * @param string $destId
     * @param string $destValue
     * @param string $reference
     */
    public function connect($sourceId, $sourceValue, $destId, $destValue = null, $reference = null)
    {
        $sourceNode = $this->createNode($sourceId, $sourceValue);
        $destNode = $this->createNode($destId, $destValue);
        $edge = new ServiceReferenceGraphEdge($sourceNode, $destNode, $reference);

        $sourceNode->addOutEdge($edge);
        $destNode->addInEdge($edge);
    }

    /**
     * Creates a graph node.
     *
     * @param string $id
     * @param string $value
     *
     * @return ServiceReferenceGraphNode
     */
    private function createNode($id, $value)
    {
        if (isset($this->nodes[$id]) && $this->nodes[$id]->getValue() === $value) {
            return $this->nodes[$id];
        }

        return $this->nodes[$id] = new ServiceReferenceGraphNode($id, $value);
    }
}
PK��Z[���	�	LSymfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphNode.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Alias;

/**
 * Represents a node in your service graph.
 *
 * Value is typically a definition, or an alias.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ServiceReferenceGraphNode
{
    private $id;
    private $inEdges = array();
    private $outEdges = array();
    private $value;

    /**
     * Constructor.
     *
     * @param string $id    The node identifier
     * @param mixed  $value The node value
     */
    public function __construct($id, $value)
    {
        $this->id = $id;
        $this->value = $value;
    }

    /**
     * Adds an in edge to this node.
     *
     * @param ServiceReferenceGraphEdge $edge
     */
    public function addInEdge(ServiceReferenceGraphEdge $edge)
    {
        $this->inEdges[] = $edge;
    }

    /**
     * Adds an out edge to this node.
     *
     * @param ServiceReferenceGraphEdge $edge
     */
    public function addOutEdge(ServiceReferenceGraphEdge $edge)
    {
        $this->outEdges[] = $edge;
    }

    /**
     * Checks if the value of this node is an Alias.
     *
     * @return Boolean True if the value is an Alias instance
     */
    public function isAlias()
    {
        return $this->value instanceof Alias;
    }

    /**
     * Checks if the value of this node is a Definition.
     *
     * @return Boolean True if the value is a Definition instance
     */
    public function isDefinition()
    {
        return $this->value instanceof Definition;
    }

    /**
     * Returns the identifier.
     *
     * @return string
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Returns the in edges.
     *
     * @return array The in ServiceReferenceGraphEdge array
     */
    public function getInEdges()
    {
        return $this->inEdges;
    }

    /**
     * Returns the out edges.
     *
     * @return array The out ServiceReferenceGraphEdge array
     */
    public function getOutEdges()
    {
        return $this->outEdges;
    }

    /**
     * Returns the value of this Node
     *
     * @return mixed The value
     */
    public function getValue()
    {
        return $this->value;
    }
}
PK��Z��ϒ��QSymfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\DefinitionDecorator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;

/**
 * This replaces all DefinitionDecorator instances with their equivalent fully
 * merged Definition instance.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ResolveDefinitionTemplatesPass implements CompilerPassInterface
{
    private $container;
    private $compiler;
    private $formatter;

    /**
     * Process the ContainerBuilder to replace DefinitionDecorator instances with their real Definition instances.
     *
     * @param ContainerBuilder $container
     */
    public function process(ContainerBuilder $container)
    {
        $this->container = $container;
        $this->compiler = $container->getCompiler();
        $this->formatter = $this->compiler->getLoggingFormatter();

        foreach (array_keys($container->getDefinitions()) as $id) {
            // yes, we are specifically fetching the definition from the
            // container to ensure we are not operating on stale data
            $definition = $container->getDefinition($id);
            if (!$definition instanceof DefinitionDecorator || $definition->isAbstract()) {
                continue;
            }

            $this->resolveDefinition($id, $definition);
        }
    }

    /**
     * Resolves the definition
     *
     * @param string              $id         The definition identifier
     * @param DefinitionDecorator $definition
     *
     * @return Definition
     *
     * @throws \RuntimeException When the definition is invalid
     */
    private function resolveDefinition($id, DefinitionDecorator $definition)
    {
        if (!$this->container->hasDefinition($parent = $definition->getParent())) {
            throw new RuntimeException(sprintf('The parent definition "%s" defined for definition "%s" does not exist.', $parent, $id));
        }

        $parentDef = $this->container->getDefinition($parent);
        if ($parentDef instanceof DefinitionDecorator) {
            $parentDef = $this->resolveDefinition($parent, $parentDef);
        }

        $this->compiler->addLogMessage($this->formatter->formatResolveInheritance($this, $id, $parent));
        $def = new Definition();

        // merge in parent definition
        // purposely ignored attributes: scope, abstract, tags
        $def->setClass($parentDef->getClass());
        $def->setArguments($parentDef->getArguments());
        $def->setMethodCalls($parentDef->getMethodCalls());
        $def->setProperties($parentDef->getProperties());
        $def->setFactoryClass($parentDef->getFactoryClass());
        $def->setFactoryMethod($parentDef->getFactoryMethod());
        $def->setFactoryService($parentDef->getFactoryService());
        $def->setConfigurator($parentDef->getConfigurator());
        $def->setFile($parentDef->getFile());
        $def->setPublic($parentDef->isPublic());
        $def->setLazy($parentDef->isLazy());

        // overwrite with values specified in the decorator
        $changes = $definition->getChanges();
        if (isset($changes['class'])) {
            $def->setClass($definition->getClass());
        }
        if (isset($changes['factory_class'])) {
            $def->setFactoryClass($definition->getFactoryClass());
        }
        if (isset($changes['factory_method'])) {
            $def->setFactoryMethod($definition->getFactoryMethod());
        }
        if (isset($changes['factory_service'])) {
            $def->setFactoryService($definition->getFactoryService());
        }
        if (isset($changes['configurator'])) {
            $def->setConfigurator($definition->getConfigurator());
        }
        if (isset($changes['file'])) {
            $def->setFile($definition->getFile());
        }
        if (isset($changes['public'])) {
            $def->setPublic($definition->isPublic());
        }
        if (isset($changes['lazy'])) {
            $def->setLazy($definition->isLazy());
        }

        // merge arguments
        foreach ($definition->getArguments() as $k => $v) {
            if (is_numeric($k)) {
                $def->addArgument($v);
                continue;
            }

            if (0 !== strpos($k, 'index_')) {
                throw new RuntimeException(sprintf('Invalid argument key "%s" found.', $k));
            }

            $index = (integer) substr($k, strlen('index_'));
            $def->replaceArgument($index, $v);
        }

        // merge properties
        foreach ($definition->getProperties() as $k => $v) {
            $def->setProperty($k, $v);
        }

        // append method calls
        if (count($calls = $definition->getMethodCalls()) > 0) {
            $def->setMethodCalls(array_merge($def->getMethodCalls(), $calls));
        }

        // these attributes are always taken from the child
        $def->setAbstract($definition->isAbstract());
        $def->setScope($definition->getScope());
        $def->setTags($definition->getTags());

        // set new definition on container
        $this->container->setDefinition($id, $def);

        return $def;
    }
}
PK��Z���nnSSymfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;

/**
 * Resolves all parameter placeholders "%somevalue%" to their real values.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ResolveParameterPlaceHoldersPass implements CompilerPassInterface
{
    /**
     * Processes the ContainerBuilder to resolve parameter placeholders.
     *
     * @param ContainerBuilder $container
     *
     * @throws ParameterNotFoundException
     */
    public function process(ContainerBuilder $container)
    {
        $parameterBag = $container->getParameterBag();

        foreach ($container->getDefinitions() as $id => $definition) {
            try {
                $definition->setClass($parameterBag->resolveValue($definition->getClass()));
                $definition->setFile($parameterBag->resolveValue($definition->getFile()));
                $definition->setArguments($parameterBag->resolveValue($definition->getArguments()));

                $calls = array();
                foreach ($definition->getMethodCalls() as $name => $arguments) {
                    $calls[$parameterBag->resolveValue($name)] = $parameterBag->resolveValue($arguments);
                }
                $definition->setMethodCalls($calls);

                $definition->setProperties($parameterBag->resolveValue($definition->getProperties()));
            } catch (ParameterNotFoundException $e) {
                $e->setSourceId($id);

                throw $e;
            }
        }

        $aliases = array();
        foreach ($container->getAliases() as $name => $target) {
            $aliases[$parameterBag->resolveValue($name)] = $parameterBag->resolveValue($target);
        }
        $container->setAliases($aliases);

        $parameterBag->resolve();
    }
}
PK��ZX�\\RSymfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;

/**
 * Merges extension configs into the container builder
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class MergeExtensionConfigurationPass implements CompilerPassInterface
{
    /**
     * {@inheritDoc}
     */
    public function process(ContainerBuilder $container)
    {
        $parameters = $container->getParameterBag()->all();
        $definitions = $container->getDefinitions();
        $aliases = $container->getAliases();

        foreach ($container->getExtensions() as $extension) {
            if ($extension instanceof PrependExtensionInterface) {
                $extension->prepend($container);
            }
        }

        foreach ($container->getExtensions() as $name => $extension) {
            if (!$config = $container->getExtensionConfig($name)) {
                // this extension was not called
                continue;
            }
            $config = $container->getParameterBag()->resolveValue($config);

            $tmpContainer = new ContainerBuilder($container->getParameterBag());
            $tmpContainer->setResourceTracking($container->isTrackingResources());
            $tmpContainer->addObjectResource($extension);

            $extension->load($config, $tmpContainer);

            $container->merge($tmpContainer);
        }

        $container->addDefinitions($definitions);
        $container->addAliases($aliases);
        $container->getParameterBag()->add($parameters);
    }
}
PK��Z�_9��HSymfony/Component/DependencyInjection/Compiler/CompilerPassInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * Interface that must be implemented by compilation passes
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @api
 */
interface CompilerPassInterface
{
    /**
     * You can modify the container here before it is dumped to PHP code.
     *
     * @param ContainerBuilder $container
     *
     * @api
     */
    public function process(ContainerBuilder $container);
}
PK��Z��Eų�JSymfony/Component/DependencyInjection/Compiler/RepeatablePassInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

/**
 * Interface that must be implemented by passes that are run as part of an
 * RepeatedPass.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface RepeatablePassInterface extends CompilerPassInterface
{
    /**
     * Sets the RepeatedPass interface.
     *
     * @param RepeatedPass $repeatedPass
     */
    public function setRepeatedPass(RepeatedPass $repeatedPass);
}
PK��Zb[_�66_Symfony/Component/DependencyInjection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Definition;

use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * Checks that all references are pointing to a valid service.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class CheckExceptionOnInvalidReferenceBehaviorPass implements CompilerPassInterface
{
    private $container;
    private $sourceId;

    public function process(ContainerBuilder $container)
    {
        $this->container = $container;

        foreach ($container->getDefinitions() as $id => $definition) {
            $this->sourceId = $id;
            $this->processDefinition($definition);
        }
    }

    private function processDefinition(Definition $definition)
    {
        $this->processReferences($definition->getArguments());
        $this->processReferences($definition->getMethodCalls());
        $this->processReferences($definition->getProperties());
    }

    private function processReferences(array $arguments)
    {
        foreach ($arguments as $argument) {
            if (is_array($argument)) {
                $this->processReferences($argument);
            } elseif ($argument instanceof Definition) {
                $this->processDefinition($argument);
            } elseif ($argument instanceof Reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $argument->getInvalidBehavior()) {
                $destId = (string) $argument;

                if (!$this->container->has($destId)) {
                    throw new ServiceNotFoundException($destId, $this->sourceId);
                }
            }
        }
    }
}
PK��Z@��q	q	NSymfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * Checks your services for circular references
 *
 * References from method calls are ignored since we might be able to resolve
 * these references depending on the order in which services are called.
 *
 * Circular reference from method calls will only be detected at run-time.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class CheckCircularReferencesPass implements CompilerPassInterface
{
    private $currentId;
    private $currentPath;
    private $checkedNodes;

    /**
     * Checks the ContainerBuilder object for circular references.
     *
     * @param ContainerBuilder $container The ContainerBuilder instances
     */
    public function process(ContainerBuilder $container)
    {
        $graph = $container->getCompiler()->getServiceReferenceGraph();

        $this->checkedNodes = array();
        foreach ($graph->getNodes() as $id => $node) {
            $this->currentId = $id;
            $this->currentPath = array($id);

            $this->checkOutEdges($node->getOutEdges());
        }
    }

    /**
     * Checks for circular references.
     *
     * @param ServiceReferenceGraphEdge[] $edges An array of Edges
     *
     * @throws ServiceCircularReferenceException When a circular reference is found.
     */
    private function checkOutEdges(array $edges)
    {
        foreach ($edges as $edge) {
            $node      = $edge->getDestNode();
            $id        = $node->getId();

            if (empty($this->checkedNodes[$id])) {
                $searchKey = array_search($id, $this->currentPath);
                $this->currentPath[] = $id;

                if (false !== $searchKey) {
                    throw new ServiceCircularReferenceException($id, array_slice($this->currentPath, $searchKey));
                }

                $this->checkOutEdges($node->getOutEdges());

                $this->checkedNodes[$id] = true;
                array_pop($this->currentPath);
            }
        }
    }
}
PK��Z��ddNSymfony/Component/DependencyInjection/Compiler/CheckDefinitionValidityPass.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;

/**
 * This pass validates each definition individually only taking the information
 * into account which is contained in the definition itself.
 *
 * Later passes can rely on the following, and specifically do not need to
 * perform these checks themselves:
 *
 * - non synthetic, non abstract services always have a class set
 * - synthetic services are always public
 * - synthetic services are always of non-prototype scope
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class CheckDefinitionValidityPass implements CompilerPassInterface
{
    /**
     * Processes the ContainerBuilder to validate the Definition.
     *
     * @param ContainerBuilder $container
     *
     * @throws RuntimeException When the Definition is invalid
     */
    public function process(ContainerBuilder $container)
    {
        foreach ($container->getDefinitions() as $id => $definition) {
            // synthetic service is public
            if ($definition->isSynthetic() && !$definition->isPublic()) {
                throw new RuntimeException(sprintf(
                    'A synthetic service ("%s") must be public.',
                    $id
                ));
            }

            // synthetic service has non-prototype scope
            if ($definition->isSynthetic() && ContainerInterface::SCOPE_PROTOTYPE === $definition->getScope()) {
                throw new RuntimeException(sprintf(
                    'A synthetic service ("%s") cannot be of scope "prototype".',
                    $id
                ));
            }

            // non-synthetic, non-abstract service has class
            if (!$definition->isAbstract() && !$definition->isSynthetic() && !$definition->getClass()) {
                if ($definition->getFactoryClass() || $definition->getFactoryService()) {
                    throw new RuntimeException(sprintf(
                        'Please add the class to service "%s" even if it is constructed by a factory '
                       .'since we might need to add method calls based on compile-time checks.',
                       $id
                    ));
                }

                throw new RuntimeException(sprintf(
                    'The definition for "%s" has no class. If you intend to inject '
                   .'this service dynamically at runtime, please mark it as synthetic=true. '
                   .'If this is an abstract definition solely used by child definitions, '
                   .'please add abstract=true, otherwise specify a class to get rid of this error.',
                   $id
                ));
            }

            // tag attribute values must be scalars
            foreach ($definition->getTags() as $name => $tags) {
                foreach ($tags as $attributes) {
                    foreach ($attributes as $attribute => $value) {
                        if (!is_scalar($value) && null !== $value) {
                            throw new RuntimeException(sprintf('A "tags" attribute must be of a scalar-type for service "%s", tag "%s", attribute "%s".', $id, $name, $attribute));
                        }
                    }
                }
            }
        }
    }
}
PK��Z�ۻǠ�OSymfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * Run this pass before passes that need to know more about the relation of
 * your services.
 *
 * This class will populate the ServiceReferenceGraph with information. You can
 * retrieve the graph in other passes from the compiler.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class AnalyzeServiceReferencesPass implements RepeatablePassInterface
{
    private $graph;
    private $container;
    private $currentId;
    private $currentDefinition;
    private $repeatedPass;
    private $onlyConstructorArguments;

    /**
     * Constructor.
     *
     * @param Boolean $onlyConstructorArguments Sets this Service Reference pass to ignore method calls
     */
    public function __construct($onlyConstructorArguments = false)
    {
        $this->onlyConstructorArguments = (Boolean) $onlyConstructorArguments;
    }

    /**
     * {@inheritDoc}
     */
    public function setRepeatedPass(RepeatedPass $repeatedPass)
    {
        $this->repeatedPass = $repeatedPass;
    }

    /**
     * Processes a ContainerBuilder object to populate the service reference graph.
     *
     * @param ContainerBuilder $container
     */
    public function process(ContainerBuilder $container)
    {
        $this->container = $container;
        $this->graph     = $container->getCompiler()->getServiceReferenceGraph();
        $this->graph->clear();

        foreach ($container->getDefinitions() as $id => $definition) {
            if ($definition->isSynthetic() || $definition->isAbstract()) {
                continue;
            }

            $this->currentId = $id;
            $this->currentDefinition = $definition;
            $this->processArguments($definition->getArguments());

            if (!$this->onlyConstructorArguments) {
                $this->processArguments($definition->getMethodCalls());
                $this->processArguments($definition->getProperties());
                if ($definition->getConfigurator()) {
                    $this->processArguments(array($definition->getConfigurator()));
                }
            }
        }

        foreach ($container->getAliases() as $id => $alias) {
            $this->graph->connect($id, $alias, (string) $alias, $this->getDefinition((string) $alias), null);
        }
    }

    /**
     * Processes service definitions for arguments to find relationships for the service graph.
     *
     * @param array $arguments An array of Reference or Definition objects relating to service definitions
     */
    private function processArguments(array $arguments)
    {
        foreach ($arguments as $argument) {
            if (is_array($argument)) {
                $this->processArguments($argument);
            } elseif ($argument instanceof Reference) {
                $this->graph->connect(
                    $this->currentId,
                    $this->currentDefinition,
                    $this->getDefinitionId((string) $argument),
                    $this->getDefinition((string) $argument),
                    $argument
                );
            } elseif ($argument instanceof Definition) {
                $this->processArguments($argument->getArguments());
                $this->processArguments($argument->getMethodCalls());
                $this->processArguments($argument->getProperties());
            }
        }
    }

    /**
     * Returns a service definition given the full name or an alias.
     *
     * @param string $id A full id or alias for a service definition.
     *
     * @return Definition|null The definition related to the supplied id
     */
    private function getDefinition($id)
    {
        $id = $this->getDefinitionId($id);

        return null === $id ? null : $this->container->getDefinition($id);
    }

    private function getDefinitionId($id)
    {
        while ($this->container->hasAlias($id)) {
            $id = (string) $this->container->getAlias($id);
        }

        if (!$this->container->hasDefinition($id)) {
            return null;
        }

        return $id;
    }
}
PK��Z�����CSymfony/Component/DependencyInjection/Compiler/LoggingFormatter.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

/**
 * Used to format logging messages during the compilation.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class LoggingFormatter
{
    public function formatRemoveService(CompilerPassInterface $pass, $id, $reason)
    {
        return $this->format($pass, sprintf('Removed service "%s"; reason: %s', $id, $reason));
    }

    public function formatInlineService(CompilerPassInterface $pass, $id, $target)
    {
        return $this->format($pass, sprintf('Inlined service "%s" to "%s".', $id, $target));
    }

    public function formatUpdateReference(CompilerPassInterface $pass, $serviceId, $oldDestId, $newDestId)
    {
        return $this->format($pass, sprintf('Changed reference of service "%s" previously pointing to "%s" to "%s".', $serviceId, $oldDestId, $newDestId));
    }

    public function formatResolveInheritance(CompilerPassInterface $pass, $childId, $parentId)
    {
        return $this->format($pass, sprintf('Resolving inheritance for "%s" (parent: %s).', $childId, $parentId));
    }

    public function format(CompilerPassInterface $pass, $message)
    {
        return sprintf('%s: %s', get_class($pass), $message);
    }
}
PK��Z����EBEB3Symfony/Component/DependencyInjection/Container.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;

/**
 * Container is a dependency injection container.
 *
 * It gives access to object instances (services).
 *
 * Services and parameters are simple key/pair stores.
 *
 * Parameter and service keys are case insensitive.
 *
 * A service id can contain lowercased letters, digits, underscores, and dots.
 * Underscores are used to separate words, and dots to group services
 * under namespaces:
 *
 * <ul>
 *   <li>request</li>
 *   <li>mysql_session_storage</li>
 *   <li>symfony.mysql_session_storage</li>
 * </ul>
 *
 * A service can also be defined by creating a method named
 * getXXXService(), where XXX is the camelized version of the id:
 *
 * <ul>
 *   <li>request -> getRequestService()</li>
 *   <li>mysql_session_storage -> getMysqlSessionStorageService()</li>
 *   <li>symfony.mysql_session_storage -> getSymfony_MysqlSessionStorageService()</li>
 * </ul>
 *
 * The container can have three possible behaviors when a service does not exist:
 *
 *  * EXCEPTION_ON_INVALID_REFERENCE: Throws an exception (the default)
 *  * NULL_ON_INVALID_REFERENCE:      Returns null
 *  * IGNORE_ON_INVALID_REFERENCE:    Ignores the wrapping command asking for the reference
 *                                    (for instance, ignore a setter if the service does not exist)
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @api
 */
class Container implements IntrospectableContainerInterface
{
    /**
     * @var ParameterBagInterface
     */
    protected $parameterBag;

    protected $services = array();
    protected $methodMap = array();
    protected $aliases = array();
    protected $scopes = array();
    protected $scopeChildren = array();
    protected $scopedServices = array();
    protected $scopeStacks = array();
    protected $loading = array();

    /**
     * Constructor.
     *
     * @param ParameterBagInterface $parameterBag A ParameterBagInterface instance
     *
     * @api
     */
    public function __construct(ParameterBagInterface $parameterBag = null)
    {
        $this->parameterBag = $parameterBag ?: new ParameterBag();

        $this->set('service_container', $this);
    }

    /**
     * Compiles the container.
     *
     * This method does two things:
     *
     *  * Parameter values are resolved;
     *  * The parameter bag is frozen.
     *
     * @api
     */
    public function compile()
    {
        $this->parameterBag->resolve();

        $this->parameterBag = new FrozenParameterBag($this->parameterBag->all());
    }

    /**
     * Returns true if the container parameter bag are frozen.
     *
     * @return Boolean true if the container parameter bag are frozen, false otherwise
     *
     * @api
     */
    public function isFrozen()
    {
        return $this->parameterBag instanceof FrozenParameterBag;
    }

    /**
     * Gets the service container parameter bag.
     *
     * @return ParameterBagInterface A ParameterBagInterface instance
     *
     * @api
     */
    public function getParameterBag()
    {
        return $this->parameterBag;
    }

    /**
     * Gets a parameter.
     *
     * @param string $name The parameter name
     *
     * @return mixed  The parameter value
     *
     * @throws InvalidArgumentException if the parameter is not defined
     *
     * @api
     */
    public function getParameter($name)
    {
        return $this->parameterBag->get($name);
    }

    /**
     * Checks if a parameter exists.
     *
     * @param string $name The parameter name
     *
     * @return Boolean The presence of parameter in container
     *
     * @api
     */
    public function hasParameter($name)
    {
        return $this->parameterBag->has($name);
    }

    /**
     * Sets a parameter.
     *
     * @param string $name  The parameter name
     * @param mixed  $value The parameter value
     *
     * @api
     */
    public function setParameter($name, $value)
    {
        $this->parameterBag->set($name, $value);
    }

    /**
     * Sets a service.
     *
     * Setting a service to null resets the service: has() returns false and get()
     * behaves in the same way as if the service was never created.
     *
     * @param string $id      The service identifier
     * @param object $service The service instance
     * @param string $scope   The scope of the service
     *
     * @throws RuntimeException When trying to set a service in an inactive scope
     * @throws InvalidArgumentException When trying to set a service in the prototype scope
     *
     * @api
     */
    public function set($id, $service, $scope = self::SCOPE_CONTAINER)
    {
        if (self::SCOPE_PROTOTYPE === $scope) {
            throw new InvalidArgumentException(sprintf('You cannot set service "%s" of scope "prototype".', $id));
        }

        $id = strtolower($id);

        if (self::SCOPE_CONTAINER !== $scope) {
            if (!isset($this->scopedServices[$scope])) {
                throw new RuntimeException(sprintf('You cannot set service "%s" of inactive scope.', $id));
            }

            $this->scopedServices[$scope][$id] = $service;
        }

        $this->services[$id] = $service;

        if (method_exists($this, $method = 'synchronize'.strtr($id, array('_' => '', '.' => '_', '\\' => '_')).'Service')) {
            $this->$method();
        }

        if (self::SCOPE_CONTAINER !== $scope && null === $service) {
            unset($this->scopedServices[$scope][$id]);
        }

        if (null === $service) {
            unset($this->services[$id]);
        }
    }

    /**
     * Returns true if the given service is defined.
     *
     * @param string $id The service identifier
     *
     * @return Boolean true if the service is defined, false otherwise
     *
     * @api
     */
    public function has($id)
    {
        $id = strtolower($id);

        return isset($this->services[$id])
            || array_key_exists($id, $this->services)
            || isset($this->aliases[$id])
            || method_exists($this, 'get'.strtr($id, array('_' => '', '.' => '_', '\\' => '_')).'Service')
        ;
    }

    /**
     * Gets a service.
     *
     * If a service is defined both through a set() method and
     * with a get{$id}Service() method, the former has always precedence.
     *
     * @param string  $id              The service identifier
     * @param integer $invalidBehavior The behavior when the service does not exist
     *
     * @return object The associated service
     *
     * @throws InvalidArgumentException if the service is not defined
     * @throws ServiceCircularReferenceException When a circular reference is detected
     * @throws ServiceNotFoundException When the service is not defined
     *
     * @see Reference
     *
     * @api
     */
    public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE)
    {
        // Attempt to retrieve the service by checking first aliases then
        // available services. Service IDs are case insensitive, however since
        // this method can be called thousands of times during a request, avoid
        // calling strtolower() unless necessary.
        foreach (array(false, true) as $strtolower) {
            if ($strtolower) {
                $id = strtolower($id);
            }
            if (isset($this->aliases[$id])) {
                $id = $this->aliases[$id];
            }
            // Re-use shared service instance if it exists.
            if (isset($this->services[$id]) || array_key_exists($id, $this->services)) {
                return $this->services[$id];
            }
        }

        if (isset($this->loading[$id])) {
            throw new ServiceCircularReferenceException($id, array_keys($this->loading));
        }

        if (isset($this->methodMap[$id])) {
            $method = $this->methodMap[$id];
        } elseif (method_exists($this, $method = 'get'.strtr($id, array('_' => '', '.' => '_', '\\' => '_')).'Service')) {
            // $method is set to the right value, proceed
        } else {
            if (self::EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior) {
                if (!$id) {
                    throw new ServiceNotFoundException($id);
                }

                $alternatives = array();
                foreach (array_keys($this->services) as $key) {
                    $lev = levenshtein($id, $key);
                    if ($lev <= strlen($id) / 3 || false !== strpos($key, $id)) {
                        $alternatives[] = $key;
                    }
                }

                throw new ServiceNotFoundException($id, null, null, $alternatives);
            }

            return null;
        }

        $this->loading[$id] = true;

        try {
            $service = $this->$method();
        } catch (\Exception $e) {
            unset($this->loading[$id]);

            if (array_key_exists($id, $this->services)) {
                unset($this->services[$id]);
            }

            if ($e instanceof InactiveScopeException && self::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) {
                return null;
            }

            throw $e;
        }

        unset($this->loading[$id]);

        return $service;
    }

    /**
     * Returns true if the given service has actually been initialized
     *
     * @param string $id The service identifier
     *
     * @return Boolean true if service has already been initialized, false otherwise
     */
    public function initialized($id)
    {
        $id = strtolower($id);

        return isset($this->services[$id]) || array_key_exists($id, $this->services);
    }

    /**
     * Gets all service ids.
     *
     * @return array An array of all defined service ids
     */
    public function getServiceIds()
    {
        $ids = array();
        $r = new \ReflectionClass($this);
        foreach ($r->getMethods() as $method) {
            if (preg_match('/^get(.+)Service$/', $method->name, $match)) {
                $ids[] = self::underscore($match[1]);
            }
        }

        return array_unique(array_merge($ids, array_keys($this->services)));
    }

    /**
     * This is called when you enter a scope
     *
     * @param string $name
     *
     * @throws RuntimeException         When the parent scope is inactive
     * @throws InvalidArgumentException When the scope does not exist
     *
     * @api
     */
    public function enterScope($name)
    {
        if (!isset($this->scopes[$name])) {
            throw new InvalidArgumentException(sprintf('The scope "%s" does not exist.', $name));
        }

        if (self::SCOPE_CONTAINER !== $this->scopes[$name] && !isset($this->scopedServices[$this->scopes[$name]])) {
            throw new RuntimeException(sprintf('The parent scope "%s" must be active when entering this scope.', $this->scopes[$name]));
        }

        // check if a scope of this name is already active, if so we need to
        // remove all services of this scope, and those of any of its child
        // scopes from the global services map
        if (isset($this->scopedServices[$name])) {
            $services = array($this->services, $name => $this->scopedServices[$name]);
            unset($this->scopedServices[$name]);

            foreach ($this->scopeChildren[$name] as $child) {
                if (isset($this->scopedServices[$child])) {
                    $services[$child] = $this->scopedServices[$child];
                    unset($this->scopedServices[$child]);
                }
            }

            // update global map
            $this->services = call_user_func_array('array_diff_key', $services);
            array_shift($services);

            // add stack entry for this scope so we can restore the removed services later
            if (!isset($this->scopeStacks[$name])) {
                $this->scopeStacks[$name] = new \SplStack();
            }
            $this->scopeStacks[$name]->push($services);
        }

        $this->scopedServices[$name] = array();
    }

    /**
     * This is called to leave the current scope, and move back to the parent
     * scope.
     *
     * @param string $name The name of the scope to leave
     *
     * @throws InvalidArgumentException if the scope is not active
     *
     * @api
     */
    public function leaveScope($name)
    {
        if (!isset($this->scopedServices[$name])) {
            throw new InvalidArgumentException(sprintf('The scope "%s" is not active.', $name));
        }

        // remove all services of this scope, or any of its child scopes from
        // the global service map
        $services = array($this->services, $this->scopedServices[$name]);
        unset($this->scopedServices[$name]);
        foreach ($this->scopeChildren[$name] as $child) {
            if (!isset($this->scopedServices[$child])) {
                continue;
            }

            $services[] = $this->scopedServices[$child];
            unset($this->scopedServices[$child]);
        }
        $this->services = call_user_func_array('array_diff_key', $services);

        // check if we need to restore services of a previous scope of this type
        if (isset($this->scopeStacks[$name]) && count($this->scopeStacks[$name]) > 0) {
            $services = $this->scopeStacks[$name]->pop();
            $this->scopedServices += $services;

            foreach ($services as $array) {
                foreach ($array as $id => $service) {
                    $this->set($id, $service, $name);
                }
            }
        }
    }

    /**
     * Adds a scope to the container.
     *
     * @param ScopeInterface $scope
     *
     * @throws InvalidArgumentException
     *
     * @api
     */
    public function addScope(ScopeInterface $scope)
    {
        $name = $scope->getName();
        $parentScope = $scope->getParentName();

        if (self::SCOPE_CONTAINER === $name || self::SCOPE_PROTOTYPE === $name) {
            throw new InvalidArgumentException(sprintf('The scope "%s" is reserved.', $name));
        }
        if (isset($this->scopes[$name])) {
            throw new InvalidArgumentException(sprintf('A scope with name "%s" already exists.', $name));
        }
        if (self::SCOPE_CONTAINER !== $parentScope && !isset($this->scopes[$parentScope])) {
            throw new InvalidArgumentException(sprintf('The parent scope "%s" does not exist, or is invalid.', $parentScope));
        }

        $this->scopes[$name] = $parentScope;
        $this->scopeChildren[$name] = array();

        // normalize the child relations
        while ($parentScope !== self::SCOPE_CONTAINER) {
            $this->scopeChildren[$parentScope][] = $name;
            $parentScope = $this->scopes[$parentScope];
        }
    }

    /**
     * Returns whether this container has a certain scope
     *
     * @param string $name The name of the scope
     *
     * @return Boolean
     *
     * @api
     */
    public function hasScope($name)
    {
        return isset($this->scopes[$name]);
    }

    /**
     * Returns whether this scope is currently active
     *
     * This does not actually check if the passed scope actually exists.
     *
     * @param string $name
     *
     * @return Boolean
     *
     * @api
     */
    public function isScopeActive($name)
    {
        return isset($this->scopedServices[$name]);
    }

    /**
     * Camelizes a string.
     *
     * @param string $id A string to camelize
     *
     * @return string The camelized string
     */
    public static function camelize($id)
    {
        return strtr(ucwords(strtr($id, array('_' => ' ', '.' => '_ ', '\\' => '_ '))), array(' ' => ''));
    }

    /**
     * A string to underscore.
     *
     * @param string $id The string to underscore
     *
     * @return string The underscored string
     */
    public static function underscore($id)
    {
        return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), strtr($id, '_', '.')));
    }
}
PK��Z�E�?<Symfony/Component/DependencyInjection/ContainerInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;

/**
 * ContainerInterface is the interface implemented by service container classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @api
 */
interface ContainerInterface
{
    const EXCEPTION_ON_INVALID_REFERENCE = 1;
    const NULL_ON_INVALID_REFERENCE      = 2;
    const IGNORE_ON_INVALID_REFERENCE    = 3;
    const SCOPE_CONTAINER                = 'container';
    const SCOPE_PROTOTYPE                = 'prototype';

    /**
     * Sets a service.
     *
     * @param string $id      The service identifier
     * @param object $service The service instance
     * @param string $scope   The scope of the service
     *
     * @api
     */
    public function set($id, $service, $scope = self::SCOPE_CONTAINER);

    /**
     * Gets a service.
     *
     * @param string $id              The service identifier
     * @param int    $invalidBehavior The behavior when the service does not exist
     *
     * @return object The associated service
     *
     * @throws InvalidArgumentException if the service is not defined
     * @throws ServiceCircularReferenceException When a circular reference is detected
     * @throws ServiceNotFoundException When the service is not defined
     *
     * @see Reference
     *
     * @api
     */
    public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE);

    /**
     * Returns true if the given service is defined.
     *
     * @param string $id The service identifier
     *
     * @return Boolean true if the service is defined, false otherwise
     *
     * @api
     */
    public function has($id);

    /**
     * Gets a parameter.
     *
     * @param string $name The parameter name
     *
     * @return mixed  The parameter value
     *
     * @throws InvalidArgumentException if the parameter is not defined
     *
     * @api
     */
    public function getParameter($name);

    /**
     * Checks if a parameter exists.
     *
     * @param string $name The parameter name
     *
     * @return Boolean The presence of parameter in container
     *
     * @api
     */
    public function hasParameter($name);

    /**
     * Sets a parameter.
     *
     * @param string $name  The parameter name
     * @param mixed  $value The parameter value
     *
     * @api
     */
    public function setParameter($name, $value);

    /**
     * Enters the given scope
     *
     * @param string $name
     *
     * @api
     */
    public function enterScope($name);

    /**
     * Leaves the current scope, and re-enters the parent scope
     *
     * @param string $name
     *
     * @api
     */
    public function leaveScope($name);

    /**
     * Adds a scope to the container
     *
     * @param ScopeInterface $scope
     *
     * @api
     */
    public function addScope(ScopeInterface $scope);

    /**
     * Whether this container has the given scope
     *
     * @param string $name
     *
     * @return Boolean
     *
     * @api
     */
    public function hasScope($name);

    /**
     * Determines whether the given scope is currently active.
     *
     * It does however not check if the scope actually exists.
     *
     * @param string $name
     *
     * @return Boolean
     *
     * @api
     */
    public function isScopeActive($name);
}
PK��Z�o
�=Symfony/Component/DependencyInjection/Extension/Extension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Extension;

use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Exception\BadMethodCallException;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\Definition\Processor;
use Symfony\Component\Config\Definition\ConfigurationInterface;

/**
 * Provides useful features shared by many extensions.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class Extension implements ExtensionInterface, ConfigurationExtensionInterface
{
    /**
     * Returns the base path for the XSD files.
     *
     * @return string The XSD base path
     */
    public function getXsdValidationBasePath()
    {
        return false;
    }

    /**
     * Returns the namespace to be used for this extension (XML namespace).
     *
     * @return string The XML namespace
     */
    public function getNamespace()
    {
        return 'http://example.org/schema/dic/'.$this->getAlias();
    }

    /**
     * Returns the recommended alias to use in XML.
     *
     * This alias is also the mandatory prefix to use when using YAML.
     *
     * This convention is to remove the "Extension" postfix from the class
     * name and then lowercase and underscore the result. So:
     *
     *     AcmeHelloExtension
     *
     * becomes
     *
     *     acme_hello
     *
     * This can be overridden in a sub-class to specify the alias manually.
     *
     * @return string The alias
     *
     * @throws BadMethodCallException When the extension name does not follow conventions
     */
    public function getAlias()
    {
        $className = get_class($this);
        if (substr($className, -9) != 'Extension') {
            throw new BadMethodCallException('This extension does not follow the naming convention; you must overwrite the getAlias() method.');
        }
        $classBaseName = substr(strrchr($className, '\\'), 1, -9);

        return Container::underscore($classBaseName);
    }

    /**
     * {@inheritDoc}
     */
    public function getConfiguration(array $config, ContainerBuilder $container)
    {
        $reflected = new \ReflectionClass($this);
        $namespace = $reflected->getNamespaceName();

        $class = $namespace.'\\Configuration';
        if (class_exists($class)) {
            $r = new \ReflectionClass($class);
            $container->addResource(new FileResource($r->getFileName()));

            if (!method_exists($class, '__construct')) {
                $configuration = new $class();

                return $configuration;
            }
        }

        return null;
    }

    final protected function processConfiguration(ConfigurationInterface $configuration, array $configs)
    {
        $processor = new Processor();

        return $processor->processConfiguration($configuration, $configs);
    }

    /**
     * @param ContainerBuilder $container
     * @param array            $config
     *
     * @return Boolean Whether the configuration is enabled
     *
     * @throws InvalidArgumentException When the config is not enableable
     */
    protected function isConfigEnabled(ContainerBuilder $container, array $config)
    {
        if (!array_key_exists('enabled', $config)) {
            throw new InvalidArgumentException("The config array has no 'enabled' key.");
        }

        return (Boolean) $container->getParameterBag()->resolveValue($config['enabled']);
    }
}
PK��ZDS�FSymfony/Component/DependencyInjection/Extension/ExtensionInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Extension;

use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * ExtensionInterface is the interface implemented by container extension classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface ExtensionInterface
{
    /**
     * Loads a specific configuration.
     *
     * @param array            $config    An array of configuration values
     * @param ContainerBuilder $container A ContainerBuilder instance
     *
     * @throws \InvalidArgumentException When provided tag is not defined in this extension
     *
     * @api
     */
    public function load(array $config, ContainerBuilder $container);

    /**
     * Returns the namespace to be used for this extension (XML namespace).
     *
     * @return string The XML namespace
     *
     * @api
     */
    public function getNamespace();

    /**
     * Returns the base path for the XSD files.
     *
     * @return string The XSD base path
     *
     * @api
     */
    public function getXsdValidationBasePath();

    /**
     * Returns the recommended alias to use in XML.
     *
     * This alias is also the mandatory prefix to use when using YAML.
     *
     * @return string The alias
     *
     * @api
     */
    public function getAlias();
}
PK��Z��J��SSymfony/Component/DependencyInjection/Extension/ConfigurationExtensionInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Extension;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;

/**
 * ConfigurationExtensionInterface is the interface implemented by container extension classes.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 */
interface ConfigurationExtensionInterface
{
    /**
     * Returns extension configuration
     *
     * @param array            $config    $config    An array of configuration values
     * @param ContainerBuilder $container A ContainerBuilder instance
     *
     * @return ConfigurationInterface|null The configuration or null
     */
    public function getConfiguration(array $config, ContainerBuilder $container);
}
PK��ZC��oMMMSymfony/Component/DependencyInjection/Extension/PrependExtensionInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Extension;

use Symfony\Component\DependencyInjection\ContainerBuilder;

interface PrependExtensionInterface
{
    /**
     * Allow an extension to prepend the extension configurations.
     *
     * @param ContainerBuilder $container
     */
    public function prepend(ContainerBuilder $container);
}
PK��Z��F"��3Symfony/Component/DependencyInjection/Parameter.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

/**
 * Parameter represents a parameter reference.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class Parameter
{
    private $id;

    /**
     * Constructor.
     *
     * @param string $id The parameter key
     */
    public function __construct($id)
    {
        $this->id = $id;
    }

    /**
     * __toString.
     *
     * @return string The parameter key
     */
    public function __toString()
    {
        return (string) $this->id;
    }
}
PK��Z��
����
Net/IDNA2.phpnu�[���<?php

// {{{ license

/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
//
// +----------------------------------------------------------------------+
// | This library is free software; you can redistribute it and/or modify |
// | it under the terms of the GNU Lesser General Public License as       |
// | published by the Free Software Foundation; either version 2.1 of the |
// | License, or (at your option) any later version.                      |
// |                                                                      |
// | This library is distributed in the hope that it will be useful, but  |
// | WITHOUT ANY WARRANTY; without even the implied warranty of           |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    |
// | Lesser General Public License for more details.                      |
// |                                                                      |
// | You should have received a copy of the GNU Lesser General Public     |
// | License along with this library; if not, write to the Free Software  |
// | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 |
// | USA.                                                                 |
// +----------------------------------------------------------------------+
//

// }}}
require_once 'Net/IDNA2/Exception.php';
require_once 'Net/IDNA2/Exception/Nameprep.php';

/**
 * Encode/decode Internationalized Domain Names.
 *
 * The class allows one to convert internationalized domain names
 * (see RFC 3490 for details) as they can be used with various registries worldwide
 * to be translated between their original (localized) form and their encoded form
 * as it will be used in the DNS (Domain Name System).
 *
 * The class provides two public methods, encode() and decode(), which do exactly
 * what you would expect them to do. You are allowed to use complete domain names,
 * simple strings and complete email addresses as well. That means, that you might
 * use any of the following notations:
 *
 * - www.n�rgler.com
 * - xn--nrgler-wxa
 * - xn--brse-5qa.xn--knrz-1ra.info
 *
 * Unicode input might be given as either UTF-8 string, UCS-4 string or UCS-4
 * array. Unicode output is available in the same formats.
 * You can select your preferred format via {@link set_paramter()}.
 *
 * ACE input and output is always expected to be ASCII.
 *
 * @package Net
 * @author  Markus Nix <mnix@docuverse.de>
 * @author  Matthias Sommerfeld <mso@phlylabs.de>
 * @author  Stefan Neufeind <pear.neufeind@speedpartner.de>
 * @version $Id$
 */
class Net_IDNA2
{
    // {{{ npdata
    /**
     * These Unicode codepoints are
     * mapped to nothing, See RFC3454 for details
     *
     * @static
     * @var array
     * @access private
     */
    private static $_np_map_nothing = array(
        0xAD,
        0x34F,
        0x1806,
        0x180B,
        0x180C,
        0x180D,
        0x200B,
        0x200C,
        0x200D,
        0x2060,
        0xFE00,
        0xFE01,
        0xFE02,
        0xFE03,
        0xFE04,
        0xFE05,
        0xFE06,
        0xFE07,
        0xFE08,
        0xFE09,
        0xFE0A,
        0xFE0B,
        0xFE0C,
        0xFE0D,
        0xFE0E,
        0xFE0F,
        0xFEFF
    );

    /**
     * Prohibited codepints
     *
     * @static
     * @var array
     * @access private
     */
    private static $_general_prohibited = array(
        0,
        1,
        2,
        3,
        4,
        5,
        6,
        7,
        8,
        9,
        0xA,
        0xB,
        0xC,
        0xD,
        0xE,
        0xF,
        0x10,
        0x11,
        0x12,
        0x13,
        0x14,
        0x15,
        0x16,
        0x17,
        0x18,
        0x19,
        0x1A,
        0x1B,
        0x1C,
        0x1D,
        0x1E,
        0x1F,
        0x20,
        0x21,
        0x22,
        0x23,
        0x24,
        0x25,
        0x26,
        0x27,
        0x28,
        0x29,
        0x2A,
        0x2B,
        0x2C,
        0x2F,
        0x3B,
        0x3C,
        0x3D,
        0x3E,
        0x3F,
        0x40,
        0x5B,
        0x5C,
        0x5D,
        0x5E,
        0x5F,
        0x60,
        0x7B,
        0x7C,
        0x7D,
        0x7E,
        0x7F,
        0x3002
    );

    /**
     * Codepints prohibited by Nameprep
     * @static
     * @var array
     * @access private
     */
    private static $_np_prohibit = array(
        0xA0,
        0x1680,
        0x2000,
        0x2001,
        0x2002,
        0x2003,
        0x2004,
        0x2005,
        0x2006,
        0x2007,
        0x2008,
        0x2009,
        0x200A,
        0x200B,
        0x202F,
        0x205F,
        0x3000,
        0x6DD,
        0x70F,
        0x180E,
        0x200C,
        0x200D,
        0x2028,
        0x2029,
        0xFEFF,
        0xFFF9,
        0xFFFA,
        0xFFFB,
        0xFFFC,
        0xFFFE,
        0xFFFF,
        0x1FFFE,
        0x1FFFF,
        0x2FFFE,
        0x2FFFF,
        0x3FFFE,
        0x3FFFF,
        0x4FFFE,
        0x4FFFF,
        0x5FFFE,
        0x5FFFF,
        0x6FFFE,
        0x6FFFF,
        0x7FFFE,
        0x7FFFF,
        0x8FFFE,
        0x8FFFF,
        0x9FFFE,
        0x9FFFF,
        0xAFFFE,
        0xAFFFF,
        0xBFFFE,
        0xBFFFF,
        0xCFFFE,
        0xCFFFF,
        0xDFFFE,
        0xDFFFF,
        0xEFFFE,
        0xEFFFF,
        0xFFFFE,
        0xFFFFF,
        0x10FFFE,
        0x10FFFF,
        0xFFF9,
        0xFFFA,
        0xFFFB,
        0xFFFC,
        0xFFFD,
        0x340,
        0x341,
        0x200E,
        0x200F,
        0x202A,
        0x202B,
        0x202C,
        0x202D,
        0x202E,
        0x206A,
        0x206B,
        0x206C,
        0x206D,
        0x206E,
        0x206F,
        0xE0001
    );

    /**
     * Codepoint ranges prohibited by nameprep
     *
     * @static
     * @var array
     * @access private
     */
    private static $_np_prohibit_ranges = array(
        array(0x80,     0x9F    ),
        array(0x2060,   0x206F  ),
        array(0x1D173,  0x1D17A ),
        array(0xE000,   0xF8FF  ),
        array(0xF0000,  0xFFFFD ),
        array(0x100000, 0x10FFFD),
        array(0xFDD0,   0xFDEF  ),
        array(0xD800,   0xDFFF  ),
        array(0x2FF0,   0x2FFB  ),
        array(0xE0020,  0xE007F )
    );

    /**
     * Replacement mappings (casemapping, replacement sequences, ...)
     *
     * @static
     * @var array
     * @access private
     */
    private static $_np_replacemaps = array(
        0x41    => array(0x61),
        0x42    => array(0x62),
        0x43    => array(0x63),
        0x44    => array(0x64),
        0x45    => array(0x65),
        0x46    => array(0x66),
        0x47    => array(0x67),
        0x48    => array(0x68),
        0x49    => array(0x69),
        0x4A    => array(0x6A),
        0x4B    => array(0x6B),
        0x4C    => array(0x6C),
        0x4D    => array(0x6D),
        0x4E    => array(0x6E),
        0x4F    => array(0x6F),
        0x50    => array(0x70),
        0x51    => array(0x71),
        0x52    => array(0x72),
        0x53    => array(0x73),
        0x54    => array(0x74),
        0x55    => array(0x75),
        0x56    => array(0x76),
        0x57    => array(0x77),
        0x58    => array(0x78),
        0x59    => array(0x79),
        0x5A    => array(0x7A),
        0xB5    => array(0x3BC),
        0xC0    => array(0xE0),
        0xC1    => array(0xE1),
        0xC2    => array(0xE2),
        0xC3    => array(0xE3),
        0xC4    => array(0xE4),
        0xC5    => array(0xE5),
        0xC6    => array(0xE6),
        0xC7    => array(0xE7),
        0xC8    => array(0xE8),
        0xC9    => array(0xE9),
        0xCA    => array(0xEA),
        0xCB    => array(0xEB),
        0xCC    => array(0xEC),
        0xCD    => array(0xED),
        0xCE    => array(0xEE),
        0xCF    => array(0xEF),
        0xD0    => array(0xF0),
        0xD1    => array(0xF1),
        0xD2    => array(0xF2),
        0xD3    => array(0xF3),
        0xD4    => array(0xF4),
        0xD5    => array(0xF5),
        0xD6    => array(0xF6),
        0xD8    => array(0xF8),
        0xD9    => array(0xF9),
        0xDA    => array(0xFA),
        0xDB    => array(0xFB),
        0xDC    => array(0xFC),
        0xDD    => array(0xFD),
        0xDE    => array(0xFE),
        0xDF    => array(0x73, 0x73),
        0x100   => array(0x101),
        0x102   => array(0x103),
        0x104   => array(0x105),
        0x106   => array(0x107),
        0x108   => array(0x109),
        0x10A   => array(0x10B),
        0x10C   => array(0x10D),
        0x10E   => array(0x10F),
        0x110   => array(0x111),
        0x112   => array(0x113),
        0x114   => array(0x115),
        0x116   => array(0x117),
        0x118   => array(0x119),
        0x11A   => array(0x11B),
        0x11C   => array(0x11D),
        0x11E   => array(0x11F),
        0x120   => array(0x121),
        0x122   => array(0x123),
        0x124   => array(0x125),
        0x126   => array(0x127),
        0x128   => array(0x129),
        0x12A   => array(0x12B),
        0x12C   => array(0x12D),
        0x12E   => array(0x12F),
        0x130   => array(0x69, 0x307),
        0x132   => array(0x133),
        0x134   => array(0x135),
        0x136   => array(0x137),
        0x139   => array(0x13A),
        0x13B   => array(0x13C),
        0x13D   => array(0x13E),
        0x13F   => array(0x140),
        0x141   => array(0x142),
        0x143   => array(0x144),
        0x145   => array(0x146),
        0x147   => array(0x148),
        0x149   => array(0x2BC, 0x6E),
        0x14A   => array(0x14B),
        0x14C   => array(0x14D),
        0x14E   => array(0x14F),
        0x150   => array(0x151),
        0x152   => array(0x153),
        0x154   => array(0x155),
        0x156   => array(0x157),
        0x158   => array(0x159),
        0x15A   => array(0x15B),
        0x15C   => array(0x15D),
        0x15E   => array(0x15F),
        0x160   => array(0x161),
        0x162   => array(0x163),
        0x164   => array(0x165),
        0x166   => array(0x167),
        0x168   => array(0x169),
        0x16A   => array(0x16B),
        0x16C   => array(0x16D),
        0x16E   => array(0x16F),
        0x170   => array(0x171),
        0x172   => array(0x173),
        0x174   => array(0x175),
        0x176   => array(0x177),
        0x178   => array(0xFF),
        0x179   => array(0x17A),
        0x17B   => array(0x17C),
        0x17D   => array(0x17E),
        0x17F   => array(0x73),
        0x181   => array(0x253),
        0x182   => array(0x183),
        0x184   => array(0x185),
        0x186   => array(0x254),
        0x187   => array(0x188),
        0x189   => array(0x256),
        0x18A   => array(0x257),
        0x18B   => array(0x18C),
        0x18E   => array(0x1DD),
        0x18F   => array(0x259),
        0x190   => array(0x25B),
        0x191   => array(0x192),
        0x193   => array(0x260),
        0x194   => array(0x263),
        0x196   => array(0x269),
        0x197   => array(0x268),
        0x198   => array(0x199),
        0x19C   => array(0x26F),
        0x19D   => array(0x272),
        0x19F   => array(0x275),
        0x1A0   => array(0x1A1),
        0x1A2   => array(0x1A3),
        0x1A4   => array(0x1A5),
        0x1A6   => array(0x280),
        0x1A7   => array(0x1A8),
        0x1A9   => array(0x283),
        0x1AC   => array(0x1AD),
        0x1AE   => array(0x288),
        0x1AF   => array(0x1B0),
        0x1B1   => array(0x28A),
        0x1B2   => array(0x28B),
        0x1B3   => array(0x1B4),
        0x1B5   => array(0x1B6),
        0x1B7   => array(0x292),
        0x1B8   => array(0x1B9),
        0x1BC   => array(0x1BD),
        0x1C4   => array(0x1C6),
        0x1C5   => array(0x1C6),
        0x1C7   => array(0x1C9),
        0x1C8   => array(0x1C9),
        0x1CA   => array(0x1CC),
        0x1CB   => array(0x1CC),
        0x1CD   => array(0x1CE),
        0x1CF   => array(0x1D0),
        0x1D1   => array(0x1D2),
        0x1D3   => array(0x1D4),
        0x1D5   => array(0x1D6),
        0x1D7   => array(0x1D8),
        0x1D9   => array(0x1DA),
        0x1DB   => array(0x1DC),
        0x1DE   => array(0x1DF),
        0x1E0   => array(0x1E1),
        0x1E2   => array(0x1E3),
        0x1E4   => array(0x1E5),
        0x1E6   => array(0x1E7),
        0x1E8   => array(0x1E9),
        0x1EA   => array(0x1EB),
        0x1EC   => array(0x1ED),
        0x1EE   => array(0x1EF),
        0x1F0   => array(0x6A, 0x30C),
        0x1F1   => array(0x1F3),
        0x1F2   => array(0x1F3),
        0x1F4   => array(0x1F5),
        0x1F6   => array(0x195),
        0x1F7   => array(0x1BF),
        0x1F8   => array(0x1F9),
        0x1FA   => array(0x1FB),
        0x1FC   => array(0x1FD),
        0x1FE   => array(0x1FF),
        0x200   => array(0x201),
        0x202   => array(0x203),
        0x204   => array(0x205),
        0x206   => array(0x207),
        0x208   => array(0x209),
        0x20A   => array(0x20B),
        0x20C   => array(0x20D),
        0x20E   => array(0x20F),
        0x210   => array(0x211),
        0x212   => array(0x213),
        0x214   => array(0x215),
        0x216   => array(0x217),
        0x218   => array(0x219),
        0x21A   => array(0x21B),
        0x21C   => array(0x21D),
        0x21E   => array(0x21F),
        0x220   => array(0x19E),
        0x222   => array(0x223),
        0x224   => array(0x225),
        0x226   => array(0x227),
        0x228   => array(0x229),
        0x22A   => array(0x22B),
        0x22C   => array(0x22D),
        0x22E   => array(0x22F),
        0x230   => array(0x231),
        0x232   => array(0x233),
        0x345   => array(0x3B9),
        0x37A   => array(0x20, 0x3B9),
        0x386   => array(0x3AC),
        0x388   => array(0x3AD),
        0x389   => array(0x3AE),
        0x38A   => array(0x3AF),
        0x38C   => array(0x3CC),
        0x38E   => array(0x3CD),
        0x38F   => array(0x3CE),
        0x390   => array(0x3B9, 0x308, 0x301),
        0x391   => array(0x3B1),
        0x392   => array(0x3B2),
        0x393   => array(0x3B3),
        0x394   => array(0x3B4),
        0x395   => array(0x3B5),
        0x396   => array(0x3B6),
        0x397   => array(0x3B7),
        0x398   => array(0x3B8),
        0x399   => array(0x3B9),
        0x39A   => array(0x3BA),
        0x39B   => array(0x3BB),
        0x39C   => array(0x3BC),
        0x39D   => array(0x3BD),
        0x39E   => array(0x3BE),
        0x39F   => array(0x3BF),
        0x3A0   => array(0x3C0),
        0x3A1   => array(0x3C1),
        0x3A3   => array(0x3C3),
        0x3A4   => array(0x3C4),
        0x3A5   => array(0x3C5),
        0x3A6   => array(0x3C6),
        0x3A7   => array(0x3C7),
        0x3A8   => array(0x3C8),
        0x3A9   => array(0x3C9),
        0x3AA   => array(0x3CA),
        0x3AB   => array(0x3CB),
        0x3B0   => array(0x3C5, 0x308, 0x301),
        0x3C2   => array(0x3C3),
        0x3D0   => array(0x3B2),
        0x3D1   => array(0x3B8),
        0x3D2   => array(0x3C5),
        0x3D3   => array(0x3CD),
        0x3D4   => array(0x3CB),
        0x3D5   => array(0x3C6),
        0x3D6   => array(0x3C0),
        0x3D8   => array(0x3D9),
        0x3DA   => array(0x3DB),
        0x3DC   => array(0x3DD),
        0x3DE   => array(0x3DF),
        0x3E0   => array(0x3E1),
        0x3E2   => array(0x3E3),
        0x3E4   => array(0x3E5),
        0x3E6   => array(0x3E7),
        0x3E8   => array(0x3E9),
        0x3EA   => array(0x3EB),
        0x3EC   => array(0x3ED),
        0x3EE   => array(0x3EF),
        0x3F0   => array(0x3BA),
        0x3F1   => array(0x3C1),
        0x3F2   => array(0x3C3),
        0x3F4   => array(0x3B8),
        0x3F5   => array(0x3B5),
        0x400   => array(0x450),
        0x401   => array(0x451),
        0x402   => array(0x452),
        0x403   => array(0x453),
        0x404   => array(0x454),
        0x405   => array(0x455),
        0x406   => array(0x456),
        0x407   => array(0x457),
        0x408   => array(0x458),
        0x409   => array(0x459),
        0x40A   => array(0x45A),
        0x40B   => array(0x45B),
        0x40C   => array(0x45C),
        0x40D   => array(0x45D),
        0x40E   => array(0x45E),
        0x40F   => array(0x45F),
        0x410   => array(0x430),
        0x411   => array(0x431),
        0x412   => array(0x432),
        0x413   => array(0x433),
        0x414   => array(0x434),
        0x415   => array(0x435),
        0x416   => array(0x436),
        0x417   => array(0x437),
        0x418   => array(0x438),
        0x419   => array(0x439),
        0x41A   => array(0x43A),
        0x41B   => array(0x43B),
        0x41C   => array(0x43C),
        0x41D   => array(0x43D),
        0x41E   => array(0x43E),
        0x41F   => array(0x43F),
        0x420   => array(0x440),
        0x421   => array(0x441),
        0x422   => array(0x442),
        0x423   => array(0x443),
        0x424   => array(0x444),
        0x425   => array(0x445),
        0x426   => array(0x446),
        0x427   => array(0x447),
        0x428   => array(0x448),
        0x429   => array(0x449),
        0x42A   => array(0x44A),
        0x42B   => array(0x44B),
        0x42C   => array(0x44C),
        0x42D   => array(0x44D),
        0x42E   => array(0x44E),
        0x42F   => array(0x44F),
        0x460   => array(0x461),
        0x462   => array(0x463),
        0x464   => array(0x465),
        0x466   => array(0x467),
        0x468   => array(0x469),
        0x46A   => array(0x46B),
        0x46C   => array(0x46D),
        0x46E   => array(0x46F),
        0x470   => array(0x471),
        0x472   => array(0x473),
        0x474   => array(0x475),
        0x476   => array(0x477),
        0x478   => array(0x479),
        0x47A   => array(0x47B),
        0x47C   => array(0x47D),
        0x47E   => array(0x47F),
        0x480   => array(0x481),
        0x48A   => array(0x48B),
        0x48C   => array(0x48D),
        0x48E   => array(0x48F),
        0x490   => array(0x491),
        0x492   => array(0x493),
        0x494   => array(0x495),
        0x496   => array(0x497),
        0x498   => array(0x499),
        0x49A   => array(0x49B),
        0x49C   => array(0x49D),
        0x49E   => array(0x49F),
        0x4A0   => array(0x4A1),
        0x4A2   => array(0x4A3),
        0x4A4   => array(0x4A5),
        0x4A6   => array(0x4A7),
        0x4A8   => array(0x4A9),
        0x4AA   => array(0x4AB),
        0x4AC   => array(0x4AD),
        0x4AE   => array(0x4AF),
        0x4B0   => array(0x4B1),
        0x4B2   => array(0x4B3),
        0x4B4   => array(0x4B5),
        0x4B6   => array(0x4B7),
        0x4B8   => array(0x4B9),
        0x4BA   => array(0x4BB),
        0x4BC   => array(0x4BD),
        0x4BE   => array(0x4BF),
        0x4C1   => array(0x4C2),
        0x4C3   => array(0x4C4),
        0x4C5   => array(0x4C6),
        0x4C7   => array(0x4C8),
        0x4C9   => array(0x4CA),
        0x4CB   => array(0x4CC),
        0x4CD   => array(0x4CE),
        0x4D0   => array(0x4D1),
        0x4D2   => array(0x4D3),
        0x4D4   => array(0x4D5),
        0x4D6   => array(0x4D7),
        0x4D8   => array(0x4D9),
        0x4DA   => array(0x4DB),
        0x4DC   => array(0x4DD),
        0x4DE   => array(0x4DF),
        0x4E0   => array(0x4E1),
        0x4E2   => array(0x4E3),
        0x4E4   => array(0x4E5),
        0x4E6   => array(0x4E7),
        0x4E8   => array(0x4E9),
        0x4EA   => array(0x4EB),
        0x4EC   => array(0x4ED),
        0x4EE   => array(0x4EF),
        0x4F0   => array(0x4F1),
        0x4F2   => array(0x4F3),
        0x4F4   => array(0x4F5),
        0x4F8   => array(0x4F9),
        0x500   => array(0x501),
        0x502   => array(0x503),
        0x504   => array(0x505),
        0x506   => array(0x507),
        0x508   => array(0x509),
        0x50A   => array(0x50B),
        0x50C   => array(0x50D),
        0x50E   => array(0x50F),
        0x531   => array(0x561),
        0x532   => array(0x562),
        0x533   => array(0x563),
        0x534   => array(0x564),
        0x535   => array(0x565),
        0x536   => array(0x566),
        0x537   => array(0x567),
        0x538   => array(0x568),
        0x539   => array(0x569),
        0x53A   => array(0x56A),
        0x53B   => array(0x56B),
        0x53C   => array(0x56C),
        0x53D   => array(0x56D),
        0x53E   => array(0x56E),
        0x53F   => array(0x56F),
        0x540   => array(0x570),
        0x541   => array(0x571),
        0x542   => array(0x572),
        0x543   => array(0x573),
        0x544   => array(0x574),
        0x545   => array(0x575),
        0x546   => array(0x576),
        0x547   => array(0x577),
        0x548   => array(0x578),
        0x549   => array(0x579),
        0x54A   => array(0x57A),
        0x54B   => array(0x57B),
        0x54C   => array(0x57C),
        0x54D   => array(0x57D),
        0x54E   => array(0x57E),
        0x54F   => array(0x57F),
        0x550   => array(0x580),
        0x551   => array(0x581),
        0x552   => array(0x582),
        0x553   => array(0x583),
        0x554   => array(0x584),
        0x555   => array(0x585),
        0x556   => array(0x586),
        0x587   => array(0x565, 0x582),
        0x1E00  => array(0x1E01),
        0x1E02  => array(0x1E03),
        0x1E04  => array(0x1E05),
        0x1E06  => array(0x1E07),
        0x1E08  => array(0x1E09),
        0x1E0A  => array(0x1E0B),
        0x1E0C  => array(0x1E0D),
        0x1E0E  => array(0x1E0F),
        0x1E10  => array(0x1E11),
        0x1E12  => array(0x1E13),
        0x1E14  => array(0x1E15),
        0x1E16  => array(0x1E17),
        0x1E18  => array(0x1E19),
        0x1E1A  => array(0x1E1B),
        0x1E1C  => array(0x1E1D),
        0x1E1E  => array(0x1E1F),
        0x1E20  => array(0x1E21),
        0x1E22  => array(0x1E23),
        0x1E24  => array(0x1E25),
        0x1E26  => array(0x1E27),
        0x1E28  => array(0x1E29),
        0x1E2A  => array(0x1E2B),
        0x1E2C  => array(0x1E2D),
        0x1E2E  => array(0x1E2F),
        0x1E30  => array(0x1E31),
        0x1E32  => array(0x1E33),
        0x1E34  => array(0x1E35),
        0x1E36  => array(0x1E37),
        0x1E38  => array(0x1E39),
        0x1E3A  => array(0x1E3B),
        0x1E3C  => array(0x1E3D),
        0x1E3E  => array(0x1E3F),
        0x1E40  => array(0x1E41),
        0x1E42  => array(0x1E43),
        0x1E44  => array(0x1E45),
        0x1E46  => array(0x1E47),
        0x1E48  => array(0x1E49),
        0x1E4A  => array(0x1E4B),
        0x1E4C  => array(0x1E4D),
        0x1E4E  => array(0x1E4F),
        0x1E50  => array(0x1E51),
        0x1E52  => array(0x1E53),
        0x1E54  => array(0x1E55),
        0x1E56  => array(0x1E57),
        0x1E58  => array(0x1E59),
        0x1E5A  => array(0x1E5B),
        0x1E5C  => array(0x1E5D),
        0x1E5E  => array(0x1E5F),
        0x1E60  => array(0x1E61),
        0x1E62  => array(0x1E63),
        0x1E64  => array(0x1E65),
        0x1E66  => array(0x1E67),
        0x1E68  => array(0x1E69),
        0x1E6A  => array(0x1E6B),
        0x1E6C  => array(0x1E6D),
        0x1E6E  => array(0x1E6F),
        0x1E70  => array(0x1E71),
        0x1E72  => array(0x1E73),
        0x1E74  => array(0x1E75),
        0x1E76  => array(0x1E77),
        0x1E78  => array(0x1E79),
        0x1E7A  => array(0x1E7B),
        0x1E7C  => array(0x1E7D),
        0x1E7E  => array(0x1E7F),
        0x1E80  => array(0x1E81),
        0x1E82  => array(0x1E83),
        0x1E84  => array(0x1E85),
        0x1E86  => array(0x1E87),
        0x1E88  => array(0x1E89),
        0x1E8A  => array(0x1E8B),
        0x1E8C  => array(0x1E8D),
        0x1E8E  => array(0x1E8F),
        0x1E90  => array(0x1E91),
        0x1E92  => array(0x1E93),
        0x1E94  => array(0x1E95),
        0x1E96  => array(0x68, 0x331),
        0x1E97  => array(0x74, 0x308),
        0x1E98  => array(0x77, 0x30A),
        0x1E99  => array(0x79, 0x30A),
        0x1E9A  => array(0x61, 0x2BE),
        0x1E9B  => array(0x1E61),
        0x1EA0  => array(0x1EA1),
        0x1EA2  => array(0x1EA3),
        0x1EA4  => array(0x1EA5),
        0x1EA6  => array(0x1EA7),
        0x1EA8  => array(0x1EA9),
        0x1EAA  => array(0x1EAB),
        0x1EAC  => array(0x1EAD),
        0x1EAE  => array(0x1EAF),
        0x1EB0  => array(0x1EB1),
        0x1EB2  => array(0x1EB3),
        0x1EB4  => array(0x1EB5),
        0x1EB6  => array(0x1EB7),
        0x1EB8  => array(0x1EB9),
        0x1EBA  => array(0x1EBB),
        0x1EBC  => array(0x1EBD),
        0x1EBE  => array(0x1EBF),
        0x1EC0  => array(0x1EC1),
        0x1EC2  => array(0x1EC3),
        0x1EC4  => array(0x1EC5),
        0x1EC6  => array(0x1EC7),
        0x1EC8  => array(0x1EC9),
        0x1ECA  => array(0x1ECB),
        0x1ECC  => array(0x1ECD),
        0x1ECE  => array(0x1ECF),
        0x1ED0  => array(0x1ED1),
        0x1ED2  => array(0x1ED3),
        0x1ED4  => array(0x1ED5),
        0x1ED6  => array(0x1ED7),
        0x1ED8  => array(0x1ED9),
        0x1EDA  => array(0x1EDB),
        0x1EDC  => array(0x1EDD),
        0x1EDE  => array(0x1EDF),
        0x1EE0  => array(0x1EE1),
        0x1EE2  => array(0x1EE3),
        0x1EE4  => array(0x1EE5),
        0x1EE6  => array(0x1EE7),
        0x1EE8  => array(0x1EE9),
        0x1EEA  => array(0x1EEB),
        0x1EEC  => array(0x1EED),
        0x1EEE  => array(0x1EEF),
        0x1EF0  => array(0x1EF1),
        0x1EF2  => array(0x1EF3),
        0x1EF4  => array(0x1EF5),
        0x1EF6  => array(0x1EF7),
        0x1EF8  => array(0x1EF9),
        0x1F08  => array(0x1F00),
        0x1F09  => array(0x1F01),
        0x1F0A  => array(0x1F02),
        0x1F0B  => array(0x1F03),
        0x1F0C  => array(0x1F04),
        0x1F0D  => array(0x1F05),
        0x1F0E  => array(0x1F06),
        0x1F0F  => array(0x1F07),
        0x1F18  => array(0x1F10),
        0x1F19  => array(0x1F11),
        0x1F1A  => array(0x1F12),
        0x1F1B  => array(0x1F13),
        0x1F1C  => array(0x1F14),
        0x1F1D  => array(0x1F15),
        0x1F28  => array(0x1F20),
        0x1F29  => array(0x1F21),
        0x1F2A  => array(0x1F22),
        0x1F2B  => array(0x1F23),
        0x1F2C  => array(0x1F24),
        0x1F2D  => array(0x1F25),
        0x1F2E  => array(0x1F26),
        0x1F2F  => array(0x1F27),
        0x1F38  => array(0x1F30),
        0x1F39  => array(0x1F31),
        0x1F3A  => array(0x1F32),
        0x1F3B  => array(0x1F33),
        0x1F3C  => array(0x1F34),
        0x1F3D  => array(0x1F35),
        0x1F3E  => array(0x1F36),
        0x1F3F  => array(0x1F37),
        0x1F48  => array(0x1F40),
        0x1F49  => array(0x1F41),
        0x1F4A  => array(0x1F42),
        0x1F4B  => array(0x1F43),
        0x1F4C  => array(0x1F44),
        0x1F4D  => array(0x1F45),
        0x1F50  => array(0x3C5, 0x313),
        0x1F52  => array(0x3C5, 0x313, 0x300),
        0x1F54  => array(0x3C5, 0x313, 0x301),
        0x1F56  => array(0x3C5, 0x313, 0x342),
        0x1F59  => array(0x1F51),
        0x1F5B  => array(0x1F53),
        0x1F5D  => array(0x1F55),
        0x1F5F  => array(0x1F57),
        0x1F68  => array(0x1F60),
        0x1F69  => array(0x1F61),
        0x1F6A  => array(0x1F62),
        0x1F6B  => array(0x1F63),
        0x1F6C  => array(0x1F64),
        0x1F6D  => array(0x1F65),
        0x1F6E  => array(0x1F66),
        0x1F6F  => array(0x1F67),
        0x1F80  => array(0x1F00, 0x3B9),
        0x1F81  => array(0x1F01, 0x3B9),
        0x1F82  => array(0x1F02, 0x3B9),
        0x1F83  => array(0x1F03, 0x3B9),
        0x1F84  => array(0x1F04, 0x3B9),
        0x1F85  => array(0x1F05, 0x3B9),
        0x1F86  => array(0x1F06, 0x3B9),
        0x1F87  => array(0x1F07, 0x3B9),
        0x1F88  => array(0x1F00, 0x3B9),
        0x1F89  => array(0x1F01, 0x3B9),
        0x1F8A  => array(0x1F02, 0x3B9),
        0x1F8B  => array(0x1F03, 0x3B9),
        0x1F8C  => array(0x1F04, 0x3B9),
        0x1F8D  => array(0x1F05, 0x3B9),
        0x1F8E  => array(0x1F06, 0x3B9),
        0x1F8F  => array(0x1F07, 0x3B9),
        0x1F90  => array(0x1F20, 0x3B9),
        0x1F91  => array(0x1F21, 0x3B9),
        0x1F92  => array(0x1F22, 0x3B9),
        0x1F93  => array(0x1F23, 0x3B9),
        0x1F94  => array(0x1F24, 0x3B9),
        0x1F95  => array(0x1F25, 0x3B9),
        0x1F96  => array(0x1F26, 0x3B9),
        0x1F97  => array(0x1F27, 0x3B9),
        0x1F98  => array(0x1F20, 0x3B9),
        0x1F99  => array(0x1F21, 0x3B9),
        0x1F9A  => array(0x1F22, 0x3B9),
        0x1F9B  => array(0x1F23, 0x3B9),
        0x1F9C  => array(0x1F24, 0x3B9),
        0x1F9D  => array(0x1F25, 0x3B9),
        0x1F9E  => array(0x1F26, 0x3B9),
        0x1F9F  => array(0x1F27, 0x3B9),
        0x1FA0  => array(0x1F60, 0x3B9),
        0x1FA1  => array(0x1F61, 0x3B9),
        0x1FA2  => array(0x1F62, 0x3B9),
        0x1FA3  => array(0x1F63, 0x3B9),
        0x1FA4  => array(0x1F64, 0x3B9),
        0x1FA5  => array(0x1F65, 0x3B9),
        0x1FA6  => array(0x1F66, 0x3B9),
        0x1FA7  => array(0x1F67, 0x3B9),
        0x1FA8  => array(0x1F60, 0x3B9),
        0x1FA9  => array(0x1F61, 0x3B9),
        0x1FAA  => array(0x1F62, 0x3B9),
        0x1FAB  => array(0x1F63, 0x3B9),
        0x1FAC  => array(0x1F64, 0x3B9),
        0x1FAD  => array(0x1F65, 0x3B9),
        0x1FAE  => array(0x1F66, 0x3B9),
        0x1FAF  => array(0x1F67, 0x3B9),
        0x1FB2  => array(0x1F70, 0x3B9),
        0x1FB3  => array(0x3B1, 0x3B9),
        0x1FB4  => array(0x3AC, 0x3B9),
        0x1FB6  => array(0x3B1, 0x342),
        0x1FB7  => array(0x3B1, 0x342, 0x3B9),
        0x1FB8  => array(0x1FB0),
        0x1FB9  => array(0x1FB1),
        0x1FBA  => array(0x1F70),
        0x1FBB  => array(0x1F71),
        0x1FBC  => array(0x3B1, 0x3B9),
        0x1FBE  => array(0x3B9),
        0x1FC2  => array(0x1F74, 0x3B9),
        0x1FC3  => array(0x3B7, 0x3B9),
        0x1FC4  => array(0x3AE, 0x3B9),
        0x1FC6  => array(0x3B7, 0x342),
        0x1FC7  => array(0x3B7, 0x342, 0x3B9),
        0x1FC8  => array(0x1F72),
        0x1FC9  => array(0x1F73),
        0x1FCA  => array(0x1F74),
        0x1FCB  => array(0x1F75),
        0x1FCC  => array(0x3B7, 0x3B9),
        0x1FD2  => array(0x3B9, 0x308, 0x300),
        0x1FD3  => array(0x3B9, 0x308, 0x301),
        0x1FD6  => array(0x3B9, 0x342),
        0x1FD7  => array(0x3B9, 0x308, 0x342),
        0x1FD8  => array(0x1FD0),
        0x1FD9  => array(0x1FD1),
        0x1FDA  => array(0x1F76),
        0x1FDB  => array(0x1F77),
        0x1FE2  => array(0x3C5, 0x308, 0x300),
        0x1FE3  => array(0x3C5, 0x308, 0x301),
        0x1FE4  => array(0x3C1, 0x313),
        0x1FE6  => array(0x3C5, 0x342),
        0x1FE7  => array(0x3C5, 0x308, 0x342),
        0x1FE8  => array(0x1FE0),
        0x1FE9  => array(0x1FE1),
        0x1FEA  => array(0x1F7A),
        0x1FEB  => array(0x1F7B),
        0x1FEC  => array(0x1FE5),
        0x1FF2  => array(0x1F7C, 0x3B9),
        0x1FF3  => array(0x3C9, 0x3B9),
        0x1FF4  => array(0x3CE, 0x3B9),
        0x1FF6  => array(0x3C9, 0x342),
        0x1FF7  => array(0x3C9, 0x342, 0x3B9),
        0x1FF8  => array(0x1F78),
        0x1FF9  => array(0x1F79),
        0x1FFA  => array(0x1F7C),
        0x1FFB  => array(0x1F7D),
        0x1FFC  => array(0x3C9, 0x3B9),
        0x20A8  => array(0x72, 0x73),
        0x2102  => array(0x63),
        0x2103  => array(0xB0, 0x63),
        0x2107  => array(0x25B),
        0x2109  => array(0xB0, 0x66),
        0x210B  => array(0x68),
        0x210C  => array(0x68),
        0x210D  => array(0x68),
        0x2110  => array(0x69),
        0x2111  => array(0x69),
        0x2112  => array(0x6C),
        0x2115  => array(0x6E),
        0x2116  => array(0x6E, 0x6F),
        0x2119  => array(0x70),
        0x211A  => array(0x71),
        0x211B  => array(0x72),
        0x211C  => array(0x72),
        0x211D  => array(0x72),
        0x2120  => array(0x73, 0x6D),
        0x2121  => array(0x74, 0x65, 0x6C),
        0x2122  => array(0x74, 0x6D),
        0x2124  => array(0x7A),
        0x2126  => array(0x3C9),
        0x2128  => array(0x7A),
        0x212A  => array(0x6B),
        0x212B  => array(0xE5),
        0x212C  => array(0x62),
        0x212D  => array(0x63),
        0x2130  => array(0x65),
        0x2131  => array(0x66),
        0x2133  => array(0x6D),
        0x213E  => array(0x3B3),
        0x213F  => array(0x3C0),
        0x2145  => array(0x64),
        0x2160  => array(0x2170),
        0x2161  => array(0x2171),
        0x2162  => array(0x2172),
        0x2163  => array(0x2173),
        0x2164  => array(0x2174),
        0x2165  => array(0x2175),
        0x2166  => array(0x2176),
        0x2167  => array(0x2177),
        0x2168  => array(0x2178),
        0x2169  => array(0x2179),
        0x216A  => array(0x217A),
        0x216B  => array(0x217B),
        0x216C  => array(0x217C),
        0x216D  => array(0x217D),
        0x216E  => array(0x217E),
        0x216F  => array(0x217F),
        0x24B6  => array(0x24D0),
        0x24B7  => array(0x24D1),
        0x24B8  => array(0x24D2),
        0x24B9  => array(0x24D3),
        0x24BA  => array(0x24D4),
        0x24BB  => array(0x24D5),
        0x24BC  => array(0x24D6),
        0x24BD  => array(0x24D7),
        0x24BE  => array(0x24D8),
        0x24BF  => array(0x24D9),
        0x24C0  => array(0x24DA),
        0x24C1  => array(0x24DB),
        0x24C2  => array(0x24DC),
        0x24C3  => array(0x24DD),
        0x24C4  => array(0x24DE),
        0x24C5  => array(0x24DF),
        0x24C6  => array(0x24E0),
        0x24C7  => array(0x24E1),
        0x24C8  => array(0x24E2),
        0x24C9  => array(0x24E3),
        0x24CA  => array(0x24E4),
        0x24CB  => array(0x24E5),
        0x24CC  => array(0x24E6),
        0x24CD  => array(0x24E7),
        0x24CE  => array(0x24E8),
        0x24CF  => array(0x24E9),
        0x3371  => array(0x68, 0x70, 0x61),
        0x3373  => array(0x61, 0x75),
        0x3375  => array(0x6F, 0x76),
        0x3380  => array(0x70, 0x61),
        0x3381  => array(0x6E, 0x61),
        0x3382  => array(0x3BC, 0x61),
        0x3383  => array(0x6D, 0x61),
        0x3384  => array(0x6B, 0x61),
        0x3385  => array(0x6B, 0x62),
        0x3386  => array(0x6D, 0x62),
        0x3387  => array(0x67, 0x62),
        0x338A  => array(0x70, 0x66),
        0x338B  => array(0x6E, 0x66),
        0x338C  => array(0x3BC, 0x66),
        0x3390  => array(0x68, 0x7A),
        0x3391  => array(0x6B, 0x68, 0x7A),
        0x3392  => array(0x6D, 0x68, 0x7A),
        0x3393  => array(0x67, 0x68, 0x7A),
        0x3394  => array(0x74, 0x68, 0x7A),
        0x33A9  => array(0x70, 0x61),
        0x33AA  => array(0x6B, 0x70, 0x61),
        0x33AB  => array(0x6D, 0x70, 0x61),
        0x33AC  => array(0x67, 0x70, 0x61),
        0x33B4  => array(0x70, 0x76),
        0x33B5  => array(0x6E, 0x76),
        0x33B6  => array(0x3BC, 0x76),
        0x33B7  => array(0x6D, 0x76),
        0x33B8  => array(0x6B, 0x76),
        0x33B9  => array(0x6D, 0x76),
        0x33BA  => array(0x70, 0x77),
        0x33BB  => array(0x6E, 0x77),
        0x33BC  => array(0x3BC, 0x77),
        0x33BD  => array(0x6D, 0x77),
        0x33BE  => array(0x6B, 0x77),
        0x33BF  => array(0x6D, 0x77),
        0x33C0  => array(0x6B, 0x3C9),
        0x33C1  => array(0x6D, 0x3C9),
        /* 0x33C2  => array(0x61, 0x2E, 0x6D, 0x2E), */
        0x33C3  => array(0x62, 0x71),
        0x33C6  => array(0x63, 0x2215, 0x6B, 0x67),
        0x33C7  => array(0x63, 0x6F, 0x2E),
        0x33C8  => array(0x64, 0x62),
        0x33C9  => array(0x67, 0x79),
        0x33CB  => array(0x68, 0x70),
        0x33CD  => array(0x6B, 0x6B),
        0x33CE  => array(0x6B, 0x6D),
        0x33D7  => array(0x70, 0x68),
        0x33D9  => array(0x70, 0x70, 0x6D),
        0x33DA  => array(0x70, 0x72),
        0x33DC  => array(0x73, 0x76),
        0x33DD  => array(0x77, 0x62),
        0xFB00  => array(0x66, 0x66),
        0xFB01  => array(0x66, 0x69),
        0xFB02  => array(0x66, 0x6C),
        0xFB03  => array(0x66, 0x66, 0x69),
        0xFB04  => array(0x66, 0x66, 0x6C),
        0xFB05  => array(0x73, 0x74),
        0xFB06  => array(0x73, 0x74),
        0xFB13  => array(0x574, 0x576),
        0xFB14  => array(0x574, 0x565),
        0xFB15  => array(0x574, 0x56B),
        0xFB16  => array(0x57E, 0x576),
        0xFB17  => array(0x574, 0x56D),
        0xFF21  => array(0xFF41),
        0xFF22  => array(0xFF42),
        0xFF23  => array(0xFF43),
        0xFF24  => array(0xFF44),
        0xFF25  => array(0xFF45),
        0xFF26  => array(0xFF46),
        0xFF27  => array(0xFF47),
        0xFF28  => array(0xFF48),
        0xFF29  => array(0xFF49),
        0xFF2A  => array(0xFF4A),
        0xFF2B  => array(0xFF4B),
        0xFF2C  => array(0xFF4C),
        0xFF2D  => array(0xFF4D),
        0xFF2E  => array(0xFF4E),
        0xFF2F  => array(0xFF4F),
        0xFF30  => array(0xFF50),
        0xFF31  => array(0xFF51),
        0xFF32  => array(0xFF52),
        0xFF33  => array(0xFF53),
        0xFF34  => array(0xFF54),
        0xFF35  => array(0xFF55),
        0xFF36  => array(0xFF56),
        0xFF37  => array(0xFF57),
        0xFF38  => array(0xFF58),
        0xFF39  => array(0xFF59),
        0xFF3A  => array(0xFF5A),
        0x10400 => array(0x10428),
        0x10401 => array(0x10429),
        0x10402 => array(0x1042A),
        0x10403 => array(0x1042B),
        0x10404 => array(0x1042C),
        0x10405 => array(0x1042D),
        0x10406 => array(0x1042E),
        0x10407 => array(0x1042F),
        0x10408 => array(0x10430),
        0x10409 => array(0x10431),
        0x1040A => array(0x10432),
        0x1040B => array(0x10433),
        0x1040C => array(0x10434),
        0x1040D => array(0x10435),
        0x1040E => array(0x10436),
        0x1040F => array(0x10437),
        0x10410 => array(0x10438),
        0x10411 => array(0x10439),
        0x10412 => array(0x1043A),
        0x10413 => array(0x1043B),
        0x10414 => array(0x1043C),
        0x10415 => array(0x1043D),
        0x10416 => array(0x1043E),
        0x10417 => array(0x1043F),
        0x10418 => array(0x10440),
        0x10419 => array(0x10441),
        0x1041A => array(0x10442),
        0x1041B => array(0x10443),
        0x1041C => array(0x10444),
        0x1041D => array(0x10445),
        0x1041E => array(0x10446),
        0x1041F => array(0x10447),
        0x10420 => array(0x10448),
        0x10421 => array(0x10449),
        0x10422 => array(0x1044A),
        0x10423 => array(0x1044B),
        0x10424 => array(0x1044C),
        0x10425 => array(0x1044D),
        0x1D400 => array(0x61),
        0x1D401 => array(0x62),
        0x1D402 => array(0x63),
        0x1D403 => array(0x64),
        0x1D404 => array(0x65),
        0x1D405 => array(0x66),
        0x1D406 => array(0x67),
        0x1D407 => array(0x68),
        0x1D408 => array(0x69),
        0x1D409 => array(0x6A),
        0x1D40A => array(0x6B),
        0x1D40B => array(0x6C),
        0x1D40C => array(0x6D),
        0x1D40D => array(0x6E),
        0x1D40E => array(0x6F),
        0x1D40F => array(0x70),
        0x1D410 => array(0x71),
        0x1D411 => array(0x72),
        0x1D412 => array(0x73),
        0x1D413 => array(0x74),
        0x1D414 => array(0x75),
        0x1D415 => array(0x76),
        0x1D416 => array(0x77),
        0x1D417 => array(0x78),
        0x1D418 => array(0x79),
        0x1D419 => array(0x7A),
        0x1D434 => array(0x61),
        0x1D435 => array(0x62),
        0x1D436 => array(0x63),
        0x1D437 => array(0x64),
        0x1D438 => array(0x65),
        0x1D439 => array(0x66),
        0x1D43A => array(0x67),
        0x1D43B => array(0x68),
        0x1D43C => array(0x69),
        0x1D43D => array(0x6A),
        0x1D43E => array(0x6B),
        0x1D43F => array(0x6C),
        0x1D440 => array(0x6D),
        0x1D441 => array(0x6E),
        0x1D442 => array(0x6F),
        0x1D443 => array(0x70),
        0x1D444 => array(0x71),
        0x1D445 => array(0x72),
        0x1D446 => array(0x73),
        0x1D447 => array(0x74),
        0x1D448 => array(0x75),
        0x1D449 => array(0x76),
        0x1D44A => array(0x77),
        0x1D44B => array(0x78),
        0x1D44C => array(0x79),
        0x1D44D => array(0x7A),
        0x1D468 => array(0x61),
        0x1D469 => array(0x62),
        0x1D46A => array(0x63),
        0x1D46B => array(0x64),
        0x1D46C => array(0x65),
        0x1D46D => array(0x66),
        0x1D46E => array(0x67),
        0x1D46F => array(0x68),
        0x1D470 => array(0x69),
        0x1D471 => array(0x6A),
        0x1D472 => array(0x6B),
        0x1D473 => array(0x6C),
        0x1D474 => array(0x6D),
        0x1D475 => array(0x6E),
        0x1D476 => array(0x6F),
        0x1D477 => array(0x70),
        0x1D478 => array(0x71),
        0x1D479 => array(0x72),
        0x1D47A => array(0x73),
        0x1D47B => array(0x74),
        0x1D47C => array(0x75),
        0x1D47D => array(0x76),
        0x1D47E => array(0x77),
        0x1D47F => array(0x78),
        0x1D480 => array(0x79),
        0x1D481 => array(0x7A),
        0x1D49C => array(0x61),
        0x1D49E => array(0x63),
        0x1D49F => array(0x64),
        0x1D4A2 => array(0x67),
        0x1D4A5 => array(0x6A),
        0x1D4A6 => array(0x6B),
        0x1D4A9 => array(0x6E),
        0x1D4AA => array(0x6F),
        0x1D4AB => array(0x70),
        0x1D4AC => array(0x71),
        0x1D4AE => array(0x73),
        0x1D4AF => array(0x74),
        0x1D4B0 => array(0x75),
        0x1D4B1 => array(0x76),
        0x1D4B2 => array(0x77),
        0x1D4B3 => array(0x78),
        0x1D4B4 => array(0x79),
        0x1D4B5 => array(0x7A),
        0x1D4D0 => array(0x61),
        0x1D4D1 => array(0x62),
        0x1D4D2 => array(0x63),
        0x1D4D3 => array(0x64),
        0x1D4D4 => array(0x65),
        0x1D4D5 => array(0x66),
        0x1D4D6 => array(0x67),
        0x1D4D7 => array(0x68),
        0x1D4D8 => array(0x69),
        0x1D4D9 => array(0x6A),
        0x1D4DA => array(0x6B),
        0x1D4DB => array(0x6C),
        0x1D4DC => array(0x6D),
        0x1D4DD => array(0x6E),
        0x1D4DE => array(0x6F),
        0x1D4DF => array(0x70),
        0x1D4E0 => array(0x71),
        0x1D4E1 => array(0x72),
        0x1D4E2 => array(0x73),
        0x1D4E3 => array(0x74),
        0x1D4E4 => array(0x75),
        0x1D4E5 => array(0x76),
        0x1D4E6 => array(0x77),
        0x1D4E7 => array(0x78),
        0x1D4E8 => array(0x79),
        0x1D4E9 => array(0x7A),
        0x1D504 => array(0x61),
        0x1D505 => array(0x62),
        0x1D507 => array(0x64),
        0x1D508 => array(0x65),
        0x1D509 => array(0x66),
        0x1D50A => array(0x67),
        0x1D50D => array(0x6A),
        0x1D50E => array(0x6B),
        0x1D50F => array(0x6C),
        0x1D510 => array(0x6D),
        0x1D511 => array(0x6E),
        0x1D512 => array(0x6F),
        0x1D513 => array(0x70),
        0x1D514 => array(0x71),
        0x1D516 => array(0x73),
        0x1D517 => array(0x74),
        0x1D518 => array(0x75),
        0x1D519 => array(0x76),
        0x1D51A => array(0x77),
        0x1D51B => array(0x78),
        0x1D51C => array(0x79),
        0x1D538 => array(0x61),
        0x1D539 => array(0x62),
        0x1D53B => array(0x64),
        0x1D53C => array(0x65),
        0x1D53D => array(0x66),
        0x1D53E => array(0x67),
        0x1D540 => array(0x69),
        0x1D541 => array(0x6A),
        0x1D542 => array(0x6B),
        0x1D543 => array(0x6C),
        0x1D544 => array(0x6D),
        0x1D546 => array(0x6F),
        0x1D54A => array(0x73),
        0x1D54B => array(0x74),
        0x1D54C => array(0x75),
        0x1D54D => array(0x76),
        0x1D54E => array(0x77),
        0x1D54F => array(0x78),
        0x1D550 => array(0x79),
        0x1D56C => array(0x61),
        0x1D56D => array(0x62),
        0x1D56E => array(0x63),
        0x1D56F => array(0x64),
        0x1D570 => array(0x65),
        0x1D571 => array(0x66),
        0x1D572 => array(0x67),
        0x1D573 => array(0x68),
        0x1D574 => array(0x69),
        0x1D575 => array(0x6A),
        0x1D576 => array(0x6B),
        0x1D577 => array(0x6C),
        0x1D578 => array(0x6D),
        0x1D579 => array(0x6E),
        0x1D57A => array(0x6F),
        0x1D57B => array(0x70),
        0x1D57C => array(0x71),
        0x1D57D => array(0x72),
        0x1D57E => array(0x73),
        0x1D57F => array(0x74),
        0x1D580 => array(0x75),
        0x1D581 => array(0x76),
        0x1D582 => array(0x77),
        0x1D583 => array(0x78),
        0x1D584 => array(0x79),
        0x1D585 => array(0x7A),
        0x1D5A0 => array(0x61),
        0x1D5A1 => array(0x62),
        0x1D5A2 => array(0x63),
        0x1D5A3 => array(0x64),
        0x1D5A4 => array(0x65),
        0x1D5A5 => array(0x66),
        0x1D5A6 => array(0x67),
        0x1D5A7 => array(0x68),
        0x1D5A8 => array(0x69),
        0x1D5A9 => array(0x6A),
        0x1D5AA => array(0x6B),
        0x1D5AB => array(0x6C),
        0x1D5AC => array(0x6D),
        0x1D5AD => array(0x6E),
        0x1D5AE => array(0x6F),
        0x1D5AF => array(0x70),
        0x1D5B0 => array(0x71),
        0x1D5B1 => array(0x72),
        0x1D5B2 => array(0x73),
        0x1D5B3 => array(0x74),
        0x1D5B4 => array(0x75),
        0x1D5B5 => array(0x76),
        0x1D5B6 => array(0x77),
        0x1D5B7 => array(0x78),
        0x1D5B8 => array(0x79),
        0x1D5B9 => array(0x7A),
        0x1D5D4 => array(0x61),
        0x1D5D5 => array(0x62),
        0x1D5D6 => array(0x63),
        0x1D5D7 => array(0x64),
        0x1D5D8 => array(0x65),
        0x1D5D9 => array(0x66),
        0x1D5DA => array(0x67),
        0x1D5DB => array(0x68),
        0x1D5DC => array(0x69),
        0x1D5DD => array(0x6A),
        0x1D5DE => array(0x6B),
        0x1D5DF => array(0x6C),
        0x1D5E0 => array(0x6D),
        0x1D5E1 => array(0x6E),
        0x1D5E2 => array(0x6F),
        0x1D5E3 => array(0x70),
        0x1D5E4 => array(0x71),
        0x1D5E5 => array(0x72),
        0x1D5E6 => array(0x73),
        0x1D5E7 => array(0x74),
        0x1D5E8 => array(0x75),
        0x1D5E9 => array(0x76),
        0x1D5EA => array(0x77),
        0x1D5EB => array(0x78),
        0x1D5EC => array(0x79),
        0x1D5ED => array(0x7A),
        0x1D608 => array(0x61),
        0x1D609 => array(0x62),
        0x1D60A => array(0x63),
        0x1D60B => array(0x64),
        0x1D60C => array(0x65),
        0x1D60D => array(0x66),
        0x1D60E => array(0x67),
        0x1D60F => array(0x68),
        0x1D610 => array(0x69),
        0x1D611 => array(0x6A),
        0x1D612 => array(0x6B),
        0x1D613 => array(0x6C),
        0x1D614 => array(0x6D),
        0x1D615 => array(0x6E),
        0x1D616 => array(0x6F),
        0x1D617 => array(0x70),
        0x1D618 => array(0x71),
        0x1D619 => array(0x72),
        0x1D61A => array(0x73),
        0x1D61B => array(0x74),
        0x1D61C => array(0x75),
        0x1D61D => array(0x76),
        0x1D61E => array(0x77),
        0x1D61F => array(0x78),
        0x1D620 => array(0x79),
        0x1D621 => array(0x7A),
        0x1D63C => array(0x61),
        0x1D63D => array(0x62),
        0x1D63E => array(0x63),
        0x1D63F => array(0x64),
        0x1D640 => array(0x65),
        0x1D641 => array(0x66),
        0x1D642 => array(0x67),
        0x1D643 => array(0x68),
        0x1D644 => array(0x69),
        0x1D645 => array(0x6A),
        0x1D646 => array(0x6B),
        0x1D647 => array(0x6C),
        0x1D648 => array(0x6D),
        0x1D649 => array(0x6E),
        0x1D64A => array(0x6F),
        0x1D64B => array(0x70),
        0x1D64C => array(0x71),
        0x1D64D => array(0x72),
        0x1D64E => array(0x73),
        0x1D64F => array(0x74),
        0x1D650 => array(0x75),
        0x1D651 => array(0x76),
        0x1D652 => array(0x77),
        0x1D653 => array(0x78),
        0x1D654 => array(0x79),
        0x1D655 => array(0x7A),
        0x1D670 => array(0x61),
        0x1D671 => array(0x62),
        0x1D672 => array(0x63),
        0x1D673 => array(0x64),
        0x1D674 => array(0x65),
        0x1D675 => array(0x66),
        0x1D676 => array(0x67),
        0x1D677 => array(0x68),
        0x1D678 => array(0x69),
        0x1D679 => array(0x6A),
        0x1D67A => array(0x6B),
        0x1D67B => array(0x6C),
        0x1D67C => array(0x6D),
        0x1D67D => array(0x6E),
        0x1D67E => array(0x6F),
        0x1D67F => array(0x70),
        0x1D680 => array(0x71),
        0x1D681 => array(0x72),
        0x1D682 => array(0x73),
        0x1D683 => array(0x74),
        0x1D684 => array(0x75),
        0x1D685 => array(0x76),
        0x1D686 => array(0x77),
        0x1D687 => array(0x78),
        0x1D688 => array(0x79),
        0x1D689 => array(0x7A),
        0x1D6A8 => array(0x3B1),
        0x1D6A9 => array(0x3B2),
        0x1D6AA => array(0x3B3),
        0x1D6AB => array(0x3B4),
        0x1D6AC => array(0x3B5),
        0x1D6AD => array(0x3B6),
        0x1D6AE => array(0x3B7),
        0x1D6AF => array(0x3B8),
        0x1D6B0 => array(0x3B9),
        0x1D6B1 => array(0x3BA),
        0x1D6B2 => array(0x3BB),
        0x1D6B3 => array(0x3BC),
        0x1D6B4 => array(0x3BD),
        0x1D6B5 => array(0x3BE),
        0x1D6B6 => array(0x3BF),
        0x1D6B7 => array(0x3C0),
        0x1D6B8 => array(0x3C1),
        0x1D6B9 => array(0x3B8),
        0x1D6BA => array(0x3C3),
        0x1D6BB => array(0x3C4),
        0x1D6BC => array(0x3C5),
        0x1D6BD => array(0x3C6),
        0x1D6BE => array(0x3C7),
        0x1D6BF => array(0x3C8),
        0x1D6C0 => array(0x3C9),
        0x1D6D3 => array(0x3C3),
        0x1D6E2 => array(0x3B1),
        0x1D6E3 => array(0x3B2),
        0x1D6E4 => array(0x3B3),
        0x1D6E5 => array(0x3B4),
        0x1D6E6 => array(0x3B5),
        0x1D6E7 => array(0x3B6),
        0x1D6E8 => array(0x3B7),
        0x1D6E9 => array(0x3B8),
        0x1D6EA => array(0x3B9),
        0x1D6EB => array(0x3BA),
        0x1D6EC => array(0x3BB),
        0x1D6ED => array(0x3BC),
        0x1D6EE => array(0x3BD),
        0x1D6EF => array(0x3BE),
        0x1D6F0 => array(0x3BF),
        0x1D6F1 => array(0x3C0),
        0x1D6F2 => array(0x3C1),
        0x1D6F3 => array(0x3B8),
        0x1D6F4 => array(0x3C3),
        0x1D6F5 => array(0x3C4),
        0x1D6F6 => array(0x3C5),
        0x1D6F7 => array(0x3C6),
        0x1D6F8 => array(0x3C7),
        0x1D6F9 => array(0x3C8),
        0x1D6FA => array(0x3C9),
        0x1D70D => array(0x3C3),
        0x1D71C => array(0x3B1),
        0x1D71D => array(0x3B2),
        0x1D71E => array(0x3B3),
        0x1D71F => array(0x3B4),
        0x1D720 => array(0x3B5),
        0x1D721 => array(0x3B6),
        0x1D722 => array(0x3B7),
        0x1D723 => array(0x3B8),
        0x1D724 => array(0x3B9),
        0x1D725 => array(0x3BA),
        0x1D726 => array(0x3BB),
        0x1D727 => array(0x3BC),
        0x1D728 => array(0x3BD),
        0x1D729 => array(0x3BE),
        0x1D72A => array(0x3BF),
        0x1D72B => array(0x3C0),
        0x1D72C => array(0x3C1),
        0x1D72D => array(0x3B8),
        0x1D72E => array(0x3C3),
        0x1D72F => array(0x3C4),
        0x1D730 => array(0x3C5),
        0x1D731 => array(0x3C6),
        0x1D732 => array(0x3C7),
        0x1D733 => array(0x3C8),
        0x1D734 => array(0x3C9),
        0x1D747 => array(0x3C3),
        0x1D756 => array(0x3B1),
        0x1D757 => array(0x3B2),
        0x1D758 => array(0x3B3),
        0x1D759 => array(0x3B4),
        0x1D75A => array(0x3B5),
        0x1D75B => array(0x3B6),
        0x1D75C => array(0x3B7),
        0x1D75D => array(0x3B8),
        0x1D75E => array(0x3B9),
        0x1D75F => array(0x3BA),
        0x1D760 => array(0x3BB),
        0x1D761 => array(0x3BC),
        0x1D762 => array(0x3BD),
        0x1D763 => array(0x3BE),
        0x1D764 => array(0x3BF),
        0x1D765 => array(0x3C0),
        0x1D766 => array(0x3C1),
        0x1D767 => array(0x3B8),
        0x1D768 => array(0x3C3),
        0x1D769 => array(0x3C4),
        0x1D76A => array(0x3C5),
        0x1D76B => array(0x3C6),
        0x1D76C => array(0x3C7),
        0x1D76D => array(0x3C8),
        0x1D76E => array(0x3C9),
        0x1D781 => array(0x3C3),
        0x1D790 => array(0x3B1),
        0x1D791 => array(0x3B2),
        0x1D792 => array(0x3B3),
        0x1D793 => array(0x3B4),
        0x1D794 => array(0x3B5),
        0x1D795 => array(0x3B6),
        0x1D796 => array(0x3B7),
        0x1D797 => array(0x3B8),
        0x1D798 => array(0x3B9),
        0x1D799 => array(0x3BA),
        0x1D79A => array(0x3BB),
        0x1D79B => array(0x3BC),
        0x1D79C => array(0x3BD),
        0x1D79D => array(0x3BE),
        0x1D79E => array(0x3BF),
        0x1D79F => array(0x3C0),
        0x1D7A0 => array(0x3C1),
        0x1D7A1 => array(0x3B8),
        0x1D7A2 => array(0x3C3),
        0x1D7A3 => array(0x3C4),
        0x1D7A4 => array(0x3C5),
        0x1D7A5 => array(0x3C6),
        0x1D7A6 => array(0x3C7),
        0x1D7A7 => array(0x3C8),
        0x1D7A8 => array(0x3C9),
        0x1D7BB => array(0x3C3),
        0x3F9   => array(0x3C3),
        0x1D2C  => array(0x61),
        0x1D2D  => array(0xE6),
        0x1D2E  => array(0x62),
        0x1D30  => array(0x64),
        0x1D31  => array(0x65),
        0x1D32  => array(0x1DD),
        0x1D33  => array(0x67),
        0x1D34  => array(0x68),
        0x1D35  => array(0x69),
        0x1D36  => array(0x6A),
        0x1D37  => array(0x6B),
        0x1D38  => array(0x6C),
        0x1D39  => array(0x6D),
        0x1D3A  => array(0x6E),
        0x1D3C  => array(0x6F),
        0x1D3D  => array(0x223),
        0x1D3E  => array(0x70),
        0x1D3F  => array(0x72),
        0x1D40  => array(0x74),
        0x1D41  => array(0x75),
        0x1D42  => array(0x77),
        0x213B  => array(0x66, 0x61, 0x78),
        0x3250  => array(0x70, 0x74, 0x65),
        0x32CC  => array(0x68, 0x67),
        0x32CE  => array(0x65, 0x76),
        0x32CF  => array(0x6C, 0x74, 0x64),
        0x337A  => array(0x69, 0x75),
        0x33DE  => array(0x76, 0x2215, 0x6D),
        0x33DF  => array(0x61, 0x2215, 0x6D)
    );

    /**
     * Normalization Combining Classes; Code Points not listed
     * got Combining Class 0.
     *
     * @static
     * @var array
     * @access private
     */
    private static $_np_norm_combcls = array(
        0x334   => 1,
        0x335   => 1,
        0x336   => 1,
        0x337   => 1,
        0x338   => 1,
        0x93C   => 7,
        0x9BC   => 7,
        0xA3C   => 7,
        0xABC   => 7,
        0xB3C   => 7,
        0xCBC   => 7,
        0x1037  => 7,
        0x3099  => 8,
        0x309A  => 8,
        0x94D   => 9,
        0x9CD   => 9,
        0xA4D   => 9,
        0xACD   => 9,
        0xB4D   => 9,
        0xBCD   => 9,
        0xC4D   => 9,
        0xCCD   => 9,
        0xD4D   => 9,
        0xDCA   => 9,
        0xE3A   => 9,
        0xF84   => 9,
        0x1039  => 9,
        0x1714  => 9,
        0x1734  => 9,
        0x17D2  => 9,
        0x5B0   => 10,
        0x5B1   => 11,
        0x5B2   => 12,
        0x5B3   => 13,
        0x5B4   => 14,
        0x5B5   => 15,
        0x5B6   => 16,
        0x5B7   => 17,
        0x5B8   => 18,
        0x5B9   => 19,
        0x5BB   => 20,
        0x5Bc   => 21,
        0x5BD   => 22,
        0x5BF   => 23,
        0x5C1   => 24,
        0x5C2   => 25,
        0xFB1E  => 26,
        0x64B   => 27,
        0x64C   => 28,
        0x64D   => 29,
        0x64E   => 30,
        0x64F   => 31,
        0x650   => 32,
        0x651   => 33,
        0x652   => 34,
        0x670   => 35,
        0x711   => 36,
        0xC55   => 84,
        0xC56   => 91,
        0xE38   => 103,
        0xE39   => 103,
        0xE48   => 107,
        0xE49   => 107,
        0xE4A   => 107,
        0xE4B   => 107,
        0xEB8   => 118,
        0xEB9   => 118,
        0xEC8   => 122,
        0xEC9   => 122,
        0xECA   => 122,
        0xECB   => 122,
        0xF71   => 129,
        0xF72   => 130,
        0xF7A   => 130,
        0xF7B   => 130,
        0xF7C   => 130,
        0xF7D   => 130,
        0xF80   => 130,
        0xF74   => 132,
        0x321   => 202,
        0x322   => 202,
        0x327   => 202,
        0x328   => 202,
        0x31B   => 216,
        0xF39   => 216,
        0x1D165 => 216,
        0x1D166 => 216,
        0x1D16E => 216,
        0x1D16F => 216,
        0x1D170 => 216,
        0x1D171 => 216,
        0x1D172 => 216,
        0x302A  => 218,
        0x316   => 220,
        0x317   => 220,
        0x318   => 220,
        0x319   => 220,
        0x31C   => 220,
        0x31D   => 220,
        0x31E   => 220,
        0x31F   => 220,
        0x320   => 220,
        0x323   => 220,
        0x324   => 220,
        0x325   => 220,
        0x326   => 220,
        0x329   => 220,
        0x32A   => 220,
        0x32B   => 220,
        0x32C   => 220,
        0x32D   => 220,
        0x32E   => 220,
        0x32F   => 220,
        0x330   => 220,
        0x331   => 220,
        0x332   => 220,
        0x333   => 220,
        0x339   => 220,
        0x33A   => 220,
        0x33B   => 220,
        0x33C   => 220,
        0x347   => 220,
        0x348   => 220,
        0x349   => 220,
        0x34D   => 220,
        0x34E   => 220,
        0x353   => 220,
        0x354   => 220,
        0x355   => 220,
        0x356   => 220,
        0x591   => 220,
        0x596   => 220,
        0x59B   => 220,
        0x5A3   => 220,
        0x5A4   => 220,
        0x5A5   => 220,
        0x5A6   => 220,
        0x5A7   => 220,
        0x5AA   => 220,
        0x655   => 220,
        0x656   => 220,
        0x6E3   => 220,
        0x6EA   => 220,
        0x6ED   => 220,
        0x731   => 220,
        0x734   => 220,
        0x737   => 220,
        0x738   => 220,
        0x739   => 220,
        0x73B   => 220,
        0x73C   => 220,
        0x73E   => 220,
        0x742   => 220,
        0x744   => 220,
        0x746   => 220,
        0x748   => 220,
        0x952   => 220,
        0xF18   => 220,
        0xF19   => 220,
        0xF35   => 220,
        0xF37   => 220,
        0xFC6   => 220,
        0x193B  => 220,
        0x20E8  => 220,
        0x1D17B => 220,
        0x1D17C => 220,
        0x1D17D => 220,
        0x1D17E => 220,
        0x1D17F => 220,
        0x1D180 => 220,
        0x1D181 => 220,
        0x1D182 => 220,
        0x1D18A => 220,
        0x1D18B => 220,
        0x59A   => 222,
        0x5AD   => 222,
        0x1929  => 222,
        0x302D  => 222,
        0x302E  => 224,
        0x302F  => 224,
        0x1D16D => 226,
        0x5AE   => 228,
        0x18A9  => 228,
        0x302B  => 228,
        0x300   => 230,
        0x301   => 230,
        0x302   => 230,
        0x303   => 230,
        0x304   => 230,
        0x305   => 230,
        0x306   => 230,
        0x307   => 230,
        0x308   => 230,
        0x309   => 230,
        0x30A   => 230,
        0x30B   => 230,
        0x30C   => 230,
        0x30D   => 230,
        0x30E   => 230,
        0x30F   => 230,
        0x310   => 230,
        0x311   => 230,
        0x312   => 230,
        0x313   => 230,
        0x314   => 230,
        0x33D   => 230,
        0x33E   => 230,
        0x33F   => 230,
        0x340   => 230,
        0x341   => 230,
        0x342   => 230,
        0x343   => 230,
        0x344   => 230,
        0x346   => 230,
        0x34A   => 230,
        0x34B   => 230,
        0x34C   => 230,
        0x350   => 230,
        0x351   => 230,
        0x352   => 230,
        0x357   => 230,
        0x363   => 230,
        0x364   => 230,
        0x365   => 230,
        0x366   => 230,
        0x367   => 230,
        0x368   => 230,
        0x369   => 230,
        0x36A   => 230,
        0x36B   => 230,
        0x36C   => 230,
        0x36D   => 230,
        0x36E   => 230,
        0x36F   => 230,
        0x483   => 230,
        0x484   => 230,
        0x485   => 230,
        0x486   => 230,
        0x592   => 230,
        0x593   => 230,
        0x594   => 230,
        0x595   => 230,
        0x597   => 230,
        0x598   => 230,
        0x599   => 230,
        0x59C   => 230,
        0x59D   => 230,
        0x59E   => 230,
        0x59F   => 230,
        0x5A0   => 230,
        0x5A1   => 230,
        0x5A8   => 230,
        0x5A9   => 230,
        0x5AB   => 230,
        0x5AC   => 230,
        0x5AF   => 230,
        0x5C4   => 230,
        0x610   => 230,
        0x611   => 230,
        0x612   => 230,
        0x613   => 230,
        0x614   => 230,
        0x615   => 230,
        0x653   => 230,
        0x654   => 230,
        0x657   => 230,
        0x658   => 230,
        0x6D6   => 230,
        0x6D7   => 230,
        0x6D8   => 230,
        0x6D9   => 230,
        0x6DA   => 230,
        0x6DB   => 230,
        0x6DC   => 230,
        0x6DF   => 230,
        0x6E0   => 230,
        0x6E1   => 230,
        0x6E2   => 230,
        0x6E4   => 230,
        0x6E7   => 230,
        0x6E8   => 230,
        0x6EB   => 230,
        0x6EC   => 230,
        0x730   => 230,
        0x732   => 230,
        0x733   => 230,
        0x735   => 230,
        0x736   => 230,
        0x73A   => 230,
        0x73D   => 230,
        0x73F   => 230,
        0x740   => 230,
        0x741   => 230,
        0x743   => 230,
        0x745   => 230,
        0x747   => 230,
        0x749   => 230,
        0x74A   => 230,
        0x951   => 230,
        0x953   => 230,
        0x954   => 230,
        0xF82   => 230,
        0xF83   => 230,
        0xF86   => 230,
        0xF87   => 230,
        0x170D  => 230,
        0x193A  => 230,
        0x20D0  => 230,
        0x20D1  => 230,
        0x20D4  => 230,
        0x20D5  => 230,
        0x20D6  => 230,
        0x20D7  => 230,
        0x20DB  => 230,
        0x20DC  => 230,
        0x20E1  => 230,
        0x20E7  => 230,
        0x20E9  => 230,
        0xFE20  => 230,
        0xFE21  => 230,
        0xFE22  => 230,
        0xFE23  => 230,
        0x1D185 => 230,
        0x1D186 => 230,
        0x1D187 => 230,
        0x1D189 => 230,
        0x1D188 => 230,
        0x1D1AA => 230,
        0x1D1AB => 230,
        0x1D1AC => 230,
        0x1D1AD => 230,
        0x315   => 232,
        0x31A   => 232,
        0x302C  => 232,
        0x35F   => 233,
        0x362   => 233,
        0x35D   => 234,
        0x35E   => 234,
        0x360   => 234,
        0x361   => 234,
        0x345   => 240
    );
    // }}}

    // {{{ properties
    /**
     * @var string
     * @access private
     */
    private $_punycode_prefix = 'xn--';

    /**
     * @access private
     */
    private $_invalid_ucs = 0x80000000;

    /**
     * @access private
     */
    private $_max_ucs = 0x10FFFF;

    /**
     * @var int
     * @access private
     */
    private $_base = 36;

    /**
     * @var int
     * @access private
     */
    private $_tmin = 1;

    /**
     * @var int
     * @access private
     */
    private $_tmax = 26;

    /**
     * @var int
     * @access private
     */
    private $_skew = 38;

    /**
     * @var int
     * @access private
     */
    private $_damp = 700;

    /**
     * @var int
     * @access private
     */
    private $_initial_bias = 72;

    /**
     * @var int
     * @access private
     */
    private $_initial_n = 0x80;

    /**
     * @var int
     * @access private
     */
    private $_slast;

    /**
     * @access private
     */
    private $_sbase = 0xAC00;

    /**
     * @access private
     */
    private $_lbase = 0x1100;

    /**
     * @access private
     */
    private $_vbase = 0x1161;

    /**
     * @access private
     */
    private $_tbase = 0x11a7;

    /**
     * @var int
     * @access private
     */
    private $_lcount = 19;

    /**
     * @var int
     * @access private
     */
    private $_vcount = 21;

    /**
     * @var int
     * @access private
     */
    private $_tcount = 28;

    /**
     * vcount * tcount
     *
     * @var int
     * @access private
     */
    private $_ncount = 588;

    /**
     * lcount * tcount * vcount
     *
     * @var int
     * @access private
     */
    private $_scount = 11172;

    /**
     * Default encoding for encode()'s input and decode()'s output is UTF-8;
     * Other possible encodings are ucs4_string and ucs4_array
     * See {@link setParams()} for how to select these
     *
     * @var bool
     * @access private
     */
    private $_api_encoding = 'utf8';

    /**
     * Overlong UTF-8 encodings are forbidden
     *
     * @var bool
     * @access private
     */
    private $_allow_overlong = false;

    /**
     * Behave strict or not
     *
     * @var bool
     * @access private
     */
    private $_strict_mode = false;

    /**
     * IDNA-version to use
     *
     * Values are "2003" and "2008".
     * Defaults to "2003", since that was the original version and for
     * compatibility with previous versions of this library.
     * If you need to encode "new" characters like the German "Eszett",
     * please switch to 2008 first before encoding.
     *
     * @var bool
     * @access private
     */
    private $_version = '2003';

    /**
     * Cached value indicating whether or not mbstring function overloading is
     * on for strlen
     *
     * This is cached for optimal performance.
     *
     * @var boolean
     * @see Net_IDNA2::_byteLength()
     */
    private static $_mb_string_overload = null;
    // }}}


    // {{{ constructor
    /**
     * Constructor
     *
     * @param array $options Options to initialise the object with
     *
     * @access public
     * @see    setParams()
     */
    public function __construct($options = null)
    {
        $this->_slast = $this->_sbase + $this->_lcount * $this->_vcount * $this->_tcount;

        if (is_array($options)) {
            $this->setParams($options);
        }

        // populate mbstring overloading cache if not set
        if (self::$_mb_string_overload === null) {
            self::$_mb_string_overload = (extension_loaded('mbstring')
                && (ini_get('mbstring.func_overload') & 0x02) === 0x02);
        }
    }
    // }}}


    /**
     * Sets a new option value. Available options and values:
     *
     * [utf8 -     Use either UTF-8 or ISO-8859-1 as input (true for UTF-8, false
     *             otherwise); The output is always UTF-8]
     * [overlong - Unicode does not allow unnecessarily long encodings of chars,
     *             to allow this, set this parameter to true, else to false;
     *             default is false.]
     * [strict -   true: strict mode, good for registration purposes - Causes errors
     *             on failures; false: loose mode, ideal for "wildlife" applications
     *             by silently ignoring errors and returning the original input instead]
     *
     * @param mixed  $option Parameter to set (string: single parameter; array of Parameter => Value pairs)
     * @param string $value  Value to use (if parameter 1 is a string)
     *
     * @return boolean       true on success, false otherwise
     * @access public
     */
    public function setParams($option, $value = false)
    {
        if (!is_array($option)) {
            $option = array($option => $value);
        }

        foreach ($option as $k => $v) {
            switch ($k) {
            case 'encoding':
                switch ($v) {
                case 'utf8':
                case 'ucs4_string':
                case 'ucs4_array':
                    $this->_api_encoding = $v;
                    break;

                default:
                    throw new InvalidArgumentException('Set Parameter: Unknown parameter '.$v.' for option '.$k);
                }

                break;

            case 'overlong':
                $this->_allow_overlong = ($v) ? true : false;
                break;

            case 'strict':
                $this->_strict_mode = ($v) ? true : false;
                break;

            case 'version':
                if (in_array($v, array('2003', '2008'))) {
                    $this->_version = $v;
                } else {
                    throw new InvalidArgumentException('Set Parameter: Invalid parameter '.$v.' for option '.$k);
                }
                break;

            default:
                return false;
            }
        }

        return true;
    }

    /**
     * Encode a given UTF-8 domain name.
     *
     * @param string $decoded           Domain name (UTF-8 or UCS-4)
     * @param string $one_time_encoding Desired input encoding, see {@link set_parameter}
     *                                  If not given will use default-encoding
     *
     * @return string Encoded Domain name (ACE string)
     * @return mixed  processed string
     * @throws Exception
     * @access public
     */
    public function encode($decoded, $one_time_encoding = false)
    {
        // Forcing conversion of input to UCS4 array
        // If one time encoding is given, use this, else the objects property
        switch (($one_time_encoding) ? $one_time_encoding : $this->_api_encoding) {
        case 'utf8':
            $decoded = $this->_utf8_to_ucs4($decoded);
            break;
        case 'ucs4_string':
            $decoded = $this->_ucs4_string_to_ucs4($decoded);
        case 'ucs4_array': // No break; before this line. Catch case, but do nothing
            break;
        default:
            throw new InvalidArgumentException('Unsupported input format');
        }

        // No input, no output, what else did you expect?
        if (empty($decoded)) return '';

        // Anchors for iteration
        $last_begin = 0;
        // Output string
        $output = '';

        foreach ($decoded as $k => $v) {
            // Make sure to use just the plain dot
            switch($v) {
            case 0x3002:
            case 0xFF0E:
            case 0xFF61:
                $decoded[$k] = 0x2E;
                // It's right, no break here
                // The codepoints above have to be converted to dots anyway

            // Stumbling across an anchoring character
            case 0x2E:
            case 0x2F:
            case 0x3A:
            case 0x3F:
            case 0x40:
                // Neither email addresses nor URLs allowed in strict mode
                if ($this->_strict_mode) {
                    throw new InvalidArgumentException('Neither email addresses nor URLs are allowed in strict mode.');
                }
                // Skip first char
                if ($k) {
                    $encoded = '';
                    $encoded = $this->_encode(array_slice($decoded, $last_begin, (($k)-$last_begin)));
                    if ($encoded) {
                        $output .= $encoded;
                    } else {
                        $output .= $this->_ucs4_to_utf8(array_slice($decoded, $last_begin, (($k)-$last_begin)));
                    }
                    $output .= chr($decoded[$k]);
                }
                $last_begin = $k + 1;
            }
        }
        // Catch the rest of the string
        if ($last_begin) {
            $inp_len = sizeof($decoded);
            $encoded = '';
            $encoded = $this->_encode(array_slice($decoded, $last_begin, (($inp_len)-$last_begin)));
            if ($encoded) {
                $output .= $encoded;
            } else {
                $output .= $this->_ucs4_to_utf8(array_slice($decoded, $last_begin, (($inp_len)-$last_begin)));
            }
            return $output;
        }

        if ($output = $this->_encode($decoded)) {
            return $output;
        }

        return $this->_ucs4_to_utf8($decoded);
    }

    /**
     * Decode a given ACE domain name.
     *
     * @param string $input             Domain name (ACE string)
     * @param string $one_time_encoding Desired output encoding, see {@link set_parameter}
     *
     * @return string                   Decoded Domain name (UTF-8 or UCS-4)
     * @throws Exception
     * @access public
     */
    public function decode($input, $one_time_encoding = false)
    {
        // Optionally set
        if ($one_time_encoding) {
            switch ($one_time_encoding) {
            case 'utf8':
            case 'ucs4_string':
            case 'ucs4_array':
                break;
            default:
                throw new InvalidArgumentException('Unknown encoding '.$one_time_encoding);
            }
        }
        // Make sure to drop any newline characters around
        $input = trim($input);

        // Negotiate input and try to determine, whether it is a plain string,
        // an email address or something like a complete URL
        if (strpos($input, '@')) { // Maybe it is an email address
            // No no in strict mode
            if ($this->_strict_mode) {
                throw new InvalidArgumentException('Only simple domain name parts can be handled in strict mode');
            }
            list($email_pref, $input) = explode('@', $input, 2);
            $arr = explode('.', $input);
            foreach ($arr as $k => $v) {
                $conv = $this->_decode($v);
                if ($conv) $arr[$k] = $conv;
            }
            $return = $email_pref . '@' . join('.', $arr);
        } elseif (preg_match('![:\./]!', $input)) { // Or a complete domain name (with or without paths / parameters)
            // No no in strict mode
            if ($this->_strict_mode) {
                throw new InvalidArgumentException('Only simple domain name parts can be handled in strict mode');
            }

            $parsed = parse_url($input);
            if (isset($parsed['host'])) {
                $arr = explode('.', $parsed['host']);
                foreach ($arr as $k => $v) {
                    $conv = $this->_decode($v);
                    if ($conv) $arr[$k] = $conv;
                }
                $parsed['host'] = join('.', $arr);
                if (isset($parsed['scheme'])) {
                    $parsed['scheme'] .= (strtolower($parsed['scheme']) == 'mailto') ? ':' : '://';
                }
                $return = $this->_unparse_url($parsed);
            } else { // parse_url seems to have failed, try without it
                $arr = explode('.', $input);
                foreach ($arr as $k => $v) {
                    $conv = $this->_decode($v);
                    if ($conv) $arr[$k] = $conv;
                }
                $return = join('.', $arr);
            }
        } else { // Otherwise we consider it being a pure domain name string
            $return = $this->_decode($input);
        }
        // The output is UTF-8 by default, other output formats need conversion here
        // If one time encoding is given, use this, else the objects property
        switch (($one_time_encoding) ? $one_time_encoding : $this->_api_encoding) {
        case 'utf8':
            return $return;
            break;
        case 'ucs4_string':
            return $this->_ucs4_to_ucs4_string($this->_utf8_to_ucs4($return));
            break;
        case 'ucs4_array':
            return $this->_utf8_to_ucs4($return);
            break;
        default:
            throw new InvalidArgumentException('Unsupported output format');
        }
    }


    // {{{ private
    /**
     * Opposite function to parse_url()
     *
     * Inspired by code from comments of php.net-documentation for parse_url()
     *
     * @param array $parts_arr parts (strings) as returned by parse_url()
     *
     * @return string
     * @access private
     */
    private function _unparse_url($parts_arr)
    {
        if (!empty($parts_arr['scheme'])) {
            $ret_url = $parts_arr['scheme'];
        }
        if (!empty($parts_arr['user'])) {
            $ret_url .= $parts_arr['user'];
            if (!empty($parts_arr['pass'])) {
                $ret_url .= ':' . $parts_arr['pass'];
            }
            $ret_url .= '@';
        }
        $ret_url .= $parts_arr['host'];
        if (!empty($parts_arr['port'])) {
            $ret_url .= ':' . $parts_arr['port'];
        }
        $ret_url .= $parts_arr['path'];
        if (!empty($parts_arr['query'])) {
            $ret_url .= '?' . $parts_arr['query'];
        }
        if (!empty($parts_arr['fragment'])) {
            $ret_url .= '#' . $parts_arr['fragment'];
        }
        return $ret_url;
    }

    /**
     * The actual encoding algorithm.
     *
     * @param string $decoded Decoded string which should be encoded
     *
     * @return string         Encoded string
     * @throws Exception
     * @access private
     */
    private function _encode($decoded)
    {
        // We cannot encode a domain name containing the Punycode prefix
        $extract = self::_byteLength($this->_punycode_prefix);
        $check_pref = $this->_utf8_to_ucs4($this->_punycode_prefix);
        $check_deco = array_slice($decoded, 0, $extract);

        if ($check_pref == $check_deco) {
            throw new InvalidArgumentException('This is already a punycode string');
        }

        // We will not try to encode strings consisting of basic code points only
        $encodable = false;
        foreach ($decoded as $k => $v) {
            if ($v > 0x7a) {
                $encodable = true;
                break;
            }
        }
        if (!$encodable) {
            if ($this->_strict_mode) {
                throw new InvalidArgumentException('The given string does not contain encodable chars');
            }

            return false;
        }

        // Do NAMEPREP
        $decoded = $this->_nameprep($decoded);

        $deco_len = count($decoded);

        // Empty array
        if (!$deco_len) {
            return false;
        }

        // How many chars have been consumed
        $codecount = 0;

        // Start with the prefix; copy it to output
        $encoded = $this->_punycode_prefix;

        $encoded = '';
        // Copy all basic code points to output
        for ($i = 0; $i < $deco_len; ++$i) {
            $test = $decoded[$i];
            // Will match [0-9a-zA-Z-]
            if ((0x2F < $test && $test < 0x40)
                || (0x40 < $test && $test < 0x5B)
                || (0x60 < $test && $test <= 0x7B)
                || (0x2D == $test)
            ) {
                $encoded .= chr($decoded[$i]);
                $codecount++;
            }
        }

        // All codepoints were basic ones
        if ($codecount == $deco_len) {
            return $encoded;
        }

        // Start with the prefix; copy it to output
        $encoded = $this->_punycode_prefix . $encoded;

        // If we have basic code points in output, add an hyphen to the end
        if ($codecount) {
            $encoded .= '-';
        }

        // Now find and encode all non-basic code points
        $is_first  = true;
        $cur_code  = $this->_initial_n;
        $bias      = $this->_initial_bias;
        $delta     = 0;

        while ($codecount < $deco_len) {
            // Find the smallest code point >= the current code point and
            // remember the last ouccrence of it in the input
            for ($i = 0, $next_code = $this->_max_ucs; $i < $deco_len; $i++) {
                if ($decoded[$i] >= $cur_code && $decoded[$i] <= $next_code) {
                    $next_code = $decoded[$i];
                }
            }

            $delta += ($next_code - $cur_code) * ($codecount + 1);
            $cur_code = $next_code;

            // Scan input again and encode all characters whose code point is $cur_code
            for ($i = 0; $i < $deco_len; $i++) {
                if ($decoded[$i] < $cur_code) {
                    $delta++;
                } else if ($decoded[$i] == $cur_code) {
                    for ($q = $delta, $k = $this->_base; 1; $k += $this->_base) {
                        $t = ($k <= $bias)?
                            $this->_tmin :
                            (($k >= $bias + $this->_tmax)? $this->_tmax : $k - $bias);

                        if ($q < $t) {
                            break;
                        }

                        $encoded .= $this->_encodeDigit(ceil($t + (($q - $t) % ($this->_base - $t))));
                        $q = ($q - $t) / ($this->_base - $t);
                    }

                    $encoded .= $this->_encodeDigit($q);
                    $bias = $this->_adapt($delta, $codecount + 1, $is_first);
                    $codecount++;
                    $delta = 0;
                    $is_first = false;
                }
            }

            $delta++;
            $cur_code++;
        }

        return $encoded;
    }

    /**
     * The actual decoding algorithm.
     *
     * @param string $encoded Encoded string which should be decoded
     *
     * @return string         Decoded string
     * @throws Exception
     * @access private
     */
    private function _decode($encoded)
    {
        // We do need to find the Punycode prefix
        if (!preg_match('!^' . preg_quote($this->_punycode_prefix, '!') . '!', $encoded)) {
            return false;
        }

        $encode_test = preg_replace('!^' . preg_quote($this->_punycode_prefix, '!') . '!', '', $encoded);

        // If nothing left after removing the prefix, it is hopeless
        if (!$encode_test) {
            return false;
        }

        // Find last occurrence of the delimiter
        $delim_pos = strrpos($encoded, '-');

        if ($delim_pos > self::_byteLength($this->_punycode_prefix)) {
            for ($k = self::_byteLength($this->_punycode_prefix); $k < $delim_pos; ++$k) {
                $decoded[] = ord($encoded{$k});
            }
        } else {
            $decoded = array();
        }

        $deco_len = count($decoded);
        $enco_len = self::_byteLength($encoded);

        // Wandering through the strings; init
        $is_first = true;
        $bias     = $this->_initial_bias;
        $idx      = 0;
        $char     = $this->_initial_n;

        for ($enco_idx = ($delim_pos)? ($delim_pos + 1) : 0; $enco_idx < $enco_len; ++$deco_len) {
            for ($old_idx = $idx, $w = 1, $k = $this->_base; 1 ; $k += $this->_base) {
                $digit = $this->_decodeDigit($encoded{$enco_idx++});
                $idx += $digit * $w;

                $t = ($k <= $bias) ?
                    $this->_tmin :
                    (($k >= $bias + $this->_tmax)? $this->_tmax : ($k - $bias));

                if ($digit < $t) {
                    break;
                }

                $w = (int)($w * ($this->_base - $t));
            }

            $bias      = $this->_adapt($idx - $old_idx, $deco_len + 1, $is_first);
            $is_first  = false;
            $char     += (int) ($idx / ($deco_len + 1));
            $idx      %= ($deco_len + 1);

            if ($deco_len > 0) {
                // Make room for the decoded char
                for ($i = $deco_len; $i > $idx; $i--) {
                    $decoded[$i] = $decoded[($i - 1)];
                }
            }

            $decoded[$idx++] = $char;
        }

        return $this->_ucs4_to_utf8($decoded);
    }

    /**
     * Adapt the bias according to the current code point and position.
     *
     * @param int     $delta    ...
     * @param int     $npoints  ...
     * @param boolean $is_first ...
     *
     * @return int
     * @access private
     */
    private function _adapt($delta, $npoints, $is_first)
    {
        $delta = (int) ($is_first ? ($delta / $this->_damp) : ($delta / 2));
        $delta += (int) ($delta / $npoints);

        for ($k = 0; $delta > (($this->_base - $this->_tmin) * $this->_tmax) / 2; $k += $this->_base) {
            $delta = (int) ($delta / ($this->_base - $this->_tmin));
        }

        return (int) ($k + ($this->_base - $this->_tmin + 1) * $delta / ($delta + $this->_skew));
    }

    /**
     * Encoding a certain digit.
     *
     * @param int $d One digit to encode
     *
     * @return char  Encoded digit
     * @access private
     */
    private function _encodeDigit($d)
    {
        return chr($d + 22 + 75 * ($d < 26));
    }

    /**
     * Decode a certain digit.
     *
     * @param char $cp One digit (character) to decode
     *
     * @return int     Decoded digit
     * @access private
     */
    private function _decodeDigit($cp)
    {
        $cp = ord($cp);
        return ($cp - 48 < 10)? $cp - 22 : (($cp - 65 < 26)? $cp - 65 : (($cp - 97 < 26)? $cp - 97 : $this->_base));
    }

    /**
     * Do Nameprep according to RFC3491 and RFC3454.
     *
     * @param array $input Unicode Characters
     *
     * @return string      Unicode Characters, Nameprep'd
     * @throws Exception
     * @access private
     */
    private function _nameprep($input)
    {
        $output = array();

        // Walking through the input array, performing the required steps on each of
        // the input chars and putting the result into the output array
        // While mapping required chars we apply the canonical ordering

        foreach ($input as $v) {
            // Map to nothing == skip that code point
            if (in_array($v, self::$_np_map_nothing)) {
                continue;
            }

            // Try to find prohibited input
            if (in_array($v, self::$_np_prohibit) || in_array($v, self::$_general_prohibited)) {
                throw new Net_IDNA2_Exception_Nameprep('Prohibited input U+' . sprintf('%08X', $v));
            }

            foreach (self::$_np_prohibit_ranges as $range) {
                if ($range[0] <= $v && $v <= $range[1]) {
                    throw new Net_IDNA2_Exception_Nameprep('Prohibited input U+' . sprintf('%08X', $v));
                }
            }

            // Hangul syllable decomposition
            if (0xAC00 <= $v && $v <= 0xD7AF) {
                foreach ($this->_hangulDecompose($v) as $out) {
                    $output[] = $out;
                }
            } else if (($this->_version == '2003') && isset(self::$_np_replacemaps[$v])) {
                // There's a decomposition mapping for that code point
                // Decompositions only in version 2003 (original) of IDNA
                foreach ($this->_applyCannonicalOrdering(self::$_np_replacemaps[$v]) as $out) {
                    $output[] = $out;
                }
            } else {
                $output[] = $v;
            }
        }

        // Combine code points

        $last_class   = 0;
        $last_starter = 0;
        $out_len      = count($output);

        for ($i = 0; $i < $out_len; ++$i) {
            $class = $this->_getCombiningClass($output[$i]);

            if ((!$last_class || $last_class != $class) && $class) {
                // Try to match
                $seq_len = $i - $last_starter;
                $out = $this->_combine(array_slice($output, $last_starter, $seq_len));

                // On match: Replace the last starter with the composed character and remove
                // the now redundant non-starter(s)
                if ($out) {
                    $output[$last_starter] = $out;

                    if (count($out) != $seq_len) {
                        for ($j = $i + 1; $j < $out_len; ++$j) {
                            $output[$j - 1] = $output[$j];
                        }

                        unset($output[$out_len]);
                    }

                    // Rewind the for loop by one, since there can be more possible compositions
                    $i--;
                    $out_len--;
                    $last_class = ($i == $last_starter)? 0 : $this->_getCombiningClass($output[$i - 1]);

                    continue;
                }
            }

            // The current class is 0
            if (!$class) {
                $last_starter = $i;
            }

            $last_class = $class;
        }

        return $output;
    }

    /**
     * Decomposes a Hangul syllable
     * (see http://www.unicode.org/unicode/reports/tr15/#Hangul).
     *
     * @param integer $char 32bit UCS4 code point
     *
     * @return array        Either Hangul Syllable decomposed or original 32bit
     *                      value as one value array
     * @access private
     */
    private function _hangulDecompose($char)
    {
        $sindex = $char - $this->_sbase;

        if ($sindex < 0 || $sindex >= $this->_scount) {
            return array($char);
        }

        $result   = array();
        $T        = $this->_tbase + $sindex % $this->_tcount;
        $result[] = (int)($this->_lbase +  $sindex / $this->_ncount);
        $result[] = (int)($this->_vbase + ($sindex % $this->_ncount) / $this->_tcount);

        if ($T != $this->_tbase) {
            $result[] = $T;
        }

        return $result;
    }

    /**
     * Ccomposes a Hangul syllable
     * (see http://www.unicode.org/unicode/reports/tr15/#Hangul).
     *
     * @param array $input Decomposed UCS4 sequence
     *
     * @return array       UCS4 sequence with syllables composed
     * @access private
     */
    private function _hangulCompose($input)
    {
        $inp_len = count($input);

        if (!$inp_len) {
            return array();
        }

        $result   = array();
        $last     = $input[0];
        $result[] = $last; // copy first char from input to output

        for ($i = 1; $i < $inp_len; ++$i) {
            $char = $input[$i];

            // Find out, wether two current characters from L and V
            $lindex = $last - $this->_lbase;

            if (0 <= $lindex && $lindex < $this->_lcount) {
                $vindex = $char - $this->_vbase;

                if (0 <= $vindex && $vindex < $this->_vcount) {
                    // create syllable of form LV
                    $last    = ($this->_sbase + ($lindex * $this->_vcount + $vindex) * $this->_tcount);
                    $out_off = count($result) - 1;
                    $result[$out_off] = $last; // reset last

                    // discard char
                    continue;
                }
            }

            // Find out, wether two current characters are LV and T
            $sindex = $last - $this->_sbase;

            if (0 <= $sindex && $sindex < $this->_scount && ($sindex % $this->_tcount) == 0) {
                $tindex = $char - $this->_tbase;

                if (0 <= $tindex && $tindex <= $this->_tcount) {
                    // create syllable of form LVT
                    $last += $tindex;
                    $out_off = count($result) - 1;
                    $result[$out_off] = $last; // reset last

                    // discard char
                    continue;
                }
            }

            // if neither case was true, just add the character
            $last = $char;
            $result[] = $char;
        }

        return $result;
    }

    /**
     * Returns the combining class of a certain wide char.
     *
     * @param integer $char Wide char to check (32bit integer)
     *
     * @return integer      Combining class if found, else 0
     * @access private
     */
    private function _getCombiningClass($char)
    {
        return isset(self::$_np_norm_combcls[$char])? self::$_np_norm_combcls[$char] : 0;
    }

    /**
     * Apllies the canonical ordering of a decomposed UCS4 sequence.
     *
     * @param array $input Decomposed UCS4 sequence
     *
     * @return array       Ordered USC4 sequence
     * @access private
     */
    private function _applyCannonicalOrdering($input)
    {
        $swap = true;
        $size = count($input);

        while ($swap) {
            $swap = false;
            $last = $this->_getCombiningClass($input[0]);

            for ($i = 0; $i < $size - 1; ++$i) {
                $next = $this->_getCombiningClass($input[$i + 1]);

                if ($next != 0 && $last > $next) {
                    // Move item leftward until it fits
                    for ($j = $i + 1; $j > 0; --$j) {
                        if ($this->_getCombiningClass($input[$j - 1]) <= $next) {
                            break;
                        }

                        $t = $input[$j];
                        $input[$j] = $input[$j - 1];
                        $input[$j - 1] = $t;
                        $swap = 1;
                    }

                    // Reentering the loop looking at the old character again
                    $next = $last;
                }

                $last = $next;
            }
        }

        return $input;
    }

    /**
     * Do composition of a sequence of starter and non-starter.
     *
     * @param array $input UCS4 Decomposed sequence
     *
     * @return array       Ordered USC4 sequence
     * @access private
     */
    private function _combine($input)
    {
        $inp_len = count($input);

        // Is it a Hangul syllable?
        if (1 != $inp_len) {
            $hangul = $this->_hangulCompose($input);

            // This place is probably wrong
            if (count($hangul) != $inp_len) {
                return $hangul;
            }
        }

        foreach (self::$_np_replacemaps as $np_src => $np_target) {
            if ($np_target[0] != $input[0]) {
                continue;
            }

            if (count($np_target) != $inp_len) {
                continue;
            }

            $hit = false;

            foreach ($input as $k2 => $v2) {
                if ($v2 == $np_target[$k2]) {
                    $hit = true;
                } else {
                    $hit = false;
                    break;
                }
            }

            if ($hit) {
                return $np_src;
            }
        }

        return false;
    }

    /**
     * This converts an UTF-8 encoded string to its UCS-4 (array) representation
     * By talking about UCS-4 we mean arrays of 32bit integers representing
     * each of the "chars". This is due to PHP not being able to handle strings with
     * bit depth different from 8. This applies to the reverse method _ucs4_to_utf8(), too.
     * The following UTF-8 encodings are supported:
     *
     * bytes bits  representation
     * 1        7  0xxxxxxx
     * 2       11  110xxxxx 10xxxxxx
     * 3       16  1110xxxx 10xxxxxx 10xxxxxx
     * 4       21  11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
     * 5       26  111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
     * 6       31  1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
     *
     * Each x represents a bit that can be used to store character data.
     *
     * @param string $input utf8-encoded string
     *
     * @return array        ucs4-encoded array
     * @throws Exception
     * @access private
     */
    private function _utf8_to_ucs4($input)
    {
        $output = array();
        $out_len = 0;
        $inp_len = self::_byteLength($input, '8bit');
        $mode = 'next';
        $test = 'none';
        for ($k = 0; $k < $inp_len; ++$k) {
            $v = ord($input{$k}); // Extract byte from input string

            if ($v < 128) { // We found an ASCII char - put into string as is
                $output[$out_len] = $v;
                ++$out_len;
                if ('add' == $mode) {
                    throw new UnexpectedValueException('Conversion from UTF-8 to UCS-4 failed: malformed input at byte '.$k);
                }
                continue;
            }
            if ('next' == $mode) { // Try to find the next start byte; determine the width of the Unicode char
                $start_byte = $v;
                $mode = 'add';
                $test = 'range';
                if ($v >> 5 == 6) { // &110xxxxx 10xxxxx
                    $next_byte = 0; // Tells, how many times subsequent bitmasks must rotate 6bits to the left
                    $v = ($v - 192) << 6;
                } elseif ($v >> 4 == 14) { // &1110xxxx 10xxxxxx 10xxxxxx
                    $next_byte = 1;
                    $v = ($v - 224) << 12;
                } elseif ($v >> 3 == 30) { // &11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
                    $next_byte = 2;
                    $v = ($v - 240) << 18;
                } elseif ($v >> 2 == 62) { // &111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
                    $next_byte = 3;
                    $v = ($v - 248) << 24;
                } elseif ($v >> 1 == 126) { // &1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
                    $next_byte = 4;
                    $v = ($v - 252) << 30;
                } else {
                    throw new UnexpectedValueException('This might be UTF-8, but I don\'t understand it at byte '.$k);
                }
                if ('add' == $mode) {
                    $output[$out_len] = (int) $v;
                    ++$out_len;
                    continue;
                }
            }
            if ('add' == $mode) {
                if (!$this->_allow_overlong && $test == 'range') {
                    $test = 'none';
                    if (($v < 0xA0 && $start_byte == 0xE0) || ($v < 0x90 && $start_byte == 0xF0) || ($v > 0x8F && $start_byte == 0xF4)) {
                        throw new OutOfRangeException('Bogus UTF-8 character detected (out of legal range) at byte '.$k);
                    }
                }
                if ($v >> 6 == 2) { // Bit mask must be 10xxxxxx
                    $v = ($v - 128) << ($next_byte * 6);
                    $output[($out_len - 1)] += $v;
                    --$next_byte;
                } else {
                    throw new UnexpectedValueException('Conversion from UTF-8 to UCS-4 failed: malformed input at byte '.$k);
                }
                if ($next_byte < 0) {
                    $mode = 'next';
                }
            }
        } // for
        return $output;
    }

    /**
     * Convert UCS-4 array into UTF-8 string
     *
     * @param array $input ucs4-encoded array
     *
     * @return string      utf8-encoded string
     * @throws Exception
     * @access private
     */
    private function _ucs4_to_utf8($input)
    {
        $output = '';

        foreach ($input as $v) {
            // $v = ord($v);

            if ($v < 128) {
                // 7bit are transferred literally
                $output .= chr($v);
            } else if ($v < 1 << 11) {
                // 2 bytes
                $output .= chr(192 + ($v >> 6))
                    . chr(128 + ($v & 63));
            } else if ($v < 1 << 16) {
                // 3 bytes
                $output .= chr(224 + ($v >> 12))
                    . chr(128 + (($v >> 6) & 63))
                    . chr(128 + ($v & 63));
            } else if ($v < 1 << 21) {
                // 4 bytes
                $output .= chr(240 + ($v >> 18))
                    . chr(128 + (($v >> 12) & 63))
                    . chr(128 + (($v >>  6) & 63))
                    . chr(128 + ($v & 63));
            } else if ($v < 1 << 26) {
                // 5 bytes
                $output .= chr(248 + ($v >> 24))
                    . chr(128 + (($v >> 18) & 63))
                    . chr(128 + (($v >> 12) & 63))
                    . chr(128 + (($v >>  6) & 63))
                    . chr(128 + ($v & 63));
            } else if ($v < 1 << 31) {
                // 6 bytes
                $output .= chr(252 + ($v >> 30))
                    . chr(128 + (($v >> 24) & 63))
                    . chr(128 + (($v >> 18) & 63))
                    . chr(128 + (($v >> 12) & 63))
                    . chr(128 + (($v >>  6) & 63))
                    . chr(128 + ($v & 63));
            } else {
                throw new UnexpectedValueException('Conversion from UCS-4 to UTF-8 failed: malformed input');
            }
        }

        return $output;
    }

    /**
     * Convert UCS-4 array into UCS-4 string
     *
     * @param array $input ucs4-encoded array
     *
     * @return string      ucs4-encoded string
     * @throws Exception
     * @access private
     */
    private function _ucs4_to_ucs4_string($input)
    {
        $output = '';
        // Take array values and split output to 4 bytes per value
        // The bit mask is 255, which reads &11111111
        foreach ($input as $v) {
            $output .= ($v & (255 << 24) >> 24) . ($v & (255 << 16) >> 16) . ($v & (255 << 8) >> 8) . ($v & 255);
        }
        return $output;
    }

    /**
     * Convert UCS-4 string into UCS-4 array
     *
     * @param string $input ucs4-encoded string
     *
     * @return array        ucs4-encoded array
     * @throws InvalidArgumentException
     * @access private
     */
    private function _ucs4_string_to_ucs4($input)
    {
        $output = array();

        $inp_len = self::_byteLength($input);
        // Input length must be dividable by 4
        if ($inp_len % 4) {
            throw new InvalidArgumentException('Input UCS4 string is broken');
        }

        // Empty input - return empty output
        if (!$inp_len) {
            return $output;
        }

        for ($i = 0, $out_len = -1; $i < $inp_len; ++$i) {
            // Increment output position every 4 input bytes
            if (!$i % 4) {
                $out_len++;
                $output[$out_len] = 0;
            }
            $output[$out_len] += ord($input{$i}) << (8 * (3 - ($i % 4) ) );
        }
        return $output;
    }

    /**
     * Echo hex representation of UCS4 sequence.
     *
     * @param array   $input       UCS4 sequence
     * @param boolean $include_bit Include bitmask in output
     *
     * @return void
     * @static
     * @access private
     */
    private static function _showHex($input, $include_bit = false)
    {
        foreach ($input as $k => $v) {
            echo '[', $k, '] => ', sprintf('%X', $v);

            if ($include_bit) {
                echo ' (', Net_IDNA2::_showBitmask($v), ')';
            }

            echo "\n";
        }
    }

    /**
     * Gives you a bit representation of given Byte (8 bits), Word (16 bits) or DWord (32 bits)
     * Output width is automagically determined
     *
     * @param int $octet ...
     *
     * @return string    Bitmask-representation
     * @static
     * @access private
     */
    private static function _showBitmask($octet)
    {
        if ($octet >= (1 << 16)) {
            $w = 31;
        } else if ($octet >= (1 << 8)) {
            $w = 15;
        } else {
            $w = 7;
        }

        $return = '';

        for ($i = $w; $i > -1; $i--) {
            $return .= ($octet & (1 << $i))? '1' : '0';
        }

        return $return;
    }

    /**
     * Gets the length of a string in bytes even if mbstring function
     * overloading is turned on
     *
     * @param string $string the string for which to get the length.
     *
     * @return integer the length of the string in bytes.
     *
     * @see Net_IDNA2::$_mb_string_overload
     */
    private static function _byteLength($string)
    {
        if (self::$_mb_string_overload) {
            return mb_strlen($string, '8bit');
        }
        return strlen((binary)$string);
    }

    // }}}}

    // {{{ factory
    /**
     * Attempts to return a concrete IDNA instance for either php4 or php5.
     *
     * @param array $params Set of paramaters
     *
     * @return Net_IDNA2
     * @access public
     */
    public static function getInstance($params = array())
    {
        return new Net_IDNA2($params);
    }
    // }}}

    // {{{ singleton
    /**
     * Attempts to return a concrete IDNA instance for either php4 or php5,
     * only creating a new instance if no IDNA instance with the same
     * parameters currently exists.
     *
     * @param array $params Set of parameters
     *
     * @return object Net_IDNA2
     * @access public
     */
    public static function singleton($params = array())
    {
        static $instances;
        if (!isset($instances)) {
            $instances = array();
        }

        $signature = serialize($params);
        if (!isset($instances[$signature])) {
            $instances[$signature] = Net_IDNA2::getInstance($params);
        }

        return $instances[$signature];
    }
    // }}}
}

?>
PK��Z���S66Net/IDNA2/Exception.phpnu�[���<?php
class Net_IDNA2_Exception extends Exception
{
}
PK��Z&��#rr Net/IDNA2/Exception/Nameprep.phpnu�[���<?php
require_once 'Net/IDNA2/Exception.php';

class Net_IDNA2_Exception_Nameprep extends Net_IDNA2_Exception
{
}
PK��Z����Z�Z�
Net/Sieve.phpnu�[���<?php
/**
 * This file contains the Net_Sieve class.
 *
 * PHP version 5
 *
 * +-----------------------------------------------------------------------+
 * | All rights reserved.                                                  |
 * |                                                                       |
 * | Redistribution and use in source and binary forms, with or without    |
 * | modification, are permitted provided that the following conditions    |
 * | are met:                                                              |
 * |                                                                       |
 * | o Redistributions of source code must retain the above copyright      |
 * |   notice, this list of conditions and the following disclaimer.       |
 * | o Redistributions in binary form must reproduce the above copyright   |
 * |   notice, this list of conditions and the following disclaimer in the |
 * |   documentation and/or other materials provided with the distribution.|
 * |                                                                       |
 * | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   |
 * | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     |
 * | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
 * | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  |
 * | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
 * | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      |
 * | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
 * | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
 * | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   |
 * | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
 * | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  |
 * +-----------------------------------------------------------------------+
 *
 * @category  Networking
 * @package   Net_Sieve
 * @author    Richard Heyes <richard@phpguru.org>
 * @author    Damian Fernandez Sosa <damlists@cnba.uba.ar>
 * @author    Anish Mistry <amistry@am-productions.biz>
 * @author    Jan Schneider <jan@horde.org>
 * @copyright 2002-2003 Richard Heyes
 * @copyright 2006-2008 Anish Mistry
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD
 * @link      http://pear.php.net/package/Net_Sieve
 */

require_once 'PEAR.php';
require_once 'Net/Socket.php';

/**
 * Disconnected state
 *
 * @const NET_SIEVE_STATE_DISCONNECTED
 */
define('NET_SIEVE_STATE_DISCONNECTED', 1);

/**
 * Authorisation state
 *
 * @const NET_SIEVE_STATE_AUTHORISATION
 */
define('NET_SIEVE_STATE_AUTHORISATION', 2);

/**
 * Transaction state
 *
 * @const NET_SIEVE_STATE_TRANSACTION
 */
define('NET_SIEVE_STATE_TRANSACTION', 3);


/**
 * A class for talking to the timsieved server which comes with Cyrus IMAP.
 *
 * @category  Networking
 * @package   Net_Sieve
 * @author    Richard Heyes <richard@phpguru.org>
 * @author    Damian Fernandez Sosa <damlists@cnba.uba.ar>
 * @author    Anish Mistry <amistry@am-productions.biz>
 * @author    Jan Schneider <jan@horde.org>
 * @author    Neil Munday <neil@mundayweb.com>
 * @copyright 2002-2003 Richard Heyes
 * @copyright 2006-2008 Anish Mistry
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/Net_Sieve
 * @link      http://tools.ietf.org/html/rfc5228 RFC 5228 (Sieve: An Email
 *            Filtering Language)
 * @link      http://tools.ietf.org/html/rfc5804 RFC 5804 A Protocol for
 *            Remotely Managing Sieve Scripts
 */
class Net_Sieve
{
    /**
     * The authentication methods this class supports.
     *
     * Can be overwritten if having problems with certain methods.
     *
     * @var array
     */
    var $supportedAuthMethods = array(
        'DIGEST-MD5',
        'CRAM-MD5',
        'EXTERNAL',
        'PLAIN' ,
        'LOGIN',
        'GSSAPI',
        'XOAUTH2'
    );

    /**
     * SASL authentication methods that require Auth_SASL.
     *
     * @var array
     */
    var $supportedSASLAuthMethods = array('DIGEST-MD5', 'CRAM-MD5');

    /**
     * The socket handle.
     *
     * @var resource
     */
    var $_sock;

    /**
     * Parameters and connection information.
     *
     * @var array
     */
    var $_data;

    /**
     * Current state of the connection.
     *
     * One of the NET_SIEVE_STATE_* constants.
     *
     * @var integer
     */
    var $_state;

    /**
     * PEAR object to avoid strict warnings.
     *
     * @var PEAR_Error
     */
    var $_pear;

    /**
     * Constructor error.
     *
     * @var PEAR_Error
     */
    var $_error;

    /**
     * Whether to enable debugging.
     *
     * @var boolean
     */
    var $_debug = false;

    /**
     * Debug output handler.
     *
     * This has to be a valid callback.
     *
     * @var string|array
     */
    var $_debug_handler = null;

    /**
     * Whether to pick up an already established connection.
     *
     * @var boolean
     */
    var $_bypassAuth = false;

    /**
     * Whether to use TLS if available.
     *
     * @var boolean
     */
    var $_useTLS = true;

    /**
     * Additional options for stream_context_create().
     *
     * @var array
     */
    var $_options = null;

    /**
     * Maximum number of referral loops
     *
     * @var array
     */
    var $_maxReferralCount = 15;

    /**
     * Kerberos service principal to use for GSSAPI authentication.
     *
     * @var string
     */
    var $_gssapiPrincipal = null;

    /**
     * Kerberos service cname to use for GSSAPI authentication.
     *
     * @var string
     */
    var $_gssapiCN = null;

    /**
     * Constructor.
     *
     * Sets up the object, connects to the server and logs in. Stores any
     * generated error in $this->_error, which can be retrieved using the
     * getError() method.
     *
     * @param string  $user       Login username.
     * @param string  $pass       Login password.
     * @param string  $host       Hostname of server.
     * @param string  $port       Port of server.
     * @param string  $logintype  Type of login to perform (see
     *                            $supportedAuthMethods).
     * @param string  $euser      Effective user. If authenticating as an
     *                            administrator, login as this user.
     * @param boolean $debug      Whether to enable debugging (@see setDebug()).
     * @param string  $bypassAuth Skip the authentication phase. Useful if the
     *                            socket is already open.
     * @param boolean $useTLS     Use TLS if available.
     * @param array   $options    Additional options for
     *                            stream_context_create().
     * @param mixed   $handler    A callback handler for the debug output.
     * @param string  $principal  Kerberos service principal to use
     *                            with GSSAPI authentication.
     * @param string  $cname      Kerberos service cname to use
     *                            with GSSAPI authentication.
     */
    function __construct($user = null, $pass  = null, $host = 'localhost',
        $port = 2000, $logintype = '', $euser = '',
        $debug = false, $bypassAuth = false, $useTLS = true,
        $options = null, $handler = null, $principal = null, $cname = null
    ) {
        $this->_pear = new PEAR();
        $this->_state             = NET_SIEVE_STATE_DISCONNECTED;
        $this->_data['user']      = $user;
        $this->_data['pass']      = $pass;
        $this->_data['host']      = $host;
        $this->_data['port']      = $port;
        $this->_data['logintype'] = $logintype;
        $this->_data['euser']     = $euser;
        $this->_sock              = new Net_Socket();
        $this->_bypassAuth        = $bypassAuth;
        $this->_useTLS            = $useTLS;
        $this->_options           = (array) $options;
        $this->_gssapiPrincipal   = $principal;
        $this->_gssapiCN          = $cname;

        $this->setDebug($debug, $handler);

        /* Try to include the Auth_SASL package.  If the package is not
         * available, we disable the authentication methods that depend upon
         * it. */
        if ((@include_once 'Auth/SASL.php') === false) {
            $this->_debug('Auth_SASL not present');
            $this->supportedAuthMethods = array_diff(
                $this->supportedAuthMethods,
                $this->supportedSASLAuthMethods
            );
        }

        if (strlen($user) && strlen($pass)) {
            $this->_error = $this->_handleConnectAndLogin();
        }
    }

    /**
     * Returns any error that may have been generated in the constructor.
     *
     * @return boolean|PEAR_Error  False if no error, PEAR_Error otherwise.
     */
    function getError()
    {
        return is_a($this->_error, 'PEAR_Error') ? $this->_error : false;
    }

    /**
     * Sets the debug state and handler function.
     *
     * @param boolean $debug   Whether to enable debugging.
     * @param string  $handler A custom debug handler. Must be a valid callback.
     *
     * @return void
     */
    function setDebug($debug = true, $handler = null)
    {
        $this->_debug = $debug;
        $this->_debug_handler = $handler;
    }

    /**
     * Sets the Kerberos service principal for use with GSSAPI
     * authentication.
     *
     * @param string $principal The Kerberos service principal
     *
     * @return void
     */
    function setServicePrincipal($principal)
    {
        $this->_gssapiPrincipal = $principal;
    }

    /**
     * Sets the Kerberos service CName for use with GSSAPI
     * authentication.
     *
     * @param string $cname The Kerberos service principal
     *
     * @return void
     */
    function setServiceCN($cname)
    {
        $this->_gssapiCN = $cname;
    }

    /**
     * Connects to the server and logs in.
     *
     * @return boolean  True on success, PEAR_Error on failure.
     */
    function _handleConnectAndLogin()
    {
        $res = $this->connect($this->_data['host'], $this->_data['port'], $this->_options, $this->_useTLS);
        if (is_a($res, 'PEAR_Error')) {
            return $res;
        }

        if ($this->_bypassAuth === false) {
            $res = $this->login($this->_data['user'], $this->_data['pass'], $this->_data['logintype'], $this->_data['euser'], $this->_bypassAuth);
            if (is_a($res, 'PEAR_Error')) {
                return $res;
            }
        }

        return true;
    }

    /**
     * Handles connecting to the server and checks the response validity.
     *
     * @param string  $host    Hostname of server.
     * @param string  $port    Port of server.
     * @param array   $options List of options to pass to
     *                         stream_context_create().
     * @param boolean $useTLS  Use TLS if available.
     *
     * @return boolean  True on success, PEAR_Error otherwise.
     */
    function connect($host, $port, $options = null, $useTLS = true)
    {
        $this->_data['host'] = $host;
        $this->_data['port'] = $port;
        $this->_useTLS       = $useTLS;

        if (is_array($options)) {
            $this->_options = array_merge($this->_options, $options);
        }

        if (NET_SIEVE_STATE_DISCONNECTED != $this->_state) {
            return $this->_pear->raiseError('Not currently in DISCONNECTED state', 1);
        }

        $res = $this->_sock->connect($host, $port, false, 5, $options);
        if (is_a($res, 'PEAR_Error')) {
            return $res;
        }

        if ($this->_bypassAuth) {
            $this->_state = NET_SIEVE_STATE_TRANSACTION;

            // Reset capabilities
            $this->_parseCapability('');
        } else {
            $this->_state = NET_SIEVE_STATE_AUTHORISATION;

            $res = $this->_doCmd();
            if (is_a($res, 'PEAR_Error')) {
                return $res;
            }

            // Reset capabilities (use unattended capabilities)
            $this->_parseCapability($res);
        }

        // Explicitly ask for the capabilities if needed
        if (empty($this->_capability['implementation'])) {
            $res = $this->_cmdCapability();
            if (is_a($res, 'PEAR_Error')) {
                return $this->_pear->raiseError(
                    'Failed to connect, server said: ' . $res->getMessage(), 2
                );
            }
        }

        // Check if we can enable TLS via STARTTLS.
        if ($useTLS && !empty($this->_capability['starttls'])
            && function_exists('stream_socket_enable_crypto')
        ) {
            $res = $this->_startTLS();
            if (is_a($res, 'PEAR_Error')) {
                return $res;
            }
        }

        return true;
    }

    /**
     * Disconnect from the Sieve server.
     *
     * @param boolean $sendLogoutCMD Whether to send LOGOUT command before
     *                               disconnecting.
     *
     * @return boolean  True on success, PEAR_Error otherwise.
     */
    function disconnect($sendLogoutCMD = true)
    {
        return $this->_cmdLogout($sendLogoutCMD);
    }

    /**
     * Logs into server.
     *
     * @param string  $user       Login username.
     * @param string  $pass       Login password.
     * @param string  $logintype  Type of login method to use.
     * @param string  $euser      Effective UID (perform on behalf of $euser).
     * @param boolean $bypassAuth Do not perform authentication.
     *
     * @return boolean  True on success, PEAR_Error otherwise.
     */
    function login($user, $pass, $logintype = null, $euser = '', $bypassAuth = false)
    {
        $this->_data['user']      = $user;
        $this->_data['pass']      = $pass;
        $this->_data['logintype'] = $logintype;
        $this->_data['euser']     = $euser;
        $this->_bypassAuth        = $bypassAuth;

        if (NET_SIEVE_STATE_AUTHORISATION != $this->_state) {
            return $this->_pear->raiseError('Not currently in AUTHORISATION state', 1);
        }

        if (!$bypassAuth ) {
            $res = $this->_cmdAuthenticate($user, $pass, $logintype, $euser);
            if (is_a($res, 'PEAR_Error')) {
                return $res;
            }
        }

        $this->_state = NET_SIEVE_STATE_TRANSACTION;

        return true;
    }

    /**
     * Returns an indexed array of scripts currently on the server.
     *
     * @param string $active Will be set to the name of the active script
     *
     * @return array  Indexed array of scriptnames, PEAR_Error on failure
     */
    function listScripts(&$active = null)
    {
        if (is_array($scripts = $this->_cmdListScripts())) {
            if (isset($scripts[1])) {
                $active = $scripts[1];
            }

            return $scripts[0];
        }

        return $scripts;
    }

    /**
     * Returns the active script.
     *
     * @return string  The active scriptname.
     */
    function getActive()
    {
        if (is_array($scripts = $this->_cmdListScripts())) {
            return $scripts[1];
        }
    }

    /**
     * Sets the active script.
     *
     * @param string $scriptname The name of the script to be set as active.
     *
     * @return boolean  True on success, PEAR_Error on failure.
     */
    function setActive($scriptname)
    {
        return $this->_cmdSetActive($scriptname);
    }

    /**
     * Retrieves a script.
     *
     * @param string $scriptname The name of the script to be retrieved.
     *
     * @return string  The script on success, PEAR_Error on failure.
     */
    function getScript($scriptname)
    {
        return $this->_cmdGetScript($scriptname);
    }

    /**
     * Adds a script to the server.
     *
     * @param string  $scriptname Name of the script.
     * @param string  $script     The script content.
     * @param boolean $makeactive Whether to make this the active script.
     *
     * @return boolean  True on success, PEAR_Error on failure.
     */
    function installScript($scriptname, $script, $makeactive = false)
    {
        $res = $this->_cmdPutScript($scriptname, $script);
        if (is_a($res, 'PEAR_Error')) {
            return $res;
        }

        if ($makeactive) {
            return $this->_cmdSetActive($scriptname);
        }

        return true;
    }

    /**
     * Removes a script from the server.
     *
     * @param string $scriptname Name of the script.
     *
     * @return boolean  True on success, PEAR_Error on failure.
     */
    function removeScript($scriptname)
    {
        return $this->_cmdDeleteScript($scriptname);
    }

    /**
     * Checks if the server has space to store the script by the server.
     *
     * @param string  $scriptname The name of the script to mark as active.
     * @param integer $size       The size of the script.
     *
     * @return boolean|PEAR_Error  True if there is space, PEAR_Error otherwise.
     *
     * @todo Rename to hasSpace()
     */
    function haveSpace($scriptname, $size)
    {
        if (NET_SIEVE_STATE_TRANSACTION != $this->_state) {
            return $this->_pear->raiseError('Not currently in TRANSACTION state', 1);
        }

        $res = $this->_doCmd(sprintf('HAVESPACE %s %d', $this->_escape($scriptname), $size));
        if (is_a($res, 'PEAR_Error')) {
            return $res;
        }

        return true;
    }

    /**
     * Returns the list of extensions the server supports.
     *
     * @return array  List of extensions or PEAR_Error on failure.
     */
    function getExtensions()
    {
        if (NET_SIEVE_STATE_DISCONNECTED == $this->_state) {
            return $this->_pear->raiseError('Not currently connected', 7);
        }

        return $this->_capability['extensions'];
    }

    /**
     * Returns whether the server supports an extension.
     *
     * @param string $extension The extension to check.
     *
     * @return boolean  Whether the extension is supported or PEAR_Error on
     *                  failure.
     */
    function hasExtension($extension)
    {
        if (NET_SIEVE_STATE_DISCONNECTED == $this->_state) {
            return $this->_pear->raiseError('Not currently connected', 7);
        }

        $extension = trim($this->_toUpper($extension));
        if (is_array($this->_capability['extensions'])) {
            foreach ($this->_capability['extensions'] as $ext) {
                if ($ext == $extension) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * Returns the list of authentication methods the server supports.
     *
     * @return array  List of authentication methods or PEAR_Error on failure.
     */
    function getAuthMechs()
    {
        if (NET_SIEVE_STATE_DISCONNECTED == $this->_state) {
            return $this->_pear->raiseError('Not currently connected', 7);
        }

        return $this->_capability['sasl'];
    }

    /**
     * Returns whether the server supports an authentication method.
     *
     * @param string $method The method to check.
     *
     * @return boolean  Whether the method is supported or PEAR_Error on
     *                  failure.
     */
    function hasAuthMech($method)
    {
        if (NET_SIEVE_STATE_DISCONNECTED == $this->_state) {
            return $this->_pear->raiseError('Not currently connected', 7);
        }

        $method = trim($this->_toUpper($method));

        if (is_array($this->_capability['sasl'])) {
            foreach ($this->_capability['sasl'] as $sasl) {
                if ($sasl == $method) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * Handles the authentication using any known method.
     *
     * @param string $uid        The userid to authenticate as.
     * @param string $pwd        The password to authenticate with.
     * @param string $userMethod The method to use. If empty, the class chooses
     *                           the best (strongest) available method.
     * @param string $euser      The effective uid to authenticate as.
     *
     * @return void
     */
    function _cmdAuthenticate($uid, $pwd, $userMethod = null, $euser = '')
    {
        $method = $this->_getBestAuthMethod($userMethod);
        if (is_a($method, 'PEAR_Error')) {
            return $method;
        }

        switch ($method) {
        case 'DIGEST-MD5':
            return $this->_authDigestMD5($uid, $pwd, $euser);
        case 'CRAM-MD5':
            $result = $this->_authCRAMMD5($uid, $pwd, $euser);
            break;
        case 'LOGIN':
            $result = $this->_authLOGIN($uid, $pwd, $euser);
            break;
        case 'PLAIN':
            $result = $this->_authPLAIN($uid, $pwd, $euser);
            break;
        case 'EXTERNAL':
            $result = $this->_authEXTERNAL($uid, $pwd, $euser);
            break;
        case 'GSSAPI':
            $result = $this->_authGSSAPI($pwd);
            break;
        case 'XOAUTH2':
            $result = $this->_authXOAUTH2($uid, $pwd, $euser);
            break;
        default :
            $result = $this->_pear->raiseError(
                $method . ' is not a supported authentication method'
            );
            break;
        }

        $res = $this->_doCmd();
        if (is_a($res, 'PEAR_Error')) {
            return $res;
        }

        if ($this->_pear->isError($res = $this->_cmdCapability())) {
            return $this->_pear->raiseError(
                'Failed to connect, server said: ' . $res->getMessage(), 2
            );
        }

        return $result;
    }

    /**
     * Authenticates the user using the PLAIN method.
     *
     * @param string $user  The userid to authenticate as.
     * @param string $pass  The password to authenticate with.
     * @param string $euser The effective uid to authenticate as.
     *
     * @return void
     */
    function _authPLAIN($user, $pass, $euser)
    {
        return $this->_sendCmd(
            sprintf(
                'AUTHENTICATE "PLAIN" "%s"',
                base64_encode($euser . chr(0) . $user . chr(0) . $pass)
            )
        );
    }

    /**
     * Authenticates the user using the GSSAPI method.
     *
     * @note the PHP krb5 extension is required and the service principal and cname
     *       must have been set.
     * @see  setServicePrincipal()
     *
     * @return void
     */
    function _authGSSAPI()
    {
        if (!extension_loaded('krb5')) {
            return $this->_pear->raiseError('The krb5 extension is required for GSSAPI authentication', 2);
        }

        if (!$this->_gssapiPrincipal) {
            return $this->_pear->raiseError('No Kerberos service principal set', 2);
        }

        if (!$this->_gssapiCN) {
            return $this->_pear->raiseError('No Kerberos service CName set', 2);
        }

        putenv('KRB5CCNAME=' . $this->_gssapiCN);

        try {
            $ccache = new KRB5CCache();
            $ccache->open($this->_gssapiCN);

            $gssapicontext = new GSSAPIContext();
            $gssapicontext->acquireCredentials($ccache);

            $token   = '';
            $success = $gssapicontext->initSecContext($this->_gssapiPrincipal, null, null, null, $token);
            $token   = base64_encode($token);
        }
        catch (Exception $e) {
            return $this->_pear->raiseError('GSSAPI authentication failed: ' . $e->getMessage());
        }

        $this->_sendCmd("AUTHENTICATE \"GSSAPI\" {" . strlen($token) . "+}");

        $response = $this->_doCmd($token, true);

        try {
            $challenge = base64_decode(substr($response, 1, -1));
            $gssapicontext->unwrap($challenge, $challenge);
            $gssapicontext->wrap($challenge, $challenge, true);
        }
        catch (Exception $e) {
            return $this->_pear->raiseError('GSSAPI authentication failed: ' . $e->getMessage());
        }

        $response = base64_encode($challenge);

        $this->_sendCmd("{" . strlen($response) . "+}");

        return $this->_sendCmd($response);
    }

    /**
     * Authenticates the user using the LOGIN method.
     *
     * @param string $user  The userid to authenticate as.
     * @param string $pass  The password to authenticate with.
     * @param string $euser The effective uid to authenticate as. Not used.
     *
     * @return void
     */
    function _authLOGIN($user, $pass, $euser)
    {
        $result = $this->_sendCmd('AUTHENTICATE "LOGIN"');
        if (is_a($result, 'PEAR_Error')) {
            return $result;
        }

        $result = $this->_doCmd('"' . base64_encode($user) . '"', true);
        if (is_a($result, 'PEAR_Error')) {
            return $result;
        }

        return $this->_doCmd('"' . base64_encode($pass) . '"', true);
    }

    /**
     * Authenticates the user using the CRAM-MD5 method.
     *
     * @param string $user  The userid to authenticate as.
     * @param string $pass  The password to authenticate with.
     * @param string $euser The effective uid to authenticate as. Not used.
     *
     * @return void
     */
    function _authCRAMMD5($user, $pass, $euser)
    {
        $challenge = $this->_doCmd('AUTHENTICATE "CRAM-MD5"', true);
        if (is_a($challenge, 'PEAR_Error')) {
            return $challenge;
        }

        $auth_sasl = new Auth_SASL;
        $cram      = $auth_sasl->factory('crammd5');
        $challenge = base64_decode(trim($challenge));
        $response  = $cram->getResponse($user, $pass, $challenge);

        if (is_a($response, 'PEAR_Error')) {
            return $response;
        }

        return $this->_sendStringResponse(base64_encode($response));
    }

    /**
     * Authenticates the user using the DIGEST-MD5 method.
     *
     * @param string $user  The userid to authenticate as.
     * @param string $pass  The password to authenticate with.
     * @param string $euser The effective uid to authenticate as.
     *
     * @return void
     */
    function _authDigestMD5($user, $pass, $euser)
    {
        $challenge = $this->_doCmd('AUTHENTICATE "DIGEST-MD5"', true);
        if (is_a($challenge, 'PEAR_Error')) {
            return $challenge;
        }

        $auth_sasl = new Auth_SASL;
        $digest    = $auth_sasl->factory('digestmd5');
        $challenge = base64_decode(trim($challenge));

        // @todo Really 'localhost'?
        $response = $digest->getResponse($user, $pass, $challenge, 'localhost', 'sieve', $euser);
        if (is_a($response, 'PEAR_Error')) {
            return $response;
        }

        $result = $this->_sendStringResponse(base64_encode($response));
        if (is_a($result, 'PEAR_Error')) {
            return $result;
        }

        $result = $this->_doCmd('', true);
        if (is_a($result, 'PEAR_Error')) {
            return $result;
        }

        if ($this->_toUpper(substr($result, 0, 2)) == 'OK') {
            return;
        }

        /* We don't use the protocol's third step because SIEVE doesn't allow
         * subsequent authentication, so we just silently ignore it. */
        $result = $this->_sendStringResponse('');
        if (is_a($result, 'PEAR_Error')) {
            return $result;
        }

        return $this->_doCmd();
    }

    /**
     * Authenticates the user using the EXTERNAL method.
     *
     * @param string $user  The userid to authenticate as.
     * @param string $pass  The password to authenticate with.
     * @param string $euser The effective uid to authenticate as.
     *
     * @return void
     *
     * @since 1.1.7
     */
    function _authEXTERNAL($user, $pass, $euser)
    {
        $cmd = sprintf(
            'AUTHENTICATE "EXTERNAL" "%s"',
            base64_encode(strlen($euser) ? $euser : $user)
        );

        return $this->_sendCmd($cmd);
    }

    /**
     * Authenticates the user using the XOAUTH2 method.
     *
     * @param string $user  The userid to authenticate as.
     * @param string $token The token to authenticate with.
     * @param string $euser The effective uid to authenticate as.
     *
     * @return void
     */
    function _authXOAUTH2($user, $token, $euser)
    {
        // default to $user if $euser is not set
        if (! $euser) {
            $euser = $user;
        }

        $auth = base64_encode("user=$euser\001auth=$token\001\001");
        return $this->_sendCmd("AUTHENTICATE \"XOAUTH2\" \"$auth\"");
    }

    /**
     * Removes a script from the server.
     *
     * @param string $scriptname Name of the script to delete.
     *
     * @return boolean  True on success, PEAR_Error otherwise.
     */
    function _cmdDeleteScript($scriptname)
    {
        if (NET_SIEVE_STATE_TRANSACTION != $this->_state) {
            return $this->_pear->raiseError('Not currently in AUTHORISATION state', 1);
        }

        $res = $this->_doCmd(sprintf('DELETESCRIPT %s', $this->_escape($scriptname)));
        if (is_a($res, 'PEAR_Error')) {
            return $res;
        }

        return true;
    }

    /**
     * Retrieves the contents of the named script.
     *
     * @param string $scriptname Name of the script to retrieve.
     *
     * @return string  The script if successful, PEAR_Error otherwise.
     */
    function _cmdGetScript($scriptname)
    {
        if (NET_SIEVE_STATE_TRANSACTION != $this->_state) {
            return $this->_pear->raiseError('Not currently in AUTHORISATION state', 1);
        }

        $res = $this->_doCmd(sprintf('GETSCRIPT %s', $this->_escape($scriptname)));
        if (is_a($res, 'PEAR_Error')) {
            return $res;
        }

        return preg_replace('/^{[0-9]+}\r\n/', '', $res);
    }

    /**
     * Sets the active script, i.e. the one that gets run on new mail by the
     * server.
     *
     * @param string $scriptname The name of the script to mark as active.
     *
     * @return boolean  True on success, PEAR_Error otherwise.
     */
    function _cmdSetActive($scriptname)
    {
        if (NET_SIEVE_STATE_TRANSACTION != $this->_state) {
            return $this->_pear->raiseError('Not currently in AUTHORISATION state', 1);
        }

        $res = $this->_doCmd(sprintf('SETACTIVE %s', $this->_escape($scriptname)));
        if (is_a($res, 'PEAR_Error')) {
            return $res;
        }

        return true;
    }

    /**
     * Returns the list of scripts on the server.
     *
     * @return array  An array with the list of scripts in the first element
     *                and the active script in the second element on success,
     *                PEAR_Error otherwise.
     */
    function _cmdListScripts()
    {
        if (NET_SIEVE_STATE_TRANSACTION != $this->_state) {
            return $this->_pear->raiseError('Not currently in AUTHORISATION state', 1);
        }

        $res = $this->_doCmd('LISTSCRIPTS');
        if (is_a($res, 'PEAR_Error')) {
            return $res;
        }

        $scripts = array();
        $activescript = null;
        $res = explode("\r\n", $res);
        foreach ($res as $value) {
            if (preg_match('/^"(.*)"( ACTIVE)?$/i', $value, $matches)) {
                $script_name = stripslashes($matches[1]);
                $scripts[] = $script_name;
                if (!empty($matches[2])) {
                    $activescript = $script_name;
                }
            }
        }

        return array($scripts, $activescript);
    }

    /**
     * Adds a script to the server.
     *
     * @param string $scriptname Name of the new script.
     * @param string $scriptdata The new script.
     *
     * @return boolean  True on success, PEAR_Error otherwise.
     */
    function _cmdPutScript($scriptname, $scriptdata)
    {
        if (NET_SIEVE_STATE_TRANSACTION != $this->_state) {
            return $this->_pear->raiseError('Not currently in AUTHORISATION state', 1);
        }

        $stringLength = $this->_getLineLength($scriptdata);
        $command      = sprintf(
            "PUTSCRIPT %s {%d+}\r\n%s",
            $this->_escape($scriptname),
            $stringLength,
            $scriptdata
        );

        $res = $this->_doCmd($command);
        if (is_a($res, 'PEAR_Error')) {
            return $res;
        }

        return true;
    }

    /**
     * Logs out of the server and terminates the connection.
     *
     * @param boolean $sendLogoutCMD Whether to send LOGOUT command before
     *                               disconnecting.
     *
     * @return boolean  True on success, PEAR_Error otherwise.
     */
    function _cmdLogout($sendLogoutCMD = true)
    {
        if (NET_SIEVE_STATE_DISCONNECTED == $this->_state) {
            return $this->_pear->raiseError('Not currently connected', 1);
        }

        if ($sendLogoutCMD) {
            $res = $this->_doCmd('LOGOUT');
            if (is_a($res, 'PEAR_Error')) {
                return $res;
            }
        }

        $this->_sock->disconnect();
        $this->_state = NET_SIEVE_STATE_DISCONNECTED;

        return true;
    }

    /**
     * Sends the CAPABILITY command
     *
     * @return boolean  True on success, PEAR_Error otherwise.
     */
    function _cmdCapability()
    {
        if (NET_SIEVE_STATE_DISCONNECTED == $this->_state) {
            return $this->_pear->raiseError('Not currently connected', 1);
        }
        $res = $this->_doCmd('CAPABILITY');
        if (is_a($res, 'PEAR_Error')) {
            return $res;
        }
        $this->_parseCapability($res);
        return true;
    }

    /**
     * Parses the response from the CAPABILITY command and stores the result
     * in $_capability.
     *
     * @param string $data The response from the capability command.
     *
     * @return void
     */
    function _parseCapability($data)
    {
        // Clear the cached capabilities.
        $this->_capability = array('sasl' => array(),
                                   'extensions' => array());

        $data = preg_split('/\r?\n/', $this->_toUpper($data), -1, PREG_SPLIT_NO_EMPTY);

        for ($i = 0; $i < count($data); $i++) {
            if (!preg_match('/^"([A-Z]+)"( "(.*)")?$/', $data[$i], $matches)) {
                continue;
            }
            switch ($matches[1]) {
            case 'IMPLEMENTATION':
                $this->_capability['implementation'] = $matches[3];
                break;

            case 'SASL':
                if (!empty($matches[3])) {
                    $this->_capability['sasl'] = preg_split('/\s+/', $matches[3]);
                }
                break;

            case 'SIEVE':
                if (!empty($matches[3])) {
                    $this->_capability['extensions'] = preg_split('/\s+/', $matches[3]);
                }
                break;

            case 'STARTTLS':
                $this->_capability['starttls'] = true;
                break;
            }
        }
    }

    /**
     * Sends a command to the server
     *
     * @param string $cmd The command to send.
     *
     * @return void
     */
    function _sendCmd($cmd)
    {
        $status = $this->_sock->getStatus();
        if (is_a($status, 'PEAR_Error') || $status['eof']) {
            return $this->_pear->raiseError('Failed to write to socket: connection lost');
        }
        $error = $this->_sock->write($cmd . "\r\n");
        if (is_a($error, 'PEAR_Error')) {
            return $this->_pear->raiseError(
                'Failed to write to socket: ' . $error->getMessage()
            );
        }
        $this->_debug("C: $cmd");
    }

    /**
     * Sends a string response to the server.
     *
     * @param string $str The string to send.
     *
     * @return void
     */
    function _sendStringResponse($str)
    {
        return $this->_sendCmd('{' . $this->_getLineLength($str) . "+}\r\n" . $str);
    }

    /**
     * Receives a single line from the server.
     *
     * @return string  The server response line.
     */
    function _recvLn()
    {
        $lastline = $this->_sock->gets(8192);
        if (is_a($lastline, 'PEAR_Error')) {
            return $this->_pear->raiseError(
                'Failed to read from socket: ' . $lastline->getMessage()
            );
        }

        $lastline = rtrim($lastline);
        $this->_debug("S: $lastline");

        if ($lastline === '') {
            return $this->_pear->raiseError('Failed to read from socket');
        }

        return $lastline;
    }

    /**
     * Receives a number of bytes from the server.
     *
     * @param integer $length Number of bytes to read.
     *
     * @return string The server response.
     */
    function _recvBytes($length)
    {
        $response = '';
        $response_length = 0;
        while ($response_length < $length) {
            $response .= $this->_sock->read($length - $response_length);
            $response_length = $this->_getLineLength($response);
        }
        $this->_debug('S: ' . rtrim($response));
        return $response;
    }

    /**
     * Send a command and retrieves a response from the server.
     *
     * @param string  $cmd  The command to send.
     * @param boolean $auth Whether this is an authentication command.
     *
     * @return string|PEAR_Error Reponse string if an OK response, PEAR_Error
     *                           if a NO response.
     */
    function _doCmd($cmd = '', $auth = false)
    {
        $referralCount = 0;
        while ($referralCount < $this->_maxReferralCount) {
            if (strlen($cmd)) {
                $error = $this->_sendCmd($cmd);
                if (is_a($error, 'PEAR_Error')) {
                    return $error;
                }
            }

            $response = '';
            while (true) {
                $line = $this->_recvLn();
                if (is_a($line, 'PEAR_Error')) {
                    return $line;
                }

                if (preg_match('/^(OK|NO)/i', $line, $tag)) {
                    // Check for string literal message.
                    if (preg_match('/{([0-9]+)}$/', $line, $matches)) {
                        $line = substr($line, 0, -(strlen($matches[1]) + 2))
                            . str_replace(
                                "\r\n", ' ', $this->_recvBytes($matches[1] + 2)
                            );
                    }

                    if ('OK' == $this->_toUpper($tag[1])) {
                        $response .= $line;
                        return rtrim($response);
                    }

                    return $this->_pear->raiseError(trim($response . substr($line, 2)), 3);
                }

                if (preg_match('/^BYE/i', $line)) {
                    $error = $this->disconnect(false);
                    if (is_a($error, 'PEAR_Error')) {
                        return $this->_pear->raiseError(
                            'Cannot handle BYE, the error was: '
                            . $error->getMessage(),
                            4
                        );
                    }
                    // Check for referral, then follow it.  Otherwise, carp an
                    // error.
                    if (preg_match('/^bye \(referral "(sieve:\/\/)?([^"]+)/i', $line, $matches)) {
                        // Replace the old host with the referral host
                        // preserving any protocol prefix.
                        $this->_data['host'] = preg_replace(
                            '/\w+(?!(\w|\:\/\/)).*/', $matches[2],
                            $this->_data['host']
                        );
                        $error = $this->_handleConnectAndLogin();
                        if (is_a($error, 'PEAR_Error')) {
                            return $this->_pear->raiseError(
                                'Cannot follow referral to '
                                . $this->_data['host'] . ', the error was: '
                                . $error->getMessage(),
                                5
                            );
                        }
                        break;
                    }
                    return $this->_pear->raiseError(trim($response . $line), 6);
                }

                if (preg_match('/^{([0-9]+)}/', $line, $matches)) {
                    // Matches literal string responses.
                    $line = $this->_recvBytes($matches[1] + 2);
                    if (!$auth) {
                        // Receive the pending OK only if we aren't
                        // authenticating since string responses during
                        // authentication don't need an OK.
                        $this->_recvLn();
                    }
                    return $line;
                }

                if ($auth) {
                    // String responses during authentication don't need an
                    // OK.
                    $response .= $line;
                    return rtrim($response);
                }

                $response .= $line . "\r\n";
                $referralCount++;
            }
        }

        return $this->_pear->raiseError('Max referral count (' . $referralCount . ') reached. Cyrus murder loop error?', 7);
    }

    /**
     * Returns the name of the best authentication method that the server
     * has advertised.
     *
     * @param string $userMethod Only consider this method as available.
     *
     * @return string  The name of the best supported authentication method or
     *                 a PEAR_Error object on failure.
     */
    function _getBestAuthMethod($userMethod = null)
    {
        if (!isset($this->_capability['sasl'])) {
            return $this->_pear->raiseError('This server doesn\'t support any authentication methods. SASL problem?');
        }
        if (!$this->_capability['sasl']) {
            return $this->_pear->raiseError('This server doesn\'t support any authentication methods.');
        }

        if ($userMethod) {
            if (in_array($userMethod, $this->_capability['sasl'])) {
                return $userMethod;
            }

            $msg = 'No supported authentication method found. The server supports these methods: %s, but we want to use: %s';
            return $this->_pear->raiseError(
                sprintf($msg, implode(', ', $this->_capability['sasl']), $userMethod)
            );
        }

        foreach ($this->supportedAuthMethods as $method) {
            if (in_array($method, $this->_capability['sasl'])) {
                return $method;
            }
        }

        $msg = 'No supported authentication method found. The server supports these methods: %s, but we only support: %s';
        return $this->_pear->raiseError(
            sprintf($msg, implode(', ', $this->_capability['sasl']), implode(', ', $this->supportedAuthMethods))
        );
    }

    /**
     * Starts a TLS connection.
     *
     * @return boolean  True on success, PEAR_Error on failure.
     */
    function _startTLS()
    {
        $res = $this->_doCmd('STARTTLS');
        if (is_a($res, 'PEAR_Error')) {
            return $res;
        }

        if (isset($this->_options['ssl']['crypto_method'])) {
            $crypto_method = $this->_options['ssl']['crypto_method'];
        } else {
            // There is no flag to enable all TLS methods. Net_SMTP
            // handles enabling TLS similarly.
            $crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT
                | @STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT
                | @STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
        }

        if (!stream_socket_enable_crypto($this->_sock->fp, true, $crypto_method)) {
            return $this->_pear->raiseError('Failed to establish TLS connection', 2);
        }

        $this->_debug('STARTTLS negotiation successful');

        // The server should be sending a CAPABILITY response after
        // negotiating TLS. Read it, and ignore if it doesn't.
        // Unfortunately old Cyrus versions are broken and don't send a
        // CAPABILITY response, thus we would wait here forever. Parse the
        // Cyrus version and work around this broken behavior.
        if (!preg_match('/^CYRUS TIMSIEVED V([0-9.]+)/', $this->_capability['implementation'], $matches)
            || version_compare($matches[1], '2.3.10', '>=')
        ) {
            $res = $this->_doCmd();
        }

        // Reset capabilities (use unattended capabilities)
        $this->_parseCapability(is_string($res) ? $res : '');

        // Query the server capabilities again now that we are under encryption.
        if (empty($this->_capability['implementation'])) {
            $res = $this->_cmdCapability();
            if (is_a($res, 'PEAR_Error')) {
                return $this->_pear->raiseError(
                    'Failed to connect, server said: ' . $res->getMessage(), 2
                );
            }
        }

        return true;
    }

    /**
     * Returns the length of a string.
     *
     * @param string $string A string.
     *
     * @return integer  The length of the string.
     */
    function _getLineLength($string)
    {
        if (extension_loaded('mbstring')) {
            return mb_strlen($string, '8bit');
        } else {
            return strlen($string);
        }
    }

    /**
     * Locale independant strtoupper() implementation.
     *
     * @param string $string The string to convert to lowercase.
     *
     * @return string  The lowercased string, based on ASCII encoding.
     */
    function _toUpper($string)
    {
        $language = setlocale(LC_CTYPE, 0);
        setlocale(LC_CTYPE, 'C');
        $string = strtoupper($string);
        setlocale(LC_CTYPE, $language);
        return $string;
    }

    /**
     * Converts strings into RFC's quoted-string or literal-c2s form.
     *
     * @param string $string The string to convert.
     *
     * @return string Result string.
     */
    function _escape($string)
    {
        // Some implementations don't allow UTF-8 characters in quoted-string,
        // use literal-c2s.
        if (preg_match('/[^\x01-\x09\x0B-\x0C\x0E-\x7F]/', $string)) {
            return sprintf("{%d+}\r\n%s", $this->_getLineLength($string), $string);
        }

        return '"' . addcslashes($string, '\\"') . '"';
    }

    /**
     * Write debug text to the current debug output handler.
     *
     * @param string $message Debug message text.
     *
     * @return void
     */
    function _debug($message)
    {
        if ($this->_debug) {
            if ($this->_debug_handler) {
                call_user_func_array($this->_debug_handler, array(&$this, $message));
            } else {
                echo "$message\n";
            }
        }
    }
}
PK��Zz��|����Net/SMTP.phpnu�[���<?php
/** vim: set expandtab softtabstop=4 tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | PHP Version 5 and 7                                                  |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2021 Jon Parise and Chuck Hagenbuch               |
// | All rights reserved.                                                 |
// |                                                                      |
// | Redistribution and use in source and binary forms, with or without   |
// | modification, are permitted provided that the following conditions   |
// | are met:                                                             |
// |                                                                      |
// | 1. Redistributions of source code must retain the above copyright    |
// |    notice, this list of conditions and the following disclaimer.     |
// |                                                                      |
// | 2. Redistributions in binary form must reproduce the above copyright |
// |    notice, this list of conditions and the following disclaimer in   |
// |    the documentation and/or other materials provided with the        |
// |    distribution.                                                     |
// |                                                                      |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT    |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS    |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE       |
// | COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;     |
// | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER     |
// | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT   |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN    |
// | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE      |
// | POSSIBILITY OF SUCH DAMAGE.                                          |
// +----------------------------------------------------------------------+
// | Authors: Chuck Hagenbuch <chuck@horde.org>                           |
// |          Jon Parise <jon@php.net>                                    |
// |          Damian Alejandro Fernandez Sosa <damlists@cnba.uba.ar>      |
// +----------------------------------------------------------------------+

require_once 'PEAR.php';
require_once 'Net/Socket.php';

/**
 * Provides an implementation of the SMTP protocol using PEAR's
 * Net_Socket class.
 *
 * @package Net_SMTP
 * @author  Chuck Hagenbuch <chuck@horde.org>
 * @author  Jon Parise <jon@php.net>
 * @author  Damian Alejandro Fernandez Sosa <damlists@cnba.uba.ar>
 * @license http://opensource.org/licenses/bsd-license.php BSD-2-Clause
 *
 * @example basic.php A basic implementation of the Net_SMTP package.
 */
class Net_SMTP
{
    /**
     * The server to connect to.
     * @var string
     */
    public $host = 'localhost';

    /**
     * The port to connect to.
     * @var int
     */
    public $port = 25;

    /**
     * The value to give when sending EHLO or HELO.
     * @var string
     */
    public $localhost = 'localhost';

    /**
     * List of supported authentication methods, in preferential order.
     * @var array
     */
    public $auth_methods = array();

    /**
     * Use SMTP command pipelining (specified in RFC 2920) if the SMTP
     * server supports it.
     *
     * When pipeling is enabled, rcptTo(), mailFrom(), sendFrom(),
     * somlFrom() and samlFrom() do not wait for a response from the
     * SMTP server but return immediately.
     *
     * @var bool
     */
    public $pipelining = false;

    /**
     * Number of pipelined commands.
     * @var int
     */
    protected $pipelined_commands = 0;

    /**
     * Should debugging output be enabled?
     * @var boolean
     */
    protected $debug = false;

    /**
     * Debug output handler.
     * @var callback
     */
    protected $debug_handler = null;

    /**
     * The socket resource being used to connect to the SMTP server.
     * @var resource
     */
    protected $socket = null;

    /**
     * Array of socket options that will be passed to Net_Socket::connect().
     * @see stream_context_create()
     * @var array
     */
    protected $socket_options = null;

    /**
     * The socket I/O timeout value in seconds.
     * @var int
     */
    protected $timeout = 0;

    /**
     * The most recent server response code.
     * @var int
     */
    protected $code = -1;

    /**
     * The most recent server response arguments.
     * @var array
     */
    protected $arguments = array();

    /**
     * Stores the SMTP server's greeting string.
     * @var string
     */
    protected $greeting = null;

    /**
     * Stores detected features of the SMTP server.
     * @var array
     */
    protected $esmtp = array();

    /**
     * Instantiates a new Net_SMTP object, overriding any defaults
     * with parameters that are passed in.
     *
     * If you have SSL support in PHP, you can connect to a server
     * over SSL using an 'ssl://' prefix:
     *
     *   // 465 is a common smtps port.
     *   $smtp = new Net_SMTP('ssl://mail.host.com', 465);
     *   $smtp->connect();
     *
     * @param string  $host             The server to connect to.
     * @param integer $port             The port to connect to.
     * @param string  $localhost        The value to give when sending EHLO or HELO.
     * @param boolean $pipelining       Use SMTP command pipelining
     * @param integer $timeout          Socket I/O timeout in seconds.
     * @param array   $socket_options   Socket stream_context_create() options.
     * @param string  $gssapi_principal GSSAPI service principal name
     * @param string  $gssapi_cname     GSSAPI credentials cache
     *
     * @since 1.0
     */
    public function __construct($host = null, $port = null, $localhost = null,
        $pipelining = false, $timeout = 0, $socket_options = null,
        $gssapi_principal=null, $gssapi_cname=null
    ) {
        if (isset($host)) {
            $this->host = $host;
        }
        if (isset($port)) {
            $this->port = $port;
        }
        if (isset($localhost)) {
            $this->localhost = $localhost;
        }

        $this->pipelining       = $pipelining;
        $this->socket           = new Net_Socket();
        $this->socket_options   = $socket_options;
        $this->timeout          = $timeout;
        $this->gssapi_principal = $gssapi_principal;
        $this->gssapi_cname     = $gssapi_cname;

        /* If PHP krb5 extension is loaded, we enable GSSAPI method. */
        if (extension_loaded('krb5')) {
            $this->setAuthMethod('GSSAPI', array($this, 'authGSSAPI'));
        }

        /* Include the Auth_SASL package.  If the package is available, we
         * enable the authentication methods that depend upon it. */
        if (@include_once 'Auth/SASL.php') {
            $this->setAuthMethod('CRAM-MD5', array($this, 'authCramMD5'));
            $this->setAuthMethod('DIGEST-MD5', array($this, 'authDigestMD5'));
        }

        /* These standard authentication methods are always available. */
        $this->setAuthMethod('LOGIN', array($this, 'authLogin'), false);
        $this->setAuthMethod('PLAIN', array($this, 'authPlain'), false);
        $this->setAuthMethod('XOAUTH2', array($this, 'authXOAuth2'), false);
    }

    /**
     * Set the socket I/O timeout value in seconds plus microseconds.
     *
     * @param integer $seconds      Timeout value in seconds.
     * @param integer $microseconds Additional value in microseconds.
     *
     * @since 1.5.0
     */
    public function setTimeout($seconds, $microseconds = 0)
    {
        return $this->socket->setTimeout($seconds, $microseconds);
    }

    /**
     * Set the value of the debugging flag.
     *
     * @param boolean  $debug   New value for the debugging flag.
     * @param callback $handler Debug handler callback
     *
     * @since 1.1.0
     */
    public function setDebug($debug, $handler = null)
    {
        $this->debug         = $debug;
        $this->debug_handler = $handler;
    }

    /**
     * Write the given debug text to the current debug output handler.
     *
     * @param string $message Debug mesage text.
     *
     * @since 1.3.3
     */
    protected function debug($message)
    {
        if ($this->debug) {
            if ($this->debug_handler) {
                call_user_func_array(
                    $this->debug_handler, array(&$this, $message)
                );
            } else {
                echo "DEBUG: $message\n";
            }
        }
    }

    /**
     * Send the given string of data to the server.
     *
     * @param string $data The string of data to send.
     *
     * @return mixed The number of bytes that were actually written,
     *               or a PEAR_Error object on failure.
     *
     * @since 1.1.0
     */
    protected function send($data)
    {
        $this->debug("Send: $data");

        $result = $this->socket->write($data);
        if (!$result || PEAR::isError($result)) {
            $msg = $result ? $result->getMessage() : "unknown error";
            return PEAR::raiseError("Failed to write to socket: $msg");
        }

        return $result;
    }

    /**
     * Send a command to the server with an optional string of
     * arguments.  A carriage return / linefeed (CRLF) sequence will
     * be appended to each command string before it is sent to the
     * SMTP server - an error will be thrown if the command string
     * already contains any newline characters. Use send() for
     * commands that must contain newlines.
     *
     * @param string $command The SMTP command to send to the server.
     * @param string $args    A string of optional arguments to append
     *                        to the command.
     *
     * @return mixed The result of the send() call.
     *
     * @since 1.1.0
     */
    protected function put($command, $args = '')
    {
        if (!empty($args)) {
            $command .= ' ' . $args;
        }

        if (strcspn($command, "\r\n") !== strlen($command)) {
            return PEAR::raiseError('Commands cannot contain newlines');
        }

        return $this->send($command . "\r\n");
    }

    /**
     * Read a reply from the SMTP server.  The reply consists of a response
     * code and a response message.
     *
     * @param mixed $valid The set of valid response codes.  These
     *                     may be specified as an array of integer
     *                     values or as a single integer value.
     * @param bool  $later Do not parse the response now, but wait
     *                     until the last command in the pipelined
     *                     command group
     *
     * @return mixed True if the server returned a valid response code or
     *               a PEAR_Error object is an error condition is reached.
     *
     * @since 1.1.0
     *
     * @see getResponse
     */
    protected function parseResponse($valid, $later = false)
    {
        $this->code      = -1;
        $this->arguments = array();

        if ($later) {
            $this->pipelined_commands++;
            return true;
        }

        for ($i = 0; $i <= $this->pipelined_commands; $i++) {
            while ($line = $this->socket->readLine()) {
                $this->debug("Recv: $line");

                /* If we receive an empty line, the connection was closed. */
                if (empty($line)) {
                    $this->disconnect();
                    return PEAR::raiseError('Connection was closed');
                }

                /* Read the code and store the rest in the arguments array. */
                $code = substr($line, 0, 3);
                $this->arguments[] = trim(substr($line, 4));

                /* Check the syntax of the response code. */
                if (is_numeric($code)) {
                    $this->code = (int)$code;
                } else {
                    $this->code = -1;
                    break;
                }

                /* If this is not a multiline response, we're done. */
                if (substr($line, 3, 1) != '-') {
                    break;
                }
            }
        }

        $this->pipelined_commands = 0;

        /* Compare the server's response code with the valid code/codes. */
        if (is_int($valid) && ($this->code === $valid)) {
            return true;
        } elseif (is_array($valid) && in_array($this->code, $valid, true)) {
            return true;
        }

        return PEAR::raiseError('Invalid response code received from server', $this->code);
    }

    /**
     * Issue an SMTP command and verify its response.
     *
     * @param string $command The SMTP command string or data.
     * @param mixed  $valid   The set of valid response codes. These
     *                        may be specified as an array of integer
     *                        values or as a single integer value.
     *
     * @return mixed True on success or a PEAR_Error object on failure.
     *
     * @since 1.6.0
     */
    public function command($command, $valid)
    {
        if (PEAR::isError($error = $this->put($command))) {
            return $error;
        }
        if (PEAR::isError($error = $this->parseResponse($valid))) {
            return $error;
        }

        return true;
    }

    /**
     * Return a 2-tuple containing the last response from the SMTP server.
     *
     * @return array A two-element array: the first element contains the
     *               response code as an integer and the second element
     *               contains the response's arguments as a string.
     *
     * @since 1.1.0
     */
    public function getResponse()
    {
        return array($this->code, join("\n", $this->arguments));
    }

    /**
     * Return the SMTP server's greeting string.
     *
     * @return string A string containing the greeting string, or null if
     *                a greeting has not been received.
     *
     * @since 1.3.3
     */
    public function getGreeting()
    {
        return $this->greeting;
    }

    /**
     * Attempt to connect to the SMTP server.
     *
     * @param int  $timeout    The timeout value (in seconds) for the
     *                         socket connection attempt.
     * @param bool $persistent Should a persistent socket connection
     *                         be used?
     *
     * @return mixed Returns a PEAR_Error with an error message on any
     *               kind of failure, or true on success.
     * @since 1.0
     */
    public function connect($timeout = null, $persistent = false)
    {
        $this->greeting = null;

        $result = $this->socket->connect(
            $this->host, $this->port, $persistent, $timeout, $this->socket_options
        );

        if (PEAR::isError($result)) {
            return PEAR::raiseError(
                'Failed to connect socket: ' . $result->getMessage()
            );
        }

        /*
         * Now that we're connected, reset the socket's timeout value for
         * future I/O operations.  This allows us to have different socket
         * timeout values for the initial connection (our $timeout parameter)
         * and all other socket operations.
         */
        if ($this->timeout > 0) {
            if (PEAR::isError($error = $this->setTimeout($this->timeout))) {
                return $error;
            }
        }

        if (PEAR::isError($error = $this->parseResponse(220))) {
            return $error;
        }

        /* Extract and store a copy of the server's greeting string. */
        list(, $this->greeting) = $this->getResponse();

        if (PEAR::isError($error = $this->negotiate())) {
            return $error;
        }

        return true;
    }

    /**
     * Attempt to disconnect from the SMTP server.
     *
     * @return mixed Returns a PEAR_Error with an error message on any
     *               kind of failure, or true on success.
     * @since 1.0
     */
    public function disconnect()
    {
        if (PEAR::isError($error = $this->put('QUIT'))) {
            return $error;
        }
        if (PEAR::isError($error = $this->parseResponse(221))) {
            return $error;
        }
        if (PEAR::isError($error = $this->socket->disconnect())) {
            return PEAR::raiseError(
                'Failed to disconnect socket: ' . $error->getMessage()
            );
        }

        return true;
    }

    /**
     * Attempt to send the EHLO command and obtain a list of ESMTP
     * extensions available, and failing that just send HELO.
     *
     * @return mixed Returns a PEAR_Error with an error message on any
     *               kind of failure, or true on success.
     *
     * @since 1.1.0
     */
    protected function negotiate()
    {
        if (PEAR::isError($error = $this->put('EHLO', $this->localhost))) {
            return $error;
        }

        if (PEAR::isError($this->parseResponse(250))) {
            /* If the EHLO failed, try the simpler HELO command. */
            if (PEAR::isError($error = $this->put('HELO', $this->localhost))) {
                return $error;
            }
            if (PEAR::isError($this->parseResponse(250))) {
                return PEAR::raiseError('HELO was not accepted', $this->code);
            }

            return true;
        }

        foreach ($this->arguments as $argument) {
            $verb      = strtok($argument, ' ');
            $len       = strlen($verb);
            $arguments = substr($argument, $len + 1, strlen($argument) - $len - 1);
            $this->esmtp[$verb] = $arguments;
        }

        if (!isset($this->esmtp['PIPELINING'])) {
            $this->pipelining = false;
        }

        return true;
    }

    /**
     * Returns the name of the best authentication method that the server
     * has advertised.
     *
     * @return mixed Returns a string containing the name of the best
     *               supported authentication method or a PEAR_Error object
     *               if a failure condition is encountered.
     * @since 1.1.0
     */
    protected function getBestAuthMethod()
    {
        $available_methods = explode(' ', $this->esmtp['AUTH']);

        foreach ($this->auth_methods as $method => $callback) {
            if (in_array($method, $available_methods)) {
                return $method;
            }
        }

        return PEAR::raiseError('No supported authentication methods');
    }
    
    /**
     * Establish STARTTLS Connection.
     *
     * @return mixed Returns a PEAR_Error with an error message on any
     *               kind of failure, true on success, or false if SSL/TLS
     *               isn't available.
     * @since 1.10.0
     */
    public function starttls()
    {
        /* We can only attempt a TLS connection if one has been requested,
         * we're running PHP 5.1.0 or later, have access to the OpenSSL
         * extension, are connected to an SMTP server which supports the
         * STARTTLS extension, and aren't already connected over a secure
         * (SSL) socket connection. */
        if (version_compare(PHP_VERSION, '5.1.0', '>=')
            && extension_loaded('openssl') && isset($this->esmtp['STARTTLS'])
            && strncasecmp($this->host, 'ssl://', 6) !== 0
            ) {
                /* Start the TLS connection attempt. */
                if (PEAR::isError($result = $this->put('STARTTLS'))) {
                    return $result;
                }
                if (PEAR::isError($result = $this->parseResponse(220))) {
                    return $result;
                }
                if (isset($this->socket_options['ssl']['crypto_method'])) {
                    $crypto_method = $this->socket_options['ssl']['crypto_method'];
                } else {
                    /* STREAM_CRYPTO_METHOD_TLS_ANY_CLIENT constant does not exist
                     * and STREAM_CRYPTO_METHOD_SSLv23_CLIENT constant is
                     * inconsistent across PHP versions. */
                    $crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT
                    | @STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT
                    | @STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
                }
                if (PEAR::isError($result = $this->socket->enableCrypto(true, $crypto_method))) {
                    return $result;
                } elseif ($result !== true) {
                    return PEAR::raiseError('STARTTLS failed');
                }
                
                /* Send EHLO again to recieve the AUTH string from the
                 * SMTP server. */
                $this->negotiate();
            } else {
                return false;
            }
            
            return true;
    }
        
    /**
     * Attempt to do SMTP authentication.
     *
     * @param string $uid    The userid to authenticate as.
     * @param string $pwd    The password to authenticate with.
     * @param string $method The requested authentication method.  If none is
     *                       specified, the best supported method will be used.
     * @param bool   $tls    Flag indicating whether or not TLS should be attempted.
     * @param string $authz  An optional authorization identifier.  If specified, this
     *                       identifier will be used as the authorization proxy.
     *
     * @return mixed Returns a PEAR_Error with an error message on any
     *               kind of failure, or true on success.
     * @since 1.0
     */
    public function auth($uid, $pwd , $method = '', $tls = true, $authz = '')
    {
        /* We can only attempt a TLS connection if one has been requested,
         * we're running PHP 5.1.0 or later, have access to the OpenSSL
         * extension, are connected to an SMTP server which supports the
         * STARTTLS extension, and aren't already connected over a secure
         * (SSL) socket connection. */
        if ($tls) {
            /* Start the TLS connection attempt. */
            if (PEAR::isError($starttls = $this->starttls())) {
                return $starttls;
            }
        }

        if (empty($this->esmtp['AUTH'])) {
            return PEAR::raiseError('SMTP server does not support authentication');
        }

        /* If no method has been specified, get the name of the best
         * supported method advertised by the SMTP server. */
        if (empty($method)) {
            if (PEAR::isError($method = $this->getBestAuthMethod())) {
                /* Return the PEAR_Error object from _getBestAuthMethod(). */
                return $method;
            }
        } else {
            $method = strtoupper($method);
            if (!array_key_exists($method, $this->auth_methods)) {
                return PEAR::raiseError("$method is not a supported authentication method");
            }
        }

        if (!isset($this->auth_methods[$method])) {
            return PEAR::raiseError("$method is not a supported authentication method");
        }

        if (!is_callable($this->auth_methods[$method], false)) {
            return PEAR::raiseError("$method authentication method cannot be called");
        }

        if (is_array($this->auth_methods[$method])) {
            list($object, $method) = $this->auth_methods[$method];
            $result = $object->{$method}($uid, $pwd, $authz, $this);
        } else {
            $func   = $this->auth_methods[$method];
            $result = $func($uid, $pwd, $authz, $this);
        }

        /* If an error was encountered, return the PEAR_Error object. */
        if (PEAR::isError($result)) {
            return $result;
        }

        return true;
    }

    /**
     * Add a new authentication method.
     *
     * @param string $name     The authentication method name (e.g. 'PLAIN')
     * @param mixed  $callback The authentication callback (given as the name of a
     *                         function or as an (object, method name) array).
     * @param bool   $prepend  Should the new method be prepended to the list of
     *                         available methods?  This is the default behavior,
     *                         giving the new method the highest priority.
     *
     * @return mixed True on success or a PEAR_Error object on failure.
     *
     * @since 1.6.0
     */
    public function setAuthMethod($name, $callback, $prepend = true)
    {
        if (!is_string($name)) {
            return PEAR::raiseError('Method name is not a string');
        }

        if (!is_string($callback) && !is_array($callback)) {
            return PEAR::raiseError('Method callback must be string or array');
        }

        if (is_array($callback)) {
            if (!is_object($callback[0]) || !is_string($callback[1])) {
                return PEAR::raiseError('Bad mMethod callback array');
            }
        }

        if ($prepend) {
            $this->auth_methods = array_merge(
                array($name => $callback), $this->auth_methods
            );
        } else {
            $this->auth_methods[$name] = $callback;
        }

        return true;
    }

    /**
     * Authenticates the user using the DIGEST-MD5 method.
     *
     * @param string $uid   The userid to authenticate as.
     * @param string $pwd   The password to authenticate with.
     * @param string $authz The optional authorization proxy identifier.
     *
     * @return mixed Returns a PEAR_Error with an error message on any
     *               kind of failure, or true on success.
     * @since 1.1.0
     */
    protected function authDigestMD5($uid, $pwd, $authz = '')
    {
        if (PEAR::isError($error = $this->put('AUTH', 'DIGEST-MD5'))) {
            return $error;
        }
        /* 334: Continue authentication request */
        if (PEAR::isError($error = $this->parseResponse(334))) {
            /* 503: Error: already authenticated */
            if ($this->code === 503) {
                return true;
            }
            return $error;
        }

        $auth_sasl = new Auth_SASL;
        $digest    = $auth_sasl->factory('digest-md5');
        $challenge = base64_decode($this->arguments[0]);
        $auth_str  = base64_encode(
            $digest->getResponse($uid, $pwd, $challenge, $this->host, "smtp", $authz)
        );

        if (PEAR::isError($error = $this->put($auth_str))) {
            return $error;
        }
        /* 334: Continue authentication request */
        if (PEAR::isError($error = $this->parseResponse(334))) {
            return $error;
        }

        /* We don't use the protocol's third step because SMTP doesn't
         * allow subsequent authentication, so we just silently ignore
         * it. */
        if (PEAR::isError($error = $this->put(''))) {
            return $error;
        }
        /* 235: Authentication successful */
        if (PEAR::isError($error = $this->parseResponse(235))) {
            return $error;
        }
    }

    /**
     * Authenticates the user using the CRAM-MD5 method.
     *
     * @param string $uid   The userid to authenticate as.
     * @param string $pwd   The password to authenticate with.
     * @param string $authz The optional authorization proxy identifier.
     *
     * @return mixed Returns a PEAR_Error with an error message on any
     *               kind of failure, or true on success.
     * @since 1.1.0
     */
    protected function authCRAMMD5($uid, $pwd, $authz = '')
    {
        if (PEAR::isError($error = $this->put('AUTH', 'CRAM-MD5'))) {
            return $error;
        }
        /* 334: Continue authentication request */
        if (PEAR::isError($error = $this->parseResponse(334))) {
            /* 503: Error: already authenticated */
            if ($this->code === 503) {
                return true;
            }
            return $error;
        }

        $auth_sasl = new Auth_SASL;
        $challenge = base64_decode($this->arguments[0]);
        $cram      = $auth_sasl->factory('cram-md5');
        $auth_str  = base64_encode($cram->getResponse($uid, $pwd, $challenge));

        if (PEAR::isError($error = $this->put($auth_str))) {
            return $error;
        }

        /* 235: Authentication successful */
        if (PEAR::isError($error = $this->parseResponse(235))) {
            return $error;
        }
    }

    /**
     * Authenticates the user using the LOGIN method.
     *
     * @param string $uid   The userid to authenticate as.
     * @param string $pwd   The password to authenticate with.
     * @param string $authz The optional authorization proxy identifier.
     *
     * @return mixed Returns a PEAR_Error with an error message on any
     *               kind of failure, or true on success.
     * @since 1.1.0
     */
    protected function authLogin($uid, $pwd, $authz = '')
    {
        if (PEAR::isError($error = $this->put('AUTH', 'LOGIN'))) {
            return $error;
        }
        /* 334: Continue authentication request */
        if (PEAR::isError($error = $this->parseResponse(334))) {
            /* 503: Error: already authenticated */
            if ($this->code === 503) {
                return true;
            }
            return $error;
        }

        if (PEAR::isError($error = $this->put(base64_encode($uid)))) {
            return $error;
        }
        /* 334: Continue authentication request */
        if (PEAR::isError($error = $this->parseResponse(334))) {
            return $error;
        }

        if (PEAR::isError($error = $this->put(base64_encode($pwd)))) {
            return $error;
        }

        /* 235: Authentication successful */
        if (PEAR::isError($error = $this->parseResponse(235))) {
            return $error;
        }

        return true;
    }

    /**
     * Authenticates the user using the PLAIN method.
     *
     * @param string $uid   The userid to authenticate as.
     * @param string $pwd   The password to authenticate with.
     * @param string $authz The optional authorization proxy identifier.
     *
     * @return mixed Returns a PEAR_Error with an error message on any
     *               kind of failure, or true on success.
     * @since 1.1.0
     */
    protected function authPlain($uid, $pwd, $authz = '')
    {
        if (PEAR::isError($error = $this->put('AUTH', 'PLAIN'))) {
            return $error;
        }
        /* 334: Continue authentication request */
        if (PEAR::isError($error = $this->parseResponse(334))) {
            /* 503: Error: already authenticated */
            if ($this->code === 503) {
                return true;
            }
            return $error;
        }

        $auth_str = base64_encode($authz . chr(0) . $uid . chr(0) . $pwd);

        if (PEAR::isError($error = $this->put($auth_str))) {
            return $error;
        }

        /* 235: Authentication successful */
        if (PEAR::isError($error = $this->parseResponse(235))) {
            return $error;
        }

        return true;
    }

     /**
     * Authenticates the user using the GSSAPI method.
     *
     * PHP krb5 extension is required,
     * service principal and credentials cache must be set.
     *
     * @param string $uid   The userid to authenticate as.
     * @param string $pwd   The password to authenticate with.
     * @param string $authz The optional authorization proxy identifier.
     *
     * @return mixed Returns a PEAR_Error with an error message on any
     *               kind of failure, or true on success.
     */
    protected function authGSSAPI($uid, $pwd, $authz = '')
    {
        if (PEAR::isError($error = $this->put('AUTH', 'GSSAPI'))) {
            return $error;
        }
        /* 334: Continue authentication request */
        if (PEAR::isError($error = $this->parseResponse(334))) {
            /* 503: Error: already authenticated */
            if ($this->code === 503) {
                return true;
            }
            return $error;
        }

        if (!$this->gssapi_principal) {
            return PEAR::raiseError('No Kerberos service principal set', 2);
        }

        if (!empty($this->gssapi_cname)) {
            putenv('KRB5CCNAME=' . $this->gssapi_cname);
        }

        try {
            $ccache = new KRB5CCache();
            if (!empty($this->gssapi_cname)) {
                $ccache->open($this->gssapi_cname);
            }
            
            $gssapicontext = new GSSAPIContext();
            $gssapicontext->acquireCredentials($ccache);

            $token   = '';
            $success = $gssapicontext->initSecContext($this->gssapi_principal, null, null, null, $token);
            $token   = base64_encode($token);
        }
        catch (Exception $e) {
            return PEAR::raiseError('GSSAPI authentication failed: ' . $e->getMessage());
        }

        if (PEAR::isError($error = $this->put($token))) {
            return $error;
        }

        /* 334: Continue authentication request */
        if (PEAR::isError($error = $this->parseResponse(334))) {
            return $error;
        }

        $response = $this->arguments[0];

        try {
            $challenge = base64_decode($response);
            $gssapicontext->unwrap($challenge, $challenge);
            $gssapicontext->wrap($challenge, $challenge, true);
        }
        catch (Exception $e) {
            return PEAR::raiseError('GSSAPI authentication failed: ' . $e->getMessage());
        }

        if (PEAR::isError($error = $this->put(base64_encode($challenge)))) {
            return $error;
        }

        /* 235: Authentication successful */
        if (PEAR::isError($error = $this->parseResponse(235))) {
            return $error;
        }

        return true;
    }

    /**
     * Authenticates the user using the XOAUTH2 method.
     *
     * @param string $uid   The userid to authenticate as.
     * @param string $token The access token to authenticate with.
     * @param string $authz The optional authorization proxy identifier.
     *
     * @return mixed Returns a PEAR_Error with an error message on any
     *               kind of failure, or true on success.
     * @since 1.9.0
     */
    public function authXOAuth2($uid, $token, $authz, $conn)
    {
        $auth = base64_encode("user=$uid\1auth=$token\1\1");
        if (PEAR::isError($error = $this->put('AUTH', 'XOAUTH2 ' . $auth))) {
            return $error;
        }

        /* 235: Authentication successful or 334: Continue authentication */
        if (PEAR::isError($error = $this->parseResponse([235, 334]))) {
            return $error;
        }

        /* 334: Continue authentication request */
        if ($this->code === 334) {
            /* Send an empty line as response to 334 */
            if (PEAR::isError($error = $this->put(''))) {
                return $error;
            }

            /* Expect 235: Authentication successful */
            if (PEAR::isError($error = $this->parseResponse(235))) {
                return $error;
            }
        }

        return true;
    }

    /**
     * Send the HELO command.
     *
     * @param string $domain The domain name to say we are.
     *
     * @return mixed Returns a PEAR_Error with an error message on any
     *               kind of failure, or true on success.
     * @since 1.0
     */
    public function helo($domain)
    {
        if (PEAR::isError($error = $this->put('HELO', $domain))) {
            return $error;
        }
        if (PEAR::isError($error = $this->parseResponse(250))) {
            return $error;
        }

        return true;
    }

    /**
     * Return the list of SMTP service extensions advertised by the server.
     *
     * @return array The list of SMTP service extensions.
     * @since 1.3
     */
    public function getServiceExtensions()
    {
        return $this->esmtp;
    }

    /**
     * Send the MAIL FROM: command.
     *
     * @param string $sender The sender (reverse path) to set.
     * @param string $params String containing additional MAIL parameters,
     *                       such as the NOTIFY flags defined by RFC 1891
     *                       or the VERP protocol.
     *
     *                       If $params is an array, only the 'verp' option
     *                       is supported.  If 'verp' is true, the XVERP
     *                       parameter is appended to the MAIL command.
     *                       If the 'verp' value is a string, the full
     *                       XVERP=value parameter is appended.
     *
     * @return mixed Returns a PEAR_Error with an error message on any
     *               kind of failure, or true on success.
     * @since 1.0
     */
    public function mailFrom($sender, $params = null)
    {
        $args = "FROM:<$sender>";

        /* Support the deprecated array form of $params. */
        if (is_array($params) && isset($params['verp'])) {
            if ($params['verp'] === true) {
                $args .= ' XVERP';
            } elseif (trim($params['verp'])) {
                $args .= ' XVERP=' . $params['verp'];
            }
        } elseif (is_string($params) && !empty($params)) {
            $args .= ' ' . $params;
        }

        if (PEAR::isError($error = $this->put('MAIL', $args))) {
            return $error;
        }
        if (PEAR::isError($error = $this->parseResponse(250, $this->pipelining))) {
            return $error;
        }

        return true;
    }

    /**
     * Send the RCPT TO: command.
     *
     * @param string $recipient The recipient (forward path) to add.
     * @param string $params    String containing additional RCPT parameters,
     *                          such as the NOTIFY flags defined by RFC 1891.
     *
     * @return mixed Returns a PEAR_Error with an error message on any
     *               kind of failure, or true on success.
     *
     * @since 1.0
     */
    public function rcptTo($recipient, $params = null)
    {
        $args = "TO:<$recipient>";
        if (is_string($params)) {
            $args .= ' ' . $params;
        }

        if (PEAR::isError($error = $this->put('RCPT', $args))) {
            return $error;
        }
        if (PEAR::isError($error = $this->parseResponse(array(250, 251), $this->pipelining))) {
            return $error;
        }

        return true;
    }

    /**
     * Quote the data so that it meets SMTP standards.
     *
     * This is provided as a separate public function to facilitate
     * easier overloading for the cases where it is desirable to
     * customize the quoting behavior.
     *
     * @param string &$data The message text to quote. The string must be passed
     *                      by reference, and the text will be modified in place.
     *
     * @since 1.2
     */
    public function quotedata(&$data)
    {
        /* Because a single leading period (.) signifies an end to the
         * data, legitimate leading periods need to be "doubled" ('..'). */
        $data = preg_replace('/^\./m', '..', $data);

        /* Change Unix (\n) and Mac (\r) linefeeds into CRLF's (\r\n). */
        $data = preg_replace('/(?:\r\n|\n|\r(?!\n))/', "\r\n", $data);
    }

    /**
     * Send the DATA command.
     *
     * @param mixed  $data    The message data, either as a string or an open
     *                        file resource.
     * @param string $headers The message headers.  If $headers is provided,
     *                        $data is assumed to contain only body data.
     *
     * @return mixed Returns a PEAR_Error with an error message on any
     *               kind of failure, or true on success.
     * @since 1.0
     */
    public function data($data, $headers = null)
    {
        /* Verify that $data is a supported type. */
        if (!is_string($data) && !is_resource($data)) {
            return PEAR::raiseError('Expected a string or file resource');
        }

        /* Start by considering the size of the optional headers string.  We
         * also account for the addition 4 character "\r\n\r\n" separator
         * sequence. */
        $size = $headers_size = (is_null($headers)) ? 0 : strlen($headers) + 4;

        if (is_resource($data)) {
            $stat = fstat($data);
            if ($stat === false) {
                return PEAR::raiseError('Failed to get file size');
            }
            $size += $stat['size'];
        } else {
            $size += strlen($data);
        }

        /* RFC 1870, section 3, subsection 3 states "a value of zero indicates
         * that no fixed maximum message size is in force".  Furthermore, it
         * says that if "the parameter is omitted no information is conveyed
         * about the server's fixed maximum message size". */
        $limit = (isset($this->esmtp['SIZE'])) ? $this->esmtp['SIZE'] : 0;
        if ($limit > 0 && $size >= $limit) {
            return PEAR::raiseError('Message size exceeds server limit');
        }

        /* Initiate the DATA command. */
        if (PEAR::isError($error = $this->put('DATA'))) {
            return $error;
        }
        if (PEAR::isError($error = $this->parseResponse(354))) {
            return $error;
        }

        /* If we have a separate headers string, send it first. */
        if (!is_null($headers)) {
            $this->quotedata($headers);
            if (PEAR::isError($result = $this->send($headers . "\r\n\r\n"))) {
                return $result;
            }

            /* Subtract the headers size now that they've been sent. */
            $size -= $headers_size;
        }

        /* Now we can send the message body data. */
        if (is_resource($data)) {
            /* Stream the contents of the file resource out over our socket
             * connection, line by line.  Each line must be run through the
             * quoting routine. */
            while (strlen($line = fread($data, 8192)) > 0) {
                /* If the last character is an newline, we need to grab the
                 * next character to check to see if it is a period. */
                while (!feof($data)) {
                    $char = fread($data, 1);
                    $line .= $char;
                    if ($char != "\n") {
                        break;
                    }
                }
                $this->quotedata($line);
                if (PEAR::isError($result = $this->send($line))) {
                    return $result;
                }
            }

             $last = $line;
        } else {
            /*
             * Break up the data by sending one chunk (up to 512k) at a time.
             * This approach reduces our peak memory usage.
             */
            for ($offset = 0; $offset < $size;) {
                $end = $offset + 512000;

                /*
                 * Ensure we don't read beyond our data size or span multiple
                 * lines.  quotedata() can't properly handle character data
                 * that's split across two line break boundaries.
                 */
                if ($end >= $size) {
                    $end = $size;
                } else {
                    for (; $end < $size; $end++) {
                        if ($data[$end] != "\n") {
                            break;
                        }
                    }
                }

                /* Extract our chunk and run it through the quoting routine. */
                $chunk = substr($data, $offset, $end - $offset);
                $this->quotedata($chunk);

                /* If we run into a problem along the way, abort. */
                if (PEAR::isError($result = $this->send($chunk))) {
                    return $result;
                }

                /* Advance the offset to the end of this chunk. */
                $offset = $end;
            }

            $last = $chunk;
        }

        /* Don't add another CRLF sequence if it's already in the data */
        $terminator = (substr($last, -2) == "\r\n" ? '' : "\r\n") . ".\r\n";

        /* Finally, send the DATA terminator sequence. */
        if (PEAR::isError($result = $this->send($terminator))) {
            return $result;
        }

        /* Verify that the data was successfully received by the server. */
        if (PEAR::isError($error = $this->parseResponse(250, $this->pipelining))) {
            return $error;
        }

        return true;
    }

    /**
     * Send the SEND FROM: command.
     *
     * @param string $path The reverse path to send.
     *
     * @return mixed Returns a PEAR_Error with an error message on any
     *               kind of failure, or true on success.
     * @since 1.2.6
     */
    public function sendFrom($path)
    {
        if (PEAR::isError($error = $this->put('SEND', "FROM:<$path>"))) {
            return $error;
        }
        if (PEAR::isError($error = $this->parseResponse(250, $this->pipelining))) {
            return $error;
        }

        return true;
    }

    /**
     * Send the SOML FROM: command.
     *
     * @param string $path The reverse path to send.
     *
     * @return mixed Returns a PEAR_Error with an error message on any
     *               kind of failure, or true on success.
     * @since 1.2.6
     */
    public function somlFrom($path)
    {
        if (PEAR::isError($error = $this->put('SOML', "FROM:<$path>"))) {
            return $error;
        }
        if (PEAR::isError($error = $this->parseResponse(250, $this->pipelining))) {
            return $error;
        }

        return true;
    }

    /**
     * Send the SAML FROM: command.
     *
     * @param string $path The reverse path to send.
     *
     * @return mixed Returns a PEAR_Error with an error message on any
     *               kind of failure, or true on success.
     * @since 1.2.6
     */
    public function samlFrom($path)
    {
        if (PEAR::isError($error = $this->put('SAML', "FROM:<$path>"))) {
            return $error;
        }
        if (PEAR::isError($error = $this->parseResponse(250, $this->pipelining))) {
            return $error;
        }

        return true;
    }

    /**
     * Send the RSET command.
     *
     * @return mixed Returns a PEAR_Error with an error message on any
     *               kind of failure, or true on success.
     * @since  1.0
     */
    public function rset()
    {
        if (PEAR::isError($error = $this->put('RSET'))) {
            return $error;
        }
        if (PEAR::isError($error = $this->parseResponse(250, $this->pipelining))) {
            return $error;
        }

        return true;
    }

    /**
     * Send the VRFY command.
     *
     * @param string $string The string to verify
     *
     * @return mixed Returns a PEAR_Error with an error message on any
     *               kind of failure, or true on success.
     * @since 1.0
     */
    public function vrfy($string)
    {
        /* Note: 251 is also a valid response code */
        if (PEAR::isError($error = $this->put('VRFY', $string))) {
            return $error;
        }
        if (PEAR::isError($error = $this->parseResponse(array(250, 252)))) {
            return $error;
        }

        return true;
    }

    /**
     * Send the NOOP command.
     *
     * @return mixed Returns a PEAR_Error with an error message on any
     *               kind of failure, or true on success.
     * @since 1.0
     */
    public function noop()
    {
        if (PEAR::isError($error = $this->put('NOOP'))) {
            return $error;
        }
        if (PEAR::isError($error = $this->parseResponse(250))) {
            return $error;
        }

        return true;
    }

    /**
     * Backwards-compatibility method.  identifySender()'s functionality is
     * now handled internally.
     *
     * @return boolean This method always return true.
     *
     * @since 1.0
     */
    public function identifySender()
    {
        return true;
    }
}
PK��Z���NFUFUNet/Socket.phpnu�[���<?php
/**
 * Net_Socket
 *
 * PHP Version 5
 *
 * LICENSE:
 *
 * Copyright (c) 1997-2017 The PHP Group
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * o Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * o Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  Net
 * @package   Net_Socket
 * @author    Stig Bakken <ssb@php.net>
 * @author    Chuck Hagenbuch <chuck@horde.org>
 * @copyright 1997-2017 The PHP Group
 * @license   http://opensource.org/licenses/bsd-license.php BSD-2-Clause
 * @link      http://pear.php.net/packages/Net_Socket
 */

require_once 'PEAR.php';

define('NET_SOCKET_READ', 1);
define('NET_SOCKET_WRITE', 2);
define('NET_SOCKET_ERROR', 4);

/**
 * Generalized Socket class.
 *
 * @category  Net
 * @package   Net_Socket
 * @author    Stig Bakken <ssb@php.net>
 * @author    Chuck Hagenbuch <chuck@horde.org>
 * @copyright 1997-2017 The PHP Group
 * @license   http://opensource.org/licenses/bsd-license.php BSD-2-Clause
 * @link      http://pear.php.net/packages/Net_Socket
 */
class Net_Socket extends PEAR
{
    /**
     * Socket file pointer.
     * @var resource $fp
     */
    public $fp = null;

    /**
     * Whether the socket is blocking. Defaults to true.
     * @var boolean $blocking
     */
    public $blocking = true;

    /**
     * Whether the socket is persistent. Defaults to false.
     * @var boolean $persistent
     */
    public $persistent = false;

    /**
     * The IP address to connect to.
     * @var string $addr
     */
    public $addr = '';

    /**
     * The port number to connect to.
     * @var integer $port
     */
    public $port = 0;

    /**
     * Number of seconds to wait on socket operations before assuming
     * there's no more data. Defaults to no timeout.
     * @var integer|float $timeout
     */
    public $timeout = null;

    /**
     * Number of bytes to read at a time in readLine() and
     * readAll(). Defaults to 2048.
     * @var integer $lineLength
     */
    public $lineLength = 2048;

    /**
     * The string to use as a newline terminator. Usually "\r\n" or "\n".
     * @var string $newline
     */
    public $newline = "\r\n";

    /**
     * Connect to the specified port. If called when the socket is
     * already connected, it disconnects and connects again.
     *
     * @param string $addr IP address or host name (may be with protocol prefix).
     * @param integer $port TCP port number.
     * @param boolean $persistent (optional) Whether the connection is
     *                            persistent (kept open between requests
     *                            by the web server).
     * @param integer $timeout (optional) Connection socket timeout.
     * @param array $options See options for stream_context_create.
     *
     * @access public
     *
     * @return boolean|PEAR_Error  True on success or a PEAR_Error on failure.
     */
    public function connect(
        $addr,
        $port = 0,
        $persistent = null,
        $timeout = null,
        $options = null
    ) {
        if (is_resource($this->fp)) {
            @fclose($this->fp);
            $this->fp = null;
        }

        if (!$addr) {
            return $this->raiseError('$addr cannot be empty');
        } else {
            if (strspn($addr, ':.0123456789') === strlen($addr)) {
                $this->addr = strpos($addr, ':') !== false ? '[' . $addr . ']' : $addr;
            } else {
                $this->addr = $addr;
            }
        }

        $this->port = $port % 65536;

        if ($persistent !== null) {
            $this->persistent = $persistent;
        }

        $openfunc = $this->persistent ? 'pfsockopen' : 'fsockopen';
        $errno = 0;
        $errstr = '';

        if (function_exists('error_clear_last')) {
            error_clear_last();
        } else {
            $old_track_errors = @ini_set('track_errors', 1);
        }

        if ($timeout <= 0) {
            $timeout = @ini_get('default_socket_timeout');
        }

        if ($options && function_exists('stream_context_create')) {
            $context = stream_context_create($options);

            // Since PHP 5 fsockopen doesn't allow context specification
            if (function_exists('stream_socket_client')) {
                $flags = STREAM_CLIENT_CONNECT;

                if ($this->persistent) {
                    $flags = STREAM_CLIENT_PERSISTENT;
                }

                $addr = $this->addr . ':' . $this->port;
                $fp = @stream_socket_client($addr, $errno, $errstr,
                    $timeout, $flags, $context);
            } else {
                $fp = @$openfunc($this->addr, $this->port, $errno,
                    $errstr, $timeout, $context);
            }
        } else {
            $fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $timeout);
        }

        if (!$fp) {
            if ($errno === 0 && !strlen($errstr)) {
                $errstr = '';
                if (isset($old_track_errors)) {
                    $errstr = $php_errormsg ?: '';  
                    @ini_set('track_errors', $old_track_errors);
                } else {
                    $lastError = error_get_last();
                    if (isset($lastError['message'])) {
                        $errstr = $lastError['message'];
                    }
                }
            }

            return $this->raiseError($errstr, $errno);
        }

        if (isset($old_track_errors)) {
            @ini_set('track_errors', $old_track_errors);
        }

        $this->fp = $fp;
        $this->setTimeout();

        return $this->setBlocking($this->blocking);
    }

    /**
     * Disconnects from the peer, closes the socket.
     *
     * @access public
     * @return mixed true on success or a PEAR_Error instance otherwise
     */
    public function disconnect()
    {
        if (!is_resource($this->fp)) {
            return $this->raiseError('not connected');
        }

        @fclose($this->fp);
        $this->fp = null;

        return true;
    }

    /**
     * Set the newline character/sequence to use.
     *
     * @param string $newline Newline character(s)
     * @return boolean True
     */
    public function setNewline($newline)
    {
        $this->newline = $newline;

        return true;
    }

    /**
     * Find out if the socket is in blocking mode.
     *
     * @access public
     * @return boolean  The current blocking mode.
     */
    public function isBlocking()
    {
        return $this->blocking;
    }

    /**
     * Sets whether the socket connection should be blocking or
     * not. A read call to a non-blocking socket will return immediately
     * if there is no data available, whereas it will block until there
     * is data for blocking sockets.
     *
     * @param boolean $mode True for blocking sockets, false for nonblocking.
     *
     * @access public
     * @return mixed true on success or a PEAR_Error instance otherwise
     */
    public function setBlocking($mode)
    {
        if (!is_resource($this->fp)) {
            return $this->raiseError('not connected');
        }

        $this->blocking = $mode;
        stream_set_blocking($this->fp, (int)$this->blocking);

        return true;
    }

    /**
     * Sets the timeout value on socket descriptor,
     * expressed in the sum of seconds and microseconds
     *
     * @param integer $seconds Seconds.
     * @param integer $microseconds Microseconds, optional.
     *
     * @access public
     * @return mixed True on success or false on failure or
     *               a PEAR_Error instance when not connected
     */
    public function setTimeout($seconds = null, $microseconds = null)
    {
        if (!is_resource($this->fp)) {
            return $this->raiseError('not connected');
        }

        if ($seconds === null && $microseconds === null) {
            $seconds = (int)$this->timeout;
            $microseconds = (int)(($this->timeout - $seconds) * 1000000);
        } else {
            $this->timeout = $seconds + $microseconds / 1000000;
        }

        if ($this->timeout > 0) {
            return stream_set_timeout($this->fp, (int)$seconds, (int)$microseconds);
        } else {
            return false;
        }
    }

    /**
     * Sets the file buffering size on the stream.
     * See php's stream_set_write_buffer for more information.
     *
     * @param integer $size Write buffer size.
     *
     * @access public
     * @return mixed on success or an PEAR_Error object otherwise
     */
    public function setWriteBuffer($size)
    {
        if (!is_resource($this->fp)) {
            return $this->raiseError('not connected');
        }

        $returned = stream_set_write_buffer($this->fp, $size);
        if ($returned === 0) {
            return true;
        }

        return $this->raiseError('Cannot set write buffer.');
    }

    /**
     * Returns information about an existing socket resource.
     * Currently returns four entries in the result array:
     *
     * <p>
     * timed_out (bool) - The socket timed out waiting for data<br>
     * blocked (bool) - The socket was blocked<br>
     * eof (bool) - Indicates EOF event<br>
     * unread_bytes (int) - Number of bytes left in the socket buffer<br>
     * </p>
     *
     * @access public
     * @return mixed Array containing information about existing socket
     *               resource or a PEAR_Error instance otherwise
     */
    public function getStatus()
    {
        if (!is_resource($this->fp)) {
            return $this->raiseError('not connected');
        }

        return stream_get_meta_data($this->fp);
    }

    /**
     * Get a specified line of data
     *
     * @param int $size Reading ends when size - 1 bytes have been read,
     *                  or a newline or an EOF (whichever comes first).
     *                  If no size is specified, it will keep reading from
     *                  the stream until it reaches the end of the line.
     *
     * @access public
     * @return mixed $size bytes of data from the socket, or a PEAR_Error if
     *         not connected. If an error occurs, FALSE is returned.
     */
    public function gets($size = null)
    {
        if (!is_resource($this->fp)) {
            return $this->raiseError('not connected');
        }

        if (null === $size) {
            return @fgets($this->fp);
        } else {
            return @fgets($this->fp, $size);
        }
    }

    /**
     * Read a specified amount of data. This is guaranteed to return,
     * and has the added benefit of getting everything in one fread()
     * chunk; if you know the size of the data you're getting
     * beforehand, this is definitely the way to go.
     *
     * @param integer $size The number of bytes to read from the socket.
     *
     * @access public
     * @return string $size bytes of data from the socket, or a PEAR_Error if
     *         not connected.
     */
    public function read($size)
    {
        if (!is_resource($this->fp)) {
            return $this->raiseError('not connected');
        }

        return @fread($this->fp, $size);
    }

    /**
     * Write a specified amount of data.
     *
     * @param string $data Data to write.
     * @param integer $blocksize Amount of data to write at once.
     *                           NULL means all at once.
     *
     * @access public
     * @return mixed If the socket is not connected, returns an instance of
     *               PEAR_Error.
     *               If the write succeeds, returns the number of bytes written.
     *               If the write fails, returns false.
     *               If the socket times out, returns an instance of PEAR_Error.
     */
    public function write($data, $blocksize = null)
    {
        if (!is_resource($this->fp)) {
            return $this->raiseError('not connected');
        }

        if (null === $blocksize && !OS_WINDOWS) {
            $written = @fwrite($this->fp, $data);

            // Check for timeout or lost connection
            if ($written === false) {
                $meta_data = $this->getStatus();

                if (!is_array($meta_data)) {
                    return $meta_data; // PEAR_Error
                }

                if (!empty($meta_data['timed_out'])) {
                    return $this->raiseError('timed out');
                }
            }

            return $written;
        } else {
            if (null === $blocksize) {
                $blocksize = 1024;
            }

            $pos = 0;
            $size = strlen($data);
            while ($pos < $size) {
                $written = @fwrite($this->fp, substr($data, $pos, $blocksize));

                // Check for timeout or lost connection
                if ($written === false) {
                    $meta_data = $this->getStatus();

                    if (!is_array($meta_data)) {
                        return $meta_data; // PEAR_Error
                    }

                    if (!empty($meta_data['timed_out'])) {
                        return $this->raiseError('timed out');
                    }

                    return $written;
                }

                $pos += $written;
            }

            return $pos;
        }
    }

    /**
     * Write a line of data to the socket, followed by a trailing newline.
     *
     * @param string $data Data to write
     *
     * @access public
     * @return mixed fwrite() result, or PEAR_Error when not connected
     */
    public function writeLine($data)
    {
        if (!is_resource($this->fp)) {
            return $this->raiseError('not connected');
        }

        return fwrite($this->fp, $data . $this->newline);
    }

    /**
     * Tests for end-of-file on a socket descriptor.
     *
     * Also returns true if the socket is disconnected.
     *
     * @access public
     * @return bool
     */
    public function eof()
    {
        return (!is_resource($this->fp) || feof($this->fp));
    }

    /**
     * Reads a byte of data
     *
     * @access public
     * @return integer 1 byte of data from the socket, or a PEAR_Error if
     *         not connected.
     */
    public function readByte()
    {
        if (!is_resource($this->fp)) {
            return $this->raiseError('not connected');
        }

        return ord(@fread($this->fp, 1));
    }

    /**
     * Reads a word of data
     *
     * @access public
     * @return integer 1 word of data from the socket, or a PEAR_Error if
     *         not connected.
     */
    public function readWord()
    {
        if (!is_resource($this->fp)) {
            return $this->raiseError('not connected');
        }

        $buf = @fread($this->fp, 2);

        return (ord($buf[0]) + (ord($buf[1]) << 8));
    }

    /**
     * Reads an int of data
     *
     * @access public
     * @return integer  1 int of data from the socket, or a PEAR_Error if
     *                  not connected.
     */
    public function readInt()
    {
        if (!is_resource($this->fp)) {
            return $this->raiseError('not connected');
        }

        $buf = @fread($this->fp, 4);

        return (ord($buf[0]) + (ord($buf[1]) << 8) +
            (ord($buf[2]) << 16) + (ord($buf[3]) << 24));
    }

    /**
     * Reads a zero-terminated string of data
     *
     * @access public
     * @return string, or a PEAR_Error if
     *         not connected.
     */
    public function readString()
    {
        if (!is_resource($this->fp)) {
            return $this->raiseError('not connected');
        }

        $string = '';
        while (($char = @fread($this->fp, 1)) !== "\x00") {
            $string .= $char;
        }

        return $string;
    }

    /**
     * Reads an IP Address and returns it in a dot formatted string
     *
     * @access public
     * @return string Dot formatted string, or a PEAR_Error if
     *         not connected.
     */
    public function readIPAddress()
    {
        if (!is_resource($this->fp)) {
            return $this->raiseError('not connected');
        }

        $buf = @fread($this->fp, 4);

        return sprintf('%d.%d.%d.%d', ord($buf[0]), ord($buf[1]),
            ord($buf[2]), ord($buf[3]));
    }

    /**
     * Read until either the end of the socket or a newline, whichever
     * comes first. Strips the trailing newline from the returned data.
     *
     * @access public
     * @return string All available data up to a newline, without that
     *         newline, or until the end of the socket, or a PEAR_Error if
     *         not connected.
     */
    public function readLine()
    {
        if (!is_resource($this->fp)) {
            return $this->raiseError('not connected');
        }

        $line = '';

        $timeout = time() + $this->timeout;

        while (!feof($this->fp) && (!$this->timeout || time() < $timeout)) {
            $line .= @fgets($this->fp, $this->lineLength);
            if (substr($line, -1) == "\n") {
                return rtrim($line, $this->newline);
            }
        }

        return $line;
    }

    /**
     * Read until the socket closes, or until there is no more data in
     * the inner PHP buffer. If the inner buffer is empty, in blocking
     * mode we wait for at least 1 byte of data. Therefore, in
     * blocking mode, if there is no data at all to be read, this
     * function will never exit (unless the socket is closed on the
     * remote end).
     *
     * @access public
     *
     * @return string  All data until the socket closes, or a PEAR_Error if
     *                 not connected.
     */
    public function readAll()
    {
        if (!is_resource($this->fp)) {
            return $this->raiseError('not connected');
        }

        $data = '';
        $timeout = time() + $this->timeout;

        while (!feof($this->fp) && (!$this->timeout || time() < $timeout)) {
            $data .= @fread($this->fp, $this->lineLength);
        }

        return $data;
    }

    /**
     * Runs the equivalent of the select() system call on the socket
     * with a timeout specified by tv_sec and tv_usec.
     *
     * @param integer $state Which of read/write/error to check for.
     * @param integer $tv_sec Number of seconds for timeout.
     * @param integer $tv_usec Number of microseconds for timeout.
     *
     * @access public
     * @return False if select fails, integer describing which of read/write/error
     *         are ready, or PEAR_Error if not connected.
     */
    public function select($state, $tv_sec, $tv_usec = 0)
    {
        if (!is_resource($this->fp)) {
            return $this->raiseError('not connected');
        }

        $read = null;
        $write = null;
        $except = null;
        if ($state & NET_SOCKET_READ) {
            $read[] = $this->fp;
        }
        if ($state & NET_SOCKET_WRITE) {
            $write[] = $this->fp;
        }
        if ($state & NET_SOCKET_ERROR) {
            $except[] = $this->fp;
        }
        if (false === ($sr = stream_select($read, $write, $except,
                $tv_sec, $tv_usec))
        ) {
            return false;
        }

        $result = 0;
        if (count($read)) {
            $result |= NET_SOCKET_READ;
        }
        if (count($write)) {
            $result |= NET_SOCKET_WRITE;
        }
        if (count($except)) {
            $result |= NET_SOCKET_ERROR;
        }

        return $result;
    }

    /**
     * Turns encryption on/off on a connected socket.
     *
     * @param bool $enabled Set this parameter to true to enable encryption
     *                         and false to disable encryption.
     * @param integer $type Type of encryption. See stream_socket_enable_crypto()
     *                         for values.
     *
     * @see    http://se.php.net/manual/en/function.stream-socket-enable-crypto.php
     * @access public
     * @return false on error, true on success and 0 if there isn't enough data
     *         and the user should try again (non-blocking sockets only).
     *         A PEAR_Error object is returned if the socket is not
     *         connected
     */
    public function enableCrypto($enabled, $type)
    {
        if (version_compare(phpversion(), '5.1.0', '>=')) {
            if (!is_resource($this->fp)) {
                return $this->raiseError('not connected');
            }

            return @stream_socket_enable_crypto($this->fp, $enabled, $type);
        } else {
            $msg = 'Net_Socket::enableCrypto() requires php version >= 5.1.0';

            return $this->raiseError($msg);
        }
    }

}
PK��Z
.depdblocknu�[���PK��Z'P���
�
ezc/Base/metadata.phpnu�[���<?php
/**
 * File containing the ezcBaseMetaData class.
 *
 * @package Base
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */
/**
 * Base class implements ways of fetching information about the installed
 * eZ Components. It knows whether to use the PEAR registry or the bundled XML
 * file, depending on how eZ Components is installed.
 *
 * @package Base
 * @version 1.8
 * @mainclass
 */
class ezcBaseMetaData
{
    /**
     * Creates a ezcBaseMetaData object
     *
     * The sole parameter $installMethod should only be used if you are really
     * sure that you need to use it. It is mostly there to make testing at
     * least slightly possible. Again, do not set it unless instructed.
     *
     * @param string $installMethod
     */
    public function __construct( $installMethod = NULL )
    {
        $installMethod = $installMethod !== NULL ? $installMethod : ezcBase::getInstallMethod();

        // figure out which reader to use
        switch ( $installMethod )
        {
            case 'tarball':
                $this->reader = new ezcBaseMetaDataTarballReader;
                break;
            case 'pear':
                $this->reader = new ezcBaseMetaDataPearReader;
                break;
            default:
                throw new ezcBaseMetaDataReaderException( "Unknown install method '$installMethod'." );
                break;
        }
    }

    /**
     * Returns the version string for the installed eZ Components bundle.
     *
     * A version string such as "2008.2.2" is returned.
     *
     * @return string
     */
    public function getBundleVersion()
    {
        return $this->reader->getBundleVersion();
    }

    /**
     * Returns a PHP version string that describes the required PHP version for
     * this installed eZ Components bundle.
     *
     * @return string
     */
    public function getRequiredPhpVersion()
    {
        return $this->reader->getRequiredPhpVersion();
    }

    /**
     * Returns whether $componentName is installed
     *
     * If installed with PEAR, it checks the PEAR registry whether the
     * component is there. In case the tarball installation method is used, it
     * will return true for every component that exists (because all of them
     * are then available).
     *
     * @return bool
     */
    public function isComponentInstalled( $componentName )
    {
        return $this->reader->isComponentInstalled( $componentName );
    }

    /**
     * Returns the version string of the available $componentName or false when
     * the component is not installed.
     *
     * @return string
     */
    public function getComponentVersion( $componentName )
    {
        return $this->reader->getComponentVersion( $componentName );
    }

    /**
     * Returns a list of components that $componentName depends on.
     *
     * If $componentName is left empty, all installed components are returned.
     *
     * The returned array has as keys the component names, and as values the
     * version of the components.
     *
     * @return array(string=>string).
     */
    public function getComponentDependencies( $componentName = null )
    {
        if ( $componentName === null )
        {
            return $this->reader->getComponentDependencies();
        }
        else
        {
            return $this->reader->getComponentDependencies( $componentName );
        }
    }
}
?>
PK��Z:��||ezc/Base/ezc_bootstrap.phpnu�[���<?php
/**
 * Include file that can be used for a quick setup of the eZ Components.
 *
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @version 1.8
 * @filesource
 * @package Base
 * @access private
 */
$dir = dirname( __FILE__ );
$dirParts = explode( DIRECTORY_SEPARATOR, $dir );

if ( $dirParts[count( $dirParts ) - 1] === 'src' )
{
    $baseDir = join( DIRECTORY_SEPARATOR, array_slice( $dirParts, 0, -2 ) );
    require $baseDir . '/Base/src/base.php'; // svn, bundle
}
else if ( $dirParts[count( $dirParts ) - 2] === 'ezc' )
{
    $baseDir = join( DIRECTORY_SEPARATOR, array_slice( $dirParts, 0, -2 ) );
    require $baseDir . '/ezc/Base/base.php'; // pear
}
else
{
    die( "Your environment isn't properly set-up. Please refer to the eZ components documentation at http://components.ez.no/doc ." );
}

/**
 * Implements the __autoload mechanism for PHP - which can only be done once
 * per request.
 *
 * @param string $className  The name of the class that should be loaded.
 */
function __autoload( $className )
{
	ezcBase::autoload( $className );
}
?>
PK��Z�����ezc/Base/options/autoload.phpnu�[���<?php
/**
 * File containing the ezcBaseAutoloadOptions class
 *
 * @package Base
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * Class containing the basic options for ezcBase' autoload.
 *
 * @property bool $preload
 *           If component preloading is enabled then as soon as one of the
 *           classes of a component is request, all other classes in the
 *           component are loaded as well (except for Exception classes).
 * @property bool $debug
 *           If debug is enabled then the autoload method will show exceptions
 *           when a class can not be found. Because exceptions are ignored by
 *           PHP in the autoload handler, you have to catch them in autoload()
 *           yourself and do something with the exception message.
 *
 * @package Base
 * @version 1.8
 */
class ezcBaseAutoloadOptions extends ezcBaseOptions
{
    /**
     * Constructs an object with the specified values.
     *
     * @throws ezcBasePropertyNotFoundException
     *         if $options contains a property not defined
     * @throws ezcBaseValueException
     *         if $options contains a property with a value not allowed
     * @param array(string=>mixed) $options
     */
    public function __construct( array $options = array() )
    {
        $this->preload = false;
        $this->debug = false;

        parent::__construct( $options );
    }

    /**
     * Sets the option $name to $value.
     *
     * @throws ezcBasePropertyNotFoundException
     *         if the property $name is not defined
     * @throws ezcBaseValueException
     *         if $value is not correct for the property $name
     * @param string $name
     * @param mixed $value
     * @ignore
     */
    public function __set( $name, $value )
    {
        switch ( $name )
        {
            case 'debug':
            case 'preload':
                if ( !is_bool( $value ) )
                {
                    throw new ezcBaseValueException( $name, $value, 'bool' );
                }
                $this->properties[$name] = $value;
                break;

            default:
                throw new ezcBasePropertyNotFoundException( $name );
        }
    }
}
?>
PK��Z|R��)ezc/Base/structs/repository_directory.phpnu�[���<?php
/**
 * File containing the ezcBaseRepositoryDirectory.
 *
 * @package Base
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * Struct which defines a repository directory.
 *
 * @package Base
 * @version 1.8
 */
class ezcBaseRepositoryDirectory extends ezcBaseStruct
{
    /**
     * Specifies that the entry is for the eZ Components repository.
     */
    const TYPE_INTERNAL = 0;

    /**
     * Specifies that the entry is for an external (user defined) repository.
     */
    const TYPE_EXTERNAL = 1;

    /**
     * The $type is one of the two TYPE_* constants defined in this class.
     *
     * @var string
     */
    public $type;

    /**
     * The path to the configured repository.
     *
     * @var string
     */
    public $basePath;

    /**
     * The path to the autoload files.
     *
     * @var string
     */
    public $autoloadPath;

    /**
     * Constructs a new ezcBaseRepositoryDirectory of type $type with base path
     * $basePath and autoload path $autoloadPath.
     *
     * @param string $type
     * @param string $basePath
     * @param string $autoloadPath
     */
    public function __construct( $type, $basePath, $autoloadPath )
    {
        $this->type = $type;
        $this->basePath = $basePath;
        $this->autoloadPath = $autoloadPath;
    }

    /**
     * Returns a new instance of this class with the data specified by $array.
     *
     * $array contains all the data members of this class in the form:
     * array('member_name'=>value).
     *
     * __set_state makes this class exportable with var_export.
     * var_export() generates code, that calls this method when it
     * is parsed with PHP.
     *
     * @param array(string=>mixed) $array
     * @return ezcBaseRepositoryDirectory
     */
    static public function __set_state( array $array )
    {
        return new ezcBaseRepositoryDirectory( $array['type'], $array['basePath'], $array['autoloadPath'] );
    }
}
?>
PK��ZS�،��&ezc/Base/structs/file_find_context.phpnu�[���<?php
/**
 * File containing the ezcBaseFileFindContext class.
 *
 * @package Base
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * Struct which defines the information collected by the file walker for locating files.
 *
 * @package Base
 * @version 1.8
 */
class ezcBaseFileFindContext extends ezcBaseStruct
{
    /**
     * The list of files
     *
     * @var array(string)
     */
    public $elements;

    /**
     * The number of files
     *
     * @var int
     */
    public $count;

    /**
     * The total file size of all files found
     *
     * @var int
     */
    public $size;

    /**
     * Constructs a new ezcBaseFileFindContext with initial values.
     *
     * @param array(string) $elements
     * @param int $count
     * @param int $size
     */
    public function __construct( $elements = array(), $count = 0, $size = 0 )
    {
        $this->elements = $elements;
        $this->count = $count;
        $this->size = $size;
    }

    /**
     * Returns a new instance of this class with the data specified by $array.
     *
     * $array contains all the data members of this class in the form:
     * array('member_name'=>value).
     *
     * __set_state makes this class exportable with var_export.
     * var_export() generates code, that calls this method when it
     * is parsed with PHP.
     *
     * @param array(string=>mixed) $array
     * @return ezcBaseFileFindContext
     */
    static public function __set_state( array $array )
    {
        return new ezcBaseFileFindContext( $array['elements'], $array['count'], $array['size'] );
    }
}
?>
PK��Zj��ezc/Base/metadata/tarball.phpnu�[���<?php
/**
 * File containing the ezcBaseMetaDataTarballReader class.
 *
 * @package Base
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */
/**
 * Base class implements ways of fetching information about the installed
 * eZ Components when installed as tarball.
 *
 * @package Base
 * @version 1.8
 * @mainclass
 */
class ezcBaseMetaDataTarballReader
{
    /**
     * Contains the handler to the XML file containing the release information.
     * @var SimpleXmlElement
     */
    private $xml;

    /**
     * Creates the reader object and opens the release-info file.
     */
    public function __construct()
    {
        $filename = dirname( __FILE__ ) . '/../../../release-info.xml';
        $this->xml = simplexml_load_file( $filename );
    }

    /**
     * Returns the version string for the installed eZ Components bundle.
     *
     * A version string such as "2008.2.2" is returned.
     *
     * @return string
     */
    public function getBundleVersion()
    {
        return (string) $this->xml->version;
    }

    /**
     * Returns a PHP version string that describes the required PHP version for
     * this installed eZ Components bundle.
     *
     * @return string
     */
    public function getRequiredPhpVersion()
    {
        return (string) $this->xml->deps->php;
    }

    /**
     * Returns whether $componentName is installed
     *
     * Returns true for every component that exists (because all of them are
     * then available).
     *
     * @return bool
     */
    public function isComponentInstalled( $componentName )
    {
        $root = $this->xml->deps->packages->package;

        foreach ( $root as $package )
        {
            if ( (string) $package['name'] == $componentName )
            {
                return true;
            }
        }
        return false;
    }

    /**
     * Returns the version string of the available $componentName or false when
     * the component is not installed.
     *
     * @return string
     */
    public function getComponentVersion( $componentName )
    {
        $root = $this->xml->deps->packages->package;

        foreach ( $root as $package )
        {
            if ( (string) $package['name'] == $componentName )
            {
                return (string) $package['version'];
            }
        }
        return false;
    }

    /**
     * Returns a list of components that $componentName depends on.
     *
     * If $componentName is left empty, all installed components are returned.
     *
     * The returned array has as keys the component names, and as values the
     * version of the components. It returns null of the $componentName
     * is not found.
     *
     * @return array(string=>string).
     */
    public function getComponentDependencies( $componentName = null )
    {
        $baseVersion = false;
        $root = $this->xml->deps->packages;
        $found = $componentName === null ? true : false;

        // in case $componentName != null, we loop through all the components
        // in the file, and figure out the new root that we can list dependency
        // packages from.
        foreach ( $root->package as $package )
        {
            if ( (string) $package['name'] == 'Base' )
            {
                $baseVersion = $package['version'];
            }
            if ( !$found && (string) $package['name'] == $componentName )
            {
                $root = $package->deps;
                $found = true;
            }
        }

        if ( !$found )
        {
            return null;
        }

        // We always add the Base dependency even though it's not in the dependency file.
        $deps = array();
        $deps['Base'] = (string) $baseVersion;

        if ( !isset( $root->package ) )
        {
            return $deps;
        }
        foreach ( $root->package as $package )
        {
            $deps[(string) $package['name']] = (string) $package['version'];
        }
        return $deps;
    }
}
?>
PK��Zmyv		ezc/Base/metadata/pear.phpnu�[���<?php
/**
 * File containing the ezcBaseMetaDataPearReader class.
 *
 * @package Base
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

@require 'PEAR/Registry.php';

/**
 * Base class implements ways of fetching information about the installed
 * eZ Components when installed as tarball.
 *
 * Note: there are lots of @ used here, because PEAR still lives in the stone
 * age with their PHP 3 code and general liberal use of throwing warnings and
 * notices.
 *
 * @package Base
 * @version 1.8
 * @mainclass
 */
class ezcBaseMetaDataPearReader
{
    /**
     * Stores the PEAR_Registry to query for information
     *
     * @var PEAR_Registry
     */
    private $registry;

    /**
     * Creates the reader object and initialized the registry for querying
     */
    public function __construct()
    {
        @$this->registry = new PEAR_Registry;
    }

    /**
     * Returns the version string for the installed eZ Components bundle.
     *
     * A version string such as "2008.2.2" is returned.
     *
     * @return string
     */
    public function getBundleVersion()
    {
        @$packageInfo = $this->registry->packageInfo( 'ezcomponents', null, 'components.ez.no' );
        return $packageInfo['version']['release'];
    }

    /**
     * Returns a PHP version string that describes the required PHP version for
     * this installed eZ Components bundle.
     *
     * @return string
     */
    public function getRequiredPhpVersion()
    {
        @$packageInfo = $this->registry->packageInfo( 'ezcomponents', null, 'components.ez.no' );
        if ( array_key_exists( 'required', $packageInfo['dependencies'] ) )
        {
            return $packageInfo['dependencies']['required']['php']['min'];
        }
        return $packageInfo['dependencies']['php']['min'];
    }

    /**
     * Returns whether $componentName is installed
     *
     * Checks the PEAR registry whether the component is there.
     *
     * @return bool
     */
    public function isComponentInstalled( $componentName )
    {
        @$packageInfo = $this->registry->packageInfo( $componentName, null, 'components.ez.no' );
        return is_array( $packageInfo );
    }

    /**
     * Returns the version string of the available $componentName or false when
     * the component is not installed.
     *
     * @return string
     */
    public function getComponentVersion( $componentName )
    {
        @$packageInfo = $this->registry->packageInfo( $componentName, null, 'components.ez.no' );
        $release = $packageInfo['version']['release'];
        return $release === null ? false : $release;
    }

    /**
     * Returns a list of components that $componentName depends on.
     *
     * If $componentName is left empty, all installed components are returned.
     *
     * The returned array has as keys the component names, and as values the
     * version of the components.
     *
     * @return array(string=>string).
     */
    public function getComponentDependencies( $componentName = 'ezcomponents' )
    {
        @$packageInfo = $this->registry->packageInfo( $componentName, 'dependencies', 'components.ez.no' );
        if ( isset( $packageInfo['required']['package'] ) )
        {
            $deps = array();
            if ( isset( $packageInfo['required']['package']['name'] ) )
            {
                $deps[$packageInfo['required']['package']['name']] = $packageInfo['required']['package']['min'];
            }
            else
            {
                foreach ( $packageInfo['required']['package'] as $package )
                {
                    $deps[$package['name']] = $package['min'];
                }
            }
            return $deps;
        }
        return array();
    }
}
?>
PK��Z�B�X�+�+ezc/Base/features.phpnu�[���<?php
/**
 * File containing the ezcBaseFeatures class.
 *
 * @package Base
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * Provides methods needed to check for features.
 *
 * Example:
 * <code>
 * <?php
 * echo "supports uid: " . ezcBaseFeatures::supportsUserId() . "\n";
 * echo "supports symlink: " . ezcBaseFeatures::supportsSymLink() . "\n";
 * echo "supports hardlink: " . ezcBaseFeatures::supportsLink() . "\n";
 * echo "has imagemagick identify: " . ezcBaseFeatures::hasImageIdentify() . "\n";
 * echo " identify path: " . ezcBaseFeatures::getImageIdentifyExecutable() . "\n";
 * echo "has imagemagick convert: " . ezcBaseFeatures::hasImageConvert() . "\n";
 * echo " convert path: " . ezcBaseFeatures::getImageConvertExecutable() . "\n";
 * echo "has gzip extension: " . ezcBaseFeatures::hasExtensionSupport( 'zlib' ) . "\n";
 * echo "has pdo_mysql 1.0.2: " . ezcBaseFeatures::hasExtensionSupport( 'pdo_mysql', '1.0.2' ) . "\n"
 * ?>
 * </code>
 *
 * @package Base
 * @version 1.8
 */
class ezcBaseFeatures
{
    /**
      * Used to store the path of the ImageMagick convert utility.
      *
      * It is initialized in the {@link getImageConvertExecutable()} function.
      *
      * @var string
      */
    private static $imageConvert = null;

    /**
      * Used to store the path of the ImageMagick identify utility.
      *
      * It is initialized in the {@link getImageIdentifyExecutable()} function.
      *
      * @var string
      */
    private static $imageIdentify = null;

    /**
      * Used to store the operating system.
      *
      * It is initialized in the {@link os()} function.
      *
      * @var string
      */
    private static $os = null;

    /**
     * Determines if hardlinks are supported.
     *
     * @return bool
     */
    public static function supportsLink()
    {
        return function_exists( 'link' );
    }

    /**
     * Determines if symlinks are supported.
     *
     * @return bool
     */
    public static function supportsSymLink()
    {
        return function_exists( 'symlink' );
    }

    /**
     * Determines if posix uids are supported.
     *
     * @return bool
     */
    public static function supportsUserId()
    {
        return function_exists( 'posix_getpwuid' );
    }

    /**
     * Determines if the ImageMagick convert utility is installed.
     *
     * @return bool
     */
    public static function hasImageConvert()
    {
        return !is_null( self::getImageConvertExecutable() );
    }

    /**
     * Returns the path to the ImageMagick convert utility.
     *
     * On Linux, Unix,... it will return something like: /usr/bin/convert
     * On Windows it will return something like: C:\Windows\System32\convert.exe
     *
     * @return string
     */
    public static function getImageConvertExecutable()
    {
        if ( !is_null( self::$imageConvert ) )
        {
            return self::$imageConvert;
        }
        return ( self::$imageConvert = self::findExecutableInPath( 'convert' ) );
    }

    /**
     * Determines if the ImageMagick identify utility is installed.
     *
     * @return bool
     */
    public static function hasImageIdentify()
    {
        return !is_null( self::getImageIdentifyExecutable() );
    }

    /**
     * Returns the path to the ImageMagick identify utility.
     *
     * On Linux, Unix,... it will return something like: /usr/bin/identify
     * On Windows it will return something like: C:\Windows\System32\identify.exe
     *
     * @return string
     */
    public static function getImageIdentifyExecutable()
    {
        if ( !is_null( self::$imageIdentify ) )
        {
            return self::$imageIdentify;
        }
        return ( self::$imageIdentify = self::findExecutableInPath( 'identify' ) );
    }

    /**
     * Determines if the specified extension is loaded.
     *
     * If $version is specified, the specified extension will be tested also
     * against the version of the loaded extension.
     *
     * Examples:
     * <code>
     * hasExtensionSupport( 'gzip' );
     * </code>
     * will return true if gzip extension is loaded.
     *
     * <code>
     * hasExtensionSupport( 'pdo_mysql', '1.0.2' );
     * </code>
     * will return true if pdo_mysql extension is loaded and its version is at least 1.0.2.
     *
     * @param string $extension
     * @param string $version
     * @return bool
     */
    public static function hasExtensionSupport( $extension, $version = null )
    {
        if ( is_null( $version ) )
        {
            return extension_loaded( $extension );
        }
        return extension_loaded( $extension ) && version_compare( phpversion( $extension ), $version, ">=" ) ;
    }

    /**
     * Determines if the specified function is available.
     *
     * Examples:
     * <code>
     * ezcBaseFeatures::hasFunction( 'imagepstext' );
     * </code>
     * will return true if support for Type 1 fonts is available with your GD
     * extension.
     *
     * @param string $functionName
     * @return bool
     */
    public static function hasFunction( $functionName )
    {
        return function_exists( $functionName );
    }

    /**
     * Returns if a given class exists.
     * Checks for a given class name and returns if this class exists or not.
     * Catches the ezcBaseAutoloadException and returns false, if it was thrown.
     *
     * @param string $className The class to check for.
     * @param bool $autoload True to use __autoload(), otherwise false.
     * @return bool True if the class exists. Otherwise false.
     */
    public static function classExists( $className, $autoload = true )
    {
        try
        {
            if ( class_exists( $className, $autoload ) )
            {
                return true;
            }
            return false;
        }
        catch ( ezcBaseAutoloadException $e )
        {
            return false;
        }
    }

    /**
     * Returns the operating system on which PHP is running.
     *
     * This method returns a sanitized form of the OS name, example
     * return values are "Windows", "Mac", "Linux" and "FreeBSD". In
     * all other cases it returns the value of the internal PHP constant
     * PHP_OS.
     *
     * @return string
     */
    public static function os()
    {
        if ( is_null( self::$os ) )
        {
            $uname = php_uname( 's' );
            if ( substr( $uname, 0, 7 ) == 'Windows' )
            {
                self::$os = 'Windows';
            }
            elseif ( substr( $uname, 0, 3 ) == 'Mac' )
            {
                self::$os = 'Mac';
            }
            elseif ( strtolower( $uname ) == 'linux' )
            {
                self::$os = 'Linux';
            }
            elseif ( strtolower( substr( $uname, 0, 7 ) ) == 'freebsd' )
            {
                self::$os = 'FreeBSD';
            }
            else
            {
                self::$os = PHP_OS;
            }
        }
        return self::$os;
    }

    /**
     * Returns the path of the specified executable, if it can be found in the system's path.
     *
     * It scans the PATH enviroment variable based on the OS to find the
     * $fileName. For Windows, the path is with \, not /.  If $fileName is not
     * found, it returns null.
     *
     * @todo consider using getenv( 'PATH' ) instead of $_ENV['PATH']
     *       (but that won't work under IIS)
     *
     * @param string $fileName
     * @return string
     */
    public static function findExecutableInPath( $fileName )
    {
        if ( array_key_exists( 'PATH', $_ENV ) )
        {
            $envPath = trim( $_ENV['PATH'] );
        }
        else if ( ( $envPath = getenv( 'PATH' ) ) !== false )
        {
            $envPath = trim( $envPath );
        }
        if ( is_string( $envPath ) && strlen( trim( $envPath ) ) == 0 )
        {
            $envPath = false;
        }

        switch ( self::os() )
        {
            case 'Unix':
            case 'FreeBSD':
            case 'Mac':
            case 'MacOS':
            case 'Darwin':
            case 'Linux':
            case 'SunOS':
                if ( $envPath )
                {
                    $dirs = explode( ':', $envPath );
                    foreach ( $dirs as $dir )
                    {
                        // The @-operator is used here mainly to avoid
                        // open_basedir warnings. If open_basedir (or any other
                        // circumstance) prevents the desired file from being
                        // accessed, it is fine for file_exists() to return
                        // false, since it is useless for use then, anyway.
                        if ( file_exists( "{$dir}/{$fileName}" ) )
                        {
                            return "{$dir}/{$fileName}";
                        }
                    }
                }
                // The @-operator is used here mainly to avoid open_basedir
                // warnings. If open_basedir (or any other circumstance)
                // prevents the desired file from being accessed, it is fine
                // for file_exists() to return false, since it is useless for
                // use then, anyway.
                elseif ( @file_exists( "./{$fileName}" ) )
                {
                    return $fileName;
                }
                break;
            case 'Windows':
                if ( $envPath )
                {
                    $dirs = explode( ';', $envPath );
                    foreach ( $dirs as $dir )
                    {
                        // The @-operator is used here mainly to avoid
                        // open_basedir warnings. If open_basedir (or any other
                        // circumstance) prevents the desired file from being
                        // accessed, it is fine for file_exists() to return
                        // false, since it is useless for use then, anyway.
                        if ( @file_exists( "{$dir}\\{$fileName}.exe" ) )
                        {
                            return "{$dir}\\{$fileName}.exe";
                        }
                    }
                }
                // The @-operator is used here mainly to avoid open_basedir
                // warnings. If open_basedir (or any other circumstance)
                // prevents the desired file from being accessed, it is fine
                // for file_exists() to return false, since it is useless for
                // use then, anyway.
                elseif ( @file_exists( "{$fileName}.exe" ) )
                {
                    return "{$fileName}.exe";
                }
                break;
        }
        return null;
    }

    /**
     * Reset the cached information. 
     * 
     * @return void
     * @access private
     * @ignore
     */
    public static function reset()
    {
        self::$imageIdentify = null;
        self::$imageConvert  = null;
        self::$os            = null;
    }
}
?>
PK��Zl��VV%ezc/Base/exceptions/setting_value.phpnu�[���<?php
/**
 * File containing the ezcBaseSettingValueException class.
 *
 * @package Base
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */
/**
 * ezcBaseSettingValueExeception is thrown whenever a value to a class'
 * configuration option is either of the wrong type, or has a wrong value.
 *
 * @package Base
 * @version 1.8
 */
class ezcBaseSettingValueException extends ezcBaseException
{
    /**
     * Constructs a new ezcBaseConfigException
     *
     * @param string  $settingName The name of the setting where something was
     *                wrong with.
     * @param mixed   $value The value that the option was tried to be set too.
     * @param string  $expectedValue A string explaining the allowed type and value range.
     */
    function __construct( $settingName, $value, $expectedValue = null )
    {
        $type = gettype( $value );
        if ( in_array( $type, array( 'array', 'object', 'resource' ) ) )
        {
            $value = serialize( $value );
        }
        $msg = "The value '{$value}' that you were trying to assign to setting '{$settingName}' is invalid.";
        if ( $expectedValue )
        {
            $msg .= " Allowed values are: " . $expectedValue;
        }
        parent::__construct( $msg );
    }
}
?>
PK��ZHDfPEE&ezc/Base/exceptions/file_not_found.phpnu�[���<?php
/**
 * File containing the ezcBaseFileNotFoundException class
 *
 * @package Base
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */
/**
 * ezcBaseFileNotFoundException is thrown when a file or directory was tried to
 * be opened, but did not exist.
 *
 * @package Base
 * @version 1.8
 */
class ezcBaseFileNotFoundException extends ezcBaseFileException
{
    /**
     * Constructs a new ezcBaseFileNotFoundException.
     *
     * @param string $path The name of the file.
     * @param string $type The type of the file.
     * @param string $message A string with extra information.
     */
    function __construct( $path, $type = null, $message = null )
    {
        $typePart = '';
        if ( $type )
        {
            $typePart = "$type ";
        }

        $messagePart = '';
        if ( $message )
        {
            $messagePart = " ($message)";
        }

        parent::__construct( "The {$typePart}file '{$path}' could not be found.$messagePart" );
    }
}
?>
PK��Z����!ezc/Base/exceptions/exception.phpnu�[���<?php
/**
 * File containing the ezcBaseException class.
 *
 * @package Base
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */
/**
 * ezcBaseException is a container from which all other exceptions in the
 * components library descent.
 *
 * @package Base
 * @version 1.8
 */
abstract class ezcBaseException extends Exception
{
    /**
     * Original message, before escaping
     */
    public $originalMessage;

    /**
     * Constructs a new ezcBaseException with $message
     *
     * @param string $message
     */
    public function __construct( $message )
    {
        $this->originalMessage = $message;

        if ( php_sapi_name() == 'cli' )
        {
            parent::__construct( $message );
        }
        else
        {
            parent::__construct( htmlspecialchars( $message ) );
        }
    }
}
?>
PK��Z�@c��*ezc/Base/exceptions/property_not_found.phpnu�[���<?php
/**
 * File containing the ezcBasePropertyNotFoundException class
 *
 * @package Base
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */
/**
 * ezcBasePropertyNotFoundException is thrown whenever a non existent property
 * is accessed in the Components library.
 *
 * @package Base
 * @version 1.8
 */
class ezcBasePropertyNotFoundException extends ezcBaseException
{
    /**
     * Constructs a new ezcBasePropertyNotFoundException for the property
     * $name.
     *
     * @param string $name The name of the property
     */
    function __construct( $name )
    {
        parent::__construct( "No such property name '{$name}'." );
    }
}
?>
PK��Zu�3� ezc/Base/exceptions/whatever.phpnu�[���<?php
/**
 * File containing the ezcBaseWhateverException class
 *
 * @package Base
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */
/**
 * ezcBaseWhateverException is thrown whenever something is so seriously wrong.
 *
 * If this happens it is not possible to repair anything gracefully. An
 * example for this could be, that your eZ components installation has thrown
 * far to many exceptions. Whenever you receive an ezcBaseWhateverException, do
 * not even try to catch it, but forget your project completely and immediately
 * stop coding! ;)
 *
 * @access private
 * @package Base
 * @version 1.8
 */
class ezcBaseWhateverException extends ezcBaseException
{
    /**
     * Constructs a new ezcBaseWhateverException.
     *
     * @param string $what  What happened?
     * @param string $where Where did it happen?
     * @param string $who   Who is responsible?
     * @param string $why   Why did is happen?
     * @access protected
     * @return void
     */
    function __construct( $what, $where, $who, $why )
    {
        parent::__construct( "Thanks for using eZ components. Hope you like it! Greetings from Amos, Derick, El Frederico, Ray and Toby." );
    }
}
?>
PK��Z�b�993ezc/Base/exceptions/functionality_not_supported.phpnu�[���<?php
/**
 * File containing the ezcBaseFunctionalityNotSupportedException class.
 *
 * @package Base
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * The ezcBaseFunctionalityNotSupportedException is thrown when a requested
 * PHP function was not found.
 *
 * @package Base
 * @version 1.8
 */
class ezcBaseFunctionalityNotSupportedException extends ezcBaseException
{
    /**
     * Constructs a new ezcBaseFunctionalityNotSupportedException.
     *
     * @param string $message The message to throw
     * @param string $reason The reason for the exception
     */
    function __construct( $message, $reason )
    {
        parent::__construct( "{$message} is not supported. Reason: {$reason}." );
    }
}
?>
PK��Z��ll.ezc/Base/exceptions/invalid_callback_class.phpnu�[���<?php
/**
 * File containing the ezcBaseInitInvalidCallbackClassException class
 *
 * @package Configuration
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * Exception that is thrown if an invalid class is passed as callback class for
 * delayed object configuration.
 *
 * @package Configuration
 * @version 1.8
 */
class ezcBaseInitInvalidCallbackClassException extends ezcBaseException
{
    /**
     * Constructs a new ezcBaseInitInvalidCallbackClassException for the $callbackClass.
     *
     * @param string $callbackClass
     * @return void
     */
    function __construct( $callbackClass )
    {
        parent::__construct( "Class '{$callbackClass}' does not exist, or does not implement the 'ezcBaseConfigurationInitializer' interface." );
    }
}
?>
PK��Z��!���ezc/Base/exceptions/file_io.phpnu�[���<?php
/**
 * File containing the ezcBaseFileIoException class
 *
 * @package Base
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */
/**
 * ezcBaseFileIoException is thrown when a problem occurs while writing
 * and reading to/from an open file.
 *
 * @package Base
 * @version 1.8
 */
class ezcBaseFileIoException extends ezcBaseFileException
{
    /**
     * Constructs a new ezcBaseFileIoException for the file $path.
     *
     * @param string $path The name of the file.
     * @param int    $mode The mode of the property that is allowed
     *               (ezcBaseFileException::READ, ezcBaseFileException::WRITE,
     *               ezcBaseFileException::EXECUTE or
     *               ezcBaseFileException::CHANGE).
     * @param string $message A string with extra information.
     */
    function __construct( $path, $mode, $message = null )
    {
        switch ( $mode )
        {
            case ezcBaseFileException::READ:
                $operation = "An error occurred while reading from '{$path}'";
                break;
            case ezcBaseFileException::WRITE:
                $operation = "An error occurred while writing to '{$path}'";
                break;
        }

        $messagePart = '';
        if ( $message )
        {
            $messagePart = " ($message)";
        }

        parent::__construct( "$operation.$messagePart" );
    }
}
?>
PK��Z�ӥ�'ezc/Base/exceptions/file_permission.phpnu�[���<?php
/**
 * File containing the ezcBaseFilePermissionException class
 *
 * @package Base
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */
/**
 * ezcBaseFilePermissionException is thrown whenever a permission problem with
 * a file, directory or stream occurred.
 *
 * @package Base
 * @version 1.8
 */
class ezcBaseFilePermissionException extends ezcBaseFileException
{
    /**
     * Constructs a new ezcPropertyPermissionException for the property $name.
     *
     * @param string $path The name of the file.
     * @param int    $mode The mode of the property that is allowed
     *               (ezcBaseFileException::READ, ezcBaseFileException::WRITE,
     *               ezcBaseFileException::EXECUTE,
     *               ezcBaseFileException::CHANGE or
     *               ezcBaseFileException::REMOVE).
     * @param string $message A string with extra information.
     */
    function __construct( $path, $mode, $message = null )
    {
        switch ( $mode )
        {
            case ezcBaseFileException::READ:
                $operation = "The file '{$path}' can not be opened for reading";
                break;
            case ezcBaseFileException::WRITE:
                $operation = "The file '{$path}' can not be opened for writing";
                break;
            case ezcBaseFileException::EXECUTE:
                $operation = "The file '{$path}' can not be executed";
                break;
            case ezcBaseFileException::CHANGE:
                $operation = "The permissions for '{$path}' can not be changed";
                break;
            case ezcBaseFileException::REMOVE:
                $operation = "The file '{$path}' can not be removed";
                break;
            case ( ezcBaseFileException::READ || ezcBaseFileException::WRITE ):
                $operation = "The file '{$path}' can not be opened for reading and writing";
                break;
        }

        $messagePart = '';
        if ( $message )
        {
            $messagePart = " ($message)";
        }

        parent::__construct( "$operation.$messagePart" );
    }
}
?>
PK��Z²Gi��ezc/Base/exceptions/value.phpnu�[���<?php
/**
 * File containing the ezcBaseValueException class.
 *
 * @package Base
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */
/**
 * ezcBaseValueException is thrown whenever the type or value of the given
 * variable is not as expected.
 *
 * @package Base
 * @version 1.8
 */
class ezcBaseValueException extends ezcBaseException
{
    /**
     * Constructs a new ezcBaseValueException on the $name variable.
     *
     * @param string  $settingName The name of the setting where something was
     *                wrong with.
     * @param mixed   $value The value that the option was tried to be set too.
     * @param string  $expectedValue A string explaining the allowed type and value range.
     * @param string  $variableType  What type of variable was tried to be set (setting, argument).
     */
    function __construct( $settingName, $value, $expectedValue = null, $variableType = 'setting' )
    {
        $type = gettype( $value );
        if ( in_array( $type, array( 'array', 'object', 'resource' ) ) )
        {
            $value = serialize( $value );
        }
        $msg = "The value '{$value}' that you were trying to assign to $variableType '{$settingName}' is invalid.";
        if ( $expectedValue )
        {
            $msg .= " Allowed values are: " . $expectedValue . '.';
        }
        parent::__construct( $msg );
    }
}
?>
PK��Z�R�~11+ezc/Base/exceptions/extension_not_found.phpnu�[���<?php
/**
 * File containing the ezcBaseExtensionNotFoundException class
 *
 * @package Base
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * ezcBaseExtensionNotFoundException is thrown when a requested PHP extension was not found.
 *
 * @package Base
 * @version 1.8
 */
class ezcBaseExtensionNotFoundException extends ezcBaseException
{
    /**
     * Constructs a new ezcBaseExtensionNotFoundException.
     *
     * @param string $name The name of the extension
     * @param string $version The version of the extension
     * @param string $message Additional text
     */
    function __construct( $name, $version = null, $message = null )
    {
        if ( $version === null )
        {
            parent::__construct( "The extension '{$name}' could not be found. {$message}" );
        }
        else
        {
            parent::__construct( "The extension '{$name}' with version '{$version}' could not be found. {$message}" );
        }
    }
}
?>
PK��ZՆ��((&ezc/Base/exceptions/file_exception.phpnu�[���<?php
/**
 * File containing the ezcBaseFileException class
 *
 * @package Base
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */
/**
 * ezcBaseFileException is the exception from which all file related exceptions
 * inherit.
 *
 * @package Base
 * @version 1.8
 */
abstract class ezcBaseFileException extends ezcBaseException
{
    const READ    = 1;
    const WRITE   = 2;
    const EXECUTE = 4;
    const CHANGE  = 8;
    const REMOVE  = 16;
}
?>
PK��Z�aa+ezc/Base/exceptions/property_permission.phpnu�[���<?php
/**
 * File containing the ezcPropertyReadOnlyException class
 *
 * @package Base
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */
/**
 * ezcBasePropertyPermissionException is thrown whenever a read-only property
 * is tried to be changed, or when a write-only property was accessed for reading.
 *
 * @package Base
 * @version 1.8
 */
class ezcBasePropertyPermissionException extends ezcBaseException
{
    /**
     * Used when the property is read-only.
     */
    const READ  = 1;

    /**
     * Used when the property is write-only.
     */
    const WRITE = 2;

    /**
     * Constructs a new ezcPropertyPermissionException for the property $name.
     *
     * @param string $name The name of the property.
     * @param int    $mode The mode of the property that is allowed (::READ or ::WRITE).
     */
    function __construct( $name, $mode )
    {
        parent::__construct( "The property '{$name}' is " .
            ( $mode == self::READ ? "read" : "write" ) .
            "-only." );
    }
}
?>
PK��Z^M�@@,ezc/Base/exceptions/invalid_parent_class.phpnu�[���<?php
/**
 * File containing the ezcBaseInvalidParentClassException class
 *
 * @package Base
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */
/**
 * Exception that is thrown if an invalid class is passed as custom class.
 *
 * @package Base
 * @version 1.8
 */
class ezcBaseInvalidParentClassException extends ezcBaseException
{
    /**
     * Constructs an ezcBaseInvalidParentClassException for custom class $customClass
     *
     * @param string $expectedParentClass
     * @param string $customClass
     */
    function __construct( $expectedParentClass, $customClass )
    {
        parent::__construct( "Class '{$customClass}' does not exist, or does not inherit from the '{$expectedParentClass}' class." );
    }
}
?>
PK��Z�{��QQ6ezc/Base/exceptions/double_class_repository_prefix.phpnu�[���<?php
/**
 * File containing the ezcBaseDoubleClassRepositoryPrefixException class
 *
 * @package Base
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */
/**
 * ezcBaseDoubleClassRepositoryPrefixException is thrown whenever you try to
 * register a class repository with a prefix that has already been added
 * before.
 *
 * @package Base
 * @version 1.8
 */
class ezcBaseDoubleClassRepositoryPrefixException extends ezcBaseException
{
    /**
     * Constructs a new ezcBaseDoubleClassRepositoryPrefixException for the
     * $prefix that points to $basePath with autoload directory
     * $autoloadDirPath.
     *
     * @param string $prefix
     * @param string $basePath
     * @param string $autoloadDirPath
     */
    function __construct( $prefix, $basePath, $autoloadDirPath )
    {
        parent::__construct( "The class repository in '{$basePath}' (with autoload dir '{$autoloadDirPath}') can not be added because another class repository already uses the prefix '{$prefix}'." );
    }
}
?>
PK��Z����0ezc/Base/exceptions/init_callback_configured.phpnu�[���<?php
/**
 * File containing the ezcBaseInitCallbackConfiguredException class
 *
 * @package Base
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */
/**
 * ezcBaseInitCallbackConfiguredException is thrown when you try to assign a
 * callback clasname to an identifier, while there is already a callback class
 * configured for this identifier.
 *
 * @package Base
 * @version 1.8
 */
class ezcBaseInitCallbackConfiguredException extends ezcBaseException
{
    /**
     * Constructs a new ezcBaseInitCallbackConfiguredException.
     *
     * @param string $identifier
     * @param string $originalCallbackClassName
     */
    function __construct( $identifier, $originalCallbackClassName )
    {
        parent::__construct( "The '{$identifier}' is already configured with callback class '{$originalCallbackClassName}'." );
    }
}
?>
PK��Z��rr ezc/Base/exceptions/autoload.phpnu�[���<?php
/**
 * File containing the ezcBaseAutoloadException class
 *
 * @package Base
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */
/**
 * ezcBaseAutoloadException is thrown whenever a class can not be found with
 * the autoload mechanism.
 *
 * @package Base
 * @version 1.8
 */
class ezcBaseAutoloadException extends ezcBaseException
{
    /**
     * Constructs a new ezcBaseAutoloadException for the $className that was
     * searched for in the autoload files $fileNames from the directories
     * specified in $dirs.
     *
     * @param string $className
     * @param array(string) $files
     * @param array(ezcBaseRepositoryDirectory) $dirs
     */
    function __construct( $className, $files, $dirs )
    {
        $paths = array();
        foreach ( $dirs as $dir )
        {
            $paths[] = realpath( $dir->autoloadPath );
        }
        parent::__construct( "Could not find a class to file mapping for '{$className}'. Searched for ". implode( ', ', $files ) . " in: " . implode( ', ', $paths ) );
    }
}
?>
PK��Z�ם�OO)ezc/Base/exceptions/setting_not_found.phpnu�[���<?php
/**
 * File containing the ezcBaseSettingNotFoundException class.
 *
 * @package Base
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */
/**
 * ezcBaseSettingNotFoundException is thrown whenever there is a name passed as
 * part as the options array to setOptions() for an option that doesn't exist.
 *
 * @package Base
 * @version 1.8
 */
class ezcBaseSettingNotFoundException extends ezcBaseException
{
    /**
     * Constructs a new ezcBaseSettingNotFoundException for $settingName.
     *
     * @param string $settingName The name of the setting that does not exist.
     */
    function __construct( $settingName )
    {
        parent::__construct( "The setting '{$settingName}' is not a valid configuration setting." );
    }
}
?>
PK��ZUJX��ezc/Base/options.phpnu�[���<?php
/**
 * File containing the ezcBaseOptions class.
 *
 * @package Base
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * Base options class for all eZ components.
 *
 * @package Base
 * @version 1.8
 */
abstract class ezcBaseOptions implements ArrayAccess
{
    /**
     * Container to hold the properties
     *
     * @var array(string=>mixed)
     */
    protected $properties;

    /**
     * Construct a new options object.
     * Options are constructed from an option array by default. The constructor
     * automatically passes the given options to the __set() method to set them
     * in the class.
     *
     * @throws ezcBasePropertyNotFoundException
     *         If trying to access a non existent property.
     * @throws ezcBaseValueException
     *         If the value for a property is out of range.
     * @param array(string=>mixed) $options The initial options to set.
     */
    public function __construct( array $options = array() )
    {
        foreach ( $options as $option => $value )
        {
            $this->__set( $option, $value );
        }
    }

    /**
     * Merge an array into the actual options object.
     * This method merges an array of new options into the actual options object.
     *
     * @throws ezcBasePropertyNotFoundException
     *         If trying to access a non existent property.
     * @throws ezcBaseValueException
     *         If the value for a property is out of range.
     * @param array(string=>mixed) $newOptions The new options.
     */
    public function merge( array $newOptions )
    {
        foreach ( $newOptions as $key => $value )
        {
            $this->__set( $key, $value );
        }
    }

    /**
     * Property get access.
     * Simply returns a given option.
     *
     * @throws ezcBasePropertyNotFoundException
     *         If a the value for the property options is not an instance of
     * @param string $propertyName The name of the option to get.
     * @return mixed The option value.
     * @ignore
     *
     * @throws ezcBasePropertyNotFoundException
     *         if the given property does not exist.
     * @throws ezcBasePropertyPermissionException
     *         if the property to be set is a write-only property.
     */
    public function __get( $propertyName )
    {
        if ( $this->__isset( $propertyName ) === true )
        {
            return $this->properties[$propertyName];
        }
        throw new ezcBasePropertyNotFoundException( $propertyName );
    }

    /**
     * Sets an option.
     * This method is called when an option is set.
     *
     * @param string $propertyName  The name of the option to set.
     * @param mixed $propertyValue The option value.
     * @ignore
     *
     * @throws ezcBasePropertyNotFoundException
     *         if the given property does not exist.
     * @throws ezcBaseValueException
     *         if the value to be assigned to a property is invalid.
     * @throws ezcBasePropertyPermissionException
     *         if the property to be set is a read-only property.
     */
    abstract public function __set( $propertyName, $propertyValue );

    /**
     * Returns if a option exists.
     *
     * @param string $propertyName Option name to check for.
     * @return bool Whether the option exists.
     * @ignore
     */
    public function __isset( $propertyName )
    {
        return array_key_exists( $propertyName, $this->properties );
    }

    /**
     * Returns if an option exists.
     * Allows isset() using ArrayAccess.
     *
     * @param string $propertyName The name of the option to get.
     * @return bool Whether the option exists.
     */
    public function offsetExists( $propertyName )
    {
        return $this->__isset( $propertyName );
    }

    /**
     * Returns an option value.
     * Get an option value by ArrayAccess.
     *
     * @throws ezcBasePropertyNotFoundException
     *         If $propertyName is not a key in the $properties array.
     * @param string $propertyName The name of the option to get.
     * @return mixed The option value.
     */
    public function offsetGet( $propertyName )
    {
        return $this->__get( $propertyName );
    }

    /**
     * Set an option.
     * Sets an option using ArrayAccess.
     *
     * @throws ezcBasePropertyNotFoundException
     *         If $propertyName is not a key in the $properties array.
     * @throws ezcBaseValueException
     *         If the value for a property is out of range.
     * @param string $propertyName The name of the option to set.
     * @param mixed $propertyValue The value for the option.
     */
    public function offsetSet( $propertyName, $propertyValue )
    {
        $this->__set( $propertyName, $propertyValue );
    }

    /**
     * Unset an option.
     * Unsets an option using ArrayAccess.
     *
     * @throws ezcBasePropertyNotFoundException
     *         If $propertyName is not a key in the $properties array.
     * @throws ezcBaseValueException
     *         If a the value for a property is out of range.
     * @param string $propertyName The name of the option to unset.
     */
    public function offsetUnset( $propertyName )
    {
        $this->__set( $propertyName, null );
    }
}
?>
PK��Z��4QEQEezc/Base/file.phpnu�[���<?php
/**
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @version 1.8
 * @filesource
 * @package Base
 */

/**
 * Provides a selection of static independent methods to provide functionality
 * for file and file system handling.
 *
 * This example shows how to use the findRecursive method:
 * <code>
 * <?php
 * // lists all the files under /etc (including subdirectories) that end in
 * // .conf
 * $confFiles = ezcBaseFile::findRecursive( "/etc", array( '@\.conf$@' ) );
 *
 * // lists all autoload files in the components source tree and excludes the
 * // ones in the autoload subdirectory. Statistics are returned in the $stats
 * // variable which is passed by reference.
 * $files = ezcBaseFile::findRecursive(
 *     "/dat/dev/ezcomponents",
 *     array( '@src/.*_autoload.php$@' ),
 *     array( '@/autoload/@' ),
 *     $stats
 * );
 *
 * // lists all binaries in /bin except the ones starting with a "g"
 * $data = ezcBaseFile::findRecursive( "/bin", array(), array( '@^/bin/g@' ) );
 * ?>
 * </code>
 *
 * @package Base
 * @version 1.8
 * @mainclass
 */
class ezcBaseFile
{
    /**
     * This is the callback used by findRecursive to collect data.
     *
     * This callback method works together with walkRecursive() and is called
     * for every file/and or directory. The $context is a callback specific
     * container in which data can be stored and shared between the different
     * calls to the callback function. The walkRecursive() function also passes
     * in the full absolute directory in $sourceDir, the filename in $fileName
     * and file information (such as size, modes, types) as an array as
     * returned by PHP's stat() in the $fileInfo parameter.
     *
     * @param ezcBaseFileFindContext $context
     * @param string $sourceDir
     * @param string $fileName
     * @param array(stat) $fileInfo
     */
    static protected function findRecursiveCallback( ezcBaseFileFindContext $context, $sourceDir, $fileName, $fileInfo )
    {
        // ignore if we have a directory
        if ( $fileInfo['mode'] & 0x4000 )
        {
            return;
        }

        // update the statistics
        $context->elements[] = $sourceDir . DIRECTORY_SEPARATOR . $fileName;
        $context->count++;
        $context->size += $fileInfo['size'];
    }

    /**
     * Walks files and directories recursively on a file system
     *
     * This method walks over a directory and calls a callback from every file
     * and directory it finds. You can use $includeFilters to include only
     * specific files, and $excludeFilters to exclude certain files from being
     * returned. The function will always go into subdirectories even if the
     * entry would not have passed the filters.
     *
     * The callback is passed in the $callback parameter, and the
     * $callbackContext will be send to the callback function/method as
     * parameter so that you can store data in there that persists with all the
     * calls and recursive calls to this method. It's up to the callback method
     * to do something useful with this. The callback function's parameters are
     * in order:
     *
     * <ul>
     * <li>ezcBaseFileFindContext $context</li>
     * <li>string $sourceDir</li>
     * <li>string $fileName</li>
     * <li>array(stat) $fileInfo</li>
     * </ul>
     *
     * See {@see findRecursiveCallback()} for an example of a callback function.
     *
     * Filters are regular expressions and are therefore required to have
     * starting and ending delimiters. The Perl Compatible syntax is used as
     * regular expression language.
     *
     * @param string         $sourceDir
     * @param array(string)  $includeFilters
     * @param array(string)  $excludeFilters
     * @param callback       $callback
     * @param mixed          $callbackContext
     *
     * @throws ezcBaseFileNotFoundException if the $sourceDir directory is not
     *         a directory or does not exist.
     * @throws ezcBaseFilePermissionException if the $sourceDir directory could
     *         not be opened for reading.
     * @return array
     */
    static public function walkRecursive( $sourceDir, array $includeFilters = array(), array $excludeFilters = array(), $callback, &$callbackContext )
    {
        if ( !is_dir( $sourceDir ) )
        {
            throw new ezcBaseFileNotFoundException( $sourceDir, 'directory' );
        }
        $elements = array();
        $d = @dir( $sourceDir );
        if ( !$d )
        {
            throw new ezcBaseFilePermissionException( $sourceDir, ezcBaseFileException::READ );
        }

        while ( ( $entry = $d->read() ) !== false )
        {
            if ( $entry == '.' || $entry == '..' )
            {
                continue;
            }

            $fileInfo = @stat( $sourceDir . DIRECTORY_SEPARATOR . $entry );
            if ( !$fileInfo )
            {
                $fileInfo = array( 'size' => 0, 'mode' => 0 );
            }

            if ( $fileInfo['mode'] & 0x4000 )
            {
                // We need to ignore the Permission exceptions here as it can
                // be normal that a directory can not be accessed. We only need
                // the exception if the top directory could not be read.
                try
                {
                    call_user_func_array( $callback, array( $callbackContext, $sourceDir, $entry, $fileInfo ) );
                    $subList = self::walkRecursive( $sourceDir . DIRECTORY_SEPARATOR . $entry, $includeFilters, $excludeFilters, $callback, $callbackContext );
                    $elements = array_merge( $elements, $subList );
                }
                catch ( ezcBaseFilePermissionException $e )
                {
                }
            }
            else
            {
                // By default a file is included in the return list
                $ok = true;
                // Iterate over the $includeFilters and prohibit the file from
                // being returned when atleast one of them does not match
                foreach ( $includeFilters as $filter )
                {
                    if ( !preg_match( $filter, $sourceDir . DIRECTORY_SEPARATOR . $entry ) )
                    {
                        $ok = false;
                        break;
                    }
                }
                // Iterate over the $excludeFilters and prohibit the file from
                // being returns when atleast one of them matches
                foreach ( $excludeFilters as $filter )
                {
                    if ( preg_match( $filter, $sourceDir . DIRECTORY_SEPARATOR . $entry ) )
                    {
                        $ok = false;
                        break;
                    }
                }

                // If everything's allright, call the callback and add the
                // entry to the elements array
                if ( $ok )
                {
                    call_user_func( $callback, $callbackContext, $sourceDir, $entry, $fileInfo );
                    $elements[] = $sourceDir . DIRECTORY_SEPARATOR . $entry;
                }
            }
        }
        sort( $elements );
        return $elements;
    }

    /**
     * Finds files recursively on a file system
     *
     * With this method you can scan the file system for files. You can use
     * $includeFilters to include only specific files, and $excludeFilters to
     * exclude certain files from being returned. The function will always go
     * into subdirectories even if the entry would not have passed the filters.
     * It uses the {@see walkRecursive()} method to do the actually recursion.
     *
     * Filters are regular expressions and are therefore required to have
     * starting and ending delimiters. The Perl Compatible syntax is used as
     * regular expression language.
     *
     * If you pass an empty array to the $statistics argument, the function
     * will in details about the number of files found into the 'count' array
     * element, and the total filesize in the 'size' array element. Because this
     * argument is passed by reference, you *have* to pass a variable and you
     * can not pass a constant value such as "array()".
     *
     * @param string         $sourceDir
     * @param array(string)  $includeFilters
     * @param array(string)  $excludeFilters
     * @param array()        $statistics
     *
     * @throws ezcBaseFileNotFoundException if the $sourceDir directory is not
     *         a directory or does not exist.
     * @throws ezcBaseFilePermissionException if the $sourceDir directory could
     *         not be opened for reading.
     * @return array
     */
    static public function findRecursive( $sourceDir, array $includeFilters = array(), array $excludeFilters = array(), &$statistics = null )
    {
        // init statistics array
        if ( !is_array( $statistics ) || !array_key_exists( 'size', $statistics ) || !array_key_exists( 'count', $statistics ) )
        {
            $statistics['size']  = 0;
            $statistics['count'] = 0;
        }

        // create the context, and then start walking over the array
        $context = new ezcBaseFileFindContext;
        self::walkRecursive( $sourceDir, $includeFilters, $excludeFilters, array( 'ezcBaseFile', 'findRecursiveCallback' ), $context );

        // collect the statistics
        $statistics['size'] = $context->size;
        $statistics['count'] = $context->count;

        // return the found and pattern-matched files
        sort( $context->elements );
        return $context->elements;
    }


    /**
     * Removes files and directories recursively from a file system
     *
     * This method recursively removes the $directory and all its contents.
     * You should be <b>extremely</b> careful with this method as it has the
     * potential to erase everything that the current user has access to.
     *
     * @param string $directory
     */
    static public function removeRecursive( $directory )
    {
        $sourceDir = realpath( $directory );
        if ( !$sourceDir )
        {
            throw new ezcBaseFileNotFoundException( $directory, 'directory' );
        }
        $d = @dir( $sourceDir );
        if ( !$d )
        {
            throw new ezcBaseFilePermissionException( $directory, ezcBaseFileException::READ );
        }
        // check if we can remove the dir
        $parentDir = realpath( $directory . DIRECTORY_SEPARATOR . '..' );
        if ( !is_writable( $parentDir ) )
        {
            throw new ezcBaseFilePermissionException( $parentDir, ezcBaseFileException::WRITE );
        }
        // loop over contents
        while ( ( $entry = $d->read() ) !== false )
        {
            if ( $entry == '.' || $entry == '..' )
            {
                continue;
            }

            if ( is_dir( $sourceDir . DIRECTORY_SEPARATOR . $entry ) )
            {
                self::removeRecursive( $sourceDir . DIRECTORY_SEPARATOR . $entry );
            }
            else
            {
                if ( @unlink( $sourceDir . DIRECTORY_SEPARATOR . $entry ) === false )
                {
                    throw new ezcBaseFilePermissionException( $directory . DIRECTORY_SEPARATOR . $entry, ezcBaseFileException::REMOVE );
                }
            }
        }
        $d->close();
        rmdir( $sourceDir );
    }

    /**
    * Recursively copy a file or directory.
    *
    * Recursively copy a file or directory in $source to the given
    * destination. If a depth is given, the operation will stop, if the given
    * recursion depth is reached. A depth of -1 means no limit, while a depth
    * of 0 means, that only the current file or directory will be copied,
    * without any recursion.
    *
    * You may optionally define modes used to create files and directories.
    *
    * @throws ezcBaseFileNotFoundException
    *      If the $sourceDir directory is not a directory or does not exist.
    * @throws ezcBaseFilePermissionException
    *      If the $sourceDir directory could not be opened for reading, or the
    *      destination is not writeable.
    *
    * @param string $source
    * @param string $destination
    * @param int $depth
    * @param int $dirMode
    * @param int $fileMode
    * @return void
    */
    static public function copyRecursive( $source, $destination, $depth = -1, $dirMode = 0775, $fileMode = 0664 )
    {
        // Check if source file exists at all.
        if ( !is_file( $source ) && !is_dir( $source ) )
        {
            throw new ezcBaseFileNotFoundException( $source );
        }

        // Destination file should NOT exist
        if ( is_file( $destination ) || is_dir( $destination ) )
        {
            throw new ezcBaseFilePermissionException( $destination, ezcBaseFileException::WRITE );
        }

        // Skip non readable files in source directory
        if ( !is_readable( $source ) )
        {
            return;
        }

        // Copy
        if ( is_dir( $source ) )
        {
            mkdir( $destination );
            // To ignore umask, umask() should not be changed with
            // multithreaded servers...
            chmod( $destination, $dirMode );
        }
        elseif ( is_file( $source ) )
        {
            copy( $source, $destination );
            chmod( $destination, $fileMode );
        }

        if ( ( $depth === 0 ) ||
            ( !is_dir( $source ) ) )
        {
            // Do not recurse (any more)
            return;
        }

        // Recurse
        $dh = opendir( $source );
        while ( ( $file = readdir( $dh ) ) !== false )
        {
            if ( ( $file === '.' ) ||
                ( $file === '..' ) )
            {
                continue;
            }

            self::copyRecursive(
                $source . '/' . $file,
                $destination . '/' . $file,
                $depth - 1, $dirMode, $fileMode
            );
        }
    }

    /**
     * Calculates the relative path of the file/directory '$path' to a given
     * $base path.
     *
     * $path and $base should be fully absolute paths. This function returns the
     * answer of "How do I go from $base to $path". If the $path and $base are
     * the same path, the function returns '.'. This method does not touch the
     * filesystem.
     *
     * @param string $path
     * @param string $base
     * @return string
     */
    static public function calculateRelativePath( $path, $base )
    {
        // Sanitize the paths to use the correct directory separator for the platform
        $path = strtr( $path, '\\/', DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR );
        $base = strtr( $base, '\\/', DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR );

        $base = explode( DIRECTORY_SEPARATOR, $base );
        $path = explode( DIRECTORY_SEPARATOR, $path );

        // If the paths are the same we return
        if ( $base === $path )
        {
            return '.';
        }

        $result = '';

        $pathPart = array_shift( $path );
        $basePart = array_shift( $base );
        while ( $pathPart == $basePart )
        {
            $pathPart = array_shift( $path );
            $basePart = array_shift( $base );
        }

        if ( $pathPart != null )
        {
            array_unshift( $path, $pathPart );
        }
        if ( $basePart != null )
        {
            array_unshift( $base, $basePart );
        }

        $result = str_repeat( '..' . DIRECTORY_SEPARATOR, count( $base ) );
        // prevent a trailing DIRECTORY_SEPARATOR in case there is only a ..
        if ( count( $path ) == 0 )
        {
            $result = substr( $result, 0, -strlen( DIRECTORY_SEPARATOR ) );
        }
        $result .= join( DIRECTORY_SEPARATOR, $path );

        return $result;
    }

    /**
     * Returns whether the passed $path is an absolute path, giving the current $os.
     *
     * With the $os parameter you can tell this function to use the semantics
     * for a different operating system to determine whether a path is
     * absolute. The $os argument defaults to the OS that the script is running
     * on.
     *
     * @param string $path
     * @param string $os
     * @return bool
     */
    public static function isAbsolutePath( $path, $os = null )
    {
        if ( $os === null )
        {
            $os = ezcBaseFeatures::os();
        }

        // Stream wrapper like phar can also be considered absolute paths
        if ( preg_match( '(^[a-z]{3,}://)S', $path ) )
        {
            return true;
        }

        switch ( $os )
        {
            case 'Windows':
                // Sanitize the paths to use the correct directory separator for the platform
                $path = strtr( $path, '\\/', '\\\\' );

                // Absolute paths with drive letter: X:\
                if ( preg_match( '@^[A-Z]:\\\\@i', $path ) )
                {
                    return true;
                }

                // Absolute paths with network paths: \\server\share\
                if ( preg_match( '@^\\\\\\\\[A-Z]+\\\\[^\\\\]@i', $path ) )
                {
                    return true;
                }
                break;
            case 'Mac':
            case 'Linux':
            case 'FreeBSD':
            default:
                // Sanitize the paths to use the correct directory separator for the platform
                $path = strtr( $path, '\\/', '//' );

                if ( $path[0] == '/' )
                {
                    return true;
                }
        }
        return false;
    }
}
?>
PK��ZS]�KKezc/Base/init.phpnu�[���<?php
/**
 * File containing the ezcBaseInit class.
 *
 * @package Base
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */
/**
 * Provides a method to implement delayed initialization of objects.
 *
 * With the methods in this class you can implement callbacks to configure
 * singleton classes. In order to do so you will have to change the
 * getInstance() method of your singleton class to include a call to
 * ezcBaseInit::fetchConfig() as in the following example:
 *
 * <code>
 * <?php
 * public static function getInstance()
 * {
 *     if ( is_null( self::$instance ) )
 *     {
 *         self::$instance = new ezcConfigurationmanager();
 *         ezcBaseInit::fetchConfig( 'ezcInitConfigurationManager', self::$instance );
 *     }
 *     return self::$instance;
 * }
 * ?>
 * </code>
 *
 * You will also need to configure which callback class to call. This you do
 * with the ezcBaseInit::setCallback() method. The following examples sets the
 * callback classname for the configuration identifier
 * 'ezcInitConfigurationManager' to 'cfgConfigurationManager':
 *
 * <code>
 * <?php
 * ezcBaseInit::setCallback( 'ezcInitConfigurationManager', 'cfgConfigurationManager' );
 * ?>
 * </code>
 *
 * The class 'cfgConfigurationManager' is required to implement the
 * ezcBaseConfigurationInitializer interface, which defines only one method:
 * configureObject(). An example on how to implement such a class could be:
 *
 * <code>
 * <?php
 * class cfgConfigurationManager implements ezcBaseConfigurationInitializer
 * {
 *     static public function configureObject( ezcConfigurationManager $cfgManagerObject )
 *     {
 *         $cfgManagerObject->init( 'ezcConfigurationIniReader', 'settings', array( 'useComments' => true ) );
 *     }
 * }
 * ?>
 * </code>
 *
 * Of course the implementation of this callback class is up to the application
 * developer that uses the component (in this example the Configuration
 * component's class ezcConfigurationManager).
 *
 * @package Base
 * @version 1.8
 */
class ezcBaseInit
{
    /**
     * Contains the callback where the identifier is the key of the array, and the classname to callback to the value.
     *
     * @var array(string=>string)
     */
    static private $callbackMap = array();

    /**
     * Adds the classname $callbackClassname as callback for the identifier $identifier.
     *
     * @param string $identifier
     * @param string $callbackClassname
     */
    public static function setCallback( $identifier, $callbackClassname )
    {
        if ( array_key_exists( $identifier, self::$callbackMap ) )
        {
            throw new ezcBaseInitCallbackConfiguredException( $identifier, self::$callbackMap[$identifier] );
        }
        else
        {
            // Check if the passed classname actually exists
            if ( !ezcBaseFeatures::classExists( $callbackClassname, true ) )
            {
                throw new ezcBaseInitInvalidCallbackClassException( $callbackClassname );
            }

            // Check if the passed classname actually implements the interface.
            if ( !in_array( 'ezcBaseConfigurationInitializer', class_implements( $callbackClassname ) ) )
            {
                throw new ezcBaseInitInvalidCallbackClassException( $callbackClassname );
            }

            self::$callbackMap[$identifier] = $callbackClassname;
        }
    }

    /**
     * Uses the configured callback belonging to $identifier to configure the $object.
     *
     * The method will return the return value of the callback method, or null
     * in case there was no callback set for the specified $identifier.
     *
     * @param string $identifier
     * @param object $object
     * @return mixed
     */
    public static function fetchConfig( $identifier, $object )
    {
        if ( isset( self::$callbackMap[$identifier] ) )
        {
            $callbackClassname = self::$callbackMap[$identifier];
            return call_user_func( array( $callbackClassname, 'configureObject' ), $object );
        }
        return null;
    }
}
?>
PK��Z��/��#ezc/Base/interfaces/persistable.phpnu�[���<?php
/**
 * File containing the ezcBasePersistable interface
 *
 * @package Base
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */
/**
 * This class provides the interface that classes need to implement to be able
 * to be used by the PersistentObject and Search components.
 *
 * @package Base
 * @version 1.8
 */
interface ezcBasePersistable
{
    /**
     * The constructor for the object needs to be able to accept no arguments.
     *
     * The data is later set through the setState() method.
     */
    public function __construct();

    /**
     * Returns all the object's properties so that they can be stored or indexed.
     *
     * @return array(string=>mixed)
     */
    public function getState();

    /**
     * Accepts an array containing data for one or more of the class' properties.
     *
     * @param array $properties
     */
    public function setState( array $properties );
}
?>
PK��Z4�ei��"ezc/Base/interfaces/exportable.phpnu�[���<?php
/**
 * File containing the ezcBaseExportable interface.
 *
 * @package Base
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */
/**
 * Interface for class of which instances can be exported using var_export().
 *
 * In some components, objects can be stored (e.g. to disc) using the var_export() 
 * function. To ensure that an object supports proper importing again, this 
 * interface should be implemented.
 *
 * @see var_export()
 */
interface ezcBaseExportable
{
    /**
     * Returns an instance of the desired object, initialized from $state.
     *
     * This method must return a new instance of the class it is implemented 
     * in, which has its properties set from the given $state array.
     *
     * @param array $state 
     * @return object
     */
    public static function __set_state( array $state );
}

?>
PK��ZPBs|��1ezc/Base/interfaces/configuration_initializer.phpnu�[���<?php
/**
 * File containing the ezcBaseConfigurationInitializer class
 *
 * @package Base
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */
/**
 * This class provides the interface that classes need to implement to act as
 * an callback initializer class to work with the delayed initialization
 * mechanism.
 *
 * @package Base
 * @version 1.8
 */
interface ezcBaseConfigurationInitializer
{
    /**
     * Configures the given object, or returns the proper object depending on
     * the given identifier.
     *
     * In case a string identifier was given, it should return the associated
     * object, in case an object was given the method should return null.
     *
     * @param string|object $object
     * @return mixed
     */
    static public function configureObject( $object );
}
?>
PK��Z�%�NNezc/Base/base_autoload.phpnu�[���<?php
/**
 * Autoloader definition for the Base component.
 *
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @version 1.8
 * @filesource
 * @package Base
 */

return array(
    'ezcBaseException'                            => 'Base/exceptions/exception.php',
    'ezcBaseFileException'                        => 'Base/exceptions/file_exception.php',
    'ezcBaseAutoloadException'                    => 'Base/exceptions/autoload.php',
    'ezcBaseDoubleClassRepositoryPrefixException' => 'Base/exceptions/double_class_repository_prefix.php',
    'ezcBaseExtensionNotFoundException'           => 'Base/exceptions/extension_not_found.php',
    'ezcBaseFileIoException'                      => 'Base/exceptions/file_io.php',
    'ezcBaseFileNotFoundException'                => 'Base/exceptions/file_not_found.php',
    'ezcBaseFilePermissionException'              => 'Base/exceptions/file_permission.php',
    'ezcBaseFunctionalityNotSupportedException'   => 'Base/exceptions/functionality_not_supported.php',
    'ezcBaseInitCallbackConfiguredException'      => 'Base/exceptions/init_callback_configured.php',
    'ezcBaseInitInvalidCallbackClassException'    => 'Base/exceptions/invalid_callback_class.php',
    'ezcBaseInvalidParentClassException'          => 'Base/exceptions/invalid_parent_class.php',
    'ezcBasePropertyNotFoundException'            => 'Base/exceptions/property_not_found.php',
    'ezcBasePropertyPermissionException'          => 'Base/exceptions/property_permission.php',
    'ezcBaseSettingNotFoundException'             => 'Base/exceptions/setting_not_found.php',
    'ezcBaseSettingValueException'                => 'Base/exceptions/setting_value.php',
    'ezcBaseValueException'                       => 'Base/exceptions/value.php',
    'ezcBaseWhateverException'                    => 'Base/exceptions/whatever.php',
    'ezcBaseOptions'                              => 'Base/options.php',
    'ezcBaseStruct'                               => 'Base/struct.php',
    'ezcBase'                                     => 'Base/base.php',
    'ezcBaseAutoloadOptions'                      => 'Base/options/autoload.php',
    'ezcBaseConfigurationInitializer'             => 'Base/interfaces/configuration_initializer.php',
    'ezcBaseExportable'                           => 'Base/interfaces/exportable.php',
    'ezcBaseFeatures'                             => 'Base/features.php',
    'ezcBaseFile'                                 => 'Base/file.php',
    'ezcBaseFileFindContext'                      => 'Base/structs/file_find_context.php',
    'ezcBaseInit'                                 => 'Base/init.php',
    'ezcBaseMetaData'                             => 'Base/metadata.php',
    'ezcBaseMetaDataPearReader'                   => 'Base/metadata/pear.php',
    'ezcBaseMetaDataTarballReader'                => 'Base/metadata/tarball.php',
    'ezcBasePersistable'                          => 'Base/interfaces/persistable.php',
    'ezcBaseRepositoryDirectory'                  => 'Base/structs/repository_directory.php',
);
?>
PK��Z�xr44ezc/Base/struct.phpnu�[���<?php
/**
 * File containing the ezcBaseStruct.
 *
 * @package Base
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * Base class for all struct classes.
 *
 * @package Base
 * @version 1.8
 */
class ezcBaseStruct
{
    /**
     * Throws a BasePropertyNotFound exception.
     *
     * @param string $name
     * @param mixed $value
     * @ignore
     */
    final public function __set( $name, $value )
    {
        throw new ezcBasePropertyNotFoundException( $name );
    }

    /**
     * Throws a BasePropertyNotFound exception.
     *
     * @param string $name
     * @ignore
     */
    final public function __get( $name )
    {
        throw new ezcBasePropertyNotFoundException( $name );
    }
}
?>
PK��Z��<�V�Vezc/Base/base.phpnu�[���<?php
/**
 * File containing the ezcBase class.
 *
 * @package Base
 * @version 1.8
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */
/**
 * Base class implements the methods needed to use the eZ components.
 *
 * @package Base
 * @version 1.8
 * @mainclass
 */
class ezcBase
{
    /**
     * Used for dependency checking, to check for a PHP extension.
     */
    const DEP_PHP_EXTENSION = "extension";

    /**
     * Used for dependency checking, to check for a PHP version.
     */
    const DEP_PHP_VERSION = "version";

    /**
     * Denotes the production mode
     */
    const MODE_PRODUCTION = 0;

    /**
     * Denotes the development mode
     */
    const MODE_DEVELOPMENT = 1;

    /**
     * Indirectly it determines the path where the autoloads are stored.
     *
     * @var string
     */
    private static $libraryMode = "pear";

    /**
     * Contains the current working directory, which is used when the
     * $libraryMode is set to "custom".
     *
     * @var string
     */
    private static $currentWorkingDirectory = null;

    /**
     * The full path to the autoload directory.
     *
     * @var string
     */
    protected static $packageDir = null;

    /**
     * Contains which development mode is used. It's "development" by default,
     * because of backwards compatibility reasons.
     */
    private static $runMode = self::MODE_DEVELOPMENT;

    /**
     * Stores info with additional paths where autoload files and classes for
     * autoloading could be found. Each item of $repositoryDirs looks like
     * array( autoloadFileDir, baseDir ). The array key is the prefix belonging
     * to classes within that repository - if provided when calling
     * addClassRepository(), or an autoincrement integer otherwise.
     *
     * @var array(string=>array)
     */
    protected static $repositoryDirs = array();

    /**
     * This variable stores all the elements from the autoload arrays. When a
     * new autoload file is loaded, their files are added to this array.
     *
     * @var array(string=>string)
     */
    protected static $autoloadArray = array();

    /**
     * This variable stores all the elements from the autoload arrays for
     * external repositories. When a new autoload file is loaded, their files
     * are added to this array.
     *
     * @var array(string=>string)
     */
    protected static $externalAutoloadArray = array();

    /**
     * Options for the ezcBase class.
     *
     * @var ezcBaseOptions
     */
    static private $options;

    /**
     * Associates an option object with this static class.
     *
     * @param ezcBaseAutoloadOptions $options
     */
    static public function setOptions( ezcBaseAutoloadOptions $options )
    {
        self::$options = $options;
    }

    /**
     * Tries to autoload the given className. If the className could be found
     * this method returns true, otherwise false.
     *
     * This class caches the requested class names (including the ones who
     * failed to load).
     *
     * @param string $className  The name of the class that should be loaded.
     *
     * @return bool
     */
    public static function autoload( $className )
    {
        ezcBase::setPackageDir();

        // Check whether the classname is already in the cached autoloadArray.
        if ( array_key_exists( $className, ezcBase::$autoloadArray ) )
        {
            // Is it registered as 'unloadable'?
            if ( ezcBase::$autoloadArray[$className] == false )
            {
                return false;
            }
            ezcBase::loadFile( ezcBase::$autoloadArray[$className] );

            return true;
        }

        // Check whether the classname is already in the cached autoloadArray
        // for external repositories.
        if ( array_key_exists( $className, ezcBase::$externalAutoloadArray ) )
        {
            // Is it registered as 'unloadable'?
            if ( ezcBase::$externalAutoloadArray[$className] == false )
            {
                return false;
            }
            ezcBase::loadExternalFile( ezcBase::$externalAutoloadArray[$className] );

            return true;
        }

        // Not cached, so load the autoload from the package.
        // Matches the first and optionally the second 'word' from the classname.
        $fileNames = array();
        if ( preg_match( "/^([a-z0-9]*)([A-Z][a-z0-9]*)?([A-Z][a-z0-9]*)?/", $className, $matches ) !== false )
        {
            $autoloadFile = "";
            // Try to match with both names, if available.
            switch ( sizeof( $matches ) )
            {
                case 4:
                    // check for x_y_autoload.php
                    $autoloadFile = strtolower( "{$matches[2]}_{$matches[3]}_autoload.php" );
                    $fileNames[] = $autoloadFile;
                    if ( ezcBase::requireFile( $autoloadFile, $className, $matches[1] ) )
                    {
                        return true;
                    }
                    // break intentionally missing.

                case 3:
                    // check for x_autoload.php
                    $autoloadFile = strtolower( "{$matches[2]}_autoload.php" );
                    $fileNames[] = $autoloadFile;
                    if ( ezcBase::requireFile( $autoloadFile, $className, $matches[1] ) )
                    {
                        return true;
                    }
                    // break intentionally missing.

                case 2:
                    // check for autoload.php
                    $autoloadFile = 'autoload.php';
                    $fileNames[] = $autoloadFile;
                    if ( ezcBase::requireFile( $autoloadFile, $className, $matches[1] ) )
                    {
                        return true;
                    }
                    break;
            }

            // Maybe there is another autoload available.
            // Register this classname as false.
            ezcBase::$autoloadArray[$className] = false;
        }

        $path = ezcBase::$packageDir . 'autoload/';
        $realPath = realpath( $path );

        if ( $realPath == '' )
        {
            // Can not be tested, because if this happens, then the autoload
            // environment has not been set-up correctly.
            trigger_error( "Couldn't find autoload directory '$path'", E_USER_ERROR );
        }

        $dirs = self::getRepositoryDirectories();
        if ( ezcBase::$options && ezcBase::$options->debug )
        {
            throw new ezcBaseAutoloadException( $className, $fileNames, $dirs );
        }

        return false;
    }

    /**
     * Sets the current working directory to $directory.
     *
     * @param string $directory
     */
    public static function setWorkingDirectory( $directory )
    {
        self::$libraryMode = 'custom';
        self::$currentWorkingDirectory = $directory;
    }

    /**
     * Figures out the base path of the eZ Components installation.
     *
     * It stores the path that it finds in a static member variable. The path
     * depends on the installation method of the eZ Components. The SVN version
     * has a different path than the PEAR installed version.
     */
    protected static function setPackageDir()
    {
        if ( ezcBase::$packageDir !== null )
        {
            return;
        }

        // Get the path to the components.
        $baseDir = dirname( __FILE__ );

        switch ( ezcBase::$libraryMode )
        {
            case "custom":
                ezcBase::$packageDir = self::$currentWorkingDirectory . '/';
                break;
            case "devel":
            case "tarball":
                ezcBase::$packageDir = $baseDir. "/../../";
                break;
            case "pear";
                ezcBase::$packageDir = $baseDir. "/../";
                break;
        }
    }

    /**
     * Tries to load the autoload array and, if loaded correctly, includes the class.
     *
     * @param string $fileName    Name of the autoload file.
     * @param string $className   Name of the class that should be autoloaded.
     * @param string $prefix      The prefix of the class repository.
     *
     * @return bool  True is returned when the file is correctly loaded.
     *                   Otherwise false is returned.
     */
    protected static function requireFile( $fileName, $className, $prefix )
    {
        $autoloadDir = ezcBase::$packageDir . "autoload/";

        // We need the full path to the fileName. The method file_exists() doesn't
        // automatically check the (php.ini) library paths. Therefore:
        // file_exists( "ezc/autoload/$fileName" ) doesn't work.
        if ( $prefix === 'ezc' && file_exists( "$autoloadDir$fileName" ) )
        {
            $array = require( "$autoloadDir$fileName" );

            if ( is_array( $array) && array_key_exists( $className, $array ) )
            {
                // Add the array to the cache, and include the requested file.
                ezcBase::$autoloadArray = array_merge( ezcBase::$autoloadArray, $array );
                if ( ezcBase::$options !== null && ezcBase::$options->preload && !preg_match( '/Exception$/', $className ) )
                {
                    foreach ( $array as $loadClassName => $file )
                    {
                        if ( $loadClassName !== 'ezcBase' && !class_exists( $loadClassName, false ) && !interface_exists( $loadClassName, false ) && !preg_match( '/Exception$/', $loadClassName ) /*&& !class_exists( $loadClassName, false ) && !interface_exists( $loadClassName, false )*/ )
                        {
                            ezcBase::loadFile( ezcBase::$autoloadArray[$loadClassName] );
                        }
                    }
                }
                else
                {
                    ezcBase::loadFile( ezcBase::$autoloadArray[$className] );
                }
                return true;
            }
        }

        // It is not in components autoload/ dir.
        // try to search in additional dirs.
        foreach ( ezcBase::$repositoryDirs as $repositoryPrefix => $extraDir )
        {
            if ( gettype( $repositoryPrefix ) === 'string' && $repositoryPrefix !== $prefix )
            {
                continue;
            }

            if ( file_exists( $extraDir['autoloadDirPath'] . '/' . $fileName ) )
            {
                $array = array();
                $originalArray = require( $extraDir['autoloadDirPath'] . '/' . $fileName );

                // Building paths.
                // Resulting path to class definition file consists of:
                // path to extra directory with autoload file +
                // basePath provided for current extra directory +
                // path to class definition file stored in autoload file.
                foreach ( $originalArray as $class => $classPath )
                {
                    $array[$class] = $extraDir['basePath'] . '/' . $classPath;
                }

                if ( is_array( $array ) && array_key_exists( $className, $array ) )
                {
                    // Add the array to the cache, and include the requested file.
                    ezcBase::$externalAutoloadArray = array_merge( ezcBase::$externalAutoloadArray, $array );
                    ezcBase::loadExternalFile( ezcBase::$externalAutoloadArray[$className] );
                    return true;
                }
            }
        }

        // Nothing found :-(.
        return false;
    }

    /**
     * Loads, require(), the given file name. If we are in development mode,
     * "/src/" is inserted into the path.
     *
     * @param string $file  The name of the file that should be loaded.
     */
    protected static function loadFile( $file )
    {
        switch ( ezcBase::$libraryMode )
        {
            case "devel":
            case "tarball":
                list( $first, $second ) = explode( '/', $file, 2 );
                $file = $first . "/src/" . $second;
                break;

            case "custom":
                list( $first, $second ) = explode( '/', $file, 2 );
                // Add the "src/" after the package name.
                if ( $first == 'Base' || $first == 'UnitTest' )
                {
                    list( $first, $second ) = explode( '/', $file, 2 );
                    $file = $first . "/src/" . $second;
                }
                else
                {
                    list( $first, $second, $third ) = explode( '/', $file, 3 );
                    $file = $first . '/' . $second . "/src/" . $third;
                }
                break;

            case "pear":
                /* do nothing, it's already correct */
                break;
        }

        if ( file_exists( ezcBase::$packageDir . $file ) )
        {
            require( ezcBase::$packageDir . $file );
        }
        else
        {
            // Can not be tested, because if this happens, then one of the
            // components has a broken autoload file.
            throw new ezcBaseFileNotFoundException( ezcBase::$packageDir.$file );
        }
    }

    /**
     * Loads, require(), the given file name from an external package.
     *
     * @param string $file  The name of the file that should be loaded.
     */
    protected static function loadExternalFile( $file )
    {
        if ( file_exists( $file ) )
        {
            require( $file );
        }
        else
        {
            throw new ezcBaseFileNotFoundException( $file );
        }
    }

    /**
     * Checks for dependencies on PHP versions or extensions
     *
     * The function as called by the $component component checks for the $type
     * dependency. The dependency $type is compared against the $value. The
     * function aborts the script if the dependency is not matched.
     *
     * @param string $component
     * @param int $type
     * @param mixed $value
     */
    public static function checkDependency( $component, $type, $value )
    {
        switch ( $type )
        {
            case self::DEP_PHP_EXTENSION:
                if ( extension_loaded( $value ) )
                {
                    return;
                }
                else
                {
                    // Can not be tested as it would abort the PHP script.
                    die( "\nThe {$component} component depends on the default PHP extension '{$value}', which is not loaded.\n" );
                }
                break;

            case self::DEP_PHP_VERSION:
                $phpVersion = phpversion();
                if ( version_compare( $phpVersion, $value, '>=' ) )
                {
                    return;
                }
                else
                {
                    // Can not be tested as it would abort the PHP script.
                    die( "\nThe {$component} component depends on the PHP version '{$value}', but the current version is '{$phpVersion}'.\n" );
                }
                break;
        }
    }

    /**
     * Return the list of directories that contain class repositories.
     *
     * The path to the eZ components directory is always included in the result
     * array. Each element in the returned array has the format of:
     * packageDirectory => ezcBaseRepositoryDirectory
     *
     * @return array(string=>ezcBaseRepositoryDirectory)
     */
    public static function getRepositoryDirectories()
    {
        $autoloadDirs = array();
        ezcBase::setPackageDir();
        $repositoryDir = self::$currentWorkingDirectory ? self::$currentWorkingDirectory : ( realpath( dirname( __FILE__ ) . '/../../' ) );
        $autoloadDirs['ezc'] = new ezcBaseRepositoryDirectory( ezcBaseRepositoryDirectory::TYPE_INTERNAL, $repositoryDir, $repositoryDir . "/autoload" );

        foreach ( ezcBase::$repositoryDirs as $extraDirKey => $extraDirArray )
        {
            $repositoryDirectory = new ezcBaseRepositoryDirectory( ezcBaseRepositoryDirectory::TYPE_EXTERNAL, realpath( $extraDirArray['basePath'] ), realpath( $extraDirArray['autoloadDirPath'] ) );
            $autoloadDirs[$extraDirKey] = $repositoryDirectory;
        }

        return $autoloadDirs;
    }

    /**
     * Adds an additional class repository.
     *
     * Used for adding class repositoryies outside the eZ components to be
     * loaded by the autoload system.
     *
     * This function takes two arguments: $basePath is the base path for the
     * whole class repository and $autoloadDirPath the path where autoload
     * files for this repository are found. The paths in the autoload files are
     * relative to the package directory as specified by the $basePath
     * argument. I.e. class definition file will be searched at location
     * $basePath + path to the class definition file as stored in the autoload
     * file.
     *
     * addClassRepository() should be called somewhere in code before external classes
     * are used.
     *
     * Example:
     * Take the following facts:
     * <ul>
     * <li>there is a class repository stored in the directory "./repos"</li>
     * <li>autoload files for that repository are stored in "./repos/autoloads"</li>
     * <li>there are two components in this repository: "Me" and "You"</li>
     * <li>the "Me" component has the classes "erMyClass1" and "erMyClass2"</li>
     * <li>the "You" component has the classes "erYourClass1" and "erYourClass2"</li>
     * </ul>
     *
     * In this case you would need to create the following files in
     * "./repos/autoloads". Please note that the part before _autoload.php in
     * the filename is the first part of the <b>classname</b>, not considering
     * the all lower-case letter prefix.
     *
     * "my_autoload.php":
     * <code>
     * <?php
     *     return array (
     *       'erMyClass1' => 'Me/myclass1.php',
     *       'erMyClass2' => 'Me/myclass2.php',
     *     );
     * ?>
     * </code>
     *
     * "your_autoload.php":
     * <code>
     * <?php
     *     return array (
     *       'erYourClass1' => 'You/yourclass1.php',
     *       'erYourClass2' => 'You/yourclass2.php',
     *     );
     * ?>
     * </code>
     *
     * The directory structure for the external repository is then:
     * <code>
     * ./repos/autoloads/my_autoload.php
     * ./repos/autoloads/you_autoload.php
     * ./repos/Me/myclass1.php
     * ./repos/Me/myclass2.php
     * ./repos/You/yourclass1.php
     * ./repos/You/yourclass2.php
     * </code>
     *
     * To use this repository with the autoload mechanism you have to use the
     * following code:
     * <code>
     * <?php
     * ezcBase::addClassRepository( './repos', './repos/autoloads' );
     * $myVar = new erMyClass2();
     * ?>
     * </code>
     *
     * @throws ezcBaseFileNotFoundException if $autoloadDirPath or $basePath do not exist.
     * @param string $basePath
     * @param string $autoloadDirPath
     * @param string $prefix
     */
    public static function addClassRepository( $basePath, $autoloadDirPath = null, $prefix = null )
    {
        // check if base path exists
        if ( !is_dir( $basePath ) )
        {
            throw new ezcBaseFileNotFoundException( $basePath, 'base directory' );
        }

        // calculate autoload path if it wasn't given
        if ( is_null( $autoloadDirPath ) )
        {
            $autoloadDirPath = $basePath . '/autoload';
        }

        // check if autoload dir exists
        if ( !is_dir( $autoloadDirPath ) )
        {
            throw new ezcBaseFileNotFoundException( $autoloadDirPath, 'autoload directory' );
        }

        // add info to $repositoryDirs
        if ( $prefix === null )
        {
            $array = array( 'basePath' => $basePath, 'autoloadDirPath' => $autoloadDirPath );

            // add info to the list of extra dirs
            ezcBase::$repositoryDirs[] = $array;
        }
        else
        {
            if ( array_key_exists( $prefix, ezcBase::$repositoryDirs ) )
            {
                throw new ezcBaseDoubleClassRepositoryPrefixException( $prefix, $basePath, $autoloadDirPath );
            }

            // add info to the list of extra dirs, and use the prefix to identify the new repository.
            ezcBase::$repositoryDirs[$prefix] = array( 'basePath' => $basePath, 'autoloadDirPath' => $autoloadDirPath );
        }
    }

    /**
     * Returns the base path of the eZ Components installation
     *
     * This method returns the base path, including a trailing directory
     * separator.
     *
     * @return string
     */
    public static function getInstallationPath()
    {
        self::setPackageDir();

        $path = realpath( self::$packageDir );
        if ( substr( $path, -1 ) !== DIRECTORY_SEPARATOR )
        {
            $path .= DIRECTORY_SEPARATOR;
        }
        return $path;
    }

    /**
     * Sets the development mode to the one specified.
     *
     * @param int $runMode
     */
    public static function setRunMode( $runMode )
    {
        if ( !in_array( $runMode, array( ezcBase::MODE_PRODUCTION, ezcBase::MODE_DEVELOPMENT ) ) )
        {
            throw new ezcBaseValueException( 'runMode', $runMode, 'ezcBase::MODE_PRODUCTION or ezcBase::MODE_DEVELOPMENT' );
        }

        self::$runMode = $runMode;
    }

    /**
     * Returns the current development mode.
     *
     * @return int
     */
    public static function getRunMode()
    {
        return self::$runMode;
    }

    /**
     * Returns true when we are in development mode.
     *
     * @return bool
     */
    public static function inDevMode()
    {
        return self::$runMode == ezcBase::MODE_DEVELOPMENT;
    }

    /**
     * Returns the installation method
     *
     * Possible return values are 'custom', 'devel', 'tarball' and 'pear'. Only
     * 'tarball' and 'pear' are returned for user-installed versions.
     *
     * @return string
     */
    public static function getInstallMethod()
    {
        return self::$libraryMode;
    }
}
?>
PK��Z�B!)s,s,ezc/ConsoleTools/table/row.phpnu�[���<?php
/**
 * File containing the ezcConsoleTableRow class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */

/**
 * Structure representing a table row in ezcConsoleTable.
 * This class represents a row in a table object. You can access
 * the properties of the row directly, but also access the cells of 
 * the row directly, as if the object was an array (index 0..).
 *
 * <code>
 * // Create new table row
 * $row = new ezcConsoleTableRow();
 * 
 * // Set default format of the row's cells
 * $row->format = 'headline';
 * 
 * // On the fly create the cell no 0
 * $row[0]->content = 'Name';
 * // On the fly create the cell no 1
 * $row[1]->content = 'Cellphone';
 *
 * // Change a setting on cell 0
 * $row[0]->align = ezcConsoleTable::ALIGN_CENTER;
 * 
 * // Iterate through the row's cells.
 * foreach ( $row as $cell )
 * {
 *     var_dump( $cell );
 * }
 *
 * // Set the default align property for all cells in the row
 * $row->align = ezcConsoleTable::ALIGN_CENTER;
 * 
 * </code>
 *
 * This class stores the rows for the {@link ezcConsoleTable} class.
 *
 * @property string $borderFormat
 *           Set the format applied to the borders of this row.  See
 *           {@link ezcConsoleOutput}
 * @property string $format
 *           Format applied to cell contents of cells marked with
 *           format "default" in this row.
 * @property mixed $align
 *           Alignment applied to cells marked with
 *           ezcConsoleTable::ALIGN_DEFAULT.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleTableRow implements Countable, Iterator, ArrayAccess
{
    /**
     * Container to hold the properties
     *
     * @var array(string=>mixed)
     */
    protected $properties;

    /**
     * The cells of the row. 
     * 
     * @var array(ezcConsoleTableCell)
     */
    protected $cells = array();

    /**
     * Create a new ezcConsoleProgressbarRow. 
     * Creates a new ezcConsoleProgressbarRow. 
     *
     * This method takes any number of {@link ezcConsoleTableCell} objects as
     * parameter, which will be added as table cells to the row in their 
     * specified order.
     * 
     * @throws ezcBaseValueException
     *         If a parameter is not of type {@link ezcConsoleTableCell}.
     */
    public function __construct()
    {
        $this->properties['borderFormat'] = 'default';
        $this->properties['format'] = 'default';
        $this->properties['align'] = ezcConsoleTable::ALIGN_DEFAULT;

        if ( func_num_args() > 0 )
        {
            foreach ( func_get_args() as $id => $arg )
            {
                if ( !( $arg instanceof ezcConsoleTableCell ) )
                {
                    throw new ezcBaseValueException( 'Parameter'.$id, $arg, 'ezcConsoleTableCell' );
                }
                $this->cells[] = $arg;
            }
        }
    }

    /**
     * Returns if the given offset exists.
     * This method is part of the ArrayAccess interface to allow access to the
     * data of this object as if it was an array.
     * 
     * @param int $offset The offset to check.
     * @return bool True when the offset exists, otherwise false.
     * 
     * @throws ezcBaseValueException
     *         If a non numeric cell ID is requested.
     */
    public function offsetExists( $offset )
    {
        if ( !is_int( $offset ) || $offset < 0 )
        {
            throw new ezcBaseValueException( 'offset', $offset, 'int >= 0' );
        }
        return isset( $this->cells[$offset] );
    }

    /**
     * Returns the element with the given offset. 
     * This method is part of the ArrayAccess interface to allow access to the
     * data of this object as if it was an array. In case of the
     * ezcConsoleTableRow class this method always returns a valid cell object
     * since it creates them on the fly, if a given item does not exist.
     * 
     * @param int $offset The offset to check.
     * @return ezcConsoleTableCell
     *
     * @throws ezcBaseValueException
     *         If a non numeric cell ID is requested.
     */
    public function offsetGet( $offset )
    {
        if ( !isset( $offset ) )
        {
            $offset = count( $this );
            $this->cells[$offset] = new ezcConsoleTableCell();
        }
        if ( !is_int( $offset ) || $offset < 0 )
        {
            throw new ezcBaseValueException( 'offset', $offset, 'int >= 0' );
        }
        if ( !isset( $this->cells[$offset] ) )
        {
            $this->cells[$offset] = new ezcConsoleTableCell();
        }
        return $this->cells[$offset];
    }

    /**
     * Set the element with the given offset. 
     * This method is part of the ArrayAccess interface to allow access to the
     * data of this object as if it was an array. 
     * 
     * @param int $offset                The offset to assign an item to.
     * @param ezcConsoleTableCell $value The cell to assign.
     * @return void
     *
     * @throws ezcBaseValueException
     *         If a non numeric cell ID is requested.
     * @throws ezcBaseValueException
     *         If the provided value is not of type {@ling ezcConsoleTableCell}.
     */
    public function offsetSet( $offset, $value )
    {
        if ( !( $value instanceof ezcConsoleTableCell ) )
        {
            throw new ezcBaseValueException( 'value', $value, 'ezcConsoleTableCell' );
        }
        if ( !isset( $offset ) )
        {
            $offset = count( $this );
        }
        if ( !is_int( $offset ) || $offset < 0 )
        {
            throw new ezcBaseValueException( 'offset', $offset, 'int >= 0' );
        }
        $this->cells[$offset] = $value;
    }

    /**
     * Unset the element with the given offset. 
     * This method is part of the ArrayAccess interface to allow access to the
     * data of this object as if it was an array. 
     * 
     * @param int $offset The offset to unset the value for.
     * @return void
     * 
     * @throws ezcBaseValueException
     *         If a non numeric cell ID is requested.
     */
    public function offsetUnset( $offset )
    {
        if ( !is_int( $offset ) || $offset < 0 )
        {
            throw new ezcBaseValueException( 'offset', $offset, 'int >= 0' );
        }
        if ( isset( $this->cells[$offset] ) )
        {
            unset( $this->cells[$offset] );
        }
    }

    /**
     * Returns the number of cells in the row.
     * This method is part of the Countable interface to allow the usage of
     * PHP's count() function to check how many cells this row has.
     *
     * @return int Number of cells in this row.
     */
    public function count()
    {
        $keys = array_keys( $this->cells );
        return count( $keys ) > 0 ? ( end( $keys ) + 1 ) : 0;
    }

    /**
     * Returns the currently selected cell.
     * This method is part of the Iterator interface to allow acces to the 
     * cells of this row by iterating over it like an array (e.g. using
     * foreach).
     * 
     * @return ezcConsoleTableCell The currently selected cell.
     */
    public function current()
    {
        return current( $this->cells );
    }

    /**
     * Returns the key of the currently selected cell.
     * This method is part of the Iterator interface to allow acces to the 
     * cells of this row by iterating over it like an array (e.g. using
     * foreach).
     * 
     * @return int The key of the currently selected cell.
     */
    public function key()
    {
        return key( $this->cells );
    }

    /**
     * Returns the next cell and selects it or false on the last cell.
     * This method is part of the Iterator interface to allow acces to the 
     * cells of this row by iterating over it like an array (e.g. using
     * foreach).
     *
     * @return mixed ezcConsoleTableCell if the next cell exists, or false.
     */
    public function next()
    {
        return next( $this->cells );
    }

    /**
     * Selects the very first cell and returns it.
     * This method is part of the Iterator interface to allow acces to the 
     * cells of this row by iterating over it like an array (e.g. using
     * foreach).
     *
     * @return ezcConsoleTableCell The very first cell of this row.
     */
    public function rewind()
    {
        return reset( $this->cells );
    }

    /**
     * Returns if the current cell is valid.
     * This method is part of the Iterator interface to allow acces to the 
     * cells of this row by iterating over it like an array (e.g. using
     * foreach).
     *
     * @return ezcConsoleTableCell The very first cell of this row.
     */
    public function valid()
    {
        return current( $this->cells ) !== false;
    }

    /**
     * Property read access.
     * 
     * @param string $key Name of the property.
     * @return mixed Value of the property or null.
     *
     * @throws ezcBasePropertyNotFoundException
     *         If the the desired property is not found.
     * @ignore
     */
    public function __get( $key )
    {
        if ( isset( $this->properties[$key] ) )
        {
            return $this->properties[$key];
        }
        throw new ezcBasePropertyNotFoundException( $key );
    }

    /**
     * Property write access.
     * 
     * @param string $key Name of the property.
     * @param mixed $val  The value for the property.
     *
     * @throws ezcBaseValueException
     *         If a the value submitted for the align is not in the range of
     *         {@link ezcConsoleTable::ALIGN_LEFT},
     *         {@link ezcConsoleTable::ALIGN_CENTER},
     *         {@link ezcConsoleTable::ALIGN_RIGHT},
     *         {@link ezcConsoleTable::ALIGN_DEFAULT}
     *
     * @ignore
     */
    public function __set( $key, $val )
    {
            
        switch ( $key )
        {
            case 'format':
            case 'borderFormat':
                if ( is_string( $val ) === false || strlen( $val ) < 1 )
                {
                    throw new ezcBaseValueException( $key, $val, "string, length > 0" );
                }
                break;
            case 'align':
                if ( $val !== ezcConsoleTable::ALIGN_LEFT 
                  && $val !== ezcConsoleTable::ALIGN_CENTER 
                  && $val !== ezcConsoleTable::ALIGN_RIGHT 
                  && $val !== ezcConsoleTable::ALIGN_DEFAULT 
                )
                {
                    throw new ezcBaseValueException( $key, $val, 'ezcConsoleTable::ALIGN_DEFAULT, ezcConsoleTable::ALIGN_LEFT, ezcConsoleTable::ALIGN_CENTER, ezcConsoleTable::ALIGN_RIGHT' );
                }
                break;
            default:
                throw new ezcBasePropertyNotFoundException( $key );
        }
        $this->properties[$key] = $val;
    }
 
    /**
     * Property isset access.
     * 
     * @param string $key Name of the property.
     * @return bool True is the property is set, otherwise false.
     * @ignore
     */
    public function __isset( $key )
    {
        switch ( $key )
        {
            case 'format':
            case 'borderFormat':
            case 'align':
                return true;
            default:
                return false;
        }
    }

}

?>
PK��Z'�rw��ezc/ConsoleTools/table/cell.phpnu�[���<?php
/**
 * File containing the ezcConsoleTableCell class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */

/**
 * Representation of a table cell.
 * An object of this class represents a table cell. A cell has a certain content,
 * may apply a format to this data, align the data in the cell and so on.
 *
 * This class stores the cells for the {@link ezcConsoleTable} class.
 *
 * @see ezcConsoleTableRow
 * 
 * @property string $content
 *           Text displayed in the cell.
 * @property string $format
 *           Format applied to the displayed text.
 * @property int $align
 *           Alignment of the text inside the cell.  Must be one of
 *           ezcConsoleTable::ALIGN_ constants. See
 *           {@link ezcConsoleTable::ALIGN_LEFT},
 *           {@link ezcConsoleTable::ALIGN_RIGHT} and
 *           {@link ezcConsoleTable::ALIGN_CENTER}.
 *
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleTableCell
{
    /**
     * Container to hold the properties
     *
     * @var array(string=>mixed)
     */
    protected $properties;

    /**
     * Create a new ezcConsoleProgressbarCell. 
     * Creates a new ezcConsoleProgressbarCell. You can either submit the cell
     * data through the constructor or set them as properties.
     * 
     * @param string $content Content of the cell.
     * @param string $format  Format to display the cell with.
     * @param mixed $align    Alignment of the content in the cell.
     * @return void
     */
    public function __construct( $content = '', $format = 'default', $align = ezcConsoleTable::ALIGN_DEFAULT )
    {
        $this->__set( 'content', $content );
        $this->__set( 'format', $format );
        $this->__set( 'align', $align );
    }

    /**
     * Property read access.
     * 
     * @param string $key Name of the property.
     * @return mixed Value of the property or null.
     *
     * @throws ezcBasePropertyNotFoundException
     *         If the the desired property is not found.
     * @ignore
     */
    public function __get( $key )
    {
        if ( isset( $this->properties[$key] ) )
        {
            return $this->properties[$key];
        }
        throw new ezcBasePropertyNotFoundException( $key );
    }

    /**
     * Property write access.
     * 
     * @param string $key Name of the property.
     * @param mixed $val  The value for the property.
     *
     * @throws ezcBaseValueException
     *         If a the value submitted for the align is not in the range of
     *         {@link ezcConsoleTable::ALIGN_LEFT},
     *         {@link ezcConsoleTable::ALIGN_CENTER},
     *         {@link ezcConsoleTable::ALIGN_RIGHT},
     *         {@link ezcConsoleTable::ALIGN_DEFAULT}
     *
     * @ignore
     */
    public function __set( $key, $val )
    {
            
        switch ( $key )
        {
            case 'content':
                if ( is_string( $val ) === false )
                {
                    throw new ezcBaseValueException( $key, $val, "string" );
                }
                break;
            case 'format':
                if ( is_string( $val ) === false || strlen( $val ) < 1 )
                {
                    throw new ezcBaseValueException( $key, $val, "string, length > 0" );
                }
                break;
            case 'align':
                if ( $val !== ezcConsoleTable::ALIGN_LEFT 
                  && $val !== ezcConsoleTable::ALIGN_CENTER 
                  && $val !== ezcConsoleTable::ALIGN_RIGHT 
                  && $val !== ezcConsoleTable::ALIGN_DEFAULT 
                )
                {
                    throw new ezcBaseValueException( $key,  $val, 'ezcConsoleTable::ALIGN_DEFAULT, ezcConsoleTable::ALIGN_LEFT, ezcConsoleTable::ALIGN_CENTER, ezcConsoleTable::ALIGN_RIGHT' );
                }
                break;
            default:
                throw new ezcBasePropertyNotFoundException( $key );
        }
        $this->properties[$key] = $val;
        return;
    }
 
    /**
     * Property isset access.
     * 
     * @param string $key Name of the property.
     * @return bool True is the property is set, otherwise false.
     * @ignore
     */
    public function __isset( $key )
    {
        switch ( $key )
        {
            case 'content':
            case 'format':
            case 'align':
                return true;
            default:
                break;
        }
        return false;
    }

}

?>
PK��Z��\Ѫ7�7 ezc/ConsoleTools/progressbar.phpnu�[���<?php
/**
 * File containing the ezcConsoleProgressbar class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */

/**
 * Creating and maintaining progress-bars to be printed to the console. 
 *
 * <code>
 * $out = new ezcConsoleOutput();
 * 
 * // Create progress bar itself
 * $progress = new ezcConsoleProgressbar( $out, 100, array( 'step' => 5 ) );
 * 
 * $progress->options->emptyChar = '-';
 * $progress->options->progressChar = '#';
 * $progress->options->formatString = "Uploading file </tmp/foobar.tar.bz2>: %act%/%max% kb [%bar%]";
 * 
 * // Perform actions
 * $i = 0;
 * while ( $i++ < 20 ) 
 * {
 *     // Do whatever you want to indicate progress for
 *     usleep( mt_rand( 20000, 2000000 ) );
 *     // Advance the progressbar by one step ( uploading 5k per run )
 *     $progress->advance();
 * }
 * 
 * // Finish progress bar and jump to next line.
 * $progress->finish();
 * 
 * $out->outputText( "Successfully uploaded </tmp/foobar.tar.bz2>.\n", 'success' );
 * </code>
 * 
 * @property ezcConsoleProgressbarOptions $options
 *           Contains the options for this class.
 * @property int $max
 *           The maximum progress value to reach.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @mainclass
 */
class ezcConsoleProgressbar
{
    /**
     * Container to hold the properties
     *
     * @var array(string=>mixed)
     */
    protected $properties;

    /**
     * Storage for actual values to be replaced in the format string.
     * Actual values are stored here and will be inserted into the bar
     * before printing it.
     * 
     * @var array(string=>string)
     */
    protected $valueMap = array( 
        'bar'       => '',
        'fraction'  => '',
        'act'       => '',
        'max'       => '',
    );

    /**
     * Stores the bar utilization.
     *
     * This array saves how much space a specific part of the bar utilizes to not
     * recalculate those on every step.
     * 
     * @var array(string=>int)
     */
    protected $measures = array( 
        'barSpace'          => 0,
        'fractionSpace'     => 0,
        'actSpace'          => 0,
        'maxSpace'          => 0,
        'fixedCharSpace'    => 0,
    );

    /**
     * The current step the progress bar should show. 
     * 
     * @var int
     */
    protected $currentStep = 0;

    /**
     * The maximum number of steps to go.
     * Calculated once from the settings.
     *
     * @var int
     */
    protected $numSteps = 0;

    /**
     * The ezcConsoleOutput object to use.
     *
     * @var ezcConsoleOutput
     */
    protected $output;

    /**
     * Indicates if the starting point for the bar has been stored.
     * Per default this is false to indicate that no start position has been
     * stored, yet.
     * 
     * @var bool
     */
    protected $started = false;

    /**
     * Tool object to perform multi-byte encoding safe string operations. 
     * 
     * @var ezcConsoleStringTool
     */
    private $stringTool;

    /**
     * Creates a new progress bar.
     *
     * @param ezcConsoleOutput $outHandler   Handler to utilize for output
     * @param int $max                       Maximum value, where progressbar 
     *                                       reaches 100%.
     * @param array(string=>string) $options Options
     *
     * @see ezcConsoleProgressbar::$options
     */
    public function __construct( ezcConsoleOutput $outHandler, $max, array $options = array() )
    {
        $this->output     = $outHandler;
        $this->stringTool = new ezcConsoleStringTool();
        $this->__set( 'max', $max );
        $this->properties['options'] = new ezcConsoleProgressbarOptions( $options );
    }
    
    /**
     * Set new options.
     * This method allows you to change the options of progressbar.
     *  
     * @param ezcConsoleProgresbarOptions $options The options to set.
     *
     * @throws ezcBaseSettingNotFoundException
     *         If you tried to set a non-existent option value.
     * @throws ezcBaseSettingValueException
     *         If the value is not valid for the desired option.
     * @throws ezcBaseValueException
     *         If you submit neither an array nor an instance of 
     *         ezcConsoleProgresbarOptions.
     */
    public function setOptions( $options ) 
    {
        if ( is_array( $options ) ) 
        {
            $this->properties['options']->merge( $options );
        } 
        else if ( $options instanceof ezcConsoleProgressbarOptions ) 
        {
            $this->properties['options'] = $options;
        }
        else
        {
            throw new ezcBaseValueException( "options", $options, "instance of ezcConsoleProgressbarOptions" );
        }
    }

    /**
     * Returns the current options.
     * Returns the options currently set for this progressbar.
     * 
     * @return ezcConsoleProgressbarOptions The current options.
     */
    public function getOptions()
    {
        return $this->properties['options'];
    }

    /**
     * Property read access.
     * 
     * @param string $key Name of the property.
     * @return mixed Value of the property or null.
     *
     * @throws ezcBasePropertyNotFoundException
     *         If the the desired property is not found.
     * @ignore
     */
    public function __get( $key )
    {
        switch ( $key )
        {
            case 'options':
                return $this->properties['options'];
            case 'step':
                // Step is now an option
                return $this->properties['options']->step;
            case 'max':
                return $this->properties[$key];
            default:
                break;
        }
        throw new ezcBasePropertyNotFoundException( $key );
    }

    /**
     * Property write access.
     * 
     * @param string $key Name of the property.
     * @param mixed $val  The value for the property.
     *
     * @throws ezcBasePropertyNotFoundException
     *         If a desired property could not be found.
     * @throws ezcBaseValueException
     *         If a desired property value is out of range.
     * @ignore
     */
    public function __set( $key, $val )
    {
        switch ( $key )
        {
            case 'options':
                if ( !( $val instanceof ezcConsoleProgressbarOptions ) )
                {
                    throw new ezcBaseValueException( 'options',  $val, 'instance of ezcConsoleProgressbarOptions' );
                };
                break;
            case 'max':
                if ( ( !is_int( $val ) && !is_float( $val ) ) || $val < 0 )
                {
                    throw new ezcBaseValueException( $key, $val, 'number >= 0' );
                }
                break;
            case 'step':
                if ( ( !is_int( $val ) && !is_float( $val ) ) || $val < 0 )
                {
                    throw new ezcBaseValueException( $key, $val, 'number >= 0' );
                }
                // Step is now an option.
                $this->properties['options']->step = $val;
                return;
            default:
                throw new ezcBasePropertyNotFoundException( $key );
                break;
        }
        // Changes settings or options, need for recalculating measures
        $this->started = false;
        $this->properties[$key] = $val;
    }
 
    /**
     * Property isset access.
     * 
     * @param string $key Name of the property.
     * @return bool True is the property is set, otherwise false.
     * @ignore
     */
    public function __isset( $key )
    {
        switch ( $key )
        {
            case 'options':
            case 'max':
            case 'step':
                return true;
        }
        return false;
    }

    /**
     * Start the progress bar
     * Starts the progress bar and sticks it to the current line.
     * No output will be done yet. Call {@link ezcConsoleProgressbar::output()}
     * to print the bar.
     * 
     * @return void
     */
    public function start() 
    {
        $this->calculateMeasures();
        $this->output->storePos();
        $this->started = true;
    }

    /**
     * Draw the progress bar.
     * Prints the progress-bar to the screen. If start() has not been called 
     * yet, the current line is used for {@link ezcConsolProgressbar::start()}.
     *
     * @return void
     */
    public function output()
    {
        if ( $this->options->minVerbosity > $this->output->options->verbosityLevel
             || ( $this->options->maxVerbosity !== false 
                  && $this->options->maxVerbosity < $this->output->options->verbosityLevel
                )
           )
        {
            // Do not print progress bar if verbosity level is lower than it's
            // output objects value.
            return;
        }

        if ( $this->started === false )
        {
            $this->start();
        }

        $this->output->restorePos();
        if ( ezcBaseFeatures::os() === "Windows" )
        {
            echo str_repeat( "\x8", $this->options->width );
        }

        $this->generateValues();
        echo $this->insertValues();
    }

    /**
     * Advance the progress bar.
     * Advances the progress bar by $step steps. Redraws the bar by default,
     * using the {@link ezcConsoleProgressbar::output()} method.
     *
     * @param bool  $redraw Whether to redraw the bar immediately.
     * @param int $step     How many steps to advance.
     * @return void
     */
    public function advance( $redraw = true, $step = 1 ) 
    {
        $this->currentStep += $step;
        if ( $redraw === true && $this->currentStep % $this->properties['options']->redrawFrequency === 0 )
        {
            $this->output();
        }
    }

    /**
     * Finish the progress bar.
     * Finishes the bar (jump to 100% if not happened yet,...) and jumps
     * to the next line to allow new output. Also resets the values of the
     * output handler used, if changed.
     *
     * @return void
     */
    public function finish()
    {
        $this->currentStep = $this->numSteps;
        $this->output();
    }

    /**
     * Generate all values to be replaced in the format string. 
     * 
     * @return void
     */
    protected function generateValues()
    {
        // Bar
        $barFilledSpace = ceil( $this->measures['barSpace'] / $this->numSteps * $this->currentStep );
        // Sanitize value if it gets to large by rounding
        $barFilledSpace = $barFilledSpace > $this->measures['barSpace'] ? $this->measures['barSpace'] : $barFilledSpace;
        $bar = $this->stringTool->strPad( 
            $this->stringTool->strPad( 
                $this->properties['options']->progressChar, 
                $barFilledSpace, 
                $this->properties['options']->barChar, 
                STR_PAD_LEFT
            ), 
            $this->measures['barSpace'], 
            $this->properties['options']->emptyChar, 
            STR_PAD_RIGHT 
        );
        $this->valueMap['bar'] = $bar;

        // Fraction
        $fractionVal = sprintf( 
            $this->properties['options']->fractionFormat,
            ( $fractionVal = ( $this->properties['options']->step * $this->currentStep ) / $this->max * 100 ) > 100 ? 100 : $fractionVal
        );
        $this->valueMap['fraction'] = $this->stringTool->strPad( 
            $fractionVal, 
            iconv_strlen( sprintf( $this->properties['options']->fractionFormat, 100 ), 'UTF-8' ),
            ' ',
            STR_PAD_LEFT
        );

        // Act / max
        $actVal = sprintf(
            $this->properties['options']->actFormat,
            ( $actVal = $this->currentStep * $this->properties['options']->step ) > $this->max ? $this->max : $actVal
        );
        $this->valueMap['act'] = $this->stringTool->strPad( 
            $actVal, 
            iconv_strlen( sprintf( $this->properties['options']->actFormat, $this->max ), 'UTF-8' ),
            ' ',
            STR_PAD_LEFT
        );
        $this->valueMap['max'] = sprintf( $this->properties['options']->maxFormat, $this->max );
    }

    /**
     * Insert values into bar format string. 
     * 
     * @return void
     */
    protected function insertValues()
    {
        $bar = $this->properties['options']->formatString;
        foreach ( $this->valueMap as $name => $val )
        {
            $bar = str_replace( "%{$name}%", $val, $bar );
        }
        return $bar;
    }

    /**
     * Calculate several measures necessary to generate a bar. 
     * 
     * @return void
     */
    protected function calculateMeasures()
    {
        // Calc number of steps bar goes through
        $this->numSteps = ( int ) round( $this->max / $this->properties['options']->step );
        // Calculate measures
        $this->measures['fixedCharSpace'] = iconv_strlen( $this->stripEscapeSequences( $this->insertValues() ), 'UTF-8' );
        if ( iconv_strpos( $this->properties['options']->formatString, '%max%', 0, 'UTF-8' ) !== false )
        {
            $this->measures['maxSpace'] = iconv_strlen( sprintf( $this->properties['options']->maxFormat, $this->max ), 'UTF-8' );

        }
        if ( iconv_strpos( $this->properties['options']->formatString, '%act%', 0, 'UTF-8' ) !== false )
        {
            $this->measures['actSpace'] = iconv_strlen( sprintf( $this->properties['options']->actFormat, $this->max ), 'UTF-8' );
        }
        if ( iconv_strpos( $this->properties['options']->formatString, '%fraction%', 0, 'UTF-8' ) !== false )
        {
            $this->measures['fractionSpace'] = iconv_strlen( sprintf( $this->properties['options']->fractionFormat, 100 ), 'UTF-8' );
        }
        $this->measures['barSpace'] = $this->properties['options']->width - array_sum( $this->measures );
    }

    /**
     * Strip all escape sequences from a string to measure it's size correctly. 
     * 
     * @param mixed $str 
     * @return void
     */
    protected function stripEscapeSequences( $str )
    {
        return preg_replace( '/\033\[[0-9a-f;]*m/i', '', $str  );
    }
}
?>
PK��Z	L�^ezc/ConsoleTools/statusbar.phpnu�[���<?php
/**
 * File containing the ezcConsoleStatusbar class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */

/**
 * Creating  and maintaining status-bars to be printed to the console. 
 *
 * <code>
 * // Construction
 * $status = new ezcConsoleStatusbar( new ezcConsoleOutput() );
 *
 * // Set option
 * $status->options['successChar'] = '*';
 *
 * // Run statusbar
 * foreach ( $files as $file )
 * {
 *      $res = $file->upload();
 *      // Add status if form of bool true/false to statusbar.
 *      $status->add( $res ); // $res is true or false
 * }
 *
 * // Retreive and display final statusbar results
 * $msg = $status->getSuccess() . ' succeeded, ' . $status->getFailure() . ' failed.';
 * $out->outputText( "Finished uploading files: $msg\n" );
 * </code>
 *  
 * @property ezcConsoleStatusbarOptions $options
 *           Contains the options for this class.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 * @mainclass
 */
class ezcConsoleStatusbar
{
    /**
     * Container to hold the properties
     *
     * @var array(string=>mixed)
     */
    protected $properties;

    /**
     * The ezcConsoleOutput object to use.
     *
     * @var ezcConsoleOutput
     */
    protected $outputHandler;

    /**
     * Counter for success and failure outputs. 
     * 
     * @var array(bool=>int)
     */
    protected $counter = array( 
        true  => 0,
        false => 0,
    );

    /**
     * Creates a new status bar.
     *
     * @param ezcConsoleOutput $outHandler Handler to utilize for output
     * @param array(string=>string) $options       Options
     *
     * @see ezcConsoleStatusbar::$options
     */
    public function __construct( ezcConsoleOutput $outHandler, array $options = array() )
    {
        $this->outputHandler = $outHandler;
        $this->properties['options'] = new ezcConsoleStatusbarOptions( $options );
    }

    /**
     * Property read access.
     * 
     * @param string $key Name of the property.
     * @return mixed Value of the property or null.
     *
     * @throws ezcBasePropertyNotFoundException
     *         If the the desired property is not found.
     * @ignore
     */
    public function __get( $key )
    {
        switch ( $key )
        {
            case 'options':
                return $this->properties['options'];
                break;
        }
        if ( isset( $this->properties['options']->$key ) )
        {
            return $this->properties['options']->$key;
        }
        throw new ezcBasePropertyNotFoundException( $key );
    }

    /**
     * Set new options.
     * This method allows you to change the options of a statusbar.
     *  
     * @param array(string=>string)|ezcConsoleOutputOptions $options The options to set.
     *
     * @throws ezcBaseSettingNotFoundException
     *         If you tried to set a non-existent option value.
     * @throws ezcBaseSettingValueException
     *         If the value is not valid for the desired option.
     * @throws ezcBaseValueException
     *         If you submit neither an array nor an instance of 
     *         ezcConsoleOutputOptions.
     */
    public function setOptions( $options ) 
    {
        if ( is_array( $options ) ) 
        {
            $this->properties['options']->merge( $options );
        } 
        else if ( $options instanceof ezcConsoleStatusbarOptions ) 
        {
            $this->properties['options'] = $options;
        }
        else
        {
            throw new ezcBaseValueException( "options", $options, "instance of ezcConsoleStatusbarOptions" );
        }
    }

    /**
     * Property write access.
     * 
     * @param string $key Name of the property.
     * @param mixed $val  The value for the property.
     *
     * @throws ezcBasePropertyNotFoundException
     *         If a desired property could not be found.
     * @throws ezcBaseValueException
     *         If a desired property value is out of range.
     * @ignore
     */
    public function __set( $key, $val )
    {
        switch ( $key )
        {
            // Those two are here for BC reasons only, it is proper to
            // use $statusbar->options->successChar instead of just
            // $statusbar->successChar.
            case 'successChar':
            case 'failureChar':
                // No checks necessary here, already performed in
                // ezcConsoleStatusbarOptions
                break;
            case "options":
                if ( ( $val instanceof ezcConsoleStatusbarOptions ) === false )
                {
                    throw new ezcBaseValueException( $key, $val, 'ezcConsoleStatusbarOptions' );
                }
                $this->properties[$key] = $val;
                return;
            default:
                throw new ezcBasePropertyNotFoundException( $key );
        }
        $this->properties['options'][$key] = $val;
    }
 
    /**
     * Property isset access.
     * 
     * @param string $key Name of the property.
     * @return bool True is the property is set, otherwise false.
     * @ignore
     */
    public function __isset( $key )
    {
        return isset( $this->properties['options'][$key] ) || isset( $this->properties[$key] );
    }
    
    /**
     * Returns the current options.
     * Returns the options currently set for this progressbar.
     * 
     * @return ezcConsoleStatusbarOptions The current options.
     */
    public function getOptions()
    {
        return $this->properties['options'];
    }

    /**
     * Add a status to the status bar.
     * Adds a new status to the bar which is printed immediately. If the
     * cursor is currently not at the beginning of a line, it will move to
     * the next line.
     *
     * @param bool $status Print successChar on true, failureChar on false.
     * @return void
     */
    public function add( $status )
    {
        if ( is_bool( $status ) === false )
        {
            trigger_error( 'Unknown status '.var_export( $status, true ).'.', E_USER_WARNING );
            $status = (bool) $status;
        }
        switch ( $status )
        {
            case true:
                $this->outputHandler->outputText( $this->properties['options']['successChar'], 'success' );
                break;

            case false:
                $this->outputHandler->outputText( $this->properties['options']['failureChar'], 'failure' );
                break;
        }
        $this->counter[$status]++;
    }

    /**
     * Reset the state of the status-bar object to its initial one. 
     * 
     * @return void
     */
    public function reset()
    {
        foreach ( $this->counter as $status => $count )
        {
            $this->counter[$status] = 0;
        }
    }

    /**
     * Returns number of successes during the run.
     * Returns the number of success characters printed from this status bar.
     * 
     * @return int Number of successes.
     */
    public function getSuccessCount()
    {
        return $this->counter[true];
    }

    /**
     * Returns number of failures during the run.
     * Returns the number of failure characters printed from this status bar.
     * 
     * @return int Number of failures.
     */
    public function getFailureCount()
    {
        return $this->counter[false];
    }
}
?>
PK��Z5���tt%ezc/ConsoleTools/console_autoload.phpnu�[���<?php
/**
 * Autoloader definition for the ConsoleTools component.
 *
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @version 1.6.1
 * @filesource
 * @package ConsoleTools
 */

return array(
    'ezcConsoleException'                           => 'ConsoleTools/exceptions/exception.php',
    'ezcConsoleArgumentException'                   => 'ConsoleTools/exceptions/argument.php',
    'ezcConsoleOptionException'                     => 'ConsoleTools/exceptions/option.php',
    'ezcConsoleArgumentAlreadyRegisteredException'  => 'ConsoleTools/exceptions/argument_already_registered.php',
    'ezcConsoleArgumentMandatoryViolationException' => 'ConsoleTools/exceptions/argument_mandatory_violation.php',
    'ezcConsoleArgumentTypeViolationException'      => 'ConsoleTools/exceptions/argument_type_violation.php',
    'ezcConsoleDialogAbortException'                => 'ConsoleTools/exceptions/dialog_abort.php',
    'ezcConsoleInvalidOptionNameException'          => 'ConsoleTools/exceptions/invalid_option_name.php',
    'ezcConsoleInvalidOutputTargetException'        => 'ConsoleTools/exceptions/invalid_output_target.php',
    'ezcConsoleNoPositionStoredException'           => 'ConsoleTools/exceptions/no_position_stored.php',
    'ezcConsoleNoValidDialogResultException'        => 'ConsoleTools/exceptions/no_valid_dialog_result.php',
    'ezcConsoleOptionAlreadyRegisteredException'    => 'ConsoleTools/exceptions/option_already_registered.php',
    'ezcConsoleOptionArgumentsViolationException'   => 'ConsoleTools/exceptions/option_arguments_violation.php',
    'ezcConsoleOptionDependencyViolationException'  => 'ConsoleTools/exceptions/option_dependency_violation.php',
    'ezcConsoleOptionExclusionViolationException'   => 'ConsoleTools/exceptions/option_exclusion_violation.php',
    'ezcConsoleOptionMandatoryViolationException'   => 'ConsoleTools/exceptions/option_mandatory_violation.php',
    'ezcConsoleOptionMissingValueException'         => 'ConsoleTools/exceptions/option_missing_value.php',
    'ezcConsoleOptionNoAliasException'              => 'ConsoleTools/exceptions/option_no_alias.php',
    'ezcConsoleOptionNotExistsException'            => 'ConsoleTools/exceptions/option_not_exists.php',
    'ezcConsoleOptionStringNotWellformedException'  => 'ConsoleTools/exceptions/option_string_not_wellformed.php',
    'ezcConsoleOptionTooManyValuesException'        => 'ConsoleTools/exceptions/option_too_many_values.php',
    'ezcConsoleOptionTypeViolationException'        => 'ConsoleTools/exceptions/option_type_violation.php',
    'ezcConsoleTooManyArgumentsException'           => 'ConsoleTools/exceptions/argument_too_many.php',
    'ezcConsoleDialogValidator'                     => 'ConsoleTools/interfaces/dialog_validator.php',
    'ezcConsoleQuestionDialogValidator'             => 'ConsoleTools/interfaces/question_dialog_validator.php',
    'ezcConsoleDialog'                              => 'ConsoleTools/interfaces/dialog.php',
    'ezcConsoleDialogOptions'                       => 'ConsoleTools/options/dialog.php',
    'ezcConsoleInputHelpGenerator'                  => 'ConsoleTools/interfaces/input_help_generator.php',
    'ezcConsoleInputValidator'                      => 'ConsoleTools/interfaces/input_validator.php',
    'ezcConsoleMenuDialogValidator'                 => 'ConsoleTools/interfaces/menu_dialog_validator.php',
    'ezcConsoleQuestionDialogCollectionValidator'   => 'ConsoleTools/dialog/validators/question_dialog_collection.php',
    'ezcConsoleArgument'                            => 'ConsoleTools/input/argument.php',
    'ezcConsoleArguments'                           => 'ConsoleTools/input/arguments.php',
    'ezcConsoleDialogViewer'                        => 'ConsoleTools/dialog_viewer.php',
    'ezcConsoleInput'                               => 'ConsoleTools/input.php',
    'ezcConsoleInputStandardHelpGenerator'          => 'ConsoleTools/input/help_generators/standard.php',
    'ezcConsoleMenuDialog'                          => 'ConsoleTools/dialog/menu_dialog.php',
    'ezcConsoleMenuDialogDefaultValidator'          => 'ConsoleTools/dialog/validators/menu_dialog_default.php',
    'ezcConsoleMenuDialogOptions'                   => 'ConsoleTools/options/menu_dialog.php',
    'ezcConsoleOption'                              => 'ConsoleTools/input/option.php',
    'ezcConsoleOptionRule'                          => 'ConsoleTools/structs/option_rule.php',
    'ezcConsoleOutput'                              => 'ConsoleTools/output.php',
    'ezcConsoleOutputFormat'                        => 'ConsoleTools/structs/output_format.php',
    'ezcConsoleOutputFormats'                       => 'ConsoleTools/structs/output_formats.php',
    'ezcConsoleOutputOptions'                       => 'ConsoleTools/options/output.php',
    'ezcConsoleProgressMonitor'                     => 'ConsoleTools/progressmonitor.php',
    'ezcConsoleProgressMonitorOptions'              => 'ConsoleTools/options/progressmonitor.php',
    'ezcConsoleProgressbar'                         => 'ConsoleTools/progressbar.php',
    'ezcConsoleProgressbarOptions'                  => 'ConsoleTools/options/progressbar.php',
    'ezcConsoleQuestionDialog'                      => 'ConsoleTools/dialog/question_dialog.php',
    'ezcConsoleQuestionDialogMappingValidator'      => 'ConsoleTools/dialog/validators/question_dialog_mapping.php',
    'ezcConsoleQuestionDialogOptions'               => 'ConsoleTools/options/question_dialog.php',
    'ezcConsoleQuestionDialogRegexValidator'        => 'ConsoleTools/dialog/validators/question_dialog_regex.php',
    'ezcConsoleQuestionDialogTypeValidator'         => 'ConsoleTools/dialog/validators/question_dialog_type.php',
    'ezcConsoleStandardInputValidator'              => 'ConsoleTools/input/validators/standard.php',
    'ezcConsoleStatusbar'                           => 'ConsoleTools/statusbar.php',
    'ezcConsoleStatusbarOptions'                    => 'ConsoleTools/options/statusbar.php',
    'ezcConsoleStringTool'                          => 'ConsoleTools/tools/string.php',
    'ezcConsoleTable'                               => 'ConsoleTools/table.php',
    'ezcConsoleTableCell'                           => 'ConsoleTools/table/cell.php',
    'ezcConsoleTableOptions'                        => 'ConsoleTools/options/table.php',
    'ezcConsoleTableRow'                            => 'ConsoleTools/table/row.php',
);
?>
PK��Z���O��!ezc/ConsoleTools/tools/string.phpnu�[���<?php
/**
 * File containing the ezcConsoleStringTool class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */
/**
 * String tool class.
 *
 * Tool class for the ConsoleTools package. Contains multi-byte encoding save
 * string methods.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 * @access private
 */
class ezcConsoleStringTool
{
    /**
     * Binary safe wordwrap() replacement.
     *
     * This method is a multi-byte encoding safe replacement for the PHP
     * function wordwrap(). It mimics exactly the behavior of wordwrap(), but
     * uses iconv_* functions with UTF-8 encoding. The parameters received by
     * this method equal the parameters of {@link http://php.net/wordwrap
     * wordwrap()}. Note: Make sure to only hand UTF-8 encoded content to this
     * method.
     * 
     * @param string $str 
     * @param int $width 
     * @param string $break 
     * @param bool $cut 
     * @return string|false
     */
    public function wordWrap( $str, $width = 75, $break = "\n", $cut = false )
    {
        $strlen   = iconv_strlen( $str, 'UTF-8' );
        $breaklen = iconv_strlen( $break, 'UTF-8' );
        $newtext  = '';

        if ( $strlen === 0 )
        {
            return '';
        }
    
        if ( $breaklen === 0 )
        {
            return false;
        }

        if ( $width === 0 && $cut )
        {
            return false;
        }

        $laststart  = $lastspace = 0;
        $breakstart = iconv_substr( $break, 0, 1, 'UTF-8' );

        for ( $current = 0; $current < $strlen; $current++ )
        {
            $char = iconv_substr( $str, $current, 1, 'UTF-8' );

            // Existing line break, copy line and  start a new one
            if ( $char === $breakstart
                 && $current + $breaklen < $strlen
                 && iconv_substr( $str, $current, $breaklen, 'UTF-8' ) === $break
               )
            {
                $newtext .= iconv_substr( $str, $laststart, $current - $laststart + $breaklen, 'UTF-8' );
                $current += $breaklen - 1;
                $laststart = $lastspace = $current + 1;
            }

            // Keep track of spaces, if line break is necessary, do it
            else if ( $char === ' ' )
            {
                if ( $current - $laststart >= $width )
                {
                    $newtext .= iconv_substr( $str, $laststart, $current - $laststart, 'UTF-8' )
                        . $break;
                    $laststart = $current + 1;
                }
                $lastspace = $current;
            }

            // Special cut case, if no space has been seen
            else if ( $current - $laststart >= $width
                      && $cut && $laststart >= $lastspace
                    )
            {
                $newtext .= iconv_substr( $str, $laststart, $current - $laststart, 'UTF-8' )
                    . $break;
                $laststart = $lastspace = $current;
            }


            // Usual case that line got longer than expected
            else if ( $current - $laststart >= $width
                      && $laststart < $lastspace
                    )
            {
                $newtext .= iconv_substr( $str, $laststart, $lastspace - $laststart, 'UTF-8' )
                    . $break;
                // $laststart = $lastspace = $lastspace + 1;
                $laststart = ++$lastspace;
            }
        }

		// Rest of the string
        if ( $laststart !== $current )
        {
            $newtext .= iconv_substr( $str, $laststart, $current - $laststart, 'UTF-8' );
        }

        return $newtext;
    }

    /**
     * Binary safe str_pad() replacement.
     *
     * This method is a multi-byte encoding safe replacement for the PHP
     * function str_pad().  It mimics exactly the behavior of str_pad(), but
     * uses iconv_* functions with UTF-8 encoding. The parameters received by
     * this method equal the parameters of {@link http://php.net/str_pad
     * str_pad()}. Note: Make sure to hand only UTF-8 encoded content to this
     * method.
     * 
     * @param string $input 
     * @param int $padLength 
     * @param string $padString 
     * @param int $padType 
     * @return string
     */
    public function strPad( $input, $padLength, $padString = ' ', $padType = STR_PAD_RIGHT )
    {
        $input     = (string) $input;

        $strLen    = iconv_strlen( $input, 'UTF-8' );
        $padStrLen = iconv_strlen( $padString, 'UTF-8' );

        if ( $strLen >= $padLength )
        {
            return $input;
        }

        if ( $padType === STR_PAD_BOTH )
        {
            return $this->strPad(
                $this->strPad(
                    $input,
                    $strLen + ceil( ( $padLength - $strLen ) / 2 ),
                    $padString
                ),
                $padLength,
                $padString,
                STR_PAD_LEFT
            );
        }

        $fullStrRepeats = (int) ( ( $padLength - $strLen ) / $padStrLen );
        $partlyPad = iconv_substr(
            $padString,
            0,
            ( ( $padLength - $strLen ) % $padStrLen )
        );

        $padding = str_repeat( $padString, $fullStrRepeats ) . $partlyPad;

        switch ( $padType )
        {
            case STR_PAD_LEFT:
                return $padding . $input;
            case STR_PAD_RIGHT:
            default:
                return $input . $padding;
        }
    }
}

?>
PK��Z;o�!"ezc/ConsoleTools/dialog_viewer.phpnu�[���<?php
/**
 * File containing the ezcConsoleDialogViewer class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */

/**
 * Utility class for ezcConsoleDialog implementations.
 * This class contains utility methods for working with {@link
 * ezcConsoleDialog} implementations.
 *
 * To display a dialog in a loop until a valid result is received do:
 * <code>
 * // Instatiate dialog in $dialog ...
 * ezcConsoleDialogViewer::displayDialog( $dialog );
 * </code>
 *
 * For implementing a custom dialog, the method {@link readLine()} method can be
 * used to read a line of input from the user.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleDialogViewer
{
    /**
     * Displays a dialog and returns a valid result from it.
     * This methods displays a dialog in a loop, until it received a valid
     * result from it and returns this result.
     * 
     * @param ezcConsoleDialog $dialog The dialog to display.
     * @return mixed The result from this dialog.
     */
    public static function displayDialog( ezcConsoleDialog $dialog )
    {
        do
        {
            $dialog->display();
        }
        while ( $dialog->hasValidResult() === false );
        return $dialog->getResult();
    }

    /**
     * Returns a line from STDIN.
     * The returned line is fully trimmed.
     * 
     * @return string
     * @throws ezcConsoleDialogAbortException
     *         if the user closes STDIN using <CTRL>-D.
     */
    public static function readLine()
    {
        $res = trim( fgets( STDIN ) );
        if ( feof( STDIN ) )
        {
            throw new ezcConsoleDialogAbortException();
        }
        return $res;
    }
}

?>
PK��Z����+ezc/ConsoleTools/dialog/question_dialog.phpnu�[���<?php
/**
 * File containing the ezcConsoleQuestionDialog class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */

/**
 * Dialog class to ask a simple question.
 * This dialog outputs a certain string to the user and requests a line of
 * input. This is commonly used to ask questions like "Do you want to proceed?"
 * and retrieve an answer like "y" for yes or "n" for no.
 *
 * The behaviour of this dialog is defined by an instance of
 * {@link ezcConsoleQuestionDialogOptions}.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 *
 * @property ezcConsoleQuestionDialogOptions $options
 *           Options for the dialog.
 * @property ezcConsoleOutput $output
 *           Output object for displaying the dialog.
 */
class ezcConsoleQuestionDialog implements ezcConsoleDialog
{

    /**
     * Dialog result 
     * 
     * @var mixed
     */
    protected $result;

    /**
     * Properties 
     * 
     * @var array
     */
    protected $properties = array(
        "options"   => null,
        "output"    => null,
    );

    /**
     * Creates a new question dialog.
     * Creates a new menu dialog to be displayed to the user. All behaviour is
     * defined through the $options parameter. The $output parameter is used to
     * display the dialog in the {@link display()} method.
     * 
     * @param ezcConsoleOutput $output                 Output object.
     * @param ezcConsoleQuestionDialogOptions $options Options.
     * @return void
     */
    public function __construct( ezcConsoleOutput $output, ezcConsoleQuestionDialogOptions $options = null )
    {
        $this->output  = $output;
        $this->options = $options === null ? new ezcConsoleQuestionDialogOptions() : $options;
    }

    /**
     * Returns if the dialog retrieved a valid result.
     * If a valid result has already been received, this method returns true,
     * otherwise false.
     * 
     * @return bool If a valid result was retrieved.
     */
    public function hasValidResult()
    {
        return $this->result !== null;
    }

    /**
     * Returns the result retrieved.
     * If no valid result was retreived, yet, this method should throw an
     * ezcConsoleNoValidDialogResultException.
     * 
     * If no valid result was retreived, yet, this method throws an
     * ezcConsoleNoValidDialogResultException. Use {@link hasValidResult()} to
     * avoid this.
     * 
     * @return mixed The retreived result.
     *
     * @throws ezcDialogNoValidResultException
     *         if this method is called without a valid result being retrieved
     *         by the object. Use {@link hasValidResult()} to avoid this
     *         exception.
     */
    public function getResult()
    {
        if ( $this->result === null )
        {
            throw new ezcConsoleNoValidDialogResultException();
        }
        return $this->result;
    }

    /**
     * Displays the dialog and retreives a value from the user.
     * Displays the dialog and retreives the desired answer from the user. If
     * the a valid result is retrieved, it can be obtained using {@link
     * getResult()}. The method {@link hasValidResult()} can be used to check
     * if a valid result is available.
     * 
     * @return void
     * @throws ezcConsoleDialogAbortException
     *         if the user closes STDIN using <CTRL>-D.
     */
    public function display()
    {
        $this->reset();

        $this->output->outputText(
            $this->options->text . ( $this->options->showResults === true ? " " . $this->options->validator->getResultString() : "" ) . " ",
            $this->options->format
        );
        $result = $this->options->validator->fixup( ezcConsoleDialogViewer::readLine() );
        if ( $this->options->validator->validate( $result ) )
        {
            $this->result = $result;
        }
    }

    /**
     * Reset the dialog.
     * Resets a possibly received result and all changes made to the dialog
     * during {@link display()}. After that, the dialog can be re-used. All
     * option values are kept.
     * 
     * @return void
     */
    public function reset()
    {
        $this->result = null;
    }

    /**
     * Returns a ready to use yes/no question dialog.
     * Returns a question dialog, which requests the answers "y" for "yes" or
     * "n" for "no" from the user. The answer is converted to lower-case.
     *
     * <code>
     * // Would you like to proceed? (y/n) 
     * $dialog = ezcConsoleDialog( $out, "Would you like to proceed?" );
     *
     * // Would you like to proceed? (y/n) [n] 
     * $dialog = ezcConsoleDialog( $out, "Would you like to proceed?", "n" );
     * </code>
     * 
     * @param ezcConsoleOutput $out  Output object.
     * @param string $questionString Question string.
     * @param string $default        "y" or "n", if default value is desired.
     * @return ezcConsoleQuestionDialog The created dialog.
     */
    public static function YesNoQuestion( ezcConsoleOutput $out, $questionString, $default = null )
    {
        $opts = new ezcConsoleQuestionDialogOptions();
        $opts->text = $questionString;
        $opts->showResults = true;
        $opts->validator = new ezcConsoleQuestionDialogMappingValidator(
            array( "y", "n" ),
            $default,
            ezcConsoleQuestionDialogCollectionValidator::CONVERT_LOWER,
            array(
                'yes' => 'y',
                'no'  => 'n',
            )
        );

        return new ezcConsoleQuestionDialog( $out, $opts );
    }

    /**
     * Property read access.
     *
     * @throws ezcBasePropertyNotFoundException 
     *         If the the desired property is not found.
     * 
     * @param string $propertyName Name of the property.
     * @return mixed Value of the property or null.
     * @ignore
     */
    public function __get( $propertyName )
    {
        if ( array_key_exists( $propertyName, $this->properties ) )
        {
            return $this->properties[$propertyName];
        }
        throw new ezcBasePropertyNotFoundException( $propertyName );
    }

    /**
     * Property write access.
     * 
     * @param string $propertyName Name of the property.
     * @param mixed $propertyValue The value for the property.
     *
     * @throws ezcBasePropertyPermissionException
     *         If the property you try to access is read-only.
     * @throws ezcBasePropertyNotFoundException 
     *         If the the desired property is not found.
     * @ignore
     */
    public function __set( $propertyName, $propertyValue )
    {
        switch ( $propertyName )
        {
            case "options":
                if ( ( $propertyValue instanceof ezcConsoleQuestionDialogOptions ) === false )
                {
                    throw new ezcBaseValueException(
                        $propertyName,
                        ( is_object( $propertyValue ) ? get_class( $propertyValue ) : gettype( $propertyValue ) ),
                        "instance of ezcConsoleQuestionDialogOptions"
                    );
                }
                break;
            case "output":
                if ( ( $propertyValue instanceof ezcConsoleOutput ) === false )
                {
                    throw new ezcBaseValueException(
                        $propertyName,
                        ( is_object( $propertyValue ) ? get_class( $propertyValue ) : gettype( $propertyValue ) ),
                        "instance of ezcConsoleOutput"
                    );
                }
                break;
            default:
                throw new ezcBasePropertyNotFoundException( $propertyName );
        }
        $this->properties[$propertyName] = $propertyValue;
    }

    /**
     * Property isset access.
     * 
     * @param string $propertyName Name of the property to check.
     * @return bool If the property exists or not.
     * @ignore
     */
    public function __isset( $propertyName )
    {
        return array_key_exists( $propertyName, $this->properties );
    }
}

?>
PK��ZegO���<ezc/ConsoleTools/dialog/validators/question_dialog_regex.phpnu�[���<?php
/**
 * File containing the ezcConsoleQuestionDialogRegexValidator class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */

/**
 * Regex validator for ezcConsoleQuestionDialog
 * Validator class for ezcConsoleQuestionDialog objects that validates by
 * matching a certain regular expression.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 *
 * @property string $pattern
 *           The pattern to use for validation. Delimiters and modifiers
 *           included.
 * @property mixed $default
 *           A default value if no (an empty string) result given.
 */
class ezcConsoleQuestionDialogRegexValidator implements ezcConsoleQuestionDialogValidator
{

    /**
     * Properties
     * 
     * @var array(string=>mixed)
     */
    protected $properties = array(
        "pattern" => null,
        "default" => null,
    );

    /**
     * Create a new question dialog regex validator.
     * Create a new question dialog regex validator, which validates the result
     * specified against a given regular expression. The delimiters and
     * eventual modifiers must be included in the pattern. If not value is
     * provided by the user a possibly set $default value is used instead.
     *
     * 
     * @param string $pattern Pattern to validate against.
     * @param mixed $default  Default value.
     * @return void
     */
    public function __construct( $pattern, $default = null )
    {
        $this->pattern = $pattern;
        $this->default = $default;
    }

    /**
     * Returns if the given result is valid. 
     * Returns if the result matches the regular expression.
     * 
     * @param mixed $result The received result.
     * @return bool If the result is valid.
     */
    public function validate( $result )
    {
        if ( $result === "" )
        {
            return $this->default !== null;
        }
        return preg_match( $this->pattern, $result ) > 0;
    }

    /**
     * Returns a fixed version of the result, if possible.
     * If no result was provided by the user, the default value will be
     * returned, if set.
     * 
     * @param mixed $result The received result.
     * @return mixed The manipulated result.
     */
    public function fixup( $result )
    {
        if ( $result === "" && $this->default !== null )
        {
            return $this->default;
        }
        return $result;
    }

    /**
     * Returns a string representing valid results.
     * Returns the string that will be displayed with the question to
     * indicate valid results to the user and a possibly set default, if
     * available.
     * 
     * @return string
     */
    public function getResultString()
    {
        return "(match {$this->pattern})" . ( $this->default !== null ? " [{$this->default}]" : "" );
    }
    
    /**
     * Property read access.
     * 
     * @param string $propertyName Name of the property.
     * @return mixed Value of the property or null.
     *
     * @throws ezcBasePropertyNotFoundException
     *         If the the desired property is not found.
     * @ignore
     */
    public function __get( $propertyName )
    {
        if ( $this->__isset( $propertyName ) )
        {
            return $this->properties[$propertyName];
        }
        throw new ezcBasePropertyNotFoundException( $propertyName );
    }

    /**
     * Property write access.
     * 
     * @param string $propertyName Name of the property.
     * @param mixed $propertyValue The value for the property.
     *
     * @throws ezcBasePropertyNotFoundException
     *         If a the value for the property options is not an instance of
     * @throws ezcBaseValueException
     *         If a the value for a property is out of range.
     * @ignore
     */
    public function __set( $propertyName, $propertyValue )
    {
        switch ( $propertyName )
        {
            case "pattern":
                if ( is_string( $propertyValue ) === false || strlen( $propertyValue ) < 2 )
                {
                    throw new ezcBaseValueException( $propertyName, $propertyValue, "string, length > 1" );
                }
                break;
            case "default":
                if ( is_scalar( $propertyValue ) === false && $propertyValue !== null )
                {
                    throw new ezcBaseValueException( $propertyName, $propertyValue, "scalar" );
                }
                break;
            default:
                throw new ezcBasePropertyNotFoundException( $propertyName );
        }
        $this->properties[$propertyName] = $propertyValue;
    }

    /**
     * Property isset access.
     * 
     * @param string $propertyName Name of the property.
     * @return bool True is the property is set, otherwise false.
     * @ignore
     */
    public function __isset( $propertyName )
    {
        return array_key_exists( $propertyName, $this->properties );
    }
}

?>
PK��Z��,M??;ezc/ConsoleTools/dialog/validators/question_dialog_type.phpnu�[���<?php
/**
 * File containing the ezcConsoleQuestionDialogTypeValidator class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */

/**
 * Validator class to validate a certain data type.
 * Validator class for ezcConsoleQuestionDialog objects that validates a
 * certain datatype.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 *
 * @property int $type
 *           One of ezcConsoleQuestionDialogTypeValidator::TYPE_*. The type to
 *           check against and convert results to.
 * @property mixed $default
 *           A default value if no result given.
 */
class ezcConsoleQuestionDialogTypeValidator implements ezcConsoleQuestionDialogValidator
{
    /**
     * Data type string. 
     */
    const TYPE_STRING = 0;
    /**
     * Data type int. 
     */
    const TYPE_INT    = 1;
    /**
     * Data type float. 
     */
    const TYPE_FLOAT  = 2;
    /**
     * Data type bool. 
     * The results 1 and "true" will be cased to true, 0 and "false" to false.
     */
    const TYPE_BOOL   = 3;

    /**
     * Properties.
     * 
     * @var array
     */
    protected $properties = array(
        "type"      => self::TYPE_STRING,
        "default"   => null,
    );

    /**
     * Creates a new question dialog type validator.
     * Creates a new question dialog type validator, which validates the result
     * specified to be of a certaon type. The $type must be one of the TYPE_*
     * constants in this class. If no value is provided by the user a possibly
     * set $default value is used instead.
     * 
     * @param int $type      One of ezcConsoleQuestionDialogTypeValidator::TYPE_*.
     * @param mixed $default Default value according to $type.
     * @return void
     */
    public function __construct( $type = self::TYPE_STRING, $default = null )
    {
        $this->type = $type;
        $this->default = $default;
    }

    /**
     * Returns if the given result is valid. 
     * Returns if the result is of the given type.
     * 
     * @param mixed $result The result to check.
     * @return bool True if the result is valid. Otherwise false.
     */
    public function validate( $result )
    {
        if ( $result === "" )
        {
            return $this->default !== null;
        }
        switch ( $this->type )
        {
            case self::TYPE_INT:
                return is_int( $result );
            case self::TYPE_FLOAT:
                return is_float( $result );
            case self::TYPE_BOOL:
                return is_bool( $result );
            case self::TYPE_STRING:
            default:
                return is_string( $result );
        }
    }

    /**
     * Returns a fixed version of the result, if possible.
     * Returns the value casted into the correct type or the default value, if
     * it exists and the result is empty.
     * 
     * @param mixed $result The result received.
     * @return mixed The manipulated result.
     */
    public function fixup( $result )
    {
        if ( $result === "" && $this->default !== null )
        {
            return $this->default;
        }
        switch ( $this->type )
        {
            case self::TYPE_INT:
                return ( preg_match( "/^[0-9\-]+$/", $result ) !== 0 ) ? (int) $result : $result;
            case self::TYPE_FLOAT:
                return ( preg_match( "/^[0-9.E\-]+$/i", $result ) !== 0 ) ? (float) $result : $result;
            case self::TYPE_BOOL:
                switch ( $result )
                {
                    case "1":
                    case "true":
                        return true;
                    case "0":
                    case "false":
                        return false;
                }
            case self::TYPE_STRING:
            default:
                return $result;
        }
    }

    /**
     * Returns a string representing valid results.
     * Returns the string that can will be displayed with the question to
     * indicate valid results to the user and a possibly set default, if
     * available.
     * 
     * @return string
     */
    public function getResultString()
    {
        $res = "(<%s>)" . ( $this->default !== null ? " [{$this->default}]" : "" );
        switch ( $this->type )
        {
            case self::TYPE_INT:
                return sprintf( $res, "int" );
            case self::TYPE_FLOAT:
                return sprintf( $res, "float" );
            case self::TYPE_BOOL:
                return sprintf( $res, "bool" );
            case self::TYPE_STRING:
            default:
                return sprintf( $res, "string" );
        }
    }
    
    /**
     * Property read access.
     * 
     * @param string $propertyName Name of the property.
     * @return mixed Value of the property or null.
     *
     * @throws ezcBasePropertyNotFoundException
     *         If the the desired property is not found.
     * @ignore
     */
    public function __get( $propertyName )
    {
        if ( isset( $this->$propertyName ) )
        {
            return $this->properties[$propertyName];
        }
        throw new ezcBasePropertyNotFoundException( $propertyName );
    }

    /**
     * Property write access.
     * 
     * @param string $propertyName Name of the property.
     * @param mixed $propertyValue The value for the property.
     *
     * @throws ezcBasePropertyNotFoundException
     *         If a the value for the property options is not an instance of
     * @throws ezcBaseValueException
     *         If a the value for a property is out of range.
     * @ignore
     */
    public function __set( $propertyName, $propertyValue )
    {
        switch ( $propertyName )
        {
            case "type":
                if ( $propertyValue !== self::TYPE_STRING && $propertyValue !== self::TYPE_INT && $propertyValue !== self::TYPE_FLOAT && $propertyValue !== self::TYPE_BOOL )
                {
                    throw new ezcBaseValueException( $propertyName, $propertyValue, "ezcConsoleQuestionDialogTypeValidator::TYPE_*" );
                }
                break;
            case "default":
                if ( is_scalar( $propertyValue ) === false && $propertyValue !== null )
                {
                    throw new ezcBaseValueException( $propertyName, $propertyValue, "scalar" );
                }
                break;
            default:
                throw new ezcBasePropertyNotFoundException( $propertyName );
        }
        $this->properties[$propertyName] = $propertyValue;
    }

    /**
     * Property isset access.
     * 
     * @param string $propertyName Name of the property.
     * @return bool True is the property is set, otherwise false.
     * @ignore
     */
    public function __isset( $propertyName )
    {
        return array_key_exists( $propertyName, $this->properties );
    }
}

?>
PK��Z�����:ezc/ConsoleTools/dialog/validators/menu_dialog_default.phpnu�[���<?php
/**
 * File containing the ezcConsoleMenuDialogDefaultValidator class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */

/**
 * Default validator for ezcConsoleMenuDialog.
 * This dialog contains a set of menu entries, defined in the $elements
 * property. The result, provided by the user, is checked against the keys of
 * this array. A conversion can be specified to relax the rules for validation
 * (like coverting the result to lower case first). For possibly conversions
 * see the CONVERT_* constants in this class If the user does not provide an
 * answer, a possibly set default value is used.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 *
 * @property array $elements The elements of the menu.
 * @property string $default The default value.
 * @property int $conversion
 *           ezcConsoleDialogValidator::CONVERT_NONE (default) or
 *           ezcConsoleDialogValidator::CONVERT_LOWER or
 *           ezcConsoleDialogValidator::CONVERT_UPPER.
 */
class ezcConsoleMenuDialogDefaultValidator implements ezcConsoleMenuDialogValidator
{
    /**
     * Properties 
     * 
     * @var array
     */
    protected $properties = array(
        "elements"      => array(),
        "default"       => null,
        "conversion"    => self::CONVERT_NONE,
    );

    /**
     * Creates a new menu default validator. 
     * Creates a validator specified by the given parameters. The $elements
     * array specifies the possible menu items to select from. The item
     * identifier (the key of the array) is used to validate the result. The
     * assigned text is displayed as the menu item text. If no result is
     * provided and an optionally provided default value is used. The
     * $conversion parameter can be used to get a conversion applied to the
     * result before validating it.
     * 
     * @param array $elements The elements of the menu.
     * @param mixed $default  The default value.
     * @param int $conversion The conversion to apply.
     * @return void
     */
    public function __construct( array $elements = array(), $default = null, $conversion = self::CONVERT_NONE )
    {
        $this->elements     = $elements;
        $this->default      = $default;
        $this->conversion   = $conversion;
    }

    /**
     * Returns if the given result is valid. 
     * Checks if the given result is a valid key in the $elements property.
     * 
     * @param mixed $result The received result.
     * @return bool If the result is valid.
     */
    public function validate( $result )
    {
        return isset( $this->elements[$result] );
    }

    /**
     * Returns a fixed version of the result, if possible.
     * Converts the given result according to the conversion defined in the
     * $conversion property.
     * 
     * @param mixed $result The received result.
     * @return mixed The manipulated result.
     */
    public function fixup( $result )
    {
        if ( $result === "" && $this->default !== null )
        {
            return $this->default;

        }
        switch ( $this->conversion )
        {
            case self::CONVERT_LOWER:
                return strtolower( $result );
            case self::CONVERT_UPPER:
                return strtoupper( $result );
            case self::CONVERT_NONE:
            default:
                return $result;
        }
    }

    /**
     * Returns a string representing the default value.
     * For example "[y]" to indicate that "y" is the preselected result and
     * will be chosen if no result is provided.
     *
     * @return string The result string.
     */
    public function getResultString()
    {
        return $this->default === null ? "" : "[{$this->default}]";
   }

    /**
     * Returns an array of the elements to display. 
     * 
     * @return array(string=>string) Elements to display.
     */
    public function getElements()
    {
        return $this->elements;
    }

    /**
     * Property read access.
     * 
     * @param string $propertyName Name of the property.
     * @return mixed Value of the property or null.
     *
     * @throws ezcBasePropertyNotFoundException
     *         If the the desired property is not found.
     * @ignore
     */
    public function __get( $propertyName )
    {
        if ( isset( $this->$propertyName ) )
        {
            return $this->properties[$propertyName];
        }
        throw new ezcBasePropertyNotFoundException( $propertyName );
    }

    /**
     * Property write access.
     * 
     * @param string $propertyName Name of the property.
     * @param mixed $propertyValue The value for the property.
     *
     * @throws ezcBasePropertyNotFoundException
     *         If a the value for the property options is not an instance of
     * @throws ezcBaseValueException
     *         If a the value for a property is out of range.
     * @ignore
     */
    public function __set( $propertyName, $propertyValue )
    {
        switch ( $propertyName )
        {
            case "elements":
                if ( is_array( $propertyValue ) === false )
                {
                    throw new ezcBaseValueException( $propertyName, $propertyValue, "array" );
                }
                break;
            case "default":
                if ( is_scalar( $propertyValue ) === false && $propertyValue !== null )
                {
                    throw new ezcBaseValueException( $propertyName, $propertyValue, "scalar" );
                }
                break;
            case "conversion":
                if ( $propertyValue !== self::CONVERT_NONE && $propertyValue !== self::CONVERT_UPPER && $propertyValue !== self::CONVERT_LOWER )
                {
                    throw new ezcBaseValueException( $propertyName, $propertyValue, "ezcConsoleMenuDialogDefaultValidator::CONVERT_*" );
                }
                break;
            default:
                throw new ezcBasePropertyNotFoundException( $propertyName );
        }
        $this->properties[$propertyName] = $propertyValue;
    }

    /**
     * Property isset access.
     * 
     * @param string $propertyName Name of the property.
     * @return bool True is the property is set, otherwise false.
     * @ignore
     */
    public function __isset( $propertyName )
    {
        return array_key_exists( $propertyName, $this->properties );
    }
}

?>
PK��Z��-�>ezc/ConsoleTools/dialog/validators/question_dialog_mapping.phpnu�[���<?php
/**
 * File containing the ezcConsoleQuestionDialogMappingValidator class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */

/**
 * Validator class to map certain results to others.
 * This validator class, for {@link ezcConsoleQuestionDialog} objects,
 * validates a given result against a set of predefined values, exactly like
 * {@link ezcConsoleQuestionDialogCollectionValidator} does, but allows in
 * addition to map certain results to other results. The $map property contains
 * an array of mappings that are checked before a received result is validated.
 * If a mapping matches, the received result is converted to the mapping target
 * before being validated.
 *
 * A valid $map looks like this:
 * <code>
 *      array(
 *          'yes' => 'y',
 *          'no'  => 'n',
 *          '1'   => 'y',
 *          '0'   => 'n'
 *      )
 * </code>
 * While the corresponding collection of valid answers would look like
 * this:
 * <code>
 *      array(
 *          'y', 'n'
 *      )
 * </code>
 * If the answer 'yes' is received by the validator, it is mapped to 'y',
 * therefore considered valid and 'y' is returned as the received value.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 *
 * @property array(string) $collection
 *           The collection of valid answers.
 * @property mixed $default
 *           Default value.
 * @property int $conversion
 *           ezcConsoleDialogValidator::CONVERT_NONE (default) or
 *           ezcConsoleDialogValidator::CONVERT_LOWER or
 *           ezcConsoleDialogValidator::CONVERT_UPPER.
 * @property array(string=>string) $map
 *           Mapping of answers to valid answers (e.g. array('yes' => 'y') to
 *           map 'yes' to 'y' while 'y' must be in $collection).
 */
class ezcConsoleQuestionDialogMappingValidator extends ezcConsoleQuestionDialogCollectionValidator
{
    /**
     * Creates a new question dialog mapping validator. 
     * Creates a new question dialog mapping validator, which validates the
     * result specified by the user against an array of valid results
     * ($collection). If not value is provided by the user a possibly set
     * $default value is used instead. The $conversion parameter can optionally
     * define a conversion to be performed on the result before validating it.
     * Valid conversions are defined by the CONVERT_* constants in this class.
     *
     * While this functionality is already provided by {@link
     * ezcConsoleQuestionDialogCollectionValidator}, the additional $map
     * paramater allows the sepcification of a map of result values. These
     * mapping is then checked for matches, before a received answer is
     * validated against the collection.
     *
     * @param array(string) $collection The collection of valid results.
     * @param mixed $default    Optional default value.
     * @param int $conversion   CONVERT_* constant.
     * @param array(string=>string) $map
     * @return void
     */
    public function __construct( array $collection, $default = null, $conversion = self::CONVERT_NONE, array $map = array() )
    {
        // Initialize additional property
        $this->properties['map'] = $map;

        parent::__construct( $collection, $default, $conversion );
    }

    /**
     * Returns a fixed version of the result, if possible.
     * Converts the given result according to the conversion defined in the
     * $conversion property.
     * 
     * @param mixed $result The received result.
     * @return mixed The manipulated result.
     */
    public function fixup( $result )
    {
        if ( $result === "" && $this->default !== null )
        {
            return $this->default;
        }
        switch ( $this->conversion )
        {
            case self::CONVERT_UPPER:
                $result = strtoupper( $result );
                break;
            case self::CONVERT_LOWER:
                $result = strtolower( $result );
                break;
        }
        return ( isset( $this->map[$result] ) ? $this->map[$result] : $result );
    }
    
    /**
     * Property write access.
     * 
     * @param string $propertyName Name of the property.
     * @param mixed $propertyValue The value for the property.
     *
     * @throws ezcBasePropertyNotFoundException
     *         If a the value for the property options is not an instance of
     * @throws ezcBaseValueException
     *         If a the value for a property is out of range.
     * @ignore
     */
    public function __set( $propertyName, $propertyValue )
    {
        switch ( $propertyName )
        {
            case "map":
                if ( is_array( $propertyValue ) === false )
                {
                    throw new ezcBaseValueException( $propertyName, $propertyValue, "array" );
                }
                break;
            default:
                return parent::__set( $propertyName, $propertyValue );
        }
        $this->properties[$propertyName] = $propertyValue;
    }
}

?>
PK��ZH�!���Aezc/ConsoleTools/dialog/validators/question_dialog_collection.phpnu�[���<?php
/**
 * File containing the ezcConsoleQuestionDialogCollectionValidator class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */

/**
 * Validator class to validate against a set of valid results.
 * This validator class, for {@link ezcConsoleQuestionDialog} objects,
 * validates a given result against a set of predefined values.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 *
 * @property array $collection
 *           The collection of valid answers.
 * @property mixed $default
 *           Default value.
 * @property int $conversion
 *           ezcConsoleDialogValidator::CONVERT_NONE (default) or
 *           ezcConsoleDialogValidator::CONVERT_LOWER or
 *           ezcConsoleDialogValidator::CONVERT_UPPER.
 */
class ezcConsoleQuestionDialogCollectionValidator implements ezcConsoleQuestionDialogValidator
{

    /**
     * Properties.
     * 
     * @var array
     */
    protected $properties  = array(
        "collection"    => array(),
        "default"       => null,
        "conversion"    => self::CONVERT_NONE,
    );

    /**
     * Creates a new question dialog collection validator. 
     * Creates a new question dialog collection validator, which validates the
     * result specified by the user against an array of valid results
     * ($collection). If not value is provided by the user a possibly set
     * $default value is used instead. The $conversion parameter can optionally
     * define a conversion to be performed on the result before validating it.
     * Valid conversions are defined by the CONVERT_* constants in this class.
     * 
     * @param array $collection The collection of valid results.
     * @param mixed $default    Optional default value.
     * @param int $conversion   CONVERT_* constant.
     * @return void
     */
    public function __construct( array $collection, $default = null, $conversion = self::CONVERT_NONE )
    {
        $this->collection = $collection;
        $this->default = $default;
        $this->conversion = $conversion;
    }

    /**
     * Returns if the given result is valid. 
     * Returns if the result is in the $collection array.
     * 
     * @param mixed $result The received result.
     * @return bool If the result is valid.
     */
    public function validate( $result )
    {
        return in_array( $result, $this->collection );
    }

    /**
     * Returns a fixed version of the result, if possible.
     * Converts the given result according to the conversion defined in the
     * $conversion property.
     * 
     * @param mixed $result The received result.
     * @return mixed The manipulated result.
     */
    public function fixup( $result )
    {
        if ( $result === "" && $this->default !== null )
        {
            return $this->default;
        }
        switch ( $this->conversion )
        {
            case self::CONVERT_UPPER:
                return strtoupper( $result );
            case self::CONVERT_LOWER:
                return strtolower( $result );
            default:
                return $result;
        }
    }

    /**
     * Returns a string representing valid results.
     * Returns the string that will be displayed with the question to
     * indicate valid results to the user and a possibly set default, if
     * available.
     * 
     * @return string
     */
    public function getResultString()
    {
        return "(" . implode( "/", $this->collection ) . ")" . ( $this->default !== null ? " [{$this->default}]" : "" );
    }
    
    /**
     * Property read access.
     * 
     * @param string $propertyName Name of the property.
     * @return mixed Value of the property or null.
     *
     * @throws ezcBasePropertyNotFoundException
     *         If the the desired property is not found.
     * @ignore
     */
    public function __get( $propertyName )
    {
        if ( isset( $this->$propertyName ) )
        {
            return $this->properties[$propertyName];
        }
        throw new ezcBasePropertyNotFoundException( $propertyName );
    }

    /**
     * Property write access.
     * 
     * @param string $propertyName Name of the property.
     * @param mixed $propertyValue The value for the property.
     *
     * @throws ezcBasePropertyNotFoundException
     *         If a the value for the property options is not an instance of
     * @throws ezcBaseValueException
     *         If a the value for a property is out of range.
     * @ignore
     */
    public function __set( $propertyName, $propertyValue )
    {
        switch ( $propertyName )
        {
            case "collection":
                if ( is_array( $propertyValue ) === false )
                {
                    throw new ezcBaseValueException( $propertyName, $propertyValue, "array" );
                }
                break;
            case "default":
                if ( is_scalar( $propertyValue ) === false && $propertyValue !== null )
                {
                    throw new ezcBaseValueException( $propertyName, $propertyValue, "scalar" );
                }
                break;
            case "conversion":
                if ( $propertyValue !== self::CONVERT_NONE && $propertyValue !== self::CONVERT_UPPER && $propertyValue !== self::CONVERT_LOWER )
                {
                    throw new ezcBaseValueException( $propertyName, $propertyValue, "ezcConsoleQuestionDialogCollectionValidator::CONVERT_*" );
                }
                break;
            default:
                throw new ezcBasePropertyNotFoundException( $propertyName );
        }
        $this->properties[$propertyName] = $propertyValue;
    }

    /**
     * Property isset access.
     * 
     * @param string $propertyName Name of the property.
     * @return bool True is the property is set, otherwise false.
     * @ignore
     */
    public function __isset( $propertyName )
    {
        return array_key_exists( $propertyName, $this->properties );
    }
}

?>
PK��Zkx2���'ezc/ConsoleTools/dialog/menu_dialog.phpnu�[���<?php
/**
 * File containing the ezcConsoleMenuDialog class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */

/**
 * Dialog class to make the user choose from a menu.
 * This dialog implementation displays a menu structure to the user and
 * receives a valid menu selection.
 *
 * The behaviour of this dialog is defined by an instance of
 * {@link ezcConsoleMenuDialogOptions}.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleMenuDialog implements ezcConsoleDialog
{

    /**
     * Dialog result 
     * 
     * @var mixed
     */
    protected $result;

    /**
     * Properties 
     * 
     * @var array
     */
    protected $properties = array(
        "options"   => null,
        "output"    => null,
    );

    /**
     * Creates a new menu dialog.
     * Creates a new question dialog to be displayed to the user. All behaviour is
     * defined through the $options parameter. The $output parameter is used to
     * display the dialog in the {@link display()} method.
     * 
     * @param ezcConsoleOutput $output             Output object.
     * @param ezcConsoleMenuDialogOptions $options The options.
     * @return void
     */
    public function __construct( ezcConsoleOutput $output, ezcConsoleMenuDialogOptions $options = null )
    {
        $this->output  = $output;
        $this->options = $options === null ? new ezcConsoleMenuDialogOptions() : $options;
    }

    /**
     * Returns if the dialog retrieved a valid result.
     * If a valid result has already been received, this method returns true,
     * otherwise false.
     * 
     * @return bool If a valid result was retrieved.
     */
    public function hasValidResult()
    {
        return ( $this->result !== null );
    }

    /**
     * Returns the result retrieved.
     * If no valid result was retreived, yet, this method throws an
     * ezcConsoleNoValidDialogResultException. Use {@link hasValidResult()} to
     * avoid this.
     * 
     * @return mixed The retreived result.
     *
     * @throws ezcDialogNoValidResultException
     *         if this method is called without a valid result being retrieved
     *         by the object. Use {@link hasValidResult()} to avoid this
     *         exception.
     */
    public function getResult()
    {
        if ( $this->result === null )
        {
            throw new ezcConsoleNoValidDialogResultException();
        }
        return $this->result;
    }

    /**
     * Displays the dialog and retreives a value from the user.
     * Displays the dialog and retreives the desired answer from the user. If
     * the a valid result is retrieved, it can be obtained using {@link
     * getResult()}. The method {@link hasValidResult()} can be used to check
     * if a valid result is available.
     * 
     * @return void
     * @throws ezcConsoleDialogAbortException
     *         if the user closes STDIN using <CTRL>-D.
     */
    public function display()
    {
        $this->reset();

        $text = "{$this->options->text}\n";
        foreach ( $this->options->validator->getElements() as $key => $entry )
        {
            $text .= sprintf(
                $this->options->formatString,
                $key,
                $entry
            );
        }
        $text .= "\n{$this->options->selectText}{$this->options->validator->getResultString()} ";

        $this->output->outputText( $text, $this->options->format );

        $result = $this->options->validator->fixup(
            ezcConsoleDialogViewer::readLine()
        );
        if ( $this->options->validator->validate( $result ) )
        {
            $this->result = $result;
        }
    }

    /**
     * Reset the dialog.
     * Resets a possibly received result and all changes made to the dialog
     * during {@link display()}. After that, the dialog can be re-used. All
     * option values are kept.
     * 
     * @return void
     */
    public function reset()
    {
        $this->result = null;
    }

    /**
     * Property read access.
     *
     * @throws ezcBasePropertyNotFoundException 
     *         If the the desired property is not found.
     * 
     * @param string $propertyName Name of the property.
     * @return mixed Value of the property or null.
     * @ignore
     */
    public function __get( $propertyName )
    {
        if ( array_key_exists( $propertyName, $this->properties ) )
        {
            return $this->properties[$propertyName];
        }
        throw new ezcBasePropertyNotFoundException( $propertyName );
    }

    /**
     * Property write access.
     * 
     * @param string $propertyName Name of the property.
     * @param mixed $propertyValue The value for the property.
     *
     * @throws ezcBasePropertyPermissionException
     *         If the property you try to access is read-only.
     * @throws ezcBasePropertyNotFoundException 
     *         If the the desired property is not found.
     * @ignore
     */
    public function __set( $propertyName, $propertyValue )
    {
        switch ( $propertyName )
        {
            case "options":
                if ( ( $propertyValue instanceof ezcConsoleMenuDialogOptions ) === false )
                {
                    throw new ezcBaseValueException(
                        $propertyName,
                        ( is_object( $propertyValue ) ? get_class( $propertyValue ) : gettype( $propertyValue ) ),
                        "instance of ezcConsoleMenuDialogOptions"
                    );
                }
                break;
            case "output":
                if ( ( $propertyValue instanceof ezcConsoleOutput ) === false )
                {
                    throw new ezcBaseValueException(
                        $propertyName,
                        ( is_object( $propertyValue ) ? get_class( $propertyValue ) : gettype( $propertyValue ) ),
                        "instance of ezcConsoleOutput"
                    );
                }
                break;
            default:
                throw new ezcBasePropertyNotFoundException( $propertyName );
        }
        $this->properties[$propertyName] = $propertyValue;
    }

    /**
     * Property isset access.
     * 
     * @param string $propertyName Name of the property to check.
     * @return bool If the property exists or not.
     * @ignore
     */
    public function __isset( $propertyName )
    {
        return array_key_exists( $propertyName, $this->properties );
    }
}

?>
PK��Z��%p%pezc/ConsoleTools/table.phpnu�[���<?php
/**
 * File containing the ezcConsoleTable class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */

/**
 * Creating tables to be printed to the console. 
 *
 * Every ezcConsoleTable object can be accessed as if it was a multidimensional,
 * numerically indexed array. The first dimension represents the rows of the 
 * table, so $table[0] gives you access to the first row of the table, which is 
 * represented by a {@link ezcConsoleTableRow} object. You can access its 
 * properties directly, using e.g. $table[0]->format. The second dimension gives 
 * you direct access to the cells of your table, like $table[0][0] accesses the 
 * first cell in the first row of your table. You can access its properties 
 * diretly here, too. This works like e.g. $table[0][0]->format. Table row and
 * cell objects are created on the fly, when you access them for the first time.
 * You can also create them as if you simply create new array elements. E.g.
 * $table[] creates a new row in the table.
 *
 * <code>
 * // Initialize the console output handler
 * $out = new ezcConsoleOutput();
 * // Define a new format "headline"
 * $out->formats->headline->color = 'red';
 * $out->formats->headline->style = array( 'bold' );
 * // Define a new format "sum"
 * $out->formats->sum->color = 'blue';
 * $out->formats->sum->style = array( 'negative' );
 * 
 * // Create a new table
 * $table = new ezcConsoleTable( $out, 60 );
 * 
 * // Create first row and in it the first cell
 * $table[0][0]->content = 'Headline 1';
 * 
 * // Create 3 more cells in row 0
 * for ( $i = 2; $i < 5; $i++ )
 * {
 *      $table[0][]->content = "Headline $i";
 * }
 * 
 * $data = array( 1, 2, 3, 4 );
 * 
 * // Create some more data in the table...
 * foreach ( $data as $value )
 * {
 *      // Create a new row each time and set it's contents to the actual value
 *      $table[][0]->content = $value;
 * }
 * 
 * // Set another border format for our headline row
 * $table[0]->borderFormat = 'headline';
 * 
 * // Set the content format for all cells of the 3rd row to "sum"
 * $table[2]->format = 'sum';
 * 
 * $table->outputTable();
 * </code>
 * 
 * @property ezcConsoleTableOptions $options
 *           Contains the options for this class.
 * @property int $width
 *           Width of the table.
 *
 * @see ezcConsoleOutput
 * @package ConsoleTools
 * @version 1.6.1
 * @mainclass
 */
class ezcConsoleTable implements Countable, Iterator, ArrayAccess
{
    /**
     * Automatically wrap text to fit into a column.
     * @see ezcConsoleTable::$options
     */
    const WRAP_AUTO = 1;

    /**
     * Do not wrap text. Columns will be extended to fit the largest text.
     * ATTENTION: This is risky!
     * @see ezcConsoleTable::$options
     */
    const WRAP_NONE = 2;

    /**
     * Text will be cut to fit into a column.
     * @see ezcConsoleTable::$options
     */
    const WRAP_CUT  = 3;
    
    /**
     * Align text in the default direction. 
     */
    const ALIGN_DEFAULT = -1;
    /**
     * Align text in cells to the right.
     */
    const ALIGN_LEFT   = STR_PAD_RIGHT;
    /**
     * Align text in cells to the left.
     */
    const ALIGN_RIGHT  = STR_PAD_LEFT;
    /**
     * Align text in cells to the center.
     */
    const ALIGN_CENTER = STR_PAD_BOTH;

    /**
     * The width given by settings must be used even if the data allows it smaller. 
     */
    const WIDTH_FIXED = 1;
    /**
     * The width given by settings is a maximum value, if data allows it, the table gets smaller.
     */
    const WIDTH_MAX = 2;

    /**
     * Container to hold the properties
     *
     * @var array(string=>mixed)
     */
    protected $properties;

    /**
     * The ezcConsoleOutput object to use.
     *
     * @var ezcConsoleOutput
     */
    protected $outputHandler;

    /**
     * Collection of the rows that are contained in the table. 
     * 
     * @var array(ezcConsoleTableRow)
     */
    protected $rows;

    /**
     * Tool object for multi-byte encoding safe string operations.
     * 
     * @var ezcConsoleStringTool
     */
    private $stringTool;

    /**
     * Creates a new table.
     *
     * @param ezcConsoleOutput $outHandler Output handler to utilize
     * @param int $width                   Overall width of the table (chars).
     * @param array $options               Options
     *
     * @see ezcConsoleTable::$options
     *
     * @throws ezcBaseValueException On an invalid setting.
     */
    public function __construct( ezcConsoleOutput $outHandler, $width, $options = array() ) 
    {
        $this->rows = array();
        $this->outputHandler = $outHandler;
        $this->stringTool = new ezcConsoleStringTool();

        $this->__set( 'width', $width );
        if ( $options instanceof ezcConsoleTableOptions )
        {
            $this->properties['options'] = $options;
        }
        else if ( is_array( $options ) )
        {
            $this->properties['options'] = new ezcConsoleTableOptions( $options );
        }
        else
        {
            throw new ezcBaseValueException( "options", $options, "array" );
        }
    }

    /**
     * Set new options.
     * This method allows you to change the options of the table.
     *
     * @param ezcConsoleTableOptions $options The options to set.
     *
     * @throws ezcBaseSettingNotFoundException
     *         If you tried to set a non-existent option value.
     * @throws ezcBaseSettingValueException
     *         If the value is not valid for the desired option.
     * @throws ezcBaseValueException
     *         If you submit neither an array nor an instance of 
     *         ezcConsoleTableOptions.
     */
    public function setOptions( $options = array() ) 
    {
        if ( is_array( $options ) ) 
        {
            $this->properties['options']->merge( $options );
        } 
        else if ( $options instanceof ezcConsoleTableOptions ) 
        {
            $this->properties['options'] = $options;
        }
        else
        {
            throw new ezcBaseValueException( "options", $options, "instance of ezcConsoleTableOptions" );
        }
    }

    /**
     * Returns the current options.
     * Returns the options currently set for this table.
     * 
     * @return ezcConsoleTableOptions The current options.
     */
    public function getOptions()
    {
        return $this->properties['options'];
    }

    /**
     * Returns the table in an array.
     *
     * Returns the entire table as an array of printable lines. Each element of
     * the array represents a physical line of the drawn table, including all
     * borders and stuff, so you can simply print the table using
     * <code>
     * echo implode( "\n" , $table->getTable() ):
     * </code>
     * which is basically what {@link ezcConsoleTable::outputTable()} does.
     *
     * @return array An array representation of the table.
     */
    public function getTable()
    {
        return $this->generateTable();
    }

    /**
     * Output the table.
     * Prints the complete table to the console.
     *
     * @return void
     */
    public function outputTable() 
    {
        echo implode( PHP_EOL, $this->generateTable() );
    }

    /**
     * Returns the table in a string.
     *
     * @return string
     */
    public function __toString()
    {
        return implode( PHP_EOL, $this->generateTable() );
    }

    /**
     * Returns if the given offset exists.
     * This method is part of the ArrayAccess interface to allow access to the
     * data of this object as if it was an array.
     * 
     * @param int $offset The offset to check.
     * @return bool True when the offset exists, otherwise false.
     * 
     * @throws ezcBaseValueException
     *         If a non numeric row ID is requested.
     */
    public function offsetExists( $offset )
    {
        if ( !is_int( $offset ) || $offset < 0 )
        {
            throw new ezcBaseValueException( 'offset', $offset, 'int >= 0' );
        }
        return isset( $this->rows[$offset] );
    }

    // From here only interface method implementations follow, which are not intended for direct usage

    /**
     * Returns the element with the given offset. 
     * This method is part of the ArrayAccess interface to allow access to the
     * data of this object as if it was an array. In case of the
     * ezcConsoleTable class this method always returns a valid row object
     * since it creates them on the fly, if a given item does not exist.
     * 
     * @param int $offset The offset to check.
     * @return ezcConsoleTableCell
     *
     * @throws ezcBaseValueException
     *         If a non numeric row ID is requested.
     */
    public function offsetGet( $offset )
    {
        $offset = ( $offset === null ) ? count( $this->rows ) : $offset;
        if ( !is_int( $offset ) || $offset < 0  )
        {
            throw new ezcBaseValueException( 'offset', $offset, 'int >= 0 or null' );
        }
        if ( !isset( $this->rows[$offset] ) )
        {
            $this->rows[$offset] = new ezcConsoleTableRow();
        }
        return $this->rows[$offset];
    }

    /**
     * Set the element with the given offset. 
     * This method is part of the ArrayAccess interface to allow access to the
     * data of this object as if it was an array. 
     * 
     * @param int $offset               The offset to assign an item to.
     * @param ezcConsoleTableRow $value The row to assign.
     * @return void
     *
     * @throws ezcBaseValueException
     *         If a non numeric row ID is requested.
     * @throws ezcBaseValueException
     *         If the provided value is not of type {@link ezcConsoleTableRow}.
     */
    public function offsetSet( $offset, $value )
    {
        if ( !( $value instanceof ezcConsoleTableRow ) )
        {
            throw new ezcBaseValueException( 'value', $value, 'ezcConsoleTableRow' );
        }
        if ( !isset( $offset ) )
        {
            $offset = count( $this );
        }
        if ( !is_int( $offset ) || $offset < 0 )
        {
            throw new ezcBaseValueException( 'offset', $offset, 'int >= 0' );
        }
        $this->rows[$offset] = $value;
    }

    /**
     * Unset the element with the given offset. 
     * This method is part of the ArrayAccess interface to allow access to the
     * data of this object as if it was an array. 
     * 
     * @param int $offset The offset to unset the value for.
     * @return void
     *
     * @throws ezcBaseValueException
     *         If a non numeric row ID is requested.
     */
    public function offsetUnset( $offset )
    {
        if ( !is_int( $offset ) || $offset < 0 )
        {
            throw new ezcBaseValueException( 'offset', $offset, 'int >= 0' );
        }
        if ( isset( $this->rows[$offset] ) )
        {
            unset( $this->rows[$offset] );
        }
    }

    /**
     * Returns the number of cells in the row.
     * This method is part of the Countable interface to allow the usage of
     * PHP's count() function to check how many cells this row has.
     *
     * @return int Number of cells in this row.
     */
    public function count()
    {
        $keys = array_keys( $this->rows );
        return count( $keys ) > 0 ? ( end( $keys ) + 1 ) : 0;
    }

    /**
     * Returns the currently selected cell.
     * This method is part of the Iterator interface to allow access to the 
     * cells of this row by iterating over it like an array (e.g. using
     * foreach).
     * 
     * @return ezcConsoleTableCell The currently selected cell.
     */
    public function current()
    {
        return current( $this->rows );
    }

    /**
     * Returns the key of the currently selected cell.
     * This method is part of the Iterator interface to allow access to the 
     * cells of this row by iterating over it like an array (e.g. using
     * foreach).
     * 
     * @return int The key of the currently selected cell.
     */
    public function key()
    {
        return key( $this->rows );
    }

    /**
     * Returns the next cell and selects it or false on the last cell.
     * This method is part of the Iterator interface to allow access to the 
     * cells of this row by iterating over it like an array (e.g. using
     * foreach).
     *
     * @return mixed ezcConsoleTableCell if the next cell exists, or false.
     */
    public function next()
    {
        return next( $this->rows );
    }

    /**
     * Selects the very first cell and returns it.
     * This method is part of the Iterator interface to allow access to the 
     * cells of this row by iterating over it like an array (e.g. using
     * foreach).
     *
     * @return ezcConsoleTableCell The very first cell of this row.
     */
    public function rewind()
    {
        return reset( $this->rows );
    }

    /**
     * Returns if the current cell is valid.
     * This method is part of the Iterator interface to allow access to the 
     * cells of this row by iterating over it like an array (e.g. using
     * foreach).
     *
     * @return ezcConsoleTableCell The very first cell of this row.
     */
    public function valid()
    {
        return current( $this->rows ) !== false;
    }

    /**
     * Property read access.
     * 
     * @param string $key Name of the property.
     * @return mixed Value of the property or null.
     *
     * @throws ezcBasePropertyNotFoundException
     *         If the the desired property is not found.
     * @ignore
     */
    public function __get( $key )
    {
        switch ( $key )
        {
            case 'options':
            case 'width':
                return $this->properties[$key];
            default:
                break;
        }
        throw new ezcBasePropertyNotFoundException( $key );
    }

    /**
     * Property write access.
     * 
     * @param string $key Name of the property.
     * @param mixed $val  The value for the property.
     *
     * @throws ezcBasePropertyNotFoundException
     *         If a the value for the property options is not an instance of
     * @throws ezcBaseValueException
     *         If a the value for a property is out of range.
     * @ignore
     */
    public function __set( $key, $val )
    {
        switch ( $key )
        {
            case 'options':
                if ( !( $val instanceof ezcConsoleTableOptions ) )
                {
                    throw new ezcBaseValueException( $key, $val, 'ezcConsoleTableOptions' );
                }
                $this->properties['options'] = $val;
                return;
            case 'width':
                if ( $val < 1 )
                {
                    throw new ezcBaseValueException( $key, $val, 'int > 0' );
                }
                $this->properties[$key] = $val; 
                return;
            default:
                break;
        }
        throw new ezcBasePropertyNotFoundException( $key );
    }
 
    /**
     * Property isset access.
     * 
     * @param string $key Name of the property.
     * @return bool True is the property is set, otherwise false.
     * @ignore
     */
    public function __isset( $key )
    {
        switch ( $key )
        {
            case 'options':
            case 'width':
            case 'cols':
                return true;
        }
        return false;
    }

    /**
     * Generate the complete table as an array. 
     * 
     * @return array(string) The table.
     */
    private function generateTable()
    {
        $colWidth = $this->getColWidths();
        $table = array();
        
        if ( $this->options->lineVertical !== null )
        {
            $table[] = $this->generateBorder(
                $colWidth,
                ( isset( $this[0] ) ? $this[0]->borderFormat : 'default' )
            );
        }

        // Rows submitted by the user
        for ( $i = 0;  $i < count( $this->rows ); $i++ )
        {
            // Auto broken rows
            foreach ( $this->breakRows( $this->rows[$i], $colWidth ) as $brkRow => $brkCells )
            {
                $table[] = $this->generateRow( $brkCells, $colWidth, $this->rows[$i] );
            }
            $afterBorderFormat = isset( $this->rows[$i + 1] ) && $this->rows[$i + 1]->borderFormat != 'default' ? $this->rows[$i + 1]->borderFormat : $this->rows[$i]->borderFormat;
            if ( $this->options->lineVertical !== null )
            {
                $table[] = $this->generateBorder( $colWidth, $afterBorderFormat );
            }
        }

        // Empty tables need closing border
        if ( $this->options->lineVertical !== null && count( $this->rows ) == null )
        {
            $table[] = $this->generateBorder( $colWidth, 'default' );
        }

        return $table; 
    }

    /**
     * Generate top/bottom borders of rows. 
     * 
     * @param array(int) $colWidth Array of column width.
     * @param string $format            Format name.
     * @return string The Border string.
     */
    private function generateBorder( $colWidth, $format )
    {
        $border = '';
        foreach ( $colWidth as $col => $width )
        {
            $border .= ( $this->options->lineHorizontal !== null ? $this->properties['options']->corner : '' )
                    . str_repeat(
                        $this->properties['options']->lineVertical,
                        $width + (
                            2 * iconv_strlen( $this->properties['options']->colPadding, 'UTF-8' )
                        )
            );
        }
        $border .= ( $this->options->lineHorizontal !== null ? $this->properties['options']->corner : '' );

        return $this->formatText( $border, $format );
    }

    /**
     * Generate a single physical row.
     * This method generates the string for a single physical table row.
     * 
     * @param array(string) $cells Cells of the row.
     * @param array(int) $colWidth Calculated columns widths.
     * @param ezcConsoleTableRow $row   The row to generate.
     * @return string The row.
     */
    private function generateRow( $cells, $colWidth, $row )
    {
        $rowData = '';
        for ( $cell = 0; $cell < count( $colWidth ); $cell++ )
        {
            $align = $this->determineAlign( $row, $cell );
            $format = $this->determineFormat( $row, $cell );
            $borderFormat = $this->determineBorderFormat( $row );
            
            $data = isset( $cells[$cell] ) ? $cells[$cell] : '';
            $rowData .= $this->formatText( 
                            $this->properties['options']->lineHorizontal, 
                            $borderFormat
                        );
            $rowData .= $this->properties['options']->colPadding;
            $rowData .= $this->formatText(
                            $this->stringTool->strPad( $data, $colWidth[$cell], ' ', $align ),
                            $format
                        );
            $rowData .= $this->properties['options']->colPadding;
        }
        $rowData .= $this->formatText( $this->properties['options']->lineHorizontal, $row->borderFormat );
        return $rowData;
    }

    /**
     * Determine the alignment of a cell.
     * Walks the inheritance path upwards to determine the alignment of a 
     * cell. Checks first, if the cell has it's own alignment (apart from 
     * ezcConsoleTable::ALIGN_DEFAULT). If not, checks the row for an 
     * alignment setting and uses the default alignment if not found.
     * 
     * @param ezcConsoleTableRow $row The row this cell belongs to.
     * @param int $cellId             Index of the desired cell.
     * @return int An alignement constant (ezcConsoleTable::ALIGN_*).
     */
    private function determineAlign( $row, $cellId = 0 )
    {
        return ( $row[$cellId]->align !== ezcConsoleTable::ALIGN_DEFAULT 
            ? $row[$cellId]->align
            : ( $row->align !== ezcConsoleTable::ALIGN_DEFAULT
                ? $row->align
                : ( $this->properties['options']->defaultAlign !== ezcConsoleTable::ALIGN_DEFAULT
                    ? $this->properties['options']->defaultAlign
                    : ezcConsoleTable::ALIGN_LEFT ) ) );
    }

    /**
     * Determine the format of a cells content.
     * Walks the inheritance path upwards to determine the format of a 
     * cells content. Checks first, if the cell has it's own format (apart 
     * from 'default'). If not, checks the row for a format setting and 
     * uses the default format if not found.
     * 
     * @param ezcConsoleTableRow $row The row this cell belongs to.
     * @param int $cellId             Index of the desired cell.
     * @return string A format name.
     */
    private function determineFormat( $row, $cellId )
    {
        return ( $row[$cellId]->format != 'default'
            ? $row[$cellId]->format
            : ( $row->format !== 'default'
                ? $row->format
                : $this->properties['options']->defaultFormat ) );
    }

    /**
     * Determine the format of a rows border.
     * Walks the inheritance path upwards to determine the format of a 
     * rows border. Checks first, if the row has it's own format (apart 
     * from 'default'). If not, uses the default format.
     * 
     * @param ezcConsoleTableRow $row   The row this cell belongs to.
     * @return string A format name.
     */
    private function determineBorderFormat( $row )
    {
        return $row->borderFormat !== 'default'
            ? $row->borderFormat
            : $this->properties['options']->defaultBorderFormat;
    }

    /**
     * Returns auto broken rows from an array of cells.
     * The data provided by a user may not fit into a cell calculated by the 
     * class. In this case, the data can be automatically wrapped. The table 
     * row then spans over multiple physical console lines.
     * 
     * @param array(string) $cells Array of cells in one row.
     * @param array(int) $colWidth Columns widths array.
     * @return array(string) Physical rows generated out of this row.
     */
    private function breakRows( $cells, $colWidth ) 
    {
        $rows = array();
        // Iterate through cells of the row
        foreach ( $colWidth as $cell => $width ) 
        {
            $data = $cells[$cell]->content;
            // Physical row id, start with 0 for each row
            $row = 0;
            // Split into multiple physical rows if manual breaks exist
            $dataLines = explode( "\n", $data );
            foreach ( $dataLines as $dataLine ) 
            {
                // Does the physical row fit?
                if ( iconv_strlen( $dataLine, 'UTF-8' ) > ( $colWidth[$cell] ) )
                {
                    switch ( $this->properties['options']->colWrap )
                    {
                        case ezcConsoleTable::WRAP_AUTO:
                            $subLines = explode(
                                "\n",
                                $this->stringTool->wordwrap( $dataLine, $colWidth[$cell], "\n", true )
                            );
                            foreach ( $subLines as $lineNo => $line )
                            {
                                $rows[$row++][$cell] = $line;
                            }
                            break;
                        case ezcConsoleTable::WRAP_CUT:
                            $rows[$row++][$cell] = iconv_substr( $dataLine, 0, $colWidth[$cell], 'UTF-8' );
                            break;
                        case ezcConsoleTable::WRAP_NONE:
                        default:
                            $rows[$row++][$cell] = $dataLine;
                            break;
                    }
                }
                else
                {
                    $rows[$row++][$cell] = $dataLine;
                }
            }
        }
        return $rows;
    }

    /**
     * Determine width of each single column. 
     *
     * @return void
     */
    private function getColWidths()
    {
        if ( is_array( $this->properties['options']->colWidth ) )
        {
            return $this->properties['options']->colWidth;
        }

        // Determine number of columns:
        $colCount = 0;
        foreach ( $this->rows as $row )
        {
            $colCount = max( sizeof( $row ), $colCount );
        }

        if ( $colCount === 0 )
        {
            return array( $this->width );
        }

        $borderWidth = iconv_strlen(
            $this->properties['options']->lineHorizontal,
            'UTF-8'
        );

        // Subtract border and padding chars from global width
        $globalWidth = $this->width
            - ( 
                // Per column: 2 * border padding + 1 border
                $colCount * (
                    2 * iconv_strlen( $this->properties['options']->colPadding, 'UTF-8' )
                    + $borderWidth 
                ) 
              // 1 Additional border
              ) - $borderWidth;
        
        // Width of a column if each is made equal
        $colNormWidth = round( $globalWidth / $colCount );
        $colMaxWidth = array();
        
        // Determine the longest data for each column
        foreach ( $this->rows as $row => $cells )
        {
            foreach ( $cells as $col => $cell )
            {
                $contentLength = 0;
                foreach ( explode( PHP_EOL, $cell->content ) as $contentRow )
                {
                    $contentLength = max(
                        $contentLength,
                        iconv_strlen( $contentRow, 'UTF-8' )
                    );
                }
                $colMaxWidth[$col] = isset( $colMaxWidth[$col] ) ? max( $colMaxWidth[$col], $contentLength ) : $contentLength;
            }
        }
        $colWidth = array();
        $colWidthOverflow = array();
        $spareWidth = 0;
        
        // Make columns best fit
        foreach ( $colMaxWidth as $col => $maxWidth )
        {
            // Does the largest data of the column fit into the average size 
            // + what we have in spare from earlier columns?
            if ( $maxWidth <= ( $colNormWidth + $spareWidth ) ) 
            {
                // We fit in, make the column as large as necessary
                $colWidth[$col] = $maxWidth;
                $spareWidth += ( $colNormWidth - $maxWidth );
            }
            else
            {
                // Does not fit, use maximal possible width
                $colWidth[$col]  = $colNormWidth + $spareWidth;
                $spareWidth = 0;
                // Store overflow for second processing step
                $colWidthOverflow[$col] = $maxWidth - $colWidth[$col];
            }
        }
        
        // Do we have spare to give to the columns again?
        if ( $spareWidth > 0 )
        {
            // Second processing step
            if ( count( $colWidthOverflow ) > 0  )
            {
                $overflowSum = array_sum( $colWidthOverflow );
                foreach ( $colWidthOverflow as $col => $overflow );
                {
                    $colWidth[$col] += floor( $overflow / $overflowSum * $spareWidth );
                }
            }
            elseif ( $this->properties['options']->widthType === ezcConsoleTable::WIDTH_FIXED )
            {
                $widthSum = array_sum( $colWidth );
                foreach ( $colWidth as $col => $width )
                {
                    $colWidth[$col] += floor( $width / $widthSum * $spareWidth );
                }
            }
        }
        
        // Finally sanitize values from rounding issues, if necessary
        if ( ( $colSum = array_sum( $colWidth ) ) != $globalWidth && $this->properties['options']->widthType === ezcConsoleTable::WIDTH_FIXED )
        {
            $colWidth[count( $colWidth ) - 1] -= $colSum - $globalWidth;
        }
        return $colWidth;
    }

    /**
     * Returns the given $text formatted with $format.
     *
     * In case $useFormats is set to false in the output handler, the text is 
     * returned as given, without any formatting.
     * 
     * @param string $text 
     * @param string $format 
     * @return string
     */
    private function formatText( $text, $format )
    {
        if ( $this->outputHandler->options->useFormats )
        {
            return $this->outputHandler->formatText( $text, $format );
        }
        else
        {
            return $text;
        }
    }
}
?>
PK��Z�,���,ezc/ConsoleTools/options/question_dialog.phpnu�[���<?php
/**
 * File containing the ezcConsoleQuestionDialogOptions class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */

/**
 * Basic options class for ezcConsoleDialog implementations.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 *
 * @property string $text
 *           The question itself.
 * @property ezcConsoleQuestionDialogValidator $validator
 *           The validator to use with this dialog.
 * @property bool $showResults
 *           Wether to display the possible results and the default selection.
 * @property string $format
 *           The output format for the dialog.
 */
class ezcConsoleQuestionDialogOptions extends ezcConsoleDialogOptions
{

    /**
     * Construct a new options object.
     * Options are constructed from an option array by default. The constructor
     * automatically passes the given options to the __set() method to set them 
     * in the class.
     * 
     * @throws ezcBasePropertyNotFoundException
     *         If trying to access a non existent property.
     * @throws ezcBaseValueException
     *         If the value for a property is out of range.
     * @param array(string=>mixed) $options The initial options to set.
     */
    public function __construct( array $options = array() )
    {
        $this->properties["text"]           = "Please enter a value: ";
        $this->properties["validator"]      = new ezcConsoleQuestionDialogTypeValidator();
        $this->properties["showResults"] = false;
        parent::__construct( $options );
    }

    /**
     * Property write access.
     * 
     * @param string $propertyName Name of the property.
     * @param mixed $propertyValue The value for the property.
     *
     * @throws ezcBasePropertyPermissionException
     *         If the property you try to access is read-only.
     * @throws ezcBasePropertyNotFoundException 
     *         If the the desired property is not found.
     * @ignore
     */
    public function __set( $propertyName, $propertyValue )
    {
        switch ( $propertyName )
        {
            case "text":
                if ( is_string( $propertyValue ) === false || strlen( $propertyValue ) < 1 )
                {
                    throw new ezcBaseValueException(
                        $propertyName,
                        $propertyValue,
                        "string, length > 0"
                    );
                }
                break;
            case "showResults":
                if ( is_bool( $propertyValue ) === false )
                {
                    throw new ezcBaseValueException( $propertyName, $propertyValue, "bool" );
                }
                break;
            case "validator":
                if ( ( $propertyValue instanceof ezcConsoleQuestionDialogValidator ) === false )
                {
                    throw new ezcBaseValueException( $propertyName, $propertyValue, "ezcConsoleQuestionDialogValidator" );
                }
                break;
            default:
                parent::__set( $propertyName, $propertyValue );
                return;
        }
        $this->properties[$propertyName] = $propertyValue;
    }
}

?>
PK��Zͅ���(ezc/ConsoleTools/options/progressbar.phpnu�[���<?php
/**
 * File containing the ezcConsoleProgressbarOptions class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */

/**
 * Struct class to store the options of the ezcConsoleOutput class.
 * This class stores the options for the {@link ezcConsoleOutput} class.
 *
 * @property string $barChar
 *           The character to fill the bar with, during progress indication.
 * @property string $emptyChar
 *           The character to pre-fill the bar, before indicating progress.
 * @property string $formatString
 *           The format string to describe the complete progressbar.
 * @property string $fractionFormat
 *           Format to display the fraction value.
 * @property string $processChar
 *           The character for the end of the progress area (the arrow!).
 * @property int $redrawFrequency
 *           How often to redraw the progressbar (on every Xth call to advance()).
 * @property int $step
 *           How many steps to advance the progressbar on each call to advance().
 * @property int $width
 *           The width of the bar itself.
 * @property string $actFormat
 *           The format to display the actual value with.
 * @property string $maxFormat
 *           The format to display the actual value with.
 * @property int $minVerbosity
 *           Defines the minimum {ezcConsoleOutputOptions->$verbosityLevel}
 *           that is needed by the progress bar to be rendered. If
 *           $verbosityLevel is lower, the bar is skipped. Default is 0 to
 *           render always.
 * @property int $maxVerbosity
 *           Defines the maximum {ezcConsoleOutputOptions->$verbosityLevel} on
 *           which the progress bar is rendered. If $verbosityLevel is higher,
 *           the bar is skipped. Default is false, to render always.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleProgressbarOptions extends ezcBaseOptions
{

    protected $properties = array(
        'barChar'         => "+",
        'emptyChar'       => "-",
        'formatString'    => "%act% / %max% [%bar%] %fraction%%",
        'fractionFormat'  => "%01.2f",
        'progressChar'    => ">",
        'redrawFrequency' => 1,
        'step'            => 1,
        'width'           => 78,
        'actFormat'       => '%.0f',
        'maxFormat'       => '%.0f',
        'minVerbosity'    => 1,
        'maxVerbosity'    => false,
    );

    /**
     * Option write access.
     * 
     * @throws ezcBasePropertyNotFoundException
     *         If a desired property could not be found.
     * @throws ezcBaseValueException
     *         If a desired property value is out of range.
     *
     * @param string $key Name of the property.
     * @param mixed $value  The value for the property.
     * @ignore
     */
    public function __set( $key, $value )
    {
        switch ( $key )
        {
            case "barChar":
            case "emptyChar":
            case "progressChar":
            case "formatString":
            case "fractionFormat":
            case "actFormat":
            case "maxFormat":
                if ( is_string( $value ) === false || strlen( $value ) < 1 )
                {
                    throw new ezcBaseValueException( $key, $value, 'string, not empty' );
                }
                break;
            case "width":
                if ( !is_int( $value ) || $value < 5 )
                {
                    throw new ezcBaseValueException( $key, $value, 'int >= 5' );
                }
                break;
            case "redrawFrequency":
            case "step":
                if ( ( !is_int( $value ) && !is_float( $value ) ) || $value < 1 )
                {
                    throw new ezcBaseValueException( $key, $value, 'int > 0' );
                }
                break;
            case 'minVerbosity':
                if ( !is_int( $value ) || $value < 0 )
                {
                    throw new ezcBaseValueException( $key, $value, 'int >= 0' );
                }
                break;
            case 'maxVerbosity':
                if ( ( !is_int( $value ) || $value < 0 ) && $value !== false )
                {
                    throw new ezcBaseValueException( $key, $value, 'int >= 0 or false' );
                }
                break;
            default:
                throw new ezcBasePropertyNotFoundException( $key );
        }
        $this->properties[$key] = $value;
    }
}

?>
PK��Z��y��&ezc/ConsoleTools/options/statusbar.phpnu�[���<?php
/**
 * File containing the ezcConsoleStatusbarOptions class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */

/**
 * Struct class to store the options of the ezcConsoleOutput class.
 * This class stores the options for the {@link ezcConsoleOutput} class.
 *
 * @property string $successChar
 *           The char shown for a succeeded status.
 * @property string $failureChar
 *           The char shown for a failed status.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleStatusbarOptions extends ezcBaseOptions
{
    protected $properties = array(
        'successChar' => "+",
        'failureChar' => "-",
    );

    /**
     * Option write access.
     * 
     * @throws ezcBasePropertyNotFoundException
     *         If a desired property could not be found.
     * @throws ezcBaseValueException
     *         If a desired property value is out of range.
     *
     * @param string $key Name of the property.
     * @param mixed $value  The value for the property.
     * @ignore
     */
    public function __set( $key, $value )
    {
        switch ( $key )
        {
            case "successChar":
            case "failureChar":
                if ( is_string( $value ) === false || strlen( $value ) < 1 )
                {
                    throw new ezcBaseValueException( $key, $value, 'string, not empty' );
                }
                break;
            default:
                throw new ezcBasePropertyNotFoundException( $key );
        }
        $this->properties[$key] = $value;
    }
}

?>
PK��Z��88HH"ezc/ConsoleTools/options/table.phpnu�[���<?php
/**
 * File containing the ezcConsoleTableOptions class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */

/**
 * Struct class to store the options of the ezcConsoleTable class.
 * This class stores the options for the {@link ezcConsoleTable} class.
 *
 * @property mixed $colWidth
 *           Either 'auto' for automatic selection of column widths, or an
 *           array of column widths like array( 10, 30, 10 ).
 * @property int $colWrap
 *           Wrap style of text contained in strings. See {@link
 *           ezcConsoleTable::WRAP_AUTO}, {@link ezcConsoleTable::WRAP_NONE}
 *           and {@link ezcConsoleTable::WRAP_CUT}.
 * @property int $defaultAlign
 *           Standard column alignment, applied to cells that have to explicit
 *           alignment assigned. See {@link ezcConsoleTable::ALIGN_LEFT},
 *           {@link ezcConsoleTable::ALIGN_RIGHT}, {@link
 *           ezcConsoleTable::ALIGN_CENTER} and {@link
 *           ezcConsoleTable::ALIGN_DEFAULT}.
 * @property string $colPadding
 *           Padding characters for side padding between data and lines.
 * @property int $widthType
 *           Type of the given table width (fixed or maximal value).
 * @property string $lineVertical
 *           Character to use for drawing vertical lines. Null to switch off.
 * @property string $lineHorizontal
 *           Character to use for drawing horizontal lines. Null to switch off.
 * @property string $corner
 *           Character to use for drawing line corners. Null to switch off.
 * @property string $defaultFormat
 *           Standard column content format, applied to cells that have
 *           "default" as the content format.
 * @property string $defaultBorderFormat
 *           Standard border format, applied to rows that have 'default' as the
 *           border format.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleTableOptions extends ezcBaseOptions
{
    protected $properties = array(
        'colWidth'            => 'auto',
        'colWrap'             => ezcConsoleTable::WRAP_AUTO,
        'defaultAlign'        => ezcConsoleTable::ALIGN_LEFT,
        'colPadding'          => ' ',
        'widthType'           => ezcConsoleTable::WIDTH_MAX,
        'lineVertical'        => '-',
        'lineHorizontal'      => '|',
        'corner'              => '+',
        'defaultFormat'       => 'default',
        'defaultBorderFormat' => 'default',
    );

    /**
     * Construct a new options object.
     *
     * NOTE: For backwards compatibility reasons the old method of instantiating this class is kept,
     * but the usage of the new version (providing an option array) is highly encouraged.
     * 
     * @param array(string=>mixed) $options The initial options to set.
     * @return void
     *
     * @throws ezcBasePropertyNotFoundException
     *         If the value for the property options is not an instance of
     * @throws ezcBaseValueException
     *         If the value for a property is out of range.
     */
    public function __construct()
    {
        $args = func_get_args();
        if ( func_num_args() === 1 && is_array( $args[0] ) && !is_int( key( $args[0] ) ) )
        {
            parent::__construct( $args[0] );
        }
        else
        {
            foreach ( $args as $id => $val )
            {
                switch ( $id )
                {
                    case 0:
                        $this->__set( 'colWidth', $val );
                        break;
                    case 1:
                        $this->__set( 'colWrap', $val );
                        break;
                    case 2:
                        $this->__set( 'defaultAlign', $val );
                        break;
                    case 3:
                        $this->__set( 'colPadding', $val );
                        break;
                    case 4:
                        $this->__set( 'widthType', $val );
                        break;
                    case 5:
                        $this->__set( 'lineVertical', $val );
                        break;
                    case 6:
                        $this->__set( 'lineHorizontal', $val );
                        break;
                    case 7:
                        $this->__set( 'corner', $val );
                        break;
                    case 8:
                        $this->__set( 'defaultFormat', $val );
                        break;
                    case 9:
                        $this->__set( 'defaultBorderFormat', $val );
                        break;
                }
            }
        }
    }

    /**
     * Property write access.
     * 
     * @throws ezcBasePropertyNotFoundException
     *         If a desired property could not be found.
     * @throws ezcBaseValueException
     *         If a desired property value is out of range.
     *
     * @param string $propertyName Name of the property.
     * @param mixed $val  The value for the property.
     * @ignore
     */
    public function __set( $propertyName, $val )
    {
        switch ( $propertyName )
        {
            case 'colWidth':
                if ( is_array( $val ) === false && ( is_string( $val ) && $val !== 'auto' ) )
                {
                    throw new ezcBaseValueException( $propertyName, $val, 'array(int) or "auto"' );
                }
                break;
            case 'colWrap':
                if ( $val !== ezcConsoleTable::WRAP_AUTO && $val !== ezcConsoleTable::WRAP_NONE && $val !== ezcConsoleTable::WRAP_CUT )
                {
                    throw new ezcBaseValueException( $propertyName, $val, 'ezcConsoleTable::WRAP_AUTO, ezcConsoleTable::WRAP_NONE, ezcConsoleTable::WRAP_CUT' );
                }
                break;
            case 'defaultAlign':
                if ( $val !== ezcConsoleTable::ALIGN_DEFAULT && $val !== ezcConsoleTable::ALIGN_LEFT && $val !== ezcConsoleTable::ALIGN_CENTER && $val !== ezcConsoleTable::ALIGN_RIGHT )
                {
                    throw new ezcBaseValueException( $propertyName, $val, 'ezcConsoleTable::ALIGN_DEFAULT, ezcConsoleTable::ALIGN_LEFT, ezcConsoleTable::ALIGN_CENTER, ezcConsoleTable::ALIGN_RIGHT' );
                }
                break;
            case 'colPadding':
                if ( !is_string( $val ) )
                {
                    throw new ezcBaseValueException( $propertyName, $val, 'string' );
                }
                break;
            case 'widthType':
                if ( $val !== ezcConsoleTable::WIDTH_MAX && $val !== ezcConsoleTable::WIDTH_FIXED )
                {
                    throw new ezcBaseValueException( $propertyName, $val, 'ezcConsoleTable::WIDTH_MAX, ezcConsoleTable::WIDTH_FIXED' );
                }
                break;
            case 'lineVertical':
            case 'lineHorizontal':
            case 'corner':
                if ( ( is_string( $val ) === false || strlen( $val ) !== 1 ) && $val !== null )
                {
                    throw new ezcBaseValueException( $propertyName, $val, 'string, length = 1, or null' );
                }
                break;
            case 'defaultFormat':
                if ( is_string( $val ) === false || strlen( $val ) < 1 )
                {
                    throw new ezcBaseValueException( $propertyName, $val, 'string, length = 1' );
                }
                break;
            case 'defaultBorderFormat':
                if ( is_string( $val ) === false || strlen( $val ) < 1 )
                {
                    throw new ezcBaseValueException( $propertyName, $val, 'string, length = 1' );
                }
                break;
            default:
                throw new ezcBasePropertyNotFoundException( $propertyName );
        }
        $this->properties[$propertyName] = $val;
    }
}

?>
PK��Z*��..#ezc/ConsoleTools/options/dialog.phpnu�[���<?php
/**
 * This file contains the ezcConsoleDialogOptions class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 * @access public
 */

/**
 * Basic options class for ezcConsoleDialog implementations.
 * 
 * @property ezcConsoleDialogValidator $validator
 *           The validator to use with this dialog.
 * @property string $format
 *           The output format for the dialog.
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleDialogOptions extends ezcBaseOptions
{
    /**
     * Properties.
     * 
     * @var array(string=>mixed)
     */
    protected $properties = array(
        "format"    => "default",
        "validator" => null
    );

    /**
     * Property write access.
     * 
     * @param string $propertyName Name of the property.
     * @param mixed $propertyValue The value for the property.
     *
     * @throws ezcBasePropertyPermissionException
     *         If the property you try to access is read-only.
     * @throws ezcBasePropertyNotFoundException 
     *         If the the desired property is not found.
     * @ignore
     */
    public function __set( $propertyName, $propertyValue )
    {
        switch ( $propertyName )
        {
            case "format":
                if ( is_string( $propertyValue ) === false || strlen( $propertyValue ) < 1 )
                {
                    throw new ezcBaseValueException( $propertyName, $propertyValue, "string, length > 0" );
                }
                break;
            case "validator":
                if ( ( $propertyValue instanceof ezcConsoleDialogValidator ) === false )
                {
                    throw new ezcBaseValueException( $propertyName, $propertyValue, "ezcConsoleDialogValidator" );
                }
                break;
            default:
                throw new ezcBasePropertyNotFoundException( $propertyName );
        }
        $this->properties[$propertyName] = $propertyValue;
    }
}

?>
PK��Z��BB,ezc/ConsoleTools/options/progressmonitor.phpnu�[���<?php
/**
 * File containing the ezcConsoleProgressMonitorOptions class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */

/**
 * Struct class to store the options of the ezcConsoleOutput class.
 * This class stores the options for the {@link ezcConsoleOutput} class.
 *
 * @property string $formatString
 *           The format string to describe the complete progress monitor.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleProgressMonitorOptions extends ezcBaseOptions
{
    protected $properties = array(
        'formatString' => '%8.1f%% %s %s',
    );

    /**
     * Option write access.
     * 
     * @throws ezcBasePropertyNotFoundException
     *         If a desired property could not be found.
     * @throws ezcBaseValueException
     *         If a desired property value is out of range.
     *
     * @param string $key Name of the property.
     * @param mixed $value  The value for the property.
     * @ignore
     */
    public function __set( $key, $value )
    {
        switch ( $key )
        {
            case "formatString":
                if ( is_string( $value ) === false || strlen( $value ) < 1 )
                {
                    throw new ezcBaseValueException( $key, $value, 'string, not empty' );
                }
                break;
            default:
                throw new ezcBasePropertyNotFoundException( $key );
        }
        $this->properties[$key] = $value;
    }
}

?>
PK��Z'��J

#ezc/ConsoleTools/options/output.phpnu�[���<?php
/**
 * File containing the ezcConsoleOutputOptions class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */

/**
 * Struct class to store the options of the ezcConsoleOutput class.
 *
 * This class stores the options for the {@link ezcConsoleOutput} class.
 *
 * @property int $verbosityLevel
 *           Determines the level of verbosity.
 * @property int $autobreak
 *           Determines, whether text is automatically wrapped after a
 *           specific amount of characters in a line. If set to 0
 *           (default), lines will not be wrapped automatically.
 * @property bool $useFormats
 *           Whether to use formatting or not.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleOutputOptions extends ezcBaseOptions
{
    /**
     * Construct a new options object.
     *
     * NOTE: For BC reasons the old method of instanciating this class is kept,
     * but the usage of the new version is highly encouraged.
     * 
     * @param array(string=>mixed) $options The initial options to set.
     * @return void
     *
     * @throws ezcBasePropertyNotFoundException
     *         If a the value for the property options is not an instance of
     * @throws ezcBaseValueException
     *         If a the value for a property is out of range.
     */
    public function __construct()
    {
        $this->properties['verbosityLevel'] = 1;
        $this->properties['autobreak'] = 0;
        $this->properties['useFormats'] = true;
        $args = func_get_args();
        if ( func_num_args() === 1 && is_array( $args[0] ) )
        {
            parent::__construct( $args[0] );
        }
        else
        {
            foreach ( $args as $id => $val )
            {
                switch ( $id )
                {
                    case 0:
                        $this->__set( "verbosityLevel", $val );
                        break;
                    case 1:
                        $this->__set( "autobreak", $val );
                        break;
                    case 2:
                        $this->__set( "useFormats", $val );
                        break;
                }
            }
        }
    }

    /**
     * Property write access.
     * 
     * @throws ezcBasePropertyNotFoundException
     *         If a desired property could not be found.
     * @throws ezcBaseValueException
     *         If a desired property value is out of range.
     *
     * @param string $propertyName Name of the property.
     * @param mixed $val  The value for the property.
     * @ignore
     */
    public function __set( $propertyName, $val )
    {
        switch ( $propertyName )
        {
            case 'verbosityLevel':
            case 'autobreak':
                if ( !is_int( $val ) || $val < 0 )
                {
                    throw new ezcBaseValueException( $propertyName, $val, 'int >= 0' );
                }
                break;
            case 'useFormats':
                if ( !is_bool( $val ) )
                {
                    throw new ezcBaseValueException( $propertyName, $val, 'bool' );
                }
                break;
            default:
                throw new ezcBasePropertyNotFoundException( $propertyName );
        }
        $this->properties[$propertyName] = $val;
    }
}

?>
PK��Z���Q��(ezc/ConsoleTools/options/menu_dialog.phpnu�[���<?php
/**
 * File containing the ezcConsoleMenuDialogOptions class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */

/**
 * Basic options class for ezcConsoleDialog implementations.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 *
 * @property string $text
 *           The text to display before the menu.
 * @property string $formatString
 *           The format string for each menu element.
 * @property string $selectText
 *           The test to display after the menu to indicate the user that he
 *           should select an item.
 * @property ezcConsoleMenuDialogValidator $validator
 *           The validator to use with this menu.
 * @property string $format
 *           The output format for the dialog.
 */
class ezcConsoleMenuDialogOptions extends ezcConsoleDialogOptions
{

    /**
     * Construct a new options object.
     * Options are constructed from an option array by default. The constructor
     * automatically passes the given options to the __set() method to set them 
     * in the class.
     * 
     * @throws ezcBasePropertyNotFoundException
     *         If trying to access a non existent property.
     * @throws ezcBaseValueException
     *         If the value for a property is out of range.
     * @param array(string=>mixed) $options The initial options to set.
     */
    public function __construct( array $options = array() )
    {
        $this->properties["text"]           = "Please choose an item.";
        $this->properties["formatString"]   = "%3s) %s\n";
        $this->properties["selectText"]     = "Select: ";
        $this->properties["validator"]      = new ezcConsoleMenuDialogDefaultValidator();
        parent::__construct( $options );
    }

    /**
     * Property write access.
     * 
     * @param string $propertyName Name of the property.
     * @param mixed $propertyValue The value for the property.
     *
     * @throws ezcBasePropertyPermissionException
     *         If the property you try to access is read-only.
     * @throws ezcBasePropertyNotFoundException 
     *         If the the desired property is not found.
     * @ignore
     */
    public function __set( $propertyName, $propertyValue )
    {
        switch ( $propertyName )
        {
            case "text":
                if ( is_string( $propertyValue ) === false || strlen( $propertyValue ) < 1 )
                {
                    throw new ezcBaseValueException(
                        $propertyName,
                        $propertyValue,
                        "string, length > 0"
                    );
                }
                break;
            case "selectText":
                if ( is_string( $propertyValue ) === false )
                {
                    throw new ezcBaseValueException(
                        $propertyName,
                        $propertyValue,
                        "string"
                    );
                }
                break;
            case "formatString":
                if ( is_string( $propertyValue ) === false )
                {
                    throw new ezcBaseValueException(
                        $propertyName,
                        $propertyValue,
                        "string"
                    );
                }
                break;
            case "validator":
                if ( ( $propertyValue instanceof ezcConsoleMenuDialogValidator ) === false )
                {
                    throw new ezcBaseValueException(
                        $propertyName,
                        $propertyValue,
                        "ezcConsoleMenuDialogValidator"
                    );
                }
            default:
                parent::__set( $propertyName, $propertyValue );
        }
        $this->properties[$propertyName] = $propertyValue;
    }
}

?>
PK��Z��c�gg*ezc/ConsoleTools/structs/output_format.phpnu�[���<?php
/**
 * File containing the ezcConsoleOutputFormat class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */

/**
 * Struct class to store formating entities used by ezcConsoleOutput.
 *
 * Struct class to store formating entities used by ezcConsoleOutput.
 *
 * Possible values of {@link ezcConsoleOutputFormat::$color} are:
 * - gray
 * - red
 * - green
 * - yellow
 * - blue
 * - magenta
 * - cyan
 * - white
 * - default (representing the consoles default color)
 *
 * For {@link ezcConsoleOutputFormat::$bgcolor} the following values are valid:
 * - black
 * - red
 * - green
 * - yellow
 * - blue
 * - magenta
 * - cyan
 * - white
 * - default (representing the consoles default background color)
 *
 * The {@link ezcConsoleOutputFormat::$style} attribute takes an array of 
 * (possibly) multiple attributes. Choose from the lists below:
 *
 * - default (resets all attributes to default)
 *
 * - bold
 * - faint
 * - normal
 *
 * - italic
 * - notitalic
 *
 * - underlined
 * - doubleunderlined
 * - notunderlined
 *
 * - blink
 * - blinkfast
 * - noblink
 *
 * - negative
 * - positive
 *
 * @property string $color
 *           Contains the color for this format.
 * @property array(string) $style
 *           Contains the lists of styles that are associated with
 *           this format.
 * @property string $bgcolor
 *           Contains the background color for this format.
 * @property string $target
 *           Contains the output target to use. Pick one of
 *           ezcConsoleOutput::TARGET_OUTPUT, ezcConsoleOutput::TARGET_STDOUT
 *           or ezcConsoleOutput::TARGET_STDERR.
 *
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleOutputFormat
{
    /**
     * Container to hold the properties
     *
     * @var array(string=>mixed)
     */
    protected $properties = array( 
        'color'     => 'default',
        'style'     => array( 'default' ),
        'bgcolor'   => 'default',
        'target'    => ezcConsoleOutput::TARGET_OUTPUT,
    );

    /**
     * Create a new ezcConsoleOutputFormat object.
     * Creates a new object of this class.
     * 
     * @param string $color             Name of a color value.
     * @param array(string) $style Names of style values.
     * @param string $bgcolor           Name of a bgcolor value.
     * @param string $target            Target output stream.
     */
    public function __construct( $color = 'default', array $style = null, $bgcolor = 'default', $target = ezcConsoleOutput::TARGET_OUTPUT )
    {
        $this->__set( 'color', $color );
        $this->__set( 'style', isset( $style ) ? $style : array( 'default' ) );
        $this->__set( 'bgcolor', $bgcolor );
        $this->__set( 'target', $target );
    }
    
    /**
     * Overloaded __get() method to gain read-only access to some attributes.
     * 
     * @param string $propertyName Name of the property to read.
     * @return mixed Desired value if exists, otherwise null.
     * @ignore
     */
    public function __get( $propertyName )
    {
        switch ( $propertyName )
        {
            case 'style':
                return (array) $this->properties[$propertyName];
            case 'color':
            case 'bgcolor':
            case 'target':
                return $this->properties[$propertyName];
            default:
                throw new ezcBasePropertyNotFoundException( $propertyName );
        }
    }

    /**
     * Overloaded __set() method to gain read-only access to properties.
     * It also performs checks on setting others.
     *
     * @throws ezcBasePropertyNotFoundException
     *         If the setting you try to access does not exists
     * @throws ezcBaseValueException
     *         If trying to set an invalid value for a setting.
     * 
     * @param string $propertyName Name of the attrinbute to access.
     * @param string $val The value to set.
     * @ignore
     */
    public function __set( $propertyName, $val )
    {
        if ( !isset( $this->properties[$propertyName] ) )
        {
            throw new ezcBasePropertyNotFoundException( $propertyName );
        }
        // Extry handling of multi styles
        if ( $propertyName === 'style' )
        {
            if ( !is_array( $val ) ) $val = array( $val );
            foreach ( $val as $style )
            {
                if ( !ezcConsoleOutput::isValidFormatCode( $propertyName, $style ) )
                {
                    throw new ezcBaseValueException( $propertyName, $style, 'valid ezcConsoleOutput format code' );
                }
            }
            $this->properties['style'] = $val;
            return;
        }
        // Continue normal handling
        if ( ( $propertyName === "color" || $propertyName === "bgcolor" )
             && !ezcConsoleOutput::isValidFormatCode( $propertyName, $val ) )
        {
            throw new ezcBaseValueException( $propertyName, $val, 'valid ezcConsoleOutput format code' );
        }
        $this->properties[$propertyName] = $val;
    }
 
    /**
     * Property isset access.
     * 
     * @param string $propertyName Name of the property.
     * @return bool True is the property is set, otherwise false.
     * @ignore
     */
    public function __isset( $propertyName )
    {
        return isset( $this->properties[$propertyName] );
    }
    
}

?>
PK��Z#�j�''+ezc/ConsoleTools/structs/output_formats.phpnu�[���<?php
/**
 * File containing the ezcConsoleOutputFormats class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */

/**
 * Class to store the collection for formating classes.
 *
 * This class stores objects of {@link ezcConsoleOutputFormat}, which
 * represents a format option set for {@link ezcConsoleOutput}.
 *
 * <code>
 * // New ezcConsoleOutput 
 * // $output->format is instance of ezcConsoleOutputFormats.
 * $output = new ezcConsoleOutput();
 * 
 * // Default format - color = blue
 * $output->formats->default->color = 'blue';
 * // Default format - weight = bold
 * $output->formats->default->style = array( 'bold' );
 *
 * // New format "important" - color = red
 * $output->formats->important->color = 'red';
 * // Format "important" - background color = black
 * $output->formats->important->bgcolor = 'black';
 * </code>
 * 
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleOutputFormats implements Iterator, Countable
{
    /**
     * Array of ezcConsoleOutputFormat.
     * 
     * @var array(ezcConsoleOutputFormat)
     */
    protected $formats = array();

    /**
     * Create a new ezcConsoleOutputFormats object.
     *
     * Creates a new, empty object of this class. It also adds a default
     * format.
     */
    public function __construct()
    {
        $this->formats['default'] = new ezcConsoleOutputFormat();
        $this->formats['success'] = new ezcConsoleOutputFormat();
        $this->formats['success']->color = 'green';
        $this->formats['success']->style = array( 'bold' );
        $this->formats['failure'] = new ezcConsoleOutputFormat();
        $this->formats['failure']->color = 'red';
        $this->formats['failure']->style = array( 'bold' );
    }

    /**
     * Returns the current Iterator value.
     *
     * Implementation of {@link Iterator::current()}.
     * 
     * @return ezcConsoleOutputFormat
     */
    public function current()
    {
        return current( $this->formats );
    }

    /**
     * Advances the Iterator to the next element. 
     *
     * Implementation of {@link Iterator::next()}.
     * 
     * @return ezcConsoleOutputFormat|bool
     */
    public function next()
    {
        return next( $this->formats );
    }

    /**
     * Returns the current Iterator key. 
     *
     * Implementation of {@link Iterator::key()}.
     * 
     * @return string
     */
    public function key()
    {
        return key( $this->formats );
    }

    /**
     * Resets the Iterator to the first element.
     *
     * Implementation of {@link Iterator::rewind()}.
     * 
     * @return ezcConsoleOutputFormat
     */
    public function rewind()
    {
        return reset( $this->formats );
    }

    /**
     * Checks if the current Iterator position is still valid.
     *
     * Implementation of {@link Iterator::valid()}.
     * 
     * @return bool
     */
    public function valid()
    {
        return ( current( $this->formats ) !== false );
    }

    /**
     * Returns the number of registered formats.
     *
     * Implementation of {@link Countable::count()}.
     * 
     * @return void
     */
    public function count()
    {
        return count( $this->formats );
    }

    /**
     * Read access to the formats.
     *
     * Formats are accessed directly like properties of this object. If a
     * format does not exist, it is created on the fly (using default values),
     * 
     * @param string $formatName
     * @return ezcConsoleOutputFormat The format.
     */
    public function __get( $formatName )
    {
        if ( !isset( $this->formats[$formatName] ) )
        {
            $this->formats[$formatName] = new ezcConsoleOutputFormat();
        }
        return $this->formats[$formatName];
    }

    /**
     * Write access to the formats.
     *
     * Formats are accessed directly like properties of this object. If a
     * format does not exist, it is created on the fly (using default values),
     * 
     * @param string $formatName
     * @param ezcConsoleOutputFormat $val The format defintion.
     * @return void
     */
    public function __set( $formatName, ezcConsoleOutputFormat $val )
    {
        $this->formats[$formatName] = $val;
    }
 
    /**
     * Property isset access.
     * 
     * @param string $formatName Name of the property.
     * @return bool True is the property is set, otherwise false.
     */
    public function __isset( $formatName )
    {
        return isset( $this->formats[$formatName] );
    }

}

?>
PK��Z�!{D��(ezc/ConsoleTools/structs/option_rule.phpnu�[���<?php
/**
 * File containing the ezcConsoleOptionRule class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */

/**
 * Struct class to store a parameter rule.
 *
 * This struct stores relation rules between parameters. A relation consists of
 * a parameter that the relation refers to and optionally the value(s) the 
 * referred parameter may have assigned. Rules may be used for dependencies and 
 * exclusions between parameters.
 *
 * The ezcConsoleOptionRule class has the following properties:
 * - <b>option</b> <i>ezcConsoleOption</i>, contains the parameter that this rule refers to.
 * - <b>values</b> <i>array(string)</i>, contains a list of values that are accepted.
 *
 * @see ezcConsoleOption
 * 
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleOptionRule
{
    /**
     * Properties.
     *
     * @var array
     */
    protected $properties = array( 
        'option' => null,
        'values' => array(),
        'ifSet'  => true
    );

    /**
     * Creates a new option rule.
     *
     * Creates a new option rule. Per default the $values parameter
     * is an empty array, which determines that the option may accept any
     * value. To indicate that a option may only have certain values,
     * place them inside tha $values array. For example to indicate an option
     * may have the values 'a', 'b' and 'c' use:
     *
     * <code>
     * $rule = new ezcConsoleOptionRule( $option, array( 'a', 'b', 'c' ) );
     * </code>
     *
     * If you want to allow only 1 specific value for an option, you do not
     * need to wrap this into an array, when creating the rule. Simply use
     *
     * <code>
     * $rule = new ezcConsoleOptionRule( $option, 'a' );
     * </code>
     *
     * to create a rule, that allows the desired option only to accept the
     * value 'a'.
     *
     * The $ifSet parameter determines, if the rule is validated when its option
     * is set or left out. If $ifSet is true, the rule is validated when the 
     * option is set. Otherwise the rule is validated if the option was not set 
     * by the user.
     *
     * @param ezcConsoleOption $option The option to refer to.
     * @param mixed $values            The affected values.
     * @param bool $ifSet
     */
    public function __construct( ezcConsoleOption $option, array $values = array(), $ifSet = true )
    {
        $this->__set( 'option', $option );
        $this->__set( 'values', $values );
        $this->__set( 'ifSet', $ifSet );
    }
    
    /**
     * Property read access.
     *
     * @throws ezcBasePropertyNotFoundException 
     *         If the the desired property is not found.
     * 
     * @param string $propertyName Name of the property.
     * @return mixed Value of the property or null.
     * @ignore
     */
    public function __get( $propertyName ) 
    {
        switch ( $propertyName )
        {
            case 'option':
                return $this->properties['option'];
            case 'values':
                return $this->properties['values'];
            case 'ifSet':
                return $this->properties['ifSet'];
        }
        throw new ezcBasePropertyNotFoundException( $propertyName );
    }
    
    /**
     * Property write access.
     * 
     * @param string $propertyName Name of the property.
     * @param mixed $propertyValue The value for the property.
     *
     * @throws ezcBasePropertyPermissionException
     *         If the property you try to access is read-only.
     * @throws ezcBasePropertyNotFoundException 
     *         If the the desired property is not found.
     * @ignore
     */
    public function __set( $propertyName, $propertyValue ) 
    {
        switch ( $propertyName )
        {
            case 'option':
                if ( !( $propertyValue instanceof ezcConsoleOption ) )
                {
                    throw new ezcBaseValueException( $propertyName, $propertyValue, 'ezcConsoleOption' );
                }
                $this->properties['option'] = $propertyValue;
                return;
            case 'values':
                if ( !is_array( $propertyValue ) )
                {
                    throw new ezcBaseValueException( $propertyName, $propertyValue, 'array' );
                }
                $this->properties['values'] = $propertyValue;
                return;
            case 'ifSet':
                if ( !is_bool( $propertyValue ) )
                {
                    throw new ezcBaseValueException( $propertyName, $propertyValue, 'bool' );
                }
                $this->properties['ifSet'] = $propertyValue;
                return;
        }
        throw new ezcBasePropertyNotFoundException( $propertyName );
    }
 
    /**
     * Property isset access.
     * 
     * @param string $propertyName Name of the property to check.
     * @return bool If the property exists or not.
     * @ignore
     */
    public function __isset( $propertyName )
    {
        switch ( $propertyName )
        {
            case 'option':
            case 'values':
            case 'ifSet':
                return true;
        }
        return false;
    }

}

?>
PK��Z\)�|��1ezc/ConsoleTools/exceptions/argument_too_many.phpnu�[���<?php
/**
 * File containing the ezcConsoleTooManyArgumentsException.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * Thrown if only a certain number of arguments were expected, but more were submitted.
 * This exception can be caught using {@link ezcConsoleOptionException}.
 *
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleTooManyArgumentsException extends ezcConsoleArgumentException
{
    /**
     * Creates a new exception object. 
     * 
     * @param array(string) $args Arguments array.
     * @param int $i                   Index in the arguments array.
     * @return void
     */
    public function __construct( $args, $i )
    {
        parent::__construct( "Only " . ( $i - 1 ) . " arguments are expected, but " . ( count( $args ) - 1 ) . " were submitted." );
    }
}

?>
PK��Z�:�<ezc/ConsoleTools/exceptions/option_string_not_wellformed.phpnu�[���<?php
/**
 * File containing the ezcConsoleOptionStringNotWellformedException.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * The option definition string supplied is not wellformed.
 *
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleOptionStringNotWellformedException extends ezcConsoleException
{
    /**
     * Creates a new exception object. 
     * 
     * @param string $reason The reason for that the string was invalid.
     * @return void
     */
    public function __construct( $reason )
    {
        parent::__construct( "The provided option defintion string was not well formed. " . $reason );
    }
}

?>
PK��Z�%�agg:ezc/ConsoleTools/exceptions/option_mandatory_violation.phpnu�[���<?php
/**
 * File containing the ezcConsoleOptionMandatoryViolationException.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * An option was marked to be mandatory but was not submitted.
 * This exception can be caught using {@link ezcConsoleOptionException}.
 *
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleOptionMandatoryViolationException extends ezcConsoleOptionException
{
    /**
     * Creates a new exception object. 
     * 
     * @param ezcConsoleOption $option The violating option.
     * @return void
     */
    public function __construct( ezcConsoleOption $option )
    {
        parent::__construct( "Option with long name '{$option->long}' is mandatory but was not submitted." );
    }
}

?>
PK��ZJ�8��&ezc/ConsoleTools/exceptions/option.phpnu�[���<?php
/**
 * File containing the ezcConsoleOptionException class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * General exception container for the ConsoleTools component referring to option handling.
 * This base container allows you to catch all exceptions which are related to 
 * errors produced by invalid user submitted options {@link ezcConsoleInput::process()}.
 *
 * @package ConsoleTools
 * @version 1.6.1
 */
abstract class ezcConsoleOptionException extends ezcConsoleException
{
}
?>
PK��Z�����<ezc/ConsoleTools/exceptions/argument_mandatory_violation.phpnu�[���<?php
/**
 * File containing the ezcConsoleArgumentMandatoryViolationException.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * An argument was marked to be mandatory but was not submitted.
 * This exception can be caught using {@link ezcConsoleArgumentException}.
 *
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleArgumentMandatoryViolationException extends ezcConsoleArgumentException
{

    /**
     * Creates a new exception object. 
     * 
     * @param ezcConsoleArgument $arg The argument object, the violation occured for.
     * @return void
     */
    public function __construct( ezcConsoleArgument $arg )
    {
        parent::__construct( "Argument with name '{$arg->name}' is mandatory but was not submitted." );
    }
}

?>
PK��Z��:ezc/ConsoleTools/exceptions/option_exclusion_violation.phpnu�[���<?php
/**
 * File containing the ezcConsoleOptionExclusionViolationException.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * An exclusion rule for a parameter was violated.
 * This exception can be caught using {@link ezcConsoleOptionException}.
 *
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleOptionExclusionViolationException extends ezcConsoleOptionException
{
    /**
     * Creates a new exception object. 
     * 
     * @param ezcConsoleOption $excludingOption The excluding option.
     * @param ezcConsoleOption $excludedOption  The excluded option.
     * @param mixed $valueRange                 The excluded value range.
     * @return void
     */
    public function __construct( ezcConsoleOption $excludingOption, ezcConsoleOption $excludedOption, $valueRange = null )
    {
        $message = "The option '{$excludingOption->long}' excludes the option '{$excludedOption->long}'";
        if ( $valueRange !== null )
        {
            $message .= " to have a value in '{$valueRange}'";
        }
        $message .= " but this one was submitted.";
        parent::__construct( $message );
    }
}
?>
PK��Z����5ezc/ConsoleTools/exceptions/option_type_violation.phpnu�[���<?php
/**
 * File containing the ezcConsoleOptionTypeViolationException.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * An option was submitted with an illigal type.
 * This exception can be caught using {@link ezcConsoleOptionException}.
 *
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleOptionTypeViolationException extends ezcConsoleOptionException
{
    /**
     * Creates a new exception object. 
     * 
     * @param ezcConsoleOption $option The option affected by the violation.
     * @param mixed $value             The violating value            The violating value..
     * @return void
     */
    public function __construct( ezcConsoleOption $option, $value )
    {
        $typeName = 'unknown';
        switch ( $option->type )
        {
            case ezcConsoleInput::TYPE_NONE:
                $typeName = 'none';
                break;
            case ezcConsoleInput::TYPE_INT:
                $typeName = 'int';
                break;
        }
        parent::__construct( "The option '{$option->long}' expects a value of type '{$typeName}', but received the value '{$value}'." );
    }
}
?>
PK��Z7���)ezc/ConsoleTools/exceptions/exception.phpnu�[���<?php
/**
 * File containing the ezcConsoleException class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * General exception container for the ConsoleTools component.
 *
 * @package ConsoleTools
 * @version 1.6.1
 */
abstract class ezcConsoleException extends ezcBaseException
{
}
?>
PK��Ze�8##1ezc/ConsoleTools/exceptions/option_not_exists.phpnu�[���<?php
/**
 * File containing the ezcConsoleOptionNotExistsException
 * 
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * Occurs if the requested option is not registered.
 * This exception can be caught using {@link ezcConsoleOptionException}.
 *
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleOptionNotExistsException extends ezcConsoleOptionException
{
    /**
     * Creates a new exception object. 
     * 
     * @param string $name Name of the already existing option.
     * @return void
     */
    public function __construct( $name )
    {
        parent::__construct( "The referenced parameter '{$name}' is not registered." );
    }
}
?>
PK��Za��rr7ezc/ConsoleTools/exceptions/argument_type_violation.phpnu�[���<?php
/**
 * File containing the ezcConsoleArgumentTypeViolationException class.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * An argument was submitted with an illigal type.
 * This exception can be caught using {@link ezcConsoleArgumentException}.
 *
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleArgumentTypeViolationException extends ezcConsoleArgumentException
{
    /**
     * Creates a new exception object. 
     * 
     * @param ezcConsoleArgument $arg The violated argument.
     * @param mixed $value            The incorrect value.
     * @return void
     */
    public function __construct( ezcConsoleArgument $arg, $value )
    {
        $typeName = 'unknown';
        switch ( $arg->type )
        {
            case ezcConsoleInput::TYPE_INT:
                $typeName = 'int';
                break;
        }
        parent::__construct( "The argument '{$arg->name}' expects a value of type '{$typeName}', but received the value '{$value}'." );
    }
}

?>
PK��ZX�XDD;ezc/ConsoleTools/exceptions/argument_already_registered.phpnu�[���<?php
/**
 * File containing the ezcConsoleArgumentAlreadyRegisteredException class.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * There is already an argument registered with the given name or at the given place.
 *
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleArgumentAlreadyRegisteredException extends ezcConsoleException
{
    /**
     * The name of the argument is already in use.
     */
    const NAMED = 1;
    
    /**
     * The position of the argument is already in use. Unset the position first and the re-register.
     */
    const ORDERED = 2;

    /**
     * Creates a new exception object.
     * The $type parameter can either be
     * {@link ezcConsoleArgumentAlreadyRegisteredException::NAMED} or
     * {@link ezcConsoleArgumentAlreadyRegisteredException::ORDERED}, indicating
     * if the name of the parameter or its place are already taken.
     * 
     * @param int $offset Offset of the already reagistered argument.
     * @param int $type   Type of the offset.
     * @return void
     */
    public function __construct( $offset, $type )
    {
        switch ( $type )
        {
            case self::NAMED:
                $message = "Argument with name '$offset' already registered.";
                break;
            case self::ORDERED:
                $message = "Argument at position '$offset' already registered.";
                break;
        }
        parent::__construct( $message );
    }
}
?>
PK��Z] 5��(ezc/ConsoleTools/exceptions/argument.phpnu�[���<?php
/**
 * File containing the ezcConsoleArgumentException class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * General exception container for the ConsoleTools component referring to argument handling.
 * This base container allows you to catch all exceptions which are related to 
 * errors produced by invalid user submitted arguments {@link ezcConsoleInput::process()}.
 *
 * @package ConsoleTools
 * @version 1.6.1
 */
abstract class ezcConsoleArgumentException extends ezcConsoleException
{
}

?>
PK��Z��ī�2ezc/ConsoleTools/exceptions/no_position_stored.phpnu�[���<?php
/**
 * File containing the ezcConsoleNoPositionStoredException.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * 'Cannot restore position, if no position has been stored before.'.
 *
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleNoPositionStoredException extends ezcConsoleException
{
    /**
     * Creates a new exception object.
     * 
     * @return void
     */
    public function __construct()
    {
        parent::__construct( 'Cannot restore position, if no position has been stored before.' );
    }
}

?>
PK��Z a�3ezc/ConsoleTools/exceptions/invalid_option_name.phpnu�[���<?php
/**
 * File containing the ezcConsoleInvalidOptionNameException.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * Thrown if an invalid option name (containing whitespaces or starting with 
 * a "-") was received by {@link ezcConsoleOption::__construct}.
 *
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleInvalidOptionNameException extends ezcConsoleException
{
    /**
     * Creates a new exception object. 
     * 
     * @param string $name The affected option name.
     * @return void
     */
    public function __construct( $name )
    {
        parent::__construct( "The option name '{$name}' is invalid." );
    }
}

?>
PK��Z|�����9ezc/ConsoleTools/exceptions/option_already_registered.phpnu�[���<?php
/**
 * File containing the ezcConsoleOptionAlreadyRegisteredException.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * The option name you tried to register is already in use.
 *
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleOptionAlreadyRegisteredException extends ezcConsoleException
{
    /**
     * Creates a new exception object. 
     * 
     * @param string $name Name of the affected option.
     * @return void
     */
    public function __construct( $name )
    {
        parent::__construct( "An option with the name '{$name}' is already registered." );
    }
}

?>
PK��Z�J���:ezc/ConsoleTools/exceptions/option_arguments_violation.phpnu�[���<?php
/**
 * File containing the ezcConsoleOptionArgumentsViolationException.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * An option excludes the usage of arguments, but there were arguments submitted.
 * This exception can be caught using {@link ezcConsoleOptionException}.
 *
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleOptionArgumentsViolationException extends ezcConsoleOptionException
{
    /**
     * Creates a new exception object.
     * 
     * @param ezcConsoleOption $option The violating option. 
     * @return void
     */
    public function __construct( ezcConsoleOption $option )
    {
        parent::__construct( "The option with long name '{$option->long}' excludes the usage of arguments, but arguments have been submitted." );
    }
}

?>
PK��Z�BW9��5ezc/ConsoleTools/exceptions/invalid_output_target.phpnu�[���<?php
/**
 * File containing the ezcConsoleInvalidOutputTargetException.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * Thrown if a given target {@link ezcConsoleOutputFormat} could not be opened.
 *
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleInvalidOutputTargetException extends ezcConsoleException
{
    
    /**
     * Creates a new exception object.
     * 
     * @param string $target Affected target.
     * @return void
     */
    public function __construct( $target )
    {
        parent::__construct( "The target '{$target}' could not be opened for writing." );
    }

}
?>
PK��Z��H��6ezc/ConsoleTools/exceptions/no_valid_dialog_result.phpnu�[���<?php
/**
 * File containing the ezcConsoleNoValidDialogResultException.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * Thrown if {@link ezcConsoleDialog::getResult()} is called before a valid
 * result was received.
 *
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleNoValidDialogResultException extends ezcConsoleException
{
    
    /**
     * Creates a new exception object.
     * 
     * @return void
     */
    public function __construct()
    {
        parent::__construct( "The dialog did not receive a valid result, yet." );
    }

}
?>
PK��Z=��?��,ezc/ConsoleTools/exceptions/dialog_abort.phpnu�[���<?php
/**
 * File containing the ezcConsoleDialogAbortException.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * Occurs if the user sends <CTRL>-D to a dialog instead of a valid answer.
 *
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleDialogAbortException extends ezcConsoleException
{
    /**
     * Creates a new exception object. 
     * 
     * @param string $name Name of the already existing option.
     * @return void
     */
    public function __construct()
    {
        parent::__construct( "User send EOF." );
    }
}
?>
PK��Z�ř��4ezc/ConsoleTools/exceptions/option_missing_value.phpnu�[���<?php
/**
 * File containing the ezcConsoleOptionMissingValueException.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * An option which expects a value was submitted without.
 * This exception can be caught using {@link ezcConsoleOptionException}.
 *
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleOptionMissingValueException extends ezcConsoleOptionException
{
    /**
     * Creates a new exception object. 
     * 
     * @param ezcConsoleOption $option The option the value is missing for The option the value is missing for.. 
     * @return void
     */
    public function __construct( ezcConsoleOption $option )
    {
        parent::__construct( "The option '{$option->long}' expects a value, but none was submitted." );
    }
}

?>
PK��Z��;ezc/ConsoleTools/exceptions/option_dependency_violation.phpnu�[���<?php
/**
 * File containing the ezcConsoleOptionDependencyViolationException.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * A dependency rule for a parameter was violated.
 * This exception can be caught using {@link ezcConsoleOptionException}.
 *
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleOptionDependencyViolationException extends ezcConsoleOptionException
{
    /**
     * Creates a new exception object. 
     * 
     * @param ezcConsoleOption $dependingOption The depending option.
     * @param ezcConsoleOption $dependantOption The option depended on.
     * @param mixed $valueRange                 The dependend value range.
     * @return void
     */
    public function __construct( ezcConsoleOption $dependingOption, ezcConsoleOption $dependantOption, $valueRange = null )
    {
        $message  = "The option '{$dependingOption->long}' depends on the option '{$dependantOption->long}' ";
        if ( $valueRange !== null )
        {
            $message .= "to have a value in '{$valueRange}' ";
        }
        $message .= "but this one was not submitted.";
        parent::__construct( $message );
    }
}
?>
PK��Zs��

/ezc/ConsoleTools/exceptions/option_no_alias.phpnu�[���<?php
/**
 * File containing the ezcConsoleOptionNoAliasException.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * Occurs if the alias you tried to unregister is not an alias, but a real option.
 *
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleOptionNoAliasException extends ezcConsoleException
{
    /**
     * Creates a new exception object. 
     * 
     * @param string $name The name of the option which is not an alias.
     * @return void
     */
    public function __construct( $name )
    {
        parent::__construct( "The option name '{$name}' refers to a real parameter, not to an alias." );
    }
}

?>
PK��Z��vv6ezc/ConsoleTools/exceptions/option_too_many_values.phpnu�[���<?php
/**
 * File containing the ezcConsoleOptionTooManyValuesException.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * An option that expects only a single value was submitted with multiple values.
 * This exception can be caught using {@link ezcConsoleOptionException}.
 *
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleOptionTooManyValuesException extends ezcConsoleOptionException
{
    /**
     * Creates a new exception object. 
     * 
     * @param ezcConsoleOption $option The affected option. 
     * @return void
     */
    public function __construct( ezcConsoleOption $option )
    {
        parent::__construct( "The option '{$option->long}' expects a single value, but multiple were submitted." );
    }
}

?>
PK��Z=	�R�L�L!ezc/ConsoleTools/input/option.phpnu�[���<?php
/**
 * File containing the ezcConsoleOption class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */

/**
 * Objects of this class store data about a single option for ezcConsoleInput.
 *
 * This class represents a single command line option, which can be handled by 
 * the ezcConsoleInput class. This classes only purpose is the storage of
 * the parameter data, the handling of options and arguments is done by the
 * class {@link ezcConsoleInput}.
 * 
 * @property-read string $short
 *                Short name of the parameter without '-' (eg. 'f').
 * @property-read string $long
 *                Long name of the parameter without '--' (eg. 'file').
 * @property int $type
 *           Value type of this parameter, default is ezcConsoleInput::TYPE_NONE.
 *           See {@link ezcConsoleInput::TYPE_NONE},
 *           {@link ezcConsoleInput::TYPE_INT} and
 *           {@link ezcConsoleInput::TYPE_STRING}.
 * @property mixed $default
 *           Default value if the parameter is submitted without value.  If a
 *           parameter is eg. of type ezcConsoleInput::TYPE_STRING and
 *           therefore expects a value when being submitted, it may be
 *           submitted without a value and automatically get the default value
 *           specified here.
 * @property bool $multiple
 *           Is the submission of multiple instances of this parameters
 *           allowed? 
 * @property string $shorthelp
 *           Short help text. Usually displayed when showing parameter help
 *           overview.
 * @property string $longhelp
 *           Long help text. Usually displayed when showing parameter detailed
 *           help.
 * @property bool $arguments
 *           Whether arguments to the program are allowed, when this parameter
 *           is submitted. 
 * @property bool $mandatory
 *           Whether a parameter is mandatory to be set.  If this flag is true,
 *           the parameter must be submitted whenever the program is run.
 * @property bool $isHelpOption
 *           Whether a parameter is a help option.  If this flag is true, and
 *           the parameter is set, all options marked as mandatory may be
 *           skipped.
 *
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleOption
{
    /**
     * Container to hold the properties
     *
     * @var array(string=>mixed)
     */
    protected $properties;

    /**
     * Dependency rules of this parameter.
     * 
     * @see ezcConsoleOption::addDependency()
     * @see ezcConsoleOption::removeDependency()
     * @see ezcConsoleOption::hasDependency()
     * @see ezcConsoleOption::getDependencies()
     * @see ezcConsoleOption::resetDependencies()
     * 
     * @var array(string=>ezcConsoleParamemterRule)
     */
    protected $dependencies = array();

    /**
     * Exclusion rules of this parameter.
     * 
     * @see ezcConsoleOption::addExclusion()
     * @see ezcConsoleOption::removeExclusion()
     * @see ezcConsoleOption::hasExclusion()
     * @see ezcConsoleOption::getExclusions()
     * @see ezcConsoleOption::resetExclusions()
     * 
     * @var array(string=>ezcConsoleParamemterRule)
     */
    protected $exclusions = array();

    /**
     * The value the parameter was assigned to when being submitted.
     * Boolean false indicates the parameter was not submitted, boolean
     * true means the parameter was submitted, but did not have a value.
     * In any other case, this caries the submitted value.
     * 
     * @var mixed
     */
    public $value = false;

    /**
     * Create a new parameter struct.
     * Creates a new basic parameter struct with the base information "$short"
     * (the short name of the parameter) and "$long" (the long version). You
     * simply apply these parameters as strings (without '-' or '--'). So
     *
     * <code>
     * $param = new ezcConsoleOption( 'f', 'file' );
     * </code>
     *
     * will result in a parameter that can be accessed using
     * 
     * <code>
     * $ mytool -f
     * </code>
     *
     * or
     * 
     * <code>
     * $ mytool --file
     * </code>
     * .
     *
     * The newly created parameter contains only it's 2 names and each other 
     * attribute is set to it's default value. You can simply manipulate
     * those attributes by accessing them directly.
     * 
     * @param string $short      Short name of the parameter without '-' (eg. 'f').
     * @param string $long       Long name of the parameter without '--' (eg. 'file').
     * @param int $type          Value type of the parameter. One of ezcConsoleInput::TYPE_*.
     * @param mixed $default     Default value the parameter holds if not submitted.
     * @param bool $multiple     If the parameter may be submitted multiple times.
     * @param string $shorthelp  Short help text.
     * @param string $longhelp   Long help text.
     * @param array(ezcConsoleOptionRule) $dependencies Dependency rules.
     * @param array(ezcConsoleOptionRule) $exclusions   Exclusion rules.
     * @param bool $arguments    Whether supplying arguments is allowed when this parameter is set.
     * @param bool $mandatory    Whether the parameter must be always submitted.
     * @param bool $isHelpOption Indicates that the given parameter is a help 
     *                           option. If a help option is set, all rule 
     *                           checking is skipped (dependency/exclusion/
     *                           mandatory).
     *
     * @throws ezcConsoleInvalidOptionNameException If the option names start with a "-" 
     *                                              sign or contain whitespaces.
     */
    public function __construct( 
        $short = '', 
        $long, 
        $type = ezcConsoleInput::TYPE_NONE, 
        $default = null, 
        $multiple = false,
        $shorthelp = 'No help available.',
        $longhelp = 'Sorry, there is no help text available for this parameter.', 
        array $dependencies = array(),
        array $exclusions = array(), 
        $arguments = true,
        $mandatory = false,
        $isHelpOption = false
    )
    {
        $this->properties['short'] = '';
        $this->properties['long'] = '';
        $this->properties['arguments'] = $arguments;

        if ( !self::validateOptionName( $short ) )
        {
            throw new ezcConsoleInvalidOptionNameException( $short );
        }
        $this->properties['short'] = $short;
        
        if ( !self::validateOptionName( $long ) )
        {
            throw new ezcConsoleInvalidOptionNameException( $long );
        }
        $this->properties['long'] = $long;
        
        $this->__set( "type",      $type         !== null ? $type      : ezcConsoleInput::TYPE_NONE  );
        $this->__set( "multiple",  $multiple     !== null ? $multiple  : false  );
        $this->__set( "default",   $default      !== null ? $default   : null );
        $this->__set( "shorthelp", $shorthelp    !== null ? $shorthelp : 'No help available.' );
        $this->__set( "longhelp",  $longhelp     !== null ? $longhelp  : 'Sorry, there is no help text available for this parameter.' );
        
        $dependencies    = $dependencies !== null && is_array( $dependencies ) ? $dependencies : array();
        foreach ( $dependencies as $dep )
        {
            $this->addDependency( $dep );
        }
        
        $exclusions = $exclusions !== null && is_array( $exclusions ) ? $exclusions : array();
        foreach ( $exclusions as $exc )
        {
            $this->addExclusion( $exc );
        }

        $this->__set( "mandatory",    $mandatory !== null ? $mandatory : false );
        $this->__set( "isHelpOption", $isHelpOption !== null ? $isHelpOption : false );
    }

    /**
     * Add a new dependency for a parameter.
     * This registeres a new dependency rule with the parameter. If you try
     * to add an already registered rule it will simply be ignored. Else,
     * the submitted rule will be added to the parameter as a dependency.
     *
     * @param ezcConsoleOptionRule $rule The rule to add.
     * @return void
     */
    public function addDependency( ezcConsoleOptionRule $rule )
    {
        foreach ( $this->dependencies as $existRule )
        {
            if ( $rule == $existRule )
            {
                return;
            }
        }
        $this->dependencies[] = $rule;
    }
    
    /**
     * Remove a dependency rule from a parameter.
     * This removes a given rule from a parameter, if it exists. If the rule is
     * not registered with the parameter, the method call will simply be ignored.
     * 
     * @param ezcConsoleOptionRule $rule The rule to be removed.
     * @return void
     */
    public function removeDependency( ezcConsoleOptionRule $rule )
    {
        foreach ( $this->dependencies as $id => $existRule )
        {
            if ( $rule == $existRule )
            {
                unset( $this->dependencies[$id] );
            }
        }
    }
    
    /**
     * Remove all dependency rule referring to a parameter.
     * This removes all dependency rules from a parameter, that refer to as specific 
     * parameter. If no rule is registered with this parameter as reference, the 
     * method call will simply be ignored.
     * 
     * @param ezcConsoleOption $param The param to be check for rules.
     * @return void
     */
    public function removeAllDependencies( ezcConsoleOption $param )
    {
        foreach ( $this->dependencies as $id => $rule )
        {
            if ( $rule->option == $param )
            {
                unset( $this->dependencies[$id] );
            }
        }
    }
    
    /**
     * Returns if a dependency to the given option exists.
     * Returns true if a dependency rule to the given option is registered,
     * otherwise false.
     * 
     * @param ezcConsoleOption $param The param to check if a dependency exists to.
     * @return bool True if rule is registered, otherwise false.
     */
    public function hasDependency( ezcConsoleOption $param )
    {
        foreach ( $this->dependencies as $id => $rule )
        {
            if ( $rule->option == $param )
            {
                return true;
            }
        }
        return false;
    }
    
    /**
     * Returns the dependency rules registered with this parameter.
     * Returns an array of registered dependencies.
     *
     * For example:
     * <code>
     * array(
     *      0 => ezcConsoleOptionRule,
     *      1 => ezcConsoleOptionRule,
     *      2 => ezcConsoleOptionRule,
     * );
     * </code>
     * 
     * @return array(ezcConsoleOptionRule) Dependency definition.
     */
    public function getDependencies()
    {
        return $this->dependencies;
    }

    /**
     * Reset existing dependency rules.
     * Deletes all registered dependency rules from the option definition.
     * 
     * @return void
     */
    public function resetDependencies() 
    {
        $this->dependencies = array();
    }

    /**
     * Add a new exclusion for an option.
     * This registeres a new exclusion rule with the option. If you try
     * to add an already registered rule it will simply be ignored. Else,
     * the submitted rule will be added to the option as a exclusion.
     *
     * @param ezcConsoleOptionRule $rule The rule to add.
     * @return void
     */
    public function addExclusion( ezcConsoleOptionRule $rule )
    {
        foreach ( $this->exclusions as $existRule )
        {
            if ( $rule == $existRule )
            {
                return;
            }
        }
        $this->exclusions[] = $rule;
    }
    
    /**
     * Remove a exclusion rule from a option.
     * This removes a given rule from a option, if it exists. If the rule is
     * not registered with the option, the method call will simply be ignored.
     * 
     * @param ezcConsoleOptionRule $rule The rule to be removed.
     * @return void
     */
    public function removeExclusion( ezcConsoleOptionRule $rule )
    {
        foreach ( $this->exclusions as $id => $existRule )
        {
            if ( $rule == $existRule )
            {
                unset( $this->exclusions[$id] );
            }
        }
    }
    
    /**
     * Remove all exclusion rule referring to a option.
     * This removes all exclusion rules from a option, that refer to as specific 
     * option. If no rule is registered with this option as reference, the 
     * method call will simply be ignored.
     * 
     * @param ezcConsoleOption $param The option to remove rule for.
     * @return void
     */
    public function removeAllExclusions( ezcConsoleOption $param )
    {
        foreach ( $this->exclusions as $id => $rule )
        {
            if ( $rule->option == $param )
            {
                unset( $this->exclusions[$id] );
            }
        }
    }
    
    /**
     * Returns if a given exclusion rule is registered with the option.
     * Returns true if a exclusion rule to the given option is registered,
     * otherwise false.
     * 
     * @param ezcConsoleOption $param The param to check if exclusions exist for.
     * @return bool True if rule is registered, otherwise false.
     */
    public function hasExclusion( ezcConsoleOption $param )
    {
        foreach ( $this->exclusions as $id => $rule )
        {
            if ( $rule->option == $param )
            {
                return true;
            }
        }
        return false;
    }
    
    /**
     * Returns the exclusion rules registered with this parameter.
     * Returns an array of registered exclusions.
     *
     * For example:
     * <code>
     * array(
     *      0 => ezcConsoleOptionRule,
     *      1 => ezcConsoleOptionRule,
     *      2 => ezcConsoleOptionRule,
     * );
     * </code>
     * 
     * @return array(ezcConsoleOptionRule) Exclusions definition.
     */
    public function getExclusions()
    {
        return $this->exclusions;
    }

    /**
     * Reset existing exclusion rules.
     * Deletes all registered exclusion rules from the option definition.
     *
     * @return void
     */
    public function resetExclusions() 
    {
        $this->exclusions = array();
    }
    
    /**
     * Property read access.
     * Provides read access to the properties of the object.
     * 
     * @param string $key The name of the property.
     * @return mixed The value if property exists and isset, otherwise null.
     * @ignore
     */
    public function __get( $key )
    {
        switch ( $key  )
        {
            case 'short':
            case 'long':
            case 'type':
            case 'default':
            case 'multiple':
            case 'shorthelp':
            case 'longhelp':
            case 'arguments':
            case 'isHelpOption':
            case 'mandatory':
                return $this->properties[$key];
            case 'dependencies':
            default:
                throw new ezcBasePropertyNotFoundException( $key );
        }
    }

    /**
     * Property write access.
     * 
     * @param string $key Name of the property.
     * @param mixed $val  The value for the property.
     *
     * @throws ezcBasePropertyPermissionException
     *         If the property you try to access is read-only.
     * @throws ezcBasePropertyNotFoundException 
     *         If the the desired property is not found.
     * @ignore
     */
    public function __set( $key, $val )
    {
        switch ( $key )
        {
            case 'type':
                if ( $val !== ezcConsoleInput::TYPE_NONE 
                     && $val !== ezcConsoleInput::TYPE_INT 
                     && $val !== ezcConsoleInput::TYPE_STRING )
                {
                    throw new ezcBaseValueException( 
                        $key,  
                        $val, 
                        'ezcConsoleInput::TYPE_STRING, ezcConsoleInput::TYPE_INT or ezcConsoleInput::TYPE_NONE' 
                    );
                }
                break;
            case 'default':
                if ( ( is_scalar( $val ) === false && $val !== null ) )
                {
                    // Newly allow arrays, if multiple is true
                    if ( $this->multiple === true && is_array( $val ) === true )
                    {
                        break;
                    }
                    throw new ezcBaseValueException( $key, $val, 'a string or a number, if multiple == true also an array' );
                }
                break;
            case 'multiple':
                if ( !is_bool( $val ) )
                {
                    throw new ezcBaseValueException( $key, $val, 'bool' );
                }
                break;
            case 'shorthelp':
                if ( !is_string( $val ) )
                {
                    throw new ezcBaseValueException( $key, $val, 'string' );
                }
                break;
            case 'longhelp':
                if ( !is_string( $val ) )
                {
                    throw new ezcBaseValueException( $key, $val, 'string' );
                }
                break;
            case 'arguments':
                if ( !is_bool( $val ) )
                {
                    throw new ezcBaseValueException( $key, $val, 'bool' );
                }
                break;
            case 'mandatory':
                if ( !is_bool( $val ) )
                {
                    throw new ezcBaseValueException( $key, $val, 'bool' );
                }
                break;
            case 'isHelpOption':
                if ( !is_bool( $val ) )
                {
                    throw new ezcBaseValueException( $key, $val, 'bool' );
                }
                break;
            case 'long':
            case 'short':
                throw new ezcBasePropertyPermissionException( $key, ezcBasePropertyPermissionException::READ );
                break;
            default:
                throw new ezcBasePropertyNotFoundException( $key );
                break;
        }
        $this->properties[$key] = $val;
    }
 
    /**
     * Property isset access.
     * 
     * @param string $key Name of the property.
     * @return bool True is the property is set, otherwise false.
     * @ignore
     */
    public function __isset( $key )
    {
        switch ( $key  )
        {
            case 'short':
            case 'long':
            case 'type':
            case 'default':
            case 'multiple':
            case 'shorthelp':
            case 'longhelp':
            case 'arguments':
            case 'isHelpOption':
            case 'mandatory':
                return ( $this->properties[$key] !== null );
        }
        return false;
    }

    /**
     * Returns if a given name if valid for use as a parameter name a parameter. 
     * Checks if a given parameter name is generally valid for use. It checks a)
     * that the name does not start with '-' or '--' and b) if it contains
     * whitespaces. Note, that this method does not check any conflicts with already
     * used parameter names.
     * 
     * @param string $name The name to check.
     * @return bool True if the name is valid, otherwise false.
     */
    public static function validateOptionName( $name )
    {
        if ( substr( $name, 0, 1 ) === '-' || strpos( $name, ' ' ) !== false )
        {
            return false;
        }
        return true;
    }
}

?>
PK��Z
t�^^$ezc/ConsoleTools/input/arguments.phpnu�[���<?php
/**
 * File containing the ezcConsoleArguments collection class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */

/**
 * Collection class for ezcConsoleArgument objects. Used in {@link ezcConsoleInput}.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleArguments implements ArrayAccess, Iterator, Countable
{
    /**
     * Ordered list of arguments. 
     * 
     * @var array(ezcConsoleArgument)
     */
    protected $ordered = array();

    /**
     * Named list of arguments. 
     * 
     * @var array(string=>ezcConsoleArgument)
     */
    protected $named = array();

    /**
     * Returns if the given offset exists.
     * This method is part of the ArrayAccess interface to allow access to the
     * data of this object as if it was an array. Valid offsets are integers or
     * strings. If an integer is used, it refers to the position in the command
     * line. A string refers to the arguments name property.
     * 
     * @param mixed $offset The offset to check.
     * @return bool True when the offset exists, otherwise false.
     * 
     * @throws ezcBaseValueException
     *         If the provided offset is neither an integer, nor a string.
     */
    public function offsetExists( $offset )
    {
        switch ( gettype( $offset ) )
        {
            case "string":
                return array_key_exists( $offset, $this->named );
            case "integer":
                return array_key_exists( $offset, $this->ordered );
            default:
                throw new ezcBaseValueException( "offset", $offset, "string or int" );
        }
    }

    /**
     * Returns the element with the given offset. 
     * This method is part of the ArrayAccess interface to allow access to the
     * data of this object as if it was an array. Valid offsets are integers or
     * strings. If an integer is used, it refers to the position in the command
     * line. A string refers to the arguments name property.
     * 
     * @param string|integer $offset The offset to check.
     * @return ezcConsoleArgument
     *
     * @throws ezcBaseValueException
     *         If the provided offset is neither an integer, nor a string.
     */
    public function offsetGet( $offset )
    {
        switch ( gettype( $offset ) )
        {
            case "string":
                if ( isset( $this[$offset] ) )
                {
                    return $this->named[$offset];
                }
                break;
            case "integer":
                if ( isset( $this[$offset] ) )
                {
                    return $this->ordered[$offset];
                }
                break;
            default:
                throw new ezcBaseValueException( "offset", $offset, "string or int" );
        }
        throw new ezcBasePropertyNotFoundException( $offset );
    }

    /**
     * Set the element with the given offset. 
     * This method is part of the ArrayAccess interface to allow access to the
     * data of this object as if it was an array. In contrast to the other
     * ArrayAccess implementations of this class, this method allows only integer
     * keys.
     * 
     * @param int $offset               The offset to assign an item to.
     * @param ezcConsoleArgument $value The argument object to register.
     * @return void
     *
     * @throws ezcBaseValueException
     *         If a non integer offset is provided.
     * @throws ezcBaseValueException
     *         If the provided value is not of type {@ling ezcConsoleTableRow}.
     * @throws ezcConsoleArgumentAlreadyRegisteredException
     *         If an argument with the given offset or name is already registered.
     */
    public function offsetSet( $offset, $value )
    {
        // Determine key if not set (using $obj[] = ...)
        if ( $offset === null )
        {
            $offset = count( $this->ordered ) === 0 ? 0 : max( array_keys( $this->ordered ) ) + 1;
        }

        // Set access only allowed with integer values
        if ( !is_int( $offset ) )
        {
            throw new ezcBaseValueException( "offset", $offset, "int" );
        }
        
        switch ( true )
        {
            case ( $value instanceof ezcConsoleArgument ):
                if ( isset( $this->ordered[$offset] ) )
                {
                    throw new ezcConsoleArgumentAlreadyRegisteredException( $offset, ezcConsoleArgumentAlreadyRegisteredException::ORDERED );
                }
                if ( isset( $this->named[$value->name] ) )
                {
                    throw new ezcConsoleArgumentAlreadyRegisteredException( $value->name, ezcConsoleArgumentAlreadyRegisteredException::NAMED );
                }

                $this->named[$value->name] = $value;
                $this->ordered[$offset]    = $value;
                break;
            case ( $value === null ):
                // Aliasing unset() with assignement to null
                unset( $this->named[$this->ordered[$offset]->name] );
                unset( $this->ordered[$offset] );
                break;
            default:
                throw new ezcBaseValueException( "value", $value, "ezcConsoleArgument or null" );
        }
    }

    /**
     * Unset the element with the given offset. 
     * This method is part of the ArrayAccess interface to allow access to the
     * data of this object as if it was an array. In contrast to the other
     * ArrayAccess implementations of this class, this method allows only integer
     * keys.
     * 
     * @param int $offset The offset to unset the value for.
     * @return void
     *
     * @throws ezcBaseValueException
     *         If a non numeric row offset is used.
     */
    public function offsetUnset( $offset )
    {
        // Set access only allowed with integer values
        if ( is_int( $offset ) === false )
        {
            throw new ezcBaseValueException( "offset", $offset, "int" );
        }

        unset( $this->named[$this->ordered[$offset]->name] );
        unset( $this->ordered[$offset] );
    }

    /**
     * Returns the currently selected argument from the list.
     * Used by foreach-Loops.
     * 
     * @return ezcConsoleArgument
     */
    public function current()
    {
        return current( $this->ordered );
    }

    /**
     * Returns the key of the currently selected argument from the list.
     * Used by foreach-Loops. In contrast to the iteration direction, which is
     * defined by the ordered list of arguments, this is the name of the
     * argument.
     * 
     * @return string
     */
    public function key()
    {
        return key( $this->ordered );
    }

    /**
     * Advances the internal pointer to the next argument and returns it. 
     * Used by foreach-Loops.
     * 
     * @return ezcConsoleArgument
     */
    public function next()
    {
        return next( $this->ordered );
    }

    /**
     * Rewinds the internal pointer to the first argument and returns it.
     * Used by foreach-Loops.
     * 
     * @return ezcConsoleArgument
     */
    public function rewind()
    {
        // Called before foreach
        ksort( $this->ordered );
        return reset( $this->ordered );
    }

    /**
     * Checks if the current position is valid.
     * Used by foreach-Loops.
     * 
     * @return bool
     */
    public function valid()
    {
        return ( current( $this->ordered ) !== false );
    }

    /**
     * Returns the number of registered arguments.
     * 
     * @return int
     */
    public function count()
    {
        return count( $this->ordered );
    }
}
?>
PK��Z�%�663ezc/ConsoleTools/input/help_generators/standard.phpnu�[���<?php
/**
 * File containing the ezcConsoleInputStandardHelpGenerator class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */
/**
 * Standard help generator for {@link ezcConsoleInput}.
 *
 * Standard help generation as {@link ezcConsoleInput} did from the start.
 *
 * @package ConsoleTools
 * @version 1.6.1
 *
 * @access private
 * @TODO Verify interface and make it public to replace the validation in 
 *       {@link ezcConsoleInput}.
 */
class ezcConsoleInputStandardHelpGenerator implements ezcConsoleInputHelpGenerator
{
    /**
     * Input object. 
     * 
     * @var ezcConsoleInput
     */
    private $input;

    /**
     * Creates a new help generator.
     *
     * Creates a new help generator for the given $input.
     * 
     * @param ezcConsoleInput $input
     */
    public function __construct( ezcConsoleInput $input )
    {
        $this->input = $input;
    }

    /**
     * Generates help information as a multidimensional array.
     *
     * This method generates a tabular view on the help information of a 
     * program. The returned array has the following structure:
     *
     * <code>
     * <?php
     * array(
     *  0 => array(
     *      0 => '<option short/long name>',
     *      1 => '<option help, depending on the $long parameter>'
     *  ),
     *  1 => array(
     *      0 => '<option short name> / <option long name>',
     *      1 => '<option help, depending on the $long parameter>'
     *  ),
     *  // ...
     * );
     * ?>
     * </code>
     *
     * Each row of the array represents the help information for a single option.
     * The first cell of a row contains the option name (maybe short, long or 
     * both), the second cell contains the help text of the option.
     *
     * The returned array is used by {@link ezcConsoleInput} for different 
     * purposes.
     * For example, the user can retrieve it raw through the
     * {@link ezcConsoleInput::getHelp()} method, he can generate a help
     * {@link ezcConsoleTable} through {@link ezcConsoleInput::getHelpTable()} 
     * are can generate a printable help text through {@link 
     * ezcConsoleInput::getHelpText()}.
     *
     * The parameter $long defines if the long or short help text of the 
     * options should be used in the second cell of the returned array. The
     * $optionsFilter parameter is used to restrict the generated help to a certain 
     * sub-set of options. It consists of an array of short or long names of 
     * the options to include.
     * 
     * @param bool $long 
     * @param array(string) $optionsFilter
     * @return array(array(string))
     */
    public function generateUngroupedOptionHelp( $long = false, array $optionsFilter = null )
    {
        $help = array();
        foreach ( $this->input->getOptions() as $id => $param )
        {
            if ( $optionsFilter === null || in_array( $param->short, $optionsFilter ) || in_array( $param->long, $optionsFilter ) )
            {
                $help[] = $this->getOptionHelpRow( $long, $param );
            }
        }
        return $help;
    }

    /**
     * Generates help information as a multidimensional array, grouped in categories.
     *
     * This method behaves similar to {@link generateUngroupedOptionHelp()}. In 
     * contrast to the latter one, this method returns an array with 1 
     * dimension more, grouping options into categories. The $groups parameter 
     * defines the categories to generate. Each category may contain an 
     * arbitrary number of options, options might occur in different 
     * categories.
     *
     * The returned array has the follorwing format:
     *
     * <code>
     * <?php
     * array(
     *  '<category name>' => array(
     *      0 => array(
     *          0 => '<option short/long name>',
     *          1 => '<option help, depending on the $long parameter>'
     *      ),
     *      1 => array(
     *          0 => '<option short name> / <option long name>',
     *          1 => '<option help, depending on the $long parameter>'
     *      ),
     *      // ...
     *  ),
     *  '<category name>' => array(
     *      // ...
     *  ),
     *  // ...
     * );
     * ?>
     * </code>
     *
     * The $long parameter, as in {@link generateUngroupedOptionHelp()} 
     * determines if the options short or long help is to be used. The
     * $params array can in addition be used to determine if a parameter
     * is displayed at all. If $optionsFilter is submitted and is not null, 
     * only options listed in it will be shown in the help at all.
     * 
     * @param array(string=>array(string)) $groups
     * @param bool $long 
     * @param array(string) $params 
     * @return array(string=>array(array(string)))
     */
    public function generateGroupedOptionHelp( array $groups, $long = false, array $optionsFilter = null )
    {
        $help = array();
        foreach ( $groups as $groupName => $groupOptions )
        {
            foreach ( $groupOptions as $optionName )
            {
                $option = $this->input->getOption( $optionName );
                if ( $optionsFilter === null || in_array( $option->short, $optionsFilter ) || in_array( $option->long, $optionsFilter ) )
                {
                    $help[$groupName][] = $this->getOptionHelpRow(
                        $long,
                        $option
                    );
                }
            }
        }
        return $help;
    }

    /**
     * Generates help information as a multi-dimensonal array for the given $argumentDefinition.
     *
     * This method generates a tabular help information for the given 
     * $argumentDefinition in the following format:
     *
     * <code>
     * <?php
     * array(
     *  0 => array(
     *      0 => '<argument synopsis>',
     *      1 => '<argument help text>'
     *  ),
     *  1 => array(
     *      0 => '<argument synopsis>',
     *      1 => '<argument help text>'
     *  ),
     *  // ...
     * )
     * ?>
     * </code>
     * 
     * The $long parameter defines if the long of short help text should be 
     * used.
     *
     * @param bool $long
     * @return array(array(string))
     */
    public function generateArgumentHelp( $long = false )
    {
        $help = array();
        if ( $this->input->argumentDefinition !== null )
        {
            foreach ( $this->input->argumentDefinition as $arg )
            {
                $argSynopsis = "<%s:%s>";
                switch ( $arg->type )
                {
                    case ezcConsoleInput::TYPE_INT:
                        $type = "int";
                        break;
                    case ezcConsoleInput::TYPE_STRING:
                        $type = "string";
                        break;
                }
                $argSynopsis = sprintf( $argSynopsis, $type, $arg->name );
                $help[] = ( $long === true )
                        ? array( 
                            $argSynopsis,
                            $arg->longhelp . ( $arg->mandatory === false 
                                               ? ' (optional' . ( $arg->default !== null 
                                                                  ? ', default = ' . ( is_array( $arg->default ) 
                                                                                       ? "'" . implode( "' '", $arg->default ) . "'" 
                                                                                       : "'$arg->default'" 
                                                                                     )
                                                                  : '' 
                                                                ) . ')'
                                               : ''
                                             )
                          )
                        : array( $argSynopsis, $arg->shorthelp );
            }
        }
        return $help;
    }

    /**
     * Creates 1 text row for displaying options help. 
     *
     * Returns a single array entry for the {@link getOptionHelpRow()} method.
     *
     * @param bool $long 
     * @param ezcConsoleOption $param
     * @return string
     */
    private function getOptionHelpRow( $long, ezcConsoleOption $param )
    {
        return array( 
            ( $param->short !== "" ? '-' . $param->short . ' / ' : "" ) . '--' . $param->long,
            $long == false ? $param->shorthelp : $param->longhelp,
        );
    }

    /**
     * Generates a command line synopsis for the options and arguments.
     *
     * This method generates a synopsis string that lists the options and 
     * parameters available, indicating their usage. If $optionsFilter is
     * submitted, only the options named in this array (short or long variant) 
     * will be included in the synopsis.
     *
     * @param array(string) $optionsFilter
     * @return string
     */
    public function generateSynopsis( array $optionFilter = null )
    {
        $usedOptions = array( 'short' => array(), 'long' => array() );
        $allowsArgs = true;
        $synopsis = '$ ' . ( isset( $argv ) && sizeof( $argv ) > 0 ? $argv[0] : $_SERVER['argv'][0] ) . ' ';
        foreach ( $this->input->getOptions() as $option )
        {
            if ( $optionFilter === null || in_array( $option->short, $optionFilter ) ||  in_array( $option->long, $optionFilter ) )
            {
                $synopsis .= $this->createOptionSynopsis( $option, $usedOptions, $allowsArgs );
            }
        }
        if ( $this->input->argumentDefinition === null )
        {
            // Old handling
            $synopsis .= " [[--] <args>]";
        }
        else
        {
            $synopsis .= "[--] " . $this->createArgumentsSynopsis();
        }
        return $synopsis;
    }

    /**
     * Returns the synopsis string for a single option and its dependencies.
     *
     * This method returns a part of the program synopsis, specifically for a
     * certain parameter. The method recursively adds depending parameters up
     * to the 2nd depth level to the synopsis. The second parameter is used
     * to store the short names of all options that have already been used in 
     * the synopsis (to avoid adding an option twice). The 3rd parameter 
     * determines the actual deps in the option dependency recursion to 
     * terminate that after 2 recursions.
     * 
     * @param ezcConsoleOption $option        The option to include.
     * @param array(string) $usedOptions Array of used option short names.
     * @param int $depth                      Current recursion depth.
     * @return string The synopsis for this parameter.
     */
    private function createOptionSynopsis( ezcConsoleOption $option, &$usedOptions, $depth = 0 )
    {
        $synopsis = '';

        // Break after a nesting level of 2
        if ( $depth++ > 2 || ( in_array( $option->short, $usedOptions['short'] ) && in_array( $option->long, $usedOptions['long'] ) ) ) return $synopsis;
        
        $usedOptions['short'][] = $option->short;
        $usedOptions['long'][]  = $option->long;
        
        $synopsis .= $option->short !== "" ? "-{$option->short}" : "--{$option->long}";

        if ( isset( $option->default ) )
        {
            $synopsis .= " " . ( $option->type === ezcConsoleInput::TYPE_STRING ? '"' : '' ) . $option->default . ( $option->type === ezcConsoleInput::TYPE_STRING ? '"' : '' );
        }
        else if ( $option->type !== ezcConsoleInput::TYPE_NONE )
        {
            $synopsis .= " ";
            switch ( $option->type )
            {
                case ezcConsoleInput::TYPE_STRING:
                    $synopsis .= "<string>";
                    break;
                case ezcConsoleInput::TYPE_INT:
                    $synopsis .= "<int>";
                    break;
            }
        }

        foreach ( $option->getDependencies() as $rule )
        {
            $deeperSynopsis = $this->createOptionSynopsis( $rule->option, $usedOptions, $depth );
            $synopsis .= ( iconv_strlen( trim( $deeperSynopsis ), 'UTF-8' ) > 0 
                ? ' ' . $deeperSynopsis
                : ''
            );
        }
        
        if ( $option->arguments === false )
        {
            $allowsArgs = false;
        }
        
        // Make the whole thing optional?
        if ( $option->mandatory === false )
        {
            $synopsis = "[$synopsis]";
        }

        return $synopsis . ' ';
    }

    /**
     * Generate synopsis for arguments. 
     * 
     * @return string The synopsis string.
     */
    private function createArgumentsSynopsis()
    {
        $mandatory = true;
        $synopsises = array();
        foreach ( $this->input->argumentDefinition as $arg )
        {
            $argSynopsis = "";
            if ( $arg->mandatory === false )
            {
                $mandatory = false;
            }
            $argSynopsis .= "<%s:%s>";
            switch ( $arg->type )
            {
                case ezcConsoleInput::TYPE_INT:
                    $type = "int";
                    break;
                case ezcConsoleInput::TYPE_STRING:
                    $type = "string";
                    break;
            }
            $argSynopsis = sprintf( $argSynopsis, $type, $arg->name );
            $synopsises[] = $mandatory === false ? "[$argSynopsis]" : $argSynopsis;
            if ( $arg->multiple === true )
            {
                $synopsises[] = "[$argSynopsis ...]";
                break;
            }
        }
        return implode( " ", $synopsises );
    }
}

?>
PK��Z�p���#ezc/ConsoleTools/input/argument.phpnu�[���<?php
/**
 * File containing the ezcConsoleArgument class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */

/**
 * The ezcConsoleArgument class represents an argument on the console.
 * This class is the container to store information about an argument submitted
 * to a shell application. It is used to define the appearance of an argument
 * before parsing the parameter string and contains the received value
 * afterwards. Argument objects are stored in an instance of the set class
 * {@link ezcConsoleArguments} which is stored in
 * {ezcConsoleInput::$argumentDefinition}.
 * 
 * @property string $name      The name for the argument. Must be unique.
 * @property int $type         The value type. 
 * @property string $shorthelp A short help text. 
 * @property string $longhelp  A long help text-
 * @property bool $mandatory   Whether the argument is mandatory.
 * @property mixed $default    A default value, if not mandatory.
 * @property bool $multiple    Whether the argument accepts multiple values.
 * @property-read mixed $value The value parsed from the parameter string, using
 *                             {@link ezcConsoleInput::process()}.
 * @package ConsoleTools
 * @version 1.6.1
 */
class ezcConsoleArgument
{
    /**
     * Properties 
     * 
     * @var array
     */
    protected $properties = array(
        "name"      => null,
        "type"      => ezcConsoleInput::TYPE_STRING,
        "shorthelp" => "No help available.",
        "longhelp"  => "There is no help for this argument available.",
        "mandatory" => true,
        "multiple"  => false,
        "default"   => null,
        "value"     => null,
    );

    /**
     * Creates a new console argument object.
     * Creates a new console argument object, which represents a single
     * argument on the shell. Arguments are stored insiede 
     * {@link ezcConsoleArguments} which is used with {@link ezcConsoleInput}.
     *
     * For the type property see {@link ezcConsoleInput::TYPE_STRING} and
     * {@link ezcConsoleInput::TYPE_INT}. If 1 argument is defined as optional
     * ($mandatory = false), all following arguments are autolamtically
     * considered optional, too.
     * 
     * @param string $name      The name for the argument. Must be unique.
     * @param int $type         The value type. 
     * @param string $shorthelp A short help text. 
     * @param string $longhelp  A long help text-
     * @param bool $mandatory   Whether the argument is mandatory.
     * @param bool $multiple    Whether the argument accepts multiple values.
     * @param mixed $default    A default value, if not mandatory.
     * @return void
     */
    public function __construct(
        $name      = null,
        $type      = ezcConsoleInput::TYPE_STRING,
        $shorthelp = "No help available.",
        $longhelp  = "There is no help for this argument available.",
        $mandatory = true,
        $multiple  = false,
        $default   = null
    )
    {
        if ( !is_string( $name ) || strlen( $name ) < 1 )
        {
            throw new ezcBaseValueException( "name", $name, "string, length > 0" );
        }
        $this->properties["name"] = $name;

        $this->type               = $type;
        $this->shorthelp          = $shorthelp;
        $this->longhelp           = $longhelp;
        $this->mandatory          = $mandatory;
        $this->multiple           = $multiple;
        $this->default            = $default;
    }

    /**
     * Property set access.
     * 
     * @param string $propertyName  Name of the property.
     * @param string $propertyValue Valze for the property.
     * @return void
     * @ignore
     */
    public function __set( $propertyName, $propertyValue )
    {
        switch ( $propertyName )
        {
            case "name":
                throw new ezcBasePropertyPermissionException( $propertyName, ezcBasePropertyPermissionException::READ );
                break;
            case "type":
                if ( $propertyValue !== ezcConsoleInput::TYPE_INT && $propertyValue !== ezcConsoleInput::TYPE_STRING )
                {
                    throw new ezcBaseValueException( $propertyName, $propertyValue, "string, length > 0" );
                }
                break;
            case "shorthelp":
            case "longhelp":
                if ( is_string( $propertyValue ) === false )
                {
                    throw new ezcBaseValueException( $propertyName, $propertyValue, "string" );
                }
                break;
            case "mandatory":
            case "multiple":
                if ( is_bool( $propertyValue ) === false )
                {
                    throw new ezcBaseValueException( $propertyName, $propertyValue, "bool" );
                }
                break;
            case "default":
                if ( is_scalar( $propertyValue ) === false && is_array( $propertyValue ) === false && $propertyValue !== null )
                {
                    throw new ezcBaseValueException( $propertyName, $propertyValue, "array, scalar or null" );
                }
                break;
            case "value":
                if ( is_scalar( $propertyValue ) === false && is_array( $propertyValue ) === false && $propertyValue !== null )
                {
                    throw new ezcBaseValueException( $propertyName, $propertyValue, "string or null" );
                }
                break;
            default:
                throw new ezcBasePropertyNotFoundException( $propertyName );
        }
        $this->properties[$propertyName] = $propertyValue;
    }

    /**
     * Property read access.
     *
     * @throws ezcBasePropertyNotFoundException 
     *         If the the desired property is not found.
     * 
     * @param string $propertyName Name of the property.
     * @return mixed Value of the property or null.
     * @ignore
     */
    public function __get( $propertyName )
    {
        if ( isset( $this->$propertyName ) )
        {
            return $this->properties[$propertyName];
        }
        throw new ezcBasePropertyNotFoundException( $propertyName );
    }

    /**
     * Property isset access.
     * 
     * @param string $propertyName Name of the property.
     * @return bool True is the property is set, otherwise false.
     * @ignore
     */
    public function __isset( $propertyName )
    {
        return array_key_exists( $propertyName, $this->properties );
    }
}

?>
PK��Z�&�T��.ezc/ConsoleTools/input/validators/standard.phpnu�[���<?php
/**
 * File containing the ezcConsoleStandardInputValidator class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */
/**
 * Validates ezcConsoleOption in terms of dependencies/exclusion and more.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 *
 * @access private
 */
class ezcConsoleStandardInputValidator implements ezcConsoleInputValidator
{
    /**
     * Validates the given $options and $arguments.
     *
     * Validates the given $options against their registered rules. Throws an 
     * exception, if any condition is not met. $hasArguments indicates if 
     * arguments have been submitted in addition.
     *
     * @param array(ezcConsoleOption) $options
     * @param bool $hasArguments
     *
     * @throws ezcConsoleOptionDependencyViolationException
     *         If a dependency was violated. 
     * @throws ezcConsoleOptionExclusionViolationException 
     *         If an exclusion rule was violated.
     * @throws ezcConsoleOptionArgumentsViolationException 
     *         If arguments are passed although a parameter dissallowed them.
     * @throws ezcConsoleOptionMandatoryViolationException
     *         If an option that was marked mandatory was not submitted.
     * @throws ezcConsoleOptionMissingValueException
     *         If an option that expects a value was submitted without one.
     */
    public function validateOptions( array $options, $hasArguments )
    {
        foreach ( $options as $id => $option )
        {
            if ( $option->mandatory === true && $option->value === false )
            {
                throw new ezcConsoleOptionMandatoryViolationException( $option );
            }

            $this->validateDependencies( $option );
            $this->validateExclusions( $option );

            if ( $option->arguments === false && $option->value !== false && $hasArguments )
            {
                throw new ezcConsoleOptionArgumentsViolationException( $option );
            }
        }
    }

    /**
     * Validated option dependencies.
     *
     * Validates dependencies by $option.
     *
     * @param ezcConsoleOption $option.
     */
    private function validateDependencies( ezcConsoleOption $option )
    {
        $optSet = ( $option->value !== false
            && ( !is_array( $option->value ) || $option->value !== array() ) );

        foreach ( $option->getDependencies() as $dep )
        {
            if ( $dep->ifSet === $optSet )
            {
                $this->validateDependency( $option, $dep );
            }
        }
    }

    /**
     * Validates a single dependency.
     *
     * Validates the dependency $dep, which is set in the $srcOpt.
     *
     * @param ezcConsoleOption $srcOpt
     * @param ezcConsoleOptionRule $dep
     */
    private function validateDependency( ezcConsoleOption $srcOpt, ezcConsoleOptionRule $dep )
    {
        $optValue = $dep->option->value;

        if ( $optValue === false || $optValue === array() )
        {
            throw new ezcConsoleOptionDependencyViolationException(
                $srcOpt,
                $dep->option
            );
        }

        if ( $dep->values !== array() )
        {
            $optVals = ( is_array( $optValue ) ? $optValue : array( $optValue) );
            $unrecognizedVals = array_diff( $optVals, $dep->values );
            if ( $unrecognizedVals !== array() )
            {
                throw new ezcConsoleOptionDependencyViolationException(
                    $srcOpt,
                    $dep->option,
                    implode( ', ', $dep->values )
                );
            }
        }
    }

    /**
     * Validated option exclusions.
     *
     * Validates exclusions by $option.
     *
     * @param ezcConsoleOption $option.
     */
    private function validateExclusions( ezcConsoleOption $option )
    {
        $optSet = ( $option->value !== false
            && ( !is_array( $option->value ) || $option->value !== array() ) );

        foreach ( $option->getExclusions() as $excl )
        {
            if ( $excl->ifSet === $optSet )
            {
                $this->validateExclusion( $option, $excl );
            }
        }
    }

    /**
     * Validates a single exclusion.
     *
     * Validates the exclusion $excl, which is set in the $srcOpt.
     *
     * @param ezcConsoleOption $srcOpt
     * @param ezcConsoleOptionRule $excl
     */
    private function validateExclusion( ezcConsoleOption $srcOpt, ezcConsoleOptionRule $excl )
    {
        $optValue = $excl->option->value;

        if ( $optValue !== false && $optValue !== array() && $excl->values === array() )
        {
            throw new ezcConsoleOptionExclusionViolationException(
                $srcOpt,
                $excl->option
            );
        }

        $optVals = ( is_array( $optValue ) ? $optValue : array( $optValue ) );
        $forbiddenVals = array_intersect( $optVals, $excl->values );
        if ( $forbiddenVals !== array() )
        {
            throw new ezcConsoleOptionExclusionViolationException(
                $srcOpt,
                $excl->option,
                implode( ', ', $excl->values )
            );
        }
    }
}

?>
PK��ZT\�G�G�ezc/ConsoleTools/input.phpnu�[���<?php
/**
 * File containing the ezcConsoleInput class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */

/**
 * The ezcConsoleInput class handles the given options and arguments on the console.
 * 
 * This class allows the complete handling of options and arguments submitted
 * to a console based application.
 *
 * The next example demonstrate how to capture the console options: 
 * 
 * <code>
 * $optionHandler = new ezcConsoleInput();
 * 
 * // Register simple parameter -h/--help
 * $optionHandler->registerOption( new ezcConsoleOption( 'h', 'help' ) );
 * 
 * // Register complex parameter -f/--file
 * $file = new ezcConsoleOption(
 *  'f',
 *  'file',
 *  ezcConsoleInput::TYPE_STRING,
 *  null,
 *  false,
 *  'Process a file.',
 *  'Processes a single file.'
 * );
 * $optionHandler->registerOption( $file );
 * 
 * // Manipulate parameter -f/--file after registration
 * $file->multiple = true;
 * 
 * // Register another complex parameter that depends on -f and excludes -h
 * $dir = new ezcConsoleOption(
 *  'd',
 *  'dir',
 *  ezcConsoleInput::TYPE_STRING,
 *  null,
 *  true,
 *  'Process a directory.',
 *  'Processes a complete directory.',
 *  array( new ezcConsoleOptionRule( $optionHandler->getOption( 'f' ) ) ),
 *  array( new ezcConsoleOptionRule( $optionHandler->getOption( 'h' ) ) )
 * );
 * $optionHandler->registerOption( $dir );
 * 
 * // Register an alias for this parameter
 * $optionHandler->registerAlias( 'e', 'extended-dir', $dir );
 * 
 * // Process registered parameters and handle errors
 * try
 * {
 *      $optionHandler->process( array( 'example_input.php', '-h' ) );
 * }
 * catch ( ezcConsoleOptionException $e )
 * {
 *      echo $e->getMessage();
 *      exit( 1 );
 * }
 * 
 * // Process a single parameter
 * $file = $optionHandler->getOption( 'f' );
 * if ( $file->value === false )
 * {
 *      echo "Parameter -{$file->short}/--{$file->long} was not submitted.\n";
 * }
 * elseif ( $file->value === true )
 * {
 *      echo "Parameter -{$file->short}/--{$file->long} was submitted without value.\n";
 * }
 * else
 * {
 *      echo "Parameter -{$file->short}/--{$file->long} was submitted with value '".var_export($file->value, true)."'.\n";
 * }
 * 
 * // Process all parameters at once:
 * foreach ( $optionHandler->getOptionValues() as $paramShort => $val )
 * {
 *      switch ( true )
 *      {
 *          case $val === false:
 *              echo "Parameter $paramShort was not submitted.\n";
 *              break;
 *          case $val === true:
 *              echo "Parameter $paramShort was submitted without a value.\n";
 *              break;
 *          case is_array( $val ):
 *              echo "Parameter $paramShort was submitted multiple times with value: '".implode(', ', $val)."'.\n";
 *              break;
 *          default:
 *              echo "Parameter $paramShort was submitted with value: '$val'.\n";
 *              break;
 *      }
 * }
 * </code>
 * 
 * @package ConsoleTools
 * @version 1.6.1
 * @mainclass
 *
 * @property ezcConsoleArguments $argumentDefinition Optional argument definition.
 */
class ezcConsoleInput
{
    /**
     * Option does not carry a value.
     */
    const TYPE_NONE     = 1;

    /**
     * Option takes an integer value.
     */
    const TYPE_INT      = 2;

    /**
     * Option takes a string value. 
     */
    const TYPE_STRING   = 3;

    /**
     * Array of option definitions, indexed by number.
     *
     * This array stores the ezcConsoleOption objects representing
     * the options.
     *
     * For lookup of an option after its short or long values the attributes
     * {@link ezcConsoleInput::$optionShort}
     * {@link ezcConsoleInput::$optionLong}
     * are used.
     * 
     * @var array(array)
     */
    private $options = array();

    /**
     * Short option names. 
     *
     * Each references a key in {@link ezcConsoleInput::$options}.
     * 
     * @var array(string=>int)
     */
    private $optionShort = array();

    /**
     * Long option names. 
     * 
     * Each references a key in {@link ezcConsoleInput::$options}.
     * 
     * @var array(string=>int)
     */
    private $optionLong = array();

    /**
     * Arguments, if submitted, are stored here. 
     * 
     * @var array(string)
     */
    private $arguments = array();

    /**
     * Wether the process() method has already been called.
     * 
     * @var bool
     */
    private $processed = false;

    /**
     * Indicates if an option was submitted, that has the isHelpOption flag set.
     * 
     * @var bool
     */
    private $helpOptionSet = false;

    /**
     * Tool object for multi-byte encoding safe string operations. 
     * 
     * @var ezcConsoleStringTool
     */
    private $stringTool;

    /**
     * Input validator.
     *
     * @var ezcConsoleInputValidator
     */
    private $validator;

    /**
     * Help generator. 
     * 
     * @var ezcConsoleInputHelpGenerator
     */
    private $helpGenerator;

    /**
     * Collection of properties. 
     * 
     * @var array(string=>mixed)
     */
    protected $properties = array();

    /**
     * Creates an input handler.
     */
    public function __construct()
    {
        $this->argumentDefinition = null;
        $this->stringTool         = new ezcConsoleStringTool();

        // @TODO Verify interface and make plugable
        $this->validator     = new ezcConsoleStandardInputValidator();
        $this->helpGenerator = new ezcConsoleInputStandardHelpGenerator( $this );
    }

    /**
     * Registers the new option $option.
     *
     * This method adds the new option $option to your option collection. If
     * already an option with the assigned short or long value exists, an
     * exception will be thrown.
     *
     * @see ezcConsoleInput::unregisterOption()
     *
     * @param ezcConsoleOption $option
     *
     * @return ezcConsoleOption The recently registered option.
     */
    public function registerOption( ezcConsoleOption $option )
    {
        foreach ( $this->optionShort as $short => $ref )
        {
            if ( $short === $option->short ) 
            {
                throw new ezcConsoleOptionAlreadyRegisteredException( $short );
            }
        }
        foreach ( $this->optionLong as $long => $ref )
        {
            if ( $long === $option->long ) 
            {
                throw new ezcConsoleOptionAlreadyRegisteredException( $long );
            }
        }
        $this->options[] = $option;
        $this->optionLong[$option->long] = $option;
        if ( $option->short !== "" )
        {
            $this->optionShort[$option->short] = $option;
        }
        return $option;
    }

    /**
     * Registers an alias for an option.
     *
     * Registers a new alias for an existing option. Aliases can
     * be used as if they were a normal option.
     *
     * The alias is registered with the short option name $short and the
     * long option name $long. The alias references to the existing 
     * option $option.
     *
     * @see ezcConsoleInput::unregisterAlias()
     *
     * @param string $short
     * @param string $long
     * @param ezcConsoleOption $option
     *
     *
     * @throws ezcConsoleOptionNotExistsException
     *         If the referenced option is not registered.
     * @throws ezcConsoleOptionAlreadyRegisteredException
     *         If another option/alias has taken the provided short or long name.
     * @return void
     */
    public function registerAlias( $short, $long, ezcConsoleOption $option )
    {
        if ( !isset( $this->optionShort[$option->short] ) || !isset( $this->optionLong[$option->long] ) )
        {
            throw new ezcConsoleOptionNotExistsException( $option->long );
        }
        if ( isset( $this->optionShort[$short] ) || isset( $this->optionLong[$long] ) )
        {
            throw new ezcConsoleOptionAlreadyRegisteredException( isset( $this->optionShort[$short] ) ? "-$short" : "--$long" );
        }
        $this->optionShort[$short] = $option;
        $this->optionLong[$long]   = $option;
    }

    /**
     * Registers options according to a string specification.
     *
     * Accepts a string to define parameters and registers all parameters as
     * options accordingly. String definition, specified in $optionDef, looks
     * like this:
     *
     * <code>
     * [s:|size:][u:|user:][a:|all:]
     * </code>
     *
     * This string registers 3 parameters:
     * -s / --size
     * -u / --user
     * -a / --all
     *
     * @param string $optionDef
     * @return void
     * 
     * @throws ezcConsoleOptionStringNotWellformedException 
     *         If provided string does not have the correct format.
     */
    public function registerOptionString( $optionDef ) 
    {
        $regex = '\[([a-z0-9-]+)([:?*+])?([^|]*)\|([a-z0-9-]+)([:?*+])?\]';
        // Check string for wellformedness
        if ( preg_match( "/^($regex)+$/", $optionDef ) == 0 )
        {
            throw new ezcConsoleOptionStringNotWellformedException( "Option definition not wellformed: \"$optionDef\"" );
        }
        if ( preg_match_all( "/$regex/", $optionDef, $matches ) )
        {
            foreach ( $matches[1] as $id => $short )
            {
                $option = null;
                $option = new ezcConsoleOption( $short, $matches[4][$id] );
                if ( !empty( $matches[2][$id] ) || !empty( $matches[5][$id] ) )
                {
                    switch ( !empty( $matches[2][$id] ) ? $matches[2][$id] : $matches[5][$id] )
                    {
                        case '*':
                            // Allows 0 or more occurances
                            $option->multiple = true;
                            break;
                        case '+':
                            // Allows 1 or more occurances
                            $option->multiple = true;
                            $option->type = self::TYPE_STRING;
                            break;
                        case '?':
                            $option->type = self::TYPE_STRING;
                            $option->default = '';
                            break;
                        default:
                            break;
                    }
                }
                if ( !empty( $matches[3][$id] ) )
                {
                    $option->default = $matches[3][$id];
                }
                $this->registerOption( $option );
            }
        }
    }

    /**
     * Removes an option.
     *
     * This function removes an option. All dependencies to that 
     * specific option are removed completely from every other registered 
     * option.
     *
     * @see ezcConsoleInput::registerOption()
     *
     * @param ezcConsoleOption $option The option object to unregister.
     *
     * @throws ezcConsoleOptionNotExistsException
     *         If requesting a not registered option.
     * @return void
     */
    public function unregisterOption( ezcConsoleOption $option )
    {
        $found = false;
        foreach ( $this->options as $id => $existParam )
        {
            if ( $existParam === $option )
            {
                $found = true;
                unset( $this->options[$id] );
                continue;
            }
            $existParam->removeAllExclusions( $option );
            $existParam->removeAllDependencies( $option );
        }
        if ( $found === false )
        {
            throw new ezcConsoleOptionNotExistsException( $option->long );
        }
        foreach ( $this->optionLong as $name => $existParam )
        {
            if ( $existParam === $option )
            {
                unset( $this->optionLong[$name] );
            }
        }
        foreach ( $this->optionShort as $name => $existParam )
        {
            if ( $existParam === $option )
            {
                unset( $this->optionShort[$name] );
            }
        }
    }
    
    /**
     * Removes an alias to an option.
     *
     * This function removes an alias with the short name $short and long
     * name $long.
     *
     * @see ezcConsoleInput::registerAlias()
     * 
     * @throws ezcConsoleOptionNoAliasException
     *      If the requested short/long name belongs to a real parameter instead.
     *
     * @param string $short
     * @param string $long
     * @return void
     *
     * @todo Check if $short and $long refer to the same option!
     */
    public function unregisterAlias( $short, $long )
    {
        foreach ( $this->options as $id => $option )
        {
            if ( $option->short === $short )
            {
                throw new ezcConsoleOptionNoAliasException( $short );
            }
            if ( $option->long === $long )
            {
                throw new ezcConsoleOptionNoAliasException( $long );
            }
        }
        if ( isset( $this->optionShort[$short] ) )
        {
            unset( $this->optionShort[$short] );
        }
        if ( isset( $this->optionLong[$long] ) )
        {
            unset( $this->optionLong[$long] );
        }
    }

    /**
     * Returns the definition object for the option with the name $name.
     *
     * This method receives the long or short name of an option and
     * returns the ezcConsoleOption object.
     * 
     * @param string $name  Short or long name of the option (without - or --).
     * @return ezcConsoleOption
     *
     * @throws ezcConsoleOptionNotExistsException 
     *         If requesting a not registered parameter.
     */
    public function getOption( $name )
    {
        $name = $name;
        if ( isset( $this->optionShort[$name] ) )
        {
            return $this->optionShort[$name];
        }
        if ( isset( $this->optionLong[$name] ) )
        {
            return $this->optionLong[$name];
        }
        throw new ezcConsoleOptionNotExistsException( $name );
    }

    /**
     * Process the input parameters.
     *
     * Actually process the input options and arguments according to the actual 
     * settings.
     * 
     * Per default this method uses $argc and $argv for processing. You can 
     * override this setting with your own input, if necessary, using the
     * parameters of this method. (Attention, first argument is always the pro
     * gram name itself!)
     *
     * All exceptions thrown by this method contain an additional attribute "option"
     * which specifies the parameter on which the error occurred.
     * 
     * @param array(string) $args The arguments
     * @return void
     *
     * @throws ezcConsoleOptionNotExistsException 
     *         If an option that was submitted does not exist.
     * @throws ezcConsoleOptionDependencyViolationException
     *         If a dependency rule was violated. 
     * @throws ezcConsoleOptionExclusionViolationException 
     *         If an exclusion rule was violated.
     * @throws ezcConsoleOptionTypeViolationException 
     *         If the type of a submitted value violates the options type rule.
     * @throws ezcConsoleOptionArgumentsViolationException 
     *         If arguments are passed although a parameter disallowed them.
     *
     * @see ezcConsoleOptionException
     */ 
    public function process( array $args = null )
    {
        if ( $this->processed )
        {
            $this->reset();
        }
        $this->processed = true;

        if ( !isset( $args ) )
        {
            $args = isset( $argv ) ? $argv : isset( $_SERVER['argv'] ) ? $_SERVER['argv'] : array();
        }

        $nextIndex = $this->processOptions( $args );

        if ( $this->helpOptionSet() )
        {
            // No need to parse arguments
            return;
        }

        $this->processArguments( $args, $nextIndex );

        $this->checkRules();

        $this->setOptionDefaults();
    }

    /**
     * Sets defaults for options that have not been submitted.
     *
     * Checks all options if they have been submited. If not and a default 
     * values is present, this is set as the options value.
     */
    private function setOptionDefaults()
    {
        foreach ( $this->options as $option )
        {
            if ( $option->value === false || $option->value === array() )
            {
                // Default value to set?
                if ( $option->default !== null )
                {
                    $option->value = $option->default;
                }
            }
        }
    }

    /**
     * Reads the submitted options from $args array.
     *
     * Returns the next index to check for arguments.
     * 
     * @param array(string) $args 
     * @returns int
     *
     * @throws ezcConsoleOptionNotExistsException
     *         if a submitted option does not exist.
     * @throws ezcConsoleOptionTooManyValuesException
     *         if an option that expects only a single value was submitted 
     *         with multiple values.
     * @throws ezcConsoleOptionTypeViolationException
     *         if an option was submitted with a value of the wrong type.
     * @throws ezcConsoleOptionMissingValueException
     *         if an option thats expects a value was submitted without.
     */
    private function processOptions( array $args )
    {
        $numArgs = count( $args );
        $i = 1;

        while ( $i < $numArgs )
        {
            if ( $args[$i] === '--' )
            {
                break;
            }

            // Equalize parameter handling (long params with =)
            if ( iconv_substr( $args[$i], 0, 2, 'UTF-8' ) == '--' )
            {
                $this->preprocessLongOption( $args, $i );
                // Update number of args, changed by preprocessLongOption()
                $numArgs = count( $args );
            }

            // Check for parameter
            if ( iconv_substr( $args[$i], 0, 1, 'UTF-8' ) === '-' )
            {
                if ( !$this->hasOption( preg_replace( '/^-*/', '', $args[$i] ) ) )
                {
                    throw new ezcConsoleOptionNotExistsException( $args[$i] );
                }
                $this->processOption( $args, $i );
            }
            // Must be the arguments
            else
            {
                break;
            }
        }

        // Move pointer over argument sign
        isset( $args[$i] ) && $args[$i] == '--' ? ++$i : $i;

        return $i;
    }

    /**
     * Resets all option and argument values.
     *
     * This method is called automatically by {@link process()}, if this method
     * is called twice or more, and may also be used to manually reset the
     * values of all registered {@ezcConsoleOption} and {@link
     * ezcConsoleArgument} objects.
     */
    public function reset()
    {
        foreach ( $this->options as $option )
        {
            $option->value = false;
        }
        if ( $this->argumentDefinition !== null )
        {
            foreach ( $this->argumentDefinition as $argument )
            {
                $argument->value = null;
            }
        }
        $this->arguments = array();
    }

    /**
     * Returns true if an option with the given name exists, otherwise false.
     *
     * Checks if an option with the given name is registered.
     * 
     * @param string $name Short or long name of the option.
     * @return bool True if option exists, otherwise false.
     */
    public function hasOption( $name )
    {
        try
        {
            $param = $this->getOption( $name );
        }
        catch ( ezcConsoleOptionNotExistsException $e )
        {
            return false;
        }
        return true;
    }

    /**
     * Returns an array of all registered options.
     *
     * Returns an array of all registered options in the following format:
     * <code>
     * array( 
     *      0 => ezcConsoleOption,
     *      1 => ezcConsoleOption,
     *      2 => ezcConsoleOption,
     *      ...
     * );
     * </code>
     *
     * @return array(string=>ezcConsoleOption) Registered options.
     */
    public function getOptions()
    {
        return $this->options;
    }

    /**
     * Returns the values of all submitted options.
     *
     * Returns an array of all values submitted to the options. The array is 
     * indexed by the parameters short name (excluding the '-' prefix). The array
     * does not contain any parameter, which value is 'false' (meaning: the
     * parameter was not submitted).
     * 
     * @param bool $longnames Wheather to use longnames for indexing.
     * @return array(string=>mixed)
     */
    public function getOptionValues( $longnames = false )
    {
        $res = array();
        foreach ( $this->options as $param )
        {
            if ( $param->value !== false ) 
            {
                $res[( $longnames === true ) ? $param->long : $param->short] = $param->value;
            }
        }
        return $res;
    }

    /**
     * Returns arguments provided to the program.
     *
     * This method returns all arguments provided to a program in an
     * int indexed array. Arguments are sorted in the way
     * they are submitted to the program. You can disable arguments
     * through the 'arguments' flag of a parameter, if you want
     * to disallow arguments.
     *
     * Arguments are either the last part of the program call (if the
     * last parameter is not a 'multiple' one) or divided via the '--'
     * method which is commonly used on Unix (if the last parameter
     * accepts multiple values this is required).
     *
     * @return array(string) Arguments.
     */
    public function getArguments()
    {
        return $this->arguments;
    }

    /**
     * Get help information for your options.
     *
     * This method returns an array of help information for your options,
     * indexed by int. Each help info has 2 fields:
     *
     * 0 => The options names ("<short> / <long>")
     * 1 => The help text (depending on the $long parameter)
     *
     * The $long options determines if you want to get the short or long help
     * texts. The array returned can be used by {@link ezcConsoleTable}.
     *
     * If using the second options, you can filter the options shown in the
     * help output (e.g. to show short help for related options). Provide
     * as simple number indexed array of short and/or long values to set a filter.
     *
     * The $paramGrouping option can be used to group options in the help
     * output. The structure of this array parameter is as follows:
     *
     * <code>
     *  array(
     *      'First section' => array(
     *          'input',
     *          'output'
     *          'overwrite',
     *      ),
     *      'Second section' => array(
     *          'v',
     *          'h',
     *      ),
     *  )
     * </code>
     *
     * As can be seen, short option names are possible as well as long ones.
     * The key of the first array level is the name of the section, which is
     * assigned to an array of options to group under this section. The $params
     * parameter still influences if an option is displayed at all.
     * 
     * @param bool $long
     * @param array(string) $params
     * @param array(string=>array(string)) $paramGrouping
     * @return array(array(string)) Table structure as explained.
     * 
     * @apichange In future versions, the default values of $params will change 
     *            to null instead of an empty array. Giving an empty array for 
     *            these will then be taken literally.
     */
    public function getHelp( $long = false, array $params = array(), array $paramGrouping = null )
    {
        // New handling
        $params = ( $params === array() || $params === null ? null : $params );

        $help = array();
        if ( $paramGrouping === null )
        {
            // Original handling
            $help = $this->getOptionHelpWithoutGrouping( $long, $params );
        }
        else
        {
            $help = $this->getOptionHelpWithGrouping( $long, $params, $paramGrouping );
        }

        if ( $this->argumentDefinition !== null )
        {
            $help[] = array( "Arguments:", '' );

            $argumentsHelp = $this->helpGenerator->generateArgumentHelp( $long );
            if ( $argumentsHelp === array() )
            {
                $help[] = array( '', "No arguments available." );
            }
            else
            {
                $help = array_merge( $help, $argumentsHelp );
            }
        }

        return $help;
    }

    /**
     * Creates the option help array in the original, ungrouped way.
     *
     * Creates the original help array generated by {@link getHelp()}. The
     * $long and $params options are the same as they are for this method.
     * 
     * @param bool $long 
     * @param array $params 
     * @return array
     */
    private function getOptionHelpWithoutGrouping( $long, $params )
    {
        return $this->helpGenerator->generateUngroupedOptionHelp(
            $long,
            $params
        );
    }

    /**
     * Generates options helo array with ordering and grouping.
     * 
     * @param mixed $long 
     * @param mixed $params 
     * @param mixed $paramGrouping 
     * @return array()
     */
    private function getOptionHelpWithGrouping( $long, $params, $paramGrouping )
    {
        $rawHelp = $this->helpGenerator->generateGroupedOptionHelp(
            $paramGrouping,
            $long,
            $params
        );

        $help  = array();
        $first = true;
        foreach ( $rawHelp as $category => $optionsHelp )
        {
            if ( !$first )
            {
                $help[] = array( '', '' );
            }
            else
            {
                $first = false;
            }

            $help[] = array( $category, '' );
            $help = array_merge( $help, $optionsHelp );
        }
        return $help;
    }

    
    /**
     * Get help information for your options as a table.
     *
     * This method provides the information returned by 
     * {@link ezcConsoleInput::getHelp()} in a table.
     *
     * The $paramGrouping option can be used to group options in the help
     * output. The structure of this array parameter is as follows:
     *
     * <code>
     *  array(
     *      'First section' => array(
     *          'input',
     *          'output'
     *          'overwrite',
     *      ),
     *      'Second section' => array(
     *          'v',
     *          'h',
     *      ),
     *  )
     * </code>
     *
     * As can be seen, short option names are possible as well as long ones.
     * The key of the first array level is the name of the section, which is
     * assigned to an array of options to group under this section. The $params
     * parameter still influences if an option as displayed at all.
     * 
     * @param ezcConsoleTable $table     The table object to fill.
     * @param bool $long                 Set this to true for getting the 
     *                                   long help version.
     * @param array(string) $params Set of option names to generate help 
     *                                   for, default is all.
     * @param array(string=>array(string)) $paramGrouping
     * @return ezcConsoleTable           The filled table.
     */
    public function getHelpTable( ezcConsoleTable $table, $long = false, array $params = array(), $paramGrouping = null )
    {
        $help = $this->getHelp( $long, $params, $paramGrouping );
        $i = 0;
        foreach ( $help as $row )
        {
            $table[$i][0]->content = $row[0];
            $table[$i++][1]->content = $row[1];
        }
        return $table;
    }

    /**
     * Returns a standard help output for your program.
     *
     * This method generates a help text as it's commonly known from Unix
     * command line programs. The output will contain the synopsis, your 
     * provided program description and the selected parameter help
     * as also provided by {@link ezcConsoleInput::getHelp()}. The returned
     * string can directly be printed to the console.
     *
     * The $paramGrouping option can be used to group options in the help
     * output. The structure of this array parameter is as follows:
     *
     * <code>
     *  array(
     *      'First section' => array(
     *          'input',
     *          'output'
     *          'overwrite',
     *      ),
     *      'Second section' => array(
     *          'v',
     *          'h',
     *      ),
     *  )
     * </code>
     *
     * As can be seen, short option names are possible as well as long ones.
     * The key of the first array level is the name of the section, which is
     * assigned to an array of options to group under this section. The $params
     * parameter still influences if an option as displayed at all.
     * 
     * @param string $programDesc        The description of your program.
     * @param int $width                 The width to adjust the output text to.
     * @param bool $long                 Set this to true for getting the long 
     *                                   help version.
     * @param array(string) $params Set of option names to generate help 
     *                                   for, default is all.
     * @param array(string=>array(string)) $paramGrouping
     * @return string The generated help text.
     */
    public function getHelpText( $programDesc, $width = 80, $long = false, array $params = null, $paramGrouping = null )
    {
        $help = $this->getHelp( $long, ( $params == null ? array() : $params ), $paramGrouping );

        // Determine max length of first column text.
        $maxLength = 0;
        foreach ( $help as $row )
        {
            $maxLength = max( $maxLength, iconv_strlen( $row[0], 'UTF-8' ) );
        }

        // Width of left column
        $leftColWidth = $maxLength + 2;
        // Width of righ column
        $rightColWidth = $width - $leftColWidth;

        $res = 'Usage: ' . $this->getSynopsis( $params ) . PHP_EOL;
        $res .= $this->stringTool->wordwrap( $programDesc, $width, PHP_EOL );
        $res .= PHP_EOL . PHP_EOL;
        foreach ( $help as $row )
        {
            $rowParts = explode(
                "\n",
                $this->stringTool->wordwrap( $row[1], $rightColWidth )
            );

            $res .= $this->stringTool->strPad( $row[0], $leftColWidth, ' ' );
            $res .= $rowParts[0] . PHP_EOL;
            // @TODO: Fix function call in loop header
            for ( $i = 1; $i < sizeof( $rowParts ); $i++ )
            {
                $res .= str_repeat( ' ', $leftColWidth ) . $rowParts[$i] . PHP_EOL;
            }
        }
        return $res;
    }

    /**
     * Returns the synopsis string for the program.
     *
     * This gives you a synopsis definition for the options and arguments 
     * defined with this instance of ezcConsoleInput. You can filter the 
     * options named in the synopsis by submitting their short names in an
     * array as the parameter of this method. If the parameter $optionNames
     * is set, only those options are listed in the synopsis. 
     * 
     * @param array(string) $optionNames
     * @return string
     */
    public function getSynopsis( array $optionNames = null )
    {
        return $this->helpGenerator->generateSynopsis( $optionNames );
    }

    /**
     * Returns if a help option was set.
     * This method returns if an option was submitted, which was defined to be
     * a help option, using the isHelpOption flag.
     * 
     * @return bool If a help option was set.
     */
    public function helpOptionSet()
    {
        return $this->helpOptionSet;
    }

    /**
     * Property read access.
     *
     * @throws ezcBasePropertyNotFoundException 
     *         If the the desired property is not found.
     * 
     * @param string $propertyName Name of the property.
     * @return mixed Value of the property or null.
     * @ignore
     */
    public function __get( $propertyName )
    {
        if ( !isset( $this->$propertyName ) )
        {
                throw new ezcBasePropertyNotFoundException( $propertyName );
        }
        return $this->properties[$propertyName];
    }

    /**
     * Property set access.
     * 
     * @param string $propertyName 
     * @param string $propertyValue 
     * @ignore
     * @return void
     */
    public function __set( $propertyName, $propertyValue )
    {
        switch ( $propertyName )
        {
            case "argumentDefinition":
                if ( ( $propertyValue instanceof ezcConsoleArguments ) === false && $propertyValue !== null )
                {
                    throw new ezcBaseValueException( $propertyName, $propertyValue, "ezcConsoleArguments" );
                }
                break;
            default:
                throw new ezcBasePropertyNotFoundException( $propertyName );
        }
        $this->properties[$propertyName] = $propertyValue;
    }
    
    /**
     * Property isset access.
     * 
     * @param string $propertyName Name of the property.
     * @return bool True if the property is set, otherwise false.
     * @ignore
     */
    public function __isset( $propertyName )
    {
        return array_key_exists( $propertyName, $this->properties );
    }

    /**
     * Returns the synopsis string for a single option and its dependencies.
     *
     * This method returns a part of the program synopsis, specifically for a
     * certain parameter. The method recursively adds depending parameters up
     * to the 2nd depth level to the synopsis. The second parameter is used
     * to store the short names of all options that have already been used in 
     * the synopsis (to avoid adding an option twice). The 3rd parameter 
     * determines the actual deps in the option dependency recursion to 
     * terminate that after 2 recursions.
     * 
     * @param ezcConsoleOption $option        The option to include.
     * @param array(string) $usedOptions Array of used option short names.
     * @param int $depth                      Current recursion depth.
     * @return string The synopsis for this parameter.
     *
     * @apichange This method is deprecates. Implement your own {@link 
     *            ezcConsoleInputHelpGenerator} instead, as soon as the 
     *            interface is made public.
     */
    protected function createOptionSynopsis( ezcConsoleOption $option, &$usedOptions, $depth = 0 )
    {
        $synopsis = '';

        // Break after a nesting level of 2
        if ( $depth++ > 2 || ( in_array( $option->short, $usedOptions['short'] ) && in_array( $option->long, $usedOptions['long'] ) ) ) return $synopsis;
        
        $usedOptions['short'][] = $option->short;
        $usedOptions['long'][]  = $option->long;
        
        $synopsis .= $option->short !== "" ? "-{$option->short}" : "--{$option->long}";

        if ( isset( $option->default ) )
        {
            $synopsis .= " " . ( $option->type === ezcConsoleInput::TYPE_STRING ? '"' : '' ) . $option->default . ( $option->type === ezcConsoleInput::TYPE_STRING ? '"' : '' );
        }
        else if ( $option->type !== ezcConsoleInput::TYPE_NONE )
        {
            $synopsis .= " ";
            switch ( $option->type )
            {
                case ezcConsoleInput::TYPE_STRING:
                    $synopsis .= "<string>";
                    break;
                case ezcConsoleInput::TYPE_INT:
                    $synopsis .= "<int>";
                    break;
            }
        }

        foreach ( $option->getDependencies() as $rule )
        {
            $deeperSynopsis = $this->createOptionSynopsis( $rule->option, $usedOptions, $depth );
            $synopsis .= ( iconv_strlen( trim( $deeperSynopsis ), 'UTF-8' ) > 0 
                ? ' ' . $deeperSynopsis
                : ''
            );
        }
        
        if ( $option->arguments === false )
        {
            $allowsArgs = false;
        }
        
        // Make the whole thing optional?
        if ( $option->mandatory === false )
        {
            $synopsis = "[$synopsis]";
        }

        return $synopsis . ' ';
    }

    /**
     * Process an option.
     *
     * This method does the processing of a single option. 
     * 
     * @param array(string) $args The arguments array.
     * @param int $i                   The current position in the arguments array.
     * @return void
     *
     * @throws ezcConsoleOptionTooManyValuesException
     *         If an option that expects only a single value was submitted 
     *         with multiple values.
     * @throws ezcConsoleOptionTypeViolationException
     *         If an option was submitted with a value of the wrong type.
     * @throws ezcConsoleOptionMissingValueException
     *         If an option thats expects a value was submitted without.
     */
    private function processOption( array $args, &$i )
    {
        $option = $this->getOption( preg_replace( '/^-+/', '', $args[$i++] ) );

        // Is the actual option a help option?
        if ( $option->isHelpOption === true )
        {
            $this->helpOptionSet = true;
        }
        // No value expected
        if ( $option->type === ezcConsoleInput::TYPE_NONE )
        {
            // No value expected
            if ( isset( $args[$i] ) && iconv_substr( $args[$i], 0, 1, 'UTF-8' ) !== '-' && sizeof( $args ) > ( $i + 1 ) )
            {
                // But one found
                throw new ezcConsoleOptionTypeViolationException( $option, $args[$i] );
            }
            // Multiple occurance possible
            if ( $option->multiple === true )
            {
                $option->value[] = true;
            }
            else
            {
                $option->value = true;
            }
            // Everything fine, nothing to do
            return $i;
        }
        // Value expected, check for it
        if ( isset( $args[$i] ) && iconv_substr( $args[$i], 0, 1, 'UTF-8' ) !== '-' )
        {
            // Type check
            if ( $this->isCorrectType( $option->type, $args[$i] ) === false )
            {
                throw new ezcConsoleOptionTypeViolationException( $option, $args[$i] );
            }
            // Multiple values possible
            if ( $option->multiple === true )
            {
                $option->value[] = $args[$i];
            }
            // Only single value expected, check for multiple
            elseif ( isset( $option->value ) && $option->value !== false )
            {
                throw new ezcConsoleOptionTooManyValuesException( $option );
            }
            else
            {
                $option->value = $args[$i];
            }
            $i++;
        }
        // Value found? If not, use default, if available
        if ( !isset( $option->value ) || $option->value === false || ( is_array( $option->value ) && count( $option->value ) === 0) ) 
        {
            throw new ezcConsoleOptionMissingValueException( $option );
        }
    }

    /**
     * Process arguments given to the program. 
     * 
     * @param array(string) $args The arguments array.
     * @param int $i                   Current index in arguments array.
     * @return void
     */
    private function processArguments( array $args, &$i )
    {
        $numArgs = count( $args );
        if ( $this->argumentDefinition === null || $this->argumentsAllowed() === false )
        {
            // Old argument handling, also used of a set option sets disallowing arguments
            while ( $i < $numArgs )
            {
                $this->arguments[] = $args[$i++];
            }
        }
        else
        {
            $mandatory = true;
            foreach ( $this->argumentDefinition as $arg )
            {
                // Check if all followinga arguments are optional
                if ( $arg->mandatory === false )
                {
                    $mandatory = false;
                }

                // Check if the current argument is present and mandatory
                if ( $mandatory === true )
                {
                    if ( !isset( $args[$i] ) )
                    {
                        throw new ezcConsoleArgumentMandatoryViolationException( $arg );
                    }
                }
                else
                {
                    // Arguments are optional, if no more left: return.
                    if ( !isset( $args[$i] ) )
                    {
                        // Optional and no more arguments left, assign default
                        $arg->value = $arg->default;
                        continue;
                    }
                }

                if ( $arg->multiple === true )
                {
                    $arg->value = array();
                    for ( $i = $i; $i < $numArgs; ++$i )
                    {
                        if ( $this->isCorrectType( $arg->type, $args[$i] ) === false )
                        {
                            throw new ezcConsoleArgumentTypeViolationException( $arg, $args[$i] );
                        }
                        $arg->value = array_merge( $arg->value, array( $args[$i] ) );
                        // Keep old handling, too
                        $this->arguments[] = $args[$i];
                    }
                    return;
                }
                else
                {
                    if ( $this->isCorrectType( $arg->type, $args[$i] ) === false )
                    {
                        throw new ezcConsoleArgumentTypeViolationException( $arg, $args[$i] );
                    }
                    $arg->value = $args[$i];
                    // Keep old handling, too
                    $this->arguments[] = $args[$i];
                }
                ++$i;
            }

            if ( $i < $numArgs )
            {
                throw new ezcConsoleTooManyArgumentsException( $args, $i );
            }
        }
    }

    /**
     * Returns if arguments are allowed with the current option submition.
     * 
     * @return bool If arguments allowed.
     */
    protected function argumentsAllowed()
    {
        foreach ( $this->options as $id => $option )
        {
            if ( $option->value !== false && $option->arguments === false )
            {
                return false;
            }
        }
        return true;
    }

    /**
     * Check the rules that may be associated with an option.
     *
     * Options are allowed to have rules associated for dependencies to other
     * options and exclusion of other options or arguments. This method
     * processes the checks.
     *
     * @throws ezcConsoleException
     *         in case validation fails.
     */
    private function checkRules()
    {
        // If a help option is set, skip rule checking
        if ( $this->helpOptionSet === true )
        {
            return;
        }
        $this->validator->validateOptions(
            $this->options,
            ( $this->arguments !== array() )
        );
    }

    /**
     * Checks if a value is of a given type. Converts the value to the
     * correct PHP type on success.
     *  
     * @param int $type   The type to check for. One of self::TYPE_*.
     * @param string $val The value to check. Will possibly altered!
     * @return bool True on succesful check, otherwise false.
     */
    private function isCorrectType( $type, &$val )
    {
        $res = false;
        switch ( $type )
        {
            case ezcConsoleInput::TYPE_STRING:
                $res = true;
                $val = preg_replace( '/^(["\'])(.*)\1$/', '\2', $val );
                break;
            case ezcConsoleInput::TYPE_INT:
                $res = preg_match( '/^[0-9]+$/', $val ) ? true : false;
                if ( $res )
                {
                    $val = ( int ) $val;
                }
                break;
        }
        return $res;
    }

    /**
     * Split parameter and value for long option names. 
     * 
     * This method checks for long options, if the value is passed using =. If
     * this is the case parameter and value get split and replaced in the
     * arguments array.
     * 
     * @param array(string) $args The arguments array
     * @param int $i                   Current arguments array position
     * @return void
     */
    private function preprocessLongOption( array &$args, $i )
    {
        // Value given?
        if ( preg_match( '/^--\w+\=[^ ]/i', $args[$i] ) )
        {
            // Split param and value and replace current param
            $parts = explode( '=', $args[$i], 2 );
            array_splice( $args, $i, 1, $parts );
        }
    }
}
?>
PK��Z�Jq�VV$ezc/ConsoleTools/progressmonitor.phpnu�[���<?php
/**
 * File containing the ezcConsoleProgressMonitor class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */

/**
 * Printing structured status information on the console. 
 *
 * <code>
 * // Construction
 * $status = new ezcConsoleProgressMonitor( new ezcConsoleOutput(), 42 );
 *
 * // Run statusbar
 * foreach ( $files as $file )
 * {
 *      $res = $file->upload();
 *      // Add a status-entry to be printed.
 *      $status->addEntry( 'UPLOAD', $file->path );
 *      // Result like "    2.5% UPLOAD /var/upload/test.png"
 * }
 * </code>
 *  
 * @property ezcConsoleProgressMonitorOptions $options
 *           Contains the options for this class.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 * @mainclass
 */
class ezcConsoleProgressMonitor
{
    /**
     * Options
     *
     * @var ezcConsoleProgressMonitorOptions
     */
    protected $options;

    /**
     * The ezcConsoleOutput object to use.
     *
     * @var ezcConsoleOutput
     */
    protected $outputHandler;

    /**
     * Counter for the items already printed. 
     * 
     * @var int
     */
    protected $counter = 0;

    /**
     * The number of entries to expect. 
     * 
     * @var int
     */
    protected $max;

    /**
     * Creates a new progress monitor.
     * The $outputHandler parameter will be used to display the progress
     * monitor. $max is the number of monitor items to expect. $options can be
     * used to define the behaviour of the monitor
     * {@link ezcConsoleProgressMonitorOptions}.
     *
     * @param ezcConsoleOutput $outHandler   Handler to utilize for output
     * @param int $max                       Number of items to expect
     * @param array(string=>string) $options Options.
     *
     * @see ezcConsoleProgressMonitor::$options
     */
    public function __construct( ezcConsoleOutput $outHandler, $max, array $options = array() )
    {
        $this->outputHandler = $outHandler;
        $this->max = $max;
        $this->options = new ezcConsoleProgressMonitorOptions( $options );
    }

    /**
     * Property read access.
     * 
     * @param string $key Name of the property.
     * @return mixed Value of the property or null.
     *
     * @throws ezcBasePropertyNotFoundException
     *         If the the desired property is not found.
     */
    public function __get( $key )
    {
        switch ( $key )
        {
            case 'options':
                return $this->options;
                break;
        }
        throw new ezcBasePropertyNotFoundException( $key );
    }
    
    /**
     * Property write access.
     * 
     * @param string $propertyName Name of the property.
     * @param mixed $val  The value for the property.
     *
     * @throws ezcBaseValueException 
     *         If a the value for the property options is not an instance of 
     *         ezcConsoleProgressMonitorOptions. 
     * @return void
     */
    public function __set( $propertyName, $val )
    {
        switch ( $propertyName ) 
        {
            case 'options':
                if ( !( $val instanceof ezcConsoleProgressMonitorOptions ) )
                {
                    throw new ezcBaseValueException( $propertyName, $val, 'instance of ezcConsoleProgressMonitorOptions' );
                }
                $this->options = $val;
                return;
        }
        throw new ezcBasePropertyNotFoundException( $propertyName );
    }
    
    
    /**
     * Property isset access.
     * 
     * @param string $propertyName Name of the property.
     * @return bool True is the property is set, otherwise false.
     */
    public function __isset( $propertyName )
    {
        switch ( $propertyName )
        {
            case 'options':
                return true;
        }
        return false;
    }

    /**
     * Set new options.
     * This method allows you to change the options of an progress monitor.
     *  
     * @param ezcConsoleProgressMonitorOptions $options The options to set.
     *
     * @throws ezcBaseSettingNotFoundException
     *         If you tried to set a non-existent option value. 
     * @throws ezcBaseSettingValueException
     *         If the value is not valid for the desired option.
     * @throws ezcBaseValueException
     *         If you submit neither an array nor an instance of 
     *         ezcConsoleProgressMonitorOptions.
     */
    public function setOptions( $options ) 
    {
        if ( is_array( $options ) ) 
        {
            $this->options->merge( $options );
        } 
        else if ( $options instanceof ezcConsoleProgressMonitorOptions ) 
        {
            $this->options = $options;
        }
        else
        {
            throw new ezcBaseValueException( "options", $options, "instance of ezcConsoleProgressMonitorOptions" );
        }
    }

    /**
     * Returns the currently set options.
     * Returns the currently set option array.
     * 
     * @return ezcConsoleProgressMonitorOptions The options.
     */
    public function getOptions()
    {
        return $this->options;
    }
 
    /**
     * Print a status entry.
     * Prints a new status entry to the console and updates the internal counter.
     *
     * @param string $tag  The tag to print (second argument in the 
     *                     formatString).
     * @param string $data The data to be printed in the status entry (third 
     *                     argument in the format string).
     * @return void
     */
    public function addEntry( $tag, $data )
    {
        $this->counter++;
        $percentage = $this->counter / $this->max * 100;

        $this->outputHandler->outputLine(
            sprintf(
                $this->options['formatString'],
                $percentage,
                $tag,
                $data
            )
        );
    }
}
?>
PK��ZwQO~4ezc/ConsoleTools/interfaces/input_help_generator.phpnu�[���<?php
/**
 * File containing the ezcConsoleInputHelpGenerator interface.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */

/**
 * Interface for help generators used in ezcConsoleInput.
 *
 * An instance of a class implementing this interface is used in {@link 
 * ezcConsoleInput} to generate the help information.
 *
 * @package ConsoleTools
 * @version 1.6.1
 *
 * @access private
 * @TODO Verify interface and make it public to replace the validation in 
 *       {@link ezcConsoleInput}.
 */
interface ezcConsoleInputHelpGenerator
{
    /**
     * Creates a new help generator.
     *
     * Creates a new help generator for the given $input.
     * 
     * @param ezcConsoleInput $input
     */
    public function __construct( ezcConsoleInput $input );

    /**
     * Generates help information as a multidimensional array.
     *
     * This method generates a tabular view on the help information of a 
     * program. The returned array has the following structure:
     *
     * <code>
     * <?php
     * array(
     *  0 => array(
     *      0 => '<option short/long name>',
     *      1 => '<option help, depending on the $long parameter>'
     *  ),
     *  1 => array(
     *      0 => '<option short name> / <option long name>',
     *      1 => '<option help, depending on the $long parameter>'
     *  ),
     *  // ...
     * );
     * ?>
     * </code>
     *
     * Each row of the array represents the help information for a single option.
     * The first cell of a row contains the option name (maybe short, long or 
     * both), the second cell contains the help text of the option.
     *
     * The returned array is used by {@link ezcConsoleInput} for different 
     * purposes.
     * For example, the user can retrieve it raw through the
     * {@link ezcConsoleInput::getHelp()} method, he can generate a help
     * {@link ezcConsoleTable} through {@link ezcConsoleInput::getHelpTable()} 
     * are can generate a printable help text through {@link 
     * ezcConsoleInput::getHelpText()}.
     *
     * The parameter $long defines if the long or short help text of the 
     * options should be used in the second cell of the returned array. The
     * $optionsFilter parameter is used to restrict the generated help to a certain 
     * sub-set of options. It consists of an array of short or long names of 
     * the options to include.
     * 
     * @param bool $long 
     * @param array(string) $optionsFilter
     * @return array(array(string))
     */
    public function generateUngroupedOptionHelp( $long = false, array $optionsFilter = null );

    /**
     * Generates help information as a multidimensional array, grouped in categories.
     *
     * This method behaves similar to {@link generateUngroupedOptionHelp()}. In 
     * contrast to the latter one, this method returns an array with 1 
     * dimension more, grouping options into categories. The $groups parameter 
     * defines the categories to generate. Each category may contain an 
     * arbitrary number of options, options might occur in different 
     * categories.
     *
     * The returned array has the follorwing format:
     *
     * <code>
     * <?php
     * array(
     *  '<category name>' => array(
     *      0 => array(
     *          0 => '<option short/long name>',
     *          1 => '<option help, depending on the $long parameter>'
     *      ),
     *      1 => array(
     *          0 => '<option short name> / <option long name>',
     *          1 => '<option help, depending on the $long parameter>'
     *      ),
     *      // ...
     *  ),
     *  '<category name>' => array(
     *      // ...
     *  ),
     *  // ...
     * );
     * ?>
     * </code>
     *
     * The $long parameter, as in {@link generateUngroupedOptionHelp()} 
     * determines if the options short or long help is to be used. The
     * $params array can in addition be used to determine if a parameter
     * is displayed at all. If $optionsFilter is submitted and is not null, 
     * only options listed in it will be shown in the help at all.
     * 
     * @param array(string=>array(string)) $groups
     * @param bool $long 
     * @param array(string) $params 
     * @return array(string=>array(array(string)))
     */
    public function generateGroupedOptionHelp( array $groups, $long = false, array $optionsFilter = null );

    /**
     * Generates help information as a multi-dimensonal array for the given $argumentDefinition.
     *
     * This method generates a tabular help information for the given 
     * $argumentDefinition in the following format:
     *
     * <code>
     * <?php
     * array(
     *  0 => array(
     *      0 => '<argument synopsis>',
     *      1 => '<argument help text>'
     *  ),
     *  1 => array(
     *      0 => '<argument synopsis>',
     *      1 => '<argument help text>'
     *  ),
     *  // ...
     * )
     * ?>
     * </code>
     *
     * The $long parameter defines if the long of short help text should be 
     * used.
     * 
     * @param bool $long
     * @return array(array(string))
     */
    public function generateArgumentHelp( $long = false );

    /**
     * Generates a command line synopsis for the options and arguments.
     *
     * This method generates a synopsis string that lists the options and 
     * parameters available, indicating their usage.
     *
     * @return string
     */
    public function generateSynopsis( array $optionFilter = null );
}

?>
PK��Z�9c"9ezc/ConsoleTools/interfaces/question_dialog_validator.phpnu�[���<?php
/**
 * File containing the ezcConsoleQuestionDialogValidator interface.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * Interface that every console question dialog validator class must implement.
 *
 * @package ConsoleTools
 * @version 1.6.1
 */
interface ezcConsoleQuestionDialogValidator extends ezcConsoleDialogValidator
{

    /**
     * Returns a string of possible results to be displayed with the question. 
     * For example "(y/n) [y]" to indicate "y" and "n" are valid values and "y" is
     * preselected.
     *
     * @return string The result string.
     */
    public function getResultString();
}

?>
PK��Z%uu/ezc/ConsoleTools/interfaces/input_validator.phpnu�[���<?php
/**
 * File containing the ezcConsoleInputValidator interface.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */
/**
 * Interface for input validators used in ezcConsoleInput.
 *
 * An instance of this interface is used in {@link ezcConsoleInput} to validate 
 * options and arguments.
 * 
 * @package ConsoleTools
 * @version 1.6.1
 *
 * @access private
 * @TODO Verify interface and make it public to replace the validation in 
 *       {@link ezcConsoleInput}.
 */
interface ezcConsoleInputValidator
{
    /**
     * Validates the given options.
     *
     * May throw an exception that derives from {@link ezcConsoleException}.  
     * Receives the array of $options defined for validation and $hasArguments 
     * to indicates if arguments have been submitted in addition.
     *
     * @param array(ezcConsoleOption) $options
     * @param bool $hasArguments
     */
    public function validateOptions( array $options, $hasArguments );

    // @TODO: validateArguments();
}

?>
PK��Z�+���5ezc/ConsoleTools/interfaces/menu_dialog_validator.phpnu�[���<?php
/**
 * File containing the ezcConsoleMenuDialogValidator interface.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * Interface that every console menu dialog validator class must implement.
 *
 * @package ConsoleTools
 * @version 1.6.1
 */
interface ezcConsoleMenuDialogValidator extends ezcConsoleQuestionDialogValidator
{

    /**
     * Returns an array of the elements to display. 
     * 
     * @return array(string=>string) Elements to display.
     */
    public function getElements();

}

?>
PK��ZA�
NS
S
&ezc/ConsoleTools/interfaces/dialog.phpnu�[���<?php
/**
 * File containing the ezcConsoleDialog interface.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * Interface that every console dialog class must implement.
 *
 * Console dialogs can either be used on their own or using the
 * {@link ezcConsoleDialogViewer} (recommended). In the dialog viewer, a dialog
 * is instanciated and displayed in a loop, until it receives a valid result
 * value.
 *
 * @package ConsoleTools
 * @version 1.6.1
 */
interface ezcConsoleDialog
{

    /**
     * Create a new dialog object.
     * This method retrieves an ezcConsoleOutput object for printing its
     * content. Additionally an instance of ezcConsoleDialogOptions or a derived
     * class is received to configure the behaviour of the dialog. Dialog
     * implementations may extend ezcConsoleDialogOptions and require an
     * instance of their extended class as options.
     * 
     * @param ezcConsoleOutput $output         Output object.
     * @param ezcConsoleDialogOptions $options Options.
     * @return void
     */
    // public function __construct( ezcConsoleOutput $output, ezcConsoleDialogOptions $options = null );

    /**
     * Returns if the dialog retrieved a valid result.
     * Typically a dialog is displayed in a loop until he received a valid
     * result. What a valid result is, is determined by the dialog itself.
     * 
     * @return bool If a valid result was retrieved.
     */
    public function hasValidResult();

    /**
     * Returns the result retrieved.
     * If no valid result was retreived, yet, this method should throw an
     * {@link ezcDialogNoValidResultException}. Otherwise this method returns
     * the result.
     * 
     * @return mixed The retreived result.
     *
     * @throws ezcDialogNoValidResultException
     *         if this method is called without a valid result being retrieved
     *         by the object. Use {@link hasValidResult()} to avoid this
     *         exception.
     */
    public function getResult();

    /**
     * Displays the dialog.
     * Displays the dialog. Dialogs will most propably block the application until
     * the user took some interaction.
     * 
     * @return void
     */
    public function display();

    /**
     * Resets the dialog to its initial state. 
     * Resets the dialog to its orginal state in respect to its internal
     * changes. Note: Any changes you made to the options are kept in tact.
     * 
     * @return void
     */
    public function reset();
}

?>
PK��Ze��ެ�0ezc/ConsoleTools/interfaces/dialog_validator.phpnu�[���<?php
/**
 * File containing the ezcConsoleDialogValidator interface.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * Interface that every console dialog validator class must implement.
 *
 * @package ConsoleTools
 * @version 1.6.1
 */
interface ezcConsoleDialogValidator
{
    /**
     * Perform no conversion on the result. 
     */
    const CONVERT_NONE  = 0;

    /**
     * Convert result to lower-case. 
     */
    const CONVERT_LOWER = 1;

    /**
     * Convert result to upper-case. 
     */
    const CONVERT_UPPER = 2;

    /**
     * Returns if the given result is valid. 
     * 
     * @param mixed $result The received result.
     * @return bool If the result is valid.
     */
    public function validate( $result );

    /**
     * Returns a fixed version of the result, if possible.
     * This method tries to repair the submitted result, if it is not valid,
     * yet. Fixing can be done in different ways, like casting into a certain
     * datatype, string manipulation, creating an object. A result returned
     * by fixup must not necessarily be valid, so a dialog should call validate
     * after trying to fix the result.
     * 
     * @param mixed $result The received result.
     * @return mixed The manipulated result.
     */
    public function fixup( $result );

}

?>
PK��Z���4�J�Jezc/ConsoleTools/output.phpnu�[���<?php
/**
 * File containing the ezcConsoleOutput class.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @filesource
 */

/**
 * Class for handling console output.
 *
 * The ezcConsoleOutput class provides an interface to output text to the console. It deals with formating 
 * text in different ways and offers some comfortable options to deal
 * with console text output.
 *
 * <code>
 * // Create the output handler
 * $out = new ezcConsoleOutput();
 * 
 * // Set the verbosity to level 10
 * $out->options->verbosityLevel = 10;
 * // Enable auto wrapping of lines after 40 characters
 * $out->options->autobreak    = 40;
 * 
 * // Set the color of the default output format to green
 * $out->formats->default->color   = 'green';
 * 
 * // Set the color of the output format named 'success' to white
 * $out->formats->success->color   = 'white';
 * // Set the style of the output format named 'success' to bold
 * $out->formats->success->style   = array( 'bold' );
 * 
 * // Set the color of the output format named 'failure' to red
 * $out->formats->failure->color   = 'red';
 * // Set the style of the output format named 'failure' to bold
 * $out->formats->failure->style   = array( 'bold' );
 * // Set the background color of the output format named 'failure' to blue
 * $out->formats->failure->bgcolor = 'blue';
 * 
 * // Output text with default format
 * $out->outputText( 'This is default text ' );
 * // Output text with format 'success'
 * $out->outputText( 'including success message', 'success' );
 * // Some more output with default output.
 * $out->outputText( "and a manual linebreak.\n" );
 * 
 * // Manipulate the later output
 * $out->formats->success->color = 'green';
 * $out->formats->default->color = 'blue';
 * 
 * // This is visible, since we set verbosityLevel to 10, and printed in default format (now blue)
 * $out->outputText( "Some verbose output.\n", null, 10 );
 * // This is not visible, since we set verbosityLevel to 10
 * $out->outputText( "Some more verbose output.\n", null, 20 );
 * // This is visible, since we set verbosityLevel to 10, and printed in format 'failure'
 * $out->outputText( "And some not so verbose, failure output.\n", 'failure', 5 );
 * </code>
 *
 * For a list of valid colors, style attributes and background colors, please 
 * refer to {@link ezcConsoleOutputFormat}.
 *
 * ATTENTION: Windows operating systems do not support styling of text on the
 * console. Therefore no styling sequences are generated on any version of
 * this operating system.
 * 
 * @property ezcConsoleOutputOptions $options
 *           Contains the options for this class.
 * @property ezcConsoleOutputFormats $formats
 *           Contains the output formats.
 *
 * @package ConsoleTools
 * @version 1.6.1
 * @mainclass
 */
class ezcConsoleOutput
{

    /**
     * Target to print to standard out, with output buffering possibility.
     */
    const TARGET_OUTPUT = "php://output";

    /**
     * Target to print to standard out. 
     */
    const TARGET_STDOUT = "php://stdout";

    /**
     * Target to print to standard error. 
     */
    const TARGET_STDERR = "php://stderr";

    /**
     * Container to hold the properties
     *
     * @var array(string=>mixed)
     */
    protected $properties;

    /**
     * Whether a position has been stored before, using the storePos() method.
     *
     * @see ezcConsoleOutput::storePos()
     * @var bool
     */
    protected $positionStored = false;

    /**
     * Stores the mapping of color names to their escape
     * sequence values.
     *
     * @var array(string=>int)
     */
    protected static $color = array(
        'gray'          => 30,
        'black'         => 30,      // Alias black to gray (Bug #8478)
        'red'           => 31,
        'green'         => 32,
        'yellow'        => 33,
        'blue'          => 34,
        'magenta'       => 35,
        'cyan'          => 36,
        'white'         => 37,
        'default'       => 39
    );

    /**
     * Stores the mapping of bgcolor names to their escape
     * sequence values.
     * 
     * @var array(string=>int)
     */
    protected static $bgcolor = array(
        'gray'       => 40,      // Alias gray to black (Bug #8478)
        'black'      => 40,
        'red'        => 41,
        'green'      => 42,
        'yellow'     => 43,
        'blue'       => 44,
        'magenta'    => 45,
        'cyan'       => 46,
        'white'      => 47,
        'default'    => 49,
    );

    /**
     * Stores the mapping of styles names to their escape
     * sequence values.
     * 
     * @var array(string=>int)
     */
    protected static $style = array( 
        'default'           => '0',
    
        'bold'              => 1,
        'faint'             => 2,
        'normal'            => 22,
        
        'italic'            => 3,
        'notitalic'         => 23,
        
        'underlined'        => 4,
        'doubleunderlined'  => 21,
        'notunderlined'     => 24,
        
        'blink'             => 5,
        'blinkfast'         => 6,
        'noblink'           => 25,
        
        'negative'          => 7,
        'positive'          => 27,
    );

    /**
     * Basic escape sequence string. Use sprintf() to insert escape codes.
     * 
     * @var string
     */
    private $escapeSequence = "\033[%sm";

    /**
     * Collection of targets to print to. 
     * 
     * @var array
     */
    private $targets = array();

    /**
     * Create a new console output handler.
     *
     * @see ezcConsoleOutput::$options
     * @see ezcConsoleOutputOptions
     * @see ezcConsoleOutput::$formats
     * @see ezcConsoleOutputFormats
     *
     * @param ezcConsoleOutputFormats $formats Formats to be used for output.
     * @param array(string=>string) $options   Options to set.
     */
    public function __construct( ezcConsoleOutputFormats $formats = null, array $options = array() )
    {
        $options = isset( $options ) ? $options : new ezcConsoleOutputOptions();
        $formats = isset( $formats ) ? $formats : new ezcConsoleOutputFormats();
        $this->properties['options'] = new ezcConsoleOutputOptions( $options );
        $this->properties['formats'] = $formats;
    }
    
    /**
     * Set new options.
     * This method allows you to change the options of an output handler.
     *  
     * @param ezcConsoleOutputOptions $options The options to set.
     *
     * @throws ezcBaseSettingNotFoundException
     *         If you tried to set a non-existent option value. 
     * @throws ezcBaseSettingValueException
     *         If the value is not valid for the desired option.
     * @throws ezcBaseValueException
     *         If you submit neither an array nor an instance of 
     *         ezcConsoleOutputOptions.
     */
    public function setOptions( $options ) 
    {
        if ( is_array( $options ) ) 
        {
            $this->properties['options']->merge( $options );
        } 
        else if ( $options instanceof ezcConsoleOutputOptions ) 
        {
            $this->properties['options'] = $options;
        }
        else
        {
            throw new ezcBaseValueException( "options", $options, "instance of ezcConsoleOutputOptions" );
        }
    }

    /**
     * Returns the current options.
     * Returns the options currently set for this output handler.
     * 
     * @return ezcConsoleOutputOptions The current options.
     */
    public function getOptions()
    {
        return $this->properties['options'];
    }

    /**
     * Property read access.
     *
     * @throws ezcBasePropertyNotFoundException 
     *         If the the desired property is not found.
     * 
     * @param string $propertyName Name of the property.
     * @return mixed Value of the property or null.
     * @ignore
     */
    public function __get( $propertyName )
    {
        switch ( $propertyName ) 
        {
            case 'options':
            case 'formats':
                return $this->properties[$propertyName];
            default:
                break;
        }
        throw new ezcBasePropertyNotFoundException( $propertyName );
    }

    /**
     * Property write access.
     * 
     * @param string $propertyName Name of the property.
     * @param mixed $val  The value for the property.
     *
     * @throws ezcBaseValueException 
     *         If a the value for the property options is not an instance of 
     *         ezcConsoleOutputOptions. 
     * @throws ezcBaseValueException 
     *         If a the value for the property formats is not an instance of 
     *         ezcConsoleOutputFormats. 
     * @ignore
     */
    public function __set( $propertyName, $val )
    {
        switch ( $propertyName ) 
        {
            case 'options':
                if ( !( $val instanceof ezcConsoleOutputOptions ) )
                {
                    throw new ezcBaseValueException( $propertyName, $val, 'ezcConsoleOutputOptions' );
                }
                $this->properties['options'] = $val;
                return;
            case 'formats':
                if ( !( $val instanceof ezcConsoleOutputFormats ) )
                {
                    throw new ezcBaseValueException( $propertyName, $val, 'ezcConsoleOutputFormats' );
                }
                $this->properties['formats'] = $val;
                return;
            default:
                break;
        }
        throw new ezcBasePropertyNotFoundException( $propertyName );
    }
 
    /**
     * Property isset access.
     * 
     * @param string $propertyName Name of the property.
     * @return bool True is the property is set, otherwise false.
     * @ignore
     */
    public function __isset( $propertyName )
    {
        switch ( $propertyName )
        {
            case 'options':
            case 'formats':
                return true;
        }
        return false;
    }

    /**
     * Print text to the console.
     *
     * Output a string to the console. If $format parameter is omitted, the
     * default style is chosen. Style can either be a special style {@link
     * ezcConsoleOutput::$options}, a style name {@link
     * ezcConsoleOutput::$formats} or 'default' to print with the default
     * styling.
     *
     * The $format parameter defines the name of a format. Formats are defined
     * through the $formats proprty, which contains format definitions in form
     * of {@link ezcConsoleOutputFormat} objects. The format influences the
     * outer appearance of a message (e.g. color) as well as the target the
     * message is printed to (e.g. STDERR).
     *
     * @throws ezcConsoleInvalidOutputTargetException
     *         If the given target ({@link ezcConsoleOutputFormat}) could not 
     *         be opened for writing or writing failed.
     *
     * @param string $text        The text to print.
     * @param string $format      Format chosen for printing.
     * @param int $verbosityLevel On which verbose level to output this message.
     * @return void
     */
    public function outputText( $text, $format = 'default', $verbosityLevel = 1 ) 
    {
        if ( $this->properties['options']->verbosityLevel >= $verbosityLevel ) 
        {
            if ( is_int( $this->properties['options']->autobreak ) && $this->properties['options']->autobreak > 0 )
            {
                $textLines = preg_split( "(\r\n|\n|\r)", $text );
                foreach ( $textLines as $id => $textLine )
                {
                    $textLines[$id] = wordwrap( $textLine, $this->properties['options']->autobreak, PHP_EOL, true );
                }
                $text = implode( PHP_EOL, $textLines );
            }
            // Initialize target, if not happened before
            if ( !isset( $this->targets[$this->formats->$format->target] ) )
            {
                // @ to suppress the warning. We handle error cases with an
                // exception here.
                if ( ( $this->targets[$this->formats->$format->target] = @fopen( $this->formats->$format->target, "w" ) ) === false )
                {
                    throw new ezcConsoleInvalidOutputTargetException( $this->formats->$format->target );
                }
            }
            // Print using formats or without. Note: Since the target is a part
            // of the format, it will also be ignored, if you switch formats off!
            if ( $this->properties['options']->useFormats === true )
            {
                if ( fwrite( $this->targets[$this->formats->$format->target], $this->formatText( $text, $format ) ) === false )
                {
                    throw new ezcConsoleInvalidOutputTargetException( $this->formats->$format->target );
                }
            }
            else
            {
               echo $text;
            }
        }
    }

    /**
     * Print text to the console and automatically append a line break.
     *
     * This method acts similar to {@link ezcConsoleOutput::outputText()}, in
     * fact it even uses it. The difference is, that outputLine()
     * automatically appends a manual line break to the printed text. Besides
     * that, you can leave out the $text parameter of outputLine() to only
     * print a line break.
     *
     * The $format parameter defines the name of a format. Formats are defined
     * through the $formats proprty, which contains format definitions in form
     * of {@link ezcConsoleOutputFormat} objects. The format influences the
     * outer appearance of a message (e.g. color) as well as the target the
     * message is printed to (e.g. STDERR).
     * 
     * @param string $text        The text to print.
     * @param string $format      Format chosen for printing.
     * @param int $verbosityLevel On which verbose level to output this message.
     * @return void
     */
    public function outputLine( $text = '', $format = 'default', $verbosityLevel = 1 )
    {
        $this->outputText( $text . PHP_EOL, $format, $verbosityLevel );
    }

    /**
     * Returns a formated version of the text.
     *
     * If $format parameter is omitted, the default style is chosen. The format
     * must be a valid registered format definition.  For information on the
     * formats, see {@link ezcConsoleOutput::$formats}.
     *
     * @param string $text   Text to apply style to.
     * @param string $format Format chosen to be applied.
     * @return string
     */
    public function formatText( $text, $format = 'default' ) 
    {
        switch ( ezcBaseFeatures::os() )
        {
            case "Windows":
                return $text;
            default:
                return $this->buildSequence( $format ) . $text . $this->buildSequence( 'default' );
        }
    }

    /**
     * Stores the current cursor position.
     *
     * Saves the current cursor position to return to it using 
     * {@link ezcConsoleOutput::restorePos()}. Multiple calls
     * to this method will override each other. Only the last
     * position is saved.
     *
     * @return void
     */
    public function storePos() 
    {
        if ( ezcBaseFeatures::os() !== "Windows" )
        {
            echo "\0337";
            $this->positionStored = true;
        }
    }

    /**
     * Restores a cursor position.
     *
     * Restores the cursor position last saved using {@link
     * ezcConsoleOutput::storePos()}.
     *
     * @throws ezcConsoleNoPositionStoredException 
     *         If no position is saved.
     * @return void
     */
    public function restorePos() 
    {
        if ( ezcBaseFeatures::os() !== "Windows" )
        {
            if ( $this->positionStored === false )
            {
                throw new ezcConsoleNoPositionStoredException();
            }
            echo "\0338";
        }
    }

    /**
     * Move the cursor to a specific column of the current line.
     *
     * Moves the cursor to a specific column index of the current line (default
     * is 1).
     * 
     * @param int $column Column to jump to.
     * @return void
     */
    public function toPos( $column = 1 ) 
    {
        if ( ezcBaseFeatures::os() !== "Windows" )
        {
            echo "\033[{$column}G";
        }
    }

    /**
     * Returns if a format code is valid for the specific formating option.
     *
     * This method determines if a given code is valid for a specific
     * formatting option ('color', 'bgcolor' or 'style').
     * 
     * @see ezcConsoleOutput::getFormatCode();
     *
     * @param string $type Formating type.
     * @param string $key  Format option name.
     * @return bool True if the code is valid.
     */
    public static function isValidFormatCode( $type, $key )
    {
        return isset( self::${$type}[$key] );
    }

    /**
     * Returns the escape sequence for a specific format.
     *
     * Returns the default format escape sequence, if the requested format does
     * not exist.
     * 
     * @param string $format Name of the format.
     * @return string The escape sequence.
     */
    protected function buildSequence( $format = 'default' )
    {
        if ( $format === 'default' )
        {
            return sprintf( $this->escapeSequence, 0 );
        }
        $modifiers = array();
        $formats = array( 'color', 'style', 'bgcolor' );
        foreach ( $formats as $formatType ) 
        {
            // Get modifiers
            if ( is_array( $this->formats->$format->$formatType ) )
            {
                if ( !in_array( 'default', $this->formats->$format->$formatType ) )
                {
                    foreach ( $this->formats->$format->$formatType as $singleVal ) 
                    {
                        $modifiers[] = $this->getFormatCode( $formatType, $singleVal );
                    }
                }
            }
            else
            {
                if ( $this->formats->$format->$formatType !== 'default' )
                {
                    $modifiers[] = $this->getFormatCode( $formatType, $this->formats->$format->$formatType );
                }
            }
        }
        // Merge modifiers
        return sprintf( $this->escapeSequence, implode( ';', $modifiers ) );
    }

    /**
     * Returns the code for a given formating option of a given type.
     *
     * $type is the type of formating ('color', 'bgcolor' or 'style'), $key the
     * name of the format to lookup. Returns the numeric code for the requested
     * format or 0 if format or type do not exist.
     * 
     * @see ezcConsoleOutput::isValidFormatCode()
     * 
     * @param string $type Formatting type.
     * @param string $key  Format option name.
     * @return int The code representation.
     */
    protected function getFormatCode( $type, $key )
    {
        if ( !ezcConsoleOutput::isValidFormatCode( $type, $key ) ) 
        {
            return 0;
        }
        return ezcConsoleOutput::${$type}[$key];
    }

}
?>
PK��Zunš�w�wezc/Archive/archive.phpnu�[���<?php
/**
 * File containing the abstract ezcArchive class.
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * The ezcArchive class provides the common interface for reading and writing
 * the archive formats Tar and Zip.
 *
 * ezcArchive provides the main API for reading and writing to an archive. The
 * archive itself can be compressed with GZip or BZip2 and will be handled
 * transparently.
 *
 * The {@link open()} method creates a new archive instance. For
 * existing archives, ezcArchive determines the correct archive format by the
 * mime-type and returns an instance of a subclass handling this format.
 * New archives should force a format type via a parameter in the open()
 * method.
 *
 * The instance of an ezcArchive class is also an iterator, which
 * points to the first file in the archive by default. Moving this pointer can
 * be done via the iterator methods: {@link rewind()}, {@link next()},
 * {@link valid()}, {@link key()}, and {@link current()}. This iterator is
 * defined as an object iterator and allows, for example, the {@link
 * http://www.php.net/foreach foreach} statement to iterate through the files.
 *
 * Extra methods that operate on the current iterator are: {@link
 * extractCurrent()} and {@link appendToCurrent()}. Which can be used,
 * respectively, to extract the files and to append a new file to the archive.
 * To append a directory to an archive you need to add a slash '/' at the end
 * of the directory name.
 *
 * The following example will open an existing tar.gz file and will append each
 * file to a zip archive:
 * <code>
 * $tar = ezcArchive::open( "/tmp/archive.tar.gz" );
 * $newZip = ezcArchive::open( "/tmp/new_archive.zip", ezcArchive::ZIP );
 *
 * foreach ( $tar as $entry )
 * {
 *    // $entry contains the information of the current entry in the archive.
 *    $tar->extractCurrent( "/tmp/" );
 *    $newZip->appendToCurrent( $entry->getPath(), "/tmp/" );
 *    $newZip->next();
 * }
 * </code>
 *
 * In order to extract an entire archive at once, use the {@link extract()}
 * method.
 *
 * @package Archive
 * @version 1.4.1
 * @mainclass
 */
abstract class ezcArchive implements Iterator
{
    /**
     * Normal tar archive.
     */
    const TAR        = 0;

    /**
     * Tar version 7 archive.
     */
    const TAR_V7     = 1;

    /**
     * USTAR tar archive.
     */
    const TAR_USTAR  = 2;

    /**
     * PAX tar archive.
     */
    const TAR_PAX    = 3;

    /**
     * GNU tar archive.
     */
    const TAR_GNU    = 4;

    /**
     * ZIP archive.
     */
    const ZIP        = 10;

    /**
     * Gnu ZIP compression format.
     */
    const GZIP       = 20;

    /**
     * BZIP2 compression format.
     */
    const BZIP2      = 30;

    /**
     * The entry or file number to which the iterator points.
     *
     * The first $fileNumber starts with 0.
     *
     * @var int
     */
    protected $fileNumber = 0;

    /**
     * The number of entries currently read from the archive.
     *
     * @var int
     */
    protected $entriesRead = 0;

    /**
     * Is true when the archive is read until the end, otherwise false.
     *
     * @var bool
     */
    protected $completed = false;

    /**
     * Stores the entries read from the archive.
     *
     * The array is not complete when the {@link $completed} variable is set to
     * false.  The array may be over-complete, so the {@link $entriesRead}
     * should be checked if the {@link $completed} variable is set to true.
     *
     * @var array(ezcArchiveEntry)
     */
    protected $entries;

    /**
     * Direct access to the archive file.
     *
     * @var ezcArchiveFile
     */
    protected $file = null;

    /**
     * Holds the options if passed to the open method.
     *
     * @var ezcArchiveOptions
     */
    protected $options;

    /**
     * Use the {@link open()} method to get an instance of this class.
     */
    private function __construct()
    {
    }

    /**
     * Returns a new ezcArchive instance.
     *
     * This method returns a new instance according to the mime-type or
     * the given $forceType.
     *
     * - If $forceType is set to null, this method will try to determine the
     *   archive format via the file data. Therefore the $forceType can only be
     *   null when the archive contains data.
     * - If $forceType is set, it will use the specified algorithm. Even when
     *   the given archive is from another type than specified.
     *
     * @throws ezcArchiveUnknownTypeException if the type of the archive cannot be determined.
     *
     * @param string  $archiveName  Absolute or relative path to the archive.
     * @param int     $forceType    Open the archive with the $forceType
     *        algorithm. Possible values are: {@link ezcArchive::ZIP},
     *        {@link ezcArchive::TAR}, {@link ezcArchive::TAR_V7}, {@link ezcArchive::TAR_USTAR},
     *        {@link ezcArchive::TAR_PAX}, {@link ezcArchive::TAR_GNU}.
     *        TAR will use the TAR_USTAR algorithm by default.
     * @param ezcArchiveOptions $options
     *
     * @return ezcArchive
     */
    public static function open( $archiveName, $forceType = null, ezcArchiveOptions $options = null )
    {
        $options = self::initOptions( $options );

        if ( !ezcArchiveFile::fileExists( $archiveName ) && $forceType === null )
        {
            throw new ezcArchiveUnknownTypeException( $archiveName );
        }

        if ( $forceType !== null )
        {
            return self::createInstance( $archiveName, $forceType, $options );
        }

        $h = ezcArchiveFileType::detect( $archiveName );

        while ( $h == ezcArchive::GZIP || $h == ezcArchive::BZIP2 )
        {
            if ( $h == ezcArchive::GZIP )
            {
                $archiveName = "compress.zlib://$archiveName";
                $h = ezcArchiveFileType::detect( $archiveName );
            }

            if ( $h == ezcArchive::BZIP2 )
            {
                $archiveName = "compress.bzip2://$archiveName";
                $h = ezcArchiveFileType::detect( $archiveName );
            }
        }

        return self::createInstance( $archiveName, $h, $options );
    }

    /**
     * Close the current archive.
     */
    public function close()
    {
    }

    /**
     * Sets the property $name to $value.
     *
     * Because there are no properties available, this method will always
     * throw an {@link ezcBasePropertyNotFoundException}.
     *
     * @throws ezcBasePropertyNotFoundException if the property does not exist.
     * @param string $name
     * @param mixed $value
     * @ignore
     */
    public function __set( $name, $value )
    {
        throw new ezcBasePropertyNotFoundException( $name );
    }

    /**
     * Returns the property $name.
     *
     * Because there are no properties available, this method will always
     * throw an {@link ezcBasePropertyNotFoundException}.
     *
     * @throws ezcBasePropertyNotFoundException if the property does not exist.
     * @param string $name
     * @ignore
     */
    public function __get( $name )
    {
        throw new ezcBasePropertyNotFoundException( $name );
    }

    /**
     * Returns the algorithm that is used currently.
     *
     * @return int   Possible values are: {@link ezcArchive::ZIP}, {@link ezcArchive::TAR}, {@link ezcArchive::TAR_V7},
     *               {@link ezcArchive::TAR_USTAR}, {@link ezcArchive::TAR_PAX}, or {@link ezcArchive::TAR_GNU}.
     */
    public abstract function getAlgorithm();

    /**
     * Returns true if writing to the archive is implemented, otherwise false.
     *
     * @see isWritable()
     *
     * @return bool
     */
    public abstract function algorithmCanWrite();

    /**
     * Returns an instance of the archive with the given type.
     *
     * Similar to {@link open()}, but the type is required.
     *
     * @param string $archiveName  The path of the archive.
     * @param int    $type        Open the archive with the $forceType
     *        algorithm. Possible values are: {@link ezcArchive::ZIP},
     *        {@link ezcArchive::TAR}, {@link ezcArchive::TAR_V7}, {@link ezcArchive::TAR_USTAR},
     *        {@link ezcArchive::TAR_PAX}, {@link ezcArchive::TAR_GNU}.
     *        TAR will use the TAR_USTAR algorithm by default.
     *
     * @return ezcArchive  Subclass of ezcArchive: {@link ezcArchiveZip},
     *                     {@link ezcArchiveV7Tar}, {@link ezcArchivePax},
     *                     {@link ezcArchiveGnuTar}, or {@link ezcArchiveUstar}.
     */
    protected static function createInstance( $archiveName, $type, ezcArchiveOptions $options = null )
    {
        $options = self::initOptions( $options );

        if ( $type == self::ZIP )
        {
            $af = new ezcArchiveCharacterFile( $archiveName, true, $options->readOnly );
            return self::getZipInstance( $af );
        }

        $af = new ezcArchiveBlockFile( $archiveName, true, 512, $options->readOnly );
        $instance = self::getTarInstance( $af, $type );
        $instance->options = $options;
        return $instance;
    }

    /**
     * This methods initializes the options by generating an options object if $options is null.
     *
     * @param null|ezcArchiveOptions $options
     *
     * @return ezcArchiveOptions
     */
    private static function initOptions( $options )
    {
        if ( $options === null )
        {
            $options = new ezcArchiveOptions;
        }
        return $options;
    }

    /**
     * This method associates a new $options object with this archive.
     *
     * @param ezcArchiveOptions $options
     */
    public function setOptions( ezcArchiveOptions $options )
    {
        $this->options = $options;
    }

    /**
     * Open a tar instance.
     *
     * This method is made public for testing purposes, and should not be used.
     *
     * @param ezcArchiveBlockFile $blockFile
     * @param int    $type
     *        The algorithm type. Possible values are:
     *        {@link ezcArchive::TAR}, {@link ezcArchive::TAR_V7}, {@link ezcArchive::TAR_USTAR},
     *        {@link ezcArchive::TAR_PAX}, {@link ezcArchive::TAR_GNU}.
     *        TAR will use the TAR_USTAR algorithm by default.
     *
     * @return ezcArchive  Subclass of ezcArchive:
     *                     {@link ezcArchiveV7Tar}, {@link ezcArchivePax},
     *                     {@link ezcArchiveGnuTar}, or {@link ezcArchiveUstar}.
     * @access private
     */
    public static function getTarInstance( ezcArchiveBlockFile $blockFile, $type )
    {
        switch ( $type )
        {
            case self::TAR_V7:
                return new ezcArchiveV7Tar( $blockFile );

            case self::TAR_USTAR:
                return new ezcArchiveUstarTar( $blockFile );

            case self::TAR_PAX:
                return new ezcArchivePaxTar( $blockFile );

            case self::TAR_GNU:
                return new ezcArchiveGnuTar( $blockFile );

            case self::TAR:
                return new ezcArchiveUstarTar( $blockFile ); // Default type.
        }

        return null;
    }

    /**
     * Open a zip instance. This method is made public for testing purposes, and
     * should not be used.
     *
     * @param ezcArchiveCharacterFile $charFile  The character file which
     *                                           contains the archive.
     * @return ezcArchive  Subclass of ezcArchive: {@link ezcArchiveZip}.
     * @access private
     */
    public static function getZipInstance( ezcArchiveCharacterFile $charFile )
    {
        return new ezcArchiveZip( $charFile );
    }

    /**
     * Returns true if the iterator points to a valid entry, otherwise false.
     *
     * @return bool
     */
    public function valid()
    {
        return ( $this->fileNumber >= 0 && $this->fileNumber < $this->entriesRead );
    }

    /**
     * Rewinds the iterator to the first entry.
     *
     * @return void
     */
    public function rewind()
    {
        $this->fileNumber = 0;
    }

    /**
     * Returns the current ezcArchiveEntry if it is valid, otherwise false is returned.
     *
     * @return ezcArchiveEntry
     */
    public function current()
    {
        return ( $this->valid() ? $this->entries[$this->fileNumber] : false );
    }

    /**
     * Returns the current key, entry number, if it is valid, otherwise false is returned.
     *
     * @return int
     */
    public function key()
    {
        return ( $this->valid() ? $this->fileNumber : false );
    }

    /**
     * Forwards the iterator to the next entry.
     *
     * If there is no next entry all iterator methods except for {@link
     * rewind()} will return false.
     *
     * @see rewind()
     *
     * @return ezcArchiveEntry  The next entry if it exists, otherwise false.
     */
    public function next()
    {
        if ( $this->valid() )
        {
            $this->fileNumber++;
            if ( $this->valid() )
            {
                return $this->current();
            }

            if ( !$this->completed )
            {
                if ( $this->readCurrentFromArchive() )
                {
                    return $this->current();
                }
            }
        }

        return false;
    }

    /**
     * Extract the current entry to which the iterator points.
     *
     * Extract the current entry to which the iterator points, and return true if the current entry is extracted.
     * If the iterator doesn't point to a valid entry, this method returns false.
     *
     * True if the file is extracted correctly, otherwise false.
     *
     * @param string $target
     *        The full path to which the target should be extracted.
     * @param bool $keepExisting
     *        True if the file shouldn't be overwritten if they already exist.
     *        For the opposite behaviour, false should be given.
     *
     * @throws ezcArchiveValueException     if the archive contains invalid values.
     * @throws ezcBaseFileNotFoundException if the link cannot be found.
     *
     * @return bool
     */
    public function extractCurrent( $target, $keepExisting = false )
    {
        if ( $this->file === null )
        {
            throw new ezcArchiveException( "The archive is closed" );
        }

        if ( !$this->valid() )
        {
            return false;
        }

        $isWindows = ( substr( php_uname( 's' ), 0, 7 ) == 'Windows' ) ? true : false;
        $entry = $this->current();
        $type = $entry->getType();
        $fileName = $target . DIRECTORY_SEPARATOR. $entry->getPath();

        if ( $type == ezcArchiveEntry::IS_LINK )
        {
            $linkName = $target . DIRECTORY_SEPARATOR . $entry->getLink();
            if ( !file_exists( $linkName ) )
            {
                throw new ezcBaseFileNotFoundException( $linkName, "link", "Hard link could not be created." );
            }
        }

        $this->createDefaultDirectory( $fileName );

        if ( !$keepExisting || ( !is_link( $fileName ) && !file_exists( $fileName ) ) )
        {
            if ( ( file_exists( $fileName ) || is_link( $fileName ) ) && !is_dir( $fileName ) )
            {
                unlink ( $fileName );
            }

            if ( !file_exists( $fileName ) ) // For example, directories are not removed.
            {
                switch ( $type )
                {
                    case ezcArchiveEntry::IS_CHARACTER_DEVICE:
                        if ( ezcBaseFeatures::hasFunction( 'posix_mknod' ) )
                        {
                            posix_mknod( $fileName, POSIX_S_IFCHR, $entry->getMajor(), $entry->getMinor() );
                        }
                        else
                        {
                            throw new ezcArchiveValueException( $type );
                        }
                        break;

                    case ezcArchiveEntry::IS_BLOCK_DEVICE:
                        if ( ezcBaseFeatures::hasFunction( 'posix_mknod' ) )
                        {
                            posix_mknod( $fileName, POSIX_S_IFBLK, $entry->getMajor(), $entry->getMinor() );
                        }
                        else
                        {
                            throw new ezcArchiveValueException( $type );
                        }
                        break;

                    case ezcArchiveEntry::IS_FIFO:
                        if ( ezcBaseFeatures::hasFunction( 'posix_mknod' ) )
                        {
                            posix_mknod( $fileName, POSIX_S_IFIFO );
                        }
                        else
                        {
                            throw new ezcArchiveValueException( $type );
                        }
                        break;

                    case ezcArchiveEntry::IS_SYMBOLIC_LINK:
                        if ( $isWindows )
                        {
                            // FIXME.. need to be sure that target file
                            // already extracted before copying it to link destination.
                            $sourcePath = dirname( $fileName ) . '/' . $entry->getLink();
                            $fileName = str_replace( '/', '\\', $fileName );
                            copy( $sourcePath, $fileName );
                        }
                        else
                        {
                            symlink( $entry->getLink(), $fileName );
                        }
                        break;

                    case ezcArchiveEntry::IS_LINK:
                        if ( $isWindows )
                        {
                            copy( $target . DIRECTORY_SEPARATOR . $entry->getLink(), $fileName );
                        }
                        else
                        {
                            link( $target . DIRECTORY_SEPARATOR . $entry->getLink(), $fileName );
                        }
                        break;

                    case ezcArchiveEntry::IS_DIRECTORY:
                        $permissions = $entry->getPermissions();

                        if ( $permissions === null || $permissions === false )
                        {
                            $permissions = '0777';
                        }
                        mkdir( $fileName, octdec( $permissions ), true );
                        break;

                    case ezcArchiveEntry::IS_FILE:
                        $this->writeCurrentDataToFile( $fileName );
                        break;

                    default:
                        throw new ezcArchiveValueException( $type );
                }

                if ( $type == ezcArchiveEntry::IS_SYMBOLIC_LINK &&
                     ezcBaseFeatures::hasFunction( 'posix_geteuid' ) &&
                     posix_geteuid() == 0 )
                {
                    $user = $entry->getUserId();
                    $group = $entry->getGroupId();
                    @lchown( $fileName, $user );
                    @lchgrp( $fileName, $group );
                }

                // Change the username and group if the filename exists and if
                // the intention is to keep it as a file. A zip archive
                // stores the symlinks in a file; thus don't change these.
                if ( file_exists( $fileName ) && ( $type == ezcArchiveEntry::IS_FILE || $type == ezcArchiveEntry::IS_DIRECTORY ) )
                {
                    $group = $entry->getGroupId();
                    $user  = $entry->getUserId();
                    $time  = $entry->getModificationTime();
                    $perms = octdec( $entry->getPermissions() );

                    if ( $this->options && $this->options->extractCallback )
                    {
                        $this->options->extractCallback->{$type == ezcArchiveEntry::IS_DIRECTORY ? 'createDirectoryCallback' : 'createFileCallback'}( $fileName, $perms, $user, $group );
                    }

                    if ( ezcBaseFeatures::hasFunction( 'posix_geteuid' ) &&
                         posix_geteuid() === 0 )
                    {
                        @chgrp( $fileName, $group );
                        @chown( $fileName, $user );
                    }

                    if ( $perms != false )
                    {
                        chmod( $fileName, $perms );
                    }

                    touch( $fileName, $time );
                }
            }

            return true;
        }

        return false;
    }

    /**
     * Search for the entry number.
     *
     * The two parameters here are the same as the PHP {@link http://www.php.net/fseek fseek()} method.
     * The internal iterator position will be set by $offset added to $whence iterations forward.
     * Where $whence is:
     * - SEEK_SET, Set the position equal to $offset.
     * - SEEK_CUR, Set the current position plus $offset.
     * - SEEK_END, Set the last file in archive position plus $offset.
     *
     * This method returns true if the new position is valid, otherwise false.
     *
     * @throws ezcArchiveException
     *         if the archive is closed
     * @param int    $offset
     * @param int    $whence
     * @return bool
     */
    public function seek( $offset, $whence = SEEK_SET )
    {
        if ( $this->file === null )
        {
            throw new ezcArchiveException( "The archive is closed" );
        }

        // Cannot trust the current position if the current position is invalid.
        if ( $whence == SEEK_CUR && $this->valid() == false )
        {
            return false;
        }

        if ( $whence == SEEK_END && !$this->completed )
        {
            // read the entire archive.
             $this->fileNumber = $this->entriesRead;
             while ( $this->readCurrentFromArchive() )
             {
                 $this->fileNumber++;
             }
        }

        switch ( $whence )
        {
            case SEEK_SET:
                $requestedFileNumber = $offset;
                break;

            case SEEK_CUR:
                $requestedFileNumber = $offset + $this->fileNumber;
                break;

            case SEEK_END:
                $requestedFileNumber = $offset + $this->entriesRead - 1;
                break;

            default:
                return false; // Invalid whence.
        }

        $this->fileNumber = $requestedFileNumber;
        if ( $this->valid() )
        {
            return true;
        }

        if ( !$this->completed )
        {
            $this->fileNumber = $this->entriesRead - 1;

            while ( $this->fileNumber != $requestedFileNumber )
            {
                $this->fileNumber++;
                if ( !$this->readCurrentFromArchive() )
                {
                    break;
                }
            }

            return $this->valid();
        }

        return false;
    }

    /**
     * Creates all the directories needed to create the file $file.
     *
     * @param string $file  Path to a file, where all the base directory names will be created.
     */
    protected function createDefaultDirectory( $file )
    {
        // Does the directory exist?
        $dirName = dirname( $file );

        if ( !file_exists( $dirName ) )
        {
            // Try to create the directory.
            if ( substr( php_uname( 's' ), 0, 7 ) == 'Windows' )
            {
                // make all slashes to be '/'
                $dirName = str_replace( '/', '\\', $dirName );
            }

            // Call the callback, to see whether we need to change permissions
            $permissions = 0777;
            $dummy = null;
            if ( $this->options && $this->options->extractCallback )
            {
                $this->options->extractCallback->createDirectoryCallback( $dirName, $permissions, $dummy, $dummy );
            }

            mkdir( $dirName, $permissions, true );
        }
    }

    /**
     * Appends a file to the archive after the current entry.
     *
     * One or multiple files can be added directly after the current file.
     * The remaining entries after the current are removed from the archive!
     *
     * The $files can either be a string or an array of strings. Which, respectively, represents a
     * single file or multiple files.
     *
     * $prefix specifies the begin part of the $files path that should not be included in the archive.
     * The files in the archive are always stored relatively.
     *
     * Example:
     * <code>
     * $tar = ezcArchive( "/tmp/my_archive.tar", ezcArchive::TAR );
     *
     * // Append two files to the end of the archive.
     * $tar->seek( 0, SEEK_END );
     * $tar->appendToCurrent( array( "/home/rb/file1.txt", "/home/rb/file2.txt" ), "/home/rb/" );
     * </code>
     *
     * When multiple files are added to the archive at the same time, thus using an array, does not
     * necessarily produce the same archive as repeatively adding one file to the archive.
     * For example, the Tar archive format, can detect that files hardlink to each other and will store
     * it in a more efficient way.
     *
     * @throws ezcArchiveWriteException  if one of the files cannot be written to the archive.
     * @throws ezcFileReadException      if one of the files cannot be read from the local filesystem.
     *
     * @param string|array(string) $files  Array or a single path to a file.
     * @param string $prefix               First part of the path used in $files.
     * @return bool
     */
    public abstract function appendToCurrent( $files, $prefix );

    /**
     * Appends a file or directory to the end of the archive. Multiple files or directory can
     * be added to the archive when an array is used as input parameter.
     *
     * @see appendToCurrent()
     *
     * @throws ezcArchiveWriteException  if one of the files cannot be written to the archive.
     * @throws ezcFileReadException      if one of the files cannot be read from the local filesystem.
     *
     * @param string|array(string) $files  Array or a single path to a file.
     * @param string $prefix               First part of the path used in $files.
     * @return bool
     */
    public abstract function append( $files, $prefix );

    /**
     * Truncates the archive to $fileNumber of files.
     *
     * The $fileNumber parameter specifies the amount of files that should remain.
     * If the default value, zero, is used then the entire archive file is cleared.
     *
     * @param int $fileNumber
     * @return bool
     */
    public abstract function truncate( $fileNumber = 0 );

    /**
     * Writes the file data from the current entry to the given file.
     *
     * @param string $targetPath  The absolute or relative path of the target file.
     * @return void
     */
    protected abstract function writeCurrentDataToFile( $targetPath );

    /**
     * Returns an array that lists the content of the archive.
     *
     * Use the getArchiveEntry method to get more information about an entry.
     *
     * @see __toString()
     *
     * @throws ezcArchiveException
     *         if the archive is closed
     * @return array(string)
     */
    public function getListing()
    {
        if ( $this->file === null )
        {
            throw new ezcArchiveException( "The archive is closed" );
        }

        $result = array();
        $this->rewind();

        do
        {
            $entry = $this->current();
            $result[] = rtrim( $entry->__toString(), "\n" ); // remove newline.
        } while ( $this->next() );

        return $result;
    }

    /**
     * Returns a string which represents all the entries from the archive.
     *
     * @throws ezcArchiveException
     *         if the archive is closed
     * @return string
     */
    public function __toString()
    {
        if ( $this->file === null )
        {
            throw new ezcArchiveException( "The archive is closed" );
        }

        $result = "";
        $this->rewind();

        while ( $this->valid() )
        {
            $result .= $this->current()->__toString() . "\n";
            $this->next();
        }

        return $result;
    }

    /**
     * Extract entries from the archive to the target directory.
     *
     * All entries from the archive are extracted to the target directory.
     * By default the files in the target directory are overwritten.
     * If the $keepExisting is set to true, the files from the archive will not overwrite existing files.
     *
     * @see extractCurrent()
     *
     * @throws ezcArchiveException
     *         if the archive is closed
     * @throws ezcArchiveEmptyException
     *         if the archive is invalid
     * @param string $target     Absolute or relative path of the directory.
     * @param bool $keepExisting If set to true then the file will be overwritten, otherwise not.
     * @return void
     */
    public function extract( $target, $keepExisting = false )
    {
        if ( $this->file === null )
        {
            throw new ezcArchiveException( "The archive is closed" );
        }

        $this->rewind();
        if ( !$this->valid() )
        {
            throw new ezcArchiveEmptyException( );
        }

        while ( $this->valid() )
        {
            $this->extractCurrent( $target, $keepExisting );
            $this->next();
        }
    }

    /**
     * Returns true if the current archive is empty, otherwise false.
     *
     * @return bool
     */
    public function isEmpty()
    {
        return ( $this->entriesRead == 0 );
    }

    /**
     * Get the file entries from the archive.
     *
     * @param string|array(string) $files  Array or a single path to a file.
     * @param string $prefix               First part of the path used in $files.
     *
     * @return ezcArchiveEntry
     */
    protected function getEntries( $files, $prefix )
    {
        if ( !is_array( $files ) )
        {
            $files = array( $files );
        }

        // Check whether the files are correct.
        foreach ( $files as $file )
        {
            if ( !file_exists( $file ) && !is_link( $file ) )
            {
                throw new ezcBaseFileNotFoundException( $file );
            }
        }

        // Search for all the entries, because otherwise hardlinked files show up as an ordinary file.
        return ezcArchiveEntry::getEntryFromFile( $files, $prefix );
    }
}
?>
PK��ZԢ"$fIfIezc/Archive/file/block_file.phpnu�[���<?php
/**
 * File contains the ezcArchiveBlockFile class.
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @access private
 */

/**
 * The ezcArchiveBlockFile class provides an interface for reading from and writing to a block file.
 *
 * A block file is a file that consist of zero or more blocks. Each block has a predefined amount
 * of bytes known as the block-size. The block file implements the Iterator interface. Via the methods
 *
 * - key()
 * - valid()
 * - current()
 * - rewind()
 *
 * can single blocks be accessed. The append(), appendToCurrent() method, appends and possibly removes
 * blocks from and to the file.
 *
 * The block-file takes the necessary measurements to read and write to a compressed stream.
 *
 * The following example stores 16 bytes in 4 blocks. The current() points to the second block: 1.
 * <code>
 *  ---- ---- ---- ----
 * |0 1 | 5 6| 9 0| 3 4|
 * |2 4 | 7 8| 1 2| 5 6|
 *  ---- ---- ---- ----
 *   0    1    2    3
 *
 *        ^         ^
 *        |         \ LastBlock
 *
 *     Current
 * </code>
 *
 *
 * @package Archive
 * @version 1.4.1
 * @access private
 */
class ezcArchiveBlockFile extends ezcArchiveFile
{
    /**
     * The block size.
     *
     * @var int
     */
    private $blockSize;

    /**
     * The current number of the block.
     *
     * The first block starts with zero.
     *
     * @var int
     */
    private $blockNumber = -1;

    /**
     * The current block data.
     *
     * @var string
     */
    private $blockData;

    /**
     * Holds the last block number.
     *
     * @var int
     */
    private $lastBlock = -1;

    /**
     * Sets the property $name to $value.
     *
     * Because there are no properties available, this method will always
     * throw an {@link ezcBasePropertyNotFoundException}.
     *
     * @throws ezcBasePropertyNotFoundException if the property does not exist.
     * @param string $name
     * @param mixed $value
     * @return void
     * @ignore
     */
    public function __set( $name, $value )
    {
        throw new ezcBasePropertyNotFoundException( $name );
    }

    /**
     * Returns the property $name.
     *
     * Available read-only property: blockSize
     *
     * @throws ezcBasePropertyNotFoundException if the property does not exist.
     * @param string $name
     * @return mixed
     * @ignore
     */
    public function __get( $name )
    {
        switch ( $name )
        {
            case "blockSize":
                return $this->blockSize;
        }

        throw new ezcBasePropertyNotFoundException( $name );
    }

    /**
     * Constructs a new ezcArchiveBlockFile.
     *
     * The given file name is tried to be opened in read / write mode. If that fails, the file will be opened
     * in read-only mode.
     *
     * If the bool $createIfNotExist is set to true, it will create the file if it doesn't exist.
     *
     * @throws ezcBaseFileNotFoundException if the file cannot be found.
     * @throws ezcBaseFilePermissionException if the file permissions are wrong.
     *
     * @param string $fileName
     * @param bool $createIfNotExist
     * @param int $blockSize
     * @param bool $readOnly
     */
    public function __construct( $fileName, $createIfNotExist = false, $blockSize = 512, $readOnly = false )
    {
        $this->blockSize = $blockSize;

        $this->openFile( $fileName, $createIfNotExist, $readOnly );
    }


    /**
     * The destructor will close all open files.
     */
    public function __destruct()
    {
        if ( $this->fp )
        {
            fclose( $this->fp );
        }
    }

    /**
     * Rewind the current file.
     *
     * @return void
     */
    public function rewind()
    {
        $this->blockNumber = -1;

        parent::rewind();
    }

    /**
     * Return the data from the current block if the block is valid.
     *
     * If the block is not valid, the value false is returned.
     *
     * @return string
     */
    public function current()
    {
        return ( $this->isValid ? $this->blockData : false );
    }

    /**
     * Iterate to the next block.
     *
     * Returns the data of the next block if it exists; otherwise returns false.
     *
     * @return string
     */
    public function next()
    {
        if ( $this->isValid  )
        {
            // XXX move the calc to readmode?
            // $this->switchReadMode( ( $this->blockNumber + 1 ) * $this->blockSize );

            // Read one block.
            $this->blockData = fread( $this->fp, $this->blockSize );

            if ( strlen( $this->blockData ) < $this->blockSize )
            {
                if ( $this->lastBlock != -1 )
                {
                    if ( $this->blockNumber != $this->lastBlock )
                    {
                        throw new ezcArchiveInternalException( "Something weird happened with the blockNumber. Lastblock number registered at " . $this->lastBlock . " but changed into " . $this->blockNumber );
                    }
                }
                $this->lastBlock = $this->blockNumber;
                $this->isValid = false;
                return false;
            }
            $this->blockNumber++;

            return $this->blockData;
        }

        return false;
    }

    /**
     * Returns the key, the current block number of the current element.
     *
     * The first block has the number zero.
     *
     * @return int
     */
    public function key()
    {
        return ( $this->isValid ? $this->blockNumber : false );
    }

    /**
     * Returns true if the current block is valid, otherwise false.
     *
     * @return bool
     */
    public function valid()
    {
        return $this->isValid;
    }

    /**
     * Returns true if the current block is a null block, otherwise false.
     *
     * A null block is a block consisting of only NUL characters.
     * If the current block is invalid, this method will return false.
     *
     * @return bool
     */
    public function isNullBlock()
    {
        if ( $this->isValid )
        {
            for ( $i = 0; $i < $this->blockSize; $i++ )
            {
                if ( ord( $this->blockData[$i] ) != 0 )
                {
                    return false;
                }
            }
            return true;
        }

        return false;
    }

    /**
     * Appends with truncate.
     */
    private function appendTruncate()
    {
        if ( $this->fileAccess == self::READ_ONLY )
        {
            throw new ezcBaseFilePermissionException( $this->fileName, ezcBaseFilePermissionException::WRITE, "The archive is opened in a read-only mode." );
        }

        if ( !$this->isEmpty && $this->isValid )
        {
            $needToTruncate = true;
            $currentBlock = $this->blockNumber;
            // Do we need to truncate the file?

            // Check if we already read the entire file. This way is quicker to check.
            if ( $this->lastBlock != -1 )
            {
                // Last block is known.
                if ( $this->lastBlock == $this->blockNumber )
                {
                    // We are at the last block.
                    $needToTruncate = false;
                }
            }
            else
            {
                // The slower method. Check if we can read the next block.
                if ( !$this->next() )
                {
                    // We got a next block.
                    $needToTruncate = false;
                }
            }

            if ( $needToTruncate )
            {
                if ( $this->fileAccess == self::READ_APPEND )
                {
                    // Sorry, don't know how to truncate this file (except copying everything).
                    throw new ezcArchiveException( "Cannot truncate the file" );
                }

                if ( $this->blockNumber < $this->lastBlock )
                {
                    throw new ezcArchiveInternalException( "Expected to be at the last block." );
                }
                $pos = $currentBlock * $this->blockSize;
                ftruncate( $this->fp, $pos );

                $this->lastBlock = $currentBlock;
                $this->blockNumber = $currentBlock;
            }
        }
        else
        {
            if ( !$this->isEmpty && !$this->isValid )
            {
                throw new ezcArchiveInternalException( "Not at a valid block position to append" );
            }
        }
    }

    /**
     * Appends the string $data after the current block.
     *
     * The blocks after the current block are removed and the $data will be
     * appended. The data will always be appended after the current block.
     * To replace the data from the first block, the truncate() method should
     * be called first.
     *
     * Multiple blocks will be written when the length of the $data exceeds
     * the block size. If the data doesn't fill an entire block, the rest
     * of the block will be filled with NUL characters.
     *
     * @param   string  $data  Data that should be appended.
     * @return int        The total amount of blocks added.
     *
     * @throws  ezcBaseFilePermissionException when the file is opened in read-only mode.
     */
    public function append( $data )
    {
        $this->appendTruncate();

        // We are at the end of the file. Let's append the data.
        // Switch write mode, if needed.
        $this->switchWriteMode();

        $dataLength = sizeof( $data );
        $length = $this->writeBytes( $data );

        if ( ( $mod = ( $length % $this->blockSize ) ) > 0 )
        {
            $this->writeBytes( pack( "a". ( $this->blockSize  - $mod ), "" ) );
        }

        $addedBlocks = ( (int) (($length - 1) / $this->blockSize ) ) + 1;

        // Added the blocks.
        $this->isModified = true;
        $this->isEmpty = false;

        $this->blockNumber += $addedBlocks;
        $this->lastBlock += $addedBlocks;
        $this->blockData = $data;
        $this->isValid = true;

        $this->switchReadMode();

        return $addedBlocks;
    }

    /**
     * Appends the data from the given file $fileName to the current block file.
     *
     * The blocks after the current block are removed and the data will be
     * appended. The data will always be appended after the current block.
     * To replace the data from the first block, the truncate() method should
     * be called first.
     *
     * Multiple blocks will be written when the length of the data exceeds
     * the block size. If the data doesn't fill an entire block, the rest
     * of the block will be filled with NUL characters.
     *
     * @param   string  $fileName  The filename that contains the data.
     * @return int                 The total amount of blocks added.
     *
     * @throws  ezcBaseFilePermissionException when the file is opened in read-only mode.
     */
    public function appendFile( $fileName )
    {
        $this->appendTruncate();

        $this->switchWriteMode();

        $localFile = @fopen( $fileName, "rb" );
        if ( !$localFile )
        {
            throw new ezcArchiveException( "Cannot open the file '{$fileName}' for reading." );
        }

        $addedBlocks = 0;
        $length = 0;
        while ( !feof( $localFile ) && ( $data = fread( $localFile, $this->blockSize ) ) !== false )
        {
            $addedBlocks++;
            $length = $this->writeBytes( $data );
        }

        if ( ( $mod = ( $length % $this->blockSize ) ) > 0 )
        {
            $this->writeBytes( pack( "a". ( $this->blockSize  - $mod ), "" ) );
        }

        fclose( $localFile );

        // Added the blocks.
        $this->isModified = true;
        $this->isEmpty = false;

        $this->blockNumber += $addedBlocks;
        $this->lastBlock += $addedBlocks;
        $this->blockData = $data;
        $this->isValid = true;

        $this->switchReadMode();

        return $addedBlocks;
    }

    /**
     * Write the given string $data to the current file.
     *
     * This method tries to write the $data to the file. Upon failure, this method
     * will retry, until no progress is made anymore. And eventually it will throw
     * an exception. Sometimes an (invalid) interrupt may stop the writing process.
     *
     * @throws ezcBaseFileIoException if it is not possible to write to the file.
     *
     * @param string $data
     * @return void
     */
    protected function writeBytes( $data )
    {
        $dl = strlen( $data );
        if ( $dl == 0 )
        {
            return; // No bytes to write.
        }

        $wl = fwrite( $this->fp, $data );

        // Partly written? For example an interrupt can occur when writing a remote file.
        while ( $dl > $wl && $wl != 0 )
        {
            // retry, until no progress is made.
            $data = substr( $data, $wl );

            $dl = strlen( $data );
            $wl = fwrite( $this->fp, $data );
        }

        if ( $wl == 0 )
        {
            throw new ezcBaseFileIoException ( $this->fileName, ezcBaseFileIoException::WRITE, "Retried to write, but no progress was made. Disk full?" );
        }

        return $wl;
    }

    /**
     * Appends one block with only NUL characters to the file.
     *
     * @throws ezcBaseFilePermissionException if the file is opened in read-only mode.
     * @apichange Rename to appendNullBlocks
     *
     * @param int $amount
     * @return void
     */
    public function appendNullBlock( $amount = 1 )
    {
        $this->append( pack( "a". ( $amount * $this->blockSize ), "" ) );
    }

    /**
     * Truncate the current block file to $block blocks.
     *
     * If $blocks is zero, the entire block file will be truncated. After the file is truncated,
     * make sure the current block position is valid. So, do a rewind() after
     * truncating the entire block file.
     *
     * @param int $blocks
     * @return void
     */
    public function truncate( $blocks = 0 )
    {
        // Empty files don't need to be truncated.
        if ( $this->isEmpty() )
        {
            return true;
        }

        if ( $this->fileAccess !== self::READ_APPEND )
        {
            // We can read-write in the file. Easy.
            $pos = $blocks * $this->blockSize;
            ftruncate( $this->fp, $pos );
            $this->isModified = true;
            if ( $pos == 0 )
            {
                $this->isEmpty = true;
            }

            if ( $this->blockNumber >= $blocks )
            {
                $this->isValid = false;
            }

            $this->lastBlock = $blocks - 1;

            return true;
        }

        // Truncate at the end?
        if ( !$this->isValid )
        {
            $this->rewind();
        }

        while ( $this->isValid && $blocks > $this->blockNumber )
        {
            $this->next();
        }

        if ( $this->isValid )
        {
            throw new ezcArchiveInternalException( "Failed to truncate the file" );
        }

        return true;
    }

    /**
     * Sets the current block position.
     *
     * The new position is obtained by adding the $blockOffset amount of blocks to
     * the position specified by $whence.
     *
     * These values are:
     *  SEEK_SET: The first block,
     *  SEEK_CUR: The current block position,
     *  SEEK_END: The last block.
     *
     * The blockOffset can be negative.
     *
     * @param int $blockOffset
     * @param int $whence
     * @return void
     */
    public function seek( $blockOffset, $whence = SEEK_SET )
    {
        if ( $this->fileAccess == self::WRITE_ONLY && $blockOffset == 0 && $whence == SEEK_END )
        {
            return true;
        }

        if ( ftell( $this->fp ) === false || $this->fileAccess == self::READ_APPEND )
        {
            // Okay, cannot tell the current file position.
            // This happens with some compression streams.

            if ( !$this->isValid )
            {
                if ( $whence == SEEK_CUR )
                {
                    throw new ezcArchiveException( "Cannot seek SEEK_CUR with an invalid block position" );
                }

                $this->rewind();
            }

            if ( $whence == SEEK_END && $this->lastBlock == -1 )
            {
                // Go to the end.
                while ( $this->next() );
            }

            switch ( $whence )
            {
                case SEEK_CUR:
                    $searchBlock = $this->blockNumber += $blockOffset;
                    break;

                case SEEK_END:
                    $searchBlock = $this->lastBlock += $blockOffset;
                    break;

                case SEEK_SET:
                    $searchBlock = $blockOffset;
                    break;
            }

            if ( $searchBlock < $this->blockNumber )
            {
                $this->rewind();
            }

            while ( $this->isValid && $this->blockNumber < $searchBlock )
            {
                $this->next();
            }

            return ( $this->blockNumber == $searchBlock );
        }
        else
        {
            $this->isValid = true;

            $pos = $this->blockSize * $blockOffset;
            if ( $whence == SEEK_END || $whence == SEEK_CUR )
            {
                if ( !$this->isEmpty() )
                {
                    $pos -= $this->blockSize;
                }
            }

            if ( !( $whence == SEEK_SET && $pos == ftell( $this->fp ) ) )
            {
                $this->positionSeek( $pos, $whence );
            }

            if ( ftell( $this->fp ) === false )
            {
                throw new ezcArchiveException( "Cannot tell the current position, but this is after the position seek. " );
            }

            $this->blockNumber = $this->getBlocksFromBytes( ftell( $this->fp ) ) - 1;
            $this->next(); // Will set isValid to false, if blockfile is empty.
        }
    }

    /**
     * Calculates the blocks for the given $bytes.
     *
     * @param  int $bytes
     * @return int
     */
    public function getBlocksFromBytes( $bytes )
    {
        return (int) ceil ($bytes  / $this->blockSize );
    }

    /**
     * Returns true if the blockfile is empty, otherwise false.
     *
     * @return bool
     */
    public function isEmpty()
    {
        return $this->isEmpty;
    }

    /**
     * Returns the last block number.
     *
     * @return int
     */
    public function getLastBlockNumber()
    {
        return $this->lastBlock;
    }
}
?>
PK��Z�cp'
(
(#ezc/Archive/file/character_file.phpnu�[���<?php
/**
 * File contains the ezcArchiveCharacterFile class.
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @access private
 */

/**
 * The ezcArchiveCharacterFile class provides an interface for reading from and writing to a file.
 *
 * The file is opened via in constructor and closed via the destructor.
 *
 * The iterator functionality can be used to read characters from and append characters to the file,
 * so it has the same behaviour as the {@link ezcArchiveBlockFile}.
 *
 * @package Archive
 * @version 1.4.1
 * @access private
 */
class ezcArchiveCharacterFile extends ezcArchiveFile
{
    /**
     * The current character.
     *
     * @todo FIXME
     *
     * @var string
     */
    private $character;

    /**
     * The current character position.
     *
     * @var int
     */
    private $position;

    /**
     * Sets the property $name to $value.
     *
     * Because there are no properties available, this method will always
     * throw an {@link ezcBasePropertyNotFoundException}.
     *
     * @throws ezcBasePropertyNotFoundException if the property does not exist.
     * @param string $name
     * @param mixed $value
     * @return void
     * @ignore
     */
    public function __set( $name, $value )
    {
        throw new ezcBasePropertyNotFoundException( $name );
    }

    /**
     * Returns the property $name.
     *
     * Because there are no properties available, this method will always
     * throw an {@link ezcBasePropertyNotFoundException}.
     *
     * @throws ezcBasePropertyNotFoundException if the property does not exist.
     * @param string $name
     * @return mixed
     * @ignore
     */
    public function __get( $name )
    {
        throw new ezcBasePropertyNotFoundException( $name );
    }

    /**
     * Constructs a new ezcArchiveBlockFile.
     *
     * The given file name is tried to be opened in read / write mode.
     * If that fails, the file will be opened in read-only mode.
     *
     * If the bool $createIfNotExist is set to true, it will create the file if
     * it doesn't exist.
     *
     * @throws ezcArchiveException if the file cannot be found or opened for any reason.
     *
     * @param string $fileName
     * @param bool $createIfNotExist
     * @param bool $readOnly
     */
    public function __construct( $fileName, $createIfNotExist = false, $readOnly = false )
    {
        $this->openFile( $fileName, $createIfNotExist, $readOnly );
        $this->rewind();
    }

    /**
     * The destructor will close all open files.
     */
    public function __destruct()
    {
        if ( $this->fp )
        {
            fclose( $this->fp );
        }
    }

    /**
     * Rewinds the current file.
     *
     * @return void
     */
    public function rewind()
    {
        parent::rewind();

        $this->position = -1;
    }

    /**
     * Returns the current character if available.
     *
     * If the character is not available, the value false is returned.
     *
     * @return string
     */
    public function current()
    {
        return ( $this->isValid ? $this->character : false );
    }

    /**
     * Iterates to the next character.
     *
     * Returns the next character if it exists; otherwise returns false.
     *
     * @return string
     */
    public function next()
    {
        if ( $this->isValid  )
        {
            $this->character = fgetc( $this->fp );

            if ( $this->character === false )
            {
                $this->isValid = false;
                return false;
            }

            $this->position++;
            return $this->character;
        }

        return false;
    }

    /**
     * Returns the current position.
     *
     * The first position has the value zero.
     *
     * @return int
     */
    public function key()
    {
        return ( $this->isValid ? ftell( $this->fp ) - 1 : false );
    }

    /**
     * Returns the file-pointer position.
     *
     * @todo FIXME Is this or the key() function needed?
     *
     * return int
     */
    public function getPosition()
    {
        return ftell( $this->fp );
    }

    /**
     * Returns true if the current character is valid, otherwise false.
     *
     * @return bool
     */
    public function valid()
    {
        return $this->isValid;
    }

    /**
     * Appends the string $data after the current position.
     *
     * The character(s) after the current position are removed and the $data will be
     * appended.
     * To start from the beginning of the file, call first the truncate() method.
     *
     * @throws  ezcBaseFilePermissionException if the file is opened in read-only mode.
     *
     * @param  string $data
     * @return int
     */
    public function append( $data )
    {
        if ( $this->fileAccess == self::READ_ONLY )
        {
            throw new ezcBaseFilePermissionException( $this->fileName, ezcBaseFilePermissionException::WRITE, "The archive is opened in a read-only mode." );
        }

        $pos = ftell( $this->fp );
        ftruncate( $this->fp, $pos );
        $length = $this->writeBytes( $data );

        $this->isValid = true;
        if ( $this->isEmpty )
        {
            rewind( $this->fp );
            $this->next();
        }
        else
        {
            $this->positionSeek( $pos, SEEK_SET );
        }

        $this->isEmpty = false;

        return $length;
    }

    /**
     * Writes the given string $data to the current file.
     *
     * This method tries to write the $data to the file. Upon failure, this method
     * will retry, until no progress is made anymore. And eventually it will throw
     * an exception.
     *
     * @throws ezcBaseFileIoException if it is not possible to write to the file.
     *
     * @param string $data
     * @return void
     */
    protected function writeBytes( $data )
    {
        $dl = strlen( $data );
        if ( $dl == 0 )
        {
            return; // No bytes to write.
        }

        $wl = fwrite( $this->fp, $data );

        // Partly written? For example an interrupt can occur when writing a remote file.
        while ( $dl > $wl && $wl != 0 )
        {
            // retry, until no progress is made.
            $data = substr( $data, $wl );

            $dl = strlen( $data );
            $wl = fwrite( $this->fp, $data );
        }

        if ( $wl == 0 )
        {
            throw new ezcBaseFileIoException ( $this->fileName, ezcBaseFileIoException::WRITE, "Retried to write, but no progress was made. Disk full?" );
        }

        return $wl;
    }

    /**
     * Truncates the current file to the number of characters $position.
     *
     * If $position is zero, the entire block file will be truncated. After the file is truncated,
     * make sure the current block position is valid. So, do a rewind() after
     * truncating the entire block file.
     *
     * @param int $position
     * @return void
     */
    public function truncate( $position = 0 )
    {
        ftruncate( $this->fp, $position );

        if ( $position == 0 )
        {
            $this->isEmpty = true;
        }

        if ( $this->position > $position )
        {
            $this->isValid = false;
        }
    }

    /**
     * Sets the current character position.
     *
     * Sets the current character position. The new position is obtained by adding
     * the $offset amount of characters to the position specified by $whence.
     *
     * These values are:
     *  SEEK_SET: The first character,
     *  SEEK_CUR: The current character position,
     *  SEEK_END: The last character.
     *
     * The blockOffset can be negative.
     *
     * @param int $offset
     * @param int $whence
     * @return void
     */
    public function seek( $offset, $whence = SEEK_SET )
    {
        $this->isValid = true;

        $pos = $offset;
        /*
        if ( $whence == SEEK_END || $whence == SEEK_CUR )
        {
            if ( !$this->isEmpty() )
            {
                $pos -= 1;
            }
        }
         */


        if ( $this->positionSeek( $pos, $whence ) == -1 )
        {
            $this->isValid = false;
        }

        $this->position = $pos - 1;
        $this->next(); // Will set isValid to false, if blockfile is empty.
    }

    /**
     * Returns true if the file is empty, otherwise false.
     *
     * @return bool
     */
    public function isEmpty()
    {
        return $this->isEmpty;
    }

    /**
     * Reads current character plus extra. Forward the current pointer.
     *
     * @param int $bytes
     * @return string
     */
    public function read( $bytes )
    {
        if ( $bytes < 1 )
        {
            return false;
        }

        $data = $this->character;
        if ( $bytes == 1 )
        {
            $this->next();
            return $data;
        }

        $data .= fread( $this->fp, $bytes - 1 );

        $this->position += $bytes - 1;

        if ( $data === false )
        {
           $this->isValid = false;
           return false;
        }
        else
        {
            $this->next();
        }
        return $data;
    }

    /**
     * Writes the specified data and returns the length of the written data.
     *
     * FIXME, maybe valid() when at the eof.
     * FIXME. Write current character plus extra.
     * FIXME.. slow.
     *
     * @throws ezcBaseFilePermissionException
     *         if the file access is read-only
     * @param string $data
     * @return int
     */
    public function write( $data )
    {
        if ( $this->fileAccess == self::READ_ONLY )
        {
            throw new ezcBaseFilePermissionException( $this->fileName, ezcBaseFilePermissionException::WRITE, "The archive is opened in a read-only mode." );
        }

        $pos = ftell( $this->fp );
        if ( $this->valid() )
        {
            $pos--;
        }

        fseek( $this->fp, $pos );
        ftruncate( $this->fp, $pos );
        $length = $this->writeBytes( $data );

        $this->isValid = false;
        $this->isEmpty = false;

        return $length;
    }
}
?>
PK��Z$�^�3�3ezc/Archive/file/file.phpnu�[���<?php
/**
 * File containing the ezcArchiveFile class.
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @access private
 */

/**
 * The ezcArchiveFile should implement the common interface between the
 * ezcArchiveBlockFile and ezcArchiveCharacterFile.
 *
 * @package Archive
 * @version 1.4.1
 * @access private
 */
abstract class ezcArchiveFile implements Iterator
{
    /**
     * The file is read-only.
     * The file permissions can be set to read-only or file is compressed with a
     * stream that can only be read. E.g. bzip2.
     */
    const READ_ONLY   = 1;

    /**
     * The file is write-only.
     * The file permissions can be set to write-only or file should be compressed with a
     * stream that can only write. E.g. bzip2.
     */
    const WRITE_ONLY  = 2;

    /**
     * The file is either read or append mode.
     * Some compressed streams (zlib) do not support reading and writing. But seperate reading
     * and appending does work.
     */
    const READ_APPEND = 3;

    /**
     * The file is opened in a read and write mode.
     */
    const READ_WRITE  = 4;

    /**
     * The mode the file is opened in. It has one of the following constant values:
     * READ_ONLY, WRITE_ONLY, READ_APPEND, or READ_WRITE.
     *
     * @var int
     */
    protected $fileAccess = null;

    /**
     * The current resource of the opened file.
     * If the file is closed, this resource should point to NULL.
     *
     * @var resource
     */
    protected $fp = null;

    /**
     * The name of the file.
     *
     * @var string
     */
    protected $fileName;

    /**
     * True when the current file does not have any blocks, otherwise false.
     *
     * @var boolean
     */
    protected $isEmpty;

    /**
     * True if the file-pointer supports seeking, otherwise false.
     * For example, files that use the bzip2 stream cannot seek.
     *
     * @var boolean
     */
    protected $fileMetaData;

    /**
     * True when the current block is valid, otherwise false.
     *
     * @var boolean
     */
    protected $isValid = false;

    /**
     * Read-mode for the archive file.
     */
    const SWITCH_READ = 0;

    /**
     * Append-mode for the archive file.
     */
    const SWITCH_APPEND = 1;

    /**
     * Switch for read-mode and append-mode.
     *
     * @var int
     */
    protected $readAppendSwitch;

    /**
     * Is the file new.
     *
     * @var bool
     */
    protected $isNew;

    /**
     * Is the file modified.
     *
     * @var bool
     */
    protected $isModified;

    /**
     * Opens the specified archive.
     *
     * If $createIfNotExist is true, then the file will be created if it does
     * not exist.
     *
     * @param string $fileName
     * @param bool $createIfNotExist
     * @param bool $readOnly
     * @return bool
     */
    protected function openFile( $fileName, $createIfNotExist, $readOnly = false )
    {
        if ( !$readOnly && $createIfNotExist && !self::fileExists( $fileName ) )
        {
            $this->isNew = true;
            $this->isEmpty = true;
            if ( !self::touch( $fileName ) )
            {
                throw new ezcBaseFilePermissionException( self::getPureFileName( $fileName ), ezcBaseFilePermissionException::WRITE );
            }
        }
        else
        {
            $this->isNew = false;
        }

        // Try to open it in read and write mode.
        $opened = false;
        if ( !$readOnly ) 
        {
            $this->fp = @fopen( $fileName, "r+b" );
            if ( $this->fp )
            {
                $this->fileAccess = self::READ_WRITE;
                $opened = true;
            }
        }

        if ( !$opened )
        {
            // Try to open it in read-only mode.
            $this->fp = @fopen( $fileName, "rb" );
            $this->fileAccess = self::READ_ONLY;

            // Check if we opened the file.
            if ( !$this->fp )
            {
                if ( !self::fileExists( $fileName ) )
                {
                    throw new ezcBaseFileNotFoundException( $fileName );
                }

                // Cannot read the file.
                throw new ezcBaseFilePermissionException( $fileName, ezcBaseFilePermissionException::READ );
            }
        }

        $this->fileMetaData = stream_get_meta_data( $this->fp );

        // Hardcode BZip2 to read-only.
        // For some reason we can open the file in read-write mode, but we cannot rewind the fp. Strange..
        if ( $this->fileMetaData["wrapper_type"] == "BZip2" )
        {
            $this->fileAccess = self::READ_ONLY;
        }

        // Why is it read only?
        if ( !$readOnly && $this->fileAccess == self::READ_ONLY )
        {
            if ( $this->fileMetaData["wrapper_type"] == "ZLIB" || $this->fileMetaData["wrapper_type"] == "BZip2" )
            {
                // Append mode available?
                $b = @fopen( $fileName, "ab" );
                if ( $b !== false )
                {
                    // We have also a write-only mode.
                    fclose( $b );

                    // The file is either read-only or write-only.
                    $this->fileAccess = self::READ_APPEND;
                    $this->readAppendSwitch = self::SWITCH_READ;
                }
                else
                {
                    // Maybe we should write only to the archive.
                    // Test this only, when the archive is new.

                    if ( $this->isNew )
                    {
                        $b = @fopen( $fileName, "wb" );
                        if ( $b !== false )
                        {
                            // XXX Clean up.
                            $this->fp = $b;

                            $this->isEmpty = true;
                            $this->fileAccess = self::WRITE_ONLY;

                            $this->fileName = $fileName;
                            $this->isModified = false;

                            return true;
                        }
                    }
                }
            }
        }

        // Check if the archive is empty.
        if ( fgetc( $this->fp ) === false )
        {
            $this->isEmpty = true;
        }
        else
        {
            $this->rewind();
            $this->isEmpty = false;
        }

        $this->fileName = $fileName;
        $this->isModified = false;
    }

    /**
     * Returns the file name or file path.
     *
     * @return string
     */
    public function getFileName()
    {
        return $this->fileName;
    }

    /**
     * Switch to write mode.
     */
    public function switchWriteMode()
    {
        // Switch only when we are in read (only) mode.
        if ( $this->fileAccess == self::READ_APPEND && $this->readAppendSwitch == self::SWITCH_READ )
        {
            fclose( $this->fp );
            $this->fp = @fopen( $this->fileName, "ab" );
            if ( $this->fp === false )
            {
                throw new ezcBaseFilePermissionException( self::getPureFileName( $this->fileName ), ezcBaseFilePermissionException::WRITE, "Cannot switch to write mode" );
            }
            $this->readAppendSwitch = self::SWITCH_APPEND;
        }
    }

    /**
     * Switch to read mode.
     *
     * @param int $pos Position to seek to; not used
     */
    public function switchReadMode( $pos = 0 )
    {
        // Switch only when we are in write (only) mode.
        if ( $this->fileAccess == self::READ_APPEND && $this->readAppendSwitch == self::SWITCH_APPEND )
        {
            fclose( $this->fp );

            $this->fp = fopen( $this->fileName, "rb" );

            if ( $this->fp === false )
            {
                throw new ezcBaseFilePermissionException( self::getPureFileName( $this->fileName ), ezcBaseFilePermissionException::READ, "Cannot switch back to read mode" );
            }
            $this->readAppendSwitch = self::SWITCH_READ;

            $this->positionSeek( 0, SEEK_END );

            // Doesn't Make sense, Seek-end should be at the end!
            while ( fgetc( $this->fp ) !== false );
        }
    }

    /**
     * Returns if the file access is in append mode.
     *
     * @return bool
     */
    public function isReadOnlyWriteOnlyStream()
    {
        return $this->fileAccess == self::READ_APPEND;
    }



    /**
     * Touches the specified file (sets the access and modification time).
     *
     * PHP system touch doesn't work correctly with the compress.zlib file.
     *
     * @param string $fileName
     * @return bool
     */
    public static function touch( $fileName )
    {
        return touch( self::getPureFileName( $fileName ) );
    }

    /**
     * Returns if the specified file exists.
     *
     * @param string $fileName
     * @return bool
     */
    public static function fileExists( $fileName )
    {
        return file_exists( self::getPureFileName( $fileName ) );
    }

    /**
     * Returns the specified file name without any filters or compression stream.
     *
     * @param string $fileName
     * @return string
     */
    private static function getPureFileName( $fileName )
    {
        // TODO: Multistream goes wrong.
        if ( strncmp( $fileName, "compress.zlib://", 16 ) == 0 )
        {
            return substr( $fileName, 16 );
        }

        if ( strncmp( $fileName, "compress.bzip2://", 17 ) == 0 )
        {
            return substr( $fileName, 17 );
        }

        return $fileName;
    }

    /**
     * Rewind the current file, and the current() method will return the
     * data from the first block, if available.
     */
    public function rewind()
    {
        if ( !is_null( $this->fp ) )
        {
            $this->isValid = true;

            if ( !$this->fileMetaData["seekable"] )
            {
                fclose( $this->fp );
                $this->fp = fopen( $this->fileMetaData["uri"], $this->fileMetaData["mode"] );
            }
            else
            {
                rewind( $this->fp );
            }

            $this->next();
        }
        else
        {
            $this->isValid = false;
        }
    }

    /**
     * Seeks in the file to/by the specified position.
     *
     * Ways of seeking ($whence):
     * - SEEK_SET - $pos is absolute, seek to that position in the file
     * - SEEK_CUR - $pos is relative, seek by $pos bytes from the current position
     *
     * @throws ezcArchiveException
     *         if trying to use SEEK_END for $whence
     * @param int $pos
     * @param int $whence
     * @return int If seek was successful or not
     */
    protected function positionSeek( $pos, $whence = SEEK_SET )
    {
        // Seek the end of the file in a write only file always succeeds.
        if ( $this->fileAccess == self::WRITE_ONLY && $pos == 0 && $whence == SEEK_END )
        {
            return true;
        }

        if ( $this->fileMetaData["seekable"] )
        {
            /**
             * Ugh, for some reason fseek starts throwing warnings for
             * zlib streams with SEEK_END. And there is no way to know this
             * upfront, so we need to use @ here. #fail.
             */
            return @fseek( $this->fp, $pos, $whence );
        }
        else
        {
            switch ( $whence )
            {
                case SEEK_SET:
                    $transPos = $pos;
                    break;

                case SEEK_CUR:
                    $transPos = $pos + ftell( $this->fp );
                    break;

                case SEEK_END:
                    throw new ezcArchiveException( "SEEK_END in a non-seekable file is not supported (yet)." );
            }

            $cur = ftell( $this->fp );
            if ( $transPos <  $cur )
            {
                fclose( $this->fp );
                $this->fp = fopen( $this->fileMetaData["uri"], $this->fileMetaData["mode"] );

                $cur = 0;
            }

            for ( $i = $cur; $i < $transPos; $i++ )
            {
                $c = fgetc( $this->fp );
                if ( $c === false )
                {
                    return -1;
                }
            }

            return 0;
        }
    }

    /**
     * Returns the current file access mode.
     *
     * @var int
     */
    public function getFileAccess()
    {
        return $this->fileAccess;
    }

    /**
     * Returns if the file is in read-only mode.
     *
     * @var bool
     */
    public function isReadOnly()
    {
        return $this->fileAccess == self::READ_ONLY;
    }

    /**
     * Returns if the file is new.
     *
     * @var bool
     */
    public function isNew()
    {
        return $this->isNew;
    }

    /**
     * Returns if the file is modified.
     *
     * @var bool
     */
    public function isModified()
    {
        return $this->isModified;
    }

    /**
     * Closes the file.
     */
    public function close()
    {
        if ( is_resource( $this->fp ) )
        {
            fclose( $this->fp );
            $this->fp = null;
        }
    }
}
?>
PK��Z��5�
�
 ezc/Archive/archive_autoload.phpnu�[���<?php
/**
 * Autoloader definition for the Archive component.
 *
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @version 1.4.1
 * @filesource
 * @package Archive
 */

return array(
    'ezcArchiveException'                 => 'Archive/exceptions/exception.php',
    'ezcArchiveBlockSizeException'        => 'Archive/exceptions/block_size.php',
    'ezcArchiveChecksumException'         => 'Archive/exceptions/checksum.php',
    'ezcArchiveEmptyException'            => 'Archive/exceptions/empty.php',
    'ezcArchiveEntryPrefixException'      => 'Archive/exceptions/entry_prefix.php',
    'ezcArchiveInternalException'         => 'Archive/exceptions/internal_exception.php',
    'ezcArchiveIoException'               => 'Archive/exceptions/io.php',
    'ezcArchiveUnknownTypeException'      => 'Archive/exceptions/unknown_type.php',
    'ezcArchiveValueException'            => 'Archive/exceptions/value.php',
    'ezcArchive'                          => 'Archive/archive.php',
    'ezcArchiveV7Header'                  => 'Archive/tar/headers/v7.php',
    'ezcArchiveV7Tar'                     => 'Archive/tar/v7.php',
    'ezcArchiveFile'                      => 'Archive/file/file.php',
    'ezcArchiveLocalFileHeader'           => 'Archive/zip/headers/local_file.php',
    'ezcArchiveUstarHeader'               => 'Archive/tar/headers/ustar.php',
    'ezcArchiveUstarTar'                  => 'Archive/tar/ustar.php',
    'ezcArchiveBlockFile'                 => 'Archive/file/block_file.php',
    'ezcArchiveCallback'                  => 'Archive/interfaces/callback.php',
    'ezcArchiveCentralDirectoryEndHeader' => 'Archive/zip/headers/central_directory_end.php',
    'ezcArchiveCentralDirectoryHeader'    => 'Archive/zip/headers/central_directory.php',
    'ezcArchiveCharacterFile'             => 'Archive/file/character_file.php',
    'ezcArchiveChecksums'                 => 'Archive/utils/checksums.php',
    'ezcArchiveEntry'                     => 'Archive/entry.php',
    'ezcArchiveFileStructure'             => 'Archive/structs/file.php',
    'ezcArchiveFileType'                  => 'Archive/utils/file_type.php',
    'ezcArchiveGnuHeader'                 => 'Archive/tar/headers/gnu.php',
    'ezcArchiveGnuTar'                    => 'Archive/tar/gnu.php',
    'ezcArchiveOptions'                   => 'Archive/options/archive.php',
    'ezcArchivePaxHeader'                 => 'Archive/tar/headers/pax.php',
    'ezcArchivePaxTar'                    => 'Archive/tar/pax.php',
    'ezcArchiveStatMode'                  => 'Archive/utils/stat_mode.php',
    'ezcArchiveZip'                       => 'Archive/zip/zip.php',
);
?>
PK��ZU��+77ezc/Archive/utils/stat_mode.phpnu�[���<?php
/**
 * File containing the ezcArchiveStatMode class.
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @access private
 */

/**
 * The ezcArchiveStatMode class stores the stat-mode constant values.
 *
 * Compare the bits from the "mode" array element from {@link http://www.php.net/stat}.
 * For example to get the file permissions in an octal number:
 * <code>
 * $stat = stat( "/tmp/myfile.txt" );
 * $perm = decoct( $stat["mode"] & ezcArchiveStatMode::S_PERM_MASK );
 * </code>
 *
 * To see if the file is a directory, the following code can be used:
 * <code>
 * $stat = stat( "/tmp/myfile.txt" );
 * $isDirectory = ( ( $stat["mode"] & S_FMT ) == ezcArchiveStatMode::S_IFDIR );
 * </code>
 *
 * @package Archive
 * @version 1.4.1
 * @access private
 */
class ezcArchiveStatMode
{
    /**
     * Type of the file.
     */
    const S_IFMT = 0170000;

    /**
     * Named pipe (fifo).
     */
    const S_IFIFO = 0010000;

    /**
     * character special.
     */
    const S_IFCHR = 0020000;

    /**
     * Directory
     */
    const S_IFDIR = 0040000;

    /**
     * block special
     */
    const S_IFBLK = 0060000;

    /**
     * regular file
     */
    const S_IFREG = 0100000;

    /**
     * Symbolic link
     */
    const S_IFLNK = 0120000;

    /**
     * Socket
     */
    const S_IFSOCK = 0140000;

    /**
     * Whiteout
     */
    const S_IFWHT = 0160000;

    /**
     * Permission mask
     */
    const S_PERM_MASK = 07777;
}
?>
PK��Z��0���ezc/Archive/utils/checksums.phpnu�[���<?php
/**
 * File containing the ezcArchiveChecksums class.
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @access private
 */

/**
 * The ezcArchiveChecksums is a collection of checksum algorithms. The
 * total-byte-value checksum and CRC32 checksum are currently available.
 *
 * For each different checksum are two methods available:
 * - Calculate the checksum from a string.
 * - Calculate the checksum from a file.
 *
 * The latter will consume less memory since a part of the file is read in
 * memory at the time, and will be freed after use. The consequence might be
 * that the checksum from a string is a bit faster.
 *
 * @package Archive
 * @version 1.4.1
 * @access private
 */
class ezcArchiveChecksums
{
    /**
     * The CRC-32 lookup table.
     *
     * @var array(int)
     */
    private static $crc32Table = false;

    /**
     * Calculates the total-byte-value checksum from a string.
     *
     * Returns the total ASCII value from all characters in the data string.
     * Example 1: For example:
     *
     * <code>
     * $crc = ezcArchiveChecksums::getTotalByteValueFromFile( "abc" );
     * // $crc contains the value: 141 + 142 + 143 = 426
     * </code>
     *
     * @param string $data  Character string.
     * @return int The total byte value.
     *
     * @see getTotalByteValueFromFile()
     */
    public static function getTotalByteValueFromString( $data )
    {
        $total = 0;
        $length = strlen( $data );
        for ( $i = 0; $i < $length; $i++ )
        {
            $total += ord( $data[$i] );
        }

        return $total;
    }

    /**
     * Calculates the total-byte-value checksum from a file.
     *
     * Returns the total ASCII value from all characters in the data string.
     * For example:
     *
     * <code>
     * $crc = ezcArchiveChecksums::getTotalByteValueFromFile( "abc" );
     * // $crc contains the value: 141 + 142 + 143 = 426
     * </code>
     *
     * @param string $fileName The file to use
     * @return int Value which contains the total byte value.
     */
    public static function getTotalByteValueFromFile( $fileName )
    {
        if ( ( $fp = fopen( $fileName, 'rb' ) ) === false )
        {
            return false;
        }

        // Perform the algorithm on each character in file
        $total = 0;
        while ( true )
        {
            $i = fread( $fp, 1 );
            if ( strlen( $i ) == 0 )
            {
                break;
            }

            $total += ord( $i );
        }

        fclose( $fp );

        return $total;
    }

   /**
    * Calculates the (official) CRC-32 polynomial from a $data string as input.
    *
    * @param string $data
    * @return int The calculated CRC-32.
    */
    public static function getCrc32FromString( $data )
    {
        return crc32( $data );
    }

    /**
     * Calculates the (official) CRC-32 polynomial from a file.
     *
     * This method is taken from the PHP user comments
     * (http://no.php.net/manual/en/function.crc32.php).
     *
     * @param string $fileName Absolute or relative path to the file.
     * @return int The calculated CRC-32.
     */
    public static function getCrc32FromFile( $fileName )
    {
        if ( self::$crc32Table === false )
        {
            self::crc32InitTable();
        }

        // Once the lookup table has been filled in by the two functions above,
        // this function creates all CRCs using only the lookup table.

        // You need unsigned variables because negative values
        // introduce high bits where zero bits are required.
        // PHP doesn't have unsigned integers:
        // I've solved this problem by doing a '&' after a '>>'.

        // Start out with all bits set high.
        $crc = 0xffffffff;

        // Added for issue #13517: Not possible to add directories to an archive on Windows
        if ( is_dir( $fileName ) )
        {
            return false;
        }

        if ( ( $fp = fopen( $fileName ,'rb' ) ) === false )
        {
            return false;
        }

        // Perform the algorithm on each character in file
        while ( true )
        {
            $i = fread( $fp, 1 );
            if ( strlen( $i ) == 0 )
            {
                break;
            }
            $crc = ( ( $crc >> 8 ) & 0x00ffffff ) ^ self::$crc32Table[( $crc & 0xFF ) ^ ord( $i )];
        }

        fclose( $fp );

        // Exclusive OR the result with the beginning value.
        return $crc ^ 0xffffffff;
    }

    /**
     * Initializes the CRC-32 table.
     *
     * Builds the lookup table array. This is the official polynomial used by
     * CRC-32 in PKZip, WinZip and Ethernet.
     *
     * This method is taken from the PHP user comments
     * (http://no.php.net/manual/en/function.crc32.php).
     */
    protected static function crc32InitTable()
    {
        // Builds lookup table array
        // This is the official polynomial used by
        // CRC-32 in PKZip, WinZip and Ethernet.
        $polynomial = 0x04c11db7;

        // 256 values representing ASCII character codes.
        for ( $i = 0; $i <= 0xFF; ++$i )
        {
            self::$crc32Table[$i] = ( self::crc32Reflect( $i, 8 ) << 24 );

            for ( $j = 0; $j < 8; ++$j )
            {
                self::$crc32Table[$i] = ( ( self::$crc32Table[$i] << 1 ) ^ ( ( self::$crc32Table[$i] & ( 1 << 31 ) ) ? $polynomial : 0 ) );
            }

            self::$crc32Table[$i] = self::crc32Reflect( self::$crc32Table[$i], 32 );
        }
    }

    /**
     * Reflects CRC bits in the lookup table
     *
     * This method is taken from the PHP user comments
     * (http://no.php.net/manual/en/function.crc32.php).
     *
     * @param int $ref
     * @param int $ch
     * @return int
     */
    protected static function crc32Reflect( $ref, $ch )
    {
        $value = 0;

        // Swap bit 0 for bit 7, bit 1 for bit 6, etc.
        for ( $i = 1; $i < ( $ch + 1 ); ++$i )
        {
            if ( $ref & 1 )
            {
                $value |= ( 1 << ( $ch - $i ) );
            }

            $ref = ( ( $ref >> 1 ) & 0x7fffffff );
        }

        return $value;
    }
}
?>
PK��Z	�z��ezc/Archive/utils/file_type.phpnu�[���<?php
/**
 * File containing the abstract ezcArchiveFileType class.
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @access private
 */

/**
 * This class provides methods to detect various archive or compression types.
 *
 * The archive formats that can be detected are:
 * - tar ( v7, ustar, pax, gnu )
 * - zip
 *
 * The compression types that can be detected are:
 * - gzip
 * - bzip2
 *
 * @package Archive
 * @version 1.4.1
 * @access private
 */
class ezcArchiveFileType
{
    /**
     * Returns the archive type of the given file.
     *
     * @param string $fileName  Absolute or relative path to the file.
     *
     * @return int    Possible values are: {@link ezcArchive::ZIP},
     *               {@link ezcArchive::TAR}, {@link ezcArchive::TAR_V7}, {@link ezcArchive::TAR_USTAR},
     *               {@link ezcArchive::TAR_PAX}, {@link ezcArchive::TAR_GNU}.
     */
    public static function detect( $fileName )
    {
        $fp = fopen( $fileName, "r" );
        if ( $fp === false )
        {
            return false;
        }

        $data = fread( $fp, 512 );
        fclose( $fp );

        if ( self::isGzip( $data ) )
        {
            return ezcArchive::GZIP;
        }

        if ( self::isBzip2( $data ) )
        {
            return ezcArchive::BZIP2;
        }

        if ( self::isZip( $data ) )
        {
            return ezcArchive::ZIP;
        }

        // Order is important.
        if ( self::isPaxTar( $data ) )
        {
            return ezcArchive::TAR_PAX;
        }

        if ( self::isV7Tar( $data ) )
        {
            return ezcArchive::TAR_V7;
        }

        if ( self::isUstarTar( $data ) )
        {
            return ezcArchive::TAR_USTAR;
        }

        if ( self::isGnuTar( $data ) )
        {
            return ezcArchive::TAR_GNU;
        }

        return false;
    }

    /**
     * Checks if the provided $data matches the known signature of a Bzip2 archive.
     *
     * The $data string parameter must contain the first block of data from a file. It will be
     *                     matched against the known signature for this archive type.
     *
     * @param string $data
     * @return bool
     */
    public static function isBzip2( $data )
    {
        if ( ord( $data[0] ) == 0x42 && ord( $data[1] ) == 0x5a )
        {
            return true;
        }
        return false;
    }

    /**
     * Checks if the provided $data matches the known signature of a Gzip archive.
     *
     * The $data string parameter must contain the first block of data from a file. It will be
     *                     matched against the known signature for this archive type.
     *
     * @param string $data
     * @return bool
     */
    public static function isGzip( $data )
    {
        $h = unpack( "Cid1/Cid2", $data[0] . $data[1] );
        if ( $h["id1"] == 0x1f && $h["id2"] == 0x8b )
        {
            return true;
        }

        return false;
    }

    /**
     * Checks if the provided $data matches the known signature of a Zip archive.
     *
     * The $data string parameter must contain the first block of data from a file. It will be
     *                     matched against the known signature for this archive type.
     *
     * @param string $data
     * @return bool
     */
    public static function isZip( $data )
    {
        if ( $data[0] . $data[1] == pack( "v",  0x4b50 ) )
        {
            return true;
        }

        return false;
    }

    /**
     * Checks if the provided $data matches the known signature of a V7 tar archive.
     *
     * The $data string parameter must contain the first block of data from a file. It will be
     *                     matched against the known signature for this archive type.
     *
     * @param string $data
     * @return bool
     */
     public static function isV7Tar( $data )
     {
        if ( strcmp( substr( $data, 257, 5 ), "\0\0\0\0\0" ) == 0 && strcmp( substr( $data, 263, 2 ), "\0\0" ) == 0 )
        {
            if ( self::tarContainsFileName( $data ) )
            {
                return true;
            }
        }

        return false;
     }

    /**
     * Checks if the provided $data matches the known signature of a USTar archive.
     *
     * The $data string parameter must contain the first block of data from a file. It will be
     *                     matched against the known signature for this archive type.
     *
     * @param string $data
     * @return bool
     */
    public static function isUstarTar( $data )
    {
        if ( strcmp( substr( $data, 257, 5 ), "ustar" ) == 0 && strcmp( substr( $data, 263, 2 ), "00" ) == 0 )
        {
            if ( self::tarContainsFileName( $data ) )
            {
                return true;
            }
        }

        return false;
    }

    /**
     * Checks if the provided $data matches the known signature of a PAX tar archive.
     *
     * The $data string parameter must contain the first block of data from a file. It will be
     *                     matched against the known signature for this archive type.
     *
     * @param string $data
     * @return bool
     */
    public static function isPaxTar( $data )
    {
        if ( strcmp( substr( $data, 257, 5 ), "ustar" ) == 0 && strcmp( substr( $data, 263, 2 ), "00" ) == 0 )
        {
            $type = substr( $data, 156, 1 );
            if ( $type == "x" || $type == "g" )
            {
                if ( self::tarContainsFileName( $data ) )
                {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * Checks if the provided $data matches the known signature of a GNU tar archive.
     *
     * The $data string parameter must contain the first block of data from a file. It will be
     *                     matched against the known signature for this archive type.
     *
     * @param string $data
     * @return bool
     */
    public static function isGnuTar( $data )
    {
        if ( strcmp( substr( $data, 257, 5 ), "ustar" ) == 0 && strcmp( substr( $data, 263, 2 ), " \0" ) == 0 )
        {
            if ( self::tarContainsFileName( $data ) )
            {
                return true;
            }
        }

        return false;
    }

    /**
     * Checks if the provided $data contains a file name.
     *
     * The $data string parameter must contain the first block of data from a file. It will be
     *                     matched against the known signature for this archive type.
     *
     * @param string $data
     * @return bool
     */
    public static function tarContainsFileName( $data )
    {
        return $data[0] != "\0";
    }
}
?>
PK��Z}�sb�	�	ezc/Archive/options/archive.phpnu�[���<?php
/**
 * File containing the ezcArchiveOptions class
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * Class containing the basic options for ezcBase' autoload.
 *
 * @property bool $readOnly
 *           Whether the archive should be opened in read only mode.
 * @property ezcArchiveCallback $extractCallback
 *           Callback object to be used for every directory and file creation
 *           action, so that permissions, user and group may be changed
 *           depending on user preferences. See {@link ezcArchiveCallback}.
 *
 * @package Archive
 * @version 1.4.1
 */
class ezcArchiveOptions extends ezcBaseOptions
{
    /**
     * Constructs an object with the specified values.
     *
     * @throws ezcBasePropertyNotFoundException
     *         if $options contains a property not defined
     * @throws ezcBaseValueException
     *         if $options contains a property with a value not allowed
     * @param array(string=>mixed) $options
     */
    public function __construct( array $options = array() )
    {
        $this->readOnly = false;
        $this->extractCallback = null;

        parent::__construct( $options );
    }

    /**
     * Sets the option $name to $value.
     *
     * @throws ezcBasePropertyNotFoundException
     *         if the property $name is not defined
     * @throws ezcBaseValueException
     *         if $value is not correct for the property $name
     * @param string $name
     * @param mixed $value
     * @ignore
     */
    public function __set( $name, $value )
    {
        switch ( $name )
        {
            case 'readOnly':
                if ( !is_bool( $value ) )
                {
                    throw new ezcBaseValueException( $name, $value, 'bool' );
                }
                $this->properties[$name] = $value;
                break;

            case 'extractCallback':
                if ( !is_null( $value ) && !( is_object( $value ) && in_array( 'ezcArchiveCallback', class_parents( $value ) ) ) )
                {
                    throw new ezcBaseValueException( $name, $value, 'instance of ezcArchiveCallback' );
                }
                $this->properties[$name] = $value;
                break;

            default:
                throw new ezcBasePropertyNotFoundException( $name );
        }
    }
}
?>
PK��Zf� S	S	ezc/Archive/structs/file.phpnu�[���<?php
/**
 * File contains the ezcArchiveFileStructure class.
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @access private
 */

/**
 * The ezcArchiveFileStructure class represents a data structure which contains file information.
 *
 * This class is used as an structure in order to prevent using an hash (or array).
 * {@link ezcArchiveEntry} encapsulates this class and has convenient methods to retrieve the information.
 *
 * @package Archive
 * @version 1.4.1
 * @access private
 */
class ezcArchiveFileStructure extends ezcBaseStruct
{
    /**
     * The file path.
     *
     * @var string
     */
    public $path;

    /**
     * The permissions of the entry.
     *
     * @var int
     */
    public $mode;

    /**
     * The user ID.
     *
     * @var int
     */
    public $uid;

    /**
     * The group ID.
     *
     * @var int
     */
    public $gid;

    /**
     * The user name (only for some supported formats).
     *
     * @var string
     */
    public $userName = null;

    /**
     * The group name (only for some supported formats).
     *
     * @var string
     */
    public $groupName = null;

    /**
     * Last modification time timestamp.
     *
     * @var int
     */
    public $mtime;

    /**
     * Last access time timestamp.
     *
     * @var int
     */
    public $atime = false;

    /**
     * Specifies the type of the entry.
     *
     * @var int  Possible values: {@link ezcArchiveEntry::IS_LINK}, {@link ezcArchiveEntry::IS_SYMBOLIC_LINK},
     *           {@link ezcArchiveEntry::IS_CHARACTER_DEVICE}, {@link ezcArchiveEntry::IS_BLOCK_DEVICE},
     *           {@link ezcArchiveEntry::IS_DIRECTORY}, or {@link ezcArchiveEntry::IS_FIFO}.
     */
    public $type;

    /**
     * The link target.
     *
     * This value is only valid when the {@link $type} indicates an actual link.
     *
     * @var string
     */
    public $link;

    /**
     * The file size in bytes.
     *
     * $var int
     */
    public $size;

    /**
     * Inode number of the file.
     *
     * $var int
     */
    public $ino;

    /**
     * Major device number.
     *
     * $var int
     */
    public $major;

    /**
     * Minor device number.
     *
     * $var int
     */
    public $minor;
}
?>
PK��Z�L��<< ezc/Archive/exceptions/empty.phpnu�[���<?php
/**
 * File containing the ezcArchiveEmptyException class.
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * Exception for when an archive is empty.
 *
 * @package Archive
 * @version 1.4.1
 */
class ezcArchiveEmptyException extends ezcArchiveException
{
    /**
     * Constructs a new exception for empty archive.
     */
    public function __construct()
    {
        parent::__construct( "The archive is empty." );
    }
}
?>
PK��Z�����'ezc/Archive/exceptions/unknown_type.phpnu�[���<?php
/**
 * File containing the ezcArchiveUnknownTypeException class.
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * Exception thrown when encountering an archive of an unknow type.
 *
 * @package Archive
 * @version 1.4.1
 */
class ezcArchiveUnknownTypeException extends ezcArchiveException
{
    /**
     * Constructs a new unknown type exception for the specified archive.
     *
     * @param string $archiveName
     */
    public function __construct( $archiveName )
    {
        parent::__construct( "The type of the archive '{$archiveName}' cannot be determined." );
    }
}
?>
PK��Z�G��MM$ezc/Archive/exceptions/exception.phpnu�[���<?php
/**
 * File containing the ezcArchiveException class.
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * General exception class for the Archive package.
 *
 * @package Archive
 * @version 1.4.1
 */
class ezcArchiveException extends ezcBaseException
{
    /**
     * Construct a new archive exception.
     *
     * @param string $message
     */
    public function __construct( $message )
    {
        parent::__construct( $message );
    }
}
?>
PK��Z&Y���#ezc/Archive/exceptions/checksum.phpnu�[���<?php
/**
 * File containing the ezcArchiveChecksumException class.
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * Exception will be thrown when the checksum of the file is invalid.
 *
 * @package Archive
 * @version 1.4.1
 */
class ezcArchiveChecksumException extends ezcArchiveException
{
    /**
     * Constructs a new checksum exception for the specified file.
     *
     * @param string $file
     */
    public function __construct( $file )
    {
        parent::__construct( "The checksum of the file '{$file}' is invalid." );
    }
}
?>
PK��Z�0dii%ezc/Archive/exceptions/block_size.phpnu�[���<?php
/**
 * File containing the ezcArchiveBlockSizeException class.
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * Exception will be thrown when the block-size of an archive is invalid.
 *
 * @package Archive
 * @version 1.4.1
 */
class ezcArchiveBlockSizeException extends ezcArchiveException
{
    /**
     * Constructs a new block-size exception for the specified archive.
     *
     * @param string $archiveName
     * @param string $msg
     */
    public function __construct( $archiveName, $msg = null )
    {
        $default = "The archive '{$archiveName}' has an invalid block size.";

        if ( $msg !== null )
        {
            $default .= " {$msg}";
        }

        parent::__construct( $default );
    }
}
?>
PK��Z�N�8TT ezc/Archive/exceptions/value.phpnu�[���<?php
/**
 * File containing the ezcArchiveValueException class.
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * Exception thrown when encountering a wrong archive value.
 *
 * @package Archive
 * @version 1.4.1
 */
class ezcArchiveValueException extends ezcArchiveException
{
    /**
     * Construct an archive exception.
     *
     * If $expectedValue is provided then it will be included in the exception
     * message thrown.
     *
     * @param mixed $value
     * @param mixed $expectedValue
     */
    public function __construct( $value, $expectedValue = null )
    {
        $type = gettype( $value );
        if ( in_array( $type, array( 'array', 'object', 'resource' ) ) )
        {
            $value = serialize( $value );
        }

        $msg = "The value '{$value}' is incorrect.";
        if ( $expectedValue )
        {
            $msg .= " Allowed values are: " . $expectedValue . '.';
        }
        parent::__construct( $msg );
    }
}
?>
PK��Z�9+IIezc/Archive/exceptions/io.phpnu�[���<?php
/**
 * File containing the ezcArchiveIoException class.
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * Exception thrown when an IO error occurs.
 *
 * @package Archive
 * @version 1.4.1
 */
class ezcArchiveIoException extends ezcArchiveException
{
    /**
     * Constructs a new IO exception.
     *
     * @param string $message
     */
    public function __construct( $message )
    {
        parent::__construct( $message );
    }
}
?>
PK��Z}�H���-ezc/Archive/exceptions/internal_exception.phpnu�[���<?php
/**
 * File containing the ezcArchiveInternalException class.
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * Exception used when an internal errors occurs in the Archive component.
 *
 * @package Archive
 * @version 1.4.1
 */
class ezcArchiveInternalException extends ezcArchiveException
{
    /**
     * Construct an internal archive exception.
     *
     * @param string $message
     */
    public function __construct( $message )
    {
        parent::__construct( "Internal error: " . $message );
    }
}
?>
PK��Z �����'ezc/Archive/exceptions/entry_prefix.phpnu�[���<?php
/**
 * File containing the ezcArchiveEntryPrefixException class.
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * An exception for an invalid prefix of a file entry.
 *
 * @package Archive
 * @version 1.4.1
 */
class ezcArchiveEntryPrefixException extends ezcArchiveException
{
    /**
     * Constructs a new entry prefix exception for the specified file entry.
     *
     * @param string $prefix
     * @param string $fileName
     */
    public function __construct( $prefix, $fileName )
    {
        parent::__construct( "The prefix '{$prefix}' from the file entry '{$fileName}' is invalid." );
    }
}
?>
PK��Z�h��A�Aezc/Archive/entry.phpnu�[���<?php
/**
 * File contains the ezcArchiveEntry class.
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * The ezcArchiveEntry class provides system-independent file information.
 *
 * ezcArchiveEntry provides file information about the file path, it's access rights and whether the file is an
 * directory, symbolic link, hard link, block-file, etc. The owner name, the group name, the last access time
 * are also available. ezcArchiveEntry can be used to get the file information directly from the file-system or
 * from an archive.
 *
 * The main purpose of ezcArchiveEntry is to provide information about:
 * - Files on the file-system that should be appended to the archive.
 * - Files currently in the archive that can be extracted to the file-system.
 *
 * Use the {@link getEntryFromFile()} to create an ezcArchiveEntry from a file in the filesystem.
 * Important is that the prefix is set.
 * This specifies which part of the path should be stripped, before the entry is appended to the archive.
 * See also {@link ezcArchive::append()} or {@link ezcArchive::appendToCurrent()}.
 *
 * When the ezcArchiveEntry is an entry in the archive, the {@link getPath()} method contains always an
 * relative path, and the prefix is not set.
 *
 * @package Archive
 * @version 1.4.1
 */
class ezcArchiveEntry
{
    /**
     * Is a regular file.
     */
    const IS_FILE = 0;

    /**
     * Is a hard link.
     */
    const IS_LINK = 1;

    /**
     * Is a symbolic link.
     */
    const IS_SYMBOLIC_LINK = 2;

    /**
     * Is a character device.
     */
    const IS_CHARACTER_DEVICE = 3;

    /**
     * Is a block device.
     */
    const IS_BLOCK_DEVICE = 4;

    /**
     * Is a directory.
     */
    const IS_DIRECTORY = 5;

    /**
     * Is a FIFO.
     */
    const IS_FIFO = 6;

    /**
     * Not used, is Tar specific?
     */
    const IS_RESERVED = 7;

    /**
     * Contains the file information.
     *
     * @var ezcArchiveFileStructure
     */
    protected $fileStructure;

    /**
     * The prefix of the file that may be removed from the path.
     *
     * @var string
     */
    protected $prefix;

    /**
     * Constructs an archiveEntry from the {@link ezcArchiveFileStructure}.
     *
     * The $struct parameter contains the raw file information.
     * This class encapsulates the file information structure and provides convenient methods to retrieve
     * the information.
     *
     * @param ezcArchiveFileStructure $struct
     */
    public function __construct( ezcArchiveFileStructure $struct )
    {
        $this->fileStructure =  $struct;
    }

    /**
     * Returns true when this entry represents a directory.
     *
     * @return bool
     */
    public function isDirectory()
    {
        return ( $this->fileStructure->type == self::IS_DIRECTORY );
    }

    /**
     * Returns true when this entry represents a file.
     *
     * @return bool
     */
    public function isFile()
    {
        return ( $this->fileStructure->type == self::IS_FILE );
    }

    /**
     * Returns true when this entry represents a hard link.
     *
     * @return bool
     */
    public function isHardLink()
    {
        return ( $this->fileStructure->type == self::IS_LINK );
    }

    /**
     * Returns true when this entry represents a symbolic link.
     *
     * @return bool
     */
    public function isSymLink()
    {
        return ( $this->fileStructure->type == self::IS_SYMBOLIC_LINK );
    }

    /**
     * Returns true when this entry represents a symbolic or a hard link.
     *
     * @return bool
     */
    public function isLink()
    {
        return ( $this->isHardLink() || $this->isSymLink() );
    }

    /**
     * Returns type of the entry.
     *
     * @return int   Possible values are: {@link IS_LINK}, {@link IS_SYMBOLIC_LINK}, {@link IS_CHARACTER_DEVICE}, {@link IS_BLOCK_DEVICE},
     * {@link IS_DIRECTORY}, or {@link IS_FIFO}.
     */
    public function getType()
    {
        return $this->fileStructure->type;
    }

    /**
     * Returns the user ID of the entry.
     *
     * @return int
     */
    public function getUserId()
    {
        return $this->fileStructure->uid;
    }

    /**
     * Returns the group ID of the entry.
     *
     * @return int
     */
    public function getGroupId()
    {
        return $this->fileStructure->gid;
    }

    /**
     * Returns the complete path or path without the prefix.
     *
     * By default the full path is returned, unless the $withPrefix is set
     * to true.
     *
     * @param bool $withPrefix
     *
     * @return string
     */
    public function getPath( $withPrefix = true )
    {
        if ( $withPrefix )
        {
            return $this->fileStructure->path;
        }
        else
        {
            return $this->getPathWithoutPrefix( $this->fileStructure->path, $this->prefix );
        }
    }

    /**
     * Returns the path without the prefix.
     *
     * The path without the prefix is returned.
     * If the prefix doesn't match with the complete path, the whole path is returned.
     *
     * @param string $completePath
     * @param string $prefix
     * @return string
     */
    private function getPathWithoutPrefix( $completePath, $prefix )
    {
        $prefixLength = strlen( $prefix );

        if ( strcmp( substr( $completePath, 0,  $prefixLength ), $prefix ) == 0 )
        {
            $i = 0;
            // Check next character
            while ( $completePath[$i + $prefixLength] == "/" )
            {
                $i++;
            }

            $result = substr( $completePath, $prefixLength + $i );
            return $result;
        }
        else
        {
            // No match.
            return $completePath;
        }
    }

    /**
     * Removes the prefix from the path and clears the prefix.
     *
     * This method is useful when it comes to adding a entry to an archive
     * and the complete path to the file is no longer needed.
     */
    public function removePrefixFromPath()
    {
        $this->fileStructure->path = $this->getPathWithoutPrefix( $this->fileStructure->path, $this->prefix );
        $this->prefix = "";
    }


    /**
     * Returns the link with or without prefix.
     *
     * This method is similar to {@link getPath()}, but returns the link instead of the path.
     * If the current does not represents a link, an empty string is returned.
     * Use the {@link isLink()} method to see if the current entry is a link.
     *
     * @param bool $withPrefix
     */
    public function getLink( $withPrefix = true )
    {
        if ( $withPrefix )
        {
            return $this->fileStructure->link;
        }
        else
        {
            return $this->getPathWithoutPrefix( $this->fileStructure->link, $this->prefix );
        }
    }

    /**
     * Returns a bit mask representing the permissions of this entry.
     *
     * It returns the permissions in octal numbers as a string, for example:
     * "0000755"
     *
     * @return string
     */
    public function getPermissions()
    {
        return $this->fileStructure->mode;
    }

    /**
     * Returns the file size.
     *
     * @return int
     */
    public function getSize()
    {
        return $this->fileStructure->size;
    }

    /**
     * Returns the modification time as a timestamp.
     *
     * @return int
     */
    public function getModificationTime()
    {
        return $this->fileStructure->mtime;
    }

    /**
     * Returns the last access time as a timestamp.
     *
     * @return int
     */
    public function getAccessTime()
    {
        return $this->fileStructure->atime;
    }

    /**
     * Returns the inode.
     *
     * @return int
     */
    public function getInode()
    {
        return $this->fileStructure->ino;
    }

    /**
     * Returns the major device number.
     *
     * @return int
     */
    public function getMajor()
    {
        return $this->fileStructure->major;
    }

    /**
     * Returns the minor device number.
     *
     * @return int
     */
    public function getMinor()
    {
        return $this->fileStructure->minor;
    }

    /**
     * Returns the device.
     *
     * FIXME DEPRECATED?
     *
     * @return int
     */
    public function getDevice()
    {
        return $this->fileStructure->device;
    }

    /**
     * Returns the permissions as a string.
     *
     * If the entry has all the permissions, it will return: "rwxrwx" Where the first three letters
     * represent the group permissions and the last three letters the user permissions.
     *
     * @return string
     */
    public function getPermissionsString()
    {
        $out = "";

        $perm = octdec( $this->getPermissions() );

        for ( $i = 6; $i >= 0; $i -= 3 )
        {
            $part = ( $perm >> $i );

            if ( $part & 4 )
            {
                $out .= "r";
            }
            else
            {
                $out .= "-";
            }

            if ( $part & 2 )
            {
                $out .= "w";
            }
            else
            {
                $out .= "-";
            }

            if ( $part & 1 )
            {
                $out .= "x";
            }
            else
            {
                $out .= "-";
            }
        }
        return $out;
    }

    /**
     * Returns the type string for the current type of the entry.
     *
     * Returns a type string for the current entry. If the entry is a:
     * - directory: "d".
     * - file: "-".
     * - symbolic link: "l".
     * - hard link: "h".
     *
     * @return string
     */
    public function getTypeString()
    {
        switch ( $this->fileStructure->type )
        {
            case self::IS_DIRECTORY:
                return "d";

            case self::IS_FILE:
                return "-";

            case self::IS_SYMBOLIC_LINK:
                return "l";

            case self::IS_LINK:
                return "h";

            default:
                return "Z";
        }
    }

    /**
     * Sets the prefix.
     *
     * @param string $prefix
     */
    public function setPrefix( $prefix )
    {
        $this->prefix = $prefix;
    }

    /**
     * Returns the prefix.
     *
     * @return string
     */
    public function getPrefix( )
    {
        return $this->prefix;
    }

    /**
     * Returns a string representing the current entry.
     *
     * @return string
     */
    public function __toString()
    {
        $out = $this->getTypeString();
        $out .= $this->getPermissionsString();

        $out .= " ";
        $out .= $this->getUserId() . " ";
        $out .= $this->getGroupId() . " ";
        $out .= str_pad( $this->getSize(), 7, " ", STR_PAD_LEFT ) . " ";
        $out .= date( "Y-m-d H:i:s ", $this->getModificationTime() );
        $out .= $this->getPath();

        $out .= ( $this->isLink() ? " -> " . $this->getLink() : "" );

        return $out;
    }

    /**
     * Create a file structure from a $file in the file system.
     *
     * @param string $file
     * @return ezcArchiveFileStructure
     */
    protected static function getFileStructureFromFile( $file )
    {
        clearstatcache();
        $stat = ( is_link( $file ) ? lstat( $file ) : stat( $file ) );
        $lstat = lstat( $file );

        // Set the file information.
        $struct = new ezcArchiveFileStructure();

        $struct->path = $file;
        $struct->gid =  $stat["gid"];
        $struct->uid =  $stat["uid"];
        $struct->mtime = $stat["mtime"];
        $struct->atime = $stat["atime"];
        $struct->mode = decoct( $stat["mode"] & ezcArchiveStatMode::S_PERM_MASK ); // First bits describe the type.
        $struct->ino = $stat["ino"];

        $struct->type = self::getLinkType( $stat );

        if ( $struct->type == ezcArchiveEntry::IS_FILE )
        {
            $struct->size = $stat["size"];
        }
        else
        {
            $struct->size = 0;
        }

        if ( $struct->type == ezcArchiveEntry::IS_SYMBOLIC_LINK )
        {
            $struct->link = readlink( $file );
        }

        $rdev = $stat["rdev"];
        if ( $rdev == -1 )
        {
            if ( $struct->type == ezcArchiveEntry::IS_BLOCK_DEVICE || $struct->type == ezcArchiveEntry::IS_CHARACTER_DEVICE)
            {
                throw new ezcArchiveException( "Cannot add a device to the TAR because the device type cannot be determined. Your system / PHP version does not support 'st_blksize'." );
            }

            $rdev = 0;
        }

        $struct->major = ( int ) ( $rdev / 256 );
        $struct->minor = ( int ) ( $rdev % 256 );

        return $struct;
    }

    /**
     * Returns one or an array of ezcArchiveEntry's from one or multiple files in the file system.
     *
     * One or multiple ezcArchiveEntry's are created upon the given files.
     * The prefix will directly set for the ezcArchiveEntry with $prefix.
     *
     * If $files contains a path to a file, then one ezcArchiveEntry will be created and returned.
     * If $files is an array of paths, then all those ezcArchiveEntry's will be created and returned in an array.
     *
     * When multiple files are given in an array, this method will search for hard links among other files in the array.
     *
     * @throws ezcArchiveEntryPrefixException if the prefix is invalid.
     *
     * @param string|array(string)  $files
     * @param string                $prefix
     * @return ezcArchiveEntry
     */
    public static function getEntryFromFile( $files, $prefix )
    {
        $isArray = true;
        if ( !is_array( $files ) )
        {
            $isArray = false;
            $files = array( $files );
        }

        $inodes = array();
        $i = 0;
        foreach ( $files as $file )
        {
            if ( !file_exists( $file ) && !is_link( $file ) )
                return false;

            $struct = self::getFileStructureFromFile( $file );

            // Check if it's a hardlink if the OS supports it, and handle it.
            if ( ezcBaseFeatures::supportsLink() )
            {
                if ( isset( $inodes[ $struct->ino ] ) )
                {
                    // Yes, it's a hardlink.
                    $struct->type = ezcArchiveEntry::IS_LINK;
                    $struct->size = 0;
                    $struct->link = $inodes[ $struct->ino ];
                }
                else
                {
                    $inodes[ $struct->ino ] = $struct->path;
                }
            }

            $entry[$i] = new ezcArchiveEntry( $struct );
            $entry[$i]->setPrefix( $prefix );

            if ( isset( $prefix ) && strlen( $prefix ) > 0 )
            {
                if ( strlen( $entry[$i]->getPath() ) == strlen( $entry[$i]->getPath( false ) ) )
                {
                    throw new ezcArchiveEntryPrefixException( $prefix, $file );
                }
            }

            $i++;
        }

        return ( $isArray ? $entry : $entry[0] );
    }

    /**
     * Returns an ezcArchiveEntry-type that corresponds to the ezcArchiveStatMode-type
     *
     * @param ezcArchiveStatMode $stat Possible values are: {@link ezcArchiveStatMode::S_IFIFO}, {@link ezcArchiveStatMode::S_IFCHR},
     *                                 {@link ezcArchiveStatMode::S_IFDIR}, {@link ezcArchiveStatMode::S_IFBLK},
     *                                 {@link ezcArchiveStatMode::S_IFREG}, or {@link ezcArchiveStatMode::S_IFLNK}.
     *
     * @return int                    Possible values are: {@link IS_LINK}, {@link IS_SYMBOLIC_LINK}, {@link IS_CHARACTER_DEVICE},
     *                                 {@link IS_BLOCK_DEVICE}, {@link IS_DIRECTORY}, or {@link IS_FIFO}.
     */
    protected static function getLinkType( $stat )
    {
        switch ( $stat["mode"] & ezcArchiveStatMode::S_IFMT )
        {
            case ezcArchiveStatMode::S_IFIFO:
                return ezcArchiveEntry::IS_FIFO;

            case ezcArchiveStatMode::S_IFCHR:
                return ezcArchiveEntry::IS_CHARACTER_DEVICE;

            case ezcArchiveStatMode::S_IFDIR:
                return ezcArchiveEntry::IS_DIRECTORY;

            case ezcArchiveStatMode::S_IFBLK:
                return ezcArchiveEntry::IS_BLOCK_DEVICE;

            case ezcArchiveStatMode::S_IFREG:
                return ezcArchiveEntry::IS_FILE;

            case ezcArchiveStatMode::S_IFLNK:
                return ezcArchiveEntry::IS_SYMBOLIC_LINK;

            // Hardlinks are not resolved here. FIXME?
        }

        return false;
    }
}
?>
PK��Z�\�^G^G-ezc/Archive/zip/headers/central_directory.phpnu�[���<?php
/**
 * File containing the ezcArchiveCentralDirectoryHeader class.
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @access private
 */

/**
 * The ezcArchiveCentralDirectoryHeader class represents the Zip central directory header.
 *
 * ezcArchiveCentralDirectoryHeader can read the header from an ezcArchiveCharacterFile or ezcArchiveEntry.
 *
 * The values from the headers are directly accessible via the class properties, and allows
 * reading and writing to specific header values.
 *
 * The entire header can be appended to an ezcArchiveCharacterFile again or written to an ezcArchiveFileStructure.
 * Information may get lost, though.
 *
 * The central directory format[1]:
 *
 * <pre>
 *  [file header 1]
 *  .
 *  .
 *  .
 *  [file header n]
 *  [digital signature] <-- Optional, TODO: check if implemented.
 * </pre>
 *
 * The Central Directory Header has the following structure:
 *
 * <pre>
 * + ---+---------+------------+------------------------+------------------------------------+
 * | ID | Offset  | Field size | Property               |  Description                       |
 * +----+---------+------------+------------------------+------------------------------------+
 * |    |  0      | 4          | -                      | Central directory header signature |
 * |    |  4      | 2          | versionMadeBy          | Version made by                    |
 * |    |  6      | 2          | versionNeededToExtract | Version needed to extract          |
 * |    |  8      | 2          | bitFlag                | General purpose bit flag           |
 * |    |  10     | 2          | compressionMethod      | Compression method                 |
 * |    |  12     | 2          | lastModFileTime        | Last modification file time        |
 * |    |  14     | 2          | lastModFileDate        | Last modification file date        |
 * |    |  16     | 4          | crc                    | crc-32                             |
 * |    |  20     | 4          | compressedSize         | compressed size                    |
 * |    |  24     | 4          | uncompressedSize       | uncompressed size                  |
 * | X: |  26     | 2          | fileNameLength         | file name length                   |
 * | Y: |  28     | 2          | extraFieldLength       | extra field length                 |
 * | Z: |  30     | 2          | fileCommentLength      | file comment length                |
 * |    |  32     | 2          | diskNumberStart        | disk number start                  |
 * |    |  34     | 2          | internalFileAttributes | internal file attributes           |
 * |    |  38     | 4          | externalFileAttributes | external file attributes           |
 * |    |  42     | 4          | relativeHeaderOffset   | relative offset of local header    |
 * |    |  46     | X          | fileName               | file name                          |
 * |    |  46+X   | Y          | -                      | extra field                        |
 * |    |  46+X+Y | Z          | comment                | file comment                       |
 * +----+---------+------------+------------------------+------------------------------------+
 * </pre>
 *
 * The columns of the table are:
 * - ID gives a label to a specific field or row in the table.
 * - Offset describes the start position of a header field.
 * - Field size describes the size of the field in bytes.
 * - Property is the name of the property that will be set by the header field.
 * - Description explains what this field describes.
 *
 * The central directory signature cannot be changed and is set in the constant {@link self::magic}.
 *
 * The extra fields that are implemented and references to extra documentation can be found in
 * the {@link ezcArchivelocalFileHeader}.
 *
 * @package Archive
 * @version 1.4.1
 * @access private
 */
class ezcArchiveCentralDirectoryHeader extends ezcArchiveLocalFileHeader
{
    /**
     * Defines the signature of this header.
     */
    const magic = 0x02014b50;

    /**
     * Creates and initializes a new header.
     *
     * If the ezcArchiveCharacterFile $file is null then the header will be empty.
     * When an ezcArchiveCharacterFile is given, the file position should be directly after the
     * signature of the header. This header will be read from the file and initialized in this class.
     *
     * @param ezcArchiveCharacterFile $file
     */
    public function __construct( ezcArchiveCharacterFile $file = null )
    {
        if ( !is_null( $file ) )
        {
            $this->properties = unpack (
                "vversionMadeBy/".
                "vversionNeededToExtract/".
                "vbitFlag/".
                "vcompressionMethod/".
                "vlastModFileTime/".
                "vlastModFileDate/".
                "Vcrc/".
                "VcompressedSize/".
                "VuncompressedSize/".
                "vfileNameLength/".
                "vextraFieldLength/".
                "vfileCommentLength/".
                "vdiskNumberStart/".
                "vinternalFileAttributes/".
                "VexternalFileAttributes/".
                "VrelativeHeaderOffset",
                $file->read( 42 ) );

                $this->properties["fileName"] = $file->read( $this->properties["fileNameLength"] );
                $extraField = $file->read( $this->properties["extraFieldLength"] ); // FIXME, extra fields.
                $this->properties["comment"] = $file->read( $this->properties["fileCommentLength"] );

                // Append extra field information.
                $this->setExtraFieldData( $extraField );
        }
        else
        {
            // Some default values:
            $this->properties["versionMadeBy"] = 791;
            $this->properties["versionNeededToExtract"] = 10;
            $this->properties["diskNumberStart"] = 0;
            $this->setComment( "" );
        }
    }

    /**
     * Sets the property $name to $value.
     *
     * @throws ezcBasePropertyNotFoundException if the property does not exist
     * @throws ezcBasePropertyReadOnlyException if the property is read-only
     * @param string $name
     * @param mixed $value
     * @return void
     * @ignore
     */
    public function __set( $name, $value )
    {
        switch ( $name )
        {
            case "versionMadeBy":
            case "versionNeededToExtract":
            case "bitFlag":
            case "compressionMethod":
            case "lastModFileTime":
            case "lastModFileDate":
            case "crc":
            case "compressedSize":
            case "uncompressedSize":
            case "diskNumberStart":
            case "internalFileAttributes":
            case "externalFileAttributes":
            case "fileName":
            case "relativeHeaderOffset":
                $this->properties[$name] = $value;
                break;

            case "comment":
                $this->setComment( $value );
                break;

            case "fileNameLength":
            case "extraFieldLength":
            case "fileCommentLength":
                throw new ezcBasePropertyReadOnlyException( $name );

            default:
                throw new ezcBasePropertyNotFoundException( $name );
        }
    }

    /**
     * Returns the value of the property $name.
     *
     * @throws ezcBasePropertyNotFoundException if the property does not exist.
     * @param string $name
     * @return mixed
     * @ignore
     */
    public function __get( $name )
    {
        switch ( $name )
        {
            case "versionMadeBy":
            case "versionNeededToExtract":
            case "bitFlag":
            case "compressionMethod":
            case "lastModFileTime":
            case "lastModFileDate":
            case "crc":
            case "compressedSize":
            case "uncompressedSize":
            case "diskNumberStart":
            case "internalFileAttributes":
            case "externalFileAttributes":
            case "relativeHeaderOffset":
            case "fileNameLength":
            case "extraFieldLength":
            case "fileCommentLength":
            case "fileName":
            case "comment":
                return $this->properties[$name];

            default:
                throw new ezcBasePropertyNotFoundException( $name );
        }
    }

    /**
     * Sets the comment to string $comment and updates the comment length.
     *
     * @param string $comment
     * @return void
     */
    public function setComment( $comment )
    {
        $this->properties["comment"] = $comment;
        $this->properties["fileCommentLength"] = strlen( $comment );
    }

    /**
     * Sets the type to int $type.
     *
     * The type is a constant from the {@link ezcArchiveEntry}. For example:
     * ezcArchiveEntry::IS_FIFO.
     * The property externalFileAttributes will be changed to reflect the $type.
     *
     * @throws ezcArchiveException
     *         if $type is unknown
     * @param int $type
     * @return void
     */
    public function setType( $type )
    {
        $ext = 0;
        switch ( $type )
        {
            case ezcArchiveEntry::IS_FIFO:
                $ext = ezcArchiveStatMode::S_IFIFO;
                break;

            case ezcArchiveEntry::IS_CHARACTER_DEVICE:
                $ext = ezcArchiveStatMode::S_IFCHR;
                break;

            case ezcArchiveEntry::IS_DIRECTORY:
                $ext = ezcArchiveStatMode::S_IFDIR;
                break;

            case ezcArchiveEntry::IS_BLOCK_DEVICE:
                $ext = ezcArchiveStatMode::S_IFBLK;
                break;

            case ezcArchiveEntry::IS_FILE:
                $ext = ezcArchiveStatMode::S_IFREG;
                break;

            case ezcArchiveEntry::IS_SYMBOLIC_LINK:
                $ext = ezcArchiveStatMode::S_IFLNK;
                break;

            default:
                throw new ezcArchiveException( "Unknown type" );
        }

        if ( !isset( $this->properties["externalFileAttributes"] ) )
        {
            $this->properties["externalFileAttributes"] = 0;
        }

        $ext <<= 16;
        $clear = ( $this->properties["externalFileAttributes"] & ezcArchiveStatMode::S_IFMT << 16 );

        $this->properties["externalFileAttributes"] ^= $clear; // Remove the bits from S_IFMT, because we XOR with self.
        $this->properties["externalFileAttributes"] |= $ext; // And add the ext bits.
    }

    /**
     * Returns the type of the file.
     *
     * The type is read and translated from the externalFileAttributes property.
     *
     * @return int  An ezcArchiveEntry constant.
     */
    public function getType()
    {
        $extAttrib = ( $this->properties["externalFileAttributes"] >> 16 );

        switch ( $extAttrib & ezcArchiveStatMode::S_IFMT )
        {
            case ezcArchiveStatMode::S_IFIFO:
                return ezcArchiveEntry::IS_FIFO;

            case ezcArchiveStatMode::S_IFCHR:
                return ezcArchiveEntry::IS_CHARACTER_DEVICE;

            case ezcArchiveStatMode::S_IFDIR:
                return ezcArchiveEntry::IS_DIRECTORY;

            case ezcArchiveStatMode::S_IFBLK:
                return ezcArchiveEntry::IS_BLOCK_DEVICE;

            case ezcArchiveStatMode::S_IFREG:
                return ezcArchiveEntry::IS_FILE;

            case ezcArchiveStatMode::S_IFLNK:
                return ezcArchiveEntry::IS_SYMBOLIC_LINK;

            default:
                if ( substr( $this->properties["fileName"], -1 ) == "/" )
                {
                    return ezcArchiveEntry::IS_DIRECTORY;
                }
                else
                {
                    return ezcArchiveEntry::IS_FILE;
                }
        }
    }

    /**
     * Returns the permissions (as a decimal number) of the file.
     *
     * The type is read and translated from the externalFileAttributes property.
     *
     * @return int
     */
    public function getPermissions()
    {
        $extAttrib = ( $this->properties["externalFileAttributes"] >> 16 );

        return decoct( $extAttrib & ezcArchiveStatMode::S_PERM_MASK );
    }

    /**
     * Sets the permissions (as a decimal number) of the file to int $permissions.
     *
     * The $permissions expects an decimal number.
     *
     * The externalFileAttributes property will be changed.
     *
     * @param int $permissions
     */
    public function setPermissions( $permissions )
    {
        $perm = octdec( $permissions );
        $perm <<= 16;

        if ( !isset( $this->properties["externalFileAttributes"] ) )
        {
            $this->properties["externalFileAttributes"] = 0;
        }

        $clear = ( $this->properties["externalFileAttributes"] & ezcArchiveStatMode::S_PERM_MASK << 16 );
        $this->properties["externalFileAttributes"] ^= $clear; // Remove the bits from S_PERM_MASK, because we XOR with self.
        $this->properties["externalFileAttributes"] |= $perm; // And add the perm bits.
    }

    /**
     * Updates the given ezcArchiveFileStructure $struct with the values from this header.
     *
     * If bool $override is false, this method will not overwrite the values from the ezcArchiveFileStructure $struct.
     * The values that can be set in the archiveFileStructure are: path, mode, type, size.
     *
     * @param ezcArchiveFileStructure &$struct
     * @param bool $override
     * @return void
     */
    public function setArchiveFileStructure( ezcArchiveFileStructure &$struct, $override = false )
    {
        if ( !isset( $struct->path ) || $override )
        {
            $struct->path = $this->fileName;
        }

        if ( !isset( $struct->mode ) || $override )
        {
            $struct->mode = ( $this->getPermissions() == 0 ? false : $this->getPermissions() );
        }

        if ( !isset( $struct->type ) || $override )
        {
            $struct->type = $this->getType();
        }

        if ( !isset( $struct->size ) || $override )
        {
            $struct->size = $this->uncompressedSize;
        }
    }

    /**
     * Returns the total size of this header.
     *
     * @return int
     */
    public function getHeaderSize()
    {
        return 46 + $this->properties["fileNameLength"] + $this->properties["extraFieldLength"] + $this->properties["fileCommentLength"];
    }

    /**
     * Sets this header with the values from the {@link ezcArchiveLocalFileHeader}.
     *
     * The properties that are set: versionNeededToExtract, bitFlag, compressionMethod,
     * lastModFileTime, lastModFileDate, crc, compressedSize, uncompressedSize, fileNameLength,
     * and fileName.
     *
     * @param ezcArchiveLocalFileHeader $localFileHeader
     * @return void
     */
    public function setHeaderFromLocalFileHeader( ezcArchiveLocalFileHeader $localFileHeader )
    {
        $this->properties["versionNeededToExtract"] = $localFileHeader->version;
        $this->properties["bitFlag"] = $localFileHeader->bitFlag;
        $this->properties["compressionMethod"] = $localFileHeader->compressionMethod;
        $this->properties["lastModFileTime"] = $localFileHeader->lastModFileTime;
        $this->properties["lastModFileDate"] = $localFileHeader->lastModFileDate;
        $this->properties["crc"] = $localFileHeader->crc;
        $this->properties["compressedSize"] = $localFileHeader->compressedSize;
        $this->properties["uncompressedSize"] = $localFileHeader->uncompressedSize;
        $this->properties["fileNameLength"] = $localFileHeader->fileNameLength;
        $this->properties["fileName"] = $localFileHeader->fileName;
    }

    /**
     * Sets this header with the values from the ezcArchiveEntry $entry.
     *
     * The values that are possible to set from the ezcArchiveEntry $entry are set in this header.
     * The properties that change are: internalFileAttributes, relativeHeaderOffset, type, and mtime.
     *
     * @param ezcArchiveEntry $entry
     * @return void
     */
    public function setHeaderFromArchiveEntry( ezcArchiveEntry $entry )
    {
        $this->properties["internalFileAttributes"] = 0;

        $this->setType( $entry->getType() );
        $this->setPermissions( $entry->getPermissions() );

        $this->properties["relativeHeaderOffset"] = 0;
        $this->properties["mtime"] = $entry->getModificationTime();
    }

    /**
     * Serializes this header and appends it to the given ezcArchiveCharacterFile $archiveFile.
     *
     * @param ezcArchiveCharacterFile $archiveFile
     * @return void
     */
    public function writeEncodedHeader( $archiveFile )
    {
        $this->properties["extraFieldLength" ] = 13; // 9 + 4.

        $enc = pack( "VvvvvvvVVVvvvvvVV",
            self::magic,           // V magic number
            $this->versionMadeBy,  // v
            $this->versionNeededToExtract,  // v
            $this->bitFlag, // v
            $this->compressionMethod, // v
            $this->lastModFileTime, // v
            $this->lastModFileDate, // v
            $this->crc, // V
            $this->compressedSize, // V
            $this->uncompressedSize, // V
            $this->fileNameLength, // v
            $this->extraFieldLength, // v extra data.
            $this->fileCommentLength , // v Comment
            $this->diskNumberStart ,  // v disknumber start
            $this->internalFileAttributes,  // v Internal attribute
            $this->externalFileAttributes,  // V external attributes
            $this->relativeHeaderOffset       // V relative header offset?
         );

         $time = pack( "vvcV", self::EF_TIME, 5, 1, $this->mtime ); // fixme atime?
         $unix2 = pack( "vv", self::EF_IZUNIX2, 0 ); // Add empty unix2 stamp.

         $archiveFile->write( $enc . $this->fileName . $time . $unix2 . $this->comment );
    }

    /**
     * Returns true if the given string $string matches with the current signature.
     *
     * @param string $string
     * @return bool
     */
    public static function isSignature( $string )
    {
        return $string == pack( "V", self::magic );
    }
}
?>
PK��ZK���`c`c&ezc/Archive/zip/headers/local_file.phpnu�[���<?php
/**
 * File containing the ezcArchiveLocalFileHeader class.
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @access private
 */

/**
 * The ezcArchiveLocalFileHeader class represents the Zip local header.
 *
 * ezcArchiveLocalFileHeader can read the header from an ezcArchiveCharacterFile or ezcArchiveEntry.
 *
 * The values from the headers are directly accessible via the class properties, and allows
 * reading and writing to specific header values.
 *
 * The entire header can be appended to an ezcArchiveCharacterFile again or written to an ezcArchiveFileStructure.
 * Information may get lost, though.
 *
 * The overall .ZIP file format[1] :
 *
 * <pre>
 *   [local file header 1]
 *   [file data 1]
 *   [data descriptor 1]
 *   .
 *   .
 *   [local file header n]
 *   [file data n]
 *   [data descriptor n]
 *   [central directory]
 *   [end of central directory record]
 * </pre>
 *
 * The Local File Header has the following structure:
 *
 * <pre>
 * + ---+--------+------------+-------------------+-------------------------------+
 * | ID | Offset | Field size | Property          |  Description                  |
 * +----+--------+------------+-------------------+-------------------------------+
 * |    |  0     | 4          | -                 | Local file header signature   |
 * |    |  4     | 2          | version           | Version needed to extract     |
 * |    |  6     | 2          | bitFlag           | General purpose bit flag      |
 * |    |  8     | 2          | compressionMethod | Compression method            |
 * |    |  10    | 2          | lastModFileTime   | Last modification file time   |
 * |    |  12    | 2          | lastModFileDate   | Last modification file date   |
 * |    |  14    | 4          | crc               | crc-32                        |
 * |    |  18    | 4          | compressedSize    | compressed size               |
 * |    |  22    | 4          | uncompressedSize  | uncompressed size             |
 * | X  |  26    | 2          | fileNameLength    | file name length              |
 * | Y  |  28    | 2          | extraFieldLength  | extra field length            |
 * |    |  30    | X          | fileName          | file name                     |
 * |    |  30+X  | Y          | -                 | extra field                   |
 * +----+--------+------------+-------------------+-------------------------------+
 * </pre>
 *
 * The columns of the table are:
 * - ID gives a label to a specific field or row in the table.
 * - Offset describes the start position of a header field.
 * - Field size describes the size of the field in bytes.
 * - Property is the name of the property that will be set by the header field.
 * - Description explains what this field describes.
 *
 * The local file signature cannot be changed and is set in the constant {@link self::magic}.
 *
 * The extra fields that are implemented are:
 * - Info-Zip Unix field (old).
 * - Info-Zip Unix field (new).
 * - Universal timestamp.
 *
 * Info-Zip Unix field (old):
 * <pre>
 * +--------+------------+------------------------------------+
 * | Offset | Field size |  Description                       |
 * +--------+------------+------------------------------------+
 * |  0     | 2          | Header ID (0x5855)                 |
 * |  2     | 2          | Data size: Full size = 12          |
 * |  4     | 4          | Last Access Time                   |
 * |  8     | 4          | Last Modification Time             |
 * |  12    | 2          | User ID  (Optional if size < 12 )  |
 * |  14    | 2          | Group ID (Optional if size < 12 )  |
 * +--------+------------+------------------------------------+
 * </pre>
 *
 * Info-Zip Unix field (new):
 * <pre>
 * +--------+------------+--------------------+
 * | Offset | Field size |  Description       |
 * +--------+------------+--------------------+
 * |  0     | 2          | Header ID (0x7855) |
 * |  2     | 2          | Data size.         |
 * |  4     | 2          | User ID            |
 * |  6     | 2          | Group ID           |
 * +--------+------------+--------------------+
 * </pre>
 *
 * Universal timestamp:
 * <pre>
 * +--------+------------+-------------------------+
 * | Offset | Field size |  Description            |
 * +--------+------------+-------------------------+
 * |  0     | 2          | Header ID (0x5455)      |
 * |  2     | 2          | Data size.              |
 * |  4     | 1          | Info bits (flags)       |
 * |  5     | 4          | Last Modification Time  |
 * |  9     | 4          | Last Access Time        |
 * |  13    | 4          | Creation Time           |
 * +--------+------------+-------------------------+
 * </pre>
 *
 * Info bits indicate which fields are set:
 * - bit 0, if set then the modification time is present.
 * - bit 1, if set then the access time is present.
 * - bit 2, if set then the creation time is present.
 *
 * These info bits are ONLY valid for the local file header. The
 * central header has the same Universal Timestamp, but reflects
 * the bits from the local file header!
 *
 *
 * See PKWare documentation and InfoZip extra field documentation for more information.
 *
 *
 * [1] PKWARE .ZIP file format specification:
 * <pre>
 * File:    APPNOTE.TXT - .ZIP File Format Specification
 * Version: 4.5
 * Revised: 11/01/2001
 * Copyright (c) 1989 - 2001 PKWARE Inc., All Rights Reserved.
 * </pre>
 *
 * [2] InfoZip distribution contains the file: proginfo/extra.fld
 *
 * @package Archive
 * @version 1.4.1
 * @access private
 */
class ezcArchiveLocalFileHeader
{
    /**
     * Defines the signature of this header.
     */
    const magic = 0x04034b50;

    /**
     * Extra field definition.
     *
     * UNIX Extra Field ID ("UX").
     */
    const EF_IZUNIX  = 0x5855;

    /**
     * Extra field definition.
     *
     * Info-ZIP's new Unix( "Ux" ).
     */
    const EF_IZUNIX2 = 0x7855;

    /**
     * Extra field definition.
     *
     * Universal timestamp( "UT" ).
     */
    const EF_TIME    = 0x5455;

    /**
     * Minimal UT field contains Flags byte
     */
    const EB_UT_MINLEN = 1;

    /**
     * Byte offset of Flags field
     */
    const EB_UT_FLAGS  = 0;

    /**
     * Byte offset of 1st time value
     */
    const EB_UT_TIME1  = 1;

    /**
     * mtime present
     */
    const EB_UT_FL_MTIME = 1;

    /**
     * atime present
     */
    const EB_UT_FL_ATIME = 2;

    /**
     * ctime present
     */
    const EB_UT_FL_CTIME = 4;

    /**
     * UT field length.
     */
    const EB_UT_FL_LEN = 4;

    /**
     * Minimal "UX" field contains atime, mtime
     */
    const EB_UX_MINLEN = 8;

    /**
     * Offset of atime in "UX" extra field data
     */
    const EB_UX_ATIME  = 0;

    /**
     * Offset of mtime in "UX" extra field data
     */
    const EB_UX_MTIME  = 4;

    /**
     * Full "UX" field ( atime, mtime, uid, gid )
     */
    const EB_UX_FULLSIZE = 12;

    /**
     * Byte offset of UID in "UX" field data
     */
    const EB_UX_UID = 8;

    /**
     * Byte offset of GID in "UX" field data
     */
    const EB_UX_GID = 10;

    /**
     * Minimal Ux field contains UID/GID
     */
    const EB_UX2_MINLEN = 4;

    /**
     * Byte offset of UID in "Ux" field data
     */
    const EB_UX2_UID = 0;

    /**
     * Byte offset of GID in "Ux" field data
     */
    const EB_UX2_GID = 2;

    /**
     * Byte offset of valid in "Ux" field data
     */
    const EB_UX2_VALID =  256;

    /**
     * Holds the properties of this class.
     *
     * @var array(string=>mixed)
     */
    protected $properties = array();

    /**
     * Holds the user ID and is false if not set.
     *
     * @var int
     */
    protected $userId = false;

    /**
     * Holds the group ID and is false if not set.
     *
     * @var int
     */
    protected $groupId = false;

    /**
     * Holds the modification time as a timestamp and is false if not set.
     *
     * @var int
     */
    protected $mtime = false;

    /**
     * Holds the modification time as a timestamp and is false if not set.
     *
     * @var int
     */
    protected $atime = false;

    /**
     * Holds the creation time as a timestamp and is false if not set.
     *
     * @var int
     */
    protected $ctime = false;

    /**
     * Creates and initializes a new header.
     *
     * If the ezcArchiveCharacterFile $file is null then the header will be empty.
     * When an ezcArchiveCharacterFile is given, the file position should be directly after the
     * signature of the header. This header will be read from the file and initialized in this class.
     *
     * @param ezcArchiveCharacterFile $file
     */
    public function __construct( ezcArchiveCharacterFile $file = null, ezcArchiveCentralDirectoryHeader $centralHeader = null )
    {
        // Offset | Field size |  Description
        // ----------------------------------
        //  0     | 4          | Local file header signature ( 0x04034b50 ).
        //  4     | 2          | Version needed to extract.
        //  6     | 2          | General purpose bit flag.
        //  8     | 2          | Compression method.
        //  10    | 2          | Last mod file time.
        //  12    | 2          | Last mod file date.
        //  14    | 4          | Crc-32.
        //  18    | 4          | Compressed size.
        //  22    | 4          | Uncompressed size.
        //  26    | 2          | File name length.
        //  28    | 2          | Extra field length.

        if ( !is_null( $file ) )
        {
            $this->properties = unpack (
                "vversion/".
                "vbitFlag/".
                "vcompressionMethod/".
                "vlastModFileTime/".
                "vlastModFileDate/".
                "Vcrc/".
                "VcompressedSize/".
                "VuncompressedSize/".
                "vfileNameLength/".
                "vextraFieldLength",
                $file->read( 26 ) );

            $this->properties["fileName"] = $file->read( $this->properties["fileNameLength"] );
            $extraField = $file->read( $this->properties["extraFieldLength"] );

            // Append extra field information.
            $this->setExtraFieldData( $extraField );

            // Fix the local file headers from the central header, in case crc,
            // compressed size and original size are not set. This is needed
            // for Open Office documents at least.
            if ( $centralHeader && $this->properties['compressedSize'] === 0 && $this->properties['uncompressedSize'] === 0 )
            {
                $this->properties['compressedSize'] = $centralHeader->compressedSize;
                $this->properties['uncompressedSize'] = $centralHeader->uncompressedSize;
                $this->properties['crc'] = $centralHeader->crc;
            }

            // Skip the file.
            $file->seek( $this->compressedSize, SEEK_CUR );
        }
    }

    /**
     * Serializes this header and appends it to the given ezcArchiveCharacterFile $archiveFile.
     *
     * @param ezcArchiveCharacterFile $archiveFile
     * @return void
     */
    public function writeEncodedHeader( $archiveFile )
    {
        $this->properties["extraFieldLength" ] = 21; // FIXME.

        $enc = pack( "VvvvvvVVVvv",
            self::magic,
            $this->properties["version"],
            $this->properties["bitFlag"],
            $this->properties["compressionMethod"],
            $this->properties["lastModFileTime"],
            $this->properties["lastModFileDate"],
            $this->properties["crc"],
            $this->properties["compressedSize"],
            $this->properties["uncompressedSize"],
            $this->properties["fileNameLength"],
            $this->properties["extraFieldLength"] );

        $time = pack( "vvcVV", self::EF_TIME, 9, 3, $this->mtime, $this->atime ); // set accesss time to modification time.
        $unix2 = pack( "vvvv", self::EF_IZUNIX2, 4, $this->userId, $this->groupId );

        $archiveFile->write( $enc . $this->fileName . $time . $unix2 );
    }

    /**
     * Sets the property $name to $value.
     *
     * @throws ezcBasePropertyNotFoundException if the property does not exist
     * @throws ezcBasePropertyReadOnlyException if the property is read-only
     * @param string $name
     * @param mixed $value
     * @return void
     * @ignore
     */
    public function __set( $name, $value )
    {
        switch ( $name )
        {
             case "version":
             case "bitFlag":
             case "compressionMethod":
             case "crc":
             case "compressedSize":
             case "uncompressedSize":
             case "extraFieldLength":
                $this->properties[$name] = $value;
                break;

             case "lastModFileTime":
             case "lastModFileDate":
             case "fileNameLength":
                throw new ezcBasePropertyReadOnlyException( $name );

             default:
                throw new ezcBasePropertyNotFoundException( $name );
        }
    }

    /**
     * Returns the value of the property $name.
     *
     * @throws ezcBasePropertyNotFoundException if the property does not exist.
     * @param string $name
     * @return mixed
     * @ignore
     */
    public function __get( $name )
    {
        switch ( $name )
        {
            case "version":
            case "bitFlag":
            case "compressionMethod":
            case "lastModFileTime":
            case "lastModFileDate":
            case "crc":
            case "compressedSize":
            case "uncompressedSize":
            case "extraFieldLength":
            case "fileNameLength":
            case "fileName":
                return $this->properties[ $name ];

            default:
                throw new ezcBasePropertyNotFoundException( $name );
        }
    }

    /**
     * Returns the modification timestamp.
     *
     * The timestamp from the extra fields is returned if it is available.
     * If it cannot be found, the ZIP time is converted to a timestamp.
     *
     * @return int
     */
    public function getModificationTime()
    {
        return ( $this->mtime ? $this->mtime : self::dosFormatToTimestamp( array( $this->lastModFileTime, $this->lastModFileDate ) ) );
    }

    /**
     * Sets the modification time to the int $timestamp.
     *
     * The properties lastModFileTime and lastModFileDate properties will be set.
     *
     * @param int $timestamp
     * @return void
     */
    public function setModificationTime( $timestamp )
    {
        $this->mtime = $timestamp;
        list( $this->properties["lastModFileTime"], $this->properties["lastModFileDate"] ) = self::timestampToDosFormat( $timestamp );
    }

    /**
     * Returns an two element array with, respectively, the dos time and dos date, which are converted from
     * the given int $timestamp.
     *
     * The DOS time and date format are described here: {@link http://www.vsft.com/hal/dostime.htm}.
     *
     * @see http://www.vsft.com/hal/dostime.htm
     *
     * @param int $timestamp
     * @return array(int)
     */
    public static function timestampToDosFormat( $timestamp )
    {
        $time = getdate( $timestamp );

        $dosTime = ( $time["hours"]  & 31 ); // Hours. Bit: 11 .. 15
        $dosTime <<= 6;
        $dosTime |= ( $time["minutes"] & 63 ); // Minutes.
        $dosTime <<= 5;
        $dosTime |= ( ( int ) ( $time["seconds"] / 2 ) & 31 );  // seconds.

        $dosDate = ( $time["year"] - 1980 ) & 127;  // Year.
        $dosDate <<= 4;
        $dosDate |= ( $time["mon"] & 15 ); // month.
        $dosDate <<= 5;
        $dosDate |= ( $time["mday"] & 31 ); // day.

        return array( $dosTime, $dosDate );
    }

    /**
     * Returns the timestamp which is converted from an array with, respectively, the dos time and dos date.
     *
     * Expects an array with two elements.
     *
     * The DOS time and date format are described here: {@link http://www.vsft.com/hal/dostime.htm}.
     *
     * @see http://www.vsft.com/hal/dostime.htm
     *
     * @param array(int) $array
     * @return int
     */
    public static function dosFormatToTimestamp( array $array )
    {
        $dosTime = $array[0];

        $seconds = ( ($dosTime ) & 31 ) * 2 ;  // Bit  0 .. 4
        $minutes = ( $dosTime >>  5 ) & 63 ;          // Bit  5 .. 10
        $hours = ( $dosTime >> 11 ) & 31;               // Bit 11 .. 15

        $dosDate = $array[1];
        $day =  ( ( $dosDate ) & 31 );          // Bit  0 .. 4
        $month = ( $dosDate >>  5 ) & 15 ;            // Bit  5 .. 8
        $year = ( ( $dosDate >> 9 ) & 127 ) + 1980;     // Bit  9 .. 15

        return mktime( $hours, $minutes, $seconds, $month, $day, $year );
    }

    /**
     * Sets the filename in the header.
     *
     * The properties fileName and file length are changed.
     *
     * @param string $name
     */
    public function setFileName( $name )
    {
        $this->properties["fileName"] = $name;
        $this->properties["fileNameLength"] = strlen( $name );
    }

    /**
     * Sets the compression.
     *
     * @param int $compressionMethod
     * @param int $compressedSize
     * @return void
     */
    public function setCompression( $compressionMethod, $compressedSize )
    {
        // Fixme, for now only decompressed.
        $this->compressionMethod = $compressionMethod;
        $this->compressedSize = $compressedSize;

    }

    /**
     * Updates the given ezcArchiveFileStructure $struct with the values from this header.
     *
     * If bool $override is false, this method will not overwrite the values from the ezcArchiveFileStructure $struct.
     * The values that can be set in the archiveFileStructure are: path, gid, uid, mtime, and size.
     *
     * @param ezcArchiveFileStructure &$struct
     * @param bool $override
     * @return void
     */
    public function setArchiveFileStructure( ezcArchiveFileStructure &$struct, $override = false )
    {
        if ( !isset( $struct->path ) || $override )
        {
            $struct->path = $this->fileName;
        }

        if ( !isset( $struct->size ) || $override )
        {
            $struct->size = $this->uncompressedSize;
        }

        if ( $this->groupId && ( !isset( $struct->size )  || $override ) )
        {
            $struct->gid   = $this->groupId;
        }

        if ( $this->userId &&  ( !isset( $struct->size )  || $override ) )
        {
            $struct->uid   = $this->userId;
        }

        if ( $this->mtime &&   ( !isset( $struct->mtime ) || $override ) )
        {
            $struct->mtime = $this->mtime;
        }

        if ( $this->atime &&   ( !isset( $struct->atime ) || $override ) )
        {
            $struct->atime = $this->atime;
        }
    }

    /**
     * Sets this header with the values from the ezcArchiveEntry $entry.
     *
     * The values that are possible to set from the ezcArchiveEntry $entry are set in this header.
     *
     * @param ezcArchiveEntry $entry
     * @return void
     */
    public function setHeaderFromArchiveEntry( ezcArchiveEntry $entry )
    {
        $this->version = 10; // FIXME
        $this->bitFlag = 0; // FIXME

        $this->atime = $entry->getAccessTime();

        $this->groupId = $entry->getGroupId();
        $this->userId = $entry->getUserId();

        $this->setModificationTime( $entry->getModificationTime() );

        if ( $entry->isSymLink() )
        {
            $this->uncompressedSize = strlen( $entry->getLink() );
            $this->crc = ezcArchiveChecksums::getCrc32FromString( $entry->getLink() );
        }
        else
        {
            $this->uncompressedSize = $entry->getSize();
            $this->crc = ezcArchiveChecksums::getCrc32FromFile( $entry->getPath() );
        }

        $this->setFileName( $entry->getPath( false ) );
    }

    /**
     * Returns the total size of this header.
     *
     * @return int
     */
    public function getHeaderSize()
    {
        return 30 + $this->properties["fileNameLength"] + $this->properties["extraFieldLength"];
    }

    /**
     * Decodes and sets the extra header properties from the string $data.
     *
     * @param string $data
     * @return void
     */
    protected function setExtraFieldData( $data )
    {
        $raw = array();

        $offset = 0;
        $dataLength = strlen( $data );

        while ( $offset < $dataLength )
        {
            // Read header.
            $dec = unpack( "vid/vlength", substr( $data, $offset, 4 ) );
            $offset += 4;

            switch ( $dec["id"] )
            {
                case self::EF_IZUNIX2:
                    $raw[ "EF_IZUNIX2" ] = $this->getNewInfoZipExtraField( substr( $data, $offset, $dec["length"] ), $dec["length"] );
                    break;

                case self::EF_IZUNIX:
                    $raw[ "EF_IZUNIX" ] = $this->getOldInfoZipExtraField( substr( $data, $offset, $dec["length"] ), $dec["length"] );
                    break;

                case self::EF_TIME:
                    $raw[ "EF_TIME" ] = $this->getUniversalTimestampField( substr( $data, $offset, $dec["length"] ), $dec["length"] );
                    break;
            }

            $offset += $dec["length"];
        }

        $result = array();

        // The order is important.
        if ( isset( $raw["EF_TIME"]["mtime"] ) )
        {
            $this->mtime = $raw["EF_TIME"]["mtime"];
        }

        if ( isset( $raw["EF_TIME"]["atime"] ) )
        {
            $this->atime = $raw["EF_TIME"]["atime"];
        }

        if ( isset( $raw["EF_TIME"]["ctime"] ) )
        {
            $this->ctime = $raw["EF_TIME"]["ctime"];
        }

        if ( isset( $raw["EF_IZUNIX"]["mtime"] ) )
        {
            $this->mtime = $raw["EF_IZUNIX"]["mtime"];
        }

        if ( isset( $raw["EF_IZUNIX"]["atime"] ) )
        {
            $this->atime = $raw["EF_IZUNIX"]["atime"];
        }

        if ( isset( $raw["EF_IZUNIX"]["gid"] ) )
        {
            $this->groupId = $raw["EF_IZUNIX"]["gid"];
        }

        if ( isset( $raw["EF_IZUNIX"]["uid"] ) )
        {
            $this->userId = $raw["EF_IZUNIX"]["uid"];
        }

        if ( isset( $raw["EF_IZUNIX2"]["gid"] ) )
        {
            $this->groupId = $raw["EF_IZUNIX2"]["gid"];
        }

        if ( isset( $raw["EF_IZUNIX2"]["uid"] ) )
        {
            $this->userId = $raw["EF_IZUNIX2"]["uid"];
        }

        return $result;
    }

    /**
     * Returns an array with the decoded 'new Info-Zip' data.
     *
     * @param string $field
     * @param int $length
     * @return array(string)
     */
    protected function getNewInfoZipExtraField( $field, $length )
    {
        $localOffset = 0;

        if ( $length >= self::EB_UX2_MINLEN )
        {
            return unpack( "vuid/vgid", substr( $field, 0, self::EB_UX2_MINLEN ) );
        }

        return array();
    }

    /**
     * Returns an array with the decoded 'old Info-Zip' data.
     *
     * @param string $field
     * @param int $length
     * @return array(string)
     */
    protected function getOldInfoZipExtraField( $field, $length )
    {
        if ( $length >= self::EB_UX_FULLSIZE )
        {
            return unpack( "Vatime/Vmtime/vuid/vgid", substr( $field, 0, self::EB_UX_FULLSIZE ) );
        }
        else if ( $length >= self::EB_UX_MINLEN )
        {
            return unpack( "Vatime/Vmtime", substr( $field, 0, self::EB_UX_MINLEN ) );
        }

        return array();
    }

    /**
     * Returns an array with the decoded 'universal timestamp' data.
     *
     * @param string $field
     * @param int $length
     * @return array(string)
     */
    protected function getUniversalTimestampField( $field, $length )
    {
        $localOffset = 0;
        $result = array();

        if ( $length >= self::EB_UT_MINLEN )
        {
            $f = unpack( "cflags", substr( $field, $localOffset, 1 ) );
            $length--; // Flag takes one byte.

            if ( ( $f["flags"] & self::EB_UT_FL_MTIME ) && $length >= 4 )
            {
                $result = array_merge( $result, unpack( "Vmtime", substr( $field, $localOffset + self::EB_UT_MINLEN + ( self::EB_UT_FL_LEN * 0 ), self::EB_UT_FL_LEN ) ) );
                $length -= 4;
            }

            if ( $f["flags"] & self::EB_UT_FL_ATIME  && $length >= 4 )
            {
                $result = array_merge( $result, unpack( "Vatime", substr( $field, $localOffset + self::EB_UT_MINLEN + ( self::EB_UT_FL_LEN * 1 ), self::EB_UT_FL_LEN ) ) );
                $length -= 4;
            }

            if ( $f["flags"] & self::EB_UT_FL_CTIME && $length >= 4 )
            {
                $result = array_merge( $result, unpack( "Vctime", substr( $field, $localOffset + self::EB_UT_MINLEN + ( self::EB_UT_FL_LEN * 2 ), self::EB_UT_FL_LEN ) ) );
                $length -= 4;
            }
        }

        return $result;
    }

    /**
     * Returns true if the given string $string matches with the current signature.
     *
     * @param string $string
     * @return bool
     */
    public static function isSignature( $string )
    {
        return $string == pack( "V", self::magic );
    }
}
?>
PK��Z�
�,�#�#1ezc/Archive/zip/headers/central_directory_end.phpnu�[���<?php
/**
 * File containing the ezcArchiveCentralDirectoryHeader class.
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @access private
 */

/**
 * The ezcArchiveCentralDirectoryEndHeader class represents the Zip central directory end header.
 *
 * ezcArchiveCentralDirectoryEndHeader can read the header from an ezcArchiveCharacterFile.
 *
 * The values from the headers are directly accessible via the class properties, and allows
 * reading and writing to specific header values.
 *
 * The entire header can be appended to an ezcArchiveCharacterFile again.
 *
 * The central directory end header is the last header of the ZIP archive. Some algorithms
 * search back to this header in order to find the other headers. The variable comment length
 * makes it tricky.
 *
 * The Central Directory End Header has the following structure:
 *
 * <pre>
 * + ---+---------+------------+------------------------------------+-------------------------------------------------------------------------------+
 * | ID | Offset  | Field size | Property                           |  Description                                                                  |
 * +----+---------+------------+------------------------------------+-------------------------------------------------------------------------------+
 * |    |  0      | 4          | -                                  | Central directory header signature                                            |
 * |    |  4      | 2          | diskNumber                         | nr of this disk                                                               |
 * |    |  6      | 2          | centralDirectoryDisk               | number of the disk with the start of the central directory                    |
 * |    |  8      | 2          | totalCentralDirectoryEntriesOnDisk | total number of entries in the central directory on this disk                 |
 * |    |  10     | 2          | totalCentralDirectoryEntries       | total number of entries in the central directory                              |
 * |    |  12     | 4          | centralDirectorySize               | size of the central directory                                                 |
 * |    |  16     | 4          | centralDirectoryStart              | offset of start of central directory with respect to the starting disk number |
 * | X: |  20     | 2          | commentLength                      | .ZIP file comment length                                                      |
 * |    |  22     | X          | comment                            | .ZIP file comment                                                             |
 * +----+---------+------------+------------------------------------+-------------------------------------------------------------------------------+
 * </pre>
 *
 *
 * The columns of the table are:
 * - ID gives a label to a specific field or row in the table.
 * - Offset describes the start position of a header field.
 * - Field size describes the size of the field in bytes.
 * - Property is the name of the property that will be set by the header field.
 * - Description explains what this field describes.
 *
 *
 * @package Archive
 * @version 1.4.1
 * @access private
 */
class ezcArchiveCentralDirectoryEndHeader
{
    /**
     * Defines the signature of this header.
     */
    const magic = 0x06054b50;

    /**
     * Holds the properties of this class.
     *
     * @var array(string=>mixed)
     */
    private $properties = array();

    /**
     * Creates and initializes a new header.
     *
     * If the ezcArchiveCharacterFile $file is null then the header will be empty.
     * When an ezcArchiveCharacterFile is given, the file position should be directly after the
     * signature of the header. This header will be read from the file and initialized in this class.
     *
     * @param ezcArchiveCharacterFile $file
     */
    public function __construct( ezcArchiveCharacterFile $file = null )
    {
        if ( !is_null( $file ) )
        {
            $this->properties = unpack (
                "vdiskNumber/".
                "vcentralDirectoryDisk/".
                "vtotalCentralDirectoryEntriesOnDisk/".
                "vtotalCentralDirectoryEntries/".
                "VcentralDirectorySize/".
                "VcentralDirectoryStart/".
                "vcommentLength",
                $file->read( 18 ) );

                $this->properties["comment"] = $file->read( $this->properties["commentLength"] );
        }
        else
        {
            $this->properties["diskNumber"] = 0;
            $this->properties["centralDirectoryDisk"] = 0;
            $this->properties["totalCentralDirectoryEntries"] = 0;
            $this->properties["totalCentralDirectoryEntriesOnDisk"] = 0;
            $this->properties["totalCentralDirectorySize"] = 0;
            $this->properties["totalCentralDirectoryStart"] = 0;

            $this->setComment( "" );
        }
    }

    /**
     * Sets the property $name to $value.
     *
     * @throws ezcBasePropertyNotFoundException if the property does not exist.
     * @throws ezcBasePropertyReadOnlyException if the property is read-only
     * @param string $name
     * @param mixed $value
     * @return void
     * @ignore
     */
    public function __set( $name, $value )
    {
        switch ( $name )
        {
            case "diskNumber":
            case "centralDirectoryDisk":
            case "totalCentralDirectoryEntriesOnDisk":
                throw new ezcBasePropertyReadOnlyException( $name );

            case "totalCentralDirectoryEntries":
                $this->setTotalDirectoryEntries( $value );
                break;

            case "centralDirectorySize":
            case "centralDirectoryStart":
                $this->properties[$name] = $value;
                break;

            case "commentLength":
                throw new ezcBasePropertyReadOnlyException( $name );

            case "comment":
                $this->setComment( $value );
                break;

            default:
                throw new ezcBasePropertyNotFoundException( $name );
        }
    }

    /**
     * Returns the value of the property $name.
     *
     * @throws ezcBasePropertyNotFoundException if the property does not exist.
     * @param string $name
     * @return mixed
     * @ignore
     */
    public function __get( $name )
    {
        switch ( $name )
        {
            case "diskNumber":
            case "centralDirectoryDisk":
            case "totalCentralDirectoryEntriesOnDisk":
            case "totalCentralDirectoryEntries":
            case "centralDirectorySize":
            case "centralDirectoryStart":
            case "commentLength":
            case "comment":
                return $this->properties[$name];

            default:
                throw new ezcBasePropertyNotFoundException( $name );
        }
    }

    /**
     * Sets the comment and comment length in the header from the string $comment.
     *
     * @param string $comment
     * @return void
     */
    public function setComment( $comment )
    {
        $this->properties["comment"] = $comment;
        $this->properties["commentLength"] = strlen( $comment );
    }

    /**
     * Sets the total directory entries to the int $numberOfEntries.
     *
     * The properties: diskNumber and centralDirectory will be set to 0.
     * The properties: totalCentralDirectoryEntriesOnDisk and totalCentralDirectoryEntries are set to the $numberOfEntries.
     *
     * @param int $numberOfEntries
     * @return void
     */
    public function setTotalDirectoryEntries( $numberOfEntries )
    {
        $this->properties["diskNumber"] = 0;
        $this->properties["centralDirectoryDisk"] = 0;
        $this->properties["totalCentralDirectoryEntriesOnDisk"] = $numberOfEntries;
        $this->properties["totalCentralDirectoryEntries"] = $numberOfEntries;
    }

    /**
     * Serializes this header and appends it to the given ezcArchiveCharacterFile $archiveFile.
     *
     * @param ezcArchiveCharacterFile $archiveFile
     * @return void
     */
    public function writeEncodedHeader( $archiveFile )
    {
        $enc = pack ( "VvvvvVVv",
            self::magic,
            $this->properties["diskNumber"],
            $this->properties["centralDirectoryDisk"],
            $this->properties["totalCentralDirectoryEntriesOnDisk"],
            $this->properties["totalCentralDirectoryEntries"],
            $this->properties["centralDirectorySize"],
            $this->properties["centralDirectoryStart"],
            $this->properties["commentLength"] );

        $archiveFile->write( $enc . $this->properties["comment"] );
    }

    /**
     * Returns true if the given string $string matches with the current signature.
     *
     * @param string $string
     * @return void
     */
    public static function isSignature( $string )
    {
        return $string == pack( "V", self::magic );
    }
}
?>
PK��ZXA�V�Vezc/Archive/zip/zip.phpnu�[���<?php
/**
 * File containing the ezcArchiveZip class.
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * The ezcArchiveZip class implements the Zip archive format.
 *
 * ezcArchiveZip is a subclass from {@link ezcArchive} that provides the common interface.
 * Zip algorithm specific methods are implemented in this class.
 *
 * ezcArchiveZip tries on creation to read the entire archive. Every {@link ezcArchiveEntry}
 * will be appended to the {@link ezcArchive::$entries} array. ({@link ezcArchiveTarV7} archive format
 * reads only an entry when needed the first time.)
 *
 * All the archive entries are read, because we need to find the {@link ezcArchiveCentralDirectoryHeader central directory}
 * that contains extra file information. Some other Zip implementations search back from the end of the archive, but:
 * - Not all of them take the comment section at the end of the archive into account.
 * - The file pointer can only forward, so they seek over the entire archive anyway.
 *
 * The current implementation can handle Non-Zip64 archives. The following extra Zip information can be read:
 * - The Unix Extra field.
 * - The Unix Extra field 2.
 * - The Universal Timestamp field.
 *
 * @package Archive
 * @version 1.4.1
 */
class ezcArchiveZip extends ezcArchive implements Iterator
{
    /**
     * Stores the byte number where the local file header starts for each entry.
     *
     * @var array(int)
     */
    protected $localHeaderPositions;

    /**
     * Stores the {@link ezcArchiveLocalFileHeader} for each entry.
     *
     * @var array(ezcArchiveLocalFileHeader)
     */
    protected $localHeaders;

    /**
     * Stores the byte number where the central directory header starts
     * (fileNumber is the index of the array).
     *
     * @var array(int)
     */
    protected $centralHeaderPositions;

    /**
     * Stores the {@link ezcArchiveCentralDirectoryHeader} for each entry.
     *
     * @var array(ezcArchiveCentralDirectoryHeader)
     */
    protected $centralHeaders;

    /**
     * Stores the {@link ezcArchiveCentralDirectoryEndHeader}.
     *
     * @var ezcArchiveCentralDirectoryEndHeader
     */
    protected $endRecord;

    /**
     * Initializes the Zip archive and reads the entire archive.
     *
     * The constructor opens the archive as a {@link ezcArchiveCharacterFile character file}.
     *
     * @param ezcArchiveCharacterFile $file
     */
    public function __construct( ezcArchiveCharacterFile $file )
    {
        $this->localHeaderPositions = array();
        $this->file = $file;

        $this->fileNumber = 0;
        $this->entriesRead = 0;

        if ( !$this->file->isEmpty() )
        {
            $this->readCentralHeaders();
        }

        $this->completed = true;
    }

    /**
     * Returns the value which specifies a ZIP algorithm.
     *
     * @return int
     */
    public function getAlgorithm()
    {
        return self::ZIP;
    }

    /**
     * Returns true because the ZIP algorithm can write.
     *
     * @see isWritable()
     *
     * @return bool
     */
    public function algorithmCanWrite()
    {
        return true;
    }

    /**
     * Reads the entire archive and creates all the entries.
     *
     * To find the central directory structure we need to read all the headers.
     * Some algorithms search backwards, but these don't expect comments at the end
     * of the archive.
     *
     * The central directory structure gives us extra information about the
     * stored file like: symlinks and permissions.
     *
     * @throws ezcArchiveException
     *         if the comment length is different than 0
     *         or if the signature from the file is invalid
     *         or if the directory central header or size are missing
     * @return void
     */
    protected function readCentralHeaders()
    {
        $this->localHeaders = array();
        $this->centralHeaders = array();

        // read the central end headers

        $this->file->seek( -22, SEEK_END );
        $filesize = $this->file->key() + 22;
        $endRecordPosition = $filesize - 22;

        $sig = $this->file->read( 4 );
        if ( ezcArchiveCentralDirectoryEndHeader::isSignature( $sig ) )
        {
            $this->endRecord = new ezcArchiveCentralDirectoryEndHeader( $this->file );

            if ( $this->endRecord->commentLength != 0 )
            {
                throw new ezcArchiveException( "Comment length invalid." );
            }
        }
        else
        {
            $signatureString = "PK\005\006";

            $startPosition = max( $filesize - ( 5 * 1024 ), 0 );

            // Maybe there is a comment at the end of the archive.
            $this->file->seek( $startPosition );
            $data = $this->file->read( $filesize - $startPosition );

            $pos = strpos( $data, $signatureString );

            if ( $pos === false )
            {
                throw new ezcArchiveException( "Could not find the central-directory header" );
            }

            $endRecordPosition = $startPosition + $pos;

            $this->file->seek( $endRecordPosition );
            $sig = $this->file->read( 4 );

            if ( ezcArchiveCentralDirectoryEndHeader::isSignature( $sig ) )
            {
                $this->endRecord = new ezcArchiveCentralDirectoryEndHeader( $this->file );
            }
            else
            {
                throw new ezcArchiveException( "Zip file corrupt" );
            }

            if ( $this->endRecord->commentLength !=  $filesize - $endRecordPosition - 22 )
            {
                throw new ezcArchiveException( "Comment length invalid." );
            }
        }

        if ( $endRecordPosition - $this->endRecord->centralDirectorySize !== $this->endRecord->centralDirectoryStart )
        {
            throw new ezcArchiveException( "Unable to determine the central directory start." );
        }

        $this->file->seek( $endRecordPosition - $this->endRecord->centralDirectorySize );
        $sig = $this->file->read( 4 );

        $i = 0;
        while ( ezcArchiveCentralDirectoryHeader::isSignature( $sig ) )
        {
            $this->centralHeaderPositions[$i] = $this->file->key() - 4;
            $this->centralHeaders[$i] = new ezcArchiveCentralDirectoryHeader( $this->file );

            $sig = $this->file->read( 4 );

            $this->localHeaderPositions[$i] = $this->centralHeaders[$i]->relativeHeaderOffset;

            $i++;
        }

        // Create the entries and check for symlinks.
        $this->entriesRead = $i;

        for ( $i = 0; $i < $this->entriesRead; $i++ )
        {
            $struct = new ezcArchiveFileStructure();

            // $this->localHeaders[$i]->setArchiveFileStructure( $struct );
            $this->centralHeaders[$i]->setArchiveFileStructure( $struct );


            // Set the symbolic links, 'cause these are written in the file data.
            if ( $this->centralHeaders[$i]->getType() == ezcArchiveEntry::IS_SYMBOLIC_LINK )
            {
                $struct->link = $this->getFileData( $i );
            }
            else
            {
                $struct->link = "";
            }

            $this->entries[$i] = new ezcArchiveEntry( $struct );
        }
    }


    /**
     * Writes the file data from the current entry to the given file.
     *
     * @param string $targetPath  The absolute or relative path of the target file.
     * @return bool
     */
    protected function writeCurrentDataToFile( $targetPath )
    {
        if ( !$this->valid() )
        {
            return false;
        }

        $this->writeFile( $this->key(), $targetPath );

        return true;
    }

    /**
     * Returns the file data of the given fileNumber.
     *
     * This method doesn't handle compression and reads the whole file in memory.
     * This method is used to get the symbolic links, since these are stored in files.
     *
     * For larger or compressed files, use the {@link writeFile()} method.
     *
     * @param int $fileNumber
     * @return string
     */
    public function getFileData( $fileNumber )
    {
        $pos = $this->localHeaderPositions[ $fileNumber ];
        $header = $this->getLocalHeader( $fileNumber );

        $newPos = $pos + $header->getHeaderSize();
        $this->file->seek( $newPos );

        // Read all the data.
        return $this->file->read( $header->compressedSize );
    }

    /**
     * Returns the local header of the specified file number.
     *
     * @throws ezcArchiveException
     *         if the signature from the file is invalid
     * @param int $fileNumber
     */
    public function getLocalHeader( $fileNumber )
    {
        if ( !isset( $this->localHeaders[$fileNumber] ) )
        {
            // Read the local header
            $this->file->seek( $this->localHeaderPositions[$fileNumber] );

            $sig = $this->file->read( 4 );

            if ( !ezcArchiveLocalFileHeader::isSignature( $sig ) )
            {
                throw new ezcArchiveException( "Zip file corrupt?" );
            }

            $this->localHeaders[$fileNumber] = new ezcArchiveLocalFileHeader( $this->file, $this->centralHeaders[$fileNumber] );
        }

        return $this->localHeaders[$fileNumber];
    }

    /**
     * Reads the file data from the archive and writes it the the $writeTo file.
     *
     * The data from the entry with $fileNumber is read from the archive.
     * If the data is compressed or deflated it will be, respectively, decompressed or inflated.
     *
     * @throws ezcArchiveChecksumException if the checksum is invalid from the created file.
     *
     * @param   int     $fileNumber
     * @param   string  $writeTo
     * @return  void
     */
    public function writeFile( $fileNumber,  $writeTo )
    {
        $header = $this->getLocalHeader( $fileNumber );
        $pos = $this->localHeaderPositions[ $fileNumber ] + $header->getHeaderSize();

        // FIXME.. don't write the entire stuff to memory.
        $this->file->seek( $pos );

        /*
        Part: 1
        - Append the stream filter.
        switch ( $header->compressionMethod )
        {
            case 8:  $this->file->appendStreamFilter( "zlib.inflate" ); break;
            case 12: $this->file->appendStreamFilter( "bzip2.decompress" ); break;
        }
        */

        $data = $this->file->read( $header->compressedSize );

        /*
        Part: 2
        - And remove the stream filter.
        - Then we can write the file directly from the archive without copying it entirely to memory.
        - Unfortunately, this method segfaults for me.

        if ( $header->compressionMethod == 8  || $header->compressionMethod == 12 )
        {
            $this->file->removeStreamFilter();
        }
        */

        if ( $data )
        {
            switch ( $header->compressionMethod )
            {
                case 8:
                    $data = gzinflate( $data );
                    break;    // Evil, memory consuming.

                case 12:
                    $data = bzdecompress( $data );
                    break;
            }
        }

        if ( strcmp( sprintf( "%u", crc32( $data ) ), sprintf( "%u", $header->crc & 0xffffffff ) ) == 0 )
        {
            $newFile = new ezcArchiveCharacterFile( $writeTo, true );
            $newFile->write( $data );
            unset( $newFile );
        }
        else
        {
            throw new ezcArchiveChecksumException( $writeTo );
        }
    }

    /**
     * Appends a file to the archive after the current entry.
     *
     * One or multiple files can be added directly after the current file.
     * The remaining entries after the current are removed from the archive!
     *
     * The $files can either be a string or an array of strings. Which, respectively, represents a
     * single file or multiple files.
     *
     * $prefix specifies the begin part of the $files path that should not be included in the archive.
     * The files in the archive are always stored relatively.
     *
     * Example:
     * <code>
     * $tar = ezcArchive( "/tmp/my_archive.tar", ezcArchive::TAR );
     *
     * // Append two files to the end of the archive.
     * $tar->seek( 0, SEEK_END );
     * $tar->appendToCurrent( array( "/home/rb/file1.txt", "/home/rb/file2.txt" ), "/home/rb/" );
     * </code>
     *
     * When multiple files are added to the archive at the same time, thus using an array, does not
     * necessarily produce the same archive as repeatively adding one file to the archive.
     * For example, the Tar archive format, can detect that files hardlink to each other and will store
     * it in a more efficient way.
     *
     * @throws ezcArchiveException            if the archive is closed or read-only
     * @throws ezcBaseFileNotFoundException   if one of the specified files is missing
     * @throws ezcBaseFilePermissionException if the archive is not writable
     *
     * @param string|array(string) $files  Array or a single path to a file.
     * @param string $prefix               First part of the path used in $files.
     * @return bool
     */
    public function appendToCurrent( $files, $prefix )
    {
        if ( !$this->isWritable() )
        {
            throw new ezcBaseFilePermissionException( $this->file->getFileName(), ezcBaseFilePermissionException::WRITE, "Archive is read-only" );
        }

        // Current position valid?
        if ( !$this->isEmpty() && !$this->valid() )
        {
            return false;
        }

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

        // Check whether the files are correct.
        foreach ( $files as $file )
        {
            if ( !file_exists( $file ) && !is_link( $file ) )
            {
                throw new ezcBaseFileNotFoundException( $file );
            }
        }

        // Search for all the entries, because otherwise hardlinked files show up as an ordinary file.
        $entries = ezcArchiveEntry::getEntryFromFile( $files, $prefix );

        if ( $this->isEmpty() )
        {
            $this->file->truncate();
            $this->file->rewind();
            $cur = -1;
        }
        else
        {
            // Create the new headers.
            $cur = $this->key(); // Current Header.

            $lh = $this->getLocalHeader( $cur );
            $pos = $this->localHeaderPositions[ $cur ] + $lh->getHeaderSize() + $lh->compressedSize;
            $this->file->truncate( $pos );
            $this->file->seek( $pos );
        }

        foreach ( $entries as $entry )
        {
            $cur++;
           // Set local header position
            $this->localHeaderPositions[$cur ] = $this->file->getPosition();

            // Set local header
            $this->localHeaders[ $cur ] =  new ezcArchiveLocalFileHeader();
            $this->localHeaders[ $cur ]->setHeaderFromArchiveEntry( $entry );

            if ( $entry->isSymLink() )
            {
                $fileData = $entry->getLink();
                $this->localHeaders[ $cur ]->setCompression( 0, $this->localHeaders[$cur]->uncompressedSize ); // Compression is 0, for now.
            }
            else if ( $entry->isDirectory() )
            {
                // Added for issue #13517: Not possible to add directories to an archive on Windows
                $fileData = gzdeflate( '' ); // empty string for directories
                $this->localHeaders[ $cur ]->setCompression( 8, strlen( $fileData ) );
            }
            else
            {
                // FIXME, File in memory, compression level always 8, add constants.
                $fileData = gzdeflate( file_get_contents( $entry->getPath() ) );
                $this->localHeaders[ $cur ]->setCompression( 8, strlen( $fileData)  );
            }

            $this->localHeaders[ $cur ]->writeEncodedHeader( $this->file );

            // Write link or file.
            $this->file->write( $fileData );
            unset( $fileData );

            // Create also the central headers.
            $this->centralHeaders[ $cur ] = new ezcArchiveCentralDirectoryHeader();
            $this->centralHeaders[ $cur ]->setHeaderFromLocalFileHeader( $this->localHeaders[ $cur ] );
            $this->centralHeaders[ $cur ]->setHeaderFromArchiveEntry( $entry );
            $this->centralHeaders[ $cur ]->relativeHeaderOffset = $this->localHeaderPositions[ $cur ];

            // Set the entry.
            $entry->removePrefixFromPath();
            $this->entries[ $cur ] = $entry;
        }

        for ( $i = 0; $i <= $cur; $i++ )
        {
            // Write the headers.
            $this->centralHeaderPositions[ $i ] = $this->file->getPosition();
            $this->centralHeaders[ $i ]->writeEncodedHeader( $this->file );
        }

        // Remove the rest of the localHeaders and centralHeaders.
        for ( $i = ( $cur + 1 ); $i < $this->entriesRead; $i++ )
        {
            unset( $this->localHeaders[ $i ] );
            unset( $this->localHeaderPositions[ $i ] );
            unset( $this->centralHeaders[ $i ] );
            unset( $this->centralHeaderPositions[ $i ] );
        }

        $this->entriesRead = $cur + 1;

        // Write the end record.
        $this->endRecord = new ezcArchiveCentralDirectoryEndHeader();
        $this->endRecord->centralDirectoryStart = $this->centralHeaderPositions[0];
        $this->endRecord->centralDirectorySize = $this->file->getPosition() - $this->centralHeaderPositions[0];

        $this->endRecord->totalCentralDirectoryEntries = $cur + 1;
        $this->endRecord->writeEncodedHeader( $this->file );
    }

    /**
     * Appends a file or directory to the end of the archive. Multiple files or directory can
     * be added to the archive when an array is used as input parameter.
     *
     * @see appendToCurrent()
     *
     * @throws ezcArchiveException  if one of the files cannot be written to the archive.
     *
     * @param string|array(string) $files  Array or a single path to a file.
     * @param string $prefix               First part of the path used in $files.
     *
     * @return bool
     */
    public function append( $files, $prefix )
    {
        if ( !$this->isWritable() )
        {
            throw new ezcArchiveException( "Archive is read-only", ezcArchiveException::ARCHIVE_NOT_WRITABLE );
        }

        $this->seek( 0, SEEK_END );
        $this->appendToCurrent( $files, $prefix );
     }

    /**
     * Truncates the archive to $fileNumber of files.
     *
     * The $fileNumber parameter specifies the amount of files that should remain.
     * If the default value, zero, is used then the entire archive file is cleared.
     *
     * @throws ezcBaseFilePermissionException
     *         if the file is read-only
     *         or if the current algorithm cannot write
     * @param int $fileNumber
     * @return bool
     */
    public function truncate( $fileNumber = 0 )
    {
        if ( !$this->isWritable() )
        {
            throw new ezcBaseFilePermissionException( $this->file->getFileName(), ezcBaseFilePermissionException::WRITE );
        }

        $originalFileNumber = $this->fileNumber;

        // Entirely empty the file.
        if ( $fileNumber == 0 )
        {
            $this->file->truncate();
            $this->entriesRead = 0;

            $this->localHeaders = array();
            $this->localHeaderPositions = array();
            $this->centralHeaders = array();
            $this->centralHeaderPositions = array();
            $this->endRecord = null;
        }
        else
        {
            $this->fileNumber = $fileNumber;
            if ( !$this->valid() )
            {
                return false;
            }

            // Truncate the file.
            $pos = $this->localHeaderPositions[ $fileNumber - 1 ];
            $this->file->truncate( $pos );
            $this->file->seek( $pos );

            for ( $i = 0; $i < $fileNumber; $i++ )
            {
                // Write the headers.
                $this->centralHeaders[$i]->writeEncodedHeader( $this->file );
            }

            // Clean up some headers.
            for ( $i = $fileNumber; $i < $this->entriesRead; $i++ )
            {
                unset( $this->localHeaderPositions[$i] );
                unset( $this->centralHeaderPositions[$i] );
                unset( $this->localHeaders[$i] );
                unset( $this->centralHeaders[$i] );
            }

            $this->entriesRead = $fileNumber;

            $this->setEndRecord();
            $this->endRecord->writeEncodedHeader( $this->file );

            $this->fileNumber = $originalFileNumber;
            return $this->valid();
        }
    }

    /**
     * Returns true if it is possible to write to the archive, otherwise false.
     *
     * This method returns false if the archive is read-only, the algorithm
     * didn't implement any write methods, or both.
     *
     * @see algorithmCanWrite()
     *
     * @throws ezcArchiveException
     *         if the archive is closed
     * @return bool
     */
    public function isWritable()
    {
        if ( $this->file === null )
        {
            throw new ezcArchiveException( "The archive is closed" );
        }

        return ( !$this->file->isReadOnly() && $this->algorithmCanWrite() );
    }

    /**
     * Creates and sets a new {@link ezcArchiveCentralDirectoryEndHeader}.
     *
     * The new {@link ezcArchiveCentralDirectoryEndHeader} is based on the current file position,
     * the centralHeaderPositions, and the number of entries read.
     *
     * @return void
     */
    protected function setEndRecord()
    {
        $this->endRecord = new ezcArchiveCentralDirectoryEndHeader();
        $this->endRecord->centralDirectoryStart = $this->centralHeaderPositions[0];
        $this->endRecord->centralDirectorySize = $this->file->getPosition() - $this->centralHeaderPositions[0];

        $this->endRecord->totalCentralDirectoryEntries = $this->entriesRead;
    }
}
?>
PK��Z�<��#ezc/Archive/interfaces/callback.phpnu�[���<?php
/**
 * File containing the ezcArchiveCallback class
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * Class containing a basic implementation of the callback class to be called
 * through extract.
 *
 * @package Archive
 * @version 1.4.1
 */
abstract class ezcArchiveCallback
{
    /**
     * Callback that's called for every file creation.
     *
     * The callback implementation is allowed to modify the $permissions,
     * $userId and $groupId. The latter two however might not have any
     * effect depending on which user and group the code runs at.
     *
     * @param string $fileName
     * @param int    $permissions
     * @param string $userId
     * @param string $groupId
     */
    function createFileCallback( $fileName, &$permissions, &$userId, &$groupId )
    {
    }

    /**
     * Callback that's called for every directory creation.
     *
     * The callback implementation is allowed to modify the $permissions,
     * $userId and $groupId. The latter two however might not have any
     * effect depending on which user and group the code runs at. You also need
     * to be aware that subsequent files might be put into this directory, and
     * bad things might happen when they can not be created there due to
     * operating system level restrictions.
     *
     * @param string $dirName
     * @param int    $permissions
     * @param string $userId
     * @param string $groupId
     */
    function createDirectoryCallback( $dirName, &$permissions, &$userId, &$groupId )
    {
    }
}
?>
PK��Z�靽�	�	ezc/Archive/tar/pax.phpnu�[���<?php
/**
 * File containing the ezcArchivePaxTar class.
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * The ezcArchivePaxTar class implements the Tar pax or posix archive format.
 *
 * ezcArchivePaxTar is a subclass from {@link ezcArchive} that provides the common interface,
 * and {@link ezcArchiveUstarTar} that provides the basic Tar implementation.
 *
 * ezcArchivePaxTar reads on creation only the first {@link ezcArchiveEntry entry} from the archive.
 * When needed next entries are read.
 *
 * The Pax Tar algorithm is an extension of Ustar Tar. Pax has the following extended features compared to Ustar:
 * - Filenames of unlimited size.
 * - File size is unlimited.
 *
 * The current implementation allows only reading from a Pax archive.
 *
 * @package Archive
 * @version 1.4.1
 */
class ezcArchivePaxTar extends ezcArchiveUstarTar
{
    /**
     * Initializes the Tar and tries to read the first entry from the archive.
     *
     * At initialization it sets the blockFactor to $blockFactor. Each tar archive
     * has always $blockFactor of blocks ( 0, $blockFactor, 2 * $blockFactor, etc ).
     *
     * The Tar archive works with blocks, so therefore the first parameter expects
     * the archive as a blockFile.
     *
     * @param ezcArchiveBlockFile $blockFile
     * @param int $blockFactor
     */
    public function __construct( ezcArchiveBlockFile $blockFile, $blockFactor = 20 )
    {
        parent::__construct( $blockFile, $blockFactor );
    }

    /**
     * Returns the value which specifies a TAR_PAX algorithm.
     *
     * @return int
     */
    public function getAlgorithm()
    {
        return self::TAR_PAX;
    }

    /**
     * Returns false because the TAR_PAX algorithm cannot write (yet).
     *
     * @see isWritable()
     *
     * @return bool
     */
    public function algorithmCanWrite()
    {
        return false;
    }

    /**
     * Creates the a new pax tar header for this class.
     *
     * This method expects an {@link ezcArchiveBlockFile} that points to the header that should be
     * read (and created). If null is given as  block file, an empty header will be created.
     *
     * @param string|null $file
     * @return ezcArchivePaxHeader
     */
    protected function createTarHeader( $file = null )
    {
        return new ezcArchivePaxHeader( $file );
    }
}
?>
PK��Z�31��	�	ezc/Archive/tar/ustar.phpnu�[���<?php
/**
 * File containing the ezcArchiveUstarTar class.
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * The ezcArchiveUstarTar class implements the Tar ustar archive format.
 *
 * ezcArchiveUstarTar is a subclass from {@link ezcArchive} that provides the common interface,
 * and {@link ezcArchiveV7Tar} that provides the basic Tar implementation.
 *
 * ezcArchiveUstarTar reads on creation only the first {@link ezcArchiveEntry entry} from the archive.
 * When needed next entries are read.
 *
 * The Ustar Tar algorithm is an extension of V7 Tar. Ustar has the following extended features:
 * - Filenames up to 255 characters.
 * - Stores the owner and group by ID and Name.
 * - Can archive: regular files, symbolic links, hard links, fifo's, and devices.
 *
 * @package Archive
 * @version 1.4.1
 */
class ezcArchiveUstarTar extends ezcArchiveV7Tar implements Iterator
{
    /**
     * Initializes the Tar and tries to read the first entry from the archive.
     *
     * At initialization it sets the blockFactor to $blockFactor. Each tar archive
     * has always $blockFactor of blocks ( 0, $blockFactor, 2 * $blockFactor, etc ).
     *
     * The Tar archive works with blocks, so therefore the first parameter expects
     * the archive as a blockFile.
     *
     * @param ezcArchiveBlockFile $blockFile
     * @param int $blockFactor
     */
    public function __construct( ezcArchiveBlockFile $blockFile, $blockFactor = 20 )
    {
        parent::__construct( $blockFile, $blockFactor );
    }

    /**
     * Returns the value which specifies a TAR_USTAR algorithm.
     *
     * @return int
     */
    public function getAlgorithm()
    {
        return self::TAR_USTAR;
    }

    /**
     * Returns true because the TAR_USTAR algorithm can write.
     *
     * @see isWritable()
     *
     * @return bool
     */
    public function algorithmCanWrite()
    {
        return true;
    }

    /**
     * Creates the a new ustar tar header for this class.
     *
     * This method expects an {@link ezcArchiveBlockFile} that points to the header that should be
     * read (and created). If null is given as  block file, an empty header will be created.
     *
     * @param string|null $file
     * @return ezcArchiveUstarHeader
     */
    protected function createTarHeader( $file = null)
    {
        return new ezcArchiveUstarHeader( $file );
    }
}
?>
PK��Z=��

ezc/Archive/tar/gnu.phpnu�[���<?php
/**
 * File contains the ezcArchiveGnuTar class.
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * The ezcArchiveGnuTar class implements the GNU Tar archive format.
 *
 * ezcArchiveGnuTar is a subclass from {@link ezcArchive} that provides the common interface,
 * and {@link ezcArchiveUstarTar} that provides the basic Tar implementation.
 *
 * ezcArchiveGnuTar reads on creation only the first {@link ezcArchiveEntry entry} from the archive.
 * When needed next entries are read.
 *
 * The Gnu Tar algorithm is an extension of Ustar Tar. Gnu has the following extended features compared to Ustar:
 * - Filenames of unlimited size.
 * - File size is unlimited.
 *
 * The current implementation allows only reading from a Gnu archive.
 *
 * The features of Gnu Tar and Pax Tar are quite similar, although their approach is different.
 *
 * @package Archive
 * @version 1.4.1
 */
class ezcArchiveGnuTar extends ezcArchiveUstarTar
{
    /**
     * Initializes the Tar and tries to read the first entry from the archive.
     *
     * At initialization it sets the blockFactor to $blockFactor. Each tar archive
     * has always $blockFactor of blocks ( 0, $blockFactor, 2 * $blockFactor, etc ).
     *
     * The Tar archive works with blocks, so therefore the first parameter expects
     * the archive as a blockFile.
     *
     * @param ezcArchiveBlockFile $blockFile
     * @param int $blockFactor
     */
    public function __construct( ezcArchiveBlockFile $blockFile, $blockFactor = 20 )
    {
        parent::__construct( $blockFile, $blockFactor );
    }

    /**
     * Returns the value which specifies a TAR_GNU algorithm.
     *
     * @return int
     */
    public function getAlgorithm()
    {
        return self::TAR_GNU;
    }

    /**
     * Returns false because the TAR_PAX algorithm cannot write (yet).
     *
     * @see isWritable()
     *
     * @return bool
     */
    public function algorithmCanWrite()
    {
        return false;
    }

    /**
     * Creates the a new pax tar header for this class.
     *
     * This method expects an {@link ezcArchiveBlockFile} that points to the header that should be
     * read (and created). If null is given as  block file, an empty header will be created.
     *
     * @param string|null $file
     * @return ezcArchiveGnuHeader
     */
    protected function createTarHeader( $file = null)
    {
        return new ezcArchiveGnuHeader( $file );
    }
}
?>
PK��Z�$����ezc/Archive/tar/headers/pax.phpnu�[���<?php
/**
 * File contains the ezcArchivePaxHeader class.
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @access private
 */

/**
 * The ezcArchivePaxHeader class represents the Tar Pax header.
 *
 * ezcArchivePaxHeader can read the header from an ezcArchiveBlockFile or ezcArchiveEntry.
 *
 * The values from the headers are directly accessible via the class properties, and allows
 * reading and writing to specific header values.
 *
 * The entire header can be appended to an ezcArchiveBlockFile again or written to an ezcArchiveFileStructure.
 * Information may get lost, though.
 *
 * The header is the {@link ezcArchiveUstarHeader} with extra header information described on the following webpage:
 * {@link http://www.opengroup.org/onlinepubs/009695399/utilities/pax.html}
 *
 * Currently, only the extended header is supported.
 *
 * @package Archive
 * @version 1.4.1
 * @access private
 */
class ezcArchivePaxHeader extends ezcArchiveUstarHeader
{
    /**
     * Sets the property $name to $value.
     *
     * @throws ezcBasePropertyNotFoundException if the property does not exist.
     * @param string $name
     * @param mixed $value
     * @return void
     * @ignore
     */
    public function __set( $name, $value )
    {
        return parent::__set( $name, $value );
    }

    /**
     * Returns the value of the property $name.
     *
     * @throws ezcBasePropertyNotFoundException if the property does not exist.
     * @param string $name
     * @return mixed
     * @ignore
     */
    public function __get( $name )
    {
        return parent::__get( $name );
    }

    /**
     * Returns an array with pax header information.
     *
     * This method reads an extended set of data from the ezcArchiveBlockFile
     * $file and returns the values in an array.
     *
     * @param ezcArchiveBlockFile $file
     * @return array(string=>string)
     */
    protected function getPaxDecodedHeader( ezcArchiveBlockFile $file )
    {
        $result = array();

        // next block has the info.
        $file->next();

        $data = $file->current();

        $offset = 0;

        while ( strcmp( $data[$offset], "\0" ) != 0 )
        {
            $space = strpos( $data, " ", $offset );

            $length = substr( $data, $offset, $space - $offset );
            $equalSign = strpos( $data, "=",  $space );

            $keyword = substr( $data, $space + 1, $equalSign - $space - 1 );

            $value = rtrim( substr( $data, $equalSign + 1, $length - $equalSign - 1 ), "\n" );

            $result[ $keyword ] = $value;

            $offset += $length;
        }

        return $result;
    }

    /**
     * Creates and initializes a new header.
     *
     * If the ezcArchiveBlockFile $file is null then the header will be empty.
     * When an ezcArchiveBlockFile is given, the block position should point to the header block.
     * This header block will be read from the file and initialized in this class.
     *
     * @param ezcArchiveBlockFile $file
     */
    public function __construct( ezcArchiveBlockFile $file = null )
    {
        if ( !is_null( $file ) )
        {
            parent::__construct( $file );

            if ( $this->type == "x" )
            {
                $paxArray = $this->getPaxDecodedHeader( $file );
                $file->next();
            }

            parent::__construct( $file );

            // Override some fields.
            foreach ( $paxArray as $key => $value )
            {
                switch ( $key )
                {
                    case "gid":
                        $this->groupId = $value;
                        break;  // For group IDs larger than 2097151.

                    case "linkpath":
                        $this->linkName = $value;
                        break;  // Long link names?

                    case "path":
                        $this->fileName = $value;
                        $this->filePrefix = "";
                        break; // Really long file names.

                    case "size":
                        $this->size = $value;
                        break;  // For files with a size greater than 8589934591 bytes.

                    case "uid":
                        $this->userId = $value;
                        break;  // For user IDs larger than 2097151.
                }
            }
        }
    }
}
?>
PK��Z�M��9�9!ezc/Archive/tar/headers/ustar.phpnu�[���<?php
/**
 * File containing the ezcArchiveUstarHeader class.
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @access private
 */

/**
 * The ezcArchiveUstarHeader class represents the Tar Ustar header.
 *
 * ezcArchiveUstarHeader can read the header from an ezcArchiveBlockFile or ezcArchiveEntry.
 *
 * The values from the headers are directly accessible via the class properties, and allows
 * reading and writing to specific header values.
 *
 * The entire header can be appended to an ezcArchiveBlockFile again or written to an ezcArchiveFileStructure.
 * Information may get lost, though.
 *
 * The Ustar Header has the following structure:
 *
 * <pre>
 * +--------+------------+-------------------+---------------------------+
 * | Offset | Field size | Property          |  Description              |
 * +--------+------------+-------------------+---------------------------+
 * |  0     | 100        | fileName          | Name of the file          |
 * |  100   | 8          | fileMode          | File mode                 |
 * |  108   | 8          | userId            | Owner user ID             |
 * |  116   | 8          | groupId           | Owner group ID            |
 * |  124   | 12         | fileSize          | Length of file in bytes   |
 * |  136   | 12         | modificationTime  | Modify time of file       |
 * |  148   | 8          | checksum          | Checksum for header       |
 * |  156   | 1          | type              | Indicator for links       |
 * |  157   | 100        | linkName          | Name of linked file       |
 * |  257   | 6          | magic             | USTAR indicator           |
 * |  263   | 2          | version           | USTAR version             |
 * |  265   | 32         | userName          | Owner user name           |
 * |  297   | 32         | groupName         | Owner group name          |
 * |  329   | 8          | deviceMajorNumber | Major device number       |
 * |  337   | 8          | deviceMinorNumber | Minor device number       |
 * |  345   | 155        | filePrefix        | Filename prefix           |
 * |  500   | 12         | -                 | NUL                       |
 * +--------+------------+-------------------+---------------------------+
 * </pre>
 *
 * The columns of the table are:
 * - Offset describes the start position of a header field.
 * - Field size describes the size of the field.
 * - Property is the name of the property that will be set by the header field.
 * - Description explains what this field describes.
 *
 *
 * @package Archive
 * @version 1.4.1
 * @access private
 */
class ezcArchiveUstarHeader extends ezcArchiveV7Header
{
    /**
     * Sets the property $name to $value.
     *
     * @throws ezcBasePropertyNotFoundException if the property does not exist.
     * @param string $name
     * @param mixed $value
     * @return void
     * @ignore
     */
    public function __set( $name, $value )
    {
        switch ( $name )
        {
            case "magic":
            case "version":
            case "userName":
            case "groupName":
            case "deviceMajorNumber":
            case "deviceMinorNumber":
            case "filePrefix":
                $this->properties[$name] = $value;
                return;
        }

        return parent::__set( $name, $value );
    }

    /**
     * Returns the value of the property $name.
     *
     * @throws ezcBasePropertyNotFoundException if the property does not exist.
     * @param string $name
     * @return mixed
     * @ignore
     */
    public function __get( $name )
    {
        switch ( $name )
        {
            case "magic":
            case "version":
            case "userName":
            case "groupName":
            case "deviceMajorNumber":
            case "deviceMinorNumber":
            case "filePrefix":
                return $this->properties[ $name ];
        }

        return parent::__get( $name );
    }

    /**
     * Creates and initializes a new header.
     *
     * If the ezcArchiveBlockFile $file is null then the header will be empty.
     * When an ezcArchiveBlockFile is given, the block position should point to the header block.
     * This header block will be read from the file and initialized in this class.
     *
     * @param ezcArchiveBlockFile $file
     */
    public function __construct( ezcArchiveBlockFile $file = null )
    {
       // Offset | Field size |  Description
        // ----------------------------------
        //  0     | 100        | Name of file
        //  100   | 8          | File mode
        //  108   | 8          | Owner user ID
        //  116   | 8          | Owner group ID
        //  124   | 12         | Length of file in bytes
        //  136   | 12         | Modify time of file
        //  148   | 8          | Checksum for header
        //  156   | 1          | Type flag.
        //  157   | 100        | Name of linked file
        //  257   | 6          | USTAR indicator.
        //  263   | 2          | USTAR version.
        //  265   | 32         | Owner user name.
        //  297   | 32         | Owner group name.
        //  329   | 8          | Major device number.
        //  337   | 8          | Minor device number.
        //  345   | 155        | Filename prefix.
        //  500   | 12         | NUL.

        if ( !is_null( $file ) )
        {
            parent::__construct( $file );

            // Decode the rest.
            $decoded = unpack( "@257/a6magic/a2version/a32userName/a32groupName/a8deviceMajorNumber/a8deviceMinorNumber/a155filePrefix", $file->current() );

            // Append the decoded array to the header.
            $this->properties = array_merge( $this->properties, $decoded );

            $this->handleOwner();
         }
    }

    /**
     * This method sets the correct owner in the headers.
     *
     * This only works if PHP has the posix extension compiled in and
     * when the effective user ID is 0 (root).
     */
    protected function handleOwner()
    {
        if ( !ezcBaseFeatures::hasFunction( 'posix_getpwuid' ) )
        {
            return;
        }

        $t =& $this->properties;

        if ( posix_geteuid() === 0 && isset( $t['userName'] ) && $t['userName'] !== '' )
        {
            if ( ( $userName = posix_getpwnam( $t['userName'] ) ) !== false )
            {
                $t['userId'] = $userName['uid'];
            }
            if ( ( $groupName = posix_getgrnam( $t['groupName'] ) ) !== false )
            {
                $t['groupId'] = $groupName['gid'];
            }
        }
    }

    /**
     * Sets this header with the values from the ezcArchiveEntry $entry.
     *
     * The values that are possible to set from the ezcArchiveEntry $entry are set in this header.
     * The properties that may change are: fileName, fileMode, userId, groupId, fileSize, modificationTime,
     * linkName, and type.
     *
     * @param ezcArchiveEntry $entry
     * @return void
     */
    public function setHeaderFromArchiveEntry( ezcArchiveEntry $entry )
    {
        $this->splitFilePrefix( $entry->getPath( false ), $file,  $filePrefix );
        $this->fileName = $file;
        $this->filePrefix = $filePrefix;

        $this->fileMode = $entry->getPermissions();
        $this->userId = $entry->getUserId();
        $this->groupId = $entry->getGroupId();
        $this->fileSize = $entry->getSize();
        $this->modificationTime = $entry->getModificationTime();
        $this->linkName = $entry->getLink( false );

        switch ( $entry->getType() )
        {
            case ezcArchiveEntry::IS_FILE:
                $this->type = 0;
                break;

            case ezcArchiveEntry::IS_LINK:
                $this->type = 1;
                break;

            case ezcArchiveEntry::IS_SYMBOLIC_LINK:
                $this->type = 2;
                break;

            case ezcArchiveEntry::IS_CHARACTER_DEVICE:
                $this->type = 3;
                break;

            case ezcArchiveEntry::IS_BLOCK_DEVICE:
                $this->type = 4;
                break;

            case ezcArchiveEntry::IS_DIRECTORY:
                $this->type = 5;
                break;

            case ezcArchiveEntry::IS_FIFO:
                $this->type = 6;
                break;

            // Devices, etc are set to \0.
            default:
                $this->type = "";
                break; // ends up as a \0 character.
        }

        $this->deviceMajorNumber = $entry->getMajor();
        $this->deviceMinorNumber = $entry->getMinor();

        $length = strlen( $this->fileName );

        if ( $entry->getType() == ezcArchiveEntry::IS_DIRECTORY )
        {
           // Make sure that the filename ends with a slash.
           if ( $this->fileName[ $length - 1] != "/" )
           {
               $this->fileName .= "/";
           }
        }
        else
        {
           if ( $this->fileName[ $length - 1] == "/" )
           {
               $this->fileName = substr( $this->fileName, 0, -1 ); // Remove last character.
           }
        }
    }

    /**
     * Splits the path $path, if it exceeds 100 tokens, into two parts: $file and $filePrefix.
     *
     * If the path contains more than 100 tokens, it will put the directory name in the $filePrefix and
     * the fileName into $file.
     * This is the same method as Gnu Tar splits the file and file prefix.
     *
     * @throws ezcArchiveIoException if the file name cannot be written to the archive.
     * @param string $path
     * @param string &$file
     * @param string &$filePrefix
     * @return void
     */
    protected function splitFilePrefix( $path, &$file, &$filePrefix )
    {
        if ( strlen( $path ) > 100 )
        {
            $filePrefix = dirname( $path );
            $file = basename( $path );

            if ( strlen( $filePrefix )  > 155 || strlen( $file ) > 100 )
            {
                throw new ezcArchiveIoException( "Filename too long: $path" );
            }
        }
        else
        {
            $filePrefix = "";
            $file = $path;
        }
    }

    /**
     * Serializes this header and appends it to the given ezcArchiveBlockFile $archiveFile.
     *
     * @param ezcArchiveBlockFile $archiveFile
     * @return void
     */
    public function writeEncodedHeader( ezcArchiveBlockFile $archiveFile )
    {
        // Offset | Field size |  Description
        // ----------------------------------
        //  0     | 100        | Name of file
        //  100   | 8          | File mode
        //  108   | 8          | Owner user ID
        //  116   | 8          | Owner group ID
        //  124   | 12         | Length of file in bytes
        //  136   | 12         | Modify time of file
        //  148   | 8          | Checksum for header
        //  156   | 1          | Type flag.
        //  157   | 100        | Name of linked file
        //  257   | 6          | USTAR indicator.
        //  263   | 2          | USTAR version.
        //  265   | 32         | Owner user name.
        //  297   | 32         | Owner group name.
        //  329   | 8          | Major device number.
        //  337   | 8          | Minor device number.
        //  345   | 155        | Filename prefix.
        //  500   | 12         | NUL.
        if ( ezcBaseFeatures::hasFunction( 'posix_getpwuid' ) )
        {
            $posixName = ( posix_getpwuid( $this->userId ) );
            $posixGroup = ( posix_getgrgid( $this->groupId ) );
        }
        else
        {
            $posixName['name']= 'nobody';
            $posixGroup['name']= 'nogroup';
        }

        $enc = pack( "a100a8a8a8a12a12a8a1a100a6a2a32a32a8a8a155a12",
            $this->fileName,
            str_pad( $this->fileMode, 7, "0", STR_PAD_LEFT),
            str_pad( decoct( $this->userId ), 7, "0", STR_PAD_LEFT),
            str_pad( decoct( $this->groupId ), 7, "0", STR_PAD_LEFT),
            str_pad( decoct( $this->fileSize ), 11, "0", STR_PAD_LEFT),
            str_pad( decoct( $this->modificationTime ), 11, "0", STR_PAD_LEFT),
            "        ",
            $this->type,
            $this->linkName,
            "ustar",
            "00",
            $posixName["name"],
            $posixGroup["name"],
            sprintf( "%07s", decoct( $this->deviceMajorNumber ) ),
            sprintf( "%07s", decoct( $this->deviceMinorNumber ) ),
            $this->filePrefix,
            "" );

        $enc = $this->setChecksum( $enc );

        $archiveFile->append( $enc );
    }

    /**
     * Updates the given ezcArchiveFileStructure $struct with the values from this header.
     *
     * The values that can be set in the archiveFileStructure are: path, gid, uid, type, link, mtime, mode, and size.
     *
     * @throws ezcArchiveValueException
     *         if trying to set the structure type to the reserved type
     * @param ezcArchiveFileStructure &$struct
     * @return void
     */
    public function setArchiveFileStructure( ezcArchiveFileStructure &$struct )
    {
        parent::setArchiveFileStructure( $struct );

        if ( $this->filePrefix != '' )
        {
            $struct->path = $this->filePrefix . DIRECTORY_SEPARATOR . $this->fileName;
        }
        else
        {
            $struct->path = $this->fileName;
        }
        $struct->major = $this->deviceMajorNumber;
        $struct->minor = $this->deviceMinorNumber;
        $struct->userName = $this->userName;
        $struct->groupName = $this->groupName;

        // Override the link type.
        switch ( $this->type )
        {
            case "\0":
            case 0:
                $struct->type = ezcArchiveEntry::IS_FILE;
                break;

            case 1:
                $struct->type = ezcArchiveEntry::IS_LINK;
                break;

            case 2:
                $struct->type = ezcArchiveEntry::IS_SYMBOLIC_LINK;
                break;

            case 3:
                $struct->type = ezcArchiveEntry::IS_CHARACTER_DEVICE;
                break;

            case 4:
                $struct->type = ezcArchiveEntry::IS_BLOCK_DEVICE;
                break;

            case 5:
                $struct->type = ezcArchiveEntry::IS_DIRECTORY;
                break;

            case 6:
                $struct->type = ezcArchiveEntry::IS_FIFO;
                break;

            case 7:
                $struct->type = ezcArchiveEntry::IS_RESERVED;
                break;
        }

        if ( $struct->type == ezcArchiveEntry::IS_RESERVED )
        {
            throw new ezcArchiveValueException( $struct->type, " < " . ezcArchiveEntry::IS_RESERVED );
        }
    }
}
?>
PK��ZNv�nnezc/Archive/tar/headers/gnu.phpnu�[���<?php
/**
 * File contains the ezcArchiveGnuHeader class.
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @access private
 */

/**
 * The ezcArchiveGnuHeader class represents the Tar Gnu header.
 *
 * ezcArchiveGnuHeader can read the header from an ezcArchiveBlockFile or ezcArchiveEntry.
 *
 * The values from the headers are directly accessible via the class properties, and allows
 * reading and writing to specific header values.
 *
 * The entire header can be appended to an ezcArchiveBlockFile again or written to an ezcArchiveFileStructure.
 * Information may get lost, though.
 *
 * The header is the {@link ezcArchiveUstarHeader} with the extension that the type can be set to "L" or "K".
 * Respectively, long filename and long link. If the type is set to either "L" or "K", the next block contains the
 * filename or link. The block thereafter repeats the original header but the type is then set to a digit.
 * (No long filename or link).
 *
 * @package Archive
 * @version 1.4.1
 * @access private
 */
class ezcArchiveGnuHeader extends ezcArchiveUstarHeader
{
    /**
     * Creates and initializes a new header.
     *
     * If the ezcArchiveBlockFile $file is null then the header will be empty.
     * When an ezcArchiveBlockFile is given, the block position should point to the header block.
     * This header block will be read from the file and initialized in this class.
     *
     * @param ezcArchiveBlockFile $file
     */
    public function __construct( ezcArchiveBlockFile $file = null )
    {
        if ( !is_null( $file ) )
        {
            // FIXME  Assumed a while.. check the gnu tar source file.
            // FIXME  Check long links, really large files, etc.
            $extensions = array();

            do
            {
                parent::__construct( $file );

                switch ( $this->type )
                {
                    case "L":
                        $extensions["fileName"] = $this->readExtension( $file );
                        break;

                    case "K":
                        $extensions["linkName"] = $this->readExtension( $file );
                        break;

                }
            } while ( $this->type < '0' || $this->type > '9' );

            parent::__construct( $file );

            foreach ( $extensions as $key => $value )
            {
                switch ( $key )
                {
                    case "fileName":
                        $this->fileName = $extensions["fileName"];
                        $this->filePrefix = "";
                        break;

                    case "linkName":
                        $this->linkName = $extensions["linkName"];
                        break;
                }
            }
        }
    }

    /**
     * Reads an extended set of data from the Block file and returns it as a string.
     *
     * Some filenames or link names do not fit in the Ustar header, and are therefor placed in a new block.
     * This method read the block(s) and returns the data as a string.
     *
     * @param ezcArchiveBlockFile $file
     * @return string
     */
    protected function readExtension( ezcArchiveBlockFile $file )
    {
        $completeBlocks = ( int ) ( $this->fileSize / self::BLOCK_SIZE );
        $rest = ( $this->fileSize % self::BLOCK_SIZE );

        $data  = "";
        for ( $i = 0; $i < $completeBlocks; $i++ )
        {
            $data .=  $file->next();
        }

        $data .= substr( $file->next(), 0, $rest );

        $file->next();
        return $data;
    }
}
?>
PK��Z^���8�8ezc/Archive/tar/headers/v7.phpnu�[���<?php
/**
 * File contains the ezcArchiveV7Header class.
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @access private
 */

/**
 * The ezcArchiveV7Header class represents the Tar V7 header.
 *
 * ezcArchiveV7Header can read the header from an ezcArchiveBlockFile or ezcArchiveEntry.
 *
 * The values from the headers are directly accessible via the class properties, and allows
 * reading and writing to specific header values.
 *
 * The entire header can be appended to an ezcArchiveBlockFile again or written to an ezcArchiveFileStructure.
 * Information may get lost, though.
 *
 * The V7 Header has the following structure:
 *
 * <pre>
 * +--------+------------+------------------+-----------------------------------------------------------+
 * | Offset | Field size | Property         |  Description                                              |
 * +--------+------------+------------------+-----------------------------------------------------------+
 * |  0     | 100        | fileName         | Name of file                                              |
 * |  100   | 8          | fileMode         | File mode                                                 |
 * |  108   | 8          | userId           | Owner user ID                                             |
 * |  116   | 8          | groupId          | Owner group ID                                            |
 * |  124   | 12         | fileSize         | Length of file in bytes                                   |
 * |  136   | 12         | modificationTime | Modify time of file                                       |
 * |  148   | 8          | checksum         | Checksum for header                                       |
 * |  156   | 1          | type             | Indicator for links                                       |
 * |  157   | 100        | linkName         | Name of linked file                                       |
 * |  257   | 72         | -                | NUL.                                                      |
 * |  329   | 8          | -                | Compatibility with GNU tar: Major device set to: 00000000.|
 * |  337   | 8          | -                | Compatibility with GNU tar: Minor device set to: 00000000.|
 * |  345   | 167        | -                | NUL.                                                      |
 * +--------+------------+------------------+-----------------------------------------------------------+
 * </pre>
 *
 * The columns of the table are:
 * - Offset describes the start position of a header field.
 * - Field size describes the size of the field.
 * - Property is the name of the property that will be set by the header field.
 * - Description explains what this field describes.
 *
 *
 * @package Archive
 * @version 1.4.1
 * @access private
 */
class ezcArchiveV7Header
{
    /**
     * Relative byte position that the header starts.
     */
    const START_HEADER    = 0;

    /**
     * Relative byte position that the checksum starts.
     */
    const CHECKSUM_OFFSET = 148;

    /**
     * Number of bytes that the checksum occupies.
     */
    const CHECKSUM_SIZE   = 8;

    /**
     * Relative byte position that the checksum ends.
     */
    const END_HEADER      = 512;

    /**
     * Number of bytes that a block occupies.
     */
    const BLOCK_SIZE      = 512;

    /**
     * Holds the properties of this class.
     *
     * @var array(string=>mixed)
     */
    protected $properties = array();

    /**
     * Sets the property $name to $value.
     *
     * @throws ezcBasePropertyNotFoundException if the property does not exist.
     * @param string $name
     * @param mixed $value
     * @return void
     * @ignore
     */
    public function __set( $name, $value )
    {
        switch ( $name )
        {
            case "fileName":
            case "fileMode":
            case "userId":
            case "groupId":
            case "fileSize":
            case "modificationTime":
            case "checksum":
            case "type":
            case "linkName":
                $this->properties[$name] = $value;
                break;

            default:
                throw new ezcBasePropertyNotFoundException( $name );
        }
    }

    /**
     * Returns the value of the property $name.
     *
     * @throws ezcBasePropertyNotFoundException if the property does not exist.
     * @param string $name
     * @return mixed
     * @ignore
     */
    public function __get( $name )
    {
        switch ( $name )
        {
            case "fileName":
            case "fileMode":
            case "userId":
            case "groupId":
            case "fileSize":
            case "modificationTime":
            case "checksum":
            case "type":
            case "linkName":
                return $this->properties[ $name ];

            default:
                throw new ezcBasePropertyNotFoundException( $name );
        }
    }

    /**
     * Creates and initializes a new header.
     *
     * If the ezcArchiveBlockFile $file is null then the header will be empty.
     * When an ezcArchiveBlockFile is given, the block position should point to the header block.
     * This header block will be read from the file and initialized in this class.
     *
     * @throws ezcArchiveChecksumException
     *         if the checksum from the file did not match the calculated one
     * @param ezcArchiveBlockFile $file
     */
    public function __construct( ezcArchiveBlockFile $file = null )
    {
        // Offset | Field size |  Description
        // ----------------------------------
        //  0     | 100        | Name of file
        //  100   | 8          | File mode
        //  108   | 8          | Owner user ID
        //  116   | 8          | Owner group ID
        //  124   | 12         | Length of file in bytes
        //  136   | 12         | Modify time of file
        //  148   | 8          | Checksum for header
        //  156   | 1          | Indicator for links
        //  157   | 100        | Name of linked file
        // ------------------------------------------
        //  257   | 72         | NUL.
        //  329   | 8          | Compatibility with GNU tar: Major device set to: 00000000.
        //  337   | 8          | Compatibility with GNU tar: Minor device set to: 00000000.
        //  345   | 167        | NUL.

        if ( !is_null( $file ) )
        {
            $this->properties = unpack ( "a100fileName/".
                                         "a8fileMode/".
                                         "a8userId/".
                                         "a8groupId/".
                                         "a12fileSize/".
                                         "a12modificationTime/".
                                         "a8checksum/".
                                         "a1type/".
                                         "a100linkName", $file->current() );

            $this->properties["userId"]   = octdec( $this->properties["userId"] );
            $this->properties["groupId"]  = octdec( $this->properties["groupId"] );
            $this->properties["fileSize"]  = octdec( $this->properties["fileSize"] );
            $this->properties["modificationTime"]  = octdec( $this->properties["modificationTime"] );
            $this->properties["checksum"]  = octdec( $this->properties["checksum"] );

            if ( !$this->checksum( $this->checksum, $file->current() ) )
            {
                throw new ezcArchiveChecksumException( $file->getFileName() );
            }
        }
    }

    /**
     * Returns true when the checksum $checksum matches with the header data $rawHeader; otherwise returns false.
     *
     * The checksum is calculated by the {@link ezcArchiveChecksums::getTotalByteValueFromString()}.
     *
     * @param  int    $checksum
     * @param  string $rawHeader
     * @return bool
     */
    protected function checksum( $checksum, $rawHeader )
    {
        $total = ezcArchiveChecksums::getTotalByteValueFromString( substr( $rawHeader, self::START_HEADER, self::END_HEADER - self::START_HEADER ) );

        // assume blanks for the checksum itself.
        $total -= ezcArchiveChecksums::getTotalByteValueFromString( substr( $rawHeader, self::CHECKSUM_OFFSET, self::CHECKSUM_SIZE ) );
        $total += ezcArchiveChecksums::getTotalByteValueFromString( str_repeat( " ", self::CHECKSUM_SIZE ) );

        return ( strcmp( sprintf( "%08x", $checksum ), sprintf( "%08x", $total ) ) == 0 );
    }

    /**
     * Returns the encoded header as given as the parameter $encodedHeader but includes the
     * checksum of the header.
     *
     * The encoded header $encodedHeader should have spaces at the place where the checksum should be stored.
     *
     * @param string $encodedHeader
     * @return string
     */
    protected function setChecksum( $encodedHeader )
    {
        $total = ezcArchiveChecksums::getTotalByteValueFromString( $encodedHeader );

        $checksum = pack( "a7", str_pad( decoct( $total ), 6, "0", STR_PAD_LEFT ) );
        $checksum .= " ";

        $begin = substr( $encodedHeader, 0, 148 );
        $end = substr( $encodedHeader, 156 );

        return $begin.$checksum.$end;
    }

    /**
     * Sets this header with the values from the ezcArchiveEntry $entry.
     *
     * The values that are possible to set from the ezcArchiveEntry $entry are set in this header.
     * The properties that may change are: fileName, fileMode, userId, groupId, fileSize, modificationTime,
     * linkName, and type.
     *
     * @param ezcArchiveEntry $entry
     * @return void
     */
    public function setHeaderFromArchiveEntry( ezcArchiveEntry $entry )
    {
        $this->fileName = $entry->getPath( false );
        $this->fileMode = $entry->getPermissions();
        $this->userId = $entry->getUserId();
        $this->groupId = $entry->getGroupId();
        $this->fileSize = $entry->getSize();
        $this->modificationTime = $entry->getModificationTime();
        $this->linkName = $entry->getLink( false );

        switch ( $entry->getType() )
        {
            case ezcArchiveEntry::IS_FILE:
                $this->type = "";
                break; // ends up as a \0 character.

            case ezcArchiveEntry::IS_LINK:
                $this->type = 1;
                break;

            case ezcArchiveEntry::IS_SYMBOLIC_LINK:
                $this->type = 2;
                break;

            case ezcArchiveEntry::IS_DIRECTORY:
                $this->type = 5;
                break;

            // Devices, etc are set to \0.
            default:
                $this->type = "";
                break; // ends up as a \0 character.
        }

        $length = strlen( $this->fileName );

        if ( $entry->getType() == ezcArchiveEntry::IS_DIRECTORY )
        {
           // Make sure that the filename ends with a slash.
           if ( $this->fileName[ $length - 1] != "/" )
           {
               $this->fileName .= "/";
           }
        }
        else
        {
           if ( $this->fileName[ $length - 1] == "/" )
           {
               $this->fileName = substr( $header->fileName, 0, -1 ); // Remove last character.
           }
        }
    }

    /**
     * Serializes this header and appends it to the given ezcArchiveBlockFile $archiveFile.
     *
     * @param ezcArchiveBlockFile $archiveFile
     * @return void
     */
    public function writeEncodedHeader( ezcArchiveBlockFile $archiveFile )
    {
        // Offset | Field size |  Description
        // ----------------------------------
        //  0     | 100        | Name of file
        //  100   | 8          | File mode
        //  108   | 8          | Owner user ID
        //  116   | 8          | Owner group ID
        //  124   | 12         | Length of file in bytes
        //  136   | 12         | Modify time of file
        //  148   | 8          | Checksum for header
        //  156   | 1          | Indicator for links
        //  157   | 100        | Name of linked file
        // ------------------------------------------
        //  257   | 72         | NUL.
        //  329   | 8          | Compatibility with GNU tar: Major device set to: 00000000.
        //  337   | 8          | Compatibility with GNU tar: Minor device set to: 00000000.
        //  345   | 167        | NUL.
        //

        $enc = pack( "a100a8a8a8a12a12a8a1a100a72a8a8a167",
            $this->fileName,
            str_pad( $this->fileMode, 7, "0", STR_PAD_LEFT ),
            str_pad( decoct( $this->userId ), 7, "0", STR_PAD_LEFT ),
            str_pad( decoct( $this->groupId ), 7, "0", STR_PAD_LEFT ),
            str_pad( decoct( $this->fileSize ), 11, "0", STR_PAD_LEFT ),
            str_pad( decoct( $this->modificationTime ), 11, "0", STR_PAD_LEFT ),
            "        ",
            $this->type,
            $this->linkName,
            "",
            "0000000",
            "0000000",
            "" );

        $enc = $this->setChecksum( $enc );
        $archiveFile->append( $enc );
    }

    /**
     * Updates the given ezcArchiveFileStructure $struct with the values from
     * this header.
     *
     * The values that can be set in the archiveFileStructure are: path, gid,
     * uid, type, link, mtime, mode, and size.
     *
     * @param ezcArchiveFileStructure &$struct
     * @return void
     */
    public function setArchiveFileStructure( ezcArchiveFileStructure &$struct )
    {
        $struct->path = $this->fileName;
        $struct->gid = $this->groupId;
        $struct->uid = $this->userId;

        switch ( $this->type )
        {
            case "\0":
            case 0:
                $struct->type = ezcArchiveEntry::IS_FILE;
                break;

            case 1:
                $struct->type = ezcArchiveEntry::IS_LINK;
                break;

            case 2:
                $struct->type = ezcArchiveEntry::IS_SYMBOLIC_LINK;
                break;
        }

        // trailing slash means directory
        if ( $this->fileName[ strlen( $this->fileName ) - 1 ] == '/' )
        {
            $struct->type = ezcArchiveEntry::IS_DIRECTORY;
        }

        $struct->link = $this->linkName;
        $struct->mtime = $this->modificationTime;
        $struct->mode = $this->fileMode;
        $struct->size = $this->fileSize;
    }
}
?>
PK��Z���BLBLezc/Archive/tar/v7.phpnu�[���<?php
/**
 * File contains the ezcArchiveV7Tar class.
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */

/**
 * The ezcArchiveV7Tar class implements the Tar v7 archive format.
 *
 * ezcArchiveV7Tar is a subclass from {@link ezcArchive} that provides the common interface.
 * Tar v7 algorithm specific methods are implemented in this class.
 *
 * ezcArchiveV7Tar reads on creation only the first {@link ezcArchiveEntry} from the archive.
 * When needed next entries are read.
 *
 * The V7 Tar algorithm is most basic implementation of Tar. This format has the following characteristics:
 * - Filenames up to 100 characters.
 * - Stores the file permissions.
 * - Stores the owner and group by ID.
 * - Stores the last modification time.
 * - Can archive: regular files and symbolic links.
 * - Maximum file size: 8 Gygabyte.
 *
 * @package Archive
 * @version 1.4.1
 */
class ezcArchiveV7Tar extends ezcArchive
{
    /**
     * Amount of bytes in a block.
     */
    const BLOCK_SIZE = 512;

    /**
     * Tar archives have always $blockFactor of blocks.
     *
     * @var int
     */
    protected $blockFactor = 20;

    /**
     * Stores all the headers from the archive.
     *
     * The first header of the archive has index zero. The ezcArchiveV7Header or a subclass from this header
     * is stored in the array. {@link createTarHeader()} will create the correct header.
     *
     * @var array(ezcArchiveV7Header)
     */
    protected $headers;

    /**
     * Stores the block number where the header starts.
     *
     * The fileNumber is the index of the array.
     *
     * @var array(int)
     */
    protected $headerPositions;

    /**
     * Specifies if the archive contains null blocks.
     *
     * @var bool
     */
    protected $hasNullBlocks;

    /**
     * Stores the number of added blocks.
     *
     * @var int
     */
    protected $addedBlocks = 0;

    /**
     * Specifies if unreliable blocks were added.
     *
     * @var bool
     */
    protected $addedBlocksNotReliable = false;

    /**
     * Initializes the Tar and tries to read the first entry from the archive.
     *
     * At initialization it sets the blockFactor to $blockFactor. Each tar archive
     * has always $blockFactor of blocks ( 0, $blockFactor, 2 * $blockFactor, etc ).
     *
     * The Tar archive works with blocks, so therefore the first parameter expects
     * the archive as a blockFile.
     *
     * @param ezcArchiveBlockFile $file
     * @param int $blockFactor
     */
    public function __construct( ezcArchiveBlockFile $file, $blockFactor = 20 )
    {
        $this->blockFactor = $blockFactor;
        $this->file = $file;

        $this->headers = array();
        $this->headerPositions = array();

        $this->entriesRead = 0;
        $this->fileNumber = 0;

        $this->hasNullBlocks = $this->file->isNew() ? false : true;
        $this->addedBlocks = 0;

        if ( $this->file->getFileAccess() !== ezcArchiveFile::WRITE_ONLY )
        {
            $this->readCurrentFromArchive();
        }
    }

    /**
     * Closes the archive.
     */
    public function __destruct()
    {
        $this->close();
    }

    /**
     * Returns the value which specifies a TAR_V7 algorithm.
     *
     * @return int
     */
    public function getAlgorithm()
    {
        return self::TAR_V7;
    }

    /**
     * Returns true because the TAR_V7 algorithm can write.
     *
     * @see isWritable()
     *
     * @return bool
     */
    public function algorithmCanWrite()
    {
        return true;
    }

    /**
     * Creates the a new tar header for this class.
     *
     * Usually this class is reimplemented by other Tar algorithms, and therefore it returns another Tar
     * header.
     *
     * This method expects an {@link ezcArchiveBlockFile} that points to the header that should be
     * read (and created). If null is given as  block file, an empty header will be created.
     *
     * @param string|null $file
     * @return ezcArchiveV7Header  The ezcArchiveV7Header or a subclass is returned.
     */
    protected function createTarHeader( $file = null )
    {
        return new ezcArchiveV7Header( $file );
    }

    /**
     * Read the current entry from the archive.
     *
     * The current entry from the archive is read, if possible. This method will set the {@link $completed}
     * to true, if the end of the archive is reached. The {@link $entriesRead} will be increased, if the
     * entry is correctly read.
     *
     * @throws ezcArchiveBlockSizeException
     *         if the file is empty
     *         or if the file is not valid
     * @return bool
     */
    protected function readCurrentFromArchive()
    {
        // Not cached, read the next block.
        if ( $this->entriesRead == 0 )
        {
            $this->file->rewind();
            if ( !$this->file->isEmpty() && !$this->file->valid() )
            {
                throw new ezcArchiveBlockSizeException( $this->file->getFileName(),  "At least one block expected in tar archive" );
            }
        }
        else
        {
            // Search the new block.
            $newBlock = $this->headerPositions[ $this->fileNumber - 1 ] +  $this->file->getBlocksFromBytes( $this->headers[ $this->fileNumber - 1 ]->fileSize );

            // Search for that block.
            if ( $newBlock != $this->file->key() )
            {
                $this->file->seek( $newBlock );
            }

            // Read the new block.
            $this->file->next();
        }

        // This might be a null block.
        if ( !$this->file->valid() || $this->file->isNullBlock() )
        {
            $this->completed = true;
            return false;
        }

        $this->headers[ $this->fileNumber ] = $this->createTarHeader( $this->file );
        $this->headerPositions[ $this->fileNumber ] = $this->file->key();

        // Set the currentEntry information.
        $struct = new ezcArchiveFileStructure();
        $this->headers[ $this->fileNumber ]->setArchiveFileStructure( $struct );
        $this->entries[ $this->fileNumber ] = new ezcArchiveEntry( $struct );

        $this->entriesRead++;

        return true;
    }

    /**
     * Writes the file data from the current entry to the given file.
     *
     * @param string $targetPath  The absolute or relative path of the target file.
     * @return bool
     */
    protected function writeCurrentDataToFile( $targetPath )
    {
        if ( !$this->valid() )
        {
            return false;
        }

        $requestedBlock = $this->headerPositions[$this->fileNumber];
        $currentBlock = $this->file->key();
        if ( $currentBlock != $requestedBlock )
        {
            $this->file->seek( $requestedBlock );
        }

        $header = $this->headers[ $this->fileNumber ];

        if ( $header->fileSize > 0 )
        {
            $completeBlocks = ( int ) ( $header->fileSize / self::BLOCK_SIZE );
            $rest = ( $header->fileSize % self::BLOCK_SIZE );

            //  Write to file
            $fp = fopen( $targetPath, "w" );

            for ( $i = 0; $i < $completeBlocks; $i++ )
            {
                fwrite( $fp, $this->file->next() );
            }

            fwrite( $fp, $this->file->next(), $rest );
            fclose( $fp );
         }
         else
         {
             touch( $targetPath );
         }

         return true;
    }

    /**
     * Truncates the archive to $fileNumber of files.
     *
     * The $fileNumber parameter specifies the amount of files that should remain.
     * If the default value, zero, is used then the entire archive file is cleared.
     *
     * @throws ezcArchiveException
     *         if the archive is closed
     * @throws ezcBaseFilePermissionException
     *         if the file is read-only
     *         or if the current algorithm cannot write
     * @param int $fileNumber
     * @return bool
     */
    public function truncate( $fileNumber = 0 )
    {
        if ( $this->file === null )
        {
            throw new ezcArchiveException( "The archive is closed" );
        }

        if ( $this->file->getFileAccess() === ezcArchiveFile::READ_ONLY || !$this->algorithmCanWrite() )
        {
            throw new ezcBaseFilePermissionException( $this->file->getFileName(), ezcBaseFilePermissionException::WRITE, "Archive is read-only" );
        }

        $originalFileNumber = $this->fileNumber;
        $this->hasNullBlocks = false;
        $this->addedBlocksNotReliable = true;

        // Entirely empty the file.
        if ( $fileNumber == 0 )
        {
            $this->file->truncate();

            $this->entriesRead = 0;
            $this->fileNumber = 0;
            $this->completed = true;
        }
        else
        {
            $this->seek( $fileNumber ); // read the headers.
            $endBlockNumber = $this->headerPositions[ $fileNumber - 1 ] +  $this->file->getBlocksFromBytes( $this->headers[ $fileNumber - 1 ]->fileSize );

            if ( $endBlockNumber === false )
            {
                return false;
            }

            if ( !$this->file->truncate ( $endBlockNumber + 1 ) )
            {
                throw new ezcArchiveException( "The archive cannot be truncated to " . ( $endBlockNumber + 1 ) . " block(s). " .
                                               "This happens with write-only files or stream (e.g. compress.zlib) " );
            }

            $this->entriesRead = $fileNumber;
            $this->completed = true;
            $this->fileNumber = $originalFileNumber;

            return $this->valid();
        }
    }

    /**
     * Appends a file to the archive after the current entry.
     *
     * One or multiple files can be added directly after the current file.
     * The remaining entries after the current are removed from the archive!
     *
     * The $files can either be a string or an array of strings. Which, respectively, represents a
     * single file or multiple files.
     *
     * $prefix specifies the begin part of the $files path that should not be included in the archive.
     * The files in the archive are always stored relatively.
     *
     * Example:
     * <code>
     * $tar = ezcArchive( "/tmp/my_archive.tar", ezcArchive::TAR );
     *
     * // Append two files to the end of the archive.
     * $tar->seek( 0, SEEK_END );
     * $tar->appendToCurrent( array( "/home/rb/file1.txt", "/home/rb/file2.txt" ), "/home/rb/" );
     * </code>
     *
     * When multiple files are added to the archive at the same time, thus using an array, does not
     * necessarily produce the same archive as repeatively adding one file to the archive.
     * For example, the Tar archive format, can detect that files hardlink to each other and will store
     * it in a more efficient way.
     *
     * @throws ezcArchiveWriteException  if one of the files cannot be written to the archive.
     * @throws ezcFileReadException      if one of the files cannot be read from the local filesystem.
     * @throws ezcArchiveException       if the archive is closed.
     *
     * @param string|array(string) $files  Array or a single path to a file.
     * @param string $prefix               First part of the path used in $files.
     * @return bool
     */
    public function appendToCurrent( $files, $prefix )
    {
        if ( $this->file === null )
        {
            throw new ezcArchiveException( "The archive is closed" );
        }

        if ( $this->file->getFileAccess() !== ezcArchiveFile::READ_WRITE )
        {
            throw new ezcArchiveException( "Cannot appendToCurrent when writing to a read-only, write-only stream (e.g. compress.zlib)." );
        }

        if ( $this->file->getFileAccess() === ezcArchiveFile::READ_ONLY || !$this->algorithmCanWrite() )
        {
            throw new ezcBaseFilePermissionException( $this->file->getFileName(),  ezcBaseFilePermissionException::WRITE );
        }

        $entries = $this->getEntries( $files, $prefix );
        $originalFileNumber = $this->fileNumber;

        for ( $i = 0; $i < sizeof( $files ); $i++ )
        {
            // Changes the fileNumber
            $this->appendHeaderAndFileToCurrent( $entries[$i] );
        }

        $this->fileNumber = $originalFileNumber;
        return $this->valid();
    }

    /**
     * Append a file or directory to the end of the archive. Multiple files or directory can
     * be added to the archive when an array is used as input parameter.
     *
     * @see appendToCurrent()
     *
     * @throws ezcArchiveWriteException  if one of the files cannot be written to the archive.
     * @throws ezcFileReadException      if one of the files cannot be read from the local filesystem.
     * @throws ezcArchiveException       if the archive is closed.
     *
     * @param string|array(string) $files  Add the files and or directories to the archive.
     * @param string $prefix               First part of the path used in $files.
     * @return bool
     */
    public function append( $files, $prefix )
    {
        if ( $this->file === null )
        {
            throw new ezcArchiveException( "The archive is closed" );
        }

        if ( $this->file->getFileAccess() === ezcArchiveFile::READ_ONLY || !$this->algorithmCanWrite() )
        {
            throw new ezcArchiveException( "Archive is read-only" );
        }

        // Appending to an existing archive with a compressed stream does not work because we have to remove the NULL-blocks.
        if ( $this->hasNullBlocks && $this->file->getFileAccess() !== ezcArchiveFile::READ_WRITE )
        {
            throw new ezcArchiveException( "Cannot append to this archive" );
        }

        // Existing files need to be read, because we don't know if it contains NULL-blocks at the end of the archive.
        if ( $this->file->getFileAccess() !== ezcArchiveFile::WRITE_ONLY )
        {
            $this->seek( 0, SEEK_END );
        }

        // Do the same as in appendToCurrent(). But we know that it's possible.
        $entries = $this->getEntries( $files, $prefix );
        $originalFileNumber = $this->fileNumber;

        for ( $i = 0; $i < sizeof( $files ); $i++ )
        {
            // Changes the fileNumber
            $this->appendHeaderAndFileToCurrent( $entries[$i] );
        }

        $this->fileNumber = $originalFileNumber;
        return $this->valid();
     }

    /**
     * Closes the archive correctly.
     */
    public function close()
    {
        if ( $this->file !== null )
        {
            $this->writeEnd();

            $this->file->close();
            $this->file = null;
        }
    }

    /**
     * Writes the end of the archive.
     *
     * @throws ezcArchiveException
     *         if the archive is closed
     */
    public function writeEnd()
    {
        if ( $this->file === null )
        {
            throw new ezcArchiveException( "The archive is closed" );
        }

        if ( $this->file->isModified() )
        {
            if ( !$this->hasNullBlocks )
            {
                if ( $this->addedBlocksNotReliable )
                {
                    $this->appendNullBlocks();
                }
                else
                {
                    // Added Blocks  -  Added null blocks (Block factor 20)
                    // 0             -  0
                    // 1             - 19
                    // 19            - 1
                    // 20            - 0
                    // 21            - 19
                    $nullBlocks = ( $this->blockFactor - ( $this->addedBlocks % $this->blockFactor ) ) % $this->blockFactor;
                    $this->file->appendNullBlock( $nullBlocks );
                }

                $this->hasNullBlocks = true;
                $this->addedBlocksNotReliable = false;
                $this->addedBlocks = 0;
            }
        }
    }

    /**
     * Appends the given {@link ezcArchiveBlockFile} $file and {@link ezcArchiveEntry} $entry
     * to the archive file.
     *
     * The $entry will be used to create the correct header, whereas the $file contains the raw data
     * that should be append to the archive.
     *
     * @param ezcArchiveEntry $entry
     * @return bool
     */
    protected function appendHeaderAndFileToCurrent( $entry )
    {
        // Are we at a valid entry?
        if ( !$this->isEmpty() && !$this->valid() )
        {
            return false;
        }

        if ( !$this->isEmpty() && $this->file->getFileAccess() !== ezcArchiveFile::WRITE_ONLY )
        {
            // Truncate the next file and don't add the null blocks.
            $this->truncate( $this->fileNumber + 1, false );
        }

        if ( $this->entriesRead == 0 )
        {
            $this->fileNumber = 0;
        }
        else
        {
            $this->fileNumber++;
        }

        // Add the new header to the file map.
        $this->headers[ $this->fileNumber ] = $this->createTarHeader();
        $this->headers[ $this->fileNumber ]->setHeaderFromArchiveEntry( $entry );

        // Search the end of the block file, append encoded header, and search for the end-again.
        $this->file->seek( 0, SEEK_END );
        $this->headers[$this->fileNumber]->writeEncodedHeader( $this->file );

        // Add the new blocknumber to the map.
        $this->headerPositions[$this->fileNumber] = $this->file->key();

        // Append the file, if needed.
        $this->addedBlocks += 1;
        if ( $entry->getSize() > 0 )
        {
            $this->addedBlocks += $this->file->appendFile( $entry->getPath() );
        }

        if ( !( $this->file->isNew() && $this->file->getFileAccess() === ezcArchiveFile::WRITE_ONLY ) )
        {
            $this->addedBlocksNotReliable = true;
        }

        $this->hasNullBlocks = false;
        $this->completed = true;
        $this->entriesRead++;

        $this->entries[$this->fileNumber] = $entry;
        return true;
    }

    /**
     * Appends zero or more null blocks to the end of the archive, so that it matches the $blockFactor.
     *
     * If the archive has already the correct size, no null blocks will be appended. Otherwise as many
     * null blocks are appended (up to $blockFactor - 1) so that it matches the $blockFactor.
     *
     * @return void
     */
    protected function appendNullBlocks()
    {
        $last = 0;
        if ( $this->file->getLastBlockNumber() == -1 )
        {
            if ( !$this->file->valid() )
            {
                $this->file->rewind();
            }

            while ( $this->file->valid() )
            {
                $last = $this->file->key();
                $this->file->next();
            }
        }
        else
        {
            $last = $this->file->getLastBlockNumber();
        }

        $this->file->seek( $last );

        // Go to the end.
        /*
         */

        // echo ("Last block: " . $this->file->getLastBlockNumber() );

        // Need a ftell in the seek.
        // $this->file->seek( 0, SEEK_END );

        $blockNumber =  $last;

        // 0  .. 19 => first block.
        // 20 .. 39 => second block.
        // e.g: 20 - ( 35 % 20 ) - 1 = 19 - 15 = 4
        $append = $this->blockFactor - ( $blockNumber % $this->blockFactor ) - 1;
        $this->file->appendNullBlock( $append );
    }
}
?>
PK��Z��
--ezc/File/file_autoload.phpnu�[���<?php
/**
 * Autoloader definition for the File component.
 *
 * @copyright Copyright (C) 2005-2007 eZ systems as. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @version 1.2
 * @filesource
 * @package File
 */

return array(
    'ezcFile' => 'File/file.php',
);
?>
PK��Z��K��ezc/File/file.phpnu�[���<?php
/**
 * @copyright Copyright (C) 2005-2007 eZ systems as. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @version 1.2
 * @filesource
 * @package File
 */

/**
 * Provides a selection of static independent methods to provide functionality
 * for file and file system handling. This class is deprecated, please use
 * ezcBaseFile instead.
 *
 * @package File
 * @version 1.2
 * @apichange Has been deprecated by ezcBaseFile
 */
class ezcFile extends ezcBaseFile
{
}
?>
PK��Z��5�
�
!ezc/autoload/archive_autoload.phpnu�[���<?php
/**
 * Autoloader definition for the Archive component.
 *
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @version 1.4.1
 * @filesource
 * @package Archive
 */

return array(
    'ezcArchiveException'                 => 'Archive/exceptions/exception.php',
    'ezcArchiveBlockSizeException'        => 'Archive/exceptions/block_size.php',
    'ezcArchiveChecksumException'         => 'Archive/exceptions/checksum.php',
    'ezcArchiveEmptyException'            => 'Archive/exceptions/empty.php',
    'ezcArchiveEntryPrefixException'      => 'Archive/exceptions/entry_prefix.php',
    'ezcArchiveInternalException'         => 'Archive/exceptions/internal_exception.php',
    'ezcArchiveIoException'               => 'Archive/exceptions/io.php',
    'ezcArchiveUnknownTypeException'      => 'Archive/exceptions/unknown_type.php',
    'ezcArchiveValueException'            => 'Archive/exceptions/value.php',
    'ezcArchive'                          => 'Archive/archive.php',
    'ezcArchiveV7Header'                  => 'Archive/tar/headers/v7.php',
    'ezcArchiveV7Tar'                     => 'Archive/tar/v7.php',
    'ezcArchiveFile'                      => 'Archive/file/file.php',
    'ezcArchiveLocalFileHeader'           => 'Archive/zip/headers/local_file.php',
    'ezcArchiveUstarHeader'               => 'Archive/tar/headers/ustar.php',
    'ezcArchiveUstarTar'                  => 'Archive/tar/ustar.php',
    'ezcArchiveBlockFile'                 => 'Archive/file/block_file.php',
    'ezcArchiveCallback'                  => 'Archive/interfaces/callback.php',
    'ezcArchiveCentralDirectoryEndHeader' => 'Archive/zip/headers/central_directory_end.php',
    'ezcArchiveCentralDirectoryHeader'    => 'Archive/zip/headers/central_directory.php',
    'ezcArchiveCharacterFile'             => 'Archive/file/character_file.php',
    'ezcArchiveChecksums'                 => 'Archive/utils/checksums.php',
    'ezcArchiveEntry'                     => 'Archive/entry.php',
    'ezcArchiveFileStructure'             => 'Archive/structs/file.php',
    'ezcArchiveFileType'                  => 'Archive/utils/file_type.php',
    'ezcArchiveGnuHeader'                 => 'Archive/tar/headers/gnu.php',
    'ezcArchiveGnuTar'                    => 'Archive/tar/gnu.php',
    'ezcArchiveOptions'                   => 'Archive/options/archive.php',
    'ezcArchivePaxHeader'                 => 'Archive/tar/headers/pax.php',
    'ezcArchivePaxTar'                    => 'Archive/tar/pax.php',
    'ezcArchiveStatMode'                  => 'Archive/utils/stat_mode.php',
    'ezcArchiveZip'                       => 'Archive/zip/zip.php',
);
?>
PK��Z5���tt!ezc/autoload/console_autoload.phpnu�[���<?php
/**
 * Autoloader definition for the ConsoleTools component.
 *
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @version 1.6.1
 * @filesource
 * @package ConsoleTools
 */

return array(
    'ezcConsoleException'                           => 'ConsoleTools/exceptions/exception.php',
    'ezcConsoleArgumentException'                   => 'ConsoleTools/exceptions/argument.php',
    'ezcConsoleOptionException'                     => 'ConsoleTools/exceptions/option.php',
    'ezcConsoleArgumentAlreadyRegisteredException'  => 'ConsoleTools/exceptions/argument_already_registered.php',
    'ezcConsoleArgumentMandatoryViolationException' => 'ConsoleTools/exceptions/argument_mandatory_violation.php',
    'ezcConsoleArgumentTypeViolationException'      => 'ConsoleTools/exceptions/argument_type_violation.php',
    'ezcConsoleDialogAbortException'                => 'ConsoleTools/exceptions/dialog_abort.php',
    'ezcConsoleInvalidOptionNameException'          => 'ConsoleTools/exceptions/invalid_option_name.php',
    'ezcConsoleInvalidOutputTargetException'        => 'ConsoleTools/exceptions/invalid_output_target.php',
    'ezcConsoleNoPositionStoredException'           => 'ConsoleTools/exceptions/no_position_stored.php',
    'ezcConsoleNoValidDialogResultException'        => 'ConsoleTools/exceptions/no_valid_dialog_result.php',
    'ezcConsoleOptionAlreadyRegisteredException'    => 'ConsoleTools/exceptions/option_already_registered.php',
    'ezcConsoleOptionArgumentsViolationException'   => 'ConsoleTools/exceptions/option_arguments_violation.php',
    'ezcConsoleOptionDependencyViolationException'  => 'ConsoleTools/exceptions/option_dependency_violation.php',
    'ezcConsoleOptionExclusionViolationException'   => 'ConsoleTools/exceptions/option_exclusion_violation.php',
    'ezcConsoleOptionMandatoryViolationException'   => 'ConsoleTools/exceptions/option_mandatory_violation.php',
    'ezcConsoleOptionMissingValueException'         => 'ConsoleTools/exceptions/option_missing_value.php',
    'ezcConsoleOptionNoAliasException'              => 'ConsoleTools/exceptions/option_no_alias.php',
    'ezcConsoleOptionNotExistsException'            => 'ConsoleTools/exceptions/option_not_exists.php',
    'ezcConsoleOptionStringNotWellformedException'  => 'ConsoleTools/exceptions/option_string_not_wellformed.php',
    'ezcConsoleOptionTooManyValuesException'        => 'ConsoleTools/exceptions/option_too_many_values.php',
    'ezcConsoleOptionTypeViolationException'        => 'ConsoleTools/exceptions/option_type_violation.php',
    'ezcConsoleTooManyArgumentsException'           => 'ConsoleTools/exceptions/argument_too_many.php',
    'ezcConsoleDialogValidator'                     => 'ConsoleTools/interfaces/dialog_validator.php',
    'ezcConsoleQuestionDialogValidator'             => 'ConsoleTools/interfaces/question_dialog_validator.php',
    'ezcConsoleDialog'                              => 'ConsoleTools/interfaces/dialog.php',
    'ezcConsoleDialogOptions'                       => 'ConsoleTools/options/dialog.php',
    'ezcConsoleInputHelpGenerator'                  => 'ConsoleTools/interfaces/input_help_generator.php',
    'ezcConsoleInputValidator'                      => 'ConsoleTools/interfaces/input_validator.php',
    'ezcConsoleMenuDialogValidator'                 => 'ConsoleTools/interfaces/menu_dialog_validator.php',
    'ezcConsoleQuestionDialogCollectionValidator'   => 'ConsoleTools/dialog/validators/question_dialog_collection.php',
    'ezcConsoleArgument'                            => 'ConsoleTools/input/argument.php',
    'ezcConsoleArguments'                           => 'ConsoleTools/input/arguments.php',
    'ezcConsoleDialogViewer'                        => 'ConsoleTools/dialog_viewer.php',
    'ezcConsoleInput'                               => 'ConsoleTools/input.php',
    'ezcConsoleInputStandardHelpGenerator'          => 'ConsoleTools/input/help_generators/standard.php',
    'ezcConsoleMenuDialog'                          => 'ConsoleTools/dialog/menu_dialog.php',
    'ezcConsoleMenuDialogDefaultValidator'          => 'ConsoleTools/dialog/validators/menu_dialog_default.php',
    'ezcConsoleMenuDialogOptions'                   => 'ConsoleTools/options/menu_dialog.php',
    'ezcConsoleOption'                              => 'ConsoleTools/input/option.php',
    'ezcConsoleOptionRule'                          => 'ConsoleTools/structs/option_rule.php',
    'ezcConsoleOutput'                              => 'ConsoleTools/output.php',
    'ezcConsoleOutputFormat'                        => 'ConsoleTools/structs/output_format.php',
    'ezcConsoleOutputFormats'                       => 'ConsoleTools/structs/output_formats.php',
    'ezcConsoleOutputOptions'                       => 'ConsoleTools/options/output.php',
    'ezcConsoleProgressMonitor'                     => 'ConsoleTools/progressmonitor.php',
    'ezcConsoleProgressMonitorOptions'              => 'ConsoleTools/options/progressmonitor.php',
    'ezcConsoleProgressbar'                         => 'ConsoleTools/progressbar.php',
    'ezcConsoleProgressbarOptions'                  => 'ConsoleTools/options/progressbar.php',
    'ezcConsoleQuestionDialog'                      => 'ConsoleTools/dialog/question_dialog.php',
    'ezcConsoleQuestionDialogMappingValidator'      => 'ConsoleTools/dialog/validators/question_dialog_mapping.php',
    'ezcConsoleQuestionDialogOptions'               => 'ConsoleTools/options/question_dialog.php',
    'ezcConsoleQuestionDialogRegexValidator'        => 'ConsoleTools/dialog/validators/question_dialog_regex.php',
    'ezcConsoleQuestionDialogTypeValidator'         => 'ConsoleTools/dialog/validators/question_dialog_type.php',
    'ezcConsoleStandardInputValidator'              => 'ConsoleTools/input/validators/standard.php',
    'ezcConsoleStatusbar'                           => 'ConsoleTools/statusbar.php',
    'ezcConsoleStatusbarOptions'                    => 'ConsoleTools/options/statusbar.php',
    'ezcConsoleStringTool'                          => 'ConsoleTools/tools/string.php',
    'ezcConsoleTable'                               => 'ConsoleTools/table.php',
    'ezcConsoleTableCell'                           => 'ConsoleTools/table/cell.php',
    'ezcConsoleTableOptions'                        => 'ConsoleTools/options/table.php',
    'ezcConsoleTableRow'                            => 'ConsoleTools/table/row.php',
);
?>
PK��Z��
--ezc/autoload/file_autoload.phpnu�[���<?php
/**
 * Autoloader definition for the File component.
 *
 * @copyright Copyright (C) 2005-2007 eZ systems as. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @version 1.2
 * @filesource
 * @package File
 */

return array(
    'ezcFile' => 'File/file.php',
);
?>
PK��Z�%�NNezc/autoload/base_autoload.phpnu�[���<?php
/**
 * Autoloader definition for the Base component.
 *
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 * @version 1.8
 * @filesource
 * @package Base
 */

return array(
    'ezcBaseException'                            => 'Base/exceptions/exception.php',
    'ezcBaseFileException'                        => 'Base/exceptions/file_exception.php',
    'ezcBaseAutoloadException'                    => 'Base/exceptions/autoload.php',
    'ezcBaseDoubleClassRepositoryPrefixException' => 'Base/exceptions/double_class_repository_prefix.php',
    'ezcBaseExtensionNotFoundException'           => 'Base/exceptions/extension_not_found.php',
    'ezcBaseFileIoException'                      => 'Base/exceptions/file_io.php',
    'ezcBaseFileNotFoundException'                => 'Base/exceptions/file_not_found.php',
    'ezcBaseFilePermissionException'              => 'Base/exceptions/file_permission.php',
    'ezcBaseFunctionalityNotSupportedException'   => 'Base/exceptions/functionality_not_supported.php',
    'ezcBaseInitCallbackConfiguredException'      => 'Base/exceptions/init_callback_configured.php',
    'ezcBaseInitInvalidCallbackClassException'    => 'Base/exceptions/invalid_callback_class.php',
    'ezcBaseInvalidParentClassException'          => 'Base/exceptions/invalid_parent_class.php',
    'ezcBasePropertyNotFoundException'            => 'Base/exceptions/property_not_found.php',
    'ezcBasePropertyPermissionException'          => 'Base/exceptions/property_permission.php',
    'ezcBaseSettingNotFoundException'             => 'Base/exceptions/setting_not_found.php',
    'ezcBaseSettingValueException'                => 'Base/exceptions/setting_value.php',
    'ezcBaseValueException'                       => 'Base/exceptions/value.php',
    'ezcBaseWhateverException'                    => 'Base/exceptions/whatever.php',
    'ezcBaseOptions'                              => 'Base/options.php',
    'ezcBaseStruct'                               => 'Base/struct.php',
    'ezcBase'                                     => 'Base/base.php',
    'ezcBaseAutoloadOptions'                      => 'Base/options/autoload.php',
    'ezcBaseConfigurationInitializer'             => 'Base/interfaces/configuration_initializer.php',
    'ezcBaseExportable'                           => 'Base/interfaces/exportable.php',
    'ezcBaseFeatures'                             => 'Base/features.php',
    'ezcBaseFile'                                 => 'Base/file.php',
    'ezcBaseFileFindContext'                      => 'Base/structs/file_find_context.php',
    'ezcBaseInit'                                 => 'Base/init.php',
    'ezcBaseMetaData'                             => 'Base/metadata.php',
    'ezcBaseMetaDataPearReader'                   => 'Base/metadata/pear.php',
    'ezcBaseMetaDataTarballReader'                => 'Base/metadata/tarball.php',
    'ezcBasePersistable'                          => 'Base/interfaces/persistable.php',
    'ezcBaseRepositoryDirectory'                  => 'Base/structs/repository_directory.php',
);
?>
PK��Z���=YYArchive/Tar.phpnu�[���<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */

/**
 * File::CSV
 *
 * PHP versions 4 and 5
 *
 * Copyright (c) 1997-2008,
 * Vincent Blavet <vincent@phpconcept.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  File_Formats
 * @package   Archive_Tar
 * @author    Vincent Blavet <vincent@phpconcept.net>
 * @copyright 1997-2010 The Authors
 * @license   http://www.opensource.org/licenses/bsd-license.php New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/Archive_Tar
 */

// If the PEAR class cannot be loaded via the autoloader,
// then try to require_once it from the PHP include path.
if (!class_exists('PEAR')) {
    require_once 'PEAR.php';
}

define('ARCHIVE_TAR_ATT_SEPARATOR', 90001);
define('ARCHIVE_TAR_END_BLOCK', pack("a512", ''));

if (!function_exists('gzopen') && function_exists('gzopen64')) {
    function gzopen($filename, $mode, $use_include_path = 0)
    {
        return gzopen64($filename, $mode, $use_include_path);
    }
}

if (!function_exists('gztell') && function_exists('gztell64')) {
    function gztell($zp)
    {
        return gztell64($zp);
    }
}

if (!function_exists('gzseek') && function_exists('gzseek64')) {
    function gzseek($zp, $offset, $whence = SEEK_SET)
    {
        return gzseek64($zp, $offset, $whence);
    }
}

/**
 * Creates a (compressed) Tar archive
 *
 * @package Archive_Tar
 * @author  Vincent Blavet <vincent@phpconcept.net>
 * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
 * @version $Revision$
 */
class Archive_Tar extends PEAR
{
    /**
     * @var string Name of the Tar
     */
    public $_tarname = '';

    /**
     * @var boolean if true, the Tar file will be gzipped
     */
    public $_compress = false;

    /**
     * @var string Type of compression : 'none', 'gz', 'bz2' or 'lzma2'
     */
    public $_compress_type = 'none';

    /**
     * @var string Explode separator
     */
    public $_separator = ' ';

    /**
     * @var file descriptor
     */
    public $_file = 0;

    /**
     * @var string Local Tar name of a remote Tar (http:// or ftp://)
     */
    public $_temp_tarname = '';

    /**
     * @var string regular expression for ignoring files or directories
     */
    public $_ignore_regexp = '';

    /**
     * @var object PEAR_Error object
     */
    public $error_object = null;

    /**
     * Format for data extraction
     *
     * @var string
     */
    public $_fmt = '';

    /**
     * @var int Length of the read buffer in bytes
     */
    protected $buffer_length;

    /**
     * Archive_Tar Class constructor. This flavour of the constructor only
     * declare a new Archive_Tar object, identifying it by the name of the
     * tar file.
     * If the compress argument is set the tar will be read or created as a
     * gzip or bz2 compressed TAR file.
     *
     * @param string $p_tarname The name of the tar archive to create
     * @param string $p_compress can be null, 'gz', 'bz2' or 'lzma2'. This
     *               parameter indicates if gzip, bz2 or lzma2 compression
     *               is required.  For compatibility reason the
     *               boolean value 'true' means 'gz'.
     * @param int $buffer_length Length of the read buffer in bytes
     *
     * @return bool
     */
    public function __construct($p_tarname, $p_compress = null, $buffer_length = 512)
    {
        parent::__construct();

        $this->_compress = false;
        $this->_compress_type = 'none';
        if (($p_compress === null) || ($p_compress == '')) {
            if (@file_exists($p_tarname)) {
                if ($fp = @fopen($p_tarname, "rb")) {
                    // look for gzip magic cookie
                    $data = fread($fp, 2);
                    fclose($fp);
                    if ($data == "\37\213") {
                        $this->_compress = true;
                        $this->_compress_type = 'gz';
                        // No sure it's enought for a magic code ....
                    } elseif ($data == "BZ") {
                        $this->_compress = true;
                        $this->_compress_type = 'bz2';
                    } elseif (file_get_contents($p_tarname, false, null, 1, 4) == '7zXZ') {
                        $this->_compress = true;
                        $this->_compress_type = 'lzma2';
                    }
                }
            } else {
                // probably a remote file or some file accessible
                // through a stream interface
                if (substr($p_tarname, -2) == 'gz') {
                    $this->_compress = true;
                    $this->_compress_type = 'gz';
                } elseif ((substr($p_tarname, -3) == 'bz2') ||
                    (substr($p_tarname, -2) == 'bz')
                ) {
                    $this->_compress = true;
                    $this->_compress_type = 'bz2';
                } else {
                    if (substr($p_tarname, -2) == 'xz') {
                        $this->_compress = true;
                        $this->_compress_type = 'lzma2';
                    }
                }
            }
        } else {
            if (($p_compress === true) || ($p_compress == 'gz')) {
                $this->_compress = true;
                $this->_compress_type = 'gz';
            } else {
                if ($p_compress == 'bz2') {
                    $this->_compress = true;
                    $this->_compress_type = 'bz2';
                } else {
                    if ($p_compress == 'lzma2') {
                        $this->_compress = true;
                        $this->_compress_type = 'lzma2';
                    } else {
                        $this->_error(
                            "Unsupported compression type '$p_compress'\n" .
                            "Supported types are 'gz', 'bz2' and 'lzma2'.\n"
                        );
                        return false;
                    }
                }
            }
        }
        $this->_tarname = $p_tarname;
        if ($this->_compress) { // assert zlib or bz2 or xz extension support
            if ($this->_compress_type == 'gz') {
                $extname = 'zlib';
            } else {
                if ($this->_compress_type == 'bz2') {
                    $extname = 'bz2';
                } else {
                    if ($this->_compress_type == 'lzma2') {
                        $extname = 'xz';
                    }
                }
            }

            if (!extension_loaded($extname)) {
                PEAR::loadExtension($extname);
            }
            if (!extension_loaded($extname)) {
                $this->_error(
                    "The extension '$extname' couldn't be found.\n" .
                    "Please make sure your version of PHP was built " .
                    "with '$extname' support.\n"
                );
                return false;
            }
        }


        if (version_compare(PHP_VERSION, "5.5.0-dev") < 0) {
            $this->_fmt = "a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/" .
                "a8checksum/a1typeflag/a100link/a6magic/a2version/" .
                "a32uname/a32gname/a8devmajor/a8devminor/a131prefix";
        } else {
            $this->_fmt = "Z100filename/Z8mode/Z8uid/Z8gid/Z12size/Z12mtime/" .
                "Z8checksum/Z1typeflag/Z100link/Z6magic/Z2version/" .
                "Z32uname/Z32gname/Z8devmajor/Z8devminor/Z131prefix";
        }


        $this->buffer_length = $buffer_length;
    }

    public function __destruct()
    {
        $this->_close();
        // ----- Look for a local copy to delete
        if ($this->_temp_tarname != '' && (bool) preg_match('/^tar[[:alnum:]]*\.tmp$/', $this->_temp_tarname)) {
            @unlink($this->_temp_tarname);
        }
    }

    /**
     * This method creates the archive file and add the files / directories
     * that are listed in $p_filelist.
     * If a file with the same name exist and is writable, it is replaced
     * by the new tar.
     * The method return false and a PEAR error text.
     * The $p_filelist parameter can be an array of string, each string
     * representing a filename or a directory name with their path if
     * needed. It can also be a single string with names separated by a
     * single blank.
     * For each directory added in the archive, the files and
     * sub-directories are also added.
     * See also createModify() method for more details.
     *
     * @param array $p_filelist An array of filenames and directory names, or a
     *              single string with names separated by a single
     *              blank space.
     *
     * @return true on success, false on error.
     * @see    createModify()
     */
    public function create($p_filelist)
    {
        return $this->createModify($p_filelist, '', '');
    }

    /**
     * This method add the files / directories that are listed in $p_filelist in
     * the archive. If the archive does not exist it is created.
     * The method return false and a PEAR error text.
     * The files and directories listed are only added at the end of the archive,
     * even if a file with the same name is already archived.
     * See also createModify() method for more details.
     *
     * @param array $p_filelist An array of filenames and directory names, or a
     *              single string with names separated by a single
     *              blank space.
     *
     * @return true on success, false on error.
     * @see    createModify()
     * @access public
     */
    public function add($p_filelist)
    {
        return $this->addModify($p_filelist, '', '');
    }

    /**
     * @param string $p_path
     * @param bool $p_preserve
     * @param bool $p_symlinks
     * @return bool
     */
    public function extract($p_path = '', $p_preserve = false, $p_symlinks = true)
    {
        return $this->extractModify($p_path, '', $p_preserve, $p_symlinks);
    }

    /**
     * @return array|int
     */
    public function listContent()
    {
        $v_list_detail = array();

        if ($this->_openRead()) {
            if (!$this->_extractList('', $v_list_detail, "list", '', '')) {
                unset($v_list_detail);
                $v_list_detail = 0;
            }
            $this->_close();
        }

        return $v_list_detail;
    }

    /**
     * This method creates the archive file and add the files / directories
     * that are listed in $p_filelist.
     * If the file already exists and is writable, it is replaced by the
     * new tar. It is a create and not an add. If the file exists and is
     * read-only or is a directory it is not replaced. The method return
     * false and a PEAR error text.
     * The $p_filelist parameter can be an array of string, each string
     * representing a filename or a directory name with their path if
     * needed. It can also be a single string with names separated by a
     * single blank.
     * The path indicated in $p_remove_dir will be removed from the
     * memorized path of each file / directory listed when this path
     * exists. By default nothing is removed (empty path '')
     * The path indicated in $p_add_dir will be added at the beginning of
     * the memorized path of each file / directory listed. However it can
     * be set to empty ''. The adding of a path is done after the removing
     * of path.
     * The path add/remove ability enables the user to prepare an archive
     * for extraction in a different path than the origin files are.
     * See also addModify() method for file adding properties.
     *
     * @param array $p_filelist An array of filenames and directory names,
     *                             or a single string with names separated by
     *                             a single blank space.
     * @param string $p_add_dir A string which contains a path to be added
     *                             to the memorized path of each element in
     *                             the list.
     * @param string $p_remove_dir A string which contains a path to be
     *                             removed from the memorized path of each
     *                             element in the list, when relevant.
     *
     * @return boolean true on success, false on error.
     * @see addModify()
     */
    public function createModify($p_filelist, $p_add_dir, $p_remove_dir = '')
    {
        $v_result = true;

        if (!$this->_openWrite()) {
            return false;
        }

        if ($p_filelist != '') {
            if (is_array($p_filelist)) {
                $v_list = $p_filelist;
            } elseif (is_string($p_filelist)) {
                $v_list = explode($this->_separator, $p_filelist);
            } else {
                $this->_cleanFile();
                $this->_error('Invalid file list');
                return false;
            }

            $v_result = $this->_addList($v_list, $p_add_dir, $p_remove_dir);
        }

        if ($v_result) {
            $this->_writeFooter();
            $this->_close();
        } else {
            $this->_cleanFile();
        }

        return $v_result;
    }

    /**
     * This method add the files / directories listed in $p_filelist at the
     * end of the existing archive. If the archive does not yet exists it
     * is created.
     * The $p_filelist parameter can be an array of string, each string
     * representing a filename or a directory name with their path if
     * needed. It can also be a single string with names separated by a
     * single blank.
     * The path indicated in $p_remove_dir will be removed from the
     * memorized path of each file / directory listed when this path
     * exists. By default nothing is removed (empty path '')
     * The path indicated in $p_add_dir will be added at the beginning of
     * the memorized path of each file / directory listed. However it can
     * be set to empty ''. The adding of a path is done after the removing
     * of path.
     * The path add/remove ability enables the user to prepare an archive
     * for extraction in a different path than the origin files are.
     * If a file/dir is already in the archive it will only be added at the
     * end of the archive. There is no update of the existing archived
     * file/dir. However while extracting the archive, the last file will
     * replace the first one. This results in a none optimization of the
     * archive size.
     * If a file/dir does not exist the file/dir is ignored. However an
     * error text is send to PEAR error.
     * If a file/dir is not readable the file/dir is ignored. However an
     * error text is send to PEAR error.
     *
     * @param array $p_filelist An array of filenames and directory
     *                             names, or a single string with names
     *                             separated by a single blank space.
     * @param string $p_add_dir A string which contains a path to be
     *                             added to the memorized path of each
     *                             element in the list.
     * @param string $p_remove_dir A string which contains a path to be
     *                             removed from the memorized path of
     *                             each element in the list, when
     *                             relevant.
     *
     * @return true on success, false on error.
     */
    public function addModify($p_filelist, $p_add_dir, $p_remove_dir = '')
    {
        $v_result = true;

        if (!$this->_isArchive()) {
            $v_result = $this->createModify(
                $p_filelist,
                $p_add_dir,
                $p_remove_dir
            );
        } else {
            if (is_array($p_filelist)) {
                $v_list = $p_filelist;
            } elseif (is_string($p_filelist)) {
                $v_list = explode($this->_separator, $p_filelist);
            } else {
                $this->_error('Invalid file list');
                return false;
            }

            $v_result = $this->_append($v_list, $p_add_dir, $p_remove_dir);
        }

        return $v_result;
    }

    /**
     * This method add a single string as a file at the
     * end of the existing archive. If the archive does not yet exists it
     * is created.
     *
     * @param string $p_filename A string which contains the full
     *                           filename path that will be associated
     *                           with the string.
     * @param string $p_string The content of the file added in
     *                           the archive.
     * @param bool|int $p_datetime A custom date/time (unix timestamp)
     *                           for the file (optional).
     * @param array $p_params An array of optional params:
     *                               stamp => the datetime (replaces
     *                                   datetime above if it exists)
     *                               mode => the permissions on the
     *                                   file (600 by default)
     *                               type => is this a link?  See the
     *                                   tar specification for details.
     *                                   (default = regular file)
     *                               uid => the user ID of the file
     *                                   (default = 0 = root)
     *                               gid => the group ID of the file
     *                                   (default = 0 = root)
     *
     * @return true on success, false on error.
     */
    public function addString($p_filename, $p_string, $p_datetime = false, $p_params = array())
    {
        $p_stamp = @$p_params["stamp"] ? $p_params["stamp"] : ($p_datetime ? $p_datetime : time());
        $p_mode = @$p_params["mode"] ? $p_params["mode"] : 0600;
        $p_type = @$p_params["type"] ? $p_params["type"] : "";
        $p_uid = @$p_params["uid"] ? $p_params["uid"] : "";
        $p_gid = @$p_params["gid"] ? $p_params["gid"] : "";
        $v_result = true;

        if (!$this->_isArchive()) {
            if (!$this->_openWrite()) {
                return false;
            }
            $this->_close();
        }

        if (!$this->_openAppend()) {
            return false;
        }

        // Need to check the get back to the temporary file ? ....
        $v_result = $this->_addString($p_filename, $p_string, $p_datetime, $p_params);

        $this->_writeFooter();

        $this->_close();

        return $v_result;
    }

    /**
     * This method extract all the content of the archive in the directory
     * indicated by $p_path. When relevant the memorized path of the
     * files/dir can be modified by removing the $p_remove_path path at the
     * beginning of the file/dir path.
     * While extracting a file, if the directory path does not exists it is
     * created.
     * While extracting a file, if the file already exists it is replaced
     * without looking for last modification date.
     * While extracting a file, if the file already exists and is write
     * protected, the extraction is aborted.
     * While extracting a file, if a directory with the same name already
     * exists, the extraction is aborted.
     * While extracting a directory, if a file with the same name already
     * exists, the extraction is aborted.
     * While extracting a file/directory if the destination directory exist
     * and is write protected, or does not exist but can not be created,
     * the extraction is aborted.
     * If after extraction an extracted file does not show the correct
     * stored file size, the extraction is aborted.
     * When the extraction is aborted, a PEAR error text is set and false
     * is returned. However the result can be a partial extraction that may
     * need to be manually cleaned.
     *
     * @param string $p_path The path of the directory where the
     *                               files/dir need to by extracted.
     * @param string $p_remove_path Part of the memorized path that can be
     *                               removed if present at the beginning of
     *                               the file/dir path.
     * @param boolean $p_preserve Preserve user/group ownership of files
     * @param boolean $p_symlinks Allow symlinks.
     *
     * @return boolean true on success, false on error.
     * @see    extractList()
     */
    public function extractModify($p_path, $p_remove_path, $p_preserve = false, $p_symlinks = true)
    {
        $v_result = true;
        $v_list_detail = array();

        if ($v_result = $this->_openRead()) {
            $v_result = $this->_extractList(
                $p_path,
                $v_list_detail,
                "complete",
                0,
                $p_remove_path,
                $p_preserve,
                $p_symlinks
            );
            $this->_close();
        }

        return $v_result;
    }

    /**
     * This method extract from the archive one file identified by $p_filename.
     * The return value is a string with the file content, or NULL on error.
     *
     * @param string $p_filename The path of the file to extract in a string.
     *
     * @return a string with the file content or NULL.
     */
    public function extractInString($p_filename)
    {
        if ($this->_openRead()) {
            $v_result = $this->_extractInString($p_filename);
            $this->_close();
        } else {
            $v_result = null;
        }

        return $v_result;
    }

    /**
     * This method extract from the archive only the files indicated in the
     * $p_filelist. These files are extracted in the current directory or
     * in the directory indicated by the optional $p_path parameter.
     * If indicated the $p_remove_path can be used in the same way as it is
     * used in extractModify() method.
     *
     * @param array $p_filelist An array of filenames and directory names,
     *                               or a single string with names separated
     *                               by a single blank space.
     * @param string $p_path The path of the directory where the
     *                               files/dir need to by extracted.
     * @param string $p_remove_path Part of the memorized path that can be
     *                               removed if present at the beginning of
     *                               the file/dir path.
     * @param boolean $p_preserve Preserve user/group ownership of files
     * @param boolean $p_symlinks Allow symlinks.
     *
     * @return true on success, false on error.
     * @see    extractModify()
     */
    public function extractList($p_filelist, $p_path = '', $p_remove_path = '', $p_preserve = false, $p_symlinks = true)
    {
        $v_result = true;
        $v_list_detail = array();

        if (is_array($p_filelist)) {
            $v_list = $p_filelist;
        } elseif (is_string($p_filelist)) {
            $v_list = explode($this->_separator, $p_filelist);
        } else {
            $this->_error('Invalid string list');
            return false;
        }

        if ($v_result = $this->_openRead()) {
            $v_result = $this->_extractList(
                $p_path,
                $v_list_detail,
                "partial",
                $v_list,
                $p_remove_path,
                $p_preserve,
                $p_symlinks
            );
            $this->_close();
        }

        return $v_result;
    }

    /**
     * This method set specific attributes of the archive. It uses a variable
     * list of parameters, in the format attribute code + attribute values :
     * $arch->setAttribute(ARCHIVE_TAR_ATT_SEPARATOR, ',');
     *
     * @return true on success, false on error.
     */
    public function setAttribute()
    {
        $v_result = true;

        // ----- Get the number of variable list of arguments
        if (($v_size = func_num_args()) == 0) {
            return true;
        }

        // ----- Get the arguments
        $v_att_list = func_get_args();

        // ----- Read the attributes
        $i = 0;
        while ($i < $v_size) {

            // ----- Look for next option
            switch ($v_att_list[$i]) {
                // ----- Look for options that request a string value
                case ARCHIVE_TAR_ATT_SEPARATOR :
                    // ----- Check the number of parameters
                    if (($i + 1) >= $v_size) {
                        $this->_error(
                            'Invalid number of parameters for '
                            . 'attribute ARCHIVE_TAR_ATT_SEPARATOR'
                        );
                        return false;
                    }

                    // ----- Get the value
                    $this->_separator = $v_att_list[$i + 1];
                    $i++;
                    break;

                default :
                    $this->_error('Unknown attribute code ' . $v_att_list[$i] . '');
                    return false;
            }

            // ----- Next attribute
            $i++;
        }

        return $v_result;
    }

    /**
     * This method sets the regular expression for ignoring files and directories
     * at import, for example:
     * $arch->setIgnoreRegexp("#CVS|\.svn#");
     *
     * @param string $regexp regular expression defining which files or directories to ignore
     */
    public function setIgnoreRegexp($regexp)
    {
        $this->_ignore_regexp = $regexp;
    }

    /**
     * This method sets the regular expression for ignoring all files and directories
     * matching the filenames in the array list at import, for example:
     * $arch->setIgnoreList(array('CVS', '.svn', 'bin/tool'));
     *
     * @param array $list a list of file or directory names to ignore
     *
     * @access public
     */
    public function setIgnoreList($list)
    {
        $list = str_replace(array('#', '.', '^', '$'), array('\#', '\.', '\^', '\$'), $list);
        $regexp = '#/' . join('$|/', $list) . '#';
        $this->setIgnoreRegexp($regexp);
    }

    /**
     * @param string $p_message
     */
    public function _error($p_message)
    {
        $this->error_object = $this->raiseError($p_message);
    }

    /**
     * @param string $p_message
     */
    public function _warning($p_message)
    {
        $this->error_object = $this->raiseError($p_message);
    }

    /**
     * @param string $p_filename
     * @return bool
     */
    public function _isArchive($p_filename = null)
    {
        if ($p_filename == null) {
            $p_filename = $this->_tarname;
        }
        clearstatcache();
        return @is_file($p_filename) && !@is_link($p_filename);
    }

    /**
     * @return bool
     */
    public function _openWrite()
    {
        if ($this->_compress_type == 'gz' && function_exists('gzopen')) {
            $this->_file = @gzopen($this->_tarname, "wb9");
        } else {
            if ($this->_compress_type == 'bz2' && function_exists('bzopen')) {
                $this->_file = @bzopen($this->_tarname, "w");
            } else {
                if ($this->_compress_type == 'lzma2' && function_exists('xzopen')) {
                    $this->_file = @xzopen($this->_tarname, 'w');
                } else {
                    if ($this->_compress_type == 'none') {
                        $this->_file = @fopen($this->_tarname, "wb");
                    } else {
                        $this->_error(
                            'Unknown or missing compression type ('
                            . $this->_compress_type . ')'
                        );
                        return false;
                    }
                }
            }
        }

        if ($this->_file == 0) {
            $this->_error(
                'Unable to open in write mode \''
                . $this->_tarname . '\''
            );
            return false;
        }

        return true;
    }

    /**
     * @return bool
     */
    public function _openRead()
    {
        if (strtolower(substr($this->_tarname, 0, 7)) == 'http://') {

            // ----- Look if a local copy need to be done
            if ($this->_temp_tarname == '') {
                $this->_temp_tarname = uniqid('tar') . '.tmp';
                if (!$v_file_from = @fopen($this->_tarname, 'rb')) {
                    $this->_error(
                        'Unable to open in read mode \''
                        . $this->_tarname . '\''
                    );
                    $this->_temp_tarname = '';
                    return false;
                }
                if (!$v_file_to = @fopen($this->_temp_tarname, 'wb')) {
                    $this->_error(
                        'Unable to open in write mode \''
                        . $this->_temp_tarname . '\''
                    );
                    $this->_temp_tarname = '';
                    return false;
                }
                while ($v_data = @fread($v_file_from, 1024)) {
                    @fwrite($v_file_to, $v_data);
                }
                @fclose($v_file_from);
                @fclose($v_file_to);
            }

            // ----- File to open if the local copy
            $v_filename = $this->_temp_tarname;
        } else {
            // ----- File to open if the normal Tar file

            $v_filename = $this->_tarname;
        }

        if ($this->_compress_type == 'gz' && function_exists('gzopen')) {
            $this->_file = @gzopen($v_filename, "rb");
        } else {
            if ($this->_compress_type == 'bz2' && function_exists('bzopen')) {
                $this->_file = @bzopen($v_filename, "r");
            } else {
                if ($this->_compress_type == 'lzma2' && function_exists('xzopen')) {
                    $this->_file = @xzopen($v_filename, "r");
                } else {
                    if ($this->_compress_type == 'none') {
                        $this->_file = @fopen($v_filename, "rb");
                    } else {
                        $this->_error(
                            'Unknown or missing compression type ('
                            . $this->_compress_type . ')'
                        );
                        return false;
                    }
                }
            }
        }

        if ($this->_file == 0) {
            $this->_error('Unable to open in read mode \'' . $v_filename . '\'');
            return false;
        }

        return true;
    }

    /**
     * @return bool
     */
    public function _openReadWrite()
    {
        if ($this->_compress_type == 'gz') {
            $this->_file = @gzopen($this->_tarname, "r+b");
        } else {
            if ($this->_compress_type == 'bz2') {
                $this->_error(
                    'Unable to open bz2 in read/write mode \''
                    . $this->_tarname . '\' (limitation of bz2 extension)'
                );
                return false;
            } else {
                if ($this->_compress_type == 'lzma2') {
                    $this->_error(
                        'Unable to open lzma2 in read/write mode \''
                        . $this->_tarname . '\' (limitation of lzma2 extension)'
                    );
                    return false;
                } else {
                    if ($this->_compress_type == 'none') {
                        $this->_file = @fopen($this->_tarname, "r+b");
                    } else {
                        $this->_error(
                            'Unknown or missing compression type ('
                            . $this->_compress_type . ')'
                        );
                        return false;
                    }
                }
            }
        }

        if ($this->_file == 0) {
            $this->_error(
                'Unable to open in read/write mode \''
                . $this->_tarname . '\''
            );
            return false;
        }

        return true;
    }

    /**
     * @return bool
     */
    public function _close()
    {
        //if (isset($this->_file)) {
        if (is_resource($this->_file)) {
            if ($this->_compress_type == 'gz') {
                @gzclose($this->_file);
            } else {
                if ($this->_compress_type == 'bz2') {
                    @bzclose($this->_file);
                } else {
                    if ($this->_compress_type == 'lzma2') {
                        @xzclose($this->_file);
                    } else {
                        if ($this->_compress_type == 'none') {
                            @fclose($this->_file);
                        } else {
                            $this->_error(
                                'Unknown or missing compression type ('
                                . $this->_compress_type . ')'
                            );
                        }
                    }
                }
            }

            $this->_file = 0;
        }

        // ----- Look if a local copy need to be erase
        // Note that it might be interesting to keep the url for a time : ToDo
        if ($this->_temp_tarname != '') {
            @unlink($this->_temp_tarname);
            $this->_temp_tarname = '';
        }

        return true;
    }

    /**
     * @return bool
     */
    public function _cleanFile()
    {
        $this->_close();

        // ----- Look for a local copy
        if ($this->_temp_tarname != '') {
            // ----- Remove the local copy but not the remote tarname
            @unlink($this->_temp_tarname);
            $this->_temp_tarname = '';
        } else {
            // ----- Remove the local tarname file
            @unlink($this->_tarname);
        }
        $this->_tarname = '';

        return true;
    }

    /**
     * @param mixed $p_binary_data
     * @param integer $p_len
     * @return bool
     */
    public function _writeBlock($p_binary_data, $p_len = null)
    {
        if (is_resource($this->_file)) {
            if ($p_len === null) {
                if ($this->_compress_type == 'gz') {
                    @gzputs($this->_file, $p_binary_data);
                } else {
                    if ($this->_compress_type == 'bz2') {
                        @bzwrite($this->_file, $p_binary_data);
                    } else {
                        if ($this->_compress_type == 'lzma2') {
                            @xzwrite($this->_file, $p_binary_data);
                        } else {
                            if ($this->_compress_type == 'none') {
                                @fputs($this->_file, $p_binary_data);
                            } else {
                                $this->_error(
                                    'Unknown or missing compression type ('
                                    . $this->_compress_type . ')'
                                );
                            }
                        }
                    }
                }
            } else {
                if ($this->_compress_type == 'gz') {
                    @gzputs($this->_file, $p_binary_data, $p_len);
                } else {
                    if ($this->_compress_type == 'bz2') {
                        @bzwrite($this->_file, $p_binary_data, $p_len);
                    } else {
                        if ($this->_compress_type == 'lzma2') {
                            @xzwrite($this->_file, $p_binary_data, $p_len);
                        } else {
                            if ($this->_compress_type == 'none') {
                                @fputs($this->_file, $p_binary_data, $p_len);
                            } else {
                                $this->_error(
                                    'Unknown or missing compression type ('
                                    . $this->_compress_type . ')'
                                );
                            }
                        }
                    }
                }
            }
        }
        return true;
    }

    /**
     * @return null|string
     */
    public function _readBlock()
    {
        $v_block = null;
        if (is_resource($this->_file)) {
            if ($this->_compress_type == 'gz') {
                $v_block = @gzread($this->_file, 512);
            } else {
                if ($this->_compress_type == 'bz2') {
                    $v_block = @bzread($this->_file, 512);
                } else {
                    if ($this->_compress_type == 'lzma2') {
                        $v_block = @xzread($this->_file, 512);
                    } else {
                        if ($this->_compress_type == 'none') {
                            $v_block = @fread($this->_file, 512);
                        } else {
                            $this->_error(
                                'Unknown or missing compression type ('
                                . $this->_compress_type . ')'
                            );
                        }
                    }
                }
            }
        }
        return $v_block;
    }

    /**
     * @param null $p_len
     * @return bool
     */
    public function _jumpBlock($p_len = null)
    {
        if (is_resource($this->_file)) {
            if ($p_len === null) {
                $p_len = 1;
            }

            if ($this->_compress_type == 'gz') {
                @gzseek($this->_file, gztell($this->_file) + ($p_len * 512));
            } else {
                if ($this->_compress_type == 'bz2') {
                    // ----- Replace missing bztell() and bzseek()
                    for ($i = 0; $i < $p_len; $i++) {
                        $this->_readBlock();
                    }
                } else {
                    if ($this->_compress_type == 'lzma2') {
                        // ----- Replace missing xztell() and xzseek()
                        for ($i = 0; $i < $p_len; $i++) {
                            $this->_readBlock();
                        }
                    } else {
                        if ($this->_compress_type == 'none') {
                            @fseek($this->_file, $p_len * 512, SEEK_CUR);
                        } else {
                            $this->_error(
                                'Unknown or missing compression type ('
                                . $this->_compress_type . ')'
                            );
                        }
                    }
                }
            }
        }
        return true;
    }

    /**
     * @return bool
     */
    public function _writeFooter()
    {
        if (is_resource($this->_file)) {
            // ----- Write the last 0 filled block for end of archive
            $v_binary_data = pack('a1024', '');
            $this->_writeBlock($v_binary_data);
        }
        return true;
    }

    /**
     * @param array $p_list
     * @param string $p_add_dir
     * @param string $p_remove_dir
     * @return bool
     */
    public function _addList($p_list, $p_add_dir, $p_remove_dir)
    {
        $v_result = true;
        $v_header = array();

        // ----- Remove potential windows directory separator
        $p_add_dir = $this->_translateWinPath($p_add_dir);
        $p_remove_dir = $this->_translateWinPath($p_remove_dir, false);

        if (!$this->_file) {
            $this->_error('Invalid file descriptor');
            return false;
        }

        if (sizeof($p_list) == 0) {
            return true;
        }

        foreach ($p_list as $v_filename) {
            if (!$v_result) {
                break;
            }

            // ----- Skip the current tar name
            if ($v_filename == $this->_tarname) {
                continue;
            }

            if ($v_filename == '') {
                continue;
            }

            // ----- ignore files and directories matching the ignore regular expression
            if ($this->_ignore_regexp && preg_match($this->_ignore_regexp, '/' . $v_filename)) {
                $this->_warning("File '$v_filename' ignored");
                continue;
            }

            if (!file_exists($v_filename) && !is_link($v_filename)) {
                $this->_warning("File '$v_filename' does not exist");
                continue;
            }

            // ----- Add the file or directory header
            if (!$this->_addFile($v_filename, $v_header, $p_add_dir, $p_remove_dir)) {
                return false;
            }

            if (@is_dir($v_filename) && !@is_link($v_filename)) {
                if (!($p_hdir = opendir($v_filename))) {
                    $this->_warning("Directory '$v_filename' can not be read");
                    continue;
                }
                while (false !== ($p_hitem = readdir($p_hdir))) {
                    if (($p_hitem != '.') && ($p_hitem != '..')) {
                        if ($v_filename != ".") {
                            $p_temp_list[0] = $v_filename . '/' . $p_hitem;
                        } else {
                            $p_temp_list[0] = $p_hitem;
                        }

                        $v_result = $this->_addList(
                            $p_temp_list,
                            $p_add_dir,
                            $p_remove_dir
                        );
                    }
                }

                unset($p_temp_list);
                unset($p_hdir);
                unset($p_hitem);
            }
        }

        return $v_result;
    }

    /**
     * @param string $p_filename
     * @param mixed $p_header
     * @param string $p_add_dir
     * @param string $p_remove_dir
     * @param null $v_stored_filename
     * @return bool
     */
    public function _addFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir, $v_stored_filename = null)
    {
        if (!$this->_file) {
            $this->_error('Invalid file descriptor');
            return false;
        }

        if ($p_filename == '') {
            $this->_error('Invalid file name');
            return false;
        }

        if (is_null($v_stored_filename)) {
            // ----- Calculate the stored filename
            $p_filename = $this->_translateWinPath($p_filename, false);
            $v_stored_filename = $p_filename;

            if (strcmp($p_filename, $p_remove_dir) == 0) {
                return true;
            }

            if ($p_remove_dir != '') {
                if (substr($p_remove_dir, -1) != '/') {
                    $p_remove_dir .= '/';
                }

                if (substr($p_filename, 0, strlen($p_remove_dir)) == $p_remove_dir) {
                    $v_stored_filename = substr($p_filename, strlen($p_remove_dir));
                }
            }

            $v_stored_filename = $this->_translateWinPath($v_stored_filename);
            if ($p_add_dir != '') {
                if (substr($p_add_dir, -1) == '/') {
                    $v_stored_filename = $p_add_dir . $v_stored_filename;
                } else {
                    $v_stored_filename = $p_add_dir . '/' . $v_stored_filename;
                }
            }

            $v_stored_filename = $this->_pathReduction($v_stored_filename);
        }

        if ($this->_isArchive($p_filename)) {
            if (($v_file = @fopen($p_filename, "rb")) == 0) {
                $this->_warning(
                    "Unable to open file '" . $p_filename
                    . "' in binary read mode"
                );
                return true;
            }

            if (!$this->_writeHeader($p_filename, $v_stored_filename)) {
                return false;
            }

            while (($v_buffer = fread($v_file, $this->buffer_length)) != '') {
                $buffer_length = strlen("$v_buffer");
                if ($buffer_length != $this->buffer_length) {
                    $pack_size = ((int)($buffer_length / 512) + ($buffer_length % 512 !== 0 ? 1 : 0)) * 512;
                    $pack_format = sprintf('a%d', $pack_size);
                } else {
                    $pack_format = sprintf('a%d', $this->buffer_length);
                }
                $v_binary_data = pack($pack_format, "$v_buffer");
                $this->_writeBlock($v_binary_data);
            }

            fclose($v_file);
        } else {
            // ----- Only header for dir
            if (!$this->_writeHeader($p_filename, $v_stored_filename)) {
                return false;
            }
        }

        return true;
    }

    /**
     * @param string $p_filename
     * @param string $p_string
     * @param bool $p_datetime
     * @param array $p_params
     * @return bool
     */
    public function _addString($p_filename, $p_string, $p_datetime = false, $p_params = array())
    {
        $p_stamp = @$p_params["stamp"] ? $p_params["stamp"] : ($p_datetime ? $p_datetime : time());
        $p_mode = @$p_params["mode"] ? $p_params["mode"] : 0600;
        $p_type = @$p_params["type"] ? $p_params["type"] : "";
        $p_uid = @$p_params["uid"] ? $p_params["uid"] : 0;
        $p_gid = @$p_params["gid"] ? $p_params["gid"] : 0;
        if (!$this->_file) {
            $this->_error('Invalid file descriptor');
            return false;
        }

        if ($p_filename == '') {
            $this->_error('Invalid file name');
            return false;
        }

        // ----- Calculate the stored filename
        $p_filename = $this->_translateWinPath($p_filename, false);

        // ----- If datetime is not specified, set current time
        if ($p_datetime === false) {
            $p_datetime = time();
        }

        if (!$this->_writeHeaderBlock(
            $p_filename,
            strlen($p_string),
            $p_stamp,
            $p_mode,
            $p_type,
            $p_uid,
            $p_gid
        )
        ) {
            return false;
        }

        $i = 0;
        while (($v_buffer = substr($p_string, (($i++) * 512), 512)) != '') {
            $v_binary_data = pack("a512", $v_buffer);
            $this->_writeBlock($v_binary_data);
        }

        return true;
    }

    /**
     * @param string $p_filename
     * @param string $p_stored_filename
     * @return bool
     */
    public function _writeHeader($p_filename, $p_stored_filename)
    {
        if ($p_stored_filename == '') {
            $p_stored_filename = $p_filename;
        }

        $v_reduced_filename = $this->_pathReduction($p_stored_filename);

        if (strlen($v_reduced_filename) > 99) {
            if (!$this->_writeLongHeader($v_reduced_filename, false)) {
                return false;
            }
        }

        $v_linkname = '';
        if (@is_link($p_filename)) {
            $v_linkname = readlink($p_filename);
        }

        if (strlen($v_linkname) > 99) {
            if (!$this->_writeLongHeader($v_linkname, true)) {
                return false;
            }
        }

        $v_info = lstat($p_filename);
        $v_uid = sprintf("%07s", DecOct($v_info[4]));
        $v_gid = sprintf("%07s", DecOct($v_info[5]));
        $v_perms = sprintf("%07s", DecOct($v_info['mode'] & 000777));
        $v_mtime = sprintf("%011s", DecOct($v_info['mtime']));

        if (@is_link($p_filename)) {
            $v_typeflag = '2';
            $v_size = sprintf("%011s", DecOct(0));
        } elseif (@is_dir($p_filename)) {
            $v_typeflag = "5";
            $v_size = sprintf("%011s", DecOct(0));
        } else {
            $v_typeflag = '0';
            clearstatcache();
            $v_size = sprintf("%011s", DecOct($v_info['size']));
        }

        $v_magic = 'ustar ';
        $v_version = ' ';
        $v_uname = '';
        $v_gname = '';

        if (function_exists('posix_getpwuid')) {
            $userinfo = posix_getpwuid($v_info[4]);
            $groupinfo = posix_getgrgid($v_info[5]);

            if (isset($userinfo['name'])) {
                $v_uname = $userinfo['name'];
            }

            if (isset($groupinfo['name'])) {
                $v_gname = $groupinfo['name'];
            }
        }

        $v_devmajor = '';
        $v_devminor = '';
        $v_prefix = '';

        $v_binary_data_first = pack(
            "a100a8a8a8a12a12",
            $v_reduced_filename,
            $v_perms,
            $v_uid,
            $v_gid,
            $v_size,
            $v_mtime
        );
        $v_binary_data_last = pack(
            "a1a100a6a2a32a32a8a8a155a12",
            $v_typeflag,
            $v_linkname,
            $v_magic,
            $v_version,
            $v_uname,
            $v_gname,
            $v_devmajor,
            $v_devminor,
            $v_prefix,
            ''
        );

        // ----- Calculate the checksum
        $v_checksum = 0;
        // ..... First part of the header
        for ($i = 0; $i < 148; $i++) {
            $v_checksum += ord(substr($v_binary_data_first, $i, 1));
        }
        // ..... Ignore the checksum value and replace it by ' ' (space)
        for ($i = 148; $i < 156; $i++) {
            $v_checksum += ord(' ');
        }
        // ..... Last part of the header
        for ($i = 156, $j = 0; $i < 512; $i++, $j++) {
            $v_checksum += ord(substr($v_binary_data_last, $j, 1));
        }

        // ----- Write the first 148 bytes of the header in the archive
        $this->_writeBlock($v_binary_data_first, 148);

        // ----- Write the calculated checksum
        $v_checksum = sprintf("%06s\0 ", DecOct($v_checksum));
        $v_binary_data = pack("a8", $v_checksum);
        $this->_writeBlock($v_binary_data, 8);

        // ----- Write the last 356 bytes of the header in the archive
        $this->_writeBlock($v_binary_data_last, 356);

        return true;
    }

    /**
     * @param string $p_filename
     * @param int $p_size
     * @param int $p_mtime
     * @param int $p_perms
     * @param string $p_type
     * @param int $p_uid
     * @param int $p_gid
     * @return bool
     */
    public function _writeHeaderBlock(
        $p_filename,
        $p_size,
        $p_mtime = 0,
        $p_perms = 0,
        $p_type = '',
        $p_uid = 0,
        $p_gid = 0
    )
    {
        $p_filename = $this->_pathReduction($p_filename);

        if (strlen($p_filename) > 99) {
            if (!$this->_writeLongHeader($p_filename, false)) {
                return false;
            }
        }

        if ($p_type == "5") {
            $v_size = sprintf("%011s", DecOct(0));
        } else {
            $v_size = sprintf("%011s", DecOct($p_size));
        }

        $v_uid = sprintf("%07s", DecOct($p_uid));
        $v_gid = sprintf("%07s", DecOct($p_gid));
        $v_perms = sprintf("%07s", DecOct($p_perms & 000777));

        $v_mtime = sprintf("%11s", DecOct($p_mtime));

        $v_linkname = '';

        $v_magic = 'ustar ';

        $v_version = ' ';

        if (function_exists('posix_getpwuid')) {
            $userinfo = posix_getpwuid($p_uid);
            $groupinfo = posix_getgrgid($p_gid);

            if ($userinfo === false || $groupinfo === false) {
                $v_uname = '';
                $v_gname = '';
            } else {
                $v_uname = $userinfo['name'];
                $v_gname = $groupinfo['name'];
            }
        } else {
            $v_uname = '';
            $v_gname = '';
        }

        $v_devmajor = '';

        $v_devminor = '';

        $v_prefix = '';

        $v_binary_data_first = pack(
            "a100a8a8a8a12A12",
            $p_filename,
            $v_perms,
            $v_uid,
            $v_gid,
            $v_size,
            $v_mtime
        );
        $v_binary_data_last = pack(
            "a1a100a6a2a32a32a8a8a155a12",
            $p_type,
            $v_linkname,
            $v_magic,
            $v_version,
            $v_uname,
            $v_gname,
            $v_devmajor,
            $v_devminor,
            $v_prefix,
            ''
        );

        // ----- Calculate the checksum
        $v_checksum = 0;
        // ..... First part of the header
        for ($i = 0; $i < 148; $i++) {
            $v_checksum += ord(substr($v_binary_data_first, $i, 1));
        }
        // ..... Ignore the checksum value and replace it by ' ' (space)
        for ($i = 148; $i < 156; $i++) {
            $v_checksum += ord(' ');
        }
        // ..... Last part of the header
        for ($i = 156, $j = 0; $i < 512; $i++, $j++) {
            $v_checksum += ord(substr($v_binary_data_last, $j, 1));
        }

        // ----- Write the first 148 bytes of the header in the archive
        $this->_writeBlock($v_binary_data_first, 148);

        // ----- Write the calculated checksum
        $v_checksum = sprintf("%06s ", DecOct($v_checksum));
        $v_binary_data = pack("a8", $v_checksum);
        $this->_writeBlock($v_binary_data, 8);

        // ----- Write the last 356 bytes of the header in the archive
        $this->_writeBlock($v_binary_data_last, 356);

        return true;
    }

    /**
     * @param string $p_filename
     * @return bool
     */
    public function _writeLongHeader($p_filename, $is_link = false)
    {
        $v_uid = sprintf("%07s", 0);
        $v_gid = sprintf("%07s", 0);
        $v_perms = sprintf("%07s", 0);
        $v_size = sprintf("%'011s", DecOct(strlen($p_filename)));
        $v_mtime = sprintf("%011s", 0);
        $v_typeflag = ($is_link ? 'K' : 'L');
        $v_linkname = '';
        $v_magic = 'ustar ';
        $v_version = ' ';
        $v_uname = '';
        $v_gname = '';
        $v_devmajor = '';
        $v_devminor = '';
        $v_prefix = '';

        $v_binary_data_first = pack(
            "a100a8a8a8a12a12",
            '././@LongLink',
            $v_perms,
            $v_uid,
            $v_gid,
            $v_size,
            $v_mtime
        );
        $v_binary_data_last = pack(
            "a1a100a6a2a32a32a8a8a155a12",
            $v_typeflag,
            $v_linkname,
            $v_magic,
            $v_version,
            $v_uname,
            $v_gname,
            $v_devmajor,
            $v_devminor,
            $v_prefix,
            ''
        );

        // ----- Calculate the checksum
        $v_checksum = 0;
        // ..... First part of the header
        for ($i = 0; $i < 148; $i++) {
            $v_checksum += ord(substr($v_binary_data_first, $i, 1));
        }
        // ..... Ignore the checksum value and replace it by ' ' (space)
        for ($i = 148; $i < 156; $i++) {
            $v_checksum += ord(' ');
        }
        // ..... Last part of the header
        for ($i = 156, $j = 0; $i < 512; $i++, $j++) {
            $v_checksum += ord(substr($v_binary_data_last, $j, 1));
        }

        // ----- Write the first 148 bytes of the header in the archive
        $this->_writeBlock($v_binary_data_first, 148);

        // ----- Write the calculated checksum
        $v_checksum = sprintf("%06s\0 ", DecOct($v_checksum));
        $v_binary_data = pack("a8", $v_checksum);
        $this->_writeBlock($v_binary_data, 8);

        // ----- Write the last 356 bytes of the header in the archive
        $this->_writeBlock($v_binary_data_last, 356);

        // ----- Write the filename as content of the block
        $i = 0;
        while (($v_buffer = substr($p_filename, (($i++) * 512), 512)) != '') {
            $v_binary_data = pack("a512", "$v_buffer");
            $this->_writeBlock($v_binary_data);
        }

        return true;
    }

    /**
     * @param mixed $v_binary_data
     * @param mixed $v_header
     * @return bool
     */
    public function _readHeader($v_binary_data, &$v_header)
    {
        if (strlen($v_binary_data) == 0) {
            $v_header['filename'] = '';
            return true;
        }

        if (strlen($v_binary_data) != 512) {
            $v_header['filename'] = '';
            $this->_error('Invalid block size : ' . strlen($v_binary_data));
            return false;
        }

        if (!is_array($v_header)) {
            $v_header = array();
        }
        // ----- Calculate the checksum
        $v_checksum = 0;
        // ..... First part of the header
        $v_binary_split = str_split($v_binary_data);
        $v_checksum += array_sum(array_map('ord', array_slice($v_binary_split, 0, 148)));
        $v_checksum += array_sum(array_map('ord', array(' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',)));
        $v_checksum += array_sum(array_map('ord', array_slice($v_binary_split, 156, 512)));


        $v_data = unpack($this->_fmt, $v_binary_data);

        if (strlen($v_data["prefix"]) > 0) {
            $v_data["filename"] = "$v_data[prefix]/$v_data[filename]";
        }

        // ----- Extract the checksum
        $v_data_checksum = trim($v_data['checksum']);
        if (!preg_match('/^[0-7]*$/', $v_data_checksum)) {
            $this->_error(
                'Invalid checksum for file "' . $v_data['filename']
                . '" : ' . $v_data_checksum . ' extracted'
            );
            return false;
        }

        $v_header['checksum'] = OctDec($v_data_checksum);
        if ($v_header['checksum'] != $v_checksum) {
            $v_header['filename'] = '';

            // ----- Look for last block (empty block)
            if (($v_checksum == 256) && ($v_header['checksum'] == 0)) {
                return true;
            }

            $this->_error(
                'Invalid checksum for file "' . $v_data['filename']
                . '" : ' . $v_checksum . ' calculated, '
                . $v_header['checksum'] . ' expected'
            );
            return false;
        }

        // ----- Extract the properties
        $v_header['filename'] = rtrim($v_data['filename'], "\0");
        if ($this->_isMaliciousFilename($v_header['filename'])) {
            $this->_error(
                'Malicious .tar detected, file "' . $v_header['filename'] .
                '" will not install in desired directory tree'
            );
            return false;
        }
        $v_header['mode'] = OctDec(trim($v_data['mode']));
        $v_header['uid'] = OctDec(trim($v_data['uid']));
        $v_header['gid'] = OctDec(trim($v_data['gid']));
        $v_header['size'] = $this->_tarRecToSize($v_data['size']);
        $v_header['mtime'] = OctDec(trim($v_data['mtime']));
        if (($v_header['typeflag'] = $v_data['typeflag']) == "5") {
            $v_header['size'] = 0;
        }
        $v_header['link'] = trim($v_data['link']);
        /* ----- All these fields are removed form the header because
        they do not carry interesting info
        $v_header[magic] = trim($v_data[magic]);
        $v_header[version] = trim($v_data[version]);
        $v_header[uname] = trim($v_data[uname]);
        $v_header[gname] = trim($v_data[gname]);
        $v_header[devmajor] = trim($v_data[devmajor]);
        $v_header[devminor] = trim($v_data[devminor]);
        */

        return true;
    }

    /**
     * Convert Tar record size to actual size
     *
     * @param string $tar_size
     * @return size of tar record in bytes
     */
    private function _tarRecToSize($tar_size)
    {
        /*
         * First byte of size has a special meaning if bit 7 is set.
         *
         * Bit 7 indicates base-256 encoding if set.
         * Bit 6 is the sign bit.
         * Bits 5:0 are most significant value bits.
         */
        $ch = ord($tar_size[0]);
        if ($ch & 0x80) {
            // Full 12-bytes record is required.
            $rec_str = $tar_size . "\x00";

            $size = ($ch & 0x40) ? -1 : 0;
            $size = ($size << 6) | ($ch & 0x3f);

            for ($num_ch = 1; $num_ch < 12; ++$num_ch) {
                $size = ($size * 256) + ord($rec_str[$num_ch]);
            }

            return $size;

        } else {
            return OctDec(trim($tar_size));
        }
    }

    /**
     * Detect and report a malicious file name
     *
     * @param string $file
     *
     * @return bool
     */
    private function _isMaliciousFilename($file)
    {
        if (strpos($file, '://') !== false) {
            return true;
        }
        if (strpos($file, '../') !== false || strpos($file, '..\\') !== false) {
            return true;
        }
        return false;
    }

    /**
     * @param $v_header
     * @return bool
     */
    public function _readLongHeader(&$v_header)
    {
        $v_filename = '';
        $v_filesize = $v_header['size'];
        $n = floor($v_header['size'] / 512);
        for ($i = 0; $i < $n; $i++) {
            $v_content = $this->_readBlock();
            $v_filename .= $v_content;
        }
        if (($v_header['size'] % 512) != 0) {
            $v_content = $this->_readBlock();
            $v_filename .= $v_content;
        }

        // ----- Read the next header
        $v_binary_data = $this->_readBlock();

        if (!$this->_readHeader($v_binary_data, $v_header)) {
            return false;
        }

        $v_filename = rtrim(substr($v_filename, 0, $v_filesize), "\0");
        $v_header['filename'] = $v_filename;
        if ($this->_isMaliciousFilename($v_filename)) {
            $this->_error(
                'Malicious .tar detected, file "' . $v_filename .
                '" will not install in desired directory tree'
            );
            return false;
        }

        return true;
    }

    /**
     * This method extract from the archive one file identified by $p_filename.
     * The return value is a string with the file content, or null on error.
     *
     * @param string $p_filename The path of the file to extract in a string.
     *
     * @return a string with the file content or null.
     */
    private function _extractInString($p_filename)
    {
        $v_result_str = "";

        while (strlen($v_binary_data = $this->_readBlock()) != 0) {
            if (!$this->_readHeader($v_binary_data, $v_header)) {
                return null;
            }

            if ($v_header['filename'] == '') {
                continue;
            }

            switch ($v_header['typeflag']) {
                case 'L':
                    {
                        if (!$this->_readLongHeader($v_header)) {
                            return null;
                        }
                    }
                    break;

                case 'K':
                    {
                        $v_link_header = $v_header;
                        if (!$this->_readLongHeader($v_link_header)) {
                            return null;
                        }
                        $v_header['link'] = $v_link_header['filename'];
                    }
                    break;
            }

            if ($v_header['filename'] == $p_filename) {
                if ($v_header['typeflag'] == "5") {
                    $this->_error(
                        'Unable to extract in string a directory '
                        . 'entry {' . $v_header['filename'] . '}'
                    );
                    return null;
                } else {
                    $n = floor($v_header['size'] / 512);
                    for ($i = 0; $i < $n; $i++) {
                        $v_result_str .= $this->_readBlock();
                    }
                    if (($v_header['size'] % 512) != 0) {
                        $v_content = $this->_readBlock();
                        $v_result_str .= substr(
                            $v_content,
                            0,
                            ($v_header['size'] % 512)
                        );
                    }
                    return $v_result_str;
                }
            } else {
                $this->_jumpBlock(ceil(($v_header['size'] / 512)));
            }
        }

        return null;
    }

    /**
     * @param string $p_path
     * @param string $p_list_detail
     * @param string $p_mode
     * @param string $p_file_list
     * @param string $p_remove_path
     * @param bool $p_preserve
     * @param bool $p_symlinks
     * @return bool
     */
    public function _extractList(
        $p_path,
        &$p_list_detail,
        $p_mode,
        $p_file_list,
        $p_remove_path,
        $p_preserve = false,
        $p_symlinks = true
    )
    {
        $v_result = true;
        $v_nb = 0;
        $v_extract_all = true;
        $v_listing = false;

        $p_path = $this->_translateWinPath($p_path, false);
        if ($p_path == '' || (substr($p_path, 0, 1) != '/'
                && substr($p_path, 0, 3) != "../" && !strpos($p_path, ':'))
        ) {
            $p_path = "./" . $p_path;
        }
        $p_remove_path = $this->_translateWinPath($p_remove_path);

        // ----- Look for path to remove format (should end by /)
        if (($p_remove_path != '') && (substr($p_remove_path, -1) != '/')) {
            $p_remove_path .= '/';
        }
        $p_remove_path_size = strlen($p_remove_path);

        switch ($p_mode) {
            case "complete" :
                $v_extract_all = true;
                $v_listing = false;
                break;
            case "partial" :
                $v_extract_all = false;
                $v_listing = false;
                break;
            case "list" :
                $v_extract_all = false;
                $v_listing = true;
                break;
            default :
                $this->_error('Invalid extract mode (' . $p_mode . ')');
                return false;
        }

        clearstatcache();

        while (strlen($v_binary_data = $this->_readBlock()) != 0) {
            $v_extract_file = false;
            $v_extraction_stopped = 0;

            if (!$this->_readHeader($v_binary_data, $v_header)) {
                return false;
            }

            if ($v_header['filename'] == '') {
                continue;
            }

            switch ($v_header['typeflag']) {
                case 'L':
                    {
                        if (!$this->_readLongHeader($v_header)) {
                            return null;
                        }
                    }
                    break;

                case 'K':
                    {
                        $v_link_header = $v_header;
                        if (!$this->_readLongHeader($v_link_header)) {
                            return null;
                        }
                        $v_header['link'] = $v_link_header['filename'];
                    }
                    break;
            }

            // ignore extended / pax headers
            if ($v_header['typeflag'] == 'x' || $v_header['typeflag'] == 'g') {
                $this->_jumpBlock(ceil(($v_header['size'] / 512)));
                continue;
            }

            if ((!$v_extract_all) && (is_array($p_file_list))) {
                // ----- By default no unzip if the file is not found
                $v_extract_file = false;

                for ($i = 0; $i < sizeof($p_file_list); $i++) {
                    // ----- Look if it is a directory
                    if (substr($p_file_list[$i], -1) == '/') {
                        // ----- Look if the directory is in the filename path
                        if ((strlen($v_header['filename']) > strlen($p_file_list[$i]))
                            && (substr($v_header['filename'], 0, strlen($p_file_list[$i]))
                                == $p_file_list[$i])
                        ) {
                            $v_extract_file = true;
                            break;
                        }
                    } // ----- It is a file, so compare the file names
                    elseif ($p_file_list[$i] == $v_header['filename']) {
                        $v_extract_file = true;
                        break;
                    }
                }
            } else {
                $v_extract_file = true;
            }

            // ----- Look if this file need to be extracted
            if (($v_extract_file) && (!$v_listing)) {
                if (($p_remove_path != '')
                    && (substr($v_header['filename'] . '/', 0, $p_remove_path_size)
                        == $p_remove_path)
                ) {
                    $v_header['filename'] = substr(
                        $v_header['filename'],
                        $p_remove_path_size
                    );
                    if ($v_header['filename'] == '') {
                        continue;
                    }
                }
                if (($p_path != './') && ($p_path != '/')) {
                    while (substr($p_path, -1) == '/') {
                        $p_path = substr($p_path, 0, strlen($p_path) - 1);
                    }

                    if (substr($v_header['filename'], 0, 1) == '/') {
                        $v_header['filename'] = $p_path . $v_header['filename'];
                    } else {
                        $v_header['filename'] = $p_path . '/' . $v_header['filename'];
                    }
                }
                if (file_exists($v_header['filename'])) {
                    if ((@is_dir($v_header['filename']))
                        && ($v_header['typeflag'] == '')
                    ) {
                        $this->_error(
                            'File ' . $v_header['filename']
                            . ' already exists as a directory'
                        );
                        return false;
                    }
                    if (($this->_isArchive($v_header['filename']))
                        && ($v_header['typeflag'] == "5")
                    ) {
                        $this->_error(
                            'Directory ' . $v_header['filename']
                            . ' already exists as a file'
                        );
                        return false;
                    }
                    if (!is_writeable($v_header['filename'])) {
                        $this->_error(
                            'File ' . $v_header['filename']
                            . ' already exists and is write protected'
                        );
                        return false;
                    }
                    if (filemtime($v_header['filename']) > $v_header['mtime']) {
                        // To be completed : An error or silent no replace ?
                    }
                } // ----- Check the directory availability and create it if necessary
                elseif (($v_result
                        = $this->_dirCheck(
                        ($v_header['typeflag'] == "5"
                            ? $v_header['filename']
                            : dirname($v_header['filename']))
                    )) != 1
                ) {
                    $this->_error('Unable to create path for ' . $v_header['filename']);
                    return false;
                }

                if ($v_extract_file) {
                    if ($v_header['typeflag'] == "5") {
                        if (!@file_exists($v_header['filename'])) {
                            if (!@mkdir($v_header['filename'], 0777)) {
                                $this->_error(
                                    'Unable to create directory {'
                                    . $v_header['filename'] . '}'
                                );
                                return false;
                            }
                        }
                    } elseif ($v_header['typeflag'] == "2") {
                        if (!$p_symlinks) {
                            $this->_warning('Symbolic links are not allowed. '
                                . 'Unable to extract {'
                                . $v_header['filename'] . '}'
                            );
                            return false;
                        }
                        $absolute_link = FALSE;
                        $link_depth = 0;
                        if (strpos($v_header['link'], "/") === 0 || strpos($v_header['link'], ':') !== FALSE) {
                          $absolute_link = TRUE;
                        }
                        else {
                            $s_filename = preg_replace('@^' . preg_quote($p_path) . '@', "", $v_header['filename']);
                            $s_linkname = str_replace('\\', '/', $v_header['link']);
                            foreach (explode("/", $s_filename) as $dir) {
                                if ($dir === "..") {
                                    $link_depth--;
                                } elseif ($dir !== "" && $dir !== "." ) {
                                    $link_depth++;
                                }
                            }
                            foreach (explode("/", $s_linkname) as $dir){
                                if ($link_depth <= 0) {
                                    break;
                                }
                                if ($dir === "..") {
                                    $link_depth--;
                                } elseif ($dir !== "" && $dir !== ".") {
                                    $link_depth++;
                                }
                            }
                        }
                        if ($absolute_link || $link_depth <= 0) {
                            $this->_error(
                                 'Out-of-path file extraction {'
                                 . $v_header['filename'] . ' --> ' .
                                 $v_header['link'] . '}'
                            );
                            return false;
                        }
                        if (@file_exists($v_header['filename'])) {
                            @unlink($v_header['filename']);
                        }
                        if (!@symlink($v_header['link'], $v_header['filename'])) {
                            $this->_error(
                                'Unable to extract symbolic link {'
                                . $v_header['filename'] . '}'
                            );
                            return false;
                        }
                    } else {
                        if (($v_dest_file = @fopen($v_header['filename'], "wb")) == 0) {
                            $this->_error(
                                'Error while opening {' . $v_header['filename']
                                . '} in write binary mode'
                            );
                            return false;
                        } else {
                            $n = floor($v_header['size'] / 512);
                            for ($i = 0; $i < $n; $i++) {
                                $v_content = $this->_readBlock();
                                fwrite($v_dest_file, $v_content, 512);
                            }
                            if (($v_header['size'] % 512) != 0) {
                                $v_content = $this->_readBlock();
                                fwrite($v_dest_file, $v_content, ($v_header['size'] % 512));
                            }

                            @fclose($v_dest_file);

                            if ($p_preserve) {
                                @chown($v_header['filename'], $v_header['uid']);
                                @chgrp($v_header['filename'], $v_header['gid']);
                            }

                            // ----- Change the file mode, mtime
                            @touch($v_header['filename'], $v_header['mtime']);
                            if ($v_header['mode'] & 0111) {
                                // make file executable, obey umask
                                $mode = fileperms($v_header['filename']) | (~umask() & 0111);
                                @chmod($v_header['filename'], $mode);
                            }
                        }

                        // ----- Check the file size
                        clearstatcache();
                        if (!is_file($v_header['filename'])) {
                            $this->_error(
                                'Extracted file ' . $v_header['filename']
                                . 'does not exist. Archive may be corrupted.'
                            );
                            return false;
                        }

                        $filesize = filesize($v_header['filename']);
                        if ($filesize != $v_header['size']) {
                            $this->_error(
                                'Extracted file ' . $v_header['filename']
                                . ' does not have the correct file size \''
                                . $filesize
                                . '\' (' . $v_header['size']
                                . ' expected). Archive may be corrupted.'
                            );
                            return false;
                        }
                    }
                } else {
                    $this->_jumpBlock(ceil(($v_header['size'] / 512)));
                }
            } else {
                $this->_jumpBlock(ceil(($v_header['size'] / 512)));
            }

            /* TBC : Seems to be unused ...
            if ($this->_compress)
              $v_end_of_file = @gzeof($this->_file);
            else
              $v_end_of_file = @feof($this->_file);
              */

            if ($v_listing || $v_extract_file || $v_extraction_stopped) {
                // ----- Log extracted files
                if (($v_file_dir = dirname($v_header['filename']))
                    == $v_header['filename']
                ) {
                    $v_file_dir = '';
                }
                if ((substr($v_header['filename'], 0, 1) == '/') && ($v_file_dir == '')) {
                    $v_file_dir = '/';
                }

                $p_list_detail[$v_nb++] = $v_header;
                if (is_array($p_file_list) && (count($p_list_detail) == count($p_file_list))) {
                    return true;
                }
            }
        }

        return true;
    }

    /**
     * @return bool
     */
    public function _openAppend()
    {
        if (filesize($this->_tarname) == 0) {
            return $this->_openWrite();
        }

        if ($this->_compress) {
            $this->_close();

            if (!@rename($this->_tarname, $this->_tarname . ".tmp")) {
                $this->_error(
                    'Error while renaming \'' . $this->_tarname
                    . '\' to temporary file \'' . $this->_tarname
                    . '.tmp\''
                );
                return false;
            }

            if ($this->_compress_type == 'gz') {
                $v_temp_tar = @gzopen($this->_tarname . ".tmp", "rb");
            } elseif ($this->_compress_type == 'bz2') {
                $v_temp_tar = @bzopen($this->_tarname . ".tmp", "r");
            } elseif ($this->_compress_type == 'lzma2') {
                $v_temp_tar = @xzopen($this->_tarname . ".tmp", "r");
            }


            if ($v_temp_tar == 0) {
                $this->_error(
                    'Unable to open file \'' . $this->_tarname
                    . '.tmp\' in binary read mode'
                );
                @rename($this->_tarname . ".tmp", $this->_tarname);
                return false;
            }

            if (!$this->_openWrite()) {
                @rename($this->_tarname . ".tmp", $this->_tarname);
                return false;
            }

            if ($this->_compress_type == 'gz') {
                $end_blocks = 0;

                while (!@gzeof($v_temp_tar)) {
                    $v_buffer = @gzread($v_temp_tar, 512);
                    if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) {
                        $end_blocks++;
                        // do not copy end blocks, we will re-make them
                        // after appending
                        continue;
                    } elseif ($end_blocks > 0) {
                        for ($i = 0; $i < $end_blocks; $i++) {
                            $this->_writeBlock(ARCHIVE_TAR_END_BLOCK);
                        }
                        $end_blocks = 0;
                    }
                    $v_binary_data = pack("a512", $v_buffer);
                    $this->_writeBlock($v_binary_data);
                }

                @gzclose($v_temp_tar);
            } elseif ($this->_compress_type == 'bz2') {
                $end_blocks = 0;

                while (strlen($v_buffer = @bzread($v_temp_tar, 512)) > 0) {
                    if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) {
                        $end_blocks++;
                        // do not copy end blocks, we will re-make them
                        // after appending
                        continue;
                    } elseif ($end_blocks > 0) {
                        for ($i = 0; $i < $end_blocks; $i++) {
                            $this->_writeBlock(ARCHIVE_TAR_END_BLOCK);
                        }
                        $end_blocks = 0;
                    }
                    $v_binary_data = pack("a512", $v_buffer);
                    $this->_writeBlock($v_binary_data);
                }

                @bzclose($v_temp_tar);
            } elseif ($this->_compress_type == 'lzma2') {
                $end_blocks = 0;

                while (strlen($v_buffer = @xzread($v_temp_tar, 512)) > 0) {
                    if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) {
                        $end_blocks++;
                        // do not copy end blocks, we will re-make them
                        // after appending
                        continue;
                    } elseif ($end_blocks > 0) {
                        for ($i = 0; $i < $end_blocks; $i++) {
                            $this->_writeBlock(ARCHIVE_TAR_END_BLOCK);
                        }
                        $end_blocks = 0;
                    }
                    $v_binary_data = pack("a512", $v_buffer);
                    $this->_writeBlock($v_binary_data);
                }

                @xzclose($v_temp_tar);
            }

            if (!@unlink($this->_tarname . ".tmp")) {
                $this->_error(
                    'Error while deleting temporary file \''
                    . $this->_tarname . '.tmp\''
                );
            }
        } else {
            // ----- For not compressed tar, just add files before the last
            //       one or two 512 bytes block
            if (!$this->_openReadWrite()) {
                return false;
            }

            clearstatcache();
            $v_size = filesize($this->_tarname);

            // We might have zero, one or two end blocks.
            // The standard is two, but we should try to handle
            // other cases.
            fseek($this->_file, $v_size - 1024);
            if (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) {
                fseek($this->_file, $v_size - 1024);
            } elseif (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) {
                fseek($this->_file, $v_size - 512);
            }
        }

        return true;
    }

    /**
     * @param $p_filelist
     * @param string $p_add_dir
     * @param string $p_remove_dir
     * @return bool
     */
    public function _append($p_filelist, $p_add_dir = '', $p_remove_dir = '')
    {
        if (!$this->_openAppend()) {
            return false;
        }

        if ($this->_addList($p_filelist, $p_add_dir, $p_remove_dir)) {
            $this->_writeFooter();
        }

        $this->_close();

        return true;
    }

    /**
     * Check if a directory exists and create it (including parent
     * dirs) if not.
     *
     * @param string $p_dir directory to check
     *
     * @return bool true if the directory exists or was created
     */
    public function _dirCheck($p_dir)
    {
        clearstatcache();
        if ((@is_dir($p_dir)) || ($p_dir == '')) {
            return true;
        }

        $p_parent_dir = dirname($p_dir);

        if (($p_parent_dir != $p_dir) &&
            ($p_parent_dir != '') &&
            (!$this->_dirCheck($p_parent_dir))
        ) {
            return false;
        }

        if (!@mkdir($p_dir, 0777)) {
            $this->_error("Unable to create directory '$p_dir'");
            return false;
        }

        return true;
    }

    /**
     * Compress path by changing for example "/dir/foo/../bar" to "/dir/bar",
     * rand emove double slashes.
     *
     * @param string $p_dir path to reduce
     *
     * @return string reduced path
     */
    private function _pathReduction($p_dir)
    {
        $v_result = '';

        // ----- Look for not empty path
        if ($p_dir != '') {
            // ----- Explode path by directory names
            $v_list = explode('/', $p_dir);

            // ----- Study directories from last to first
            for ($i = sizeof($v_list) - 1; $i >= 0; $i--) {
                // ----- Look for current path
                if ($v_list[$i] == ".") {
                    // ----- Ignore this directory
                    // Should be the first $i=0, but no check is done
                } else {
                    if ($v_list[$i] == "..") {
                        // ----- Ignore it and ignore the $i-1
                        $i--;
                    } else {
                        if (($v_list[$i] == '')
                            && ($i != (sizeof($v_list) - 1))
                            && ($i != 0)
                        ) {
                            // ----- Ignore only the double '//' in path,
                            // but not the first and last /
                        } else {
                            $v_result = $v_list[$i] . ($i != (sizeof($v_list) - 1) ? '/'
                                    . $v_result : '');
                        }
                    }
                }
            }
        }

        if (defined('OS_WINDOWS') && OS_WINDOWS) {
            $v_result = strtr($v_result, '\\', '/');
        }

        return $v_result;
    }

    /**
     * @param $p_path
     * @param bool $p_remove_disk_letter
     * @return string
     */
    public function _translateWinPath($p_path, $p_remove_disk_letter = true)
    {
        if (defined('OS_WINDOWS') && OS_WINDOWS) {
            // ----- Look for potential disk letter
            if (($p_remove_disk_letter)
                && (($v_position = strpos($p_path, ':')) != false)
            ) {
                $p_path = substr($p_path, $v_position + 1);
            }
            // ----- Change potential windows directory separator
            if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0, 1) == '\\')) {
                $p_path = strtr($p_path, '\\', '/');
            }
        }
        return $p_path;
    }
}
PK��Z�/f��File/MARCBASE.phpnu�[���<?php

/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */

/**
 * Parser for MARC records
 *
 * This package is based on the PHP MARC package, originally called "php-marc",
 * that is part of the Emilda Project (http://www.emilda.org). Christoffer
 * Landtman generously agreed to make the "php-marc" code available under the
 * GNU LGPL so it could be used as the basis of this PEAR package.
 * 
 * PHP version 5
 *
 * LICENSE: This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category  File_Formats
 * @package   File_MARC
 * @author    Dan Scott <dscott@laurentian.ca>
 * @copyright 2007-2010 Dan Scott
 * @license   http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @version   CVS: $Id: MARCXML.php 301727 2010-07-30 17:30:51Z dbs $
 * @link      http://pear.php.net/package/File_MARC
 * @example   read.php Retrieve specific fields and subfields from a record
 * @example   subfields.php Create new subfields and add them in specific order
 * @example   marc_yaz.php Pretty print a MARC record retrieved via yaz extension
 */

require_once 'File/MARC/Record.php';

// {{{ class File_MARCBASE
/**
 * The main File_MARCBASE class provides common methods for File_MARC and
 * File_MARCXML - primarily for generating MARCXML output.
 *
 * @category File_Formats
 * @package  File_MARC
 * @author   Dan Scott <dscott@laurentian.ca>
 * @license  http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @link     http://pear.php.net/package/File_MARC
 */
class File_MARCBASE
{

    /**
     * XMLWriter for writing collections
     * 
     * @var XMLWriter
     */
    protected $xmlwriter;

    /**
     * Record class
     *
     * @var string
     */
    protected $record_class;
    // }}}

    // {{{ Constructor: function __construct()
    /**
     * Read in MARCXML records
     *
     * This function reads in files or strings that
     * contain one or more MARCXML records.
     *
     * <code>
     * <?php
     * // Retrieve MARC records from a file
     * $journals = new File_MARC('journals.mrc', SOURCE_FILE);
     *
     * // Retrieve MARC records from a string (e.g. Z39 query results)
     * $monographs = new File_MARC($raw_marc, SOURCE_STRING);
     * ?>
     * </code>
     *
     * @param string $source       Name of the file, or a raw MARC string
     * @param int    $type         Source of the input: SOURCE_FILE or SOURCE_STRING
     * @param string $record_class Record class, defaults to File_MARC_Record
     */
    function __construct($source, $type, $record_class)
    {
        $this->xmlwriter = new XMLWriter();
        $this->xmlwriter->openMemory();
        $this->xmlwriter->startDocument('1.0', 'UTF-8');

        $this->record_class = $record_class ?: File_MARC_Record::class;
    }
    // }}}

    // {{{ toXMLHeader()
    /**
     * Initializes the MARCXML output of a record or collection of records 
     *
     * This method produces an XML representation of a MARC record that
     * attempts to adhere to the MARCXML standard documented at
     * http://www.loc.gov/standards/marcxml/
     *
     * @return bool true if successful
     */
    function toXMLHeader()
    {
        $this->xmlwriter->startElement("collection");
        $this->xmlwriter->writeAttribute("xmlns", "http://www.loc.gov/MARC21/slim");
        return true;
    }
    // }}}

    // {{{ getXMLWriter()
    /**
     * Returns the XMLWriter object
     *
     * This method produces an XML representation of a MARC record that
     * attempts to adhere to the MARCXML standard documented at
     * http://www.loc.gov/standards/marcxml/
     *
     * @return XMLWriter XMLWriter instance
     */
    function getXMLWriter()
    {
        return $this->xmlwriter;
    }
    // }}}

    // {{{ toXMLFooter()
    /**
     * Returns the MARCXML collection footer
     *
     * This method produces an XML representation of a MARC record that
     * attempts to adhere to the MARCXML standard documented at
     * http://www.loc.gov/standards/marcxml/
     *
     * @return string           representation of MARC record in MARCXML format
     */
    function toXMLFooter()
    {
        $this->xmlwriter->endElement(); // end collection
        $this->xmlwriter->endDocument();
        return $this->xmlwriter->outputMemory();
    }
    // }}}

}
// }}}
PK��Z5F	'�"�"File/MARCXML.phpnu�[���<?php

/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */

/**
 * Parser for MARC records
 *
 * This package is based on the PHP MARC package, originally called "php-marc",
 * that is part of the Emilda Project (http://www.emilda.org). Christoffer
 * Landtman generously agreed to make the "php-marc" code available under the
 * GNU LGPL so it could be used as the basis of this PEAR package.
 * 
 * PHP version 5
 *
 * LICENSE: This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category  File_Formats
 * @package   File_MARC
 * @author    Dan Scott <dscott@laurentian.ca>
 * @copyright 2007-2010 Dan Scott
 * @license   http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/File_MARC
 * @example   read.php Retrieve specific fields and subfields from a record
 * @example   subfields.php Create new subfields and add them in specific order
 * @example   marc_yaz.php Pretty print a MARC record retrieved through the PECL yaz extension
 */

require_once 'PEAR/Exception.php';
require_once 'File/MARCBASE.php';
require_once 'File/MARC.php';
require_once 'File/MARC/Record.php';
require_once 'File/MARC/Field.php';
require_once 'File/MARC/Control_Field.php';
require_once 'File/MARC/Data_Field.php';
require_once 'File/MARC/Subfield.php';
require_once 'File/MARC/Exception.php';
require_once 'File/MARC/List.php';

// {{{ class File_MARCXML
/**
 * The main File_MARCXML class enables you to return File_MARC_Record
 * objects from an XML stream or string.
 *
 * @category File_Formats
 * @package  File_MARC
 * @author   Dan Scott <dscott@laurentian.ca>
 * @license  http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @link     http://pear.php.net/package/File_MARC
 */
class File_MARCXML extends File_MARCBASE
{

    // {{{ constants

    /**
     * MARC records retrieved from a file
     */
    const SOURCE_FILE = 1;

    /**
     * MARC records retrieved from a binary string 
     */
    const SOURCE_STRING = 2;
    // }}}

    /**
     * MARC records retrieved from a SimpleXMLElement object
     */
    const SOURCE_SIMPLEXMLELEMENT = 3;
    // }}}

    // {{{ properties
    /**
     * Source containing raw records
     * 
     * @var resource
     */
    protected $source;

    /**
     * Source type (SOURCE_FILE or SOURCE_STRING)
     * 
     * @var int
     */
    protected $type;

    /**
     * Counter for MARCXML records in a collection
     *
     * @var int
     */
    protected $counter;

    /**
     * XMLWriter for writing collections
     * 
     * @var XMLWriter
     */
    protected $xmlwriter;
    // }}}

    // {{{ Constructor: function __construct()
    /**
     * Read in MARCXML records
     *
     * This function reads in files, strings or SimpleXMLElement objects that
     * contain one or more MARCXML records.
     *
     * <code>
     * <?php
     * // Retrieve MARC records from a file
     * $journals = new File_MARC('journals.mrc', SOURCE_FILE);
     *
     * // Retrieve MARC records from a string (e.g. Z39 query results)
     * $monographs = new File_MARC($raw_marc, SOURCE_STRING);
     *
     * // Retrieve MARCXML records from a string with a namespace URL
     * $records = new File_MARCXML($xml_data, File_MARC::SOURCE_STRING,"http://www.loc.gov/MARC21/slim");
     *
     * // Retrieve MARCXML records from a file with a namespace prefix
     * $records = new File_MARCXML($xml_data, File_MARC::SOURCE_FILE,"marc",true);
     * ?>
     * </code>
     *
     * @param string|SimpleXMLElement $source        Filename, raw MARC string or SimpleXMLElement object
     * @param int                     $type          Source of the input, either SOURCE_FILE, SOURCE_STRING or SOURCE_SIMPLEXMLELEMENT
     * @param string                  $ns            URI or prefix of the namespace
     * @param bool                    $is_prefix     TRUE if $ns is a prefix, FALSE if it's a URI; defaults to FALSE
     * @param string                  $record_class  Record class, defaults to File_MARC_Record
     */
    function __construct($source, $type = self::SOURCE_FILE, $ns = "", $is_prefix = false, $record_class = null)
    {
        parent::__construct($source, $type, $record_class);

        $this->counter = 0;

        if ($source instanceof \SimpleXMLElement) {
            $type = self::SOURCE_SIMPLEXMLELEMENT;
        }

        switch ($type) {

        case self::SOURCE_SIMPLEXMLELEMENT:
            $this->type = self::SOURCE_SIMPLEXMLELEMENT;
            $this->source = $source;
            break;

        case self::SOURCE_FILE:
            $this->type = self::SOURCE_FILE;
            $this->source = simplexml_load_file($source, "SimpleXMLElement", 0, $ns, $is_prefix);
            break;

        case self::SOURCE_STRING:
            $this->type = self::SOURCE_STRING;
            $this->source = simplexml_load_string($source, "SimpleXMLElement", 0, $ns, $is_prefix);
            break;

        default:
            throw new File_MARC_Exception(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_SOURCE], File_MARC_Exception::ERROR_INVALID_SOURCE);
        }

        if (!$this->source) {
            $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_FILE], array('filename' => $source));
            throw new File_MARC_Exception($errorMessage, File_MARC_Exception::ERROR_INVALID_FILE);
        }
    }
    // }}}

    // {{{ next()
    /**
     * Return next {@link File_MARC_Record} object
     *
     * Decodes the next MARCXML record and returns the {@link File_MARC_Record}
     * object.
     * <code>
     * <?php
     * // Retrieve a set of MARCXML records from a file
     * $journals = new File_MARCXML('journals.xml', SOURCE_FILE);
     *
     * // Iterate through the retrieved records
     * while ($record = $journals->next()) {
     *     print $record;
     *     print "\n";
     * }
     *
     * ?>
     * </code>
     *
     * @return File_MARC_Record next record, or false if there are
     * no more records
     */
    function next()
    {
        if (isset($this->source->record[$this->counter])) {
            $record = $this->source->record[$this->counter++];
        } elseif ($this->source->getName() == "record" && $this->counter == 0) {
            $record = $this->source;
            $this->counter++;
        } else {
            return false;
        }

        if ($record) {
            return $this->_decode($record);
        } else {
            return false;
        }
    }
    // }}}

    // {{{ _decode()
    /**
     * Decode a given MARCXML record
     *
     * @param string $text MARCXML record element
     *
     * @return File_MARC_Record Decoded File_MARC_Record object
     */
    private function _decode($text)
    {
        $marc = new $this->record_class($this);

        // Store leader
        $marc->setLeader($text->leader);

        // go through all the control fields
        foreach ($text->controlfield as $controlfield) {
            $controlfieldattributes = $controlfield->attributes();
            $marc->appendField(new File_MARC_Control_Field((string)$controlfieldattributes['tag'], $controlfield));
        }

        // go through all the data fields
        foreach ($text->datafield as $datafield) {
            $datafieldattributes = $datafield->attributes();
            $subfield_data = array();
            foreach ($datafield->subfield as $subfield) {
                $subfieldattributes = $subfield->attributes();
                $subfield_data[] = new File_MARC_Subfield((string)$subfieldattributes['code'], $subfield);
            }
            
            // If the data is invalid, let's just ignore the one field
            try {
                $new_field = new File_MARC_Data_Field((string)$datafieldattributes['tag'], $subfield_data, $datafieldattributes['ind1'], $datafieldattributes['ind2']);
                $marc->appendField($new_field);
            } catch (Exception $e) {
                $marc->addWarning($e->getMessage());
            }
        }

        return $marc;
    }
    // }}}

}
// }}}

PK��ZSbw�{7{7
File/MARC.phpnu�[���<?php

/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */

/**
 * Parser for MARC records
 *
 * This package is based on the PHP MARC package, originally called "php-marc",
 * that is part of the Emilda Project (http://www.emilda.org). Christoffer
 * Landtman generously agreed to make the "php-marc" code available under the
 * GNU LGPL so it could be used as the basis of this PEAR package.
 * 
 * PHP version 5
 *
 * LICENSE: This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category  File_Formats
 * @package   File_MARC
 * @author    Christoffer Landtman <landtman@realnode.com>
 * @author    Dan Scott <dscott@laurentian.ca>
 * @copyright 2003-2010 Oy Realnode Ab, Dan Scott
 * @license   http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/File_MARC
 * @example   read.php Retrieve specific fields and subfields from a record
 * @example   subfields.php Create new subfields and add them in specific order
 * @example   marc_yaz.php Pretty print a MARC record retrieved through the PECL yaz extension
 */

require_once 'PEAR/Exception.php';
require_once 'File/MARCBASE.php';
require_once 'File/MARC/Record.php';
require_once 'File/MARC/Field.php';
require_once 'File/MARC/Control_Field.php';
require_once 'File/MARC/Data_Field.php';
require_once 'File/MARC/Subfield.php';
require_once 'File/MARC/Exception.php';
require_once 'File/MARC/List.php';

// {{{ class File_MARC
/**
 * The main File_MARC class enables you to return File_MARC_Record
 * objects from a stream or string.
 *
 * @category File_Formats
 * @package  File_MARC
 * @author   Christoffer Landtman <landtman@realnode.com>
 * @author   Dan Scott <dscott@laurentian.ca>
 * @license  http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @link     http://pear.php.net/package/File_MARC
 */
class File_MARC extends File_MARCBASE
{

    // {{{ constants

    /**
     * MARC records retrieved from a file
     */
    const SOURCE_FILE = 1;

    /**
     * MARC records retrieved from a binary string 
     */
    const SOURCE_STRING = 2;

    /**
     * Hexadecimal value for Subfield indicator
     */
    const SUBFIELD_INDICATOR = "\x1F";

    /**
     * Hexadecimal value for End of Field
     */
    const END_OF_FIELD = "\x1E";

    /**
     * Hexadecimal value for End of Record
     */
    const END_OF_RECORD = "\x1D";

    /**
     * Length of the Directory
     */
    const DIRECTORY_ENTRY_LEN = 12;

    /**
     * Length of the Leader
     */
    const LEADER_LEN = 24;

    /**
     * Maximum record length
     */
    const MAX_RECORD_LENGTH = 99999;
    // }}}

    // {{{ properties
    /**
     * Source containing raw records
     * 
     * @var resource
     */
    protected $source;

    /**
     * Source type (SOURCE_FILE or SOURCE_STRING)
     * 
     * @var int
     */
    protected $type;

    /**
     * XMLWriter for writing collections
     * 
     * @var XMLWriter
     */
    protected $xmlwriter;
    // }}}

    // {{{ Constructor: function __construct()
    /**
     * Read in MARC records
     *
     * This function reads in MARC record files or strings that
     * contain one or more MARC records.
     *
     * <code>
     * <?php
     * // Retrieve MARC records from a file
     * $journals = new File_MARC('journals.mrc', SOURCE_FILE);
     *
     * // Retrieve MARC records from a string (e.g. Z39 query results)
     * $monographs = new File_MARC($raw_marc, SOURCE_STRING);
     * ?>
     * </code>
     *
     * @param string $source        Name of the file, or a raw MARC string
     * @param int    $type          Source of the input, either SOURCE_FILE or SOURCE_STRING
     * @param string $record_class  Record class, defaults to File_MARC_Record
     */
    function __construct($source, $type = self::SOURCE_FILE, $record_class = null)
    {

        parent::__construct($source, $type, $record_class);

        switch ($type) {

        case self::SOURCE_FILE:
            $this->type = self::SOURCE_FILE;
            $this->source = fopen($source, 'rb');
            if (!$this->source) {
                 $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_FILE], array('filename' => $source));
                 throw new File_MARC_Exception($errorMessage, File_MARC_Exception::ERROR_INVALID_FILE);
            }
            break;

        case self::SOURCE_STRING:
            $this->type = self::SOURCE_STRING;
            $this->source = explode(File_MARC::END_OF_RECORD, $source);
            break;

        default:
            throw new File_MARC_Exception(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_SOURCE], File_MARC_Exception::ERROR_INVALID_SOURCE);
        }
    }
    // }}}

    // {{{ nextRaw()
    /**
     * Return the next raw MARC record
     *
     * Returns the next raw MARC record, unless all records already have
     * been read.
     *
     * @return string Either a raw record or false
     */
    function nextRaw()
    {
        if ($this->type == self::SOURCE_FILE) {
            $record = stream_get_line($this->source, File_MARC::MAX_RECORD_LENGTH, File_MARC::END_OF_RECORD);

            // Remove illegal stuff that sometimes occurs between records
            $record = preg_replace('/^[\\x0a\\x0d\\x00]+/', "", $record);

        } elseif ($this->type == self::SOURCE_STRING) {
            $record = array_shift($this->source);
        }

        // Exit if we are at the end of the file
        if (!$record) {
            return false;
        }

        // Append the end of record we lost during stream_get_line() or explode()
        $record .= File_MARC::END_OF_RECORD;
        return $record;
    }
    // }}}

    // {{{ next()
    /**
     * Return next {@link File_MARC_Record} object
     *
     * Decodes the next raw MARC record and returns the {@link File_MARC_Record}
     * object.
     * <code>
     * <?php
     * // Retrieve a set of MARC records from a file
     * $journals = new File_MARC('journals.mrc', SOURCE_FILE);
     *
     * // Iterate through the retrieved records
     * while ($record = $journals->next()) {
     *     print $record;
     *     print "\n";
     * }
     *
     * ?>
     * </code>
     *
     * @return File_MARC_Record next record, or false if there are
     * no more records
     */
    function next()
    {
        $raw = $this->nextRaw();
        if ($raw) {
            return $this->_decode($raw);
        } else {
            return false;
        }
    }
    // }}}

    // {{{ _decode()
    /**
     * Decode a given raw MARC record
     *
     * Port of Andy Lesters MARC::File::USMARC->decode() Perl function into PHP.
     *
     * @param string $text Raw MARC record
     *
     * @return File_MARC_Record Decoded File_MARC_Record object
     */
    private function _decode($text)
    {
        $marc = new $this->record_class($this);

        // fallback on the actual byte length
        $record_length = strlen($text);

        $matches = array();
        if (preg_match("/^(\d{5})/", $text, $matches)) {
            // Store record length
            $record_length = $matches[1];
            if ($record_length != strlen($text)) {
                $marc->addWarning(File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INCORRECT_LENGTH], array("record_length" => $record_length, "actual" => strlen($text))));
                // Real beats declared byte length
                $record_length = strlen($text);
            }
        } else {
            $marc->addWarning(File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_NONNUMERIC_LENGTH], array("record_length" => substr($text, 0, 5))));
        }

        if (substr($text, -1, 1) != File_MARC::END_OF_RECORD)
             throw new File_MARC_Exception(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_TERMINATOR], File_MARC_Exception::ERROR_INVALID_TERMINATOR);

        // Store leader
        $marc->setLeader(substr($text, 0, File_MARC::LEADER_LEN));

        // bytes 12 - 16 of leader give offset to the body of the record
        $data_start = 0 + substr($text, 12, 5);

        // immediately after the leader comes the directory (no separator)
        $dir = substr($text, File_MARC::LEADER_LEN, $data_start - File_MARC::LEADER_LEN - 1);  // -1 to allow for \x1e at end of directory

        // character after the directory must be \x1e
        if (substr($text, $data_start-1, 1) != File_MARC::END_OF_FIELD) {
            $marc->addWarning(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_NO_DIRECTORY]);
        }

        // All directory entries 12 bytes long, so length % 12 must be 0
        if (strlen($dir) % File_MARC::DIRECTORY_ENTRY_LEN != 0) {
            $marc->addWarning(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_DIRECTORY_LENGTH]);
        }

        // go through all the fields
        $nfields = strlen($dir) / File_MARC::DIRECTORY_ENTRY_LEN;
        for ($n=0; $n<$nfields; $n++) {
            // As pack returns to key 1, leave place 0 in list empty
            list(, $tag) = unpack("A3", substr($dir, $n*File_MARC::DIRECTORY_ENTRY_LEN, File_MARC::DIRECTORY_ENTRY_LEN));
            list(, $len) = unpack("A3/A4", substr($dir, $n*File_MARC::DIRECTORY_ENTRY_LEN, File_MARC::DIRECTORY_ENTRY_LEN));
            list(, $offset) = unpack("A3/A4/A5", substr($dir, $n*File_MARC::DIRECTORY_ENTRY_LEN, File_MARC::DIRECTORY_ENTRY_LEN));

            // Check directory validity
            if (!preg_match("/^[0-9A-Za-z]{3}$/", $tag)) {
                $marc->addWarning(File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_DIRECTORY_TAG], array("tag" => $tag)));
            }
            if (!preg_match("/^\d{4}$/", $len)) {
                $marc->addWarning(File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_DIRECTORY_TAG_LENGTH], array("tag" => $tag, "len" => $len)));
            }
            if (!preg_match("/^\d{5}$/", $offset)) {
                $marc->addWarning(File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_DIRECTORY_OFFSET], array("tag" => $tag, "offset" => $offset)));
            }
            if ($offset + $len > $record_length) {
                $marc->addWarning(File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_DIRECTORY], array("tag" => $tag)));
            }

            $tag_data = substr($text, $data_start + $offset, $len);

            if (substr($tag_data, -1, 1) == File_MARC::END_OF_FIELD) {
                /* get rid of the end-of-tag character */
                $tag_data = substr($tag_data, 0, -1);
                $len--;
            } else {
                $marc->addWarning(File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_FIELD_EOF], array("tag" => $tag)));
            }

            if (preg_match("/^\d+$/", $tag) and ($tag < 10)) {
                $marc->appendField(new File_MARC_Control_Field($tag, $tag_data));
            } else {
                $subfields = explode(File_MARC::SUBFIELD_INDICATOR, $tag_data);
                $indicators = array_shift($subfields);

                if (strlen($indicators) != 2) {
                    $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_INDICATORS], array("tag" => $tag, "indicators" => $indicators));
                    $marc->addWarning($errorMessage);
                    // Do the best with the indicators we've got
                    if (strlen($indicators) == 1) {
                        $ind1 = $indicators;
                        $ind2 = " ";
                    } else {
                        list($ind1,$ind2) = array(" ", " ");
                    }
                } else {
                    $ind1 = substr($indicators, 0, 1);
                    $ind2 = substr($indicators, 1, 1);
                }

                // Split the subfield data into subfield name and data pairs
                $subfield_data = array();
                foreach ($subfields as $subfield) {
                    if (strlen($subfield) > 0) {
                        $subfield_data[] = new File_MARC_Subfield(substr($subfield, 0, 1), substr($subfield, 1));
                    } else {
                         $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_EMPTY_SUBFIELD], array("tag" => $tag));
                         $marc->addWarning($errorMessage);
                    }
                }

                if (!isset($subfield_data)) {
                     $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_EMPTY_SUBFIELD], array("tag" => $tag));
                     $marc->addWarning($errorMessage);
                }


                // If the data is invalid, let's just ignore the one field
                try {
                    $new_field = new File_MARC_Data_Field($tag, $subfield_data, $ind1, $ind2);
                    $marc->appendField($new_field);
                } catch (Exception $e) {
                    $marc->addWarning($e->getMessage());
                }
            }
        }

        return $marc;
    }
    // }}}

}
// }}}

PK��Z�9g4xUxUFile/MARC/Record.phpnu�[���<?php

/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */

/**
 * Parser for MARC records
 *
 * This package is based on the PHP MARC package, originally called "php-marc",
 * that is part of the Emilda Project (http://www.emilda.org). Christoffer
 * Landtman generously agreed to make the "php-marc" code available under the
 * GNU LGPL so it could be used as the basis of this PEAR package.
 * 
 * PHP version 5
 *
 * LICENSE: This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category  File_Formats
 * @package   File_MARC
 * @author    Christoffer Landtman <landtman@realnode.com>
 * @author    Dan Scott <dscott@laurentian.ca>
 * @copyright 2003-2008 Oy Realnode Ab, Dan Scott
 * @license   http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/File_MARC
 */

// {{{ class File_MARC_Record
/**
 * Represents a single MARC record
 * 
 * A MARC record contains a leader and zero or more fields held within a
 * linked list structure. Fields are represented by {@link File_MARC_Data_Field}
 * objects.
 *
 * @category File_Formats
 * @package  File_MARC
 * @author   Christoffer Landtman <landtman@realnode.com>
 * @author   Dan Scott <dscott@laurentian.ca>
 * @license  http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @link     http://pear.php.net/package/File_MARC
 */
class File_MARC_Record
{

    // {{{ properties
    /**
     * Contains a linked list of {@link File_MARC_Data_Field} objects for
     * this record
     * @var File_MARC_List
     */
    protected $fields;

    /**
     * Record leader
     * @var string
     */
    protected $leader;

    /**
     * Non-fatal warnings generated during parsing
     * @var array
     */
    protected $warnings;

    /**
     * XMLWriter for writing collections
     * 
     * @var XMLWriter
     */
    protected $marcxml;

    /**
     * MARC instance for access to the XML header/footer methods
     * We need this so that we can properly wrap a collection of MARC records.
     * 
     * @var File_MARC
     */
    protected $marc;

    // }}}

    // {{{ Constructor: function __construct()
    /**
     * Start function
     *
     * Set all variables to defaults to create new File_MARC_Record object
     *
     * @param File_MARC $marc MARC record from File_MARC or File_MARCXML
     *
     * @return true 
     */
    function __construct($marc = null)
    {
        $this->fields = new File_MARC_List();
        $this->setLeader(str_repeat(' ', 24));
        if (!$marc) {
            $marc = new File_MARC(null, File_MARC::SOURCE_STRING); // oh the hack
        }
        $this->marc = $marc;
        $this->marcxml = $marc->getXMLWriter();
    }
    // }}}

    // {{{ Destructor: function __destruct()
    /**
     * Destroys the data field
     */
    function __destruct()
    {
        $this->fields = null;
        $this->warnings = null;
    }
    // }}}

    // {{{ getLeader()
    /**
     * Get MARC leader
     *
     * Returns the leader for the MARC record. No validation
     * on the specified leader is performed.
     *
     * @return string returns the leader
     */
    function getLeader()
    {
        return (string)$this->leader;
    }
    // }}}

    // {{{ setLeader()
    /**
     * Set MARC record leader
     *
     * Sets the leader for the MARC record. No validation
     * on the specified leader is performed.
     *
     * @param string $leader Leader
     *
     * @return string returns the leader
     */
    function setLeader($leader)
    {
        $this->leader = $leader;
        return $this->leader;
    }
    // }}}

    // {{{ appendField()
    /**
     * Appends field to MARC record
     *
     * Adds a {@link File_MARC_Control_Field} or {@link File_MARC_Data_Field}
     * object to the end of the existing list of fields.
     *
     * @param File_MARC_Field $new_field The field to add
     *
     * @return File_MARC_Field The field that was added
     */
    function appendField(File_MARC_Field $new_field)
    {
        /* Append as the last field in the record */
        $this->fields->appendNode($new_field);
        return $new_field;
    }
    // }}}

    // {{{ prependField()
    /**
     * Prepends field to MARC record
     *
     * Adds a {@link File_MARC_Control_Field} or {@link File_MARC_Data_Field}
     * object to the start of to the existing list of fields.
     *
     * @param File_MARC_Field $new_field The field to add
     *
     * @return File_MARC_Field The field that was added
     */
    function prependField(File_MARC_Field $new_field)
    {
        $this->fields->prependNode($new_field);
        return $new_field;
    }
    // }}}

    // {{{ insertField()
    /**
     * Inserts a field in the MARC record relative to an existing field
     *
     * Inserts a {@link File_MARC_Control_Field} or {@link File_MARC_Data_Field}
     * object before or after a specified existing field.
     *
     * <code>
     * // Example: Insert a new field before the first 650 field
     *
     * // Create the new field
     * $subfields[] = new File_MARC_Subfield('a', 'Scott, Daniel.');
     * $new_field = new File_MARC_Data_Field('100', $subfields, 0, null);
     *
     * // Retrieve the target field for our insertion point
     * $subject = $record->getFields('650');
     *
     * // Insert the new field
     * if (is_array($subject)) {
     *     $record->insertField($new_field, $subject[0], true);
     * }
     * elseif ($subject) {
     *     $record->insertField($new_field, $subject, true);
     * }
     * </code>
     *
     * @param File_MARC_Field $new_field      The field to add
     * @param File_MARC_Field $existing_field The target field
     * @param bool            $before         Insert the new field before the existing field if true, after the existing field if false
     *
     * @return File_MARC_Field                The field that was added
     */
    function insertField(File_MARC_Field $new_field, File_MARC_Field $existing_field, $before = false)
    {
        $this->fields->insertNode($new_field, $existing_field, $before);
        return $new_field;
    }
    // }}}

    // {{{ _buildDirectory()
    /**
     * Build record directory
     *
     * Generate the directory of the record according to the current contents
     * of the record.
     *
     * @return array Array ($fields, $directory, $total, $base_address)
     */
    private function _buildDirectory()
    {
        // Vars
        $fields = array();
        $directory = array();
        $data_end = 0;

        foreach ($this->fields as $field) {
            // No empty fields allowed
            if (!$field->isEmpty()) {
                // Get data in raw format
                $str = $field->toRaw();
                $fields[] = $str;

                // Create directory entry
                $len = strlen($str);
                $direntry = sprintf("%03s%04d%05d", $field->getTag(), $len, $data_end);
                $directory[] = $direntry;
                $data_end += $len;
            }
        }

        /**
         * Rules from MARC::Record::USMARC
         */
        $base_address
            = File_MARC::LEADER_LEN +    // better be 24
                (count($directory) * File_MARC::DIRECTORY_ENTRY_LEN) +
                                // all the directory entries
                1;              // end-of-field marker


        $total
            = $base_address +  // stuff before first field
                $data_end +      // Length of the fields
                1;              // End-of-record marker


        return array($fields, $directory, $total, $base_address);
    }
    // }}}

    // {{{ setLeaderLengths()
    /**
     * Set MARC record leader lengths
     *
     * Set the Leader lengths of the record according to defaults specified in
     * {@link http://www.loc.gov/marc/bibliographic/ecbdldrd.html}
     *
     * @param int $record_length Record length
     * @param int $base_address  Base address of data
     *
     * @return bool              Success or failure
     */
    function setLeaderLengths($record_length, $base_address)
    {
        if (!is_int($record_length)) {
            return false;
        }
        if (!is_int($base_address)) {
            return false;
        }

        // Set record length
        $this->setLeader(substr_replace($this->getLeader(), sprintf("%05d", $record_length), 0, 5));
        $this->setLeader(substr_replace($this->getLeader(), sprintf("%05d", $base_address), File_MARC::DIRECTORY_ENTRY_LEN, 5));
        $this->setLeader(substr_replace($this->getLeader(), '22', 10, 2));
        $this->setLeader(substr_replace($this->getLeader(), '4500', 20, 4));

        if (strlen($this->getLeader()) > File_MARC::LEADER_LEN) {
            // Avoid incoming leaders that are mangled to be overly long
            $this->setLeader(substr($this->getLeader(), 0, File_MARC::LEADER_LEN));
            $this->addWarning("Input leader was too long; truncated to " . File_MARC::LEADER_LEN . " characters");
        }
        return true;
    }
    // }}}

    // {{{ getField()
    /**
     * Return the first {@link File_MARC_Data_Field} or
     * {@link File_MARC_Control_Field} object that matches the specified tag
     * name. Returns false if no match is found.
     *
     * @param string $spec tag name
     * @param bool   $pcre if true, then match as a regular expression
     *
     * @return {@link File_MARC_Data_Field}|{@link File_MARC_Control_Field} first field that matches the requested tag name
     */
    function getField($spec = null, $pcre = null)
    {
        foreach ($this->fields as $field) {
            if (($pcre
                && preg_match("/$spec/", $field->getTag()))
                || (!$pcre
                && $spec == $field->getTag())
            ) {
                return $field;
            }
        }
        return false;
    }
    // }}}

    // {{{ getFields()
    /**
     * Return an array or {@link File_MARC_List} containing all
     * {@link File_MARC_Data_Field} or  {@link File_MARC_Control_Field} objects
     * that match the specified tag name. If the tag name is omitted all
     * fields are returned.
     *
     * @param string $spec tag name
     * @param bool   $pcre if true, then match as a regular expression
     *
     * @return File_MARC_List|array {@link File_MARC_Data_Field} or
     * {@link File_MARC_Control_Field} objects that match the requested tag name
     */
    function getFields($spec = null, $pcre = null)
    {
        if (!$spec) {
            return $this->fields;
        }

        // Okay, we're actually looking for something specific
        $matches = array();
        foreach ($this->fields as $field) {
            if (($pcre && preg_match("/$spec/", $field->getTag()))
                || (!$pcre && $spec == $field->getTag())
            ) {
                $matches[] = $field;
            }
        }
        return $matches;
    }
    // }}}

    // {{{ deleteFields()
    /**
     * Delete all occurrences of a field matching a tag name from the record.
     *
     * @param string $tag  tag for the fields to be deleted
     * @param bool   $pcre if true, then match as a regular expression
     *
     * @return int         number of fields that were deleted
     */
    function deleteFields($tag, $pcre = null)
    {
        $cnt = 0;
        foreach ($this->getFields() as $field) {
            if (($pcre
                && preg_match("/$tag/", $field->getTag()))
                || (!$pcre
                && $tag == $field->getTag())
            ) {
                $field->delete();
                $cnt++;
            }
        }
        return $cnt;
    }
    // }}}

    // {{{ addWarning()
    /**
     * Add a warning to the MARC record that something non-fatal occurred during
     * parsing.
     *
     * @param string $warning warning message
     *
     * @return true
     */
    public function addWarning($warning)
    {
        $this->warnings[] = $warning;
    }
    // }}}

    // {{{ getWarnings()
    /**
     * Return the array of warnings from the MARC record.
     *
     * @return array warning messages
     */
    public function getWarnings()
    {
        return $this->warnings;
    }
    // }}}

    // {{{ output methods
    /**
     * ========== OUTPUT METHODS ==========
     */

    // {{{ toRaw()
    /**
     * Return the record in raw MARC format.
     *
     * If you have modified an existing MARC record or created a new MARC
     * record, use this method to save the record for use in other programs
     * that accept the MARC format -- for example, your integrated library
     * system.
     *
     * <code>
     * // Example: Modify a record and save the output to a file
     * $record->deleteFields('650');
     *
     * // Now that the record has no subject fields, save it to disk
     * fopen($file, '/home/dan/no_subject.mrc', 'w');
     * fwrite($file, $record->toRaw());
     * fclose($file);
     * </code>
     *
     * @return string Raw MARC data
     */
    function toRaw()
    {
        list($fields, $directory, $record_length, $base_address) = $this->_buildDirectory();
        $this->setLeaderLengths($record_length, $base_address);

        /**
         * Glue together all parts
         */
        return $this->getLeader().implode("", $directory).File_MARC::END_OF_FIELD.implode("", $fields).File_MARC::END_OF_RECORD;
    }
    // }}}

    // {{{ __toString()
    /**
     * Return the MARC record in a pretty printed string
     *
     * This method produces an easy-to-read textual display of a MARC record.
     *
     * The structure is roughly:
     * <tag> <ind1> <ind2> _<code><data>
     *                     _<code><data>
     *
     * @return string Formatted representation of MARC record
     */
    function __toString()
    {
        // Begin output
        $formatted = "LDR " . $this->getLeader() . "\n";
        foreach ($this->fields as $field) {
            if (!$field->isEmpty()) {
                $formatted .= $field->__toString() . "\n";
            }
        }
        return $formatted;
    }
    // }}}

    // {{{ toJSON()
    /**
     * Return the MARC record in JSON format
     *
     * This method produces a JSON representation of a MARC record. The input
     * encoding must be UTF8, otherwise the returned values will be corrupted.
     *
     * @return string          representation of MARC record in JSON format
     *
     * @todo Fix encoding input / output issues (PHP 6.0 required?)
     */
    function toJSON()
    {
        $json = new StdClass();
        $json->leader = utf8_encode($this->getLeader());

        /* Start fields */
        $fields = array();
        foreach ($this->fields as $field) {
            if (!$field->isEmpty()) {
                switch(get_class($field)) {
                case "File_MARC_Control_Field":
                    $fields[] = array(utf8_encode($field->getTag()) => utf8_encode($field->getData()));
                    break;

                case "File_MARC_Data_Field":
                    $subs = array();
                    foreach ($field->getSubfields() as $sf) {
                        $subs[] = array(utf8_encode($sf->getCode()) => utf8_encode($sf->getData()));
                    }
                    $contents = new StdClass();
                    $contents->ind1 = utf8_encode($field->getIndicator(1));
                    $contents->ind2 = utf8_encode($field->getIndicator(2));
                    $contents->subfields = $subs;
                    $fields[] = array(utf8_encode($field->getTag()) => $contents);
                    break;
                }
            }
        }
        /* End fields and record */

        $json->fields = $fields;
        $json_rec = json_encode($json);
        // Required because json_encode() does not let us stringify integer keys
        return preg_replace('/("subfields":)(.*?)\["([^\"]+?)"\]/', '\1\2{"0":"\3"}', $json_rec);
    }

    // }}}

    // {{{ toJSONHash()
    /**
     * Return the MARC record in Bill Dueber's MARC-HASH JSON format
     *
     * This method produces a JSON representation of a MARC record as defined
     * at http://robotlibrarian.billdueber.com/new-interest-in-marc-hash-json/
     * The input * encoding must be UTF8, otherwise the returned values will
     * be corrupted.
     *
     * @return string          representation of MARC record in JSON format
     *
     * @todo Fix encoding input / output issues (PHP 6.0 required?)
     */
    function toJSONHash()
    {
        $json = new StdClass();
        $json->type = "marc-hash";
        $json->version = array(1, 0);
        $json->leader = utf8_encode($this->getLeader());

        /* Start fields */
        $fields = array();
        foreach ($this->fields as $field) {
            if (!$field->isEmpty()) {
                switch(get_class($field)) {
                case "File_MARC_Control_Field":
                    $fields[] = array(utf8_encode($field->getTag()), utf8_encode($field->getData()));
                    break;

                case "File_MARC_Data_Field":
                    $subs = array();
                    foreach ($field->getSubfields() as $sf) {
                        $subs[] = array(utf8_encode($sf->getCode()), utf8_encode($sf->getData()));
                    }
                    $contents = array(
                        utf8_encode($field->getTag()),
                        utf8_encode($field->getIndicator(1)),
                        utf8_encode($field->getIndicator(2)),
                        $subs
                    );
                    $fields[] = $contents;
                    break;
                }
            }
        }
        /* End fields and record */

        $json->fields = $fields;
        return json_encode($json);
    }

    // }}}


    // {{{ toXML()
    /**
     * Return the MARC record in MARCXML format
     *
     * This method produces an XML representation of a MARC record that
     * attempts to adhere to the MARCXML standard documented at
     * http://www.loc.gov/standards/marcxml/
     *
     * @param string $encoding output encoding for the MARCXML record
     * @param bool   $indent   pretty-print the MARCXML record
     * @param bool   $single   wrap the <record> element in a <collection> element
     *
     * @return string          representation of MARC record in MARCXML format
     *
     * @todo Fix encoding input / output issues (PHP 6.0 required?)
     */
    function toXML($encoding = "UTF-8", $indent = true, $single = true)
    {
        $this->marcxml->setIndent($indent);
        if ($single) {
            $this->marcxml->startElement("collection");
            $this->marcxml->writeAttribute("xmlns", "http://www.loc.gov/MARC21/slim");
            $this->marcxml->startElement("record");
        } else {
            $this->marcxml->startElement("record");
            $this->marcxml->writeAttribute("xmlns", "http://www.loc.gov/MARC21/slim");
        }
        

        // MARCXML schema has some strict requirements
        // We'll set reasonable defaults to avoid invalid MARCXML
        $xmlLeader = $this->getLeader();

        // Record status
        if ($xmlLeader[5] == " ") {
            // Default to "n" (new record)
            $xmlLeader[5] = "n";
        }

        // Type of record
        if ($xmlLeader[6] == " ") {
            // Default to "a" (language material)
            $xmlLeader[6] = "a";
        }

        $this->marcxml->writeElement("leader", $xmlLeader);

        foreach ($this->fields as $field) {
            if (!$field->isEmpty()) {
                switch(get_class($field)) {
                case "File_MARC_Control_Field":
                    $this->marcxml->startElement("controlfield");
                    $this->marcxml->writeAttribute("tag", $field->getTag());
                    $this->marcxml->text($field->getData());
                    $this->marcxml->endElement(); // end control field
                    break;

                case "File_MARC_Data_Field":
                    $this->marcxml->startElement("datafield");
                    $this->marcxml->writeAttribute("tag", $field->getTag());
                    $this->marcxml->writeAttribute("ind1", $field->getIndicator(1));
                    $this->marcxml->writeAttribute("ind2", $field->getIndicator(2));
                    foreach ($field->getSubfields() as $subfield) {
                        $this->marcxml->startElement("subfield");
                        $this->marcxml->writeAttribute("code", $subfield->getCode());
                        $this->marcxml->text($subfield->getData());
                        $this->marcxml->endElement(); // end subfield
                    }
                    $this->marcxml->endElement(); // end data field
                    break;
                }
            }
        }

        $this->marcxml->endElement(); // end record
        if ($single) {
            $this->marcxml->endElement(); // end collection
            $this->marcxml->endDocument();
        }
        return $this->marcxml->outputMemory();
    }
    // }}}

}
// }}}

PK��Z(#�~��File/MARC/Exception.phpnu�[���<?php

/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */

/**
 * Parser for MARC records
 *
 * This package is based on the PHP MARC package, originally called "php-marc",
 * that is part of the Emilda Project (http://www.emilda.org). Christoffer
 * Landtman generously agreed to make the "php-marc" code available under the
 * GNU LGPL so it could be used as the basis of this PEAR package.
 * 
 * PHP version 5
 *
 * LICENSE: This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category  File_Formats
 * @package   File_MARC
 * @author    Christoffer Landtman <landtman@realnode.com>
 * @author    Dan Scott <dscott@laurentian.ca>
 * @copyright 2003-2008 Oy Realnode Ab, Dan Scott
 * @license   http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/File_MARC
 */

// {{{ class File_MARC_Exception extends PEAR_Exception
/**
 * The File_MARC_Exception class enables error-handling
 * for the File_MARC package.
 *
 * @category File_Formats
 * @package  File_MARC
 * @author   Dan Scott <dscott@laurentian.ca>
 * @license  http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @link     http://pear.php.net/package/File_MARC
 */
class File_MARC_Exception extends PEAR_Exception
{
    // {{{ Error codes
    /**
     * File could not be opened
     */
    const ERROR_INVALID_FILE = -1;

    /**
     * User passed an unknown SOURCE_ constant
     */
    const ERROR_INVALID_SOURCE = -2;

    /**
     * MARC record ended with an invalid terminator
     */
    const ERROR_INVALID_TERMINATOR = -3;

    /**
     * No directory was found for the MARC record
     */
    const ERROR_NO_DIRECTORY = -4;

    /**
     * An entry in the MARC directory was not 12 bytes
     */
    const ERROR_INVALID_DIRECTORY_LENGTH = -5;

    /**
     * An entry in the MARC directory specified an invalid tag
     */
    const ERROR_INVALID_DIRECTORY_TAG = -6;

    /**
     * An entry in the MARC directory specified an invalid tag length
     */
    const ERROR_INVALID_DIRECTORY_TAG_LENGTH = -7;

    /**
     * An entry in the MARC directory specified an invalid field offset
     */
    const ERROR_INVALID_DIRECTORY_OFFSET = -8;

    /**
     * An entry in the MARC directory runs past the end of the record
     */
    const ERROR_INVALID_DIRECTORY = -9;

    /**
     * A field does not end with the expected end-of-field character
     */
    const ERROR_FIELD_EOF = -10;

    /**
     * A field has invalid indicators
     */
    const ERROR_INVALID_INDICATORS = -11;

    /**
     * A subfield is defined, but has no data
     */
    const ERROR_EMPTY_SUBFIELD = -12;

    /**
     * An indicator other than 1 or 2 was requested
     */
    const ERROR_INVALID_INDICATOR_REQUEST = -13;

    /**
     * An invalid mode for adding a field was specified
     */
    const ERROR_INSERTFIELD_MODE = -14;

    /**
     * An invalid object was passed instead of a File_MARC_Field object
     */
    const ERROR_INVALID_FIELD = -15;

    /**
     * An invalid object was passed instead of a File_MARC_Subfield object
     */
    const ERROR_INVALID_SUBFIELD = -16;

    /**
     * An invalid mode for adding a subfield was specified
     */
    const ERROR_INSERTSUBFIELD_MODE = -17;

    /**
     * The length in the MARC leader does not match the actual record length
     */
    const ERROR_INCORRECT_LENGTH = -18;

    /**
     * The length field in the leader was less than five characters long
     */
    const ERROR_MISSING_LENGTH = -19;

    /**
     * A five-digit length could not be found in the MARC leader
     */
    const ERROR_NONNUMERIC_LENGTH = -20;

    /**
     * Tag does not adhere to MARC standards
     */
    const ERROR_INVALID_TAG = -21;

    /**
     * A field has invalid indicators
     */
    const ERROR_INVALID_INDICATOR = -22;
    // }}}

    // {{{ error messages
    public static $messages = array(
        self::ERROR_EMPTY_SUBFIELD => 'No subfield data found in tag "%tag%"', 
        self::ERROR_FIELD_EOF => 'Field for tag "%tag%" does not end with an end of field character', 
        self::ERROR_INCORRECT_LENGTH => 'Invalid record length: Leader says "%record_length%" bytes; actual record length is "%actual%"', 
        self::ERROR_INSERTFIELD_MODE => 'insertField() mode "%mode%" was not recognized', 
        self::ERROR_INSERTSUBFIELD_MODE => 'insertSubfield() mode "%mode%" was not recognized', 
        self::ERROR_INVALID_DIRECTORY => 'Directory entry for tag "%tag%" runs past the end of the record', 
        self::ERROR_INVALID_DIRECTORY_LENGTH => 'Invalid directory length', 
        self::ERROR_INVALID_DIRECTORY_OFFSET => 'Invalid offset "%offset%" for tag "%tag%" in directory', 
        self::ERROR_INVALID_DIRECTORY_TAG => 'Invalid tag "%tag%" in directory', 
        self::ERROR_INVALID_DIRECTORY_TAG_LENGTH => 'Invalid length "%len%" in directory for tag "%tag%"', 
        self::ERROR_INVALID_FIELD => 'Specified field must be a File_MARC_Data_Field or File_MARC_Control_Field object, but was "%field%"', 
        self::ERROR_INVALID_FILE => 'Invalid input file "%filename%"', 
        self::ERROR_INVALID_INDICATOR_REQUEST => 'Attempt to access indicator "%indicator%" failed; 1 and 2 are the only valid indicators', 
        self::ERROR_INVALID_INDICATORS => 'Invalid indicators "%indicators%" forced to blanks for tag "%tag%"', 
        self::ERROR_INVALID_SOURCE => "Invalid source for MARC records", 
        self::ERROR_INVALID_SUBFIELD => 'Specified field must be a File_MARC_Subfield object, but was "%class%"', 
        self::ERROR_INVALID_TAG => 'Tag "%tag%" is not a valid tag.', 
        self::ERROR_INVALID_TERMINATOR => 'Invalid record terminator', 
        self::ERROR_MISSING_LENGTH => "Couldn't find record length", 
        self::ERROR_NO_DIRECTORY => 'No directory found', 
        self::ERROR_NONNUMERIC_LENGTH => 'Record length "%record_length%" is not numeric',
        self::ERROR_INVALID_INDICATOR => 'Illegal indicator "%indicator%" in field "%tag%" forced to blank', 
    );
    // }}}

    // {{{ formatError()
    /**
     * Replaces placeholder tokens in an error message with actual values.
     *
     * This method enables you to internationalize the messages for the
     * File_MARC class by simply replacing the File_MARC_Exception::$messages
     * array with translated values for the messages.
     *
     * @param string $message     Error message containing placeholders
     * @param array  $errorValues Actual values to substitute for placeholders
     *
     * @return string             Formatted message
     */
    public static function formatError($message, $errorValues)
    {
        foreach ($errorValues as $token => $value) {
            $message = preg_replace("/\%$token\%/", $value, $message);
        }
        return $message;
    }
    // }}}
}
// }}}

PK��Z�S��hhFile/MARC/List.phpnu�[���<?php

/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */

/**
 * Parser for MARC records
 *
 * This package is based on the PHP MARC package, originally called "php-marc",
 * that is part of the Emilda Project (http://www.emilda.org). Christoffer
 * Landtman generously agreed to make the "php-marc" code available under the
 * GNU LGPL so it could be used as the basis of this PEAR package.
 *
 * PHP version 5
 *
 * LICENSE: This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category  File_Formats
 * @package   File_MARC
 * @author    Christoffer Landtman <landtman@realnode.com>
 * @author    Dan Scott <dscott@laurentian.ca>
 * @copyright 2003-2008 Oy Realnode Ab, Dan Scott
 * @license   http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/File_MARC
 */

// {{{ class File_MARC_List extends SplDoublyLinkedList
/**
 * The File_MARC_List class extends the SplDoublyLinkedList class
 * to override the key() method in a meaningful way for foreach() iterators.
 *
 * For the list of {@link File_MARC_Field} objects in a {@link File_MARC_Record}
 * object, the key() method returns the tag name of the field.
 *
 * For the list of {@link File_MARC_Subfield} objects in a {@link
 * File_MARC_Data_Field} object, the key() method returns the code of
 * the subfield.
 *
 * <code>
 * // Iterate through the fields in a record with key=>value iteration
 * foreach ($record->getFields() as $tag=>$value) {
 *     print "$tag: ";
 *     if ($value instanceof File_MARC_Control_Field) {
 *         print $value->getData();
 *     }
 *     else {
 *         // Iterate through the subfields in this data field
 *         foreach ($value->getSubfields() as $code=>$subdata) {
 *             print "_$code";
 *         }
 *     }
 *     print "\n";
 * }
 * </code>
 *
 * @category File_Formats
 * @package  File_MARC
 * @author   Dan Scott <dscott@laurentian.ca>
 * @license  http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @link     http://pear.php.net/package/File_MARC
 */
class File_MARC_List extends SplDoublyLinkedList
{

    // {{{ properties
    /**
     * Position of the subfield
     * @var int
     */
    protected $position;

    // }}}

    // {{{ key()
    /**
     * Returns the tag for a {@link File_MARC_Field} object, or the code
     * for a {@link File_MARC_Subfield} object.
     *
     * This method enables you to use a foreach iterator to retrieve
     * the tag or code as the key for the iterator.
     *
     * @return string returns the tag or code
     */
    function key()
    {
        if ($this->current() instanceof File_MARC_Field) {
            return $this->current()->getTag();
        } elseif ($this->current() instanceof File_MARC_Subfield) {
            return $this->current()->getCode();
        }
        return false;
    }
    // }}}

    // {{{ function insertNode()
    /**
     * Inserts a node into the linked list, based on a reference node that
     * already exists in the list.
     *
     * @param mixed $new_node      New node to add to the list
     * @param mixed $existing_node Reference position node
     * @param bool  $before        Insert new node before or after the existing node
     *
     * @return bool Success or failure
     **/
    public function insertNode($new_node, $existing_node, $before = false)
    {
        $pos = 0;
        $exist_pos = $existing_node->getPosition();
        $this->rewind();

        // Now add the node according to the requested mode
        switch ($before) {

        case true:
            $this->add($exist_pos, $new_node);
            break;

        // after
        case false:
            if ($this->offsetExists($exist_pos + 1)) {
                $this->add($exist_pos + 1, $new_node);
            } else {
                $this->appendNode($new_node);
                return true;
            }
            break;
        }

        // Fix positions
        $this->rewind();
        while ($n = $this->current()) {
            $n->setPosition($pos);
            $this->next();
            $pos++;
        }

        return true;
    }
    // }}}

    // {{{ function appendNode()
    /**
     * Adds a node onto the linked list.
     *
     * @param mixed $new_node New node to add to the list
     *
     * @return void
     **/
    public function appendNode($new_node)
    {
        $pos = $this->count();
        $new_node->setPosition($pos);
        $this->push($new_node);
    }
    // }}}

    // {{{ function prependNode()
    /**
     * Adds a node to the start of the linked list.
     *
     * @param mixed $new_node New node to add to the list
     *
     * @return void
     **/
    public function prependNode($new_node)
    {
        $this->insertNode($new_node, $this->bottom(), true);
    }
    // }}}

    // {{{ function deleteNode()
    /**
     * Deletes a node from the linked list.
     *
     * @param mixed $node Node to delete from the list
     *
     * @return void
     **/
    public function deleteNode($node)
    {
        $target_pos = $node->getPosition();
        $this->rewind();
        $pos = 0;

        // Omit target node and adjust pos of remainder
        $done = false;
        try {
            while ($n = $this->current()) {
                if ($pos == $target_pos && !$done) {
                    $done = true;
                    $this->next();
                    $this->offsetUnset($pos);
                } elseif ($pos >= $target_pos) {
                    $n->setPosition($pos);
                    $pos++;
                    $this->next();
                } else {
                    $pos++;
                    $this->next();
                }
            }
        }
        catch (Exception $e) {
            // no-op - shift() throws an exception, sigh
        }

    }
    // }}}

    // {{{ setPosition()
    /**
     * Sets position of the subfield
     *
     * @param string $pos new position of the subfield
     *
     * @return void
     */
    function setPosition($pos)
    {
        $this->position = $pos;
    }
    // }}}

    // {{{ getPosition()
    /**
     * Return position of the subfield
     *
     * @return int data
     */
    function getPosition()
    {
        return $this->position;
    }
    // }}}

}
// }}}

PK��Z�+����File/MARC/Field.phpnu�[���<?php

/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */

/**
 * Parser for MARC records
 *
 * This package is based on the PHP MARC package, originally called "php-marc",
 * that is part of the Emilda Project (http://www.emilda.org). Christoffer
 * Landtman generously agreed to make the "php-marc" code available under the
 * GNU LGPL so it could be used as the basis of this PEAR package.
 * 
 * PHP version 5
 *
 * LICENSE: This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category  File_Formats
 * @package   File_MARC
 * @author    Christoffer Landtman <landtman@realnode.com>
 * @author    Dan Scott <dscott@laurentian.ca>
 * @copyright 2003-2008 Oy Realnode Ab, Dan Scott
 * @license   http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/File_MARC
 */

require_once 'File/MARC/List.php';

// {{{ class File_MARC_Field extends File_MARC_List
/**
 * The File_MARC_Field class is expected to be extended to reflect the
 * requirements of control and data fields.
 *
 * Every MARC field contains a tag name.
 *
 * @category File_Formats
 * @package  File_MARC
 * @author   Christoffer Landtman <landtman@realnode.com>
 * @author   Dan Scott <dscott@laurentian.ca>
 * @license  http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @link     http://pear.php.net/package/File_MARC
 */
class File_MARC_Field extends File_MARC_List
{

    // {{{ properties
    /**
     * The tag name of the Field
     * @var string
     */
    protected $tag;
    // }}}

    // {{{ Constructor: function __construct()
    /**
     * File_MARC_Field constructor
     *
     * Create a new {@link File_MARC_Field} object from passed arguments. We
     * define placeholders for the arguments required by child classes.
     *
     * @param string $tag       tag
     * @param string $subfields placeholder for subfields or control data
     * @param string $ind1      placeholder for first indicator
     * @param string $ind2      placeholder for second indicator
     */
    function __construct($tag, $subfields = null, $ind1 = null, $ind2 = null) 
    {
        $this->tag = $tag;

        // Check if valid tag
        if (!preg_match("/^[0-9A-Za-z]{3}$/", $tag)) {
             $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_TAG], array("tag" => $tag));
             throw new File_MARC_Exception($errorMessage, File_MARC_Exception::ERROR_INVALID_TAG);
        }

    }
    // }}}

    // {{{ Destructor: function __destruct()
    /**
     * Destroys the data field
     */
    function __destruct()
    {
        $this->tag = null;
    }
    // }}}

    // {{{ getTag()
    /**
     * Returns the tag for this {@link File_MARC_Field} object
     *
     * @return string returns the tag number of the field
     */
    function getTag()
    {
        return (string)$this->tag;
    }
    // }}}

    // {{{ setTag()
    /**
     * Sets the tag for this {@link File_MARC_Field} object
     *
     * @param string $tag new value for the tag
     *
     * @return string returns the tag number of the field
     */
    function setTag($tag)
    {
        $this->tag = $tag;
        return $this->getTag();
    }
    // }}}

    // {{{ isEmpty()
    /**
     * Is empty
     *
     * Checks if the field is empty.
     *
     * @return bool Returns true if the field is empty, otherwise false
     */
    function isEmpty()
    {
        if ($this->getTag()) {
            return false;
        }
        // It is empty
        return true;
    }
    // }}}

    // {{{ isControlField()
    /**
     * Is control field
     *
     * Checks if the field is a control field.
     *
     * @return bool Returns true if the field is a control field, otherwise false
     */
    function isControlField()
    {
        if (get_class($this) == 'File_MARC_Control_Field') {
            return true;
        }
        return false;
    }
    // }}}

    // {{{ isDataField()
    /**
     * Is data field
     *
     * Checks if the field is a data field.
     *
     * @return bool Returns true if the field is a data field, otherwise false
     */
    function isDataField()
    {
        if (get_class($this) == 'File_MARC_Data_Field') {
            return true;
        }
        return false;
    }
    // }}}


    /**
     * ========== OUTPUT METHODS ==========
     */

    // {{{ __toString()
    /**
     * Return Field formatted
     *
     * Return Field as a formatted string.
     *
     * @return string Formatted output of Field
     */
    function __toString()
    {
        return (string)$this->getTag();
    }
    // }}}

    // {{{ toRaw()
    /**
     * Return field in raw MARC format (stub)
     *
     * Return the field formatted in raw MARC for saving into MARC files. This
     * stub method is extended by the child classes.
     *
     * @return bool Raw MARC
     */
    function toRaw()
    {
        return false;
    }
    // }}}

    // {{{ formatField()
    /**
     * Pretty print a MARC_Field object without tags, indicators, etc.
     *
     * @param array $exclude Subfields to exclude from formatted output
     * 
     * @return string Returns the formatted field data
     */

    function formatField($exclude = array('2'))
    {
        if ($this->isControlField()) {
            return $this->getData();
        } else {
            $out = '';
            foreach ($this->getSubfields() as $subfield) {
                if (substr($this->getTag(), 0, 1) == '6' and (in_array($subfield->getCode(), array('v','x','y','z')))) {
                    $out .= ' -- ' . $subfield->getData();
                } elseif (!in_array($subfield->getCode(), $exclude)) {
                    $out .= ' ' . $subfield->getData();
                }
            }
            return trim($out);
        }
    }
    // }}}
}
// }}}

PK��Z�IC�(A(AFile/MARC/Lint/CodeData.phpnu�[���<?php

/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */

/**
 * Code Data to support Lint for MARC records
 *
 * This module is adapted from the MARC::Lint::CodeData CPAN module for Perl,
 * maintained by Bryan Baldus <eijabb@cpan.org> and available for download at
 * http://search.cpan.org/~eijabb/
 *
 * Current MARC::Lint::CodeData version used as basis for this module: 1.37
 *
 * PHP version 5
 *
 * LICENSE: This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category  File_Formats
 * @package   File_MARC
 * @author    Demian Katz <demian.katz@villanova.edu>
 * @author    Dan Scott <dscott@laurentian.ca>
 * @copyright 2003-2019 Oy Realnode Ab, Dan Scott
 * @license   http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @version   CVS: $Id: Record.php 308146 2011-02-08 20:36:20Z dbs $
 * @link      http://pear.php.net/package/File_MARC
 */

// {{{ class File_MARC_Lint
/**
 * Contains codes from the MARC code lists for Geographic Areas, Languages, and
 * Countries.
 *
 * Code data is used for validating fields 008, 040, 041, and 043.
 *
 * Also, sources for subfield 2 in 600-651 and 655.
 *
 * Note: According to the official MARC documentation, Sears is not a valid 655
 * term. The code data below treats it as valid, in anticipation of a change in
 * the official documentation.
 *
 * @category File_Formats
 * @package  File_MARC
 * @author   Demian Katz <demian.katz@villanova.edu>
 * @author   Dan Scott <dscott@laurentian.ca>
 * @license  http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @link     http://pear.php.net/package/File_MARC
 */
class File_MARC_Lint_CodeData
{

    // {{{ properties
    /**
     * Valid Geographic Area Codes
     * @var array
     */
    public $geogAreaCodes;

    /**
     * Obsolete Geographic Area Codes
     * @var array
     */
    public $obsoleteGeogAreaCodes;

    /**
     * Valid Language Codes
     * @var array
     */
    public $languageCodes;

    /**
     * Obsolete Language Codes
     * @var array
     */
    public $obsoleteLanguageCodes;

    /**
     * Valid Country Codes
     * @var array
     */
    public $countryCodes;

    /**
     * Obsolete Country Codes
     * @var array
     */
    public $obsoleteCountryCodes;

    /**
     * Valid sources for fields 600-651
     * @var array
     */
    public $sources600_651;

    /**
     * Obsolete sources for fields 600-651
     * @var array
     */
    public $obsoleteSources600_651;

    /**
     * Valid sources for field 655
     * @var array
     */
    public $sources655;

    /**
     * Obsolete sources for field 655
     * @var array
     */
    public $obsoleteSources655;

    // }}}

    // {{{ Constructor: function __construct()
    /**
     * Start function
     *
     * Initialize code arrays.
     *
     * @return true 
     */
    public function __construct()
    {
        // @codingStandardsIgnoreStart
        // fill the valid Geographic Area Codes array
        $this->geogAreaCodes = explode("\t", "a------	a-af---	a-ai---	a-aj---	a-ba---	a-bg---	a-bn---	a-br---	a-bt---	a-bx---	a-cb---	a-cc---	a-cc-an	a-cc-ch	a-cc-cq	a-cc-fu	a-cc-ha	a-cc-he	a-cc-hh	a-cc-hk	a-cc-ho	a-cc-hp	a-cc-hu	a-cc-im	a-cc-ka	a-cc-kc	a-cc-ki	a-cc-kn	a-cc-kr	a-cc-ku	a-cc-kw	a-cc-lp	a-cc-mh	a-cc-nn	a-cc-pe	a-cc-sh	a-cc-sm	a-cc-sp	a-cc-ss	a-cc-su	a-cc-sz	a-cc-ti	a-cc-tn	a-cc-ts	a-cc-yu	a-ccg--	a-cck--	a-ccp--	a-ccs--	a-ccy--	a-ce---	a-ch---	a-cy---	a-em---	a-gs---	a-ii---	a-io---	a-iq---	a-ir---	a-is---	a-ja---	a-jo---	a-kg---	a-kn---	a-ko---	a-kr---	a-ku---	a-kz---	a-le---	a-ls---	a-mk---	a-mp---	a-my---	a-np---	a-nw---	a-ph---	a-pk---	a-pp---	a-qa---	a-si---	a-su---	a-sy---	a-ta---	a-th---	a-tk---	a-ts---	a-tu---	a-uz---	a-vt---	a-ye---	aa-----	ab-----	ac-----	ae-----	af-----	ag-----	ah-----	ai-----	ak-----	am-----	an-----	ao-----	aopf---	aoxp---	ap-----	ar-----	as-----	at-----	au-----	aw-----	awba---	awgz---	ay-----	az-----	b------	c------	cc-----	cl-----	d------	dd-----	e------	e-aa---	e-an---	e-au---	e-be---	e-bn---	e-bu---	e-bw---	e-ci---	e-cs---	e-dk---	e-er---	e-fi---	e-fr---	e-ge---	e-gi---	e-gr---	e-gw---	e-gx---	e-hu---	e-ic---	e-ie---	e-it---	e-kv---	e-lh---	e-li---	e-lu---	e-lv---	e-mc---	e-mm---	e-mo---	e-mv---	e-ne---	e-no---	e-pl---	e-po---	e-rb---	e-rm---	e-ru---	e-sm---	e-sp---	e-sw---	e-sz---	e-uk---	e-uk-en	e-uk-ni	e-uk-st	e-uk-ui	e-uk-wl	e-un---	e-ur---	e-urc--	e-ure--	e-urf--	e-urk--	e-urn--	e-urp--	e-urr--	e-urs--	e-uru--	e-urw--	e-vc---	e-xn---	e-xo---	e-xr---	e-xv---	e-yu---	ea-----	eb-----	ec-----	ed-----	ee-----	el-----	en-----	eo-----	ep-----	er-----	es-----	ev-----	ew-----	f------	f-ae---	f-ao---	f-bd---	f-bs---	f-cd---	f-cf---	f-cg---	f-cm---	f-cx---	f-dm---	f-ea---	f-eg---	f-et---	f-ft---	f-gh---	f-gm---	f-go---	f-gv---	f-iv---	f-ke---	f-lb---	f-lo---	f-ly---	f-mg---	f-ml---	f-mr---	f-mu---	f-mw---	f-mz---	f-ng---	f-nr---	f-pg---	f-rh---	f-rw---	f-sa---	f-sd---	f-sf---	f-sg---	f-sh---	f-sj---	f-sl---	f-so---	f-sq---	f-ss---	f-sx---	f-tg---	f-ti---	f-tz---	f-ua---	f-ug---	f-uv---	f-za---	fa-----	fb-----	fc-----	fd-----	fe-----	ff-----	fg-----	fh-----	fi-----	fl-----	fn-----	fq-----	fr-----	fs-----	fu-----	fv-----	fw-----	fz-----	h------	i------	i-bi---	i-cq---	i-fs---	i-hm---	i-mf---	i-my---	i-re---	i-se---	i-xa---	i-xb---	i-xc---	i-xo---	l------	ln-----	lnaz---	lnbm---	lnca---	lncv---	lnfa---	lnjn---	lnma---	lnsb---	ls-----	lsai---	lsbv---	lsfk---	lstd---	lsxj---	lsxs---	m------	ma-----	mb-----	me-----	mm-----	mr-----	n------	n-cn---	n-cn-ab	n-cn-bc	n-cn-mb	n-cn-nf	n-cn-nk	n-cn-ns	n-cn-nt	n-cn-nu	n-cn-on	n-cn-pi	n-cn-qu	n-cn-sn	n-cn-yk	n-cnh--	n-cnm--	n-cnp--	n-gl---	n-mx---	n-us---	n-us-ak	n-us-al	n-us-ar	n-us-az	n-us-ca	n-us-co	n-us-ct	n-us-dc	n-us-de	n-us-fl	n-us-ga	n-us-hi	n-us-ia	n-us-id	n-us-il	n-us-in	n-us-ks	n-us-ky	n-us-la	n-us-ma	n-us-md	n-us-me	n-us-mi	n-us-mn	n-us-mo	n-us-ms	n-us-mt	n-us-nb	n-us-nc	n-us-nd	n-us-nh	n-us-nj	n-us-nm	n-us-nv	n-us-ny	n-us-oh	n-us-ok	n-us-or	n-us-pa	n-us-ri	n-us-sc	n-us-sd	n-us-tn	n-us-tx	n-us-ut	n-us-va	n-us-vt	n-us-wa	n-us-wi	n-us-wv	n-us-wy	n-usa--	n-usc--	n-use--	n-usl--	n-usm--	n-usn--	n-uso--	n-usp--	n-usr--	n-uss--	n-ust--	n-usu--	n-xl---	nc-----	ncbh---	nccr---	nccz---	nces---	ncgt---	ncho---	ncnq---	ncpn---	nl-----	nm-----	np-----	nr-----	nw-----	nwaq---	nwaw---	nwbb---	nwbf---	nwbn---	nwcj---	nwco---	nwcu---	nwdq---	nwdr---	nweu---	nwgd---	nwgp---	nwhi---	nwht---	nwjm---	nwla---	nwli---	nwmj---	nwmq---	nwna---	nwpr---	nwsc---	nwsd---	nwsn---	nwst---	nwsv---	nwtc---	nwtr---	nwuc---	nwvb---	nwvi---	nwwi---	nwxa---	nwxi---	nwxk---	nwxm---	p------	pn-----	po-----	poas---	pobp---	poci---	pocw---	poea---	pofj---	pofp---	pogg---	pogu---	poji---	pokb---	poki---	poln---	pome---	pomi---	ponl---	ponn---	ponu---	popc---	popl---	pops---	posh---	potl---	poto---	pott---	potv---	poup---	powf---	powk---	pows---	poxd---	poxe---	poxf---	poxh---	ps-----	q------	r------	s------	s-ag---	s-bl---	s-bo---	s-ck---	s-cl---	s-ec---	s-fg---	s-gy---	s-pe---	s-py---	s-sr---	s-uy---	s-ve---	sa-----	sn-----	sp-----	t------	u------	u-ac---	u-at---	u-at-ac	u-at-ne	u-at-no	u-at-qn	u-at-sa	u-at-tm	u-at-vi	u-at-we	u-atc--	u-ate--	u-atn--	u-cs---	u-nz---	w------	x------	xa-----	xb-----	xc-----	xd-----	zd-----	zju----	zma----	zme----	zmo----	zne----	zo-----	zpl----	zs-----	zsa----	zsu----	zur----	zve----");
        
        // fill the obsolete Geographic Area Codes array
        $this->obsoleteGeogAreaCodes = explode("\t", "t-ay---	e-ur-ai	e-ur-aj	nwbc---	e-ur-bw	f-by---	pocp---	e-url--	cr-----	v------	e-ur-er	et-----	e-ur-gs	pogn---	nwga---	nwgs---	a-hk---	ei-----	f-if---	awiy---	awiw---	awiu---	e-ur-kz	e-ur-kg	e-ur-lv	e-ur-li	a-mh---	cm-----	e-ur-mv	n-usw--	a-ok---	a-pt---	e-ur-ru	pory---	nwsb---	posc---	a-sk---	posn---	e-uro--	e-ur-ta	e-ur-tk	e-ur-un	e-ur-uz	a-vn---	a-vs---	nwvr---	e-urv--	a-ys---");
        
        // fill the valid Language Codes array
        $this->languageCodes = explode("\t", "   	aar	abk	ace	ach	ada	ady	afa	afh	afr	ain	aka	akk	alb	ale	alg	alt	amh	ang	anp	apa	ara	arc	arg	arm	arn	arp	art	arw	asm	ast	ath	aus	ava	ave	awa	aym	aze	bad	bai	bak	bal	bam	ban	baq	bas	bat	bej	bel	bem	ben	ber	bho	bih	bik	bin	bis	bla	bnt	bos	bra	bre	btk	bua	bug	bul	bur	byn	cad	cai	car	cat	cau	ceb	cel	cha	chb	che	chg	chi	chk	chm	chn	cho	chp	chr	chu	chv	chy	cmc	cop	cor	cos	cpe	cpf	cpp	cre	crh	crp	csb	cus	cze	dak	dan	dar	day	del	den	dgr	din	div	doi	dra	dsb	dua	dum	dut	dyu	dzo	efi	egy	eka	elx	eng	enm	epo	est	ewe	ewo	fan	fao	fat	fij	fil	fin	fiu	fon	fre	frm	fro	frr	frs	fry	ful	fur	gaa	gay	gba	gem	geo	ger	gez	gil	gla	gle	glg	glv	gmh	goh	gon	gor	got	grb	grc	gre	grn	gsw	guj	gwi	hai	hat	hau	haw	heb	her	hil	him	hin	hit	hmn	hmo	hrv	hsb	hun	hup	iba	ibo	ice	ido	iii	ijo	iku	ile	ilo	ina	inc	ind	ine	inh	ipk	ira	iro	ita	jav	jbo	jpn	jpr	jrb	kaa	kab	kac	kal	kam	kan	kar	kas	kau	kaw	kaz	kbd	kha	khi	khm	kho	kik	kin	kir	kmb	kok	kom	kon	kor	kos	kpe	krc	krl	kro	kru	kua	kum	kur	kut	lad	lah	lam	lao	lat	lav	lez	lim	lin	lit	lol	loz	ltz	lua	lub	lug	lui	lun	luo	lus	mac	mad	mag	mah	mai	mak	mal	man	mao	map	mar	mas	may	mdf	mdr	men	mga	mic	min	mis	mkh	mlg	mlt	mnc	mni	mno	moh	mon	mos	mul	mun	mus	mwl	mwr	myn	myv	nah	nai	nap	nau	nav	nbl	nde	ndo	nds	nep	new	nia	nic	niu	nno	nob	nog	non	nor	nqo	nso	nub	nwc	nya	nym	nyn	nyo	nzi	oci	oji	ori	orm	osa	oss	ota	oto	paa	pag	pal	pam	pan	pap	pau	peo	per	phi	phn	pli	pol	pon	por	pra	pro	pus	que	raj	rap	rar	roa	roh	rom	rum	run	rup	rus	sad	sag	sah	sai	sal	sam	san	sas	sat	scn	sco	sel	sem	sga	sgn	shn	sid	sin	sio	sit	sla	slo	slv	sma	sme	smi	smj	smn	smo	sms	sna	snd	snk	sog	som	son	sot	spa	srd	srn	srp	srr	ssa	ssw	suk	sun	sus	sux	swa	swe	syc	syr	tah	tai	tam	tat	tel	tem	ter	tet	tgk	tgl	tha	tib	tig	tir	tiv	tkl	tlh	tli	tmh	tog	ton	tpi	tsi	tsn	tso	tuk	tum	tup	tur	tut	tvl	twi	tyv	udm	uga	uig	ukr	umb	und	urd	uzb	vai	ven	vie	vol	vot	wak	wal	war	was	wel	wen	wln	wol	xal	xho	yao	yap	yid	yor	ypk	zap	zbl	zen	zha	znd	zul	zun	zxx	zza");
        
        // fill the obsolete Language Codes array
        $this->obsoleteLanguageCodes = explode("\t", "ajm	esk	esp	eth	far	fri	gag	gua	int	iri	cam	kus	mla	max	mol	lan	gal	lap	sao	gae	scc	scr	sho	snh	sso	swz	tag	taj	tar	tru	tsw");
        
        // fill the valid Country Codes array
        $this->countryCodes = explode("\t", "aa 	abc	aca	ae 	af 	ag 	ai 	aj 	aku	alu	am 	an 	ao 	aq 	aru	as 	at 	au 	aw 	ay 	azu	ba 	bb 	bcc	bd 	be 	bf 	bg 	bh 	bi 	bl 	bm 	bn 	bo 	bp 	br 	bs 	bt 	bu 	bv 	bw 	bx 	ca 	cau	cb 	cc 	cd 	ce 	cf 	cg 	ch 	ci 	cj 	ck 	cl 	cm 	co 	cou	cq 	cr 	ctu	cu 	cv 	cw 	cx 	cy 	dcu	deu	dk 	dm 	dq 	dr 	ea 	ec 	eg 	em 	enk	er 	es 	et 	fa 	fg 	fi 	fj 	fk 	flu	fm 	fp 	fr 	fs 	ft 	gau	gb 	gd 	gh 	gi 	gl 	gm 	go 	gp 	gr 	gs 	gt 	gu 	gv 	gw 	gy 	gz 	hiu	hm 	ho 	ht 	hu 	iau	ic 	idu	ie 	ii 	ilu	inu	io 	iq 	ir 	is 	it 	iv 	iy 	ja 	ji 	jm 	jo 	ke 	kg 	kn 	ko 	ksu	ku 	kv 	kyu	kz 	lau	lb 	le 	lh 	li 	lo 	ls 	lu 	lv 	ly 	mau	mbc	mc 	mdu	meu	mf 	mg 	miu	mj 	mk 	ml 	mm 	mnu	mo 	mou	mp 	mq 	mr 	msu	mtu	mu 	mv 	mw 	mx 	my 	mz 	na 	nbu	ncu	ndu	ne 	nfc	ng 	nhu	nik	nju	nkc	nl 	nmu	nn 	no 	np 	nq 	nr 	nsc	ntc	nu 	nuc	nvu	nw 	nx 	nyu	nz 	ohu	oku	onc	oru	ot 	pau	pc 	pe 	pf 	pg 	ph 	pic	pk 	pl 	pn 	po 	pp 	pr 	pw 	py 	qa 	qea	quc	rb 	re 	rh 	riu	rm 	ru 	rw 	sa 	sc 	scu	sd 	sdu	se 	sf 	sg 	sh 	si 	sj 	sl 	sm 	sn 	snc	so 	sp 	sq 	sr 	ss 	st 	stk	su 	sw 	sx 	sy 	sz 	ta 	tc 	tg 	th 	ti 	tk 	tl 	tma	tnu	to 	tr 	ts 	tu 	tv 	txu	tz 	ua 	uc 	ug 	uik	un 	up 	utu	uv 	uy 	uz 	vau	vb 	vc 	ve 	vi 	vm 	vp 	vra	vtu	wau	wea	wf 	wiu	wj 	wk 	wlk	ws 	wvu	wyu	xa 	xb 	xc 	xd 	xe 	xf 	xga	xh 	xj 	xk 	xl 	xm 	xn 	xna	xo 	xoa	xp 	xr 	xra	xs 	xv 	xx 	xxc	xxk	xxu	ye 	ykc	za ");
        
        // fill the obsolete Country Codes array
        $this->obsoleteCountryCodes = explode("\t", "ai 	air	ac 	ajr	bwr	cn 	cz 	cp 	ln 	cs 	err	gsr	ge 	gn 	hk 	iw 	iu 	jn 	kzr	kgr	lvr	lir	mh 	mvr	nm 	pt 	rur	ry 	xi 	sk 	xxr	sb 	sv 	tar	tt 	tkr	unr	uk 	ui 	us 	uzr	vn 	vs 	wb 	ys 	yu ");
        
        // the codes cash, lcsh, lcshac, mesh, nal, and rvm are covered by 2nd
        // indicators in 600-655
        // they are only used when indicators are not available
        $this->sources600_651 = explode("\t", "aass	aat	abne	aedoml	afo	afset	agrifors	agrovoc	agrovocf	agrovocs	aiatsisl	aiatsisp	aiatsiss	aktp	albt	allars	apaist	armac	asft	ashlnl	asrcrfcd	asrcseo	asrctoa	asth	ated	atg	atla	aucsh	bare	barn	bhb	bella	bet	bhammf	bhashe	bib1814	bibalex	biccbmc	bicssc	bidex	bisacsh	bisacmt	bisacrt	bjornson	blcpss	blmlsh	blnpn	bokbas	bt	btr	cabt	cash	cbk	cck	ccsa	cct	ccte	cctf	cdcng	ceeus	chirosh	cht	ciesiniv	cilla	collett	conorsi	csahssa	csalsct	csapa	csh	csht	cstud	czenas	czmesh	dacs	dbn	dcs	ddcri	ddcrit	ddcut	dissao	dit	dltlt	dltt	drama	dtict	ebfem	eclas	eet	eflch	eks	embiaecid	embne	emnmus	ept	erfemn	ericd	est	eum	eurovocen	eurovocfr	eurovocsl	fast	fes	finmesh	fire	fmesh	fnhl	francis	fssh	galestne	gccst	gcipmedia	gcipplatform	gem	gemet	georeft	gnd	gnis	gst	gtt	hamsun	hapi	hkcan	helecon	henn	hlasstg	hoidokki	hrvmesh	huc	humord	iaat	ibsen	ica	icpsr	idas	idsbb	idszbz	idszbzes	idszbzna	idszbzzg	idszbzzh	idszbzzk	iescs	iest	ilot	ilpt	inist	inspect	ipat	ipsp	isis	itglit	itoamc	itrt	jhpb	jhpk	jlabsh	juho	jupo	jurivoc	kaa	kaba	kao	kassu	kauno	kaunokki	kdm	khib	kito	kitu	kkts	koko	kssbar	kta	kto	ktpt	ktta	kubikat	kula	kulo	kupu	lacnaf	lapponica	larpcal	lcac	lcdgt	lcmpt	lcsh	lcshac	lcstt	lctgm	lemac	lemb	liito	liv	lnmmbr	local	ltcsh	lua	maaq	maotao	mar	masa	mech	mero	mesh	mipfesd	mmm	mpirdes	msc	msh	mtirdes	musa	muso	muzeukc	muzeukn	muzvukci	naf	nal	nalnaf	nasat	nbdbt	nbiemnfag	ncjt	ndlsh	netc	ndllsh	nicem	nimacsc	nlgaf	nlgkk	nlgsh	nlmnaf	no-ubo-mr	noraf	noram	norbok	normesh	noubomn	noubojur	nsbncf	nskps	ntcpsc	ntcsd	ntids	ntissc	nzggn	nznb	odlt	ogst	onet	opms	ordnok	pascal	pepp	peri	pha	pkk	pleiades	pmbok	pmcsg	pmont	pmt	poliscit	popinte	precis	prvt	psychit	puho	quiding	qlsp	qrma	qrmak	qtglit	raam	ram	rasuqam	renib	reo	rero	rerovoc	rma	rpe	rswk	rswkaf	rugeo	rurkp	rvm	rvmgd	samisk	sanb	sao	sbiao	sbt	scbi	scgdst	scisshl	scot	sears	sfit	sgc	sgce	shbe	she	shsples	sigle	sipri	sk	skon	slem	smda	snt	socio	solstad	sosa	spines	ssg	sthus	stw	swd	swemesh	taika	tasmas	taxhs	tbit	tbjvp	tekord	tero	tesa	tesbhaecid	test	tgn	tha	thema	thesoz	thia	tho	thub	tips	tisa	tlka	tlsh	toit	trfarn	trfbmb	trfgr	trfoba	trfzb	trt	trtsa	tsht	tsr	ttka	ttll	tucua	udc	ukslc	ulan	umitrist	unbisn	unbist	unescot	usaidt	valo	vcaadu	vffyl	vmj	waqaf	watrest	wgst	wot	wpicsh	ysa	yso");
        $this->obsoleteSources600_651 = explode("\t", "cash	lcsh	lcshac	mesh	nal	nobomn	noubojor	reroa	rvm");
        $this->sources655 = explode("\t", "aat	afset	aiatsisl	aiatsisp	aiatsiss	aktp	alett	amg	asrcrfcd	asrcseo	asrctoa	asth	aucsh	barn	barngf	bib1814	bibalex	biccbmc	bidex	bgtchm	bisacsh	bisacmt	bisacrt	bjornson	bt	cash	chirosh	cct	cdcng	cjh	collett	conorsi	csht	czenas	dacs	dcs	dct	ddcut	eet	eflch	embne	emnmus	ept	erfemn	ericd	estc	eurovocen	eurovocsl	fast	fbg	fgtpcm	finmesh	fire	ftamc	galestne	gatbeg	gem	gmd	gmgpc	gnd	gsafd	gst	gtlm	hamsun	hapi	hkcan	hoidokki	ica	ilot	isbdcontent	isbdmedia	itglit	itrt	jhpb	jhpk	kkts	lacnaf	lcgft	lcmpt	lcsh	lcshac	lcstt	lctgm	lemac	lobt	local	maaq	mar	marccategory	marcform	marcgt	marcsmd	mech	mesh	migfg	mim	msh	muzeukc	muzeukn	muzeukv	muzvukci	nal	nalnaf	nbdbgf	nbiemnfag	ndlsh	netc	ngl	nimafc	nlgaf	nlgkk	nlgsh	nlmnaf	nmc	no-ubo-mr	noraf	noram	nsbncf	ntids	nzcoh	nzggn	nznb	onet	opms	ordnok	pkk	pmcsg	pmt	proysen	quiding	qlsp	qrmak	qtglit	raam	radfg	rasuqam	rbbin	rbgenr	rbmscv	rbpap	rbpri	rbprov	rbpub	rbtyp	rdabf	rdabs	rdacarrier	rdaco	rdacontent	rdacpc	rdact	rdafnm	rdafs	rdaft	rdagen	rdagrp	rdagw	rdalay	rdamat	rdamedia	rdamt	rdapf	rdapm	rdapo	rdarm	rdarr	rdaspc	rdatc	rdatr	rdavf	reo	rerovoc	reveal	rma	rswk	rswkaf	rugeo	rvm	rvmgf	sao	saogf	scbi	sears	sgc	sgce	sgp	sipri	skon	snt	socio	spines	ssg	stw	swd	swemesh	tbit	thema	tesa	tgfbne	thesoz	tho	thub	toit	tsht	tucua	ukslc	ulan	vgmsgg	vgmsng	vmj	waqaf");
        $this->obsoleteSources655 = explode("\t", "cash	ftamc	lcsh	lcshac	marccarrier	marccontent	marcmedia	mesh	nal	reroa	rvm");
        // @codingStandardsIgnoreEnd
    }
    // }}}
}
// }}}
PK��ZR��A;A;File/MARC/Data_Field.phpnu�[���<?php

/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */

/**
 * Parser for MARC records
 *
 * This package is based on the PHP MARC package, originally called "php-marc",
 * that is part of the Emilda Project (http://www.emilda.org). Christoffer
 * Landtman generously agreed to make the "php-marc" code available under the
 * GNU LGPL so it could be used as the basis of this PEAR package.
 *
 * PHP version 5
 *
 * LICENSE: This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category  File_Formats
 * @package   File_MARC
 * @author    Christoffer Landtman <landtman@realnode.com>
 * @author    Dan Scott <dscott@laurentian.ca>
 * @copyright 2003-2008 Oy Realnode Ab, Dan Scott
 * @license   http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/File_MARC
 */

// {{{ class File_MARC_Data_Field extends File_MARC_Field
/**
 * The File_MARC_Data_Field class represents a single field in a MARC record.
 *
 * A MARC data field consists of a tag name, two indicators which may be null,
 * and zero or more subfields represented by {@link File_MARC_Subfield} objects.
 * Subfields are held within a linked list structure.
 *
 * @category File_Formats
 * @package  File_MARC
 * @author   Christoffer Landtman <landtman@realnode.com>
 * @author   Dan Scott <dscott@laurentian.ca>
 * @license  http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @link     http://pear.php.net/package/File_MARC
 */
class File_MARC_Data_Field extends File_MARC_Field
{

    // {{{ properties
    /**
     * Value of the first indicator
     * @var string
     */
    protected $ind1;

    /**
     * Value of the second indicator
     * @var string
     */
    protected $ind2;

    /**
     * Linked list of subfields
     * @var File_MARC_List
     */
    protected $subfields;

    // }}}

    // {{{ Constructor: function __construct()
    /**
     * {@link File_MARC_Data_Field} constructor
     *
     * Create a new {@link File_MARC_Data_Field} object. The only required
     * parameter is a tag. This enables programs to build up new fields
     * programmatically.
     *
     * <code>
     * // Example: Create a new data field
     *
     * // We can optionally create an array of subfields first
     * $subfields[] = new File_MARC_Subfield('a', 'Scott, Daniel.');
     *
     * // Create the new 100 field complete with a _a subfield and an indicator
     * $new_field = new File_MARC_Data_Field('100', $subfields, 0, null);
     * </code>
     *
     * @param string $tag       tag
     * @param array  $subfields array of {@link File_MARC_Subfield} objects
     * @param string $ind1      first indicator
     * @param string $ind2      second indicator
     */
    function __construct($tag, array $subfields = null, $ind1 = null, $ind2 = null)
    {
        $this->subfields = new File_MARC_List();

        parent::__construct($tag);

        $this->ind1 = $this->_validateIndicator($ind1);
        $this->ind2 = $this->_validateIndicator($ind2);

        // we'll let users add subfields after if they so desire
        if ($subfields) {
            $this->addSubfields($subfields);
        }
    }
    // }}}

    // {{{ Destructor: function __destruct()
    /**
     * Destroys the data field
     */
    function __destruct()
    {
        $this->subfields = null;
        $this->ind1 = null;
        $this->ind2 = null;
        parent::__destruct();
    }
    // }}}

    // {{{ Explicit destructor: function delete()
    /**
     * Destroys the data field
     *
     * @return true
     */
    function delete()
    {
        $this->__destruct();
    }
    // }}}

    // {{{ protected function _validateIndicator()
    /**
     * Validates an indicator field
     *
     * Validates the value passed in for an indicator. This routine ensures
     * that an indicator is a single character. If the indicator value is null,
     * then this method returns a single character.
     *
     * If the indicator value contains more than a single character, this
     * throws an exception.
     *
     * @param string $indicator Value of the indicator to be validated
     *
     * @return string Returns the indicator, or space if the indicator was null
     */
    private function _validateIndicator($indicator)
    {
        if ($indicator == null) {
            $indicator = ' ';
        } elseif (strlen($indicator) > 1) {
            $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_INDICATOR], array("tag" => $this->getTag(), "indicator" => $indicator));
            throw new File_MARC_Exception($errorMessage, File_MARC_Exception::ERROR_INVALID_INDICATOR);
        }
        return $indicator;
    }
    // }}}

    // {{{ appendSubfield()
    /**
     * Appends subfield to subfield list
     *
     * Adds a File_MARC_Subfield object to the end of the existing list
     * of subfields.
     *
     * @param File_MARC_Subfield $new_subfield The subfield to add
     *
     * @return File_MARC_Subfield the new File_MARC_Subfield object
     */
    function appendSubfield(File_MARC_Subfield $new_subfield)
    {
        /* Append as the last subfield in the field */
        $this->subfields->appendNode($new_subfield);
    }
    // }}}

    // {{{ prependSubfield()
    /**
     * Prepends subfield to subfield list
     *
     * Adds a File_MARC_Subfield object to the  start of the existing list
     * of subfields.
     *
     * @param File_MARC_Subfield $new_subfield The subfield to add
     *
     * @return File_MARC_Subfield the new File_MARC_Subfield object
     */
    function prependSubfield(File_MARC_Subfield $new_subfield)
    {
        $this->subfields->unshift($new_subfield);
        return $new_subfield;
    }
    // }}}

    // {{{ insertSubfield()
    /**
     * Inserts a field in the MARC record relative to an existing field
     *
     * Inserts a {@link File_MARC_Subfield} object before or after an existing
     * subfield.
     *
     * @param File_MARC_Subfield $new_field      The subfield to add
     * @param File_MARC_Subfield $existing_field The target subfield
     * @param bool               $before         Insert the subfield before the existing subfield if true; after the existing subfield if false
     *
     * @return File_MARC_Subfield                The new subfield
     */
    function insertSubfield(File_MARC_Subfield $new_field, File_MARC_Subfield $existing_field, $before = false)
    {
        $this->subfields->insertNode($new_field, $existing_field, $before);
        return $new_field;
    }
    // }}}

    // {{{ addSubfields()
    /**
     * Adds an array of subfields to a {@link File_MARC_Data_Field} object
     *
     * Appends subfields to existing subfields in the order in which
     * they appear in the array. For finer grained control of the subfield
     * order, use {@link appendSubfield()}, {@link prependSubfield()},
     * or {@link insertSubfield()} to add each subfield individually.
     *
     * @param array $subfields array of {@link File_MARC_Subfield} objects
     *
     * @return int returns the number of subfields that were added
     */
    function addSubfields(array $subfields)
    {
        /*
         * Just in case someone passes in a single File_MARC_Subfield
         * instead of an array
         */
        if ($subfields instanceof File_MARC_Subfield) {
            $this->appendSubfield($subfields);
            return 1;
        }

        // Add subfields
        $cnt = 0;
        foreach ($subfields as $subfield) {
            $this->appendSubfield($subfield);
            $cnt++;
        }

        return $cnt;
    }
    // }}}

    // {{{ deleteSubfield()
    /**
     * Delete a subfield from the field.
     *
     * @param File_MARC_Subfield $subfield The subfield to delete
     *
     * @return void
     */
    function deleteSubfield(File_MARC_Subfield $subfield)
    {
        $this->subfields->deleteNode($subfield);
    }
    // }}}

    // {{{ getIndicator()
    /**
     * Get the value of an indicator
     *
     * @param int $ind number of the indicator (1 or 2)
     *
     * @return string returns indicator value if it exists, otherwise false
     */
    function getIndicator($ind)
    {
        if ($ind == 1) {
            return (string)$this->ind1;
        } elseif ($ind == 2) {
            return (string)$this->ind2;
        } else {
             $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_INDICATOR_REQUEST], array("indicator" => $indicator));
             throw new File_MARC_Exception($errorMessage, File_MARC_Exception::ERROR_INVALID_INDICATOR_REQUEST);
        }
        return false;
    }
    // }}}

    // {{{ setIndicator()
    /**
     * Set the value of an indicator
     *
     * @param int    $ind   number of the indicator (1 or 2)
     * @param string $value value of the indicator
     *
     * @return string       returns indicator value if it exists, otherwise false
     */
    function setIndicator($ind, $value)
    {
        switch ($ind) {

        case 1:
            $this->ind1 = $this->_validateIndicator($value);
            break;

        case 2:
            $this->ind2 = $this->_validateIndicator($value);
            break;

        default:
            $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_INDICATOR_REQUEST], array("indicator" => $ind));
            throw new File_MARC_Exception($errorMessage, File_MARC_Exception::ERROR_INVALID_INDICATOR_REQUEST);
            return false;
        }

        return $this->getIndicator($ind);
    }
    // }}}

    // {{{ getSubfield()
    /**
     * Returns the first subfield that matches a requested code.
     *
     * @param string $code subfield code for which the
     * {@link File_MARC_Subfield} is retrieved
     * @param bool   $pcre if true, then match as a regular expression
     *
     * @return File_MARC_Subfield returns the first subfield that matches
     * $code, or false if no codes match $code
     */
    function getSubfield($code = null, $pcre = null)
    {
        // iterate merrily through the subfields looking for the requested code
        foreach ($this->subfields as $sf) {
            if (($pcre
                && preg_match("/$code/", $sf->getCode()))
                || (!$pcre
                && $code == $sf->getCode())
            ) {
                return $sf;
            }
        }

        // No matches were found
        return false;
    }
    // }}}

    // {{{ getSubfields()
    /**
     * Returns an array of subfields that match a requested code,
     * or a {@link File_MARC_List} that contains all of the subfields
     * if the requested code is null.
     *
     * @param string $code subfield code for which the
     * {@link File_MARC_Subfield} is retrieved
     * @param bool   $pcre if true, then match as a regular expression
     *
     * @return File_MARC_List|array returns a linked list of all subfields
     * if $code is null, an array of {@link File_MARC_Subfield} objects if
     * one or more subfields match, or an empty array if no codes match $code
     */
    function getSubfields($code = null, $pcre = null)
    {
        $results = array();

        // return all subfields if no specific subfields were requested
        if ($code === null) {
            $results = $this->subfields;
            return $results;
        }

        // iterate merrily through the subfields looking for the requested code
        foreach ($this->subfields as $sf) {
            if (($pcre
                && preg_match("/$code/", $sf->getCode()))
                || (!$pcre
                && $code == $sf->getCode())
            ) {
                $results[] = $sf;
            }
        }
        return $results;
    }
    // }}}

    // {{{ isEmpty()
    /**
     * Checks if the field is empty.
     *
     * Checks if the field is empty. If the field has at least one subfield
     * with data, it is not empty.
     *
     * @return bool Returns true if the field is empty, otherwise false
     */
    function isEmpty()
    {
        // If $this->subfields is null, we must have deleted it
        if (!$this->subfields) {
            return true;
        }

        // Iterate through the subfields looking for some data
        foreach ($this->subfields as $subfield) {
            // Check if subfield has data
            if (!$subfield->isEmpty()) {
                return false;
            }
        }
        // It is empty
        return true;
    }
    // }}}

    /**
     * ========== OUTPUT METHODS ==========
     */

    // {{{ __toString()
    /**
     * Return Field formatted
     *
     * Return Field as a formatted string.
     *
     * @return string Formatted output of Field
     */
    function __toString()
    {
        // Variables
        $lines = array();
        // Process tag and indicators
        $pre = sprintf("%3s %1s%1s", $this->tag, $this->ind1, $this->ind2);

        // Process subfields
        foreach ($this->subfields as $subfield) {
            $lines[] = sprintf("%6s _%1s%s", $pre, $subfield->getCode(), $subfield->getData());
            $pre = "";
        }

        return join("\n", $lines);
    }
    // }}}

    // {{{ toRaw()
    /**
     * Return Field in Raw MARC
     *
     * Return the Field formatted in Raw MARC for saving into MARC files
     *
     * @return string Raw MARC
     */
    function toRaw()
    {
        $subfields = array();
        foreach ($this->subfields as $subfield) {
            if (!$subfield->isEmpty()) {
                $subfields[] = $subfield->toRaw();
            }
        }
        return (string)$this->ind1.$this->ind2.implode("", $subfields).File_MARC::END_OF_FIELD;
    }
    // }}}

    // {{{ getContents()
    /**
     * Return fields data content as joined string
     *
     * Return all the fields data content as a joined string
     *
     * @param  string $joinChar A string used to join the data conntent.
     * Default is an empty string
     *
     * @return string Joined string
     */
    function getContents($joinChar = '')
    {
        $contents = array();
        foreach($this->subfields as $subfield) {
            $contents[] = $subfield->getData();
        }
        return implode($joinChar, $contents);
    }
    // }}}
}
// }}}

PK��Zlz�`File/MARC/Control_Field.phpnu�[���<?php

/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */

/**
 * Parser for MARC records
 *
 * This package is based on the PHP MARC package, originally called "php-marc",
 * that is part of the Emilda Project (http://www.emilda.org). Christoffer
 * Landtman generously agreed to make the "php-marc" code available under the
 * GNU LGPL so it could be used as the basis of this PEAR package.
 * 
 * PHP version 5
 *
 * LICENSE: This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category  File_Formats
 * @package   File_MARC
 * @author    Christoffer Landtman <landtman@realnode.com>
 * @author    Dan Scott <dscott@laurentian.ca>
 * @copyright 2003-2008 Oy Realnode Ab, Dan Scott
 * @license   http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/File_MARC
 */

// {{{ class File_MARC_Control_Field extends File_MARC_Field
/**
 * The File_MARC_Control_Field class represents a single control field
 * in a MARC record.
 *
 * A MARC control field consists of a tag name and control data.
 *
 * @category File_Formats
 * @package  File_MARC
 * @author   Christoffer Landtman <landtman@realnode.com>
 * @author   Dan Scott <dscott@laurentian.ca>
 * @license  http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @link     http://pear.php.net/package/File_MARC
 */
class File_MARC_Control_Field extends File_MARC_Field
{

    // {{{ Properties
    /**
     * Value of field, if field is a Control field
     * @var string
     */
    protected $data;
    // }}}

    // {{{ Constructor: function __construct()
    /**
     * Field init function
     *
     * Create a new {@link File_MARC_Control_Field} object from passed arguments
     *
     * @param string $tag  tag
     * @param string $data control field data
     * @param string $ind1 placeholder for class strictness
     * @param string $ind2 placeholder for class strictness
     */
    function __construct($tag, $data, $ind1 = null, $ind2 = null) 
    {
        $this->data = $data;
        parent::__construct($tag);

    }
    // }}}

    // {{{ Destructor: function __destruct()
    /**
     * Destroys the control field
     */
    function __destruct()
    {
        $this->data = null;
        parent::__destruct();
    }
    // }}}

    // {{{ Explicit destructor: function delete()
    /**
     * Destroys the control field
     *
     * @return true
     */
    function delete()
    {
        $this->__destruct();
    }
    // }}}

    // {{{ getData()
    /**
     * Get control field data
     *
     * @return string returns data in control field
     */
    function getData()
    {
        return (string)$this->data;
    }
    // }}}

    // {{{ isEmpty()
    /**
     * Is empty
     *
     * Checks if the field contains data
     *
     * @return bool Returns true if the field is empty, otherwise false
     */
    function isEmpty()
    {
        return ($this->data) ? false : true;
    }
    // }}}

    // {{{ setData()
    /**
     * Set control field data
     *
     * @param string $data data for the control field
     *
     * @return bool returns the new data in the control field
     */
    function setData($data)
    {
        $this->data = $data;
        return $this->getData();
    }
    // }}}

    // {{{ __toString()
    /**
     * Return as a formatted string
     *
     * Return the control field as a formatted string for pretty printing
     *
     * @return string Formatted output of control Field
     */
    function __toString()
    {
        return sprintf("%3s     %s", $this->tag, $this->data);
    }
    // }}}

    // {{{ toRaw()
    /**
     * Return as raw MARC
     *
     * Return the control field formatted in Raw MARC for saving into MARC files
     *
     * @return string Raw MARC
     */
    function toRaw()
    {
        return (string)$this->data.File_MARC::END_OF_FIELD;
    }
    // }}}

}
// }}}

PK��ZɌ5��9�9File/MARC/Lint.phpnu�[���<?php

/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */

/**
 * Lint for MARC records
 *
 * This module is adapted from the MARC::Lint CPAN module for Perl, maintained by
 * Bryan Baldus <eijabb@cpan.org> and available at http://search.cpan.org/~eijabb/
 *
 * Current MARC::Lint version used as basis for this module: 1.52
 *
 * PHP version 5
 *
 * LICENSE: This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category  File_Formats
 * @package   File_MARC
 * @author    Demian Katz <demian.katz@villanova.edu>
 * @author    Dan Scott <dscott@laurentian.ca>
 * @copyright 2003-2019 Oy Realnode Ab, Dan Scott
 * @license   http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @version   CVS: $Id: Record.php 308146 2011-02-08 20:36:20Z dbs $
 * @link      http://pear.php.net/package/File_MARC
 */
require_once 'File/MARC/Lint/CodeData.php';
require_once 'Validate/ISPN.php';

// {{{ class File_MARC_Lint
/**
 * Class for testing validity of MARC records against MARC21 standard.
 *
 * @category File_Formats
 * @package  File_MARC
 * @author   Demian Katz <demian.katz@villanova.edu>
 * @author   Dan Scott <dscott@laurentian.ca>
 * @license  http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @link     http://pear.php.net/package/File_MARC
 */
class File_MARC_Lint
{

    // {{{ properties
    /**
     * Rules used for testing records
     * @var array
     */
    protected $rules;

    /**
     * A File_MARC_Lint_CodeData object for validating codes
     * @var File_MARC_Lint_CodeData
     */
    protected $data;

    /**
     * A Validate_ISPN object for validating ISBN numbers
     * @var Validate_ISPN
     */
    protected $validateIspn;

    /**
     * Warnings generated during analysis
     * @var array
     */
    protected $warnings = array();

    // }}}

    // {{{ Constructor: function __construct()
    /**
     * Start function
     *
     * Set up rules for testing MARC records.
     *
     * @return true
     */
    public function __construct()
    {
        $this->parseRules();
        $this->data = new File_MARC_Lint_CodeData();
        $this->validateIspn = new Validate_ISPN();
    }
    // }}}

    // {{{ getWarnings()
    /**
     * Check the provided MARC record and return an array of warning messages.
     *
     * @param File_MARC_Record $marc Record to check
     *
     * @return array
     */
    public function checkRecord($marc)
    {
        // Reset warnings:
        $this->warnings = array();

        // Fail if we didn't get a valid object:
        if (!is_a($marc, 'File_MARC_Record')) {
            $this->warn('Must pass a File_MARC_Record object to checkRecord');
        } else {
            $this->checkDuplicate1xx($marc);
            $this->checkMissing245($marc);
            $this->standardFieldChecks($marc);
        }

        return $this->warnings;
    }
    // }}}

    // {{{ warn()
    /**
     * Add a warning.
     *
     * @param string $warning Warning to add
     *
     * @return void
     */
    protected function warn($warning)
    {
        $this->warnings[] = $warning;
    }
    // }}}

    // {{{ checkDuplicate1xx()
    /**
     * Check for multiple 1xx fields.
     *
     * @param File_MARC_Record $marc Record to check
     *
     * @return void
     */
    protected function checkDuplicate1xx($marc)
    {
        $result = $marc->getFields('1[0-9][0-9]', true);
        $count = count($result);
        if ($count > 1) {
            $this->warn(
                "1XX: Only one 1XX tag is allowed, but I found $count of them."
            );
        }
    }
    // }}}

    // {{{ checkMissing245()
    /**
     * Check for missing 245 field.
     *
     * @param File_MARC_Record $marc Record to check
     *
     * @return void
     */
    protected function checkMissing245($marc)
    {
        $result = $marc->getFields('245');
        if (count($result) == 0) {
            $this->warn('245: No 245 tag.');
        }
    }
    // }}}

    // {{{ standardFieldChecks()
    /**
     * Check all fields against the standard rules encoded in the class.
     *
     * @param File_MARC_Record $marc Record to check
     *
     * @return void
     */
    protected function standardFieldChecks($marc)
    {
        $fieldsSeen = array();
        foreach ($marc->getFields() as $current) {
            $tagNo = $current->getTag();
            // if 880 field, inherit rules from tagno in subfield _6
            if ($tagNo == 880) {
                if ($sub6 = $current->getSubfield(6)) {
                    $tagNo = substr($sub6->getData(), 0, 3);
                    $tagrules = isset($this->rules[$tagNo])
                        ? $this->rules[$tagNo] : null;
                    // 880 is repeatable, but its linked field may not be
                    if (isset($tagrules['repeatable'])
                        && $tagrules['repeatable'] == 'NR'
                        && isset($fieldsSeen['880.'.$tagNo])
                    ) {
                        $this->warn("$tagNo: Field is not repeatable.");
                    }
                    $fieldsSeen['880.'.$tagNo] = isset($fieldsSeen['880.'.$tagNo])
                        ? $fieldsSeen['880.'.$tagNo] + 1 : 1;
                } else {
                    $this->warn("880: No subfield 6.");
                    $tagRules = null;
                }
            } else {
                // Default case -- not an 880 field:
                $tagrules = isset($this->rules[$tagNo])
                    ? $this->rules[$tagNo] : null;
                if (isset($tagrules['repeatable']) && $tagrules['repeatable'] == 'NR'
                    && isset($fieldsSeen[$tagNo])
                ) {
                    $this->warn("$tagNo: Field is not repeatable.");
                }
                $fieldsSeen[$tagNo] = isset($fieldsSeen[$tagNo])
                    ? $fieldsSeen[$tagNo] + 1 : 1;
            }

            // Treat data fields differently from control fields:
            if (intval(ltrim($tagNo, '0')) >= 10) {
                if (!empty($tagrules)) {
                    $this->checkIndicators($tagNo, $current, $tagrules);
                    $this->checkSubfields($tagNo, $current, $tagrules);
                }
            } else {
                // Control field:
                if (strstr($current->toRaw(), chr(hexdec('1F')))) {
                    $this->warn(
                        "$tagNo: Subfields are not allowed in fields lower than 010"
                    );
                }
            }

            // Check to see if a checkxxx() function exists, and call it on the
            // field if it does
            $method = 'check' . $tagNo;
            if (method_exists($this, $method)) {
                $this->$method($current);
            }
        }
    }
    // }}}

    // {{{ checkIndicators()
    /**
     * Check the indicators for the provided field.
     *
     * @param string          $tagNo Tag number being checked
     * @param File_MARC_Field $field Field to check
     * @param array           $rules Rules to use for checking
     *
     * @return void
     */
    protected function checkIndicators($tagNo, $field, $rules)
    {
        for ($i = 1; $i <= 2; $i++) {
            $ind = $field->getIndicator($i);
            if ($ind === false || $ind == ' ') {
                $ind = 'b';
            }
            if (!strstr($rules['ind' . $i]['values'], $ind)) {
                // Make indicator blank value human-readable for message:
                if ($ind == 'b') {
                    $ind = 'blank';
                }
                $this->warn(
                    "$tagNo: Indicator $i must be "
                    . $rules['ind' . $i]['hr_values']
                    . " but it's \"$ind\""
                );
            }
        }
    }
    // }}}

    // {{{ checkSubfields()
    /**
     * Check the subfields for the provided field.
     *
     * @param string          $tagNo Tag number being checked
     * @param File_MARC_Field $field Field to check
     * @param array           $rules Rules to use for checking
     *
     * @return void
     */
    protected function checkSubfields($tagNo, $field, $rules)
    {
        $subSeen = array();

        foreach ($field->getSubfields() as $current) {
            $code = $current->getCode();
            $data = $current->getData();

            $subrules = isset($rules['sub' . $code])
                ? $rules['sub' . $code] : null;

            if (empty($subrules)) {
                $this->warn("$tagNo: Subfield _$code is not allowed.");
            } elseif ($subrules['repeatable'] == 'NR' && isset($subSeen[$code])) {
                $this->warn("$tagNo: Subfield _$code is not repeatable.");
            }

            if (preg_match('/\r|\t|\n/', $data)) {
                $this->warn(
                    "$tagNo: Subfield _$code has an invalid control character"
                );
            }

            $subSeen[$code] = isset($subSeen[$code]) ? $subSeen[$code]++ : 1;
        }
    }
    // }}}

    // {{{ check020()
    /**
     * Looks at 020$a and reports errors if the check digit is wrong.
     * Looks at 020$z and validates number if hyphens are present.
     *
     * @param File_MARC_Field $field Field to check
     *
     * @return void
     */
    protected function check020($field)
    {
        foreach ($field->getSubfields() as $current) {
            $data = $current->getData();
            // remove any hyphens
            $isbn = str_replace('-', '', $data);
            // remove nondigits
            $isbn = preg_replace('/^\D*(\d{9,12}[X\d])\b.*$/', '$1', $isbn);

            if ($current->getCode() == 'a') {
                if ((substr($data, 0, strlen($isbn)) != $isbn)) {
                    $this->warn("020: Subfield a may have invalid characters.");
                }

                // report error if no space precedes a qualifier in subfield a
                if (preg_match('/\(/', $data) && !preg_match('/[X0-9] \(/', $data)) {
                    $this->warn(
                        "020: Subfield a qualifier must be preceded by space, $data."
                    );
                }

                // report error if unable to find 10-13 digit string of digits in
                // subfield 'a'
                if (!preg_match('/(?:^\d{10}$)|(?:^\d{13}$)|(?:^\d{9}X$)/', $isbn)) {
                    $this->warn(
                        "020: Subfield a has the wrong number of digits, $data."
                    );
                } else {
                    if (strlen($isbn) == 10) {
                        if (!$this->validateIspn->isbn10($isbn)) {
                            $this->warn("020: Subfield a has bad checksum, $data.");
                        }
                    } else if (strlen($isbn) == 13) {
                        if (!$this->validateIspn->isbn13($isbn)) {
                            $this->warn(
                                "020: Subfield a has bad checksum (13 digit), $data."
                            );
                        }
                    }
                }
            } else if ($current->getCode() == 'z') {
                // look for valid isbn in 020$z
                if (preg_match('/^ISBN/', $data)
                    || preg_match('/^\d*\-\d+/', $data)
                ) {
                    // ##################################################
                    // ## Turned on for now--Comment to unimplement  ####
                    // ##################################################
                    if ((strlen($isbn) == 10)
                        && ($this->validateIspn->isbn10($isbn) == 1)
                    ) {
                        $this->warn("020:  Subfield z is numerically valid.");
                    }
                }
            }
        }
    }
    // }}}

    // {{{ check041()
    /**
     * Warns if subfields are not evenly divisible by 3 unless second indicator is 7
     * (future implementation would ensure that each subfield is exactly 3 characters
     * unless ind2 is 7--since subfields are now repeatable. This is not implemented
     * here due to the large number of records needing to be corrected.). Validates
     * against the MARC Code List for Languages (<http://www.loc.gov/marc/>).
     *
     * @param File_MARC_Field $field Field to check
     *
     * @return void
     */
    protected function check041($field)
    {
        // warn if length of each subfield is not divisible by 3 unless ind2 is 7
        if ($field->getIndicator(2) != '7') {
            foreach ($field->getSubfields() as $sub) {
                $code = $sub->getCode();
                $data = $sub->getData();
                if (strlen($data) % 3 != 0) {
                    $this->warn(
                        "041: Subfield _$code must be evenly divisible by 3 or "
                        . "exactly three characters if ind2 is not 7, ($data)."
                    );
                } else {
                    for ($i = 0; $i < strlen($data); $i += 3) {
                        $chk = substr($data, $i, 3);
                        if (!in_array($chk, $this->data->languageCodes)) {
                            $obs = $this->data->obsoleteLanguageCodes;
                            if (in_array($chk, $obs)) {
                                $this->warn(
                                    "041: Subfield _$code, $data, may be obsolete."
                                );
                            } else {
                                $this->warn(
                                    "041: Subfield _$code, $data ($chk),"
                                    . " is not valid."
                                );
                            }
                        }
                    }
                }
            }
        }
    }
    // }}}

    // {{{ check043()
    /**
     * Warns if each subfield a is not exactly 7 characters. Validates each code
     * against the MARC code list for Geographic Areas (<http://www.loc.gov/marc/>).
     *
     * @param File_MARC_Field $field Field to check
     *
     * @return void
     */
    protected function check043($field)
    {
        foreach ($field->getSubfields('a') as $suba) {
            // warn if length of subfield a is not exactly 7
            $data = $suba->getData();
            if (strlen($data) != 7) {
                $this->warn("043: Subfield _a must be exactly 7 characters, $data");
            } else if (!in_array($data, $this->data->geogAreaCodes)) {
                if (in_array($data, $this->data->obsoleteGeogAreaCodes)) {
                    $this->warn("043: Subfield _a, $data, may be obsolete.");
                } else {
                    $this->warn("043: Subfield _a, $data, is not valid.");
                }
            }
        }
    }
    // }}}

    // {{{ check245()
    /**
     * -Makes sure $a exists (and is first subfield).
     * -Warns if last character of field is not a period
     * --Follows LCRI 1.0C, Nov. 2003 rather than MARC21 rule
     * -Verifies that $c is preceded by / (space-/)
     * -Verifies that initials in $c are not spaced
     * -Verifies that $b is preceded by :;= (space-colon, space-semicolon,
     *  space-equals)
     * -Verifies that $h is not preceded by space unless it is dash-space
     * -Verifies that data of $h is enclosed in square brackets
     * -Verifies that $n is preceded by . (period)
     * --As part of that, looks for no-space period, or dash-space-period
     *  (for replaced elipses)
     * -Verifies that $p is preceded by , (no-space-comma) when following $n and
     *  . (period) when following other subfields.
     * -Performs rudimentary article check of 245 2nd indicator vs. 1st word of
     *  245$a (for manual verification).
     *
     * Article checking is done by internal checkArticle method, which should work
     * for 130, 240, 245, 440, 630, 730, and 830.
     *
     * @param File_MARC_Field $field Field to check
     *
     * @return void
     */
    protected function check245($field)
    {
        if (count($field->getSubfields('a')) == 0) {
            $this->warn("245: Must have a subfield _a.");
        }

        // Convert subfields to array and set flags indicating which subfields are
        // present while we're at it.
        $tmp = $field->getSubfields();
        $hasSubfields = $subfields = array();
        foreach ($tmp as $current) {
            $subfields[] = $current;
            $hasSubfields[$current->getCode()] = true;
        }

        // 245 must end in period (may want to make this less restrictive by allowing
        // trailing spaces)
        // do 2 checks--for final punctuation (MARC21 rule), and for period
        // (LCRI 1.0C, Nov. 2003)
        $lastChar = substr($subfields[count($subfields)-1]->getData(), -1);
        if (!in_array($lastChar, array('.', '?', '!'))) {
            $this->warn("245: Must end with . (period).");
        } else if ($lastChar != '.') {
            $this->warn(
                "245: MARC21 allows ? or ! as final punctuation but LCRI 1.0C, Nov."
                . " 2003 (LCPS 1.7.1 for RDA records), requires period."
            );
        }

        // Check for first subfield
        // subfield a should be first subfield (or 2nd if subfield '6' is present)
        if (isset($hasSubfields['6'])) {
            // make sure there are at least 2 subfields
            if (count($subfields) < 2) {
                $this->warn("245: May have too few subfields.");
            } else {
                $first = $subfields[0]->getCode();
                $second = $subfields[1]->getCode();
                if ($first != '6') {
                    $this->warn("245: First subfield must be _6, but it is $first");
                }
                if ($second != 'a') {
                    $this->warn(
                        "245: First subfield after subfield _6 must be _a, but it "
                        . "is _$second"
                    );
                }
            }
        } else {
            // 1st subfield must be 'a'
            $first = $subfields[0]->getCode();
            if ($first != 'a') {
                $this->warn("245: First subfield must be _a, but it is _$first");
            }
        }
        // End check for first subfield

        // subfield c, if present, must be preceded by /
        // also look for space between initials
        if (isset($hasSubfields['c'])) {
            foreach ($subfields as $i => $current) {
                // 245 subfield c must be preceded by / (space-/)
                if ($current->getCode() == 'c') {
                    if ($i > 0
                        && !preg_match('/\s\/$/', $subfields[$i-1]->getData())
                    ) {
                        $this->warn("245: Subfield _c must be preceded by /");
                    }
                    // 245 subfield c initials should not have space
                    if (preg_match('/\b\w\. \b\w\./', $current->getData())) {
                        $this->warn(
                            "245: Subfield _c initials should not have a space."
                        );
                    }
                    break;
                }
            }
        }

        // each subfield b, if present, should be preceded by :;= (colon, semicolon,
        // or equals sign)
        if (isset($hasSubfields['b'])) {
            // 245 subfield b should be preceded by space-:;= (colon, semicolon, or
            // equals sign)
            foreach ($subfields as $i => $current) {
                if ($current->getCode() == 'b' && $i > 0
                    && !preg_match('/ [:;=]$/', $subfields[$i-1]->getData())
                ) {
                    $this->warn(
                        "245: Subfield _b should be preceded by space-colon, "
                        . "space-semicolon, or space-equals sign."
                    );
                }
            }
        }

        // each subfield h, if present, should be preceded by non-space
        if (isset($hasSubfields['h'])) {
            // 245 subfield h should not be preceded by space
            foreach ($subfields as $i => $current) {
                // report error if subfield 'h' is preceded by space (unless
                // dash-space)
                if ($current->getCode() == 'h') {
                    $prev = $subfields[$i-1]->getData();
                    if ($i > 0 && !preg_match('/(\S$)|(\-\- $)/', $prev)) {
                        $this->warn(
                            "245: Subfield _h should not be preceded by space."
                        );
                    }
                    // report error if subfield 'h' does not start with open square
                    // bracket with a matching close bracket; could have check
                    // against list of valid values here
                    $data = $current->getData();
                    if (!preg_match('/^\[\w*\s*\w*\]/', $data)) {
                        $this->warn(
                            "245: Subfield _h must have matching square brackets,"
                            . " $data."
                        );
                    }
                }
            }
        }

        // each subfield n, if present, must be preceded by . (period)
        if (isset($hasSubfields['n'])) {
            // 245 subfield n must be preceded by . (period)
            foreach ($subfields as $i => $current) {
                // report error if subfield 'n' is not preceded by non-space-period
                // or dash-space-period
                if ($current->getCode() == 'n' && $i > 0) {
                    $prev = $subfields[$i-1]->getData();
                    if (!preg_match('/(\S\.$)|(\-\- \.$)/', $prev)) {
                        $this->warn(
                            "245: Subfield _n must be preceded by . (period)."
                        );
                    }
                }
            }
        }

        // each subfield p, if present, must be preceded by a , (no-space-comma)
        // if it follows subfield n, or by . (no-space-period or
        // dash-space-period) following other subfields
        if (isset($hasSubfields['p'])) {
            // 245 subfield p must be preceded by . (period) or , (comma)
            foreach ($subfields as $i => $current) {
                if ($current->getCode() == 'p' && $i > 0) {
                    $prev = $subfields[$i-1];
                    // case for subfield 'n' being field before this one (allows
                    // dash-space-comma)
                    if ($prev->getCode() == 'n'
                        && !preg_match('/(\S,$)|(\-\- ,$)/', $prev->getData())
                    ) {
                        $this->warn(
                            "245: Subfield _p must be preceded by , (comma) "
                            . "when it follows subfield _n."
                        );
                    } else if ($prev->getCode() != 'n'
                        && !preg_match('/(\S\.$)|(\-\- \.$)/', $prev->getData())
                    ) {
                        $this->warn(
                            "245: Subfield _p must be preceded by . (period)"
                            . " when it follows a subfield other than _n."
                        );
                    }
                }
            }
        }

        // check for invalid 2nd indicator
        $this->checkArticle($field);
    }
    // }}}

    // {{{ checkArticle()
    /**
     * Check of articles is based on code from Ian Hamilton. This version is more
     * limited in that it focuses on English, Spanish, French, Italian and German
     * articles. Certain possible articles have been removed if they are valid
     * English non-articles. This version also disregards 008_language/041 codes
     * and just uses the list of articles to provide warnings/suggestions.
     *
     * source for articles = <http://www.loc.gov/marc/bibliographic/bdapp-e.html>
     *
     * Should work with fields 130, 240, 245, 440, 630, 730, and 830. Reports error
     * if another field is passed in.
     *
     * @param File_MARC_Field $field Field to check
     *
     * @return void
     */
    protected function checkArticle($field)
    {
        // add articles here as needed
        // Some omitted due to similarity with valid words (e.g. the German 'die').
        static $article = array(
            'a' => 'eng glg hun por',
            'an' => 'eng',
            'das' => 'ger',
            'dem' => 'ger',
            'der' => 'ger',
            'ein' => 'ger',
            'eine' => 'ger',
            'einem' => 'ger',
            'einen' => 'ger',
            'einer' => 'ger',
            'eines' => 'ger',
            'el' => 'spa',
            'en' => 'cat dan nor swe',
            'gl' => 'ita',
            'gli' => 'ita',
            'il' => 'ita mlt',
            'l' => 'cat fre ita mlt',
            'la' => 'cat fre ita spa',
            'las' => 'spa',
            'le' => 'fre ita',
            'les' => 'cat fre',
            'lo' => 'ita spa',
            'los' => 'spa',
            'os' => 'por',
            'the' => 'eng',
            'um' => 'por',
            'uma' => 'por',
            'un' => 'cat spa fre ita',
            'una' => 'cat spa ita',
            'une' => 'fre',
            'uno' => 'ita',
        );

        // add exceptions here as needed
        // may want to make keys lowercase
        static $exceptions = array(
            'A & E',
            'A & ',
            'A-',
            'A+',
            'A is ',
            'A isn\'t ',
            'A l\'',
            'A la ',
            'A posteriori',
            'A priori',
            'A to ',
            'El Nino',
            'El Salvador',
            'L is ',
            'L-',
            'La Salle',
            'Las Vegas',
            'Lo cual',
            'Lo mein',
            'Lo que',
            'Los Alamos',
            'Los Angeles',
        );

        // get tagno to determine which indicator to check and for reporting
        $tagNo = $field->getTag();
        // retrieve tagno from subfield 6 if 880 field
        if ($tagNo == '880' && ($sub6 = $field->getSubfield('6'))) {
            $tagNo = substr($sub6->getData(), 0, 3);
        }

        // $ind holds nonfiling character indicator value
        $ind = '';
        // $first_or_second holds which indicator is for nonfiling char value
        $first_or_second = '';
        if (in_array($tagNo, array(130, 630, 730))) {
            $ind = $field->getIndicator(1);
            $first_or_second = '1st';
        } else if (in_array($tagNo, array(240, 245, 440, 830))) {
            $ind = $field->getIndicator(2);
            $first_or_second = '2nd';
        } else {
            $this->warn(
                'Internal error: ' . $tagNo
                . " is not a valid field for article checking\n"
            );
            return;
        }

        if (!is_numeric($ind)) {
            $this->warn($tagNo . ": Non-filing indicator is non-numeric");
            return;
        }

        // get subfield 'a' of the title field
        $titleField = $field->getSubfield('a');
        $title = $titleField ? $titleField->getData() : '';

        // warn about out-of-range skip indicators (note: this feature is an
        // addition to the PHP code; it is not ported directly from MARC::Lint).
        if ($ind > strlen($title)) {
            $this->warn($tagNo . ": Non-filing indicator is out of range");
            return;
        }

        $char1_notalphanum = 0;
        // check for apostrophe, quote, bracket,  or parenthesis, before first word
        // remove if found and add to non-word counter
        while (preg_match('/^["\'\[\(*]/', $title)) {
            $char1_notalphanum++;
            $title = preg_replace('/^["\'\[\(*]/', '', $title);
        }
        // split title into first word + rest on space, parens, bracket, apostrophe,
        // quote, or hyphen
        preg_match('/^([^ \(\)\[\]\'"\-]+)([ \(\)\[\]\'"\-])?(.*)/i', $title, $hits);
        $firstword = isset($hits[1]) ? $hits[1] : '';
        $separator = isset($hits[2]) ? $hits[2] : '';
        $etc = isset($hits[3]) ? $hits[3] : '';

        // get length of first word plus the number of chars removed above plus one
        // for the separator
        $nonfilingchars = strlen($firstword) + $char1_notalphanum + 1;

        // check to see if first word is an exception
        $isan_exception = false;
        foreach ($exceptions as $current) {
            if (substr($title, 0, strlen($current)) == $current) {
                $isan_exception = true;
                break;
            }
        }

        // lowercase chars of $firstword for comparison with article list
        $firstword = strtolower($firstword);

        // see if first word is in the list of articles and not an exception
        $isan_article = !$isan_exception && isset($article[$firstword]);

        // if article then $nonfilingchars should match $ind
        if ($isan_article) {
            // account for quotes, apostrophes, parens, or brackets before 2nd word
            if (strlen($separator) && preg_match('/^[ \(\)\[\]\'"\-]+/', $etc)) {
                while (preg_match('/^[ "\'\[\]\(\)*]/', $etc)) {
                    $nonfilingchars++;
                    $etc = preg_replace('/^[ "\'\[\]\(\)*]/', '', $etc);
                }
            }
            if ($nonfilingchars != $ind) {
                $this->warn(
                    $tagNo . ": First word, $firstword, may be an article, check "
                    . "$first_or_second indicator ($ind)."
                );
            }
        } else {
            // not an article so warn if $ind is not 0
            if ($ind != '0') {
                $this->warn(
                    $tagNo . ": First word, $firstword, does not appear to be an "
                    . "article, check $first_or_second indicator ($ind)."
                );
            }
        }
    }
    // }}}

    // {{{ parseRules()
    /**
     * Support method for constructor to load MARC rules.
     *
     * @return void
     */
    protected function parseRules()
    {
        // Break apart the rule data on line breaks:
        $lines = explode("\n", $this->getRawRules());

        // Each group of data is split by a blank line -- process one group
        // at a time:
        $currentGroup = array();
        foreach ($lines as $currentLine) {
            if (empty($currentLine) && !empty($currentGroup)) {
                $this->processRuleGroup($currentGroup);
                $currentGroup = array();
            } else {
                $currentGroup[] = preg_replace("/\s+/", " ", $currentLine);
            }
        }

        // Still have unprocessed data after the loop?  Handle it now:
        if (!empty($currentGroup)) {
            $this->processRuleGroup($currentGroup);
        }
    }
    // }}}

    // {{{ processRuleGroup()
    /**
     * Support method for parseRules() -- process one group of lines representing
     * a single tag.
     *
     * @param array $rules Rule lines to process
     *
     * @return void
     */
    protected function processRuleGroup($rules)
    {
        // The first line is guaranteed to exist and gives us some basic info:
        list($tag, $repeatable, $description) = explode(' ', $rules[0]);
        $this->rules[$tag] = array(
            'repeatable' => $repeatable,
            'desc' => $description
        );

        // We may or may not have additional details:
        for ($i = 1; $i < count($rules); $i++) {
            list($key, $value, $lineDesc) = explode(' ', $rules[$i] . ' ');
            if (substr($key, 0, 3) == 'ind') {
                // Expand ranges:
                $value = str_replace('0-9', '0123456789', $value);
                $this->rules[$tag][$key] = array(
                    'values' => $value,
                    'hr_values' => $this->getHumanReadableIndicatorValues($value),
                    'desc'=> $lineDesc
                );
            } else {
                if (strlen($key) <= 1) {
                    $this->rules[$tag]['sub' . $key] = array(
                        'repeatable' => $value,
                        'desc' => $lineDesc
                    );
                } elseif (strstr($key, '-')) {
                    list($startKey, $endKey) = explode('-', $key);
                    for ($key = $startKey; $key <= $endKey; $key++) {
                        $this->rules[$tag]['sub' . $key] = array(
                            'repeatable' => $value,
                            'desc' => $lineDesc
                        );
                    }
                }
            }
        }
    }
    // }}}

    // {{{ getHumanReadableIndicatorValues()
    /**
     * Turn a set of indicator rules into a human-readable list.
     *
     * @param string $rules Indicator rules
     *
     * @return string
     */
    protected function getHumanReadableIndicatorValues($rules)
    {
        // No processing needed for blank rule:
        if ($rules == 'blank') {
            return $rules;
        }

        // Create string:
        $string = '';
        $length = strlen($rules);
        for ($i = 0; $i < $length; $i++) {
            $current = substr($rules, $i, 1);
            if ($current == 'b') {
                $current = 'blank';
            }
            $string .= $current;
            if ($length - $i == 2) {
                $string .= ' or ';
            } else if ($length - $i > 2) {
                $string .= ', ';
            }
        }

        return $string;
    }
    // }}}

    // {{{ getRawRules()
    /**
     * Support method for parseRules() -- get the raw rules from MARC::Lint.
     *
     * @return string
     */
    protected function getRawRules()
    {
        // When updating rules, don't forget to escape the dollar signs in the text!
        // It would be simpler to change from HEREDOC to NOWDOC syntax, but that
        // would raise the requirements to PHP 5.3.
        // @codingStandardsIgnoreStart
        return <<<RULES
001     NR      CONTROL NUMBER
ind1    blank   Undefined
ind2    blank   Undefined
        NR      Undefined

002     NR      LOCALLY DEFINED (UNOFFICIAL)
ind1    blank   Undefined
ind2    blank   Undefined
        NR      Undefined

003     NR      CONTROL NUMBER IDENTIFIER
ind1    blank   Undefined
ind2    blank   Undefined
        NR      Undefined

005     NR      DATE AND TIME OF LATEST TRANSACTION
ind1    blank   Undefined
ind2    blank   Undefined
        NR      Undefined

006     R       FIXED-LENGTH DATA ELEMENTS--ADDITIONAL MATERIAL CHARACTERISTICS--GENERAL INFORMATION
ind1    blank   Undefined
ind2    blank   Undefined
        R       Undefined

007     R       PHYSICAL DESCRIPTION FIXED FIELD--GENERAL INFORMATION
ind1    blank   Undefined
ind2    blank   Undefined
        R       Undefined

008     NR      FIXED-LENGTH DATA ELEMENTS--GENERAL INFORMATION
ind1    blank   Undefined
ind2    blank   Undefined
        NR      Undefined

010     NR      LIBRARY OF CONGRESS CONTROL NUMBER
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      LC control number
b       R       NUCMC control number
z       R       Canceled/invalid LC control number
8       R       Field link and sequence number

013     R       PATENT CONTROL INFORMATION
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Number
b       NR      Country
c       NR      Type of number
d       R       Date
e       R       Status
f       R       Party to document
6       NR      Linkage
8       R       Field link and sequence number

015     R       NATIONAL BIBLIOGRAPHY NUMBER
ind1    blank   Undefined
ind2    blank   Undefined
a       R       National bibliography number
q       R       Qualifying information
z       R       Canceled/Invalid national bibliography number
2       NR      Source
6       NR      Linkage
8       R       Field link and sequence number

016     R       NATIONAL BIBLIOGRAPHIC AGENCY CONTROL NUMBER
ind1    b7      National bibliographic agency
ind2    blank   Undefined
a       NR      Record control number
z       R       Canceled or invalid record control number
2       NR      Source
8       R       Field link and sequence number

017     R       COPYRIGHT OR LEGAL DEPOSIT NUMBER
ind1    blank   Undefined
ind2    b8      Undefined
a       R       Copyright or legal deposit number
b       NR      Assigning agency
d       NR      Date
i       NR      Display text
z       R       Canceled/invalid copyright or legal deposit number
2       NR      Source
6       NR      Linkage
8       R       Field link and sequence number

018     NR      COPYRIGHT ARTICLE-FEE CODE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Copyright article-fee code
6       NR      Linkage
8       R       Field link and sequence number

020     R       INTERNATIONAL STANDARD BOOK NUMBER
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      International Standard Book Number
c       NR      Terms of availability
q       R       Qualifying information
z       R       Canceled/invalid ISBN
6       NR      Linkage
8       R       Field link and sequence number

022     R       INTERNATIONAL STANDARD SERIAL NUMBER
ind1    b01     Level of international interest
ind2    blank   Undefined
a       NR      International Standard Serial Number
l       NR      ISSN-L
m       R       Canceled ISSN-L
y       R       Incorrect ISSN
z       R       Canceled ISSN
2       NR      Source
6       NR      Linkage
8       R       Field link and sequence number

024     R       OTHER STANDARD IDENTIFIER
ind1    0123478    Type of standard number or code
ind2    b01     Difference indicator
a       NR      Standard number or code
c       NR      Terms of availability
d       NR      Additional codes following the standard number or code
q       R       Qualifying information
z       R       Canceled/invalid standard number or code
2       NR      Source of number or code
6       NR      Linkage
8       R       Field link and sequence number

025     R       OVERSEAS ACQUISITION NUMBER
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Overseas acquisition number
8       R       Field link and sequence number

026     R       FINGERPRINT IDENTIFIER
ind1    blank   Undefined
ind2    blank   Undefined
a       R       First and second groups of characters
b       R       Third and fourth groups of characters
c       NR      Date
d       R       Number of volume or part
e       NR      Unparsed fingerprint
2       NR      Source
5       R       Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

027     R       STANDARD TECHNICAL REPORT NUMBER
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Standard technical report number
q       R       Qualifying information
z       R       Canceled/invalid number
6       NR      Linkage
8       R       Field link and sequence number

028     R       PUBLISHER NUMBER OR DISTRIBUTOR NUMBER
ind1    0123456   Type of publisher number
ind2    0123    Note/added entry controller
a       NR      Publisher or distributor number
b       NR      Source
q       R       Qualifying information
6       NR      Linkage
8       R       Field link and sequence number

030     R       CODEN DESIGNATION
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      CODEN
z       R       Canceled/invalid CODEN
6       NR      Linkage
8       R       Field link and sequence number

031     R       MUSICAL INCIPITS INFORMATION
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Number of work
b       NR      Number of movement
c       NR      Number of excerpt
d       R       Caption or heading
e       NR      Role
g       NR      Clef
m       NR      Voice/instrument
n       NR      Key signature
o       NR      Time signature
p       NR      Musical notation
q       R       General note
r       NR      Key or mode
s       R       Coded validity note
t       R       Text incipit
u       R       Uniform Resource Identifier
y       R       Link text
z       R       Public note
2       NR      System code
6       NR      Linkage
8       R       Field link and sequence number

032     R       POSTAL REGISTRATION NUMBER
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Postal registration number
b       NR      Source (agency assigning number)
6       NR      Linkage
8       R       Field link and sequence number

033     R       DATE/TIME AND PLACE OF AN EVENT
ind1    b012    Type of date in subfield \$a
ind2    b012    Type of event
a       R       Formatted date/time
b       R       Geographic classification area code
c       R       Geographic classification subarea code
p       R       Place of event
0       R       Record control number
2       R       Source of term
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

034     R       CODED CARTOGRAPHIC MATHEMATICAL DATA
ind1    013     Type of scale
ind2    b01     Type of ring
a       NR      Category of scale
b       R       Constant ratio linear horizontal scale
c       R       Constant ratio linear vertical scale
d       NR      Coordinates--westernmost longitude
e       NR      Coordinates--easternmost longitude
f       NR      Coordinates--northernmost latitude
g       NR      Coordinates--southernmost latitude
h       R       Angular scale
j       NR      Declination--northern limit
k       NR      Declination--southern limit
m       NR      Right ascension--eastern limit
n       NR      Right ascension--western limit
p       NR      Equinox
r       NR      Distance from earth
s       R       G-ring latitude
t       R       G-ring longitude
x       NR      Beginning date
y       NR      Ending date
z       NR      Name of extraterrestrial body
0       R       Authority record control number or standard number
2       NR      Source
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

035     R       SYSTEM CONTROL NUMBER
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      System control number
z       R       Canceled/invalid control number
6       NR      Linkage
8       R       Field link and sequence number

036     NR      ORIGINAL STUDY NUMBER FOR COMPUTER DATA FILES
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Original study number
b       NR      Source (agency assigning number)
6       NR      Linkage
8       R       Field link and sequence number

037     R       SOURCE OF ACQUISITION
ind1    b23     Source of acquisition sequence
ind2    blank   Undefined
a       NR      Stock number
b       NR      Source of stock number/acquisition
c       R       Terms of availability
f       R       Form of issue
g       R       Additional format characteristics
n       R       Note
3       NR      Materials specified
5       R       Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

038     NR      RECORD CONTENT LICENSOR
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Record content licensor
6       NR      Linkage
8       R       Field link and sequence number

040     NR      CATALOGING SOURCE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Original cataloging agency
b       NR      Language of cataloging
c       NR      Transcribing agency
d       R       Modifying agency
e       R       Description conventions
6       NR      Linkage
8       R       Field link and sequence number

041     R       LANGUAGE CODE
ind1    b01      Translation indication
ind2    b7      Source of code
a       R       Language code of text/sound track or separate title
b       R       Language code of summary or abstract
d       R       Language code of sung or spoken text
e       R       Language code of librettos
f       R       Language code of table of contents
g       R       Language code of accompanying material other than librettos
h       R       Language code of original
j       R       Language code of subtitles or captions
k       R       Language code of intermediate translations
m       R       Language code of original accompanying materials other than librettos
n       R       Language code of original libretto
2       NR      Source of code
6       NR      Linkage
8       R       Field link and sequence number

042     NR      AUTHENTICATION CODE
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Authentication code

043     NR      GEOGRAPHIC AREA CODE
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Geographic area code
b       R       Local GAC code
c       R       ISO code
0       R       Authority record control number or standard number
2       R       Source of local code
6       NR      Linkage
8       R       Field link and sequence number

044     NR      COUNTRY OF PUBLISHING/PRODUCING ENTITY CODE
ind1    blank   Undefined
ind2    blank   Undefined
a       R       MARC country code
b       R       Local subentity code
c       R       ISO country code
2       R       Source of local subentity code
6       NR      Linkage
8       R       Field link and sequence number

045     NR      TIME PERIOD OF CONTENT
ind1    b012    Type of time period in subfield \$b or \$c
ind2    blank   Undefined
a       R       Time period code
b       R       Formatted 9999 B.C. through C.E. time period
c       R       Formatted pre-9999 B.C. time period
6       NR      Linkage
8       R       Field link and sequence number

046     R       SPECIAL CODED DATES
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Type of date code
b       NR      Date 1 (B.C.E. date)
c       NR      Date 1 (C.E. date)
d       NR      Date 2 (B.C.E. date)
e       NR      Date 2 (C.E. date)
j       NR      Date resource modified
k       NR      Beginning or single date created
l       NR      Ending date created
m       NR      Beginning of date valid
n       NR      End of date valid
o       NR      Single or starting date for aggregated content
p       NR      Ending date for aggregated content
2       NR      Source of date
6       NR      Linkage
8       R       Field link and sequence number

047     R       FORM OF MUSICAL COMPOSITION CODE
ind1    blank   Undefined
ind2    b7      Source of code
a       R       Form of musical composition code
2       NR      Source of code
8       R       Field link and sequence number

048     R       NUMBER OF MUSICAL INSTRUMENTS OR VOICES CODE
ind1    blank   Undefined
ind2    b7      Source specified in subfield \$2
a       R       Performer or ensemble
b       R       Soloist
2       NR      Source of code
8       R       Field link and sequence number

050     R       LIBRARY OF CONGRESS CALL NUMBER
ind1    b01     Existence in LC collection
ind2    04      Source of call number
a       R       Classification number
b       NR      Item number
0       R       Authority record control number or standard number
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

051     R       LIBRARY OF CONGRESS COPY, ISSUE, OFFPRINT STATEMENT
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Classification number
b       NR      Item number
c       NR      Copy information
8       R       Field link and sequence number

052     R       GEOGRAPHIC CLASSIFICATION
ind1    b17     Code source
ind2    blank   Undefined
a       NR      Geographic classification area code
b       R       Geographic classification subarea code
d       R       Populated place name
0       R       Authority record control number or standard number
2       NR      Code source
6       NR      Linkage
8       R       Field link and sequence number

055     R       CLASSIFICATION NUMBERS ASSIGNED IN CANADA
ind1    b01     Existence in LAC collection
ind2    0123456789   Type, completeness, source of class/call number
a       NR      Classification number
b       NR      Item number
0       R       Authority record control number or standard number
2       NR      Source of call/class number
8       R       Field link and sequence number

060     R       NATIONAL LIBRARY OF MEDICINE CALL NUMBER
ind1    b01     Existence in NLM collection
ind2    04      Source of call number
a       R       Classification number
b       NR      Item number
0       R       Authority record control number or standard number
8       R       Field link and sequence number

061     R       NATIONAL LIBRARY OF MEDICINE COPY STATEMENT
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Classification number
b       NR      Item number
c       NR      Copy information
8       R       Field link and sequence number

066     NR      CHARACTER SETS PRESENT
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Primary G0 character set
b       NR      Primary G1 character set
c       R       Alternate G0 or G1 character set

070     R       NATIONAL AGRICULTURAL LIBRARY CALL NUMBER
ind1    b01     Existence in NAL collection
ind2    blank   Undefined
a       R       Classification number
b       NR      Item number
0       R       Authority record control number or standard number
8       R       Field link and sequence number

071     R       NATIONAL AGRICULTURAL LIBRARY COPY STATEMENT
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Classification number
b       NR      Item number
c       NR      Copy information
8       R       Field link and sequence number

072     R       SUBJECT CATEGORY CODE
ind1    blank   Undefined
ind2    07      Source specified in subfield \$2
a       NR      Subject category code
x       R       Subject category code subdivision
2       NR      Source
6       NR      Linkage
8       R       Field link and sequence number

074     R       GPO ITEM NUMBER
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      GPO item number
z       R       Canceled/invalid GPO item number
8       R       Field link and sequence number

080     R       UNIVERSAL DECIMAL CLASSIFICATION NUMBER
ind1    01      Type of edition
ind2    blank   Undefined
a       NR      Universal Decimal Classification number
b       NR      Item number
x       R       Common auxiliary subdivision
0       R       Authority record control number or standard number
2       NR      Edition identifier
6       NR      Linkage
8       R       Field link and sequence number

082     R       DEWEY DECIMAL CLASSIFICATION NUMBER
ind1    017     Type of edition
ind2    b04     Source of classification number
a       R       Classification number
b       NR      Item number
m       NR      Standard or optional designation
q       NR      Assigning agency
2       NR      Edition number
6       NR      Linkage
8       R       Field link and sequence number

083     R       ADDITIONAL DEWEY DECIMAL CLASSIFICATION NUMBER
ind1    017     Type of edition
ind2    blank   Undefined
a       R       Classification number
c       R       Classification number--Ending number of span
m       NR      Standard or optional designation
q       NR      Assigning agency
y       R       Table sequence number for internal subarrangement or add table
z       R       Table identification
2       NR      Edition number
6       NR      Linkage
8       R       Field link and sequence number

084     R       OTHER CLASSIFICATION NUMBER
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Classification number
b       NR      Item number
q       NR      Assigning agency
0       R       Authority record control number or standard number
2       NR      Source of number
6       NR      Linkage
8       R       Field link and sequence number

085     R       SYNTHESIZED CLASSIFICATION NUMBER COMPONENTS
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Number where instructions are found-single number or beginning number of span
b       R       Base number
c       R       Classification number-ending number of span
f       R       Facet designator
r       R       Root number
s       R       Digits added from classification number in schedule or external table
t       R       Digits added from internal subarrangement or add table
u       R       Number being analyzed
v       R       Number in internal subarrangement or add table where instructions are found
w       R       Table identification-Internal subarrangement or add table
y       R       Table sequence number for internal subarrangement or add table
z       R       Table identification
0       R       Authority record control number or standard number
6       NR      Linkage
8       R       Field link and sequence number

086     R       GOVERNMENT DOCUMENT CLASSIFICATION NUMBER
ind1    b01     Number source
ind2    blank   Undefined
a       NR      Classification number
z       R       Canceled/invalid classification number
0       R       Authority record control number or standard number
2       NR      Number source
6       NR      Linkage
8       R       Field link and sequence number

088     R       REPORT NUMBER
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Report number
z       R       Canceled/invalid report number
6       NR      Linkage
8       R       Field link and sequence number

100     NR      MAIN ENTRY--PERSONAL NAME
ind1    013     Type of personal name entry element
ind2    blank   Undefined
a       NR      Personal name
b       NR      Numeration
c       R       Titles and other words associated with a name
d       NR      Dates associated with a name
e       R       Relator term
f       NR      Date of a work
g       R       Miscellaneous information
j       R       Attribution qualifier
k       R       Form subheading
l       NR      Language of a work
n       R       Number of part/section of a work
p       R       Name of part/section of a work
q       NR      Fuller form of name
t       NR      Title of a work
u       NR      Affiliation
0       R       Authority record control number
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

110     NR      MAIN ENTRY--CORPORATE NAME
ind1    012     Type of corporate name entry element
ind2    blank   Undefined
a       NR      Corporate name or jurisdiction name as entry element
b       R       Subordinate unit
c       R       Location of meeting
d       R       Date of meeting or treaty signing
e       R       Relator term
f       NR      Date of a work
g       R       Miscellaneous information
k       R       Form subheading
l       NR      Language of a work
n       R       Number of part/section/meeting
p       R       Name of part/section of a work
t       NR      Title of a work
u       NR      Affiliation
0       R       Authority record control number
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

111     NR      MAIN ENTRY--MEETING NAME
ind1    012     Type of meeting name entry element
ind2    blank   Undefined
a       NR      Meeting name or jurisdiction name as entry element
c       R       Location of meeting
d       NR      Date of meeting
e       R       Subordinate unit
f       NR      Date of a work
g       R       Miscellaneous information
j       R       Relator term
k       R       Form subheading
l       NR      Language of a work
n       R       Number of part/section/meeting
p       R       Name of part/section of a work
q       NR      Name of meeting following jurisdiction name entry element
t       NR      Title of a work
u       NR      Affiliation
0       R       Authority record control number
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

130     NR      MAIN ENTRY--UNIFORM TITLE
ind1    0-9     Nonfiling characters
ind2    blank   Undefined
a       NR      Uniform title
d       R       Date of treaty signing
f       NR      Date of a work
g       R       Miscellaneous information
h       NR      Medium
k       R       Form subheading
l       NR      Language of a work
m       R       Medium of performance for music
n       R       Number of part/section of a work
o       NR      Arranged statement for music
p       R       Name of part/section of a work
r       NR      Key for music
s       NR      Version
t       NR      Title of a work
0       R       Authority record control number
6       NR      Linkage
8       R       Field link and sequence number

210     R       ABBREVIATED TITLE
ind1    01      Title added entry
ind2    b0      Type
a       NR      Abbreviated title
b       NR      Qualifying information
2       R       Source
6       NR      Linkage
8       R       Field link and sequence number

222     R       KEY TITLE
ind1    blank   Specifies whether variant title and/or added entry is required
ind2    0-9     Nonfiling characters
a       NR      Key title
b       NR      Qualifying information
6       NR      Linkage
8       R       Field link and sequence number

240     NR      UNIFORM TITLE
ind1    01    Uniform title printed or displayed
ind2    0-9    Nonfiling characters
a       NR      Uniform title
d       R       Date of treaty signing
f       NR      Date of a work
g       R       Miscellaneous information
h       NR      Medium
k       R       Form subheading
l       NR      Language of a work
m       R       Medium of performance for music
n       R       Number of part/section of a work
o       NR      Arranged statement for music
p       R       Name of part/section of a work
r       NR      Key for music
s       NR      Version
0       R       Authority record control number
6       NR      Linkage
8       R       Field link and sequence number

242     R       TRANSLATION OF TITLE BY CATALOGING AGENCY
ind1    01    Title added entry
ind2    0-9    Nonfiling characters
a       NR      Title
b       NR      Remainder of title
c       NR      Statement of responsibility, etc.
h       NR      Medium
n       R       Number of part/section of a work
p       R       Name of part/section of a work
y       NR      Language code of translated title
6       NR      Linkage
8       R       Field link and sequence number

243     NR      COLLECTIVE UNIFORM TITLE
ind1    01    Uniform title printed or displayed
ind2    0-9    Nonfiling characters
a       NR      Uniform title
d       R       Date of treaty signing
f       NR      Date of a work
g       R       Miscellaneous information
h       NR      Medium
k       R       Form subheading
l       NR      Language of a work
m       R       Medium of performance for music
n       R       Number of part/section of a work
o       NR      Arranged statement for music
p       R       Name of part/section of a work
r       NR      Key for music
s       NR      Version
6       NR      Linkage
8       R       Field link and sequence number

245     NR      TITLE STATEMENT
ind1    01    Title added entry
ind2    0-9    Nonfiling characters
a       NR      Title
b       NR      Remainder of title
c       NR      Statement of responsibility, etc.
f       NR      Inclusive dates
g       NR      Bulk dates
h       NR      Medium
k       R       Form
n       R       Number of part/section of a work
p       R       Name of part/section of a work
s       NR      Version
6       NR      Linkage
8       R       Field link and sequence number

246     R       VARYING FORM OF TITLE
ind1    0123    Note/added entry controller
ind2    b012345678    Type of title
a       NR      Title proper/short title
b       NR      Remainder of title
f       NR      Date or sequential designation
g       R       Miscellaneous information
h       NR      Medium
i       NR      Display text
n       R       Number of part/section of a work
p       R       Name of part/section of a work
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

247     R       FORMER TITLE
ind1    01      Title added entry
ind2    01      Note controller
a       NR      Title
b       NR      Remainder of title
f       NR      Date or sequential designation
g       R       Miscellaneous information
h       NR      Medium
n       R       Number of part/section of a work
p       R       Name of part/section of a work
x       NR      International Standard Serial Number
6       NR      Linkage
8       R       Field link and sequence number

250     R       EDITION STATEMENT
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Edition statement
b       NR      Remainder of edition statement
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

254     NR      MUSICAL PRESENTATION STATEMENT
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Musical presentation statement
6       NR      Linkage
8       R       Field link and sequence number

255     R       CARTOGRAPHIC MATHEMATICAL DATA
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Statement of scale
b       NR      Statement of projection
c       NR      Statement of coordinates
d       NR      Statement of zone
e       NR      Statement of equinox
f       NR      Outer G-ring coordinate pairs
g       NR      Exclusion G-ring coordinate pairs
6       NR      Linkage
8       R       Field link and sequence number

256     NR      COMPUTER FILE CHARACTERISTICS
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Computer file characteristics
6       NR      Linkage
8       R       Field link and sequence number

257     R       COUNTRY OF PRODUCING ENTITY
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Country of producing entity
0       R       Authority record control number or standard number
2       NR      Source
6       NR      Linkage
8       R       Field link and sequence number

258     R       PHILATELIC ISSUE DATE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Issuing jurisdiction
b       NR      Denomination
6       NR      Linkage
8       R       Field link and sequence number

260     R       PUBLICATION, DISTRIBUTION, ETC. (IMPRINT)
ind1    b23     Sequence of publishing statements
ind2    blank   Undefined
a       R       Place of publication, distribution, etc.
b       R       Name of publisher, distributor, etc.
c       R       Date of publication, distribution, etc.
d       NR      Plate or publisher's number for music (Pre-AACR 2)
e       R       Place of manufacture
f       R       Manufacturer
g       R       Date of manufacture
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

261     NR      IMPRINT STATEMENT FOR FILMS (Pre-AACR 1 Revised)
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Producing company
b       R       Releasing company (primary distributor)
d       R       Date of production, release, etc.
e       R       Contractual producer
f       R       Place of production, release, etc.
6       NR      Linkage
8       R       Field link and sequence number

262     NR      IMPRINT STATEMENT FOR SOUND RECORDINGS (Pre-AACR 2)
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Place of production, release, etc.
b       NR      Publisher or trade name
c       NR      Date of production, release, etc.
k       NR      Serial identification
l       NR      Matrix and/or take number
6       NR      Linkage
8       R       Field link and sequence number

263     NR      PROJECTED PUBLICATION DATE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Projected publication date
6       NR      Linkage
8       R       Field link and sequence number

264     R       PRODUCTION, PUBLICATION, DISTRIBUTION, MANUFACTURE, AND COPYRIGHT NOTICE
ind1    b23     Sequence of statements
ind2    01234   Function of entity
a       R       Place of production, publication, distribution, manufacture
b       R       Name of producer, publisher, distributor, manufacturer
c       R       Date of production, publication, distribution, manufacture, or copyright notice
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number (R)

270     R       ADDRESS
ind1    b12     Level
ind2    b07     Type of address
a       R       Address
b       NR      City
c       NR      State or province
d       NR      Country
e       NR      Postal code
f       NR      Terms preceding attention name
g       NR      Attention name
h       NR      Attention position
i       NR      Type of address
j       R       Specialized telephone number
k       R       Telephone number
l       R       Fax number
m       R       Electronic mail address
n       R       TDD or TTY number
p       R       Contact person
q       R       Title of contact person
r       R       Hours
z       R       Public note
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

300     R       PHYSICAL DESCRIPTION
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Extent
b       NR      Other physical details
c       R       Dimensions
e       NR      Accompanying material
f       R       Type of unit
g       R       Size of unit
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

306     NR      PLAYING TIME
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Playing time
6       NR      Linkage
8       R       Field link and sequence number

307     R       HOURS, ETC.
ind1    b8      Display constant controller
ind2    blank   Undefined
a       NR      Hours
b       NR      Additional information
6       NR      Linkage
8       R       Field link and sequence number

310     NR      CURRENT PUBLICATION FREQUENCY
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Current publication frequency
b       NR      Date of current publication frequency
6       NR      Linkage
8       R       Field link and sequence number

321     R       FORMER PUBLICATION FREQUENCY
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Former publication frequency
b       NR      Dates of former publication frequency
6       NR      Linkage
8       R       Field link and sequence number

336     R       CONTENT TYPE
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Content type term
b       R       Content type code
0       R       Authority record control number or standard number
2       NR      Source
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

337     R       MEDIA TYPE
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Media type term
b       R       Media type code
0       R       Authority record control number or standard number
2       NR      Source
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

338     R       CARRIER TYPE
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Carrier type term
b       R       Carrier type code
0       R       Authority record control number or standard number
2       NR      Source
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

340     R       PHYSICAL MEDIUM
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Material base and configuration
b       R       Dimensions
c       R       Materials applied to surface
d       R       Information recording technique
e       R       Support
f       R       Production rate/ratio
g       R       Color content
h       R       Location within medium
i       R       Technical specifications of medium
j       R       Generation
k       R       Layout
m       R       Book format
n       R       Font size
o       R       Polarity
0       R       Authority record control number or standard number
2       NR      Source
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

342     R       GEOSPATIAL REFERENCE DATA
ind1    01      Geospatial reference dimension
ind2    012345678    Geospatial reference method
a       NR      Name
b       NR      Coordinate or distance units
c       NR      Latitude resolution
d       NR      Longitude resolution
e       R       Standard parallel or oblique line latitude
f       R       Oblique line longitude
g       NR      Longitude of central meridian or projection center
h       NR      Latitude of projection origin or projection center
i       NR      False easting
j       NR      False northing
k       NR      Scale factor
l       NR      Height of perspective point above surface
m       NR      Azimuthal angle
o       NR      Landsat number and path number
p       NR      Zone identifier
q       NR      Ellipsoid name
r       NR      Semi-major axis
s       NR      Denominator of flattening ratio
t       NR      Vertical resolution
u       NR      Vertical encoding method
v       NR      Local planar, local, or other projection or grid description
w       NR      Local planar or local georeference information
2       NR      Reference method used
6       NR      Linkage
8       R       Field link and sequence number

343     R       PLANAR COORDINATE DATA
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Planar coordinate encoding method
b       NR      Planar distance units
c       NR      Abscissa resolution
d       NR      Ordinate resolution
e       NR      Distance resolution
f       NR      Bearing resolution
g       NR      Bearing units
h       NR      Bearing reference direction
i       NR      Bearing reference meridian
6       NR      Linkage
8       R       Field link and sequence number

344     R       SOUND CHARACTERISTICS
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Type of recording
b       R       Recording medium
c       R       Playing speed
d       R       Groove characteristic
e       R       Track configuration
f       R       Tape configuration
g       R       Configuration of playback channels
h       R       Special playback characteristics
0       R       Authority record control number or standard number
2       NR      Source
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

345     R       PROJECTION CHARACTERISTICS OF MOVING IMAGE
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Presentation format
b       R       Projection speed
0       R       Authority record control number or standard number
2       NR      Source
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

346     R       VIDEO CHARACTERISTICS
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Video format
b       R       Broadcast standard
0       R       Authority record control number or standard number
2       NR      Source
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

347     R       DIGITAL FILE CHARACTERISTICS
ind1    blank   Undefined
ind2    blank   Undefined
a       R       File type
b       R       Encoding format
c       R       File size
d       R       Resolution
e       R       Regional encoding
f       R       Encoded bitrate
0       R       Authority record control number or standard number
2       NR      Source
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

348     R       FORMAT OF NOTATED MUSIC
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Format of notated music term
b       R       Format of notated music code
0       R       Authority record control number or standard number
2       NR      Source of term
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

351     R       ORGANIZATION AND ARRANGEMENT OF MATERIALS
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Organization
b       R       Arrangement
c       NR      Hierarchical level
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

352     R       DIGITAL GRAPHIC REPRESENTATION
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Direct reference method
b       R       Object type
c       R       Object count
d       NR      Row count
e       NR      Column count
f       NR      Vertical count
g       NR      VPF topology level
i       NR      Indirect reference description
q       R       Format of the digital image
6       NR      Linkage
8       R       Field link and sequence number

355     R       SECURITY CLASSIFICATION CONTROL
ind1    0123458    Controlled element
ind2    blank   Undefined
a       NR      Security classification
b       R       Handling instructions
c       R       External dissemination information
d       NR      Downgrading or declassification event
e       NR      Classification system
f       NR      Country of origin code
g       NR      Downgrading date
h       NR      Declassification date
j       R       Authorization
6       NR      Linkage
8       R       Field link and sequence number

357     NR      ORIGINATOR DISSEMINATION CONTROL
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Originator control term
b       R       Originating agency
c       R       Authorized recipients of material
g       R       Other restrictions
6       NR      Linkage
8       R       Field link and sequence number

362     R       DATES OF PUBLICATION AND/OR SEQUENTIAL DESIGNATION
ind1    01      Format of date
ind2    blank   Undefined
a       NR      Dates of publication and/or sequential designation
z       NR      Source of information
6       NR      Linkage
8       R       Field link and sequence number

363     R       NORMALIZED DATE AND SEQUENTIAL DESIGNATION
ind1    b01      Start/End designator
ind2    b01      State of issuanceUndefined
a       NR      First level of enumeration
b       NR      Second level of enumeration
c       NR      Third level of enumeration
d       NR      Fourth level of enumeration
e       NR      Fifth level of enumeration
f       NR      Sixth level of enumeration
g       NR      Alternative numbering scheme, first level of enumeration
h       NR      Alternative numbering scheme, second level of enumeration
i       NR      First level of chronology
j       NR      Second level of chronology
k       NR      Third level of chronology
l       NR      Fourth level of chronology
m       NR      Alternative numbering scheme, chronology
u       NR      First level textual designation
v       NR      First level of chronology, issuance
x       R       Nonpublic note
z       R       Public note
6       NR      Linkage
8       NR      Field link and sequence number

365     R       TRADE PRICE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Price type code
b       NR      Price amount
c       NR      Currency code
d       NR      Unit of pricing
e       NR      Price note
f       NR      Price effective from
g       NR      Price effective until
h       NR      Tax rate 1
i       NR      Tax rate 2
j       NR      ISO country code
k       NR      MARC country code
m       NR      Identification of pricing entity
2       NR      Source of price type code
6       NR      Linkage
8       R       Field link and sequence number

366     R       TRADE AVAILABILITY INFORMATION
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Publishers' compressed title identification
b       NR      Detailed date of publication
c       NR      Availability status code
d       NR      Expected next availability date
e       NR      Note
f       NR      Publishers' discount category
g       NR      Date made out of print
j       NR      ISO country code
k       NR      MARC country code
m       NR      Identification of agency
2       NR      Source of availability status code
6       NR      Linkage
8       R       Field link and sequence number

370     R       ASSOCIATED PLACE
ind1    blank   Undefined
ind2    blank   Undefined
c       R       Associated country
f       R       Other associated place
g       R       Place of origin of work or expression
i       R       Relationship information
s       NR      Start period
t       NR      End period
u       R       Uniform Resource Identifier
v       R       Source of information
0       R       Authority record control number or standard number
2       NR      Source of term
3       NR      Materials specified
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

377     R       ASSOCIATED LANGUAGE
ind1    blank   Undefined
ind2    b7      Undefined
a       R       Language code
0       R       Authority record control number or standard number
l       R       Language term
2       NR      Source
6       NR      Linkage
8       R       Field link and sequence number

380     R       FORM OF WORK
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Form of work
0       R       Record control number
2       NR      Source of term
6       NR      Linkage
8       R       Field link and sequence number

381     R       OTHER DISTINGUISHING CHARACTERISTICS OF WORK OR EXPRESSION
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Other distinguishing characteristic
u       R       Uniform Resource Identifier
v       R       Source of information
0       R       Record control number
2       NR      Source of term
6       NR      Linkage
8       R       Field link and sequence number

382     R       MEDIUM OF PERFORMANCE
ind1    b01     Undefined
ind2    b01     Undefined
a       R       Medium of performance
b       R       Soloist
d       R       Doubling instrument
e       R       Number of ensembles of the same type
n       R       Number of performers of the same medium
p       R       Alternative medium of performance
r       NR      Total number of individuals performing alongside ensembles
s       NR      Total number of performers
t       NR      Total number of ensembles
v       R       Note
0       R       Record control number
2       NR      Source of term
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

383     R       NUMERIC DESIGNATION OF MUSICAL WORK
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Serial number
b       R       Opus number
c       R       Thematic index number
d       NR      Thematic index code
e       NR      Publisher associated with opus number
2       NR      Source
6       NR      Linkage
8       R       Field link and sequence number

384     NR      KEY
ind1    b01     Key type
ind2    blank   Undefined
a       NR      Key
6       NR      Linkage
8       R       Field link and sequence number

385     R       AUDIENCE CHARACTERISTICS
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Audience term
b       R       Audience code
m       NR      Demographic group term
n       NR      Demographic group code
0       R       Authority record control number or standard number
2       NR      Source
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

386     R       CREATOR/CONTRIBUTOR CHARACTERISTICS
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Creator/contributor term
b       R       Creator/contributor code
i       R       Relationship information
m       NR      Demographic group term
n       NR      Demographic group code
0       R       Authority record control number or standard number
2       NR      Source
3       NR      Materials specified
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

388     R       TIME PERIOD OF CREATION
ind1    b12     Type of time period
ind2    blank   Undefined
a       R       Time period of creation term (R)
0       R       Authority record control number or standard number (R)
2       NR      Source of term (NR)
3       NR      Materials specified (NR)
6       NR      Linkage (NR)
8       R       Field link and sequence number (R)

400     R       SERIES STATEMENT/ADDED ENTRY--PERSONAL NAME
ind1    013     Type of personal name entry element
ind2    01      Pronoun represents main entry
a       NR      Personal name
b       NR      Numeration
c       R       Titles and other words associated with a name
d       NR      Dates associated with a name
e       R       Relator term
f       NR      Date of a work
g       NR      Miscellaneous information
k       R       Form subheading
l       NR      Language of a work
n       R       Number of part/section of a work
p       R       Name of part/section of a work
t       NR      Title of a work
u       NR      Affiliation
v       NR      Volume number/sequential designation
x       NR      International Standard Serial Number
4       R       Relator code
6       NR      Linkage
8       R       Field link and sequence number

410     R       SERIES STATEMENT/ADDED ENTRY--CORPORATE NAME
ind1    012     Type of corporate name entry element
ind2    01      Pronoun represents main entry
a       NR      Corporate name or jurisdiction name as entry element
b       R       Subordinate unit
c       NR      Location of meeting
d       R       Date of meeting or treaty signing
e       R       Relator term
f       NR      Date of a work
g       NR      Miscellaneous information
k       R       Form subheading
l       NR      Language of a work
n       R       Number of part/section/meeting
p       R       Name of part/section of a work
t       NR      Title of a work
u       NR      Affiliation
v       NR      Volume number/sequential designation
x       NR      International Standard Serial Number
4       R       Relator code
6       NR      Linkage
8       R       Field link and sequence number

411     R       SERIES STATEMENT/ADDED ENTRY--MEETING NAME
ind1    012     Type of meeting name entry element
ind2    01      Pronoun represents main entry
a       NR      Meeting name or jurisdiction name as entry element
c       NR      Location of meeting
d       NR      Date of meeting
e       R       Subordinate unit
f       NR      Date of a work
g       NR      Miscellaneous information
k       R       Form subheading
l       NR      Language of a work
n       R       Number of part/section/meeting
p       R       Name of part/section of a work
q       NR      Name of meeting following jurisdiction name entry element
t       NR      Title of a work
u       NR      Affiliation
v       NR      Volume number/sequential designation
x       NR      International Standard Serial Number
4       R       Relator code
6       NR      Linkage
8       R       Field link and sequence number

440     R       SERIES STATEMENT/ADDED ENTRY--TITLE [OBSOLETE]
ind1    blank   Undefined
ind2    0-9     Nonfiling characters
a       NR      Title
n       R       Number of part/section of a work
p       R       Name of part/section of a work
v       NR      Volume number/sequential designation
x       NR      International Standard Serial Number
w       R       Bibliographic record control number
0       R       Authority record control number
6       NR      Linkage
8       R       Field link and sequence number

490     R       SERIES STATEMENT
ind1    01      Specifies whether series is traced
ind2    blank   Undefined
a       R       Series statement
l       NR      Library of Congress call number
v       R       Volume number/sequential designation
x       R       International Standard Serial Number
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

500     R       GENERAL NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      General note
3       NR      Materials specified
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

501     R       WITH NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      With note
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

502     R       DISSERTATION NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Dissertation note
b       NR      Degree type
c       NR      Name of granting institution
d       NR      Year of degree granted
g       R       Miscellaneous information
o       R       Dissertation identifier
6       NR      Linkage
8       R       Field link and sequence number

504     R       BIBLIOGRAPHY, ETC. NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Bibliography, etc. note
b       NR      Number of references
6       NR      Linkage
8       R       Field link and sequence number

505     R       FORMATTED CONTENTS NOTE
ind1    0128    Display constant controller
ind2    b0      Level of content designation
a       NR      Formatted contents note
g       R       Miscellaneous information
r       R       Statement of responsibility
t       R       Title
u       R       Uniform Resource Identifier
6       NR      Linkage
8       R       Field link and sequence number

506     R       RESTRICTIONS ON ACCESS NOTE
ind1    b01     Restriction
ind2    blank   Undefined
a       NR      Terms governing access
b       R       Jurisdiction
c       R       Physical access provisions
d       R       Authorized users
e       R       Authorization
f       R       Standard terminology for access restiction
u       R       Uniform Resource Identifier
2       NR      Source of term
3       NR      Materials specified
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

507     NR      SCALE NOTE FOR GRAPHIC MATERIAL
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Representative fraction of scale note
b       NR      Remainder of scale note
6       NR      Linkage
8       R       Field link and sequence number

508     R       CREATION/PRODUCTION CREDITS NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Creation/production credits note
6       NR      Linkage
8       R       Field link and sequence number

510     R       CITATION/REFERENCES NOTE
ind1    01234   Coverage/location in source
ind2    blank   Undefined
a       NR      Name of source
b       NR      Coverage of source
c       NR      Location within source
u       R       Uniform Resource Identifier
x       NR      International Standard Serial Number
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

511     R       PARTICIPANT OR PERFORMER NOTE
ind1    01      Display constant controller
ind2    blank   Undefined
a       NR      Participant or performer note
6       NR      Linkage
8       R       Field link and sequence number

513     R       TYPE OF REPORT AND PERIOD COVERED NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Type of report
b       NR      Period covered
6       NR      Linkage
8       R       Field link and sequence number

514     NR      DATA QUALITY NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Attribute accuracy report
b       R       Attribute accuracy value
c       R       Attribute accuracy explanation
d       NR      Logical consistency report
e       NR      Completeness report
f       NR      Horizontal position accuracy report
g       R       Horizontal position accuracy value
h       R       Horizontal position accuracy explanation
i       NR      Vertical positional accuracy report
j       R       Vertical positional accuracy value
k       R       Vertical positional accuracy explanation
m       NR      Cloud cover
u       R       Uniform Resource Identifier
z       R       Display note
6       NR      Linkage
8       R       Field link and sequence number

515     R       NUMBERING PECULIARITIES NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Numbering peculiarities note
6       NR      Linkage
8       R       Field link and sequence number

516     R       TYPE OF COMPUTER FILE OR DATA NOTE
ind1    b8      Display constant controller
ind2    blank   Undefined
a       NR      Type of computer file or data note
6       NR      Linkage
8       R       Field link and sequence number

518     R       DATE/TIME AND PLACE OF AN EVENT NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Date/time and place of an event note
d       R       Date of event
o       R       Other event information
p       R       Place of event
0       R       Record control number
2       R       Source of term
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

520     R       SUMMARY, ETC.
ind1    b012348    Display constant controller
ind2    blank   Undefined
a       NR      Summary, etc. note
b       NR      Expansion of summary note
c       NR      Assigning agency
u       R       Uniform Resource Identifier
2       NR      Source
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

521     R       TARGET AUDIENCE NOTE
ind1    b012348    Display constant controller
ind2    blank   Undefined
a       R       Target audience note
b       NR      Source
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

522     R       GEOGRAPHIC COVERAGE NOTE
ind1    b8      Display constant controller
ind2    blank   Undefined
a       NR      Geographic coverage note
6       NR      Linkage
8       R       Field link and sequence number

524     R       PREFERRED CITATION OF DESCRIBED MATERIALS NOTE
ind1    b8      Display constant controller
ind2    blank   Undefined
a       NR      Preferred citation of described materials note
2       NR      Source of schema used
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

525     R       SUPPLEMENT NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Supplement note
6       NR      Linkage
8       R       Field link and sequence number

526     R       STUDY PROGRAM INFORMATION NOTE
ind1    08      Display constant controller
ind2    blank   Undefined
a       NR      Program name
b       NR      Interest level
c       NR      Reading level
d       NR      Title point value
i       NR      Display text
x       R       Nonpublic note
z       R       Public note
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

530     R       ADDITIONAL PHYSICAL FORM AVAILABLE NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Additional physical form available note
b       NR      Availability source
c       NR      Availability conditions
d       NR      Order number
u       R       Uniform Resource Identifier
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

533     R       REPRODUCTION NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Type of reproduction
b       R       Place of reproduction
c       R       Agency responsible for reproduction
d       NR      Date of reproduction
e       NR      Physical description of reproduction
f       R       Series statement of reproduction
m       R       Dates and/or sequential designation of issues reproduced
n       R       Note about reproduction
3       NR      Materials specified
5       NR      Institution to which field applies
6       NR      Linkage
7       NR      Fixed-length data elements of reproduction
8       R       Field link and sequence number

534     R       ORIGINAL VERSION NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Main entry of original
b       NR      Edition statement of original
c       NR      Publication, distribution, etc. of original
e       NR      Physical description, etc. of original
f       R       Series statement of original
k       R       Key title of original
l       NR      Location of original
m       NR      Material specific details
n       R       Note about original
o       R       Other resource identifier
p       NR      Introductory phrase
t       NR      Title statement of original
x       R       International Standard Serial Number
z       R       International Standard Book Number
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

535     R       LOCATION OF ORIGINALS/DUPLICATES NOTE
ind1    12      Additional information about custodian
ind2    blank   Undefined
a       NR      Custodian
b       R       Postal address
c       R       Country
d       R       Telecommunications address
g       NR      Repository location code
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

536     R       FUNDING INFORMATION NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Text of note
b       R       Contract number
c       R       Grant number
d       R       Undifferentiated number
e       R       Program element number
f       R       Project number
g       R       Task number
h       R       Work unit number
6       NR      Linkage
8       R       Field link and sequence number

538     R       SYSTEM DETAILS NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      System details note
i       NR      Display text
u       R       Uniform Resource Identifier
3       NR      Materials specified
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

540     R       TERMS GOVERNING USE AND REPRODUCTION NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Terms governing use and reproduction
b       NR      Jurisdiction
c       NR      Authorization
d       NR      Authorized users
u       R       Uniform Resource Identifier
3       NR      Materials specified
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

541     R       IMMEDIATE SOURCE OF ACQUISITION NOTE
ind1    b01     Undefined
ind2    blank   Undefined
a       NR      Source of acquisition
b       NR      Address
c       NR      Method of acquisition
d       NR      Date of acquisition
e       NR      Accession number
f       NR      Owner
h       NR      Purchase price
n       R       Extent
o       R       Type of unit
3       NR      Materials specified
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

542     R       INFORMATION RELATING TO COPYRIGHT STATUS
ind1    b01     Relationship
ind2    blank   Undefined
a       NR      Personal creator
b       NR      Personal creator death date
c       NR      Corporate creator
d       R       Copyright holder
e       R       Copyright holder contact information
f       R       Copyright statement
g       NR      Copyright date
h       R       Copyright renewal date
i       NR      Publication date
j       NR      Creation date
k       R       Publisher
l       NR      Copyright status
m       NR      Publication status
n       R       Note
o       NR      Research date
q       NR      Assigning agency
r       NR      Jurisdiction of copyright assessment
s       NR      Source of information
u       R       Uniform Resource Identifier
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

544     R       LOCATION OF OTHER ARCHIVAL MATERIALS NOTE
ind1    b01     Relationship
ind2    blank   Undefined
a       R       Custodian
b       R       Address
c       R       Country
d       R       Title
e       R       Provenance
n       R       Note
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

545     R       BIOGRAPHICAL OR HISTORICAL DATA
ind1    b01     Type of data
ind2    blank   Undefined
a       NR      Biographical or historical note
b       NR      Expansion
u       R       Uniform Resource Identifier
6       NR      Linkage
8       R       Field link and sequence number

546     R       LANGUAGE NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Language note
b       R       Information code or alphabet
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

547     R       FORMER TITLE COMPLEXITY NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Former title complexity note
6       NR      Linkage
8       R       Field link and sequence number

550     R       ISSUING BODY NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Issuing body note
6       NR      Linkage
8       R       Field link and sequence number

552     R       ENTITY AND ATTRIBUTE INFORMATION NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Entity type label
b       NR      Entity type definition and source
c       NR      Attribute label
d       NR      Attribute definition and source
e       R       Enumerated domain value
f       R       Enumerated domain value definition and source
g       NR      Range domain minimum and maximum
h       NR      Codeset name and source
i       NR      Unrepresentable domain
j       NR      Attribute units of measurement and resolution
k       NR      Beginning date and ending date of attribute values
l       NR      Attribute value accuracy
m       NR      Attribute value accuracy explanation
n       NR      Attribute measurement frequency
o       R       Entity and attribute overview
p       R       Entity and attribute detail citation
u       R       Uniform Resource Identifier
z       R       Display note
6       NR      Linkage
8       R       Field link and sequence number

555     R       CUMULATIVE INDEX/FINDING AIDS NOTE
ind1    b08     Display constant controller
ind2    blank   Undefined
a       NR      Cumulative index/finding aids note
b       R       Availability source
c       NR      Degree of control
d       NR      Bibliographic reference
u       R       Uniform Resource Identifier
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

556     R       INFORMATION ABOUT DOCUMENTATION NOTE
ind1    b8      Display constant controller
ind2    blank   Undefined
a       NR      Information about documentation note
z       R       International Standard Book Number
6       NR      Linkage
8       R       Field link and sequence number

561     R       OWNERSHIP AND CUSTODIAL HISTORY
ind1    b01     Undefined
ind2    blank   Undefined
a       NR      History
u       R       Uniform Resource Identifier
3       NR      Materials specified
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

562     R       COPY AND VERSION IDENTIFICATION NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Identifying markings
b       R       Copy identification
c       R       Version identification
d       R       Presentation format
e       R       Number of copies
3       NR      Materials specified
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

563     R       BINDING INFORMATION
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Binding note
u       R       Uniform Resource Identifier
3       NR      Materials specified
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

565     R       CASE FILE CHARACTERISTICS NOTE
ind1    b08     Display constant controller
ind2    blank   Undefined
a       NR      Number of cases/variables
b       R       Name of variable
c       R       Unit of analysis
d       R       Universe of data
e       R       Filing scheme or code
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

567     R       METHODOLOGY NOTE
ind1    b8      Display constant controller
ind2    blank   Undefined
a       NR      Methodology note
b       R       Controlled term
0       R       Authority record control number or standard number
2       NR      Source of term
6       NR      Linkage
8       R       Field link and sequence number

580     R       LINKING ENTRY COMPLEXITY NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Linking entry complexity note
6       NR      Linkage
8       R       Field link and sequence number

581     R       PUBLICATIONS ABOUT DESCRIBED MATERIALS NOTE
ind1    b8      Display constant controller
ind2    blank   Undefined
a       NR      Publications about described materials note
z       R       International Standard Book Number
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

583     R       ACTION NOTE
ind1    b01     Undefined
ind2    blank   Undefined
a       NR      Action
b       R       Action identification
c       R       Time/date of action
d       R       Action interval
e       R       Contingency for action
f       R       Authorization
h       R       Jurisdiction
i       R       Method of action
j       R       Site of action
k       R       Action agent
l       R       Status
n       R       Extent
o       R       Type of unit
u       R       Uniform Resource Identifier
x       R       Nonpublic note
z       R       Public note
2       NR      Source of term
3       NR      Materials specified
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

584     R       ACCUMULATION AND FREQUENCY OF USE NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Accumulation
b       R       Frequency of use
3       NR      Materials specified
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

585     R       EXHIBITIONS NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Exhibitions note
3       NR      Materials specified
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

586     R       AWARDS NOTE
ind1    b8      Display constant controller
ind2    blank   Undefined
a       NR      Awards note
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

588     R       SOURCE OF DESCRIPTION NOTE
ind1    b01     Display constant controller
ind2    blank   Undefined
a       NR      Source of description note
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

600     R       SUBJECT ADDED ENTRY--PERSONAL NAME
ind1    013     Type of personal name entry element
ind2    01234567    Thesaurus
a       NR      Personal name
b       NR      Numeration
c       R       Titles and other words associated with a name
d       NR      Dates associated with a name
e       R       Relator term
f       NR      Date of a work
g       R       Miscellaneous information
h       NR      Medium
j       R       Attribution qualifier
k       R       Form subheading
l       NR      Language of a work
m       R       Medium of performance for music
n       R       Number of part/section of a work
o       NR      Arranged statement for music
p       R       Name of part/section of a work
q       NR      Fuller form of name
r       NR      Key for music
s       NR      Version
t       NR      Title of a work
u       NR      Affiliation
v       R       Form subdivision
x       R       General subdivision
y       R       Chronological subdivision
z       R       Geographic subdivision
0       R       Authority record control number
2       NR      Source of heading or term
3       NR      Materials specified
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

610     R       SUBJECT ADDED ENTRY--CORPORATE NAME
ind1    012     Type of corporate name entry element
ind2    01234567    Thesaurus
a       NR      Corporate name or jurisdiction name as entry element
b       R       Subordinate unit
c       R       Location of meeting
d       R       Date of meeting or treaty signing
e       R       Relator term
f       NR      Date of a work
g       R       Miscellaneous information
h       NR      Medium
k       R       Form subheading
l       NR      Language of a work
m       R       Medium of performance for music
n       R       Number of part/section/meeting
o       NR      Arranged statement for music
p       R       Name of part/section of a work
r       NR      Key for music
s       NR      Version
t       NR      Title of a work
u       NR      Affiliation
v       R       Form subdivision
x       R       General subdivision
y       R       Chronological subdivision
z       R       Geographic subdivision
0       R       Authority record control number
2       NR      Source of heading or term
3       NR      Materials specified
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

611     R       SUBJECT ADDED ENTRY--MEETING NAME
ind1    012     Type of meeting name entry element
ind2    01234567    Thesaurus
a       NR      Meeting name or jurisdiction name as entry element
c       R       Location of meeting
d       NR      Date of meeting
e       R       Subordinate unit
f       NR      Date of a work
g       R       Miscellaneous information
h       NR      Medium
j       R       Relator term
k       R       Form subheading
l       NR      Language of a work
n       R       Number of part/section/meeting
p       R       Name of part/section of a work
q       NR      Name of meeting following jurisdiction name entry element
s       NR      Version
t       NR      Title of a work
u       NR      Affiliation
v       R       Form subdivision
x       R       General subdivision
y       R       Chronological subdivision
z       R       Geographic subdivision
0       R       Authority record control number
2       NR      Source of heading or term
3       NR      Materials specified
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

630     R       SUBJECT ADDED ENTRY--UNIFORM TITLE
ind1    0-9     Nonfiling characters
ind2    01234567    Thesaurus
a       NR      Uniform title
d       R       Date of treaty signing
e       R       Relator term
f       NR      Date of a work
g       R       Miscellaneous information
h       NR      Medium
k       R       Form subheading
l       NR      Language of a work
m       R       Medium of performance for music
n       R       Number of part/section of a work
o       NR      Arranged statement for music
p       R       Name of part/section of a work
r       NR      Key for music
s       NR      Version
t       NR      Title of a work
v       R       Form subdivision
x       R       General subdivision
y       R       Chronological subdivision
z       R       Geographic subdivision
0       R       Authority record control number
2       NR      Source of heading or term
3       NR      Materials specified
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

647     R       SUBJECT ADDED ENTRY--NAMED EVENT
ind1    blank   Undefined
ind2    01234567    Thesaurus
a       NR      Named event
c       R       Location of named event
d       NR      Date of named event
g       R       Miscellaneous information
v       R       Form subdivision
x       R       General subdivision
y       R       Chronological subdivision
z       R       Geographic subdivision
0       R       Authority record control number or standard number
2       NR      Source of heading or term
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

648     R       SUBJECT ADDED ENTRY--CHRONOLOGICAL TERM
ind1    blank   Undefined
ind2    01234567    Thesaurus
a       NR      Chronological term
v       R       Form subdivision
x       R       General subdivision
y       R       Chronological subdivision
z       R       Geographic subdivision
0       R       Authority record control number
2       NR      Source of heading or term
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

650     R       SUBJECT ADDED ENTRY--TOPICAL TERM
ind1    b012    Level of subject
ind2    01234567    Thesaurus
a       NR      Topical term or geographic name as entry element
b       NR      Topical term following geographic name as entry element
c       NR      Location of event
d       NR      Active dates
e       NR      Relator term
v       R       Form subdivision
x       R       General subdivision
y       R       Chronological subdivision
z       R       Geographic subdivision
0       R       Authority record control number
2       NR      Source of heading or term
3       NR      Materials specified
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

651     R       SUBJECT ADDED ENTRY--GEOGRAPHIC NAME
ind1    blank   Undefined
ind2    01234567    Thesaurus
a       NR      Geographic name
e       R       Relator term
v       R       Form subdivision
x       R       General subdivision
y       R       Chronological subdivision
z       R       Geographic subdivision
0       R       Authority record control number
2       NR      Source of heading or term
3       NR      Materials specified
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

653     R       INDEX TERM--UNCONTROLLED
ind1    b012    Level of index term
ind2    b0123456   Type of term or name
a       R       Uncontrolled term
6       NR      Linkage
8       R       Field link and sequence number

654     R       SUBJECT ADDED ENTRY--FACETED TOPICAL TERMS
ind1    b012    Level of subject
ind2    blank   Undefined
a       R       Focus term
b       R       Non-focus term
c       R       Facet/hierarchy designation
e       R       Relator term
v       R       Form subdivision
y       R       Chronological subdivision
z       R       Geographic subdivision
0       R       Authority record control number
2       NR      Source of heading or term
3       NR      Materials specified
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

655     R       INDEX TERM--GENRE/FORM
ind1    b0      Type of heading
ind2    01234567    Thesaurus
a       NR      Genre/form data or focus term
b       R       Non-focus term
c       R       Facet/hierarchy designation
v       R       Form subdivision
x       R       General subdivision
y       R       Chronological subdivision
z       R       Geographic subdivision
0       R       Authority record control number
2       NR      Source of term
3       NR      Materials specified
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

656     R       INDEX TERM--OCCUPATION
ind1    blank   Undefined
ind2    7       Source of term
a       NR      Occupation
k       NR      Form
v       R       Form subdivision
x       R       General subdivision
y       R       Chronological subdivision
z       R       Geographic subdivision
0       R       Authority record control number
2       NR      Source of term
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

657     R       INDEX TERM--FUNCTION
ind1    blank   Undefined
ind2    7       Source of term
a       NR      Function
v       R       Form subdivision
x       R       General subdivision
y       R       Chronological subdivision
z       R       Geographic subdivision
0       R       Authority record control number
2       NR      Source of term
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

658     R       INDEX TERM--CURRICULUM OBJECTIVE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Main curriculum objective
b       R       Subordinate curriculum objective
c       NR      Curriculum code
d       NR      Correlation factor
2       NR      Source of term or code
6       NR      Linkage
8       R       Field link and sequence number

662     R       SUBJECT ADDED ENTRY--HIERARCHICAL PLACE NAME
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Country or larger entity
b       NR      First-order political jurisdiction
c       R       Intermediate political jurisdiction
d       NR      City
e       R       Relator term
f       R       City subsection
g       R       Other nonjurisdictional geographic region and feature
h       R       Extraterrestrial area
0       R       Authority record control number
2       NR      Source of heading or term
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

700     R       ADDED ENTRY--PERSONAL NAME
ind1    013     Type of personal name entry element
ind2    b2      Type of added entry
a       NR      Personal name
b       NR      Numeration
c       R       Titles and other words associated with a name
d       NR      Dates associated with a name
e       R       Relator term
f       NR      Date of a work
g       R       Miscellaneous information
h       NR      Medium
i       R       Relationship information
j       R       Attribution qualifier
k       R       Form subheading
l       NR      Language of a work
m       R       Medium of performance for music
n       R       Number of part/section of a work
o       NR      Arranged statement for music
p       R       Name of part/section of a work
q       NR      Fuller form of name
r       NR      Key for music
s       NR      Version
t       NR      Title of a work
u       NR      Affiliation
x       NR      International Standard Serial Number
0       R       Authority record control number
3       NR      Materials specified
4       R       Relationship
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

710     R       ADDED ENTRY--CORPORATE NAME
ind1    012     Type of corporate name entry element
ind2    b2      Type of added entry
a       NR      Corporate name or jurisdiction name as entry element
b       R       Subordinate unit
c       R       Location of meeting
d       R       Date of meeting or treaty signing
e       R       Relator term
f       NR      Date of a work
g       R       Miscellaneous information
h       NR      Medium
i       R       Relationship information
k       R       Form subheading
l       NR      Language of a work
m       R       Medium of performance for music
n       R       Number of part/section/meeting
o       NR      Arranged statement for music
p       R       Name of part/section of a work
r       NR      Key for music
s       NR      Version
t       NR      Title of a work
u       NR      Affiliation
x       NR      International Standard Serial Number
0       R       Authority record control number
3       NR      Materials specified
4       R       Relationship
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

711     R       ADDED ENTRY--MEETING NAME
ind1    012     Type of meeting name entry element
ind2    b2      Type of added entry
a       NR      Meeting name or jurisdiction name as entry element
c       R       Location of meeting
d       NR      Date of meeting
e       R       Subordinate unit
f       NR      Date of a work
g       R       Miscellaneous information
h       NR      Medium
i       R       Relationship information
j       R       Relator term
k       R       Form subheading
l       NR      Language of a work
n       R       Number of part/section/meeting
p       R       Name of part/section of a work
q       NR      Name of meeting following jurisdiction name entry element
s       NR      Version
t       NR      Title of a work
u       NR      Affiliation
x       NR      International Standard Serial Number
0       R       Authority record control number
3       NR      Materials specified
4       R       Relationship
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

720     R       ADDED ENTRY--UNCONTROLLED NAME
ind1    b12     Type of name
ind2    blank   Undefined
a       NR      Name
e       R       Relator term
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

730     R       ADDED ENTRY--UNIFORM TITLE
ind1    0-9     Nonfiling characters
ind2    b2      Type of added entry
a       NR      Uniform title
d       R       Date of treaty signing
f       NR      Date of a work
g       R       Miscellaneous information
h       NR      Medium
i       R       Relationship information
k       R       Form subheading
l       NR      Language of a work
m       R       Medium of performance for music
n       R       Number of part/section of a work
o       NR      Arranged statement for music
p       R       Name of part/section of a work
r       NR      Key for music
s       NR      Version
t       NR      Title of a work
x       NR      International Standard Serial Number
0       R       Authority record control number
3       NR      Materials specified
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

740     R       ADDED ENTRY--UNCONTROLLED RELATED/ANALYTICAL TITLE
ind1    0-9     Nonfiling characters
ind2    b2      Type of added entry
a       NR      Uncontrolled related/analytical title
h       NR      Medium
n       R       Number of part/section of a work
p       R       Name of part/section of a work
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

751     R       ADDED ENTRY--GEOGRAPHIC NAME
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Geographic name
e       R       Relator term
0       R       Authority record control number
2       NR      Source of heading or term
3       NR      Materials specified
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

752     R       ADDED ENTRY--HIERARCHICAL PLACE NAME
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Country or larger entity
b       NR      First-order political jurisdiction
c       NR      Intermediate political jurisdiction
d       NR      City
e       R       Relator term
f       R       City subsection
g       R       Other nonjurisdictional geographic region and feature
h       R       Extraterrestrial area
0       R       Authority record control number
2       NR      Source of heading or term
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

753     R       SYSTEM DETAILS ACCESS TO COMPUTER FILES
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Make and model of machine
b       NR      Programming language
c       NR      Operating system
0       R       Authority record control number or standard number
2       NR      Source of term
6       NR      Linkage
8       R       Field link and sequence number

754     R       ADDED ENTRY--TAXONOMIC IDENTIFICATION
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Taxonomic name
c       R       Taxonomic category
d       R       Common or alternative name
x       R       Non-public note
z       R       Public note
0       R       Authority record control number
2       NR      Source of taxonomic identification
6       NR      Linkage
8       R       Field link and sequence number

760     R       MAIN SERIES ENTRY
ind1    01      Note controller
ind2    b8      Display constant controller
a       NR      Main entry heading
b       NR      Edition
c       NR      Qualifying information
d       NR      Place, publisher, and date of publication
g       R       Related parts
h       NR      Physical description
i       R       Relationship information
m       NR      Material-specific details
n       R       Note
o       R       Other item identifier
s       NR      Uniform title
t       NR      Title
w       R       Record control number
x       NR      International Standard Serial Number
y       NR      CODEN designation
4       R       Relationship
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

762     R       SUBSERIES ENTRY
ind1    01      Note controller
ind2    b8      Display constant controller
a       NR      Main entry heading
b       NR      Edition
c       NR      Qualifying information
d       NR      Place, publisher, and date of publication
g       R       Related parts
h       NR      Physical description
i       R       Relationship information
m       NR      Material-specific details
n       R       Note
o       R       Other item identifier
s       NR      Uniform title
t       NR      Title
w       R       Record control number
x       NR      International Standard Serial Number
y       NR      CODEN designation
4       R       Relationship
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

765     R       ORIGINAL LANGUAGE ENTRY
ind1    01      Note controller
ind2    b8      Display constant controller
a       NR      Main entry heading
b       NR      Edition
c       NR      Qualifying information
d       NR      Place, publisher, and date of publication
g       R       Related parts
h       NR      Physical description
i       R       Relationship information
k       R       Series data for related item
m       NR      Material-specific details
n       R       Note
o       R       Other item identifier
r       R       Report number
s       NR      Uniform title
t       NR      Title
u       NR      Standard Technical Report Number
w       R       Record control number
x       NR      International Standard Serial Number
y       NR      CODEN designation
z       R       International Standard Book Number
4       R       Relationship
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

767     R       TRANSLATION ENTRY
ind1    01      Note controller
ind2    b8      Display constant controller
a       NR      Main entry heading
b       NR      Edition
c       NR      Qualifying information
d       NR      Place, publisher, and date of publication
g       R       Related parts
h       NR      Physical description
i       R       Relationship information
k       R       Series data for related item
m       NR      Material-specific details
n       R       Note
o       R       Other item identifier
r       R       Report number
s       NR      Uniform title
t       NR      Title
u       NR      Standard Technical Report Number
w       R       Record control number
x       NR      International Standard Serial Number
y       NR      CODEN designation
z       R       International Standard Book Number
4       R       Relationship
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

770     R       SUPPLEMENT/SPECIAL ISSUE ENTRY
ind1    01      Note controller
ind2    b8      Display constant controller
a       NR      Main entry heading
b       NR      Edition
c       NR      Qualifying information
d       NR      Place, publisher, and date of publication
g       R       Related parts
h       NR      Physical description
i       R       Relationship information
k       R       Series data for related item
m       NR      Material-specific details
n       R       Note
o       R       Other item identifier
r       R       Report number
s       NR      Uniform title
t       NR      Title
u       NR      Standard Technical Report Number
w       R       Record control number
x       NR      International Standard Serial Number
y       NR      CODEN designation
z       R       International Standard Book Number
4       R       Relationship
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

772     R       SUPPLEMENT PARENT ENTRY
ind1    01      Note controller
ind2    b08     Display constant controller
a       NR      Main entry heading
b       NR      Edition
c       NR      Qualifying information
d       NR      Place, publisher, and date of publication
g       R       Related parts
h       NR      Physical description
i       R       Relationship information
k       R       Series data for related item
m       NR      Material-specific details
n       R       Note
o       R       Other item identifier
r       R       Report number
s       NR      Uniform title
t       NR      Title
u       NR      Standard Technical Report Number
w       R       Record control number
x       NR      International Standard Serial Number
y       NR      CODEN designation
z       R       International Stan dard Book Number
4       R       Relationship
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

773     R       HOST ITEM ENTRY
ind1    01      Note controller
ind2    b8      Display constant controller
a       NR      Main entry heading
b       NR      Edition
d       NR      Place, publisher, and date of publication
g       R       Related parts
h       NR      Physical description
i       R       Relationship information
k       R       Series data for related item
m       NR      Material-specific details
n       R       Note
o       R       Other item identifier
p       NR      Abbreviated title
q       NR      Enumeration and first page
r       R       Report number
s       NR      Uniform title
t       NR      Title
u       NR      Standard Technical Report Number
w       R       Record control number
x       NR      International Standard Serial Number
y       NR      CODEN designation
z       R       International Standard Book Number
3       NR      Materials specified
4       R       Relationship
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

774     R       CONSTITUENT UNIT ENTRY
ind1    01      Note controller
ind2    b8      Display constant controller
a       NR      Main entry heading
b       NR      Edition
c       NR      Qualifying information
d       NR      Place, publisher, and date of publication
g       R       Related parts
h       NR      Physical description
i       R       Relationship information
k       R       Series data for related item
m       NR      Material-specific details
n       R       Note
o       R       Other item identifier
r       R       Report number
s       NR      Uniform title
t       NR      Title
u       NR      Standard Technical Report Number
w       R       Record control number
x       NR      International Standard Serial Number
y       NR      CODEN designation
z       R       International Standard Book Number
4       R       Relationship
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

775     R       OTHER EDITION ENTRY
ind1    01      Note controller
ind2    b8      Display constant controller
a       NR      Main entry heading
b       NR      Edition
c       NR      Qualifying information
d       NR      Place, publisher, and date of publication
e       NR      Language code
f       NR      Country code
g       R       Related parts
h       NR      Physical description
i       R       Relationship information
k       R       Series data for related item
m       NR      Material-specific details
n       R       Note
o       R       Other item identifier
r       R       Report number
s       NR      Uniform title
t       NR      Title
u       NR      Standard Technical Report Number
w       R       Record control number
x       NR      International Standard Serial Number
y       NR      CODEN designation
z       R       International Standard Book Number
4       R       Relationship
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

776     R       ADDITIONAL PHYSICAL FORM ENTRY
ind1    01      Note controller
ind2    b8      Display constant controller
a       NR      Main entry heading
b       NR      Edition
c       NR      Qualifying information
d       NR      Place, publisher, and date of publication
g       R       Related parts
h       NR      Physical description
i       R       Relationship information
k       R       Series data for related item
m       NR      Material-specific details
n       R       Note
o       R       Other item identifier
r       R       Report number
s       NR      Uniform title
t       NR      Title
u       NR      Standard Technical Report Number
w       R       Record control number
x       NR      International Standard Serial Number
y       NR      CODEN designation
z       R       International Standard Book Number
4       R       Relationship
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

777     R       ISSUED WITH ENTRY
ind1    01      Note controller
ind2    b8      Display constant controller
a       NR      Main entry heading
b       NR      Edition
c       NR      Qualifying information
d       NR      Place, publisher, and date of publication
g       R       Related parts
h       NR      Physical description
i       R       Relationship information
k       R       Series data for related item
m       NR      Material-specific details
n       R       Note
o       R       Other item identifier
s       NR      Uniform title
t       NR      Title
w       R       Record control number
x       NR      International Standard Serial Number
y       NR      CODEN designation
4       R       Relationship
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

780     R       PRECEDING ENTRY
ind1    01      Note controller
ind2    01234567    Type of relationship
a       NR      Main entry heading
b       NR      Edition
c       NR      Qualifying information
d       NR      Place, publisher, and date of publication
g       R       Related parts
h       NR      Physical description
i       R       Relationship information
k       R       Series data for related item
m       NR      Material-specific details
n       R       Note
o       R       Other item identifier
r       R       Report number
s       NR      Uniform title
t       NR      Title
u       NR      Standard Technical Report Number
w       R       Record control number
x       NR      International Standard Serial Number
y       NR      CODEN designation
z       R       International Standard Book Number
4       R       Relationship
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

785     R       SUCCEEDING ENTRY
ind1    01      Note controller
ind2    012345678    Type of relationship
a       NR      Main entry heading
b       NR      Edition
c       NR      Qualifying information
d       NR      Place, publisher, and date of publication
g       R       Related parts
h       NR      Physical description
i       R       Relationship information
k       R       Series data for related item
m       NR      Material-specific details
n       R       Note
o       R       Other item identifier
r       R       Report number
s       NR      Uniform title
t       NR      Title
u       NR      Standa rd Technical Report Number
w       R       Record control number
x       NR      International Standard Serial Number
y       NR      CODEN designation
z       R       International Standard Book Number
4       R       Relationship
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

786     R       DATA SOURCE ENTRY
ind1    01      Note controller
ind2    b8      Display constant controller
a       NR      Main entry heading
b       NR      Edition
c       NR      Qualifying information
d       NR      Place, publisher, and date of publication
g       R       Related parts
h       NR      Physical description
i       R       Relationship information
j       NR      Period of content
k       R       Series data for related item
m       NR      Material-specific details
n       R       Note
o       R       Other item identifier
p       NR      Abbreviated title
r       R       Report number
s       NR      Uniform title
t       NR      Title
u       NR      Standard Technical Report Number
v       NR      Source Contribution
w       R       Record control number
x       NR      International Standard Serial Number
y       NR      CODEN designation
z       R       International Standard Book Number
4       R       Relationship
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

787     R       OTHER RELATIONSHIP ENTRY
ind1    01      Note controller
ind2    b8      Display constant controller
a       NR      Main entry heading
b       NR      Edition
c       NR      Qualifying information
d       NR      Place, publisher, and date of publication
g       R       Related parts
h       NR      Physical description
i       R       Relationship information
k       R       Series data for related item
m       NR      Material-specific details
n       R       Note
o       R       Other item identifier
r       R       Report number
s       NR      Uniform title
t       NR      Title
u       NR      Standard Technical Report Number
w       R       Record control number
x       NR      International Standard Serial Number
y       NR      CODEN designation
z       R       International Standard Book Number
4       R       Relationship
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

800     R       SERIES ADDED ENTRY--PERSONAL NAME
ind1    013     Type of personal name entry element
ind2    blank   Undefined
a       NR      Personal name
b       NR      Numeration
c       R       Titles and other words associated with a name
d       NR      Dates associated with a name
e       R       Relator term
f       NR      Date of a work
g       R       Miscellaneous information
h       NR      Medium
j       R       Attribution qualifier
k       R       Form subheading
l       NR      Language of a work
m       R       Medium of performance for music
n       R       Number of part/section of a work
o       NR      Arranged statement for music
p       R       Name of part/section of a work
q       NR      Fuller form of name
r       NR      Key for music
s       NR      Version
t       NR      Title of a work
u       NR      Affiliation
v       NR      Volume/sequential designation
w       R       Bibliographic record control number
x       NR      International Standard Serial Number
0       R       Authority record control number
3       NR      Materials specified
4       R       Relationship
5       R       Institution to which field applies
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

810     R       SERIES ADDED ENTRY--CORPORATE NAME
ind1    012     Type of corporate name entry element
ind2    blank   Undefined
a       NR      Corporate name or jurisdiction name as entry element
b       R       Subordinate unit
c       R       Location of meeting
d       R       Date of meeting or treaty signing
e       R       Relator term
f       NR      Date of a work
g       R       Miscellaneous information
h       NR      Medium
k       R       Form subheading
l       NR      Language of a work
m       R       Medium of performance for music
n       R       Number of part/section/meeting
o       NR      Arranged statement for music
p       R       Name of part/section of a work
r       NR      Key for music
s       NR      Version
t       NR      Title of a work
u       NR      Affiliation
v       NR      Volume/sequential designation
w       R       Bibliographic record control number
x       NR      International Standard Serial Number
0       R       Authority record control number
3       NR      Materials specified
4       R       Relationship
5       R       Institution to which field applies
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

811     R       SERIES ADDED ENTRY--MEETING NAME
ind1    012     Type of meeting name entry element
ind2    blank   Undefined
a       NR      Meeting name or jurisdiction name as entry element
c       R       Location of meeting
d       NR      Date of meeting
e       R       Subordinate unit
f       NR      Date of a work
g       R       Miscellaneous information
h       NR      Medium
j       R       Relator term
k       R       Form subheading
l       NR      Language of a work
n       R       Number of part/section/meeting
p       R       Name of part/section of a work
q       NR      Name of meeting following jurisdiction name entry element
s       NR      Version
t       NR      Title of a work
u       NR      Affiliation
v       NR      Volume/sequential designation
w       R       Bibliographic record control number
x       NR      International Standard Serial Number
0       R       Authority record control number
3       NR      Materials specified
4       R       Relationship
5       R       Institution to which field applies
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

830     R       SERIES ADDED ENTRY--UNIFORM TITLE
ind1    blank   Undefined
ind2    0-9     Nonfiling characters
a       NR      Uniform title
d       R       Date of treaty signing
f       NR      Date of a work
g       R       Miscellaneous information
h       NR      Medium
k       R       Form subheading
l       NR      Language of a work
m       R       Medium of performance for music
n       R       Number of part/section of a work
o       NR      Arranged statement for music
p       R       Name of part/section of a work
r       NR      Key for music
s       NR      Version
t       NR      Title of a work
v       NR      Volume/sequential designation
w       R       Bibliographic record control number
x       NR      International Standard Serial Number
0       R       Authority record control number
3       NR      Materials specified
5       R       Institution to which field applies
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

841     NR      HOLDINGS CODED DATA VALUES

842     NR      TEXTUAL PHYSICAL FORM DESIGNATOR

843     R       REPRODUCTION NOTE

844     NR      NAME OF UNIT

845     R       TERMS GOVERNING USE AND REPRODUCTION NOTE

850     R       HOLDING INSTITUTION
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Holding institution
8       R       Field link and sequence number

852     R       LOCATION
ind1    b012345678    Shelving scheme
ind2    b012    Shelving order
a       NR      Location
b       R       Sublocation or collection
c       R       Shelving location
d       R       Former shelving location
e       R       Address
f       R       Coded location qualifier
g       R       Non-coded location qualifier
h       NR      Classification part
i       R       Item part
j       NR      Shelving control number
k       R       Call number prefix
l       NR      Shelving form of title
m       R       Call number suffix
n       NR      Country code
p       NR      Piece designation
q       NR      Piece physical condition
s       R       Copyright article-fee code
t       NR      Copy number
u       R       Uniform Resource Identifier
x       R       Nonpublic note
z       R       Public note
2       NR      Source of classification or shelving scheme
3       NR      Materials specified
6       NR      Linkage
8       NR      Sequence number

853     R       CAPTIONS AND PATTERN--BASIC BIBLIOGRAPHIC UNIT

854     R       CAPTIONS AND PATTERN--SUPPLEMENTARY MATERIAL

855     R       CAPTIONS AND PATTERN--INDEXES

856     R       ELECTRONIC LOCATION AND ACCESS
ind1    b012347    Access method
ind2    b0128   Relationship
a       R       Host name
b       R       Access number
c       R       Compression information
d       R       Path
f       R       Electronic name
h       NR      Processor of request
i       R       Instruction
j       NR      Bits per second
k       NR      Password
l       NR      Logon
m       R       Contact for access assistance
n       NR      Name of location of host
o       NR      Operating system
p       NR      Port
q       NR      Electronic format type
r       NR      Settings
s       R       File size
t       R       Terminal emulation
u       R       Uniform Resource Identifier
v       R       Hours access method available
w       R       Record control number
x       R       Nonpublic note
y       R       Link text
z       R       Public note
2       NR      Access method
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

863     R       ENUMERATION AND CHRONOLOGY--BASIC BIBLIOGRAPHIC UNIT

864     R       ENUMERATION AND CHRONOLOGY--SUPPLEMENTARY MATERIAL

865     R       ENUMERATION AND CHRONOLOGY--INDEXES

866     R       TEXTUAL HOLDINGS--BASIC BIBLIOGRAPHIC UNIT

867     R       TEXTUAL HOLDINGS--SUPPLEMENTARY MATERIAL

868     R       TEXTUAL HOLDINGS--INDEXES

876     R       ITEM INFORMATION--BASIC BIBLIOGRAPHIC UNIT

877     R       ITEM INFORMATION--SUPPLEMENTARY MATERIAL

878     R       ITEM INFORMATION--INDEXES

880     R       ALTERNATE GRAPHIC REPRESENTATION
ind1            Same as associated field
ind2            Same as associated field
6       NR      Linkage

882     NR      REPLACEMENT RECORD INFORMATION
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Replacement title
i       R       Explanatory text
w       R       Replacement bibliographic record control number
6       NR      Linkage
8       R       Field link and sequence number

883     R       MACHINE-GENERATED METADATA PROVENANCE
ind1    b01     Type of field
ind2    blank   Undefined
a       NR      Generation process
c       NR      Confidence value
d       NR      Generation date
q       NR      Generation agency
x       NR      Validity end date
u       NR      Uniform Resource Identifier
w       R       Bibliographic record control number
0       R       Authority record control number or standard number
8       R       Field link and sequence number

884     R       DESCRIPTION CONVERSION INFORMATION
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Conversion process
g       NR      Conversion date
k       NR      Identifier of source metadata
q       NR      Conversion agency
u       R       Uniform Resource Identifier

885     R       MATCHING INFORMATION
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Matching information
b       NR      Status of matching and its checking
c       NR      Confidence value
d       NR      Generation date
w       R       Record control number
x       R       Nonpublic note
z       R       Public note
0       R       Authority record control number or standard number
2       NR      Source
5       R       Institution to which field applies

886     R       FOREIGN MARC INFORMATION FIELD
ind1    012     Type of field
ind2    blank   Undefined
a       NR      Tag of the foreign MARC field
b       NR      Content of the foreign MARC field
c-z     NR      Foreign MARC subfield
0-1     NR      Foreign MARC subfield
2       NR      Source of data
4       NR      Source of data
3-9     NR      Source of data

887     R       NON-MARC INFORMATION FIELD
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Content of non-MARC field
2       NR      Source of data
RULES;
        // @codingStandardsIgnoreEnd
    }
    // }}}
}
// }}}

PK��Z7�*c��File/MARC/Subfield.phpnu�[���<?php

/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */

/**
 * Parser for MARC records
 *
 * This package is based on the PHP MARC package, originally called "php-marc",
 * that is part of the Emilda Project (http://www.emilda.org). Christoffer
 * Landtman generously agreed to make the "php-marc" code available under the
 * GNU LGPL so it could be used as the basis of this PEAR package.
 * 
 * PHP version 5
 *
 * LICENSE: This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category  File_Formats
 * @package   File_MARC
 * @author    Christoffer Landtman <landtman@realnode.com>
 * @author    Dan Scott <dscott@laurentian.ca>
 * @copyright 2003-2008 Oy Realnode Ab, Dan Scott
 * @license   http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/File_MARC
 */

// {{{ class File_MARC_Subfield
/**
 * The File_MARC_Subfield class represents a single subfield in a MARC
 * record field.
 *
 * Represents a subfield within a MARC field and implements all management
 * functions related to a single subfield. This class also implements
 * the possibility of duplicate subfields within a single field, for example
 * 650 _z Test1 _z Test2.
 *
 * @category File_Formats
 * @package  File_MARC
 * @author   Christoffer Landtman <landtman@realnode.com>
 * @author   Dan Scott <dscott@laurentian.ca>
 * @license  http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @link     http://pear.php.net/package/File_MARC
 */
class File_MARC_Subfield
{
    // {{{ properties
    /**
     * Subfield code, e.g. _a, _b
     * @var string
     */
    protected $code;

    /**
     * Data contained by the subfield
     * @var string
     */
    protected $data;

    /**
     * Position of the subfield
     * @var int
     */
    protected $position;

    // }}}

    // {{{ Constructor: function __construct()
    /**
     * File_MARC_Subfield constructor
     *
     * Create a new subfield to represent the code and data
     *
     * @param string $code Subfield code
     * @param string $data Subfield data
     */
    function __construct($code, $data)
    {
        $this->code = $code;
        $this->data = $data;
    }
    // }}}

    // {{{ Destructor: function __destruct()
    /**
     * Destroys the subfield
     */
    function __destruct()
    {
        $this->code = null;
        $this->data = null;
        $this->position = null;
    }
    // }}}

    // {{{ Explicit destructor: function delete()
    /**
     * Destroys the subfield
     *
     * @return true
     */
    function delete()
    {
        $this->__destruct();
    }
    // }}}

    // {{{ getCode()
    /**
     * Return code of the subfield
     *
     * @return string Tag name
     */
    function getCode()
    {
        return (string)$this->code;
    }
    // }}}

    // {{{ getData()
    /**
     * Return data of the subfield
     *
     * @return string data
     */
    function getData()
    {
        return (string)$this->data;
    }
    // }}}

    // {{{ getPosition()
    /**
     * Return position of the subfield
     *
     * @return int data
     */
    function getPosition()
    {
        return $this->position;
    }
    // }}}

    // {{{ __toString()
    /**
     * Return string representation of subfield
     *
     * @return string String representation
     */
    public function __toString()
    {
        $pretty = '[' . $this->getCode() . ']: ' . $this->getData();
        return $pretty;
    }
    // }}}

    // {{{ toRaw()
    /**
     * Return the USMARC representation of the subfield
     *
     * @return string USMARC representation
     */
    function toRaw()
    {
        $result = File_MARC::SUBFIELD_INDICATOR.$this->code.$this->data;
        return (string)$result;
    }
    // }}}

    // {{{ setCode()
    /**
     * Sets code of the subfield
     *
     * @param string $code new code for the subfield
     *
     * @return string code 
     */
    function setCode($code)
    {
        if ($code) {
            // could check more stringently; m/[a-Z]/ or the likes
            $this->code = $code;
        } else {
            // code must be _something_; raise error
            return false;
        }
        return true;
    }
    // }}}

    // {{{ setData()
    /**
     * Sets data of the subfield
     *
     * @param string $data new data for the subfield
     *
     * @return string data
     */
    function setData($data)
    {
        $this->data = $data;
        return true;
    }
    // }}}

    // {{{ setPosition()
    /**
     * Sets position of the subfield
     *
     * @param string $pos new position of the subfield
     *
     * @return void
     */
    function setPosition($pos)
    {
        $this->position = $pos;
    }
    // }}}

    // {{{ isEmpty()
    /**
     * Checks whether the subfield is empty or not
     *
     * @return bool True or false
     */
    function isEmpty()
    {
        // There is data
        if (strlen($this->data)) {
            return false;
        }

        // There is no data
        return true;
    }
    // }}}
}
// }}}

PK��Z�1����5test/Structures_LinkedList/tests/single_link_007.phptnu�[���--TEST--
single_link_007: Test many corner cases
--FILE--
<?php
 
$dir = dirname(__FILE__);
require 'Structures/LinkedList/Single.php';
require 'SingleLinkTester.php';

$xyy = new Structures_LinkedList_Single();

// prepend to an empty list corner case: 1
$xyy->prependNode($tester1);
print "Current: {$xyy->current()->getNumb()}\n";

// prepend to a list with only one element: 21
$xyy->prependNode($tester2);
print "Current: {$xyy->current()->getNumb()}\n";

// insert after tail node corner case: 213
$xyy->insertNode($tester3, $tester1);
print "Current: {$xyy->current()->getNumb()}\n";

// insert before root node corner case: 4213
$xyy->insertNode($tester4, $tester2, true);
print "Current: {$xyy->current()->getNumb()}\n";

// insert before tail node corner case: 42153
$xyy->insertNode($tester5, $tester3, true);
print "Current: {$xyy->current()->getNumb()}\n";

print "Foreach: ";
foreach ($xyy as $node) {
    print $node->getNumb();
}

print "\nWhile (in reverse): ";
// test reverse iteration with while()
$link = $xyy->end();
do {
    print $link->getNumb();
} while ($link = $xyy->previous());
?>
--EXPECT--
Current: 1
Current: 1
Current: 1
Current: 1
Current: 1
Foreach: 42153
While (in reverse): 35124
PK��Z�Z�x��5test/Structures_LinkedList/tests/single_link_002.phptnu�[���--TEST--
single_link_002: Append links to an initially empty linked list
--FILE--
<?php
 
$dir = dirname(__FILE__);
require 'Structures/LinkedList/Single.php';
require 'SingleLinkTester.php';

$xyy = new Structures_LinkedList_Single();
$xyy->appendNode($tester1);
$xyy->appendNode($tester2);
$xyy->appendNode($tester3);
$xyy->insertNode($tester4, $tester2, true);

$link = $xyy->current();
print $link->getNumb();

// test iteration with while()
while ($link = $xyy->next()) {
    print $link->getNumb();
}
$link = $xyy->rewind();
print "\n";
print $link->getNumb();
print "\n";

// test foreach() iteration
foreach ($xyy as $bull) {
  print $bull->getNumb();
}
?>
--EXPECT--
1423
1
1423
PK��Z(��  .test/Structures_LinkedList/tests/link_004.phptnu�[���--TEST--
link_004: Delete every link in the list
--FILE--
<?php
 
$dir = dirname(__FILE__);
require 'Structures/LinkedList/Double.php';
require 'LinkTester.php';

$xyy = new Structures_LinkedList_Double($tester1);
$xyy->appendNode($tester2);
$xyy->appendNode($tester3);
$xyy->appendNode($tester4);

// Delete all nodes from the list
while ($link = $xyy->rewind()) {
    print "Deleted " . $link->getNumb() . "\n";
    $xyy->deleteNode($link);
}
$link = $xyy->rewind();
print "Done\n";
?>
--EXPECT--
Deleted 1
Deleted 2
Deleted 3
Deleted 4
Done
PK��Z���|��5test/Structures_LinkedList/tests/SingleLinkTester.phpnu�[���<?php
class LinkTester extends Structures_LinkedList_SingleNode {
    protected $_my_number;

    function __construct($num) {
        $this->_my_number = $num;
    }

    function getNumb() {
        return $this->_my_number;
    }

    function setNumb($numb) {
        $this->_my_number = $numb;
    }
}

$tester1 = new LinkTester(1);
$tester2 = new LinkTester(2);
$tester3 = new LinkTester(3);
$tester4 = new LinkTester(4);
$tester5 = new LinkTester(5);

?>
PK��Z髂[��5test/Structures_LinkedList/tests/single_link_006.phptnu�[���--TEST--
single_link_006: Corner case: add a node before the root
--FILE--
<?php
 
$dir = dirname(__FILE__);
require 'Structures/LinkedList/Single.php';
require 'SingleLinkTester.php';

$xyy = new Structures_LinkedList_Single();
$xyy->prependNode($tester1);
$xyy->appendNode($tester2);
$xyy->appendNode($tester3);
$xyy->insertNode($tester4, $tester2, true);

// Ensure we can increment the current node without messing up the list
print "\nCurrent: " . $xyy->current()->getNumb() . "\n";
$link = $xyy->next();
print "Current: " . $link->getNumb() . "\n";

$xyy->insertNode($tester5, $tester1, true);

print "\n";

$link = $xyy->current();
print "Current: " . $link->getNumb();

print "\n\nWhile: ";
// test iteration with while()
$link = $xyy->rewind();
do {
    print $link->getNumb();
} while ($link = $xyy->next());

print "\n\nForeach: ";

// test foreach() iteration
foreach ($xyy as $bull) {
  print $bull->getNumb();
}
?>
--EXPECT--
Current: 1
Current: 4

Current: 4

While: 51423

Foreach: 51423
PK��Zs��DHH.test/Structures_LinkedList/tests/link_007.phptnu�[���--TEST--
link_007: Test many corner cases
--FILE--
<?php
 
$dir = dirname(__FILE__);
require 'Structures/LinkedList/Double.php';
require 'LinkTester.php';

$xyy = new Structures_LinkedList_Double();

// prepend to an empty list corner case: 1
$xyy->prependNode($tester1);
print "Current: {$xyy->current()->getNumb()}\n";

// prepend to a list with only one element: 21
$xyy->prependNode($tester2);
print "Current: {$xyy->current()->getNumb()}\n";

// insert after tail node corner case: 213
$xyy->insertNode($tester3, $tester1);
print "Current: {$xyy->current()->getNumb()}\n";

// insert before root node corner case: 4213
$xyy->insertNode($tester4, $tester2, true);
print "Current: {$xyy->current()->getNumb()}\n";

// insert before tail node corner case: 42153
$xyy->insertNode($tester5, $tester3, true);
print "Current: {$xyy->current()->getNumb()}\n";

// insert after root node corner case: 421653
$xyy->insertNode($tester6, $tester1);
print "Current: {$xyy->current()->getNumb()}\n";

print "Foreach: ";
foreach ($xyy as $node) {
    print $node->getNumb();
}

print "\nWhile (in reverse): ";
// test reverse iteration with while()
$link = $xyy->end();
do {
    print $link->getNumb();
} while ($link = $xyy->previous());
?>
--EXPECT--
Current: 1
Current: 1
Current: 1
Current: 1
Current: 1
Current: 1
Foreach: 421653
While (in reverse): 356124
PK��Z�����.test/Structures_LinkedList/tests/link_005.phptnu�[���--TEST--
link_005: Pass different class types to constructors
--FILE--
<?php
 
$dir = dirname(__FILE__);
require 'Structures/LinkedList/Double.php';

class TesterExtend extends Structures_LinkedList_DoubleNode {
    protected $_my_number;

    function __construct($tester, $num) {
        $this->_my_number = $num;
        parent::__construct($tester);
    }
}

class TesterFail {
    protected $summary;
    protected $fulltext;

    function __construct($summary, $fulltext) {
        $this->summary = $summary;
        $this->fulltext = $fulltext;
    }
}


// This should work: TesterExtend extends the Structure_LinkedList_DoubleNode class
$tester_extend = new TesterExtend(null, 1);
$xyy = new Structures_LinkedList_Double($tester_extend);
print "Checking for errors in the expected success case:\n";

// This should fail
print "Checking for errors in the expected failure case:\n";
$tester_fail = new TesterFail(null, 1);
$xyy_fail = new Structures_LinkedList_Double($tester_fail);
?>
--EXPECTF--
Checking for errors in the expected success case:
Checking for errors in the expected failure case:

%satal error: Argument 1 passed to Structures_LinkedList_Double::__construct() must be an instance of Structures_LinkedList_DoubleNode%s
PK��Z�#,E��5test/Structures_LinkedList/tests/single_link_005.phptnu�[���--TEST--
single_link_005: Pass different class types to constructors
--FILE--
<?php
 
$dir = dirname(__FILE__);
require 'Structures/LinkedList/Single.php';

class TesterExtend extends Structures_LinkedList_SingleNode {
    protected $_my_number;

    function __construct($tester, $num) {
        $this->_my_number = $num;
        parent::__construct($tester);
    }
}

class TesterFail {
    protected $summary;
    protected $fulltext;

    function __construct($summary, $fulltext) {
        $this->summary = $summary;
        $this->fulltext = $fulltext;
    }
}


// This should work: TesterExtend extends the Structure_LinkedList_SingleNode class
$tester_extend = new TesterExtend(null, 1);
$xyy = new Structures_LinkedList_Single($tester_extend);
print "Checking for errors in the expected success case:\n";

// This should fail
print "Checking for errors in the expected failure case:\n";
$tester_fail = new TesterFail(null, 1);
$xyy_fail = new Structures_LinkedList_Single($tester_fail);
?>
--EXPECTF--
Checking for errors in the expected success case:
Checking for errors in the expected failure case:

%satal error: Argument 1 passed to Structures_LinkedList_Single::__construct() must be an instance of Structures_LinkedList_SingleNode%s
PK��Z����/test/Structures_LinkedList/tests/LinkTester.phpnu�[���<?php
class LinkTester extends Structures_LinkedList_DoubleNode {
    protected $_my_number;

    function __construct($num) {
        $this->_my_number = $num;
    }

    function getNumb() {
        return $this->_my_number;
    }

    function setNumb($numb) {
        $this->_my_number = $numb;
    }
}

$tester1 = new LinkTester(1);
$tester2 = new LinkTester(2);
$tester3 = new LinkTester(3);
$tester4 = new LinkTester(4);
$tester5 = new LinkTester(5);
$tester6 = new LinkTester(6);

?>
PK��Z� ���.test/Structures_LinkedList/tests/link_001.phptnu�[���--TEST--
link_001: Test linked list constructed with an initial link
--FILE--
<?php
 
$dir = dirname(__FILE__);
require 'Structures/LinkedList/Double.php';
require 'LinkTester.php';

$xyy = new Structures_LinkedList_Double($tester1);
$xyy->appendNode($tester2);
$xyy->appendNode($tester3);
$xyy->appendNode($tester4);

$link = $xyy->current();
print "Current: " . $link->getNumb() . "\n";

print "While: ";
// test iteration with while()
do {
    print $link->getNumb();
} while ($link = $xyy->next());

print "\nRewind: ";
$link = $xyy->rewind();
print $link->getNumb();
print "\n";

print "Foreach: ";
// test foreach() iteration
foreach ($xyy as $bull) {
  print $bull->getNumb();
}

print "\nEnd: ";
$link = $xyy->end();
print $link->getNumb();
print "\n";

print "While (in reverse): ";
// test iteration with while()
do {
    print $link->getNumb();
} while ($link = $xyy->previous());


?>
--EXPECT--
Current: 1
While: 1234
Rewind: 1
Foreach: 1234
End: 4
While (in reverse): 4321
PK��Z骗���.test/Structures_LinkedList/tests/link_006.phptnu�[���--TEST--
link_006: Corner case: add a node before the root
--FILE--
<?php
 
$dir = dirname(__FILE__);
require 'Structures/LinkedList/Double.php';
require 'LinkTester.php';

$xyy = new Structures_LinkedList_Double();
$xyy->prependNode($tester1);
$xyy->appendNode($tester2);
$xyy->appendNode($tester3);
$xyy->insertNode($tester4, $tester2, true);

// Ensure we can increment the current node without messing up the list
print "\nCurrent: " . $xyy->current()->getNumb() . "\n";
$link = $xyy->next();
print "Current: " . $link->getNumb() . "\n";

$xyy->insertNode($tester5, $tester1, true);

print "\n";

$link = $xyy->current();
print "Current: " . $link->getNumb();

print "\n\nWhile: ";
// test iteration with while()
$link = $xyy->rewind();
do {
    print $link->getNumb();
} while ($link = $xyy->next());

print "\n\nForeach: ";

// test foreach() iteration
foreach ($xyy as $bull) {
  print $bull->getNumb();
}
?>
--EXPECT--
Current: 1
Current: 4

Current: 4

While: 51423

Foreach: 51423
PK��Z��)��.test/Structures_LinkedList/tests/link_002.phptnu�[���--TEST--
link_002: Append links to an initially empty linked list
--FILE--
<?php
 
$dir = dirname(__FILE__);
require 'Structures/LinkedList/Double.php';
require 'LinkTester.php';

$xyy = new Structures_LinkedList_Double();
$xyy->appendNode($tester1);
$xyy->appendNode($tester2);
$xyy->appendNode($tester3);
$xyy->insertNode($tester4, $tester2, true);

$link = $xyy->current();
print $link->getNumb();

// test iteration with while()
while ($link = $xyy->next()) {
    print $link->getNumb();
}
$link = $xyy->rewind();
print "\n";
print $link->getNumb();
print "\n";

// test foreach() iteration
foreach ($xyy as $bull) {
  print $bull->getNumb();
}
?>
--EXPECT--
1423
1
1423
PK��Z�4����5test/Structures_LinkedList/tests/single_link_001.phptnu�[���--TEST--
single_link_001: Test linked list constructed with an initial link
--FILE--
<?php
 
$dir = dirname(__FILE__);
require 'Structures/LinkedList/Single.php';
require 'SingleLinkTester.php';

$xyy = new Structures_LinkedList_Single($tester1);
$xyy->appendNode($tester2);
$xyy->appendNode($tester3);
$xyy->appendNode($tester4);

$link = $xyy->current();
print "Current: " . $link->getNumb() . "\n";

print "While: ";
// test iteration with while()
do {
    print $link->getNumb();
} while ($link = $xyy->next());

print "\nRewind: ";
$link = $xyy->rewind();
print $link->getNumb();
print "\n";

print "Foreach: ";
// test foreach() iteration
foreach ($xyy as $bull) {
  print $bull->getNumb();
}

print "\nEnd: ";
$link = $xyy->end();
print $link->getNumb();
print "\n";

print "While (in reverse): ";
// test iteration with while()
do {
    print $link->getNumb();
} while ($link = $xyy->previous());


?>
--EXPECT--
Current: 1
While: 1234
Rewind: 1
Foreach: 1234
End: 4
While (in reverse): 4321
PK��Z)�y--5test/Structures_LinkedList/tests/single_link_004.phptnu�[���--TEST--
single_link_004: Delete every link in the list
--FILE--
<?php
 
$dir = dirname(__FILE__);
require 'Structures/LinkedList/Single.php';
require 'SingleLinkTester.php';

$xyy = new Structures_LinkedList_Single($tester1);
$xyy->appendNode($tester2);
$xyy->appendNode($tester3);
$xyy->appendNode($tester4);

// Delete all nodes from the list
while ($link = $xyy->rewind()) {
    print "Deleted " . $link->getNumb() . "\n";
    $xyy->deleteNode($link);
}
$link = $xyy->rewind();
print "Done\n";
?>
--EXPECT--
Deleted 1
Deleted 2
Deleted 3
Deleted 4
Done
PK��Z�K��5test/Structures_LinkedList/tests/single_link_003.phptnu�[���--TEST--
single_link_003: Append links in a specific order
--FILE--
<?php
 
$dir = dirname(__FILE__);
require 'Structures/LinkedList/Single.php';
require 'SingleLinkTester.php';

$xyy = new Structures_LinkedList_Single();

// add initial link in the list
$xyy->appendNode($tester1);
print $tester1->getNumb() . "\n";

// add after initial link
$xyy->appendNode($tester2);
print $tester2->getNumb() . "\n";

// add after initial link, bumping #2 up
$xyy->insertNode($tester3, $tester1);
print $tester3->getNumb() . "\n";

// add after link #3, bumping #2 up again
$xyy->insertNode($tester4, $tester3);
print $tester4->getNumb() . "\n";

print "\n";

$link = $xyy->current();
print $link->getNumb();
print "\n";

// test iteration with while()
while ($link = $xyy->next()) {
    print $link->getNumb();
    print "\n";
}
$link = $xyy->rewind();
print "\n";
print $link->getNumb();
print "\n";

// test foreach() iteration
foreach ($xyy as $bull) {
  print $bull->getNumb();
}
?>
--EXPECT--
1
2
3
4

1
3
4
2

1
1342
PK��Z�o���.test/Structures_LinkedList/tests/link_003.phptnu�[���--TEST--
link_003: Append links in a specific order
--FILE--
<?php
 
$dir = dirname(__FILE__);
require 'Structures/LinkedList/Double.php';
require 'LinkTester.php';

$xyy = new Structures_LinkedList_Double();

// add initial link in the list
$xyy->appendNode($tester1);
print $tester1->getNumb() . "\n";

// add after initial link
$xyy->appendNode($tester2);
print $tester2->getNumb() . "\n";

// add after initial link, bumping #2 up
$xyy->insertNode($tester3, $tester1);
print $tester3->getNumb() . "\n";

// add after link #3, bumping #2 up again
$xyy->insertNode($tester4, $tester3);
print $tester4->getNumb() . "\n";

print "\n";

$link = $xyy->current();
print $link->getNumb();
print "\n";

// test iteration with while()
while ($link = $xyy->next()) {
    print $link->getNumb();
    print "\n";
}
$link = $xyy->rewind();
print "\n";
print $link->getNumb();
print "\n";

// test foreach() iteration
foreach ($xyy as $bull) {
  print $bull->getNumb();
}
?>
--EXPECT--
1
2
3
4

1
3
4
2

1
1342
PK��Z�x`(��test/Mail/tests/bug17317.phptnu�[���--TEST--
Mail_RFC822::parseAddressList invalid periods in mail address
--FILE--
<?php
require "Mail/RFC822.php";

$result[] = Mail_RFC822::parseAddressList('.name@example.com');
$result[] = Mail_RFC822::parseAddressList('name.@example.com');
$result[] = Mail_RFC822::parseAddressList('name..name@example.com');

foreach ($result as $r) {
    if (is_a($r, 'PEAR_Error')) {
        echo "OK\n";
    }
}
--EXPECT--
OK
OK
OK
PK��Z��q/��test/Mail/tests/13659.phptnu�[���--TEST--
Mail: Test for bug #13659
--FILE--
<?php
//require_once dirname(__FILE__) . '/../Mail/RFC822.php';
require_once 'Mail/RFC822.php';
require_once 'PEAR.php';

$address = '"Test Student" <test@mydomain.com> (test)';
$parser = new Mail_RFC822();
$result = $parser->parseAddressList($address, 'anydomain.com', TRUE);

if (!PEAR::isError($result) && is_array($result) && is_object($result[0]))
    if ($result[0]->personal == '"Test Student"' &&
        $result[0]->mailbox == "test" &&
	$result[0]->host == "mydomain.com" &&
	is_array($result[0]->comment) && $result[0]->comment[0] == 'test')
    {
        print("OK");
    }


?>
--EXPECT--
OK
PK��Z��test/Mail/tests/9137_2.phptnu�[���--TEST--
Mail: Test for bug #9137, take 2
--FILE--
<?php

require_once dirname(__FILE__) . '/../Mail/RFC822.php';
require_once 'PEAR.php';

$addresses = array(
    array('raw' => '"John Doe" <test@example.com>'),
    array('raw' => '"John Doe' . chr(92) . '" <test@example.com>'),
    array('raw' => '"John Doe' . chr(92) . chr(92) . '" <test@example.com>'),
    array('raw' => '"John Doe' . chr(92) . chr(92) . chr(92) . '" <test@example.com>'),
    array('raw' => '"John Doe' . chr(92) . chr(92) . chr(92) . chr(92) . '" <test@example.com>'),
    array('raw' => '"John Doe <test@example.com>'),
);

for ($i = 0; $i < count($addresses); $i++) {
    // construct the address
    $address = $addresses[$i]['raw'];
    $parsedAddresses = Mail_RFC822::parseAddressList($address);
    if (PEAR::isError($parsedAddresses)) {
        echo $address." :: Failed to validate\n";
    } else {
        echo $address." :: Parsed\n";
    }
}

--EXPECT--
"John Doe" <test@example.com> :: Parsed
"John Doe\" <test@example.com> :: Failed to validate
"John Doe\\" <test@example.com> :: Parsed
"John Doe\\\" <test@example.com> :: Failed to validate
"John Doe\\\\" <test@example.com> :: Parsed
"John Doe <test@example.com> :: Failed to validate
PK��Zw�����test/Mail/tests/smtp_error.phptnu�[���--TEST--
Mail: SMTP Error Reporting
--SKIPIF--
<?php

require_once 'PEAR/Registry.php';
$registry = new PEAR_Registry();

if (!$registry->packageExists('Net_SMTP')) die("skip\n");
--FILE--
<?php
require_once 'Mail.php';

/* Reference a bogus SMTP server address to guarantee a connection failure. */
$params = array('host' => 'bogus.host.tld');

/* Create our SMTP-based mailer object. */
$mailer = Mail::factory('smtp', $params);

/* Attempt to send an empty message in order to trigger an error. */
$e = $mailer->send(array(), array(), '');
if (is_a($e, 'PEAR_Error')) {
     $err = $e->getMessage();
     if (preg_match('/Failed to connect to bogus.host.tld:25 \[SMTP: Failed to connect socket:.*/i', $err)) {
        echo "OK";
     }
}

--EXPECT--
OKPK��Z)f$�!!test/Mail/tests/rfc822.phptnu�[���--TEST--
Mail_RFC822: Address Parsing
--FILE--
<?php
require_once 'Mail/RFC822.php';

$parser = new Mail_RFC822();

/* A simple, bare address. */
$address = 'user@example.com';
print_r($parser->parseAddressList($address, null, true, true));

/* Address groups. */
$address = 'My Group: "Richard" <richard@localhost> (A comment), ted@example.com (Ted Bloggs), Barney;';
print_r($parser->parseAddressList($address, null, true, true));

/* A valid address with spaces in the local part. */
$address = '<"Jon Parise"@php.net>';
print_r($parser->parseAddressList($address, null, true, true));

/* An invalid address with spaces in the local part. */
$address = '<Jon Parise@php.net>';
$result = $parser->parseAddressList($address, null, true, true);
if (is_a($result, 'PEAR_Error')) echo $result->getMessage() . "\n";

/* A valid address with an uncommon TLD. */
$address = 'jon@host.longtld';
$result = $parser->parseAddressList($address, null, true, true);
if (is_a($result, 'PEAR_Error')) echo $result->getMessage() . "\n";

--EXPECT--
Array
(
    [0] => stdClass Object
        (
            [personal] => 
            [comment] => Array
                (
                )

            [mailbox] => user
            [host] => example.com
        )

)
Array
(
    [0] => stdClass Object
        (
            [groupname] => My Group
            [addresses] => Array
                (
                    [0] => stdClass Object
                        (
                            [personal] => "Richard"
                            [comment] => Array
                                (
                                    [0] => A comment
                                )

                            [mailbox] => richard
                            [host] => localhost
                        )

                    [1] => stdClass Object
                        (
                            [personal] => 
                            [comment] => Array
                                (
                                    [0] => Ted Bloggs
                                )

                            [mailbox] => ted
                            [host] => example.com
                        )

                    [2] => stdClass Object
                        (
                            [personal] => 
                            [comment] => Array
                                (
                                )

                            [mailbox] => Barney
                            [host] => localhost
                        )

                )

        )

)
Array
(
    [0] => stdClass Object
        (
            [personal] => 
            [comment] => Array
                (
                )

            [mailbox] => "Jon Parise"
            [host] => php.net
        )

)
Validation failed for: <Jon Parise@php.net>
PK��Z8x����test/Mail/tests/bug17178.phptnu�[���--TEST--
Mail_RFC822::parseAddressList does not accept RFC-valid group syntax
--FILE--
<?php
require "Mail/RFC822.php";

var_dump(Mail_RFC822::parseAddressList("empty-group:;","invalid",false,false)); 

--EXPECT--
array(0) {
} 
PK��Z*����test/Mail/tests/9137.phptnu�[���--TEST--
Mail: Test for bug #9137
--FILE--
<?php

require_once dirname(__FILE__) . '/../Mail/RFC822.php';
require_once 'PEAR.php';

$addresses = array(
    array('name' => 'John Doe', 'email' => 'test@example.com'),
    array('name' => 'John Doe\\', 'email' => 'test@example.com'),
    array('name' => 'John "Doe', 'email' => 'test@example.com'),
    array('name' => 'John "Doe\\', 'email' => 'test@example.com'),
);

for ($i = 0; $i < count($addresses); $i++) {
    // construct the address
    $address = "\"" . addslashes($addresses[$i]['name']) . "\" ".
        "<".$addresses[$i]['email'].">";

    $parsedAddresses = Mail_RFC822::parseAddressList($address);
    if (is_a($parsedAddresses, 'PEAR_Error')) {
        echo $address." :: Failed to validate\n";
    } else {
        echo $address." :: Parsed\n";
    }
}

--EXPECT--
"John Doe" <test@example.com> :: Parsed
"John Doe\\" <test@example.com> :: Parsed
"John \"Doe" <test@example.com> :: Parsed
"John \"Doe\\" <test@example.com> :: Parsed
PK��ZFtest/Finder/Symfony/Component/Finder/Tests/Fixtures/with space/foo.txtnu�[���PK��ZAtest/Finder/Symfony/Component/Finder/Tests/Fixtures/A/B/C/abc.datnu�[���PK��Z>test/Finder/Symfony/Component/Finder/Tests/Fixtures/A/B/ab.datnu�[���PK��Z;test/Finder/Symfony/Component/Finder/Tests/Fixtures/A/a.datnu�[���PK��Z9test/Finder/Symfony/Component/Finder/Tests/Fixtures/one/anu�[���PK��Z@test/Finder/Symfony/Component/Finder/Tests/Fixtures/one/b/d.neonnu�[���PK��Z@test/Finder/Symfony/Component/Finder/Tests/Fixtures/one/b/c.neonnu�[���PK��Zo�5|=test/Finder/Symfony/Component/Finder/Tests/Fixtures/dolor.txtnu�[���dolor sit amet
DOLOR SIT AMETPK��Z'���))=test/Finder/Symfony/Component/Finder/Tests/Fixtures/ipsum.txtnu�[���ipsum dolor sit amet
IPSUM DOLOR SIT AMETPK��Z��55=test/Finder/Symfony/Component/Finder/Tests/Fixtures/lorem.txtnu�[���lorem ipsum dolor sit amet
LOREM IPSUM DOLOR SIT AMETPK��ZEtest/Finder/Symfony/Component/Finder/Tests/Fixtures/copy/A/a.dat.copynu�[���PK��ZKtest/Finder/Symfony/Component/Finder/Tests/Fixtures/copy/A/B/C/abc.dat.copynu�[���PK��ZHtest/Finder/Symfony/Component/Finder/Tests/Fixtures/copy/A/B/ab.dat.copynu�[���PK��Z˟�ׄ	�	Ltest/Finder/Symfony/Component/Finder/Tests/Comparator/DateComparatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Comparator;

use Symfony\Component\Finder\Comparator\DateComparator;

class DateComparatorTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        try {
            new DateComparator('foobar');
            $this->fail('__construct() throws an \InvalidArgumentException if the test expression is not valid.');
        } catch (\Exception $e) {
            $this->assertInstanceOf('InvalidArgumentException', $e, '__construct() throws an \InvalidArgumentException if the test expression is not valid.');
        }

        try {
            new DateComparator('');
            $this->fail('__construct() throws an \InvalidArgumentException if the test expression is not valid.');
        } catch (\Exception $e) {
            $this->assertInstanceOf('InvalidArgumentException', $e, '__construct() throws an \InvalidArgumentException if the test expression is not valid.');
        }
    }

    /**
     * @dataProvider getTestData
     */
    public function testTest($test, $match, $noMatch)
    {
        $c = new DateComparator($test);

        foreach ($match as $m) {
            $this->assertTrue($c->test($m), '->test() tests a string against the expression');
        }

        foreach ($noMatch as $m) {
            $this->assertFalse($c->test($m), '->test() tests a string against the expression');
        }
    }

    public function getTestData()
    {
        return array(
            array('< 2005-10-10', array(strtotime('2005-10-09')), array(strtotime('2005-10-15'))),
            array('until 2005-10-10', array(strtotime('2005-10-09')), array(strtotime('2005-10-15'))),
            array('before 2005-10-10', array(strtotime('2005-10-09')), array(strtotime('2005-10-15'))),
            array('> 2005-10-10', array(strtotime('2005-10-15')), array(strtotime('2005-10-09'))),
            array('after 2005-10-10', array(strtotime('2005-10-15')), array(strtotime('2005-10-09'))),
            array('since 2005-10-10', array(strtotime('2005-10-15')), array(strtotime('2005-10-09'))),
            array('!= 2005-10-10', array(strtotime('2005-10-11')), array(strtotime('2005-10-10'))),
        );

    }
}
PK��Z�W.�//Ntest/Finder/Symfony/Component/Finder/Tests/Comparator/NumberComparatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Comparator;

use Symfony\Component\Finder\Comparator\NumberComparator;

class NumberComparatorTest extends \PHPUnit_Framework_TestCase
{

    /**
     * @dataProvider getConstructorTestData
     */
    public function testConstructor($successes, $failures)
    {
        foreach ($successes as $s) {
            new NumberComparator($s);
        }

        foreach ($failures as $f) {
            try {
                new NumberComparator($f);
                $this->fail('__construct() throws an \InvalidArgumentException if the test expression is not valid.');
            } catch (\Exception $e) {
                $this->assertInstanceOf('InvalidArgumentException', $e, '__construct() throws an \InvalidArgumentException if the test expression is not valid.');
            }
        }
    }

    /**
     * @dataProvider getTestData
     */
    public function testTest($test, $match, $noMatch)
    {
        $c = new NumberComparator($test);

        foreach ($match as $m) {
            $this->assertTrue($c->test($m), '->test() tests a string against the expression');
        }

        foreach ($noMatch as $m) {
            $this->assertFalse($c->test($m), '->test() tests a string against the expression');
        }
    }

    public function getTestData()
    {
        return array(
            array('< 1000', array('500', '999'), array('1000', '1500')),

            array('< 1K', array('500', '999'), array('1000', '1500')),
            array('<1k', array('500', '999'), array('1000', '1500')),
            array('  < 1 K ', array('500', '999'), array('1000', '1500')),
            array('<= 1K', array('1000'), array('1001')),
            array('> 1K', array('1001'), array('1000')),
            array('>= 1K', array('1000'), array('999')),

            array('< 1KI', array('500', '1023'), array('1024', '1500')),
            array('<= 1KI', array('1024'), array('1025')),
            array('> 1KI', array('1025'), array('1024')),
            array('>= 1KI', array('1024'), array('1023')),

            array('1KI', array('1024'), array('1023', '1025')),
            array('==1KI', array('1024'), array('1023', '1025')),

            array('==1m', array('1000000'), array('999999', '1000001')),
            array('==1mi', array(1024*1024), array(1024*1024-1, 1024*1024+1)),

            array('==1g', array('1000000000'), array('999999999', '1000000001')),
            array('==1gi', array(1024*1024*1024), array(1024*1024*1024-1, 1024*1024*1024+1)),

            array('!= 1000', array('500', '999'), array('1000')),
        );
    }

    public function getConstructorTestData()
    {
        return array(
            array(
                array(
                    '1', '0',
                    '3.5', '33.55', '123.456', '123456.78',
                    '.1', '.123',
                    '.0', '0.0',
                    '1.', '0.', '123.',
                    '==1', '!=1', '<1', '>1', '<=1', '>=1',
                    '==1k', '==1ki', '==1m', '==1mi', '==1g', '==1gi',
                    '1k', '1ki', '1m', '1mi', '1g', '1gi',
                ),
                array(
                    false, null, '',
                    ' ', 'foobar',
                    '=1', '===1',
                    '0 . 1', '123 .45', '234. 567',
                    '..', '.0.', '0.1.2',
                )
            ),
        );
    }

}
PK��Z��Ŗ�Htest/Finder/Symfony/Component/Finder/Tests/Comparator/ComparatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Comparator;

use Symfony\Component\Finder\Comparator\Comparator;

class ComparatorTest extends \PHPUnit_Framework_TestCase
{
    public function testGetSetOperator()
    {
        $comparator = new Comparator();
        try {
            $comparator->setOperator('foo');
            $this->fail('->setOperator() throws an \InvalidArgumentException if the operator is not valid.');
        } catch (\Exception $e) {
            $this->assertInstanceOf('InvalidArgumentException', $e, '->setOperator() throws an \InvalidArgumentException if the operator is not valid.');
        }

        $comparator = new Comparator();
        $comparator->setOperator('>');
        $this->assertEquals('>', $comparator->getOperator(), '->getOperator() returns the current operator');
    }

    public function testGetSetTarget()
    {
        $comparator = new Comparator();
        $comparator->setTarget(8);
        $this->assertEquals(8, $comparator->getTarget(), '->getTarget() returns the target');
    }

    /**
     * @dataProvider getTestData
     */
    public function testTest($operator, $target, $match, $noMatch)
    {
        $c = new Comparator();
        $c->setOperator($operator);
        $c->setTarget($target);

        foreach ($match as $m) {
            $this->assertTrue($c->test($m), '->test() tests a string against the expression');
        }

        foreach ($noMatch as $m) {
            $this->assertFalse($c->test($m), '->test() tests a string against the expression');
        }
    }

    public function getTestData()
    {
        return array(
            array('<', '1000', array('500', '999'), array('1000', '1500')),
        );
    }
}
PK��Z6G��mwmw9test/Finder/Symfony/Component/Finder/Tests/FinderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests;

use Symfony\Component\Finder\Finder;
use Symfony\Component\Finder\Adapter;

class FinderTest extends Iterator\RealIteratorTestCase
{

    public function testCreate()
    {
        $this->assertInstanceOf('Symfony\Component\Finder\Finder', Finder::create());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testDirectories($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->directories());
        $this->assertIterator($this->toAbsolute(array('foo', 'toto')), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $finder->directories();
        $finder->files();
        $finder->directories();
        $this->assertIterator($this->toAbsolute(array('foo', 'toto')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testFiles($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->files());
        $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'test.py', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $finder->files();
        $finder->directories();
        $finder->files();
        $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'test.py', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testDepth($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->depth('< 1'));
        $this->assertIterator($this->toAbsolute(array('foo', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->depth('<= 0'));
        $this->assertIterator($this->toAbsolute(array('foo', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->depth('>= 1'));
        $this->assertIterator($this->toAbsolute(array('foo/bar.tmp')), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $finder->depth('< 1')->depth('>= 1');
        $this->assertIterator(array(), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testName($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->name('*.php'));
        $this->assertIterator($this->toAbsolute(array('test.php')), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $finder->name('test.ph*');
        $finder->name('test.py');
        $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $finder->name('~^test~i');
        $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $finder->name('~\\.php$~i');
        $this->assertIterator($this->toAbsolute(array('test.php')), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $finder->name('test.p{hp,y}');
        $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testNotName($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->notName('*.php'));
        $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $finder->notName('*.php');
        $finder->notName('*.py');
        $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $finder->name('test.ph*');
        $finder->name('test.py');
        $finder->notName('*.php');
        $finder->notName('*.py');
        $this->assertIterator(array(), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $finder->name('test.ph*');
        $finder->name('test.py');
        $finder->notName('*.p{hp,y}');
        $this->assertIterator(array(), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getRegexNameTestData
     *
     * @group regexName
     */
    public function testRegexName($adapter, $regex)
    {
        $finder = $this->buildFinder($adapter);
        $finder->name($regex);
        $this->assertIterator($this->toAbsolute(array('test.py', 'test.php')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testSize($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->files()->size('< 1K')->size('> 500'));
        $this->assertIterator($this->toAbsolute(array('test.php')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testDate($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->files()->date('until last month'));
        $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testExclude($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->exclude('foo'));
        $this->assertIterator($this->toAbsolute(array('test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testIgnoreVCS($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->ignoreVCS(false)->ignoreDotFiles(false));
        $this->assertIterator($this->toAbsolute(array('.git', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $finder->ignoreVCS(false)->ignoreVCS(false)->ignoreDotFiles(false);
        $this->assertIterator($this->toAbsolute(array('.git', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->ignoreVCS(true)->ignoreDotFiles(false));
        $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testIgnoreDotFiles($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->ignoreDotFiles(false)->ignoreVCS(false));
        $this->assertIterator($this->toAbsolute(array('.git', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $finder->ignoreDotFiles(false)->ignoreDotFiles(false)->ignoreVCS(false);
        $this->assertIterator($this->toAbsolute(array('.git', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->ignoreDotFiles(true)->ignoreVCS(false));
        $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testSortByName($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->sortByName());
        $this->assertIterator($this->toAbsolute(array('foo', 'foo bar', 'foo/bar.tmp', 'test.php', 'test.py', 'toto')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testSortByType($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->sortByType());
        $this->assertIterator($this->toAbsolute(array('foo', 'foo bar', 'toto', 'foo/bar.tmp', 'test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testSortByAccessedTime($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->sortByAccessedTime());
        $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'toto', 'test.py', 'foo', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testSortByChangedTime($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->sortByChangedTime());
        $this->assertIterator($this->toAbsolute(array('toto', 'test.py', 'test.php', 'foo/bar.tmp', 'foo', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testSortByModifiedTime($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->sortByModifiedTime());
        $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'toto', 'test.py', 'foo', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testSort($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->sort(function (\SplFileInfo $a, \SplFileInfo $b) { return strcmp($a->getRealpath(), $b->getRealpath()); }));
        $this->assertIterator($this->toAbsolute(array('foo', 'foo bar', 'foo/bar.tmp', 'test.php', 'test.py', 'toto')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testFilter($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->filter(function (\SplFileInfo $f) { return preg_match('/test/', $f) > 0; }));
        $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testFollowLinks($adapter)
    {
        if ('\\' == DIRECTORY_SEPARATOR) {
            return;
        }

        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->followLinks());
        $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testIn($adapter)
    {
        $finder = $this->buildFinder($adapter);
        try {
            $finder->in('foobar');
            $this->fail('->in() throws a \InvalidArgumentException if the directory does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('InvalidArgumentException', $e, '->in() throws a \InvalidArgumentException if the directory does not exist');
        }

        $finder = $this->buildFinder($adapter);
        $iterator = $finder->files()->name('*.php')->depth('< 1')->in(array(self::$tmpDir, __DIR__))->getIterator();

        $this->assertIterator(array(self::$tmpDir.DIRECTORY_SEPARATOR.'test.php', __DIR__.DIRECTORY_SEPARATOR.'FinderTest.php'), $iterator);
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testInWithGlob($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $finder->in(array(__DIR__.'/Fixtures/*/B/C', __DIR__.'/Fixtures/*/*/B/C'))->getIterator();

        $this->assertIterator($this->toAbsoluteFixtures(array('A/B/C/abc.dat', 'copy/A/B/C/abc.dat.copy')), $finder);
    }

    /**
     * @dataProvider getAdaptersTestData
     * @expectedException \InvalidArgumentException
     */
    public function testInWithNonDirectoryGlob($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $finder->in(__DIR__.'/Fixtures/A/a*');
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testGetIterator($adapter)
    {
        $finder = $this->buildFinder($adapter);
        try {
            $finder->getIterator();
            $this->fail('->getIterator() throws a \LogicException if the in() method has not been called');
        } catch (\Exception $e) {
            $this->assertInstanceOf('LogicException', $e, '->getIterator() throws a \LogicException if the in() method has not been called');
        }

        $finder = $this->buildFinder($adapter);
        $dirs = array();
        foreach ($finder->directories()->in(self::$tmpDir) as $dir) {
            $dirs[] = (string) $dir;
        }

        $expected = $this->toAbsolute(array('foo', 'toto'));

        sort($dirs);
        sort($expected);

        $this->assertEquals($expected, $dirs, 'implements the \IteratorAggregate interface');

        $finder = $this->buildFinder($adapter);
        $this->assertEquals(2, iterator_count($finder->directories()->in(self::$tmpDir)), 'implements the \IteratorAggregate interface');

        $finder = $this->buildFinder($adapter);
        $a = iterator_to_array($finder->directories()->in(self::$tmpDir));
        $a = array_values(array_map(function ($a) { return (string) $a; }, $a));
        sort($a);
        $this->assertEquals($expected, $a, 'implements the \IteratorAggregate interface');
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testRelativePath($adapter)
    {
        $finder = $this->buildFinder($adapter)->in(self::$tmpDir);

        $paths = array();

        foreach ($finder as $file) {
            $paths[] = $file->getRelativePath();
        }

        $ref = array("", "", "", "", "foo", "");

        sort($ref);
        sort($paths);

        $this->assertEquals($ref, $paths);
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testRelativePathname($adapter)
    {
        $finder = $this->buildFinder($adapter)->in(self::$tmpDir)->sortByName();

        $paths = array();

        foreach ($finder as $file) {
            $paths[] = $file->getRelativePathname();
        }

        $ref = array("test.php", "toto", "test.py", "foo", "foo".DIRECTORY_SEPARATOR."bar.tmp", "foo bar");

        sort($paths);
        sort($ref);

        $this->assertEquals($ref, $paths);
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testAppendWithAFinder($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $finder->files()->in(self::$tmpDir.DIRECTORY_SEPARATOR.'foo');

        $finder1 = $this->buildFinder($adapter);
        $finder1->directories()->in(self::$tmpDir);

        $finder = $finder->append($finder1);

        $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'toto')), $finder->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testAppendWithAnArray($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $finder->files()->in(self::$tmpDir.DIRECTORY_SEPARATOR.'foo');

        $finder->append($this->toAbsolute(array('foo', 'toto')));

        $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'toto')), $finder->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testAppendReturnsAFinder($adapter)
    {
        $this->assertInstanceOf('Symfony\\Component\\Finder\\Finder', $this->buildFinder($adapter)->append(array()));
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testAppendDoesNotRequireIn($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $finder->in(self::$tmpDir.DIRECTORY_SEPARATOR.'foo');

        $finder1 = Finder::create()->append($finder);

        $this->assertIterator(iterator_to_array($finder->getIterator()), $finder1->getIterator());
    }

    public function testCountDirectories()
    {
        $directory = Finder::create()->directories()->in(self::$tmpDir);
        $i = 0;

        foreach ($directory as $dir) {
            $i++;
        }

        $this->assertCount($i, $directory);
    }

    public function testCountFiles()
    {
        $files = Finder::create()->files()->in(__DIR__.DIRECTORY_SEPARATOR.'Fixtures');
        $i = 0;

        foreach ($files as $file) {
            $i++;
        }

        $this->assertCount($i, $files);
    }

    /**
     * @expectedException \LogicException
     */
    public function testCountWithoutIn()
    {
        $finder = Finder::create()->files();
        count($finder);
    }

    /**
     * @dataProvider getContainsTestData
     * @group grep
     */
    public function testContains($adapter, $matchPatterns, $noMatchPatterns, $expected)
    {
        $finder = $this->buildFinder($adapter);
        $finder->in(__DIR__.DIRECTORY_SEPARATOR.'Fixtures')
            ->name('*.txt')->sortByName()
            ->contains($matchPatterns)
            ->notContains($noMatchPatterns);

        $this->assertIterator($this->toAbsoluteFixtures($expected), $finder);
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testContainsOnDirectory(Adapter\AdapterInterface $adapter)
    {
        $finder = $this->buildFinder($adapter);
        $finder->in(__DIR__)
            ->directories()
            ->name('Fixtures')
            ->contains('abc');
        $this->assertIterator(array(), $finder);
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testNotContainsOnDirectory(Adapter\AdapterInterface $adapter)
    {
        $finder = $this->buildFinder($adapter);
        $finder->in(__DIR__)
            ->directories()
            ->name('Fixtures')
            ->notContains('abc');
        $this->assertIterator(array(), $finder);
    }

    /**
     * Searching in multiple locations involves AppendIterator which does an unnecessary rewind which leaves FilterIterator
     * with inner FilesystemIterator in an invalid state.
     *
     * @see https://bugs.php.net/bug.php?id=49104
     *
     * @dataProvider getAdaptersTestData
     */
    public function testMultipleLocations(Adapter\AdapterInterface $adapter)
    {
        $locations = array(
            self::$tmpDir.'/',
            self::$tmpDir.'/toto/',
        );

        // it is expected that there are test.py test.php in the tmpDir
        $finder = $this->buildFinder($adapter);
        $finder->in($locations)->depth('< 1')->name('test.php');

        $this->assertCount(1, $finder);
    }

    /**
     * Iterator keys must be the file pathname.
     *
     * @dataProvider getAdaptersTestData
     */
    public function testIteratorKeys(Adapter\AdapterInterface $adapter)
    {
        $finder = $this->buildFinder($adapter)->in(self::$tmpDir);
        foreach ($finder as $key => $file) {
            $this->assertEquals($file->getPathname(), $key);
        }
    }

    public function testAdaptersOrdering()
    {
        $finder = Finder::create()
            ->removeAdapters()
            ->addAdapter(new FakeAdapter\NamedAdapter('a'), 0)
            ->addAdapter(new FakeAdapter\NamedAdapter('b'), -50)
            ->addAdapter(new FakeAdapter\NamedAdapter('c'), 50)
            ->addAdapter(new FakeAdapter\NamedAdapter('d'), -25)
            ->addAdapter(new FakeAdapter\NamedAdapter('e'), 25);

        $this->assertEquals(
            array('c', 'e', 'a', 'd', 'b'),
            array_map(function (Adapter\AdapterInterface $adapter) {
                return $adapter->getName();
            }, $finder->getAdapters())
        );
    }

    public function testAdaptersChaining()
    {
        $iterator  = new \ArrayIterator(array());
        $filenames = $this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto'));
        foreach ($filenames as $file) {
            $iterator->append(new \Symfony\Component\Finder\SplFileInfo($file, null, null));
        }

        $finder = Finder::create()
            ->removeAdapters()
            ->addAdapter(new FakeAdapter\UnsupportedAdapter(), 3)
            ->addAdapter(new FakeAdapter\FailingAdapter(), 2)
            ->addAdapter(new FakeAdapter\DummyAdapter($iterator), 1);

        $this->assertIterator($filenames, $finder->in(sys_get_temp_dir())->getIterator());
    }

    public function getAdaptersTestData()
    {
        return array_map(
            function ($adapter) { return array($adapter); },
            $this->getValidAdapters()
        );
    }

    public function getContainsTestData()
    {
        $tests = array(
            array('', '', array()),
            array('foo', 'bar', array()),
            array('', 'foobar', array('dolor.txt', 'ipsum.txt', 'lorem.txt')),
            array('lorem ipsum dolor sit amet', 'foobar', array('lorem.txt')),
            array('sit', 'bar', array('dolor.txt', 'ipsum.txt', 'lorem.txt')),
            array('dolor sit amet', '@^L@m', array('dolor.txt', 'ipsum.txt')),
            array('/^lorem ipsum dolor sit amet$/m', 'foobar', array('lorem.txt')),
            array('lorem', 'foobar', array('lorem.txt')),
            array('', 'lorem', array('dolor.txt', 'ipsum.txt')),
            array('ipsum dolor sit amet', '/^IPSUM/m', array('lorem.txt')),
        );

        return $this->buildTestData($tests);
    }

    public function getRegexNameTestData()
    {
        $tests = array(
            array('~.+\\.p.+~i'),
            array('~t.*s~i'),
        );

        return $this->buildTestData($tests);
    }

    /**
     * @dataProvider getTestPathData
     */
    public function testPath(Adapter\AdapterInterface $adapter, $matchPatterns, $noMatchPatterns, array $expected)
    {
        $finder = $this->buildFinder($adapter);
        $finder->in(__DIR__.DIRECTORY_SEPARATOR.'Fixtures')
            ->path($matchPatterns)
            ->notPath($noMatchPatterns);

        $this->assertIterator($this->toAbsoluteFixtures($expected), $finder);
    }

    public function testAdapterSelection()
    {
        // test that by default, PhpAdapter is selected
        $adapters = Finder::create()->getAdapters();
        $this->assertTrue($adapters[0] instanceof Adapter\PhpAdapter);

        // test another adapter selection
        $adapters = Finder::create()->setAdapter('gnu_find')->getAdapters();
        $this->assertTrue($adapters[0] instanceof Adapter\GnuFindAdapter);

        // test that useBestAdapter method removes selection
        $adapters = Finder::create()->useBestAdapter()->getAdapters();
        $this->assertFalse($adapters[0] instanceof Adapter\PhpAdapter);
    }

    public function getTestPathData()
    {
        $tests = array(
            array('', '', array()),
            array('/^A\/B\/C/', '/C$/',
                array('A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat')
            ),
            array('/^A\/B/', 'foobar',
                array(
                    'A'.DIRECTORY_SEPARATOR.'B',
                    'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C',
                    'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'ab.dat',
                    'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat',
                )
            ),
            array('A/B/C', 'foobar',
                array(
                    'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C',
                    'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat',
                    'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C',
                    'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat.copy',
                )
            ),
            array('A/B', 'foobar',
                array(
                    //dirs
                    'A'.DIRECTORY_SEPARATOR.'B',
                    'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C',
                    'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B',
                    'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C',
                    //files
                    'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'ab.dat',
                    'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat',
                    'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'ab.dat.copy',
                    'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat.copy',
                )
            ),
            array('/^with space\//', 'foobar',
                array(
                    'with space'.DIRECTORY_SEPARATOR.'foo.txt',
                )
            ),
        );

        return $this->buildTestData($tests);
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testAccessDeniedException(Adapter\AdapterInterface $adapter)
    {
        if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
            $this->markTestSkipped('chmod is not supported on Windows');
        }

        $finder = $this->buildFinder($adapter);
        $finder->files()->in(self::$tmpDir);

        // make 'foo' directory non-readable
        chmod(self::$tmpDir.DIRECTORY_SEPARATOR.'foo', 0333);

        try {
            $this->assertIterator($this->toAbsolute(array('foo bar', 'test.php', 'test.py')), $finder->getIterator());
            $this->fail('Finder should throw an exception when opening a non-readable directory.');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\\Component\\Finder\\Exception\\AccessDeniedException', $e);
        }

        // restore original permissions
        chmod(self::$tmpDir.DIRECTORY_SEPARATOR.'foo', 0777);
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testIgnoredAccessDeniedException(Adapter\AdapterInterface $adapter)
    {
        if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
            $this->markTestSkipped('chmod is not supported on Windows');
        }

        $finder = $this->buildFinder($adapter);
        $finder->files()->ignoreUnreadableDirs()->in(self::$tmpDir);

        // make 'foo' directory non-readable
        chmod(self::$tmpDir.DIRECTORY_SEPARATOR.'foo', 0333);

        $this->assertIterator($this->toAbsolute(array('foo bar', 'test.php', 'test.py')), $finder->getIterator());

        // restore original permissions
        chmod(self::$tmpDir.DIRECTORY_SEPARATOR.'foo', 0777);
    }

    private function buildTestData(array $tests)
    {
        $data = array();
        foreach ($this->getValidAdapters() as $adapter) {
            foreach ($tests as $test) {
                $data[] = array_merge(array($adapter), $test);
            }
        }

        return $data;
    }

    private function buildFinder(Adapter\AdapterInterface $adapter)
    {
        return Finder::create()
            ->removeAdapters()
            ->addAdapter($adapter);
    }

    private function getValidAdapters()
    {
        return array_filter(
            array(
                new Adapter\BsdFindAdapter(),
                new Adapter\GnuFindAdapter(),
                new Adapter\PhpAdapter()
            ),
            function (Adapter\AdapterInterface $adapter) {
                return $adapter->isSupported();
            }
        );
    }

   /**
     * Searching in multiple locations with sub directories involves
     * AppendIterator which does an unnecessary rewind which leaves
     * FilterIterator with inner FilesystemIterator in an invalid state.
     *
     * @see https://bugs.php.net/bug.php?id=49104
     */
    public function testMultipleLocationsWithSubDirectories()
    {
        $locations = array(
            __DIR__.'/Fixtures/one',
            self::$tmpDir.DIRECTORY_SEPARATOR.'toto',
        );

        $finder = new Finder();
        $finder->in($locations)->depth('< 10')->name('*.neon');

        $expected = array(
            __DIR__.'/Fixtures/one'.DIRECTORY_SEPARATOR.'b'.DIRECTORY_SEPARATOR.'c.neon',
            __DIR__.'/Fixtures/one'.DIRECTORY_SEPARATOR.'b'.DIRECTORY_SEPARATOR.'d.neon',
        );

        $this->assertIterator($expected, $finder);
        $this->assertIteratorInForeach($expected, $finder);
    }

    public function testNonSeekableStream()
    {
        try {
            $i = Finder::create()->in('ftp://ftp.mozilla.org/')->depth(0)->getIterator();
        } catch (\UnexpectedValueException $e) {
            $this->markTestSkipped(sprintf('Unsupported stream "%s".', 'ftp'));
        }

        $contains = array(
            'ftp://ftp.mozilla.org'.DIRECTORY_SEPARATOR.'README',
            'ftp://ftp.mozilla.org'.DIRECTORY_SEPARATOR.'index.html',
            'ftp://ftp.mozilla.org'.DIRECTORY_SEPARATOR.'pub',
        );

        $this->assertIteratorInForeach($contains, $i);
    }
}
PK��Z+드44Ltest/Finder/Symfony/Component/Finder/Tests/Iterator/RealIteratorTestCase.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

abstract class RealIteratorTestCase extends IteratorTestCase
{

    protected static $tmpDir;
    protected static $files;

    public static function setUpBeforeClass()
    {
        self::$tmpDir = realpath(sys_get_temp_dir()).DIRECTORY_SEPARATOR.'symfony2_finder';

        self::$files = array(
            '.git/',
            '.foo/',
            '.foo/.bar',
            '.foo/bar',
            '.bar',
            'test.py',
            'foo/',
            'foo/bar.tmp',
            'test.php',
            'toto/',
            'foo bar'
        );

        self::$files = self::toAbsolute(self::$files);

        if (is_dir(self::$tmpDir)) {
            self::tearDownAfterClass();
        } else {
            mkdir(self::$tmpDir);
        }

        foreach (self::$files as $file) {
            if (DIRECTORY_SEPARATOR === $file[strlen($file) - 1]) {
                mkdir($file);
            } else {
                touch($file);
            }
        }

        file_put_contents(self::toAbsolute('test.php'), str_repeat(' ', 800));
        file_put_contents(self::toAbsolute('test.py'), str_repeat(' ', 2000));

        touch(self::toAbsolute('foo/bar.tmp'), strtotime('2005-10-15'));
        touch(self::toAbsolute('test.php'), strtotime('2005-10-15'));
    }

    public static function tearDownAfterClass()
    {
        foreach (array_reverse(self::$files) as $file) {
            if (DIRECTORY_SEPARATOR === $file[strlen($file) - 1]) {
                @rmdir($file);
            } else {
                @unlink($file);
            }
        }
    }

    protected static function toAbsolute($files = null)
    {
        /*
         * Without the call to setUpBeforeClass() property can be null.
         */
        if (!self::$tmpDir) {
            self::$tmpDir = realpath(sys_get_temp_dir()).DIRECTORY_SEPARATOR.'symfony2_finder';
        }

        if (is_array($files)) {
            $f = array();
            foreach ($files as $file) {
                $f[] = self::$tmpDir.DIRECTORY_SEPARATOR.str_replace('/', DIRECTORY_SEPARATOR, $file);
            }

            return $f;
        }

        if (is_string($files)) {
            return self::$tmpDir.DIRECTORY_SEPARATOR.str_replace('/', DIRECTORY_SEPARATOR, $files);
        }

        return self::$tmpDir;
    }

    protected static function toAbsoluteFixtures($files)
    {
        $f = array();
        foreach ($files as $file) {
            $f[] = realpath(__DIR__.DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR.$file);
        }

        return $f;
    }

}
PK��Z:@���
�
Mtest/Finder/Symfony/Component/Finder/Tests/Iterator/FilePathsIteratorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

use Symfony\Component\Finder\Iterator\FilePathsIterator;

class FilePathsIteratorTest extends RealIteratorTestCase
{
    /**
     * @dataProvider getSubPathData
     */
    public function testSubPath($baseDir, array $paths, array $subPaths, array $subPathnames)
    {
        $iterator = new FilePathsIterator($paths, $baseDir);

        foreach ($iterator as $index => $file) {
            $this->assertEquals($paths[$index], $file->getPathname());
            $this->assertEquals($subPaths[$index], $iterator->getSubPath());
            $this->assertEquals($subPathnames[$index], $iterator->getSubPathname());
        }
    }

    public function getSubPathData()
    {
        $tmpDir = sys_get_temp_dir().'/symfony2_finder';

        return array(
            array(
                $tmpDir,
                array( // paths
                    $tmpDir.DIRECTORY_SEPARATOR.'.git' => $tmpDir.DIRECTORY_SEPARATOR.'.git',
                    $tmpDir.DIRECTORY_SEPARATOR.'test.py' => $tmpDir.DIRECTORY_SEPARATOR.'test.py',
                    $tmpDir.DIRECTORY_SEPARATOR.'foo' => $tmpDir.DIRECTORY_SEPARATOR.'foo',
                    $tmpDir.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'bar.tmp' => $tmpDir.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'bar.tmp',
                    $tmpDir.DIRECTORY_SEPARATOR.'test.php' => $tmpDir.DIRECTORY_SEPARATOR.'test.php',
                    $tmpDir.DIRECTORY_SEPARATOR.'toto' => $tmpDir.DIRECTORY_SEPARATOR.'toto'
                ),
                array( // subPaths
                    $tmpDir.DIRECTORY_SEPARATOR.'.git' => '',
                    $tmpDir.DIRECTORY_SEPARATOR.'test.py' => '',
                    $tmpDir.DIRECTORY_SEPARATOR.'foo' => '',
                    $tmpDir.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'bar.tmp' => 'foo',
                    $tmpDir.DIRECTORY_SEPARATOR.'test.php' => '',
                    $tmpDir.DIRECTORY_SEPARATOR.'toto' => ''
                ),
                array( // subPathnames
                    $tmpDir.DIRECTORY_SEPARATOR.'.git' => '.git',
                    $tmpDir.DIRECTORY_SEPARATOR.'test.py' => 'test.py',
                    $tmpDir.DIRECTORY_SEPARATOR.'foo' => 'foo',
                    $tmpDir.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'bar.tmp' => 'foo'.DIRECTORY_SEPARATOR.'bar.tmp',
                    $tmpDir.DIRECTORY_SEPARATOR.'test.php' => 'test.php',
                    $tmpDir.DIRECTORY_SEPARATOR.'toto' => 'toto'
                ),
            ),
        );
    }
}
PK��Z�qbe�
�
Utest/Finder/Symfony/Component/Finder/Tests/Iterator/FilecontentFilterIteratorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

use Symfony\Component\Finder\Iterator\FilecontentFilterIterator;

class FilecontentFilterIteratorTest extends IteratorTestCase
{

    public function testAccept()
    {
        $inner = new MockFileListIterator(array('test.txt'));
        $iterator = new FilecontentFilterIterator($inner, array(), array());
        $this->assertIterator(array('test.txt'), $iterator);
    }

    public function testDirectory()
    {
        $inner = new MockFileListIterator(array('directory'));
        $iterator = new FilecontentFilterIterator($inner, array('directory'), array());
        $this->assertIterator(array(), $iterator);
    }

    public function testUnreadableFile()
    {
        $inner = new MockFileListIterator(array('file r-'));
        $iterator = new FilecontentFilterIterator($inner, array('file r-'), array());
        $this->assertIterator(array(), $iterator);
    }

    /**
     * @dataProvider getTestFilterData
     */
    public function testFilter(\Iterator $inner, array $matchPatterns, array $noMatchPatterns, array $resultArray)
    {
        $iterator = new FilecontentFilterIterator($inner, $matchPatterns, $noMatchPatterns);
        $this->assertIterator($resultArray, $iterator);
    }

    public function getTestFilterData()
    {
        $inner = new MockFileListIterator();

        $inner[] = new MockSplFileInfo(array(
            'name'     => 'a.txt',
            'contents' => 'Lorem ipsum...',
            'type'     => 'file',
            'mode'     => 'r+')
        );

        $inner[] = new MockSplFileInfo(array(
            'name'     => 'b.yml',
            'contents' => 'dolor sit...',
            'type'     => 'file',
            'mode'     => 'r+')
        );

        $inner[] = new MockSplFileInfo(array(
            'name'     => 'some/other/dir/third.php',
            'contents' => 'amet...',
            'type'     => 'file',
            'mode'     => 'r+')
        );

        $inner[] = new MockSplFileInfo(array(
            'name'     => 'unreadable-file.txt',
            'contents' => false,
            'type'     => 'file',
            'mode'     => 'r+')
        );

        return array(
            array($inner, array('.'), array(), array('a.txt', 'b.yml', 'some/other/dir/third.php')),
            array($inner, array('ipsum'), array(), array('a.txt')),
            array($inner, array('i', 'amet'), array('Lorem', 'amet'), array('b.yml')),
        );
    }
}
PK��ZYbk�MMRtest/Finder/Symfony/Component/Finder/Tests/Iterator/FileTypeFilterIteratorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

use Symfony\Component\Finder\Iterator\FileTypeFilterIterator;

class FileTypeFilterIteratorTest extends RealIteratorTestCase
{
    /**
     * @dataProvider getAcceptData
     */
    public function testAccept($mode, $expected)
    {
        $inner = new InnerTypeIterator(self::$files);

        $iterator = new FileTypeFilterIterator($inner, $mode);

        $this->assertIterator($expected, $iterator);
    }

    public function getAcceptData()
    {
        $onlyFiles = array(
            'test.py',
            'foo/bar.tmp',
            'test.php',
            '.bar',
            '.foo/.bar',
            '.foo/bar',
            'foo bar',
        );

        $onlyDirectories = array(
            '.git',
            'foo',
            'toto',
            '.foo',
        );

        return array(
            array(FileTypeFilterIterator::ONLY_FILES, $this->toAbsolute($onlyFiles)),
            array(FileTypeFilterIterator::ONLY_DIRECTORIES, $this->toAbsolute($onlyDirectories)),
        );
    }
}

class InnerTypeIterator extends \ArrayIterator
{
   public function current()
    {
        return new \SplFileInfo(parent::current());
    }

    public function isFile()
    {
        return $this->current()->isFile();
    }

    public function isDir()
    {
        return $this->current()->isDir();
    }
}
PK��Z���Ŋ�Vtest/Finder/Symfony/Component/Finder/Tests/Iterator/RecursiveDirectoryIteratorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Finder\Tests\Iterator;

use Symfony\Component\Finder\Iterator\RecursiveDirectoryIterator;

class RecursiveDirectoryIteratorTest extends IteratorTestCase
{
    /**
     * @dataProvider getPaths
     *
     * @param string  $path
     * @param Boolean $seekable
     * @param array   $contains
     * @param string  $message
     */
    public function testRewind($path, $seekable, $contains, $message = null)
    {
        try {
            $i = new RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS);
        } catch (\UnexpectedValueException $e) {
            $this->markTestSkipped(sprintf('Unsupported stream "%s".', $path));
        }

        $i->rewind();

        $this->assertTrue(true, $message);
    }

    /**
     * @dataProvider getPaths
     *
     * @param string  $path
     * @param Boolean $seekable
     * @param array   $contains
     * @param string  $message
     */
    public function testSeek($path, $seekable, $contains, $message = null)
    {
        try {
            $i = new RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS);
        } catch (\UnexpectedValueException $e) {
            $this->markTestSkipped(sprintf('Unsupported stream "%s".', $path));
        }

        $actual = array();

        $i->seek(0);
        $actual[] = $i->getPathname();

        $i->seek(1);
        $actual[] = $i->getPathname();

        $i->seek(2);
        $actual[] = $i->getPathname();

        $this->assertEquals($contains, $actual);
    }

    public function getPaths()
    {
        $data = array();

        // ftp
        $contains = array(
            'ftp://ftp.mozilla.org'.DIRECTORY_SEPARATOR.'README',
            'ftp://ftp.mozilla.org'.DIRECTORY_SEPARATOR.'index.html',
            'ftp://ftp.mozilla.org'.DIRECTORY_SEPARATOR.'pub',
        );
        $data[] = array('ftp://ftp.mozilla.org/', false, $contains);

        return $data;
    }
}
PK��Z4/aaZtest/Finder/Symfony/Component/Finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator;
use Symfony\Component\Finder\Iterator\RecursiveDirectoryIterator;

class ExcludeDirectoryFilterIteratorTest extends RealIteratorTestCase
{
    /**
     * @dataProvider getAcceptData
     */
    public function testAccept($directories, $expected)
    {
        $inner = new \RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->toAbsolute(), \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST);

        $iterator = new ExcludeDirectoryFilterIterator($inner, $directories);

        $this->assertIterator($expected, $iterator);
    }

    public function getAcceptData()
    {
        $foo = array(
            '.bar',
            '.foo',
            '.foo/.bar',
            '.foo/bar',
            '.git',
            'test.py',
            'test.php',
            'toto',
            'foo bar'
        );

        $fo = array(
            '.bar',
            '.foo',
            '.foo/.bar',
            '.foo/bar',
            '.git',
            'test.py',
            'foo',
            'foo/bar.tmp',
            'test.php',
            'toto',
            'foo bar'
        );

        return array(
            array(array('foo'), $this->toAbsolute($foo)),
            array(array('fo'), $this->toAbsolute($fo)),
        );
    }

}
PK��Z��nI��Ntest/Finder/Symfony/Component/Finder/Tests/Iterator/PathFilterIteratorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

use Symfony\Component\Finder\Iterator\PathFilterIterator;

class PathFilterIteratorTest extends IteratorTestCase
{

    /**
     * @dataProvider getTestFilterData
     */
    public function testFilter(\Iterator $inner, array $matchPatterns, array $noMatchPatterns, array $resultArray)
    {
        $iterator = new PathFilterIterator($inner, $matchPatterns, $noMatchPatterns);
        $this->assertIterator($resultArray, $iterator);
    }

    public function getTestFilterData()
    {
        $inner = new MockFileListIterator();

        //PATH:   A/B/C/abc.dat
        $inner[] = new MockSplFileInfo(array(
            'name'              => 'abc.dat',
            'relativePathname'  => 'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat',
        ));

        //PATH:   A/B/ab.dat
        $inner[] = new MockSplFileInfo(array(
            'name'              => 'ab.dat',
            'relativePathname'  => 'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'ab.dat',
        ));

        //PATH:   A/a.dat
        $inner[] = new MockSplFileInfo(array(
            'name'              => 'a.dat',
            'relativePathname'  => 'A'.DIRECTORY_SEPARATOR.'a.dat',
        ));

        //PATH:   copy/A/B/C/abc.dat.copy
        $inner[] = new MockSplFileInfo(array(
            'name'              => 'abc.dat.copy',
            'relativePathname'  => 'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat',
        ));

        //PATH:   copy/A/B/ab.dat.copy
        $inner[] = new MockSplFileInfo(array(
            'name'              => 'ab.dat.copy',
            'relativePathname'  => 'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'ab.dat',
        ));

        //PATH:   copy/A/a.dat.copy
        $inner[] = new MockSplFileInfo(array(
            'name'              => 'a.dat.copy',
            'relativePathname'  => 'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'a.dat',
        ));

        return array(
            array($inner, array('/^A/'),       array(), array('abc.dat', 'ab.dat', 'a.dat')),
            array($inner, array('/^A\/B/'),    array(), array('abc.dat', 'ab.dat')),
            array($inner, array('/^A\/B\/C/'), array(), array('abc.dat')),
            array($inner, array('/A\/B\/C/'),  array(), array('abc.dat', 'abc.dat.copy')),

            array($inner, array('A'),      array(), array('abc.dat', 'ab.dat', 'a.dat', 'abc.dat.copy', 'ab.dat.copy', 'a.dat.copy')),
            array($inner, array('A/B'),    array(), array('abc.dat', 'ab.dat', 'abc.dat.copy', 'ab.dat.copy')),
            array($inner, array('A/B/C'),  array(), array('abc.dat', 'abc.dat.copy')),

            array($inner, array('copy/A'),      array(), array('abc.dat.copy', 'ab.dat.copy', 'a.dat.copy')),
            array($inner, array('copy/A/B'),    array(), array('abc.dat.copy', 'ab.dat.copy')),
            array($inner, array('copy/A/B/C'),  array(), array('abc.dat.copy')),

        );
    }

}
PK��Z��++Vtest/Finder/Symfony/Component/Finder/Tests/Iterator/MultiplePcreFilterIteratorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

use Symfony\Component\Finder\Iterator\MultiplePcreFilterIterator;

class MultiplePcreFilterIteratorTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getIsRegexFixtures
     */
    public function testIsRegex($string, $isRegex, $message)
    {
        $testIterator = new TestMultiplePcreFilterIterator();
        $this->assertEquals($isRegex, $testIterator->isRegex($string), $message);
    }

    public function getIsRegexFixtures()
    {
        return array(
            array('foo', false, 'string'),
            array(' foo ', false, '" " is not a valid delimiter'),
            array('\\foo\\', false, '"\\" is not a valid delimiter'),
            array('afooa', false, '"a" is not a valid delimiter'),
            array('//', false, 'the pattern should contain at least 1 character'),
            array('/a/', true, 'valid regex'),
            array('/foo/', true, 'valid regex'),
            array('/foo/i', true, 'valid regex with a single modifier'),
            array('/foo/imsxu', true, 'valid regex with multiple modifiers'),
            array('#foo#', true, '"#" is a valid delimiter'),
            array('{foo}', true, '"{,}" is a valid delimiter pair'),
            array('*foo.*', false, '"*" is not considered as a valid delimiter'),
            array('?foo.?', false, '"?" is not considered as a valid delimiter'),
        );
    }
}

class TestMultiplePcreFilterIterator extends MultiplePcreFilterIterator
{
    public function __construct()
    {
    }

    public function accept()
    {
        throw new \BadFunctionCallException('Not implemented');
    }

    public function isRegex($str)
    {
        return parent::isRegex($str);
    }

    public function toRegex($str)
    {
        throw new \BadFunctionCallException('Not implemented');
    }
}
PK��Z�7Wa	a	Ltest/Finder/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

use Symfony\Component\Finder\Iterator\SortableIterator;

class SortableIteratorTest extends RealIteratorTestCase
{
    public function testConstructor()
    {
        try {
            new SortableIterator(new Iterator(array()), 'foobar');
            $this->fail('__construct() throws an \InvalidArgumentException exception if the mode is not valid');
        } catch (\Exception $e) {
            $this->assertInstanceOf('InvalidArgumentException', $e, '__construct() throws an \InvalidArgumentException exception if the mode is not valid');
        }
    }

    /**
     * @dataProvider getAcceptData
     */
    public function testAccept($mode, $expected)
    {
        $inner = new Iterator(self::$files);

        $iterator = new SortableIterator($inner, $mode);

        $this->assertOrderedIterator($expected, $iterator);
    }

    public function getAcceptData()
    {

        $sortByName = array(
            '.bar',
            '.foo',
            '.foo/.bar',
            '.foo/bar',
            '.git',
            'foo',
            'foo bar',
            'foo/bar.tmp',
            'test.php',
            'test.py',
            'toto',
        );

        $sortByType = array(
            '.foo',
            '.git',
            'foo',
            'toto',
            '.bar',
            '.foo/.bar',
            '.foo/bar',
            'foo bar',
            'foo/bar.tmp',
            'test.php',
            'test.py',
        );

        $customComparison = array(
            '.bar',
            '.foo',
            '.foo/.bar',
            '.foo/bar',
            '.git',
            'foo',
            'foo bar',
            'foo/bar.tmp',
            'test.php',
            'test.py',
            'toto',
        );

        return array(
            array(SortableIterator::SORT_BY_NAME, $this->toAbsolute($sortByName)),
            array(SortableIterator::SORT_BY_TYPE, $this->toAbsolute($sortByType)),
            array(function (\SplFileInfo $a, \SplFileInfo $b) { return strcmp($a->getRealpath(), $b->getRealpath()); }, $this->toAbsolute($customComparison)),
        );
    }
}
PK��Z�7���Rtest/Finder/Symfony/Component/Finder/Tests/Iterator/FilenameFilterIteratorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

use Symfony\Component\Finder\Iterator\FilenameFilterIterator;

class FilenameFilterIteratorTest extends IteratorTestCase
{
    /**
     * @dataProvider getAcceptData
     */
    public function testAccept($matchPatterns, $noMatchPatterns, $expected)
    {
        $inner = new InnerNameIterator(array('test.php', 'test.py', 'foo.php'));

        $iterator = new FilenameFilterIterator($inner, $matchPatterns, $noMatchPatterns);

        $this->assertIterator($expected, $iterator);
    }

    public function getAcceptData()
    {
        return array(
            array(array('test.*'), array(), array('test.php', 'test.py')),
            array(array(), array('test.*'), array('foo.php')),
            array(array('*.php'), array('test.*'), array('foo.php')),
            array(array('*.php', '*.py'), array('foo.*'), array('test.php', 'test.py')),
            array(array('/\.php$/'), array(), array('test.php', 'foo.php')),
            array(array(), array('/\.php$/'), array('test.py')),
        );
    }
}

class InnerNameIterator extends \ArrayIterator
{
    public function current()
    {
        return new \SplFileInfo(parent::current());
    }

    public function getFilename()
    {
        return parent::current();
    }
}
PK��Z߫����Ptest/Finder/Symfony/Component/Finder/Tests/Iterator/CustomFilterIteratorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

use Symfony\Component\Finder\Iterator\CustomFilterIterator;

class CustomFilterIteratorTest extends IteratorTestCase
{
    /**
     * @expectedException \InvalidArgumentException
     */
    public function testWithInvalidFilter()
    {
        new CustomFilterIterator(new Iterator(), array('foo'));
    }

    /**
     * @dataProvider getAcceptData
     */
    public function testAccept($filters, $expected)
    {
        $inner = new Iterator(array('test.php', 'test.py', 'foo.php'));

        $iterator = new CustomFilterIterator($inner, $filters);

        $this->assertIterator($expected, $iterator);
    }

    public function getAcceptData()
    {
        return array(
            array(array(function (\SplFileInfo $fileinfo) { return false; }), array()),
            array(array(function (\SplFileInfo $fileinfo) { return preg_match('/^test/', $fileinfo) > 0; }), array('test.php', 'test.py')),
            array(array('is_dir'), array()),
        );
    }
}
PK��Z��o�
�
Gtest/Finder/Symfony/Component/Finder/Tests/Iterator/MockSplFileInfo.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

class MockSplFileInfo extends \SplFileInfo
{
    const   TYPE_DIRECTORY = 1;
    const   TYPE_FILE      = 2;
    const   TYPE_UNKNOWN   = 3;

    private $contents         = null;
    private $mode             = null;
    private $type             = null;
    private $relativePath     = null;
    private $relativePathname = null;

    public function __construct($param)
    {
        if (is_string($param)) {
            parent::__construct($param);
        } elseif (is_array($param)) {
            $defaults = array(
              'name'             => 'file.txt',
              'contents'         => null,
              'mode'             => null,
              'type'             => null,
              'relativePath'     => null,
              'relativePathname' => null,
            );
            $defaults = array_merge($defaults, $param);
            parent::__construct($defaults['name']);
            $this->setContents($defaults['contents']);
            $this->setMode($defaults['mode']);
            $this->setType($defaults['type']);
            $this->setRelativePath($defaults['relativePath']);
            $this->setRelativePathname($defaults['relativePathname']);
        } else {
            throw new \RuntimeException(sprintf('Incorrect parameter "%s"', $param));
        }
    }

    public function isFile()
    {
        if ($this->type === null) {
            return preg_match('/file/', $this->getFilename());
        };

        return self::TYPE_FILE === $this->type;
    }

    public function isDir()
    {
        if ($this->type === null) {
            return preg_match('/directory/', $this->getFilename());
        }

        return self::TYPE_DIRECTORY === $this->type;
    }

    public function isReadable()
    {
        if ($this->mode === null) {
            return preg_match('/r\+/', $this->getFilename());
        }

        return preg_match('/r\+/', $this->mode);
    }

    public function getContents()
    {
        return $this->contents;
    }

    public function setContents($contents)
    {
        $this->contents = $contents;
    }

    public function setMode($mode)
    {
        $this->mode = $mode;
    }

    public function setType($type)
    {
        if (is_string($type)) {
            switch ($type) {
                case 'directory':
                    $this->type = self::TYPE_DIRECTORY;
                case 'd':
                    $this->type = self::TYPE_DIRECTORY;
                    break;
                case 'file':
                    $this->type = self::TYPE_FILE;
                case 'f':
                    $this->type = self::TYPE_FILE;
                    break;
                default:
                    $this->type = self::TYPE_UNKNOWN;
            }
        } else {
            $this->type = $type;
        }
    }

    public function setRelativePath($relativePath)
    {
        $this->relativePath = $relativePath;
    }

    public function setRelativePathname($relativePathname)
    {
        $this->relativePathname = $relativePathname;
    }

    public function getRelativePath()
    {
        return $this->relativePath;
    }

    public function getRelativePathname()
    {
        return $this->relativePathname;
    }
}
PK��ZZo�*))Ttest/Finder/Symfony/Component/Finder/Tests/Iterator/DepthRangeFilterIteratorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

use Symfony\Component\Finder\Iterator\DepthRangeFilterIterator;

class DepthRangeFilterIteratorTest extends RealIteratorTestCase
{
    /**
     * @dataProvider getAcceptData
     */
    public function testAccept($minDepth, $maxDepth, $expected)
    {
        $inner = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->toAbsolute(), \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST);

        $iterator = new DepthRangeFilterIterator($inner, $minDepth, $maxDepth);

        $actual = array_keys(iterator_to_array($iterator));
        sort($expected);
        sort($actual);
        $this->assertEquals($expected, $actual);
    }

    public function getAcceptData()
    {
        $lessThan1 = array(
            '.git',
            'test.py',
            'foo',
            'test.php',
            'toto',
            '.foo',
            '.bar',
            'foo bar',
        );

        $lessThanOrEqualTo1 = array(
            '.git',
            'test.py',
            'foo',
            'foo/bar.tmp',
            'test.php',
            'toto',
            '.foo',
            '.foo/.bar',
            '.bar',
            'foo bar',
            '.foo/bar',
        );

        $graterThanOrEqualTo1 = array(
            'foo/bar.tmp',
            '.foo/.bar',
            '.foo/bar',
        );

        $equalTo1 = array(
            'foo/bar.tmp',
            '.foo/.bar',
            '.foo/bar',
        );

        return array(
            array(0, 0, $this->toAbsolute($lessThan1)),
            array(0, 1, $this->toAbsolute($lessThanOrEqualTo1)),
            array(2, PHP_INT_MAX, array()),
            array(1, PHP_INT_MAX, $this->toAbsolute($graterThanOrEqualTo1)),
            array(1, 1, $this->toAbsolute($equalTo1)),
        );
    }

}
PK��Z�S�@test/Finder/Symfony/Component/Finder/Tests/Iterator/Iterator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

class Iterator implements \Iterator
{
    protected $values = array();

    public function __construct(array $values = array())
    {
        foreach ($values as $value) {
            $this->attach(new \SplFileInfo($value));
        }
        $this->rewind();
    }

    public function attach(\SplFileInfo $fileinfo)
    {
        $this->values[] = $fileinfo;
    }

    public function rewind()
    {
        reset($this->values);
    }

    public function valid()
    {
        return false !== $this->current();
    }

    public function next()
    {
        next($this->values);
    }

    public function current()
    {
        return current($this->values);
    }

    public function key()
    {
        return key($this->values);
    }
}
PK��Z���FStest/Finder/Symfony/Component/Finder/Tests/Iterator/SizeRangeFilterIteratorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

use Symfony\Component\Finder\Iterator\SizeRangeFilterIterator;
use Symfony\Component\Finder\Comparator\NumberComparator;

class SizeRangeFilterIteratorTest extends RealIteratorTestCase
{
    /**
     * @dataProvider getAcceptData
     */
    public function testAccept($size, $expected)
    {
        $inner = new InnerSizeIterator(self::$files);

        $iterator = new SizeRangeFilterIterator($inner, $size);

        $this->assertIterator($expected, $iterator);
    }

    public function getAcceptData()
    {
        $lessThan1KGreaterThan05K = array(
            '.foo',
            '.git',
            'foo',
            'test.php',
            'toto',
        );

        return array(
            array(array(new NumberComparator('< 1K'), new NumberComparator('> 0.5K')), $this->toAbsolute($lessThan1KGreaterThan05K)),
        );
    }
}

class InnerSizeIterator extends \ArrayIterator
{
   public function current()
    {
        return new \SplFileInfo(parent::current());
    }

    public function getFilename()
    {
        return parent::current();
    }

    public function isFile()
    {
        return $this->current()->isFile();
    }

    public function getSize()
    {
        return $this->current()->getSize();
    }
}
PK��Z-���66Jtest/Finder/Symfony/Component/Finder/Tests/Iterator/FilterIteratorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

/**
 * @author Alex Bogomazov
 */
class FilterIteratorTest extends RealIteratorTestCase
{
    public function testFilterFilesystemIterators()
    {
        $i = new \FilesystemIterator($this->toAbsolute());

        // it is expected that there are test.py test.php in the tmpDir
        $i = $this->getMockForAbstractClass('Symfony\Component\Finder\Iterator\FilterIterator', array($i));
        $i->expects($this->any())
            ->method('accept')
            ->will($this->returnCallback(function () use ($i) {
                return (bool) preg_match('/\.php/', (string) $i->current());
            })
        );

        $c = 0;
        foreach ($i as $item) {
            $c++;
        }

        $this->assertEquals(1, $c);

        $i->rewind();

        $c = 0;
        foreach ($i as $item) {
            $c++;
        }

        // This would fail with \FilterIterator but works with Symfony\Component\Finder\Iterator\FilterIterator
        // see https://bugs.php.net/bug.php?id=49104
        $this->assertEquals(1, $c);
    }
}
PK��Z{�)\o	o	Htest/Finder/Symfony/Component/Finder/Tests/Iterator/IteratorTestCase.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

abstract class IteratorTestCase extends \PHPUnit_Framework_TestCase
{
    protected function assertIterator($expected, \Traversable $iterator)
    {
        // set iterator_to_array $use_key to false to avoid values merge
        // this made FinderTest::testAppendWithAnArray() failed with GnuFinderAdapter
        $values = array_map(function (\SplFileInfo $fileinfo) { return str_replace('/', DIRECTORY_SEPARATOR, $fileinfo->getPathname()); }, iterator_to_array($iterator, false));

        $expected = array_map(function ($path) { return str_replace('/', DIRECTORY_SEPARATOR, $path); }, $expected);

        sort($values);
        sort($expected);

        $this->assertEquals($expected, array_values($values));
    }

    protected function assertOrderedIterator($expected, \Traversable $iterator)
    {
        $values = array_map(function (\SplFileInfo $fileinfo) { return $fileinfo->getPathname(); }, iterator_to_array($iterator));

        $this->assertEquals($expected, array_values($values));
    }

    /**
     * Same as IteratorTestCase::assertIterator with foreach usage
     *
     * @param array $expected
     * @param \Traversable $iterator
     */
    protected function assertIteratorInForeach($expected, \Traversable $iterator)
    {
        $values = array();
        foreach ($iterator as $file) {
            $this->assertInstanceOf('Symfony\\Component\\Finder\\SplFileInfo', $file);
            $values[] = $file->getPathname();
        }

        sort($values);
        sort($expected);

        $this->assertEquals($expected, array_values($values));
    }

    /**
     * Same as IteratorTestCase::assertOrderedIterator with foreach usage
     *
     * @param array $expected
     * @param \Traversable $iterator
     */
    protected function assertOrderedIteratorInForeach($expected, \Traversable $iterator)
    {
        $values = array();
        foreach ($iterator as $file) {
            $this->assertInstanceOf('Symfony\\Component\\Finder\\SplFileInfo', $file);
            $values[] = $file->getPathname();
        }

        $this->assertEquals($expected, array_values($values));
    }
}
PK��Z�[+((Ltest/Finder/Symfony/Component/Finder/Tests/Iterator/MockFileListIterator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

class MockFileListIterator extends \ArrayIterator
{
    public function __construct(array $filesArray = array())
    {
        $files = array_map(function ($file) { return new MockSplFileInfo($file); }, $filesArray);
        parent::__construct($files);
    }
}
PK��Z(��g==Stest/Finder/Symfony/Component/Finder/Tests/Iterator/DateRangeFilterIteratorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

use Symfony\Component\Finder\Iterator\DateRangeFilterIterator;
use Symfony\Component\Finder\Comparator\DateComparator;

class DateRangeFilterIteratorTest extends RealIteratorTestCase
{
    /**
     * @dataProvider getAcceptData
     */
    public function testAccept($size, $expected)
    {
        $inner = new Iterator(self::$files);

        $iterator = new DateRangeFilterIterator($inner, $size);

        $this->assertIterator($expected, $iterator);
    }

    public function getAcceptData()
    {
        $since20YearsAgo = array(
            '.git',
            'test.py',
            'foo',
            'foo/bar.tmp',
            'test.php',
            'toto',
            '.bar',
            '.foo',
            '.foo/.bar',
            'foo bar',
            '.foo/bar',
        );

        $since2MonthsAgo = array(
            '.git',
            'test.py',
            'foo',
            'toto',
            '.bar',
            '.foo',
            '.foo/.bar',
            'foo bar',
            '.foo/bar',
        );

        $untilLastMonth = array(
            '.git',
            'foo',
            'foo/bar.tmp',
            'test.php',
            'toto',
            '.foo',
        );

        return array(
            array(array(new DateComparator('since 20 years ago')), $this->toAbsolute($since20YearsAgo)),
            array(array(new DateComparator('since 2 months ago')), $this->toAbsolute($since2MonthsAgo)),
            array(array(new DateComparator('until last month')), $this->toAbsolute($untilLastMonth)),
        );
    }
}
PK��Z�|ߐ�Htest/Finder/Symfony/Component/Finder/Tests/Expression/ExpressionTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Expression;

use Symfony\Component\Finder\Expression\Expression;

class ExpressionTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getTypeGuesserData
     */
    public function testTypeGuesser($expr, $type)
    {
        $this->assertEquals($type, Expression::create($expr)->getType());
    }

    /**
     * @dataProvider getCaseSensitiveData
     */
    public function testCaseSensitive($expr, $isCaseSensitive)
    {
        $this->assertEquals($isCaseSensitive, Expression::create($expr)->isCaseSensitive());
    }

    /**
     * @dataProvider getRegexRenderingData
     */
    public function testRegexRendering($expr, $body)
    {
        $this->assertEquals($body, Expression::create($expr)->renderPattern());
    }

    public function getTypeGuesserData()
    {
        return array(
            array('{foo}', Expression::TYPE_REGEX),
            array('/foo/', Expression::TYPE_REGEX),
            array('foo',   Expression::TYPE_GLOB),
            array('foo*',  Expression::TYPE_GLOB),
        );
    }

    public function getCaseSensitiveData()
    {
        return array(
            array('{foo}m', true),
            array('/foo/i', false),
            array('foo*',   true),
        );
    }

    public function getRegexRenderingData()
    {
        return array(
            array('{foo}m', 'foo'),
            array('/foo/i', 'foo'),
        );
    }
}
PK��Z�9]��Ctest/Finder/Symfony/Component/Finder/Tests/Expression/RegexTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Expression;

use Symfony\Component\Finder\Expression\Expression;

class RegexTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getHasFlagsData
     */
    public function testHasFlags($regex, $start, $end)
    {
        $expr = new Expression($regex);

        $this->assertEquals($start, $expr->getRegex()->hasStartFlag());
        $this->assertEquals($end,   $expr->getRegex()->hasEndFlag());
    }

    /**
     * @dataProvider getHasJokersData
     */
    public function testHasJokers($regex, $start, $end)
    {
        $expr = new Expression($regex);

        $this->assertEquals($start, $expr->getRegex()->hasStartJoker());
        $this->assertEquals($end,   $expr->getRegex()->hasEndJoker());
    }

    /**
     * @dataProvider getSetFlagsData
     */
    public function testSetFlags($regex, $start, $end, $expected)
    {
        $expr = new Expression($regex);
        $expr->getRegex()->setStartFlag($start)->setEndFlag($end);

        $this->assertEquals($expected, $expr->render());
    }

    /**
     * @dataProvider getSetJokersData
     */
    public function testSetJokers($regex, $start, $end, $expected)
    {
        $expr = new Expression($regex);
        $expr->getRegex()->setStartJoker($start)->setEndJoker($end);

        $this->assertEquals($expected, $expr->render());
    }

    public function testOptions()
    {
        $expr = new Expression('~abc~is');
        $expr->getRegex()->removeOption('i')->addOption('m');

        $this->assertEquals('~abc~sm', $expr->render());
    }

    public function testMixFlagsAndJokers()
    {
        $expr = new Expression('~^.*abc.*$~is');

        $expr->getRegex()->setStartFlag(false)->setEndFlag(false)->setStartJoker(false)->setEndJoker(false);
        $this->assertEquals('~abc~is', $expr->render());

        $expr->getRegex()->setStartFlag(true)->setEndFlag(true)->setStartJoker(true)->setEndJoker(true);
        $this->assertEquals('~^.*abc.*$~is', $expr->render());
    }

    /**
     * @dataProvider getReplaceJokersTestData
     */
    public function testReplaceJokers($regex, $expected)
    {
        $expr = new Expression($regex);
        $expr = $expr->getRegex()->replaceJokers('@');

        $this->assertEquals($expected, $expr->renderPattern());
    }

    public function getHasFlagsData()
    {
        return array(
            array('~^abc~', true, false),
            array('~abc$~', false, true),
            array('~abc~', false, false),
            array('~^abc$~', true, true),
            array('~^abc\\$~', true, false),
        );
    }

    public function getHasJokersData()
    {
        return array(
            array('~.*abc~', true, false),
            array('~abc.*~', false, true),
            array('~abc~', false, false),
            array('~.*abc.*~', true, true),
            array('~.*abc\\.*~', true, false),
        );
    }

    public function getSetFlagsData()
    {
        return array(
            array('~abc~', true, false, '~^abc~'),
            array('~abc~', false, true, '~abc$~'),
            array('~abc~', false, false, '~abc~'),
            array('~abc~', true, true, '~^abc$~'),
        );
    }

    public function getSetJokersData()
    {
        return array(
            array('~abc~', true, false, '~.*abc~'),
            array('~abc~', false, true, '~abc.*~'),
            array('~abc~', false, false, '~abc~'),
            array('~abc~', true, true, '~.*abc.*~'),
        );
    }

    public function getReplaceJokersTestData()
    {
        return array(
            array('~.abc~', '@abc'),
            array('~\\.abc~', '\\.abc'),
            array('~\\\\.abc~', '\\\\@abc'),
            array('~\\\\\\.abc~', '\\\\\\.abc'),
        );
    }
}
PK��Z7u��ttBtest/Finder/Symfony/Component/Finder/Tests/Expression/GlobTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Expression;

use Symfony\Component\Finder\Expression\Expression;

class GlobTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getToRegexData
     */
    public function testGlobToRegex($glob, $match, $noMatch)
    {
        foreach ($match as $m) {
            $this->assertRegExp(Expression::create($glob)->getRegex()->render(), $m, '::toRegex() converts a glob to a regexp');
        }

        foreach ($noMatch as $m) {
            $this->assertNotRegExp(Expression::create($glob)->getRegex()->render(), $m, '::toRegex() converts a glob to a regexp');
        }
    }

    public function getToRegexData()
    {
        return array(
            array('', array(''), array('f', '/')),
            array('*', array('foo'), array('foo/', '/foo')),
            array('foo.*', array('foo.php', 'foo.a', 'foo.'), array('fooo.php', 'foo.php/foo')),
            array('fo?', array('foo', 'fot'), array('fooo', 'ffoo', 'fo/')),
            array('fo{o,t}', array('foo', 'fot'), array('fob', 'fo/')),
            array('foo(bar|foo)', array('foo(bar|foo)'), array('foobar', 'foofoo')),
            array('foo,bar', array('foo,bar'), array('foo', 'bar')),
            array('fo{o,\\,}', array('foo', 'fo,'), array()),
            array('fo{o,\\\\}', array('foo', 'fo\\'), array()),
            array('/foo', array('/foo'), array('foo')),
        );
    }
}
PK��Z`�2��Gtest/Finder/Symfony/Component/Finder/Tests/FakeAdapter/NamedAdapter.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\FakeAdapter;

use Symfony\Component\Finder\Adapter\AbstractAdapter;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class NamedAdapter extends AbstractAdapter
{
    /**
     * @var string
     */
    private $name;

    /**
     * @param string $name
     */
    public function __construct($name)
    {
        $this->name = $name;
    }

    /**
     * {@inheritdoc}
     */
    public function searchInDirectory($dir)
    {
        return new \ArrayIterator(array());
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * {@inheritdoc}
     */
    protected function canBeUsed()
    {
        return true;
    }
}
PK��ZI����Gtest/Finder/Symfony/Component/Finder/Tests/FakeAdapter/DummyAdapter.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\FakeAdapter;

use Symfony\Component\Finder\Adapter\AbstractAdapter;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class DummyAdapter extends AbstractAdapter
{
    /**
     * @var \Iterator
     */
    private $iterator;

    /**
     * @param \Iterator $iterator
     */
    public function __construct(\Iterator $iterator)
    {
        $this->iterator = $iterator;
    }

    /**
     * {@inheritdoc}
     */
    public function searchInDirectory($dir)
    {
        return $this->iterator;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'yes';
    }

    /**
     * {@inheritdoc}
     */
    protected function canBeUsed()
    {
        return true;
    }
}
PK��Z/��00Mtest/Finder/Symfony/Component/Finder/Tests/FakeAdapter/UnsupportedAdapter.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\FakeAdapter;

use Symfony\Component\Finder\Adapter\AbstractAdapter;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class UnsupportedAdapter extends AbstractAdapter
{
    /**
     * {@inheritdoc}
     */
    public function searchInDirectory($dir)
    {
        return new \ArrayIterator(array());
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'unsupported';
    }

    /**
     * {@inheritdoc}
     */
    protected function canBeUsed()
    {
        return false;
    }
}
PK��Z��mmItest/Finder/Symfony/Component/Finder/Tests/FakeAdapter/FailingAdapter.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\FakeAdapter;

use Symfony\Component\Finder\Adapter\AbstractAdapter;
use Symfony\Component\Finder\Exception\AdapterFailureException;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class FailingAdapter extends AbstractAdapter
{
    /**
     * {@inheritdoc}
     */
    public function searchInDirectory($dir)
    {
        throw new AdapterFailureException($this);
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'failing';
    }

    /**
     * {@inheritdoc}
     */
    protected function canBeUsed()
    {
        return true;
    }
}
PK��Z���555test/Finder/Symfony/Component/Finder/phpunit.xml.distnu�[���<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony Finder Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./Tests</directory>
                <directory>./vendor</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
PK��Z9���Ktest/TwigBridge/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Tests\Translation;

use Symfony\Bridge\Twig\Extension\TranslationExtension;
use Symfony\Bridge\Twig\Translation\TwigExtractor;
use Symfony\Component\Translation\MessageCatalogue;

class TwigExtractorTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getExtractData
     */
    public function testExtract($template, $messages)
    {
        $loader = new \Twig_Loader_Array(array());
        $twig = new \Twig_Environment($loader, array(
            'strict_variables' => true,
            'debug' => true,
            'cache' => false,
            'autoescape' => false,
        ));
        $twig->addExtension(new TranslationExtension($this->getMock('Symfony\Component\Translation\TranslatorInterface')));

        $extractor = new TwigExtractor($twig);
        $extractor->setPrefix('prefix');
        $catalogue = new MessageCatalogue('en');

        $m = new \ReflectionMethod($extractor, 'extractTemplate');
        $m->setAccessible(true);
        $m->invoke($extractor, $template, $catalogue);

        foreach ($messages as $key => $domain) {
            $this->assertTrue($catalogue->has($key, $domain));
            $this->assertEquals('prefix'.$key, $catalogue->get($key, $domain));
        }
    }

    public function getExtractData()
    {
        return array(
            array('{{ "new key" | trans() }}', array('new key' => 'messages')),
            array('{{ "new key" | trans() | upper }}', array('new key' => 'messages')),
            array('{{ "new key" | trans({}, "domain") }}', array('new key' => 'domain')),
            array('{{ "new key" | transchoice(1) }}', array('new key' => 'messages')),
            array('{{ "new key" | transchoice(1) | upper }}', array('new key' => 'messages')),
            array('{{ "new key" | transchoice(1, {}, "domain") }}', array('new key' => 'domain')),
            array('{% trans %}new key{% endtrans %}', array('new key' => 'messages')),
            array('{% trans %}  new key  {% endtrans %}', array('new key' => 'messages')),
            array('{% trans from "domain" %}new key{% endtrans %}', array('new key' => 'domain')),
            array('{% set foo = "new key" | trans %}', array('new key' => 'messages')),
            array('{{ 1 ? "new key" | trans : "another key" | trans }}', array('new key' => 'messages', 'another key' => 'messages')),

            // make sure 'trans_default_domain' tag is supported
            array('{% trans_default_domain "domain" %}{{ "new key"|trans }}', array('new key' => 'domain')),
            array('{% trans_default_domain "domain" %}{{ "new key"|transchoice }}', array('new key' => 'domain')),
            array('{% trans_default_domain "domain" %}{% trans %}new key{% endtrans %}', array('new key' => 'domain')),

            // make sure this works with twig's named arguments
            array('{{ "new key" | trans(domain="domain") }}', array('new key' => 'domain')),
            array('{{ "new key" | transchoice(domain="domain", count=1) }}', array('new key' => 'domain')),
        );
    }
}
PK��Z�O#�''Otest/TwigBridge/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Tests\Node;

use Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode;

class SearchAndRenderBlockNodeTest extends \PHPUnit_Framework_TestCase
{
    public function testCompileWidget()
    {
        $arguments = new \Twig_Node(array(
            new \Twig_Node_Expression_Name('form', 0),
        ));

        $node = new SearchAndRenderBlockNode('form_widget', $arguments, 0);

        $compiler = new \Twig_Compiler(new \Twig_Environment());

        $this->assertEquals(
            sprintf(
                '$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(%s, \'widget\')',
                $this->getVariableGetter('form')
             ),
            trim($compiler->compile($node)->getSource())
        );
    }

    public function testCompileWidgetWithVariables()
    {
        $arguments = new \Twig_Node(array(
            new \Twig_Node_Expression_Name('form', 0),
            new \Twig_Node_Expression_Array(array(
                new \Twig_Node_Expression_Constant('foo', 0),
                new \Twig_Node_Expression_Constant('bar', 0),
            ), 0),
        ));

        $node = new SearchAndRenderBlockNode('form_widget', $arguments, 0);

        $compiler = new \Twig_Compiler(new \Twig_Environment());

        $this->assertEquals(
            sprintf(
                '$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(%s, \'widget\', array("foo" => "bar"))',
                $this->getVariableGetter('form')
            ),
            trim($compiler->compile($node)->getSource())
        );
    }

    public function testCompileLabelWithLabel()
    {
        $arguments = new \Twig_Node(array(
            new \Twig_Node_Expression_Name('form', 0),
            new \Twig_Node_Expression_Constant('my label', 0),
        ));

        $node = new SearchAndRenderBlockNode('form_label', $arguments, 0);

        $compiler = new \Twig_Compiler(new \Twig_Environment());

        $this->assertEquals(
            sprintf(
                '$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(%s, \'label\', array("label" => "my label"))',
                $this->getVariableGetter('form')
            ),
            trim($compiler->compile($node)->getSource())
        );
    }

    public function testCompileLabelWithNullLabel()
    {
        $arguments = new \Twig_Node(array(
            new \Twig_Node_Expression_Name('form', 0),
            new \Twig_Node_Expression_Constant(null, 0),
        ));

        $node = new SearchAndRenderBlockNode('form_label', $arguments, 0);

        $compiler = new \Twig_Compiler(new \Twig_Environment());

        // "label" => null must not be included in the output!
        // Otherwise the default label is overwritten with null.
        $this->assertEquals(
            sprintf(
                '$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(%s, \'label\')',
                $this->getVariableGetter('form')
            ),
            trim($compiler->compile($node)->getSource())
        );
    }

    public function testCompileLabelWithEmptyStringLabel()
    {
        $arguments = new \Twig_Node(array(
            new \Twig_Node_Expression_Name('form', 0),
            new \Twig_Node_Expression_Constant('', 0),
        ));

        $node = new SearchAndRenderBlockNode('form_label', $arguments, 0);

        $compiler = new \Twig_Compiler(new \Twig_Environment());

        // "label" => null must not be included in the output!
        // Otherwise the default label is overwritten with null.
        $this->assertEquals(
            sprintf(
                '$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(%s, \'label\')',
                $this->getVariableGetter('form')
            ),
            trim($compiler->compile($node)->getSource())
        );
    }

    public function testCompileLabelWithDefaultLabel()
    {
        $arguments = new \Twig_Node(array(
            new \Twig_Node_Expression_Name('form', 0),
        ));

        $node = new SearchAndRenderBlockNode('form_label', $arguments, 0);

        $compiler = new \Twig_Compiler(new \Twig_Environment());

        $this->assertEquals(
            sprintf(
                '$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(%s, \'label\')',
                $this->getVariableGetter('form')
            ),
            trim($compiler->compile($node)->getSource())
        );
    }

    public function testCompileLabelWithAttributes()
    {
        $arguments = new \Twig_Node(array(
            new \Twig_Node_Expression_Name('form', 0),
            new \Twig_Node_Expression_Constant(null, 0),
            new \Twig_Node_Expression_Array(array(
                new \Twig_Node_Expression_Constant('foo', 0),
                new \Twig_Node_Expression_Constant('bar', 0),
            ), 0),
        ));

        $node = new SearchAndRenderBlockNode('form_label', $arguments, 0);

        $compiler = new \Twig_Compiler(new \Twig_Environment());

        // "label" => null must not be included in the output!
        // Otherwise the default label is overwritten with null.
        // https://github.com/symfony/symfony/issues/5029
        $this->assertEquals(
            sprintf(
                '$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(%s, \'label\', array("foo" => "bar"))',
                $this->getVariableGetter('form')
            ),
            trim($compiler->compile($node)->getSource())
        );
    }

    public function testCompileLabelWithLabelAndAttributes()
    {
        $arguments = new \Twig_Node(array(
            new \Twig_Node_Expression_Name('form', 0),
            new \Twig_Node_Expression_Constant('value in argument', 0),
            new \Twig_Node_Expression_Array(array(
                new \Twig_Node_Expression_Constant('foo', 0),
                new \Twig_Node_Expression_Constant('bar', 0),
                new \Twig_Node_Expression_Constant('label', 0),
                new \Twig_Node_Expression_Constant('value in attributes', 0),
            ), 0),
        ));

        $node = new SearchAndRenderBlockNode('form_label', $arguments, 0);

        $compiler = new \Twig_Compiler(new \Twig_Environment());

        $this->assertEquals(
            sprintf(
                '$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(%s, \'label\', array("foo" => "bar", "label" => "value in argument"))',
                $this->getVariableGetter('form')
            ),
            trim($compiler->compile($node)->getSource())
        );
    }

    public function testCompileLabelWithLabelThatEvaluatesToNull()
    {
        $arguments = new \Twig_Node(array(
            new \Twig_Node_Expression_Name('form', 0),
            new \Twig_Node_Expression_Conditional(
                // if
                new \Twig_Node_Expression_Constant(true, 0),
                // then
                new \Twig_Node_Expression_Constant(null, 0),
                // else
                new \Twig_Node_Expression_Constant(null, 0),
                0
            ),
        ));

        $node = new SearchAndRenderBlockNode('form_label', $arguments, 0);

        $compiler = new \Twig_Compiler(new \Twig_Environment());

        // "label" => null must not be included in the output!
        // Otherwise the default label is overwritten with null.
        // https://github.com/symfony/symfony/issues/5029
        $this->assertEquals(
            sprintf(
                '$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(%s, \'label\', (twig_test_empty($_label_ = ((true) ? (null) : (null))) ? array() : array("label" => $_label_)))',
                $this->getVariableGetter('form')
            ),
            trim($compiler->compile($node)->getSource())
        );
    }

    public function testCompileLabelWithLabelThatEvaluatesToNullAndAttributes()
    {
        $arguments = new \Twig_Node(array(
            new \Twig_Node_Expression_Name('form', 0),
            new \Twig_Node_Expression_Conditional(
                // if
                new \Twig_Node_Expression_Constant(true, 0),
                // then
                new \Twig_Node_Expression_Constant(null, 0),
                // else
                new \Twig_Node_Expression_Constant(null, 0),
                0
            ),
            new \Twig_Node_Expression_Array(array(
                new \Twig_Node_Expression_Constant('foo', 0),
                new \Twig_Node_Expression_Constant('bar', 0),
                new \Twig_Node_Expression_Constant('label', 0),
                new \Twig_Node_Expression_Constant('value in attributes', 0),
            ), 0),
        ));

        $node = new SearchAndRenderBlockNode('form_label', $arguments, 0);

        $compiler = new \Twig_Compiler(new \Twig_Environment());

        // "label" => null must not be included in the output!
        // Otherwise the default label is overwritten with null.
        // https://github.com/symfony/symfony/issues/5029
        $this->assertEquals(
            sprintf(
                '$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(%s, \'label\', array("foo" => "bar", "label" => "value in attributes") + (twig_test_empty($_label_ = ((true) ? (null) : (null))) ? array() : array("label" => $_label_)))',
                $this->getVariableGetter('form')
            ),
            trim($compiler->compile($node)->getSource())
        );
    }

    protected function getVariableGetter($name)
    {
        if (version_compare(phpversion(), '5.4.0RC1', '>=')) {
            return sprintf('(isset($context["%s"]) ? $context["%s"] : null)', $name, $name);
        }

        return sprintf('$this->getContext($context, "%s")', $name);
    }
}
PK��Z�h�H	H	@test/TwigBridge/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Tests\Node;

use Symfony\Bridge\Twig\Node\FormThemeNode;

class FormThemeTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $form = new \Twig_Node_Expression_Name('form', 0);
        $resources = new \Twig_Node(array(
            new \Twig_Node_Expression_Constant('tpl1', 0),
            new \Twig_Node_Expression_Constant('tpl2', 0)
        ));

        $node = new FormThemeNode($form, $resources, 0);

        $this->assertEquals($form, $node->getNode('form'));
        $this->assertEquals($resources, $node->getNode('resources'));
    }

    public function testCompile()
    {
        $form = new \Twig_Node_Expression_Name('form', 0);
        $resources = new \Twig_Node_Expression_Array(array(
            new \Twig_Node_Expression_Constant(0, 0),
            new \Twig_Node_Expression_Constant('tpl1', 0),
            new \Twig_Node_Expression_Constant(1, 0),
            new \Twig_Node_Expression_Constant('tpl2', 0)
        ), 0);

        $node = new FormThemeNode($form, $resources, 0);

        $compiler = new \Twig_Compiler(new \Twig_Environment());

        $this->assertEquals(
            sprintf(
                '$this->env->getExtension(\'form\')->renderer->setTheme(%s, array(0 => "tpl1", 1 => "tpl2"));',
                $this->getVariableGetter('form')
             ),
            trim($compiler->compile($node)->getSource())
        );

        $resources = new \Twig_Node_Expression_Constant('tpl1', 0);

        $node = new FormThemeNode($form, $resources, 0);

        $this->assertEquals(
            sprintf(
                '$this->env->getExtension(\'form\')->renderer->setTheme(%s, "tpl1");',
                $this->getVariableGetter('form')
             ),
            trim($compiler->compile($node)->getSource())
        );
    }

    protected function getVariableGetter($name)
    {
        if (version_compare(phpversion(), '5.4.0RC1', '>=')) {
            return sprintf('(isset($context["%s"]) ? $context["%s"] : null)', $name, $name);
        }

        return sprintf('$this->getContext($context, "%s")', $name);
    }
}
PK��Zͅi�99<test/TwigBridge/Symfony/Bridge/Twig/Tests/TwigEngineTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Tests;

use Symfony\Bridge\Twig\TwigEngine;
use Symfony\Component\Templating\TemplateReference;

class TwigEngineTest extends \PHPUnit_Framework_TestCase
{
    public function testExistsWithTemplateInstances()
    {
        $engine = $this->getTwig();

        $this->assertTrue($engine->exists($this->getMockForAbstractClass('Twig_Template', array(), '', false)));
    }

    public function testExistsWithNonExistentTemplates()
    {
        $engine = $this->getTwig();

        $this->assertFalse($engine->exists('foobar'));
        $this->assertFalse($engine->exists(new TemplateReference('foorbar')));
    }

    public function testExistsWithTemplateWithSyntaxErrors()
    {
        $engine = $this->getTwig();

        $this->assertTrue($engine->exists('error'));
        $this->assertTrue($engine->exists(new TemplateReference('error')));
    }

    public function testExists()
    {
        $engine = $this->getTwig();

        $this->assertTrue($engine->exists('index'));
        $this->assertTrue($engine->exists(new TemplateReference('index')));
    }

    public function testRender()
    {
        $engine = $this->getTwig();

        $this->assertSame('foo', $engine->render('index'));
        $this->assertSame('foo', $engine->render(new TemplateReference('index')));
    }

    /**
     * @expectedException \Twig_Error_Syntax
     */
    public function testRenderWithError()
    {
        $engine = $this->getTwig();

        $engine->render(new TemplateReference('error'));
    }

    protected function getTwig()
    {
        $twig = new \Twig_Environment(new \Twig_Loader_Array(array(
            'index' => 'foo',
            'error' => '{{ foo }',
        )));
        $parser = $this->getMock('Symfony\Component\Templating\TemplateNameParserInterface');

        return new TwigEngine($twig, $parser);
    }
}
PK��Zk�K�atest/TwigBridge/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationDefaultDomainNodeVisitorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Tests\NodeVisitor;

use Symfony\Bridge\Twig\NodeVisitor\TranslationDefaultDomainNodeVisitor;
use Symfony\Bridge\Twig\NodeVisitor\TranslationNodeVisitor;

class TranslationDefaultDomainNodeVisitorTest extends \PHPUnit_Framework_TestCase
{
    private static $message = 'message';
    private static $domain = 'domain';

    /** @dataProvider getDefaultDomainAssignmentTestData */
    public function testDefaultDomainAssignment(\Twig_Node $node)
    {
        $env = new \Twig_Environment(new \Twig_Loader_String(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0));
        $visitor = new TranslationDefaultDomainNodeVisitor();

        // visit trans_default_domain tag
        $defaultDomain = TwigNodeProvider::getTransDefaultDomainTag(self::$domain);
        $visitor->enterNode($defaultDomain, $env);
        $visitor->leaveNode($defaultDomain, $env);

        // visit tested node
        $enteredNode = $visitor->enterNode($node, $env);
        $leavedNode = $visitor->leaveNode($node, $env);
        $this->assertSame($node, $enteredNode);
        $this->assertSame($node, $leavedNode);

        // extracting tested node messages
        $visitor = new TranslationNodeVisitor();
        $visitor->enable();
        $visitor->enterNode($node, $env);
        $visitor->leaveNode($node, $env);

        $this->assertEquals(array(array(self::$message, self::$domain)), $visitor->getMessages());
    }

    /** @dataProvider getDefaultDomainAssignmentTestData */
    public function testNewModuleWithoutDefaultDomainTag(\Twig_Node $node)
    {
        $env = new \Twig_Environment(new \Twig_Loader_String(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0));
        $visitor = new TranslationDefaultDomainNodeVisitor();

        // visit trans_default_domain tag
        $newModule = TwigNodeProvider::getModule('test');
        $visitor->enterNode($newModule, $env);
        $visitor->leaveNode($newModule, $env);

        // visit tested node
        $enteredNode = $visitor->enterNode($node, $env);
        $leavedNode = $visitor->leaveNode($node, $env);
        $this->assertSame($node, $enteredNode);
        $this->assertSame($node, $leavedNode);

        // extracting tested node messages
        $visitor = new TranslationNodeVisitor();
        $visitor->enable();
        $visitor->enterNode($node, $env);
        $visitor->leaveNode($node, $env);

        $this->assertEquals(array(array(self::$message, null)), $visitor->getMessages());
    }

    public function getDefaultDomainAssignmentTestData()
    {
        return array(
            array(TwigNodeProvider::getTransFilter(self::$message)),
            array(TwigNodeProvider::getTransChoiceFilter(self::$message)),
            array(TwigNodeProvider::getTransTag(self::$message)),
        );
    }
}
PK��Z¶
���Ttest/TwigBridge/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationNodeVisitorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Tests\NodeVisitor;

use Symfony\Bridge\Twig\NodeVisitor\TranslationNodeVisitor;

class TranslationNodeVisitorTest extends \PHPUnit_Framework_TestCase
{
    /** @dataProvider getMessagesExtractionTestData */
    public function testMessagesExtraction(\Twig_Node $node, array $expectedMessages)
    {
        $env = new \Twig_Environment(new \Twig_Loader_String(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0));
        $visitor = new TranslationNodeVisitor();
        $visitor->enable();
        $visitor->enterNode($node, $env);
        $visitor->leaveNode($node, $env);
        $this->assertEquals($expectedMessages, $visitor->getMessages());
    }

    public function testMessageExtractionWithInvalidDomainNode()
    {
        $message = 'new key';

        $node = new \Twig_Node_Expression_Filter(
            new \Twig_Node_Expression_Constant($message, 0),
            new \Twig_Node_Expression_Constant('trans', 0),
            new \Twig_Node(array(
                new \Twig_Node_Expression_Array(array(), 0),
                new \Twig_Node_Expression_Name('variable', 0),
            )),
            0
        );

        $this->testMessagesExtraction($node, array(array($message, TranslationNodeVisitor::UNDEFINED_DOMAIN)));
    }

    public function getMessagesExtractionTestData()
    {
        $message = 'new key';
        $domain = 'domain';

        return array(
            array(TwigNodeProvider::getTransFilter($message), array(array($message, null))),
            array(TwigNodeProvider::getTransChoiceFilter($message), array(array($message, null))),
            array(TwigNodeProvider::getTransTag($message), array(array($message, null))),
            array(TwigNodeProvider::getTransFilter($message, $domain), array(array($message, $domain))),
            array(TwigNodeProvider::getTransChoiceFilter($message, $domain), array(array($message, $domain))),
            array(TwigNodeProvider::getTransTag($message, $domain), array(array($message, $domain))),
        );
    }
}
PK��Zj|$		Jtest/TwigBridge/Symfony/Bridge/Twig/Tests/NodeVisitor/TwigNodeProvider.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Tests\NodeVisitor;

use Symfony\Bridge\Twig\Node\TransDefaultDomainNode;
use Symfony\Bridge\Twig\Node\TransNode;

class TwigNodeProvider
{
    public static function getModule($content)
    {
        return new \Twig_Node_Module(
            new \Twig_Node_Expression_Constant($content, 0),
            null,
            new \Twig_Node_Expression_Array(array(), 0),
            new \Twig_Node_Expression_Array(array(), 0),
            new \Twig_Node_Expression_Array(array(), 0),
            null,
            null
        );
    }

    public static function getTransFilter($message, $domain = null)
    {
        $arguments = $domain ? array(
            new \Twig_Node_Expression_Array(array(), 0),
            new \Twig_Node_Expression_Constant($domain, 0),
        ) : array();

        return new \Twig_Node_Expression_Filter(
            new \Twig_Node_Expression_Constant($message, 0),
            new \Twig_Node_Expression_Constant('trans', 0),
            new \Twig_Node($arguments),
            0
        );
    }

    public static function getTransChoiceFilter($message, $domain = null)
    {
        $arguments = $domain ? array(
            new \Twig_Node_Expression_Constant(0, 0),
            new \Twig_Node_Expression_Array(array(), 0),
            new \Twig_Node_Expression_Constant($domain, 0),
        ) : array();

        return new \Twig_Node_Expression_Filter(
            new \Twig_Node_Expression_Constant($message, 0),
            new \Twig_Node_Expression_Constant('transchoice', 0),
            new \Twig_Node($arguments),
            0
        );
    }

    public static function getTransTag($message, $domain = null)
    {
        return new TransNode(
            new \Twig_Node_Body(array(), array('data' => $message)),
            $domain ? new \Twig_Node_Expression_Constant($domain, 0) : null
        );
    }

    public static function getTransDefaultDomainTag($domain)
    {
        return new TransDefaultDomainNode(
            new \Twig_Node_Expression_Constant($domain, 0)
        );
    }
}
PK��Z�6��!!Ctest/TwigBridge/Symfony/Bridge/Twig/Tests/NodeVisitor/ScopeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Tests\NodeVisitor;

use Symfony\Bridge\Twig\NodeVisitor\Scope;

class ScopeTest extends \PHPUnit_Framework_TestCase
{
    public function testScopeInitiation()
    {
        $scope = new Scope();
        $scope->enter();
        $this->assertNull($scope->get('test'));
    }
}
PK��Z#�
�
Rtest/TwigBridge/Symfony/Bridge/Twig/Tests/TokenParser/FormThemeTokenParserTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Tests\TokenParser;

use Symfony\Bridge\Twig\TokenParser\FormThemeTokenParser;
use Symfony\Bridge\Twig\Node\FormThemeNode;

class FormThemeTokenParserTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getTestsForFormTheme
     */
    public function testCompile($source, $expected)
    {
        $env = new \Twig_Environment(new \Twig_Loader_String(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0));
        $env->addTokenParser(new FormThemeTokenParser());
        $stream = $env->tokenize($source);
        $parser = new \Twig_Parser($env);

        $this->assertEquals($expected, $parser->parse($stream)->getNode('body')->getNode(0));
    }

    public function getTestsForFormTheme()
    {
        return array(
            array(
                '{% form_theme form "tpl1" %}',
                new FormThemeNode(
                    new \Twig_Node_Expression_Name('form', 1),
                    new \Twig_Node_Expression_Array(array(
                        new \Twig_Node_Expression_Constant(0, 1),
                        new \Twig_Node_Expression_Constant('tpl1', 1),
                    ), 1),
                    1,
                    'form_theme'
                )
            ),
            array(
                '{% form_theme form "tpl1" "tpl2" %}',
                new FormThemeNode(
                    new \Twig_Node_Expression_Name('form', 1),
                    new \Twig_Node_Expression_Array(array(
                        new \Twig_Node_Expression_Constant(0, 1),
                        new \Twig_Node_Expression_Constant('tpl1', 1),
                        new \Twig_Node_Expression_Constant(1, 1),
                        new \Twig_Node_Expression_Constant('tpl2', 1)
                    ), 1),
                    1,
                    'form_theme'
                )
            ),
            array(
                '{% form_theme form with "tpl1" %}',
                new FormThemeNode(
                    new \Twig_Node_Expression_Name('form', 1),
                    new \Twig_Node_Expression_Constant('tpl1', 1),
                    1,
                    'form_theme'
                )
            ),
            array(
                '{% form_theme form with ["tpl1"] %}',
                new FormThemeNode(
                    new \Twig_Node_Expression_Name('form', 1),
                    new \Twig_Node_Expression_Array(array(
                        new \Twig_Node_Expression_Constant(0, 1),
                        new \Twig_Node_Expression_Constant('tpl1', 1),
                    ), 1),
                    1,
                    'form_theme'
                )
            ),
            array(
                '{% form_theme form with ["tpl1", "tpl2"] %}',
                new FormThemeNode(
                    new \Twig_Node_Expression_Name('form', 1),
                    new \Twig_Node_Expression_Array(array(
                        new \Twig_Node_Expression_Constant(0, 1),
                        new \Twig_Node_Expression_Constant('tpl1', 1),
                        new \Twig_Node_Expression_Constant(1, 1),
                        new \Twig_Node_Expression_Constant('tpl2', 1)
                    ), 1),
                    1,
                    'form_theme'
                )
            ),
        );
    }
}
PK��Z��x��Ltest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/RoutingExtensionTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Tests\Extension;

use Symfony\Bridge\Twig\Extension\RoutingExtension;

class RoutingExtensionTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getEscapingTemplates
     */
    public function testEscaping($template, $mustBeEscaped)
    {
        $twig = new \Twig_Environment(null, array('debug' => true, 'cache' => false, 'autoescape' => true, 'optimizations' => 0));
        $twig->addExtension(new RoutingExtension($this->getMock('Symfony\Component\Routing\Generator\UrlGeneratorInterface')));

        $nodes = $twig->parse($twig->tokenize($template));

        $this->assertSame($mustBeEscaped, $nodes->getNode('body')->getNode(0)->getNode('expr') instanceof \Twig_Node_Expression_Filter);
    }

    public function getEscapingTemplates()
    {
        return array(
            array('{{ path("foo") }}', false),
            array('{{ path("foo", {}) }}', false),
            array('{{ path("foo", { foo: "foo" }) }}', false),
            array('{{ path("foo", foo) }}', true),
            array('{{ path("foo", { foo: foo }) }}', true),
            array('{{ path("foo", { foo: ["foo", "bar"] }) }}', true),
            array('{{ path("foo", { foo: "foo", bar: "bar" }) }}', true),

            array('{{ path(name = "foo", parameters = {}) }}', false),
            array('{{ path(name = "foo", parameters = { foo: "foo" }) }}', false),
            array('{{ path(name = "foo", parameters = foo) }}', true),
            array('{{ path(name = "foo", parameters = { foo: ["foo", "bar"] }) }}', true),
            array('{{ path(name = "foo", parameters = { foo: foo }) }}', true),
            array('{{ path(name = "foo", parameters = { foo: "foo", bar: "bar" }) }}', true),
        );
    }
}
PK��Z:��WWTtest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Tests\Extension;

use Symfony\Component\Form\FormView;
use Symfony\Bridge\Twig\Form\TwigRenderer;
use Symfony\Bridge\Twig\Form\TwigRendererEngine;
use Symfony\Bridge\Twig\Extension\FormExtension;
use Symfony\Bridge\Twig\Extension\TranslationExtension;
use Symfony\Component\Form\Tests\AbstractTableLayoutTest;
use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubTranslator;
use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubFilesystemLoader;

class FormExtensionTableLayoutTest extends AbstractTableLayoutTest
{
    /**
     * @var FormExtension
     */
    protected $extension;

    protected function setUp()
    {
        parent::setUp();

        $rendererEngine = new TwigRendererEngine(array(
            'form_table_layout.html.twig',
            'custom_widgets.html.twig',
        ));
        $renderer = new TwigRenderer($rendererEngine, $this->getMock('Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface'));

        $this->extension = new FormExtension($renderer);

        $loader = new StubFilesystemLoader(array(
            __DIR__.'/../../Resources/views/Form',
            __DIR__,
        ));

        $environment = new \Twig_Environment($loader, array('strict_variables' => true));
        $environment->addExtension(new TranslationExtension(new StubTranslator()));
        $environment->addGlobal('global', '');
        $environment->addExtension($this->extension);

        $this->extension->initRuntime($environment);
    }

    protected function tearDown()
    {
        parent::tearDown();

        $this->extension = null;
    }

    protected function renderForm(FormView $view, array $vars = array())
    {
        return (string) $this->extension->renderer->renderBlock($view, 'form', $vars);
    }

    protected function renderEnctype(FormView $view)
    {
        return (string) $this->extension->renderer->searchAndRenderBlock($view, 'enctype');
    }

    protected function renderLabel(FormView $view, $label = null, array $vars = array())
    {
        if ($label !== null) {
            $vars += array('label' => $label);
        }

        return (string) $this->extension->renderer->searchAndRenderBlock($view, 'label', $vars);
    }

    protected function renderErrors(FormView $view)
    {
        return (string) $this->extension->renderer->searchAndRenderBlock($view, 'errors');
    }

    protected function renderWidget(FormView $view, array $vars = array())
    {
        return (string) $this->extension->renderer->searchAndRenderBlock($view, 'widget', $vars);
    }

    protected function renderRow(FormView $view, array $vars = array())
    {
        return (string) $this->extension->renderer->searchAndRenderBlock($view, 'row', $vars);
    }

    protected function renderRest(FormView $view, array $vars = array())
    {
        return (string) $this->extension->renderer->searchAndRenderBlock($view, 'rest', $vars);
    }

    protected function renderStart(FormView $view, array $vars = array())
    {
        return (string) $this->extension->renderer->renderBlock($view, 'form_start', $vars);
    }

    protected function renderEnd(FormView $view, array $vars = array())
    {
        return (string) $this->extension->renderer->renderBlock($view, 'form_end', $vars);
    }

    protected function setTheme(FormView $view, array $themes)
    {
        $this->extension->renderer->setTheme($view, $themes);
    }
}
PK��Zt�9A
A
Otest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Tests\Extension;

use Symfony\Bridge\Twig\Extension\HttpKernelExtension;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Fragment\FragmentHandler;

class HttpKernelExtensionTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \Twig_Error_Runtime
     */
    public function testFragmentWithError()
    {
        $renderer = $this->getFragmentHandler($this->throwException(new \Exception('foo')));

        $this->renderTemplate($renderer);
    }

    public function testRenderFragment()
    {
        $renderer = $this->getFragmentHandler($this->returnValue(new Response('html')));

        $response = $this->renderTemplate($renderer);

        $this->assertEquals('html', $response);
    }

    public function testUnknownFragmentRenderer()
    {
        $context = $this->getMockBuilder('Symfony\\Component\\HttpFoundation\\RequestStack')
            ->disableOriginalConstructor()
            ->getMock()
        ;
        $renderer = new FragmentHandler(array(), false, $context);

        $this->setExpectedException('InvalidArgumentException', 'The "inline" renderer does not exist.');
        $renderer->render('/foo');
    }

    protected function getFragmentHandler($return)
    {
        $strategy = $this->getMock('Symfony\\Component\\HttpKernel\\Fragment\\FragmentRendererInterface');
        $strategy->expects($this->once())->method('getName')->will($this->returnValue('inline'));
        $strategy->expects($this->once())->method('render')->will($return);

        $context = $this->getMockBuilder('Symfony\\Component\\HttpFoundation\\RequestStack')
            ->disableOriginalConstructor()
            ->getMock()
        ;

        $context->expects($this->any())->method('getCurrentRequest')->will($this->returnValue(Request::create('/')));

        $renderer = new FragmentHandler(array($strategy), false, $context);

        return $renderer;
    }

    protected function renderTemplate(FragmentHandler $renderer, $template = '{{ render("foo") }}')
    {
        $loader = new \Twig_Loader_Array(array('index' => $template));
        $twig = new \Twig_Environment($loader, array('debug' => true, 'cache' => false));
        $twig->addExtension(new HttpKernelExtension($renderer));

        return $twig->render('index');
    }
}
PK��Z�V�%33Rtest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/page_dynamic_extends.html.twignu�[���{% extends dynamic_template_name ~ '.html.twig' %}
PK��Z�]��Utest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubFilesystemLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Tests\Extension\Fixtures;

class StubFilesystemLoader extends \Twig_Loader_Filesystem
{
    protected function findTemplate($name)
    {
        // strip away bundle name
        $parts = explode(':', $name);

        return parent::findTemplate(end($parts));
    }
}
PK��Z*��n**Otest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubTranslator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Tests\Extension\Fixtures;

use Symfony\Component\Translation\TranslatorInterface;

class StubTranslator implements TranslatorInterface
{
    public function trans($id, array $parameters = array(), $domain = null, $locale = null)
    {
        return '[trans]'.$id.'[/trans]';
    }

    public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
    {
        return '[trans]'.$id.'[/trans]';
    }

    public function setLocale($locale)
    {
    }

    public function getLocale()
    {
    }
}
PK��Z̙nsGtest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/theme_use.html.twignu�[���{% use 'form_div_layout.html.twig' %}

{% block form_widget_simple %}
{% spaceless %}
    {% set type = type|default('text') %}
    <input type="{{ type }}" {{ block('widget_attributes') }} value="{{ value }}" rel="theme" />
{% endspaceless %}
{% endblock form_widget_simple %}
PK��Z�+����Itest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/CodeExtensionTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Tests\Extension;

use Symfony\Bridge\Twig\Extension\CodeExtension;

class CodeExtensionTest extends \PHPUnit_Framework_TestCase
{
    protected $helper;

    public function testFormatFile()
    {
        $expected = sprintf('<a href="txmt://open?url=file://%s&amp;line=25" title="Click to open this file" class="file_link">%s at line 25</a>', __FILE__, __FILE__);
        $this->assertEquals($expected, $this->getExtension()->formatFile(__FILE__, 25));
    }

    /**
     * @dataProvider getClassNameProvider
     */
    public function testGettingClassAbbreviation($class, $abbr)
    {
        $this->assertEquals($this->getExtension()->abbrClass($class), $abbr);
    }

    /**
     * @dataProvider getMethodNameProvider
     */
    public function testGettingMethodAbbreviation($method, $abbr)
    {
        $this->assertEquals($this->getExtension()->abbrMethod($method), $abbr);
    }

    public function getClassNameProvider()
    {
        return array(
            array('F\Q\N\Foo', '<abbr title="F\Q\N\Foo">Foo</abbr>'),
            array('Bare', '<abbr title="Bare">Bare</abbr>'),
        );
    }

    public function getMethodNameProvider()
    {
        return array(
            array('F\Q\N\Foo::Method', '<abbr title="F\Q\N\Foo">Foo</abbr>::Method()'),
            array('Bare::Method', '<abbr title="Bare">Bare</abbr>::Method()'),
            array('Closure', '<abbr title="Closure">Closure</abbr>'),
            array('Method', '<abbr title="Method">Method</abbr>()')
        );
    }

    public function testGetName()
    {
        $this->assertEquals('code', $this->getExtension()->getName());
    }

    protected function getExtension()
    {
        return new CodeExtension('txmt://open?url=file://%f&line=%l', '/root', 'UTF-8');
    }
}
PK��Z%o��	�	Ntest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/StopwatchExtensionTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Tests\Extension;

use Symfony\Bridge\Twig\Extension\StopwatchExtension;

class StopwatchExtensionTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \Twig_Error_Syntax
     */
    public function testFailIfStoppingWrongEvent()
    {
        $this->testTiming('{% stopwatch "foo" %}{% endstopwatch "bar" %}', array());
    }

    /**
     * @dataProvider getTimingTemplates
     */
    public function testTiming($template, $events)
    {
        $twig = new \Twig_Environment(new \Twig_Loader_String(), array('debug' => true, 'cache' => false, 'autoescape' => true, 'optimizations' => 0));
        $twig->addExtension(new StopwatchExtension($this->getStopwatch($events)));

        try {
            $nodes = $twig->render($template);
        } catch (\Twig_Error_Runtime $e) {
            throw $e->getPrevious();
        }
    }

    public function getTimingTemplates()
    {
        return array(
            array('{% stopwatch "foo" %}something{% endstopwatch %}', 'foo'),
            array('{% stopwatch "foo" %}symfony2 is fun{% endstopwatch %}{% stopwatch "bar" %}something{% endstopwatch %}', array('foo', 'bar')),
            array('{% set foo = "foo" %}{% stopwatch foo %}something{% endstopwatch %}', 'foo'),
            array('{% set foo = "foo" %}{% stopwatch foo %}something {% set foo = "bar" %}{% endstopwatch %}', 'foo'),
            array('{% stopwatch "foo.bar" %}something{% endstopwatch %}', 'foo.bar'),
            array('{% stopwatch "foo" %}something{% endstopwatch %}{% stopwatch "foo" %}something else{% endstopwatch %}', array('foo', 'foo')),
        );
    }

    protected function getStopwatch($events = array())
    {
        $events = is_array($events) ? $events : array($events);
        $stopwatch = $this->getMock('Symfony\Component\Stopwatch\Stopwatch');

        $i = -1;
        foreach ($events as $eventName) {
            $stopwatch->expects($this->at(++$i))
                ->method('start')
                ->with($this->equalTo($eventName), 'template')
            ;
            $stopwatch->expects($this->at(++$i))
                ->method('stop')
                ->with($this->equalTo($eventName))
            ;
        }

        return $stopwatch;
    }
}
PK��Z��ߋ��Otest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/ExpressionExtensionTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Tests\Extension;

use Symfony\Bridge\Twig\Extension\ExpressionExtension;
use Symfony\Component\ExpressionLanguage\Expression;

class ExpressionExtensionTest extends \PHPUnit_Framework_TestCase
{
    protected $helper;

    public function testExpressionCreation()
    {
        $template = "{{ expression('1 == 1') }}";
        $twig = new \Twig_Environment(new \Twig_Loader_String(), array('debug' => true, 'cache' => false, 'autoescape' => true, 'optimizations' => 0));
        $twig->addExtension(new ExpressionExtension());

        $output = $twig->render($template);
        $this->assertEquals('1 == 1', $output);
    }
}
PK��Z��,'KKJtest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/parent_label.html.twignu�[���{% block form_label %}
    <label>parent</label>
{% endblock form_label %}
PK��Z�����Ptest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Tests\Extension;

use Symfony\Bridge\Twig\Extension\TranslationExtension;
use Symfony\Component\Translation\Translator;
use Symfony\Component\Translation\MessageSelector;
use Symfony\Component\Translation\Loader\ArrayLoader;

class TranslationExtensionTest extends \PHPUnit_Framework_TestCase
{
    public function testEscaping()
    {
        $output = $this->getTemplate('{% trans %}Percent: %value%%% (%msg%){% endtrans %}')->render(array('value' => 12, 'msg' => 'approx.'));

        $this->assertEquals('Percent: 12% (approx.)', $output);
    }

    /**
     * @dataProvider getTransTests
     */
    public function testTrans($template, $expected, array $variables = array())
    {
        if ($expected != $this->getTemplate($template)->render($variables)) {
            print $template."\n";
            $loader = new \Twig_Loader_Array(array('index' => $template));
            $twig = new \Twig_Environment($loader, array('debug' => true, 'cache' => false));
            $twig->addExtension(new TranslationExtension(new Translator('en', new MessageSelector())));

            echo $twig->compile($twig->parse($twig->tokenize($twig->getLoader()->getSource('index'), 'index')))."\n\n";
            $this->assertEquals($expected, $this->getTemplate($template)->render($variables));
        }

        $this->assertEquals($expected, $this->getTemplate($template)->render($variables));
    }

    /**
     * @expectedException        \Twig_Error_Syntax
     * @expectedExceptionMessage Unexpected token. Twig was looking for the "with", "from", or "into" keyword in "index" at line 3.
     */
    public function testTransUnknownKeyword()
    {
        $output = $this->getTemplate("{% trans \n\nfoo %}{% endtrans %}")->render();
    }

    /**
     * @expectedException        \Twig_Error_Syntax
     * @expectedExceptionMessage A message inside a trans tag must be a simple text in "index" at line 2.
     */
    public function testTransComplexBody()
    {
        $output = $this->getTemplate("{% trans %}\n{{ 1 + 2 }}{% endtrans %}")->render();
    }

    /**
     * @expectedException        \Twig_Error_Syntax
     * @expectedExceptionMessage A message inside a transchoice tag must be a simple text in "index" at line 2.
     */
    public function testTransChoiceComplexBody()
    {
        $output = $this->getTemplate("{% transchoice count %}\n{{ 1 + 2 }}{% endtranschoice %}")->render();
    }

    public function getTransTests()
    {
        return array(
            // trans tag
            array('{% trans %}Hello{% endtrans %}', 'Hello'),
            array('{% trans %}%name%{% endtrans %}', 'Symfony2', array('name' => 'Symfony2')),

            array('{% trans from elsewhere %}Hello{% endtrans %}', 'Hello'),

            array('{% trans %}Hello %name%{% endtrans %}', 'Hello Symfony2', array('name' => 'Symfony2')),
            array('{% trans with { \'%name%\': \'Symfony2\' } %}Hello %name%{% endtrans %}', 'Hello Symfony2'),
            array('{% set vars = { \'%name%\': \'Symfony2\' } %}{% trans with vars %}Hello %name%{% endtrans %}', 'Hello Symfony2'),

            array('{% trans into "fr"%}Hello{% endtrans %}', 'Hello'),

            // transchoice
            array('{% transchoice count from "messages" %}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples{% endtranschoice %}',
                'There is no apples', array('count' => 0)),
            array('{% transchoice count %}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples{% endtranschoice %}',
                'There is 5 apples', array('count' => 5)),
            array('{% transchoice count %}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples (%name%){% endtranschoice %}',
                'There is 5 apples (Symfony2)', array('count' => 5, 'name' => 'Symfony2')),
            array('{% transchoice count with { \'%name%\': \'Symfony2\' } %}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples (%name%){% endtranschoice %}',
                'There is 5 apples (Symfony2)', array('count' => 5)),
            array('{% transchoice count into "fr"%}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples{% endtranschoice %}',
                'There is no apples', array('count' => 0)),

            // trans filter
            array('{{ "Hello"|trans }}', 'Hello'),
            array('{{ name|trans }}', 'Symfony2', array('name' => 'Symfony2')),
            array('{{ hello|trans({ \'%name%\': \'Symfony2\' }) }}', 'Hello Symfony2', array('hello' => 'Hello %name%')),
            array('{% set vars = { \'%name%\': \'Symfony2\' } %}{{ hello|trans(vars) }}', 'Hello Symfony2', array('hello' => 'Hello %name%')),
            array('{{ "Hello"|trans({}, "messages", "fr") }}', 'Hello'),

            // transchoice filter
            array('{{ "{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples"|transchoice(count) }}', 'There is 5 apples', array('count' => 5)),
            array('{{ text|transchoice(5, {\'%name%\': \'Symfony2\'}) }}', 'There is 5 apples (Symfony2)', array('text' => '{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples (%name%)')),
            array('{{ "{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples"|transchoice(count, {}, "messages", "fr") }}', 'There is 5 apples', array('count' => 5)),
        );
    }

    public function testDefaultTranslationDomain()
    {
        $templates = array(
            'index' => '
                {%- extends "base" %}

                {%- trans_default_domain "foo" %}

                {%- block content %}
                    {%- trans %}foo{% endtrans %}
                    {%- trans from "custom" %}foo{% endtrans %}
                    {{- "foo"|trans }}
                    {{- "foo"|trans({}, "custom") }}
                    {{- "foo"|transchoice(1) }}
                    {{- "foo"|transchoice(1, {}, "custom") }}
                {% endblock %}
            ',

            'base' => '
                {%- block content "" %}
            ',
        );

        $translator = new Translator('en', new MessageSelector());
        $translator->addLoader('array', new ArrayLoader());
        $translator->addResource('array', array('foo' => 'foo (messages)'), 'en');
        $translator->addResource('array', array('foo' => 'foo (custom)'), 'en', 'custom');
        $translator->addResource('array', array('foo' => 'foo (foo)'), 'en', 'foo');

        $template = $this->getTemplate($templates, $translator);

        $this->assertEquals('foo (foo)foo (custom)foo (foo)foo (custom)foo (foo)foo (custom)', trim($template->render(array())));
    }

    protected function getTemplate($template, $translator = null)
    {
        if (null === $translator) {
            $translator = new Translator('en', new MessageSelector());
        }

        if (is_array($template)) {
            $loader = new \Twig_Loader_Array($template);
        } else {
            $loader = new \Twig_Loader_Array(array('index' => $template));
        }
        $twig = new \Twig_Environment($loader, array('debug' => true, 'cache' => false));
        $twig->addExtension(new TranslationExtension($translator));

        return $twig->loadTemplate('index');
    }
}
PK��Z(���Ctest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/theme.html.twignu�[���{% block form_widget_simple %}
{% spaceless %}
    {% set type = type|default('text') %}
    <input type="{{ type }}" {{ block('widget_attributes') }} value="{{ value }}" rel="theme" />
{% endspaceless %}
{% endblock form_widget_simple %}
PK��Z��i�!!Rtest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Twig\Tests\Extension;

use Symfony\Bridge\Twig\Extension\FormExtension;
use Symfony\Bridge\Twig\Form\TwigRenderer;
use Symfony\Bridge\Twig\Form\TwigRendererEngine;
use Symfony\Bridge\Twig\Extension\TranslationExtension;
use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubTranslator;
use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubFilesystemLoader;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\Extension\Core\View\ChoiceView;
use Symfony\Component\Form\Tests\AbstractDivLayoutTest;

class FormExtensionDivLayoutTest extends AbstractDivLayoutTest
{
    /**
     * @var FormExtension
     */
    protected $extension;

    protected function setUp()
    {
        parent::setUp();

        $rendererEngine = new TwigRendererEngine(array(
            'form_div_layout.html.twig',
            'custom_widgets.html.twig',
        ));
        $renderer = new TwigRenderer($rendererEngine, $this->getMock('Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface'));

        $this->extension = new FormExtension($renderer);

        $loader = new StubFilesystemLoader(array(
            __DIR__.'/../../Resources/views/Form',
            __DIR__,
        ));

        $environment = new \Twig_Environment($loader, array('strict_variables' => true));
        $environment->addExtension(new TranslationExtension(new StubTranslator()));
        $environment->addGlobal('global', '');
        // the value can be any template that exists
        $environment->addGlobal('dynamic_template_name', 'child_label');
        $environment->addExtension($this->extension);

        $this->extension->initRuntime($environment);
    }

    protected function tearDown()
    {
        parent::tearDown();

        $this->extension = null;
    }

    public function testThemeBlockInheritanceUsingUse()
    {
        $view = $this->factory
            ->createNamed('name', 'email')
            ->createView()
        ;

        $this->setTheme($view, array('theme_use.html.twig'));

        $this->assertMatchesXpath(
            $this->renderWidget($view),
            '/input[@type="email"][@rel="theme"]'
        );
    }

    public function testThemeBlockInheritanceUsingExtend()
    {
        $view = $this->factory
            ->createNamed('name', 'email')
            ->createView()
        ;

        $this->setTheme($view, array('theme_extends.html.twig'));

        $this->assertMatchesXpath(
            $this->renderWidget($view),
            '/input[@type="email"][@rel="theme"]'
        );
    }

    public function testThemeBlockInheritanceUsingDynamicExtend()
    {
        $view = $this->factory
            ->createNamed('name', 'email')
            ->createView()
        ;

        $renderer = $this->extension->renderer;
        $renderer->setTheme($view, array('page_dynamic_extends.html.twig'));
        $renderer->searchAndRenderBlock($view, 'row');
    }

    public function isSelectedChoiceProvider()
    {
        // The commented cases should not be necessary anymore, because the
        // choice lists should assure that both values passed here are always
        // strings
        return array(
//             array(true, 0, 0),
            array(true, '0', '0'),
            array(true, '1', '1'),
//             array(true, false, 0),
//             array(true, true, 1),
            array(true, '', ''),
//             array(true, null, ''),
            array(true, '1.23', '1.23'),
            array(true, 'foo', 'foo'),
            array(true, 'foo10', 'foo10'),
            array(true, 'foo', array(1, 'foo', 'foo10')),

            array(false, 10, array(1, 'foo', 'foo10')),
            array(false, 0, array(1, 'foo', 'foo10')),
        );
    }

    /**
     * @dataProvider isSelectedChoiceProvider
     */
    public function testIsChoiceSelected($expected, $choice, $value)
    {
        $choice = new ChoiceView($choice, $choice, $choice.' label');

        $this->assertSame($expected, $this->extension->isSelectedChoice($choice, $value));
    }

    protected function renderForm(FormView $view, array $vars = array())
    {
        return (string) $this->extension->renderer->renderBlock($view, 'form', $vars);
    }

    protected function renderEnctype(FormView $view)
    {
        return (string) $this->extension->renderer->searchAndRenderBlock($view, 'enctype');
    }

    protected function renderLabel(FormView $view, $label = null, array $vars = array())
    {
        if ($label !== null) {
            $vars += array('label' => $label);
        }

        return (string) $this->extension->renderer->searchAndRenderBlock($view, 'label', $vars);
    }

    protected function renderErrors(FormView $view)
    {
        return (string) $this->extension->renderer->searchAndRenderBlock($view, 'errors');
    }

    protected function renderWidget(FormView $view, array $vars = array())
    {
        return (string) $this->extension->renderer->searchAndRenderBlock($view, 'widget', $vars);
    }

    protected function renderRow(FormView $view, array $vars = array())
    {
        return (string) $this->extension->renderer->searchAndRenderBlock($view, 'row', $vars);
    }

    protected function renderRest(FormView $view, array $vars = array())
    {
        return (string) $this->extension->renderer->searchAndRenderBlock($view, 'rest', $vars);
    }

    protected function renderStart(FormView $view, array $vars = array())
    {
        return (string) $this->extension->renderer->renderBlock($view, 'form_start', $vars);
    }

    protected function renderEnd(FormView $view, array $vars = array())
    {
        return (string) $this->extension->renderer->renderBlock($view, 'form_end', $vars);
    }

    protected function setTheme(FormView $view, array $themes)
    {
        $this->extension->renderer->setTheme($view, $themes);
    }

    public static function themeBlockInheritanceProvider()
    {
        return array(
            array(array('theme.html.twig'))
        );
    }

    public static function themeInheritanceProvider()
    {
        return array(
            array(array('parent_label.html.twig'), array('child_label.html.twig'))
        );
    }
}
PK��ZҺ
�VVItest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/child_label.html.twignu�[���{% block form_label %}
    <label>{{ global }}child</label>
{% endblock form_label %}
PK��Z�tdKtest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/theme_extends.html.twignu�[���{% extends 'form_div_layout.html.twig' %}

{% block form_widget_simple %}
{% spaceless %}
    {% set type = type|default('text') %}
    <input type="{{ type }}" {{ block('widget_attributes') }} value="{{ value }}" rel="theme" />
{% endspaceless %}
{% endblock form_widget_simple %}
PK��Z��b���Ltest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/custom_widgets.html.twignu�[���{% block _text_id_widget %}
{% spaceless %}
    <div id="container">
        {{ form_widget(form) }}
    </div>
{% endspaceless %}
{% endblock _text_id_widget %}

{% block _name_entry_label %}
{% spaceless %}
    {% if label is empty %}
        {% set label = name|humanize %}
    {% endif %}
    <label>Custom label: {{ label|trans({}, translation_domain) }}</label>
{% endspaceless %}
{% endblock _name_entry_label %}
PK��ZPcc4test/TwigBridge/Symfony/Bridge/Twig/phpunit.xml.distnu�[���<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony Twig Bridge Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./Resources</directory>
                <directory>./Tests</directory>
                <directory>./vendor</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
PK��Zh�9=UUOtest/Translation/Symfony/Component/Translation/Tests/IdentityTranslatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests;

use Symfony\Component\Translation\IdentityTranslator;

class IdentityTranslatorTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getTransTests
     */
    public function testTrans($expected, $id, $parameters)
    {
        $translator = new IdentityTranslator();

        $this->assertEquals($expected, $translator->trans($id, $parameters));
    }

    /**
     * @dataProvider getTransChoiceTests
     */
    public function testTransChoiceWithExplicitLocale($expected, $id, $number, $parameters)
    {
        $translator = new IdentityTranslator();
        $translator->setLocale('en');

        $this->assertEquals($expected, $translator->transChoice($id, $number, $parameters));
    }

    /**
     * @dataProvider getTransChoiceTests
     */
    public function testTransChoiceWithDefaultLocale($expected, $id, $number, $parameters)
    {
        \Locale::setDefault('en');

        $translator = new IdentityTranslator();

        $this->assertEquals($expected, $translator->transChoice($id, $number, $parameters));
    }

    public function testGetSetLocale()
    {
        $translator = new IdentityTranslator();
        $translator->setLocale('en');

        $this->assertEquals('en', $translator->getLocale());
    }

    public function testGetLocaleReturnsDefaultLocaleIfNotSet()
    {
        $translator = new IdentityTranslator();

        \Locale::setDefault('en');
        $this->assertEquals('en', $translator->getLocale());

        \Locale::setDefault('pt_BR');
        $this->assertEquals('pt_BR', $translator->getLocale());
    }

    public function getTransTests()
    {
        return array(
            array('Symfony2 is great!', 'Symfony2 is great!', array()),
            array('Symfony2 is awesome!', 'Symfony2 is %what%!', array('%what%' => 'awesome')),
        );
    }

    public function getTransChoiceTests()
    {
        return array(
            array('There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0, array('%count%' => 0)),
            array('There is one apple', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 1, array('%count%' => 1)),
            array('There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10, array('%count%' => 10)),
            array('There are 0 apples', 'There is 1 apple|There are %count% apples', 0, array('%count%' => 0)),
            array('There is 1 apple', 'There is 1 apple|There are %count% apples', 1, array('%count%' => 1)),
            array('There are 10 apples', 'There is 1 apple|There are %count% apples', 10, array('%count%' => 10)),
            // custom validation messages may be coded with a fixed value
            array('There are 2 apples', 'There are 2 apples', 2, array('%count%' => 2)),
        );
    }
}
PK��Z���*|1|1Gtest/Translation/Symfony/Component/Translation/Tests/TranslatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests;

use Symfony\Component\Translation\Translator;
use Symfony\Component\Translation\Loader\ArrayLoader;

class TranslatorTest extends \PHPUnit_Framework_TestCase
{
    public function testSetGetLocale()
    {
        $translator = new Translator('en');

        $this->assertEquals('en', $translator->getLocale());

        $translator->setLocale('fr');
        $this->assertEquals('fr', $translator->getLocale());
    }

    public function testSetFallbackLocales()
    {
        $translator = new Translator('en');
        $translator->addLoader('array', new ArrayLoader());
        $translator->addResource('array', array('foo' => 'foofoo'), 'en');
        $translator->addResource('array', array('bar' => 'foobar'), 'fr');

        // force catalogue loading
        $translator->trans('bar');

        $translator->setFallbackLocales(array('fr'));
        $this->assertEquals('foobar', $translator->trans('bar'));
    }

    public function testSetFallbackLocalesMultiple()
    {
        $translator = new Translator('en');
        $translator->addLoader('array', new ArrayLoader());
        $translator->addResource('array', array('foo' => 'foo (en)'), 'en');
        $translator->addResource('array', array('bar' => 'bar (fr)'), 'fr');

        // force catalogue loading
        $translator->trans('bar');

        $translator->setFallbackLocales(array('fr_FR', 'fr'));
        $this->assertEquals('bar (fr)', $translator->trans('bar'));
    }

    public function testTransWithFallbackLocale()
    {
        $translator = new Translator('fr_FR');
        $translator->addLoader('array', new ArrayLoader());
        $translator->addResource('array', array('foo' => 'foofoo'), 'en_US');
        $translator->addResource('array', array('bar' => 'foobar'), 'en');

        $translator->setFallbackLocales(array('en'));

        $this->assertEquals('foobar', $translator->trans('bar'));
    }

    public function testAddResourceAfterTrans()
    {
        $translator = new Translator('fr');
        $translator->addLoader('array', new ArrayLoader());

        $translator->setFallbackLocale(array('en'));

        $translator->addResource('array', array('foo' => 'foofoo'), 'en');
        $this->assertEquals('foofoo', $translator->trans('foo'));

        $translator->addResource('array', array('bar' => 'foobar'), 'en');
        $this->assertEquals('foobar', $translator->trans('bar'));
    }

    /**
     * @dataProvider      getTransFileTests
     * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
     */
    public function testTransWithoutFallbackLocaleFile($format, $loader)
    {
        $loaderClass = 'Symfony\\Component\\Translation\\Loader\\'.$loader;
        $translator = new Translator('en');
        $translator->addLoader($format, new $loaderClass());
        $translator->addResource($format, __DIR__.'/fixtures/non-existing', 'en');
        $translator->addResource($format, __DIR__.'/fixtures/resources.'.$format, 'en');

        // force catalogue loading
        $translator->trans('foo');
    }

    /**
     * @dataProvider getTransFileTests
     */
    public function testTransWithFallbackLocaleFile($format, $loader)
    {
        $loaderClass = 'Symfony\\Component\\Translation\\Loader\\'.$loader;
        $translator = new Translator('en_GB');
        $translator->addLoader($format, new $loaderClass());
        $translator->addResource($format, __DIR__.'/fixtures/non-existing', 'en_GB');
        $translator->addResource($format, __DIR__.'/fixtures/resources.'.$format, 'en', 'resources');

        $this->assertEquals('bar', $translator->trans('foo', array(), 'resources'));
    }

    public function testTransWithFallbackLocaleBis()
    {
        $translator = new Translator('en_US');
        $translator->addLoader('array', new ArrayLoader());
        $translator->addResource('array', array('foo' => 'foofoo'), 'en_US');
        $translator->addResource('array', array('bar' => 'foobar'), 'en');
        $this->assertEquals('foobar', $translator->trans('bar'));
    }

    public function testTransWithFallbackLocaleTer()
    {
        $translator = new Translator('fr_FR');
        $translator->addLoader('array', new ArrayLoader());
        $translator->addResource('array', array('foo' => 'foo (en_US)'), 'en_US');
        $translator->addResource('array', array('bar' => 'bar (en)'), 'en');

        $translator->setFallbackLocales(array('en_US', 'en'));

        $this->assertEquals('foo (en_US)', $translator->trans('foo'));
        $this->assertEquals('bar (en)', $translator->trans('bar'));
    }

    public function testTransNonExistentWithFallback()
    {
        $translator = new Translator('fr');
        $translator->setFallbackLocales(array('en'));
        $translator->addLoader('array', new ArrayLoader());
        $this->assertEquals('non-existent', $translator->trans('non-existent'));
    }

    /**
     * @expectedException \RuntimeException
     */
    public function testWhenAResourceHasNoRegisteredLoader()
    {
        $translator = new Translator('en');
        $translator->addResource('array', array('foo' => 'foofoo'), 'en');

        $translator->trans('foo');
    }

    /**
     * @dataProvider getTransTests
     */
    public function testTrans($expected, $id, $translation, $parameters, $locale, $domain)
    {
        $translator = new Translator('en');
        $translator->addLoader('array', new ArrayLoader());
        $translator->addResource('array', array((string) $id => $translation), $locale, $domain);

        $this->assertEquals($expected, $translator->trans($id, $parameters, $domain, $locale));
    }

    /**
     * @dataProvider getFlattenedTransTests
     */
    public function testFlattenedTrans($expected, $messages, $id)
    {
        $translator = new Translator('en');
        $translator->addLoader('array', new ArrayLoader());
        $translator->addResource('array', $messages, 'fr', '');

        $this->assertEquals($expected, $translator->trans($id, array(), '', 'fr'));
    }

    /**
     * @dataProvider getTransChoiceTests
     */
    public function testTransChoice($expected, $id, $translation, $number, $parameters, $locale, $domain)
    {
        $translator = new Translator('en');
        $translator->addLoader('array', new ArrayLoader());
        $translator->addResource('array', array((string) $id => $translation), $locale, $domain);

        $this->assertEquals($expected, $translator->transChoice($id, $number, $parameters, $domain, $locale));
    }

    public function getTransFileTests()
    {
        return array(
            array('csv', 'CsvFileLoader'),
            array('ini', 'IniFileLoader'),
            array('mo', 'MoFileLoader'),
            array('po', 'PoFileLoader'),
            array('php', 'PhpFileLoader'),
            array('ts', 'QtFileLoader'),
            array('xlf', 'XliffFileLoader'),
            array('yml', 'YamlFileLoader'),
            array('json', 'JsonFileLoader'),
        );
    }

    public function getTransTests()
    {
        return array(
            array('Symfony2 est super !', 'Symfony2 is great!', 'Symfony2 est super !', array(), 'fr', ''),
            array('Symfony2 est awesome !', 'Symfony2 is %what%!', 'Symfony2 est %what% !', array('%what%' => 'awesome'), 'fr', ''),
            array('Symfony2 est super !', new String('Symfony2 is great!'), 'Symfony2 est super !', array(), 'fr', ''),
        );
    }

    public function getFlattenedTransTests()
    {
        $messages = array(
            'symfony2' => array(
                'is' => array(
                    'great' => 'Symfony2 est super!'
                )
            ),
            'foo' => array(
                'bar' => array(
                    'baz' => 'Foo Bar Baz'
                ),
                'baz' => 'Foo Baz',
            ),
        );

        return array(
            array('Symfony2 est super!', $messages, 'symfony2.is.great'),
            array('Foo Bar Baz', $messages, 'foo.bar.baz'),
            array('Foo Baz', $messages, 'foo.baz'),
        );
    }

    public function getTransChoiceTests()
    {
        return array(
            array('Il y a 0 pomme', '{0} There are no appless|{1} There is one apple|]1,Inf] There is %count% apples', '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 0, array('%count%' => 0), 'fr', ''),
            array('Il y a 1 pomme', '{0} There are no appless|{1} There is one apple|]1,Inf] There is %count% apples', '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 1, array('%count%' => 1), 'fr', ''),
            array('Il y a 10 pommes', '{0} There are no appless|{1} There is one apple|]1,Inf] There is %count% apples', '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 10, array('%count%' => 10), 'fr', ''),

            array('Il y a 0 pomme', 'There is one apple|There is %count% apples', 'Il y a %count% pomme|Il y a %count% pommes', 0, array('%count%' => 0), 'fr', ''),
            array('Il y a 1 pomme', 'There is one apple|There is %count% apples', 'Il y a %count% pomme|Il y a %count% pommes', 1, array('%count%' => 1), 'fr', ''),
            array('Il y a 10 pommes', 'There is one apple|There is %count% apples', 'Il y a %count% pomme|Il y a %count% pommes', 10, array('%count%' => 10), 'fr', ''),

            array('Il y a 0 pomme', 'one: There is one apple|more: There is %count% apples', 'one: Il y a %count% pomme|more: Il y a %count% pommes', 0, array('%count%' => 0), 'fr', ''),
            array('Il y a 1 pomme', 'one: There is one apple|more: There is %count% apples', 'one: Il y a %count% pomme|more: Il y a %count% pommes', 1, array('%count%' => 1), 'fr', ''),
            array('Il y a 10 pommes', 'one: There is one apple|more: There is %count% apples', 'one: Il y a %count% pomme|more: Il y a %count% pommes', 10, array('%count%' => 10), 'fr', ''),

            array('Il n\'y a aucune pomme', '{0} There are no apples|one: There is one apple|more: There is %count% apples', '{0} Il n\'y a aucune pomme|one: Il y a %count% pomme|more: Il y a %count% pommes', 0, array('%count%' => 0), 'fr', ''),
            array('Il y a 1 pomme', '{0} There are no apples|one: There is one apple|more: There is %count% apples', '{0} Il n\'y a aucune pomme|one: Il y a %count% pomme|more: Il y a %count% pommes', 1, array('%count%' => 1), 'fr', ''),
            array('Il y a 10 pommes', '{0} There are no apples|one: There is one apple|more: There is %count% apples', '{0} Il n\'y a aucune pomme|one: Il y a %count% pomme|more: Il y a %count% pommes', 10, array('%count%' => 10), 'fr', ''),

            array('Il y a 0 pomme', new String('{0} There are no appless|{1} There is one apple|]1,Inf] There is %count% apples'), '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 0, array('%count%' => 0), 'fr', ''),
        );
    }

    public function testTransChoiceFallback()
    {
        $translator = new Translator('ru');
        $translator->setFallbackLocales(array('en'));
        $translator->addLoader('array', new ArrayLoader());
        $translator->addResource('array', array('some_message2' => 'one thing|%count% things'), 'en');

        $this->assertEquals('10 things', $translator->transChoice('some_message2', 10, array('%count%' => 10)));
    }

    public function testTransChoiceFallbackBis()
    {
        $translator = new Translator('ru');
        $translator->setFallbackLocales(array('en_US', 'en'));
        $translator->addLoader('array', new ArrayLoader());
        $translator->addResource('array', array('some_message2' => 'one thing|%count% things'), 'en_US');

        $this->assertEquals('10 things', $translator->transChoice('some_message2', 10, array('%count%' => 10)));
    }

    public function testTransChoiceFallbackWithNoTranslation()
    {
        $translator = new Translator('ru');
        $translator->setFallbackLocales(array('en'));
        $translator->addLoader('array', new ArrayLoader());

        // consistent behavior with Translator::trans(), which returns the string
        // unchanged if it can't be found
        $this->assertEquals('some_message2', $translator->transChoice('some_message2', 10, array('%count%' => 10)));
    }
}

class String
{
    protected $str;

    public function __construct($str)
    {
        $this->str = $str;
    }

    public function __toString()
    {
        return $this->str;
    }
}
PK��Zl.!���Otest/Translation/Symfony/Component/Translation/Tests/PluralizationRulesTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests;

use Symfony\Component\Translation\PluralizationRules;

/**
 * Test should cover all languages mentioned on http://translate.sourceforge.net/wiki/l10n/pluralforms
 * and Plural forms mentioned on http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms
 *
 * See also https://developer.mozilla.org/en/Localization_and_Plurals which mentions 15 rules having a maximum of 6 forms.
 * The mozilla code is also interesting to check for.
 *
 * As mentioned by chx http://drupal.org/node/1273968 we can cover all by testing number from 0 to 199
 *
 * The goal to cover all languages is to far fetched so this test case is smaller.
 *
 * @author Clemens Tolboom clemens@build2be.nl
 */
class PluralizationRulesTest  extends \PHPUnit_Framework_TestCase
{

    /**
     * We test failed langcode here.
     *
     * TODO: The languages mentioned in the data provide need to get fixed somehow within PluralizationRules.
     *
     * @dataProvider failingLangcodes
     */
    public function testFailedLangcodes($nplural, $langCodes)
    {
        $matrix = $this->generateTestData($nplural, $langCodes);
        $this->validateMatrix($nplural, $matrix, false);
    }

    /**
     * @dataProvider successLangcodes
     */
    public function testLangcodes($nplural, $langCodes)
    {
        $matrix = $this->generateTestData($nplural, $langCodes);
        $this->validateMatrix($nplural, $matrix);
    }

    /**
     * This array should contain all currently known langcodes.
     *
     * As it is impossible to have this ever complete we should try as hard as possible to have it almost complete.
     *
     * @return type
     */
    public function successLangcodes()
    {
      return array(
        array('1' , array('ay','bo', 'cgg','dz','id', 'ja', 'jbo', 'ka','kk','km','ko','ky')),
        array('2' , array('nl', 'fr', 'en', 'de', 'de_GE')),
        array('3' , array('be','bs','cs','hr')),
        array('4' , array('cy','mt', 'sl')),
        array('5' , array()),
        array('6' , array('ar')),
      );
    }

    /**
     * This array should be at least empty within the near future.
     *
     * This both depends on a complete list trying to add above as understanding
     * the plural rules of the current failing languages.
     *
     * @return array with nplural together with langcodes
     */
    public function failingLangcodes()
    {
      return array(
        array('1' , array('fa')),
        array('2' , array('jbo')),
        array('3' , array('cbs')),
        array('4' , array('gd','kw')),
        array('5' , array('ga')),
        array('6' , array()),
      );
    }

    /**
     * We validate only on the plural coverage. Thus the real rules is not tested.
     *
     * @param string  $nplural       plural expected
     * @param array   $matrix        containing langcodes and their plural index values.
     * @param boolean $expectSuccess
     */
    protected function validateMatrix($nplural, $matrix, $expectSuccess = true)
    {
        foreach ($matrix as $langCode => $data) {
            $indexes = array_flip($data);
            if ($expectSuccess) {
                $this->assertEquals($nplural, count($indexes), "Langcode '$langCode' has '$nplural' plural forms.");
            } else {
                $this->assertNotEquals((int) $nplural, count($indexes), "Langcode '$langCode' has '$nplural' plural forms.");
            }
        }
    }

    protected function generateTestData($plural, $langCodes)
    {
        $matrix = array();
        foreach ($langCodes as $langCode) {
            for ($count=0; $count<200; $count++) {
                $plural = PluralizationRules::get($count, $langCode);
                $matrix[$langCode][$count] = $plural;
            }
        }

        return $matrix;
    }
}
PK��Z�h�l��Ttest/Translation/Symfony/Component/Translation/Tests/Catalogue/DiffOperationTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Catalogue;

use Symfony\Component\Translation\Catalogue\DiffOperation;
use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\MessageCatalogueInterface;

class DiffOperationTest extends AbstractOperationTest
{
    public function testGetMessagesFromSingleDomain()
    {
        $operation = $this->createOperation(
            new MessageCatalogue('en', array('messages' => array('a' => 'old_a', 'b' => 'old_b'))),
            new MessageCatalogue('en', array('messages' => array('a' => 'new_a', 'c' => 'new_c')))
        );

        $this->assertEquals(
            array('a' => 'old_a', 'c' => 'new_c'),
            $operation->getMessages('messages')
        );

        $this->assertEquals(
            array('c' => 'new_c'),
            $operation->getNewMessages('messages')
        );

        $this->assertEquals(
            array('b' => 'old_b'),
            $operation->getObsoleteMessages('messages')
        );
    }

    public function testGetResultFromSingleDomain()
    {
        $this->assertEquals(
            new MessageCatalogue('en', array(
                'messages' => array('a' => 'old_a', 'c' => 'new_c')
            )),
            $this->createOperation(
                new MessageCatalogue('en', array('messages' => array('a' => 'old_a', 'b' => 'old_b'))),
                new MessageCatalogue('en', array('messages' => array('a' => 'new_a', 'c' => 'new_c')))
            )->getResult()
        );
    }

    protected function createOperation(MessageCatalogueInterface $source, MessageCatalogueInterface $target)
    {
        return new DiffOperation($source, $target);
    }
}
PK��Z$͒ϛ�Utest/Translation/Symfony/Component/Translation/Tests/Catalogue/MergeOperationTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Catalogue;

use Symfony\Component\Translation\Catalogue\MergeOperation;
use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\MessageCatalogueInterface;

class MergeOperationTest extends AbstractOperationTest
{
    public function testGetMessagesFromSingleDomain()
    {
        $operation = $this->createOperation(
            new MessageCatalogue('en', array('messages' => array('a' => 'old_a', 'b' => 'old_b'))),
            new MessageCatalogue('en', array('messages' => array('a' => 'new_a', 'c' => 'new_c')))
        );

        $this->assertEquals(
            array('a' => 'old_a', 'b' => 'old_b', 'c' => 'new_c'),
            $operation->getMessages('messages')
        );

        $this->assertEquals(
            array('c' => 'new_c'),
            $operation->getNewMessages('messages')
        );

        $this->assertEquals(
            array(),
            $operation->getObsoleteMessages('messages')
        );
    }

    public function testGetResultFromSingleDomain()
    {
        $this->assertEquals(
            new MessageCatalogue('en', array(
                'messages' => array('a' => 'old_a', 'b' => 'old_b', 'c' => 'new_c')
            )),
            $this->createOperation(
                new MessageCatalogue('en', array('messages' => array('a' => 'old_a', 'b' => 'old_b'))),
                new MessageCatalogue('en', array('messages' => array('a' => 'new_a', 'c' => 'new_c')))
            )->getResult()
        );
    }

    protected function createOperation(MessageCatalogueInterface $source, MessageCatalogueInterface $target)
    {
        return new MergeOperation($source, $target);
    }
}
PK��Zײ�))Xtest/Translation/Symfony/Component/Translation/Tests/Catalogue/AbstractOperationTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Catalogue;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\MessageCatalogueInterface;

abstract class AbstractOperationTest extends \PHPUnit_Framework_TestCase
{
    public function testGetEmptyDomains()
    {
        $this->assertEquals(
            array(),
            $this->createOperation(
                new MessageCatalogue('en'),
                new MessageCatalogue('en')
            )->getDomains()
        );
    }

    public function testGetMergedDomains()
    {
        $this->assertEquals(
            array('a', 'b', 'c'),
            $this->createOperation(
                new MessageCatalogue('en', array('a' => array(), 'b' => array())),
                new MessageCatalogue('en', array('b' => array(), 'c' => array()))
            )->getDomains()
        );
    }

    public function testGetMessagesFromUnknownDomain()
    {
        $this->setExpectedException('InvalidArgumentException');
        $this->createOperation(
            new MessageCatalogue('en'),
            new MessageCatalogue('en')
        )->getMessages('domain');
    }

    public function testGetEmptyMessages()
    {
        $this->assertEquals(
            array(),
            $this->createOperation(
                new MessageCatalogue('en', array('a' => array())),
                new MessageCatalogue('en')
            )->getMessages('a')
        );
    }

    public function testGetEmptyResult()
    {
        $this->assertEquals(
            new MessageCatalogue('en'),
            $this->createOperation(
                new MessageCatalogue('en'),
                new MessageCatalogue('en')
            )->getResult()
        );
    }

    abstract protected function createOperation(MessageCatalogueInterface $source, MessageCatalogueInterface $target);
}
PK��Z0�2��Etest/Translation/Symfony/Component/Translation/Tests/IntervalTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests;

use Symfony\Component\Translation\Interval;

class IntervalTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getTests
     */
    public function testTest($expected, $number, $interval)
    {
        $this->assertEquals($expected, Interval::test($number, $interval));
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testTestException()
    {
        Interval::test(1, 'foobar');
    }

    public function getTests()
    {
        return array(
            array(true, 3, '{1,2, 3 ,4}'),
            array(false, 10, '{1,2, 3 ,4}'),
            array(false, 3, '[1,2]'),
            array(true, 1, '[1,2]'),
            array(true, 2, '[1,2]'),
            array(false, 1, ']1,2['),
            array(false, 2, ']1,2['),
            array(true, log(0), '[-Inf,2['),
            array(true, -log(0), '[-2,+Inf]'),
        );
    }
}
PK��Z��V��Qtest/Translation/Symfony/Component/Translation/Tests/Dumper/IniFileDumperTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Dumper;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Dumper\IniFileDumper;

class IniFileDumperTest extends \PHPUnit_Framework_TestCase
{
    public function testDump()
    {
        $catalogue = new MessageCatalogue('en');
        $catalogue->add(array('foo' => 'bar'));

        $tempDir = sys_get_temp_dir();
        $dumper = new IniFileDumper();
        $dumper->dump($catalogue, array('path' => $tempDir));

        $this->assertEquals(file_get_contents(__DIR__.'/../fixtures/resources.ini'), file_get_contents($tempDir.'/messages.en.ini'));

        unlink($tempDir.'/messages.en.ini');
    }
}
PK��Z`��׹�Stest/Translation/Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Dumper;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Dumper\XliffFileDumper;

class XliffFileDumperTest extends \PHPUnit_Framework_TestCase
{
    public function testDump()
    {
        $catalogue = new MessageCatalogue('en');
        $catalogue->add(array('foo' => 'bar', 'key' => ''));

        $tempDir = sys_get_temp_dir();
        $dumper = new XliffFileDumper();
        $dumper->dump($catalogue, array('path' => $tempDir));

        $this->assertEquals(file_get_contents(__DIR__.'/../fixtures/resources-clean.xlf'), file_get_contents($tempDir.'/messages.en.xlf'));

        unlink($tempDir.'/messages.en.xlf');
    }
}
PK��Z����Qtest/Translation/Symfony/Component/Translation/Tests/Dumper/PhpFileDumperTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Dumper;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Dumper\PhpFileDumper;

class PhpFileDumperTest extends \PHPUnit_Framework_TestCase
{
    public function testDump()
    {
        $catalogue = new MessageCatalogue('en');
        $catalogue->add(array('foo' => 'bar'));

        $tempDir = sys_get_temp_dir();
        $dumper = new PhpFileDumper();
        $dumper->dump($catalogue, array('path' => $tempDir));

        $this->assertEquals(file_get_contents(__DIR__.'/../fixtures/resources.php'), file_get_contents($tempDir.'/messages.en.php'));

        unlink($tempDir.'/messages.en.php');
    }
}
PK��Z����Rtest/Translation/Symfony/Component/Translation/Tests/Dumper/YamlFileDumperTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Dumper;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Dumper\YamlFileDumper;

class YamlFileDumperTest extends \PHPUnit_Framework_TestCase
{
    public function testDump()
    {
        $catalogue = new MessageCatalogue('en');
        $catalogue->add(array('foo' => 'bar'));

        $tempDir = sys_get_temp_dir();
        $dumper = new YamlFileDumper();
        $dumper->dump($catalogue, array('path' => $tempDir));

        $this->assertEquals(file_get_contents(__DIR__.'/../fixtures/resources.yml'), file_get_contents($tempDir.'/messages.en.yml'));

        unlink($tempDir.'/messages.en.yml');
    }
}
PK��Zub/��Ttest/Translation/Symfony/Component/Translation/Tests/Dumper/IcuResFileDumperTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Dumper;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Dumper\IcuResFileDumper;

class IcuResFileDumperTest extends \PHPUnit_Framework_TestCase
{
    public function testDump()
    {
        if (!extension_loaded('mbstring')) {
            $this->markTestSkipped('This test requires mbstring to work.');
        }

        $catalogue = new MessageCatalogue('en');
        $catalogue->add(array('foo' => 'bar'));

        $tempDir = sys_get_temp_dir() . '/IcuResFileDumperTest';
        mkdir($tempDir);
        $dumper = new IcuResFileDumper();
        $dumper->dump($catalogue, array('path' => $tempDir));

        $this->assertEquals(file_get_contents(__DIR__.'/../fixtures/resourcebundle/res/en.res'), file_get_contents($tempDir.'/messages/en.res'));

        unlink($tempDir.'/messages/en.res');
        rmdir($tempDir.'/messages');
        rmdir($tempDir);
    }
}
PK��Z�����Qtest/Translation/Symfony/Component/Translation/Tests/Dumper/CsvFileDumperTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Dumper;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Dumper\CsvFileDumper;

class CsvFileDumperTest extends \PHPUnit_Framework_TestCase
{
    public function testDump()
    {
        $catalogue = new MessageCatalogue('en');
        $catalogue->add(array('foo' => 'bar', 'bar' => 'foo
foo', 'foo;foo' => 'bar'));

        $tempDir = sys_get_temp_dir();
        $dumper = new CsvFileDumper();
        $dumper->dump($catalogue, array('path' => $tempDir));

        $this->assertEquals(file_get_contents(__DIR__.'/../fixtures/valid.csv'), file_get_contents($tempDir.'/messages.en.csv'));

        unlink($tempDir.'/messages.en.csv');
    }
}
PK��Z�����Ptest/Translation/Symfony/Component/Translation/Tests/Dumper/MoFileDumperTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Dumper;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Dumper\MoFileDumper;

class MoFileDumperTest extends \PHPUnit_Framework_TestCase
{
    public function testDump()
    {
        $catalogue = new MessageCatalogue('en');
        $catalogue->add(array('foo' => 'bar'));

        $tempDir = sys_get_temp_dir();
        $dumper = new MoFileDumper();
        $dumper->dump($catalogue, array('path' => $tempDir));
        $this->assertEquals(file_get_contents(__DIR__.'/../fixtures/resources.mo'), file_get_contents($tempDir.'/messages.en.mo'));

        unlink($tempDir.'/messages.en.mo');
    }
}
PK��Z�BY���Ptest/Translation/Symfony/Component/Translation/Tests/Dumper/QtFileDumperTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Dumper;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Dumper\QtFileDumper;

class QtFileDumperTest extends \PHPUnit_Framework_TestCase
{
    public function testDump()
    {
        $catalogue = new MessageCatalogue('en');
        $catalogue->add(array('foo' => 'bar'), 'resources');

        $tempDir = sys_get_temp_dir();
        $dumper = new QtFileDumper();
        $dumper->dump($catalogue, array('path' => $tempDir));

        $this->assertEquals(file_get_contents(__DIR__.'/../fixtures/resources.ts'), file_get_contents($tempDir.'/resources.en.ts'));

        unlink($tempDir.'/resources.en.ts');
    }
}
PK��Z��IIRtest/Translation/Symfony/Component/Translation/Tests/Dumper/JsonFileDumperTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Dumper;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Dumper\JsonFileDumper;

class JsonFileDumperTest extends \PHPUnit_Framework_TestCase
{
    public function testDump()
    {
        if (version_compare(PHP_VERSION, '5.4.0', '<')) {
            $this->markTestIncomplete('PHP below 5.4 doesn\'t support JSON pretty printing');
        }

        $catalogue = new MessageCatalogue('en');
        $catalogue->add(array('foo' => 'bar'));

        $tempDir = sys_get_temp_dir();
        $dumper = new JsonFileDumper();
        $dumper->dump($catalogue, array('path' => $tempDir));

        $this->assertEquals(file_get_contents(__DIR__.'/../fixtures/resources.json'), file_get_contents($tempDir.'/messages.en.json'));

        unlink($tempDir.'/messages.en.json');
    }
}
PK��Z&��ݙ�Ptest/Translation/Symfony/Component/Translation/Tests/Dumper/PoFileDumperTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Dumper;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Dumper\PoFileDumper;

class PoFileDumperTest extends \PHPUnit_Framework_TestCase
{
    public function testDump()
    {
        $catalogue = new MessageCatalogue('en');
        $catalogue->add(array('foo' => 'bar'));

        $tempDir = sys_get_temp_dir();
        $dumper = new PoFileDumper();
        $dumper->dump($catalogue, array('path' => $tempDir));
        $this->assertEquals(file_get_contents(__DIR__.'/../fixtures/resources.po'), file_get_contents($tempDir.'/messages.en.po'));

        unlink($tempDir.'/messages.en.po');
    }
}
PK��Z8^�k��Stest/Translation/Symfony/Component/Translation/Tests/Loader/XliffFileLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Loader;

use Symfony\Component\Translation\Loader\XliffFileLoader;
use Symfony\Component\Config\Resource\FileResource;

class XliffFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testLoad()
    {
        $loader = new XliffFileLoader();
        $resource = __DIR__.'/../fixtures/resources.xlf';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    public function testLoadWithResname()
    {
        $loader = new XliffFileLoader();
        $catalogue = $loader->load(__DIR__.'/../fixtures/resname.xlf', 'en', 'domain1');

        $this->assertEquals(array('foo' => 'bar', 'bar' => 'baz', 'baz' => 'foo'), $catalogue->all('domain1'));
    }

    public function testIncompleteResource()
    {
        $loader = new XliffFileLoader();
        $catalogue = $loader->load(__DIR__.'/../fixtures/resources.xlf', 'en', 'domain1');

        $this->assertEquals(array('foo' => 'bar', 'key' => '', 'test' => 'with'), $catalogue->all('domain1'));
        $this->assertFalse($catalogue->has('extra', 'domain1'));
    }

    public function testEncoding()
    {
        if (!function_exists('iconv') && !function_exists('mb_convert_encoding')) {
            $this->markTestSkipped('The iconv and mbstring extensions are not available.');
        }

        $loader = new XliffFileLoader();
        $catalogue = $loader->load(__DIR__.'/../fixtures/encoding.xlf', 'en', 'domain1');

        $this->assertEquals(utf8_decode('föö'), $catalogue->get('bar', 'domain1'));
        $this->assertEquals(utf8_decode('bär'), $catalogue->get('foo', 'domain1'));
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
     */
    public function testLoadInvalidResource()
    {
        $loader = new XliffFileLoader();
        $loader->load(__DIR__.'/../fixtures/resources.php', 'en', 'domain1');
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
     */
    public function testLoadResourceDoesNotValidate()
    {
        $loader = new XliffFileLoader();
        $loader->load(__DIR__.'/../fixtures/non-valid.xlf', 'en', 'domain1');
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
     */
    public function testLoadNonExistingResource()
    {
        $loader = new XliffFileLoader();
        $resource = __DIR__.'/../fixtures/non-existing.xlf';
        $loader->load($resource, 'en', 'domain1');
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
     */
    public function testLoadThrowsAnExceptionIfFileNotLocal()
    {
        $loader = new XliffFileLoader();
        $resource = 'http://example.com/resources.xlf';
        $loader->load($resource, 'en', 'domain1');
    }

    /**
     * @expectedException        \Symfony\Component\Translation\Exception\InvalidResourceException
     * @expectedExceptionMessage Document types are not allowed.
     */
    public function testDocTypeIsNotAllowed()
    {
        $loader = new XliffFileLoader();
        $loader->load(__DIR__.'/../fixtures/withdoctype.xlf', 'en', 'domain1');
    }

    public function testParseEmptyFile()
    {
        $loader = new XliffFileLoader();
        $resource = __DIR__.'/../fixtures/empty.xlf';
        $this->setExpectedException('Symfony\Component\Translation\Exception\InvalidResourceException', sprintf('Unable to load "%s":', $resource));
        $loader->load($resource, 'en', 'domain1');
    }
}
PK��Z��|=��Ptest/Translation/Symfony/Component/Translation/Tests/Loader/QtFileLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Loader;

use Symfony\Component\Translation\Loader\QtFileLoader;
use Symfony\Component\Config\Resource\FileResource;

class QtFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testLoad()
    {
        $loader = new QtFileLoader();
        $resource = __DIR__.'/../fixtures/resources.ts';
        $catalogue = $loader->load($resource, 'en', 'resources');

        $this->assertEquals(array('foo' => 'bar'), $catalogue->all('resources'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
     */
    public function testLoadNonExistingResource()
    {
        $loader = new QtFileLoader();
        $resource = __DIR__.'/../fixtures/non-existing.ts';
        $loader->load($resource, 'en', 'domain1');
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
     */
    public function testLoadNonLocalResource()
    {
        $loader = new QtFileLoader();
        $resource = 'http://domain1.com/resources.ts';
        $loader->load($resource, 'en', 'domain1');
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
     */
    public function testLoadInvalidResource()
    {
        $loader = new QtFileLoader();
        $resource = __DIR__.'/../fixtures/invalid-xml-resources.xlf';
        $loader->load($resource, 'en', 'domain1');
    }

    public function testLoadEmptyResource()
    {
        $loader = new QtFileLoader();
        $resource = __DIR__.'/../fixtures/empty.xlf';
        $this->setExpectedException('Symfony\Component\Translation\Exception\InvalidResourceException', sprintf('Unable to load "%s".', $resource));
        $loader->load($resource, 'en', 'domain1');
    }
}
PK��Z���3Qtest/Translation/Symfony/Component/Translation/Tests/Loader/LocalizedTestCase.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Loader;

abstract class LocalizedTestCase extends \PHPUnit_Framework_TestCase
{
    protected function setUp()
    {
        if (!extension_loaded('intl')) {
            $this->markTestSkipped('The "intl" extension is not available');
        }
    }
}
PK��Z���Qtest/Translation/Symfony/Component/Translation/Tests/Loader/PhpFileLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Loader;

use Symfony\Component\Translation\Loader\PhpFileLoader;
use Symfony\Component\Config\Resource\FileResource;

class PhpFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testLoad()
    {
        $loader = new PhpFileLoader();
        $resource = __DIR__.'/../fixtures/resources.php';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array('foo' => 'bar'), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
     */
    public function testLoadNonExistingResource()
    {
        $loader = new PhpFileLoader();
        $resource = __DIR__.'/../fixtures/non-existing.php';
        $loader->load($resource, 'en', 'domain1');
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
     */
    public function testLoadThrowsAnExceptionIfFileNotLocal()
    {
        $loader = new PhpFileLoader();
        $resource = 'http://example.com/resources.php';
        $loader->load($resource, 'en', 'domain1');
    }
}
PK��Z~�		Rtest/Translation/Symfony/Component/Translation/Tests/Loader/YamlFileLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Loader;

use Symfony\Component\Translation\Loader\YamlFileLoader;
use Symfony\Component\Config\Resource\FileResource;

class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testLoad()
    {
        $loader = new YamlFileLoader();
        $resource = __DIR__.'/../fixtures/resources.yml';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array('foo' => 'bar'), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    public function testLoadDoesNothingIfEmpty()
    {
        $loader = new YamlFileLoader();
        $resource = __DIR__.'/../fixtures/empty.yml';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array(), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
     */
    public function testLoadNonExistingResource()
    {
        $loader = new YamlFileLoader();
        $resource = __DIR__.'/../fixtures/non-existing.yml';
        $loader->load($resource, 'en', 'domain1');
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
     */
    public function testLoadThrowsAnExceptionIfFileNotLocal()
    {
        $loader = new YamlFileLoader();
        $resource = 'http://example.com/resources.yml';
        $loader->load($resource, 'en', 'domain1');
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
     */
    public function testLoadThrowsAnExceptionIfNotAnArray()
    {
        $loader = new YamlFileLoader();
        $resource = __DIR__.'/../fixtures/non-valid.yml';
        $loader->load($resource, 'en', 'domain1');
    }
}
PK��Z�$X

Ptest/Translation/Symfony/Component/Translation/Tests/Loader/PoFileLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Loader;

use Symfony\Component\Translation\Loader\PoFileLoader;
use Symfony\Component\Config\Resource\FileResource;

class PoFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testLoad()
    {
        $loader = new PoFileLoader();
        $resource = __DIR__.'/../fixtures/resources.po';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array('foo' => 'bar'), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    public function testLoadPlurals()
    {
        $loader = new PoFileLoader();
        $resource = __DIR__.'/../fixtures/plurals.po';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array('foo' => 'bar', 'foos' => 'bar|bars'), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    public function testLoadDoesNothingIfEmpty()
    {
        $loader = new PoFileLoader();
        $resource = __DIR__.'/../fixtures/empty.po';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array(), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
     */
    public function testLoadNonExistingResource()
    {
        $loader = new PoFileLoader();
        $resource = __DIR__.'/../fixtures/non-existing.po';
        $loader->load($resource, 'en', 'domain1');
    }

    public function testLoadEmptyTranslation()
    {
        $loader = new PoFileLoader();
        $resource = __DIR__.'/../fixtures/empty-translation.po';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array('foo' => ''), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }
}
PK��Z[����Qtest/Translation/Symfony/Component/Translation/Tests/Loader/CsvFileLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Loader;

use Symfony\Component\Translation\Loader\CsvFileLoader;
use Symfony\Component\Config\Resource\FileResource;

class CsvFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testLoad()
    {
        $loader = new CsvFileLoader();
        $resource = __DIR__.'/../fixtures/resources.csv';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array('foo' => 'bar'), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    public function testLoadDoesNothingIfEmpty()
    {
        $loader = new CsvFileLoader();
        $resource = __DIR__.'/../fixtures/empty.csv';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array(), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
     */
    public function testLoadNonExistingResource()
    {
        $loader = new CsvFileLoader();
        $resource = __DIR__.'/../fixtures/not-exists.csv';
        $loader->load($resource, 'en', 'domain1');
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
     */
    public function testLoadNonLocalResource()
    {
        $loader = new CsvFileLoader();
        $resource = 'http://example.com/resources.csv';
        $loader->load($resource, 'en', 'domain1');
    }
}
PK��Z/�݂�Qtest/Translation/Symfony/Component/Translation/Tests/Loader/IniFileLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Loader;

use Symfony\Component\Translation\Loader\IniFileLoader;
use Symfony\Component\Config\Resource\FileResource;

class IniFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testLoad()
    {
        $loader = new IniFileLoader();
        $resource = __DIR__.'/../fixtures/resources.ini';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array('foo' => 'bar'), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    public function testLoadDoesNothingIfEmpty()
    {
        $loader = new IniFileLoader();
        $resource = __DIR__.'/../fixtures/empty.ini';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array(), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
     */
    public function testLoadNonExistingResource()
    {
        $loader = new IniFileLoader();
        $resource = __DIR__.'/../fixtures/non-existing.ini';
        $loader->load($resource, 'en', 'domain1');
    }
}
PK��Z��j��Ttest/Translation/Symfony/Component/Translation/Tests/Loader/IcuResFileLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Loader;

use Symfony\Component\Translation\Loader\IcuResFileLoader;
use Symfony\Component\Config\Resource\DirectoryResource;

class IcuResFileLoaderTest extends LocalizedTestCase
{
    protected function setUp()
    {
        if (!extension_loaded('intl')) {
            $this->markTestSkipped('This test requires intl extension to work.');
        }
    }

    public function testLoad()
    {
        // resource is build using genrb command
        $loader = new IcuResFileLoader();
        $resource = __DIR__.'/../fixtures/resourcebundle/res';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array('foo' => 'bar'), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new DirectoryResource($resource)), $catalogue->getResources());
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
     */
    public function testLoadNonExistingResource()
    {
        $loader = new IcuResFileLoader();
        $loader->load(__DIR__.'/../fixtures/non-existing.txt', 'en', 'domain1');
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
     */
    public function testLoadInvalidResource()
    {
        $loader = new IcuResFileLoader();
        $loader->load(__DIR__.'/../fixtures/resourcebundle/corrupted', 'en', 'domain1');
    }
}
PK��ZP�e��Rtest/Translation/Symfony/Component/Translation/Tests/Loader/JsonFileLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Loader;

use Symfony\Component\Translation\Loader\JsonFileLoader;
use Symfony\Component\Config\Resource\FileResource;

class JsonFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    protected function setUp()
    {
        if (!class_exists('Symfony\Component\Config\Loader\Loader')) {
            $this->markTestSkipped('The "Config" component is not available');
        }
    }

    public function testLoad()
    {
        $loader = new JsonFileLoader();
        $resource = __DIR__.'/../fixtures/resources.json';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array('foo' => 'bar'), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    public function testLoadDoesNothingIfEmpty()
    {
        $loader = new JsonFileLoader();
        $resource = __DIR__.'/../fixtures/empty.json';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array(), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
     */
    public function testLoadNonExistingResource()
    {
        $loader = new JsonFileLoader();
        $resource = __DIR__.'/../fixtures/non-existing.json';
        $loader->load($resource, 'en', 'domain1');
    }

    /**
     * @expectedException           \Symfony\Component\Translation\Exception\InvalidResourceException
     * @expectedExceptionMessage    Error parsing JSON - Syntax error, malformed JSON
     */
    public function testParseException()
    {
        $loader = new JsonFileLoader();
        $resource = __DIR__.'/../fixtures/malformed.json';
        $loader->load($resource, 'en', 'domain1');
    }
}
PK��Z����Ptest/Translation/Symfony/Component/Translation/Tests/Loader/MoFileLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Loader;

use Symfony\Component\Translation\Loader\MoFileLoader;
use Symfony\Component\Config\Resource\FileResource;

class MoFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testLoad()
    {
        $loader = new MoFileLoader();
        $resource = __DIR__.'/../fixtures/resources.mo';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array('foo' => 'bar'), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    public function testLoadPlurals()
    {
        $loader = new MoFileLoader();
        $resource = __DIR__.'/../fixtures/plurals.mo';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array('foo' => 'bar', 'foos' => '{0} bar|{1} bars'), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
     */
    public function testLoadNonExistingResource()
    {
        $loader = new MoFileLoader();
        $resource = __DIR__.'/../fixtures/non-existing.mo';
        $loader->load($resource, 'en', 'domain1');
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
     */
    public function testLoadInvalidResource()
    {
        $loader = new MoFileLoader();
        $resource = __DIR__.'/../fixtures/empty.mo';
        $loader->load($resource, 'en', 'domain1');
    }
}
PK��Z�)�	�	�	Ttest/Translation/Symfony/Component/Translation/Tests/Loader/IcuDatFileLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Loader;

use Symfony\Component\Translation\Loader\IcuDatFileLoader;
use Symfony\Component\Config\Resource\FileResource;

class IcuDatFileLoaderTest extends LocalizedTestCase
{
    protected function setUp()
    {
        if (!extension_loaded('intl')) {
            $this->markTestSkipped('This test requires intl extension to work.');
        }
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
     */
    public function testLoadInvalidResource()
    {
        $loader = new IcuDatFileLoader();
        $loader->load(__DIR__.'/../fixtures/resourcebundle/corrupted/resources', 'es', 'domain2');
    }

    public function testDatEnglishLoad()
    {
        // bundled resource is build using pkgdata command which at least in ICU 4.2 comes in extremely! buggy form
        // you must specify an temporary build directory which is not the same as current directory and
        // MUST reside on the same partition. pkgdata -p resources -T /srv -d.packagelist.txt
        $loader = new IcuDatFileLoader();
        $resource = __DIR__.'/../fixtures/resourcebundle/dat/resources';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array('symfony' => 'Symfony 2 is great'), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource.'.dat')), $catalogue->getResources());
    }

    public function testDatFrenchLoad()
    {
        $loader = new IcuDatFileLoader();
        $resource = __DIR__.'/../fixtures/resourcebundle/dat/resources';
        $catalogue = $loader->load($resource, 'fr', 'domain1');

        $this->assertEquals(array('symfony' => 'Symfony 2 est génial'), $catalogue->all('domain1'));
        $this->assertEquals('fr', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource.'.dat')), $catalogue->getResources());
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
     */
    public function testLoadNonExistingResource()
    {
        $loader = new IcuDatFileLoader();
        $loader->load(__DIR__.'/../fixtures/non-existing.txt', 'en', 'domain1');
    }
}
PK��ZM��Mtest/Translation/Symfony/Component/Translation/Tests/MessageCatalogueTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests;

use Symfony\Component\Translation\MessageCatalogue;

class MessageCatalogueTest extends \PHPUnit_Framework_TestCase
{
    public function testGetLocale()
    {
        $catalogue = new MessageCatalogue('en');

        $this->assertEquals('en', $catalogue->getLocale());
    }

    public function testGetDomains()
    {
        $catalogue = new MessageCatalogue('en', array('domain1' => array(), 'domain2' => array()));

        $this->assertEquals(array('domain1', 'domain2'), $catalogue->getDomains());
    }

    public function testAll()
    {
        $catalogue = new MessageCatalogue('en', $messages = array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));

        $this->assertEquals(array('foo' => 'foo'), $catalogue->all('domain1'));
        $this->assertEquals(array(), $catalogue->all('domain88'));
        $this->assertEquals($messages, $catalogue->all());
    }

    public function testHas()
    {
        $catalogue = new MessageCatalogue('en', array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));

        $this->assertTrue($catalogue->has('foo', 'domain1'));
        $this->assertFalse($catalogue->has('bar', 'domain1'));
        $this->assertFalse($catalogue->has('foo', 'domain88'));
    }

    public function testGetSet()
    {
        $catalogue = new MessageCatalogue('en', array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));
        $catalogue->set('foo1', 'foo1', 'domain1');

        $this->assertEquals('foo', $catalogue->get('foo', 'domain1'));
        $this->assertEquals('foo1', $catalogue->get('foo1', 'domain1'));
    }

    public function testAdd()
    {
        $catalogue = new MessageCatalogue('en', array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));
        $catalogue->add(array('foo1' => 'foo1'), 'domain1');

        $this->assertEquals('foo', $catalogue->get('foo', 'domain1'));
        $this->assertEquals('foo1', $catalogue->get('foo1', 'domain1'));

        $catalogue->add(array('foo' => 'bar'), 'domain1');
        $this->assertEquals('bar', $catalogue->get('foo', 'domain1'));
        $this->assertEquals('foo1', $catalogue->get('foo1', 'domain1'));

        $catalogue->add(array('foo' => 'bar'), 'domain88');
        $this->assertEquals('bar', $catalogue->get('foo', 'domain88'));
    }

    public function testReplace()
    {
        $catalogue = new MessageCatalogue('en', array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));
        $catalogue->replace($messages = array('foo1' => 'foo1'), 'domain1');

        $this->assertEquals($messages, $catalogue->all('domain1'));
    }

    public function testAddCatalogue()
    {
        $r = $this->getMock('Symfony\Component\Config\Resource\ResourceInterface');
        $r->expects($this->any())->method('__toString')->will($this->returnValue('r'));

        $r1 = $this->getMock('Symfony\Component\Config\Resource\ResourceInterface');
        $r1->expects($this->any())->method('__toString')->will($this->returnValue('r1'));

        $catalogue = new MessageCatalogue('en', array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));
        $catalogue->addResource($r);

        $catalogue1 = new MessageCatalogue('en', array('domain1' => array('foo1' => 'foo1')));
        $catalogue1->addResource($r1);

        $catalogue->addCatalogue($catalogue1);

        $this->assertEquals('foo', $catalogue->get('foo', 'domain1'));
        $this->assertEquals('foo1', $catalogue->get('foo1', 'domain1'));

        $this->assertEquals(array($r, $r1), $catalogue->getResources());
    }

    public function testAddFallbackCatalogue()
    {
        $r = $this->getMock('Symfony\Component\Config\Resource\ResourceInterface');
        $r->expects($this->any())->method('__toString')->will($this->returnValue('r'));

        $r1 = $this->getMock('Symfony\Component\Config\Resource\ResourceInterface');
        $r1->expects($this->any())->method('__toString')->will($this->returnValue('r1'));

        $catalogue = new MessageCatalogue('en_US', array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));
        $catalogue->addResource($r);

        $catalogue1 = new MessageCatalogue('en', array('domain1' => array('foo' => 'bar', 'foo1' => 'foo1')));
        $catalogue1->addResource($r1);

        $catalogue->addFallbackCatalogue($catalogue1);

        $this->assertEquals('foo', $catalogue->get('foo', 'domain1'));
        $this->assertEquals('foo1', $catalogue->get('foo1', 'domain1'));

        $this->assertEquals(array($r, $r1), $catalogue->getResources());
    }

    /**
     * @expectedException \LogicException
     */
    public function testAddFallbackCatalogueWithCircularReference()
    {
        $main = new MessageCatalogue('en_US');
        $fallback = new MessageCatalogue('fr_FR');

        $fallback->addFallbackCatalogue($main);
        $main->addFallbackCatalogue($fallback);
    }

    /**
     * @expectedException \LogicException
     */
    public function testAddCatalogueWhenLocaleIsNotTheSameAsTheCurrentOne()
    {
        $catalogue = new MessageCatalogue('en');
        $catalogue->addCatalogue(new MessageCatalogue('fr', array()));
    }

    public function testGetAddResource()
    {
        $catalogue = new MessageCatalogue('en');
        $r = $this->getMock('Symfony\Component\Config\Resource\ResourceInterface');
        $r->expects($this->any())->method('__toString')->will($this->returnValue('r'));
        $catalogue->addResource($r);
        $catalogue->addResource($r);
        $r1 = $this->getMock('Symfony\Component\Config\Resource\ResourceInterface');
        $r1->expects($this->any())->method('__toString')->will($this->returnValue('r1'));
        $catalogue->addResource($r1);

        $this->assertEquals(array($r, $r1), $catalogue->getResources());
    }

    public function testMetadataDelete()
    {
        $catalogue = new MessageCatalogue('en');
        $this->assertEquals(array(), $catalogue->getMetadata('', ''), 'Metadata is empty');
        $catalogue->deleteMetadata('key', 'messages');
        $catalogue->deleteMetadata('', 'messages');
        $catalogue->deleteMetadata();
    }

    public function testMetadataSetGetDelete()
    {
        $catalogue = new MessageCatalogue('en');
        $catalogue->setMetadata('key', 'value');
        $this->assertEquals('value', $catalogue->getMetadata('key', 'messages'), "Metadata 'key' = 'value'");

        $catalogue->setMetadata('key2', array());
        $this->assertEquals(array(), $catalogue->getMetadata('key2', 'messages'), 'Metadata key2 is array');

        $catalogue->deleteMetadata('key2', 'messages');
        $this->assertEquals(null, $catalogue->getMetadata('key2', 'messages'), 'Metadata key2 should is deleted.');

        $catalogue->deleteMetadata('key2', 'domain');
        $this->assertEquals(null, $catalogue->getMetadata('key2', 'domain'), 'Metadata key2 should is deleted.');
    }

    public function testMetadataMerge()
    {
        $cat1 = new MessageCatalogue('en');
        $cat1->setMetadata('a', 'b');
        $this->assertEquals(array('messages' => array('a' => 'b')), $cat1->getMetadata('', ''), 'Cat1 contains messages metadata.');

        $cat2 = new MessageCatalogue('en');
        $cat2->setMetadata('b', 'c', 'domain');
        $this->assertEquals(array('domain' => array('b' => 'c')), $cat2->getMetadata('', ''), 'Cat2 contains domain metadata.');

        $cat1->addCatalogue($cat2);
        $this->assertEquals(array('messages' => array('a' => 'b'), 'domain' => array('b' => 'c')), $cat1->getMetadata('', ''), 'Cat1 contains merged metadata.');
    }
}
PK��Z���  Ltest/Translation/Symfony/Component/Translation/Tests/MessageSelectorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests;

use Symfony\Component\Translation\MessageSelector;

class MessageSelectorTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getChooseTests
     */
    public function testChoose($expected, $id, $number)
    {
        $selector = new MessageSelector();

        $this->assertEquals($expected, $selector->choose($id, $number, 'en'));
    }

    public function testReturnMessageIfExactlyOneStandardRuleIsGiven()
    {
        $selector = new MessageSelector();

        $this->assertEquals('There are two apples', $selector->choose('There are two apples', 2, 'en'));
    }

    /**
     * @dataProvider getNonMatchingMessages
     * @expectedException \InvalidArgumentException
     */
    public function testThrowExceptionIfMatchingMessageCannotBeFound($id, $number)
    {
        $selector = new MessageSelector();

        $selector->choose($id, $number, 'en');
    }

    public function getNonMatchingMessages()
    {
        return array(
            array('{0} There are no apples|{1} There is one apple', 2),
            array('{1} There is one apple|]1,Inf] There are %count% apples', 0),
            array('{1} There is one apple|]2,Inf] There are %count% apples', 2),
            array('{0} There are no apples|There is one apple', 2),
        );
    }

    public function getChooseTests()
    {
        return array(
            array('There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0),
            array('There are no apples', '{0}     There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0),
            array('There are no apples', '{0}There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0),

            array('There is one apple', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 1),

            array('There are %count% apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10),
            array('There are %count% apples', '{0} There are no apples|{1} There is one apple|]1,Inf]There are %count% apples', 10),
            array('There are %count% apples', '{0} There are no apples|{1} There is one apple|]1,Inf]     There are %count% apples', 10),

            array('There are %count% apples', 'There is one apple|There are %count% apples', 0),
            array('There is one apple', 'There is one apple|There are %count% apples', 1),
            array('There are %count% apples', 'There is one apple|There are %count% apples', 10),

            array('There are %count% apples', 'one: There is one apple|more: There are %count% apples', 0),
            array('There is one apple', 'one: There is one apple|more: There are %count% apples', 1),
            array('There are %count% apples', 'one: There is one apple|more: There are %count% apples', 10),

            array('There are no apples', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 0),
            array('There is one apple', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 1),
            array('There are %count% apples', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 10),

            array('', '{0}|{1} There is one apple|]1,Inf] There are %count% apples', 0),
            array('', '{0} There are no apples|{1}|]1,Inf] There are %count% apples', 1),

            // Indexed only tests which are Gettext PoFile* compatible strings.
            array('There are %count% apples', 'There is one apple|There are %count% apples', 0),
            array('There is one apple', 'There is one apple|There are %count% apples', 1),
            array('There are %count% apples', 'There is one apple|There are %count% apples', 2),

            // Tests for float numbers
            array('There is almost one apple', '{0} There are no apples|]0,1[ There is almost one apple|{1} There is one apple|[1,Inf] There is more than one apple', 0.7),
            array('There is one apple', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 1),
            array('There is more than one apple', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 1.7),
            array('There are no apples', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0),
            array('There are no apples', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0.0),
            array('There are no apples', '{0.0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0),
        );
    }
}
PK��Z��W44Jtest/Translation/Symfony/Component/Translation/Tests/fixtures/resources.monu�[�����$,-1foobarPK��Z!f����Jtest/Translation/Symfony/Component/Translation/Tests/fixtures/resources.ponu�[���msgid ""
msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: en\n"

msgid "foo"
msgstr "bar"PK��Z=BsRtest/Translation/Symfony/Component/Translation/Tests/fixtures/empty-translation.ponu�[���msgid "foo"
msgstr ""

PK��ZGtest/Translation/Symfony/Component/Translation/Tests/fixtures/empty.ininu�[���PK��ZYڸCQtest/Translation/Symfony/Component/Translation/Tests/fixtures/resources-clean.xlfnu�[���<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
  <file source-language="en" datatype="plaintext" original="file.ext">
    <body>
      <trans-unit id="acbd18db4cc2f85cedef654fccc4a4d8" resname="foo">
        <source>foo</source>
        <target>bar</target>
      </trans-unit>
      <trans-unit id="3c6e0b8a9c15224a8228b9a98ca1531d" resname="key">
        <source>key</source>
        <target></target>
      </trans-unit>
    </body>
  </file>
</xliff>
PK��Z�:�++Ktest/Translation/Symfony/Component/Translation/Tests/fixtures/resources.phpnu�[���<?php

return array (
  'foo' => 'bar',
);
PK��ZGtest/Translation/Symfony/Component/Translation/Tests/fixtures/empty.ymlnu�[���PK��ZHtest/Translation/Symfony/Component/Translation/Tests/fixtures/empty.jsonnu�[���PK��ZY���44Itest/Translation/Symfony/Component/Translation/Tests/fixtures/resname.xlfnu�[���<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
  <file source-language="en" datatype="plaintext" original="file.ext">
    <body>
      <trans-unit id="1" resname="foo">
        <source></source>
        <target>bar</target>
      </trans-unit>
      <trans-unit id="2" resname="bar">
        <source>bar source</source>
        <target>baz</target>
      </trans-unit>
      <trans-unit id="3">
        <source>baz</source>
        <target>foo</target>
      </trans-unit>
    </body>
  </file>
</xliff>
PK��ZGtest/Translation/Symfony/Component/Translation/Tests/fixtures/empty.xlfnu�[���PK��Z;.�BBHtest/Translation/Symfony/Component/Translation/Tests/fixtures/plurals.ponu�[���msgid "foo"
msgid_plural "foos"
msgstr[0] "bar"
msgstr[1] "bars"

PK��Z�ߞLtest/Translation/Symfony/Component/Translation/Tests/fixtures/malformed.jsonnu�[���{
    "foo": "bar" "
}PK��Z�.�zzKtest/Translation/Symfony/Component/Translation/Tests/fixtures/resources.xlfnu�[���<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
  <file source-language="en" datatype="plaintext" original="file.ext">
    <body>
      <trans-unit id="1">
        <source>foo</source>
        <target>bar</target>
      </trans-unit>
      <trans-unit id="2">
        <source>extra</source>
      </trans-unit>
      <trans-unit id="3">
        <source>key</source>
        <target></target>
      </trans-unit>
      <trans-unit id="4">
        <source>test</source>
        <target>with</target>
        <note>note</note>
      </trans-unit>
    </body>
  </file>
</xliff>
PK��Z�e2~Ktest/Translation/Symfony/Component/Translation/Tests/fixtures/non-valid.ymlnu�[���foo
PK��Z�'�F

Ktest/Translation/Symfony/Component/Translation/Tests/fixtures/resources.ininu�[���foo="bar"
PK��Z� TTKtest/Translation/Symfony/Component/Translation/Tests/fixtures/non-valid.xlfnu�[���<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit>
                <source>foo</source>
                <target>bar</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��ZFtest/Translation/Symfony/Component/Translation/Tests/fixtures/empty.ponu�[���PK��ZGtest/Translation/Symfony/Component/Translation/Tests/fixtures/empty.csvnu�[���PK��Z*֔�JJHtest/Translation/Symfony/Component/Translation/Tests/fixtures/plurals.monu�[�����$,8AfoofoosbarbarsPK��Z+�L�TTWtest/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/res/en.resnu�[��� �'ResB 

foobarPK��Zw˦(||Wtest/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/fr.resnu�[��� �'ResB 	symfonySymfony 2 est g�nial��	PK��ZX��**Wtest/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/fr.txtnu�[���fr{
    symfony{"Symfony 2 est génial"}
}PK��ZrQ�``^test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/resources.datnu�[��� �'CmnD@%�resources/en.resresources/fr.res���������� �'ResB 	symfonySymfony 2 is great��	�������� �'ResB 	symfonySymfony 2 est g�nial��	����PK��Z�M�RxxWtest/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/en.resnu�[��� �'ResB 	symfonySymfony 2 is great��	PK��Z�g.�`test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/packagelist.txtnu�[���en.res
fr.res
PK��Z�25�''Wtest/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/en.txtnu�[���en{
    symfony{"Symfony 2 is great"}
}PK��Z��<�dtest/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/corrupted/resources.datnu�[���XXXPK��ZFtest/Translation/Symfony/Component/Translation/Tests/fixtures/empty.monu�[���PK��Z��jjMtest/Translation/Symfony/Component/Translation/Tests/fixtures/withdoctype.xlfnu�[���<?xml version="1.0"?>
<!DOCTYPE foo>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>foo</source>
                <target>bar</target>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z̉^2��Jtest/Translation/Symfony/Component/Translation/Tests/fixtures/encoding.xlfnu�[���<?xml version="1.0" encoding="ISO-8859-1"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
  <file source-language="en" datatype="plaintext" original="file.ext">
    <body>
      <trans-unit id="1" resname="foo">
        <source>foo</source>
        <target>b�r</target>
      </trans-unit>
      <trans-unit id="2" resname="bar">
        <source>bar</source>
        <target>f��</target>
      </trans-unit>
    </body>
  </file>
</xliff>
PK��Z�B$$Gtest/Translation/Symfony/Component/Translation/Tests/fixtures/valid.csvnu�[���foo;bar
bar;"foo
foo"
"foo;foo";bar
PK��Z����Ltest/Translation/Symfony/Component/Translation/Tests/fixtures/resources.jsonnu�[���{
    "foo": "bar"
}PK��Z�C(���Jtest/Translation/Symfony/Component/Translation/Tests/fixtures/resources.tsnu�[���<?xml version="1.0" encoding="utf-8"?>
<TS>
  <context>
    <name>resources</name>
    <message>
      <source>foo</source>
      <translation>bar</translation>
    </message>
  </context>
</TS>
PK��Z/�
��Wtest/Translation/Symfony/Component/Translation/Tests/fixtures/invalid-xml-resources.xlfnu�[���<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>foo</source>
                <target>bar
            </trans-unit>
            <trans-unit id="2">
                <source>extra</source>
            </trans-unit>
            <trans-unit id="3">
                <source>key</source>
                <target></target>
            </trans-unit>
            <trans-unit id="4">
                <source>test</source>
                <target>with</target>
                <note>note</note>
            </trans-unit>
        </body>
    </file>
</xliff>
PK��Z���		Ktest/Translation/Symfony/Component/Translation/Tests/fixtures/resources.ymlnu�[���foo: bar
PK��Z�D��``Ktest/Translation/Symfony/Component/Translation/Tests/fixtures/resources.csvnu�[���"foo"; "bar"
#"bar"; "foo"
"incorrect"; "number"; "columns"; "will"; "be"; "ignored"
"incorrect"PK��Z^C�	::?test/Translation/Symfony/Component/Translation/phpunit.xml.distnu�[���<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony Translation Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./vendor</directory>
                <directory>./Tests</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
PK��Z���LLEtest/Routing/Symfony/Component/Routing/Tests/Annotation/RouteTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Tests\Annotation;

use Symfony\Component\Routing\Annotation\Route;

class RouteTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \BadMethodCallException
     */
    public function testInvalidRouteParameter()
    {
        $route = new Route(array('foo' => 'bar'));
    }

    /**
     * @dataProvider getValidParameters
     */
    public function testRouteParameters($parameter, $value, $getter)
    {
        $route = new Route(array($parameter => $value));
        $this->assertEquals($route->$getter(), $value);
    }

    public function getValidParameters()
    {
        return array(
            array('value', '/Blog', 'getPattern'),
            array('value', '/Blog', 'getPath'),
            array('requirements', array('_method' => 'GET'), 'getRequirements'),
            array('options', array('compiler_class' => 'RouteCompiler'), 'getOptions'),
            array('name', 'blog_index', 'getName'),
            array('defaults', array('_controller' => 'MyBlogBundle:Blog:index'), 'getDefaults'),
            array('schemes', array('https'), 'getSchemes'),
            array('methods', array('GET', 'POST'), 'getMethods'),
            array('host', array('{locale}.example.com'), 'getHost'),
            array('condition', array('context.getMethod() == "GET"'), 'getCondition'),
        );
    }
}
PK��Z�%��])])Btest/Routing/Symfony/Component/Routing/Tests/RouteCompilerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Tests;

use Symfony\Component\Routing\Route;

class RouteCompilerTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider provideCompileData
     */
    public function testCompile($name, $arguments, $prefix, $regex, $variables, $tokens)
    {
        $r = new \ReflectionClass('Symfony\\Component\\Routing\\Route');
        $route = $r->newInstanceArgs($arguments);

        $compiled = $route->compile();
        $this->assertEquals($prefix, $compiled->getStaticPrefix(), $name.' (static prefix)');
        $this->assertEquals($regex, $compiled->getRegex(), $name.' (regex)');
        $this->assertEquals($variables, $compiled->getVariables(), $name.' (variables)');
        $this->assertEquals($tokens, $compiled->getTokens(), $name.' (tokens)');
    }

    public function provideCompileData()
    {
        return array(
            array(
                'Static route',
                array('/foo'),
                '/foo', '#^/foo$#s', array(), array(
                    array('text', '/foo'),
                )),

            array(
                'Route with a variable',
                array('/foo/{bar}'),
                '/foo', '#^/foo/(?P<bar>[^/]++)$#s', array('bar'), array(
                    array('variable', '/', '[^/]++', 'bar'),
                    array('text', '/foo'),
                )),

            array(
                'Route with a variable that has a default value',
                array('/foo/{bar}', array('bar' => 'bar')),
                '/foo', '#^/foo(?:/(?P<bar>[^/]++))?$#s', array('bar'), array(
                    array('variable', '/', '[^/]++', 'bar'),
                    array('text', '/foo'),
                )),

            array(
                'Route with several variables',
                array('/foo/{bar}/{foobar}'),
                '/foo', '#^/foo/(?P<bar>[^/]++)/(?P<foobar>[^/]++)$#s', array('bar', 'foobar'), array(
                    array('variable', '/', '[^/]++', 'foobar'),
                    array('variable', '/', '[^/]++', 'bar'),
                    array('text', '/foo'),
                )),

            array(
                'Route with several variables that have default values',
                array('/foo/{bar}/{foobar}', array('bar' => 'bar', 'foobar' => '')),
                '/foo', '#^/foo(?:/(?P<bar>[^/]++)(?:/(?P<foobar>[^/]++))?)?$#s', array('bar', 'foobar'), array(
                    array('variable', '/', '[^/]++', 'foobar'),
                    array('variable', '/', '[^/]++', 'bar'),
                    array('text', '/foo'),
                )),

            array(
                'Route with several variables but some of them have no default values',
                array('/foo/{bar}/{foobar}', array('bar' => 'bar')),
                '/foo', '#^/foo/(?P<bar>[^/]++)/(?P<foobar>[^/]++)$#s', array('bar', 'foobar'), array(
                    array('variable', '/', '[^/]++', 'foobar'),
                    array('variable', '/', '[^/]++', 'bar'),
                    array('text', '/foo'),
                )),

            array(
                'Route with an optional variable as the first segment',
                array('/{bar}', array('bar' => 'bar')),
                '', '#^/(?P<bar>[^/]++)?$#s', array('bar'), array(
                    array('variable', '/', '[^/]++', 'bar'),
                )),

            array(
                'Route with a requirement of 0',
                array('/{bar}', array('bar' => null), array('bar' => '0')),
                '', '#^/(?P<bar>0)?$#s', array('bar'), array(
                    array('variable', '/', '0', 'bar'),
                )),

            array(
                'Route with an optional variable as the first segment with requirements',
                array('/{bar}', array('bar' => 'bar'), array('bar' => '(foo|bar)')),
                '', '#^/(?P<bar>(foo|bar))?$#s', array('bar'), array(
                    array('variable', '/', '(foo|bar)', 'bar'),
                )),

            array(
                'Route with only optional variables',
                array('/{foo}/{bar}', array('foo' => 'foo', 'bar' => 'bar')),
                '', '#^/(?P<foo>[^/]++)?(?:/(?P<bar>[^/]++))?$#s', array('foo', 'bar'), array(
                    array('variable', '/', '[^/]++', 'bar'),
                    array('variable', '/', '[^/]++', 'foo'),
                )),

            array(
                'Route with a variable in last position',
                array('/foo-{bar}'),
                '/foo', '#^/foo\-(?P<bar>[^/]++)$#s', array('bar'), array(
                array('variable', '-', '[^/]++', 'bar'),
                array('text', '/foo'),
            )),

            array(
                'Route with nested placeholders',
                array('/{static{var}static}'),
                '/{static', '#^/\{static(?P<var>[^/]+)static\}$#s', array('var'), array(
                array('text', 'static}'),
                array('variable', '', '[^/]+', 'var'),
                array('text', '/{static'),
            )),

            array(
                'Route without separator between variables',
                array('/{w}{x}{y}{z}.{_format}', array('z' => 'default-z', '_format' => 'html'), array('y' => '(y|Y)')),
                '', '#^/(?P<w>[^/\.]+)(?P<x>[^/\.]+)(?P<y>(y|Y))(?:(?P<z>[^/\.]++)(?:\.(?P<_format>[^/]++))?)?$#s', array('w', 'x', 'y', 'z', '_format'), array(
                array('variable', '.', '[^/]++', '_format'),
                array('variable', '', '[^/\.]++', 'z'),
                array('variable', '', '(y|Y)', 'y'),
                array('variable', '', '[^/\.]+', 'x'),
                array('variable', '/', '[^/\.]+', 'w'),
            )),

            array(
                'Route with a format',
                array('/foo/{bar}.{_format}'),
                '/foo', '#^/foo/(?P<bar>[^/\.]++)\.(?P<_format>[^/]++)$#s', array('bar', '_format'), array(
                array('variable', '.', '[^/]++', '_format'),
                array('variable', '/', '[^/\.]++', 'bar'),
                array('text', '/foo'),
            )),
        );
    }

    /**
     * @expectedException \LogicException
     */
    public function testRouteWithSameVariableTwice()
    {
        $route = new Route('/{name}/{name}');

        $compiled = $route->compile();
    }

    /**
     * @dataProvider getNumericVariableNames
     * @expectedException \DomainException
     */
    public function testRouteWithNumericVariableName($name)
    {
        $route = new Route('/{'. $name.'}');
        $route->compile();
    }

    public function getNumericVariableNames()
    {
        return array(
           array('09'),
           array('123'),
           array('1e2')
        );
    }

    /**
     * @dataProvider provideCompileWithHostData
     */
    public function testCompileWithHost($name, $arguments, $prefix, $regex, $variables, $pathVariables, $tokens, $hostRegex, $hostVariables, $hostTokens)
    {
        $r = new \ReflectionClass('Symfony\\Component\\Routing\\Route');
        $route = $r->newInstanceArgs($arguments);

        $compiled = $route->compile();
        $this->assertEquals($prefix, $compiled->getStaticPrefix(), $name.' (static prefix)');
        $this->assertEquals($regex, str_replace(array("\n", ' '), '', $compiled->getRegex()), $name.' (regex)');
        $this->assertEquals($variables, $compiled->getVariables(), $name.' (variables)');
        $this->assertEquals($pathVariables, $compiled->getPathVariables(), $name.' (path variables)');
        $this->assertEquals($tokens, $compiled->getTokens(), $name.' (tokens)');
        $this->assertEquals($hostRegex, str_replace(array("\n", ' '), '', $compiled->getHostRegex()), $name.' (host regex)');
        $this->assertEquals($hostVariables, $compiled->getHostVariables(), $name.' (host variables)');
        $this->assertEquals($hostTokens, $compiled->getHostTokens(), $name.' (host tokens)');
    }

    public function provideCompileWithHostData()
    {
        return array(
            array(
                'Route with host pattern',
                array('/hello', array(), array(), array(), 'www.example.com'),
                '/hello', '#^/hello$#s', array(), array(), array(
                    array('text', '/hello'),
                ),
                '#^www\.example\.com$#s', array(), array(
                    array('text', 'www.example.com'),
                ),
            ),
            array(
                'Route with host pattern and some variables',
                array('/hello/{name}', array(), array(), array(), 'www.example.{tld}'),
                '/hello', '#^/hello/(?P<name>[^/]++)$#s', array('tld', 'name'), array('name'), array(
                    array('variable', '/', '[^/]++', 'name'),
                    array('text', '/hello'),
                ),
                '#^www\.example\.(?P<tld>[^\.]++)$#s', array('tld'), array(
                    array('variable', '.', '[^\.]++', 'tld'),
                    array('text', 'www.example'),
                ),
            ),
            array(
                'Route with variable at beginning of host',
                array('/hello', array(), array(), array(), '{locale}.example.{tld}'),
                '/hello', '#^/hello$#s', array('locale', 'tld'), array(), array(
                    array('text', '/hello'),
                ),
                '#^(?P<locale>[^\.]++)\.example\.(?P<tld>[^\.]++)$#s', array('locale', 'tld'), array(
                    array('variable', '.', '[^\.]++', 'tld'),
                    array('text', '.example'),
                    array('variable', '', '[^\.]++', 'locale'),
                ),
            ),
            array(
                'Route with host variables that has a default value',
                array('/hello', array('locale' => 'a', 'tld' => 'b'), array(), array(), '{locale}.example.{tld}'),
                '/hello', '#^/hello$#s', array('locale', 'tld'), array(), array(
                    array('text', '/hello'),
                ),
                '#^(?P<locale>[^\.]++)\.example\.(?P<tld>[^\.]++)$#s', array('locale', 'tld'), array(
                    array('variable', '.', '[^\.]++', 'tld'),
                    array('text', '.example'),
                    array('variable', '', '[^\.]++', 'locale'),
                ),
            ),
        );
    }
}
PK��Z1�d	nnMtest/Routing/Symfony/Component/Routing/Tests/Fixtures/CustomXmlFileLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Tests\Fixtures;

use Symfony\Component\Routing\Loader\XmlFileLoader;
use Symfony\Component\Config\Util\XmlUtils;

/**
 * XmlFileLoader with schema validation turned off
 */
class CustomXmlFileLoader extends XmlFileLoader
{
    protected function loadFile($file)
    {
        return XmlUtils::loadFile($file, function () { return true; });
    }
}
PK��ZCtest/Routing/Symfony/Component/Routing/Tests/Fixtures/annotated.phpnu�[���PK��Z?test/Routing/Symfony/Component/Routing/Tests/Fixtures/empty.ymlnu�[���PK��Z�/���Ftest/Routing/Symfony/Component/Routing/Tests/Fixtures/validpattern.ymlnu�[���blog_show:
    path:         /blog/{slug}
    defaults:     { _controller: "MyBundle:Blog:show" }
    host:         "{locale}.example.com"
    requirements: { 'locale': '\w+' }
    methods:      ['GET','POST','put','OpTiOnS']
    schemes:      ['https']
    condition:    'context.getMethod() == "GET"'
    options:
        compiler_class: RouteCompiler

blog_show_legacy:
    pattern:      /blog/{slug}
    defaults:     { _controller: "MyBundle:Blog:show" }
    host:         "{locale}.example.com"
    requirements: { '_method': 'GET|POST|put|OpTiOnS', _scheme: https, 'locale': '\w+' }
    condition:    'context.getMethod() == "GET"'
    options:
        compiler_class: RouteCompiler

blog_show_inherited:
    path:      /blog/{slug}
PK��Z�M��Ftest/Routing/Symfony/Component/Routing/Tests/Fixtures/validpattern.xmlnu�[���<?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">

    <route id="blog_show" path="/blog/{slug}" host="{locale}.example.com" methods="GET|POST  put,OpTiOnS" schemes="hTTps">
        <default key="_controller">MyBundle:Blog:show</default>
        <requirement key="locale">\w+</requirement>
        <option key="compiler_class">RouteCompiler</option>
        <condition>context.getMethod() == "GET"</condition>
    </route>

    <route id="blog_show_legacy" pattern="/blog/{slug}" host="{locale}.example.com">
        <default key="_controller">MyBundle:Blog:show</default>
        <default key="slug" xsi:nil="true" />
        <requirement key="_method">GET|POST|put|OpTiOnS</requirement>
        <requirement key="_scheme">hTTps</requirement>
        <requirement key="locale">\w+</requirement>
        <option key="compiler_class">RouteCompiler</option>
        <condition>context.getMethod() == "GET"</condition>
    </route>

    <route id="blog_show_inherited" path="/blog/{slug}" />
</routes>
PK��Z�/�$>>Vtest/Routing/Symfony/Component/Routing/Tests/Fixtures/nonesense_resource_plus_path.ymlnu�[���blog_show:
    resource: validpattern.yml
    path:     /test
PK��Z��==Ftest/Routing/Symfony/Component/Routing/Tests/Fixtures/nonvalidkeys.ymlnu�[���someroute:
  resource: path/to/some.yml
  name_prefix: test_
PK��Z�ie��Itest/Routing/Symfony/Component/Routing/Tests/Fixtures/namespaceprefix.xmlnu�[���<?xml version="1.0" encoding="UTF-8" ?>

<r:routes xmlns:r="http://symfony.com/schema/routing"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">

    <r:route id="blog_show" path="/blog/{slug}" host="{_locale}.example.com">
        <r:default key="_controller">MyBundle:Blog:show</r:default>
        <requirement xmlns="http://symfony.com/schema/routing" key="slug">\w+</requirement>
        <r2:requirement xmlns:r2="http://symfony.com/schema/routing" key="_locale">en|fr|de</r2:requirement>
        <r:option key="compiler_class">RouteCompiler</r:option>
    </r:route>
</r:routes>
PK��Z#q��//Dtest/Routing/Symfony/Component/Routing/Tests/Fixtures/missing_id.xmlnu�[���<?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">

    <route path="/test"></route>
</routes>
PK��Zx'�	11Etest/Routing/Symfony/Component/Routing/Tests/Fixtures/withdoctype.xmlnu�[���<?xml version="1.0"?>
<!DOCTYPE foo>
<foo></foo>
PK��Z�;h�%%Ptest/Routing/Symfony/Component/Routing/Tests/Fixtures/RedirectableUrlMatcher.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Tests\Fixtures;

use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface;

/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
class RedirectableUrlMatcher extends UrlMatcher implements RedirectableUrlMatcherInterface
{
    public function redirect($path, $route, $scheme = null)
    {
        return array(
            '_controller' => 'Some controller reference...',
            'path'        => $path,
            'scheme'      => $scheme,
        );
    }
}
PK��Zs��[//Ftest/Routing/Symfony/Component/Routing/Tests/Fixtures/missing_path.xmlnu�[���<?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">

    <route id="myroute"></route>
</routes>
PK��Z�e2~Btest/Routing/Symfony/Component/Routing/Tests/Fixtures/nonvalid.ymlnu�[���foo
PK��Zix��77Ftest/Routing/Symfony/Component/Routing/Tests/Fixtures/validpattern.phpnu�[���<?php
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;

$collection = new RouteCollection();
$collection->add('blog_show', new Route(
    '/blog/{slug}',
    array('_controller' => 'MyBlogBundle:Blog:show'),
    array('locale' => '\w+'),
    array('compiler_class' => 'RouteCompiler'),
    '{locale}.example.com',
    array('https'),
    array('GET','POST','put','OpTiOnS'),
    'context.getMethod() == "GET"'
));
$collection->add('blog_show_legacy', new Route(
    '/blog/{slug}',
    array('_controller' => 'MyBlogBundle:Blog:show'),
    array('_method' => 'GET|POST|put|OpTiOnS', '_scheme' => 'https', 'locale' => '\w+',),
    array('compiler_class' => 'RouteCompiler'),
    '{locale}.example.com',
    array(),
    array(),
    'context.getMethod() == "GET"'
));

return $collection;
PK��Z�G�V,+,+Mtest/Routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.phpnu�[���<?php

use Symfony\Component\Routing\Exception\MethodNotAllowedException;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\RequestContext;

/**
 * ProjectUrlMatcher
 *
 * This class has been auto-generated
 * by the Symfony Routing Component.
 */
class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
{
    /**
     * Constructor.
     */
    public function __construct(RequestContext $context)
    {
        $this->context = $context;
    }

    public function match($pathinfo)
    {
        $allow = array();
        $pathinfo = rawurldecode($pathinfo);
        $context = $this->context;
        $request = $this->request;

        // foo
        if (0 === strpos($pathinfo, '/foo') && preg_match('#^/foo/(?P<bar>baz|symfony)$#s', $pathinfo, $matches)) {
            return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo')), array (  'def' => 'test',));
        }

        if (0 === strpos($pathinfo, '/bar')) {
            // bar
            if (preg_match('#^/bar/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) {
                if (!in_array($this->context->getMethod(), array('GET', 'HEAD'))) {
                    $allow = array_merge($allow, array('GET', 'HEAD'));
                    goto not_bar;
                }

                return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar')), array ());
            }
            not_bar:

            // barhead
            if (0 === strpos($pathinfo, '/barhead') && preg_match('#^/barhead/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) {
                if (!in_array($this->context->getMethod(), array('GET', 'HEAD'))) {
                    $allow = array_merge($allow, array('GET', 'HEAD'));
                    goto not_barhead;
                }

                return $this->mergeDefaults(array_replace($matches, array('_route' => 'barhead')), array ());
            }
            not_barhead:

        }

        if (0 === strpos($pathinfo, '/test')) {
            if (0 === strpos($pathinfo, '/test/baz')) {
                // baz
                if ($pathinfo === '/test/baz') {
                    return array('_route' => 'baz');
                }

                // baz2
                if ($pathinfo === '/test/baz.html') {
                    return array('_route' => 'baz2');
                }

                // baz3
                if ($pathinfo === '/test/baz3/') {
                    return array('_route' => 'baz3');
                }

            }

            // baz4
            if (preg_match('#^/test/(?P<foo>[^/]++)/$#s', $pathinfo, $matches)) {
                return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz4')), array ());
            }

            // baz5
            if (preg_match('#^/test/(?P<foo>[^/]++)/$#s', $pathinfo, $matches)) {
                if ($this->context->getMethod() != 'POST') {
                    $allow[] = 'POST';
                    goto not_baz5;
                }

                return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz5')), array ());
            }
            not_baz5:

            // baz.baz6
            if (preg_match('#^/test/(?P<foo>[^/]++)/$#s', $pathinfo, $matches)) {
                if ($this->context->getMethod() != 'PUT') {
                    $allow[] = 'PUT';
                    goto not_bazbaz6;
                }

                return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz.baz6')), array ());
            }
            not_bazbaz6:

        }

        // foofoo
        if ($pathinfo === '/foofoo') {
            return array (  'def' => 'test',  '_route' => 'foofoo',);
        }

        // quoter
        if (preg_match('#^/(?P<quoter>[\']+)$#s', $pathinfo, $matches)) {
            return $this->mergeDefaults(array_replace($matches, array('_route' => 'quoter')), array ());
        }

        // space
        if ($pathinfo === '/spa ce') {
            return array('_route' => 'space');
        }

        if (0 === strpos($pathinfo, '/a')) {
            if (0 === strpos($pathinfo, '/a/b\'b')) {
                // foo1
                if (preg_match('#^/a/b\'b/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) {
                    return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo1')), array ());
                }

                // bar1
                if (preg_match('#^/a/b\'b/(?P<bar>[^/]++)$#s', $pathinfo, $matches)) {
                    return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar1')), array ());
                }

            }

            // overridden
            if (preg_match('#^/a/(?P<var>.*)$#s', $pathinfo, $matches)) {
                return $this->mergeDefaults(array_replace($matches, array('_route' => 'overridden')), array ());
            }

            if (0 === strpos($pathinfo, '/a/b\'b')) {
                // foo2
                if (preg_match('#^/a/b\'b/(?P<foo1>[^/]++)$#s', $pathinfo, $matches)) {
                    return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo2')), array ());
                }

                // bar2
                if (preg_match('#^/a/b\'b/(?P<bar1>[^/]++)$#s', $pathinfo, $matches)) {
                    return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar2')), array ());
                }

            }

        }

        if (0 === strpos($pathinfo, '/multi')) {
            // helloWorld
            if (0 === strpos($pathinfo, '/multi/hello') && preg_match('#^/multi/hello(?:/(?P<who>[^/]++))?$#s', $pathinfo, $matches)) {
                return $this->mergeDefaults(array_replace($matches, array('_route' => 'helloWorld')), array (  'who' => 'World!',));
            }

            // overridden2
            if ($pathinfo === '/multi/new') {
                return array('_route' => 'overridden2');
            }

            // hey
            if ($pathinfo === '/multi/hey/') {
                return array('_route' => 'hey');
            }

        }

        // foo3
        if (preg_match('#^/(?P<_locale>[^/]++)/b/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) {
            return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo3')), array ());
        }

        // bar3
        if (preg_match('#^/(?P<_locale>[^/]++)/b/(?P<bar>[^/]++)$#s', $pathinfo, $matches)) {
            return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar3')), array ());
        }

        if (0 === strpos($pathinfo, '/aba')) {
            // ababa
            if ($pathinfo === '/ababa') {
                return array('_route' => 'ababa');
            }

            // foo4
            if (preg_match('#^/aba/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) {
                return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo4')), array ());
            }

        }

        $host = $this->context->getHost();

        if (preg_match('#^a\\.example\\.com$#s', $host, $hostMatches)) {
            // route1
            if ($pathinfo === '/route1') {
                return array('_route' => 'route1');
            }

            // route2
            if ($pathinfo === '/c2/route2') {
                return array('_route' => 'route2');
            }

        }

        if (preg_match('#^b\\.example\\.com$#s', $host, $hostMatches)) {
            // route3
            if ($pathinfo === '/c2/route3') {
                return array('_route' => 'route3');
            }

        }

        if (preg_match('#^a\\.example\\.com$#s', $host, $hostMatches)) {
            // route4
            if ($pathinfo === '/route4') {
                return array('_route' => 'route4');
            }

        }

        if (preg_match('#^c\\.example\\.com$#s', $host, $hostMatches)) {
            // route5
            if ($pathinfo === '/route5') {
                return array('_route' => 'route5');
            }

        }

        // route6
        if ($pathinfo === '/route6') {
            return array('_route' => 'route6');
        }

        if (preg_match('#^(?P<var1>[^\\.]++)\\.example\\.com$#s', $host, $hostMatches)) {
            if (0 === strpos($pathinfo, '/route1')) {
                // route11
                if ($pathinfo === '/route11') {
                    return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route11')), array ());
                }

                // route12
                if ($pathinfo === '/route12') {
                    return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route12')), array (  'var1' => 'val',));
                }

                // route13
                if (0 === strpos($pathinfo, '/route13') && preg_match('#^/route13/(?P<name>[^/]++)$#s', $pathinfo, $matches)) {
                    return $this->mergeDefaults(array_replace($hostMatches, $matches, array('_route' => 'route13')), array ());
                }

                // route14
                if (0 === strpos($pathinfo, '/route14') && preg_match('#^/route14/(?P<name>[^/]++)$#s', $pathinfo, $matches)) {
                    return $this->mergeDefaults(array_replace($hostMatches, $matches, array('_route' => 'route14')), array (  'var1' => 'val',));
                }

            }

        }

        if (preg_match('#^c\\.example\\.com$#s', $host, $hostMatches)) {
            // route15
            if (0 === strpos($pathinfo, '/route15') && preg_match('#^/route15/(?P<name>[^/]++)$#s', $pathinfo, $matches)) {
                return $this->mergeDefaults(array_replace($matches, array('_route' => 'route15')), array ());
            }

        }

        if (0 === strpos($pathinfo, '/route1')) {
            // route16
            if (0 === strpos($pathinfo, '/route16') && preg_match('#^/route16/(?P<name>[^/]++)$#s', $pathinfo, $matches)) {
                return $this->mergeDefaults(array_replace($matches, array('_route' => 'route16')), array (  'var1' => 'val',));
            }

            // route17
            if ($pathinfo === '/route17') {
                return array('_route' => 'route17');
            }

        }

        if (0 === strpos($pathinfo, '/a')) {
            // a
            if ($pathinfo === '/a/a...') {
                return array('_route' => 'a');
            }

            if (0 === strpos($pathinfo, '/a/b')) {
                // b
                if (preg_match('#^/a/b/(?P<var>[^/]++)$#s', $pathinfo, $matches)) {
                    return $this->mergeDefaults(array_replace($matches, array('_route' => 'b')), array ());
                }

                // c
                if (0 === strpos($pathinfo, '/a/b/c') && preg_match('#^/a/b/c/(?P<var>[^/]++)$#s', $pathinfo, $matches)) {
                    return $this->mergeDefaults(array_replace($matches, array('_route' => 'c')), array ());
                }

            }

        }

        throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException();
    }
}
PK��ZT����Mtest/Routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.phpnu�[���<?php

use Symfony\Component\Routing\Exception\MethodNotAllowedException;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\RequestContext;

/**
 * ProjectUrlMatcher
 *
 * This class has been auto-generated
 * by the Symfony Routing Component.
 */
class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
{
    /**
     * Constructor.
     */
    public function __construct(RequestContext $context)
    {
        $this->context = $context;
    }

    public function match($pathinfo)
    {
        $allow = array();
        $pathinfo = rawurldecode($pathinfo);
        $context = $this->context;
        $request = $this->request;

        if (0 === strpos($pathinfo, '/rootprefix')) {
            // static
            if ($pathinfo === '/rootprefix/test') {
                return array('_route' => 'static');
            }

            // dynamic
            if (preg_match('#^/rootprefix/(?P<var>[^/]++)$#s', $pathinfo, $matches)) {
                return $this->mergeDefaults(array_replace($matches, array('_route' => 'dynamic')), array ());
            }

        }

        // with-condition
        if ($pathinfo === '/with-condition' && ($context->getMethod() == "GET")) {
            return array('_route' => 'with-condition');
        }

        throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException();
    }
}
PK��Z@4��Ptest/Routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.apachenu�[���# skip "real" requests
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule .* - [QSA,L]

# foo
RewriteCond %{REQUEST_URI} ^/foo/(baz|symfony)$
RewriteRule .* app.php [QSA,L,E=_ROUTING_route:foo,E=_ROUTING_param_bar:%1,E=_ROUTING_default_def:test]

# foobar
RewriteCond %{REQUEST_URI} ^/foo(?:/([^/]++))?$
RewriteRule .* app.php [QSA,L,E=_ROUTING_route:foobar,E=_ROUTING_param_bar:%1,E=_ROUTING_default_bar:toto]

# bar
RewriteCond %{REQUEST_URI} ^/bar/([^/]++)$
RewriteCond %{REQUEST_METHOD} !^(GET|HEAD)$ [NC]
RewriteRule .* - [S=1,E=_ROUTING_allow_GET:1,E=_ROUTING_allow_HEAD:1]
RewriteCond %{REQUEST_URI} ^/bar/([^/]++)$
RewriteRule .* app.php [QSA,L,E=_ROUTING_route:bar,E=_ROUTING_param_foo:%1]

# baragain
RewriteCond %{REQUEST_URI} ^/baragain/([^/]++)$
RewriteCond %{REQUEST_METHOD} !^(GET|POST|HEAD)$ [NC]
RewriteRule .* - [S=1,E=_ROUTING_allow_GET:1,E=_ROUTING_allow_POST:1,E=_ROUTING_allow_HEAD:1]
RewriteCond %{REQUEST_URI} ^/baragain/([^/]++)$
RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baragain,E=_ROUTING_param_foo:%1]

# baz
RewriteCond %{REQUEST_URI} ^/test/baz$
RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz]

# baz2
RewriteCond %{REQUEST_URI} ^/test/baz\.html$
RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz2]

# baz3
RewriteCond %{REQUEST_URI} ^/test/baz3$
RewriteRule .* $0/ [QSA,L,R=301]
RewriteCond %{REQUEST_URI} ^/test/baz3/$
RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz3]

# baz4
RewriteCond %{REQUEST_URI} ^/test/([^/]++)$
RewriteRule .* $0/ [QSA,L,R=301]
RewriteCond %{REQUEST_URI} ^/test/([^/]++)/$
RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz4,E=_ROUTING_param_foo:%1]

# baz5
RewriteCond %{REQUEST_URI} ^/test/([^/]++)/$
RewriteCond %{REQUEST_METHOD} !^(GET|HEAD)$ [NC]
RewriteRule .* - [S=2,E=_ROUTING_allow_GET:1,E=_ROUTING_allow_HEAD:1]
RewriteCond %{REQUEST_URI} ^/test/([^/]++)$
RewriteRule .* $0/ [QSA,L,R=301]
RewriteCond %{REQUEST_URI} ^/test/([^/]++)/$
RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz5,E=_ROUTING_param_foo:%1]

# baz5unsafe
RewriteCond %{REQUEST_URI} ^/testunsafe/([^/]++)/$
RewriteCond %{REQUEST_METHOD} !^(POST)$ [NC]
RewriteRule .* - [S=1,E=_ROUTING_allow_POST:1]
RewriteCond %{REQUEST_URI} ^/testunsafe/([^/]++)/$
RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz5unsafe,E=_ROUTING_param_foo:%1]

# baz6
RewriteCond %{REQUEST_URI} ^/test/baz$
RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz6,E=_ROUTING_default_foo:bar\ baz]

# baz7
RewriteCond %{REQUEST_URI} ^/te\ st/baz$
RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz7]

# baz8
RewriteCond %{REQUEST_URI} ^/te\\\ st/baz$
RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz8]

# baz9
RewriteCond %{REQUEST_URI} ^/test/(te\\\ st)$
RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz9,E=_ROUTING_param_baz:%1]

RewriteCond %{HTTP:Host} ^a\.example\.com$
RewriteRule .? - [E=__ROUTING_host_1:1]

# route1
RewriteCond %{ENV:__ROUTING_host_1} =1
RewriteCond %{REQUEST_URI} ^/route1$
RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route1]

# route2
RewriteCond %{ENV:__ROUTING_host_1} =1
RewriteCond %{REQUEST_URI} ^/c2/route2$
RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route2]

RewriteCond %{HTTP:Host} ^b\.example\.com$
RewriteRule .? - [E=__ROUTING_host_2:1]

# route3
RewriteCond %{ENV:__ROUTING_host_2} =1
RewriteCond %{REQUEST_URI} ^/c2/route3$
RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route3]

RewriteCond %{HTTP:Host} ^a\.example\.com$
RewriteRule .? - [E=__ROUTING_host_3:1]

# route4
RewriteCond %{ENV:__ROUTING_host_3} =1
RewriteCond %{REQUEST_URI} ^/route4$
RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route4]

RewriteCond %{HTTP:Host} ^c\.example\.com$
RewriteRule .? - [E=__ROUTING_host_4:1]

# route5
RewriteCond %{ENV:__ROUTING_host_4} =1
RewriteCond %{REQUEST_URI} ^/route5$
RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route5]

# route6
RewriteCond %{REQUEST_URI} ^/route6$
RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route6]

RewriteCond %{HTTP:Host} ^([^\.]++)\.example\.com$
RewriteRule .? - [E=__ROUTING_host_5:1,E=__ROUTING_host_5_var1:%1]

# route11
RewriteCond %{ENV:__ROUTING_host_5} =1
RewriteCond %{REQUEST_URI} ^/route11$
RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route11,E=_ROUTING_param_var1:%{ENV:__ROUTING_host_5_var1}]

# route12
RewriteCond %{ENV:__ROUTING_host_5} =1
RewriteCond %{REQUEST_URI} ^/route12$
RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route12,E=_ROUTING_param_var1:%{ENV:__ROUTING_host_5_var1},E=_ROUTING_default_var1:val]

# route13
RewriteCond %{ENV:__ROUTING_host_5} =1
RewriteCond %{REQUEST_URI} ^/route13/([^/]++)$
RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route13,E=_ROUTING_param_var1:%{ENV:__ROUTING_host_5_var1},E=_ROUTING_param_name:%1]

# route14
RewriteCond %{ENV:__ROUTING_host_5} =1
RewriteCond %{REQUEST_URI} ^/route14/([^/]++)$
RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route14,E=_ROUTING_param_var1:%{ENV:__ROUTING_host_5_var1},E=_ROUTING_param_name:%1,E=_ROUTING_default_var1:val]

RewriteCond %{HTTP:Host} ^c\.example\.com$
RewriteRule .? - [E=__ROUTING_host_6:1]

# route15
RewriteCond %{ENV:__ROUTING_host_6} =1
RewriteCond %{REQUEST_URI} ^/route15/([^/]++)$
RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route15,E=_ROUTING_param_name:%1]

# route16
RewriteCond %{REQUEST_URI} ^/route16/([^/]++)$
RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route16,E=_ROUTING_param_name:%1,E=_ROUTING_default_var1:val]

# route17
RewriteCond %{REQUEST_URI} ^/route17$
RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route17]

# 405 Method Not Allowed
RewriteCond %{ENV:_ROUTING__allow_GET} =1 [OR]
RewriteCond %{ENV:_ROUTING__allow_HEAD} =1 [OR]
RewriteCond %{ENV:_ROUTING__allow_POST} =1
RewriteRule .* app.php [QSA,L]
PK��ZBx�6��Ptest/Routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.apachenu�[���# skip "real" requests
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule .* - [QSA,L]

# foo
RewriteCond %{REQUEST_URI} ^/foo$
RewriteRule .* ap\ p_d\ ev.php [QSA,L,E=_ROUTING_route:foo]
PK��Zn�k�//Mtest/Routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.phpnu�[���<?php

use Symfony\Component\Routing\Exception\MethodNotAllowedException;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\RequestContext;

/**
 * ProjectUrlMatcher
 *
 * This class has been auto-generated
 * by the Symfony Routing Component.
 */
class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\RedirectableUrlMatcher
{
    /**
     * Constructor.
     */
    public function __construct(RequestContext $context)
    {
        $this->context = $context;
    }

    public function match($pathinfo)
    {
        $allow = array();
        $pathinfo = rawurldecode($pathinfo);
        $context = $this->context;
        $request = $this->request;

        // foo
        if (0 === strpos($pathinfo, '/foo') && preg_match('#^/foo/(?P<bar>baz|symfony)$#s', $pathinfo, $matches)) {
            return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo')), array (  'def' => 'test',));
        }

        if (0 === strpos($pathinfo, '/bar')) {
            // bar
            if (preg_match('#^/bar/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) {
                if (!in_array($this->context->getMethod(), array('GET', 'HEAD'))) {
                    $allow = array_merge($allow, array('GET', 'HEAD'));
                    goto not_bar;
                }

                return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar')), array ());
            }
            not_bar:

            // barhead
            if (0 === strpos($pathinfo, '/barhead') && preg_match('#^/barhead/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) {
                if (!in_array($this->context->getMethod(), array('GET', 'HEAD'))) {
                    $allow = array_merge($allow, array('GET', 'HEAD'));
                    goto not_barhead;
                }

                return $this->mergeDefaults(array_replace($matches, array('_route' => 'barhead')), array ());
            }
            not_barhead:

        }

        if (0 === strpos($pathinfo, '/test')) {
            if (0 === strpos($pathinfo, '/test/baz')) {
                // baz
                if ($pathinfo === '/test/baz') {
                    return array('_route' => 'baz');
                }

                // baz2
                if ($pathinfo === '/test/baz.html') {
                    return array('_route' => 'baz2');
                }

                // baz3
                if (rtrim($pathinfo, '/') === '/test/baz3') {
                    if (substr($pathinfo, -1) !== '/') {
                        return $this->redirect($pathinfo.'/', 'baz3');
                    }

                    return array('_route' => 'baz3');
                }

            }

            // baz4
            if (preg_match('#^/test/(?P<foo>[^/]++)/?$#s', $pathinfo, $matches)) {
                if (substr($pathinfo, -1) !== '/') {
                    return $this->redirect($pathinfo.'/', 'baz4');
                }

                return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz4')), array ());
            }

            // baz5
            if (preg_match('#^/test/(?P<foo>[^/]++)/$#s', $pathinfo, $matches)) {
                if ($this->context->getMethod() != 'POST') {
                    $allow[] = 'POST';
                    goto not_baz5;
                }

                return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz5')), array ());
            }
            not_baz5:

            // baz.baz6
            if (preg_match('#^/test/(?P<foo>[^/]++)/$#s', $pathinfo, $matches)) {
                if ($this->context->getMethod() != 'PUT') {
                    $allow[] = 'PUT';
                    goto not_bazbaz6;
                }

                return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz.baz6')), array ());
            }
            not_bazbaz6:

        }

        // foofoo
        if ($pathinfo === '/foofoo') {
            return array (  'def' => 'test',  '_route' => 'foofoo',);
        }

        // quoter
        if (preg_match('#^/(?P<quoter>[\']+)$#s', $pathinfo, $matches)) {
            return $this->mergeDefaults(array_replace($matches, array('_route' => 'quoter')), array ());
        }

        // space
        if ($pathinfo === '/spa ce') {
            return array('_route' => 'space');
        }

        if (0 === strpos($pathinfo, '/a')) {
            if (0 === strpos($pathinfo, '/a/b\'b')) {
                // foo1
                if (preg_match('#^/a/b\'b/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) {
                    return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo1')), array ());
                }

                // bar1
                if (preg_match('#^/a/b\'b/(?P<bar>[^/]++)$#s', $pathinfo, $matches)) {
                    return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar1')), array ());
                }

            }

            // overridden
            if (preg_match('#^/a/(?P<var>.*)$#s', $pathinfo, $matches)) {
                return $this->mergeDefaults(array_replace($matches, array('_route' => 'overridden')), array ());
            }

            if (0 === strpos($pathinfo, '/a/b\'b')) {
                // foo2
                if (preg_match('#^/a/b\'b/(?P<foo1>[^/]++)$#s', $pathinfo, $matches)) {
                    return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo2')), array ());
                }

                // bar2
                if (preg_match('#^/a/b\'b/(?P<bar1>[^/]++)$#s', $pathinfo, $matches)) {
                    return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar2')), array ());
                }

            }

        }

        if (0 === strpos($pathinfo, '/multi')) {
            // helloWorld
            if (0 === strpos($pathinfo, '/multi/hello') && preg_match('#^/multi/hello(?:/(?P<who>[^/]++))?$#s', $pathinfo, $matches)) {
                return $this->mergeDefaults(array_replace($matches, array('_route' => 'helloWorld')), array (  'who' => 'World!',));
            }

            // overridden2
            if ($pathinfo === '/multi/new') {
                return array('_route' => 'overridden2');
            }

            // hey
            if (rtrim($pathinfo, '/') === '/multi/hey') {
                if (substr($pathinfo, -1) !== '/') {
                    return $this->redirect($pathinfo.'/', 'hey');
                }

                return array('_route' => 'hey');
            }

        }

        // foo3
        if (preg_match('#^/(?P<_locale>[^/]++)/b/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) {
            return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo3')), array ());
        }

        // bar3
        if (preg_match('#^/(?P<_locale>[^/]++)/b/(?P<bar>[^/]++)$#s', $pathinfo, $matches)) {
            return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar3')), array ());
        }

        if (0 === strpos($pathinfo, '/aba')) {
            // ababa
            if ($pathinfo === '/ababa') {
                return array('_route' => 'ababa');
            }

            // foo4
            if (preg_match('#^/aba/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) {
                return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo4')), array ());
            }

        }

        $host = $this->context->getHost();

        if (preg_match('#^a\\.example\\.com$#s', $host, $hostMatches)) {
            // route1
            if ($pathinfo === '/route1') {
                return array('_route' => 'route1');
            }

            // route2
            if ($pathinfo === '/c2/route2') {
                return array('_route' => 'route2');
            }

        }

        if (preg_match('#^b\\.example\\.com$#s', $host, $hostMatches)) {
            // route3
            if ($pathinfo === '/c2/route3') {
                return array('_route' => 'route3');
            }

        }

        if (preg_match('#^a\\.example\\.com$#s', $host, $hostMatches)) {
            // route4
            if ($pathinfo === '/route4') {
                return array('_route' => 'route4');
            }

        }

        if (preg_match('#^c\\.example\\.com$#s', $host, $hostMatches)) {
            // route5
            if ($pathinfo === '/route5') {
                return array('_route' => 'route5');
            }

        }

        // route6
        if ($pathinfo === '/route6') {
            return array('_route' => 'route6');
        }

        if (preg_match('#^(?P<var1>[^\\.]++)\\.example\\.com$#s', $host, $hostMatches)) {
            if (0 === strpos($pathinfo, '/route1')) {
                // route11
                if ($pathinfo === '/route11') {
                    return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route11')), array ());
                }

                // route12
                if ($pathinfo === '/route12') {
                    return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route12')), array (  'var1' => 'val',));
                }

                // route13
                if (0 === strpos($pathinfo, '/route13') && preg_match('#^/route13/(?P<name>[^/]++)$#s', $pathinfo, $matches)) {
                    return $this->mergeDefaults(array_replace($hostMatches, $matches, array('_route' => 'route13')), array ());
                }

                // route14
                if (0 === strpos($pathinfo, '/route14') && preg_match('#^/route14/(?P<name>[^/]++)$#s', $pathinfo, $matches)) {
                    return $this->mergeDefaults(array_replace($hostMatches, $matches, array('_route' => 'route14')), array (  'var1' => 'val',));
                }

            }

        }

        if (preg_match('#^c\\.example\\.com$#s', $host, $hostMatches)) {
            // route15
            if (0 === strpos($pathinfo, '/route15') && preg_match('#^/route15/(?P<name>[^/]++)$#s', $pathinfo, $matches)) {
                return $this->mergeDefaults(array_replace($matches, array('_route' => 'route15')), array ());
            }

        }

        if (0 === strpos($pathinfo, '/route1')) {
            // route16
            if (0 === strpos($pathinfo, '/route16') && preg_match('#^/route16/(?P<name>[^/]++)$#s', $pathinfo, $matches)) {
                return $this->mergeDefaults(array_replace($matches, array('_route' => 'route16')), array (  'var1' => 'val',));
            }

            // route17
            if ($pathinfo === '/route17') {
                return array('_route' => 'route17');
            }

        }

        if (0 === strpos($pathinfo, '/a')) {
            // a
            if ($pathinfo === '/a/a...') {
                return array('_route' => 'a');
            }

            if (0 === strpos($pathinfo, '/a/b')) {
                // b
                if (preg_match('#^/a/b/(?P<var>[^/]++)$#s', $pathinfo, $matches)) {
                    return $this->mergeDefaults(array_replace($matches, array('_route' => 'b')), array ());
                }

                // c
                if (0 === strpos($pathinfo, '/a/b/c') && preg_match('#^/a/b/c/(?P<var>[^/]++)$#s', $pathinfo, $matches)) {
                    return $this->mergeDefaults(array_replace($matches, array('_route' => 'c')), array ());
                }

            }

        }

        // secure
        if ($pathinfo === '/secure') {
            if ($this->context->getScheme() !== 'https') {
                return $this->redirect($pathinfo, 'secure', 'https');
            }

            return array('_route' => 'secure');
        }

        // nonsecure
        if ($pathinfo === '/nonsecure') {
            if ($this->context->getScheme() !== 'http') {
                return $this->redirect($pathinfo, 'nonsecure', 'http');
            }

            return array('_route' => 'nonsecure');
        }

        throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException();
    }
}
PK��Z�p��Btest/Routing/Symfony/Component/Routing/Tests/Fixtures/nonvalid.xmlnu�[���<?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">

    <route id="blog_show" path="/blog/{slug}">
        <default key="_controller">MyBundle:Blog:show</default>
        <requirement key="_method">GET</requirement>
    <!-- </route> -->
</routes>
PK��Zͼ�n!!Ftest/Routing/Symfony/Component/Routing/Tests/Fixtures/nonvalidnode.xmlnu�[���<?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">

    <foo>bar</foo>
</routes>
PK��ZT��Stest/Routing/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/BarClass.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses;

class BarClass
{
    public function routeAction($arg1, $arg2 = 'defaultValue2', $arg3 = 'defaultValue3')
    {
    }
}
PK��Z���GGStest/Routing/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/FooClass.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses;

class FooClass
{
}
PK��Z�zUUXtest/Routing/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/AbstractClass.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses;

abstract class AbstractClass
{
}
PK��Z�M�tCtest/Routing/Symfony/Component/Routing/Tests/Fixtures/nonvalid2.ymlnu�[���route: string
PK��Z�b�Gtest/Routing/Symfony/Component/Routing/Tests/Fixtures/validresource.xmlnu�[���<?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">

    <import resource="validpattern.xml" prefix="/{foo}" host="">
        <default key="foo">123</default>
        <requirement key="foo">\d+</requirement>
        <option key="foo">bar</option>
        <condition>context.getMethod() == "POST"</condition>
    </import>
</routes>
PK��Z��q�Gtest/Routing/Symfony/Component/Routing/Tests/Fixtures/nonvalidroute.xmlnu�[���<?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">

    <route id="blog_show" path="/blog/{slug}">
        <default key="_controller">MyBundle:Blog:show</default>
        <requirement key="_method">GET</requirement>
        <option key="compiler_class">RouteCompiler</option>
        <foo key="bar">baz</foo>
    </route>
</routes>
PK��Z��ϮBBDtest/Routing/Symfony/Component/Routing/Tests/Fixtures/incomplete.ymlnu�[���blog_show:
    defaults:  { _controller: MyBlogBundle:Blog:show }
PK��Z�J?�Ltest/Routing/Symfony/Component/Routing/Tests/Fixtures/special_route_name.ymlnu�[���"#$péß^a|":
    path: "true"
PK��Z�q�99Ytest/Routing/Symfony/Component/Routing/Tests/Fixtures/nonesense_type_without_resource.ymlnu�[���blog_show:
    path:    /blog/{slug}
    type:    custom
PK��ZjX���Gtest/Routing/Symfony/Component/Routing/Tests/Fixtures/validresource.ymlnu�[���_blog:
    resource:     validpattern.yml
    prefix:       /{foo}
    defaults:     { 'foo': '123' }
    requirements: { 'foo': '\d+' }
    options:      { 'foo': 'bar' }
    host:         ""
    condition:    'context.getMethod() == "POST"'
PK��Z>test/Routing/Symfony/Component/Routing/Tests/Fixtures/foo1.xmlnu�[���PK��Z=test/Routing/Symfony/Component/Routing/Tests/Fixtures/foo.xmlnu�[���PK��Z��/��
�
Ctest/Routing/Symfony/Component/Routing/Tests/RequestContextTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Tests;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\RequestContext;

class RequestContextTest extends \PHPUnit_Framework_TestCase
{
    public function testConstruct()
    {
        $requestContext = new RequestContext(
            'foo',
            'post',
            'foo.bar',
            'HTTPS',
            8080,
            444,
            '/baz',
            'bar=foobar'
        );

        $this->assertEquals('foo', $requestContext->getBaseUrl());
        $this->assertEquals('POST', $requestContext->getMethod());
        $this->assertEquals('foo.bar', $requestContext->getHost());
        $this->assertEquals('https', $requestContext->getScheme());
        $this->assertSame(8080, $requestContext->getHttpPort());
        $this->assertSame(444, $requestContext->getHttpsPort());
        $this->assertEquals('/baz', $requestContext->getPathInfo());
        $this->assertEquals('bar=foobar', $requestContext->getQueryString());
    }

    public function testFromRequest()
    {
        $request = Request::create('https://test.com:444/foo?bar=baz');
        $requestContext = new RequestContext();
        $requestContext->setHttpPort(123);
        $requestContext->fromRequest($request);

        $this->assertEquals('', $requestContext->getBaseUrl());
        $this->assertEquals('GET', $requestContext->getMethod());
        $this->assertEquals('test.com', $requestContext->getHost());
        $this->assertEquals('https', $requestContext->getScheme());
        $this->assertEquals('/foo', $requestContext->getPathInfo());
        $this->assertEquals('bar=baz', $requestContext->getQueryString());
        $this->assertSame(123, $requestContext->getHttpPort());
        $this->assertSame(444, $requestContext->getHttpsPort());

        $request = Request::create('http://test.com:8080/foo?bar=baz');
        $requestContext = new RequestContext();
        $requestContext->setHttpsPort(567);
        $requestContext->fromRequest($request);

        $this->assertSame(8080, $requestContext->getHttpPort());
        $this->assertSame(567, $requestContext->getHttpsPort());
    }

    public function testGetParameters()
    {
        $requestContext = new RequestContext();
        $this->assertEquals(array(), $requestContext->getParameters());

        $requestContext->setParameters(array('foo' => 'bar'));
        $this->assertEquals(array('foo' => 'bar'), $requestContext->getParameters());
    }

    public function testHasParameter()
    {
        $requestContext = new RequestContext();
        $requestContext->setParameters(array('foo' => 'bar'));

        $this->assertTrue($requestContext->hasParameter('foo'));
        $this->assertFalse($requestContext->hasParameter('baz'));
    }

    public function testGetParameter()
    {
        $requestContext = new RequestContext();
        $requestContext->setParameters(array('foo' => 'bar'));

        $this->assertEquals('bar', $requestContext->getParameter('foo'));
        $this->assertNull($requestContext->getParameter('baz'));
    }

    public function testSetParameter()
    {
        $requestContext = new RequestContext();
        $requestContext->setParameter('foo', 'bar');

        $this->assertEquals('bar', $requestContext->getParameter('foo'));
    }
}
PK��Z���
�
Ptest/Routing/Symfony/Component/Routing/Tests/Matcher/TraceableUrlMatcherTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Tests\Matcher;

use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\Matcher\TraceableUrlMatcher;

class TraceableUrlMatcherTest extends \PHPUnit_Framework_TestCase
{
    public function test()
    {
        $coll = new RouteCollection();
        $coll->add('foo', new Route('/foo', array(), array('_method' => 'POST')));
        $coll->add('bar', new Route('/bar/{id}', array(), array('id' => '\d+')));
        $coll->add('bar1', new Route('/bar/{name}', array(), array('id' => '\w+', '_method' => 'POST')));
        $coll->add('bar2', new Route('/foo', array(), array(), array(), 'baz'));
        $coll->add('bar3', new Route('/foo1', array(), array(), array(), 'baz'));
        $coll->add('bar4', new Route('/foo2', array(), array(), array(), 'baz', array(), array(), 'context.getMethod() == "GET"'));

        $context = new RequestContext();
        $context->setHost('baz');

        $matcher = new TraceableUrlMatcher($coll, $context);
        $traces = $matcher->getTraces('/babar');
        $this->assertEquals(array(0, 0, 0, 0, 0, 0), $this->getLevels($traces));

        $traces = $matcher->getTraces('/foo');
        $this->assertEquals(array(1, 0, 0, 2), $this->getLevels($traces));

        $traces = $matcher->getTraces('/bar/12');
        $this->assertEquals(array(0, 2), $this->getLevels($traces));

        $traces = $matcher->getTraces('/bar/dd');
        $this->assertEquals(array(0, 1, 1, 0, 0, 0), $this->getLevels($traces));

        $traces = $matcher->getTraces('/foo1');
        $this->assertEquals(array(0, 0, 0, 0, 2), $this->getLevels($traces));

        $context->setMethod('POST');
        $traces = $matcher->getTraces('/foo');
        $this->assertEquals(array(2), $this->getLevels($traces));

        $traces = $matcher->getTraces('/bar/dd');
        $this->assertEquals(array(0, 1, 2), $this->getLevels($traces));

        $traces = $matcher->getTraces('/foo2');
        $this->assertEquals(array(0, 0, 0, 0, 0, 1), $this->getLevels($traces));
    }

    public function testMatchRouteOnMultipleHosts()
    {
        $routes = new RouteCollection();
        $routes->add('first', new Route(
            '/mypath/',
            array('_controller' => 'MainBundle:Info:first'),
            array(),
            array(),
            'some.example.com'
        ));

        $routes->add('second', new Route(
            '/mypath/',
            array('_controller' => 'MainBundle:Info:second'),
            array(),
            array(),
            'another.example.com'
        ));

        $context = new RequestContext();
        $context->setHost('baz');

        $matcher = new TraceableUrlMatcher($routes, $context);

        $traces = $matcher->getTraces('/mypath/');
        $this->assertEquals(
            array(TraceableUrlMatcher::ROUTE_ALMOST_MATCHES, TraceableUrlMatcher::ROUTE_ALMOST_MATCHES),
            $this->getLevels($traces)
        );
    }

    public function getLevels($traces)
    {
        $levels = array();
        foreach ($traces as $trace) {
            $levels[] = $trace['level'];
        }

        return $levels;
    }
}
PK��Zt�kT�B�BGtest/Routing/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Tests\Matcher;

use Symfony\Component\Routing\Exception\MethodNotAllowedException;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\RequestContext;

class UrlMatcherTest extends \PHPUnit_Framework_TestCase
{
    public function testNoMethodSoAllowed()
    {
        $coll = new RouteCollection();
        $coll->add('foo', new Route('/foo'));

        $matcher = new UrlMatcher($coll, new RequestContext());
        $matcher->match('/foo');
    }

    public function testMethodNotAllowed()
    {
        $coll = new RouteCollection();
        $coll->add('foo', new Route('/foo', array(), array('_method' => 'post')));

        $matcher = new UrlMatcher($coll, new RequestContext());

        try {
            $matcher->match('/foo');
            $this->fail();
        } catch (MethodNotAllowedException $e) {
            $this->assertEquals(array('POST'), $e->getAllowedMethods());
        }
    }

    public function testHeadAllowedWhenRequirementContainsGet()
    {
        $coll = new RouteCollection();
        $coll->add('foo', new Route('/foo', array(), array('_method' => 'get')));

        $matcher = new UrlMatcher($coll, new RequestContext('', 'head'));
        $matcher->match('/foo');
    }

    public function testMethodNotAllowedAggregatesAllowedMethods()
    {
        $coll = new RouteCollection();
        $coll->add('foo1', new Route('/foo', array(), array('_method' => 'post')));
        $coll->add('foo2', new Route('/foo', array(), array('_method' => 'put|delete')));

        $matcher = new UrlMatcher($coll, new RequestContext());

        try {
            $matcher->match('/foo');
            $this->fail();
        } catch (MethodNotAllowedException $e) {
            $this->assertEquals(array('POST', 'PUT', 'DELETE'), $e->getAllowedMethods());
        }
    }

    public function testMatch()
    {
        // test the patterns are matched and parameters are returned
        $collection = new RouteCollection();
        $collection->add('foo', new Route('/foo/{bar}'));
        $matcher = new UrlMatcher($collection, new RequestContext());
        try {
            $matcher->match('/no-match');
            $this->fail();
        } catch (ResourceNotFoundException $e) {}
        $this->assertEquals(array('_route' => 'foo', 'bar' => 'baz'), $matcher->match('/foo/baz'));

        // test that defaults are merged
        $collection = new RouteCollection();
        $collection->add('foo', new Route('/foo/{bar}', array('def' => 'test')));
        $matcher = new UrlMatcher($collection, new RequestContext());
        $this->assertEquals(array('_route' => 'foo', 'bar' => 'baz', 'def' => 'test'), $matcher->match('/foo/baz'));

        // test that route "method" is ignored if no method is given in the context
        $collection = new RouteCollection();
        $collection->add('foo', new Route('/foo', array(), array('_method' => 'GET|head')));
        $matcher = new UrlMatcher($collection, new RequestContext());
        $this->assertInternalType('array', $matcher->match('/foo'));

        // route does not match with POST method context
        $matcher = new UrlMatcher($collection, new RequestContext('', 'post'));
        try {
            $matcher->match('/foo');
            $this->fail();
        } catch (MethodNotAllowedException $e) {}

        // route does match with GET or HEAD method context
        $matcher = new UrlMatcher($collection, new RequestContext());
        $this->assertInternalType('array', $matcher->match('/foo'));
        $matcher = new UrlMatcher($collection, new RequestContext('', 'head'));
        $this->assertInternalType('array', $matcher->match('/foo'));

        // route with an optional variable as the first segment
        $collection = new RouteCollection();
        $collection->add('bar', new Route('/{bar}/foo', array('bar' => 'bar'), array('bar' => 'foo|bar')));
        $matcher = new UrlMatcher($collection, new RequestContext());
        $this->assertEquals(array('_route' => 'bar', 'bar' => 'bar'), $matcher->match('/bar/foo'));
        $this->assertEquals(array('_route' => 'bar', 'bar' => 'foo'), $matcher->match('/foo/foo'));

        $collection = new RouteCollection();
        $collection->add('bar', new Route('/{bar}', array('bar' => 'bar'), array('bar' => 'foo|bar')));
        $matcher = new UrlMatcher($collection, new RequestContext());
        $this->assertEquals(array('_route' => 'bar', 'bar' => 'foo'), $matcher->match('/foo'));
        $this->assertEquals(array('_route' => 'bar', 'bar' => 'bar'), $matcher->match('/'));

        // route with only optional variables
        $collection = new RouteCollection();
        $collection->add('bar', new Route('/{foo}/{bar}', array('foo' => 'foo', 'bar' => 'bar'), array()));
        $matcher = new UrlMatcher($collection, new RequestContext());
        $this->assertEquals(array('_route' => 'bar', 'foo' => 'foo', 'bar' => 'bar'), $matcher->match('/'));
        $this->assertEquals(array('_route' => 'bar', 'foo' => 'a', 'bar' => 'bar'), $matcher->match('/a'));
        $this->assertEquals(array('_route' => 'bar', 'foo' => 'a', 'bar' => 'b'), $matcher->match('/a/b'));
    }

    public function testMatchWithPrefixes()
    {
        $collection = new RouteCollection();
        $collection->add('foo', new Route('/{foo}'));
        $collection->addPrefix('/b');
        $collection->addPrefix('/a');

        $matcher = new UrlMatcher($collection, new RequestContext());
        $this->assertEquals(array('_route' => 'foo', 'foo' => 'foo'), $matcher->match('/a/b/foo'));
    }

    public function testMatchWithDynamicPrefix()
    {
        $collection = new RouteCollection();
        $collection->add('foo', new Route('/{foo}'));
        $collection->addPrefix('/b');
        $collection->addPrefix('/{_locale}');

        $matcher = new UrlMatcher($collection, new RequestContext());
        $this->assertEquals(array('_locale' => 'fr', '_route' => 'foo', 'foo' => 'foo'), $matcher->match('/fr/b/foo'));
    }

    public function testMatchSpecialRouteName()
    {
        $collection = new RouteCollection();
        $collection->add('$péß^a|', new Route('/bar'));

        $matcher = new UrlMatcher($collection, new RequestContext());
        $this->assertEquals(array('_route' => '$péß^a|'), $matcher->match('/bar'));
    }

    public function testMatchNonAlpha()
    {
        $collection = new RouteCollection();
        $chars = '!"$%éà &\'()*+,./:;<=>@ABCDEFGHIJKLMNOPQRSTUVWXYZ\\[]^_`abcdefghijklmnopqrstuvwxyz{|}~-';
        $collection->add('foo', new Route('/{foo}/bar', array(), array('foo' => '['.preg_quote($chars).']+')));

        $matcher = new UrlMatcher($collection, new RequestContext());
        $this->assertEquals(array('_route' => 'foo', 'foo' => $chars), $matcher->match('/'.rawurlencode($chars).'/bar'));
        $this->assertEquals(array('_route' => 'foo', 'foo' => $chars), $matcher->match('/'.strtr($chars, array('%' => '%25')).'/bar'));
    }

    public function testMatchWithDotMetacharacterInRequirements()
    {
        $collection = new RouteCollection();
        $collection->add('foo', new Route('/{foo}/bar', array(), array('foo' => '.+')));

        $matcher = new UrlMatcher($collection, new RequestContext());
        $this->assertEquals(array('_route' => 'foo', 'foo' => "\n"), $matcher->match('/'.urlencode("\n").'/bar'), 'linefeed character is matched');
    }

    public function testMatchOverriddenRoute()
    {
        $collection = new RouteCollection();
        $collection->add('foo', new Route('/foo'));

        $collection1 = new RouteCollection();
        $collection1->add('foo', new Route('/foo1'));

        $collection->addCollection($collection1);

        $matcher = new UrlMatcher($collection, new RequestContext());

        $this->assertEquals(array('_route' => 'foo'), $matcher->match('/foo1'));
        $this->setExpectedException('Symfony\Component\Routing\Exception\ResourceNotFoundException');
        $this->assertEquals(array(), $matcher->match('/foo'));
    }

    public function testMatchRegression()
    {
        $coll = new RouteCollection();
        $coll->add('foo', new Route('/foo/{foo}'));
        $coll->add('bar', new Route('/foo/bar/{foo}'));

        $matcher = new UrlMatcher($coll, new RequestContext());
        $this->assertEquals(array('foo' => 'bar', '_route' => 'bar'), $matcher->match('/foo/bar/bar'));

        $collection = new RouteCollection();
        $collection->add('foo', new Route('/{bar}'));
        $matcher = new UrlMatcher($collection, new RequestContext());
        try {
            $matcher->match('/');
            $this->fail();
        } catch (ResourceNotFoundException $e) {
        }
    }

    public function testDefaultRequirementForOptionalVariables()
    {
        $coll = new RouteCollection();
        $coll->add('test', new Route('/{page}.{_format}', array('page' => 'index', '_format' => 'html')));

        $matcher = new UrlMatcher($coll, new RequestContext());
        $this->assertEquals(array('page' => 'my-page', '_format' => 'xml', '_route' => 'test'), $matcher->match('/my-page.xml'));
    }

    public function testMatchingIsEager()
    {
        $coll = new RouteCollection();
        $coll->add('test', new Route('/{foo}-{bar}-', array(), array('foo' => '.+', 'bar' => '.+')));

        $matcher = new UrlMatcher($coll, new RequestContext());
        $this->assertEquals(array('foo' => 'text1-text2-text3', 'bar' => 'text4', '_route' => 'test'), $matcher->match('/text1-text2-text3-text4-'));
    }

    public function testAdjacentVariables()
    {
        $coll = new RouteCollection();
        $coll->add('test', new Route('/{w}{x}{y}{z}.{_format}', array('z' => 'default-z', '_format' => 'html'), array('y' => 'y|Y')));

        $matcher = new UrlMatcher($coll, new RequestContext());
        // 'w' eagerly matches as much as possible and the other variables match the remaining chars.
        // This also shows that the variables w-z must all exclude the separating char (the dot '.' in this case) by default requirement.
        // Otherwise they would also consume '.xml' and _format would never match as it's an optional variable.
        $this->assertEquals(array('w' => 'wwwww', 'x' => 'x', 'y' => 'Y', 'z' => 'Z','_format' => 'xml', '_route' => 'test'), $matcher->match('/wwwwwxYZ.xml'));
        // As 'y' has custom requirement and can only be of value 'y|Y', it will leave  'ZZZ' to variable z.
        // So with carefully chosen requirements adjacent variables, can be useful.
        $this->assertEquals(array('w' => 'wwwww', 'x' => 'x', 'y' => 'y', 'z' => 'ZZZ','_format' => 'html', '_route' => 'test'), $matcher->match('/wwwwwxyZZZ'));
        // z and _format are optional.
        $this->assertEquals(array('w' => 'wwwww', 'x' => 'x', 'y' => 'y', 'z' => 'default-z','_format' => 'html', '_route' => 'test'), $matcher->match('/wwwwwxy'));

        $this->setExpectedException('Symfony\Component\Routing\Exception\ResourceNotFoundException');
        $matcher->match('/wxy.html');
    }

    public function testOptionalVariableWithNoRealSeparator()
    {
        $coll = new RouteCollection();
        $coll->add('test', new Route('/get{what}', array('what' => 'All')));
        $matcher = new UrlMatcher($coll, new RequestContext());

        $this->assertEquals(array('what' => 'All', '_route' => 'test'), $matcher->match('/get'));
        $this->assertEquals(array('what' => 'Sites', '_route' => 'test'), $matcher->match('/getSites'));

        // Usually the character in front of an optional parameter can be left out, e.g. with pattern '/get/{what}' just '/get' would match.
        // But here the 't' in 'get' is not a separating character, so it makes no sense to match without it.
        $this->setExpectedException('Symfony\Component\Routing\Exception\ResourceNotFoundException');
        $matcher->match('/ge');
    }

    public function testRequiredVariableWithNoRealSeparator()
    {
        $coll = new RouteCollection();
        $coll->add('test', new Route('/get{what}Suffix'));
        $matcher = new UrlMatcher($coll, new RequestContext());

        $this->assertEquals(array('what' => 'Sites', '_route' => 'test'), $matcher->match('/getSitesSuffix'));
    }

    public function testDefaultRequirementOfVariable()
    {
        $coll = new RouteCollection();
        $coll->add('test', new Route('/{page}.{_format}'));
        $matcher = new UrlMatcher($coll, new RequestContext());

        $this->assertEquals(array('page' => 'index', '_format' => 'mobile.html', '_route' => 'test'), $matcher->match('/index.mobile.html'));
    }

    /**
     * @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException
     */
    public function testDefaultRequirementOfVariableDisallowsSlash()
    {
        $coll = new RouteCollection();
        $coll->add('test', new Route('/{page}.{_format}'));
        $matcher = new UrlMatcher($coll, new RequestContext());

        $matcher->match('/index.sl/ash');
    }

    /**
     * @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException
     */
    public function testDefaultRequirementOfVariableDisallowsNextSeparator()
    {
        $coll = new RouteCollection();
        $coll->add('test', new Route('/{page}.{_format}', array(), array('_format' => 'html|xml')));
        $matcher = new UrlMatcher($coll, new RequestContext());

        $matcher->match('/do.t.html');
    }

    /**
     * @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException
     */
    public function testSchemeRequirement()
    {
        $coll = new RouteCollection();
        $coll->add('foo', new Route('/foo', array(), array('_scheme' => 'https')));
        $matcher = new UrlMatcher($coll, new RequestContext());
        $matcher->match('/foo');
    }

    /**
     * @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException
     */
    public function testCondition()
    {
        $coll = new RouteCollection();
        $route = new Route('/foo');
        $route->setCondition('context.getMethod() == "POST"');
        $coll->add('foo', $route);
        $matcher = new UrlMatcher($coll, new RequestContext());
        $matcher->match('/foo');
    }

    public function testDecodeOnce()
    {
        $coll = new RouteCollection();
        $coll->add('foo', new Route('/foo/{foo}'));

        $matcher = new UrlMatcher($coll, new RequestContext());
        $this->assertEquals(array('foo' => 'bar%23', '_route' => 'foo'), $matcher->match('/foo/bar%2523'));
    }

    public function testCannotRelyOnPrefix()
    {
        $coll = new RouteCollection();

        $subColl = new RouteCollection();
        $subColl->add('bar', new Route('/bar'));
        $subColl->addPrefix('/prefix');
        // overwrite the pattern, so the prefix is not valid anymore for this route in the collection
        $subColl->get('bar')->setPattern('/new');

        $coll->addCollection($subColl);

        $matcher = new UrlMatcher($coll, new RequestContext());
        $this->assertEquals(array('_route' => 'bar'), $matcher->match('/new'));
    }

    public function testWithHost()
    {
        $coll = new RouteCollection();
        $coll->add('foo', new Route('/foo/{foo}', array(), array(), array(), '{locale}.example.com'));

        $matcher = new UrlMatcher($coll, new RequestContext('', 'GET', 'en.example.com'));
        $this->assertEquals(array('foo' => 'bar', '_route' => 'foo', 'locale' => 'en'), $matcher->match('/foo/bar'));
    }

    public function testWithHostOnRouteCollection()
    {
        $coll = new RouteCollection();
        $coll->add('foo', new Route('/foo/{foo}'));
        $coll->add('bar', new Route('/bar/{foo}', array(), array(), array(), '{locale}.example.net'));
        $coll->setHost('{locale}.example.com');

        $matcher = new UrlMatcher($coll, new RequestContext('', 'GET', 'en.example.com'));
        $this->assertEquals(array('foo' => 'bar', '_route' => 'foo', 'locale' => 'en'), $matcher->match('/foo/bar'));

        $matcher = new UrlMatcher($coll, new RequestContext('', 'GET', 'en.example.com'));
        $this->assertEquals(array('foo' => 'bar', '_route' => 'bar', 'locale' => 'en'), $matcher->match('/bar/bar'));
    }

    /**
     * @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException
     */
    public function testWithOutHostHostDoesNotMatch()
    {
        $coll = new RouteCollection();
        $coll->add('foo', new Route('/foo/{foo}', array(), array(), array(), '{locale}.example.com'));

        $matcher = new UrlMatcher($coll, new RequestContext('', 'GET', 'example.com'));
        $matcher->match('/foo/bar');
    }
}
PK��Zȁ@���Ztest/Routing/Symfony/Component/Routing/Tests/Matcher/Dumper/DumperPrefixCollectionTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Tests\Matcher\Dumper;

use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\Matcher\Dumper\DumperPrefixCollection;
use Symfony\Component\Routing\Matcher\Dumper\DumperRoute;
use Symfony\Component\Routing\Matcher\Dumper\DumperCollection;

class DumperPrefixCollectionTest extends \PHPUnit_Framework_TestCase
{
    public function testAddPrefixRoute()
    {
        $coll = new DumperPrefixCollection();
        $coll->setPrefix('');

        $route = new DumperRoute('bar', new Route('/foo/bar'));
        $coll = $coll->addPrefixRoute($route);

        $route = new DumperRoute('bar2', new Route('/foo/bar'));
        $coll = $coll->addPrefixRoute($route);

        $route = new DumperRoute('qux', new Route('/foo/qux'));
        $coll = $coll->addPrefixRoute($route);

        $route = new DumperRoute('bar3', new Route('/foo/bar'));
        $coll = $coll->addPrefixRoute($route);

        $route = new DumperRoute('bar4', new Route(''));
        $result = $coll->addPrefixRoute($route);

        $expect = <<<'EOF'
            |-coll /
            | |-coll /f
            | | |-coll /fo
            | | | |-coll /foo
            | | | | |-coll /foo/
            | | | | | |-coll /foo/b
            | | | | | | |-coll /foo/ba
            | | | | | | | |-coll /foo/bar
            | | | | | | | | |-route bar /foo/bar
            | | | | | | | | |-route bar2 /foo/bar
            | | | | | |-coll /foo/q
            | | | | | | |-coll /foo/qu
            | | | | | | | |-coll /foo/qux
            | | | | | | | | |-route qux /foo/qux
            | | | | | |-coll /foo/b
            | | | | | | |-coll /foo/ba
            | | | | | | | |-coll /foo/bar
            | | | | | | | | |-route bar3 /foo/bar
            | |-route bar4 /

EOF;

        $this->assertSame($expect, $this->collectionToString($result->getRoot(), '            '));
    }

    public function testMergeSlashNodes()
    {
        $coll = new DumperPrefixCollection();
        $coll->setPrefix('');

        $route = new DumperRoute('bar', new Route('/foo/bar'));
        $coll = $coll->addPrefixRoute($route);

        $route = new DumperRoute('bar2', new Route('/foo/bar'));
        $coll = $coll->addPrefixRoute($route);

        $route = new DumperRoute('qux', new Route('/foo/qux'));
        $coll = $coll->addPrefixRoute($route);

        $route = new DumperRoute('bar3', new Route('/foo/bar'));
        $result = $coll->addPrefixRoute($route);

        $result->getRoot()->mergeSlashNodes();

        $expect = <<<'EOF'
            |-coll /f
            | |-coll /fo
            | | |-coll /foo
            | | | |-coll /foo/b
            | | | | |-coll /foo/ba
            | | | | | |-coll /foo/bar
            | | | | | | |-route bar /foo/bar
            | | | | | | |-route bar2 /foo/bar
            | | | |-coll /foo/q
            | | | | |-coll /foo/qu
            | | | | | |-coll /foo/qux
            | | | | | | |-route qux /foo/qux
            | | | |-coll /foo/b
            | | | | |-coll /foo/ba
            | | | | | |-coll /foo/bar
            | | | | | | |-route bar3 /foo/bar

EOF;

        $this->assertSame($expect, $this->collectionToString($result->getRoot(), '            '));
    }

    private function collectionToString(DumperCollection $collection, $prefix)
    {
        $string = '';
        foreach ($collection as $route) {
            if ($route instanceof DumperCollection) {
                $string .= sprintf("%s|-coll %s\n", $prefix, $route->getPrefix());
                $string .= $this->collectionToString($route, $prefix.'| ');
            } else {
                $string .= sprintf("%s|-route %s %s\n", $prefix, $route->getName(), $route->getRoute()->getPath());
            }
        }

        return $string;
    }
}
PK��Z)�#0%%Ttest/Routing/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Tests\Matcher\Dumper;

use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;

class PhpMatcherDumperTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \LogicException
     */
    public function testDumpWhenSchemeIsUsedWithoutAProperDumper()
    {
        $collection = new RouteCollection();
        $collection->add('secure', new Route(
            '/secure',
            array(),
            array('_scheme' => 'https')
        ));
        $dumper = new PhpMatcherDumper($collection);
        $dumper->dump();
    }

    /**
     * @dataProvider getRouteCollections
     */
    public function testDump(RouteCollection $collection, $fixture, $options = array())
    {
        $basePath = __DIR__.'/../../Fixtures/dumper/';

        $dumper = new PhpMatcherDumper($collection);
        $this->assertStringEqualsFile($basePath.$fixture, $dumper->dump($options), '->dump() correctly dumps routes as optimized PHP code.');
    }

    public function getRouteCollections()
    {
        /* test case 1 */

        $collection = new RouteCollection();

        $collection->add('overridden', new Route('/overridden'));

        // defaults and requirements
        $collection->add('foo', new Route(
            '/foo/{bar}',
            array('def' => 'test'),
            array('bar' => 'baz|symfony')
        ));
        // method requirement
        $collection->add('bar', new Route(
            '/bar/{foo}',
            array(),
            array('_method' => 'GET|head')
        ));
        // GET method requirement automatically adds HEAD as valid
        $collection->add('barhead', new Route(
            '/barhead/{foo}',
            array(),
            array('_method' => 'GET')
        ));
        // simple
        $collection->add('baz', new Route(
            '/test/baz'
        ));
        // simple with extension
        $collection->add('baz2', new Route(
            '/test/baz.html'
        ));
        // trailing slash
        $collection->add('baz3', new Route(
            '/test/baz3/'
        ));
        // trailing slash with variable
        $collection->add('baz4', new Route(
            '/test/{foo}/'
        ));
        // trailing slash and method
        $collection->add('baz5', new Route(
            '/test/{foo}/',
            array(),
            array('_method' => 'post')
        ));
        // complex name
        $collection->add('baz.baz6', new Route(
            '/test/{foo}/',
            array(),
            array('_method' => 'put')
        ));
        // defaults without variable
        $collection->add('foofoo', new Route(
            '/foofoo',
            array('def' => 'test')
        ));
        // pattern with quotes
        $collection->add('quoter', new Route(
            '/{quoter}',
            array(),
            array('quoter' => '[\']+')
        ));
        // space in pattern
        $collection->add('space', new Route(
            '/spa ce'
        ));

        // prefixes
        $collection1 = new RouteCollection();
        $collection1->add('overridden', new Route('/overridden1'));
        $collection1->add('foo1', new Route('/{foo}'));
        $collection1->add('bar1', new Route('/{bar}'));
        $collection1->addPrefix('/b\'b');
        $collection2 = new RouteCollection();
        $collection2->addCollection($collection1);
        $collection2->add('overridden', new Route('/{var}', array(), array('var' => '.*')));
        $collection1 = new RouteCollection();
        $collection1->add('foo2', new Route('/{foo1}'));
        $collection1->add('bar2', new Route('/{bar1}'));
        $collection1->addPrefix('/b\'b');
        $collection2->addCollection($collection1);
        $collection2->addPrefix('/a');
        $collection->addCollection($collection2);

        // overridden through addCollection() and multiple sub-collections with no own prefix
        $collection1 = new RouteCollection();
        $collection1->add('overridden2', new Route('/old'));
        $collection1->add('helloWorld', new Route('/hello/{who}', array('who' => 'World!')));
        $collection2 = new RouteCollection();
        $collection3 = new RouteCollection();
        $collection3->add('overridden2', new Route('/new'));
        $collection3->add('hey', new Route('/hey/'));
        $collection2->addCollection($collection3);
        $collection1->addCollection($collection2);
        $collection1->addPrefix('/multi');
        $collection->addCollection($collection1);

        // "dynamic" prefix
        $collection1 = new RouteCollection();
        $collection1->add('foo3', new Route('/{foo}'));
        $collection1->add('bar3', new Route('/{bar}'));
        $collection1->addPrefix('/b');
        $collection1->addPrefix('{_locale}');
        $collection->addCollection($collection1);

        // route between collections
        $collection->add('ababa', new Route('/ababa'));

        // collection with static prefix but only one route
        $collection1 = new RouteCollection();
        $collection1->add('foo4', new Route('/{foo}'));
        $collection1->addPrefix('/aba');
        $collection->addCollection($collection1);

        // prefix and host

        $collection1 = new RouteCollection();

        $route1 = new Route('/route1', array(), array(), array(), 'a.example.com');
        $collection1->add('route1', $route1);

        $collection2 = new RouteCollection();

        $route2 = new Route('/c2/route2', array(), array(), array(), 'a.example.com');
        $collection1->add('route2', $route2);

        $route3 = new Route('/c2/route3', array(), array(), array(), 'b.example.com');
        $collection1->add('route3', $route3);

        $route4 = new Route('/route4', array(), array(), array(), 'a.example.com');
        $collection1->add('route4', $route4);

        $route5 = new Route('/route5', array(), array(), array(), 'c.example.com');
        $collection1->add('route5', $route5);

        $route6 = new Route('/route6', array(), array(), array(), null);
        $collection1->add('route6', $route6);

        $collection->addCollection($collection1);

        // host and variables

        $collection1 = new RouteCollection();

        $route11 = new Route('/route11', array(), array(), array(), '{var1}.example.com');
        $collection1->add('route11', $route11);

        $route12 = new Route('/route12', array('var1' => 'val'), array(), array(), '{var1}.example.com');
        $collection1->add('route12', $route12);

        $route13 = new Route('/route13/{name}', array(), array(), array(), '{var1}.example.com');
        $collection1->add('route13', $route13);

        $route14 = new Route('/route14/{name}', array('var1' => 'val'), array(), array(), '{var1}.example.com');
        $collection1->add('route14', $route14);

        $route15 = new Route('/route15/{name}', array(), array(), array(), 'c.example.com');
        $collection1->add('route15', $route15);

        $route16 = new Route('/route16/{name}', array('var1' => 'val'), array(), array(), null);
        $collection1->add('route16', $route16);

        $route17 = new Route('/route17', array(), array(), array(), null);
        $collection1->add('route17', $route17);

        $collection->addCollection($collection1);

        // multiple sub-collections with a single route and a prefix each
        $collection1 = new RouteCollection();
        $collection1->add('a', new Route('/a...'));
        $collection2 = new RouteCollection();
        $collection2->add('b', new Route('/{var}'));
        $collection3 = new RouteCollection();
        $collection3->add('c', new Route('/{var}'));
        $collection3->addPrefix('/c');
        $collection2->addCollection($collection3);
        $collection2->addPrefix('/b');
        $collection1->addCollection($collection2);
        $collection1->addPrefix('/a');
        $collection->addCollection($collection1);

        /* test case 2 */

        $redirectCollection = clone $collection;

        // force HTTPS redirection
        $redirectCollection->add('secure', new Route(
            '/secure',
            array(),
            array('_scheme' => 'https')
        ));

        // force HTTP redirection
        $redirectCollection->add('nonsecure', new Route(
            '/nonsecure',
            array(),
            array('_scheme' => 'http')
        ));

        /* test case 3 */

        $rootprefixCollection = new RouteCollection();
        $rootprefixCollection->add('static', new Route('/test'));
        $rootprefixCollection->add('dynamic', new Route('/{var}'));
        $rootprefixCollection->addPrefix('rootprefix');
        $route = new Route('/with-condition');
        $route->setCondition('context.getMethod() == "GET"');
        $rootprefixCollection->add('with-condition', $route);

        return array(
           array($collection, 'url_matcher1.php', array()),
           array($redirectCollection, 'url_matcher2.php', array('base_class' => 'Symfony\Component\Routing\Tests\Fixtures\RedirectableUrlMatcher')),
           array($rootprefixCollection, 'url_matcher3.php', array())
        );
    }
}
PK��ZU���Ttest/Routing/Symfony/Component/Routing/Tests/Matcher/Dumper/DumperCollectionTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Tests\Matcher\Dumper;

use Symfony\Component\Routing\Matcher\Dumper\DumperCollection;

class DumperCollectionTest extends \PHPUnit_Framework_TestCase
{
    public function testGetRoot()
    {
        $a = new DumperCollection();

        $b = new DumperCollection();
        $a->add($b);

        $c = new DumperCollection();
        $b->add($c);

        $d = new DumperCollection();
        $c->add($d);

        $this->assertSame($a, $c->getRoot());
    }
}
PK��Z�IQ��Wtest/Routing/Symfony/Component/Routing/Tests/Matcher/Dumper/ApacheMatcherDumperTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Tests\Matcher\Dumper;

use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Matcher\Dumper\ApacheMatcherDumper;

class ApacheMatcherDumperTest extends \PHPUnit_Framework_TestCase
{
    protected static $fixturesPath;

    public static function setUpBeforeClass()
    {
        self::$fixturesPath = realpath(__DIR__.'/../../Fixtures/');
    }

    public function testDump()
    {
        $dumper = new ApacheMatcherDumper($this->getRouteCollection());

        $this->assertStringEqualsFile(self::$fixturesPath.'/dumper/url_matcher1.apache', $dumper->dump(), '->dump() dumps basic routes to the correct apache format.');
    }

    /**
     * @dataProvider provideEscapeFixtures
     */
    public function testEscapePattern($src, $dest, $char, $with, $message)
    {
        $r = new \ReflectionMethod(new ApacheMatcherDumper($this->getRouteCollection()), 'escape');
        $r->setAccessible(true);
        $this->assertEquals($dest, $r->invoke(null, $src, $char, $with), $message);
    }

    public function provideEscapeFixtures()
    {
        return array(
            array('foo', 'foo', ' ', '-', 'Preserve string that should not be escaped'),
            array('fo-o', 'fo-o', ' ', '-', 'Preserve string that should not be escaped'),
            array('fo o', 'fo- o', ' ', '-', 'Escape special characters'),
            array('fo-- o', 'fo--- o', ' ', '-', 'Escape special characters'),
            array('fo- o', 'fo- o', ' ', '-', 'Do not escape already escaped string'),
        );
    }

    public function testEscapeScriptName()
    {
        $collection = new RouteCollection();
        $collection->add('foo', new Route('/foo'));
        $dumper = new ApacheMatcherDumper($collection);
        $this->assertStringEqualsFile(self::$fixturesPath.'/dumper/url_matcher2.apache', $dumper->dump(array('script_name' => 'ap p_d\ ev.php')));
    }

    private function getRouteCollection()
    {
        $collection = new RouteCollection();

        // defaults and requirements
        $collection->add('foo', new Route(
            '/foo/{bar}',
            array('def' => 'test'),
            array('bar' => 'baz|symfony')
        ));
        // defaults parameters in pattern
        $collection->add('foobar', new Route(
            '/foo/{bar}',
            array('bar' => 'toto')
        ));
        // method requirement
        $collection->add('bar', new Route(
            '/bar/{foo}',
            array(),
            array('_method' => 'GET|head')
        ));
        // method requirement (again)
        $collection->add('baragain', new Route(
            '/baragain/{foo}',
            array(),
            array('_method' => 'get|post')
        ));
        // simple
        $collection->add('baz', new Route(
            '/test/baz'
        ));
        // simple with extension
        $collection->add('baz2', new Route(
            '/test/baz.html'
        ));
        // trailing slash
        $collection->add('baz3', new Route(
            '/test/baz3/'
        ));
        // trailing slash with variable
        $collection->add('baz4', new Route(
            '/test/{foo}/'
        ));
        // trailing slash and safe method
        $collection->add('baz5', new Route(
            '/test/{foo}/',
            array(),
            array('_method' => 'get')
        ));
        // trailing slash and unsafe method
        $collection->add('baz5unsafe', new Route(
            '/testunsafe/{foo}/',
            array(),
            array('_method' => 'post')
        ));
        // complex
        $collection->add('baz6', new Route(
            '/test/baz',
            array('foo' => 'bar baz')
        ));
        // space in path
        $collection->add('baz7', new Route(
            '/te st/baz'
        ));
        // space preceded with \ in path
        $collection->add('baz8', new Route(
            '/te\\ st/baz'
        ));
        // space preceded with \ in requirement
        $collection->add('baz9', new Route(
            '/test/{baz}',
            array(),
            array(
                'baz' => 'te\\\\ st',
            )
        ));

        $collection1 = new RouteCollection();

        $route1 = new Route('/route1', array(), array(), array(), 'a.example.com');
        $collection1->add('route1', $route1);

        $collection2 = new RouteCollection();

        $route2 = new Route('/route2', array(), array(), array(), 'a.example.com');
        $collection2->add('route2', $route2);

        $route3 = new Route('/route3', array(), array(), array(), 'b.example.com');
        $collection2->add('route3', $route3);

        $collection2->addPrefix('/c2');
        $collection1->addCollection($collection2);

        $route4 = new Route('/route4', array(), array(), array(), 'a.example.com');
        $collection1->add('route4', $route4);

        $route5 = new Route('/route5', array(), array(), array(), 'c.example.com');
        $collection1->add('route5', $route5);

        $route6 = new Route('/route6', array(), array(), array(), null);
        $collection1->add('route6', $route6);

        $collection->addCollection($collection1);

        // host and variables

        $collection1 = new RouteCollection();

        $route11 = new Route('/route11', array(), array(), array(), '{var1}.example.com');
        $collection1->add('route11', $route11);

        $route12 = new Route('/route12', array('var1' => 'val'), array(), array(), '{var1}.example.com');
        $collection1->add('route12', $route12);

        $route13 = new Route('/route13/{name}', array(), array(), array(), '{var1}.example.com');
        $collection1->add('route13', $route13);

        $route14 = new Route('/route14/{name}', array('var1' => 'val'), array(), array(), '{var1}.example.com');
        $collection1->add('route14', $route14);

        $route15 = new Route('/route15/{name}', array(), array(), array(), 'c.example.com');
        $collection1->add('route15', $route15);

        $route16 = new Route('/route16/{name}', array('var1' => 'val'), array(), array(), null);
        $collection1->add('route16', $route16);

        $route17 = new Route('/route17', array(), array(), array(), null);
        $collection1->add('route17', $route17);

        $collection->addCollection($collection1);

        return $collection;
    }
}
PK��Z�̼�aaMtest/Routing/Symfony/Component/Routing/Tests/Matcher/ApacheUrlMatcherTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Tests\Matcher;

use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\Matcher\ApacheUrlMatcher;

class ApacheUrlMatcherTest extends \PHPUnit_Framework_TestCase
{
    protected $server;

    protected function setUp()
    {
        $this->server = $_SERVER;
    }

    protected function tearDown()
    {
        $_SERVER = $this->server;
    }

    /**
     * @dataProvider getMatchData
     */
    public function testMatch($name, $pathinfo, $server, $expect)
    {
        $collection = new RouteCollection();
        $context = new RequestContext();
        $matcher = new ApacheUrlMatcher($collection, $context);

        $_SERVER = $server;

        $result = $matcher->match($pathinfo, $server);
        $this->assertSame(var_export($expect, true), var_export($result, true));
    }

    public function getMatchData()
    {
        return array(
            array(
                'Simple route',
                '/hello/world',
                array(
                    '_ROUTING_route' => 'hello',
                    '_ROUTING_param__controller' => 'AcmeBundle:Default:index',
                    '_ROUTING_param_name' => 'world',
                ),
                array(
                    '_controller' => 'AcmeBundle:Default:index',
                    'name' => 'world',
                    '_route' => 'hello',
                ),
            ),
            array(
                'Route with params and defaults',
                '/hello/hugo',
                array(
                    '_ROUTING_route' => 'hello',
                    '_ROUTING_param__controller' => 'AcmeBundle:Default:index',
                    '_ROUTING_param_name' => 'hugo',
                    '_ROUTING_default_name' => 'world',
                ),
                array(
                    'name' => 'hugo',
                    '_controller' => 'AcmeBundle:Default:index',
                    '_route' => 'hello',
                ),
            ),
            array(
                'Route with defaults only',
                '/hello',
                array(
                    '_ROUTING_route' => 'hello',
                    '_ROUTING_param__controller' => 'AcmeBundle:Default:index',
                    '_ROUTING_default_name' => 'world',
                ),
                array(
                    'name' => 'world',
                    '_controller' => 'AcmeBundle:Default:index',
                    '_route' => 'hello',
                ),
            ),
            array(
                'Redirect with many ignored attributes',
                '/legacy/{cat1}/{cat2}/{id}.html',
                array(
                    '_ROUTING_route' => 'product_view',
                    '_ROUTING_param__controller' => 'FrameworkBundle:Redirect:redirect',
                    '_ROUTING_default_ignoreAttributes[0]' => 'attr_a',
                    '_ROUTING_default_ignoreAttributes[1]' => 'attr_b',
                ),
                array(
                    'ignoreAttributes' => array('attr_a', 'attr_b'),
                    '_controller' => 'FrameworkBundle:Redirect:redirect',
                    '_route' => 'product_view',
                )
            ),
            array(
                'REDIRECT_ envs',
                '/hello/world',
                array(
                    'REDIRECT__ROUTING_route' => 'hello',
                    'REDIRECT__ROUTING_param__controller' => 'AcmeBundle:Default:index',
                    'REDIRECT__ROUTING_param_name' => 'world',
                ),
                array(
                    '_controller' => 'AcmeBundle:Default:index',
                    'name' => 'world',
                    '_route' => 'hello',
                ),
            ),
            array(
                'REDIRECT_REDIRECT_ envs',
                '/hello/world',
                array(
                    'REDIRECT_REDIRECT__ROUTING_route' => 'hello',
                    'REDIRECT_REDIRECT__ROUTING_param__controller' => 'AcmeBundle:Default:index',
                    'REDIRECT_REDIRECT__ROUTING_param_name' => 'world',
                ),
                array(
                    '_controller' => 'AcmeBundle:Default:index',
                    'name' => 'world',
                    '_route' => 'hello',
                ),
            ),
            array(
                'REDIRECT_REDIRECT_ envs',
                '/hello/world',
                array(
                    'REDIRECT_REDIRECT__ROUTING_route' => 'hello',
                    'REDIRECT_REDIRECT__ROUTING_param__controller' => 'AcmeBundle:Default:index',
                    'REDIRECT_REDIRECT__ROUTING_param_name' => 'world',
                ),
                array(
                    '_controller' => 'AcmeBundle:Default:index',
                    'name' => 'world',
                    '_route' => 'hello',
                ),
            )
        );
    }
}
PK��ZA ���Stest/Routing/Symfony/Component/Routing/Tests/Matcher/RedirectableUrlMatcherTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Tests\Matcher;

use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\RequestContext;

class RedirectableUrlMatcherTest extends \PHPUnit_Framework_TestCase
{
    public function testRedirectWhenNoSlash()
    {
        $coll = new RouteCollection();
        $coll->add('foo', new Route('/foo/'));

        $matcher = $this->getMockForAbstractClass('Symfony\Component\Routing\Matcher\RedirectableUrlMatcher', array($coll, new RequestContext()));
        $matcher->expects($this->once())->method('redirect');
        $matcher->match('/foo');
    }

    /**
     * @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException
     */
    public function testRedirectWhenNoSlashForNonSafeMethod()
    {
        $coll = new RouteCollection();
        $coll->add('foo', new Route('/foo/'));

        $context = new RequestContext();
        $context->setMethod('POST');
        $matcher = $this->getMockForAbstractClass('Symfony\Component\Routing\Matcher\RedirectableUrlMatcher', array($coll, $context));
        $matcher->match('/foo');
    }

    public function testSchemeRedirect()
    {
        $coll = new RouteCollection();
        $coll->add('foo', new Route('/foo', array(), array('_scheme' => 'https')));

        $matcher = $this->getMockForAbstractClass('Symfony\Component\Routing\Matcher\RedirectableUrlMatcher', array($coll, new RequestContext()));
        $matcher
            ->expects($this->once())
            ->method('redirect')
            ->with('/foo', 'foo', 'https')
            ->will($this->returnValue(array('_route' => 'foo')))
        ;
        $matcher->match('/foo');
    }
}
PK��Z%"�?7?7Dtest/Routing/Symfony/Component/Routing/Tests/RouteCollectionTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Tests;

use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;
use Symfony\Component\Config\Resource\FileResource;

class RouteCollectionTest extends \PHPUnit_Framework_TestCase
{
    public function testRoute()
    {
        $collection = new RouteCollection();
        $route = new Route('/foo');
        $collection->add('foo', $route);
        $this->assertEquals(array('foo' => $route), $collection->all(), '->add() adds a route');
        $this->assertEquals($route, $collection->get('foo'), '->get() returns a route by name');
        $this->assertNull($collection->get('bar'), '->get() returns null if a route does not exist');
    }

    public function testOverriddenRoute()
    {
        $collection = new RouteCollection();
        $collection->add('foo', new Route('/foo'));
        $collection->add('foo', new Route('/foo1'));

        $this->assertEquals('/foo1', $collection->get('foo')->getPath());
    }

    public function testDeepOverriddenRoute()
    {
        $collection = new RouteCollection();
        $collection->add('foo', new Route('/foo'));

        $collection1 = new RouteCollection();
        $collection1->add('foo', new Route('/foo1'));

        $collection2 = new RouteCollection();
        $collection2->add('foo', new Route('/foo2'));

        $collection1->addCollection($collection2);
        $collection->addCollection($collection1);

        $this->assertEquals('/foo2', $collection1->get('foo')->getPath());
        $this->assertEquals('/foo2', $collection->get('foo')->getPath());
    }

    public function testIterator()
    {
        $collection = new RouteCollection();
        $collection->add('foo', new Route('/foo'));

        $collection1 = new RouteCollection();
        $collection1->add('bar', $bar = new Route('/bar'));
        $collection1->add('foo', $foo = new Route('/foo-new'));
        $collection->addCollection($collection1);
        $collection->add('last', $last = new Route('/last'));

        $this->assertInstanceOf('\ArrayIterator', $collection->getIterator());
        $this->assertSame(array('bar' => $bar, 'foo' => $foo, 'last' => $last), $collection->getIterator()->getArrayCopy());
    }

    public function testCount()
    {
        $collection = new RouteCollection();
        $collection->add('foo', new Route('/foo'));

        $collection1 = new RouteCollection();
        $collection1->add('bar', new Route('/bar'));
        $collection->addCollection($collection1);

        $this->assertCount(2, $collection);
    }

    public function testAddCollection()
    {
        $collection = new RouteCollection();
        $collection->add('foo', new Route('/foo'));

        $collection1 = new RouteCollection();
        $collection1->add('bar', $bar = new Route('/bar'));
        $collection1->add('foo', $foo = new Route('/foo-new'));

        $collection2 = new RouteCollection();
        $collection2->add('grandchild', $grandchild = new Route('/grandchild'));

        $collection1->addCollection($collection2);
        $collection->addCollection($collection1);
        $collection->add('last', $last = new Route('/last'));

        $this->assertSame(array('bar' => $bar, 'foo' => $foo, 'grandchild' => $grandchild, 'last' => $last), $collection->all(),
            '->addCollection() imports routes of another collection, overrides if necessary and adds them at the end');
    }

    public function testAddCollectionWithResources()
    {
        $collection = new RouteCollection();
        $collection->addResource($foo = new FileResource(__DIR__.'/Fixtures/foo.xml'));
        $collection1 = new RouteCollection();
        $collection1->addResource($foo1 = new FileResource(__DIR__.'/Fixtures/foo1.xml'));
        $collection->addCollection($collection1);
        $this->assertEquals(array($foo, $foo1), $collection->getResources(), '->addCollection() merges resources');
    }

    public function testAddDefaultsAndRequirementsAndOptions()
    {
        $collection = new RouteCollection();
        $collection->add('foo', new Route('/{placeholder}'));
        $collection1 = new RouteCollection();
        $collection1->add('bar', new Route('/{placeholder}',
            array('_controller' => 'fixed', 'placeholder' => 'default'), array('placeholder' => '.+'), array('option' => 'value'))
        );
        $collection->addCollection($collection1);

        $collection->addDefaults(array('placeholder' => 'new-default'));
        $this->assertEquals(array('placeholder' => 'new-default'), $collection->get('foo')->getDefaults(), '->addDefaults() adds defaults to all routes');
        $this->assertEquals(array('_controller' => 'fixed', 'placeholder' => 'new-default'), $collection->get('bar')->getDefaults(),
            '->addDefaults() adds defaults to all routes and overwrites existing ones');

        $collection->addRequirements(array('placeholder' => '\d+'));
        $this->assertEquals(array('placeholder' => '\d+'), $collection->get('foo')->getRequirements(), '->addRequirements() adds requirements to all routes');
        $this->assertEquals(array('placeholder' => '\d+'), $collection->get('bar')->getRequirements(),
            '->addRequirements() adds requirements to all routes and overwrites existing ones');

        $collection->addOptions(array('option' => 'new-value'));
        $this->assertEquals(
            array('option' => 'new-value', 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler'),
            $collection->get('bar')->getOptions(), '->addOptions() adds options to all routes and overwrites existing ones'
        );
    }

    public function testAddPrefix()
    {
        $collection = new RouteCollection();
        $collection->add('foo', $foo = new Route('/foo'));
        $collection2 = new RouteCollection();
        $collection2->add('bar', $bar = new Route('/bar'));
        $collection->addCollection($collection2);
        $collection->addPrefix(' / ');
        $this->assertSame('/foo', $collection->get('foo')->getPattern(), '->addPrefix() trims the prefix and a single slash has no effect');
        $collection->addPrefix('/{admin}', array('admin' => 'admin'), array('admin' => '\d+'));
        $this->assertEquals('/{admin}/foo', $collection->get('foo')->getPath(), '->addPrefix() adds a prefix to all routes');
        $this->assertEquals('/{admin}/bar', $collection->get('bar')->getPath(), '->addPrefix() adds a prefix to all routes');
        $this->assertEquals(array('admin' => 'admin'), $collection->get('foo')->getDefaults(), '->addPrefix() adds defaults to all routes');
        $this->assertEquals(array('admin' => 'admin'), $collection->get('bar')->getDefaults(), '->addPrefix() adds defaults to all routes');
        $this->assertEquals(array('admin' => '\d+'), $collection->get('foo')->getRequirements(), '->addPrefix() adds requirements to all routes');
        $this->assertEquals(array('admin' => '\d+'), $collection->get('bar')->getRequirements(), '->addPrefix() adds requirements to all routes');
        $collection->addPrefix('0');
        $this->assertEquals('/0/{admin}/foo', $collection->get('foo')->getPattern(), '->addPrefix() ensures a prefix must start with a slash and must not end with a slash');
        $collection->addPrefix('/ /');
        $this->assertSame('/ /0/{admin}/foo', $collection->get('foo')->getPath(), '->addPrefix() can handle spaces if desired');
        $this->assertSame('/ /0/{admin}/bar', $collection->get('bar')->getPath(), 'the route pattern of an added collection is in synch with the added prefix');
    }

    public function testAddPrefixOverridesDefaultsAndRequirements()
    {
        $collection = new RouteCollection();
        $collection->add('foo', $foo = new Route('/foo'));
        $collection->add('bar', $bar = new Route('/bar', array(), array('_scheme' => 'http')));
        $collection->addPrefix('/admin', array(), array('_scheme' => 'https'));

        $this->assertEquals('https', $collection->get('foo')->getRequirement('_scheme'), '->addPrefix() overrides existing requirements');
        $this->assertEquals('https', $collection->get('bar')->getRequirement('_scheme'), '->addPrefix() overrides existing requirements');
    }

    public function testResource()
    {
        $collection = new RouteCollection();
        $collection->addResource($foo = new FileResource(__DIR__.'/Fixtures/foo.xml'));
        $collection->addResource($bar = new FileResource(__DIR__.'/Fixtures/bar.xml'));
        $collection->addResource(new FileResource(__DIR__.'/Fixtures/foo.xml'));

        $this->assertEquals(array($foo, $bar), $collection->getResources(),
            '->addResource() adds a resource and getResources() only returns unique ones by comparing the string representation');
    }

    public function testUniqueRouteWithGivenName()
    {
        $collection1 = new RouteCollection();
        $collection1->add('foo', new Route('/old'));
        $collection2 = new RouteCollection();
        $collection3 = new RouteCollection();
        $collection3->add('foo', $new = new Route('/new'));

        $collection2->addCollection($collection3);
        $collection1->addCollection($collection2);

        $this->assertSame($new, $collection1->get('foo'), '->get() returns new route that overrode previous one');
        // size of 1 because collection1 contains /new but not /old anymore
        $this->assertCount(1, $collection1->getIterator(), '->addCollection() removes previous routes when adding new routes with the same name');
    }

    public function testGet()
    {
        $collection1 = new RouteCollection();
        $collection1->add('a', $a = new Route('/a'));
        $collection2 = new RouteCollection();
        $collection2->add('b', $b = new Route('/b'));
        $collection1->addCollection($collection2);
        $collection1->add('$péß^a|', $c = new Route('/special'));

        $this->assertSame($b, $collection1->get('b'), '->get() returns correct route in child collection');
        $this->assertSame($c, $collection1->get('$péß^a|'), '->get() can handle special characters');
        $this->assertNull($collection2->get('a'), '->get() does not return the route defined in parent collection');
        $this->assertNull($collection1->get('non-existent'), '->get() returns null when route does not exist');
        $this->assertNull($collection1->get(0), '->get() does not disclose internal child RouteCollection');
    }

    public function testRemove()
    {
        $collection = new RouteCollection();
        $collection->add('foo', $foo = new Route('/foo'));

        $collection1 = new RouteCollection();
        $collection1->add('bar', $bar = new Route('/bar'));
        $collection->addCollection($collection1);
        $collection->add('last', $last = new Route('/last'));

        $collection->remove('foo');
        $this->assertSame(array('bar' => $bar, 'last' => $last), $collection->all(), '->remove() can remove a single route');
        $collection->remove(array('bar', 'last'));
        $this->assertSame(array(), $collection->all(), '->remove() accepts an array and can remove multiple routes at once');
    }

    public function testSetHost()
    {
        $collection = new RouteCollection();
        $routea = new Route('/a');
        $routeb = new Route('/b', array(), array(), array(), '{locale}.example.net');
        $collection->add('a', $routea);
        $collection->add('b', $routeb);

        $collection->setHost('{locale}.example.com');

        $this->assertEquals('{locale}.example.com', $routea->getHost());
        $this->assertEquals('{locale}.example.com', $routeb->getHost());
    }

    public function testSetCondition()
    {
        $collection = new RouteCollection();
        $routea = new Route('/a');
        $routeb = new Route('/b', array(), array(), array(), '{locale}.example.net', array(), array(), 'context.getMethod() == "GET"');
        $collection->add('a', $routea);
        $collection->add('b', $routeb);

        $collection->setCondition('context.getMethod() == "POST"');

        $this->assertEquals('context.getMethod() == "POST"', $routea->getCondition());
        $this->assertEquals('context.getMethod() == "POST"', $routeb->getCondition());
    }

    public function testClone()
    {
        $collection = new RouteCollection();
        $collection->add('a', new Route('/a'));
        $collection->add('b', new Route('/b', array('placeholder' => 'default'), array('placeholder' => '.+')));

        $clonedCollection = clone $collection;

        $this->assertCount(2, $clonedCollection);
        $this->assertEquals($collection->get('a'), $clonedCollection->get('a'));
        $this->assertNotSame($collection->get('a'), $clonedCollection->get('a'));
        $this->assertEquals($collection->get('b'), $clonedCollection->get('b'));
        $this->assertNotSame($collection->get('b'), $clonedCollection->get('b'));
    }

    public function testSetSchemes()
    {
        $collection = new RouteCollection();
        $routea = new Route('/a', array(), array(), array(), '', 'http');
        $routeb = new Route('/b');
        $collection->add('a', $routea);
        $collection->add('b', $routeb);

        $collection->setSchemes(array('http', 'https'));

        $this->assertEquals(array('http', 'https'), $routea->getSchemes());
        $this->assertEquals(array('http', 'https'), $routeb->getSchemes());
    }

    public function testSetMethods()
    {
        $collection = new RouteCollection();
        $routea = new Route('/a', array(), array(), array(), '', array(), array('GET', 'POST'));
        $routeb = new Route('/b');
        $collection->add('a', $routea);
        $collection->add('b', $routeb);

        $collection->setMethods('PUT');

        $this->assertEquals(array('PUT'), $routea->getMethods());
        $this->assertEquals(array('PUT'), $routeb->getMethods());
    }
}
PK��Z kl�g�gKtest/Routing/Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Tests\Generator;

use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\Generator\UrlGenerator;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\RequestContext;

class UrlGeneratorTest extends \PHPUnit_Framework_TestCase
{
    public function testAbsoluteUrlWithPort80()
    {
        $routes = $this->getRoutes('test', new Route('/testing'));
        $url = $this->getGenerator($routes)->generate('test', array(), true);

        $this->assertEquals('http://localhost/app.php/testing', $url);
    }

    public function testAbsoluteSecureUrlWithPort443()
    {
        $routes = $this->getRoutes('test', new Route('/testing'));
        $url = $this->getGenerator($routes, array('scheme' => 'https'))->generate('test', array(), true);

        $this->assertEquals('https://localhost/app.php/testing', $url);
    }

    public function testAbsoluteUrlWithNonStandardPort()
    {
        $routes = $this->getRoutes('test', new Route('/testing'));
        $url = $this->getGenerator($routes, array('httpPort' => 8080))->generate('test', array(), true);

        $this->assertEquals('http://localhost:8080/app.php/testing', $url);
    }

    public function testAbsoluteSecureUrlWithNonStandardPort()
    {
        $routes = $this->getRoutes('test', new Route('/testing'));
        $url = $this->getGenerator($routes, array('httpsPort' => 8080, 'scheme' => 'https'))->generate('test', array(), true);

        $this->assertEquals('https://localhost:8080/app.php/testing', $url);
    }

    public function testRelativeUrlWithoutParameters()
    {
        $routes = $this->getRoutes('test', new Route('/testing'));
        $url = $this->getGenerator($routes)->generate('test', array(), false);

        $this->assertEquals('/app.php/testing', $url);
    }

    public function testRelativeUrlWithParameter()
    {
        $routes = $this->getRoutes('test', new Route('/testing/{foo}'));
        $url = $this->getGenerator($routes)->generate('test', array('foo' => 'bar'), false);

        $this->assertEquals('/app.php/testing/bar', $url);
    }

    public function testRelativeUrlWithNullParameter()
    {
        $routes = $this->getRoutes('test', new Route('/testing.{format}', array('format' => null)));
        $url = $this->getGenerator($routes)->generate('test', array(), false);

        $this->assertEquals('/app.php/testing', $url);
    }

    /**
     * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException
     */
    public function testRelativeUrlWithNullParameterButNotOptional()
    {
        $routes = $this->getRoutes('test', new Route('/testing/{foo}/bar', array('foo' => null)));
        // This must raise an exception because the default requirement for "foo" is "[^/]+" which is not met with these params.
        // Generating path "/testing//bar" would be wrong as matching this route would fail.
        $this->getGenerator($routes)->generate('test', array(), false);
    }

    public function testRelativeUrlWithOptionalZeroParameter()
    {
        $routes = $this->getRoutes('test', new Route('/testing/{page}'));
        $url = $this->getGenerator($routes)->generate('test', array('page' => 0), false);

        $this->assertEquals('/app.php/testing/0', $url);
    }

    public function testNotPassedOptionalParameterInBetween()
    {
        $routes = $this->getRoutes('test', new Route('/{slug}/{page}', array('slug' => 'index', 'page' => 0)));
        $this->assertSame('/app.php/index/1', $this->getGenerator($routes)->generate('test', array('page' => 1)));
        $this->assertSame('/app.php/', $this->getGenerator($routes)->generate('test'));
    }

    public function testRelativeUrlWithExtraParameters()
    {
        $routes = $this->getRoutes('test', new Route('/testing'));
        $url = $this->getGenerator($routes)->generate('test', array('foo' => 'bar'), false);

        $this->assertEquals('/app.php/testing?foo=bar', $url);
    }

    public function testAbsoluteUrlWithExtraParameters()
    {
        $routes = $this->getRoutes('test', new Route('/testing'));
        $url = $this->getGenerator($routes)->generate('test', array('foo' => 'bar'), true);

        $this->assertEquals('http://localhost/app.php/testing?foo=bar', $url);
    }

    public function testUrlWithNullExtraParameters()
    {
        $routes = $this->getRoutes('test', new Route('/testing'));
        $url = $this->getGenerator($routes)->generate('test', array('foo' => null), true);

        $this->assertEquals('http://localhost/app.php/testing', $url);
    }

    public function testUrlWithExtraParametersFromGlobals()
    {
        $routes = $this->getRoutes('test', new Route('/testing'));
        $generator = $this->getGenerator($routes);
        $context = new RequestContext('/app.php');
        $context->setParameter('bar', 'bar');
        $generator->setContext($context);
        $url = $generator->generate('test', array('foo' => 'bar'));

        $this->assertEquals('/app.php/testing?foo=bar', $url);
    }

    public function testUrlWithGlobalParameter()
    {
        $routes = $this->getRoutes('test', new Route('/testing/{foo}'));
        $generator = $this->getGenerator($routes);
        $context = new RequestContext('/app.php');
        $context->setParameter('foo', 'bar');
        $generator->setContext($context);
        $url = $generator->generate('test', array());

        $this->assertEquals('/app.php/testing/bar', $url);
    }

    public function testGlobalParameterHasHigherPriorityThanDefault()
    {
        $routes = $this->getRoutes('test', new Route('/{_locale}', array('_locale' => 'en')));
        $generator = $this->getGenerator($routes);
        $context = new RequestContext('/app.php');
        $context->setParameter('_locale', 'de');
        $generator->setContext($context);
        $url = $generator->generate('test', array());

        $this->assertSame('/app.php/de', $url);
    }

    /**
     * @expectedException \Symfony\Component\Routing\Exception\RouteNotFoundException
     */
    public function testGenerateWithoutRoutes()
    {
        $routes = $this->getRoutes('foo', new Route('/testing/{foo}'));
        $this->getGenerator($routes)->generate('test', array(), true);
    }

    /**
     * @expectedException \Symfony\Component\Routing\Exception\MissingMandatoryParametersException
     */
    public function testGenerateForRouteWithoutMandatoryParameter()
    {
        $routes = $this->getRoutes('test', new Route('/testing/{foo}'));
        $this->getGenerator($routes)->generate('test', array(), true);
    }

    /**
     * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException
     */
    public function testGenerateForRouteWithInvalidOptionalParameter()
    {
        $routes = $this->getRoutes('test', new Route('/testing/{foo}', array('foo' => '1'), array('foo' => 'd+')));
        $this->getGenerator($routes)->generate('test', array('foo' => 'bar'), true);
    }

    /**
     * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException
     */
    public function testGenerateForRouteWithInvalidParameter()
    {
        $routes = $this->getRoutes('test', new Route('/testing/{foo}', array(), array('foo' => '1|2')));
        $this->getGenerator($routes)->generate('test', array('foo' => '0'), true);
    }

    public function testGenerateForRouteWithInvalidOptionalParameterNonStrict()
    {
        $routes = $this->getRoutes('test', new Route('/testing/{foo}', array('foo' => '1'), array('foo' => 'd+')));
        $generator = $this->getGenerator($routes);
        $generator->setStrictRequirements(false);
        $this->assertNull($generator->generate('test', array('foo' => 'bar'), true));
    }

    public function testGenerateForRouteWithInvalidOptionalParameterNonStrictWithLogger()
    {
        $routes = $this->getRoutes('test', new Route('/testing/{foo}', array('foo' => '1'), array('foo' => 'd+')));
        $logger = $this->getMock('Psr\Log\LoggerInterface');
        $logger->expects($this->once())
            ->method('error');
        $generator = $this->getGenerator($routes, array(), $logger);
        $generator->setStrictRequirements(false);
        $this->assertNull($generator->generate('test', array('foo' => 'bar'), true));
    }

    public function testGenerateForRouteWithInvalidParameterButDisabledRequirementsCheck()
    {
        $routes = $this->getRoutes('test', new Route('/testing/{foo}', array('foo' => '1'), array('foo' => 'd+')));
        $generator = $this->getGenerator($routes);
        $generator->setStrictRequirements(null);
        $this->assertSame('/app.php/testing/bar', $generator->generate('test', array('foo' => 'bar')));
    }

    /**
     * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException
     */
    public function testGenerateForRouteWithInvalidMandatoryParameter()
    {
        $routes = $this->getRoutes('test', new Route('/testing/{foo}', array(), array('foo' => 'd+')));
        $this->getGenerator($routes)->generate('test', array('foo' => 'bar'), true);
    }

    /**
     * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException
     */
    public function testRequiredParamAndEmptyPassed()
    {
        $routes = $this->getRoutes('test', new Route('/{slug}', array(), array('slug' => '.+')));
        $this->getGenerator($routes)->generate('test', array('slug' => ''));
    }

    public function testSchemeRequirementDoesNothingIfSameCurrentScheme()
    {
        $routes = $this->getRoutes('test', new Route('/', array(), array('_scheme' => 'http')));
        $this->assertEquals('/app.php/', $this->getGenerator($routes)->generate('test'));

        $routes = $this->getRoutes('test', new Route('/', array(), array('_scheme' => 'https')));
        $this->assertEquals('/app.php/', $this->getGenerator($routes, array('scheme' => 'https'))->generate('test'));
    }

    public function testSchemeRequirementForcesAbsoluteUrl()
    {
        $routes = $this->getRoutes('test', new Route('/', array(), array('_scheme' => 'https')));
        $this->assertEquals('https://localhost/app.php/', $this->getGenerator($routes)->generate('test'));

        $routes = $this->getRoutes('test', new Route('/', array(), array('_scheme' => 'http')));
        $this->assertEquals('http://localhost/app.php/', $this->getGenerator($routes, array('scheme' => 'https'))->generate('test'));
    }

    public function testPathWithTwoStartingSlashes()
    {
        $routes = $this->getRoutes('test', new Route('//path-and-not-domain'));

        // this must not generate '//path-and-not-domain' because that would be a network path
        $this->assertSame('/path-and-not-domain', $this->getGenerator($routes, array('BaseUrl' => ''))->generate('test'));
    }

    public function testNoTrailingSlashForMultipleOptionalParameters()
    {
        $routes = $this->getRoutes('test', new Route('/category/{slug1}/{slug2}/{slug3}', array('slug2' => null, 'slug3' => null)));

        $this->assertEquals('/app.php/category/foo', $this->getGenerator($routes)->generate('test', array('slug1' => 'foo')));
    }

    public function testWithAnIntegerAsADefaultValue()
    {
        $routes = $this->getRoutes('test', new Route('/{default}', array('default' => 0)));

        $this->assertEquals('/app.php/foo', $this->getGenerator($routes)->generate('test', array('default' => 'foo')));
    }

    public function testNullForOptionalParameterIsIgnored()
    {
        $routes = $this->getRoutes('test', new Route('/test/{default}', array('default' => 0)));

        $this->assertEquals('/app.php/test', $this->getGenerator($routes)->generate('test', array('default' => null)));
    }

    public function testQueryParamSameAsDefault()
    {
        $routes = $this->getRoutes('test', new Route('/test', array('default' => 'value')));

        $this->assertSame('/app.php/test', $this->getGenerator($routes)->generate('test', array('default' => 'foo')));
        $this->assertSame('/app.php/test', $this->getGenerator($routes)->generate('test', array('default' => 'value')));
        $this->assertSame('/app.php/test', $this->getGenerator($routes)->generate('test'));
    }

    public function testGenerateWithSpecialRouteName()
    {
        $routes = $this->getRoutes('$péß^a|', new Route('/bar'));

        $this->assertSame('/app.php/bar', $this->getGenerator($routes)->generate('$péß^a|'));
    }

    public function testUrlEncoding()
    {
        // This tests the encoding of reserved characters that are used for delimiting of URI components (defined in RFC 3986)
        // and other special ASCII chars. These chars are tested as static text path, variable path and query param.
        $chars = '@:[]/()*\'" +,;-._~&$<>|{}%\\^`!?foo=bar#id';
        $routes = $this->getRoutes('test', new Route("/$chars/{varpath}", array(), array('varpath' => '.+')));
        $this->assertSame('/app.php/@:%5B%5D/%28%29*%27%22%20+,;-._~%26%24%3C%3E|%7B%7D%25%5C%5E%60!%3Ffoo=bar%23id'
           .'/@:%5B%5D/%28%29*%27%22%20+,;-._~%26%24%3C%3E|%7B%7D%25%5C%5E%60!%3Ffoo=bar%23id'
           .'?query=%40%3A%5B%5D%2F%28%29%2A%27%22+%2B%2C%3B-._%7E%26%24%3C%3E%7C%7B%7D%25%5C%5E%60%21%3Ffoo%3Dbar%23id',
            $this->getGenerator($routes)->generate('test', array(
                'varpath' => $chars,
                'query' => $chars
            ))
        );
    }

    public function testEncodingOfRelativePathSegments()
    {
        $routes = $this->getRoutes('test', new Route('/dir/../dir/..'));
        $this->assertSame('/app.php/dir/%2E%2E/dir/%2E%2E', $this->getGenerator($routes)->generate('test'));
        $routes = $this->getRoutes('test', new Route('/dir/./dir/.'));
        $this->assertSame('/app.php/dir/%2E/dir/%2E', $this->getGenerator($routes)->generate('test'));
        $routes = $this->getRoutes('test', new Route('/a./.a/a../..a/...'));
        $this->assertSame('/app.php/a./.a/a../..a/...', $this->getGenerator($routes)->generate('test'));
    }

    public function testAdjacentVariables()
    {
        $routes = $this->getRoutes('test', new Route('/{x}{y}{z}.{_format}', array('z' => 'default-z', '_format' => 'html'), array('y' => '\d+')));
        $generator = $this->getGenerator($routes);
        $this->assertSame('/app.php/foo123', $generator->generate('test', array('x' => 'foo', 'y' => '123')));
        $this->assertSame('/app.php/foo123bar.xml', $generator->generate('test', array('x' => 'foo', 'y' => '123', 'z' => 'bar', '_format' => 'xml')));

        // The default requirement for 'x' should not allow the separator '.' in this case because it would otherwise match everything
        // and following optional variables like _format could never match.
        $this->setExpectedException('Symfony\Component\Routing\Exception\InvalidParameterException');
        $generator->generate('test', array('x' => 'do.t', 'y' => '123', 'z' => 'bar', '_format' => 'xml'));
    }

    public function testOptionalVariableWithNoRealSeparator()
    {
        $routes = $this->getRoutes('test', new Route('/get{what}', array('what' => 'All')));
        $generator = $this->getGenerator($routes);

        $this->assertSame('/app.php/get', $generator->generate('test'));
        $this->assertSame('/app.php/getSites', $generator->generate('test', array('what' => 'Sites')));
    }

    public function testRequiredVariableWithNoRealSeparator()
    {
        $routes = $this->getRoutes('test', new Route('/get{what}Suffix'));
        $generator = $this->getGenerator($routes);

        $this->assertSame('/app.php/getSitesSuffix', $generator->generate('test', array('what' => 'Sites')));
    }

    public function testDefaultRequirementOfVariable()
    {
        $routes = $this->getRoutes('test', new Route('/{page}.{_format}'));
        $generator = $this->getGenerator($routes);

        $this->assertSame('/app.php/index.mobile.html', $generator->generate('test', array('page' => 'index', '_format' => 'mobile.html')));
    }

    /**
     * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException
     */
    public function testDefaultRequirementOfVariableDisallowsSlash()
    {
        $routes = $this->getRoutes('test', new Route('/{page}.{_format}'));
        $this->getGenerator($routes)->generate('test', array('page' => 'index', '_format' => 'sl/ash'));
    }

    /**
     * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException
     */
    public function testDefaultRequirementOfVariableDisallowsNextSeparator()
    {
        $routes = $this->getRoutes('test', new Route('/{page}.{_format}'));
        $this->getGenerator($routes)->generate('test', array('page' => 'do.t', '_format' => 'html'));
    }

    public function testWithHostDifferentFromContext()
    {
        $routes = $this->getRoutes('test', new Route('/{name}', array(), array(), array(), '{locale}.example.com'));

        $this->assertEquals('//fr.example.com/app.php/Fabien', $this->getGenerator($routes)->generate('test', array('name' =>'Fabien', 'locale' => 'fr')));
    }

    public function testWithHostSameAsContext()
    {
        $routes = $this->getRoutes('test', new Route('/{name}', array(), array(), array(), '{locale}.example.com'));

        $this->assertEquals('/app.php/Fabien', $this->getGenerator($routes, array('host' => 'fr.example.com'))->generate('test', array('name' =>'Fabien', 'locale' => 'fr')));
    }

    public function testWithHostSameAsContextAndAbsolute()
    {
        $routes = $this->getRoutes('test', new Route('/{name}', array(), array(), array(), '{locale}.example.com'));

        $this->assertEquals('http://fr.example.com/app.php/Fabien', $this->getGenerator($routes, array('host' => 'fr.example.com'))->generate('test', array('name' =>'Fabien', 'locale' => 'fr'), true));
    }

    /**
     * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException
     */
    public function testUrlWithInvalidParameterInHost()
    {
        $routes = $this->getRoutes('test', new Route('/', array(), array('foo' => 'bar'), array(), '{foo}.example.com'));
        $this->getGenerator($routes)->generate('test', array('foo' => 'baz'), false);
    }

    /**
     * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException
     */
    public function testUrlWithInvalidParameterInHostWhenParamHasADefaultValue()
    {
        $routes = $this->getRoutes('test', new Route('/', array('foo' => 'bar'), array('foo' => 'bar'), array(), '{foo}.example.com'));
        $this->getGenerator($routes)->generate('test', array('foo' => 'baz'), false);
    }

    /**
     * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException
     */
    public function testUrlWithInvalidParameterEqualsDefaultValueInHost()
    {
        $routes = $this->getRoutes('test', new Route('/', array('foo' => 'baz'), array('foo' => 'bar'), array(), '{foo}.example.com'));
        $this->getGenerator($routes)->generate('test', array('foo' => 'baz'), false);
    }

    public function testUrlWithInvalidParameterInHostInNonStrictMode()
    {
        $routes = $this->getRoutes('test', new Route('/', array(), array('foo' => 'bar'), array(), '{foo}.example.com'));
        $generator = $this->getGenerator($routes);
        $generator->setStrictRequirements(false);
        $this->assertNull($generator->generate('test', array('foo' => 'baz'), false));
    }

    public function testGenerateNetworkPath()
    {
        $routes = $this->getRoutes('test', new Route('/{name}', array(), array('_scheme' => 'http'), array(), '{locale}.example.com'));

        $this->assertSame('//fr.example.com/app.php/Fabien', $this->getGenerator($routes)->generate('test',
            array('name' =>'Fabien', 'locale' => 'fr'), UrlGeneratorInterface::NETWORK_PATH), 'network path with different host'
        );
        $this->assertSame('//fr.example.com/app.php/Fabien?query=string', $this->getGenerator($routes, array('host' => 'fr.example.com'))->generate('test',
            array('name' =>'Fabien', 'locale' => 'fr', 'query' => 'string'), UrlGeneratorInterface::NETWORK_PATH), 'network path although host same as context'
        );
        $this->assertSame('http://fr.example.com/app.php/Fabien', $this->getGenerator($routes, array('scheme' => 'https'))->generate('test',
            array('name' =>'Fabien', 'locale' => 'fr'), UrlGeneratorInterface::NETWORK_PATH), 'absolute URL because scheme requirement does not match context'
        );
        $this->assertSame('http://fr.example.com/app.php/Fabien', $this->getGenerator($routes)->generate('test',
            array('name' =>'Fabien', 'locale' => 'fr'), UrlGeneratorInterface::ABSOLUTE_URL), 'absolute URL with same scheme because it is requested'
        );
    }

    public function testGenerateRelativePath()
    {
        $routes = new RouteCollection();
        $routes->add('article', new Route('/{author}/{article}/'));
        $routes->add('comments', new Route('/{author}/{article}/comments'));
        $routes->add('host', new Route('/{article}', array(), array(), array(), '{author}.example.com'));
        $routes->add('scheme', new Route('/{author}', array(), array('_scheme' => 'https')));
        $routes->add('unrelated', new Route('/about'));

        $generator = $this->getGenerator($routes, array('host' => 'example.com', 'pathInfo' => '/fabien/symfony-is-great/'));

        $this->assertSame('comments', $generator->generate('comments',
            array('author' =>'fabien', 'article' => 'symfony-is-great'), UrlGeneratorInterface::RELATIVE_PATH)
        );
        $this->assertSame('comments?page=2', $generator->generate('comments',
            array('author' =>'fabien', 'article' => 'symfony-is-great', 'page' => 2), UrlGeneratorInterface::RELATIVE_PATH)
        );
        $this->assertSame('../twig-is-great/', $generator->generate('article',
            array('author' =>'fabien', 'article' => 'twig-is-great'), UrlGeneratorInterface::RELATIVE_PATH)
        );
        $this->assertSame('../../bernhard/forms-are-great/', $generator->generate('article',
            array('author' =>'bernhard', 'article' => 'forms-are-great'), UrlGeneratorInterface::RELATIVE_PATH)
        );
        $this->assertSame('//bernhard.example.com/app.php/forms-are-great', $generator->generate('host',
            array('author' =>'bernhard', 'article' => 'forms-are-great'), UrlGeneratorInterface::RELATIVE_PATH)
        );
        $this->assertSame('https://example.com/app.php/bernhard', $generator->generate('scheme',
            array('author' =>'bernhard'), UrlGeneratorInterface::RELATIVE_PATH)
        );
        $this->assertSame('../../about', $generator->generate('unrelated',
            array(), UrlGeneratorInterface::RELATIVE_PATH)
        );
    }

    /**
     * @dataProvider provideRelativePaths
     */
    public function testGetRelativePath($sourcePath, $targetPath, $expectedPath)
    {
        $this->assertSame($expectedPath, UrlGenerator::getRelativePath($sourcePath, $targetPath));
    }

    public function provideRelativePaths()
    {
        return array(
            array(
                '/same/dir/',
                '/same/dir/',
                ''
            ),
            array(
                '/same/file',
                '/same/file',
                ''
            ),
            array(
                '/',
                '/file',
                'file'
            ),
            array(
                '/',
                '/dir/file',
                'dir/file'
            ),
            array(
                '/dir/file.html',
                '/dir/different-file.html',
                'different-file.html'
            ),
            array(
                '/same/dir/extra-file',
                '/same/dir/',
                './'
            ),
            array(
                '/parent/dir/',
                '/parent/',
                '../'
            ),
            array(
                '/parent/dir/extra-file',
                '/parent/',
                '../'
            ),
            array(
                '/a/b/',
                '/x/y/z/',
                '../../x/y/z/'
            ),
            array(
                '/a/b/c/d/e',
                '/a/c/d',
                '../../../c/d'
            ),
            array(
                '/a/b/c//',
                '/a/b/c/',
                '../'
            ),
            array(
                '/a/b/c/',
                '/a/b/c//',
                './/'
            ),
            array(
                '/root/a/b/c/',
                '/root/x/b/c/',
                '../../../x/b/c/'
            ),
            array(
                '/a/b/c/d/',
                '/a',
                '../../../../a'
            ),
            array(
                '/special-chars/sp%20ce/1€/mäh/e=mc²',
                '/special-chars/sp%20ce/1€/<µ>/e=mc²',
                '../<µ>/e=mc²'
            ),
            array(
                'not-rooted',
                'dir/file',
                'dir/file'
            ),
            array(
                '//dir/',
                '',
                '../../'
            ),
            array(
                '/dir/',
                '/dir/file:with-colon',
                './file:with-colon'
            ),
            array(
                '/dir/',
                '/dir/subdir/file:with-colon',
                'subdir/file:with-colon'
            ),
            array(
                '/dir/',
                '/dir/:subdir/',
                './:subdir/'
            ),
        );
    }

    protected function getGenerator(RouteCollection $routes, array $parameters = array(), $logger = null)
    {
        $context = new RequestContext('/app.php');
        foreach ($parameters as $key => $value) {
            $method = 'set'.$key;
            $context->$method($value);
        }
        $generator = new UrlGenerator($routes, $context, $logger);

        return $generator;
    }

    protected function getRoutes($name, Route $route)
    {
        $routes = new RouteCollection();
        $routes->add($name, $route);

        return $routes;
    }
}
PK��Z������Xtest/Routing/Symfony/Component/Routing/Tests/Generator/Dumper/PhpGeneratorDumperTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Tests\Generator\Dumper;

use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\Generator\Dumper\PhpGeneratorDumper;
use Symfony\Component\Routing\RequestContext;

class PhpGeneratorDumperTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var RouteCollection
     */
    private $routeCollection;

    /**
     * @var PhpGeneratorDumper
     */
    private $generatorDumper;

    /**
     * @var string
     */
    private $testTmpFilepath;

    protected function setUp()
    {
        parent::setUp();

        $this->routeCollection = new RouteCollection();
        $this->generatorDumper = new PhpGeneratorDumper($this->routeCollection);
        $this->testTmpFilepath = sys_get_temp_dir().DIRECTORY_SEPARATOR.'php_generator.php';
        @unlink($this->testTmpFilepath);
    }

    protected function tearDown()
    {
        parent::tearDown();

        @unlink($this->testTmpFilepath);

        $this->routeCollection = null;
        $this->generatorDumper = null;
        $this->testTmpFilepath = null;
    }

    public function testDumpWithRoutes()
    {
        $this->routeCollection->add('Test', new Route('/testing/{foo}'));
        $this->routeCollection->add('Test2', new Route('/testing2'));

        file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump());
        include ($this->testTmpFilepath);

        $projectUrlGenerator = new \ProjectUrlGenerator(new RequestContext('/app.php'));

        $absoluteUrlWithParameter    = $projectUrlGenerator->generate('Test', array('foo' => 'bar'), true);
        $absoluteUrlWithoutParameter = $projectUrlGenerator->generate('Test2', array(), true);
        $relativeUrlWithParameter    = $projectUrlGenerator->generate('Test', array('foo' => 'bar'), false);
        $relativeUrlWithoutParameter = $projectUrlGenerator->generate('Test2', array(), false);

        $this->assertEquals($absoluteUrlWithParameter, 'http://localhost/app.php/testing/bar');
        $this->assertEquals($absoluteUrlWithoutParameter, 'http://localhost/app.php/testing2');
        $this->assertEquals($relativeUrlWithParameter, '/app.php/testing/bar');
        $this->assertEquals($relativeUrlWithoutParameter, '/app.php/testing2');
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testDumpWithoutRoutes()
    {
        file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump(array('class' => 'WithoutRoutesUrlGenerator')));
        include ($this->testTmpFilepath);

        $projectUrlGenerator = new \WithoutRoutesUrlGenerator(new RequestContext('/app.php'));

        $projectUrlGenerator->generate('Test', array());
    }

    /**
     * @expectedException \Symfony\Component\Routing\Exception\RouteNotFoundException
     */
    public function testGenerateNonExistingRoute()
    {
        $this->routeCollection->add('Test', new Route('/test'));

        file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump(array('class' => 'NonExistingRoutesUrlGenerator')));
        include ($this->testTmpFilepath);

        $projectUrlGenerator = new \NonExistingRoutesUrlGenerator(new RequestContext());
        $url = $projectUrlGenerator->generate('NonExisting', array());
    }

    public function testDumpForRouteWithDefaults()
    {
        $this->routeCollection->add('Test', new Route('/testing/{foo}', array('foo' => 'bar')));

        file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump(array('class' => 'DefaultRoutesUrlGenerator')));
        include ($this->testTmpFilepath);

        $projectUrlGenerator = new \DefaultRoutesUrlGenerator(new RequestContext());
        $url = $projectUrlGenerator->generate('Test', array());

        $this->assertEquals($url, '/testing');
    }
}
PK��Z8!!&GGBtest/Routing/Symfony/Component/Routing/Tests/CompiledRouteTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Tests;

use Symfony\Component\Routing\CompiledRoute;

class CompiledRouteTest extends \PHPUnit_Framework_TestCase
{
    public function testAccessors()
    {
        $compiled = new CompiledRoute('prefix', 'regex', array('tokens'), array(), array(), array(), array(), array('variables'));
        $this->assertEquals('prefix', $compiled->getStaticPrefix(), '__construct() takes a static prefix as its second argument');
        $this->assertEquals('regex', $compiled->getRegex(), '__construct() takes a regexp as its third argument');
        $this->assertEquals(array('tokens'), $compiled->getTokens(), '__construct() takes an array of tokens as its fourth argument');
        $this->assertEquals(array('variables'), $compiled->getVariables(), '__construct() takes an array of variables as its ninth argument');
    }
}
PK��Z���k��Itest/Routing/Symfony/Component/Routing/Tests/Loader/ClosureLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Tests\Loader;

use Symfony\Component\Routing\Loader\ClosureLoader;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;

class ClosureLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testSupports()
    {
        $loader = new ClosureLoader();

        $closure = function () {};

        $this->assertTrue($loader->supports($closure), '->supports() returns true if the resource is loadable');
        $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable');

        $this->assertTrue($loader->supports($closure, 'closure'), '->supports() checks the resource type if specified');
        $this->assertFalse($loader->supports($closure, 'foo'), '->supports() checks the resource type if specified');
    }

    public function testLoad()
    {
        $loader = new ClosureLoader();

        $route = new Route('/');
        $routes = $loader->load(function () use ($route) {
            $routes = new RouteCollection();

            $routes->add('foo', $route);

            return $routes;
        });

        $this->assertEquals($route, $routes->get('foo'), '->load() loads a \Closure resource');
    }
}
PK��Z�����Qtest/Routing/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Tests\Loader;

use Symfony\Component\Routing\Annotation\Route;

class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest
{
    protected $loader;

    protected function setUp()
    {
        parent::setUp();

        $this->reader = $this->getReader();
        $this->loader = $this->getClassLoader($this->reader);
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testLoadMissingClass()
    {
        $this->loader->load('MissingClass');
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testLoadAbstractClass()
    {
        $this->loader->load('Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\AbstractClass');
    }

    /**
     * @dataProvider provideTestSupportsChecksResource
     */
    public function testSupportsChecksResource($resource, $expectedSupports)
    {
        $this->assertSame($expectedSupports, $this->loader->supports($resource), '->supports() returns true if the resource is loadable');
    }

    public function provideTestSupportsChecksResource()
    {
        return array(
            array('class', true),
            array('\fully\qualified\class\name', true),
            array('namespaced\class\without\leading\slash', true),
            array('ÿClassWithLegalSpecialCharacters', true),
            array('5', false),
            array('foo.foo', false),
            array(null, false),
        );
    }

    public function testSupportsChecksTypeIfSpecified()
    {
        $this->assertTrue($this->loader->supports('class', 'annotation'), '->supports() checks the resource type if specified');
        $this->assertFalse($this->loader->supports('class', 'foo'), '->supports() checks the resource type if specified');
    }

    public function getLoadTests()
    {
        return array(
            array(
                'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BarClass',
                array('name' => 'route1'),
                array('arg2' => 'defaultValue2', 'arg3' => 'defaultValue3')
            ),
            array(
                'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BarClass',
                array('name' => 'route1', 'defaults' => array('arg2' => 'foo')),
                array('arg2' => 'defaultValue2', 'arg3' => 'defaultValue3')
            ),
            array(
                'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BarClass',
                array('name' => 'route1', 'defaults' => array('arg2' => 'foobar')),
                array('arg2' => 'defaultValue2', 'arg3' =>'defaultValue3')
            ),
            array(
                'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BarClass',
                array('name' => 'route1', 'defaults' => array('arg2' => 'foo'), 'condition' => 'context.getMethod() == "GET"'),
                array('arg2' => 'defaultValue2', 'arg3' =>'defaultValue3')
            ),
        );
    }

    /**
     * @dataProvider getLoadTests
     */
    public function testLoad($className, $routeDatas = array(), $methodArgs = array())
    {
        $routeDatas = array_replace(array(
            'name'         => 'route',
            'path'         => '/',
            'requirements' => array(),
            'options'      => array(),
            'defaults'     => array(),
            'schemes'      => array(),
            'methods'      => array(),
            'condition'    => null,
        ), $routeDatas);

        $this->reader
            ->expects($this->once())
            ->method('getMethodAnnotations')
            ->will($this->returnValue(array($this->getAnnotatedRoute($routeDatas))))
        ;
        $routeCollection = $this->loader->load($className);
        $route = $routeCollection->get($routeDatas['name']);

        $this->assertSame($routeDatas['path'], $route->getPath(), '->load preserves path annotation');
        $this->assertSame($routeDatas['requirements'],$route->getRequirements(), '->load preserves requirements annotation');
        $this->assertCount(0, array_intersect($route->getOptions(), $routeDatas['options']), '->load preserves options annotation');
        $this->assertSame(array_replace($methodArgs, $routeDatas['defaults']), $route->getDefaults(), '->load preserves defaults annotation');
        $this->assertEquals($routeDatas['condition'], $route->getCondition(), '->load preserves condition annotation');
    }

    private function getAnnotatedRoute($datas)
    {
        return new Route($datas);
    }
}
PK��Zg�U��Itest/Routing/Symfony/Component/Routing/Tests/Loader/PhpFileLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Tests\Loader;

use Symfony\Component\Config\FileLocator;
use Symfony\Component\Routing\Loader\PhpFileLoader;

class PhpFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testSupports()
    {
        $loader = new PhpFileLoader($this->getMock('Symfony\Component\Config\FileLocator'));

        $this->assertTrue($loader->supports('foo.php'), '->supports() returns true if the resource is loadable');
        $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable');

        $this->assertTrue($loader->supports('foo.php', 'php'), '->supports() checks the resource type if specified');
        $this->assertFalse($loader->supports('foo.php', 'foo'), '->supports() checks the resource type if specified');
    }

    public function testLoadWithRoute()
    {
        $loader = new PhpFileLoader(new FileLocator(array(__DIR__.'/../Fixtures')));
        $routeCollection = $loader->load('validpattern.php');
        $routes = $routeCollection->all();

        $this->assertCount(2, $routes, 'Two routes are loaded');
        $this->assertContainsOnly('Symfony\Component\Routing\Route', $routes);

        foreach ($routes as $route) {
            $this->assertSame('/blog/{slug}', $route->getPath());
            $this->assertSame('MyBlogBundle:Blog:show', $route->getDefault('_controller'));
            $this->assertSame('{locale}.example.com', $route->getHost());
            $this->assertSame('RouteCompiler', $route->getOption('compiler_class'));
            $this->assertEquals(array('GET', 'POST', 'PUT', 'OPTIONS'), $route->getMethods());
            $this->assertEquals(array('https'), $route->getSchemes());
        }
    }
}
PK��Z{��t��Jtest/Routing/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Tests\Loader;

use Symfony\Component\Config\FileLocator;
use Symfony\Component\Routing\Loader\YamlFileLoader;
use Symfony\Component\Config\Resource\FileResource;

class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testSupports()
    {
        $loader = new YamlFileLoader($this->getMock('Symfony\Component\Config\FileLocator'));

        $this->assertTrue($loader->supports('foo.yml'), '->supports() returns true if the resource is loadable');
        $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable');

        $this->assertTrue($loader->supports('foo.yml', 'yaml'), '->supports() checks the resource type if specified');
        $this->assertFalse($loader->supports('foo.yml', 'foo'), '->supports() checks the resource type if specified');
    }

    public function testLoadDoesNothingIfEmpty()
    {
        $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures')));
        $collection = $loader->load('empty.yml');

        $this->assertEquals(array(), $collection->all());
        $this->assertEquals(array(new FileResource(realpath(__DIR__.'/../Fixtures/empty.yml'))), $collection->getResources());
    }

    /**
     * @expectedException \InvalidArgumentException
     * @dataProvider getPathsToInvalidFiles
     */
    public function testLoadThrowsExceptionWithInvalidFile($filePath)
    {
        $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures')));
        $loader->load($filePath);
    }

    public function getPathsToInvalidFiles()
    {
        return array(array('nonvalid.yml'), array('nonvalid2.yml'), array('incomplete.yml'), array('nonvalidkeys.yml'), array('nonesense_resource_plus_path.yml'), array('nonesense_type_without_resource.yml'));
    }

    public function testLoadSpecialRouteName()
    {
        $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures')));
        $routeCollection = $loader->load('special_route_name.yml');
        $route = $routeCollection->get('#$péß^a|');

        $this->assertInstanceOf('Symfony\Component\Routing\Route', $route);
        $this->assertSame('/true', $route->getPath());
    }

    public function testLoadWithRoute()
    {
        $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures')));
        $routeCollection = $loader->load('validpattern.yml');
        $routes = $routeCollection->all();

        $this->assertCount(3, $routes, 'Three routes are loaded');
        $this->assertContainsOnly('Symfony\Component\Routing\Route', $routes);

        $identicalRoutes = array_slice($routes, 0, 2);

        foreach ($identicalRoutes as $route) {
            $this->assertSame('/blog/{slug}', $route->getPath());
            $this->assertSame('{locale}.example.com', $route->getHost());
            $this->assertSame('MyBundle:Blog:show', $route->getDefault('_controller'));
            $this->assertSame('\w+', $route->getRequirement('locale'));
            $this->assertSame('RouteCompiler', $route->getOption('compiler_class'));
            $this->assertEquals(array('GET', 'POST', 'PUT', 'OPTIONS'), $route->getMethods());
            $this->assertEquals(array('https'), $route->getSchemes());
            $this->assertEquals('context.getMethod() == "GET"', $route->getCondition());
        }
    }

    public function testLoadWithResource()
    {
        $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures')));
        $routeCollection = $loader->load('validresource.yml');
        $routes = $routeCollection->all();

        $this->assertCount(3, $routes, 'Three routes are loaded');
        $this->assertContainsOnly('Symfony\Component\Routing\Route', $routes);

        foreach ($routes as $route) {
            $this->assertSame('/{foo}/blog/{slug}', $route->getPath());
            $this->assertSame('123', $route->getDefault('foo'));
            $this->assertSame('\d+', $route->getRequirement('foo'));
            $this->assertSame('bar', $route->getOption('foo'));
            $this->assertSame('', $route->getHost());
            $this->assertSame('context.getMethod() == "POST"', $route->getCondition());
        }
    }

}
PK��Z6����Utest/Routing/Symfony/Component/Routing/Tests/Loader/AnnotationDirectoryLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Tests\Loader;

use Symfony\Component\Routing\Loader\AnnotationDirectoryLoader;
use Symfony\Component\Config\FileLocator;

class AnnotationDirectoryLoaderTest extends AbstractAnnotationLoaderTest
{
    protected $loader;
    protected $reader;

    protected function setUp()
    {
        parent::setUp();

        $this->reader = $this->getReader();
        $this->loader = new AnnotationDirectoryLoader(new FileLocator(), $this->getClassLoader($this->reader));
    }

    public function testLoad()
    {
        $this->reader->expects($this->exactly(2))->method('getClassAnnotation');

        $this->reader
            ->expects($this->any())
            ->method('getMethodAnnotations')
            ->will($this->returnValue(array()))
        ;

        $this->loader->load(__DIR__.'/../Fixtures/AnnotatedClasses');
    }

    public function testSupports()
    {
        $fixturesDir = __DIR__.'/../Fixtures';

        $this->assertTrue($this->loader->supports($fixturesDir), '->supports() returns true if the resource is loadable');
        $this->assertFalse($this->loader->supports('foo.foo'), '->supports() returns true if the resource is loadable');

        $this->assertTrue($this->loader->supports($fixturesDir, 'annotation'), '->supports() checks the resource type if specified');
        $this->assertFalse($this->loader->supports($fixturesDir, 'foo'), '->supports() checks the resource type if specified');
    }
}
PK��ZM�~�##Itest/Routing/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Tests\Loader;

use Symfony\Component\Config\FileLocator;
use Symfony\Component\Routing\Loader\XmlFileLoader;
use Symfony\Component\Routing\Tests\Fixtures\CustomXmlFileLoader;

class XmlFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testSupports()
    {
        $loader = new XmlFileLoader($this->getMock('Symfony\Component\Config\FileLocator'));

        $this->assertTrue($loader->supports('foo.xml'), '->supports() returns true if the resource is loadable');
        $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable');

        $this->assertTrue($loader->supports('foo.xml', 'xml'), '->supports() checks the resource type if specified');
        $this->assertFalse($loader->supports('foo.xml', 'foo'), '->supports() checks the resource type if specified');
    }

    public function testLoadWithRoute()
    {
        $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures')));
        $routeCollection = $loader->load('validpattern.xml');
        $routes = $routeCollection->all();

        $this->assertCount(3, $routes, 'Three routes are loaded');
        $this->assertContainsOnly('Symfony\Component\Routing\Route', $routes);

        $identicalRoutes = array_slice($routes, 0, 2);

        foreach ($identicalRoutes as $route) {
            $this->assertSame('/blog/{slug}', $route->getPath());
            $this->assertSame('{locale}.example.com', $route->getHost());
            $this->assertSame('MyBundle:Blog:show', $route->getDefault('_controller'));
            $this->assertSame('\w+', $route->getRequirement('locale'));
            $this->assertSame('RouteCompiler', $route->getOption('compiler_class'));
            $this->assertEquals(array('GET', 'POST', 'PUT', 'OPTIONS'), $route->getMethods());
            $this->assertEquals(array('https'), $route->getSchemes());
            $this->assertEquals('context.getMethod() == "GET"', $route->getCondition());
        }
    }

    public function testLoadWithNamespacePrefix()
    {
        $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures')));
        $routeCollection = $loader->load('namespaceprefix.xml');

        $this->assertCount(1, $routeCollection->all(), 'One route is loaded');

        $route = $routeCollection->get('blog_show');
        $this->assertSame('/blog/{slug}', $route->getPath());
        $this->assertSame('{_locale}.example.com', $route->getHost());
        $this->assertSame('MyBundle:Blog:show', $route->getDefault('_controller'));
        $this->assertSame('\w+', $route->getRequirement('slug'));
        $this->assertSame('en|fr|de', $route->getRequirement('_locale'));
        $this->assertSame(null, $route->getDefault('slug'));
        $this->assertSame('RouteCompiler', $route->getOption('compiler_class'));
    }

    public function testLoadWithImport()
    {
        $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures')));
        $routeCollection = $loader->load('validresource.xml');
        $routes = $routeCollection->all();

        $this->assertCount(3, $routes, 'Three routes are loaded');
        $this->assertContainsOnly('Symfony\Component\Routing\Route', $routes);

        foreach ($routes as $route) {
            $this->assertSame('/{foo}/blog/{slug}', $route->getPath());
            $this->assertSame('123', $route->getDefault('foo'));
            $this->assertSame('\d+', $route->getRequirement('foo'));
            $this->assertSame('bar', $route->getOption('foo'));
            $this->assertSame('', $route->getHost());
            $this->assertSame('context.getMethod() == "POST"', $route->getCondition());
        }
    }

    /**
     * @expectedException \InvalidArgumentException
     * @dataProvider getPathsToInvalidFiles
     */
    public function testLoadThrowsExceptionWithInvalidFile($filePath)
    {
        $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures')));
        $loader->load($filePath);
    }

    /**
     * @expectedException \InvalidArgumentException
     * @dataProvider getPathsToInvalidFiles
     */
    public function testLoadThrowsExceptionWithInvalidFileEvenWithoutSchemaValidation($filePath)
    {
        $loader = new CustomXmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures')));
        $loader->load($filePath);
    }

    public function getPathsToInvalidFiles()
    {
        return array(array('nonvalidnode.xml'), array('nonvalidroute.xml'), array('nonvalid.xml'), array('missing_id.xml'), array('missing_path.xml'));
    }

    /**
     * @expectedException \InvalidArgumentException
     * @expectedExceptionMessage Document types are not allowed.
     */
    public function testDocTypeIsNotAllowed()
    {
        $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures')));
        $loader->load('withdoctype.xml');
    }
}
PK��Z|�C44Ttest/Routing/Symfony/Component/Routing/Tests/Loader/AbstractAnnotationLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Tests\Loader;

abstract class AbstractAnnotationLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function getReader()
    {
        return $this->getMockBuilder('Doctrine\Common\Annotations\Reader')
            ->disableOriginalConstructor()
            ->getMock()
        ;
    }

    public function getClassLoader($reader)
    {
        return $this->getMockBuilder('Symfony\Component\Routing\Loader\AnnotationClassLoader')
            ->setConstructorArgs(array($reader))
            ->getMockForAbstractClass()
        ;
    }
}
PK��Zu��;Ptest/Routing/Symfony/Component/Routing/Tests/Loader/AnnotationFileLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Tests\Loader;

use Symfony\Component\Routing\Loader\AnnotationFileLoader;
use Symfony\Component\Config\FileLocator;

class AnnotationFileLoaderTest extends AbstractAnnotationLoaderTest
{
    protected $loader;
    protected $reader;

    protected function setUp()
    {
        parent::setUp();

        $this->reader = $this->getReader();
        $this->loader = new AnnotationFileLoader(new FileLocator(), $this->getClassLoader($this->reader));
    }

    public function testLoad()
    {
        $this->reader->expects($this->once())->method('getClassAnnotation');

        $this->loader->load(__DIR__.'/../Fixtures/AnnotatedClasses/FooClass.php');
    }

    public function testSupports()
    {
        $fixture = __DIR__.'/../Fixtures/annotated.php';

        $this->assertTrue($this->loader->supports($fixture), '->supports() returns true if the resource is loadable');
        $this->assertFalse($this->loader->supports('foo.foo'), '->supports() returns true if the resource is loadable');

        $this->assertTrue($this->loader->supports($fixture, 'annotation'), '->supports() checks the resource type if specified');
        $this->assertFalse($this->loader->supports($fixture, 'foo'), '->supports() checks the resource type if specified');
    }
}
PK��Z��;test/Routing/Symfony/Component/Routing/Tests/RouterTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Tests;

use Symfony\Component\Routing\Router;
use Symfony\Component\HttpFoundation\Request;

class RouterTest extends \PHPUnit_Framework_TestCase
{
    private $router = null;

    private $loader = null;

    protected function setUp()
    {
        $this->loader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface');
        $this->router = new Router($this->loader, 'routing.yml');
    }

    public function testSetOptionsWithSupportedOptions()
    {
        $this->router->setOptions(array(
            'cache_dir' => './cache',
            'debug' => true,
            'resource_type' => 'ResourceType'
        ));

        $this->assertSame('./cache', $this->router->getOption('cache_dir'));
        $this->assertTrue($this->router->getOption('debug'));
        $this->assertSame('ResourceType', $this->router->getOption('resource_type'));
    }

    /**
     * @expectedException \InvalidArgumentException
     * @expectedExceptionMessage The Router does not support the following options: "option_foo", "option_bar"
     */
    public function testSetOptionsWithUnsupportedOptions()
    {
        $this->router->setOptions(array(
            'cache_dir' => './cache',
            'option_foo' => true,
            'option_bar' => 'baz',
            'resource_type' => 'ResourceType'
        ));
    }

    public function testSetOptionWithSupportedOption()
    {
        $this->router->setOption('cache_dir', './cache');

        $this->assertSame('./cache', $this->router->getOption('cache_dir'));
    }

    /**
     * @expectedException \InvalidArgumentException
     * @expectedExceptionMessage The Router does not support the "option_foo" option
     */
    public function testSetOptionWithUnsupportedOption()
    {
        $this->router->setOption('option_foo', true);
    }

    /**
     * @expectedException \InvalidArgumentException
     * @expectedExceptionMessage The Router does not support the "option_foo" option
     */
    public function testGetOptionWithUnsupportedOption()
    {
        $this->router->getOption('option_foo', true);
    }

    public function testThatRouteCollectionIsLoaded()
    {
        $this->router->setOption('resource_type', 'ResourceType');

        $routeCollection = $this->getMock('Symfony\Component\Routing\RouteCollection');

        $this->loader->expects($this->once())
            ->method('load')->with('routing.yml', 'ResourceType')
            ->will($this->returnValue($routeCollection));

        $this->assertSame($routeCollection, $this->router->getRouteCollection());
    }

    /**
     * @dataProvider provideMatcherOptionsPreventingCaching
     */
    public function testMatcherIsCreatedIfCacheIsNotConfigured($option)
    {
        $this->router->setOption($option, null);

        $this->loader->expects($this->once())
            ->method('load')->with('routing.yml', null)
            ->will($this->returnValue($this->getMock('Symfony\Component\Routing\RouteCollection')));

        $this->assertInstanceOf('Symfony\\Component\\Routing\\Matcher\\UrlMatcher', $this->router->getMatcher());

    }

    public function provideMatcherOptionsPreventingCaching()
    {
        return array(
            array('cache_dir'),
            array('matcher_cache_class')
        );
    }

    /**
     * @dataProvider provideGeneratorOptionsPreventingCaching
     */
    public function testGeneratorIsCreatedIfCacheIsNotConfigured($option)
    {
        $this->router->setOption($option, null);

        $this->loader->expects($this->once())
            ->method('load')->with('routing.yml', null)
            ->will($this->returnValue($this->getMock('Symfony\Component\Routing\RouteCollection')));

        $this->assertInstanceOf('Symfony\\Component\\Routing\\Generator\\UrlGenerator', $this->router->getGenerator());

    }

    public function provideGeneratorOptionsPreventingCaching()
    {
        return array(
            array('cache_dir'),
            array('generator_cache_class')
        );
    }

    public function testMatchRequestWithUrlMatcherInterface()
    {
        $matcher = $this->getMock('Symfony\Component\Routing\Matcher\UrlMatcherInterface');
        $matcher->expects($this->once())->method('match');

        $p = new \ReflectionProperty($this->router, 'matcher');
        $p->setAccessible(true);
        $p->setValue($this->router, $matcher);

        $this->router->matchRequest(Request::create('/'));
    }

    public function testMatchRequestWithRequestMatcherInterface()
    {
        $matcher = $this->getMock('Symfony\Component\Routing\Matcher\RequestMatcherInterface');
        $matcher->expects($this->once())->method('matchRequest');

        $p = new \ReflectionProperty($this->router, 'matcher');
        $p->setAccessible(true);
        $p->setValue($this->router, $matcher);

        $this->router->matchRequest(Request::create('/'));
    }
}
PK��Zu��A�,�,:test/Routing/Symfony/Component/Routing/Tests/RouteTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Routing\Tests;

use Symfony\Component\Routing\Route;

class RouteTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $route = new Route('/{foo}', array('foo' => 'bar'), array('foo' => '\d+'), array('foo' => 'bar'), '{locale}.example.com');
        $this->assertEquals('/{foo}', $route->getPath(), '__construct() takes a path as its first argument');
        $this->assertEquals(array('foo' => 'bar'), $route->getDefaults(), '__construct() takes defaults as its second argument');
        $this->assertEquals(array('foo' => '\d+'), $route->getRequirements(), '__construct() takes requirements as its third argument');
        $this->assertEquals('bar', $route->getOption('foo'), '__construct() takes options as its fourth argument');
        $this->assertEquals('{locale}.example.com', $route->getHost(), '__construct() takes a host pattern as its fifth argument');

        $route = new Route('/', array(), array(), array(), '', array('Https'), array('POST', 'put'), 'context.getMethod() == "GET"');
        $this->assertEquals(array('https'), $route->getSchemes(), '__construct() takes schemes as its sixth argument and lowercases it');
        $this->assertEquals(array('POST', 'PUT'), $route->getMethods(), '__construct() takes methods as its seventh argument and uppercases it');
        $this->assertEquals('context.getMethod() == "GET"', $route->getCondition(), '__construct() takes a condition as its eight argument');

        $route = new Route('/', array(), array(), array(), '', 'Https', 'Post');
        $this->assertEquals(array('https'), $route->getSchemes(), '__construct() takes a single scheme as its sixth argument');
        $this->assertEquals(array('POST'), $route->getMethods(), '__construct() takes a single method as its seventh argument');
    }

    public function testPath()
    {
        $route = new Route('/{foo}');
        $route->setPath('/{bar}');
        $this->assertEquals('/{bar}', $route->getPath(), '->setPath() sets the path');
        $route->setPath('');
        $this->assertEquals('/', $route->getPath(), '->setPath() adds a / at the beginning of the path if needed');
        $route->setPath('bar');
        $this->assertEquals('/bar', $route->getPath(), '->setPath() adds a / at the beginning of the path if needed');
        $this->assertEquals($route, $route->setPath(''), '->setPath() implements a fluent interface');
        $route->setPath('//path');
        $this->assertEquals('/path', $route->getPath(), '->setPath() does not allow two slashes "//" at the beginning of the path as it would be confused with a network path when generating the path from the route');
    }

    public function testOptions()
    {
        $route = new Route('/{foo}');
        $route->setOptions(array('foo' => 'bar'));
        $this->assertEquals(array_merge(array(
        'compiler_class'     => 'Symfony\\Component\\Routing\\RouteCompiler',
        ), array('foo' => 'bar')), $route->getOptions(), '->setOptions() sets the options');
        $this->assertEquals($route, $route->setOptions(array()), '->setOptions() implements a fluent interface');

        $route->setOptions(array('foo' => 'foo'));
        $route->addOptions(array('bar' => 'bar'));
        $this->assertEquals($route, $route->addOptions(array()), '->addOptions() implements a fluent interface');
        $this->assertEquals(array('foo' => 'foo', 'bar' => 'bar', 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler'), $route->getOptions(), '->addDefaults() keep previous defaults');
    }

    public function testOption()
    {
        $route = new Route('/{foo}');
        $this->assertFalse($route->hasOption('foo'), '->hasOption() return false if option is not set');
        $this->assertEquals($route, $route->setOption('foo', 'bar'), '->setOption() implements a fluent interface');
        $this->assertEquals('bar', $route->getOption('foo'), '->setOption() sets the option');
        $this->assertTrue($route->hasOption('foo'), '->hasOption() return true if option is set');
    }

    public function testDefaults()
    {
        $route = new Route('/{foo}');
        $route->setDefaults(array('foo' => 'bar'));
        $this->assertEquals(array('foo' => 'bar'), $route->getDefaults(), '->setDefaults() sets the defaults');
        $this->assertEquals($route, $route->setDefaults(array()), '->setDefaults() implements a fluent interface');

        $route->setDefault('foo', 'bar');
        $this->assertEquals('bar', $route->getDefault('foo'), '->setDefault() sets a default value');

        $route->setDefault('foo2', 'bar2');
        $this->assertEquals('bar2', $route->getDefault('foo2'), '->getDefault() return the default value');
        $this->assertNull($route->getDefault('not_defined'), '->getDefault() return null if default value is not set');

        $route->setDefault('_controller', $closure = function () { return 'Hello'; });
        $this->assertEquals($closure, $route->getDefault('_controller'), '->setDefault() sets a default value');

        $route->setDefaults(array('foo' => 'foo'));
        $route->addDefaults(array('bar' => 'bar'));
        $this->assertEquals($route, $route->addDefaults(array()), '->addDefaults() implements a fluent interface');
        $this->assertEquals(array('foo' => 'foo', 'bar' => 'bar'), $route->getDefaults(), '->addDefaults() keep previous defaults');
    }

    public function testRequirements()
    {
        $route = new Route('/{foo}');
        $route->setRequirements(array('foo' => '\d+'));
        $this->assertEquals(array('foo' => '\d+'), $route->getRequirements(), '->setRequirements() sets the requirements');
        $this->assertEquals('\d+', $route->getRequirement('foo'), '->getRequirement() returns a requirement');
        $this->assertNull($route->getRequirement('bar'), '->getRequirement() returns null if a requirement is not defined');
        $route->setRequirements(array('foo' => '^\d+$'));
        $this->assertEquals('\d+', $route->getRequirement('foo'), '->getRequirement() removes ^ and $ from the path');
        $this->assertEquals($route, $route->setRequirements(array()), '->setRequirements() implements a fluent interface');

        $route->setRequirements(array('foo' => '\d+'));
        $route->addRequirements(array('bar' => '\d+'));
        $this->assertEquals($route, $route->addRequirements(array()), '->addRequirements() implements a fluent interface');
        $this->assertEquals(array('foo' => '\d+', 'bar' => '\d+'), $route->getRequirements(), '->addRequirement() keep previous requirements');
    }

    public function testRequirement()
    {
        $route = new Route('/{foo}');
        $this->assertFalse($route->hasRequirement('foo'), '->hasRequirement() return false if requirement is not set');
        $route->setRequirement('foo', '^\d+$');
        $this->assertEquals('\d+', $route->getRequirement('foo'), '->setRequirement() removes ^ and $ from the path');
        $this->assertTrue($route->hasRequirement('foo'), '->hasRequirement() return true if requirement is set');
    }

    /**
     * @dataProvider getInvalidRequirements
     * @expectedException \InvalidArgumentException
     */
    public function testSetInvalidRequirement($req)
    {
        $route = new Route('/{foo}');
        $route->setRequirement('foo', $req);
    }

    public function getInvalidRequirements()
    {
        return array(
           array(''),
           array(array()),
           array('^$'),
           array('^'),
           array('$')
        );
    }

    public function testHost()
    {
        $route = new Route('/');
        $route->setHost('{locale}.example.net');
        $this->assertEquals('{locale}.example.net', $route->getHost(), '->setHost() sets the host pattern');
    }

    public function testScheme()
    {
        $route = new Route('/');
        $this->assertEquals(array(), $route->getSchemes(), 'schemes is initialized with array()');
        $route->setSchemes('hTTp');
        $this->assertEquals(array('http'), $route->getSchemes(), '->setSchemes() accepts a single scheme string and lowercases it');
        $route->setSchemes(array('HttpS', 'hTTp'));
        $this->assertEquals(array('https', 'http'), $route->getSchemes(), '->setSchemes() accepts an array of schemes and lowercases them');
    }

    public function testSchemeIsBC()
    {
        $route = new Route('/');
        $route->setRequirement('_scheme', 'http|https');
        $this->assertEquals('http|https', $route->getRequirement('_scheme'));
        $this->assertEquals(array('http', 'https'), $route->getSchemes());
        $route->setSchemes(array('hTTp'));
        $this->assertEquals('http', $route->getRequirement('_scheme'));
        $route->setSchemes(array());
        $this->assertNull($route->getRequirement('_scheme'));
    }

    public function testMethod()
    {
        $route = new Route('/');
        $this->assertEquals(array(), $route->getMethods(), 'methods is initialized with array()');
        $route->setMethods('gEt');
        $this->assertEquals(array('GET'), $route->getMethods(), '->setMethods() accepts a single method string and uppercases it');
        $route->setMethods(array('gEt', 'PosT'));
        $this->assertEquals(array('GET', 'POST'), $route->getMethods(), '->setMethods() accepts an array of methods and uppercases them');
    }

    public function testMethodIsBC()
    {
        $route = new Route('/');
        $route->setRequirement('_method', 'GET|POST');
        $this->assertEquals('GET|POST', $route->getRequirement('_method'));
        $this->assertEquals(array('GET', 'POST'), $route->getMethods());
        $route->setMethods(array('gEt'));
        $this->assertEquals('GET', $route->getRequirement('_method'));
        $route->setMethods(array());
        $this->assertNull($route->getRequirement('_method'));
    }

    public function testCondition()
    {
        $route = new Route('/');
        $this->assertEquals(null, $route->getCondition());
        $route->setCondition('context.getMethod() == "GET"');
        $this->assertEquals('context.getMethod() == "GET"', $route->getCondition());
    }

    public function testCompile()
    {
        $route = new Route('/{foo}');
        $this->assertInstanceOf('Symfony\Component\Routing\CompiledRoute', $compiled = $route->compile(), '->compile() returns a compiled route');
        $this->assertSame($compiled, $route->compile(), '->compile() only compiled the route once if unchanged');
        $route->setRequirement('foo', '.*');
        $this->assertNotSame($compiled, $route->compile(), '->compile() recompiles if the route was modified');
    }

    public function testPattern()
    {
        $route = new Route('/{foo}');
        $this->assertEquals('/{foo}', $route->getPattern());

        $route->setPattern('/bar');
        $this->assertEquals('/bar', $route->getPattern());
    }

    public function testSerialize()
    {
        $route = new Route('/{foo}', array('foo' => 'default'), array('foo' => '\d+'));

        $serialized = serialize($route);
        $unserialized = unserialize($serialized);

        $this->assertEquals($route, $unserialized);
        $this->assertNotSame($route, $unserialized);
    }
}
PK��Z~�667test/Routing/Symfony/Component/Routing/phpunit.xml.distnu�[���<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony Routing Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./vendor</directory>
                <directory>./Tests</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
PK��Z��W8j#j#.test/Structures_Graph/tests/BasicGraphTest.phpnu�[���<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
// +-----------------------------------------------------------------------------+
// | Copyright (c) 2003 S�rgio Gon�alves Carvalho                                |
// +-----------------------------------------------------------------------------+
// | This file is part of Structures_Graph.                                      |
// |                                                                             |
// | Structures_Graph is free software; you can redistribute it and/or modify    |
// | it under the terms of the GNU Lesser General Public License as published by |
// | the Free Software Foundation; either version 2.1 of the License, or         |
// | (at your option) any later version.                                         |
// |                                                                             |
// | Structures_Graph is distributed in the hope that it will be useful,         |
// | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
// | GNU Lesser General Public License for more details.                         |
// |                                                                             |
// | You should have received a copy of the GNU Lesser General Public License    |
// | along with Structures_Graph; if not, write to the Free Software             |
// | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA                    |
// | 02111-1307 USA                                                              |
// +-----------------------------------------------------------------------------+
// | Author: S�rgio Carvalho <sergio.carvalho@portugalmail.com>                  |
// +-----------------------------------------------------------------------------+
//

require_once dirname(__FILE__) . '/helper.inc';

/**
 * @access private
 */
class BasicGraph extends PHPUnit_Framework_TestCase
{
    var $_graph = null;

    function test_create_graph() {
        $this->_graph = new Structures_Graph();
        $this->assertTrue(is_a($this->_graph, 'Structures_Graph')); 
    }

    function test_add_node() {
        $this->_graph = new Structures_Graph();
        $data = 1;
        $node = new Structures_Graph_Node($data);
        $this->_graph->addNode($node);
        $node = new Structures_Graph_Node($data);
        $this->_graph->addNode($node);
        $node = new Structures_Graph_Node($data);
        $this->_graph->addNode($node);
    }

    function test_connect_node() {
        $this->_graph = new Structures_Graph();
        $data = 1;
        $node1 = new Structures_Graph_Node($data);
        $node2 = new Structures_Graph_Node($data);
        $this->_graph->addNode($node1);
        $this->_graph->addNode($node2);
        $node1->connectTo($node2);

        $node =& $this->_graph->getNodes();
        $node =& $node[0];
        $node = $node->getNeighbours();
        $node =& $node[0];
        /* 
         ZE1 == and === operators fail on $node,$node2 because of the recursion introduced
         by the _graph field in the Node object. So, we'll use the stupid method for reference
         testing
        */
        $node = true;
        $this->assertTrue($node2);
        $node = false;
        $this->assertFalse($node2);
    }

    function test_data_references() {
        $this->_graph = new Structures_Graph();
        $data = 1;
        $node = new Structures_Graph_Node();
        $node->setData($data);
        $this->_graph->addNode($node);
        $data = 2;
        $dataInNode =& $this->_graph->getNodes();
        $dataInNode =& $dataInNode[0];
        $dataInNode =& $dataInNode->getData();
        $this->assertEquals($data, $dataInNode);
    }

    function test_metadata_references() {
        $this->_graph = new Structures_Graph();
        $data = 1;
        $node = new Structures_Graph_Node();
        $node->setMetadata('5', $data);
        $data = 2;
        $dataInNode =& $node->getMetadata('5');
        $this->assertEquals($data, $dataInNode);
    }
   
    function test_metadata_key_exists() {
        $this->_graph = new Structures_Graph();
        $data = 1;
        $node = new Structures_Graph_Node();
        $node->setMetadata('5', $data);
        $this->assertTrue($node->metadataKeyExists('5'));
        $this->assertFalse($node->metadataKeyExists('1'));
    }

    function test_directed_degree() {
        $this->_graph = new Structures_Graph(true);
        $node = array();
        $node[] = new Structures_Graph_Node();
        $node[] = new Structures_Graph_Node();
        $node[] = new Structures_Graph_Node();
        $this->_graph->addNode($node[0]);
        $this->_graph->addNode($node[1]);
        $this->_graph->addNode($node[2]);
        $this->assertEquals(0, $node[0]->inDegree(), 'inDegree test failed for node 0 with 0 arcs');
        $this->assertEquals(0, $node[1]->inDegree(), 'inDegree test failed for node 1 with 0 arcs');
        $this->assertEquals(0, $node[2]->inDegree(), 'inDegree test failed for node 2 with 0 arcs');
        $this->assertEquals(0, $node[0]->outDegree(), 'outDegree test failed for node 0 with 0 arcs');
        $this->assertEquals(0, $node[1]->outDegree(), 'outDegree test failed for node 1 with 0 arcs');
        $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 0 arcs');
        $node[0]->connectTo($node[1]);
        $this->assertEquals(0, $node[0]->inDegree(), 'inDegree test failed for node 0 with 1 arc');
        $this->assertEquals(1, $node[1]->inDegree(), 'inDegree test failed for node 1 with 1 arc');
        $this->assertEquals(0, $node[2]->inDegree(), 'inDegree test failed for node 2 with 1 arc');
        $this->assertEquals(1, $node[0]->outDegree(), 'outDegree test failed for node 0 with 1 arc');
        $this->assertEquals(0, $node[1]->outDegree(), 'outDegree test failed for node 1 with 1 arc');
        $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 1 arc');
        $node[0]->connectTo($node[2]);
        $this->assertEquals(0, $node[0]->inDegree(), 'inDegree test failed for node 0 with 2 arcs');
        $this->assertEquals(1, $node[1]->inDegree(), 'inDegree test failed for node 1 with 2 arcs');
        $this->assertEquals(1, $node[2]->inDegree(), 'inDegree test failed for node 2 with 2 arcs');
        $this->assertEquals(2, $node[0]->outDegree(), 'outDegree test failed for node 0 with 2 arcs');
        $this->assertEquals(0, $node[1]->outDegree(), 'outDegree test failed for node 1 with 2 arcs');
        $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 2 arcs');
    }

    function test_undirected_degree() {
        $this->_graph = new Structures_Graph(false);
        $node = array();
        $node[] = new Structures_Graph_Node();
        $node[] = new Structures_Graph_Node();
        $node[] = new Structures_Graph_Node();
        $this->_graph->addNode($node[0]);
        $this->_graph->addNode($node[1]);
        $this->_graph->addNode($node[2]);
        $this->assertEquals(0, $node[0]->inDegree(), 'inDegree test failed for node 0 with 0 arcs');
        $this->assertEquals(0, $node[1]->inDegree(), 'inDegree test failed for node 1 with 0 arcs');
        $this->assertEquals(0, $node[2]->inDegree(), 'inDegree test failed for node 2 with 0 arcs');
        $this->assertEquals(0, $node[0]->outDegree(), 'outDegree test failed for node 0 with 0 arcs');
        $this->assertEquals(0, $node[1]->outDegree(), 'outDegree test failed for node 1 with 0 arcs');
        $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 0 arcs');
        $node[0]->connectTo($node[1]);
        $this->assertEquals(1, $node[0]->inDegree(), 'inDegree test failed for node 0 with 1 arc');
        $this->assertEquals(1, $node[1]->inDegree(), 'inDegree test failed for node 1 with 1 arc');
        $this->assertEquals(0, $node[2]->inDegree(), 'inDegree test failed for node 2 with 1 arc');
        $this->assertEquals(1, $node[0]->outDegree(), 'outDegree test failed for node 0 with 1 arc');
        $this->assertEquals(1, $node[1]->outDegree(), 'outDegree test failed for node 1 with 1 arc');
        $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 1 arc');
        $node[0]->connectTo($node[2]);
        $this->assertEquals(2, $node[0]->inDegree(), 'inDegree test failed for node 0 with 2 arcs');
        $this->assertEquals(1, $node[1]->inDegree(), 'inDegree test failed for node 1 with 2 arcs');
        $this->assertEquals(1, $node[2]->inDegree(), 'inDegree test failed for node 2 with 2 arcs');
        $this->assertEquals(2, $node[0]->outDegree(), 'outDegree test failed for node 0 with 2 arcs');
        $this->assertEquals(1, $node[1]->outDegree(), 'outDegree test failed for node 1 with 2 arcs');
        $this->assertEquals(1, $node[2]->outDegree(), 'outDegree test failed for node 2 with 2 arcs');
    }
}
?>
PK��Z6��:UU5test/Structures_Graph/tests/TopologicalSorterTest.phpnu�[���<?php
require_once dirname(__FILE__) . '/helper.inc';
require_once 'Structures/Graph/Manipulator/TopologicalSorter.php';

class TopologicalSorterTest extends PHPUnit_Framework_TestCase
{
    public function testSort()
    {
        $graph = new Structures_Graph();

        $name1 = 'node1';
        $node1 = new Structures_Graph_Node();
        $node1->setData($name1);
        $graph->addNode($node1);

        $name11 = 'node11';
        $node11 = new Structures_Graph_Node();
        $node11->setData($name11);
        $graph->addNode($node11);
        $node1->connectTo($node11);

        $name12 = 'node12';
        $node12 = new Structures_Graph_Node();
        $node12->setData($name12);
        $graph->addNode($node12);
        $node1->connectTo($node12);

        $name121 = 'node121';
        $node121 = new Structures_Graph_Node();
        $node121->setData($name121);
        $graph->addNode($node121);
        $node12->connectTo($node121);

        $name2 = 'node2';
        $node2 = new Structures_Graph_Node();
        $node2->setData($name2);
        $graph->addNode($node2);

        $name21 = 'node21';
        $node21 = new Structures_Graph_Node();
        $node21->setData($name21);
        $graph->addNode($node21);
        $node2->connectTo($node21);

        $nodes = Structures_Graph_Manipulator_TopologicalSorter::sort($graph);
        $this->assertCount(2, $nodes[0]);
        $this->assertEquals('node1', $nodes[0][0]->getData());
        $this->assertEquals('node2', $nodes[0][1]->getData());

        $this->assertCount(3, $nodes[1]);
        $this->assertEquals('node11', $nodes[1][0]->getData());
        $this->assertEquals('node12', $nodes[1][1]->getData());
        $this->assertEquals('node21', $nodes[1][2]->getData());

        $this->assertCount(1, $nodes[2]);
        $this->assertEquals('node121', $nodes[2][0]->getData());
    }
}
?>
PK��Z�V���(test/Structures_Graph/tests/AllTests.phpnu�[���<?php
require_once dirname(__FILE__) . '/helper.inc';

class Structures_Graph_AllTests
{
    public static function main()
    {
        PHPUnit_TextUI_TestRunner::run(self::suite());
    }

    public static function suite()
    {
        $suite = new PHPUnit_Framework_TestSuite('Structures_Graph Tests');

        $dir = new GlobIterator(dirname(__FILE__) . '/*Test.php');
        $suite->addTestFiles($dir);

        return $suite;
    }
}
PK��Z���/test/Structures_Graph/tests/AcyclicTestTest.phpnu�[���<?php
require_once dirname(__FILE__) . '/helper.inc';
require_once 'Structures/Graph/Manipulator/AcyclicTest.php';

class AcyclicTestTest extends PHPUnit_Framework_TestCase
{
    public function testIsAcyclicFalse()
    {
        $graph = new Structures_Graph();
        $node1 = new Structures_Graph_Node();
        $graph->addNode($node1);

        $node2 = new Structures_Graph_Node();
        $graph->addNode($node2);
        $node1->connectTo($node2);

        $node3 = new Structures_Graph_Node();
        $graph->addNode($node3);
        $node2->connectTo($node3);

        $node3->connectTo($node1);

        $this->assertFalse(
            Structures_Graph_Manipulator_AcyclicTest::isAcyclic($graph),
            'Graph is cyclic'
        );
    }

    public function testIsAcyclicTrue()
    {
        $graph = new Structures_Graph();
        $node1 = new Structures_Graph_Node();
        $graph->addNode($node1);

        $node2 = new Structures_Graph_Node();
        $graph->addNode($node2);
        $node1->connectTo($node2);

        $node3 = new Structures_Graph_Node();
        $graph->addNode($node3);
        $node2->connectTo($node3);

        $this->assertTrue(
            Structures_Graph_Manipulator_AcyclicTest::isAcyclic($graph),
            'Graph is acyclic'
        );
    }
}
?>
PK��Z���ii&test/Structures_Graph/tests/helper.incnu�[���<?php
if ('/opt/alt/php74/usr/share/pear' == '@'.'php_dir'.'@') {
    // This package hasn't been installed.
    // Adjust path to ensure includes find files in working directory.
    set_include_path(dirname(dirname(__FILE__))
        . PATH_SEPARATOR . dirname(__FILE__)
        . PATH_SEPARATOR . get_include_path());
}

require_once 'Structures/Graph.php';
PK��Z��+\MMHtest/Process/Symfony/Component/Process/Tests/PhpExecutableFinderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Tests;

use Symfony\Component\Process\PhpExecutableFinder;

/**
 * @author Robert Schönthal <seroscho@googlemail.com>
 */
class PhpExecutableFinderTest extends \PHPUnit_Framework_TestCase
{
    /**
     * tests find() with the env var PHP_PATH
     */
    public function testFindWithPhpPath()
    {
        if (defined('PHP_BINARY')) {
            $this->markTestSkipped('The PHP binary is easily available as of PHP 5.4');
        }

        $f = new PhpExecutableFinder();

        $current = $f->find();

        //not executable PHP_PATH
        putenv('PHP_PATH=/not/executable/php');
        $this->assertFalse($f->find(), '::find() returns false for not executable PHP');

        //executable PHP_PATH
        putenv('PHP_PATH='.$current);
        $this->assertEquals($f->find(), $current, '::find() returns the executable PHP');
    }

    /**
     * tests find() with default executable
     */
    public function testFindWithSuffix()
    {
        if (defined('PHP_BINARY')) {
            $this->markTestSkipped('The PHP binary is easily available as of PHP 5.4');
        }

        putenv('PHP_PATH=');
        putenv('PHP_PEAR_PHP_BIN=');
        $f = new PhpExecutableFinder();

        $current = $f->find();

        //TODO maybe php executable is custom or even Windows
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->assertTrue(is_executable($current));
            $this->assertTrue((bool) preg_match('/'.addSlashes(DIRECTORY_SEPARATOR).'php\.(exe|bat|cmd|com)$/i', $current), '::find() returns the executable PHP with suffixes');
        }
    }
}
PK��Z#�Ttest/Process/Symfony/Component/Process/Tests/PipeStdinInStdoutStdErrStreamSelect.phpnu�[���<?php

define('ERR_SELECT_FAILED', 1);
define('ERR_TIMEOUT', 2);
define('ERR_READ_FAILED', 3);
define('ERR_WRITE_FAILED', 4);

$read = array(STDIN);
$write = array(STDOUT, STDERR);

stream_set_blocking(STDIN, 0);
stream_set_blocking(STDOUT, 0);
stream_set_blocking(STDERR, 0);

$out = $err = '';
while ($read || $write) {
    $r = $read;
    $w = $write;
    $e = null;
    $n = stream_select($r, $w, $e, 5);

    if (false === $n) {
        die(ERR_SELECT_FAILED);
    } elseif ($n < 1) {
        die(ERR_TIMEOUT);
    }

    if (in_array(STDOUT, $w) && strlen($out) > 0) {
         $written = fwrite(STDOUT, (binary) $out, 32768);
         if (false === $written) {
             die(ERR_WRITE_FAILED);
         }
         $out = (binary) substr($out, $written);
    }
    if (null === $read && strlen($out) < 1) {
        $write = array_diff($write, array(STDOUT));
    }

    if (in_array(STDERR, $w) && strlen($err) > 0) {
         $written = fwrite(STDERR, (binary) $err, 32768);
         if (false === $written) {
             die(ERR_WRITE_FAILED);
         }
         $err = (binary) substr($err, $written);
    }
    if (null === $read && strlen($err) < 1) {
        $write = array_diff($write, array(STDERR));
    }

    if ($r) {
        $str = fread(STDIN, 32768);
        if (false !== $str) {
            $out .= $str;
            $err .= $str;
        }
        if (false === $str || feof(STDIN)) {
            $read = null;
            if (!feof(STDIN)) {
                die(ERR_READ_FAILED);
            }
        }
    }
}
PK��Z�WKo�
�
Ktest/Process/Symfony/Component/Process/Tests/ProcessFailedExceptionTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Tests;

use Symfony\Component\Process\Exception\ProcessFailedException;

/**
 * @author Sebastian Marek <proofek@gmail.com>
 */
class ProcessFailedExceptionTest extends \PHPUnit_Framework_TestCase
{
    /**
     * tests ProcessFailedException throws exception if the process was successful
     */
    public function testProcessFailedExceptionThrowsException()
    {
        $process = $this->getMock(
            'Symfony\Component\Process\Process',
            array('isSuccessful'),
            array('php')
        );
        $process->expects($this->once())
            ->method('isSuccessful')
            ->will($this->returnValue(true));

        $this->setExpectedException(
            '\InvalidArgumentException',
            'Expected a failed process, but the given process was successful.'
        );

        new ProcessFailedException($process);
    }

    /**
     * tests ProcessFailedException uses information from process output
     * to generate exception message
     */
    public function testProcessFailedExceptionPopulatesInformationFromProcessOutput()
    {
        $cmd = 'php';
        $exitCode = 1;
        $exitText = 'General error';
        $output = "Command output";
        $errorOutput = "FATAL: Unexpected error";

        $process = $this->getMock(
            'Symfony\Component\Process\Process',
            array('isSuccessful', 'getOutput', 'getErrorOutput', 'getExitCode', 'getExitCodeText'),
            array($cmd)
        );
        $process->expects($this->once())
            ->method('isSuccessful')
            ->will($this->returnValue(false));
        $process->expects($this->once())
            ->method('getOutput')
            ->will($this->returnValue($output));
        $process->expects($this->once())
            ->method('getErrorOutput')
            ->will($this->returnValue($errorOutput));
        $process->expects($this->once())
            ->method('getExitCode')
            ->will($this->returnValue($exitCode));
        $process->expects($this->once())
            ->method('getExitCodeText')
            ->will($this->returnValue($exitText));

        $exception = new ProcessFailedException($process);

        $this->assertEquals(
            "The command \"$cmd\" failed.\nExit Code: $exitCode($exitText)\n\nOutput:\n================\n{$output}\n\nError Output:\n================\n{$errorOutput}",
            $exception->getMessage()
        );
    }
}
PK��ZC�u^UUAtest/Process/Symfony/Component/Process/Tests/ProcessUtilsTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Tests;

use Symfony\Component\Process\ProcessUtils;

class ProcessUtilsTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider dataArguments
     */
    public function testEscapeArgument($result, $argument)
    {
        $this->assertSame($result, ProcessUtils::escapeArgument($argument));
    }

    public function dataArguments()
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            return array(
                array('"\"php\" \"-v\""', '"php" "-v"'),
                array('"foo bar"', 'foo bar'),
                array('^%"path"^%', '%path%'),
                array('"<|>\\" \\"\'f"', '<|>" "\'f'),
                array('""', ''),
                array('"with\trailingbs\\\\"', 'with\trailingbs\\'),
            );
        }

        return array(
            array("'\"php\" \"-v\"'", '"php" "-v"'),
            array("'foo bar'", 'foo bar'),
            array("'%path%'", '%path%'),
            array("'<|>\" \"'\\''f'", '<|>" "\'f'),
            array("''", ''),
            array("'with\\trailingbs\\'", 'with\trailingbs\\'),
        );
    }
}
PK��Z[�VAChChDtest/Process/Symfony/Component/Process/Tests/AbstractProcessTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Tests;

use Symfony\Component\Process\Exception\ProcessTimedOutException;
use Symfony\Component\Process\Process;
use Symfony\Component\Process\Exception\RuntimeException;
use Symfony\Component\Process\ProcessPipes;

/**
 * @author Robert Schönthal <seroscho@googlemail.com>
 */
abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase
{
    public function testThatProcessDoesNotThrowWarningDuringRun()
    {
        @trigger_error('Test Error', E_USER_NOTICE);
        $process = $this->getProcess("php -r 'sleep(3)'");
        $process->run();
        $actualError = error_get_last();
        $this->assertEquals('Test Error', $actualError['message']);
        $this->assertEquals(E_USER_NOTICE, $actualError['type']);
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\InvalidArgumentException
     */
    public function testNegativeTimeoutFromConstructor()
    {
        $this->getProcess('', null, null, null, -1);
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\InvalidArgumentException
     */
    public function testNegativeTimeoutFromSetter()
    {
        $p = $this->getProcess('');
        $p->setTimeout(-1);
    }

    public function testFloatAndNullTimeout()
    {
        $p = $this->getProcess('');

        $p->setTimeout(10);
        $this->assertSame(10.0, $p->getTimeout());

        $p->setTimeout(null);
        $this->assertNull($p->getTimeout());

        $p->setTimeout(0.0);
        $this->assertNull($p->getTimeout());
    }

    public function testStopWithTimeoutIsActuallyWorking()
    {
        $this->verifyPosixIsEnabled();

        // exec is mandatory here since we send a signal to the process
        // see https://github.com/symfony/symfony/issues/5030 about prepending
        // command with exec
        $p = $this->getProcess('exec php '.__DIR__.'/NonStopableProcess.php 3');
        $p->start();
        usleep(100000);
        $start = microtime(true);
        $p->stop(1.1, SIGKILL);
        while ($p->isRunning()) {
            usleep(1000);
        }
        $duration = microtime(true) - $start;

        $this->assertLessThan(1.8, $duration);
    }

    public function testAllOutputIsActuallyReadOnTermination()
    {
        // this code will result in a maximum of 2 reads of 8192 bytes by calling
        // start() and isRunning().  by the time getOutput() is called the process
        // has terminated so the internal pipes array is already empty. normally
        // the call to start() will not read any data as the process will not have
        // generated output, but this is non-deterministic so we must count it as
        // a possibility.  therefore we need 2 * ProcessPipes::CHUNK_SIZE plus
        // another byte which will never be read.
        $expectedOutputSize = ProcessPipes::CHUNK_SIZE * 2 + 2;

        $code = sprintf('echo str_repeat(\'*\', %d);', $expectedOutputSize);
        $p = $this->getProcess(sprintf('php -r %s', escapeshellarg($code)));

        $p->start();
        // Let's wait enough time for process to finish...
        // Here we don't call Process::run or Process::wait to avoid any read of pipes
        usleep(500000);

        if ($p->isRunning()) {
            $this->markTestSkipped('Process execution did not complete in the required time frame');
        }

        $o = $p->getOutput();

        $this->assertEquals($expectedOutputSize, strlen($o));
    }

    public function testCallbacksAreExecutedWithStart()
    {
        $data = '';

        $process = $this->getProcess('echo foo && php -r "sleep(1);" && echo foo');
        $process->start(function ($type, $buffer) use (&$data) {
            $data .= $buffer;
        });

        while ($process->isRunning()) {
            usleep(10000);
        }

        $this->assertEquals(2, preg_match_all('/foo/', $data, $matches));
    }

    /**
     * tests results from sub processes
     *
     * @dataProvider responsesCodeProvider
     */
    public function testProcessResponses($expected, $getter, $code)
    {
        $p = $this->getProcess(sprintf('php -r %s', escapeshellarg($code)));
        $p->run();

        $this->assertSame($expected, $p->$getter());
    }

    /**
     * tests results from sub processes
     *
     * @dataProvider pipesCodeProvider
     */
    public function testProcessPipes($code, $size)
    {
        $expected = str_repeat(str_repeat('*', 1024), $size) . '!';
        $expectedLength = (1024 * $size) + 1;

        $p = $this->getProcess(sprintf('php -r %s', escapeshellarg($code)));
        $p->setStdin($expected);
        $p->run();

        $this->assertEquals($expectedLength, strlen($p->getOutput()));
        $this->assertEquals($expectedLength, strlen($p->getErrorOutput()));
    }

    public function chainedCommandsOutputProvider()
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            return array(
                array("2 \r\n2\r\n", '&&', '2')
            );
        }

        return array(
            array("1\n1\n", ';', '1'),
            array("2\n2\n", '&&', '2'),
        );
    }

    /**
     *
     * @dataProvider chainedCommandsOutputProvider
     */
    public function testChainedCommandsOutput($expected, $operator, $input)
    {
        $process = $this->getProcess(sprintf('echo %s %s echo %s', $input, $operator, $input));
        $process->run();
        $this->assertEquals($expected, $process->getOutput());
    }

    public function testCallbackIsExecutedForOutput()
    {
        $p = $this->getProcess(sprintf('php -r %s', escapeshellarg('echo \'foo\';')));

        $called = false;
        $p->run(function ($type, $buffer) use (&$called) {
            $called = $buffer === 'foo';
        });

        $this->assertTrue($called, 'The callback should be executed with the output');
    }

    public function testGetErrorOutput()
    {
        $p = $this->getProcess(sprintf('php -r %s', escapeshellarg('$n = 0; while ($n < 3) { file_put_contents(\'php://stderr\', \'ERROR\'); $n++; }')));

        $p->run();
        $this->assertEquals(3, preg_match_all('/ERROR/', $p->getErrorOutput(), $matches));
    }

    public function testGetIncrementalErrorOutput()
    {
        $p = $this->getProcess(sprintf('php -r %s', escapeshellarg('$n = 0; while ($n < 3) { usleep(100000); file_put_contents(\'php://stderr\', \'ERROR\'); $n++; }')));

        $p->start();
        while ($p->isRunning()) {
            $this->assertLessThanOrEqual(1, preg_match_all('/ERROR/', $p->getIncrementalErrorOutput(), $matches));
            usleep(20000);
        }
    }

    public function testFlushErrorOutput()
    {
        $p = $this->getProcess(sprintf('php -r %s', escapeshellarg('$n = 0; while ($n < 3) { file_put_contents(\'php://stderr\', \'ERROR\'); $n++; }')));

        $p->run();
        $p->clearErrorOutput();
        $this->assertEmpty($p->getErrorOutput());
    }

    public function testGetOutput()
    {
        $p = $this->getProcess(sprintf('php -r %s', escapeshellarg('$n=0;while ($n<3) {echo \' foo \';$n++; usleep(500); }')));

        $p->run();
        $this->assertEquals(3, preg_match_all('/foo/', $p->getOutput(), $matches));
    }

    public function testGetIncrementalOutput()
    {
        $p = $this->getProcess(sprintf('php -r %s', escapeshellarg('$n=0;while ($n<3) { echo \' foo \'; usleep(50000); $n++; }')));

        $p->start();
        while ($p->isRunning()) {
            $this->assertLessThanOrEqual(1, preg_match_all('/foo/', $p->getIncrementalOutput(), $matches));
            usleep(20000);
        }
    }

    public function testFlushOutput()
    {
        $p = $this->getProcess(sprintf('php -r %s', escapeshellarg('$n=0;while ($n<3) {echo \' foo \';$n++;}')));

        $p->run();
        $p->clearOutput();
        $this->assertEmpty($p->getOutput());
    }

    public function testExitCodeCommandFailed()
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->markTestSkipped('Windows does not support POSIX exit code');
        }

        // such command run in bash return an exitcode 127
        $process = $this->getProcess('nonexistingcommandIhopeneversomeonewouldnameacommandlikethis');
        $process->run();

        $this->assertGreaterThan(0, $process->getExitCode());
    }

    public function testTTYCommand()
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->markTestSkipped('Windows does have /dev/tty support');
        }

        $process = $this->getProcess('echo "foo" >> /dev/null && php -r "usleep(100000);"');
        $process->setTTY(true);
        $process->start();
        $this->assertTrue($process->isRunning());
        $process->wait();

        $this->assertSame(Process::STATUS_TERMINATED, $process->getStatus());
    }

    public function testTTYCommandExitCode()
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->markTestSkipped('Windows does have /dev/tty support');
        }

        $process = $this->getProcess('echo "foo" >> /dev/null');
        $process->setTTY(true);
        $process->run();

        $this->assertTrue($process->isSuccessful());
    }

    public function testExitCodeTextIsNullWhenExitCodeIsNull()
    {
        $process = $this->getProcess('');
        $this->assertNull($process->getExitCodeText());
    }

    public function testExitCodeText()
    {
        $process = $this->getProcess('');
        $r = new \ReflectionObject($process);
        $p = $r->getProperty('exitcode');
        $p->setAccessible(true);

        $p->setValue($process, 2);
        $this->assertEquals('Misuse of shell builtins', $process->getExitCodeText());
    }

    public function testStartIsNonBlocking()
    {
        $process = $this->getProcess('php -r "usleep(500000);"');
        $start = microtime(true);
        $process->start();
        $end = microtime(true);
        $this->assertLessThan(0.2, $end-$start);
        $process->wait();
    }

    public function testUpdateStatus()
    {
        $process = $this->getProcess('php -h');
        $process->run();
        $this->assertTrue(strlen($process->getOutput()) > 0);
    }

    public function testGetExitCodeIsNullOnStart()
    {
        $process = $this->getProcess('php -r "usleep(200000);"');
        $this->assertNull($process->getExitCode());
        $process->start();
        $this->assertNull($process->getExitCode());
        $process->wait();
        $this->assertEquals(0, $process->getExitCode());
    }

    public function testGetExitCodeIsNullOnWhenStartingAgain()
    {
        $process = $this->getProcess('php -r "usleep(200000);"');
        $process->run();
        $this->assertEquals(0, $process->getExitCode());
        $process->start();
        $this->assertNull($process->getExitCode());
        $process->wait();
        $this->assertEquals(0, $process->getExitCode());
    }

    public function testGetExitCode()
    {
        $process = $this->getProcess('php -m');
        $process->run();
        $this->assertSame(0, $process->getExitCode());
    }

    public function testStatus()
    {
        $process = $this->getProcess('php -r "usleep(500000);"');
        $this->assertFalse($process->isRunning());
        $this->assertFalse($process->isStarted());
        $this->assertFalse($process->isTerminated());
        $this->assertSame(Process::STATUS_READY, $process->getStatus());
        $process->start();
        $this->assertTrue($process->isRunning());
        $this->assertTrue($process->isStarted());
        $this->assertFalse($process->isTerminated());
        $this->assertSame(Process::STATUS_STARTED, $process->getStatus());
        $process->wait();
        $this->assertFalse($process->isRunning());
        $this->assertTrue($process->isStarted());
        $this->assertTrue($process->isTerminated());
        $this->assertSame(Process::STATUS_TERMINATED, $process->getStatus());
    }

    public function testStop()
    {
        $process = $this->getProcess('php -r "sleep(4);"');
        $process->start();
        $this->assertTrue($process->isRunning());
        $process->stop();
        $this->assertFalse($process->isRunning());
    }

    public function testIsSuccessful()
    {
        $process = $this->getProcess('php -m');
        $process->run();
        $this->assertTrue($process->isSuccessful());
    }

    public function testIsSuccessfulOnlyAfterTerminated()
    {
        $process = $this->getProcess('php -r "sleep(1);"');
        $process->start();
        while ($process->isRunning()) {
            $this->assertFalse($process->isSuccessful());
            usleep(300000);
        }

        $this->assertTrue($process->isSuccessful());
    }

    public function testIsNotSuccessful()
    {
        $process = $this->getProcess('php -r "usleep(500000);throw new \Exception(\'BOUM\');"');
        $process->start();
        $this->assertTrue($process->isRunning());
        $process->wait();
        $this->assertFalse($process->isSuccessful());
    }

    public function testProcessIsNotSignaled()
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->markTestSkipped('Windows does not support POSIX signals');
        }

        $process = $this->getProcess('php -m');
        $process->run();
        $this->assertFalse($process->hasBeenSignaled());
    }

    public function testProcessWithoutTermSignalIsNotSignaled()
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->markTestSkipped('Windows does not support POSIX signals');
        }

        $process = $this->getProcess('php -m');
        $process->run();
        $this->assertFalse($process->hasBeenSignaled());
    }

    public function testProcessWithoutTermSignal()
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->markTestSkipped('Windows does not support POSIX signals');
        }

        $process = $this->getProcess('php -m');
        $process->run();
        $this->assertEquals(0, $process->getTermSignal());
    }

    public function testProcessIsSignaledIfStopped()
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->markTestSkipped('Windows does not support POSIX signals');
        }

        $process = $this->getProcess('php -r "sleep(4);"');
        $process->start();
        $process->stop();
        $this->assertTrue($process->hasBeenSignaled());
    }

    public function testProcessWithTermSignal()
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->markTestSkipped('Windows does not support POSIX signals');
        }

        // SIGTERM is only defined if pcntl extension is present
        $termSignal = defined('SIGTERM') ? SIGTERM : 15;

        $process = $this->getProcess('php -r "sleep(4);"');
        $process->start();
        $process->stop();

        $this->assertEquals($termSignal, $process->getTermSignal());
    }

    public function testProcessThrowsExceptionWhenExternallySignaled()
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->markTestSkipped('Windows does not support POSIX signals');
        }

        if (!function_exists('posix_kill')) {
            $this->markTestSkipped('posix_kill is required for this test');
        }

        $termSignal = defined('SIGKILL') ? SIGKILL : 9;

        $process = $this->getProcess('exec php -r "while (true) {}"');
        $process->start();
        posix_kill($process->getPid(), $termSignal);

        $this->setExpectedException('Symfony\Component\Process\Exception\RuntimeException', 'The process has been signaled with signal "9".');
        $process->wait();
    }

    public function testRestart()
    {
        $process1 = $this->getProcess('php -r "echo getmypid();"');
        $process1->run();
        $process2 = $process1->restart();

        $process2->wait(); // wait for output

        // Ensure that both processed finished and the output is numeric
        $this->assertFalse($process1->isRunning());
        $this->assertFalse($process2->isRunning());
        $this->assertTrue(is_numeric($process1->getOutput()));
        $this->assertTrue(is_numeric($process2->getOutput()));

        // Ensure that restart returned a new process by check that the output is different
        $this->assertNotEquals($process1->getOutput(), $process2->getOutput());
    }

    public function testPhpDeadlock()
    {
        $this->markTestSkipped('Can course PHP to hang');

        // Sleep doesn't work as it will allow the process to handle signals and close
        // file handles from the other end.
        $process = $this->getProcess('php -r "while (true) {}"');
        $process->start();

        // PHP will deadlock when it tries to cleanup $process
    }

    public function testRunProcessWithTimeout()
    {
        $timeout = 0.5;
        $process = $this->getProcess('php -r "usleep(600000);"');
        $process->setTimeout($timeout);
        $start = microtime(true);
        try {
            $process->run();
            $this->fail('A RuntimeException should have been raised');
        } catch (RuntimeException $e) {

        }
        $duration = microtime(true) - $start;

        $this->assertLessThan($timeout + Process::TIMEOUT_PRECISION, $duration);
    }

    public function testCheckTimeoutOnNonStartedProcess()
    {
        $process = $this->getProcess('php -r "sleep(3);"');
        $process->checkTimeout();
    }

    public function testCheckTimeoutOnTerminatedProcess()
    {
        $process = $this->getProcess('php -v');
        $process->run();
        $process->checkTimeout();
    }

    public function testCheckTimeoutOnStartedProcess()
    {
        $timeout = 0.5;
        $precision = 100000;
        $process = $this->getProcess('php -r "sleep(3);"');
        $process->setTimeout($timeout);
        $start = microtime(true);

        $process->start();

        try {
            while ($process->isRunning()) {
                $process->checkTimeout();
                usleep($precision);
            }
            $this->fail('A RuntimeException should have been raised');
        } catch (RuntimeException $e) {

        }
        $duration = microtime(true) - $start;

        $this->assertLessThan($timeout + $precision, $duration);
        $this->assertFalse($process->isSuccessful());
    }

    /**
     * @group idle-timeout
     */
    public function testIdleTimeout()
    {
        $process = $this->getProcess('sleep 3');
        $process->setTimeout(10);
        $process->setIdleTimeout(1);

        try {
            $process->run();

            $this->fail('A timeout exception was expected.');
        } catch (ProcessTimedOutException $ex) {
            $this->assertTrue($ex->isIdleTimeout());
            $this->assertFalse($ex->isGeneralTimeout());
            $this->assertEquals(1.0, $ex->getExceededTimeout());
        }
    }

    /**
     * @group idle-timeout
     */
    public function testIdleTimeoutNotExceededWhenOutputIsSent()
    {
        $process = $this->getProcess('echo "foo" && sleep 1 && echo "foo" && sleep 1 && echo "foo" && sleep 1 && echo "foo" && sleep 5');
        $process->setTimeout(5);
        $process->setIdleTimeout(3);

        try {
            $process->run();
            $this->fail('A timeout exception was expected.');
        } catch (ProcessTimedOutException $ex) {
            $this->assertTrue($ex->isGeneralTimeout());
            $this->assertFalse($ex->isIdleTimeout());
            $this->assertEquals(5.0, $ex->getExceededTimeout());
        }
    }

    public function testStartAfterATimeout()
    {
        $process = $this->getProcess('php -r "$n = 1000; while ($n--) {echo \'\'; usleep(1000); }"');
        $process->setTimeout(0.1);
        try {
            $process->run();
            $this->fail('An exception should have been raised.');
        } catch (\Exception $e) {

        }
        $process->start();
        usleep(10000);
        $process->stop();
    }

    public function testGetPid()
    {
        $process = $this->getProcess('php -r "usleep(500000);"');
        $process->start();
        $this->assertGreaterThan(0, $process->getPid());
        $process->wait();
    }

    public function testGetPidIsNullBeforeStart()
    {
        $process = $this->getProcess('php -r "sleep(1);"');
        $this->assertNull($process->getPid());
    }

    public function testGetPidIsNullAfterRun()
    {
        $process = $this->getProcess('php -m');
        $process->run();
        $this->assertNull($process->getPid());
    }

    public function testSignal()
    {
        $this->verifyPosixIsEnabled();

        $process = $this->getProcess('exec php -f ' . __DIR__ . '/SignalListener.php');
        $process->start();
        usleep(500000);
        $process->signal(SIGUSR1);

        while ($process->isRunning() && false === strpos($process->getoutput(), 'Caught SIGUSR1')) {
            usleep(10000);
        }

        $this->assertEquals('Caught SIGUSR1', $process->getOutput());
    }

    public function testExitCodeIsAvailableAfterSignal()
    {
        $this->verifyPosixIsEnabled();

        $process = $this->getProcess('sleep 4');
        $process->start();
        $process->signal(SIGKILL);

        while ($process->isRunning()) {
            usleep(10000);
        }

        $this->assertFalse($process->isRunning());
        $this->assertTrue($process->hasBeenSignaled());
        $this->assertFalse($process->isSuccessful());
        $this->assertEquals(137, $process->getExitCode());
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\LogicException
     */
    public function testSignalProcessNotRunning()
    {
        $this->verifyPosixIsEnabled();
        $process = $this->getProcess('php -m');
        $process->signal(SIGHUP);
    }

    /**
     * @dataProvider provideMethodsThatNeedARunningProcess
     */
    public function testMethodsThatNeedARunningProcess($method)
    {
        $process = $this->getProcess('php -m');
        $this->setExpectedException('Symfony\Component\Process\Exception\LogicException', sprintf('Process must be started before calling %s.', $method));
        call_user_func(array($process, $method));
    }

    public function provideMethodsThatNeedARunningProcess()
    {
        return array(
            array('getOutput'),
            array('getIncrementalOutput'),
            array('getErrorOutput'),
            array('getIncrementalErrorOutput'),
            array('wait'),
        );
    }

    /**
     * @dataProvider provideMethodsThatNeedATerminatedProcess
     */
    public function testMethodsThatNeedATerminatedProcess($method)
    {
        $process = $this->getProcess('php -r "sleep(1);"');
        $process->start();
        try {
            call_user_func(array($process, $method));
            $process->stop(0);
            $this->fail('A LogicException must have been thrown');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\Component\Process\Exception\LogicException', $e);
            $this->assertEquals(sprintf('Process must be terminated before calling %s.', $method), $e->getMessage());
        }
        $process->stop(0);
    }

    public function provideMethodsThatNeedATerminatedProcess()
    {
        return array(
            array('hasBeenSignaled'),
            array('getTermSignal'),
            array('hasBeenStopped'),
            array('getStopSignal'),
        );
    }

    private function verifyPosixIsEnabled()
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->markTestSkipped('POSIX signals do not work on Windows');
        }
        if (!defined('SIGUSR1')) {
            $this->markTestSkipped('The pcntl extension is not enabled');
        }
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testSignalWithWrongIntSignal()
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->markTestSkipped('POSIX signals do not work on Windows');
        }

        $process = $this->getProcess('php -r "sleep(3);"');
        $process->start();
        $process->signal(-4);
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testSignalWithWrongNonIntSignal()
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->markTestSkipped('POSIX signals do not work on Windows');
        }

        $process = $this->getProcess('php -r "sleep(3);"');
        $process->start();
        $process->signal('Céphalopodes');
    }

    public function responsesCodeProvider()
    {
        return array(
            //expected output / getter / code to execute
            //array(1,'getExitCode','exit(1);'),
            //array(true,'isSuccessful','exit();'),
            array('output', 'getOutput', 'echo \'output\';'),
        );
    }

    public function pipesCodeProvider()
    {
        $variations = array(
            'fwrite(STDOUT, $in = file_get_contents(\'php://stdin\')); fwrite(STDERR, $in);',
            'include \''.__DIR__.'/PipeStdinInStdoutStdErrStreamSelect.php\';',
        );

        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            // Avoid XL buffers on Windows because of https://bugs.php.net/bug.php?id=65650
            $sizes = array(1, 2, 4, 8);
        } else {
            $sizes = array(1, 16, 64, 1024, 4096);
        }

        $codes = array();
        foreach ($sizes as $size) {
            foreach ($variations as $code) {
                $codes[] = array($code, $size);
            }
        }

        return $codes;
    }

    /**
     * provides default method names for simple getter/setter
     */
    public function methodProvider()
    {
        $defaults = array(
            array('CommandLine'),
            array('Timeout'),
            array('WorkingDirectory'),
            array('Env'),
            array('Stdin'),
            array('Options')
        );

        return $defaults;
    }

    /**
     * @param string  $commandline
     * @param null    $cwd
     * @param array   $env
     * @param null    $stdin
     * @param integer $timeout
     * @param array   $options
     *
     * @return Process
     */
    abstract protected function getProcess($commandline, $cwd = null, array $env = null, $stdin = null, $timeout = 60, array $options = array());
}
PK��Z=�,j��?test/Process/Symfony/Component/Process/Tests/SignalListener.phpnu�[���<?php

// required for signal handling
declare(ticks = 1);

pcntl_signal(SIGUSR1, function () {echo "Caught SIGUSR1"; exit;});

$n=0;

// ticks require activity to work - sleep(4); does not work
while ($n < 400) {
    usleep(10000);
    $n++;
}

return;
PK��Z���
��Btest/Process/Symfony/Component/Process/Tests/SimpleProcessTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Tests;

use Symfony\Component\Process\Process;

class SimpleProcessTest extends AbstractProcessTest
{
    private $enabledSigchild = false;

    public function setUp()
    {
        ob_start();
        phpinfo(INFO_GENERAL);

        $this->enabledSigchild = false !== strpos(ob_get_clean(), '--enable-sigchild');
    }

    public function testGetExitCode()
    {
        $this->skipIfPHPSigchild(); // This test use exitcode that is not available in this case
        parent::testGetExitCode();
    }

    public function testExitCodeCommandFailed()
    {
        $this->skipIfPHPSigchild(); // This test use exitcode that is not available in this case
        parent::testExitCodeCommandFailed();
    }

    public function testProcessIsSignaledIfStopped()
    {
        $this->expectExceptionIfPHPSigchild('Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved');
        parent::testProcessIsSignaledIfStopped();
    }

    public function testProcessWithTermSignal()
    {
        $this->expectExceptionIfPHPSigchild('Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved');
        parent::testProcessWithTermSignal();
    }

    public function testProcessIsNotSignaled()
    {
        $this->expectExceptionIfPHPSigchild('Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved');
        parent::testProcessIsNotSignaled();
    }

    public function testProcessWithoutTermSignal()
    {
        $this->expectExceptionIfPHPSigchild('Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved');
        parent::testProcessWithoutTermSignal();
    }

    public function testExitCodeText()
    {
        $this->skipIfPHPSigchild(); // This test use exitcode that is not available in this case
        parent::testExitCodeText();
    }

    public function testIsSuccessful()
    {
        $this->skipIfPHPSigchild(); // This test use PID that is not available in this case
        parent::testIsSuccessful();
    }

    public function testIsNotSuccessful()
    {
        $this->skipIfPHPSigchild(); // This test use PID that is not available in this case
        parent::testIsNotSuccessful();
    }

    public function testGetPid()
    {
        $this->skipIfPHPSigchild(); // This test use PID that is not available in this case
        parent::testGetPid();
    }

    public function testGetPidIsNullBeforeStart()
    {
        $this->skipIfPHPSigchild(); // This test use PID that is not available in this case
        parent::testGetPidIsNullBeforeStart();
    }

    public function testGetPidIsNullAfterRun()
    {
        $this->skipIfPHPSigchild(); // This test use PID that is not available in this case
        parent::testGetPidIsNullAfterRun();
    }

    public function testSignal()
    {
        $this->expectExceptionIfPHPSigchild('Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild. The process can not be signaled.');
        parent::testSignal();
    }

    public function testProcessWithoutTermSignalIsNotSignaled()
    {
        $this->expectExceptionIfPHPSigchild('Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved');
        parent::testProcessWithoutTermSignalIsNotSignaled();
    }

    public function testProcessThrowsExceptionWhenExternallySignaled()
    {
        $this->skipIfPHPSigchild(); // This test use PID that is not available in this case
        parent::testProcessThrowsExceptionWhenExternallySignaled();
    }

    public function testExitCodeIsAvailableAfterSignal()
    {
        $this->expectExceptionIfPHPSigchild('Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild. The process can not be signaled.');
        parent::testExitCodeIsAvailableAfterSignal();
    }

    public function testSignalProcessNotRunning()
    {
        $this->setExpectedException('Symfony\Component\Process\Exception\LogicException', 'Can not send signal on a non running process.');
        parent::testSignalProcessNotRunning();
    }

    public function testSignalWithWrongIntSignal()
    {
        if ($this->enabledSigchild) {
            $this->expectExceptionIfPHPSigchild('Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild. The process can not be signaled.');
        } else {
            $this->setExpectedException('Symfony\Component\Process\Exception\RuntimeException', 'Error while sending signal `-4`.');
        }
        parent::testSignalWithWrongIntSignal();
    }

    public function testSignalWithWrongNonIntSignal()
    {
        if ($this->enabledSigchild) {
            $this->expectExceptionIfPHPSigchild('Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild. The process can not be signaled.');
        } else {
            $this->setExpectedException('Symfony\Component\Process\Exception\RuntimeException', 'Error while sending signal `Céphalopodes`.');
        }
        parent::testSignalWithWrongNonIntSignal();
    }

    /**
     * {@inheritdoc}
     */
    protected function getProcess($commandline, $cwd = null, array $env = null, $stdin = null, $timeout = 60, array $options = array())
    {
        return new Process($commandline, $cwd, $env, $stdin, $timeout, $options);
    }

    private function skipIfPHPSigchild()
    {
        if ($this->enabledSigchild) {
            $this->markTestSkipped('Your PHP has been compiled with --enable-sigchild, this test can not be executed');
        }
    }

    private function expectExceptionIfPHPSigchild($classname, $message)
    {
        if ($this->enabledSigchild) {
            $this->setExpectedException($classname, $message);
        }
    }
}
PK��Z�+�v,,Ctest/Process/Symfony/Component/Process/Tests/NonStopableProcess.phpnu�[���<?php

/**
 * Runs a PHP script that can be stopped only with a SIGKILL (9) signal for 3 seconds
 *
 * @args duration Run this script with a custom duration
 *
 * @example `php NonStopableProcess.php 42` will run the script for 42 seconds
 */

function handleSignal($signal)
{
    switch ($signal) {
        case SIGTERM:
            $name = 'SIGTERM';
            break;
        case SIGINT:
            $name = 'SIGINT';
            break;
        default:
            $name = $signal . ' (unknown)';
            break;
    }

    echo "received signal $name\n";
}

declare(ticks = 1);
pcntl_signal(SIGTERM, 'handleSignal');
pcntl_signal(SIGINT, 'handleSignal');

$duration = isset($argv[1]) ? (int) $argv[1] : 3;
$start = microtime(true);

while ($duration > (microtime(true) - $start)) {
    usleep(1000);
}
PK��Zm�����Mtest/Process/Symfony/Component/Process/Tests/ProcessInSigchildEnvironment.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Tests;

use Symfony\Component\Process\Process;

class ProcessInSigchildEnvironment extends Process
{
    protected function isSigchildEnabled()
    {
        return true;
    }
}
PK��Z����Ltest/Process/Symfony/Component/Process/Tests/SigchildDisabledProcessTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Tests;

class SigchildDisabledProcessTest extends AbstractProcessTest
{
    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.
     */
    public function testGetExitCode()
    {
        parent::testGetExitCode();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.
     */
    public function testGetExitCodeIsNullOnStart()
    {
        parent::testGetExitCodeIsNullOnStart();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.
     */
    public function testGetExitCodeIsNullOnWhenStartingAgain()
    {
        parent::testGetExitCodeIsNullOnWhenStartingAgain();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.
     */
    public function testExitCodeCommandFailed()
    {
        parent::testExitCodeCommandFailed();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     * @expectedExceptionMessage his PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.
     */
    public function testProcessIsSignaledIfStopped()
    {
        parent::testProcessIsSignaledIfStopped();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     * @expectedExceptionMessage his PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.
     */
    public function testProcessWithTermSignal()
    {
        parent::testProcessWithTermSignal();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     * @expectedExceptionMessage his PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.
     */
    public function testProcessIsNotSignaled()
    {
        parent::testProcessIsNotSignaled();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     * @expectedExceptionMessage his PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.
     */
    public function testProcessWithoutTermSignal()
    {
        parent::testProcessWithoutTermSignal();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.
     */
    public function testCheckTimeoutOnStartedProcess()
    {
        parent::testCheckTimeoutOnStartedProcess();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. The process identifier can not be retrieved.
     */
    public function testGetPid()
    {
        parent::testGetPid();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. The process identifier can not be retrieved.
     */
    public function testGetPidIsNullBeforeStart()
    {
        parent::testGetPidIsNullBeforeStart();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. The process identifier can not be retrieved.
     */
    public function testGetPidIsNullAfterRun()
    {
        parent::testGetPidIsNullAfterRun();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.
     */
    public function testExitCodeText()
    {
        $process = $this->getProcess('qdfsmfkqsdfmqmsd');
        $process->run();

        $process->getExitCodeText();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.
     */
    public function testExitCodeTextIsNullWhenExitCodeIsNull()
    {
        parent::testExitCodeTextIsNullWhenExitCodeIsNull();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.
     */
    public function testIsSuccessful()
    {
        parent::testIsSuccessful();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.
     */
    public function testIsSuccessfulOnlyAfterTerminated()
    {
        parent::testIsSuccessfulOnlyAfterTerminated();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.
     */
    public function testIsNotSuccessful()
    {
        parent::testIsNotSuccessful();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.
     */
    public function testTTYCommandExitCode()
    {
        parent::testTTYCommandExitCode();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. The process can not be signaled.
     */
    public function testSignal()
    {
        parent::testSignal();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.
     */
    public function testProcessWithoutTermSignalIsNotSignaled()
    {
        parent::testProcessWithoutTermSignalIsNotSignaled();
    }

    public function testStopWithTimeoutIsActuallyWorking()
    {
        $this->markTestSkipped('Stopping with signal is not supported in sigchild environment');
    }

    public function testProcessThrowsExceptionWhenExternallySignaled()
    {
        $this->markTestSkipped('Retrieving Pid is not supported in sigchild environment');
    }

    public function testExitCodeIsAvailableAfterSignal()
    {
        $this->markTestSkipped('Signal is not supported in sigchild environment');
    }

    /**
     * {@inheritdoc}
     */
    protected function getProcess($commandline, $cwd = null, array $env = null, $stdin = null, $timeout = 60, array $options = array())
    {
        $process = new ProcessInSigchildEnvironment($commandline, $cwd, $env, $stdin, $timeout, $options);
        $process->setEnhanceSigchildCompatibility(false);

        return $process;
    }
}
PK��ZH��sppCtest/Process/Symfony/Component/Process/Tests/ProcessBuilderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Tests;

use Symfony\Component\Process\ProcessBuilder;

class ProcessBuilderTest extends \PHPUnit_Framework_TestCase
{
    public function testInheritEnvironmentVars()
    {
        $_ENV['MY_VAR_1'] = 'foo';

        $proc = ProcessBuilder::create()
            ->add('foo')
            ->getProcess();

        unset($_ENV['MY_VAR_1']);

        $env = $proc->getEnv();
        $this->assertArrayHasKey('MY_VAR_1', $env);
        $this->assertEquals('foo', $env['MY_VAR_1']);
    }

    public function testAddEnvironmentVariables()
    {
        $pb = new ProcessBuilder();
        $env = array(
            'foo' => 'bar',
            'foo2' => 'bar2',
        );
        $proc = $pb
            ->add('command')
            ->setEnv('foo', 'bar2')
            ->addEnvironmentVariables($env)
            ->inheritEnvironmentVariables(false)
            ->getProcess()
        ;

        $this->assertSame($env, $proc->getEnv());
    }

    public function testProcessShouldInheritAndOverrideEnvironmentVars()
    {
        $_ENV['MY_VAR_1'] = 'foo';

        $proc = ProcessBuilder::create()
            ->setEnv('MY_VAR_1', 'bar')
            ->add('foo')
            ->getProcess();

        unset($_ENV['MY_VAR_1']);

        $env = $proc->getEnv();
        $this->assertArrayHasKey('MY_VAR_1', $env);
        $this->assertEquals('bar', $env['MY_VAR_1']);
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\InvalidArgumentException
     */
    public function testNegativeTimeoutFromSetter()
    {
        $pb = new ProcessBuilder();
        $pb->setTimeout(-1);
    }

    public function testNullTimeout()
    {
        $pb = new ProcessBuilder();
        $pb->setTimeout(10);
        $pb->setTimeout(null);

        $r = new \ReflectionObject($pb);
        $p = $r->getProperty('timeout');
        $p->setAccessible(true);

        $this->assertNull($p->getValue($pb));
    }

    public function testShouldSetArguments()
    {
        $pb = new ProcessBuilder(array('initial'));
        $pb->setArguments(array('second'));

        $proc = $pb->getProcess();

        $this->assertContains("second", $proc->getCommandLine());
    }

    public function testPrefixIsPrependedToAllGeneratedProcess()
    {
        $pb = new ProcessBuilder();
        $pb->setPrefix('/usr/bin/php');

        $proc = $pb->setArguments(array('-v'))->getProcess();
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->assertEquals('"/usr/bin/php" "-v"', $proc->getCommandLine());
        } else {
            $this->assertEquals("'/usr/bin/php' '-v'", $proc->getCommandLine());
        }

        $proc = $pb->setArguments(array('-i'))->getProcess();
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->assertEquals('"/usr/bin/php" "-i"', $proc->getCommandLine());
        } else {
            $this->assertEquals("'/usr/bin/php' '-i'", $proc->getCommandLine());
        }
    }

    public function testArrayPrefixesArePrependedToAllGeneratedProcess()
    {
        $pb = new ProcessBuilder();
        $pb->setPrefix(array('/usr/bin/php', 'composer.phar'));

        $proc = $pb->setArguments(array('-v'))->getProcess();
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->assertEquals('"/usr/bin/php" "composer.phar" "-v"', $proc->getCommandLine());
        } else {
            $this->assertEquals("'/usr/bin/php' 'composer.phar' '-v'", $proc->getCommandLine());
        }

        $proc = $pb->setArguments(array('-i'))->getProcess();
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->assertEquals('"/usr/bin/php" "composer.phar" "-i"', $proc->getCommandLine());
        } else {
            $this->assertEquals("'/usr/bin/php' 'composer.phar' '-i'", $proc->getCommandLine());
        }
    }

    public function testShouldEscapeArguments()
    {
        $pb = new ProcessBuilder(array('%path%', 'foo " bar', '%baz%baz'));
        $proc = $pb->getProcess();

        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->assertSame('^%"path"^% "foo \\" bar" "%baz%baz"', $proc->getCommandLine());
        } else {
            $this->assertSame("'%path%' 'foo \" bar' '%baz%baz'", $proc->getCommandLine());
        }
    }

    public function testShouldEscapeArgumentsAndPrefix()
    {
        $pb = new ProcessBuilder(array('arg'));
        $pb->setPrefix('%prefix%');
        $proc = $pb->getProcess();

        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->assertSame('^%"prefix"^% "arg"', $proc->getCommandLine());
        } else {
            $this->assertSame("'%prefix%' 'arg'", $proc->getCommandLine());
        }
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\LogicException
     */
    public function testShouldThrowALogicExceptionIfNoPrefixAndNoArgument()
    {
        ProcessBuilder::create()->getProcess();
    }

    public function testShouldNotThrowALogicExceptionIfNoArgument()
    {
        $process = ProcessBuilder::create()
            ->setPrefix('/usr/bin/php')
            ->getProcess();

        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->assertEquals('"/usr/bin/php"', $process->getCommandLine());
        } else {
            $this->assertEquals("'/usr/bin/php'", $process->getCommandLine());
        }
    }

    public function testShouldNotThrowALogicExceptionIfNoPrefix()
    {
        $process = ProcessBuilder::create(array('/usr/bin/php'))
            ->getProcess();

        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->assertEquals('"/usr/bin/php"', $process->getCommandLine());
        } else {
            $this->assertEquals("'/usr/bin/php'", $process->getCommandLine());
        }
    }
}
PK��Zx[��?test/Process/Symfony/Component/Process/Tests/PhpProcessTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Tests;

use Symfony\Component\Process\PhpProcess;

class PhpProcessTest extends \PHPUnit_Framework_TestCase
{
    public function testNonBlockingWorks()
    {
        $expected = 'hello world!';
        $process = new PhpProcess(<<<PHP
<?php echo '$expected';
PHP
        );
        $process->start();
        $process->wait();
        $this->assertEquals($expected, $process->getOutput());
    }
}
PK��Z钊�\\Ktest/Process/Symfony/Component/Process/Tests/SigchildEnabledProcessTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Tests;

class SigchildEnabledProcessTest extends AbstractProcessTest
{
    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.
     */
    public function testProcessIsSignaledIfStopped()
    {
        parent::testProcessIsSignaledIfStopped();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.
     */
    public function testProcessWithTermSignal()
    {
        parent::testProcessWithTermSignal();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.
     */
    public function testProcessIsNotSignaled()
    {
        parent::testProcessIsNotSignaled();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.
     */
    public function testProcessWithoutTermSignal()
    {
        parent::testProcessWithoutTermSignal();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. The process identifier can not be retrieved.
     */
    public function testGetPid()
    {
        parent::testGetPid();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. The process identifier can not be retrieved.
     */
    public function testGetPidIsNullBeforeStart()
    {
        parent::testGetPidIsNullBeforeStart();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. The process identifier can not be retrieved.
     */
    public function testGetPidIsNullAfterRun()
    {
        parent::testGetPidIsNullAfterRun();
    }

    public function testExitCodeText()
    {
        $process = $this->getProcess('qdfsmfkqsdfmqmsd');
        $process->run();

        $this->assertInternalType('string', $process->getExitCodeText());
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. The process can not be signaled.
     */
    public function testSignal()
    {
        parent::testSignal();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.
     */
    public function testProcessWithoutTermSignalIsNotSignaled()
    {
        parent::testProcessWithoutTermSignalIsNotSignaled();
    }

    public function testProcessThrowsExceptionWhenExternallySignaled()
    {
        $this->markTestSkipped('Retrieving Pid is not supported in sigchild environment');
    }

    public function testExitCodeIsAvailableAfterSignal()
    {
        $this->markTestSkipped('Signal is not supported in sigchild environment');
    }

    public function testStartAfterATimeout()
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->markTestSkipped('Restarting a timed-out process on Windows is not supported in sigchild environment');
        }
        parent::testStartAfterATimeout();
    }

    /**
     * {@inheritdoc}
     */
    protected function getProcess($commandline, $cwd = null, array $env = null, $stdin = null, $timeout = 60, array $options = array())
    {
        $process = new ProcessInSigchildEnvironment($commandline, $cwd, $env, $stdin, $timeout, $options);
        $process->setEnhanceSigchildCompatibility(true);

        return $process;
    }
}
PK��Zp\H7test/Process/Symfony/Component/Process/phpunit.xml.distnu�[���<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony Process Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./Tests</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
PK��Z2�c�$�$Etest/Serializer/Symfony/Component/Serializer/Tests/SerializerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Tests;

use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
use Symfony\Component\Serializer\Normalizer\CustomNormalizer;
use Symfony\Component\Serializer\Tests\Fixtures\TraversableDummy;
use Symfony\Component\Serializer\Tests\Fixtures\NormalizableTraversableDummy;
use Symfony\Component\Serializer\Tests\Normalizer\TestNormalizer;
use Symfony\Component\Serializer\Tests\Normalizer\TestDenormalizer;

class SerializerTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException
     */
    public function testNormalizeNoMatch()
    {
        $this->serializer = new Serializer(array($this->getMock('Symfony\Component\Serializer\Normalizer\CustomNormalizer')));
        $this->serializer->normalize(new \stdClass(), 'xml');
    }

    public function testNormalizeTraversable()
    {
        $this->serializer = new Serializer(array(), array('json' => new JsonEncoder()));
        $result = $this->serializer->serialize(new TraversableDummy(), 'json');
        $this->assertEquals('{"foo":"foo","bar":"bar"}', $result);
    }

    public function testNormalizeGivesPriorityToInterfaceOverTraversable()
    {
        $this->serializer = new Serializer(array(new CustomNormalizer()), array('json' => new JsonEncoder()));
        $result = $this->serializer->serialize(new NormalizableTraversableDummy(), 'json');
        $this->assertEquals('{"foo":"normalizedFoo","bar":"normalizedBar"}', $result);
    }

    /**
     * @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException
     */
    public function testNormalizeOnDenormalizer()
    {
        $this->serializer = new Serializer(array(new TestDenormalizer()), array());
        $this->assertTrue($this->serializer->normalize(new \stdClass(), 'json'));
    }

    /**
     * @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException
     */
    public function testDenormalizeNoMatch()
    {
        $this->serializer = new Serializer(array($this->getMock('Symfony\Component\Serializer\Normalizer\CustomNormalizer')));
        $this->serializer->denormalize('foo', 'stdClass');
    }

    /**
     * @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException
     */
    public function testDenormalizeOnNormalizer()
    {
        $this->serializer = new Serializer(array(new TestNormalizer()), array());
        $data = array('title' => 'foo', 'numbers' => array(5, 3));
        $this->assertTrue($this->serializer->denormalize(json_encode($data), 'stdClass', 'json'));
    }

    public function testSerialize()
    {
        $this->serializer = new Serializer(array(new GetSetMethodNormalizer()), array('json' => new JsonEncoder()));
        $data = array('title' => 'foo', 'numbers' => array(5, 3));
        $result = $this->serializer->serialize(Model::fromArray($data), 'json');
        $this->assertEquals(json_encode($data), $result);
    }

    public function testSerializeScalar()
    {
        $this->serializer = new Serializer(array(), array('json' => new JsonEncoder()));
        $result = $this->serializer->serialize('foo', 'json');
        $this->assertEquals('"foo"', $result);
    }

    public function testSerializeArrayOfScalars()
    {
        $this->serializer = new Serializer(array(), array('json' => new JsonEncoder()));
        $data = array('foo', array(5, 3));
        $result = $this->serializer->serialize($data, 'json');
        $this->assertEquals(json_encode($data), $result);
    }

    /**
     * @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException
     */
    public function testSerializeNoEncoder()
    {
        $this->serializer = new Serializer(array(), array());
        $data = array('title' => 'foo', 'numbers' => array(5, 3));
        $this->serializer->serialize($data, 'json');
    }

    /**
     * @expectedException \Symfony\Component\Serializer\Exception\LogicException
     */
    public function testSerializeNoNormalizer()
    {
        $this->serializer = new Serializer(array(), array('json' => new JsonEncoder()));
        $data = array('title' => 'foo', 'numbers' => array(5, 3));
        $this->serializer->serialize(Model::fromArray($data), 'json');
    }

    public function testDeserialize()
    {
        $this->serializer = new Serializer(array(new GetSetMethodNormalizer()), array('json' => new JsonEncoder()));
        $data = array('title' => 'foo', 'numbers' => array(5, 3));
        $result = $this->serializer->deserialize(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json');
        $this->assertEquals($data, $result->toArray());
    }

    public function testDeserializeUseCache()
    {
        $this->serializer = new Serializer(array(new GetSetMethodNormalizer()), array('json' => new JsonEncoder()));
        $data = array('title' => 'foo', 'numbers' => array(5, 3));
        $this->serializer->deserialize(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json');
        $data = array('title' => 'bar', 'numbers' => array(2, 8));
        $result = $this->serializer->deserialize(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json');
        $this->assertEquals($data, $result->toArray());
    }

    /**
     * @expectedException \Symfony\Component\Serializer\Exception\LogicException
     */
    public function testDeserializeNoNormalizer()
    {
        $this->serializer = new Serializer(array(), array('json' => new JsonEncoder()));
        $data = array('title' => 'foo', 'numbers' => array(5, 3));
        $this->serializer->deserialize(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json');
    }

    /**
     * @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException
     */
    public function testDeserializeWrongNormalizer()
    {
        $this->serializer = new Serializer(array(new CustomNormalizer()), array('json' => new JsonEncoder()));
        $data = array('title' => 'foo', 'numbers' => array(5, 3));
        $this->serializer->deserialize(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json');
    }

    /**
     * @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException
     */
    public function testDeserializeNoEncoder()
    {
        $this->serializer = new Serializer(array(), array());
        $data = array('title' => 'foo', 'numbers' => array(5, 3));
        $this->serializer->deserialize(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json');
    }

    public function testDeserializeSupported()
    {
        $this->serializer = new Serializer(array(new GetSetMethodNormalizer()), array());
        $data = array('title' => 'foo', 'numbers' => array(5, 3));
        $this->assertTrue($this->serializer->supportsDenormalization(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json'));
    }

    public function testDeserializeNotSupported()
    {
        $this->serializer = new Serializer(array(new GetSetMethodNormalizer()), array());
        $data = array('title' => 'foo', 'numbers' => array(5, 3));
        $this->assertFalse($this->serializer->supportsDenormalization(json_encode($data), 'stdClass', 'json'));
    }

    public function testDeserializeNotSupportedMissing()
    {
        $this->serializer = new Serializer(array(), array());
        $data = array('title' => 'foo', 'numbers' => array(5, 3));
        $this->assertFalse($this->serializer->supportsDenormalization(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json'));
    }

    public function testEncode()
    {
        $this->serializer = new Serializer(array(), array('json' => new JsonEncoder()));
        $data = array('foo', array(5, 3));
        $result = $this->serializer->encode($data, 'json');
        $this->assertEquals(json_encode($data), $result);
    }

    public function testDecode()
    {
        $this->serializer = new Serializer(array(), array('json' => new JsonEncoder()));
        $data = array('foo', array(5, 3));
        $result = $this->serializer->decode(json_encode($data), 'json');
        $this->assertEquals($data, $result);
    }
}

class Model
{
    private $title;
    private $numbers;

    public static function fromArray($array)
    {
        $model = new self();
        if (isset($array['title'])) {
            $model->setTitle($array['title']);
        }
        if (isset($array['numbers'])) {
            $model->setNumbers($array['numbers']);
        }

        return $model;
    }

    public function getTitle()
    {
        return $this->title;
    }

    public function setTitle($title)
    {
        $this->title = $title;
    }

    public function getNumbers()
    {
        return $this->numbers;
    }

    public function setNumbers($numbers)
    {
        $this->numbers = $numbers;
    }

    public function toArray()
    {
        return array('title' => $this->title, 'numbers' => $this->numbers);
    }
}
PK��Z�m�))Ptest/Serializer/Symfony/Component/Serializer/Tests/Normalizer/TestNormalizer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Tests\Normalizer;

use Symfony\Component\Serializer\Normalizer\NormalizerInterface;

/**
 * Provides a test Normalizer which only implements the NormalizerInterface.
 *
 * @author Lin Clark <lin@lin-clark.com>
 */
class TestNormalizer implements NormalizerInterface
{
    /**
    * {@inheritdoc}
    */
    public function normalize($object, $format = null, array $context = array())
    {
    }

    /**
    * {@inheritdoc}
    */
    public function supportsNormalization($data, $format = null)
    {
        return true;
    }
}
PK��Z$ѕ�Vtest/Serializer/Symfony/Component/Serializer/Tests/Normalizer/CustomNormalizerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Tests\Normalizer;

use Symfony\Component\Serializer\Tests\Fixtures\ScalarDummy;
use Symfony\Component\Serializer\Normalizer\CustomNormalizer;
use Symfony\Component\Serializer\Serializer;

class CustomNormalizerTest extends \PHPUnit_Framework_TestCase
{
    protected function setUp()
    {
        $this->normalizer = new CustomNormalizer();
        $this->normalizer->setSerializer(new Serializer());
    }

    public function testSerialize()
    {
        $obj = new ScalarDummy();
        $obj->foo = 'foo';
        $obj->xmlFoo = 'xml';
        $this->assertEquals('foo', $this->normalizer->normalize($obj, 'json'));
        $this->assertEquals('xml', $this->normalizer->normalize($obj, 'xml'));
    }

    public function testDeserialize()
    {
        $obj = $this->normalizer->denormalize('foo', get_class(new ScalarDummy()), 'xml');
        $this->assertEquals('foo', $obj->xmlFoo);
        $this->assertNull($obj->foo);

        $obj = $this->normalizer->denormalize('foo', get_class(new ScalarDummy()), 'json');
        $this->assertEquals('foo', $obj->foo);
        $this->assertNull($obj->xmlFoo);
    }

    public function testSupportsNormalization()
    {
        $this->assertTrue($this->normalizer->supportsNormalization(new ScalarDummy()));
        $this->assertFalse($this->normalizer->supportsNormalization(new \stdClass()));
    }

    public function testSupportsDenormalization()
    {
        $this->assertTrue($this->normalizer->supportsDenormalization(array(), 'Symfony\Component\Serializer\Tests\Fixtures\ScalarDummy'));
        $this->assertFalse($this->normalizer->supportsDenormalization(array(), 'stdClass'));
        $this->assertTrue($this->normalizer->supportsDenormalization(array(), 'Symfony\Component\Serializer\Tests\Fixtures\DenormalizableDummy'));
    }
}
PK��Z��P1!!\test/Serializer/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Tests\Normalizer;

use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;

class GetSetMethodNormalizerTest extends \PHPUnit_Framework_TestCase
{
    protected function setUp()
    {
        $this->serializer = $this->getMock(__NAMESPACE__.'\SerializerNormalizer');
        $this->normalizer = new GetSetMethodNormalizer();
        $this->normalizer->setSerializer($this->serializer);
    }

    public function testNormalize()
    {
        $obj = new GetSetDummy();
        $object = new \stdClass();
        $obj->setFoo('foo');
        $obj->setBar('bar');
        $obj->setCamelCase('camelcase');
        $obj->setObject($object);

        $this->serializer
            ->expects($this->once())
            ->method('normalize')
            ->with($object, 'any')
            ->will($this->returnValue('string_object'))
        ;

        $this->assertEquals(
            array(
                'foo' => 'foo',
                'bar' => 'bar',
                'fooBar' => 'foobar',
                'camelCase' => 'camelcase',
                'object' => 'string_object',
            ),
            $this->normalizer->normalize($obj, 'any')
        );
    }

    public function testDenormalize()
    {
        $obj = $this->normalizer->denormalize(
            array('foo' => 'foo', 'bar' => 'bar', 'fooBar' => 'foobar'),
            __NAMESPACE__.'\GetSetDummy',
            'any'
        );
        $this->assertEquals('foo', $obj->getFoo());
        $this->assertEquals('bar', $obj->getBar());
    }

    public function testDenormalizeOnCamelCaseFormat()
    {
        $this->normalizer->setCamelizedAttributes(array('camel_case'));
        $obj = $this->normalizer->denormalize(
            array('camel_case' => 'camelCase'),
            __NAMESPACE__.'\GetSetDummy'
        );
        $this->assertEquals('camelCase', $obj->getCamelCase());
    }

    /**
     * @dataProvider attributeProvider
     */
    public function testFormatAttribute($attribute, $camelizedAttributes, $result)
    {
        $r = new \ReflectionObject($this->normalizer);
        $m = $r->getMethod('formatAttribute');
        $m->setAccessible(true);

        $this->normalizer->setCamelizedAttributes($camelizedAttributes);
        $this->assertEquals($m->invoke($this->normalizer, $attribute, $camelizedAttributes), $result);
    }

    public function attributeProvider()
    {
        return array(
            array('attribute_test', array('attribute_test'),'AttributeTest'),
            array('attribute_test', array('any'),'attribute_test'),
            array('attribute', array('attribute'),'Attribute'),
            array('attribute', array(), 'attribute'),
        );
    }

    public function testConstructorDenormalize()
    {
        $obj = $this->normalizer->denormalize(
            array('foo' => 'foo', 'bar' => 'bar', 'fooBar' => 'foobar'),
            __NAMESPACE__.'\GetConstructorDummy', 'any');
        $this->assertEquals('foo', $obj->getFoo());
        $this->assertEquals('bar', $obj->getBar());
    }

    /**
     * @dataProvider provideCallbacks
     */
    public function testCallbacks($callbacks, $value, $result, $message)
    {
        $this->normalizer->setCallbacks($callbacks);

        $obj = new GetConstructorDummy('', $value);

        $this->assertEquals(
            $result,
            $this->normalizer->normalize($obj, 'any'),
            $message
        );
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testUncallableCallbacks()
    {
        $this->normalizer->setCallbacks(array('bar' => null));

        $obj = new GetConstructorDummy('baz', 'quux');

        $this->normalizer->normalize($obj, 'any');
    }

    public function testIgnoredAttributes()
    {
        $this->normalizer->setIgnoredAttributes(array('foo', 'bar', 'camelCase', 'object'));

        $obj = new GetSetDummy();
        $obj->setFoo('foo');
        $obj->setBar('bar');

        $this->assertEquals(
            array('fooBar' => 'foobar'),
            $this->normalizer->normalize($obj, 'any')
        );
    }

    public function provideCallbacks()
    {
        return array(
            array(
                array(
                    'bar' => function ($bar) {
                        return 'baz';
                    },
                ),
                'baz',
                array('foo' => '', 'bar' => 'baz'),
                'Change a string',
            ),
            array(
                array(
                    'bar' => function ($bar) {
                        return null;
                    },
                ),
                'baz',
                array('foo' => '', 'bar' => null),
                'Null an item'
            ),
            array(
                array(
                    'bar' => function ($bar) {
                        return $bar->format('d-m-Y H:i:s');
                    },
                ),
                new \DateTime('2011-09-10 06:30:00'),
                array('foo' => '', 'bar' => '10-09-2011 06:30:00'),
                'Format a date',
            ),
            array(
                array(
                    'bar' => function ($bars) {
                        $foos = '';
                        foreach ($bars as $bar) {
                            $foos .= $bar->getFoo();
                        }

                        return $foos;
                    },
                ),
                array(new GetConstructorDummy('baz', ''), new GetConstructorDummy('quux', '')),
                array('foo' => '', 'bar' => 'bazquux'),
                'Collect a property',
            ),
            array(
                array(
                    'bar' => function ($bars) {
                        return count($bars);
                    },
                ),
                array(new GetConstructorDummy('baz', ''), new GetConstructorDummy('quux', '')),
                array('foo' => '', 'bar' => 2),
                'Count a property',
            ),
        );
    }

    /**
     * @expectedException \LogicException
     * @expectedExceptionMessage Cannot normalize attribute "object" because injected serializer is not a normalizer
     */
    public function testUnableToNormalizeObjectAttribute()
    {
        $serializer = $this->getMock('Symfony\Component\Serializer\SerializerInterface');
        $this->normalizer->setSerializer($serializer);

        $obj    = new GetSetDummy();
        $object = new \stdClass();
        $obj->setObject($object);

        $this->normalizer->normalize($obj, 'any');
    }
}

class GetSetDummy
{
    protected $foo;
    private $bar;
    protected $camelCase;
    protected $object;

    public function getFoo()
    {
        return $this->foo;
    }

    public function setFoo($foo)
    {
        $this->foo = $foo;
    }

    public function getBar()
    {
        return $this->bar;
    }

    public function setBar($bar)
    {
        $this->bar = $bar;
    }

    public function getFooBar()
    {
        return $this->foo.$this->bar;
    }

    public function getCamelCase()
    {
        return $this->camelCase;
    }

    public function setCamelCase($camelCase)
    {
        $this->camelCase = $camelCase;
    }

    public function otherMethod()
    {
        throw new \RuntimeException("Dummy::otherMethod() should not be called");
    }

    public function setObject($object)
    {
        $this->object = $object;
    }

    public function getObject()
    {
        return $this->object;
    }
}

class GetConstructorDummy
{
    protected $foo;
    private $bar;

    public function __construct($foo, $bar)
    {
        $this->foo = $foo;
        $this->bar = $bar;
    }

    public function getFoo()
    {
        return $this->foo;
    }

    public function getBar()
    {
        return $this->bar;
    }

    public function otherMethod()
    {
        throw new \RuntimeException("Dummy::otherMethod() should not be called");
    }
}

abstract class SerializerNormalizer implements SerializerInterface, NormalizerInterface
{
}
PK��Z�qBBRtest/Serializer/Symfony/Component/Serializer/Tests/Normalizer/TestDenormalizer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Tests\Normalizer;

use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;

/**
 * Provides a test Normalizer which only implements the DenormalizerInterface.
 *
 * @author Lin Clark <lin@lin-clark.com>
 */
class TestDenormalizer implements DenormalizerInterface
{
    /**
    * {@inheritdoc}
    */
    public function denormalize($data, $class, $format = null, array $context = array())
    {
    }

    /**
    * {@inheritdoc}
    */
    public function supportsDenormalization($data, $type, $format = null)
    {
        return true;
    }
}
PK��Z��K�__Ktest/Serializer/Symfony/Component/Serializer/Tests/Fixtures/ScalarDummy.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Tests\Fixtures;

use Symfony\Component\Serializer\Normalizer\NormalizableInterface;
use Symfony\Component\Serializer\Normalizer\DenormalizableInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;

class ScalarDummy implements NormalizableInterface, DenormalizableInterface
{
    public $foo;
    public $xmlFoo;

    public function normalize(NormalizerInterface $normalizer, $format = null, array $context = array())
    {
        return $format === 'xml' ? $this->xmlFoo : $this->foo;
    }

    public function denormalize(DenormalizerInterface $denormalizer, $data, $format = null, array $context = array())
    {
        if ($format === 'xml') {
            $this->xmlFoo = $data;
        } else {
            $this->foo = $data;
        }
    }
}
PK��Z��_��Ptest/Serializer/Symfony/Component/Serializer/Tests/Fixtures/TraversableDummy.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Tests\Fixtures;

class TraversableDummy implements \IteratorAggregate
{
    public $foo = 'foo';
    public $bar = 'bar';

    public function getIterator()
    {
        return new \ArrayIterator(get_object_vars($this));
    }
}
PK��ZG��5��\test/Serializer/Symfony/Component/Serializer/Tests/Fixtures/NormalizableTraversableDummy.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Tests\Fixtures;

use Symfony\Component\Serializer\Normalizer\NormalizableInterface;
use Symfony\Component\Serializer\Normalizer\DenormalizableInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;

class NormalizableTraversableDummy extends TraversableDummy implements NormalizableInterface, DenormalizableInterface
{
    public function normalize(NormalizerInterface $normalizer, $format = null, array $context = array())
    {
        return array(
            'foo' => 'normalizedFoo',
            'bar' => 'normalizedBar',
        );
    }

    public function denormalize(DenormalizerInterface $denormalizer, $data, $format = null, array $context = array())
    {
        return array(
            'foo' => 'denormalizedFoo',
            'bar' => 'denormalizedBar',
        );
    }
}
PK��Z�LY��Etest/Serializer/Symfony/Component/Serializer/Tests/Fixtures/Dummy.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Tests\Fixtures;

use Symfony\Component\Serializer\Normalizer\NormalizableInterface;
use Symfony\Component\Serializer\Normalizer\DenormalizableInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;

class Dummy implements NormalizableInterface, DenormalizableInterface
{
    public $foo;
    public $bar;
    public $baz;
    public $qux;

    public function normalize(NormalizerInterface $normalizer, $format = null, array $context = array())
    {
        return array(
            'foo' => $this->foo,
            'bar' => $this->bar,
            'baz' => $this->baz,
            'qux' => $this->qux,
        );
    }

    public function denormalize(DenormalizerInterface $denormalizer, $data, $format = null, array $context = array())
    {
        $this->foo = $data['foo'];
        $this->bar = $data['bar'];
        $this->baz = $data['baz'];
        $this->qux = $data['qux'];
    }
}
PK��ZY["�uuStest/Serializer/Symfony/Component/Serializer/Tests/Fixtures/DenormalizableDummy.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Tests\Fixtures;

use Symfony\Component\Serializer\Normalizer\DenormalizableInterface;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;

class DenormalizableDummy implements DenormalizableInterface
{

    public function denormalize(DenormalizerInterface $denormalizer, $data, $format = null, array $context = array())
    {

    }

}
PK��Zf|�B.B.Mtest/Serializer/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Tests\Encoder;

use Symfony\Component\Serializer\Tests\Fixtures\Dummy;
use Symfony\Component\Serializer\Tests\Fixtures\ScalarDummy;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
use Symfony\Component\Serializer\Normalizer\CustomNormalizer;

class XmlEncoderTest extends \PHPUnit_Framework_TestCase
{
    private $encoder;

    protected function setUp()
    {
        $this->encoder = new XmlEncoder();
        $serializer = new Serializer(array(new CustomNormalizer()), array('xml' => new XmlEncoder()));
        $this->encoder->setSerializer($serializer);
    }

    public function testEncodeScalar()
    {
        $obj = new ScalarDummy();
        $obj->xmlFoo = "foo";

        $expected = '<?xml version="1.0"?>'."\n".
            '<response>foo</response>'."\n";

        $this->assertEquals($expected, $this->encoder->encode($obj, 'xml'));
    }

    public function testSetRootNodeName()
    {
        $obj = new ScalarDummy();
        $obj->xmlFoo = "foo";

        $this->encoder->setRootNodeName('test');
        $expected = '<?xml version="1.0"?>'."\n".
            '<test>foo</test>'."\n";

        $this->assertEquals($expected, $this->encoder->encode($obj, 'xml'));
    }

    /**
     * @expectedException        \Symfony\Component\Serializer\Exception\UnexpectedValueException
     * @expectedExceptionMessage Document types are not allowed.
     */
    public function testDocTypeIsNotAllowed()
    {
        $this->encoder->decode('<?xml version="1.0"?><!DOCTYPE foo><foo></foo>', 'foo');
    }

    public function testAttributes()
    {
        $obj = new ScalarDummy();
        $obj->xmlFoo = array(
            'foo-bar' => array(
                '@id' => 1,
                '@name' => 'Bar'
            ),
            'Foo' => array(
                'Bar' => "Test",
                '@Type' => 'test'
            ),
            'föo_bär' => 'a',
            "Bar" => array(1,2,3),
            'a' => 'b',
        );
        $expected = '<?xml version="1.0"?>'."\n".
            '<response>'.
            '<foo-bar id="1" name="Bar"/>'.
            '<Foo Type="test"><Bar>Test</Bar></Foo>'.
            '<föo_bär>a</föo_bär>'.
            '<Bar>1</Bar>'.
            '<Bar>2</Bar>'.
            '<Bar>3</Bar>'.
            '<a>b</a>'.
            '</response>'."\n";
        $this->assertEquals($expected, $this->encoder->encode($obj, 'xml'));
    }

    public function testElementNameValid()
    {
        $obj = new ScalarDummy();
        $obj->xmlFoo = array(
            'foo-bar' => 'a',
            'foo_bar' => 'a',
            'föo_bär' => 'a',
        );

        $expected = '<?xml version="1.0"?>'."\n".
            '<response>'.
            '<foo-bar>a</foo-bar>'.
            '<foo_bar>a</foo_bar>'.
            '<föo_bär>a</föo_bär>'.
            '</response>'."\n";

        $this->assertEquals($expected, $this->encoder->encode($obj, 'xml'));
    }

    public function testEncodeSimpleXML()
    {
        $xml = simplexml_load_string('<firstname>Peter</firstname>');
        $array = array('person' => $xml);

        $expected = '<?xml version="1.0"?>'."\n".
            '<response><person><firstname>Peter</firstname></person></response>'."\n";

        $this->assertEquals($expected, $this->encoder->encode($array, 'xml'));
    }

    public function testEncodeXmlAttributes()
    {
        $xml = simplexml_load_string('<firstname>Peter</firstname>');
        $array = array('person' => $xml);

        $expected = '<?xml version="1.1" encoding="utf-8" standalone="yes"?>'."\n".
            '<response><person><firstname>Peter</firstname></person></response>'."\n";

        $context = array(
            'xml_version' => '1.1',
            'xml_encoding' => 'utf-8',
            'xml_standalone' => true,
        );

        $this->assertSame($expected, $this->encoder->encode($array, 'xml', $context));
    }

    public function testEncodeScalarRootAttributes()
    {
        $array = array(
          '#' => 'Paul',
          '@gender' => 'm'
        );

        $expected = '<?xml version="1.0"?>'."\n".
            '<response gender="m">Paul</response>'."\n";

        $this->assertEquals($expected, $this->encoder->encode($array, 'xml'));
    }

    public function testEncodeRootAttributes()
    {
        $array = array(
          'firstname' => 'Paul',
          '@gender' => 'm'
        );

        $expected = '<?xml version="1.0"?>'."\n".
            '<response gender="m"><firstname>Paul</firstname></response>'."\n";

        $this->assertEquals($expected, $this->encoder->encode($array, 'xml'));
    }

    public function testEncodeCdataWrapping()
    {
        $array = array(
          'firstname' => 'Paul <or Me>',
        );

        $expected = '<?xml version="1.0"?>'."\n".
            '<response><firstname><![CDATA[Paul <or Me>]]></firstname></response>'."\n";

        $this->assertEquals($expected, $this->encoder->encode($array, 'xml'));
    }

    public function testEncodeScalarWithAttribute()
    {
        $array = array(
            'person' => array('@gender' => 'M', '#' => 'Peter'),
        );

        $expected = '<?xml version="1.0"?>'."\n".
            '<response><person gender="M">Peter</person></response>'."\n";

        $this->assertEquals($expected, $this->encoder->encode($array, 'xml'));
    }

    public function testDecodeScalar()
    {
        $source = '<?xml version="1.0"?>'."\n".
            '<response>foo</response>'."\n";

        $this->assertEquals('foo', $this->encoder->decode($source, 'xml'));
    }

    public function testEncode()
    {
        $source = $this->getXmlSource();
        $obj = $this->getObject();

        $this->assertEquals($source, $this->encoder->encode($obj, 'xml'));
    }

    public function testEncodeSerializerXmlRootNodeNameOption()
    {
        $options = array('xml_root_node_name' => 'test');
        $this->encoder = new XmlEncoder();
        $serializer = new Serializer(array(), array('xml' => new XmlEncoder()));
        $this->encoder->setSerializer($serializer);

        $array = array(
            'person' => array('@gender' => 'M', '#' => 'Peter'),
        );

        $expected = '<?xml version="1.0"?>'."\n".
            '<test><person gender="M">Peter</person></test>'."\n";

        $this->assertEquals($expected, $serializer->serialize($array, 'xml', $options));
    }

    public function testDecode()
    {
        $source = $this->getXmlSource();
        $obj = $this->getObject();

        $this->assertEquals(get_object_vars($obj), $this->encoder->decode($source, 'xml'));
    }

    public function testDecodeScalarWithAttribute()
    {
        $source = '<?xml version="1.0"?>'."\n".
            '<response><person gender="M">Peter</person></response>'."\n";

        $expected = array(
            'person' => array('@gender' => 'M', '#' => 'Peter'),
        );

        $this->assertEquals($expected, $this->encoder->decode($source, 'xml'));
    }

    public function testDecodeScalarRootAttributes()
    {
        $source = '<?xml version="1.0"?>'."\n".
            '<person gender="M">Peter</person>'."\n";

        $expected = array(
            '#' => 'Peter',
            '@gender' => 'M'
        );

        $this->assertEquals($expected, $this->encoder->decode($source, 'xml'));
    }

    public function testDecodeRootAttributes()
    {
        $source = '<?xml version="1.0"?>'."\n".
            '<person gender="M"><firstname>Peter</firstname><lastname>Mac Calloway</lastname></person>'."\n";

        $expected = array(
            'firstname' => 'Peter',
            'lastname' => 'Mac Calloway',
            '@gender' => 'M'
        );

        $this->assertEquals($expected, $this->encoder->decode($source, 'xml'));
    }

    public function testDecodeArray()
    {
        $source = '<?xml version="1.0"?>'."\n".
            '<response>'.
            '<people>'.
            '<person><firstname>Benjamin</firstname><lastname>Alexandre</lastname></person>'.
            '<person><firstname>Damien</firstname><lastname>Clay</lastname></person>'.
            '</people>'.
            '</response>'."\n";

        $expected = array(
            'people' => array('person' => array(
                array('firstname' => 'Benjamin', 'lastname' => 'Alexandre'),
                array('firstname' => 'Damien', 'lastname' => 'Clay')
            ))
        );

        $this->assertEquals($expected, $this->encoder->decode($source, 'xml'));
    }

    public function testDecodeWithoutItemHash()
    {
        $obj = new ScalarDummy();
        $obj->xmlFoo = array(
            'foo-bar' => array(
                '@key' => "value",
                'item' => array("@key" => 'key', "key-val" => 'val')
            ),
            'Foo' => array(
                'Bar' => "Test",
                '@Type' => 'test'
            ),
            'föo_bär' => 'a',
            "Bar" => array(1,2,3),
            'a' => 'b',
        );
        $expected = array(
            'foo-bar' => array(
                '@key' => "value",
                'key' => array('@key' => 'key', "key-val" => 'val')
            ),
            'Foo' => array(
                'Bar' => "Test",
                '@Type' => 'test'
            ),
            'föo_bär' => 'a',
            "Bar" => array(1,2,3),
            'a' => 'b',
        );
        $xml = $this->encoder->encode($obj, 'xml');
        $this->assertEquals($expected, $this->encoder->decode($xml, 'xml'));
    }

    /**
     * @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException
     */
    public function testDecodeInvalidXml()
    {
        $this->encoder->decode('<?xml version="1.0"?><invalid><xml>', 'xml');
    }

    public function testPreventsComplexExternalEntities()
    {
        $oldCwd = getcwd();
        chdir(__DIR__);

        try {
            $this->encoder->decode('<?xml version="1.0"?><!DOCTYPE scan[<!ENTITY test SYSTEM "php://filter/read=convert.base64-encode/resource=XmlEncoderTest.php">]><scan>&test;</scan>', 'xml');
            chdir($oldCwd);

            $this->fail('No exception was thrown.');
        } catch (\Exception $e) {
            chdir($oldCwd);

            if (!$e instanceof UnexpectedValueException) {
                $this->fail('Expected UnexpectedValueException');
            }
        }
    }

    public function testDecodeEmptyXml()
    {
        $this->setExpectedException('Symfony\Component\Serializer\Exception\UnexpectedValueException', 'Invalid XML data, it can not be empty.');
        $this->encoder->decode(' ', 'xml');
    }

    protected function getXmlSource()
    {
        return '<?xml version="1.0"?>'."\n".
            '<response>'.
            '<foo>foo</foo>'.
            '<bar>a</bar><bar>b</bar>'.
            '<baz><key>val</key><key2>val</key2><item key="A B">bar</item>'.
            '<item><title>title1</title></item><item><title>title2</title></item>'.
            '<Barry><FooBar id="1"><Baz>Ed</Baz></FooBar></Barry></baz>'.
            '<qux>1</qux>'.
            '</response>'."\n";
    }

    protected function getObject()
    {
        $obj = new Dummy();
        $obj->foo = 'foo';
        $obj->bar = array('a', 'b');
        $obj->baz = array('key' => 'val', 'key2' => 'val', 'A B' => 'bar', 'item' => array(array('title' => 'title1'), array('title' => 'title2')), 'Barry' => array('FooBar' => array('Baz' => 'Ed', '@id' => 1)));
        $obj->qux = "1";

        return $obj;
    }
}
PK��ZF��		Ntest/Serializer/Symfony/Component/Serializer/Tests/Encoder/JsonEncoderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Tests\Encoder;

use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Normalizer\CustomNormalizer;

class JsonEncoderTest extends \PHPUnit_Framework_TestCase
{
    protected function setUp()
    {
        $this->encoder = new JsonEncoder();
        $this->serializer = new Serializer(array(new CustomNormalizer()), array('json' => new JsonEncoder()));
    }

    public function testEncodeScalar()
    {
        $obj = new \stdClass();
        $obj->foo = "foo";

        $expected = '{"foo":"foo"}';

        $this->assertEquals($expected, $this->encoder->encode($obj, 'json'));
    }

    public function testComplexObject()
    {
        $obj = $this->getObject();

        $expected = $this->getJsonSource();

        $this->assertEquals($expected, $this->encoder->encode($obj, 'json'));
    }

    public function testOptions()
    {
        $context = array('json_encode_options' => JSON_NUMERIC_CHECK);

        $arr = array();
        $arr['foo'] = "3";

        $expected = '{"foo":3}';

        $this->assertEquals($expected, $this->serializer->serialize($arr, 'json', $context));

        $arr = array();
        $arr['foo'] = "3";

        $expected = '{"foo":"3"}';

        $this->assertEquals($expected, $this->serializer->serialize($arr, 'json'), 'Context should not be persistent');
    }

    protected function getJsonSource()
    {
        return '{"foo":"foo","bar":["a","b"],"baz":{"key":"val","key2":"val","A B":"bar","item":[{"title":"title1"},{"title":"title2"}],"Barry":{"FooBar":{"Baz":"Ed","@id":1}}},"qux":"1"}';
    }

    protected function getObject()
    {
        $obj = new \stdClass();
        $obj->foo = 'foo';
        $obj->bar = array('a', 'b');
        $obj->baz = array('key' => 'val', 'key2' => 'val', 'A B' => 'bar', 'item' => array(array('title' => 'title1'), array('title' => 'title2')), 'Barry' => array('FooBar' => array('Baz' => 'Ed', '@id' => 1)));
        $obj->qux = "1";

        return $obj;
    }
}
PK��Z���99=test/Serializer/Symfony/Component/Serializer/phpunit.xml.distnu�[���<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony Serializer Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./vendor</directory>
                <directory>./Tests</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
PK��Z�Ǫ���9test/Locale/Symfony/Component/Locale/Tests/LocaleTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Locale\Tests;

use Symfony\Component\Intl\Intl;
use Symfony\Component\Intl\Util\IntlTestHelper;
use Symfony\Component\Locale\Locale;

/**
 * Test case for the {@link Locale} class.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class LocaleTest extends \PHPUnit_Framework_TestCase
{
    protected function setUp()
    {
        // Locale extends \Locale, so intl must be present
        IntlTestHelper::requireIntl($this);
    }

    public function testGetDisplayCountries()
    {
        $countries = Locale::getDisplayCountries('en');
        $this->assertEquals('Brazil', $countries['BR']);
    }

    public function testGetCountries()
    {
        $countries = Locale::getCountries();
        $this->assertTrue(in_array('BR', $countries));
    }

    public function testGetDisplayLanguages()
    {
        $languages = Locale::getDisplayLanguages('en');
        $this->assertEquals('Brazilian Portuguese', $languages['pt_BR']);
    }

    public function testGetLanguages()
    {
        $languages = Locale::getLanguages();
        $this->assertTrue(in_array('pt_BR', $languages));
    }

    public function testGetDisplayLocales()
    {
        $locales = Locale::getDisplayLocales('en');
        $this->assertEquals('Portuguese', $locales['pt']);
    }

    public function testGetLocales()
    {
        $locales = Locale::getLocales();
        $this->assertTrue(in_array('pt', $locales));
    }
}
PK��Z<��Btest/Locale/Symfony/Component/Locale/Tests/Stub/StubLocaleTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Locale\Tests\Stub;

use Symfony\Component\Intl\Util\IntlTestHelper;
use Symfony\Component\Locale\Stub\StubLocale;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class StubLocaleTest extends \PHPUnit_Framework_TestCase
{
    protected function setUp()
    {
        IntlTestHelper::requireIntl($this);

        parent::setUp();
    }

    public function testGetCurrenciesData()
    {
        $currencies = StubLocale::getCurrenciesData('en');
        $this->assertEquals('R$', $currencies['BRL']['symbol']);
        $this->assertEquals('Brazilian Real', $currencies['BRL']['name']);
        $this->assertEquals(2, $currencies['BRL']['fractionDigits']);
        $this->assertEquals(0, $currencies['BRL']['roundingIncrement']);
    }

    public function testGetDisplayCurrencies()
    {
        $currencies = StubLocale::getDisplayCurrencies('en');
        $this->assertEquals('Brazilian Real', $currencies['BRL']);

        // Checking that the cache is being used
        $currencies = StubLocale::getDisplayCurrencies('en');
        $this->assertEquals('Argentine Peso', $currencies['ARS']);
    }

    public function testGetCurrencies()
    {
        $currencies = StubLocale::getCurrencies();
        $this->assertTrue(in_array('BRL', $currencies));
    }
}
PK��Z+��hh5test/Locale/Symfony/Component/Locale/phpunit.xml.distnu�[���<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony Locale Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./Resources</directory>
                <directory>./Tests</directory>
                <directory>./vendor</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
PK��Z�;�Itest/Filesystem/Symfony/Component/Filesystem/Tests/FilesystemTestCase.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Filesystem\Tests;

class FilesystemTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * @var string $workspace
     */
    protected $workspace = null;

    protected static $symlinkOnWindows = null;

    public static function setUpBeforeClass()
    {
        if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
            static::$symlinkOnWindows = true;
            $originDir = tempnam(sys_get_temp_dir(), 'sl');
            $targetDir = tempnam(sys_get_temp_dir(), 'sl');
            if (true !== @symlink($originDir, $targetDir)) {
                $report = error_get_last();
                if (is_array($report) && false !== strpos($report['message'], 'error code(1314)')) {
                    static::$symlinkOnWindows = false;
                }
            }
        }
    }

    public function setUp()
    {
        $this->workspace = rtrim(sys_get_temp_dir(), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.time().rand(0, 1000);
        mkdir($this->workspace, 0777, true);
        $this->workspace = realpath($this->workspace);
    }

    public function tearDown()
    {
        $this->clean($this->workspace);
    }

    /**
     * @param string $file
     */
    protected function clean($file)
    {
        if (is_dir($file) && !is_link($file)) {
            $dir = new \FilesystemIterator($file);
            foreach ($dir as $childFile) {
                $this->clean($childFile);
            }

            rmdir($file);
        } else {
            unlink($file);
        }
    }

    /**
     * @param int $expectedFilePerms expected file permissions as three digits (i.e. 755)
     * @param string $filePath
     */
    protected function assertFilePermissions($expectedFilePerms, $filePath)
    {
        $actualFilePerms = (int) substr(sprintf('%o', fileperms($filePath)), -3);
        $this->assertEquals(
            $expectedFilePerms,
            $actualFilePerms,
            sprintf('File permissions for %s must be %s. Actual %s', $filePath, $expectedFilePerms, $actualFilePerms)
        );
    }

    protected function getFileOwner($filepath)
    {
        $this->markAsSkippedIfPosixIsMissing();

        $infos = stat($filepath);
        if ($datas = posix_getpwuid($infos['uid'])) {
            return $datas['name'];
        }
    }

    protected function getFileGroup($filepath)
    {
        $this->markAsSkippedIfPosixIsMissing();

        $infos = stat($filepath);
        if ($datas = posix_getgrgid($infos['gid'])) {
            return $datas['name'];
        }
    }

    protected function markAsSkippedIfSymlinkIsMissing()
    {
        if (!function_exists('symlink')) {
            $this->markTestSkipped('symlink is not supported');
        }

        if (defined('PHP_WINDOWS_VERSION_MAJOR') && false === static::$symlinkOnWindows) {
            $this->markTestSkipped('symlink requires "Create symbolic links" privilege on windows');
        }
    }

    protected function markAsSkippedIfChmodIsMissing()
    {
        if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
            $this->markTestSkipped('chmod is not supported on windows');
        }
    }

    protected function markAsSkippedIfPosixIsMissing()
    {
        if (defined('PHP_WINDOWS_VERSION_MAJOR') || !function_exists('posix_isatty')) {
            $this->markTestSkipped('Posix is not supported');
        }
    }
}
PK��Z'B 0�o�oEtest/Filesystem/Symfony/Component/Filesystem/Tests/FilesystemTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Filesystem\Tests;

use Symfony\Component\Filesystem\Filesystem;

/**
 * Test class for Filesystem.
 */
class FilesystemTest extends FilesystemTestCase
{
    /**
     * @var \Symfony\Component\Filesystem\Filesystem $filesystem
     */
    private $filesystem = null;

    public function setUp()
    {
        parent::setUp();
        $this->filesystem = new Filesystem();
    }

    public function testCopyCreatesNewFile()
    {
        $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
        $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';

        file_put_contents($sourceFilePath, 'SOURCE FILE');

        $this->filesystem->copy($sourceFilePath, $targetFilePath);

        $this->assertFileExists($targetFilePath);
        $this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
    }

    /**
     * @expectedException \Symfony\Component\Filesystem\Exception\IOException
     */
    public function testCopyFails()
    {
        $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
        $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';

        $this->filesystem->copy($sourceFilePath, $targetFilePath);
    }

    public function testCopyOverridesExistingFileIfModified()
    {
        $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
        $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';

        file_put_contents($sourceFilePath, 'SOURCE FILE');
        file_put_contents($targetFilePath, 'TARGET FILE');
        touch($targetFilePath, time() - 1000);

        $this->filesystem->copy($sourceFilePath, $targetFilePath);

        $this->assertFileExists($targetFilePath);
        $this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
    }

    public function testCopyDoesNotOverrideExistingFileByDefault()
    {
        $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
        $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';

        file_put_contents($sourceFilePath, 'SOURCE FILE');
        file_put_contents($targetFilePath, 'TARGET FILE');

        // make sure both files have the same modification time
        $modificationTime = time() - 1000;
        touch($sourceFilePath, $modificationTime);
        touch($targetFilePath, $modificationTime);

        $this->filesystem->copy($sourceFilePath, $targetFilePath);

        $this->assertFileExists($targetFilePath);
        $this->assertEquals('TARGET FILE', file_get_contents($targetFilePath));
    }

    public function testCopyOverridesExistingFileIfForced()
    {
        $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
        $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';

        file_put_contents($sourceFilePath, 'SOURCE FILE');
        file_put_contents($targetFilePath, 'TARGET FILE');

        // make sure both files have the same modification time
        $modificationTime = time() - 1000;
        touch($sourceFilePath, $modificationTime);
        touch($targetFilePath, $modificationTime);

        $this->filesystem->copy($sourceFilePath, $targetFilePath, true);

        $this->assertFileExists($targetFilePath);
        $this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
    }

    public function testCopyCreatesTargetDirectoryIfItDoesNotExist()
    {
        $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
        $targetFileDirectory = $this->workspace.DIRECTORY_SEPARATOR.'directory';
        $targetFilePath = $targetFileDirectory.DIRECTORY_SEPARATOR.'copy_target_file';

        file_put_contents($sourceFilePath, 'SOURCE FILE');

        $this->filesystem->copy($sourceFilePath, $targetFilePath);

        $this->assertTrue(is_dir($targetFileDirectory));
        $this->assertFileExists($targetFilePath);
        $this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
    }

    public function testCopyForOriginUrlsAndExistingLocalFileDefaultsToNotCopy()
    {
        $sourceFilePath = 'http://symfony.com/images/common/logo/logo_symfony_header.png';
        $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';

        file_put_contents($targetFilePath, 'TARGET FILE');

        $this->filesystem->copy($sourceFilePath, $targetFilePath, false);

        $this->assertFileExists($targetFilePath);
        $this->assertEquals(file_get_contents($sourceFilePath), file_get_contents($targetFilePath));
    }

    public function testMkdirCreatesDirectoriesRecursively()
    {
        $directory = $this->workspace
            .DIRECTORY_SEPARATOR.'directory'
            .DIRECTORY_SEPARATOR.'sub_directory';

        $this->filesystem->mkdir($directory);

        $this->assertTrue(is_dir($directory));
    }

    public function testMkdirCreatesDirectoriesFromArray()
    {
        $basePath = $this->workspace.DIRECTORY_SEPARATOR;
        $directories = array(
            $basePath.'1', $basePath.'2', $basePath.'3'
        );

        $this->filesystem->mkdir($directories);

        $this->assertTrue(is_dir($basePath.'1'));
        $this->assertTrue(is_dir($basePath.'2'));
        $this->assertTrue(is_dir($basePath.'3'));
    }

    public function testMkdirCreatesDirectoriesFromTraversableObject()
    {
        $basePath = $this->workspace.DIRECTORY_SEPARATOR;
        $directories = new \ArrayObject(array(
            $basePath.'1', $basePath.'2', $basePath.'3'
        ));

        $this->filesystem->mkdir($directories);

        $this->assertTrue(is_dir($basePath.'1'));
        $this->assertTrue(is_dir($basePath.'2'));
        $this->assertTrue(is_dir($basePath.'3'));
    }

    /**
     * @expectedException \Symfony\Component\Filesystem\Exception\IOException
     */
    public function testMkdirCreatesDirectoriesFails()
    {
        $basePath = $this->workspace.DIRECTORY_SEPARATOR;
        $dir = $basePath.'2';

        file_put_contents($dir, '');

        $this->filesystem->mkdir($dir);
    }

    public function testTouchCreatesEmptyFile()
    {
        $file = $this->workspace.DIRECTORY_SEPARATOR.'1';

        $this->filesystem->touch($file);

        $this->assertFileExists($file);
    }

    /**
     * @expectedException \Symfony\Component\Filesystem\Exception\IOException
     */
    public function testTouchFails()
    {
        $file = $this->workspace.DIRECTORY_SEPARATOR.'1'.DIRECTORY_SEPARATOR.'2';

        $this->filesystem->touch($file);
    }

    public function testTouchCreatesEmptyFilesFromArray()
    {
        $basePath = $this->workspace.DIRECTORY_SEPARATOR;
        $files = array(
            $basePath.'1', $basePath.'2', $basePath.'3'
        );

        $this->filesystem->touch($files);

        $this->assertFileExists($basePath.'1');
        $this->assertFileExists($basePath.'2');
        $this->assertFileExists($basePath.'3');
    }

    public function testTouchCreatesEmptyFilesFromTraversableObject()
    {
        $basePath = $this->workspace.DIRECTORY_SEPARATOR;
        $files = new \ArrayObject(array(
            $basePath.'1', $basePath.'2', $basePath.'3'
        ));

        $this->filesystem->touch($files);

        $this->assertFileExists($basePath.'1');
        $this->assertFileExists($basePath.'2');
        $this->assertFileExists($basePath.'3');
    }

    public function testRemoveCleansFilesAndDirectoriesIteratively()
    {
        $basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;

        mkdir($basePath);
        mkdir($basePath.'dir');
        touch($basePath.'file');

        $this->filesystem->remove($basePath);

        $this->assertTrue(!is_dir($basePath));
    }

    public function testRemoveCleansArrayOfFilesAndDirectories()
    {
        $basePath = $this->workspace.DIRECTORY_SEPARATOR;

        mkdir($basePath.'dir');
        touch($basePath.'file');

        $files = array(
            $basePath.'dir', $basePath.'file'
        );

        $this->filesystem->remove($files);

        $this->assertTrue(!is_dir($basePath.'dir'));
        $this->assertTrue(!is_file($basePath.'file'));
    }

    public function testRemoveCleansTraversableObjectOfFilesAndDirectories()
    {
        $basePath = $this->workspace.DIRECTORY_SEPARATOR;

        mkdir($basePath.'dir');
        touch($basePath.'file');

        $files = new \ArrayObject(array(
            $basePath.'dir', $basePath.'file'
        ));

        $this->filesystem->remove($files);

        $this->assertTrue(!is_dir($basePath.'dir'));
        $this->assertTrue(!is_file($basePath.'file'));
    }

    public function testRemoveIgnoresNonExistingFiles()
    {
        $basePath = $this->workspace.DIRECTORY_SEPARATOR;

        mkdir($basePath.'dir');

        $files = array(
            $basePath.'dir', $basePath.'file'
        );

        $this->filesystem->remove($files);

        $this->assertTrue(!is_dir($basePath.'dir'));
    }

    public function testRemoveCleansInvalidLinks()
    {
        $this->markAsSkippedIfSymlinkIsMissing();

        $basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;

        mkdir($basePath);
        mkdir($basePath.'dir');
        // create symlink to nonexistent file
        @symlink($basePath.'file', $basePath.'link');

        $this->filesystem->remove($basePath);

        $this->assertTrue(!is_dir($basePath));
    }

    public function testFilesExists()
    {
        $basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;

        mkdir($basePath);
        touch($basePath.'file1');
        mkdir($basePath.'folder');

        $this->assertTrue($this->filesystem->exists($basePath.'file1'));
        $this->assertTrue($this->filesystem->exists($basePath.'folder'));
    }

    public function testFilesExistsTraversableObjectOfFilesAndDirectories()
    {
        $basePath = $this->workspace.DIRECTORY_SEPARATOR;

        mkdir($basePath.'dir');
        touch($basePath.'file');

        $files = new \ArrayObject(array(
            $basePath.'dir', $basePath.'file'
        ));

        $this->assertTrue($this->filesystem->exists($files));
    }

    public function testFilesNotExistsTraversableObjectOfFilesAndDirectories()
    {
        $basePath = $this->workspace.DIRECTORY_SEPARATOR;

        mkdir($basePath.'dir');
        touch($basePath.'file');
        touch($basePath.'file2');

        $files = new \ArrayObject(array(
            $basePath.'dir', $basePath.'file', $basePath.'file2'
        ));

        unlink($basePath.'file');

        $this->assertFalse($this->filesystem->exists($files));
    }

    public function testInvalidFileNotExists()
    {
        $basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;

        $this->assertFalse($this->filesystem->exists($basePath.time()));
    }

    public function testChmodChangesFileMode()
    {
        $this->markAsSkippedIfChmodIsMissing();

        $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
        mkdir($dir);
        $file = $dir.DIRECTORY_SEPARATOR.'file';
        touch($file);

        $this->filesystem->chmod($file, 0400);
        $this->filesystem->chmod($dir, 0753);

        $this->assertFilePermissions(753, $dir);
        $this->assertFilePermissions(400, $file);
    }

    public function testChmodWrongMod()
    {
        $this->markAsSkippedIfChmodIsMissing();

        $dir = $this->workspace.DIRECTORY_SEPARATOR.'file';
        touch($dir);

        $this->filesystem->chmod($dir, 'Wrongmode');
    }

    public function testChmodRecursive()
    {
        $this->markAsSkippedIfChmodIsMissing();

        $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
        mkdir($dir);
        $file = $dir.DIRECTORY_SEPARATOR.'file';
        touch($file);

        $this->filesystem->chmod($file, 0400, 0000, true);
        $this->filesystem->chmod($dir, 0753, 0000, true);

        $this->assertFilePermissions(753, $dir);
        $this->assertFilePermissions(753, $file);
    }

    public function testChmodAppliesUmask()
    {
        $this->markAsSkippedIfChmodIsMissing();

        $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
        touch($file);

        $this->filesystem->chmod($file, 0770, 0022);
        $this->assertFilePermissions(750, $file);
    }

    public function testChmodChangesModeOfArrayOfFiles()
    {
        $this->markAsSkippedIfChmodIsMissing();

        $directory = $this->workspace.DIRECTORY_SEPARATOR.'directory';
        $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
        $files = array($directory, $file);

        mkdir($directory);
        touch($file);

        $this->filesystem->chmod($files, 0753);

        $this->assertFilePermissions(753, $file);
        $this->assertFilePermissions(753, $directory);
    }

    public function testChmodChangesModeOfTraversableFileObject()
    {
        $this->markAsSkippedIfChmodIsMissing();

        $directory = $this->workspace.DIRECTORY_SEPARATOR.'directory';
        $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
        $files = new \ArrayObject(array($directory, $file));

        mkdir($directory);
        touch($file);

        $this->filesystem->chmod($files, 0753);

        $this->assertFilePermissions(753, $file);
        $this->assertFilePermissions(753, $directory);
    }

    public function testChown()
    {
        $this->markAsSkippedIfPosixIsMissing();

        $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
        mkdir($dir);

        $this->filesystem->chown($dir, $this->getFileOwner($dir));
    }

    public function testChownRecursive()
    {
        $this->markAsSkippedIfPosixIsMissing();

        $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
        mkdir($dir);
        $file = $dir.DIRECTORY_SEPARATOR.'file';
        touch($file);

        $this->filesystem->chown($dir, $this->getFileOwner($dir), true);
    }

    public function testChownSymlink()
    {
        $this->markAsSkippedIfSymlinkIsMissing();

        $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
        $link = $this->workspace.DIRECTORY_SEPARATOR.'link';

        touch($file);

        $this->filesystem->symlink($file, $link);

        $this->filesystem->chown($link, $this->getFileOwner($link));
    }

    /**
     * @expectedException \Symfony\Component\Filesystem\Exception\IOException
     */
    public function testChownSymlinkFails()
    {
        $this->markAsSkippedIfSymlinkIsMissing();

        $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
        $link = $this->workspace.DIRECTORY_SEPARATOR.'link';

        touch($file);

        $this->filesystem->symlink($file, $link);

        $this->filesystem->chown($link, 'user'.time().mt_rand(1000, 9999));
    }

    /**
     * @expectedException \Symfony\Component\Filesystem\Exception\IOException
     */
    public function testChownFail()
    {
        $this->markAsSkippedIfPosixIsMissing();

        $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
        mkdir($dir);

        $this->filesystem->chown($dir, 'user'.time().mt_rand(1000, 9999));
    }

    public function testChgrp()
    {
        $this->markAsSkippedIfPosixIsMissing();

        $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
        mkdir($dir);

        $this->filesystem->chgrp($dir, $this->getFileGroup($dir));
    }

    public function testChgrpRecursive()
    {
        $this->markAsSkippedIfPosixIsMissing();

        $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
        mkdir($dir);
        $file = $dir.DIRECTORY_SEPARATOR.'file';
        touch($file);

        $this->filesystem->chgrp($dir, $this->getFileGroup($dir), true);
    }

    public function testChgrpSymlink()
    {
        $this->markAsSkippedIfSymlinkIsMissing();

        $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
        $link = $this->workspace.DIRECTORY_SEPARATOR.'link';

        touch($file);

        $this->filesystem->symlink($file, $link);

        $this->filesystem->chgrp($link, $this->getFileGroup($link));
    }

    /**
     * @expectedException \Symfony\Component\Filesystem\Exception\IOException
     */
    public function testChgrpSymlinkFails()
    {
        $this->markAsSkippedIfSymlinkIsMissing();

        $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
        $link = $this->workspace.DIRECTORY_SEPARATOR.'link';

        touch($file);

        $this->filesystem->symlink($file, $link);

        $this->filesystem->chgrp($link, 'user'.time().mt_rand(1000, 9999));
    }

    /**
     * @expectedException \Symfony\Component\Filesystem\Exception\IOException
     */
    public function testChgrpFail()
    {
        $this->markAsSkippedIfPosixIsMissing();

        $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
        mkdir($dir);

        $this->filesystem->chgrp($dir, 'user'.time().mt_rand(1000, 9999));
    }

    public function testRename()
    {
        $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
        $newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';
        touch($file);

        $this->filesystem->rename($file, $newPath);

        $this->assertFileNotExists($file);
        $this->assertFileExists($newPath);
    }

    /**
     * @expectedException \Symfony\Component\Filesystem\Exception\IOException
     */
    public function testRenameThrowsExceptionIfTargetAlreadyExists()
    {
        $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
        $newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';

        touch($file);
        touch($newPath);

        $this->filesystem->rename($file, $newPath);
    }

    public function testRenameOverwritesTheTargetIfItAlreadyExists()
    {
        $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
        $newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';

        touch($file);
        touch($newPath);

        $this->filesystem->rename($file, $newPath, true);

        $this->assertFileNotExists($file);
        $this->assertFileExists($newPath);
    }

    /**
     * @expectedException \Symfony\Component\Filesystem\Exception\IOException
     */
    public function testRenameThrowsExceptionOnError()
    {
        $file = $this->workspace.DIRECTORY_SEPARATOR.uniqid();
        $newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';

        $this->filesystem->rename($file, $newPath);
    }

    public function testSymlink()
    {
        $this->markAsSkippedIfSymlinkIsMissing();

        $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
        $link = $this->workspace.DIRECTORY_SEPARATOR.'link';

        touch($file);

        $this->filesystem->symlink($file, $link);

        $this->assertTrue(is_link($link));
        $this->assertEquals($file, readlink($link));
    }

    /**
     * @depends testSymlink
     */
    public function testRemoveSymlink()
    {
        $this->markAsSkippedIfSymlinkIsMissing();

        $link = $this->workspace.DIRECTORY_SEPARATOR.'link';

        $this->filesystem->remove($link);

        $this->assertTrue(!is_link($link));
    }

    public function testSymlinkIsOverwrittenIfPointsToDifferentTarget()
    {
        $this->markAsSkippedIfSymlinkIsMissing();

        $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
        $link = $this->workspace.DIRECTORY_SEPARATOR.'link';

        touch($file);
        symlink($this->workspace, $link);

        $this->filesystem->symlink($file, $link);

        $this->assertTrue(is_link($link));
        $this->assertEquals($file, readlink($link));
    }

    public function testSymlinkIsNotOverwrittenIfAlreadyCreated()
    {
        $this->markAsSkippedIfSymlinkIsMissing();

        $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
        $link = $this->workspace.DIRECTORY_SEPARATOR.'link';

        touch($file);
        symlink($file, $link);

        $this->filesystem->symlink($file, $link);

        $this->assertTrue(is_link($link));
        $this->assertEquals($file, readlink($link));
    }

    public function testSymlinkCreatesTargetDirectoryIfItDoesNotExist()
    {
        $this->markAsSkippedIfSymlinkIsMissing();

        $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
        $link1 = $this->workspace.DIRECTORY_SEPARATOR.'dir'.DIRECTORY_SEPARATOR.'link';
        $link2 = $this->workspace.DIRECTORY_SEPARATOR.'dir'.DIRECTORY_SEPARATOR.'subdir'.DIRECTORY_SEPARATOR.'link';

        touch($file);

        $this->filesystem->symlink($file, $link1);
        $this->filesystem->symlink($file, $link2);

        $this->assertTrue(is_link($link1));
        $this->assertEquals($file, readlink($link1));
        $this->assertTrue(is_link($link2));
        $this->assertEquals($file, readlink($link2));
    }

    /**
     * @dataProvider providePathsForMakePathRelative
     */
    public function testMakePathRelative($endPath, $startPath, $expectedPath)
    {
        $path = $this->filesystem->makePathRelative($endPath, $startPath);

        $this->assertEquals($expectedPath, $path);
    }

    /**
     * @return array
     */
    public function providePathsForMakePathRelative()
    {
        $paths = array(
            array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/src/Symfony/Component', '../'),
            array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/src/Symfony/Component/', '../'),
            array('/var/lib/symfony/src/Symfony', '/var/lib/symfony/src/Symfony/Component', '../'),
            array('/var/lib/symfony/src/Symfony', '/var/lib/symfony/src/Symfony/Component/', '../'),
            array('var/lib/symfony/', 'var/lib/symfony/src/Symfony/Component', '../../../'),
            array('/usr/lib/symfony/', '/var/lib/symfony/src/Symfony/Component', '../../../../../../usr/lib/symfony/'),
            array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/', 'src/Symfony/'),
            array('/aa/bb', '/aa/bb', './'),
            array('/aa/bb', '/aa/bb/', './'),
            array('/aa/bb/', '/aa/bb', './'),
            array('/aa/bb/', '/aa/bb/', './'),
            array('/aa/bb/cc', '/aa/bb/cc/dd', '../'),
            array('/aa/bb/cc', '/aa/bb/cc/dd/', '../'),
            array('/aa/bb/cc/', '/aa/bb/cc/dd', '../'),
            array('/aa/bb/cc/', '/aa/bb/cc/dd/', '../'),
            array('/aa/bb/cc', '/aa', 'bb/cc/'),
            array('/aa/bb/cc', '/aa/', 'bb/cc/'),
            array('/aa/bb/cc/', '/aa', 'bb/cc/'),
            array('/aa/bb/cc/', '/aa/', 'bb/cc/'),
            array('/a/aab/bb', '/a/aa', '../aab/bb/'),
            array('/a/aab/bb', '/a/aa/', '../aab/bb/'),
            array('/a/aab/bb/', '/a/aa', '../aab/bb/'),
            array('/a/aab/bb/', '/a/aa/', '../aab/bb/'),
        );

        if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
            $paths[] = array('c:\var\lib/symfony/src/Symfony/', 'c:/var/lib/symfony/', 'src/Symfony/');
        }

        return $paths;
    }

    public function testMirrorCopiesFilesAndDirectoriesRecursively()
    {
        $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;
        $directory = $sourcePath.'directory'.DIRECTORY_SEPARATOR;
        $file1 = $directory.'file1';
        $file2 = $sourcePath.'file2';

        mkdir($sourcePath);
        mkdir($directory);
        file_put_contents($file1, 'FILE1');
        file_put_contents($file2, 'FILE2');

        $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;

        $this->filesystem->mirror($sourcePath, $targetPath);

        $this->assertTrue(is_dir($targetPath));
        $this->assertTrue(is_dir($targetPath.'directory'));
        $this->assertFileEquals($file1, $targetPath.'directory'.DIRECTORY_SEPARATOR.'file1');
        $this->assertFileEquals($file2, $targetPath.'file2');

        $this->filesystem->remove($file1);

        $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => false));
        $this->assertTrue($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1'));

        $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => true));
        $this->assertFalse($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1'));

        file_put_contents($file1, 'FILE1');

        $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => true));
        $this->assertTrue($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1'));

        $this->filesystem->remove($directory);
        $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => true));
        $this->assertFalse($this->filesystem->exists($targetPath.'directory'));
        $this->assertFalse($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1'));
    }

    public function testMirrorCopiesLinks()
    {
        $this->markAsSkippedIfSymlinkIsMissing();

        $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;

        mkdir($sourcePath);
        file_put_contents($sourcePath.'file1', 'FILE1');
        symlink($sourcePath.'file1', $sourcePath.'link1');

        $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;

        $this->filesystem->mirror($sourcePath, $targetPath);

        $this->assertTrue(is_dir($targetPath));
        $this->assertFileEquals($sourcePath.'file1', $targetPath.DIRECTORY_SEPARATOR.'link1');
        $this->assertTrue(is_link($targetPath.DIRECTORY_SEPARATOR.'link1'));
    }

    public function testMirrorCopiesLinkedDirectoryContents()
    {
        $this->markAsSkippedIfSymlinkIsMissing();

        $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;

        mkdir($sourcePath.'nested/', 0777, true);
        file_put_contents($sourcePath.'/nested/file1.txt', 'FILE1');
        // Note: We symlink directory, not file
        symlink($sourcePath.'nested', $sourcePath.'link1');

        $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;

        $this->filesystem->mirror($sourcePath, $targetPath);

        $this->assertTrue(is_dir($targetPath));
        $this->assertFileEquals($sourcePath.'/nested/file1.txt', $targetPath.DIRECTORY_SEPARATOR.'link1/file1.txt');
        $this->assertTrue(is_link($targetPath.DIRECTORY_SEPARATOR.'link1'));
    }

    /**
     * @dataProvider providePathsForIsAbsolutePath
     */
    public function testIsAbsolutePath($path, $expectedResult)
    {
        $result = $this->filesystem->isAbsolutePath($path);

        $this->assertEquals($expectedResult, $result);
    }

    /**
     * @return array
     */
    public function providePathsForIsAbsolutePath()
    {
        return array(
            array('/var/lib', true),
            array('c:\\\\var\\lib', true),
            array('\\var\\lib', true),
            array('var/lib', false),
            array('../var/lib', false),
            array('', false),
            array(null, false)
        );
    }

    public function testDumpFile()
    {
        $filename = $this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'baz.txt';

        $this->filesystem->dumpFile($filename, 'bar', 0753);

        $this->assertFileExists($filename);
        $this->assertSame('bar', file_get_contents($filename));

        // skip mode check on Windows
        if (!defined('PHP_WINDOWS_VERSION_MAJOR')) {
            $this->assertFilePermissions(753, $filename);
        }
    }

    public function testDumpFileWithNullMode()
    {
        $filename = $this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'baz.txt';

        $this->filesystem->dumpFile($filename, 'bar', null);

        $this->assertFileExists($filename);
        $this->assertSame('bar', file_get_contents($filename));

        // skip mode check on Windows
        if (!defined('PHP_WINDOWS_VERSION_MAJOR')) {
            $this->assertFilePermissions(600, $filename);
        }
    }

    public function testDumpFileOverwritesAnExistingFile()
    {
        $filename = $this->workspace.DIRECTORY_SEPARATOR.'foo.txt';
        file_put_contents($filename, 'FOO BAR');

        $this->filesystem->dumpFile($filename, 'bar');

        $this->assertFileExists($filename);
        $this->assertSame('bar', file_get_contents($filename));
    }
}
PK��Z��í�Dtest/Filesystem/Symfony/Component/Filesystem/Tests/ExceptionTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Filesystem\Tests;

use Symfony\Component\Filesystem\Exception\IOException;
use Symfony\Component\Filesystem\Exception\FileNotFoundException;

/**
 * Test class for Filesystem.
 */
class ExceptionTest extends \PHPUnit_Framework_TestCase
{
    public function testGetPath()
    {
        $e = new IOException('', 0, null, '/foo');
        $this->assertEquals('/foo', $e->getPath(), 'The pass should be returned.');
    }

    public function testGeneratedMessage()
    {
        $e = new FileNotFoundException(null, 0, null, '/foo');
        $this->assertEquals('/foo', $e->getPath());
        $this->assertEquals('File "/foo" could not be found.', $e->getMessage(), 'A message should be generated.');
    }

    public function testGeneratedMessageWithoutPath()
    {
        $e = new FileNotFoundException();
        $this->assertEquals('File could not be found.', $e->getMessage(), 'A message should be generated.');
    }

    public function testCustomMessage()
    {
        $e = new FileNotFoundException('bar', 0, null, '/foo');
        $this->assertEquals('bar', $e->getMessage(), 'A custom message should be possible still.');
    }
}
PK��Z�Ejc		=test/Filesystem/Symfony/Component/Filesystem/phpunit.xml.distnu�[���<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony Filesystem Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./Tests</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
PK��Z�ag�@<@<Btest/Form/Symfony/Component/Form/Tests/AbstractTableLayoutTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests;

use Symfony\Component\Form\FormError;
use Symfony\Component\Security\Csrf\CsrfToken;

abstract class AbstractTableLayoutTest extends AbstractLayoutTest
{
    public function testRow()
    {
        $form = $this->factory->createNamed('name', 'text');
        $form->addError(new FormError('[trans]Error![/trans]'));
        $view = $form->createView();
        $html = $this->renderRow($view);

        $this->assertMatchesXpath($html,
'/tr
    [
        ./td
            [./label[@for="name"]]
        /following-sibling::td
            [
                ./ul
                    [./li[.="[trans]Error![/trans]"]]
                    [count(./li)=1]
                /following-sibling::input[@id="name"]
            ]
    ]
'
        );
    }

    public function testLabelIsNotRenderedWhenSetToFalse()
    {
        $form = $this->factory->createNamed('name', 'text', null, array(
            'label' => false
        ));
        $html = $this->renderRow($form->createView());

        $this->assertMatchesXpath($html,
'/tr
    [
        ./td
            [count(//label)=0]
        /following-sibling::td
            [./input[@id="name"]]
    ]
'
        );
    }

    public function testRepeatedRow()
    {
        $form = $this->factory->createNamed('name', 'repeated');
        $html = $this->renderRow($form->createView());

        $this->assertMatchesXpath($html,
'/tr
    [
        ./td
            [./label[@for="name_first"]]
        /following-sibling::td
            [./input[@id="name_first"]]
    ]
/following-sibling::tr
    [
        ./td
            [./label[@for="name_second"]]
        /following-sibling::td
            [./input[@id="name_second"]]
    ]
/following-sibling::tr[@style="display: none"]
    [./td[@colspan="2"]/input
        [@type="hidden"]
        [@id="name__token"]
    ]
    [count(../tr)=3]
'
        );
    }

    public function testRepeatedRowWithErrors()
    {
        $form = $this->factory->createNamed('name', 'repeated');
        $form->addError(new FormError('[trans]Error![/trans]'));
        $view = $form->createView();
        $html = $this->renderRow($view);

        // The errors of the form are not rendered by intention!
        // In practice, repeated fields cannot have errors as all errors
        // on them are mapped to the first child.
        // (see RepeatedTypeValidatorExtension)

        $this->assertMatchesXpath($html,
'/tr
    [
        ./td
            [./label[@for="name_first"]]
        /following-sibling::td
            [./input[@id="name_first"]]
    ]
/following-sibling::tr
    [
        ./td
            [./label[@for="name_second"]]
        /following-sibling::td
            [./input[@id="name_second"]]
    ]
/following-sibling::tr[@style="display: none"]
    [./td[@colspan="2"]/input
        [@type="hidden"]
        [@id="name__token"]
    ]
    [count(../tr)=3]
'
        );
    }

    public function testButtonRow()
    {
        $form = $this->factory->createNamed('name', 'button');
        $view = $form->createView();
        $html = $this->renderRow($view);

        $this->assertMatchesXpath($html,
'/tr
    [
        ./td
            [.=""]
        /following-sibling::td
            [./button[@type="button"][@name="name"]]
    ]
    [count(//label)=0]
'
        );
    }

    public function testRest()
    {
        $view = $this->factory->createNamedBuilder('name', 'form')
            ->add('field1', 'text')
            ->add('field2', 'repeated')
            ->add('field3', 'text')
            ->add('field4', 'text')
            ->getForm()
            ->createView();

        // Render field2 row -> does not implicitly call renderWidget because
        // it is a repeated field!
        $this->renderRow($view['field2']);

        // Render field3 widget
        $this->renderWidget($view['field3']);

        // Rest should only contain field1 and field4
        $html = $this->renderRest($view);

        $this->assertMatchesXpath($html,
'/tr
    [
        ./td
            [./label[@for="name_field1"]]
        /following-sibling::td
            [./input[@id="name_field1"]]
    ]
/following-sibling::tr
    [
        ./td
            [./label[@for="name_field4"]]
        /following-sibling::td
            [./input[@id="name_field4"]]
    ]
    [count(../tr)=3]
    [count(..//label)=2]
    [count(..//input)=3]
/following-sibling::tr[@style="display: none"]
    [./td[@colspan="2"]/input
        [@type="hidden"]
        [@id="name__token"]
    ]
'
        );
    }

    public function testCollection()
    {
        $form = $this->factory->createNamed('name', 'collection', array('a', 'b'), array(
            'type' => 'text',
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/table
    [
        ./tr[./td/input[@type="text"][@value="a"]]
        /following-sibling::tr[./td/input[@type="text"][@value="b"]]
        /following-sibling::tr[@style="display: none"][./td[@colspan="2"]/input[@type="hidden"][@id="name__token"]]
    ]
    [count(./tr[./td/input])=3]
'
        );
    }

    public function testEmptyCollection()
    {
        $form = $this->factory->createNamed('name', 'collection', array(), array(
            'type' => 'text',
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/table
    [./tr[@style="display: none"][./td[@colspan="2"]/input[@type="hidden"][@id="name__token"]]]
    [count(./tr[./td/input])=1]
'
        );
    }

    public function testForm()
    {
        $view = $this->factory->createNamedBuilder('name', 'form')
            ->setMethod('PUT')
            ->setAction('http://example.com')
            ->add('firstName', 'text')
            ->add('lastName', 'text')
            ->getForm()
            ->createView();

        $html = $this->renderForm($view, array(
            'id' => 'my&id',
            'attr' => array('class' => 'my&class'),
        ));

        $this->assertMatchesXpath($html,
'/form
    [
        ./input[@type="hidden"][@name="_method"][@value="PUT"]
        /following-sibling::table
            [
                ./tr
                    [
                        ./td
                            [./label[@for="name_firstName"]]
                        /following-sibling::td
                            [./input[@id="name_firstName"]]
                    ]
                /following-sibling::tr
                    [
                        ./td
                            [./label[@for="name_lastName"]]
                        /following-sibling::td
                            [./input[@id="name_lastName"]]
                    ]
                /following-sibling::tr[@style="display: none"]
                    [./td[@colspan="2"]/input
                        [@type="hidden"]
                        [@id="name__token"]
                    ]
            ]
            [count(.//input)=3]
            [@id="my&id"]
            [@class="my&class"]
    ]
    [@method="post"]
    [@action="http://example.com"]
    [@class="my&class"]
'
        );
    }

    public function testFormWidget()
    {
        $view = $this->factory->createNamedBuilder('name', 'form')
            ->add('firstName', 'text')
            ->add('lastName', 'text')
            ->getForm()
            ->createView();

        $this->assertWidgetMatchesXpath($view, array(),
'/table
    [
        ./tr
            [
                ./td
                    [./label[@for="name_firstName"]]
                /following-sibling::td
                    [./input[@id="name_firstName"]]
            ]
        /following-sibling::tr
            [
                ./td
                    [./label[@for="name_lastName"]]
                /following-sibling::td
                    [./input[@id="name_lastName"]]
            ]
        /following-sibling::tr[@style="display: none"]
            [./td[@colspan="2"]/input
                [@type="hidden"]
                [@id="name__token"]
            ]
    ]
    [count(.//input)=3]
'
        );
    }

    // https://github.com/symfony/symfony/issues/2308
    public function testNestedFormError()
    {
        $form = $this->factory->createNamedBuilder('name', 'form')
            ->add($this->factory
                ->createNamedBuilder('child', 'form', null, array('error_bubbling' => false))
                ->add('grandChild', 'form')
            )
            ->getForm();

        $form->get('child')->addError(new FormError('[trans]Error![/trans]'));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/table
    [
        ./tr/td/ul[./li[.="[trans]Error![/trans]"]]
        /following-sibling::table[@id="name_child"]
    ]
    [count(.//li[.="[trans]Error![/trans]"])=1]
'
        );
    }

    public function testCsrf()
    {
        $this->csrfTokenManager->expects($this->any())
            ->method('getToken')
            ->will($this->returnValue(new CsrfToken('token_id', 'foo&bar')));

        $form = $this->factory->createNamedBuilder('name', 'form')
            ->add($this->factory
                // No CSRF protection on nested forms
                ->createNamedBuilder('child', 'form')
                ->add($this->factory->createNamedBuilder('grandchild', 'text'))
            )
            ->getForm();

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/table
    [
        ./tr[@style="display: none"]
            [./td[@colspan="2"]/input
                [@type="hidden"]
                [@id="name__token"]
            ]
    ]
    [count(.//input[@type="hidden"])=1]
'
        );
    }

    public function testRepeated()
    {
        $form = $this->factory->createNamed('name', 'repeated', 'foobar', array(
            'type' => 'text',
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/table
    [
        ./tr
            [
                ./td
                    [./label[@for="name_first"]]
                /following-sibling::td
                    [./input[@type="text"][@id="name_first"]]
            ]
        /following-sibling::tr
            [
                ./td
                    [./label[@for="name_second"]]
                /following-sibling::td
                    [./input[@type="text"][@id="name_second"]]
            ]
        /following-sibling::tr[@style="display: none"]
            [./td[@colspan="2"]/input
                [@type="hidden"]
                [@id="name__token"]
            ]
    ]
    [count(.//input)=3]
'
        );
    }

    public function testRepeatedWithCustomOptions()
    {
        $form = $this->factory->createNamed('name', 'repeated', 'foobar', array(
            'type'           => 'password',
            'first_options'  => array('label' => 'Test', 'required' => false),
            'second_options' => array('label' => 'Test2')
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/table
    [
        ./tr
            [
                ./td
                    [./label[@for="name_first"][.="[trans]Test[/trans]"]]
                /following-sibling::td
                    [./input[@type="password"][@id="name_first"][@required="required"]]
            ]
        /following-sibling::tr
            [
                ./td
                    [./label[@for="name_second"][.="[trans]Test2[/trans]"]]
                /following-sibling::td
                    [./input[@type="password"][@id="name_second"][@required="required"]]
            ]
        /following-sibling::tr[@style="display: none"]
            [./td[@colspan="2"]/input
                [@type="hidden"]
                [@id="name__token"]
            ]
    ]
    [count(.//input)=3]
'
        );
    }

    /**
     * The block "_name_child_label" should be overridden in the theme of the
     * implemented driver.
     */
    public function testCollectionRowWithCustomBlock()
    {
        $collection = array('one', 'two', 'three');
        $form = $this->factory->createNamedBuilder('name', 'collection', $collection)
            ->getForm();

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/table
    [
        ./tr[./td/label[.="Custom label: [trans]0[/trans]"]]
        /following-sibling::tr[./td/label[.="Custom label: [trans]1[/trans]"]]
        /following-sibling::tr[./td/label[.="Custom label: [trans]2[/trans]"]]
    ]
'
        );
    }

    public function testFormEndWithRest()
    {
        $view = $this->factory->createNamedBuilder('name', 'form')
            ->add('field1', 'text')
            ->add('field2', 'text')
            ->getForm()
            ->createView();

        $this->renderWidget($view['field1']);

        // Rest should only contain field2
        $html = $this->renderEnd($view);

        // Insert the start tag, the end tag should be rendered by the helper
        // Unfortunately this is not valid HTML, because the surrounding table
        // tag is missing. If someone renders a form with table layout
        // manually, she should call form_rest() explicitly within the <table>
        // tag.
        $this->assertMatchesXpath('<form>' . $html,
'/form
    [
        ./tr
            [
                ./td
                    [./label[@for="name_field2"]]
                /following-sibling::td
                    [./input[@id="name_field2"]]
            ]
        /following-sibling::tr[@style="display: none"]
            [./td[@colspan="2"]/input
                [@type="hidden"]
                [@id="name__token"]
            ]
    ]
'
        );
    }

    public function testFormEndWithoutRest()
    {
        $view = $this->factory->createNamedBuilder('name', 'form')
            ->add('field1', 'text')
            ->add('field2', 'text')
            ->getForm()
            ->createView();

        $this->renderWidget($view['field1']);

        // Rest should only contain field2, but isn't rendered
        $html = $this->renderEnd($view, array('render_rest' => false));

        $this->assertEquals('</form>', $html);
    }

    public function testWidgetContainerAttributes()
    {
        $form = $this->factory->createNamed('form', 'form', null, array(
            'attr' => array('class' => 'foobar', 'data-foo' => 'bar'),
        ));

        $form->add('text', 'text');

        $html = $this->renderWidget($form->createView());

        // compare plain HTML to check the whitespace
        $this->assertContains('<table id="form" class="foobar" data-foo="bar">', $html);
    }

    public function testWidgetContainerAttributeNameRepeatedIfTrue()
    {
        $form = $this->factory->createNamed('form', 'form', null, array(
            'attr' => array('foo' => true),
        ));

        $html = $this->renderWidget($form->createView());

        // foo="foo"
        $this->assertContains('<table id="form" foo="foo">', $html);
    }

    public function testWidgetContainerAttributeHiddenIfFalse()
    {
        $form = $this->factory->createNamed('form', 'form', null, array(
            'attr' => array('foo' => false),
        ));

        $html = $this->renderWidget($form->createView());

        // no foo
        $this->assertContains('<table id="form">', $html);
    }
}
PK��Z���KKBtest/Form/Symfony/Component/Form/Tests/FormPerformanceTestCase.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests;

use Symfony\Component\Form\Test\FormPerformanceTestCase as BaseFormPerformanceTestCase;

/**
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use Symfony\Component\Form\Test\FormPerformanceTestCase instead.
 */
abstract class FormPerformanceTestCase extends BaseFormPerformanceTestCase
{
}
PK��Z@U���=test/Form/Symfony/Component/Form/Tests/AbstractLayoutTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests;

use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\Extension\Csrf\CsrfExtension;

abstract class AbstractLayoutTest extends \Symfony\Component\Form\Test\FormIntegrationTestCase
{
    protected $csrfTokenManager;

    protected function setUp()
    {
        if (!extension_loaded('intl')) {
            $this->markTestSkipped('The "intl" extension is not available');
        }

        \Locale::setDefault('en');

        $this->csrfTokenManager = $this->getMock('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface');

        parent::setUp();
    }

    protected function getExtensions()
    {
        return array(
            new CsrfExtension($this->csrfTokenManager),
        );
    }

    protected function tearDown()
    {
        $this->csrfTokenManager = null;

        parent::tearDown();
    }

    protected function assertXpathNodeValue(\DomElement $element, $expression, $nodeValue)
    {
        $xpath = new \DOMXPath($element->ownerDocument);
        $nodeList = $xpath->evaluate($expression);
        $this->assertEquals(1, $nodeList->length);
        $this->assertEquals($nodeValue, $nodeList->item(0)->nodeValue);
    }

    protected function assertMatchesXpath($html, $expression, $count = 1)
    {
        $dom = new \DomDocument('UTF-8');
        try {
            // Wrap in <root> node so we can load HTML with multiple tags at
            // the top level
            $dom->loadXml('<root>'.$html.'</root>');
        } catch (\Exception $e) {
            $this->fail(sprintf(
                "Failed loading HTML:\n\n%s\n\nError: %s",
                $html,
                $e->getMessage()
            ));
        }
        $xpath = new \DOMXPath($dom);
        $nodeList = $xpath->evaluate('/root'.$expression);

        if ($nodeList->length != $count) {
            $dom->formatOutput = true;
            $this->fail(sprintf(
                "Failed asserting that \n\n%s\n\nmatches exactly %s. Matches %s in \n\n%s",
                $expression,
                $count == 1 ? 'once' : $count.' times',
                $nodeList->length == 1 ? 'once' : $nodeList->length.' times',
                // strip away <root> and </root>
                substr($dom->saveHTML(), 6, -8)
            ));
        }
    }

    protected function assertWidgetMatchesXpath(FormView $view, array $vars, $xpath)
    {
        // include ampersands everywhere to validate escaping
        $html = $this->renderWidget($view, array_merge(array(
            'id' => 'my&id',
            'attr' => array('class' => 'my&class'),
        ), $vars));

        $xpath = trim($xpath).'
    [@id="my&id"]
    [@class="my&class"]';

        $this->assertMatchesXpath($html, $xpath);
    }

    abstract protected function renderForm(FormView $view, array $vars = array());

    abstract protected function renderEnctype(FormView $view);

    abstract protected function renderLabel(FormView $view, $label = null, array $vars = array());

    abstract protected function renderErrors(FormView $view);

    abstract protected function renderWidget(FormView $view, array $vars = array());

    abstract protected function renderRow(FormView $view, array $vars = array());

    abstract protected function renderRest(FormView $view, array $vars = array());

    abstract protected function renderStart(FormView $view, array $vars = array());

    abstract protected function renderEnd(FormView $view, array $vars = array());

    abstract protected function setTheme(FormView $view, array $themes);

    public function testEnctype()
    {
        $form = $this->factory->createNamedBuilder('name', 'form')
            ->add('file', 'file')
            ->getForm();

        $this->assertEquals('enctype="multipart/form-data"', $this->renderEnctype($form->createView()));
    }

    public function testNoEnctype()
    {
        $form = $this->factory->createNamedBuilder('name', 'form')
            ->add('text', 'text')
            ->getForm();

        $this->assertEquals('', $this->renderEnctype($form->createView()));
    }

    public function testLabel()
    {
        $form = $this->factory->createNamed('name', 'text');
        $view = $form->createView();
        $this->renderWidget($view, array('label' => 'foo'));
        $html = $this->renderLabel($view);

        $this->assertMatchesXpath($html,
'/label
    [@for="name"]
    [.="[trans]Name[/trans]"]
'
        );
    }

    public function testLabelOnForm()
    {
        $form = $this->factory->createNamed('name', 'date');
        $view = $form->createView();
        $this->renderWidget($view, array('label' => 'foo'));
        $html = $this->renderLabel($view);

        $this->assertMatchesXpath($html,
'/label
    [@class="required"]
    [.="[trans]Name[/trans]"]
'
        );
    }

    public function testLabelWithCustomTextPassedAsOption()
    {
        $form = $this->factory->createNamed('name', 'text', null, array(
            'label' => 'Custom label',
        ));
        $html = $this->renderLabel($form->createView());

        $this->assertMatchesXpath($html,
'/label
    [@for="name"]
    [.="[trans]Custom label[/trans]"]
'
        );
    }

    public function testLabelWithCustomTextPassedDirectly()
    {
        $form = $this->factory->createNamed('name', 'text');
        $html = $this->renderLabel($form->createView(), 'Custom label');

        $this->assertMatchesXpath($html,
'/label
    [@for="name"]
    [.="[trans]Custom label[/trans]"]
'
        );
    }

    public function testLabelWithCustomTextPassedAsOptionAndDirectly()
    {
        $form = $this->factory->createNamed('name', 'text', null, array(
            'label' => 'Custom label',
        ));
        $html = $this->renderLabel($form->createView(), 'Overridden label');

        $this->assertMatchesXpath($html,
'/label
    [@for="name"]
    [.="[trans]Overridden label[/trans]"]
'
        );
    }

    public function testLabelDoesNotRenderFieldAttributes()
    {
        $form = $this->factory->createNamed('name', 'text');
        $html = $this->renderLabel($form->createView(), null, array(
            'attr' => array(
                'class' => 'my&class'
            ),
        ));

        $this->assertMatchesXpath($html,
'/label
    [@for="name"]
    [@class="required"]
'
        );
    }

    public function testLabelWithCustomAttributesPassedDirectly()
    {
        $form = $this->factory->createNamed('name', 'text');
        $html = $this->renderLabel($form->createView(), null, array(
            'label_attr' => array(
                'class' => 'my&class'
            ),
        ));

        $this->assertMatchesXpath($html,
'/label
    [@for="name"]
    [@class="my&class required"]
'
        );
    }

    public function testLabelWithCustomTextAndCustomAttributesPassedDirectly()
    {
        $form = $this->factory->createNamed('name', 'text');
        $html = $this->renderLabel($form->createView(), 'Custom label', array(
            'label_attr' => array(
                'class' => 'my&class'
            ),
        ));

        $this->assertMatchesXpath($html,
'/label
    [@for="name"]
    [@class="my&class required"]
    [.="[trans]Custom label[/trans]"]
'
        );
    }

    // https://github.com/symfony/symfony/issues/5029
    public function testLabelWithCustomTextAsOptionAndCustomAttributesPassedDirectly()
    {
        $form = $this->factory->createNamed('name', 'text', null, array(
            'label' => 'Custom label',
        ));
        $html = $this->renderLabel($form->createView(), null, array(
            'label_attr' => array(
                'class' => 'my&class'
            ),
        ));

        $this->assertMatchesXpath($html,
            '/label
    [@for="name"]
    [@class="my&class required"]
    [.="[trans]Custom label[/trans]"]
'
        );
    }

    public function testErrors()
    {
        $form = $this->factory->createNamed('name', 'text');
        $form->addError(new FormError('[trans]Error 1[/trans]'));
        $form->addError(new FormError('[trans]Error 2[/trans]'));
        $view = $form->createView();
        $html = $this->renderErrors($view);

        $this->assertMatchesXpath($html,
'/ul
    [
        ./li[.="[trans]Error 1[/trans]"]
        /following-sibling::li[.="[trans]Error 2[/trans]"]
    ]
    [count(./li)=2]
'
        );
    }

    public function testOverrideWidgetBlock()
    {
        // see custom_widgets.html.twig
        $form = $this->factory->createNamed('text_id', 'text');
        $html = $this->renderWidget($form->createView());

        $this->assertMatchesXpath($html,
'/div
    [
        ./input
        [@type="text"]
        [@id="text_id"]
    ]
    [@id="container"]
'
        );
    }

    public function testCheckedCheckbox()
    {
        $form = $this->factory->createNamed('name', 'checkbox', true);

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/input
    [@type="checkbox"]
    [@name="name"]
    [@checked="checked"]
    [@value="1"]
'
        );
    }

    public function testUncheckedCheckbox()
    {
        $form = $this->factory->createNamed('name', 'checkbox', false);

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/input
    [@type="checkbox"]
    [@name="name"]
    [not(@checked)]
'
        );
    }

    public function testCheckboxWithValue()
    {
        $form = $this->factory->createNamed('name', 'checkbox', false, array(
            'value' => 'foo&bar',
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/input
    [@type="checkbox"]
    [@name="name"]
    [@value="foo&bar"]
'
        );
    }

    public function testSingleChoice()
    {
        $form = $this->factory->createNamed('name', 'choice', '&a', array(
            'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'),
            'multiple' => false,
            'expanded' => false,
        ));

        // If the field is collapsed, has no "multiple" attribute, is required but
        // has *no* empty value, the "required" must not be added, otherwise
        // the resulting HTML is invalid.
        // https://github.com/symfony/symfony/issues/8942

        // HTML 5 spec
        // http://www.w3.org/html/wg/drafts/html/master/forms.html#placeholder-label-option

        // "If a select element has a required attribute specified, does not
        //  have a multiple attribute specified, and has a display size of 1,
        //  then the select element must have a placeholder label option."

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/select
    [@name="name"]
    [not(@required)]
    [
        ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
        /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
    ]
    [count(./option)=2]
'
        );
    }

    public function testSingleChoiceWithPreferred()
    {
        $form = $this->factory->createNamed('name', 'choice', '&a', array(
            'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'),
            'preferred_choices' => array('&b'),
            'multiple' => false,
            'expanded' => false,
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array('separator' => '-- sep --'),
'/select
    [@name="name"]
    [not(@required)]
    [
        ./option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
        /following-sibling::option[@disabled="disabled"][not(@selected)][.="-- sep --"]
        /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
    ]
    [count(./option)=3]
'
        );
    }

    public function testSingleChoiceWithPreferredAndNoSeparator()
    {
        $form = $this->factory->createNamed('name', 'choice', '&a', array(
            'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'),
            'preferred_choices' => array('&b'),
            'multiple' => false,
            'expanded' => false,
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array('separator' => null),
'/select
    [@name="name"]
    [not(@required)]
    [
        ./option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
        /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
    ]
    [count(./option)=2]
'
        );
    }

    public function testSingleChoiceWithPreferredAndBlankSeparator()
    {
        $form = $this->factory->createNamed('name', 'choice', '&a', array(
            'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'),
            'preferred_choices' => array('&b'),
            'multiple' => false,
            'expanded' => false,
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array('separator' => ''),
'/select
    [@name="name"]
    [not(@required)]
    [
        ./option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
        /following-sibling::option[@disabled="disabled"][not(@selected)][.=""]
        /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
    ]
    [count(./option)=3]
'
        );
    }

    public function testChoiceWithOnlyPreferred()
    {
        $form = $this->factory->createNamed('name', 'choice', '&a', array(
            'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'),
            'preferred_choices' => array('&a', '&b'),
            'multiple' => false,
            'expanded' => false,
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/select
    [count(./option)=2]
'
        );
    }

    public function testSingleChoiceNonRequired()
    {
        $form = $this->factory->createNamed('name', 'choice', '&a', array(
            'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'),
            'required' => false,
            'multiple' => false,
            'expanded' => false,
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/select
    [@name="name"]
    [not(@required)]
    [
        ./option[@value=""][.="[trans][/trans]"]
        /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
        /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
    ]
    [count(./option)=3]
'
        );
    }

    public function testSingleChoiceNonRequiredNoneSelected()
    {
        $form = $this->factory->createNamed('name', 'choice', null, array(
            'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'),
            'required' => false,
            'multiple' => false,
            'expanded' => false,
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/select
    [@name="name"]
    [not(@required)]
    [
        ./option[@value=""][.="[trans][/trans]"]
        /following-sibling::option[@value="&a"][not(@selected)][.="[trans]Choice&A[/trans]"]
        /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
    ]
    [count(./option)=3]
'
        );
    }

    public function testSingleChoiceWithNonRequiredEmptyValue()
    {
        $form = $this->factory->createNamed('name', 'choice', '&a', array(
            'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'),
            'multiple' => false,
            'expanded' => false,
            'required' => false,
            'empty_value' => 'Select&Anything&Not&Me',
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/select
    [@name="name"]
    [not(@required)]
    [
        ./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Select&Anything&Not&Me[/trans]"]
        /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
        /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
    ]
    [count(./option)=3]
'
        );
    }

    public function testSingleChoiceRequiredWithEmptyValue()
    {
        $form = $this->factory->createNamed('name', 'choice', '&a', array(
            'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'),
            'required' => true,
            'multiple' => false,
            'expanded' => false,
            'empty_value' => 'Test&Me'
        ));

        // The "disabled" attribute was removed again due to a bug in the
        // BlackBerry 10 browser.
        // See https://github.com/symfony/symfony/pull/7678
        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/select
    [@name="name"]
    [@required="required"]
    [
        ./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Test&Me[/trans]"]
        /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
        /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
    ]
    [count(./option)=3]
'
        );
    }

    public function testSingleChoiceRequiredWithEmptyValueViaView()
    {
        $form = $this->factory->createNamed('name', 'choice', '&a', array(
            'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'),
            'required' => true,
            'multiple' => false,
            'expanded' => false,
        ));

        // The "disabled" attribute was removed again due to a bug in the
        // BlackBerry 10 browser.
        // See https://github.com/symfony/symfony/pull/7678
        $this->assertWidgetMatchesXpath($form->createView(), array('empty_value' => ''),
'/select
    [@name="name"]
    [@required="required"]
    [
        ./option[@value=""][not(@selected)][not(@disabled)][.="[trans][/trans]"]
        /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
        /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
    ]
    [count(./option)=3]
'
        );
    }

    public function testSingleChoiceGrouped()
    {
        $form = $this->factory->createNamed('name', 'choice', '&a', array(
            'choices' => array(
                'Group&1' => array('&a' => 'Choice&A', '&b' => 'Choice&B'),
                'Group&2' => array('&c' => 'Choice&C'),
            ),
            'multiple' => false,
            'expanded' => false,
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/select
    [@name="name"]
    [./optgroup[@label="[trans]Group&1[/trans]"]
        [
            ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
            /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
        ]
        [count(./option)=2]
    ]
    [./optgroup[@label="[trans]Group&2[/trans]"]
        [./option[@value="&c"][not(@selected)][.="[trans]Choice&C[/trans]"]]
        [count(./option)=1]
    ]
    [count(./optgroup)=2]
'
        );
    }

    public function testMultipleChoice()
    {
        $form = $this->factory->createNamed('name', 'choice', array('&a'), array(
            'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'),
            'required' => true,
            'multiple' => true,
            'expanded' => false,
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/select
    [@name="name[]"]
    [@required="required"]
    [@multiple="multiple"]
    [
        ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
        /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
    ]
    [count(./option)=2]
'
        );
    }

    public function testMultipleChoiceSkipsEmptyValue()
    {
        $form = $this->factory->createNamed('name', 'choice', array('&a'), array(
            'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'),
            'multiple' => true,
            'expanded' => false,
            'empty_value' => 'Test&Me'
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/select
    [@name="name[]"]
    [@multiple="multiple"]
    [
        ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
        /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
    ]
    [count(./option)=2]
'
        );
    }

    public function testMultipleChoiceNonRequired()
    {
        $form = $this->factory->createNamed('name', 'choice', array('&a'), array(
            'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'),
            'required' => false,
            'multiple' => true,
            'expanded' => false,
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/select
    [@name="name[]"]
    [@multiple="multiple"]
    [
        ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
        /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
    ]
    [count(./option)=2]
'
        );
    }

    public function testSingleChoiceExpanded()
    {
        $form = $this->factory->createNamed('name', 'choice', '&a', array(
            'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'),
            'multiple' => false,
            'expanded' => true,
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
    [
        ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked]
        /following-sibling::label[@for="name_0"][.="[trans]Choice&A[/trans]"]
        /following-sibling::input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)]
        /following-sibling::label[@for="name_1"][.="[trans]Choice&B[/trans]"]
        /following-sibling::input[@type="hidden"][@id="name__token"]
    ]
    [count(./input)=3]
'
        );
    }

    public function testSingleChoiceExpandedWithEmptyValue()
    {
        $form = $this->factory->createNamed('name', 'choice', '&a', array(
            'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'),
            'multiple' => false,
            'expanded' => true,
            'empty_value' => 'Test&Me'
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
    [
        ./input[@type="radio"][@name="name"][@id="name_placeholder"][not(@checked)]
        /following-sibling::label[@for="name_placeholder"][.="[trans]Test&Me[/trans]"]
        /following-sibling::input[@type="radio"][@name="name"][@id="name_0"][@checked]
        /following-sibling::label[@for="name_0"][.="[trans]Choice&A[/trans]"]
        /following-sibling::input[@type="radio"][@name="name"][@id="name_1"][not(@checked)]
        /following-sibling::label[@for="name_1"][.="[trans]Choice&B[/trans]"]
        /following-sibling::input[@type="hidden"][@id="name__token"]
    ]
    [count(./input)=4]
'
        );
    }

    public function testSingleChoiceExpandedWithBooleanValue()
    {
        $form = $this->factory->createNamed('name', 'choice', true, array(
            'choices' => array('1' => 'Choice&A', '0' => 'Choice&B'),
            'multiple' => false,
            'expanded' => true,
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
    [
        ./input[@type="radio"][@name="name"][@id="name_0"][@checked]
        /following-sibling::label[@for="name_0"][.="[trans]Choice&A[/trans]"]
        /following-sibling::input[@type="radio"][@name="name"][@id="name_1"][not(@checked)]
        /following-sibling::label[@for="name_1"][.="[trans]Choice&B[/trans]"]
        /following-sibling::input[@type="hidden"][@id="name__token"]
    ]
    [count(./input)=3]
'
        );
    }

    public function testMultipleChoiceExpanded()
    {
        $form = $this->factory->createNamed('name', 'choice', array('&a', '&c'), array(
            'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B', '&c' => 'Choice&C'),
            'multiple' => true,
            'expanded' => true,
            'required' => true,
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
    [
        ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@checked][not(@required)]
        /following-sibling::label[@for="name_0"][.="[trans]Choice&A[/trans]"]
        /following-sibling::input[@type="checkbox"][@name="name[]"][@id="name_1"][not(@checked)][not(@required)]
        /following-sibling::label[@for="name_1"][.="[trans]Choice&B[/trans]"]
        /following-sibling::input[@type="checkbox"][@name="name[]"][@id="name_2"][@checked][not(@required)]
        /following-sibling::label[@for="name_2"][.="[trans]Choice&C[/trans]"]
        /following-sibling::input[@type="hidden"][@id="name__token"]
    ]
    [count(./input)=4]
'
        );
    }

    public function testCountry()
    {
        $form = $this->factory->createNamed('name', 'country', 'AT');

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/select
    [@name="name"]
    [./option[@value="AT"][@selected="selected"][.="[trans]Austria[/trans]"]]
    [count(./option)>200]
'
        );
    }

    public function testCountryWithEmptyValue()
    {
        $form = $this->factory->createNamed('name', 'country', 'AT', array(
            'empty_value' => 'Select&Country',
            'required' => false,
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/select
    [@name="name"]
    [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Select&Country[/trans]"]]
    [./option[@value="AT"][@selected="selected"][.="[trans]Austria[/trans]"]]
    [count(./option)>201]
'
        );
    }

    public function testDateTime()
    {
        $form = $this->factory->createNamed('name', 'datetime', '2011-02-03 04:05:06', array(
            'input' => 'string',
            'with_seconds' => false,
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
    [
        ./div
            [@id="name_date"]
            [
                ./select
                    [@id="name_date_month"]
                    [./option[@value="2"][@selected="selected"]]
                /following-sibling::select
                    [@id="name_date_day"]
                    [./option[@value="3"][@selected="selected"]]
                /following-sibling::select
                    [@id="name_date_year"]
                    [./option[@value="2011"][@selected="selected"]]
            ]
        /following-sibling::div
            [@id="name_time"]
            [
                ./select
                    [@id="name_time_hour"]
                    [./option[@value="4"][@selected="selected"]]
                /following-sibling::select
                    [@id="name_time_minute"]
                    [./option[@value="5"][@selected="selected"]]
            ]
    ]
    [count(.//select)=5]
'
        );
    }

    public function testDateTimeWithEmptyValueGlobal()
    {
        $form = $this->factory->createNamed('name', 'datetime', null, array(
            'input' => 'string',
            'empty_value' => 'Change&Me',
            'required' => false,
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
    [
        ./div
            [@id="name_date"]
            [
                ./select
                    [@id="name_date_month"]
                    [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]]
                /following-sibling::select
                    [@id="name_date_day"]
                    [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]]
                /following-sibling::select
                    [@id="name_date_year"]
                    [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]]
            ]
        /following-sibling::div
            [@id="name_time"]
            [
                ./select
                    [@id="name_time_hour"]
                    [./option[@value=""][.="[trans]Change&Me[/trans]"]]
                /following-sibling::select
                    [@id="name_time_minute"]
                    [./option[@value=""][.="[trans]Change&Me[/trans]"]]
            ]
    ]
    [count(.//select)=5]
'
        );
    }

    public function testDateTimeWithHourAndMinute()
    {
        $data = array('year' => '2011', 'month' => '2', 'day' => '3', 'hour' => '4', 'minute' => '5');

        $form = $this->factory->createNamed('name', 'datetime', $data, array(
            'input' => 'array',
            'required' => false,
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
    [
        ./div
            [@id="name_date"]
            [
                ./select
                    [@id="name_date_month"]
                    [./option[@value="2"][@selected="selected"]]
                /following-sibling::select
                    [@id="name_date_day"]
                    [./option[@value="3"][@selected="selected"]]
                /following-sibling::select
                    [@id="name_date_year"]
                    [./option[@value="2011"][@selected="selected"]]
            ]
        /following-sibling::div
            [@id="name_time"]
            [
                ./select
                    [@id="name_time_hour"]
                    [./option[@value="4"][@selected="selected"]]
                /following-sibling::select
                    [@id="name_time_minute"]
                    [./option[@value="5"][@selected="selected"]]
            ]
    ]
    [count(.//select)=5]
'
        );
    }

    public function testDateTimeWithSeconds()
    {
        $form = $this->factory->createNamed('name', 'datetime', '2011-02-03 04:05:06', array(
            'input' => 'string',
            'with_seconds' => true,
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
    [
        ./div
            [@id="name_date"]
            [
                ./select
                    [@id="name_date_month"]
                    [./option[@value="2"][@selected="selected"]]
                /following-sibling::select
                    [@id="name_date_day"]
                    [./option[@value="3"][@selected="selected"]]
                /following-sibling::select
                    [@id="name_date_year"]
                    [./option[@value="2011"][@selected="selected"]]
            ]
        /following-sibling::div
            [@id="name_time"]
            [
                ./select
                    [@id="name_time_hour"]
                    [./option[@value="4"][@selected="selected"]]
                /following-sibling::select
                    [@id="name_time_minute"]
                    [./option[@value="5"][@selected="selected"]]
                /following-sibling::select
                    [@id="name_time_second"]
                    [./option[@value="6"][@selected="selected"]]
            ]
    ]
    [count(.//select)=6]
'
        );
    }

    public function testDateTimeSingleText()
    {
        $form = $this->factory->createNamed('name', 'datetime', '2011-02-03 04:05:06', array(
            'input' => 'string',
            'date_widget' => 'single_text',
            'time_widget' => 'single_text',
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
    [
        ./input
            [@type="date"]
            [@id="name_date"]
            [@name="name[date]"]
            [@value="2011-02-03"]
        /following-sibling::input
            [@type="time"]
            [@id="name_time"]
            [@name="name[time]"]
            [@value="04:05"]
    ]
'
        );
    }

    public function testDateTimeWithWidgetSingleText()
    {
        $form = $this->factory->createNamed('name', 'datetime', '2011-02-03 04:05:06', array(
            'input' => 'string',
            'widget' => 'single_text',
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/input
    [@type="datetime"]
    [@name="name"]
    [@value="2011-02-03T04:05:06Z"]
'
        );
    }

    public function testDateTimeWithWidgetSingleTextIgnoreDateAndTimeWidgets()
    {
        $form = $this->factory->createNamed('name', 'datetime', '2011-02-03 04:05:06', array(
            'input' => 'string',
            'date_widget' => 'choice',
            'time_widget' => 'choice',
            'widget' => 'single_text',
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/input
    [@type="datetime"]
    [@name="name"]
    [@value="2011-02-03T04:05:06Z"]
'
        );
    }

    public function testDateChoice()
    {
        $form = $this->factory->createNamed('name', 'date', '2011-02-03', array(
            'input' => 'string',
            'widget' => 'choice',
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
    [
        ./select
            [@id="name_month"]
            [./option[@value="2"][@selected="selected"]]
        /following-sibling::select
            [@id="name_day"]
            [./option[@value="3"][@selected="selected"]]
        /following-sibling::select
            [@id="name_year"]
            [./option[@value="2011"][@selected="selected"]]
    ]
    [count(./select)=3]
'
        );
    }

    public function testDateChoiceWithEmptyValueGlobal()
    {
        $form = $this->factory->createNamed('name', 'date', null, array(
            'input' => 'string',
            'widget' => 'choice',
            'empty_value' => 'Change&Me',
            'required' => false,
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
    [
        ./select
            [@id="name_month"]
            [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]]
        /following-sibling::select
            [@id="name_day"]
            [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]]
        /following-sibling::select
            [@id="name_year"]
            [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]]
    ]
    [count(./select)=3]
'
        );
    }

    public function testDateChoiceWithEmptyValueOnYear()
    {
        $form = $this->factory->createNamed('name', 'date', null, array(
            'input' => 'string',
            'widget' => 'choice',
            'required' => false,
            'empty_value' => array('year' => 'Change&Me'),
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
    [
        ./select
            [@id="name_month"]
            [./option[@value="1"]]
        /following-sibling::select
            [@id="name_day"]
            [./option[@value="1"]]
        /following-sibling::select
            [@id="name_year"]
            [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]]
    ]
    [count(./select)=3]
'
        );
    }

    public function testDateText()
    {
        $form = $this->factory->createNamed('name', 'date', '2011-02-03', array(
            'input' => 'string',
            'widget' => 'text',
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
    [
        ./input
            [@id="name_month"]
            [@type="text"]
            [@value="2"]
        /following-sibling::input
            [@id="name_day"]
            [@type="text"]
            [@value="3"]
        /following-sibling::input
            [@id="name_year"]
            [@type="text"]
            [@value="2011"]
    ]
    [count(./input)=3]
'
        );
    }

    public function testDateSingleText()
    {
        $form = $this->factory->createNamed('name', 'date', '2011-02-03', array(
            'input' => 'string',
            'widget' => 'single_text',
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/input
    [@type="date"]
    [@name="name"]
    [@value="2011-02-03"]
'
        );
    }

    public function testDateErrorBubbling()
    {
        $form = $this->factory->createNamedBuilder('form', 'form')
            ->add('date', 'date')
            ->getForm();
        $form->get('date')->addError(new FormError('[trans]Error![/trans]'));
        $view = $form->createView();

        $this->assertEmpty($this->renderErrors($view));
        $this->assertNotEmpty($this->renderErrors($view['date']));
    }

    public function testBirthDay()
    {
        $form = $this->factory->createNamed('name', 'birthday', '2000-02-03', array(
            'input' => 'string',
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
    [
        ./select
            [@id="name_month"]
            [./option[@value="2"][@selected="selected"]]
        /following-sibling::select
            [@id="name_day"]
            [./option[@value="3"][@selected="selected"]]
        /following-sibling::select
            [@id="name_year"]
            [./option[@value="2000"][@selected="selected"]]
    ]
    [count(./select)=3]
'
        );
    }

    public function testBirthDayWithEmptyValue()
    {
        $form = $this->factory->createNamed('name', 'birthday', '1950-01-01', array(
            'input' => 'string',
            'empty_value' => '',
            'required' => false,
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
    [
        ./select
            [@id="name_month"]
            [./option[@value=""][not(@selected)][not(@disabled)][.="[trans][/trans]"]]
            [./option[@value="1"][@selected="selected"]]
        /following-sibling::select
            [@id="name_day"]
            [./option[@value=""][not(@selected)][not(@disabled)][.="[trans][/trans]"]]
            [./option[@value="1"][@selected="selected"]]
        /following-sibling::select
            [@id="name_year"]
            [./option[@value=""][not(@selected)][not(@disabled)][.="[trans][/trans]"]]
            [./option[@value="1950"][@selected="selected"]]
    ]
    [count(./select)=3]
'
        );
    }

    public function testEmail()
    {
        $form = $this->factory->createNamed('name', 'email', 'foo&bar');

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/input
    [@type="email"]
    [@name="name"]
    [@value="foo&bar"]
    [not(@maxlength)]
'
        );
    }

    public function testEmailWithMaxLength()
    {
        $form = $this->factory->createNamed('name', 'email', 'foo&bar', array(
            'max_length' => 123,
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/input
    [@type="email"]
    [@name="name"]
    [@value="foo&bar"]
    [@maxlength="123"]
'
        );
    }

    public function testFile()
    {
        $form = $this->factory->createNamed('name', 'file');

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/input
    [@type="file"]
'
        );
    }

    public function testHidden()
    {
        $form = $this->factory->createNamed('name', 'hidden', 'foo&bar');

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/input
    [@type="hidden"]
    [@name="name"]
    [@value="foo&bar"]
'
        );
    }

    public function testReadOnly()
    {
        $form = $this->factory->createNamed('name', 'text', null, array(
            'read_only' => true,
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/input
    [@type="text"]
    [@name="name"]
    [@readonly="readonly"]
'
        );
    }

    public function testDisabled()
    {
        $form = $this->factory->createNamed('name', 'text', null, array(
            'disabled' => true,
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/input
    [@type="text"]
    [@name="name"]
    [@disabled="disabled"]
'
        );
    }

    public function testInteger()
    {
        $form = $this->factory->createNamed('name', 'integer', 123);

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/input
    [@type="number"]
    [@name="name"]
    [@value="123"]
'
        );
    }

    public function testLanguage()
    {
        $form = $this->factory->createNamed('name', 'language', 'de');

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/select
    [@name="name"]
    [./option[@value="de"][@selected="selected"][.="[trans]German[/trans]"]]
    [count(./option)>200]
'
        );
    }

    public function testLocale()
    {
        $form = $this->factory->createNamed('name', 'locale', 'de_AT');

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/select
    [@name="name"]
    [./option[@value="de_AT"][@selected="selected"][.="[trans]German (Austria)[/trans]"]]
    [count(./option)>200]
'
        );
    }

    public function testMoney()
    {
        $form = $this->factory->createNamed('name', 'money', 1234.56, array(
            'currency' => 'EUR',
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/input
    [@type="text"]
    [@name="name"]
    [@value="1234.56"]
    [contains(.., "€")]
'
        );
    }

    public function testNumber()
    {
        $form = $this->factory->createNamed('name', 'number', 1234.56);

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/input
    [@type="text"]
    [@name="name"]
    [@value="1234.56"]
'
        );
    }

    public function testPassword()
    {
        $form = $this->factory->createNamed('name', 'password', 'foo&bar');

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/input
    [@type="password"]
    [@name="name"]
'
        );
    }

    public function testPasswordSubmittedWithNotAlwaysEmpty()
    {
        $form = $this->factory->createNamed('name', 'password', null, array(
            'always_empty' => false,
        ));
        $form->submit('foo&bar');

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/input
    [@type="password"]
    [@name="name"]
    [@value="foo&bar"]
'
        );
    }

    public function testPasswordWithMaxLength()
    {
        $form = $this->factory->createNamed('name', 'password', 'foo&bar', array(
            'max_length' => 123,
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/input
    [@type="password"]
    [@name="name"]
    [@maxlength="123"]
'
        );
    }

    public function testPercent()
    {
        $form = $this->factory->createNamed('name', 'percent', 0.1);

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/input
    [@type="text"]
    [@name="name"]
    [@value="10"]
    [contains(.., "%")]
'
        );
    }

    public function testCheckedRadio()
    {
        $form = $this->factory->createNamed('name', 'radio', true);

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/input
    [@type="radio"]
    [@name="name"]
    [@checked="checked"]
    [@value="1"]
'
        );
    }

    public function testUncheckedRadio()
    {
        $form = $this->factory->createNamed('name', 'radio', false);

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/input
    [@type="radio"]
    [@name="name"]
    [not(@checked)]
'
        );
    }

    public function testRadioWithValue()
    {
        $form = $this->factory->createNamed('name', 'radio', false, array(
            'value' => 'foo&bar',
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/input
    [@type="radio"]
    [@name="name"]
    [@value="foo&bar"]
'
        );
    }

    public function testTextarea()
    {
        $form = $this->factory->createNamed('name', 'textarea', 'foo&bar', array(
            'pattern' => 'foo',
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/textarea
    [@name="name"]
    [not(@pattern)]
    [.="foo&bar"]
'
        );
    }

    public function testText()
    {
        $form = $this->factory->createNamed('name', 'text', 'foo&bar');

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/input
    [@type="text"]
    [@name="name"]
    [@value="foo&bar"]
    [not(@maxlength)]
'
        );
    }

    public function testTextWithMaxLength()
    {
        $form = $this->factory->createNamed('name', 'text', 'foo&bar', array(
            'max_length' => 123,
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/input
    [@type="text"]
    [@name="name"]
    [@value="foo&bar"]
    [@maxlength="123"]
'
        );
    }

    public function testSearch()
    {
        $form = $this->factory->createNamed('name', 'search', 'foo&bar');

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/input
    [@type="search"]
    [@name="name"]
    [@value="foo&bar"]
    [not(@maxlength)]
'
        );
    }

    public function testTime()
    {
        $form = $this->factory->createNamed('name', 'time', '04:05:06', array(
            'input' => 'string',
            'with_seconds' => false,
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
    [
        ./select
            [@id="name_hour"]
            [not(@size)]
            [./option[@value="4"][@selected="selected"]]
        /following-sibling::select
            [@id="name_minute"]
            [not(@size)]
            [./option[@value="5"][@selected="selected"]]
    ]
    [count(./select)=2]
'
        );
    }

    public function testTimeWithSeconds()
    {
        $form = $this->factory->createNamed('name', 'time', '04:05:06', array(
            'input' => 'string',
            'with_seconds' => true,
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
    [
        ./select
            [@id="name_hour"]
            [not(@size)]
            [./option[@value="4"][@selected="selected"]]
            [count(./option)>23]
        /following-sibling::select
            [@id="name_minute"]
            [not(@size)]
            [./option[@value="5"][@selected="selected"]]
            [count(./option)>59]
        /following-sibling::select
            [@id="name_second"]
            [not(@size)]
            [./option[@value="6"][@selected="selected"]]
            [count(./option)>59]
    ]
    [count(./select)=3]
'
        );
    }

    public function testTimeText()
    {
        $form = $this->factory->createNamed('name', 'time', '04:05:06', array(
            'input' => 'string',
            'widget' => 'text',
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
    [
        ./input
            [@type="text"]
            [@id="name_hour"]
            [@name="name[hour]"]
            [@value="04"]
            [@size="1"]
            [@required="required"]
        /following-sibling::input
            [@type="text"]
            [@id="name_minute"]
            [@name="name[minute]"]
            [@value="05"]
            [@size="1"]
            [@required="required"]
    ]
    [count(./input)=2]
'
        );
    }

    public function testTimeSingleText()
    {
        $form = $this->factory->createNamed('name', 'time', '04:05:06', array(
            'input' => 'string',
            'widget' => 'single_text',
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/input
    [@type="time"]
    [@name="name"]
    [@value="04:05"]
    [not(@size)]
'
        );
    }

    public function testTimeWithEmptyValueGlobal()
    {
        $form = $this->factory->createNamed('name', 'time', null, array(
            'input' => 'string',
            'empty_value' => 'Change&Me',
            'required' => false,
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
    [
        ./select
            [@id="name_hour"]
            [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]]
            [count(./option)>24]
        /following-sibling::select
            [@id="name_minute"]
            [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]]
            [count(./option)>60]
    ]
    [count(./select)=2]
'
        );
    }

    public function testTimeWithEmptyValueOnYear()
    {
        $form = $this->factory->createNamed('name', 'time', null, array(
            'input' => 'string',
            'required' => false,
            'empty_value' => array('hour' => 'Change&Me'),
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
    [
        ./select
            [@id="name_hour"]
            [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]]
            [count(./option)>24]
        /following-sibling::select
            [@id="name_minute"]
            [./option[@value="1"]]
            [count(./option)>59]
    ]
    [count(./select)=2]
'
        );
    }

    public function testTimeErrorBubbling()
    {
        $form = $this->factory->createNamedBuilder('form', 'form')
            ->add('time', 'time')
            ->getForm();
        $form->get('time')->addError(new FormError('[trans]Error![/trans]'));
        $view = $form->createView();

        $this->assertEmpty($this->renderErrors($view));
        $this->assertNotEmpty($this->renderErrors($view['time']));
    }

    public function testTimezone()
    {
        $form = $this->factory->createNamed('name', 'timezone', 'Europe/Vienna');

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/select
    [@name="name"]
    [not(@required)]
    [./optgroup
        [@label="[trans]Europe[/trans]"]
        [./option[@value="Europe/Vienna"][@selected="selected"][.="[trans]Vienna[/trans]"]]
    ]
    [count(./optgroup)>10]
    [count(.//option)>200]
'
        );
    }

    public function testTimezoneWithEmptyValue()
    {
        $form = $this->factory->createNamed('name', 'timezone', null, array(
            'empty_value' => 'Select&Timezone',
            'required' => false,
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/select
    [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Select&Timezone[/trans]"]]
    [count(./optgroup)>10]
    [count(.//option)>201]
'
        );
    }

    public function testUrl()
    {
        $url = 'http://www.google.com?foo1=bar1&foo2=bar2';
        $form = $this->factory->createNamed('name', 'url', $url);

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/input
    [@type="url"]
    [@name="name"]
    [@value="http://www.google.com?foo1=bar1&foo2=bar2"]
'
        );
    }

    public function testCollectionPrototype()
    {
        $form = $this->factory->createNamedBuilder('name', 'form', array('items' => array('one', 'two', 'three')))
            ->add('items', 'collection', array('allow_add' => true))
            ->getForm()
            ->createView();

        $html = $this->renderWidget($form);

        $this->assertMatchesXpath($html,
            '//div[@id="name_items"][@data-prototype]
            |
            //table[@id="name_items"][@data-prototype]'
        );
    }

    public function testEmptyRootFormName()
    {
        $form = $this->factory->createNamedBuilder('', 'form')
            ->add('child', 'text')
            ->getForm();

        $this->assertMatchesXpath($this->renderWidget($form->createView()),
            '//input[@type="hidden"][@id="_token"][@name="_token"]
            |
             //input[@type="text"][@id="child"][@name="child"]'
        , 2);
    }

    public function testButton()
    {
        $form = $this->factory->createNamed('name', 'button');

        $this->assertWidgetMatchesXpath($form->createView(), array(),
            '/button[@type="button"][@name="name"][.="[trans]Name[/trans]"]'
        );
    }

    public function testButtonLabelIsEmpty()
    {
        $form = $this->factory->createNamed('name', 'button');

        $this->assertSame('', $this->renderLabel($form->createView()));
    }

    public function testSubmit()
    {
        $form = $this->factory->createNamed('name', 'submit');

        $this->assertWidgetMatchesXpath($form->createView(), array(),
            '/button[@type="submit"][@name="name"]'
        );
    }

    public function testReset()
    {
        $form = $this->factory->createNamed('name', 'reset');

        $this->assertWidgetMatchesXpath($form->createView(), array(),
            '/button[@type="reset"][@name="name"]'
        );
    }

    public function testStartTag()
    {
        $form = $this->factory->create('form', null, array(
            'method' => 'get',
            'action' => 'http://example.com/directory'
        ));

        $html = $this->renderStart($form->createView());

        $this->assertSame('<form name="form" method="get" action="http://example.com/directory">', $html);
    }

    public function testStartTagForPutRequest()
    {
        $form = $this->factory->create('form', null, array(
            'method' => 'put',
            'action' => 'http://example.com/directory'
        ));

        $html = $this->renderStart($form->createView());

        $this->assertMatchesXpath($html . '</form>',
'/form
    [./input[@type="hidden"][@name="_method"][@value="PUT"]]
    [@method="post"]
    [@action="http://example.com/directory"]'
        );
    }

    public function testStartTagWithOverriddenVars()
    {
        $form = $this->factory->create('form', null, array(
            'method' => 'put',
            'action' => 'http://example.com/directory',
        ));

        $html = $this->renderStart($form->createView(), array(
            'method' => 'post',
            'action' => 'http://foo.com/directory'
        ));

        $this->assertSame('<form name="form" method="post" action="http://foo.com/directory">', $html);
    }

    public function testStartTagForMultipartForm()
    {
        $form = $this->factory->createBuilder('form', null, array(
                'method' => 'get',
                'action' => 'http://example.com/directory'
            ))
            ->add('file', 'file')
            ->getForm();

        $html = $this->renderStart($form->createView());

        $this->assertSame('<form name="form" method="get" action="http://example.com/directory" enctype="multipart/form-data">', $html);
    }

    public function testStartTagWithExtraAttributes()
    {
        $form = $this->factory->create('form', null, array(
            'method' => 'get',
            'action' => 'http://example.com/directory'
        ));

        $html = $this->renderStart($form->createView(), array(
            'attr' => array('class' => 'foobar'),
        ));

        $this->assertSame('<form name="form" method="get" action="http://example.com/directory" class="foobar">', $html);
    }

    public function testWidgetAttributes()
    {
        $form = $this->factory->createNamed('text', 'text', 'value', array(
            'required' => true,
            'disabled' => true,
            'read_only' => true,
            'max_length' => 10,
            'pattern' => '\d+',
            'attr' => array('class' => 'foobar', 'data-foo' => 'bar'),
        ));

        $html = $this->renderWidget($form->createView());

        // compare plain HTML to check the whitespace
        $this->assertSame('<input type="text" id="text" name="text" readonly="readonly" disabled="disabled" required="required" maxlength="10" pattern="\d+" class="foobar" data-foo="bar" value="value" />', $html);
    }

    public function testWidgetAttributeNameRepeatedIfTrue()
    {
        $form = $this->factory->createNamed('text', 'text', 'value', array(
            'attr' => array('foo' => true),
        ));

        $html = $this->renderWidget($form->createView());

        // foo="foo"
        $this->assertSame('<input type="text" id="text" name="text" required="required" foo="foo" value="value" />', $html);
    }

    public function testWidgetAttributeHiddenIfFalse()
    {
        $form = $this->factory->createNamed('text', 'text', 'value', array(
            'attr' => array('foo' => false),
        ));

        $html = $this->renderWidget($form->createView());

        // no foo
        $this->assertSame('<input type="text" id="text" name="text" required="required" value="value" />', $html);
    }

    public function testButtonAttributes()
    {
        $form = $this->factory->createNamed('button', 'button', null, array(
            'disabled' => true,
            'attr' => array('class' => 'foobar', 'data-foo' => 'bar'),
        ));

        $html = $this->renderWidget($form->createView());

        // compare plain HTML to check the whitespace
        $this->assertSame('<button type="button" id="button" name="button" disabled="disabled" class="foobar" data-foo="bar">[trans]Button[/trans]</button>', $html);
    }

    public function testButtonAttributeNameRepeatedIfTrue()
    {
        $form = $this->factory->createNamed('button', 'button', null, array(
            'attr' => array('foo' => true),
        ));

        $html = $this->renderWidget($form->createView());

        // foo="foo"
        $this->assertSame('<button type="button" id="button" name="button" foo="foo">[trans]Button[/trans]</button>', $html);
    }

    public function testButtonAttributeHiddenIfFalse()
    {
        $form = $this->factory->createNamed('button', 'button', null, array(
            'attr' => array('foo' => false),
        ));

        $html = $this->renderWidget($form->createView());

        // no foo
        $this->assertSame('<button type="button" id="button" name="button">[trans]Button[/trans]</button>', $html);
    }
}
PK��Z����:test/Form/Symfony/Component/Form/Tests/Guess/GuessTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Guess;

use Symfony\Component\Form\Guess\Guess;

class TestGuess extends Guess {}

class GuessTest extends \PHPUnit_Framework_TestCase
{
    public function testGetBestGuessReturnsGuessWithHighestConfidence()
    {
        $guess1 = new TestGuess(Guess::MEDIUM_CONFIDENCE);
        $guess2 = new TestGuess(Guess::LOW_CONFIDENCE);
        $guess3 = new TestGuess(Guess::HIGH_CONFIDENCE);

        $this->assertSame($guess3, Guess::getBestGuess(array($guess1, $guess2, $guess3)));
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testGuessExpectsValidConfidence()
    {
        new TestGuess(5);
    }
}
PK��Z�uEtest/Form/Symfony/Component/Form/Tests/Fixtures/CustomArrayObject.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Fixtures;

/**
 * This class is a hand written simplified version of PHP native `ArrayObject`
 * class, to show that it behaves differently than the PHP native implementation.
 */
class CustomArrayObject implements \ArrayAccess, \IteratorAggregate, \Countable, \Serializable
{
    private $array;

    public function __construct(array $array = null)
    {
        $this->array = $array ?: array();
    }

    public function offsetExists($offset)
    {
        return array_key_exists($offset, $this->array);
    }

    public function offsetGet($offset)
    {
        return $this->array[$offset];
    }

    public function offsetSet($offset, $value)
    {
        if (null === $offset) {
            $this->array[] = $value;
        } else {
            $this->array[$offset] = $value;
        }
    }

    public function offsetUnset($offset)
    {
        unset($this->array[$offset]);
    }

    public function getIterator()
    {
        return new \ArrayIterator($this->array);
    }

    public function count()
    {
        return count($this->array);
    }

    public function serialize()
    {
        return serialize($this->array);
    }

    public function unserialize($serialized)
    {
        $this->array = (array) unserialize((string) $serialized);
    }
}
PK��Z�x���:test/Form/Symfony/Component/Form/Tests/Fixtures/Author.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Fixtures;

class Author
{
    public $firstName;
    private $lastName;
    private $australian;
    public $child;
    private $readPermissions;

    private $privateProperty;

    public function setLastName($lastName)
    {
        $this->lastName = $lastName;
    }

    public function getLastName()
    {
        return $this->lastName;
    }

    private function getPrivateGetter()
    {
        return 'foobar';
    }

    public function setAustralian($australian)
    {
        $this->australian = $australian;
    }

    public function isAustralian()
    {
        return $this->australian;
    }

    public function setReadPermissions($bool)
    {
        $this->readPermissions = $bool;
    }

    public function hasReadPermissions()
    {
        return $this->readPermissions;
    }

    private function isPrivateIsser()
    {
        return true;
    }

    public function getPrivateSetter()
    {
    }

    private function setPrivateSetter($data)
    {
    }
}
PK��Z3test/Form/Symfony/Component/Form/Tests/Fixtures/foonu�[���PK��Z[��َ�Gtest/Form/Symfony/Component/Form/Tests/Fixtures/FooTypeBazExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Fixtures;

use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\FormBuilderInterface;

class FooTypeBazExtension extends AbstractTypeExtension
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->setAttribute('baz', 'x');
    }

    public function getExtendedType()
    {
        return 'foo';
    }
}
PK��Z���*��;test/Form/Symfony/Component/Form/Tests/Fixtures/FooType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Fixtures;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class FooType extends AbstractType
{
    public function getName()
    {
        return 'foo';
    }

    public function getParent()
    {
        return null;
    }
}
PK��Z:�.z��Ftest/Form/Symfony/Component/Form/Tests/Fixtures/AlternatingRowType.phpnu�[���<?php

namespace Symfony\Component\Form\Tests\Fixtures;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormBuilderInterface;

class AlternatingRowType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $formFactory = $builder->getFormFactory();

        $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($formFactory) {
            $form = $event->getForm();
            $type = $form->getName() % 2 === 0 ? 'text' : 'textarea';
            $form->add('title', $type);
        });
    }

    public function getName()
    {
        return 'alternating_row';
    }
}
PK��Z֫�v��>test/Form/Symfony/Component/Form/Tests/Fixtures/AuthorType.phpnu�[���<?php

namespace Symfony\Component\Form\Tests\Fixtures;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class AuthorType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('firstName')
            ->add('lastName')
        ;
    }

    public function getName()
    {
        return 'author';
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author',
        ));
    }
}
PK��Z#�o>test/Form/Symfony/Component/Form/Tests/Fixtures/FooSubType.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Fixtures;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class FooSubType extends AbstractType
{
    public function getName()
    {
        return 'foo_sub_type';
    }

    public function getParent()
    {
        return 'foo';
    }
}
PK��Z��8���Atest/Form/Symfony/Component/Form/Tests/Fixtures/TestExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Fixtures;

use Symfony\Component\Form\FormTypeInterface;
use Symfony\Component\Form\FormTypeExtensionInterface;
use Symfony\Component\Form\FormTypeGuesserInterface;
use Symfony\Component\Form\FormExtensionInterface;

class TestExtension implements FormExtensionInterface
{
    private $types = array();

    private $extensions = array();

    private $guesser;

    public function __construct(FormTypeGuesserInterface $guesser)
    {
        $this->guesser = $guesser;
    }

    public function addType(FormTypeInterface $type)
    {
        $this->types[$type->getName()] = $type;
    }

    public function getType($name)
    {
        return isset($this->types[$name]) ? $this->types[$name] : null;
    }

    public function hasType($name)
    {
        return isset($this->types[$name]);
    }

    public function addTypeExtension(FormTypeExtensionInterface $extension)
    {
        $type = $extension->getExtendedType();

        if (!isset($this->extensions[$type])) {
            $this->extensions[$type] = array();
        }

        $this->extensions[$type][] = $extension;
    }

    public function getTypeExtensions($name)
    {
        return isset($this->extensions[$name]) ? $this->extensions[$name] : array();
    }

    public function hasTypeExtensions($name)
    {
        return isset($this->extensions[$name]);
    }

    public function getTypeGuesser()
    {
        return $this->guesser;
    }
}
PK��Z��x�

Gtest/Form/Symfony/Component/Form/Tests/Fixtures/FooTypeBarExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Fixtures;

use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\FormBuilderInterface;

class FooTypeBarExtension extends AbstractTypeExtension
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->setAttribute('bar', 'x');
    }

    public function getAllowedOptionValues()
    {
        return array(
            'a_or_b' => array('c'),
        );
    }

    public function getExtendedType()
    {
        return 'foo';
    }
}
PK��Zm^�2++Ptest/Form/Symfony/Component/Form/Tests/Fixtures/FooSubTypeWithParentInstance.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Fixtures;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class FooSubTypeWithParentInstance extends AbstractType
{
    public function getName()
    {
        return 'foo_sub_type_parent_instance';
    }

    public function getParent()
    {
        return new FooType();
    }
}
PK��Z��!u��Gtest/Form/Symfony/Component/Form/Tests/Fixtures/FixedFilterListener.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Fixtures;

use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class FixedFilterListener implements EventSubscriberInterface
{
    private $mapping;

    public function __construct(array $mapping)
    {
        $this->mapping = array_merge(array(
            'preSubmit' => array(),
            'onSubmit' => array(),
            'preSetData' => array(),
        ), $mapping);
    }

    public function preSubmit(FormEvent $event)
    {
        $data = $event->getData();

        if (isset($this->mapping['preSubmit'][$data])) {
            $event->setData($this->mapping['preSubmit'][$data]);
        }
    }

    public function onSubmit(FormEvent $event)
    {
        $data = $event->getData();

        if (isset($this->mapping['onSubmit'][$data])) {
            $event->setData($this->mapping['onSubmit'][$data]);
        }
    }

    public function preSetData(FormEvent $event)
    {
        $data = $event->getData();

        if (isset($this->mapping['preSetData'][$data])) {
            $event->setData($this->mapping['preSetData'][$data]);
        }
    }

    public static function getSubscribedEvents()
    {
        return array(
            FormEvents::PRE_SUBMIT => 'preSubmit',
            FormEvents::SUBMIT => 'onSubmit',
            FormEvents::PRE_SET_DATA => 'preSetData',
        );
    }
}
PK��Z��UUHtest/Form/Symfony/Component/Form/Tests/Fixtures/FixedDataTransformer.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Fixtures;

use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\RuntimeException;

class FixedDataTransformer implements DataTransformerInterface
{
    private $mapping;

    public function __construct(array $mapping)
    {
        $this->mapping = $mapping;
    }

    public function transform($value)
    {
        if (!array_key_exists($value, $this->mapping)) {
            throw new RuntimeException(sprintf('No mapping for value "%s"', $value));
        }

        return $this->mapping[$value];
    }

    public function reverseTransform($value)
    {
        $result = array_search($value, $this->mapping, true);

        if ($result === false) {
            throw new RuntimeException(sprintf('No reverse mapping for value "%s"', $value));
        }

        return $result;
    }
}
PK��ZJ����R�R:test/Form/Symfony/Component/Form/Tests/FormFactoryTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests;

use Symfony\Component\Form\FormTypeGuesserChain;
use Symfony\Component\Form\FormFactory;
use Symfony\Component\Form\Guess\Guess;
use Symfony\Component\Form\Guess\ValueGuess;
use Symfony\Component\Form\Guess\TypeGuess;
use Symfony\Component\Form\Tests\Fixtures\Author;
use Symfony\Component\Form\Tests\Fixtures\FooType;
use Symfony\Component\Form\Tests\Fixtures\FooSubType;
use Symfony\Component\Form\Tests\Fixtures\FooSubTypeWithParentInstance;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class FormFactoryTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $guesser1;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $guesser2;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $registry;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $resolvedTypeFactory;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $builder;

    /**
     * @var FormFactory
     */
    private $factory;

    protected function setUp()
    {
        $this->resolvedTypeFactory = $this->getMock('Symfony\Component\Form\ResolvedFormTypeFactoryInterface');
        $this->guesser1 = $this->getMock('Symfony\Component\Form\FormTypeGuesserInterface');
        $this->guesser2 = $this->getMock('Symfony\Component\Form\FormTypeGuesserInterface');
        $this->registry = $this->getMock('Symfony\Component\Form\FormRegistryInterface');
        $this->builder = $this->getMock('Symfony\Component\Form\Test\FormBuilderInterface');
        $this->factory = new FormFactory($this->registry, $this->resolvedTypeFactory);

        $this->registry->expects($this->any())
            ->method('getTypeGuesser')
            ->will($this->returnValue(new FormTypeGuesserChain(array(
                $this->guesser1,
                $this->guesser2,
            ))));
    }

    public function testCreateNamedBuilderWithTypeName()
    {
        $options = array('a' => '1', 'b' => '2');
        $resolvedOptions = array('a' => '2', 'b' => '3');
        $resolvedType = $this->getMockResolvedType();

        $this->registry->expects($this->once())
            ->method('getType')
            ->with('type')
            ->will($this->returnValue($resolvedType));

        $resolvedType->expects($this->once())
            ->method('createBuilder')
            ->with($this->factory, 'name', $options)
            ->will($this->returnValue($this->builder));

        $this->builder->expects($this->any())
            ->method('getOptions')
            ->will($this->returnValue($resolvedOptions));

        $resolvedType->expects($this->once())
            ->method('buildForm')
            ->with($this->builder, $resolvedOptions);

        $this->assertSame($this->builder, $this->factory->createNamedBuilder('name', 'type', null, $options));
    }

    public function testCreateNamedBuilderWithTypeInstance()
    {
        $options = array('a' => '1', 'b' => '2');
        $resolvedOptions = array('a' => '2', 'b' => '3');
        $type = new FooType();
        $resolvedType = $this->getMockResolvedType();

        $this->resolvedTypeFactory->expects($this->once())
            ->method('createResolvedType')
            ->with($type)
            ->will($this->returnValue($resolvedType));

        $resolvedType->expects($this->once())
            ->method('createBuilder')
            ->with($this->factory, 'name', $options)
            ->will($this->returnValue($this->builder));

        $this->builder->expects($this->any())
            ->method('getOptions')
            ->will($this->returnValue($resolvedOptions));

        $resolvedType->expects($this->once())
            ->method('buildForm')
            ->with($this->builder, $resolvedOptions);

        $this->assertSame($this->builder, $this->factory->createNamedBuilder('name', $type, null, $options));
    }

    public function testCreateNamedBuilderWithTypeInstanceWithParentType()
    {
        $options = array('a' => '1', 'b' => '2');
        $resolvedOptions = array('a' => '2', 'b' => '3');
        $type = new FooSubType();
        $resolvedType = $this->getMockResolvedType();
        $parentResolvedType = $this->getMockResolvedType();

        $this->registry->expects($this->once())
            ->method('getType')
            ->with('foo')
            ->will($this->returnValue($parentResolvedType));

        $this->resolvedTypeFactory->expects($this->once())
            ->method('createResolvedType')
            ->with($type, array(), $parentResolvedType)
            ->will($this->returnValue($resolvedType));

        $resolvedType->expects($this->once())
            ->method('createBuilder')
            ->with($this->factory, 'name', $options)
            ->will($this->returnValue($this->builder));

        $this->builder->expects($this->any())
            ->method('getOptions')
            ->will($this->returnValue($resolvedOptions));

        $resolvedType->expects($this->once())
            ->method('buildForm')
            ->with($this->builder, $resolvedOptions);

        $this->assertSame($this->builder, $this->factory->createNamedBuilder('name', $type, null, $options));
    }

    public function testCreateNamedBuilderWithTypeInstanceWithParentTypeInstance()
    {
        $options = array('a' => '1', 'b' => '2');
        $resolvedOptions = array('a' => '2', 'b' => '3');
        $type = new FooSubTypeWithParentInstance();
        $resolvedType = $this->getMockResolvedType();
        $parentResolvedType = $this->getMockResolvedType();

        $this->resolvedTypeFactory->expects($this->at(0))
            ->method('createResolvedType')
            ->with($type->getParent())
            ->will($this->returnValue($parentResolvedType));

        $this->resolvedTypeFactory->expects($this->at(1))
            ->method('createResolvedType')
            ->with($type, array(), $parentResolvedType)
            ->will($this->returnValue($resolvedType));

        $resolvedType->expects($this->once())
            ->method('createBuilder')
            ->with($this->factory, 'name', $options)
            ->will($this->returnValue($this->builder));

        $this->builder->expects($this->any())
            ->method('getOptions')
            ->will($this->returnValue($resolvedOptions));

        $resolvedType->expects($this->once())
            ->method('buildForm')
            ->with($this->builder, $resolvedOptions);

        $this->assertSame($this->builder, $this->factory->createNamedBuilder('name', $type, null, $options));
    }

    public function testCreateNamedBuilderWithResolvedTypeInstance()
    {
        $options = array('a' => '1', 'b' => '2');
        $resolvedOptions = array('a' => '2', 'b' => '3');
        $resolvedType = $this->getMockResolvedType();

        $resolvedType->expects($this->once())
            ->method('createBuilder')
            ->with($this->factory, 'name', $options)
            ->will($this->returnValue($this->builder));

        $this->builder->expects($this->any())
            ->method('getOptions')
            ->will($this->returnValue($resolvedOptions));

        $resolvedType->expects($this->once())
            ->method('buildForm')
            ->with($this->builder, $resolvedOptions);

        $this->assertSame($this->builder, $this->factory->createNamedBuilder('name', $resolvedType, null, $options));
    }

    public function testCreateNamedBuilderFillsDataOption()
    {
        $givenOptions = array('a' => '1', 'b' => '2');
        $expectedOptions = array_merge($givenOptions, array('data' => 'DATA'));
        $resolvedOptions = array('a' => '2', 'b' => '3', 'data' => 'DATA');
        $resolvedType = $this->getMockResolvedType();

        $this->registry->expects($this->once())
            ->method('getType')
            ->with('type')
            ->will($this->returnValue($resolvedType));

        $resolvedType->expects($this->once())
            ->method('createBuilder')
            ->with($this->factory, 'name', $expectedOptions)
            ->will($this->returnValue($this->builder));

        $this->builder->expects($this->any())
            ->method('getOptions')
            ->will($this->returnValue($resolvedOptions));

        $resolvedType->expects($this->once())
            ->method('buildForm')
            ->with($this->builder, $resolvedOptions);

        $this->assertSame($this->builder, $this->factory->createNamedBuilder('name', 'type', 'DATA', $givenOptions));
    }

    public function testCreateNamedBuilderDoesNotOverrideExistingDataOption()
    {
        $options = array('a' => '1', 'b' => '2', 'data' => 'CUSTOM');
        $resolvedOptions = array('a' => '2', 'b' => '3', 'data' => 'CUSTOM');
        $resolvedType = $this->getMockResolvedType();

        $this->registry->expects($this->once())
            ->method('getType')
            ->with('type')
            ->will($this->returnValue($resolvedType));

        $resolvedType->expects($this->once())
            ->method('createBuilder')
            ->with($this->factory, 'name', $options)
            ->will($this->returnValue($this->builder));

        $this->builder->expects($this->any())
            ->method('getOptions')
            ->will($this->returnValue($resolvedOptions));

        $resolvedType->expects($this->once())
            ->method('buildForm')
            ->with($this->builder, $resolvedOptions);

        $this->assertSame($this->builder, $this->factory->createNamedBuilder('name', 'type', 'DATA', $options));
    }

    /**
     * @expectedException        \Symfony\Component\Form\Exception\UnexpectedTypeException
     * @expectedExceptionMessage Expected argument of type "string, Symfony\Component\Form\ResolvedFormTypeInterface or Symfony\Component\Form\FormTypeInterface", "stdClass" given
     */
    public function testCreateNamedBuilderThrowsUnderstandableException()
    {
        $this->factory->createNamedBuilder('name', new \stdClass());
    }

    public function testCreateUsesTypeNameIfTypeGivenAsString()
    {
        $options = array('a' => '1', 'b' => '2');
        $resolvedOptions = array('a' => '2', 'b' => '3');
        $resolvedType = $this->getMockResolvedType();

        $this->registry->expects($this->once())
            ->method('getType')
            ->with('TYPE')
            ->will($this->returnValue($resolvedType));

        $resolvedType->expects($this->once())
            ->method('createBuilder')
            ->with($this->factory, 'TYPE', $options)
            ->will($this->returnValue($this->builder));

        $this->builder->expects($this->any())
            ->method('getOptions')
            ->will($this->returnValue($resolvedOptions));

        $resolvedType->expects($this->once())
            ->method('buildForm')
            ->with($this->builder, $resolvedOptions);

        $this->builder->expects($this->once())
            ->method('getForm')
            ->will($this->returnValue('FORM'));

        $this->assertSame('FORM', $this->factory->create('TYPE', null, $options));
    }

    public function testCreateUsesTypeNameIfTypeGivenAsObject()
    {
        $options = array('a' => '1', 'b' => '2');
        $resolvedOptions = array('a' => '2', 'b' => '3');
        $resolvedType = $this->getMockResolvedType();

        $resolvedType->expects($this->once())
            ->method('getName')
            ->will($this->returnValue('TYPE'));

        $resolvedType->expects($this->once())
            ->method('createBuilder')
            ->with($this->factory, 'TYPE', $options)
            ->will($this->returnValue($this->builder));

        $this->builder->expects($this->any())
            ->method('getOptions')
            ->will($this->returnValue($resolvedOptions));

        $resolvedType->expects($this->once())
            ->method('buildForm')
            ->with($this->builder, $resolvedOptions);

        $this->builder->expects($this->once())
            ->method('getForm')
            ->will($this->returnValue('FORM'));

        $this->assertSame('FORM', $this->factory->create($resolvedType, null, $options));
    }

    public function testCreateNamed()
    {
        $options = array('a' => '1', 'b' => '2');
        $resolvedOptions = array('a' => '2', 'b' => '3');
        $resolvedType = $this->getMockResolvedType();

        $this->registry->expects($this->once())
            ->method('getType')
            ->with('type')
            ->will($this->returnValue($resolvedType));

        $resolvedType->expects($this->once())
            ->method('createBuilder')
            ->with($this->factory, 'name', $options)
            ->will($this->returnValue($this->builder));

        $this->builder->expects($this->any())
            ->method('getOptions')
            ->will($this->returnValue($resolvedOptions));

        $resolvedType->expects($this->once())
            ->method('buildForm')
            ->with($this->builder, $resolvedOptions);

        $this->builder->expects($this->once())
            ->method('getForm')
            ->will($this->returnValue('FORM'));

        $this->assertSame('FORM', $this->factory->createNamed('name', 'type', null, $options));
    }

    public function testCreateBuilderForPropertyWithoutTypeGuesser()
    {
        $registry = $this->getMock('Symfony\Component\Form\FormRegistryInterface');
        $factory = $this->getMockBuilder('Symfony\Component\Form\FormFactory')
            ->setMethods(array('createNamedBuilder'))
            ->setConstructorArgs(array($registry, $this->resolvedTypeFactory))
            ->getMock();

        $factory->expects($this->once())
            ->method('createNamedBuilder')
            ->with('firstName', 'text', null, array())
            ->will($this->returnValue('builderInstance'));

        $this->builder = $factory->createBuilderForProperty('Application\Author', 'firstName');

        $this->assertEquals('builderInstance', $this->builder);
    }

    public function testCreateBuilderForPropertyCreatesFormWithHighestConfidence()
    {
        $this->guesser1->expects($this->once())
            ->method('guessType')
            ->with('Application\Author', 'firstName')
            ->will($this->returnValue(new TypeGuess(
                'text',
                array('max_length' => 10),
                Guess::MEDIUM_CONFIDENCE
            )));

        $this->guesser2->expects($this->once())
            ->method('guessType')
            ->with('Application\Author', 'firstName')
            ->will($this->returnValue(new TypeGuess(
                'password',
                array('max_length' => 7),
                Guess::HIGH_CONFIDENCE
            )));

        $factory = $this->getMockFactory(array('createNamedBuilder'));

        $factory->expects($this->once())
            ->method('createNamedBuilder')
            ->with('firstName', 'password', null, array('max_length' => 7))
            ->will($this->returnValue('builderInstance'));

        $this->builder = $factory->createBuilderForProperty('Application\Author', 'firstName');

        $this->assertEquals('builderInstance', $this->builder);
    }

    public function testCreateBuilderCreatesTextFormIfNoGuess()
    {
        $this->guesser1->expects($this->once())
                ->method('guessType')
                ->with('Application\Author', 'firstName')
                ->will($this->returnValue(null));

        $factory = $this->getMockFactory(array('createNamedBuilder'));

        $factory->expects($this->once())
            ->method('createNamedBuilder')
            ->with('firstName', 'text')
            ->will($this->returnValue('builderInstance'));

        $this->builder = $factory->createBuilderForProperty('Application\Author', 'firstName');

        $this->assertEquals('builderInstance', $this->builder);
    }

    public function testOptionsCanBeOverridden()
    {
        $this->guesser1->expects($this->once())
                ->method('guessType')
                ->with('Application\Author', 'firstName')
                ->will($this->returnValue(new TypeGuess(
                    'text',
                    array('max_length' => 10),
                    Guess::MEDIUM_CONFIDENCE
                )));

        $factory = $this->getMockFactory(array('createNamedBuilder'));

        $factory->expects($this->once())
            ->method('createNamedBuilder')
            ->with('firstName', 'text', null, array('max_length' => 11))
            ->will($this->returnValue('builderInstance'));

        $this->builder = $factory->createBuilderForProperty(
            'Application\Author',
            'firstName',
            null,
            array('max_length' => 11)
        );

        $this->assertEquals('builderInstance', $this->builder);
    }

    public function testCreateBuilderUsesMaxLengthIfFound()
    {
        $this->guesser1->expects($this->once())
                ->method('guessMaxLength')
                ->with('Application\Author', 'firstName')
                ->will($this->returnValue(new ValueGuess(
                    15,
                    Guess::MEDIUM_CONFIDENCE
                )));

        $this->guesser2->expects($this->once())
                ->method('guessMaxLength')
                ->with('Application\Author', 'firstName')
                ->will($this->returnValue(new ValueGuess(
                    20,
                    Guess::HIGH_CONFIDENCE
                )));

        $factory = $this->getMockFactory(array('createNamedBuilder'));

        $factory->expects($this->once())
            ->method('createNamedBuilder')
            ->with('firstName', 'text', null, array('max_length' => 20))
            ->will($this->returnValue('builderInstance'));

        $this->builder = $factory->createBuilderForProperty(
            'Application\Author',
            'firstName'
        );

        $this->assertEquals('builderInstance', $this->builder);
    }

    public function testCreateBuilderUsesRequiredSettingWithHighestConfidence()
    {
        $this->guesser1->expects($this->once())
                ->method('guessRequired')
                ->with('Application\Author', 'firstName')
                ->will($this->returnValue(new ValueGuess(
                    true,
                    Guess::MEDIUM_CONFIDENCE
                )));

        $this->guesser2->expects($this->once())
                ->method('guessRequired')
                ->with('Application\Author', 'firstName')
                ->will($this->returnValue(new ValueGuess(
                    false,
                    Guess::HIGH_CONFIDENCE
                )));

        $factory = $this->getMockFactory(array('createNamedBuilder'));

        $factory->expects($this->once())
            ->method('createNamedBuilder')
            ->with('firstName', 'text', null, array('required' => false))
            ->will($this->returnValue('builderInstance'));

        $this->builder = $factory->createBuilderForProperty(
            'Application\Author',
            'firstName'
        );

        $this->assertEquals('builderInstance', $this->builder);
    }

    public function testCreateBuilderUsesPatternIfFound()
    {
        $this->guesser1->expects($this->once())
                ->method('guessPattern')
                ->with('Application\Author', 'firstName')
                ->will($this->returnValue(new ValueGuess(
                    '[a-z]',
                    Guess::MEDIUM_CONFIDENCE
                )));

        $this->guesser2->expects($this->once())
                ->method('guessPattern')
                ->with('Application\Author', 'firstName')
                ->will($this->returnValue(new ValueGuess(
                    '[a-zA-Z]',
                    Guess::HIGH_CONFIDENCE
                )));

        $factory = $this->getMockFactory(array('createNamedBuilder'));

        $factory->expects($this->once())
            ->method('createNamedBuilder')
            ->with('firstName', 'text', null, array('pattern' => '[a-zA-Z]'))
            ->will($this->returnValue('builderInstance'));

        $this->builder = $factory->createBuilderForProperty(
            'Application\Author',
            'firstName'
        );

        $this->assertEquals('builderInstance', $this->builder);
    }

    private function getMockFactory(array $methods = array())
    {
        return $this->getMockBuilder('Symfony\Component\Form\FormFactory')
            ->setMethods($methods)
            ->setConstructorArgs(array($this->registry, $this->resolvedTypeFactory))
            ->getMock();
    }

    private function getMockResolvedType()
    {
        return $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface');
    }

    private function getMockType()
    {
        return $this->getMock('Symfony\Component\Form\FormTypeInterface');
    }
}
PK��ZȔfVA6A6Btest/Form/Symfony/Component/Form/Tests/Util/OrderedHashMapTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Util;

use Symfony\Component\Form\Util\OrderedHashMap;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class OrderedHashMapTest extends \PHPUnit_Framework_TestCase
{
    public function testGet()
    {
        $map = new OrderedHashMap();
        $map['first'] = 1;

        $this->assertSame(1, $map['first']);
    }

    /**
     * @expectedException \OutOfBoundsException
     */
    public function testGetNonExistingFails()
    {
        $map = new OrderedHashMap();

        $map['first'];
    }

    public function testInsertStringKeys()
    {
        $map = new OrderedHashMap();
        $map['first'] = 1;
        $map['second'] = 2;

        $this->assertSame(array('first' => 1, 'second' => 2), iterator_to_array($map));
    }

    public function testInsertNullKeys()
    {
        $map = new OrderedHashMap();
        $map[] = 1;
        $map['foo'] = 2;
        $map[] = 3;

        $this->assertSame(array(0 => 1, 'foo' => 2, 1 => 3), iterator_to_array($map));
    }

    /**
     * Updates should not change the position of an element, otherwise we could
     * turn foreach loops into endless loops if they change the current
     * element:
     *
     *     foreach ($map as $index => $value) {
     *         $map[$index] = $value + 1;
     *     }
     *
     * And we don't want this, right? :)
     */
    public function testUpdateDoesNotChangeElementPosition()
    {
        $map = new OrderedHashMap();
        $map['first'] = 1;
        $map['second'] = 2;
        $map['first'] = 1;

        $this->assertSame(array('first' => 1, 'second' => 2), iterator_to_array($map));
    }

    public function testIsset()
    {
        $map = new OrderedHashMap();
        $map['first'] = 1;

        $this->assertTrue(isset($map['first']));
    }

    public function testIssetReturnsFalseForNonExisting()
    {
        $map = new OrderedHashMap();

        $this->assertFalse(isset($map['first']));
    }

    public function testIssetReturnsFalseForNull()
    {
        $map = new OrderedHashMap();
        $map['first'] = null;

        $this->assertFalse(isset($map['first']));
    }

    public function testUnset()
    {
        $map = new OrderedHashMap();
        $map['first'] = 1;
        $map['second'] = 2;

        unset($map['first']);

        $this->assertSame(array('second' => 2), iterator_to_array($map));
    }

    public function testUnsetNonExistingSucceeds()
    {
        $map = new OrderedHashMap();

        unset($map['first']);
    }

    public function testEmptyIteration()
    {
        $map = new OrderedHashMap();
        $it = $map->getIterator();

        $it->rewind();
        $this->assertFalse($it->valid());
        $this->assertNull($it->key());
        $this->assertNull($it->current());
    }

    public function testIterationSupportsInsertion()
    {
        $map = new OrderedHashMap(array('first' => 1));
        $it = $map->getIterator();

        $it->rewind();
        $this->assertTrue($it->valid());
        $this->assertSame('first', $it->key());
        $this->assertSame(1, $it->current());

        // dynamic modification
        $map['added'] = 2;

        // iterator is unchanged
        $this->assertTrue($it->valid());
        $this->assertSame('first', $it->key());
        $this->assertSame(1, $it->current());

        // continue iteration
        $it->next();
        $this->assertTrue($it->valid());
        $this->assertSame('added', $it->key());
        $this->assertSame(2, $it->current());

        // end of map
        $it->next();
        $this->assertFalse($it->valid());
        $this->assertNull($it->key());
        $this->assertNull($it->current());
    }

    public function testIterationSupportsDeletionAndInsertion()
    {
        $map = new OrderedHashMap(array('first' => 1, 'removed' => 2));
        $it = $map->getIterator();

        $it->rewind();
        $this->assertTrue($it->valid());
        $this->assertSame('first', $it->key());
        $this->assertSame(1, $it->current());

        // dynamic modification
        unset($map['removed']);
        $map['added'] = 3;

        // iterator is unchanged
        $this->assertTrue($it->valid());
        $this->assertSame('first', $it->key());
        $this->assertSame(1, $it->current());

        // continue iteration
        $it->next();
        $this->assertTrue($it->valid());
        $this->assertSame('added', $it->key());
        $this->assertSame(3, $it->current());

        // end of map
        $it->next();
        $this->assertFalse($it->valid());
        $this->assertNull($it->key());
        $this->assertNull($it->current());
    }

    public function testIterationSupportsDeletionOfCurrentElement()
    {
        $map = new OrderedHashMap(array('removed' => 1, 'next' => 2));
        $it = $map->getIterator();

        $it->rewind();
        $this->assertTrue($it->valid());
        $this->assertSame('removed', $it->key());
        $this->assertSame(1, $it->current());

        unset($map['removed']);

        // iterator is unchanged
        $this->assertTrue($it->valid());
        $this->assertSame('removed', $it->key());
        $this->assertSame(1, $it->current());

        // continue iteration
        $it->next();
        $this->assertTrue($it->valid());
        $this->assertSame('next', $it->key());
        $this->assertSame(2, $it->current());

        // end of map
        $it->next();
        $this->assertFalse($it->valid());
        $this->assertNull($it->key());
        $this->assertNull($it->current());
    }

    public function testIterationIgnoresReplacementOfCurrentElement()
    {
        $map = new OrderedHashMap(array('replaced' => 1, 'next' => 2));
        $it = $map->getIterator();

        $it->rewind();
        $this->assertTrue($it->valid());
        $this->assertSame('replaced', $it->key());
        $this->assertSame(1, $it->current());

        $map['replaced'] = 3;

        // iterator is unchanged
        $this->assertTrue($it->valid());
        $this->assertSame('replaced', $it->key());
        $this->assertSame(1, $it->current());

        // continue iteration
        $it->next();
        $this->assertTrue($it->valid());
        $this->assertSame('next', $it->key());
        $this->assertSame(2, $it->current());

        // end of map
        $it->next();
        $this->assertFalse($it->valid());
        $this->assertNull($it->key());
        $this->assertNull($it->current());
    }

    public function testIterationSupportsDeletionOfCurrentAndLastElement()
    {
        $map = new OrderedHashMap(array('removed' => 1));
        $it = $map->getIterator();

        $it->rewind();
        $this->assertTrue($it->valid());
        $this->assertSame('removed', $it->key());
        $this->assertSame(1, $it->current());

        unset($map['removed']);

        // iterator is unchanged
        $this->assertTrue($it->valid());
        $this->assertSame('removed', $it->key());
        $this->assertSame(1, $it->current());

        // end of map
        $it->next();
        $this->assertFalse($it->valid());
        $this->assertNull($it->key());
        $this->assertNull($it->current());
    }

    public function testIterationIgnoresReplacementOfCurrentAndLastElement()
    {
        $map = new OrderedHashMap(array('replaced' => 1));
        $it = $map->getIterator();

        $it->rewind();
        $this->assertTrue($it->valid());
        $this->assertSame('replaced', $it->key());
        $this->assertSame(1, $it->current());

        $map['replaced'] = 2;

        // iterator is unchanged
        $this->assertTrue($it->valid());
        $this->assertSame('replaced', $it->key());
        $this->assertSame(1, $it->current());

        // end of map
        $it->next();
        $this->assertFalse($it->valid());
        $this->assertNull($it->key());
        $this->assertNull($it->current());
    }

    public function testIterationSupportsDeletionOfPreviousElement()
    {
        $map = new OrderedHashMap(array('removed' => 1, 'next' => 2, 'onemore' => 3));
        $it = $map->getIterator();

        $it->rewind();
        $this->assertTrue($it->valid());
        $this->assertSame('removed', $it->key());
        $this->assertSame(1, $it->current());

        // continue iteration
        $it->next();
        $this->assertTrue($it->valid());
        $this->assertSame('next', $it->key());
        $this->assertSame(2, $it->current());

        unset($map['removed']);

        // iterator is unchanged
        $this->assertTrue($it->valid());
        $this->assertSame('next', $it->key());
        $this->assertSame(2, $it->current());

        // continue iteration
        $it->next();
        $this->assertTrue($it->valid());
        $this->assertSame('onemore', $it->key());
        $this->assertSame(3, $it->current());

        // end of map
        $it->next();
        $this->assertFalse($it->valid());
        $this->assertNull($it->key());
        $this->assertNull($it->current());
    }

    public function testIterationIgnoresReplacementOfPreviousElement()
    {
        $map = new OrderedHashMap(array('replaced' => 1, 'next' => 2, 'onemore' => 3));
        $it = $map->getIterator();

        $it->rewind();
        $this->assertTrue($it->valid());
        $this->assertSame('replaced', $it->key());
        $this->assertSame(1, $it->current());

        // continue iteration
        $it->next();
        $this->assertTrue($it->valid());
        $this->assertSame('next', $it->key());
        $this->assertSame(2, $it->current());

        $map['replaced'] = 4;

        // iterator is unchanged
        $this->assertTrue($it->valid());
        $this->assertSame('next', $it->key());
        $this->assertSame(2, $it->current());

        // continue iteration
        $it->next();
        $this->assertTrue($it->valid());
        $this->assertSame('onemore', $it->key());
        $this->assertSame(3, $it->current());

        // end of map
        $it->next();
        $this->assertFalse($it->valid());
        $this->assertNull($it->key());
        $this->assertNull($it->current());
    }

    public function testIterationSupportsDeletionOfMultiplePreviousElements()
    {
        $map = new OrderedHashMap(array('removed' => 1, 'alsoremoved' => 2, 'next' => 3, 'onemore' => 4));
        $it = $map->getIterator();

        $it->rewind();
        $this->assertTrue($it->valid());
        $this->assertSame('removed', $it->key());
        $this->assertSame(1, $it->current());

        // continue iteration
        $it->next();
        $this->assertTrue($it->valid());
        $this->assertSame('alsoremoved', $it->key());
        $this->assertSame(2, $it->current());

        // continue iteration
        $it->next();
        $this->assertTrue($it->valid());
        $this->assertSame('next', $it->key());
        $this->assertSame(3, $it->current());

        unset($map['removed'], $map['alsoremoved']);

        // iterator is unchanged
        $this->assertTrue($it->valid());
        $this->assertSame('next', $it->key());
        $this->assertSame(3, $it->current());

        // continue iteration
        $it->next();
        $this->assertTrue($it->valid());
        $this->assertSame('onemore', $it->key());
        $this->assertSame(4, $it->current());

        // end of map
        $it->next();
        $this->assertFalse($it->valid());
        $this->assertNull($it->key());
        $this->assertNull($it->current());
    }

    public function testParallelIteration()
    {
        $map = new OrderedHashMap(array('first' => 1, 'second' => 2));
        $it1 = $map->getIterator();
        $it2 = $map->getIterator();

        $it1->rewind();
        $this->assertTrue($it1->valid());
        $this->assertSame('first', $it1->key());
        $this->assertSame(1, $it1->current());

        $it2->rewind();
        $this->assertTrue($it2->valid());
        $this->assertSame('first', $it2->key());
        $this->assertSame(1, $it2->current());

        // 1: continue iteration
        $it1->next();
        $this->assertTrue($it1->valid());
        $this->assertSame('second', $it1->key());
        $this->assertSame(2, $it1->current());

        // 2: remains unchanged
        $this->assertTrue($it2->valid());
        $this->assertSame('first', $it2->key());
        $this->assertSame(1, $it2->current());

        // 1: advance to end of map
        $it1->next();
        $this->assertFalse($it1->valid());
        $this->assertNull($it1->key());
        $this->assertNull($it1->current());

        // 2: remains unchanged
        $this->assertTrue($it2->valid());
        $this->assertSame('first', $it2->key());
        $this->assertSame(1, $it2->current());

        // 2: continue iteration
        $it2->next();
        $this->assertTrue($it2->valid());
        $this->assertSame('second', $it2->key());
        $this->assertSame(2, $it2->current());

        // 1: remains unchanged
        $this->assertFalse($it1->valid());
        $this->assertNull($it1->key());
        $this->assertNull($it1->current());

        // 2: advance to end of map
        $it2->next();
        $this->assertFalse($it2->valid());
        $this->assertNull($it2->key());
        $this->assertNull($it2->current());

        // 1: remains unchanged
        $this->assertFalse($it1->valid());
        $this->assertNull($it1->key());
        $this->assertNull($it1->current());
    }

    public function testCount()
    {
        $map = new OrderedHashMap();
        $map[] = 1;
        $map['foo'] = 2;
        unset($map[0]);
        $map[] = 3;

        $this->assertSame(2, count($map));
    }
}
PK��Z�z�nznz;test/Form/Symfony/Component/Form/Tests/CompoundFormTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests;

use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;
use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\Forms;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\SubmitButtonBuilder;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Form\Tests\Fixtures\FixedDataTransformer;

class CompoundFormTest extends AbstractFormTest
{
    public function testValidIfAllChildrenAreValid()
    {
        $this->form->add($this->getBuilder('firstName')->getForm());
        $this->form->add($this->getBuilder('lastName')->getForm());

        $this->form->submit(array(
            'firstName' => 'Bernhard',
            'lastName' => 'Schussek',
        ));

        $this->assertTrue($this->form->isValid());
    }

    public function testInvalidIfChildIsInvalid()
    {
        $this->form->add($this->getBuilder('firstName')->getForm());
        $this->form->add($this->getBuilder('lastName')->getForm());

        $this->form->submit(array(
            'firstName' => 'Bernhard',
            'lastName' => 'Schussek',
        ));

        $this->form->get('lastName')->addError(new FormError('Invalid'));

        $this->assertFalse($this->form->isValid());
    }

    public function testValidIfChildIsNotSubmitted()
    {
        $this->form->add($this->getBuilder('firstName')->getForm());
        $this->form->add($this->getBuilder('lastName')->getForm());

        $this->form->submit(array(
            'firstName' => 'Bernhard',
        ));

        // "lastName" is not "valid" because it was not submitted. This happens
        // for example in PATCH requests. The parent form should still be
        // considered valid.

        $this->assertTrue($this->form->isValid());
    }

    public function testDisabledFormsValidEvenIfChildrenInvalid()
    {
        $form = $this->getBuilder('person')
            ->setDisabled(true)
            ->setCompound(true)
            ->setDataMapper($this->getDataMapper())
            ->add($this->getBuilder('name'))
            ->getForm();

        $form->submit(array('name' => 'Jacques Doe'));

        $form->get('name')->addError(new FormError('Invalid'));

        $this->assertTrue($form->isValid());
    }

    public function testSubmitForwardsNullIfNotClearMissingButValueIsExplicitlyNull()
    {
        $child = $this->getMockForm('firstName');

        $this->form->add($child);

        $child->expects($this->once())
            ->method('submit')
            ->with($this->equalTo(null));

        $this->form->submit(array('firstName' => null), false);
    }

    public function testSubmitForwardsNullIfValueIsMissing()
    {
        $child = $this->getMockForm('firstName');

        $this->form->add($child);

        $child->expects($this->once())
            ->method('submit')
            ->with($this->equalTo(null));

        $this->form->submit(array());
    }

    public function testSubmitDoesNotForwardNullIfNotClearMissing()
    {
        $child = $this->getMockForm('firstName');

        $this->form->add($child);

        $child->expects($this->never())
            ->method('submit');

        $this->form->submit(array(), false);
    }

    public function testSubmitDoesNotAddExtraFieldForNullValues()
    {
        $factory = Forms::createFormFactoryBuilder()
            ->getFormFactory();

        $child = $factory->create('file', null, array('auto_initialize' => false));

        $this->form->add($child);
        $this->form->submit(array('file' => null), false);

        $this->assertCount(0, $this->form->getExtraData());
    }

    public function testClearMissingFlagIsForwarded()
    {
        $child = $this->getMockForm('firstName');

        $this->form->add($child);

        $child->expects($this->once())
            ->method('submit')
            ->with($this->equalTo('foo'), false);

        $this->form->submit(array('firstName' => 'foo'), false);
    }

    public function testCloneChildren()
    {
        $child = $this->getBuilder('child')->getForm();
        $this->form->add($child);

        $clone = clone $this->form;

        $this->assertNotSame($this->form, $clone);
        $this->assertNotSame($child, $clone['child']);
        $this->assertNotSame($this->form['child'], $clone['child']);
    }

    public function testNotEmptyIfChildNotEmpty()
    {
        $child = $this->getMockForm();
        $child->expects($this->once())
            ->method('isEmpty')
            ->will($this->returnValue(false));

        $this->form->setData(null);
        $this->form->add($child);

        $this->assertFalse($this->form->isEmpty());
    }

    public function testAdd()
    {
        $child = $this->getBuilder('foo')->getForm();
        $this->form->add($child);

        $this->assertTrue($this->form->has('foo'));
        $this->assertSame($this->form, $child->getParent());
        $this->assertSame(array('foo' => $child), $this->form->all());
    }

    public function testAddUsingNameAndType()
    {
        $child = $this->getBuilder('foo')->getForm();

        $this->factory->expects($this->once())
            ->method('createNamed')
            ->with('foo', 'text', null, array(
                'bar' => 'baz',
                'auto_initialize' => false,
            ))
            ->will($this->returnValue($child));

        $this->form->add('foo', 'text', array('bar' => 'baz'));

        $this->assertTrue($this->form->has('foo'));
        $this->assertSame($this->form, $child->getParent());
        $this->assertSame(array('foo' => $child), $this->form->all());
    }

    public function testAddUsingIntegerNameAndType()
    {
        $child = $this->getBuilder(0)->getForm();

        $this->factory->expects($this->once())
            ->method('createNamed')
            ->with('0', 'text', null, array(
                'bar' => 'baz',
                'auto_initialize' => false,
            ))
            ->will($this->returnValue($child));

        // in order to make casting unnecessary
        $this->form->add(0, 'text', array('bar' => 'baz'));

        $this->assertTrue($this->form->has(0));
        $this->assertSame($this->form, $child->getParent());
        $this->assertSame(array(0 => $child), $this->form->all());
    }

    public function testAddUsingNameButNoType()
    {
        $this->form = $this->getBuilder('name', null, '\stdClass')
            ->setCompound(true)
            ->setDataMapper($this->getDataMapper())
            ->getForm();

        $child = $this->getBuilder('foo')->getForm();

        $this->factory->expects($this->once())
            ->method('createForProperty')
            ->with('\stdClass', 'foo')
            ->will($this->returnValue($child));

        $this->form->add('foo');

        $this->assertTrue($this->form->has('foo'));
        $this->assertSame($this->form, $child->getParent());
        $this->assertSame(array('foo' => $child), $this->form->all());
    }

    public function testAddUsingNameButNoTypeAndOptions()
    {
        $this->form = $this->getBuilder('name', null, '\stdClass')
            ->setCompound(true)
            ->setDataMapper($this->getDataMapper())
            ->getForm();

        $child = $this->getBuilder('foo')->getForm();

        $this->factory->expects($this->once())
            ->method('createForProperty')
            ->with('\stdClass', 'foo', null, array(
                'bar' => 'baz',
                'auto_initialize' => false,
            ))
            ->will($this->returnValue($child));

        $this->form->add('foo', null, array('bar' => 'baz'));

        $this->assertTrue($this->form->has('foo'));
        $this->assertSame($this->form, $child->getParent());
        $this->assertSame(array('foo' => $child), $this->form->all());
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\AlreadySubmittedException
     */
    public function testAddThrowsExceptionIfAlreadySubmitted()
    {
        $this->form->submit(array());
        $this->form->add($this->getBuilder('foo')->getForm());
    }

    public function testRemove()
    {
        $child = $this->getBuilder('foo')->getForm();
        $this->form->add($child);
        $this->form->remove('foo');

        $this->assertNull($child->getParent());
        $this->assertCount(0, $this->form);
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\AlreadySubmittedException
     */
    public function testRemoveThrowsExceptionIfAlreadySubmitted()
    {
        $this->form->add($this->getBuilder('foo')->setCompound(false)->getForm());
        $this->form->submit(array('foo' => 'bar'));
        $this->form->remove('foo');
    }

    public function testRemoveIgnoresUnknownName()
    {
        $this->form->remove('notexisting');
    }

    public function testArrayAccess()
    {
        $child = $this->getBuilder('foo')->getForm();

        $this->form[] = $child;

        $this->assertTrue(isset($this->form['foo']));
        $this->assertSame($child, $this->form['foo']);

        unset($this->form['foo']);

        $this->assertFalse(isset($this->form['foo']));
    }

    public function testCountable()
    {
        $this->form->add($this->getBuilder('foo')->getForm());
        $this->form->add($this->getBuilder('bar')->getForm());

        $this->assertCount(2, $this->form);
    }

    public function testIterator()
    {
        $this->form->add($this->getBuilder('foo')->getForm());
        $this->form->add($this->getBuilder('bar')->getForm());

        $this->assertSame($this->form->all(), iterator_to_array($this->form));
    }

    public function testAddMapsViewDataToFormIfInitialized()
    {
        $test = $this;
        $mapper = $this->getDataMapper();
        $form = $this->getBuilder()
            ->setCompound(true)
            ->setDataMapper($mapper)
            ->addViewTransformer(new FixedDataTransformer(array(
                '' => '',
                'foo' => 'bar',
            )))
            ->setData('foo')
            ->getForm();

        $child = $this->getBuilder()->getForm();
        $mapper->expects($this->once())
            ->method('mapDataToForms')
            ->with('bar', $this->isInstanceOf('\RecursiveIteratorIterator'))
            ->will($this->returnCallback(function ($data, \RecursiveIteratorIterator $iterator) use ($child, $test) {
                $test->assertInstanceOf('Symfony\Component\Form\Util\InheritDataAwareIterator', $iterator->getInnerIterator());
                $test->assertSame(array($child), iterator_to_array($iterator));
            }));

        $form->initialize();
        $form->add($child);
    }

    public function testAddDoesNotMapViewDataToFormIfNotInitialized()
    {
        $mapper = $this->getDataMapper();
        $form = $this->getBuilder()
            ->setCompound(true)
            ->setDataMapper($mapper)
            ->getForm();

        $child = $this->getBuilder()->getForm();
        $mapper->expects($this->never())
            ->method('mapDataToForms');

        $form->add($child);
    }

    public function testAddDoesNotMapViewDataToFormIfInheritData()
    {
        $mapper = $this->getDataMapper();
        $form = $this->getBuilder()
            ->setCompound(true)
            ->setDataMapper($mapper)
            ->setInheritData(true)
            ->getForm();

        $child = $this->getBuilder()->getForm();
        $mapper->expects($this->never())
            ->method('mapDataToForms');

        $form->initialize();
        $form->add($child);
    }

    public function testSetDataSupportsDynamicAdditionAndRemovalOfChildren()
    {
        $form = $this->getBuilder()
            ->setCompound(true)
            // We test using PropertyPathMapper on purpose. The traversal logic
            // is currently contained in InheritDataAwareIterator, but even
            // if that changes, this test should still function.
            ->setDataMapper(new PropertyPathMapper())
            ->getForm();

        $child = $this->getMockForm('child');
        $childToBeRemoved = $this->getMockForm('removed');
        $childToBeAdded = $this->getMockForm('added');

        $form->add($child);
        $form->add($childToBeRemoved);

        $child->expects($this->once())
            ->method('setData')
            ->will($this->returnCallback(function () use ($form, $childToBeAdded) {
                $form->remove('removed');
                $form->add($childToBeAdded);
            }));

        $childToBeRemoved->expects($this->never())
            ->method('setData');

        // once when it it is created, once when it is added
        $childToBeAdded->expects($this->exactly(2))
            ->method('setData');

        // pass NULL to all children
        $form->setData(array());
    }

    public function testSetDataMapsViewDataToChildren()
    {
        $test = $this;
        $mapper = $this->getDataMapper();
        $form = $this->getBuilder()
            ->setCompound(true)
            ->setDataMapper($mapper)
            ->addViewTransformer(new FixedDataTransformer(array(
                '' => '',
                'foo' => 'bar',
            )))
            ->getForm();

        $form->add($child1 = $this->getBuilder('firstName')->getForm());
        $form->add($child2 = $this->getBuilder('lastName')->getForm());

        $mapper->expects($this->once())
            ->method('mapDataToForms')
            ->with('bar', $this->isInstanceOf('\RecursiveIteratorIterator'))
            ->will($this->returnCallback(function ($data, \RecursiveIteratorIterator $iterator) use ($child1, $child2, $test) {
                $test->assertInstanceOf('Symfony\Component\Form\Util\InheritDataAwareIterator', $iterator->getInnerIterator());
                $test->assertSame(array('firstName' => $child1, 'lastName' => $child2), iterator_to_array($iterator));
            }));

        $form->setData('foo');
    }

    public function testSubmitSupportsDynamicAdditionAndRemovalOfChildren()
    {
        $child = $this->getMockForm('child');
        $childToBeRemoved = $this->getMockForm('removed');
        $childToBeAdded = $this->getMockForm('added');

        $this->form->add($child);
        $this->form->add($childToBeRemoved);

        $form = $this->form;

        $child->expects($this->once())
            ->method('submit')
            ->will($this->returnCallback(function () use ($form, $childToBeAdded) {
                $form->remove('removed');
                $form->add($childToBeAdded);
            }));

        $childToBeRemoved->expects($this->never())
            ->method('submit');

        $childToBeAdded->expects($this->once())
            ->method('submit');

        // pass NULL to all children
        $this->form->submit(array());
    }

    public function testSubmitMapsSubmittedChildrenOntoExistingViewData()
    {
        $test = $this;
        $mapper = $this->getDataMapper();
        $form = $this->getBuilder()
            ->setCompound(true)
            ->setDataMapper($mapper)
            ->addViewTransformer(new FixedDataTransformer(array(
                '' => '',
                'foo' => 'bar',
            )))
            ->setData('foo')
            ->getForm();

        $form->add($child1 = $this->getBuilder('firstName')->setCompound(false)->getForm());
        $form->add($child2 = $this->getBuilder('lastName')->setCompound(false)->getForm());

        $mapper->expects($this->once())
            ->method('mapFormsToData')
            ->with($this->isInstanceOf('\RecursiveIteratorIterator'), 'bar')
            ->will($this->returnCallback(function (\RecursiveIteratorIterator $iterator) use ($child1, $child2, $test) {
                $test->assertInstanceOf('Symfony\Component\Form\Util\InheritDataAwareIterator', $iterator->getInnerIterator());
                $test->assertSame(array('firstName' => $child1, 'lastName' => $child2), iterator_to_array($iterator));
                $test->assertEquals('Bernhard', $child1->getData());
                $test->assertEquals('Schussek', $child2->getData());
            }));

        $form->submit(array(
            'firstName' => 'Bernhard',
            'lastName' => 'Schussek',
        ));
    }

    public function testMapFormsToDataIsNotInvokedIfInheritData()
    {
        $mapper = $this->getDataMapper();
        $form = $this->getBuilder()
            ->setCompound(true)
            ->setDataMapper($mapper)
            ->setInheritData(true)
            ->addViewTransformer(new FixedDataTransformer(array(
                '' => '',
                'foo' => 'bar',
            )))
            ->getForm();

        $form->add($child1 = $this->getBuilder('firstName')->setCompound(false)->getForm());
        $form->add($child2 = $this->getBuilder('lastName')->setCompound(false)->getForm());

        $mapper->expects($this->never())
            ->method('mapFormsToData');

        $form->submit(array(
            'firstName' => 'Bernhard',
            'lastName' => 'Schussek',
        ));
    }

    /*
     * https://github.com/symfony/symfony/issues/4480
     */
    public function testSubmitRestoresViewDataIfCompoundAndEmpty()
    {
        $mapper = $this->getDataMapper();
        $object = new \stdClass();
        $form = $this->getBuilder('name', null, 'stdClass')
            ->setCompound(true)
            ->setDataMapper($mapper)
            ->setData($object)
            ->getForm();

        $form->submit(array());

        $this->assertSame($object, $form->getData());
    }

    public function testSubmitMapsSubmittedChildrenOntoEmptyData()
    {
        $test = $this;
        $mapper = $this->getDataMapper();
        $object = new \stdClass();
        $form = $this->getBuilder()
            ->setCompound(true)
            ->setDataMapper($mapper)
            ->setEmptyData($object)
            ->setData(null)
            ->getForm();

        $form->add($child = $this->getBuilder('name')->setCompound(false)->getForm());

        $mapper->expects($this->once())
            ->method('mapFormsToData')
            ->with($this->isInstanceOf('\RecursiveIteratorIterator'), $object)
            ->will($this->returnCallback(function (\RecursiveIteratorIterator $iterator) use ($child, $test) {
                $test->assertInstanceOf('Symfony\Component\Form\Util\InheritDataAwareIterator', $iterator->getInnerIterator());
                $test->assertSame(array('name' => $child), iterator_to_array($iterator));
            }));

        $form->submit(array(
            'name' => 'Bernhard',
        ));
    }

    public function requestMethodProvider()
    {
        return array(
            array('POST'),
            array('PUT'),
            array('DELETE'),
            array('PATCH'),
        );
    }

    /**
     * @dataProvider requestMethodProvider
     */
    public function testSubmitPostOrPutRequest($method)
    {
        $path = tempnam(sys_get_temp_dir(), 'sf2');
        touch($path);

        $values = array(
            'author' => array(
                'name' => 'Bernhard',
                'image' => array('filename' => 'foobar.png'),
            ),
        );

        $files = array(
            'author' => array(
                'error' => array('image' => UPLOAD_ERR_OK),
                'name' => array('image' => 'upload.png'),
                'size' => array('image' => 123),
                'tmp_name' => array('image' => $path),
                'type' => array('image' => 'image/png'),
            ),
        );

        $request = new Request(array(), $values, array(), array(), $files, array(
            'REQUEST_METHOD' => $method,
        ));

        $form = $this->getBuilder('author')
            ->setMethod($method)
            ->setCompound(true)
            ->setDataMapper($this->getDataMapper())
            ->setRequestHandler(new HttpFoundationRequestHandler())
            ->getForm();
        $form->add($this->getBuilder('name')->getForm());
        $form->add($this->getBuilder('image')->getForm());

        $form->handleRequest($request);

        $file = new UploadedFile($path, 'upload.png', 'image/png', 123, UPLOAD_ERR_OK);

        $this->assertEquals('Bernhard', $form['name']->getData());
        $this->assertEquals($file, $form['image']->getData());

        unlink($path);
    }

    /**
     * @dataProvider requestMethodProvider
     */
    public function testSubmitPostOrPutRequestWithEmptyRootFormName($method)
    {
        $path = tempnam(sys_get_temp_dir(), 'sf2');
        touch($path);

        $values = array(
            'name' => 'Bernhard',
            'extra' => 'data',
        );

        $files = array(
            'image' => array(
                'error' => UPLOAD_ERR_OK,
                'name' => 'upload.png',
                'size' => 123,
                'tmp_name' => $path,
                'type' => 'image/png',
            ),
        );

        $request = new Request(array(), $values, array(), array(), $files, array(
            'REQUEST_METHOD' => $method,
        ));

        $form = $this->getBuilder('')
            ->setMethod($method)
            ->setCompound(true)
            ->setDataMapper($this->getDataMapper())
            ->setRequestHandler(new HttpFoundationRequestHandler())
            ->getForm();
        $form->add($this->getBuilder('name')->getForm());
        $form->add($this->getBuilder('image')->getForm());

        $form->handleRequest($request);

        $file = new UploadedFile($path, 'upload.png', 'image/png', 123, UPLOAD_ERR_OK);

        $this->assertEquals('Bernhard', $form['name']->getData());
        $this->assertEquals($file, $form['image']->getData());
        $this->assertEquals(array('extra' => 'data'), $form->getExtraData());

        unlink($path);
    }

    /**
     * @dataProvider requestMethodProvider
     */
    public function testSubmitPostOrPutRequestWithSingleChildForm($method)
    {
        $path = tempnam(sys_get_temp_dir(), 'sf2');
        touch($path);

        $files = array(
            'image' => array(
                'error' => UPLOAD_ERR_OK,
                'name' => 'upload.png',
                'size' => 123,
                'tmp_name' => $path,
                'type' => 'image/png',
            ),
        );

        $request = new Request(array(), array(), array(), array(), $files, array(
            'REQUEST_METHOD' => $method,
        ));

        $form = $this->getBuilder('image')
            ->setMethod($method)
            ->setRequestHandler(new HttpFoundationRequestHandler())
            ->getForm();

        $form->handleRequest($request);

        $file = new UploadedFile($path, 'upload.png', 'image/png', 123, UPLOAD_ERR_OK);

        $this->assertEquals($file, $form->getData());

        unlink($path);
    }

    /**
     * @dataProvider requestMethodProvider
     */
    public function testSubmitPostOrPutRequestWithSingleChildFormUploadedFile($method)
    {
        $path = tempnam(sys_get_temp_dir(), 'sf2');
        touch($path);

        $values = array(
            'name' => 'Bernhard',
        );

        $request = new Request(array(), $values, array(), array(), array(), array(
            'REQUEST_METHOD' => $method,
        ));

        $form = $this->getBuilder('name')
            ->setMethod($method)
            ->setRequestHandler(new HttpFoundationRequestHandler())
            ->getForm();

        $form->handleRequest($request);

        $this->assertEquals('Bernhard', $form->getData());

        unlink($path);
    }

    public function testSubmitGetRequest()
    {
        $values = array(
            'author' => array(
                'firstName' => 'Bernhard',
                'lastName' => 'Schussek',
            ),
        );

        $request = new Request($values, array(), array(), array(), array(), array(
            'REQUEST_METHOD' => 'GET',
        ));

        $form = $this->getBuilder('author')
            ->setMethod('GET')
            ->setCompound(true)
            ->setDataMapper($this->getDataMapper())
            ->setRequestHandler(new HttpFoundationRequestHandler())
            ->getForm();
        $form->add($this->getBuilder('firstName')->getForm());
        $form->add($this->getBuilder('lastName')->getForm());

        $form->handleRequest($request);

        $this->assertEquals('Bernhard', $form['firstName']->getData());
        $this->assertEquals('Schussek', $form['lastName']->getData());
    }

    public function testSubmitGetRequestWithEmptyRootFormName()
    {
        $values = array(
            'firstName' => 'Bernhard',
            'lastName' => 'Schussek',
            'extra' => 'data'
        );

        $request = new Request($values, array(), array(), array(), array(), array(
            'REQUEST_METHOD' => 'GET',
        ));

        $form = $this->getBuilder('')
            ->setMethod('GET')
            ->setCompound(true)
            ->setDataMapper($this->getDataMapper())
            ->setRequestHandler(new HttpFoundationRequestHandler())
            ->getForm();
        $form->add($this->getBuilder('firstName')->getForm());
        $form->add($this->getBuilder('lastName')->getForm());

        $form->handleRequest($request);

        $this->assertEquals('Bernhard', $form['firstName']->getData());
        $this->assertEquals('Schussek', $form['lastName']->getData());
        $this->assertEquals(array('extra' => 'data'), $form->getExtraData());
    }

    public function testGetErrorsAsStringDeep()
    {
        $parent = $this->getBuilder()
            ->setCompound(true)
            ->setDataMapper($this->getDataMapper())
            ->getForm();

        $this->form->addError(new FormError('Error!'));

        $parent->add($this->form);
        $parent->add($this->getBuilder('foo')->getForm());

        $this->assertEquals("name:\n    ERROR: Error!\nfoo:\n    No errors\n", $parent->getErrorsAsString());
    }

    // Basic cases are covered in SimpleFormTest
    public function testCreateViewWithChildren()
    {
        $type = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface');
        $options = array('a' => 'Foo', 'b' => 'Bar');
        $field1 = $this->getMockForm('foo');
        $field2 = $this->getMockForm('bar');
        $view = new FormView();
        $field1View = new FormView();
        $field2View = new FormView();

        $this->form = $this->getBuilder('form', null, null, $options)
            ->setCompound(true)
            ->setDataMapper($this->getDataMapper())
            ->setType($type)
            ->getForm();
        $this->form->add($field1);
        $this->form->add($field2);

        $test = $this;

        $assertChildViewsEqual = function (array $childViews) use ($test) {
            return function (FormView $view) use ($test, $childViews) {
                /* @var \PHPUnit_Framework_TestCase $test */
                $test->assertSame($childViews, $view->children);
            };
        };

        // First create the view
        $type->expects($this->once())
            ->method('createView')
            ->will($this->returnValue($view));

        // Then build it for the form itself
        $type->expects($this->once())
            ->method('buildView')
            ->with($view, $this->form, $options)
            ->will($this->returnCallback($assertChildViewsEqual(array())));

        // Then add the first child form
        $field1->expects($this->once())
            ->method('createView')
            ->will($this->returnValue($field1View));

        // Then the second child form
        $field2->expects($this->once())
            ->method('createView')
            ->will($this->returnValue($field2View));

        // Again build the view for the form itself. This time the child views
        // exist.
        $type->expects($this->once())
            ->method('finishView')
            ->with($view, $this->form, $options)
            ->will($this->returnCallback($assertChildViewsEqual(array('foo' => $field1View, 'bar' => $field2View))));

        $this->assertSame($view, $this->form->createView());
    }

    public function testNoClickedButtonBeforeSubmission()
    {
        $this->assertNull($this->form->getClickedButton());
    }

    public function testNoClickedButton()
    {
        $button = $this->getMockBuilder('Symfony\Component\Form\SubmitButton')
            ->setConstructorArgs(array(new SubmitButtonBuilder('submit')))
            ->setMethods(array('isClicked'))
            ->getMock();

        $button->expects($this->any())
            ->method('isClicked')
            ->will($this->returnValue(false));

        $parentForm = $this->getBuilder('parent')->getForm();
        $nestedForm = $this->getBuilder('nested')->getForm();

        $this->form->setParent($parentForm);
        $this->form->add($button);
        $this->form->add($nestedForm);
        $this->form->submit(array());

        $this->assertNull($this->form->getClickedButton());
    }

    public function testClickedButton()
    {
        $button = $this->getMockBuilder('Symfony\Component\Form\SubmitButton')
            ->setConstructorArgs(array(new SubmitButtonBuilder('submit')))
            ->setMethods(array('isClicked'))
            ->getMock();

        $button->expects($this->any())
            ->method('isClicked')
            ->will($this->returnValue(true));

        $this->form->add($button);
        $this->form->submit(array());

        $this->assertSame($button, $this->form->getClickedButton());
    }

    public function testClickedButtonFromNestedForm()
    {
        $button = $this->getBuilder('submit')->getForm();

        $nestedForm = $this->getMockBuilder('Symfony\Component\Form\Form')
            ->setConstructorArgs(array($this->getBuilder('nested')))
            ->setMethods(array('getClickedButton'))
            ->getMock();

        $nestedForm->expects($this->any())
            ->method('getClickedButton')
            ->will($this->returnValue($button));

        $this->form->add($nestedForm);
        $this->form->submit(array());

        $this->assertSame($button, $this->form->getClickedButton());
    }

    public function testClickedButtonFromParentForm()
    {
        $button = $this->getBuilder('submit')->getForm();

        $parentForm = $this->getMockBuilder('Symfony\Component\Form\Form')
            ->setConstructorArgs(array($this->getBuilder('parent')))
            ->setMethods(array('getClickedButton'))
            ->getMock();

        $parentForm->expects($this->any())
            ->method('getClickedButton')
            ->will($this->returnValue($button));

        $this->form->setParent($parentForm);
        $this->form->submit(array());

        $this->assertSame($button, $this->form->getClickedButton());
    }

    protected function createForm()
    {
        return $this->getBuilder()
            ->setCompound(true)
            ->setDataMapper($this->getDataMapper())
            ->getForm();
    }
}
PK��Z���dAtest/Form/Symfony/Component/Form/Tests/FormFactoryBuilderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests;

use Symfony\Component\Form\FormFactoryBuilder;
use Symfony\Component\Form\Tests\Fixtures\FooType;

class FormFactoryBuilderTest extends \PHPUnit_Framework_TestCase
{
    private $registry;
    private $guesser;
    private $type;

    protected function setUp()
    {
        $factory = new \ReflectionClass('Symfony\Component\Form\FormFactory');
        $this->registry = $factory->getProperty('registry');
        $this->registry->setAccessible(true);

        $this->guesser = $this->getMock('Symfony\Component\Form\FormTypeGuesserInterface');
        $this->type = new FooType();
    }

    public function testAddType()
    {
        $factoryBuilder = new FormFactoryBuilder();
        $factoryBuilder->addType($this->type);

        $factory = $factoryBuilder->getFormFactory();
        $registry = $this->registry->getValue($factory);
        $extensions = $registry->getExtensions();

        $this->assertCount(1, $extensions);
        $this->assertTrue($extensions[0]->hasType($this->type->getName()));
        $this->assertNull($extensions[0]->getTypeGuesser());
    }

    public function testAddTypeGuesser()
    {
        $factoryBuilder = new FormFactoryBuilder();
        $factoryBuilder->addTypeGuesser($this->guesser);

        $factory = $factoryBuilder->getFormFactory();
        $registry = $this->registry->getValue($factory);
        $extensions = $registry->getExtensions();

        $this->assertCount(1, $extensions);
        $this->assertNotNull($extensions[0]->getTypeGuesser());
    }
}
PK��Z̈́����;test/Form/Symfony/Component/Form/Tests/FormRegistryTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests;

use Symfony\Component\Form\FormRegistry;
use Symfony\Component\Form\FormTypeGuesserChain;
use Symfony\Component\Form\Tests\Fixtures\TestExtension;
use Symfony\Component\Form\Tests\Fixtures\FooSubTypeWithParentInstance;
use Symfony\Component\Form\Tests\Fixtures\FooSubType;
use Symfony\Component\Form\Tests\Fixtures\FooTypeBazExtension;
use Symfony\Component\Form\Tests\Fixtures\FooTypeBarExtension;
use Symfony\Component\Form\Tests\Fixtures\FooType;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class FormRegistryTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var FormRegistry
     */
    private $registry;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $resolvedTypeFactory;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $guesser1;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $guesser2;

    /**
     * @var TestExtension
     */
    private $extension1;

    /**
     * @var TestExtension
     */
    private $extension2;

    protected function setUp()
    {
        $this->resolvedTypeFactory = $this->getMock('Symfony\Component\Form\ResolvedFormTypeFactory');
        $this->guesser1 = $this->getMock('Symfony\Component\Form\FormTypeGuesserInterface');
        $this->guesser2 = $this->getMock('Symfony\Component\Form\FormTypeGuesserInterface');
        $this->extension1 = new TestExtension($this->guesser1);
        $this->extension2 = new TestExtension($this->guesser2);
        $this->registry = new FormRegistry(array(
            $this->extension1,
            $this->extension2,
        ), $this->resolvedTypeFactory);
    }

    public function testGetTypeFromExtension()
    {
        $type = new FooType();
        $resolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface');

        $this->extension2->addType($type);

        $this->resolvedTypeFactory->expects($this->once())
            ->method('createResolvedType')
            ->with($type)
            ->will($this->returnValue($resolvedType));

        $resolvedType->expects($this->any())
            ->method('getName')
            ->will($this->returnValue('foo'));

        $resolvedType = $this->registry->getType('foo');

        $this->assertSame($resolvedType, $this->registry->getType('foo'));
    }

    public function testGetTypeWithTypeExtensions()
    {
        $type = new FooType();
        $ext1 = new FooTypeBarExtension();
        $ext2 = new FooTypeBazExtension();
        $resolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface');

        $this->extension2->addType($type);
        $this->extension1->addTypeExtension($ext1);
        $this->extension2->addTypeExtension($ext2);

        $this->resolvedTypeFactory->expects($this->once())
            ->method('createResolvedType')
            ->with($type, array($ext1, $ext2))
            ->will($this->returnValue($resolvedType));

        $resolvedType->expects($this->any())
            ->method('getName')
            ->will($this->returnValue('foo'));

        $this->assertSame($resolvedType, $this->registry->getType('foo'));
    }

    public function testGetTypeConnectsParent()
    {
        $parentType = new FooType();
        $type = new FooSubType();
        $parentResolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface');
        $resolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface');

        $this->extension1->addType($parentType);
        $this->extension2->addType($type);

        $this->resolvedTypeFactory->expects($this->at(0))
            ->method('createResolvedType')
            ->with($parentType)
            ->will($this->returnValue($parentResolvedType));

        $this->resolvedTypeFactory->expects($this->at(1))
            ->method('createResolvedType')
            ->with($type, array(), $parentResolvedType)
            ->will($this->returnValue($resolvedType));

        $parentResolvedType->expects($this->any())
            ->method('getName')
            ->will($this->returnValue('foo'));

        $resolvedType->expects($this->any())
            ->method('getName')
            ->will($this->returnValue('foo_sub_type'));

        $this->assertSame($resolvedType, $this->registry->getType('foo_sub_type'));
    }

    public function testGetTypeConnectsParentIfGetParentReturnsInstance()
    {
        $type = new FooSubTypeWithParentInstance();
        $parentResolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface');
        $resolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface');

        $this->extension1->addType($type);

        $this->resolvedTypeFactory->expects($this->at(0))
            ->method('createResolvedType')
            ->with($this->isInstanceOf('Symfony\Component\Form\Tests\Fixtures\FooType'))
            ->will($this->returnValue($parentResolvedType));

        $this->resolvedTypeFactory->expects($this->at(1))
            ->method('createResolvedType')
            ->with($type, array(), $parentResolvedType)
            ->will($this->returnValue($resolvedType));

        $parentResolvedType->expects($this->any())
            ->method('getName')
            ->will($this->returnValue('foo'));

        $resolvedType->expects($this->any())
            ->method('getName')
            ->will($this->returnValue('foo_sub_type_parent_instance'));

        $this->assertSame($resolvedType, $this->registry->getType('foo_sub_type_parent_instance'));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException
     */
    public function testGetTypeThrowsExceptionIfParentNotFound()
    {
        $type = new FooSubType();

        $this->extension1->addType($type);

        $this->registry->getType($type);
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException
     */
    public function testGetTypeThrowsExceptionIfTypeNotFound()
    {
        $this->registry->getType('bar');
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException
     */
    public function testGetTypeThrowsExceptionIfNoString()
    {
        $this->registry->getType(array());
    }

    public function testHasTypeAfterLoadingFromExtension()
    {
        $type = new FooType();
        $resolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface');

        $this->resolvedTypeFactory->expects($this->once())
            ->method('createResolvedType')
            ->with($type)
            ->will($this->returnValue($resolvedType));

        $resolvedType->expects($this->any())
            ->method('getName')
            ->will($this->returnValue('foo'));

        $this->assertFalse($this->registry->hasType('foo'));

        $this->extension2->addType($type);

        $this->assertTrue($this->registry->hasType('foo'));
    }

    public function testGetTypeGuesser()
    {
        $expectedGuesser = new FormTypeGuesserChain(array($this->guesser1, $this->guesser2));

        $this->assertEquals($expectedGuesser, $this->registry->getTypeGuesser());

        $registry = new FormRegistry(
            array($this->getMock('Symfony\Component\Form\FormExtensionInterface')),
            $this->resolvedTypeFactory);

        $this->assertNull($registry->getTypeGuesser());
    }

    public function testGetExtensions()
    {
        $expectedExtensions = array($this->extension1, $this->extension2);

        $this->assertEquals($expectedExtensions, $this->registry->getExtensions());
    }
}
PK��Z]�9�}}9test/Form/Symfony/Component/Form/Tests/FormConfigTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests;

use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\Form\FormConfigBuilder;
use Symfony\Component\Form\Exception\InvalidArgumentException;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class FormConfigTest extends \PHPUnit_Framework_TestCase
{
    public function getHtml4Ids()
    {
        return array(
            array('z0', true),
            array('A0', true),
            array('A9', true),
            array('Z0', true),
            array('#', false),
            array('a#', false),
            array('a$', false),
            array('a%', false),
            array('a ', false),
            array("a\t", false),
            array("a\n", false),
            array('a-', true),
            array('a_', true),
            array('a:', true),
            // Periods are allowed by the HTML4 spec, but disallowed by us
            // because they break the generated property paths
            array('a.', false),
            // Contrary to the HTML4 spec, we allow names starting with a
            // number, otherwise naming fields by collection indices is not
            // possible.
            // For root forms, leading digits will be stripped from the
            // "id" attribute to produce valid HTML4.
            array('0', true),
            array('9', true),
            // Contrary to the HTML4 spec, we allow names starting with an
            // underscore, since this is already a widely used practice in
            // Symfony2.
            // For root forms, leading underscores will be stripped from the
            // "id" attribute to produce valid HTML4.
            array('_', true),
            // Integers are allowed
            array(0, true),
            array(123, true),
            // NULL is allowed
            array(null, true),
            // Other types are not
            array(1.23, false),
            array(5., false),
            array(true, false),
            array(new \stdClass(), false),
        );
    }

    /**
     * @dataProvider getHtml4Ids
     */
    public function testNameAcceptsOnlyNamesValidAsIdsInHtml4($name, $accepted)
    {
        $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');

        try {
            new FormConfigBuilder($name, null, $dispatcher);
            if (!$accepted) {
                $this->fail(sprintf('The value "%s" should not be accepted', $name));
            }
        } catch (UnexpectedTypeException $e) {
            // if the value was not accepted, but should be, rethrow exception
            if ($accepted) {
                throw $e;
            }
        } catch (InvalidArgumentException $e) {
            // if the value was not accepted, but should be, rethrow exception
            if ($accepted) {
                throw $e;
            }
        }
    }

    public function testGetRequestHandlerCreatesNativeRequestHandlerIfNotSet()
    {
        $config = $this->getConfigBuilder()->getFormConfig();

        $this->assertInstanceOf('Symfony\Component\Form\NativeRequestHandler', $config->getRequestHandler());
    }

    public function testGetRequestHandlerReusesNativeRequestHandlerInstance()
    {
        $config1 = $this->getConfigBuilder()->getFormConfig();
        $config2 = $this->getConfigBuilder()->getFormConfig();

        $this->assertSame($config1->getRequestHandler(), $config2->getRequestHandler());
    }

    public function testSetMethodAllowsGet()
    {
        $this->getConfigBuilder()->setMethod('GET');
    }

    public function testSetMethodAllowsPost()
    {
        $this->getConfigBuilder()->setMethod('POST');
    }

    public function testSetMethodAllowsPut()
    {
        $this->getConfigBuilder()->setMethod('PUT');
    }

    public function testSetMethodAllowsDelete()
    {
        $this->getConfigBuilder()->setMethod('DELETE');
    }

    public function testSetMethodAllowsPatch()
    {
        $this->getConfigBuilder()->setMethod('PATCH');
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException
     */
    public function testSetMethodDoesNotAllowOtherValues()
    {
        $this->getConfigBuilder()->setMethod('foo');
    }

    private function getConfigBuilder($name = 'name')
    {
        $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');

        return new FormConfigBuilder($name, null, $dispatcher);
    }
}
PK��Z�>)�bbEtest/Form/Symfony/Component/Form/Tests/AbstractRequestHandlerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
abstract class AbstractRequestHandlerTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var \Symfony\Component\Form\RequestHandlerInterface
     */
    protected $requestHandler;

    protected $request;

    protected function setUp()
    {
        $this->requestHandler = $this->getRequestHandler();
        $this->request = null;
    }

    public function methodExceptGetProvider()
    {
        return array(
            array('POST'),
            array('PUT'),
            array('DELETE'),
            array('PATCH'),
        );
    }

    public function methodProvider()
    {
        return array_merge(array(
            array('GET'),
        ), $this->methodExceptGetProvider());
    }

    /**
     * @dataProvider methodProvider
     */
    public function testSubmitIfNameInRequest($method)
    {
        $form = $this->getMockForm('param1', $method);

        $this->setRequestData($method, array(
            'param1' => 'DATA',
        ));

        $form->expects($this->once())
            ->method('submit')
            ->with('DATA', 'PATCH' !== $method);

        $this->requestHandler->handleRequest($form, $this->request);
    }

    /**
     * @dataProvider methodProvider
     */
    public function testDoNotSubmitIfWrongRequestMethod($method)
    {
        $form = $this->getMockForm('param1', $method);

        $otherMethod = 'POST' === $method ? 'PUT' : 'POST';

        $this->setRequestData($otherMethod, array(
            'param1' => 'DATA',
        ));

        $form->expects($this->never())
            ->method('submit');

        $this->requestHandler->handleRequest($form, $this->request);
    }

    /**
     * @dataProvider methodExceptGetProvider
     */
    public function testDoNoSubmitSimpleFormIfNameNotInRequestAndNotGetRequest($method)
    {
        $form = $this->getMockForm('param1', $method, false);

        $this->setRequestData($method, array(
            'paramx' => array(),
        ));

        $form->expects($this->never())
            ->method('submit');

        $this->requestHandler->handleRequest($form, $this->request);
    }

    /**
     * @dataProvider methodExceptGetProvider
     */
    public function testDoNotSubmitCompoundFormIfNameNotInRequestAndNotGetRequest($method)
    {
        $form = $this->getMockForm('param1', $method, true);

        $this->setRequestData($method, array(
            'paramx' => array(),
        ));

        $form->expects($this->never())
            ->method('submit');

        $this->requestHandler->handleRequest($form, $this->request);
    }

    public function testDoNotSubmitIfNameNotInRequestAndGetRequest()
    {
        $form = $this->getMockForm('param1', 'GET');

        $this->setRequestData('GET', array(
            'paramx' => array(),
        ));

        $form->expects($this->never())
            ->method('submit');

        $this->requestHandler->handleRequest($form, $this->request);
    }

    /**
     * @dataProvider methodProvider
     */
    public function testSubmitFormWithEmptyNameIfAtLeastOneFieldInRequest($method)
    {
        $form = $this->getMockForm('', $method);
        $form->expects($this->any())
            ->method('all')
            ->will($this->returnValue(array(
                'param1' => $this->getMockForm('param1'),
                'param2' => $this->getMockForm('param2'),
            )));

        $this->setRequestData($method, $requestData = array(
            'param1' => 'submitted value',
            'paramx' => 'submitted value',
        ));

        $form->expects($this->once())
            ->method('submit')
            ->with($requestData, 'PATCH' !== $method);

        $this->requestHandler->handleRequest($form, $this->request);
    }

    /**
     * @dataProvider methodProvider
     */
    public function testDoNotSubmitFormWithEmptyNameIfNoFieldInRequest($method)
    {
        $form = $this->getMockForm('', $method);
        $form->expects($this->any())
            ->method('all')
            ->will($this->returnValue(array(
                'param1' => $this->getMockForm('param1'),
                'param2' => $this->getMockForm('param2'),
            )));

        $this->setRequestData($method, array(
            'paramx' => 'submitted value',
        ));

        $form->expects($this->never())
            ->method('submit');

        $this->requestHandler->handleRequest($form, $this->request);
    }

    /**
     * @dataProvider methodExceptGetProvider
     */
    public function testMergeParamsAndFiles($method)
    {
        $form = $this->getMockForm('param1', $method);
        $file = $this->getMockFile();

        $this->setRequestData($method, array(
            'param1' => array(
                'field1' => 'DATA',
            ),
        ), array(
            'param1' => array(
                'field2' => $file,
            ),
        ));

        $form->expects($this->once())
            ->method('submit')
            ->with(array(
                'field1' => 'DATA',
                'field2' => $file,
            ), 'PATCH' !== $method);

        $this->requestHandler->handleRequest($form, $this->request);
    }

    /**
     * @dataProvider methodExceptGetProvider
     */
    public function testParamTakesPrecedenceOverFile($method)
    {
        $form = $this->getMockForm('param1', $method);
        $file = $this->getMockFile();

        $this->setRequestData($method, array(
            'param1' => 'DATA',
        ), array(
            'param1' => $file,
        ));

        $form->expects($this->once())
            ->method('submit')
            ->with('DATA', 'PATCH' !== $method);

        $this->requestHandler->handleRequest($form, $this->request);
    }

    /**
     * @dataProvider methodExceptGetProvider
     */
    public function testSubmitFileIfNoParam($method)
    {
        $form = $this->getMockForm('param1', $method);
        $file = $this->getMockFile();

        $this->setRequestData($method, array(
            'param1' => null,
        ), array(
            'param1' => $file,
        ));

        $form->expects($this->once())
            ->method('submit')
            ->with($file, 'PATCH' !== $method);

        $this->requestHandler->handleRequest($form, $this->request);
    }

    abstract protected function setRequestData($method, $data, $files = array());

    abstract protected function getRequestHandler();

    abstract protected function getMockFile();

    protected function getMockForm($name, $method = null, $compound = true)
    {
        $config = $this->getMock('Symfony\Component\Form\FormConfigInterface');
        $config->expects($this->any())
            ->method('getMethod')
            ->will($this->returnValue($method));
        $config->expects($this->any())
            ->method('getCompound')
            ->will($this->returnValue($compound));

        $form = $this->getMock('Symfony\Component\Form\Test\FormInterface');
        $form->expects($this->any())
            ->method('getName')
            ->will($this->returnValue($name));
        $form->expects($this->any())
            ->method('getConfig')
            ->will($this->returnValue($config));

        return $form;
    }
}
PK��Zū@d22?test/Form/Symfony/Component/Form/Tests/ResolvedFormTypeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests;

use Symfony\Component\Form\ResolvedFormType;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\Form;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ResolvedFormTypeTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $dispatcher;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $factory;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $dataMapper;
    private $parentType;
    private $type;
    private $extension1;
    private $extension2;
    private $parentResolvedType;
    private $resolvedType;

    protected function setUp()
    {
        $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
        $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface');
        $this->dataMapper = $this->getMock('Symfony\Component\Form\DataMapperInterface');
        $this->parentType = $this->getMockFormType();
        $this->type = $this->getMockFormType();
        $this->extension1 = $this->getMockFormTypeExtension();
        $this->extension2 = $this->getMockFormTypeExtension();
        $this->parentResolvedType = new ResolvedFormType($this->parentType);
        $this->resolvedType = new ResolvedFormType($this->type, array($this->extension1, $this->extension2), $this->parentResolvedType);
    }

    public function testGetOptionsResolver()
    {
        if (version_compare(\PHPUnit_Runner_Version::id(), '3.7', '<')) {
            $this->markTestSkipped('This test requires PHPUnit 3.7.');
        }

        $test = $this;
        $i = 0;

        $assertIndexAndAddOption = function ($index, $option, $default) use (&$i, $test) {
            return function (OptionsResolverInterface $resolver) use (&$i, $test, $index, $option, $default) {
                /* @var \PHPUnit_Framework_TestCase $test */
                $test->assertEquals($index, $i, 'Executed at index '.$index);

                ++$i;

                $resolver->setDefaults(array($option => $default));
            };
        };

        // First the default options are generated for the super type
        $this->parentType->expects($this->once())
            ->method('setDefaultOptions')
            ->will($this->returnCallback($assertIndexAndAddOption(0, 'a', 'a_default')));

        // The form type itself
        $this->type->expects($this->once())
            ->method('setDefaultOptions')
            ->will($this->returnCallback($assertIndexAndAddOption(1, 'b', 'b_default')));

        // And its extensions
        $this->extension1->expects($this->once())
            ->method('setDefaultOptions')
            ->will($this->returnCallback($assertIndexAndAddOption(2, 'c', 'c_default')));

        $this->extension2->expects($this->once())
            ->method('setDefaultOptions')
            ->will($this->returnCallback($assertIndexAndAddOption(3, 'd', 'd_default')));

        $givenOptions = array('a' => 'a_custom', 'c' => 'c_custom');
        $resolvedOptions = array('a' => 'a_custom', 'b' => 'b_default', 'c' => 'c_custom', 'd' => 'd_default');

        $resolver = $this->resolvedType->getOptionsResolver();

        $this->assertEquals($resolvedOptions, $resolver->resolve($givenOptions));
    }

    public function testCreateBuilder()
    {
        if (version_compare(\PHPUnit_Runner_Version::id(), '3.7', '<')) {
            $this->markTestSkipped('This test requires PHPUnit 3.7.');
        }

        $givenOptions = array('a' => 'a_custom', 'c' => 'c_custom');
        $resolvedOptions = array('a' => 'a_custom', 'b' => 'b_default', 'c' => 'c_custom', 'd' => 'd_default');
        $optionsResolver = $this->getMock('Symfony\Component\OptionsResolver\OptionsResolverInterface');

        $this->resolvedType = $this->getMockBuilder('Symfony\Component\Form\ResolvedFormType')
            ->setConstructorArgs(array($this->type, array($this->extension1, $this->extension2), $this->parentResolvedType))
            ->setMethods(array('getOptionsResolver'))
            ->getMock();

        $this->resolvedType->expects($this->once())
            ->method('getOptionsResolver')
            ->will($this->returnValue($optionsResolver));

        $optionsResolver->expects($this->once())
            ->method('resolve')
            ->with($givenOptions)
            ->will($this->returnValue($resolvedOptions));

        $factory = $this->getMockFormFactory();
        $builder = $this->resolvedType->createBuilder($factory, 'name', $givenOptions);

        $this->assertSame($this->resolvedType, $builder->getType());
        $this->assertSame($resolvedOptions, $builder->getOptions());
        $this->assertNull($builder->getDataClass());
    }

    public function testCreateBuilderWithDataClassOption()
    {
        if (version_compare(\PHPUnit_Runner_Version::id(), '3.7', '<')) {
            $this->markTestSkipped('This test requires PHPUnit 3.7.');
        }

        $givenOptions = array('data_class' => 'Foo');
        $resolvedOptions = array('data_class' => '\stdClass');
        $optionsResolver = $this->getMock('Symfony\Component\OptionsResolver\OptionsResolverInterface');

        $this->resolvedType = $this->getMockBuilder('Symfony\Component\Form\ResolvedFormType')
            ->setConstructorArgs(array($this->type, array($this->extension1, $this->extension2), $this->parentResolvedType))
            ->setMethods(array('getOptionsResolver'))
            ->getMock();

        $this->resolvedType->expects($this->once())
            ->method('getOptionsResolver')
            ->will($this->returnValue($optionsResolver));

        $optionsResolver->expects($this->once())
            ->method('resolve')
            ->with($givenOptions)
            ->will($this->returnValue($resolvedOptions));

        $factory = $this->getMockFormFactory();
        $builder = $this->resolvedType->createBuilder($factory, 'name', $givenOptions);

        $this->assertSame($this->resolvedType, $builder->getType());
        $this->assertSame($resolvedOptions, $builder->getOptions());
        $this->assertSame('\stdClass', $builder->getDataClass());
    }

    public function testBuildForm()
    {
        if (version_compare(\PHPUnit_Runner_Version::id(), '3.7', '<')) {
            $this->markTestSkipped('This test requires PHPUnit 3.7.');
        }

        $test = $this;
        $i = 0;

        $assertIndex = function ($index) use (&$i, $test) {
            return function () use (&$i, $test, $index) {
                /* @var \PHPUnit_Framework_TestCase $test */
                $test->assertEquals($index, $i, 'Executed at index '.$index);

                ++$i;
            };
        };

        $options = array('a' => 'Foo', 'b' => 'Bar');
        $builder = $this->getMock('Symfony\Component\Form\Test\FormBuilderInterface');

        // First the form is built for the super type
        $this->parentType->expects($this->once())
            ->method('buildForm')
            ->with($builder, $options)
            ->will($this->returnCallback($assertIndex(0)));

        // Then the type itself
        $this->type->expects($this->once())
            ->method('buildForm')
            ->with($builder, $options)
            ->will($this->returnCallback($assertIndex(1)));

        // Then its extensions
        $this->extension1->expects($this->once())
            ->method('buildForm')
            ->with($builder, $options)
            ->will($this->returnCallback($assertIndex(2)));

        $this->extension2->expects($this->once())
            ->method('buildForm')
            ->with($builder, $options)
            ->will($this->returnCallback($assertIndex(3)));

        $this->resolvedType->buildForm($builder, $options);
    }

    public function testCreateView()
    {
        $form = $this->getMock('Symfony\Component\Form\Test\FormInterface');

        $view = $this->resolvedType->createView($form);

        $this->assertInstanceOf('Symfony\Component\Form\FormView', $view);
        $this->assertNull($view->parent);
    }

    public function testCreateViewWithParent()
    {
        $form = $this->getMock('Symfony\Component\Form\Test\FormInterface');
        $parentView = $this->getMock('Symfony\Component\Form\FormView');

        $view = $this->resolvedType->createView($form, $parentView);

        $this->assertInstanceOf('Symfony\Component\Form\FormView', $view);
        $this->assertSame($parentView, $view->parent);
    }

    public function testBuildView()
    {
        $options = array('a' => '1', 'b' => '2');
        $form = $this->getMock('Symfony\Component\Form\Test\FormInterface');
        $view = $this->getMock('Symfony\Component\Form\FormView');

        $test = $this;
        $i = 0;

        $assertIndex = function ($index) use (&$i, $test) {
            return function () use (&$i, $test, $index) {
                /* @var \PHPUnit_Framework_TestCase $test */
                $test->assertEquals($index, $i, 'Executed at index '.$index);

                ++$i;
            };
        };

        // First the super type
        $this->parentType->expects($this->once())
            ->method('buildView')
            ->with($view, $form, $options)
            ->will($this->returnCallback($assertIndex(0)));

        // Then the type itself
        $this->type->expects($this->once())
            ->method('buildView')
            ->with($view, $form, $options)
            ->will($this->returnCallback($assertIndex(1)));

        // Then its extensions
        $this->extension1->expects($this->once())
            ->method('buildView')
            ->with($view, $form, $options)
            ->will($this->returnCallback($assertIndex(2)));

        $this->extension2->expects($this->once())
            ->method('buildView')
            ->with($view, $form, $options)
            ->will($this->returnCallback($assertIndex(3)));

        $this->resolvedType->buildView($view, $form, $options);
    }

    public function testFinishView()
    {
        $options = array('a' => '1', 'b' => '2');
        $form = $this->getMock('Symfony\Component\Form\Test\FormInterface');
        $view = $this->getMock('Symfony\Component\Form\FormView');

        $test = $this;
        $i = 0;

        $assertIndex = function ($index) use (&$i, $test) {
            return function () use (&$i, $test, $index) {
                /* @var \PHPUnit_Framework_TestCase $test */
                $test->assertEquals($index, $i, 'Executed at index '.$index);

                ++$i;
            };
        };

        // First the super type
        $this->parentType->expects($this->once())
            ->method('finishView')
            ->with($view, $form, $options)
            ->will($this->returnCallback($assertIndex(0)));

        // Then the type itself
        $this->type->expects($this->once())
            ->method('finishView')
            ->with($view, $form, $options)
            ->will($this->returnCallback($assertIndex(1)));

        // Then its extensions
        $this->extension1->expects($this->once())
            ->method('finishView')
            ->with($view, $form, $options)
            ->will($this->returnCallback($assertIndex(2)));

        $this->extension2->expects($this->once())
            ->method('finishView')
            ->with($view, $form, $options)
            ->will($this->returnCallback($assertIndex(3)));

        $this->resolvedType->finishView($view, $form, $options);
    }

    /**
     * @return \PHPUnit_Framework_MockObject_MockObject
     */
    private function getMockFormType()
    {
        return $this->getMock('Symfony\Component\Form\FormTypeInterface');
    }

    /**
     * @return \PHPUnit_Framework_MockObject_MockObject
     */
    private function getMockFormTypeExtension()
    {
        return $this->getMock('Symfony\Component\Form\FormTypeExtensionInterface');
    }

    /**
     * @return \PHPUnit_Framework_MockObject_MockObject
     */
    private function getMockFormFactory()
    {
        return $this->getMock('Symfony\Component\Form\FormFactoryInterface');
    }

    /**
     * @param string $name
     * @param array $options
     *
     * @return FormBuilder
     */
    protected function getBuilder($name = 'name', array $options = array())
    {
        return new FormBuilder($name, null, $this->dispatcher, $this->factory, $options);
    }
}
PK��ZO� )KKBtest/Form/Symfony/Component/Form/Tests/FormIntegrationTestCase.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests;

use Symfony\Component\Form\Test\FormIntegrationTestCase as BaseFormIntegrationTestCase;

/**
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use Symfony\Component\Form\Test\FormIntegrationTestCase instead.
 */
abstract class FormIntegrationTestCase extends BaseFormIntegrationTestCase
{
}
PK��Z��K)ooFtest/Form/Symfony/Component/Form/Tests/CompoundFormPerformanceTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class CompoundFormPerformanceTest extends \Symfony\Component\Form\Tests\FormPerformanceTestCase
{
    /**
     * Create a compound form multiple times, as happens in a collection form
     *
     * @group benchmark
     */
    public function testArrayBasedForm()
    {
        $this->setMaxRunningTime(1);

        for ($i = 0; $i < 40; ++$i) {
            $form = $this->factory->createBuilder('form')
                ->add('firstName', 'text')
                ->add('lastName', 'text')
                ->add('gender', 'choice', array(
                    'choices' => array('male' => 'Male', 'female' => 'Female'),
                    'required' => false,
                ))
                ->add('age', 'number')
                ->add('birthDate', 'birthday')
                ->add('city', 'choice', array(
                    // simulate 300 different cities
                    'choices' => range(1, 300),
                ))
                ->getForm();

            // load the form into a view
            $form->createView();
        }
    }
}
PK��Ztٴ��;test/Form/Symfony/Component/Form/Tests/FormRendererTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests;

class FormRendererTest extends \PHPUnit_Framework_TestCase
{
    public function testHumanize()
    {
        $renderer = $this->getMockBuilder('Symfony\Component\Form\FormRenderer')
            ->setMethods(null)
            ->disableOriginalConstructor()
            ->getMock()
        ;

        $this->assertEquals('Is active', $renderer->humanize('is_active'));
        $this->assertEquals('Is active', $renderer->humanize('isActive'));
    }
}
PK��Z�d�!!Ctest/Form/Symfony/Component/Form/Tests/NativeRequestHandlerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests;

use Symfony\Component\Form\NativeRequestHandler;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class NativeRequestHandlerTest extends AbstractRequestHandlerTest
{
    private static $serverBackup;

    public static function setUpBeforeClass()
    {
        self::$serverBackup = $_SERVER;
    }

    protected function setUp()
    {
        parent::setUp();

        $_GET = array();
        $_POST = array();
        $_FILES = array();
        $_SERVER = array(
            // PHPUnit needs this entry
            'SCRIPT_NAME' => self::$serverBackup['SCRIPT_NAME'],
        );
    }

    protected function tearDown()
    {
        parent::tearDown();

        $_GET = array();
        $_POST = array();
        $_FILES = array();
        $_SERVER = self::$serverBackup;
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException
     */
    public function testRequestShouldBeNull()
    {
        $this->requestHandler->handleRequest($this->getMockForm('name', 'GET'), 'request');
    }

    public function testMethodOverrideHeaderTakesPrecedenceIfPost()
    {
        $form = $this->getMockForm('param1', 'PUT');

        $this->setRequestData('POST', array(
            'param1' => 'DATA',
        ));

        $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] = 'PUT';

        $form->expects($this->once())
            ->method('submit')
            ->with('DATA');

        $this->requestHandler->handleRequest($form, $this->request);
    }

    public function testConvertEmptyUploadedFilesToNull()
    {
        $form = $this->getMockForm('param1', 'POST', false);

        $this->setRequestData('POST', array(), array('param1' => array(
            'name' => '',
            'type' => '',
            'tmp_name' => '',
            'error' => UPLOAD_ERR_NO_FILE,
            'size' => 0
        )));

        $form->expects($this->once())
            ->method('submit')
            ->with($this->identicalTo(null));

        $this->requestHandler->handleRequest($form, $this->request);
    }

    public function testFixBuggyFilesArray()
    {
        $form = $this->getMockForm('param1', 'POST', false);

        $this->setRequestData('POST', array(), array('param1' => array(
            'name' => array(
                'field' => 'upload.txt',
            ),
            'type' => array(
                'field' => 'text/plain',
            ),
            'tmp_name' => array(
                'field' => 'owfdskjasdfsa',
            ),
            'error' => array(
                'field' => UPLOAD_ERR_OK,
            ),
            'size' => array(
                'field' => 100,
            ),
        )));

        $form->expects($this->once())
            ->method('submit')
            ->with(array(
                'field' => array(
                    'name' => 'upload.txt',
                    'type' => 'text/plain',
                    'tmp_name' => 'owfdskjasdfsa',
                    'error' => UPLOAD_ERR_OK,
                    'size' => 100,
                ),
            ));

        $this->requestHandler->handleRequest($form, $this->request);
    }

    public function testFixBuggyNestedFilesArray()
    {
        $form = $this->getMockForm('param1', 'POST');

        $this->setRequestData('POST', array(), array('param1' => array(
            'name' => array(
                'field' => array('subfield' => 'upload.txt'),
            ),
            'type' => array(
                'field' => array('subfield' => 'text/plain'),
            ),
            'tmp_name' => array(
                'field' => array('subfield' => 'owfdskjasdfsa'),
            ),
            'error' => array(
                'field' => array('subfield' => UPLOAD_ERR_OK),
            ),
            'size' => array(
                'field' => array('subfield' => 100),
            ),
        )));

        $form->expects($this->once())
            ->method('submit')
            ->with(array(
                'field' => array(
                    'subfield' => array(
                        'name' => 'upload.txt',
                        'type' => 'text/plain',
                        'tmp_name' => 'owfdskjasdfsa',
                        'error' => UPLOAD_ERR_OK,
                        'size' => 100,
                    ),
                ),
            ));

        $this->requestHandler->handleRequest($form, $this->request);
    }

    public function testMethodOverrideHeaderIgnoredIfNotPost()
    {
        $form = $this->getMockForm('param1', 'POST');

        $this->setRequestData('GET', array(
                'param1' => 'DATA',
            ));

        $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] = 'PUT';

        $form->expects($this->never())
            ->method('submit');

        $this->requestHandler->handleRequest($form, $this->request);
    }

    protected function setRequestData($method, $data, $files = array())
    {
        if ('GET' === $method) {
            $_GET = $data;
            $_FILES = array();
        } else {
            $_POST = $data;
            $_FILES = $files;
        }

        $_SERVER = array(
            'REQUEST_METHOD' => $method,
            // PHPUnit needs this entry
            'SCRIPT_NAME' => self::$serverBackup['SCRIPT_NAME'],
        );
    }

    protected function getRequestHandler()
    {
        return new NativeRequestHandler();
    }

    protected function getMockFile()
    {
        return array(
            'name' => 'upload.txt',
            'type' => 'text/plain',
            'tmp_name' => 'owfdskjasdfsa',
            'error' => UPLOAD_ERR_OK,
            'size' => 100,
        );
    }
}
PK��Z�����:test/Form/Symfony/Component/Form/Tests/FormBuilderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests;

use Symfony\Component\Form\FormBuilder;

class FormBuilderTest extends \PHPUnit_Framework_TestCase
{
    private $dispatcher;

    private $factory;

    private $builder;

    protected function setUp()
    {
        $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
        $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface');
        $this->builder = new FormBuilder('name', null, $this->dispatcher, $this->factory);
    }

    protected function tearDown()
    {
        $this->dispatcher = null;
        $this->factory = null;
        $this->builder = null;
    }

    /**
     * Changing the name is not allowed, otherwise the name and property path
     * are not synchronized anymore
     *
     * @see FormType::buildForm
     */
    public function testNoSetName()
    {
        $this->assertFalse(method_exists($this->builder, 'setName'));
    }

    public function testAddNameNoStringAndNoInteger()
    {
        $this->setExpectedException('Symfony\Component\Form\Exception\UnexpectedTypeException');
        $this->builder->add(true);
    }

    public function testAddTypeNoString()
    {
        $this->setExpectedException('Symfony\Component\Form\Exception\UnexpectedTypeException');
        $this->builder->add('foo', 1234);
    }

    public function testAddWithGuessFluent()
    {
        $this->builder = new FormBuilder('name', 'stdClass', $this->dispatcher, $this->factory);
        $builder = $this->builder->add('foo');
        $this->assertSame($builder, $this->builder);
    }

    public function testAddIsFluent()
    {
        $builder = $this->builder->add('foo', 'text', array('bar' => 'baz'));
        $this->assertSame($builder, $this->builder);
    }

    public function testAdd()
    {
        $this->assertFalse($this->builder->has('foo'));
        $this->builder->add('foo', 'text');
        $this->assertTrue($this->builder->has('foo'));
    }

    public function testAddIntegerName()
    {
        $this->assertFalse($this->builder->has(0));
        $this->builder->add(0, 'text');
        $this->assertTrue($this->builder->has(0));
    }

    public function testAll()
    {
        $this->factory->expects($this->once())
            ->method('createNamedBuilder')
            ->with('foo', 'text')
            ->will($this->returnValue(new FormBuilder('foo', null, $this->dispatcher, $this->factory)));

        $this->assertCount(0, $this->builder->all());
        $this->assertFalse($this->builder->has('foo'));

        $this->builder->add('foo', 'text');
        $children = $this->builder->all();

        $this->assertTrue($this->builder->has('foo'));
        $this->assertCount(1, $children);
        $this->assertArrayHasKey('foo', $children);
    }

    /*
     * https://github.com/symfony/symfony/issues/4693
     */
    public function testMaintainOrderOfLazyAndExplicitChildren()
    {
        $this->builder->add('foo', 'text');
        $this->builder->add($this->getFormBuilder('bar'));
        $this->builder->add('baz', 'text');

        $children = $this->builder->all();

        $this->assertSame(array('foo', 'bar', 'baz'), array_keys($children));
    }

    public function testAddFormType()
    {
        $this->assertFalse($this->builder->has('foo'));
        $this->builder->add('foo', $this->getMock('Symfony\Component\Form\FormTypeInterface'));
        $this->assertTrue($this->builder->has('foo'));
    }

    public function testRemove()
    {
        $this->builder->add('foo', 'text');
        $this->builder->remove('foo');
        $this->assertFalse($this->builder->has('foo'));
    }

    public function testRemoveUnknown()
    {
        $this->builder->remove('foo');
        $this->assertFalse($this->builder->has('foo'));
    }

    // https://github.com/symfony/symfony/pull/4826
    public function testRemoveAndGetForm()
    {
        $this->builder->add('foo', 'text');
        $this->builder->remove('foo');
        $form = $this->builder->getForm();
        $this->assertInstanceOf('Symfony\Component\Form\Form', $form);
    }

    public function testCreateNoTypeNo()
    {
        $this->factory->expects($this->once())
            ->method('createNamedBuilder')
            ->with('foo', 'text', null, array())
        ;

        $this->builder->create('foo');
    }

    public function testGetUnknown()
    {
        $this->setExpectedException('Symfony\Component\Form\Exception\InvalidArgumentException', 'The child with the name "foo" does not exist.');
        $this->builder->get('foo');
    }

    public function testGetExplicitType()
    {
        $expectedType = 'text';
        $expectedName = 'foo';
        $expectedOptions = array('bar' => 'baz');

        $this->factory->expects($this->once())
            ->method('createNamedBuilder')
            ->with($expectedName, $expectedType, null, $expectedOptions)
            ->will($this->returnValue($this->getFormBuilder()));

        $this->builder->add($expectedName, $expectedType, $expectedOptions);
        $builder = $this->builder->get($expectedName);

        $this->assertNotSame($builder, $this->builder);
    }

    public function testGetGuessedType()
    {
        $expectedName = 'foo';
        $expectedOptions = array('bar' => 'baz');

        $this->factory->expects($this->once())
            ->method('createBuilderForProperty')
            ->with('stdClass', $expectedName, null, $expectedOptions)
            ->will($this->returnValue($this->getFormBuilder()));

        $this->builder = new FormBuilder('name', 'stdClass', $this->dispatcher, $this->factory);
        $this->builder->add($expectedName, null, $expectedOptions);
        $builder = $this->builder->get($expectedName);

        $this->assertNotSame($builder, $this->builder);
    }

    public function testGetFormConfigErasesReferences()
    {
        $builder = new FormBuilder('name', null, $this->dispatcher, $this->factory);
        $builder->add(new FormBuilder('child', null, $this->dispatcher, $this->factory));

        $config = $builder->getFormConfig();
        $reflClass = new \ReflectionClass($config);
        $children = $reflClass->getProperty('children');
        $unresolvedChildren = $reflClass->getProperty('unresolvedChildren');

        $children->setAccessible(true);
        $unresolvedChildren->setAccessible(true);

        $this->assertEmpty($children->getValue($config));
        $this->assertEmpty($unresolvedChildren->getValue($config));
    }

    private function getFormBuilder($name = 'name')
    {
        $mock = $this->getMockBuilder('Symfony\Component\Form\FormBuilder')
            ->disableOriginalConstructor()
            ->getMock();

        $mock->expects($this->any())
            ->method('getName')
            ->will($this->returnValue($name));

        return $mock;
    }
}
PK��ZRmhZTZT@test/Form/Symfony/Component/Form/Tests/AbstractDivLayoutTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests;

use Symfony\Component\Form\FormError;
use Symfony\Component\Form\Tests\Fixtures\AlternatingRowType;
use Symfony\Component\Security\Csrf\CsrfToken;

abstract class AbstractDivLayoutTest extends AbstractLayoutTest
{
    public function testRow()
    {
        $form = $this->factory->createNamed('name', 'text');
        $form->addError(new FormError('[trans]Error![/trans]'));
        $view = $form->createView();
        $html = $this->renderRow($view);

        $this->assertMatchesXpath($html,
'/div
    [
        ./label[@for="name"]
        /following-sibling::ul
            [./li[.="[trans]Error![/trans]"]]
            [count(./li)=1]
        /following-sibling::input[@id="name"]
    ]
'
        );
    }

    public function testRowOverrideVariables()
    {
        $view = $this->factory->createNamed('name', 'text')->createView();
        $html = $this->renderRow($view, array(
            'attr' => array('class' => 'my&class'),
            'label' => 'foo&bar',
            'label_attr' => array('class' => 'my&label&class'),
        ));

        $this->assertMatchesXpath($html,
'/div
    [
        ./label[@for="name"][@class="my&label&class required"][.="[trans]foo&bar[/trans]"]
        /following-sibling::input[@id="name"][@class="my&class"]
    ]
'
        );
    }

    public function testRepeatedRow()
    {
        $form = $this->factory->createNamed('name', 'repeated');
        $form->addError(new FormError('[trans]Error![/trans]'));
        $view = $form->createView();
        $html = $this->renderRow($view);

        // The errors of the form are not rendered by intention!
        // In practice, repeated fields cannot have errors as all errors
        // on them are mapped to the first child.
        // (see RepeatedTypeValidatorExtension)

        $this->assertMatchesXpath($html,
'/div
    [
        ./label[@for="name_first"]
        /following-sibling::input[@id="name_first"]
    ]
/following-sibling::div
    [
        ./label[@for="name_second"]
        /following-sibling::input[@id="name_second"]
    ]
'
        );
    }

    public function testButtonRow()
    {
        $form = $this->factory->createNamed('name', 'button');
        $view = $form->createView();
        $html = $this->renderRow($view);

        $this->assertMatchesXpath($html,
'/div
    [
        ./button[@type="button"][@name="name"]
    ]
    [count(//label)=0]
'
        );
    }

    public function testRest()
    {
        $view = $this->factory->createNamedBuilder('name', 'form')
            ->add('field1', 'text')
            ->add('field2', 'repeated')
            ->add('field3', 'text')
            ->add('field4', 'text')
            ->getForm()
            ->createView();

        // Render field2 row -> does not implicitly call renderWidget because
        // it is a repeated field!
        $this->renderRow($view['field2']);

        // Render field3 widget
        $this->renderWidget($view['field3']);

        // Rest should only contain field1 and field4
        $html = $this->renderRest($view);

        $this->assertMatchesXpath($html,
'/div
    [
        ./label[@for="name_field1"]
        /following-sibling::input[@type="text"][@id="name_field1"]
    ]
/following-sibling::div
    [
        ./label[@for="name_field4"]
        /following-sibling::input[@type="text"][@id="name_field4"]
    ]
    [count(../div)=2]
    [count(..//label)=2]
    [count(..//input)=3]
/following-sibling::input
    [@type="hidden"]
    [@id="name__token"]
'
        );
    }

    public function testRestWithChildrenForms()
    {
        $child1 = $this->factory->createNamedBuilder('child1', 'form')
            ->add('field1', 'text')
            ->add('field2', 'text');

        $child2 = $this->factory->createNamedBuilder('child2', 'form')
            ->add('field1', 'text')
            ->add('field2', 'text');

        $view = $this->factory->createNamedBuilder('parent', 'form')
            ->add($child1)
            ->add($child2)
            ->getForm()
            ->createView();

        // Render child1.field1 row
        $this->renderRow($view['child1']['field1']);

        // Render child2.field2 widget (remember that widget don't render label)
        $this->renderWidget($view['child2']['field2']);

        // Rest should only contain child1.field2 and child2.field1
        $html = $this->renderRest($view);

        $this->assertMatchesXpath($html,
'/div
    [
        ./label[not(@for)]
        /following-sibling::div[@id="parent_child1"]
            [
                ./div
                    [
                        ./label[@for="parent_child1_field2"]
                        /following-sibling::input[@id="parent_child1_field2"]
                    ]
            ]
    ]

/following-sibling::div
    [
        ./label[not(@for)]
        /following-sibling::div[@id="parent_child2"]
            [
                ./div
                    [
                        ./label[@for="parent_child2_field1"]
                        /following-sibling::input[@id="parent_child2_field1"]
                    ]
            ]
    ]
    [count(//label)=4]
    [count(//input[@type="text"])=2]
/following-sibling::input[@type="hidden"][@id="parent__token"]
'
        );
    }

    public function testRestAndRepeatedWithRow()
    {
        $view = $this->factory->createNamedBuilder('name', 'form')
            ->add('first', 'text')
            ->add('password', 'repeated')
            ->getForm()
            ->createView();

        $this->renderRow($view['password']);

        $html = $this->renderRest($view);

        $this->assertMatchesXpath($html,
'/div
    [
        ./label[@for="name_first"]
        /following-sibling::input[@type="text"][@id="name_first"]
    ]
    [count(.//input)=1]
/following-sibling::input
    [@type="hidden"]
    [@id="name__token"]
'
        );
    }

    public function testRestAndRepeatedWithRowPerChild()
    {
        $view = $this->factory->createNamedBuilder('name', 'form')
            ->add('first', 'text')
            ->add('password', 'repeated')
            ->getForm()
            ->createView();

        $this->renderRow($view['password']['first']);
        $this->renderRow($view['password']['second']);

        $html = $this->renderRest($view);

        $this->assertMatchesXpath($html,
'/div
    [
        ./label[@for="name_first"]
        /following-sibling::input[@type="text"][@id="name_first"]
    ]
    [count(.//input)=1]
    [count(.//label)=1]
/following-sibling::input
    [@type="hidden"]
    [@id="name__token"]
'
        );
    }

    public function testRestAndRepeatedWithWidgetPerChild()
    {
        $view = $this->factory->createNamedBuilder('name', 'form')
            ->add('first', 'text')
            ->add('password', 'repeated')
            ->getForm()
            ->createView();

        // The password form is considered as rendered as all its children
        // are rendered
        $this->renderWidget($view['password']['first']);
        $this->renderWidget($view['password']['second']);

        $html = $this->renderRest($view);

        $this->assertMatchesXpath($html,
'/div
    [
        ./label[@for="name_first"]
        /following-sibling::input[@type="text"][@id="name_first"]
    ]
    [count(//input)=2]
    [count(//label)=1]
/following-sibling::input
    [@type="hidden"]
    [@id="name__token"]
'
        );
    }

    public function testCollection()
    {
        $form = $this->factory->createNamed('name', 'collection', array('a', 'b'), array(
            'type' => 'text',
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
    [
        ./div[./input[@type="text"][@value="a"]]
        /following-sibling::div[./input[@type="text"][@value="b"]]
    ]
    [count(./div[./input])=2]
'
        );
    }

    // https://github.com/symfony/symfony/issues/5038
    public function testCollectionWithAlternatingRowTypes()
    {
        $data = array(
            array('title' => 'a'),
            array('title' => 'b'),
        );
        $form = $this->factory->createNamed('name', 'collection', $data, array(
            'type' => new AlternatingRowType(),
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
    [
        ./div[./div/div/input[@type="text"][@value="a"]]
        /following-sibling::div[./div/div/textarea[.="b"]]
    ]
    [count(./div[./div/div/input])=1]
    [count(./div[./div/div/textarea])=1]
'
        );
    }

    public function testEmptyCollection()
    {
        $form = $this->factory->createNamed('name', 'collection', array(), array(
            'type' => 'text',
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
    [./input[@type="hidden"][@id="name__token"]]
    [count(./div)=0]
'
        );
    }

    public function testCollectionRow()
    {
        $collection = $this->factory->createNamedBuilder(
            'collection',
            'collection',
            array('a', 'b'),
            array('type' => 'text')
        );

        $form = $this->factory->createNamedBuilder('form', 'form')
          ->add($collection)
          ->getForm();

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
    [
        ./div
            [
                ./label[not(@for)]
                /following-sibling::div
                    [
                        ./div
                            [
                                ./label[@for="form_collection_0"]
                                /following-sibling::input[@type="text"][@value="a"]
                            ]
                        /following-sibling::div
                            [
                                ./label[@for="form_collection_1"]
                                /following-sibling::input[@type="text"][@value="b"]
                            ]
                    ]
            ]
        /following-sibling::input[@type="hidden"][@id="form__token"]
    ]
    [count(.//input)=3]
'
        );
    }

    public function testForm()
    {
        $form = $this->factory->createNamedBuilder('name', 'form')
            ->setMethod('PUT')
            ->setAction('http://example.com')
            ->add('firstName', 'text')
            ->add('lastName', 'text')
            ->getForm();

        // include ampersands everywhere to validate escaping
        $html = $this->renderForm($form->createView(), array(
            'id' => 'my&id',
            'attr' => array('class' => 'my&class'),
        ));

        $this->assertMatchesXpath($html,
'/form
    [
        ./input[@type="hidden"][@name="_method"][@value="PUT"]
        /following-sibling::div
            [
                ./div
                    [
                        ./label[@for="name_firstName"]
                        /following-sibling::input[@type="text"][@id="name_firstName"]
                    ]
                /following-sibling::div
                    [
                        ./label[@for="name_lastName"]
                        /following-sibling::input[@type="text"][@id="name_lastName"]
                    ]
                /following-sibling::input[@type="hidden"][@id="name__token"]
            ]
            [count(.//input)=3]
            [@id="my&id"]
            [@class="my&class"]
    ]
    [@method="post"]
    [@action="http://example.com"]
    [@class="my&class"]
'
        );
    }

    public function testFormWidget()
    {
        $form = $this->factory->createNamedBuilder('name', 'form')
            ->add('firstName', 'text')
            ->add('lastName', 'text')
            ->getForm();

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
    [
        ./div
            [
                ./label[@for="name_firstName"]
                /following-sibling::input[@type="text"][@id="name_firstName"]
            ]
        /following-sibling::div
            [
                ./label[@for="name_lastName"]
                /following-sibling::input[@type="text"][@id="name_lastName"]
            ]
        /following-sibling::input[@type="hidden"][@id="name__token"]
    ]
    [count(.//input)=3]
'
        );
    }

    // https://github.com/symfony/symfony/issues/2308
    public function testNestedFormError()
    {
        $form = $this->factory->createNamedBuilder('name', 'form')
            ->add($this->factory
                ->createNamedBuilder('child', 'form', null, array('error_bubbling' => false))
                ->add('grandChild', 'form')
            )
            ->getForm();

        $form->get('child')->addError(new FormError('[trans]Error![/trans]'));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
    [
        ./div/label
        /following-sibling::ul[./li[.="[trans]Error![/trans]"]]
    ]
    [count(.//li[.="[trans]Error![/trans]"])=1]
'
        );
    }

    public function testCsrf()
    {
        $this->csrfTokenManager->expects($this->any())
            ->method('getToken')
            ->will($this->returnValue(new CsrfToken('token_id', 'foo&bar')));

        $form = $this->factory->createNamedBuilder('name', 'form')
            ->add($this->factory
                // No CSRF protection on nested forms
                ->createNamedBuilder('child', 'form')
                ->add($this->factory->createNamedBuilder('grandchild', 'text'))
            )
            ->getForm();

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
    [
        ./div
        /following-sibling::input[@type="hidden"][@id="name__token"][@value="foo&bar"]
    ]
    [count(.//input[@type="hidden"])=1]
'
        );
    }

    public function testRepeated()
    {
        $form = $this->factory->createNamed('name', 'repeated', 'foobar', array(
            'type' => 'text',
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
    [
        ./div
            [
                ./label[@for="name_first"]
                /following-sibling::input[@type="text"][@id="name_first"]
            ]
        /following-sibling::div
            [
                ./label[@for="name_second"]
                /following-sibling::input[@type="text"][@id="name_second"]
            ]
        /following-sibling::input[@type="hidden"][@id="name__token"]
    ]
    [count(.//input)=3]
'
        );
    }

    public function testRepeatedWithCustomOptions()
    {
        $form = $this->factory->createNamed('name', 'repeated', null, array(
            // the global required value cannot be overridden
            'first_options'  => array('label' => 'Test', 'required' => false),
            'second_options' => array('label' => 'Test2')
        ));

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
    [
        ./div
            [
                ./label[@for="name_first"][.="[trans]Test[/trans]"]
                /following-sibling::input[@type="text"][@id="name_first"][@required="required"]
            ]
        /following-sibling::div
            [
                ./label[@for="name_second"][.="[trans]Test2[/trans]"]
                /following-sibling::input[@type="text"][@id="name_second"][@required="required"]
            ]
        /following-sibling::input[@type="hidden"][@id="name__token"]
    ]
    [count(.//input)=3]
'
        );
    }

    public function testSearchInputName()
    {
        $form = $this->factory->createNamedBuilder('full', 'form')
            ->add('name', 'search')
            ->getForm();

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
    [
        ./div
            [
                ./label[@for="full_name"]
                /following-sibling::input[@type="search"][@id="full_name"][@name="full[name]"]
            ]
        /following-sibling::input[@type="hidden"][@id="full__token"]
    ]
    [count(//input)=2]
'
        );
    }

    public function testLabelHasNoId()
    {
        $form = $this->factory->createNamed('name', 'text');
        $html = $this->renderRow($form->createView());

        $this->assertMatchesXpath($html,
'/div
    [
        ./label[@for="name"][not(@id)]
        /following-sibling::input[@id="name"]
    ]
'
        );
    }

    public function testLabelIsNotRenderedWhenSetToFalse()
    {
        $form = $this->factory->createNamed('name', 'text', null, array(
            'label' => false
        ));
        $html = $this->renderRow($form->createView());

        $this->assertMatchesXpath($html,
'/div
    [
        ./input[@id="name"]
    ]
    [count(//label)=0]
'
        );
    }

    /**
     * @dataProvider themeBlockInheritanceProvider
     */
    public function testThemeBlockInheritance($theme)
    {
        $view = $this->factory
            ->createNamed('name', 'email')
            ->createView()
        ;

        $this->setTheme($view, $theme);

        $this->assertMatchesXpath(
            $this->renderWidget($view),
            '/input[@type="email"][@rel="theme"]'
        );
    }

    /**
     * @dataProvider themeInheritanceProvider
     */
    public function testThemeInheritance($parentTheme, $childTheme)
    {
        $child = $this->factory->createNamedBuilder('child', 'form')
            ->add('field', 'text');

        $view = $this->factory->createNamedBuilder('parent', 'form')
            ->add('field', 'text')
            ->add($child)
            ->getForm()
            ->createView()
        ;

        $this->setTheme($view, $parentTheme);
        $this->setTheme($view['child'], $childTheme);

        $this->assertWidgetMatchesXpath($view, array(),
'/div
    [
        ./div
            [
                ./label[.="parent"]
                /following-sibling::input[@type="text"]
            ]
        /following-sibling::div
            [
                ./label[.="child"]
                /following-sibling::div
                    [
                        ./div
                            [
                                ./label[.="child"]
                                /following-sibling::input[@type="text"]
                            ]
                    ]
            ]
        /following-sibling::input[@type="hidden"]
    ]
'
        );
    }

    /**
     * The block "_name_child_label" should be overridden in the theme of the
     * implemented driver.
     */
    public function testCollectionRowWithCustomBlock()
    {
        $collection = array('one', 'two', 'three');
        $form = $this->factory->createNamedBuilder('name', 'collection', $collection)
            ->getForm();

        $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
    [
        ./div[./label[.="Custom label: [trans]0[/trans]"]]
        /following-sibling::div[./label[.="Custom label: [trans]1[/trans]"]]
        /following-sibling::div[./label[.="Custom label: [trans]2[/trans]"]]
    ]
'
        );
    }

    public function testFormEndWithRest()
    {
        $view = $this->factory->createNamedBuilder('name', 'form')
            ->add('field1', 'text')
            ->add('field2', 'text')
            ->getForm()
            ->createView();

        $this->renderWidget($view['field1']);

        // Rest should only contain field2
        $html = $this->renderEnd($view);

        // Insert the start tag, the end tag should be rendered by the helper
        $this->assertMatchesXpath('<form>' . $html,
'/form
    [
        ./div
            [
                ./label[@for="name_field2"]
                /following-sibling::input[@type="text"][@id="name_field2"]
            ]
        /following-sibling::input
            [@type="hidden"]
            [@id="name__token"]
    ]
'
        );
    }

    public function testFormEndWithoutRest()
    {
        $view = $this->factory->createNamedBuilder('name', 'form')
            ->add('field1', 'text')
            ->add('field2', 'text')
            ->getForm()
            ->createView();

        $this->renderWidget($view['field1']);

        // Rest should only contain field2, but isn't rendered
        $html = $this->renderEnd($view, array('render_rest' => false));

        $this->assertEquals('</form>', $html);
    }

    public function testWidgetContainerAttributes()
    {
        $form = $this->factory->createNamed('form', 'form', null, array(
            'attr' => array('class' => 'foobar', 'data-foo' => 'bar'),
        ));

        $form->add('text', 'text');

        $html = $this->renderWidget($form->createView());

        // compare plain HTML to check the whitespace
        $this->assertContains('<div id="form" class="foobar" data-foo="bar">', $html);
    }

    public function testWidgetContainerAttributeNameRepeatedIfTrue()
    {
        $form = $this->factory->createNamed('form', 'form', null, array(
            'attr' => array('foo' => true),
        ));

        $html = $this->renderWidget($form->createView());

        // foo="foo"
        $this->assertContains('<div id="form" foo="foo">', $html);
    }

    public function testWidgetContainerAttributeHiddenIfFalse()
    {
        $form = $this->factory->createNamed('form', 'form', null, array(
            'attr' => array('foo' => false),
        ));

        $html = $this->renderWidget($form->createView());

        // no foo
        $this->assertContains('<div id="form">', $html);
    }
}
PK��Zk/6;test/Form/Symfony/Component/Form/Tests/AbstractFormTest.phpnu�[���<?php

    /*
    * This file is part of the Symfony package.
    *
    * (c) Fabien Potencier <fabien@symfony.com>
    *
    * For the full copyright and license information, please view the LICENSE
    * file that was distributed with this source code.
    */

namespace Symfony\Component\Form\Tests;

use Symfony\Component\Form\FormBuilder;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

abstract class AbstractFormTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var EventDispatcherInterface
     */
    protected $dispatcher;

    /**
     * @var \Symfony\Component\Form\FormFactoryInterface
     */
    protected $factory;

    /**
     * @var \Symfony\Component\Form\FormInterface
     */
    protected $form;

    protected function setUp()
    {
        // We need an actual dispatcher to use the deprecated
        // bindRequest() method
        $this->dispatcher = new EventDispatcher();
        $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface');
        $this->form = $this->createForm();
    }

    protected function tearDown()
    {
        $this->dispatcher = null;
        $this->factory = null;
        $this->form = null;
    }

    /**
     * @return \Symfony\Component\Form\FormInterface
     */
    abstract protected function createForm();

    /**
     * @param string                   $name
     * @param EventDispatcherInterface $dispatcher
     * @param string                   $dataClass
     * @param array                    $options
     *
     * @return FormBuilder
     */
    protected function getBuilder($name = 'name', EventDispatcherInterface $dispatcher = null, $dataClass = null, array $options = array())
    {
        return new FormBuilder($name, $dataClass, $dispatcher ?: $this->dispatcher, $this->factory, $options);
    }

    /**
     * @param  string $name
     *
     * @return \PHPUnit_Framework_MockObject_MockObject
     */
    protected function getMockForm($name = 'name')
    {
        $form = $this->getMock('Symfony\Component\Form\Test\FormInterface');
        $config = $this->getMock('Symfony\Component\Form\FormConfigInterface');

        $form->expects($this->any())
            ->method('getName')
            ->will($this->returnValue($name));
        $form->expects($this->any())
            ->method('getConfig')
            ->will($this->returnValue($config));

        return $form;
    }

    /**
     * @return \PHPUnit_Framework_MockObject_MockObject
     */
    protected function getDataMapper()
    {
        return $this->getMock('Symfony\Component\Form\DataMapperInterface');
    }

    /**
     * @return \PHPUnit_Framework_MockObject_MockObject
     */
    protected function getDataTransformer()
    {
        return $this->getMock('Symfony\Component\Form\DataTransformerInterface');
    }

    /**
     * @return \PHPUnit_Framework_MockObject_MockObject
     */
    protected function getFormValidator()
    {
        return $this->getMock('Symfony\Component\Form\FormValidatorInterface');
    }
}
PK��ZrM�{�{9test/Form/Symfony/Component/Form/Tests/SimpleFormTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests;

use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\PropertyAccess\PropertyPath;
use Symfony\Component\Form\FormConfigBuilder;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\Form\Tests\Fixtures\FixedDataTransformer;
use Symfony\Component\Form\Tests\Fixtures\FixedFilterListener;

class SimpleFormTest_Countable implements \Countable
{
    private $count;

    public function __construct($count)
    {
        $this->count = $count;
    }

    public function count()
    {
        return $this->count;
    }
}

class SimpleFormTest_Traversable implements \IteratorAggregate
{
    private $iterator;

    public function __construct($count)
    {
        $this->iterator = new \ArrayIterator($count > 0 ? array_fill(0, $count, 'Foo') : array());
    }

    public function getIterator()
    {
        return $this->iterator;
    }
}

class SimpleFormTest extends AbstractFormTest
{
    public function testDataIsInitializedToConfiguredValue()
    {
        $model = new FixedDataTransformer(array(
            'default' => 'foo',
        ));
        $view = new FixedDataTransformer(array(
            'foo' => 'bar',
        ));

        $config = new FormConfigBuilder('name', null, $this->dispatcher);
        $config->addViewTransformer($view);
        $config->addModelTransformer($model);
        $config->setData('default');
        $form = new Form($config);

        $this->assertSame('default', $form->getData());
        $this->assertSame('foo', $form->getNormData());
        $this->assertSame('bar', $form->getViewData());
    }

    // https://github.com/symfony/symfony/commit/d4f4038f6daf7cf88ca7c7ab089473cce5ebf7d8#commitcomment-1632879
    public function testDataIsInitializedFromSubmit()
    {
        $mock = $this->getMockBuilder('\stdClass')
            ->setMethods(array('preSetData', 'preSubmit'))
            ->getMock();
        $mock->expects($this->at(0))
            ->method('preSetData');
        $mock->expects($this->at(1))
            ->method('preSubmit');

        $config = new FormConfigBuilder('name', null, $this->dispatcher);
        $config->addEventListener(FormEvents::PRE_SET_DATA, array($mock, 'preSetData'));
        $config->addEventListener(FormEvents::PRE_SUBMIT, array($mock, 'preSubmit'));
        $form = new Form($config);

        // no call to setData() or similar where the object would be
        // initialized otherwise

        $form->submit('foobar');
    }

    // https://github.com/symfony/symfony/pull/7789
    public function testFalseIsConvertedToNull()
    {
        $mock = $this->getMockBuilder('\stdClass')
            ->setMethods(array('preBind'))
            ->getMock();
        $mock->expects($this->once())
            ->method('preBind')
            ->with($this->callback(function ($event) {
                return null === $event->getData();
            }));

        $config = new FormConfigBuilder('name', null, $this->dispatcher);
        $config->addEventListener(FormEvents::PRE_BIND, array($mock, 'preBind'));
        $form = new Form($config);

        $form->bind(false);

        $this->assertTrue($form->isValid());
        $this->assertNull($form->getData());
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\AlreadySubmittedException
     */
    public function testSubmitThrowsExceptionIfAlreadySubmitted()
    {
        $this->form->submit(array());
        $this->form->submit(array());
    }

    public function testSubmitIsIgnoredIfDisabled()
    {
        $form = $this->getBuilder()
            ->setDisabled(true)
            ->setData('initial')
            ->getForm();

        $form->submit('new');

        $this->assertEquals('initial', $form->getData());
        $this->assertTrue($form->isSubmitted());
    }

    public function testNeverRequiredIfParentNotRequired()
    {
        $parent = $this->getBuilder()->setRequired(false)->getForm();
        $child = $this->getBuilder()->setRequired(true)->getForm();

        $child->setParent($parent);

        $this->assertFalse($child->isRequired());
    }

    public function testRequired()
    {
        $parent = $this->getBuilder()->setRequired(true)->getForm();
        $child = $this->getBuilder()->setRequired(true)->getForm();

        $child->setParent($parent);

        $this->assertTrue($child->isRequired());
    }

    public function testNotRequired()
    {
        $parent = $this->getBuilder()->setRequired(true)->getForm();
        $child = $this->getBuilder()->setRequired(false)->getForm();

        $child->setParent($parent);

        $this->assertFalse($child->isRequired());
    }

    public function testAlwaysDisabledIfParentDisabled()
    {
        $parent = $this->getBuilder()->setDisabled(true)->getForm();
        $child = $this->getBuilder()->setDisabled(false)->getForm();

        $child->setParent($parent);

        $this->assertTrue($child->isDisabled());
    }

    public function testDisabled()
    {
        $parent = $this->getBuilder()->setDisabled(false)->getForm();
        $child = $this->getBuilder()->setDisabled(true)->getForm();

        $child->setParent($parent);

        $this->assertTrue($child->isDisabled());
    }

    public function testNotDisabled()
    {
        $parent = $this->getBuilder()->setDisabled(false)->getForm();
        $child = $this->getBuilder()->setDisabled(false)->getForm();

        $child->setParent($parent);

        $this->assertFalse($child->isDisabled());
    }

    public function testGetRootReturnsRootOfParent()
    {
        $parent = $this->getMockForm();
        $parent->expects($this->once())
            ->method('getRoot')
            ->will($this->returnValue('ROOT'));

        $this->form->setParent($parent);

        $this->assertEquals('ROOT', $this->form->getRoot());
    }

    public function testGetRootReturnsSelfIfNoParent()
    {
        $this->assertSame($this->form, $this->form->getRoot());
    }

    public function testEmptyIfEmptyArray()
    {
        $this->form->setData(array());

        $this->assertTrue($this->form->isEmpty());
    }

    public function testEmptyIfEmptyCountable()
    {
        $this->form = new Form(new FormConfigBuilder('name', __NAMESPACE__.'\SimpleFormTest_Countable', $this->dispatcher));

        $this->form->setData(new SimpleFormTest_Countable(0));

        $this->assertTrue($this->form->isEmpty());
    }

    public function testNotEmptyIfFilledCountable()
    {
        $this->form = new Form(new FormConfigBuilder('name', __NAMESPACE__.'\SimpleFormTest_Countable', $this->dispatcher));

        $this->form->setData(new SimpleFormTest_Countable(1));

        $this->assertFalse($this->form->isEmpty());
    }

    public function testEmptyIfEmptyTraversable()
    {
        $this->form = new Form(new FormConfigBuilder('name', __NAMESPACE__.'\SimpleFormTest_Traversable', $this->dispatcher));

        $this->form->setData(new SimpleFormTest_Traversable(0));

        $this->assertTrue($this->form->isEmpty());
    }

    public function testNotEmptyIfFilledTraversable()
    {
        $this->form = new Form(new FormConfigBuilder('name', __NAMESPACE__.'\SimpleFormTest_Traversable', $this->dispatcher));

        $this->form->setData(new SimpleFormTest_Traversable(1));

        $this->assertFalse($this->form->isEmpty());
    }

    public function testEmptyIfNull()
    {
        $this->form->setData(null);

        $this->assertTrue($this->form->isEmpty());
    }

    public function testEmptyIfEmptyString()
    {
        $this->form->setData('');

        $this->assertTrue($this->form->isEmpty());
    }

    public function testNotEmptyIfText()
    {
        $this->form->setData('foobar');

        $this->assertFalse($this->form->isEmpty());
    }

    public function testValidIfSubmitted()
    {
        $form = $this->getBuilder()->getForm();
        $form->submit('foobar');

        $this->assertTrue($form->isValid());
    }

    public function testValidIfSubmittedAndDisabled()
    {
        $form = $this->getBuilder()->setDisabled(true)->getForm();
        $form->submit('foobar');

        $this->assertTrue($form->isValid());
    }

    public function testNotValidIfNotSubmitted()
    {
        $this->assertFalse($this->form->isValid());
    }

    public function testNotValidIfErrors()
    {
        $form = $this->getBuilder()->getForm();
        $form->submit('foobar');
        $form->addError(new FormError('Error!'));

        $this->assertFalse($form->isValid());
    }

    public function testHasErrors()
    {
        $this->form->addError(new FormError('Error!'));

        $this->assertCount(1, $this->form->getErrors());
    }

    public function testHasNoErrors()
    {
        $this->assertCount(0, $this->form->getErrors());
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\AlreadySubmittedException
     */
    public function testSetParentThrowsExceptionIfAlreadySubmitted()
    {
        $this->form->submit(array());
        $this->form->setParent($this->getBuilder('parent')->getForm());
    }

    public function testSubmitted()
    {
        $form = $this->getBuilder()->getForm();
        $form->submit('foobar');

        $this->assertTrue($form->isSubmitted());
    }

    public function testNotSubmitted()
    {
        $this->assertFalse($this->form->isSubmitted());
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\AlreadySubmittedException
     */
    public function testSetDataThrowsExceptionIfAlreadySubmitted()
    {
        $this->form->submit(array());
        $this->form->setData(null);
    }

    public function testSetDataClonesObjectIfNotByReference()
    {
        $data = new \stdClass();
        $form = $this->getBuilder('name', null, '\stdClass')->setByReference(false)->getForm();
        $form->setData($data);

        $this->assertNotSame($data, $form->getData());
        $this->assertEquals($data, $form->getData());
    }

    public function testSetDataDoesNotCloneObjectIfByReference()
    {
        $data = new \stdClass();
        $form = $this->getBuilder('name', null, '\stdClass')->setByReference(true)->getForm();
        $form->setData($data);

        $this->assertSame($data, $form->getData());
    }

    public function testSetDataExecutesTransformationChain()
    {
        // use real event dispatcher now
        $form = $this->getBuilder('name', new EventDispatcher())
            ->addEventSubscriber(new FixedFilterListener(array(
                'preSetData' => array(
                    'app' => 'filtered',
                ),
            )))
            ->addModelTransformer(new FixedDataTransformer(array(
                '' => '',
                'filtered' => 'norm',
            )))
            ->addViewTransformer(new FixedDataTransformer(array(
                '' => '',
                'norm' => 'client',
            )))
            ->getForm();

        $form->setData('app');

        $this->assertEquals('filtered', $form->getData());
        $this->assertEquals('norm', $form->getNormData());
        $this->assertEquals('client', $form->getViewData());
    }

    public function testSetDataExecutesViewTransformersInOrder()
    {
        $form = $this->getBuilder()
            ->addViewTransformer(new FixedDataTransformer(array(
                '' => '',
                'first' => 'second',
            )))
            ->addViewTransformer(new FixedDataTransformer(array(
                '' => '',
                'second' => 'third',
            )))
            ->getForm();

        $form->setData('first');

        $this->assertEquals('third', $form->getViewData());
    }

    public function testSetDataExecutesModelTransformersInReverseOrder()
    {
        $form = $this->getBuilder()
            ->addModelTransformer(new FixedDataTransformer(array(
                '' => '',
                'second' => 'third',
            )))
            ->addModelTransformer(new FixedDataTransformer(array(
                '' => '',
                'first' => 'second',
            )))
            ->getForm();

        $form->setData('first');

        $this->assertEquals('third', $form->getNormData());
    }

    /*
     * When there is no data transformer, the data must have the same format
     * in all three representations
     */
    public function testSetDataConvertsScalarToStringIfNoTransformer()
    {
        $form = $this->getBuilder()->getForm();

        $form->setData(1);

        $this->assertSame('1', $form->getData());
        $this->assertSame('1', $form->getNormData());
        $this->assertSame('1', $form->getViewData());
    }

    /*
     * Data in client format should, if possible, always be a string to
     * facilitate differentiation between '0' and ''
     */
    public function testSetDataConvertsScalarToStringIfOnlyModelTransformer()
    {
        $form = $this->getBuilder()
            ->addModelTransformer(new FixedDataTransformer(array(
            '' => '',
            1 => 23,
        )))
            ->getForm();

        $form->setData(1);

        $this->assertSame(1, $form->getData());
        $this->assertSame(23, $form->getNormData());
        $this->assertSame('23', $form->getViewData());
    }

    /*
     * NULL remains NULL in app and norm format to remove the need to treat
     * empty values and NULL explicitly in the application
     */
    public function testSetDataConvertsNullToStringIfNoTransformer()
    {
        $form = $this->getBuilder()->getForm();

        $form->setData(null);

        $this->assertNull($form->getData());
        $this->assertNull($form->getNormData());
        $this->assertSame('', $form->getViewData());
    }

    public function testSetDataIsIgnoredIfDataIsLocked()
    {
        $form = $this->getBuilder()
            ->setData('default')
            ->setDataLocked(true)
            ->getForm();

        $form->setData('foobar');

        $this->assertSame('default', $form->getData());
    }

    public function testSubmitConvertsEmptyToNullIfNoTransformer()
    {
        $form = $this->getBuilder()->getForm();

        $form->submit('');

        $this->assertNull($form->getData());
        $this->assertNull($form->getNormData());
        $this->assertSame('', $form->getViewData());
    }

    public function testSubmitExecutesTransformationChain()
    {
        // use real event dispatcher now
        $form = $this->getBuilder('name', new EventDispatcher())
            ->addEventSubscriber(new FixedFilterListener(array(
                'preSubmit' => array(
                    'client' => 'filteredclient',
                ),
                'onSubmit' => array(
                    'norm' => 'filterednorm',
                ),
            )))
            ->addViewTransformer(new FixedDataTransformer(array(
                '' => '',
                // direction is reversed!
                'norm' => 'filteredclient',
                'filterednorm' => 'cleanedclient'
            )))
            ->addModelTransformer(new FixedDataTransformer(array(
                '' => '',
                // direction is reversed!
                'app' => 'filterednorm',
            )))
            ->getForm();

        $form->submit('client');

        $this->assertEquals('app', $form->getData());
        $this->assertEquals('filterednorm', $form->getNormData());
        $this->assertEquals('cleanedclient', $form->getViewData());
    }

    public function testSubmitExecutesViewTransformersInReverseOrder()
    {
        $form = $this->getBuilder()
            ->addViewTransformer(new FixedDataTransformer(array(
                '' => '',
                'third' => 'second',
            )))
            ->addViewTransformer(new FixedDataTransformer(array(
                '' => '',
                'second' => 'first',
            )))
            ->getForm();

        $form->submit('first');

        $this->assertEquals('third', $form->getNormData());
    }

    public function testSubmitExecutesModelTransformersInOrder()
    {
        $form = $this->getBuilder()
            ->addModelTransformer(new FixedDataTransformer(array(
                '' => '',
                'second' => 'first',
            )))
            ->addModelTransformer(new FixedDataTransformer(array(
                '' => '',
                'third' => 'second',
            )))
            ->getForm();

        $form->submit('first');

        $this->assertEquals('third', $form->getData());
    }

    public function testSynchronizedByDefault()
    {
        $this->assertTrue($this->form->isSynchronized());
    }

    public function testSynchronizedAfterSubmission()
    {
        $this->form->submit('foobar');

        $this->assertTrue($this->form->isSynchronized());
    }

    public function testNotSynchronizedIfViewReverseTransformationFailed()
    {
        $transformer = $this->getDataTransformer();
        $transformer->expects($this->once())
            ->method('reverseTransform')
            ->will($this->throwException(new TransformationFailedException()));

        $form = $this->getBuilder()
            ->addViewTransformer($transformer)
            ->getForm();

        $form->submit('foobar');

        $this->assertFalse($form->isSynchronized());
    }

    public function testNotSynchronizedIfModelReverseTransformationFailed()
    {
        $transformer = $this->getDataTransformer();
        $transformer->expects($this->once())
            ->method('reverseTransform')
            ->will($this->throwException(new TransformationFailedException()));

        $form = $this->getBuilder()
            ->addModelTransformer($transformer)
            ->getForm();

        $form->submit('foobar');

        $this->assertFalse($form->isSynchronized());
    }

    public function testEmptyDataCreatedBeforeTransforming()
    {
        $form = $this->getBuilder()
            ->setEmptyData('foo')
            ->addViewTransformer(new FixedDataTransformer(array(
            '' => '',
            // direction is reversed!
            'bar' => 'foo',
        )))
            ->getForm();

        $form->submit('');

        $this->assertEquals('bar', $form->getData());
    }

    public function testEmptyDataFromClosure()
    {
        $test = $this;
        $form = $this->getBuilder()
            ->setEmptyData(function ($form) use ($test) {
            // the form instance is passed to the closure to allow use
            // of form data when creating the empty value
            $test->assertInstanceOf('Symfony\Component\Form\FormInterface', $form);

            return 'foo';
        })
            ->addViewTransformer(new FixedDataTransformer(array(
            '' => '',
            // direction is reversed!
            'bar' => 'foo',
        )))
            ->getForm();

        $form->submit('');

        $this->assertEquals('bar', $form->getData());
    }

    public function testSubmitResetsErrors()
    {
        $this->form->addError(new FormError('Error!'));
        $this->form->submit('foobar');

        $this->assertSame(array(), $this->form->getErrors());
    }

    public function testCreateView()
    {
        $type = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface');
        $view = $this->getMock('Symfony\Component\Form\FormView');
        $form = $this->getBuilder()->setType($type)->getForm();

        $type->expects($this->once())
            ->method('createView')
            ->with($form)
            ->will($this->returnValue($view));

        $this->assertSame($view, $form->createView());
    }

    public function testCreateViewWithParent()
    {
        $type = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface');
        $view = $this->getMock('Symfony\Component\Form\FormView');
        $parentForm = $this->getMock('Symfony\Component\Form\Test\FormInterface');
        $parentView = $this->getMock('Symfony\Component\Form\FormView');
        $form = $this->getBuilder()->setType($type)->getForm();
        $form->setParent($parentForm);

        $parentForm->expects($this->once())
            ->method('createView')
            ->will($this->returnValue($parentView));

        $type->expects($this->once())
            ->method('createView')
            ->with($form, $parentView)
            ->will($this->returnValue($view));

        $this->assertSame($view, $form->createView());
    }

    public function testCreateViewWithExplicitParent()
    {
        $type = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface');
        $view = $this->getMock('Symfony\Component\Form\FormView');
        $parentView = $this->getMock('Symfony\Component\Form\FormView');
        $form = $this->getBuilder()->setType($type)->getForm();

        $type->expects($this->once())
            ->method('createView')
            ->with($form, $parentView)
            ->will($this->returnValue($view));

        $this->assertSame($view, $form->createView($parentView));
    }

    public function testGetErrorsAsString()
    {
        $this->form->addError(new FormError('Error!'));

        $this->assertEquals("ERROR: Error!\n", $this->form->getErrorsAsString());
    }

    public function testFormCanHaveEmptyName()
    {
        $form = $this->getBuilder('')->getForm();

        $this->assertEquals('', $form->getName());
    }

    public function testSetNullParentWorksWithEmptyName()
    {
        $form = $this->getBuilder('')->getForm();
        $form->setParent(null);

        $this->assertNull($form->getParent());
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\LogicException
     * @expectedExceptionMessage A form with an empty name cannot have a parent form.
     */
    public function testFormCannotHaveEmptyNameNotInRootLevel()
    {
        $this->getBuilder()
            ->setCompound(true)
            ->setDataMapper($this->getDataMapper())
            ->add($this->getBuilder(''))
            ->getForm();
    }

    public function testGetPropertyPathReturnsConfiguredPath()
    {
        $form = $this->getBuilder()->setPropertyPath('address.street')->getForm();

        $this->assertEquals(new PropertyPath('address.street'), $form->getPropertyPath());
    }

    // see https://github.com/symfony/symfony/issues/3903
    public function testGetPropertyPathDefaultsToNameIfParentHasDataClass()
    {
        $parent = $this->getBuilder(null, null, 'stdClass')
            ->setCompound(true)
            ->setDataMapper($this->getDataMapper())
            ->getForm();
        $form = $this->getBuilder('name')->getForm();
        $parent->add($form);

        $this->assertEquals(new PropertyPath('name'), $form->getPropertyPath());
    }

    // see https://github.com/symfony/symfony/issues/3903
    public function testGetPropertyPathDefaultsToIndexedNameIfParentDataClassIsNull()
    {
        $parent = $this->getBuilder()
            ->setCompound(true)
            ->setDataMapper($this->getDataMapper())
            ->getForm();
        $form = $this->getBuilder('name')->getForm();
        $parent->add($form);

        $this->assertEquals(new PropertyPath('[name]'), $form->getPropertyPath());
    }

    public function testGetPropertyPathDefaultsToNameIfFirstParentWithoutInheritDataHasDataClass()
    {
        $grandParent = $this->getBuilder(null, null, 'stdClass')
            ->setCompound(true)
            ->setDataMapper($this->getDataMapper())
            ->getForm();
        $parent = $this->getBuilder()
            ->setCompound(true)
            ->setDataMapper($this->getDataMapper())
            ->setInheritData(true)
            ->getForm();
        $form = $this->getBuilder('name')->getForm();
        $grandParent->add($parent);
        $parent->add($form);

        $this->assertEquals(new PropertyPath('name'), $form->getPropertyPath());
    }

    public function testGetPropertyPathDefaultsToIndexedNameIfDataClassOfFirstParentWithoutInheritDataIsNull()
    {
        $grandParent = $this->getBuilder()
            ->setCompound(true)
            ->setDataMapper($this->getDataMapper())
            ->getForm();
        $parent = $this->getBuilder()
            ->setCompound(true)
            ->setDataMapper($this->getDataMapper())
            ->setInheritData(true)
            ->getForm();
        $form = $this->getBuilder('name')->getForm();
        $grandParent->add($parent);
        $parent->add($form);

        $this->assertEquals(new PropertyPath('[name]'), $form->getPropertyPath());
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\LogicException
     */
    public function testViewDataMustNotBeObjectIfDataClassIsNull()
    {
        $config = new FormConfigBuilder('name', null, $this->dispatcher);
        $config->addViewTransformer(new FixedDataTransformer(array(
            '' => '',
            'foo' => new \stdClass(),
        )));
        $form = new Form($config);

        $form->setData('foo');
    }

    public function testViewDataMayBeArrayAccessIfDataClassIsNull()
    {
        $arrayAccess = $this->getMock('\ArrayAccess');
        $config = new FormConfigBuilder('name', null, $this->dispatcher);
        $config->addViewTransformer(new FixedDataTransformer(array(
            '' => '',
            'foo' => $arrayAccess,
        )));
        $form = new Form($config);

        $form->setData('foo');

        $this->assertSame($arrayAccess, $form->getViewData());
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\LogicException
     */
    public function testViewDataMustBeObjectIfDataClassIsSet()
    {
        $config = new FormConfigBuilder('name', 'stdClass', $this->dispatcher);
        $config->addViewTransformer(new FixedDataTransformer(array(
            '' => '',
            'foo' => array('bar' => 'baz'),
        )));
        $form = new Form($config);

        $form->setData('foo');
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\RuntimeException
     */
    public function testSetDataCannotInvokeItself()
    {
        // Cycle detection to prevent endless loops
        $config = new FormConfigBuilder('name', 'stdClass', $this->dispatcher);
        $config->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
            $event->getForm()->setData('bar');
        });
        $form = new Form($config);

        $form->setData('foo');
    }

    public function testSubmittingWrongDataIsIgnored()
    {
        $test = $this;

        $child = $this->getBuilder('child', $this->dispatcher);
        $child->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) use ($test) {
            // child form doesn't receive the wrong data that is submitted on parent
            $test->assertNull($event->getData());
        });

        $parent = $this->getBuilder('parent', new EventDispatcher())
            ->setCompound(true)
            ->setDataMapper($this->getDataMapper())
            ->add($child)
            ->getForm();

        $parent->submit('not-an-array');
    }

    public function testHandleRequestForwardsToRequestHandler()
    {
        $handler = $this->getMock('Symfony\Component\Form\RequestHandlerInterface');

        $form = $this->getBuilder()
            ->setRequestHandler($handler)
            ->getForm();

        $handler->expects($this->once())
            ->method('handleRequest')
            ->with($this->identicalTo($form), 'REQUEST');

        $this->assertSame($form, $form->handleRequest('REQUEST'));
    }

    public function testFormInheritsParentData()
    {
        $child = $this->getBuilder('child')
            ->setInheritData(true);

        $parent = $this->getBuilder('parent')
            ->setCompound(true)
            ->setDataMapper($this->getDataMapper())
            ->setData('foo')
            ->addModelTransformer(new FixedDataTransformer(array(
                'foo' => 'norm[foo]',
            )))
            ->addViewTransformer(new FixedDataTransformer(array(
                'norm[foo]' => 'view[foo]',
            )))
            ->add($child)
            ->getForm();

        $this->assertSame('foo', $parent->get('child')->getData());
        $this->assertSame('norm[foo]', $parent->get('child')->getNormData());
        $this->assertSame('view[foo]', $parent->get('child')->getViewData());
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\RuntimeException
     */
    public function testInheritDataDisallowsSetData()
    {
        $form = $this->getBuilder()
            ->setInheritData(true)
            ->getForm();

        $form->setData('foo');
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\RuntimeException
     */
    public function testGetDataRequiresParentToBeSetIfInheritData()
    {
        $form = $this->getBuilder()
            ->setInheritData(true)
            ->getForm();

        $form->getData();
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\RuntimeException
     */
    public function testGetNormDataRequiresParentToBeSetIfInheritData()
    {
        $form = $this->getBuilder()
            ->setInheritData(true)
            ->getForm();

        $form->getNormData();
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\RuntimeException
     */
    public function testGetViewDataRequiresParentToBeSetIfInheritData()
    {
        $form = $this->getBuilder()
            ->setInheritData(true)
            ->getForm();

        $form->getViewData();
    }

    public function testPostSubmitDataIsNullIfInheritData()
    {
        $test = $this;
        $form = $this->getBuilder()
            ->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) use ($test) {
                $test->assertNull($event->getData());
            })
            ->setInheritData(true)
            ->getForm();

        $form->submit('foo');
    }

    public function testSubmitIsNeverFiredIfInheritData()
    {
        $test = $this;
        $form = $this->getBuilder()
            ->addEventListener(FormEvents::SUBMIT, function (FormEvent $event) use ($test) {
                $test->fail('The SUBMIT event should not be fired');
            })
            ->setInheritData(true)
            ->getForm();

        $form->submit('foo');
    }

    public function testInitializeSetsDefaultData()
    {
        $config = $this->getBuilder()->setData('DEFAULT')->getFormConfig();
        $form = $this->getMock('Symfony\Component\Form\Form', array('setData'), array($config));

        $form->expects($this->once())
            ->method('setData')
            ->with($this->identicalTo('DEFAULT'));

        /* @var Form $form */
        $form->initialize();
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\RuntimeException
     */
    public function testInitializeFailsIfParent()
    {
        $parent = $this->getBuilder()->setRequired(false)->getForm();
        $child = $this->getBuilder()->setRequired(true)->getForm();

        $child->setParent($parent);

        $child->initialize();
    }

    protected function createForm()
    {
        return $this->getBuilder()->getForm();
    }
}
PK��Zۿt��ctest/Form/Symfony/Component/Form/Tests/Extension/Validator/EventListener/ValidationListenerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Validator\EventListener;

use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\Extension\Validator\Constraints\Form;
use Symfony\Component\Form\Extension\Validator\EventListener\ValidationListener;
use Symfony\Component\PropertyAccess\PropertyPath;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;

class ValidationListenerTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $dispatcher;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $factory;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $validator;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $violationMapper;

    /**
     * @var ValidationListener
     */
    private $listener;

    private $message;

    private $messageTemplate;

    private $params;

    protected function setUp()
    {
        $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
        $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface');
        $this->validator = $this->getMock('Symfony\Component\Validator\ValidatorInterface');
        $this->violationMapper = $this->getMock('Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapperInterface');
        $this->listener = new ValidationListener($this->validator, $this->violationMapper);
        $this->message = 'Message';
        $this->messageTemplate = 'Message template';
        $this->params = array('foo' => 'bar');
    }

    private function getConstraintViolation($code = null)
    {
        return new ConstraintViolation($this->message, $this->messageTemplate, $this->params, null, 'prop.path', null, null, $code);
    }

    private function getBuilder($name = 'name', $propertyPath = null, $dataClass = null)
    {
        $builder = new FormBuilder($name, $dataClass, $this->dispatcher, $this->factory);
        $builder->setPropertyPath(new PropertyPath($propertyPath ?: $name));
        $builder->setAttribute('error_mapping', array());
        $builder->setErrorBubbling(false);
        $builder->setMapped(true);

        return $builder;
    }

    private function getForm($name = 'name', $propertyPath = null, $dataClass = null)
    {
        return $this->getBuilder($name, $propertyPath, $dataClass)->getForm();
    }

    private function getMockForm()
    {
        return $this->getMock('Symfony\Component\Form\Test\FormInterface');
    }

    // More specific mapping tests can be found in ViolationMapperTest
    public function testMapViolation()
    {
        $violation = $this->getConstraintViolation();
        $form = $this->getForm('street');

        $this->validator->expects($this->once())
            ->method('validate')
            ->will($this->returnValue(array($violation)));

        $this->violationMapper->expects($this->once())
            ->method('mapViolation')
            ->with($violation, $form, false);

        $this->listener->validateForm(new FormEvent($form, null));
    }

    public function testMapViolationAllowsNonSyncIfInvalid()
    {
        $violation = $this->getConstraintViolation(Form::ERR_INVALID);
        $form = $this->getForm('street');

        $this->validator->expects($this->once())
            ->method('validate')
            ->will($this->returnValue(array($violation)));

        $this->violationMapper->expects($this->once())
            ->method('mapViolation')
            // pass true now
            ->with($violation, $form, true);

        $this->listener->validateForm(new FormEvent($form, null));
    }

    public function testValidateIgnoresNonRoot()
    {
        $form = $this->getMockForm();
        $form->expects($this->once())
            ->method('isRoot')
            ->will($this->returnValue(false));

        $this->validator->expects($this->never())
            ->method('validate');

        $this->violationMapper->expects($this->never())
            ->method('mapViolation');

        $this->listener->validateForm(new FormEvent($form, null));
    }

    public function testValidateWithEmptyViolationList()
    {
        $form = $this->getMockForm();
        $form->expects($this->once())
            ->method('isRoot')
            ->will($this->returnValue(true));

        $this->validator
            ->expects($this->once())
            ->method('validate')
            ->will($this->returnValue(new ConstraintViolationList()));

        $this->violationMapper
            ->expects($this->never())
            ->method('mapViolation');

        $this->listener->validateForm(new FormEvent($form, null));
    }
}
PK��Z�EY޵�Ttest/Form/Symfony/Component/Form/Tests/Extension/Validator/Util/ServerParamsTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Validator\Util;

class ServerParamsTest extends \PHPUnit_Framework_TestCase
{
    /** @dataProvider getGetPostMaxSizeTestData */
    public function testGetPostMaxSize($size, $bytes)
    {
        $serverParams = $this->getMock('Symfony\Component\Form\Extension\Validator\Util\ServerParams', array('getNormalizedIniPostMaxSize'));
        $serverParams
            ->expects($this->any())
            ->method('getNormalizedIniPostMaxSize')
            ->will($this->returnValue(strtoupper($size)));

        $this->assertEquals($bytes, $serverParams->getPostMaxSize());
    }

    public function getGetPostMaxSizeTestData()
    {
        return array(
            array('2k', 2048),
            array('2 k', 2048),
            array('8m', 8 * 1024 * 1024),
            array('+2 k', 2048),
            array('+2???k', 2048),
            array('0x10', 16),
            array('0xf', 15),
            array('010', 8),
            array('+0x10 k', 16 * 1024),
            array('1g', 1024 * 1024 * 1024),
            array('-1', -1),
            array('0', 0),
            array('2mk', 2048), // the unit must be the last char, so in this case 'k', not 'm'
        );
    }
}
PK��Z�l"�	�	Wtest/Form/Symfony/Component/Form/Tests/Extension/Validator/ValidatorTypeGuesserTest.phpnu�[���<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Form\Tests\Extension\Validator;

use Symfony\Component\Form\Extension\Validator\ValidatorTypeGuesser;
use Symfony\Component\Form\Guess\Guess;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\Type;

/**
* @author franek <franek@chicour.net>
*/
class ValidatorTypeGuesserTest extends \PHPUnit_Framework_TestCase
{
    private $typeGuesser;

    public function setUp()
    {
        if (!class_exists('Symfony\Component\Validator\Constraint')) {
            $this->markTestSkipped('The "Validator" component is not available');
        }

        $metadataFactory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface');

        $this->typeGuesser = new ValidatorTypeGuesser($metadataFactory);
    }

    public function testGuessMaxLengthForConstraintWithMaxValue()
    {
        $constraint = new Length(array('max' => '2'));

        $result = $this->typeGuesser->guessMaxLengthForConstraint($constraint);
        $this->assertInstanceOf('Symfony\Component\Form\Guess\ValueGuess', $result);
        $this->assertEquals(2, $result->getValue());
        $this->assertEquals(Guess::HIGH_CONFIDENCE, $result->getConfidence());
    }

    public function testGuessMaxLengthForConstraintWithMinValue()
    {
        $constraint = new Length(array('min' => '2'));

        $result = $this->typeGuesser->guessMaxLengthForConstraint($constraint);
        $this->assertNull($result);
    }

    /**
* @dataProvider dataProviderTestGuessMaxLengthForConstraintWithType
*/
    public function testGuessMaxLengthForConstraintWithType($type)
    {
        $constraint = new Type($type);

        $result = $this->typeGuesser->guessMaxLengthForConstraint($constraint);
        $this->assertInstanceOf('Symfony\Component\Form\Guess\ValueGuess', $result);
        $this->assertEquals(null, $result->getValue());
        $this->assertEquals(Guess::MEDIUM_CONFIDENCE, $result->getConfidence());
    }

    public static function dataProviderTestGuessMaxLengthForConstraintWithType()
    {
        return array (
            array('double'),
            array('float'),
            array('numeric'),
            array('real')
        );
    }
}
PK��Z��
gtest/Form/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorPerformanceTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Validator\Constraints;

use Symfony\Component\Form\Extension\Validator\ValidatorExtension;
use Symfony\Component\Form\Test\FormPerformanceTestCase;
use Symfony\Component\Validator\Validation;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class FormValidatorPerformanceTest extends FormPerformanceTestCase
{
    protected function getExtensions()
    {
        return array(
            new ValidatorExtension(Validation::createValidator()),
        );
    }

    /**
     * findClickedButton() used to have an exponential number of calls
     *
     * @group benchmark
     */
    public function testValidationPerformance()
    {
        $this->setMaxRunningTime(1);

        $builder = $this->factory->createBuilder('form');

        for ($i = 0; $i < 40; ++$i) {
            $builder->add($i, 'form');

            $builder->get($i)
                ->add('a')
                ->add('b')
                ->add('c');
        }

        $form = $builder->getForm();

        $form->submit(null);
    }
}
PK��Zِ�GbGb\test/Form/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Validator\Constraints;

use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Symfony\Component\Form\CallbackTransformer;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\Extension\Validator\Constraints\Form;
use Symfony\Component\Form\Extension\Validator\Constraints\FormValidator;
use Symfony\Component\Form\SubmitButtonBuilder;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Constraints\NotNull;
use Symfony\Component\Validator\Constraints\NotBlank;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class FormValidatorTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $dispatcher;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $factory;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $serverParams;

    /**
     * @var FormValidator
     */
    private $validator;

    protected function setUp()
    {
        $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
        $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface');
        $this->serverParams = $this->getMock(
            'Symfony\Component\Form\Extension\Validator\Util\ServerParams',
            array('getNormalizedIniPostMaxSize', 'getContentLength')
        );
        $this->validator = new FormValidator($this->serverParams);
    }

    public function testValidate()
    {
        $context = $this->getMockExecutionContext();
        $object = $this->getMock('\stdClass');
        $options = array('validation_groups' => array('group1', 'group2'));
        $form = $this->getBuilder('name', '\stdClass', $options)
            ->setData($object)
            ->getForm();

        $context->expects($this->at(0))
            ->method('validate')
            ->with($object, 'data', 'group1', true);
        $context->expects($this->at(1))
            ->method('validate')
            ->with($object, 'data', 'group2', true);

        $this->validator->initialize($context);
        $this->validator->validate($form, new Form());
    }

    public function testValidateConstraints()
    {
        $context = $this->getMockExecutionContext();
        $object = $this->getMock('\stdClass');
        $constraint1 = new NotNull(array('groups' => array('group1', 'group2')));
        $constraint2 = new NotBlank(array('groups' => 'group2'));

        $options = array(
            'validation_groups' => array('group1', 'group2'),
            'constraints' => array($constraint1, $constraint2),
        );
        $form = $this->getBuilder('name', '\stdClass', $options)
            ->setData($object)
            ->getForm();

        // First default constraints
        $context->expects($this->at(0))
            ->method('validate')
            ->with($object, 'data', 'group1', true);
        $context->expects($this->at(1))
            ->method('validate')
            ->with($object, 'data', 'group2', true);

        // Then custom constraints
        $context->expects($this->at(2))
            ->method('validateValue')
            ->with($object, $constraint1, 'data', 'group1');
        $context->expects($this->at(3))
            ->method('validateValue')
            ->with($object, $constraint2, 'data', 'group2');

        $this->validator->initialize($context);
        $this->validator->validate($form, new Form());
    }

    public function testDontValidateIfParentWithoutCascadeValidation()
    {
        $context = $this->getMockExecutionContext();
        $object = $this->getMock('\stdClass');

        $parent = $this->getBuilder('parent', null, array('cascade_validation' => false))
            ->setCompound(true)
            ->setDataMapper($this->getDataMapper())
            ->getForm();
        $options = array('validation_groups' => array('group1', 'group2'));
        $form = $this->getBuilder('name', '\stdClass', $options)->getForm();
        $parent->add($form);

        $form->setData($object);

        $context->expects($this->never())
            ->method('validate');

        $this->validator->initialize($context);
        $this->validator->validate($form, new Form());
    }

    public function testValidateConstraintsEvenIfNoCascadeValidation()
    {
        $context = $this->getMockExecutionContext();
        $object = $this->getMock('\stdClass');
        $constraint1 = new NotNull(array('groups' => array('group1', 'group2')));
        $constraint2 = new NotBlank(array('groups' => 'group2'));

        $parent = $this->getBuilder('parent', null, array('cascade_validation' => false))
            ->setCompound(true)
            ->setDataMapper($this->getDataMapper())
            ->getForm();
        $options = array(
            'validation_groups' => array('group1', 'group2'),
            'constraints' => array($constraint1, $constraint2),
        );
        $form = $this->getBuilder('name', '\stdClass', $options)
            ->setData($object)
            ->getForm();
        $parent->add($form);

        $context->expects($this->at(0))
            ->method('validateValue')
            ->with($object, $constraint1, 'data', 'group1');
        $context->expects($this->at(1))
            ->method('validateValue')
            ->with($object, $constraint2, 'data', 'group2');

        $this->validator->initialize($context);
        $this->validator->validate($form, new Form());
    }

    public function testDontValidateIfNoValidationGroups()
    {
        $context = $this->getMockExecutionContext();
        $object = $this->getMock('\stdClass');

        $form = $this->getBuilder('name', '\stdClass', array(
                'validation_groups' => array(),
            ))
            ->setData($object)
            ->getForm();

        $form->setData($object);

        $context->expects($this->never())
            ->method('validate');

        $this->validator->initialize($context);
        $this->validator->validate($form, new Form());
    }

    public function testDontValidateConstraintsIfNoValidationGroups()
    {
        $context = $this->getMockExecutionContext();
        $object = $this->getMock('\stdClass');
        $constraint1 = $this->getMock('Symfony\Component\Validator\Constraint');
        $constraint2 = $this->getMock('Symfony\Component\Validator\Constraint');

        $options = array(
            'validation_groups' => array(),
            'constraints' => array($constraint1, $constraint2),
        );
        $form = $this->getBuilder('name', '\stdClass', $options)
            ->setData($object)
            ->getForm();

        // Launch transformer
        $form->submit(array());

        $context->expects($this->never())
            ->method('validate');

        $this->validator->initialize($context);
        $this->validator->validate($form, new Form());
    }

    public function testDontValidateIfNotSynchronized()
    {
        $context = $this->getMockExecutionContext();
        $object = $this->getMock('\stdClass');

        $form = $this->getBuilder('name', '\stdClass', array(
                'invalid_message' => 'invalid_message_key',
                // Invalid message parameters must be supported, because the
                // invalid message can be a translation key
                // see https://github.com/symfony/symfony/issues/5144
                'invalid_message_parameters' => array('{{ foo }}' => 'bar'),
            ))
            ->setData($object)
            ->addViewTransformer(new CallbackTransformer(
                function ($data) { return $data; },
                function () { throw new TransformationFailedException(); }
            ))
            ->getForm();

        // Launch transformer
        $form->submit('foo');

        $context->expects($this->never())
            ->method('validate');

        $context->expects($this->once())
            ->method('addViolation')
            ->with(
                'invalid_message_key',
                array('{{ value }}' => 'foo', '{{ foo }}' => 'bar'),
                'foo'
            );
        $context->expects($this->never())
            ->method('addViolationAt');

        $this->validator->initialize($context);
        $this->validator->validate($form, new Form());
    }

    public function testAddInvalidErrorEvenIfNoValidationGroups()
    {
        $context = $this->getMockExecutionContext();
        $object = $this->getMock('\stdClass');

        $form = $this->getBuilder('name', '\stdClass', array(
                'invalid_message' => 'invalid_message_key',
                // Invalid message parameters must be supported, because the
                // invalid message can be a translation key
                // see https://github.com/symfony/symfony/issues/5144
                'invalid_message_parameters' => array('{{ foo }}' => 'bar'),
                'validation_groups' => array(),
            ))
            ->setData($object)
            ->addViewTransformer(new CallbackTransformer(
                    function ($data) { return $data; },
                    function () { throw new TransformationFailedException(); }
                ))
            ->getForm();

        // Launch transformer
        $form->submit('foo');

        $context->expects($this->never())
            ->method('validate');

        $context->expects($this->once())
            ->method('addViolation')
            ->with(
                'invalid_message_key',
                array('{{ value }}' => 'foo', '{{ foo }}' => 'bar'),
                'foo'
            );
        $context->expects($this->never())
            ->method('addViolationAt');

        $this->validator->initialize($context);
        $this->validator->validate($form, new Form());
    }

    public function testDontValidateConstraintsIfNotSynchronized()
    {
        $context = $this->getMockExecutionContext();
        $object = $this->getMock('\stdClass');
        $constraint1 = $this->getMock('Symfony\Component\Validator\Constraint');
        $constraint2 = $this->getMock('Symfony\Component\Validator\Constraint');

        $options = array(
            'validation_groups' => array('group1', 'group2'),
            'constraints' => array($constraint1, $constraint2),
        );
        $form = $this->getBuilder('name', '\stdClass', $options)
            ->setData($object)
            ->addViewTransformer(new CallbackTransformer(
                function ($data) { return $data; },
                function () { throw new TransformationFailedException(); }
            ))
            ->getForm();

        // Launch transformer
        $form->submit(array());

        $context->expects($this->never())
            ->method('validate');

        $this->validator->initialize($context);
        $this->validator->validate($form, new Form());
    }

    // https://github.com/symfony/symfony/issues/4359
    public function testDontMarkInvalidIfAnyChildIsNotSynchronized()
    {
        $context = $this->getMockExecutionContext();
        $object = $this->getMock('\stdClass');

        $failingTransformer = new CallbackTransformer(
            function ($data) { return $data; },
            function () { throw new TransformationFailedException(); }
        );

        $form = $this->getBuilder('name', '\stdClass')
            ->setData($object)
            ->addViewTransformer($failingTransformer)
            ->setCompound(true)
            ->setDataMapper($this->getDataMapper())
            ->add(
                $this->getBuilder('child')
                    ->addViewTransformer($failingTransformer)
            )
            ->getForm();

        // Launch transformer
        $form->submit(array('child' => 'foo'));

        $context->expects($this->never())
            ->method('addViolation');
        $context->expects($this->never())
            ->method('addViolationAt');

        $this->validator->initialize($context);
        $this->validator->validate($form, new Form());
    }

    public function testHandleCallbackValidationGroups()
    {
        $context = $this->getMockExecutionContext();
        $object = $this->getMock('\stdClass');
        $options = array('validation_groups' => array($this, 'getValidationGroups'));
        $form = $this->getBuilder('name', '\stdClass', $options)
            ->setData($object)
            ->getForm();

        $context->expects($this->at(0))
            ->method('validate')
            ->with($object, 'data', 'group1', true);
        $context->expects($this->at(1))
            ->method('validate')
            ->with($object, 'data', 'group2', true);

        $this->validator->initialize($context);
        $this->validator->validate($form, new Form());
    }

    public function testDontExecuteFunctionNames()
    {
        $context = $this->getMockExecutionContext();
        $object = $this->getMock('\stdClass');
        $options = array('validation_groups' => 'header');
        $form = $this->getBuilder('name', '\stdClass', $options)
            ->setData($object)
            ->getForm();

        $context->expects($this->once())
            ->method('validate')
            ->with($object, 'data', 'header', true);

        $this->validator->initialize($context);
        $this->validator->validate($form, new Form());
    }

    public function testHandleClosureValidationGroups()
    {
        $context = $this->getMockExecutionContext();
        $object = $this->getMock('\stdClass');
        $options = array('validation_groups' => function (FormInterface $form) {
            return array('group1', 'group2');
        });
        $form = $this->getBuilder('name', '\stdClass', $options)
            ->setData($object)
            ->getForm();

        $context->expects($this->at(0))
            ->method('validate')
            ->with($object, 'data', 'group1', true);
        $context->expects($this->at(1))
            ->method('validate')
            ->with($object, 'data', 'group2', true);

        $this->validator->initialize($context);
        $this->validator->validate($form, new Form());
    }

    public function testUseValidationGroupOfClickedButton()
    {
        $context = $this->getMockExecutionContext();
        $object = $this->getMock('\stdClass');

        $parent = $this->getBuilder('parent', null, array('cascade_validation' => true))
            ->setCompound(true)
            ->setDataMapper($this->getDataMapper())
            ->getForm();
        $form = $this->getForm('name', '\stdClass', array(
            'validation_groups' => 'form_group',
        ));

        $parent->add($form);
        $parent->add($this->getSubmitButton('submit', array(
            'validation_groups' => 'button_group',
        )));

        $parent->submit(array('name' => $object, 'submit' => ''));

        $context->expects($this->once())
            ->method('validate')
            ->with($object, 'data', 'button_group', true);

        $this->validator->initialize($context);
        $this->validator->validate($form, new Form());
    }

    public function testDontUseValidationGroupOfUnclickedButton()
    {
        $context = $this->getMockExecutionContext();
        $object = $this->getMock('\stdClass');

        $parent = $this->getBuilder('parent', null, array('cascade_validation' => true))
            ->setCompound(true)
            ->setDataMapper($this->getDataMapper())
            ->getForm();
        $form = $this->getForm('name', '\stdClass', array(
            'validation_groups' => 'form_group',
        ));

        $parent->add($form);
        $parent->add($this->getSubmitButton('submit', array(
            'validation_groups' => 'button_group',
        )));

        $form->setData($object);

        $context->expects($this->once())
            ->method('validate')
            ->with($object, 'data', 'form_group', true);

        $this->validator->initialize($context);
        $this->validator->validate($form, new Form());
    }

    public function testUseInheritedValidationGroup()
    {
        $context = $this->getMockExecutionContext();
        $object = $this->getMock('\stdClass');

        $parentOptions = array(
            'validation_groups' => 'group',
            'cascade_validation' => true,
        );
        $parent = $this->getBuilder('parent', null, $parentOptions)
            ->setCompound(true)
            ->setDataMapper($this->getDataMapper())
            ->getForm();
        $form = $this->getBuilder('name', '\stdClass')->getForm();
        $parent->add($form);

        $form->setData($object);

        $context->expects($this->once())
            ->method('validate')
            ->with($object, 'data', 'group', true);

        $this->validator->initialize($context);
        $this->validator->validate($form, new Form());
    }

    public function testUseInheritedCallbackValidationGroup()
    {
        $context = $this->getMockExecutionContext();
        $object = $this->getMock('\stdClass');

        $parentOptions = array(
            'validation_groups' => array($this, 'getValidationGroups'),
            'cascade_validation' => true,
        );
        $parent = $this->getBuilder('parent', null, $parentOptions)
            ->setCompound(true)
            ->setDataMapper($this->getDataMapper())
            ->getForm();
        $form = $this->getBuilder('name', '\stdClass')->getForm();
        $parent->add($form);

        $form->setData($object);

        $context->expects($this->at(0))
            ->method('validate')
            ->with($object, 'data', 'group1', true);
        $context->expects($this->at(1))
            ->method('validate')
            ->with($object, 'data', 'group2', true);

        $this->validator->initialize($context);
        $this->validator->validate($form, new Form());
    }

    public function testUseInheritedClosureValidationGroup()
    {
        $context = $this->getMockExecutionContext();
        $object = $this->getMock('\stdClass');

        $parentOptions = array(
            'validation_groups' => function (FormInterface $form) {
                return array('group1', 'group2');
            },
            'cascade_validation' => true,
        );
        $parent = $this->getBuilder('parent', null, $parentOptions)
            ->setCompound(true)
            ->setDataMapper($this->getDataMapper())
            ->getForm();
        $form = $this->getBuilder('name', '\stdClass')->getForm();
        $parent->add($form);

        $form->setData($object);

        $context->expects($this->at(0))
            ->method('validate')
            ->with($object, 'data', 'group1', true);
        $context->expects($this->at(1))
            ->method('validate')
            ->with($object, 'data', 'group2', true);

        $this->validator->initialize($context);
        $this->validator->validate($form, new Form());
    }

    public function testAppendPropertyPath()
    {
        $context = $this->getMockExecutionContext();
        $object = $this->getMock('\stdClass');
        $form = $this->getBuilder('name', '\stdClass')
            ->setData($object)
            ->getForm();

        $context->expects($this->once())
            ->method('validate')
            ->with($object, 'data', 'Default', true);

        $this->validator->initialize($context);
        $this->validator->validate($form, new Form());
    }

    public function testDontWalkScalars()
    {
        $context = $this->getMockExecutionContext();

        $form = $this->getBuilder()
            ->setData('scalar')
            ->getForm();

        $context->expects($this->never())
            ->method('validate');

        $this->validator->initialize($context);
        $this->validator->validate($form, new Form());
    }

    public function testViolationIfExtraData()
    {
        $context = $this->getMockExecutionContext();

        $form = $this->getBuilder('parent', null, array('extra_fields_message' => 'Extra!'))
            ->setCompound(true)
            ->setDataMapper($this->getDataMapper())
            ->add($this->getBuilder('child'))
            ->getForm();

        $form->submit(array('foo' => 'bar'));

        $context->expects($this->once())
            ->method('addViolation')
            ->with(
                'Extra!',
                array('{{ extra_fields }}' => 'foo'),
                array('foo' => 'bar')
            );
        $context->expects($this->never())
            ->method('addViolationAt');

        $this->validator->initialize($context);
        $this->validator->validate($form, new Form());
    }

    /**
     * @dataProvider getPostMaxSizeFixtures
     */
    public function testPostMaxSizeViolation($contentLength, $iniMax, $nbViolation, array $params = array())
    {
        $this->serverParams->expects($this->once())
            ->method('getContentLength')
            ->will($this->returnValue($contentLength));
        $this->serverParams->expects($this->any())
            ->method('getNormalizedIniPostMaxSize')
            ->will($this->returnValue($iniMax));

        $context = $this->getMockExecutionContext();
        $options = array('post_max_size_message' => 'Max {{ max }}!');
        $form = $this->getBuilder('name', null, $options)->getForm();

        for ($i = 0; $i < $nbViolation; ++$i) {
            if (0 === $i && count($params) > 0) {
                $context->expects($this->at($i))
                    ->method('addViolation')
                    ->with($options['post_max_size_message'], $params);
            } else {
                $context->expects($this->at($i))
                    ->method('addViolation');
            }
        }

        $context->expects($this->never())
            ->method('addViolationAt');

        $this->validator->initialize($context);
        $this->validator->validate($form, new Form());
    }

    public function getPostMaxSizeFixtures()
    {
        return array(
            array(pow(1024, 3) + 1, '1G', 1, array('{{ max }}' => '1G')),
            array(pow(1024, 3), '1G', 0),
            array(pow(1024, 2) + 1, '1M', 1, array('{{ max }}' => '1M')),
            array(pow(1024, 2), '1M', 0),
            array(1024 + 1, '1K', 1, array('{{ max }}' => '1K')),
            array(1024, '1K', 0),
            array(null, '1K', 0),
            array(1024, '', 0),
            array(1024, 0, 0),
        );
    }

    public function testNoViolationIfNotRoot()
    {
        $this->serverParams->expects($this->once())
            ->method('getContentLength')
            ->will($this->returnValue(1025));
        $this->serverParams->expects($this->never())
            ->method('getNormalizedIniPostMaxSize');

        $context = $this->getMockExecutionContext();
        $parent = $this->getBuilder()
            ->setCompound(true)
            ->setDataMapper($this->getDataMapper())
            ->getForm();
        $form = $this->getForm();
        $parent->add($form);

        $context->expects($this->never())
            ->method('addViolation');
        $context->expects($this->never())
            ->method('addViolationAt');

        $this->validator->initialize($context);
        $this->validator->validate($form, new Form());
    }

    /**
     * Access has to be public, as this method is called via callback array
     * in {@link testValidateFormDataCanHandleCallbackValidationGroups()}
     * and {@link testValidateFormDataUsesInheritedCallbackValidationGroup()}
     */
    public function getValidationGroups(FormInterface $form)
    {
        return array('group1', 'group2');
    }

    private function getMockExecutionContext()
    {
        return $this->getMock('Symfony\Component\Validator\ExecutionContextInterface');
    }

    /**
     * @param string $name
     * @param string $dataClass
     * @param array  $options
     *
     * @return FormBuilder
     */
    private function getBuilder($name = 'name', $dataClass = null, array $options = array())
    {
        $options = array_replace(array(
            'constraints' => array(),
            'invalid_message_parameters' => array(),
        ), $options);

        return new FormBuilder($name, $dataClass, $this->dispatcher, $this->factory, $options);
    }

    private function getForm($name = 'name', $dataClass = null, array $options = array())
    {
        return $this->getBuilder($name, $dataClass, $options)->getForm();
    }

    private function getSubmitButton($name = 'name', array $options = array())
    {
        $builder = new SubmitButtonBuilder($name, $options);

        return $builder->getForm();
    }

    /**
     * @return \PHPUnit_Framework_MockObject_MockObject
     */
    private function getDataMapper()
    {
        return $this->getMock('Symfony\Component\Form\DataMapperInterface');
    }
}
PK��Z�$�Ǵ�`test/Form/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationPathTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Validator\ViolationMapper;

use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationPath;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ViolationPathTest extends \PHPUnit_Framework_TestCase
{
    public function providePaths()
    {
        return array(
            array('children[address]', array(
                array('address', true, true),
            )),
            array('children[address].children[street]', array(
                array('address', true, true),
                array('street', true, true),
            )),
            array('children[address][street]', array(
                array('address', true, true),
            ), 'children[address]'),
            array('children[address].data', array(
                array('address', true, true),
            ), 'children[address]'),
            array('children[address].data.street', array(
                array('address', true, true),
                array('street', false, false),
            )),
            array('children[address].data[street]', array(
                array('address', true, true),
                array('street', false, true),
            )),
            array('children[address].children[street].data.name', array(
                array('address', true, true),
                array('street', true, true),
                array('name', false, false),
            )),
            array('children[address].children[street].data[name]', array(
                array('address', true, true),
                array('street', true, true),
                array('name', false, true),
            )),
            array('data.address', array(
                array('address', false, false),
            )),
            array('data[address]', array(
                array('address', false, true),
            )),
            array('data.address.street', array(
                array('address', false, false),
                array('street', false, false),
            )),
            array('data[address].street', array(
                array('address', false, true),
                array('street', false, false),
            )),
            array('data.address[street]', array(
                array('address', false, false),
                array('street', false, true),
            )),
            array('data[address][street]', array(
                array('address', false, true),
                array('street', false, true),
            )),
            // A few invalid examples
            array('data', array(), ''),
            array('children', array(), ''),
            array('children.address', array(), ''),
            array('children.address[street]', array(), ''),
        );
    }

    /**
     * @dataProvider providePaths
     */
    public function testCreatePath($string, $entries, $slicedPath = null)
    {
        if (null === $slicedPath) {
            $slicedPath = $string;
        }

        $path = new ViolationPath($string);

        $this->assertSame($slicedPath, $path->__toString());
        $this->assertSame(count($entries), count($path->getElements()));
        $this->assertSame(count($entries), $path->getLength());

        foreach ($entries as $index => $entry) {
            $this->assertEquals($entry[0], $path->getElement($index));
            $this->assertSame($entry[1], $path->mapsForm($index));
            $this->assertSame($entry[2], $path->isIndex($index));
            $this->assertSame(!$entry[2], $path->isProperty($index));
        }
    }

    public function provideParents()
    {
        return array(
            array('children[address]', null),
            array('children[address].children[street]', 'children[address]'),
            array('children[address].data.street', 'children[address]'),
            array('children[address].data[street]', 'children[address]'),
            array('data.address', null),
            array('data.address.street', 'data.address'),
            array('data.address[street]', 'data.address'),
            array('data[address].street', 'data[address]'),
            array('data[address][street]', 'data[address]'),
        );
    }

    /**
     * @dataProvider provideParents
     */
    public function testGetParent($violationPath, $parentPath)
    {
        $path = new ViolationPath($violationPath);
        $parent = $parentPath === null ? null : new ViolationPath($parentPath);

        $this->assertEquals($parent, $path->getParent());
    }

    public function testGetElement()
    {
        $path = new ViolationPath('children[address].data[street].name');

        $this->assertEquals('street', $path->getElement(1));
    }

    /**
     * @expectedException \OutOfBoundsException
     */
    public function testGetElementDoesNotAcceptInvalidIndices()
    {
        $path = new ViolationPath('children[address].data[street].name');

        $path->getElement(3);
    }

    /**
     * @expectedException \OutOfBoundsException
     */
    public function testGetElementDoesNotAcceptNegativeIndices()
    {
        $path = new ViolationPath('children[address].data[street].name');

        $path->getElement(-1);
    }

    public function testIsProperty()
    {
        $path = new ViolationPath('children[address].data[street].name');

        $this->assertFalse($path->isProperty(1));
        $this->assertTrue($path->isProperty(2));
    }

    /**
     * @expectedException \OutOfBoundsException
     */
    public function testIsPropertyDoesNotAcceptInvalidIndices()
    {
        $path = new ViolationPath('children[address].data[street].name');

        $path->isProperty(3);
    }

    /**
     * @expectedException \OutOfBoundsException
     */
    public function testIsPropertyDoesNotAcceptNegativeIndices()
    {
        $path = new ViolationPath('children[address].data[street].name');

        $path->isProperty(-1);
    }

    public function testIsIndex()
    {
        $path = new ViolationPath('children[address].data[street].name');

        $this->assertTrue($path->isIndex(1));
        $this->assertFalse($path->isIndex(2));
    }

    /**
     * @expectedException \OutOfBoundsException
     */
    public function testIsIndexDoesNotAcceptInvalidIndices()
    {
        $path = new ViolationPath('children[address].data[street].name');

        $path->isIndex(3);
    }

    /**
     * @expectedException \OutOfBoundsException
     */
    public function testIsIndexDoesNotAcceptNegativeIndices()
    {
        $path = new ViolationPath('children[address].data[street].name');

        $path->isIndex(-1);
    }

    public function testMapsForm()
    {
        $path = new ViolationPath('children[address].data[street].name');

        $this->assertTrue($path->mapsForm(0));
        $this->assertFalse($path->mapsForm(1));
        $this->assertFalse($path->mapsForm(2));
    }

    /**
     * @expectedException \OutOfBoundsException
     */
    public function testMapsFormDoesNotAcceptInvalidIndices()
    {
        $path = new ViolationPath('children[address].data[street].name');

        $path->mapsForm(3);
    }

    /**
     * @expectedException \OutOfBoundsException
     */
    public function testMapsFormDoesNotAcceptNegativeIndices()
    {
        $path = new ViolationPath('children[address].data[street].name');

        $path->mapsForm(-1);
    }
}
PK��Z�@1�,�,btest/Form/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Validator\ViolationMapper;

use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapper;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Symfony\Component\Form\CallbackTransformer;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormConfigBuilder;
use Symfony\Component\Form\FormError;
use Symfony\Component\PropertyAccess\PropertyPath;
use Symfony\Component\Validator\ConstraintViolation;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ViolationMapperTest extends \PHPUnit_Framework_TestCase
{
    const LEVEL_0 = 0;

    const LEVEL_1 = 1;

    const LEVEL_1B = 2;

    const LEVEL_2 = 3;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $dispatcher;

    /**
     * @var ViolationMapper
     */
    private $mapper;

    /**
     * @var string
     */
    private $message;

    /**
     * @var string
     */
    private $messageTemplate;

    /**
     * @var array
     */
    private $params;

    protected function setUp()
    {
        $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
        $this->mapper = new ViolationMapper();
        $this->message = 'Message';
        $this->messageTemplate = 'Message template';
        $this->params = array('foo' => 'bar');
    }

    protected function getForm($name = 'name', $propertyPath = null, $dataClass = null, $errorMapping = array(), $inheritData = false, $synchronized = true)
    {
        $config = new FormConfigBuilder($name, $dataClass, $this->dispatcher, array(
            'error_mapping' => $errorMapping,
        ));
        $config->setMapped(true);
        $config->setInheritData($inheritData);
        $config->setPropertyPath($propertyPath);
        $config->setCompound(true);
        $config->setDataMapper($this->getDataMapper());

        if (!$synchronized) {
            $config->addViewTransformer(new CallbackTransformer(
                function ($normData) { return $normData; },
                function () { throw new TransformationFailedException(); }
            ));
        }

        return new Form($config);
    }

    /**
     * @return \PHPUnit_Framework_MockObject_MockObject
     */
    private function getDataMapper()
    {
        return $this->getMock('Symfony\Component\Form\DataMapperInterface');
    }

    /**
     * @param $propertyPath
     *
     * @return ConstraintViolation
     */
    protected function getConstraintViolation($propertyPath)
    {
        return new ConstraintViolation($this->message, $this->messageTemplate, $this->params, null, $propertyPath, null);
    }

    /**
     * @return FormError
     */
    protected function getFormError()
    {
        return new FormError($this->message, $this->messageTemplate, $this->params);
    }

    public function testMapToFormInheritingParentDataIfDataDoesNotMatch()
    {
        $violation = $this->getConstraintViolation('children[address].data.foo');
        $parent = $this->getForm('parent');
        $child = $this->getForm('address', 'address', null, array(), true);
        $grandChild = $this->getForm('street');

        $parent->add($child);
        $child->add($grandChild);

        $this->mapper->mapViolation($violation, $parent);

        $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one');
        $this->assertEquals(array($this->getFormError()), $child->getErrors(), $child->getName().' should have an error, but has none');
        $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one');
    }

    public function testFollowDotRules()
    {
        $violation = $this->getConstraintViolation('data.foo');
        $parent = $this->getForm('parent', null, null, array(
            'foo' => 'address',
        ));
        $child = $this->getForm('address', null, null, array(
            '.' => 'street',
        ));
        $grandChild = $this->getForm('street', null, null, array(
            '.' => 'name',
        ));
        $grandGrandChild = $this->getForm('name');

        $parent->add($child);
        $child->add($grandChild);
        $grandChild->add($grandGrandChild);

        $this->mapper->mapViolation($violation, $parent);

        $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one');
        $this->assertCount(0, $child->getErrors(), $child->getName().' should not have an error, but has one');
        $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one');
        $this->assertEquals(array($this->getFormError()), $grandGrandChild->getErrors(), $grandGrandChild->getName().' should have an error, but has none');
    }

    public function testAbortMappingIfNotSynchronized()
    {
        $violation = $this->getConstraintViolation('children[address].data.street');
        $parent = $this->getForm('parent');
        $child = $this->getForm('address', 'address', null, array(), false, false);
        // even though "street" is synchronized, it should not have any errors
        // due to its parent not being synchronized
        $grandChild = $this->getForm('street' , 'street');

        $parent->add($child);
        $child->add($grandChild);

        // submit to invoke the transformer and mark the form unsynchronized
        $parent->submit(array());

        $this->mapper->mapViolation($violation, $parent);

        $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one');
        $this->assertCount(0, $child->getErrors(), $child->getName().' should not have an error, but has one');
        $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one');
    }

    public function testAbortDotRuleMappingIfNotSynchronized()
    {
        $violation = $this->getConstraintViolation('data.address');
        $parent = $this->getForm('parent');
        $child = $this->getForm('address', 'address', null, array(
            '.' => 'street',
        ), false, false);
        // even though "street" is synchronized, it should not have any errors
        // due to its parent not being synchronized
        $grandChild = $this->getForm('street');

        $parent->add($child);
        $child->add($grandChild);

        // submit to invoke the transformer and mark the form unsynchronized
        $parent->submit(array());

        $this->mapper->mapViolation($violation, $parent);

        $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one');
        $this->assertCount(0, $child->getErrors(), $child->getName().' should not have an error, but has one');
        $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one');
    }

    public function provideDefaultTests()
    {
        // The mapping must be deterministic! If a child has the property path "[street]",
        // "data[street]" should be mapped, but "data.street" should not!
        return array(
            // mapping target, child name, its property path, grand child name, its property path, violation path
            array(self::LEVEL_0, 'address', 'address', 'street', 'street', ''),
            array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data'),

            array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].children[street].data'),
            array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].children[street].data.prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address].data'),
            array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].data.street'),
            array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].data.street.prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address].data[street]'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address].data[street].prop'),
            array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'data.address.street'),
            array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'data.address.street.prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'data.address[street]'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'data.address[street].prop'),
            array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address].street'),
            array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address].street.prop'),
            array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address][street]'),
            array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address][street].prop'),

            array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'children[address].children[street].data'),
            array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'children[address].children[street].data.prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'children[address].data'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'children[address].data.street'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'children[address].data.street.prop'),
            array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'children[address].data[street]'),
            array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'children[address].data[street].prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'data.address.street'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'data.address.street.prop'),
            array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'data.address[street]'),
            array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'data.address[street].prop'),
            array(self::LEVEL_0, 'address', 'address', 'street', '[street]', 'data[address].street'),
            array(self::LEVEL_0, 'address', 'address', 'street', '[street]', 'data[address].street.prop'),
            array(self::LEVEL_0, 'address', 'address', 'street', '[street]', 'data[address][street]'),
            array(self::LEVEL_0, 'address', 'address', 'street', '[street]', 'data[address][street].prop'),

            array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'children[address].children[street].data'),
            array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'children[address].children[street].data.prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'children[address].data'),
            array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'children[address].data.street'),
            array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'children[address].data.street.prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'children[address].data[street]'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'children[address].data[street].prop'),
            array(self::LEVEL_0, 'address', '[address]', 'street', 'street', 'data.address.street'),
            array(self::LEVEL_0, 'address', '[address]', 'street', 'street', 'data.address.street.prop'),
            array(self::LEVEL_0, 'address', '[address]', 'street', 'street', 'data.address[street]'),
            array(self::LEVEL_0, 'address', '[address]', 'street', 'street', 'data.address[street].prop'),
            array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'data[address].street'),
            array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'data[address].street.prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'data[address][street]'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'data[address][street].prop'),

            array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'children[address].children[street].data'),
            array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'children[address].children[street].data.prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'children[address].data'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'children[address].data.street'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'children[address].data.street.prop'),
            array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'children[address].data[street]'),
            array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'children[address].data[street].prop'),
            array(self::LEVEL_0, 'address', '[address]', 'street', '[street]', 'data.address.street'),
            array(self::LEVEL_0, 'address', '[address]', 'street', '[street]', 'data.address.street.prop'),
            array(self::LEVEL_0, 'address', '[address]', 'street', '[street]', 'data.address[street]'),
            array(self::LEVEL_0, 'address', '[address]', 'street', '[street]', 'data.address[street].prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'data[address].street'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'data[address].street.prop'),
            array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'data[address][street]'),
            array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'data[address][street].prop'),

            array(self::LEVEL_2, 'address', 'person.address', 'street', 'street', 'children[address].children[street].data'),
            array(self::LEVEL_2, 'address', 'person.address', 'street', 'street', 'children[address].children[street].data.prop'),
            array(self::LEVEL_1, 'address', 'person.address', 'street', 'street', 'children[address].data'),
            array(self::LEVEL_2, 'address', 'person.address', 'street', 'street', 'children[address].data.street'),
            array(self::LEVEL_2, 'address', 'person.address', 'street', 'street', 'children[address].data.street.prop'),
            array(self::LEVEL_1, 'address', 'person.address', 'street', 'street', 'children[address].data[street]'),
            array(self::LEVEL_1, 'address', 'person.address', 'street', 'street', 'children[address].data[street].prop'),
            array(self::LEVEL_2, 'address', 'person.address', 'street', 'street', 'data.person.address.street'),
            array(self::LEVEL_2, 'address', 'person.address', 'street', 'street', 'data.person.address.street.prop'),
            array(self::LEVEL_1, 'address', 'person.address', 'street', 'street', 'data.person.address[street]'),
            array(self::LEVEL_1, 'address', 'person.address', 'street', 'street', 'data.person.address[street].prop'),
            array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data.person[address].street'),
            array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data.person[address].street.prop'),
            array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data.person[address][street]'),
            array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data.person[address][street].prop'),
            array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person].address.street'),
            array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person].address.street.prop'),
            array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person].address[street]'),
            array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person].address[street].prop'),
            array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person][address].street'),
            array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person][address].street.prop'),
            array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person][address][street]'),
            array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person][address][street].prop'),

            array(self::LEVEL_2, 'address', 'person.address', 'street', '[street]', 'children[address].children[street].data'),
            array(self::LEVEL_2, 'address', 'person.address', 'street', '[street]', 'children[address].children[street].data.prop'),
            array(self::LEVEL_1, 'address', 'person.address', 'street', '[street]', 'children[address].data'),
            array(self::LEVEL_1, 'address', 'person.address', 'street', '[street]', 'children[address].data.street'),
            array(self::LEVEL_1, 'address', 'person.address', 'street', '[street]', 'children[address].data.street.prop'),
            array(self::LEVEL_2, 'address', 'person.address', 'street', '[street]', 'children[address].data[street]'),
            array(self::LEVEL_2, 'address', 'person.address', 'street', '[street]', 'children[address].data[street].prop'),
            array(self::LEVEL_1, 'address', 'person.address', 'street', '[street]', 'data.person.address.street'),
            array(self::LEVEL_1, 'address', 'person.address', 'street', '[street]', 'data.person.address.street.prop'),
            array(self::LEVEL_2, 'address', 'person.address', 'street', '[street]', 'data.person.address[street]'),
            array(self::LEVEL_2, 'address', 'person.address', 'street', '[street]', 'data.person.address[street].prop'),
            array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data.person[address].street'),
            array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data.person[address].street.prop'),
            array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data.person[address][street]'),
            array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data.person[address][street].prop'),
            array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person].address.street'),
            array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person].address.street.prop'),
            array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person].address[street]'),
            array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person].address[street].prop'),
            array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person][address].street'),
            array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person][address].street.prop'),
            array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person][address][street]'),
            array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person][address][street].prop'),

            array(self::LEVEL_2, 'address', 'person[address]', 'street', 'street', 'children[address].children[street].data'),
            array(self::LEVEL_2, 'address', 'person[address]', 'street', 'street', 'children[address].children[street].data.prop'),
            array(self::LEVEL_1, 'address', 'person[address]', 'street', 'street', 'children[address].data'),
            array(self::LEVEL_2, 'address', 'person[address]', 'street', 'street', 'children[address].data.street'),
            array(self::LEVEL_2, 'address', 'person[address]', 'street', 'street', 'children[address].data.street.prop'),
            array(self::LEVEL_1, 'address', 'person[address]', 'street', 'street', 'children[address].data[street]'),
            array(self::LEVEL_1, 'address', 'person[address]', 'street', 'street', 'children[address].data[street].prop'),
            array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data.person.address.street'),
            array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data.person.address.street.prop'),
            array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data.person.address[street]'),
            array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data.person.address[street].prop'),
            array(self::LEVEL_2, 'address', 'person[address]', 'street', 'street', 'data.person[address].street'),
            array(self::LEVEL_2, 'address', 'person[address]', 'street', 'street', 'data.person[address].street.prop'),
            array(self::LEVEL_1, 'address', 'person[address]', 'street', 'street', 'data.person[address][street]'),
            array(self::LEVEL_1, 'address', 'person[address]', 'street', 'street', 'data.person[address][street].prop'),
            array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person].address.street'),
            array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person].address.street.prop'),
            array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person].address[street]'),
            array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person].address[street].prop'),
            array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person][address].street'),
            array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person][address].street.prop'),
            array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person][address][street]'),
            array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person][address][street].prop'),

            array(self::LEVEL_2, 'address', 'person[address]', 'street', '[street]', 'children[address].children[street].data'),
            array(self::LEVEL_2, 'address', 'person[address]', 'street', '[street]', 'children[address].children[street].data.prop'),
            array(self::LEVEL_1, 'address', 'person[address]', 'street', '[street]', 'children[address].data'),
            array(self::LEVEL_1, 'address', 'person[address]', 'street', '[street]', 'children[address].data.street'),
            array(self::LEVEL_1, 'address', 'person[address]', 'street', '[street]', 'children[address].data.street.prop'),
            array(self::LEVEL_2, 'address', 'person[address]', 'street', '[street]', 'children[address].data[street]'),
            array(self::LEVEL_2, 'address', 'person[address]', 'street', '[street]', 'children[address].data[street].prop'),
            array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data.person.address.street'),
            array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data.person.address.street.prop'),
            array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data.person.address[street]'),
            array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data.person.address[street].prop'),
            array(self::LEVEL_1, 'address', 'person[address]', 'street', '[street]', 'data.person[address].street'),
            array(self::LEVEL_1, 'address', 'person[address]', 'street', '[street]', 'data.person[address].street.prop'),
            array(self::LEVEL_2, 'address', 'person[address]', 'street', '[street]', 'data.person[address][street]'),
            array(self::LEVEL_2, 'address', 'person[address]', 'street', '[street]', 'data.person[address][street].prop'),
            array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person].address.street'),
            array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person].address.street.prop'),
            array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person].address[street]'),
            array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person].address[street].prop'),
            array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person][address].street'),
            array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person][address].street.prop'),
            array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person][address][street]'),
            array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person][address][street].prop'),

            array(self::LEVEL_2, 'address', '[person].address', 'street', 'street', 'children[address].children[street].data'),
            array(self::LEVEL_2, 'address', '[person].address', 'street', 'street', 'children[address].children[street].data.prop'),
            array(self::LEVEL_1, 'address', '[person].address', 'street', 'street', 'children[address].data'),
            array(self::LEVEL_2, 'address', '[person].address', 'street', 'street', 'children[address].data.street'),
            array(self::LEVEL_2, 'address', '[person].address', 'street', 'street', 'children[address].data.street.prop'),
            array(self::LEVEL_1, 'address', '[person].address', 'street', 'street', 'children[address].data[street]'),
            array(self::LEVEL_1, 'address', '[person].address', 'street', 'street', 'children[address].data[street].prop'),
            array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person.address.street'),
            array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person.address.street.prop'),
            array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person.address[street]'),
            array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person.address[street].prop'),
            array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person[address].street'),
            array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person[address].street.prop'),
            array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person[address][street]'),
            array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person[address][street].prop'),
            array(self::LEVEL_2, 'address', '[person].address', 'street', 'street', 'data[person].address.street'),
            array(self::LEVEL_2, 'address', '[person].address', 'street', 'street', 'data[person].address.street.prop'),
            array(self::LEVEL_1, 'address', '[person].address', 'street', 'street', 'data[person].address[street]'),
            array(self::LEVEL_1, 'address', '[person].address', 'street', 'street', 'data[person].address[street].prop'),
            array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data[person][address].street'),
            array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data[person][address].street.prop'),
            array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data[person][address][street]'),
            array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data[person][address][street].prop'),

            array(self::LEVEL_2, 'address', '[person].address', 'street', '[street]', 'children[address].children[street].data'),
            array(self::LEVEL_2, 'address', '[person].address', 'street', '[street]', 'children[address].children[street].data.prop'),
            array(self::LEVEL_1, 'address', '[person].address', 'street', '[street]', 'children[address].data'),
            array(self::LEVEL_1, 'address', '[person].address', 'street', '[street]', 'children[address].data.street'),
            array(self::LEVEL_1, 'address', '[person].address', 'street', '[street]', 'children[address].data.street.prop'),
            array(self::LEVEL_2, 'address', '[person].address', 'street', '[street]', 'children[address].data[street]'),
            array(self::LEVEL_2, 'address', '[person].address', 'street', '[street]', 'children[address].data[street].prop'),
            array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person.address.street'),
            array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person.address.street.prop'),
            array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person.address[street]'),
            array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person.address[street].prop'),
            array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person[address].street'),
            array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person[address].street.prop'),
            array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person[address][street]'),
            array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person[address][street].prop'),
            array(self::LEVEL_1, 'address', '[person].address', 'street', '[street]', 'data[person].address.street'),
            array(self::LEVEL_1, 'address', '[person].address', 'street', '[street]', 'data[person].address.street.prop'),
            array(self::LEVEL_2, 'address', '[person].address', 'street', '[street]', 'data[person].address[street]'),
            array(self::LEVEL_2, 'address', '[person].address', 'street', '[street]', 'data[person].address[street].prop'),
            array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data[person][address].street'),
            array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data[person][address].street.prop'),
            array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data[person][address][street]'),
            array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data[person][address][street].prop'),

            array(self::LEVEL_2, 'address', '[person][address]', 'street', 'street', 'children[address].children[street].data'),
            array(self::LEVEL_2, 'address', '[person][address]', 'street', 'street', 'children[address].children[street].data.prop'),
            array(self::LEVEL_1, 'address', '[person][address]', 'street', 'street', 'children[address]'),
            array(self::LEVEL_1, 'address', '[person][address]', 'street', 'street', 'children[address].data'),
            array(self::LEVEL_2, 'address', '[person][address]', 'street', 'street', 'children[address].data.street'),
            array(self::LEVEL_2, 'address', '[person][address]', 'street', 'street', 'children[address].data.street.prop'),
            array(self::LEVEL_1, 'address', '[person][address]', 'street', 'street', 'children[address].data[street]'),
            array(self::LEVEL_1, 'address', '[person][address]', 'street', 'street', 'children[address].data[street].prop'),
            array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person.address.street'),
            array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person.address.street.prop'),
            array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person.address[street]'),
            array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person.address[street].prop'),
            array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person[address].street'),
            array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person[address].street.prop'),
            array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person[address][street]'),
            array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person[address][street].prop'),
            array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data[person].address.street'),
            array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data[person].address.street.prop'),
            array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data[person].address[street]'),
            array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data[person].address[street].prop'),
            array(self::LEVEL_2, 'address', '[person][address]', 'street', 'street', 'data[person][address].street'),
            array(self::LEVEL_2, 'address', '[person][address]', 'street', 'street', 'data[person][address].street.prop'),
            array(self::LEVEL_1, 'address', '[person][address]', 'street', 'street', 'data[person][address][street]'),
            array(self::LEVEL_1, 'address', '[person][address]', 'street', 'street', 'data[person][address][street].prop'),

            array(self::LEVEL_2, 'address', '[person][address]', 'street', '[street]', 'children[address].children[street].data'),
            array(self::LEVEL_2, 'address', '[person][address]', 'street', '[street]', 'children[address].children[street].data.prop'),
            array(self::LEVEL_1, 'address', '[person][address]', 'street', '[street]', 'children[address].data'),
            array(self::LEVEL_1, 'address', '[person][address]', 'street', '[street]', 'children[address].data.street'),
            array(self::LEVEL_1, 'address', '[person][address]', 'street', '[street]', 'children[address].data.street.prop'),
            array(self::LEVEL_2, 'address', '[person][address]', 'street', '[street]', 'children[address].data[street]'),
            array(self::LEVEL_2, 'address', '[person][address]', 'street', '[street]', 'children[address].data[street].prop'),
            array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person.address.street'),
            array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person.address.street.prop'),
            array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person.address[street]'),
            array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person.address[street].prop'),
            array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person[address].street'),
            array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person[address].street.prop'),
            array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person[address][street]'),
            array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person[address][street].prop'),
            array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data[person].address.street'),
            array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data[person].address.street.prop'),
            array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data[person].address[street]'),
            array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data[person].address[street].prop'),
            array(self::LEVEL_1, 'address', '[person][address]', 'street', '[street]', 'data[person][address].street'),
            array(self::LEVEL_1, 'address', '[person][address]', 'street', '[street]', 'data[person][address].street.prop'),
            array(self::LEVEL_2, 'address', '[person][address]', 'street', '[street]', 'data[person][address][street]'),
            array(self::LEVEL_2, 'address', '[person][address]', 'street', '[street]', 'data[person][address][street].prop'),

            array(self::LEVEL_2, 'address', 'address', 'street', 'office.street', 'children[address].children[street].data'),
            array(self::LEVEL_2, 'address', 'address', 'street', 'office.street', 'children[address].children[street].data.prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data.office'),
            array(self::LEVEL_2, 'address', 'address', 'street', 'office.street', 'children[address].data.office.street'),
            array(self::LEVEL_2, 'address', 'address', 'street', 'office.street', 'children[address].data.office.street.prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data.office[street]'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data.office[street].prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data[office]'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data[office].street'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data[office].street.prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data[office][street]'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data[office][street].prop'),
            array(self::LEVEL_2, 'address', 'address', 'street', 'office.street', 'data.address.office.street'),
            array(self::LEVEL_2, 'address', 'address', 'street', 'office.street', 'data.address.office.street.prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address.office[street]'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address.office[street].prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address[office].street'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address[office].street.prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address[office][street]'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address[office][street].prop'),
            array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address].office.street'),
            array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address].office.street.prop'),
            array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address].office[street]'),
            array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address].office[street].prop'),
            array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address][office].street'),
            array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address][office].street.prop'),
            array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address][office][street]'),
            array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address][office][street].prop'),

            array(self::LEVEL_2, 'address', '[address]', 'street', 'office.street', 'children[address].children[street].data'),
            array(self::LEVEL_2, 'address', '[address]', 'street', 'office.street', 'children[address].children[street].data.prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data.office'),
            array(self::LEVEL_2, 'address', '[address]', 'street', 'office.street', 'children[address].data.office.street'),
            array(self::LEVEL_2, 'address', '[address]', 'street', 'office.street', 'children[address].data.office.street.prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data.office[street]'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data.office[street].prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data[office]'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data[office].street'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data[office].street.prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data[office][street]'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data[office][street].prop'),
            array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address.office.street'),
            array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address.office.street.prop'),
            array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address.office[street]'),
            array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address.office[street].prop'),
            array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address[office].street'),
            array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address[office].street.prop'),
            array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address[office][street]'),
            array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address[office][street].prop'),
            array(self::LEVEL_2, 'address', '[address]', 'street', 'office.street', 'data[address].office.street'),
            array(self::LEVEL_2, 'address', '[address]', 'street', 'office.street', 'data[address].office.street.prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'data[address].office[street]'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'data[address].office[street].prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'data[address][office].street'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'data[address][office].street.prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'data[address][office][street]'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'data[address][office][street].prop'),

            array(self::LEVEL_2, 'address', 'address', 'street', 'office[street]', 'children[address].children[street].data'),
            array(self::LEVEL_2, 'address', 'address', 'street', 'office[street]', 'children[address].children[street].data.prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data.office'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data.office.street'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data.office.street.prop'),
            array(self::LEVEL_2, 'address', 'address', 'street', 'office[street]', 'children[address].data.office[street]'),
            array(self::LEVEL_2, 'address', 'address', 'street', 'office[street]', 'children[address].data.office[street].prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data[office]'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data[office].street'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data[office].street.prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data[office][street]'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data[office][street].prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'data.address.office.street'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'data.address.office.street.prop'),
            array(self::LEVEL_2, 'address', 'address', 'street', 'office[street]', 'data.address.office[street]'),
            array(self::LEVEL_2, 'address', 'address', 'street', 'office[street]', 'data.address.office[street].prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'data.address[office].street'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'data.address[office].street.prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'data.address[office][street]'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'data.address[office][street].prop'),
            array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address].office.street'),
            array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address].office.street.prop'),
            array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address].office[street]'),
            array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address].office[street].prop'),
            array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address][office].street'),
            array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address][office].street.prop'),
            array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address][office][street]'),
            array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address][office][street].prop'),

            array(self::LEVEL_2, 'address', '[address]', 'street', 'office[street]', 'children[address].children[street].data'),
            array(self::LEVEL_2, 'address', '[address]', 'street', 'office[street]', 'children[address].children[street].data.prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data.office.street'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data.office.street.prop'),
            array(self::LEVEL_2, 'address', '[address]', 'street', 'office[street]', 'children[address].data.office[street]'),
            array(self::LEVEL_2, 'address', '[address]', 'street', 'office[street]', 'children[address].data.office[street].prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data[office]'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data[office].street'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data[office].street.prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data[office][street]'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data[office][street].prop'),
            array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address.office.street'),
            array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address.office.street.prop'),
            array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address.office[street]'),
            array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address.office[street].prop'),
            array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address[office].street'),
            array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address[office].street.prop'),
            array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address[office][street]'),
            array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address[office][street].prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'data[address].office.street'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'data[address].office.street.prop'),
            array(self::LEVEL_2, 'address', '[address]', 'street', 'office[street]', 'data[address].office[street]'),
            array(self::LEVEL_2, 'address', '[address]', 'street', 'office[street]', 'data[address].office[street].prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'data[address][office].street'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'data[address][office].street.prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'data[address][office][street]'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'data[address][office][street].prop'),

            array(self::LEVEL_2, 'address', 'address', 'street', '[office].street', 'children[address].children[street].data'),
            array(self::LEVEL_2, 'address', 'address', 'street', '[office].street', 'children[address].children[street].data.prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data.office'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data.office.street'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data.office.street.prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data.office[street]'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data.office[street].prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data[office]'),
            array(self::LEVEL_2, 'address', 'address', 'street', '[office].street', 'children[address].data[office].street'),
            array(self::LEVEL_2, 'address', 'address', 'street', '[office].street', 'children[address].data[office].street.prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data[office][street]'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data[office][street].prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'data.address.office.street'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'data.address.office.street.prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'data.address.office[street]'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'data.address.office[street].prop'),
            array(self::LEVEL_2, 'address', 'address', 'street', '[office].street', 'data.address[office].street'),
            array(self::LEVEL_2, 'address', 'address', 'street', '[office].street', 'data.address[office].street.prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'data.address[office][street]'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'data.address[office][street].prop'),
            array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address].office.street'),
            array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address].office.street.prop'),
            array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address].office[street]'),
            array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address].office[street].prop'),
            array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address][office].street'),
            array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address][office].street.prop'),
            array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address][office][street]'),
            array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address][office][street].prop'),

            array(self::LEVEL_2, 'address', '[address]', 'street', '[office].street', 'children[address].children[street].data'),
            array(self::LEVEL_2, 'address', '[address]', 'street', '[office].street', 'children[address].children[street].data.prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data.office'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data.office.street'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data.office.street.prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data.office[street]'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data.office[street].prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data[office]'),
            array(self::LEVEL_2, 'address', '[address]', 'street', '[office].street', 'children[address].data[office].street'),
            array(self::LEVEL_2, 'address', '[address]', 'street', '[office].street', 'children[address].data[office].street.prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data[office][street]'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data[office][street].prop'),
            array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address.office.street'),
            array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address.office.street.prop'),
            array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address.office[street]'),
            array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address.office[street].prop'),
            array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address[office].street'),
            array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address[office].street.prop'),
            array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address[office][street]'),
            array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address[office][street].prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'data[address].office.street'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'data[address].office.street.prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'data[address].office[street]'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'data[address].office[street].prop'),
            array(self::LEVEL_2, 'address', '[address]', 'street', '[office].street', 'data[address][office].street'),
            array(self::LEVEL_2, 'address', '[address]', 'street', '[office].street', 'data[address][office].street.prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'data[address][office][street]'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'data[address][office][street].prop'),

            array(self::LEVEL_2, 'address', 'address', 'street', '[office][street]', 'children[address].children[street].data'),
            array(self::LEVEL_2, 'address', 'address', 'street', '[office][street]', 'children[address].children[street].data.prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data.office'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data.office.street'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data.office.street.prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data.office[street]'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data.office[street].prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data[office]'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data[office].street'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data[office].street.prop'),
            array(self::LEVEL_2, 'address', 'address', 'street', '[office][street]', 'children[address].data[office][street]'),
            array(self::LEVEL_2, 'address', 'address', 'street', '[office][street]', 'children[address].data[office][street].prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'data.address.office.street'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'data.address.office.street.prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'data.address.office[street]'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'data.address.office[street].prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'data.address[office].street'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'data.address[office].street.prop'),
            array(self::LEVEL_2, 'address', 'address', 'street', '[office][street]', 'data.address[office][street]'),
            array(self::LEVEL_2, 'address', 'address', 'street', '[office][street]', 'data.address[office][street].prop'),
            array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address].office.street'),
            array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address].office.street.prop'),
            array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address].office[street]'),
            array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address].office[street].prop'),
            array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address][office].street'),
            array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address][office].street.prop'),
            array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address][office][street]'),
            array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address][office][street].prop'),

            array(self::LEVEL_2, 'address', '[address]', 'street', '[office][street]', 'children[address].children[street].data'),
            array(self::LEVEL_2, 'address', '[address]', 'street', '[office][street]', 'children[address].children[street].data.prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data.office'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data.office.street'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data.office.street.prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data.office[street]'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data.office[street].prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data[office]'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data[office].street'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data[office].street.prop'),
            array(self::LEVEL_2, 'address', '[address]', 'street', '[office][street]', 'children[address].data[office][street]'),
            array(self::LEVEL_2, 'address', '[address]', 'street', '[office][street]', 'children[address].data[office][street].prop'),
            array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address.office.street'),
            array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address.office.street.prop'),
            array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address.office[street]'),
            array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address.office[street].prop'),
            array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address[office].street'),
            array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address[office].street.prop'),
            array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address[office][street]'),
            array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address[office][street].prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'data[address].office.street'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'data[address].office.street.prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'data[address].office[street]'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'data[address].office[street].prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'data[address][office].street'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'data[address][office].street.prop'),
            array(self::LEVEL_2, 'address', '[address]', 'street', '[office][street]', 'data[address][office][street]'),
            array(self::LEVEL_2, 'address', '[address]', 'street', '[office][street]', 'data[address][office][street].prop'),

            // Edge cases which must not occur
            array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address][street]'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address][street].prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'children[address][street]'),
            array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'children[address][street].prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'children[address][street]'),
            array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'children[address][street].prop'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'children[address][street]'),
            array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'children[address][street].prop'),

            array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'children[person].children[address].children[street]'),
            array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'children[person].children[address].data.street'),
            array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'children[person].data.address.street'),
            array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data.address.street'),

            array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].children[office].children[street]'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].children[office].data.street'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data.street'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address.street'),
        );
    }

    /**
     * @dataProvider provideDefaultTests
     */
    public function testDefaultErrorMapping($target, $childName, $childPath, $grandChildName, $grandChildPath, $violationPath)
    {
        $violation = $this->getConstraintViolation($violationPath);
        $parent = $this->getForm('parent');
        $child = $this->getForm($childName, $childPath);
        $grandChild = $this->getForm($grandChildName, $grandChildPath);

        $parent->add($child);
        $child->add($grandChild);

        $this->mapper->mapViolation($violation, $parent);

        if (self::LEVEL_0 === $target) {
            $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName().' should have an error, but has none');
            $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one');
            $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one');
        } elseif (self::LEVEL_1 === $target) {
            $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one');
            $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName.' should have an error, but has none');
            $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one');
        } else {
            $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one');
            $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one');
            $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName.' should have an error, but has none');
        }
    }

    public function provideCustomDataErrorTests()
    {
        return array(
            // mapping target, error mapping, child name, its property path, grand child name, its property path, violation path
            array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.foo'),
            array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.foo.prop'),
            array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[foo]'),
            array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[foo].prop'),

            array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.address'),
            array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.address.prop'),
            array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[address]'),
            array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[address].prop'),

            array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo'),
            array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo.prop'),
            array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo]'),
            array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo].prop'),

            array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.address'),
            array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.address.prop'),
            array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[address]'),
            array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[address].prop'),

            array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo.prop'),
            array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo]'),
            array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo].prop'),

            array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.address'),
            array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.address.prop'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[address]'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[address].prop'),

            array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.foo'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.foo.prop'),
            array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[foo]'),
            array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[foo].prop'),

            array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.address'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.address.prop'),
            array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[address]'),
            array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[address].prop'),

            array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.foo.street'),
            array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.foo.street.prop'),
            array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.foo[street]'),
            array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.foo[street].prop'),
            array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[foo].street'),
            array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[foo].street.prop'),
            array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[foo][street]'),
            array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[foo][street].prop'),

            array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.address.street'),
            array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.address.street.prop'),
            array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.address[street]'),
            array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.address[street].prop'),
            array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[address].street'),
            array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[address].street.prop'),
            array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[address][street]'),
            array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[address][street].prop'),

            array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.foo.street'),
            array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.foo.street.prop'),
            array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.foo[street]'),
            array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.foo[street].prop'),
            array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[foo].street'),
            array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[foo].street.prop'),
            array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[foo][street]'),
            array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[foo][street].prop'),

            array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.address.street'),
            array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.address.street.prop'),
            array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.address[street]'),
            array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.address[street].prop'),
            array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[address].street'),
            array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[address].street.prop'),
            array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[address][street]'),
            array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[address][street].prop'),

            array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo.street'),
            array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo.street.prop'),
            array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo[street]'),
            array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo[street].prop'),
            array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo].street'),
            array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo].street.prop'),
            array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo][street]'),
            array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo][street].prop'),

            array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.address.street'),
            array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.address.street.prop'),
            array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.address[street]'),
            array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.address[street].prop'),
            array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[address].street'),
            array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[address].street.prop'),
            array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[address][street]'),
            array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[address][street].prop'),

            array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.foo.street'),
            array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.foo.street.prop'),
            array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.foo[street]'),
            array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.foo[street].prop'),
            array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[foo].street'),
            array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[foo].street.prop'),
            array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[foo][street]'),
            array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[foo][street].prop'),

            array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.address.street'),
            array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.address.street.prop'),
            array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.address[street]'),
            array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.address[street].prop'),
            array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[address].street'),
            array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[address].street.prop'),
            array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[address][street]'),
            array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[address][street].prop'),

            array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo.street'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo.street.prop'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo[street]'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo[street].prop'),
            array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo].street'),
            array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo].street.prop'),
            array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo][street]'),
            array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo][street].prop'),

            array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.address.street'),
            array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.address.street.prop'),
            array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.address[street]'),
            array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.address[street].prop'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[address].street'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[address].street.prop'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[address][street]'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[address][street].prop'),

            array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.street'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.street.prop'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[street]'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[street].prop'),
            array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].street'),
            array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].street.prop'),
            array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][street]'),
            array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][street].prop'),

            array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.address.street'),
            array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.address.street.prop'),
            array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.address[street]'),
            array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.address[street].prop'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[address].street'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[address].street.prop'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[address][street]'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[address][street].prop'),

            array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.foo.street'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.foo.street.prop'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.foo[street]'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.foo[street].prop'),
            array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[foo].street'),
            array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[foo].street.prop'),
            array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[foo][street]'),
            array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[foo][street].prop'),

            array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.address.street'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.address.street.prop'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.address[street]'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.address[street].prop'),
            array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[address].street'),
            array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[address].street.prop'),
            array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[address][street]'),
            array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[address][street].prop'),

            array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.foo.street'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.foo.street.prop'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.foo[street]'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.foo[street].prop'),
            array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[foo].street'),
            array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[foo].street.prop'),
            array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[foo][street]'),
            array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[foo][street].prop'),

            array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.address.street'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.address.street.prop'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.address[street]'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.address[street].prop'),
            array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[address].street'),
            array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[address].street.prop'),
            array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[address][street]'),
            array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[address][street].prop'),

            array(self::LEVEL_1, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar'),
            array(self::LEVEL_1, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.prop'),
            array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar]'),
            array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].prop'),
            array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar'),
            array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.prop'),
            array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar]'),
            array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].prop'),

            array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar'),
            array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.prop'),
            array(self::LEVEL_1, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar]'),
            array(self::LEVEL_1, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].prop'),
            array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar'),
            array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.prop'),
            array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar]'),
            array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].prop'),

            array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar'),
            array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.prop'),
            array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar]'),
            array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].prop'),
            array(self::LEVEL_1, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar'),
            array(self::LEVEL_1, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.prop'),
            array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar]'),
            array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].prop'),

            array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar'),
            array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.prop'),
            array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar]'),
            array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].prop'),
            array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar'),
            array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.prop'),
            array(self::LEVEL_1, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar]'),
            array(self::LEVEL_1, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].prop'),

            array(self::LEVEL_2, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street'),
            array(self::LEVEL_2, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street.prop'),
            array(self::LEVEL_1, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street]'),
            array(self::LEVEL_1, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street].prop'),
            array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street'),
            array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street.prop'),
            array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street]'),
            array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street].prop'),
            array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street'),
            array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street.prop'),
            array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street]'),
            array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street].prop'),
            array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street'),
            array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street.prop'),
            array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street]'),
            array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street].prop'),

            array(self::LEVEL_1, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street'),
            array(self::LEVEL_1, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street.prop'),
            array(self::LEVEL_2, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street]'),
            array(self::LEVEL_2, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street].prop'),
            array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street'),
            array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street.prop'),
            array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street]'),
            array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street].prop'),
            array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street'),
            array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street.prop'),
            array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street]'),
            array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street].prop'),
            array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street'),
            array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street.prop'),
            array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street]'),
            array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street].prop'),

            array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street'),
            array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street.prop'),
            array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street]'),
            array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street].prop'),
            array(self::LEVEL_2, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street'),
            array(self::LEVEL_2, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street.prop'),
            array(self::LEVEL_1, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street]'),
            array(self::LEVEL_1, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street].prop'),
            array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street'),
            array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street.prop'),
            array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street]'),
            array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street].prop'),
            array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street'),
            array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street.prop'),
            array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street]'),
            array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street].prop'),

            array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street'),
            array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street.prop'),
            array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street]'),
            array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street].prop'),
            array(self::LEVEL_1, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street'),
            array(self::LEVEL_1, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street.prop'),
            array(self::LEVEL_2, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street]'),
            array(self::LEVEL_2, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street].prop'),
            array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street'),
            array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street.prop'),
            array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street]'),
            array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street].prop'),
            array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street'),
            array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street.prop'),
            array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street]'),
            array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street].prop'),

            array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street'),
            array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street.prop'),
            array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street]'),
            array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street].prop'),
            array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street'),
            array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street.prop'),
            array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street]'),
            array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street].prop'),
            array(self::LEVEL_2, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street'),
            array(self::LEVEL_2, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street.prop'),
            array(self::LEVEL_1, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street]'),
            array(self::LEVEL_1, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street].prop'),
            array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street'),
            array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street.prop'),
            array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street]'),
            array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street].prop'),

            array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street'),
            array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street.prop'),
            array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street]'),
            array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street].prop'),
            array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street'),
            array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street.prop'),
            array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street]'),
            array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street].prop'),
            array(self::LEVEL_1, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street'),
            array(self::LEVEL_1, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street.prop'),
            array(self::LEVEL_2, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street]'),
            array(self::LEVEL_2, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street].prop'),
            array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street'),
            array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street.prop'),
            array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street]'),
            array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street].prop'),

            array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street'),
            array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street.prop'),
            array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street]'),
            array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street].prop'),
            array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street'),
            array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street.prop'),
            array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street]'),
            array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street].prop'),
            array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street'),
            array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street.prop'),
            array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street]'),
            array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street].prop'),
            array(self::LEVEL_2, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street'),
            array(self::LEVEL_2, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street.prop'),
            array(self::LEVEL_1, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street]'),
            array(self::LEVEL_1, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street].prop'),

            array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street'),
            array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street.prop'),
            array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street]'),
            array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street].prop'),
            array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street'),
            array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street.prop'),
            array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street]'),
            array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street].prop'),
            array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street'),
            array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street.prop'),
            array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street]'),
            array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street].prop'),
            array(self::LEVEL_1, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street'),
            array(self::LEVEL_1, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street.prop'),
            array(self::LEVEL_2, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street]'),
            array(self::LEVEL_2, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street].prop'),

            array(self::LEVEL_2, 'foo', 'address.street', 'address', 'address', 'street', 'street', 'data.foo'),
            array(self::LEVEL_2, 'foo', 'address.street', 'address', 'address', 'street', 'street', 'data.foo.prop'),
            array(self::LEVEL_2, '[foo]', 'address.street', 'address', 'address', 'street', 'street', 'data[foo]'),
            array(self::LEVEL_2, '[foo]', 'address.street', 'address', 'address', 'street', 'street', 'data[foo].prop'),

            array(self::LEVEL_2, 'foo', 'address.street', 'address', 'address', 'street', '[street]', 'data.foo'),
            array(self::LEVEL_2, 'foo', 'address.street', 'address', 'address', 'street', '[street]', 'data.foo.prop'),
            array(self::LEVEL_2, '[foo]', 'address.street', 'address', 'address', 'street', '[street]', 'data[foo]'),
            array(self::LEVEL_2, '[foo]', 'address.street', 'address', 'address', 'street', '[street]', 'data[foo].prop'),

            array(self::LEVEL_2, 'foo', 'address.street', 'address', '[address]', 'street', 'street', 'data.foo'),
            array(self::LEVEL_2, 'foo', 'address.street', 'address', '[address]', 'street', 'street', 'data.foo.prop'),
            array(self::LEVEL_2, '[foo]', 'address.street', 'address', '[address]', 'street', 'street', 'data[foo]'),
            array(self::LEVEL_2, '[foo]', 'address.street', 'address', '[address]', 'street', 'street', 'data[foo].prop'),

            array(self::LEVEL_2, 'foo.bar', 'address.street', 'address', 'address', 'street', 'street', 'data.foo.bar'),
            array(self::LEVEL_2, 'foo.bar', 'address.street', 'address', 'address', 'street', 'street', 'data.foo.bar.prop'),
            array(self::LEVEL_2, 'foo[bar]', 'address.street', 'address', 'address', 'street', 'street', 'data.foo[bar]'),
            array(self::LEVEL_2, 'foo[bar]', 'address.street', 'address', 'address', 'street', 'street', 'data.foo[bar].prop'),
            array(self::LEVEL_2, '[foo].bar', 'address.street', 'address', 'address', 'street', 'street', 'data[foo].bar'),
            array(self::LEVEL_2, '[foo].bar', 'address.street', 'address', 'address', 'street', 'street', 'data[foo].bar.prop'),
            array(self::LEVEL_2, '[foo][bar]', 'address.street', 'address', 'address', 'street', 'street', 'data[foo][bar]'),
            array(self::LEVEL_2, '[foo][bar]', 'address.street', 'address', 'address', 'street', 'street', 'data[foo][bar].prop'),

            array(self::LEVEL_2, 'foo.bar', 'address.street', 'address', 'address', 'street', '[street]', 'data.foo.bar'),
            array(self::LEVEL_2, 'foo.bar', 'address.street', 'address', 'address', 'street', '[street]', 'data.foo.bar.prop'),
            array(self::LEVEL_2, 'foo[bar]', 'address.street', 'address', 'address', 'street', '[street]', 'data.foo[bar]'),
            array(self::LEVEL_2, 'foo[bar]', 'address.street', 'address', 'address', 'street', '[street]', 'data.foo[bar].prop'),
            array(self::LEVEL_2, '[foo].bar', 'address.street', 'address', 'address', 'street', '[street]', 'data[foo].bar'),
            array(self::LEVEL_2, '[foo].bar', 'address.street', 'address', 'address', 'street', '[street]', 'data[foo].bar.prop'),
            array(self::LEVEL_2, '[foo][bar]', 'address.street', 'address', 'address', 'street', '[street]', 'data[foo][bar]'),
            array(self::LEVEL_2, '[foo][bar]', 'address.street', 'address', 'address', 'street', '[street]', 'data[foo][bar].prop'),

            array(self::LEVEL_2, 'foo.bar', 'address.street', 'address', '[address]', 'street', 'street', 'data.foo.bar'),
            array(self::LEVEL_2, 'foo.bar', 'address.street', 'address', '[address]', 'street', 'street', 'data.foo.bar.prop'),
            array(self::LEVEL_2, 'foo[bar]', 'address.street', 'address', '[address]', 'street', 'street', 'data.foo[bar]'),
            array(self::LEVEL_2, 'foo[bar]', 'address.street', 'address', '[address]', 'street', 'street', 'data.foo[bar].prop'),
            array(self::LEVEL_2, '[foo].bar', 'address.street', 'address', '[address]', 'street', 'street', 'data[foo].bar'),
            array(self::LEVEL_2, '[foo].bar', 'address.street', 'address', '[address]', 'street', 'street', 'data[foo].bar.prop'),
            array(self::LEVEL_2, '[foo][bar]', 'address.street', 'address', '[address]', 'street', 'street', 'data[foo][bar]'),
            array(self::LEVEL_2, '[foo][bar]', 'address.street', 'address', '[address]', 'street', 'street', 'data[foo][bar].prop'),

            // Edge cases
            array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo.street'),
            array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo.street.prop'),
            array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo[street]'),
            array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo[street].prop'),
            array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo].street'),
            array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo].street.prop'),
            array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo][street]'),
            array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo][street].prop'),

            array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo.street'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo.street.prop'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo[street]'),
            array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo[street].prop'),
            array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo].street'),
            array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo].street.prop'),
            array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo][street]'),
            array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo][street].prop'),
        );
    }

    /**
     * @dataProvider provideCustomDataErrorTests
     */
    public function testCustomDataErrorMapping($target, $mapFrom, $mapTo, $childName, $childPath, $grandChildName, $grandChildPath, $violationPath)
    {
        $violation = $this->getConstraintViolation($violationPath);
        $parent = $this->getForm('parent', null, null, array($mapFrom => $mapTo));
        $child = $this->getForm($childName, $childPath);
        $grandChild = $this->getForm($grandChildName, $grandChildPath);

        $parent->add($child);
        $child->add($grandChild);

        // Add a field mapped to the first element of $mapFrom
        // to try to distract the algorithm
        // Only add it if we expect the error to come up on a different
        // level than LEVEL_0, because in this case the error would
        // (correctly) be mapped to the distraction field
        if ($target !== self::LEVEL_0) {
            $mapFromPath = new PropertyPath($mapFrom);
            $mapFromPrefix = $mapFromPath->isIndex(0)
                ? '['.$mapFromPath->getElement(0).']'
                : $mapFromPath->getElement(0);
            $distraction = $this->getForm('distraction', $mapFromPrefix);

            $parent->add($distraction);
        }

        $this->mapper->mapViolation($violation, $parent);

        if ($target !== self::LEVEL_0) {
            $this->assertCount(0, $distraction->getErrors(), 'distraction should not have an error, but has one');
        }

        if (self::LEVEL_0 === $target) {
            $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName().' should have an error, but has none');
            $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one');
            $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one');
        } elseif (self::LEVEL_1 === $target) {
            $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one');
            $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName.' should have an error, but has none');
            $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one');
        } else {
            $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one');
            $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one');
            $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName.' should have an error, but has none');
        }
    }

    public function provideCustomFormErrorTests()
    {
        // This case is different than the data errors, because here the
        // left side of the mapping refers to the property path of the actual
        // children. In other words, a child error only works if
        // 1) the error actually maps to an existing child and
        // 2) the property path of that child (relative to the form providing
        //    the mapping) matches the left side of the mapping
        return array(
            // mapping target, map from, map to, child name, its property path, grand child name, its property path, violation path
            array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].children[street].data'),
            array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].children[street].data.prop'),
            array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data.street'),
            array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data.street.prop'),
            array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data[street]'),
            array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data[street].prop'),

            array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].children[street].data'),
            array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].children[street].data.prop'),
            array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data.street'),
            array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data.street.prop'),
            array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data[street]'),
            array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data[street].prop'),

            // Property path of the erroneous field and mapping must match exactly
            array(self::LEVEL_1B, 'foo', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].children[street].data'),
            array(self::LEVEL_1B, 'foo', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].children[street].data.prop'),
            array(self::LEVEL_1B, 'foo', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data.street'),
            array(self::LEVEL_1B, 'foo', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data.street.prop'),
            array(self::LEVEL_1B, 'foo', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data[street]'),
            array(self::LEVEL_1B, 'foo', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data[street].prop'),

            array(self::LEVEL_1B, '[foo]', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].children[street].data'),
            array(self::LEVEL_1B, '[foo]', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].children[street].data.prop'),
            array(self::LEVEL_1B, '[foo]', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data.street'),
            array(self::LEVEL_1B, '[foo]', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data.street.prop'),
            array(self::LEVEL_1B, '[foo]', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data[street]'),
            array(self::LEVEL_1B, '[foo]', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data[street].prop'),

            array(self::LEVEL_1, '[foo]', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].children[street].data'),
            array(self::LEVEL_1, '[foo]', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].children[street].data.prop'),
            array(self::LEVEL_2, '[foo]', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data.street'),
            array(self::LEVEL_2, '[foo]', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data.street.prop'),
            array(self::LEVEL_1, '[foo]', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data[street]'),
            array(self::LEVEL_1, '[foo]', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data[street].prop'),

            array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo].children[street].data'),
            array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo].children[street].data.prop'),
            array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo].data.street'),
            array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo].data.street.prop'),
            array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo].data[street]'),
            array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo].data[street].prop'),

            array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].children[street].data'),
            array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].children[street].data.prop'),
            array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data.street'),
            array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data.street.prop'),
            array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data[street]'),
            array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data[street].prop'),

            array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo].children[street].data'),
            array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo].children[street].data.prop'),
            array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo].data.street'),
            array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo].data.street.prop'),
            array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo].data[street]'),
            array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo].data[street].prop'),

            array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].children[street].data'),
            array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].children[street].data.prop'),
            array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data.street'),
            array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data.street.prop'),
            array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data[street]'),
            array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data[street].prop'),

            array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo].children[street].data'),
            array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo].children[street].data.prop'),
            array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo].data.street'),
            array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo].data.street.prop'),
            array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo].data[street]'),
            array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo].data[street].prop'),

            array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].children[street].data'),
            array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].children[street].data.prop'),
            array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data.street'),
            array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data.street.prop'),
            array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data[street]'),
            array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data[street].prop'),

            // Map to a nested child
            array(self::LEVEL_2, 'foo', 'address.street', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo]'),
            array(self::LEVEL_2, 'foo', 'address.street', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo]'),
            array(self::LEVEL_2, 'foo', 'address.street', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo]'),
            array(self::LEVEL_2, 'foo', 'address.street', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo]'),

            // Map from a nested child
            array(self::LEVEL_1B, 'address.street', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].children[street]'),
            array(self::LEVEL_1B, 'address.street', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data.street'),
            array(self::LEVEL_1, 'address.street', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data[street]'),
            array(self::LEVEL_2, 'address.street', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].children[street]'),
            array(self::LEVEL_1B, 'address.street', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data.street'),
            array(self::LEVEL_2, 'address.street', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data[street]'),
            array(self::LEVEL_2, 'address.street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].children[street]'),
            array(self::LEVEL_2, 'address.street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data.street'),
            array(self::LEVEL_1, 'address.street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data[street]'),
            array(self::LEVEL_2, 'address.street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].children[street]'),
            array(self::LEVEL_1, 'address.street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data.street'),
            array(self::LEVEL_2, 'address.street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data[street]'),

            array(self::LEVEL_2, 'address[street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].children[street]'),
            array(self::LEVEL_2, 'address[street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data.street'),
            array(self::LEVEL_1B, 'address[street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data[street]'),
            array(self::LEVEL_1B, 'address[street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].children[street]'),
            array(self::LEVEL_1, 'address[street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data.street'),
            array(self::LEVEL_1B, 'address[street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data[street]'),
            array(self::LEVEL_2, 'address[street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].children[street]'),
            array(self::LEVEL_2, 'address[street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data.street'),
            array(self::LEVEL_1, 'address[street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data[street]'),
            array(self::LEVEL_2, 'address[street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].children[street]'),
            array(self::LEVEL_1, 'address[street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data.street'),
            array(self::LEVEL_2, 'address[street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data[street]'),

            array(self::LEVEL_2, '[address].street', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].children[street]'),
            array(self::LEVEL_2, '[address].street', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data.street'),
            array(self::LEVEL_1, '[address].street', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data[street]'),
            array(self::LEVEL_2, '[address].street', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].children[street]'),
            array(self::LEVEL_1, '[address].street', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data.street'),
            array(self::LEVEL_2, '[address].street', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data[street]'),
            array(self::LEVEL_1B, '[address].street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].children[street]'),
            array(self::LEVEL_1B, '[address].street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data.street'),
            array(self::LEVEL_1, '[address].street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data[street]'),
            array(self::LEVEL_2, '[address].street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].children[street]'),
            array(self::LEVEL_1B, '[address].street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data.street'),
            array(self::LEVEL_2, '[address].street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data[street]'),

            array(self::LEVEL_2, '[address][street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].children[street]'),
            array(self::LEVEL_2, '[address][street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data.street'),
            array(self::LEVEL_1, '[address][street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data[street]'),
            array(self::LEVEL_2, '[address][street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].children[street]'),
            array(self::LEVEL_1, '[address][street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data.street'),
            array(self::LEVEL_2, '[address][street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data[street]'),
            array(self::LEVEL_2, '[address][street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].children[street]'),
            array(self::LEVEL_2, '[address][street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data.street'),
            array(self::LEVEL_1B, '[address][street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data[street]'),
            array(self::LEVEL_1B, '[address][street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].children[street]'),
            array(self::LEVEL_1, '[address][street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data.street'),
            array(self::LEVEL_1B, '[address][street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data[street]'),
        );
    }

    /**
     * @dataProvider provideCustomFormErrorTests
     */
    public function testCustomFormErrorMapping($target, $mapFrom, $mapTo, $errorName, $errorPath, $childName, $childPath, $grandChildName, $grandChildPath, $violationPath)
    {
        $violation = $this->getConstraintViolation($violationPath);
        $parent = $this->getForm('parent', null, null, array($mapFrom => $mapTo));
        $child = $this->getForm($childName, $childPath);
        $grandChild = $this->getForm($grandChildName, $grandChildPath);
        $errorChild = $this->getForm($errorName, $errorPath);

        $parent->add($child);
        $parent->add($errorChild);
        $child->add($grandChild);

        $this->mapper->mapViolation($violation, $parent);

        if (self::LEVEL_0 === $target) {
            $this->assertCount(0, $errorChild->getErrors(), $errorName.' should not have an error, but has one');
            $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName().' should have an error, but has none');
            $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one');
            $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one');
        } elseif (self::LEVEL_1 === $target) {
            $this->assertCount(0, $errorChild->getErrors(), $errorName.' should not have an error, but has one');
            $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one');
            $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName.' should have an error, but has none');
            $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one');
        } elseif (self::LEVEL_1B === $target) {
            $this->assertEquals(array($this->getFormError()), $errorChild->getErrors(), $errorName.' should have an error, but has none');
            $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one');
            $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one');
            $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one');
        } else {
            $this->assertCount(0, $errorChild->getErrors(), $errorName.' should not have an error, but has one');
            $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one');
            $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one');
            $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName.' should have an error, but has none');
        }
    }

    public function provideErrorTestsForFormInheritingParentData()
    {
        return array(
            // mapping target, child name, its property path, grand child name, its property path, violation path
            array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].children[street].data'),
            array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].children[street].data.prop'),
            array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].data.street'),
            array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].data.street.prop'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address].data[street]'),
            array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address].data[street].prop'),
            array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'data.street'),
            array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'data.street.prop'),
            array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[street]'),
            array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[street].prop'),
            array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data.address.street'),
            array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data.address.street.prop'),
            array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data.address[street]'),
            array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data.address[street].prop'),
            array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address].street'),
            array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address].street.prop'),
            array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address][street]'),
            array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address][street].prop'),
        );
    }

    /**
     * @dataProvider provideErrorTestsForFormInheritingParentData
     */
    public function testErrorMappingForFormInheritingParentData($target, $childName, $childPath, $grandChildName, $grandChildPath, $violationPath)
    {
        $violation = $this->getConstraintViolation($violationPath);
        $parent = $this->getForm('parent');
        $child = $this->getForm($childName, $childPath, null, array(), true);
        $grandChild = $this->getForm($grandChildName, $grandChildPath);

        $parent->add($child);
        $child->add($grandChild);

        $this->mapper->mapViolation($violation, $parent);

        if (self::LEVEL_0 === $target) {
            $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName().' should have an error, but has none');
            $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one');
            $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one');
        } elseif (self::LEVEL_1 === $target) {
            $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one');
            $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName.' should have an error, but has none');
            $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one');
        } else {
            $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one');
            $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one');
            $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName.' should have an error, but has none');
        }
    }
}
PK��Z`f�[��Ptest/Form/Symfony/Component/Form/Tests/Extension/Validator/Type/TypeTestCase.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Validator\Type;

use Symfony\Component\Form\Test\TypeTestCase as BaseTypeTestCase;
use Symfony\Component\Form\Extension\Validator\ValidatorExtension;

abstract class TypeTestCase extends BaseTypeTestCase
{
    protected $validator;

    protected function setUp()
    {
        $this->validator = $this->getMock('Symfony\Component\Validator\ValidatorInterface');
        $metadataFactory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface');
        $this->validator->expects($this->once())->method('getMetadataFactory')->will($this->returnValue($metadataFactory));
        $metadata = $this->getMockBuilder('Symfony\Component\Validator\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock();
        $metadataFactory->expects($this->once())->method('getMetadataFor')->will($this->returnValue($metadata));

        parent::setUp();
    }

    protected function tearDown()
    {
        $this->validator = null;

        parent::tearDown();
    }

    protected function getExtensions()
    {
        return array_merge(parent::getExtensions(), array(
            new ValidatorExtension($this->validator),
        ));
    }
}
PK��ZY��
xx^test/Form/Symfony/Component/Form/Tests/Extension/Validator/Type/BaseValidatorExtensionTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Validator\Type;

use Symfony\Component\Form\Test\FormInterface;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
abstract class BaseValidatorExtensionTest extends TypeTestCase
{
    public function testValidationGroupNullByDefault()
    {
        $form = $this->createForm();

        $this->assertNull($form->getConfig()->getOption('validation_groups'));
    }

    public function testValidationGroupsTransformedToArray()
    {
        $form = $this->createForm(array(
            'validation_groups' => 'group',
        ));

        $this->assertEquals(array('group'), $form->getConfig()->getOption('validation_groups'));
    }

    public function testValidationGroupsCanBeSetToArray()
    {
        $form = $this->createForm(array(
            'validation_groups' => array('group1', 'group2'),
        ));

        $this->assertEquals(array('group1', 'group2'), $form->getConfig()->getOption('validation_groups'));
    }

    public function testValidationGroupsCanBeSetToFalse()
    {
        $form = $this->createForm(array(
            'validation_groups' => false,
        ));

        $this->assertEquals(array(), $form->getConfig()->getOption('validation_groups'));
    }

    public function testValidationGroupsCanBeSetToCallback()
    {
        $form = $this->createForm(array(
            'validation_groups' => array($this, 'testValidationGroupsCanBeSetToCallback'),
        ));

        $this->assertTrue(is_callable($form->getConfig()->getOption('validation_groups')));
    }

    public function testValidationGroupsCanBeSetToClosure()
    {
        $form = $this->createForm(array(
            'validation_groups' => function (FormInterface $form) { return null; },
        ));

        $this->assertTrue(is_callable($form->getConfig()->getOption('validation_groups')));
    }

    abstract protected function createForm(array $options = array());
}
PK��ZS�m�dtest/Form/Symfony/Component/Form/Tests/Extension/Validator/Type/SubmitTypeValidatorExtensionTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Validator\Type;

class SubmitTypeValidatorExtensionTest extends BaseValidatorExtensionTest
{
    protected function createForm(array $options = array())
    {
        return $this->factory->create('submit', null, $options);
    }
}
PK��Z7>lˉ�btest/Form/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Validator\Type;

use Symfony\Component\Validator\ConstraintViolationList;

class FormTypeValidatorExtensionTest extends BaseValidatorExtensionTest
{
    public function testSubmitValidatesData()
    {
        $builder = $this->factory->createBuilder(
            'form',
            null,
            array(
                'validation_groups' => 'group',
            )
        );
        $builder->add('firstName', 'form');
        $form = $builder->getForm();

        $this->validator->expects($this->once())
            ->method('validate')
            ->with($this->equalTo($form))
            ->will($this->returnValue(new ConstraintViolationList()));

        // specific data is irrelevant
        $form->submit(array());
    }

    protected function createForm(array $options = array())
    {
        return $this->factory->create('form', null, $options);
    }
}
PK��Z1���� � itest/Form/Symfony/Component/Form/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\HttpFoundation\EventListener;

use Symfony\Component\Form\Extension\HttpFoundation\EventListener\BindRequestListener;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormConfigBuilder;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\Test\DeprecationErrorHandler;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\File\UploadedFile;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class BindRequestListenerTest extends \PHPUnit_Framework_TestCase
{
    private $values;

    private $filesPlain;

    private $filesNested;

    /**
     * @var UploadedFile
     */
    private $uploadedFile;

    protected function setUp()
    {
        $path = tempnam(sys_get_temp_dir(), 'sf2');
        touch($path);

        $this->values = array(
            'name' => 'Bernhard',
            'image' => array('filename' => 'foobar.png'),
        );

        $this->filesPlain = array(
            'image' => array(
                'error' => UPLOAD_ERR_OK,
                'name' => 'upload.png',
                'size' => 123,
                'tmp_name' => $path,
                'type' => 'image/png'
            ),
        );

        $this->filesNested = array(
            'error' => array('image' => UPLOAD_ERR_OK),
            'name' => array('image' => 'upload.png'),
            'size' => array('image' => 123),
            'tmp_name' => array('image' => $path),
            'type' => array('image' => 'image/png'),
        );

        $this->uploadedFile = new UploadedFile($path, 'upload.png', 'image/png', 123, UPLOAD_ERR_OK);
    }

    protected function tearDown()
    {
        unlink($this->uploadedFile->getRealPath());
    }

    public function requestMethodProvider()
    {
        return array(
            array('POST'),
            array('PUT'),
            array('DELETE'),
            array('PATCH'),
        );
    }

    /**
     * @dataProvider requestMethodProvider
     */
    public function testSubmitRequest($method)
    {
        $values = array('author' => $this->values);
        $files = array('author' => $this->filesNested);
        $request = new Request(array(), $values, array(), array(), $files, array(
            'REQUEST_METHOD' => $method,
        ));

        $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
        $config = new FormConfigBuilder('author', null, $dispatcher);
        $form = new Form($config);
        $event = new FormEvent($form, $request);

        $listener = new BindRequestListener();
        DeprecationErrorHandler::preBind($listener, $event);

        $this->assertEquals(array(
            'name' => 'Bernhard',
            'image' => $this->uploadedFile,
        ), $event->getData());
    }

    /**
     * @dataProvider requestMethodProvider
     */
    public function testSubmitRequestWithEmptyName($method)
    {
        $request = new Request(array(), $this->values, array(), array(), $this->filesPlain, array(
            'REQUEST_METHOD' => $method,
        ));

        $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
        $config = new FormConfigBuilder('', null, $dispatcher);
        $form = new Form($config);
        $event = new FormEvent($form, $request);

        $listener = new BindRequestListener();
        DeprecationErrorHandler::preBind($listener, $event);

        $this->assertEquals(array(
            'name' => 'Bernhard',
            'image' => $this->uploadedFile,
        ), $event->getData());
    }

    /**
     * @dataProvider requestMethodProvider
     */
    public function testSubmitEmptyRequestToCompoundForm($method)
    {
        $request = new Request(array(), array(), array(), array(), array(), array(
            'REQUEST_METHOD' => $method,
        ));

        $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
        $config = new FormConfigBuilder('author', null, $dispatcher);
        $config->setCompound(true);
        $config->setDataMapper($this->getMock('Symfony\Component\Form\DataMapperInterface'));
        $form = new Form($config);
        $event = new FormEvent($form, $request);

        $listener = new BindRequestListener();
        DeprecationErrorHandler::preBind($listener, $event);

        // Default to empty array
        $this->assertEquals(array(), $event->getData());
    }

    /**
     * @dataProvider requestMethodProvider
     */
    public function testSubmitEmptyRequestToSimpleForm($method)
    {
        $request = new Request(array(), array(), array(), array(), array(), array(
            'REQUEST_METHOD' => $method,
        ));

        $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
        $config = new FormConfigBuilder('author', null, $dispatcher);
        $config->setCompound(false);
        $form = new Form($config);
        $event = new FormEvent($form, $request);

        $listener = new BindRequestListener();
        DeprecationErrorHandler::preBind($listener, $event);

        // Default to null
        $this->assertNull($event->getData());
    }

    public function testSubmitGetRequest()
    {
        $values = array('author' => $this->values);
        $request = new Request($values, array(), array(), array(), array(), array(
            'REQUEST_METHOD' => 'GET',
        ));

        $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
        $config = new FormConfigBuilder('author', null, $dispatcher);
        $form = new Form($config);
        $event = new FormEvent($form, $request);

        $listener = new BindRequestListener();
        DeprecationErrorHandler::preBind($listener, $event);

        $this->assertEquals(array(
            'name' => 'Bernhard',
            'image' => array('filename' => 'foobar.png'),
        ), $event->getData());
    }

    public function testSubmitGetRequestWithEmptyName()
    {
        $request = new Request($this->values, array(), array(), array(), array(), array(
            'REQUEST_METHOD' => 'GET',
        ));

        $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
        $config = new FormConfigBuilder('', null, $dispatcher);
        $form = new Form($config);
        $event = new FormEvent($form, $request);

        $listener = new BindRequestListener();
        DeprecationErrorHandler::preBind($listener, $event);

        $this->assertEquals(array(
            'name' => 'Bernhard',
            'image' => array('filename' => 'foobar.png'),
        ), $event->getData());
    }

    public function testSubmitEmptyGetRequestToCompoundForm()
    {
        $request = new Request(array(), array(), array(), array(), array(), array(
            'REQUEST_METHOD' => 'GET',
        ));

        $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
        $config = new FormConfigBuilder('author', null, $dispatcher);
        $config->setCompound(true);
        $config->setDataMapper($this->getMock('Symfony\Component\Form\DataMapperInterface'));
        $form = new Form($config);
        $event = new FormEvent($form, $request);

        $listener = new BindRequestListener();
        DeprecationErrorHandler::preBind($listener, $event);

        $this->assertEquals(array(), $event->getData());
    }

    public function testSubmitEmptyGetRequestToSimpleForm()
    {
        $request = new Request(array(), array(), array(), array(), array(), array(
            'REQUEST_METHOD' => 'GET',
        ));

        $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
        $config = new FormConfigBuilder('author', null, $dispatcher);
        $config->setCompound(false);
        $form = new Form($config);
        $event = new FormEvent($form, $request);

        $listener = new BindRequestListener();
        DeprecationErrorHandler::preBind($listener, $event);

        $this->assertNull($event->getData());
    }
}
PK��Zf͍ffdtest/Form/Symfony/Component/Form/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\HttpFoundation;

use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler;
use Symfony\Component\Form\Tests\AbstractRequestHandlerTest;
use Symfony\Component\HttpFoundation\Request;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class HttpFoundationRequestHandlerTest extends AbstractRequestHandlerTest
{
    /**
     * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException
     */
    public function testRequestShouldNotBeNull()
    {
        $this->requestHandler->handleRequest($this->getMockForm('name', 'GET'));
    }
    /**
     * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException
     */
    public function testRequestShouldBeInstanceOfRequest()
    {
        $this->requestHandler->handleRequest($this->getMockForm('name', 'GET'), new \stdClass());
    }

    protected function setRequestData($method, $data, $files = array())
    {
        $this->request = Request::create('http://localhost', $method, $data, array(), $files);
    }

    protected function getRequestHandler()
    {
        return new HttpFoundationRequestHandler();
    }

    protected function getMockFile()
    {
        return $this->getMockBuilder('Symfony\Component\HttpFoundation\File\UploadedFile')
            ->disableOriginalConstructor()
            ->getMock();
    }
}
PK��Z%u����^test/Form/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/SessionCsrfProviderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Csrf\CsrfProvider;

use Symfony\Component\Form\Extension\Csrf\CsrfProvider\SessionCsrfProvider;

class SessionCsrfProviderTest extends \PHPUnit_Framework_TestCase
{
    protected $provider;
    protected $session;

    protected function setUp()
    {
        $this->session = $this->getMock(
            'Symfony\Component\HttpFoundation\Session\Session',
            array(),
            array(),
            '',
            false // don't call constructor
        );
        $this->provider = new SessionCsrfProvider($this->session, 'SECRET');
    }

    protected function tearDown()
    {
        $this->provider = null;
        $this->session = null;
    }

    public function testGenerateCsrfToken()
    {
        $this->session->expects($this->once())
                ->method('getId')
                ->will($this->returnValue('ABCDEF'));

        $token = $this->provider->generateCsrfToken('foo');

        $this->assertEquals(sha1('SECRET'.'foo'.'ABCDEF'), $token);
    }

    public function testIsCsrfTokenValidSucceeds()
    {
        $this->session->expects($this->once())
                ->method('getId')
                ->will($this->returnValue('ABCDEF'));

        $token = sha1('SECRET'.'foo'.'ABCDEF');

        $this->assertTrue($this->provider->isCsrfTokenValid('foo', $token));
    }

    public function testIsCsrfTokenValidFails()
    {
        $this->session->expects($this->once())
                ->method('getId')
                ->will($this->returnValue('ABCDEF'));

        $token = sha1('SECRET'.'bar'.'ABCDEF');

        $this->assertFalse($this->provider->isCsrfTokenValid('foo', $token));
    }
}
PK��Z_Nn���^test/Form/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/DefaultCsrfProviderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Csrf\CsrfProvider;

use Symfony\Component\Form\Extension\Csrf\CsrfProvider\DefaultCsrfProvider;

/**
 * @runTestsInSeparateProcesses
 */
class DefaultCsrfProviderTest extends \PHPUnit_Framework_TestCase
{
    protected $provider;

    public static function setUpBeforeClass()
    {
        ini_set('session.save_handler', 'files');
        ini_set('session.save_path', sys_get_temp_dir());
    }

    protected function setUp()
    {
        $this->provider = new DefaultCsrfProvider('SECRET');
    }

    protected function tearDown()
    {
        $this->provider = null;
    }

    public function testGenerateCsrfToken()
    {
        session_start();

        $token = $this->provider->generateCsrfToken('foo');

        $this->assertEquals(sha1('SECRET'.'foo'.session_id()), $token);
    }

    public function testGenerateCsrfTokenOnUnstartedSession()
    {
        session_id('touti');

        if (!version_compare(PHP_VERSION, '5.4', '>=')) {
            $this->markTestSkipped('This test requires PHP >= 5.4');
        }

        $this->assertSame(PHP_SESSION_NONE, session_status());

        $token = $this->provider->generateCsrfToken('foo');

        $this->assertEquals(sha1('SECRET'.'foo'.session_id()), $token);
        $this->assertSame(PHP_SESSION_ACTIVE, session_status());
    }

    public function testIsCsrfTokenValidSucceeds()
    {
        session_start();

        $token = sha1('SECRET'.'foo'.session_id());

        $this->assertTrue($this->provider->isCsrfTokenValid('foo', $token));
    }

    public function testIsCsrfTokenValidFails()
    {
        session_start();

        $token = sha1('SECRET'.'bar'.session_id());

        $this->assertFalse($this->provider->isCsrfTokenValid('foo', $token));
    }
}
PK��Z�A��btest/Form/Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Csrf\EventListener;

use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\Extension\Csrf\EventListener\CsrfValidationListener;

class CsrfValidationListenerTest extends \PHPUnit_Framework_TestCase
{
    protected $dispatcher;
    protected $factory;
    protected $tokenManager;
    protected $form;

    protected function setUp()
    {
        $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
        $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface');
        $this->tokenManager = $this->getMock('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface');
        $this->form = $this->getBuilder('post')
            ->setDataMapper($this->getDataMapper())
            ->getForm();
    }

    protected function tearDown()
    {
        $this->dispatcher = null;
        $this->factory = null;
        $this->tokenManager = null;
        $this->form = null;
    }

    protected function getBuilder($name = 'name')
    {
        return new FormBuilder($name, null, $this->dispatcher, $this->factory, array('compound' => true));
    }

    protected function getForm($name = 'name')
    {
        return $this->getBuilder($name)->getForm();
    }

    protected function getDataMapper()
    {
        return $this->getMock('Symfony\Component\Form\DataMapperInterface');
    }

    protected function getMockForm()
    {
        return $this->getMock('Symfony\Component\Form\Test\FormInterface');
    }

    // https://github.com/symfony/symfony/pull/5838
    public function testStringFormData()
    {
        $data = "XP4HUzmHPi";
        $event = new FormEvent($this->form, $data);

        $validation = new CsrfValidationListener('csrf', $this->tokenManager, 'unknown', 'Invalid.');
        $validation->preSubmit($event);

        // Validate accordingly
        $this->assertSame($data, $event->getData());
    }
}
PK��Z�L?��.�.Xtest/Form/Symfony/Component/Form/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Csrf\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\Test\TypeTestCase;
use Symfony\Component\Form\Extension\Csrf\CsrfExtension;
use Symfony\Component\Security\Csrf\CsrfToken;

class FormTypeCsrfExtensionTest_ChildType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        // The form needs a child in order to trigger CSRF protection by
        // default
        $builder->add('name', 'text');
    }

    public function getName()
    {
        return 'csrf_collection_test';
    }
}

class FormTypeCsrfExtensionTest extends TypeTestCase
{
    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    protected $tokenManager;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    protected $translator;

    protected function setUp()
    {
        $this->tokenManager = $this->getMock('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface');
        $this->translator = $this->getMock('Symfony\Component\Translation\TranslatorInterface');

        parent::setUp();
    }

    protected function tearDown()
    {
        $this->tokenManager = null;
        $this->translator = null;

        parent::tearDown();
    }

    protected function getExtensions()
    {
        return array_merge(parent::getExtensions(), array(
            new CsrfExtension($this->tokenManager, $this->translator),
        ));
    }

    public function testCsrfProtectionByDefaultIfRootAndCompound()
    {
        $view = $this->factory
            ->create('form', null, array(
                'csrf_field_name' => 'csrf',
                'compound' => true,
            ))
            ->createView();

        $this->assertTrue(isset($view['csrf']));
    }

    public function testNoCsrfProtectionByDefaultIfCompoundButNotRoot()
    {
        $view = $this->factory
            ->createNamedBuilder('root', 'form')
            ->add($this->factory
                ->createNamedBuilder('form', 'form', null, array(
                    'csrf_field_name' => 'csrf',
                    'compound' => true,
                ))
            )
            ->getForm()
            ->get('form')
            ->createView();

        $this->assertFalse(isset($view['csrf']));
    }

    public function testNoCsrfProtectionByDefaultIfRootButNotCompound()
    {
        $view = $this->factory
            ->create('form', null, array(
                'csrf_field_name' => 'csrf',
                'compound' => false,
            ))
            ->createView();

        $this->assertFalse(isset($view['csrf']));
    }

    public function testCsrfProtectionCanBeDisabled()
    {
        $view = $this->factory
            ->create('form', null, array(
                'csrf_field_name' => 'csrf',
                'csrf_protection' => false,
                'compound' => true,
            ))
            ->createView();

        $this->assertFalse(isset($view['csrf']));
    }

    public function testGenerateCsrfToken()
    {
        $this->tokenManager->expects($this->once())
            ->method('getToken')
            ->with('TOKEN_ID')
            ->will($this->returnValue(new CsrfToken('TOKEN_ID', 'token')));

        $view = $this->factory
            ->create('form', null, array(
                'csrf_field_name' => 'csrf',
                'csrf_token_manager' => $this->tokenManager,
                'csrf_token_id' => 'TOKEN_ID',
                'compound' => true,
            ))
            ->createView();

        $this->assertEquals('token', $view['csrf']->vars['value']);
    }

    public function testGenerateCsrfTokenUsesFormNameAsIntentionByDefault()
    {
        $this->tokenManager->expects($this->once())
            ->method('getToken')
            ->with('FORM_NAME')
            ->will($this->returnValue('token'));

        $view = $this->factory
            ->createNamed('FORM_NAME', 'form', null, array(
                'csrf_field_name' => 'csrf',
                'csrf_token_manager' => $this->tokenManager,
                'compound' => true,
            ))
            ->createView();

        $this->assertEquals('token', $view['csrf']->vars['value']);
    }

    public function testGenerateCsrfTokenUsesTypeClassAsIntentionIfEmptyFormName()
    {
        $this->tokenManager->expects($this->once())
            ->method('getToken')
            ->with('Symfony\Component\Form\Extension\Core\Type\FormType')
            ->will($this->returnValue('token'));

        $view = $this->factory
            ->createNamed('', 'form', null, array(
                'csrf_field_name' => 'csrf',
                'csrf_token_manager' => $this->tokenManager,
                'compound' => true,
            ))
            ->createView();

        $this->assertEquals('token', $view['csrf']->vars['value']);
    }

    public function provideBoolean()
    {
        return array(
            array(true),
            array(false),
        );
    }

    /**
     * @dataProvider provideBoolean
     */
    public function testValidateTokenOnSubmitIfRootAndCompound($valid)
    {
        $this->tokenManager->expects($this->once())
            ->method('isTokenValid')
            ->with(new CsrfToken('TOKEN_ID', 'token'))
            ->will($this->returnValue($valid));

        $form = $this->factory
            ->createBuilder('form', null, array(
                'csrf_field_name' => 'csrf',
                'csrf_token_manager' => $this->tokenManager,
                'csrf_token_id' => 'TOKEN_ID',
                'compound' => true,
            ))
            ->add('child', 'text')
            ->getForm();

        $form->submit(array(
            'child' => 'foobar',
            'csrf' => 'token',
        ));

        // Remove token from data
        $this->assertSame(array('child' => 'foobar'), $form->getData());

        // Validate accordingly
        $this->assertSame($valid, $form->isValid());
    }

    /**
     * @dataProvider provideBoolean
     */
    public function testValidateTokenOnSubmitIfRootAndCompoundUsesFormNameAsIntentionByDefault($valid)
    {
        $this->tokenManager->expects($this->once())
            ->method('isTokenValid')
            ->with(new CsrfToken('FORM_NAME', 'token'))
            ->will($this->returnValue($valid));

        $form = $this->factory
            ->createNamedBuilder('FORM_NAME', 'form', null, array(
                'csrf_field_name' => 'csrf',
                'csrf_token_manager' => $this->tokenManager,
                'compound' => true,
            ))
            ->add('child', 'text')
            ->getForm();

        $form->submit(array(
            'child' => 'foobar',
            'csrf' => 'token',
        ));

        // Remove token from data
        $this->assertSame(array('child' => 'foobar'), $form->getData());

        // Validate accordingly
        $this->assertSame($valid, $form->isValid());
    }

    /**
     * @dataProvider provideBoolean
     */
    public function testValidateTokenOnSubmitIfRootAndCompoundUsesTypeClassAsIntentionIfEmptyFormName($valid)
    {
        $this->tokenManager->expects($this->once())
            ->method('isTokenValid')
            ->with(new CsrfToken('Symfony\Component\Form\Extension\Core\Type\FormType', 'token'))
            ->will($this->returnValue($valid));

        $form = $this->factory
            ->createNamedBuilder('', 'form', null, array(
                'csrf_field_name' => 'csrf',
                'csrf_token_manager' => $this->tokenManager,
                'compound' => true,
            ))
            ->add('child', 'text')
            ->getForm();

        $form->submit(array(
            'child' => 'foobar',
            'csrf' => 'token',
        ));

        // Remove token from data
        $this->assertSame(array('child' => 'foobar'), $form->getData());

        // Validate accordingly
        $this->assertSame($valid, $form->isValid());
    }

    public function testFailIfRootAndCompoundAndTokenMissing()
    {
        $this->tokenManager->expects($this->never())
            ->method('isTokenValid');

        $form = $this->factory
            ->createBuilder('form', null, array(
                'csrf_field_name' => 'csrf',
                'csrf_token_manager' => $this->tokenManager,
                'csrf_token_id' => 'TOKEN_ID',
                'compound' => true,
            ))
            ->add('child', 'text')
            ->getForm();

        $form->submit(array(
            'child' => 'foobar',
            // token is missing
        ));

        // Remove token from data
        $this->assertSame(array('child' => 'foobar'), $form->getData());

        // Validate accordingly
        $this->assertFalse($form->isValid());
    }

    public function testDontValidateTokenIfCompoundButNoRoot()
    {
        $this->tokenManager->expects($this->never())
            ->method('isTokenValid');

        $form = $this->factory
            ->createNamedBuilder('root', 'form')
            ->add($this->factory
                ->createNamedBuilder('form', 'form', null, array(
                    'csrf_field_name' => 'csrf',
                    'csrf_token_manager' => $this->tokenManager,
                    'csrf_token_id' => 'TOKEN_ID',
                    'compound' => true,
                ))
            )
            ->getForm()
            ->get('form');

        $form->submit(array(
            'child' => 'foobar',
            'csrf' => 'token',
        ));
    }

    public function testDontValidateTokenIfRootButNotCompound()
    {
        $this->tokenManager->expects($this->never())
            ->method('isTokenValid');

        $form = $this->factory
            ->create('form', null, array(
                'csrf_field_name' => 'csrf',
                'csrf_token_manager' => $this->tokenManager,
                'csrf_token_id' => 'TOKEN_ID',
                'compound' => false,
            ));

        $form->submit(array(
            'csrf' => 'token',
        ));
    }

    public function testNoCsrfProtectionOnPrototype()
    {
        $prototypeView = $this->factory
            ->create('collection', null, array(
                'type' => new FormTypeCsrfExtensionTest_ChildType(),
                'options' => array(
                    'csrf_field_name' => 'csrf',
                ),
                'prototype' => true,
                'allow_add' => true,
            ))
            ->createView()
            ->vars['prototype'];

        $this->assertFalse(isset($prototypeView['csrf']));
        $this->assertCount(1, $prototypeView);
    }

    public function testsTranslateCustomErrorMessage()
    {
        $this->tokenManager->expects($this->once())
            ->method('isTokenValid')
            ->with(new CsrfToken('TOKEN_ID', 'token'))
            ->will($this->returnValue(false));

        $this->translator->expects($this->once())
             ->method('trans')
             ->with('Foobar')
             ->will($this->returnValue('[trans]Foobar[/trans]'));

        $form = $this->factory
            ->createBuilder('form', null, array(
                'csrf_field_name' => 'csrf',
                'csrf_token_manager' => $this->tokenManager,
                'csrf_message' => 'Foobar',
                'csrf_token_id' => 'TOKEN_ID',
                'compound' => true,
            ))
            ->getForm();

        $form->submit(array(
            'csrf' => 'token',
        ));

        $errors = $form->getErrors();

        $this->assertGreaterThan(0, count($errors));
        $this->assertEquals(new FormError('[trans]Foobar[/trans]'), $errors[0]);
    }
}
PK��Z��܏##Wtest/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/Fixtures/randomhashnu�[���GIF87a�������,D;PK��Z��**atest/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\EventListener;

use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\Extension\Core\EventListener\FixRadioInputListener;
use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList;

class FixRadioInputListenerTest extends \PHPUnit_Framework_TestCase
{
    private $choiceList;

    protected function setUp()
    {
        parent::setUp();

        $this->choiceList = new SimpleChoiceList(array('' => 'Empty', 0 => 'A', 1 => 'B'));
    }

    protected function tearDown()
    {
        parent::tearDown();

        $listener = null;
    }

    public function testFixRadio()
    {
        $data = '1';
        $form = $this->getMock('Symfony\Component\Form\Test\FormInterface');
        $event = new FormEvent($form, $data);

        $listener = new FixRadioInputListener($this->choiceList, true);
        $listener->preSubmit($event);

        // Indices in SimpleChoiceList are zero-based generated integers
        $this->assertEquals(array(2 => '1'), $event->getData());
    }

    public function testFixZero()
    {
        $data = '0';
        $form = $this->getMock('Symfony\Component\Form\Test\FormInterface');
        $event = new FormEvent($form, $data);

        $listener = new FixRadioInputListener($this->choiceList, true);
        $listener->preSubmit($event);

        // Indices in SimpleChoiceList are zero-based generated integers
        $this->assertEquals(array(1 => '0'), $event->getData());
    }

    public function testFixEmptyString()
    {
        $data = '';
        $form = $this->getMock('Symfony\Component\Form\Test\FormInterface');
        $event = new FormEvent($form, $data);

        $listener = new FixRadioInputListener($this->choiceList, true);
        $listener->preSubmit($event);

        // Indices in SimpleChoiceList are zero-based generated integers
        $this->assertEquals(array(0 => ''), $event->getData());
    }

    public function testConvertEmptyStringToPlaceholderIfNotFound()
    {
        $list = new SimpleChoiceList(array(0 => 'A', 1 => 'B'));

        $data = '';
        $form = $this->getMock('Symfony\Component\Form\Test\FormInterface');
        $event = new FormEvent($form, $data);

        $listener = new FixRadioInputListener($list, true);
        $listener->preSubmit($event);

        $this->assertEquals(array('placeholder' => ''), $event->getData());
    }

    public function testDontConvertEmptyStringToPlaceholderIfNoPlaceholderUsed()
    {
        $list = new SimpleChoiceList(array(0 => 'A', 1 => 'B'));

        $data = '';
        $form = $this->getMock('Symfony\Component\Form\Test\FormInterface');
        $event = new FormEvent($form, $data);

        $listener = new FixRadioInputListener($list, false);
        $listener->preSubmit($event);

        $this->assertEquals(array(), $event->getData());
    }
}
PK��Z��!��$�$^test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/ResizeFormListenerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\EventListener;

use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Form\Extension\Core\EventListener\ResizeFormListener;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\FormEvent;

class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase
{
    private $dispatcher;
    private $factory;
    private $form;

    protected function setUp()
    {
        $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
        $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface');
        $this->form = $this->getBuilder()
            ->setCompound(true)
            ->setDataMapper($this->getDataMapper())
            ->getForm();
    }

    protected function tearDown()
    {
        $this->dispatcher = null;
        $this->factory = null;
        $this->form = null;
    }

    protected function getBuilder($name = 'name')
    {
        return new FormBuilder($name, null, $this->dispatcher, $this->factory);
    }

    protected function getForm($name = 'name')
    {
        return $this->getBuilder($name)->getForm();
    }

    /**
     * @return \PHPUnit_Framework_MockObject_MockObject
     */
    private function getDataMapper()
    {
        return $this->getMock('Symfony\Component\Form\DataMapperInterface');
    }

    protected function getMockForm()
    {
        return $this->getMock('Symfony\Component\Form\Test\FormInterface');
    }

    public function testPreSetDataResizesForm()
    {
        $this->form->add($this->getForm('0'));
        $this->form->add($this->getForm('1'));

        $this->factory->expects($this->at(0))
            ->method('createNamed')
            ->with(1, 'text', null, array('property_path' => '[1]', 'max_length' => 10, 'auto_initialize' => false))
            ->will($this->returnValue($this->getForm('1')));
        $this->factory->expects($this->at(1))
            ->method('createNamed')
            ->with(2, 'text', null, array('property_path' => '[2]', 'max_length' => 10, 'auto_initialize' => false))
            ->will($this->returnValue($this->getForm('2')));

        $data = array(1 => 'string', 2 => 'string');
        $event = new FormEvent($this->form, $data);
        $listener = new ResizeFormListener('text', array('max_length' => '10'), false, false);
        $listener->preSetData($event);

        $this->assertFalse($this->form->has('0'));
        $this->assertTrue($this->form->has('1'));
        $this->assertTrue($this->form->has('2'));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException
     */
    public function testPreSetDataRequiresArrayOrTraversable()
    {
        $data = 'no array or traversable';
        $event = new FormEvent($this->form, $data);
        $listener = new ResizeFormListener('text', array(), false, false);
        $listener->preSetData($event);
    }

    public function testPreSetDataDealsWithNullData()
    {
        $this->factory->expects($this->never())->method('createNamed');

        $data = null;
        $event = new FormEvent($this->form, $data);
        $listener = new ResizeFormListener('text', array(), false, false);
        $listener->preSetData($event);
    }

    public function testPreSubmitResizesUpIfAllowAdd()
    {
        $this->form->add($this->getForm('0'));

        $this->factory->expects($this->once())
            ->method('createNamed')
            ->with(1, 'text', null, array('property_path' => '[1]', 'max_length' => 10, 'auto_initialize' => false))
            ->will($this->returnValue($this->getForm('1')));

        $data = array(0 => 'string', 1 => 'string');
        $event = new FormEvent($this->form, $data);
        $listener = new ResizeFormListener('text', array('max_length' => 10), true, false);
        $listener->preSubmit($event);

        $this->assertTrue($this->form->has('0'));
        $this->assertTrue($this->form->has('1'));
    }

    public function testPreSubmitResizesDownIfAllowDelete()
    {
        $this->form->add($this->getForm('0'));
        $this->form->add($this->getForm('1'));

        $data = array(0 => 'string');
        $event = new FormEvent($this->form, $data);
        $listener = new ResizeFormListener('text', array(), false, true);
        $listener->preSubmit($event);

        $this->assertTrue($this->form->has('0'));
        $this->assertFalse($this->form->has('1'));
    }

    // fix for https://github.com/symfony/symfony/pull/493
    public function testPreSubmitRemovesZeroKeys()
    {
        $this->form->add($this->getForm('0'));

        $data = array();
        $event = new FormEvent($this->form, $data);
        $listener = new ResizeFormListener('text', array(), false, true);
        $listener->preSubmit($event);

        $this->assertFalse($this->form->has('0'));
    }

    public function testPreSubmitDoesNothingIfNotAllowAddNorAllowDelete()
    {
        $this->form->add($this->getForm('0'));
        $this->form->add($this->getForm('1'));

        $data = array(0 => 'string', 2 => 'string');
        $event = new FormEvent($this->form, $data);
        $listener = new ResizeFormListener('text', array(), false, false);
        $listener->preSubmit($event);

        $this->assertTrue($this->form->has('0'));
        $this->assertTrue($this->form->has('1'));
        $this->assertFalse($this->form->has('2'));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException
     */
    public function testPreSubmitRequiresArrayOrTraversable()
    {
        $data = 'no array or traversable';
        $event = new FormEvent($this->form, $data);
        $listener = new ResizeFormListener('text', array(), false, false);
        $listener->preSubmit($event);
    }

    public function testPreSubmitDealsWithNullData()
    {
        $this->form->add($this->getForm('1'));

        $data = null;
        $event = new FormEvent($this->form, $data);
        $listener = new ResizeFormListener('text', array(), false, true);
        $listener->preSubmit($event);

        $this->assertFalse($this->form->has('1'));
    }

    // fixes https://github.com/symfony/symfony/pull/40
    public function testPreSubmitDealsWithEmptyData()
    {
        $this->form->add($this->getForm('1'));

        $data = '';
        $event = new FormEvent($this->form, $data);
        $listener = new ResizeFormListener('text', array(), false, true);
        $listener->preSubmit($event);

        $this->assertFalse($this->form->has('1'));
    }

    public function testOnSubmitNormDataRemovesEntriesMissingInTheFormIfAllowDelete()
    {
        $this->form->add($this->getForm('1'));

        $data = array(0 => 'first', 1 => 'second', 2 => 'third');
        $event = new FormEvent($this->form, $data);
        $listener = new ResizeFormListener('text', array(), false, true);
        $listener->onSubmit($event);

        $this->assertEquals(array(1 => 'second'), $event->getData());
    }

    public function testOnSubmitNormDataDoesNothingIfNotAllowDelete()
    {
        $this->form->add($this->getForm('1'));

        $data = array(0 => 'first', 1 => 'second', 2 => 'third');
        $event = new FormEvent($this->form, $data);
        $listener = new ResizeFormListener('text', array(), false, false);
        $listener->onSubmit($event);

        $this->assertEquals($data, $event->getData());
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException
     */
    public function testOnSubmitNormDataRequiresArrayOrTraversable()
    {
        $data = 'no array or traversable';
        $event = new FormEvent($this->form, $data);
        $listener = new ResizeFormListener('text', array(), false, false);
        $listener->onSubmit($event);
    }

    public function testOnSubmitNormDataDealsWithNullData()
    {
        $this->form->add($this->getForm('1'));

        $data = null;
        $event = new FormEvent($this->form, $data);
        $listener = new ResizeFormListener('text', array(), false, true);
        $listener->onSubmit($event);

        $this->assertEquals(array(), $event->getData());
    }

    public function testOnSubmitDealsWithObjectBackedIteratorAggregate()
    {
        $this->form->add($this->getForm('1'));

        $data = new \ArrayObject(array(0 => 'first', 1 => 'second', 2 => 'third'));
        $event = new FormEvent($this->form, $data);
        $listener = new ResizeFormListener('text', array(), false, true);
        $listener->onSubmit($event);

        $this->assertArrayNotHasKey(0, $event->getData());
        $this->assertArrayNotHasKey(2, $event->getData());
    }

    public function testOnSubmitDealsWithArrayBackedIteratorAggregate()
    {
        $this->form->add($this->getForm('1'));

        $data = new ArrayCollection(array(0 => 'first', 1 => 'second', 2 => 'third'));
        $event = new FormEvent($this->form, $data);
        $listener = new ResizeFormListener('text', array(), false, true);
        $listener->onSubmit($event);

        $this->assertArrayNotHasKey(0, $event->getData());
        $this->assertArrayNotHasKey(2, $event->getData());
    }
}
PK��Zfk5s3	3	Xtest/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/TrimListenerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\EventListener;

use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\Extension\Core\EventListener\TrimListener;

class TrimListenerTest extends \PHPUnit_Framework_TestCase
{
    public function testTrim()
    {
        $data = " Foo! ";
        $form = $this->getMock('Symfony\Component\Form\Test\FormInterface');
        $event = new FormEvent($form, $data);

        $filter = new TrimListener();
        $filter->preSubmit($event);

        $this->assertEquals('Foo!', $event->getData());
    }

    public function testTrimSkipNonStrings()
    {
        $data = 1234;
        $form = $this->getMock('Symfony\Component\Form\Test\FormInterface');
        $event = new FormEvent($form, $data);

        $filter = new TrimListener();
        $filter->preSubmit($event);

        $this->assertSame(1234, $event->getData());
    }

    /**
     * @dataProvider codePointProvider
     */
    public function testTrimUtf8($chars)
    {
        if (!function_exists('mb_check_encoding')) {
            $this->markTestSkipped('The "mb_check_encoding" function is not available');
        }

        $data = mb_convert_encoding(pack('H*', implode('', $chars)), 'UTF-8', 'UCS-2BE');
        $data = $data."ab\ncd".$data;

        $form  = $this->getMock('Symfony\Component\Form\Test\FormInterface');
        $event = new FormEvent($form, $data);

        $filter = new TrimListener();
        $filter->preSubmit($event);

        $this->assertSame("ab\ncd", $event->getData(), 'TrimListener should trim character(s): '.implode(', ', $chars));
    }

    public function codePointProvider()
    {
        return array(
            'General category: Separator' => array(array('0020', '00A0', '1680', '180E', '2000', '2001', '2002', '2003', '2004', '2005', '2006', '2007', '2008', '2009', '200A', '2028', '2029', '202F', '205F', '3000')),
            'General category: Other, control' => array(array('0009', '000A', '000B', '000C', '000D', '0085')),
            //'General category: Other, format. ZERO WIDTH SPACE' => array(array('200B')),
        );
    }
}
PK��ZB+�K��ntest/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayObjectTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\EventListener;

use Symfony\Component\Form\FormBuilder;

class MergeCollectionListenerArrayObjectTest extends MergeCollectionListenerTest
{
    protected function getData(array $data)
    {
        return new \ArrayObject($data);
    }

    protected function getBuilder($name = 'name')
    {
        return new FormBuilder($name, '\ArrayObject', $this->dispatcher, $this->factory);
    }
}
PK��Z�@ڦttest/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerCustomArrayObjectTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\EventListener;

use Symfony\Component\Form\Tests\Fixtures\CustomArrayObject;
use Symfony\Component\Form\FormBuilder;

class MergeCollectionListenerCustomArrayObjectTest extends MergeCollectionListenerTest
{
    protected function getData(array $data)
    {
        return new CustomArrayObject($data);
    }

    protected function getBuilder($name = 'name')
    {
        return new FormBuilder($name, 'Symfony\Component\Form\Tests\Fixtures\CustomArrayObject', $this->dispatcher, $this->factory);
    }
}
PK��ZЭ
���htest/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\EventListener;

use Symfony\Component\Form\FormBuilder;

class MergeCollectionListenerArrayTest extends MergeCollectionListenerTest
{
    protected function getData(array $data)
    {
        return $data;
    }

    protected function getBuilder($name = 'name')
    {
        return new FormBuilder($name, null, $this->dispatcher, $this->factory);
    }
}
PK��Z��ggbtest/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\EventListener;

use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\Extension\Core\EventListener\FixUrlProtocolListener;

class FixUrlProtocolListenerTest extends \PHPUnit_Framework_TestCase
{
    public function testFixHttpUrl()
    {
        $data = "www.symfony.com";
        $form = $this->getMock('Symfony\Component\Form\Test\FormInterface');
        $event = new FormEvent($form, $data);

        $filter = new FixUrlProtocolListener('http');
        $filter->onSubmit($event);

        $this->assertEquals('http://www.symfony.com', $event->getData());
    }

    public function testSkipKnownUrl()
    {
        $data = "http://www.symfony.com";
        $form = $this->getMock('Symfony\Component\Form\Test\FormInterface');
        $event = new FormEvent($form, $data);

        $filter = new FixUrlProtocolListener('http');
        $filter->onSubmit($event);

        $this->assertEquals('http://www.symfony.com', $event->getData());
    }

    public function testSkipOtherProtocol()
    {
        $data = "ftp://www.symfony.com";
        $form = $this->getMock('Symfony\Component\Form\Test\FormInterface');
        $event = new FormEvent($form, $data);

        $filter = new FixUrlProtocolListener('http');
        $filter->onSubmit($event);

        $this->assertEquals('ftp://www.symfony.com', $event->getData());
    }
}
PK��Z�O�&ctest/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\EventListener;

use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\Extension\Core\EventListener\MergeCollectionListener;

abstract class MergeCollectionListenerTest extends \PHPUnit_Framework_TestCase
{
    protected $dispatcher;
    protected $factory;
    protected $form;

    protected function setUp()
    {
        $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
        $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface');
        $this->form = $this->getForm('axes');
    }

    protected function tearDown()
    {
        $this->dispatcher = null;
        $this->factory = null;
        $this->form = null;
    }

    abstract protected function getBuilder($name = 'name');

    protected function getForm($name = 'name', $propertyPath = null)
    {
        $propertyPath = $propertyPath ?: $name;

        return $this->getBuilder($name)->setAttribute('property_path', $propertyPath)->getForm();
    }

    protected function getMockForm()
    {
        return $this->getMock('Symfony\Component\Form\Test\FormInterface');
    }

    public function getBooleanMatrix1()
    {
        return array(
            array(true),
            array(false),
        );
    }

    public function getBooleanMatrix2()
    {
        return array(
            array(true, true),
            array(true, false),
            array(false, true),
            array(false, false),
        );
    }

    abstract protected function getData(array $data);

    /**
     * @dataProvider getBooleanMatrix1
     */
    public function testAddExtraEntriesIfAllowAdd($allowDelete)
    {
        $originalData = $this->getData(array(1 => 'second'));
        $newData = $this->getData(array(0 => 'first', 1 => 'second', 2 => 'third'));

        $listener = new MergeCollectionListener(true, $allowDelete);

        $this->form->setData($originalData);

        $event = new FormEvent($this->form, $newData);
        $listener->onSubmit($event);

        // The original object was modified
        if (is_object($originalData)) {
            $this->assertSame($originalData, $event->getData());
        }

        // The original object matches the new object
        $this->assertEquals($newData, $event->getData());
    }

    /**
     * @dataProvider getBooleanMatrix1
     */
    public function testAddExtraEntriesIfAllowAddDontOverwriteExistingIndices($allowDelete)
    {
        $originalData = $this->getData(array(1 => 'first'));
        $newData = $this->getData(array(0 => 'first', 1 => 'second'));

        $listener = new MergeCollectionListener(true, $allowDelete);

        $this->form->setData($originalData);

        $event = new FormEvent($this->form, $newData);
        $listener->onSubmit($event);

        // The original object was modified
        if (is_object($originalData)) {
            $this->assertSame($originalData, $event->getData());
        }

        // The original object matches the new object
        $this->assertEquals($this->getData(array(1 => 'first', 2 => 'second')), $event->getData());
    }

    /**
     * @dataProvider getBooleanMatrix1
     */
    public function testDoNothingIfNotAllowAdd($allowDelete)
    {
        $originalDataArray = array(1 => 'second');
        $originalData = $this->getData($originalDataArray);
        $newData = $this->getData(array(0 => 'first', 1 => 'second', 2 => 'third'));

        $listener = new MergeCollectionListener(false, $allowDelete);

        $this->form->setData($originalData);

        $event = new FormEvent($this->form, $newData);
        $listener->onSubmit($event);

        // We still have the original object
        if (is_object($originalData)) {
            $this->assertSame($originalData, $event->getData());
        }

        // Nothing was removed
        $this->assertEquals($this->getData($originalDataArray), $event->getData());
    }

    /**
     * @dataProvider getBooleanMatrix1
     */
    public function testRemoveMissingEntriesIfAllowDelete($allowAdd)
    {
        $originalData = $this->getData(array(0 => 'first', 1 => 'second', 2 => 'third'));
        $newData = $this->getData(array(1 => 'second'));

        $listener = new MergeCollectionListener($allowAdd, true);

        $this->form->setData($originalData);

        $event = new FormEvent($this->form, $newData);
        $listener->onSubmit($event);

        // The original object was modified
        if (is_object($originalData)) {
            $this->assertSame($originalData, $event->getData());
        }

        // The original object matches the new object
        $this->assertEquals($newData, $event->getData());
    }

    /**
     * @dataProvider getBooleanMatrix1
     */
    public function testDoNothingIfNotAllowDelete($allowAdd)
    {
        $originalDataArray = array(0 => 'first', 1 => 'second', 2 => 'third');
        $originalData = $this->getData($originalDataArray);
        $newData = $this->getData(array(1 => 'second'));

        $listener = new MergeCollectionListener($allowAdd, false);

        $this->form->setData($originalData);

        $event = new FormEvent($this->form, $newData);
        $listener->onSubmit($event);

        // We still have the original object
        if (is_object($originalData)) {
            $this->assertSame($originalData, $event->getData());
        }

        // Nothing was removed
        $this->assertEquals($this->getData($originalDataArray), $event->getData());
    }

    /**
     * @dataProvider getBooleanMatrix2
     * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException
     */
    public function testRequireArrayOrTraversable($allowAdd, $allowDelete)
    {
        $newData = 'no array or traversable';
        $event = new FormEvent($this->form, $newData);
        $listener = new MergeCollectionListener($allowAdd, $allowDelete);
        $listener->onSubmit($event);
    }

    public function testDealWithNullData()
    {
        $originalData = $this->getData(array(0 => 'first', 1 => 'second', 2 => 'third'));
        $newData = null;

        $listener = new MergeCollectionListener(false, false);

        $this->form->setData($originalData);

        $event = new FormEvent($this->form, $newData);
        $listener->onSubmit($event);

        $this->assertSame($originalData, $event->getData());
    }

    /**
     * @dataProvider getBooleanMatrix1
     */
    public function testDealWithNullOriginalDataIfAllowAdd($allowDelete)
    {
        $originalData = null;
        $newData = $this->getData(array(0 => 'first', 1 => 'second', 2 => 'third'));

        $listener = new MergeCollectionListener(true, $allowDelete);

        $this->form->setData($originalData);

        $event = new FormEvent($this->form, $newData);
        $listener->onSubmit($event);

        $this->assertSame($newData, $event->getData());
    }

    /**
     * @dataProvider getBooleanMatrix1
     */
    public function testDontDealWithNullOriginalDataIfNotAllowAdd($allowDelete)
    {
        $originalData = null;
        $newData = $this->getData(array(0 => 'first', 1 => 'second', 2 => 'third'));

        $listener = new MergeCollectionListener(false, $allowDelete);

        $this->form->setData($originalData);

        $event = new FormEvent($this->form, $newData);
        $listener->onSubmit($event);

        $this->assertNull($event->getData());
    }
}
PK��Z���� � Ytest/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList;

use Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList;
use Symfony\Component\Form\Extension\Core\View\ChoiceView;

class ObjectChoiceListTest_EntityWithToString
{
    private $property;

    public function __construct($property)
    {
        $this->property = $property;
    }

    public function __toString()
    {
        return $this->property;
    }
}

class ObjectChoiceListTest extends AbstractChoiceListTest
{
    private $obj1;

    private $obj2;

    private $obj3;

    private $obj4;

    protected function setUp()
    {
        $this->obj1 = (object) array('name' => 'A');
        $this->obj2 = (object) array('name' => 'B');
        $this->obj3 = (object) array('name' => 'C');
        $this->obj4 = (object) array('name' => 'D');

        parent::setUp();
    }

    public function testInitArray()
    {
        $this->list = new ObjectChoiceList(
            array($this->obj1, $this->obj2, $this->obj3, $this->obj4),
            'name',
            array($this->obj2)
        );

        $this->assertSame(array($this->obj1, $this->obj2, $this->obj3, $this->obj4), $this->list->getChoices());
        $this->assertSame(array('0', '1', '2', '3'), $this->list->getValues());
        $this->assertEquals(array(1 => new ChoiceView($this->obj2, '1', 'B')), $this->list->getPreferredViews());
        $this->assertEquals(array(0 => new ChoiceView($this->obj1, '0', 'A'), 2 => new ChoiceView($this->obj3, '2', 'C'), 3 => new ChoiceView($this->obj4, '3', 'D')), $this->list->getRemainingViews());
    }

    public function testInitNestedArray()
    {
        $this->assertSame(array($this->obj1, $this->obj2, $this->obj3, $this->obj4), $this->list->getChoices());
        $this->assertSame(array('0', '1', '2', '3'), $this->list->getValues());
        $this->assertEquals(array(
            'Group 1' => array(1 => new ChoiceView($this->obj2, '1', 'B')),
            'Group 2' => array(2 => new ChoiceView($this->obj3, '2', 'C'))
        ), $this->list->getPreferredViews());
        $this->assertEquals(array(
            'Group 1' => array(0 => new ChoiceView($this->obj1, '0', 'A')),
            'Group 2' => array(3 => new ChoiceView($this->obj4, '3', 'D'))
        ), $this->list->getRemainingViews());
    }

    public function testInitArrayWithGroupPath()
    {
        $this->obj1 = (object) array('name' => 'A', 'category' => 'Group 1');
        $this->obj2 = (object) array('name' => 'B', 'category' => 'Group 1');
        $this->obj3 = (object) array('name' => 'C', 'category' => 'Group 2');
        $this->obj4 = (object) array('name' => 'D', 'category' => 'Group 2');

        // Objects with NULL groups are not grouped
        $obj5 = (object) array('name' => 'E', 'category' => null);

        // Objects without the group property are not grouped either
        // see https://github.com/symfony/symfony/commit/d9b7abb7c7a0f28e0ce970afc5e305dce5dccddf
        $obj6 = (object) array('name' => 'F');

        $this->list = new ObjectChoiceList(
            array($this->obj1, $this->obj2, $this->obj3, $this->obj4, $obj5, $obj6),
            'name',
            array($this->obj2, $this->obj3),
            'category'
        );

        $this->assertSame(array($this->obj1, $this->obj2, $this->obj3, $this->obj4, $obj5, $obj6), $this->list->getChoices());
        $this->assertSame(array('0', '1', '2', '3', '4', '5'), $this->list->getValues());
        $this->assertEquals(array(
            'Group 1' => array(1 => new ChoiceView($this->obj2, '1', 'B')),
            'Group 2' => array(2 => new ChoiceView($this->obj3, '2', 'C'))
        ), $this->list->getPreferredViews());
        $this->assertEquals(array(
            'Group 1' => array(0 => new ChoiceView($this->obj1, '0', 'A')),
            'Group 2' => array(3 => new ChoiceView($this->obj4, '3', 'D')),
            4 => new ChoiceView($obj5, '4', 'E'),
            5 => new ChoiceView($obj6, '5', 'F'),
        ), $this->list->getRemainingViews());
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testInitArrayWithGroupPathThrowsExceptionIfNestedArray()
    {
        $this->obj1 = (object) array('name' => 'A', 'category' => 'Group 1');
        $this->obj2 = (object) array('name' => 'B', 'category' => 'Group 1');
        $this->obj3 = (object) array('name' => 'C', 'category' => 'Group 2');
        $this->obj4 = (object) array('name' => 'D', 'category' => 'Group 2');

        new ObjectChoiceList(
            array(
                'Group 1' => array($this->obj1, $this->obj2),
                'Group 2' => array($this->obj3, $this->obj4),
            ),
            'name',
            array($this->obj2, $this->obj3),
            'category'
        );
    }

    public function testInitArrayWithValuePath()
    {
        $this->obj1 = (object) array('name' => 'A', 'id' => 10);
        $this->obj2 = (object) array('name' => 'B', 'id' => 20);
        $this->obj3 = (object) array('name' => 'C', 'id' => 30);
        $this->obj4 = (object) array('name' => 'D', 'id' => 40);

        $this->list = new ObjectChoiceList(
            array($this->obj1, $this->obj2, $this->obj3, $this->obj4),
            'name',
            array($this->obj2, $this->obj3),
            null,
            'id'
        );

        $this->assertSame(array($this->obj1, $this->obj2, $this->obj3, $this->obj4), $this->list->getChoices());
        $this->assertSame(array('10', '20', '30', '40'), $this->list->getValues());
        $this->assertEquals(array(1 => new ChoiceView($this->obj2, '20', 'B'), 2 => new ChoiceView($this->obj3, '30', 'C')), $this->list->getPreferredViews());
        $this->assertEquals(array(0 => new ChoiceView($this->obj1, '10', 'A'), 3 => new ChoiceView($this->obj4, '40', 'D')), $this->list->getRemainingViews());
    }

    public function testInitArrayUsesToString()
    {
        $this->obj1 = new ObjectChoiceListTest_EntityWithToString('A');
        $this->obj2 = new ObjectChoiceListTest_EntityWithToString('B');
        $this->obj3 = new ObjectChoiceListTest_EntityWithToString('C');
        $this->obj4 = new ObjectChoiceListTest_EntityWithToString('D');

        $this->list = new ObjectChoiceList(
            array($this->obj1, $this->obj2, $this->obj3, $this->obj4)
        );

        $this->assertSame(array($this->obj1, $this->obj2, $this->obj3, $this->obj4), $this->list->getChoices());
        $this->assertSame(array('0', '1', '2', '3'), $this->list->getValues());
        $this->assertEquals(array(0 => new ChoiceView($this->obj1, '0', 'A'), 1 => new ChoiceView($this->obj2, '1', 'B'), 2 => new ChoiceView($this->obj3, '2', 'C'), 3 => new ChoiceView($this->obj4, '3', 'D')), $this->list->getRemainingViews());
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\StringCastException
     */
    public function testInitArrayThrowsExceptionIfToStringNotFound()
    {
        $this->obj1 = new ObjectChoiceListTest_EntityWithToString('A');
        $this->obj2 = new ObjectChoiceListTest_EntityWithToString('B');
        $this->obj3 = (object) array('name' => 'C');
        $this->obj4 = new ObjectChoiceListTest_EntityWithToString('D');

        new ObjectChoiceList(
            array($this->obj1, $this->obj2, $this->obj3, $this->obj4)
        );
    }

    /**
     * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface
     */
    protected function createChoiceList()
    {
        return new ObjectChoiceList(
            array(
                'Group 1' => array($this->obj1, $this->obj2),
                'Group 2' => array($this->obj3, $this->obj4),
            ),
            'name',
            array($this->obj2, $this->obj3)
        );
    }

    protected function getChoices()
    {
        return array(0 => $this->obj1, 1 => $this->obj2, 2 => $this->obj3, 3 => $this->obj4);
    }

    protected function getLabels()
    {
        return array(0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D');
    }

    protected function getValues()
    {
        return array(0 => '0', 1 => '1', 2 => '2', 3 => '3');
    }

    protected function getIndices()
    {
        return array(0, 1, 2, 3);
    }
}
PK��Z�.�p))Stest/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ChoiceListTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList;

use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList;
use Symfony\Component\Form\Extension\Core\View\ChoiceView;

class ChoiceListTest extends AbstractChoiceListTest
{
    private $obj1;

    private $obj2;

    private $obj3;

    private $obj4;

    protected function setUp()
    {
        $this->obj1 = new \stdClass();
        $this->obj2 = new \stdClass();
        $this->obj3 = new \stdClass();
        $this->obj4 = new \stdClass();

        parent::setUp();
    }

    public function testInitArray()
    {
        $this->list = new ChoiceList(
            array($this->obj1, $this->obj2, $this->obj3, $this->obj4),
            array('A', 'B', 'C', 'D'),
            array($this->obj2)
        );

        $this->assertSame(array($this->obj1, $this->obj2, $this->obj3, $this->obj4), $this->list->getChoices());
        $this->assertSame(array('0', '1', '2', '3'), $this->list->getValues());
        $this->assertEquals(array(1 => new ChoiceView($this->obj2, '1', 'B')), $this->list->getPreferredViews());
        $this->assertEquals(array(0 => new ChoiceView($this->obj1, '0', 'A'), 2 => new ChoiceView($this->obj3, '2', 'C'), 3 => new ChoiceView($this->obj4, '3', 'D')), $this->list->getRemainingViews());
    }

    /**
     * Necessary for interoperability with MongoDB cursors or ORM relations as
     * choices parameter. A choice itself that is an object implementing \Traversable
     * is not treated as hierarchical structure, but as-is.
     */
    public function testInitNestedTraversable()
    {
        $traversableChoice = new \ArrayIterator(array($this->obj3, $this->obj4));

        $this->list = new ChoiceList(
            new \ArrayIterator(array(
                'Group' => array($this->obj1, $this->obj2),
                'Not a Group' => $traversableChoice
            )),
            array(
                'Group' => array('A', 'B'),
                'Not a Group' => 'C',
            ),
            array($this->obj2)
        );

        $this->assertSame(array($this->obj1, $this->obj2, $traversableChoice), $this->list->getChoices());
        $this->assertSame(array('0', '1', '2'), $this->list->getValues());
        $this->assertEquals(array(
            'Group' => array(1 => new ChoiceView($this->obj2, '1', 'B'))
        ), $this->list->getPreferredViews());
        $this->assertEquals(array(
            'Group' => array(0 => new ChoiceView($this->obj1, '0', 'A')),
            2 => new ChoiceView($traversableChoice, '2', 'C')
        ), $this->list->getRemainingViews());
    }

    public function testInitNestedArray()
    {
        $this->assertSame(array($this->obj1, $this->obj2, $this->obj3, $this->obj4), $this->list->getChoices());
        $this->assertSame(array('0', '1', '2', '3'), $this->list->getValues());
        $this->assertEquals(array(
            'Group 1' => array(1 => new ChoiceView($this->obj2, '1', 'B')),
            'Group 2' => array(2 => new ChoiceView($this->obj3, '2', 'C'))
        ), $this->list->getPreferredViews());
        $this->assertEquals(array(
            'Group 1' => array(0 => new ChoiceView($this->obj1, '0', 'A')),
            'Group 2' => array(3 => new ChoiceView($this->obj4, '3', 'D'))
        ), $this->list->getRemainingViews());
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testInitWithInsufficientLabels()
    {
        $this->list = new ChoiceList(
            array($this->obj1, $this->obj2),
            array('A')
        );
    }

    public function testInitWithLabelsContainingNull()
    {
        $this->list = new ChoiceList(
            array($this->obj1, $this->obj2),
            array('A', null)
        );

        $this->assertEquals(
            array(0 => new ChoiceView($this->obj1, '0', 'A'), 1 => new ChoiceView($this->obj2, '1', null)),
            $this->list->getRemainingViews()
        );
    }

    /**
     * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface
     */
    protected function createChoiceList()
    {
        return new ChoiceList(
            array(
                'Group 1' => array($this->obj1, $this->obj2),
                'Group 2' => array($this->obj3, $this->obj4),
            ),
            array(
                'Group 1' => array('A', 'B'),
                'Group 2' => array('C', 'D'),
            ),
            array($this->obj2, $this->obj3)
        );
    }

    protected function getChoices()
    {
        return array(0 => $this->obj1, 1 => $this->obj2, 2 => $this->obj3, 3 => $this->obj4);
    }

    protected function getLabels()
    {
        return array(0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D');
    }

    protected function getValues()
    {
        return array(0 => '0', 1 => '1', 2 => '2', 3 => '3');
    }

    protected function getIndices()
    {
        return array(0, 1, 2, 3);
    }
}
PK��Z�![���[test/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
abstract class AbstractChoiceListTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface
     */
    protected $list;

    /**
     * @var array
     */
    protected $choices;

    /**
     * @var array
     */
    protected $values;

    /**
     * @var array
     */
    protected $indices;

    /**
     * @var array
     */
    protected $labels;

    /**
     * @var mixed
     */
    protected $choice1;

    /**
     * @var mixed
     */
    protected $choice2;

    /**
     * @var mixed
     */
    protected $choice3;

    /**
     * @var mixed
     */
    protected $choice4;

    /**
     * @var string
     */
    protected $value1;

    /**
     * @var string
     */
    protected $value2;

    /**
     * @var string
     */
    protected $value3;

    /**
     * @var string
     */
    protected $value4;

    /**
     * @var int|string
     */
    protected $index1;

    /**
     * @var int|string
     */
    protected $index2;

    /**
     * @var int|string
     */
    protected $index3;

    /**
     * @var int|string
     */
    protected $index4;

    /**
     * @var string
     */
    protected $label1;

    /**
     * @var string
     */
    protected $label2;

    /**
     * @var string
     */
    protected $label3;

    /**
     * @var string
     */
    protected $label4;

    protected function setUp()
    {
        parent::setUp();

        $this->list = $this->createChoiceList();

        $this->choices = $this->getChoices();
        $this->indices = $this->getIndices();
        $this->values = $this->getValues();
        $this->labels = $this->getLabels();

        // allow access to the individual entries without relying on their indices
        reset($this->choices);
        reset($this->indices);
        reset($this->values);
        reset($this->labels);

        for ($i = 1; $i <= 4; ++$i) {
            $this->{'choice'.$i} = current($this->choices);
            $this->{'index'.$i} = current($this->indices);
            $this->{'value'.$i} = current($this->values);
            $this->{'label'.$i} = current($this->labels);

            next($this->choices);
            next($this->indices);
            next($this->values);
            next($this->labels);
        }
    }

    public function testGetChoices()
    {
        $this->assertSame($this->choices, $this->list->getChoices());
    }

    public function testGetValues()
    {
        $this->assertSame($this->values, $this->list->getValues());
    }

    public function testGetIndicesForChoices()
    {
        $choices = array($this->choice1, $this->choice2);
        $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForChoices($choices));
    }

    public function testGetIndicesForChoicesPreservesKeys()
    {
        $choices = array(5 => $this->choice1, 8 => $this->choice2);
        $this->assertSame(array(5 => $this->index1, 8 => $this->index2), $this->list->getIndicesForChoices($choices));
    }

    public function testGetIndicesForChoicesPreservesOrder()
    {
        $choices = array($this->choice2, $this->choice1);
        $this->assertSame(array($this->index2, $this->index1), $this->list->getIndicesForChoices($choices));
    }

    public function testGetIndicesForChoicesIgnoresNonExistingChoices()
    {
        $choices = array($this->choice1, $this->choice2, 'foobar');
        $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForChoices($choices));
    }

    public function testGetIndicesForChoicesEmpty()
    {
        $this->assertSame(array(), $this->list->getIndicesForChoices(array()));
    }

    public function testGetIndicesForValues()
    {
        // values and indices are always the same
        $values = array($this->value1, $this->value2);
        $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForValues($values));
    }

    public function testGetIndicesForValuesPreservesKeys()
    {
        // values and indices are always the same
        $values = array(5 => $this->value1, 8 => $this->value2);
        $this->assertSame(array(5 => $this->index1, 8 => $this->index2), $this->list->getIndicesForValues($values));
    }

    public function testGetIndicesForValuesPreservesOrder()
    {
        $values = array($this->value2, $this->value1);
        $this->assertSame(array($this->index2, $this->index1), $this->list->getIndicesForValues($values));
    }

    public function testGetIndicesForValuesIgnoresNonExistingValues()
    {
        $values = array($this->value1, $this->value2, 'foobar');
        $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForValues($values));
    }

    public function testGetIndicesForValuesEmpty()
    {
        $this->assertSame(array(), $this->list->getIndicesForValues(array()));
    }

    public function testGetChoicesForValues()
    {
        $values = array($this->value1, $this->value2);
        $this->assertSame(array($this->choice1, $this->choice2), $this->list->getChoicesForValues($values));
    }

    public function testGetChoicesForValuesPreservesKeys()
    {
        $values = array(5 => $this->value1, 8 => $this->value2);
        $this->assertSame(array(5 => $this->choice1, 8 => $this->choice2), $this->list->getChoicesForValues($values));
    }

    public function testGetChoicesForValuesPreservesOrder()
    {
        $values = array($this->value2, $this->value1);
        $this->assertSame(array($this->choice2, $this->choice1), $this->list->getChoicesForValues($values));
    }

    public function testGetChoicesForValuesIgnoresNonExistingValues()
    {
        $values = array($this->value1, $this->value2, 'foobar');
        $this->assertSame(array($this->choice1, $this->choice2), $this->list->getChoicesForValues($values));
    }

    // https://github.com/symfony/symfony/issues/3446
    public function testGetChoicesForValuesEmpty()
    {
        $this->assertSame(array(), $this->list->getChoicesForValues(array()));
    }

    public function testGetValuesForChoices()
    {
        $choices = array($this->choice1, $this->choice2);
        $this->assertSame(array($this->value1, $this->value2), $this->list->getValuesForChoices($choices));
    }

    public function testGetValuesForChoicesPreservesKeys()
    {
        $choices = array(5 => $this->choice1, 8 => $this->choice2);
        $this->assertSame(array(5 => $this->value1, 8 => $this->value2), $this->list->getValuesForChoices($choices));
    }

    public function testGetValuesForChoicesPreservesOrder()
    {
        $choices = array($this->choice2, $this->choice1);
        $this->assertSame(array($this->value2, $this->value1), $this->list->getValuesForChoices($choices));
    }

    public function testGetValuesForChoicesIgnoresNonExistingChoices()
    {
        $choices = array($this->choice1, $this->choice2, 'foobar');
        $this->assertSame(array($this->value1, $this->value2), $this->list->getValuesForChoices($choices));
    }

    public function testGetValuesForChoicesEmpty()
    {
        $this->assertSame(array(), $this->list->getValuesForChoices(array()));
    }

    /**
     * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface
     */
    abstract protected function createChoiceList();

    abstract protected function getChoices();

    abstract protected function getLabels();

    abstract protected function getValues();

    abstract protected function getIndices();
}
PK��Z�gUI��Wtest/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList;

use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList;
use Symfony\Component\Form\Extension\Core\ChoiceList\LazyChoiceList;
use Symfony\Component\Form\Extension\Core\View\ChoiceView;

class LazyChoiceListTest extends \PHPUnit_Framework_TestCase
{
    private $list;

    protected function setUp()
    {
        parent::setUp();

        $this->list = new LazyChoiceListTest_Impl(new SimpleChoiceList(array(
            'a' => 'A',
            'b' => 'B',
            'c' => 'C',
        ), array('b')));
    }

    protected function tearDown()
    {
        parent::tearDown();

        $this->list = null;
    }

    public function testGetChoices()
    {
        $this->assertSame(array(0 => 'a', 1 => 'b', 2 => 'c'), $this->list->getChoices());
    }

    public function testGetValues()
    {
        $this->assertSame(array(0 => 'a', 1 => 'b', 2 => 'c'), $this->list->getValues());
    }

    public function testGetPreferredViews()
    {
        $this->assertEquals(array(1 => new ChoiceView('b', 'b', 'B')), $this->list->getPreferredViews());
    }

    public function testGetRemainingViews()
    {
        $this->assertEquals(array(0 => new ChoiceView('a', 'a', 'A'), 2 => new ChoiceView('c', 'c', 'C')), $this->list->getRemainingViews());
    }

    public function testGetIndicesForChoices()
    {
        $choices = array('b', 'c');
        $this->assertSame(array(1, 2), $this->list->getIndicesForChoices($choices));
    }

    public function testGetIndicesForValues()
    {
        $values = array('b', 'c');
        $this->assertSame(array(1, 2), $this->list->getIndicesForValues($values));
    }

    public function testGetChoicesForValues()
    {
        $values = array('b', 'c');
        $this->assertSame(array('b', 'c'), $this->list->getChoicesForValues($values));
    }

    public function testGetValuesForChoices()
    {
        $choices = array('b', 'c');
        $this->assertSame(array('b', 'c'), $this->list->getValuesForChoices($choices));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException
     */
    public function testLoadChoiceListShouldReturnChoiceList()
    {
        $list = new LazyChoiceListTest_InvalidImpl();

        $list->getChoices();
    }
}

class LazyChoiceListTest_Impl extends LazyChoiceList
{
    private $choiceList;

    public function __construct($choiceList)
    {
        $this->choiceList = $choiceList;
    }

    protected function loadChoiceList()
    {
        return $this->choiceList;
    }
}

class LazyChoiceListTest_InvalidImpl extends LazyChoiceList
{
    protected function loadChoiceList()
    {
        return new \stdClass();
    }
}
PK��ZR��
�
Ytest/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList;

use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList;
use Symfony\Component\Form\Extension\Core\View\ChoiceView;

class SimpleChoiceListTest extends AbstractChoiceListTest
{
    public function testInitArray()
    {
        $choices = array('a' => 'A', 'b' => 'B', 'c' => 'C');
        $this->list = new SimpleChoiceList($choices, array('b'));

        $this->assertSame(array(0 => 'a', 1 => 'b', 2 => 'c'), $this->list->getChoices());
        $this->assertSame(array(0 => 'a', 1 => 'b', 2 => 'c'), $this->list->getValues());
        $this->assertEquals(array(1 => new ChoiceView('b', 'b', 'B')), $this->list->getPreferredViews());
        $this->assertEquals(array(0 => new ChoiceView('a', 'a', 'A'), 2 => new ChoiceView('c', 'c', 'C')), $this->list->getRemainingViews());
    }

    public function testInitNestedArray()
    {
        $this->assertSame(array(0 => 'a', 1 => 'b', 2 => 'c', 3 => 'd'), $this->list->getChoices());
        $this->assertSame(array(0 => 'a', 1 => 'b', 2 => 'c', 3 => 'd'), $this->list->getValues());
        $this->assertEquals(array(
            'Group 1' => array(1 => new ChoiceView('b', 'b', 'B')),
            'Group 2' => array(2 => new ChoiceView('c', 'c', 'C'))
        ), $this->list->getPreferredViews());
        $this->assertEquals(array(
            'Group 1' => array(0 => new ChoiceView('a', 'a', 'A')),
            'Group 2' => array(3 => new ChoiceView('d', 'd', 'D'))
        ), $this->list->getRemainingViews());
    }

    /**
     * @dataProvider dirtyValuesProvider
     */
    public function testGetValuesForChoicesDealsWithDirtyValues($choice, $value)
    {
        $choices = array(
            '0' => 'Zero',
            '1' => 'One',
            '' => 'Empty',
            '1.23' => 'Float',
            'foo' => 'Foo',
            'foo10' => 'Foo 10',
        );

        $this->list = new SimpleChoiceList($choices, array());

        $this->assertSame(array($value), $this->list->getValuesForChoices(array($choice)));
    }

    public function dirtyValuesProvider()
    {
        return array(
            array(0, '0'),
            array('0', '0'),
            array('1', '1'),
            array(false, '0'),
            array(true, '1'),
            array('', ''),
            array(null, ''),
            array('1.23', '1.23'),
            array('foo', 'foo'),
            array('foo10', 'foo10'),
        );
    }

    /**
     * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface
     */
    protected function createChoiceList()
    {
        return new SimpleChoiceList(array(
            'Group 1' => array('a' => 'A', 'b' => 'B'),
            'Group 2' => array('c' => 'C', 'd' => 'D'),
        ), array('b', 'c'));
    }

    protected function getChoices()
    {
        return array(0 => 'a', 1 => 'b', 2 => 'c', 3 => 'd');
    }

    protected function getLabels()
    {
        return array(0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D');
    }

    protected function getValues()
    {
        return array(0 => 'a', 1 => 'b', 2 => 'c', 3 => 'd');
    }

    protected function getIndices()
    {
        return array(0, 1, 2, 3);
    }
}
PK��Z��x��`test/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList;

use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList;

class SimpleNumericChoiceListTest extends AbstractChoiceListTest
{
    public function testGetIndicesForChoicesDealsWithNumericChoices()
    {
        // Pass choices as strings although they are integers
        $choices = array('0', '1');
        $this->assertSame(array(0, 1), $this->list->getIndicesForChoices($choices));
    }

    public function testGetIndicesForValuesDealsWithNumericValues()
    {
        // Pass values as strings although they are integers
        $values = array('0', '1');
        $this->assertSame(array(0, 1), $this->list->getIndicesForValues($values));
    }

    public function testGetChoicesForValuesDealsWithNumericValues()
    {
        // Pass values as strings although they are integers
        $values = array('0', '1');
        $this->assertSame(array(0, 1), $this->list->getChoicesForValues($values));
    }

    public function testGetValuesForChoicesDealsWithNumericValues()
    {
        // Pass values as strings although they are integers
        $values = array('0', '1');

        $this->assertSame(array('0', '1'), $this->list->getValuesForChoices($values));
    }

    /**
     * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface
     */
    protected function createChoiceList()
    {
        return new SimpleChoiceList(array(
            'Group 1' => array(0 => 'A', 1 => 'B'),
            'Group 2' => array(2 => 'C', 3 => 'D'),
        ), array(1, 2));
    }

    protected function getChoices()
    {
        return array(0 => 0, 1 => 1, 2 => 2, 3 => 3);
    }

    protected function getLabels()
    {
        return array(0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D');
    }

    protected function getValues()
    {
        return array(0 => '0', 1 => '1', 2 => '2', 3 => '3');
    }

    protected function getIndices()
    {
        return array(0, 1, 2, 3);
    }
}
PK��Z?�R8�.�.[test/Form/Symfony/Component/Form/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\DataMapper;

use Symfony\Component\Form\FormConfigBuilder;
use Symfony\Component\Form\FormConfigInterface;
use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;

class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var PropertyPathMapper
     */
    private $mapper;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $dispatcher;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $propertyAccessor;

    protected function setUp()
    {
        $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
        $this->propertyAccessor = $this->getMock('Symfony\Component\PropertyAccess\PropertyAccessorInterface');
        $this->mapper = new PropertyPathMapper($this->propertyAccessor);
    }

    /**
     * @param $path
     * @return \PHPUnit_Framework_MockObject_MockObject
     */
    private function getPropertyPath($path)
    {
        return $this->getMockBuilder('Symfony\Component\PropertyAccess\PropertyPath')
            ->setConstructorArgs(array($path))
            ->setMethods(array('getValue', 'setValue'))
            ->getMock();
    }

    /**
     * @param FormConfigInterface $config
     * @param Boolean $synchronized
     * @param Boolean $submitted
     * @return \PHPUnit_Framework_MockObject_MockObject
     */
    private function getForm(FormConfigInterface $config, $synchronized = true, $submitted = true)
    {
        $form = $this->getMockBuilder('Symfony\Component\Form\Form')
            ->setConstructorArgs(array($config))
            ->setMethods(array('isSynchronized', 'isSubmitted'))
            ->getMock();

        $form->expects($this->any())
            ->method('isSynchronized')
            ->will($this->returnValue($synchronized));

        $form->expects($this->any())
            ->method('isSubmitted')
            ->will($this->returnValue($submitted));

        return $form;
    }

    /**
     * @return \PHPUnit_Framework_MockObject_MockObject
     */
    private function getDataMapper()
    {
        return $this->getMock('Symfony\Component\Form\DataMapperInterface');
    }

    public function testMapDataToFormsPassesObjectRefIfByReference()
    {
        $car = new \stdClass();
        $engine = new \stdClass();
        $propertyPath = $this->getPropertyPath('engine');

        $this->propertyAccessor->expects($this->once())
            ->method('getValue')
            ->with($car, $propertyPath)
            ->will($this->returnValue($engine));

        $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher);
        $config->setByReference(true);
        $config->setPropertyPath($propertyPath);
        $form = $this->getForm($config);

        $this->mapper->mapDataToForms($car, array($form));

        // Can't use isIdentical() above because mocks always clone their
        // arguments which can't be disabled in PHPUnit 3.6
        $this->assertSame($engine, $form->getData());
    }

    public function testMapDataToFormsPassesObjectCloneIfNotByReference()
    {
        $car = new \stdClass();
        $engine = new \stdClass();
        $propertyPath = $this->getPropertyPath('engine');

        $this->propertyAccessor->expects($this->once())
            ->method('getValue')
            ->with($car, $propertyPath)
            ->will($this->returnValue($engine));

        $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher);
        $config->setByReference(false);
        $config->setPropertyPath($propertyPath);
        $form = $this->getForm($config);

        $this->mapper->mapDataToForms($car, array($form));

        $this->assertNotSame($engine, $form->getData());
        $this->assertEquals($engine, $form->getData());
    }

    public function testMapDataToFormsIgnoresEmptyPropertyPath()
    {
        $car = new \stdClass();

        $config = new FormConfigBuilder(null, '\stdClass', $this->dispatcher);
        $config->setByReference(true);
        $form = $this->getForm($config);

        $this->assertNull($form->getPropertyPath());

        $this->mapper->mapDataToForms($car, array($form));

        $this->assertNull($form->getData());
    }

    public function testMapDataToFormsIgnoresUnmapped()
    {
        $car = new \stdClass();
        $propertyPath = $this->getPropertyPath('engine');

        $this->propertyAccessor->expects($this->never())
            ->method('getValue');

        $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher);
        $config->setByReference(true);
        $config->setMapped(false);
        $config->setPropertyPath($propertyPath);
        $form = $this->getForm($config);

        $this->mapper->mapDataToForms($car, array($form));

        $this->assertNull($form->getData());
    }

    public function testMapDataToFormsSetsDefaultDataIfPassedDataIsNull()
    {
        $default = new \stdClass();
        $propertyPath = $this->getPropertyPath('engine');

        $this->propertyAccessor->expects($this->never())
            ->method('getValue');

        $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher);
        $config->setByReference(true);
        $config->setPropertyPath($propertyPath);
        $config->setData($default);

        $form = $this->getMockBuilder('Symfony\Component\Form\Form')
            ->setConstructorArgs(array($config))
            ->setMethods(array('setData'))
            ->getMock();

        $form->expects($this->once())
            ->method('setData')
            ->with($default);

        $this->mapper->mapDataToForms(null, array($form));
    }

    public function testMapDataToFormsSetsDefaultDataIfPassedDataIsEmptyArray()
    {
        $default = new \stdClass();
        $propertyPath = $this->getPropertyPath('engine');

        $this->propertyAccessor->expects($this->never())
            ->method('getValue');

        $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher);
        $config->setByReference(true);
        $config->setPropertyPath($propertyPath);
        $config->setData($default);

        $form = $this->getMockBuilder('Symfony\Component\Form\Form')
            ->setConstructorArgs(array($config))
            ->setMethods(array('setData'))
            ->getMock();

        $form->expects($this->once())
            ->method('setData')
            ->with($default);

        $this->mapper->mapDataToForms(array(), array($form));
    }

    public function testMapFormsToDataWritesBackIfNotByReference()
    {
        $car = new \stdClass();
        $engine = new \stdClass();
        $propertyPath = $this->getPropertyPath('engine');

        $this->propertyAccessor->expects($this->once())
            ->method('setValue')
            ->with($car, $propertyPath, $engine);

        $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher);
        $config->setByReference(false);
        $config->setPropertyPath($propertyPath);
        $config->setData($engine);
        $form = $this->getForm($config);

        $this->mapper->mapFormsToData(array($form), $car);
    }

    public function testMapFormsToDataWritesBackIfByReferenceButNoReference()
    {
        $car = new \stdClass();
        $engine = new \stdClass();
        $propertyPath = $this->getPropertyPath('engine');

        $this->propertyAccessor->expects($this->once())
            ->method('setValue')
            ->with($car, $propertyPath, $engine);

        $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher);
        $config->setByReference(true);
        $config->setPropertyPath($propertyPath);
        $config->setData($engine);
        $form = $this->getForm($config);

        $this->mapper->mapFormsToData(array($form), $car);
    }

    public function testMapFormsToDataWritesBackIfByReferenceAndReference()
    {
        $car = new \stdClass();
        $engine = new \stdClass();
        $propertyPath = $this->getPropertyPath('engine');

        // $car already contains the reference of $engine
        $this->propertyAccessor->expects($this->once())
            ->method('getValue')
            ->with($car, $propertyPath)
            ->will($this->returnValue($engine));

        $this->propertyAccessor->expects($this->never())
            ->method('setValue');

        $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher);
        $config->setByReference(true);
        $config->setPropertyPath($propertyPath);
        $config->setData($engine);
        $form = $this->getForm($config);

        $this->mapper->mapFormsToData(array($form), $car);
    }

    public function testMapFormsToDataIgnoresUnmapped()
    {
        $car = new \stdClass();
        $engine = new \stdClass();
        $propertyPath = $this->getPropertyPath('engine');

        $this->propertyAccessor->expects($this->never())
            ->method('setValue');

        $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher);
        $config->setByReference(true);
        $config->setPropertyPath($propertyPath);
        $config->setData($engine);
        $config->setMapped(false);
        $form = $this->getForm($config);

        $this->mapper->mapFormsToData(array($form), $car);
    }

    public function testMapFormsToDataIgnoresUnsubmittedForms()
    {
        $car = new \stdClass();
        $engine = new \stdClass();
        $propertyPath = $this->getPropertyPath('engine');

        $this->propertyAccessor->expects($this->never())
            ->method('setValue');

        $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher);
        $config->setByReference(true);
        $config->setPropertyPath($propertyPath);
        $config->setData($engine);
        $form = $this->getForm($config, true, false);

        $this->mapper->mapFormsToData(array($form), $car);
    }

    public function testMapFormsToDataIgnoresEmptyData()
    {
        $car = new \stdClass();
        $propertyPath = $this->getPropertyPath('engine');

        $this->propertyAccessor->expects($this->never())
            ->method('setValue');

        $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher);
        $config->setByReference(true);
        $config->setPropertyPath($propertyPath);
        $config->setData(null);
        $form = $this->getForm($config);

        $this->mapper->mapFormsToData(array($form), $car);
    }

    public function testMapFormsToDataIgnoresUnsynchronized()
    {
        $car = new \stdClass();
        $engine = new \stdClass();
        $propertyPath = $this->getPropertyPath('engine');

        $this->propertyAccessor->expects($this->never())
            ->method('setValue');

        $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher);
        $config->setByReference(true);
        $config->setPropertyPath($propertyPath);
        $config->setData($engine);
        $form = $this->getForm($config, false);

        $this->mapper->mapFormsToData(array($form), $car);
    }

    public function testMapFormsToDataIgnoresDisabled()
    {
        $car = new \stdClass();
        $engine = new \stdClass();
        $propertyPath = $this->getPropertyPath('engine');

        $this->propertyAccessor->expects($this->never())
            ->method('setValue');

        $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher);
        $config->setByReference(true);
        $config->setPropertyPath($propertyPath);
        $config->setData($engine);
        $config->setDisabled(true);
        $form = $this->getForm($config);

        $this->mapper->mapFormsToData(array($form), $car);
    }
}
PK��Z���4��ftest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ChoiceToValueTransformerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;

use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList;
use Symfony\Component\Form\Extension\Core\DataTransformer\ChoiceToValueTransformer;

class ChoiceToValueTransformerTest extends \PHPUnit_Framework_TestCase
{
    protected $transformer;

    protected function setUp()
    {
        $list = new SimpleChoiceList(array('' => 'A', 0 => 'B', 1 => 'C'));
        $this->transformer = new ChoiceToValueTransformer($list);
    }

    protected function tearDown()
    {
        $this->transformer = null;
    }

    public function transformProvider()
    {
        return array(
            // more extensive test set can be found in FormUtilTest
            array(0, '0'),
            array(false, '0'),
            array('', ''),
        );
    }

    /**
     * @dataProvider transformProvider
     */
    public function testTransform($in, $out)
    {
        $this->assertSame($out, $this->transformer->transform($in));
    }

    public function reverseTransformProvider()
    {
        return array(
            // values are expected to be valid choice keys already and stay
            // the same
            array('0', 0),
            array('', null),
            array(null, null),
        );
    }

    /**
     * @dataProvider reverseTransformProvider
     */
    public function testReverseTransform($in, $out)
    {
        $this->assertSame($out, $this->transformer->reverseTransform($in));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformExpectsScalar()
    {
        $this->transformer->reverseTransform(array());
    }
}
PK��Z�����qtest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;

use Symfony\Component\Form\Extension\Core\DataTransformer\PercentToLocalizedStringTransformer;
use Symfony\Component\Intl\Util\IntlTestHelper;

class PercentToLocalizedStringTransformerTest extends \PHPUnit_Framework_TestCase
{
    protected function setUp()
    {
        parent::setUp();

        // Since we test against "de_AT", we need the full implementation
        IntlTestHelper::requireFullIntl($this);

        \Locale::setDefault('de_AT');
    }

    public function testTransform()
    {
        $transformer = new PercentToLocalizedStringTransformer();

        $this->assertEquals('10', $transformer->transform(0.1));
        $this->assertEquals('15', $transformer->transform(0.15));
        $this->assertEquals('12', $transformer->transform(0.1234));
        $this->assertEquals('200', $transformer->transform(2));
    }

    public function testTransformEmpty()
    {
        $transformer = new PercentToLocalizedStringTransformer();

        $this->assertEquals('', $transformer->transform(null));
    }

    public function testTransformWithInteger()
    {
        $transformer = new PercentToLocalizedStringTransformer(null, 'integer');

        $this->assertEquals('0', $transformer->transform(0.1));
        $this->assertEquals('1', $transformer->transform(1));
        $this->assertEquals('15', $transformer->transform(15));
        $this->assertEquals('16', $transformer->transform(15.9));
    }

    public function testTransformWithPrecision()
    {
        $transformer = new PercentToLocalizedStringTransformer(2);

        $this->assertEquals('12,34', $transformer->transform(0.1234));
    }

    public function testReverseTransform()
    {
        $transformer = new PercentToLocalizedStringTransformer();

        $this->assertEquals(0.1, $transformer->reverseTransform('10'));
        $this->assertEquals(0.15, $transformer->reverseTransform('15'));
        $this->assertEquals(0.12, $transformer->reverseTransform('12'));
        $this->assertEquals(2, $transformer->reverseTransform('200'));
    }

    public function testReverseTransformEmpty()
    {
        $transformer = new PercentToLocalizedStringTransformer();

        $this->assertNull($transformer->reverseTransform(''));
    }

    public function testReverseTransformWithInteger()
    {
        $transformer = new PercentToLocalizedStringTransformer(null, 'integer');

        $this->assertEquals(10, $transformer->reverseTransform('10'));
        $this->assertEquals(15, $transformer->reverseTransform('15'));
        $this->assertEquals(12, $transformer->reverseTransform('12'));
        $this->assertEquals(200, $transformer->reverseTransform('200'));
    }

    public function testReverseTransformWithPrecision()
    {
        $transformer = new PercentToLocalizedStringTransformer(2);

        $this->assertEquals(0.1234, $transformer->reverseTransform('12,34'));
    }

    public function testTransformExpectsNumeric()
    {
        $transformer = new PercentToLocalizedStringTransformer();

        $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException');

        $transformer->transform('foo');
    }

    public function testReverseTransformExpectsString()
    {
        $transformer = new PercentToLocalizedStringTransformer();

        $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException');

        $transformer->reverseTransform(1);
    }
}
PK��ZWs�**rtest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;

use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToLocalizedStringTransformer;
use Symfony\Component\Intl\Util\IntlTestHelper;

class DateTimeToLocalizedStringTransformerTest extends DateTimeTestCase
{
    protected $dateTime;
    protected $dateTimeWithoutSeconds;

    protected function setUp()
    {
        parent::setUp();

        // Since we test against "de_AT", we need the full implementation
        IntlTestHelper::requireFullIntl($this);

        \Locale::setDefault('de_AT');

        $this->dateTime = new \DateTime('2010-02-03 04:05:06 UTC');
        $this->dateTimeWithoutSeconds = new \DateTime('2010-02-03 04:05:00 UTC');
    }

    protected function tearDown()
    {
        $this->dateTime = null;
        $this->dateTimeWithoutSeconds = null;
    }

    public static function assertEquals($expected, $actual, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false)
    {
        if ($expected instanceof \DateTime && $actual instanceof \DateTime) {
            $expected = $expected->format('c');
            $actual = $actual->format('c');
        }

        parent::assertEquals($expected, $actual, $message, $delta, $maxDepth, $canonicalize, $ignoreCase);
    }

    public function dataProvider()
    {
        return array(
            array(\IntlDateFormatter::SHORT, null, null, '03.02.10 04:05', '2010-02-03 04:05:00 UTC'),
            array(\IntlDateFormatter::MEDIUM, null, null, '03.02.2010 04:05', '2010-02-03 04:05:00 UTC'),
            array(\IntlDateFormatter::LONG, null, null, '03. Februar 2010 04:05', '2010-02-03 04:05:00 UTC'),
            array(\IntlDateFormatter::FULL, null, null, 'Mittwoch, 03. Februar 2010 04:05', '2010-02-03 04:05:00 UTC'),
            array(\IntlDateFormatter::SHORT, \IntlDateFormatter::NONE, null, '03.02.10', '2010-02-03 00:00:00 UTC'),
            array(\IntlDateFormatter::MEDIUM, \IntlDateFormatter::NONE, null, '03.02.2010', '2010-02-03 00:00:00 UTC'),
            array(\IntlDateFormatter::LONG, \IntlDateFormatter::NONE, null, '03. Februar 2010', '2010-02-03 00:00:00 UTC'),
            array(\IntlDateFormatter::FULL, \IntlDateFormatter::NONE, null, 'Mittwoch, 03. Februar 2010', '2010-02-03 00:00:00 UTC'),
            array(null, \IntlDateFormatter::SHORT, null, '03.02.2010 04:05', '2010-02-03 04:05:00 UTC'),
            array(null, \IntlDateFormatter::MEDIUM, null, '03.02.2010 04:05:06', '2010-02-03 04:05:06 UTC'),
            array(null, \IntlDateFormatter::LONG, null, '03.02.2010 04:05:06 GMT', '2010-02-03 04:05:06 UTC'),
            // see below for extra test case for time format FULL
            array(\IntlDateFormatter::NONE, \IntlDateFormatter::SHORT, null, '04:05', '1970-01-01 04:05:00 UTC'),
            array(\IntlDateFormatter::NONE, \IntlDateFormatter::MEDIUM, null, '04:05:06', '1970-01-01 04:05:06 UTC'),
            array(\IntlDateFormatter::NONE, \IntlDateFormatter::LONG, null, '04:05:06 GMT', '1970-01-01 04:05:06 UTC'),
            array(null, null, 'yyyy-MM-dd HH:mm:00', '2010-02-03 04:05:00', '2010-02-03 04:05:00 UTC'),
            array(null, null, 'yyyy-MM-dd HH:mm', '2010-02-03 04:05', '2010-02-03 04:05:00 UTC'),
            array(null, null, 'yyyy-MM-dd HH', '2010-02-03 04', '2010-02-03 04:00:00 UTC'),
            array(null, null, 'yyyy-MM-dd', '2010-02-03', '2010-02-03 00:00:00 UTC'),
            array(null, null, 'yyyy-MM', '2010-02', '2010-02-01 00:00:00 UTC'),
            array(null, null, 'yyyy', '2010', '2010-01-01 00:00:00 UTC'),
            array(null, null, 'dd-MM-yyyy', '03-02-2010', '2010-02-03 00:00:00 UTC'),
            array(null, null, 'HH:mm:ss', '04:05:06', '1970-01-01 04:05:06 UTC'),
            array(null, null, 'HH:mm:00', '04:05:00', '1970-01-01 04:05:00 UTC'),
            array(null, null, 'HH:mm', '04:05', '1970-01-01 04:05:00 UTC'),
            array(null, null, 'HH', '04', '1970-01-01 04:00:00 UTC'),
        );
    }

    /**
     * @dataProvider dataProvider
     */
    public function testTransform($dateFormat, $timeFormat, $pattern, $output, $input)
    {
        $transformer = new DateTimeToLocalizedStringTransformer(
            'UTC',
            'UTC',
            $dateFormat,
            $timeFormat,
            \IntlDateFormatter::GREGORIAN,
            $pattern
        );

        $input = new \DateTime($input);

        $this->assertEquals($output, $transformer->transform($input));
    }

    public function testTransformFullTime()
    {
        $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', null, \IntlDateFormatter::FULL);

        $this->assertEquals('03.02.2010 04:05:06 GMT', $transformer->transform($this->dateTime));
    }

    public function testTransformToDifferentLocale()
    {
        \Locale::setDefault('en_US');

        $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC');

        $this->assertEquals('Feb 3, 2010, 4:05 AM', $transformer->transform($this->dateTime));
    }

    public function testTransformEmpty()
    {
        $transformer = new DateTimeToLocalizedStringTransformer();

        $this->assertSame('', $transformer->transform(null));
    }

    public function testTransformWithDifferentTimezones()
    {
        $transformer = new DateTimeToLocalizedStringTransformer('America/New_York', 'Asia/Hong_Kong');

        $input = new \DateTime('2010-02-03 04:05:06 America/New_York');

        $dateTime = clone $input;
        $dateTime->setTimezone(new \DateTimeZone('Asia/Hong_Kong'));

        $this->assertEquals($dateTime->format('d.m.Y H:i'), $transformer->transform($input));
    }

    public function testTransformWithDifferentPatterns()
    {
        $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', \IntlDateFormatter::FULL, \IntlDateFormatter::FULL, \IntlDateFormatter::GREGORIAN, 'MM*yyyy*dd HH|mm|ss');

        $this->assertEquals('02*2010*03 04|05|06', $transformer->transform($this->dateTime));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testTransformRequiresValidDateTime()
    {
        $transformer = new DateTimeToLocalizedStringTransformer();
        $transformer->transform('2010-01-01');
    }

    public function testTransformWrapsIntlErrors()
    {
        $transformer = new DateTimeToLocalizedStringTransformer();

        // HOW TO REPRODUCE?

        //$this->setExpectedException('Symfony\Component\Form\Extension\Core\DataTransformer\Transdate_formationFailedException');

        //$transformer->transform(1.5);
    }

    /**
     * @dataProvider dataProvider
     */
    public function testReverseTransform($dateFormat, $timeFormat, $pattern, $input, $output)
    {
        $transformer = new DateTimeToLocalizedStringTransformer(
            'UTC',
            'UTC',
            $dateFormat,
            $timeFormat,
            \IntlDateFormatter::GREGORIAN,
            $pattern
        );

        $output = new \DateTime($output);

        $this->assertEquals($output, $transformer->reverseTransform($input));
    }

    public function testReverseTransformFullTime()
    {
        $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', null, \IntlDateFormatter::FULL);

        $this->assertDateTimeEquals($this->dateTime, $transformer->reverseTransform('03.02.2010 04:05:06 GMT+00:00'));
    }

    public function testReverseTransformFromDifferentLocale()
    {
        \Locale::setDefault('en_US');

        $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC');

        $this->assertDateTimeEquals($this->dateTimeWithoutSeconds, $transformer->reverseTransform('Feb 3, 2010, 04:05 AM'));
    }

    public function testReverseTransformWithDifferentTimezones()
    {
        $transformer = new DateTimeToLocalizedStringTransformer('America/New_York', 'Asia/Hong_Kong');

        $dateTime = new \DateTime('2010-02-03 04:05:00 Asia/Hong_Kong');
        $dateTime->setTimezone(new \DateTimeZone('America/New_York'));

        $this->assertDateTimeEquals($dateTime, $transformer->reverseTransform('03.02.2010 04:05'));
    }

    public function testReverseTransformWithDifferentPatterns()
    {
        $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', \IntlDateFormatter::FULL, \IntlDateFormatter::FULL, \IntlDateFormatter::GREGORIAN, 'MM*yyyy*dd HH|mm|ss');

        $this->assertDateTimeEquals($this->dateTime, $transformer->reverseTransform('02*2010*03 04|05|06'));
    }

    public function testReverseTransformEmpty()
    {
        $transformer = new DateTimeToLocalizedStringTransformer();

        $this->assertNull($transformer->reverseTransform(''));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformRequiresString()
    {
        $transformer = new DateTimeToLocalizedStringTransformer();
        $transformer->reverseTransform(12345);
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformWrapsIntlErrors()
    {
        $transformer = new DateTimeToLocalizedStringTransformer();
        $transformer->reverseTransform('12345');
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException
     */
    public function testValidateDateFormatOption()
    {
        new DateTimeToLocalizedStringTransformer(null, null, 'foobar');
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException
     */
    public function testValidateTimeFormatOption()
    {
        new DateTimeToLocalizedStringTransformer(null, null, null, 'foobar');
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformWithNonExistingDate()
    {
        $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', \IntlDateFormatter::SHORT);

        $this->assertDateTimeEquals($this->dateTimeWithoutSeconds, $transformer->reverseTransform('31.04.10 04:05'));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformOutOfTimestampRange()
    {
        $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC');
        $transformer->reverseTransform('1789-07-14');
    }
}
PK��Z�Ub,,Ztest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeTestCase.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;

abstract class DateTimeTestCase extends \PHPUnit_Framework_TestCase
{
    public static function assertDateTimeEquals(\DateTime $expected, \DateTime $actual)
    {
        self::assertEquals($expected->format('c'), $actual->format('c'));
    }
}
PK��Z�}��!
!
ltest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToTimestampTransformerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;

use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer;

class DateTimeToTimestampTransformerTest extends DateTimeTestCase
{
    public function testTransform()
    {
        $transformer = new DateTimeToTimestampTransformer('UTC', 'UTC');

        $input = new \DateTime('2010-02-03 04:05:06 UTC');
        $output = $input->format('U');

        $this->assertEquals($output, $transformer->transform($input));
    }

    public function testTransformEmpty()
    {
        $transformer = new DateTimeToTimestampTransformer();

        $this->assertNull($transformer->transform(null));
    }

    public function testTransformWithDifferentTimezones()
    {
        $transformer = new DateTimeToTimestampTransformer('Asia/Hong_Kong', 'America/New_York');

        $input = new \DateTime('2010-02-03 04:05:06 America/New_York');
        $output = $input->format('U');
        $input->setTimezone(new \DateTimeZone('Asia/Hong_Kong'));

        $this->assertEquals($output, $transformer->transform($input));
    }

    public function testTransformFromDifferentTimezone()
    {
        $transformer = new DateTimeToTimestampTransformer('Asia/Hong_Kong', 'UTC');

        $input = new \DateTime('2010-02-03 04:05:06 Asia/Hong_Kong');

        $dateTime = clone $input;
        $dateTime->setTimezone(new \DateTimeZone('UTC'));
        $output = $dateTime->format('U');

        $this->assertEquals($output, $transformer->transform($input));
    }

    public function testTransformExpectsDateTime()
    {
        $transformer = new DateTimeToTimestampTransformer();

        $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException');

        $transformer->transform('1234');
    }

    public function testReverseTransform()
    {
        $reverseTransformer = new DateTimeToTimestampTransformer('UTC', 'UTC');

        $output = new \DateTime('2010-02-03 04:05:06 UTC');
        $input = $output->format('U');

        $this->assertDateTimeEquals($output, $reverseTransformer->reverseTransform($input));
    }

    public function testReverseTransformEmpty()
    {
        $reverseTransformer = new DateTimeToTimestampTransformer();

        $this->assertNull($reverseTransformer->reverseTransform(null));
    }

    public function testReverseTransformWithDifferentTimezones()
    {
        $reverseTransformer = new DateTimeToTimestampTransformer('Asia/Hong_Kong', 'America/New_York');

        $output = new \DateTime('2010-02-03 04:05:06 America/New_York');
        $input = $output->format('U');
        $output->setTimezone(new \DateTimeZone('Asia/Hong_Kong'));

        $this->assertDateTimeEquals($output, $reverseTransformer->reverseTransform($input));
    }

    public function testReverseTransformExpectsValidTimestamp()
    {
        $reverseTransformer = new DateTimeToTimestampTransformer();

        $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException');

        $reverseTransformer->reverseTransform('2010-2010-2010');
    }
}
PK��Z��=�C?C?htest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToArrayTransformerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;

use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer;

class DateTimeToArrayTransformerTest extends DateTimeTestCase
{
    public function testTransform()
    {
        $transformer = new DateTimeToArrayTransformer('UTC', 'UTC');

        $input = new \DateTime('2010-02-03 04:05:06 UTC');

        $output = array(
            'year' => '2010',
            'month' => '2',
            'day' => '3',
            'hour' => '4',
            'minute' => '5',
            'second' => '6',
        );

        $this->assertSame($output, $transformer->transform($input));
    }

    public function testTransformEmpty()
    {
        $transformer = new DateTimeToArrayTransformer();

        $output = array(
            'year' => '',
            'month' => '',
            'day' => '',
            'hour' => '',
            'minute' => '',
            'second' => '',
        );

        $this->assertSame($output, $transformer->transform(null));
    }

    public function testTransformEmptyWithFields()
    {
        $transformer = new DateTimeToArrayTransformer(null, null, array('year', 'minute', 'second'));

        $output = array(
            'year' => '',
            'minute' => '',
            'second' => '',
        );

        $this->assertSame($output, $transformer->transform(null));
    }

    public function testTransformWithFields()
    {
        $transformer = new DateTimeToArrayTransformer('UTC', 'UTC', array('year', 'month', 'minute', 'second'));

        $input = new \DateTime('2010-02-03 04:05:06 UTC');

        $output = array(
            'year' => '2010',
            'month' => '2',
            'minute' => '5',
            'second' => '6',
        );

        $this->assertSame($output, $transformer->transform($input));
    }

    public function testTransformWithPadding()
    {
        $transformer = new DateTimeToArrayTransformer('UTC', 'UTC', null, true);

        $input = new \DateTime('2010-02-03 04:05:06 UTC');

        $output = array(
            'year' => '2010',
            'month' => '02',
            'day' => '03',
            'hour' => '04',
            'minute' => '05',
            'second' => '06',
        );

        $this->assertSame($output, $transformer->transform($input));
    }

    public function testTransformDifferentTimezones()
    {
        $transformer = new DateTimeToArrayTransformer('America/New_York', 'Asia/Hong_Kong');

        $input = new \DateTime('2010-02-03 04:05:06 America/New_York');

        $dateTime = new \DateTime('2010-02-03 04:05:06 America/New_York');
        $dateTime->setTimezone(new \DateTimeZone('Asia/Hong_Kong'));
        $output = array(
            'year' => (string) (int) $dateTime->format('Y'),
            'month' => (string) (int) $dateTime->format('m'),
            'day' => (string) (int) $dateTime->format('d'),
            'hour' => (string) (int) $dateTime->format('H'),
            'minute' => (string) (int) $dateTime->format('i'),
            'second' => (string) (int) $dateTime->format('s'),
        );

        $this->assertSame($output, $transformer->transform($input));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testTransformRequiresDateTime()
    {
        $transformer = new DateTimeToArrayTransformer();
        $transformer->reverseTransform('12345');
    }

    public function testReverseTransform()
    {
        $transformer = new DateTimeToArrayTransformer('UTC', 'UTC');

        $input = array(
            'year' => '2010',
            'month' => '2',
            'day' => '3',
            'hour' => '4',
            'minute' => '5',
            'second' => '6',
        );

        $output = new \DateTime('2010-02-03 04:05:06 UTC');

        $this->assertDateTimeEquals($output, $transformer->reverseTransform($input));
    }

    public function testReverseTransformWithSomeZero()
    {
        $transformer = new DateTimeToArrayTransformer('UTC', 'UTC');

        $input = array(
            'year' => '2010',
            'month' => '2',
            'day' => '3',
            'hour' => '4',
            'minute' => '0',
            'second' => '0',
        );

        $output = new \DateTime('2010-02-03 04:00:00 UTC');

        $this->assertDateTimeEquals($output, $transformer->reverseTransform($input));
    }

    public function testReverseTransformCompletelyEmpty()
    {
        $transformer = new DateTimeToArrayTransformer();

        $input = array(
            'year' => '',
            'month' => '',
            'day' => '',
            'hour' => '',
            'minute' => '',
            'second' => '',
        );

        $this->assertNull($transformer->reverseTransform($input));
    }

    public function testReverseTransformCompletelyEmptySubsetOfFields()
    {
        $transformer = new DateTimeToArrayTransformer(null, null, array('year', 'month', 'day'));

        $input = array(
            'year' => '',
            'month' => '',
            'day' => '',
        );

        $this->assertNull($transformer->reverseTransform($input));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformPartiallyEmptyYear()
    {
        $transformer = new DateTimeToArrayTransformer();
        $transformer->reverseTransform(array(
            'month' => '2',
            'day' => '3',
            'hour' => '4',
            'minute' => '5',
            'second' => '6',
        ));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformPartiallyEmptyMonth()
    {
        $transformer = new DateTimeToArrayTransformer();
        $transformer->reverseTransform(array(
            'year' => '2010',
            'day' => '3',
            'hour' => '4',
            'minute' => '5',
            'second' => '6',
        ));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformPartiallyEmptyDay()
    {
        $transformer = new DateTimeToArrayTransformer();
        $transformer->reverseTransform(array(
            'year' => '2010',
            'month' => '2',
            'hour' => '4',
            'minute' => '5',
            'second' => '6',
        ));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformPartiallyEmptyHour()
    {
        $transformer = new DateTimeToArrayTransformer();
        $transformer->reverseTransform(array(
            'year' => '2010',
            'month' => '2',
            'day' => '3',
            'minute' => '5',
            'second' => '6',
        ));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformPartiallyEmptyMinute()
    {
        $transformer = new DateTimeToArrayTransformer();
        $transformer->reverseTransform(array(
            'year' => '2010',
            'month' => '2',
            'day' => '3',
            'hour' => '4',
            'second' => '6',
        ));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformPartiallyEmptySecond()
    {
        $transformer = new DateTimeToArrayTransformer();
        $transformer->reverseTransform(array(
            'year' => '2010',
            'month' => '2',
            'day' => '3',
            'hour' => '4',
            'minute' => '5',
        ));
    }

    public function testReverseTransformNull()
    {
        $transformer = new DateTimeToArrayTransformer();

        $this->assertNull($transformer->reverseTransform(null));
    }

    public function testReverseTransformDifferentTimezones()
    {
        $transformer = new DateTimeToArrayTransformer('America/New_York', 'Asia/Hong_Kong');

        $input = array(
            'year' => '2010',
            'month' => '2',
            'day' => '3',
            'hour' => '4',
            'minute' => '5',
            'second' => '6',
        );

        $output = new \DateTime('2010-02-03 04:05:06 Asia/Hong_Kong');
        $output->setTimezone(new \DateTimeZone('America/New_York'));

        $this->assertDateTimeEquals($output, $transformer->reverseTransform($input));
    }

    public function testReverseTransformToDifferentTimezone()
    {
        $transformer = new DateTimeToArrayTransformer('Asia/Hong_Kong', 'UTC');

        $input = array(
            'year' => '2010',
            'month' => '2',
            'day' => '3',
            'hour' => '4',
            'minute' => '5',
            'second' => '6',
        );

        $output = new \DateTime('2010-02-03 04:05:06 UTC');
        $output->setTimezone(new \DateTimeZone('Asia/Hong_Kong'));

        $this->assertDateTimeEquals($output, $transformer->reverseTransform($input));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformRequiresArray()
    {
        $transformer = new DateTimeToArrayTransformer();
        $transformer->reverseTransform('12345');
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformWithNegativeYear()
    {
        $transformer = new DateTimeToArrayTransformer();
        $transformer->reverseTransform(array(
            'year' => '-1',
            'month' => '2',
            'day' => '3',
            'hour' => '4',
            'minute' => '5',
            'second' => '6',
        ));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformWithNegativeMonth()
    {
        $transformer = new DateTimeToArrayTransformer();
        $transformer->reverseTransform(array(
            'year' => '2010',
            'month' => '-1',
            'day' => '3',
            'hour' => '4',
            'minute' => '5',
            'second' => '6',
        ));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformWithNegativeDay()
    {
        $transformer = new DateTimeToArrayTransformer();
        $transformer->reverseTransform(array(
            'year' => '2010',
            'month' => '2',
            'day' => '-1',
            'hour' => '4',
            'minute' => '5',
            'second' => '6',
        ));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformWithNegativeHour()
    {
        $transformer = new DateTimeToArrayTransformer();
        $transformer->reverseTransform(array(
            'year' => '2010',
            'month' => '2',
            'day' => '3',
            'hour' => '-1',
            'minute' => '5',
            'second' => '6',
        ));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformWithNegativeMinute()
    {
        $transformer = new DateTimeToArrayTransformer();
        $transformer->reverseTransform(array(
            'year' => '2010',
            'month' => '2',
            'day' => '3',
            'hour' => '4',
            'minute' => '-1',
            'second' => '6',
        ));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformWithNegativeSecond()
    {
        $transformer = new DateTimeToArrayTransformer();
        $transformer->reverseTransform(array(
            'year' => '2010',
            'month' => '2',
            'day' => '3',
            'hour' => '4',
            'minute' => '5',
            'second' => '-1',
        ));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformWithInvalidMonth()
    {
        $transformer = new DateTimeToArrayTransformer();
        $transformer->reverseTransform(array(
            'year' => '2010',
            'month' => '13',
            'day' => '3',
            'hour' => '4',
            'minute' => '5',
            'second' => '6',
        ));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformWithInvalidDay()
    {
        $transformer = new DateTimeToArrayTransformer();
        $transformer->reverseTransform(array(
            'year' => '2010',
            'month' => '2',
            'day' => '31',
            'hour' => '4',
            'minute' => '5',
            'second' => '6',
        ));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformWithStringDay()
    {
        $transformer = new DateTimeToArrayTransformer();
        $transformer->reverseTransform(array(
            'year' => '2010',
            'month' => '2',
            'day' => 'bazinga',
            'hour' => '4',
            'minute' => '5',
            'second' => '6',
        ));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformWithStringMonth()
    {
        $transformer = new DateTimeToArrayTransformer();
        $transformer->reverseTransform(array(
            'year' => '2010',
            'month' => 'bazinga',
            'day' => '31',
            'hour' => '4',
            'minute' => '5',
            'second' => '6',
        ));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformWithStringYear()
    {
        $transformer = new DateTimeToArrayTransformer();
        $transformer->reverseTransform(array(
            'year' => 'bazinga',
            'month' => '2',
            'day' => '31',
            'hour' => '4',
            'minute' => '5',
            'second' => '6',
        ));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformWithEmptyStringHour()
    {
        $transformer = new DateTimeToArrayTransformer();
        $transformer->reverseTransform(array(
            'year' => '2010',
            'month' => '2',
            'day' => '31',
            'hour' => '',
            'minute' => '5',
            'second' => '6',
        ));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformWithEmptyStringMinute()
    {
        $transformer = new DateTimeToArrayTransformer();
        $transformer->reverseTransform(array(
            'year' => '2010',
            'month' => '2',
            'day' => '31',
            'hour' => '4',
            'minute' => '',
            'second' => '6',
        ));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformWithEmptyStringSecond()
    {
        $transformer = new DateTimeToArrayTransformer();
        $transformer->reverseTransform(array(
            'year' => '2010',
            'month' => '2',
            'day' => '31',
            'hour' => '4',
            'minute' => '5',
            'second' => '',
        ));
    }
}
PK��Z���etest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ArrayToPartsTransformerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;

use Symfony\Component\Form\Extension\Core\DataTransformer\ArrayToPartsTransformer;

class ArrayToPartsTransformerTest extends \PHPUnit_Framework_TestCase
{
    private $transformer;

    protected function setUp()
    {
        $this->transformer = new ArrayToPartsTransformer(array(
            'first' => array('a', 'b', 'c'),
            'second' => array('d', 'e', 'f'),
        ));
    }

    protected function tearDown()
    {
        $this->transformer = null;
    }

    public function testTransform()
    {
        $input = array(
            'a' => '1',
            'b' => '2',
            'c' => '3',
            'd' => '4',
            'e' => '5',
            'f' => '6',
        );

        $output = array(
            'first' => array(
                'a' => '1',
                'b' => '2',
                'c' => '3',
            ),
            'second' => array(
                'd' => '4',
                'e' => '5',
                'f' => '6',
            ),
        );

        $this->assertSame($output, $this->transformer->transform($input));
    }

    public function testTransformEmpty()
    {
        $output = array(
            'first' => null,
            'second' => null,
        );

        $this->assertSame($output, $this->transformer->transform(null));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testTransformRequiresArray()
    {
        $this->transformer->transform('12345');
    }

    public function testReverseTransform()
    {
        $input = array(
            'first' => array(
                'a' => '1',
                'b' => '2',
                'c' => '3',
            ),
            'second' => array(
                'd' => '4',
                'e' => '5',
                'f' => '6',
            ),
        );

        $output = array(
            'a' => '1',
            'b' => '2',
            'c' => '3',
            'd' => '4',
            'e' => '5',
            'f' => '6',
        );

        $this->assertSame($output, $this->transformer->reverseTransform($input));
    }

    public function testReverseTransformCompletelyEmpty()
    {
        $input = array(
            'first' => '',
            'second' => '',
        );

        $this->assertNull($this->transformer->reverseTransform($input));
    }

    public function testReverseTransformCompletelyNull()
    {
        $input = array(
            'first' => null,
            'second' => null,
        );

        $this->assertNull($this->transformer->reverseTransform($input));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformPartiallyNull()
    {
        $input = array(
            'first' => array(
                'a' => '1',
                'b' => '2',
                'c' => '3',
            ),
            'second' => null,
        );

        $this->transformer->reverseTransform($input);
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformRequiresArray()
    {
        $this->transformer->reverseTransform('12345');
    }
}
PK��Z\R��btest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DataTransformerChainTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;

use Symfony\Component\Form\Extension\Core\DataTransformer\DataTransformerChain;

class DataTransformerChainTest extends \PHPUnit_Framework_TestCase
{
    public function testTransform()
    {
        $transformer1 = $this->getMock('Symfony\Component\Form\DataTransformerInterface');
        $transformer1->expects($this->once())
                                 ->method('transform')
                                 ->with($this->identicalTo('foo'))
                                 ->will($this->returnValue('bar'));
        $transformer2 = $this->getMock('Symfony\Component\Form\DataTransformerInterface');
        $transformer2->expects($this->once())
                                 ->method('transform')
                                 ->with($this->identicalTo('bar'))
                                 ->will($this->returnValue('baz'));

        $chain = new DataTransformerChain(array($transformer1, $transformer2));

        $this->assertEquals('baz', $chain->transform('foo'));
    }

    public function testReverseTransform()
    {
        $transformer2 = $this->getMock('Symfony\Component\Form\DataTransformerInterface');
        $transformer2->expects($this->once())
                                 ->method('reverseTransform')
                                 ->with($this->identicalTo('foo'))
                                 ->will($this->returnValue('bar'));
        $transformer1 = $this->getMock('Symfony\Component\Form\DataTransformerInterface');
        $transformer1->expects($this->once())
                                 ->method('reverseTransform')
                                 ->with($this->identicalTo('bar'))
                                 ->will($this->returnValue('baz'));

        $chain = new DataTransformerChain(array($transformer1, $transformer2));

        $this->assertEquals('baz', $chain->reverseTransform('foo'));
    }
}
PK��Z�6���htest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;

use Symfony\Component\Form\Extension\Core\DataTransformer\BooleanToStringTransformer;

class BooleanToStringTransformerTest extends \PHPUnit_Framework_TestCase
{
    const TRUE_VALUE = '1';

    /**
     * @var BooleanToStringTransformer
     */
    protected $transformer;

    protected function setUp()
    {
        $this->transformer = new BooleanToStringTransformer(self::TRUE_VALUE);
    }

    protected function tearDown()
    {
        $this->transformer = null;
    }

    public function testTransform()
    {
        $this->assertEquals(self::TRUE_VALUE, $this->transformer->transform(true));
        $this->assertNull($this->transformer->transform(false));
    }

    // https://github.com/symfony/symfony/issues/8989
    public function testTransformAcceptsNull()
    {
        $this->assertNull($this->transformer->transform(null));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testTransformFailsIfString()
    {
        $this->transformer->transform('1');
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformFailsIfInteger()
    {
        $this->transformer->reverseTransform(1);
    }

    public function testReverseTransform()
    {
        $this->assertTrue($this->transformer->reverseTransform(self::TRUE_VALUE));
        $this->assertTrue($this->transformer->reverseTransform('foobar'));
        $this->assertTrue($this->transformer->reverseTransform(''));
        $this->assertFalse($this->transformer->reverseTransform(null));
    }
}
PK��ZY@zjjotest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;

use Symfony\Component\Form\Extension\Core\DataTransformer\MoneyToLocalizedStringTransformer;
use Symfony\Component\Intl\Util\IntlTestHelper;

class MoneyToLocalizedStringTransformerTest extends \PHPUnit_Framework_TestCase
{
    protected function setUp()
    {
        parent::setUp();

        // Since we test against "de_AT", we need the full implementation
        IntlTestHelper::requireFullIntl($this);

        \Locale::setDefault('de_AT');
    }

    public function testTransform()
    {
        $transformer = new MoneyToLocalizedStringTransformer(null, null, null, 100);

        $this->assertEquals('1,23', $transformer->transform(123));
    }

    public function testTransformExpectsNumeric()
    {
        $transformer = new MoneyToLocalizedStringTransformer(null, null, null, 100);

        $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException');

        $transformer->transform('abcd');
    }

    public function testTransformEmpty()
    {
        $transformer = new MoneyToLocalizedStringTransformer();

        $this->assertSame('', $transformer->transform(null));
    }

    public function testReverseTransform()
    {
        $transformer = new MoneyToLocalizedStringTransformer(null, null, null, 100);

        $this->assertEquals(123, $transformer->reverseTransform('1,23'));
    }

    public function testReverseTransformExpectsString()
    {
        $transformer = new MoneyToLocalizedStringTransformer(null, null, null, 100);

        $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException');

        $transformer->reverseTransform(12345);
    }

    public function testReverseTransformEmpty()
    {
        $transformer = new MoneyToLocalizedStringTransformer();

        $this->assertNull($transformer->reverseTransform(''));
    }
}
PK��Z]e"��jtest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;

use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToRfc3339Transformer;

class DateTimeToRfc3339TransformerTest extends DateTimeTestCase
{
    protected $dateTime;
    protected $dateTimeWithoutSeconds;

    protected function setUp()
    {
        parent::setUp();

        $this->dateTime = new \DateTime('2010-02-03 04:05:06 UTC');
        $this->dateTimeWithoutSeconds = new \DateTime('2010-02-03 04:05:00 UTC');
    }

    protected function tearDown()
    {
        $this->dateTime = null;
        $this->dateTimeWithoutSeconds = null;
    }

    public static function assertEquals($expected, $actual, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = FALSE, $ignoreCase = FALSE)
    {
        if ($expected instanceof \DateTime && $actual instanceof \DateTime) {
            $expected = $expected->format('c');
            $actual = $actual->format('c');
        }

        parent::assertEquals($expected, $actual, $message, $delta, $maxDepth, $canonicalize, $ignoreCase);
    }

    public function allProvider()
    {
        return array(
            array('UTC', 'UTC', '2010-02-03 04:05:06 UTC', '2010-02-03T04:05:06Z'),
            array('UTC', 'UTC', null, ''),
            array('America/New_York', 'Asia/Hong_Kong', '2010-02-03 04:05:06 America/New_York', '2010-02-03T17:05:06+08:00'),
            array('America/New_York', 'Asia/Hong_Kong', null, ''),
            array('UTC', 'Asia/Hong_Kong', '2010-02-03 04:05:06 UTC', '2010-02-03T12:05:06+08:00'),
            array('America/New_York', 'UTC', '2010-02-03 04:05:06 America/New_York', '2010-02-03T09:05:06Z'),
        );
    }

    public function transformProvider()
    {
        return $this->allProvider();
    }

    public function reverseTransformProvider()
    {
        return array_merge($this->allProvider(), array(
            // format without seconds, as appears in some browsers
            array('UTC', 'UTC', '2010-02-03 04:05:00 UTC', '2010-02-03T04:05Z'),
            array('America/New_York', 'Asia/Hong_Kong', '2010-02-03 04:05:00 America/New_York', '2010-02-03T17:05+08:00'),
            array('Europe/Amsterdam', 'Europe/Amsterdam', '2013-08-21 10:30:00 Europe/Amsterdam', '2013-08-21T08:30:00Z')
        ));
    }

    /**
     * @dataProvider transformProvider
     */
    public function testTransform($fromTz, $toTz, $from, $to)
    {
        $transformer = new DateTimeToRfc3339Transformer($fromTz, $toTz);

        $this->assertSame($to, $transformer->transform(null !== $from ? new \DateTime($from) : null));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testTransformRequiresValidDateTime()
    {
        $transformer = new DateTimeToRfc3339Transformer();
        $transformer->transform('2010-01-01');
    }

    /**
     * @dataProvider reverseTransformProvider
     */
    public function testReverseTransform($toTz, $fromTz, $to, $from)
    {
        $transformer = new DateTimeToRfc3339Transformer($toTz, $fromTz);

        if (null !== $to) {
            $this->assertDateTimeEquals(new \DateTime($to), $transformer->reverseTransform($from));
        } else {
            $this->assertSame($to, $transformer->reverseTransform($from));
        }
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformRequiresString()
    {
        $transformer = new DateTimeToRfc3339Transformer();
        $transformer->reverseTransform(12345);
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformWithNonExistingDate()
    {
        $transformer = new DateTimeToRfc3339Transformer('UTC', 'UTC');

        $transformer->reverseTransform('2010-04-31T04:05Z');
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformExpectsValidDateString()
    {
        $transformer = new DateTimeToRfc3339Transformer('UTC', 'UTC');

        $transformer->reverseTransform('2010-2010-2010');
    }
}
PK��ZN�z.z.qtest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;

use Symfony\Component\Form\Extension\Core\DataTransformer\IntegerToLocalizedStringTransformer;
use Symfony\Component\Intl\Util\IntlTestHelper;

class IntegerToLocalizedStringTransformerTest extends \PHPUnit_Framework_TestCase
{
    protected function setUp()
    {
        parent::setUp();

        // Since we test against "de_AT", we need the full implementation
        IntlTestHelper::requireFullIntl($this);

        \Locale::setDefault('de_AT');
    }

    public function transformWithRoundingProvider()
    {
        return array(
            // towards positive infinity (1.6 -> 2, -1.6 -> -1)
            array(1234.5, '1235', IntegerToLocalizedStringTransformer::ROUND_CEILING),
            array(1234.4, '1235', IntegerToLocalizedStringTransformer::ROUND_CEILING),
            array(-1234.5, '-1234', IntegerToLocalizedStringTransformer::ROUND_CEILING),
            array(-1234.4, '-1234', IntegerToLocalizedStringTransformer::ROUND_CEILING),
            // towards negative infinity (1.6 -> 1, -1.6 -> -2)
            array(1234.5, '1234', IntegerToLocalizedStringTransformer::ROUND_FLOOR),
            array(1234.4, '1234', IntegerToLocalizedStringTransformer::ROUND_FLOOR),
            array(-1234.5, '-1235', IntegerToLocalizedStringTransformer::ROUND_FLOOR),
            array(-1234.4, '-1235', IntegerToLocalizedStringTransformer::ROUND_FLOOR),
            // away from zero (1.6 -> 2, -1.6 -> 2)
            array(1234.5, '1235', IntegerToLocalizedStringTransformer::ROUND_UP),
            array(1234.4, '1235', IntegerToLocalizedStringTransformer::ROUND_UP),
            array(-1234.5, '-1235', IntegerToLocalizedStringTransformer::ROUND_UP),
            array(-1234.4, '-1235', IntegerToLocalizedStringTransformer::ROUND_UP),
            // towards zero (1.6 -> 1, -1.6 -> -1)
            array(1234.5, '1234', IntegerToLocalizedStringTransformer::ROUND_DOWN),
            array(1234.4, '1234', IntegerToLocalizedStringTransformer::ROUND_DOWN),
            array(-1234.5, '-1234', IntegerToLocalizedStringTransformer::ROUND_DOWN),
            array(-1234.4, '-1234', IntegerToLocalizedStringTransformer::ROUND_DOWN),
            // round halves (.5) to the next even number
            array(1234.6, '1235', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(1234.5, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(1234.4, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(1233.5, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(1232.5, '1232', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(-1234.6, '-1235', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(-1234.5, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(-1234.4, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(-1233.5, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(-1232.5, '-1232', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
            // round halves (.5) away from zero
            array(1234.6, '1235', IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
            array(1234.5, '1235', IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
            array(1234.4, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
            array(-1234.6, '-1235', IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
            array(-1234.5, '-1235', IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
            array(-1234.4, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
            // round halves (.5) towards zero
            array(1234.6, '1235', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array(1234.5, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array(1234.4, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array(-1234.6, '-1235', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array(-1234.5, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array(-1234.4, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
        );
    }

    /**
     * @dataProvider transformWithRoundingProvider
     */
    public function testTransformWithRounding($input, $output, $roundingMode)
    {
        $transformer = new IntegerToLocalizedStringTransformer(null, null, $roundingMode);

        $this->assertEquals($output, $transformer->transform($input));
    }

    public function testReverseTransform()
    {
        $transformer = new IntegerToLocalizedStringTransformer();

        $this->assertEquals(1, $transformer->reverseTransform('1'));
        $this->assertEquals(1, $transformer->reverseTransform('1,5'));
        $this->assertEquals(1234, $transformer->reverseTransform('1234,5'));
        $this->assertEquals(12345, $transformer->reverseTransform('12345,912'));
    }

    public function testReverseTransformEmpty()
    {
        $transformer = new IntegerToLocalizedStringTransformer();

        $this->assertNull($transformer->reverseTransform(''));
    }

    public function testReverseTransformWithGrouping()
    {
        $transformer = new IntegerToLocalizedStringTransformer(null, true);

        $this->assertEquals(1234, $transformer->reverseTransform('1.234,5'));
        $this->assertEquals(12345, $transformer->reverseTransform('12.345,912'));
        $this->assertEquals(1234, $transformer->reverseTransform('1234,5'));
        $this->assertEquals(12345, $transformer->reverseTransform('12345,912'));
    }

    public function reverseTransformWithRoundingProvider()
    {
        return array(
            // towards positive infinity (1.6 -> 2, -1.6 -> -1)
            array('1234,5', 1235, IntegerToLocalizedStringTransformer::ROUND_CEILING),
            array('1234,4', 1235, IntegerToLocalizedStringTransformer::ROUND_CEILING),
            array('-1234,5', -1234, IntegerToLocalizedStringTransformer::ROUND_CEILING),
            array('-1234,4', -1234, IntegerToLocalizedStringTransformer::ROUND_CEILING),
            // towards negative infinity (1.6 -> 1, -1.6 -> -2)
            array('1234,5', 1234, IntegerToLocalizedStringTransformer::ROUND_FLOOR),
            array('1234,4', 1234, IntegerToLocalizedStringTransformer::ROUND_FLOOR),
            array('-1234,5', -1235, IntegerToLocalizedStringTransformer::ROUND_FLOOR),
            array('-1234,4', -1235, IntegerToLocalizedStringTransformer::ROUND_FLOOR),
            // away from zero (1.6 -> 2, -1.6 -> 2)
            array('1234,5', 1235, IntegerToLocalizedStringTransformer::ROUND_UP),
            array('1234,4', 1235, IntegerToLocalizedStringTransformer::ROUND_UP),
            array('-1234,5', -1235, IntegerToLocalizedStringTransformer::ROUND_UP),
            array('-1234,4', -1235, IntegerToLocalizedStringTransformer::ROUND_UP),
            // towards zero (1.6 -> 1, -1.6 -> -1)
            array('1234,5', 1234, IntegerToLocalizedStringTransformer::ROUND_DOWN),
            array('1234,4', 1234, IntegerToLocalizedStringTransformer::ROUND_DOWN),
            array('-1234,5', -1234, IntegerToLocalizedStringTransformer::ROUND_DOWN),
            array('-1234,4', -1234, IntegerToLocalizedStringTransformer::ROUND_DOWN),
            // round halves (.5) to the next even number
            array('1234,6', 1235, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array('1234,5', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array('1234,4', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array('1233,5', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array('1232,5', 1232, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array('-1234,6', -1235, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array('-1234,5', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array('-1234,4', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array('-1233,5', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array('-1232,5', -1232, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
            // round halves (.5) away from zero
            array('1234,6', 1235, IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
            array('1234,5', 1235, IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
            array('1234,4', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
            array('-1234,6', -1235, IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
            array('-1234,5', -1235, IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
            array('-1234,4', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
            // round halves (.5) towards zero
            array('1234,6', 1235, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array('1234,5', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array('1234,4', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array('-1234,6', -1235, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array('-1234,5', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array('-1234,4', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
        );
    }

    /**
     * @dataProvider reverseTransformWithRoundingProvider
     */
    public function testReverseTransformWithRounding($input, $output, $roundingMode)
    {
        $transformer = new IntegerToLocalizedStringTransformer(null, null, $roundingMode);

        $this->assertEquals($output, $transformer->reverseTransform($input));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformExpectsString()
    {
        $transformer = new IntegerToLocalizedStringTransformer();

        $transformer->reverseTransform(1);
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformExpectsValidNumber()
    {
        $transformer = new IntegerToLocalizedStringTransformer();

        $transformer->reverseTransform('foo');
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformDisallowsNaN()
    {
        $transformer = new IntegerToLocalizedStringTransformer();

        $transformer->reverseTransform('NaN');
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformDisallowsNaN2()
    {
        $transformer = new IntegerToLocalizedStringTransformer();

        $transformer->reverseTransform('nan');
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformDisallowsInfinity()
    {
        $transformer = new IntegerToLocalizedStringTransformer();

        $transformer->reverseTransform('∞');
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformDisallowsNegativeInfinity()
    {
        $transformer = new IntegerToLocalizedStringTransformer();

        $transformer->reverseTransform('-∞');
    }
}
PK��Z��`nonoptest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;

use Symfony\Component\Form\Extension\Core\DataTransformer\NumberToLocalizedStringTransformer;
use Symfony\Component\Intl\Util\IntlTestHelper;

class NumberToLocalizedStringTransformerTest extends \PHPUnit_Framework_TestCase
{
    protected function setUp()
    {
        parent::setUp();

        // Since we test against "de_AT", we need the full implementation
        IntlTestHelper::requireFullIntl($this);

        \Locale::setDefault('de_AT');
    }

    public function provideTransformations()
    {
        return array(
            array(null, '', 'de_AT'),
            array(1, '1', 'de_AT'),
            array(1.5, '1,5', 'de_AT'),
            array(1234.5, '1234,5', 'de_AT'),
            array(12345.912, '12345,912', 'de_AT'),
            array(1234.5, '1234,5', 'ru'),
            array(1234.5, '1234,5', 'fi'),
        );
    }

    /**
     * @dataProvider provideTransformations
     */
    public function testTransform($from, $to, $locale)
    {
        \Locale::setDefault($locale);

        $transformer = new NumberToLocalizedStringTransformer();

        $this->assertSame($to, $transformer->transform($from));
    }

    public function provideTransformationsWithGrouping()
    {
        return array(
            array(1234.5, '1.234,5', 'de_AT'),
            array(12345.912, '12.345,912', 'de_AT'),
            array(1234.5, '1 234,5', 'fr'),
            array(1234.5, '1 234,5', 'ru'),
            array(1234.5, '1 234,5', 'fi'),
        );
    }

    /**
     * @dataProvider provideTransformationsWithGrouping
     */
    public function testTransformWithGrouping($from, $to, $locale)
    {
        \Locale::setDefault($locale);

        $transformer = new NumberToLocalizedStringTransformer(null, true);

        $this->assertSame($to, $transformer->transform($from));
    }

    public function testTransformWithPrecision()
    {
        $transformer = new NumberToLocalizedStringTransformer(2);

        $this->assertEquals('1234,50', $transformer->transform(1234.5));
        $this->assertEquals('678,92', $transformer->transform(678.916));
    }

    public function transformWithRoundingProvider()
    {
        return array(
            // towards positive infinity (1.6 -> 2, -1.6 -> -1)
            array(0, 1234.5, '1235', NumberToLocalizedStringTransformer::ROUND_CEILING),
            array(0, 1234.4, '1235', NumberToLocalizedStringTransformer::ROUND_CEILING),
            array(0, -1234.5, '-1234', NumberToLocalizedStringTransformer::ROUND_CEILING),
            array(0, -1234.4, '-1234', NumberToLocalizedStringTransformer::ROUND_CEILING),
            array(1, 123.45, '123,5', NumberToLocalizedStringTransformer::ROUND_CEILING),
            array(1, 123.44, '123,5', NumberToLocalizedStringTransformer::ROUND_CEILING),
            array(1, -123.45, '-123,4', NumberToLocalizedStringTransformer::ROUND_CEILING),
            array(1, -123.44, '-123,4', NumberToLocalizedStringTransformer::ROUND_CEILING),
            // towards negative infinity (1.6 -> 1, -1.6 -> -2)
            array(0, 1234.5, '1234', NumberToLocalizedStringTransformer::ROUND_FLOOR),
            array(0, 1234.4, '1234', NumberToLocalizedStringTransformer::ROUND_FLOOR),
            array(0, -1234.5, '-1235', NumberToLocalizedStringTransformer::ROUND_FLOOR),
            array(0, -1234.4, '-1235', NumberToLocalizedStringTransformer::ROUND_FLOOR),
            array(1, 123.45, '123,4', NumberToLocalizedStringTransformer::ROUND_FLOOR),
            array(1, 123.44, '123,4', NumberToLocalizedStringTransformer::ROUND_FLOOR),
            array(1, -123.45, '-123,5', NumberToLocalizedStringTransformer::ROUND_FLOOR),
            array(1, -123.44, '-123,5', NumberToLocalizedStringTransformer::ROUND_FLOOR),
            // away from zero (1.6 -> 2, -1.6 -> 2)
            array(0, 1234.5, '1235', NumberToLocalizedStringTransformer::ROUND_UP),
            array(0, 1234.4, '1235', NumberToLocalizedStringTransformer::ROUND_UP),
            array(0, -1234.5, '-1235', NumberToLocalizedStringTransformer::ROUND_UP),
            array(0, -1234.4, '-1235', NumberToLocalizedStringTransformer::ROUND_UP),
            array(1, 123.45, '123,5', NumberToLocalizedStringTransformer::ROUND_UP),
            array(1, 123.44, '123,5', NumberToLocalizedStringTransformer::ROUND_UP),
            array(1, -123.45, '-123,5', NumberToLocalizedStringTransformer::ROUND_UP),
            array(1, -123.44, '-123,5', NumberToLocalizedStringTransformer::ROUND_UP),
            // towards zero (1.6 -> 1, -1.6 -> -1)
            array(0, 1234.5, '1234', NumberToLocalizedStringTransformer::ROUND_DOWN),
            array(0, 1234.4, '1234', NumberToLocalizedStringTransformer::ROUND_DOWN),
            array(0, -1234.5, '-1234', NumberToLocalizedStringTransformer::ROUND_DOWN),
            array(0, -1234.4, '-1234', NumberToLocalizedStringTransformer::ROUND_DOWN),
            array(1, 123.45, '123,4', NumberToLocalizedStringTransformer::ROUND_DOWN),
            array(1, 123.44, '123,4', NumberToLocalizedStringTransformer::ROUND_DOWN),
            array(1, -123.45, '-123,4', NumberToLocalizedStringTransformer::ROUND_DOWN),
            array(1, -123.44, '-123,4', NumberToLocalizedStringTransformer::ROUND_DOWN),
            // round halves (.5) to the next even number
            array(0, 1234.6, '1235', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(0, 1234.5, '1234', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(0, 1234.4, '1234', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(0, 1233.5, '1234', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(0, 1232.5, '1232', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(0, -1234.6, '-1235', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(0, -1234.5, '-1234', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(0, -1234.4, '-1234', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(0, -1233.5, '-1234', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(0, -1232.5, '-1232', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(1, 123.46, '123,5', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(1, 123.45, '123,4', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(1, 123.44, '123,4', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(1, 123.35, '123,4', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(1, 123.25, '123,2', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(1, -123.46, '-123,5', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(1, -123.45, '-123,4', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(1, -123.44, '-123,4', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(1, -123.35, '-123,4', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(1, -123.25, '-123,2', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            // round halves (.5) away from zero
            array(0, 1234.6, '1235', NumberToLocalizedStringTransformer::ROUND_HALF_UP),
            array(0, 1234.5, '1235', NumberToLocalizedStringTransformer::ROUND_HALF_UP),
            array(0, 1234.4, '1234', NumberToLocalizedStringTransformer::ROUND_HALF_UP),
            array(0, -1234.6, '-1235', NumberToLocalizedStringTransformer::ROUND_HALF_UP),
            array(0, -1234.5, '-1235', NumberToLocalizedStringTransformer::ROUND_HALF_UP),
            array(0, -1234.4, '-1234', NumberToLocalizedStringTransformer::ROUND_HALF_UP),
            array(1, 123.46, '123,5', NumberToLocalizedStringTransformer::ROUND_HALF_UP),
            array(1, 123.45, '123,5', NumberToLocalizedStringTransformer::ROUND_HALF_UP),
            array(1, 123.44, '123,4', NumberToLocalizedStringTransformer::ROUND_HALF_UP),
            array(1, -123.46, '-123,5', NumberToLocalizedStringTransformer::ROUND_HALF_UP),
            array(1, -123.45, '-123,5', NumberToLocalizedStringTransformer::ROUND_HALF_UP),
            array(1, -123.44, '-123,4', NumberToLocalizedStringTransformer::ROUND_HALF_UP),
            // round halves (.5) towards zero
            array(0, 1234.6, '1235', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array(0, 1234.5, '1234', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array(0, 1234.4, '1234', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array(0, -1234.6, '-1235', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array(0, -1234.5, '-1234', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array(0, -1234.4, '-1234', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array(1, 123.46, '123,5', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array(1, 123.45, '123,4', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array(1, 123.44, '123,4', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array(1, -123.46, '-123,5', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array(1, -123.45, '-123,4', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array(1, -123.44, '-123,4', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
        );
    }

    /**
     * @dataProvider transformWithRoundingProvider
     */
    public function testTransformWithRounding($precision, $input, $output, $roundingMode)
    {
        $transformer = new NumberToLocalizedStringTransformer($precision, null, $roundingMode);

        $this->assertEquals($output, $transformer->transform($input));
    }

    public function testTransformDoesNotRoundIfNoPrecision()
    {
        $transformer = new NumberToLocalizedStringTransformer(null, null, NumberToLocalizedStringTransformer::ROUND_DOWN);

        $this->assertEquals('1234,547', $transformer->transform(1234.547));
    }

    /**
     * @dataProvider provideTransformations
     */
    public function testReverseTransform($to, $from, $locale)
    {
        \Locale::setDefault($locale);

        $transformer = new NumberToLocalizedStringTransformer();

        $this->assertEquals($to, $transformer->reverseTransform($from));
    }

    /**
     * @dataProvider provideTransformationsWithGrouping
     */
    public function testReverseTransformWithGrouping($to, $from, $locale)
    {
        \Locale::setDefault($locale);

        $transformer = new NumberToLocalizedStringTransformer(null, true);

        $this->assertEquals($to, $transformer->reverseTransform($from));
    }

    // https://github.com/symfony/symfony/issues/7609
    public function testReverseTransformWithGroupingAndFixedSpaces()
    {
        if (!extension_loaded('mbstring')) {
            $this->markTestSkipped('The "mbstring" extension is required for this test.');
        }

        \Locale::setDefault('ru');

        $transformer = new NumberToLocalizedStringTransformer(null, true);

        $this->assertEquals(1234.5, $transformer->reverseTransform("1\xc2\xa0234,5"));
    }

    public function testReverseTransformWithGroupingButWithoutGroupSeparator()
    {
        $transformer = new NumberToLocalizedStringTransformer(null, true);

        // omit group separator
        $this->assertEquals(1234.5, $transformer->reverseTransform('1234,5'));
        $this->assertEquals(12345.912, $transformer->reverseTransform('12345,912'));
    }

    public function reverseTransformWithRoundingProvider()
    {
        return array(
            // towards positive infinity (1.6 -> 2, -1.6 -> -1)
            array(0, '1234,5', 1235, NumberToLocalizedStringTransformer::ROUND_CEILING),
            array(0, '1234,4', 1235, NumberToLocalizedStringTransformer::ROUND_CEILING),
            array(0, '-1234,5', -1234, NumberToLocalizedStringTransformer::ROUND_CEILING),
            array(0, '-1234,4', -1234, NumberToLocalizedStringTransformer::ROUND_CEILING),
            array(1, '123,45', 123.5, NumberToLocalizedStringTransformer::ROUND_CEILING),
            array(1, '123,44', 123.5, NumberToLocalizedStringTransformer::ROUND_CEILING),
            array(1, '-123,45', -123.4, NumberToLocalizedStringTransformer::ROUND_CEILING),
            array(1, '-123,44', -123.4, NumberToLocalizedStringTransformer::ROUND_CEILING),
            // towards negative infinity (1.6 -> 1, -1.6 -> -2)
            array(0, '1234,5', 1234, NumberToLocalizedStringTransformer::ROUND_FLOOR),
            array(0, '1234,4', 1234, NumberToLocalizedStringTransformer::ROUND_FLOOR),
            array(0, '-1234,5', -1235, NumberToLocalizedStringTransformer::ROUND_FLOOR),
            array(0, '-1234,4', -1235, NumberToLocalizedStringTransformer::ROUND_FLOOR),
            array(1, '123,45', 123.4, NumberToLocalizedStringTransformer::ROUND_FLOOR),
            array(1, '123,44', 123.4, NumberToLocalizedStringTransformer::ROUND_FLOOR),
            array(1, '-123,45', -123.5, NumberToLocalizedStringTransformer::ROUND_FLOOR),
            array(1, '-123,44', -123.5, NumberToLocalizedStringTransformer::ROUND_FLOOR),
            // away from zero (1.6 -> 2, -1.6 -> 2)
            array(0, '1234,5', 1235, NumberToLocalizedStringTransformer::ROUND_UP),
            array(0, '1234,4', 1235, NumberToLocalizedStringTransformer::ROUND_UP),
            array(0, '-1234,5', -1235, NumberToLocalizedStringTransformer::ROUND_UP),
            array(0, '-1234,4', -1235, NumberToLocalizedStringTransformer::ROUND_UP),
            array(1, '123,45', 123.5, NumberToLocalizedStringTransformer::ROUND_UP),
            array(1, '123,44', 123.5, NumberToLocalizedStringTransformer::ROUND_UP),
            array(1, '-123,45', -123.5, NumberToLocalizedStringTransformer::ROUND_UP),
            array(1, '-123,44', -123.5, NumberToLocalizedStringTransformer::ROUND_UP),
            // towards zero (1.6 -> 1, -1.6 -> -1)
            array(0, '1234,5', 1234, NumberToLocalizedStringTransformer::ROUND_DOWN),
            array(0, '1234,4', 1234, NumberToLocalizedStringTransformer::ROUND_DOWN),
            array(0, '-1234,5', -1234, NumberToLocalizedStringTransformer::ROUND_DOWN),
            array(0, '-1234,4', -1234, NumberToLocalizedStringTransformer::ROUND_DOWN),
            array(1, '123,45', 123.4, NumberToLocalizedStringTransformer::ROUND_DOWN),
            array(1, '123,44', 123.4, NumberToLocalizedStringTransformer::ROUND_DOWN),
            array(1, '-123,45', -123.4, NumberToLocalizedStringTransformer::ROUND_DOWN),
            array(1, '-123,44', -123.4, NumberToLocalizedStringTransformer::ROUND_DOWN),
            // round halves (.5) to the next even number
            array(0, '1234,6', 1235, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(0, '1234,5', 1234, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(0, '1234,4', 1234, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(0, '1233,5', 1234, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(0, '1232,5', 1232, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(0, '-1234,6', -1235, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(0, '-1234,5', -1234, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(0, '-1234,4', -1234, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(0, '-1233,5', -1234, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(0, '-1232,5', -1232, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(1, '123,46', 123.5, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(1, '123,45', 123.4, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(1, '123,44', 123.4, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(1, '123,35', 123.4, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(1, '123,25', 123.2, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(1, '-123,46', -123.5, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(1, '-123,45', -123.4, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(1, '-123,44', -123.4, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(1, '-123,35', -123.4, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            array(1, '-123,25', -123.2, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
            // round halves (.5) away from zero
            array(0, '1234,6', 1235, NumberToLocalizedStringTransformer::ROUND_HALF_UP),
            array(0, '1234,5', 1235, NumberToLocalizedStringTransformer::ROUND_HALF_UP),
            array(0, '1234,4', 1234, NumberToLocalizedStringTransformer::ROUND_HALF_UP),
            array(0, '-1234,6', -1235, NumberToLocalizedStringTransformer::ROUND_HALF_UP),
            array(0, '-1234,5', -1235, NumberToLocalizedStringTransformer::ROUND_HALF_UP),
            array(0, '-1234,4', -1234, NumberToLocalizedStringTransformer::ROUND_HALF_UP),
            array(1, '123,46', 123.5, NumberToLocalizedStringTransformer::ROUND_HALF_UP),
            array(1, '123,45', 123.5, NumberToLocalizedStringTransformer::ROUND_HALF_UP),
            array(1, '123,44', 123.4, NumberToLocalizedStringTransformer::ROUND_HALF_UP),
            array(1, '-123,46', -123.5, NumberToLocalizedStringTransformer::ROUND_HALF_UP),
            array(1, '-123,45', -123.5, NumberToLocalizedStringTransformer::ROUND_HALF_UP),
            array(1, '-123,44', -123.4, NumberToLocalizedStringTransformer::ROUND_HALF_UP),
            // round halves (.5) towards zero
            array(0, '1234,6', 1235, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array(0, '1234,5', 1234, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array(0, '1234,4', 1234, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array(0, '-1234,6', -1235, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array(0, '-1234,5', -1234, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array(0, '-1234,4', -1234, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array(1, '123,46', 123.5, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array(1, '123,45', 123.4, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array(1, '123,44', 123.4, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array(1, '-123,46', -123.5, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array(1, '-123,45', -123.4, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
            array(1, '-123,44', -123.4, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
        );
    }

    /**
     * @dataProvider reverseTransformWithRoundingProvider
     */
    public function testReverseTransformWithRounding($precision, $input, $output, $roundingMode)
    {
        $transformer = new NumberToLocalizedStringTransformer($precision, null, $roundingMode);

        $this->assertEquals($output, $transformer->reverseTransform($input));
    }

    public function testReverseTransformDoesNotRoundIfNoPrecision()
    {
        $transformer = new NumberToLocalizedStringTransformer(null, null, NumberToLocalizedStringTransformer::ROUND_DOWN);

        $this->assertEquals(1234.547, $transformer->reverseTransform('1234,547'));
    }

    public function testDecimalSeparatorMayBeDotIfGroupingSeparatorIsNotDot()
    {
        \Locale::setDefault('fr');
        $transformer = new NumberToLocalizedStringTransformer(null, true);

        // completely valid format
        $this->assertEquals(1234.5, $transformer->reverseTransform('1 234,5'));
        // accept dots
        $this->assertEquals(1234.5, $transformer->reverseTransform('1 234.5'));
        // omit group separator
        $this->assertEquals(1234.5, $transformer->reverseTransform('1234,5'));
        $this->assertEquals(1234.5, $transformer->reverseTransform('1234.5'));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testDecimalSeparatorMayNotBeDotIfGroupingSeparatorIsDot()
    {
        $transformer = new NumberToLocalizedStringTransformer(null, true);

        $transformer->reverseTransform('1.234.5');
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testDecimalSeparatorMayNotBeDotIfGroupingSeparatorIsDotWithNoGroupSep()
    {
        $transformer = new NumberToLocalizedStringTransformer(null, true);

        $transformer->reverseTransform('1234.5');
    }

    public function testDecimalSeparatorMayBeDotIfGroupingSeparatorIsDotButNoGroupingUsed()
    {
        \Locale::setDefault('fr');
        $transformer = new NumberToLocalizedStringTransformer();

        $this->assertEquals(1234.5, $transformer->reverseTransform('1234,5'));
        $this->assertEquals(1234.5, $transformer->reverseTransform('1234.5'));
    }

    public function testDecimalSeparatorMayBeCommaIfGroupingSeparatorIsNotComma()
    {
        \Locale::setDefault('bg');
        $transformer = new NumberToLocalizedStringTransformer(null, true);

        // completely valid format
        $this->assertEquals(1234.5, $transformer->reverseTransform('1 234.5'));
        // accept commas
        $this->assertEquals(1234.5, $transformer->reverseTransform('1 234,5'));
        // omit group separator
        $this->assertEquals(1234.5, $transformer->reverseTransform('1234.5'));
        $this->assertEquals(1234.5, $transformer->reverseTransform('1234,5'));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testDecimalSeparatorMayNotBeCommaIfGroupingSeparatorIsComma()
    {
        \Locale::setDefault('en');
        $transformer = new NumberToLocalizedStringTransformer(null, true);

        $transformer->reverseTransform('1,234,5');
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testDecimalSeparatorMayNotBeCommaIfGroupingSeparatorIsCommaWithNoGroupSep()
    {
        \Locale::setDefault('en');
        $transformer = new NumberToLocalizedStringTransformer(null, true);

        $transformer->reverseTransform('1234,5');
    }

    public function testDecimalSeparatorMayBeCommaIfGroupingSeparatorIsCommaButNoGroupingUsed()
    {
        \Locale::setDefault('en');
        $transformer = new NumberToLocalizedStringTransformer();

        $this->assertEquals(1234.5, $transformer->reverseTransform('1234,5'));
        $this->assertEquals(1234.5, $transformer->reverseTransform('1234.5'));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testTransformExpectsNumeric()
    {
        $transformer = new NumberToLocalizedStringTransformer();

        $transformer->transform('foo');
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformExpectsString()
    {
        $transformer = new NumberToLocalizedStringTransformer();

        $transformer->reverseTransform(1);
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformExpectsValidNumber()
    {
        $transformer = new NumberToLocalizedStringTransformer();

        $transformer->reverseTransform('foo');
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     * @link https://github.com/symfony/symfony/issues/3161
     */
    public function testReverseTransformDisallowsNaN()
    {
        $transformer = new NumberToLocalizedStringTransformer();

        $transformer->reverseTransform('NaN');
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformDisallowsNaN2()
    {
        $transformer = new NumberToLocalizedStringTransformer();

        $transformer->reverseTransform('nan');
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformDisallowsInfinity()
    {
        $transformer = new NumberToLocalizedStringTransformer();

        $transformer->reverseTransform('∞');
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformDisallowsInfinity2()
    {
        $transformer = new NumberToLocalizedStringTransformer();

        $transformer->reverseTransform('∞,123');
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformDisallowsNegativeInfinity()
    {
        $transformer = new NumberToLocalizedStringTransformer();

        $transformer->reverseTransform('-∞');
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformDisallowsLeadingExtraCharacters()
    {
        $transformer = new NumberToLocalizedStringTransformer();

        $transformer->reverseTransform('foo123');
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     * @expectedExceptionMessage The number contains unrecognized characters: "foo3"
     */
    public function testReverseTransformDisallowsCenteredExtraCharacters()
    {
        $transformer = new NumberToLocalizedStringTransformer();

        $transformer->reverseTransform('12foo3');
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     * @expectedExceptionMessage The number contains unrecognized characters: "foo8"
     */
    public function testReverseTransformDisallowsCenteredExtraCharactersMultibyte()
    {
        if (!extension_loaded('mbstring')) {
            $this->markTestSkipped('The "mbstring" extension is required for this test.');
        }

        \Locale::setDefault('ru');

        $transformer = new NumberToLocalizedStringTransformer(null, true);

        $transformer->reverseTransform("12\xc2\xa0345,67foo8");
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     * @expectedExceptionMessage The number contains unrecognized characters: "foo8"
     */
    public function testReverseTransformIgnoresTrailingSpacesInExceptionMessage()
    {
        if (!extension_loaded('mbstring')) {
            $this->markTestSkipped('The "mbstring" extension is required for this test.');
        }

        \Locale::setDefault('ru');

        $transformer = new NumberToLocalizedStringTransformer(null, true);

        $transformer->reverseTransform("12\xc2\xa0345,67foo8  \xc2\xa0\t");
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     * @expectedExceptionMessage The number contains unrecognized characters: "foo"
     */
    public function testReverseTransformDisallowsTrailingExtraCharacters()
    {
        $transformer = new NumberToLocalizedStringTransformer();

        $transformer->reverseTransform('123foo');
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     * @expectedExceptionMessage The number contains unrecognized characters: "foo"
     */
    public function testReverseTransformDisallowsTrailingExtraCharactersMultibyte()
    {
        if (!extension_loaded('mbstring')) {
            $this->markTestSkipped('The "mbstring" extension is required for this test.');
        }

        \Locale::setDefault('ru');

        $transformer = new NumberToLocalizedStringTransformer(null, true);

        $transformer->reverseTransform("12\xc2\xa0345,678foo");
    }
}
PK��Z�?+�<<jtest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ValueToDuplicatesTransformerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;

use Symfony\Component\Form\Extension\Core\DataTransformer\ValueToDuplicatesTransformer;

class ValueToDuplicatesTransformerTest extends \PHPUnit_Framework_TestCase
{
    private $transformer;

    protected function setUp()
    {
        $this->transformer = new ValueToDuplicatesTransformer(array('a', 'b', 'c'));
    }

    protected function tearDown()
    {
        $this->transformer = null;
    }

    public function testTransform()
    {
        $output = array(
            'a' => 'Foo',
            'b' => 'Foo',
            'c' => 'Foo',
        );

        $this->assertSame($output, $this->transformer->transform('Foo'));
    }

    public function testTransformEmpty()
    {
        $output = array(
            'a' => null,
            'b' => null,
            'c' => null,
        );

        $this->assertSame($output, $this->transformer->transform(null));
    }

    public function testReverseTransform()
    {
        $input = array(
            'a' => 'Foo',
            'b' => 'Foo',
            'c' => 'Foo',
        );

        $this->assertSame('Foo', $this->transformer->reverseTransform($input));
    }

    public function testReverseTransformCompletelyEmpty()
    {
        $input = array(
            'a' => '',
            'b' => '',
            'c' => '',
        );

        $this->assertNull($this->transformer->reverseTransform($input));
    }

    public function testReverseTransformCompletelyNull()
    {
        $input = array(
            'a' => null,
            'b' => null,
            'c' => null,
        );

        $this->assertNull($this->transformer->reverseTransform($input));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformPartiallyNull()
    {
        $input = array(
            'a' => 'Foo',
            'b' => 'Foo',
            'c' => null,
        );

        $this->transformer->reverseTransform($input);
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformDifferences()
    {
        $input = array(
            'a' => 'Foo',
            'b' => 'Bar',
            'c' => 'Foo',
        );

        $this->transformer->reverseTransform($input);
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformRequiresArray()
    {
        $this->transformer->reverseTransform('12345');
    }
}
PK��ZfJ��etest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BaseDateTimeTransformerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;

class BaseDateTimeTransformerTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException
     * @expectedExceptionMessage this_timezone_does_not_exist
     */
    public function testConstructFailsIfInputTimezoneIsInvalid()
    {
        $this->getMock(
            'Symfony\Component\Form\Extension\Core\DataTransformer\BaseDateTimeTransformer',
            array(),
            array('this_timezone_does_not_exist')
        );
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException
     * @expectedExceptionMessage that_timezone_does_not_exist
     */
    public function testConstructFailsIfOutputTimezoneIsInvalid()
    {
        $this->getMock(
            'Symfony\Component\Form\Extension\Core\DataTransformer\BaseDateTimeTransformer',
            array(),
            array(null, 'that_timezone_does_not_exist')
        );
    }
}
PK��Z�.bc))htest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ChoicesToValuesTransformerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;

use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList;

use Symfony\Component\Form\Extension\Core\DataTransformer\ChoicesToValuesTransformer;

class ChoicesToValuesTransformerTest extends \PHPUnit_Framework_TestCase
{
    protected $transformer;

    protected function setUp()
    {
        $list = new SimpleChoiceList(array(0 => 'A', 1 => 'B', 2 => 'C'));
        $this->transformer = new ChoicesToValuesTransformer($list);
    }

    protected function tearDown()
    {
        $this->transformer = null;
    }

    public function testTransform()
    {
        // Value strategy in SimpleChoiceList is to copy and convert to string
        $in = array(0, 1, 2);
        $out = array('0', '1', '2');

        $this->assertSame($out, $this->transformer->transform($in));
    }

    public function testTransformNull()
    {
        $this->assertSame(array(), $this->transformer->transform(null));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testTransformExpectsArray()
    {
        $this->transformer->transform('foobar');
    }

    public function testReverseTransform()
    {
        // values are expected to be valid choices and stay the same
        $in = array('0', '1', '2');
        $out = array(0, 1, 2);

        $this->assertSame($out, $this->transformer->reverseTransform($in));
    }

    public function testReverseTransformNull()
    {
        $this->assertSame(array(), $this->transformer->reverseTransform(null));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testReverseTransformExpectsArray()
    {
        $this->transformer->reverseTransform('foobar');
    }
}
PK��ZJW����itest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;

use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer;

class DateTimeToStringTransformerTest extends DateTimeTestCase
{
    public function dataProvider()
    {
        $data = array(
            array('Y-m-d H:i:s', '2010-02-03 16:05:06', '2010-02-03 16:05:06 UTC'),
            array('Y-m-d H:i:00', '2010-02-03 16:05:00', '2010-02-03 16:05:00 UTC'),
            array('Y-m-d H:i', '2010-02-03 16:05', '2010-02-03 16:05:00 UTC'),
            array('Y-m-d H', '2010-02-03 16', '2010-02-03 16:00:00 UTC'),
            array('Y-m-d', '2010-02-03', '2010-02-03 00:00:00 UTC'),
            array('Y-m', '2010-12', '2010-12-01 00:00:00 UTC'),
            array('Y', '2010', '2010-01-01 00:00:00 UTC'),
            array('d-m-Y', '03-02-2010', '2010-02-03 00:00:00 UTC'),
            array('H:i:s', '16:05:06', '1970-01-01 16:05:06 UTC'),
            array('H:i:00', '16:05:00', '1970-01-01 16:05:00 UTC'),
            array('H:i', '16:05', '1970-01-01 16:05:00 UTC'),
            array('H', '16', '1970-01-01 16:00:00 UTC'),

            // different day representations
            array('Y-m-j', '2010-02-3', '2010-02-03 00:00:00 UTC'),
            array('z', '33', '1970-02-03 00:00:00 UTC'),

            // not bijective
            // this will not work as PHP will use actual date to replace missing info
            // and after change of date will lookup for closest Wednesday
            // i.e. value: 2010-02, PHP value: 2010-02-(today i.e. 20), parsed date: 2010-02-24
            //array('Y-m-D', '2010-02-Wed', '2010-02-03 00:00:00 UTC'),
            //array('Y-m-l', '2010-02-Wednesday', '2010-02-03 00:00:00 UTC'),

            // different month representations
            array('Y-n-d', '2010-2-03', '2010-02-03 00:00:00 UTC'),
            array('Y-M-d', '2010-Feb-03', '2010-02-03 00:00:00 UTC'),
            array('Y-F-d', '2010-February-03', '2010-02-03 00:00:00 UTC'),

            // different year representations
            array('y-m-d', '10-02-03', '2010-02-03 00:00:00 UTC'),

            // different time representations
            array('G:i:s', '16:05:06', '1970-01-01 16:05:06 UTC'),
            array('g:i:s a', '4:05:06 pm', '1970-01-01 16:05:06 UTC'),
            array('h:i:s a', '04:05:06 pm', '1970-01-01 16:05:06 UTC'),

            // seconds since Unix
            array('U', '1265213106', '2010-02-03 16:05:06 UTC'),
        );

        // This test will fail < 5.3.9 - see https://bugs.php.net/51994
        if (version_compare(phpversion(), '5.3.9', '>=')) {
            $data[] = array('Y-z', '2010-33', '2010-02-03 00:00:00 UTC');
        }

        return $data;
    }

    /**
     * @dataProvider dataProvider
     */
    public function testTransform($format, $output, $input)
    {
        $transformer = new DateTimeToStringTransformer('UTC', 'UTC', $format);

        $input = new \DateTime($input);

        $this->assertEquals($output, $transformer->transform($input));
    }

    public function testTransformEmpty()
    {
        $transformer = new DateTimeToStringTransformer();

        $this->assertSame('', $transformer->transform(null));
    }

    public function testTransformWithDifferentTimezones()
    {
        $transformer = new DateTimeToStringTransformer('Asia/Hong_Kong', 'America/New_York', 'Y-m-d H:i:s');

        $input = new \DateTime('2010-02-03 12:05:06 America/New_York');
        $output = $input->format('Y-m-d H:i:s');
        $input->setTimezone(new \DateTimeZone('Asia/Hong_Kong'));

        $this->assertEquals($output, $transformer->transform($input));
    }

    public function testTransformExpectsDateTime()
    {
        $transformer = new DateTimeToStringTransformer();

        $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException');

        $transformer->transform('1234');
    }

    /**
     * @dataProvider dataProvider
     */
    public function testReverseTransformUsingPipe($format, $input, $output)
    {
        if (version_compare(phpversion(), '5.3.7', '<')) {
            $this->markTestSkipped('Pipe usage requires PHP 5.3.7 or newer.');
        }

        $reverseTransformer = new DateTimeToStringTransformer('UTC', 'UTC', $format, true);

        $output = new \DateTime($output);

        $this->assertDateTimeEquals($output, $reverseTransformer->reverseTransform($input));
    }

    /**
     * @dataProvider dataProvider
     */
    public function testReverseTransformWithoutUsingPipe($format, $input, $output)
    {
        $reverseTransformer = new DateTimeToStringTransformer('UTC', 'UTC', $format, false);

        $output = new \DateTime($output);

        $this->assertDateTimeEquals($output, $reverseTransformer->reverseTransform($input));
    }

    public function testReverseTransformEmpty()
    {
        $reverseTransformer = new DateTimeToStringTransformer();

        $this->assertNull($reverseTransformer->reverseTransform(''));
    }

    public function testReverseTransformWithDifferentTimezones()
    {
        $reverseTransformer = new DateTimeToStringTransformer('America/New_York', 'Asia/Hong_Kong', 'Y-m-d H:i:s');

        $output = new \DateTime('2010-02-03 16:05:06 Asia/Hong_Kong');
        $input = $output->format('Y-m-d H:i:s');
        $output->setTimeZone(new \DateTimeZone('America/New_York'));

        $this->assertDateTimeEquals($output, $reverseTransformer->reverseTransform($input));
    }

    public function testReverseTransformExpectsString()
    {
        $reverseTransformer = new DateTimeToStringTransformer();

        $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException');

        $reverseTransformer->reverseTransform(1234);
    }

    public function testReverseTransformExpectsValidDateString()
    {
        $reverseTransformer = new DateTimeToStringTransformer();

        $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException');

        $reverseTransformer->reverseTransform('2010-2010-2010');
    }

    public function testReverseTransformWithNonExistingDate()
    {
        $reverseTransformer = new DateTimeToStringTransformer();

        $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException');

        $reverseTransformer->reverseTransform('2010-04-31');
    }
}
PK��Z��W@@Otest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/LanguageTypeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\Type;

use Symfony\Component\Form\Extension\Core\View\ChoiceView;
use Symfony\Component\Intl\Util\IntlTestHelper;

class LanguageTypeTest extends TypeTestCase
{
    protected function setUp()
    {
        IntlTestHelper::requireIntl($this);

        parent::setUp();
    }

    public function testCountriesAreSelectable()
    {
        $form = $this->factory->create('language');
        $view = $form->createView();
        $choices = $view->vars['choices'];

        $this->assertContains(new ChoiceView('en', 'en', 'English'), $choices, '', false, false);
        $this->assertContains(new ChoiceView('en_GB', 'en_GB', 'British English'), $choices, '', false, false);
        $this->assertContains(new ChoiceView('en_US', 'en_US', 'U.S. English'), $choices, '', false, false);
        $this->assertContains(new ChoiceView('fr', 'fr', 'French'), $choices, '', false, false);
        $this->assertContains(new ChoiceView('my', 'my', 'Burmese'), $choices, '', false, false);
    }

    public function testMultipleLanguagesIsNotIncluded()
    {
        $form = $this->factory->create('language', 'language');
        $view = $form->createView();
        $choices = $view->vars['choices'];

        $this->assertNotContains(new ChoiceView('mul', 'mul', 'Mehrsprachig'), $choices, '', false, false);
    }
}
PK��Zx���aaMtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/LocaleTypeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\Type;

use Symfony\Component\Form\Extension\Core\View\ChoiceView;
use Symfony\Component\Intl\Util\IntlTestHelper;

class LocaleTypeTest extends TypeTestCase
{
    protected function setUp()
    {
        IntlTestHelper::requireIntl($this);

        parent::setUp();
    }

    public function testLocalesAreSelectable()
    {
        $form = $this->factory->create('locale');
        $view = $form->createView();
        $choices = $view->vars['choices'];

        $this->assertContains(new ChoiceView('en', 'en', 'English'), $choices, '', false, false);
        $this->assertContains(new ChoiceView('en_GB', 'en_GB', 'English (United Kingdom)'), $choices, '', false, false);
        $this->assertContains(new ChoiceView('zh_Hant_MO', 'zh_Hant_MO', 'Chinese (Traditional, Macau SAR China)'), $choices, '', false, false);
    }
}
PK��Z�C���Mtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/ButtonTypeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\Type;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ButtonTypeTest extends BaseTypeTest
{
    public function testCreateButtonInstances()
    {
        $this->assertInstanceOf('Symfony\Component\Form\Button', $this->factory->create('button'));
    }

    protected function getTestedType()
    {
        return 'button';
    }
}
PK��Z�'�\�\Ktest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\Type;

use Symfony\Component\Form\Extension\Core\View\ChoiceView;
use Symfony\Component\Form\FormError;
use Symfony\Component\Intl\Util\IntlTestHelper;

class DateTypeTest extends TypeTestCase
{
    protected function setUp()
    {
        parent::setUp();

        // we test against "de_AT", so we need the full implementation
        IntlTestHelper::requireFullIntl($this);

        \Locale::setDefault('de_AT');
    }

    /**
     * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
     */
    public function testInvalidWidgetOption()
    {
        $this->factory->create('date', null, array(
            'widget' => 'fake_widget',
        ));
    }

    /**
     * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
     */
    public function testInvalidInputOption()
    {
        $this->factory->create('date', null, array(
            'input' => 'fake_input',
        ));
    }

    public function testSubmitFromSingleTextDateTimeWithDefaultFormat()
    {
        $form = $this->factory->create('date', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'widget' => 'single_text',
            'input' => 'datetime',
        ));

        $form->submit('2010-06-02');

        $this->assertDateTimeEquals(new \DateTime('2010-06-02 UTC'), $form->getData());
        $this->assertEquals('2010-06-02', $form->getViewData());
    }

    public function testSubmitFromSingleTextDateTime()
    {
        $form = $this->factory->create('date', null, array(
            'format' => \IntlDateFormatter::MEDIUM,
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'widget' => 'single_text',
            'input' => 'datetime',
        ));

        $form->submit('2.6.2010');

        $this->assertDateTimeEquals(new \DateTime('2010-06-02 UTC'), $form->getData());
        $this->assertEquals('02.06.2010', $form->getViewData());
    }

    public function testSubmitFromSingleTextString()
    {
        $form = $this->factory->create('date', null, array(
            'format' => \IntlDateFormatter::MEDIUM,
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'widget' => 'single_text',
            'input' => 'string',
        ));

        $form->submit('2.6.2010');

        $this->assertEquals('2010-06-02', $form->getData());
        $this->assertEquals('02.06.2010', $form->getViewData());
    }

    public function testSubmitFromSingleTextTimestamp()
    {
        $form = $this->factory->create('date', null, array(
            'format' => \IntlDateFormatter::MEDIUM,
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'widget' => 'single_text',
            'input' => 'timestamp',
        ));

        $form->submit('2.6.2010');

        $dateTime = new \DateTime('2010-06-02 UTC');

        $this->assertEquals($dateTime->format('U'), $form->getData());
        $this->assertEquals('02.06.2010', $form->getViewData());
    }

    public function testSubmitFromSingleTextRaw()
    {
        $form = $this->factory->create('date', null, array(
            'format' => \IntlDateFormatter::MEDIUM,
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'widget' => 'single_text',
            'input' => 'array',
        ));

        $form->submit('2.6.2010');

        $output = array(
            'day' => '2',
            'month' => '6',
            'year' => '2010',
        );

        $this->assertEquals($output, $form->getData());
        $this->assertEquals('02.06.2010', $form->getViewData());
    }

    public function testSubmitFromText()
    {
        $form = $this->factory->create('date', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'widget' => 'text',
        ));

        $text = array(
            'day' => '2',
            'month' => '6',
            'year' => '2010',
        );

        $form->submit($text);

        $dateTime = new \DateTime('2010-06-02 UTC');

        $this->assertDateTimeEquals($dateTime, $form->getData());
        $this->assertEquals($text, $form->getViewData());
    }

    public function testSubmitFromChoice()
    {
        $form = $this->factory->create('date', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'widget' => 'choice',
        ));

        $text = array(
            'day' => '2',
            'month' => '6',
            'year' => '2010',
        );

        $form->submit($text);

        $dateTime = new \DateTime('2010-06-02 UTC');

        $this->assertDateTimeEquals($dateTime, $form->getData());
        $this->assertEquals($text, $form->getViewData());
    }

    public function testSubmitFromChoiceEmpty()
    {
        $form = $this->factory->create('date', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'widget' => 'choice',
            'required' => false,
        ));

        $text = array(
            'day' => '',
            'month' => '',
            'year' => '',
        );

        $form->submit($text);

        $this->assertNull($form->getData());
        $this->assertEquals($text, $form->getViewData());
    }

    public function testSubmitFromInputDateTimeDifferentPattern()
    {
        $form = $this->factory->create('date', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'format' => 'MM*yyyy*dd',
            'widget' => 'single_text',
            'input' => 'datetime',
        ));

        $form->submit('06*2010*02');

        $this->assertDateTimeEquals(new \DateTime('2010-06-02 UTC'), $form->getData());
        $this->assertEquals('06*2010*02', $form->getViewData());
    }

    public function testSubmitFromInputStringDifferentPattern()
    {
        $form = $this->factory->create('date', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'format' => 'MM*yyyy*dd',
            'widget' => 'single_text',
            'input' => 'string',
        ));

        $form->submit('06*2010*02');

        $this->assertEquals('2010-06-02', $form->getData());
        $this->assertEquals('06*2010*02', $form->getViewData());
    }

    public function testSubmitFromInputTimestampDifferentPattern()
    {
        $form = $this->factory->create('date', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'format' => 'MM*yyyy*dd',
            'widget' => 'single_text',
            'input' => 'timestamp',
        ));

        $form->submit('06*2010*02');

        $dateTime = new \DateTime('2010-06-02 UTC');

        $this->assertEquals($dateTime->format('U'), $form->getData());
        $this->assertEquals('06*2010*02', $form->getViewData());
    }

    public function testSubmitFromInputRawDifferentPattern()
    {
        $form = $this->factory->create('date', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'format' => 'MM*yyyy*dd',
            'widget' => 'single_text',
            'input' => 'array',
        ));

        $form->submit('06*2010*02');

        $output = array(
            'day' => '2',
            'month' => '6',
            'year' => '2010',
        );

        $this->assertEquals($output, $form->getData());
        $this->assertEquals('06*2010*02', $form->getViewData());
    }

    /**
     * @dataProvider provideDateFormats
     */
    public function testDatePatternWithFormatOption($format, $pattern)
    {
        $form = $this->factory->create('date', null, array(
            'format' => $format,
        ));

        $view = $form->createView();

        $this->assertEquals($pattern, $view->vars['date_pattern']);
    }

    public function provideDateFormats()
    {
        return array(
            array('dMy', '{{ day }}{{ month }}{{ year }}'),
            array('d-M-yyyy', '{{ day }}-{{ month }}-{{ year }}'),
            array('M d y', '{{ month }} {{ day }} {{ year }}'),
        );
    }

    /**
     * This test is to check that the strings '0', '1', '2', '3' are not accepted
     * as valid IntlDateFormatter constants for FULL, LONG, MEDIUM or SHORT respectively.
     *
     * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
     */
    public function testThrowExceptionIfFormatIsNoPattern()
    {
        $this->factory->create('date', null, array(
            'format' => '0',
            'widget' => 'single_text',
            'input' => 'string',
        ));
    }

    /**
     * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
     */
    public function testThrowExceptionIfFormatDoesNotContainYearMonthAndDay()
    {
        $this->factory->create('date', null, array(
            'months' => array(6, 7),
            'format' => 'yy',
        ));
    }

    /**
     * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
     */
    public function testThrowExceptionIfFormatIsNoConstant()
    {
        $this->factory->create('date', null, array(
            'format' => 105,
        ));
    }

    /**
     * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
     */
    public function testThrowExceptionIfFormatIsInvalid()
    {
        $this->factory->create('date', null, array(
            'format' => array(),
        ));
    }

    public function testSetDataWithDifferentTimezones()
    {
        $form = $this->factory->create('date', null, array(
            'format' => \IntlDateFormatter::MEDIUM,
            'model_timezone' => 'America/New_York',
            'view_timezone' => 'Pacific/Tahiti',
            'input' => 'string',
            'widget' => 'single_text',
        ));

        $form->setData('2010-06-02');

        $this->assertEquals('01.06.2010', $form->getViewData());
    }

    public function testSetDataWithDifferentTimezonesDateTime()
    {
        $form = $this->factory->create('date', null, array(
            'format' => \IntlDateFormatter::MEDIUM,
            'model_timezone' => 'America/New_York',
            'view_timezone' => 'Pacific/Tahiti',
            'input' => 'datetime',
            'widget' => 'single_text',
        ));

        $dateTime = new \DateTime('2010-06-02 America/New_York');

        $form->setData($dateTime);

        $this->assertDateTimeEquals($dateTime, $form->getData());
        $this->assertEquals('01.06.2010', $form->getViewData());
    }

    public function testYearsOption()
    {
        $form = $this->factory->create('date', null, array(
            'years' => array(2010, 2011),
        ));

        $view = $form->createView();

        $this->assertEquals(array(
            new ChoiceView('2010', '2010', '2010'),
            new ChoiceView('2011', '2011', '2011'),
        ), $view['year']->vars['choices']);
    }

    public function testMonthsOption()
    {
        $form = $this->factory->create('date', null, array(
            'months' => array(6, 7),
        ));

        $view = $form->createView();

        $this->assertEquals(array(
            new ChoiceView('6', '6', '06'),
            new ChoiceView('7', '7', '07'),
        ), $view['month']->vars['choices']);
    }

    public function testMonthsOptionShortFormat()
    {
        $form = $this->factory->create('date', null, array(
            'months' => array(1, 4),
            'format' => 'dd.MMM.yy',
        ));

        $view = $form->createView();

        $this->assertEquals(array(
            new ChoiceView('1', '1', 'Jän'),
            new ChoiceView('4', '4', 'Apr.')
        ), $view['month']->vars['choices']);
    }

    public function testMonthsOptionLongFormat()
    {
        $form = $this->factory->create('date', null, array(
            'months' => array(1, 4),
            'format' => 'dd.MMMM.yy',
        ));

        $view = $form->createView();

        $this->assertEquals(array(
            new ChoiceView('1', '1', 'Jänner'),
            new ChoiceView('4', '4', 'April'),
        ), $view['month']->vars['choices']);
    }

    public function testMonthsOptionLongFormatWithDifferentTimezone()
    {
        $form = $this->factory->create('date', null, array(
            'months' => array(1, 4),
            'format' => 'dd.MMMM.yy',
        ));

        $view = $form->createView();

        $this->assertEquals(array(
            new ChoiceView('1', '1', 'Jänner'),
            new ChoiceView('4', '4', 'April'),
        ), $view['month']->vars['choices']);
    }

    public function testIsDayWithinRangeReturnsTrueIfWithin()
    {
        $form = $this->factory->create('date', null, array(
            'days' => array(6, 7),
        ));

        $view = $form->createView();

        $this->assertEquals(array(
            new ChoiceView('6', '6', '06'),
            new ChoiceView('7', '7', '07'),
        ), $view['day']->vars['choices']);
    }

    public function testIsPartiallyFilledReturnsFalseIfSingleText()
    {
        $this->markTestIncomplete('Needs to be reimplemented using validators');

        $form = $this->factory->create('date', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'widget' => 'single_text',
        ));

        $form->submit('7.6.2010');

        $this->assertFalse($form->isPartiallyFilled());
    }

    public function testIsPartiallyFilledReturnsFalseIfChoiceAndCompletelyEmpty()
    {
        $this->markTestIncomplete('Needs to be reimplemented using validators');

        $form = $this->factory->create('date', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'widget' => 'choice',
        ));

        $form->submit(array(
            'day' => '',
            'month' => '',
            'year' => '',
        ));

        $this->assertFalse($form->isPartiallyFilled());
    }

    public function testIsPartiallyFilledReturnsFalseIfChoiceAndCompletelyFilled()
    {
        $this->markTestIncomplete('Needs to be reimplemented using validators');

        $form = $this->factory->create('date', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'widget' => 'choice',
        ));

        $form->submit(array(
            'day' => '2',
            'month' => '6',
            'year' => '2010',
        ));

        $this->assertFalse($form->isPartiallyFilled());
    }

    public function testIsPartiallyFilledReturnsTrueIfChoiceAndDayEmpty()
    {
        $this->markTestIncomplete('Needs to be reimplemented using validators');

        $form = $this->factory->create('date', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'widget' => 'choice',
        ));

        $form->submit(array(
            'day' => '',
            'month' => '6',
            'year' => '2010',
        ));

        $this->assertTrue($form->isPartiallyFilled());
    }

    public function testPassDatePatternToView()
    {
        $form = $this->factory->create('date');
        $view = $form->createView();

        $this->assertSame('{{ day }}{{ month }}{{ year }}', $view->vars['date_pattern']);
    }

    public function testPassDatePatternToViewDifferentFormat()
    {
        $form = $this->factory->create('date', null, array(
            'format' => \IntlDateFormatter::LONG,
        ));

        $view = $form->createView();

        $this->assertSame('{{ day }}{{ month }}{{ year }}', $view->vars['date_pattern']);
    }

    public function testPassDatePatternToViewDifferentPattern()
    {
        $form = $this->factory->create('date', null, array(
            'format' => 'MMyyyydd'
        ));

        $view = $form->createView();

        $this->assertSame('{{ month }}{{ year }}{{ day }}', $view->vars['date_pattern']);
    }

    public function testPassDatePatternToViewDifferentPatternWithSeparators()
    {
        $form = $this->factory->create('date', null, array(
            'format' => 'MM*yyyy*dd'
        ));

        $view = $form->createView();

        $this->assertSame('{{ month }}*{{ year }}*{{ day }}', $view->vars['date_pattern']);
    }

    public function testDontPassDatePatternIfText()
    {
        $form = $this->factory->create('date', null, array(
            'widget' => 'single_text',
        ));
        $view = $form->createView();

        $this->assertFalse(isset($view->vars['date_pattern']));
    }

    public function testPassWidgetToView()
    {
        $form = $this->factory->create('date', null, array(
            'widget' => 'single_text',
        ));
        $view = $form->createView();

        $this->assertSame('single_text', $view->vars['widget']);
    }

    // Bug fix
    public function testInitializeWithDateTime()
    {
        // Throws an exception if "data_class" option is not explicitly set
        // to null in the type
        $this->factory->create('date', new \DateTime());
    }

    public function testSingleTextWidgetShouldUseTheRightInputType()
    {
        $form = $this->factory->create('date', null, array(
            'widget' => 'single_text',
        ));

        $view = $form->createView();
        $this->assertEquals('date', $view->vars['type']);
    }

    public function testPassDefaultEmptyValueToViewIfNotRequired()
    {
        $form = $this->factory->create('date', null, array(
            'required' => false,
        ));

        $view = $form->createView();
        $this->assertSame('', $view['year']->vars['empty_value']);
        $this->assertSame('', $view['month']->vars['empty_value']);
        $this->assertSame('', $view['day']->vars['empty_value']);
    }

    public function testPassNoEmptyValueToViewIfRequired()
    {
        $form = $this->factory->create('date', null, array(
            'required' => true,
        ));

        $view = $form->createView();
        $this->assertNull($view['year']->vars['empty_value']);
        $this->assertNull($view['month']->vars['empty_value']);
        $this->assertNull($view['day']->vars['empty_value']);
    }

    public function testPassEmptyValueAsString()
    {
        $form = $this->factory->create('date', null, array(
            'empty_value' => 'Empty',
        ));

        $view = $form->createView();
        $this->assertSame('Empty', $view['year']->vars['empty_value']);
        $this->assertSame('Empty', $view['month']->vars['empty_value']);
        $this->assertSame('Empty', $view['day']->vars['empty_value']);
    }

    public function testPassEmptyValueAsArray()
    {
        $form = $this->factory->create('date', null, array(
            'empty_value' => array(
                'year' => 'Empty year',
                'month' => 'Empty month',
                'day' => 'Empty day',
            ),
        ));

        $view = $form->createView();
        $this->assertSame('Empty year', $view['year']->vars['empty_value']);
        $this->assertSame('Empty month', $view['month']->vars['empty_value']);
        $this->assertSame('Empty day', $view['day']->vars['empty_value']);
    }

    public function testPassEmptyValueAsPartialArrayAddEmptyIfNotRequired()
    {
        $form = $this->factory->create('date', null, array(
            'required' => false,
            'empty_value' => array(
                'year' => 'Empty year',
                'day' => 'Empty day',
            ),
        ));

        $view = $form->createView();
        $this->assertSame('Empty year', $view['year']->vars['empty_value']);
        $this->assertSame('', $view['month']->vars['empty_value']);
        $this->assertSame('Empty day', $view['day']->vars['empty_value']);
    }

    public function testPassEmptyValueAsPartialArrayAddNullIfRequired()
    {
        $form = $this->factory->create('date', null, array(
            'required' => true,
            'empty_value' => array(
                'year' => 'Empty year',
                'day' => 'Empty day',
            ),
        ));

        $view = $form->createView();
        $this->assertSame('Empty year', $view['year']->vars['empty_value']);
        $this->assertNull($view['month']->vars['empty_value']);
        $this->assertSame('Empty day', $view['day']->vars['empty_value']);
    }

    public function testPassHtml5TypeIfSingleTextAndHtml5Format()
    {
        $form = $this->factory->create('date', null, array(
            'widget' => 'single_text',
        ));

        $view = $form->createView();
        $this->assertSame('date', $view->vars['type']);
    }

    public function testDontPassHtml5TypeIfNotHtml5Format()
    {
        $form = $this->factory->create('date', null, array(
            'widget' => 'single_text',
            'format' => \IntlDateFormatter::MEDIUM,
        ));

        $view = $form->createView();
        $this->assertFalse(isset($view->vars['type']));
    }

    public function testDontPassHtml5TypeIfNotSingleText()
    {
        $form = $this->factory->create('date', null, array(
            'widget' => 'text',
        ));

        $view = $form->createView();
        $this->assertFalse(isset($view->vars['type']));
    }

    public function provideCompoundWidgets()
    {
        return array(
            array('text'),
            array('choice'),
        );
    }

    /**
     * @dataProvider provideCompoundWidgets
     */
    public function testYearErrorsBubbleUp($widget)
    {
        $error = new FormError('Invalid!');
        $form = $this->factory->create('date', null, array(
            'widget' => $widget,
        ));
        $form['year']->addError($error);

        $this->assertSame(array(), $form['year']->getErrors());
        $this->assertSame(array($error), $form->getErrors());
    }

    /**
     * @dataProvider provideCompoundWidgets
     */
    public function testMonthErrorsBubbleUp($widget)
    {
        $error = new FormError('Invalid!');
        $form = $this->factory->create('date', null, array(
            'widget' => $widget,
        ));
        $form['month']->addError($error);

        $this->assertSame(array(), $form['month']->getErrors());
        $this->assertSame(array($error), $form->getErrors());
    }

    /**
     * @dataProvider provideCompoundWidgets
     */
    public function testDayErrorsBubbleUp($widget)
    {
        $error = new FormError('Invalid!');
        $form = $this->factory->create('date', null, array(
            'widget' => $widget,
        ));
        $form['day']->addError($error);

        $this->assertSame(array(), $form['day']->getErrors());
        $this->assertSame(array($error), $form->getErrors());
    }

    public function testYearsFor32BitsMachines()
    {
        if (4 !== PHP_INT_SIZE) {
            $this->markTestSkipped(
                'PHP must be compiled in 32 bit mode to run this test');
        }

        $form = $this->factory->create('date', null, array(
            'years' => range(1900, 2040),
        ));

        $view = $form->createView();

        $listChoices = array();
        foreach (range(1902, 2037) as $y) {
            $listChoices[] = new ChoiceView($y, $y, $y);
        }

        $this->assertEquals($listChoices, $view['year']->vars['choices']);
    }
}
PK��Zvzw�LLQtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\Type;

use Symfony\Component\Form\Form;

class CollectionTypeTest extends \Symfony\Component\Form\Test\TypeTestCase
{
    public function testContainsNoChildByDefault()
    {
        $form = $this->factory->create('collection', null, array(
            'type' => 'text',
        ));

        $this->assertCount(0, $form);
    }

    public function testSetDataAdjustsSize()
    {
        $form = $this->factory->create('collection', null, array(
            'type' => 'text',
            'options' => array(
                'max_length' => 20,
            ),
        ));
        $form->setData(array('foo@foo.com', 'foo@bar.com'));

        $this->assertInstanceOf('Symfony\Component\Form\Form', $form[0]);
        $this->assertInstanceOf('Symfony\Component\Form\Form', $form[1]);
        $this->assertCount(2, $form);
        $this->assertEquals('foo@foo.com', $form[0]->getData());
        $this->assertEquals('foo@bar.com', $form[1]->getData());
        $this->assertEquals(20, $form[0]->getConfig()->getOption('max_length'));
        $this->assertEquals(20, $form[1]->getConfig()->getOption('max_length'));

        $form->setData(array('foo@baz.com'));
        $this->assertInstanceOf('Symfony\Component\Form\Form', $form[0]);
        $this->assertFalse(isset($form[1]));
        $this->assertCount(1, $form);
        $this->assertEquals('foo@baz.com', $form[0]->getData());
        $this->assertEquals(20, $form[0]->getConfig()->getOption('max_length'));
    }

    public function testThrowsExceptionIfObjectIsNotTraversable()
    {
        $form = $this->factory->create('collection', null, array(
            'type' => 'text',
        ));
        $this->setExpectedException('Symfony\Component\Form\Exception\UnexpectedTypeException');
        $form->setData(new \stdClass());
    }

    public function testNotResizedIfSubmittedWithMissingData()
    {
        $form = $this->factory->create('collection', null, array(
            'type' => 'text',
        ));
        $form->setData(array('foo@foo.com', 'bar@bar.com'));
        $form->submit(array('foo@bar.com'));

        $this->assertTrue($form->has('0'));
        $this->assertTrue($form->has('1'));
        $this->assertEquals('foo@bar.com', $form[0]->getData());
        $this->assertEquals('', $form[1]->getData());
    }

    public function testResizedDownIfSubmittedWithMissingDataAndAllowDelete()
    {
        $form = $this->factory->create('collection', null, array(
            'type' => 'text',
            'allow_delete' => true,
        ));
        $form->setData(array('foo@foo.com', 'bar@bar.com'));
        $form->submit(array('foo@foo.com'));

        $this->assertTrue($form->has('0'));
        $this->assertFalse($form->has('1'));
        $this->assertEquals('foo@foo.com', $form[0]->getData());
        $this->assertEquals(array('foo@foo.com'), $form->getData());
    }

    public function testNotResizedIfSubmittedWithExtraData()
    {
        $form = $this->factory->create('collection', null, array(
            'type' => 'text',
        ));
        $form->setData(array('foo@bar.com'));
        $form->submit(array('foo@foo.com', 'bar@bar.com'));

        $this->assertTrue($form->has('0'));
        $this->assertFalse($form->has('1'));
        $this->assertEquals('foo@foo.com', $form[0]->getData());
    }

    public function testResizedUpIfSubmittedWithExtraDataAndAllowAdd()
    {
        $form = $this->factory->create('collection', null, array(
            'type' => 'text',
            'allow_add' => true,
        ));
        $form->setData(array('foo@bar.com'));
        $form->submit(array('foo@bar.com', 'bar@bar.com'));

        $this->assertTrue($form->has('0'));
        $this->assertTrue($form->has('1'));
        $this->assertEquals('foo@bar.com', $form[0]->getData());
        $this->assertEquals('bar@bar.com', $form[1]->getData());
        $this->assertEquals(array('foo@bar.com', 'bar@bar.com'), $form->getData());
    }

    public function testAllowAddButNoPrototype()
    {
        $form = $this->factory->create('collection', null, array(
            'type'      => 'form',
            'allow_add' => true,
            'prototype' => false,
        ));

        $this->assertFalse($form->has('__name__'));
    }

    public function testPrototypeMultipartPropagation()
    {
        $form = $this->factory
            ->create('collection', null, array(
                'type'      => 'file',
                'allow_add' => true,
                'prototype' => true,
            ))
        ;

        $this->assertTrue($form->createView()->vars['multipart']);
    }

    public function testGetDataDoesNotContainsPrototypeNameBeforeDataAreSet()
    {
        $form = $this->factory->create('collection', array(), array(
            'type'      => 'file',
            'prototype' => true,
            'allow_add' => true,
        ));

        $data = $form->getData();
        $this->assertFalse(isset($data['__name__']));
    }

    public function testGetDataDoesNotContainsPrototypeNameAfterDataAreSet()
    {
        $form = $this->factory->create('collection', array(), array(
            'type'      => 'file',
            'allow_add' => true,
            'prototype' => true,
        ));

        $form->setData(array('foobar.png'));
        $data = $form->getData();
        $this->assertFalse(isset($data['__name__']));
    }

    public function testPrototypeNameOption()
    {
        $form = $this->factory->create('collection', null, array(
            'type'      => 'form',
            'prototype' => true,
            'allow_add' => true,
        ));

        $this->assertSame('__name__', $form->getConfig()->getAttribute('prototype')->getName(), '__name__ is the default');

        $form = $this->factory->create('collection', null, array(
            'type'           => 'form',
            'prototype'      => true,
            'allow_add'      => true,
            'prototype_name' => '__test__',
        ));

        $this->assertSame('__test__', $form->getConfig()->getAttribute('prototype')->getName());
    }

    public function testPrototypeDefaultLabel()
    {
        $form = $this->factory->create('collection', array(), array(
            'type'      => 'file',
            'allow_add' => true,
            'prototype' => true,
            'prototype_name' => '__test__',
        ));

        $this->assertSame('__test__label__', $form->createView()->vars['prototype']->vars['label']);
    }
}
PK��Z�(��__Otest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/PasswordTypeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\Type;

class PasswordTypeTest extends \Symfony\Component\Form\Test\TypeTestCase
{
    public function testEmptyIfNotSubmitted()
    {
        $form = $this->factory->create('password');
        $form->setData('pAs5w0rd');
        $view = $form->createView();

        $this->assertSame('', $view->vars['value']);
    }

    public function testEmptyIfSubmitted()
    {
        $form = $this->factory->create('password');
        $form->submit('pAs5w0rd');
        $view = $form->createView();

        $this->assertSame('', $view->vars['value']);
    }

    public function testNotEmptyIfSubmittedAndNotAlwaysEmpty()
    {
        $form = $this->factory->create('password', null, array('always_empty' => false));
        $form->submit('pAs5w0rd');
        $view = $form->createView();

        $this->assertSame('pAs5w0rd', $view->vars['value']);
    }

    public function testNotTrimmed()
    {
        $form = $this->factory->create('password', null);
        $form->submit(' pAs5w0rd ');
        $data = $form->getData();

        $this->assertSame(' pAs5w0rd ', $data);
    }
}
PK��Zx�=�t=t=Otest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\Type;

use Symfony\Component\Form\FormError;
use Symfony\Component\Intl\Util\IntlTestHelper;

class DateTimeTypeTest extends TypeTestCase
{
    protected function setUp()
    {
        IntlTestHelper::requireIntl($this);

        parent::setUp();
    }

    public function testSubmitDateTime()
    {
        $form = $this->factory->create('datetime', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'date_widget' => 'choice',
            'time_widget' => 'choice',
            'input' => 'datetime',
        ));

        $form->submit(array(
            'date' => array(
                'day' => '2',
                'month' => '6',
                'year' => '2010',
            ),
            'time' => array(
                'hour' => '3',
                'minute' => '4',
            ),
        ));

        $dateTime = new \DateTime('2010-06-02 03:04:00 UTC');

        $this->assertDateTimeEquals($dateTime, $form->getData());
    }

    public function testSubmitString()
    {
        $form = $this->factory->create('datetime', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'input' => 'string',
            'date_widget' => 'choice',
            'time_widget' => 'choice',
        ));

        $form->submit(array(
            'date' => array(
                'day' => '2',
                'month' => '6',
                'year' => '2010',
            ),
            'time' => array(
                'hour' => '3',
                'minute' => '4',
            ),
        ));

        $this->assertEquals('2010-06-02 03:04:00', $form->getData());
    }

    public function testSubmitTimestamp()
    {
        $form = $this->factory->create('datetime', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'input' => 'timestamp',
            'date_widget' => 'choice',
            'time_widget' => 'choice',
        ));

        $form->submit(array(
            'date' => array(
                'day' => '2',
                'month' => '6',
                'year' => '2010',
            ),
            'time' => array(
                'hour' => '3',
                'minute' => '4',
            ),
        ));

        $dateTime = new \DateTime('2010-06-02 03:04:00 UTC');

        $this->assertEquals($dateTime->format('U'), $form->getData());
    }

    public function testSubmitWithoutMinutes()
    {
        $form = $this->factory->create('datetime', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'date_widget' => 'choice',
            'time_widget' => 'choice',
            'input' => 'datetime',
            'with_minutes' => false,
        ));

        $form->setData(new \DateTime('2010-06-02 03:04:05 UTC'));

        $input = array(
            'date' => array(
                'day' => '2',
                'month' => '6',
                'year' => '2010',
            ),
            'time' => array(
                'hour' => '3',
            ),
        );

        $form->submit($input);

        $this->assertDateTimeEquals(new \DateTime('2010-06-02 03:00:00 UTC'), $form->getData());
    }

    public function testSubmitWithSeconds()
    {
        $form = $this->factory->create('datetime', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'date_widget' => 'choice',
            'time_widget' => 'choice',
            'input' => 'datetime',
            'with_seconds' => true,
        ));

        $form->setData(new \DateTime('2010-06-02 03:04:05 UTC'));

        $input = array(
            'date' => array(
                'day' => '2',
                'month' => '6',
                'year' => '2010',
            ),
            'time' => array(
                'hour' => '3',
                'minute' => '4',
                'second' => '5',
            ),
        );

        $form->submit($input);

        $this->assertDateTimeEquals(new \DateTime('2010-06-02 03:04:05 UTC'), $form->getData());
    }

    public function testSubmitDifferentTimezones()
    {
        $form = $this->factory->create('datetime', null, array(
            'model_timezone' => 'America/New_York',
            'view_timezone' => 'Pacific/Tahiti',
            'date_widget' => 'choice',
            'time_widget' => 'choice',
            'input' => 'string',
            'with_seconds' => true,
        ));

        $dateTime = new \DateTime('2010-06-02 03:04:05 Pacific/Tahiti');

        $form->submit(array(
            'date' => array(
                'day' => (int) $dateTime->format('d'),
                'month' => (int) $dateTime->format('m'),
                'year' => (int) $dateTime->format('Y'),
            ),
            'time' => array(
                'hour' => (int) $dateTime->format('H'),
                'minute' => (int) $dateTime->format('i'),
                'second' => (int) $dateTime->format('s'),
            ),
        ));

        $dateTime->setTimezone(new \DateTimeZone('America/New_York'));

        $this->assertEquals($dateTime->format('Y-m-d H:i:s'), $form->getData());
    }

    public function testSubmitDifferentTimezonesDateTime()
    {
        $form = $this->factory->create('datetime', null, array(
            'model_timezone' => 'America/New_York',
            'view_timezone' => 'Pacific/Tahiti',
            'widget' => 'single_text',
            'input' => 'datetime',
        ));

        $outputTime = new \DateTime('2010-06-02 03:04:00 Pacific/Tahiti');

        $form->submit('2010-06-02T03:04:00-10:00');

        $outputTime->setTimezone(new \DateTimeZone('America/New_York'));

        $this->assertDateTimeEquals($outputTime, $form->getData());
        $this->assertEquals('2010-06-02T03:04:00-10:00', $form->getViewData());
    }

    public function testSubmitStringSingleText()
    {
        $form = $this->factory->create('datetime', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'input' => 'string',
            'widget' => 'single_text',
        ));

        $form->submit('2010-06-02T03:04:00Z');

        $this->assertEquals('2010-06-02 03:04:00', $form->getData());
        $this->assertEquals('2010-06-02T03:04:00Z', $form->getViewData());
    }

    public function testSubmitStringSingleTextWithSeconds()
    {
        $form = $this->factory->create('datetime', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'input' => 'string',
            'widget' => 'single_text',
            'with_seconds' => true,
        ));

        $form->submit('2010-06-02T03:04:05Z');

        $this->assertEquals('2010-06-02 03:04:05', $form->getData());
        $this->assertEquals('2010-06-02T03:04:05Z', $form->getViewData());
    }

    public function testSubmitDifferentPattern()
    {
        $form = $this->factory->create('datetime', null, array(
            'date_format' => 'MM*yyyy*dd',
            'date_widget' => 'single_text',
            'time_widget' => 'single_text',
            'input' => 'datetime',
        ));

        $dateTime = new \DateTime('2010-06-02 03:04');

        $form->submit(array(
            'date' => '06*2010*02',
            'time' => '03:04',
        ));

        $this->assertDateTimeEquals($dateTime, $form->getData());
    }

    // Bug fix
    public function testInitializeWithDateTime()
    {
        // Throws an exception if "data_class" option is not explicitly set
        // to null in the type
        $this->factory->create('datetime', new \DateTime());
    }

    public function testSingleTextWidgetShouldUseTheRightInputType()
    {
        $form = $this->factory->create('datetime', null, array(
            'widget' => 'single_text',
        ));

        $view = $form->createView();
        $this->assertEquals('datetime', $view->vars['type']);
    }

    public function testPassDefaultEmptyValueToViewIfNotRequired()
    {
        $form = $this->factory->create('datetime', null, array(
            'required' => false,
            'with_seconds' => true,
        ));

        $view = $form->createView();
        $this->assertSame('', $view['date']['year']->vars['empty_value']);
        $this->assertSame('', $view['date']['month']->vars['empty_value']);
        $this->assertSame('', $view['date']['day']->vars['empty_value']);
        $this->assertSame('', $view['time']['hour']->vars['empty_value']);
        $this->assertSame('', $view['time']['minute']->vars['empty_value']);
        $this->assertSame('', $view['time']['second']->vars['empty_value']);
    }

    public function testPassNoEmptyValueToViewIfRequired()
    {
        $form = $this->factory->create('datetime', null, array(
            'required' => true,
            'with_seconds' => true,
        ));

        $view = $form->createView();
        $this->assertNull($view['date']['year']->vars['empty_value']);
        $this->assertNull($view['date']['month']->vars['empty_value']);
        $this->assertNull($view['date']['day']->vars['empty_value']);
        $this->assertNull($view['time']['hour']->vars['empty_value']);
        $this->assertNull($view['time']['minute']->vars['empty_value']);
        $this->assertNull($view['time']['second']->vars['empty_value']);
    }

    public function testPassEmptyValueAsString()
    {
        $form = $this->factory->create('datetime', null, array(
            'empty_value' => 'Empty',
            'with_seconds' => true,
        ));

        $view = $form->createView();
        $this->assertSame('Empty', $view['date']['year']->vars['empty_value']);
        $this->assertSame('Empty', $view['date']['month']->vars['empty_value']);
        $this->assertSame('Empty', $view['date']['day']->vars['empty_value']);
        $this->assertSame('Empty', $view['time']['hour']->vars['empty_value']);
        $this->assertSame('Empty', $view['time']['minute']->vars['empty_value']);
        $this->assertSame('Empty', $view['time']['second']->vars['empty_value']);
    }

    public function testPassEmptyValueAsArray()
    {
        $form = $this->factory->create('datetime', null, array(
            'empty_value' => array(
                'year' => 'Empty year',
                'month' => 'Empty month',
                'day' => 'Empty day',
                'hour' => 'Empty hour',
                'minute' => 'Empty minute',
                'second' => 'Empty second',
            ),
            'with_seconds' => true,
        ));

        $view = $form->createView();
        $this->assertSame('Empty year', $view['date']['year']->vars['empty_value']);
        $this->assertSame('Empty month', $view['date']['month']->vars['empty_value']);
        $this->assertSame('Empty day', $view['date']['day']->vars['empty_value']);
        $this->assertSame('Empty hour', $view['time']['hour']->vars['empty_value']);
        $this->assertSame('Empty minute', $view['time']['minute']->vars['empty_value']);
        $this->assertSame('Empty second', $view['time']['second']->vars['empty_value']);
    }

    public function testPassEmptyValueAsPartialArrayAddEmptyIfNotRequired()
    {
        $form = $this->factory->create('datetime', null, array(
            'required' => false,
            'empty_value' => array(
                'year' => 'Empty year',
                'day' => 'Empty day',
                'hour' => 'Empty hour',
                'second' => 'Empty second',
            ),
            'with_seconds' => true,
        ));

        $view = $form->createView();
        $this->assertSame('Empty year', $view['date']['year']->vars['empty_value']);
        $this->assertSame('', $view['date']['month']->vars['empty_value']);
        $this->assertSame('Empty day', $view['date']['day']->vars['empty_value']);
        $this->assertSame('Empty hour', $view['time']['hour']->vars['empty_value']);
        $this->assertSame('', $view['time']['minute']->vars['empty_value']);
        $this->assertSame('Empty second', $view['time']['second']->vars['empty_value']);
    }

    public function testPassEmptyValueAsPartialArrayAddNullIfRequired()
    {
        $form = $this->factory->create('datetime', null, array(
            'required' => true,
            'empty_value' => array(
                'year' => 'Empty year',
                'day' => 'Empty day',
                'hour' => 'Empty hour',
                'second' => 'Empty second',
            ),
            'with_seconds' => true,
        ));

        $view = $form->createView();
        $this->assertSame('Empty year', $view['date']['year']->vars['empty_value']);
        $this->assertNull($view['date']['month']->vars['empty_value']);
        $this->assertSame('Empty day', $view['date']['day']->vars['empty_value']);
        $this->assertSame('Empty hour', $view['time']['hour']->vars['empty_value']);
        $this->assertNull($view['time']['minute']->vars['empty_value']);
        $this->assertSame('Empty second', $view['time']['second']->vars['empty_value']);
    }

    public function testPassHtml5TypeIfSingleTextAndHtml5Format()
    {
        $form = $this->factory->create('datetime', null, array(
            'widget' => 'single_text',
        ));

        $view = $form->createView();
        $this->assertSame('datetime', $view->vars['type']);
    }

    public function testDontPassHtml5TypeIfNotHtml5Format()
    {
        $form = $this->factory->create('datetime', null, array(
            'widget' => 'single_text',
            'format' => 'yyyy-MM-dd HH:mm',
        ));

        $view = $form->createView();
        $this->assertFalse(isset($view->vars['type']));
    }

    public function testDontPassHtml5TypeIfNotSingleText()
    {
        $form = $this->factory->create('datetime', null, array(
            'widget' => 'text',
        ));

        $view = $form->createView();
        $this->assertFalse(isset($view->vars['type']));
    }

    public function testDateTypeChoiceErrorsBubbleUp()
    {
        $error = new FormError('Invalid!');
        $form = $this->factory->create('datetime', null);

        $form['date']->addError($error);

        $this->assertSame(array(), $form['date']->getErrors());
        $this->assertSame(array($error), $form->getErrors());
    }

    public function testDateTypeSingleTextErrorsBubbleUp()
    {
        $error = new FormError('Invalid!');
        $form = $this->factory->create('datetime', null, array(
            'date_widget' => 'single_text'
        ));

        $form['date']->addError($error);

        $this->assertSame(array(), $form['date']->getErrors());
        $this->assertSame(array($error), $form->getErrors());
    }

    public function testTimeTypeChoiceErrorsBubbleUp()
    {
        $error = new FormError('Invalid!');
        $form = $this->factory->create('datetime', null);

        $form['time']->addError($error);

        $this->assertSame(array(), $form['time']->getErrors());
        $this->assertSame(array($error), $form->getErrors());
    }

    public function testTimeTypeSingleTextErrorsBubbleUp()
    {
        $error = new FormError('Invalid!');
        $form = $this->factory->create('datetime', null, array(
            'time_widget' => 'single_text'
        ));

        $form['time']->addError($error);

        $this->assertSame(array(), $form['time']->getErrors());
        $this->assertSame(array($error), $form->getErrors());
    }

}
PK��ZP�!���Jtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/UrlTypeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\Type;

class UrlTypeTest extends TypeTestCase
{
    public function testSubmitAddsDefaultProtocolIfNoneIsIncluded()
    {
        $form = $this->factory->create('url', 'name');

        $form->submit('www.domain.com');

        $this->assertSame('http://www.domain.com', $form->getData());
        $this->assertSame('http://www.domain.com', $form->getViewData());
    }

    public function testSubmitAddsNoDefaultProtocolIfAlreadyIncluded()
    {
        $form = $this->factory->create('url', null, array(
            'default_protocol' => 'http',
        ));

        $form->submit('ftp://www.domain.com');

        $this->assertSame('ftp://www.domain.com', $form->getData());
        $this->assertSame('ftp://www.domain.com', $form->getViewData());
    }

    public function testSubmitAddsNoDefaultProtocolIfEmpty()
    {
        $form = $this->factory->create('url', null, array(
            'default_protocol' => 'http',
        ));

        $form->submit('');

        $this->assertNull($form->getData());
        $this->assertSame('', $form->getViewData());
    }

    public function testSubmitAddsNoDefaultProtocolIfSetToNull()
    {
        $form = $this->factory->create('url', null, array(
            'default_protocol' => null,
        ));

        $form->submit('www.domain.com');

        $this->assertSame('www.domain.com', $form->getData());
        $this->assertSame('www.domain.com', $form->getViewData());
    }
}
PK��ZX�:::Ktest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/TypeTestCase.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\Type;

use Symfony\Component\Form\Test\TypeTestCase as BaseTypeTestCase;

/**
 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use Symfony\Component\Form\Test\TypeTestCase instead.
 */
abstract class TypeTestCase extends BaseTypeTestCase
{
}
PK��Z����Ntest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/CountryTypeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\Type;

use Symfony\Component\Form\Extension\Core\View\ChoiceView;
use Symfony\Component\Intl\Util\IntlTestHelper;

class CountryTypeTest extends TypeTestCase
{
    protected function setUp()
    {
        IntlTestHelper::requireIntl($this);

        parent::setUp();
    }

    public function testCountriesAreSelectable()
    {
        $form = $this->factory->create('country');
        $view = $form->createView();
        $choices = $view->vars['choices'];

        // Don't check objects for identity
        $this->assertContains(new ChoiceView('DE', 'DE', 'Germany'), $choices, '', false, false);
        $this->assertContains(new ChoiceView('GB', 'GB', 'United Kingdom'), $choices, '', false, false);
        $this->assertContains(new ChoiceView('US', 'US', 'United States'), $choices, '', false, false);
        $this->assertContains(new ChoiceView('FR', 'FR', 'France'), $choices, '', false, false);
        $this->assertContains(new ChoiceView('MY', 'MY', 'Malaysia'), $choices, '', false, false);
    }

    public function testUnknownCountryIsNotIncluded()
    {
        $form = $this->factory->create('country', 'country');
        $view = $form->createView();
        $choices = $view->vars['choices'];

        foreach ($choices as $choice) {
            if ('ZZ' === $choice->value) {
                $this->fail('Should not contain choice "ZZ"');
            }
        }
    }
}
PK��Z�_*G��Xtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypePerformanceTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\Type;

use Symfony\Component\Form\Test\FormPerformanceTestCase;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ChoiceTypePerformanceTest extends FormPerformanceTestCase
{
    /**
     * This test case is realistic in collection forms where each
     * row contains the same choice field.
     *
     * @group benchmark
     */
    public function testSameChoiceFieldCreatedMultipleTimes()
    {
        $this->setMaxRunningTime(1);
        $choices = range(1, 300);

        for ($i = 0; $i < 100; ++$i) {
            $this->factory->create('choice', rand(1, 400), array(
                'choices' => $choices,
            ));
        }
    }
}
PK��Z�{MK��Ktest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/BaseTypeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\Type;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
abstract class BaseTypeTest extends \Symfony\Component\Form\Test\TypeTestCase
{
    public function testPassDisabledAsOption()
    {
        $form = $this->factory->create($this->getTestedType(), null, array('disabled' => true));

        $this->assertTrue($form->isDisabled());
    }

    public function testPassIdAndNameToView()
    {
        $view = $this->factory->createNamed('name', $this->getTestedType())
            ->createView();

        $this->assertEquals('name', $view->vars['id']);
        $this->assertEquals('name', $view->vars['name']);
        $this->assertEquals('name', $view->vars['full_name']);
    }

    public function testStripLeadingUnderscoresAndDigitsFromId()
    {
        $view = $this->factory->createNamed('_09name', $this->getTestedType())
            ->createView();

        $this->assertEquals('name', $view->vars['id']);
        $this->assertEquals('_09name', $view->vars['name']);
        $this->assertEquals('_09name', $view->vars['full_name']);
    }

    public function testPassIdAndNameToViewWithParent()
    {
        $view = $this->factory->createNamedBuilder('parent', 'form')
            ->add('child', $this->getTestedType())
            ->getForm()
            ->createView();

        $this->assertEquals('parent_child', $view['child']->vars['id']);
        $this->assertEquals('child', $view['child']->vars['name']);
        $this->assertEquals('parent[child]', $view['child']->vars['full_name']);
    }

    public function testPassIdAndNameToViewWithGrandParent()
    {
        $builder = $this->factory->createNamedBuilder('parent', 'form')
            ->add('child', 'form');
        $builder->get('child')->add('grand_child', $this->getTestedType());
        $view = $builder->getForm()->createView();

        $this->assertEquals('parent_child_grand_child', $view['child']['grand_child']->vars['id']);
        $this->assertEquals('grand_child', $view['child']['grand_child']->vars['name']);
        $this->assertEquals('parent[child][grand_child]', $view['child']['grand_child']->vars['full_name']);
    }

    public function testPassTranslationDomainToView()
    {
        $form = $this->factory->create($this->getTestedType(), null, array(
            'translation_domain' => 'domain',
        ));
        $view = $form->createView();

        $this->assertSame('domain', $view->vars['translation_domain']);
    }

    public function testInheritTranslationDomainFromParent()
    {
        $view = $this->factory
            ->createNamedBuilder('parent', 'form', null, array(
                'translation_domain' => 'domain',
            ))
            ->add('child', $this->getTestedType())
            ->getForm()
            ->createView();

        $this->assertEquals('domain', $view['child']->vars['translation_domain']);
    }

    public function testPreferOwnTranslationDomain()
    {
        $view = $this->factory
            ->createNamedBuilder('parent', 'form', null, array(
                'translation_domain' => 'parent_domain',
            ))
            ->add('child', $this->getTestedType(), array(
                'translation_domain' => 'domain',
            ))
            ->getForm()
            ->createView();

        $this->assertEquals('domain', $view['child']->vars['translation_domain']);
    }

    public function testDefaultTranslationDomain()
    {
        $view = $this->factory->createNamedBuilder('parent', 'form')
            ->add('child', $this->getTestedType())
            ->getForm()
            ->createView();

        $this->assertEquals('messages', $view['child']->vars['translation_domain']);
    }

    public function testPassLabelToView()
    {
        $form = $this->factory->createNamed('__test___field', $this->getTestedType(), null, array('label' => 'My label'));
        $view = $form->createView();

        $this->assertSame('My label', $view->vars['label']);
    }

    public function testPassMultipartFalseToView()
    {
        $form = $this->factory->create($this->getTestedType());
        $view = $form->createView();

        $this->assertFalse($view->vars['multipart']);
    }

    abstract protected function getTestedType();
}
PK��Zސ/���Otest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/TimezoneTypeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\Type;

use Symfony\Component\Form\Extension\Core\View\ChoiceView;

class TimezoneTypeTest extends \Symfony\Component\Form\Test\TypeTestCase
{
    public function testTimezonesAreSelectable()
    {
        $form = $this->factory->create('timezone');
        $view = $form->createView();
        $choices = $view->vars['choices'];

        $this->assertArrayHasKey('Africa', $choices);
        $this->assertContains(new ChoiceView('Africa/Kinshasa', 'Africa/Kinshasa', 'Kinshasa'), $choices['Africa'], '', false, false);

        $this->assertArrayHasKey('America', $choices);
        $this->assertContains(new ChoiceView('America/New_York', 'America/New_York', 'New York'), $choices['America'], '', false, false);
    }
}
PK��ZdwҢSJSJKtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\Type;

use Symfony\Component\Form\Extension\Core\View\ChoiceView;
use Symfony\Component\Form\FormError;
use Symfony\Component\Intl\Util\IntlTestHelper;

class TimeTypeTest extends TypeTestCase
{
    protected function setUp()
    {
        IntlTestHelper::requireIntl($this);

        parent::setUp();
    }

    public function testSubmitDateTime()
    {
        $form = $this->factory->create('time', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'input' => 'datetime',
        ));

        $input = array(
            'hour' => '3',
            'minute' => '4',
        );

        $form->submit($input);

        $dateTime = new \DateTime('1970-01-01 03:04:00 UTC');

        $this->assertEquals($dateTime, $form->getData());
        $this->assertEquals($input, $form->getViewData());
    }

    public function testSubmitString()
    {
        $form = $this->factory->create('time', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'input' => 'string',
        ));

        $input = array(
            'hour' => '3',
            'minute' => '4',
        );

        $form->submit($input);

        $this->assertEquals('03:04:00', $form->getData());
        $this->assertEquals($input, $form->getViewData());
    }

    public function testSubmitTimestamp()
    {
        $form = $this->factory->create('time', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'input' => 'timestamp',
        ));

        $input = array(
            'hour' => '3',
            'minute' => '4',
        );

        $form->submit($input);

        $dateTime = new \DateTime('1970-01-01 03:04:00 UTC');

        $this->assertEquals($dateTime->format('U'), $form->getData());
        $this->assertEquals($input, $form->getViewData());
    }

    public function testSubmitArray()
    {
        $form = $this->factory->create('time', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'input' => 'array',
        ));

        $input = array(
            'hour' => '3',
            'minute' => '4',
        );

        $form->submit($input);

        $this->assertEquals($input, $form->getData());
        $this->assertEquals($input, $form->getViewData());
    }

    public function testSubmitDatetimeSingleText()
    {
        $form = $this->factory->create('time', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'input' => 'datetime',
            'widget' => 'single_text',
        ));

        $form->submit('03:04');

        $this->assertEquals(new \DateTime('1970-01-01 03:04:00 UTC'), $form->getData());
        $this->assertEquals('03:04', $form->getViewData());
    }

    public function testSubmitDatetimeSingleTextWithoutMinutes()
    {
        $form = $this->factory->create('time', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'input' => 'datetime',
            'widget' => 'single_text',
            'with_minutes' => false,
        ));

        $form->submit('03');

        $this->assertEquals(new \DateTime('1970-01-01 03:00:00 UTC'), $form->getData());
        $this->assertEquals('03', $form->getViewData());
    }

    public function testSubmitArraySingleText()
    {
        $form = $this->factory->create('time', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'input' => 'array',
            'widget' => 'single_text',
        ));

        $data = array(
            'hour' => '3',
            'minute' => '4',
        );

        $form->submit('03:04');

        $this->assertEquals($data, $form->getData());
        $this->assertEquals('03:04', $form->getViewData());
    }

    public function testSubmitArraySingleTextWithoutMinutes()
    {
        $form = $this->factory->create('time', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'input' => 'array',
            'widget' => 'single_text',
            'with_minutes' => false,
        ));

        $data = array(
            'hour' => '3',
        );

        $form->submit('03');

        $this->assertEquals($data, $form->getData());
        $this->assertEquals('03', $form->getViewData());
    }

    public function testSubmitArraySingleTextWithSeconds()
    {
        $form = $this->factory->create('time', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'input' => 'array',
            'widget' => 'single_text',
            'with_seconds' => true,
        ));

        $data = array(
            'hour' => '3',
            'minute' => '4',
            'second' => '5',
        );

        $form->submit('03:04:05');

        $this->assertEquals($data, $form->getData());
        $this->assertEquals('03:04:05', $form->getViewData());
    }

    public function testSubmitStringSingleText()
    {
        $form = $this->factory->create('time', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'input' => 'string',
            'widget' => 'single_text',
        ));

        $form->submit('03:04');

        $this->assertEquals('03:04:00', $form->getData());
        $this->assertEquals('03:04', $form->getViewData());
    }

    public function testSubmitStringSingleTextWithoutMinutes()
    {
        $form = $this->factory->create('time', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'input' => 'string',
            'widget' => 'single_text',
            'with_minutes' => false,
        ));

        $form->submit('03');

        $this->assertEquals('03:00:00', $form->getData());
        $this->assertEquals('03', $form->getViewData());
    }

    public function testSetDataWithoutMinutes()
    {
        $form = $this->factory->create('time', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'input' => 'datetime',
            'with_minutes' => false,
        ));

        $form->setData(new \DateTime('03:04:05 UTC'));

        $this->assertEquals(array('hour' => 3), $form->getViewData());
    }

    public function testSetDataWithSeconds()
    {
        $form = $this->factory->create('time', null, array(
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',
            'input' => 'datetime',
            'with_seconds' => true,
        ));

        $form->setData(new \DateTime('03:04:05 UTC'));

        $this->assertEquals(array('hour' => 3, 'minute' => 4, 'second' => 5), $form->getViewData());
    }

    public function testSetDataDifferentTimezones()
    {
        $form = $this->factory->create('time', null, array(
            'model_timezone' => 'America/New_York',
            'view_timezone' => 'Asia/Hong_Kong',
            'input' => 'string',
            'with_seconds' => true,
        ));

        $dateTime = new \DateTime('2013-01-01 12:04:05');
        $dateTime->setTimezone(new \DateTimeZone('America/New_York'));

        $form->setData($dateTime->format('H:i:s'));

        $outputTime = clone $dateTime;
        $outputTime->setTimezone(new \DateTimeZone('Asia/Hong_Kong'));

        $displayedData = array(
            'hour' => (int) $outputTime->format('H'),
            'minute' => (int) $outputTime->format('i'),
            'second' => (int) $outputTime->format('s')
        );

        $this->assertEquals($displayedData, $form->getViewData());
    }

    public function testSetDataDifferentTimezonesDateTime()
    {
        $form = $this->factory->create('time', null, array(
            'model_timezone' => 'America/New_York',
            'view_timezone' => 'Asia/Hong_Kong',
            'input' => 'datetime',
            'with_seconds' => true,
        ));

        $dateTime = new \DateTime('12:04:05');
        $dateTime->setTimezone(new \DateTimeZone('America/New_York'));

        $form->setData($dateTime);

        $outputTime = clone $dateTime;
        $outputTime->setTimezone(new \DateTimeZone('Asia/Hong_Kong'));

        $displayedData = array(
            'hour' => (int) $outputTime->format('H'),
            'minute' => (int) $outputTime->format('i'),
            'second' => (int) $outputTime->format('s')
        );

        $this->assertDateTimeEquals($dateTime, $form->getData());
        $this->assertEquals($displayedData, $form->getViewData());
    }

    public function testHoursOption()
    {
        $form = $this->factory->create('time', null, array(
            'hours' => array(6, 7),
        ));

        $view = $form->createView();

        $this->assertEquals(array(
            new ChoiceView('6', '6', '06'),
            new ChoiceView('7', '7', '07'),
        ), $view['hour']->vars['choices']);
    }

    public function testIsMinuteWithinRangeReturnsTrueIfWithin()
    {
        $form = $this->factory->create('time', null, array(
            'minutes' => array(6, 7),
        ));

        $view = $form->createView();

        $this->assertEquals(array(
            new ChoiceView('6', '6', '06'),
            new ChoiceView('7', '7', '07'),
        ), $view['minute']->vars['choices']);
    }

    public function testIsSecondWithinRangeReturnsTrueIfWithin()
    {
        $form = $this->factory->create('time', null, array(
            'seconds' => array(6, 7),
            'with_seconds' => true,
        ));

        $view = $form->createView();

        $this->assertEquals(array(
            new ChoiceView('6', '6', '06'),
            new ChoiceView('7', '7', '07'),
        ), $view['second']->vars['choices']);
    }

    public function testIsPartiallyFilledReturnsFalseIfCompletelyEmpty()
    {
        $this->markTestIncomplete('Needs to be reimplemented using validators');

        $form = $this->factory->create('time', null, array(
            'widget' => 'choice',
        ));

        $form->submit(array(
            'hour' => '',
            'minute' => '',
        ));

        $this->assertFalse($form->isPartiallyFilled());
    }

    public function testIsPartiallyFilledReturnsFalseIfCompletelyEmptyWithSeconds()
    {
        $this->markTestIncomplete('Needs to be reimplemented using validators');

        $form = $this->factory->create('time', null, array(
            'widget' => 'choice',
            'with_seconds' => true,
        ));

        $form->submit(array(
            'hour' => '',
            'minute' => '',
            'second' => '',
        ));

        $this->assertFalse($form->isPartiallyFilled());
    }

    public function testIsPartiallyFilledReturnsFalseIfCompletelyFilled()
    {
        $this->markTestIncomplete('Needs to be reimplemented using validators');

        $form = $this->factory->create('time', null, array(
            'widget' => 'choice',
        ));

        $form->submit(array(
            'hour' => '0',
            'minute' => '0',
        ));

        $this->assertFalse($form->isPartiallyFilled());
    }

    public function testIsPartiallyFilledReturnsFalseIfCompletelyFilledWithSeconds()
    {
        $this->markTestIncomplete('Needs to be reimplemented using validators');

        $form = $this->factory->create('time', null, array(
            'widget' => 'choice',
            'with_seconds' => true,
        ));

        $form->submit(array(
            'hour' => '0',
            'minute' => '0',
            'second' => '0',
        ));

        $this->assertFalse($form->isPartiallyFilled());
    }

    public function testIsPartiallyFilledReturnsTrueIfChoiceAndHourEmpty()
    {
        $this->markTestIncomplete('Needs to be reimplemented using validators');

        $form = $this->factory->create('time', null, array(
            'widget' => 'choice',
            'with_seconds' => true,
        ));

        $form->submit(array(
            'hour' => '',
            'minute' => '0',
            'second' => '0',
        ));

        $this->assertTrue($form->isPartiallyFilled());
    }

    public function testIsPartiallyFilledReturnsTrueIfChoiceAndMinuteEmpty()
    {
        $this->markTestIncomplete('Needs to be reimplemented using validators');

        $form = $this->factory->create('time', null, array(
            'widget' => 'choice',
            'with_seconds' => true,
        ));

        $form->submit(array(
            'hour' => '0',
            'minute' => '',
            'second' => '0',
        ));

        $this->assertTrue($form->isPartiallyFilled());
    }

    public function testIsPartiallyFilledReturnsTrueIfChoiceAndSecondsEmpty()
    {
        $this->markTestIncomplete('Needs to be reimplemented using validators');

        $form = $this->factory->create('time', null, array(
            'widget' => 'choice',
            'with_seconds' => true,
        ));

        $form->submit(array(
            'hour' => '0',
            'minute' => '0',
            'second' => '',
        ));

        $this->assertTrue($form->isPartiallyFilled());
    }

    // Bug fix
    public function testInitializeWithDateTime()
    {
        // Throws an exception if "data_class" option is not explicitly set
        // to null in the type
        $this->factory->create('time', new \DateTime());
    }

    public function testSingleTextWidgetShouldUseTheRightInputType()
    {
        $form = $this->factory->create('time', null, array(
            'widget' => 'single_text',
        ));

        $view = $form->createView();
        $this->assertEquals('time', $view->vars['type']);
    }

    public function testPassDefaultEmptyValueToViewIfNotRequired()
    {
        $form = $this->factory->create('time', null, array(
            'required' => false,
            'with_seconds' => true,
        ));

        $view = $form->createView();
        $this->assertSame('', $view['hour']->vars['empty_value']);
        $this->assertSame('', $view['minute']->vars['empty_value']);
        $this->assertSame('', $view['second']->vars['empty_value']);
    }

    public function testPassNoEmptyValueToViewIfRequired()
    {
        $form = $this->factory->create('time', null, array(
            'required' => true,
            'with_seconds' => true,
        ));

        $view = $form->createView();
        $this->assertNull($view['hour']->vars['empty_value']);
        $this->assertNull($view['minute']->vars['empty_value']);
        $this->assertNull($view['second']->vars['empty_value']);
    }

    public function testPassEmptyValueAsString()
    {
        $form = $this->factory->create('time', null, array(
            'empty_value' => 'Empty',
            'with_seconds' => true,
        ));

        $view = $form->createView();
        $this->assertSame('Empty', $view['hour']->vars['empty_value']);
        $this->assertSame('Empty', $view['minute']->vars['empty_value']);
        $this->assertSame('Empty', $view['second']->vars['empty_value']);
    }

    public function testPassEmptyValueAsArray()
    {
        $form = $this->factory->create('time', null, array(
            'empty_value' => array(
                'hour' => 'Empty hour',
                'minute' => 'Empty minute',
                'second' => 'Empty second',
            ),
            'with_seconds' => true,
        ));

        $view = $form->createView();
        $this->assertSame('Empty hour', $view['hour']->vars['empty_value']);
        $this->assertSame('Empty minute', $view['minute']->vars['empty_value']);
        $this->assertSame('Empty second', $view['second']->vars['empty_value']);
    }

    public function testPassEmptyValueAsPartialArrayAddEmptyIfNotRequired()
    {
        $form = $this->factory->create('time', null, array(
            'required' => false,
            'empty_value' => array(
                'hour' => 'Empty hour',
                'second' => 'Empty second',
            ),
            'with_seconds' => true,
        ));

        $view = $form->createView();
        $this->assertSame('Empty hour', $view['hour']->vars['empty_value']);
        $this->assertSame('', $view['minute']->vars['empty_value']);
        $this->assertSame('Empty second', $view['second']->vars['empty_value']);
    }

    public function testPassEmptyValueAsPartialArrayAddNullIfRequired()
    {
        $form = $this->factory->create('time', null, array(
            'required' => true,
            'empty_value' => array(
                'hour' => 'Empty hour',
                'second' => 'Empty second',
            ),
            'with_seconds' => true,
        ));

        $view = $form->createView();
        $this->assertSame('Empty hour', $view['hour']->vars['empty_value']);
        $this->assertNull($view['minute']->vars['empty_value']);
        $this->assertSame('Empty second', $view['second']->vars['empty_value']);
    }

    public function provideCompoundWidgets()
    {
        return array(
            array('text'),
            array('choice'),
        );
    }

    /**
     * @dataProvider provideCompoundWidgets
     */
    public function testHourErrorsBubbleUp($widget)
    {
        $error = new FormError('Invalid!');
        $form = $this->factory->create('time', null, array(
            'widget' => $widget,
        ));
        $form['hour']->addError($error);

        $this->assertSame(array(), $form['hour']->getErrors());
        $this->assertSame(array($error), $form->getErrors());
    }

    /**
     * @dataProvider provideCompoundWidgets
     */
    public function testMinuteErrorsBubbleUp($widget)
    {
        $error = new FormError('Invalid!');
        $form = $this->factory->create('time', null, array(
            'widget' => $widget,
        ));
        $form['minute']->addError($error);

        $this->assertSame(array(), $form['minute']->getErrors());
        $this->assertSame(array($error), $form->getErrors());
    }

    /**
     * @dataProvider provideCompoundWidgets
     */
    public function testSecondErrorsBubbleUp($widget)
    {
        $error = new FormError('Invalid!');
        $form = $this->factory->create('time', null, array(
            'widget' => $widget,
            'with_seconds' => true,
        ));
        $form['second']->addError($error);

        $this->assertSame(array(), $form['second']->getErrors());
        $this->assertSame(array($error), $form->getErrors());
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\InvalidConfigurationException
     */
    public function testInitializeWithSecondsAndWithoutMinutes()
    {
        $this->factory->create('time', null, array(
            'with_minutes' => false,
            'with_seconds' => true,
        ));
    }
}
PK��Z/����Ltest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/MoneyTypeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\Type;

use Symfony\Component\Intl\Util\IntlTestHelper;

class MoneyTypeTest extends TypeTestCase
{
    protected function setUp()
    {
        // we test against different locales, so we need the full
        // implementation
        IntlTestHelper::requireFullIntl($this);

        parent::setUp();
    }

    public function testPassMoneyPatternToView()
    {
        \Locale::setDefault('de_DE');

        $form = $this->factory->create('money');
        $view = $form->createView();

        $this->assertSame('{{ widget }} €', $view->vars['money_pattern']);
    }

    public function testMoneyPatternWorksForYen()
    {
        \Locale::setDefault('en_US');

        $form = $this->factory->create('money', null, array('currency' => 'JPY'));
        $view = $form->createView();
        $this->assertTrue((Boolean) strstr($view->vars['money_pattern'], '¥'));
    }

    // https://github.com/symfony/symfony/issues/5458
    public function testPassDifferentPatternsForDifferentCurrencies()
    {
        \Locale::setDefault('de_DE');

        $form1 = $this->factory->create('money', null, array('currency' => 'GBP'));
        $form2 = $this->factory->create('money', null, array('currency' => 'EUR'));
        $view1 = $form1->createView();
        $view2 = $form2->createView();

        $this->assertSame('{{ widget }} £', $view1->vars['money_pattern']);
        $this->assertSame('{{ widget }} €', $view2->vars['money_pattern']);
    }
}
PK��Z���J��Mtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/NumberTypeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\Type;

use Symfony\Component\Intl\Util\IntlTestHelper;

class NumberTypeTest extends TypeTestCase
{
    protected function setUp()
    {
        parent::setUp();

        // we test against "de_DE", so we need the full implementation
        IntlTestHelper::requireFullIntl($this);

        \Locale::setDefault('de_DE');
    }

    public function testDefaultFormatting()
    {
        $form = $this->factory->create('number');
        $form->setData('12345.67890');
        $view = $form->createView();

        $this->assertSame('12345,679', $view->vars['value']);
    }

    public function testDefaultFormattingWithGrouping()
    {
        $form = $this->factory->create('number', null, array('grouping' => true));
        $form->setData('12345.67890');
        $view = $form->createView();

        $this->assertSame('12.345,679', $view->vars['value']);
    }

    public function testDefaultFormattingWithPrecision()
    {
        $form = $this->factory->create('number', null, array('precision' => 2));
        $form->setData('12345.67890');
        $view = $form->createView();

        $this->assertSame('12345,68', $view->vars['value']);
    }

    public function testDefaultFormattingWithRounding()
    {
        $form = $this->factory->create('number', null, array('precision' => 0, 'rounding_mode' => \NumberFormatter::ROUND_UP));
        $form->setData('12345.54321');
        $view = $form->createView();

        $this->assertSame('12346', $view->vars['value']);
    }
}
PK��Z�}�C%%Mtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/SubmitTypeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\Type;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class SubmitTypeTest extends TypeTestCase
{
    public function testCreateSubmitButtonInstances()
    {
        $this->assertInstanceOf('Symfony\Component\Form\SubmitButton', $this->factory->create('submit'));
    }

    public function testNotClickedByDefault()
    {
        $button = $this->factory->create('submit');

        $this->assertFalse($button->isClicked());
    }

    public function testNotClickedIfSubmittedWithNull()
    {
        $button = $this->factory->create('submit');
        $button->submit(null);

        $this->assertFalse($button->isClicked());
    }

    public function testClickedIfSubmittedWithEmptyString()
    {
        $button = $this->factory->create('submit');
        $button->submit('');

        $this->assertTrue($button->isClicked());
    }

    public function testClickedIfSubmittedWithUnemptyString()
    {
        $button = $this->factory->create('submit');
        $button->submit('foo');

        $this->assertTrue($button->isClicked());
    }

    public function testSubmitCanBeAddedToForm()
    {
        $form = $this->factory
            ->createBuilder('form')
            ->getForm();

        $this->assertSame($form, $form->add('send', 'submit'));
    }
}
PK��Z�!]i00Otest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/CurrencyTypeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\Type;

use Symfony\Component\Form\Extension\Core\View\ChoiceView;
use Symfony\Component\Intl\Util\IntlTestHelper;

class CurrencyTypeTest extends TypeTestCase
{
    protected function setUp()
    {
        IntlTestHelper::requireIntl($this);

        parent::setUp();
    }

    public function testCurrenciesAreSelectable()
    {
        $form = $this->factory->create('currency');
        $view = $form->createView();
        $choices = $view->vars['choices'];

        $this->assertContains(new ChoiceView('EUR', 'EUR', 'Euro'), $choices, '', false, false);
        $this->assertContains(new ChoiceView('USD', 'USD', 'US Dollar'), $choices, '', false, false);
        $this->assertContains(new ChoiceView('SIT', 'SIT', 'Slovenian Tolar'), $choices, '', false, false);
    }

}
PK��Z�IJ��Otest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/CheckboxTypeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\Type;

use Symfony\Component\Form\CallbackTransformer;

class CheckboxTypeTest extends \Symfony\Component\Form\Test\TypeTestCase
{
    public function testDataIsFalseByDefault()
    {
        $form = $this->factory->create('checkbox');

        $this->assertFalse($form->getData());
        $this->assertFalse($form->getNormData());
        $this->assertNull($form->getViewData());
    }

    public function testPassValueToView()
    {
        $form = $this->factory->create('checkbox', null, array('value' => 'foobar'));
        $view = $form->createView();

        $this->assertEquals('foobar', $view->vars['value']);
    }

    public function testCheckedIfDataTrue()
    {
        $form = $this->factory->create('checkbox');
        $form->setData(true);
        $view = $form->createView();

        $this->assertTrue($view->vars['checked']);
    }

    public function testCheckedIfDataTrueWithEmptyValue()
    {
        $form = $this->factory->create('checkbox', null, array('value' => ''));
        $form->setData(true);
        $view = $form->createView();

        $this->assertTrue($view->vars['checked']);
    }

    public function testNotCheckedIfDataFalse()
    {
        $form = $this->factory->create('checkbox');
        $form->setData(false);
        $view = $form->createView();

        $this->assertFalse($view->vars['checked']);
    }

    public function testSubmitWithValueChecked()
    {
        $form = $this->factory->create('checkbox', null, array(
            'value' => 'foobar',
        ));
        $form->submit('foobar');

        $this->assertTrue($form->getData());
        $this->assertEquals('foobar', $form->getViewData());
    }

    public function testSubmitWithRandomValueChecked()
    {
        $form = $this->factory->create('checkbox', null, array(
            'value' => 'foobar',
        ));
        $form->submit('krixikraxi');

        $this->assertTrue($form->getData());
        $this->assertEquals('foobar', $form->getViewData());
    }

    public function testSubmitWithValueUnchecked()
    {
        $form = $this->factory->create('checkbox', null, array(
            'value' => 'foobar',
        ));
        $form->submit(null);

        $this->assertFalse($form->getData());
        $this->assertNull($form->getViewData());
    }

    public function testSubmitWithEmptyValueChecked()
    {
        $form = $this->factory->create('checkbox', null, array(
            'value' => '',
        ));
        $form->submit('');

        $this->assertTrue($form->getData());
        $this->assertSame('', $form->getViewData());
    }

    public function testSubmitWithEmptyValueUnchecked()
    {
        $form = $this->factory->create('checkbox', null, array(
            'value' => '',
        ));
        $form->submit(null);

        $this->assertFalse($form->getData());
        $this->assertNull($form->getViewData());
    }

    public function testSubmitWithEmptyValueAndFalseUnchecked()
    {
        $form = $this->factory->create('checkbox', null, array(
            'value' => '',
        ));
        $form->submit(false);

        $this->assertFalse($form->getData());
        $this->assertNull($form->getViewData());
    }

    public function testSubmitWithEmptyValueAndTrueChecked()
    {
        $form = $this->factory->create('checkbox', null, array(
            'value' => '',
        ));
        $form->submit(true);

        $this->assertTrue($form->getData());
        $this->assertSame('', $form->getViewData());
    }

    /**
     * @dataProvider provideCustomModelTransformerData
     */
    public function testCustomModelTransformer($data, $checked)
    {
        // present a binary status field as a checkbox
        $transformer = new CallbackTransformer(
            function ($value) {
                return 'checked' == $value;
            },
            function ($value) {
                return $value ? 'checked' : 'unchecked';
            }
        );

        $form = $this->factory->createBuilder('checkbox')
            ->addModelTransformer($transformer)
            ->getForm();

        $form->setData($data);
        $view = $form->createView();

        $this->assertSame($data, $form->getData());
        $this->assertSame($checked, $form->getNormData());
        $this->assertEquals($checked, $view->vars['checked']);
    }

    public function provideCustomModelTransformerData()
    {
        return array(
            array('checked', true),
            array('unchecked', false),
        );
    }
}
PK��Z�ñI��Otest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/RepeatedTypeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\Type;

class RepeatedTypeTest extends \Symfony\Component\Form\Test\TypeTestCase
{
    protected $form;

    protected function setUp()
    {
        parent::setUp();

        $this->form = $this->factory->create('repeated', null, array(
            'type' => 'text',
        ));
        $this->form->setData(null);
    }

    public function testSetData()
    {
        $this->form->setData('foobar');

        $this->assertEquals('foobar', $this->form['first']->getData());
        $this->assertEquals('foobar', $this->form['second']->getData());
    }

    public function testSetOptions()
    {
        $form = $this->factory->create('repeated', null, array(
            'type'    => 'text',
            'options' => array('label' => 'Global'),
        ));

        $this->assertEquals('Global', $form['first']->getConfig()->getOption('label'));
        $this->assertEquals('Global', $form['second']->getConfig()->getOption('label'));
        $this->assertTrue($form['first']->isRequired());
        $this->assertTrue($form['second']->isRequired());
    }

    public function testSetOptionsPerChild()
    {
        $form = $this->factory->create('repeated', null, array(
            // the global required value cannot be overridden
            'type'           => 'text',
            'first_options'  => array('label' => 'Test', 'required' => false),
            'second_options' => array('label' => 'Test2')
        ));

        $this->assertEquals('Test', $form['first']->getConfig()->getOption('label'));
        $this->assertEquals('Test2', $form['second']->getConfig()->getOption('label'));
        $this->assertTrue($form['first']->isRequired());
        $this->assertTrue($form['second']->isRequired());
    }

    public function testSetRequired()
    {
        $form = $this->factory->create('repeated', null, array(
            'required' => false,
            'type'     => 'text',
        ));

        $this->assertFalse($form['first']->isRequired());
        $this->assertFalse($form['second']->isRequired());
    }

    public function testSetErrorBubblingToTrue()
    {
        $form = $this->factory->create('repeated', null, array(
            'error_bubbling' => true,
        ));

        $this->assertTrue($form->getConfig()->getOption('error_bubbling'));
        $this->assertTrue($form['first']->getConfig()->getOption('error_bubbling'));
        $this->assertTrue($form['second']->getConfig()->getOption('error_bubbling'));
    }

    public function testSetErrorBubblingToFalse()
    {
        $form = $this->factory->create('repeated', null, array(
            'error_bubbling' => false,
        ));

        $this->assertFalse($form->getConfig()->getOption('error_bubbling'));
        $this->assertFalse($form['first']->getConfig()->getOption('error_bubbling'));
        $this->assertFalse($form['second']->getConfig()->getOption('error_bubbling'));
    }

    public function testSetErrorBubblingIndividually()
    {
        $form = $this->factory->create('repeated', null, array(
            'error_bubbling' => true,
            'options' => array('error_bubbling' => false),
            'second_options' => array('error_bubbling' => true),
        ));

        $this->assertTrue($form->getConfig()->getOption('error_bubbling'));
        $this->assertFalse($form['first']->getConfig()->getOption('error_bubbling'));
        $this->assertTrue($form['second']->getConfig()->getOption('error_bubbling'));
    }

    public function testSetOptionsPerChildAndOverwrite()
    {
        $form = $this->factory->create('repeated', null, array(
            'type'           => 'text',
            'options'        => array('label' => 'Label'),
            'second_options' => array('label' => 'Second label')
        ));

        $this->assertEquals('Label', $form['first']->getConfig()->getOption('label'));
        $this->assertEquals('Second label', $form['second']->getConfig()->getOption('label'));
        $this->assertTrue($form['first']->isRequired());
        $this->assertTrue($form['second']->isRequired());
    }

    public function testSubmitUnequal()
    {
        $input = array('first' => 'foo', 'second' => 'bar');

        $this->form->submit($input);

        $this->assertEquals('foo', $this->form['first']->getViewData());
        $this->assertEquals('bar', $this->form['second']->getViewData());
        $this->assertFalse($this->form->isSynchronized());
        $this->assertEquals($input, $this->form->getViewData());
        $this->assertNull($this->form->getData());
    }

    public function testSubmitEqual()
    {
        $input = array('first' => 'foo', 'second' => 'foo');

        $this->form->submit($input);

        $this->assertEquals('foo', $this->form['first']->getViewData());
        $this->assertEquals('foo', $this->form['second']->getViewData());
        $this->assertTrue($this->form->isSynchronized());
        $this->assertEquals($input, $this->form->getViewData());
        $this->assertEquals('foo', $this->form->getData());
    }
}
PK��Zk�ƅ��Ntest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/IntegerTypeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\Type;

use Symfony\Component\Intl\Util\IntlTestHelper;

class IntegerTypeTest extends TypeTestCase
{
    protected function setUp()
    {
        IntlTestHelper::requireIntl($this);

        parent::setUp();
    }

    public function testSubmitCastsToInteger()
    {
        $form = $this->factory->create('integer');

        $form->submit('1.678');

        $this->assertSame(1, $form->getData());
        $this->assertSame('1', $form->getViewData());
    }
}
PK��ZI��E����Mtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\Type;

use Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList;
use Symfony\Component\Form\Extension\Core\View\ChoiceView;

class ChoiceTypeTest extends \Symfony\Component\Form\Test\TypeTestCase
{
    private $choices = array(
        'a' => 'Bernhard',
        'b' => 'Fabien',
        'c' => 'Kris',
        'd' => 'Jon',
        'e' => 'Roman',
    );

    private $numericChoices = array(
        0 => 'Bernhard',
        1 => 'Fabien',
        2 => 'Kris',
        3 => 'Jon',
        4 => 'Roman',
    );

    private $objectChoices;

    protected $groupedChoices = array(
        'Symfony' => array(
            'a' => 'Bernhard',
            'b' => 'Fabien',
            'c' => 'Kris',
        ),
        'Doctrine' => array(
            'd' => 'Jon',
            'e' => 'Roman',
        )
    );

    protected function setUp()
    {
        parent::setUp();

        $this->objectChoices = array(
            (object) array('id' => 1, 'name' => 'Bernhard'),
            (object) array('id' => 2, 'name' => 'Fabien'),
            (object) array('id' => 3, 'name' => 'Kris'),
            (object) array('id' => 4, 'name' => 'Jon'),
            (object) array('id' => 5, 'name' => 'Roman'),
        );
    }

    protected function tearDown()
    {
        parent::tearDown();

        $this->objectChoices = null;
    }

    /**
     * @expectedException \PHPUnit_Framework_Error
     */
    public function testChoicesOptionExpectsArray()
    {
        $this->factory->create('choice', null, array(
            'choices' => new \ArrayObject(),
        ));
    }

    /**
     * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
     */
    public function testChoiceListOptionExpectsChoiceListInterface()
    {
        $this->factory->create('choice', null, array(
            'choice_list' => array('foo' => 'foo'),
        ));
    }

    public function testChoiceListAndChoicesCanBeEmpty()
    {
        $this->factory->create('choice');
    }

    public function testExpandedChoicesOptionsTurnIntoChildren()
    {
        $form = $this->factory->create('choice', null, array(
            'expanded'  => true,
            'choices'   => $this->choices,
        ));

        $this->assertCount(count($this->choices), $form, 'Each choice should become a new field');
    }

    public function testPlaceholderPresentOnNonRequiredExpandedSingleChoice()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple'  => false,
            'expanded'  => true,
            'required'  => false,
            'choices'   => $this->choices,
        ));

        $this->assertTrue(isset($form['placeholder']));
        $this->assertCount(count($this->choices) + 1, $form, 'Each choice should become a new field');
    }

    public function testPlaceholderNotPresentIfRequired()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple'  => false,
            'expanded'  => true,
            'required'  => true,
            'choices'   => $this->choices,
        ));

        $this->assertFalse(isset($form['placeholder']));
        $this->assertCount(count($this->choices), $form, 'Each choice should become a new field');
    }

    public function testPlaceholderNotPresentIfMultiple()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple'  => true,
            'expanded'  => true,
            'required'  => false,
            'choices'   => $this->choices,
        ));

        $this->assertFalse(isset($form['placeholder']));
        $this->assertCount(count($this->choices), $form, 'Each choice should become a new field');
    }

    public function testPlaceholderNotPresentIfEmptyChoice()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple'  => false,
            'expanded'  => true,
            'required'  => false,
            'choices' => array(
                '' => 'Empty',
                1 => 'Not empty',
            ),
        ));

        $this->assertFalse(isset($form['placeholder']));
        $this->assertCount(2, $form, 'Each choice should become a new field');
    }

    public function testExpandedChoicesOptionsAreFlattened()
    {
        $form = $this->factory->create('choice', null, array(
            'expanded'  => true,
            'choices'   => $this->groupedChoices,
        ));

        $flattened = array();
        foreach ($this->groupedChoices as $choices) {
            $flattened = array_merge($flattened, array_keys($choices));
        }

        $this->assertCount($form->count(), $flattened, 'Each nested choice should become a new field, not the groups');

        foreach ($flattened as $value => $choice) {
            $this->assertTrue($form->has($value), 'Flattened choice is named after it\'s value');
        }
    }

    public function testExpandedCheckboxesAreNeverRequired()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => true,
            'expanded' => true,
            'required' => true,
            'choices' => $this->choices,
        ));

        foreach ($form as $child) {
            $this->assertFalse($child->isRequired());
        }
    }

    public function testExpandedRadiosAreRequiredIfChoiceChildIsRequired()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => false,
            'expanded' => true,
            'required' => true,
            'choices' => $this->choices,
        ));

        foreach ($form as $child) {
            $this->assertTrue($child->isRequired());
        }
    }

    public function testExpandedRadiosAreNotRequiredIfChoiceChildIsNotRequired()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => false,
            'expanded' => true,
            'required' => false,
            'choices' => $this->choices,
        ));

        foreach ($form as $child) {
            $this->assertFalse($child->isRequired());
        }
    }

    public function testSubmitSingleNonExpanded()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => false,
            'expanded' => false,
            'choices' => $this->choices,
        ));

        $form->submit('b');

        $this->assertEquals('b', $form->getData());
        $this->assertEquals('b', $form->getViewData());
    }

    public function testSubmitSingleNonExpandedInvalidChoice()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => false,
            'expanded' => false,
            'choices' => $this->choices,
        ));

        $form->submit('foobar');

        $this->assertNull($form->getData());
        $this->assertEquals('foobar', $form->getViewData());
        $this->assertFalse($form->isSynchronized());
    }

    public function testSubmitSingleNonExpandedObjectChoices()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => false,
            'expanded' => false,
            'choice_list' => new ObjectChoiceList(
                $this->objectChoices,
                // label path
                'name',
                array(),
                null,
                // value path
                'id'
            ),
        ));

        // "id" value of the second entry
        $form->submit('2');

        $this->assertEquals($this->objectChoices[1], $form->getData());
        $this->assertEquals('2', $form->getViewData());
    }

    public function testSubmitMultipleNonExpanded()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => true,
            'expanded' => false,
            'choices' => $this->choices,
        ));

        $form->submit(array('a', 'b'));

        $this->assertEquals(array('a', 'b'), $form->getData());
        $this->assertEquals(array('a', 'b'), $form->getViewData());
    }

    public function testSubmitMultipleNonExpandedInvalidScalarChoice()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => true,
            'expanded' => false,
            'choices' => $this->choices,
        ));

        $form->submit('foobar');

        $this->assertNull($form->getData());
        $this->assertEquals('foobar', $form->getViewData());
        $this->assertFalse($form->isSynchronized());
    }

    public function testSubmitMultipleNonExpandedInvalidArrayChoice()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => true,
            'expanded' => false,
            'choices' => $this->choices,
        ));

        $form->submit(array('a', 'foobar'));

        $this->assertNull($form->getData());
        $this->assertEquals(array('a', 'foobar'), $form->getViewData());
        $this->assertFalse($form->isSynchronized());
    }

    public function testSubmitMultipleNonExpandedObjectChoices()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => true,
            'expanded' => false,
            'choice_list' => new ObjectChoiceList(
                $this->objectChoices,
                // label path
                'name',
                array(),
                null,
                // value path
                'id'
            ),
        ));

        $form->submit(array('2', '3'));

        $this->assertEquals(array($this->objectChoices[1], $this->objectChoices[2]), $form->getData());
        $this->assertEquals(array('2', '3'), $form->getViewData());
    }

    public function testSubmitSingleExpandedRequired()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => false,
            'expanded' => true,
            'required' => true,
            'choices' => $this->choices,
        ));

        $form->submit('b');

        $this->assertSame('b', $form->getData());
        $this->assertSame(array(
            0 => false,
            1 => true,
            2 => false,
            3 => false,
            4 => false,
        ), $form->getViewData());
        $this->assertEmpty($form->getExtraData());
        $this->assertTrue($form->isSynchronized());

        $this->assertFalse($form[0]->getData());
        $this->assertTrue($form[1]->getData());
        $this->assertFalse($form[2]->getData());
        $this->assertFalse($form[3]->getData());
        $this->assertFalse($form[4]->getData());
        $this->assertNull($form[0]->getViewData());
        $this->assertSame('b', $form[1]->getViewData());
        $this->assertNull($form[2]->getViewData());
        $this->assertNull($form[3]->getViewData());
        $this->assertNull($form[4]->getViewData());
    }

    public function testSubmitSingleExpandedRequiredInvalidChoice()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => false,
            'expanded' => true,
            'required' => true,
            'choices' => $this->choices,
        ));

        $form->submit('foobar');

        $this->assertSame(null, $form->getData());
        $this->assertSame('foobar', $form->getViewData());
        $this->assertEmpty($form->getExtraData());
        $this->assertFalse($form->isSynchronized());

        $this->assertFalse($form[0]->getData());
        $this->assertFalse($form[1]->getData());
        $this->assertFalse($form[2]->getData());
        $this->assertFalse($form[3]->getData());
        $this->assertFalse($form[4]->getData());
        $this->assertNull($form[0]->getViewData());
        $this->assertNull($form[1]->getViewData());
        $this->assertNull($form[2]->getViewData());
        $this->assertNull($form[3]->getViewData());
        $this->assertNull($form[4]->getViewData());
    }

    public function testSubmitSingleExpandedNonRequired()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => false,
            'expanded' => true,
            'required' => false,
            'choices' => $this->choices,
        ));

        $form->submit('b');

        $this->assertSame('b', $form->getData());
        $this->assertSame(array(
            0 => false,
            1 => true,
            2 => false,
            3 => false,
            4 => false,
            'placeholder' => false,
        ), $form->getViewData());
        $this->assertEmpty($form->getExtraData());
        $this->assertTrue($form->isSynchronized());

        $this->assertFalse($form['placeholder']->getData());
        $this->assertFalse($form[0]->getData());
        $this->assertTrue($form[1]->getData());
        $this->assertFalse($form[2]->getData());
        $this->assertFalse($form[3]->getData());
        $this->assertFalse($form[4]->getData());
        $this->assertNull($form['placeholder']->getViewData());
        $this->assertNull($form[0]->getViewData());
        $this->assertSame('b', $form[1]->getViewData());
        $this->assertNull($form[2]->getViewData());
        $this->assertNull($form[3]->getViewData());
        $this->assertNull($form[4]->getViewData());
    }

    public function testSubmitSingleExpandedNonRequiredInvalidChoice()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => false,
            'expanded' => true,
            'required' => false,
            'choices' => $this->choices,
        ));

        $form->submit('foobar');

        $this->assertSame(null, $form->getData());
        $this->assertSame('foobar', $form->getViewData());
        $this->assertEmpty($form->getExtraData());
        $this->assertFalse($form->isSynchronized());

        $this->assertFalse($form[0]->getData());
        $this->assertFalse($form[1]->getData());
        $this->assertFalse($form[2]->getData());
        $this->assertFalse($form[3]->getData());
        $this->assertFalse($form[4]->getData());
        $this->assertNull($form[0]->getViewData());
        $this->assertNull($form[1]->getViewData());
        $this->assertNull($form[2]->getViewData());
        $this->assertNull($form[3]->getViewData());
        $this->assertNull($form[4]->getViewData());
    }

    public function testSubmitSingleExpandedRequiredNull()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => false,
            'expanded' => true,
            'required' => true,
            'choices' => $this->choices,
        ));

        $form->submit(null);

        $this->assertNull($form->getData());
        $this->assertSame(array(
            0 => false,
            1 => false,
            2 => false,
            3 => false,
            4 => false,
        ), $form->getViewData());
        $this->assertEmpty($form->getExtraData());
        $this->assertTrue($form->isSynchronized());

        $this->assertFalse($form[0]->getData());
        $this->assertFalse($form[1]->getData());
        $this->assertFalse($form[2]->getData());
        $this->assertFalse($form[3]->getData());
        $this->assertFalse($form[4]->getData());
        $this->assertNull($form[0]->getViewData());
        $this->assertNull($form[1]->getViewData());
        $this->assertNull($form[2]->getViewData());
        $this->assertNull($form[3]->getViewData());
        $this->assertNull($form[4]->getViewData());
    }

    public function testSubmitSingleExpandedRequiredEmpty()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => false,
            'expanded' => true,
            'required' => true,
            'choices' => $this->choices,
        ));

        $form->submit('');

        $this->assertNull($form->getData());
        $this->assertSame(array(
            0 => false,
            1 => false,
            2 => false,
            3 => false,
            4 => false,
        ), $form->getViewData());
        $this->assertEmpty($form->getExtraData());
        $this->assertTrue($form->isSynchronized());

        $this->assertFalse($form[0]->getData());
        $this->assertFalse($form[1]->getData());
        $this->assertFalse($form[2]->getData());
        $this->assertFalse($form[3]->getData());
        $this->assertFalse($form[4]->getData());
        $this->assertNull($form[0]->getViewData());
        $this->assertNull($form[1]->getViewData());
        $this->assertNull($form[2]->getViewData());
        $this->assertNull($form[3]->getViewData());
        $this->assertNull($form[4]->getViewData());
    }

    public function testSubmitSingleExpandedRequiredFalse()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => false,
            'expanded' => true,
            'required' => true,
            'choices' => $this->choices,
        ));

        $form->submit(false);

        $this->assertNull($form->getData());
        $this->assertSame(array(
            0 => false,
            1 => false,
            2 => false,
            3 => false,
            4 => false,
        ), $form->getViewData());
        $this->assertEmpty($form->getExtraData());
        $this->assertTrue($form->isSynchronized());

        $this->assertFalse($form[0]->getData());
        $this->assertFalse($form[1]->getData());
        $this->assertFalse($form[2]->getData());
        $this->assertFalse($form[3]->getData());
        $this->assertFalse($form[4]->getData());
        $this->assertNull($form[0]->getViewData());
        $this->assertNull($form[1]->getViewData());
        $this->assertNull($form[2]->getViewData());
        $this->assertNull($form[3]->getViewData());
        $this->assertNull($form[4]->getViewData());
    }

    public function testSubmitSingleExpandedNonRequiredNull()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => false,
            'expanded' => true,
            'required' => false,
            'choices' => $this->choices,
        ));

        $form->submit(null);

        $this->assertNull($form->getData());
        $this->assertSame(array(
            0 => false,
            1 => false,
            2 => false,
            3 => false,
            4 => false,
            'placeholder' => true,
        ), $form->getViewData());
        $this->assertEmpty($form->getExtraData());
        $this->assertTrue($form->isSynchronized());

        $this->assertTrue($form['placeholder']->getData());
        $this->assertFalse($form[0]->getData());
        $this->assertFalse($form[1]->getData());
        $this->assertFalse($form[2]->getData());
        $this->assertFalse($form[3]->getData());
        $this->assertFalse($form[4]->getData());
        $this->assertSame('', $form['placeholder']->getViewData());
        $this->assertNull($form[0]->getViewData());
        $this->assertNull($form[1]->getViewData());
        $this->assertNull($form[2]->getViewData());
        $this->assertNull($form[3]->getViewData());
        $this->assertNull($form[4]->getViewData());
    }

    public function testSubmitSingleExpandedNonRequiredEmpty()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => false,
            'expanded' => true,
            'required' => false,
            'choices' => $this->choices,
        ));

        $form->submit('');

        $this->assertNull($form->getData());
        $this->assertSame(array(
            0 => false,
            1 => false,
            2 => false,
            3 => false,
            4 => false,
            'placeholder' => true,
        ), $form->getViewData());
        $this->assertEmpty($form->getExtraData());
        $this->assertTrue($form->isSynchronized());

        $this->assertTrue($form['placeholder']->getData());
        $this->assertFalse($form[0]->getData());
        $this->assertFalse($form[1]->getData());
        $this->assertFalse($form[2]->getData());
        $this->assertFalse($form[3]->getData());
        $this->assertFalse($form[4]->getData());
        $this->assertSame('', $form['placeholder']->getViewData());
        $this->assertNull($form[0]->getViewData());
        $this->assertNull($form[1]->getViewData());
        $this->assertNull($form[2]->getViewData());
        $this->assertNull($form[3]->getViewData());
        $this->assertNull($form[4]->getViewData());
    }

    public function testSubmitSingleExpandedNonRequiredFalse()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => false,
            'expanded' => true,
            'required' => false,
            'choices' => $this->choices,
        ));

        $form->submit(false);

        $this->assertNull($form->getData());
        $this->assertSame(array(
            0 => false,
            1 => false,
            2 => false,
            3 => false,
            4 => false,
            'placeholder' => true,
        ), $form->getViewData());
        $this->assertEmpty($form->getExtraData());
        $this->assertTrue($form->isSynchronized());

        $this->assertTrue($form['placeholder']->getData());
        $this->assertFalse($form[0]->getData());
        $this->assertFalse($form[1]->getData());
        $this->assertFalse($form[2]->getData());
        $this->assertFalse($form[3]->getData());
        $this->assertFalse($form[4]->getData());
        $this->assertSame('', $form['placeholder']->getViewData());
        $this->assertNull($form[0]->getViewData());
        $this->assertNull($form[1]->getViewData());
        $this->assertNull($form[2]->getViewData());
        $this->assertNull($form[3]->getViewData());
        $this->assertNull($form[4]->getViewData());
    }

    public function testSubmitSingleExpandedWithEmptyChild()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => false,
            'expanded' => true,
            'choices' => array(
                '' => 'Empty',
                1 => 'Not empty',
            ),
        ));

        $form->submit('');

        $this->assertNull($form->getData());
        $this->assertTrue($form[0]->getData());
        $this->assertFalse($form[1]->getData());
        $this->assertSame('', $form[0]->getViewData());
        $this->assertNull($form[1]->getViewData());
    }

    public function testSubmitSingleExpandedObjectChoices()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => false,
            'expanded' => true,
            'choice_list' => new ObjectChoiceList(
                $this->objectChoices,
                // label path
                'name',
                array(),
                null,
                // value path
                'id'
            ),
        ));

        $form->submit('2');

        $this->assertSame($this->objectChoices[1], $form->getData());
        $this->assertFalse($form[0]->getData());
        $this->assertTrue($form[1]->getData());
        $this->assertFalse($form[2]->getData());
        $this->assertFalse($form[3]->getData());
        $this->assertFalse($form[4]->getData());
        $this->assertNull($form[0]->getViewData());
        $this->assertSame('2', $form[1]->getViewData());
        $this->assertNull($form[2]->getViewData());
        $this->assertNull($form[3]->getViewData());
        $this->assertNull($form[4]->getViewData());
    }

    public function testSubmitSingleExpandedNumericChoices()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => false,
            'expanded' => true,
            'choices' => $this->numericChoices,
        ));

        $form->submit('1');

        $this->assertSame(1, $form->getData());
        $this->assertFalse($form[0]->getData());
        $this->assertTrue($form[1]->getData());
        $this->assertFalse($form[2]->getData());
        $this->assertFalse($form[3]->getData());
        $this->assertFalse($form[4]->getData());
        $this->assertNull($form[0]->getViewData());
        $this->assertSame('1', $form[1]->getViewData());
        $this->assertNull($form[2]->getViewData());
        $this->assertNull($form[3]->getViewData());
        $this->assertNull($form[4]->getViewData());
    }

    public function testSubmitMultipleExpanded()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => true,
            'expanded' => true,
            'choices' => $this->choices,
        ));

        $form->submit(array('a', 'c'));

        $this->assertSame(array('a', 'c'), $form->getData());
        $this->assertSame(array(
            0 => true,
            1 => false,
            2 => true,
            3 => false,
            4 => false,
        ), $form->getViewData());
        $this->assertEmpty($form->getExtraData());
        $this->assertTrue($form->isSynchronized());

        $this->assertTrue($form[0]->getData());
        $this->assertFalse($form[1]->getData());
        $this->assertTrue($form[2]->getData());
        $this->assertFalse($form[3]->getData());
        $this->assertFalse($form[4]->getData());
        $this->assertSame('a', $form[0]->getViewData());
        $this->assertNull($form[1]->getViewData());
        $this->assertSame('c', $form[2]->getViewData());
        $this->assertNull($form[3]->getViewData());
        $this->assertNull($form[4]->getViewData());
    }

    public function testSubmitMultipleExpandedInvalidScalarChoice()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => true,
            'expanded' => true,
            'choices' => $this->choices,
        ));

        $form->submit('foobar');

        $this->assertNull($form->getData());
        $this->assertSame('foobar', $form->getViewData());
        $this->assertEmpty($form->getExtraData());
        $this->assertFalse($form->isSynchronized());

        $this->assertFalse($form[0]->getData());
        $this->assertFalse($form[1]->getData());
        $this->assertFalse($form[2]->getData());
        $this->assertFalse($form[3]->getData());
        $this->assertFalse($form[4]->getData());
        $this->assertNull($form[0]->getViewData());
        $this->assertNull($form[1]->getViewData());
        $this->assertNull($form[2]->getViewData());
        $this->assertNull($form[3]->getViewData());
        $this->assertNull($form[4]->getViewData());
    }

    public function testSubmitMultipleExpandedInvalidArrayChoice()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => true,
            'expanded' => true,
            'choices' => $this->choices,
        ));

        $form->submit(array('a', 'foobar'));

        $this->assertNull($form->getData());
        $this->assertSame(array('a', 'foobar'), $form->getViewData());
        $this->assertEmpty($form->getExtraData());
        $this->assertFalse($form->isSynchronized());

        $this->assertFalse($form[0]->getData());
        $this->assertFalse($form[1]->getData());
        $this->assertFalse($form[2]->getData());
        $this->assertFalse($form[3]->getData());
        $this->assertFalse($form[4]->getData());
        $this->assertNull($form[0]->getViewData());
        $this->assertNull($form[1]->getViewData());
        $this->assertNull($form[2]->getViewData());
        $this->assertNull($form[3]->getViewData());
        $this->assertNull($form[4]->getViewData());
    }

    public function testSubmitMultipleExpandedEmpty()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => true,
            'expanded' => true,
            'choices' => $this->choices,
        ));

        $form->submit(array());

        $this->assertSame(array(), $form->getData());
        $this->assertFalse($form[0]->getData());
        $this->assertFalse($form[1]->getData());
        $this->assertFalse($form[2]->getData());
        $this->assertFalse($form[3]->getData());
        $this->assertFalse($form[4]->getData());
        $this->assertNull($form[0]->getViewData());
        $this->assertNull($form[1]->getViewData());
        $this->assertNull($form[2]->getViewData());
        $this->assertNull($form[3]->getViewData());
        $this->assertNull($form[4]->getViewData());
    }

    public function testSubmitMultipleExpandedWithEmptyChild()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => true,
            'expanded' => true,
            'choices' => array(
                '' => 'Empty',
                1 => 'Not Empty',
                2 => 'Not Empty 2',
            )
        ));

        $form->submit(array('', '2'));

        $this->assertSame(array('', 2), $form->getData());
        $this->assertTrue($form[0]->getData());
        $this->assertFalse($form[1]->getData());
        $this->assertTrue($form[2]->getData());
        $this->assertSame('', $form[0]->getViewData());
        $this->assertNull($form[1]->getViewData());
        $this->assertSame('2', $form[2]->getViewData());
    }

    public function testSubmitMultipleExpandedObjectChoices()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => true,
            'expanded' => true,
            'choice_list' => new ObjectChoiceList(
                $this->objectChoices,
                // label path
                'name',
                array(),
                null,
                // value path
                'id'
            ),
        ));

        $form->submit(array('1', '2'));

        $this->assertSame(array($this->objectChoices[0], $this->objectChoices[1]), $form->getData());
        $this->assertTrue($form[0]->getData());
        $this->assertTrue($form[1]->getData());
        $this->assertFalse($form[2]->getData());
        $this->assertFalse($form[3]->getData());
        $this->assertFalse($form[4]->getData());
        $this->assertSame('1', $form[0]->getViewData());
        $this->assertSame('2', $form[1]->getViewData());
        $this->assertNull($form[2]->getViewData());
        $this->assertNull($form[3]->getViewData());
        $this->assertNull($form[4]->getViewData());
    }

    public function testSubmitMultipleExpandedNumericChoices()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => true,
            'expanded' => true,
            'choices' => $this->numericChoices,
        ));

        $form->submit(array('1', '2'));

        $this->assertSame(array(1, 2), $form->getData());
        $this->assertFalse($form[0]->getData());
        $this->assertTrue($form[1]->getData());
        $this->assertTrue($form[2]->getData());
        $this->assertFalse($form[3]->getData());
        $this->assertFalse($form[4]->getData());
        $this->assertNull($form[0]->getViewData());
        $this->assertSame('1', $form[1]->getViewData());
        $this->assertSame('2', $form[2]->getViewData());
        $this->assertNull($form[3]->getViewData());
        $this->assertNull($form[4]->getViewData());
    }

    /*
     * We need this functionality to create choice fields for Boolean types,
     * e.g. false => 'No', true => 'Yes'
     */
    public function testSetDataSingleNonExpandedAcceptsBoolean()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => false,
            'expanded' => false,
            'choices' => $this->numericChoices,
        ));

        $form->setData(false);

        $this->assertFalse($form->getData());
        $this->assertEquals('0', $form->getViewData());
    }

    public function testSetDataMultipleNonExpandedAcceptsBoolean()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => true,
            'expanded' => false,
            'choices' => $this->numericChoices,
        ));

        $form->setData(array(false, true));

        $this->assertEquals(array(false, true), $form->getData());
        $this->assertEquals(array('0', '1'), $form->getViewData());
    }

    public function testPassRequiredToView()
    {
        $form = $this->factory->create('choice', null, array(
            'choices' => $this->choices,
        ));
        $view = $form->createView();

        $this->assertTrue($view->vars['required']);
    }

    public function testPassNonRequiredToView()
    {
        $form = $this->factory->create('choice', null, array(
            'required' => false,
            'choices' => $this->choices,
        ));
        $view = $form->createView();

        $this->assertFalse($view->vars['required']);
    }

    public function testPassMultipleToView()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => true,
            'choices' => $this->choices,
        ));
        $view = $form->createView();

        $this->assertTrue($view->vars['multiple']);
    }

    public function testPassExpandedToView()
    {
        $form = $this->factory->create('choice', null, array(
            'expanded' => true,
            'choices' => $this->choices,
        ));
        $view = $form->createView();

        $this->assertTrue($view->vars['expanded']);
    }

    public function testEmptyValueIsNullByDefaultIfRequired()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => false,
            'required' => true,
            'choices' => $this->choices,
        ));
        $view = $form->createView();

        $this->assertNull($view->vars['empty_value']);
    }

    public function testEmptyValueIsEmptyStringByDefaultIfNotRequired()
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => false,
            'required' => false,
            'choices' => $this->choices,
        ));
        $view = $form->createView();

        $this->assertSame('', $view->vars['empty_value']);
    }

    /**
     * @dataProvider getOptionsWithEmptyValue
     */
    public function testPassEmptyValueToView($multiple, $expanded, $required, $emptyValue, $viewValue)
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => $multiple,
            'expanded' => $expanded,
            'required' => $required,
            'empty_value' => $emptyValue,
            'choices' => $this->choices,
        ));
        $view = $form->createView();

        $this->assertEquals($viewValue, $view->vars['empty_value']);
        $this->assertFalse($view->vars['empty_value_in_choices']);
    }

    /**
     * @dataProvider getOptionsWithEmptyValue
     */
    public function testDontPassEmptyValueIfContainedInChoices($multiple, $expanded, $required, $emptyValue, $viewValue)
    {
        $form = $this->factory->create('choice', null, array(
            'multiple' => $multiple,
            'expanded' => $expanded,
            'required' => $required,
            'empty_value' => $emptyValue,
            'choices' => array('a' => 'A', '' => 'Empty'),
        ));
        $view = $form->createView();

        $this->assertNull($view->vars['empty_value']);
        $this->assertTrue($view->vars['empty_value_in_choices']);
    }

    public function getOptionsWithEmptyValue()
    {
        return array(
            // single non-expanded
            array(false, false, false, 'foobar', 'foobar'),
            array(false, false, false, '', ''),
            array(false, false, false, null, null),
            array(false, false, false, false, null),
            array(false, false, true, 'foobar', 'foobar'),
            array(false, false, true, '', ''),
            array(false, false, true, null, null),
            array(false, false, true, false, null),
            // single expanded
            array(false, true, false, 'foobar', 'foobar'),
            // radios should never have an empty label
            array(false, true, false, '', 'None'),
            array(false, true, false, null, null),
            array(false, true, false, false, null),
            array(false, true, true, 'foobar', 'foobar'),
            // radios should never have an empty label
            array(false, true, true, '', 'None'),
            array(false, true, true, null, null),
            array(false, true, true, false, null),
            // multiple non-expanded
            array(true, false, false, 'foobar', null),
            array(true, false, false, '', null),
            array(true, false, false, null, null),
            array(true, false, false, false, null),
            array(true, false, true, 'foobar', null),
            array(true, false, true, '', null),
            array(true, false, true, null, null),
            array(true, false, true, false, null),
            // multiple expanded
            array(true, true, false, 'foobar', null),
            array(true, true, false, '', null),
            array(true, true, false, null, null),
            array(true, true, false, false, null),
            array(true, true, true, 'foobar', null),
            array(true, true, true, '', null),
            array(true, true, true, null, null),
            array(true, true, true, false, null),
        );
    }

    public function testPassChoicesToView()
    {
        $choices = array('a' => 'A', 'b' => 'B', 'c' => 'C', 'd' => 'D');
        $form = $this->factory->create('choice', null, array(
            'choices' => $choices,
        ));
        $view = $form->createView();

        $this->assertEquals(array(
            new ChoiceView('a', 'a', 'A'),
            new ChoiceView('b', 'b', 'B'),
            new ChoiceView('c', 'c', 'C'),
            new ChoiceView('d', 'd', 'D'),
        ), $view->vars['choices']);
    }

    public function testPassPreferredChoicesToView()
    {
        $choices = array('a' => 'A', 'b' => 'B', 'c' => 'C', 'd' => 'D');
        $form = $this->factory->create('choice', null, array(
            'choices' => $choices,
            'preferred_choices' => array('b', 'd'),
        ));
        $view = $form->createView();

        $this->assertEquals(array(
            0 => new ChoiceView('a', 'a', 'A'),
            2 => new ChoiceView('c', 'c', 'C'),
        ), $view->vars['choices']);
        $this->assertEquals(array(
            1 => new ChoiceView('b', 'b', 'B'),
            3 => new ChoiceView('d', 'd', 'D'),
        ), $view->vars['preferred_choices']);
    }

    public function testPassHierarchicalChoicesToView()
    {
        $form = $this->factory->create('choice', null, array(
            'choices' => $this->groupedChoices,
            'preferred_choices' => array('b', 'd'),
        ));
        $view = $form->createView();

        $this->assertEquals(array(
            'Symfony' => array(
                0 => new ChoiceView('a', 'a', 'Bernhard'),
                2 => new ChoiceView('c', 'c', 'Kris'),
            ),
            'Doctrine' => array(
                4 => new ChoiceView('e', 'e', 'Roman'),
            ),
        ), $view->vars['choices']);
        $this->assertEquals(array(
            'Symfony' => array(
                1 => new ChoiceView('b', 'b', 'Fabien'),
            ),
            'Doctrine' => array(
                3 => new ChoiceView('d', 'd', 'Jon'),
            ),
        ), $view->vars['preferred_choices']);
    }

    public function testPassChoiceDataToView()
    {
        $obj1 = (object) array('value' => 'a', 'label' => 'A');
        $obj2 = (object) array('value' => 'b', 'label' => 'B');
        $obj3 = (object) array('value' => 'c', 'label' => 'C');
        $obj4 = (object) array('value' => 'd', 'label' => 'D');
        $form = $this->factory->create('choice', null, array(
            'choice_list' => new ObjectChoiceList(array($obj1, $obj2, $obj3, $obj4), 'label', array(), null, 'value'),
        ));
        $view = $form->createView();

        $this->assertEquals(array(
            new ChoiceView($obj1, 'a', 'A'),
            new ChoiceView($obj2, 'b', 'B'),
            new ChoiceView($obj3, 'c', 'C'),
            new ChoiceView($obj4, 'd', 'D'),
        ), $view->vars['choices']);
    }

    public function testAdjustFullNameForMultipleNonExpanded()
    {
        $form = $this->factory->createNamed('name', 'choice', null, array(
            'multiple' => true,
            'expanded' => false,
            'choices' => $this->choices,
        ));
        $view = $form->createView();

        $this->assertSame('name[]', $view->vars['full_name']);
    }

    // https://github.com/symfony/symfony/issues/3298
    public function testInitializeWithEmptyChoices()
    {
        $this->factory->createNamed('name', 'choice', null, array(
            'choices' => array(),
        ));
    }

    public function testInitializeWithDefaultObjectChoice()
    {
        $obj1 = (object) array('value' => 'a', 'label' => 'A');
        $obj2 = (object) array('value' => 'b', 'label' => 'B');
        $obj3 = (object) array('value' => 'c', 'label' => 'C');
        $obj4 = (object) array('value' => 'd', 'label' => 'D');

        $form = $this->factory->create('choice', null, array(
            'choice_list' => new ObjectChoiceList(array($obj1, $obj2, $obj3, $obj4), 'label', array(), null, 'value'),
            // Used to break because "data_class" was inferred, which needs to
            // remain null in every case (because it refers to the view format)
            'data' => $obj3,
        ));

        // Trigger data initialization
        $form->getViewData();
    }
}
PK��Z�jGgJgJKtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\Type;

use Symfony\Component\PropertyAccess\PropertyPath;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\CallbackTransformer;
use Symfony\Component\Form\Tests\Fixtures\Author;
use Symfony\Component\Form\Tests\Fixtures\FixedDataTransformer;
use Symfony\Component\Form\FormError;

class FormTest_AuthorWithoutRefSetter
{
    protected $reference;

    protected $referenceCopy;

    public function __construct($reference)
    {
        $this->reference = $reference;
        $this->referenceCopy = $reference;
    }

    // The returned object should be modified by reference without having
    // to provide a setReference() method
    public function getReference()
    {
        return $this->reference;
    }

    // The returned object is a copy, so setReferenceCopy() must be used
    // to update it
    public function getReferenceCopy()
    {
        return is_object($this->referenceCopy) ? clone $this->referenceCopy : $this->referenceCopy;
    }

    public function setReferenceCopy($reference)
    {
        $this->referenceCopy = $reference;
    }
}

class FormTypeTest extends BaseTypeTest
{
    public function testCreateFormInstances()
    {
        $this->assertInstanceOf('Symfony\Component\Form\Form', $this->factory->create('form'));
    }

    public function testPassRequiredAsOption()
    {
        $form = $this->factory->create('form', null, array('required' => false));

        $this->assertFalse($form->isRequired());

        $form = $this->factory->create('form', null, array('required' => true));

        $this->assertTrue($form->isRequired());
    }

    public function testSubmittedDataIsTrimmedBeforeTransforming()
    {
        $form = $this->factory->createBuilder('form')
            ->addViewTransformer(new FixedDataTransformer(array(
                null => '',
                'reverse[a]' => 'a',
            )))
            ->setCompound(false)
            ->getForm();

        $form->submit(' a ');

        $this->assertEquals('a', $form->getViewData());
        $this->assertEquals('reverse[a]', $form->getData());
    }

    public function testSubmittedDataIsNotTrimmedBeforeTransformingIfNoTrimming()
    {
        $form = $this->factory->createBuilder('form', null, array('trim' => false))
            ->addViewTransformer(new FixedDataTransformer(array(
                null => '',
                'reverse[ a ]' => ' a ',
            )))
            ->setCompound(false)
            ->getForm();

        $form->submit(' a ');

        $this->assertEquals(' a ', $form->getViewData());
        $this->assertEquals('reverse[ a ]', $form->getData());
    }

    public function testNonReadOnlyFormWithReadOnlyParentIsReadOnly()
    {
        $view = $this->factory->createNamedBuilder('parent', 'form', null, array('read_only' => true))
            ->add('child', 'form')
            ->getForm()
            ->createView();

        $this->assertTrue($view['child']->vars['read_only']);
    }

    public function testReadOnlyFormWithNonReadOnlyParentIsReadOnly()
    {
        $view = $this->factory->createNamedBuilder('parent', 'form')
            ->add('child', 'form', array('read_only' => true))
            ->getForm()
            ->createView();

        $this->assertTrue($view['child']->vars['read_only']);
    }

    public function testNonReadOnlyFormWithNonReadOnlyParentIsNotReadOnly()
    {
        $view = $this->factory->createNamedBuilder('parent', 'form')
                ->add('child', 'form')
                ->getForm()
                ->createView();

        $this->assertFalse($view['child']->vars['read_only']);
    }

    public function testPassMaxLengthToView()
    {
        $form = $this->factory->create('form', null, array('max_length' => 10));
        $view = $form->createView();

        $this->assertSame(10, $view->vars['max_length']);
    }

    public function testSubmitWithEmptyDataCreatesObjectIfClassAvailable()
    {
        $builder = $this->factory->createBuilder('form', null, array(
            'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author',
            'required' => false,
        ));
        $builder->add('firstName', 'text');
        $builder->add('lastName', 'text');
        $form = $builder->getForm();

        $form->setData(null);
        // partially empty, still an object is created
        $form->submit(array('firstName' => 'Bernhard', 'lastName' => ''));

        $author = new Author();
        $author->firstName = 'Bernhard';
        $author->setLastName('');

        $this->assertEquals($author, $form->getData());
    }

    public function testSubmitWithEmptyDataCreatesObjectIfInitiallySubmittedWithObject()
    {
        $builder = $this->factory->createBuilder('form', null, array(
            // data class is inferred from the passed object
            'data' => new Author(),
            'required' => false,
        ));
        $builder->add('firstName', 'text');
        $builder->add('lastName', 'text');
        $form = $builder->getForm();

        $form->setData(null);
        // partially empty, still an object is created
        $form->submit(array('firstName' => 'Bernhard', 'lastName' => ''));

        $author = new Author();
        $author->firstName = 'Bernhard';
        $author->setLastName('');

        $this->assertEquals($author, $form->getData());
    }

    public function testSubmitWithEmptyDataCreatesArrayIfDataClassIsNull()
    {
        $builder = $this->factory->createBuilder('form', null, array(
            'data_class' => null,
            'required' => false,
        ));
        $builder->add('firstName', 'text');
        $form = $builder->getForm();

        $form->setData(null);
        $form->submit(array('firstName' => 'Bernhard'));

        $this->assertSame(array('firstName' => 'Bernhard'), $form->getData());
    }

    public function testSubmitEmptyWithEmptyDataCreatesNoObjectIfNotRequired()
    {
        $builder = $this->factory->createBuilder('form', null, array(
            'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author',
            'required' => false,
        ));
        $builder->add('firstName', 'text');
        $builder->add('lastName', 'text');
        $form = $builder->getForm();

        $form->setData(null);
        $form->submit(array('firstName' => '', 'lastName' => ''));

        $this->assertNull($form->getData());
    }

    public function testSubmitEmptyWithEmptyDataCreatesObjectIfRequired()
    {
        $builder = $this->factory->createBuilder('form', null, array(
            'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author',
            'required' => true,
        ));
        $builder->add('firstName', 'text');
        $builder->add('lastName', 'text');
        $form = $builder->getForm();

        $form->setData(null);
        $form->submit(array('firstName' => '', 'lastName' => ''));

        $this->assertEquals(new Author(), $form->getData());
    }

    /*
     * We need something to write the field values into
     */
    public function testSubmitWithEmptyDataStoresArrayIfNoClassAvailable()
    {
        $form = $this->factory->createBuilder('form')
            ->add('firstName', 'text')
            ->getForm();

        $form->setData(null);
        $form->submit(array('firstName' => 'Bernhard'));

        $this->assertSame(array('firstName' => 'Bernhard'), $form->getData());
    }

    public function testSubmitWithEmptyDataPassesEmptyStringToTransformerIfNotCompound()
    {
        $form = $this->factory->createBuilder('form')
            ->addViewTransformer(new FixedDataTransformer(array(
                // required for the initial, internal setData(null)
                null => 'null',
                // required to test that submit(null) is converted to ''
                'empty' => '',
            )))
            ->setCompound(false)
            ->getForm();

        $form->submit(null);

        $this->assertSame('empty', $form->getData());
    }

    public function testSubmitWithEmptyDataUsesEmptyDataOption()
    {
        $author = new Author();

        $builder = $this->factory->createBuilder('form', null, array(
            'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author',
            'empty_data' => $author,
        ));
        $builder->add('firstName', 'text');
        $form = $builder->getForm();

        $form->submit(array('firstName' => 'Bernhard'));

        $this->assertSame($author, $form->getData());
        $this->assertEquals('Bernhard', $author->firstName);
    }

    public function provideZeros()
    {
        return array(
            array(0, '0'),
            array('0', '0'),
            array('00000', '00000'),
        );
    }

    /**
     * @dataProvider provideZeros
     * @see https://github.com/symfony/symfony/issues/1986
     */
    public function testSetDataThroughParamsWithZero($data, $dataAsString)
    {
        $form = $this->factory->create('form', null, array(
            'data' => $data,
            'compound' => false,
        ));
        $view = $form->createView();

        $this->assertFalse($form->isEmpty());

        $this->assertSame($dataAsString, $view->vars['value']);
        $this->assertSame($dataAsString, $form->getData());
    }

    /**
     * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
     */
    public function testAttributesException()
    {
        $this->factory->create('form', null, array('attr' => ''));
    }

    public function testNameCanBeEmptyString()
    {
        $form = $this->factory->createNamed('', 'form');

        $this->assertEquals('', $form->getName());
    }

    public function testSubformDoesntCallSetters()
    {
        $author = new FormTest_AuthorWithoutRefSetter(new Author());

        $builder = $this->factory->createBuilder('form', $author);
        $builder->add('reference', 'form', array(
            'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author',
        ));
        $builder->get('reference')->add('firstName', 'text');
        $form = $builder->getForm();

        $form->submit(array(
            // reference has a getter, but not setter
            'reference' => array(
                'firstName' => 'Foo',
            )
        ));

        $this->assertEquals('Foo', $author->getReference()->firstName);
    }

    public function testSubformCallsSettersIfTheObjectChanged()
    {
        // no reference
        $author = new FormTest_AuthorWithoutRefSetter(null);
        $newReference = new Author();

        $builder = $this->factory->createBuilder('form', $author);
        $builder->add('referenceCopy', 'form', array(
            'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author',
        ));
        $builder->get('referenceCopy')->add('firstName', 'text');
        $form = $builder->getForm();

        $form['referenceCopy']->setData($newReference); // new author object

        $form->submit(array(
        // referenceCopy has a getter that returns a copy
            'referenceCopy' => array(
                'firstName' => 'Foo',
        )
        ));

        $this->assertEquals('Foo', $author->getReferenceCopy()->firstName);
    }

    public function testSubformCallsSettersIfByReferenceIsFalse()
    {
        $author = new FormTest_AuthorWithoutRefSetter(new Author());

        $builder = $this->factory->createBuilder('form', $author);
        $builder->add('referenceCopy', 'form', array(
            'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author',
            'by_reference' => false
        ));
        $builder->get('referenceCopy')->add('firstName', 'text');
        $form = $builder->getForm();

        $form->submit(array(
            // referenceCopy has a getter that returns a copy
            'referenceCopy' => array(
                'firstName' => 'Foo',
            )
        ));

        // firstName can only be updated if setReferenceCopy() was called
        $this->assertEquals('Foo', $author->getReferenceCopy()->firstName);
    }

    public function testSubformCallsSettersIfReferenceIsScalar()
    {
        $author = new FormTest_AuthorWithoutRefSetter('scalar');

        $builder = $this->factory->createBuilder('form', $author);
        $builder->add('referenceCopy', 'form');
        $builder->get('referenceCopy')->addViewTransformer(new CallbackTransformer(
            function () {},
            function ($value) { // reverseTransform

                return 'foobar';
            }
        ));
        $form = $builder->getForm();

        $form->submit(array(
            'referenceCopy' => array(), // doesn't matter actually
        ));

        // firstName can only be updated if setReferenceCopy() was called
        $this->assertEquals('foobar', $author->getReferenceCopy());
    }

    public function testSubformAlwaysInsertsIntoArrays()
    {
        $ref1 = new Author();
        $ref2 = new Author();
        $author = array('referenceCopy' => $ref1);

        $builder = $this->factory->createBuilder('form');
        $builder->setData($author);
        $builder->add('referenceCopy', 'form');
        $builder->get('referenceCopy')->addViewTransformer(new CallbackTransformer(
            function () {},
            function ($value) use ($ref2) { // reverseTransform

                return $ref2;
            }
        ));
        $form = $builder->getForm();

        $form->submit(array(
            'referenceCopy' => array('a' => 'b'), // doesn't matter actually
        ));

        // the new reference was inserted into the array
        $author = $form->getData();
        $this->assertSame($ref2, $author['referenceCopy']);
    }

    public function testPassMultipartTrueIfAnyChildIsMultipartToView()
    {
        $view = $this->factory->createBuilder('form')
            ->add('foo', 'text')
            ->add('bar', 'file')
            ->getForm()
            ->createView();

        $this->assertTrue($view->vars['multipart']);
    }

    public function testViewIsNotRenderedByDefault()
    {
        $view = $this->factory->createBuilder('form')
                ->add('foo', 'form')
                ->getForm()
                ->createView();

        $this->assertFalse($view->isRendered());
    }

    public function testErrorBubblingIfCompound()
    {
        $form = $this->factory->create('form', null, array(
            'compound' => true,
        ));

        $this->assertTrue($form->getConfig()->getErrorBubbling());
    }

    public function testNoErrorBubblingIfNotCompound()
    {
        $form = $this->factory->create('form', null, array(
            'compound' => false,
        ));

        $this->assertFalse($form->getConfig()->getErrorBubbling());
    }

    public function testOverrideErrorBubbling()
    {
        $form = $this->factory->create('form', null, array(
            'compound' => false,
            'error_bubbling' => true,
        ));

        $this->assertTrue($form->getConfig()->getErrorBubbling());
    }

    public function testPropertyPath()
    {
        $form = $this->factory->create('form', null, array(
            'property_path' => 'foo',
        ));

        $this->assertEquals(new PropertyPath('foo'), $form->getPropertyPath());
        $this->assertTrue($form->getConfig()->getMapped());
    }

    public function testPropertyPathNullImpliesDefault()
    {
        $form = $this->factory->createNamed('name', 'form', null, array(
            'property_path' => null,
        ));

        $this->assertEquals(new PropertyPath('name'), $form->getPropertyPath());
        $this->assertTrue($form->getConfig()->getMapped());
    }

    public function testNotMapped()
    {
        $form = $this->factory->create('form', null, array(
            'property_path' => 'foo',
            'mapped' => false,
        ));

        $this->assertEquals(new PropertyPath('foo'), $form->getPropertyPath());
        $this->assertFalse($form->getConfig()->getMapped());
    }

    public function testViewValidNotSubmitted()
    {
        $form = $this->factory->create('form');
        $view = $form->createView();
        $this->assertTrue($view->vars['valid']);
    }

    public function testViewNotValidSubmitted()
    {
        $form = $this->factory->create('form');
        $form->submit(array());
        $form->addError(new FormError('An error'));
        $view = $form->createView();
        $this->assertFalse($view->vars['valid']);
    }

    public function testViewSubmittedNotSubmitted()
    {
        $form = $this->factory->create('form');
        $view = $form->createView();
        $this->assertFalse($view->vars['submitted']);
    }

    public function testViewSubmittedSubmitted()
    {
        $form = $this->factory->create('form');
        $form->submit(array());
        $view = $form->createView();
        $this->assertTrue($view->vars['submitted']);
    }

    public function testDataOptionSupersedesSetDataCalls()
    {
        $form = $this->factory->create('form', null, array(
            'data' => 'default',
            'compound' => false,
        ));

        $form->setData('foobar');

        $this->assertSame('default', $form->getData());
    }

    public function testDataOptionSupersedesSetDataCallsIfNull()
    {
        $form = $this->factory->create('form', null, array(
            'data' => null,
            'compound' => false,
        ));

        $form->setData('foobar');

        $this->assertNull($form->getData());
    }

    public function testNormDataIsPassedToView()
    {
        $view = $this->factory->createBuilder('form')
            ->addViewTransformer(new FixedDataTransformer(array(
                'foo' => 'bar',
            )))
            ->setData('foo')
            ->getForm()
            ->createView();

        $this->assertSame('foo', $view->vars['data']);
        $this->assertSame('bar', $view->vars['value']);
    }

    // https://github.com/symfony/symfony/issues/6862
    public function testPassZeroLabelToView()
    {
        $view = $this->factory->create('form', null, array(
                'label' => '0'
            ))
            ->createView();

        $this->assertSame('0', $view->vars['label']);
    }

    public function testCanGetErrorsWhenButtonInForm()
    {
        $builder = $this->factory->createBuilder('form', null, array(
            'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author',
            'required' => false,
        ));
        $builder->add('foo', 'text');
        $builder->add('submit', 'submit');
        $form = $builder->getForm();

        //This method should not throw a Fatal Error Exception.
        $form->getErrorsAsString();
    }

    protected function getTestedType()
    {
        return 'form';
    }
}
PK��Z&����Ktest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\Core\Type;

class FileTypeTest extends \Symfony\Component\Form\Test\TypeTestCase
{
    // https://github.com/symfony/symfony/pull/5028
    public function testSetData()
    {
        $form = $this->factory->createBuilder('file')->getForm();
        $data = $this->createUploadedFileMock('abcdef', 'original.jpg', true);

        $form->setData($data);

        $this->assertSame($data, $form->getData());
    }

    public function testSubmit()
    {
        $form = $this->factory->createBuilder('file')->getForm();
        $data = $this->createUploadedFileMock('abcdef', 'original.jpg', true);

        $form->submit($data);

        $this->assertSame($data, $form->getData());
    }

    // https://github.com/symfony/symfony/issues/6134
    public function testSubmitEmpty()
    {
        $form = $this->factory->createBuilder('file')->getForm();

        $form->submit(null);

        $this->assertNull($form->getData());
    }

    public function testDontPassValueToView()
    {
        $form = $this->factory->create('file');
        $form->submit(array(
            'file' => $this->createUploadedFileMock('abcdef', 'original.jpg', true),
        ));
        $view = $form->createView();

        $this->assertEquals('', $view->vars['value']);
    }

    private function createUploadedFileMock($name, $originalName, $valid)
    {
        $file = $this
            ->getMockBuilder('Symfony\Component\HttpFoundation\File\UploadedFile')
            ->disableOriginalConstructor()
            ->getMock()
        ;
        $file
            ->expects($this->any())
            ->method('getBasename')
            ->will($this->returnValue($name))
        ;
        $file
            ->expects($this->any())
            ->method('getClientOriginalName')
            ->will($this->returnValue($originalName))
        ;
        $file
            ->expects($this->any())
            ->method('isValid')
            ->will($this->returnValue($valid))
        ;

        return $file;
    }
}
PK��Z����>�>Xtest/Form/Symfony/Component/Form/Tests/Extension/DataCollector/FormDataCollectorTest.phpnu�[���<?php
/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\DataCollector;

use Symfony\Component\Form\Extension\DataCollector\FormDataCollector;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\FormView;

class FormDataCollectorTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $dataExtractor;

    /**
     * @var FormDataCollector
     */
    private $dataCollector;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $dispatcher;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $factory;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $dataMapper;

    /**
     * @var Form
     */
    private $form;

    /**
     * @var Form
     */
    private $childForm;

    /**
     * @var FormView
     */
    private $view;

    /**
     * @var FormView
     */
    private $childView;

    protected function setUp()
    {
        $this->dataExtractor = $this->getMock('Symfony\Component\Form\Extension\DataCollector\FormDataExtractorInterface');
        $this->dataCollector = new FormDataCollector($this->dataExtractor);
        $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
        $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface');
        $this->dataMapper = $this->getMock('Symfony\Component\Form\DataMapperInterface');
        $this->form = $this->createForm('name');
        $this->childForm = $this->createForm('child');
        $this->view = new FormView();
        $this->childView = new FormView();
    }

    public function testBuildPreliminaryFormTree()
    {
        $this->form->add($this->childForm);

        $this->dataExtractor->expects($this->at(0))
            ->method('extractConfiguration')
            ->with($this->form)
            ->will($this->returnValue(array('config' => 'foo')));
        $this->dataExtractor->expects($this->at(1))
            ->method('extractConfiguration')
            ->with($this->childForm)
            ->will($this->returnValue(array('config' => 'bar')));

        $this->dataExtractor->expects($this->at(2))
            ->method('extractDefaultData')
            ->with($this->form)
            ->will($this->returnValue(array('default_data' => 'foo')));
        $this->dataExtractor->expects($this->at(3))
            ->method('extractDefaultData')
            ->with($this->childForm)
            ->will($this->returnValue(array('default_data' => 'bar')));

        $this->dataExtractor->expects($this->at(4))
            ->method('extractSubmittedData')
            ->with($this->form)
            ->will($this->returnValue(array('submitted_data' => 'foo')));
        $this->dataExtractor->expects($this->at(5))
            ->method('extractSubmittedData')
            ->with($this->childForm)
            ->will($this->returnValue(array('submitted_data' => 'bar')));

        $this->dataCollector->collectConfiguration($this->form);
        $this->dataCollector->collectDefaultData($this->form);
        $this->dataCollector->collectSubmittedData($this->form);
        $this->dataCollector->buildPreliminaryFormTree($this->form);

        $this->assertSame(array(
             'forms' => array(
                 'name' => array(
                     'config' => 'foo',
                     'default_data' => 'foo',
                     'submitted_data' => 'foo',
                     'children' => array(
                         'child' => array(
                             'config' => 'bar',
                             'default_data' => 'bar',
                             'submitted_data' => 'bar',
                             'children' => array(),
                         ),
                     ),
                 ),
             ),
             'nb_errors' => 0,
         ), $this->dataCollector->getData());
    }

    public function testBuildMultiplePreliminaryFormTrees()
    {
        $form1 = $this->createForm('form1');
        $form2 = $this->createForm('form2');

        $this->dataExtractor->expects($this->at(0))
            ->method('extractConfiguration')
            ->with($form1)
            ->will($this->returnValue(array('config' => 'foo')));
        $this->dataExtractor->expects($this->at(1))
            ->method('extractConfiguration')
            ->with($form2)
            ->will($this->returnValue(array('config' => 'bar')));

        $this->dataCollector->collectConfiguration($form1);
        $this->dataCollector->collectConfiguration($form2);
        $this->dataCollector->buildPreliminaryFormTree($form1);

        $this->assertSame(array(
            'forms' => array(
                'form1' => array(
                    'config' => 'foo',
                    'children' => array(),
                ),
            ),
            'nb_errors' => 0,
        ), $this->dataCollector->getData());

        $this->dataCollector->buildPreliminaryFormTree($form2);

        $this->assertSame(array(
            'forms' => array(
                'form1' => array(
                    'config' => 'foo',
                    'children' => array(),
                ),
                'form2' => array(
                    'config' => 'bar',
                    'children' => array(),
                ),
            ),
            'nb_errors' => 0,
        ), $this->dataCollector->getData());
    }

    public function testBuildSamePreliminaryFormTreeMultipleTimes()
    {
        $this->dataExtractor->expects($this->at(0))
            ->method('extractConfiguration')
            ->with($this->form)
            ->will($this->returnValue(array('config' => 'foo')));

        $this->dataExtractor->expects($this->at(1))
            ->method('extractDefaultData')
            ->with($this->form)
            ->will($this->returnValue(array('default_data' => 'foo')));

        $this->dataCollector->collectConfiguration($this->form);
        $this->dataCollector->buildPreliminaryFormTree($this->form);

        $this->assertSame(array(
            'forms' => array(
                'name' => array(
                    'config' => 'foo',
                    'children' => array(),
                ),
            ),
            'nb_errors' => 0,
        ), $this->dataCollector->getData());

        $this->dataCollector->collectDefaultData($this->form);
        $this->dataCollector->buildPreliminaryFormTree($this->form);

        $this->assertSame(array(
            'forms' => array(
                'name' => array(
                    'config' => 'foo',
                    'default_data' => 'foo',
                    'children' => array(),
                ),
            ),
            'nb_errors' => 0,
        ), $this->dataCollector->getData());
    }

    public function testBuildPreliminaryFormTreeWithoutCollectingAnyData()
    {
        $this->dataCollector->buildPreliminaryFormTree($this->form);

        $this->assertSame(array(
            'forms' => array(
                'name' => array(
                    'children' => array(),
                ),
            ),
            'nb_errors' => 0,
        ), $this->dataCollector->getData());
    }

    public function testBuildFinalFormTree()
    {
        $this->form->add($this->childForm);
        $this->view->children['child'] = $this->childView;

        $this->dataExtractor->expects($this->at(0))
            ->method('extractConfiguration')
            ->with($this->form)
            ->will($this->returnValue(array('config' => 'foo')));
        $this->dataExtractor->expects($this->at(1))
            ->method('extractConfiguration')
            ->with($this->childForm)
            ->will($this->returnValue(array('config' => 'bar')));

        $this->dataExtractor->expects($this->at(2))
            ->method('extractDefaultData')
            ->with($this->form)
            ->will($this->returnValue(array('default_data' => 'foo')));
        $this->dataExtractor->expects($this->at(3))
            ->method('extractDefaultData')
            ->with($this->childForm)
            ->will($this->returnValue(array('default_data' => 'bar')));

        $this->dataExtractor->expects($this->at(4))
            ->method('extractSubmittedData')
            ->with($this->form)
            ->will($this->returnValue(array('submitted_data' => 'foo')));
        $this->dataExtractor->expects($this->at(5))
            ->method('extractSubmittedData')
            ->with($this->childForm)
            ->will($this->returnValue(array('submitted_data' => 'bar')));

        $this->dataExtractor->expects($this->at(6))
            ->method('extractViewVariables')
            ->with($this->view)
            ->will($this->returnValue(array('view_vars' => 'foo')));

        $this->dataExtractor->expects($this->at(7))
            ->method('extractViewVariables')
            ->with($this->childView)
            ->will($this->returnValue(array('view_vars' => 'bar')));

        $this->dataCollector->collectConfiguration($this->form);
        $this->dataCollector->collectDefaultData($this->form);
        $this->dataCollector->collectSubmittedData($this->form);
        $this->dataCollector->collectViewVariables($this->view);
        $this->dataCollector->buildFinalFormTree($this->form, $this->view);

        $this->assertSame(array(
            'forms' => array(
                'name' => array(
                    'view_vars' => 'foo',
                    'config' => 'foo',
                    'default_data' => 'foo',
                    'submitted_data' => 'foo',
                    'children' => array(
                        'child' => array(
                            'view_vars' => 'bar',
                            'config' => 'bar',
                            'default_data' => 'bar',
                            'submitted_data' => 'bar',
                            'children' => array(),
                        ),
                    ),
                ),
            ),
            'nb_errors' => 0,
        ), $this->dataCollector->getData());
    }

    public function testFinalFormReliesOnFormViewStructure()
    {
        $this->form->add($this->createForm('first'));
        $this->form->add($this->createForm('second'));

        $this->view->children['second'] = $this->childView;

        $this->dataCollector->buildPreliminaryFormTree($this->form);

        $this->assertSame(array(
            'forms' => array(
                'name' => array(
                    'children' => array(
                        'first' => array(
                            'children' => array(),
                        ),
                        'second' => array(
                            'children' => array(),
                        ),
                    ),
                ),
            ),
            'nb_errors' => 0,
        ), $this->dataCollector->getData());

        $this->dataCollector->buildFinalFormTree($this->form, $this->view);

        $this->assertSame(array(
            'forms' => array(
                'name' => array(
                    'children' => array(
                        // "first" not present in FormView
                        'second' => array(
                            'children' => array(),
                        ),
                    ),
                ),
            ),
            'nb_errors' => 0,
        ), $this->dataCollector->getData());
    }

    public function testChildViewsCanBeWithoutCorrespondingChildForms()
    {
        // don't add $this->childForm to $this->form!

        $this->view->children['child'] = $this->childView;

        $this->dataExtractor->expects($this->at(0))
            ->method('extractConfiguration')
            ->with($this->form)
            ->will($this->returnValue(array('config' => 'foo')));
        $this->dataExtractor->expects($this->at(1))
            ->method('extractConfiguration')
            ->with($this->childForm)
            ->will($this->returnValue(array('config' => 'bar')));

        // explicitly call collectConfiguration(), since $this->childForm is not
        // contained in the form tree
        $this->dataCollector->collectConfiguration($this->form);
        $this->dataCollector->collectConfiguration($this->childForm);
        $this->dataCollector->buildFinalFormTree($this->form, $this->view);

        $this->assertSame(array(
            'forms' => array(
                'name' => array(
                    'config' => 'foo',
                    'children' => array(
                        'child' => array(
                            // no "config" key
                            'children' => array(),
                        ),
                    ),
                ),
            ),
            'nb_errors' => 0,
        ), $this->dataCollector->getData());
    }

    public function testChildViewsWithoutCorrespondingChildFormsMayBeExplicitlyAssociated()
    {
        // don't add $this->childForm to $this->form!

        $this->view->children['child'] = $this->childView;

        // but associate the two
        $this->dataCollector->associateFormWithView($this->childForm, $this->childView);

        $this->dataExtractor->expects($this->at(0))
            ->method('extractConfiguration')
            ->with($this->form)
            ->will($this->returnValue(array('config' => 'foo')));
        $this->dataExtractor->expects($this->at(1))
            ->method('extractConfiguration')
            ->with($this->childForm)
            ->will($this->returnValue(array('config' => 'bar')));

        // explicitly call collectConfiguration(), since $this->childForm is not
        // contained in the form tree
        $this->dataCollector->collectConfiguration($this->form);
        $this->dataCollector->collectConfiguration($this->childForm);
        $this->dataCollector->buildFinalFormTree($this->form, $this->view);

        $this->assertSame(array(
            'forms' => array(
                'name' => array(
                    'config' => 'foo',
                    'children' => array(
                        'child' => array(
                            'config' => 'bar',
                            'children' => array(),
                        ),
                    ),
                ),
            ),
            'nb_errors' => 0,
        ), $this->dataCollector->getData());
    }

    public function testCollectSubmittedDataCountsErrors()
    {
        $form1 = $this->createForm('form1');
        $childForm1 = $this->createForm('child1');
        $form2 = $this->createForm('form2');

        $form1->add($childForm1);

        $this->dataExtractor->expects($this->at(0))
            ->method('extractSubmittedData')
            ->with($form1)
            ->will($this->returnValue(array('errors' => array('foo'))));
        $this->dataExtractor->expects($this->at(1))
            ->method('extractSubmittedData')
            ->with($childForm1)
            ->will($this->returnValue(array('errors' => array('bar', 'bam'))));
        $this->dataExtractor->expects($this->at(2))
            ->method('extractSubmittedData')
            ->with($form2)
            ->will($this->returnValue(array('errors' => array('baz'))));

        $this->dataCollector->collectSubmittedData($form1);

        $data = $this->dataCollector->getData();
        $this->assertSame(3, $data['nb_errors']);

        $this->dataCollector->collectSubmittedData($form2);

        $data = $this->dataCollector->getData();
        $this->assertSame(4, $data['nb_errors']);

    }

    private function createForm($name)
    {
        $builder = new FormBuilder($name, null, $this->dispatcher, $this->factory);
        $builder->setCompound(true);
        $builder->setDataMapper($this->dataMapper);

        return $builder->getForm();
    }
}
PK��Zb�,�<<]test/Form/Symfony/Component/Form/Tests/Extension/DataCollector/DataCollectorExtensionTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\DataCollector;

use Symfony\Component\Form\Extension\DataCollector\DataCollectorExtension;

/**
 * @covers Symfony\Component\Form\Extension\DataCollector\DataCollectorExtension
 */
class DataCollectorExtensionTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var DataCollectorExtension
     */
    private $extension;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $dataCollector;

    public function setUp()
    {
        $this->dataCollector = $this->getMock('Symfony\Component\Form\Extension\DataCollector\FormDataCollectorInterface');
        $this->extension = new DataCollectorExtension($this->dataCollector);
    }

    public function testLoadTypeExtensions()
    {
        $typeExtensions = $this->extension->getTypeExtensions('form');

        $this->assertInternalType('array', $typeExtensions);
        $this->assertCount(1, $typeExtensions);
        $this->assertInstanceOf('Symfony\Component\Form\Extension\DataCollector\Type\DataCollectorTypeExtension', array_shift($typeExtensions));
    }
}
PK��Z�{�(�,�,Xtest/Form/Symfony/Component/Form/Tests/Extension/DataCollector/FormDataExtractorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\DataCollector;

use Symfony\Component\Form\CallbackTransformer;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Symfony\Component\Form\Extension\DataCollector\FormDataExtractor;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\Tests\Fixtures\FixedDataTransformer;
use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter;

class FormDataExtractorTest_SimpleValueExporter extends ValueExporter
{
    /**
     * {@inheritdoc}
     */
    public function exportValue($value)
    {
        return var_export($value, true);
    }
}

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class FormDataExtractorTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var FormDataExtractorTest_SimpleValueExporter
     */
    private $valueExporter;

    /**
     * @var FormDataExtractor
     */
    private $dataExtractor;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $dispatcher;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $factory;

    protected function setUp()
    {
        $this->valueExporter = new FormDataExtractorTest_SimpleValueExporter();
        $this->dataExtractor = new FormDataExtractor($this->valueExporter);
        $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
        $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface');
    }

    public function testExtractConfiguration()
    {
        $type = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface');
        $type->expects($this->any())
            ->method('getName')
            ->will($this->returnValue('type_name'));
        $type->expects($this->any())
            ->method('getInnerType')
            ->will($this->returnValue(new \stdClass()));

        $form = $this->createBuilder('name')
            ->setType($type)
            ->getForm();

        $this->assertSame(array(
            'id' => 'name',
            'type' => 'type_name',
            'type_class' => 'stdClass',
            'synchronized' => 'true',
            'passed_options' => array(),
            'resolved_options' => array(),
        ), $this->dataExtractor->extractConfiguration($form));
    }

    public function testExtractConfigurationSortsPassedOptions()
    {
        $type = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface');
        $type->expects($this->any())
            ->method('getName')
            ->will($this->returnValue('type_name'));
        $type->expects($this->any())
            ->method('getInnerType')
            ->will($this->returnValue(new \stdClass()));

        $options = array(
            'b' => 'foo',
            'a' => 'bar',
            'c' => 'baz',
        );

        $form = $this->createBuilder('name')
            ->setType($type)
            // passed options are stored in an attribute by
            // ResolvedTypeDataCollectorProxy
            ->setAttribute('data_collector/passed_options', $options)
            ->getForm();

        $this->assertSame(array(
            'id' => 'name',
            'type' => 'type_name',
            'type_class' => 'stdClass',
            'synchronized' => 'true',
            'passed_options' => array(
                'a' => "'bar'",
                'b' => "'foo'",
                'c' => "'baz'",
            ),
            'resolved_options' => array(),
        ), $this->dataExtractor->extractConfiguration($form));
    }

    public function testExtractConfigurationSortsResolvedOptions()
    {
        $type = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface');
        $type->expects($this->any())
            ->method('getName')
            ->will($this->returnValue('type_name'));
        $type->expects($this->any())
            ->method('getInnerType')
            ->will($this->returnValue(new \stdClass()));

        $options = array(
            'b' => 'foo',
            'a' => 'bar',
            'c' => 'baz',
        );

        $form = $this->createBuilder('name', $options)
            ->setType($type)
            ->getForm();

        $this->assertSame(array(
            'id' => 'name',
            'type' => 'type_name',
            'type_class' => 'stdClass',
            'synchronized' => 'true',
            'passed_options' => array(),
            'resolved_options' => array(
                'a' => "'bar'",
                'b' => "'foo'",
                'c' => "'baz'",
            ),
        ), $this->dataExtractor->extractConfiguration($form));
    }

    public function testExtractConfigurationBuildsIdRecursively()
    {
        $type = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface');
        $type->expects($this->any())
            ->method('getName')
            ->will($this->returnValue('type_name'));
        $type->expects($this->any())
            ->method('getInnerType')
            ->will($this->returnValue(new \stdClass()));

        $grandParent = $this->createBuilder('grandParent')
            ->setCompound(true)
            ->setDataMapper($this->getMock('Symfony\Component\Form\DataMapperInterface'))
            ->getForm();
        $parent = $this->createBuilder('parent')
            ->setCompound(true)
            ->setDataMapper($this->getMock('Symfony\Component\Form\DataMapperInterface'))
            ->getForm();
        $form = $this->createBuilder('name')
            ->setType($type)
            ->getForm();

        $grandParent->add($parent);
        $parent->add($form);

        $this->assertSame(array(
            'id' => 'grandParent_parent_name',
            'type' => 'type_name',
            'type_class' => 'stdClass',
            'synchronized' => 'true',
            'passed_options' => array(),
            'resolved_options' => array(),
        ), $this->dataExtractor->extractConfiguration($form));
    }

    public function testExtractDefaultData()
    {
        $form = $this->createBuilder('name')->getForm();

        $form->setData('Foobar');

        $this->assertSame(array(
            'default_data' => array(
                'norm' => "'Foobar'",
            ),
            'submitted_data' => array(),
        ), $this->dataExtractor->extractDefaultData($form));
    }

    public function testExtractDefaultDataStoresModelDataIfDifferent()
    {
        $form = $this->createBuilder('name')
            ->addModelTransformer(new FixedDataTransformer(array(
                'Foo' => 'Bar'
            )))
            ->getForm();

        $form->setData('Foo');

        $this->assertSame(array(
            'default_data' => array(
                'norm' => "'Bar'",
                'model' => "'Foo'",
            ),
            'submitted_data' => array(),
        ), $this->dataExtractor->extractDefaultData($form));
    }

    public function testExtractDefaultDataStoresViewDataIfDifferent()
    {
        $form = $this->createBuilder('name')
            ->addViewTransformer(new FixedDataTransformer(array(
                'Foo' => 'Bar'
            )))
            ->getForm();

        $form->setData('Foo');

        $this->assertSame(array(
            'default_data' => array(
                'norm' => "'Foo'",
                'view' => "'Bar'",
            ),
            'submitted_data' => array(),
        ), $this->dataExtractor->extractDefaultData($form));
    }

    public function testExtractSubmittedData()
    {
        $form = $this->createBuilder('name')->getForm();

        $form->submit('Foobar');

        $this->assertSame(array(
            'submitted_data' => array(
                'norm' => "'Foobar'",
            ),
            'errors' => array(),
            'synchronized' => 'true',
        ), $this->dataExtractor->extractSubmittedData($form));
    }

    public function testExtractSubmittedDataStoresModelDataIfDifferent()
    {
        $form = $this->createBuilder('name')
            ->addModelTransformer(new FixedDataTransformer(array(
                'Foo' => 'Bar',
                '' => '',
            )))
            ->getForm();

        $form->submit('Bar');

        $this->assertSame(array(
            'submitted_data' => array(
                'norm' => "'Bar'",
                'model' => "'Foo'",
            ),
            'errors' => array(),
            'synchronized' => 'true',
        ), $this->dataExtractor->extractSubmittedData($form));
    }

    public function testExtractSubmittedDataStoresViewDataIfDifferent()
    {
        $form = $this->createBuilder('name')
            ->addViewTransformer(new FixedDataTransformer(array(
                'Foo' => 'Bar',
                '' => '',
            )))
            ->getForm();

        $form->submit('Bar');

        $this->assertSame(array(
            'submitted_data' => array(
                'norm' => "'Foo'",
                'view' => "'Bar'",
            ),
            'errors' => array(),
            'synchronized' => 'true',
        ), $this->dataExtractor->extractSubmittedData($form));
    }

    public function testExtractSubmittedDataStoresErrors()
    {
        $form = $this->createBuilder('name')->getForm();

        $form->submit('Foobar');
        $form->addError(new FormError('Invalid!'));

        $this->assertSame(array(
            'submitted_data' => array(
                'norm' => "'Foobar'",
            ),
            'errors' => array(
                array('message' => 'Invalid!'),
            ),
            'synchronized' => 'true',
        ), $this->dataExtractor->extractSubmittedData($form));
    }

    public function testExtractSubmittedDataRemembersIfNonSynchronized()
    {
        $form = $this->createBuilder('name')
            ->addModelTransformer(new CallbackTransformer(
                function () {},
                function () {
                    throw new TransformationFailedException('Fail!');
                }
            ))
            ->getForm();

        $form->submit('Foobar');

        $this->assertSame(array(
            'submitted_data' => array(
                'norm' => "'Foobar'",
                'model' => 'NULL',
            ),
            'errors' => array(),
            'synchronized' => 'false',
        ), $this->dataExtractor->extractSubmittedData($form));
    }

    public function testExtractViewVariables()
    {
        $view = new FormView();

        $view->vars = array(
            'b' => 'foo',
            'a' => 'bar',
            'c' => 'baz',
            'id' => 'foo_bar',
        );

        $this->assertSame(array(
            'id' => 'foo_bar',
            'view_vars' => array(
                'a' => "'bar'",
                'b' => "'foo'",
                'c' => "'baz'",
                'id' => "'foo_bar'",
            ),
        ), $this->dataExtractor->extractViewVariables($view));
    }

    /**
     * @param string $name
     * @param array  $options
     *
     * @return FormBuilder
     */
    private function createBuilder($name, array $options = array())
    {
        return new FormBuilder($name, null, $this->dispatcher, $this->factory, $options);
    }
}
PK��Z��q��ftest/Form/Symfony/Component/Form/Tests/Extension/DataCollector/Type/DataCollectorTypeExtensionTest.phpnu�[���<?php
/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests\Extension\DataCollector\Type;

use Symfony\Component\Form\Extension\DataCollector\Type\DataCollectorTypeExtension;

class DataCollectorTypeExtensionTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var DataCollectorTypeExtension
     */
    private $extension;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $dataCollector;

    public function setUp()
    {
        $this->dataCollector = $this->getMock('Symfony\Component\Form\Extension\DataCollector\FormDataCollectorInterface');
        $this->extension = new DataCollectorTypeExtension($this->dataCollector);
    }

    public function testGetExtendedType()
    {
        $this->assertEquals('form', $this->extension->getExtendedType());
    }

    public function testBuildForm()
    {
        $builder = $this->getMock('Symfony\Component\Form\Test\FormBuilderInterface');
        $builder->expects($this->atLeastOnce())
            ->method('addEventSubscriber')
            ->with($this->isInstanceOf('Symfony\Component\Form\Extension\DataCollector\EventListener\DataCollectorListener'));

        $this->extension->buildForm($builder, array());
    }
}
PK��Z�'�@test/Form/Symfony/Component/Form/Tests/AbstractExtensionTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Form\Tests;

use Symfony\Component\Form\AbstractExtension;
use Symfony\Component\Form\Tests\Fixtures\FooType;

class AbstractExtensionTest extends \PHPUnit_Framework_TestCase
{
    public function testHasType()
    {
        $loader = new ConcreteExtension();
        $this->assertTrue($loader->hasType('foo'));
        $this->assertFalse($loader->hasType('bar'));
    }

    public function testGetType()
    {
        $loader = new ConcreteExtension();
        $this->assertInstanceOf('Symfony\Component\Form\Tests\Fixtures\FooType', $loader->getType('foo'));
    }
}

class ConcreteExtension extends AbstractExtension
{
    protected function loadTypes()
    {
        return array(new FooType());
    }

    protected function loadTypeGuesser()
    {
    }
}
PK��Z�g	�331test/Form/Symfony/Component/Form/phpunit.xml.distnu�[���<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony Form Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./Tests</directory>
                <directory>./vendor</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
PK��Z�ԍZP5P5Itest/Security/Symfony/Component/Security/Acl/Tests/Voter/AclVoterTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Tests\Voter;

use Symfony\Component\Security\Acl\Exception\NoAceFoundException;
use Symfony\Component\Security\Acl\Voter\FieldVote;
use Symfony\Component\Security\Acl\Exception\AclNotFoundException;
use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity;
use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity;
use Symfony\Component\Security\Acl\Domain\ObjectIdentity;
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
use Symfony\Component\Security\Acl\Voter\AclVoter;

class AclVoterTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getSupportsAttributeTests
     */
    public function testSupportsAttribute($attribute, $supported)
    {
        list($voter,, $permissionMap,,) = $this->getVoter();

        $permissionMap
            ->expects($this->once())
            ->method('contains')
            ->with($this->identicalTo($attribute))
            ->will($this->returnValue($supported))
        ;

        $this->assertSame($supported, $voter->supportsAttribute($attribute));
    }

    public function getSupportsAttributeTests()
    {
        return array(
            array('foo', true),
            array('foo', false),
        );
    }

    /**
     * @dataProvider getSupportsClassTests
     */
    public function testSupportsClass($class)
    {
        list($voter,,,,) = $this->getVoter();

        $this->assertTrue($voter->supportsClass($class));
    }

    public function getSupportsClassTests()
    {
        return array(
            array('foo'),
            array('bar'),
            array('moo'),
        );
    }

    public function testVote()
    {
        list($voter,, $permissionMap,,) = $this->getVoter();
        $permissionMap
            ->expects($this->atLeastOnce())
            ->method('getMasks')
            ->will($this->returnValue(null))
        ;

        $this->assertSame(VoterInterface::ACCESS_ABSTAIN, $voter->vote($this->getToken(), null, array('VIEW', 'EDIT', 'DELETE')));
    }

    /**
     * @dataProvider getTrueFalseTests
     */
    public function testVoteWhenNoObjectIsPassed($allowIfObjectIdentityUnavailable)
    {
        list($voter,, $permissionMap,,) = $this->getVoter($allowIfObjectIdentityUnavailable);
        $permissionMap
            ->expects($this->once())
            ->method('getMasks')
            ->will($this->returnValue(array()))
        ;

        if ($allowIfObjectIdentityUnavailable) {
            $vote = VoterInterface::ACCESS_GRANTED;
        } else {
            $vote = VoterInterface::ACCESS_ABSTAIN;
        }

        $this->assertSame($vote, $voter->vote($this->getToken(), null, array('VIEW')));
    }

    /**
     * @dataProvider getTrueFalseTests
     */
    public function testVoteWhenOidStrategyReturnsNull($allowIfUnavailable)
    {
        list($voter,, $permissionMap, $oidStrategy,) = $this->getVoter($allowIfUnavailable);
        $permissionMap
            ->expects($this->once())
            ->method('getMasks')
            ->will($this->returnValue(array()))
        ;

        $oidStrategy
            ->expects($this->once())
            ->method('getObjectIdentity')
            ->will($this->returnValue(null))
        ;

        if ($allowIfUnavailable) {
            $vote = VoterInterface::ACCESS_GRANTED;
        } else {
            $vote = VoterInterface::ACCESS_ABSTAIN;
        }

        $this->assertSame($vote, $voter->vote($this->getToken(), new \stdClass(), array('VIEW')));
    }

    public function getTrueFalseTests()
    {
        return array(array(true), array(false));
    }

    public function testVoteNoAclFound()
    {
        list($voter, $provider, $permissionMap, $oidStrategy, $sidStrategy) = $this->getVoter();

        $permissionMap
            ->expects($this->once())
            ->method('getMasks')
            ->will($this->returnValue(array()))
        ;

        $oidStrategy
            ->expects($this->once())
            ->method('getObjectIdentity')
            ->will($this->returnValue($oid = new ObjectIdentity('1', 'Foo')))
        ;

        $sidStrategy
            ->expects($this->once())
            ->method('getSecurityIdentities')
            ->will($this->returnValue($sids = array(new UserSecurityIdentity('johannes', 'Foo'), new RoleSecurityIdentity('ROLE_FOO'))))
        ;

        $provider
            ->expects($this->once())
            ->method('findAcl')
            ->with($this->equalTo($oid), $this->equalTo($sids))
            ->will($this->throwException(new AclNotFoundException('Not found.')))
        ;

        $this->assertSame(VoterInterface::ACCESS_DENIED, $voter->vote($this->getToken(), new \stdClass(), array('VIEW')));
    }

    /**
     * @dataProvider getTrueFalseTests
     */
    public function testVoteGrantsAccess($grant)
    {
        list($voter, $provider, $permissionMap, $oidStrategy, $sidStrategy) = $this->getVoter();

        $permissionMap
            ->expects($this->once())
            ->method('getMasks')
            ->with($this->equalTo('VIEW'))
            ->will($this->returnValue($masks = array(1, 2, 3)))
        ;

        $oidStrategy
            ->expects($this->once())
            ->method('getObjectIdentity')
            ->will($this->returnValue($oid = new ObjectIdentity('1', 'Foo')))
        ;

        $sidStrategy
            ->expects($this->once())
            ->method('getSecurityIdentities')
            ->will($this->returnValue($sids = array(new UserSecurityIdentity('johannes', 'Foo'), new RoleSecurityIdentity('ROLE_FOO'))))
        ;

        $provider
            ->expects($this->once())
            ->method('findAcl')
            ->with($this->equalTo($oid), $this->equalTo($sids))
            ->will($this->returnValue($acl = $this->getMock('Symfony\Component\Security\Acl\Model\AclInterface')))
        ;

        $acl
            ->expects($this->once())
            ->method('isGranted')
            ->with($this->identicalTo($masks), $this->equalTo($sids), $this->isFalse())
            ->will($this->returnValue($grant))
        ;

        if ($grant) {
            $vote = VoterInterface::ACCESS_GRANTED;
        } else {
            $vote = VoterInterface::ACCESS_DENIED;
        }

        $this->assertSame($vote, $voter->vote($this->getToken(), new \stdClass(), array('VIEW')));
    }

    public function testVoteNoAceFound()
    {
        list($voter, $provider, $permissionMap, $oidStrategy, $sidStrategy) = $this->getVoter();

        $permissionMap
            ->expects($this->once())
            ->method('getMasks')
            ->with($this->equalTo('VIEW'))
            ->will($this->returnValue($masks = array(1, 2, 3)))
        ;

        $oidStrategy
            ->expects($this->once())
            ->method('getObjectIdentity')
            ->will($this->returnValue($oid = new ObjectIdentity('1', 'Foo')))
        ;

        $sidStrategy
            ->expects($this->once())
            ->method('getSecurityIdentities')
            ->will($this->returnValue($sids = array(new UserSecurityIdentity('johannes', 'Foo'), new RoleSecurityIdentity('ROLE_FOO'))))
        ;

        $provider
            ->expects($this->once())
            ->method('findAcl')
            ->with($this->equalTo($oid), $this->equalTo($sids))
            ->will($this->returnValue($acl = $this->getMock('Symfony\Component\Security\Acl\Model\AclInterface')))
        ;

        $acl
            ->expects($this->once())
            ->method('isGranted')
            ->with($this->identicalTo($masks), $this->equalTo($sids), $this->isFalse())
            ->will($this->throwException(new NoAceFoundException('No ACE')))
        ;

        $this->assertSame(VoterInterface::ACCESS_DENIED, $voter->vote($this->getToken(), new \stdClass(), array('VIEW')));
    }

    /**
     * @dataProvider getTrueFalseTests
     */
    public function testVoteGrantsFieldAccess($grant)
    {
        list($voter, $provider, $permissionMap, $oidStrategy, $sidStrategy) = $this->getVoter();

        $permissionMap
            ->expects($this->once())
            ->method('getMasks')
            ->with($this->equalTo('VIEW'))
            ->will($this->returnValue($masks = array(1, 2, 3)))
        ;

        $oidStrategy
            ->expects($this->once())
            ->method('getObjectIdentity')
            ->will($this->returnValue($oid = new ObjectIdentity('1', 'Foo')))
        ;

        $sidStrategy
            ->expects($this->once())
            ->method('getSecurityIdentities')
            ->will($this->returnValue($sids = array(new UserSecurityIdentity('johannes', 'Foo'), new RoleSecurityIdentity('ROLE_FOO'))))
        ;

        $provider
            ->expects($this->once())
            ->method('findAcl')
            ->with($this->equalTo($oid), $this->equalTo($sids))
            ->will($this->returnValue($acl = $this->getMock('Symfony\Component\Security\Acl\Model\AclInterface')))
        ;

        $acl
            ->expects($this->once())
            ->method('isFieldGranted')
            ->with($this->identicalTo('foo'), $this->identicalTo($masks), $this->equalTo($sids), $this->isFalse())
            ->will($this->returnValue($grant))
        ;

        if ($grant) {
            $vote = VoterInterface::ACCESS_GRANTED;
        } else {
            $vote = VoterInterface::ACCESS_DENIED;
        }

        $this->assertSame($vote, $voter->vote($this->getToken(), new FieldVote(new \stdClass(), 'foo'), array('VIEW')));
    }

    public function testVoteNoFieldAceFound()
    {
        list($voter, $provider, $permissionMap, $oidStrategy, $sidStrategy) = $this->getVoter();

        $permissionMap
            ->expects($this->once())
            ->method('getMasks')
            ->with($this->equalTo('VIEW'))
            ->will($this->returnValue($masks = array(1, 2, 3)))
        ;

        $oidStrategy
            ->expects($this->once())
            ->method('getObjectIdentity')
            ->will($this->returnValue($oid = new ObjectIdentity('1', 'Foo')))
        ;

        $sidStrategy
            ->expects($this->once())
            ->method('getSecurityIdentities')
            ->will($this->returnValue($sids = array(new UserSecurityIdentity('johannes', 'Foo'), new RoleSecurityIdentity('ROLE_FOO'))))
        ;

        $provider
            ->expects($this->once())
            ->method('findAcl')
            ->with($this->equalTo($oid), $this->equalTo($sids))
            ->will($this->returnValue($acl = $this->getMock('Symfony\Component\Security\Acl\Model\AclInterface')))
        ;

        $acl
            ->expects($this->once())
            ->method('isFieldGranted')
            ->with($this->identicalTo('foo'), $this->identicalTo($masks), $this->equalTo($sids), $this->isFalse())
            ->will($this->throwException(new NoAceFoundException('No ACE')))
        ;

        $this->assertSame(VoterInterface::ACCESS_DENIED, $voter->vote($this->getToken(), new FieldVote(new \stdClass(), 'foo'), array('VIEW')));
    }

    public function testWhenReceivingAnObjectIdentityInterfaceWeDontRetrieveANewObjectIdentity()
    {
        list($voter, $provider, $permissionMap, $oidStrategy, $sidStrategy) = $this->getVoter();

        $oid = new ObjectIdentity('someID','someType');

        $permissionMap
            ->expects($this->once())
            ->method('getMasks')
            ->with($this->equalTo('VIEW'))
            ->will($this->returnValue($masks = array(1, 2, 3)))
        ;

        $oidStrategy
            ->expects($this->never())
            ->method('getObjectIdentity')
        ;

        $sidStrategy
            ->expects($this->once())
            ->method('getSecurityIdentities')
            ->will($this->returnValue($sids = array(new UserSecurityIdentity('johannes', 'Foo'), new RoleSecurityIdentity('ROLE_FOO'))))
        ;

        $provider
            ->expects($this->once())
            ->method('findAcl')
            ->with($this->equalTo($oid), $this->equalTo($sids))
            ->will($this->returnValue($acl = $this->getMock('Symfony\Component\Security\Acl\Model\AclInterface')))
        ;

        $acl
            ->expects($this->once())
            ->method('isGranted')
            ->with($this->identicalTo($masks), $this->equalTo($sids), $this->isFalse())
            ->will($this->throwException(new NoAceFoundException('No ACE')))
        ;

        $voter->vote($this->getToken(), $oid, array('VIEW'));
    }

    protected function getToken()
    {
        return $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
    }

    protected function getVoter($allowIfObjectIdentityUnavailable = true)
    {
        $provider = $this->getMock('Symfony\Component\Security\Acl\Model\AclProviderInterface');
        $permissionMap = $this->getMock('Symfony\Component\Security\Acl\Permission\PermissionMapInterface');
        $oidStrategy = $this->getMock('Symfony\Component\Security\Acl\Model\ObjectIdentityRetrievalStrategyInterface');
        $sidStrategy = $this->getMock('Symfony\Component\Security\Acl\Model\SecurityIdentityRetrievalStrategyInterface');

        return array(
            new AclVoter($provider, $oidStrategy, $sidStrategy, $permissionMap, null, $allowIfObjectIdentityUnavailable),
            $provider,
            $permissionMap,
            $oidStrategy,
            $sidStrategy,
        );
    }
}
PK��Z�޻>�Q�QRtest/Security/Symfony/Component/Security/Acl/Tests/Dbal/MutableAclProviderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Tests\Dbal;

use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity;
use Symfony\Component\Security\Acl\Model\FieldEntryInterface;
use Symfony\Component\Security\Acl\Model\AuditableEntryInterface;
use Symfony\Component\Security\Acl\Model\EntryInterface;
use Symfony\Component\Security\Acl\Domain\Entry;
use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity;
use Symfony\Component\Security\Acl\Domain\Acl;
use Symfony\Component\Security\Acl\Exception\AclNotFoundException;
use Symfony\Component\Security\Acl\Exception\ConcurrentModificationException;
use Symfony\Component\Security\Acl\Dbal\AclProvider;
use Symfony\Component\Security\Acl\Domain\PermissionGrantingStrategy;
use Symfony\Component\Security\Acl\Dbal\MutableAclProvider;
use Symfony\Component\Security\Acl\Dbal\Schema;
use Doctrine\DBAL\DriverManager;
use Symfony\Component\Security\Acl\Domain\ObjectIdentity;

class MutableAclProviderTest extends \PHPUnit_Framework_TestCase
{
    protected $con;

    public static function assertAceEquals(EntryInterface $a, EntryInterface $b)
    {
        self::assertInstanceOf(get_class($a), $b);

        foreach (array('getId', 'getMask', 'getStrategy', 'isGranting') as $getter) {
            self::assertSame($a->$getter(), $b->$getter());
        }

        self::assertTrue($a->getSecurityIdentity()->equals($b->getSecurityIdentity()));
        self::assertSame($a->getAcl()->getId(), $b->getAcl()->getId());

        if ($a instanceof AuditableEntryInterface) {
            self::assertSame($a->isAuditSuccess(), $b->isAuditSuccess());
            self::assertSame($a->isAuditFailure(), $b->isAuditFailure());
        }

        if ($a instanceof FieldEntryInterface) {
            self::assertSame($a->getField(), $b->getField());
        }
    }

    /**
     * @expectedException \Symfony\Component\Security\Acl\Exception\AclAlreadyExistsException
     */
    public function testCreateAclThrowsExceptionWhenAclAlreadyExists()
    {
        $provider = $this->getProvider();
        $oid = new ObjectIdentity('123456', 'FOO');
        $provider->createAcl($oid);
        $provider->createAcl($oid);
    }

    public function testCreateAcl()
    {
        $provider = $this->getProvider();
        $oid = new ObjectIdentity('123456', 'FOO');
        $acl = $provider->createAcl($oid);
        $cachedAcl = $provider->findAcl($oid);

        $this->assertInstanceOf('Symfony\Component\Security\Acl\Domain\Acl', $acl);
        $this->assertSame($acl, $cachedAcl);
        $this->assertTrue($acl->getObjectIdentity()->equals($oid));
    }

    public function testDeleteAcl()
    {
        $provider = $this->getProvider();
        $oid = new ObjectIdentity(1, 'Foo');
        $acl = $provider->createAcl($oid);

        $provider->deleteAcl($oid);
        $loadedAcls = $this->getField($provider, 'loadedAcls');
        $this->assertCount(0, $loadedAcls['Foo']);

        try {
            $provider->findAcl($oid);
            $this->fail('ACL has not been properly deleted.');
        } catch (AclNotFoundException $notFound) { }
    }

    public function testDeleteAclDeletesChildren()
    {
        $provider = $this->getProvider();
        $acl = $provider->createAcl(new ObjectIdentity(1, 'Foo'));
        $parentAcl = $provider->createAcl(new ObjectIdentity(2, 'Foo'));
        $acl->setParentAcl($parentAcl);
        $provider->updateAcl($acl);
        $provider->deleteAcl($parentAcl->getObjectIdentity());

        try {
            $provider->findAcl(new ObjectIdentity(1, 'Foo'));
            $this->fail('Child-ACLs have not been deleted.');
        } catch (AclNotFoundException $notFound) { }
    }

    public function testFindAclsAddsPropertyListener()
    {
        $provider = $this->getProvider();
        $acl = $provider->createAcl(new ObjectIdentity(1, 'Foo'));

        $propertyChanges = $this->getField($provider, 'propertyChanges');
        $this->assertCount(1, $propertyChanges);
        $this->assertTrue($propertyChanges->contains($acl));
        $this->assertEquals(array(), $propertyChanges->offsetGet($acl));

        $listeners = $this->getField($acl, 'listeners');
        $this->assertSame($provider, $listeners[0]);
    }

    public function testFindAclsAddsPropertyListenerOnlyOnce()
    {
        $provider = $this->getProvider();
        $acl = $provider->createAcl(new ObjectIdentity(1, 'Foo'));
        $acl = $provider->findAcl(new ObjectIdentity(1, 'Foo'));

        $propertyChanges = $this->getField($provider, 'propertyChanges');
        $this->assertCount(1, $propertyChanges);
        $this->assertTrue($propertyChanges->contains($acl));
        $this->assertEquals(array(), $propertyChanges->offsetGet($acl));

        $listeners = $this->getField($acl, 'listeners');
        $this->assertCount(1, $listeners);
        $this->assertSame($provider, $listeners[0]);
    }

    public function testFindAclsAddsPropertyListenerToParentAcls()
    {
        $provider = $this->getProvider();
        $this->importAcls($provider, array(
            'main' => array(
                'object_identifier' => '1',
                'class_type' => 'foo',
                'parent_acl' => 'parent',
            ),
            'parent' => array(
                'object_identifier' => '1',
                'class_type' => 'anotherFoo',
            )
        ));

        $propertyChanges = $this->getField($provider, 'propertyChanges');
        $this->assertCount(0, $propertyChanges);

        $acl = $provider->findAcl(new ObjectIdentity('1', 'foo'));
        $this->assertCount(2, $propertyChanges);
        $this->assertTrue($propertyChanges->contains($acl));
        $this->assertTrue($propertyChanges->contains($acl->getParentAcl()));
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testPropertyChangedDoesNotTrackUnmanagedAcls()
    {
        $provider = $this->getProvider();
        $acl = new Acl(1, new ObjectIdentity(1, 'foo'), new PermissionGrantingStrategy(), array(), false);

        $provider->propertyChanged($acl, 'classAces', array(), array('foo'));
    }

    public function testPropertyChangedTracksChangesToAclProperties()
    {
        $provider = $this->getProvider();
        $acl = $provider->createAcl(new ObjectIdentity(1, 'Foo'));
        $propertyChanges = $this->getField($provider, 'propertyChanges');

        $provider->propertyChanged($acl, 'entriesInheriting', false, true);
        $changes = $propertyChanges->offsetGet($acl);
        $this->assertTrue(isset($changes['entriesInheriting']));
        $this->assertFalse($changes['entriesInheriting'][0]);
        $this->assertTrue($changes['entriesInheriting'][1]);

        $provider->propertyChanged($acl, 'entriesInheriting', true, false);
        $provider->propertyChanged($acl, 'entriesInheriting', false, true);
        $provider->propertyChanged($acl, 'entriesInheriting', true, false);
        $changes = $propertyChanges->offsetGet($acl);
        $this->assertFalse(isset($changes['entriesInheriting']));
    }

    public function testPropertyChangedTracksChangesToAceProperties()
    {
        $provider = $this->getProvider();
        $acl = $provider->createAcl(new ObjectIdentity(1, 'Foo'));
        $ace = new Entry(1, $acl, new UserSecurityIdentity('foo', 'FooClass'), 'all', 1, true, true, true);
        $ace2 = new Entry(2, $acl, new UserSecurityIdentity('foo', 'FooClass'), 'all', 1, true, true, true);
        $propertyChanges = $this->getField($provider, 'propertyChanges');

        $provider->propertyChanged($ace, 'mask', 1, 3);
        $changes = $propertyChanges->offsetGet($acl);
        $this->assertTrue(isset($changes['aces']));
        $this->assertInstanceOf('\SplObjectStorage', $changes['aces']);
        $this->assertTrue($changes['aces']->contains($ace));
        $aceChanges = $changes['aces']->offsetGet($ace);
        $this->assertTrue(isset($aceChanges['mask']));
        $this->assertEquals(1, $aceChanges['mask'][0]);
        $this->assertEquals(3, $aceChanges['mask'][1]);

        $provider->propertyChanged($ace, 'strategy', 'all', 'any');
        $changes = $propertyChanges->offsetGet($acl);
        $this->assertTrue(isset($changes['aces']));
        $this->assertInstanceOf('\SplObjectStorage', $changes['aces']);
        $this->assertTrue($changes['aces']->contains($ace));
        $aceChanges = $changes['aces']->offsetGet($ace);
        $this->assertTrue(isset($aceChanges['mask']));
        $this->assertTrue(isset($aceChanges['strategy']));
        $this->assertEquals('all', $aceChanges['strategy'][0]);
        $this->assertEquals('any', $aceChanges['strategy'][1]);

        $provider->propertyChanged($ace, 'mask', 3, 1);
        $changes = $propertyChanges->offsetGet($acl);
        $aceChanges = $changes['aces']->offsetGet($ace);
        $this->assertFalse(isset($aceChanges['mask']));
        $this->assertTrue(isset($aceChanges['strategy']));

        $provider->propertyChanged($ace2, 'mask', 1, 3);
        $provider->propertyChanged($ace, 'strategy', 'any', 'all');
        $changes = $propertyChanges->offsetGet($acl);
        $this->assertTrue(isset($changes['aces']));
        $this->assertFalse($changes['aces']->contains($ace));
        $this->assertTrue($changes['aces']->contains($ace2));

        $provider->propertyChanged($ace2, 'mask', 3, 4);
        $provider->propertyChanged($ace2, 'mask', 4, 1);
        $changes = $propertyChanges->offsetGet($acl);
        $this->assertFalse(isset($changes['aces']));
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testUpdateAclDoesNotAcceptUntrackedAcls()
    {
        $provider = $this->getProvider();
        $acl = new Acl(1, new ObjectIdentity(1, 'Foo'), new PermissionGrantingStrategy(), array(), true);
        $provider->updateAcl($acl);
    }

    public function testUpdateDoesNothingWhenThereAreNoChanges()
    {
        $con = $this->getMock('Doctrine\DBAL\Connection', array(), array(), '', false);
        $con
            ->expects($this->never())
            ->method('beginTransaction')
        ;
        $con
            ->expects($this->never())
            ->method('executeQuery')
        ;

        $provider = new MutableAclProvider($con, new PermissionGrantingStrategy(), array());
        $acl = new Acl(1, new ObjectIdentity(1, 'Foo'), new PermissionGrantingStrategy(), array(), true);
        $propertyChanges = $this->getField($provider, 'propertyChanges');
        $propertyChanges->offsetSet($acl, array());
        $provider->updateAcl($acl);
    }

    public function testUpdateAclThrowsExceptionOnConcurrentModificationOfSharedProperties()
    {
        $provider = $this->getProvider();
        $acl1 = $provider->createAcl(new ObjectIdentity(1, 'Foo'));
        $acl2 = $provider->createAcl(new ObjectIdentity(2, 'Foo'));
        $acl3 = $provider->createAcl(new ObjectIdentity(1, 'AnotherFoo'));
        $sid = new RoleSecurityIdentity('ROLE_FOO');

        $acl1->insertClassAce($sid, 1);
        $acl3->insertClassAce($sid, 1);
        $provider->updateAcl($acl1);
        $provider->updateAcl($acl3);

        $acl2->insertClassAce($sid, 16);
        $provider->updateAcl($acl2);

        $acl1->insertClassAce($sid, 3);
        $acl2->insertClassAce($sid, 5);
        try {
            $provider->updateAcl($acl1);
            $this->fail('Provider failed to detect a concurrent modification.');
        } catch (ConcurrentModificationException $ex) { }
    }

    public function testUpdateAcl()
    {
        $provider = $this->getProvider();
        $acl = $provider->createAcl(new ObjectIdentity(1, 'Foo'));
        $sid = new UserSecurityIdentity('johannes', 'FooClass');
        $acl->setEntriesInheriting(!$acl->isEntriesInheriting());

        $acl->insertObjectAce($sid, 1);
        $acl->insertClassAce($sid, 5, 0, false);
        $acl->insertObjectAce($sid, 2, 1, true);
        $acl->insertClassFieldAce('field', $sid, 2, 0, true);
        $provider->updateAcl($acl);

        $acl->updateObjectAce(0, 3);
        $acl->deleteObjectAce(1);
        $acl->updateObjectAuditing(0, true, false);
        $acl->updateClassFieldAce(0, 'field', 15);
        $provider->updateAcl($acl);

        $reloadProvider = $this->getProvider();
        $reloadedAcl = $reloadProvider->findAcl(new ObjectIdentity(1, 'Foo'));
        $this->assertNotSame($acl, $reloadedAcl);
        $this->assertSame($acl->isEntriesInheriting(), $reloadedAcl->isEntriesInheriting());

        $aces = $acl->getObjectAces();
        $reloadedAces = $reloadedAcl->getObjectAces();
        $this->assertEquals(count($aces), count($reloadedAces));
        foreach ($aces as $index => $ace) {
            $this->assertAceEquals($ace, $reloadedAces[$index]);
        }
    }

    public function testUpdateAclWorksForChangingTheParentAcl()
    {
        $provider = $this->getProvider();
        $acl = $provider->createAcl(new ObjectIdentity(1, 'Foo'));
        $parentAcl = $provider->createAcl(new ObjectIdentity(1, 'AnotherFoo'));
        $acl->setParentAcl($parentAcl);
        $provider->updateAcl($acl);

        $reloadProvider = $this->getProvider();
        $reloadedAcl = $reloadProvider->findAcl(new ObjectIdentity(1, 'Foo'));
        $this->assertNotSame($acl, $reloadedAcl);
        $this->assertSame($parentAcl->getId(), $reloadedAcl->getParentAcl()->getId());
    }

    public function testUpdateAclUpdatesChildAclsCorrectly()
    {
        $provider = $this->getProvider();
        $acl = $provider->createAcl(new ObjectIdentity(1, 'Foo'));

        $parentAcl = $provider->createAcl(new ObjectIdentity(1, 'Bar'));
        $acl->setParentAcl($parentAcl);
        $provider->updateAcl($acl);

        $parentParentAcl = $provider->createAcl(new ObjectIdentity(1, 'Baz'));
        $parentAcl->setParentAcl($parentParentAcl);
        $provider->updateAcl($parentAcl);

        $newParentParentAcl = $provider->createAcl(new ObjectIdentity(2, 'Baz'));
        $parentAcl->setParentAcl($newParentParentAcl);
        $provider->updateAcl($parentAcl);

        $reloadProvider = $this->getProvider();
        $reloadedAcl = $reloadProvider->findAcl(new ObjectIdentity(1, 'Foo'));
        $this->assertEquals($newParentParentAcl->getId(), $reloadedAcl->getParentAcl()->getParentAcl()->getId());
    }

    public function testUpdateAclInsertingMultipleObjectFieldAcesThrowsDBConstraintViolations()
    {
        $provider = $this->getProvider();
        $oid = new ObjectIdentity(1, 'Foo');
        $sid1 = new UserSecurityIdentity('johannes', 'FooClass');
        $sid2 = new UserSecurityIdentity('guilro', 'FooClass');
        $sid3 = new UserSecurityIdentity('bmaz', 'FooClass');
        $fieldName = 'fieldName';

        $acl = $provider->createAcl($oid);
        $acl->insertObjectFieldAce($fieldName, $sid1, 4);
        $provider->updateAcl($acl);

        $acl = $provider->findAcl($oid);
        $acl->insertObjectFieldAce($fieldName, $sid2, 4);
        $provider->updateAcl($acl);

        $acl = $provider->findAcl($oid);
        $acl->insertObjectFieldAce($fieldName, $sid3, 4);
        $provider->updateAcl($acl);
    }

    public function testUpdateAclDeletingObjectFieldAcesThrowsDBConstraintViolations()
    {
        $provider = $this->getProvider();
        $oid = new ObjectIdentity(1, 'Foo');
        $sid1 = new UserSecurityIdentity('johannes', 'FooClass');
        $sid2 = new UserSecurityIdentity('guilro', 'FooClass');
        $sid3 = new UserSecurityIdentity('bmaz', 'FooClass');
        $fieldName = 'fieldName';

        $acl = $provider->createAcl($oid);
        $acl->insertObjectFieldAce($fieldName, $sid1, 4);
        $provider->updateAcl($acl);

        $acl = $provider->findAcl($oid);
        $acl->insertObjectFieldAce($fieldName, $sid2, 4);
        $provider->updateAcl($acl);

        $index = 0;
        $acl->deleteObjectFieldAce($index, $fieldName);
        $provider->updateAcl($acl);

        $acl = $provider->findAcl($oid);
        $acl->insertObjectFieldAce($fieldName, $sid3, 4);
        $provider->updateAcl($acl);
    }

    /**
     * Data must have the following format:
     * array(
     *     *name* => array(
     *         'object_identifier' => *required*
     *         'class_type' => *required*,
     *         'parent_acl' => *name (optional)*
     *     ),
     * )
     *
     * @param AclProvider $provider
     * @param array       $data
     * @throws \InvalidArgumentException
     * @throws \Exception
     */
    protected function importAcls(AclProvider $provider, array $data)
    {
        $aclIds = $parentAcls = array();
        $con = $this->getField($provider, 'connection');
        $con->beginTransaction();
        try {
            foreach ($data as $name => $aclData) {
                if (!isset($aclData['object_identifier'], $aclData['class_type'])) {
                    throw new \InvalidArgumentException('"object_identifier", and "class_type" must be present.');
                }

                $this->callMethod($provider, 'createObjectIdentity', array(new ObjectIdentity($aclData['object_identifier'], $aclData['class_type'])));
                $aclId = $con->lastInsertId();
                $aclIds[$name] = $aclId;

                $sql = $this->callMethod($provider, 'getInsertObjectIdentityRelationSql', array($aclId, $aclId));
                $con->executeQuery($sql);

                if (isset($aclData['parent_acl'])) {
                    if (isset($aclIds[$aclData['parent_acl']])) {
                        $con->executeQuery("UPDATE acl_object_identities SET parent_object_identity_id = ".$aclIds[$aclData['parent_acl']]." WHERE id = ".$aclId);
                        $con->executeQuery($this->callMethod($provider, 'getInsertObjectIdentityRelationSql', array($aclId, $aclIds[$aclData['parent_acl']])));
                    } else {
                        $parentAcls[$aclId] = $aclData['parent_acl'];
                    }
                }
            }

            foreach ($parentAcls as $aclId => $name) {
                if (!isset($aclIds[$name])) {
                    throw new \InvalidArgumentException(sprintf('"%s" does not exist.', $name));
                }

                $con->executeQuery(sprintf("UPDATE acl_object_identities SET parent_object_identity_id = %d WHERE id = %d", $aclIds[$name], $aclId));
                $con->executeQuery($this->callMethod($provider, 'getInsertObjectIdentityRelationSql', array($aclId, $aclIds[$name])));
            }

            $con->commit();
        } catch (\Exception $e) {
            $con->rollBack();

            throw $e;
        }
    }

    protected function callMethod($object, $method, array $args)
    {
        $method = new \ReflectionMethod($object, $method);
        $method->setAccessible(true);

        return $method->invokeArgs($object, $args);
    }

    protected function setUp()
    {
        if (!class_exists('PDO') || !in_array('sqlite', \PDO::getAvailableDrivers())) {
            self::markTestSkipped('This test requires SQLite support in your environment');
        }

        $this->con = DriverManager::getConnection(array(
            'driver' => 'pdo_sqlite',
            'memory' => true,
        ));

        // import the schema
        $schema = new Schema($this->getOptions());
        foreach ($schema->toSql($this->con->getDatabasePlatform()) as $sql) {
            $this->con->exec($sql);
        }
    }

    protected function tearDown()
    {
        $this->con = null;
    }

    protected function getField($object, $field)
    {
        $reflection = new \ReflectionProperty($object, $field);
        $reflection->setAccessible(true);

        return $reflection->getValue($object);
    }

    public function setField($object, $field, $value)
    {
        $reflection = new \ReflectionProperty($object, $field);
        $reflection->setAccessible(true);
        $reflection->setValue($object, $value);
        $reflection->setAccessible(false);
    }

    protected function getOptions()
    {
        return array(
            'oid_table_name' => 'acl_object_identities',
            'oid_ancestors_table_name' => 'acl_object_identity_ancestors',
            'class_table_name' => 'acl_classes',
            'sid_table_name' => 'acl_security_identities',
            'entry_table_name' => 'acl_entries',
        );
    }

    protected function getStrategy()
    {
        return new PermissionGrantingStrategy();
    }

    protected function getProvider($cache = null)
    {
        return new MutableAclProvider($this->con, $this->getStrategy(), $this->getOptions(), $cache);
    }
}
PK��Z�
�� � Ttest/Security/Symfony/Component/Security/Acl/Tests/Dbal/AclProviderBenchmarkTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Tests\Dbal;

use Symfony\Component\Security\Acl\Dbal\AclProvider;
use Symfony\Component\Security\Acl\Domain\PermissionGrantingStrategy;
use Symfony\Component\Security\Acl\Domain\ObjectIdentity;
use Symfony\Component\Security\Acl\Dbal\Schema;
use Doctrine\DBAL\DriverManager;

/**
 * @group benchmark
 */
class AclProviderBenchmarkTest extends \PHPUnit_Framework_TestCase
{
    /** @var \Doctrine\DBAL\Connection */
    protected $con;
    protected $insertClassStmt;
    protected $insertSidStmt;
    protected $insertOidAncestorStmt;
    protected $insertOidStmt;
    protected $insertEntryStmt;

    protected function setUp()
    {
        try {
            $this->con = DriverManager::getConnection(array(
                'driver' => 'pdo_mysql',
                'host' => 'localhost',
                'user' => 'root',
                'dbname' => 'testdb',
            ));
            $this->con->connect();
        } catch (\Exception $e) {
            $this->markTestSkipped('Unable to connect to the database: '.$e->getMessage());
        }
    }

    protected function tearDown()
    {
        $this->con = null;
    }

    public function testFindAcls()
    {
        // $this->generateTestData();

        // get some random test object identities from the database
        $oids = array();
        $stmt = $this->con->executeQuery("SELECT object_identifier, class_type FROM acl_object_identities o INNER JOIN acl_classes c ON c.id = o.class_id ORDER BY RAND() LIMIT 25");
        foreach ($stmt->fetchAll() as $oid) {
            $oids[] = new ObjectIdentity($oid['object_identifier'], $oid['class_type']);
        }

        $provider = $this->getProvider();

        $start = microtime(true);
        $provider->findAcls($oids);
        $time = microtime(true) - $start;
        echo "Total Time: ".$time."s\n";
    }

    /**
     * This generates a huge amount of test data to be used mainly for benchmarking
     * purposes, not so much for testing. That's why it's not called by default.
     */
    protected function generateTestData()
    {
        $sm = $this->con->getSchemaManager();
        $sm->dropAndCreateDatabase('testdb');
        $this->con->exec("USE testdb");

        // import the schema
        $schema = new Schema($options = $this->getOptions());
        foreach ($schema->toSql($this->con->getDatabasePlatform()) as $sql) {
            $this->con->exec($sql);
        }

        // setup prepared statements
        $this->insertClassStmt = $this->con->prepare('INSERT INTO acl_classes (id, class_type) VALUES (?, ?)');
        $this->insertSidStmt = $this->con->prepare('INSERT INTO acl_security_identities (id, identifier, username) VALUES (?, ?, ?)');
        $this->insertOidStmt = $this->con->prepare('INSERT INTO acl_object_identities (id, class_id, object_identifier, parent_object_identity_id, entries_inheriting) VALUES (?, ?, ?, ?, ?)');
        $this->insertEntryStmt = $this->con->prepare('INSERT INTO acl_entries (id, class_id, object_identity_id, field_name, ace_order, security_identity_id, mask, granting, granting_strategy, audit_success, audit_failure) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)');
        $this->insertOidAncestorStmt = $this->con->prepare('INSERT INTO acl_object_identity_ancestors (object_identity_id, ancestor_id) VALUES (?, ?)');

        for ($i=0; $i<40000; $i++) {
            $this->generateAclHierarchy();
        }
    }

    protected function generateAclHierarchy()
    {
        $rootId = $this->generateAcl($this->chooseClassId(), null, array());

        $this->generateAclLevel(rand(1, 15), $rootId, array($rootId));
    }

    protected function generateAclLevel($depth, $parentId, $ancestors)
    {
        $level = count($ancestors);
        for ($i=0,$t=rand(1, 10); $i<$t; $i++) {
            $id = $this->generateAcl($this->chooseClassId(), $parentId, $ancestors);

            if ($level < $depth) {
                $this->generateAclLevel($depth, $id, array_merge($ancestors, array($id)));
            }
        }
    }

    protected function chooseClassId()
    {
        static $id = 1000;

        if ($id === 1000 || ($id < 1500 && rand(0, 1))) {
            $this->insertClassStmt->execute(array($id, $this->getRandomString(rand(20, 100), 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\\_')));
            $id += 1;

            return $id-1;
        } else {
            return rand(1000, $id-1);
        }
    }

    protected function generateAcl($classId, $parentId, $ancestors)
    {
        static $id = 1000;

        $this->insertOidStmt->execute(array(
            $id,
            $classId,
            $this->getRandomString(rand(20, 50)),
            $parentId,
            rand(0, 1),
        ));

        $this->insertOidAncestorStmt->execute(array($id, $id));
        foreach ($ancestors as $ancestor) {
            $this->insertOidAncestorStmt->execute(array($id, $ancestor));
        }

        $this->generateAces($classId, $id);
        $id += 1;

        return $id-1;
    }

    protected function chooseSid()
    {
        static $id = 1000;

        if ($id === 1000 || ($id < 11000 && rand(0, 1))) {
            $this->insertSidStmt->execute(array(
                $id,
                $this->getRandomString(rand(5, 30)),
                rand(0, 1)
            ));
            $id += 1;

            return $id-1;
        } else {
            return rand(1000, $id-1);
        }
    }

    protected function generateAces($classId, $objectId)
    {
        static $id = 1000;

        $sids = array();
        $fieldOrder = array();

        for ($i=0; $i<=30; $i++) {
            $fieldName = rand(0, 1) ? null : $this->getRandomString(rand(10, 20));

            do {
                $sid = $this->chooseSid();
            } while (array_key_exists($sid, $sids) && in_array($fieldName, $sids[$sid], true));

            $fieldOrder[$fieldName] = array_key_exists($fieldName, $fieldOrder) ? $fieldOrder[$fieldName]+1 : 0;
            if (!isset($sids[$sid])) {
                $sids[$sid] = array();
            }
            $sids[$sid][] = $fieldName;

            $strategy = rand(0, 2);
            if ($strategy === 0) {
                $strategy = PermissionGrantingStrategy::ALL;
            } elseif ($strategy === 1) {
                $strategy = PermissionGrantingStrategy::ANY;
            } else {
                $strategy = PermissionGrantingStrategy::EQUAL;
            }

            // id, cid, oid, field, order, sid, mask, granting, strategy, a success, a failure
            $this->insertEntryStmt->execute(array(
                $id,
                $classId,
                rand(0, 5) ? $objectId : null,
                $fieldName,
                $fieldOrder[$fieldName],
                $sid,
                $this->generateMask(),
                rand(0, 1),
                $strategy,
                rand(0, 1),
                rand(0, 1),
            ));

            $id += 1;
        }
    }

    protected function generateMask()
    {
        $i = rand(1, 30);
        $mask = 0;

        while ($i <= 30) {
            $mask |= 1 << rand(0, 30);
            $i++;
        }

        return $mask;
    }

    protected function getRandomString($length, $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789')
    {
        $s = '';
        $cLength = strlen($chars);

        while (strlen($s) < $length) {
            $s .= $chars[mt_rand(0, $cLength-1)];
        }

        return $s;
    }

    protected function getOptions()
    {
        return array(
            'oid_table_name' => 'acl_object_identities',
            'oid_ancestors_table_name' => 'acl_object_identity_ancestors',
            'class_table_name' => 'acl_classes',
            'sid_table_name' => 'acl_security_identities',
            'entry_table_name' => 'acl_entries',
        );
    }

    protected function getStrategy()
    {
        return new PermissionGrantingStrategy();
    }

    protected function getProvider()
    {
        return new AclProvider($this->con, $this->getStrategy(), $this->getOptions());
    }
}
PK��Z�'(��'�'Ktest/Security/Symfony/Component/Security/Acl/Tests/Dbal/AclProviderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Tests\Dbal;

use Symfony\Component\Security\Acl\Dbal\AclProvider;
use Symfony\Component\Security\Acl\Domain\PermissionGrantingStrategy;
use Symfony\Component\Security\Acl\Domain\ObjectIdentity;
use Symfony\Component\Security\Acl\Dbal\Schema;
use Doctrine\DBAL\DriverManager;

class AclProviderTest extends \PHPUnit_Framework_TestCase
{
    protected $con;
    protected $insertClassStmt;
    protected $insertEntryStmt;
    protected $insertOidStmt;
    protected $insertOidAncestorStmt;
    protected $insertSidStmt;

    /**
     * @expectedException \Symfony\Component\Security\Acl\Exception\AclNotFoundException
     * @expectedMessage There is no ACL for the given object identity.
     */
    public function testFindAclThrowsExceptionWhenNoAclExists()
    {
        $this->getProvider()->findAcl(new ObjectIdentity('foo', 'foo'));
    }

    public function testFindAclsThrowsExceptionUnlessAnACLIsFoundForEveryOID()
    {
        $oids = array();
        $oids[] = new ObjectIdentity('1', 'foo');
        $oids[] = new ObjectIdentity('foo', 'foo');

        try {
            $this->getProvider()->findAcls($oids);

            $this->fail('Provider did not throw an expected exception.');
        } catch (\Exception $ex) {
            $this->assertInstanceOf('Symfony\Component\Security\Acl\Exception\AclNotFoundException', $ex);
            $this->assertInstanceOf('Symfony\Component\Security\Acl\Exception\NotAllAclsFoundException', $ex);

            $partialResult = $ex->getPartialResult();
            $this->assertTrue($partialResult->contains($oids[0]));
            $this->assertFalse($partialResult->contains($oids[1]));
        }
    }

    public function testFindAcls()
    {
        $oids = array();
        $oids[] = new ObjectIdentity('1', 'foo');
        $oids[] = new ObjectIdentity('2', 'foo');

        $provider = $this->getProvider();

        $acls = $provider->findAcls($oids);
        $this->assertInstanceOf('SplObjectStorage', $acls);
        $this->assertCount(2, $acls);
        $this->assertInstanceOf('Symfony\Component\Security\Acl\Domain\Acl', $acl0 = $acls->offsetGet($oids[0]));
        $this->assertInstanceOf('Symfony\Component\Security\Acl\Domain\Acl', $acl1 = $acls->offsetGet($oids[1]));
        $this->assertTrue($oids[0]->equals($acl0->getObjectIdentity()));
        $this->assertTrue($oids[1]->equals($acl1->getObjectIdentity()));
    }

    public function testFindAclsWithDifferentTypes()
    {
        $oids = array();
        $oids[] = new ObjectIdentity('123', 'Bundle\SomeVendor\MyBundle\Entity\SomeEntity');
        $oids[] = new ObjectIdentity('123', 'Bundle\MyBundle\Entity\AnotherEntity');

        $provider = $this->getProvider();

        $acls = $provider->findAcls($oids);
        $this->assertInstanceOf('SplObjectStorage', $acls);
        $this->assertCount(2, $acls);
        $this->assertInstanceOf('Symfony\Component\Security\Acl\Domain\Acl', $acl0 = $acls->offsetGet($oids[0]));
        $this->assertInstanceOf('Symfony\Component\Security\Acl\Domain\Acl', $acl1 = $acls->offsetGet($oids[1]));
        $this->assertTrue($oids[0]->equals($acl0->getObjectIdentity()));
        $this->assertTrue($oids[1]->equals($acl1->getObjectIdentity()));
    }

    public function testFindAclCachesAclInMemory()
    {
        $oid = new ObjectIdentity('1', 'foo');
        $provider = $this->getProvider();

        $acl = $provider->findAcl($oid);
        $this->assertSame($acl, $cAcl = $provider->findAcl($oid));

        $cAces = $cAcl->getObjectAces();
        foreach ($acl->getObjectAces() as $index => $ace) {
            $this->assertSame($ace, $cAces[$index]);
        }
    }

    public function testFindAcl()
    {
        $oid = new ObjectIdentity('1', 'foo');
        $provider = $this->getProvider();

        $acl = $provider->findAcl($oid);

        $this->assertInstanceOf('Symfony\Component\Security\Acl\Domain\Acl', $acl);
        $this->assertTrue($oid->equals($acl->getObjectIdentity()));
        $this->assertEquals(4, $acl->getId());
        $this->assertCount(0, $acl->getClassAces());
        $this->assertCount(0, $this->getField($acl, 'classFieldAces'));
        $this->assertCount(3, $acl->getObjectAces());
        $this->assertCount(0, $this->getField($acl, 'objectFieldAces'));

        $aces = $acl->getObjectAces();
        $this->assertInstanceOf('Symfony\Component\Security\Acl\Domain\Entry', $aces[0]);
        $this->assertTrue($aces[0]->isGranting());
        $this->assertTrue($aces[0]->isAuditSuccess());
        $this->assertTrue($aces[0]->isAuditFailure());
        $this->assertEquals('all', $aces[0]->getStrategy());
        $this->assertSame(2, $aces[0]->getMask());

        // check ACE are in correct order
        $i = 0;
        foreach ($aces as $index => $ace) {
            $this->assertEquals($i, $index);
            $i++;
        }

        $sid = $aces[0]->getSecurityIdentity();
        $this->assertInstanceOf('Symfony\Component\Security\Acl\Domain\UserSecurityIdentity', $sid);
        $this->assertEquals('john.doe', $sid->getUsername());
        $this->assertEquals('SomeClass', $sid->getClass());
    }

    protected function setUp()
    {
        if (!class_exists('PDO') || !in_array('sqlite', \PDO::getAvailableDrivers())) {
            self::markTestSkipped('This test requires SQLite support in your environment');
        }

        $this->con = DriverManager::getConnection(array(
            'driver' => 'pdo_sqlite',
            'memory' => true,
        ));

        // import the schema
        $schema = new Schema($options = $this->getOptions());
        foreach ($schema->toSql($this->con->getDatabasePlatform()) as $sql) {
            $this->con->exec($sql);
        }

        // populate the schema with some test data
        $this->insertClassStmt = $this->con->prepare('INSERT INTO acl_classes (id, class_type) VALUES (?, ?)');
        foreach ($this->getClassData() as $data) {
            $this->insertClassStmt->execute($data);
        }

        $this->insertSidStmt = $this->con->prepare('INSERT INTO acl_security_identities (id, identifier, username) VALUES (?, ?, ?)');
        foreach ($this->getSidData() as $data) {
            $this->insertSidStmt->execute($data);
        }

        $this->insertOidStmt = $this->con->prepare('INSERT INTO acl_object_identities (id, class_id, object_identifier, parent_object_identity_id, entries_inheriting) VALUES (?, ?, ?, ?, ?)');
        foreach ($this->getOidData() as $data) {
            $this->insertOidStmt->execute($data);
        }

        $this->insertEntryStmt = $this->con->prepare('INSERT INTO acl_entries (id, class_id, object_identity_id, field_name, ace_order, security_identity_id, mask, granting, granting_strategy, audit_success, audit_failure) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)');
        foreach ($this->getEntryData() as $data) {
            $this->insertEntryStmt->execute($data);
        }

        $this->insertOidAncestorStmt = $this->con->prepare('INSERT INTO acl_object_identity_ancestors (object_identity_id, ancestor_id) VALUES (?, ?)');
        foreach ($this->getOidAncestorData() as $data) {
            $this->insertOidAncestorStmt->execute($data);
        }
    }

    protected function tearDown()
    {
        $this->con = null;
    }

    protected function getField($object, $field)
    {
        $reflection = new \ReflectionProperty($object, $field);
        $reflection->setAccessible(true);

        return $reflection->getValue($object);
    }

    protected function getEntryData()
    {
        // id, cid, oid, field, order, sid, mask, granting, strategy, a success, a failure
        return array(
            array(1, 1, 1, null, 0, 1, 1, 1, 'all', 1, 1),
            array(2, 1, 1, null, 1, 2, 1 << 2 | 1 << 1, 0, 'any', 0, 0),
            array(3, 3, 4, null, 0, 1, 2, 1, 'all', 1, 1),
            array(4, 3, 4, null, 2, 2, 1, 1, 'all', 1, 1),
            array(5, 3, 4, null, 1, 3, 1, 1, 'all', 1, 1),
        );
    }

    protected function getOidData()
    {
        // id, cid, oid, parent_oid, entries_inheriting
        return array(
            array(1, 1, '123', null, 1),
            array(2, 2, '123', 1, 1),
            array(3, 2, 'i:3:123', 1, 1),
            array(4, 3, '1', 2, 1),
            array(5, 3, '2', 2, 1),
        );
    }

    protected function getOidAncestorData()
    {
        return array(
            array(1, 1),
            array(2, 1),
            array(2, 2),
            array(3, 1),
            array(3, 3),
            array(4, 2),
            array(4, 1),
            array(4, 4),
            array(5, 2),
            array(5, 1),
            array(5, 5),
        );
    }

    protected function getSidData()
    {
        return array(
            array(1, 'SomeClass-john.doe', 1),
            array(2, 'MyClass-john.doe@foo.com', 1),
            array(3, 'FooClass-123', 1),
            array(4, 'MooClass-ROLE_USER', 1),
            array(5, 'ROLE_USER', 0),
            array(6, 'IS_AUTHENTICATED_FULLY', 0),
        );
    }

    protected function getClassData()
    {
        return array(
            array(1, 'Bundle\SomeVendor\MyBundle\Entity\SomeEntity'),
            array(2, 'Bundle\MyBundle\Entity\AnotherEntity'),
            array(3, 'foo'),
        );
    }

    protected function getOptions()
    {
        return array(
            'oid_table_name' => 'acl_object_identities',
            'oid_ancestors_table_name' => 'acl_object_identity_ancestors',
            'class_table_name' => 'acl_classes',
            'sid_table_name' => 'acl_security_identities',
            'entry_table_name' => 'acl_entries',
        );
    }

    protected function getStrategy()
    {
        return new PermissionGrantingStrategy();
    }

    protected function getProvider()
    {
        return new AclProvider($this->con, $this->getStrategy(), $this->getOptions());
    }
}
PK��Z�ˆ5Mtest/Security/Symfony/Component/Security/Acl/Tests/Domain/AuditLoggerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Tests\Domain;

class AuditLoggerTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getTestLogData
     */
    public function testLogIfNeeded($granting, $audit)
    {
        $logger = $this->getLogger();
        $ace = $this->getEntry();

        if (true === $granting) {
            $ace
                ->expects($this->once())
                ->method('isAuditSuccess')
                ->will($this->returnValue($audit))
           ;

           $ace
               ->expects($this->never())
               ->method('isAuditFailure')
           ;
        } else {
            $ace
                ->expects($this->never())
                ->method('isAuditSuccess')
            ;

            $ace
                ->expects($this->once())
                ->method('isAuditFailure')
                ->will($this->returnValue($audit))
            ;
        }

        if (true === $audit) {
            $logger
               ->expects($this->once())
               ->method('doLog')
               ->with($this->equalTo($granting), $this->equalTo($ace))
            ;
        } else {
            $logger
                ->expects($this->never())
                ->method('doLog')
            ;
        }

        $logger->logIfNeeded($granting, $ace);
    }

    public function getTestLogData()
    {
        return array(
            array(true, false),
            array(true, true),
            array(false, false),
            array(false, true),
        );
    }

    protected function getEntry()
    {
        return $this->getMock('Symfony\Component\Security\Acl\Model\AuditableEntryInterface');
    }

    protected function getLogger()
    {
        return $this->getMockForAbstractClass('Symfony\Component\Security\Acl\Domain\AuditLogger');
    }
}
PK��Z6x�}&&Ltest/Security/Symfony/Component/Security/Acl/Tests/Domain/FieldEntryTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Tests\Domain;

use Symfony\Component\Security\Acl\Domain\FieldEntry;

class FieldEntryTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $ace = $this->getAce();

        $this->assertEquals('foo', $ace->getField());
    }

    public function testSerializeUnserialize()
    {
        $ace = $this->getAce();

        $serialized = serialize($ace);
        $uAce = unserialize($serialized);

        $this->assertNull($uAce->getAcl());
        $this->assertInstanceOf('Symfony\Component\Security\Acl\Model\SecurityIdentityInterface', $uAce->getSecurityIdentity());
        $this->assertEquals($ace->getId(), $uAce->getId());
        $this->assertEquals($ace->getField(), $uAce->getField());
        $this->assertEquals($ace->getMask(), $uAce->getMask());
        $this->assertEquals($ace->getStrategy(), $uAce->getStrategy());
        $this->assertEquals($ace->isGranting(), $uAce->isGranting());
        $this->assertEquals($ace->isAuditSuccess(), $uAce->isAuditSuccess());
        $this->assertEquals($ace->isAuditFailure(), $uAce->isAuditFailure());
    }

    protected function getAce($acl = null, $sid = null)
    {
        if (null === $acl) {
            $acl = $this->getAcl();
        }
        if (null === $sid) {
            $sid = $this->getSid();
        }

        return new FieldEntry(
            123,
            $acl,
            'foo',
            $sid,
            'foostrat',
            123456,
            true,
            false,
            true
        );
    }

    protected function getAcl()
    {
        return $this->getMock('Symfony\Component\Security\Acl\Model\AclInterface');
    }

    protected function getSid()
    {
        return $this->getMock('Symfony\Component\Security\Acl\Model\SecurityIdentityInterface');
    }
}
PK��Z��+&Ptest/Security/Symfony/Component/Security/Acl/Tests/Domain/ObjectIdentityTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Tests\Domain
{
    use Symfony\Component\Security\Acl\Domain\ObjectIdentity;

    class ObjectIdentityTest extends \PHPUnit_Framework_TestCase
    {
        public function testConstructor()
        {
            $id = new ObjectIdentity('fooid', 'footype');

            $this->assertEquals('fooid', $id->getIdentifier());
            $this->assertEquals('footype', $id->getType());
        }

        // Test that constructor never changes passed type, even with proxies
        public function testConstructorWithProxy()
        {
            $id = new ObjectIdentity('fooid', 'Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Acl\Tests\Domain\TestDomainObject');

            $this->assertEquals('fooid', $id->getIdentifier());
            $this->assertEquals('Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Acl\Tests\Domain\TestDomainObject', $id->getType());
        }

        public function testFromDomainObjectPrefersInterfaceOverGetId()
        {
            $domainObject = $this->getMock('Symfony\Component\Security\Acl\Model\DomainObjectInterface');
            $domainObject
                ->expects($this->once())
                ->method('getObjectIdentifier')
                ->will($this->returnValue('getObjectIdentifier()'))
            ;
            $domainObject
                ->expects($this->never())
                ->method('getId')
                ->will($this->returnValue('getId()'))
            ;

            $id = ObjectIdentity::fromDomainObject($domainObject);
            $this->assertEquals('getObjectIdentifier()', $id->getIdentifier());
        }

        public function testFromDomainObjectWithoutInterface()
        {
            $id = ObjectIdentity::fromDomainObject(new TestDomainObject());
            $this->assertEquals('getId()', $id->getIdentifier());
            $this->assertEquals('Symfony\Component\Security\Acl\Tests\Domain\TestDomainObject', $id->getType());
        }

        public function testFromDomainObjectWithProxy()
        {
            $id = ObjectIdentity::fromDomainObject(new \Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Acl\Tests\Domain\TestDomainObject());
            $this->assertEquals('getId()', $id->getIdentifier());
            $this->assertEquals('Symfony\Component\Security\Acl\Tests\Domain\TestDomainObject', $id->getType());
        }

        /**
         * @dataProvider getCompareData
         */
        public function testEquals($oid1, $oid2, $equal)
        {
            if ($equal) {
                $this->assertTrue($oid1->equals($oid2));
            } else {
                $this->assertFalse($oid1->equals($oid2));
            }
        }

        public function getCompareData()
        {
            return array(
                array(new ObjectIdentity('123', 'foo'), new ObjectIdentity('123', 'foo'), true),
                array(new ObjectIdentity('123', 'foo'), new ObjectIdentity(123, 'foo'), true),
                array(new ObjectIdentity('1', 'foo'), new ObjectIdentity('2', 'foo'), false),
                array(new ObjectIdentity('1', 'bla'), new ObjectIdentity('1', 'blub'), false),
            );
        }
    }

    class TestDomainObject
    {
        public function getObjectIdentifier()
        {
            return 'getObjectIdentifier()';
        }

        public function getId()
        {
            return 'getId()';
        }
    }
}

namespace Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Acl\Tests\Domain
{
    class TestDomainObject extends \Symfony\Component\Security\Acl\Tests\Domain\TestDomainObject
    {
    }
}
PK��Z_�~��atest/Security/Symfony/Component/Security/Acl/Tests/Domain/ObjectIdentityRetrievalStrategyTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Tests\Domain;

use Symfony\Component\Security\Acl\Domain\ObjectIdentityRetrievalStrategy;

class ObjectIdentityRetrievalStrategyTest extends \PHPUnit_Framework_TestCase
{
    public function testGetObjectIdentityReturnsNullForInvalidDomainObject()
    {
        $strategy = new ObjectIdentityRetrievalStrategy();
        $this->assertNull($strategy->getObjectIdentity('foo'));
    }

    public function testGetObjectIdentity()
    {
        $strategy = new ObjectIdentityRetrievalStrategy();
        $domainObject = new DomainObject();
        $objectIdentity = $strategy->getObjectIdentity($domainObject);

        $this->assertEquals($domainObject->getId(), $objectIdentity->getIdentifier());
        $this->assertEquals(get_class($domainObject), $objectIdentity->getType());
    }
}

class DomainObject
{
    public function getId()
    {
        return 'foo';
    }
}
PK��Z��HHRtest/Security/Symfony/Component/Security/Acl/Tests/Domain/DoctrineAclCacheTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Tests\Domain;

use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity;
use Symfony\Component\Security\Acl\Domain\ObjectIdentity;
use Symfony\Component\Security\Acl\Domain\PermissionGrantingStrategy;
use Symfony\Component\Security\Acl\Domain\Acl;
use Symfony\Component\Security\Acl\Domain\DoctrineAclCache;
use Doctrine\Common\Cache\ArrayCache;

class DoctrineAclCacheTest extends \PHPUnit_Framework_TestCase
{
    protected $permissionGrantingStrategy;

    /**
     * @expectedException \InvalidArgumentException
     * @dataProvider getEmptyValue
     */
    public function testConstructorDoesNotAcceptEmptyPrefix($empty)
    {
        new DoctrineAclCache(new ArrayCache(), $this->getPermissionGrantingStrategy(), $empty);
    }

    public function getEmptyValue()
    {
        return array(
            array(null),
            array(false),
            array(''),
        );
    }

    public function test()
    {
        $cache = $this->getCache();

        $aclWithParent = $this->getAcl(1);
        $acl = $this->getAcl();

        $cache->putInCache($aclWithParent);
        $cache->putInCache($acl);

        $cachedAcl = $cache->getFromCacheByIdentity($acl->getObjectIdentity());
        $this->assertEquals($acl->getId(), $cachedAcl->getId());
        $this->assertNull($acl->getParentAcl());

        $cachedAclWithParent = $cache->getFromCacheByIdentity($aclWithParent->getObjectIdentity());
        $this->assertEquals($aclWithParent->getId(), $cachedAclWithParent->getId());
        $this->assertNotNull($cachedParentAcl = $cachedAclWithParent->getParentAcl());
        $this->assertEquals($aclWithParent->getParentAcl()->getId(), $cachedParentAcl->getId());
    }

    protected function getAcl($depth = 0)
    {
        static $id = 1;

        $acl = new Acl($id, new ObjectIdentity($id, 'foo'), $this->getPermissionGrantingStrategy(), array(), $depth > 0);

        // insert some ACEs
        $sid = new UserSecurityIdentity('johannes', 'Foo');
        $acl->insertClassAce($sid, 1);
        $acl->insertClassFieldAce('foo', $sid, 1);
        $acl->insertObjectAce($sid, 1);
        $acl->insertObjectFieldAce('foo', $sid, 1);
        $id++;

        if ($depth > 0) {
            $acl->setParentAcl($this->getAcl($depth - 1));
        }

        return $acl;
    }

    protected function getPermissionGrantingStrategy()
    {
        if (null === $this->permissionGrantingStrategy) {
            $this->permissionGrantingStrategy = new PermissionGrantingStrategy();
        }

        return $this->permissionGrantingStrategy;
    }

    protected function getCache($cacheDriver = null, $prefix = DoctrineAclCache::PREFIX)
    {
        if (null === $cacheDriver) {
            $cacheDriver = new ArrayCache();
        }

        return new DoctrineAclCache($cacheDriver, $this->getPermissionGrantingStrategy(), $prefix);
    }
}
PK��Z��v��\test/Security/Symfony/Component/Security/Acl/Tests/Domain/PermissionGrantingStrategyTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Tests\Domain;

use Symfony\Component\Security\Acl\Domain\ObjectIdentity;
use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity;
use Symfony\Component\Security\Acl\Domain\Acl;
use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity;
use Symfony\Component\Security\Acl\Domain\PermissionGrantingStrategy;
use Symfony\Component\Security\Acl\Exception\NoAceFoundException;

class PermissionGrantingStrategyTest extends \PHPUnit_Framework_TestCase
{
    public function testIsGrantedObjectAcesHavePriority()
    {
        $strategy = new PermissionGrantingStrategy();
        $acl = $this->getAcl($strategy);
        $sid = new UserSecurityIdentity('johannes', 'Foo');

        $acl->insertClassAce($sid, 1);
        $acl->insertObjectAce($sid, 1, 0, false);
        $this->assertFalse($strategy->isGranted($acl, array(1), array($sid)));
    }

    public function testIsGrantedFallsBackToClassAcesIfNoApplicableObjectAceWasFound()
    {
        $strategy = new PermissionGrantingStrategy();
        $acl = $this->getAcl($strategy);
        $sid = new UserSecurityIdentity('johannes', 'Foo');

        $acl->insertClassAce($sid, 1);
        $this->assertTrue($strategy->isGranted($acl, array(1), array($sid)));
    }

    public function testIsGrantedFavorsLocalAcesOverParentAclAces()
    {
        $strategy = new PermissionGrantingStrategy();
        $sid = new UserSecurityIdentity('johannes', 'Foo');

        $acl = $this->getAcl($strategy);
        $acl->insertClassAce($sid, 1);

        $parentAcl = $this->getAcl($strategy);
        $acl->setParentAcl($parentAcl);
        $parentAcl->insertClassAce($sid, 1, 0, false);

        $this->assertTrue($strategy->isGranted($acl, array(1), array($sid)));
    }

    public function testIsGrantedFallsBackToParentAcesIfNoLocalAcesAreApplicable()
    {
        $strategy = new PermissionGrantingStrategy();
        $sid = new UserSecurityIdentity('johannes', 'Foo');
        $anotherSid = new UserSecurityIdentity('ROLE_USER', 'Foo');

        $acl = $this->getAcl($strategy);
        $acl->insertClassAce($anotherSid, 1, 0, false);

        $parentAcl = $this->getAcl($strategy);
        $acl->setParentAcl($parentAcl);
        $parentAcl->insertClassAce($sid, 1);

        $this->assertTrue($strategy->isGranted($acl, array(1), array($sid)));
    }

    /**
     * @expectedException \Symfony\Component\Security\Acl\Exception\NoAceFoundException
     */
    public function testIsGrantedReturnsExceptionIfNoAceIsFound()
    {
        $strategy = new PermissionGrantingStrategy();
        $acl = $this->getAcl($strategy);
        $sid = new UserSecurityIdentity('johannes', 'Foo');

        $strategy->isGranted($acl, array(1), array($sid));
    }

    public function testIsGrantedFirstApplicableEntryMakesUltimateDecisionForPermissionIdentityCombination()
    {
        $strategy = new PermissionGrantingStrategy();
        $acl = $this->getAcl($strategy);
        $sid = new UserSecurityIdentity('johannes', 'Foo');
        $aSid = new RoleSecurityIdentity('ROLE_USER');

        $acl->insertClassAce($aSid, 1);
        $acl->insertClassAce($sid, 1, 1, false);
        $acl->insertClassAce($sid, 1, 2);
        $this->assertFalse($strategy->isGranted($acl, array(1), array($sid, $aSid)));

        $acl->insertObjectAce($sid, 1, 0, false);
        $acl->insertObjectAce($aSid, 1, 1);
        $this->assertFalse($strategy->isGranted($acl, array(1), array($sid, $aSid)));
    }

    public function testIsGrantedCallsAuditLoggerOnGrant()
    {
        $strategy = new PermissionGrantingStrategy();
        $acl = $this->getAcl($strategy);
        $sid = new UserSecurityIdentity('johannes', 'Foo');

        $logger = $this->getMock('Symfony\Component\Security\Acl\Model\AuditLoggerInterface');
        $logger
            ->expects($this->once())
            ->method('logIfNeeded')
        ;
        $strategy->setAuditLogger($logger);

        $acl->insertObjectAce($sid, 1);
        $acl->updateObjectAuditing(0, true, false);

        $this->assertTrue($strategy->isGranted($acl, array(1), array($sid)));
    }

    public function testIsGrantedCallsAuditLoggerOnDeny()
    {
        $strategy = new PermissionGrantingStrategy();
        $acl = $this->getAcl($strategy);
        $sid = new UserSecurityIdentity('johannes', 'Foo');

        $logger = $this->getMock('Symfony\Component\Security\Acl\Model\AuditLoggerInterface');
        $logger
            ->expects($this->once())
            ->method('logIfNeeded')
        ;
        $strategy->setAuditLogger($logger);

        $acl->insertObjectAce($sid, 1, 0, false);
        $acl->updateObjectAuditing(0, false, true);

        $this->assertFalse($strategy->isGranted($acl, array(1), array($sid)));
    }

    /**
     * @dataProvider getAllStrategyTests
     */
    public function testIsGrantedStrategies($maskStrategy, $aceMask, $requiredMask, $result)
    {
        $strategy = new PermissionGrantingStrategy();
        $acl = $this->getAcl($strategy);
        $sid = new UserSecurityIdentity('johannes', 'Foo');

        $acl->insertObjectAce($sid, $aceMask, 0, true, $maskStrategy);

        if (false === $result) {
            try {
                $strategy->isGranted($acl, array($requiredMask), array($sid));
                $this->fail('The ACE is not supposed to match.');
            } catch (NoAceFoundException $noAce) { }
        } else {
            $this->assertTrue($strategy->isGranted($acl, array($requiredMask), array($sid)));
        }
    }

    public function getAllStrategyTests()
    {
        return array(
            array('all', 1 << 0 | 1 << 1, 1 << 0, true),
            array('all', 1 << 0 | 1 << 1, 1 << 2, false),
            array('all', 1 << 0 | 1 << 10, 1 << 0 | 1 << 10, true),
            array('all', 1 << 0 | 1 << 1, 1 << 0 | 1 << 1 || 1 << 2, false),
            array('any', 1 << 0 | 1 << 1, 1 << 0, true),
            array('any', 1 << 0 | 1 << 1, 1 << 0 | 1 << 2, true),
            array('any', 1 << 0 | 1 << 1, 1 << 2, false),
            array('equal', 1 << 0 | 1 << 1, 1 << 0, false),
            array('equal', 1 << 0 | 1 << 1, 1 << 1, false),
            array('equal', 1 << 0 | 1 << 1, 1 << 0 | 1 << 1, true),
        );
    }

    protected function getAcl($strategy)
    {
        static $id = 1;

        return new Acl($id++, new ObjectIdentity(1, 'Foo'), $strategy, array(), true);
    }
}
PK��Z/bAbAEtest/Security/Symfony/Component/Security/Acl/Tests/Domain/AclTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Tests\Domain;

use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity;

use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity;
use Symfony\Component\Security\Acl\Domain\PermissionGrantingStrategy;
use Symfony\Component\Security\Acl\Domain\ObjectIdentity;
use Symfony\Component\Security\Acl\Domain\Acl;

class AclTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $acl = new Acl(1, $oid = new ObjectIdentity('foo', 'foo'), $permissionStrategy = new PermissionGrantingStrategy(), array(), true);

        $this->assertSame(1, $acl->getId());
        $this->assertSame($oid, $acl->getObjectIdentity());
        $this->assertNull($acl->getParentAcl());
        $this->assertTrue($acl->isEntriesInheriting());
    }

    /**
     * @expectedException \OutOfBoundsException
     * @dataProvider getDeleteAceTests
     */
    public function testDeleteAceThrowsExceptionOnInvalidIndex($type)
    {
        $acl = $this->getAcl();
        $acl->{'delete'.$type.'Ace'}(0);
    }

    /**
     * @dataProvider getDeleteAceTests
     */
    public function testDeleteAce($type)
    {
        $acl = $this->getAcl();
        $acl->{'insert'.$type.'Ace'}(new RoleSecurityIdentity('foo'), 1);
        $acl->{'insert'.$type.'Ace'}(new RoleSecurityIdentity('foo'), 2, 1);
        $acl->{'insert'.$type.'Ace'}(new RoleSecurityIdentity('foo'), 3, 2);

        $listener = $this->getListener(array(
            $type.'Aces', 'aceOrder', 'aceOrder', $type.'Aces',
        ));
        $acl->addPropertyChangedListener($listener);

        $this->assertCount(3, $acl->{'get'.$type.'Aces'}());

        $acl->{'delete'.$type.'Ace'}(0);
        $this->assertCount(2, $aces = $acl->{'get'.$type.'Aces'}());
        $this->assertEquals(2, $aces[0]->getMask());
        $this->assertEquals(3, $aces[1]->getMask());

        $acl->{'delete'.$type.'Ace'}(1);
        $this->assertCount(1, $aces = $acl->{'get'.$type.'Aces'}());
        $this->assertEquals(2, $aces[0]->getMask());
    }

    public function getDeleteAceTests()
    {
        return array(
            array('class'),
            array('object'),
        );
    }

    /**
     * @expectedException \OutOfBoundsException
     * @dataProvider getDeleteFieldAceTests
     */
    public function testDeleteFieldAceThrowsExceptionOnInvalidIndex($type)
    {
        $acl = $this->getAcl();
        $acl->{'delete'.$type.'Ace'}('foo', 0);
    }

    /**
     * @dataProvider getDeleteFieldAceTests
     */
    public function testDeleteFieldAce($type)
    {
        $acl = $this->getAcl();
        $acl->{'insert'.$type.'Ace'}('foo', new RoleSecurityIdentity('foo'), 1, 0);
        $acl->{'insert'.$type.'Ace'}('foo', new RoleSecurityIdentity('foo'), 2, 1);
        $acl->{'insert'.$type.'Ace'}('foo', new RoleSecurityIdentity('foo'), 3, 2);

        $listener = $this->getListener(array(
            $type.'Aces', 'aceOrder', 'aceOrder', $type.'Aces',
        ));
        $acl->addPropertyChangedListener($listener);

        $this->assertCount(3, $acl->{'get'.$type.'Aces'}('foo'));

        $acl->{'delete'.$type.'Ace'}(0, 'foo');
        $this->assertCount(2, $aces = $acl->{'get'.$type.'Aces'}('foo'));
        $this->assertEquals(2, $aces[0]->getMask());
        $this->assertEquals(3, $aces[1]->getMask());

        $acl->{'delete'.$type.'Ace'}(1, 'foo');
        $this->assertCount(1, $aces = $acl->{'get'.$type.'Aces'}('foo'));
        $this->assertEquals(2, $aces[0]->getMask());
    }

    public function getDeleteFieldAceTests()
    {
        return array(
            array('classField'),
            array('objectField'),
        );
    }

    /**
     * @dataProvider getInsertAceTests
     */
    public function testInsertAce($property, $method)
    {
        $acl = $this->getAcl();

        $listener = $this->getListener(array(
            $property, 'aceOrder', $property, 'aceOrder', $property
        ));
        $acl->addPropertyChangedListener($listener);

        $sid = new RoleSecurityIdentity('foo');
        $acl->$method($sid, 1);
        $acl->$method($sid, 2);
        $acl->$method($sid, 3, 1, false);

        $this->assertCount(3, $aces = $acl->{'get'.$property}());
        $this->assertEquals(2, $aces[0]->getMask());
        $this->assertEquals(3, $aces[1]->getMask());
        $this->assertEquals(1, $aces[2]->getMask());
    }

    /**
     * @expectedException \OutOfBoundsException
     * @dataProvider getInsertAceTests
     */
    public function testInsertClassAceThrowsExceptionOnInvalidIndex($property, $method)
    {
        $acl = $this->getAcl();
        $acl->$method(new RoleSecurityIdentity('foo'), 1, 1);
    }

    public function getInsertAceTests()
    {
        return array(
            array('classAces', 'insertClassAce'),
            array('objectAces', 'insertObjectAce'),
        );
    }

    /**
     * @dataProvider getInsertFieldAceTests
     */
    public function testInsertClassFieldAce($property, $method)
    {
        $acl = $this->getAcl();

        $listener = $this->getListener(array(
            $property, $property, 'aceOrder', $property,
            'aceOrder', 'aceOrder', $property,
        ));
        $acl->addPropertyChangedListener($listener);

        $sid = new RoleSecurityIdentity('foo');
        $acl->$method('foo', $sid, 1);
        $acl->$method('foo2', $sid, 1);
        $acl->$method('foo', $sid, 3);
        $acl->$method('foo', $sid, 2);

        $this->assertCount(3, $aces = $acl->{'get'.$property}('foo'));
        $this->assertCount(1, $acl->{'get'.$property}('foo2'));
        $this->assertEquals(2, $aces[0]->getMask());
        $this->assertEquals(3, $aces[1]->getMask());
        $this->assertEquals(1, $aces[2]->getMask());
    }

    /**
     * @expectedException \OutOfBoundsException
     * @dataProvider getInsertFieldAceTests
     */
    public function testInsertClassFieldAceThrowsExceptionOnInvalidIndex($property, $method)
    {
        $acl = $this->getAcl();
        $acl->$method('foo', new RoleSecurityIdentity('foo'), 1, 1);
    }

    public function getInsertFieldAceTests()
    {
        return array(
            array('classFieldAces', 'insertClassFieldAce'),
            array('objectFieldAces', 'insertObjectFieldAce'),
        );
    }

    public function testIsFieldGranted()
    {
        $sids = array(new RoleSecurityIdentity('ROLE_FOO'), new RoleSecurityIdentity('ROLE_IDDQD'));
        $masks = array(1, 2, 4);
        $strategy = $this->getMock('Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface');
        $acl = new Acl(1, new ObjectIdentity(1, 'foo'), $strategy, array(), true);

        $strategy
            ->expects($this->once())
            ->method('isFieldGranted')
            ->with($this->equalTo($acl), $this->equalTo('foo'), $this->equalTo($masks), $this->equalTo($sids), $this->isTrue())
            ->will($this->returnValue(true))
        ;

        $this->assertTrue($acl->isFieldGranted('foo', $masks, $sids, true));
    }

    public function testIsGranted()
    {
        $sids = array(new RoleSecurityIdentity('ROLE_FOO'), new RoleSecurityIdentity('ROLE_IDDQD'));
        $masks = array(1, 2, 4);
        $strategy = $this->getMock('Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface');
        $acl = new Acl(1, new ObjectIdentity(1, 'foo'), $strategy, array(), true);

        $strategy
            ->expects($this->once())
            ->method('isGranted')
            ->with($this->equalTo($acl), $this->equalTo($masks), $this->equalTo($sids), $this->isTrue())
            ->will($this->returnValue(true))
        ;

        $this->assertTrue($acl->isGranted($masks, $sids, true));
    }

    public function testSetGetParentAcl()
    {
        $acl = $this->getAcl();
        $parentAcl = $this->getAcl();

        $listener = $this->getListener(array('parentAcl'));
        $acl->addPropertyChangedListener($listener);

        $this->assertNull($acl->getParentAcl());
        $acl->setParentAcl($parentAcl);
        $this->assertSame($parentAcl, $acl->getParentAcl());

        $acl->setParentAcl(null);
        $this->assertNull($acl->getParentAcl());
    }

    public function testSetIsEntriesInheriting()
    {
        $acl = $this->getAcl();

        $listener = $this->getListener(array('entriesInheriting'));
        $acl->addPropertyChangedListener($listener);

        $this->assertTrue($acl->isEntriesInheriting());
        $acl->setEntriesInheriting(false);
        $this->assertFalse($acl->isEntriesInheriting());
    }

    public function testIsSidLoadedWhenAllSidsAreLoaded()
    {
        $acl = $this->getAcl();

        $this->assertTrue($acl->isSidLoaded(new UserSecurityIdentity('foo', 'Foo')));
        $this->assertTrue($acl->isSidLoaded(new RoleSecurityIdentity('ROLE_FOO', 'Foo')));
    }

    public function testIsSidLoaded()
    {
        $acl = new Acl(1, new ObjectIdentity('1', 'foo'), new PermissionGrantingStrategy(), array(new UserSecurityIdentity('foo', 'Foo'), new UserSecurityIdentity('johannes', 'Bar')), true);

        $this->assertTrue($acl->isSidLoaded(new UserSecurityIdentity('foo', 'Foo')));
        $this->assertTrue($acl->isSidLoaded(new UserSecurityIdentity('johannes', 'Bar')));
        $this->assertTrue($acl->isSidLoaded(array(
            new UserSecurityIdentity('foo', 'Foo'),
            new UserSecurityIdentity('johannes', 'Bar'),
        )));
        $this->assertFalse($acl->isSidLoaded(new RoleSecurityIdentity('ROLE_FOO')));
        $this->assertFalse($acl->isSidLoaded(new UserSecurityIdentity('schmittjoh@gmail.com', 'Moo')));
        $this->assertFalse($acl->isSidLoaded(array(
            new UserSecurityIdentity('foo', 'Foo'),
            new UserSecurityIdentity('johannes', 'Bar'),
            new RoleSecurityIdentity('ROLE_FOO'),
        )));
    }

    /**
     * @dataProvider getUpdateAceTests
     * @expectedException \OutOfBoundsException
     */
    public function testUpdateAceThrowsOutOfBoundsExceptionOnInvalidIndex($type)
    {
        $acl = $this->getAcl();
        $acl->{'update'.$type}(0, 1);
    }

    /**
     * @dataProvider getUpdateAceTests
     */
    public function testUpdateAce($type)
    {
        $acl = $this->getAcl();
        $acl->{'insert'.$type}(new RoleSecurityIdentity('foo'), 1);

        $listener = $this->getListener(array(
            'mask', 'mask', 'strategy',
        ));
        $acl->addPropertyChangedListener($listener);

        $aces = $acl->{'get'.$type.'s'}();
        $ace = reset($aces);
        $this->assertEquals(1, $ace->getMask());
        $this->assertEquals('all', $ace->getStrategy());

        $acl->{'update'.$type}(0, 3);
        $this->assertEquals(3, $ace->getMask());
        $this->assertEquals('all', $ace->getStrategy());

        $acl->{'update'.$type}(0, 1, 'foo');
        $this->assertEquals(1, $ace->getMask());
        $this->assertEquals('foo', $ace->getStrategy());
    }

    public function getUpdateAceTests()
    {
        return array(
            array('classAce'),
            array('objectAce'),
        );
    }

    /**
     * @dataProvider getUpdateFieldAceTests
     * @expectedException \OutOfBoundsException
     */
    public function testUpdateFieldAceThrowsExceptionOnInvalidIndex($type)
    {
        $acl = $this->getAcl();
        $acl->{'update'.$type}(0, 'foo', 1);
    }

    /**
     * @dataProvider getUpdateFieldAceTests
     */
    public function testUpdateFieldAce($type)
    {
        $acl = $this->getAcl();
        $acl->{'insert'.$type}('foo', new UserSecurityIdentity('foo', 'Foo'), 1);

        $listener = $this->getListener(array(
            'mask', 'mask', 'strategy'
        ));
        $acl->addPropertyChangedListener($listener);

        $aces = $acl->{'get'.$type.'s'}('foo');
        $ace = reset($aces);
        $this->assertEquals(1, $ace->getMask());
        $this->assertEquals('all', $ace->getStrategy());

        $acl->{'update'.$type}(0, 'foo', 3);
        $this->assertEquals(3, $ace->getMask());
        $this->assertEquals('all', $ace->getStrategy());

        $acl->{'update'.$type}(0, 'foo', 1, 'foo');
        $this->assertEquals(1, $ace->getMask());
        $this->assertEquals('foo', $ace->getStrategy());
    }

    public function getUpdateFieldAceTests()
    {
        return array(
            array('classFieldAce'),
            array('objectFieldAce'),
        );
    }

    /**
     * @dataProvider getUpdateAuditingTests
     * @expectedException \OutOfBoundsException
     */
    public function testUpdateAuditingThrowsExceptionOnInvalidIndex($type)
    {
        $acl = $this->getAcl();
        $acl->{'update'.$type.'Auditing'}(0, true, false);
    }

    /**
     * @dataProvider getUpdateAuditingTests
     */
    public function testUpdateAuditing($type)
    {
        $acl = $this->getAcl();
        $acl->{'insert'.$type.'Ace'}(new RoleSecurityIdentity('foo'), 1);

        $listener = $this->getListener(array(
            'auditFailure', 'auditSuccess', 'auditFailure',
        ));
        $acl->addPropertyChangedListener($listener);

        $aces = $acl->{'get'.$type.'Aces'}();
        $ace = reset($aces);
        $this->assertFalse($ace->isAuditSuccess());
        $this->assertFalse($ace->isAuditFailure());

        $acl->{'update'.$type.'Auditing'}(0, false, true);
        $this->assertFalse($ace->isAuditSuccess());
        $this->assertTrue($ace->isAuditFailure());

        $acl->{'update'.$type.'Auditing'}(0, true, false);
        $this->assertTrue($ace->isAuditSuccess());
        $this->assertFalse($ace->isAuditFailure());
    }

    public function getUpdateAuditingTests()
    {
        return array(
            array('class'),
            array('object'),
        );
    }

    /**
     * @expectedException \InvalidArgumentException
     * @dataProvider getUpdateFieldAuditingTests
     */
    public function testUpdateFieldAuditingThrowsExceptionOnInvalidField($type)
    {
        $acl = $this->getAcl();
        $acl->{'update'.$type.'Auditing'}(0, 'foo', true, true);
    }

    /**
     * @expectedException \OutOfBoundsException
     * @dataProvider getUpdateFieldAuditingTests
     */
    public function testUpdateFieldAuditingThrowsExceptionOnInvalidIndex($type)
    {
        $acl = $this->getAcl();
        $acl->{'insert'.$type.'Ace'}('foo', new RoleSecurityIdentity('foo'), 1);
        $acl->{'update'.$type.'Auditing'}(1, 'foo', true, false);
    }

    /**
     * @dataProvider getUpdateFieldAuditingTests
     */
    public function testUpdateFieldAuditing($type)
    {
        $acl = $this->getAcl();
        $acl->{'insert'.$type.'Ace'}('foo', new RoleSecurityIdentity('foo'), 1);

        $listener = $this->getListener(array(
            'auditSuccess', 'auditSuccess', 'auditFailure',
        ));
        $acl->addPropertyChangedListener($listener);

        $aces = $acl->{'get'.$type.'Aces'}('foo');
        $ace = reset($aces);
        $this->assertFalse($ace->isAuditSuccess());
        $this->assertFalse($ace->isAuditFailure());

        $acl->{'update'.$type.'Auditing'}(0, 'foo', true, false);
        $this->assertTrue($ace->isAuditSuccess());
        $this->assertFalse($ace->isAuditFailure());

        $acl->{'update'.$type.'Auditing'}(0, 'foo', false, true);
        $this->assertFalse($ace->isAuditSuccess());
        $this->assertTrue($ace->isAuditFailure());
    }

    public function getUpdateFieldAuditingTests()
    {
        return array(
            array('classField'),
            array('objectField'),
        );
    }

    protected function getListener($expectedChanges)
    {
        $aceProperties = array('aceOrder', 'mask', 'strategy', 'auditSuccess', 'auditFailure');

        $listener = $this->getMock('Doctrine\Common\PropertyChangedListener');
        foreach ($expectedChanges as $index => $property) {
            if (in_array($property, $aceProperties)) {
                $class = 'Symfony\Component\Security\Acl\Domain\Entry';
            } else {
                $class = 'Symfony\Component\Security\Acl\Domain\Acl';
            }

            $listener
                ->expects($this->at($index))
                ->method('propertyChanged')
                ->with($this->isInstanceOf($class), $this->equalTo($property))
            ;
        }

        return $listener;
    }

    protected function getAcl()
    {
        return new Acl(1, new ObjectIdentity(1, 'foo'), new PermissionGrantingStrategy(), array(), true);
    }
}
PK��Z5�Vtest/Security/Symfony/Component/Security/Acl/Tests/Domain/RoleSecurityIdentityTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Tests\Domain;

use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity;
use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity;

class RoleSecurityIdentityTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $id = new RoleSecurityIdentity('ROLE_FOO');

        $this->assertEquals('ROLE_FOO', $id->getRole());
    }

    public function testConstructorWithRoleInstance()
    {
        $id = new RoleSecurityIdentity(new Role('ROLE_FOO'));

        $this->assertEquals('ROLE_FOO', $id->getRole());
    }

    /**
     * @dataProvider getCompareData
     */
    public function testEquals($id1, $id2, $equal)
    {
        if ($equal) {
            $this->assertTrue($id1->equals($id2));
        } else {
            $this->assertFalse($id1->equals($id2));
        }
    }

    public function getCompareData()
    {
        return array(
            array(new RoleSecurityIdentity('ROLE_FOO'), new RoleSecurityIdentity('ROLE_FOO'), true),
            array(new RoleSecurityIdentity('ROLE_FOO'), new RoleSecurityIdentity(new Role('ROLE_FOO')), true),
            array(new RoleSecurityIdentity('ROLE_USER'), new RoleSecurityIdentity('ROLE_FOO'), false),
            array(new RoleSecurityIdentity('ROLE_FOO'), new UserSecurityIdentity('ROLE_FOO', 'Foo'), false),
        );
    }
}
PK��Z��a((Vtest/Security/Symfony/Component/Security/Acl/Tests/Domain/UserSecurityIdentityTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Tests\Domain;

use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity;
use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity;

class UserSecurityIdentityTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $id = new UserSecurityIdentity('foo', 'Foo');

        $this->assertEquals('foo', $id->getUsername());
        $this->assertEquals('Foo', $id->getClass());
    }

    // Test that constructor never changes the type, even for proxies
    public function testConstructorWithProxy()
    {
        $id = new UserSecurityIdentity('foo', 'Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Acl\Tests\Domain\Foo');

        $this->assertEquals('foo', $id->getUsername());
        $this->assertEquals('Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Acl\Tests\Domain\Foo', $id->getClass());
    }

    /**
     * @dataProvider getCompareData
     */
    public function testEquals($id1, $id2, $equal)
    {
        $this->assertSame($equal, $id1->equals($id2));
    }

    public function getCompareData()
    {
        $account = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')
                            ->setMockClassName('USI_AccountImpl')
                            ->getMock();
        $account
            ->expects($this->any())
            ->method('getUsername')
            ->will($this->returnValue('foo'))
        ;

        $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
        $token
            ->expects($this->any())
            ->method('getUser')
            ->will($this->returnValue($account))
        ;

        return array(
            array(new UserSecurityIdentity('foo', 'Foo'), new UserSecurityIdentity('foo', 'Foo'), true),
            array(new UserSecurityIdentity('foo', 'Bar'), new UserSecurityIdentity('foo', 'Foo'), false),
            array(new UserSecurityIdentity('foo', 'Foo'), new UserSecurityIdentity('bar', 'Foo'), false),
            array(new UserSecurityIdentity('foo', 'Foo'), UserSecurityIdentity::fromAccount($account), false),
            array(new UserSecurityIdentity('bla', 'Foo'), new UserSecurityIdentity('blub', 'Foo'), false),
            array(new UserSecurityIdentity('foo', 'Foo'), new RoleSecurityIdentity('foo'), false),
            array(new UserSecurityIdentity('foo', 'Foo'), UserSecurityIdentity::fromToken($token), false),
            array(new UserSecurityIdentity('foo', 'USI_AccountImpl'), UserSecurityIdentity::fromToken($token), true),
        );
    }
}
PK��Z�am��ctest/Security/Symfony/Component/Security/Acl/Tests/Domain/SecurityIdentityRetrievalStrategyTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Tests\Domain;

use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity;
use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity;
use Symfony\Component\Security\Acl\Domain\SecurityIdentityRetrievalStrategy;

class SecurityIdentityRetrievalStrategyTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getSecurityIdentityRetrievalTests
     */
    public function testGetSecurityIdentities($user, array $roles, $authenticationStatus, array $sids)
    {
        $strategy = $this->getStrategy($roles, $authenticationStatus);

        if ('anonymous' === $authenticationStatus) {
            $token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\AnonymousToken')
                                ->disableOriginalConstructor()
                                ->getMock();
        } else {
            $class = '';
            if (is_string($user)) {
                $class = 'MyCustomTokenImpl';
            }

            $token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')
                        ->setMockClassName($class)
                        ->getMock();
        }
        $token
            ->expects($this->once())
            ->method('getRoles')
            ->will($this->returnValue(array('foo')))
        ;
        if ('anonymous' === $authenticationStatus) {
            $token
                ->expects($this->never())
                ->method('getUser')
            ;
        } else {
            $token
                ->expects($this->once())
                ->method('getUser')
                ->will($this->returnValue($user))
            ;
        }

        $extractedSids = $strategy->getSecurityIdentities($token);

        foreach ($extractedSids as $index => $extractedSid) {
            if (!isset($sids[$index])) {
                $this->fail(sprintf('Expected SID at index %d, but there was none.', true));
            }

            if (false === $sids[$index]->equals($extractedSid)) {
                $this->fail(sprintf('Index: %d, expected SID "%s", but got "%s".', $index, $sids[$index], $extractedSid));
            }
        }
    }

    public function getSecurityIdentityRetrievalTests()
    {
        return array(
            array($this->getAccount('johannes', 'FooUser'), array('ROLE_USER', 'ROLE_SUPERADMIN'), 'fullFledged', array(
                new UserSecurityIdentity('johannes', 'FooUser'),
                new RoleSecurityIdentity('ROLE_USER'),
                new RoleSecurityIdentity('ROLE_SUPERADMIN'),
                new RoleSecurityIdentity('IS_AUTHENTICATED_FULLY'),
                new RoleSecurityIdentity('IS_AUTHENTICATED_REMEMBERED'),
                new RoleSecurityIdentity('IS_AUTHENTICATED_ANONYMOUSLY'),
            )),
            array('johannes', array('ROLE_FOO'), 'fullFledged', array(
                new UserSecurityIdentity('johannes', 'MyCustomTokenImpl'),
                new RoleSecurityIdentity('ROLE_FOO'),
                new RoleSecurityIdentity('IS_AUTHENTICATED_FULLY'),
                new RoleSecurityIdentity('IS_AUTHENTICATED_REMEMBERED'),
                new RoleSecurityIdentity('IS_AUTHENTICATED_ANONYMOUSLY'),
            )),
            array(new CustomUserImpl('johannes'), array('ROLE_FOO'), 'fullFledged', array(
                new UserSecurityIdentity('johannes', 'Symfony\Component\Security\Acl\Tests\Domain\CustomUserImpl'),
                new RoleSecurityIdentity('ROLE_FOO'),
                new RoleSecurityIdentity('IS_AUTHENTICATED_FULLY'),
                new RoleSecurityIdentity('IS_AUTHENTICATED_REMEMBERED'),
                new RoleSecurityIdentity('IS_AUTHENTICATED_ANONYMOUSLY'),
            )),
            array($this->getAccount('foo', 'FooBarUser'), array('ROLE_FOO'), 'rememberMe', array(
                new UserSecurityIdentity('foo', 'FooBarUser'),
                new RoleSecurityIdentity('ROLE_FOO'),
                new RoleSecurityIdentity('IS_AUTHENTICATED_REMEMBERED'),
                new RoleSecurityIdentity('IS_AUTHENTICATED_ANONYMOUSLY'),
            )),
            array('guest', array('ROLE_FOO'), 'anonymous', array(
                new RoleSecurityIdentity('ROLE_FOO'),
                new RoleSecurityIdentity('IS_AUTHENTICATED_ANONYMOUSLY'),
            ))
        );
    }

    protected function getAccount($username, $class)
    {
        $account = $this->getMock('Symfony\Component\Security\Core\User\UserInterface', array(), array(), $class);
        $account
            ->expects($this->any())
            ->method('getUsername')
            ->will($this->returnValue($username))
        ;

        return $account;
    }

    protected function getStrategy(array $roles = array(), $authenticationStatus = 'fullFledged')
    {
        $roleHierarchy = $this->getMock('Symfony\Component\Security\Core\Role\RoleHierarchyInterface');
        $roleHierarchy
            ->expects($this->once())
            ->method('getReachableRoles')
            ->with($this->equalTo(array('foo')))
            ->will($this->returnValue($roles))
        ;

        $trustResolver = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver', array(), array('', ''));

        $trustResolver
            ->expects($this->at(0))
            ->method('isAnonymous')
            ->will($this->returnValue('anonymous' === $authenticationStatus))
        ;

        if ('fullFledged' === $authenticationStatus) {
            $trustResolver
                ->expects($this->once())
                ->method('isFullFledged')
                ->will($this->returnValue(true))
            ;
            $trustResolver
                ->expects($this->never())
                ->method('isRememberMe')
            ;
        } elseif ('rememberMe' === $authenticationStatus) {
            $trustResolver
                ->expects($this->once())
                ->method('isFullFledged')
                ->will($this->returnValue(false))
            ;
            $trustResolver
                ->expects($this->once())
                ->method('isRememberMe')
                ->will($this->returnValue(true))
            ;
        } else {
            $trustResolver
                ->expects($this->at(1))
                ->method('isAnonymous')
                ->will($this->returnValue(true))
            ;
            $trustResolver
                ->expects($this->once())
                ->method('isFullFledged')
                ->will($this->returnValue(false))
            ;
            $trustResolver
                ->expects($this->once())
                ->method('isRememberMe')
                ->will($this->returnValue(false))
            ;
        }

        return new SecurityIdentityRetrievalStrategy($roleHierarchy, $trustResolver);
    }
}

class CustomUserImpl
{
    protected $name;

    public function __construct($name)
    {
        $this->name = $name;
    }

    public function __toString()
    {
        return $this->name;
    }
}
PK��ZF��@�
�
Gtest/Security/Symfony/Component/Security/Acl/Tests/Domain/EntryTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Tests\Domain;

use Symfony\Component\Security\Acl\Domain\Entry;

class EntryTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $ace = $this->getAce($acl = $this->getAcl(), $sid = $this->getSid());

        $this->assertEquals(123, $ace->getId());
        $this->assertSame($acl, $ace->getAcl());
        $this->assertSame($sid, $ace->getSecurityIdentity());
        $this->assertEquals('foostrat', $ace->getStrategy());
        $this->assertEquals(123456, $ace->getMask());
        $this->assertTrue($ace->isGranting());
        $this->assertTrue($ace->isAuditSuccess());
        $this->assertFalse($ace->isAuditFailure());
    }

    public function testSetAuditSuccess()
    {
        $ace = $this->getAce();

        $this->assertTrue($ace->isAuditSuccess());
        $ace->setAuditSuccess(false);
        $this->assertFalse($ace->isAuditSuccess());
        $ace->setAuditsuccess(true);
        $this->assertTrue($ace->isAuditSuccess());
    }

    public function testSetAuditFailure()
    {
        $ace = $this->getAce();

        $this->assertFalse($ace->isAuditFailure());
        $ace->setAuditFailure(true);
        $this->assertTrue($ace->isAuditFailure());
        $ace->setAuditFailure(false);
        $this->assertFalse($ace->isAuditFailure());
    }

    public function testSetMask()
    {
        $ace = $this->getAce();

        $this->assertEquals(123456, $ace->getMask());
        $ace->setMask(4321);
        $this->assertEquals(4321, $ace->getMask());
    }

    public function testSetStrategy()
    {
        $ace = $this->getAce();

        $this->assertEquals('foostrat', $ace->getStrategy());
        $ace->setStrategy('foo');
        $this->assertEquals('foo', $ace->getStrategy());
    }

    public function testSerializeUnserialize()
    {
        $ace = $this->getAce();

        $serialized = serialize($ace);
        $uAce = unserialize($serialized);

        $this->assertNull($uAce->getAcl());
        $this->assertInstanceOf('Symfony\Component\Security\Acl\Model\SecurityIdentityInterface', $uAce->getSecurityIdentity());
        $this->assertEquals($ace->getId(), $uAce->getId());
        $this->assertEquals($ace->getMask(), $uAce->getMask());
        $this->assertEquals($ace->getStrategy(), $uAce->getStrategy());
        $this->assertEquals($ace->isGranting(), $uAce->isGranting());
        $this->assertEquals($ace->isAuditSuccess(), $uAce->isAuditSuccess());
        $this->assertEquals($ace->isAuditFailure(), $uAce->isAuditFailure());
    }

    protected function getAce($acl = null, $sid = null)
    {
        if (null === $acl) {
            $acl = $this->getAcl();
        }
        if (null === $sid) {
            $sid = $this->getSid();
        }

        return new Entry(
            123,
            $acl,
            $sid,
            'foostrat',
            123456,
            true,
            false,
            true
        );
    }

    protected function getAcl()
    {
        return $this->getMock('Symfony\Component\Security\Acl\Model\AclInterface');
    }

    protected function getSid()
    {
        return $this->getMock('Symfony\Component\Security\Acl\Model\SecurityIdentityInterface');
    }
}
PK��Z���yyXtest/Security/Symfony/Component/Security/Acl/Tests/Permission/BasicPermissionMapTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Tests\Permission;

use Symfony\Component\Security\Acl\Permission\BasicPermissionMap;

class BasicPermissionMapTest extends \PHPUnit_Framework_TestCase
{
    public function testGetMasksReturnsNullWhenNotSupportedMask()
    {
        $map = new BasicPermissionMap();
        $this->assertNull($map->getMasks('IS_AUTHENTICATED_REMEMBERED', null));
    }
}
PK��ZeE���Qtest/Security/Symfony/Component/Security/Acl/Tests/Permission/MaskBuilderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Acl\Tests\Permission;

use Symfony\Component\Security\Acl\Permission\MaskBuilder;

class MaskBuilderTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \InvalidArgumentException
     * @dataProvider getInvalidConstructorData
     */
    public function testConstructorWithNonInteger($invalidMask)
    {
        new MaskBuilder($invalidMask);
    }

    public function getInvalidConstructorData()
    {
        return array(
            array(234.463),
            array('asdgasdf'),
            array(array()),
            array(new \stdClass()),
        );
    }

    public function testConstructorWithoutArguments()
    {
        $builder = new MaskBuilder();

        $this->assertEquals(0, $builder->get());
    }

    public function testConstructor()
    {
        $builder = new MaskBuilder(123456);

        $this->assertEquals(123456, $builder->get());
    }

    public function testAddAndRemove()
    {
        $builder = new MaskBuilder();

        $builder
            ->add('view')
            ->add('eDiT')
            ->add('ownEr')
        ;
        $mask = $builder->get();

        $this->assertEquals(MaskBuilder::MASK_VIEW, $mask & MaskBuilder::MASK_VIEW);
        $this->assertEquals(MaskBuilder::MASK_EDIT, $mask & MaskBuilder::MASK_EDIT);
        $this->assertEquals(MaskBuilder::MASK_OWNER, $mask & MaskBuilder::MASK_OWNER);
        $this->assertEquals(0, $mask & MaskBuilder::MASK_MASTER);
        $this->assertEquals(0, $mask & MaskBuilder::MASK_CREATE);
        $this->assertEquals(0, $mask & MaskBuilder::MASK_DELETE);
        $this->assertEquals(0, $mask & MaskBuilder::MASK_UNDELETE);

        $builder->remove('edit')->remove('OWner');
        $mask = $builder->get();
        $this->assertEquals(0, $mask & MaskBuilder::MASK_EDIT);
        $this->assertEquals(0, $mask & MaskBuilder::MASK_OWNER);
        $this->assertEquals(MaskBuilder::MASK_VIEW, $mask & MaskBuilder::MASK_VIEW);
    }

    public function testGetPattern()
    {
        $builder = new MaskBuilder();
        $this->assertEquals(MaskBuilder::ALL_OFF, $builder->getPattern());

        $builder->add('view');
        $this->assertEquals(str_repeat('.', 31).'V', $builder->getPattern());

        $builder->add('owner');
        $this->assertEquals(str_repeat('.', 24).'N......V', $builder->getPattern());

        $builder->add(1 << 10);
        $this->assertEquals(str_repeat('.', 21).MaskBuilder::ON.'..N......V', $builder->getPattern());
    }

    public function testReset()
    {
        $builder = new MaskBuilder();
        $this->assertEquals(0, $builder->get());

        $builder->add('view');
        $this->assertTrue($builder->get() > 0);

        $builder->reset();
        $this->assertEquals(0, $builder->get());
    }
}
PK��Zܲ#&;;=test/Security/Symfony/Component/Security/Acl/phpunit.xml.distnu�[���<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony Security Component ACL Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./vendor</directory>
                <directory>./Tests</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
PK��ZC��)!"!"Vtest/Security/Symfony/Component/Security/Tests/Http/Firewall/ExceptionListenerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Tests\Http\Firewall;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Http\Authorization\AccessDeniedHandlerInterface;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use Symfony\Component\Security\Http\Firewall\ExceptionListener;
use Symfony\Component\Security\Http\HttpUtils;

class ExceptionListenerTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getAuthenticationExceptionProvider
     */
    public function testAuthenticationExceptionWithoutEntryPoint(\Exception $exception, \Exception $eventException = null)
    {
        $event = $this->createEvent($exception);

        $listener = $this->createExceptionListener();
        $listener->onKernelException($event);

        $this->assertNull($event->getResponse());
        $this->assertSame(null === $eventException ? $exception : $eventException, $event->getException());
    }

    /**
     * @dataProvider getAuthenticationExceptionProvider
     */
    public function testAuthenticationExceptionWithEntryPoint(\Exception $exception, \Exception $eventException = null)
    {
        $event = $this->createEvent($exception = new AuthenticationException());

        $listener = $this->createExceptionListener(null, null, null, $this->createEntryPoint());
        $listener->onKernelException($event);

        $this->assertEquals('OK', $event->getResponse()->getContent());
        $this->assertSame($exception, $event->getException());
    }

    public function getAuthenticationExceptionProvider()
    {
        return array(
            array(new AuthenticationException()),
            array(new \LogicException('random', 0, $e = new AuthenticationException()), $e),
            array(new \LogicException('random', 0, $e = new AuthenticationException('embed', 0, new AuthenticationException())), $e),
            array(new \LogicException('random', 0, $e = new AuthenticationException('embed', 0, new AccessDeniedException())), $e),
            array(new AuthenticationException('random', 0, new \LogicException())),
        );
    }

    /**
     * @dataProvider getAccessDeniedExceptionProvider
     */
    public function testAccessDeniedExceptionFullFledgedAndWithoutAccessDeniedHandlerAndWithoutErrorPage(\Exception $exception, \Exception $eventException = null)
    {
        $event = $this->createEvent($exception);

        $listener = $this->createExceptionListener(null, $this->createTrustResolver(true));
        $listener->onKernelException($event);

        $this->assertNull($event->getResponse());
        $this->assertSame(null === $eventException ? $exception : $eventException, $event->getException()->getPrevious());
    }

    /**
     * @dataProvider getAccessDeniedExceptionProvider
     */
    public function testAccessDeniedExceptionFullFledgedAndWithoutAccessDeniedHandlerAndWithErrorPage(\Exception $exception, \Exception $eventException = null)
    {
        $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
        $kernel->expects($this->once())->method('handle')->will($this->returnValue(new Response('error')));

        $event = $this->createEvent($exception, $kernel);

        $httpUtils = $this->getMock('Symfony\Component\Security\Http\HttpUtils');
        $httpUtils->expects($this->once())->method('createRequest')->will($this->returnValue(Request::create('/error')));

        $listener = $this->createExceptionListener(null, $this->createTrustResolver(true), $httpUtils, null, '/error');
        $listener->onKernelException($event);

        $this->assertEquals('error', $event->getResponse()->getContent());
        $this->assertSame(null === $eventException ? $exception : $eventException, $event->getException()->getPrevious());
    }

    /**
     * @dataProvider getAccessDeniedExceptionProvider
     */
    public function testAccessDeniedExceptionFullFledgedAndWithAccessDeniedHandlerAndWithoutErrorPage(\Exception $exception, \Exception $eventException = null)
    {
        $event = $this->createEvent($exception);

        $accessDeniedHandler = $this->getMock('Symfony\Component\Security\Http\Authorization\AccessDeniedHandlerInterface');
        $accessDeniedHandler->expects($this->once())->method('handle')->will($this->returnValue(new Response('error')));

        $listener = $this->createExceptionListener(null, $this->createTrustResolver(true), null, null, null, $accessDeniedHandler);
        $listener->onKernelException($event);

        $this->assertEquals('error', $event->getResponse()->getContent());
        $this->assertSame(null === $eventException ? $exception : $eventException, $event->getException()->getPrevious());
    }

    /**
     * @dataProvider getAccessDeniedExceptionProvider
     */
    public function testAccessDeniedExceptionNotFullFledged(\Exception $exception, \Exception $eventException = null)
    {
        $event = $this->createEvent($exception);

        $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
        $context->expects($this->once())->method('getToken')->will($this->returnValue($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')));

        $listener = $this->createExceptionListener($context, $this->createTrustResolver(false), null, $this->createEntryPoint());
        $listener->onKernelException($event);

        $this->assertEquals('OK', $event->getResponse()->getContent());
        $this->assertSame(null === $eventException ? $exception : $eventException, $event->getException()->getPrevious());
    }

    public function getAccessDeniedExceptionProvider()
    {
        return array(
            array(new AccessDeniedException()),
            array(new \LogicException('random', 0, $e = new AccessDeniedException()), $e),
            array(new \LogicException('random', 0, $e = new AccessDeniedException('embed', new AccessDeniedException())), $e),
            array(new \LogicException('random', 0, $e = new AccessDeniedException('embed', new AuthenticationException())), $e),
            array(new AccessDeniedException('random', new \LogicException())),
        );
    }

    private function createEntryPoint()
    {
        $entryPoint = $this->getMock('Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface');
        $entryPoint->expects($this->once())->method('start')->will($this->returnValue(new Response('OK')));

        return $entryPoint;
    }

    private function createTrustResolver($fullFledged)
    {
        $trustResolver = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface');
        $trustResolver->expects($this->once())->method('isFullFledged')->will($this->returnValue($fullFledged));

        return $trustResolver;
    }

    private function createEvent(\Exception $exception, $kernel = null)
    {
        if (null === $kernel) {
            $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
        }

        return new GetResponseForExceptionEvent($kernel, Request::create('/'), HttpKernelInterface::MASTER_REQUEST, $exception);
    }

    private function createExceptionListener(SecurityContextInterface $context = null, AuthenticationTrustResolverInterface $trustResolver = null, HttpUtils $httpUtils = null, AuthenticationEntryPointInterface $authenticationEntryPoint = null, $errorPage = null, AccessDeniedHandlerInterface $accessDeniedHandler = null)
    {
        return new ExceptionListener(
            $context ? $context : $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'),
            $trustResolver ? $trustResolver : $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface'),
            $httpUtils ? $httpUtils : $this->getMock('Symfony\Component\Security\Http\HttpUtils'),
            'key',
            $authenticationEntryPoint,
            $errorPage,
            $accessDeniedHandler
        );
    }
}
PK��Zs�f�[[Ltest/Security/Symfony/Component/Security/Tests/Core/User/UserCheckerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Tests\Core\User;

use Symfony\Component\Security\Core\User\UserChecker;

class UserCheckerTest extends \PHPUnit_Framework_TestCase
{
    public function testCheckPostAuthNotAdvancedUserInterface()
    {
        $checker = new UserChecker();

        $this->assertNull($checker->checkPostAuth($this->getMock('Symfony\Component\Security\Core\User\UserInterface')));
    }

    public function testCheckPostAuthPass()
    {
        $checker = new UserChecker();

        $account = $this->getMock('Symfony\Component\Security\Core\User\AdvancedUserInterface');
        $account->expects($this->once())->method('isCredentialsNonExpired')->will($this->returnValue(true));

        $this->assertNull($checker->checkPostAuth($account));
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\CredentialsExpiredException
     */
    public function testCheckPostAuthCredentialsExpired()
    {
        $checker = new UserChecker();

        $account = $this->getMock('Symfony\Component\Security\Core\User\AdvancedUserInterface');
        $account->expects($this->once())->method('isCredentialsNonExpired')->will($this->returnValue(false));

        $checker->checkPostAuth($account);
    }

    public function testCheckPreAuthNotAdvancedUserInterface()
    {
        $checker = new UserChecker();

        $this->assertNull($checker->checkPreAuth($this->getMock('Symfony\Component\Security\Core\User\UserInterface')));
    }

    public function testCheckPreAuthPass()
    {
        $checker = new UserChecker();

        $account = $this->getMock('Symfony\Component\Security\Core\User\AdvancedUserInterface');
        $account->expects($this->once())->method('isAccountNonLocked')->will($this->returnValue(true));
        $account->expects($this->once())->method('isEnabled')->will($this->returnValue(true));
        $account->expects($this->once())->method('isAccountNonExpired')->will($this->returnValue(true));

        $this->assertNull($checker->checkPreAuth($account));
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\LockedException
     */
    public function testCheckPreAuthAccountLocked()
    {
        $checker = new UserChecker();

        $account = $this->getMock('Symfony\Component\Security\Core\User\AdvancedUserInterface');
        $account->expects($this->once())->method('isAccountNonLocked')->will($this->returnValue(false));

        $checker->checkPreAuth($account);
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\DisabledException
     */
    public function testCheckPreAuthDisabled()
    {
        $checker = new UserChecker();

        $account = $this->getMock('Symfony\Component\Security\Core\User\AdvancedUserInterface');
        $account->expects($this->once())->method('isAccountNonLocked')->will($this->returnValue(true));
        $account->expects($this->once())->method('isEnabled')->will($this->returnValue(false));

        $checker->checkPreAuth($account);
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\AccountExpiredException
     */
    public function testCheckPreAuthAccountExpired()
    {
        $checker = new UserChecker();

        $account = $this->getMock('Symfony\Component\Security\Core\User\AdvancedUserInterface');
        $account->expects($this->once())->method('isAccountNonLocked')->will($this->returnValue(true));
        $account->expects($this->once())->method('isEnabled')->will($this->returnValue(true));
        $account->expects($this->once())->method('isAccountNonExpired')->will($this->returnValue(false));

        $checker->checkPreAuth($account);
    }
}
PK��Z����!!Utest/Security/Symfony/Component/Security/Tests/Core/User/InMemoryUserProviderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Tests\Core\User;

use Symfony\Component\Security\Core\User\InMemoryUserProvider;
use Symfony\Component\Security\Core\User\User;

class InMemoryUserProviderTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $provider = new InMemoryUserProvider(array(
            'fabien' => array(
                'password' => 'foo',
                'enabled'  => false,
                'roles'    => array('ROLE_USER'),
            ),
        ));

        $user = $provider->loadUserByUsername('fabien');
        $this->assertEquals('foo', $user->getPassword());
        $this->assertEquals(array('ROLE_USER'), $user->getRoles());
        $this->assertFalse($user->isEnabled());
    }

    public function testCreateUser()
    {
        $provider = new InMemoryUserProvider();
        $provider->createUser(new User('fabien', 'foo'));

        $user = $provider->loadUserByUsername('fabien');
        $this->assertEquals('foo', $user->getPassword());
    }

    /**
     * @expectedException \LogicException
     */
    public function testCreateUserAlreadyExist()
    {
        $provider = new InMemoryUserProvider();
        $provider->createUser(new User('fabien', 'foo'));
        $provider->createUser(new User('fabien', 'foo'));
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\UsernameNotFoundException
     */
    public function testLoadUserByUsernameDoesNotExist()
    {
        $provider = new InMemoryUserProvider();
        $provider->loadUserByUsername('fabien');
    }
}
PK��Z2�nBB`test/Security/Symfony/Component/Security/Tests/Core/Authentication/Token/RememberMeTokenTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Tests\Core\Authentication\Token;

use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken;
use Symfony\Component\Security\Core\Role\Role;

class RememberMeTokenTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $user = $this->getUser();
        $token = new RememberMeToken($user, 'fookey', 'foo');

        $this->assertEquals('fookey', $token->getProviderKey());
        $this->assertEquals('foo', $token->getKey());
        $this->assertEquals(array(new Role('ROLE_FOO')), $token->getRoles());
        $this->assertSame($user, $token->getUser());
        $this->assertTrue($token->isAuthenticated());
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testConstructorKeyCannotBeNull()
    {
        new RememberMeToken(
            $this->getUser(),
            null,
            null
        );
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testConstructorKeyCannotBeEmptyString()
    {
        new RememberMeToken(
            $this->getUser(),
            '',
            ''
        );
    }

    /**
     * @expectedException \PHPUnit_Framework_Error
     * @dataProvider getUserArguments
     */
    public function testConstructorUserCannotBeNull($user)
    {
        new RememberMeToken($user, 'foo', 'foo');
    }

    public function getUserArguments()
    {
        return array(
            array(null),
            array('foo'),
        );
    }

    protected function getUser($roles = array('ROLE_FOO'))
    {
        $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
        $user
            ->expects($this->once())
            ->method('getRoles')
            ->will($this->returnValue($roles))
        ;

        return $user;
    }
}
PK��Z9�#�		9test/Security/Symfony/Component/Security/phpunit.xml.distnu�[���<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony Security Component Test Suite">
            <directory>./Acl/Tests/</directory>
            <directory>./Core/Tests/</directory>
            <directory>./Http/Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./vendor</directory>
                <directory>./Acl/Tests</directory>
                <directory>./Core/Tests</directory>
                <directory>./Http/Tests</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
PK��Zg3�%%Dtest/Security/Symfony/Component/Security/Http/Tests/FirewallTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Tests;

use Symfony\Component\Security\Http\Firewall;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;

class FirewallTest extends \PHPUnit_Framework_TestCase
{
    public function testOnKernelRequestRegistersExceptionListener()
    {
        $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');

        $listener = $this->getMock('Symfony\Component\Security\Http\Firewall\ExceptionListener', array(), array(), '', false);
        $listener
            ->expects($this->once())
            ->method('register')
            ->with($this->equalTo($dispatcher))
        ;

        $request = $this->getMock('Symfony\Component\HttpFoundation\Request', array(), array(), '', false, false);

        $map = $this->getMock('Symfony\Component\Security\Http\FirewallMapInterface');
        $map
            ->expects($this->once())
            ->method('getListeners')
            ->with($this->equalTo($request))
            ->will($this->returnValue(array(array(), $listener)))
        ;

        $event = new GetResponseEvent($this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'), $request, HttpKernelInterface::MASTER_REQUEST);

        $firewall = new Firewall($map, $dispatcher);
        $firewall->onKernelRequest($event);
    }

    public function testOnKernelRequestStopsWhenThereIsAResponse()
    {
        $response = $this->getMock('Symfony\Component\HttpFoundation\Response');

        $first = $this->getMock('Symfony\Component\Security\Http\Firewall\ListenerInterface');
        $first
            ->expects($this->once())
            ->method('handle')
        ;

        $second = $this->getMock('Symfony\Component\Security\Http\Firewall\ListenerInterface');
        $second
            ->expects($this->never())
            ->method('handle')
        ;

        $map = $this->getMock('Symfony\Component\Security\Http\FirewallMapInterface');
        $map
            ->expects($this->once())
            ->method('getListeners')
            ->will($this->returnValue(array(array($first, $second), null)))
        ;

        $event = $this->getMock(
            'Symfony\Component\HttpKernel\Event\GetResponseEvent',
            array('hasResponse'),
            array(
                $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'),
                $this->getMock('Symfony\Component\HttpFoundation\Request', array(), array(), '', false, false),
                HttpKernelInterface::MASTER_REQUEST
            )
        );
        $event
            ->expects($this->once())
            ->method('hasResponse')
            ->will($this->returnValue(true))
        ;

        $firewall = new Firewall($map, $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'));
        $firewall->onKernelRequest($event);
    }

    public function testOnKernelRequestWithSubRequest()
    {
        $map = $this->getMock('Symfony\Component\Security\Http\FirewallMapInterface');
        $map
            ->expects($this->never())
            ->method('getListeners')
        ;

        $event = new GetResponseEvent(
            $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'),
            $this->getMock('Symfony\Component\HttpFoundation\Request'),
            HttpKernelInterface::SUB_REQUEST
        );

        $firewall = new Firewall($map, $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'));
        $firewall->onKernelRequest($event);

        $this->assertFalse($event->hasResponse());
    }
}
PK��Z��+MbbGtest/Security/Symfony/Component/Security/Http/Tests/FirewallMapTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Tests;

use Symfony\Component\Security\Http\FirewallMap;
use Symfony\Component\HttpFoundation\Request;

class FirewallMapTest extends \PHPUnit_Framework_TestCase
{
    public function testGetListeners()
    {
        $map = new FirewallMap();

        $request = new Request();

        $notMatchingMatcher = $this->getMock('Symfony\Component\HttpFoundation\RequestMatcher');
        $notMatchingMatcher
            ->expects($this->once())
            ->method('matches')
            ->with($this->equalTo($request))
            ->will($this->returnValue(false))
        ;

        $map->add($notMatchingMatcher, array($this->getMock('Symfony\Component\Security\Http\Firewall\ListenerInterface')));

        $matchingMatcher = $this->getMock('Symfony\Component\HttpFoundation\RequestMatcher');
        $matchingMatcher
            ->expects($this->once())
            ->method('matches')
            ->with($this->equalTo($request))
            ->will($this->returnValue(true))
        ;
        $theListener = $this->getMock('Symfony\Component\Security\Http\Firewall\ListenerInterface');
        $theException = $this->getMock('Symfony\Component\Security\Http\Firewall\ExceptionListener', array(), array(), '', false);

        $map->add($matchingMatcher, array($theListener), $theException);

        $tooLateMatcher = $this->getMock('Symfony\Component\HttpFoundation\RequestMatcher');
        $tooLateMatcher
            ->expects($this->never())
            ->method('matches')
        ;

        $map->add($tooLateMatcher, array($this->getMock('Symfony\Component\Security\Http\Firewall\ListenerInterface')));

        list($listeners, $exception) = $map->getListeners($request);

        $this->assertEquals(array($theListener), $listeners);
        $this->assertEquals($theException, $exception);
    }

    public function testGetListenersWithAnEntryHavingNoRequestMatcher()
    {
        $map = new FirewallMap();

        $request = new Request();

        $notMatchingMatcher = $this->getMock('Symfony\Component\HttpFoundation\RequestMatcher');
        $notMatchingMatcher
            ->expects($this->once())
            ->method('matches')
            ->with($this->equalTo($request))
            ->will($this->returnValue(false))
        ;

        $map->add($notMatchingMatcher, array($this->getMock('Symfony\Component\Security\Http\Firewall\ListenerInterface')));

        $theListener = $this->getMock('Symfony\Component\Security\Http\Firewall\ListenerInterface');
        $theException = $this->getMock('Symfony\Component\Security\Http\Firewall\ExceptionListener', array(), array(), '', false);

        $map->add(null, array($theListener), $theException);

        $tooLateMatcher = $this->getMock('Symfony\Component\HttpFoundation\RequestMatcher');
        $tooLateMatcher
            ->expects($this->never())
            ->method('matches')
        ;

        $map->add($tooLateMatcher, array($this->getMock('Symfony\Component\Security\Http\Firewall\ListenerInterface')));

        list($listeners, $exception) = $map->getListeners($request);

        $this->assertEquals(array($theListener), $listeners);
        $this->assertEquals($theException, $exception);
    }

    public function testGetListenersWithNoMatchingEntry()
    {
        $map = new FirewallMap();

        $request = new Request();

        $notMatchingMatcher = $this->getMock('Symfony\Component\HttpFoundation\RequestMatcher');
        $notMatchingMatcher
            ->expects($this->once())
            ->method('matches')
            ->with($this->equalTo($request))
            ->will($this->returnValue(false))
        ;

        $map->add($notMatchingMatcher, array($this->getMock('Symfony\Component\Security\Http\Firewall\ListenerInterface')));

        list($listeners, $exception) = $map->getListeners($request);

        $this->assertEquals(array(), $listeners);
        $this->assertNull($exception);
    }
}
PK��Z����%�%Etest/Security/Symfony/Component/Security/Http/Tests/HttpUtilsTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Tests;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Http\HttpUtils;

class HttpUtilsTest extends \PHPUnit_Framework_TestCase
{
    public function testCreateRedirectResponseWithPath()
    {
        $utils = new HttpUtils($this->getUrlGenerator());
        $response = $utils->createRedirectResponse($this->getRequest(), '/foobar');

        $this->assertTrue($response->isRedirect('http://localhost/foobar'));
        $this->assertEquals(302, $response->getStatusCode());
    }

    public function testCreateRedirectResponseWithAbsoluteUrl()
    {
        $utils = new HttpUtils($this->getUrlGenerator());
        $response = $utils->createRedirectResponse($this->getRequest(), 'http://symfony.com/');

        $this->assertTrue($response->isRedirect('http://symfony.com/'));
    }

    public function testCreateRedirectResponseWithRouteName()
    {
        $utils = new HttpUtils($urlGenerator = $this->getMock('Symfony\Component\Routing\Generator\UrlGeneratorInterface'));

        $urlGenerator
            ->expects($this->any())
            ->method('generate')
            ->with('foobar', array(), true)
            ->will($this->returnValue('http://localhost/foo/bar'))
        ;
        $urlGenerator
            ->expects($this->any())
            ->method('getContext')
            ->will($this->returnValue($this->getMock('Symfony\Component\Routing\RequestContext')))
        ;

        $response = $utils->createRedirectResponse($this->getRequest(), 'foobar');

        $this->assertTrue($response->isRedirect('http://localhost/foo/bar'));
    }

    public function testCreateRequestWithPath()
    {
        $request = $this->getRequest();
        $request->server->set('Foo', 'bar');

        $utils = new HttpUtils($this->getUrlGenerator());
        $subRequest = $utils->createRequest($request, '/foobar');

        $this->assertEquals('GET', $subRequest->getMethod());
        $this->assertEquals('/foobar', $subRequest->getPathInfo());
        $this->assertEquals('bar', $subRequest->server->get('Foo'));
    }

    public function testCreateRequestWithRouteName()
    {
        $utils = new HttpUtils($urlGenerator = $this->getMock('Symfony\Component\Routing\Generator\UrlGeneratorInterface'));

        $urlGenerator
            ->expects($this->once())
            ->method('generate')
            ->will($this->returnValue('/foo/bar'))
        ;
        $urlGenerator
            ->expects($this->any())
            ->method('getContext')
            ->will($this->returnValue($this->getMock('Symfony\Component\Routing\RequestContext')))
        ;

        $subRequest = $utils->createRequest($this->getRequest(), 'foobar');

        $this->assertEquals('/foo/bar', $subRequest->getPathInfo());
    }

    public function testCreateRequestWithAbsoluteUrl()
    {
        $utils = new HttpUtils($this->getMock('Symfony\Component\Routing\Generator\UrlGeneratorInterface'));
        $subRequest = $utils->createRequest($this->getRequest(), 'http://symfony.com/');

        $this->assertEquals('/', $subRequest->getPathInfo());
    }

    public function testCreateRequestPassesSessionToTheNewRequest()
    {
        $request = $this->getRequest();
        $request->setSession($session = $this->getMock('Symfony\Component\HttpFoundation\Session\SessionInterface'));

        $utils = new HttpUtils($this->getUrlGenerator());
        $subRequest = $utils->createRequest($request, '/foobar');

        $this->assertSame($session, $subRequest->getSession());
    }

    /**
     * @dataProvider provideSecurityContextAttributes
     */
    public function testCreateRequestPassesSecurityContextAttributesToTheNewRequest($attribute)
    {
        $request = $this->getRequest();
        $request->attributes->set($attribute, 'foo');

        $utils = new HttpUtils($this->getUrlGenerator());
        $subRequest = $utils->createRequest($request, '/foobar');

        $this->assertSame('foo', $subRequest->attributes->get($attribute));
    }

    public function provideSecurityContextAttributes()
    {
        return array(
            array(SecurityContextInterface::AUTHENTICATION_ERROR),
            array(SecurityContextInterface::ACCESS_DENIED_ERROR),
            array(SecurityContextInterface::LAST_USERNAME)
        );
    }

    public function testCheckRequestPath()
    {
        $utils = new HttpUtils($this->getUrlGenerator());

        $this->assertTrue($utils->checkRequestPath($this->getRequest(), '/'));
        $this->assertFalse($utils->checkRequestPath($this->getRequest(), '/foo'));
        $this->assertTrue($utils->checkRequestPath($this->getRequest('/foo%20bar'), '/foo bar'));
        // Plus must not decoded to space
        $this->assertTrue($utils->checkRequestPath($this->getRequest('/foo+bar'), '/foo+bar'));
        // Checking unicode
        $this->assertTrue($utils->checkRequestPath($this->getRequest(urlencode('/вход')), '/вход'));
    }

    public function testCheckRequestPathWithUrlMatcherAndResourceNotFound()
    {
        $urlMatcher = $this->getMock('Symfony\Component\Routing\Matcher\UrlMatcherInterface');
        $urlMatcher
            ->expects($this->any())
            ->method('match')
            ->with('/')
            ->will($this->throwException(new ResourceNotFoundException()))
        ;

        $utils = new HttpUtils(null, $urlMatcher);
        $this->assertFalse($utils->checkRequestPath($this->getRequest(), 'foobar'));
    }

    public function testCheckRequestPathWithUrlMatcherAndMethodNotAllowed()
    {
        $request = $this->getRequest();
        $urlMatcher = $this->getMock('Symfony\Component\Routing\Matcher\RequestMatcherInterface');
        $urlMatcher
            ->expects($this->any())
            ->method('matchRequest')
            ->with($request)
            ->will($this->throwException(new MethodNotAllowedException(array())))
        ;

        $utils = new HttpUtils(null, $urlMatcher);
        $this->assertFalse($utils->checkRequestPath($request, 'foobar'));
    }

    public function testCheckRequestPathWithUrlMatcherAndResourceFoundByUrl()
    {
        $urlMatcher = $this->getMock('Symfony\Component\Routing\Matcher\UrlMatcherInterface');
        $urlMatcher
            ->expects($this->any())
            ->method('match')
            ->with('/foo/bar')
            ->will($this->returnValue(array('_route' => 'foobar')))
        ;

        $utils = new HttpUtils(null, $urlMatcher);
        $this->assertTrue($utils->checkRequestPath($this->getRequest('/foo/bar'), 'foobar'));
    }

    public function testCheckRequestPathWithUrlMatcherAndResourceFoundByRequest()
    {
        $request = $this->getRequest();
        $urlMatcher = $this->getMock('Symfony\Component\Routing\Matcher\RequestMatcherInterface');
        $urlMatcher
            ->expects($this->any())
            ->method('matchRequest')
            ->with($request)
            ->will($this->returnValue(array('_route' => 'foobar')))
        ;

        $utils = new HttpUtils(null, $urlMatcher);
        $this->assertTrue($utils->checkRequestPath($request, 'foobar'));
    }

    /**
     * @expectedException \RuntimeException
     */
    public function testCheckRequestPathWithUrlMatcherLoadingException()
    {
        $urlMatcher = $this->getMock('Symfony\Component\Routing\Matcher\UrlMatcherInterface');
        $urlMatcher
            ->expects($this->any())
            ->method('match')
            ->will($this->throwException(new \RuntimeException()))
        ;

        $utils = new HttpUtils(null, $urlMatcher);
        $utils->checkRequestPath($this->getRequest(), 'foobar');
    }

    /**
     * @expectedException \InvalidArgumentException
     * @expectedExceptionMessage Matcher must either implement UrlMatcherInterface or RequestMatcherInterface
     */
    public function testUrlMatcher()
    {
        new HttpUtils($this->getUrlGenerator(), new \stdClass());
    }

    public function testGenerateUriRemovesQueryString()
    {
        $utils = new HttpUtils($this->getUrlGenerator('/foo/bar'));
        $this->assertEquals('/foo/bar', $utils->generateUri(new Request(), 'route_name'));

        $utils = new HttpUtils($this->getUrlGenerator('/foo/bar?param=value'));
        $this->assertEquals('/foo/bar', $utils->generateUri(new Request(), 'route_name'));
    }

    /**
     * @expectedException \LogicException
     * @expectedExceptionMessage You must provide a UrlGeneratorInterface instance to be able to use routes.
     */
    public function testUrlGeneratorIsRequiredToGenerateUrl()
    {
        $utils = new HttpUtils();
        $utils->generateUri(new Request(), 'route_name');
    }

    private function getUrlGenerator($generatedUrl = '/foo/bar')
    {
        $urlGenerator = $this->getMock('Symfony\Component\Routing\Generator\UrlGeneratorInterface');
        $urlGenerator
            ->expects($this->any())
            ->method('generate')
            ->will($this->returnValue($generatedUrl))
        ;

        return $urlGenerator;
    }

    private function getRequest($path = '/')
    {
        return Request::create($path, 'get');
    }
}
PK��Z�ck�~
~
ctest/Security/Symfony/Component/Security/Http/Tests/EntryPoint/FormAuthenticationEntryPointTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Tests\EntryPoint;

use Symfony\Component\Security\Http\EntryPoint\FormAuthenticationEntryPoint;
use Symfony\Component\HttpKernel\HttpKernelInterface;

class FormAuthenticationEntryPointTest extends \PHPUnit_Framework_TestCase
{
    public function testStart()
    {
        $request = $this->getMock('Symfony\Component\HttpFoundation\Request', array(), array(), '', false, false);
        $response = $this->getMock('Symfony\Component\HttpFoundation\Response');

        $httpKernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
        $httpUtils = $this->getMock('Symfony\Component\Security\Http\HttpUtils');
        $httpUtils
            ->expects($this->once())
            ->method('createRedirectResponse')
            ->with($this->equalTo($request), $this->equalTo('/the/login/path'))
            ->will($this->returnValue($response))
        ;

        $entryPoint = new FormAuthenticationEntryPoint($httpKernel, $httpUtils, '/the/login/path', false);

        $this->assertEquals($response, $entryPoint->start($request));
    }

    public function testStartWithUseForward()
    {
        $request = $this->getMock('Symfony\Component\HttpFoundation\Request', array(), array(), '', false, false);
        $subRequest = $this->getMock('Symfony\Component\HttpFoundation\Request', array(), array(), '', false, false);
        $response = new \Symfony\Component\HttpFoundation\Response('', 200);

        $httpUtils = $this->getMock('Symfony\Component\Security\Http\HttpUtils');
        $httpUtils
            ->expects($this->once())
            ->method('createRequest')
            ->with($this->equalTo($request), $this->equalTo('/the/login/path'))
            ->will($this->returnValue($subRequest))
        ;

        $httpKernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
        $httpKernel
            ->expects($this->once())
            ->method('handle')
            ->with($this->equalTo($subRequest), $this->equalTo(HttpKernelInterface::SUB_REQUEST))
            ->will($this->returnValue($response))
        ;

        $entryPoint = new FormAuthenticationEntryPoint($httpKernel, $httpUtils, '/the/login/path', true);

        $entryPointResponse = $entryPoint->start($request);

        $this->assertEquals($response, $entryPointResponse);
        $this->assertEquals(401, $entryPointResponse->headers->get('X-Status-Code'));
    }
}
PK��Ze���dtest/Security/Symfony/Component/Security/Http/Tests/EntryPoint/BasicAuthenticationEntryPointTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Tests\EntryPoint;

use Symfony\Component\Security\Http\EntryPoint\BasicAuthenticationEntryPoint;
use Symfony\Component\Security\Core\Exception\AuthenticationException;

class BasicAuthenticationEntryPointTest extends \PHPUnit_Framework_TestCase
{
    public function testStart()
    {
        $request = $this->getMock('Symfony\Component\HttpFoundation\Request');

        $authException = new AuthenticationException('The exception message');

        $entryPoint = new BasicAuthenticationEntryPoint('TheRealmName');
        $response = $entryPoint->start($request, $authException);

        $this->assertEquals('Basic realm="TheRealmName"', $response->headers->get('WWW-Authenticate'));
        $this->assertEquals(401, $response->getStatusCode());
    }

    public function testStartWithoutAuthException()
    {
        $request = $this->getMock('Symfony\Component\HttpFoundation\Request');

        $entryPoint = new BasicAuthenticationEntryPoint('TheRealmName');

        $response = $entryPoint->start($request);

        $this->assertEquals('Basic realm="TheRealmName"', $response->headers->get('WWW-Authenticate'));
        $this->assertEquals(401, $response->getStatusCode());
    }
}
PK��Z-Ɔ��dtest/Security/Symfony/Component/Security/Http/Tests/EntryPoint/RetryAuthenticationEntryPointTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Tests\EntryPoint;

use Symfony\Component\Security\Http\EntryPoint\RetryAuthenticationEntryPoint;
use Symfony\Component\HttpFoundation\Request;

class RetryAuthenticationEntryPointTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider dataForStart
     */
    public function testStart($httpPort, $httpsPort, $request, $expectedUrl)
    {
        $entryPoint = new RetryAuthenticationEntryPoint($httpPort, $httpsPort);
        $response = $entryPoint->start($request);

        $this->assertInstanceOf('Symfony\Component\HttpFoundation\RedirectResponse', $response);
        $this->assertEquals($expectedUrl, $response->headers->get('Location'));
    }

    public function dataForStart()
    {
        if (!class_exists('Symfony\Component\HttpFoundation\Request')) {
            return array(array());
        }

        return array(
            array(
                80,
                443,
                Request::create('http://localhost/foo/bar?baz=bat'),
                'https://localhost/foo/bar?baz=bat'
            ),
            array(
                80,
                443,
                Request::create('https://localhost/foo/bar?baz=bat'),
                'http://localhost/foo/bar?baz=bat'
            ),
            array(
                80,
                123,
                Request::create('http://localhost/foo/bar?baz=bat'),
                'https://localhost:123/foo/bar?baz=bat'
            ),
            array(
                8080,
                443,
                Request::create('https://localhost/foo/bar?baz=bat'),
                'http://localhost:8080/foo/bar?baz=bat'
            )
        );
    }
}
PK��ZGrT�		etest/Security/Symfony/Component/Security/Http/Tests/EntryPoint/DigestAuthenticationEntryPointTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Tests\EntryPoint;

use Symfony\Component\Security\Http\EntryPoint\DigestAuthenticationEntryPoint;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\NonceExpiredException;

class DigestAuthenticationEntryPointTest extends \PHPUnit_Framework_TestCase
{
    public function testStart()
    {
        $request = $this->getMock('Symfony\Component\HttpFoundation\Request');

        $authenticationException = new AuthenticationException('TheAuthenticationExceptionMessage');

        $entryPoint = new DigestAuthenticationEntryPoint('TheRealmName', 'TheKey');
        $response = $entryPoint->start($request, $authenticationException);

        $this->assertEquals(401, $response->getStatusCode());
        $this->assertRegExp('/^Digest realm="TheRealmName", qop="auth", nonce="[a-zA-Z0-9\/+]+={0,2}"$/', $response->headers->get('WWW-Authenticate'));
    }

    public function testStartWithNoException()
    {
        $request = $this->getMock('Symfony\Component\HttpFoundation\Request');

        $entryPoint = new DigestAuthenticationEntryPoint('TheRealmName', 'TheKey');
        $response = $entryPoint->start($request);

        $this->assertEquals(401, $response->getStatusCode());
        $this->assertRegExp('/^Digest realm="TheRealmName", qop="auth", nonce="[a-zA-Z0-9\/+]+={0,2}"$/', $response->headers->get('WWW-Authenticate'));
    }

    public function testStartWithNonceExpiredException()
    {
        $request = $this->getMock('Symfony\Component\HttpFoundation\Request');

        $nonceExpiredException = new NonceExpiredException('TheNonceExpiredExceptionMessage');

        $entryPoint = new DigestAuthenticationEntryPoint('TheRealmName', 'TheKey');
        $response = $entryPoint->start($request, $nonceExpiredException);

        $this->assertEquals(401, $response->getStatusCode());
        $this->assertRegExp('/^Digest realm="TheRealmName", qop="auth", nonce="[a-zA-Z0-9\/+]+={0,2}", stale="true"$/', $response->headers->get('WWW-Authenticate'));
    }
}
PK��ZҒ)��Wtest/Security/Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Tests\Firewall;

use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Firewall\RememberMeListener;
use Symfony\Component\HttpFoundation\Request;

class RememberMeListenerTest extends \PHPUnit_Framework_TestCase
{
    public function testOnCoreSecurityDoesNotTryToPopulateNonEmptySecurityContext()
    {
        list($listener, $context, $service,,) = $this->getListener();

        $context
            ->expects($this->once())
            ->method('getToken')
            ->will($this->returnValue($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')))
        ;

        $context
            ->expects($this->never())
            ->method('setToken')
        ;

        $this->assertNull($listener->handle($this->getGetResponseEvent()));
    }

    public function testOnCoreSecurityDoesNothingWhenNoCookieIsSet()
    {
        list($listener, $context, $service,,) = $this->getListener();

        $context
            ->expects($this->once())
            ->method('getToken')
            ->will($this->returnValue(null))
        ;

        $service
            ->expects($this->once())
            ->method('autoLogin')
            ->will($this->returnValue(null))
        ;

        $event = $this->getGetResponseEvent();
        $event
            ->expects($this->once())
            ->method('getRequest')
            ->will($this->returnValue(new Request()))
        ;

        $this->assertNull($listener->handle($event));
    }

    public function testOnCoreSecurityIgnoresAuthenticationExceptionThrownByAuthenticationManagerImplementation()
    {
        list($listener, $context, $service, $manager,) = $this->getListener();

        $context
            ->expects($this->once())
            ->method('getToken')
            ->will($this->returnValue(null))
        ;

        $service
            ->expects($this->once())
            ->method('autoLogin')
            ->will($this->returnValue($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')))
        ;

        $service
            ->expects($this->once())
            ->method('loginFail')
        ;

        $exception = new AuthenticationException('Authentication failed.');
        $manager
            ->expects($this->once())
            ->method('authenticate')
            ->will($this->throwException($exception))
        ;

        $event = $this->getGetResponseEvent();
        $event
            ->expects($this->once())
            ->method('getRequest')
            ->will($this->returnValue(new Request()))
        ;

        $listener->handle($event);
    }

    public function testOnCoreSecurity()
    {
        list($listener, $context, $service, $manager,) = $this->getListener();

        $context
            ->expects($this->once())
            ->method('getToken')
            ->will($this->returnValue(null))
        ;

        $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
        $service
            ->expects($this->once())
            ->method('autoLogin')
            ->will($this->returnValue($token))
        ;

        $context
            ->expects($this->once())
            ->method('setToken')
            ->with($this->equalTo($token))
        ;

        $manager
            ->expects($this->once())
            ->method('authenticate')
            ->will($this->returnValue($token))
        ;

        $event = $this->getGetResponseEvent();
        $event
            ->expects($this->once())
            ->method('getRequest')
            ->will($this->returnValue(new Request()))
        ;

        $listener->handle($event);
    }

    protected function getGetResponseEvent()
    {
        return $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false);
    }

    protected function getFilterResponseEvent()
    {
        return $this->getMock('Symfony\Component\HttpKernel\Event\FilterResponseEvent', array(), array(), '', false);
    }

    protected function getListener()
    {
        $listener = new RememberMeListener(
            $context = $this->getContext(),
            $service = $this->getService(),
            $manager = $this->getManager(),
            $logger = $this->getLogger()
        );

        return array($listener, $context, $service, $manager, $logger);
    }

    protected function getLogger()
    {
        return $this->getMock('Psr\Log\LoggerInterface');
    }

    protected function getManager()
    {
        return $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface');
    }

    protected function getService()
    {
        return $this->getMock('Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface');
    }

    protected function getContext()
    {
        return $this->getMockBuilder('Symfony\Component\Security\Core\SecurityContext')
                    ->disableOriginalConstructor()
                    ->getMock();
    }
}
PK��Z�G��

Ttest/Security/Symfony/Component/Security/Http/Tests/Firewall/ChannelListenerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Tests\Firewall;

use Symfony\Component\Security\Http\Firewall\ChannelListener;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpFoundation\Response;

class ChannelListenerTest extends \PHPUnit_Framework_TestCase
{
    public function testHandleWithNotSecuredRequestAndHttpChannel()
    {
        $request = $this->getMock('Symfony\Component\HttpFoundation\Request', array(), array(), '', false, false);
        $request
            ->expects($this->any())
            ->method('isSecure')
            ->will($this->returnValue(false))
        ;

        $accessMap = $this->getMock('Symfony\Component\Security\Http\AccessMapInterface');
        $accessMap
            ->expects($this->any())
            ->method('getPatterns')
            ->with($this->equalTo($request))
            ->will($this->returnValue(array(array(), 'http')))
        ;

        $entryPoint = $this->getMock('Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface');
        $entryPoint
            ->expects($this->never())
            ->method('start')
        ;

        $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false);
        $event
            ->expects($this->any())
            ->method('getRequest')
            ->will($this->returnValue($request))
        ;
        $event
            ->expects($this->never())
            ->method('setResponse')
        ;

        $listener = new ChannelListener($accessMap, $entryPoint);
        $listener->handle($event);
    }

    public function testHandleWithSecuredRequestAndHttpsChannel()
    {
        $request = $this->getMock('Symfony\Component\HttpFoundation\Request', array(), array(), '', false, false);
        $request
            ->expects($this->any())
            ->method('isSecure')
            ->will($this->returnValue(true))
        ;

        $accessMap = $this->getMock('Symfony\Component\Security\Http\AccessMapInterface');
        $accessMap
            ->expects($this->any())
            ->method('getPatterns')
            ->with($this->equalTo($request))
            ->will($this->returnValue(array(array(), 'https')))
        ;

        $entryPoint = $this->getMock('Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface');
        $entryPoint
            ->expects($this->never())
            ->method('start')
        ;

        $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false);
        $event
            ->expects($this->any())
            ->method('getRequest')
            ->will($this->returnValue($request))
        ;
        $event
            ->expects($this->never())
            ->method('setResponse')
        ;

        $listener = new ChannelListener($accessMap, $entryPoint);
        $listener->handle($event);
    }

    public function testHandleWithNotSecuredRequestAndHttpsChannel()
    {
        $request = $this->getMock('Symfony\Component\HttpFoundation\Request', array(), array(), '', false, false);
        $request
            ->expects($this->any())
            ->method('isSecure')
            ->will($this->returnValue(false))
        ;

        $response = new Response();

        $accessMap = $this->getMock('Symfony\Component\Security\Http\AccessMapInterface');
        $accessMap
            ->expects($this->any())
            ->method('getPatterns')
            ->with($this->equalTo($request))
            ->will($this->returnValue(array(array(), 'https')))
        ;

        $entryPoint = $this->getMock('Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface');
        $entryPoint
            ->expects($this->once())
            ->method('start')
            ->with($this->equalTo($request))
            ->will($this->returnValue($response))
        ;

        $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false);
        $event
            ->expects($this->any())
            ->method('getRequest')
            ->will($this->returnValue($request))
        ;
        $event
            ->expects($this->once())
            ->method('setResponse')
            ->with($this->equalTo($response))
        ;

        $listener = new ChannelListener($accessMap, $entryPoint);
        $listener->handle($event);
    }

    public function testHandleWithSecuredRequestAndHttpChannel()
    {
        $request = $this->getMock('Symfony\Component\HttpFoundation\Request', array(), array(), '', false, false);
        $request
            ->expects($this->any())
            ->method('isSecure')
            ->will($this->returnValue(true))
        ;

        $response = new Response();

        $accessMap = $this->getMock('Symfony\Component\Security\Http\AccessMapInterface');
        $accessMap
            ->expects($this->any())
            ->method('getPatterns')
            ->with($this->equalTo($request))
            ->will($this->returnValue(array(array(), 'http')))
        ;

        $entryPoint = $this->getMock('Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface');
        $entryPoint
            ->expects($this->once())
            ->method('start')
            ->with($this->equalTo($request))
            ->will($this->returnValue($response))
        ;

        $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false);
        $event
            ->expects($this->any())
            ->method('getRequest')
            ->will($this->returnValue($request))
        ;
        $event
            ->expects($this->once())
            ->method('setResponse')
            ->with($this->equalTo($response))
        ;

        $listener = new ChannelListener($accessMap, $entryPoint);
        $listener->handle($event);
    }
}
PK��Z�e��
�
dtest/Security/Symfony/Component/Security/Http/Tests/Firewall/AnonymousAuthenticationListenerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Tests\Firewall;

use Symfony\Component\Security\Http\Firewall\AnonymousAuthenticationListener;

class AnonymousAuthenticationListenerTest extends \PHPUnit_Framework_TestCase
{
    public function testHandleWithContextHavingAToken()
    {
        $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
        $context
            ->expects($this->any())
            ->method('getToken')
            ->will($this->returnValue($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')))
        ;
        $context
            ->expects($this->never())
            ->method('setToken')
        ;

        $listener = new AnonymousAuthenticationListener($context, 'TheKey');
        $listener->handle($this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false));
    }

    public function testHandleWithContextHavingNoToken()
    {
        $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
        $context
            ->expects($this->any())
            ->method('getToken')
            ->will($this->returnValue(null))
        ;
        $context
            ->expects($this->once())
            ->method('setToken')
            ->with(self::logicalAnd(
                $this->isInstanceOf('Symfony\Component\Security\Core\Authentication\Token\AnonymousToken'),
                $this->attributeEqualTo('key', 'TheKey')
            ))
        ;

        $listener = new AnonymousAuthenticationListener($context, 'TheKey');
        $listener->handle($this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false));
    }

    public function testHandledEventIsLogged()
    {
        if (!interface_exists('Psr\Log\LoggerInterface')) {
            $this->markTestSkipped('The "LoggerInterface" is not available');
        }

        $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
        $logger = $this->getMock('Psr\Log\LoggerInterface');
        $logger->expects($this->once())
            ->method('info')
            ->with('Populated SecurityContext with an anonymous Token')
        ;

        $listener = new AnonymousAuthenticationListener($context, 'TheKey', $logger);
        $listener->handle($this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false));
    }
}
PK��Z��K�$$`test/Security/Symfony/Component/Security/Http/Tests/Firewall/BasicAuthenticationListenerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Tests\Firewall;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Http\Firewall\BasicAuthenticationListener;
use Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager;

class BasicAuthenticationListenerTest extends \PHPUnit_Framework_TestCase
{
    public function testHandleWithValidUsernameAndPasswordServerParameters()
    {
        $request = new Request(array(), array(), array(), array(), array(), array(
            'PHP_AUTH_USER' => 'TheUsername',
            'PHP_AUTH_PW'   => 'ThePassword'
        ));

        $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');

        $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
        $context
            ->expects($this->any())
            ->method('getToken')
            ->will($this->returnValue(null))
        ;
        $context
            ->expects($this->once())
            ->method('setToken')
            ->with($this->equalTo($token))
        ;

        $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface');
        $authenticationManager
            ->expects($this->once())
            ->method('authenticate')
            ->with($this->isInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken'))
            ->will($this->returnValue($token))
        ;

        $listener = new BasicAuthenticationListener(
            $context,
            $authenticationManager,
            'TheProviderKey',
            $this->getMock('Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface')
        );

        $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false);
        $event
            ->expects($this->any())
            ->method('getRequest')
            ->will($this->returnValue($request))
        ;

        $listener->handle($event);
    }

    public function testHandleWhenAuthenticationFails()
    {
        $request = new Request(array(), array(), array(), array(), array(), array(
            'PHP_AUTH_USER' => 'TheUsername',
            'PHP_AUTH_PW'   => 'ThePassword'
        ));

        $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');

        $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
        $context
            ->expects($this->any())
            ->method('getToken')
            ->will($this->returnValue(null))
        ;
        $context
            ->expects($this->never())
            ->method('setToken')
        ;

        $response = new Response();

        $authenticationEntryPoint = $this->getMock('Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface');
        $authenticationEntryPoint
            ->expects($this->any())
            ->method('start')
            ->with($this->equalTo($request), $this->isInstanceOf('Symfony\Component\Security\Core\Exception\AuthenticationException'))
            ->will($this->returnValue($response))
        ;

        $listener = new BasicAuthenticationListener(
            $context,
            new AuthenticationProviderManager(array($this->getMock('Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface'))),
            'TheProviderKey',
            $authenticationEntryPoint
        );

        $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false);
        $event
            ->expects($this->any())
            ->method('getRequest')
            ->will($this->returnValue($request))
        ;
        $event
            ->expects($this->once())
            ->method('setResponse')
            ->with($this->equalTo($response))
        ;

        $listener->handle($event);
    }

    public function testHandleWithNoUsernameServerParameter()
    {
        $request = new Request();

        $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
        $context
            ->expects($this->never())
            ->method('getToken')
        ;

        $listener = new BasicAuthenticationListener(
            $context,
            $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'),
            'TheProviderKey',
            $this->getMock('Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface')
        );

        $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false);
        $event
            ->expects($this->any())
            ->method('getRequest')
            ->will($this->returnValue($request))
        ;

        $listener->handle($event);
    }

    public function testHandleWithASimilarAuthenticatedToken()
    {
        $request = new Request(array(), array(), array(), array(), array(), array('PHP_AUTH_USER' => 'TheUsername'));

        $token = new UsernamePasswordToken('TheUsername', 'ThePassword', 'TheProviderKey', array('ROLE_FOO'));

        $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
        $context
            ->expects($this->any())
            ->method('getToken')
            ->will($this->returnValue($token))
        ;

        $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface');
        $authenticationManager
            ->expects($this->never())
            ->method('authenticate')
        ;

        $listener = new BasicAuthenticationListener(
            $context,
            $authenticationManager,
            'TheProviderKey',
            $this->getMock('Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface')
        );

        $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false);
        $event
            ->expects($this->any())
            ->method('getRequest')
            ->will($this->returnValue($request))
        ;

        $listener->handle($event);
    }

    /**
     * @expectedException \InvalidArgumentException
     * @expectedExceptionMessage $providerKey must not be empty
     */
    public function testItRequiresProviderKey()
    {
        new BasicAuthenticationListener(
            $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'),
            $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'),
            '',
            $this->getMock('Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface')
        );
    }

    public function testHandleWithADifferentAuthenticatedToken()
    {
        $request = new Request(array(), array(), array(), array(), array(), array(
            'PHP_AUTH_USER' => 'TheUsername',
            'PHP_AUTH_PW'   => 'ThePassword'
        ));

        $token = new PreAuthenticatedToken('TheUser', 'TheCredentials', 'TheProviderKey', array('ROLE_FOO'));

        $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
        $context
            ->expects($this->any())
            ->method('getToken')
            ->will($this->returnValue($token))
        ;
        $context
            ->expects($this->never())
            ->method('setToken')
        ;

        $response = new Response();

        $authenticationEntryPoint = $this->getMock('Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface');
        $authenticationEntryPoint
            ->expects($this->any())
            ->method('start')
            ->with($this->equalTo($request), $this->isInstanceOf('Symfony\Component\Security\Core\Exception\AuthenticationException'))
            ->will($this->returnValue($response))
        ;

        $listener = new BasicAuthenticationListener(
            $context,
            new AuthenticationProviderManager(array($this->getMock('Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface'))),
            'TheProviderKey',
            $authenticationEntryPoint
        );

        $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false);
        $event
            ->expects($this->any())
            ->method('getRequest')
            ->will($this->returnValue($request))
        ;
        $event
            ->expects($this->once())
            ->method('setResponse')
            ->with($this->equalTo($response))
        ;

        $listener->handle($event);
    }
}
PK��Z��l���Otest/Security/Symfony/Component/Security/Http/Tests/Firewall/DigestDataTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Tests\Firewall;

use Symfony\Component\Security\Http\Firewall\DigestData;

class DigestDataTest extends \PHPUnit_Framework_TestCase
{
    public function testGetResponse()
    {
        $digestAuth = new DigestData(
            'username="user", realm="Welcome, robot!", ' .
            'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", ' .
            'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' .
            'response="b52938fc9e6d7c01be7702ece9031b42"'
        );

        $this->assertEquals('b52938fc9e6d7c01be7702ece9031b42', $digestAuth->getResponse());
    }

    public function testGetUsername()
    {
        $digestAuth = new DigestData(
            'username="user", realm="Welcome, robot!", ' .
            'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", ' .
            'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' .
            'response="b52938fc9e6d7c01be7702ece9031b42"'
        );

        $this->assertEquals('user', $digestAuth->getUsername());
    }

    public function testGetUsernameWithQuote()
    {
        $digestAuth = new DigestData(
            'username="\"user\"", realm="Welcome, robot!", ' .
            'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", ' .
            'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' .
            'response="b52938fc9e6d7c01be7702ece9031b42"'
        );

        $this->assertEquals('"user"', $digestAuth->getUsername());
    }

    public function testGetUsernameWithQuoteAndEscape()
    {
        $digestAuth = new DigestData(
            'username="\"u\\\\\"ser\"", realm="Welcome, robot!", ' .
            'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", ' .
            'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' .
            'response="b52938fc9e6d7c01be7702ece9031b42"'
        );

        $this->assertEquals('"u\\"ser"', $digestAuth->getUsername());
    }

    public function testGetUsernameWithSingleQuote()
    {
        $digestAuth = new DigestData(
            'username="\"u\'ser\"", realm="Welcome, robot!", ' .
            'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", ' .
            'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' .
            'response="b52938fc9e6d7c01be7702ece9031b42"'
        );

        $this->assertEquals('"u\'ser"', $digestAuth->getUsername());
    }

    public function testGetUsernameWithSingleQuoteAndEscape()
    {
        $digestAuth = new DigestData(
            'username="\"u\\\'ser\"", realm="Welcome, robot!", ' .
            'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", ' .
            'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' .
            'response="b52938fc9e6d7c01be7702ece9031b42"'
        );

        $this->assertEquals('"u\\\'ser"', $digestAuth->getUsername());
    }

    public function testGetUsernameWithEscape()
    {
        $digestAuth = new DigestData(
            'username="\"u\\ser\"", realm="Welcome, robot!", ' .
            'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", ' .
            'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' .
            'response="b52938fc9e6d7c01be7702ece9031b42"'
        );

        $this->assertEquals('"u\\ser"', $digestAuth->getUsername());
    }

    public function testValidateAndDecode()
    {
        $time = microtime(true);
        $key = 'ThisIsAKey';
        $nonce = base64_encode($time.':'.md5($time.':'.$key));

        $digestAuth = new DigestData(
            'username="user", realm="Welcome, robot!", nonce="'.$nonce.'", ' .
            'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' .
            'response="b52938fc9e6d7c01be7702ece9031b42"'
        );

        try {
            $digestAuth->validateAndDecode($key, 'Welcome, robot!');
        } catch (\Exception $e) {
            $this->fail(sprintf('testValidateAndDecode fail with message: %s', $e->getMessage()));
        }
    }

    public function testCalculateServerDigest()
    {
        $this->calculateServerDigest('user', 'Welcome, robot!', 'pass,word=password', 'ThisIsAKey', '00000001', 'MDIwODkz', 'auth', 'GET', '/path/info?p1=5&p2=5');
    }

    public function testCalculateServerDigestWithQuote()
    {
        $this->calculateServerDigest('\"user\"', 'Welcome, \"robot\"!', 'pass,word=password', 'ThisIsAKey', '00000001', 'MDIwODkz', 'auth', 'GET', '/path/info?p1=5&p2=5');
    }

    public function testCalculateServerDigestWithQuoteAndEscape()
    {
        $this->calculateServerDigest('\"u\\\\\"ser\"', 'Welcome, \"robot\"!', 'pass,word=password', 'ThisIsAKey', '00000001', 'MDIwODkz', 'auth', 'GET', '/path/info?p1=5&p2=5');
    }

    public function testCalculateServerDigestEscape()
    {
        $this->calculateServerDigest('\"u\\ser\"', 'Welcome, \"robot\"!', 'pass,word=password', 'ThisIsAKey', '00000001', 'MDIwODkz', 'auth', 'GET', '/path/info?p1=5&p2=5');
        $this->calculateServerDigest('\"u\\ser\\\\\"', 'Welcome, \"robot\"!', 'pass,word=password', 'ThisIsAKey', '00000001', 'MDIwODkz', 'auth', 'GET', '/path/info?p1=5&p2=5');
    }

    public function testIsNonceExpired()
    {
        $time = microtime(true) + 10;
        $key = 'ThisIsAKey';
        $nonce = base64_encode($time.':'.md5($time.':'.$key));

        $digestAuth = new DigestData(
            'username="user", realm="Welcome, robot!", nonce="'.$nonce.'", ' .
            'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' .
            'response="b52938fc9e6d7c01be7702ece9031b42"'
        );

        $digestAuth->validateAndDecode($key, 'Welcome, robot!');

        $this->assertFalse($digestAuth->isNonceExpired());
    }

    protected function setUp()
    {
        class_exists('Symfony\Component\Security\Http\Firewall\DigestAuthenticationListener', true);
    }

    private function calculateServerDigest($username, $realm, $password, $key, $nc, $cnonce, $qop, $method, $uri)
    {
        $time = microtime(true);
        $nonce = base64_encode($time.':'.md5($time.':'.$key));

        $response = md5(
            md5($username.':'.$realm.':'.$password).':'.$nonce.':'.$nc.':'.$cnonce.':'.$qop.':'.md5($method.':'.$uri)
        );

        $digest = sprintf('username="%s", realm="%s", nonce="%s", uri="%s", cnonce="%s", nc=%s, qop="%s", response="%s"',
            $username, $realm, $nonce, $uri, $cnonce, $nc, $qop, $response
        );

        $digestAuth = new DigestData($digest);

        $this->assertEquals($digestAuth->getResponse(), $digestAuth->calculateServerDigest($password, $method));
    }
}
PK��Zj�z9�"�"Ttest/Security/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Tests\Firewall;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\Security\Http\Firewall\ContextListener;

class ContextListenerTest extends \PHPUnit_Framework_TestCase
{
    protected function setUp()
    {
        $this->securityContext = new SecurityContext(
            $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'),
            $this->getMock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface')
        );
    }

    protected function tearDown()
    {
        unset($this->securityContext);
    }

    /**
     * @expectedException \InvalidArgumentException
     * @expectedExceptionMessage $contextKey must not be empty
     */
    public function testItRequiresContextKey()
    {
        new ContextListener(
            $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'),
            array(),
            ''
        );
    }

    /**
     * @expectedException \InvalidArgumentException
     * @expectedExceptionMessage User provider "stdClass" must implement "Symfony\Component\Security\Core\User\UserProviderInterface
     */
    public function testUserProvidersNeedToImplementAnInterface()
    {
        new ContextListener(
            $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'),
            array(new \stdClass()),
            'key123'
        );
    }

    public function testOnKernelResponseWillAddSession()
    {
        $session = $this->runSessionOnKernelResponse(
            new UsernamePasswordToken('test1', 'pass1', 'phpunit'),
            null
        );

        $token = unserialize($session->get('_security_session'));
        $this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', $token);
        $this->assertEquals('test1', $token->getUsername());
    }

    public function testOnKernelResponseWillReplaceSession()
    {
        $session = $this->runSessionOnKernelResponse(
            new UsernamePasswordToken('test1', 'pass1', 'phpunit'),
            'C:10:"serialized"'
        );

        $token = unserialize($session->get('_security_session'));
        $this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', $token);
        $this->assertEquals('test1', $token->getUsername());
    }

    public function testOnKernelResponseWillRemoveSession()
    {
        $session = $this->runSessionOnKernelResponse(
            null,
            'C:10:"serialized"'
        );

        $this->assertFalse($session->has('_security_session'));
    }

    public function testOnKernelResponseWithoutSession()
    {
        $this->securityContext->setToken(new UsernamePasswordToken('test1', 'pass1', 'phpunit'));
        $request = new Request();
        $session = new Session(new MockArraySessionStorage());
        $request->setSession($session);

        $event = new FilterResponseEvent(
            $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'),
            $request,
            HttpKernelInterface::MASTER_REQUEST,
            new Response()
        );

        $listener = new ContextListener($this->securityContext, array(), 'session');
        $listener->onKernelResponse($event);

        $this->assertTrue($session->isStarted());
    }

    public function testOnKernelResponseWithoutSessionNorToken()
    {
        $request = new Request();
        $session = new Session(new MockArraySessionStorage());
        $request->setSession($session);

        $event = new FilterResponseEvent(
            $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'),
            $request,
            HttpKernelInterface::MASTER_REQUEST,
            new Response()
        );

        $listener = new ContextListener($this->securityContext, array(), 'session');
        $listener->onKernelResponse($event);

        $this->assertFalse($session->isStarted());
    }

    /**
     * @dataProvider provideInvalidToken
     */
    public function testInvalidTokenInSession($token)
    {
        $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
        $event = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\GetResponseEvent')
            ->disableOriginalConstructor()
            ->getMock();
        $request = $this->getMock('Symfony\Component\HttpFoundation\Request');
        $session = $this->getMock('Symfony\Component\HttpFoundation\Session\SessionInterface');

        $event->expects($this->any())
            ->method('getRequest')
            ->will($this->returnValue($request));
        $request->expects($this->any())
            ->method('hasPreviousSession')
            ->will($this->returnValue(true));
        $request->expects($this->any())
            ->method('getSession')
            ->will($this->returnValue($session));
        $session->expects($this->any())
            ->method('get')
            ->with('_security_key123')
            ->will($this->returnValue($token));
        $context->expects($this->once())
            ->method('setToken')
            ->with(null);

        $listener = new ContextListener($context, array(), 'key123');
        $listener->handle($event);
    }

    public function provideInvalidToken()
    {
        return array(
            array(serialize(new \__PHP_Incomplete_Class())),
            array(serialize(null)),
            array(null)
        );
    }

    public function testHandleAddsKernelResponseListener()
    {
        $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
        $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
        $event = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\GetResponseEvent')
            ->disableOriginalConstructor()
            ->getMock();

        $listener = new ContextListener($context, array(), 'key123', null, $dispatcher);

        $event->expects($this->any())
            ->method('isMasterRequest')
            ->will($this->returnValue(true));
        $event->expects($this->any())
            ->method('getRequest')
            ->will($this->returnValue($this->getMock('Symfony\Component\HttpFoundation\Request')));

        $dispatcher->expects($this->once())
            ->method('addListener')
            ->with(KernelEvents::RESPONSE, array($listener, 'onKernelResponse'));

        $listener->handle($event);
    }

    public function testHandleRemovesTokenIfNoPreviousSessionWasFound()
    {
        $request = $this->getMock('Symfony\Component\HttpFoundation\Request');
        $request->expects($this->any())->method('hasPreviousSession')->will($this->returnValue(false));

        $event = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\GetResponseEvent')
            ->disableOriginalConstructor()
            ->getMock();
        $event->expects($this->any())->method('getRequest')->will($this->returnValue($request));

        $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
        $context->expects($this->once())->method('setToken')->with(null);

        $listener = new ContextListener($context, array(), 'key123');
        $listener->handle($event);
    }

    protected function runSessionOnKernelResponse($newToken, $original = null)
    {
        $session = new Session(new MockArraySessionStorage());

        if ($original !== null) {
            $session->set('_security_session', $original);
        }

        $this->securityContext->setToken($newToken);

        $request = new Request();
        $request->setSession($session);
        $request->cookies->set('MOCKSESSID', true);

        $event = new FilterResponseEvent(
            $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'),
            $request,
            HttpKernelInterface::MASTER_REQUEST,
            new Response()
        );

        $listener = new ContextListener($this->securityContext, array(), 'session');
        $listener->onKernelResponse($event);

        return $session;
    }
}
PK��Z<��%%etest/Security/Symfony/Component/Security/Http/Tests/Firewall/AbstractPreAuthenticatedListenerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Tests\Firewall;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\AuthenticationException;

class AbstractPreAuthenticatedListenerTest extends \PHPUnit_Framework_TestCase
{
    public function testHandleWithValidValues()
    {
        $userCredentials = array('TheUser', 'TheCredentials');

        $request = new Request(array(), array(), array(), array(), array(), array());

        $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');

        $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
        $context
            ->expects($this->any())
            ->method('getToken')
            ->will($this->returnValue(null))
        ;
        $context
            ->expects($this->once())
            ->method('setToken')
            ->with($this->equalTo($token))
        ;

        $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface');
        $authenticationManager
            ->expects($this->once())
            ->method('authenticate')
            ->with($this->isInstanceOf('Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken'))
            ->will($this->returnValue($token))
        ;

        $listener = $this->getMockForAbstractClass('Symfony\Component\Security\Http\Firewall\AbstractPreAuthenticatedListener', array(
            $context,
            $authenticationManager,
            'TheProviderKey'
        ));
        $listener
            ->expects($this->once())
            ->method('getPreAuthenticatedData')
            ->will($this->returnValue($userCredentials));

        $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false);
        $event
            ->expects($this->any())
            ->method('getRequest')
            ->will($this->returnValue($request))
        ;

        $listener->handle($event);
    }

    public function testHandleWhenAuthenticationFails()
    {
        $userCredentials = array('TheUser', 'TheCredentials');

        $request = new Request(array(), array(), array(), array(), array(), array());

        $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
        $context
            ->expects($this->any())
            ->method('getToken')
            ->will($this->returnValue(null))
        ;
        $context
            ->expects($this->never())
            ->method('setToken')
        ;

        $exception = new AuthenticationException('Authentication failed.');
        $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface');
        $authenticationManager
            ->expects($this->once())
            ->method('authenticate')
            ->with($this->isInstanceOf('Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken'))
            ->will($this->throwException($exception))
        ;

        $listener = $this->getMockForAbstractClass('Symfony\Component\Security\Http\Firewall\AbstractPreAuthenticatedListener', array(
            $context,
            $authenticationManager,
            'TheProviderKey'
        ));
        $listener
            ->expects($this->once())
            ->method('getPreAuthenticatedData')
            ->will($this->returnValue($userCredentials));

        $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false);
        $event
            ->expects($this->any())
            ->method('getRequest')
            ->will($this->returnValue($request))
        ;

        $listener->handle($event);
    }

    public function testHandleWhenAuthenticationFailsWithDifferentToken()
    {
        $userCredentials = array('TheUser', 'TheCredentials');

        $token = new UsernamePasswordToken('TheUsername', 'ThePassword', 'TheProviderKey', array('ROLE_FOO'));

        $request = new Request(array(), array(), array(), array(), array(), array());

        $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
        $context
            ->expects($this->any())
            ->method('getToken')
            ->will($this->returnValue($token))
        ;
        $context
            ->expects($this->never())
            ->method('setToken')
        ;

        $exception = new AuthenticationException('Authentication failed.');
        $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface');
        $authenticationManager
            ->expects($this->once())
            ->method('authenticate')
            ->with($this->isInstanceOf('Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken'))
            ->will($this->throwException($exception))
        ;

        $listener = $this->getMockForAbstractClass('Symfony\Component\Security\Http\Firewall\AbstractPreAuthenticatedListener', array(
            $context,
            $authenticationManager,
            'TheProviderKey'
        ));
        $listener
            ->expects($this->once())
            ->method('getPreAuthenticatedData')
            ->will($this->returnValue($userCredentials));

        $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false);
        $event
            ->expects($this->any())
            ->method('getRequest')
            ->will($this->returnValue($request))
        ;

        $listener->handle($event);
    }

    public function testHandleWithASimilarAuthenticatedToken()
    {
        $userCredentials = array('TheUser', 'TheCredentials');

        $request = new Request(array(), array(), array(), array(), array(), array());

        $token = new PreAuthenticatedToken('TheUser', 'TheCredentials', 'TheProviderKey', array('ROLE_FOO'));

        $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
        $context
            ->expects($this->any())
            ->method('getToken')
            ->will($this->returnValue($token))
        ;

        $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface');
        $authenticationManager
            ->expects($this->never())
            ->method('authenticate')
        ;

        $listener = $this->getMockForAbstractClass('Symfony\Component\Security\Http\Firewall\AbstractPreAuthenticatedListener', array(
            $context,
            $authenticationManager,
            'TheProviderKey'
        ));
        $listener
            ->expects($this->once())
            ->method('getPreAuthenticatedData')
            ->will($this->returnValue($userCredentials));

        $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false);
        $event
            ->expects($this->any())
            ->method('getRequest')
            ->will($this->returnValue($request))
        ;

        $listener->handle($event);
    }

    public function testHandleWithAnInvalidSimilarToken()
    {
        $userCredentials = array('TheUser', 'TheCredentials');

        $request = new Request(array(), array(), array(), array(), array(), array());

        $token = new PreAuthenticatedToken('AnotherUser', 'TheCredentials', 'TheProviderKey', array('ROLE_FOO'));

        $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
        $context
            ->expects($this->any())
            ->method('getToken')
            ->will($this->returnValue($token))
        ;
        $context
            ->expects($this->once())
            ->method('setToken')
            ->with($this->equalTo(null))
        ;

        $exception = new AuthenticationException('Authentication failed.');
        $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface');
        $authenticationManager
            ->expects($this->once())
            ->method('authenticate')
            ->with($this->isInstanceOf('Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken'))
            ->will($this->throwException($exception))
        ;

        $listener = $this->getMockForAbstractClass('Symfony\Component\Security\Http\Firewall\AbstractPreAuthenticatedListener', array(
            $context,
            $authenticationManager,
            'TheProviderKey'
        ));
        $listener
            ->expects($this->once())
            ->method('getPreAuthenticatedData')
            ->will($this->returnValue($userCredentials));

        $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false);
        $event
            ->expects($this->any())
            ->method('getRequest')
            ->will($this->returnValue($request))
        ;

        $listener->handle($event);
    }
}
PK��Zq���Stest/Security/Symfony/Component/Security/Http/Tests/Firewall/AccessListenerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Tests\Firewall;

use Symfony\Component\Security\Http\Firewall\AccessListener;

class AccessListenerTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\AccessDeniedException
     */
    public function testHandleWhenTheAccessDecisionManagerDecidesToRefuseAccess()
    {
        $request = $this->getMock('Symfony\Component\HttpFoundation\Request', array(), array(), '', false, false);

        $accessMap = $this->getMock('Symfony\Component\Security\Http\AccessMapInterface');
        $accessMap
            ->expects($this->any())
            ->method('getPatterns')
            ->with($this->equalTo($request))
            ->will($this->returnValue(array(array('foo' => 'bar'), null)))
        ;

        $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
        $token
            ->expects($this->any())
            ->method('isAuthenticated')
            ->will($this->returnValue(true))
        ;

        $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
        $context
            ->expects($this->any())
            ->method('getToken')
            ->will($this->returnValue($token))
        ;

        $accessDecisionManager = $this->getMock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface');
        $accessDecisionManager
            ->expects($this->once())
            ->method('decide')
            ->with($this->equalTo($token), $this->equalTo(array('foo' => 'bar')), $this->equalTo($request))
            ->will($this->returnValue(false))
        ;

        $listener = new AccessListener(
            $context,
            $accessDecisionManager,
            $accessMap,
            $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface')
        );

        $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false);
        $event
            ->expects($this->any())
            ->method('getRequest')
            ->will($this->returnValue($request))
        ;

        $listener->handle($event);
    }

    public function testHandleWhenTheTokenIsNotAuthenticated()
    {
        $request = $this->getMock('Symfony\Component\HttpFoundation\Request', array(), array(), '', false, false);

        $accessMap = $this->getMock('Symfony\Component\Security\Http\AccessMapInterface');
        $accessMap
            ->expects($this->any())
            ->method('getPatterns')
            ->with($this->equalTo($request))
            ->will($this->returnValue(array(array('foo' => 'bar'), null)))
        ;

        $notAuthenticatedToken = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
        $notAuthenticatedToken
            ->expects($this->any())
            ->method('isAuthenticated')
            ->will($this->returnValue(false))
        ;

        $authenticatedToken = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
        $authenticatedToken
            ->expects($this->any())
            ->method('isAuthenticated')
            ->will($this->returnValue(true))
        ;

        $authManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface');
        $authManager
            ->expects($this->once())
            ->method('authenticate')
            ->with($this->equalTo($notAuthenticatedToken))
            ->will($this->returnValue($authenticatedToken))
        ;

        $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
        $context
            ->expects($this->any())
            ->method('getToken')
            ->will($this->returnValue($notAuthenticatedToken))
        ;
        $context
            ->expects($this->once())
            ->method('setToken')
            ->with($this->equalTo($authenticatedToken))
        ;

        $accessDecisionManager = $this->getMock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface');
        $accessDecisionManager
            ->expects($this->once())
            ->method('decide')
            ->with($this->equalTo($authenticatedToken), $this->equalTo(array('foo' => 'bar')), $this->equalTo($request))
            ->will($this->returnValue(true))
        ;

        $listener = new AccessListener(
            $context,
            $accessDecisionManager,
            $accessMap,
            $authManager
        );

        $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false);
        $event
            ->expects($this->any())
            ->method('getRequest')
            ->will($this->returnValue($request))
        ;

        $listener->handle($event);
    }

    public function testHandleWhenThereIsNoAccessMapEntryMatchingTheRequest()
    {
        $request = $this->getMock('Symfony\Component\HttpFoundation\Request', array(), array(), '', false, false);

        $accessMap = $this->getMock('Symfony\Component\Security\Http\AccessMapInterface');
        $accessMap
            ->expects($this->any())
            ->method('getPatterns')
            ->with($this->equalTo($request))
            ->will($this->returnValue(array(null, null)))
        ;

        $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
        $token
            ->expects($this->never())
            ->method('isAuthenticated')
        ;

        $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
        $context
            ->expects($this->any())
            ->method('getToken')
            ->will($this->returnValue($token))
        ;

        $listener = new AccessListener(
            $context,
            $this->getMock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface'),
            $accessMap,
            $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface')
        );

        $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false);
        $event
            ->expects($this->any())
            ->method('getRequest')
            ->will($this->returnValue($request))
        ;

        $listener->handle($event);
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException
     */
    public function testHandleWhenTheSecurityContextHasNoToken()
    {
        $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
        $context
            ->expects($this->any())
            ->method('getToken')
            ->will($this->returnValue(null))
        ;

        $listener = new AccessListener(
            $context,
            $this->getMock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface'),
            $this->getMock('Symfony\Component\Security\Http\AccessMapInterface'),
            $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface')
        );

        $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false);

        $listener->handle($event);
    }
}
PK��Z�V�k��Stest/Security/Symfony/Component/Security/Http/Tests/Firewall/LogoutListenerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Tests\Firewall;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Http\Firewall\LogoutListener;

class LogoutListenerTest extends \PHPUnit_Framework_TestCase
{
    public function testHandleUnmatchedPath()
    {
        list($listener, $context, $httpUtils, $options) = $this->getListener();

        list($event, $request) = $this->getGetResponseEvent();

        $event->expects($this->never())
            ->method('setResponse');

        $httpUtils->expects($this->once())
            ->method('checkRequestPath')
            ->with($request, $options['logout_path'])
            ->will($this->returnValue(false));

        $listener->handle($event);
    }

    public function testHandleMatchedPathWithSuccessHandlerAndCsrfValidation()
    {
        $successHandler = $this->getSuccessHandler();
        $tokenManager = $this->getTokenManager();

        list($listener, $context, $httpUtils, $options) = $this->getListener($successHandler, $tokenManager);

        list($event, $request) = $this->getGetResponseEvent();

        $request->query->set('_csrf_token', 'token');

        $httpUtils->expects($this->once())
            ->method('checkRequestPath')
            ->with($request, $options['logout_path'])
            ->will($this->returnValue(true));

        $tokenManager->expects($this->once())
            ->method('isTokenValid')
            ->will($this->returnValue(true));

        $successHandler->expects($this->once())
            ->method('onLogoutSuccess')
            ->with($request)
            ->will($this->returnValue($response = new Response()));

        $context->expects($this->once())
            ->method('getToken')
            ->will($this->returnValue($token = $this->getToken()));

        $handler = $this->getHandler();
        $handler->expects($this->once())
            ->method('logout')
            ->with($request, $response, $token);

        $context->expects($this->once())
            ->method('setToken')
            ->with(null);

        $event->expects($this->once())
            ->method('setResponse')
            ->with($response);

        $listener->addHandler($handler);

        $listener->handle($event);
    }

    public function testHandleMatchedPathWithoutSuccessHandlerAndCsrfValidation()
    {
        $successHandler = $this->getSuccessHandler();

        list($listener, $context, $httpUtils, $options) = $this->getListener($successHandler);

        list($event, $request) = $this->getGetResponseEvent();

        $httpUtils->expects($this->once())
            ->method('checkRequestPath')
            ->with($request, $options['logout_path'])
            ->will($this->returnValue(true));

        $successHandler->expects($this->once())
            ->method('onLogoutSuccess')
            ->with($request)
            ->will($this->returnValue($response = new Response()));

        $context->expects($this->once())
            ->method('getToken')
            ->will($this->returnValue($token = $this->getToken()));

        $handler = $this->getHandler();
        $handler->expects($this->once())
            ->method('logout')
            ->with($request, $response, $token);

        $context->expects($this->once())
            ->method('setToken')
            ->with(null);

        $event->expects($this->once())
            ->method('setResponse')
            ->with($response);

        $listener->addHandler($handler);

        $listener->handle($event);
    }

    /**
     * @expectedException \RuntimeException
     */
    public function testSuccessHandlerReturnsNonResponse()
    {
        $successHandler = $this->getSuccessHandler();

        list($listener, $context, $httpUtils, $options) = $this->getListener($successHandler);

        list($event, $request) = $this->getGetResponseEvent();

        $httpUtils->expects($this->once())
            ->method('checkRequestPath')
            ->with($request, $options['logout_path'])
            ->will($this->returnValue(true));

        $successHandler->expects($this->once())
            ->method('onLogoutSuccess')
            ->with($request)
            ->will($this->returnValue(null));

        $listener->handle($event);
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\LogoutException
     */
    public function testCsrfValidationFails()
    {
        $tokenManager = $this->getTokenManager();

        list($listener, $context, $httpUtils, $options) = $this->getListener(null, $tokenManager);

        list($event, $request) = $this->getGetResponseEvent();

        $request->query->set('_csrf_token', 'token');

        $httpUtils->expects($this->once())
            ->method('checkRequestPath')
            ->with($request, $options['logout_path'])
            ->will($this->returnValue(true));

        $tokenManager->expects($this->once())
            ->method('isTokenValid')
            ->will($this->returnValue(false));

        $listener->handle($event);
    }

    private function getTokenManager()
    {
        return $this->getMock('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface');
    }

    private function getContext()
    {
        return $this->getMockBuilder('Symfony\Component\Security\Core\SecurityContext')
            ->disableOriginalConstructor()
            ->getMock();
    }

    private function getGetResponseEvent()
    {
        $event = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\GetResponseEvent')
            ->disableOriginalConstructor()
            ->getMock();

        $event->expects($this->any())
            ->method('getRequest')
            ->will($this->returnValue($request = new Request()));

        return array($event, $request);
    }

    private function getHandler()
    {
        return $this->getMock('Symfony\Component\Security\Http\Logout\LogoutHandlerInterface');
    }

    private function getHttpUtils()
    {
        return $this->getMockBuilder('Symfony\Component\Security\Http\HttpUtils')
            ->disableOriginalConstructor()
            ->getMock();
    }

    private function getListener($successHandler = null, $tokenManager = null)
    {
        $listener = new LogoutListener(
            $context = $this->getContext(),
            $httpUtils = $this->getHttpUtils(),
            $successHandler ?: $this->getSuccessHandler(),
            $options = array(
                'csrf_parameter' => '_csrf_token',
                'intention'      => 'logout',
                'logout_path'    => '/logout',
                'target_url'     => '/',
            ),
            $tokenManager
        );

        return array($listener, $context, $httpUtils, $options);
    }

    private function getSuccessHandler()
    {
        return $this->getMock('Symfony\Component\Security\Http\Logout\LogoutSuccessHandlerInterface');
    }

    private function getToken()
    {
        return $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
    }
}
PK��Z���@&@&Wtest/Security/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Tests\Firewall;

use Symfony\Component\Security\Http\Firewall\SwitchUserListener;

class SwitchUserListenerTest extends \PHPUnit_Framework_TestCase
{
    private $securityContext;

    private $userProvider;

    private $userChecker;

    private $accessDecisionManager;

    private $request;

    private $event;

    protected function setUp()
    {
        $this->securityContext = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
        $this->userProvider = $this->getMock('Symfony\Component\Security\Core\User\UserProviderInterface');
        $this->userChecker = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface');
        $this->accessDecisionManager = $this->getMock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface');
        $this->request = $this->getMock('Symfony\Component\HttpFoundation\Request');
        $this->request->query = $this->getMock('Symfony\Component\HttpFoundation\ParameterBag');
        $this->request->server = $this->getMock('Symfony\Component\HttpFoundation\ServerBag');
        $this->event = $this->getEvent($this->request);
    }

    /**
     * @expectedException \InvalidArgumentException
     * @expectedExceptionMessage $providerKey must not be empty
     */
    public function testProviderKeyIsRequired()
    {
        new SwitchUserListener($this->securityContext, $this->userProvider, $this->userChecker, '', $this->accessDecisionManager);
    }

    public function testEventIsIgnoredIfUsernameIsNotPassedWithTheRequest()
    {
        $this->request->expects($this->any())->method('get')->with('_switch_user')->will($this->returnValue(null));

        $this->event->expects($this->never())->method('setResponse');
        $this->securityContext->expects($this->never())->method('setToken');

        $listener = new SwitchUserListener($this->securityContext, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager);
        $listener->handle($this->event);
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException
     */
    public function testExitUserThrowsAuthenticationExceptionIfOriginalTokenCannotBeFound()
    {
        $token = $this->getToken(array($this->getMock('Symfony\Component\Security\Core\Role\RoleInterface')));

        $this->securityContext->expects($this->any())->method('getToken')->will($this->returnValue($token));
        $this->request->expects($this->any())->method('get')->with('_switch_user')->will($this->returnValue('_exit'));

        $listener = new SwitchUserListener($this->securityContext, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager);
        $listener->handle($this->event);
    }

    public function testExitUserUpdatesToken()
    {
        $originalToken = $this->getToken();
        $role = $this->getMockBuilder('Symfony\Component\Security\Core\Role\SwitchUserRole')
            ->disableOriginalConstructor()
            ->getMock();
        $role->expects($this->any())->method('getSource')->will($this->returnValue($originalToken));

        $this->securityContext->expects($this->any())
            ->method('getToken')
            ->will($this->returnValue($this->getToken(array($role))));

        $this->request->expects($this->any())->method('get')->with('_switch_user')->will($this->returnValue('_exit'));
        $this->request->expects($this->any())->method('getUri')->will($this->returnValue('/'));
        $this->request->query->expects($this->once())->method('remove','_switch_user');
        $this->request->query->expects($this->any())->method('all')->will($this->returnValue(array()));
        $this->request->server->expects($this->once())->method('set')->with('QUERY_STRING', '');

        $this->securityContext->expects($this->once())
            ->method('setToken')->with($originalToken);
        $this->event->expects($this->once())
            ->method('setResponse')->with($this->isInstanceOf('Symfony\Component\HttpFoundation\RedirectResponse'));

        $listener = new SwitchUserListener($this->securityContext, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager);
        $listener->handle($this->event);
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\AccessDeniedException
     */
    public function testSwitchUserIsDissallowed()
    {
        $token = $this->getToken(array($this->getMock('Symfony\Component\Security\Core\Role\RoleInterface')));

        $this->securityContext->expects($this->any())->method('getToken')->will($this->returnValue($token));
        $this->request->expects($this->any())->method('get')->with('_switch_user')->will($this->returnValue('kuba'));

        $this->accessDecisionManager->expects($this->once())
            ->method('decide')->with($token, array('ROLE_ALLOWED_TO_SWITCH'))
            ->will($this->returnValue(false));

        $listener = new SwitchUserListener($this->securityContext, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager);
        $listener->handle($this->event);
    }

    public function testSwitchUser()
    {
        $token = $this->getToken(array($this->getMock('Symfony\Component\Security\Core\Role\RoleInterface')));
        $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
        $user->expects($this->any())->method('getRoles')->will($this->returnValue(array()));

        $this->securityContext->expects($this->any())->method('getToken')->will($this->returnValue($token));
        $this->request->expects($this->any())->method('get')->with('_switch_user')->will($this->returnValue('kuba'));
        $this->request->query->expects($this->once())->method('remove','_switch_user');
        $this->request->query->expects($this->any())->method('all')->will($this->returnValue(array()));

        $this->request->expects($this->any())->method('getUri')->will($this->returnValue('/'));
        $this->request->server->expects($this->once())->method('set')->with('QUERY_STRING', '');

        $this->accessDecisionManager->expects($this->once())
            ->method('decide')->with($token, array('ROLE_ALLOWED_TO_SWITCH'))
            ->will($this->returnValue(true));

        $this->userProvider->expects($this->once())
            ->method('loadUserByUsername')->with('kuba')
            ->will($this->returnValue($user));
        $this->userChecker->expects($this->once())
            ->method('checkPostAuth')->with($user);
        $this->securityContext->expects($this->once())
            ->method('setToken')->with($this->isInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken'));

        $listener = new SwitchUserListener($this->securityContext, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager);
        $listener->handle($this->event);
    }

    public function testSwitchUserKeepsOtherQueryStringParameters()
    {
        $token = $this->getToken(array($this->getMock('Symfony\Component\Security\Core\Role\RoleInterface')));
        $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
        $user->expects($this->any())->method('getRoles')->will($this->returnValue(array()));

        $this->securityContext->expects($this->any())->method('getToken')->will($this->returnValue($token));
        $this->request->expects($this->any())->method('get')->with('_switch_user')->will($this->returnValue('kuba'));
        $this->request->query->expects($this->once())->method('remove','_switch_user');
        $this->request->query->expects($this->any())->method('all')->will($this->returnValue(array('page'=>3,'section'=>2)));
        $this->request->expects($this->any())->method('getUri')->will($this->returnValue('/'));
        $this->request->server->expects($this->once())->method('set')->with('QUERY_STRING', 'page=3&section=2');

        $this->accessDecisionManager->expects($this->once())
            ->method('decide')->with($token, array('ROLE_ALLOWED_TO_SWITCH'))
            ->will($this->returnValue(true));

        $this->userProvider->expects($this->once())
            ->method('loadUserByUsername')->with('kuba')
            ->will($this->returnValue($user));
        $this->userChecker->expects($this->once())
            ->method('checkPostAuth')->with($user);
        $this->securityContext->expects($this->once())
            ->method('setToken')->with($this->isInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken'));

        $listener = new SwitchUserListener($this->securityContext, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager);
        $listener->handle($this->event);
    }

    private function getEvent($request)
    {
        $event = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\GetResponseEvent')
            ->disableOriginalConstructor()
            ->getMock();

        $event->expects($this->any())
            ->method('getRequest')
            ->will($this->returnValue($request));

        return $event;
    }

    private function getToken(array $roles = array())
    {
        $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
        $token->expects($this->any())
            ->method('getRoles')
            ->will($this->returnValue($roles));

        return $token;
    }
}
PK��Z�LMM_test/Security/Symfony/Component/Security/Http/Tests/Firewall/X509AuthenticationListenerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Tests\Firewall;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Http\Firewall\X509AuthenticationListener;

class X509AuthenticationListenerTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider dataProviderGetPreAuthenticatedData
     */
    public function testGetPreAuthenticatedData($user, $credentials)
    {
        $serverVars = array();
        if ('' !== $user) {
            $serverVars['SSL_CLIENT_S_DN_Email'] = $user;
        }
        if ('' !== $credentials) {
            $serverVars['SSL_CLIENT_S_DN'] = $credentials;
        }

        $request = new Request(array(), array(), array(), array(), array(), $serverVars);

        $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');

        $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface');

        $listener = new X509AuthenticationListener(
            $context,
            $authenticationManager,
            'TheProviderKey'
        );

        $method = new \ReflectionMethod($listener, 'getPreAuthenticatedData');
        $method->setAccessible(true);

        $result = $method->invokeArgs($listener, array($request));
        $this->assertSame($result, array($user, $credentials));
    }

    public static function dataProviderGetPreAuthenticatedData()
    {
        return array(
            'validValues' => array('TheUser', 'TheCredentials'),
            'noCredentials' => array('TheUser', ''),
        );
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
     */
    public function testGetPreAuthenticatedDataNoUser()
    {
        $request = new Request(array(), array(), array(), array(), array(), array());

        $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');

        $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface');

        $listener = new X509AuthenticationListener(
            $context,
            $authenticationManager,
            'TheProviderKey'
        );

        $method = new \ReflectionMethod($listener, 'getPreAuthenticatedData');
        $method->setAccessible(true);

        $result = $method->invokeArgs($listener, array($request));
    }

    public function testGetPreAuthenticatedDataWithDifferentKeys()
    {
        $userCredentials = array('TheUser', 'TheCredentials');

        $request = new Request(array(), array(), array(), array(), array(), array(
            'TheUserKey' => 'TheUser',
            'TheCredentialsKey' => 'TheCredentials'
        ));
        $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');

        $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface');

        $listener = new X509AuthenticationListener(
            $context,
            $authenticationManager,
            'TheProviderKey',
            'TheUserKey',
            'TheCredentialsKey'
        );

        $method = new \ReflectionMethod($listener, 'getPreAuthenticatedData');
        $method->setAccessible(true);

        $result = $method->invokeArgs($listener, array($request));
        $this->assertSame($result, $userCredentials);
    }
}
PK��Zx��W��Etest/Security/Symfony/Component/Security/Http/Tests/AccessMapTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Tests;

use Symfony\Component\Security\Http\AccessMap;

class AccessMapTest extends \PHPUnit_Framework_TestCase
{
    public function testReturnsFirstMatchedPattern()
    {
        $request = $this->getMock('Symfony\Component\HttpFoundation\Request');
        $requestMatcher1 = $this->getRequestMatcher($request, false);
        $requestMatcher2 = $this->getRequestMatcher($request, true);

        $map = new AccessMap();
        $map->add($requestMatcher1, array('ROLE_ADMIN'), 'http');
        $map->add($requestMatcher2, array('ROLE_USER'), 'https');

        $this->assertSame(array(array('ROLE_USER'), 'https'), $map->getPatterns($request));
    }

    public function testReturnsEmptyPatternIfNoneMatched()
    {
        $request = $this->getMock('Symfony\Component\HttpFoundation\Request');
        $requestMatcher = $this->getRequestMatcher($request, false);

        $map = new AccessMap();
        $map->add($requestMatcher, array('ROLE_USER'), 'https');

        $this->assertSame(array(null, null), $map->getPatterns($request));
    }

    private function getRequestMatcher($request, $matches)
    {
        $requestMatcher = $this->getMock('Symfony\Component\HttpFoundation\RequestMatcherInterface');
        $requestMatcher->expects($this->once())
            ->method('matches')->with($request)
            ->will($this->returnValue($matches));

        return $requestMatcher;
    }
}
PK��Z���F8F8mtest/Security/Symfony/Component/Security/Http/Tests/RememberMe/PersistentTokenBasedRememberMeServicesTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Tests\RememberMe;

use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;

use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Component\Security\Http\RememberMe\PersistentTokenBasedRememberMeServices;
use Symfony\Component\Security\Core\Exception\TokenNotFoundException;
use Symfony\Component\Security\Core\Exception\CookieTheftException;
use Symfony\Component\Security\Core\Util\SecureRandom;

class PersistentTokenBasedRememberMeServicesTest extends \PHPUnit_Framework_TestCase
{
    public function testAutoLoginReturnsNullWhenNoCookie()
    {
        $service = $this->getService(null, array('name' => 'foo'));

        $this->assertNull($service->autoLogin(new Request()));
    }

    public function testAutoLoginThrowsExceptionOnInvalidCookie()
    {
        $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null, 'always_remember_me' => false, 'remember_me_parameter' => 'foo'));
        $request = new Request();
        $request->request->set('foo', 'true');
        $request->cookies->set('foo', 'foo');

        $this->assertNull($service->autoLogin($request));
        $this->assertTrue($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME)->isCleared());
    }

    public function testAutoLoginThrowsExceptionOnNonExistentToken()
    {
        $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null, 'always_remember_me' => false, 'remember_me_parameter' => 'foo'));
        $request = new Request();
        $request->request->set('foo', 'true');
        $request->cookies->set('foo', $this->encodeCookie(array(
            $series = 'fooseries',
            $tokenValue = 'foovalue',
        )));

        $tokenProvider = $this->getMock('Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface');
        $tokenProvider
            ->expects($this->once())
            ->method('loadTokenBySeries')
            ->will($this->throwException(new TokenNotFoundException('Token not found.')))
        ;
        $service->setTokenProvider($tokenProvider);

        $this->assertNull($service->autoLogin($request));
        $this->assertTrue($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME)->isCleared());
    }

    public function testAutoLoginReturnsNullOnNonExistentUser()
    {
        $userProvider = $this->getProvider();
        $service = $this->getService($userProvider, array('name' => 'foo', 'path' => null, 'domain' => null, 'always_remember_me' => true, 'lifetime' => 3600, 'secure' => false, 'httponly' => false));
        $request = new Request();
        $request->cookies->set('foo', $this->encodeCookie(array('fooseries', 'foovalue')));

        $tokenProvider = $this->getMock('Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface');
        $tokenProvider
            ->expects($this->once())
            ->method('loadTokenBySeries')
            ->will($this->returnValue(new PersistentToken('fooclass', 'fooname', 'fooseries', 'foovalue', new \DateTime())))
        ;
        $service->setTokenProvider($tokenProvider);

        $userProvider
            ->expects($this->once())
            ->method('loadUserByUsername')
            ->will($this->throwException(new UsernameNotFoundException('user not found')))
        ;

        $this->assertNull($service->autoLogin($request));
        $this->assertTrue($request->attributes->has(RememberMeServicesInterface::COOKIE_ATTR_NAME));
    }

    public function testAutoLoginThrowsExceptionOnStolenCookieAndRemovesItFromThePersistentBackend()
    {
        $userProvider = $this->getProvider();
        $service = $this->getService($userProvider, array('name' => 'foo', 'path' => null, 'domain' => null, 'always_remember_me' => true));
        $request = new Request();
        $request->cookies->set('foo', $this->encodeCookie(array('fooseries', 'foovalue')));

        $tokenProvider = $this->getMock('Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface');
        $service->setTokenProvider($tokenProvider);

        $tokenProvider
            ->expects($this->once())
            ->method('loadTokenBySeries')
            ->will($this->returnValue(new PersistentToken('fooclass', 'foouser', 'fooseries', 'anotherFooValue', new \DateTime())))
        ;

        $tokenProvider
            ->expects($this->once())
            ->method('deleteTokenBySeries')
            ->with($this->equalTo('fooseries'))
            ->will($this->returnValue(null))
        ;

        try {
            $service->autoLogin($request);
            $this->fail('Expected CookieTheftException was not thrown.');
        } catch (CookieTheftException $theft) { }

        $this->assertTrue($request->attributes->has(RememberMeServicesInterface::COOKIE_ATTR_NAME));
    }

    public function testAutoLoginDoesNotAcceptAnExpiredCookie()
    {
        $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null, 'always_remember_me' => true, 'lifetime' => 3600));
        $request = new Request();
        $request->cookies->set('foo', $this->encodeCookie(array('fooseries', 'foovalue')));

        $tokenProvider = $this->getMock('Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface');
        $tokenProvider
            ->expects($this->once())
            ->method('loadTokenBySeries')
            ->with($this->equalTo('fooseries'))
            ->will($this->returnValue(new PersistentToken('fooclass', 'username', 'fooseries', 'foovalue', new \DateTime('yesterday'))))
        ;
        $service->setTokenProvider($tokenProvider);

        $this->assertNull($service->autoLogin($request));
        $this->assertTrue($request->attributes->has(RememberMeServicesInterface::COOKIE_ATTR_NAME));
    }

    public function testAutoLogin()
    {
        $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
        $user
            ->expects($this->once())
            ->method('getRoles')
            ->will($this->returnValue(array('ROLE_FOO')))
        ;

        $userProvider = $this->getProvider();
        $userProvider
            ->expects($this->once())
            ->method('loadUserByUsername')
            ->with($this->equalTo('foouser'))
            ->will($this->returnValue($user))
        ;

        $service = $this->getService($userProvider, array('name' => 'foo', 'path' => null, 'domain' => null, 'secure' => false, 'httponly' => false, 'always_remember_me' => true, 'lifetime' => 3600));
        $request = new Request();
        $request->cookies->set('foo', $this->encodeCookie(array('fooseries', 'foovalue')));

        $tokenProvider = $this->getMock('Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface');
        $tokenProvider
            ->expects($this->once())
            ->method('loadTokenBySeries')
            ->with($this->equalTo('fooseries'))
            ->will($this->returnValue(new PersistentToken('fooclass', 'foouser', 'fooseries', 'foovalue', new \DateTime())))
        ;
        $service->setTokenProvider($tokenProvider);

        $returnedToken = $service->autoLogin($request);

        $this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\RememberMeToken', $returnedToken);
        $this->assertSame($user, $returnedToken->getUser());
        $this->assertEquals('fookey', $returnedToken->getKey());
        $this->assertTrue($request->attributes->has(RememberMeServicesInterface::COOKIE_ATTR_NAME));
    }

    public function testLogout()
    {
        $service = $this->getService(null, array('name' => 'foo', 'path' => '/foo', 'domain' => 'foodomain.foo'));
        $request = new Request();
        $request->cookies->set('foo', $this->encodeCookie(array('fooseries', 'foovalue')));
        $response = new Response();
        $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');

        $tokenProvider = $this->getMock('Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface');
        $tokenProvider
            ->expects($this->once())
            ->method('deleteTokenBySeries')
            ->with($this->equalTo('fooseries'))
            ->will($this->returnValue(null))
        ;
        $service->setTokenProvider($tokenProvider);

        $service->logout($request, $response, $token);

        $cookie = $request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME);
        $this->assertTrue($cookie->isCleared());
        $this->assertEquals('/foo', $cookie->getPath());
        $this->assertEquals('foodomain.foo', $cookie->getDomain());
    }

    public function testLogoutSimplyIgnoresNonSetRequestCookie()
    {
        $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null));
        $request = new Request();
        $response = new Response();
        $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');

        $tokenProvider = $this->getMock('Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface');
        $tokenProvider
            ->expects($this->never())
            ->method('deleteTokenBySeries')
        ;
        $service->setTokenProvider($tokenProvider);

        $service->logout($request, $response, $token);

        $cookie = $request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME);
        $this->assertTrue($cookie->isCleared());
        $this->assertEquals('/', $cookie->getPath());
        $this->assertNull($cookie->getDomain());
    }

    public function testLogoutSimplyIgnoresInvalidCookie()
    {
        $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null));
        $request = new Request();
        $request->cookies->set('foo', 'somefoovalue');
        $response = new Response();
        $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');

        $tokenProvider = $this->getMock('Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface');
        $tokenProvider
            ->expects($this->never())
            ->method('deleteTokenBySeries')
        ;
        $service->setTokenProvider($tokenProvider);

        $service->logout($request, $response, $token);

        $this->assertTrue($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME)->isCleared());
    }

    public function testLoginFail()
    {
        $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null));
        $request = new Request();

        $this->assertFalse($request->attributes->has(RememberMeServicesInterface::COOKIE_ATTR_NAME));
        $service->loginFail($request);
        $this->assertTrue($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME)->isCleared());
    }

    public function testLoginSuccessSetsCookieWhenLoggedInWithNonRememberMeTokenInterfaceImplementation()
    {
        $service = $this->getService(null, array('name' => 'foo', 'domain' => 'myfoodomain.foo', 'path' => '/foo/path', 'secure' => true, 'httponly' => true, 'lifetime' => 3600, 'always_remember_me' => true));
        $request = new Request();
        $response = new Response();

        $account = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
        $account
            ->expects($this->once())
            ->method('getUsername')
            ->will($this->returnValue('foo'))
        ;
        $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
        $token
            ->expects($this->any())
            ->method('getUser')
            ->will($this->returnValue($account))
        ;

        $tokenProvider = $this->getMock('Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface');
        $tokenProvider
            ->expects($this->once())
            ->method('createNewToken')
        ;
        $service->setTokenProvider($tokenProvider);

        $cookies = $response->headers->getCookies();
        $this->assertCount(0, $cookies);

        $service->loginSuccess($request, $response, $token);

        $cookies = $response->headers->getCookies(ResponseHeaderBag::COOKIES_ARRAY);
        $cookie  = $cookies['myfoodomain.foo']['/foo/path']['foo'];
        $this->assertFalse($cookie->isCleared());
        $this->assertTrue($cookie->isSecure());
        $this->assertTrue($cookie->isHttpOnly());
        $this->assertTrue($cookie->getExpiresTime() > time() + 3590 && $cookie->getExpiresTime() < time() + 3610);
        $this->assertEquals('myfoodomain.foo', $cookie->getDomain());
        $this->assertEquals('/foo/path', $cookie->getPath());
    }

    protected function encodeCookie(array $parts)
    {
        $service = $this->getService();
        $r = new \ReflectionMethod($service, 'encodeCookie');
        $r->setAccessible(true);

        return $r->invoke($service, $parts);
    }

    protected function getService($userProvider = null, $options = array(), $logger = null)
    {
        if (null === $userProvider) {
            $userProvider = $this->getProvider();
        }

        return new PersistentTokenBasedRememberMeServices(array($userProvider), 'fookey', 'fookey', $options, $logger, new SecureRandom(sys_get_temp_dir().'/_sf2.seed'));
    }

    protected function getProvider()
    {
        $provider = $this->getMock('Symfony\Component\Security\Core\User\UserProviderInterface');
        $provider
            ->expects($this->any())
            ->method('supportsClass')
            ->will($this->returnValue(true))
        ;

        return $provider;
    }
}
PK��Z�䗥1#1#atest/Security/Symfony/Component/Security/Http/Tests/RememberMe/AbstractRememberMeServicesTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Tests\RememberMe;

use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class AbstractRememberMeServicesTest extends \PHPUnit_Framework_TestCase
{
    public function testGetRememberMeParameter()
    {
        $service = $this->getService(null, array('remember_me_parameter' => 'foo'));

        $this->assertEquals('foo', $service->getRememberMeParameter());
    }

    public function testGetKey()
    {
        $service = $this->getService();
        $this->assertEquals('fookey', $service->getKey());
    }

    public function testAutoLoginReturnsNullWhenNoCookie()
    {
        $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null));

        $this->assertNull($service->autoLogin(new Request()));
    }

    /**
     * @expectedException \RuntimeException
     */
    public function testAutoLoginThrowsExceptionWhenImplementationDoesNotReturnUserInterface()
    {
        $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null));
        $request = new Request();
        $request->cookies->set('foo', 'foo');

        $service
            ->expects($this->once())
            ->method('processAutoLoginCookie')
            ->will($this->returnValue(null))
        ;

        $service->autoLogin($request);
    }

    public function testAutoLogin()
    {
        $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null));
        $request = new Request();
        $request->cookies->set('foo', 'foo');

        $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
        $user
            ->expects($this->once())
            ->method('getRoles')
            ->will($this->returnValue(array()))
        ;

        $service
            ->expects($this->once())
            ->method('processAutoLoginCookie')
            ->will($this->returnValue($user))
        ;

        $returnedToken = $service->autoLogin($request);

        $this->assertSame($user, $returnedToken->getUser());
        $this->assertSame('fookey', $returnedToken->getKey());
        $this->assertSame('fookey', $returnedToken->getProviderKey());
    }

    public function testLogout()
    {
        $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null));
        $request = new Request();
        $response = new Response();
        $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');

        $service->logout($request, $response, $token);

        $this->assertTrue($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME)->isCleared());
    }

    public function testLoginFail()
    {
        $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null));
        $request = new Request();

        $service->loginFail($request);

        $this->assertTrue($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME)->isCleared());
    }

    public function testLoginSuccessIsNotProcessedWhenTokenDoesNotContainUserInterfaceImplementation()
    {
        $service = $this->getService(null, array('name' => 'foo', 'always_remember_me' => true, 'path' => null, 'domain' => null));
        $request = new Request();
        $response = new Response();
        $account = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
        $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
        $token
            ->expects($this->once())
            ->method('getUser')
            ->will($this->returnValue('foo'))
        ;

        $service
            ->expects($this->never())
            ->method('onLoginSuccess')
        ;

        $this->assertFalse($request->request->has('foo'));

        $service->loginSuccess($request, $response, $token);
    }

    public function testLoginSuccessIsNotProcessedWhenRememberMeIsNotRequested()
    {
        $service = $this->getService(null, array('name' => 'foo', 'always_remember_me' => false, 'remember_me_parameter' => 'foo', 'path' => null, 'domain' => null));
        $request = new Request();
        $response = new Response();
        $account = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
        $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
        $token
            ->expects($this->once())
            ->method('getUser')
            ->will($this->returnValue($account))
        ;

        $service
            ->expects($this->never())
            ->method('onLoginSuccess')
            ->will($this->returnValue(null))
        ;

        $this->assertFalse($request->request->has('foo'));

        $service->loginSuccess($request, $response, $token);
    }

    public function testLoginSuccessWhenRememberMeAlwaysIsTrue()
    {
        $service = $this->getService(null, array('name' => 'foo', 'always_remember_me' => true, 'path' => null, 'domain' => null));
        $request = new Request();
        $response = new Response();
        $account = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
        $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
        $token
            ->expects($this->once())
            ->method('getUser')
            ->will($this->returnValue($account))
        ;

        $service
            ->expects($this->once())
            ->method('onLoginSuccess')
            ->will($this->returnValue(null))
        ;

        $service->loginSuccess($request, $response, $token);
    }

    /**
     * @dataProvider getPositiveRememberMeParameterValues
     */
    public function testLoginSuccessWhenRememberMeParameterWithPathIsPositive($value)
    {
        $service = $this->getService(null, array('name' => 'foo', 'always_remember_me' => false, 'remember_me_parameter' => 'foo[bar]', 'path' => null, 'domain' => null));

        $request = new Request();
        $request->request->set('foo', array('bar' => $value));
        $response = new Response();
        $account = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
        $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
        $token
            ->expects($this->once())
            ->method('getUser')
            ->will($this->returnValue($account))
        ;

        $service
            ->expects($this->once())
            ->method('onLoginSuccess')
            ->will($this->returnValue(true))
        ;

        $service->loginSuccess($request, $response, $token);
    }

    /**
     * @dataProvider getPositiveRememberMeParameterValues
     */
    public function testLoginSuccessWhenRememberMeParameterIsPositive($value)
    {
        $service = $this->getService(null, array('name' => 'foo', 'always_remember_me' => false, 'remember_me_parameter' => 'foo', 'path' => null, 'domain' => null));

        $request = new Request();
        $request->request->set('foo', $value);
        $response = new Response();
        $account = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
        $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
        $token
            ->expects($this->once())
            ->method('getUser')
            ->will($this->returnValue($account))
        ;

        $service
            ->expects($this->once())
            ->method('onLoginSuccess')
            ->will($this->returnValue(true))
        ;

        $service->loginSuccess($request, $response, $token);
    }

    public function getPositiveRememberMeParameterValues()
    {
        return array(
            array('true'),
            array('1'),
            array('on'),
            array('yes'),
        );
    }

    protected function getService($userProvider = null, $options = array(), $logger = null)
    {
        if (null === $userProvider) {
            $userProvider = $this->getProvider();
        }

        return $this->getMockForAbstractClass('Symfony\Component\Security\Http\RememberMe\AbstractRememberMeServices', array(
            array($userProvider), 'fookey', 'fookey', $options, $logger
        ));
    }

    protected function getProvider()
    {
        $provider = $this->getMock('Symfony\Component\Security\Core\User\UserProviderInterface');
        $provider
            ->expects($this->any())
            ->method('supportsClass')
            ->will($this->returnValue(true))
        ;

        return $provider;
    }
}
PK��Z�gZ)Z)ctest/Security/Symfony/Component/Security/Http/Tests/RememberMe/TokenBasedRememberMeServicesTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Tests\RememberMe;

use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;

use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Component\Security\Http\RememberMe\TokenBasedRememberMeServices;

class TokenBasedRememberMeServicesTest extends \PHPUnit_Framework_TestCase
{
    public function testAutoLoginReturnsNullWhenNoCookie()
    {
        $service = $this->getService(null, array('name' => 'foo'));

        $this->assertNull($service->autoLogin(new Request()));
    }

    public function testAutoLoginThrowsExceptionOnInvalidCookie()
    {
        $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null, 'always_remember_me' => false, 'remember_me_parameter' => 'foo'));
        $request = new Request();
        $request->request->set('foo', 'true');
        $request->cookies->set('foo', 'foo');

        $this->assertNull($service->autoLogin($request));
        $this->assertTrue($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME)->isCleared());
    }

    public function testAutoLoginThrowsExceptionOnNonExistentUser()
    {
        $userProvider = $this->getProvider();
        $service = $this->getService($userProvider, array('name' => 'foo', 'path' => null, 'domain' => null, 'always_remember_me' => true, 'lifetime' => 3600));
        $request = new Request();
        $request->cookies->set('foo', $this->getCookie('fooclass', 'foouser', time()+3600, 'foopass'));

        $userProvider
            ->expects($this->once())
            ->method('loadUserByUsername')
            ->will($this->throwException(new UsernameNotFoundException('user not found')))
        ;

        $this->assertNull($service->autoLogin($request));
        $this->assertTrue($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME)->isCleared());
    }

    public function testAutoLoginDoesNotAcceptCookieWithInvalidHash()
    {
        $userProvider = $this->getProvider();
        $service = $this->getService($userProvider, array('name' => 'foo', 'path' => null, 'domain' => null, 'always_remember_me' => true, 'lifetime' => 3600));
        $request = new Request();
        $request->cookies->set('foo', base64_encode('class:'.base64_encode('foouser').':123456789:fooHash'));

        $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
        $user
            ->expects($this->once())
            ->method('getPassword')
            ->will($this->returnValue('foopass'))
        ;

        $userProvider
            ->expects($this->once())
            ->method('loadUserByUsername')
            ->with($this->equalTo('foouser'))
            ->will($this->returnValue($user))
        ;

        $this->assertNull($service->autoLogin($request));
        $this->assertTrue($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME)->isCleared());
    }

    public function testAutoLoginDoesNotAcceptAnExpiredCookie()
    {
        $userProvider = $this->getProvider();
        $service = $this->getService($userProvider, array('name' => 'foo', 'path' => null, 'domain' => null, 'always_remember_me' => true, 'lifetime' => 3600));
        $request = new Request();
        $request->cookies->set('foo', $this->getCookie('fooclass', 'foouser', time() - 1, 'foopass'));

        $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
        $user
            ->expects($this->once())
            ->method('getPassword')
            ->will($this->returnValue('foopass'))
        ;

        $userProvider
            ->expects($this->once())
            ->method('loadUserByUsername')
            ->with($this->equalTo('foouser'))
            ->will($this->returnValue($user))
        ;

        $this->assertNull($service->autoLogin($request));
        $this->assertTrue($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME)->isCleared());
    }

    public function testAutoLogin()
    {
        $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
        $user
            ->expects($this->once())
            ->method('getRoles')
            ->will($this->returnValue(array('ROLE_FOO')))
        ;
        $user
            ->expects($this->once())
            ->method('getPassword')
            ->will($this->returnValue('foopass'))
        ;

        $userProvider = $this->getProvider();
        $userProvider
            ->expects($this->once())
            ->method('loadUserByUsername')
            ->with($this->equalTo('foouser'))
            ->will($this->returnValue($user))
        ;

        $service = $this->getService($userProvider, array('name' => 'foo', 'always_remember_me' => true, 'lifetime' => 3600));
        $request = new Request();
        $request->cookies->set('foo', $this->getCookie('fooclass', 'foouser', time()+3600, 'foopass'));

        $returnedToken = $service->autoLogin($request);

        $this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\RememberMeToken', $returnedToken);
        $this->assertSame($user, $returnedToken->getUser());
        $this->assertEquals('fookey', $returnedToken->getKey());
    }

    public function testLogout()
    {
        $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null));
        $request = new Request();
        $response = new Response();
        $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');

        $service->logout($request, $response, $token);

        $cookie = $request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME);
        $this->assertTrue($cookie->isCleared());
        $this->assertEquals('/', $cookie->getPath());
        $this->assertNull($cookie->getDomain());
    }

    public function testLoginFail()
    {
        $service = $this->getService(null, array('name' => 'foo', 'path' => '/foo', 'domain' => 'foodomain.foo'));
        $request = new Request();
        $response = new Response();

        $service->loginFail($request, $response);

        $cookie = $request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME);
        $this->assertTrue($cookie->isCleared());
        $this->assertEquals('/foo', $cookie->getPath());
        $this->assertEquals('foodomain.foo', $cookie->getDomain());
    }

    public function testLoginSuccessIgnoresTokensWhichDoNotContainAnUserInterfaceImplementation()
    {
        $service = $this->getService(null, array('name' => 'foo', 'always_remember_me' => true, 'path' => null, 'domain' => null));
        $request = new Request();
        $response = new Response();
        $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
        $token
            ->expects($this->once())
            ->method('getUser')
            ->will($this->returnValue('foo'))
        ;

        $cookies = $response->headers->getCookies();
        $this->assertCount(0, $cookies);

        $service->loginSuccess($request, $response, $token);

        $cookies = $response->headers->getCookies();
        $this->assertCount(0, $cookies);
    }

    public function testLoginSuccess()
    {
        $service = $this->getService(null, array('name' => 'foo', 'domain' => 'myfoodomain.foo', 'path' => '/foo/path', 'secure' => true, 'httponly' => true, 'lifetime' => 3600, 'always_remember_me' => true));
        $request = new Request();
        $response = new Response();

        $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
        $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
        $user
            ->expects($this->once())
            ->method('getPassword')
            ->will($this->returnValue('foopass'))
        ;
        $user
            ->expects($this->once())
            ->method('getUsername')
            ->will($this->returnValue('foouser'))
        ;
        $token
            ->expects($this->atLeastOnce())
            ->method('getUser')
            ->will($this->returnValue($user))
        ;

        $cookies = $response->headers->getCookies();
        $this->assertCount(0, $cookies);

        $service->loginSuccess($request, $response, $token);

        $cookies = $response->headers->getCookies(ResponseHeaderBag::COOKIES_ARRAY);
        $cookie  = $cookies['myfoodomain.foo']['/foo/path']['foo'];
        $this->assertFalse($cookie->isCleared());
        $this->assertTrue($cookie->isSecure());
        $this->assertTrue($cookie->isHttpOnly());
        $this->assertTrue($cookie->getExpiresTime() > time() + 3590 && $cookie->getExpiresTime() < time() + 3610);
        $this->assertEquals('myfoodomain.foo', $cookie->getDomain());
        $this->assertEquals('/foo/path', $cookie->getPath());
    }

    protected function getCookie($class, $username, $expires, $password)
    {
        $service = $this->getService();
        $r = new \ReflectionMethod($service, 'generateCookieValue');
        $r->setAccessible(true);

        return $r->invoke($service, $class, $username, $expires, $password);
    }

    protected function encodeCookie(array $parts)
    {
        $service = $this->getService();
        $r = new \ReflectionMethod($service, 'encodeCookie');
        $r->setAccessible(true);

        return $r->invoke($service, $parts);
    }

    protected function getService($userProvider = null, $options = array(), $logger = null)
    {
        if (null === $userProvider) {
            $userProvider = $this->getProvider();
        }

        $service = new TokenBasedRememberMeServices(array($userProvider), 'fookey', 'fookey', $options, $logger);

        return $service;
    }

    protected function getProvider()
    {
        $provider = $this->getMock('Symfony\Component\Security\Core\User\UserProviderInterface');
        $provider
            ->expects($this->any())
            ->method('supportsClass')
            ->will($this->returnValue(true))
        ;

        return $provider;
    }
}
PK��Z��ʅ
�
Wtest/Security/Symfony/Component/Security/Http/Tests/RememberMe/ResponseListenerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Tests\RememberMe;

use Symfony\Component\Security\Http\RememberMe\ResponseListener;
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpKernel\KernelEvents;

class ResponseListenerTest extends \PHPUnit_Framework_TestCase
{
    public function testRememberMeCookieIsSentWithResponse()
    {
        $cookie = new Cookie('rememberme');

        $request = $this->getRequest(array(
            RememberMeServicesInterface::COOKIE_ATTR_NAME => $cookie
        ));

        $response = $this->getResponse();
        $response->headers->expects($this->once())->method('setCookie')->with($cookie);

        $listener = new ResponseListener();
        $listener->onKernelResponse($this->getEvent($request, $response));
    }

    public function testRememberMeCookieIsNotSendWithResponse()
    {
        $request = $this->getRequest();

        $response = $this->getResponse();
        $response->headers->expects($this->never())->method('setCookie');

        $listener = new ResponseListener();
        $listener->onKernelResponse($this->getEvent($request, $response));
    }

    public function testItSubscribesToTheOnKernelResponseEvent()
    {
        $listener = new ResponseListener();

        $this->assertSame(array(KernelEvents::RESPONSE => 'onKernelResponse'), ResponseListener::getSubscribedEvents());
    }

    private function getRequest(array $attributes = array())
    {
        $request = new Request();

        foreach ($attributes as $name => $value) {
            $request->attributes->set($name, $value);
        }

        return $request;
    }

    private function getResponse()
    {
        $response = $this->getMock('Symfony\Component\HttpFoundation\Response');
        $response->headers = $this->getMock('Symfony\Component\HttpFoundation\ResponseHeaderBag');

        return $response;
    }

    private function getEvent($request, $response)
    {
        $event = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\FilterResponseEvent')
            ->disableOriginalConstructor()
            ->getMock();

        $event->expects($this->any())->method('getRequest')->will($this->returnValue($request));
        $event->expects($this->any())->method('getResponse')->will($this->returnValue($response));

        return $event;
    }
}
PK��ZY�Ң	�	atest/Security/Symfony/Component/Security/Http/Tests/Session/SessionAuthenticationStrategyTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Tests\Session;

use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategy;

class SessionAuthenticationStrategyTest extends \PHPUnit_Framework_TestCase
{
    public function testSessionIsNotChanged()
    {
        $request = $this->getRequest();
        $request->expects($this->never())->method('getSession');

        $strategy = new SessionAuthenticationStrategy(SessionAuthenticationStrategy::NONE);
        $strategy->onAuthentication($request, $this->getToken());
    }

    /**
     * @expectedException \RuntimeException
     * @expectedExceptionMessage Invalid session authentication strategy "foo"
     */
    public function testUnsupportedStrategy()
    {
        $request = $this->getRequest();
        $request->expects($this->never())->method('getSession');

        $strategy = new SessionAuthenticationStrategy('foo');
        $strategy->onAuthentication($request, $this->getToken());
    }

    public function testSessionIsMigrated()
    {
        $session = $this->getMock('Symfony\Component\HttpFoundation\Session\SessionInterface');
        $session->expects($this->once())->method('migrate');

        $strategy = new SessionAuthenticationStrategy(SessionAuthenticationStrategy::MIGRATE);
        $strategy->onAuthentication($this->getRequest($session), $this->getToken());
    }

    public function testSessionIsInvalidated()
    {
        $session = $this->getMock('Symfony\Component\HttpFoundation\Session\SessionInterface');
        $session->expects($this->once())->method('invalidate');

        $strategy = new SessionAuthenticationStrategy(SessionAuthenticationStrategy::INVALIDATE);
        $strategy->onAuthentication($this->getRequest($session), $this->getToken());
    }

    private function getRequest($session = null)
    {
        $request = $this->getMock('Symfony\Component\HttpFoundation\Request');

        if (null !== $session) {
            $request->expects($this->any())->method('getSession')->will($this->returnValue($session));
        }

        return $request;
    }

    private function getToken()
    {
        return $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
    }
}
PK��Z�
{{^test/Security/Symfony/Component/Security/Http/Tests/Logout/DefaultLogoutSuccessHandlerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Tests\Logout;

use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Http\Logout\DefaultLogoutSuccessHandler;

class DefaultLogoutSuccessHandlerTest extends \PHPUnit_Framework_TestCase
{
    public function testLogout()
    {
        $request = $this->getMock('Symfony\Component\HttpFoundation\Request');
        $response = $this->getMock('Symfony\Component\HttpFoundation\Response');

        $httpUtils = $this->getMock('Symfony\Component\Security\Http\HttpUtils');
        $httpUtils->expects($this->once())
            ->method('createRedirectResponse')
            ->with($request, '/dashboard')
            ->will($this->returnValue($response));

        $handler = new DefaultLogoutSuccessHandler($httpUtils, '/dashboard');
        $result = $handler->onLogoutSuccess($request);

        $this->assertSame($response, $result);
    }
}
PK��Z]�ͷ��Wtest/Security/Symfony/Component/Security/Http/Tests/Logout/SessionLogoutHandlerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Tests\Logout;

use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Http\Logout\SessionLogoutHandler;

class SessionLogoutHandlerTest extends \PHPUnit_Framework_TestCase
{
    public function testLogout()
    {
        $handler = new SessionLogoutHandler();

        $request = $this->getMock('Symfony\Component\HttpFoundation\Request');
        $response = new Response();
        $session = $this->getMock('Symfony\Component\HttpFoundation\Session\Session', array(), array(), '', false);

        $request
            ->expects($this->once())
            ->method('getSession')
            ->will($this->returnValue($session))
        ;

        $session
            ->expects($this->once())
            ->method('invalidate')
        ;

        $handler->logout($request, $response, $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'));
    }
}
PK��Zk��^test/Security/Symfony/Component/Security/Http/Tests/Logout/CookieClearingLogoutHandlerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Tests\Logout;

use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Http\Logout\CookieClearingLogoutHandler;

class CookieClearingLogoutHandlerTest extends \PHPUnit_Framework_TestCase
{
    public function testLogout()
    {
        $request = new Request();
        $response = new Response();
        $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');

        $handler = new CookieClearingLogoutHandler(array('foo' => array('path' => '/foo', 'domain' => 'foo.foo'), 'foo2' => array('path' => null, 'domain' => null)));

        $cookies = $response->headers->getCookies();
        $this->assertCount(0, $cookies);

        $handler->logout($request, $response, $token);

        $cookies = $response->headers->getCookies(ResponseHeaderBag::COOKIES_ARRAY);
        $this->assertCount(2, $cookies);

        $cookie = $cookies['foo.foo']['/foo']['foo'];
        $this->assertEquals('foo', $cookie->getName());
        $this->assertEquals('/foo', $cookie->getPath());
        $this->assertEquals('foo.foo', $cookie->getDomain());
        $this->assertTrue($cookie->isCleared());

        $cookie = $cookies['']['/']['foo2'];
        $this->assertStringStartsWith('foo2', $cookie->getName());
        $this->assertEquals('/', $cookie->getPath());
        $this->assertNull($cookie->getDomain());
        $this->assertTrue($cookie->isCleared());
    }
}
PK��Z$a��ntest/Security/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationFailureHandlerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Tests\Authentication;

use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationFailureHandler;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\HttpKernel\HttpKernelInterface;

class DefaultAuthenticationFailureHandlerTest extends \PHPUnit_Framework_TestCase
{
    private $httpKernel = null;

    private $httpUtils = null;

    private $logger = null;

    private $request = null;

    private $session = null;

    private $exception = null;

    protected function setUp()
    {
        $this->httpKernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
        $this->httpUtils = $this->getMock('Symfony\Component\Security\Http\HttpUtils');
        $this->logger = $this->getMock('Psr\Log\LoggerInterface');

        $this->session = $this->getMock('Symfony\Component\HttpFoundation\Session\SessionInterface');
        $this->request = $this->getMock('Symfony\Component\HttpFoundation\Request');
        $this->request->expects($this->any())->method('getSession')->will($this->returnValue($this->session));
        $this->exception = $this->getMock('Symfony\Component\Security\Core\Exception\AuthenticationException');
    }

    public function testForward()
    {
        $options = array('failure_forward' => true);

        $subRequest = $this->getRequest();
        $subRequest->attributes->expects($this->once())
            ->method('set')->with(SecurityContextInterface::AUTHENTICATION_ERROR, $this->exception);
        $this->httpUtils->expects($this->once())
            ->method('createRequest')->with($this->request, '/login')
            ->will($this->returnValue($subRequest));

        $response = $this->getMock('Symfony\Component\HttpFoundation\Response');
        $this->httpKernel->expects($this->once())
            ->method('handle')->with($subRequest, HttpKernelInterface::SUB_REQUEST)
            ->will($this->returnValue($response));

        $handler = new DefaultAuthenticationFailureHandler($this->httpKernel, $this->httpUtils, $options, $this->logger);
        $result = $handler->onAuthenticationFailure($this->request, $this->exception);

        $this->assertSame($response, $result);
    }

    public function testRedirect()
    {
        $response = $this->getMock('Symfony\Component\HttpFoundation\Response');
        $this->httpUtils->expects($this->once())
            ->method('createRedirectResponse')->with($this->request, '/login')
            ->will($this->returnValue($response));

        $handler = new DefaultAuthenticationFailureHandler($this->httpKernel, $this->httpUtils, array(), $this->logger);
        $result = $handler->onAuthenticationFailure($this->request, $this->exception);

        $this->assertSame($response, $result);
    }

    public function testExceptionIsPersistedInSession()
    {
        $this->session->expects($this->once())
            ->method('set')->with(SecurityContextInterface::AUTHENTICATION_ERROR, $this->exception);

        $handler = new DefaultAuthenticationFailureHandler($this->httpKernel, $this->httpUtils, array(), $this->logger);
        $handler->onAuthenticationFailure($this->request, $this->exception);
    }

    public function testExceptionIsPassedInRequestOnForward()
    {
        $options = array('failure_forward' => true);

        $subRequest = $this->getRequest();
        $subRequest->attributes->expects($this->once())
            ->method('set')->with(SecurityContextInterface::AUTHENTICATION_ERROR, $this->exception);

        $this->httpUtils->expects($this->once())
            ->method('createRequest')->with($this->request, '/login')
            ->will($this->returnValue($subRequest));

        $this->session->expects($this->never())->method('set');

        $handler = new DefaultAuthenticationFailureHandler($this->httpKernel, $this->httpUtils, $options, $this->logger);
        $handler->onAuthenticationFailure($this->request, $this->exception);
    }

    public function testRedirectIsLogged()
    {
        $this->logger->expects($this->once())->method('debug')->with('Redirecting to /login');

        $handler = new DefaultAuthenticationFailureHandler($this->httpKernel, $this->httpUtils, array(), $this->logger);
        $handler->onAuthenticationFailure($this->request, $this->exception);
    }

    public function testForwardIsLogged()
    {
        $options = array('failure_forward' => true);

        $this->httpUtils->expects($this->once())
            ->method('createRequest')->with($this->request, '/login')
            ->will($this->returnValue($this->getRequest()));

        $this->logger->expects($this->once())->method('debug')->with('Forwarding to /login');

        $handler = new DefaultAuthenticationFailureHandler($this->httpKernel, $this->httpUtils, $options, $this->logger);
        $handler->onAuthenticationFailure($this->request, $this->exception);
    }

    public function testFailurePathCanBeOverwritten()
    {
        $options = array('failure_path' => '/auth/login');

        $this->httpUtils->expects($this->once())
            ->method('createRedirectResponse')->with($this->request, '/auth/login');

        $handler = new DefaultAuthenticationFailureHandler($this->httpKernel, $this->httpUtils, $options, $this->logger);
        $handler->onAuthenticationFailure($this->request, $this->exception);
    }

    public function testFailurePathCanBeOverwrittenWithRequest()
    {
        $this->request->expects($this->once())
            ->method('get')->with('_failure_path', null, true)
            ->will($this->returnValue('/auth/login'));

        $this->httpUtils->expects($this->once())
            ->method('createRedirectResponse')->with($this->request, '/auth/login');

        $handler = new DefaultAuthenticationFailureHandler($this->httpKernel, $this->httpUtils, array(), $this->logger);
        $handler->onAuthenticationFailure($this->request, $this->exception);
    }

    public function testFailurePathParameterCanBeOverwritten()
    {
        $options = array('failure_path_parameter' => '_my_failure_path');

        $this->request->expects($this->once())
            ->method('get')->with('_my_failure_path', null, true)
            ->will($this->returnValue('/auth/login'));

        $this->httpUtils->expects($this->once())
            ->method('createRedirectResponse')->with($this->request, '/auth/login');

        $handler = new DefaultAuthenticationFailureHandler($this->httpKernel, $this->httpUtils, $options, $this->logger);
        $handler->onAuthenticationFailure($this->request, $this->exception);
    }

    private function getRequest()
    {
        $request = $this->getMock('Symfony\Component\HttpFoundation\Request');
        $request->attributes = $this->getMock('Symfony\Component\HttpFoundation\ParameterBag');

        return $request;
    }
}
PK��Z/w!w!ftest/Security/Symfony/Component/Security/Http/Tests/Authentication/SimpleAuthenticationHandlerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Tests;

use Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Http\Authentication\SimpleAuthenticationHandler;

class SimpleAuthenticationHandlerTest extends \PHPUnit_Framework_TestCase
{
    private $successHandler;

    private $failureHandler;

    private $request;

    private $token;

    private $authenticationException;

    private $response;

    public function setUp()
    {
        $this->successHandler = $this->getMock('Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface');
        $this->failureHandler = $this->getMock('Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface');

        $this->request = $this->getMock('Symfony\Component\HttpFoundation\Request');
        $this->token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
        $this->authenticationException = $this->getMock('Symfony\Component\Security\Core\Exception\AuthenticationException');

        $this->response = $this->getMock('Symfony\Component\HttpFoundation\Response');
    }

    public function testOnAuthenticationSuccessFallsBackToDefaultHandlerIfSimpleIsNotASuccessHandler()
    {
        $authenticator = $this->getMock('Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface');

        $this->successHandler->expects($this->once())
            ->method('onAuthenticationSuccess')
            ->with($this->request, $this->token)
            ->will($this->returnValue($this->response));

        $handler = new SimpleAuthenticationHandler($authenticator, $this->successHandler, $this->failureHandler);
        $result = $handler->onAuthenticationSuccess($this->request, $this->token);

        $this->assertSame($this->response, $result);
    }

    public function testOnAuthenticationSuccessCallsSimpleAuthenticator()
    {
        $this->successHandler->expects($this->never())
            ->method('onAuthenticationSuccess');

        $authenticator = $this->getMockForAbstractClass('Symfony\Component\Security\Http\Tests\TestSuccessHandlerInterface');
        $authenticator->expects($this->once())
            ->method('onAuthenticationSuccess')
            ->with($this->request, $this->token)
            ->will($this->returnValue($this->response));

        $handler = new SimpleAuthenticationHandler($authenticator, $this->successHandler, $this->failureHandler);
        $result = $handler->onAuthenticationSuccess($this->request, $this->token);

        $this->assertSame($this->response, $result);
    }

    /**
     * @expectedException        \UnexpectedValueException
     * @expectedExceptionMessage onAuthenticationSuccess method must return null to use the default success handler, or a Response object
     */
    public function testOnAuthenticationSuccessThrowsAnExceptionIfNonResponseIsReturned()
    {
        $this->successHandler->expects($this->never())
            ->method('onAuthenticationSuccess');

        $authenticator = $this->getMockForAbstractClass('Symfony\Component\Security\Http\Tests\TestSuccessHandlerInterface');
        $authenticator->expects($this->once())
            ->method('onAuthenticationSuccess')
            ->with($this->request, $this->token)
            ->will($this->returnValue(new \stdClass()));

        $handler = new SimpleAuthenticationHandler($authenticator, $this->successHandler, $this->failureHandler);
        $handler->onAuthenticationSuccess($this->request, $this->token);
    }

    public function testOnAuthenticationSuccessFallsBackToDefaultHandlerIfNullIsReturned()
    {
        $this->successHandler->expects($this->once())
            ->method('onAuthenticationSuccess')
            ->with($this->request, $this->token)
            ->will($this->returnValue($this->response));

        $authenticator = $this->getMockForAbstractClass('Symfony\Component\Security\Http\Tests\TestSuccessHandlerInterface');
        $authenticator->expects($this->once())
            ->method('onAuthenticationSuccess')
            ->with($this->request, $this->token)
            ->will($this->returnValue(null));

        $handler = new SimpleAuthenticationHandler($authenticator, $this->successHandler, $this->failureHandler);
        $result = $handler->onAuthenticationSuccess($this->request, $this->token);

        $this->assertSame($this->response, $result);
    }

    public function testOnAuthenticationFailureFallsBackToDefaultHandlerIfSimpleIsNotAFailureHandler()
    {
        $authenticator = $this->getMock('Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface');

        $this->failureHandler->expects($this->once())
            ->method('onAuthenticationFailure')
            ->with($this->request, $this->authenticationException)
            ->will($this->returnValue($this->response));

        $handler = new SimpleAuthenticationHandler($authenticator, $this->successHandler, $this->failureHandler);
        $result = $handler->onAuthenticationFailure($this->request, $this->authenticationException);

        $this->assertSame($this->response, $result);
    }

    public function testOnAuthenticationFailureCallsSimpleAuthenticator()
    {
        $this->failureHandler->expects($this->never())
            ->method('onAuthenticationFailure');

        $authenticator = $this->getMockForAbstractClass('Symfony\Component\Security\Http\Tests\TestFailureHandlerInterface');
        $authenticator->expects($this->once())
            ->method('onAuthenticationFailure')
            ->with($this->request, $this->authenticationException)
            ->will($this->returnValue($this->response));

        $handler = new SimpleAuthenticationHandler($authenticator, $this->successHandler, $this->failureHandler);
        $result = $handler->onAuthenticationFailure($this->request, $this->authenticationException);

        $this->assertSame($this->response, $result);
    }

    /**
     * @expectedException        \UnexpectedValueException
     * @expectedExceptionMessage onAuthenticationFailure method must return null to use the default failure handler, or a Response object
     */
    public function testOnAuthenticationFailureThrowsAnExceptionIfNonResponseIsReturned()
    {
        $this->failureHandler->expects($this->never())
            ->method('onAuthenticationFailure');

        $authenticator = $this->getMockForAbstractClass('Symfony\Component\Security\Http\Tests\TestFailureHandlerInterface');
        $authenticator->expects($this->once())
            ->method('onAuthenticationFailure')
            ->with($this->request, $this->authenticationException)
            ->will($this->returnValue(new \stdClass()));

        $handler = new SimpleAuthenticationHandler($authenticator, $this->successHandler, $this->failureHandler);
        $handler->onAuthenticationFailure($this->request, $this->authenticationException);
    }

    public function testOnAuthenticationFailureFallsBackToDefaultHandlerIfNullIsReturned()
    {
        $this->failureHandler->expects($this->once())
            ->method('onAuthenticationFailure')
            ->with($this->request, $this->authenticationException)
            ->will($this->returnValue($this->response));

        $authenticator = $this->getMockForAbstractClass('Symfony\Component\Security\Http\Tests\TestFailureHandlerInterface');
        $authenticator->expects($this->once())
            ->method('onAuthenticationFailure')
            ->with($this->request, $this->authenticationException)
            ->will($this->returnValue(null));

        $handler = new SimpleAuthenticationHandler($authenticator, $this->successHandler, $this->failureHandler);
        $result = $handler->onAuthenticationFailure($this->request, $this->authenticationException);

        $this->assertSame($this->response, $result);
    }
}

interface TestSuccessHandlerInterface extends AuthenticationSuccessHandlerInterface, SimpleAuthenticatorInterface
{
}

interface TestFailureHandlerInterface extends AuthenticationFailureHandlerInterface, SimpleAuthenticatorInterface
{
}
PK��Zid]z��ntest/Security/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationSuccessHandlerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Http\Tests\Authentication;

use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationSuccessHandler;

class DefaultAuthenticationSuccessHandlerTest extends \PHPUnit_Framework_TestCase
{
    private $httpUtils = null;

    private $request = null;

    private $token = null;

    protected function setUp()
    {
        $this->httpUtils = $this->getMock('Symfony\Component\Security\Http\HttpUtils');
        $this->request = $this->getMock('Symfony\Component\HttpFoundation\Request');
        $this->request->headers = $this->getMock('Symfony\Component\HttpFoundation\HeaderBag');
        $this->token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
    }

    public function testRequestIsRedirected()
    {
        $response = $this->expectRedirectResponse('/');

        $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, array());
        $result = $handler->onAuthenticationSuccess($this->request, $this->token);

        $this->assertSame($response, $result);
    }

    public function testDefaultTargetPathCanBeForced()
    {
        $options = array(
            'always_use_default_target_path' => true,
            'default_target_path' => '/dashboard'
        );

        $response = $this->expectRedirectResponse('/dashboard');

        $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, $options);
        $result = $handler->onAuthenticationSuccess($this->request, $this->token);

        $this->assertSame($response, $result);
    }

    public function testTargetPathIsPassedWithRequest()
    {
        $this->request->expects($this->once())
            ->method('get')->with('_target_path')
            ->will($this->returnValue('/dashboard'));

        $response = $this->expectRedirectResponse('/dashboard');

        $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, array());
        $result = $handler->onAuthenticationSuccess($this->request, $this->token);

        $this->assertSame($response, $result);
    }

    public function testTargetPathParameterIsCustomised()
    {
        $options = array('target_path_parameter' => '_my_target_path');

        $this->request->expects($this->once())
            ->method('get')->with('_my_target_path')
            ->will($this->returnValue('/dashboard'));

        $response = $this->expectRedirectResponse('/dashboard');

        $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, $options);
        $result = $handler->onAuthenticationSuccess($this->request, $this->token);

        $this->assertSame($response, $result);
    }

    public function testTargetPathIsTakenFromTheSession()
    {
        $session = $this->getMock('Symfony\Component\HttpFoundation\Session\SessionInterface');
        $session->expects($this->once())
            ->method('get')->with('_security.admin.target_path')
            ->will($this->returnValue('/admin/dashboard'));
        $session->expects($this->once())
            ->method('remove')->with('_security.admin.target_path');

        $this->request->expects($this->any())
            ->method('getSession')
            ->will($this->returnValue($session));

        $response = $this->expectRedirectResponse('/admin/dashboard');

        $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, array());
        $handler->setProviderKey('admin');

        $result = $handler->onAuthenticationSuccess($this->request, $this->token);

        $this->assertSame($response, $result);
    }

    public function testTargetPathIsPassedAsReferer()
    {
        $options = array('use_referer' => true);

        $this->request->headers->expects($this->once())
            ->method('get')->with('Referer')
            ->will($this->returnValue('/dashboard'));

        $response = $this->expectRedirectResponse('/dashboard');

        $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, $options);
        $result = $handler->onAuthenticationSuccess($this->request, $this->token);

        $this->assertSame($response, $result);
    }

    public function testRefererHasToBeDifferentThatLoginUrl()
    {
        $options = array('use_referer' => true);

        $this->request->headers->expects($this->any())
            ->method('get')->with('Referer')
            ->will($this->returnValue('/login'));

        $this->httpUtils->expects($this->once())
            ->method('generateUri')->with($this->request, '/login')
            ->will($this->returnValue('/login'));

        $response = $this->expectRedirectResponse('/');

        $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, $options);
        $result = $handler->onAuthenticationSuccess($this->request, $this->token);

        $this->assertSame($response, $result);
    }

    public function testRefererTargetPathIsIgnoredByDefault()
    {
        $this->request->headers->expects($this->never())->method('get');

        $response = $this->expectRedirectResponse('/');

        $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, array());
        $result = $handler->onAuthenticationSuccess($this->request, $this->token);

        $this->assertSame($response, $result);
    }

    private function expectRedirectResponse($path)
    {
        $response = $this->getMock('Symfony\Component\HttpFoundation\Response');

        $this->httpUtils->expects($this->once())
            ->method('createRedirectResponse')
            ->with($this->request, $path)
            ->will($this->returnValue($response));

        return $response;
    }
}
PK��Z?k,.<<>test/Security/Symfony/Component/Security/Http/phpunit.xml.distnu�[���<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony Security Component HTTP Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./vendor</directory>
                <directory>./Tests</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
PK��Z�|G

btest/Security/Symfony/Component/Security/Csrf/Tests/TokenStorage/NativeSessionTokenStorageTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Csrf\Tests\TokenStorage;

use Symfony\Component\Security\Csrf\TokenStorage\NativeSessionTokenStorage;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @runTestsInSeparateProcesses
 */
class NativeSessionTokenStorageTest extends \PHPUnit_Framework_TestCase
{
    const SESSION_NAMESPACE = 'foobar';

    /**
     * @var NativeSessionTokenStorage
     */
    private $storage;

    public static function setUpBeforeClass()
    {
        ini_set('session.save_handler', 'files');
        ini_set('session.save_path', sys_get_temp_dir());

        parent::setUpBeforeClass();
    }

    protected function setUp()
    {
        $_SESSION = array();

        $this->storage = new NativeSessionTokenStorage(self::SESSION_NAMESPACE);
    }

    public function testStoreTokenInClosedSession()
    {
        $this->storage->setToken('token_id', 'TOKEN');

        $this->assertSame(array(self::SESSION_NAMESPACE => array('token_id' => 'TOKEN')), $_SESSION);
    }

    public function testStoreTokenInClosedSessionWithExistingSessionId()
    {
        if (version_compare(PHP_VERSION, '5.4', '<')) {
            $this->markTestSkipped('This test requires PHP 5.4 or later.');
        }

        session_id('foobar');

        $this->assertSame(PHP_SESSION_NONE, session_status());

        $this->storage->setToken('token_id', 'TOKEN');

        $this->assertSame(PHP_SESSION_ACTIVE, session_status());
        $this->assertSame(array(self::SESSION_NAMESPACE => array('token_id' => 'TOKEN')), $_SESSION);
    }

    public function testStoreTokenInActiveSession()
    {
        session_start();

        $this->storage->setToken('token_id', 'TOKEN');

        $this->assertSame(array(self::SESSION_NAMESPACE => array('token_id' => 'TOKEN')), $_SESSION);
    }

    /**
     * @depends testStoreTokenInClosedSession
     */
    public function testCheckToken()
    {
        $this->assertFalse($this->storage->hasToken('token_id'));

        $this->storage->setToken('token_id', 'TOKEN');

        $this->assertTrue($this->storage->hasToken('token_id'));
    }

    /**
     * @depends testStoreTokenInClosedSession
     */
    public function testGetExistingToken()
    {
        $this->storage->setToken('token_id', 'TOKEN');

        $this->assertSame('TOKEN', $this->storage->getToken('token_id'));
    }

    /**
     * @expectedException \Symfony\Component\Security\Csrf\Exception\TokenNotFoundException
     */
    public function testGetNonExistingToken()
    {
        $this->storage->getToken('token_id');
    }

    /**
     * @depends testCheckToken
     */
    public function testRemoveNonExistingToken()
    {
        $this->assertNull($this->storage->removeToken('token_id'));
        $this->assertFalse($this->storage->hasToken('token_id'));
    }

    /**
     * @depends testCheckToken
     */
    public function testRemoveExistingToken()
    {
        $this->storage->setToken('token_id', 'TOKEN');

        $this->assertSame('TOKEN', $this->storage->removeToken('token_id'));
        $this->assertFalse($this->storage->hasToken('token_id'));
    }
}
PK��Z���WW\test/Security/Symfony/Component/Security/Csrf/Tests/TokenStorage/SessionTokenStorageTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Csrf\Tests\TokenStorage;

use Symfony\Component\Security\Csrf\TokenStorage\SessionTokenStorage;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class SessionTokenStorageTest extends \PHPUnit_Framework_TestCase
{
    const SESSION_NAMESPACE = 'foobar';

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $session;

    /**
     * @var SessionTokenStorage
     */
    private $storage;

    protected function setUp()
    {
        if (!interface_exists('Symfony\Component\HttpFoundation\Session\SessionInterface')) {
            $this->markTestSkipped('The "HttpFoundation" component is not available');
        }

        $this->session = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\SessionInterface')
            ->disableOriginalConstructor()
            ->getMock();
        $this->storage = new SessionTokenStorage($this->session, self::SESSION_NAMESPACE);
    }

    public function testStoreTokenInClosedSession()
    {
        $this->session->expects($this->any())
            ->method('isStarted')
            ->will($this->returnValue(false));

        $this->session->expects($this->once())
            ->method('start');

        $this->session->expects($this->once())
            ->method('set')
            ->with(self::SESSION_NAMESPACE.'/token_id', 'TOKEN');

        $this->storage->setToken('token_id', 'TOKEN');
    }

    public function testStoreTokenInActiveSession()
    {
        $this->session->expects($this->any())
            ->method('isStarted')
            ->will($this->returnValue(true));

        $this->session->expects($this->never())
            ->method('start');

        $this->session->expects($this->once())
            ->method('set')
            ->with(self::SESSION_NAMESPACE.'/token_id', 'TOKEN');

        $this->storage->setToken('token_id', 'TOKEN');
    }

    public function testCheckTokenInClosedSession()
    {
        $this->session->expects($this->any())
            ->method('isStarted')
            ->will($this->returnValue(false));

        $this->session->expects($this->once())
            ->method('start');

        $this->session->expects($this->once())
            ->method('has')
            ->with(self::SESSION_NAMESPACE.'/token_id')
            ->will($this->returnValue('RESULT'));

        $this->assertSame('RESULT', $this->storage->hasToken('token_id'));
    }

    public function testCheckTokenInActiveSession()
    {
        $this->session->expects($this->any())
            ->method('isStarted')
            ->will($this->returnValue(true));

        $this->session->expects($this->never())
            ->method('start');

        $this->session->expects($this->once())
            ->method('has')
            ->with(self::SESSION_NAMESPACE.'/token_id')
            ->will($this->returnValue('RESULT'));

        $this->assertSame('RESULT', $this->storage->hasToken('token_id'));
    }

    public function testGetExistingTokenFromClosedSession()
    {
        $this->session->expects($this->any())
            ->method('isStarted')
            ->will($this->returnValue(false));

        $this->session->expects($this->once())
            ->method('start');

        $this->session->expects($this->once())
            ->method('has')
            ->with(self::SESSION_NAMESPACE.'/token_id')
            ->will($this->returnValue(true));

        $this->session->expects($this->once())
            ->method('get')
            ->with(self::SESSION_NAMESPACE.'/token_id')
            ->will($this->returnValue('RESULT'));

        $this->assertSame('RESULT', $this->storage->getToken('token_id'));
    }

    public function testGetExistingTokenFromActiveSession()
    {
        $this->session->expects($this->any())
            ->method('isStarted')
            ->will($this->returnValue(true));

        $this->session->expects($this->never())
            ->method('start');

        $this->session->expects($this->once())
            ->method('has')
            ->with(self::SESSION_NAMESPACE.'/token_id')
            ->will($this->returnValue(true));

        $this->session->expects($this->once())
            ->method('get')
            ->with(self::SESSION_NAMESPACE.'/token_id')
            ->will($this->returnValue('RESULT'));

        $this->assertSame('RESULT', $this->storage->getToken('token_id'));
    }

    /**
     * @expectedException \Symfony\Component\Security\Csrf\Exception\TokenNotFoundException
     */
    public function testGetNonExistingTokenFromClosedSession()
    {
        $this->session->expects($this->any())
            ->method('isStarted')
            ->will($this->returnValue(false));

        $this->session->expects($this->once())
            ->method('start');

        $this->session->expects($this->once())
            ->method('has')
            ->with(self::SESSION_NAMESPACE.'/token_id')
            ->will($this->returnValue(false));

        $this->storage->getToken('token_id');
    }

    /**
     * @expectedException \Symfony\Component\Security\Csrf\Exception\TokenNotFoundException
     */
    public function testGetNonExistingTokenFromActiveSession()
    {
        $this->session->expects($this->any())
            ->method('isStarted')
            ->will($this->returnValue(true));

        $this->session->expects($this->never())
            ->method('start');

        $this->session->expects($this->once())
            ->method('has')
            ->with(self::SESSION_NAMESPACE.'/token_id')
            ->will($this->returnValue(false));

        $this->storage->getToken('token_id');
    }

    public function testRemoveNonExistingTokenFromClosedSession()
    {
        $this->session->expects($this->any())
            ->method('isStarted')
            ->will($this->returnValue(false));

        $this->session->expects($this->once())
            ->method('start');

        $this->session->expects($this->once())
            ->method('remove')
            ->with(self::SESSION_NAMESPACE.'/token_id')
            ->will($this->returnValue(null));

        $this->assertNull($this->storage->removeToken('token_id'));
    }

    public function testRemoveNonExistingTokenFromActiveSession()
    {
        $this->session->expects($this->any())
            ->method('isStarted')
            ->will($this->returnValue(true));

        $this->session->expects($this->never())
            ->method('start');

        $this->session->expects($this->once())
            ->method('remove')
            ->with(self::SESSION_NAMESPACE.'/token_id')
            ->will($this->returnValue(null));

        $this->assertNull($this->storage->removeToken('token_id'));
    }

    public function testRemoveExistingTokenFromClosedSession()
    {
        $this->session->expects($this->any())
            ->method('isStarted')
            ->will($this->returnValue(false));

        $this->session->expects($this->once())
            ->method('start');

        $this->session->expects($this->once())
            ->method('remove')
            ->with(self::SESSION_NAMESPACE.'/token_id')
            ->will($this->returnValue('TOKEN'));

        $this->assertSame('TOKEN', $this->storage->removeToken('token_id'));
    }

    public function testRemoveExistingTokenFromActiveSession()
    {
        $this->session->expects($this->any())
            ->method('isStarted')
            ->will($this->returnValue(true));

        $this->session->expects($this->never())
            ->method('start');

        $this->session->expects($this->once())
            ->method('remove')
            ->with(self::SESSION_NAMESPACE.'/token_id')
            ->will($this->returnValue('TOKEN'));

        $this->assertSame('TOKEN', $this->storage->removeToken('token_id'));
    }
}
PK��Z�-�kkLtest/Security/Symfony/Component/Security/Csrf/Tests/CsrfTokenManagerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Csrf\Tests;

use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManager;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class CsrfTokenManagerTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $generator;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $storage;

    /**
     * @var CsrfTokenManager
     */
    private $manager;

    protected function setUp()
    {
        $this->generator = $this->getMock('Symfony\Component\Security\Csrf\TokenGenerator\TokenGeneratorInterface');
        $this->storage = $this->getMock('Symfony\Component\Security\Csrf\TokenStorage\TokenStorageInterface');
        $this->manager = new CsrfTokenManager($this->generator, $this->storage);
    }

    protected function tearDown()
    {
        $this->generator = null;
        $this->storage = null;
        $this->manager = null;
    }

    public function testGetNonExistingToken()
    {
        $this->storage->expects($this->once())
            ->method('hasToken')
            ->with('token_id')
            ->will($this->returnValue(false));

        $this->generator->expects($this->once())
            ->method('generateToken')
            ->will($this->returnValue('TOKEN'));

        $this->storage->expects($this->once())
            ->method('setToken')
            ->with('token_id', 'TOKEN');

        $token = $this->manager->getToken('token_id');

        $this->assertInstanceOf('Symfony\Component\Security\Csrf\CsrfToken', $token);
        $this->assertSame('token_id', $token->getId());
        $this->assertSame('TOKEN', $token->getValue());
    }

    public function testUseExistingTokenIfAvailable()
    {
        $this->storage->expects($this->once())
            ->method('hasToken')
            ->with('token_id')
            ->will($this->returnValue(true));

        $this->storage->expects($this->once())
            ->method('getToken')
            ->with('token_id')
            ->will($this->returnValue('TOKEN'));

        $token = $this->manager->getToken('token_id');

        $this->assertInstanceOf('Symfony\Component\Security\Csrf\CsrfToken', $token);
        $this->assertSame('token_id', $token->getId());
        $this->assertSame('TOKEN', $token->getValue());
    }

    public function testRefreshTokenAlwaysReturnsNewToken()
    {
        $this->storage->expects($this->never())
            ->method('hasToken');

        $this->generator->expects($this->once())
            ->method('generateToken')
            ->will($this->returnValue('TOKEN'));

        $this->storage->expects($this->once())
            ->method('setToken')
            ->with('token_id', 'TOKEN');

        $token = $this->manager->refreshToken('token_id');

        $this->assertInstanceOf('Symfony\Component\Security\Csrf\CsrfToken', $token);
        $this->assertSame('token_id', $token->getId());
        $this->assertSame('TOKEN', $token->getValue());
    }

    public function testMatchingTokenIsValid()
    {
        $this->storage->expects($this->once())
            ->method('hasToken')
            ->with('token_id')
            ->will($this->returnValue(true));

        $this->storage->expects($this->once())
            ->method('getToken')
            ->with('token_id')
            ->will($this->returnValue('TOKEN'));

        $this->assertTrue($this->manager->isTokenValid(new CsrfToken('token_id', 'TOKEN')));
    }

    public function testNonMatchingTokenIsNotValid()
    {
        $this->storage->expects($this->once())
            ->method('hasToken')
            ->with('token_id')
            ->will($this->returnValue(true));

        $this->storage->expects($this->once())
            ->method('getToken')
            ->with('token_id')
            ->will($this->returnValue('TOKEN'));

        $this->assertFalse($this->manager->isTokenValid(new CsrfToken('token_id', 'FOOBAR')));
    }

    public function testNonExistingTokenIsNotValid()
    {
        $this->storage->expects($this->once())
            ->method('hasToken')
            ->with('token_id')
            ->will($this->returnValue(false));

        $this->storage->expects($this->never())
            ->method('getToken');

        $this->assertFalse($this->manager->isTokenValid(new CsrfToken('token_id', 'FOOBAR')));
    }

    public function testRemoveToken()
    {
        $this->storage->expects($this->once())
            ->method('removeToken')
            ->with('token_id')
            ->will($this->returnValue('REMOVED_TOKEN'));

        $this->assertSame('REMOVED_TOKEN', $this->manager->removeToken('token_id'));
    }
}
PK��Z�3�z((`test/Security/Symfony/Component/Security/Csrf/Tests/TokenGenerator/UriSafeTokenGeneratorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Csrf\Tests\TokenGenerator;

use Symfony\Component\Security\Csrf\TokenGenerator\UriSafeTokenGenerator;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class UriSafeTokenGeneratorTest extends \PHPUnit_Framework_TestCase
{
    const ENTROPY = 1000;

    /**
     * A non alpha-numeric byte string
     * @var string
     */
    private static $bytes;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $random;

    /**
     * @var UriSafeTokenGenerator
     */
    private $generator;

    public static function setUpBeforeClass()
    {
        self::$bytes = base64_decode('aMf+Tct/RLn2WQ==');
    }

    protected function setUp()
    {
        $this->random = $this->getMock('Symfony\Component\Security\Core\Util\SecureRandomInterface');
        $this->generator = new UriSafeTokenGenerator($this->random, self::ENTROPY);
    }

    protected function tearDown()
    {
        $this->random = null;
        $this->generator = null;
    }

    public function testGenerateToken()
    {
        $this->random->expects($this->once())
            ->method('nextBytes')
            ->with(self::ENTROPY/8)
            ->will($this->returnValue(self::$bytes));

        $token = $this->generator->generateToken();

        $this->assertTrue(ctype_print($token), 'is printable');
        $this->assertStringNotMatchesFormat('%S+%S', $token, 'is URI safe');
        $this->assertStringNotMatchesFormat('%S/%S', $token, 'is URI safe');
        $this->assertStringNotMatchesFormat('%S=%S', $token, 'is URI safe');
    }
}
PK��Z��*�<<>test/Security/Symfony/Component/Security/Csrf/phpunit.xml.distnu�[���<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony Security Component CSRF Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./vendor</directory>
                <directory>./Tests</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
PK��ZׄHAnnKtest/Security/Symfony/Component/Security/Core/Tests/SecurityContextTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests;

use Symfony\Component\Security\Core\SecurityContext;

class SecurityContextTest extends \PHPUnit_Framework_TestCase
{
    public function testVoteAuthenticatesTokenIfNecessary()
    {
        $authManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface');
        $decisionManager = $this->getMock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface');

        $context = new SecurityContext($authManager, $decisionManager);
        $context->setToken($token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'));

        $authManager
            ->expects($this->once())
            ->method('authenticate')
            ->with($this->equalTo($token))
            ->will($this->returnValue($newToken = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')))
        ;

        $decisionManager
            ->expects($this->once())
            ->method('decide')
            ->will($this->returnValue(true))
        ;

        $this->assertTrue($context->isGranted('foo'));
        $this->assertSame($newToken, $context->getToken());
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException
     */
    public function testVoteWithoutAuthenticationToken()
    {
        $context = new SecurityContext(
            $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'),
            $this->getMock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface')
        );

        $context->isGranted('ROLE_FOO');
    }

    public function testIsGranted()
    {
        $manager = $this->getMock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface');
        $manager->expects($this->once())->method('decide')->will($this->returnValue(false));
        $context = new SecurityContext($this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'), $manager);
        $context->setToken($token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'));
        $token
            ->expects($this->once())
            ->method('isAuthenticated')
            ->will($this->returnValue(true))
        ;
        $this->assertFalse($context->isGranted('ROLE_FOO'));

        $manager = $this->getMock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface');
        $manager->expects($this->once())->method('decide')->will($this->returnValue(true));
        $context = new SecurityContext($this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'), $manager);
        $context->setToken($token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'));
        $token
            ->expects($this->once())
            ->method('isAuthenticated')
            ->will($this->returnValue(true))
        ;
        $this->assertTrue($context->isGranted('ROLE_FOO'));
    }

    public function testGetSetToken()
    {
        $context = new SecurityContext(
            $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'),
            $this->getMock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface')
        );
        $this->assertNull($context->getToken());

        $context->setToken($token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'));
        $this->assertSame($token, $context->getToken());
    }
}
PK��ZxF�Etest/Security/Symfony/Component/Security/Core/Tests/Role/RoleTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Role;

use Symfony\Component\Security\Core\Role\Role;

class RoleTest extends \PHPUnit_Framework_TestCase
{
    public function testGetRole()
    {
        $role = new Role('FOO');

        $this->assertEquals('FOO', $role->getRole());
    }
}
PK��Zt�S��Ntest/Security/Symfony/Component/Security/Core/Tests/Role/RoleHierarchyTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Role;

use Symfony\Component\Security\Core\Role\RoleHierarchy;
use Symfony\Component\Security\Core\Role\Role;

class RoleHierarchyTest extends \PHPUnit_Framework_TestCase
{
    public function testGetReachableRoles()
    {
        $role = new RoleHierarchy(array(
            'ROLE_ADMIN' => array('ROLE_USER'),
            'ROLE_SUPER_ADMIN' => array('ROLE_ADMIN', 'ROLE_FOO'),
        ));

        $this->assertEquals(array(new Role('ROLE_USER')), $role->getReachableRoles(array(new Role('ROLE_USER'))));
        $this->assertEquals(array(new Role('ROLE_FOO')), $role->getReachableRoles(array(new Role('ROLE_FOO'))));
        $this->assertEquals(array(new Role('ROLE_ADMIN'), new Role('ROLE_USER')), $role->getReachableRoles(array(new Role('ROLE_ADMIN'))));
        $this->assertEquals(array(new Role('ROLE_FOO'), new Role('ROLE_ADMIN'), new Role('ROLE_USER')), $role->getReachableRoles(array(new Role('ROLE_FOO'), new Role('ROLE_ADMIN'))));
        $this->assertEquals(array(new Role('ROLE_SUPER_ADMIN'), new Role('ROLE_ADMIN'), new Role('ROLE_FOO'), new Role('ROLE_USER')), $role->getReachableRoles(array(new Role('ROLE_SUPER_ADMIN'))));
    }
}
PK��Z��{{Otest/Security/Symfony/Component/Security/Core/Tests/Role/SwitchUserRoleTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Role;

use Symfony\Component\Security\Core\Role\SwitchUserRole;

class SwitchUserRoleTest extends \PHPUnit_Framework_TestCase
{
    public function testGetSource()
    {
        $role = new SwitchUserRole('FOO', $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'));

        $this->assertSame($token, $role->getSource());
    }

    public function testGetRole()
    {
        $role = new SwitchUserRole('FOO', $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'));

        $this->assertEquals('FOO', $role->getRole());
    }
}
PK��Zr��nnYtest/Security/Symfony/Component/Security/Core/Tests/Encoder/Pbkdf2PasswordEncoderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Encoder;

use Symfony\Component\Security\Core\Encoder\Pbkdf2PasswordEncoder;

class Pbkdf2PasswordEncoderTest extends \PHPUnit_Framework_TestCase
{
    public function testIsPasswordValid()
    {
        $encoder = new Pbkdf2PasswordEncoder('sha256', false, 1, 40);

        $this->assertTrue($encoder->isPasswordValid('c1232f10f62715fda06ae7c0a2037ca19b33cf103b727ba56d870c11f290a2ab106974c75607c8a3', 'password', ''));
    }

    public function testEncodePassword()
    {
        $encoder = new Pbkdf2PasswordEncoder('sha256', false, 1, 40);
        $this->assertSame('c1232f10f62715fda06ae7c0a2037ca19b33cf103b727ba56d870c11f290a2ab106974c75607c8a3', $encoder->encodePassword('password', ''));

        $encoder = new Pbkdf2PasswordEncoder('sha256', true, 1, 40);
        $this->assertSame('wSMvEPYnFf2gaufAogN8oZszzxA7cnulbYcMEfKQoqsQaXTHVgfIow==', $encoder->encodePassword('password', ''));

        $encoder = new Pbkdf2PasswordEncoder('sha256', false, 2, 40);
        $this->assertSame('8bc2f9167a81cdcfad1235cd9047f1136271c1f978fcfcb35e22dbeafa4634f6fd2214218ed63ebb', $encoder->encodePassword('password', ''));
    }

    /**
     * @expectedException \LogicException
     */
    public function testEncodePasswordAlgorithmDoesNotExist()
    {
        $encoder = new Pbkdf2PasswordEncoder('foobar');
        $encoder->encodePassword('password', '');
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
     */
    public function testEncodePasswordLength()
    {
        $encoder = new Pbkdf2PasswordEncoder('foobar');

        $encoder->encodePassword(str_repeat('a', 5000), 'salt');
    }

    public function testCheckPasswordLength()
    {
        $encoder = new Pbkdf2PasswordEncoder('foobar');

        $this->assertFalse($encoder->isPasswordValid('encoded', str_repeat('a', 5000), 'salt'));
    }
}
PK��Z6���\test/Security/Symfony/Component/Security/Core/Tests/Encoder/PlaintextPasswordEncoderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Encoder;

use Symfony\Component\Security\Core\Encoder\PlaintextPasswordEncoder;

class PlaintextPasswordEncoderTest extends \PHPUnit_Framework_TestCase
{
    public function testIsPasswordValid()
    {
        $encoder = new PlaintextPasswordEncoder();

        $this->assertTrue($encoder->isPasswordValid('foo', 'foo', ''));
        $this->assertFalse($encoder->isPasswordValid('bar', 'foo', ''));
        $this->assertFalse($encoder->isPasswordValid('FOO', 'foo', ''));

        $encoder = new PlaintextPasswordEncoder(true);

        $this->assertTrue($encoder->isPasswordValid('foo', 'foo', ''));
        $this->assertFalse($encoder->isPasswordValid('bar', 'foo', ''));
        $this->assertTrue($encoder->isPasswordValid('FOO', 'foo', ''));
    }

    public function testEncodePassword()
    {
        $encoder = new PlaintextPasswordEncoder();

        $this->assertSame('foo', $encoder->encodePassword('foo', ''));
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
     */
    public function testEncodePasswordLength()
    {
        $encoder = new PlaintextPasswordEncoder();

        $encoder->encodePassword(str_repeat('a', 5000), 'salt');
    }

    public function testCheckPasswordLength()
    {
        $encoder = new PlaintextPasswordEncoder();

        $this->assertFalse($encoder->isPasswordValid('encoded', str_repeat('a', 5000), 'salt'));
    }
}
PK��ZL�'��Wtest/Security/Symfony/Component/Security/Core/Tests/Encoder/BasePasswordEncoderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Encoder;

use Symfony\Component\Security\Core\Encoder\BasePasswordEncoder;

class PasswordEncoder extends BasePasswordEncoder
{
    public function encodePassword($raw, $salt)
    {
    }

    public function isPasswordValid($encoded, $raw, $salt)
    {
    }
}

class BasePasswordEncoderTest extends \PHPUnit_Framework_TestCase
{
    public function testComparePassword()
    {
        $this->assertTrue($this->invokeComparePasswords('password', 'password'));
        $this->assertFalse($this->invokeComparePasswords('password', 'foo'));
    }

    public function testDemergePasswordAndSalt()
    {
        $this->assertEquals(array('password', 'salt'), $this->invokeDemergePasswordAndSalt('password{salt}'));
        $this->assertEquals(array('password', ''), $this->invokeDemergePasswordAndSalt('password'));
        $this->assertEquals(array('', ''), $this->invokeDemergePasswordAndSalt(''));
    }

    public function testMergePasswordAndSalt()
    {
        $this->assertEquals('password{salt}', $this->invokeMergePasswordAndSalt('password', 'salt'));
        $this->assertEquals('password', $this->invokeMergePasswordAndSalt('password', ''));
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testMergePasswordAndSaltWithException()
    {
        $this->invokeMergePasswordAndSalt('password', '{foo}');
    }

    public function testIsPasswordTooLong()
    {
        $this->assertTrue($this->invokeIsPasswordTooLong(str_repeat('a', 10000)));
        $this->assertFalse($this->invokeIsPasswordTooLong(str_repeat('a', 10)));
    }

    protected function invokeDemergePasswordAndSalt($password)
    {
        $encoder = new PasswordEncoder();
        $r = new \ReflectionObject($encoder);
        $m = $r->getMethod('demergePasswordAndSalt');
        $m->setAccessible(true);

        return $m->invoke($encoder, $password);
    }

    protected function invokeMergePasswordAndSalt($password, $salt)
    {
        $encoder = new PasswordEncoder();
        $r = new \ReflectionObject($encoder);
        $m = $r->getMethod('mergePasswordAndSalt');
        $m->setAccessible(true);

        return $m->invoke($encoder, $password, $salt);
    }

    protected function invokeComparePasswords($p1, $p2)
    {
        $encoder = new PasswordEncoder();
        $r = new \ReflectionObject($encoder);
        $m = $r->getMethod('comparePasswords');
        $m->setAccessible(true);

        return $m->invoke($encoder, $p1, $p2);
    }

    protected function invokeIsPasswordTooLong($p)
    {
        $encoder = new PasswordEncoder();
        $r = new \ReflectionObject($encoder);
        $m = $r->getMethod('isPasswordTooLong');
        $m->setAccessible(true);

        return $m->invoke($encoder, $p);
    }
}
PK��Z%�s�Rtest/Security/Symfony/Component/Security/Core/Tests/Encoder/EncoderFactoryTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Encoder;

use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder;
use Symfony\Component\Security\Core\Encoder\EncoderFactory;
use Symfony\Component\Security\Core\User\User;
use Symfony\Component\Security\Core\User\UserInterface;

class EncoderFactoryTest extends \PHPUnit_Framework_TestCase
{
    public function testGetEncoderWithMessageDigestEncoder()
    {
        $factory = new EncoderFactory(array('Symfony\Component\Security\Core\User\UserInterface' => array(
            'class' => 'Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder',
            'arguments' => array('sha512', true, 5),
        )));

        $encoder = $factory->getEncoder($this->getMock('Symfony\Component\Security\Core\User\UserInterface'));
        $expectedEncoder = new MessageDigestPasswordEncoder('sha512', true, 5);

        $this->assertEquals($expectedEncoder->encodePassword('foo', 'moo'), $encoder->encodePassword('foo', 'moo'));
    }

    public function testGetEncoderWithService()
    {
        $factory = new EncoderFactory(array(
            'Symfony\Component\Security\Core\User\UserInterface' => new MessageDigestPasswordEncoder('sha1'),
        ));

        $encoder = $factory->getEncoder($this->getMock('Symfony\Component\Security\Core\User\UserInterface'));
        $expectedEncoder = new MessageDigestPasswordEncoder('sha1');
        $this->assertEquals($expectedEncoder->encodePassword('foo', ''), $encoder->encodePassword('foo', ''));

        $encoder = $factory->getEncoder(new User('user', 'pass'));
        $expectedEncoder = new MessageDigestPasswordEncoder('sha1');
        $this->assertEquals($expectedEncoder->encodePassword('foo', ''), $encoder->encodePassword('foo', ''));
    }

    public function testGetEncoderWithClassName()
    {
        $factory = new EncoderFactory(array(
            'Symfony\Component\Security\Core\User\UserInterface' => new MessageDigestPasswordEncoder('sha1'),
        ));

        $encoder = $factory->getEncoder('Symfony\Component\Security\Core\Tests\Encoder\SomeChildUser');
        $expectedEncoder = new MessageDigestPasswordEncoder('sha1');
        $this->assertEquals($expectedEncoder->encodePassword('foo', ''), $encoder->encodePassword('foo', ''));
    }

    public function testGetEncoderConfiguredForConcreteClassWithService()
    {
        $factory = new EncoderFactory(array(
            'Symfony\Component\Security\Core\User\User' => new MessageDigestPasswordEncoder('sha1'),
        ));

        $encoder = $factory->getEncoder(new User('user', 'pass'));
        $expectedEncoder = new MessageDigestPasswordEncoder('sha1');
        $this->assertEquals($expectedEncoder->encodePassword('foo', ''), $encoder->encodePassword('foo', ''));
    }

    public function testGetEncoderConfiguredForConcreteClassWithClassName()
    {
        $factory = new EncoderFactory(array(
            'Symfony\Component\Security\Core\Tests\Encoder\SomeUser' => new MessageDigestPasswordEncoder('sha1'),
        ));

        $encoder = $factory->getEncoder('Symfony\Component\Security\Core\Tests\Encoder\SomeChildUser');
        $expectedEncoder = new MessageDigestPasswordEncoder('sha1');
        $this->assertEquals($expectedEncoder->encodePassword('foo', ''), $encoder->encodePassword('foo', ''));
    }
}

class SomeUser implements UserInterface
{
    public function getRoles() {}
    public function getPassword() {}
    public function getSalt() {}
    public function getUsername() {}
    public function eraseCredentials() {}
}

class SomeChildUser extends SomeUser
{
}
PK��Ze5���`test/Security/Symfony/Component/Security/Core/Tests/Encoder/MessageDigestPasswordEncoderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Encoder;

use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder;

class MessageDigestPasswordEncoderTest extends \PHPUnit_Framework_TestCase
{
    public function testIsPasswordValid()
    {
        $encoder = new MessageDigestPasswordEncoder('sha256', false, 1);

        $this->assertTrue($encoder->isPasswordValid(hash('sha256', 'password'), 'password', ''));
    }

    public function testEncodePassword()
    {
        $encoder = new MessageDigestPasswordEncoder('sha256', false, 1);
        $this->assertSame(hash('sha256', 'password'), $encoder->encodePassword('password', ''));

        $encoder = new MessageDigestPasswordEncoder('sha256', true, 1);
        $this->assertSame(base64_encode(hash('sha256', 'password', true)), $encoder->encodePassword('password', ''));

        $encoder = new MessageDigestPasswordEncoder('sha256', false, 2);
        $this->assertSame(hash('sha256', hash('sha256', 'password', true).'password'), $encoder->encodePassword('password', ''));
    }

    /**
     * @expectedException \LogicException
     */
    public function testEncodePasswordAlgorithmDoesNotExist()
    {
        $encoder = new MessageDigestPasswordEncoder('foobar');
        $encoder->encodePassword('password', '');
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
     */
    public function testEncodePasswordLength()
    {
        $encoder = new MessageDigestPasswordEncoder();

        $encoder->encodePassword(str_repeat('a', 5000), 'salt');
    }

    public function testCheckPasswordLength()
    {
        $encoder = new MessageDigestPasswordEncoder();

        $this->assertFalse($encoder->isPasswordValid('encoded', str_repeat('a', 5000), 'salt'));
    }
}
PK��Z!�?��	�	Ytest/Security/Symfony/Component/Security/Core/Tests/Encoder/BCryptPasswordEncoderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Encoder;

use Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder;

/**
 * @author Elnur Abdurrakhimov <elnur@elnur.pro>
 */
class BCryptPasswordEncoderTest extends \PHPUnit_Framework_TestCase
{
    const PASSWORD = 'password';
    const BYTES = '0123456789abcdef';
    const VALID_COST = '04';

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testCostBelowRange()
    {
        new BCryptPasswordEncoder(3);
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testCostAboveRange()
    {
        new BCryptPasswordEncoder(32);
    }

    public function testCostInRange()
    {
        for ($cost = 4; $cost <= 31; $cost++) {
            new BCryptPasswordEncoder($cost);
        }
    }

    public function testResultLength()
    {
        $this->skipIfPhpVersionIsNotSupported();

        $encoder = new BCryptPasswordEncoder(self::VALID_COST);
        $result = $encoder->encodePassword(self::PASSWORD, null);
        $this->assertEquals(60, strlen($result));
    }

    public function testValidation()
    {
        $this->skipIfPhpVersionIsNotSupported();

        $encoder = new BCryptPasswordEncoder(self::VALID_COST);
        $result = $encoder->encodePassword(self::PASSWORD, null);
        $this->assertTrue($encoder->isPasswordValid($result, self::PASSWORD, null));
        $this->assertFalse($encoder->isPasswordValid($result, 'anotherPassword', null));
    }

    private function skipIfPhpVersionIsNotSupported()
    {
        if (version_compare(phpversion(), '5.3.7', '<')) {
            $this->markTestSkipped('Requires PHP >= 5.3.7');
        }
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
     */
    public function testEncodePasswordLength()
    {
        $encoder = new BCryptPasswordEncoder(self::VALID_COST);

        $encoder->encodePassword(str_repeat('a', 5000), 'salt');
    }

    public function testCheckPasswordLength()
    {
        $encoder = new BCryptPasswordEncoder(self::VALID_COST);

        $this->assertFalse($encoder->isPasswordValid('encoded', str_repeat('a', 5000), 'salt'));
    }
}
PK��Z�����gtest/Security/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Validator\Constraints;

use Symfony\Component\Security\Core\Validator\Constraints\UserPassword;
use Symfony\Component\Security\Core\Validator\Constraints\UserPasswordValidator;

class UserPasswordValidatorTest extends \PHPUnit_Framework_TestCase
{
    const PASSWORD_VALID   = true;
    const PASSWORD_INVALID = false;

    protected $context;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
    }

    protected function tearDown()
    {
        $this->context = null;
    }

    public function testPasswordIsValid()
    {
        $user = $this->createUser();
        $securityContext = $this->createSecurityContext($user);

        $encoder = $this->createPasswordEncoder(static::PASSWORD_VALID);
        $encoderFactory = $this->createEncoderFactory($encoder);

        $validator = new UserPasswordValidator($securityContext, $encoderFactory);
        $validator->initialize($this->context);

        $this
            ->context
            ->expects($this->never())
            ->method('addViolation')
        ;

        $validator->validate('secret', new UserPassword());
    }

    public function testPasswordIsNotValid()
    {
        $user = $this->createUser();
        $securityContext = $this->createSecurityContext($user);

        $encoder = $this->createPasswordEncoder(static::PASSWORD_INVALID);
        $encoderFactory = $this->createEncoderFactory($encoder);

        $validator = new UserPasswordValidator($securityContext, $encoderFactory);
        $validator->initialize($this->context);

        $this
            ->context
            ->expects($this->once())
            ->method('addViolation')
        ;

        $validator->validate('secret', new UserPassword());
    }

    public function testUserIsNotValid()
    {
        $this->setExpectedException('Symfony\Component\Validator\Exception\ConstraintDefinitionException');

        $user = $this->getMock('Foo\Bar\User');
        $encoderFactory = $this->getMock('Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface');
        $securityContext = $this->createSecurityContext($user);

        $validator = new UserPasswordValidator($securityContext, $encoderFactory);
        $validator->initialize($this->context);
        $validator->validate('secret', new UserPassword());
    }

    protected function createUser()
    {
        $mock = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');

        $mock
            ->expects($this->once())
            ->method('getPassword')
            ->will($this->returnValue('s3Cr3t'))
        ;

        $mock
            ->expects($this->once())
            ->method('getSalt')
            ->will($this->returnValue('^S4lt$'))
        ;

        return $mock;
    }

    protected function createPasswordEncoder($isPasswordValid = true)
    {
        $mock = $this->getMock('Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface');

        $mock
            ->expects($this->once())
            ->method('isPasswordValid')
            ->will($this->returnValue($isPasswordValid))
        ;

        return $mock;
    }

    protected function createEncoderFactory($encoder = null)
    {
        $mock = $this->getMock('Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface');

        $mock
            ->expects($this->once())
            ->method('getEncoder')
            ->will($this->returnValue($encoder))
        ;

        return $mock;
    }

    protected function createSecurityContext($user = null)
    {
        $token = $this->createAuthenticationToken($user);

        $mock = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
        $mock
            ->expects($this->once())
            ->method('getToken')
            ->will($this->returnValue($token))
        ;

        return $mock;
    }

    protected function createAuthenticationToken($user = null)
    {
        $mock = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
        $mock
            ->expects($this->once())
            ->method('getUser')
            ->will($this->returnValue($user))
        ;

        return $mock;
    }
}
PK��Z�KN��Mtest/Security/Symfony/Component/Security/Core/Tests/Util/SecureRandomTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Util;

use Symfony\Component\Security\Core\Util\SecureRandom;

class SecureRandomTest extends \PHPUnit_Framework_TestCase
{
    /**
     * T1: Monobit test
     *
     * @dataProvider getSecureRandoms
     */
    public function testMonobit($secureRandom)
    {
        $nbOnBits = substr_count($this->getBitSequence($secureRandom, 20000), '1');
        $this->assertTrue($nbOnBits > 9654 && $nbOnBits < 10346, 'Monobit test failed, number of turned on bits: '.$nbOnBits);
    }

    /**
     * T2: Chi-square test with 15 degrees of freedom (chi-Quadrat-Anpassungstest)
     *
     * @dataProvider getSecureRandoms
     */
    public function testPoker($secureRandom)
    {
        $b = $this->getBitSequence($secureRandom, 20000);
        $c = array();
        for ($i = 0; $i <= 15; $i++) {
            $c[$i] = 0;
        }

        for ($j = 1; $j <= 5000; $j++) {
            $k = 4 * $j - 1;
            $c[8 * $b[$k - 3] + 4 * $b[$k - 2] + 2 * $b[$k - 1] + $b[$k]] += 1;
        }

        $f = 0;
        for ($i = 0; $i <= 15; $i++) {
            $f += $c[$i] * $c[$i];
        }

        $Y = 16/5000 * $f - 5000;

        $this->assertTrue($Y > 1.03 && $Y < 57.4, 'Poker test failed, Y = '.$Y);
    }

    /**
     * Run test
     *
     * @dataProvider getSecureRandoms
     */
    public function testRun($secureRandom)
    {
        $b = $this->getBitSequence($secureRandom, 20000);

        $runs = array();
        for ($i = 1; $i <= 6; $i++) {
            $runs[$i] = 0;
        }

        $addRun = function ($run) use (&$runs) {
            if ($run > 6) {
                $run = 6;
            }

            $runs[$run] += 1;
        };

        $currentRun = 0;
        $lastBit = null;
        for ($i = 0; $i < 20000; $i++) {
            if ($lastBit === $b[$i]) {
                $currentRun += 1;
            } else {
                if ($currentRun > 0) {
                    $addRun($currentRun);
                }

                $lastBit = $b[$i];
                $currentRun = 0;
            }
        }
        if ($currentRun > 0) {
            $addRun($currentRun);
        }

        $this->assertTrue($runs[1] > 2267 && $runs[1] < 2733, 'Runs of length 1 outside of defined interval: '.$runs[1]);
        $this->assertTrue($runs[2] > 1079 && $runs[2] < 1421, 'Runs of length 2 outside of defined interval: '.$runs[2]);
        $this->assertTrue($runs[3] > 502 && $runs[3] < 748, 'Runs of length 3 outside of defined interval: '.$runs[3]);
        $this->assertTrue($runs[4] > 233 && $runs[4] < 402, 'Runs of length 4 outside of defined interval: '.$runs[4]);
        $this->assertTrue($runs[5] > 90 && $runs[5] < 223, 'Runs of length 5 outside of defined interval: '.$runs[5]);
        $this->assertTrue($runs[6] > 90 && $runs[6] < 233, 'Runs of length 6 outside of defined interval: '.$runs[6]);
    }

    /**
     * Long-run test
     *
     * @dataProvider getSecureRandoms
     */
    public function testLongRun($secureRandom)
    {
        $b = $this->getBitSequence($secureRandom, 20000);

        $longestRun = $currentRun = 0;
        $lastBit = null;
        for ($i = 0; $i < 20000; $i++) {
            if ($lastBit === $b[$i]) {
                $currentRun += 1;
            } else {
                if ($currentRun > $longestRun) {
                    $longestRun = $currentRun;
                }
                $lastBit = $b[$i];
                $currentRun = 0;
            }
        }
        if ($currentRun > $longestRun) {
            $longestRun = $currentRun;
        }

        $this->assertTrue($longestRun < 34, 'Failed longest run test: '.$longestRun);
    }

    /**
     * Serial Correlation (Autokorrelationstest)
     *
     * @dataProvider getSecureRandoms
     */
    public function testSerialCorrelation($secureRandom)
    {
        $shift = rand(1, 5000);
        $b = $this->getBitSequence($secureRandom, 20000);

        $Z = 0;
        for ($i = 0; $i < 5000; $i++) {
            $Z += $b[$i] === $b[$i + $shift] ? 1 : 0;
        }

        $this->assertTrue($Z > 2326 && $Z < 2674, 'Failed serial correlation test: '.$Z);
    }

    public function getSecureRandoms()
    {
        $secureRandoms = array();

        // only add if openssl is indeed present
        $secureRandom = new SecureRandom();
        if ($this->hasOpenSsl($secureRandom)) {
            $secureRandoms[] = array($secureRandom);
        }

        // no-openssl with custom seed provider
        $secureRandom = new SecureRandom(sys_get_temp_dir().'/_sf2.seed');
        $this->disableOpenSsl($secureRandom);
        $secureRandoms[] = array($secureRandom);

        return $secureRandoms;
    }

    protected function disableOpenSsl($secureRandom)
    {
        $ref = new \ReflectionProperty($secureRandom, 'useOpenSsl');
        $ref->setAccessible(true);
        $ref->setValue($secureRandom, false);
        $ref->setAccessible(false);
    }

    protected function hasOpenSsl($secureRandom)
    {
        $ref = new \ReflectionProperty($secureRandom, 'useOpenSsl');
        $ref->setAccessible(true);

        $ret = $ref->getValue($secureRandom);

        $ref->setAccessible(false);

        return $ret;
    }

    private function getBitSequence($secureRandom, $length)
    {
        $bitSequence = '';
        for ($i = 0; $i < $length; $i += 40) {
            $value = unpack('H*', $secureRandom->nextBytes(5));
            $value = str_pad(base_convert($value[1], 16, 2), 40, '0', STR_PAD_LEFT);
            $bitSequence .= $value;
        }

        return substr($bitSequence, 0, $length);
    }
}
PK��Zn�;�SSLtest/Security/Symfony/Component/Security/Core/Tests/Util/StringUtilsTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Util;

use Symfony\Component\Security\Core\Util\StringUtils;

class StringUtilsTest extends \PHPUnit_Framework_TestCase
{
    public function testEquals()
    {
        $this->assertTrue(StringUtils::equals('password', 'password'));
        $this->assertFalse(StringUtils::equals('password', 'foo'));
    }
}
PK��Z�����Ktest/Security/Symfony/Component/Security/Core/Tests/Util/ClassUtilsTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Util
{
    use Symfony\Component\Security\Core\Util\ClassUtils;

    class ClassUtilsTest extends \PHPUnit_Framework_TestCase
    {
        public static function dataGetClass()
        {
            return array(
                array('stdClass', 'stdClass'),
                array('Symfony\Component\Security\Core\Util\ClassUtils', 'Symfony\Component\Security\Core\Util\ClassUtils'),
                array('MyProject\Proxies\__CG__\stdClass', 'stdClass'),
                array('MyProject\Proxies\__CG__\OtherProject\Proxies\__CG__\stdClass', 'stdClass'),
                array('MyProject\Proxies\__CG__\Symfony\Component\Security\Core\Tests\Util\ChildObject', 'Symfony\Component\Security\Core\Tests\Util\ChildObject'),
                array(new TestObject(), 'Symfony\Component\Security\Core\Tests\Util\TestObject'),
                array(new \Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Core\Tests\Util\TestObject(), 'Symfony\Component\Security\Core\Tests\Util\TestObject'),
            );
        }

        /**
         * @dataProvider dataGetClass
         */
        public function testGetRealClass($object, $expectedClassName)
        {
            $this->assertEquals($expectedClassName, ClassUtils::getRealClass($object));
        }
    }

    class TestObject
    {
    }
}

namespace Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Core\Tests\Util
{
    class TestObject extends \Symfony\Component\Security\Core\Tests\Util\TestObject
    {
    }
}
PK��ZI-���_test/Security/Symfony/Component/Security/Core/Tests/Authorization/AccessDecisionManagerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Authorization;

use Symfony\Component\Security\Core\Authorization\AccessDecisionManager;
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;

class AccessDecisionManagerTest extends \PHPUnit_Framework_TestCase
{
    public function testSupportsClass()
    {
        $manager = new AccessDecisionManager(array(
            $this->getVoterSupportsClass(true),
            $this->getVoterSupportsClass(false),
        ));
        $this->assertTrue($manager->supportsClass('FooClass'));

        $manager = new AccessDecisionManager(array(
            $this->getVoterSupportsClass(false),
            $this->getVoterSupportsClass(false),
        ));
        $this->assertFalse($manager->supportsClass('FooClass'));
    }

    public function testSupportsAttribute()
    {
        $manager = new AccessDecisionManager(array(
            $this->getVoterSupportsAttribute(true),
            $this->getVoterSupportsAttribute(false),
        ));
        $this->assertTrue($manager->supportsAttribute('foo'));

        $manager = new AccessDecisionManager(array(
            $this->getVoterSupportsAttribute(false),
            $this->getVoterSupportsAttribute(false),
        ));
        $this->assertFalse($manager->supportsAttribute('foo'));
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testSetVotersEmpty()
    {
        $manager = new AccessDecisionManager(array());
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testSetUnsupportedStrategy()
    {
        new AccessDecisionManager(array($this->getVoter(VoterInterface::ACCESS_GRANTED)), 'fooBar');
    }

    /**
     * @dataProvider getStrategyTests
     */
    public function testStrategies($strategy, $voters, $allowIfAllAbstainDecisions, $allowIfEqualGrantedDeniedDecisions, $expected)
    {
        $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
        $manager = new AccessDecisionManager($voters, $strategy, $allowIfAllAbstainDecisions, $allowIfEqualGrantedDeniedDecisions);

        $this->assertSame($expected, $manager->decide($token, array('ROLE_FOO')));
    }

    public function getStrategyTests()
    {
        return array(
            // affirmative
            array('affirmative', $this->getVoters(1, 0, 0), false, true, true),
            array('affirmative', $this->getVoters(1, 2, 0), false, true, true),
            array('affirmative', $this->getVoters(0, 1, 0), false, true, false),
            array('affirmative', $this->getVoters(0, 0, 1), false, true, false),
            array('affirmative', $this->getVoters(0, 0, 1), true, true, true),

            // consensus
            array('consensus', $this->getVoters(1, 0, 0), false, true, true),
            array('consensus', $this->getVoters(1, 2, 0), false, true, false),
            array('consensus', $this->getVoters(2, 1, 0), false, true, true),

            array('consensus', $this->getVoters(0, 0, 1), false, true, false),

            array('consensus', $this->getVoters(0, 0, 1), true, true, true),

            array('consensus', $this->getVoters(2, 2, 0), false, true, true),
            array('consensus', $this->getVoters(2, 2, 1), false, true, true),

            array('consensus', $this->getVoters(2, 2, 0), false, false, false),
            array('consensus', $this->getVoters(2, 2, 1), false, false, false),

            // unanimous
            array('unanimous', $this->getVoters(1, 0, 0), false, true, true),
            array('unanimous', $this->getVoters(1, 0, 1), false, true, true),
            array('unanimous', $this->getVoters(1, 1, 0), false, true, false),

            array('unanimous', $this->getVoters(0, 0, 2), false, true, false),
            array('unanimous', $this->getVoters(0, 0, 2), true, true, true),
        );
    }

    protected function getVoters($grants, $denies, $abstains)
    {
        $voters = array();
        for ($i = 0; $i < $grants; $i++) {
            $voters[] = $this->getVoter(VoterInterface::ACCESS_GRANTED);
        }
        for ($i = 0; $i < $denies; $i++) {
            $voters[] = $this->getVoter(VoterInterface::ACCESS_DENIED);
        }
        for ($i = 0; $i < $abstains; $i++) {
            $voters[] = $this->getVoter(VoterInterface::ACCESS_ABSTAIN);
        }

        return $voters;
    }

    protected function getVoter($vote)
    {
        $voter = $this->getMock('Symfony\Component\Security\Core\Authorization\Voter\VoterInterface');
        $voter->expects($this->any())
              ->method('vote')
              ->will($this->returnValue($vote));
        ;

        return $voter;
    }

    protected function getVoterSupportsClass($ret)
    {
        $voter = $this->getMock('Symfony\Component\Security\Core\Authorization\Voter\VoterInterface');
        $voter->expects($this->any())
              ->method('supportsClass')
              ->will($this->returnValue($ret));
        ;

        return $voter;
    }

    protected function getVoterSupportsAttribute($ret)
    {
        $voter = $this->getMock('Symfony\Component\Security\Core\Authorization\Voter\VoterInterface');
        $voter->expects($this->any())
              ->method('supportsAttribute')
              ->will($this->returnValue($ret));
        ;

        return $voter;
    }
}
PK��Z�bdw�
�
\test/Security/Symfony/Component/Security/Core/Tests/Authorization/ExpressionLanguageTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Authorization;

use Symfony\Component\Security\Core\Authorization\ExpressionLanguage;
use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver;
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\User\User;

class ExpressionLanguageTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider provider
     */
    public function testIsAuthenticated($token, $expression, $result, array $roles = array())
    {
        $anonymousTokenClass = 'Symfony\\Component\\Security\\Core\\Authentication\\Token\\AnonymousToken';
        $rememberMeTokenClass = 'Symfony\\Component\\Security\\Core\\Authentication\\Token\\RememberMeToken';
        $expressionLanguage = new ExpressionLanguage();
        $trustResolver = new AuthenticationTrustResolver($anonymousTokenClass, $rememberMeTokenClass);

        $context = array();
        $context['trust_resolver'] = $trustResolver;
        $context['token'] = $token;
        $context['roles'] = $roles;

        $this->assertEquals($result, $expressionLanguage->evaluate($expression, $context));
    }

    public function provider()
    {
        $roles = array('ROLE_USER', 'ROLE_ADMIN');
        $user = new User('username', 'password', $roles);

        $noToken = null;
        $anonymousToken = new AnonymousToken('firewall', 'anon.');
        $rememberMeToken = new RememberMeToken($user, 'providerkey', 'firewall');
        $usernamePasswordToken = new UsernamePasswordToken('username', 'password', 'providerkey', $roles);

        return array(
            array($noToken, 'is_anonymous()', false),
            array($noToken, 'is_authenticated()', false),
            array($noToken, 'is_fully_authenticated()', false),
            array($noToken, 'is_remember_me()', false),
            array($noToken, "has_role('ROLE_USER')", false),

            array($anonymousToken, 'is_anonymous()', true),
            array($anonymousToken, 'is_authenticated()', false),
            array($anonymousToken, 'is_fully_authenticated()', false),
            array($anonymousToken, 'is_remember_me()', false),
            array($anonymousToken, "has_role('ROLE_USER')", false),

            array($rememberMeToken, 'is_anonymous()', false),
            array($rememberMeToken, 'is_authenticated()', true),
            array($rememberMeToken, 'is_fully_authenticated()', false),
            array($rememberMeToken, 'is_remember_me()', true),
            array($rememberMeToken, "has_role('ROLE_FOO')", false, $roles),
            array($rememberMeToken, "has_role('ROLE_USER')", true, $roles),

            array($usernamePasswordToken, 'is_anonymous()', false),
            array($usernamePasswordToken, 'is_authenticated()', true),
            array($usernamePasswordToken, 'is_fully_authenticated()', true),
            array($usernamePasswordToken, 'is_remember_me()', false),
            array($usernamePasswordToken, "has_role('ROLE_FOO')", false, $roles),
            array($usernamePasswordToken, "has_role('ROLE_USER')", true, $roles),
        );
    }
}
PK��Z�Ƕ'�
�
_test/Security/Symfony/Component/Security/Core/Tests/Authorization/Voter/ExpressionVoterTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Authorization\Voter;

use Symfony\Component\Security\Core\Authorization\Voter\ExpressionVoter;
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
use Symfony\Component\Security\Core\Role\Role;

class ExpressionVoterTest extends \PHPUnit_Framework_TestCase
{
    public function testSupportsAttribute()
    {
        $expression = $this->createExpression();
        $expressionLanguage = $this->getMock('Symfony\Component\Security\Core\Authorization\ExpressionLanguage');
        $voter = new ExpressionVoter($expressionLanguage, $this->createTrustResolver(), $this->createRoleHierarchy());

        $this->assertTrue($voter->supportsAttribute($expression));
    }

    /**
     * @dataProvider getVoteTests
     */
    public function testVote($roles, $attributes, $expected, $tokenExpectsGetRoles = true, $expressionLanguageExpectsEvaluate = true)
    {
        $voter = new ExpressionVoter($this->createExpressionLanguage($expressionLanguageExpectsEvaluate), $this->createTrustResolver());

        $this->assertSame($expected, $voter->vote($this->getToken($roles, $tokenExpectsGetRoles), null, $attributes));
    }

    public function getVoteTests()
    {
        return array(
            array(array(), array(), VoterInterface::ACCESS_ABSTAIN, false, false),
            array(array(), array('FOO'), VoterInterface::ACCESS_ABSTAIN, false, false),

            array(array(), array($this->createExpression()), VoterInterface::ACCESS_DENIED, true, false),

            array(array('ROLE_FOO'), array($this->createExpression(), $this->createExpression()), VoterInterface::ACCESS_GRANTED),
            array(array('ROLE_BAR', 'ROLE_FOO'), array($this->createExpression()), VoterInterface::ACCESS_GRANTED),
        );
    }

    protected function getToken(array $roles, $tokenExpectsGetRoles = true)
    {
        foreach ($roles as $i => $role) {
            $roles[$i] = new Role($role);
        }
        $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');

        if ($tokenExpectsGetRoles) {
            $token->expects($this->once())
                ->method('getRoles')
                ->will($this->returnValue($roles));
        }

        return $token;
    }

    protected function createExpressionLanguage($expressionLanguageExpectsEvaluate = true)
    {
        $mock = $this->getMock('Symfony\Component\Security\Core\Authorization\ExpressionLanguage');

        if ($expressionLanguageExpectsEvaluate) {
            $mock->expects($this->once())
                ->method('evaluate')
                ->will($this->returnValue(true));
        }

        return $mock;
    }

    protected function createTrustResolver()
    {
        return $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface');
    }

    protected function createRoleHierarchy()
    {
        return $this->getMock('Symfony\Component\Security\Core\Role\RoleHierarchyInterface');
    }

    protected function createExpression()
    {
        return $this->getMockBuilder('Symfony\Component\ExpressionLanguage\Expression')
            ->disableOriginalConstructor()
            ->getMock();
    }
}
PK��Zjq�o��Ytest/Security/Symfony/Component/Security/Core/Tests/Authorization/Voter/RoleVoterTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Authorization\Voter;

use Symfony\Component\Security\Core\Authorization\Voter\RoleVoter;
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
use Symfony\Component\Security\Core\Role\Role;

class RoleVoterTest extends \PHPUnit_Framework_TestCase
{
    public function testSupportsClass()
    {
        $voter = new RoleVoter();

        $this->assertTrue($voter->supportsClass('Foo'));
    }

    /**
     * @dataProvider getVoteTests
     */
    public function testVote($roles, $attributes, $expected)
    {
        $voter = new RoleVoter();

        $this->assertSame($expected, $voter->vote($this->getToken($roles), null, $attributes));
    }

    public function getVoteTests()
    {
        return array(
            array(array(), array(), VoterInterface::ACCESS_ABSTAIN),
            array(array(), array('FOO'), VoterInterface::ACCESS_ABSTAIN),
            array(array(), array('ROLE_FOO'), VoterInterface::ACCESS_DENIED),
            array(array('ROLE_FOO'), array('ROLE_FOO'), VoterInterface::ACCESS_GRANTED),
            array(array('ROLE_FOO'), array('FOO', 'ROLE_FOO'), VoterInterface::ACCESS_GRANTED),
            array(array('ROLE_BAR', 'ROLE_FOO'), array('ROLE_FOO'), VoterInterface::ACCESS_GRANTED),
        );
    }

    protected function getToken(array $roles)
    {
        foreach ($roles as $i => $role) {
            $roles[$i] = new Role($role);
        }
        $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
        $token->expects($this->once())
              ->method('getRoles')
              ->will($this->returnValue($roles));
        ;

        return $token;
    }
}
PK��Z�R�MMbtest/Security/Symfony/Component/Security/Core/Tests/Authorization/Voter/RoleHierarchyVoterTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Authorization\Voter;

use Symfony\Component\Security\Core\Authorization\Voter\RoleHierarchyVoter;
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
use Symfony\Component\Security\Core\Role\RoleHierarchy;

class RoleHierarchyVoterTest extends RoleVoterTest
{
    /**
     * @dataProvider getVoteTests
     */
    public function testVote($roles, $attributes, $expected)
    {
        $voter = new RoleHierarchyVoter(new RoleHierarchy(array('ROLE_FOO' => array('ROLE_FOOBAR'))));

        $this->assertSame($expected, $voter->vote($this->getToken($roles), null, $attributes));
    }

    public function getVoteTests()
    {
        return array_merge(parent::getVoteTests(), array(
            array(array('ROLE_FOO'), array('ROLE_FOOBAR'), VoterInterface::ACCESS_GRANTED),
        ));
    }
}
PK��Z��� ,
,
btest/Security/Symfony/Component/Security/Core/Tests/Authorization/Voter/AuthenticatedVoterTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Authorization\Voter;

use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver;
use Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter;
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;

class AuthenticatedVoterTest extends \PHPUnit_Framework_TestCase
{
    public function testSupportsClass()
    {
        $voter = new AuthenticatedVoter($this->getResolver());
        $this->assertTrue($voter->supportsClass('stdClass'));
    }

    /**
     * @dataProvider getVoteTests
     */
    public function testVote($authenticated, $attributes, $expected)
    {
        $voter = new AuthenticatedVoter($this->getResolver());

        $this->assertSame($expected, $voter->vote($this->getToken($authenticated), null, $attributes));
    }

    public function getVoteTests()
    {
        return array(
            array('fully', array(), VoterInterface::ACCESS_ABSTAIN),
            array('fully', array('FOO'), VoterInterface::ACCESS_ABSTAIN),
            array('remembered', array(), VoterInterface::ACCESS_ABSTAIN),
            array('remembered', array('FOO'), VoterInterface::ACCESS_ABSTAIN),
            array('anonymously', array(), VoterInterface::ACCESS_ABSTAIN),
            array('anonymously', array('FOO'), VoterInterface::ACCESS_ABSTAIN),

            array('fully', array('IS_AUTHENTICATED_ANONYMOUSLY'), VoterInterface::ACCESS_GRANTED),
            array('remembered', array('IS_AUTHENTICATED_ANONYMOUSLY'), VoterInterface::ACCESS_GRANTED),
            array('anonymously', array('IS_AUTHENTICATED_ANONYMOUSLY'), VoterInterface::ACCESS_GRANTED),

            array('fully', array('IS_AUTHENTICATED_REMEMBERED'), VoterInterface::ACCESS_GRANTED),
            array('remembered', array('IS_AUTHENTICATED_REMEMBERED'), VoterInterface::ACCESS_GRANTED),
            array('anonymously', array('IS_AUTHENTICATED_REMEMBERED'), VoterInterface::ACCESS_DENIED),

            array('fully', array('IS_AUTHENTICATED_FULLY'), VoterInterface::ACCESS_GRANTED),
            array('remembered', array('IS_AUTHENTICATED_FULLY'), VoterInterface::ACCESS_DENIED),
            array('anonymously', array('IS_AUTHENTICATED_FULLY'), VoterInterface::ACCESS_DENIED),
        );
    }

    protected function getResolver()
    {
        return new AuthenticationTrustResolver(
            'Symfony\\Component\\Security\\Core\\Authentication\\Token\\AnonymousToken',
            'Symfony\\Component\\Security\\Core\\Authentication\\Token\\RememberMeToken'
        );
    }

    protected function getToken($authenticated)
    {
        if ('fully' === $authenticated) {
            return $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
        } elseif ('remembered' === $authenticated) {
            return $this->getMock('Symfony\Component\Security\Core\Authentication\Token\RememberMeToken', array('setPersistent'), array(), '', false);
        } else {
            return $this->getMock('Symfony\Component\Security\Core\Authentication\Token\AnonymousToken', null, array('', ''));
        }
    }
}
PK��ZLS�(��Etest/Security/Symfony/Component/Security/Core/Tests/User/UserTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\User;

use Symfony\Component\Security\Core\User\User;

class UserTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Symfony\Component\Security\Core\User\User::__construct
     * @expectedException \InvalidArgumentException
     */
    public function testConstructorException()
    {
        new User('', 'superpass');
    }

    /**
     * @covers Symfony\Component\Security\Core\User\User::__construct
     * @covers Symfony\Component\Security\Core\User\User::getRoles
     */
    public function testGetRoles()
    {
        $user = new User('fabien', 'superpass');
        $this->assertEquals(array(), $user->getRoles());

        $user = new User('fabien', 'superpass', array('ROLE_ADMIN'));
        $this->assertEquals(array('ROLE_ADMIN'), $user->getRoles());
    }

    /**
     * @covers Symfony\Component\Security\Core\User\User::__construct
     * @covers Symfony\Component\Security\Core\User\User::getPassword
     */
    public function testGetPassword()
    {
        $user = new User('fabien', 'superpass');
        $this->assertEquals('superpass', $user->getPassword());
    }

    /**
     * @covers Symfony\Component\Security\Core\User\User::__construct
     * @covers Symfony\Component\Security\Core\User\User::getUsername
     */
    public function testGetUsername()
    {
        $user = new User('fabien', 'superpass');
        $this->assertEquals('fabien', $user->getUsername());
    }

    /**
     * @covers Symfony\Component\Security\Core\User\User::getSalt
     */
    public function testGetSalt()
    {
        $user = new User('fabien', 'superpass');
        $this->assertEquals('', $user->getSalt());
    }

    /**
     * @covers Symfony\Component\Security\Core\User\User::isAccountNonExpired
     */
    public function testIsAccountNonExpired()
    {
        $user = new User('fabien', 'superpass');
        $this->assertTrue($user->isAccountNonExpired());

        $user = new User('fabien', 'superpass', array(), true, false);
        $this->assertFalse($user->isAccountNonExpired());
    }

    /**
     * @covers Symfony\Component\Security\Core\User\User::isCredentialsNonExpired
     */
    public function testIsCredentialsNonExpired()
    {
        $user = new User('fabien', 'superpass');
        $this->assertTrue($user->isCredentialsNonExpired());

        $user = new User('fabien', 'superpass', array(), true, true, false);
        $this->assertFalse($user->isCredentialsNonExpired());
    }

    /**
     * @covers Symfony\Component\Security\Core\User\User::isAccountNonLocked
     */
    public function testIsAccountNonLocked()
    {
        $user = new User('fabien', 'superpass');
        $this->assertTrue($user->isAccountNonLocked());

        $user = new User('fabien', 'superpass', array(), true, true, true, false);
        $this->assertFalse($user->isAccountNonLocked());
    }

    /**
     * @covers Symfony\Component\Security\Core\User\User::isEnabled
     */
    public function testIsEnabled()
    {
        $user = new User('fabien', 'superpass');
        $this->assertTrue($user->isEnabled());

        $user = new User('fabien', 'superpass', array(), false);
        $this->assertFalse($user->isEnabled());
    }

    /**
     * @covers Symfony\Component\Security\Core\User\User::eraseCredentials
     */
    public function testEraseCredentials()
    {
        $user = new User('fabien', 'superpass');
        $user->eraseCredentials();
        $this->assertEquals('superpass', $user->getPassword());
    }
}
PK��Z��qRtest/Security/Symfony/Component/Security/Core/Tests/User/ChainUserProviderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\User;

use Symfony\Component\Security\Core\Exception\UnsupportedUserException;

use Symfony\Component\Security\Core\User\ChainUserProvider;

use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;

class ChainUserProviderTest extends \PHPUnit_Framework_TestCase
{
    public function testLoadUserByUsername()
    {
        $provider1 = $this->getProvider();
        $provider1
            ->expects($this->once())
            ->method('loadUserByUsername')
            ->with($this->equalTo('foo'))
            ->will($this->throwException(new UsernameNotFoundException('not found')))
        ;

        $provider2 = $this->getProvider();
        $provider2
            ->expects($this->once())
            ->method('loadUserByUsername')
            ->with($this->equalTo('foo'))
            ->will($this->returnValue($account = $this->getAccount()))
        ;

        $provider = new ChainUserProvider(array($provider1, $provider2));
        $this->assertSame($account, $provider->loadUserByUsername('foo'));
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\UsernameNotFoundException
     */
    public function testLoadUserByUsernameThrowsUsernameNotFoundException()
    {
        $provider1 = $this->getProvider();
        $provider1
            ->expects($this->once())
            ->method('loadUserByUsername')
            ->with($this->equalTo('foo'))
            ->will($this->throwException(new UsernameNotFoundException('not found')))
        ;

        $provider2 = $this->getProvider();
        $provider2
            ->expects($this->once())
            ->method('loadUserByUsername')
            ->with($this->equalTo('foo'))
            ->will($this->throwException(new UsernameNotFoundException('not found')))
        ;

        $provider = new ChainUserProvider(array($provider1, $provider2));
        $provider->loadUserByUsername('foo');
    }

    public function testRefreshUser()
    {
        $provider1 = $this->getProvider();
        $provider1
            ->expects($this->once())
            ->method('refreshUser')
            ->will($this->throwException(new UnsupportedUserException('unsupported')))
        ;

        $provider2 = $this->getProvider();
        $provider2
            ->expects($this->once())
            ->method('refreshUser')
            ->will($this->returnValue($account = $this->getAccount()))
        ;

        $provider = new ChainUserProvider(array($provider1, $provider2));
        $this->assertSame($account, $provider->refreshUser($this->getAccount()));
    }

    public function testRefreshUserAgain()
    {
        $provider1 = $this->getProvider();
        $provider1
            ->expects($this->once())
            ->method('refreshUser')
            ->will($this->throwException(new UsernameNotFoundException('not found')))
        ;

        $provider2 = $this->getProvider();
        $provider2
            ->expects($this->once())
            ->method('refreshUser')
            ->will($this->returnValue($account = $this->getAccount()))
        ;

        $provider = new ChainUserProvider(array($provider1, $provider2));
        $this->assertSame($account, $provider->refreshUser($this->getAccount()));
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\UnsupportedUserException
     */
    public function testRefreshUserThrowsUnsupportedUserException()
    {
        $provider1 = $this->getProvider();
        $provider1
            ->expects($this->once())
            ->method('refreshUser')
            ->will($this->throwException(new UnsupportedUserException('unsupported')))
        ;

        $provider2 = $this->getProvider();
        $provider2
            ->expects($this->once())
            ->method('refreshUser')
            ->will($this->throwException(new UnsupportedUserException('unsupported')))
        ;

        $provider = new ChainUserProvider(array($provider1, $provider2));
        $provider->refreshUser($this->getAccount());
    }

    public function testSupportsClass()
    {
        $provider1 = $this->getProvider();
        $provider1
            ->expects($this->once())
            ->method('supportsClass')
            ->with($this->equalTo('foo'))
            ->will($this->returnValue(false))
        ;

        $provider2 = $this->getProvider();
        $provider2
            ->expects($this->once())
            ->method('supportsClass')
            ->with($this->equalTo('foo'))
            ->will($this->returnValue(true))
        ;

        $provider = new ChainUserProvider(array($provider1, $provider2));
        $this->assertTrue($provider->supportsClass('foo'));
    }

    public function testSupportsClassWhenNotSupported()
    {
        $provider1 = $this->getProvider();
        $provider1
            ->expects($this->once())
            ->method('supportsClass')
            ->with($this->equalTo('foo'))
            ->will($this->returnValue(false))
        ;

        $provider2 = $this->getProvider();
        $provider2
            ->expects($this->once())
            ->method('supportsClass')
            ->with($this->equalTo('foo'))
            ->will($this->returnValue(false))
        ;

        $provider = new ChainUserProvider(array($provider1, $provider2));
        $this->assertFalse($provider->supportsClass('foo'));
    }

    protected function getAccount()
    {
        return $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
    }

    protected function getProvider()
    {
        return $this->getMock('Symfony\Component\Security\Core\User\UserProviderInterface');
    }
}
PK��Z�$��stest/Security/Symfony/Component/Security/Core/Tests/Authentication/Provider/AnonymousAuthenticationProviderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Authentication\Provider;

use Symfony\Component\Security\Core\Authentication\Provider\AnonymousAuthenticationProvider;

class AnonymousAuthenticationProviderTest extends \PHPUnit_Framework_TestCase
{
    public function testSupports()
    {
        $provider = $this->getProvider('foo');

        $this->assertTrue($provider->supports($this->getSupportedToken('foo')));
        $this->assertFalse($provider->supports($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')));
    }

    public function testAuthenticateWhenTokenIsNotSupported()
    {
        $provider = $this->getProvider('foo');

        $this->assertNull($provider->authenticate($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')));
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
     */
    public function testAuthenticateWhenKeyIsNotValid()
    {
        $provider = $this->getProvider('foo');

        $this->assertNull($provider->authenticate($this->getSupportedToken('bar')));
    }

    public function testAuthenticate()
    {
        $provider = $this->getProvider('foo');
        $token = $this->getSupportedToken('foo');

        $this->assertSame($token, $provider->authenticate($token));
    }

    protected function getSupportedToken($key)
    {
        $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\AnonymousToken', array('getKey'), array(), '', false);
        $token->expects($this->any())
              ->method('getKey')
              ->will($this->returnValue($key))
        ;

        return $token;
    }

    protected function getProvider($key)
    {
        return new AnonymousAuthenticationProvider($key);
    }
}
PK��ZP��[.[.mtest/Security/Symfony/Component/Security/Core/Tests/Authentication/Provider/DaoAuthenticationProviderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Authentication\Provider;

use Symfony\Component\Security\Core\Encoder\PlaintextPasswordEncoder;

use Symfony\Component\Security\Core\Authentication\Provider\DaoAuthenticationProvider;

class DaoAuthenticationProviderTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationServiceException
     */
    public function testRetrieveUserWhenProviderDoesNotReturnAnUserInterface()
    {
        $provider = $this->getProvider('fabien');
        $method = new \ReflectionMethod($provider, 'retrieveUser');
        $method->setAccessible(true);

        $method->invoke($provider, 'fabien', $this->getSupportedToken());
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\UsernameNotFoundException
     */
    public function testRetrieveUserWhenUsernameIsNotFound()
    {
        $userProvider = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserProviderInterface');
        $userProvider->expects($this->once())
                     ->method('loadUserByUsername')
                     ->will($this->throwException($this->getMock('Symfony\\Component\\Security\\Core\\Exception\\UsernameNotFoundException', null, array(), '', false)))
        ;

        $provider = new DaoAuthenticationProvider($userProvider, $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserCheckerInterface'), 'key', $this->getMock('Symfony\\Component\\Security\\Core\\Encoder\\EncoderFactoryInterface'));
        $method = new \ReflectionMethod($provider, 'retrieveUser');
        $method->setAccessible(true);

        $method->invoke($provider, 'fabien', $this->getSupportedToken());
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationServiceException
     */
    public function testRetrieveUserWhenAnExceptionOccurs()
    {
        $userProvider = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserProviderInterface');
        $userProvider->expects($this->once())
                     ->method('loadUserByUsername')
                     ->will($this->throwException($this->getMock('RuntimeException', null, array(), '', false)))
        ;

        $provider = new DaoAuthenticationProvider($userProvider, $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserCheckerInterface'), 'key', $this->getMock('Symfony\\Component\\Security\\Core\\Encoder\\EncoderFactoryInterface'));
        $method = new \ReflectionMethod($provider, 'retrieveUser');
        $method->setAccessible(true);

        $method->invoke($provider, 'fabien', $this->getSupportedToken());
    }

    public function testRetrieveUserReturnsUserFromTokenOnReauthentication()
    {
        $userProvider = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserProviderInterface');
        $userProvider->expects($this->never())
                     ->method('loadUserByUsername')
        ;

        $user = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserInterface');
        $token = $this->getSupportedToken();
        $token->expects($this->once())
              ->method('getUser')
              ->will($this->returnValue($user))
        ;

        $provider = new DaoAuthenticationProvider($userProvider, $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserCheckerInterface'), 'key', $this->getMock('Symfony\\Component\\Security\\Core\\Encoder\\EncoderFactoryInterface'));
        $reflection = new \ReflectionMethod($provider, 'retrieveUser');
        $reflection->setAccessible(true);
        $result = $reflection->invoke($provider, null, $token);

        $this->assertSame($user, $result);
    }

    public function testRetrieveUser()
    {
        $user = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserInterface');

        $userProvider = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserProviderInterface');
        $userProvider->expects($this->once())
                     ->method('loadUserByUsername')
                     ->will($this->returnValue($user))
        ;

        $provider = new DaoAuthenticationProvider($userProvider, $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserCheckerInterface'), 'key', $this->getMock('Symfony\\Component\\Security\\Core\\Encoder\\EncoderFactoryInterface'));
        $method = new \ReflectionMethod($provider, 'retrieveUser');
        $method->setAccessible(true);

        $this->assertSame($user, $method->invoke($provider, 'fabien', $this->getSupportedToken()));
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
     */
    public function testCheckAuthenticationWhenCredentialsAreEmpty()
    {
        $encoder = $this->getMock('Symfony\\Component\\Security\\Core\\Encoder\\PasswordEncoderInterface');
        $encoder
            ->expects($this->never())
            ->method('isPasswordValid')
        ;

        $provider = $this->getProvider(null, null, $encoder);
        $method = new \ReflectionMethod($provider, 'checkAuthentication');
        $method->setAccessible(true);

        $token = $this->getSupportedToken();
        $token
            ->expects($this->once())
            ->method('getCredentials')
            ->will($this->returnValue(''))
        ;

        $method->invoke(
            $provider,
            $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserInterface'),
            $token
        );
    }

    public function testCheckAuthenticationWhenCredentialsAre0()
    {
        $encoder = $this->getMock('Symfony\\Component\\Security\\Core\\Encoder\\PasswordEncoderInterface');
        $encoder
            ->expects($this->once())
            ->method('isPasswordValid')
            ->will($this->returnValue(true))
        ;

        $provider = $this->getProvider(null, null, $encoder);
        $method = new \ReflectionMethod($provider, 'checkAuthentication');
        $method->setAccessible(true);

        $token = $this->getSupportedToken();
        $token
            ->expects($this->once())
            ->method('getCredentials')
            ->will($this->returnValue('0'))
        ;

        $method->invoke(
            $provider,
            $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserInterface'),
            $token
        );
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
     */
    public function testCheckAuthenticationWhenCredentialsAreNotValid()
    {
        $encoder = $this->getMock('Symfony\\Component\\Security\\Core\\Encoder\\PasswordEncoderInterface');
        $encoder->expects($this->once())
                ->method('isPasswordValid')
                ->will($this->returnValue(false))
        ;

        $provider = $this->getProvider(null, null, $encoder);
        $method = new \ReflectionMethod($provider, 'checkAuthentication');
        $method->setAccessible(true);

        $token = $this->getSupportedToken();
        $token->expects($this->once())
              ->method('getCredentials')
              ->will($this->returnValue('foo'))
        ;

        $method->invoke($provider, $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserInterface'), $token);
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
     */
    public function testCheckAuthenticationDoesNotReauthenticateWhenPasswordHasChanged()
    {
        $user = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserInterface');
        $user->expects($this->once())
             ->method('getPassword')
             ->will($this->returnValue('foo'))
        ;

        $token = $this->getSupportedToken();
        $token->expects($this->once())
              ->method('getUser')
              ->will($this->returnValue($user));

        $dbUser = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserInterface');
        $dbUser->expects($this->once())
               ->method('getPassword')
               ->will($this->returnValue('newFoo'))
        ;

        $provider = $this->getProvider();
        $reflection = new \ReflectionMethod($provider, 'checkAuthentication');
        $reflection->setAccessible(true);
        $reflection->invoke($provider, $dbUser, $token);
    }

    public function testCheckAuthenticationWhenTokenNeedsReauthenticationWorksWithoutOriginalCredentials()
    {
        $user = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserInterface');
        $user->expects($this->once())
             ->method('getPassword')
             ->will($this->returnValue('foo'))
        ;

        $token = $this->getSupportedToken();
        $token->expects($this->once())
              ->method('getUser')
              ->will($this->returnValue($user));

        $dbUser = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserInterface');
        $dbUser->expects($this->once())
               ->method('getPassword')
               ->will($this->returnValue('foo'))
        ;

        $provider = $this->getProvider();
        $reflection = new \ReflectionMethod($provider, 'checkAuthentication');
        $reflection->setAccessible(true);
        $reflection->invoke($provider, $dbUser, $token);
    }

    public function testCheckAuthentication()
    {
        $encoder = $this->getMock('Symfony\\Component\\Security\\Core\\Encoder\\PasswordEncoderInterface');
        $encoder->expects($this->once())
                ->method('isPasswordValid')
                ->will($this->returnValue(true))
        ;

        $provider = $this->getProvider(null, null, $encoder);
        $method = new \ReflectionMethod($provider, 'checkAuthentication');
        $method->setAccessible(true);

        $token = $this->getSupportedToken();
        $token->expects($this->once())
              ->method('getCredentials')
              ->will($this->returnValue('foo'))
        ;

        $method->invoke($provider, $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserInterface'), $token);
    }

    protected function getSupportedToken()
    {
        $mock = $this->getMock('Symfony\\Component\\Security\\Core\\Authentication\\Token\\UsernamePasswordToken', array('getCredentials', 'getUser', 'getProviderKey'), array(), '', false);
        $mock
            ->expects($this->any())
            ->method('getProviderKey')
            ->will($this->returnValue('key'))
        ;

        return $mock;
    }

    protected function getProvider($user = null, $userChecker = null, $passwordEncoder = null)
    {
        $userProvider = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserProviderInterface');
        if (null !== $user) {
            $userProvider->expects($this->once())
                         ->method('loadUserByUsername')
                         ->will($this->returnValue($user))
            ;
        }

        if (null === $userChecker) {
            $userChecker = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserCheckerInterface');
        }

        if (null === $passwordEncoder) {
            $passwordEncoder = new PlaintextPasswordEncoder();
        }

        $encoderFactory = $this->getMock('Symfony\\Component\\Security\\Core\\Encoder\\EncoderFactoryInterface');
        $encoderFactory
            ->expects($this->any())
            ->method('getEncoder')
            ->will($this->returnValue($passwordEncoder))
        ;

        return new DaoAuthenticationProvider($userProvider, $userChecker, 'key', $encoderFactory);
    }
}
PK��Zו�Gi&i&ntest/Security/Symfony/Component/Security/Core/Tests/Authentication/Provider/UserAuthenticationProviderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Authentication\Provider;

use Symfony\Component\Security\Core\Authentication\Provider\UserAuthenticationProvider;
use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Security\Core\Role\SwitchUserRole;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;

class UserAuthenticationProviderTest extends \PHPUnit_Framework_TestCase
{
    public function testSupports()
    {
        $provider = $this->getProvider();

        $this->assertTrue($provider->supports($this->getSupportedToken()));
        $this->assertFalse($provider->supports($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')));
    }

    public function testAuthenticateWhenTokenIsNotSupported()
    {
        $provider = $this->getProvider();

        $this->assertNull($provider->authenticate($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')));
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\UsernameNotFoundException
     */
    public function testAuthenticateWhenUsernameIsNotFound()
    {
        $provider = $this->getProvider(false, false);
        $provider->expects($this->once())
                 ->method('retrieveUser')
                 ->will($this->throwException($this->getMock('Symfony\Component\Security\Core\Exception\UsernameNotFoundException', null, array(), '', false)))
        ;

        $provider->authenticate($this->getSupportedToken());
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
     */
    public function testAuthenticateWhenUsernameIsNotFoundAndHideIsTrue()
    {
        $provider = $this->getProvider(false, true);
        $provider->expects($this->once())
                 ->method('retrieveUser')
                 ->will($this->throwException($this->getMock('Symfony\Component\Security\Core\Exception\UsernameNotFoundException', null, array(), '', false)))
        ;

        $provider->authenticate($this->getSupportedToken());
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationServiceException
     */
    public function testAuthenticateWhenProviderDoesNotReturnAnUserInterface()
    {
        $provider = $this->getProvider(false, true);
        $provider->expects($this->once())
                 ->method('retrieveUser')
                 ->will($this->returnValue(null))
        ;

        $provider->authenticate($this->getSupportedToken());
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\CredentialsExpiredException
     */
    public function testAuthenticateWhenPreChecksFails()
    {
        $userChecker = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface');
        $userChecker->expects($this->once())
                    ->method('checkPreAuth')
                    ->will($this->throwException($this->getMock('Symfony\Component\Security\Core\Exception\CredentialsExpiredException', null, array(), '', false)))
        ;

        $provider = $this->getProvider($userChecker);
        $provider->expects($this->once())
                 ->method('retrieveUser')
                 ->will($this->returnValue($this->getMock('Symfony\Component\Security\Core\User\UserInterface')))
        ;

        $provider->authenticate($this->getSupportedToken());
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\AccountExpiredException
     */
    public function testAuthenticateWhenPostChecksFails()
    {
        $userChecker = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface');
        $userChecker->expects($this->once())
                    ->method('checkPostAuth')
                    ->will($this->throwException($this->getMock('Symfony\Component\Security\Core\Exception\AccountExpiredException', null, array(), '', false)))
        ;

        $provider = $this->getProvider($userChecker);
        $provider->expects($this->once())
                 ->method('retrieveUser')
                 ->will($this->returnValue($this->getMock('Symfony\Component\Security\Core\User\UserInterface')))
        ;

        $provider->authenticate($this->getSupportedToken());
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
     * @expectedExceptionMessage Bad credentials
     */
    public function testAuthenticateWhenPostCheckAuthenticationFails()
    {
        $provider = $this->getProvider();
        $provider->expects($this->once())
                 ->method('retrieveUser')
                 ->will($this->returnValue($this->getMock('Symfony\Component\Security\Core\User\UserInterface')))
        ;
        $provider->expects($this->once())
                 ->method('checkAuthentication')
                 ->will($this->throwException($this->getMock('Symfony\Component\Security\Core\Exception\BadCredentialsException', null, array(), '', false)))
        ;

        $provider->authenticate($this->getSupportedToken());
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
     * @expectedExceptionMessage Foo
     */
    public function testAuthenticateWhenPostCheckAuthenticationFailsWithHideFalse()
    {
        $provider = $this->getProvider(false, false);
        $provider->expects($this->once())
                 ->method('retrieveUser')
                 ->will($this->returnValue($this->getMock('Symfony\Component\Security\Core\User\UserInterface')))
        ;
        $provider->expects($this->once())
                 ->method('checkAuthentication')
                 ->will($this->throwException(new BadCredentialsException('Foo')))
        ;

        $provider->authenticate($this->getSupportedToken());
    }

    public function testAuthenticate()
    {
        $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
        $user->expects($this->once())
             ->method('getRoles')
             ->will($this->returnValue(array('ROLE_FOO')))
        ;

        $provider = $this->getProvider();
        $provider->expects($this->once())
                 ->method('retrieveUser')
                 ->will($this->returnValue($user))
        ;

        $token = $this->getSupportedToken();
        $token->expects($this->once())
              ->method('getCredentials')
              ->will($this->returnValue('foo'))
        ;

        $token->expects($this->once())
              ->method('getRoles')
              ->will($this->returnValue(array()))
        ;

        $authToken = $provider->authenticate($token);

        $this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', $authToken);
        $this->assertSame($user, $authToken->getUser());
        $this->assertEquals(array(new Role('ROLE_FOO')), $authToken->getRoles());
        $this->assertEquals('foo', $authToken->getCredentials());
        $this->assertEquals(array('foo' => 'bar'), $authToken->getAttributes(), '->authenticate() copies token attributes');
    }

    public function testAuthenticateWithPreservingRoleSwitchUserRole()
    {
        $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
        $user->expects($this->once())
             ->method('getRoles')
             ->will($this->returnValue(array('ROLE_FOO')))
        ;

        $provider = $this->getProvider();
        $provider->expects($this->once())
                 ->method('retrieveUser')
                 ->will($this->returnValue($user))
        ;

        $token = $this->getSupportedToken();
        $token->expects($this->once())
              ->method('getCredentials')
              ->will($this->returnValue('foo'))
        ;

        $switchUserRole = new SwitchUserRole('foo', $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'));
        $token->expects($this->once())
              ->method('getRoles')
              ->will($this->returnValue(array($switchUserRole)))
        ;

        $authToken = $provider->authenticate($token);

        $this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', $authToken);
        $this->assertSame($user, $authToken->getUser());
        $this->assertContains(new Role('ROLE_FOO'), $authToken->getRoles(), '', false, false);
        $this->assertContains($switchUserRole, $authToken->getRoles());
        $this->assertEquals('foo', $authToken->getCredentials());
        $this->assertEquals(array('foo' => 'bar'), $authToken->getAttributes(), '->authenticate() copies token attributes');
    }

    protected function getSupportedToken()
    {
        $mock = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', array('getCredentials', 'getProviderKey', 'getRoles'), array(), '', false);
        $mock
            ->expects($this->any())
            ->method('getProviderKey')
            ->will($this->returnValue('key'))
        ;

        $mock->setAttributes(array('foo' => 'bar'));

        return $mock;
    }

    protected function getProvider($userChecker = false, $hide = true)
    {
        if (false === $userChecker) {
            $userChecker = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface');
        }

        return $this->getMockForAbstractClass('Symfony\Component\Security\Core\Authentication\Provider\UserAuthenticationProvider', array($userChecker, 'key', $hide));
    }
}
PK��Z�75ttttest/Security/Symfony/Component/Security/Core/Tests/Authentication/Provider/RememberMeAuthenticationProviderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Authentication\Provider;

use Symfony\Component\Security\Core\Authentication\Provider\RememberMeAuthenticationProvider;
use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken;
use Symfony\Component\Security\Core\Role\Role;

class RememberMeAuthenticationProviderTest extends \PHPUnit_Framework_TestCase
{
    public function testSupports()
    {
        $provider = $this->getProvider();

        $this->assertTrue($provider->supports($this->getSupportedToken()));
        $this->assertFalse($provider->supports($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')));
    }

    public function testAuthenticateWhenTokenIsNotSupported()
    {
        $provider = $this->getProvider();

        $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
        $this->assertNull($provider->authenticate($token));
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
     */
    public function testAuthenticateWhenKeysDoNotMatch()
    {
        $provider = $this->getProvider(null, 'key1');
        $token = $this->getSupportedToken(null, 'key2');

        $provider->authenticate($token);
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\AccountExpiredException
     */
    public function testAuthenticateWhenPostChecksFails()
    {
        $userChecker = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface');
        $userChecker->expects($this->once())
                    ->method('checkPostAuth')
                    ->will($this->throwException($this->getMock('Symfony\Component\Security\Core\Exception\AccountExpiredException', null, array(), '', false)))
        ;

        $provider = $this->getProvider($userChecker);

        $provider->authenticate($this->getSupportedToken());
    }

    public function testAuthenticate()
    {
        $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
        $user->expects($this->exactly(2))
             ->method('getRoles')
             ->will($this->returnValue(array('ROLE_FOO')))
        ;

        $provider = $this->getProvider();

        $token = $this->getSupportedToken($user);
        $authToken = $provider->authenticate($token);

        $this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\RememberMeToken', $authToken);
        $this->assertSame($user, $authToken->getUser());
        $this->assertEquals(array(new Role('ROLE_FOO')), $authToken->getRoles());
        $this->assertEquals('', $authToken->getCredentials());
    }

    protected function getSupportedToken($user = null, $key = 'test')
    {
        if (null === $user) {
            $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
            $user
                ->expects($this->any())
                ->method('getRoles')
                ->will($this->returnValue(array()))
            ;
        }

        $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\RememberMeToken', array('getProviderKey'), array($user, 'foo', $key));
        $token
            ->expects($this->once())
            ->method('getProviderKey')
            ->will($this->returnValue('foo'))
        ;

        return $token;
    }

    protected function getProvider($userChecker = null, $key = 'test')
    {
        if (null === $userChecker) {
            $userChecker = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface');
        }

        return new RememberMeAuthenticationProvider($userChecker, $key, 'foo');
    }
}
PK��Z���ZZztest/Security/Symfony/Component/Security/Core/Tests/Authentication/Provider/PreAuthenticatedAuthenticationProviderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Authentication\Provider;

use Symfony\Component\Security\Core\Authentication\Provider\PreAuthenticatedAuthenticationProvider;

class PreAuthenticatedAuthenticationProviderTest extends \PHPUnit_Framework_TestCase
{
    public function testSupports()
    {
        $provider = $this->getProvider();

        $this->assertTrue($provider->supports($this->getSupportedToken()));
        $this->assertFalse($provider->supports($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')));

        $token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken')
                    ->disableOriginalConstructor()
                    ->getMock()
        ;
        $token
            ->expects($this->once())
            ->method('getProviderKey')
            ->will($this->returnValue('foo'))
        ;
        $this->assertFalse($provider->supports($token));
    }

    public function testAuthenticateWhenTokenIsNotSupported()
    {
        $provider = $this->getProvider();

        $this->assertNull($provider->authenticate($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')));
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
     */
    public function testAuthenticateWhenNoUserIsSet()
    {
        $provider = $this->getProvider();
        $provider->authenticate($this->getSupportedToken(''));
    }

    public function testAuthenticate()
    {
        $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
        $user
            ->expects($this->once())
            ->method('getRoles')
            ->will($this->returnValue(array()))
        ;
        $provider = $this->getProvider($user);

        $token = $provider->authenticate($this->getSupportedToken('fabien', 'pass'));
        $this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken', $token);
        $this->assertEquals('pass', $token->getCredentials());
        $this->assertEquals('key', $token->getProviderKey());
        $this->assertEquals(array(), $token->getRoles());
        $this->assertEquals(array('foo' => 'bar'), $token->getAttributes(), '->authenticate() copies token attributes');
        $this->assertSame($user, $token->getUser());
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\LockedException
     */
    public function testAuthenticateWhenUserCheckerThrowsException()
    {
        $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');

        $userChecker = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface');
        $userChecker->expects($this->once())
                    ->method('checkPostAuth')
                    ->will($this->throwException($this->getMock('Symfony\Component\Security\Core\Exception\LockedException', null, array(), '', false)))
        ;

        $provider = $this->getProvider($user, $userChecker);

        $provider->authenticate($this->getSupportedToken('fabien'));
    }

    protected function getSupportedToken($user = false, $credentials = false)
    {
        $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken', array('getUser', 'getCredentials', 'getProviderKey'), array(), '', false);
        if (false !== $user) {
            $token->expects($this->once())
                  ->method('getUser')
                  ->will($this->returnValue($user))
            ;
        }
        if (false !== $credentials) {
            $token->expects($this->once())
                  ->method('getCredentials')
                  ->will($this->returnValue($credentials))
            ;
        }

        $token
            ->expects($this->any())
            ->method('getProviderKey')
            ->will($this->returnValue('key'))
        ;

        $token->setAttributes(array('foo' => 'bar'));

        return $token;
    }

    protected function getProvider($user = null, $userChecker = null)
    {
        $userProvider = $this->getMock('Symfony\Component\Security\Core\User\UserProviderInterface');
        if (null !== $user) {
            $userProvider->expects($this->once())
                         ->method('loadUserByUsername')
                         ->will($this->returnValue($user))
            ;
        }

        if (null === $userChecker) {
            $userChecker = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface');
        }

        return new PreAuthenticatedAuthenticationProvider($userProvider, $userChecker, 'key');
    }
}
PK��Z�����htest/Security/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationProviderManagerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Authentication;

use Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager;
use Symfony\Component\Security\Core\Exception\ProviderNotFoundException;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\AccountStatusException;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;

class AuthenticationProviderManagerTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \InvalidArgumentException
     */
    public function testAuthenticateWithoutProviders()
    {
        new AuthenticationProviderManager(array());
    }

    public function testAuthenticateWhenNoProviderSupportsToken()
    {
        $manager = new AuthenticationProviderManager(array(
            $this->getAuthenticationProvider(false),
        ));

        try {
            $manager->authenticate($token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'));
            $this->fail();
        } catch (ProviderNotFoundException $e) {
            $this->assertSame($token, $e->getToken());
        }
    }

    public function testAuthenticateWhenProviderReturnsAccountStatusException()
    {
        $manager = new AuthenticationProviderManager(array(
            $this->getAuthenticationProvider(true, null, 'Symfony\Component\Security\Core\Exception\AccountStatusException'),
        ));

        try {
            $manager->authenticate($token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'));
            $this->fail();
        } catch (AccountStatusException $e) {
            $this->assertSame($token, $e->getToken());
        }
    }

    public function testAuthenticateWhenProviderReturnsAuthenticationException()
    {
        $manager = new AuthenticationProviderManager(array(
            $this->getAuthenticationProvider(true, null, 'Symfony\Component\Security\Core\Exception\AuthenticationException'),
        ));

        try {
            $manager->authenticate($token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'));
            $this->fail();
        } catch (AuthenticationException $e) {
            $this->assertSame($token, $e->getToken());
        }
    }

    public function testAuthenticateWhenOneReturnsAuthenticationExceptionButNotAll()
    {
        $manager = new AuthenticationProviderManager(array(
            $this->getAuthenticationProvider(true, null, 'Symfony\Component\Security\Core\Exception\AuthenticationException'),
            $this->getAuthenticationProvider(true, $expected = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')),
        ));

        $token = $manager->authenticate($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'));
        $this->assertSame($expected, $token);
    }

    public function testAuthenticateReturnsTokenOfTheFirstMatchingProvider()
    {
        $second = $this->getMock('Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface');
        $second
            ->expects($this->never())
            ->method('supports')
        ;
        $manager = new AuthenticationProviderManager(array(
            $this->getAuthenticationProvider(true, $expected = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')),
            $second,
        ));

        $token = $manager->authenticate($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'));
        $this->assertSame($expected, $token);
    }

    public function testEraseCredentialFlag()
    {
        $manager = new AuthenticationProviderManager(array(
            $this->getAuthenticationProvider(true, $token = new UsernamePasswordToken('foo', 'bar', 'key')),
        ));

        $token = $manager->authenticate($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'));
        $this->assertEquals('', $token->getCredentials());

        $manager = new AuthenticationProviderManager(array(
            $this->getAuthenticationProvider(true, $token = new UsernamePasswordToken('foo', 'bar', 'key')),
        ), false);

        $token = $manager->authenticate($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'));
        $this->assertEquals('bar', $token->getCredentials());
    }

    protected function getAuthenticationProvider($supports, $token = null, $exception = null)
    {
        $provider = $this->getMock('Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface');
        $provider->expects($this->once())
                 ->method('supports')
                 ->will($this->returnValue($supports))
        ;

        if (null !== $token) {
            $provider->expects($this->once())
                     ->method('authenticate')
                     ->will($this->returnValue($token))
            ;
        } elseif (null !== $exception) {
            $provider->expects($this->once())
                     ->method('authenticate')
                     ->will($this->throwException($this->getMock($exception, null, array(), '', false)))
            ;
        }

        return $provider;
    }
}
PK��Z ����ktest/Security/Symfony/Component/Security/Core/Tests/Authentication/RememberMe/InMemoryTokenProviderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Authentication\RememberMe;

use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken;
use Symfony\Component\Security\Core\Authentication\RememberMe\InMemoryTokenProvider;

class InMemoryTokenProviderTest extends \PHPUnit_Framework_TestCase
{
    public function testCreateNewToken()
    {
        $provider = new InMemoryTokenProvider();

        $token = new PersistentToken('foo', 'foo', 'foo', 'foo', new \DateTime());
        $provider->createNewToken($token);

        $this->assertSame($provider->loadTokenBySeries('foo'), $token);
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\TokenNotFoundException
     */
    public function testLoadTokenBySeriesThrowsNotFoundException()
    {
        $provider = new InMemoryTokenProvider();
        $provider->loadTokenBySeries('foo');
    }

    public function testUpdateToken()
    {
        $provider = new InMemoryTokenProvider();

        $token = new PersistentToken('foo', 'foo', 'foo', 'foo', new \DateTime());
        $provider->createNewToken($token);
        $provider->updateToken('foo', 'newFoo', $lastUsed = new \DateTime());
        $token = $provider->loadTokenBySeries('foo');

        $this->assertEquals('newFoo', $token->getTokenValue());
        $this->assertSame($token->getLastUsed(), $lastUsed);
    }

    /**
     * @expectedException \Symfony\Component\Security\Core\Exception\TokenNotFoundException
     */
    public function testDeleteToken()
    {
        $provider = new InMemoryTokenProvider();

        $token = new PersistentToken('foo', 'foo', 'foo', 'foo', new \DateTime());
        $provider->createNewToken($token);
        $provider->deleteTokenBySeries('foo');
        $provider->loadTokenBySeries('foo');
    }
}
PK��ZB�����etest/Security/Symfony/Component/Security/Core/Tests/Authentication/RememberMe/PersistentTokenTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Authentication\RememberMe;

use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken;

class PersistentTokenTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $lastUsed = new \DateTime();
        $token = new PersistentToken('fooclass', 'fooname', 'fooseries', 'footokenvalue', $lastUsed);

        $this->assertEquals('fooclass', $token->getClass());
        $this->assertEquals('fooname', $token->getUsername());
        $this->assertEquals('fooseries', $token->getSeries());
        $this->assertEquals('footokenvalue', $token->getTokenValue());
        $this->assertSame($lastUsed, $token->getLastUsed());
    }
}
PK��ZI?��

ftest/Security/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationTrustResolverTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Authentication;

use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken;
use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver;

class AuthenticationTrustResolverTest extends \PHPUnit_Framework_TestCase
{
    public function testIsAnonymous()
    {
        $resolver = $this->getResolver();

        $this->assertFalse($resolver->isAnonymous(null));
        $this->assertFalse($resolver->isAnonymous($this->getToken()));
        $this->assertFalse($resolver->isAnonymous($this->getRememberMeToken()));
        $this->assertTrue($resolver->isAnonymous($this->getAnonymousToken()));
    }

    public function testIsRememberMe()
    {
        $resolver = $this->getResolver();

        $this->assertFalse($resolver->isRememberMe(null));
        $this->assertFalse($resolver->isRememberMe($this->getToken()));
        $this->assertFalse($resolver->isRememberMe($this->getAnonymousToken()));
        $this->assertTrue($resolver->isRememberMe($this->getRememberMeToken()));
    }

    public function testisFullFledged()
    {
        $resolver = $this->getResolver();

        $this->assertFalse($resolver->isFullFledged(null));
        $this->assertFalse($resolver->isFullFledged($this->getAnonymousToken()));
        $this->assertFalse($resolver->isFullFledged($this->getRememberMeToken()));
        $this->assertTrue($resolver->isFullFledged($this->getToken()));
    }

    protected function getToken()
    {
        return $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
    }

    protected function getAnonymousToken()
    {
        return $this->getMock('Symfony\Component\Security\Core\Authentication\Token\AnonymousToken', null, array('', ''));
    }

    protected function getRememberMeToken()
    {
        return $this->getMock('Symfony\Component\Security\Core\Authentication\Token\RememberMeToken', array('setPersistent'), array(), '', false);
    }

    protected function getResolver()
    {
        return new AuthenticationTrustResolver(
            'Symfony\\Component\\Security\\Core\\Authentication\\Token\\AnonymousToken',
            'Symfony\\Component\\Security\\Core\\Authentication\\Token\\RememberMeToken'
        );
    }
}
PK��Z�B3��$�$^test/Security/Symfony/Component/Security/Core/Tests/Authentication/Token/AbstractTokenTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Authentication\Token;

use Symfony\Component\Security\Core\Authentication\Token\AbstractToken;
use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Security\Core\Role\SwitchUserRole;

class TestUser
{
    protected $name;

    public function __construct($name)
    {
        $this->name = $name;
    }

    public function __toString()
    {
        return $this->name;
    }
}

class ConcreteToken extends AbstractToken
{
    private $credentials = 'credentials_value';

    public function __construct($user, array $roles = array())
    {
        parent::__construct($roles);

        $this->setUser($user);
    }

    public function serialize()
    {
        return serialize(array($this->credentials, parent::serialize()));
    }

    public function unserialize($serialized)
    {
        list($this->credentials, $parentStr) = unserialize($serialized);
        parent::unserialize($parentStr);
    }

    public function getCredentials() {}
}

class AbstractTokenTest extends \PHPUnit_Framework_TestCase
{
    public function testGetUsername()
    {
        $token = $this->getToken(array('ROLE_FOO'));
        $token->setUser('fabien');
        $this->assertEquals('fabien', $token->getUsername());

        $token->setUser(new TestUser('fabien'));
        $this->assertEquals('fabien', $token->getUsername());

        $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
        $user->expects($this->once())->method('getUsername')->will($this->returnValue('fabien'));
        $token->setUser($user);
        $this->assertEquals('fabien', $token->getUsername());
    }

    public function testEraseCredentials()
    {
        $token = $this->getToken(array('ROLE_FOO'));

        $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
        $user->expects($this->once())->method('eraseCredentials');
        $token->setUser($user);

        $token->eraseCredentials();
    }

    /**
     * @covers Symfony\Component\Security\Core\Authentication\Token\AbstractToken::serialize
     * @covers Symfony\Component\Security\Core\Authentication\Token\AbstractToken::unserialize
     */
    public function testSerialize()
    {
        $token = $this->getToken(array('ROLE_FOO'));
        $token->setAttributes(array('foo' => 'bar'));

        $uToken = unserialize(serialize($token));

        $this->assertEquals($token->getRoles(), $uToken->getRoles());
        $this->assertEquals($token->getAttributes(), $uToken->getAttributes());
    }

    public function testSerializeParent()
    {
        $user = new TestUser('fabien');
        $token = new ConcreteToken($user, array('ROLE_FOO'));

        $parentToken = new ConcreteToken($user, array(new SwitchUserRole('ROLE_PREVIOUS', $token)));
        $uToken = unserialize(serialize($parentToken));

        $this->assertEquals(
            current($parentToken->getRoles())->getSource()->getUser(),
            current($uToken->getRoles())->getSource()->getUser()
        );
    }

    /**
     * @covers Symfony\Component\Security\Core\Authentication\Token\AbstractToken::__construct
     */
    public function testConstructor()
    {
        $token = $this->getToken(array('ROLE_FOO'));
        $this->assertEquals(array(new Role('ROLE_FOO')), $token->getRoles());

        $token = $this->getToken(array(new Role('ROLE_FOO')));
        $this->assertEquals(array(new Role('ROLE_FOO')), $token->getRoles());

        $token = $this->getToken(array(new Role('ROLE_FOO'), 'ROLE_BAR'));
        $this->assertEquals(array(new Role('ROLE_FOO'), new Role('ROLE_BAR')), $token->getRoles());
    }

    /**
     * @covers Symfony\Component\Security\Core\Authentication\Token\AbstractToken::isAuthenticated
     * @covers Symfony\Component\Security\Core\Authentication\Token\AbstractToken::setAuthenticated
     */
    public function testAuthenticatedFlag()
    {
        $token = $this->getToken();
        $this->assertFalse($token->isAuthenticated());

        $token->setAuthenticated(true);
        $this->assertTrue($token->isAuthenticated());

        $token->setAuthenticated(false);
        $this->assertFalse($token->isAuthenticated());
    }

    /**
     * @covers Symfony\Component\Security\Core\Authentication\Token\AbstractToken::getAttributes
     * @covers Symfony\Component\Security\Core\Authentication\Token\AbstractToken::setAttributes
     * @covers Symfony\Component\Security\Core\Authentication\Token\AbstractToken::hasAttribute
     * @covers Symfony\Component\Security\Core\Authentication\Token\AbstractToken::getAttribute
     * @covers Symfony\Component\Security\Core\Authentication\Token\AbstractToken::setAttribute
     */
    public function testAttributes()
    {
        $attributes = array('foo' => 'bar');
        $token = $this->getToken();
        $token->setAttributes($attributes);

        $this->assertEquals($attributes, $token->getAttributes(), '->getAttributes() returns the token attributes');
        $this->assertEquals('bar', $token->getAttribute('foo'), '->getAttribute() returns the value of an attribute');
        $token->setAttribute('foo', 'foo');
        $this->assertEquals('foo', $token->getAttribute('foo'), '->setAttribute() changes the value of an attribute');
        $this->assertTrue($token->hasAttribute('foo'), '->hasAttribute() returns true if the attribute is defined');
        $this->assertFalse($token->hasAttribute('oof'), '->hasAttribute() returns false if the attribute is not defined');

        try {
            $token->getAttribute('foobar');
            $this->fail('->getAttribute() throws an \InvalidArgumentException exception when the attribute does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->getAttribute() throws an \InvalidArgumentException exception when the attribute does not exist');
            $this->assertEquals('This token has no "foobar" attribute.', $e->getMessage(), '->getAttribute() throws an \InvalidArgumentException exception when the attribute does not exist');
        }
    }

    /**
     * @dataProvider getUsers
     */
    public function testSetUser($user)
    {
        $token = $this->getToken();
        $token->setUser($user);
        $this->assertSame($user, $token->getUser());
    }

    public function getUsers()
    {
        $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
        $advancedUser = $this->getMock('Symfony\Component\Security\Core\User\AdvancedUserInterface');

        return array(
            array($advancedUser),
            array($user),
            array(new TestUser('foo')),
            array('foo'),
        );
    }

    /**
     * @dataProvider getUserChanges
     */
    public function testSetUserSetsAuthenticatedToFalseWhenUserChanges($firstUser, $secondUser)
    {
        $token = $this->getToken();
        $token->setAuthenticated(true);
        $this->assertTrue($token->isAuthenticated());

        $token->setUser($firstUser);
        $this->assertTrue($token->isAuthenticated());

        $token->setUser($secondUser);
        $this->assertFalse($token->isAuthenticated());
    }

    public function getUserChanges()
    {
        $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
        $advancedUser = $this->getMock('Symfony\Component\Security\Core\User\AdvancedUserInterface');

        return array(
            array(
                'foo', 'bar',
            ),
            array(
                'foo', new TestUser('bar'),
            ),
            array(
                'foo', $user,
            ),
            array(
                'foo', $advancedUser
            ),
            array(
                $user, 'foo'
            ),
            array(
                $advancedUser, 'foo'
            ),
            array(
                $user, new TestUser('foo'),
            ),
            array(
                $advancedUser, new TestUser('foo'),
            ),
            array(
                new TestUser('foo'), new TestUser('bar'),
            ),
            array(
                new TestUser('foo'), 'bar',
            ),
            array(
                new TestUser('foo'), $user,
            ),
            array(
                new TestUser('foo'), $advancedUser,
            ),
            array(
                $user, $advancedUser
            ),
            array(
                $advancedUser, $user
            ),
        );
    }

    /**
     * @dataProvider getUsers
     */
    public function testSetUserDoesNotSetAuthenticatedToFalseWhenUserDoesNotChange($user)
    {
        $token = $this->getToken();
        $token->setAuthenticated(true);
        $this->assertTrue($token->isAuthenticated());

        $token->setUser($user);
        $this->assertTrue($token->isAuthenticated());

        $token->setUser($user);
        $this->assertTrue($token->isAuthenticated());
    }

    protected function getToken(array $roles = array())
    {
        return $this->getMockForAbstractClass('Symfony\Component\Security\Core\Authentication\Token\AbstractToken', array($roles));
    }
}
PK��Z�j��KKftest/Security/Symfony/Component/Security/Core/Tests/Authentication/Token/UsernamePasswordTokenTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Authentication\Token;

use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Role\Role;

class UsernamePasswordTokenTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $token = new UsernamePasswordToken('foo', 'bar', 'key');
        $this->assertFalse($token->isAuthenticated());

        $token = new UsernamePasswordToken('foo', 'bar', 'key', array('ROLE_FOO'));
        $this->assertEquals(array(new Role('ROLE_FOO')), $token->getRoles());
        $this->assertTrue($token->isAuthenticated());
        $this->assertEquals('key', $token->getProviderKey());
    }

    /**
     * @expectedException \LogicException
     */
    public function testSetAuthenticatedToTrue()
    {
        $token = new UsernamePasswordToken('foo', 'bar', 'key');
        $token->setAuthenticated(true);
    }

    public function testSetAuthenticatedToFalse()
    {
        $token = new UsernamePasswordToken('foo', 'bar', 'key');
        $token->setAuthenticated(false);
        $this->assertFalse($token->isAuthenticated());
    }

    public function testEraseCredentials()
    {
        $token = new UsernamePasswordToken('foo', 'bar', 'key');
        $token->eraseCredentials();
        $this->assertEquals('', $token->getCredentials());
    }

    public function testToString()
    {
        $token = new UsernamePasswordToken('foo', '', 'foo', array('A', 'B'));
        $this->assertEquals('UsernamePasswordToken(user="foo", authenticated=true, roles="A, B")', (string) $token);
    }
}
PK��Zd���ftest/Security/Symfony/Component/Security/Core/Tests/Authentication/Token/PreAuthenticatedTokenTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Authentication\Token;

use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken;
use Symfony\Component\Security\Core\Role\Role;

class PreAuthenticatedTokenTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $token = new PreAuthenticatedToken('foo', 'bar', 'key');
        $this->assertFalse($token->isAuthenticated());

        $token = new PreAuthenticatedToken('foo', 'bar', 'key', array('ROLE_FOO'));
        $this->assertTrue($token->isAuthenticated());
        $this->assertEquals(array(new Role('ROLE_FOO')), $token->getRoles());
        $this->assertEquals('key', $token->getProviderKey());
    }

    public function testGetCredentials()
    {
        $token = new PreAuthenticatedToken('foo', 'bar', 'key');
        $this->assertEquals('bar', $token->getCredentials());
    }

    public function testGetUser()
    {
        $token = new PreAuthenticatedToken('foo', 'bar', 'key');
        $this->assertEquals('foo', $token->getUser());
    }

    public function testEraseCredentials()
    {
        $token = new PreAuthenticatedToken('foo', 'bar', 'key');
        $token->eraseCredentials();
        $this->assertEquals('', $token->getCredentials());
    }
}
PK��Z��ۛ��_test/Security/Symfony/Component/Security/Core/Tests/Authentication/Token/AnonymousTokenTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Authentication\Token;

use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
use Symfony\Component\Security\Core\Role\Role;

class AnonymousTokenTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $token = new AnonymousToken('foo', 'bar');
        $this->assertTrue($token->isAuthenticated());

        $token = new AnonymousToken('foo', 'bar', array('ROLE_FOO'));
        $this->assertEquals(array(new Role('ROLE_FOO')), $token->getRoles());
    }

    public function testGetKey()
    {
        $token = new AnonymousToken('foo', 'bar');
        $this->assertEquals('foo', $token->getKey());
    }

    public function testGetCredentials()
    {
        $token = new AnonymousToken('foo', 'bar');
        $this->assertEquals('', $token->getCredentials());
    }

    public function testGetUser()
    {
        $token = new AnonymousToken('foo', 'bar');
        $this->assertEquals('bar', $token->getUser());
    }
}
PK��Z]�P�<<>test/Security/Symfony/Component/Security/Core/phpunit.xml.distnu�[���<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony Security Component Core Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./vendor</directory>
                <directory>./Tests</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
PK��Z���n��Ltest/Validator/Symfony/Component/Validator/Tests/ConstraintViolationTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests;

use Symfony\Component\Validator\ConstraintViolation;

class ConstraintViolationTest extends \PHPUnit_Framework_TestCase
{
    public function testToStringHandlesArrays()
    {
        $violation = new ConstraintViolation(
            'Array',
            '{{ value }}',
            array('{{ value }}' => array(1, 2, 3)),
            'Root',
            'property.path',
            null
        );

        $expected = <<<EOF
Root.property.path:
    Array
EOF;

        $this->assertSame($expected, (string) $violation);
    }

    public function testToStringHandlesArrayRoots()
    {
        $violation = new ConstraintViolation(
            '42 cannot be used here',
            'this is the message template',
            array(),
            array('some_value' =>  42),
            'some_value',
            null
        );

        $expected = <<<EOF
Array.some_value:
    42 cannot be used here
EOF;

        $this->assertSame($expected, (string) $violation);
    }
}
PK��ZzJ.4�
�
Ptest/Validator/Symfony/Component/Validator/Tests/ConstraintViolationListTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests;

use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;

class ConstraintViolationListTest extends \PHPUnit_Framework_TestCase
{
    protected $list;

    protected function setUp()
    {
        $this->list = new ConstraintViolationList();
    }

    protected function tearDown()
    {
        $this->list = null;
    }

    public function testInit()
    {
        $this->assertCount(0, $this->list);
    }

    public function testInitWithViolations()
    {
        $violation = $this->getViolation('Error');
        $this->list = new ConstraintViolationList(array($violation));

        $this->assertCount(1, $this->list);
        $this->assertSame($violation, $this->list[0]);
    }

    public function testAdd()
    {
        $violation = $this->getViolation('Error');
        $this->list->add($violation);

        $this->assertCount(1, $this->list);
        $this->assertSame($violation, $this->list[0]);
    }

    public function testAddAll()
    {
        $violations = array(
            10 => $this->getViolation('Error 1'),
            20 => $this->getViolation('Error 2'),
            30 => $this->getViolation('Error 3'),
        );
        $otherList = new ConstraintViolationList($violations);
        $this->list->addAll($otherList);

        $this->assertCount(3, $this->list);

        $this->assertSame($violations[10], $this->list[0]);
        $this->assertSame($violations[20], $this->list[1]);
        $this->assertSame($violations[30], $this->list[2]);
    }

    public function testIterator()
    {
        $violations = array(
            10 => $this->getViolation('Error 1'),
            20 => $this->getViolation('Error 2'),
            30 => $this->getViolation('Error 3'),
        );

        $this->list = new ConstraintViolationList($violations);

        // indices are reset upon adding -> array_values()
        $this->assertSame(array_values($violations), iterator_to_array($this->list));
    }

    public function testArrayAccess()
    {
        $violation = $this->getViolation('Error');
        $this->list[] = $violation;

        $this->assertSame($violation, $this->list[0]);
        $this->assertTrue(isset($this->list[0]));

        unset($this->list[0]);

        $this->assertFalse(isset($this->list[0]));

        $this->list[10] = $violation;

        $this->assertSame($violation, $this->list[10]);
        $this->assertTrue(isset($this->list[10]));
    }

    public function testToString()
    {
        $this->list = new ConstraintViolationList(array(
            $this->getViolation('Error 1', 'Root'),
            $this->getViolation('Error 2', 'Root', 'foo.bar'),
            $this->getViolation('Error 3', 'Root', '[baz]'),
            $this->getViolation('Error 4', '', 'foo.bar'),
            $this->getViolation('Error 5', '', '[baz]'),
        ));

        $expected = <<<EOF
Root:
    Error 1
Root.foo.bar:
    Error 2
Root[baz]:
    Error 3
foo.bar:
    Error 4
[baz]:
    Error 5

EOF;

        $this->assertEquals($expected, (string) $this->list);
    }

    protected function getViolation($message, $root = null, $propertyPath = null)
    {
        return new ConstraintViolation($message, $message, array(), $root, $propertyPath, null);
    }
}
PK��Z�p��ggXtest/Validator/Symfony/Component/Validator/Tests/Fixtures/FailingConstraintValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class FailingConstraintValidator extends ConstraintValidator
{
    public function validate($value, Constraint $constraint)
    {
        $this->context->addViolation($constraint->message, array());

        return;
    }
}
PK��Z5*�Itest/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintB.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\Constraint;

/** @Annotation */
class ConstraintB extends Constraint
{
    public function getTargets()
    {
        return array(self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT);
    }
}
PK��Z]�qqItest/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintC.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\Constraint;

/** @Annotation */
class ConstraintC extends Constraint
{
    public $option1;

    public function getRequiredOptions()
    {
        return array('option1');
    }

    public function getTargets()
    {
        return array(self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT);
    }
}
PK��Z���&��Itest/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintA.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\Constraint;

/** @Annotation */
class ConstraintA extends Constraint
{
    public $property1;
    public $property2;

    public function getDefaultOption()
    {
        return 'property2';
    }

    public function getTargets()
    {
        return array(self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT);
    }
}
PK��Zߛ��[[Dtest/Validator/Symfony/Component/Validator/Tests/Fixtures/Entity.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\ExecutionContextInterface;

/**
 * @Symfony\Component\Validator\Tests\Fixtures\ConstraintA
 * @Assert\GroupSequence({"Foo", "Entity"})
 * @Assert\Callback({"Symfony\Component\Validator\Tests\Fixtures\CallbackClass", "callback"})
 */
class Entity extends EntityParent implements EntityInterface
{
    /**
     * @Assert\NotNull
     * @Assert\Range(min=3)
     * @Assert\All({@Assert\NotNull, @Assert\Range(min=3)}),
     * @Assert\All(constraints={@Assert\NotNull, @Assert\Range(min=3)})
     * @Assert\Collection(fields={
     *   "foo" = {@Assert\NotNull, @Assert\Range(min=3)},
     *   "bar" = @Assert\Range(min=5)
     * })
     * @Assert\Choice(choices={"A", "B"}, message="Must be one of %choices%")
     */
    protected $firstName;
    protected $lastName;
    public $reference;
    private $internal;
    public $data = 'Overridden data';

    public function __construct($internal = null)
    {
        $this->internal = $internal;
    }

    public function getInternal()
    {
        return $this->internal.' from getter';
    }

    /**
     * @Assert\NotNull
     */
    public function getLastName()
    {
        return $this->lastName;
    }

    public function getData()
    {
        return 'Overridden data';
    }

    /**
     * @Assert\Callback
     */
    public function validateMe(ExecutionContextInterface $context)
    {
    }

    /**
     * @Assert\Callback
     */
    public static function validateMeStatic($object, ExecutionContextInterface $context)
    {
    }
}
PK��Zp�Tq��Ztest/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintWithValueAsDefault.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\Constraint;

/** @Annotation */
class ConstraintWithValueAsDefault extends Constraint
{
    public $property;
    public $value;

    public function getDefaultOption()
    {
        return 'value';
    }

    public function getTargets()
    {
        return array(self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT);
    }
}
PK��Z@��w��Qtest/Validator/Symfony/Component/Validator/Tests/Fixtures/FakeMetadataFactory.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\MetadataFactoryInterface;
use Symfony\Component\Validator\Exception\NoSuchMetadataException;
use Symfony\Component\Validator\Mapping\ClassMetadata;

class FakeMetadataFactory implements MetadataFactoryInterface
{
    protected $metadatas = array();

    public function getMetadataFor($class)
    {
        if (is_object($class)) {
            $class = get_class($class);
        }

        if (!is_string($class)) {
            throw new NoSuchMetadataException(sprintf('No metadata for type %s', gettype($class)));
        }

        if (!isset($this->metadatas[$class])) {
            throw new NoSuchMetadataException(sprintf('No metadata for "%s"', $class));
        }

        return $this->metadatas[$class];
    }

    public function hasMetadataFor($class)
    {
        if (is_object($class)) {
            $class = get_class($class);
        }

        if (!is_string($class)) {
            return false;
        }

        return isset($this->metadatas[$class]);
    }

    public function addMetadata(ClassMetadata $metadata)
    {
        $this->metadatas[$metadata->getClassName()] = $metadata;
    }
}
PK��Z��a�CCMtest/Validator/Symfony/Component/Validator/Tests/Fixtures/EntityInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

interface EntityInterface
{
}
PK��Z?>��Rtest/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintAValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\ExecutionContextInterface;

class ConstraintAValidator extends ConstraintValidator
{
    public static $passedContext;

    public function initialize(ExecutionContextInterface $context)
    {
        parent::initialize($context);

        self::$passedContext = $context;
    }

    public function validate($value, Constraint $constraint)
    {
        if ('VALID' != $value) {
            $this->context->addViolation('message', array('param' => 'value'));

            return;
        }

        return;
    }
}
PK��Z^t��Mtest/Validator/Symfony/Component/Validator/Tests/Fixtures/ClassConstraint.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\Constraint;

class ClassConstraint extends Constraint
{
    public function getTargets()
    {
        return self::CLASS_CONSTRAINT;
    }
}
PK��Z��88Jtest/Validator/Symfony/Component/Validator/Tests/Fixtures/EntityParent.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\Constraints\NotNull;

class EntityParent
{
    protected $firstName;
    private $internal;
    private $data = 'Data';

    /**
     * @NotNull
     */
    protected $other;

    public function getData()
    {
        return 'Data';
    }
}
PK��Z�h��Ytest/Validator/Symfony/Component/Validator/Tests/Fixtures/GroupSequenceProviderEntity.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\GroupSequenceProviderInterface;

/**
 * @Assert\GroupSequenceProvider
 */
class GroupSequenceProviderEntity implements GroupSequenceProviderInterface
{
    public $firstName;
    public $lastName;

    protected $groups = array();

    public function setGroups($groups)
    {
        $this->groups = $groups;
    }

    public function getGroupSequence()
    {
        return $this->groups;
    }
}
PK��Z�5>��Qtest/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintWithValue.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\Constraint;

/** @Annotation */
class ConstraintWithValue extends Constraint
{
    public $property;
    public $value;

    public function getDefaultOption()
    {
        return 'property';
    }

    public function getTargets()
    {
        return array(self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT);
    }
}
PK��Z=�2Otest/Validator/Symfony/Component/Validator/Tests/Fixtures/FailingConstraint.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\Constraint;

class FailingConstraint extends Constraint
{
    public $message = 'Failed';

    public function getTargets()
    {
        return array(self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT);
    }
}
PK��ZO��l99Gtest/Validator/Symfony/Component/Validator/Tests/Fixtures/Reference.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

class Reference
{
}
PK��Z2�	���Otest/Validator/Symfony/Component/Validator/Tests/Fixtures/InvalidConstraint.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\Constraint;

class InvalidConstraint extends Constraint
{
}
PK��Zj�/���Itest/Validator/Symfony/Component/Validator/Tests/Fixtures/FilesLoader.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\Mapping\Loader\FilesLoader as BaseFilesLoader;
use Symfony\Component\Validator\Mapping\Loader\LoaderInterface;

abstract class FilesLoader extends BaseFilesLoader
{
    protected $timesCalled = 0;
    protected $loader;

    public function __construct(array $paths, LoaderInterface $loader)
    {
        $this->loader = $loader;
        parent::__construct($paths);
    }

    protected function getFileLoaderInstance($file)
    {
        $this->timesCalled++;

        return $this->loader;
    }

    public function getTimesCalled()
    {
        return $this->timesCalled;
    }
}
PK��ZY��/Ktest/Validator/Symfony/Component/Validator/Tests/Fixtures/CallbackClass.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\ExecutionContextInterface;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class CallbackClass
{
    public static function callback($object, ExecutionContextInterface $context)
    {
    }
}
PK��Z���JJXtest/Validator/Symfony/Component/Validator/Tests/Fixtures/InvalidConstraintValidator.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

class InvalidConstraintValidator
{
}
PK��ZG#i��Ptest/Validator/Symfony/Component/Validator/Tests/Fixtures/PropertyConstraint.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\Constraint;

class PropertyConstraint extends Constraint
{
    public function getTargets()
    {
        return self::PROPERTY_CONSTRAINT;
    }
}
PK��Z�Ε_))Itest/Validator/Symfony/Component/Validator/Tests/ValidatorBuilderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests;

use Symfony\Component\Validator\ValidatorBuilder;
use Symfony\Component\Validator\ValidatorBuilderInterface;

class ValidatorBuilderTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var ValidatorBuilderInterface
     */
    protected $builder;

    protected function setUp()
    {
        $this->builder = new ValidatorBuilder();
    }

    protected function tearDown()
    {
        $this->builder = null;
    }

    public function testAddObjectInitializer()
    {
        $this->assertSame($this->builder, $this->builder->addObjectInitializer(
            $this->getMock('Symfony\Component\Validator\ObjectInitializerInterface')
        ));
    }

    public function testAddObjectInitializers()
    {
        $this->assertSame($this->builder, $this->builder->addObjectInitializers(array()));
    }

    public function testAddXmlMapping()
    {
        $this->assertSame($this->builder, $this->builder->addXmlMapping('mapping'));
    }

    public function testAddXmlMappings()
    {
        $this->assertSame($this->builder, $this->builder->addXmlMappings(array()));
    }

    public function testAddYamlMapping()
    {
        $this->assertSame($this->builder, $this->builder->addYamlMapping('mapping'));
    }

    public function testAddYamlMappings()
    {
        $this->assertSame($this->builder, $this->builder->addYamlMappings(array()));
    }

    public function testAddMethodMapping()
    {
        $this->assertSame($this->builder, $this->builder->addMethodMapping('mapping'));
    }

    public function testAddMethodMappings()
    {
        $this->assertSame($this->builder, $this->builder->addMethodMappings(array()));
    }

    public function testEnableAnnotationMapping()
    {
        $this->assertSame($this->builder, $this->builder->enableAnnotationMapping());
    }

    public function testDisableAnnotationMapping()
    {
        $this->assertSame($this->builder, $this->builder->disableAnnotationMapping());
    }

    public function testSetMetadataCache()
    {
        $this->assertSame($this->builder, $this->builder->setMetadataCache(
            $this->getMock('Symfony\Component\Validator\Mapping\Cache\CacheInterface'))
        );
    }

    public function testSetConstraintValidatorFactory()
    {
        $this->assertSame($this->builder, $this->builder->setConstraintValidatorFactory(
            $this->getMock('Symfony\Component\Validator\ConstraintValidatorFactoryInterface'))
        );
    }

    public function testSetTranslator()
    {
        $this->assertSame($this->builder, $this->builder->setTranslator(
            $this->getMock('Symfony\Component\Translation\TranslatorInterface'))
        );
    }

    public function testSetTranslationDomain()
    {
        $this->assertSame($this->builder, $this->builder->setTranslationDomain('TRANS_DOMAIN'));
    }
}
PK��Z��>���Ntest/Validator/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Mapping;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Constraints\Valid;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Exception\GroupDefinitionException;
use Symfony\Component\Validator\Tests\Fixtures\Entity;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintB;
use Symfony\Component\Validator\Tests\Fixtures\PropertyConstraint;

class ClassMetadataTest extends \PHPUnit_Framework_TestCase
{
    const CLASSNAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity';
    const PARENTCLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityParent';
    const PROVIDERCLASS = 'Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity';

    protected $metadata;

    protected function setUp()
    {
        $this->metadata = new ClassMetadata(self::CLASSNAME);
    }

    protected function tearDown()
    {
        $this->metadata = null;
    }

    public function testAddConstraintDoesNotAcceptValid()
    {
        $this->setExpectedException('Symfony\Component\Validator\Exception\ConstraintDefinitionException');

        $this->metadata->addConstraint(new Valid());
    }

    public function testAddConstraintRequiresClassConstraints()
    {
        $this->setExpectedException('Symfony\Component\Validator\Exception\ConstraintDefinitionException');

        $this->metadata->addConstraint(new PropertyConstraint());
    }

    public function testAddPropertyConstraints()
    {
        $this->metadata->addPropertyConstraint('firstName', new ConstraintA());
        $this->metadata->addPropertyConstraint('lastName', new ConstraintB());

        $this->assertEquals(array('firstName', 'lastName'), $this->metadata->getConstrainedProperties());
    }

    public function testMergeConstraintsMergesClassConstraints()
    {
        $parent = new ClassMetadata(self::PARENTCLASS);
        $parent->addConstraint(new ConstraintA());

        $this->metadata->mergeConstraints($parent);
        $this->metadata->addConstraint(new ConstraintA());

        $constraints = array(
            new ConstraintA(array('groups' => array(
                'Default',
                'EntityParent',
                'Entity',
            ))),
            new ConstraintA(array('groups' => array(
                'Default',
                'Entity',
            ))),
        );

        $this->assertEquals($constraints, $this->metadata->getConstraints());
    }

    public function testMergeConstraintsMergesMemberConstraints()
    {
        $parent = new ClassMetadata(self::PARENTCLASS);
        $parent->addPropertyConstraint('firstName', new ConstraintA());

        $this->metadata->mergeConstraints($parent);
        $this->metadata->addPropertyConstraint('firstName', new ConstraintA());

        $constraints = array(
            new ConstraintA(array('groups' => array(
                'Default',
                'EntityParent',
                'Entity',
            ))),
            new ConstraintA(array('groups' => array(
                'Default',
                'Entity',
            ))),
        );

        $members = $this->metadata->getMemberMetadatas('firstName');

        $this->assertCount(1, $members);
        $this->assertEquals(self::PARENTCLASS, $members[0]->getClassName());
        $this->assertEquals($constraints, $members[0]->getConstraints());
    }

    public function testMemberMetadatas()
    {
        $this->metadata->addPropertyConstraint('firstName', new ConstraintA());

        $this->assertTrue($this->metadata->hasMemberMetadatas('firstName'));
        $this->assertFalse($this->metadata->hasMemberMetadatas('non_existant_field'));
    }

    public function testMergeConstraintsKeepsPrivateMembersSeparate()
    {
        $parent = new ClassMetadata(self::PARENTCLASS);
        $parent->addPropertyConstraint('internal', new ConstraintA());

        $this->metadata->mergeConstraints($parent);
        $this->metadata->addPropertyConstraint('internal', new ConstraintA());

        $parentConstraints = array(
            new ConstraintA(array('groups' => array(
                'Default',
                'EntityParent',
                'Entity',
            ))),
        );
        $constraints = array(
            new ConstraintA(array('groups' => array(
                'Default',
                'Entity',
            ))),
        );

        $members = $this->metadata->getMemberMetadatas('internal');

        $this->assertCount(2, $members);
        $this->assertEquals(self::PARENTCLASS, $members[0]->getClassName());
        $this->assertEquals($parentConstraints, $members[0]->getConstraints());
        $this->assertEquals(self::CLASSNAME, $members[1]->getClassName());
        $this->assertEquals($constraints, $members[1]->getConstraints());
    }

    public function testGetReflectionClass()
    {
        $reflClass = new \ReflectionClass(self::CLASSNAME);

        $this->assertEquals($reflClass, $this->metadata->getReflectionClass());
    }

    public function testSerialize()
    {
        $this->metadata->addConstraint(new ConstraintA(array('property1' => 'A')));
        $this->metadata->addConstraint(new ConstraintB(array('groups' => 'TestGroup')));
        $this->metadata->addPropertyConstraint('firstName', new ConstraintA());
        $this->metadata->addGetterConstraint('lastName', new ConstraintB());

        $metadata = unserialize(serialize($this->metadata));

        $this->assertEquals($this->metadata, $metadata);
    }

    public function testGroupSequencesWorkIfContainingDefaultGroup()
    {
        $this->metadata->setGroupSequence(array('Foo', $this->metadata->getDefaultGroup()));
    }

    public function testGroupSequencesFailIfNotContainingDefaultGroup()
    {
        $this->setExpectedException('Symfony\Component\Validator\Exception\GroupDefinitionException');

        $this->metadata->setGroupSequence(array('Foo', 'Bar'));
    }

    public function testGroupSequencesFailIfContainingDefault()
    {
        $this->setExpectedException('Symfony\Component\Validator\Exception\GroupDefinitionException');

        $this->metadata->setGroupSequence(array('Foo', $this->metadata->getDefaultGroup(), Constraint::DEFAULT_GROUP));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\GroupDefinitionException
     */
    public function testGroupSequenceFailsIfGroupSequenceProviderIsSet()
    {
        $metadata = new ClassMetadata(self::PROVIDERCLASS);
        $metadata->setGroupSequenceProvider(true);
        $metadata->setGroupSequence(array('GroupSequenceProviderEntity', 'Foo'));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\GroupDefinitionException
     */
    public function testGroupSequenceProviderFailsIfGroupSequenceIsSet()
    {
        $metadata = new ClassMetadata(self::PROVIDERCLASS);
        $metadata->setGroupSequence(array('GroupSequenceProviderEntity', 'Foo'));
        $metadata->setGroupSequenceProvider(true);
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\GroupDefinitionException
     */
    public function testGroupSequenceProviderFailsIfDomainClassIsInvalid()
    {
        $metadata = new ClassMetadata('stdClass');
        $metadata->setGroupSequenceProvider(true);
    }

    public function testGroupSequenceProvider()
    {
        $metadata = new ClassMetadata(self::PROVIDERCLASS);
        $metadata->setGroupSequenceProvider(true);
        $this->assertTrue($metadata->isGroupSequenceProvider());
    }
}
PK��ZF���Utest/Validator/Symfony/Component/Validator/Tests/Mapping/ClassMetadataFactoryTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Mapping;

use Symfony\Component\Validator\Tests\Fixtures\Entity;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
use Symfony\Component\Validator\Mapping\ClassMetadataFactory;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Mapping\Loader\LoaderInterface;

class ClassMetadataFactoryTest extends \PHPUnit_Framework_TestCase
{
    const CLASSNAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity';
    const PARENTCLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityParent';

    public function testLoadClassMetadata()
    {
        $factory = new ClassMetadataFactory(new TestLoader());
        $metadata = $factory->getMetadataFor(self::PARENTCLASS);

        $constraints = array(
            new ConstraintA(array('groups' => array('Default', 'EntityParent'))),
        );

        $this->assertEquals($constraints, $metadata->getConstraints());
    }

    public function testMergeParentConstraints()
    {
        $factory = new ClassMetadataFactory(new TestLoader());
        $metadata = $factory->getMetadataFor(self::CLASSNAME);

        $constraints = array(
            new ConstraintA(array('groups' => array(
                'Default',
                'EntityParent',
                'Entity',
            ))),
            new ConstraintA(array('groups' => array(
                'Default',
                'EntityInterface',
                'Entity',
            ))),
            new ConstraintA(array('groups' => array(
                'Default',
                'Entity',
            ))),
        );

        $this->assertEquals($constraints, $metadata->getConstraints());
    }

    public function testWriteMetadataToCache()
    {
        $cache = $this->getMock('Symfony\Component\Validator\Mapping\Cache\CacheInterface');
        $factory = new ClassMetadataFactory(new TestLoader(), $cache);

        $tester = $this;
        $constraints = array(
            new ConstraintA(array('groups' => array('Default', 'EntityParent'))),
        );

        $cache->expects($this->never())
              ->method('has');
        $cache->expects($this->once())
              ->method('read')
              ->with($this->equalTo(self::PARENTCLASS))
              ->will($this->returnValue(false));
        $cache->expects($this->once())
              ->method('write')
              ->will($this->returnCallback(function ($metadata) use ($tester, $constraints) {
                  $tester->assertEquals($constraints, $metadata->getConstraints());
              }));

        $metadata = $factory->getMetadataFor(self::PARENTCLASS);

        $this->assertEquals(self::PARENTCLASS, $metadata->getClassName());
        $this->assertEquals($constraints, $metadata->getConstraints());
    }

    public function testReadMetadataFromCache()
    {
        $loader = $this->getMock('Symfony\Component\Validator\Mapping\Loader\LoaderInterface');
        $cache = $this->getMock('Symfony\Component\Validator\Mapping\Cache\CacheInterface');
        $factory = new ClassMetadataFactory($loader, $cache);

        $tester = $this;
        $metadata = new ClassMetadata(self::PARENTCLASS);
        $metadata->addConstraint(new ConstraintA());

        $loader->expects($this->never())
               ->method('loadClassMetadata');

        $cache->expects($this->never())
              ->method('has');
        $cache->expects($this->once())
              ->method('read')
              ->will($this->returnValue($metadata));

        $this->assertEquals($metadata,$factory->getMetadataFor(self::PARENTCLASS));
    }
}

class TestLoader implements LoaderInterface
{
    public function loadClassMetadata(ClassMetadata $metadata)
    {
        $metadata->addConstraint(new ConstraintA());
    }
}
PK��Z)����Ptest/Validator/Symfony/Component/Validator/Tests/Mapping/ElementMetadataTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Mapping;

use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintB;
use Symfony\Component\Validator\Mapping\ElementMetadata;

class ElementMetadataTest extends \PHPUnit_Framework_TestCase
{
    protected $metadata;

    protected function setUp()
    {
        $this->metadata = new TestElementMetadata();
    }

    protected function tearDown()
    {
        $this->metadata = null;
    }

    public function testAddConstraints()
    {
        $this->metadata->addConstraint($constraint1 = new ConstraintA());
        $this->metadata->addConstraint($constraint2 = new ConstraintA());

        $this->assertEquals(array($constraint1, $constraint2), $this->metadata->getConstraints());
    }

    public function testMultipleConstraintsOfTheSameType()
    {
        $constraint1 = new ConstraintA(array('property1' => 'A'));
        $constraint2 = new ConstraintA(array('property1' => 'B'));

        $this->metadata->addConstraint($constraint1);
        $this->metadata->addConstraint($constraint2);

        $this->assertEquals(array($constraint1, $constraint2), $this->metadata->getConstraints());
    }

    public function testFindConstraintsByGroup()
    {
        $constraint1 = new ConstraintA(array('groups' => 'TestGroup'));
        $constraint2 = new ConstraintB();

        $this->metadata->addConstraint($constraint1);
        $this->metadata->addConstraint($constraint2);

        $this->assertEquals(array($constraint1), $this->metadata->findConstraints('TestGroup'));
    }

    public function testSerialize()
    {
        $this->metadata->addConstraint(new ConstraintA(array('property1' => 'A')));
        $this->metadata->addConstraint(new ConstraintB(array('groups' => 'TestGroup')));

        $metadata = unserialize(serialize($this->metadata));

        $this->assertEquals($this->metadata, $metadata);
    }
}

class TestElementMetadata extends ElementMetadata {}
PK��Z�D��Otest/Validator/Symfony/Component/Validator/Tests/Mapping/MemberMetadataTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Mapping;

use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintB;
use Symfony\Component\Validator\Tests\Fixtures\ClassConstraint;
use Symfony\Component\Validator\Constraints\Valid;
use Symfony\Component\Validator\Mapping\MemberMetadata;

class MemberMetadataTest extends \PHPUnit_Framework_TestCase
{
    protected $metadata;

    protected function setUp()
    {
        $this->metadata = new TestMemberMetadata(
            'Symfony\Component\Validator\Tests\Fixtures\Entity',
            'getLastName',
            'lastName'
        );
    }

    protected function tearDown()
    {
        $this->metadata = null;
    }

    public function testAddValidSetsMemberToCascaded()
    {
        $result = $this->metadata->addConstraint(new Valid());

        $this->assertEquals(array(), $this->metadata->getConstraints());
        $this->assertEquals($result, $this->metadata);
        $this->assertTrue($this->metadata->isCascaded());
    }

    public function testAddOtherConstraintDoesNotSetMemberToCascaded()
    {
        $result = $this->metadata->addConstraint($constraint = new ConstraintA());

        $this->assertEquals(array($constraint), $this->metadata->getConstraints());
        $this->assertEquals($result, $this->metadata);
        $this->assertFalse($this->metadata->isCascaded());
    }

    public function testAddConstraintRequiresClassConstraints()
    {
        $this->setExpectedException('Symfony\Component\Validator\Exception\ConstraintDefinitionException');

        $this->metadata->addConstraint(new ClassConstraint());
    }

    public function testSerialize()
    {
        $this->metadata->addConstraint(new ConstraintA(array('property1' => 'A')));
        $this->metadata->addConstraint(new ConstraintB(array('groups' => 'TestGroup')));

        $metadata = unserialize(serialize($this->metadata));

        $this->assertEquals($this->metadata, $metadata);
    }

    public function testSerializeCollectionCascaded()
    {
        $this->metadata->addConstraint(new Valid(array('traverse' => true, 'deep' => false)));

        $metadata = unserialize(serialize($this->metadata));

        $this->assertEquals($this->metadata, $metadata);
    }

    public function testSerializeCollectionCascadedDeeply()
    {
        $this->metadata->addConstraint(new Valid(array('traverse' => true, 'deep' => true)));

        $metadata = unserialize(serialize($this->metadata));

        $this->assertEquals($this->metadata, $metadata);
    }

    public function testSerializeCollectionNotCascaded()
    {
        $this->metadata->addConstraint(new Valid(array('traverse' => false)));

        $metadata = unserialize(serialize($this->metadata));

        $this->assertEquals($this->metadata, $metadata);
    }
}

class TestMemberMetadata extends MemberMetadata
{
    public function getPropertyValue($object)
    {
    }

    protected function newReflectionMember($object)
    {
    }
}
PK��ZW_Ϙ�Otest/Validator/Symfony/Component/Validator/Tests/Mapping/GetterMetadataTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Mapping;

use Symfony\Component\Validator\Mapping\GetterMetadata;
use Symfony\Component\Validator\Tests\Fixtures\Entity;

class GetterMetadataTest extends \PHPUnit_Framework_TestCase
{
    const CLASSNAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity';

    public function testInvalidPropertyName()
    {
        $this->setExpectedException('Symfony\Component\Validator\Exception\ValidatorException');

        new GetterMetadata(self::CLASSNAME, 'foobar');
    }

    public function testGetPropertyValueFromPublicGetter()
    {
        // private getters don't work yet because ReflectionMethod::setAccessible()
        // does not exist yet in a stable PHP release

        $entity = new Entity('foobar');
        $metadata = new GetterMetadata(self::CLASSNAME, 'internal');

        $this->assertEquals('foobar from getter', $metadata->getPropertyValue($entity));
    }

    public function testGetPropertyValueFromOverriddenPublicGetter()
    {
        $entity = new Entity();
        $metadata = new GetterMetadata(self::CLASSNAME, 'data');

        $this->assertEquals('Overridden data', $metadata->getPropertyValue($entity));
    }
}
PK��Z"��,�	�	Otest/Validator/Symfony/Component/Validator/Tests/Mapping/Cache/ApcCacheTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Mapping\Cache;

use Symfony\Component\Validator\Mapping\Cache\ApcCache;

class ApcCacheTest extends \PHPUnit_Framework_TestCase
{
    protected function setUp()
    {
        if (!extension_loaded('apc') || !ini_get('apc.enable_cli')) {
            $this->markTestSkipped('APC is not loaded.');
        }
    }

    public function testWrite()
    {
        $meta = $this->getMockBuilder('Symfony\\Component\\Validator\\Mapping\\ClassMetadata')
            ->disableOriginalConstructor()
            ->setMethods(array('getClassName'))
            ->getMock();

        $meta->expects($this->once())
            ->method('getClassName')
            ->will($this->returnValue('bar'));

        $cache = new ApcCache('foo');
        $cache->write($meta);

        $this->assertInstanceOf('Symfony\\Component\\Validator\\Mapping\\ClassMetadata', apc_fetch('foobar'), '->write() stores metadata in APC');
    }

    public function testHas()
    {
        $meta = $this->getMockBuilder('Symfony\\Component\\Validator\\Mapping\\ClassMetadata')
            ->disableOriginalConstructor()
            ->setMethods(array('getClassName'))
            ->getMock();

        $meta->expects($this->once())
            ->method('getClassName')
            ->will($this->returnValue('bar'));

        apc_delete('foobar');

        $cache = new ApcCache('foo');
        $this->assertFalse($cache->has('bar'), '->has() returns false when there is no entry');

        $cache->write($meta);
        $this->assertTrue($cache->has('bar'), '->has() returns true when the is an entry');
    }

    public function testRead()
    {
        $meta = $this->getMockBuilder('Symfony\\Component\\Validator\\Mapping\\ClassMetadata')
            ->disableOriginalConstructor()
            ->setMethods(array('getClassName'))
            ->getMock();

        $meta->expects($this->once())
            ->method('getClassName')
            ->will($this->returnValue('bar'));

        $cache = new ApcCache('foo');
        $cache->write($meta);

        $this->assertInstanceOf('Symfony\\Component\\Validator\\Mapping\\ClassMetadata', $cache->read('bar'), '->read() returns metadata');
    }
}
PK��Zos%�eeYtest/Validator/Symfony/Component/Validator/Tests/Mapping/BlackholeMetadataFactoryTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Mapping;

use Symfony\Component\Validator\Mapping\BlackholeMetadataFactory;

class BlackholeMetadataFactoryTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \LogicException
     */
    public function testGetMetadataForThrowsALogicException()
    {
        $metadataFactory = new BlackholeMetadataFactory();
        $metadataFactory->getMetadataFor('foo');
    }

    public function testHasMetadataForReturnsFalse()
    {
        $metadataFactory = new BlackholeMetadataFactory();

        $this->assertFalse($metadataFactory->hasMetadataFor('foo'));
    }
}
PK��Zu��gStest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/LoaderChainTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Mapping\Loader;

use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Mapping\Loader\LoaderChain;

class LoaderChainTest extends \PHPUnit_Framework_TestCase
{
    public function testAllLoadersAreCalled()
    {
        $metadata = new ClassMetadata('\stdClass');

        $loader1 = $this->getMock('Symfony\Component\Validator\Mapping\Loader\LoaderInterface');
        $loader1->expects($this->once())
                        ->method('loadClassMetadata')
                        ->with($this->equalTo($metadata));

        $loader2 = $this->getMock('Symfony\Component\Validator\Mapping\Loader\LoaderInterface');
        $loader2->expects($this->once())
                        ->method('loadClassMetadata')
                        ->with($this->equalTo($metadata));

        $chain = new LoaderChain(array(
            $loader1,
            $loader2,
        ));

        $chain->loadClassMetadata($metadata);
    }

    public function testReturnsTrueIfAnyLoaderReturnedTrue()
    {
        $metadata = new ClassMetadata('\stdClass');

        $loader1 = $this->getMock('Symfony\Component\Validator\Mapping\Loader\LoaderInterface');
        $loader1->expects($this->any())
                        ->method('loadClassMetadata')
                        ->will($this->returnValue(true));

        $loader2 = $this->getMock('Symfony\Component\Validator\Mapping\Loader\LoaderInterface');
        $loader2->expects($this->any())
                        ->method('loadClassMetadata')
                        ->will($this->returnValue(false));

        $chain = new LoaderChain(array(
            $loader1,
            $loader2,
        ));

        $this->assertTrue($chain->loadClassMetadata($metadata));
    }

    public function testReturnsFalseIfNoLoaderReturnedTrue()
    {
        $metadata = new ClassMetadata('\stdClass');

        $loader1 = $this->getMock('Symfony\Component\Validator\Mapping\Loader\LoaderInterface');
        $loader1->expects($this->any())
                        ->method('loadClassMetadata')
                        ->will($this->returnValue(false));

        $loader2 = $this->getMock('Symfony\Component\Validator\Mapping\Loader\LoaderInterface');
        $loader2->expects($this->any())
                        ->method('loadClassMetadata')
                        ->will($this->returnValue(false));

        $chain = new LoaderChain(array(
            $loader1,
            $loader2,
        ));

        $this->assertFalse($chain->loadClassMetadata($metadata));
    }
}
PK��Z�=����btest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping-non-strings.xmlnu�[���<?xml version="1.0" ?>

<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">

  <namespace prefix="custom">Symfony\Component\Validator\Tests\Fixtures\</namespace>

  <class name="Symfony\Component\Validator\Tests\Fixtures\Entity">
    <property name="firstName">
      <!-- Constraint with a Boolean -->
      <constraint name="Regex">
          <option name="pattern">/^1/</option>
          <option name="match">false</option>
      </constraint>
    </property>
  </class>

</constraint-mapping>
PK��Z�D�k��Vtest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.xmlnu�[���<?xml version="1.0" ?>

<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">

  <namespace prefix="custom">Symfony\Component\Validator\Tests\Fixtures\</namespace>

  <class name="Symfony\Component\Validator\Tests\Fixtures\Entity">

    <group-sequence>
       <value>Foo</value>
       <value>Entity</value>
    </group-sequence>

    <!-- CLASS CONSTRAINTS -->

    <!-- Custom constraint -->
    <constraint name="Symfony\Component\Validator\Tests\Fixtures\ConstraintA" />

    <!-- Custom constraint with namespace abbreviation-->
    <constraint name="custom:ConstraintB" />

    <!-- Callbacks -->
    <constraint name="Callback">validateMe</constraint>

    <constraint name="Callback">validateMeStatic</constraint>

    <constraint name="Callback">
        <value>Symfony\Component\Validator\Tests\Fixtures\CallbackClass</value>
        <value>callback</value>
    </constraint>

    <!-- PROPERTY CONSTRAINTS -->

    <property name="firstName">

      <!-- Constraint without value -->
      <constraint name="NotNull" />

      <!-- Constraint with single value -->
      <constraint name="Range">
         <option name="min">3</option>
      </constraint>

      <!-- Constraint with multiple values -->
      <constraint name="Choice">
        <value>A</value>
        <value>B</value>
      </constraint>

      <!-- Constraint with child constraints -->
      <constraint name="All">
        <constraint name="NotNull" />
        <constraint name="Range">
           <option name="min">3</option>
        </constraint>

      </constraint>

      <!-- Option with child constraints -->
      <constraint name="All">
        <option name="constraints">
          <constraint name="NotNull" />
          <constraint name="Range">
             <option name="min">3</option>
          </constraint>
        </option>
      </constraint>

      <!-- Value with child constraints -->
      <constraint name="Collection">
        <option name="fields">
          <value key="foo">
            <constraint name="NotNull" />
            <constraint name="Range">
               <option name="min">3</option>
            </constraint>
          </value>
          <value key="bar">
            <constraint name="Range">
               <option name="min">5</option>
            </constraint>
          </value>
        </option>
      </constraint>

      <!-- Constraint with options -->
      <constraint name="Choice">
        <!-- Option with single value -->
        <option name="message"> Must be one of %choices% </option>
        <!-- Option with multiple values -->
        <option name="choices">
          <value>A</value>
          <value>B</value>
        </option>
      </constraint>
    </property>

    <!-- GETTER CONSTRAINTS -->

    <getter property="lastName">
      <constraint name="NotNull" />
    </getter>
  </class>

  <class name="Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity">

    <!-- GROUP SEQUENCE PROVIDER -->
    <group-sequence-provider />

  </class>
</constraint-mapping>
PK��Z�-���Vtest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.ymlnu�[���namespaces:
  custom: Symfony\Component\Validator\Tests\Fixtures\

Symfony\Component\Validator\Tests\Fixtures\Entity:
  group_sequence:
    - Foo
    - Entity

  constraints:
    # Custom constraint
    - Symfony\Component\Validator\Tests\Fixtures\ConstraintA: ~
    # Custom constraint with namespaces prefix
    - "custom:ConstraintB": ~
    # Callbacks
    - Callback: validateMe
    - Callback: validateMeStatic
    - Callback: [Symfony\Component\Validator\Tests\Fixtures\CallbackClass, callback]

  properties:
    firstName:
      # Constraint without value
      - NotNull: ~
      # Constraint with single value
      - Range:
          min: 3
      # Constraint with multiple values
      - Choice: [A, B]
      # Constraint with child constraints
      - All:
          - NotNull: ~
          - Range:
              min: 3
      # Option with child constraints
      - All:
          constraints:
            - NotNull: ~
            - Range:
                min: 3
      # Value with child constraints
      - Collection:
          fields:
            foo:
              - NotNull: ~
              - Range:
                  min: 3
            bar:
              - Range:
                  min: 5
      # Constraint with options
      - Choice: { choices: [A, B], message: Must be one of %choices% }
    dummy:

  getters:
    lastName:
      - NotNull: ~

Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity:
  group_sequence_provider: true
PK��Z{�%uZtest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/StaticMethodLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Mapping\Loader;

use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Mapping\Loader\StaticMethodLoader;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;

class StaticMethodLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testLoadClassMetadataReturnsTrueIfSuccessful()
    {
        $loader = new StaticMethodLoader('loadMetadata');
        $metadata = new ClassMetadata(__NAMESPACE__.'\StaticLoaderEntity');

        $this->assertTrue($loader->loadClassMetadata($metadata));
    }

    public function testLoadClassMetadataReturnsFalseIfNotSuccessful()
    {
        $loader = new StaticMethodLoader('loadMetadata');
        $metadata = new ClassMetadata('\stdClass');

        $this->assertFalse($loader->loadClassMetadata($metadata));
    }

    public function testLoadClassMetadata()
    {
        $loader = new StaticMethodLoader('loadMetadata');
        $metadata = new ClassMetadata(__NAMESPACE__.'\StaticLoaderEntity');

        $loader->loadClassMetadata($metadata);

        $this->assertEquals(StaticLoaderEntity::$invokedWith, $metadata);
    }

    public function testLoadClassMetadataDoesNotRepeatLoadWithParentClasses()
    {
        $loader = new StaticMethodLoader('loadMetadata');
        $metadata = new ClassMetadata(__NAMESPACE__.'\StaticLoaderDocument');
        $loader->loadClassMetadata($metadata);
        $this->assertCount(0, $metadata->getConstraints());

        $loader = new StaticMethodLoader('loadMetadata');
        $metadata = new ClassMetadata(__NAMESPACE__.'\BaseStaticLoaderDocument');
        $loader->loadClassMetadata($metadata);
        $this->assertCount(1, $metadata->getConstraints());
    }

    public function testLoadClassMetadataIgnoresInterfaces()
    {
        $loader = new StaticMethodLoader('loadMetadata');
        $metadata = new ClassMetadata(__NAMESPACE__.'\StaticLoaderInterface');

        $loader->loadClassMetadata($metadata);

        $this->assertCount(0, $metadata->getConstraints());
    }

    public function testLoadClassMetadataInAbstractClasses()
    {
        $loader = new StaticMethodLoader('loadMetadata');
        $metadata = new ClassMetadata(__NAMESPACE__.'\AbstractStaticLoader');

        $loader->loadClassMetadata($metadata);

        $this->assertCount(1, $metadata->getConstraints());
    }

    public function testLoadClassMetadataIgnoresAbstractMethods()
    {
        $loader = new StaticMethodLoader('loadMetadata');
        try {
            include __DIR__ . '/AbstractMethodStaticLoader.php';
            $this->fail('AbstractMethodStaticLoader should produce a strict standard error.');
        } catch (\Exception $e) {
        }

        $metadata = new ClassMetadata(__NAMESPACE__.'\AbstractMethodStaticLoader');
        $loader->loadClassMetadata($metadata);

        $this->assertCount(0, $metadata->getConstraints());
    }
}

interface StaticLoaderInterface
{
    public static function loadMetadata(ClassMetadata $metadata);
}

abstract class AbstractStaticLoader
{
    public static function loadMetadata(ClassMetadata $metadata)
    {
        $metadata->addConstraint(new ConstraintA());
    }
}

class StaticLoaderEntity
{
    public static $invokedWith = null;

    public static function loadMetadata(ClassMetadata $metadata)
    {
        self::$invokedWith = $metadata;
    }
}

class StaticLoaderDocument extends BaseStaticLoaderDocument
{
}

class BaseStaticLoaderDocument
{
    public static function loadMetadata(ClassMetadata $metadata)
    {
        $metadata->addConstraint(new ConstraintA());
    }
}
PK��Z���mXtest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/AnnotationLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Mapping\Loader;

use Doctrine\Common\Annotations\AnnotationReader;
use Symfony\Component\Validator\Constraints\All;
use Symfony\Component\Validator\Constraints\Callback;
use Symfony\Component\Validator\Constraints\Collection;
use Symfony\Component\Validator\Constraints\NotNull;
use Symfony\Component\Validator\Constraints\Range;
use Symfony\Component\Validator\Constraints\Choice;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Mapping\Loader\AnnotationLoader;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;

class AnnotationLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testLoadClassMetadataReturnsTrueIfSuccessful()
    {
        $reader = new AnnotationReader();
        $loader = new AnnotationLoader($reader);
        $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');

        $this->assertTrue($loader->loadClassMetadata($metadata));
    }

    public function testLoadClassMetadataReturnsFalseIfNotSuccessful()
    {
        $loader = new AnnotationLoader(new AnnotationReader());
        $metadata = new ClassMetadata('\stdClass');

        $this->assertFalse($loader->loadClassMetadata($metadata));
    }

    public function testLoadClassMetadata()
    {
        $loader = new AnnotationLoader(new AnnotationReader());
        $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');

        $loader->loadClassMetadata($metadata);

        $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');
        $expected->setGroupSequence(array('Foo', 'Entity'));
        $expected->addConstraint(new ConstraintA());
        $expected->addConstraint(new Callback(array('Symfony\Component\Validator\Tests\Fixtures\CallbackClass', 'callback')));
        $expected->addConstraint(new Callback('validateMe'));
        $expected->addConstraint(new Callback('validateMeStatic'));
        $expected->addPropertyConstraint('firstName', new NotNull());
        $expected->addPropertyConstraint('firstName', new Range(array('min' => 3)));
        $expected->addPropertyConstraint('firstName', new All(array(new NotNull(), new Range(array('min' => 3)))));
        $expected->addPropertyConstraint('firstName', new All(array('constraints' => array(new NotNull(), new Range(array('min' => 3))))));
        $expected->addPropertyConstraint('firstName', new Collection(array('fields' => array(
            'foo' => array(new NotNull(), new Range(array('min' => 3))),
            'bar' => new Range(array('min' => 5)),
        ))));
        $expected->addPropertyConstraint('firstName', new Choice(array(
            'message' => 'Must be one of %choices%',
            'choices' => array('A', 'B'),
        )));
        $expected->addGetterConstraint('lastName', new NotNull());

        // load reflection class so that the comparison passes
        $expected->getReflectionClass();

        $this->assertEquals($expected, $metadata);
    }

    /**
     * Test MetaData merge with parent annotation.
     */
    public function testLoadParentClassMetadata()
    {
        $loader = new AnnotationLoader(new AnnotationReader());

        // Load Parent MetaData
        $parent_metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\EntityParent');
        $loader->loadClassMetadata($parent_metadata);

        $expected_parent = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\EntityParent');
        $expected_parent->addPropertyConstraint('other', new NotNull());
        $expected_parent->getReflectionClass();

        $this->assertEquals($expected_parent, $parent_metadata);
    }
    /**
     * Test MetaData merge with parent annotation.
     */
    public function testLoadClassMetadataAndMerge()
    {
        $loader = new AnnotationLoader(new AnnotationReader());

        // Load Parent MetaData
        $parent_metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\EntityParent');
        $loader->loadClassMetadata($parent_metadata);

        $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');

        // Merge parent metaData.
        $metadata->mergeConstraints($parent_metadata);

        $loader->loadClassMetadata($metadata);

        $expected_parent = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\EntityParent');
        $expected_parent->addPropertyConstraint('other', new NotNull());
        $expected_parent->getReflectionClass();

        $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');
        $expected->mergeConstraints($expected_parent);

        $expected->setGroupSequence(array('Foo', 'Entity'));
        $expected->addConstraint(new ConstraintA());
        $expected->addConstraint(new Callback(array('Symfony\Component\Validator\Tests\Fixtures\CallbackClass', 'callback')));
        $expected->addConstraint(new Callback('validateMe'));
        $expected->addConstraint(new Callback('validateMeStatic'));
        $expected->addPropertyConstraint('firstName', new NotNull());
        $expected->addPropertyConstraint('firstName', new Range(array('min' => 3)));
        $expected->addPropertyConstraint('firstName', new All(array(new NotNull(), new Range(array('min' => 3)))));
        $expected->addPropertyConstraint('firstName', new All(array('constraints' => array(new NotNull(), new Range(array('min' => 3))))));
        $expected->addPropertyConstraint('firstName', new Collection(array('fields' => array(
            'foo' => array(new NotNull(), new Range(array('min' => 3))),
            'bar' => new Range(array('min' => 5)),
        ))));
        $expected->addPropertyConstraint('firstName', new Choice(array(
            'message' => 'Must be one of %choices%',
            'choices' => array('A', 'B'),
        )));
        $expected->addGetterConstraint('lastName', new NotNull());

        // load reflection class so that the comparison passes
        $expected->getReflectionClass();

        $this->assertEquals($expected, $metadata);
    }

    public function testLoadGroupSequenceProviderAnnotation()
    {
        $loader = new AnnotationLoader(new AnnotationReader());

        $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity');
        $loader->loadClassMetadata($metadata);

        $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity');
        $expected->setGroupSequenceProvider(true);
        $expected->getReflectionClass();

        $this->assertEquals($expected, $metadata);
    }
}
PK��Z��N��Vtest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Mapping\Loader;

use Symfony\Component\Validator\Constraints\All;
use Symfony\Component\Validator\Constraints\Callback;
use Symfony\Component\Validator\Constraints\Collection;
use Symfony\Component\Validator\Constraints\NotNull;
use Symfony\Component\Validator\Constraints\Range;
use Symfony\Component\Validator\Constraints\Choice;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Mapping\Loader\YamlFileLoader;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintB;

class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testLoadClassMetadataReturnsFalseIfEmpty()
    {
        $loader = new YamlFileLoader(__DIR__.'/empty-mapping.yml');
        $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');

        $this->assertFalse($loader->loadClassMetadata($metadata));
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testLoadClassMetadataThrowsExceptionIfNotAnArray()
    {
        $loader = new YamlFileLoader(__DIR__.'/nonvalid-mapping.yml');
        $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');
        $loader->loadClassMetadata($metadata);
    }

    public function testLoadClassMetadataReturnsTrueIfSuccessful()
    {
        $loader = new YamlFileLoader(__DIR__.'/constraint-mapping.yml');
        $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');

        $this->assertTrue($loader->loadClassMetadata($metadata));
    }

    public function testLoadClassMetadataReturnsFalseIfNotSuccessful()
    {
        $loader = new YamlFileLoader(__DIR__.'/constraint-mapping.yml');
        $metadata = new ClassMetadata('\stdClass');

        $this->assertFalse($loader->loadClassMetadata($metadata));
    }

    public function testLoadClassMetadata()
    {
        $loader = new YamlFileLoader(__DIR__.'/constraint-mapping.yml');
        $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');

        $loader->loadClassMetadata($metadata);

        $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');
        $expected->setGroupSequence(array('Foo', 'Entity'));
        $expected->addConstraint(new ConstraintA());
        $expected->addConstraint(new ConstraintB());
        $expected->addConstraint(new Callback('validateMe'));
        $expected->addConstraint(new Callback('validateMeStatic'));
        $expected->addConstraint(new Callback(array('Symfony\Component\Validator\Tests\Fixtures\CallbackClass', 'callback')));
        $expected->addPropertyConstraint('firstName', new NotNull());
        $expected->addPropertyConstraint('firstName', new Range(array('min' => 3)));
        $expected->addPropertyConstraint('firstName', new Choice(array('A', 'B')));
        $expected->addPropertyConstraint('firstName', new All(array(new NotNull(), new Range(array('min' => 3)))));
        $expected->addPropertyConstraint('firstName', new All(array('constraints' => array(new NotNull(), new Range(array('min' => 3))))));
        $expected->addPropertyConstraint('firstName', new Collection(array('fields' => array(
            'foo' => array(new NotNull(), new Range(array('min' => 3))),
            'bar' => array(new Range(array('min' => 5))),
        ))));
        $expected->addPropertyConstraint('firstName', new Choice(array(
            'message' => 'Must be one of %choices%',
            'choices' => array('A', 'B'),
        )));
        $expected->addGetterConstraint('lastName', new NotNull());

        $this->assertEquals($expected, $metadata);
    }

    public function testLoadGroupSequenceProvider()
    {
        $loader = new YamlFileLoader(__DIR__.'/constraint-mapping.yml');
        $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity');

        $loader->loadClassMetadata($metadata);

        $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity');
        $expected->setGroupSequenceProvider(true);

        $this->assertEquals($expected, $metadata);
    }
}
PK��ZN�;��Otest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/withdoctype.xmlnu�[���<?xml version="1.0"?>
<!DOCTYPE foo>
<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">
  <class name="Symfony\Component\Validator\Tests\Fixtures\Entity" />
</constraint-mapping>
PK��ZQtest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/empty-mapping.ymlnu�[���PK��Z�Qi���Utest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/XmlFileLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Mapping\Loader;

use Symfony\Component\Validator\Constraints\All;
use Symfony\Component\Validator\Constraints\Callback;
use Symfony\Component\Validator\Constraints\Collection;
use Symfony\Component\Validator\Constraints\NotNull;
use Symfony\Component\Validator\Constraints\Range;
use Symfony\Component\Validator\Constraints\Choice;
use Symfony\Component\Validator\Constraints\Regex;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Mapping\Loader\XmlFileLoader;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintB;

class XmlFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testLoadClassMetadataReturnsTrueIfSuccessful()
    {
        $loader = new XmlFileLoader(__DIR__.'/constraint-mapping.xml');
        $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');

        $this->assertTrue($loader->loadClassMetadata($metadata));
    }

    public function testLoadClassMetadataReturnsFalseIfNotSuccessful()
    {
        $loader = new XmlFileLoader(__DIR__.'/constraint-mapping.xml');
        $metadata = new ClassMetadata('\stdClass');

        $this->assertFalse($loader->loadClassMetadata($metadata));
    }

    public function testLoadClassMetadata()
    {
        $loader = new XmlFileLoader(__DIR__.'/constraint-mapping.xml');
        $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');

        $loader->loadClassMetadata($metadata);

        $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');
        $expected->setGroupSequence(array('Foo', 'Entity'));
        $expected->addConstraint(new ConstraintA());
        $expected->addConstraint(new ConstraintB());
        $expected->addConstraint(new Callback('validateMe'));
        $expected->addConstraint(new Callback('validateMeStatic'));
        $expected->addConstraint(new Callback(array('Symfony\Component\Validator\Tests\Fixtures\CallbackClass', 'callback')));
        $expected->addPropertyConstraint('firstName', new NotNull());
        $expected->addPropertyConstraint('firstName', new Range(array('min' => 3)));
        $expected->addPropertyConstraint('firstName', new Choice(array('A', 'B')));
        $expected->addPropertyConstraint('firstName', new All(array(new NotNull(), new Range(array('min' => 3)))));
        $expected->addPropertyConstraint('firstName', new All(array('constraints' => array(new NotNull(), new Range(array('min' => 3))))));
        $expected->addPropertyConstraint('firstName', new Collection(array('fields' => array(
            'foo' => array(new NotNull(), new Range(array('min' => 3))),
            'bar' => array(new Range(array('min' => 5))),
        ))));
        $expected->addPropertyConstraint('firstName', new Choice(array(
            'message' => 'Must be one of %choices%',
            'choices' => array('A', 'B'),
        )));
        $expected->addGetterConstraint('lastName', new NotNull());

        $this->assertEquals($expected, $metadata);
    }

    public function testLoadClassMetadataWithNonStrings()
    {
        $loader = new XmlFileLoader(__DIR__.'/constraint-mapping-non-strings.xml');
        $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');

        $loader->loadClassMetadata($metadata);

        $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');
        $expected->addPropertyConstraint('firstName', new Regex(array('pattern' => '/^1/', 'match' => false)));

        $properties = $metadata->getPropertyMetadata('firstName');
        $constraints = $properties[0]->getConstraints();

        $this->assertFalse($constraints[0]->match);
    }

    public function testLoadGroupSequenceProvider()
    {
        $loader = new XmlFileLoader(__DIR__.'/constraint-mapping.xml');
        $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity');

        $loader->loadClassMetadata($metadata);

        $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity');
        $expected->setGroupSequenceProvider(true);

        $this->assertEquals($expected, $metadata);
    }

    /**
     * @expectedException        \Symfony\Component\Validator\Exception\MappingException
     * @expectedExceptionMessage Document types are not allowed.
     */
    public function testDocTypeIsNotAllowed()
    {
        $loader = new XmlFileLoader(__DIR__.'/withdoctype.xml');
        $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');

        $loader->loadClassMetadata($metadata);
    }
}
PK��Z�e2~Ttest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/nonvalid-mapping.ymlnu�[���foo
PK��Z����^test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/AbstractMethodStaticLoader.phpnu�[���<?php

namespace Symfony\Component\Validator\Tests\Mapping\Loader;

use Symfony\Component\Validator\Mapping\ClassMetadata;

abstract class AbstractMethodStaticLoader
{
    abstract public static function loadMetadata(ClassMetadata $metadata);
}
PK��ZF���<<Stest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/FilesLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Mapping\Loader;

use Symfony\Component\Validator\Mapping\Loader\LoaderInterface;
use Symfony\Component\Validator\Mapping\ClassMetadata;

class FilesLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testCallsGetFileLoaderInstanceForeachPath()
    {
        $loader = $this->getFilesLoader($this->getFileLoader());
        $this->assertEquals(4, $loader->getTimesCalled());
    }

    public function testCallsActualFileLoaderForMetadata()
    {
        $fileLoader = $this->getFileLoader();
        $fileLoader->expects($this->exactly(4))
            ->method('loadClassMetadata');
        $loader = $this->getFilesLoader($fileLoader);
        $loader->loadClassMetadata(new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'));
    }

    public function getFilesLoader(LoaderInterface $loader)
    {
        return $this->getMockForAbstractClass('Symfony\Component\Validator\Tests\Fixtures\FilesLoader', array(array(
            __DIR__.'/constraint-mapping.xml',
            __DIR__.'/constraint-mapping.yaml',
            __DIR__.'/constraint-mapping.test',
            __DIR__.'/constraint-mapping.txt',
        ), $loader));
    }

    public function getFileLoader()
    {
        return $this->getMock('Symfony\Component\Validator\Mapping\Loader\LoaderInterface');
    }
}
PK��Z{�d���Qtest/Validator/Symfony/Component/Validator/Tests/Mapping/PropertyMetadataTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Mapping;

use Symfony\Component\Validator\Mapping\PropertyMetadata;
use Symfony\Component\Validator\Tests\Fixtures\Entity;

class PropertyMetadataTest extends \PHPUnit_Framework_TestCase
{
    const CLASSNAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity';
    const PARENTCLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityParent';

    public function testInvalidPropertyName()
    {
        $this->setExpectedException('Symfony\Component\Validator\Exception\ValidatorException');

        new PropertyMetadata(self::CLASSNAME, 'foobar');
    }

    public function testGetPropertyValueFromPrivateProperty()
    {
        $entity = new Entity('foobar');
        $metadata = new PropertyMetadata(self::CLASSNAME, 'internal');

        $this->assertEquals('foobar', $metadata->getPropertyValue($entity));
    }

    public function testGetPropertyValueFromOverriddenPrivateProperty()
    {
        $entity = new Entity('foobar');
        $metadata = new PropertyMetadata(self::PARENTCLASS, 'data');

        $this->assertTrue($metadata->isPublic($entity));
        $this->assertEquals('Overridden data', $metadata->getPropertyValue($entity));
    }
}
PK��Z��~6�F�FJtest/Validator/Symfony/Component/Validator/Tests/ValidationVisitorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests;

use Symfony\Component\Validator\Tests\Fixtures\FakeMetadataFactory;
use Symfony\Component\Validator\Constraints\Valid;
use Symfony\Component\Validator\Tests\Fixtures\Reference;
use Symfony\Component\Validator\DefaultTranslator;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;
use Symfony\Component\Validator\Tests\Fixtures\FailingConstraint;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintAValidator;
use Symfony\Component\Validator\Tests\Fixtures\Entity;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\ConstraintValidatorFactory;
use Symfony\Component\Validator\ValidationVisitor;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ValidationVisitorTest extends \PHPUnit_Framework_TestCase
{
    const CLASS_NAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity';

    /**
     * @var ValidationVisitor
     */
    private $visitor;

    /**
     * @var FakeMetadataFactory
     */
    private $metadataFactory;

    /**
     * @var ClassMetadata
     */
    private $metadata;

    protected function setUp()
    {
        $this->metadataFactory = new FakeMetadataFactory();
        $this->visitor = new ValidationVisitor('Root', $this->metadataFactory, new ConstraintValidatorFactory(), new DefaultTranslator());
        $this->metadata = new ClassMetadata(self::CLASS_NAME);
        $this->metadataFactory->addMetadata($this->metadata);
    }

    protected function tearDown()
    {
        $this->metadataFactory = null;
        $this->visitor = null;
        $this->metadata = null;
    }

    public function testValidatePassesCorrectClassAndProperty()
    {
        $this->metadata->addConstraint(new ConstraintA());

        $entity = new Entity();
        $this->visitor->validate($entity, 'Default', '');

        $context = ConstraintAValidator::$passedContext;

        $this->assertEquals('Symfony\Component\Validator\Tests\Fixtures\Entity', $context->getClassName());
        $this->assertNull($context->getPropertyName());
    }

    public function testValidateConstraints()
    {
        $this->metadata->addConstraint(new ConstraintA());

        $this->visitor->validate(new Entity(), 'Default', '');

        $this->assertCount(1, $this->visitor->getViolations());
    }

    public function testValidateTwiceValidatesConstraintsOnce()
    {
        $this->metadata->addConstraint(new ConstraintA());

        $entity = new Entity();

        $this->visitor->validate($entity, 'Default', '');
        $this->visitor->validate($entity, 'Default', '');

        $this->assertCount(1, $this->visitor->getViolations());
    }

    public function testValidateDifferentObjectsValidatesTwice()
    {
        $this->metadata->addConstraint(new ConstraintA());

        $this->visitor->validate(new Entity(), 'Default', '');
        $this->visitor->validate(new Entity(), 'Default', '');

        $this->assertCount(2, $this->visitor->getViolations());
    }

    public function testValidateTwiceInDifferentGroupsValidatesTwice()
    {
        $this->metadata->addConstraint(new ConstraintA());
        $this->metadata->addConstraint(new ConstraintA(array('groups' => 'Custom')));

        $entity = new Entity();

        $this->visitor->validate($entity, 'Default', '');
        $this->visitor->validate($entity, 'Custom', '');

        $this->assertCount(2, $this->visitor->getViolations());
    }

    public function testValidatePropertyConstraints()
    {
        $this->metadata->addPropertyConstraint('firstName', new ConstraintA());

        $this->visitor->validate(new Entity(), 'Default', '');

        $this->assertCount(1, $this->visitor->getViolations());
    }

    public function testValidateGetterConstraints()
    {
        $this->metadata->addGetterConstraint('lastName', new ConstraintA());

        $this->visitor->validate(new Entity(), 'Default', '');

        $this->assertCount(1, $this->visitor->getViolations());
    }

    public function testValidateInDefaultGroupTraversesGroupSequence()
    {
        $entity = new Entity();

        $this->metadata->addPropertyConstraint('firstName', new FailingConstraint(array(
            'groups' => 'First',
        )));
        $this->metadata->addGetterConstraint('lastName', new FailingConstraint(array(
            'groups' => 'Default',
        )));
        $this->metadata->setGroupSequence(array('First', $this->metadata->getDefaultGroup()));

        $this->visitor->validate($entity, 'Default', '');

        // After validation of group "First" failed, no more group was
        // validated
        $violations = new ConstraintViolationList(array(
            new ConstraintViolation(
                'Failed',
                'Failed',
                array(),
                'Root',
                'firstName',
                ''
            ),
        ));

        $this->assertEquals($violations, $this->visitor->getViolations());
    }

    public function testValidateInGroupSequencePropagatesDefaultGroup()
    {
        $entity = new Entity();
        $entity->reference = new Reference();

        $this->metadata->addPropertyConstraint('reference', new Valid());
        $this->metadata->setGroupSequence(array($this->metadata->getDefaultGroup()));

        $referenceMetadata = new ClassMetadata(get_class($entity->reference));
        $referenceMetadata->addConstraint(new FailingConstraint(array(
                // this constraint is only evaluated if group "Default" is
                // propagated to the reference
                'groups' => 'Default',
            )));
        $this->metadataFactory->addMetadata($referenceMetadata);

        $this->visitor->validate($entity, 'Default', '');

        // The validation of the reference's FailingConstraint in group
        // "Default" was launched
        $violations = new ConstraintViolationList(array(
            new ConstraintViolation(
                'Failed',
                'Failed',
                array(),
                'Root',
                'reference',
                $entity->reference
            ),
        ));

        $this->assertEquals($violations, $this->visitor->getViolations());
    }

    public function testValidateInOtherGroupTraversesNoGroupSequence()
    {
        $entity = new Entity();

        $this->metadata->addPropertyConstraint('firstName', new FailingConstraint(array(
            'groups' => 'First',
        )));
        $this->metadata->addGetterConstraint('lastName', new FailingConstraint(array(
            'groups' => $this->metadata->getDefaultGroup(),
        )));
        $this->metadata->setGroupSequence(array('First', $this->metadata->getDefaultGroup()));

        $this->visitor->validate($entity, $this->metadata->getDefaultGroup(), '');

        // Only group "Second" was validated
        $violations = new ConstraintViolationList(array(
            new ConstraintViolation(
                'Failed',
                'Failed',
                array(),
                'Root',
                'lastName',
                ''
            ),
        ));

        $this->assertEquals($violations, $this->visitor->getViolations());
    }

    public function testValidateCascadedPropertyValidatesReferences()
    {
        $entity = new Entity();
        $entity->reference = new Entity();

        // add a constraint for the entity that always fails
        $this->metadata->addConstraint(new FailingConstraint());

        // validate entity when validating the property "reference"
        $this->metadata->addPropertyConstraint('reference', new Valid());

        // invoke validation on an object
        $this->visitor->validate($entity, 'Default', '');

        $violations = new ConstraintViolationList(array(
            // generated by the root object
            new ConstraintViolation(
                'Failed',
                'Failed',
                array(),
                'Root',
                '',
                $entity
            ),
            // generated by the reference
            new ConstraintViolation(
                'Failed',
                'Failed',
                array(),
                'Root',
                'reference',
                $entity->reference
            ),
        ));

        $this->assertEquals($violations, $this->visitor->getViolations());
    }

    public function testValidateCascadedPropertyValidatesArraysByDefault()
    {
        $entity = new Entity();
        $entity->reference = array('key' => new Entity());

        // add a constraint for the entity that always fails
        $this->metadata->addConstraint(new FailingConstraint());

        // validate array when validating the property "reference"
        $this->metadata->addPropertyConstraint('reference', new Valid());

        $this->visitor->validate($entity, 'Default', '');

        $violations = new ConstraintViolationList(array(
            // generated by the root object
            new ConstraintViolation(
                'Failed',
                'Failed',
                array(),
                'Root',
                '',
                $entity
            ),
            // generated by the reference
            new ConstraintViolation(
                'Failed',
                'Failed',
                array(),
                'Root',
                'reference[key]',
                $entity->reference['key']
            ),
        ));

        $this->assertEquals($violations, $this->visitor->getViolations());
    }

    public function testValidateCascadedPropertyValidatesTraversableByDefault()
    {
        $entity = new Entity();
        $entity->reference = new \ArrayIterator(array('key' => new Entity()));

        // add a constraint for the entity that always fails
        $this->metadata->addConstraint(new FailingConstraint());

        // validate array when validating the property "reference"
        $this->metadata->addPropertyConstraint('reference', new Valid());

        $this->visitor->validate($entity, 'Default', '');

        $violations = new ConstraintViolationList(array(
            // generated by the root object
            new ConstraintViolation(
                'Failed',
                'Failed',
                array(),
                'Root',
                '',
                $entity
            ),
            // generated by the reference
            new ConstraintViolation(
                'Failed',
                'Failed',
                array(),
                'Root',
                'reference[key]',
                $entity->reference['key']
            ),
        ));

        $this->assertEquals($violations, $this->visitor->getViolations());
    }

    public function testValidateCascadedPropertyDoesNotValidateTraversableIfDisabled()
    {
        $entity = new Entity();
        $entity->reference = new \ArrayIterator(array('key' => new Entity()));

        $this->metadataFactory->addMetadata(new ClassMetadata('ArrayIterator'));

        // add a constraint for the entity that always fails
        $this->metadata->addConstraint(new FailingConstraint());

        // validate array when validating the property "reference"
        $this->metadata->addPropertyConstraint('reference', new Valid(array(
            'traverse' => false,
        )));

        $this->visitor->validate($entity, 'Default', '');

        $violations = new ConstraintViolationList(array(
            // generated by the root object
            new ConstraintViolation(
                'Failed',
                'Failed',
                array(),
                'Root',
                '',
                $entity
            ),
            // nothing generated by the reference!
        ));

        $this->assertEquals($violations, $this->visitor->getViolations());
    }

    public function testMetadataMayNotExistIfTraversalIsEnabled()
    {
        $entity = new Entity();
        $entity->reference = new \ArrayIterator();

        $this->metadata->addPropertyConstraint('reference', new Valid(array(
            'traverse' => true,
        )));

        $this->visitor->validate($entity, 'Default', '');
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\NoSuchMetadataException
     */
    public function testMetadataMustExistIfTraversalIsDisabled()
    {
        $entity = new Entity();
        $entity->reference = new \ArrayIterator();

        $this->metadata->addPropertyConstraint('reference', new Valid(array(
            'traverse' => false,
        )));

        $this->visitor->validate($entity, 'Default', '');
    }

    public function testValidateCascadedPropertyDoesNotRecurseByDefault()
    {
        $entity = new Entity();
        $entity->reference = new \ArrayIterator(array(
            // The inner iterator should not be traversed by default
            'key' => new \ArrayIterator(array(
                'nested' => new Entity(),
            )),
        ));

        $this->metadataFactory->addMetadata(new ClassMetadata('ArrayIterator'));

        // add a constraint for the entity that always fails
        $this->metadata->addConstraint(new FailingConstraint());

        // validate iterator when validating the property "reference"
        $this->metadata->addPropertyConstraint('reference', new Valid());

        $this->visitor->validate($entity, 'Default', '');

        $violations = new ConstraintViolationList(array(
            // generated by the root object
            new ConstraintViolation(
                'Failed',
                'Failed',
                array(),
                'Root',
                '',
                $entity
            ),
            // nothing generated by the reference!
        ));

        $this->assertEquals($violations, $this->visitor->getViolations());
    }

    // https://github.com/symfony/symfony/issues/6246
    public function testValidateCascadedPropertyRecursesArraysByDefault()
    {
        $entity = new Entity();
        $entity->reference = array(
            'key' => array(
                'nested' => new Entity(),
            ),
        );

        // add a constraint for the entity that always fails
        $this->metadata->addConstraint(new FailingConstraint());

        // validate iterator when validating the property "reference"
        $this->metadata->addPropertyConstraint('reference', new Valid());

        $this->visitor->validate($entity, 'Default', '');

        $violations = new ConstraintViolationList(array(
            // generated by the root object
            new ConstraintViolation(
                'Failed',
                'Failed',
                array(),
                'Root',
                '',
                $entity
            ),
            // nothing generated by the reference!
            new ConstraintViolation(
                'Failed',
                'Failed',
                array(),
                'Root',
                'reference[key][nested]',
                $entity->reference['key']['nested']
            ),
        ));

        $this->assertEquals($violations, $this->visitor->getViolations());
    }

    public function testValidateCascadedPropertyRecursesIfDeepIsSet()
    {
        $entity = new Entity();
        $entity->reference = new \ArrayIterator(array(
            // The inner iterator should now be traversed
            'key' => new \ArrayIterator(array(
                'nested' => new Entity(),
            )),
        ));

        // add a constraint for the entity that always fails
        $this->metadata->addConstraint(new FailingConstraint());

        // validate iterator when validating the property "reference"
        $this->metadata->addPropertyConstraint('reference', new Valid(array(
            'deep' => true,
        )));

        $this->visitor->validate($entity, 'Default', '');

        $violations = new ConstraintViolationList(array(
            // generated by the root object
            new ConstraintViolation(
                'Failed',
                'Failed',
                array(),
                'Root',
                '',
                $entity
            ),
            // nothing generated by the reference!
            new ConstraintViolation(
                'Failed',
                'Failed',
                array(),
                'Root',
                'reference[key][nested]',
                $entity->reference['key']['nested']
            ),
        ));

        $this->assertEquals($violations, $this->visitor->getViolations());
    }

    public function testValidateCascadedPropertyDoesNotValidateNestedScalarValues()
    {
        $entity = new Entity();
        $entity->reference = array('scalar', 'values');

        // validate array when validating the property "reference"
        $this->metadata->addPropertyConstraint('reference', new Valid());

        $this->visitor->validate($entity, 'Default', '');

        $this->assertCount(0, $this->visitor->getViolations());
    }

    public function testValidateCascadedPropertyDoesNotValidateNullValues()
    {
        $entity = new Entity();
        $entity->reference = null;

        $this->metadata->addPropertyConstraint('reference', new Valid());

        $this->visitor->validate($entity, 'Default', '');

        $this->assertCount(0, $this->visitor->getViolations());
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\NoSuchMetadataException
     */
    public function testValidateCascadedPropertyRequiresObjectOrArray()
    {
        $entity = new Entity();
        $entity->reference = 'no object';

        $this->metadata->addPropertyConstraint('reference', new Valid());

        $this->visitor->validate($entity, 'Default', '');
    }
}
PK��ZK��y'$'$Btest/Validator/Symfony/Component/Validator/Tests/ValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests;

use Symfony\Component\Validator\Tests\Fixtures\Entity;
use Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity;
use Symfony\Component\Validator\Tests\Fixtures\FakeMetadataFactory;
use Symfony\Component\Validator\Tests\Fixtures\FailingConstraint;
use Symfony\Component\Validator\Validator;
use Symfony\Component\Validator\DefaultTranslator;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;
use Symfony\Component\Validator\ConstraintValidatorFactory;
use Symfony\Component\Validator\Constraints\Valid;
use Symfony\Component\Validator\Mapping\ClassMetadata;

class ValidatorTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var FakeMetadataFactory
     */
    private $metadataFactory;

    /**
     * @var Validator
     */
    private $validator;

    protected function setUp()
    {
        $this->metadataFactory = new FakeMetadataFactory();
        $this->validator = new Validator($this->metadataFactory, new ConstraintValidatorFactory(), new DefaultTranslator());
    }

    protected function tearDown()
    {
        $this->metadataFactory = null;
        $this->validator = null;
    }

    public function testValidateDefaultGroup()
    {
        $entity = new Entity();
        $metadata = new ClassMetadata(get_class($entity));
        $metadata->addPropertyConstraint('firstName', new FailingConstraint());
        $metadata->addPropertyConstraint('lastName', new FailingConstraint(array(
            'groups' => 'Custom',
        )));
        $this->metadataFactory->addMetadata($metadata);

        // Only the constraint of group "Default" failed
        $violations = new ConstraintViolationList();
        $violations->add(new ConstraintViolation(
            'Failed',
            'Failed',
            array(),
            $entity,
            'firstName',
            ''
        ));

        $this->assertEquals($violations, $this->validator->validate($entity));
    }

    public function testValidateOneGroup()
    {
        $entity = new Entity();
        $metadata = new ClassMetadata(get_class($entity));
        $metadata->addPropertyConstraint('firstName', new FailingConstraint());
        $metadata->addPropertyConstraint('lastName', new FailingConstraint(array(
            'groups' => 'Custom',
        )));
        $this->metadataFactory->addMetadata($metadata);

        // Only the constraint of group "Custom" failed
        $violations = new ConstraintViolationList();
        $violations->add(new ConstraintViolation(
            'Failed',
            'Failed',
            array(),
            $entity,
            'lastName',
            ''
        ));

        $this->assertEquals($violations, $this->validator->validate($entity, 'Custom'));
    }

    public function testValidateMultipleGroups()
    {
        $entity = new Entity();
        $metadata = new ClassMetadata(get_class($entity));
        $metadata->addPropertyConstraint('firstName', new FailingConstraint(array(
            'groups' => 'First',
        )));
        $metadata->addPropertyConstraint('lastName', new FailingConstraint(array(
            'groups' => 'Second',
        )));
        $this->metadataFactory->addMetadata($metadata);

        // The constraints of both groups failed
        $violations = new ConstraintViolationList();
        $violations->add(new ConstraintViolation(
            'Failed',
            'Failed',
            array(),
            $entity,
            'firstName',
            ''
        ));
        $violations->add(new ConstraintViolation(
            'Failed',
            'Failed',
            array(),
            $entity,
            'lastName',
            ''
        ));

        $result = $this->validator->validate($entity, array('First', 'Second'));

        $this->assertEquals($violations, $result);
    }

    public function testValidateGroupSequenceProvider()
    {
        $entity = new GroupSequenceProviderEntity();
        $metadata = new ClassMetadata(get_class($entity));
        $metadata->addPropertyConstraint('firstName', new FailingConstraint(array(
            'groups' => 'First',
        )));
        $metadata->addPropertyConstraint('lastName', new FailingConstraint(array(
            'groups' => 'Second',
        )));
        $metadata->setGroupSequenceProvider(true);
        $this->metadataFactory->addMetadata($metadata);

        $violations = new ConstraintViolationList();
        $violations->add(new ConstraintViolation(
            'Failed',
            'Failed',
            array(),
            $entity,
            'firstName',
            ''
        ));

        $entity->setGroups(array('First'));
        $result = $this->validator->validate($entity);
        $this->assertEquals($violations, $result);

        $violations = new ConstraintViolationList();
        $violations->add(new ConstraintViolation(
            'Failed',
            'Failed',
            array(),
            $entity,
            'lastName',
            ''
        ));

        $entity->setGroups(array('Second'));
        $result = $this->validator->validate($entity);
        $this->assertEquals($violations, $result);

        $entity->setGroups(array());
        $result = $this->validator->validate($entity);
        $this->assertEquals(new ConstraintViolationList(), $result);
    }

    public function testValidateProperty()
    {
        $entity = new Entity();
        $metadata = new ClassMetadata(get_class($entity));
        $metadata->addPropertyConstraint('firstName', new FailingConstraint());
        $this->metadataFactory->addMetadata($metadata);

        $result = $this->validator->validateProperty($entity, 'firstName');

        $this->assertCount(1, $result);

        $result = $this->validator->validateProperty($entity, 'lastName');

        $this->assertCount(0, $result);
    }

    public function testValidatePropertyValue()
    {
        $entity = new Entity();
        $metadata = new ClassMetadata(get_class($entity));
        $metadata->addPropertyConstraint('firstName', new FailingConstraint());
        $this->metadataFactory->addMetadata($metadata);

        $result = $this->validator->validatePropertyValue(get_class($entity), 'firstName', 'Bernhard');

        $this->assertCount(1, $result);
    }

    public function testValidateValue()
    {
        $violations = new ConstraintViolationList();
        $violations->add(new ConstraintViolation(
            'Failed',
            'Failed',
            array(),
            'Bernhard',
            '',
            'Bernhard'
        ));

        $this->assertEquals($violations, $this->validator->validateValue('Bernhard', new FailingConstraint()));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ValidatorException
     */
    public function testValidateValueRejectsValid()
    {
        $entity = new Entity();
        $metadata = new ClassMetadata(get_class($entity));
        $this->metadataFactory->addMetadata($metadata);

        $this->validator->validateValue($entity, new Valid());
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ValidatorException
     */
    public function testValidatePropertyFailsIfPropertiesNotSupported()
    {
        // $metadata does not implement PropertyMetadataContainerInterface
        $metadata = $this->getMock('Symfony\Component\Validator\MetadataInterface');
        $this->metadataFactory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface');
        $this->metadataFactory->expects($this->any())
            ->method('getMetadataFor')
            ->with('VALUE')
            ->will($this->returnValue($metadata));
        $this->validator = new Validator($this->metadataFactory, new ConstraintValidatorFactory(), new DefaultTranslator());

        $this->validator->validateProperty('VALUE', 'someProperty');
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ValidatorException
     */
    public function testValidatePropertyValueFailsIfPropertiesNotSupported()
    {
        // $metadata does not implement PropertyMetadataContainerInterface
        $metadata = $this->getMock('Symfony\Component\Validator\MetadataInterface');
        $this->metadataFactory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface');
        $this->metadataFactory->expects($this->any())
            ->method('getMetadataFor')
            ->with('VALUE')
            ->will($this->returnValue($metadata));
        $this->validator = new Validator($this->metadataFactory, new ConstraintValidatorFactory(), new DefaultTranslator());

        $this->validator->validatePropertyValue('VALUE', 'someProperty', 'propertyValue');
    }

    public function testGetMetadataFactory()
    {
        $this->assertInstanceOf(
            'Symfony\Component\Validator\MetadataFactoryInterface',
            $this->validator->getMetadataFactory()
        );
    }
}
PK��Z�P�6�)�)Itest/Validator/Symfony/Component/Validator/Tests/ExecutionContextTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests;

use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;
use Symfony\Component\Validator\ExecutionContext;
use Symfony\Component\Validator\Constraints\Collection;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
use Symfony\Component\Validator\ValidationVisitor;
use Symfony\Component\Validator\ConstraintValidatorFactory;

class ExecutionContextTest extends \PHPUnit_Framework_TestCase
{
    const TRANS_DOMAIN = 'trans_domain';

    private $visitor;
    private $violations;
    private $metadata;
    private $metadataFactory;
    private $globalContext;
    private $translator;

    /**
     * @var ExecutionContext
     */
    private $context;

    protected function setUp()
    {
        $this->visitor = $this->getMockBuilder('Symfony\Component\Validator\ValidationVisitor')
            ->disableOriginalConstructor()
            ->getMock();
        $this->violations = new ConstraintViolationList();
        $this->metadata = $this->getMock('Symfony\Component\Validator\MetadataInterface');
        $this->metadataFactory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface');
        $this->globalContext = $this->getMock('Symfony\Component\Validator\GlobalExecutionContextInterface');
        $this->globalContext->expects($this->any())
            ->method('getRoot')
            ->will($this->returnValue('Root'));
        $this->globalContext->expects($this->any())
            ->method('getViolations')
            ->will($this->returnValue($this->violations));
        $this->globalContext->expects($this->any())
            ->method('getVisitor')
            ->will($this->returnValue($this->visitor));
        $this->globalContext->expects($this->any())
            ->method('getMetadataFactory')
            ->will($this->returnValue($this->metadataFactory));
        $this->translator = $this->getMock('Symfony\Component\Translation\TranslatorInterface');
        $this->context = new ExecutionContext($this->globalContext, $this->translator, self::TRANS_DOMAIN, $this->metadata, 'currentValue', 'Group', 'foo.bar');
    }

    protected function tearDown()
    {
        $this->globalContext = null;
        $this->context = null;
    }

    public function testInit()
    {
        $this->assertCount(0, $this->context->getViolations());
        $this->assertSame('Root', $this->context->getRoot());
        $this->assertSame('foo.bar', $this->context->getPropertyPath());
        $this->assertSame('Group', $this->context->getGroup());
    }

    public function testClone()
    {
        $clone = clone $this->context;

        // Cloning the context keeps the reference to the original violation
        // list. This way we can efficiently duplicate context instances during
        // the validation run and only modify the properties that need to be
        // changed.
        $this->assertSame($this->context->getViolations(), $clone->getViolations());
    }

    public function testAddViolation()
    {
        $this->translator->expects($this->once())
            ->method('trans')
            ->with('Error', array('foo' => 'bar'))
            ->will($this->returnValue('Translated error'));

        $this->context->addViolation('Error', array('foo' => 'bar'), 'invalid');

        $this->assertEquals(new ConstraintViolationList(array(
            new ConstraintViolation(
                'Translated error',
                'Error',
                array('foo' => 'bar'),
                'Root',
                'foo.bar',
                'invalid'
            ),
        )), $this->context->getViolations());
    }

    public function testAddViolationUsesPreconfiguredValueIfNotPassed()
    {
        $this->translator->expects($this->once())
            ->method('trans')
            ->with('Error', array())
            ->will($this->returnValue('Translated error'));

        $this->context->addViolation('Error');

        $this->assertEquals(new ConstraintViolationList(array(
            new ConstraintViolation(
                'Translated error',
                'Error',
                array(),
                'Root',
                'foo.bar',
                'currentValue'
            ),
        )), $this->context->getViolations());
    }

    public function testAddViolationUsesPassedNullValue()
    {
        $this->translator->expects($this->once())
            ->method('trans')
            ->with('Error', array('foo1' => 'bar1'))
            ->will($this->returnValue('Translated error'));
        $this->translator->expects($this->once())
            ->method('transChoice')
            ->with('Choice error', 1, array('foo2' => 'bar2'))
            ->will($this->returnValue('Translated choice error'));

        // passed null value should override preconfigured value "invalid"
        $this->context->addViolation('Error', array('foo1' => 'bar1'), null);
        $this->context->addViolation('Choice error', array('foo2' => 'bar2'), null, 1);

        $this->assertEquals(new ConstraintViolationList(array(
            new ConstraintViolation(
                'Translated error',
                'Error',
                array('foo1' => 'bar1'),
                'Root',
                'foo.bar',
                null
            ),
            new ConstraintViolation(
                'Translated choice error',
                'Choice error',
                array('foo2' => 'bar2'),
                'Root',
                'foo.bar',
                null,
                1
            ),
        )), $this->context->getViolations());
    }

    public function testAddViolationAt()
    {
        $this->translator->expects($this->once())
            ->method('trans')
            ->with('Error', array('foo' => 'bar'))
            ->will($this->returnValue('Translated error'));

        // override preconfigured property path
        $this->context->addViolationAt('bam.baz', 'Error', array('foo' => 'bar'), 'invalid');

        $this->assertEquals(new ConstraintViolationList(array(
            new ConstraintViolation(
                'Translated error',
                'Error',
                array('foo' => 'bar'),
                'Root',
                'foo.bar.bam.baz',
                'invalid'
            ),
        )), $this->context->getViolations());
    }

    public function testAddViolationAtUsesPreconfiguredValueIfNotPassed()
    {
        $this->translator->expects($this->once())
            ->method('trans')
            ->with('Error', array())
            ->will($this->returnValue('Translated error'));

        $this->context->addViolationAt('bam.baz', 'Error');

        $this->assertEquals(new ConstraintViolationList(array(
            new ConstraintViolation(
                'Translated error',
                'Error',
                array(),
                'Root',
                'foo.bar.bam.baz',
                'currentValue'
            ),
        )), $this->context->getViolations());
    }

    public function testAddViolationAtUsesPassedNullValue()
    {
        $this->translator->expects($this->once())
            ->method('trans')
            ->with('Error', array('foo' => 'bar'))
            ->will($this->returnValue('Translated error'));
        $this->translator->expects($this->once())
            ->method('transChoice')
            ->with('Choice error', 2, array('foo' => 'bar'))
            ->will($this->returnValue('Translated choice error'));

        // passed null value should override preconfigured value "invalid"
        $this->context->addViolationAt('bam.baz', 'Error', array('foo' => 'bar'), null);
        $this->context->addViolationAt('bam.baz', 'Choice error', array('foo' => 'bar'), null, 2);

        $this->assertEquals(new ConstraintViolationList(array(
            new ConstraintViolation(
                'Translated error',
                'Error',
                array('foo' => 'bar'),
                'Root',
                'foo.bar.bam.baz',
                null
            ),
            new ConstraintViolation(
                'Translated choice error',
                'Choice error',
                array('foo' => 'bar'),
                'Root',
                'foo.bar.bam.baz',
                null,
                2
            ),
        )), $this->context->getViolations());
    }

    public function testAddViolationPluralTranslationError()
    {
        $this->translator->expects($this->once())
            ->method('transChoice')
            ->with('foo')
            ->will($this->throwException(new \InvalidArgumentException()));
        $this->translator->expects($this->once())
            ->method('trans')
            ->with('foo');

        $this->context->addViolation('foo', array(), null, 2);
    }

    public function testGetPropertyPath()
    {
        $this->assertEquals('foo.bar', $this->context->getPropertyPath());
    }

    public function testGetPropertyPathWithIndexPath()
    {
        $this->assertEquals('foo.bar[bam]', $this->context->getPropertyPath('[bam]'));
    }

    public function testGetPropertyPathWithEmptyPath()
    {
        $this->assertEquals('foo.bar', $this->context->getPropertyPath(''));
    }

    public function testGetPropertyPathWithEmptyCurrentPropertyPath()
    {
        $this->context = new ExecutionContext($this->globalContext, $this->translator, self::TRANS_DOMAIN, $this->metadata, 'currentValue', 'Group', '');

        $this->assertEquals('bam.baz', $this->context->getPropertyPath('bam.baz'));
    }

    public function testGetPropertyPathWithNestedCollectionsMixed()
    {
        $constraints = new Collection(array(
            'foo' => new Collection(array(
                'foo' => new ConstraintA(),
                'bar' => new ConstraintA(),
             )),
            'name' => new ConstraintA()
        ));

        $visitor = new ValidationVisitor('Root', $this->metadataFactory, new ConstraintValidatorFactory(), $this->translator);
        $context = new ExecutionContext($visitor, $this->translator, self::TRANS_DOMAIN);
        $context->validateValue(array('foo' => array('foo' => 'VALID')), $constraints);
        $violations = $context->getViolations();

        $this->assertEquals('[name]', $violations[1]->getPropertyPath());
    }
}

class ExecutionContextTest_TestClass
{
    public $myProperty;
}
PK��Z����Qtest/Validator/Symfony/Component/Validator/Tests/Constraints/AllValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\ExecutionContext;
use Symfony\Component\Validator\Constraints\Range;
use Symfony\Component\Validator\Constraints\NotNull;
use Symfony\Component\Validator\Constraints\All;
use Symfony\Component\Validator\Constraints\AllValidator;

class AllValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new AllValidator();
        $this->validator->initialize($this->context);

        $this->context->expects($this->any())
            ->method('getGroup')
            ->will($this->returnValue('MyGroup'));
    }

    protected function tearDown()
    {
        $this->validator = null;
        $this->context = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new All(new Range(array('min' => 4))));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testThrowsExceptionIfNotTraversable()
    {
        $this->validator->validate('foo.barbar', new All(new Range(array('min' => 4))));
    }

    /**
     * @dataProvider getValidArguments
     */
    public function testWalkSingleConstraint($array)
    {
        $constraint = new Range(array('min' => 4));

        $i = 1;

        foreach ($array as $key => $value) {
            $this->context->expects($this->at($i++))
                ->method('validateValue')
                ->with($value, $constraint, '['.$key.']', 'MyGroup');
        }

        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($array, new All($constraint));
    }

    /**
     * @dataProvider getValidArguments
     */
    public function testWalkMultipleConstraints($array)
    {
        $constraint1 = new Range(array('min' => 4));
        $constraint2 = new NotNull();

        $constraints = array($constraint1, $constraint2);
        $i = 1;

        foreach ($array as $key => $value) {
            $this->context->expects($this->at($i++))
                ->method('validateValue')
                ->with($value, $constraint1, '['.$key.']', 'MyGroup');
            $this->context->expects($this->at($i++))
                ->method('validateValue')
                ->with($value, $constraint2, '['.$key.']', 'MyGroup');
        }

        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($array, new All($constraints));
    }

    public function getValidArguments()
    {
        return array(
            array(array(5, 6, 7)),
            array(new \ArrayObject(array(5, 6, 7))),
        );
    }
}
PK��Z�ĀDDStest/Validator/Symfony/Component/Validator/Tests/Constraints/RegexValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Regex;
use Symfony\Component\Validator\Constraints\RegexValidator;

class RegexValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new RegexValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Regex(array('pattern' => '/^[0-9]+$/')));
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Regex(array('pattern' => '/^[0-9]+$/')));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsStringCompatibleType()
    {
        $this->validator->validate(new \stdClass(), new Regex(array('pattern' => '/^[0-9]+$/')));
    }

    /**
     * @dataProvider getValidValues
     */
    public function testValidValues($value)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = new Regex(array('pattern' => '/^[0-9]+$/'));
        $this->validator->validate($value, $constraint);
    }

    public function getValidValues()
    {
        return array(
            array(0),
            array('0'),
            array('090909'),
            array(90909),
        );
    }

    /**
     * @dataProvider getInvalidValues
     */
    public function testInvalidValues($value)
    {
        $constraint = new Regex(array(
            'pattern' => '/^[0-9]+$/',
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $value,
            ));

        $this->validator->validate($value, $constraint);
    }

    public function getInvalidValues()
    {
        return array(
            array('abcd'),
            array('090foo'),
        );
    }

    public function testConstraintGetDefaultOption()
    {
        $constraint = new Regex(array(
            'pattern' => '/^[0-9]+$/',
        ));

        $this->assertEquals('pattern', $constraint->getDefaultOption());
    }

    public function testHtmlPatternEscaping()
    {
        $constraint = new Regex(array(
            'pattern' => '/^[0-9]+\/$/',
        ));

        $this->assertEquals('[0-9]+/', $constraint->getHtmlPattern());

        $constraint = new Regex(array(
            'pattern' => '#^[0-9]+\#$#',
        ));

        $this->assertEquals('[0-9]+#', $constraint->getHtmlPattern());
    }

    public function testHtmlPattern()
    {
        // Specified htmlPattern
        $constraint = new Regex(array(
            'pattern' => '/^[a-z]+$/i',
            'htmlPattern' => '[a-zA-Z]+',
        ));
        $this->assertEquals('[a-zA-Z]+', $constraint->getHtmlPattern());

        // Disabled htmlPattern
        $constraint = new Regex(array(
            'pattern' => '/^[a-z]+$/i',
            'htmlPattern' => false,
        ));
        $this->assertNull($constraint->getHtmlPattern());

        // Cannot be converted
        $constraint = new Regex(array(
            'pattern' => '/^[a-z]+$/i',
        ));
        $this->assertNull($constraint->getHtmlPattern());

        // Automatically converted
        $constraint = new Regex(array(
            'pattern' => '/^[a-z]+$/',
        ));
        $this->assertEquals('[a-z]+', $constraint->getHtmlPattern());

        // Automatically converted, adds .*
        $constraint = new Regex(array(
            'pattern' => '/[a-z]+/',
        ));
        $this->assertEquals('.*[a-z]+.*', $constraint->getHtmlPattern());

        // Dropped because of match=false
        $constraint = new Regex(array(
            'pattern' => '/[a-z]+/',
            'match' => false
        ));
        $this->assertNull($constraint->getHtmlPattern());
    }
}
PK��Z�Q�]test/Validator/Symfony/Component/Validator/Tests/Constraints/LessThanOrEqualValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\LessThanOrEqual;
use Symfony\Component\Validator\Constraints\LessThanOrEqualValidator;

/**
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class LessThanOrEqualValidatorTest extends AbstractComparisonValidatorTestCase
{
    protected function createValidator()
    {
        return new LessThanOrEqualValidator();
    }

    protected function createConstraint(array $options)
    {
        return new LessThanOrEqual($options);
    }

    /**
     * {@inheritDoc}
     */
    public function provideValidComparisons()
    {
        return array(
            array(1, 2),
            array(1, 1),
            array(new \DateTime('2000-01-01'), new \DateTime('2000-01-01')),
            array(new \DateTime('2000-01-01'), new \DateTime('2020-01-01')),
            array(new ComparisonTest_Class(4), new ComparisonTest_Class(5)),
            array(new ComparisonTest_Class(5), new ComparisonTest_Class(5)),
            array('a', 'a'),
            array('a', 'z'),
            array(null, 1),
        );
    }

    /**
     * {@inheritDoc}
     */
    public function provideInvalidComparisons()
    {
        return array(
            array(2, 1, '1', 'integer'),
            array(new \DateTime('2010-01-01'), new \DateTime('2000-01-01'), '2000-01-01 00:00:00', 'DateTime'),
            array(new ComparisonTest_Class(5), new ComparisonTest_Class(4), '4', __NAMESPACE__.'\ComparisonTest_Class'),
            array('c', 'b', "'b'", 'string')
        );
    }
}
PK��Z�;�55Rtest/Validator/Symfony/Component/Validator/Tests/Constraints/IssnValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Issn;
use Symfony\Component\Validator\Constraints\IssnValidator;

/**
 * @see https://en.wikipedia.org/wiki/Issn
 */
class IssnValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    public function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new IssnValidator();
        $this->validator->initialize($this->context);
    }

    public function getValidLowerCasedIssn()
    {
        return array(
            array('2162-321x'),
            array('2160-200x'),
            array('1537-453x'),
            array('1937-710x'),
            array('0002-922x'),
            array('1553-345x'),
            array('1553-619x'),
        );
    }

    public function getValidNonHyphenatedIssn()
    {
        return array(
            array('2162321X'),
            array('01896016'),
            array('15744647'),
            array('14350645'),
            array('07174055'),
            array('20905076'),
            array('14401592'),
        );
    }

    public function getFullValidIssn()
    {
        return array(
            array('1550-7416'),
            array('1539-8560'),
            array('2156-5376'),
            array('1119-023X'),
            array('1684-5315'),
            array('1996-0786'),
            array('1684-5374'),
            array('1996-0794'),
        );
    }

    public function getValidIssn()
    {
        return array_merge(
            $this->getValidLowerCasedIssn(),
            $this->getValidNonHyphenatedIssn(),
            $this->getFullValidIssn()
        );
    }

    public function getInvalidFormatedIssn()
    {
        return array(
            array(0),
            array('1539'),
            array('2156-537A')
        );
    }

    public function getInvalidValueIssn()
    {
        return array(
            array('1119-0231'),
            array('1684-5312'),
            array('1996-0783'),
            array('1684-537X'),
            array('1996-0795'),
        );

    }

    public function getInvalidIssn()
    {
        return array_merge(
            $this->getInvalidFormatedIssn(),
            $this->getInvalidValueIssn()
        );
    }

    public function testNullIsValid()
    {
        $constraint = new Issn();
        $this->context
            ->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, $constraint);
    }

    public function testEmptyStringIsValid()
    {
        $constraint = new Issn();
        $this->context
            ->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', $constraint);
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsStringCompatibleType()
    {
        $constraint = new Issn();
        $this->validator->validate(new \stdClass(), $constraint);
    }

    /**
     * @dataProvider getValidLowerCasedIssn
     */
    public function testCaseSensitiveIssns($issn)
    {
        $constraint = new Issn(array('caseSensitive' => true));
        $this->context
            ->expects($this->once())
            ->method('addViolation')
            ->with($constraint->message);

        $this->validator->validate($issn, $constraint);
    }

    /**
     * @dataProvider getValidNonHyphenatedIssn
     */
    public function testRequireHyphenIssns($issn)
    {
        $constraint = new Issn(array('requireHyphen' => true));
        $this->context
            ->expects($this->once())
            ->method('addViolation')
            ->with($constraint->message);

        $this->validator->validate($issn, $constraint);
    }

    /**
     * @dataProvider getValidIssn
     */
    public function testValidIssn($issn)
    {
        $constraint = new Issn();
        $this->context
            ->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($issn, $constraint);
    }

    /**
     * @dataProvider getInvalidFormatedIssn
     */
    public function testInvalidFormatIssn($issn)
    {
        $constraint = new Issn();
        $this->context
            ->expects($this->once())
            ->method('addViolation')
            ->with($constraint->message);

        $this->validator->validate($issn, $constraint);
    }

    /**
     * @dataProvider getInvalidValueIssn
     */
    public function testInvalidValueIssn($issn)
    {
        $constraint = new Issn();
        $this->context
            ->expects($this->once())
            ->method('addViolation')
            ->with($constraint->message);

        $this->validator->validate($issn, $constraint);
    }

    /**
     * @dataProvider getInvalidIssn
     */
    public function testInvalidIssn($issn)
    {
        $constraint = new Issn();
        $this->context
            ->expects($this->once())
            ->method('addViolation');

        $this->validator->validate($issn, $constraint);
    }
}
PK��Z����K1K1Ptest/Validator/Symfony/Component/Validator/Tests/Constraints/IpValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Ip;
use Symfony\Component\Validator\Constraints\IpValidator;

class IpValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new IpValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Ip());
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Ip());
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsStringCompatibleType()
    {
        $this->validator->validate(new \stdClass(), new Ip());
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testInvalidValidatorVersion()
    {
        $ip = new Ip(array(
            'version' => 666,
        ));
    }

    /**
     * @dataProvider getValidIpsV4
     */
    public function testValidIpsV4($ip)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($ip, new Ip(array(
            'version' => Ip::V4,
        )));
    }

    public function getValidIpsV4()
    {
        return array(
            array('0.0.0.0'),
            array('10.0.0.0'),
            array('123.45.67.178'),
            array('172.16.0.0'),
            array('192.168.1.0'),
            array('224.0.0.1'),
            array('255.255.255.255'),
            array('127.0.0.0'),
        );
    }

    /**
     * @dataProvider getValidIpsV6
     */
    public function testValidIpsV6($ip)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($ip, new Ip(array(
            'version' => Ip::V6,
        )));
    }

    public function getValidIpsV6()
    {
        return array(
            array('2001:0db8:85a3:0000:0000:8a2e:0370:7334'),
            array('2001:0DB8:85A3:0000:0000:8A2E:0370:7334'),
            array('2001:0Db8:85a3:0000:0000:8A2e:0370:7334'),
            array('fdfe:dcba:9876:ffff:fdc6:c46b:bb8f:7d4c'),
            array('fdc6:c46b:bb8f:7d4c:fdc6:c46b:bb8f:7d4c'),
            array('fdc6:c46b:bb8f:7d4c:0000:8a2e:0370:7334'),
            array('fe80:0000:0000:0000:0202:b3ff:fe1e:8329'),
            array('fe80:0:0:0:202:b3ff:fe1e:8329'),
            array('fe80::202:b3ff:fe1e:8329'),
            array('0:0:0:0:0:0:0:0'),
            array('::'),
            array('0::'),
            array('::0'),
            array('0::0'),
            // IPv4 mapped to IPv6
            array('2001:0db8:85a3:0000:0000:8a2e:0.0.0.0'),
            array('::0.0.0.0'),
            array('::255.255.255.255'),
            array('::123.45.67.178'),
        );
    }

    /**
     * @dataProvider getValidIpsAll
     */
    public function testValidIpsAll($ip)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($ip, new Ip(array(
            'version' => Ip::ALL,
        )));
    }

    public function getValidIpsAll()
    {
        return array_merge($this->getValidIpsV4(), $this->getValidIpsV6());
    }

    /**
     * @dataProvider getInvalidIpsV4
     */
    public function testInvalidIpsV4($ip)
    {
        $constraint = new Ip(array(
            'version' => Ip::V4,
            'message' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $ip,
            ));

        $this->validator->validate($ip, $constraint);
    }

    public function getInvalidIpsV4()
    {
        return array(
            array('0'),
            array('0.0'),
            array('0.0.0'),
            array('256.0.0.0'),
            array('0.256.0.0'),
            array('0.0.256.0'),
            array('0.0.0.256'),
            array('-1.0.0.0'),
            array('foobar'),
        );
    }

    /**
     * @dataProvider getInvalidPrivateIpsV4
     */
    public function testInvalidPrivateIpsV4($ip)
    {
        $constraint = new Ip(array(
            'version' => Ip::V4_NO_PRIV,
            'message' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $ip,
            ));

        $this->validator->validate($ip, $constraint);
    }

    public function getInvalidPrivateIpsV4()
    {
        return array(
            array('10.0.0.0'),
            array('172.16.0.0'),
            array('192.168.1.0'),
        );
    }

    /**
     * @dataProvider getInvalidReservedIpsV4
     */
    public function testInvalidReservedIpsV4($ip)
    {
        $constraint = new Ip(array(
            'version' => Ip::V4_NO_RES,
            'message' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $ip,
            ));

        $this->validator->validate($ip, $constraint);
    }

    public function getInvalidReservedIpsV4()
    {
        return array(
            array('0.0.0.0'),
            array('224.0.0.1'),
            array('255.255.255.255'),
        );
    }

    /**
     * @dataProvider getInvalidPublicIpsV4
     */
    public function testInvalidPublicIpsV4($ip)
    {
        $constraint = new Ip(array(
            'version' => Ip::V4_ONLY_PUBLIC,
            'message' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $ip,
            ));

        $this->validator->validate($ip, $constraint);
    }

    public function getInvalidPublicIpsV4()
    {
        return array_merge($this->getInvalidPrivateIpsV4(), $this->getInvalidReservedIpsV4());
    }

    /**
     * @dataProvider getInvalidIpsV6
     */
    public function testInvalidIpsV6($ip)
    {
        $constraint = new Ip(array(
            'version' => Ip::V6,
            'message' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $ip,
            ));

        $this->validator->validate($ip, $constraint);
    }

    public function getInvalidIpsV6()
    {
        return array(
            array('z001:0db8:85a3:0000:0000:8a2e:0370:7334'),
            array('fe80'),
            array('fe80:8329'),
            array('fe80:::202:b3ff:fe1e:8329'),
            array('fe80::202:b3ff::fe1e:8329'),
            // IPv4 mapped to IPv6
            array('2001:0db8:85a3:0000:0000:8a2e:0370:0.0.0.0'),
            array('::0.0'),
            array('::0.0.0'),
            array('::256.0.0.0'),
            array('::0.256.0.0'),
            array('::0.0.256.0'),
            array('::0.0.0.256'),
        );
    }

    /**
     * @dataProvider getInvalidPrivateIpsV6
     */
    public function testInvalidPrivateIpsV6($ip)
    {
        $constraint = new Ip(array(
            'version' => Ip::V6_NO_PRIV,
            'message' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $ip,
            ));

        $this->validator->validate($ip, $constraint);
    }

    public function getInvalidPrivateIpsV6()
    {
        return array(
            array('fdfe:dcba:9876:ffff:fdc6:c46b:bb8f:7d4c'),
            array('fdc6:c46b:bb8f:7d4c:fdc6:c46b:bb8f:7d4c'),
            array('fdc6:c46b:bb8f:7d4c:0000:8a2e:0370:7334'),
        );
    }

    /**
     * @dataProvider getInvalidReservedIpsV6
     */
    public function testInvalidReservedIpsV6($ip)
    {
        $constraint = new Ip(array(
            'version' => Ip::V6_NO_RES,
            'message' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $ip,
            ));

        $this->validator->validate($ip, $constraint);
    }

    public function getInvalidReservedIpsV6()
    {
        // Quoting after official filter documentation:
        // "FILTER_FLAG_NO_RES_RANGE = This flag does not apply to IPv6 addresses."
        // Full description: http://php.net/manual/en/filter.filters.flags.php
        return $this->getInvalidIpsV6();
    }

    /**
     * @dataProvider getInvalidPublicIpsV6
     */
    public function testInvalidPublicIpsV6($ip)
    {
        $constraint = new Ip(array(
            'version' => Ip::V6_ONLY_PUBLIC,
            'message' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $ip,
            ));

        $this->validator->validate($ip, $constraint);
    }

    public function getInvalidPublicIpsV6()
    {
        return array_merge($this->getInvalidPrivateIpsV6(), $this->getInvalidReservedIpsV6());
    }

    /**
     * @dataProvider getInvalidIpsAll
     */
    public function testInvalidIpsAll($ip)
    {
        $constraint = new Ip(array(
            'version' => Ip::ALL,
            'message' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $ip,
            ));

        $this->validator->validate($ip, $constraint);
    }

    public function getInvalidIpsAll()
    {
        return array_merge($this->getInvalidIpsV4(), $this->getInvalidIpsV6());
    }

    /**
     * @dataProvider getInvalidPrivateIpsAll
     */
    public function testInvalidPrivateIpsAll($ip)
    {
        $constraint = new Ip(array(
            'version' => Ip::ALL_NO_PRIV,
            'message' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $ip,
            ));

        $this->validator->validate($ip, $constraint);
    }

    public function getInvalidPrivateIpsAll()
    {
        return array_merge($this->getInvalidPrivateIpsV4(), $this->getInvalidPrivateIpsV6());
    }

    /**
     * @dataProvider getInvalidReservedIpsAll
     */
    public function testInvalidReservedIpsAll($ip)
    {
        $constraint = new Ip(array(
            'version' => Ip::ALL_NO_RES,
            'message' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $ip,
            ));

        $this->validator->validate($ip, $constraint);
    }

    public function getInvalidReservedIpsAll()
    {
        return array_merge($this->getInvalidReservedIpsV4(), $this->getInvalidReservedIpsV6());
    }

    /**
     * @dataProvider getInvalidPublicIpsAll
     */
    public function testInvalidPublicIpsAll($ip)
    {
        $constraint = new Ip(array(
            'version' => Ip::ALL_ONLY_PUBLIC,
            'message' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $ip,
            ));

        $this->validator->validate($ip, $constraint);
    }

    public function getInvalidPublicIpsAll()
    {
        return array_merge($this->getInvalidPublicIpsV4(), $this->getInvalidPublicIpsV6());
    }
}
PK��Z�rH���itest/Validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorCustomArrayObjectTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

/**
 * This class is a hand written simplified version of PHP native `ArrayObject`
 * class, to show that it behaves differently than the PHP native implementation.
 */
class CustomArrayObject implements \ArrayAccess, \IteratorAggregate, \Countable, \Serializable
{
    private $array;

    public function __construct(array $array = null)
    {
        $this->array = $array ?: array();
    }

    public function offsetExists($offset)
    {
        return array_key_exists($offset, $this->array);
    }

    public function offsetGet($offset)
    {
        return $this->array[$offset];
    }

    public function offsetSet($offset, $value)
    {
        if (null === $offset) {
            $this->array[] = $value;
        } else {
            $this->array[$offset] = $value;
        }
    }

    public function offsetUnset($offset)
    {
        unset($this->array[$offset]);
    }

    public function getIterator()
    {
        return new \ArrayIterator($this->array);
    }

    public function count()
    {
        return count($this->array);
    }

    public function serialize()
    {
        return serialize($this->array);
    }

    public function unserialize($serialized)
    {
        $this->array = (array) unserialize((string) $serialized);
    }
}

class CollectionValidatorCustomArrayObjectTest extends CollectionValidatorTest
{
    public function prepareTestData(array $contents)
    {
        return new CustomArrayObject($contents);
    }
}
PK��Z�GRf��Utest/Validator/Symfony/Component/Validator/Tests/Constraints/NotNullValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\NotNull;
use Symfony\Component\Validator\Constraints\NotNullValidator;

class NotNullValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new NotNullValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    /**
     * @dataProvider getValidValues
     */
    public function testValidValues($value)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($value, new NotNull());
    }

    public function getValidValues()
    {
        return array(
            array(0),
            array(false),
            array(true),
            array(''),
        );
    }

    public function testNullIsInvalid()
    {
        $constraint = new NotNull(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
            ));

        $this->validator->validate(null, $constraint);
    }
}
PK��Z���I��Otest/Validator/Symfony/Component/Validator/Tests/Constraints/CollectionTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Collection;
use Symfony\Component\Validator\Constraints\Required;
use Symfony\Component\Validator\Constraints\Optional;
use Symfony\Component\Validator\Constraints\Email;
use Symfony\Component\Validator\Constraints\Valid;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class CollectionTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testRejectInvalidFieldsOption()
    {
        new Collection(array(
            'fields' => 'foo',
        ));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testRejectNonConstraints()
    {
        new Collection(array(
            'foo' => 'bar',
        ));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testRejectValidConstraint()
    {
        new Collection(array(
            'foo' => new Valid(),
        ));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testRejectValidConstraintWithinOptional()
    {
        new Collection(array(
            'foo' => new Optional(new Valid()),
        ));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testRejectValidConstraintWithinRequired()
    {
        new Collection(array(
            'foo' => new Required(new Valid()),
        ));
    }

    public function testAcceptOptionalConstraintAsOneElementArray()
    {
        $collection1 = new Collection(array(
            "fields" => array(
                "alternate_email" => array(
                    new Optional(new Email()),
                ),
            ),
        ));

        $collection2 = new Collection(array(
            "fields" => array(
                "alternate_email" => new Optional(new Email()),
            ),
        ));

        $this->assertEquals($collection1, $collection2);
    }

    public function testAcceptRequiredConstraintAsOneElementArray()
    {
        $collection1 = new Collection(array(
            "fields" => array(
                "alternate_email" => array(
                    new Required(new Email()),
                ),
            ),
        ));

        $collection2 = new Collection(array(
            "fields" => array(
                "alternate_email" => new Required(new Email()),
            ),
        ));

        $this->assertEquals($collection1, $collection2);
    }
}
PK��Z���W��Xtest/Validator/Symfony/Component/Validator/Tests/Constraints/FileValidatorObjectTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\HttpFoundation\File\File;

class FileValidatorObjectTest extends FileValidatorTest
{
    protected function getFile($filename)
    {
        return new File($filename);
    }
}
PK��Zs{*pQQRtest/Validator/Symfony/Component/Validator/Tests/Constraints/TrueValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\True;
use Symfony\Component\Validator\Constraints\TrueValidator;

class TrueValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new TrueValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new True());
    }

    public function testTrueIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(true, new True());
    }

    public function testFalseIsInvalid()
    {
        $constraint = new True(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
            ));

        $this->validator->validate(false, $constraint);
    }
}
PK��Z�|�++Wtest/Validator/Symfony/Component/Validator/Tests/Constraints/Fixtures/test_portrait.gifnu�[���GIF89a�������!�
,L
;PK��ZJ��++Xtest/Validator/Symfony/Component/Validator/Tests/Constraints/Fixtures/test_landscape.gifnu�[���GIF89a�������!�
,L
;PK��ZЍ��!!Ntest/Validator/Symfony/Component/Validator/Tests/Constraints/Fixtures/test.gifnu�[���GIF89a����,;PK��Z)m�RTtest/Validator/Symfony/Component/Validator/Tests/Constraints/LengthValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\LengthValidator;

class LengthValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new LengthValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Length(6));
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Length(6));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsStringCompatibleType()
    {
        $this->validator->validate(new \stdClass(), new Length(5));
    }

    public function getThreeOrLessCharacters()
    {
        return array(
            array(12),
            array('12'),
            array('üü', true),
            array('éé', true),
            array(123),
            array('123'),
            array('üüü', true),
            array('ééé', true),
        );
    }

    public function getFourCharacters()
    {
        return array(
            array(1234),
            array('1234'),
            array('üüüü', true),
            array('éééé', true),
        );
    }

    public function getNotFourCharacters()
    {
        return array_merge(
            $this->getThreeOrLessCharacters(),
            $this->getFiveOrMoreCharacters()
        );
    }

    public function getFiveOrMoreCharacters()
    {
        return array(
            array(12345),
            array('12345'),
            array('üüüüü', true),
            array('ééééé', true),
            array(123456),
            array('123456'),
            array('üüüüüü', true),
            array('éééééé', true),
        );
    }

    /**
     * @dataProvider getFiveOrMoreCharacters
     */
    public function testValidValuesMin($value, $mbOnly = false)
    {
        if ($mbOnly && !function_exists('mb_strlen')) {
            $this->markTestSkipped('mb_strlen does not exist');
        }

        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = new Length(array('min' => 5));
        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getThreeOrLessCharacters
     */
    public function testValidValuesMax($value, $mbOnly = false)
    {
        if ($mbOnly && !function_exists('mb_strlen')) {
            $this->markTestSkipped('mb_strlen does not exist');
        }

        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = new Length(array('max' => 3));
        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getFourCharacters
     */
    public function testValidValuesExact($value, $mbOnly = false)
    {
        if ($mbOnly && !function_exists('mb_strlen')) {
            $this->markTestSkipped('mb_strlen does not exist');
        }

        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = new Length(4);
        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getThreeOrLessCharacters
     */
    public function testInvalidValuesMin($value, $mbOnly = false)
    {
        if ($mbOnly && !function_exists('mb_strlen')) {
            $this->markTestSkipped('mb_strlen does not exist');
        }

        $constraint = new Length(array(
            'min' => 4,
            'minMessage' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', $this->identicalTo(array(
                '{{ value }}' => (string) $value,
                '{{ limit }}' => 4,
            )), $this->identicalTo($value), 4);

        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getFiveOrMoreCharacters
     */
    public function testInvalidValuesMax($value, $mbOnly = false)
    {
        if ($mbOnly && !function_exists('mb_strlen')) {
            $this->markTestSkipped('mb_strlen does not exist');
        }

        $constraint = new Length(array(
            'max' => 4,
            'maxMessage' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', $this->identicalTo(array(
                '{{ value }}' => (string) $value,
                '{{ limit }}' => 4,
            )), $this->identicalTo($value), 4);

        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getNotFourCharacters
     */
    public function testInvalidValuesExact($value, $mbOnly = false)
    {
        if ($mbOnly && !function_exists('mb_strlen')) {
            $this->markTestSkipped('mb_strlen does not exist');
        }

        $constraint = new Length(array(
            'min' => 4,
            'max' => 4,
            'exactMessage' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', $this->identicalTo(array(
                '{{ value }}' => (string) $value,
                '{{ limit }}' => 4,
            )), $this->identicalTo($value), 4);

        $this->validator->validate($value, $constraint);
    }

    public function testConstraintGetDefaultOption()
    {
        $constraint = new Length(5);

        $this->assertEquals(5, $constraint->min);
        $this->assertEquals(5, $constraint->max);
    }
}
PK��Z��̈́
�
Ttest/Validator/Symfony/Component/Validator/Tests/Constraints/LocaleValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Intl\Util\IntlTestHelper;
use Symfony\Component\Validator\Constraints\Locale;
use Symfony\Component\Validator\Constraints\LocaleValidator;

class LocaleValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        IntlTestHelper::requireIntl($this);

        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new LocaleValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Locale());
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Locale());
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsStringCompatibleType()
    {
        $this->validator->validate(new \stdClass(), new Locale());
    }

    /**
     * @dataProvider getValidLocales
     */
    public function testValidLocales($locale)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($locale, new Locale());
    }

    public function getValidLocales()
    {
        return array(
            array('en'),
            array('en_US'),
            array('pt'),
            array('pt_PT'),
            array('zh_Hans'),
        );
    }

    /**
     * @dataProvider getInvalidLocales
     */
    public function testInvalidLocales($locale)
    {
        $constraint = new Locale(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $locale,
            ));

        $this->validator->validate($locale, $constraint);
    }

    public function getInvalidLocales()
    {
        return array(
            array('EN'),
            array('foobar'),
        );
    }
}
PK��Z�s�VVXtest/Validator/Symfony/Component/Validator/Tests/Constraints/NotEqualToValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\NotEqualTo;
use Symfony\Component\Validator\Constraints\NotEqualToValidator;

/**
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class NotEqualToValidatorTest extends AbstractComparisonValidatorTestCase
{
    protected function createValidator()
    {
        return new NotEqualToValidator();
    }

    protected function createConstraint(array $options)
    {
        return new NotEqualTo($options);
    }

    /**
     * {@inheritDoc}
     */
    public function provideValidComparisons()
    {
        return array(
            array(1, 2),
            array('22', '333'),
            array(new \DateTime('2001-01-01'), new \DateTime('2000-01-01')),
            array(new ComparisonTest_Class(6), new ComparisonTest_Class(5)),
            array(null, 1),
        );
    }

    /**
     * {@inheritDoc}
     */
    public function provideInvalidComparisons()
    {
        return array(
            array(3, 3, '3', 'integer'),
            array('2', 2, '2', 'integer'),
            array('a', 'a', "'a'", 'string'),
            array(new \DateTime('2000-01-01'), new \DateTime('2000-01-01'), '2000-01-01 00:00:00', 'DateTime'),
            array(new ComparisonTest_Class(5), new ComparisonTest_Class(5), '5', __NAMESPACE__.'\ComparisonTest_Class'),
        );
    }
}
PK��Z���8w
w
Stest/Validator/Symfony/Component/Validator/Tests/Constraints/EmailValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Email;
use Symfony\Component\Validator\Constraints\EmailValidator;

class EmailValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new EmailValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Email());
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Email());
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsStringCompatibleType()
    {
        $this->validator->validate(new \stdClass(), new Email());
    }

    /**
     * @dataProvider getValidEmails
     */
    public function testValidEmails($email)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($email, new Email());
    }

    public function getValidEmails()
    {
        return array(
            array('fabien@symfony.com'),
            array('example@example.co.uk'),
            array('fabien_potencier@example.fr'),
        );
    }

    /**
     * @dataProvider getInvalidEmails
     */
    public function testInvalidEmails($email)
    {
        $constraint = new Email(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $email,
            ));

        $this->validator->validate($email, $constraint);
    }

    public function getInvalidEmails()
    {
        return array(
            array('example'),
            array('example@'),
            array('example@localhost'),
            array('example@example.com@example.com'),
        );
    }
}
PK��Z�w88\test/Validator/Symfony/Component/Validator/Tests/Constraints/CountValidatorCountableTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

class CountValidatorCountableTest_Countable implements \Countable
{
    private $content;

    public function __construct(array $content)
    {
        $this->content = $content;
    }

    public function count()
    {
        return count($this->content);
    }
}

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class CountValidatorCountableTest extends CountValidatorTest
{
    protected function createCollection(array $content)
    {
        return new CountValidatorCountableTest_Countable($content);
    }
}
PK��Z];XwwStest/Validator/Symfony/Component/Validator/Tests/Constraints/BlankValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Blank;
use Symfony\Component\Validator\Constraints\BlankValidator;

class BlankValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new BlankValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Blank());
    }

    public function testBlankIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Blank());
    }

    /**
     * @dataProvider getInvalidValues
     */
    public function testInvalidValues($value)
    {
        $constraint = new Blank(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $value,
            ));

        $this->validator->validate($value, $constraint);
    }

    public function getInvalidValues()
    {
        return array(
            array('foobar'),
            array(0),
            array(false),
            array(1234),
        );
    }
}
PK��Z3�ê�
�
dtest/Validator/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Constraints\AbstractComparisonValidator;

class ComparisonTest_Class
{
    protected $value;

    public function __construct($value)
    {
        $this->value = $value;
    }

    public function __toString()
    {
        return (string) $this->value;
    }
}

/**
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
abstract class AbstractComparisonValidatorTestCase extends \PHPUnit_Framework_TestCase
{
    private $validator;
    private $context;

    protected function setUp()
    {
        $this->validator = $this->createValidator();
        $this->context = $this->getMockBuilder('Symfony\Component\Validator\ExecutionContext')
            ->disableOriginalConstructor()
            ->getMock();
        $this->validator->initialize($this->context);
    }

    /**
     * @return AbstractComparisonValidator
     */
    abstract protected function createValidator();

    public function testThrowsConstraintExceptionIfNoValueOrProperty()
    {
        $this->setExpectedException('Symfony\Component\Validator\Exception\ConstraintDefinitionException');

        $comparison = $this->createConstraint(array());
        $this->validator->validate('some value', $comparison);
    }

    /**
     * @dataProvider provideValidComparisons
     * @param mixed $dirtyValue
     * @param mixed $comparisonValue
     */
    public function testValidComparisonToValue($dirtyValue, $comparisonValue)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = $this->createConstraint(array('value' => $comparisonValue));

        $this->context->expects($this->any())
            ->method('getPropertyPath')
            ->will($this->returnValue('property1'));

        $this->validator->validate($dirtyValue, $constraint);
    }

    /**
     * @return array
     */
    abstract public function provideValidComparisons();

    /**
     * @dataProvider provideInvalidComparisons
     * @param mixed  $dirtyValue
     * @param mixed  $comparedValue
     * @param mixed  $comparedValueString
     * @param string $comparedValueType
     */
    public function testInvalidComparisonToValue($dirtyValue, $comparedValue, $comparedValueString, $comparedValueType)
    {
        $constraint = $this->createConstraint(array('value' => $comparedValue));
        $constraint->message = 'Constraint Message';

        $this->context->expects($this->any())
            ->method('getPropertyPath')
            ->will($this->returnValue('property1'));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('Constraint Message', array(
                '{{ value }}' => $comparedValueString,
                '{{ compared_value }}' => $comparedValueString,
                '{{ compared_value_type }}' => $comparedValueType
            ));

        $this->validator->validate($dirtyValue, $constraint);
    }

    /**
     * @return array
     */
    abstract public function provideInvalidComparisons();

    /**
     * @param  array      $options Options for the constraint
     * @return Constraint
     */
    abstract protected function createConstraint(array $options);
}
PK��Z7��a��Ttest/Validator/Symfony/Component/Validator/Tests/Constraints/ChoiceValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Choice;
use Symfony\Component\Validator\Constraints\ChoiceValidator;

function choice_callback()
{
    return array('foo', 'bar');
}

class ChoiceValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    public static function staticCallback()
    {
        return array('foo', 'bar');
    }

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new ChoiceValidator();
        $this->validator->initialize($this->context);

        $this->context->expects($this->any())
            ->method('getClassName')
            ->will($this->returnValue(__CLASS__));
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectArrayIfMultipleIsTrue()
    {
        $constraint = new Choice(array(
            'choices' => array('foo', 'bar'),
            'multiple' => true,
        ));

        $this->validator->validate('asdf', $constraint);
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Choice(array('choices' => array('foo', 'bar'))));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testChoicesOrCallbackExpected()
    {
        $this->validator->validate('foobar', new Choice());
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testValidCallbackExpected()
    {
        $this->validator->validate('foobar', new Choice(array('callback' => 'abcd')));
    }

    public function testValidChoiceArray()
    {
        $constraint = new Choice(array('choices' => array('foo', 'bar')));

        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('bar', $constraint);
    }

    public function testValidChoiceCallbackFunction()
    {
        $constraint = new Choice(array('callback' => __NAMESPACE__.'\choice_callback'));

        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('bar', $constraint);
    }

    public function testValidChoiceCallbackClosure()
    {
        $constraint = new Choice(array('callback' => function () {
            return array('foo', 'bar');
        }));

        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('bar', $constraint);
    }

    public function testValidChoiceCallbackStaticMethod()
    {
        $constraint = new Choice(array('callback' => array(__CLASS__, 'staticCallback')));

        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('bar', $constraint);
    }

    public function testValidChoiceCallbackContextMethod()
    {
        $constraint = new Choice(array('callback' => 'staticCallback'));

        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('bar', $constraint);
    }

    public function testMultipleChoices()
    {
        $constraint = new Choice(array(
            'choices' => array('foo', 'bar', 'baz'),
            'multiple' => true,
        ));

        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(array('baz', 'bar'), $constraint);
    }

    public function testInvalidChoice()
    {
        $constraint = new Choice(array(
            'choices' => array('foo', 'bar'),
            'message' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => 'baz',
            ), null, null);

        $this->validator->validate('baz', $constraint);
    }

    public function testInvalidChoiceMultiple()
    {
        $constraint = new Choice(array(
            'choices' => array('foo', 'bar'),
            'multipleMessage' => 'myMessage',
            'multiple' => true,
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => 'baz',
            ));

        $this->validator->validate(array('foo', 'baz'), $constraint);
    }

    public function testTooFewChoices()
    {
        $constraint = new Choice(array(
            'choices' => array('foo', 'bar', 'moo', 'maa'),
            'multiple' => true,
            'min' => 2,
            'minMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ limit }}' => 2,
            ), null, 2);

        $this->validator->validate(array('foo'), $constraint);
    }

    public function testTooManyChoices()
    {
        $constraint = new Choice(array(
            'choices' => array('foo', 'bar', 'moo', 'maa'),
            'multiple' => true,
            'max' => 2,
            'maxMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ limit }}' => 2,
            ), null, 2);

        $this->validator->validate(array('foo', 'bar', 'moo'), $constraint);
    }

    public function testNonStrict()
    {
        $constraint = new Choice(array(
            'choices' => array(1, 2),
            'strict' => false,
        ));

        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('2', $constraint);
        $this->validator->validate(2, $constraint);
    }

    public function testStrictAllowsExactValue()
    {
        $constraint = new Choice(array(
            'choices' => array(1, 2),
            'strict' => true,
        ));

        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(2, $constraint);
    }

    public function testStrictDisallowsDifferentType()
    {
        $constraint = new Choice(array(
            'choices' => array(1, 2),
            'strict' => true,
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => '2',
            ));

        $this->validator->validate('2', $constraint);
    }

    public function testNonStrictWithMultipleChoices()
    {
        $constraint = new Choice(array(
            'choices' => array(1, 2, 3),
            'multiple' => true,
            'strict' => false
        ));

        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(array('2', 3), $constraint);
    }

    public function testStrictWithMultipleChoices()
    {
        $constraint = new Choice(array(
            'choices' => array(1, 2, 3),
            'multiple' => true,
            'strict' => true,
            'multipleMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => '3',
            ));

        $this->validator->validate(array(2, '3'), $constraint);
    }
}
PK��Z�2�(�(Rtest/Validator/Symfony/Component/Validator/Tests/Constraints/FileValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\File;
use Symfony\Component\Validator\Constraints\FileValidator;
use Symfony\Component\HttpFoundation\File\UploadedFile;

abstract class FileValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;
    protected $path;
    protected $file;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new FileValidator();
        $this->validator->initialize($this->context);
        $this->path = sys_get_temp_dir().DIRECTORY_SEPARATOR.'FileValidatorTest';
        $this->file = fopen($this->path, 'w');
    }

    protected function tearDown()
    {
        fclose($this->file);

        $this->context = null;
        $this->validator = null;
        $this->path = null;
        $this->file = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new File());
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new File());
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsStringCompatibleTypeOrFile()
    {
        $this->validator->validate(new \stdClass(), new File());
    }

    public function testValidFile()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($this->path, new File());
    }

    public function testValidUploadedfile()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $file = new UploadedFile($this->path, 'originalName', null, null, null, true);
        $this->validator->validate($file, new File());
    }

    public function testTooLargeBytes()
    {
        fwrite($this->file, str_repeat('0', 11));

        $constraint = new File(array(
            'maxSize'           => 10,
            'maxSizeMessage'    => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ limit }}'   => '10',
                '{{ size }}'    => '11',
                '{{ suffix }}'  => 'bytes',
                '{{ file }}'    => $this->path,
            ));

        $this->validator->validate($this->getFile($this->path), $constraint);
    }

    public function testTooLargeKiloBytes()
    {
        fwrite($this->file, str_repeat('0', 1400));

        $constraint = new File(array(
            'maxSize'           => '1k',
            'maxSizeMessage'    => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ limit }}'   => '1',
                '{{ size }}'    => '1.4',
                '{{ suffix }}'  => 'kB',
                '{{ file }}'    => $this->path,
            ));

        $this->validator->validate($this->getFile($this->path), $constraint);
    }

    public function testTooLargeMegaBytes()
    {
        fwrite($this->file, str_repeat('0', 1400000));

        $constraint = new File(array(
            'maxSize'           => '1M',
            'maxSizeMessage'    => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ limit }}'   => '1',
                '{{ size }}'    => '1.4',
                '{{ suffix }}'  => 'MB',
                '{{ file }}'    => $this->path,
            ));

        $this->validator->validate($this->getFile($this->path), $constraint);
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testInvalidMaxSize()
    {
        $constraint = new File(array(
            'maxSize' => '1abc',
        ));

        $this->validator->validate($this->path, $constraint);
    }

    public function testValidMimeType()
    {
        $file = $this
            ->getMockBuilder('Symfony\Component\HttpFoundation\File\File')
            ->disableOriginalConstructor()
            ->getMock()
        ;
        $file
            ->expects($this->once())
            ->method('getPathname')
            ->will($this->returnValue($this->path))
        ;
        $file
            ->expects($this->once())
            ->method('getMimeType')
            ->will($this->returnValue('image/jpg'))
        ;

        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = new File(array(
            'mimeTypes' => array('image/png', 'image/jpg'),
        ));

        $this->validator->validate($file, $constraint);
    }

    public function testValidWildcardMimeType()
    {
        $file = $this
            ->getMockBuilder('Symfony\Component\HttpFoundation\File\File')
            ->disableOriginalConstructor()
            ->getMock()
        ;
        $file
            ->expects($this->once())
            ->method('getPathname')
            ->will($this->returnValue($this->path))
        ;
        $file
            ->expects($this->once())
            ->method('getMimeType')
            ->will($this->returnValue('image/jpg'))
        ;

        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = new File(array(
            'mimeTypes' => array('image/*'),
        ));

        $this->validator->validate($file, $constraint);
    }

    public function testInvalidMimeType()
    {
        $file = $this
            ->getMockBuilder('Symfony\Component\HttpFoundation\File\File')
            ->disableOriginalConstructor()
            ->getMock()
        ;
        $file
            ->expects($this->once())
            ->method('getPathname')
            ->will($this->returnValue($this->path))
        ;
        $file
            ->expects($this->once())
            ->method('getMimeType')
            ->will($this->returnValue('application/pdf'))
        ;

        $constraint = new File(array(
            'mimeTypes' => array('image/png', 'image/jpg'),
            'mimeTypesMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ type }}'    => '"application/pdf"',
                '{{ types }}'   => '"image/png", "image/jpg"',
                '{{ file }}'    => $this->path,
            ));

        $this->validator->validate($file, $constraint);
    }

    public function testInvalidWildcardMimeType()
    {
        $file = $this
            ->getMockBuilder('Symfony\Component\HttpFoundation\File\File')
            ->disableOriginalConstructor()
            ->getMock()
        ;
        $file
            ->expects($this->once())
            ->method('getPathname')
            ->will($this->returnValue($this->path))
        ;
        $file
            ->expects($this->once())
            ->method('getMimeType')
            ->will($this->returnValue('application/pdf'))
        ;

        $constraint = new File(array(
            'mimeTypes' => array('image/*', 'image/jpg'),
            'mimeTypesMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ type }}'    => '"application/pdf"',
                '{{ types }}'   => '"image/*", "image/jpg"',
                '{{ file }}'    => $this->path,
            ));

        $this->validator->validate($file, $constraint);
    }

    /**
     * @dataProvider uploadedFileErrorProvider
     */
    public function testUploadedFileError($error, $message, array $params = array(), $maxSize = null)
    {
        $file = new UploadedFile('/path/to/file', 'originalName', 'mime', 0, $error);

        $constraint = new File(array(
            $message => 'myMessage',
            'maxSize' => $maxSize
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', $params);

        $this->validator->validate($file, $constraint);

    }

    public function uploadedFileErrorProvider()
    {
        $tests = array(
            array(UPLOAD_ERR_FORM_SIZE, 'uploadFormSizeErrorMessage'),
            array(UPLOAD_ERR_PARTIAL, 'uploadPartialErrorMessage'),
            array(UPLOAD_ERR_NO_FILE, 'uploadNoFileErrorMessage'),
            array(UPLOAD_ERR_NO_TMP_DIR, 'uploadNoTmpDirErrorMessage'),
            array(UPLOAD_ERR_CANT_WRITE, 'uploadCantWriteErrorMessage'),
            array(UPLOAD_ERR_EXTENSION, 'uploadExtensionErrorMessage'),
        );

        if (class_exists('Symfony\Component\HttpFoundation\File\UploadedFile')) {
            // when no maxSize is specified on constraint, it should use the ini value
            $tests[] = array(UPLOAD_ERR_INI_SIZE, 'uploadIniSizeErrorMessage', array(
                '{{ limit }}' => UploadedFile::getMaxFilesize(),
                '{{ suffix }}' => 'bytes',
            ));

            // it should use the smaller limitation (maxSize option in this case)
            $tests[] = array(UPLOAD_ERR_INI_SIZE, 'uploadIniSizeErrorMessage', array(
                '{{ limit }}' => 1,
                '{{ suffix }}' => 'bytes',
            ), '1');

            // it correctly parses the maxSize option and not only uses simple string comparison
            // 1000M should be bigger than the ini value
            $tests[] = array(UPLOAD_ERR_INI_SIZE, 'uploadIniSizeErrorMessage', array(
                '{{ limit }}' => UploadedFile::getMaxFilesize(),
                '{{ suffix }}' => 'bytes',
            ), '1000M');
        }

        return $tests;
    }

    abstract protected function getFile($filename);
}
PK��Z�����Xtest/Validator/Symfony/Component/Validator/Tests/Constraints/CardSchemeValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\CardScheme;
use Symfony\Component\Validator\Constraints\CardSchemeValidator;

class CardSchemeValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new CardSchemeValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new CardScheme(array('schemes' => array())));
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new CardScheme(array('schemes' => array())));
    }

    /**
     * @dataProvider getValidNumbers
     */
    public function testValidNumbers($scheme, $number)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($number, new CardScheme(array('schemes' => $scheme)));
    }

    /**
     * @dataProvider getInvalidNumbers
     */
    public function testInvalidNumbers($scheme, $number)
    {
        $this->context->expects($this->once())
            ->method('addViolation');

        $this->validator->validate($number, new CardScheme(array('schemes' => $scheme)));
    }

    public function getValidNumbers()
    {
        return array(
            array('AMEX', '378282246310005'),
            array('AMEX', '371449635398431'),
            array('AMEX', '378734493671000'),
            array('AMEX', '347298508610146'),
            array('CHINA_UNIONPAY', '6228888888888888'),
            array('CHINA_UNIONPAY', '62288888888888888'),
            array('CHINA_UNIONPAY', '622888888888888888'),
            array('CHINA_UNIONPAY', '6228888888888888888'),
            array('DINERS', '30569309025904'),
            array('DINERS', '36088894118515'),
            array('DINERS', '38520000023237'),
            array('DISCOVER', '6011111111111117'),
            array('DISCOVER', '6011000990139424'),
            array('INSTAPAYMENT', '6372476031350068'),
            array('INSTAPAYMENT', '6385537775789749'),
            array('INSTAPAYMENT', '6393440808445746'),
            array('JCB', '3530111333300000'),
            array('JCB', '3566002020360505'),
            array('JCB', '213112345678901'),
            array('JCB', '180012345678901'),
            array('LASER', '6304678107004080'),
            array('LASER', '6706440607428128629'),
            array('LASER', '6771656738314582216'),
            array('MAESTRO', '6759744069209'),
            array('MAESTRO', '5020507657408074712'),
            array('MAESTRO', '6759744069209'),
            array('MAESTRO', '6759744069209'),
            array('MASTERCARD', '5555555555554444'),
            array('MASTERCARD', '5105105105105100'),
            array('VISA', '4111111111111111'),
            array('VISA', '4012888888881881'),
            array('VISA', '4222222222222'),
            array(array('AMEX', 'VISA'), '4111111111111111'),
            array(array('AMEX', 'VISA'), '378282246310005'),
            array(array('JCB', 'MASTERCARD'), '5105105105105100'),
            array(array('VISA', 'MASTERCARD'), '5105105105105100'),
        );
    }

    public function getInvalidNumbers()
    {
        return array(
            array('VISA', '42424242424242424242'),
            array('AMEX', '357298508610146'),
            array('DINERS', '31569309025904'),
            array('DINERS', '37088894118515'),
            array('INSTAPAYMENT', '6313440808445746'),
            array('CHINA_UNIONPAY', '622888888888888'),
            array('CHINA_UNIONPAY', '62288888888888888888'),
            array('AMEX', '30569309025904'), // DINERS number
            array('AMEX', 'invalid'), // A string
            array('AMEX', 0), // a lone number
            array('AMEX', '0'), // a lone number
            array('AMEX', '000000000000'), // a lone number
            array('DINERS', '3056930'), // only first part of the number
            array('DISCOVER', '1117'), // only last 4 digits
        );
    }
}
PK��Z{r>K��Rtest/Validator/Symfony/Component/Validator/Tests/Constraints/IsbnValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Isbn;
use Symfony\Component\Validator\Constraints\IsbnValidator;

/**
 * @see https://en.wikipedia.org/wiki/Isbn
 */
class IsbnValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    public function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new IsbnValidator();
        $this->validator->initialize($this->context);
    }

    public function getValidIsbn10()
    {
        return array(
            array('2723442284'),
            array('2723442276'),
            array('2723455041'),
            array('2070546810'),
            array('2711858839'),
            array('2756406767'),
            array('2870971648'),
            array('226623854X'),
            array('2851806424'),
            array('0321812700'),
            array('0-45122-5244'),
            array('0-4712-92311'),
        );
    }

    public function getInvalidIsbn10()
    {
        return array(
            array('1234567890'),
            array('987'),
            array('0987656789'),
            array(0),
            array('7-35622-5444'),
            array('0-4X19-92611'),
            array('0_45122_5244'),
            array('2870#971#648'),
        );
    }

    public function getValidIsbn13()
    {
        return array(
            array('978-2723442282'),
            array('978-2723442275'),
            array('978-2723455046'),
            array('978-2070546817'),
            array('978-2711858835'),
            array('978-2756406763'),
            array('978-2870971642'),
            array('978-2266238540'),
            array('978-2851806420'),
            array('978-0321812704'),
            array('978-0451225245'),
            array('978-0471292319'),
        );
    }

    public function getInvalidIsbn13()
    {
        return array(
            array('1234567890'),
            array('987'),
            array('0987656789'),
            array(0),
            array('0-4X19-9261981'),
            array('978-0321513774'),
            array('979-0431225385'),
            array('980-0474292319'),
            array('978_0451225245'),
            array('978#0471292319'),
        );
    }

    public function getValidIsbn()
    {
        return array_merge(
            $this->getValidIsbn10(),
            $this->getValidIsbn13()
        );
    }

    public function getInvalidIsbn()
    {
        return array_merge(
            $this->getInvalidIsbn10(),
            $this->getInvalidIsbn13()
        );
    }

    public function testNullIsValid()
    {
        $constraint = new Isbn(true);
        $this->context
            ->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, $constraint);
    }

    public function testEmptyStringIsValid()
    {
        $constraint = new Isbn(true);
        $this->context
            ->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', $constraint);
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsStringCompatibleType()
    {
        $constraint = new Isbn(true);
        $this->validator->validate(new \stdClass(), $constraint);
    }

    /**
     * @dataProvider getValidIsbn10
     */
    public function testValidIsbn10($isbn)
    {
        $constraint = new Isbn(array('isbn10' => true));
        $this->context
            ->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($isbn, $constraint);
    }

    /**
     * @dataProvider getInvalidIsbn10
     */
    public function testInvalidIsbn10($isbn)
    {
        $constraint = new Isbn(array('isbn10' => true));
        $this->context
            ->expects($this->once())
            ->method('addViolation')
            ->with($constraint->isbn10Message);

        $this->validator->validate($isbn, $constraint);
    }

    /**
     * @dataProvider getValidIsbn13
     */
    public function testValidIsbn13($isbn)
    {
        $constraint = new Isbn(array('isbn13' => true));
        $this->context
            ->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($isbn, $constraint);
    }

    /**
     * @dataProvider getInvalidIsbn13
     */
    public function testInvalidIsbn13($isbn)
    {
        $constraint = new Isbn(array('isbn13' => true));
        $this->context
            ->expects($this->once())
            ->method('addViolation')
            ->with($constraint->isbn13Message);

        $this->validator->validate($isbn, $constraint);
    }

    /**
     * @dataProvider getValidIsbn
     */
    public function testValidIsbn($isbn)
    {
        $constraint = new Isbn(array('isbn10' => true, 'isbn13' => true));
        $this->context
            ->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($isbn, $constraint);
    }

    /**
     * @dataProvider getInvalidIsbn
     */
    public function testInvalidIsbn($isbn)
    {
        $constraint = new Isbn(array('isbn10' => true, 'isbn13' => true));
        $this->context
            ->expects($this->once())
            ->method('addViolation')
            ->with($constraint->bothIsbnMessage);

        $this->validator->validate($isbn, $constraint);
    }
}
PK��ZjTL�99Utest/Validator/Symfony/Component/Validator/Tests/Constraints/EqualToValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\EqualTo;
use Symfony\Component\Validator\Constraints\EqualToValidator;

/**
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class EqualToValidatorTest extends AbstractComparisonValidatorTestCase
{
    protected function createValidator()
    {
        return new EqualToValidator();
    }

    protected function createConstraint(array $options)
    {
        return new EqualTo($options);
    }

    /**
     * {@inheritDoc}
     */
    public function provideValidComparisons()
    {
        return array(
            array(3, 3),
            array(3, '3'),
            array('a', 'a'),
            array(new \DateTime('2000-01-01'), new \DateTime('2000-01-01')),
            array(new ComparisonTest_Class(5), new ComparisonTest_Class(5)),
            array(null, 1),
        );
    }

    /**
     * {@inheritDoc}
     */
    public function provideInvalidComparisons()
    {
        return array(
            array(1, 2, '2', 'integer'),
            array('22', '333', "'333'", 'string'),
            array(new \DateTime('2001-01-01'), new \DateTime('2000-01-01'), '2000-01-01 00:00:00', 'DateTime'),
            array(new ComparisonTest_Class(4), new ComparisonTest_Class(5), '5', __NAMESPACE__.'\ComparisonTest_Class'),
        );
    }
}
PK��Z�$&��Ytest/Validator/Symfony/Component/Validator/Tests/Constraints/IdenticalToValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\IdenticalTo;
use Symfony\Component\Validator\Constraints\IdenticalToValidator;

/**
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class IdenticalToValidatorTest extends AbstractComparisonValidatorTestCase
{
    protected function createValidator()
    {
        return new IdenticalToValidator();
    }

    protected function createConstraint(array $options)
    {
        return new IdenticalTo($options);
    }

    /**
     * {@inheritDoc}
     */
    public function provideValidComparisons()
    {
        $date = new \DateTime('2000-01-01');
        $object = new ComparisonTest_Class(2);

        return array(
            array(3, 3),
            array('a', 'a'),
            array($date, $date),
            array($object, $object),
            array(null, 1),
        );
    }

    /**
     * {@inheritDoc}
     */
    public function provideInvalidComparisons()
    {
        return array(
            array(1, 2, '2', 'integer'),
            array(2, '2', "'2'", 'string'),
            array('22', '333', "'333'", 'string'),
            array(new \DateTime('2001-01-01'), new \DateTime('2001-01-01'), '2001-01-01 00:00:00', 'DateTime'),
            array(new \DateTime('2001-01-01'), new \DateTime('1999-01-01'), '1999-01-01 00:00:00', 'DateTime'),
            array(new ComparisonTest_Class(4), new ComparisonTest_Class(5), '5', __NAMESPACE__.'\ComparisonTest_Class'),
        );
    }
}
PK��Z��|=��ctest/Validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorArrayObjectTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

class CollectionValidatorArrayObjectTest extends CollectionValidatorTest
{
    public function prepareTestData(array $contents)
    {
        return new \ArrayObject($contents);
    }
}
PK��Z�z0���Utest/Validator/Symfony/Component/Validator/Tests/Constraints/CountryValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Intl\Util\IntlTestHelper;
use Symfony\Component\Validator\Constraints\Country;
use Symfony\Component\Validator\Constraints\CountryValidator;

class CountryValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        IntlTestHelper::requireIntl($this);

        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new CountryValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Country());
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Country());
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsStringCompatibleType()
    {
        $this->validator->validate(new \stdClass(), new Country());
    }

    /**
     * @dataProvider getValidCountries
     */
    public function testValidCountries($country)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($country, new Country());
    }

    public function getValidCountries()
    {
        return array(
            array('GB'),
            array('AT'),
            array('MY'),
        );
    }

    /**
     * @dataProvider getInvalidCountries
     */
    public function testInvalidCountries($country)
    {
        $constraint = new Country(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $country,
            ));

        $this->validator->validate($country, $constraint);
    }

    public function getInvalidCountries()
    {
        return array(
            array('foobar'),
            array('EN'),
        );
    }

    public function testValidateUsingCountrySpecificLocale()
    {
        \Locale::setDefault('en_GB');
        $existingCountry = 'GB';
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($existingCountry, new Country());
    }
}
PK��Z�rZcc\test/Validator/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\NotIdenticalTo;
use Symfony\Component\Validator\Constraints\NotIdenticalToValidator;

/**
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class NotIdenticalToValidatorTest extends AbstractComparisonValidatorTestCase
{
    protected function createValidator()
    {
        return new NotIdenticalToValidator();
    }

    protected function createConstraint(array $options)
    {
        return new NotIdenticalTo($options);
    }

    /**
     * {@inheritDoc}
     */
    public function provideValidComparisons()
    {
        return array(
            array(1, 2),
            array('2', 2),
            array('22', '333'),
            array(new \DateTime('2001-01-01'), new \DateTime('2000-01-01')),
            array(new \DateTime('2000-01-01'), new \DateTime('2000-01-01')),
            array(null, 1),
        );
    }

    /**
     * {@inheritDoc}
     */
    public function provideInvalidComparisons()
    {
        $date = new \DateTime('2000-01-01');
        $object = new ComparisonTest_Class(2);

        return array(
            array(3, 3, '3', 'integer'),
            array('a', 'a', "'a'", 'string'),
            array($date, $date, '2000-01-01 00:00:00', 'DateTime'),
            array($object, $object, '2', __NAMESPACE__.'\ComparisonTest_Class'),
        );
    }
}
PK��Z�C��NNQtest/Validator/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Url;
use Symfony\Component\Validator\Constraints\UrlValidator;

class UrlValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new UrlValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Url());
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Url());
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsStringCompatibleType()
    {
        $this->validator->validate(new \stdClass(), new Url());
    }

    /**
     * @dataProvider getValidUrls
     */
    public function testValidUrls($url)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($url, new Url());
    }

    public function getValidUrls()
    {
        return array(
            array('http://a.pl'),
            array('http://www.google.com'),
            array('http://www.google.museum'),
            array('https://google.com/'),
            array('https://google.com:80/'),
            array('http://www.example.coop/'),
            array('http://www.test-example.com/'),
            array('http://www.symfony.com/'),
            array('http://symfony.fake/blog/'),
            array('http://symfony.com/?'),
            array('http://symfony.com/search?type=&q=url+validator'),
            array('http://symfony.com/#'),
            array('http://symfony.com/#?'),
            array('http://www.symfony.com/doc/current/book/validation.html#supported-constraints'),
            array('http://very.long.domain.name.com/'),
            array('http://127.0.0.1/'),
            array('http://127.0.0.1:80/'),
            array('http://[::1]/'),
            array('http://[::1]:80/'),
            array('http://[1:2:3::4:5:6:7]/'),
            array('http://sãopaulo.com/'),
            array('http://xn--sopaulo-xwa.com/'),
            array('http://sãopaulo.com.br/'),
            array('http://xn--sopaulo-xwa.com.br/'),
            array('http://пример.испытание/'),
            array('http://xn--e1afmkfd.xn--80akhbyknj4f/'),
            array('http://مثال.إختبار/'),
            array('http://xn--mgbh0fb.xn--kgbechtv/'),
            array('http://例子.测试/'),
            array('http://xn--fsqu00a.xn--0zwm56d/'),
            array('http://例子.測試/'),
            array('http://xn--fsqu00a.xn--g6w251d/'),
            array('http://例え.テスト/'),
            array('http://xn--r8jz45g.xn--zckzah/'),
            array('http://مثال.آزمایشی/'),
            array('http://xn--mgbh0fb.xn--hgbk6aj7f53bba/'),
            array('http://실례.테스트/'),
            array('http://xn--9n2bp8q.xn--9t4b11yi5a/'),
            array('http://العربية.idn.icann.org/'),
            array('http://xn--ogb.idn.icann.org/'),
            array('http://xn--e1afmkfd.xn--80akhbyknj4f.xn--e1afmkfd/'),
            array('http://xn--espaa-rta.xn--ca-ol-fsay5a/'),
            array('http://xn--d1abbgf6aiiy.xn--p1ai/'),
            array('http://☎.com/'),
        );
    }

    /**
     * @dataProvider getInvalidUrls
     */
    public function testInvalidUrls($url)
    {
        $constraint = new Url(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $url,
            ));

        $this->validator->validate($url, $constraint);
    }

    public function getInvalidUrls()
    {
        return array(
            array('google.com'),
            array('://google.com'),
            array('http ://google.com'),
            array('http:/google.com'),
            array('http://goog_le.com'),
            array('http://google.com::aa'),
            array('http://google.com:aa'),
            array('http://symfony.com?'),
            array('http://symfony.com#'),
            array('ftp://google.fr'),
            array('faked://google.fr'),
            array('http://127.0.0.1:aa/'),
            array('ftp://[::1]/'),
            array('http://[::1'),
        );
    }

    /**
     * @dataProvider getValidCustomUrls
     */
    public function testCustomProtocolIsValid($url)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = new Url(array(
            'protocols' => array('ftp', 'file', 'git')
        ));

        $this->validator->validate($url, $constraint);
    }

    public function getValidCustomUrls()
    {
        return array(
            array('ftp://google.com'),
            array('file://127.0.0.1'),
            array('git://[::1]/'),
        );
    }
}
PK��Z(�3��Jtest/Validator/Symfony/Component/Validator/Tests/Constraints/ValidTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Valid;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ValidTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testRejectGroupsOption()
    {
        new Valid(array('groups' => 'foo'));
    }
}
PK��Z���A��Vtest/Validator/Symfony/Component/Validator/Tests/Constraints/CurrencyValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Intl\Util\IntlTestHelper;
use Symfony\Component\Validator\Constraints\Currency;
use Symfony\Component\Validator\Constraints\CurrencyValidator;

class CurrencyValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        IntlTestHelper::requireIntl($this);

        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new CurrencyValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Currency());
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Currency());
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsStringCompatibleType()
    {
        $this->validator->validate(new \stdClass(), new Currency());
    }

    /**
     * @dataProvider getValidCurrencies
     */
    public function testValidCurrencies($currency)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($currency, new Currency());
    }

    /**
     * @dataProvider getValidCurrencies
     **/
    public function testValidCurrenciesWithCountrySpecificLocale($currency)
    {
        \Locale::setDefault('en_GB');
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($currency, new Currency());
    }

    public function getValidCurrencies()
    {
        return array(
            array('EUR'),
            array('USD'),
            array('SIT'),
            array('AUD'),
            array('CAD'),
        );
    }

    /**
     * @dataProvider getInvalidCurrencies
     */
    public function testInvalidCurrencies($currency)
    {
        $constraint = new Currency(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $currency,
            ));

        $this->validator->validate($currency, $constraint);
    }

    public function getInvalidCurrencies()
    {
        return array(
            array('EN'),
            array('foobar'),
        );
    }
}
PK��ZB����Htest/Validator/Symfony/Component/Validator/Tests/Constraints/AllTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\All;
use Symfony\Component\Validator\Constraints\Valid;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class AllTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testRejectNonConstraints()
    {
        new All(array(
            'foo',
        ));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testRejectValidConstraint()
    {
        new All(array(
            new Valid(),
        ));
    }
}
PK��Z�p�)D
D
Rtest/Validator/Symfony/Component/Validator/Tests/Constraints/LuhnValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Luhn;
use Symfony\Component\Validator\Constraints\LuhnValidator;

class LuhnValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new LuhnValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Luhn());
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Luhn());
    }

    /**
     * @dataProvider getValidNumbers
     */
    public function testValidNumbers($number)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($number, new Luhn());
    }

    public function getValidNumbers()
    {
        return array(
            array('42424242424242424242'),
            array('378282246310005'),
            array('371449635398431'),
            array('378734493671000'),
            array('5610591081018250'),
            array('30569309025904'),
            array('38520000023237'),
            array('6011111111111117'),
            array('6011000990139424'),
            array('3530111333300000'),
            array('3566002020360505'),
            array('5555555555554444'),
            array('5105105105105100'),
            array('4111111111111111'),
            array('4012888888881881'),
            array('4222222222222'),
            array('5019717010103742'),
            array('6331101999990016'),
        );
    }

    /**
     * @dataProvider getInvalidNumbers
     */
    public function testInvalidNumbers($number)
    {
        $constraint = new Luhn();

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with($constraint->message);

        $this->validator->validate($number, $constraint);
    }

    public function getInvalidNumbers()
    {
        return array(
            array('1234567812345678'),
            array('4222222222222222'),
            array('0000000000000000'),
        );
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     * @dataProvider getInvalidTypes
     */
    public function testInvalidTypes($number)
    {
        $constraint = new Luhn();

        $this->validator->validate($number, $constraint);
    }

    public function getInvalidTypes()
    {
        return array(
            array(0),
            array(123),
            array(42424242424242424242),
            array(378282246310005),
            array(371449635398431),
        );
    }
}
PK��Z��͸�Stest/Validator/Symfony/Component/Validator/Tests/Constraints/RangeValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Range;
use Symfony\Component\Validator\Constraints\RangeValidator;

class RangeValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new RangeValidator();
        $this->validator->initialize($this->context);
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Range(array('min' => 10, 'max' => 20)));
    }

    public function getTenToTwenty()
    {
        return array(
            array(10.00001),
            array(19.99999),
            array('10.00001'),
            array('19.99999'),
            array(10),
            array(20),
            array(10.0),
            array(20.0),
        );
    }

    public function getLessThanTen()
    {
        return array(
            array(9.99999),
            array('9.99999'),
            array(5),
            array(1.0),
        );
    }

    public function getMoreThanTwenty()
    {
        return array(
            array(20.000001),
            array('20.000001'),
            array(21),
            array(30.0),
        );
    }

    /**
     * @dataProvider getTenToTwenty
     */
    public function testValidValuesMin($value)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = new Range(array('min' => 10));
        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getTenToTwenty
     */
    public function testValidValuesMax($value)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = new Range(array('max' => 20));
        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getTenToTwenty
     */
    public function testValidValuesMinMax($value)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = new Range(array('min' => 10, 'max' => 20));
        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getLessThanTen
     */
    public function testInvalidValuesMin($value)
    {
        $constraint = new Range(array(
            'min' => 10,
            'minMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', $this->identicalTo(array(
                '{{ value }}' => $value,
                '{{ limit }}' => 10,
        )));

        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getMoreThanTwenty
     */
    public function testInvalidValuesMax($value)
    {
        $constraint = new Range(array(
            'max' => 20,
            'maxMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', $this->identicalTo(array(
                '{{ value }}' => $value,
                '{{ limit }}' => 20,
            )));

        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getMoreThanTwenty
     */
    public function testInvalidValuesCombinedMax($value)
    {
        $constraint = new Range(array(
            'min' => 10,
            'max' => 20,
            'minMessage' => 'myMinMessage',
            'maxMessage' => 'myMaxMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMaxMessage', $this->identicalTo(array(
                '{{ value }}' => $value,
                '{{ limit }}' => 20,
            )));

        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getLessThanTen
     */
    public function testInvalidValuesCombinedMin($value)
    {
        $constraint = new Range(array(
            'min' => 10,
            'max' => 20,
            'minMessage' => 'myMinMessage',
            'maxMessage' => 'myMaxMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMinMessage', $this->identicalTo(array(
            '{{ value }}' => $value,
            '{{ limit }}' => 10,
        )));

        $this->validator->validate($value, $constraint);
    }

    public function getInvalidValues()
    {
        return array(
            array(9.999999),
            array(20.000001),
            array('9.999999'),
            array('20.000001'),
            array(new \stdClass()),
        );
    }

    public function testMinMessageIsSet()
    {
        $constraint = new Range(array(
            'min' => 10,
            'max' => 20,
            'minMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => 9,
                '{{ limit }}' => 10,
            ));

        $this->validator->validate(9, $constraint);
    }

    public function testMaxMessageIsSet()
    {
        $constraint = new Range(array(
            'min' => 10,
            'max' => 20,
            'maxMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => 21,
                '{{ limit }}' => 20,
            ));

        $this->validator->validate(21, $constraint);
    }
}
PK��ZQ��s(s(Vtest/Validator/Symfony/Component/Validator/Tests/Constraints/CallbackValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\ExecutionContext;
use Symfony\Component\Validator\Constraints\Callback;
use Symfony\Component\Validator\Constraints\CallbackValidator;

class CallbackValidatorTest_Class
{
    public static function validateCallback($object, ExecutionContext $context)
    {
        $context->addViolation('Callback message', array('{{ value }}' => 'foobar'), 'invalidValue');

        return false;
    }
}

class CallbackValidatorTest_Object
{
    public function validate(ExecutionContext $context)
    {
        $context->addViolation('My message', array('{{ value }}' => 'foobar'), 'invalidValue');

        return false;
    }

    public static function validateStatic($object, ExecutionContext $context)
    {
        $context->addViolation('Static message', array('{{ value }}' => 'baz'), 'otherInvalidValue');

        return false;
    }
}

class CallbackValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new CallbackValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Callback(array('foo')));
    }

    public function testSingleMethod()
    {
        $object = new CallbackValidatorTest_Object();
        $constraint = new Callback('validate');

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('My message', array(
                '{{ value }}' => 'foobar',
            ));

        $this->validator->validate($object, $constraint);
    }

    public function testSingleMethodExplicitName()
    {
        $object = new CallbackValidatorTest_Object();
        $constraint = new Callback(array('callback' => 'validate'));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('My message', array(
                '{{ value }}' => 'foobar',
            ));

        $this->validator->validate($object, $constraint);
    }

    public function testSingleStaticMethod()
    {
        $object = new CallbackValidatorTest_Object();
        $constraint = new Callback('validateStatic');

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('Static message', array(
                '{{ value }}' => 'baz',
            ));

        $this->validator->validate($object, $constraint);
    }

    public function testClosure()
    {
        $object = new CallbackValidatorTest_Object();
        $constraint = new Callback(function ($object, ExecutionContext $context) {
            $context->addViolation('My message', array('{{ value }}' => 'foobar'), 'invalidValue');

            return false;
        });

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('My message', array(
                '{{ value }}' => 'foobar',
            ));

        $this->validator->validate($object, $constraint);
    }

    public function testClosureExplicitName()
    {
        $object = new CallbackValidatorTest_Object();
        $constraint = new Callback(array(
            'callback' => function ($object, ExecutionContext $context) {
                $context->addViolation('My message', array('{{ value }}' => 'foobar'), 'invalidValue');

                return false;
            },
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('My message', array(
                '{{ value }}' => 'foobar',
            ));

        $this->validator->validate($object, $constraint);
    }

    public function testArrayCallable()
    {
        $object = new CallbackValidatorTest_Object();
        $constraint = new Callback(array(__CLASS__.'_Class', 'validateCallback'));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('Callback message', array(
                '{{ value }}' => 'foobar',
            ));

        $this->validator->validate($object, $constraint);
    }

    public function testArrayCallableExplicitName()
    {
        $object = new CallbackValidatorTest_Object();
        $constraint = new Callback(array(
            'callback' => array(__CLASS__.'_Class', 'validateCallback'),
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('Callback message', array(
                '{{ value }}' => 'foobar',
            ));

        $this->validator->validate($object, $constraint);
    }

    // BC with Symfony < 2.4
    public function testSingleMethodBc()
    {
        $object = new CallbackValidatorTest_Object();
        $constraint = new Callback(array('validate'));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('My message', array(
                '{{ value }}' => 'foobar',
            ));

        $this->validator->validate($object, $constraint);
    }

    // BC with Symfony < 2.4
    public function testSingleMethodBcExplicitName()
    {
        $object = new CallbackValidatorTest_Object();
        $constraint = new Callback(array('methods' => array('validate')));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('My message', array(
                '{{ value }}' => 'foobar',
            ));

        $this->validator->validate($object, $constraint);
    }

    // BC with Symfony < 2.4
    public function testMultipleMethodsBc()
    {
        $object = new CallbackValidatorTest_Object();
        $constraint = new Callback(array('validate', 'validateStatic'));

        $this->context->expects($this->at(0))
            ->method('addViolation')
            ->with('My message', array(
                '{{ value }}' => 'foobar',
            ));
        $this->context->expects($this->at(1))
            ->method('addViolation')
            ->with('Static message', array(
                '{{ value }}' => 'baz',
            ));

        $this->validator->validate($object, $constraint);
    }

    // BC with Symfony < 2.4
    public function testMultipleMethodsBcExplicitName()
    {
        $object = new CallbackValidatorTest_Object();
        $constraint = new Callback(array(
            'methods' => array('validate', 'validateStatic'),
        ));

        $this->context->expects($this->at(0))
            ->method('addViolation')
            ->with('My message', array(
                '{{ value }}' => 'foobar',
            ));
        $this->context->expects($this->at(1))
            ->method('addViolation')
            ->with('Static message', array(
                '{{ value }}' => 'baz',
            ));

        $this->validator->validate($object, $constraint);
    }

    // BC with Symfony < 2.4
    public function testSingleStaticMethodBc()
    {
        $object = new CallbackValidatorTest_Object();
        $constraint = new Callback(array(
            array(__CLASS__.'_Class', 'validateCallback')
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('Callback message', array(
                '{{ value }}' => 'foobar',
            ));

        $this->validator->validate($object, $constraint);
    }

    // BC with Symfony < 2.4
    public function testSingleStaticMethodBcExplicitName()
    {
        $object = new CallbackValidatorTest_Object();
        $constraint = new Callback(array(
            'methods' => array(array(__CLASS__.'_Class', 'validateCallback')),
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('Callback message', array(
                '{{ value }}' => 'foobar',
            ));

        $this->validator->validate($object, $constraint);
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testExpectValidMethods()
    {
        $object = new CallbackValidatorTest_Object();

        $this->validator->validate($object, new Callback(array('foobar')));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testExpectValidCallbacks()
    {
        $object = new CallbackValidatorTest_Object();

        $this->validator->validate($object, new Callback(array(array('foo', 'bar'))));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testExpectEitherCallbackOrMethods()
    {
        $object = new CallbackValidatorTest_Object();

        $this->validator->validate($object, new Callback(array(
            'callback' => 'validate',
            'methods' => array('validateStatic'),
        )));
    }

    public function testConstraintGetTargets()
    {
        $constraint = new Callback(array('foo'));

        $this->assertEquals('class', $constraint->getTargets());
    }

    // Should succeed. Needed when defining constraints as annotations.
    public function testNoConstructorArguments()
    {
        new Callback();
    }

    public function testAnnotationInvocationSingleValued()
    {
        $constraint = new Callback(array('value' => 'validateStatic'));

        $this->assertEquals(new Callback('validateStatic'), $constraint);
    }

    public function testAnnotationInvocationMultiValued()
    {
        $constraint = new Callback(array('value' => array(__CLASS__.'_Class', 'validateCallback')));

        $this->assertEquals(new Callback(array(__CLASS__.'_Class', 'validateCallback')), $constraint);
    }
}
PK��Z@*�VHHRtest/Validator/Symfony/Component/Validator/Tests/Constraints/DateValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Date;
use Symfony\Component\Validator\Constraints\DateValidator;

class DateValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new DateValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Date());
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Date());
    }

    public function testDateTimeClassIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(new \DateTime(), new Date());
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsStringCompatibleType()
    {
        $this->validator->validate(new \stdClass(), new Date());
    }

    /**
     * @dataProvider getValidDates
     */
    public function testValidDates($date)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($date, new Date());
    }

    public function getValidDates()
    {
        return array(
            array('2010-01-01'),
            array('1955-12-12'),
            array('2030-05-31'),
        );
    }

    /**
     * @dataProvider getInvalidDates
     */
    public function testInvalidDates($date)
    {
        $constraint = new Date(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $date,
            ));

        $this->validator->validate($date, $constraint);
    }

    public function getInvalidDates()
    {
        return array(
            array('foobar'),
            array('foobar 2010-13-01'),
            array('2010-13-01 foobar'),
            array('2010-13-01'),
            array('2010-04-32'),
            array('2010-02-29'),
        );
    }
}
PK��Z�� BTTRtest/Validator/Symfony/Component/Validator/Tests/Constraints/TimeValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Time;
use Symfony\Component\Validator\Constraints\TimeValidator;

class TimeValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new TimeValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Time());
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Time());
    }

    public function testDateTimeClassIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(new \DateTime(), new Time());
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsStringCompatibleType()
    {
        $this->validator->validate(new \stdClass(), new Time());
    }

    /**
     * @dataProvider getValidTimes
     */
    public function testValidTimes($time)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($time, new Time());
    }

    public function getValidTimes()
    {
        return array(
            array('01:02:03'),
            array('00:00:00'),
            array('23:59:59'),
        );
    }

    /**
     * @dataProvider getInvalidTimes
     */
    public function testInvalidTimes($time)
    {
        $constraint = new Time(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $time,
            ));

        $this->validator->validate($time, $constraint);
    }

    public function getInvalidTimes()
    {
        return array(
            array('foobar'),
            array('foobar 12:34:56'),
            array('12:34:56 foobar'),
            array('00:00'),
            array('24:00:00'),
            array('00:60:00'),
            array('00:00:60'),
        );
    }
}
PK��Z�i�KKStest/Validator/Symfony/Component/Validator/Tests/Constraints/FalseValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\False;
use Symfony\Component\Validator\Constraints\FalseValidator;

class FalseValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new FalseValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new False());
    }

    public function testFalseIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(false, new False());
    }

    public function testTrueIsInvalid()
    {
        $constraint = new False(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array());

        $this->validator->validate(true, $constraint);
    }
}
PK��ZϏ�R��Xtest/Validator/Symfony/Component/Validator/Tests/Constraints/CountValidatorArrayTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class CountValidatorArrayTest extends CountValidatorTest
{
    protected function createCollection(array $content)
    {
        return $content;
    }
}
PK��ZqC����Vtest/Validator/Symfony/Component/Validator/Tests/Constraints/LanguageValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Intl\Util\IntlTestHelper;
use Symfony\Component\Validator\Constraints\Language;
use Symfony\Component\Validator\Constraints\LanguageValidator;

class LanguageValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        IntlTestHelper::requireIntl($this);

        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new LanguageValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Language());
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Language());
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsStringCompatibleType()
    {
        $this->validator->validate(new \stdClass(), new Language());
    }

    /**
     * @dataProvider getValidLanguages
     */
    public function testValidLanguages($language)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($language, new Language());
    }

    public function getValidLanguages()
    {
        return array(
            array('en'),
            array('en_US'),
            array('my'),
        );
    }

    /**
     * @dataProvider getInvalidLanguages
     */
    public function testInvalidLanguages($language)
    {
        $constraint = new Language(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $language,
            ));

        $this->validator->validate($language, $constraint);
    }

    public function getInvalidLanguages()
    {
        return array(
            array('EN'),
            array('foobar'),
        );
    }

    public function testValidateUsingCountrySpecificLocale()
    {
        \Locale::setDefault('fr_FR');
        $existingLanguage = 'en';
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($existingLanguage, new Language(array(
            'message' => 'aMessage'
        )));
    }
}
PK��Zֆ���Stest/Validator/Symfony/Component/Validator/Tests/Constraints/CountValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Count;
use Symfony\Component\Validator\Constraints\CountValidator;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
abstract class CountValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new CountValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    abstract protected function createCollection(array $content);

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Count(6));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsCountableType()
    {
        $this->validator->validate(new \stdClass(), new Count(5));
    }

    public function getThreeOrLessElements()
    {
        return array(
            array($this->createCollection(array(1))),
            array($this->createCollection(array(1, 2))),
            array($this->createCollection(array(1, 2, 3))),
            array($this->createCollection(array('a' => 1, 'b' => 2, 'c' => 3))),
        );
    }

    public function getFourElements()
    {
        return array(
            array($this->createCollection(array(1, 2, 3, 4))),
            array($this->createCollection(array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4))),
        );
    }

    public function getNotFourElements()
    {
        return array_merge(
            $this->getThreeOrLessElements(),
            $this->getFiveOrMoreElements()
        );
    }

    public function getFiveOrMoreElements()
    {
        return array(
            array($this->createCollection(array(1, 2, 3, 4, 5))),
            array($this->createCollection(array(1, 2, 3, 4, 5, 6))),
            array($this->createCollection(array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5))),
        );
    }

    /**
     * @dataProvider getThreeOrLessElements
     */
    public function testValidValuesMax($value)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = new Count(array('max' => 3));
        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getFiveOrMoreElements
     */
    public function testValidValuesMin($value)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = new Count(array('min' => 5));
        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getFourElements
     */
    public function testValidValuesExact($value)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = new Count(4);
        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getFiveOrMoreElements
     */
    public function testInvalidValuesMax($value)
    {
        $constraint = new Count(array(
            'max' => 4,
            'maxMessage' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', $this->identicalTo(array(
                '{{ count }}' => count($value),
                '{{ limit }}' => 4,
            )), $value, 4);

        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getThreeOrLessElements
     */
    public function testInvalidValuesMin($value)
    {
        $constraint = new Count(array(
            'min' => 4,
            'minMessage' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', $this->identicalTo(array(
                '{{ count }}' => count($value),
                '{{ limit }}' => 4,
            )), $value, 4);

        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getNotFourElements
     */
    public function testInvalidValuesExact($value)
    {
        $constraint = new Count(array(
            'min' => 4,
            'max' => 4,
            'exactMessage' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', $this->identicalTo(array(
            '{{ count }}' => count($value),
            '{{ limit }}' => 4,
        )), $value, 4);

        $this->validator->validate($value, $constraint);
    }

    public function testDefaultOption()
    {
        $constraint = new Count(5);

        $this->assertEquals(5, $constraint->min);
        $this->assertEquals(5, $constraint->max);
    }
}
PK��Z��LwwYtest/Validator/Symfony/Component/Validator/Tests/Constraints/GreaterThanValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\GreaterThan;
use Symfony\Component\Validator\Constraints\GreaterThanValidator;

/**
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class GreaterThanValidatorTest extends AbstractComparisonValidatorTestCase
{
    protected function createValidator()
    {
        return new GreaterThanValidator();
    }

    protected function createConstraint(array $options)
    {
        return new GreaterThan($options);
    }

    /**
     * {@inheritDoc}
     */
    public function provideValidComparisons()
    {
        return array(
            array(2, 1),
            array(new \DateTime('2005/01/01'), new \DateTime('2001/01/01')),
            array(new ComparisonTest_Class(5), new ComparisonTest_Class(4)),
            array('333', '22'),
            array(null, 1),
        );
    }

    /**
     * {@inheritDoc}
     */
    public function provideInvalidComparisons()
    {
        return array(
            array(1, 2, '2', 'integer'),
            array(2, 2, '2', 'integer'),
            array(new \DateTime('2000/01/01'), new \DateTime('2005/01/01'), '2005-01-01 00:00:00', 'DateTime'),
            array(new \DateTime('2000/01/01'), new \DateTime('2000/01/01'), '2000-01-01 00:00:00', 'DateTime'),
            array(new ComparisonTest_Class(4), new ComparisonTest_Class(5), '5', __NAMESPACE__.'\ComparisonTest_Class'),
            array(new ComparisonTest_Class(5), new ComparisonTest_Class(5), '5', __NAMESPACE__.'\ComparisonTest_Class'),
            array('22', '333', "'333'", 'string'),
            array('22', '22', "'22'", 'string')
        );
    }
}
PK��Z���kkVtest/Validator/Symfony/Component/Validator/Tests/Constraints/FileValidatorPathTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\File;

class FileValidatorPathTest extends FileValidatorTest
{
    protected function getFile($filename)
    {
        return $filename;
    }

    public function testFileNotFound()
    {
        $constraint = new File(array(
            'notFoundMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ file }}' => 'foobar',
            ));

        $this->validator->validate('foobar', $constraint);
    }
}
PK��Z׫��`test/Validator/Symfony/Component/Validator/Tests/Constraints/GreaterThanOrEqualValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\GreaterThanOrEqual;
use Symfony\Component\Validator\Constraints\GreaterThanOrEqualValidator;

/**
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class GreaterThanOrEqualValidatorTest extends AbstractComparisonValidatorTestCase
{
    protected function createValidator()
    {
        return new GreaterThanOrEqualValidator();
    }

    protected function createConstraint(array $options)
    {
        return new GreaterThanOrEqual($options);
    }

    /**
     * {@inheritDoc}
     */
    public function provideValidComparisons()
    {
        return array(
            array(3, 2),
            array(1, 1),
            array(new \DateTime('2010/01/01'), new \DateTime('2000/01/01')),
            array(new \DateTime('2000/01/01'), new \DateTime('2000/01/01')),
            array('a', 'a'),
            array('z', 'a'),
            array(null, 1),
        );
    }

    /**
     * {@inheritDoc}
     */
    public function provideInvalidComparisons()
    {
        return array(
            array(1, 2, '2', 'integer'),
            array(new \DateTime('2000/01/01'), new \DateTime('2005/01/01'), '2005-01-01 00:00:00', 'DateTime'),
            array('b', 'c', "'c'", 'string')
        );
    }
}
PK��ZW�@� � Rtest/Validator/Symfony/Component/Validator/Tests/Constraints/IbanValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Iban;
use Symfony\Component\Validator\Constraints\IbanValidator;

class IbanValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new IbanValidator();
        $this->validator->initialize($this->context);
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())->method('addViolation');

        $this->validator->validate(null, new Iban());
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())->method('addViolation');

        $this->validator->validate('', new Iban());
    }

    /**
     * @dataProvider getValidIbans
     */
    public function testValidIbans($iban)
    {
        $this->context->expects($this->never())->method('addViolation');

        $this->validator->validate($iban, new Iban());
    }

    public function getValidIbans()
    {
        return array(
            array('CH9300762011623852957'), // Switzerland without spaces

            //Country list
            //http://www.rbs.co.uk/corporate/international/g0/guide-to-international-business/regulatory-information/iban/iban-example.ashx

            array('AL47 2121 1009 0000 0002 3569 8741'), //Albania
            array('AD12 0001 2030 2003 5910 0100'), //Andorra
            array('AT61 1904 3002 3457 3201'), //Austria
            array('AZ21 NABZ 0000 0000 1370 1000 1944'), //Azerbaijan
            array('BH67 BMAG 0000 1299 1234 56'), //Bahrain
            array('BE62 5100 0754 7061'), //Belgium
            array('BA39 1290 0794 0102 8494'), //Bosnia and Herzegovina
            array('BG80 BNBG 9661 1020 3456 78'), //Bulgaria
            array('HR12 1001 0051 8630 0016 0'), //Croatia
            array('CY17 0020 0128 0000 0012 0052 7600'), //Cyprus
            array('CZ65 0800 0000 1920 0014 5399'), //Czech Republic
            array('DK50 0040 0440 1162 43'), //Denmark
            array('EE38 2200 2210 2014 5685'), //Estonia
            array('FO97 5432 0388 8999 44'), //Faroe Islands
            array('FI21 1234 5600 0007 85'), //Finland
            array('FR14 2004 1010 0505 0001 3M02 606'), //France
            array('GE29 NB00 0000 0101 9049 17'), //Georgia
            array('DE89 3704 0044 0532 0130 00'), //Germany
            array('GI75 NWBK 0000 0000 7099 453'), //Gibraltar
            array('GR16 0110 1250 0000 0001 2300 695'), //Greece
            array('GL56 0444 9876 5432 10'), //Greenland
            array('HU42 1177 3016 1111 1018 0000 0000'), //Hungary
            array('IS14 0159 2600 7654 5510 7303 39'), //Iceland
            array('IE29 AIBK 9311 5212 3456 78'), //Ireland
            array('IL62 0108 0000 0009 9999 999'), //Israel
            array('IT40 S054 2811 1010 0000 0123 456'), //Italy
            array('LV80 BANK 0000 4351 9500 1'), //Latvia
            array('LB62 0999 0000 0001 0019 0122 9114'), //Lebanon
            array('LI21 0881 0000 2324 013A A'), //Liechtenstein
            array('LT12 1000 0111 0100 1000'), //Lithuania
            array('LU28 0019 4006 4475 0000'), //Luxembourg
            array('MK072 5012 0000 0589 84'), //Macedonia
            array('MT84 MALT 0110 0001 2345 MTLC AST0 01S'), //Malta
            array('MU17 BOMM 0101 1010 3030 0200 000M UR'), //Mauritius
            array('MD24 AG00 0225 1000 1310 4168'), //Moldova
            array('MC93 2005 2222 1001 1223 3M44 555'), //Monaco
            array('ME25 5050 0001 2345 6789 51'), //Montenegro
            array('NL39 RABO 0300 0652 64'), //Netherlands
            array('NO93 8601 1117 947'), //Norway
            array('PK36 SCBL 0000 0011 2345 6702'), //Pakistan
            array('PL60 1020 1026 0000 0422 7020 1111'), //Poland
            array('PT50 0002 0123 1234 5678 9015 4'), //Portugal
            array('RO49 AAAA 1B31 0075 9384 0000'), //Romania
            array('SM86 U032 2509 8000 0000 0270 100'), //San Marino
            array('SA03 8000 0000 6080 1016 7519'), //Saudi Arabia
            array('RS35 2600 0560 1001 6113 79'), //Serbia
            array('SK31 1200 0000 1987 4263 7541'), //Slovak Republic
            array('SI56 1910 0000 0123 438'), //Slovenia
            array('ES80 2310 0001 1800 0001 2345'), //Spain
            array('SE35 5000 0000 0549 1000 0003'), //Sweden
            array('CH93 0076 2011 6238 5295 7'), //Switzerland
            array('TN59 1000 6035 1835 9847 8831'), //Tunisia
            array('TR33 0006 1005 1978 6457 8413 26'), //Turkey
            array('AE07 0331 2345 6789 0123 456'), //UAE
            array('GB 12 CPBK 0892 9965 0449 91'), //United Kingdom

            //Extended country list
            //http://www.nordea.com/Our+services/International+products+and+services/Cash+Management/IBAN+countries/908462.html
            array('AO06000600000100037131174'), //Angola
            array('AZ21NABZ00000000137010001944'), //Azerbaijan
            array('BH29BMAG1299123456BH00'), //Bahrain
            array('BJ11B00610100400271101192591'), //Benin
            array('VG96VPVG0000012345678901'), //British Virgin Islands
            array('BF1030134020015400945000643'), //Burkina Faso
            array('BI43201011067444'), //Burundi
            array('CM2110003001000500000605306'), //Cameroon
            array('CV64000300004547069110176'), //Cape Verde
            array('FR7630007000110009970004942'), //Central African Republic
            array('CG5230011000202151234567890'), //Congo
            array('CR0515202001026284066'), //Costa Rica
            array('DO28BAGR00000001212453611324'), //Dominican Republic
            array('GT82TRAJ01020000001210029690'), //Guatemala
            array('IR580540105180021273113007'), //Iran
            array('IL620108000000099999999'), //Israel
            array('CI05A00060174100178530011852'), //Ivory Coast
            array('KZ176010251000042993'), //Kazakhstan
            array('KW74NBOK0000000000001000372151'), //Kuwait
            array('LB30099900000001001925579115'), //Lebanon
            array('MG4600005030010101914016056'), //Madagascar
            array('ML03D00890170001002120000447'), //Mali
            array('MR1300012000010000002037372'), //Mauritania
            array('MU17BOMM0101101030300200000MUR'), //Mauritius
            array('MZ59000100000011834194157'), //Mozambique
            array('PS92PALS000000000400123456702'), //Palestinian Territory
            array('PT50000200000163099310355'), //Sao Tome and Principe
            array('SA0380000000608010167519'), //Saudi Arabia
            array('SN12K00100152000025690007542'), //Senegal
            array('TN5914207207100707129648'), //Tunisia
            array('TR330006100519786457841326'), //Turkey
            array('AE260211000000230064016'), //United Arab Emirates
        );
    }

    /**
     * @dataProvider getInvalidIbans
     */
    public function testInvalidIbans($iban)
    {
        $constraint = new Iban(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $iban,
            ));

        $this->validator->validate($iban, $constraint);
    }

    public function getInvalidIbans()
    {
        return array(
            array('CH93 0076 2011 6238 5295'),
            array('CH930076201162385295'),
            array('GB29 RBOS 6016 1331 9268 19'),
            array('CH930072011623852957'),
            array('NL39 RASO 0300 0652 64'),
            array('NO93 8601117 947'),
            array('CY170020 128 0000 0012 0052 7600'),
            array('foo'),
            array('123'),
            array('0750447346'),

            //Ibans with lower case values are invalid
            array('Ae260211000000230064016'),
            array('ae260211000000230064016')
        );
    }
}
PK��Z�y7{==Rtest/Validator/Symfony/Component/Validator/Tests/Constraints/TypeValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Type;
use Symfony\Component\Validator\Constraints\TypeValidator;

class TypeValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected static $file;

    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new TypeValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Type(array('type' => 'integer')));
    }

    public function testEmptyIsValidIfString()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Type(array('type' => 'string')));
    }

    public function testEmptyIsInvalidIfNoString()
    {
        $this->context->expects($this->once())
            ->method('addViolation');

        $this->validator->validate('', new Type(array('type' => 'integer')));
    }

    /**
     * @dataProvider getValidValues
     */
    public function testValidValues($value, $type)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = new Type(array('type' => $type));

        $this->validator->validate($value, $constraint);
    }

    public function getValidValues()
    {
        $object = new \stdClass();
        $file = $this->createFile();

        return array(
            array(true, 'Boolean'),
            array(false, 'Boolean'),
            array(true, 'boolean'),
            array(false, 'boolean'),
            array(true, 'bool'),
            array(false, 'bool'),
            array(0, 'numeric'),
            array('0', 'numeric'),
            array(1.5, 'numeric'),
            array('1.5', 'numeric'),
            array(0, 'integer'),
            array(1.5, 'float'),
            array('12345', 'string'),
            array(array(), 'array'),
            array($object, 'object'),
            array($object, 'stdClass'),
            array($file, 'resource'),
            array('12345', 'digit'),
            array('12a34', 'alnum'),
            array('abcde', 'alpha'),
            array("\n\r\t", 'cntrl'),
            array('arf12', 'graph'),
            array('abcde', 'lower'),
            array('ABCDE', 'upper'),
            array('arf12', 'print'),
            array('*&$()', 'punct'),
            array("\n\r\t", 'space'),
            array('AB10BC99', 'xdigit'),
        );
    }

    /**
     * @dataProvider getInvalidValues
     */
    public function testInvalidValues($value, $type, $valueAsString)
    {
        $constraint = new Type(array(
            'type' => $type,
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $valueAsString,
                '{{ type }}' => $type,
            ));

        $this->validator->validate($value, $constraint);
    }

    public function getInvalidValues()
    {
        $object = new \stdClass();
        $file = $this->createFile();

        return array(
            array('foobar', 'numeric', 'foobar'),
            array('foobar', 'boolean', 'foobar'),
            array('0', 'integer', '0'),
            array('1.5', 'float', '1.5'),
            array(12345, 'string', '12345'),
            array($object, 'boolean', 'stdClass'),
            array($object, 'numeric', 'stdClass'),
            array($object, 'integer', 'stdClass'),
            array($object, 'float', 'stdClass'),
            array($object, 'string', 'stdClass'),
            array($object, 'resource', 'stdClass'),
            array($file, 'boolean', (string) $file),
            array($file, 'numeric', (string) $file),
            array($file, 'integer', (string) $file),
            array($file, 'float', (string) $file),
            array($file, 'string', (string) $file),
            array($file, 'object', (string) $file),
            array('12a34', 'digit', '12a34'),
            array('1a#23', 'alnum', '1a#23'),
            array('abcd1', 'alpha', 'abcd1'),
            array("\nabc", 'cntrl', "\nabc"),
            array("abc\n", 'graph', "abc\n"),
            array('abCDE', 'lower', 'abCDE'),
            array('ABcde', 'upper', 'ABcde'),
            array("\nabc", 'print', "\nabc"),
            array('abc&$!', 'punct', 'abc&$!'),
            array("\nabc", 'space', "\nabc"),
            array('AR1012', 'xdigit', 'AR1012'),
        );
    }

    protected function createFile()
    {
        if (!self::$file) {
            self::$file = fopen(__FILE__, 'r');
        }

        return self::$file;
    }

    public static function tearDownAfterClass()
    {
        if (self::$file) {
            fclose(self::$file);
        }
    }
}
PK��Z\z?�+�+Xtest/Validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Range;
use Symfony\Component\Validator\Constraints\NotNull;
use Symfony\Component\Validator\Constraints\Required;
use Symfony\Component\Validator\Constraints\Optional;
use Symfony\Component\Validator\Constraints\Collection;
use Symfony\Component\Validator\Constraints\CollectionValidator;

abstract class CollectionValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new CollectionValidator();
        $this->validator->initialize($this->context);

        $this->context->expects($this->any())
            ->method('getGroup')
            ->will($this->returnValue('MyGroup'));
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    abstract protected function prepareTestData(array $contents);

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolationAt');

        $this->validator->validate(null, new Collection(array('fields' => array(
            'foo' => new Range(array('min' => 4)),
        ))));
    }

    public function testFieldsAsDefaultOption()
    {
        $data = $this->prepareTestData(array('foo' => 'foobar'));

        $this->context->expects($this->never())
            ->method('addViolationAt');

        $this->validator->validate($data, new Collection(array(
            'foo' => new Range(array('min' => 4)),
        )));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testThrowsExceptionIfNotTraversable()
    {
        $this->validator->validate('foobar', new Collection(array('fields' => array(
            'foo' => new Range(array('min' => 4)),
        ))));
    }

    public function testWalkSingleConstraint()
    {
        $constraint = new Range(array('min' => 4));

        $array = array(
            'foo' => 3,
            'bar' => 5,
        );
        $i = 1;

        foreach ($array as $key => $value) {
            $this->context->expects($this->at($i++))
                ->method('validateValue')
                ->with($value, $constraint, '['.$key.']', 'MyGroup');
        }

        $data = $this->prepareTestData($array);

        $this->context->expects($this->never())
            ->method('addViolationAt');

        $this->validator->validate($data, new Collection(array(
            'fields' => array(
                'foo' => $constraint,
                'bar' => $constraint,
            ),
        )));
    }

    public function testWalkMultipleConstraints()
    {
        $constraints = array(
            new Range(array('min' => 4)),
            new NotNull(),
        );

        $array = array(
            'foo' => 3,
            'bar' => 5,
        );
        $i = 1;

        foreach ($array as $key => $value) {
            foreach ($constraints as $constraint) {
                $this->context->expects($this->at($i++))
                    ->method('validateValue')
                    ->with($value, $constraint, '['.$key.']', 'MyGroup');
            }
        }

        $data = $this->prepareTestData($array);

        $this->context->expects($this->never())
            ->method('addViolationAt');

        $this->validator->validate($data, new Collection(array(
            'fields' => array(
                'foo' => $constraints,
                'bar' => $constraints,
            )
        )));
    }

    public function testExtraFieldsDisallowed()
    {
        $data = $this->prepareTestData(array(
            'foo' => 5,
            'baz' => 6,
        ));

        $this->context->expects($this->once())
            ->method('addViolationAt')
            ->with('[baz]', 'myMessage', array(
                '{{ field }}' => 'baz'
            ));

        $this->validator->validate($data, new Collection(array(
            'fields' => array(
                'foo' => new Range(array('min' => 4)),
            ),
            'extraFieldsMessage' => 'myMessage',
        )));
    }

    // bug fix
    public function testNullNotConsideredExtraField()
    {
        $data = $this->prepareTestData(array(
            'foo' => null,
        ));

        $constraint = new Collection(array(
            'fields' => array(
                'foo' => new Range(array('min' => 4)),
            ),
        ));

        $this->context->expects($this->never())
            ->method('addViolationAt');

        $this->validator->validate($data, $constraint);
    }

    public function testExtraFieldsAllowed()
    {
        $data = $this->prepareTestData(array(
            'foo' => 5,
            'bar' => 6,
        ));

        $constraint = new Collection(array(
            'fields' => array(
                'foo' => new Range(array('min' => 4)),
            ),
            'allowExtraFields' => true,
        ));

        $this->context->expects($this->never())
            ->method('addViolationAt');

        $this->validator->validate($data, $constraint);
    }

    public function testMissingFieldsDisallowed()
    {
        $data = $this->prepareTestData(array());

        $constraint = new Collection(array(
            'fields' => array(
                'foo' => new Range(array('min' => 4)),
            ),
            'missingFieldsMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolationAt')
            ->with('[foo]', 'myMessage', array(
                '{{ field }}' => 'foo',
            ));

        $this->validator->validate($data, $constraint);
    }

    public function testMissingFieldsAllowed()
    {
        $data = $this->prepareTestData(array());

        $constraint = new Collection(array(
            'fields' => array(
                'foo' => new Range(array('min' => 4)),
            ),
            'allowMissingFields' => true,
        ));

        $this->context->expects($this->never())
            ->method('addViolationAt');

        $this->validator->validate($data, $constraint);
    }

    public function testOptionalFieldPresent()
    {
        $data = $this->prepareTestData(array(
            'foo' => null,
        ));

        $this->context->expects($this->never())
            ->method('addViolationAt');

        $this->validator->validate($data, new Collection(array(
            'foo' => new Optional(),
        )));
    }

    public function testOptionalFieldNotPresent()
    {
        $data = $this->prepareTestData(array());

        $this->context->expects($this->never())
            ->method('addViolationAt');

        $this->validator->validate($data, new Collection(array(
            'foo' => new Optional(),
        )));
    }

    public function testOptionalFieldSingleConstraint()
    {
        $array = array(
            'foo' => 5,
        );

        $constraint = new Range(array('min' => 4));

        $this->context->expects($this->once())
            ->method('validateValue')
            ->with($array['foo'], $constraint, '[foo]', 'MyGroup');

        $this->context->expects($this->never())
            ->method('addViolationAt');

        $data = $this->prepareTestData($array);

        $this->validator->validate($data, new Collection(array(
            'foo' => new Optional($constraint),
        )));
    }

    public function testOptionalFieldMultipleConstraints()
    {
        $array = array(
            'foo' => 5,
        );

        $constraints = array(
            new NotNull(),
            new Range(array('min' => 4)),
        );
        $i = 1;

        foreach ($constraints as $constraint) {
            $this->context->expects($this->at($i++))
                ->method('validateValue')
                ->with($array['foo'], $constraint, '[foo]', 'MyGroup');
        }

        $this->context->expects($this->never())
            ->method('addViolationAt');

        $data = $this->prepareTestData($array);

        $this->validator->validate($data, new Collection(array(
            'foo' => new Optional($constraints),
        )));
    }

    public function testRequiredFieldPresent()
    {
        $data = $this->prepareTestData(array(
            'foo' => null,
        ));

        $this->context->expects($this->never())
            ->method('addViolationAt');

        $this->validator->validate($data, new Collection(array(
            'foo' => new Required(),
        )));
    }

    public function testRequiredFieldNotPresent()
    {
        $data = $this->prepareTestData(array());

        $this->context->expects($this->once())
            ->method('addViolationAt')
            ->with('[foo]', 'myMessage', array(
                '{{ field }}' => 'foo',
            ));

        $this->validator->validate($data, new Collection(array(
            'fields' => array(
                'foo' => new Required(),
            ),
            'missingFieldsMessage' => 'myMessage',
        )));
    }

    public function testRequiredFieldSingleConstraint()
    {
        $array = array(
            'foo' => 5,
        );

        $constraint = new Range(array('min' => 4));

        $this->context->expects($this->once())
            ->method('validateValue')
            ->with($array['foo'], $constraint, '[foo]', 'MyGroup');

        $this->context->expects($this->never())
            ->method('addViolationAt');

        $data = $this->prepareTestData($array);

        $this->validator->validate($data, new Collection(array(
            'foo' => new Required($constraint),
        )));
    }

    public function testRequiredFieldMultipleConstraints()
    {
        $array = array(
            'foo' => 5,
        );

        $constraints = array(
            new NotNull(),
            new Range(array('min' => 4)),
        );
        $i = 1;

        foreach ($constraints as $constraint) {
            $this->context->expects($this->at($i++))
                ->method('validateValue')
                ->with($array['foo'], $constraint, '[foo]', 'MyGroup');
        }

        $this->context->expects($this->never())
            ->method('addViolationAt');

        $data = $this->prepareTestData($array);

        $this->validator->validate($array, new Collection(array(
            'foo' => new Required($constraints),
        )));
    }

    public function testObjectShouldBeLeftUnchanged()
    {
        $value = new \ArrayObject(array(
            'foo' => 3
        ));

        $this->validator->validate($value, new Collection(array(
            'fields' => array(
                'foo' => new Range(array('min' => 2)),
            )
        )));

        $this->assertEquals(array(
            'foo' => 3
        ), (array) $value);
    }
}
PK��ZC���77Vtest/Validator/Symfony/Component/Validator/Tests/Constraints/LessThanValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\LessThan;
use Symfony\Component\Validator\Constraints\LessThanValidator;

/**
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class LessThanValidatorTest extends AbstractComparisonValidatorTestCase
{
    protected function createValidator()
    {
        return new LessThanValidator();
    }

    protected function createConstraint(array $options)
    {
        return new LessThan($options);
    }

    /**
     * {@inheritDoc}
     */
    public function provideValidComparisons()
    {
        return array(
            array(1, 2),
            array(new \DateTime('2000-01-01'), new \DateTime('2010-01-01')),
            array(new ComparisonTest_Class(4), new ComparisonTest_Class(5)),
            array('22', '333'),
            array(null, 1),
        );
    }

    /**
     * {@inheritDoc}
     */
    public function provideInvalidComparisons()
    {
        return array(
            array(3, 2, '2', 'integer'),
            array(2, 2, '2', 'integer'),
            array(new \DateTime('2010-01-01'), new \DateTime('2000-01-01'), '2000-01-01 00:00:00', 'DateTime'),
            array(new \DateTime('2000-01-01'), new \DateTime('2000-01-01'), '2000-01-01 00:00:00', 'DateTime'),
            array(new ComparisonTest_Class(5), new ComparisonTest_Class(5), '5', __NAMESPACE__.'\ComparisonTest_Class'),
            array(new ComparisonTest_Class(6), new ComparisonTest_Class(5), '5', __NAMESPACE__.'\ComparisonTest_Class'),
            array('333', '22', "'22'", 'string'),
        );
    }
}
PK��Zb���ggVtest/Validator/Symfony/Component/Validator/Tests/Constraints/DateTimeValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\DateTime;
use Symfony\Component\Validator\Constraints\DateTimeValidator;

class DateTimeValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new DateTimeValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new DateTime());
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new DateTime());
    }

    public function testDateTimeClassIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(new \DateTime(), new DateTime());
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsStringCompatibleType()
    {
        $this->validator->validate(new \stdClass(), new DateTime());
    }

    /**
     * @dataProvider getValidDateTimes
     */
    public function testValidDateTimes($dateTime)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($dateTime, new DateTime());
    }

    public function getValidDateTimes()
    {
        return array(
            array('2010-01-01 01:02:03'),
            array('1955-12-12 00:00:00'),
            array('2030-05-31 23:59:59'),
        );
    }

    /**
     * @dataProvider getInvalidDateTimes
     */
    public function testInvalidDateTimes($dateTime)
    {
        $constraint = new DateTime(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $dateTime,
            ));

        $this->validator->validate($dateTime, $constraint);
    }

    public function getInvalidDateTimes()
    {
        return array(
            array('foobar'),
            array('2010-01-01'),
            array('00:00:00'),
            array('2010-01-01 00:00'),
            array('2010-13-01 00:00:00'),
            array('2010-04-32 00:00:00'),
            array('2010-02-29 00:00:00'),
            array('2010-01-01 24:00:00'),
            array('2010-01-01 00:60:00'),
            array('2010-01-01 00:00:60'),
        );
    }
}
PK��Z;���,,Xtest/Validator/Symfony/Component/Validator/Tests/Constraints/ExpressionValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\Validator\Constraints\Expression;
use Symfony\Component\Validator\Constraints\ExpressionValidator;

class ExpressionValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new ExpressionValidator(PropertyAccess::createPropertyAccessor());
        $this->validator->initialize($this->context);

        $this->context->expects($this->any())
            ->method('getClassName')
            ->will($this->returnValue(__CLASS__));
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Expression('value == 1'));
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Expression('value == 1'));
    }

    public function testSucceedingExpressionAtObjectLevel()
    {
        $constraint = new Expression('this.property == 1');

        $object = (object) array('property' => '1');

        $this->context->expects($this->any())
            ->method('getPropertyName')
            ->will($this->returnValue(null));

        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($object, $constraint);
    }

    public function testFailingExpressionAtObjectLevel()
    {
        $constraint = new Expression(array(
            'expression' => 'this.property == 1',
            'message' => 'myMessage',
        ));

        $object = (object) array('property' => '2');

        $this->context->expects($this->any())
            ->method('getPropertyName')
            ->will($this->returnValue(null));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage');

        $this->validator->validate($object, $constraint);
    }

    public function testSucceedingExpressionAtPropertyLevel()
    {
        $constraint = new Expression('value == this.expected');

        $object = (object) array('expected' => '1');

        $this->context->expects($this->any())
            ->method('getPropertyName')
            ->will($this->returnValue('property'));

        $this->context->expects($this->any())
            ->method('getPropertyPath')
            ->will($this->returnValue('property'));

        $this->context->expects($this->any())
            ->method('getRoot')
            ->will($this->returnValue($object));

        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('1', $constraint);
    }

    public function testFailingExpressionAtPropertyLevel()
    {
        $constraint = new Expression(array(
            'expression' => 'value == this.expected',
            'message' => 'myMessage',
        ));

        $object = (object) array('expected' => '1');

        $this->context->expects($this->any())
            ->method('getPropertyName')
            ->will($this->returnValue('property'));

        $this->context->expects($this->any())
            ->method('getPropertyPath')
            ->will($this->returnValue('property'));

        $this->context->expects($this->any())
            ->method('getRoot')
            ->will($this->returnValue($object));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage');

        $this->validator->validate('2', $constraint);
    }

    public function testSucceedingExpressionAtNestedPropertyLevel()
    {
        $constraint = new Expression('value == this.expected');

        $object = (object) array('expected' => '1');
        $root = (object) array('nested' => $object);

        $this->context->expects($this->any())
            ->method('getPropertyName')
            ->will($this->returnValue('property'));

        $this->context->expects($this->any())
            ->method('getPropertyPath')
            ->will($this->returnValue('nested.property'));

        $this->context->expects($this->any())
            ->method('getRoot')
            ->will($this->returnValue($root));

        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('1', $constraint);
    }

    public function testFailingExpressionAtNestedPropertyLevel()
    {
        $constraint = new Expression(array(
            'expression' => 'value == this.expected',
            'message' => 'myMessage',
        ));

        $object = (object) array('expected' => '1');
        $root = (object) array('nested' => $object);

        $this->context->expects($this->any())
            ->method('getPropertyName')
            ->will($this->returnValue('property'));

        $this->context->expects($this->any())
            ->method('getPropertyPath')
            ->will($this->returnValue('nested.property'));

        $this->context->expects($this->any())
            ->method('getRoot')
            ->will($this->returnValue($root));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage');

        $this->validator->validate('2', $constraint);
    }
}
PK��Z�Zf^
^
Vtest/Validator/Symfony/Component/Validator/Tests/Constraints/NotBlankValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\NotBlankValidator;

class NotBlankValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new NotBlankValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    /**
     * @dataProvider getValidValues
     */
    public function testValidValues($date)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($date, new NotBlank());
    }

    public function getValidValues()
    {
        return array(
            array('foobar'),
            array(0),
            array(0.0),
            array('0'),
            array(1234),
        );
    }

    public function testNullIsInvalid()
    {
        $constraint = new NotBlank(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage');

        $this->validator->validate(null, $constraint);
    }

    public function testBlankIsInvalid()
    {
        $constraint = new NotBlank(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage');

        $this->validator->validate('', $constraint);
    }

    public function testFalseIsInvalid()
    {
        $constraint = new NotBlank(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage');

        $this->validator->validate(false, $constraint);
    }

    public function testEmptyArrayIsInvalid()
    {
        $constraint = new NotBlank(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage');

        $this->validator->validate(array(), $constraint);
    }
}
PK��Z}mW��]test/Validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorArrayTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

class CollectionValidatorArrayTest extends CollectionValidatorTest
{
    public function prepareTestData(array $contents)
    {
        return $contents;
    }
}
PK��Z�r3UURtest/Validator/Symfony/Component/Validator/Tests/Constraints/NullValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Null;
use Symfony\Component\Validator\Constraints\NullValidator;

class NullValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new NullValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Null());
    }

    /**
     * @dataProvider getInvalidValues
     */
    public function testInvalidValues($value, $readableValue)
    {
        $constraint = new Null(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $readableValue,
            ));

        $this->validator->validate($value, $constraint);
    }

    public function getInvalidValues()
    {
        return array(
            array(0, 0),
            array(false, false),
            array(true, true),
            array('', ''),
            array('foo bar', 'foo bar'),
            array(new \DateTime(), 'DateTime'),
            array(array(), 'Array'),
        );
    }
}
PK��Z0�h'��Stest/Validator/Symfony/Component/Validator/Tests/Constraints/ImageValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Image;
use Symfony\Component\Validator\Constraints\ImageValidator;

class ImageValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;
    protected $path;
    protected $image;
    protected $imageLandscape;
    protected $imagePortrait;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new ImageValidator();
        $this->validator->initialize($this->context);
        $this->image = __DIR__.'/Fixtures/test.gif';
        $this->imageLandscape = __DIR__.'/Fixtures/test_landscape.gif';
        $this->imagePortrait = __DIR__.'/Fixtures/test_portrait.gif';
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Image());
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Image());
    }

    public function testValidImage()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($this->image, new Image());
    }

    public function testValidSize()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = new Image(array(
            'minWidth' => 1,
            'maxWidth' => 2,
            'minHeight' => 1,
            'maxHeight' => 2,
        ));

        $this->validator->validate($this->image, $constraint);
    }

    public function testWidthTooSmall()
    {
        $constraint = new Image(array(
            'minWidth' => 3,
            'minWidthMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ width }}' => '2',
                '{{ min_width }}' => '3',
            ));

        $this->validator->validate($this->image, $constraint);
    }

    public function testWidthTooBig()
    {
        $constraint = new Image(array(
            'maxWidth' => 1,
            'maxWidthMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ width }}' => '2',
                '{{ max_width }}' => '1',
            ));

        $this->validator->validate($this->image, $constraint);
    }

    public function testHeightTooSmall()
    {
        $constraint = new Image(array(
            'minHeight' => 3,
            'minHeightMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ height }}' => '2',
                '{{ min_height }}' => '3',
            ));

        $this->validator->validate($this->image, $constraint);
    }

    public function testHeightTooBig()
    {
        $constraint = new Image(array(
            'maxHeight' => 1,
            'maxHeightMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ height }}' => '2',
                '{{ max_height }}' => '1',
            ));

        $this->validator->validate($this->image, $constraint);
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testInvalidMinWidth()
    {
        $constraint = new Image(array(
            'minWidth' => '1abc',
        ));

        $this->validator->validate($this->image, $constraint);
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testInvalidMaxWidth()
    {
        $constraint = new Image(array(
            'maxWidth' => '1abc',
        ));

        $this->validator->validate($this->image, $constraint);
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testInvalidMinHeight()
    {
        $constraint = new Image(array(
            'minHeight' => '1abc',
        ));

        $this->validator->validate($this->image, $constraint);
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testInvalidMaxHeight()
    {
        $constraint = new Image(array(
            'maxHeight' => '1abc',
        ));

        $this->validator->validate($this->image, $constraint);
    }

    public function testRatioTooSmall()
    {
        $constraint = new Image(array(
            'minRatio' => 2,
            'minRatioMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ ratio }}' => 1,
                '{{ min_ratio }}' => 2,
            ));

        $this->validator->validate($this->image, $constraint);
    }

    public function testRatioTooBig()
    {
        $constraint = new Image(array(
            'maxRatio' => 0.5,
            'maxRatioMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ ratio }}' => 1,
                '{{ max_ratio }}' => 0.5,
            ));

        $this->validator->validate($this->image, $constraint);
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testInvalidMinRatio()
    {
        $constraint = new Image(array(
            'minRatio' => '1abc',
        ));

        $this->validator->validate($this->image, $constraint);
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testInvalidMaxRatio()
    {
        $constraint = new Image(array(
            'maxRatio' => '1abc',
        ));

        $this->validator->validate($this->image, $constraint);
    }

    public function testSquareNotAllowed()
    {
        $constraint = new Image(array(
            'allowSquare' => false,
            'allowSquareMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ width }}' => 2,
                '{{ height }}' => 2,
            ));

        $this->validator->validate($this->image, $constraint);
    }

    public function testLandscapeNotAllowed()
    {
        $constraint = new Image(array(
            'allowLandscape' => false,
            'allowLandscapeMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ width }}' => 2,
                '{{ height }}' => 1,
            ));

        $this->validator->validate($this->imageLandscape, $constraint);
    }

    public function testPortraitNotAllowed()
    {
        $constraint = new Image(array(
            'allowPortrait' => false,
            'allowPortraitMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ width }}' => 1,
                '{{ height }}' => 2,
            ));

        $this->validator->validate($this->imagePortrait, $constraint);
    }
}
PK��Z�d��..Ctest/Validator/Symfony/Component/Validator/Tests/ConstraintTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests;

use Symfony\Component\Validator\Tests\Fixtures\ClassConstraint;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintB;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintC;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintWithValue;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintWithValueAsDefault;

class ConstraintTest extends \PHPUnit_Framework_TestCase
{
    public function testSetProperties()
    {
        $constraint = new ConstraintA(array(
            'property1' => 'foo',
            'property2' => 'bar',
        ));

        $this->assertEquals('foo', $constraint->property1);
        $this->assertEquals('bar', $constraint->property2);
    }

    public function testSetNotExistingPropertyThrowsException()
    {
        $this->setExpectedException('Symfony\Component\Validator\Exception\InvalidOptionsException');

        new ConstraintA(array(
            'foo' => 'bar',
        ));
    }

    public function testMagicPropertiesAreNotAllowed()
    {
        $constraint = new ConstraintA();

        $this->setExpectedException('Symfony\Component\Validator\Exception\InvalidOptionsException');

        $constraint->foo = 'bar';
    }

    public function testInvalidAndRequiredOptionsPassed()
    {
        $this->setExpectedException('Symfony\Component\Validator\Exception\InvalidOptionsException');

        new ConstraintC(array(
            'option1' => 'default',
            'foo' => 'bar'
        ));
    }

    public function testSetDefaultProperty()
    {
        $constraint = new ConstraintA('foo');

        $this->assertEquals('foo', $constraint->property2);
    }

    public function testSetDefaultPropertyDoctrineStyle()
    {
        $constraint = new ConstraintA(array('value' => 'foo'));

        $this->assertEquals('foo', $constraint->property2);
    }

    public function testSetDefaultPropertyDoctrineStylePlusOtherProperty()
    {
        $constraint = new ConstraintA(array('value' => 'foo', 'property1' => 'bar'));

        $this->assertEquals('foo', $constraint->property2);
        $this->assertEquals('bar', $constraint->property1);
    }

    public function testSetDefaultPropertyDoctrineStyleWhenDefaultPropertyIsNamedValue()
    {
        $constraint = new ConstraintWithValueAsDefault(array('value' => 'foo'));

        $this->assertEquals('foo', $constraint->value);
        $this->assertNull($constraint->property);
    }

    public function testDontSetDefaultPropertyIfValuePropertyExists()
    {
        $constraint = new ConstraintWithValue(array('value' => 'foo'));

        $this->assertEquals('foo', $constraint->value);
        $this->assertNull($constraint->property);
    }

    public function testSetUndefinedDefaultProperty()
    {
        $this->setExpectedException('Symfony\Component\Validator\Exception\ConstraintDefinitionException');

        new ConstraintB('foo');
    }

    public function testRequiredOptionsMustBeDefined()
    {
        $this->setExpectedException('Symfony\Component\Validator\Exception\MissingOptionsException');

        new ConstraintC();
    }

    public function testRequiredOptionsPassed()
    {
        new ConstraintC(array('option1' => 'default'));
    }

    public function testGroupsAreConvertedToArray()
    {
        $constraint = new ConstraintA(array('groups' => 'Foo'));

        $this->assertEquals(array('Foo'), $constraint->groups);
    }

    public function testAddDefaultGroupAddsGroup()
    {
        $constraint = new ConstraintA(array('groups' => 'Default'));
        $constraint->addImplicitGroupName('Foo');
        $this->assertEquals(array('Default', 'Foo'), $constraint->groups);
    }

    public function testAllowsSettingZeroRequiredPropertyValue()
    {
        $constraint = new ConstraintA(0);
        $this->assertEquals(0, $constraint->property2);
    }

    public function testCanCreateConstraintWithNoDefaultOptionAndEmptyArray()
    {
        new ConstraintB(array());
    }

    public function testGetTargetsCanBeString()
    {
        $constraint = new ClassConstraint();

        $this->assertEquals('class', $constraint->getTargets());
    }

    public function testGetTargetsCanBeArray()
    {
        $constraint = new ConstraintA();

        $this->assertEquals(array('property', 'class'), $constraint->getTargets());
    }
}
PK��Z��,Q88;test/Validator/Symfony/Component/Validator/phpunit.xml.distnu�[���<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony Validator Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./vendor</directory>
                <directory>./Tests</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
PK��Z�����Ktest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Logger/DbalLoggerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Logger;

use Symfony\Bridge\Doctrine\Logger\DbalLogger;

class DbalLoggerTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getLogFixtures
     */
    public function testLog($sql, $params, $logParams)
    {
        $logger = $this->getMock('Psr\\Log\\LoggerInterface');

        $dbalLogger = $this
            ->getMockBuilder('Symfony\\Bridge\\Doctrine\\Logger\\DbalLogger')
            ->setConstructorArgs(array($logger, null))
            ->setMethods(array('log'))
            ->getMock()
        ;

        $dbalLogger
            ->expects($this->once())
            ->method('log')
            ->with($sql, $logParams)
        ;

        $dbalLogger->startQuery($sql, $params);
    }

    public function getLogFixtures()
    {
        return array(
            array('SQL', null, array()),
            array('SQL', array(), array()),
            array('SQL', array('foo' => 'bar'), array('foo' => 'bar'))
        );
    }

    public function testLogNonUtf8()
    {
        $logger = $this->getMock('Psr\\Log\\LoggerInterface');

        $dbalLogger = $this
            ->getMockBuilder('Symfony\\Bridge\\Doctrine\\Logger\\DbalLogger')
            ->setConstructorArgs(array($logger, null))
            ->setMethods(array('log'))
            ->getMock()
        ;

        $dbalLogger
            ->expects($this->once())
            ->method('log')
            ->with('SQL', array('utf8' => 'foo', 'nonutf8' => DbalLogger::BINARY_DATA_VALUE))
        ;

        $dbalLogger->startQuery('SQL', array(
            'utf8'    => 'foo',
            'nonutf8' => "\x7F\xFF",
        ));
    }

    public function testLogLongString()
    {
        $logger = $this->getMock('Symfony\\Component\\HttpKernel\\Log\\LoggerInterface');

        $dbalLogger = $this
            ->getMockBuilder('Symfony\\Bridge\\Doctrine\\Logger\\DbalLogger')
            ->setConstructorArgs(array($logger, null))
            ->setMethods(array('log'))
            ->getMock()
        ;

        $testString = 'abc';

        $shortString = str_pad('', DbalLogger::MAX_STRING_LENGTH, $testString);
        $longString = str_pad('', DbalLogger::MAX_STRING_LENGTH+1, $testString);

        $dbalLogger
            ->expects($this->once())
            ->method('log')
            ->with('SQL', array('short' => $shortString, 'long' => substr($longString, 0, DbalLogger::MAX_STRING_LENGTH - 6).' [...]'))
        ;

        $dbalLogger->startQuery('SQL', array(
            'short' => $shortString,
            'long'  => $longString,
        ));
    }

    public function testLogUTF8LongString()
    {
        if (!function_exists('mb_detect_encoding')) {
            $this->markTestSkipped('Testing log shortening of utf8 charsets requires the mb_detect_encoding() function.');
        }

        $logger = $this->getMock('Symfony\\Component\\HttpKernel\\Log\\LoggerInterface');

        $dbalLogger = $this
            ->getMockBuilder('Symfony\\Bridge\\Doctrine\\Logger\\DbalLogger')
            ->setConstructorArgs(array($logger, null))
            ->setMethods(array('log'))
            ->getMock()
        ;

        $testStringArray = array('é', 'á', 'ű', 'ő', 'ú', 'ö', 'ü', 'ó', 'í');
        $testStringCount = count($testStringArray);

        $shortString = '';
        $longString = '';
        for ($i = 1; $i <= DbalLogger::MAX_STRING_LENGTH; $i++) {
            $shortString .= $testStringArray[$i % $testStringCount];
            $longString .= $testStringArray[$i % $testStringCount];
        }
        $longString .= $testStringArray[$i % $testStringCount];

        $dbalLogger
            ->expects($this->once())
            ->method('log')
            ->with('SQL', array('short' => $shortString, 'long' => mb_substr($longString, 0, DbalLogger::MAX_STRING_LENGTH - 6, mb_detect_encoding($longString)).' [...]'))
        ;

        $dbalLogger->startQuery('SQL', array(
                'short' => $shortString,
                'long'  => $longString,
            ));
    }

}
PK��Zl;���?test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/bootstrap.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

$loader = require __DIR__.'/../vendor/autoload.php';

Doctrine\Common\Annotations\AnnotationRegistry::registerLoader(array($loader, 'loadClass'));
PK��Z1g��Ptest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/SingleIntIdEntity.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Fixtures;

use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Entity;

/** @Entity */
class SingleIntIdEntity
{
    /** @Id @Column(type="integer") */
    protected $id;

    /** @Column(type="string", nullable=true) */
    public $name;

    public function __construct($id, $name)
    {
        $this->id = $id;
        $this->name = $name;
    }

    public function __toString()
    {
        return (string) $this->name;
    }
}
PK��ZI>�[��Ztest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/SingleIntIdNoToStringEntity.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Fixtures;

use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Entity;

/** @Entity */
class SingleIntIdNoToStringEntity
{
    /** @Id @Column(type="integer") */
    protected $id;

    /** @Column(type="string", nullable=true) */
    public $name;

    public function __construct($id, $name)
    {
        $this->id = $id;
        $this->name = $name;
    }
}
PK��Z�+�88Stest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/CompositeIntIdEntity.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Fixtures;

use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Entity;

/** @Entity */
class CompositeIntIdEntity
{
    /** @Id @Column(type="integer") */
    protected $id1;

    /** @Id @Column(type="integer") */
    protected $id2;

    /** @Column(type="string") */
    public $name;

    public function __construct($id1, $id2, $name)
    {
        $this->id1 = $id1;
        $this->id2 = $id2;
        $this->name = $name;
    }

    public function __toString()
    {
        return $this->name;
    }
}
PK��Z�ͭ��Ptest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/AssociationEntity.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Fixtures;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 */
class AssociationEntity
{
    /**
     * @var int
     * @ORM\Id @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity="SingleIntIdEntity")
     * @var \Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity
     */
    public $single;

    /**
     * @ORM\ManyToOne(targetEntity="CompositeIntIdEntity")
     * @ORM\JoinColumns({
     *  @ORM\JoinColumn(name="composite_id1", referencedColumnName="id1"),
     *  @ORM\JoinColumn(name="composite_id2", referencedColumnName="id2")
     * })
     * @var \Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeIntIdEntity
     */
    public $composite;
}
PK��Z��3Ntest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/GroupableEntity.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Fixtures;

use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Entity;

/** @Entity */
class GroupableEntity
{
    /** @Id @Column(type="integer") */
    protected $id;

    /** @Column(type="string", nullable=true) */
    public $name;

    /** @Column(type="string", nullable=true) */
    public $groupName;

    public function __construct($id, $name, $groupName)
    {
        $this->id = $id;
        $this->name = $name;
        $this->groupName = $groupName;
    }
}
PK��Z��!��Stest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/SingleStringIdEntity.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Fixtures;

use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Entity;

/** @Entity */
class SingleStringIdEntity
{
    /** @Id @Column(type="string") */
    protected $id;

    /** @Column(type="string") */
    public $name;

    public function __construct($id, $name)
    {
        $this->id = $id;
        $this->name = $name;
    }

    public function __toString()
    {
        return $this->name;
    }
}
PK��Z6i+**Ttest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/ContainerAwareFixture.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Fixtures;

use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;

class ContainerAwareFixture implements FixtureInterface, ContainerAwareInterface
{
    public $container;

    public function setContainer(ContainerInterface $container = null)
    {
        $this->container = $container;
    }

    public function load(ObjectManager $manager)
    {
    }
}
PK��Z�m��Otest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/DoubleNameEntity.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Fixtures;

use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Entity;

/** @Entity */
class DoubleNameEntity
{
    /** @Id @Column(type="integer") */
    protected $id;

    /** @Column(type="string") */
    public $name;

    /** @Column(type="string", nullable=true) */
    public $name2;

    public function __construct($id, $name, $name2)
    {
        $this->id = $id;
        $this->name = $name;
        $this->name2 = $name2;
    }
}
PK��Z�%b�99Vtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/CompositeStringIdEntity.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Fixtures;

use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Entity;

/** @Entity */
class CompositeStringIdEntity
{
    /** @Id @Column(type="string") */
    protected $id1;

    /** @Id @Column(type="string") */
    protected $id2;

    /** @Column(type="string") */
    public $name;

    public function __construct($id1, $id2, $name)
    {
        $this->id1 = $id1;
        $this->id2 = $id2;
        $this->name = $name;
    }

    public function __toString()
    {
        return $this->name;
    }
}
PK��Z�'N|qqCtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/User.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Fixtures;

use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Entity;
use Symfony\Component\Security\Core\User\UserInterface;

/** @Entity */
class User implements UserInterface
{
    /** @Id @Column(type="integer") */
    protected $id1;

    /** @Id @Column(type="integer") */
    protected $id2;

    /** @Column(type="string") */
    public $name;

    public function __construct($id1, $id2, $name)
    {
        $this->id1 = $id1;
        $this->id2 = $id2;
        $this->name = $name;
    }

    public function getRoles()
    {
    }

    public function getPassword()
    {
    }

    public function getSalt()
    {
    }

    public function getUsername()
    {
        return $this->name;
    }

    public function eraseCredentials()
    {
    }

    public function equals(UserInterface $user)
    {
    }
}
PK��Z��.���Itest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/DoctrineOrmTestCase.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests;

use Symfony\Bridge\Doctrine\Test\DoctrineTestHelper;

/**
 * Class DoctrineOrmTestCase
 *
 * @deprecated Deprecated as of Symfony 2.4, to be removed in Symfony 3.0.
 *             Use {@link DoctrineTestHelper} instead.
 */
abstract class DoctrineOrmTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * @return \Doctrine\ORM\EntityManager
     */
    public static function createTestEntityManager()
    {
        return DoctrineTestHelper::createTestEntityManager();
    }
}
PK��Z��۵��Utest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/DoctrineOrmTypeGuesserTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Form;

use Doctrine\Common\Persistence\Mapping\ClassMetadata;
use Symfony\Bridge\Doctrine\Form\DoctrineOrmTypeGuesser;
use Symfony\Component\Form\Guess\Guess;
use Symfony\Component\Form\Guess\ValueGuess;

class DoctrineOrmTypeGuesserTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider requiredProvider
     */
    public function testRequiredGuesser($classMetadata, $expected)
    {
        $this->assertEquals($expected, $this->getGuesser($classMetadata)->guessRequired('TestEntity', 'field'));
    }

    public function requiredProvider()
    {
        $return = array();

        // Simple field, not nullable
        $classMetadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock();
        $classMetadata->expects($this->once())->method('hasField')->with('field')->will($this->returnValue(true));
        $classMetadata->expects($this->once())->method('isNullable')->with('field')->will($this->returnValue(false));

        $return[] = array($classMetadata, new ValueGuess(true, Guess::HIGH_CONFIDENCE));

        // Simple field, nullable
        $classMetadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock();
        $classMetadata->expects($this->once())->method('hasField')->with('field')->will($this->returnValue(true));
        $classMetadata->expects($this->once())->method('isNullable')->with('field')->will($this->returnValue(true));

        $return[] = array($classMetadata, new ValueGuess(false, Guess::MEDIUM_CONFIDENCE));

        // One-to-one, nullable (by default)
        $classMetadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock();
        $classMetadata->expects($this->once())->method('hasField')->with('field')->will($this->returnValue(false));
        $classMetadata->expects($this->once())->method('isAssociationWithSingleJoinColumn')->with('field')->will($this->returnValue(true));

        $mapping = array('joinColumns' => array(array()));
        $classMetadata->expects($this->once())->method('getAssociationMapping')->with('field')->will($this->returnValue($mapping));

        $return[] = array($classMetadata, new ValueGuess(false, Guess::HIGH_CONFIDENCE));

        // One-to-one, nullable (explicit)
        $classMetadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock();
        $classMetadata->expects($this->once())->method('hasField')->with('field')->will($this->returnValue(false));
        $classMetadata->expects($this->once())->method('isAssociationWithSingleJoinColumn')->with('field')->will($this->returnValue(true));

        $mapping = array('joinColumns' => array(array('nullable'=>true)));
        $classMetadata->expects($this->once())->method('getAssociationMapping')->with('field')->will($this->returnValue($mapping));

        $return[] = array($classMetadata, new ValueGuess(false, Guess::HIGH_CONFIDENCE));

        // One-to-one, not nullable
        $classMetadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock();
        $classMetadata->expects($this->once())->method('hasField')->with('field')->will($this->returnValue(false));
        $classMetadata->expects($this->once())->method('isAssociationWithSingleJoinColumn')->with('field')->will($this->returnValue(true));

        $mapping = array('joinColumns' => array(array('nullable'=>false)));
        $classMetadata->expects($this->once())->method('getAssociationMapping')->with('field')->will($this->returnValue($mapping));

        $return[] = array($classMetadata, new ValueGuess(true, Guess::HIGH_CONFIDENCE));

        // One-to-many, no clue
        $classMetadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock();
        $classMetadata->expects($this->once())->method('hasField')->with('field')->will($this->returnValue(false));
        $classMetadata->expects($this->once())->method('isAssociationWithSingleJoinColumn')->with('field')->will($this->returnValue(false));

        $return[] = array($classMetadata, null);

        return $return;
    }

    private function getGuesser(ClassMetadata $classMetadata)
    {
        $em = $this->getMock('Doctrine\Common\Persistence\ObjectManager');
        $em->expects($this->once())->method('getClassMetaData')->with('TestEntity')->will($this->returnValue($classMetadata));

        $registry = $this->getMock('Doctrine\Common\Persistence\ManagerRegistry');
        $registry->expects($this->once())->method('getManagers')->will($this->returnValue(array($em)));

        return new DoctrineOrmTypeGuesser($registry);
    }

}
PK��Z��`Հ�ptest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleStringIdTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class UnloadedEntityChoiceListSingleStringIdTest extends AbstractEntityChoiceListSingleStringIdTest
{
    public function testGetIndicesForValuesIgnoresNonExistingValues()
    {
        $this->markTestSkipped('Non-existing values are not detected for unloaded choice lists.');
    }
}
PK��Z�'�;�!�!atest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/GenericEntityChoiceListTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList;

use Symfony\Bridge\Doctrine\Test\DoctrineTestHelper;
use Symfony\Bridge\Doctrine\Tests\Fixtures\GroupableEntity;
use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity;
use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdNoToStringEntity;
use Symfony\Bridge\Doctrine\Form\ChoiceList\EntityChoiceList;
use Symfony\Component\Form\Extension\Core\View\ChoiceView;
use Doctrine\ORM\Tools\SchemaTool;

class GenericEntityChoiceListTest extends \PHPUnit_Framework_TestCase
{
    const SINGLE_INT_ID_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity';

    const SINGLE_STRING_ID_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleStringIdEntity';

    const COMPOSITE_ID_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeIntIdEntity';

    const GROUPABLE_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\GroupableEntity';

    /**
     * @var \Doctrine\ORM\EntityManager
     */
    private $em;

    protected function setUp()
    {
        if (!class_exists('Symfony\Component\Form\Form')) {
            $this->markTestSkipped('The "Form" component is not available');
        }

        if (!class_exists('Doctrine\DBAL\Platforms\MySqlPlatform')) {
            $this->markTestSkipped('Doctrine DBAL is not available.');
        }

        if (!class_exists('Doctrine\Common\Version')) {
            $this->markTestSkipped('Doctrine Common is not available.');
        }

        if (!class_exists('Doctrine\ORM\EntityManager')) {
            $this->markTestSkipped('Doctrine ORM is not available.');
        }

        $this->em = DoctrineTestHelper::createTestEntityManager();

        $schemaTool = new SchemaTool($this->em);
        $classes = array(
            $this->em->getClassMetadata(self::SINGLE_INT_ID_CLASS),
            $this->em->getClassMetadata(self::SINGLE_STRING_ID_CLASS),
            $this->em->getClassMetadata(self::COMPOSITE_ID_CLASS),
            $this->em->getClassMetadata(self::GROUPABLE_CLASS),
        );

        try {
            $schemaTool->dropSchema($classes);
        } catch (\Exception $e) {
        }

        try {
            $schemaTool->createSchema($classes);
        } catch (\Exception $e) {
        }

        parent::setUp();
    }

    protected function tearDown()
    {
        parent::tearDown();

        $this->em = null;
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\StringCastException
     * @expectedMessage   Entity "Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity" passed to the choice field must have a "__toString()" method defined (or you can also override the "property" option).
     */
    public function testEntitiesMustHaveAToStringMethod()
    {
        $entity1 = new SingleIntIdNoToStringEntity(1, 'Foo');
        $entity2 = new SingleIntIdNoToStringEntity(2, 'Bar');

        // Persist for managed state
        $this->em->persist($entity1);
        $this->em->persist($entity2);

        $choiceList = new EntityChoiceList(
            $this->em,
            self::SINGLE_INT_ID_CLASS,
            null,
            null,
            array(
                $entity1,
                $entity2,
            )
        );

        $choiceList->getValues();
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\RuntimeException
     */
    public function testChoicesMustBeManaged()
    {
        $entity1 = new SingleIntIdEntity(1, 'Foo');
        $entity2 = new SingleIntIdEntity(2, 'Bar');

        // no persist here!

        $choiceList = new EntityChoiceList(
            $this->em,
            self::SINGLE_INT_ID_CLASS,
            'name',
            null,
            array(
                $entity1,
                $entity2,
            )
        );

        // triggers loading -> exception
        $choiceList->getChoices();
    }

    public function testInitExplicitChoices()
    {
        $entity1 = new SingleIntIdEntity(1, 'Foo');
        $entity2 = new SingleIntIdEntity(2, 'Bar');

        // Persist for managed state
        $this->em->persist($entity1);
        $this->em->persist($entity2);

        $choiceList = new EntityChoiceList(
            $this->em,
            self::SINGLE_INT_ID_CLASS,
            'name',
            null,
            array(
                $entity1,
                $entity2,
            )
        );

        $this->assertSame(array(1 => $entity1, 2 => $entity2), $choiceList->getChoices());
    }

    public function testInitEmptyChoices()
    {
        $entity1 = new SingleIntIdEntity(1, 'Foo');
        $entity2 = new SingleIntIdEntity(2, 'Bar');

        // Persist for managed state
        $this->em->persist($entity1);
        $this->em->persist($entity2);

        $choiceList = new EntityChoiceList(
            $this->em,
            self::SINGLE_INT_ID_CLASS,
            'name',
            null,
            array()
        );

        $this->assertSame(array(), $choiceList->getChoices());
    }

    public function testInitNestedChoices()
    {
        $entity1 = new SingleIntIdEntity(1, 'Foo');
        $entity2 = new SingleIntIdEntity(2, 'Bar');

        // Oh yeah, we're persisting with fire now!
        $this->em->persist($entity1);
        $this->em->persist($entity2);

        $choiceList = new EntityChoiceList(
            $this->em,
            self::SINGLE_INT_ID_CLASS,
            'name',
            null,
            array(
                'group1' => array($entity1),
                'group2' => array($entity2),
            ),
            array()
        );

        $this->assertSame(array(1 => $entity1, 2 => $entity2), $choiceList->getChoices());
        $this->assertEquals(array(
            'group1' => array(1 => new ChoiceView($entity1, '1', 'Foo')),
            'group2' => array(2 => new ChoiceView($entity2, '2', 'Bar'))
        ), $choiceList->getRemainingViews());
    }

    public function testGroupByPropertyPath()
    {
        $item1 = new GroupableEntity(1, 'Foo', 'Group1');
        $item2 = new GroupableEntity(2, 'Bar', 'Group1');
        $item3 = new GroupableEntity(3, 'Baz', 'Group2');
        $item4 = new GroupableEntity(4, 'Boo!', null);

        $this->em->persist($item1);
        $this->em->persist($item2);
        $this->em->persist($item3);
        $this->em->persist($item4);

        $choiceList = new EntityChoiceList(
            $this->em,
            self::GROUPABLE_CLASS,
            'name',
            null,
            array(
                $item1,
                $item2,
                $item3,
                $item4,
            ),
            array(),
            'groupName'
        );

        $this->assertEquals(array(1 => $item1, 2 => $item2, 3 => $item3, 4 => $item4), $choiceList->getChoices());
        $this->assertEquals(array(
            'Group1' => array(1 => new ChoiceView($item1, '1', 'Foo'), 2 => new ChoiceView($item2, '2', 'Bar')),
            'Group2' => array(3 => new ChoiceView($item3, '3', 'Baz')),
            4 => new ChoiceView($item4, '4', 'Boo!')
        ), $choiceList->getRemainingViews());
    }

    public function testGroupByInvalidPropertyPathReturnsFlatChoices()
    {
        $item1 = new GroupableEntity(1, 'Foo', 'Group1');
        $item2 = new GroupableEntity(2, 'Bar', 'Group1');

        $this->em->persist($item1);
        $this->em->persist($item2);

        $choiceList = new EntityChoiceList(
            $this->em,
            self::GROUPABLE_CLASS,
            'name',
            null,
            array(
                $item1,
                $item2,
            ),
            array(),
            'child.that.does.not.exist'
        );

        $this->assertEquals(array(
            1 => $item1,
            2 => $item2
        ), $choiceList->getChoices());
    }

    public function testInitShorthandEntityName()
    {
        $item1 = new SingleIntIdEntity(1, 'Foo');
        $item2 = new SingleIntIdEntity(2, 'Bar');

        $this->em->persist($item1);
        $this->em->persist($item2);

        $choiceList = new EntityChoiceList(
            $this->em,
            'SymfonyTestsDoctrine:SingleIntIdEntity'
        );

        $this->assertEquals(array(1, 2), $choiceList->getValuesForChoices(array($item1, $item2)));
        $this->assertEquals(array(1, 2), $choiceList->getIndicesForChoices(array($item1, $item2)));
    }
}
PK��Z9&���test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleStringIdWithQueryBuilderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList;

use Symfony\Bridge\Doctrine\Form\ChoiceList\EntityChoiceList;
use Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class UnloadedEntityChoiceListSingleStringIdWithQueryBuilderTest extends UnloadedEntityChoiceListSingleStringIdTest
{
    /**
     * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface
     */
    protected function createChoiceList()
    {
        $qb = $this->em->createQueryBuilder()->select('s')->from($this->getEntityClass(), 's');
        $loader = new ORMQueryBuilderLoader($qb);

        return new EntityChoiceList($this->em, $this->getEntityClass(), null, $loader);
    }
}
PK��Zb#����mtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListSingleIntIdTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList;

use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
abstract class AbstractEntityChoiceListSingleIntIdTest extends AbstractEntityChoiceListTest
{
    protected function getEntityClass()
    {
        return 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity';
    }

    /**
     * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface
     */
    protected function createObjects()
    {
        return array(
            new SingleIntIdEntity(-10, 'A'),
            new SingleIntIdEntity(10, 'B'),
            new SingleIntIdEntity(20, 'C'),
            new SingleIntIdEntity(30, 'D'),
        );
    }

    protected function getChoices()
    {
        return array('_10' => $this->obj1, 10 => $this->obj2, 20 => $this->obj3, 30 => $this->obj4);
    }

    protected function getLabels()
    {
        return array('_10' => 'A', 10 => 'B', 20 => 'C', 30 => 'D');
    }

    protected function getValues()
    {
        return array('_10' => '-10', 10 => '10', 20 => '20', 30 => '30');
    }

    protected function getIndices()
    {
        return array('_10', 10, 20, 30);
    }
}
PK��ZAGA��}test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleIntIdWithQueryBuilderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList;

use Symfony\Bridge\Doctrine\Form\ChoiceList\EntityChoiceList;
use Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class UnloadedEntityChoiceListSingleIntIdWithQueryBuilderTest extends UnloadedEntityChoiceListSingleIntIdTest
{
    /**
     * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface
     */
    protected function createChoiceList()
    {
        $qb = $this->em->createQueryBuilder()->select('s')->from($this->getEntityClass(), 's');
        $loader = new ORMQueryBuilderLoader($qb);

        return new EntityChoiceList($this->em, $this->getEntityClass(), null, $loader);
    }
}
PK��Z�~h���}test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListCompositeIdWithQueryBuilderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList;

use Symfony\Bridge\Doctrine\Form\ChoiceList\EntityChoiceList;
use Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class UnloadedEntityChoiceListCompositeIdWithQueryBuilderTest extends UnloadedEntityChoiceListCompositeIdTest
{
    /**
     * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface
     */
    protected function createChoiceList()
    {
        $qb = $this->em->createQueryBuilder()->select('s')->from($this->getEntityClass(), 's');
        $loader = new ORMQueryBuilderLoader($qb);

        return new EntityChoiceList($this->em, $this->getEntityClass(), null, $loader);
    }
}
PK��Z�'j��ntest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/LoadedEntityChoiceListSingleStringIdTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class LoadedEntityChoiceListSingleStringIdTest extends AbstractEntityChoiceListSingleStringIdTest
{
    /**
     * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface
     */
    protected function createChoiceList()
    {
        $list = parent::createChoiceList();

        // load list
        $list->getChoices();

        return $list;
    }
}
PK��Z�0�e��ktest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/LoadedEntityChoiceListSingleIntIdTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class LoadedEntityChoiceListSingleIntIdTest extends AbstractEntityChoiceListSingleIntIdTest
{
    /**
     * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface
     */
    protected function createChoiceList()
    {
        $list = parent::createChoiceList();

        // load list
        $list->getChoices();

        return $list;
    }
}
PK��Z��V
zzmtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListCompositeIdTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class UnloadedEntityChoiceListCompositeIdTest extends AbstractEntityChoiceListCompositeIdTest
{
    public function testGetIndicesForValuesIgnoresNonExistingValues()
    {
        $this->markTestSkipped('Non-existing values are not detected for unloaded choice lists.');
    }
}
PK��Z��*��mtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListCompositeIdTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList;

use Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeIntIdEntity;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
abstract class AbstractEntityChoiceListCompositeIdTest extends AbstractEntityChoiceListTest
{
    protected function getEntityClass()
    {
        return 'Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeIntIdEntity';
    }

    /**
     * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface
     */
    protected function createObjects()
    {
        return array(
            new CompositeIntIdEntity(10, 11, 'A'),
            new CompositeIntIdEntity(20, 21, 'B'),
            new CompositeIntIdEntity(30, 31, 'C'),
            new CompositeIntIdEntity(40, 41, 'D'),
        );
    }

    protected function getChoices()
    {
        return array(0 => $this->obj1, 1 => $this->obj2, 2 => $this->obj3, 3 => $this->obj4);
    }

    protected function getLabels()
    {
        return array(0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D');
    }

    protected function getValues()
    {
        return array(0 => '0', 1 => '1', 2 => '2', 3 => '3');
    }

    protected function getIndices()
    {
        return array(0, 1, 2, 3);
    }
}
PK��Z�n<-	-	_test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList;

use Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader;
use Symfony\Bridge\Doctrine\Tests\DoctrineOrmTestCase;
use Doctrine\DBAL\Connection;

class ORMQueryBuilderLoaderTest extends DoctrineOrmTestCase
{
    /**
     * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException
     */
    public function testItOnlyWorksWithQueryBuilderOrClosure()
    {
        new ORMQueryBuilderLoader(new \stdClass());
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException
     */
    public function testClosureRequiresTheEntityManager()
    {
        $closure = function () {};

        new ORMQueryBuilderLoader($closure);
    }

    public function testIdentifierTypeIsStringArray()
    {
        $this->checkIdentifierType('Symfony\Bridge\Doctrine\Tests\Fixtures\SingleStringIdEntity', Connection::PARAM_STR_ARRAY);
    }

    public function testIdentifierTypeIsIntegerArray()
    {
        $this->checkIdentifierType('Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity', Connection::PARAM_INT_ARRAY);
    }

    protected function checkIdentifierType($classname, $expectedType)
    {
        $em = $this->createTestEntityManager();

        $query = $this->getMockBuilder('QueryMock')
            ->setMethods(array('setParameter', 'getResult', 'getSql', '_doExecute'))
            ->getMock();

        $query->expects($this->once())
            ->method('setParameter')
            ->with('ORMQueryBuilderLoader_getEntitiesByIds_id', array(), $expectedType)
            ->will($this->returnValue($query));

        $qb = $this->getMockBuilder('Doctrine\ORM\QueryBuilder')
            ->setConstructorArgs(array($em))
            ->setMethods(array('getQuery'))
            ->getMock();

        $qb->expects($this->once())
            ->method('getQuery')
            ->will($this->returnValue($query));

        $qb->select('e')
            ->from($classname, 'e');

        $loader = new ORMQueryBuilderLoader($qb);
        $loader->getEntitiesByIds('id', array());
    }
}
PK��Z�-��1
1
btest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList;

use Symfony\Bridge\Doctrine\Test\DoctrineTestHelper;
use Symfony\Bridge\Doctrine\Form\ChoiceList\EntityChoiceList;
use Doctrine\ORM\Tools\SchemaTool;
use Symfony\Component\Form\Tests\Extension\Core\ChoiceList\AbstractChoiceListTest;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
abstract class AbstractEntityChoiceListTest extends AbstractChoiceListTest
{
    /**
     * @var \Doctrine\ORM\EntityManager
     */
    protected $em;

    protected $obj1;

    protected $obj2;

    protected $obj3;

    protected $obj4;

    protected function setUp()
    {
        if (!class_exists('Symfony\Component\Form\Form')) {
            $this->markTestSkipped('The "Form" component is not available');
        }

        if (!class_exists('Doctrine\DBAL\Platforms\MySqlPlatform')) {
            $this->markTestSkipped('Doctrine DBAL is not available.');
        }

        if (!class_exists('Doctrine\Common\Version')) {
            $this->markTestSkipped('Doctrine Common is not available.');
        }

        if (!class_exists('Doctrine\ORM\EntityManager')) {
            $this->markTestSkipped('Doctrine ORM is not available.');
        }

        $this->em = DoctrineTestHelper::createTestEntityManager();

        $schemaTool = new SchemaTool($this->em);
        $classes = array($this->em->getClassMetadata($this->getEntityClass()));

        try {
            $schemaTool->dropSchema($classes);
        } catch (\Exception $e) {
        }

        try {
            $schemaTool->createSchema($classes);
        } catch (\Exception $e) {
        }

        list($this->obj1, $this->obj2, $this->obj3, $this->obj4) = $this->createObjects();

        $this->em->persist($this->obj1);
        $this->em->persist($this->obj2);
        $this->em->persist($this->obj3);
        $this->em->persist($this->obj4);
        $this->em->flush();

        parent::setUp();
    }

    protected function tearDown()
    {
        parent::tearDown();

        $this->em = null;
    }

    abstract protected function getEntityClass();

    abstract protected function createObjects();

    /**
     * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface
     */
    protected function createChoiceList()
    {
        return new EntityChoiceList($this->em, $this->getEntityClass());
    }
}
PK��Zc�&zzmtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleIntIdTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class UnloadedEntityChoiceListSingleIntIdTest extends AbstractEntityChoiceListSingleIntIdTest
{
    public function testGetIndicesForValuesIgnoresNonExistingValues()
    {
        $this->markTestSkipped('Non-existing values are not detected for unloaded choice lists.');
    }
}
PK��Z�ǜ"��ktest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/LoadedEntityChoiceListCompositeIdTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class LoadedEntityChoiceListCompositeIdTest extends AbstractEntityChoiceListCompositeIdTest
{
    /**
     * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface
     */
    protected function createChoiceList()
    {
        $list = parent::createChoiceList();

        // load list
        $list->getChoices();

        return $list;
    }
}
PK��Z_UNF��ptest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListSingleStringIdTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList;

use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleStringIdEntity;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
abstract class AbstractEntityChoiceListSingleStringIdTest extends AbstractEntityChoiceListTest
{
    protected function getEntityClass()
    {
        return 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleStringIdEntity';
    }

    /**
     * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface
     */
    protected function createObjects()
    {
        return array(
            new SingleStringIdEntity('a', 'A'),
            new SingleStringIdEntity('b', 'B'),
            new SingleStringIdEntity('c', 'C'),
            new SingleStringIdEntity('d', 'D'),
        );
    }

    protected function getChoices()
    {
        return array(0 => $this->obj1, 1 => $this->obj2, 2 => $this->obj3, 3 => $this->obj4);
    }

    protected function getLabels()
    {
        return array(0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D');
    }

    protected function getValues()
    {
        return array(0 => 'a', 1 => 'b', 2 => 'c', 3 => 'd');
    }

    protected function getIndices()
    {
        return array(0, 1, 2, 3);
    }
}
PK��ZYv�:B	B	ktest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/DataTransformer/CollectionToArrayTransformerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Form\DataTransformer;

use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Bridge\Doctrine\Form\DataTransformer\CollectionToArrayTransformer;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class CollectionToArrayTransformerTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var CollectionToArrayTransformer
     */
    private $transformer;

    protected function setUp()
    {
        $this->transformer = new CollectionToArrayTransformer();
    }

    public function testTransform()
    {
        $array = array(
            2 => 'foo',
            3 => 'bar',
        );

        $this->assertSame($array, $this->transformer->transform(new ArrayCollection($array)));
    }

    /**
     * This test is needed for cases when getXxxs() in the entity returns the
     * result of $collection->toArray(), in order to prevent modifications of
     * the inner collection.
     *
     * See https://github.com/symfony/symfony/pull/9308
     */
    public function testTransformArray()
    {
        $array = array(
            2 => 'foo',
            3 => 'bar',
        );

        $this->assertSame($array, $this->transformer->transform($array));
    }

    public function testTransformNull()
    {
        $this->assertSame(array(), $this->transformer->transform(null));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
     */
    public function testTransformExpectsArrayOrCollection()
    {
        $this->transformer->transform('Foo');
    }

    public function testReverseTransform()
    {
        $array = array(
            2 => 'foo',
            3 => 'bar',
        );

        $this->assertEquals(new ArrayCollection($array), $this->transformer->reverseTransform($array));
    }

    public function testReverseTransformEmpty()
    {
        $this->assertEquals(new ArrayCollection(), $this->transformer->reverseTransform(''));
    }

    public function testReverseTransformNull()
    {
        $this->assertEquals(new ArrayCollection(), $this->transformer->reverseTransform(null));
    }
}
PK��Z��(iiNtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Form\Type;

use Symfony\Bridge\Doctrine\Test\DoctrineTestHelper;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\Form\Test\TypeTestCase;
use Symfony\Bridge\Doctrine\Tests\Fixtures\GroupableEntity;
use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity;
use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleStringIdEntity;
use Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeIntIdEntity;
use Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeStringIdEntity;
use Symfony\Bridge\Doctrine\Form\DoctrineOrmExtension;
use Doctrine\ORM\Tools\SchemaTool;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Form\Extension\Core\View\ChoiceView;

class EntityTypeTest extends TypeTestCase
{
    const ITEM_GROUP_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\GroupableEntity';
    const SINGLE_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity';
    const SINGLE_STRING_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleStringIdEntity';
    const COMPOSITE_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeIntIdEntity';
    const COMPOSITE_STRING_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeStringIdEntity';

    /**
     * @var \Doctrine\ORM\EntityManager
     */
    private $em;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $emRegistry;

    protected function setUp()
    {
        if (!class_exists('Symfony\Component\Form\Form')) {
            $this->markTestSkipped('The "Form" component is not available');
        }

        if (!class_exists('Doctrine\DBAL\Platforms\MySqlPlatform')) {
            $this->markTestSkipped('Doctrine DBAL is not available.');
        }

        if (!class_exists('Doctrine\Common\Version')) {
            $this->markTestSkipped('Doctrine Common is not available.');
        }

        if (!class_exists('Doctrine\ORM\EntityManager')) {
            $this->markTestSkipped('Doctrine ORM is not available.');
        }

        $this->em = DoctrineTestHelper::createTestEntityManager();
        $this->emRegistry = $this->createRegistryMock('default', $this->em);

        parent::setUp();

        $schemaTool = new SchemaTool($this->em);
        $classes = array(
            $this->em->getClassMetadata(self::ITEM_GROUP_CLASS),
            $this->em->getClassMetadata(self::SINGLE_IDENT_CLASS),
            $this->em->getClassMetadata(self::SINGLE_STRING_IDENT_CLASS),
            $this->em->getClassMetadata(self::COMPOSITE_IDENT_CLASS),
            $this->em->getClassMetadata(self::COMPOSITE_STRING_IDENT_CLASS),
        );

        try {
            $schemaTool->dropSchema($classes);
        } catch (\Exception $e) {
        }

        try {
            $schemaTool->createSchema($classes);
        } catch (\Exception $e) {
        }
    }

    protected function tearDown()
    {
        parent::tearDown();

        $this->em = null;
        $this->emRegistry = null;
    }

    protected function getExtensions()
    {
        return array_merge(parent::getExtensions(), array(
            new DoctrineOrmExtension($this->emRegistry),
        ));
    }

    protected function persist(array $entities)
    {
        foreach ($entities as $entity) {
            $this->em->persist($entity);
        }

        $this->em->flush();
        // no clear, because entities managed by the choice field must
        // be managed!
    }

    /**
     * @expectedException \Symfony\Component\OptionsResolver\Exception\MissingOptionsException
     */
    public function testClassOptionIsRequired()
    {
        $this->factory->createNamed('name', 'entity');
    }

    public function testSetDataToUninitializedEntityWithNonRequired()
    {
        $entity1 = new SingleIntIdEntity(1, 'Foo');
        $entity2 = new SingleIntIdEntity(2, 'Bar');

        $this->persist(array($entity1, $entity2));

        $field = $this->factory->createNamed('name', 'entity', null, array(
            'em' => 'default',
            'class' => self::SINGLE_IDENT_CLASS,
            'required' => false,
            'property' => 'name'
        ));

        $this->assertEquals(array(1 => new ChoiceView($entity1, '1', 'Foo'), 2 => new ChoiceView($entity2, '2', 'Bar')), $field->createView()->vars['choices']);
    }

    public function testSetDataToUninitializedEntityWithNonRequiredToString()
    {
        $entity1 = new SingleIntIdEntity(1, 'Foo');
        $entity2 = new SingleIntIdEntity(2, 'Bar');

        $this->persist(array($entity1, $entity2));

        $field = $this->factory->createNamed('name', 'entity', null, array(
            'em' => 'default',
            'class' => self::SINGLE_IDENT_CLASS,
            'required' => false,
        ));

        $this->assertEquals(array(1 => new ChoiceView($entity1, '1', 'Foo'), 2 => new ChoiceView($entity2, '2', 'Bar')), $field->createView()->vars['choices']);
    }

    public function testSetDataToUninitializedEntityWithNonRequiredQueryBuilder()
    {
        $entity1 = new SingleIntIdEntity(1, 'Foo');
        $entity2 = new SingleIntIdEntity(2, 'Bar');

        $this->persist(array($entity1, $entity2));
        $qb = $this->em->createQueryBuilder()->select('e')->from(self::SINGLE_IDENT_CLASS, 'e');

        $field = $this->factory->createNamed('name', 'entity', null, array(
            'em' => 'default',
            'class' => self::SINGLE_IDENT_CLASS,
            'required' => false,
            'property' => 'name',
            'query_builder' => $qb
        ));

        $this->assertEquals(array(1 => new ChoiceView($entity1, '1', 'Foo'), 2 => new ChoiceView($entity2, '2', 'Bar')), $field->createView()->vars['choices']);
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException
     */
    public function testConfigureQueryBuilderWithNonQueryBuilderAndNonClosure()
    {
        $field = $this->factory->createNamed('name', 'entity', null, array(
            'em' => 'default',
            'class' => self::SINGLE_IDENT_CLASS,
            'query_builder' => new \stdClass(),
        ));
    }

    /**
     * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException
     */
    public function testConfigureQueryBuilderWithClosureReturningNonQueryBuilder()
    {
        $field = $this->factory->createNamed('name', 'entity', null, array(
            'em' => 'default',
            'class' => self::SINGLE_IDENT_CLASS,
            'query_builder' => function () {
                return new \stdClass();
            },
        ));

        $field->submit('2');
    }

    public function testSetDataSingleNull()
    {
        $field = $this->factory->createNamed('name', 'entity', null, array(
            'multiple' => false,
            'em' => 'default',
            'class' => self::SINGLE_IDENT_CLASS,
        ));
        $field->setData(null);

        $this->assertNull($field->getData());
        $this->assertSame('', $field->getViewData());
    }

    public function testSetDataMultipleExpandedNull()
    {
        $field = $this->factory->createNamed('name', 'entity', null, array(
            'multiple' => true,
            'expanded' => true,
            'em' => 'default',
            'class' => self::SINGLE_IDENT_CLASS,
        ));
        $field->setData(null);

        $this->assertNull($field->getData());
        $this->assertSame(array(), $field->getViewData());
    }

    public function testSetDataMultipleNonExpandedNull()
    {
        $field = $this->factory->createNamed('name', 'entity', null, array(
            'multiple' => true,
            'expanded' => false,
            'em' => 'default',
            'class' => self::SINGLE_IDENT_CLASS,
        ));
        $field->setData(null);

        $this->assertNull($field->getData());
        $this->assertSame(array(), $field->getViewData());
    }

    public function testSubmitSingleExpandedNull()
    {
        $field = $this->factory->createNamed('name', 'entity', null, array(
            'multiple' => false,
            'expanded' => true,
            'em' => 'default',
            'class' => self::SINGLE_IDENT_CLASS,
        ));
        $field->submit(null);

        $this->assertNull($field->getData());
        $this->assertSame(array(), $field->getViewData());
    }

    public function testSubmitSingleNonExpandedNull()
    {
        $field = $this->factory->createNamed('name', 'entity', null, array(
            'multiple' => false,
            'expanded' => false,
            'em' => 'default',
            'class' => self::SINGLE_IDENT_CLASS,
        ));
        $field->submit(null);

        $this->assertNull($field->getData());
        $this->assertSame('', $field->getViewData());
    }

    public function testSubmitMultipleNull()
    {
        $field = $this->factory->createNamed('name', 'entity', null, array(
            'multiple' => true,
            'em' => 'default',
            'class' => self::SINGLE_IDENT_CLASS,
        ));
        $field->submit(null);

        $this->assertEquals(new ArrayCollection(), $field->getData());
        $this->assertSame(array(), $field->getViewData());
    }

    public function testSubmitSingleNonExpandedSingleIdentifier()
    {
        $entity1 = new SingleIntIdEntity(1, 'Foo');
        $entity2 = new SingleIntIdEntity(2, 'Bar');

        $this->persist(array($entity1, $entity2));

        $field = $this->factory->createNamed('name', 'entity', null, array(
            'multiple' => false,
            'expanded' => false,
            'em' => 'default',
            'class' => self::SINGLE_IDENT_CLASS,
            'property' => 'name',
        ));

        $field->submit('2');

        $this->assertTrue($field->isSynchronized());
        $this->assertSame($entity2, $field->getData());
        $this->assertSame('2', $field->getViewData());
    }

    public function testSubmitSingleNonExpandedCompositeIdentifier()
    {
        $entity1 = new CompositeIntIdEntity(10, 20, 'Foo');
        $entity2 = new CompositeIntIdEntity(30, 40, 'Bar');

        $this->persist(array($entity1, $entity2));

        $field = $this->factory->createNamed('name', 'entity', null, array(
            'multiple' => false,
            'expanded' => false,
            'em' => 'default',
            'class' => self::COMPOSITE_IDENT_CLASS,
            'property' => 'name',
        ));

        // the collection key is used here
        $field->submit('1');

        $this->assertTrue($field->isSynchronized());
        $this->assertSame($entity2, $field->getData());
        $this->assertSame('1', $field->getViewData());
    }

    public function testSubmitMultipleNonExpandedSingleIdentifier()
    {
        $entity1 = new SingleIntIdEntity(1, 'Foo');
        $entity2 = new SingleIntIdEntity(2, 'Bar');
        $entity3 = new SingleIntIdEntity(3, 'Baz');

        $this->persist(array($entity1, $entity2, $entity3));

        $field = $this->factory->createNamed('name', 'entity', null, array(
            'multiple' => true,
            'expanded' => false,
            'em' => 'default',
            'class' => self::SINGLE_IDENT_CLASS,
            'property' => 'name',
        ));

        $field->submit(array('1', '3'));

        $expected = new ArrayCollection(array($entity1, $entity3));

        $this->assertTrue($field->isSynchronized());
        $this->assertEquals($expected, $field->getData());
        $this->assertSame(array('1', '3'), $field->getViewData());
    }

    public function testSubmitMultipleNonExpandedSingleIdentifierForExistingData()
    {
        $entity1 = new SingleIntIdEntity(1, 'Foo');
        $entity2 = new SingleIntIdEntity(2, 'Bar');
        $entity3 = new SingleIntIdEntity(3, 'Baz');

        $this->persist(array($entity1, $entity2, $entity3));

        $field = $this->factory->createNamed('name', 'entity', null, array(
            'multiple' => true,
            'expanded' => false,
            'em' => 'default',
            'class' => self::SINGLE_IDENT_CLASS,
            'property' => 'name',
        ));

        $existing = new ArrayCollection(array(0 => $entity2));

        $field->setData($existing);
        $field->submit(array('1', '3'));

        // entry with index 0 ($entity2) was replaced
        $expected = new ArrayCollection(array(0 => $entity1, 1 => $entity3));

        $this->assertTrue($field->isSynchronized());
        $this->assertEquals($expected, $field->getData());
        // same object still, useful if it is a PersistentCollection
        $this->assertSame($existing, $field->getData());
        $this->assertSame(array('1', '3'), $field->getViewData());
    }

    public function testSubmitMultipleNonExpandedCompositeIdentifier()
    {
        $entity1 = new CompositeIntIdEntity(10, 20, 'Foo');
        $entity2 = new CompositeIntIdEntity(30, 40, 'Bar');
        $entity3 = new CompositeIntIdEntity(50, 60, 'Baz');

        $this->persist(array($entity1, $entity2, $entity3));

        $field = $this->factory->createNamed('name', 'entity', null, array(
            'multiple' => true,
            'expanded' => false,
            'em' => 'default',
            'class' => self::COMPOSITE_IDENT_CLASS,
            'property' => 'name',
        ));

        // because of the composite key collection keys are used
        $field->submit(array('0', '2'));

        $expected = new ArrayCollection(array($entity1, $entity3));

        $this->assertTrue($field->isSynchronized());
        $this->assertEquals($expected, $field->getData());
        $this->assertSame(array('0', '2'), $field->getViewData());
    }

    public function testSubmitMultipleNonExpandedCompositeIdentifierExistingData()
    {
        $entity1 = new CompositeIntIdEntity(10, 20, 'Foo');
        $entity2 = new CompositeIntIdEntity(30, 40, 'Bar');
        $entity3 = new CompositeIntIdEntity(50, 60, 'Baz');

        $this->persist(array($entity1, $entity2, $entity3));

        $field = $this->factory->createNamed('name', 'entity', null, array(
            'multiple' => true,
            'expanded' => false,
            'em' => 'default',
            'class' => self::COMPOSITE_IDENT_CLASS,
            'property' => 'name',
        ));

        $existing = new ArrayCollection(array(0 => $entity2));

        $field->setData($existing);
        $field->submit(array('0', '2'));

        // entry with index 0 ($entity2) was replaced
        $expected = new ArrayCollection(array(0 => $entity1, 1 => $entity3));

        $this->assertTrue($field->isSynchronized());
        $this->assertEquals($expected, $field->getData());
        // same object still, useful if it is a PersistentCollection
        $this->assertSame($existing, $field->getData());
        $this->assertSame(array('0', '2'), $field->getViewData());
    }

    public function testSubmitSingleExpanded()
    {
        $entity1 = new SingleIntIdEntity(1, 'Foo');
        $entity2 = new SingleIntIdEntity(2, 'Bar');

        $this->persist(array($entity1, $entity2));

        $field = $this->factory->createNamed('name', 'entity', null, array(
            'multiple' => false,
            'expanded' => true,
            'em' => 'default',
            'class' => self::SINGLE_IDENT_CLASS,
            'property' => 'name',
        ));

        $field->submit('2');

        $this->assertTrue($field->isSynchronized());
        $this->assertSame($entity2, $field->getData());
        $this->assertFalse($field['1']->getData());
        $this->assertTrue($field['2']->getData());
        $this->assertNull($field['1']->getViewData());
        $this->assertSame('2', $field['2']->getViewData());
    }

    public function testSubmitMultipleExpanded()
    {
        $entity1 = new SingleIntIdEntity(1, 'Foo');
        $entity2 = new SingleIntIdEntity(2, 'Bar');
        $entity3 = new SingleIntIdEntity(3, 'Bar');

        $this->persist(array($entity1, $entity2, $entity3));

        $field = $this->factory->createNamed('name', 'entity', null, array(
            'multiple' => true,
            'expanded' => true,
            'em' => 'default',
            'class' => self::SINGLE_IDENT_CLASS,
            'property' => 'name',
        ));

        $field->submit(array('1', '3'));

        $expected = new ArrayCollection(array($entity1, $entity3));

        $this->assertTrue($field->isSynchronized());
        $this->assertEquals($expected, $field->getData());
        $this->assertTrue($field['1']->getData());
        $this->assertFalse($field['2']->getData());
        $this->assertTrue($field['3']->getData());
        $this->assertSame('1', $field['1']->getViewData());
        $this->assertNull($field['2']->getViewData());
        $this->assertSame('3', $field['3']->getViewData());
    }

    public function testOverrideChoices()
    {
        $entity1 = new SingleIntIdEntity(1, 'Foo');
        $entity2 = new SingleIntIdEntity(2, 'Bar');
        $entity3 = new SingleIntIdEntity(3, 'Baz');

        $this->persist(array($entity1, $entity2, $entity3));

        $field = $this->factory->createNamed('name', 'entity', null, array(
            'em' => 'default',
            'class' => self::SINGLE_IDENT_CLASS,
            // not all persisted entities should be displayed
            'choices' => array($entity1, $entity2),
            'property' => 'name',
        ));

        $field->submit('2');

        $this->assertEquals(array(1 => new ChoiceView($entity1, '1', 'Foo'), 2 => new ChoiceView($entity2, '2', 'Bar')), $field->createView()->vars['choices']);
        $this->assertTrue($field->isSynchronized());
        $this->assertSame($entity2, $field->getData());
        $this->assertSame('2', $field->getViewData());
    }

    public function testGroupByChoices()
    {
        $item1 = new GroupableEntity(1, 'Foo', 'Group1');
        $item2 = new GroupableEntity(2, 'Bar', 'Group1');
        $item3 = new GroupableEntity(3, 'Baz', 'Group2');
        $item4 = new GroupableEntity(4, 'Boo!', null);

        $this->persist(array($item1, $item2, $item3, $item4));

        $field = $this->factory->createNamed('name', 'entity', null, array(
            'em' => 'default',
            'class' => self::ITEM_GROUP_CLASS,
            'choices' => array($item1, $item2, $item3, $item4),
            'property' => 'name',
            'group_by' => 'groupName',
        ));

        $field->submit('2');

        $this->assertSame('2', $field->getViewData());
        $this->assertEquals(array(
            'Group1' => array(1 => new ChoiceView($item1, '1', 'Foo'), 2 => new ChoiceView($item2, '2', 'Bar')),
            'Group2' => array(3 => new ChoiceView($item3, '3', 'Baz')),
            '4' => new ChoiceView($item4, '4', 'Boo!')
        ), $field->createView()->vars['choices']);
    }

    public function testPreferredChoices()
    {
        $entity1 = new SingleIntIdEntity(1, 'Foo');
        $entity2 = new SingleIntIdEntity(2, 'Bar');
        $entity3 = new SingleIntIdEntity(3, 'Baz');

        $this->persist(array($entity1, $entity2, $entity3));

        $field = $this->factory->createNamed('name', 'entity', null, array(
            'em' => 'default',
            'class' => self::SINGLE_IDENT_CLASS,
            'preferred_choices' => array($entity3, $entity2),
            'property' => 'name',
        ));

        $this->assertEquals(array(3 => new ChoiceView($entity3, '3', 'Baz'), 2 => new ChoiceView($entity2, '2', 'Bar')), $field->createView()->vars['preferred_choices']);
        $this->assertEquals(array(1 => new ChoiceView($entity1, '1', 'Foo')), $field->createView()->vars['choices']);
    }

    public function testOverrideChoicesWithPreferredChoices()
    {
        $entity1 = new SingleIntIdEntity(1, 'Foo');
        $entity2 = new SingleIntIdEntity(2, 'Bar');
        $entity3 = new SingleIntIdEntity(3, 'Baz');

        $this->persist(array($entity1, $entity2, $entity3));

        $field = $this->factory->createNamed('name', 'entity', null, array(
            'em' => 'default',
            'class' => self::SINGLE_IDENT_CLASS,
            'choices' => array($entity2, $entity3),
            'preferred_choices' => array($entity3),
            'property' => 'name',
        ));

        $this->assertEquals(array(3 => new ChoiceView($entity3, '3', 'Baz')), $field->createView()->vars['preferred_choices']);
        $this->assertEquals(array(2 => new ChoiceView($entity2, '2', 'Bar')), $field->createView()->vars['choices']);
    }

    public function testDisallowChoicesThatAreNotIncludedChoicesSingleIdentifier()
    {
        $entity1 = new SingleIntIdEntity(1, 'Foo');
        $entity2 = new SingleIntIdEntity(2, 'Bar');
        $entity3 = new SingleIntIdEntity(3, 'Baz');

        $this->persist(array($entity1, $entity2, $entity3));

        $field = $this->factory->createNamed('name', 'entity', null, array(
            'em' => 'default',
            'class' => self::SINGLE_IDENT_CLASS,
            'choices' => array($entity1, $entity2),
            'property' => 'name',
        ));

        $field->submit('3');

        $this->assertFalse($field->isSynchronized());
        $this->assertNull($field->getData());
    }

    public function testDisallowChoicesThatAreNotIncludedChoicesCompositeIdentifier()
    {
        $entity1 = new CompositeIntIdEntity(10, 20, 'Foo');
        $entity2 = new CompositeIntIdEntity(30, 40, 'Bar');
        $entity3 = new CompositeIntIdEntity(50, 60, 'Baz');

        $this->persist(array($entity1, $entity2, $entity3));

        $field = $this->factory->createNamed('name', 'entity', null, array(
            'em' => 'default',
            'class' => self::COMPOSITE_IDENT_CLASS,
            'choices' => array($entity1, $entity2),
            'property' => 'name',
        ));

        $field->submit('2');

        $this->assertFalse($field->isSynchronized());
        $this->assertNull($field->getData());
    }

    public function testDisallowChoicesThatAreNotIncludedQueryBuilderSingleIdentifier()
    {
        $entity1 = new SingleIntIdEntity(1, 'Foo');
        $entity2 = new SingleIntIdEntity(2, 'Bar');
        $entity3 = new SingleIntIdEntity(3, 'Baz');

        $this->persist(array($entity1, $entity2, $entity3));

        $repository = $this->em->getRepository(self::SINGLE_IDENT_CLASS);

        $field = $this->factory->createNamed('name', 'entity', null, array(
            'em' => 'default',
            'class' => self::SINGLE_IDENT_CLASS,
            'query_builder' => $repository->createQueryBuilder('e')
                ->where('e.id IN (1, 2)'),
            'property' => 'name',
        ));

        $field->submit('3');

        $this->assertFalse($field->isSynchronized());
        $this->assertNull($field->getData());
    }

    public function testDisallowChoicesThatAreNotIncludedQueryBuilderAsClosureSingleIdentifier()
    {
        $entity1 = new SingleIntIdEntity(1, 'Foo');
        $entity2 = new SingleIntIdEntity(2, 'Bar');
        $entity3 = new SingleIntIdEntity(3, 'Baz');

        $this->persist(array($entity1, $entity2, $entity3));

        $field = $this->factory->createNamed('name', 'entity', null, array(
            'em' => 'default',
            'class' => self::SINGLE_IDENT_CLASS,
            'query_builder' => function ($repository) {
                return $repository->createQueryBuilder('e')
                        ->where('e.id IN (1, 2)');
            },
            'property' => 'name',
        ));

        $field->submit('3');

        $this->assertFalse($field->isSynchronized());
        $this->assertNull($field->getData());
    }

    public function testDisallowChoicesThatAreNotIncludedQueryBuilderAsClosureCompositeIdentifier()
    {
        $entity1 = new CompositeIntIdEntity(10, 20, 'Foo');
        $entity2 = new CompositeIntIdEntity(30, 40, 'Bar');
        $entity3 = new CompositeIntIdEntity(50, 60, 'Baz');

        $this->persist(array($entity1, $entity2, $entity3));

        $field = $this->factory->createNamed('name', 'entity', null, array(
            'em' => 'default',
            'class' => self::COMPOSITE_IDENT_CLASS,
            'query_builder' => function ($repository) {
                return $repository->createQueryBuilder('e')
                        ->where('e.id1 IN (10, 50)');
            },
            'property' => 'name',
        ));

        $field->submit('2');

        $this->assertFalse($field->isSynchronized());
        $this->assertNull($field->getData());
    }

    public function testSubmitSingleStringIdentifier()
    {
        $entity1 = new SingleStringIdEntity('foo', 'Foo');

        $this->persist(array($entity1));

        $field = $this->factory->createNamed('name', 'entity', null, array(
            'multiple' => false,
            'expanded' => false,
            'em' => 'default',
            'class' => self::SINGLE_STRING_IDENT_CLASS,
            'property' => 'name',
        ));

        $field->submit('foo');

        $this->assertTrue($field->isSynchronized());
        $this->assertSame($entity1, $field->getData());
        $this->assertSame('foo', $field->getViewData());
    }

    public function testSubmitCompositeStringIdentifier()
    {
        $entity1 = new CompositeStringIdEntity('foo1', 'foo2', 'Foo');

        $this->persist(array($entity1));

        $field = $this->factory->createNamed('name', 'entity', null, array(
            'multiple' => false,
            'expanded' => false,
            'em' => 'default',
            'class' => self::COMPOSITE_STRING_IDENT_CLASS,
            'property' => 'name',
        ));

        // the collection key is used here
        $field->submit('0');

        $this->assertTrue($field->isSynchronized());
        $this->assertSame($entity1, $field->getData());
        $this->assertSame('0', $field->getViewData());
    }

    public function testGetManagerForClassIfNoEm()
    {
        $this->emRegistry->expects($this->never())
            ->method('getManager');

        $this->emRegistry->expects($this->once())
            ->method('getManagerForClass')
            ->with(self::SINGLE_IDENT_CLASS)
            ->will($this->returnValue($this->em));

        $this->factory->createNamed('name', 'entity', null, array(
            'class' => self::SINGLE_IDENT_CLASS,
            'required' => false,
            'property' => 'name'
        ));
    }

    protected function createRegistryMock($name, $em)
    {
        $registry = $this->getMock('Doctrine\Common\Persistence\ManagerRegistry');
        $registry->expects($this->any())
                 ->method('getManager')
                 ->with($this->equalTo($name))
                 ->will($this->returnValue($em));

        return $registry;
    }
}
PK��Z�I�m��Ytest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypePerformanceTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Form\Type;

use Symfony\Component\Form\Tests\FormPerformanceTestCase;
use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity;
use Doctrine\ORM\Tools\SchemaTool;
use Symfony\Bridge\Doctrine\Tests\DoctrineOrmTestCase;
use Symfony\Component\Form\Extension\Core\CoreExtension;
use Symfony\Bridge\Doctrine\Form\DoctrineOrmExtension;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class EntityTypePerformanceTest extends FormPerformanceTestCase
{
    const ENTITY_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity';

    /**
     * @var \Doctrine\ORM\EntityManager
     */
    private $em;

    protected function getExtensions()
    {
        $manager = $this->getMock('Doctrine\Common\Persistence\ManagerRegistry');

        $manager->expects($this->any())
            ->method('getManager')
            ->will($this->returnValue($this->em));

        $manager->expects($this->any())
            ->method('getManagerForClass')
            ->will($this->returnValue($this->em));

        return array(
            new CoreExtension(),
            new DoctrineOrmExtension($manager)
        );
    }

    protected function setUp()
    {
        $this->em = DoctrineOrmTestCase::createTestEntityManager();

        parent::setUp();

        $schemaTool = new SchemaTool($this->em);
        $classes = array(
            $this->em->getClassMetadata(self::ENTITY_CLASS),
        );

        try {
            $schemaTool->dropSchema($classes);
        } catch (\Exception $e) {
        }

        try {
            $schemaTool->createSchema($classes);
        } catch (\Exception $e) {
        }

        $ids = range(1, 300);

        foreach ($ids as $id) {
            $name = 65 + chr($id % 57);
            $this->em->persist(new SingleIntIdEntity($id, $name));
        }

        $this->em->flush();
    }

    /**
     * This test case is realistic in collection forms where each
     * row contains the same entity field.
     *
     * @group benchmark
     */
    public function testCollapsedEntityField()
    {
        $this->setMaxRunningTime(1);

        for ($i = 0; $i < 40; ++$i) {
            $form = $this->factory->create('entity', null, array(
                'class' => self::ENTITY_CLASS,
            ));

            // force loading of the choice list
            $form->createView();
        }
    }

    /**
     * @group benchmark
     */
    public function testCollapsedEntityFieldWithChoices()
    {
        $choices = $this->em->createQuery('SELECT c FROM '.self::ENTITY_CLASS.' c')->getResult();
        $this->setMaxRunningTime(1);

        for ($i = 0; $i < 40; ++$i) {
            $form = $this->factory->create('entity', null, array(
                'class' => self::ENTITY_CLASS,
                'choices' => $choices,
            ));

            // force loading of the choice list
            $form->createView();
        }
    }

    /**
     * @group benchmark
     */
    public function testCollapsedEntityFieldWithPreferredChoices()
    {
        $choices = $this->em->createQuery('SELECT c FROM '.self::ENTITY_CLASS.' c')->getResult();
        $this->setMaxRunningTime(1);

        for ($i = 0; $i < 40; ++$i) {
            $form = $this->factory->create('entity', null, array(
                    'class' => self::ENTITY_CLASS,
                    'preferred_choices' => $choices,
                ));

            // force loading of the choice list
            $form->createView();
        }
    }
}
PK��Z�;��
�
Ztest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Security/User/EntityUserProviderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Security\User;

use Symfony\Bridge\Doctrine\Test\DoctrineTestHelper;
use Symfony\Bridge\Doctrine\Tests\Fixtures\User;
use Symfony\Bridge\Doctrine\Security\User\EntityUserProvider;
use Doctrine\ORM\Tools\SchemaTool;

class EntityUserProviderTest extends \PHPUnit_Framework_TestCase
{
    public function testRefreshUserGetsUserByPrimaryKey()
    {
        $em = DoctrineTestHelper::createTestEntityManager();
        $this->createSchema($em);

        $user1 = new User(1, 1, 'user1');
        $user2 = new User(1, 2, 'user2');

        $em->persist($user1);
        $em->persist($user2);
        $em->flush();

        $provider = new EntityUserProvider($this->getManager($em), 'Symfony\Bridge\Doctrine\Tests\Fixtures\User', 'name');

        // try to change the user identity
        $user1->name = 'user2';

        $this->assertSame($user1, $provider->refreshUser($user1));
    }

    public function testRefreshUserRequiresId()
    {
        $em = DoctrineTestHelper::createTestEntityManager();

        $user1 = new User(null, null, 'user1');
        $provider = new EntityUserProvider($this->getManager($em), 'Symfony\Bridge\Doctrine\Tests\Fixtures\User', 'name');

        $this->setExpectedException(
            'InvalidArgumentException',
            'You cannot refresh a user from the EntityUserProvider that does not contain an identifier. The user object has to be serialized with its own identifier mapped by Doctrine'
        );
        $provider->refreshUser($user1);
    }

    public function testRefreshInvalidUser()
    {
        $em = DoctrineTestHelper::createTestEntityManager();
        $this->createSchema($em);

        $user1 = new User(1, 1, 'user1');

        $em->persist($user1);
        $em->flush();

        $provider = new EntityUserProvider($this->getManager($em), 'Symfony\Bridge\Doctrine\Tests\Fixtures\User', 'name');

        $user2 = new User(1, 2, 'user2');
        $this->setExpectedException(
            'Symfony\Component\Security\Core\Exception\UsernameNotFoundException',
            'User with id {"id1":1,"id2":2} not found'
        );
        $provider->refreshUser($user2);
    }

    public function testSupportProxy()
    {
        $em = DoctrineTestHelper::createTestEntityManager();
        $this->createSchema($em);

        $user1 = new User(1, 1, 'user1');

        $em->persist($user1);
        $em->flush();
        $em->clear();

        $provider = new EntityUserProvider($this->getManager($em), 'Symfony\Bridge\Doctrine\Tests\Fixtures\User', 'name');

        $user2 = $em->getReference('Symfony\Bridge\Doctrine\Tests\Fixtures\User', array('id1' => 1, 'id2' => 1));
        $this->assertTrue($provider->supportsClass(get_class($user2)));
    }

    private function getManager($em, $name = null)
    {
        $manager = $this->getMock('Doctrine\Common\Persistence\ManagerRegistry');
        $manager->expects($this->once())
            ->method('getManager')
            ->with($this->equalTo($name))
            ->will($this->returnValue($em));

        return $manager;
    }

    private function createSchema($em)
    {
        $schemaTool = new SchemaTool($em);
        $schemaTool->createSchema(array(
            $em->getClassMetadata('Symfony\Bridge\Doctrine\Tests\Fixtures\User'),
        ));
    }
}
PK��Z}��u>u>_test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueValidatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\Validator\Constraints;

use Symfony\Bridge\Doctrine\Test\DoctrineTestHelper;
use Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeIntIdEntity;
use Symfony\Component\Validator\DefaultTranslator;
use Symfony\Component\Validator\Tests\Fixtures\FakeMetadataFactory;
use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity;
use Symfony\Bridge\Doctrine\Tests\Fixtures\DoubleNameEntity;
use Symfony\Bridge\Doctrine\Tests\Fixtures\AssociationEntity;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntityValidator;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Validator;
use Doctrine\ORM\Tools\SchemaTool;

class UniqueValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected function createRegistryMock($entityManagerName, $em)
    {
        $registry = $this->getMock('Doctrine\Common\Persistence\ManagerRegistry');
        $registry->expects($this->any())
                 ->method('getManager')
                 ->with($this->equalTo($entityManagerName))
                 ->will($this->returnValue($em));

        return $registry;
    }

    protected function createRepositoryMock()
    {
        $repository = $this->getMockBuilder('Doctrine\Common\Persistence\ObjectRepository')
            ->setMethods(array('findByCustom', 'find', 'findAll', 'findOneBy', 'findBy', 'getClassName'))
            ->getMock()
        ;

        return $repository;
    }

    protected function createEntityManagerMock($repositoryMock)
    {
        $em = $this->getMockBuilder('Doctrine\Common\Persistence\ObjectManager')
            ->getMock()
        ;
        $em->expects($this->any())
             ->method('getRepository')
             ->will($this->returnValue($repositoryMock))
        ;

        $classMetadata = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata');
        $classMetadata
            ->expects($this->any())
            ->method('hasField')
            ->will($this->returnValue(true))
        ;
        $refl = $this->getMockBuilder('Doctrine\Common\Reflection\StaticReflectionProperty')
            ->disableOriginalConstructor()
            ->setMethods(array('getValue'))
            ->getMock()
        ;
        $refl
            ->expects($this->any())
            ->method('getValue')
            ->will($this->returnValue(true))
        ;
        $classMetadata->reflFields = array('name' => $refl);
        $em->expects($this->any())
             ->method('getClassMetadata')
             ->will($this->returnValue($classMetadata))
        ;

        return $em;
    }

    protected function createValidatorFactory($uniqueValidator)
    {
        $validatorFactory = $this->getMock('Symfony\Component\Validator\ConstraintValidatorFactoryInterface');
        $validatorFactory->expects($this->any())
                         ->method('getInstance')
                         ->with($this->isInstanceOf('Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity'))
                         ->will($this->returnValue($uniqueValidator));

        return $validatorFactory;
    }

    public function createValidator($entityManagerName, $em, $validateClass = null, $uniqueFields = null, $errorPath = null, $repositoryMethod = 'findBy', $ignoreNull = true)
    {
        if (!$validateClass) {
            $validateClass = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity';
        }
        if (!$uniqueFields) {
            $uniqueFields = array('name');
        }

        $registry = $this->createRegistryMock($entityManagerName, $em);

        $uniqueValidator = new UniqueEntityValidator($registry);

        $metadata = new ClassMetadata($validateClass);
        $constraint = new UniqueEntity(array(
            'fields' => $uniqueFields,
            'em' => $entityManagerName,
            'errorPath' => $errorPath,
            'repositoryMethod' => $repositoryMethod,
            'ignoreNull' => $ignoreNull
        ));
        $metadata->addConstraint($constraint);

        $metadataFactory = new FakeMetadataFactory();
        $metadataFactory->addMetadata($metadata);
        $validatorFactory = $this->createValidatorFactory($uniqueValidator);

        return new Validator($metadataFactory, $validatorFactory, new DefaultTranslator());
    }

    private function createSchema($em)
    {
        $schemaTool = new SchemaTool($em);
        $schemaTool->createSchema(array(
            $em->getClassMetadata('Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity'),
            $em->getClassMetadata('Symfony\Bridge\Doctrine\Tests\Fixtures\DoubleNameEntity'),
            $em->getClassMetadata('Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeIntIdEntity'),
            $em->getClassMetadata('Symfony\Bridge\Doctrine\Tests\Fixtures\AssociationEntity'),
        ));
    }

    /**
     * This is a functional test as there is a large integration necessary to get the validator working.
     */
    public function testValidateUniqueness()
    {
        $entityManagerName = "foo";
        $em = DoctrineTestHelper::createTestEntityManager();
        $this->createSchema($em);
        $validator = $this->createValidator($entityManagerName, $em);

        $entity1 = new SingleIntIdEntity(1, 'Foo');
        $violationsList = $validator->validate($entity1);
        $this->assertEquals(0, $violationsList->count(), "No violations found on entity before it is saved to the database.");

        $em->persist($entity1);
        $em->flush();

        $violationsList = $validator->validate($entity1);
        $this->assertEquals(0, $violationsList->count(), "No violations found on entity after it was saved to the database.");

        $entity2 = new SingleIntIdEntity(2, 'Foo');

        $violationsList = $validator->validate($entity2);
        $this->assertEquals(1, $violationsList->count(), "Violation found on entity with conflicting entity existing in the database.");

        $violation = $violationsList[0];
        $this->assertEquals('This value is already used.', $violation->getMessage());
        $this->assertEquals('name', $violation->getPropertyPath());
        $this->assertEquals('Foo', $violation->getInvalidValue());
    }

    public function testValidateCustomErrorPath()
    {
        $entityManagerName = "foo";
        $em = DoctrineTestHelper::createTestEntityManager();
        $this->createSchema($em);
        $validator = $this->createValidator($entityManagerName, $em, null, null, 'bar');

        $entity1 = new SingleIntIdEntity(1, 'Foo');

        $em->persist($entity1);
        $em->flush();

        $entity2 = new SingleIntIdEntity(2, 'Foo');

        $violationsList = $validator->validate($entity2);
        $this->assertEquals(1, $violationsList->count(), "Violation found on entity with conflicting entity existing in the database.");

        $violation = $violationsList[0];
        $this->assertEquals('This value is already used.', $violation->getMessage());
        $this->assertEquals('bar', $violation->getPropertyPath());
        $this->assertEquals('Foo', $violation->getInvalidValue());
    }

    public function testValidateUniquenessWithNull()
    {
        $entityManagerName = "foo";
        $em = DoctrineTestHelper::createTestEntityManager();
        $this->createSchema($em);
        $validator = $this->createValidator($entityManagerName, $em);

        $entity1 = new SingleIntIdEntity(1, null);
        $entity2 = new SingleIntIdEntity(2, null);

        $em->persist($entity1);
        $em->persist($entity2);
        $em->flush();

        $violationsList = $validator->validate($entity1);
        $this->assertEquals(0, $violationsList->count(), "No violations found on entity having a null value.");
    }

    public function testValidateUniquenessWithIgnoreNull()
    {
        $entityManagerName = "foo";
        $validateClass = 'Symfony\Bridge\Doctrine\Tests\Fixtures\DoubleNameEntity';
        $em = DoctrineTestHelper::createTestEntityManager();
        $this->createSchema($em);
        $validator = $this->createValidator($entityManagerName, $em, $validateClass, array('name', 'name2'), 'bar', 'findby', false);

        $entity1 = new DoubleNameEntity(1, 'Foo', null);
        $violationsList = $validator->validate($entity1);
        $this->assertEquals(0, $violationsList->count(), "No violations found on entity before it is saved to the database.");

        $em->persist($entity1);
        $em->flush();

        $violationsList = $validator->validate($entity1);
        $this->assertEquals(0, $violationsList->count(), "No violations found on entity after it was saved to the database.");

        $entity2 = new DoubleNameEntity(2, 'Foo', null);

        $violationsList = $validator->validate($entity2);
        $this->assertEquals(1, $violationsList->count(), "Violation found on entity with conflicting entity existing in the database.");

        $violation = $violationsList[0];
        $this->assertEquals('This value is already used.', $violation->getMessage());
        $this->assertEquals('bar', $violation->getPropertyPath());
        $this->assertEquals('Foo', $violation->getInvalidValue());
    }

    public function testValidateUniquenessAfterConsideringMultipleQueryResults()
    {
        $entityManagerName = "foo";
        $em = DoctrineTestHelper::createTestEntityManager();
        $this->createSchema($em);
        $validator = $this->createValidator($entityManagerName, $em);

        $entity1 = new SingleIntIdEntity(1, 'foo');
        $entity2 = new SingleIntIdEntity(2, 'foo');

        $em->persist($entity1);
        $em->persist($entity2);
        $em->flush();

        $violationsList = $validator->validate($entity1);
        $this->assertEquals(1, $violationsList->count(), 'Violation found on entity with conflicting entity existing in the database.');

        $violationsList = $validator->validate($entity2);
        $this->assertEquals(1, $violationsList->count(), 'Violation found on entity with conflicting entity existing in the database.');
    }

    public function testValidateUniquenessUsingCustomRepositoryMethod()
    {
        $entityManagerName = 'foo';
        $repository = $this->createRepositoryMock();
        $repository->expects($this->once())
             ->method('findByCustom')
             ->will($this->returnValue(array()))
        ;
        $em = $this->createEntityManagerMock($repository);
        $validator = $this->createValidator($entityManagerName, $em, null, array(), null, 'findByCustom');

        $entity1 = new SingleIntIdEntity(1, 'foo');

        $violationsList = $validator->validate($entity1);
        $this->assertEquals(0, $violationsList->count(), 'Violation is using custom repository method.');
    }

    public function testValidateUniquenessWithUnrewoundArray()
    {
        $entity = new SingleIntIdEntity(1, 'foo');

        $entityManagerName = 'foo';
        $repository = $this->createRepositoryMock();
        $repository->expects($this->once())
            ->method('findByCustom')
            ->will(
                $this->returnCallback(function () use ($entity) {
                    $returnValue = array(
                        $entity,
                    );
                    next($returnValue);

                    return $returnValue;
                })
            )
        ;
        $em = $this->createEntityManagerMock($repository);
        $validator = $this->createValidator($entityManagerName, $em, null, array(), null, 'findByCustom');

        $violationsList = $validator->validate($entity);
        $this->assertCount(0, $violationsList, 'Violation is using unrewound array as return value in the repository method.');
    }

    /**
     * @group GH-1635
     */
    public function testAssociatedEntity()
    {
        $entityManagerName = "foo";
        $em = DoctrineTestHelper::createTestEntityManager();
        $this->createSchema($em);
        $validator = $this->createValidator($entityManagerName, $em, 'Symfony\Bridge\Doctrine\Tests\Fixtures\AssociationEntity', array('single'));

        $entity1 = new SingleIntIdEntity(1, 'foo');
        $associated = new AssociationEntity();
        $associated->single = $entity1;

        $em->persist($entity1);
        $em->persist($associated);
        $em->flush();

        $violationsList = $validator->validate($associated);
        $this->assertEquals(0, $violationsList->count());

        $associated2 = new AssociationEntity();
        $associated2->single = $entity1;

        $em->persist($associated2);
        $em->flush();

        $violationsList = $validator->validate($associated2);
        $this->assertEquals(1, $violationsList->count());
    }

    public function testAssociatedEntityWithNull()
    {
        $entityManagerName = "foo";
        $em = DoctrineTestHelper::createTestEntityManager();
        $this->createSchema($em);
        $validator = $this->createValidator($entityManagerName, $em, 'Symfony\Bridge\Doctrine\Tests\Fixtures\AssociationEntity', array('single'), null, 'findBy', false);

        $associated = new AssociationEntity();
        $associated->single = null;

        $em->persist($associated);
        $em->flush();

        $violationsList = $validator->validate($associated);
        $this->assertEquals(0, $violationsList->count());
    }

    /**
     * @group GH-1635
     */
    public function testAssociatedCompositeEntity()
    {
        $entityManagerName = "foo";
        $em = DoctrineTestHelper::createTestEntityManager();
        $this->createSchema($em);
        $validator = $this->createValidator($entityManagerName, $em, 'Symfony\Bridge\Doctrine\Tests\Fixtures\AssociationEntity', array('composite'));

        $composite = new CompositeIntIdEntity(1, 1, "test");
        $associated = new AssociationEntity();
        $associated->composite = $composite;

        $em->persist($composite);
        $em->persist($associated);
        $em->flush();

        $this->setExpectedException(
            'Symfony\Component\Validator\Exception\ConstraintDefinitionException',
            'Associated entities are not allowed to have more than one identifier field'
        );
        $violationsList = $validator->validate($associated);
    }

    public function testDedicatedEntityManagerNullObject()
    {
        $uniqueFields = array('name');
        $entityManagerName = 'foo';

        $registry = $this->getMock('Doctrine\Common\Persistence\ManagerRegistry');

        $constraint = new UniqueEntity(array(
            'fields' => $uniqueFields,
            'em' => $entityManagerName,
        ));

        $uniqueValidator = new UniqueEntityValidator($registry);

        $entity = new SingleIntIdEntity(1, null);

        $this->setExpectedException(
            'Symfony\Component\Validator\Exception\ConstraintDefinitionException',
            'Object manager "foo" does not exist.'
        );

        $uniqueValidator->validate($entity, $constraint);
    }

    public function testEntityManagerNullObject()
    {
        $uniqueFields = array('name');

        $registry = $this->getMock('Doctrine\Common\Persistence\ManagerRegistry');

        $constraint = new UniqueEntity(array(
            'fields' => $uniqueFields,
        ));

        $uniqueValidator = new UniqueEntityValidator($registry);

        $entity = new SingleIntIdEntity(1, null);

        $this->setExpectedException(
            'Symfony\Component\Validator\Exception\ConstraintDefinitionException',
            'Unable to find the object manager associated with an entity of class "Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity"'
        );

        $uniqueValidator->validate($entity, $constraint);
    }
}
PK��Z���,��`test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/ExpressionLanguage/DoctrineParserCacheTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\ExpressionLanguage;

use Symfony\Bridge\Doctrine\ExpressionLanguage\DoctrineParserCache;

class DoctrineParserCacheTest extends \PHPUnit_Framework_TestCase
{
    public function testFetch()
    {
        $doctrineCacheMock = $this->getMock('Doctrine\Common\Cache\Cache');
        $parserCache = new DoctrineParserCache($doctrineCacheMock);

        $doctrineCacheMock->expects($this->once())
            ->method('fetch')
            ->will($this->returnValue('bar'));

        $result = $parserCache->fetch('foo');

        $this->assertEquals('bar', $result);
    }

    public function testFetchUnexisting()
    {
        $doctrineCacheMock = $this->getMock('Doctrine\Common\Cache\Cache');
        $parserCache = new DoctrineParserCache($doctrineCacheMock);

        $doctrineCacheMock
            ->expects($this->once())
            ->method('fetch')
            ->will($this->returnValue(false));

        $this->assertNull($parserCache->fetch(''));
    }

    public function testSave()
    {
        $doctrineCacheMock = $this->getMock('Doctrine\Common\Cache\Cache');
        $parserCache = new DoctrineParserCache($doctrineCacheMock);

        $expression = $this->getMockBuilder('Symfony\Component\ExpressionLanguage\ParsedExpression')
            ->disableOriginalConstructor()
            ->getMock();

        $doctrineCacheMock->expects($this->once())
            ->method('save')
            ->with('foo', $expression);

        $parserCache->save('foo', $expression);
    }
}
PK��Z�$K�BBTtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/ContainerAwareEventManagerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests;

use Symfony\Bridge\Doctrine\ContainerAwareEventManager;
use Symfony\Component\DependencyInjection\Container;

class ContainerAwareEventManagerTest extends \PHPUnit_Framework_TestCase
{
    protected function setUp()
    {
        $this->container = new Container();
        $this->evm = new ContainerAwareEventManager($this->container);
    }

    public function testDispatchEvent()
    {
        $this->container->set('foobar', $listener1 = new MyListener());
        $this->evm->addEventListener('foo', 'foobar');
        $this->evm->addEventListener('foo', $listener2 = new MyListener());

        $this->evm->dispatchEvent('foo');

        $this->assertTrue($listener1->called);
        $this->assertTrue($listener2->called);
    }

    public function testRemoveEventListener()
    {
        $this->evm->addEventListener('foo', 'bar');
        $this->evm->addEventListener('foo', $listener = new MyListener());

        $listeners = array('foo' => array('_service_bar' => 'bar', spl_object_hash($listener) => $listener));
        $this->assertSame($listeners, $this->evm->getListeners());
        $this->assertSame($listeners['foo'], $this->evm->getListeners('foo'));

        $this->evm->removeEventListener('foo', $listener);
        $this->assertSame(array('_service_bar' => 'bar'), $this->evm->getListeners('foo'));

        $this->evm->removeEventListener('foo', 'bar');
        $this->assertSame(array(), $this->evm->getListeners('foo'));
    }
}

class MyListener
{
    public $called = false;

    public function foo()
    {
        $this->called = true;
    }
}
PK��Z�9qq[test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/DataFixtures/ContainerAwareLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\DataFixtures;

use Symfony\Bridge\Doctrine\DataFixtures\ContainerAwareLoader;
use Symfony\Bridge\Doctrine\Tests\Fixtures\ContainerAwareFixture;

class ContainerAwareLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testShouldSetContainerOnContainerAwareFixture()
    {
        $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
        $loader    = new ContainerAwareLoader($container);
        $fixture   = new ContainerAwareFixture();

        $loader->addFixture($fixture);

        $this->assertSame($container, $fixture->container);
    }
}
PK��ZC�II[test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/HttpFoundation/DbalSessionHandlerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\HttpFoundation;

use Symfony\Bridge\Doctrine\HttpFoundation\DbalSessionHandler;

/**
 * Test class for DbalSessionHandler.
 *
 * @author Drak <drak@zikula.org>
 */
class DbalSessionHandlerTest extends \PHPUnit_Framework_TestCase
{
    public function testConstruct()
    {
        $this->connection = $this->getMock('Doctrine\DBAL\Driver\Connection');
        $mock = $this->getMockBuilder('Symfony\Bridge\Doctrine\HttpFoundation\DbalSessionHandler');
        $mock->setConstructorArgs(array($this->connection));
        $this->driver = $mock->getMock();
    }
}
PK��Z�l��]test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Doctrine\Tests\DataCollector;

use Doctrine\DBAL\Platforms\MySqlPlatform;
use Symfony\Bridge\Doctrine\DataCollector\DoctrineDataCollector;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class DoctrineDataCollectorTest extends \PHPUnit_Framework_TestCase
{
    public function testCollectConnections()
    {
        $c = $this->createCollector(array());
        $c->collect(new Request(), new Response());
        $this->assertEquals(array('default' => 'doctrine.dbal.default_connection'), $c->getConnections());
    }

    public function testCollectManagers()
    {
        $c = $this->createCollector(array());
        $c->collect(new Request(), new Response());
        $this->assertEquals(array('default' => 'doctrine.orm.default_entity_manager'), $c->getManagers());
    }

    public function testCollectQueryCount()
    {
        $c = $this->createCollector(array());
        $c->collect(new Request(), new Response());
        $this->assertEquals(0, $c->getQueryCount());

        $queries = array(
            array('sql' => "SELECT * FROM table1", 'params' => array(), 'types' => array(), 'executionMS' => 0)
        );
        $c = $this->createCollector($queries);
        $c->collect(new Request(), new Response());
        $this->assertEquals(1, $c->getQueryCount());
    }

    public function testCollectTime()
    {
        $c = $this->createCollector(array());
        $c->collect(new Request(), new Response());
        $this->assertEquals(0, $c->getTime());

        $queries = array(
            array('sql' => "SELECT * FROM table1", 'params' => array(), 'types' => array(), 'executionMS' => 1)
        );
        $c = $this->createCollector($queries);
        $c->collect(new Request(), new Response());
        $this->assertEquals(1, $c->getTime());

        $queries = array(
            array('sql' => "SELECT * FROM table1", 'params' => array(), 'types' => array(), 'executionMS' => 1),
            array('sql' => "SELECT * FROM table2", 'params' => array(), 'types' => array(), 'executionMS' => 2)
        );
        $c = $this->createCollector($queries);
        $c->collect(new Request(), new Response());
        $this->assertEquals(3, $c->getTime());
    }

    /**
     * @dataProvider paramProvider
     */
    public function testCollectQueries($param, $types, $expected, $explainable)
    {
        $queries = array(
            array('sql' => "SELECT * FROM table1 WHERE field1 = ?1", 'params' => array($param), 'types' => $types, 'executionMS' => 1)
        );
        $c = $this->createCollector($queries);
        $c->collect(new Request(), new Response());

        $collected_queries = $c->getQueries();
        $this->assertEquals($expected, $collected_queries['default'][0]['params'][0]);
        $this->assertEquals($explainable, $collected_queries['default'][0]['explainable']);
    }

    /**
     * @dataProvider paramProvider
     */
    public function testSerialization($param, $types, $expected, $explainable)
    {
        $queries = array(
            array('sql' => "SELECT * FROM table1 WHERE field1 = ?1", 'params' => array($param), 'types' => $types, 'executionMS' => 1)
        );
        $c = $this->createCollector($queries);
        $c->collect(new Request(), new Response());
        $c = unserialize(serialize($c));

        $collected_queries = $c->getQueries();
        $this->assertEquals($expected, $collected_queries['default'][0]['params'][0]);
        $this->assertEquals($explainable, $collected_queries['default'][0]['explainable']);
    }

    public function paramProvider()
    {
        return array(
            array('some value', array(), 'some value', true),
            array(1, array(), 1, true),
            array(true, array(), true, true),
            array(null, array(), null, true),
            array(new \DateTime('2011-09-11'), array('date'), '2011-09-11', true),
            array(fopen(__FILE__, 'r'), array(), 'Resource(stream)', false),
            array(new \SplFileInfo(__FILE__), array(), 'Object(SplFileInfo)', false),
        );
    }

    private function createCollector($queries)
    {
        $connection = $this->getMockBuilder('Doctrine\DBAL\Connection')
            ->disableOriginalConstructor()
            ->getMock();
        $connection->expects($this->any())
            ->method('getDatabasePlatform')
            ->will($this->returnValue(new MySqlPlatform()));

        $registry = $this->getMock('Doctrine\Common\Persistence\ManagerRegistry');
        $registry
                ->expects($this->any())
                ->method('getConnectionNames')
                ->will($this->returnValue(array('default' => 'doctrine.dbal.default_connection')));
        $registry
                ->expects($this->any())
                ->method('getManagerNames')
                ->will($this->returnValue(array('default' => 'doctrine.orm.default_entity_manager')));
        $registry->expects($this->any())
            ->method('getConnection')
            ->will($this->returnValue($connection));

        $logger = $this->getMock('Doctrine\DBAL\Logging\DebugStack');
        $logger->queries = $queries;

        $collector = new DoctrineDataCollector($registry);
        $collector->addLogger('default', $logger);

        return $collector;
    }
}
PK��ZO����test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPassTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Bridge\Doctrine\Tests\DependencyInjection\CompilerPass;

use Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass\RegisterEventListenersAndSubscribersPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class RegisterEventListenersAndSubscribersPassTest extends \PHPUnit_Framework_TestCase
{
    public function testProcessEventListenersWithPriorities()
    {
        $container = $this->createBuilder();

        $container
            ->register('a', 'stdClass')
            ->addTag('doctrine.event_listener', array(
                'event' => 'foo',
                'priority' => -5,
            ))
            ->addTag('doctrine.event_listener', array(
                'event' => 'bar',
            ))
        ;
        $container
            ->register('b', 'stdClass')
            ->addTag('doctrine.event_listener', array(
                'event' => 'foo',
            ))
        ;

        $this->process($container);
        $this->assertEquals(array('b', 'a'), $this->getServiceOrder($container, 'addEventListener'));

        $calls = $container->getDefinition('doctrine.dbal.default_connection.event_manager')->getMethodCalls();
        $this->assertEquals(array('foo', 'bar'), $calls[1][1][0]);
    }

    public function testProcessEventListenersWithMultipleConnections()
    {
        $container = $this->createBuilder(true);

        $container
            ->register('a', 'stdClass')
            ->addTag('doctrine.event_listener', array(
                'event' => 'onFlush',
            ))
        ;
        $this->process($container);

        $callsDefault = $container->getDefinition('doctrine.dbal.default_connection.event_manager')->getMethodCalls();

        $this->assertEquals('addEventListener', $callsDefault[0][0]);
        $this->assertEquals(array('onFlush'), $callsDefault[0][1][0]);

        $callsSecond = $container->getDefinition('doctrine.dbal.second_connection.event_manager')->getMethodCalls();
        $this->assertEquals($callsDefault, $callsSecond);
    }

    public function testProcessEventSubscribersWithPriorities()
    {
        $container = $this->createBuilder();

        $container
            ->register('a', 'stdClass')
            ->addTag('doctrine.event_subscriber')
        ;
        $container
            ->register('b', 'stdClass')
            ->addTag('doctrine.event_subscriber', array(
                'priority' => 5,
            ))
        ;
        $container
            ->register('c', 'stdClass')
            ->addTag('doctrine.event_subscriber', array(
                'priority' => 10,
            ))
        ;
        $container
            ->register('d', 'stdClass')
            ->addTag('doctrine.event_subscriber', array(
                'priority' => 10,
            ))
        ;
        $container
            ->register('e', 'stdClass')
            ->addTag('doctrine.event_subscriber', array(
                'priority' => 10,
            ))
        ;

        $this->process($container);
        $this->assertEquals(array('c', 'd', 'e', 'b', 'a'), $this->getServiceOrder($container, 'addEventSubscriber'));
    }

    public function testProcessNoTaggedServices()
    {
        $container = $this->createBuilder(true);

        $this->process($container);

        $this->assertEquals(array(), $container->getDefinition('doctrine.dbal.default_connection.event_manager')->getMethodCalls());

        $this->assertEquals(array(), $container->getDefinition('doctrine.dbal.second_connection.event_manager')->getMethodCalls());
    }

    private function process(ContainerBuilder $container)
    {
        $pass = new RegisterEventListenersAndSubscribersPass('doctrine.connections', 'doctrine.dbal.%s_connection.event_manager', 'doctrine');
        $pass->process($container);
    }

    private function getServiceOrder(ContainerBuilder $container, $method)
    {
        $order = array();
        foreach ($container->getDefinition('doctrine.dbal.default_connection.event_manager')->getMethodCalls() as $call) {
            list($name, $arguments) = $call;
            if ($method !== $name) {
                continue;
            }

            if ('addEventListener' === $name) {
                $order[] = (string) $arguments[1];
                continue;
            }

            $order[] = (string) $arguments[0];
        }

        return $order;
    }

    private function createBuilder($multipleConnections = false)
    {
        $container = new ContainerBuilder();

        $connections = array('default' => 'doctrine.dbal.default_connection');

        $container->register('doctrine.dbal.default_connection.event_manager', 'stdClass');
        $container->register('doctrine.dbal.default_connection', 'stdClass');

        if ($multipleConnections) {
            $container->register('doctrine.dbal.second_connection.event_manager', 'stdClass');
            $container->register('doctrine.dbal.second_connection', 'stdClass');
            $connections['second'] = 'doctrine.dbal.second_connection';
        }

        $container->setParameter('doctrine.connections', $connections);

        return $container;
    }
}
PK��Z�ޠ�77<test/DoctrineBridge/Symfony/Bridge/Doctrine/phpunit.xml.distnu�[���<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="Tests/bootstrap.php"
>
    <testsuites>
        <testsuite name="Symfony Doctrine Bridge Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./Resources</directory>
                <directory>./Tests</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
PK��Z&�ǦGGNtest/MonologBridge/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Monolog\Tests\Handler;

use Monolog\Logger;
use Symfony\Bridge\Monolog\Handler\ConsoleHandler;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * Tests the ConsoleHandler and also the ConsoleFormatter.
 *
 * @author Tobias Schultze <http://tobion.de>
 */
class ConsoleHandlerTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $handler = new ConsoleHandler(null, false);
        $this->assertFalse($handler->getBubble(), 'the bubble parameter gets propagated');
    }

    public function testIsHandling()
    {
        $handler = new ConsoleHandler();
        $this->assertFalse($handler->isHandling(array()), '->isHandling returns false when no output is set');
    }

    /**
     * @dataProvider provideVerbosityMappingTests
     */
    public function testVerbosityMapping($verbosity, $level, $isHandling, array $map = array())
    {
        $output = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
        $output
            ->expects($this->atLeastOnce())
            ->method('getVerbosity')
            ->will($this->returnValue($verbosity))
        ;
        $handler = new ConsoleHandler($output, true, $map);
        $this->assertSame($isHandling, $handler->isHandling(array('level' => $level)),
            '->isHandling returns correct value depending on console verbosity and log level'
        );
    }

    public function provideVerbosityMappingTests()
    {
        return array(
            array(OutputInterface::VERBOSITY_QUIET, Logger::ERROR, false),
            array(OutputInterface::VERBOSITY_NORMAL, Logger::WARNING, true),
            array(OutputInterface::VERBOSITY_NORMAL, Logger::NOTICE, false),
            array(OutputInterface::VERBOSITY_VERBOSE, Logger::NOTICE, true),
            array(OutputInterface::VERBOSITY_VERBOSE, Logger::INFO, false),
            array(OutputInterface::VERBOSITY_VERY_VERBOSE, Logger::INFO, true),
            array(OutputInterface::VERBOSITY_VERY_VERBOSE, Logger::DEBUG, false),
            array(OutputInterface::VERBOSITY_DEBUG, Logger::DEBUG, true),
            array(OutputInterface::VERBOSITY_DEBUG, Logger::EMERGENCY, true),
            array(OutputInterface::VERBOSITY_NORMAL, Logger::NOTICE, true, array(
                OutputInterface::VERBOSITY_NORMAL => Logger::NOTICE
            )),
            array(OutputInterface::VERBOSITY_DEBUG, Logger::NOTICE, true, array(
                OutputInterface::VERBOSITY_NORMAL => Logger::NOTICE
            )),
        );
    }

    public function testVerbosityChanged()
    {
        $output = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
        $output
            ->expects($this->at(0))
            ->method('getVerbosity')
            ->will($this->returnValue(OutputInterface::VERBOSITY_QUIET))
        ;
        $output
            ->expects($this->at(1))
            ->method('getVerbosity')
            ->will($this->returnValue(OutputInterface::VERBOSITY_DEBUG))
        ;
        $handler = new ConsoleHandler($output);
        $this->assertFalse($handler->isHandling(array('level' => Logger::NOTICE)),
            'when verbosity is set to quiet, the handler does not handle the log'
        );
        $this->assertTrue($handler->isHandling(array('level' => Logger::NOTICE)),
            'since the verbosity of the output increased externally, the handler is now handling the log'
        );
    }

    public function testGetFormatter()
    {
        $handler = new ConsoleHandler();
        $this->assertInstanceOf('Symfony\Bridge\Monolog\Formatter\ConsoleFormatter', $handler->getFormatter(),
            '-getFormatter returns ConsoleFormatter by default'
        );
    }

    public function testWritingAndFormatting()
    {
        $output = $this->getMock('Symfony\Component\Console\Output\ConsoleOutputInterface');
        $output
            ->expects($this->any())
            ->method('getVerbosity')
            ->will($this->returnValue(OutputInterface::VERBOSITY_DEBUG))
        ;
        $output
            ->expects($this->once())
            ->method('write')
            ->with('<info>[2013-05-29 16:21:54] app.INFO:</info> My info message [] []'."\n")
        ;

        $errorOutput = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
        $errorOutput
            ->expects($this->once())
            ->method('write')
            ->with('<error>[2013-05-29 16:21:54] app.ERROR:</error> My error message [] []'."\n")
        ;

        $output
            ->expects($this->any())
            ->method('getErrorOutput')
            ->will($this->returnValue($errorOutput))
        ;

        $handler = new ConsoleHandler(null, false);
        $handler->setOutput($output);

        $infoRecord = array(
            'message' => 'My info message',
            'context' => array(),
            'level' => Logger::INFO,
            'level_name' => Logger::getLevelName(Logger::INFO),
            'channel' => 'app',
            'datetime' => new \DateTime('2013-05-29 16:21:54'),
            'extra' => array(),
        );

        $this->assertTrue($handler->handle($infoRecord), 'The handler finished handling the log as bubble is false.');

        $errorRecord = array(
            'message' => 'My error message',
            'context' => array(),
            'level' => Logger::ERROR,
            'level_name' => Logger::getLevelName(Logger::ERROR),
            'channel' => 'app',
            'datetime' => new \DateTime('2013-05-29 16:21:54'),
            'extra' => array(),
        );

        $this->assertTrue($handler->handle($errorRecord), 'The handler finished handling the log as bubble is false.');
    }
}
PK��Z�o.���Ntest/MonologBridge/Symfony/Bridge/Monolog/Tests/Processor/WebProcessorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Bridge\Monolog\Tests\Processor;

use Monolog\Logger;
use Symfony\Bridge\Monolog\Processor\WebProcessor;
use Symfony\Component\HttpFoundation\Request;

class WebProcessorTest extends \PHPUnit_Framework_TestCase
{
    public function testUsesRequestServerData()
    {
        $server = array(
            'REQUEST_URI'    => 'A',
            'REMOTE_ADDR'    => 'B',
            'REQUEST_METHOD' => 'C',
            'SERVER_NAME'    => 'D',
            'HTTP_REFERER'   => 'E'
        );

        $request = new Request();
        $request->server->replace($server);

        $event = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\GetResponseEvent')
            ->disableOriginalConstructor()
            ->getMock();
        $event->expects($this->any())
            ->method('isMasterRequest')
            ->will($this->returnValue(true));
        $event->expects($this->any())
            ->method('getRequest')
            ->will($this->returnValue($request));

        $processor = new WebProcessor();
        $processor->onKernelRequest($event);
        $record = $processor($this->getRecord());

        $this->assertEquals($server['REQUEST_URI'], $record['extra']['url']);
        $this->assertEquals($server['REMOTE_ADDR'], $record['extra']['ip']);
        $this->assertEquals($server['REQUEST_METHOD'], $record['extra']['http_method']);
        $this->assertEquals($server['SERVER_NAME'], $record['extra']['server']);
        $this->assertEquals($server['HTTP_REFERER'], $record['extra']['referrer']);
    }

    /**
     * @param integer $level
     * @param string  $message
     *
     * @return array Record
     */
    protected function getRecord($level = Logger::WARNING, $message = 'test')
    {
        return array(
            'message' => $message,
            'context' => array(),
            'level' => $level,
            'level_name' => Logger::getLevelName($level),
            'channel' => 'test',
            'datetime' => new \DateTime(),
            'extra' => array(),
        );
    }
}
PK��Z��Ki66:test/MonologBridge/Symfony/Bridge/Monolog/phpunit.xml.distnu�[���<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony Monolog Bridge Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./Resources</directory>
                <directory>./Tests</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
PK��Z}/�66Mtest/Templating/Symfony/Component/Templating/Tests/TemplateNameParserTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Tests;

use Symfony\Component\Templating\TemplateNameParser;
use Symfony\Component\Templating\TemplateReference;

class TemplateNameParserTest extends \PHPUnit_Framework_TestCase
{
    protected $parser;

    protected function setUp()
    {
        $this->parser = new TemplateNameParser();
    }

    protected function tearDown()
    {
        $this->parser = null;
    }

    /**
     * @dataProvider getLogicalNameToTemplateProvider
     */
    public function testParse($name, $ref)
    {
        $template = $this->parser->parse($name);

        $this->assertEquals($template->getLogicalName(), $ref->getLogicalName());
        $this->assertEquals($template->getLogicalName(), $name);
    }

    public function getLogicalNameToTemplateProvider()
    {
        return array(
            array('/path/to/section/name.engine', new TemplateReference('/path/to/section/name.engine', 'engine')),
            array('name.engine', new TemplateReference('name.engine', 'engine')),
            array('name', new TemplateReference('name')),
        );
    }
}
PK��Z���xxLtest/Templating/Symfony/Component/Templating/Tests/Fixtures/SimpleHelper.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Tests\Fixtures;

use Symfony\Component\Templating\Helper\Helper;

class SimpleHelper extends Helper
{
    protected $value = '';

    public function __construct($value)
    {
        $this->value = $value;
    }

    public function __toString()
    {
        return $this->value;
    }

    public function getName()
    {
        return 'foo';
    }
}
PK��Z�`�2Mtest/Templating/Symfony/Component/Templating/Tests/Fixtures/templates/foo.phpnu�[���<?php echo $foo ?>
PK��Z=D����Ntest/Templating/Symfony/Component/Templating/Tests/Storage/FileStorageTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Tests\Storage;

use Symfony\Component\Templating\Storage\Storage;
use Symfony\Component\Templating\Storage\FileStorage;

class FileStorageTest extends \PHPUnit_Framework_TestCase
{
    public function testGetContent()
    {
        $storage = new FileStorage('foo');
        $this->assertInstanceOf('Symfony\Component\Templating\Storage\Storage', $storage, 'FileStorage is an instance of Storage');
        $storage = new FileStorage(__DIR__.'/../Fixtures/templates/foo.php');
        $this->assertEquals('<?php echo $foo ?>'."\n", $storage->getContent(), '->getContent() returns the content of the template');
    }
}
PK��Z`7�SSPtest/Templating/Symfony/Component/Templating/Tests/Storage/StringStorageTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Tests\Storage;

use Symfony\Component\Templating\Storage\Storage;
use Symfony\Component\Templating\Storage\StringStorage;

class StringStorageTest extends \PHPUnit_Framework_TestCase
{
    public function testGetContent()
    {
        $storage = new StringStorage('foo');
        $this->assertInstanceOf('Symfony\Component\Templating\Storage\Storage', $storage, 'StringStorage is an instance of Storage');
        $storage = new StringStorage('foo');
        $this->assertEquals('foo', $storage->getContent(), '->getContent() returns the content of the template');
    }
}
PK��ZS	�٦�Jtest/Templating/Symfony/Component/Templating/Tests/Storage/StorageTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Tests\Storage;

use Symfony\Component\Templating\Storage\Storage;

class StorageTest extends \PHPUnit_Framework_TestCase
{
    public function testMagicToString()
    {
        $storage = new TestStorage('foo');
        $this->assertEquals('foo', (string) $storage, '__toString() returns the template name');
    }
}

class TestStorage extends Storage
{
    public function getContent()
    {
    }
}
PK��Z��7���Htest/Templating/Symfony/Component/Templating/Tests/Loader/LoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Tests\Loader;

use Symfony\Component\Templating\Loader\Loader;
use Symfony\Component\Templating\TemplateReferenceInterface;

class LoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testGetSetLogger()
    {
        $loader = new ProjectTemplateLoader4();
        $logger = $this->getMock('Psr\Log\LoggerInterface');
        $loader->setLogger($logger);
        $this->assertSame($logger, $loader->getLogger(), '->setLogger() sets the logger instance');
    }

    public function testGetSetDebugger()
    {
        $loader = new ProjectTemplateLoader4();
        $debugger = $this->getMock('Symfony\Component\Templating\DebuggerInterface');
        $loader->setDebugger($debugger);
        $this->assertSame($debugger, $loader->getDebugger(), '->setDebugger() sets the debugger instance');
    }
}

class ProjectTemplateLoader4 extends Loader
{
    public function load(TemplateReferenceInterface $template)
    {
    }

    public function getLogger()
    {
        return $this->logger;
    }

    public function getDebugger()
    {
        return $this->debugger;
    }

    public function isFresh(TemplateReferenceInterface $template, $time)
    {
        return false;
    }
}
PK��ZWl�‡�Rtest/Templating/Symfony/Component/Templating/Tests/Loader/FilesystemLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Tests\Loader;

use Symfony\Component\Templating\Loader\FilesystemLoader;
use Symfony\Component\Templating\Storage\FileStorage;
use Symfony\Component\Templating\TemplateReference;

class FilesystemLoaderTest extends \PHPUnit_Framework_TestCase
{
    protected static $fixturesPath;

    public static function setUpBeforeClass()
    {
        self::$fixturesPath = realpath(__DIR__.'/../Fixtures/');
    }

    public function testConstructor()
    {
        $pathPattern = self::$fixturesPath.'/templates/%name%.%engine%';
        $path = self::$fixturesPath.'/templates';
        $loader = new ProjectTemplateLoader2($pathPattern);
        $this->assertEquals(array($pathPattern), $loader->getTemplatePathPatterns(), '__construct() takes a path as its second argument');
        $loader = new ProjectTemplateLoader2(array($pathPattern));
        $this->assertEquals(array($pathPattern), $loader->getTemplatePathPatterns(), '__construct() takes an array of paths as its second argument');
    }

    public function testIsAbsolutePath()
    {
        $this->assertTrue(ProjectTemplateLoader2::isAbsolutePath('/foo.xml'), '->isAbsolutePath() returns true if the path is an absolute path');
        $this->assertTrue(ProjectTemplateLoader2::isAbsolutePath('c:\\\\foo.xml'), '->isAbsolutePath() returns true if the path is an absolute path');
        $this->assertTrue(ProjectTemplateLoader2::isAbsolutePath('c:/foo.xml'), '->isAbsolutePath() returns true if the path is an absolute path');
        $this->assertTrue(ProjectTemplateLoader2::isAbsolutePath('\\server\\foo.xml'), '->isAbsolutePath() returns true if the path is an absolute path');
        $this->assertTrue(ProjectTemplateLoader2::isAbsolutePath('https://server/foo.xml'), '->isAbsolutePath() returns true if the path is an absolute path');
        $this->assertTrue(ProjectTemplateLoader2::isAbsolutePath('phar://server/foo.xml'), '->isAbsolutePath() returns true if the path is an absolute path');
    }

    public function testLoad()
    {
        $pathPattern = self::$fixturesPath.'/templates/%name%';
        $path = self::$fixturesPath.'/templates';
        $loader = new ProjectTemplateLoader2($pathPattern);
        $storage = $loader->load(new TemplateReference($path.'/foo.php', 'php'));
        $this->assertInstanceOf('Symfony\Component\Templating\Storage\FileStorage', $storage, '->load() returns a FileStorage if you pass an absolute path');
        $this->assertEquals($path.'/foo.php', (string) $storage, '->load() returns a FileStorage pointing to the passed absolute path');

        $this->assertFalse($loader->load(new TemplateReference('bar', 'php')), '->load() returns false if the template is not found');

        $storage = $loader->load(new TemplateReference('foo.php', 'php'));
        $this->assertInstanceOf('Symfony\Component\Templating\Storage\FileStorage', $storage, '->load() returns a FileStorage if you pass a relative template that exists');
        $this->assertEquals($path.'/foo.php', (string) $storage, '->load() returns a FileStorage pointing to the absolute path of the template');

        $logger = $this->getMock('Psr\Log\LoggerInterface');
        $logger->expects($this->exactly(2))->method('debug');

        $loader = new ProjectTemplateLoader2($pathPattern);
        $loader->setLogger($logger);
        $this->assertFalse($loader->load(new TemplateReference('foo.xml', 'php')), '->load() returns false if the template does not exist for the given engine');

        $loader = new ProjectTemplateLoader2(array(self::$fixturesPath.'/null/%name%', $pathPattern));
        $loader->setLogger($logger);
        $loader->load(new TemplateReference('foo.php', 'php'));
    }
}

class ProjectTemplateLoader2 extends FilesystemLoader
{
    public function getTemplatePathPatterns()
    {
        return $this->templatePathPatterns;
    }

    public static function isAbsolutePath($path)
    {
        return parent::isAbsolutePath($path);
    }
}
PK��Z���
�
Mtest/Templating/Symfony/Component/Templating/Tests/Loader/CacheLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Tests\Loader;

use Symfony\Component\Templating\Loader\Loader;
use Symfony\Component\Templating\Loader\CacheLoader;
use Symfony\Component\Templating\Storage\StringStorage;
use Symfony\Component\Templating\TemplateReferenceInterface;
use Symfony\Component\Templating\TemplateReference;

class CacheLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $loader = new ProjectTemplateLoader($varLoader = new ProjectTemplateLoaderVar(), sys_get_temp_dir());
        $this->assertTrue($loader->getLoader() === $varLoader, '__construct() takes a template loader as its first argument');
        $this->assertEquals(sys_get_temp_dir(), $loader->getDir(), '__construct() takes a directory where to store the cache as its second argument');
    }

    public function testLoad()
    {
        $dir = sys_get_temp_dir().DIRECTORY_SEPARATOR.rand(111111, 999999);
        mkdir($dir, 0777, true);

        $loader = new ProjectTemplateLoader($varLoader = new ProjectTemplateLoaderVar(), $dir);
        $this->assertFalse($loader->load(new TemplateReference('foo', 'php')), '->load() returns false if the embed loader is not able to load the template');

        $logger = $this->getMock('Psr\Log\LoggerInterface');
        $logger->expects($this->once())->method('debug')->with('Storing template "index" in cache');
        $loader->setLogger($logger);
        $loader->load(new TemplateReference('index'));

        $logger = $this->getMock('Psr\Log\LoggerInterface');
        $logger->expects($this->once())->method('debug')->with('Fetching template "index" from cache');
        $loader->setLogger($logger);
        $loader->load(new TemplateReference('index'));
    }
}

class ProjectTemplateLoader extends CacheLoader
{
    public function getDir()
    {
        return $this->dir;
    }

    public function getLoader()
    {
        return $this->loader;
    }
}

class ProjectTemplateLoaderVar extends Loader
{
    public function getIndexTemplate()
    {
        return 'Hello World';
    }

    public function getSpecialTemplate()
    {
        return 'Hello {{ name }}';
    }

    public function load(TemplateReferenceInterface $template)
    {
        if (method_exists($this, $method = 'get'.ucfirst($template->get('name')).'Template')) {
            return new StringStorage($this->$method());
        }

        return false;
    }

    public function isFresh(TemplateReferenceInterface $template, $time)
    {
        return false;
    }
}
PK��ZˡA`��Mtest/Templating/Symfony/Component/Templating/Tests/Loader/ChainLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Tests\Loader;

use Symfony\Component\Templating\Loader\ChainLoader;
use Symfony\Component\Templating\Loader\FilesystemLoader;
use Symfony\Component\Templating\Storage\FileStorage;
use Symfony\Component\Templating\TemplateReference;

class ChainLoaderTest extends \PHPUnit_Framework_TestCase
{
    protected $loader1;
    protected $loader2;

    protected function setUp()
    {
        $fixturesPath = realpath(__DIR__.'/../Fixtures/');
        $this->loader1 = new FilesystemLoader($fixturesPath.'/null/%name%');
        $this->loader2 = new FilesystemLoader($fixturesPath.'/templates/%name%');
    }

    public function testConstructor()
    {
        $loader = new ProjectTemplateLoader1(array($this->loader1, $this->loader2));
        $this->assertEquals(array($this->loader1, $this->loader2), $loader->getLoaders(), '__construct() takes an array of template loaders as its second argument');
    }

    public function testAddLoader()
    {
        $loader = new ProjectTemplateLoader1(array($this->loader1));
        $loader->addLoader($this->loader2);
        $this->assertEquals(array($this->loader1, $this->loader2), $loader->getLoaders(), '->addLoader() adds a template loader at the end of the loaders');
    }

    public function testLoad()
    {
        $loader = new ProjectTemplateLoader1(array($this->loader1, $this->loader2));
        $this->assertFalse($loader->load(new TemplateReference('bar', 'php')), '->load() returns false if the template is not found');
        $this->assertFalse($loader->load(new TemplateReference('foo', 'php')), '->load() returns false if the template does not exist for the given renderer');
        $this->assertInstanceOf(
            'Symfony\Component\Templating\Storage\FileStorage',
            $loader->load(new TemplateReference('foo.php', 'php')),
            '->load() returns a FileStorage if the template exists'
        );
    }
}

class ProjectTemplateLoader1 extends ChainLoader
{
    public function getLoaders()
    {
        return $this->loaders;
    }
}
PK��Z�`n}�
�
Ntest/Templating/Symfony/Component/Templating/Tests/Helper/AssetsHelperTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Tests\Helper;

use Symfony\Component\Templating\Helper\AssetsHelper;

class AssetsHelperTest extends \PHPUnit_Framework_TestCase
{
    public function testGetVersion()
    {
        $helper = new AssetsHelper(null, array(), 'foo');
        $this->assertEquals('foo', $helper->getVersion(), '->getVersion() returns the version');
    }

    public function testGetUrl()
    {
        $helper = new AssetsHelper();
        $this->assertEquals('http://example.com/foo.js', $helper->getUrl('http://example.com/foo.js'), '->getUrl() does nothing if an absolute URL is given');

        $helper = new AssetsHelper();
        $this->assertEquals('/foo.js', $helper->getUrl('foo.js'), '->getUrl() appends a / on relative paths');
        $this->assertEquals('/foo.js', $helper->getUrl('/foo.js'), '->getUrl() does nothing on absolute paths');

        $helper = new AssetsHelper('/foo');
        $this->assertEquals('/foo/foo.js', $helper->getUrl('foo.js'), '->getUrl() appends the basePath on relative paths');
        $this->assertEquals('/foo.js', $helper->getUrl('/foo.js'), '->getUrl() does not append the basePath on absolute paths');

        $helper = new AssetsHelper(null, 'http://assets.example.com/');
        $this->assertEquals('http://assets.example.com/foo.js', $helper->getUrl('foo.js'), '->getUrl() prepends the base URL');
        $this->assertEquals('http://assets.example.com/foo.js', $helper->getUrl('/foo.js'), '->getUrl() prepends the base URL');

        $helper = new AssetsHelper(null, 'http://www.example.com/foo');
        $this->assertEquals('http://www.example.com/foo/foo.js', $helper->getUrl('foo.js'), '->getUrl() prepends the base URL with a path');
        $this->assertEquals('http://www.example.com/foo/foo.js', $helper->getUrl('/foo.js'), '->getUrl() prepends the base URL with a path');

        $helper = new AssetsHelper('/foo', 'http://www.example.com/');
        $this->assertEquals('http://www.example.com/foo.js', $helper->getUrl('foo.js'), '->getUrl() prepends the base URL and the base path if defined');
        $this->assertEquals('http://www.example.com/foo.js', $helper->getUrl('/foo.js'), '->getUrl() prepends the base URL but not the base path on absolute paths');

        $helper = new AssetsHelper('/bar', 'http://www.example.com/foo');
        $this->assertEquals('http://www.example.com/foo/foo.js', $helper->getUrl('foo.js'), '->getUrl() prepends the base URL and the base path if defined');
        $this->assertEquals('http://www.example.com/foo/foo.js', $helper->getUrl('/foo.js'), '->getUrl() prepends the base URL but not the base path on absolute paths');

        $helper = new AssetsHelper('/bar', 'http://www.example.com/foo', 'abcd');
        $this->assertEquals('http://www.example.com/foo/foo.js?abcd', $helper->getUrl('foo.js'), '->getUrl() appends the version if defined');

        $helper = new AssetsHelper();
        $this->assertEquals('/', $helper->getUrl(''), '->getUrl() with empty arg returns the prefix alone');
    }

    public function testGetUrlLeavesProtocolRelativePathsUntouched()
    {
        $helper = new AssetsHelper(null, 'http://foo.com');
        $this->assertEquals('//bar.com/asset', $helper->getUrl('//bar.com/asset'));
    }
}
PK��Z�q=R

Htest/Templating/Symfony/Component/Templating/Tests/Helper/HelperTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Tests\Helper;

use Symfony\Component\Templating\Helper\Helper;

class HelperTest extends \PHPUnit_Framework_TestCase
{
    public function testGetSetCharset()
    {
        $helper = new ProjectTemplateHelper();
        $helper->setCharset('ISO-8859-1');
        $this->assertTrue('ISO-8859-1' === $helper->getCharset(), '->setCharset() sets the charset set related to this helper');
    }
}

class ProjectTemplateHelper extends Helper
{
    public function getName()
    {
        return 'foo';
    }
}
PK��ZM<��Rtest/Templating/Symfony/Component/Templating/Tests/Helper/CoreAssetsHelperTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Tests\Helper;

use Symfony\Component\Templating\Helper\CoreAssetsHelper;

class CoreAssetsHelperTest extends \PHPUnit_Framework_TestCase
{
    protected $package;

    protected function setUp()
    {
        $this->package = $this->getMock('Symfony\Component\Templating\Asset\PackageInterface');
    }

    protected function tearDown()
    {
        $this->package = null;
    }

    public function testAddGetPackage()
    {
        $helper = new CoreAssetsHelper($this->package);

        $helper->addPackage('foo', $this->package);

        $this->assertSame($this->package, $helper->getPackage('foo'));
    }

    public function testGetNonexistingPackage()
    {
        $helper = new CoreAssetsHelper($this->package);

        $this->setExpectedException('\InvalidArgumentException');

        $helper->getPackage('foo');
    }

    public function testGetHelperName()
    {
        $helper = new CoreAssetsHelper($this->package);

        $this->assertEquals('assets', $helper->getName());
    }
}
PK��Z0�nl

Mtest/Templating/Symfony/Component/Templating/Tests/Helper/SlotsHelperTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Tests\Helper;

use Symfony\Component\Templating\Helper\SlotsHelper;

class SlotsHelperTest extends \PHPUnit_Framework_TestCase
{
    public function testHasGetSet()
    {
        $helper = new SlotsHelper();
        $helper->set('foo', 'bar');
        $this->assertEquals('bar', $helper->get('foo'), '->set() sets a slot value');
        $this->assertEquals('bar', $helper->get('bar', 'bar'), '->get() takes a default value to return if the slot does not exist');

        $this->assertTrue($helper->has('foo'), '->has() returns true if the slot exists');
        $this->assertFalse($helper->has('bar'), '->has() returns false if the slot does not exist');
    }

    public function testOutput()
    {
        $helper = new SlotsHelper();
        $helper->set('foo', 'bar');
        ob_start();
        $ret = $helper->output('foo');
        $output = ob_get_clean();
        $this->assertEquals('bar', $output, '->output() outputs the content of a slot');
        $this->assertTrue($ret, '->output() returns true if the slot exists');

        ob_start();
        $ret = $helper->output('bar', 'bar');
        $output = ob_get_clean();
        $this->assertEquals('bar', $output, '->output() takes a default value to return if the slot does not exist');
        $this->assertTrue($ret, '->output() returns true if the slot does not exist but a default value is provided');

        ob_start();
        $ret = $helper->output('bar');
        $output = ob_get_clean();
        $this->assertEquals('', $output, '->output() outputs nothing if the slot does not exist');
        $this->assertFalse($ret, '->output() returns false if the slot does not exist');
    }

    public function testStartStop()
    {
        $helper = new SlotsHelper();
        $helper->start('bar');
        echo 'foo';
        $helper->stop();
        $this->assertEquals('foo', $helper->get('bar'), '->start() starts a slot');
        $this->assertTrue($helper->has('bar'), '->starts() starts a slot');

        $helper->start('bar');
        try {
            $helper->start('bar');
            $helper->stop();
            $this->fail('->start() throws an InvalidArgumentException if a slot with the same name is already started');
        } catch (\Exception $e) {
            $helper->stop();
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->start() throws an InvalidArgumentException if a slot with the same name is already started');
            $this->assertEquals('A slot named "bar" is already started.', $e->getMessage(), '->start() throws an InvalidArgumentException if a slot with the same name is already started');
        }

        try {
            $helper->stop();
            $this->fail('->stop() throws an LogicException if no slot is started');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\LogicException', $e, '->stop() throws an LogicException if no slot is started');
            $this->assertEquals('No slot started.', $e->getMessage(), '->stop() throws an LogicException if no slot is started');
        }
    }
}
PK��Z��`#`#Dtest/Templating/Symfony/Component/Templating/Tests/PhpEngineTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Tests;

use Symfony\Component\Templating\PhpEngine;
use Symfony\Component\Templating\Loader\Loader;
use Symfony\Component\Templating\Storage\Storage;
use Symfony\Component\Templating\Storage\StringStorage;
use Symfony\Component\Templating\Helper\SlotsHelper;
use Symfony\Component\Templating\TemplateNameParser;
use Symfony\Component\Templating\TemplateReferenceInterface;
use Symfony\Component\Templating\TemplateReference;

class PhpEngineTest extends \PHPUnit_Framework_TestCase
{
    protected $loader;

    protected function setUp()
    {
        $this->loader = new ProjectTemplateLoader();
    }

    protected function tearDown()
    {
        $this->loader = null;
    }

    public function testConstructor()
    {
        $engine = new ProjectTemplateEngine(new TemplateNameParser(), $this->loader);
        $this->assertEquals($this->loader, $engine->getLoader(), '__construct() takes a loader instance as its second first argument');
    }

    public function testOffsetGet()
    {
        $engine = new ProjectTemplateEngine(new TemplateNameParser(), $this->loader);
        $engine->set($helper = new \Symfony\Component\Templating\Tests\Fixtures\SimpleHelper('bar'), 'foo');
        $this->assertEquals($helper, $engine['foo'], '->offsetGet() returns the value of a helper');

        try {
            $engine['bar'];
            $this->fail('->offsetGet() throws an InvalidArgumentException if the helper is not defined');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->offsetGet() throws an InvalidArgumentException if the helper is not defined');
            $this->assertEquals('The helper "bar" is not defined.', $e->getMessage(), '->offsetGet() throws an InvalidArgumentException if the helper is not defined');
        }
    }

    public function testGetSetHas()
    {
        $engine = new ProjectTemplateEngine(new TemplateNameParser(), $this->loader);
        $foo = new \Symfony\Component\Templating\Tests\Fixtures\SimpleHelper('foo');
        $engine->set($foo);
        $this->assertEquals($foo, $engine->get('foo'), '->set() sets a helper');

        $engine[$foo] = 'bar';
        $this->assertEquals($foo, $engine->get('bar'), '->set() takes an alias as a second argument');

        $this->assertTrue(isset($engine['bar']));

        try {
            $engine->get('foobar');
            $this->fail('->get() throws an InvalidArgumentException if the helper is not defined');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->get() throws an InvalidArgumentException if the helper is not defined');
            $this->assertEquals('The helper "foobar" is not defined.', $e->getMessage(), '->get() throws an InvalidArgumentException if the helper is not defined');
        }

        $this->assertTrue(isset($engine['bar']));
        $this->assertTrue($engine->has('foo'), '->has() returns true if the helper exists');
        $this->assertFalse($engine->has('foobar'), '->has() returns false if the helper does not exist');
    }

    public function testUnsetHelper()
    {
        $engine = new ProjectTemplateEngine(new TemplateNameParser(), $this->loader);
        $foo = new \Symfony\Component\Templating\Tests\Fixtures\SimpleHelper('foo');
        $engine->set($foo);

        $this->setExpectedException('\LogicException');

        unset($engine['foo']);
    }

    public function testExtendRender()
    {
        $engine = new ProjectTemplateEngine(new TemplateNameParser(), $this->loader, array(), array(new SlotsHelper()));
        try {
            $engine->render('name');
            $this->fail('->render() throws an InvalidArgumentException if the template does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->render() throws an InvalidArgumentException if the template does not exist');
            $this->assertEquals('The template "name" does not exist.', $e->getMessage(), '->render() throws an InvalidArgumentException if the template does not exist');
        }

        $engine = new ProjectTemplateEngine(new TemplateNameParser(), $this->loader, array(new SlotsHelper()));
        $engine->set(new \Symfony\Component\Templating\Tests\Fixtures\SimpleHelper('bar'));
        $this->loader->setTemplate('foo.php', '<?php $view->extend("layout.php"); echo $view[\'foo\'].$foo ?>');
        $this->loader->setTemplate('layout.php', '-<?php echo $view[\'slots\']->get("_content") ?>-');
        $this->assertEquals('-barfoo-', $engine->render('foo.php', array('foo' => 'foo')), '->render() uses the decorator to decorate the template');

        $engine = new ProjectTemplateEngine(new TemplateNameParser(), $this->loader, array(new SlotsHelper()));
        $engine->set(new \Symfony\Component\Templating\Tests\Fixtures\SimpleHelper('bar'));
        $this->loader->setTemplate('bar.php', 'bar');
        $this->loader->setTemplate('foo.php', '<?php $view->extend("layout.php"); echo $foo ?>');
        $this->loader->setTemplate('layout.php', '<?php echo $view->render("bar.php") ?>-<?php echo $view[\'slots\']->get("_content") ?>-');
        $this->assertEquals('bar-foo-', $engine->render('foo.php', array('foo' => 'foo', 'bar' => 'bar')), '->render() supports render() calls in templates');
    }

    public function testRenderParameter()
    {
        $engine = new ProjectTemplateEngine(new TemplateNameParser(), $this->loader);
        $this->loader->setTemplate('foo.php', '<?php echo $template . $parameters ?>');
        $this->assertEquals('foobar', $engine->render('foo.php', array('template' => 'foo', 'parameters' => 'bar')), '->render() extract variables');
    }

    /**
     * @expectedException \InvalidArgumentException
     * @dataProvider forbiddenParameterNames
     */
    public function testRenderForbiddenParameter($name)
    {
        $engine = new ProjectTemplateEngine(new TemplateNameParser(), $this->loader);
        $this->loader->setTemplate('foo.php', 'bar');
        $engine->render('foo.php', array($name => 'foo'));
    }

    public function forbiddenParameterNames()
    {
        return array(
            array('this'),
            array('view'),
        );
    }

    public function testEscape()
    {
        $engine = new ProjectTemplateEngine(new TemplateNameParser(), $this->loader);
        $this->assertEquals('&lt;br /&gt;', $engine->escape('<br />'), '->escape() escapes strings');
        $foo = new \stdClass();
        $this->assertEquals($foo, $engine->escape($foo), '->escape() does nothing on non strings');
    }

    public function testGetSetCharset()
    {
        $engine = new ProjectTemplateEngine(new TemplateNameParser(), $this->loader);
        $this->assertEquals('UTF-8', $engine->getCharset(), '->getCharset() returns UTF-8 by default');
        $engine->setCharset('ISO-8859-1');
        $this->assertEquals('ISO-8859-1', $engine->getCharset(), '->setCharset() changes the default charset to use');
    }

    public function testGlobalVariables()
    {
        $engine = new ProjectTemplateEngine(new TemplateNameParser(), $this->loader);
        $engine->addGlobal('global_variable', 'lorem ipsum');

        $this->assertEquals(array(
            'global_variable' => 'lorem ipsum',
        ), $engine->getGlobals());
    }

    public function testGlobalsGetPassedToTemplate()
    {
        $engine = new ProjectTemplateEngine(new TemplateNameParser(), $this->loader);
        $engine->addGlobal('global', 'global variable');

        $this->loader->setTemplate('global.php', '<?php echo $global; ?>');

        $this->assertEquals($engine->render('global.php'), 'global variable');

        $this->assertEquals($engine->render('global.php', array('global' => 'overwritten')), 'overwritten');
    }

    public function testGetLoader()
    {
        $engine = new ProjectTemplateEngine(new TemplateNameParser(), $this->loader);

        $this->assertSame($this->loader, $engine->getLoader());
    }
}

class ProjectTemplateEngine extends PhpEngine
{
    public function getLoader()
    {
        return $this->loader;
    }
}

class ProjectTemplateLoader extends Loader
{
    public $templates = array();

    public function setTemplate($name, $content)
    {
        $template = new TemplateReference($name, 'php');
        $this->templates[$template->getLogicalName()] = $content;
    }

    public function load(TemplateReferenceInterface $template)
    {
        if (isset($this->templates[$template->getLogicalName()])) {
            return new StringStorage($this->templates[$template->getLogicalName()]);
        }

        return false;
    }

    public function isFresh(TemplateReferenceInterface $template, $time)
    {
        return false;
    }
}
PK��Z�氵�Ktest/Templating/Symfony/Component/Templating/Tests/DelegatingEngineTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Templating\Tests;

use Symfony\Component\Templating\DelegatingEngine;
use Symfony\Component\Templating\StreamingEngineInterface;
use Symfony\Component\Templating\EngineInterface;

class DelegatingEngineTest extends \PHPUnit_Framework_TestCase
{
    public function testRenderDelegatesToSupportedEngine()
    {
        $firstEngine = $this->getEngineMock('template.php', false);
        $secondEngine = $this->getEngineMock('template.php', true);

        $secondEngine->expects($this->once())
            ->method('render')
            ->with('template.php', array('foo' => 'bar'))
            ->will($this->returnValue('<html />'));

        $delegatingEngine = new DelegatingEngine(array($firstEngine, $secondEngine));
        $result = $delegatingEngine->render('template.php', array('foo' => 'bar'));

        $this->assertSame('<html />', $result);
    }

    /**
     * @expectedException \RuntimeException
     * @expectedExceptionMessage No engine is able to work with the template "template.php"
     */
    public function testRenderWithNoSupportedEngine()
    {
        $firstEngine = $this->getEngineMock('template.php', false);
        $secondEngine = $this->getEngineMock('template.php', false);

        $delegatingEngine = new DelegatingEngine(array($firstEngine, $secondEngine));
        $delegatingEngine->render('template.php', array('foo' => 'bar'));
    }

    public function testStreamDelegatesToSupportedEngine()
    {
        $streamingEngine = $this->getStreamingEngineMock('template.php', true);
        $streamingEngine->expects($this->once())
            ->method('stream')
            ->with('template.php', array('foo' => 'bar'))
            ->will($this->returnValue('<html />'));

        $delegatingEngine = new DelegatingEngine(array($streamingEngine));
        $result = $delegatingEngine->stream('template.php', array('foo' => 'bar'));

        $this->assertNull($result);
    }

    /**
     * @expectedException \LogicException
     * @expectedExceptionMessage Template "template.php" cannot be streamed as the engine supporting it does not implement StreamingEngineInterface
     */
    public function testStreamRequiresStreamingEngine()
    {
        $engine = $this->getEngineMock('template.php', true);
        $engine->expects($this->never())->method('stream');

        $delegatingEngine = new DelegatingEngine(array($engine));
        $delegatingEngine->stream('template.php', array('foo' => 'bar'));
    }

    public function testExists()
    {
        $engine = $this->getEngineMock('template.php', true);
        $engine->expects($this->once())
            ->method('exists')
            ->with('template.php')
            ->will($this->returnValue(true));

        $delegatingEngine = new DelegatingEngine(array($engine));

        $this->assertTrue($delegatingEngine->exists('template.php'));
    }

    public function testSupports()
    {
        $engine = $this->getEngineMock('template.php', true);

        $delegatingEngine = new DelegatingEngine(array($engine));

        $this->assertTrue($delegatingEngine->supports('template.php'));
    }

    public function testSupportsWithNoSupportedEngine()
    {
        $engine = $this->getEngineMock('template.php', false);

        $delegatingEngine = new DelegatingEngine(array($engine));

        $this->assertFalse($delegatingEngine->supports('template.php'));
    }

    public function testGetExistingEngine()
    {
        $firstEngine = $this->getEngineMock('template.php', false);
        $secondEngine = $this->getEngineMock('template.php', true);

        $delegatingEngine = new DelegatingEngine(array($firstEngine, $secondEngine));

        $this->assertSame($secondEngine, $delegatingEngine->getEngine('template.php'));
    }

    /**
     * @expectedException \RuntimeException
     * @expectedExceptionMessage No engine is able to work with the template "template.php"
     */
    public function testGetInvalidEngine()
    {
        $firstEngine = $this->getEngineMock('template.php', false);
        $secondEngine = $this->getEngineMock('template.php', false);

        $delegatingEngine = new DelegatingEngine(array($firstEngine, $secondEngine));
        $delegatingEngine->getEngine('template.php', array('foo' => 'bar'));
    }

    private function getEngineMock($template, $supports)
    {
        $engine = $this->getMock('Symfony\Component\Templating\EngineInterface');

        $engine->expects($this->once())
            ->method('supports')
            ->with($template)
            ->will($this->returnValue($supports));

        return $engine;
    }

    private function getStreamingEngineMock($template, $supports)
    {
        $engine = $this->getMockForAbstractClass('Symfony\Component\Templating\Tests\MyStreamingEngine');

        $engine->expects($this->once())
            ->method('supports')
            ->with($template)
            ->will($this->returnValue($supports));

        return $engine;
    }
}

interface MyStreamingEngine extends StreamingEngineInterface, EngineInterface
{
}
PK��Z�%�D99=test/Templating/Symfony/Component/Templating/phpunit.xml.distnu�[���<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony Templating Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./vendor</directory>
                <directory>./Tests</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
PK��Z��Q��5test/Yaml/Symfony/Component/Yaml/Tests/DumperTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Yaml\Tests;

use Symfony\Component\Yaml\Yaml;
use Symfony\Component\Yaml\Parser;
use Symfony\Component\Yaml\Dumper;

class DumperTest extends \PHPUnit_Framework_TestCase
{
    protected $parser;
    protected $dumper;
    protected $path;

    protected $array = array(
        '' => 'bar',
        'foo' => '#bar',
        'foo\'bar' => array(),
        'bar' => array(1, 'foo'),
        'foobar' => array(
            'foo' => 'bar',
            'bar' => array(1, 'foo'),
            'foobar' => array(
                'foo' => 'bar',
                'bar' => array(1, 'foo'),
            ),
        ),
    );

    protected function setUp()
    {
        $this->parser = new Parser();
        $this->dumper = new Dumper();
        $this->path = __DIR__.'/Fixtures';
    }

    protected function tearDown()
    {
        $this->parser = null;
        $this->dumper = null;
        $this->path = null;
        $this->array = null;
    }

    public function testSetIndentation()
    {
        $this->dumper->setIndentation(7);

$expected = <<<EOF
'': bar
foo: '#bar'
'foo''bar': {  }
bar:
       - 1
       - foo
foobar:
       foo: bar
       bar:
              - 1
              - foo
       foobar:
              foo: bar
              bar:
                     - 1
                     - foo

EOF;
        $this->assertEquals($expected, $this->dumper->dump($this->array, 4, 0));
    }

    public function testSpecifications()
    {
        $files = $this->parser->parse(file_get_contents($this->path.'/index.yml'));
        foreach ($files as $file) {
            $yamls = file_get_contents($this->path.'/'.$file.'.yml');

            // split YAMLs documents
            foreach (preg_split('/^---( %YAML\:1\.0)?/m', $yamls) as $yaml) {
                if (!$yaml) {
                    continue;
                }

                $test = $this->parser->parse($yaml);
                if (isset($test['dump_skip']) && $test['dump_skip']) {
                    continue;
                } elseif (isset($test['todo']) && $test['todo']) {
                    // TODO
                } else {
                    eval('$expected = '.trim($test['php']).';');

                    $this->assertEquals($expected, $this->parser->parse($this->dumper->dump($expected, 10)), $test['test']);
                }
            }
        }
    }

    public function testInlineLevel()
    {
        $expected = <<<EOF
{ '': bar, foo: '#bar', 'foo''bar': {  }, bar: [1, foo], foobar: { foo: bar, bar: [1, foo], foobar: { foo: bar, bar: [1, foo] } } }
EOF;
$this->assertEquals($expected, $this->dumper->dump($this->array, -10), '->dump() takes an inline level argument');
$this->assertEquals($expected, $this->dumper->dump($this->array, 0), '->dump() takes an inline level argument');

$expected = <<<EOF
'': bar
foo: '#bar'
'foo''bar': {  }
bar: [1, foo]
foobar: { foo: bar, bar: [1, foo], foobar: { foo: bar, bar: [1, foo] } }

EOF;
        $this->assertEquals($expected, $this->dumper->dump($this->array, 1), '->dump() takes an inline level argument');

        $expected = <<<EOF
'': bar
foo: '#bar'
'foo''bar': {  }
bar:
    - 1
    - foo
foobar:
    foo: bar
    bar: [1, foo]
    foobar: { foo: bar, bar: [1, foo] }

EOF;
        $this->assertEquals($expected, $this->dumper->dump($this->array, 2), '->dump() takes an inline level argument');

        $expected = <<<EOF
'': bar
foo: '#bar'
'foo''bar': {  }
bar:
    - 1
    - foo
foobar:
    foo: bar
    bar:
        - 1
        - foo
    foobar:
        foo: bar
        bar: [1, foo]

EOF;
        $this->assertEquals($expected, $this->dumper->dump($this->array, 3), '->dump() takes an inline level argument');

        $expected = <<<EOF
'': bar
foo: '#bar'
'foo''bar': {  }
bar:
    - 1
    - foo
foobar:
    foo: bar
    bar:
        - 1
        - foo
    foobar:
        foo: bar
        bar:
            - 1
            - foo

EOF;
        $this->assertEquals($expected, $this->dumper->dump($this->array, 4), '->dump() takes an inline level argument');
        $this->assertEquals($expected, $this->dumper->dump($this->array, 10), '->dump() takes an inline level argument');
    }

    public function testObjectSupportEnabled()
    {
        $dump = $this->dumper->dump(array('foo' => new A(), 'bar' => 1), 0, 0, false, true);

        $this->assertEquals('{ foo: !!php/object:O:30:"Symfony\Component\Yaml\Tests\A":1:{s:1:"a";s:3:"foo";}, bar: 1 }', $dump, '->dump() is able to dump objects');
    }

    public function testObjectSupportDisabledButNoExceptions()
    {
        $dump = $this->dumper->dump(array('foo' => new A(), 'bar' => 1));

        $this->assertEquals('{ foo: null, bar: 1 }', $dump, '->dump() does not dump objects when disabled');
    }

    /**
     * @expectedException \Symfony\Component\Yaml\Exception\DumpException
     */
    public function testObjectSupportDisabledWithExceptions()
    {
        $this->dumper->dump(array('foo' => new A(), 'bar' => 1), 0, 0, true, false);
    }
}

class A
{
    public $a = 'foo';
}
PK��Z�����Ctest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsBlockMapping.ymlnu�[���---
test: One Element Mapping
brief: |
    A mapping with one key/value pair
yaml: |
    foo: bar
php: |
    array('foo' => 'bar')
---
test: Multi Element Mapping
brief: |
    More than one key/value pair
yaml: |
    red: baron
    white: walls
    blue: berries
php: |
    array(
     'red' => 'baron',
     'white' => 'walls',
     'blue' => 'berries',
    )
---
test: Values aligned
brief: |
    Often times human editors of documents will align the values even
    though YAML emitters generally don't.
yaml: |
    red:   baron
    white: walls
    blue:  berries
php: |
    array(
     'red' => 'baron',
     'white' => 'walls',
     'blue' => 'berries',
    )
---
test: Colons aligned
brief: |
    Spaces can come before the ': ' key/value separator.
yaml: |
    red   : baron
    white : walls
    blue  : berries
php: |
    array(
     'red' => 'baron',
     'white' => 'walls',
     'blue' => 'berries',
    )
PK��Z��UU=test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfCompact.ymlnu�[���--- %YAML:1.0
test: Compact notation
brief: |
    Compact notation for sets of mappings with single element
yaml: |
  ---
  # products purchased
  - item    : Super Hoop
  - item    : Basketball
    quantity: 1
  - item:
      name: Big Shoes
      nick: Biggies
    quantity: 1
php: |
  array (
    array (
      'item' => 'Super Hoop',
    ),
    array (
      'item' => 'Basketball',
      'quantity' => 1,
    ),
    array (
      'item' => array(
        'name' => 'Big Shoes',
        'nick' => 'Biggies'
      ),
      'quantity' => 1
    )
  )
---
test: Compact notation combined with inline notation
brief: |
    Combinations of compact and inline notation are allowed
yaml: |
  ---
  items:
    - { item: Super Hoop, quantity: 1 }
    - [ Basketball, Big Shoes ]
php: |
  array (
    'items' => array (
      array (
        'item' => 'Super Hoop',
        'quantity' => 1,
      ),
      array (
        'Basketball',
        'Big Shoes'
      )
    )
  )
--- %YAML:1.0
test: Compact notation
brief: |
    Compact notation for sets of mappings with single element
yaml: |
  ---
  # products purchased
  - item    : Super Hoop
  - item    : Basketball
    quantity: 1
  - item:
      name: Big Shoes
      nick: Biggies
    quantity: 1
php: |
  array (
    array (
      'item' => 'Super Hoop',
    ),
    array (
      'item' => 'Basketball',
      'quantity' => 1,
    ),
    array (
      'item' => array(
        'name' => 'Big Shoes',
        'nick' => 'Biggies'
      ),
      'quantity' => 1
    )
  )
---
test: Compact notation combined with inline notation
brief: |
    Combinations of compact and inline notation are allowed
yaml: |
  ---
  items:
    - { item: Super Hoop, quantity: 1 }
    - [ Basketball, Big Shoes ]
php: |
  array (
    'items' => array (
      array (
        'item' => 'Super Hoop',
        'quantity' => 1,
      ),
      array (
        'Basketball',
        'Big Shoes'
      )
    )
  )
--- %YAML:1.0
test: Compact notation
brief: |
    Compact notation for sets of mappings with single element
yaml: |
  ---
  # products purchased
  - item    : Super Hoop
  - item    : Basketball
    quantity: 1
  - item:
      name: Big Shoes
      nick: Biggies
    quantity: 1
php: |
  array (
    array (
      'item' => 'Super Hoop',
    ),
    array (
      'item' => 'Basketball',
      'quantity' => 1,
    ),
    array (
      'item' => array(
        'name' => 'Big Shoes',
        'nick' => 'Biggies'
      ),
      'quantity' => 1
    )
  )
---
test: Compact notation combined with inline notation
brief: |
    Combinations of compact and inline notation are allowed
yaml: |
  ---
  items:
    - { item: Super Hoop, quantity: 1 }
    - [ Basketball, Big Shoes ]
php: |
  array (
    'items' => array (
      array (
        'item' => 'Super Hoop',
        'quantity' => 1,
      ),
      array (
        'Basketball',
        'Big Shoes'
      )
    )
  )
PK��Z�5�R[[Btest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsAnchorAlias.ymlnu�[���--- %YAML:1.0
test: Simple Alias Example
brief: >
    If you need to refer to the same item of data twice,
    you can give that item an alias.  The alias is a plain
    string, starting with an ampersand.  The item may then
    be referred to by the alias throughout your document
    by using an asterisk before the name of the alias.
    This is called an anchor.
yaml: |
    - &showell Steve
    - Clark
    - Brian
    - Oren
    - *showell
php: |
    array('Steve', 'Clark', 'Brian', 'Oren', 'Steve')

---
test: Alias of a Mapping
brief: >
    An alias can be used on any item of data, including
    sequences, mappings, and other complex data types.
yaml: |
    - &hello
        Meat: pork
        Starch: potato
    - banana
    - *hello
php: |
    array(array('Meat'=>'pork', 'Starch'=>'potato'), 'banana', array('Meat'=>'pork', 'Starch'=>'potato'))
PK��ZU���;test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfTests.ymlnu�[���--- %YAML:1.0
test: Multiple quoted string on one line
brief: >
    Multiple quoted string on one line
yaml: |
    stripped_title: { name: "foo bar", help: "bar foo" }
php: |
    array('stripped_title' => array('name' => 'foo bar', 'help' => 'bar foo'))
---
test: Empty sequence
yaml: |
    foo: [ ]
php: |
    array('foo' => array())
---
test: Empty value
yaml: |
    foo:
php: |
    array('foo' => null)
---
test: Inline string parsing
brief: >
    Inline string parsing
yaml: |
    test: ['complex: string', 'another [string]']
php: |
    array('test' => array('complex: string', 'another [string]'))
---
test: Boolean
brief: >
    Boolean
yaml: |
    - false
    - true
    - null
    - ~
    - 'false'
    - 'true'
    - 'null'
    - '~'
php: |
    array(
      false,
      true,
      null,
      null,
      'false',
      'true',
      'null',
      '~',
    )
---
test: Empty lines in folded blocks
brief: >
  Empty lines in folded blocks
yaml: |
  foo:
    bar: |
      foo


        
      bar
php: |
  array('foo' => array('bar' => "foo\n\n\n  \nbar\n"))
---
test: IP addresses
brief: >
  IP addresses
yaml: |
  foo: 10.0.0.2
php: |
  array('foo' => '10.0.0.2')
---
test: A sequence with an embedded mapping
brief: >
  A sequence with an embedded mapping
yaml: |
  - foo
  - bar: { bar: foo }
php: |
  array('foo', array('bar' => array('bar' => 'foo')))
---
test: A sequence with an unordered array
brief: >
  A sequence with an unordered array
yaml: |
  1: foo
  0: bar
php: |
  array(1 => 'foo', 0 => 'bar')
---
test: Octal
brief: as in spec example 2.19, octal value is converted
yaml: |
  foo: 0123
php: |
  array('foo' => 83)
---
test: Octal strings
brief: Octal notation in a string must remain a string
yaml: |
  foo: "0123"
php: |
  array('foo' => '0123')
---
test: Octal strings
brief: Octal notation in a string must remain a string
yaml: |
  foo: '0123'
php: |
  array('foo' => '0123')
---
test: Octal strings
brief: Octal notation in a string must remain a string
yaml: |
  foo: |
    0123
php: |
  array('foo' => "0123\n")
---
test: Document as a simple hash
brief: Document as a simple hash
yaml: |
  { foo: bar }
php: |
  array('foo' => 'bar')
---
test: Document as a simple array
brief: Document as a simple array
yaml: |
  [ foo, bar ]
php: |
  array('foo', 'bar')
PK��Z�@�UU>test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfComments.ymlnu�[���--- %YAML:1.0
test: Comments at the end of a line
brief: >
    Comments at the end of a line
yaml: |
    ex1: "foo # bar"
    ex2: "foo # bar" # comment
    ex3: 'foo # bar' # comment
    ex4: foo # comment
php: |
    array('ex1' => 'foo # bar', 'ex2' => 'foo # bar', 'ex3' => 'foo # bar', 'ex4' => 'foo')
---
test: Comments in the middle
brief: >
  Comments in the middle
yaml: |
    foo:
    # some comment
    # some comment
      bar: foo
    # some comment
    # some comment
php: |
    array('foo' => array('bar' => 'foo'))
---
test: Comments on a hash line
brief: >
  Comments on a hash line
yaml: |
    foo:   # a comment
      foo: bar # a comment
php: |
    array('foo' => array('foo' => 'bar'))
---
test: 'Value starting with a #'
brief: >
  'Value starting with a #'
yaml: |
    foo:   '#bar'
php: |
    array('foo' => '#bar')
---
test: Document starting with a comment and a separator
brief: >
  Commenting before document start is allowed
yaml: |
    # document comment
    ---
    foo: bar # a comment
php: |
    array('foo' => 'bar')
---
test: Comment containing a colon on a hash line
brief: >
    Comment containing a colon on a scalar line
yaml: 'foo # comment: this is also part of the comment'
php: |
    'foo'
---
test: 'Hash key containing a #'
brief: >
    'Hash key containing a #'
yaml: 'foo#bar: baz'
php: |
    array('foo#bar' => 'baz')
PK��Z��--Itest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/unindentedCollections.ymlnu�[���--- %YAML:1.0
test: Unindented collection
brief: >
    Unindented collection
yaml: |
    collection:
    - item1
    - item2
    - item3
php: |
    array('collection' => array('item1', 'item2', 'item3'))
---
test: Nested unindented collection (two levels)
brief: >
    Nested unindented collection
yaml: |
    collection:
        key:
        - a
        - b
        - c
php: |
    array('collection' => array('key' => array('a', 'b', 'c')))
---
test: Nested unindented collection (three levels)
brief: >
    Nested unindented collection
yaml: |
    collection:
        key:
            subkey:
            - one
            - two
            - three
php: |
    array('collection' => array('key' => array('subkey' => array('one', 'two', 'three'))))
---
test: Key/value after unindented collection (1)
brief: >
    Key/value after unindented collection (1)
yaml: |
    collection:
        key:
        - a
        - b
        - c
    foo: bar
php: |
    array('collection' => array('key' => array('a', 'b', 'c')), 'foo' => 'bar')
---
test: Key/value after unindented collection (at the same level)
brief: >
    Key/value after unindented collection
yaml: |
    collection:
        key:
        - a
        - b
        - c
        foo: bar
php: |
    array('collection' => array('key' => array('a', 'b', 'c'), 'foo' => 'bar'))
PK��Z�>;���Ftest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsNullsAndEmpties.ymlnu�[���--- %YAML:1.0
test: Empty Sequence
brief: >
    You can represent the empty sequence
    with an empty inline sequence.
yaml: |
    empty: []
php: |
    array('empty' => array())
---
test: Empty Mapping
brief: >
    You can represent the empty mapping
    with an empty inline mapping.
yaml: |
    empty: {}
php: |
    array('empty' => array())
---
test: Empty Sequence as Entire Document
yaml: |
    []
php: |
    array()
---
test: Empty Mapping as Entire Document
yaml: |
    {}
php: |
    array()
---
test: Null as Document
yaml: |
    ~
php: |
    null
---
test: Empty String
brief: >
    You can represent an empty string
    with a pair of quotes.
yaml: |
    ''
php: |
    ''
PK��Zt��rqqAtest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsErrorTests.ymlnu�[���---
test: Missing value for hash item
todo: true
brief: |
    Third item in this hash doesn't have a value
yaml: |
    okay: value
    also okay: ~
    causes error because no value specified
    last key: value okay here too
python-error: causes error because no value specified

---
test: Not indenting enough
brief: |
    There was a bug in PyYaml where it was off by one
    in the indentation check.  It was allowing the YAML
    below.
# This is actually valid YAML now. Someone should tell showell.
yaml: |
    foo:
    firstline: 1
    secondline: 2
php: |
  array('foo' => null, 'firstline' => 1, 'secondline' => 2)
PK��ZZ{k�XXFtest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsFlowCollections.ymlnu�[���---
test: Simple Inline Array
brief: >
    Sequences can be contained on a
    single line, using the inline syntax.
    Separate each entry with commas and
    enclose in square brackets.
yaml: |
    seq: [ a, b, c ]
php: |
    array('seq' => array('a', 'b', 'c'))
---
test: Simple Inline Hash
brief: >
    Mapping can also be contained on
    a single line, using the inline
    syntax.  Each key-value pair is
    separated by a colon, with a comma
    between each entry in the mapping.
    Enclose with curly braces.
yaml: |
    hash: { name: Steve, foo: bar }
php: |
    array('hash' => array('name' => 'Steve', 'foo' => 'bar'))
---
test: Multi-line Inline Collections
todo: true
brief: >
    Both inline sequences and inline mappings
    can span multiple lines, provided that you
    indent the additional lines.
yaml: |
    languages: [ Ruby,
                 Perl,
                 Python ]
    websites: { YAML: yaml.org,
                Ruby: ruby-lang.org,
                Python: python.org,
                Perl: use.perl.org }
php: |
    array(
      'languages' => array('Ruby', 'Perl', 'Python'),
      'websites' => array(
        'YAML' => 'yaml.org',
        'Ruby' => 'ruby-lang.org',
        'Python' => 'python.org',
        'Perl' => 'use.perl.org'
      )
    )
---
test: Commas in Values (not in the spec!)
todo: true
brief: >
    List items in collections are delimited by commas, but
    there must be a space after each comma.  This allows you
    to add numbers without quoting.
yaml: |
    attendances: [ 45,123, 70,000, 17,222 ]
php: |
    array('attendances' => array(45123, 70000, 17222))
PK��Z�*���Etest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/escapedCharacters.ymlnu�[���test: outside double quotes
yaml: |
    \0 \ \a \b \n
php: |
    "\\0 \\ \\a \\b \\n"
---
test: null
yaml: |
    "\0"
php: |
    "\x00"
---
test: bell
yaml: |
    "\a"
php: |
    "\x07"
---
test: backspace
yaml: |
    "\b"
php: |
    "\x08"
---
test: horizontal tab (1)
yaml: |
    "\t"
php: |
    "\x09"
---
test: horizontal tab (2)
yaml: |
    "\	"
php: |
    "\x09"
---
test: line feed
yaml: |
    "\n"
php: |
    "\x0a"
---
test: vertical tab
yaml: |
    "\v"
php: |
    "\x0b"
---
test: form feed
yaml: |
    "\f"
php: |
    "\x0c"
---
test: carriage return
yaml: |
    "\r"
php: |
    "\x0d"
---
test: escape
yaml: |
    "\e"
php: |
   "\x1b"
---
test: space
yaml: |
    "\ "
php: |
    "\x20"
---
test: slash
yaml: |
    "\/"
php: |
    "\x2f"
---
test: backslash
yaml: |
    "\\"
php: |
    "\\"
---
test: Unicode next line
yaml: |
    "\N"
php: |
    "\xc2\x85"
---
test: Unicode non-breaking space
yaml: |
    "\_"
php: |
    "\xc2\xa0"
---
test: Unicode line separator
yaml: |
    "\L"
php: |
    "\xe2\x80\xa8"
---
test: Unicode paragraph separator
yaml: |
    "\P"
php: |
    "\xe2\x80\xa9"
---
test: Escaped 8-bit Unicode
yaml: |
    "\x42"
php: |
    "B"
---
test: Escaped 16-bit Unicode
yaml: |
    "\u20ac"
php: |
    "\xe2\x82\xac"
---
test: Escaped 32-bit Unicode
yaml: |
    "\U00000043"
php: |
    "C"
---
test: Example 5.13 Escaped Characters
note: |
    Currently throws an error parsing first line. Maybe Symfony Yaml doesn't support
    continuation of string across multiple lines? Keeping test here but disabled.
todo: true
yaml: |
    "Fun with \\
    \" \a \b \e \f \
    \n \r \t \v \0 \
    \  \_ \N \L \P \
    \x41 \u0041 \U00000041"
php: |
    "Fun with \x5C\n\x22 \x07 \x08 \x1B \x0C\n\x0A \x0D \x09 \x0B \x00\n\x20 \xA0 \x85 \xe2\x80\xa8 \xe2\x80\xa9\nA A A"
---
test: Double quotes with a line feed
yaml: |
   { double: "some value\n \"some quoted string\" and 'some single quotes one'" }
php: |
    array(
        'double' => "some value\n \"some quoted string\" and 'some single quotes one'"
    )
PK��Z֋�O��Atest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsBasicTests.ymlnu�[���--- %YAML:1.0
test: Simple Sequence
brief: |
    You can specify a list in YAML by placing each
    member of the list on a new line with an opening
    dash. These lists are called sequences.
yaml: |
    - apple
    - banana
    - carrot
php: |
    array('apple', 'banana', 'carrot')
---
test: Nested Sequences
brief: |
    You can include a sequence within another
    sequence by giving the sequence an empty
    dash, followed by an indented list.
yaml: |
    -
     - foo
     - bar
     - baz
php: |
    array(array('foo', 'bar', 'baz'))
---
test: Mixed Sequences
brief: |
    Sequences can contain any YAML data,
    including strings and other sequences.
yaml: |
    - apple
    -
     - foo
     - bar
     - x123
    - banana
    - carrot
php: |
    array('apple', array('foo', 'bar', 'x123'), 'banana', 'carrot')
---
test: Deeply Nested Sequences
brief: |
    Sequences can be nested even deeper, with each
    level of indentation representing a level of
    depth.
yaml: |
    -
     -
      - uno
      - dos
php: |
    array(array(array('uno', 'dos')))
---
test: Simple Mapping
brief: |
    You can add a keyed list (also known as a dictionary or
    hash) to your document by placing each member of the
    list on a new line, with a colon separating the key
    from its value.  In YAML, this type of list is called
    a mapping.
yaml: |
    foo: whatever
    bar: stuff
php: |
    array('foo' => 'whatever', 'bar' => 'stuff')
---
test: Sequence in a Mapping
brief: |
    A value in a mapping can be a sequence.
yaml: |
    foo: whatever
    bar:
     - uno
     - dos
php: |
    array('foo' => 'whatever', 'bar' => array('uno', 'dos'))
---
test: Nested Mappings
brief: |
    A value in a mapping can be another mapping.
yaml: |
    foo: whatever
    bar:
     fruit: apple
     name: steve
     sport: baseball
php: |
    array(
      'foo' => 'whatever',
      'bar' => array(
         'fruit' => 'apple',
         'name' => 'steve',
         'sport' => 'baseball'
       )
    )
---
test: Mixed Mapping
brief: |
    A mapping can contain any assortment
    of mappings and sequences as values.
yaml: |
    foo: whatever
    bar:
     -
       fruit: apple
       name: steve
       sport: baseball
     - more
     -
       python: rocks
       perl: papers
       ruby: scissorses
php: |
    array(
      'foo' => 'whatever',
      'bar' => array(
        array(
            'fruit' => 'apple',
            'name' => 'steve',
            'sport' => 'baseball'
        ),
        'more',
        array(
            'python' => 'rocks',
            'perl' => 'papers',
            'ruby' => 'scissorses'
        )
      )
    )
---
test: Mapping-in-Sequence Shortcut
todo: true
brief: |
     If you are adding a mapping to a sequence, you
     can place the mapping on the same line as the
     dash as a shortcut.
yaml: |
     - work on YAML.py:
        - work on Store
php: |
    array(array('work on YAML.py' => array('work on Store')))
---
test: Sequence-in-Mapping Shortcut
todo: true
brief: |
     The dash in a sequence counts as indentation, so
     you can add a sequence inside of a mapping without
     needing spaces as indentation.
yaml: |
     allow:
     - 'localhost'
     - '%.sourceforge.net'
     - '%.freepan.org'
php: |
     array('allow' => array('localhost', '%.sourceforge.net', '%.freepan.org'))
---
todo: true
test: Merge key
brief: |
     A merge key ('<<') can be used in a mapping to insert other mappings.  If
     the value associated with the merge key is a mapping, each of its key/value
     pairs is inserted into the current mapping.
yaml: |
     mapping:
       name: Joe
       job: Accountant
       <<:
         age: 38
php: |
     array(
       'mapping' =>
       array(
         'name' => 'Joe',
         'job' => 'Accountant',
         'age' => 38
       )
     )
PK��ZګغzzDtest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsFoldedScalars.ymlnu�[���--- %YAML:1.0
test: Single ending newline
brief: >
    A pipe character, followed by an indented
    block of text is treated as a literal
    block, in which newlines are preserved
    throughout the block, including the final
    newline.
yaml: |
    ---
    this: |
        Foo
        Bar
php: |
    array('this' => "Foo\nBar\n")
---
test: The '+' indicator
brief: >
    The '+' indicator says to keep newlines at the end of text
    blocks.
yaml: |
    normal: |
      extra new lines not kept

    preserving: |+
      extra new lines are kept


    dummy: value
php: |
    array(
        'normal' => "extra new lines not kept\n",
        'preserving' => "extra new lines are kept\n\n\n",
        'dummy' => 'value'
    )
---
test: Three trailing newlines in literals
brief: >
    To give you more control over how space
    is preserved in text blocks, YAML has
    the keep '+' and chomp '-' indicators.
    The keep indicator will preserve all
    ending newlines, while the chomp indicator
    will strip all ending newlines.
yaml: |
    clipped: |
        This has one newline.



    same as "clipped" above: "This has one newline.\n"

    stripped: |-
        This has no newline.



    same as "stripped" above: "This has no newline."

    kept: |+
        This has four newlines.



    same as "kept" above: "This has four newlines.\n\n\n\n"
php: |
    array(
      'clipped' => "This has one newline.\n",
      'same as "clipped" above' => "This has one newline.\n",
      'stripped' => 'This has no newline.',
      'same as "stripped" above' => 'This has no newline.',
      'kept' => "This has four newlines.\n\n\n\n",
      'same as "kept" above' => "This has four newlines.\n\n\n\n"
    )
---
test: Extra trailing newlines with spaces
todo: true
brief: >
    Normally, only a single newline is kept
    from the end of a literal block, unless the
    keep '+' character is used in combination
    with the pipe.  The following example
    will preserve all ending whitespace
    since the last line of both literal blocks
    contains spaces which extend past the indentation
    level.
yaml: |
    ---
    this: |
        Foo


    kept: |+
        Foo


php: |
    array('this' => "Foo\n\n  \n",
      'kept' => "Foo\n\n  \n" )

---
test: Folded Block in a Sequence
brief: >
    A greater-then character, followed by an indented
    block of text is treated as a folded block, in
    which lines of text separated by a single newline
    are concatenated as a single line.
yaml: |
    ---
    - apple
    - banana
    - >
        can't you see
        the beauty of yaml?
        hmm
    - dog
php: |
    array(
        'apple',
        'banana',
        "can't you see the beauty of yaml? hmm\n",
        'dog'
    )
---
test: Folded Block as a Mapping Value
brief: >
    Both literal and folded blocks can be
    used in collections, as values in a
    sequence or a mapping.
yaml: |
    ---
    quote: >
        Mark McGwire's
        year was crippled
        by a knee injury.
    source: espn
php: |
    array(
        'quote' => "Mark McGwire's year was crippled by a knee injury.\n",
        'source' => 'espn'
    )
---
test: Three trailing newlines in folded blocks
brief: >
    The keep and chomp indicators can also
    be applied to folded blocks.
yaml: |
    clipped: >
        This has one newline.



    same as "clipped" above: "This has one newline.\n"

    stripped: >-
        This has no newline.



    same as "stripped" above: "This has no newline."

    kept: >+
        This has four newlines.



    same as "kept" above: "This has four newlines.\n\n\n\n"
php: |
    array(
      'clipped' => "This has one newline.\n",
      'same as "clipped" above' => "This has one newline.\n",
      'stripped' => 'This has no newline.',
      'same as "stripped" above' => 'This has no newline.',
      'kept' => "This has four newlines.\n\n\n\n",
      'same as "kept" above' => "This has four newlines.\n\n\n\n"
    )
PK��Z���889test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/index.ymlnu�[���- escapedCharacters
- sfComments
- sfCompact
- sfTests
- sfObjects
- sfMergeKey
- sfQuotes
- YtsAnchorAlias
- YtsBasicTests
- YtsBlockMapping
- YtsDocumentSeparator
- YtsErrorTests
- YtsFlowCollections
- YtsFoldedScalars
- YtsNullsAndEmpties
- YtsSpecificationExamples
- YtsTypeTransfers
- unindentedCollections
PK��Z%MC��Htest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsDocumentSeparator.ymlnu�[���--- %YAML:1.0
test: Trailing Document Separator
todo: true
brief: >
    You can separate YAML documents
    with a string of three dashes.
yaml: |
    - foo: 1
      bar: 2
    ---
    more: stuff
python: |
    [
        [ { 'foo': 1, 'bar': 2 } ],
        { 'more': 'stuff' }
    ]
ruby: |
    [ { 'foo' => 1, 'bar' => 2 } ]

---
test: Leading Document Separator
todo: true
brief: >
    You can explicity give an opening
    document separator to your YAML stream.
yaml: |
    ---
    - foo: 1
      bar: 2
    ---
    more: stuff
python: |
    [
        [ {'foo': 1, 'bar': 2}],
        {'more': 'stuff'}
    ]
ruby: |
    [ { 'foo' => 1, 'bar' => 2 } ]

---
test: YAML Header
todo: true
brief: >
    The opening separator can contain directives
    to the YAML parser, such as the version
    number.
yaml: |
    --- %YAML:1.0
    foo: 1
    bar: 2
php: |
    array('foo' => 1, 'bar' => 2)
documents: 1

---
test: Red Herring Document Separator
brief: >
    Separators included in blocks or strings
    are treated as blocks or strings, as the
    document separator should have no indentation
    preceding it.
yaml: |
    foo: |
        ---
php: |
    array('foo' => "---\n")

---
test: Multiple Document Separators in Block
brief: >
    This technique allows you to embed other YAML
    documents within literal blocks.
yaml: |
    foo: |
        ---
        foo: bar
        ---
        yo: baz
    bar: |
        fooness
php: |
    array(
       'foo' => "---\nfoo: bar\n---\nyo: baz\n",
       'bar' => "fooness\n"
    )
PK��Z;:�QJJ>test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfMergeKey.ymlnu�[���--- %YAML:1.0
test: Simple In Place Substitution
brief: >
    If you want to reuse an entire alias, only overwriting what is different
    you can use a << in place substitution. This is not part of the official
    YAML spec, but a widely implemented extension. See the following URL for
    details: http://yaml.org/type/merge.html
yaml: |
    foo: &foo
        a: Steve
        b: Clark
        c: Brian
    bar: &bar
        <<: *foo
        x: Oren
    foo2: &foo2
        a: Ballmer
    ding: &dong [ fi, fei, fo, fam]
    check:
        <<:
            - *foo
            - *dong
        isit: tested
    head:
        <<: [ *foo , *dong , *foo2 ]
php: |
    array('foo' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian'), 'bar' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'x' => 'Oren'), 'foo2' => array('a' => 'Ballmer'), 'ding' => array('fi', 'fei', 'fo', 'fam'), 'check' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'fi', 'fei', 'fo', 'fam', 'isit' => 'tested'), 'head' => array('a' => 'Ballmer', 'b' => 'Clark', 'c' => 'Brian', 'fi', 'fei', 'fo', 'fam'))
PK��ZZ��>test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/embededPhp.ymlnu�[���value: <?php echo 1 + 2 + 3 ?>
PK��Z�<�=test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfObjects.ymlnu�[���--- %YAML:1.0
test: Objects
brief: >
    Comments at the end of a line
yaml: |
    ex1: "foo # bar"
    ex2: "foo # bar" # comment
    ex3: 'foo # bar' # comment
    ex4: foo # comment
php: |
    array('ex1' => 'foo # bar', 'ex2' => 'foo # bar', 'ex3' => 'foo # bar', 'ex4' => 'foo')
PK��Z�$R��Dtest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsTypeTransfers.ymlnu�[���--- %YAML:1.0
test: Strings
brief: >
    Any group of characters beginning with an
    alphabetic or numeric character is a string,
    unless it belongs to one of the groups below
    (such as an Integer or Time).
yaml: |
    String
php: |
    'String'
---
test: String characters
brief: >
    A string can contain any alphabetic or
    numeric character, along with many
    punctuation characters, including the
    period, dash, space, quotes, exclamation, and
    question mark.
yaml: |
    - What's Yaml?
    - It's for writing data structures in plain text.
    - And?
    - And what? That's not good enough for you?
    - No, I mean, "And what about Yaml?"
    - Oh, oh yeah. Uh.. Yaml for Ruby.
php: |
    array(
      "What's Yaml?",
      "It's for writing data structures in plain text.",
      "And?",
      "And what? That's not good enough for you?",
      "No, I mean, \"And what about Yaml?\"",
      "Oh, oh yeah. Uh.. Yaml for Ruby."
    )
---
test: Indicators in Strings
brief: >
    Be careful using indicators in strings.  In particular,
    the comma, colon, and pound sign must be used carefully.
yaml: |
    the colon followed by space is an indicator: but is a string:right here
    same for the pound sign: here we have it#in a string
    the comma can, honestly, be used in most cases: [ but not in, inline collections ]
php: |
    array(
      'the colon followed by space is an indicator' => 'but is a string:right here',
      'same for the pound sign' => 'here we have it#in a string',
      'the comma can, honestly, be used in most cases' => array('but not in', 'inline collections')
    )
---
test: Forcing Strings
brief: >
    Any YAML type can be forced into a string using the
    explicit !str method.
yaml: |
    date string: !str 2001-08-01
    number string: !str 192
php: |
    array(
      'date string' => '2001-08-01',
      'number string' => '192'
    )
---
test: Single-quoted Strings
brief: >
    You can also enclose your strings within single quotes,
    which allows use of slashes, colons, and other indicators
    freely.  Inside single quotes, you can represent a single
    quote in your string by using two single quotes next to
    each other.
yaml: |
    all my favorite symbols: '#:!/%.)'
    a few i hate: '&(*'
    why do i hate them?: 'it''s very hard to explain'
    entities: '&pound; me'
php: |
    array(
      'all my favorite symbols' => '#:!/%.)',
      'a few i hate' => '&(*',
      'why do i hate them?' => 'it\'s very hard to explain',
      'entities' => '&pound; me'
    )
---
test: Double-quoted Strings
brief: >
    Enclosing strings in double quotes allows you
    to use escapings to represent ASCII and
    Unicode characters.
yaml: |
    i know where i want my line breaks: "one here\nand another here\n"
php: |
    array(
      'i know where i want my line breaks' => "one here\nand another here\n"
    )
---
test: Multi-line Quoted Strings
todo: true
brief: >
    Both single- and double-quoted strings may be
    carried on to new lines in your YAML document.
    They must be indented a step and indentation
    is interpreted as a single space.
yaml: |
    i want a long string: "so i'm going to
      let it go on and on to other lines
      until i end it with a quote."
php: |
    array('i want a long string' => "so i'm going to ".
         "let it go on and on to other lines ".
         "until i end it with a quote."
    )

---
test: Plain scalars
todo: true
brief: >
    Unquoted strings may also span multiple lines, if they
    are free of YAML space indicators and indented.
yaml: |
    - My little toe is broken in two places;
    - I'm crazy to have skied this way;
    - I'm not the craziest he's seen, since there was always the German guy
      who skied for 3 hours on a broken shin bone (just below the kneecap);
    - Nevertheless, second place is respectable, and he doesn't
      recommend going for the record;
    - He's going to put my foot in plaster for a month;
    - This would impair my skiing ability somewhat for the
      duration, as can be imagined.
php: |
    array(
      "My little toe is broken in two places;",
      "I'm crazy to have skied this way;",
      "I'm not the craziest he's seen, since there was always ".
         "the German guy who skied for 3 hours on a broken shin ".
         "bone (just below the kneecap);",
      "Nevertheless, second place is respectable, and he doesn't ".
         "recommend going for the record;",
      "He's going to put my foot in plaster for a month;",
      "This would impair my skiing ability somewhat for the duration, ".
         "as can be imagined."
    )
---
test: 'Null'
brief: >
    You can use the tilde '~' character for a null value.
yaml: |
    name: Mr. Show
    hosted by: Bob and David
    date of next season: ~
php: |
    array(
      'name' => 'Mr. Show',
      'hosted by' => 'Bob and David',
      'date of next season' => null
    )
---
test: Boolean
brief: >
    You can use 'true' and 'false' for Boolean values.
yaml: |
    Is Gus a Liar?: true
    Do I rely on Gus for Sustenance?: false
php: |
    array(
      'Is Gus a Liar?' => true,
      'Do I rely on Gus for Sustenance?' => false
    )
---
test: Integers
dump_skip: true
brief: >
    An integer is a series of numbers, optionally
    starting with a positive or negative sign.  Integers
    may also contain commas for readability.
yaml: |
    zero: 0
    simple: 12
    one-thousand: 1,000
    negative one-thousand: -1,000
php: |
    array(
      'zero' => 0,
      'simple' => 12,
      'one-thousand' => 1000,
      'negative one-thousand' => -1000
    )
---
test: Integers as Map Keys
brief: >
    An integer can be used a dictionary key.
yaml: |
    1: one
    2: two
    3: three
php: |
    array(
        1 => 'one',
        2 => 'two',
        3 => 'three'
    )
---
test: Floats
dump_skip: true
brief: >
     Floats are represented by numbers with decimals,
     allowing for scientific notation, as well as
     positive and negative infinity and "not a number."
yaml: |
     a simple float: 2.00
     larger float: 1,000.09
     scientific notation: 1.00009e+3
php: |
     array(
       'a simple float' => 2.0,
       'larger float' => 1000.09,
       'scientific notation' => 1000.09
     )
---
test: Time
todo: true
brief: >
    You can represent timestamps by using
    ISO8601 format, or a variation which
    allows spaces between the date, time and
    time zone.
yaml: |
    iso8601: 2001-12-14t21:59:43.10-05:00
    space separated: 2001-12-14 21:59:43.10 -05:00
php: |
    array(
      'iso8601' => mktime( 2001, 12, 14, 21, 59, 43, 0.10, "-05:00" ),
      'space separated' => mktime( 2001, 12, 14, 21, 59, 43, 0.10, "-05:00" )
    )
---
test: Date
todo: true
brief: >
    A date can be represented by its year,
    month and day in ISO8601 order.
yaml: |
    1976-07-31
php: |
    date( 1976, 7, 31 )
PK��Z����<test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfQuotes.ymlnu�[���--- %YAML:1.0
test: Some characters at the beginning of a string must be escaped
brief: >
    Some characters at the beginning of a string must be escaped
yaml: |
    foo: | bar
php: |
    array('foo' => '| bar')
---
test: A key can be a quoted string
brief: >
  A key can be a quoted string
yaml: |
    "foo1": bar
    'foo2': bar
    "foo \" bar": bar
    'foo '' bar': bar
    'foo3: ': bar
    "foo4: ": bar
    foo5: { "foo \" bar: ": bar, 'foo '' bar: ': bar }
php: |
    array(
      'foo1' => 'bar',
      'foo2' => 'bar',
      'foo " bar' => 'bar',
      'foo \' bar' => 'bar',
      'foo3: ' => 'bar',
      'foo4: ' => 'bar',
      'foo5' => array(
        'foo " bar: ' => 'bar',
        'foo \' bar: ' => 'bar',
      ),
    )
PK��ZܷU�1�1�Ltest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.ymlnu�[���--- %YAML:1.0
test: Sequence of scalars
spec: 2.1
yaml: |
  - Mark McGwire
  - Sammy Sosa
  - Ken Griffey
php: |
  array('Mark McGwire', 'Sammy Sosa', 'Ken Griffey')
---
test: Mapping of scalars to scalars
spec: 2.2
yaml: |
  hr:  65
  avg: 0.278
  rbi: 147
php: |
  array('hr' => 65, 'avg' => 0.278, 'rbi' => 147)
---
test: Mapping of scalars to sequences
spec: 2.3
yaml: |
    american:
       - Boston Red Sox
       - Detroit Tigers
       - New York Yankees
    national:
       - New York Mets
       - Chicago Cubs
       - Atlanta Braves
php: |
    array('american' =>
        array( 'Boston Red Sox', 'Detroit Tigers',
          'New York Yankees' ),
      'national' =>
        array( 'New York Mets', 'Chicago Cubs',
          'Atlanta Braves' )
    )
---
test: Sequence of mappings
spec: 2.4
yaml: |
    -
      name: Mark McGwire
      hr:   65
      avg:  0.278
    -
      name: Sammy Sosa
      hr:   63
      avg:  0.288
php: |
    array(
      array('name' => 'Mark McGwire', 'hr' => 65, 'avg' => 0.278),
      array('name' => 'Sammy Sosa', 'hr' => 63, 'avg' => 0.288)
    )
---
test: Legacy A5
todo: true
spec: legacy_A5
yaml: |
    ?
        - New York Yankees
        - Atlanta Braves
    :
      - 2001-07-02
      - 2001-08-12
      - 2001-08-14
    ?
        - Detroit Tigers
        - Chicago Cubs
    :
      - 2001-07-23
perl-busted: >
    YAML.pm will be able to emulate this behavior soon. In this regard
    it may be somewhat more correct than Python's native behaviour which
    can only use tuples as mapping keys. PyYAML will also need to figure
    out some clever way to roundtrip structured keys.
python: |
    [
    {
        ('New York Yankees', 'Atlanta Braves'):
            [yaml.timestamp('2001-07-02'),
             yaml.timestamp('2001-08-12'),
             yaml.timestamp('2001-08-14')],
        ('Detroit Tigers', 'Chicago Cubs'):
        [yaml.timestamp('2001-07-23')]
    }
    ]
ruby: |
    {
      [ 'New York Yankees', 'Atlanta Braves' ] =>
        [ Date.new( 2001, 7, 2 ), Date.new( 2001, 8, 12 ), Date.new( 2001, 8, 14 ) ],
      [ 'Detroit Tigers', 'Chicago Cubs' ] =>
        [ Date.new( 2001, 7, 23 ) ]
    }
syck: |
  struct test_node seq1[] = {
      { T_STR, 0, "New York Yankees" },
      { T_STR, 0, "Atlanta Braves" },
      end_node
  };
  struct test_node seq2[] = {
      { T_STR, 0, "2001-07-02" },
      { T_STR, 0, "2001-08-12" },
      { T_STR, 0, "2001-08-14" },
      end_node
  };
  struct test_node seq3[] = {
      { T_STR, 0, "Detroit Tigers" },
      { T_STR, 0, "Chicago Cubs" },
      end_node
  };
  struct test_node seq4[] = {
      { T_STR, 0, "2001-07-23" },
      end_node
  };
  struct test_node map[] = {
      { T_SEQ, 0, 0, seq1 },
      { T_SEQ, 0, 0, seq2 },
      { T_SEQ, 0, 0, seq3 },
      { T_SEQ, 0, 0, seq4 },
      end_node
  };
  struct test_node stream[] = {
      { T_MAP, 0, 0, map },
      end_node
  };

---
test: Sequence of sequences
spec: 2.5
yaml: |
  - [ name         , hr , avg   ]
  - [ Mark McGwire , 65 , 0.278 ]
  - [ Sammy Sosa   , 63 , 0.288 ]
php: |
  array(
    array( 'name', 'hr', 'avg' ),
    array( 'Mark McGwire', 65, 0.278 ),
    array( 'Sammy Sosa', 63, 0.288 )
  )
---
test: Mapping of mappings
todo: true
spec: 2.6
yaml: |
  Mark McGwire: {hr: 65, avg: 0.278}
  Sammy Sosa: {
      hr: 63,
      avg: 0.288
    }
php: |
  array(
    'Mark McGwire' =>
      array( 'hr' => 65, 'avg' => 0.278 ),
    'Sammy Sosa' =>
      array( 'hr' => 63, 'avg' => 0.288 )
  )
---
test: Two documents in a stream each with a leading comment
todo: true
spec: 2.7
yaml: |
  # Ranking of 1998 home runs
  ---
  - Mark McGwire
  - Sammy Sosa
  - Ken Griffey

  # Team ranking
  ---
  - Chicago Cubs
  - St Louis Cardinals
ruby: |
  y = YAML::Stream.new
  y.add( [ 'Mark McGwire', 'Sammy Sosa', 'Ken Griffey' ] )
  y.add( [ 'Chicago Cubs', 'St Louis Cardinals' ] )
documents: 2

---
test: Play by play feed from a game
todo: true
spec: 2.8
yaml: |
  ---
  time: 20:03:20
  player: Sammy Sosa
  action: strike (miss)
  ...
  ---
  time: 20:03:47
  player: Sammy Sosa
  action: grand slam
  ...
perl: |
  [ 'Mark McGwire', 'Sammy Sosa', 'Ken Griffey' ]
documents: 2

---
test: Single document with two comments
spec: 2.9
yaml: |
  hr: # 1998 hr ranking
    - Mark McGwire
    - Sammy Sosa
  rbi:
    # 1998 rbi ranking
    - Sammy Sosa
    - Ken Griffey
php: |
  array(
    'hr' => array( 'Mark McGwire', 'Sammy Sosa' ),
    'rbi' => array( 'Sammy Sosa', 'Ken Griffey' )
  )
---
test: Node for Sammy Sosa appears twice in this document
spec: 2.10
yaml: |
   ---
   hr:
      - Mark McGwire
      # Following node labeled SS
      - &SS Sammy Sosa
   rbi:
      - *SS # Subsequent occurrence
      - Ken Griffey
php: |
   array(
      'hr' =>
         array('Mark McGwire', 'Sammy Sosa'),
      'rbi' =>
         array('Sammy Sosa', 'Ken Griffey')
   )
---
test: Mapping between sequences
todo: true
spec: 2.11
yaml: |
   ? # PLAY SCHEDULE
     - Detroit Tigers
     - Chicago Cubs
   :
     - 2001-07-23

   ? [ New York Yankees,
       Atlanta Braves ]
   : [ 2001-07-02, 2001-08-12,
       2001-08-14 ]
ruby: |
   {
      [ 'Detroit Tigers', 'Chicago Cubs' ] => [ Date.new( 2001, 7, 23 ) ],
      [ 'New York Yankees', 'Atlanta Braves' ] => [ Date.new( 2001, 7, 2 ), Date.new( 2001, 8, 12 ), Date.new( 2001, 8, 14 ) ]
   }
syck: |
  struct test_node seq1[] = {
      { T_STR, 0, "New York Yankees" },
      { T_STR, 0, "Atlanta Braves" },
      end_node
  };
  struct test_node seq2[] = {
      { T_STR, 0, "2001-07-02" },
      { T_STR, 0, "2001-08-12" },
      { T_STR, 0, "2001-08-14" },
      end_node
  };
  struct test_node seq3[] = {
      { T_STR, 0, "Detroit Tigers" },
      { T_STR, 0, "Chicago Cubs" },
      end_node
  };
  struct test_node seq4[] = {
      { T_STR, 0, "2001-07-23" },
      end_node
  };
  struct test_node map[] = {
      { T_SEQ, 0, 0, seq3 },
      { T_SEQ, 0, 0, seq4 },
      { T_SEQ, 0, 0, seq1 },
      { T_SEQ, 0, 0, seq2 },
      end_node
  };
  struct test_node stream[] = {
      { T_MAP, 0, 0, map },
      end_node
  };

---
test: Sequence key shortcut
spec: 2.12
yaml: |
  ---
  # products purchased
  - item    : Super Hoop
    quantity: 1
  - item    : Basketball
    quantity: 4
  - item    : Big Shoes
    quantity: 1
php: |
  array (
    array (
      'item' => 'Super Hoop',
      'quantity' => 1,
    ),
    array (
      'item' => 'Basketball',
      'quantity' => 4,
    ),
    array (
      'item' => 'Big Shoes',
      'quantity' => 1,
    )
  )
perl: |
  [
     { item => 'Super Hoop', quantity => 1 },
     { item => 'Basketball', quantity => 4 },
     { item => 'Big Shoes',  quantity => 1 }
  ]

ruby: |
  [
     { 'item' => 'Super Hoop', 'quantity' => 1 },
     { 'item' => 'Basketball', 'quantity' => 4 },
     { 'item' => 'Big Shoes', 'quantity' => 1 }
  ]
python: |
  [
       { 'item': 'Super Hoop', 'quantity': 1 },
       { 'item': 'Basketball', 'quantity': 4 },
       { 'item': 'Big Shoes',  'quantity': 1 }
  ]
syck: |
  struct test_node map1[] = {
      { T_STR, 0, "item" },
          { T_STR, 0, "Super Hoop" },
      { T_STR, 0, "quantity" },
          { T_STR, 0, "1" },
      end_node
  };
  struct test_node map2[] = {
      { T_STR, 0, "item" },
          { T_STR, 0, "Basketball" },
      { T_STR, 0, "quantity" },
          { T_STR, 0, "4" },
      end_node
  };
  struct test_node map3[] = {
      { T_STR, 0, "item" },
          { T_STR, 0, "Big Shoes" },
      { T_STR, 0, "quantity" },
          { T_STR, 0, "1" },
      end_node
  };
  struct test_node seq[] = {
      { T_MAP, 0, 0, map1 },
      { T_MAP, 0, 0, map2 },
      { T_MAP, 0, 0, map3 },
      end_node
  };
  struct test_node stream[] = {
      { T_SEQ, 0, 0, seq },
      end_node
  };


---
test: Literal perserves newlines
todo: true
spec: 2.13
yaml: |
  # ASCII Art
  --- |
    \//||\/||
    // ||  ||_
perl: |
  "\\//||\\/||\n// ||  ||_\n"
ruby: |
  "\\//||\\/||\n// ||  ||_\n"
python: |
    [
        flushLeft(
        """
        \//||\/||
        // ||  ||_
        """
        )
    ]
syck: |
  struct test_node stream[] = {
      { T_STR, 0, "\\//||\\/||\n// ||  ||_\n" },
      end_node
  };

---
test: Folded treats newlines as a space
todo: true
spec: 2.14
yaml: |
  ---
    Mark McGwire's
    year was crippled
    by a knee injury.
perl: |
  "Mark McGwire's year was crippled by a knee injury."
ruby: |
  "Mark McGwire's year was crippled by a knee injury."
python: |
    [ "Mark McGwire's year was crippled by a knee injury." ]
syck: |
  struct test_node stream[] = {
      { T_STR, 0, "Mark McGwire's year was crippled by a knee injury." },
      end_node
  };

---
test: Newlines preserved for indented and blank lines
todo: true
spec: 2.15
yaml: |
  --- >
   Sammy Sosa completed another
   fine season with great stats.

     63 Home Runs
     0.288 Batting Average

   What a year!
perl: |
  "Sammy Sosa completed another fine season with great stats.\n\n  63 Home Runs\n  0.288 Batting Average\n\nWhat a year!\n"
ruby: |
  "Sammy Sosa completed another fine season with great stats.\n\n  63 Home Runs\n  0.288 Batting Average\n\nWhat a year!\n"
python: |
    [
        flushLeft(
        """
        Sammy Sosa completed another fine season with great stats.

          63 Home Runs
          0.288 Batting Average

        What a year!
        """
        )
    ]
syck: |
  struct test_node stream[] = {
      { T_STR, 0, "Sammy Sosa completed another fine season with great stats.\n\n  63 Home Runs\n  0.288 Batting Average\n\nWhat a year!\n" },
      end_node
  };


---
test: Indentation determines scope
spec: 2.16
yaml: |
  name: Mark McGwire
  accomplishment: >
     Mark set a major league
     home run record in 1998.
  stats: |
     65 Home Runs
     0.278 Batting Average
php: |
  array(
    'name'           => 'Mark McGwire',
    'accomplishment' => "Mark set a major league home run record in 1998.\n",
    'stats'          => "65 Home Runs\n0.278 Batting Average\n"
  )
---
test: Quoted scalars
todo: true
spec: 2.17
yaml: |
  unicode: "Sosa did fine.\u263A"
  control: "\b1998\t1999\t2000\n"
  hexesc:  "\x0D\x0A is \r\n"

  single: '"Howdy!" he cried.'
  quoted: ' # not a ''comment''.'
  tie-fighter: '|\-*-/|'
ruby: |
  {
    "tie-fighter" => "|\\-*-/|",
    "control"=>"\0101998\t1999\t2000\n",
    "unicode"=>"Sosa did fine." + ["263A".hex ].pack('U*'),
    "quoted"=>" # not a 'comment'.",
    "single"=>"\"Howdy!\" he cried.",
    "hexesc"=>"\r\n is \r\n"
  }
---
test: Multiline flow scalars
todo: true
spec: 2.18
yaml: |
  plain:
    This unquoted scalar
    spans many lines.

  quoted: "So does this
    quoted scalar.\n"
ruby: |
  {
    'plain' => 'This unquoted scalar spans many lines.',
    'quoted' => "So does this quoted scalar.\n"
  }
---
test: Integers
spec: 2.19
yaml: |
  canonical: 12345
  decimal: +12,345
  octal: 014
  hexadecimal: 0xC
php: |
  array(
    'canonical' => 12345,
    'decimal' => 12345,
    'octal' => 014,
    'hexadecimal' => 0xC
  )
---
# FIX: spec shows parens around -inf and NaN
test: Floating point
spec: 2.20
yaml: |
  canonical: 1.23015e+3
  exponential: 12.3015e+02
  fixed: 1,230.15
  negative infinity: -.inf
  not a number: .NaN
php: |
  array(
    'canonical' => 1230.15,
    'exponential' => 1230.15,
    'fixed' => 1230.15,
    'negative infinity' => log(0),
    'not a number' => -log(0),
  )
---
test: Miscellaneous
spec: 2.21
yaml: |
  null: ~
  true: true
  false: false
  string: '12345'
php: |
  array(
    '' => null,
    1 => true,
    0 => false,
    'string' => '12345'
  )
---
test: Timestamps
todo: true
spec: 2.22
yaml: |
  canonical: 2001-12-15T02:59:43.1Z
  iso8601:  2001-12-14t21:59:43.10-05:00
  spaced:  2001-12-14 21:59:43.10 -05:00
  date:   2002-12-14 # Time is noon UTC
php: |
  array(
    'canonical' => YAML::mktime( 2001, 12, 15, 2, 59, 43, 0.10 ),
    'iso8601' => YAML::mktime( 2001, 12, 14, 21, 59, 43, 0.10, "-05:00" ),
    'spaced' => YAML::mktime( 2001, 12, 14, 21, 59, 43, 0.10, "-05:00" ),
    'date' => Date.new( 2002, 12, 14 )
  )
---
test: legacy Timestamps test
todo: true
spec: legacy D4
yaml: |
    canonical: 2001-12-15T02:59:43.00Z
    iso8601:  2001-02-28t21:59:43.00-05:00
    spaced:  2001-12-14 21:59:43.00 -05:00
    date:   2002-12-14
php: |
   array(
     'canonical' => Time::utc( 2001, 12, 15, 2, 59, 43, 0 ),
     'iso8601' => YAML::mktime( 2001, 2, 28, 21, 59, 43, 0, "-05:00" ),
     'spaced' => YAML::mktime( 2001, 12, 14, 21, 59, 43, 0, "-05:00" ),
     'date' => Date.new( 2002, 12, 14 )
   )
---
test: Various explicit families
todo: true
spec: 2.23
yaml: |
  not-date: !str 2002-04-28
  picture: !binary |
   R0lGODlhDAAMAIQAAP//9/X
   17unp5WZmZgAAAOfn515eXv
   Pz7Y6OjuDg4J+fn5OTk6enp
   56enmleECcgggoBADs=

  application specific tag: !!something |
   The semantics of the tag
   above may be different for
   different documents.

ruby-setup: |
  YAML.add_private_type( "something" ) do |type, val|
    "SOMETHING: #{val}"
  end
ruby: |
  {
    'not-date' => '2002-04-28',
    'picture' => "GIF89a\f\000\f\000\204\000\000\377\377\367\365\365\356\351\351\345fff\000\000\000\347\347\347^^^\363\363\355\216\216\216\340\340\340\237\237\237\223\223\223\247\247\247\236\236\236i^\020' \202\n\001\000;",
    'application specific tag' => "SOMETHING: The semantics of the tag\nabove may be different for\ndifferent documents.\n"
  }
---
test: Application specific family
todo: true
spec: 2.24
yaml: |
  # Establish a tag prefix
  --- !clarkevans.com,2002/graph/^shape
    # Use the prefix: shorthand for
    # !clarkevans.com,2002/graph/circle
  - !^circle
    center: &ORIGIN {x: 73, 'y': 129}
    radius: 7
  - !^line # !clarkevans.com,2002/graph/line
    start: *ORIGIN
    finish: { x: 89, 'y': 102 }
  - !^label
    start: *ORIGIN
    color: 0xFFEEBB
    value: Pretty vector drawing.
ruby-setup: |
  YAML.add_domain_type( "clarkevans.com,2002", 'graph/shape' ) { |type, val|
    if Array === val
      val << "Shape Container"
      val
    else
      raise YAML::Error, "Invalid graph of class #{ val.class }: " + val.inspect
    end
  }
  one_shape_proc = Proc.new { |type, val|
    scheme, domain, type = type.split( /:/, 3 )
    if val.is_a? ::Hash
      val['TYPE'] = "Shape: #{type}"
      val
    else
      raise YAML::Error, "Invalid graph of class #{ val.class }: " + val.inspect
    end
  }
  YAML.add_domain_type( "clarkevans.com,2002", 'graph/circle', &one_shape_proc )
  YAML.add_domain_type( "clarkevans.com,2002", 'graph/line', &one_shape_proc )
  YAML.add_domain_type( "clarkevans.com,2002", 'graph/label', &one_shape_proc )
ruby: |
  [
    {
      "radius" => 7,
      "center"=>
      {
        "x" => 73,
        "y" => 129
      },
      "TYPE" => "Shape: graph/circle"
    }, {
      "finish" =>
      {
        "x" => 89,
        "y" => 102
      },
      "TYPE" => "Shape: graph/line",
      "start" =>
      {
        "x" => 73,
        "y" => 129
      }
    }, {
      "TYPE" => "Shape: graph/label",
      "value" => "Pretty vector drawing.",
      "start" =>
      {
        "x" => 73,
        "y" => 129
      },
      "color" => 16772795
    },
    "Shape Container"
  ]
# ---
# test: Unordered set
# spec: 2.25
# yaml: |
#   # sets are represented as a
#   # mapping where each key is
#   # associated with the empty string
#   --- !set
#   ? Mark McGwire
#   ? Sammy Sosa
#   ? Ken Griff
---
test: Ordered mappings
todo: true
spec: 2.26
yaml: |
  # ordered maps are represented as
  # a sequence of mappings, with
  # each mapping having one key
  --- !omap
  - Mark McGwire: 65
  - Sammy Sosa: 63
  - Ken Griffy: 58
ruby: |
  YAML::Omap[
    'Mark McGwire', 65,
    'Sammy Sosa', 63,
    'Ken Griffy', 58
  ]
---
test: Invoice
dump_skip: true
spec: 2.27
yaml: |
  --- !clarkevans.com,2002/^invoice
  invoice: 34843
  date   : 2001-01-23
  bill-to: &id001
      given  : Chris
      family : Dumars
      address:
          lines: |
              458 Walkman Dr.
              Suite #292
          city    : Royal Oak
          state   : MI
          postal  : 48046
  ship-to: *id001
  product:
      -
        sku         : BL394D
        quantity    : 4
        description : Basketball
        price       : 450.00
      -
        sku         : BL4438H
        quantity    : 1
        description : Super Hoop
        price       : 2392.00
  tax  : 251.42
  total: 4443.52
  comments: >
    Late afternoon is best.
    Backup contact is Nancy
    Billsmer @ 338-4338.
php: |
  array(
     'invoice' => 34843, 'date' => mktime(0, 0, 0, 1, 23, 2001),
     'bill-to' =>
      array( 'given' => 'Chris', 'family' => 'Dumars', 'address' => array( 'lines' => "458 Walkman Dr.\nSuite #292\n", 'city' => 'Royal Oak', 'state' => 'MI', 'postal' => 48046 ) )
     , 'ship-to' =>
      array( 'given' => 'Chris', 'family' => 'Dumars', 'address' => array( 'lines' => "458 Walkman Dr.\nSuite #292\n", 'city' => 'Royal Oak', 'state' => 'MI', 'postal' => 48046 ) )
     , 'product' =>
       array(
        array( 'sku' => 'BL394D', 'quantity' => 4, 'description' => 'Basketball', 'price' => 450.00 ),
        array( 'sku' => 'BL4438H', 'quantity' => 1, 'description' => 'Super Hoop', 'price' => 2392.00 )
      ),
     'tax' => 251.42, 'total' => 4443.52,
     'comments' => "Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338.\n"
  )
---
test: Log file
todo: true
spec: 2.28
yaml: |
  ---
  Time: 2001-11-23 15:01:42 -05:00
  User: ed
  Warning: >
    This is an error message
    for the log file
  ---
  Time: 2001-11-23 15:02:31 -05:00
  User: ed
  Warning: >
    A slightly different error
    message.
  ---
  Date: 2001-11-23 15:03:17 -05:00
  User: ed
  Fatal: >
    Unknown variable "bar"
  Stack:
    - file: TopClass.py
      line: 23
      code: |
        x = MoreObject("345\n")
    - file: MoreClass.py
      line: 58
      code: |-
        foo = bar
ruby: |
  y = YAML::Stream.new
  y.add( { 'Time' => YAML::mktime( 2001, 11, 23, 15, 01, 42, 00, "-05:00" ),
           'User' => 'ed', 'Warning' => "This is an error message for the log file\n" } )
  y.add( { 'Time' => YAML::mktime( 2001, 11, 23, 15, 02, 31, 00, "-05:00" ),
           'User' => 'ed', 'Warning' => "A slightly different error message.\n" } )
  y.add( { 'Date' => YAML::mktime( 2001, 11, 23, 15, 03, 17, 00, "-05:00" ),
           'User' => 'ed', 'Fatal' => "Unknown variable \"bar\"\n",
           'Stack' => [
           { 'file' => 'TopClass.py', 'line' => 23, 'code' => "x = MoreObject(\"345\\n\")\n" },
           { 'file' => 'MoreClass.py', 'line' => 58, 'code' => "foo = bar" } ] } )
documents: 3

---
test: Throwaway comments
yaml: |
   ### These are four throwaway comment  ###

   ### lines (the second line is empty). ###
   this: |   # Comments may trail lines.
      contains three lines of text.
      The third one starts with a
      # character. This isn't a comment.

   # These are three throwaway comment
   # lines (the first line is empty).
php: |
   array(
     'this' => "contains three lines of text.\nThe third one starts with a\n# character. This isn't a comment.\n"
   )
---
test: Document with a single value
todo: true
yaml: |
   --- >
   This YAML stream contains a single text value.
   The next stream is a log file - a sequence of
   log entries. Adding an entry to the log is a
   simple matter of appending it at the end.
ruby: |
   "This YAML stream contains a single text value. The next stream is a log file - a sequence of log entries. Adding an entry to the log is a simple matter of appending it at the end.\n"
---
test: Document stream
todo: true
yaml: |
   ---
   at: 2001-08-12 09:25:00.00 Z
   type: GET
   HTTP: '1.0'
   url: '/index.html'
   ---
   at: 2001-08-12 09:25:10.00 Z
   type: GET
   HTTP: '1.0'
   url: '/toc.html'
ruby: |
   y = YAML::Stream.new
   y.add( {
      'at' => Time::utc( 2001, 8, 12, 9, 25, 00 ),
      'type' => 'GET',
      'HTTP' => '1.0',
      'url' => '/index.html'
   } )
   y.add( {
      'at' => Time::utc( 2001, 8, 12, 9, 25, 10 ),
      'type' => 'GET',
      'HTTP' => '1.0',
      'url' => '/toc.html'
   } )
documents: 2

---
test: Top level mapping
yaml: |
   # This stream is an example of a top-level mapping.
   invoice : 34843
   date    : 2001-01-23
   total   : 4443.52
php: |
   array(
      'invoice' => 34843,
      'date' => mktime(0, 0, 0, 1, 23, 2001),
      'total' => 4443.52
   )
---
test: Single-line documents
todo: true
yaml: |
  # The following is a sequence of three documents.
  # The first contains an empty mapping, the second
  # an empty sequence, and the last an empty string.
  --- {}
  --- [ ]
  --- ''
ruby: |
  y = YAML::Stream.new
  y.add( {} )
  y.add( [] )
  y.add( '' )
documents: 3

---
test: Document with pause
todo: true
yaml: |
  # A communication channel based on a YAML stream.
  ---
  sent at: 2002-06-06 11:46:25.10 Z
  payload: Whatever
  # Receiver can process this as soon as the following is sent:
  ...
  # Even if the next message is sent long after:
  ---
  sent at: 2002-06-06 12:05:53.47 Z
  payload: Whatever
  ...
ruby: |
  y = YAML::Stream.new
  y.add(
    { 'sent at' => YAML::mktime( 2002, 6, 6, 11, 46, 25, 0.10 ),
      'payload' => 'Whatever' }
  )
  y.add(
    { "payload" => "Whatever", "sent at" => YAML::mktime( 2002, 6, 6, 12, 5, 53, 0.47 ) }
  )
documents: 2

---
test: Explicit typing
yaml: |
   integer: 12
   also int: ! "12"
   string: !str 12
php: |
   array( 'integer' => 12, 'also int' => 12, 'string' => '12' )
---
test: Private types
todo: true
yaml: |
  # Both examples below make use of the 'x-private:ball'
  # type family URI, but with different semantics.
  ---
  pool: !!ball
    number: 8
    color: black
  ---
  bearing: !!ball
    material: steel
ruby: |
  y = YAML::Stream.new
  y.add( { 'pool' =>
    YAML::PrivateType.new( 'ball',
      { 'number' => 8, 'color' => 'black' } ) }
  )
  y.add( { 'bearing' =>
    YAML::PrivateType.new( 'ball',
      { 'material' => 'steel' } ) }
  )
documents: 2

---
test: Type family under yaml.org
yaml: |
  # The URI is 'tag:yaml.org,2002:str'
  - !str a Unicode string
php: |
  array( 'a Unicode string' )
---
test: Type family under perl.yaml.org
todo: true
yaml: |
  # The URI is 'tag:perl.yaml.org,2002:Text::Tabs'
  - !perl/Text::Tabs {}
ruby: |
  [ YAML::DomainType.new( 'perl.yaml.org,2002', 'Text::Tabs', {} ) ]
---
test: Type family under clarkevans.com
todo: true
yaml: |
  # The URI is 'tag:clarkevans.com,2003-02:timesheet'
  - !clarkevans.com,2003-02/timesheet {}
ruby: |
  [ YAML::DomainType.new( 'clarkevans.com,2003-02', 'timesheet', {} ) ]
---
test: URI Escaping
todo: true
yaml: |
  same:
    - !domain.tld,2002/type\x30 value
    - !domain.tld,2002/type0 value
  different: # As far as the YAML parser is concerned
    - !domain.tld,2002/type%30 value
    - !domain.tld,2002/type0 value
ruby-setup: |
  YAML.add_domain_type( "domain.tld,2002", "type0" ) { |type, val|
    "ONE: #{val}"
  }
  YAML.add_domain_type( "domain.tld,2002", "type%30" ) { |type, val|
    "TWO: #{val}"
  }
ruby: |
  { 'same' => [ 'ONE: value', 'ONE: value' ], 'different' => [ 'TWO: value', 'ONE: value' ] }
---
test: URI Prefixing
todo: true
yaml: |
  # 'tag:domain.tld,2002:invoice' is some type family.
  invoice: !domain.tld,2002/^invoice
    # 'seq' is shorthand for 'tag:yaml.org,2002:seq'.
    # This does not effect '^customer' below
    # because it is does not specify a prefix.
    customers: !seq
      # '^customer' is shorthand for the full
      # notation 'tag:domain.tld,2002:customer'.
      - !^customer
        given : Chris
        family : Dumars
ruby-setup: |
  YAML.add_domain_type( "domain.tld,2002", /(invoice|customer)/ ) { |type, val|
    if val.is_a? ::Hash
      scheme, domain, type = type.split( /:/, 3 )
      val['type'] = "domain #{type}"
      val
    else
      raise YAML::Error, "Not a Hash in domain.tld/invoice: " + val.inspect
    end
  }
ruby: |
  { "invoice"=> { "customers"=> [ { "given"=>"Chris", "type"=>"domain customer", "family"=>"Dumars" } ], "type"=>"domain invoice" } }

---
test: Overriding anchors
yaml: |
  anchor : &A001 This scalar has an anchor.
  override : &A001 >
   The alias node below is a
   repeated use of this value.
  alias : *A001
php: |
  array( 'anchor' => 'This scalar has an anchor.',
    'override' => "The alias node below is a repeated use of this value.\n",
    'alias' => "The alias node below is a repeated use of this value.\n" )
---
test: Flow and block formatting
todo: true
yaml: |
  empty: []
  flow: [ one, two, three # May span lines,
           , four,           # indentation is
             five ]          # mostly ignored.
  block:
   - First item in top sequence
   -
    - Subordinate sequence entry
   - >
     A folded sequence entry
   - Sixth item in top sequence
ruby: |
  { 'empty' => [], 'flow' => [ 'one', 'two', 'three', 'four', 'five' ],
    'block' => [ 'First item in top sequence', [ 'Subordinate sequence entry' ],
    "A folded sequence entry\n", 'Sixth item in top sequence' ] }
---
test: Complete mapping test
todo: true
yaml: |
 empty: {}
 flow: { one: 1, two: 2 }
 spanning: { one: 1,
    two: 2 }
 block:
  first : First entry
  second:
   key: Subordinate mapping
  third:
   - Subordinate sequence
   - { }
   - Previous mapping is empty.
   - A key: value pair in a sequence.
     A second: key:value pair.
   - The previous entry is equal to the following one.
   -
     A key: value pair in a sequence.
     A second: key:value pair.
  !float 12 : This key is a float.
  ? >
   ?
  : This key had to be protected.
  "\a" : This key had to be escaped.
  ? >
   This is a
   multi-line
   folded key
  : Whose value is
    also multi-line.
  ? this also works as a key
  : with a value at the next line.
  ?
   - This key
   - is a sequence
  :
   - With a sequence value.
  ?
   This: key
   is a: mapping
  :
   with a: mapping value.
ruby: |
  { 'empty' => {}, 'flow' => { 'one' => 1, 'two' => 2 },
    'spanning' => { 'one' => 1, 'two' => 2 },
    'block' => { 'first' => 'First entry', 'second' =>
    { 'key' => 'Subordinate mapping' }, 'third' =>
      [ 'Subordinate sequence', {}, 'Previous mapping is empty.',
        { 'A key' => 'value pair in a sequence.', 'A second' => 'key:value pair.' },
        'The previous entry is equal to the following one.',
        { 'A key' => 'value pair in a sequence.', 'A second' => 'key:value pair.' } ],
    12.0 => 'This key is a float.', "?\n" => 'This key had to be protected.',
    "\a" => 'This key had to be escaped.',
    "This is a multi-line folded key\n" => "Whose value is also multi-line.",
    'this also works as a key' => 'with a value at the next line.',
    [ 'This key', 'is a sequence' ] => [ 'With a sequence value.' ] } }
  # Couldn't recreate map exactly, so we'll do a detailed check to be sure it's entact
  obj_y['block'].keys.each { |k|
    if Hash === k
      v = obj_y['block'][k]
      if k['This'] == 'key' and k['is a'] == 'mapping' and v['with a'] == 'mapping value.'
         obj_r['block'][k] = v
      end
    end
  }
---
test: Literal explicit indentation
yaml: |
   # Explicit indentation must
   # be given in all the three
   # following cases.
   leading spaces: |2
         This value starts with four spaces.

   leading line break: |2

     This value starts with a line break.

   leading comment indicator: |2
     # first line starts with a
     # character.

   # Explicit indentation may
   # also be given when it is
   # not required.
   redundant: |2
     This value is indented 2 spaces.
php: |
   array(
      'leading spaces' => "    This value starts with four spaces.\n",
      'leading line break' => "\nThis value starts with a line break.\n",
      'leading comment indicator' => "# first line starts with a\n# character.\n",
      'redundant' => "This value is indented 2 spaces.\n"
   )
---
test: Chomping and keep modifiers
yaml: |
    clipped: |
        This has one newline.

    same as "clipped" above: "This has one newline.\n"

    stripped: |-
        This has no newline.

    same as "stripped" above: "This has no newline."

    kept: |+
        This has two newlines.

    same as "kept" above: "This has two newlines.\n\n"
php: |
    array(
      'clipped' => "This has one newline.\n",
      'same as "clipped" above' => "This has one newline.\n",
      'stripped' => 'This has no newline.',
      'same as "stripped" above' => 'This has no newline.',
      'kept' => "This has two newlines.\n\n",
      'same as "kept" above' => "This has two newlines.\n\n"
    )
---
test: Literal combinations
todo: true
yaml: |
   empty: |

   literal: |
    The \ ' " characters may be
    freely used. Leading white
       space is significant.

    Line breaks are significant.
    Thus this value contains one
    empty line and ends with a
    single line break, but does
    not start with one.

   is equal to: "The \\ ' \" characters may \
    be\nfreely used. Leading white\n   space \
    is significant.\n\nLine breaks are \
    significant.\nThus this value contains \
    one\nempty line and ends with a\nsingle \
    line break, but does\nnot start with one.\n"

   # Comments may follow a block
   # scalar value. They must be
   # less indented.

   # Modifiers may be combined in any order.
   indented and chomped: |2-
       This has no newline.

   also written as: |-2
       This has no newline.

   both are equal to: "  This has no newline."
php: |
   array(
     'empty' => '',
     'literal' => "The \\ ' \" characters may be\nfreely used. Leading white\n   space " +
       "is significant.\n\nLine breaks are significant.\nThus this value contains one\n" +
       "empty line and ends with a\nsingle line break, but does\nnot start with one.\n",
     'is equal to' => "The \\ ' \" characters may be\nfreely used. Leading white\n   space " +
       "is significant.\n\nLine breaks are significant.\nThus this value contains one\n" +
       "empty line and ends with a\nsingle line break, but does\nnot start with one.\n",
     'indented and chomped' => '  This has no newline.',
     'also written as' => '  This has no newline.',
     'both are equal to' => '  This has no newline.'
   )
---
test: Folded combinations
todo: true
yaml: |
   empty: >

   one paragraph: >
    Line feeds are converted
    to spaces, so this value
    contains no line breaks
    except for the final one.

   multiple paragraphs: >2

     An empty line, either
     at the start or in
     the value:

     Is interpreted as a
     line break. Thus this
     value contains three
     line breaks.

   indented text: >
       This is a folded
       paragraph followed
       by a list:
        * first entry
        * second entry
       Followed by another
       folded paragraph,
       another list:

        * first entry

        * second entry

       And a final folded
       paragraph.

   above is equal to: |
       This is a folded paragraph followed by a list:
        * first entry
        * second entry
       Followed by another folded paragraph, another list:

        * first entry

        * second entry

       And a final folded paragraph.

   # Explicit comments may follow
   # but must be less indented.
php: |
   array(
     'empty' => '',
     'one paragraph' => 'Line feeds are converted to spaces, so this value'.
       " contains no line breaks except for the final one.\n",
     'multiple paragraphs' => "\nAn empty line, either at the start or in the value:\n".
       "Is interpreted as a line break. Thus this value contains three line breaks.\n",
     'indented text' => "This is a folded paragraph followed by a list:\n".
       " * first entry\n * second entry\nFollowed by another folded paragraph, ".
       "another list:\n\n * first entry\n\n * second entry\n\nAnd a final folded paragraph.\n",
     'above is equal to' => "This is a folded paragraph followed by a list:\n".
       " * first entry\n * second entry\nFollowed by another folded paragraph, ".
       "another list:\n\n * first entry\n\n * second entry\n\nAnd a final folded paragraph.\n"
   )
---
test: Single quotes
todo: true
yaml: |
   empty: ''
   second: '! : \ etc. can be used freely.'
   third: 'a single quote '' must be escaped.'
   span: 'this contains
         six spaces

         and one
         line break'
   is same as: "this contains six spaces\nand one line break"
php: |
   array(
     'empty' => '',
     'second' => '! : \\ etc. can be used freely.',
     'third' => "a single quote ' must be escaped.",
     'span' => "this contains six spaces\nand one line break",
     'is same as' => "this contains six spaces\nand one line break"
   )
---
test: Double quotes
todo: true
yaml: |
   empty: ""
   second: "! : etc. can be used freely."
   third: "a \" or a \\ must be escaped."
   fourth: "this value ends with an LF.\n"
   span: "this contains
     four  \
         spaces"
   is equal to: "this contains four  spaces"
php: |
   array(
     'empty' => '',
     'second' => '! : etc. can be used freely.',
     'third' => 'a " or a \\ must be escaped.',
     'fourth' => "this value ends with an LF.\n",
     'span' => "this contains four  spaces",
     'is equal to' => "this contains four  spaces"
   )
---
test: Unquoted strings
todo: true
yaml: |
   first: There is no unquoted empty string.

   second: 12          ## This is an integer.

   third: !str 12      ## This is a string.

   span: this contains
         six spaces

         and one
         line break

   indicators: this has no comments.
               #:foo and bar# are
               both text.

   flow: [ can span
              lines, # comment
              like
              this ]

   note: { one-line keys: but multi-line values }

php: |
   array(
     'first' => 'There is no unquoted empty string.',
     'second' => 12,
     'third' => '12',
     'span' => "this contains six spaces\nand one line break",
     'indicators' => "this has no comments. #:foo and bar# are both text.",
     'flow' => [ 'can span lines', 'like this' ],
     'note' => { 'one-line keys' => 'but multi-line values' }
   )
---
test: Spanning sequences
todo: true
yaml: |
   # The following are equal seqs
   # with different identities.
   flow: [ one, two ]
   spanning: [ one,
        two ]
   block:
     - one
     - two
php: |
   array(
     'flow' => [ 'one', 'two' ],
     'spanning' => [ 'one', 'two' ],
     'block' => [ 'one', 'two' ]
   )
---
test: Flow mappings
yaml: |
   # The following are equal maps
   # with different identities.
   flow: { one: 1, two: 2 }
   block:
       one: 1
       two: 2
php: |
   array(
     'flow' => array( 'one' => 1, 'two' => 2 ),
     'block' => array( 'one' => 1, 'two' => 2 )
   )
---
test: Representations of 12
todo: true
yaml: |
   - 12 # An integer
   # The following scalars
   # are loaded to the
   # string value '1' '2'.
   - !str 12
   - '12'
   - "12"
   - "\
     1\
     2\
     "
   # Strings containing paths and regexps can be unquoted:
   - /foo/bar
   - d:/foo/bar
   - foo/bar
   - /a.*b/
php: |
   array( 12, '12', '12', '12', '12', '/foo/bar', 'd:/foo/bar', 'foo/bar', '/a.*b/' )
---
test: "Null"
todo: true
yaml: |
   canonical: ~

   english: null

   # This sequence has five
   # entries, two with values.
   sparse:
     - ~
     - 2nd entry
     - Null
     - 4th entry
     -

   four: This mapping has five keys,
         only two with values.

php: |
   array (
     'canonical' => null,
     'english' => null,
     'sparse' => array( null, '2nd entry', null, '4th entry', null ]),
     'four' => 'This mapping has five keys, only two with values.'
   )
---
test: Omap
todo: true
yaml: |
   # Explicitly typed dictionary.
   Bestiary: !omap
     - aardvark: African pig-like ant eater. Ugly.
     - anteater: South-American ant eater. Two species.
     - anaconda: South-American constrictor snake. Scary.
     # Etc.
ruby: |
   {
     'Bestiary' => YAML::Omap[
       'aardvark', 'African pig-like ant eater. Ugly.',
       'anteater', 'South-American ant eater. Two species.',
       'anaconda', 'South-American constrictor snake. Scary.'
     ]
   }

---
test: Pairs
todo: true
yaml: |
  # Explicitly typed pairs.
  tasks: !pairs
    - meeting: with team.
    - meeting: with boss.
    - break: lunch.
    - meeting: with client.
ruby: |
  {
    'tasks' => YAML::Pairs[
      'meeting', 'with team.',
      'meeting', 'with boss.',
      'break', 'lunch.',
      'meeting', 'with client.'
    ]
  }

---
test: Set
todo: true
yaml: |
  # Explicitly typed set.
  baseball players: !set
    Mark McGwire:
    Sammy Sosa:
    Ken Griffey:
ruby: |
  {
    'baseball players' => YAML::Set[
      'Mark McGwire', nil,
      'Sammy Sosa', nil,
      'Ken Griffey', nil
    ]
  }

---
test: Boolean
yaml: |
   false: used as key
   logical:  true
   answer: false
php: |
   array(
     false => 'used as key',
     'logical' => true,
     'answer' => false
   )
---
test: Integer
yaml: |
   canonical: 12345
   decimal: +12,345
   octal: 014
   hexadecimal: 0xC
php: |
   array(
     'canonical' => 12345,
     'decimal' => 12345,
     'octal' => 12,
     'hexadecimal' => 12
   )
---
test: Float
yaml: |
   canonical: 1.23015e+3
   exponential: 12.3015e+02
   fixed: 1,230.15
   negative infinity: -.inf
   not a number: .NaN
php: |
  array(
    'canonical' => 1230.15,
    'exponential' => 1230.15,
    'fixed' => 1230.15,
    'negative infinity' => log(0),
    'not a number' => -log(0)
  )
---
test: Timestamp
todo: true
yaml: |
   canonical:       2001-12-15T02:59:43.1Z
   valid iso8601:   2001-12-14t21:59:43.10-05:00
   space separated: 2001-12-14 21:59:43.10 -05:00
   date (noon UTC): 2002-12-14
ruby: |
   array(
     'canonical' => YAML::mktime( 2001, 12, 15, 2, 59, 43, 0.10 ),
     'valid iso8601' => YAML::mktime( 2001, 12, 14, 21, 59, 43, 0.10, "-05:00" ),
     'space separated' => YAML::mktime( 2001, 12, 14, 21, 59, 43, 0.10, "-05:00" ),
     'date (noon UTC)' => Date.new( 2002, 12, 14 )
   )
---
test: Binary
todo: true
yaml: |
   canonical: !binary "\
    R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5\
    OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+\
    +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC\
    AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs="
   base64: !binary |
    R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5
    OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+
    +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC
    AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs=
   description: >
    The binary value above is a tiny arrow
    encoded as a gif image.
ruby-setup: |
   arrow_gif = "GIF89a\f\000\f\000\204\000\000\377\377\367\365\365\356\351\351\345fff\000\000\000\347\347\347^^^\363\363\355\216\216\216\340\340\340\237\237\237\223\223\223\247\247\247\236\236\236iiiccc\243\243\243\204\204\204\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371!\376\016Made with GIMP\000,\000\000\000\000\f\000\f\000\000\005,  \216\2010\236\343@\024\350i\020\304\321\212\010\034\317\200M$z\357\3770\205p\270\2601f\r\e\316\001\303\001\036\020' \202\n\001\000;"
ruby: |
   {
     'canonical' => arrow_gif,
     'base64' => arrow_gif,
     'description' => "The binary value above is a tiny arrow encoded as a gif image.\n"
   }

---
test: Merge key
todo: true
yaml: |
  ---
  - &CENTER { x: 1, y: 2 }
  - &LEFT { x: 0, y: 2 }
  - &BIG { r: 10 }
  - &SMALL { r: 1 }

  # All the following maps are equal:

  - # Explicit keys
    x: 1
    y: 2
    r: 10
    label: center/big

  - # Merge one map
    << : *CENTER
    r: 10
    label: center/big

  - # Merge multiple maps
    << : [ *CENTER, *BIG ]
    label: center/big

  - # Override
    << : [ *BIG, *LEFT, *SMALL ]
    x: 1
    label: center/big

ruby-setup: |
  center = { 'x' => 1, 'y' => 2 }
  left = { 'x' => 0, 'y' => 2 }
  big = { 'r' => 10 }
  small = { 'r' => 1 }
  node1 = { 'x' => 1, 'y' => 2, 'r' => 10, 'label' => 'center/big' }
  node2 = center.dup
  node2.update( { 'r' => 10, 'label' => 'center/big' } )
  node3 = big.dup
  node3.update( center )
  node3.update( { 'label' => 'center/big' } )
  node4 = small.dup
  node4.update( left )
  node4.update( big )
  node4.update( { 'x' => 1, 'label' => 'center/big' } )

ruby: |
  [
    center, left, big, small, node1, node2, node3, node4
  ]

---
test: Default key
todo: true
yaml: |
   ---     # Old schema
   link with:
     - library1.dll
     - library2.dll
   ---     # New schema
   link with:
     - = : library1.dll
       version: 1.2
     - = : library2.dll
       version: 2.3
ruby: |
   y = YAML::Stream.new
   y.add( { 'link with' => [ 'library1.dll', 'library2.dll' ] } )
   obj_h = Hash[ 'version' => 1.2 ]
   obj_h.default = 'library1.dll'
   obj_h2 = Hash[ 'version' => 2.3 ]
   obj_h2.default = 'library2.dll'
   y.add( { 'link with' => [ obj_h, obj_h2 ] } )
documents: 2

---
test: Special keys
todo: true
yaml: |
   "!": These three keys
   "&": had to be quoted
   "=": and are normal strings.
   # NOTE: the following node should NOT be serialized this way.
   encoded node :
    !special '!' : '!type'
    !special|canonical '&' : 12
    = : value
   # The proper way to serialize the above node is as follows:
   node : !!type &12 value
ruby: |
   { '!' => 'These three keys', '&' => 'had to be quoted',
     '=' => 'and are normal strings.',
     'encoded node' => YAML::PrivateType.new( 'type', 'value' ),
     'node' => YAML::PrivateType.new( 'type', 'value' ) }
PK��Z~;�p2p25test/Yaml/Symfony/Component/Yaml/Tests/ParserTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Yaml\Tests;

use Symfony\Component\Yaml\Yaml;
use Symfony\Component\Yaml\Parser;

class ParserTest extends \PHPUnit_Framework_TestCase
{
    protected $parser;

    protected function setUp()
    {
        $this->parser = new Parser();
    }

    protected function tearDown()
    {
        $this->parser = null;
    }

    /**
     * @dataProvider getDataFormSpecifications
     */
    public function testSpecifications($file, $expected, $yaml, $comment)
    {
        if ('escapedCharacters' == $file) {
            if (!function_exists('iconv') && !function_exists('mb_convert_encoding')) {
                $this->markTestSkipped('The iconv and mbstring extensions are not available.');
            }
        }

        $this->assertEquals($expected, var_export($this->parser->parse($yaml), true), $comment);
    }

    public function getDataFormSpecifications()
    {
        $parser = new Parser();
        $path = __DIR__.'/Fixtures';

        $tests = array();
        $files = $parser->parse(file_get_contents($path.'/index.yml'));
        foreach ($files as $file) {
            $yamls = file_get_contents($path.'/'.$file.'.yml');

            // split YAMLs documents
            foreach (preg_split('/^---( %YAML\:1\.0)?/m', $yamls) as $yaml) {
                if (!$yaml) {
                    continue;
                }

                $test = $parser->parse($yaml);
                if (isset($test['todo']) && $test['todo']) {
                    // TODO
                } else {
                    eval('$expected = '.trim($test['php']).';');

                    $tests[] = array($file, var_export($expected, true), $test['yaml'], $test['test']);
                }
            }
        }

        return $tests;
    }

    public function testTabsInYaml()
    {
        // test tabs in YAML
        $yamls = array(
            "foo:\n	bar",
            "foo:\n 	bar",
            "foo:\n	 bar",
            "foo:\n 	 bar",
        );

        foreach ($yamls as $yaml) {
            try {
                $content = $this->parser->parse($yaml);

                $this->fail('YAML files must not contain tabs');
            } catch (\Exception $e) {
                $this->assertInstanceOf('\Exception', $e, 'YAML files must not contain tabs');
                $this->assertEquals('A YAML file cannot contain tabs as indentation at line 2 (near "'.strpbrk($yaml, "\t").'").', $e->getMessage(), 'YAML files must not contain tabs');
            }
        }
    }

    public function testEndOfTheDocumentMarker()
    {
        $yaml = <<<EOF
--- %YAML:1.0
foo
...
EOF;

        $this->assertEquals('foo', $this->parser->parse($yaml));
    }

    public function getBlockChompingTests()
    {
        $tests = array();

        $yaml = <<<'EOF'
foo: |-
    one
    two
bar: |-
    one
    two

EOF;
        $expected = array(
            'foo' => "one\ntwo",
            'bar' => "one\ntwo",
        );
        $tests['Literal block chomping strip with single trailing newline'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: |-
    one
    two

bar: |-
    one
    two


EOF;
        $expected = array(
            'foo' => "one\ntwo",
            'bar' => "one\ntwo",
        );
        $tests['Literal block chomping strip with multiple trailing newlines'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: |-
    one
    two
bar: |-
    one
    two
EOF;
        $expected = array(
            'foo' => "one\ntwo",
            'bar' => "one\ntwo",
        );
        $tests['Literal block chomping strip without trailing newline'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: |
    one
    two
bar: |
    one
    two

EOF;
        $expected = array(
            'foo' => "one\ntwo\n",
            'bar' => "one\ntwo\n",
        );
        $tests['Literal block chomping clip with single trailing newline'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: |
    one
    two

bar: |
    one
    two


EOF;
        $expected = array(
            'foo' => "one\ntwo\n",
            'bar' => "one\ntwo\n",
        );
        $tests['Literal block chomping clip with multiple trailing newlines'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: |
    one
    two
bar: |
    one
    two
EOF;
        $expected = array(
            'foo' => "one\ntwo\n",
            'bar' => "one\ntwo",
        );
        $tests['Literal block chomping clip without trailing newline'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: |+
    one
    two
bar: |+
    one
    two

EOF;
        $expected = array(
            'foo' => "one\ntwo\n",
            'bar' => "one\ntwo\n",
        );
        $tests['Literal block chomping keep with single trailing newline'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: |+
    one
    two

bar: |+
    one
    two


EOF;
        $expected = array(
            'foo' => "one\ntwo\n\n",
            'bar' => "one\ntwo\n\n",
        );
        $tests['Literal block chomping keep with multiple trailing newlines'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: |+
    one
    two
bar: |+
    one
    two
EOF;
        $expected = array(
            'foo' => "one\ntwo\n",
            'bar' => "one\ntwo",
        );
        $tests['Literal block chomping keep without trailing newline'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: >-
    one
    two
bar: >-
    one
    two

EOF;
        $expected = array(
            'foo' => "one two",
            'bar' => "one two",
        );
        $tests['Folded block chomping strip with single trailing newline'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: >-
    one
    two

bar: >-
    one
    two


EOF;
        $expected = array(
            'foo' => "one two",
            'bar' => "one two",
        );
        $tests['Folded block chomping strip with multiple trailing newlines'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: >-
    one
    two
bar: >-
    one
    two
EOF;
        $expected = array(
            'foo' => "one two",
            'bar' => "one two",
        );
        $tests['Folded block chomping strip without trailing newline'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: >
    one
    two
bar: >
    one
    two

EOF;
        $expected = array(
            'foo' => "one two\n",
            'bar' => "one two\n",
        );
        $tests['Folded block chomping clip with single trailing newline'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: >
    one
    two

bar: >
    one
    two


EOF;
        $expected = array(
            'foo' => "one two\n",
            'bar' => "one two\n",
        );
        $tests['Folded block chomping clip with multiple trailing newlines'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: >
    one
    two
bar: >
    one
    two
EOF;
        $expected = array(
            'foo' => "one two\n",
            'bar' => "one two",
        );
        $tests['Folded block chomping clip without trailing newline'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: >+
    one
    two
bar: >+
    one
    two

EOF;
        $expected = array(
            'foo' => "one two\n",
            'bar' => "one two\n",
        );
        $tests['Folded block chomping keep with single trailing newline'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: >+
    one
    two

bar: >+
    one
    two


EOF;
        $expected = array(
            'foo' => "one two\n\n",
            'bar' => "one two\n\n",
        );
        $tests['Folded block chomping keep with multiple trailing newlines'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: >+
    one
    two
bar: >+
    one
    two
EOF;
        $expected = array(
            'foo' => "one two\n",
            'bar' => "one two",
        );
        $tests['Folded block chomping keep without trailing newline'] = array($expected, $yaml);

        return $tests;
    }

    /**
     * @dataProvider getBlockChompingTests
     */
    public function testBlockChomping($expected, $yaml)
    {
        $this->assertSame($expected, $this->parser->parse($yaml));
    }

    /**
     * Regression test for issue #7989.
     *
     * @see https://github.com/symfony/symfony/issues/7989
     */
    public function testBlockLiteralWithLeadingNewlines()
    {
        $yaml = <<<'EOF'
foo: |-


    bar

EOF;
        $expected = array(
            'foo' => "\n\nbar"
        );

        $this->assertSame($expected, $this->parser->parse($yaml));
    }

    public function testObjectSupportEnabled()
    {
        $input = <<<EOF
foo: !!php/object:O:30:"Symfony\Component\Yaml\Tests\B":1:{s:1:"b";s:3:"foo";}
bar: 1
EOF;
        $this->assertEquals(array('foo' => new B(), 'bar' => 1), $this->parser->parse($input, false, true), '->parse() is able to parse objects');
    }

    public function testObjectSupportDisabledButNoExceptions()
    {
        $input = <<<EOF
foo: !!php/object:O:30:"Symfony\Tests\Component\Yaml\B":1:{s:1:"b";s:3:"foo";}
bar: 1
EOF;

        $this->assertEquals(array('foo' => null, 'bar' => 1), $this->parser->parse($input), '->parse() does not parse objects');
    }

    /**
     * @expectedException \Symfony\Component\Yaml\Exception\ParseException
     */
    public function testObjectsSupportDisabledWithExceptions()
    {
        $this->parser->parse('foo: !!php/object:O:30:"Symfony\Tests\Component\Yaml\B":1:{s:1:"b";s:3:"foo";}', true, false);
    }

    public function testNonUtf8Exception()
    {
        if (!function_exists('mb_detect_encoding') || !function_exists('iconv')) {
            $this->markTestSkipped('Exceptions for non-utf8 charsets require the mb_detect_encoding() and iconv() functions.');

            return;
        }

        $yamls = array(
            iconv("UTF-8", "ISO-8859-1", "foo: 'äöüß'"),
            iconv("UTF-8", "ISO-8859-15", "euro: '€'"),
            iconv("UTF-8", "CP1252", "cp1252: '©ÉÇáñ'")
        );

        foreach ($yamls as $yaml) {
            try {
                $this->parser->parse($yaml);

                $this->fail('charsets other than UTF-8 are rejected.');
            } catch (\Exception $e) {
                 $this->assertInstanceOf('Symfony\Component\Yaml\Exception\ParseException', $e, 'charsets other than UTF-8 are rejected.');
            }
        }
    }

    /**
     *
     * @expectedException \Symfony\Component\Yaml\Exception\ParseException
     *
     */
    public function testUnindentedCollectionException()
    {
        $yaml = <<<EOF

collection:
-item1
-item2
-item3

EOF;

        $this->parser->parse($yaml);
    }

    /**
     * @expectedException \Symfony\Component\Yaml\Exception\ParseException
     */
    public function testSequenceInAMapping()
    {
        Yaml::parse(<<<EOF
yaml:
  hash: me
  - array stuff
EOF
        );
    }

    /**
     * @expectedException \Symfony\Component\Yaml\Exception\ParseException
     */
    public function testMappingInASequence()
    {
        Yaml::parse(<<<EOF
yaml:
  - array stuff
  hash: me
EOF
        );
    }

    public function testEmptyValue()
    {
        $input = <<<EOF
hash:
EOF;

        $this->assertEquals(array('hash' => null), Yaml::parse($input));
    }

    public function testStringBlockWithComments()
    {
        $this->assertEquals(array('content' => <<<EOT
# comment 1
header

    # comment 2
    <body>
        <h1>title</h1>
    </body>

footer # comment3
EOT
        ), Yaml::parse(<<<EOF
content: |
    # comment 1
    header

        # comment 2
        <body>
            <h1>title</h1>
        </body>

    footer # comment3
EOF
        ));
    }

    public function testFoldedStringBlockWithComments()
    {
        $this->assertEquals(array(array('content' => <<<EOT
# comment 1
header

    # comment 2
    <body>
        <h1>title</h1>
    </body>

footer # comment3
EOT
        )), Yaml::parse(<<<EOF
-
    content: |
        # comment 1
        header

            # comment 2
            <body>
                <h1>title</h1>
            </body>

        footer # comment3
EOF
        ));
    }

    public function testNestedFoldedStringBlockWithComments()
    {
        $this->assertEquals(array(array(
            'title'   => 'some title',
            'content' => <<<EOT
# comment 1
header

    # comment 2
    <body>
        <h1>title</h1>
    </body>

footer # comment3
EOT
        )), Yaml::parse(<<<EOF
-
    title: some title
    content: |
        # comment 1
        header

            # comment 2
            <body>
                <h1>title</h1>
            </body>

        footer # comment3
EOF
        ));
    }
}

class B
{
    public $b = 'foo';
}
PK��Z=a�o[%[%5test/Yaml/Symfony/Component/Yaml/Tests/InlineTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Yaml\Tests;

use Symfony\Component\Yaml\Inline;

class InlineTest extends \PHPUnit_Framework_TestCase
{
    public function testParse()
    {
        foreach ($this->getTestsForParse() as $yaml => $value) {
            $this->assertSame($value, Inline::parse($yaml), sprintf('::parse() converts an inline YAML to a PHP structure (%s)', $yaml));
        }
    }

    public function testDump()
    {
        $testsForDump = $this->getTestsForDump();

        foreach ($testsForDump as $yaml => $value) {
            $this->assertEquals($yaml, Inline::dump($value), sprintf('::dump() converts a PHP structure to an inline YAML (%s)', $yaml));
        }

        foreach ($this->getTestsForParse() as $value) {
            $this->assertEquals($value, Inline::parse(Inline::dump($value)), 'check consistency');
        }

        foreach ($testsForDump as $value) {
            $this->assertEquals($value, Inline::parse(Inline::dump($value)), 'check consistency');
        }
    }

    public function testDumpNumericValueWithLocale()
    {
        $locale = setlocale(LC_NUMERIC, 0);
        if (false === $locale) {
            $this->markTestSkipped('Your platform does not support locales.');
        }

        $required_locales = array('fr_FR.UTF-8', 'fr_FR.UTF8', 'fr_FR.utf-8', 'fr_FR.utf8', 'French_France.1252');
        if (false === setlocale(LC_ALL, $required_locales)) {
            $this->markTestSkipped('Could not set any of required locales: '.implode(", ", $required_locales));
        }

        $this->assertEquals('1.2', Inline::dump(1.2));
        $this->assertContains('fr', strtolower(setlocale(LC_NUMERIC, 0)));

        setlocale(LC_ALL, $locale);
    }

    public function testHashStringsResemblingExponentialNumericsShouldNotBeChangedToINF()
    {
        $value = '686e444';

        $this->assertSame($value, Inline::parse(Inline::dump($value)));
    }

    /**
     * @expectedException \Symfony\Component\Yaml\Exception\ParseException
     */
    public function testParseScalarWithIncorrectlyQuotedStringShouldThrowException()
    {
        $value = "'don't do somthin' like that'";
        Inline::parse($value);
    }

    /**
     * @expectedException \Symfony\Component\Yaml\Exception\ParseException
     */
    public function testParseScalarWithIncorrectlyDoubleQuotedStringShouldThrowException()
    {
        $value = '"don"t do somthin" like that"';
        Inline::parse($value);
    }

    /**
     * @expectedException \Symfony\Component\Yaml\Exception\ParseException
     */
    public function testParseInvalidMappingKeyShouldThrowException()
    {
        $value = '{ "foo " bar": "bar" }';
        Inline::parse($value);
    }

    /**
     * @expectedException \Symfony\Component\Yaml\Exception\ParseException
     */
    public function testParseInvalidMappingShouldThrowException()
    {
        Inline::parse('[foo] bar');
    }

    /**
     * @expectedException \Symfony\Component\Yaml\Exception\ParseException
     */
    public function testParseInvalidSequenceShouldThrowException()
    {
        Inline::parse('{ foo: bar } bar');
    }

    public function testParseScalarWithCorrectlyQuotedStringShouldReturnString()
    {
        $value = "'don''t do somthin'' like that'";
        $expect = "don't do somthin' like that";

        $this->assertSame($expect, Inline::parseScalar($value));
    }

    protected function getTestsForParse()
    {
        return array(
            '' => '',
            'null' => null,
            'false' => false,
            'true' => true,
            '12' => 12,
            '-12' => -12,
            '"quoted string"' => 'quoted string',
            "'quoted string'" => 'quoted string',
            '12.30e+02' => 12.30e+02,
            '0x4D2' => 0x4D2,
            '02333' => 02333,
            '.Inf' => -log(0),
            '-.Inf' => log(0),
            "'686e444'" => '686e444',
            '686e444' => 646e444,
            '123456789123456789123456789123456789' => '123456789123456789123456789123456789',
            '"foo\r\nbar"' => "foo\r\nbar",
            "'foo#bar'" => 'foo#bar',
            "'foo # bar'" => 'foo # bar',
            "'#cfcfcf'" => '#cfcfcf',
            '::form_base.html.twig' => '::form_base.html.twig',

            '2007-10-30' => mktime(0, 0, 0, 10, 30, 2007),
            '2007-10-30T02:59:43Z' => gmmktime(2, 59, 43, 10, 30, 2007),
            '2007-10-30 02:59:43 Z' => gmmktime(2, 59, 43, 10, 30, 2007),
            '1960-10-30 02:59:43 Z' => gmmktime(2, 59, 43, 10, 30, 1960),
            '1730-10-30T02:59:43Z' => gmmktime(2, 59, 43, 10, 30, 1730),

            '"a \\"string\\" with \'quoted strings inside\'"' => 'a "string" with \'quoted strings inside\'',
            "'a \"string\" with ''quoted strings inside'''" => 'a "string" with \'quoted strings inside\'',

            // sequences
            // urls are no key value mapping. see #3609. Valid yaml "key: value" mappings require a space after the colon
            '[foo, http://urls.are/no/mappings, false, null, 12]' => array('foo', 'http://urls.are/no/mappings', false, null, 12),
            '[  foo  ,   bar , false  ,  null     ,  12  ]' => array('foo', 'bar', false, null, 12),
            '[\'foo,bar\', \'foo bar\']' => array('foo,bar', 'foo bar'),

            // mappings
            '{foo:bar,bar:foo,false:false,null:null,integer:12}' => array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12),
            '{ foo  : bar, bar : foo,  false  :   false,  null  :   null,  integer :  12  }' => array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12),
            '{foo: \'bar\', bar: \'foo: bar\'}' => array('foo' => 'bar', 'bar' => 'foo: bar'),
            '{\'foo\': \'bar\', "bar": \'foo: bar\'}' => array('foo' => 'bar', 'bar' => 'foo: bar'),
            '{\'foo\'\'\': \'bar\', "bar\"": \'foo: bar\'}' => array('foo\'' => 'bar', "bar\"" => 'foo: bar'),
            '{\'foo: \': \'bar\', "bar: ": \'foo: bar\'}' => array('foo: ' => 'bar', "bar: " => 'foo: bar'),

            // nested sequences and mappings
            '[foo, [bar, foo]]' => array('foo', array('bar', 'foo')),
            '[foo, {bar: foo}]' => array('foo', array('bar' => 'foo')),
            '{ foo: {bar: foo} }' => array('foo' => array('bar' => 'foo')),
            '{ foo: [bar, foo] }' => array('foo' => array('bar', 'foo')),

            '[  foo, [  bar, foo  ]  ]' => array('foo', array('bar', 'foo')),

            '[{ foo: {bar: foo} }]' => array(array('foo' => array('bar' => 'foo'))),

            '[foo, [bar, [foo, [bar, foo]], foo]]' => array('foo', array('bar', array('foo', array('bar', 'foo')), 'foo')),

            '[foo, {bar: foo, foo: [foo, {bar: foo}]}, [foo, {bar: foo}]]' => array('foo', array('bar' => 'foo', 'foo' => array('foo', array('bar' => 'foo'))), array('foo', array('bar' => 'foo'))),

            '[foo, bar: { foo: bar }]' => array('foo', '1' => array('bar' => array('foo' => 'bar'))),
            '[foo, \'@foo.baz\', { \'%foo%\': \'foo is %foo%\', bar: \'%foo%\' }, true, \'@service_container\']' => array('foo', '@foo.baz', array('%foo%' => 'foo is %foo%', 'bar' => '%foo%',), true, '@service_container',),
        );
    }

    protected function getTestsForDump()
    {
        return array(
            'null' => null,
            'false' => false,
            'true' => true,
            '12' => 12,
            "'quoted string'" => 'quoted string',
            '12.30e+02' => 12.30e+02,
            '1234' => 0x4D2,
            '1243' => 02333,
            '.Inf' => -log(0),
            '-.Inf' => log(0),
            "'686e444'" => '686e444',
            '"foo\r\nbar"' => "foo\r\nbar",
            "'foo#bar'" => 'foo#bar',
            "'foo # bar'" => 'foo # bar',
            "'#cfcfcf'" => '#cfcfcf',

            "'a \"string\" with ''quoted strings inside'''" => 'a "string" with \'quoted strings inside\'',

            "'-dash'" => '-dash',
            "'-'" => '-',

            // sequences
            '[foo, bar, false, null, 12]' => array('foo', 'bar', false, null, 12),
            '[\'foo,bar\', \'foo bar\']' => array('foo,bar', 'foo bar'),

            // mappings
            '{ foo: bar, bar: foo, \'false\': false, \'null\': null, integer: 12 }' => array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12),
            '{ foo: bar, bar: \'foo: bar\' }' => array('foo' => 'bar', 'bar' => 'foo: bar'),

            // nested sequences and mappings
            '[foo, [bar, foo]]' => array('foo', array('bar', 'foo')),

            '[foo, [bar, [foo, [bar, foo]], foo]]' => array('foo', array('bar', array('foo', array('bar', 'foo')), 'foo')),

            '{ foo: { bar: foo } }' => array('foo' => array('bar' => 'foo')),

            '[foo, { bar: foo }]' => array('foo', array('bar' => 'foo')),

            '[foo, { bar: foo, foo: [foo, { bar: foo }] }, [foo, { bar: foo }]]' => array('foo', array('bar' => 'foo', 'foo' => array('foo', array('bar' => 'foo'))), array('foo', array('bar' => 'foo'))),

            '[foo, \'@foo.baz\', { \'%foo%\': \'foo is %foo%\', bar: \'%foo%\' }, true, \'@service_container\']' => array('foo', '@foo.baz', array('%foo%' => 'foo is %foo%', 'bar' => '%foo%',), true, '@service_container',),
        );
    }
}
PK��Z`�@ee3test/Yaml/Symfony/Component/Yaml/Tests/YamlTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Yaml\Tests;

use Symfony\Component\Yaml\Yaml;

class YamlTest extends \PHPUnit_Framework_TestCase
{
    public function testParseAndDump()
    {
        $data = array('lorem' => 'ipsum', 'dolor' => 'sit');
        $yml = Yaml::dump($data);
        $parsed = Yaml::parse($yml);
        $this->assertEquals($data, $parsed);

        $filename = __DIR__.'/Fixtures/index.yml';
        $contents = file_get_contents($filename);
        $parsedByFilename = Yaml::parse($filename);
        $parsedByContents = Yaml::parse($contents);
        $this->assertEquals($parsedByFilename, $parsedByContents);
    }
}
PK��Z��?o��=test/Yaml/Symfony/Component/Yaml/Tests/ParseExceptionTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Yaml\Tests;

use Symfony\Component\Yaml\Exception\ParseException;
use Symfony\Component\Yaml\Yaml;

class ParseExceptionTest extends \PHPUnit_Framework_TestCase
{
    public function testGetMessage()
    {
        $exception = new ParseException('Error message', 42, 'foo: bar', '/var/www/app/config.yml');
        if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
            $message = 'Error message in "/var/www/app/config.yml" at line 42 (near "foo: bar")';
        } else {
            $message = 'Error message in "\\/var\\/www\\/app\\/config.yml" at line 42 (near "foo: bar")';
        }

        $this->assertEquals($message, $exception->getMessage());
    }
}
PK��Z�>[331test/Yaml/Symfony/Component/Yaml/phpunit.xml.distnu�[���<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony Yaml Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./vendor</directory>
                <directory>./Tests</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
PK��Z����)test/Console_Getopt/tests/001-getopt.phptnu�[���--TEST--
Console_Getopt
--FILE--
<?php
require_once 'Console/Getopt.php';
PEAR::setErrorHandling(PEAR_ERROR_PRINT, "%s\n\n");

function test($argstr, $optstr) {
    $argv = preg_split('/[[:space:]]+/', $argstr);
    if (PEAR::isError($options = Console_Getopt::getopt($argv, $optstr))) {
        return;
    }
    $opts = $options[0];
    $non_opts = $options[1];
    $i = 0;
    print "options: ";
    foreach ($opts as $o => $d) {
        if ($i++ > 0) {
            print ", ";
        }
        print $d[0] . '=' . $d[1];
    }
    print "\n";
    print "params: " . implode(", ", $non_opts) . "\n";
    print "\n";
}

test("-abc", "abc");
test("-abc foo", "abc");
test("-abc foo", "abc:");
test("-abc foo bar gazonk", "abc");
test("-abc foo bar gazonk", "abc:");
test("-a -b -c", "abc");
test("-a -b -c", "abc:");
test("-abc", "ab:c");
test("-abc foo -bar gazonk", "abc");
?>
--EXPECT--
options: a=, b=, c=
params: 

options: a=, b=, c=
params: foo

options: a=, b=, c=foo
params: 

options: a=, b=, c=
params: foo, bar, gazonk

options: a=, b=, c=foo
params: bar, gazonk

options: a=, b=, c=
params: 

Console_Getopt: option requires an argument --c

options: a=, b=c
params: 

options: a=, b=, c=
params: foo, -bar, gazonk
PK��Z��'test/Console_Getopt/tests/bug11068.phptnu�[���--TEST--
Console_Getopt [bug 11068]
--SKIPIF--
--FILE--
<?php
$_SERVER['argv'] =
$argv = array('hi', '-fjjohnston@mail.com', '--to', 'hi', '-');
require_once 'Console/Getopt.php';
$ret = Console_Getopt::getopt(Console_Getopt::readPHPArgv(), 'f:t:',
array('from=','to=','mailpack=','direction=','verbose','debug'));
if(PEAR::isError($ret))
{
	echo $ret->getMessage()."\n";
	echo 'FATAL';
	exit;
}

print_r($ret);
?>
--EXPECT--
Array
(
    [0] => Array
        (
            [0] => Array
                (
                    [0] => f
                    [1] => jjohnston@mail.com
                )

            [1] => Array
                (
                    [0] => --to
                    [1] => hi
                )

        )

    [1] => Array
        (
            [0] => -
        )

)PK��Z���'test/Console_Getopt/tests/bug10557.phptnu�[���--TEST--
Console_Getopt [bug 10557]
--SKIPIF--
--FILE--
<?php
$_SERVER['argv'] =
$argv = array('hi', '-fjjohnston@mail.com', '--to', '--mailpack', '--debug');
require_once 'Console/Getopt.php';
$ret = Console_Getopt::getopt(Console_Getopt::readPHPArgv(), 'f:t:',
array('from=','to=','mailpack=','direction=','verbose','debug'));
if(PEAR::isError($ret))
{
	echo $ret->getMessage()."\n";
	echo 'FATAL';
	exit;
}

print_r($ret);
?>
--EXPECT--
Console_Getopt: option requires an argument --to
FATALPK��Z��|EE'test/Console_Getopt/tests/bug13140.phptnu�[���--TEST--
Console_Getopt [bug 13140]
--SKIPIF--
--FILE--
<?php
$_SERVER['argv'] = $argv =
    array('--bob', '--foo' , '-bar', '--test', '-rq', 'thisshouldbehere');

require_once 'Console/Getopt.php';
$cg = new Console_GetOpt();

print_r($cg->getopt2($cg->readPHPArgv(), 't', array('test'), true));
print_r($cg->getopt2($cg->readPHPArgv(), 'bar', array('foo'), true));
?>
--EXPECT--
Array
(
    [0] => Array
        (
            [0] => Array
                (
                    [0] => --test
                    [1] => 
                )

        )

    [1] => Array
        (
            [0] => thisshouldbehere
        )

)
Array
(
    [0] => Array
        (
            [0] => Array
                (
                    [0] => --foo
                    [1] => 
                )

            [1] => Array
                (
                    [0] => b
                    [1] => 
                )

            [2] => Array
                (
                    [0] => a
                    [1] => 
                )

            [3] => Array
                (
                    [0] => r
                    [1] => 
                )

            [4] => Array
                (
                    [0] => r
                    [1] => 
                )

        )

    [1] => Array
        (
            [0] => thisshouldbehere
        )

)
PK��Z��mg�
�
Jtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests;

use Symfony\Component\HttpFoundation\IpUtils;

class IpUtilsTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider testIpv4Provider
     */
    public function testIpv4($matches, $remoteAddr, $cidr)
    {
        $this->assertSame($matches, IpUtils::checkIp($remoteAddr, $cidr));
    }

    public function testIpv4Provider()
    {
        return array(
            array(true, '192.168.1.1', '192.168.1.1'),
            array(true, '192.168.1.1', '192.168.1.1/1'),
            array(true, '192.168.1.1', '192.168.1.0/24'),
            array(false, '192.168.1.1', '1.2.3.4/1'),
            array(false, '192.168.1.1', '192.168.1/33'),
            array(true, '192.168.1.1', array('1.2.3.4/1', '192.168.1.0/24')),
            array(true, '192.168.1.1', array('192.168.1.0/24', '1.2.3.4/1')),
            array(false, '192.168.1.1', array('1.2.3.4/1', '4.3.2.1/1')),
        );
    }

    /**
     * @dataProvider testIpv6Provider
     */
    public function testIpv6($matches, $remoteAddr, $cidr)
    {
        if (!defined('AF_INET6')) {
            $this->markTestSkipped('Only works when PHP is compiled without the option "disable-ipv6".');
        }

        $this->assertSame($matches, IpUtils::checkIp($remoteAddr, $cidr));
    }

    public function testIpv6Provider()
    {
        return array(
            array(true, '2a01:198:603:0:396e:4789:8e99:890f', '2a01:198:603:0::/65'),
            array(false, '2a00:198:603:0:396e:4789:8e99:890f', '2a01:198:603:0::/65'),
            array(false, '2a01:198:603:0:396e:4789:8e99:890f', '::1'),
            array(true, '0:0:0:0:0:0:0:1', '::1'),
            array(false, '0:0:603:0:396e:4789:8e99:0001', '::1'),
            array(true, '2a01:198:603:0:396e:4789:8e99:890f', array('::1', '2a01:198:603:0::/65')),
            array(true, '2a01:198:603:0:396e:4789:8e99:890f', array('2a01:198:603:0::/65', '::1')),
            array(false, '2a01:198:603:0:396e:4789:8e99:890f', array('::1', '1a01:198:603:0::/65')),
        );
    }

    /**
     * @expectedException \RuntimeException
     */
    public function testAnIpv6WithOptionDisabledIpv6()
    {
        if (!extension_loaded('sockets')) {
            $this->markTestSkipped('Only works when the socket extension is enabled');
        }

        if (defined('AF_INET6')) {
            $this->markTestSkipped('Only works when PHP is compiled with the option "disable-ipv6".');
        }

        IpUtils::checkIp('2a01:198:603:0:396e:4789:8e99:890f', '2a01:198:603:0::/65');
    }
}
PK��Z��Otest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/RequestStackTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;

class RequestStackTest extends \PHPUnit_Framework_TestCase
{
    public function testGetCurrentRequest()
    {
        $requestStack = new RequestStack();
        $this->assertNull($requestStack->getCurrentRequest());

        $request = Request::create('/foo');

        $requestStack->push($request);
        $this->assertSame($request, $requestStack->getCurrentRequest());

        $this->assertSame($request, $requestStack->pop());
        $this->assertNull($requestStack->getCurrentRequest());

        $this->assertNull($requestStack->pop());
    }

    public function testGetMasterRequest()
    {
        $requestStack = new RequestStack();
        $this->assertNull($requestStack->getMasterRequest());

        $masterRequest = Request::create('/foo');
        $subRequest = Request::create('/bar');

        $requestStack->push($masterRequest);
        $requestStack->push($subRequest);

        $this->assertSame($masterRequest, $requestStack->getMasterRequest());
    }

    public function testGetParentRequest()
    {
        $requestStack = new RequestStack();
        $this->assertNull($requestStack->getParentRequest());

        $masterRequest = Request::create('/foo');

        $requestStack->push($masterRequest);
        $this->assertNull($requestStack->getParentRequest());

        $firstSubRequest = Request::create('/bar');

        $requestStack->push($firstSubRequest);
        $this->assertSame($masterRequest, $requestStack->getParentRequest());

        $secondSubRequest = Request::create('/baz');

        $requestStack->push($secondSubRequest);
        $this->assertSame($firstSubRequest, $requestStack->getParentRequest());
    }
}
PK��Z��lOD
D
Otest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ResponseTestCase.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests;

use Symfony\Component\HttpFoundation\Request;

abstract class ResponseTestCase extends \PHPUnit_Framework_TestCase
{
    public function testNoCacheControlHeaderOnAttachmentUsingHTTPSAndMSIE()
    {
        // Check for HTTPS and IE 8
        $request = new Request();
        $request->server->set('HTTPS', true);
        $request->server->set('HTTP_USER_AGENT', 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)');

        $response = $this->provideResponse();
        $response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"');
        $response->prepare($request);

        $this->assertFalse($response->headers->has('Cache-Control'));

        // Check for IE 10 and HTTPS
        $request->server->set('HTTP_USER_AGENT', 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)');

        $response = $this->provideResponse();
        $response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"');
        $response->prepare($request);

        $this->assertTrue($response->headers->has('Cache-Control'));

        // Check for IE 9 and HTTPS
        $request->server->set('HTTP_USER_AGENT', 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 7.1; Trident/5.0)');

        $response = $this->provideResponse();
        $response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"');
        $response->prepare($request);

        $this->assertTrue($response->headers->has('Cache-Control'));

        // Check for IE 9 and HTTP
        $request->server->set('HTTPS', false);

        $response = $this->provideResponse();
        $response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"');
        $response->prepare($request);

        $this->assertTrue($response->headers->has('Cache-Control'));

        // Check for IE 8 and HTTP
        $request->server->set('HTTP_USER_AGENT', 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)');

        $response = $this->provideResponse();
        $response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"');
        $response->prepare($request);

        $this->assertTrue($response->headers->has('Cache-Control'));

        // Check for non-IE and HTTPS
        $request->server->set('HTTPS', true);
        $request->server->set('HTTP_USER_AGENT', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.60 Safari/537.17');

        $response = $this->provideResponse();
        $response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"');
        $response->prepare($request);

        $this->assertTrue($response->headers->has('Cache-Control'));

        // Check for non-IE and HTTP
        $request->server->set('HTTPS', false);

        $response = $this->provideResponse();
        $response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"');
        $response->prepare($request);

        $this->assertTrue($response->headers->has('Cache-Control'));
    }

    abstract protected function provideResponse();
}
PK��Z�F�9bbItest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/CookieTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests;

use Symfony\Component\HttpFoundation\Cookie;

/**
 * CookieTest
 *
 * @author John Kary <john@johnkary.net>
 * @author Hugo Hamon <hugo.hamon@sensio.com>
 */
class CookieTest extends \PHPUnit_Framework_TestCase
{
    public function invalidNames()
    {
        return array(
            array(''),
            array(",MyName"),
            array(";MyName"),
            array(" MyName"),
            array("\tMyName"),
            array("\rMyName"),
            array("\nMyName"),
            array("\013MyName"),
            array("\014MyName"),
        );
    }

    /**
     * @dataProvider invalidNames
     * @expectedException \InvalidArgumentException
     * @covers Symfony\Component\HttpFoundation\Cookie::__construct
     */
    public function testInstantiationThrowsExceptionIfCookieNameContainsInvalidCharacters($name)
    {
        new Cookie($name);
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testInvalidExpiration()
    {
        $cookie = new Cookie('MyCookie', 'foo', 'bar');
    }

    /**
     * @covers Symfony\Component\HttpFoundation\Cookie::getValue
     */
    public function testGetValue()
    {
        $value = 'MyValue';
        $cookie = new Cookie('MyCookie', $value);

        $this->assertSame($value, $cookie->getValue(), '->getValue() returns the proper value');
    }

    public function testGetPath()
    {
        $cookie = new Cookie('foo', 'bar');

        $this->assertSame('/', $cookie->getPath(), '->getPath() returns / as the default path');
    }

    public function testGetExpiresTime()
    {
        $cookie = new Cookie('foo', 'bar', 3600);

        $this->assertEquals(3600, $cookie->getExpiresTime(), '->getExpiresTime() returns the expire date');
    }

    public function testConstructorWithDateTime()
    {
        $expire = new \DateTime();
        $cookie = new Cookie('foo', 'bar', $expire);

        $this->assertEquals($expire->format('U'), $cookie->getExpiresTime(), '->getExpiresTime() returns the expire date');
    }

    public function testGetExpiresTimeWithStringValue()
    {
        $value = "+1 day";
        $cookie = new Cookie('foo', 'bar', $value);
        $expire = strtotime($value);

        $this->assertEquals($expire, $cookie->getExpiresTime(), '->getExpiresTime() returns the expire date');
    }

    public function testGetDomain()
    {
        $cookie = new Cookie('foo', 'bar', 3600, '/', '.myfoodomain.com');

        $this->assertEquals('.myfoodomain.com', $cookie->getDomain(), '->getDomain() returns the domain name on which the cookie is valid');
    }

    public function testIsSecure()
    {
        $cookie = new Cookie('foo', 'bar', 3600, '/', '.myfoodomain.com', true);

        $this->assertTrue($cookie->isSecure(), '->isSecure() returns whether the cookie is transmitted over HTTPS');
    }

    public function testIsHttpOnly()
    {
        $cookie = new Cookie('foo', 'bar', 3600, '/', '.myfoodomain.com', false, true);

        $this->assertTrue($cookie->isHttpOnly(), '->isHttpOnly() returns whether the cookie is only transmitted over HTTP');
    }

    public function testCookieIsNotCleared()
    {
        $cookie = new Cookie('foo', 'bar', time()+3600*24);

        $this->assertFalse($cookie->isCleared(), '->isCleared() returns false if the cookie did not expire yet');
    }

    public function testCookieIsCleared()
    {
        $cookie = new Cookie('foo', 'bar', time()-20);

        $this->assertTrue($cookie->isCleared(), '->isCleared() returns true if the cookie has expired');
    }

    public function testToString()
    {
        $cookie = new Cookie('foo', 'bar', strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true);
        $this->assertEquals('foo=bar; expires=Fri, 20-May-2011 15:25:52 GMT; path=/; domain=.myfoodomain.com; secure; httponly', $cookie->__toString(), '->__toString() returns string representation of the cookie');

        $cookie = new Cookie('foo', null, 1, '/admin/', '.myfoodomain.com');
        $this->assertEquals('foo=deleted; expires='.gmdate("D, d-M-Y H:i:s T", time()-31536001).'; path=/admin/; domain=.myfoodomain.com; httponly', $cookie->__toString(), '->__toString() returns string representation of a cleared cookie if value is NULL');

        $cookie = new Cookie('foo', 'bar', 0, '/', '');
        $this->assertEquals('foo=bar; path=/; httponly', $cookie->__toString());
    }
}
PK��Z�q�H��Stest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/RedirectResponseTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests;

use Symfony\Component\HttpFoundation\RedirectResponse;

class RedirectResponseTest extends \PHPUnit_Framework_TestCase
{
    public function testGenerateMetaRedirect()
    {
        $response = new RedirectResponse('foo.bar');

        $this->assertEquals(1, preg_match(
            '#<meta http-equiv="refresh" content="\d+;url=foo\.bar" />#',
            preg_replace(array('/\s+/', '/\'/'), array(' ', '"'), $response->getContent())
        ));
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testRedirectResponseConstructorNullUrl()
    {
        $response = new RedirectResponse(null);
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testRedirectResponseConstructorWrongStatusCode()
    {
        $response = new RedirectResponse('foo.bar', 404);
    }

    public function testGenerateLocationHeader()
    {
        $response = new RedirectResponse('foo.bar');

        $this->assertTrue($response->headers->has('Location'));
        $this->assertEquals('foo.bar', $response->headers->get('Location'));
    }

    public function testGetTargetUrl()
    {
        $response = new RedirectResponse('foo.bar');

        $this->assertEquals('foo.bar', $response->getTargetUrl());
    }

    public function testSetTargetUrl()
    {
        $response = new RedirectResponse('foo.bar');
        $response->setTargetUrl('baz.beep');

        $this->assertEquals('baz.beep', $response->getTargetUrl());
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testSetTargetUrlNull()
    {
        $response = new RedirectResponse('foo.bar');
        $response->setTargetUrl(null);
    }

    public function testCreate()
    {
        $response = RedirectResponse::create('foo', 301);

        $this->assertInstanceOf('Symfony\Component\HttpFoundation\RedirectResponse', $response);
        $this->assertEquals(301, $response->getStatusCode());
    }
}
PK��Zqr��



[test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ExpressionRequestMatcherTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests;

use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use Symfony\Component\HttpFoundation\ExpressionRequestMatcher;
use Symfony\Component\HttpFoundation\Request;

class ExpressionRequestMatcherTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \LogicException
     */
    public function testWhenNoExpressionIsSet()
    {
        $expressionRequestMatcher = new ExpressionRequestMatcher();
        $expressionRequestMatcher->matches(new Request());
    }

    /**
     * @dataProvider provideExpressions
     */
    public function testMatchesWhenParentMatchesIsTrue($expression, $expected)
    {
        $request = Request::create('/foo');
        $expressionRequestMatcher = new ExpressionRequestMatcher();

        $expressionRequestMatcher->setExpression(new ExpressionLanguage(), $expression);
        $this->assertSame($expected, $expressionRequestMatcher->matches($request));
    }

    /**
     * @dataProvider provideExpressions
     */
    public function testMatchesWhenParentMatchesIsFalse($expression)
    {
        $request = Request::create('/foo');
        $request->attributes->set('foo', 'foo');
        $expressionRequestMatcher = new ExpressionRequestMatcher();
        $expressionRequestMatcher->matchAttribute('foo', 'bar');

        $expressionRequestMatcher->setExpression(new ExpressionLanguage(), $expression);
        $this->assertFalse($expressionRequestMatcher->matches($request));
    }

    public function provideExpressions()
    {
        return array(
            array('request.getMethod() == method', true),
            array('request.getPathInfo() == path', true),
            array('request.getHost() == host', true),
            array('request.getClientIp() == ip', true),
            array('request.attributes.all() == attributes', true),
            array('request.getMethod() == method && request.getPathInfo() == path && request.getHost() == host && request.getClientIp() == ip &&  request.attributes.all() == attributes', true),
            array('request.getMethod() != method', false),
            array('request.getMethod() != method && request.getPathInfo() == path && request.getHost() == host && request.getClientIp() == ip &&  request.attributes.all() == attributes', false),
        );
    }
}
PK��Z_�|���Utest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/BinaryFileResponseTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests;

use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;

class BinaryFileResponseTest extends ResponseTestCase
{
    public function testConstruction()
    {
        $response = new BinaryFileResponse('README.md', 404, array('X-Header' => 'Foo'), true, null, true, true);
        $this->assertEquals(404, $response->getStatusCode());
        $this->assertEquals('Foo', $response->headers->get('X-Header'));
        $this->assertTrue($response->headers->has('ETag'));
        $this->assertTrue($response->headers->has('Last-Modified'));
        $this->assertFalse($response->headers->has('Content-Disposition'));

        $response = BinaryFileResponse::create('README.md', 404, array(), true, ResponseHeaderBag::DISPOSITION_INLINE);
        $this->assertEquals(404, $response->getStatusCode());
        $this->assertFalse($response->headers->has('ETag'));
        $this->assertEquals('inline; filename="README.md"', $response->headers->get('Content-Disposition'));
    }

    /**
     * @expectedException \LogicException
     */
    public function testSetContent()
    {
        $response = new BinaryFileResponse('README.md');
        $response->setContent('foo');
    }

    public function testGetContent()
    {
        $response = new BinaryFileResponse('README.md');
        $this->assertFalse($response->getContent());
    }

    /**
     * @dataProvider provideRanges
     */
    public function testRequests($requestRange, $offset, $length, $responseRange)
    {
        $response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif')->setAutoEtag();

        // do a request to get the ETag
        $request = Request::create('/');
        $response->prepare($request);
        $etag = $response->headers->get('ETag');

        // prepare a request for a range of the testing file
        $request = Request::create('/');
        $request->headers->set('If-Range', $etag);
        $request->headers->set('Range', $requestRange);

        $file = fopen(__DIR__.'/File/Fixtures/test.gif', 'r');
        fseek($file, $offset);
        $data = fread($file, $length);
        fclose($file);

        $this->expectOutputString($data);
        $response = clone $response;
        $response->prepare($request);
        $response->sendContent();

        $this->assertEquals(206, $response->getStatusCode());
        $this->assertEquals('binary', $response->headers->get('Content-Transfer-Encoding'));
        $this->assertEquals($responseRange, $response->headers->get('Content-Range'));
    }

    public function provideRanges()
    {
        return array(
            array('bytes=1-4', 1, 4, 'bytes 1-4/35'),
            array('bytes=-5', 30, 5, 'bytes 30-34/35'),
            array('bytes=30-', 30, 5, 'bytes 30-34/35'),
            array('bytes=30-30', 30, 1, 'bytes 30-30/35'),
            array('bytes=30-34', 30, 5, 'bytes 30-34/35'),
        );
    }

    /**
     * @dataProvider provideFullFileRanges
     */
    public function testFullFileRequests($requestRange)
    {
        $response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif')->setAutoEtag();

        // prepare a request for a range of the testing file
        $request = Request::create('/');
        $request->headers->set('Range', $requestRange);

        $file = fopen(__DIR__.'/File/Fixtures/test.gif', 'r');
        $data = fread($file, 35);
        fclose($file);

        $this->expectOutputString($data);
        $response = clone $response;
        $response->prepare($request);
        $response->sendContent();

        $this->assertEquals(200, $response->getStatusCode());
        $this->assertEquals('binary', $response->headers->get('Content-Transfer-Encoding'));
    }

    public function provideFullFileRanges()
    {
        return array(
            array('bytes=0-'),
            array('bytes=0-34'),
            array('bytes=-35'),
            // Syntactical invalid range-request should also return the full resource
            array('bytes=20-10'),
            array('bytes=50-40'),
        );
    }

    /**
     * @dataProvider provideInvalidRanges
     */
    public function testInvalidRequests($requestRange)
    {
        $response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif')->setAutoEtag();

        // prepare a request for a range of the testing file
        $request = Request::create('/');
        $request->headers->set('Range', $requestRange);

        $response = clone $response;
        $response->prepare($request);
        $response->sendContent();

        $this->assertEquals(416, $response->getStatusCode());
        $this->assertEquals('binary', $response->headers->get('Content-Transfer-Encoding'));
        #$this->assertEquals('', $response->headers->get('Content-Range'));
    }

    public function provideInvalidRanges()
    {
        return array(
            array('bytes=-40'),
            array('bytes=30-40')
        );
    }

    public function testXSendfile()
    {
        $request = Request::create('/');
        $request->headers->set('X-Sendfile-Type', 'X-Sendfile');

        BinaryFileResponse::trustXSendfileTypeHeader();
        $response = BinaryFileResponse::create('README.md');
        $response->prepare($request);

        $this->expectOutputString('');
        $response->sendContent();

        $this->assertContains('README.md', $response->headers->get('X-Sendfile'));
    }

    /**
     * @dataProvider getSampleXAccelMappings
     */
    public function testXAccelMapping($realpath, $mapping, $virtual)
    {
        $request = Request::create('/');
        $request->headers->set('X-Sendfile-Type', 'X-Accel-Redirect');
        $request->headers->set('X-Accel-Mapping', $mapping);

        $file = $this->getMockBuilder('Symfony\Component\HttpFoundation\File\File')
                     ->disableOriginalConstructor()
                     ->getMock();
        $file->expects($this->any())
             ->method('getRealPath')
             ->will($this->returnValue($realpath));
        $file->expects($this->any())
             ->method('isReadable')
             ->will($this->returnValue(true));

        BinaryFileResponse::trustXSendFileTypeHeader();
        $response = new BinaryFileResponse('README.md');
        $reflection = new \ReflectionObject($response);
        $property = $reflection->getProperty('file');
        $property->setAccessible(true);
        $property->setValue($response, $file);

        $response->prepare($request);
        $this->assertEquals($virtual, $response->headers->get('X-Accel-Redirect'));
    }

    public function getSampleXAccelMappings()
    {
        return array(
            array('/var/www/var/www/files/foo.txt', '/files/=/var/www/', '/files/var/www/files/foo.txt'),
            array('/home/foo/bar.txt', '/files/=/var/www/,/baz/=/home/foo/', '/baz/bar.txt'),
        );
    }

    protected function provideResponse()
    {
        return new BinaryFileResponse('README.md');
    }
}
PK��Z��@LLJtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/FileBagTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests;

use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\FileBag;

/**
 * FileBagTest.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
 */
class FileBagTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \InvalidArgumentException
     */
    public function testFileMustBeAnArrayOrUploadedFile()
    {
        new FileBag(array('file' => 'foo'));
    }

    public function testShouldConvertsUploadedFiles()
    {
        $tmpFile = $this->createTempFile();
        $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0);

        $bag = new FileBag(array('file' => array(
            'name' => basename($tmpFile),
            'type' => 'text/plain',
            'tmp_name' => $tmpFile,
            'error' => 0,
            'size' => 100
        )));

        $this->assertEquals($file, $bag->get('file'));
    }

    public function testShouldSetEmptyUploadedFilesToNull()
    {
        $bag = new FileBag(array('file' => array(
            'name' => '',
            'type' => '',
            'tmp_name' => '',
            'error' => UPLOAD_ERR_NO_FILE,
            'size' => 0
        )));

        $this->assertNull($bag->get('file'));
    }

    public function testShouldConvertUploadedFilesWithPhpBug()
    {
        $tmpFile = $this->createTempFile();
        $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0);

        $bag = new FileBag(array(
            'child' => array(
                'name' => array(
                    'file' => basename($tmpFile),
                ),
                'type' => array(
                    'file' => 'text/plain',
                ),
                'tmp_name' => array(
                    'file' => $tmpFile,
                ),
                'error' => array(
                    'file' => 0,
                ),
                'size' => array(
                    'file' => 100,
                ),
            )
        ));

        $files = $bag->all();
        $this->assertEquals($file, $files['child']['file']);
    }

    public function testShouldConvertNestedUploadedFilesWithPhpBug()
    {
        $tmpFile = $this->createTempFile();
        $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0);

        $bag = new FileBag(array(
            'child' => array(
                'name' => array(
                    'sub' => array('file' => basename($tmpFile))
                ),
                'type' => array(
                    'sub' => array('file' => 'text/plain')
                ),
                'tmp_name' => array(
                    'sub' => array('file' => $tmpFile)
                ),
                'error' => array(
                    'sub' => array('file' => 0)
                ),
                'size' => array(
                    'sub' => array('file' => 100)
                ),
            )
        ));

        $files = $bag->all();
        $this->assertEquals($file, $files['child']['sub']['file']);
    }

    public function testShouldNotConvertNestedUploadedFiles()
    {
        $tmpFile = $this->createTempFile();
        $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0);
        $bag = new FileBag(array('image' => array('file' => $file)));

        $files = $bag->all();
        $this->assertEquals($file, $files['image']['file']);
    }

    protected function createTempFile()
    {
        return tempnam(sys_get_temp_dir().'/form_test', 'FormTest');
    }

    protected function setUp()
    {
        mkdir(sys_get_temp_dir().'/form_test', 0777, true);
    }

    protected function tearDown()
    {
        foreach (glob(sys_get_temp_dir().'/form_test/*') as $file) {
            unlink($file);
        }

        rmdir(sys_get_temp_dir().'/form_test');
    }
}
PK��Z�m��..Ltest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/HeaderBagTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests;

use Symfony\Component\HttpFoundation\HeaderBag;

class HeaderBagTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Symfony\Component\HttpFoundation\HeaderBag::__construct
     */
    public function testConstructor()
    {
        $bag = new HeaderBag(array('foo' => 'bar'));
        $this->assertTrue($bag->has('foo'));
    }

    public function testToStringNull()
    {
        $bag = new HeaderBag();
        $this->assertEquals('', $bag->__toString());
    }

    public function testToStringNotNull()
    {
        $bag = new HeaderBag(array('foo' => 'bar'));
        $this->assertEquals("Foo: bar\r\n", $bag->__toString());
    }

    public function testKeys()
    {
        $bag = new HeaderBag(array('foo' => 'bar'));
        $keys = $bag->keys();
        $this->assertEquals("foo", $keys[0]);
    }

    public function testGetDate()
    {
        $bag = new HeaderBag(array('foo' => 'Tue, 4 Sep 2012 20:00:00 +0200'));
        $headerDate = $bag->getDate('foo');
        $this->assertInstanceOf('DateTime', $headerDate);
    }

    /**
     * @expectedException \RuntimeException
     */
    public function testGetDateException()
    {
        $bag = new HeaderBag(array('foo' => 'Tue'));
        $headerDate = $bag->getDate('foo');
    }

    public function testGetCacheControlHeader()
    {
        $bag = new HeaderBag();
        $bag->addCacheControlDirective('public', '#a');
        $this->assertTrue($bag->hasCacheControlDirective('public'));
        $this->assertEquals('#a', $bag->getCacheControlDirective('public'));
    }

    /**
     * @covers Symfony\Component\HttpFoundation\HeaderBag::all
     */
    public function testAll()
    {
        $bag = new HeaderBag(array('foo' => 'bar'));
        $this->assertEquals(array('foo' => array('bar')), $bag->all(), '->all() gets all the input');

        $bag = new HeaderBag(array('FOO' => 'BAR'));
        $this->assertEquals(array('foo' => array('BAR')), $bag->all(), '->all() gets all the input key are lower case');
    }

    /**
     * @covers Symfony\Component\HttpFoundation\HeaderBag::replace
     */
    public function testReplace()
    {
        $bag = new HeaderBag(array('foo' => 'bar'));

        $bag->replace(array('NOPE' => 'BAR'));
        $this->assertEquals(array('nope' => array('BAR')), $bag->all(), '->replace() replaces the input with the argument');
        $this->assertFalse($bag->has('foo'), '->replace() overrides previously set the input');
    }

    /**
     * @covers Symfony\Component\HttpFoundation\HeaderBag::get
     */
    public function testGet()
    {
        $bag = new HeaderBag(array('foo' => 'bar', 'fuzz' => 'bizz'));
        $this->assertEquals( 'bar', $bag->get('foo'), '->get return current value');
        $this->assertEquals( 'bar', $bag->get('FoO'), '->get key in case insensitive');
        $this->assertEquals( array('bar'), $bag->get('foo', 'nope', false), '->get return the value as array');

        // defaults
        $this->assertNull($bag->get('none'), '->get unknown values returns null');
        $this->assertEquals( 'default', $bag->get('none', 'default'), '->get unknown values returns default');
        $this->assertEquals( array('default'), $bag->get('none', 'default', false), '->get unknown values returns default as array');

        $bag->set('foo', 'bor', false);
        $this->assertEquals( 'bar', $bag->get('foo'), '->get return first value');
        $this->assertEquals( array('bar', 'bor'), $bag->get('foo', 'nope', false), '->get return all values as array');
    }

    public function testSetAssociativeArray()
    {
        $bag = new HeaderBag();
        $bag->set('foo', array('bad-assoc-index' => 'value'));
        $this->assertSame('value', $bag->get('foo'));
        $this->assertEquals(array('value'), $bag->get('foo', 'nope', false), 'assoc indices of multi-valued headers are ignored');
    }

    /**
     * @covers Symfony\Component\HttpFoundation\HeaderBag::contains
     */
    public function testContains()
    {
        $bag = new HeaderBag(array('foo' => 'bar', 'fuzz' => 'bizz'));
        $this->assertTrue(  $bag->contains('foo', 'bar'), '->contains first value');
        $this->assertTrue(  $bag->contains('fuzz', 'bizz'), '->contains second value');
        $this->assertFalse(  $bag->contains('nope', 'nope'), '->contains unknown value');
        $this->assertFalse(  $bag->contains('foo', 'nope'), '->contains unknown value');

        // Multiple values
        $bag->set('foo', 'bor', false);
        $this->assertTrue(  $bag->contains('foo', 'bar'), '->contains first value');
        $this->assertTrue(  $bag->contains('foo', 'bor'), '->contains second value');
        $this->assertFalse(  $bag->contains('foo', 'nope'), '->contains unknown value');
    }

    public function testCacheControlDirectiveAccessors()
    {
        $bag = new HeaderBag();
        $bag->addCacheControlDirective('public');

        $this->assertTrue($bag->hasCacheControlDirective('public'));
        $this->assertTrue($bag->getCacheControlDirective('public'));
        $this->assertEquals('public', $bag->get('cache-control'));

        $bag->addCacheControlDirective('max-age', 10);
        $this->assertTrue($bag->hasCacheControlDirective('max-age'));
        $this->assertEquals(10, $bag->getCacheControlDirective('max-age'));
        $this->assertEquals('max-age=10, public', $bag->get('cache-control'));

        $bag->removeCacheControlDirective('max-age');
        $this->assertFalse($bag->hasCacheControlDirective('max-age'));
    }

    public function testCacheControlDirectiveParsing()
    {
        $bag = new HeaderBag(array('cache-control' => 'public, max-age=10'));
        $this->assertTrue($bag->hasCacheControlDirective('public'));
        $this->assertTrue($bag->getCacheControlDirective('public'));

        $this->assertTrue($bag->hasCacheControlDirective('max-age'));
        $this->assertEquals(10, $bag->getCacheControlDirective('max-age'));

        $bag->addCacheControlDirective('s-maxage', 100);
        $this->assertEquals('max-age=10, public, s-maxage=100', $bag->get('cache-control'));
    }

    public function testCacheControlDirectiveParsingQuotedZero()
    {
        $bag = new HeaderBag(array('cache-control' => 'max-age="0"'));
        $this->assertTrue($bag->hasCacheControlDirective('max-age'));
        $this->assertEquals(0, $bag->getCacheControlDirective('max-age'));
    }

    public function testCacheControlDirectiveOverrideWithReplace()
    {
        $bag = new HeaderBag(array('cache-control' => 'private, max-age=100'));
        $bag->replace(array('cache-control' => 'public, max-age=10'));
        $this->assertTrue($bag->hasCacheControlDirective('public'));
        $this->assertTrue($bag->getCacheControlDirective('public'));

        $this->assertTrue($bag->hasCacheControlDirective('max-age'));
        $this->assertEquals(10, $bag->getCacheControlDirective('max-age'));
    }

    /**
     * @covers Symfony\Component\HttpFoundation\HeaderBag::getIterator
     */
    public function testGetIterator()
    {
        $headers   = array('foo' => 'bar', 'hello' => 'world', 'third' => 'charm');
        $headerBag = new HeaderBag($headers);

        $i = 0;
        foreach ($headerBag as $key => $val) {
            $i++;
            $this->assertEquals(array($headers[$key]), $val);
        }

        $this->assertEquals(count($headers), $i);
    }

    /**
     * @covers Symfony\Component\HttpFoundation\HeaderBag::count
     */
    public function testCount()
    {
        $headers   = array('foo' => 'bar', 'HELLO' => 'WORLD');
        $headerBag = new HeaderBag($headers);

        $this->assertEquals(count($headers), count($headerBag));
    }
}
PK��Z��܏##Qtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/Fixtures/test.gifnu�[���GIF87a�������,D;PK��Z�+�vZtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/Fixtures/.unknownextensionnu�[���fPK��ZYtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/Fixtures/directory/.emptynu�[���PK��Z��܏##Mtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/Fixtures/testnu�[���GIF87a�������,D;PK��Z~rM;;Ytest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/MimeType/MimeTypeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests\File\MimeType;

use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser;
use Symfony\Component\HttpFoundation\File\MimeType\FileBinaryMimeTypeGuesser;
use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException;

class MimeTypeTest extends \PHPUnit_Framework_TestCase
{
    protected $path;

    public function testGuessImageWithoutExtension()
    {
        if (extension_loaded('fileinfo')) {
            $this->assertEquals('image/gif', MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/test'));
        } else {
            $this->assertNull(MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/test'));
        }
    }

    public function testGuessImageWithDirectory()
    {
        $this->setExpectedException('Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException');

        MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/directory');
    }

    public function testGuessImageWithFileBinaryMimeTypeGuesser()
    {
        $guesser = MimeTypeGuesser::getInstance();
        $guesser->register(new FileBinaryMimeTypeGuesser());
        if (extension_loaded('fileinfo')) {
            $this->assertEquals('image/gif', MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/test'));
        } else {
            $this->assertNull(MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/test'));
        }
    }

    public function testGuessImageWithKnownExtension()
    {
        if (extension_loaded('fileinfo')) {
            $this->assertEquals('image/gif', MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/test.gif'));
        } else {
            $this->assertNull(MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/test.gif'));
        }
    }

    public function testGuessFileWithUnknownExtension()
    {
        if (extension_loaded('fileinfo')) {
            $this->assertEquals('application/octet-stream', MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/.unknownextension'));
        } else {
            $this->assertNull(MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/.unknownextension'));
        }
    }

    public function testGuessWithIncorrectPath()
    {
        $this->setExpectedException('Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException');
        MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/not_here');
    }

    public function testGuessWithNonReadablePath()
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->markTestSkipped('Can not verify chmod operations on Windows');
        }

        if (in_array(get_current_user(), array('root'))) {
            $this->markTestSkipped('This test will fail if run under superuser');
        }

        $path = __DIR__.'/../Fixtures/to_delete';
        touch($path);
        @chmod($path, 0333);

        if (get_current_user() != 'root' && substr(sprintf('%o', fileperms($path)), -4) == '0333') {
            $this->setExpectedException('Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException');
            MimeTypeGuesser::getInstance()->guess($path);
        } else {
            $this->markTestSkipped('Can not verify chmod operations, change of file permissions failed');
        }
    }

    public static function tearDownAfterClass()
    {
        $path = __DIR__.'/../Fixtures/to_delete';
        if (file_exists($path)) {
            @chmod($path, 0666);
            @unlink($path);
        }
    }
}
PK��Z��##Ltest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/FileTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests\File;

use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser;

class FileTest extends \PHPUnit_Framework_TestCase
{
    protected $file;

    public function testGetMimeTypeUsesMimeTypeGuessers()
    {
        $file = new File(__DIR__.'/Fixtures/test.gif');
        $guesser = $this->createMockGuesser($file->getPathname(), 'image/gif');

        MimeTypeGuesser::getInstance()->register($guesser);

        $this->assertEquals('image/gif', $file->getMimeType());
    }

    public function testGuessExtensionWithoutGuesser()
    {
        $file = new File(__DIR__.'/Fixtures/directory/.empty');

        $this->assertNull($file->guessExtension());
    }

    public function testGuessExtensionIsBasedOnMimeType()
    {
        $file = new File(__DIR__.'/Fixtures/test');
        $guesser = $this->createMockGuesser($file->getPathname(), 'image/gif');

        MimeTypeGuesser::getInstance()->register($guesser);

        $this->assertEquals('gif', $file->guessExtension());
    }

    public function testConstructWhenFileNotExists()
    {
        $this->setExpectedException('Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException');

        new File(__DIR__.'/Fixtures/not_here');
    }

    public function testMove()
    {
        $path = __DIR__.'/Fixtures/test.copy.gif';
        $targetDir = __DIR__.'/Fixtures/directory';
        $targetPath = $targetDir.'/test.copy.gif';
        @unlink($path);
        @unlink($targetPath);
        copy(__DIR__.'/Fixtures/test.gif', $path);

        $file = new File($path);
        $movedFile = $file->move($targetDir);
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\File\File', $movedFile);

        $this->assertTrue(file_exists($targetPath));
        $this->assertFalse(file_exists($path));
        $this->assertEquals(realpath($targetPath), $movedFile->getRealPath());

        @unlink($targetPath);
    }

    public function testMoveWithNewName()
    {
        $path = __DIR__.'/Fixtures/test.copy.gif';
        $targetDir = __DIR__.'/Fixtures/directory';
        $targetPath = $targetDir.'/test.newname.gif';
        @unlink($path);
        @unlink($targetPath);
        copy(__DIR__.'/Fixtures/test.gif', $path);

        $file = new File($path);
        $movedFile = $file->move($targetDir, 'test.newname.gif');

        $this->assertTrue(file_exists($targetPath));
        $this->assertFalse(file_exists($path));
        $this->assertEquals(realpath($targetPath), $movedFile->getRealPath());

        @unlink($targetPath);
    }

    public function getFilenameFixtures()
    {
        return array(
            array('original.gif', 'original.gif'),
            array('..\\..\\original.gif', 'original.gif'),
            array('../../original.gif', 'original.gif'),
            array('файлfile.gif', 'файлfile.gif'),
            array('..\\..\\файлfile.gif', 'файлfile.gif'),
            array('../../файлfile.gif', 'файлfile.gif'),
        );
    }

    /**
     * @dataProvider getFilenameFixtures
     */
    public function testMoveWithNonLatinName($filename, $sanitizedFilename)
    {
        $path = __DIR__.'/Fixtures/'.$sanitizedFilename;
        $targetDir = __DIR__.'/Fixtures/directory/';
        $targetPath = $targetDir.$sanitizedFilename;
        @unlink($path);
        @unlink($targetPath);
        copy(__DIR__.'/Fixtures/test.gif', $path);

        $file = new File($path);
        $movedFile = $file->move($targetDir,$filename);
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\File\File', $movedFile);

        $this->assertTrue(file_exists($targetPath));
        $this->assertFalse(file_exists($path));
        $this->assertEquals(realpath($targetPath), $movedFile->getRealPath());

        @unlink($targetPath);
    }

    public function testMoveToAnUnexistentDirectory()
    {
        $sourcePath = __DIR__.'/Fixtures/test.copy.gif';
        $targetDir = __DIR__.'/Fixtures/directory/sub';
        $targetPath = $targetDir.'/test.copy.gif';
        @unlink($sourcePath);
        @unlink($targetPath);
        @rmdir($targetDir);
        copy(__DIR__.'/Fixtures/test.gif', $sourcePath);

        $file = new File($sourcePath);
        $movedFile = $file->move($targetDir);

        $this->assertFileExists($targetPath);
        $this->assertFileNotExists($sourcePath);
        $this->assertEquals(realpath($targetPath), $movedFile->getRealPath());

        @unlink($sourcePath);
        @unlink($targetPath);
        @rmdir($targetDir);
    }

    public function testGetExtension()
    {
        $file = new File(__DIR__.'/Fixtures/test.gif');
        $this->assertEquals('gif', $file->getExtension());
    }

    protected function createMockGuesser($path, $mimeType)
    {
        $guesser = $this->getMock('Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface');
        $guesser
            ->expects($this->once())
            ->method('guess')
            ->with($this->equalTo($path))
            ->will($this->returnValue($mimeType))
        ;

        return $guesser;
    }
}
PK��Z��t�AATtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/UploadedFileTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests\File;

use Symfony\Component\HttpFoundation\File\UploadedFile;

class UploadedFileTest extends \PHPUnit_Framework_TestCase
{
    protected function setUp()
    {
        if (!ini_get('file_uploads')) {
            $this->markTestSkipped('file_uploads is disabled in php.ini');
        }
    }

    public function testConstructWhenFileNotExists()
    {
        $this->setExpectedException('Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException');

        new UploadedFile(
            __DIR__.'/Fixtures/not_here',
            'original.gif',
            null
        );
    }

    public function testFileUploadsWithNoMimeType()
    {
        $file = new UploadedFile(
            __DIR__.'/Fixtures/test.gif',
            'original.gif',
            null,
            filesize(__DIR__.'/Fixtures/test.gif'),
            UPLOAD_ERR_OK
        );

        $this->assertEquals('application/octet-stream', $file->getClientMimeType());

        if (extension_loaded('fileinfo')) {
            $this->assertEquals('image/gif', $file->getMimeType());
        }
    }

    public function testFileUploadsWithUnknownMimeType()
    {
        $file = new UploadedFile(
            __DIR__.'/Fixtures/.unknownextension',
            'original.gif',
            null,
            filesize(__DIR__.'/Fixtures/.unknownextension'),
            UPLOAD_ERR_OK
        );

        $this->assertEquals('application/octet-stream', $file->getClientMimeType());
    }

    public function testGuessClientExtension()
    {
        $file = new UploadedFile(
            __DIR__.'/Fixtures/test.gif',
            'original.gif',
            'image/gif',
            filesize(__DIR__.'/Fixtures/test.gif'),
            null
        );

        $this->assertEquals('gif', $file->guessClientExtension());
    }

    public function testGuessClientExtensionWithIncorrectMimeType()
    {
        $file = new UploadedFile(
            __DIR__.'/Fixtures/test.gif',
            'original.gif',
            'image/jpeg',
            filesize(__DIR__.'/Fixtures/test.gif'),
            null
        );

        $this->assertEquals('jpeg', $file->guessClientExtension());
    }

    public function testErrorIsOkByDefault()
    {
        $file = new UploadedFile(
            __DIR__.'/Fixtures/test.gif',
            'original.gif',
            'image/gif',
            filesize(__DIR__.'/Fixtures/test.gif'),
            null
        );

        $this->assertEquals(UPLOAD_ERR_OK, $file->getError());
    }

    public function testGetClientOriginalName()
    {
        $file = new UploadedFile(
            __DIR__.'/Fixtures/test.gif',
            'original.gif',
            'image/gif',
            filesize(__DIR__.'/Fixtures/test.gif'),
            null
        );

        $this->assertEquals('original.gif', $file->getClientOriginalName());
    }

    public function testGetClientOriginalExtension()
    {
        $file = new UploadedFile(
            __DIR__.'/Fixtures/test.gif',
            'original.gif',
            'image/gif',
            filesize(__DIR__.'/Fixtures/test.gif'),
            null
        );

        $this->assertEquals('gif', $file->getClientOriginalExtension());
    }

    /**
     * @expectedException \Symfony\Component\HttpFoundation\File\Exception\FileException
     */
    public function testMoveLocalFileIsNotAllowed()
    {
        $file = new UploadedFile(
            __DIR__.'/Fixtures/test.gif',
            'original.gif',
            'image/gif',
            filesize(__DIR__.'/Fixtures/test.gif'),
            UPLOAD_ERR_OK
        );

        $movedFile = $file->move(__DIR__.'/Fixtures/directory');
    }

    public function testMoveLocalFileIsAllowedInTestMode()
    {
        $path = __DIR__.'/Fixtures/test.copy.gif';
        $targetDir = __DIR__.'/Fixtures/directory';
        $targetPath = $targetDir.'/test.copy.gif';
        @unlink($path);
        @unlink($targetPath);
        copy(__DIR__.'/Fixtures/test.gif', $path);

        $file = new UploadedFile(
            $path,
            'original.gif',
            'image/gif',
            filesize($path),
            UPLOAD_ERR_OK,
            true
        );

        $movedFile = $file->move(__DIR__.'/Fixtures/directory');

        $this->assertTrue(file_exists($targetPath));
        $this->assertFalse(file_exists($path));
        $this->assertEquals(realpath($targetPath), $movedFile->getRealPath());

        @unlink($targetPath);
    }

    public function testGetClientOriginalNameSanitizeFilename()
    {
        $file = new UploadedFile(
            __DIR__.'/Fixtures/test.gif',
            '../../original.gif',
            'image/gif',
            filesize(__DIR__.'/Fixtures/test.gif'),
            null
        );

        $this->assertEquals('original.gif', $file->getClientOriginalName());
    }

    public function testGetSize()
    {
        $file = new UploadedFile(
            __DIR__.'/Fixtures/test.gif',
            'original.gif',
            'image/gif',
            filesize(__DIR__.'/Fixtures/test.gif'),
            null
        );

        $this->assertEquals(filesize(__DIR__.'/Fixtures/test.gif'), $file->getSize());

        $file = new UploadedFile(
            __DIR__.'/Fixtures/test',
            'original.gif',
            'image/gif'
        );

        $this->assertEquals(filesize(__DIR__.'/Fixtures/test'), $file->getSize());
    }

    public function testGetExtension()
    {
        $file = new UploadedFile(
            __DIR__.'/Fixtures/test.gif',
            'original.gif',
            null
        );

        $this->assertEquals('gif', $file->getExtension());
    }

    public function testIsValid()
    {
        $file = new UploadedFile(
            __DIR__.'/Fixtures/test.gif',
            'original.gif',
            null,
            filesize(__DIR__.'/Fixtures/test.gif'),
            UPLOAD_ERR_OK,
            true
        );

        $this->assertTrue($file->isValid());
    }

    /**
     * @dataProvider uploadedFileErrorProvider
     */
    public function testIsInvalidOnUploadError($error)
    {
        $file = new UploadedFile(
            __DIR__.'/Fixtures/test.gif',
            'original.gif',
            null,
            filesize(__DIR__.'/Fixtures/test.gif'),
            $error
        );

        $this->assertFalse($file->isValid());
    }

    public function uploadedFileErrorProvider()
    {
        return array(
            array(UPLOAD_ERR_INI_SIZE),
            array(UPLOAD_ERR_FORM_SIZE),
            array(UPLOAD_ERR_PARTIAL),
            array(UPLOAD_ERR_NO_TMP_DIR),
            array(UPLOAD_ERR_EXTENSION),
        );
    }

    public function testIsInvalidIfNotHttpUpload()
    {
        $file = new UploadedFile(
            __DIR__.'/Fixtures/test.gif',
            'original.gif',
            null,
            filesize(__DIR__.'/Fixtures/test.gif'),
            UPLOAD_ERR_OK
        );

        $this->assertFalse($file->isValid());
    }
}
PK��Z�ʾV�
�
Stest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/StreamedResponseTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\StreamedResponse;

class StreamedResponseTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $response = new StreamedResponse(function () { echo 'foo'; }, 404, array('Content-Type' => 'text/plain'));

        $this->assertEquals(404, $response->getStatusCode());
        $this->assertEquals('text/plain', $response->headers->get('Content-Type'));
    }

    public function testPrepareWith11Protocol()
    {
        $response = new StreamedResponse(function () { echo 'foo'; });
        $request = Request::create('/');
        $request->server->set('SERVER_PROTOCOL', 'HTTP/1.1');

        $response->prepare($request);

        $this->assertEquals('1.1', $response->getProtocolVersion());
        $this->assertNotEquals('chunked', $response->headers->get('Transfer-Encoding'), 'Apache assumes responses with a Transfer-Encoding header set to chunked to already be encoded.');
        $this->assertEquals('no-cache, private', $response->headers->get('Cache-Control'));
    }

    public function testPrepareWith10Protocol()
    {
        $response = new StreamedResponse(function () { echo 'foo'; });
        $request = Request::create('/');
        $request->server->set('SERVER_PROTOCOL', 'HTTP/1.0');

        $response->prepare($request);

        $this->assertEquals('1.0', $response->getProtocolVersion());
        $this->assertNull($response->headers->get('Transfer-Encoding'));
        $this->assertEquals('no-cache, private', $response->headers->get('Cache-Control'));
    }

    public function testPrepareWithHeadRequest()
    {
        $response = new StreamedResponse(function () { echo 'foo'; });
        $request = Request::create('/', 'HEAD');

        $response->prepare($request);
    }

    public function testSendContent()
    {
        $called = 0;

        $response = new StreamedResponse(function () use (&$called) { ++$called; });

        $response->sendContent();
        $this->assertEquals(1, $called);

        $response->sendContent();
        $this->assertEquals(1, $called);
    }

    /**
     * @expectedException \LogicException
     */
    public function testSendContentWithNonCallable()
    {
        $response = new StreamedResponse(null);
        $response->sendContent();
    }

    /**
     * @expectedException \LogicException
     */
    public function testSetCallbackNonCallable()
    {
        $response = new StreamedResponse(null);
        $response->setCallback(null);
    }

    /**
     * @expectedException \LogicException
     */
    public function testSetContent()
    {
        $response = new StreamedResponse(function () { echo 'foo'; });
        $response->setContent('foo');
    }

    public function testGetContent()
    {
        $response = new StreamedResponse(function () { echo 'foo'; });
        $this->assertFalse($response->getContent());
    }

    public function testCreate()
    {
        $response = StreamedResponse::create(function () {}, 204);

        $this->assertInstanceOf('Symfony\Component\HttpFoundation\StreamedResponse', $response);
        $this->assertEquals(204, $response->getStatusCode());
    }
}
PK��ZM�{��ctest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Flash/AutoExpireFlashBagTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests\Session\Flash;

use Symfony\Component\HttpFoundation\Session\Flash\AutoExpireFlashBag as FlashBag;

/**
 * AutoExpireFlashBagTest
 *
 * @author Drak <drak@zikula.org>
 */
class AutoExpireFlashBagTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var \Symfony\Component\HttpFoundation\Session\Flash\AutoExpireFlashBag
     */
    private $bag;

    /**
     * @var array
     */
    protected $array = array();

    protected function setUp()
    {
        parent::setUp();
        $this->bag = new FlashBag();
        $this->array = array('new' => array('notice' => array('A previous flash message')));
        $this->bag->initialize($this->array);
    }

    public function tearDown()
    {
        $this->bag = null;
        parent::tearDown();
    }

    public function testInitialize()
    {
        $bag = new FlashBag();
        $array = array('new' => array('notice' => array('A previous flash message')));
        $bag->initialize($array);
        $this->assertEquals(array('A previous flash message'), $bag->peek('notice'));
        $array = array('new' => array(
                'notice' => array('Something else'),
                'error' => array('a'),
            ));
        $bag->initialize($array);
        $this->assertEquals(array('Something else'), $bag->peek('notice'));
        $this->assertEquals(array('a'), $bag->peek('error'));
    }

    public function testGetStorageKey()
    {
        $this->assertEquals('_sf2_flashes', $this->bag->getStorageKey());
        $attributeBag = new FlashBag('test');
        $this->assertEquals('test', $attributeBag->getStorageKey());
    }

    public function testGetSetName()
    {
        $this->assertEquals('flashes', $this->bag->getName());
        $this->bag->setName('foo');
        $this->assertEquals('foo', $this->bag->getName());
    }

    public function testPeek()
    {
        $this->assertEquals(array(), $this->bag->peek('non_existing'));
        $this->assertEquals(array('default'), $this->bag->peek('non_existing', array('default')));
        $this->assertEquals(array('A previous flash message'), $this->bag->peek('notice'));
        $this->assertEquals(array('A previous flash message'), $this->bag->peek('notice'));
    }

    public function testSet()
    {
        $this->bag->set('notice', 'Foo');
        $this->assertEquals(array('A previous flash message'), $this->bag->peek('notice'));
    }

    public function testHas()
    {
        $this->assertFalse($this->bag->has('nothing'));
        $this->assertTrue($this->bag->has('notice'));
    }

    public function testKeys()
    {
        $this->assertEquals(array('notice'), $this->bag->keys());
    }

    public function testPeekAll()
    {
        $array = array(
            'new' => array(
                'notice' => 'Foo',
                'error' => 'Bar',
            ),
        );

        $this->bag->initialize($array);
        $this->assertEquals(array(
            'notice' => 'Foo',
            'error' => 'Bar',
            ), $this->bag->peekAll()
        );

        $this->assertEquals(array(
            'notice' => 'Foo',
            'error' => 'Bar',
            ), $this->bag->peekAll()
        );
    }

    public function testGet()
    {
        $this->assertEquals(array(), $this->bag->get('non_existing'));
        $this->assertEquals(array('default'), $this->bag->get('non_existing', array('default')));
        $this->assertEquals(array('A previous flash message'), $this->bag->get('notice'));
        $this->assertEquals(array(), $this->bag->get('notice'));
    }

    public function testSetAll()
    {
        $this->bag->setAll(array('a' => 'first', 'b' => 'second'));
        $this->assertFalse($this->bag->has('a'));
        $this->assertFalse($this->bag->has('b'));
    }

    public function testAll()
    {
        $this->bag->set('notice', 'Foo');
        $this->bag->set('error', 'Bar');
        $this->assertEquals(array(
            'notice' => array('A previous flash message'),
            ), $this->bag->all()
        );

        $this->assertEquals(array(), $this->bag->all());
    }

    public function testClear()
    {
        $this->assertEquals(array('notice' => array('A previous flash message')), $this->bag->clear());
    }
}
PK��Z��ƒ��Ytest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Flash/FlashBagTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests\Session\Flash;

use Symfony\Component\HttpFoundation\Session\Flash\FlashBag;
use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;

/**
 * FlashBagTest
 *
 * @author Drak <drak@zikula.org>
 */
class FlashBagTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var \Symfony\Component\HttpFoundation\SessionFlash\FlashBagInterface
     */
    private $bag;

    /**
     * @var array
     */
    protected $array = array();

    protected function setUp()
    {
        parent::setUp();
        $this->bag = new FlashBag();
        $this->array = array('notice' => array('A previous flash message'));
        $this->bag->initialize($this->array);
    }

    public function tearDown()
    {
        $this->bag = null;
        parent::tearDown();
    }

    public function testInitialize()
    {
        $bag = new FlashBag();
        $bag->initialize($this->array);
        $this->assertEquals($this->array, $bag->peekAll());
        $array = array('should' => array('change'));
        $bag->initialize($array);
        $this->assertEquals($array, $bag->peekAll());
    }

    public function testGetStorageKey()
    {
        $this->assertEquals('_sf2_flashes', $this->bag->getStorageKey());
        $attributeBag = new FlashBag('test');
        $this->assertEquals('test', $attributeBag->getStorageKey());
    }

    public function testGetSetName()
    {
        $this->assertEquals('flashes', $this->bag->getName());
        $this->bag->setName('foo');
        $this->assertEquals('foo', $this->bag->getName());
    }

    public function testPeek()
    {
        $this->assertEquals(array(), $this->bag->peek('non_existing'));
        $this->assertEquals(array('default'), $this->bag->peek('not_existing', array('default')));
        $this->assertEquals(array('A previous flash message'), $this->bag->peek('notice'));
        $this->assertEquals(array('A previous flash message'), $this->bag->peek('notice'));
    }

    public function testGet()
    {
        $this->assertEquals(array(), $this->bag->get('non_existing'));
        $this->assertEquals(array('default'), $this->bag->get('not_existing', array('default')));
        $this->assertEquals(array('A previous flash message'), $this->bag->get('notice'));
        $this->assertEquals(array(), $this->bag->get('notice'));
    }

    public function testAll()
    {
        $this->bag->set('notice', 'Foo');
        $this->bag->set('error', 'Bar');
        $this->assertEquals(array(
            'notice' => array('Foo'),
            'error' => array('Bar')), $this->bag->all()
        );

        $this->assertEquals(array(), $this->bag->all());
    }

    public function testSet()
    {
        $this->bag->set('notice', 'Foo');
        $this->bag->set('notice', 'Bar');
        $this->assertEquals(array('Bar'), $this->bag->peek('notice'));
    }

    public function testHas()
    {
        $this->assertFalse($this->bag->has('nothing'));
        $this->assertTrue($this->bag->has('notice'));
    }

    public function testKeys()
    {
        $this->assertEquals(array('notice'), $this->bag->keys());
    }

    public function testPeekAll()
    {
        $this->bag->set('notice', 'Foo');
        $this->bag->set('error', 'Bar');
        $this->assertEquals(array(
            'notice' => array('Foo'),
            'error' => array('Bar'),
            ), $this->bag->peekAll()
        );
        $this->assertTrue($this->bag->has('notice'));
        $this->assertTrue($this->bag->has('error'));
        $this->assertEquals(array(
            'notice' => array('Foo'),
            'error' => array('Bar'),
            ), $this->bag->peekAll()
        );
    }

    /**
     * @covers Symfony\Component\HttpFoundation\Session\Flash\FlashBag::getIterator
     */
    public function testGetIterator()
    {
        $flashes = array('hello' => 'world', 'beep' => 'boop', 'notice' => 'nope');
        foreach ($flashes as $key => $val) {
            $this->bag->set($key, $val);
        }

        $i = 0;
        foreach ($this->bag as $key => $val) {
            $this->assertEquals(array($flashes[$key]), $val);
            $i++;
        }

        $this->assertEquals(count($flashes), $i);
        $this->assertCount(0, $this->bag->all());
    }
}
PK��Z0�����atest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Attribute/AttributeBagTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests\Session\Attribute;

use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag;

/**
 * Tests AttributeBag
 *
 * @author Drak <drak@zikula.org>
 */
class AttributeBagTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var array
     */
    private $array;

    /**
     * @var AttributeBag
     */
    private $bag;

    protected function setUp()
    {
        $this->array = array(
            'hello' => 'world',
            'always' => 'be happy',
            'user.login' => 'drak',
            'csrf.token' => array(
                'a' => '1234',
                'b' => '4321',
            ),
            'category' => array(
                'fishing' => array(
                    'first' => 'cod',
                    'second' => 'sole')
                ),
        );
        $this->bag = new AttributeBag('_sf2');
        $this->bag->initialize($this->array);
    }

    protected function tearDown()
    {
        $this->bag = null;
        $this->array = array();
    }

    public function testInitialize()
    {
        $bag = new AttributeBag();
        $bag->initialize($this->array);
        $this->assertEquals($this->array, $bag->all());
        $array = array('should' => 'change');
        $bag->initialize($array);
        $this->assertEquals($array, $bag->all());
    }

    public function testGetStorageKey()
    {
        $this->assertEquals('_sf2', $this->bag->getStorageKey());
        $attributeBag = new AttributeBag('test');
        $this->assertEquals('test', $attributeBag->getStorageKey());
    }

    public function testGetSetName()
    {
        $this->assertEquals('attributes', $this->bag->getName());
        $this->bag->setName('foo');
        $this->assertEquals('foo', $this->bag->getName());
    }

    /**
     * @dataProvider attributesProvider
     */
    public function testHas($key, $value, $exists)
    {
        $this->assertEquals($exists, $this->bag->has($key));
    }

    /**
     * @dataProvider attributesProvider
     */
    public function testGet($key, $value, $expected)
    {
        $this->assertEquals($value, $this->bag->get($key));
    }

    public function testGetDefaults()
    {
        $this->assertNull($this->bag->get('user2.login'));
        $this->assertEquals('default', $this->bag->get('user2.login', 'default'));
    }

    /**
     * @dataProvider attributesProvider
     */
    public function testSet($key, $value, $expected)
    {
        $this->bag->set($key, $value);
        $this->assertEquals($value, $this->bag->get($key));
    }

    public function testAll()
    {
        $this->assertEquals($this->array, $this->bag->all());

        $this->bag->set('hello', 'fabien');
        $array = $this->array;
        $array['hello'] = 'fabien';
        $this->assertEquals($array, $this->bag->all());
    }

    public function testReplace()
    {
        $array = array();
        $array['name'] = 'jack';
        $array['foo.bar'] = 'beep';
        $this->bag->replace($array);
        $this->assertEquals($array, $this->bag->all());
        $this->assertNull($this->bag->get('hello'));
        $this->assertNull($this->bag->get('always'));
        $this->assertNull($this->bag->get('user.login'));
    }

    public function testRemove()
    {
        $this->assertEquals('world', $this->bag->get('hello'));
        $this->bag->remove('hello');
        $this->assertNull($this->bag->get('hello'));

        $this->assertEquals('be happy', $this->bag->get('always'));
        $this->bag->remove('always');
        $this->assertNull($this->bag->get('always'));

        $this->assertEquals('drak', $this->bag->get('user.login'));
        $this->bag->remove('user.login');
        $this->assertNull($this->bag->get('user.login'));
    }

    public function testClear()
    {
        $this->bag->clear();
        $this->assertEquals(array(), $this->bag->all());
    }

    public function attributesProvider()
    {
        return array(
            array('hello', 'world', true),
            array('always', 'be happy', true),
            array('user.login', 'drak', true),
            array('csrf.token', array('a' => '1234', 'b' => '4321'), true),
            array('category', array('fishing' => array('first' => 'cod', 'second' => 'sole')), true),
            array('user2.login', null, false),
            array('never', null, false),
            array('bye', null, false),
            array('bye/for/now', null, false),
        );
    }

    /**
     * @covers Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag::getIterator
     */
    public function testGetIterator()
    {
        $i = 0;
        foreach ($this->bag as $key => $val) {
            $this->assertEquals($this->array[$key], $val);
            $i++;
        }

        $this->assertEquals(count($this->array), $i);
    }

    /**
     * @covers Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag::count
     */
    public function testCount()
    {
        $this->assertEquals(count($this->array), count($this->bag));
    }
}
PK��Z)��ktest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Attribute/NamespacedAttributeBagTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests\Session\Attribute;

use Symfony\Component\HttpFoundation\Session\Attribute\NamespacedAttributeBag;

/**
 * Tests NamespacedAttributeBag
 *
 * @author Drak <drak@zikula.org>
 */
class NamespacedAttributeBagTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var array
     */
    private $array;

    /**
     * @var NamespacedAttributeBag
     */
    private $bag;

    protected function setUp()
    {
        $this->array = array(
            'hello' => 'world',
            'always' => 'be happy',
            'user.login' => 'drak',
            'csrf.token' => array(
                'a' => '1234',
                'b' => '4321',
            ),
            'category' => array(
                'fishing' => array(
                    'first' => 'cod',
                    'second' => 'sole')
                ),
        );
        $this->bag = new NamespacedAttributeBag('_sf2', '/');
        $this->bag->initialize($this->array);
    }

    protected function tearDown()
    {
        $this->bag = null;
        $this->array = array();
    }

    public function testInitialize()
    {
        $bag = new NamespacedAttributeBag();
        $bag->initialize($this->array);
        $this->assertEquals($this->array, $this->bag->all());
        $array = array('should' => 'not stick');
        $bag->initialize($array);

        // should have remained the same
        $this->assertEquals($this->array, $this->bag->all());
    }

    public function testGetStorageKey()
    {
        $this->assertEquals('_sf2', $this->bag->getStorageKey());
        $attributeBag = new NamespacedAttributeBag('test');
        $this->assertEquals('test', $attributeBag->getStorageKey());
    }

    /**
     * @dataProvider attributesProvider
     */
    public function testHas($key, $value, $exists)
    {
        $this->assertEquals($exists, $this->bag->has($key));
    }

    /**
     * @dataProvider attributesProvider
     */
    public function testGet($key, $value, $expected)
    {
        $this->assertEquals($value, $this->bag->get($key));
    }

    public function testGetDefaults()
    {
        $this->assertNull($this->bag->get('user2.login'));
        $this->assertEquals('default', $this->bag->get('user2.login', 'default'));
    }

    /**
     * @dataProvider attributesProvider
     */
    public function testSet($key, $value, $expected)
    {
        $this->bag->set($key, $value);
        $this->assertEquals($value, $this->bag->get($key));
    }

    public function testAll()
    {
        $this->assertEquals($this->array, $this->bag->all());

        $this->bag->set('hello', 'fabien');
        $array = $this->array;
        $array['hello'] = 'fabien';
        $this->assertEquals($array, $this->bag->all());
    }

    public function testReplace()
    {
        $array = array();
        $array['name'] = 'jack';
        $array['foo.bar'] = 'beep';
        $this->bag->replace($array);
        $this->assertEquals($array, $this->bag->all());
        $this->assertNull($this->bag->get('hello'));
        $this->assertNull($this->bag->get('always'));
        $this->assertNull($this->bag->get('user.login'));
    }

    public function testRemove()
    {
        $this->assertEquals('world', $this->bag->get('hello'));
        $this->bag->remove('hello');
        $this->assertNull($this->bag->get('hello'));

        $this->assertEquals('be happy', $this->bag->get('always'));
        $this->bag->remove('always');
        $this->assertNull($this->bag->get('always'));

        $this->assertEquals('drak', $this->bag->get('user.login'));
        $this->bag->remove('user.login');
        $this->assertNull($this->bag->get('user.login'));
    }

    public function testRemoveExistingNamespacedAttribute()
    {
        $this->assertSame('cod', $this->bag->remove('category/fishing/first'));
    }

    public function testRemoveNonexistingNamespacedAttribute()
    {
        $this->assertNull($this->bag->remove('foo/bar/baz'));
    }

    public function testClear()
    {
        $this->bag->clear();
        $this->assertEquals(array(), $this->bag->all());
    }

    public function attributesProvider()
    {
        return array(
            array('hello', 'world', true),
            array('always', 'be happy', true),
            array('user.login', 'drak', true),
            array('csrf.token', array('a' => '1234', 'b' => '4321'), true),
            array('csrf.token/a', '1234', true),
            array('csrf.token/b', '4321', true),
            array('category', array('fishing' => array('first' => 'cod', 'second' => 'sole')), true),
            array('category/fishing', array('first' => 'cod', 'second' => 'sole'), true),
            array('category/fishing/missing/first', null, false),
            array('category/fishing/first', 'cod', true),
            array('category/fishing/second', 'sole', true),
            array('category/fishing/missing/second', null, false),
            array('user2.login', null, false),
            array('never', null, false),
            array('bye', null, false),
            array('bye/for/now', null, false),
        );
    }
}
PK��Z��ppRtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/SessionTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests\Session;

use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\Flash\FlashBag;
use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag;
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;

/**
 * SessionTest
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Robert Schönthal <seroscho@googlemail.com>
 * @author Drak <drak@zikula.org>
 */
class SessionTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var \Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface
     */
    protected $storage;

    /**
     * @var \Symfony\Component\HttpFoundation\Session\SessionInterface
     */
    protected $session;

    protected function setUp()
    {
        $this->storage = new MockArraySessionStorage();
        $this->session = new Session($this->storage, new AttributeBag(), new FlashBag());
    }

    protected function tearDown()
    {
        $this->storage = null;
        $this->session = null;
    }

    public function testStart()
    {
        $this->assertEquals('', $this->session->getId());
        $this->assertTrue($this->session->start());
        $this->assertNotEquals('', $this->session->getId());
    }

    public function testIsStarted()
    {
        $this->assertFalse($this->session->isStarted());
        $this->session->start();
        $this->assertTrue($this->session->isStarted());
    }

    public function testSetId()
    {
        $this->assertEquals('', $this->session->getId());
        $this->session->setId('0123456789abcdef');
        $this->session->start();
        $this->assertEquals('0123456789abcdef', $this->session->getId());
    }

    public function testSetName()
    {
        $this->assertEquals('MOCKSESSID', $this->session->getName());
        $this->session->setName('session.test.com');
        $this->session->start();
        $this->assertEquals('session.test.com', $this->session->getName());
    }

    public function testGet()
    {
        // tests defaults
        $this->assertNull($this->session->get('foo'));
        $this->assertEquals(1, $this->session->get('foo', 1));
    }

    /**
     * @dataProvider setProvider
     */
    public function testSet($key, $value)
    {
        $this->session->set($key, $value);
        $this->assertEquals($value, $this->session->get($key));
    }

    /**
     * @dataProvider setProvider
     */
    public function testHas($key, $value)
    {
        $this->session->set($key, $value);
        $this->assertTrue($this->session->has($key));
        $this->assertFalse($this->session->has($key.'non_value'));
    }

    public function testReplace()
    {
        $this->session->replace(array('happiness' => 'be good', 'symfony' => 'awesome'));
        $this->assertEquals(array('happiness' => 'be good', 'symfony' => 'awesome'), $this->session->all());
        $this->session->replace(array());
        $this->assertEquals(array(), $this->session->all());
    }

    /**
     * @dataProvider setProvider
     */
    public function testAll($key, $value, $result)
    {
        $this->session->set($key, $value);
        $this->assertEquals($result, $this->session->all());
    }

    /**
     * @dataProvider setProvider
     */
    public function testClear($key, $value)
    {
        $this->session->set('hi', 'fabien');
        $this->session->set($key, $value);
        $this->session->clear();
        $this->assertEquals(array(), $this->session->all());
    }

    public function setProvider()
    {
        return array(
            array('foo', 'bar', array('foo' => 'bar')),
            array('foo.bar', 'too much beer', array('foo.bar' => 'too much beer')),
            array('great', 'symfony2 is great', array('great' => 'symfony2 is great')),
        );
    }

    /**
     * @dataProvider setProvider
     */
    public function testRemove($key, $value)
    {
        $this->session->set('hi.world', 'have a nice day');
        $this->session->set($key, $value);
        $this->session->remove($key);
        $this->assertEquals(array('hi.world' => 'have a nice day'), $this->session->all());
    }

    public function testInvalidate()
    {
        $this->session->set('invalidate', 123);
        $this->session->invalidate();
        $this->assertEquals(array(), $this->session->all());
    }

    public function testMigrate()
    {
        $this->session->set('migrate', 321);
        $this->session->migrate();
        $this->assertEquals(321, $this->session->get('migrate'));
    }

    public function testMigrateDestroy()
    {
        $this->session->set('migrate', 333);
        $this->session->migrate(true);
        $this->assertEquals(333, $this->session->get('migrate'));
    }

    public function testSave()
    {
        $this->session->start();
        $this->session->save();
    }

    public function testGetId()
    {
        $this->assertEquals('', $this->session->getId());
        $this->session->start();
        $this->assertNotEquals('', $this->session->getId());
    }

    public function testGetFlashBag()
    {
        $this->assertInstanceOf('Symfony\\Component\\HttpFoundation\\Session\\Flash\\FlashBagInterface', $this->session->getFlashBag());
    }

    /**
     * @covers Symfony\Component\HttpFoundation\Session\Session::getIterator
     */
    public function testGetIterator()
    {
        $attributes = array('hello' => 'world', 'symfony2' => 'rocks');
        foreach ($attributes as $key => $val) {
            $this->session->set($key, $val);
        }

        $i = 0;
        foreach ($this->session as $key => $val) {
            $this->assertEquals($attributes[$key], $val);
            $i++;
        }

        $this->assertEquals(count($attributes), $i);
    }

    /**
     * @covers \Symfony\Component\HttpFoundation\Session\Session::count
     */
    public function testGetCount()
    {
        $this->session->set('hello', 'world');
        $this->session->set('symfony2', 'rocks');

        $this->assertCount(2, $this->session);
    }

    public function testGetMeta()
    {
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\MetadataBag', $this->session->getMetadataBag());
    }
}
PK��Z>��*itest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockFileSessionStorageTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests\Session\Storage;

use Symfony\Component\HttpFoundation\Session\Storage\MockFileSessionStorage;
use Symfony\Component\HttpFoundation\Session\Flash\FlashBag;
use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag;

/**
 * Test class for MockFileSessionStorage.
 *
 * @author Drak <drak@zikula.org>
 */
class MockFileSessionStorageTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var string
     */
    private $sessionDir;

    /**
     * @var FileMockSessionStorage
     */
    protected $storage;

    protected function setUp()
    {
        $this->sessionDir = sys_get_temp_dir().'/sf2test';
        $this->storage = $this->getStorage();
    }

    protected function tearDown()
    {
        $this->sessionDir = null;
        $this->storage = null;
        array_map('unlink', glob($this->sessionDir.'/*.session'));
        if (is_dir($this->sessionDir)) {
            rmdir($this->sessionDir);
        }
    }

    public function testStart()
    {
        $this->assertEquals('', $this->storage->getId());
        $this->assertTrue($this->storage->start());
        $id = $this->storage->getId();
        $this->assertNotEquals('', $this->storage->getId());
        $this->assertTrue($this->storage->start());
        $this->assertEquals($id, $this->storage->getId());
    }

    public function testRegenerate()
    {
        $this->storage->start();
        $this->storage->getBag('attributes')->set('regenerate', 1234);
        $this->storage->regenerate();
        $this->assertEquals(1234, $this->storage->getBag('attributes')->get('regenerate'));
        $this->storage->regenerate(true);
        $this->assertEquals(1234, $this->storage->getBag('attributes')->get('regenerate'));
    }

    public function testGetId()
    {
        $this->assertEquals('', $this->storage->getId());
        $this->storage->start();
        $this->assertNotEquals('', $this->storage->getId());
    }

    public function testSave()
    {
        $this->storage->start();
        $id = $this->storage->getId();
        $this->assertNotEquals('108', $this->storage->getBag('attributes')->get('new'));
        $this->assertFalse($this->storage->getBag('flashes')->has('newkey'));
        $this->storage->getBag('attributes')->set('new', '108');
        $this->storage->getBag('flashes')->set('newkey', 'test');
        $this->storage->save();

        $storage = $this->getStorage();
        $storage->setId($id);
        $storage->start();
        $this->assertEquals('108', $storage->getBag('attributes')->get('new'));
        $this->assertTrue($storage->getBag('flashes')->has('newkey'));
        $this->assertEquals(array('test'), $storage->getBag('flashes')->peek('newkey'));
    }

    public function testMultipleInstances()
    {
        $storage1 = $this->getStorage();
        $storage1->start();
        $storage1->getBag('attributes')->set('foo', 'bar');
        $storage1->save();

        $storage2 = $this->getStorage();
        $storage2->setId($storage1->getId());
        $storage2->start();
        $this->assertEquals('bar', $storage2->getBag('attributes')->get('foo'), 'values persist between instances');
    }

    /**
     * @expectedException \RuntimeException
     */
    public function testSaveWithoutStart()
    {
        $storage1 = $this->getStorage();
        $storage1->save();
    }

    private function getStorage()
    {
        $storage = new MockFileSessionStorage($this->sessionDir);
        $storage->registerBag(new FlashBag());
        $storage->registerBag(new AttributeBag());

        return $storage;
    }
}
PK��Z5�h���otest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeSessionHandlerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler;

use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler;

/**
 * Test class for NativeSessionHandler.
 *
 * @author Drak <drak@zikula.org>
 *
 * @runTestsInSeparateProcesses
 */
class NativeSessionHandlerTest extends \PHPUnit_Framework_TestCase
{
    public function testConstruct()
    {
        $handler = new NativeSessionHandler();

        // note for PHPUnit optimisers - the use of assertTrue/False
        // here is deliberate since the tests do not require the classes to exist - drak
        if (version_compare(phpversion(), '5.4.0', '<')) {
            $this->assertFalse($handler instanceof \SessionHandler);
            $this->assertTrue($handler instanceof NativeSessionHandler);
        } else {
            $this->assertTrue($handler instanceof \SessionHandler);
            $this->assertTrue($handler instanceof NativeSessionHandler);
        }
    }
}
PK��Z1�Mf
f
qtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler;

use Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcacheSessionHandler;

class MemcacheSessionHandlerTest extends \PHPUnit_Framework_TestCase
{
    const PREFIX = 'prefix_';
    const TTL = 1000;
    /**
     * @var MemcacheSessionHandler
     */
    protected $storage;

    protected $memcache;

    protected function setUp()
    {
        if (!class_exists('Memcache')) {
            $this->markTestSkipped('Skipped tests Memcache class is not present');
        }

        $this->memcache = $this->getMock('Memcache');
        $this->storage = new MemcacheSessionHandler(
            $this->memcache,
            array('prefix' => self::PREFIX, 'expiretime' => self::TTL)
        );
    }

    protected function tearDown()
    {
        $this->memcache = null;
        $this->storage = null;
    }

    public function testOpenSession()
    {
        $this->assertTrue($this->storage->open('', ''));
    }

    public function testCloseSession()
    {
        $this->memcache
            ->expects($this->once())
            ->method('close')
            ->will($this->returnValue(true))
        ;

        $this->assertTrue($this->storage->close());
    }

    public function testReadSession()
    {
        $this->memcache
            ->expects($this->once())
            ->method('get')
            ->with(self::PREFIX.'id')
        ;

        $this->assertEquals('', $this->storage->read('id'));
    }

    public function testWriteSession()
    {
        $this->memcache
            ->expects($this->once())
            ->method('set')
            ->with(self::PREFIX.'id', 'data', 0, $this->equalTo(time() + self::TTL, 2))
            ->will($this->returnValue(true))
        ;

        $this->assertTrue($this->storage->write('id', 'data'));
    }

    public function testDestroySession()
    {
        $this->memcache
            ->expects($this->once())
            ->method('delete')
            ->with(self::PREFIX.'id')
            ->will($this->returnValue(true))
        ;

        $this->assertTrue($this->storage->destroy('id'));
    }

    public function testGcSession()
    {
        $this->assertTrue($this->storage->gc(123));
    }

    /**
     * @dataProvider getOptionFixtures
     */
    public function testSupportedOptions($options, $supported)
    {
        try {
            new MemcacheSessionHandler($this->memcache, $options);
            $this->assertTrue($supported);
        } catch (\InvalidArgumentException $e) {
            $this->assertFalse($supported);
        }
    }

    public function getOptionFixtures()
    {
        return array(
            array(array('prefix' => 'session'), true),
            array(array('expiretime' => 100), true),
            array(array('prefix' => 'session', 'expiretime' => 200), true),
            array(array('expiretime' => 100, 'foo' => 'bar'), false),
        );
    }

    public function testGetConnection()
    {
        $method = new \ReflectionMethod($this->storage, 'getMemcache');
        $method->setAccessible(true);

        $this->assertInstanceOf('\Memcache', $method->invoke($this->storage));
    }
}
PK��Z�+?�

stest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler;

use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeFileSessionHandler;
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;

/**
 * Test class for NativeFileSessionHandler.
 *
 * @author Drak <drak@zikula.org>
 *
 * @runTestsInSeparateProcesses
 */
class NativeFileSessionHandlerTest extends \PHPUnit_Framework_TestCase
{
    public function testConstruct()
    {
        $storage = new NativeSessionStorage(array('name' => 'TESTING'), new NativeFileSessionHandler(sys_get_temp_dir()));

        if (version_compare(phpversion(), '5.4.0', '<')) {
            $this->assertEquals('files', $storage->getSaveHandler()->getSaveHandlerName());
            $this->assertEquals('files', ini_get('session.save_handler'));
        } else {
            $this->assertEquals('files', $storage->getSaveHandler()->getSaveHandlerName());
            $this->assertEquals('user', ini_get('session.save_handler'));
        }

        $this->assertEquals(sys_get_temp_dir(), ini_get('session.save_path'));
        $this->assertEquals('TESTING', ini_get('session.name'));
    }

    /**
     * @dataProvider savePathDataProvider
     */
    public function testConstructSavePath($savePath, $expectedSavePath, $path)
    {
        $handler = new NativeFileSessionHandler($savePath);
        $this->assertEquals($expectedSavePath, ini_get('session.save_path'));
        $this->assertTrue(is_dir(realpath($path)));

        rmdir($path);
    }

    public function savePathDataProvider()
    {
        $base = sys_get_temp_dir();

        return array(
            array("$base/foo", "$base/foo", "$base/foo"),
            array("5;$base/foo", "5;$base/foo", "$base/foo"),
            array("5;0600;$base/foo", "5;0600;$base/foo", "$base/foo"),
        );
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testConstructException()
    {
        $handler = new NativeFileSessionHandler('something;invalid;with;too-many-args');
    }

    public function testConstructDefault()
    {
        $path = ini_get('session.save_path');
        $storage = new NativeSessionStorage(array('name' => 'TESTING'), new NativeFileSessionHandler());

        $this->assertEquals($path, ini_get('session.save_path'));
    }
}
PK��Z>��$$ptest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler;

use Symfony\Component\HttpFoundation\Session\Storage\Handler\MongoDbSessionHandler;

/**
 * @author Markus Bachmann <markus.bachmann@bachi.biz>
 */
class MongoDbSessionHandlerTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $mongo;
    private $storage;
    public $options;

    protected function setUp()
    {
        if (!extension_loaded('mongo')) {
            $this->markTestSkipped('MongoDbSessionHandler requires the PHP "mongo" extension.');
        }

        $mongoClass = version_compare(phpversion('mongo'), '1.3.0', '<') ? 'Mongo' : 'MongoClient';

        $this->mongo = $this->getMockBuilder($mongoClass)
            ->disableOriginalConstructor()
            ->getMock();

        $this->options = array(
            'id_field'   => '_id',
            'data_field' => 'data',
            'time_field' => 'time',
            'database' => 'sf2-test',
            'collection' => 'session-test'
        );

        $this->storage = new MongoDbSessionHandler($this->mongo, $this->options);
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testConstructorShouldThrowExceptionForInvalidMongo()
    {
        new MongoDbSessionHandler(new \stdClass(), $this->options);
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testConstructorShouldThrowExceptionForMissingOptions()
    {
        new MongoDbSessionHandler($this->mongo, array());
    }

    public function testOpenMethodAlwaysReturnTrue()
    {
        $this->assertTrue($this->storage->open('test', 'test'), 'The "open" method should always return true');
    }

    public function testCloseMethodAlwaysReturnTrue()
    {
        $this->assertTrue($this->storage->close(), 'The "close" method should always return true');
    }

    public function testWrite()
    {
        $collection = $this->getMockBuilder('MongoCollection')
            ->disableOriginalConstructor()
            ->getMock();

        $this->mongo->expects($this->once())
            ->method('selectCollection')
            ->with($this->options['database'], $this->options['collection'])
            ->will($this->returnValue($collection));

        $that = $this;
        $data = array();

        $collection->expects($this->once())
            ->method('update')
            ->will($this->returnCallback(function ($criteria, $updateData, $options) use ($that, &$data) {
                $that->assertEquals(array($that->options['id_field'] => 'foo'), $criteria);
                $that->assertEquals(array('upsert' => true, 'multiple' => false), $options);

                $data = $updateData['$set'];
            }));

        $this->assertTrue($this->storage->write('foo', 'bar'));

        $this->assertEquals('bar', $data[$this->options['data_field']]->bin);
        $that->assertInstanceOf('MongoDate', $data[$this->options['time_field']]);
    }

    public function testReplaceSessionData()
    {
        $collection = $this->getMockBuilder('MongoCollection')
            ->disableOriginalConstructor()
            ->getMock();

        $this->mongo->expects($this->once())
            ->method('selectCollection')
            ->with($this->options['database'], $this->options['collection'])
            ->will($this->returnValue($collection));

        $data = array();

        $collection->expects($this->exactly(2))
            ->method('update')
            ->will($this->returnCallback(function ($criteria, $updateData, $options) use (&$data) {
                $data = $updateData;
            }));

        $this->storage->write('foo', 'bar');
        $this->storage->write('foo', 'foobar');

        $this->assertEquals('foobar', $data['$set'][$this->options['data_field']]->bin);
    }

    public function testDestroy()
    {
        $collection = $this->getMockBuilder('MongoCollection')
            ->disableOriginalConstructor()
            ->getMock();

        $this->mongo->expects($this->once())
            ->method('selectCollection')
            ->with($this->options['database'], $this->options['collection'])
            ->will($this->returnValue($collection));

        $collection->expects($this->once())
            ->method('remove')
            ->with(array($this->options['id_field'] => 'foo'));

        $this->assertTrue($this->storage->destroy('foo'));
    }

    public function testGc()
    {
        $collection = $this->getMockBuilder('MongoCollection')
            ->disableOriginalConstructor()
            ->getMock();

        $this->mongo->expects($this->once())
            ->method('selectCollection')
            ->with($this->options['database'], $this->options['collection'])
            ->will($this->returnValue($collection));

        $that = $this;

        $collection->expects($this->once())
            ->method('remove')
            ->will($this->returnCallback(function ($criteria) use ($that) {
                $that->assertInstanceOf('MongoDate', $criteria[$that->options['time_field']]['$lt']);
                $that->assertGreaterThanOrEqual(time() - -1, $criteria[$that->options['time_field']]['$lt']->sec);
            }));

        $this->assertTrue($this->storage->gc(-1));
    }

    public function testGetConnection()
    {
        $method = new \ReflectionMethod($this->storage, 'getMongo');
        $method->setAccessible(true);

        $mongoClass = (version_compare(phpversion('mongo'), '1.3.0', '<')) ? '\Mongo' : '\MongoClient';

        $this->assertInstanceOf($mongoClass, $method->invoke($this->storage));
    }
}
PK��Z`����rtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler;

use Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcachedSessionHandler;

class MemcachedSessionHandlerTest extends \PHPUnit_Framework_TestCase
{
    const PREFIX = 'prefix_';
    const TTL = 1000;

    /**
     * @var MemcachedSessionHandler
     */
    protected $storage;

    protected $memcached;

    protected function setUp()
    {
        if (!class_exists('Memcached')) {
            $this->markTestSkipped('Skipped tests Memcached class is not present');
        }

        $this->memcached = $this->getMock('Memcached');
        $this->storage = new MemcachedSessionHandler(
            $this->memcached,
            array('prefix' => self::PREFIX, 'expiretime' => self::TTL)
        );
    }

    protected function tearDown()
    {
        $this->memcached = null;
        $this->storage = null;
    }

    public function testOpenSession()
    {
        $this->assertTrue($this->storage->open('', ''));
    }

    public function testCloseSession()
    {
        $this->assertTrue($this->storage->close());
    }

    public function testReadSession()
    {
        $this->memcached
            ->expects($this->once())
            ->method('get')
            ->with(self::PREFIX.'id')
        ;

        $this->assertEquals('', $this->storage->read('id'));
    }

    public function testWriteSession()
    {
        $this->memcached
            ->expects($this->once())
            ->method('set')
            ->with(self::PREFIX.'id', 'data', $this->equalTo(time() + self::TTL, 2))
            ->will($this->returnValue(true))
        ;

        $this->assertTrue($this->storage->write('id', 'data'));
    }

    public function testDestroySession()
    {
        $this->memcached
            ->expects($this->once())
            ->method('delete')
            ->with(self::PREFIX.'id')
            ->will($this->returnValue(true))
        ;

        $this->assertTrue($this->storage->destroy('id'));
    }

    public function testGcSession()
    {
        $this->assertTrue($this->storage->gc(123));
    }

    /**
     * @dataProvider getOptionFixtures
     */
    public function testSupportedOptions($options, $supported)
    {
        try {
            new MemcachedSessionHandler($this->memcached, $options);
            $this->assertTrue($supported);
        } catch (\InvalidArgumentException $e) {
            $this->assertFalse($supported);
        }
    }

    public function getOptionFixtures()
    {
        return array(
            array(array('prefix' => 'session'), true),
            array(array('expiretime' => 100), true),
            array(array('prefix' => 'session', 'expiretime' => 200), true),
            array(array('expiretime' => 100, 'foo' => 'bar'), false),
        );
    }

    public function testGetConnection()
    {
        $method = new \ReflectionMethod($this->storage, 'getMemcached');
        $method->setAccessible(true);

        $this->assertInstanceOf('\Memcached', $method->invoke($this->storage));
    }
}
PK��Z�c=��stest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/WriteCheckSessionHandlerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler;

use Symfony\Component\HttpFoundation\Session\Storage\Handler\WriteCheckSessionHandler;

/**
 * @author Adrien Brault <adrien.brault@gmail.com>
 */
class WriteCheckSessionHandlerTest extends \PHPUnit_Framework_TestCase
{
    public function test()
    {
        $wrappedSessionHandlerMock = $this->getMock('SessionHandlerInterface');
        $writeCheckSessionHandler = new WriteCheckSessionHandler($wrappedSessionHandlerMock);

        $wrappedSessionHandlerMock
            ->expects($this->once())
            ->method('close')
            ->with()
            ->will($this->returnValue(true))
        ;

        $this->assertEquals(true, $writeCheckSessionHandler->close());
    }

    public function testWrite()
    {
        $wrappedSessionHandlerMock = $this->getMock('SessionHandlerInterface');
        $writeCheckSessionHandler = new WriteCheckSessionHandler($wrappedSessionHandlerMock);

        $wrappedSessionHandlerMock
            ->expects($this->once())
            ->method('write')
            ->with('foo', 'bar')
            ->will($this->returnValue(true))
        ;

        $this->assertEquals(true, $writeCheckSessionHandler->write('foo', 'bar'));
    }

    public function testSkippedWrite()
    {
        $wrappedSessionHandlerMock = $this->getMock('SessionHandlerInterface');
        $writeCheckSessionHandler = new WriteCheckSessionHandler($wrappedSessionHandlerMock);

        $wrappedSessionHandlerMock
            ->expects($this->once())
            ->method('read')
            ->with('foo')
            ->will($this->returnValue('bar'))
        ;

        $wrappedSessionHandlerMock
            ->expects($this->never())
            ->method('write')
        ;

        $this->assertEquals('bar', $writeCheckSessionHandler->read('foo'));
        $this->assertEquals(true, $writeCheckSessionHandler->write('foo', 'bar'));
    }

    public function testNonSkippedWrite()
    {
        $wrappedSessionHandlerMock = $this->getMock('SessionHandlerInterface');
        $writeCheckSessionHandler = new WriteCheckSessionHandler($wrappedSessionHandlerMock);

        $wrappedSessionHandlerMock
            ->expects($this->once())
            ->method('read')
            ->with('foo')
            ->will($this->returnValue('bar'))
        ;

        $wrappedSessionHandlerMock
            ->expects($this->once())
            ->method('write')
            ->with('foo', 'baZZZ')
            ->will($this->returnValue(true))
        ;

        $this->assertEquals('bar', $writeCheckSessionHandler->read('foo'));
        $this->assertEquals(true, $writeCheckSessionHandler->write('foo', 'baZZZ'));
    }
}
PK��Z�Qttltest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler;

use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler;

class PdoSessionHandlerTest extends \PHPUnit_Framework_TestCase
{
    private $pdo;

    protected function setUp()
    {
        if (!class_exists('PDO') || !in_array('sqlite', \PDO::getAvailableDrivers())) {
            $this->markTestSkipped('This test requires SQLite support in your environment');
        }

        $this->pdo = new \PDO("sqlite::memory:");
        $this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
        $sql = "CREATE TABLE sessions (sess_id VARCHAR(255) PRIMARY KEY, sess_data TEXT, sess_time INTEGER)";
        $this->pdo->exec($sql);
    }

    public function testIncompleteOptions()
    {
        $this->setExpectedException('InvalidArgumentException');
        $storage = new PdoSessionHandler($this->pdo, array(), array());
    }

    public function testWrongPdoErrMode()
    {
        $pdo = new \PDO("sqlite::memory:");
        $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_SILENT);
        $pdo->exec("CREATE TABLE sessions (sess_id VARCHAR(255) PRIMARY KEY, sess_data TEXT, sess_time INTEGER)");

        $this->setExpectedException('InvalidArgumentException');
        $storage = new PdoSessionHandler($pdo, array('db_table' => 'sessions'), array());
    }

    public function testWrongTableOptionsWrite()
    {
        $storage = new PdoSessionHandler($this->pdo, array('db_table' => 'bad_name'), array());
        $this->setExpectedException('RuntimeException');
        $storage->write('foo', 'bar');
    }

    public function testWrongTableOptionsRead()
    {
        $storage = new PdoSessionHandler($this->pdo, array('db_table' => 'bad_name'), array());
        $this->setExpectedException('RuntimeException');
        $storage->read('foo', 'bar');
    }

    public function testWriteRead()
    {
        $storage = new PdoSessionHandler($this->pdo, array('db_table' => 'sessions'), array());
        $storage->write('foo', 'bar');
        $this->assertEquals('bar', $storage->read('foo'), 'written value can be read back correctly');
    }

    public function testMultipleInstances()
    {
        $storage1 = new PdoSessionHandler($this->pdo, array('db_table' => 'sessions'), array());
        $storage1->write('foo', 'bar');

        $storage2 = new PdoSessionHandler($this->pdo, array('db_table' => 'sessions'), array());
        $this->assertEquals('bar', $storage2->read('foo'), 'values persist between instances');
    }

    public function testSessionDestroy()
    {
        $storage = new PdoSessionHandler($this->pdo, array('db_table' => 'sessions'), array());
        $storage->write('foo', 'bar');
        $this->assertCount(1, $this->pdo->query('SELECT * FROM sessions')->fetchAll());

        $storage->destroy('foo');

        $this->assertCount(0, $this->pdo->query('SELECT * FROM sessions')->fetchAll());
    }

    public function testSessionGC()
    {
        $storage = new PdoSessionHandler($this->pdo, array('db_table' => 'sessions'), array());

        $storage->write('foo', 'bar');
        $storage->write('baz', 'bar');

        $this->assertCount(2, $this->pdo->query('SELECT * FROM sessions')->fetchAll());

        $storage->gc(-1);
        $this->assertCount(0, $this->pdo->query('SELECT * FROM sessions')->fetchAll());
    }

    public function testGetConnection()
    {
        $storage = new PdoSessionHandler($this->pdo, array('db_table' => 'sessions'), array());

        $method = new \ReflectionMethod($storage, 'getConnection');
        $method->setAccessible(true);

        $this->assertInstanceOf('\PDO', $method->invoke($storage));
    }
}
PK��Z+�ɠ��mtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NullSessionHandlerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler;

use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler;
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
use Symfony\Component\HttpFoundation\Session\Session;

/**
 * Test class for NullSessionHandler.
 *
 * @author Drak <drak@zikula.org>
 *
 * @runTestsInSeparateProcesses
 */
class NullSessionHandlerTest extends \PHPUnit_Framework_TestCase
{
    public function testSaveHandlers()
    {
        $storage = $this->getStorage();
        $this->assertEquals('user', ini_get('session.save_handler'));
    }

    public function testSession()
    {
        session_id('nullsessionstorage');
        $storage = $this->getStorage();
        $session = new Session($storage);
        $this->assertNull($session->get('something'));
        $session->set('something', 'unique');
        $this->assertEquals('unique', $session->get('something'));
    }

    public function testNothingIsPersisted()
    {
        session_id('nullsessionstorage');
        $storage = $this->getStorage();
        $session = new Session($storage);
        $session->start();
        $this->assertEquals('nullsessionstorage', $session->getId());
        $this->assertNull($session->get('something'));
    }

    public function getStorage()
    {
        return new NativeSessionStorage(array(), new NullSessionHandler());
    }
}
PK��Z��x�..jtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/PhpBridgeSessionStorageTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests\Session\Storage;

use Symfony\Component\HttpFoundation\Session\Storage\PhpBridgeSessionStorage;
use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag;

/**
 * Test class for PhpSessionStorage.
 *
 * @author Drak <drak@zikula.org>
 *
 * These tests require separate processes.
 *
 * @runTestsInSeparateProcesses
 */
class PhpBridgeSessionStorageTest extends \PHPUnit_Framework_TestCase
{
    private $savePath;

    protected function setUp()
    {
        ini_set('session.save_handler', 'files');
        ini_set('session.save_path', $this->savePath = sys_get_temp_dir().'/sf2test');
        if (!is_dir($this->savePath)) {
            mkdir($this->savePath);
        }
    }

    protected function tearDown()
    {
        session_write_close();
        array_map('unlink', glob($this->savePath.'/*'));
        if (is_dir($this->savePath)) {
            rmdir($this->savePath);
        }

        $this->savePath = null;
    }

    /**
     * @return PhpBridgeSessionStorage
     */
    protected function getStorage()
    {
        $storage = new PhpBridgeSessionStorage();
        $storage->registerBag(new AttributeBag());

        return $storage;
    }

    public function testPhpSession53()
    {
        if (version_compare(phpversion(), '5.4.0', '>=')) {
            $this->markTestSkipped('Test skipped, for PHP 5.3 only.');
        }

        $storage = $this->getStorage();

        $this->assertFalse(isset($_SESSION));
        $this->assertFalse($storage->getSaveHandler()->isActive());

        session_start();
        $this->assertTrue(isset($_SESSION));
        // in PHP 5.3 we cannot reliably tell if a session has started
        $this->assertFalse($storage->getSaveHandler()->isActive());
        // PHP session might have started, but the storage driver has not, so false is correct here
        $this->assertFalse($storage->isStarted());

        $key = $storage->getMetadataBag()->getStorageKey();
        $this->assertFalse(isset($_SESSION[$key]));
        $storage->start();
        $this->assertTrue(isset($_SESSION[$key]));
    }

    public function testPhpSession54()
    {
        if (version_compare(phpversion(), '5.4.0', '<')) {
            $this->markTestSkipped('Test skipped, for PHP 5.4 only.');
        }

        $storage = $this->getStorage();

        $this->assertFalse(isset($_SESSION));
        $this->assertFalse($storage->getSaveHandler()->isActive());
        $this->assertFalse($storage->isStarted());

        session_start();
        $this->assertTrue(isset($_SESSION));
        // in PHP 5.4 we can reliably detect a session started
        $this->assertTrue($storage->getSaveHandler()->isActive());
        // PHP session might have started, but the storage driver has not, so false is correct here
        $this->assertFalse($storage->isStarted());

        $key = $storage->getMetadataBag()->getStorageKey();
        $this->assertFalse(isset($_SESSION[$key]));
        $storage->start();
        $this->assertTrue(isset($_SESSION[$key]));
    }

    public function testClear()
    {
        $storage = $this->getStorage();
        session_start();
        $_SESSION['drak'] = 'loves symfony';
        $storage->getBag('attributes')->set('symfony', 'greatness');
        $key = $storage->getBag('attributes')->getStorageKey();
        $this->assertEquals($_SESSION[$key], array('symfony' => 'greatness'));
        $this->assertEquals($_SESSION['drak'], 'loves symfony');
        $storage->clear();
        $this->assertEquals($_SESSION[$key], array());
        $this->assertEquals($_SESSION['drak'], 'loves symfony');
    }
}
PK��Z�����jtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockArraySessionStorageTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests\Session\Storage;

use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag;
use Symfony\Component\HttpFoundation\Session\Flash\FlashBag;

/**
 * Test class for MockArraySessionStorage.
 *
 * @author Drak <drak@zikula.org>
 */
class MockArraySessionStorageTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var MockArraySessionStorage
     */
    private $storage;

    /**
     * @var AttributeBag
     */
    private $attributes;

    /**
     * @var FlashBag
     */
    private $flashes;

    private $data;

    protected function setUp()
    {
        $this->attributes = new AttributeBag();
        $this->flashes = new FlashBag();

        $this->data = array(
            $this->attributes->getStorageKey() => array('foo' => 'bar'),
            $this->flashes->getStorageKey() => array('notice' => 'hello'),
            );

        $this->storage = new MockArraySessionStorage();
        $this->storage->registerBag($this->flashes);
        $this->storage->registerBag($this->attributes);
        $this->storage->setSessionData($this->data);
    }

    protected function tearDown()
    {
        $this->data = null;
        $this->flashes = null;
        $this->attributes = null;
        $this->storage = null;
    }

    public function testStart()
    {
        $this->assertEquals('', $this->storage->getId());
        $this->storage->start();
        $id = $this->storage->getId();
        $this->assertNotEquals('', $id);
        $this->storage->start();
        $this->assertEquals($id, $this->storage->getId());
    }

    public function testRegenerate()
    {
        $this->storage->start();
        $id = $this->storage->getId();
        $this->storage->regenerate();
        $this->assertNotEquals($id, $this->storage->getId());
        $this->assertEquals(array('foo' => 'bar'), $this->storage->getBag('attributes')->all());
        $this->assertEquals(array('notice' => 'hello'), $this->storage->getBag('flashes')->peekAll());

        $id = $this->storage->getId();
        $this->storage->regenerate(true);
        $this->assertNotEquals($id, $this->storage->getId());
        $this->assertEquals(array('foo' => 'bar'), $this->storage->getBag('attributes')->all());
        $this->assertEquals(array('notice' => 'hello'), $this->storage->getBag('flashes')->peekAll());
    }

    public function testGetId()
    {
        $this->assertEquals('', $this->storage->getId());
        $this->storage->start();
        $this->assertNotEquals('', $this->storage->getId());
    }

    /**
     * @expectedException \RuntimeException
     */
    public function testUnstartedSave()
    {
        $this->storage->save();
    }
}
PK��Zt䪑�$�$gtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests\Session\Storage;

use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler;
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
use Symfony\Component\HttpFoundation\Session\Flash\FlashBag;
use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag;
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy;
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy;

/**
 * Test class for NativeSessionStorage.
 *
 * @author Drak <drak@zikula.org>
 *
 * These tests require separate processes.
 *
 * @runTestsInSeparateProcesses
 */
class NativeSessionStorageTest extends \PHPUnit_Framework_TestCase
{
    private $savePath;

    protected function setUp()
    {
        ini_set('session.save_handler', 'files');
        ini_set('session.save_path', $this->savePath = sys_get_temp_dir().'/sf2test');
        if (!is_dir($this->savePath)) {
            mkdir($this->savePath);
        }
    }

    protected function tearDown()
    {
        session_write_close();
        array_map('unlink', glob($this->savePath.'/*'));
        if (is_dir($this->savePath)) {
            rmdir($this->savePath);
        }

        $this->savePath = null;
    }

    /**
     * @param array $options
     *
     * @return NativeSessionStorage
     */
    protected function getStorage(array $options = array())
    {
        $storage = new NativeSessionStorage($options);
        $storage->registerBag(new AttributeBag());

        return $storage;
    }

    public function testBag()
    {
        $storage = $this->getStorage();
        $bag = new FlashBag();
        $storage->registerBag($bag);
        $this->assertSame($bag, $storage->getBag($bag->getName()));
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testRegisterBagException()
    {
        $storage = $this->getStorage();
        $storage->getBag('non_existing');
    }

    public function testGetId()
    {
        $storage = $this->getStorage();
        $this->assertEquals('', $storage->getId());

        $storage->start();
        $this->assertNotEquals('', $storage->getId());

        $storage->save();
        $this->assertNotEquals('', $storage->getId());
    }

    public function testRegenerate()
    {
        $storage = $this->getStorage();
        $storage->start();
        $id = $storage->getId();
        $storage->getBag('attributes')->set('lucky', 7);
        $storage->regenerate();
        $this->assertNotEquals($id, $storage->getId());
        $this->assertEquals(7, $storage->getBag('attributes')->get('lucky'));
    }

    public function testRegenerateDestroy()
    {
        $storage = $this->getStorage();
        $storage->start();
        $id = $storage->getId();
        $storage->getBag('attributes')->set('legs', 11);
        $storage->regenerate(true);
        $this->assertNotEquals($id, $storage->getId());
        $this->assertEquals(11, $storage->getBag('attributes')->get('legs'));
    }

    public function testDefaultSessionCacheLimiter()
    {
        ini_set('session.cache_limiter', 'nocache');

        $storage = new NativeSessionStorage();
        $this->assertEquals('', ini_get('session.cache_limiter'));
    }

    public function testExplicitSessionCacheLimiter()
    {
        ini_set('session.cache_limiter', 'nocache');

        $storage = new NativeSessionStorage(array('cache_limiter' => 'public'));
        $this->assertEquals('public', ini_get('session.cache_limiter'));
    }

    public function testCookieOptions()
    {
        $options = array(
            'cookie_lifetime' => 123456,
            'cookie_path' => '/my/cookie/path',
            'cookie_domain' => 'symfony2.example.com',
            'cookie_secure' => true,
            'cookie_httponly' => false,
        );

        $this->getStorage($options);
        $temp = session_get_cookie_params();
        $gco = array();

        foreach ($temp as $key => $value) {
            $gco['cookie_'.$key] = $value;
        }

        $this->assertEquals($options, $gco);
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testSetSaveHandlerException()
    {
        $storage = $this->getStorage();
        $storage->setSaveHandler(new \stdClass());
    }

    public function testSetSaveHandler53()
    {
        if (version_compare(phpversion(), '5.4.0', '>=')) {
            $this->markTestSkipped('Test skipped, for PHP 5.3 only.');
        }

        ini_set('session.save_handler', 'files');
        $storage = $this->getStorage();
        $storage->setSaveHandler();
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy', $storage->getSaveHandler());
        $storage->setSaveHandler(null);
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy', $storage->getSaveHandler());
        $storage->setSaveHandler(new NativeSessionHandler());
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy', $storage->getSaveHandler());
        $storage->setSaveHandler(new SessionHandlerProxy(new SessionHandler()));
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler());
        $storage->setSaveHandler(new SessionHandler());
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler());
        $storage->setSaveHandler(new NativeProxy());
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy', $storage->getSaveHandler());
    }

    public function testSetSaveHandler54()
    {
        if (version_compare(phpversion(), '5.4.0', '<')) {
            $this->markTestSkipped('Test skipped, for PHP 5.4 only.');
        }

        ini_set('session.save_handler', 'files');
        $storage = $this->getStorage();
        $storage->setSaveHandler();
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler());
        $storage->setSaveHandler(null);
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler());
        $storage->setSaveHandler(new SessionHandlerProxy(new NativeSessionHandler()));
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler());
        $storage->setSaveHandler(new NativeSessionHandler());
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler());
        $storage->setSaveHandler(new SessionHandlerProxy(new SessionHandler()));
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler());
        $storage->setSaveHandler(new SessionHandler());
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler());
    }

    /**
     * @expectedException \RuntimeException
     */
    public function testStartedOutside53()
    {
        if (version_compare(phpversion(), '5.4.0', '>=')) {
            $this->markTestSkipped('Test skipped, for PHP 5.3 only.');
        }

        $storage = $this->getStorage();

        $this->assertFalse(isset($_SESSION));

        session_start();
        $this->assertTrue(isset($_SESSION));
        // PHP session might have started, but the storage driver has not, so false is correct here
        $this->assertFalse($storage->isStarted());

        $key = $storage->getMetadataBag()->getStorageKey();
        $this->assertFalse(isset($_SESSION[$key]));
        $storage->start();
    }

    /**
     * @expectedException \RuntimeException
     */
    public function testCanStartOutside54()
    {
        if (version_compare(phpversion(), '5.4.0', '<')) {
            $this->markTestSkipped('Test skipped, for PHP 5.4 only.');
        }

        $storage = $this->getStorage();

        $this->assertFalse(isset($_SESSION));
        $this->assertFalse($storage->getSaveHandler()->isActive());
        $this->assertFalse($storage->isStarted());

        session_start();
        $this->assertTrue(isset($_SESSION));
        $this->assertTrue($storage->getSaveHandler()->isActive());
        // PHP session might have started, but the storage driver has not, so false is correct here
        $this->assertFalse($storage->isStarted());

        $key = $storage->getMetadataBag()->getStorageKey();
        $this->assertFalse(isset($_SESSION[$key]));
        $storage->start();
    }
}

class SessionHandler implements \SessionHandlerInterface
{
    public function open($savePath, $sessionName)
    {
    }

    public function close()
    {
    }

    public function read($id)
    {
    }

    public function write($id, $data)
    {
    }

    public function destroy($id)
    {
    }

    public function gc($maxlifetime)
    {
    }
}
PK��Z�@|B``dtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/NativeProxyTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Proxy;

use Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy;

/**
 * Test class for NativeProxy.
 *
 * @author Drak <drak@zikula.org>
 */
class NativeProxyTest extends \PHPUnit_Framework_TestCase
{
    public function testIsWrapper()
    {
        $proxy = new NativeProxy();
        $this->assertFalse($proxy->isWrapper());
    }

    public function testGetSaveHandlerName()
    {
        $name = ini_get('session.save_handler');
        $proxy = new NativeProxy();
        $this->assertEquals($name, $proxy->getSaveHandlerName());
    }
}
PK��ZF�++ftest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/AbstractProxyTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Proxy;

use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;

// Note until PHPUnit_Mock_Objects 1.2 is released you cannot mock abstracts due to
// https://github.com/sebastianbergmann/phpunit-mock-objects/issues/73
class ConcreteProxy extends AbstractProxy
{

}

class ConcreteSessionHandlerInterfaceProxy extends AbstractProxy implements \SessionHandlerInterface
{
    public function open($savePath, $sessionName)
    {
    }

    public function close()
    {
    }

    public function read($id)
    {
    }

    public function write($id, $data)
    {
    }

    public function destroy($id)
    {
    }

    public function gc($maxlifetime)
    {
    }
}

/**
 * Test class for AbstractProxy.
 *
 * @author Drak <drak@zikula.org>
 */
class AbstractProxyTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var AbstractProxy
     */
    protected $proxy;

    protected function setUp()
    {
        $this->proxy = new ConcreteProxy();
    }

    protected function tearDown()
    {
        $this->proxy = null;
    }

    public function testGetSaveHandlerName()
    {
        $this->assertNull($this->proxy->getSaveHandlerName());
    }

    public function testIsSessionHandlerInterface()
    {
        $this->assertFalse($this->proxy->isSessionHandlerInterface());
        $sh = new ConcreteSessionHandlerInterfaceProxy();
        $this->assertTrue($sh->isSessionHandlerInterface());
    }

    public function testIsWrapper()
    {
        $this->assertFalse($this->proxy->isWrapper());
    }

    public function testIsActivePhp53()
    {
        if (version_compare(phpversion(), '5.4.0', '>=')) {
            $this->markTestSkipped('Test skipped, for PHP 5.3 only.');
        }

        $this->assertFalse($this->proxy->isActive());
    }

    /**
     * @runInSeparateProcess
     */
    public function testIsActivePhp54()
    {
        if (version_compare(phpversion(), '5.4.0', '<')) {
            $this->markTestSkipped('Test skipped, for PHP 5.4 only.');
        }

        $this->assertFalse($this->proxy->isActive());
        session_start();
        $this->assertTrue($this->proxy->isActive());
    }

    public function testSetActivePhp53()
    {
        if (version_compare(phpversion(), '5.4.0', '>=')) {
            $this->markTestSkipped('Test skipped, for PHP 5.3 only.');
        }

        $this->proxy->setActive(true);
        $this->assertTrue($this->proxy->isActive());
        $this->proxy->setActive(false);
        $this->assertFalse($this->proxy->isActive());
    }

    /**
     * @runInSeparateProcess
     * @expectedException \LogicException
     */
    public function testSetActivePhp54()
    {
        if (version_compare(phpversion(), '5.4.0', '<')) {
            $this->markTestSkipped('Test skipped, for PHP 5.4 only.');
        }

        $this->proxy->setActive(true);
    }

    /**
     * @runInSeparateProcess
     */
    public function testName()
    {
        $this->assertEquals(session_name(), $this->proxy->getName());
        $this->proxy->setName('foo');
        $this->assertEquals('foo', $this->proxy->getName());
        $this->assertEquals(session_name(), $this->proxy->getName());
    }

    /**
     * @expectedException \LogicException
     */
    public function testNameExceptionPhp53()
    {
        if (version_compare(phpversion(), '5.4.0', '>=')) {
            $this->markTestSkipped('Test skipped, for PHP 5.3 only.');
        }

        $this->proxy->setActive(true);
        $this->proxy->setName('foo');
    }

    /**
     * @runInSeparateProcess
     * @expectedException \LogicException
     */
    public function testNameExceptionPhp54()
    {
        if (version_compare(phpversion(), '5.4.0', '<')) {
            $this->markTestSkipped('Test skipped, for PHP 5.4 only.');
        }

        session_start();
        $this->proxy->setName('foo');
    }

    /**
     * @runInSeparateProcess
     */
    public function testId()
    {
        $this->assertEquals(session_id(), $this->proxy->getId());
        $this->proxy->setId('foo');
        $this->assertEquals('foo', $this->proxy->getId());
        $this->assertEquals(session_id(), $this->proxy->getId());
    }

    /**
     * @expectedException \LogicException
     */
    public function testIdExceptionPhp53()
    {
        if (version_compare(phpversion(), '5.4.0', '>=')) {
            $this->markTestSkipped('Test skipped, for PHP 5.3 only.');
        }

        $this->proxy->setActive(true);
        $this->proxy->setId('foo');
    }

    /**
     * @runInSeparateProcess
     * @expectedException \LogicException
     */
    public function testIdExceptionPhp54()
    {
        if (version_compare(phpversion(), '5.4.0', '<')) {
            $this->markTestSkipped('Test skipped, for PHP 5.4 only.');
        }

        session_start();
        $this->proxy->setId('foo');
    }
}
PK��ZČ#��ltest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Proxy;

use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy;

/**
 * Tests for SessionHandlerProxy class.
 *
 * @author Drak <drak@zikula.org>
 *
 * @runTestsInSeparateProcesses
 */
class SessionHandlerProxyTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var \PHPUnit_Framework_MockObject_Matcher
     */
    private $mock;

    /**
     * @var SessionHandlerProxy
     */
    private $proxy;

    protected function setUp()
    {
        $this->mock = $this->getMock('SessionHandlerInterface');
        $this->proxy = new SessionHandlerProxy($this->mock);
    }

    protected function tearDown()
    {
        $this->mock = null;
        $this->proxy = null;
    }

    public function testOpen()
    {
        $this->mock->expects($this->once())
            ->method('open')
            ->will($this->returnValue(true));

        $this->assertFalse($this->proxy->isActive());
        $this->proxy->open('name', 'id');
        if (version_compare(phpversion(), '5.4.0', '<')) {
            $this->assertTrue($this->proxy->isActive());
        } else {
            $this->assertFalse($this->proxy->isActive());
        }
    }

    public function testOpenFalse()
    {
        $this->mock->expects($this->once())
            ->method('open')
            ->will($this->returnValue(false));

        $this->assertFalse($this->proxy->isActive());
        $this->proxy->open('name', 'id');
        $this->assertFalse($this->proxy->isActive());
    }

    public function testClose()
    {
        $this->mock->expects($this->once())
            ->method('close')
            ->will($this->returnValue(true));

        $this->assertFalse($this->proxy->isActive());
        $this->proxy->close();
        $this->assertFalse($this->proxy->isActive());
    }

    public function testCloseFalse()
    {
        $this->mock->expects($this->once())
            ->method('close')
            ->will($this->returnValue(false));

        $this->assertFalse($this->proxy->isActive());
        $this->proxy->close();
        $this->assertFalse($this->proxy->isActive());
    }

    public function testRead()
    {
        $this->mock->expects($this->once())
            ->method('read');

        $this->proxy->read('id');
    }

    public function testWrite()
    {
        $this->mock->expects($this->once())
            ->method('write');

        $this->proxy->write('id', 'data');
    }

    public function testDestroy()
    {
        $this->mock->expects($this->once())
            ->method('destroy');

        $this->proxy->destroy('id');
    }

    public function testGc()
    {
        $this->mock->expects($this->once())
            ->method('gc');

        $this->proxy->gc(86400);
    }
}
PK��ZT �S��^test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/MetadataBagTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests\Session\Storage;

use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag;

/**
 * Test class for MetadataBag.
 */
class MetadataBagTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var MetadataBag
     */
    protected $bag;

    /**
     * @var array
     */
    protected $array = array();

    protected function setUp()
    {
        $this->bag = new MetadataBag();
        $this->array = array(MetadataBag::CREATED => 1234567, MetadataBag::UPDATED => 12345678, MetadataBag::LIFETIME => 0);
        $this->bag->initialize($this->array);
    }

    protected function tearDown()
    {
        $this->array = array();
        $this->bag = null;
    }

    public function testInitialize()
    {
        $sessionMetadata = array();

        $bag1 = new MetadataBag();
        $bag1->initialize($sessionMetadata);
        $this->assertGreaterThanOrEqual(time(), $bag1->getCreated());
        $this->assertEquals($bag1->getCreated(), $bag1->getLastUsed());

        sleep(1);
        $bag2 = new MetadataBag();
        $bag2->initialize($sessionMetadata);
        $this->assertEquals($bag1->getCreated(), $bag2->getCreated());
        $this->assertEquals($bag1->getLastUsed(), $bag2->getLastUsed());
        $this->assertEquals($bag2->getCreated(), $bag2->getLastUsed());

        sleep(1);
        $bag3 = new MetadataBag();
        $bag3->initialize($sessionMetadata);
        $this->assertEquals($bag1->getCreated(), $bag3->getCreated());
        $this->assertGreaterThan($bag2->getLastUsed(), $bag3->getLastUsed());
        $this->assertNotEquals($bag3->getCreated(), $bag3->getLastUsed());
    }

    public function testGetSetName()
    {
        $this->assertEquals('__metadata', $this->bag->getName());
        $this->bag->setName('foo');
        $this->assertEquals('foo', $this->bag->getName());

    }

    public function testGetStorageKey()
    {
        $this->assertEquals('_sf2_meta', $this->bag->getStorageKey());
    }

    public function testGetLifetime()
    {
        $bag = new MetadataBag();
        $array = array(MetadataBag::CREATED => 1234567, MetadataBag::UPDATED => 12345678, MetadataBag::LIFETIME => 1000);
        $bag->initialize($array);
        $this->assertEquals(1000, $bag->getLifetime());
    }

    public function testGetCreated()
    {
        $this->assertEquals(1234567, $this->bag->getCreated());
    }

    public function testGetLastUsed()
    {
        $this->assertLessThanOrEqual(time(), $this->bag->getLastUsed());
    }

    public function testClear()
    {
        $this->bag->clear();
    }

    public function testSkipLastUsedUpdate()
    {
        $bag = new MetadataBag('', 30);
        $timeStamp = time();

        $created = $timeStamp - 15;
        $sessionMetadata = array(
            MetadataBag::CREATED => $created,
            MetadataBag::UPDATED => $created,
            MetadataBag::LIFETIME => 1000
        );
        $bag->initialize($sessionMetadata);

        $this->assertEquals($created, $sessionMetadata[MetadataBag::UPDATED]);
    }

    public function testDoesNotSkipLastUsedUpdate()
    {
        $bag = new MetadataBag('', 30);
        $timeStamp = time();

        $created = $timeStamp - 45;
        $sessionMetadata = array(
            MetadataBag::CREATED => $created,
            MetadataBag::UPDATED => $created,
            MetadataBag::LIFETIME => 1000
        );
        $bag->initialize($sessionMetadata);

        $this->assertEquals($timeStamp, $sessionMetadata[MetadataBag::UPDATED]);
    }
}
PK��Z��7�
�
Stest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/AcceptHeaderItemTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests;

use Symfony\Component\HttpFoundation\AcceptHeaderItem;

class AcceptHeaderItemTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider provideFromStringData
     */
    public function testFromString($string, $value, array $attributes)
    {
        $item = AcceptHeaderItem::fromString($string);
        $this->assertEquals($value, $item->getValue());
        $this->assertEquals($attributes, $item->getAttributes());
    }

    public function provideFromStringData()
    {
        return array(
            array(
                'text/html',
                'text/html', array()
            ),
            array(
                '"this;should,not=matter"',
                'this;should,not=matter', array()
            ),
            array(
                "text/plain; charset=utf-8;param=\"this;should,not=matter\";\tfootnotes=true",
                'text/plain', array('charset' => 'utf-8', 'param' => 'this;should,not=matter', 'footnotes' => 'true')
            ),
            array(
                '"this;should,not=matter";charset=utf-8',
                'this;should,not=matter', array('charset' => 'utf-8')
            ),
        );
    }

    /**
     * @dataProvider provideToStringData
     */
    public function testToString($value, array $attributes, $string)
    {
        $item = new AcceptHeaderItem($value, $attributes);
        $this->assertEquals($string, (string) $item);
    }

    public function provideToStringData()
    {
        return array(
            array(
                'text/html', array(),
                'text/html'
            ),
            array(
                'text/plain', array('charset' => 'utf-8', 'param' => 'this;should,not=matter', 'footnotes' => 'true'),
                'text/plain;charset=utf-8;param="this;should,not=matter";footnotes=true'
            ),
        );
    }

    public function testValue()
    {
        $item = new AcceptHeaderItem('value', array());
        $this->assertEquals('value', $item->getValue());

        $item->setValue('new value');
        $this->assertEquals('new value', $item->getValue());

        $item->setValue(1);
        $this->assertEquals('1', $item->getValue());
    }

    public function testQuality()
    {
        $item = new AcceptHeaderItem('value', array());
        $this->assertEquals(1.0, $item->getQuality());

        $item->setQuality(0.5);
        $this->assertEquals(0.5, $item->getQuality());

        $item->setAttribute('q', 0.75);
        $this->assertEquals(0.75, $item->getQuality());
        $this->assertFalse($item->hasAttribute('q'));
    }

    public function testAttribute()
    {
        $item = new AcceptHeaderItem('value', array());
        $this->assertEquals(array(), $item->getAttributes());
        $this->assertFalse($item->hasAttribute('test'));
        $this->assertNull($item->getAttribute('test'));
        $this->assertEquals('default', $item->getAttribute('test', 'default'));

        $item->setAttribute('test', 'value');
        $this->assertEquals(array('test' => 'value'), $item->getAttributes());
        $this->assertTrue($item->hasAttribute('test'));
        $this->assertEquals('value', $item->getAttribute('test'));
        $this->assertEquals('value', $item->getAttribute('test', 'default'));
    }
}
PK��Z�`k Otest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/JsonResponseTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests;

use Symfony\Component\HttpFoundation\JsonResponse;

class JsonResponseTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructorEmptyCreatesJsonObject()
    {
        $response = new JsonResponse();
        $this->assertSame('{}', $response->getContent());
    }

    public function testConstructorWithArrayCreatesJsonArray()
    {
        $response = new JsonResponse(array(0, 1, 2, 3));
        $this->assertSame('[0,1,2,3]', $response->getContent());
    }

    public function testConstructorWithAssocArrayCreatesJsonObject()
    {
        $response = new JsonResponse(array('foo' => 'bar'));
        $this->assertSame('{"foo":"bar"}', $response->getContent());
    }

    public function testConstructorWithSimpleTypes()
    {
        $response = new JsonResponse('foo');
        $this->assertSame('"foo"', $response->getContent());

        $response = new JsonResponse(0);
        $this->assertSame('0', $response->getContent());

        $response = new JsonResponse(0.1);
        $this->assertSame('0.1', $response->getContent());

        $response = new JsonResponse(true);
        $this->assertSame('true', $response->getContent());
    }

    public function testConstructorWithCustomStatus()
    {
        $response = new JsonResponse(array(), 202);
        $this->assertSame(202, $response->getStatusCode());
    }

    public function testConstructorAddsContentTypeHeader()
    {
        $response = new JsonResponse();
        $this->assertSame('application/json', $response->headers->get('Content-Type'));
    }

    public function testConstructorWithCustomHeaders()
    {
        $response = new JsonResponse(array(), 200, array('ETag' => 'foo'));
        $this->assertSame('application/json', $response->headers->get('Content-Type'));
        $this->assertSame('foo', $response->headers->get('ETag'));
    }

    public function testConstructorWithCustomContentType()
    {
        $headers = array('Content-Type' => 'application/vnd.acme.blog-v1+json');

        $response = new JsonResponse(array(), 200, $headers);
        $this->assertSame('application/vnd.acme.blog-v1+json', $response->headers->get('Content-Type'));
    }

    public function testCreate()
    {
        $response = JsonResponse::create(array('foo' => 'bar'), 204);

        $this->assertInstanceOf('Symfony\Component\HttpFoundation\JsonResponse', $response);
        $this->assertEquals('{"foo":"bar"}', $response->getContent());
        $this->assertEquals(204, $response->getStatusCode());
    }

    public function testStaticCreateEmptyJsonObject()
    {
        $response = JsonResponse::create();
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\JsonResponse', $response);
        $this->assertSame('{}', $response->getContent());
    }

    public function testStaticCreateJsonArray()
    {
        $response = JsonResponse::create(array(0, 1, 2, 3));
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\JsonResponse', $response);
        $this->assertSame('[0,1,2,3]', $response->getContent());
    }

    public function testStaticCreateJsonObject()
    {
        $response = JsonResponse::create(array('foo' => 'bar'));
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\JsonResponse', $response);
        $this->assertSame('{"foo":"bar"}', $response->getContent());
    }

    public function testStaticCreateWithSimpleTypes()
    {
        $response = JsonResponse::create('foo');
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\JsonResponse', $response);
        $this->assertSame('"foo"', $response->getContent());

        $response = JsonResponse::create(0);
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\JsonResponse', $response);
        $this->assertSame('0', $response->getContent());

        $response = JsonResponse::create(0.1);
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\JsonResponse', $response);
        $this->assertSame('0.1', $response->getContent());

        $response = JsonResponse::create(true);
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\JsonResponse', $response);
        $this->assertSame('true', $response->getContent());
    }

    public function testStaticCreateWithCustomStatus()
    {
        $response = JsonResponse::create(array(), 202);
        $this->assertSame(202, $response->getStatusCode());
    }

    public function testStaticCreateAddsContentTypeHeader()
    {
        $response = JsonResponse::create();
        $this->assertSame('application/json', $response->headers->get('Content-Type'));
    }

    public function testStaticCreateWithCustomHeaders()
    {
        $response = JsonResponse::create(array(), 200, array('ETag' => 'foo'));
        $this->assertSame('application/json', $response->headers->get('Content-Type'));
        $this->assertSame('foo', $response->headers->get('ETag'));
    }

    public function testStaticCreateWithCustomContentType()
    {
        $headers = array('Content-Type' => 'application/vnd.acme.blog-v1+json');

        $response = JsonResponse::create(array(), 200, $headers);
        $this->assertSame('application/vnd.acme.blog-v1+json', $response->headers->get('Content-Type'));
    }

    public function testSetCallback()
    {
        $response = JsonResponse::create(array('foo' => 'bar'))->setCallback('callback');

        $this->assertEquals('callback({"foo":"bar"});', $response->getContent());
        $this->assertEquals('text/javascript', $response->headers->get('Content-Type'));
    }

    public function testJsonEncodeFlags()
    {
        $response = new JsonResponse('<>\'&"');

        $this->assertEquals('"\u003C\u003E\u0027\u0026\u0022"', $response->getContent());
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testSetCallbackInvalidIdentifier()
    {
        $response = new JsonResponse('foo');
        $response->setCallback('+invalid');
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testSetContent()
    {
        JsonResponse::create("\xB1\x31");
    }
}
PK��Z�E����Qtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/RequestMatcherTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests;

use Symfony\Component\HttpFoundation\RequestMatcher;
use Symfony\Component\HttpFoundation\Request;

class RequestMatcherTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider testMethodFixtures
     */
    public function testMethod($requestMethod, $matcherMethod, $isMatch)
    {
        $matcher = new RequestMatcher();
        $matcher->matchMethod($matcherMethod);
        $request = Request::create('', $requestMethod);
        $this->assertSame($isMatch, $matcher->matches($request));

        $matcher = new RequestMatcher(null, null, $matcherMethod);
        $request = Request::create('', $requestMethod);
        $this->assertSame($isMatch, $matcher->matches($request));
    }

    public function testMethodFixtures()
    {
        return array(
            array('get', 'get', true),
            array('get', array('get', 'post'), true),
            array('get', 'post', false),
            array('get', 'GET', true),
            array('get', array('GET', 'POST'), true),
            array('get', 'POST', false),
        );
    }

    /**
     * @dataProvider testHostFixture
     */
    public function testHost($pattern, $isMatch)
    {
        $matcher = new RequestMatcher();
        $request = Request::create('', 'get', array(), array(), array(), array('HTTP_HOST' => 'foo.example.com'));

        $matcher->matchHost($pattern);
        $this->assertSame($isMatch, $matcher->matches($request));

        $matcher= new RequestMatcher(null, $pattern);
        $this->assertSame($isMatch, $matcher->matches($request));
    }

    public function testHostFixture()
    {
        return array(
            array('.*\.example\.com', true),
            array('\.example\.com$', true),
            array('^.*\.example\.com$', true),
            array('.*\.sensio\.com', false),
            array('.*\.example\.COM', true),
            array('\.example\.COM$', true),
            array('^.*\.example\.COM$', true),
            array('.*\.sensio\.COM', false),        );
    }

    public function testPath()
    {
        $matcher = new RequestMatcher();

        $request = Request::create('/admin/foo');

        $matcher->matchPath('/admin/.*');
        $this->assertTrue($matcher->matches($request));

        $matcher->matchPath('/admin');
        $this->assertTrue($matcher->matches($request));

        $matcher->matchPath('^/admin/.*$');
        $this->assertTrue($matcher->matches($request));

        $matcher->matchMethod('/blog/.*');
        $this->assertFalse($matcher->matches($request));
    }

    public function testPathWithLocaleIsNotSupported()
    {
        $matcher = new RequestMatcher();
        $request = Request::create('/en/login');
        $request->setLocale('en');

        $matcher->matchPath('^/{_locale}/login$');
        $this->assertFalse($matcher->matches($request));
    }

    public function testPathWithEncodedCharacters()
    {
        $matcher = new RequestMatcher();
        $request = Request::create('/admin/fo%20o');
        $matcher->matchPath('^/admin/fo o*$');
        $this->assertTrue($matcher->matches($request));
    }

    public function testAttributes()
    {
        $matcher = new RequestMatcher();

        $request = Request::create('/admin/foo');
        $request->attributes->set('foo', 'foo_bar');

        $matcher->matchAttribute('foo', 'foo_.*');
        $this->assertTrue($matcher->matches($request));

        $matcher->matchAttribute('foo', 'foo');
        $this->assertTrue($matcher->matches($request));

        $matcher->matchAttribute('foo', '^foo_bar$');
        $this->assertTrue($matcher->matches($request));

        $matcher->matchAttribute('foo', 'babar');
        $this->assertFalse($matcher->matches($request));
    }
}
PK��Z����,�,Ttest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests;

use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Component\HttpFoundation\Cookie;

class ResponseHeaderBagTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Symfony\Component\HttpFoundation\ResponseHeaderBag::allPreserveCase
     * @dataProvider provideAllPreserveCase
     */
    public function testAllPreserveCase($headers, $expected)
    {
        $bag = new ResponseHeaderBag($headers);

        $this->assertEquals($expected, $bag->allPreserveCase(), '->allPreserveCase() gets all input keys in original case');
    }

    public function provideAllPreserveCase()
    {
        return array(
            array(
                array('fOo' => 'BAR'),
                array('fOo' => array('BAR'), 'Cache-Control' => array('no-cache'))
            ),
            array(
                array('ETag' => 'xyzzy'),
                array('ETag' => array('xyzzy'), 'Cache-Control' => array('private, must-revalidate'))
            ),
            array(
                array('Content-MD5' => 'Q2hlY2sgSW50ZWdyaXR5IQ=='),
                array('Content-MD5' => array('Q2hlY2sgSW50ZWdyaXR5IQ=='), 'Cache-Control' => array('no-cache'))
            ),
            array(
                array('P3P' => 'CP="CAO PSA OUR"'),
                array('P3P' => array('CP="CAO PSA OUR"'), 'Cache-Control' => array('no-cache'))
            ),
            array(
                array('WWW-Authenticate' => 'Basic realm="WallyWorld"'),
                array('WWW-Authenticate' => array('Basic realm="WallyWorld"'), 'Cache-Control' => array('no-cache'))
            ),
            array(
                array('X-UA-Compatible' => 'IE=edge,chrome=1'),
                array('X-UA-Compatible' => array('IE=edge,chrome=1'), 'Cache-Control' => array('no-cache'))
            ),
            array(
                array('X-XSS-Protection' => '1; mode=block'),
                array('X-XSS-Protection' => array('1; mode=block'), 'Cache-Control' => array('no-cache'))
            ),
        );
    }

    public function testCacheControlHeader()
    {
        $bag = new ResponseHeaderBag(array());
        $this->assertEquals('no-cache', $bag->get('Cache-Control'));
        $this->assertTrue($bag->hasCacheControlDirective('no-cache'));

        $bag = new ResponseHeaderBag(array('Cache-Control' => 'public'));
        $this->assertEquals('public', $bag->get('Cache-Control'));
        $this->assertTrue($bag->hasCacheControlDirective('public'));

        $bag = new ResponseHeaderBag(array('ETag' => 'abcde'));
        $this->assertEquals('private, must-revalidate', $bag->get('Cache-Control'));
        $this->assertTrue($bag->hasCacheControlDirective('private'));
        $this->assertTrue($bag->hasCacheControlDirective('must-revalidate'));
        $this->assertFalse($bag->hasCacheControlDirective('max-age'));

        $bag = new ResponseHeaderBag(array('Expires' => 'Wed, 16 Feb 2011 14:17:43 GMT'));
        $this->assertEquals('private, must-revalidate', $bag->get('Cache-Control'));

        $bag = new ResponseHeaderBag(array(
            'Expires' => 'Wed, 16 Feb 2011 14:17:43 GMT',
            'Cache-Control' => 'max-age=3600'
        ));
        $this->assertEquals('max-age=3600, private', $bag->get('Cache-Control'));

        $bag = new ResponseHeaderBag(array('Last-Modified' => 'abcde'));
        $this->assertEquals('private, must-revalidate', $bag->get('Cache-Control'));

        $bag = new ResponseHeaderBag(array('Etag' => 'abcde', 'Last-Modified' => 'abcde'));
        $this->assertEquals('private, must-revalidate', $bag->get('Cache-Control'));

        $bag = new ResponseHeaderBag(array('cache-control' => 'max-age=100'));
        $this->assertEquals('max-age=100, private', $bag->get('Cache-Control'));

        $bag = new ResponseHeaderBag(array('cache-control' => 's-maxage=100'));
        $this->assertEquals('s-maxage=100', $bag->get('Cache-Control'));

        $bag = new ResponseHeaderBag(array('cache-control' => 'private, max-age=100'));
        $this->assertEquals('max-age=100, private', $bag->get('Cache-Control'));

        $bag = new ResponseHeaderBag(array('cache-control' => 'public, max-age=100'));
        $this->assertEquals('max-age=100, public', $bag->get('Cache-Control'));

        $bag = new ResponseHeaderBag();
        $bag->set('Last-Modified', 'abcde');
        $this->assertEquals('private, must-revalidate', $bag->get('Cache-Control'));
    }

    public function testToStringIncludesCookieHeaders()
    {
        $bag = new ResponseHeaderBag(array());
        $bag->setCookie(new Cookie('foo', 'bar'));

        $this->assertContains("Set-Cookie: foo=bar; path=/; httponly", explode("\r\n", $bag->__toString()));

        $bag->clearCookie('foo');

        $this->assertContains("Set-Cookie: foo=deleted; expires=".gmdate("D, d-M-Y H:i:s T", time() - 31536001)."; path=/; httponly", explode("\r\n", $bag->__toString()));
    }

    public function testReplace()
    {
        $bag = new ResponseHeaderBag(array());
        $this->assertEquals('no-cache', $bag->get('Cache-Control'));
        $this->assertTrue($bag->hasCacheControlDirective('no-cache'));

        $bag->replace(array('Cache-Control' => 'public'));
        $this->assertEquals('public', $bag->get('Cache-Control'));
        $this->assertTrue($bag->hasCacheControlDirective('public'));
    }

    public function testReplaceWithRemove()
    {
        $bag = new ResponseHeaderBag(array());
        $this->assertEquals('no-cache', $bag->get('Cache-Control'));
        $this->assertTrue($bag->hasCacheControlDirective('no-cache'));

        $bag->remove('Cache-Control');
        $bag->replace(array());
        $this->assertEquals('no-cache', $bag->get('Cache-Control'));
        $this->assertTrue($bag->hasCacheControlDirective('no-cache'));
    }

    public function testCookiesWithSameNames()
    {
        $bag = new ResponseHeaderBag();
        $bag->setCookie(new Cookie('foo', 'bar', 0, '/path/foo', 'foo.bar'));
        $bag->setCookie(new Cookie('foo', 'bar', 0, '/path/bar', 'foo.bar'));
        $bag->setCookie(new Cookie('foo', 'bar', 0, '/path/bar', 'bar.foo'));
        $bag->setCookie(new Cookie('foo', 'bar'));

        $this->assertCount(4, $bag->getCookies());

        $headers = explode("\r\n", $bag->__toString());
        $this->assertContains("Set-Cookie: foo=bar; path=/path/foo; domain=foo.bar; httponly", $headers);
        $this->assertContains("Set-Cookie: foo=bar; path=/path/foo; domain=foo.bar; httponly", $headers);
        $this->assertContains("Set-Cookie: foo=bar; path=/path/bar; domain=bar.foo; httponly", $headers);
        $this->assertContains("Set-Cookie: foo=bar; path=/; httponly", $headers);

        $cookies = $bag->getCookies(ResponseHeaderBag::COOKIES_ARRAY);
        $this->assertTrue(isset($cookies['foo.bar']['/path/foo']['foo']));
        $this->assertTrue(isset($cookies['foo.bar']['/path/bar']['foo']));
        $this->assertTrue(isset($cookies['bar.foo']['/path/bar']['foo']));
        $this->assertTrue(isset($cookies['']['/']['foo']));
    }

    public function testRemoveCookie()
    {
        $bag = new ResponseHeaderBag();
        $bag->setCookie(new Cookie('foo', 'bar', 0, '/path/foo', 'foo.bar'));
        $bag->setCookie(new Cookie('bar', 'foo', 0, '/path/bar', 'foo.bar'));

        $cookies = $bag->getCookies(ResponseHeaderBag::COOKIES_ARRAY);
        $this->assertTrue(isset($cookies['foo.bar']['/path/foo']));

        $bag->removeCookie('foo', '/path/foo', 'foo.bar');

        $cookies = $bag->getCookies(ResponseHeaderBag::COOKIES_ARRAY);
        $this->assertFalse(isset($cookies['foo.bar']['/path/foo']));

        $bag->removeCookie('bar', '/path/bar', 'foo.bar');

        $cookies = $bag->getCookies(ResponseHeaderBag::COOKIES_ARRAY);
        $this->assertFalse(isset($cookies['foo.bar']));
    }

    public function testRemoveCookieWithNullRemove()
    {
        $bag = new ResponseHeaderBag();
        $bag->setCookie(new Cookie('foo', 'bar', 0));
        $bag->setCookie(new Cookie('bar', 'foo', 0));

        $cookies = $bag->getCookies(ResponseHeaderBag::COOKIES_ARRAY);
        $this->assertTrue(isset($cookies['']['/']));

        $bag->removeCookie('foo', null);
        $cookies = $bag->getCookies(ResponseHeaderBag::COOKIES_ARRAY);
        $this->assertFalse(isset($cookies['']['/']['foo']));

        $bag->removeCookie('bar', null);
        $cookies = $bag->getCookies(ResponseHeaderBag::COOKIES_ARRAY);
        $this->assertFalse(isset($cookies['']['/']['bar']));
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testGetCookiesWithInvalidArgument()
    {
        $bag = new ResponseHeaderBag();

        $cookies = $bag->getCookies('invalid_argument');
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testMakeDispositionInvalidDisposition()
    {
        $headers = new ResponseHeaderBag();

        $headers->makeDisposition('invalid', 'foo.html');
    }

    /**
     * @dataProvider provideMakeDisposition
     */
    public function testMakeDisposition($disposition, $filename, $filenameFallback, $expected)
    {
        $headers = new ResponseHeaderBag();

        $this->assertEquals($expected, $headers->makeDisposition($disposition, $filename, $filenameFallback));
    }

    public function testToStringDoesntMessUpHeaders()
    {
        $headers = new ResponseHeaderBag();

        $headers->set('Location', 'http://www.symfony.com');
        $headers->set('Content-type', 'text/html');

        (string) $headers;

        $allHeaders = $headers->allPreserveCase();
        $this->assertEquals(array('http://www.symfony.com'), $allHeaders['Location']);
        $this->assertEquals(array('text/html'), $allHeaders['Content-type']);
    }

    public function provideMakeDisposition()
    {
        return array(
            array('attachment', 'foo.html', 'foo.html', 'attachment; filename="foo.html"'),
            array('attachment', 'foo.html', '', 'attachment; filename="foo.html"'),
            array('attachment', 'foo bar.html', '', 'attachment; filename="foo bar.html"'),
            array('attachment', 'foo "bar".html', '', 'attachment; filename="foo \\"bar\\".html"'),
            array('attachment', 'foo%20bar.html', 'foo bar.html', 'attachment; filename="foo bar.html"; filename*=utf-8\'\'foo%2520bar.html'),
            array('attachment', 'föö.html', 'foo.html', 'attachment; filename="foo.html"; filename*=utf-8\'\'f%C3%B6%C3%B6.html'),
        );
    }

    /**
     * @dataProvider provideMakeDispositionFail
     * @expectedException \InvalidArgumentException
     */
    public function testMakeDispositionFail($disposition, $filename)
    {
        $headers = new ResponseHeaderBag();

        $headers->makeDisposition($disposition, $filename);
    }

    public function provideMakeDispositionFail()
    {
        return array(
            array('attachment', 'foo%20bar.html'),
            array('attachment', 'foo/bar.html'),
            array('attachment', '/foo.html'),
            array('attachment', 'foo\bar.html'),
            array('attachment', '\foo.html'),
            array('attachment', 'föö.html'),
        );
    }
}
PK��Zk\B��r�rKtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ResponseTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class ResponseTest extends ResponseTestCase
{
    public function testCreate()
    {
        $response = Response::create('foo', 301, array('Foo' => 'bar'));

        $this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $response);
        $this->assertEquals(301, $response->getStatusCode());
        $this->assertEquals('bar', $response->headers->get('foo'));
    }

    public function testToString()
    {
        $response = new Response();
        $response = explode("\r\n", $response);
        $this->assertEquals("HTTP/1.0 200 OK", $response[0]);
        $this->assertEquals("Cache-Control: no-cache", $response[1]);
    }

    public function testClone()
    {
        $response = new Response();
        $responseClone = clone $response;
        $this->assertEquals($response, $responseClone);
    }

    public function testSendHeaders()
    {
        $response = new Response();
        $headers = $response->sendHeaders();
        $this->assertObjectHasAttribute('headers', $headers);
        $this->assertObjectHasAttribute('content', $headers);
        $this->assertObjectHasAttribute('version', $headers);
        $this->assertObjectHasAttribute('statusCode', $headers);
        $this->assertObjectHasAttribute('statusText', $headers);
        $this->assertObjectHasAttribute('charset', $headers);
    }

    public function testSend()
    {
        $response = new Response();
        $responseSend = $response->send();
        $this->assertObjectHasAttribute('headers', $responseSend);
        $this->assertObjectHasAttribute('content', $responseSend);
        $this->assertObjectHasAttribute('version', $responseSend);
        $this->assertObjectHasAttribute('statusCode', $responseSend);
        $this->assertObjectHasAttribute('statusText', $responseSend);
        $this->assertObjectHasAttribute('charset', $responseSend);
    }

    public function testGetCharset()
    {
        $response = new Response();
        $charsetOrigin = 'UTF-8';
        $response->setCharset($charsetOrigin);
        $charset = $response->getCharset();
        $this->assertEquals($charsetOrigin, $charset);
    }

    public function testIsCacheable()
    {
        $response = new Response();
        $this->assertFalse($response->isCacheable());
    }

    public function testIsCacheableWithErrorCode()
    {
        $response = new Response('', 500);
        $this->assertFalse($response->isCacheable());
    }

    public function testIsCacheableWithNoStoreDirective()
    {
        $response = new Response();
        $response->headers->set('cache-control', 'private');
        $this->assertFalse($response->isCacheable());
    }

    public function testIsCacheableWithSetTtl()
    {
        $response = new Response();
        $response->setTtl(10);
        $this->assertTrue($response->isCacheable());
    }

    public function testMustRevalidate()
    {
        $response = new Response();
        $this->assertFalse($response->mustRevalidate());
    }

    public function testSetNotModified()
    {
        $response = new Response();
        $modified = $response->setNotModified();
        $this->assertObjectHasAttribute('headers', $modified);
        $this->assertObjectHasAttribute('content', $modified);
        $this->assertObjectHasAttribute('version', $modified);
        $this->assertObjectHasAttribute('statusCode', $modified);
        $this->assertObjectHasAttribute('statusText', $modified);
        $this->assertObjectHasAttribute('charset', $modified);
        $this->assertEquals(304, $modified->getStatusCode());
    }

    public function testIsSuccessful()
    {
        $response = new Response();
        $this->assertTrue($response->isSuccessful());
    }

    public function testIsNotModified()
    {
        $response = new Response();
        $modified = $response->isNotModified(new Request());
        $this->assertFalse($modified);
    }

    public function testIsNotModifiedNotSafe()
    {
        $request = Request::create('/homepage', 'POST');

        $response = new Response();
        $this->assertFalse($response->isNotModified($request));
    }

    public function testIsNotModifiedLastModified()
    {
        $modified = 'Sun, 25 Aug 2013 18:33:31 GMT';

        $request = new Request();
        $request->headers->set('If-Modified-Since', $modified);

        $response = new Response();
        $response->headers->set('Last-Modified', $modified);

        $this->assertTrue($response->isNotModified($request));

        $response->headers->set('Last-Modified', '');
        $this->assertFalse($response->isNotModified($request));
    }

    public function testIsNotModifiedEtag()
    {
        $etagOne = 'randomly_generated_etag';
        $etagTwo = 'randomly_generated_etag_2';

        $request = new Request();
        $request->headers->set('if_none_match', sprintf('%s, %s, %s', $etagOne, $etagTwo, 'etagThree'));

        $response = new Response();

        $response->headers->set('ETag', $etagOne);
        $this->assertTrue($response->isNotModified($request));

        $response->headers->set('ETag', $etagTwo);
        $this->assertTrue($response->isNotModified($request));

        $response->headers->set('ETag', '');
        $this->assertFalse($response->isNotModified($request));
    }

    public function testIsValidateable()
    {
        $response = new Response('', 200, array('Last-Modified' => $this->createDateTimeOneHourAgo()->format(DATE_RFC2822)));
        $this->assertTrue($response->isValidateable(), '->isValidateable() returns true if Last-Modified is present');

        $response = new Response('', 200, array('ETag' => '"12345"'));
        $this->assertTrue($response->isValidateable(), '->isValidateable() returns true if ETag is present');

        $response = new Response();
        $this->assertFalse($response->isValidateable(), '->isValidateable() returns false when no validator is present');
    }

    public function testGetDate()
    {
        $response = new Response('', 200, array('Date' => $this->createDateTimeOneHourAgo()->format(DATE_RFC2822)));
        $this->assertEquals(0, $this->createDateTimeOneHourAgo()->diff($response->getDate())->format('%s'), '->getDate() returns the Date header if present');

        $response = new Response();
        $date = $response->getDate();
        $this->assertLessThan(1, $date->diff(new \DateTime(), true)->format('%s'), '->getDate() returns the current Date if no Date header present');

        $response = new Response('', 200, array('Date' => $this->createDateTimeOneHourAgo()->format(DATE_RFC2822)));
        $now = $this->createDateTimeNow();
        $response->headers->set('Date', $now->format(DATE_RFC2822));
        $this->assertEquals(0, $now->diff($response->getDate())->format('%s'), '->getDate() returns the date when the header has been modified');

        $response = new Response('', 200);
        $response->headers->remove('Date');
        $this->assertInstanceOf('\DateTime', $response->getDate());
    }

    public function testGetMaxAge()
    {
        $response = new Response();
        $response->headers->set('Cache-Control', 's-maxage=600, max-age=0');
        $this->assertEquals(600, $response->getMaxAge(), '->getMaxAge() uses s-maxage cache control directive when present');

        $response = new Response();
        $response->headers->set('Cache-Control', 'max-age=600');
        $this->assertEquals(600, $response->getMaxAge(), '->getMaxAge() falls back to max-age when no s-maxage directive present');

        $response = new Response();
        $response->headers->set('Cache-Control', 'must-revalidate');
        $response->headers->set('Expires', $this->createDateTimeOneHourLater()->format(DATE_RFC2822));
        $this->assertEquals(3600, $response->getMaxAge(), '->getMaxAge() falls back to Expires when no max-age or s-maxage directive present');

        $response = new Response();
        $response->headers->set('Cache-Control', 'must-revalidate');
        $response->headers->set('Expires', -1);
        $this->assertEquals('Sat, 01 Jan 00 00:00:00 +0000', $response->getExpires()->format(DATE_RFC822));

        $response = new Response();
        $this->assertNull($response->getMaxAge(), '->getMaxAge() returns null if no freshness information available');
    }

    public function testSetSharedMaxAge()
    {
        $response = new Response();
        $response->setSharedMaxAge(20);

        $cacheControl = $response->headers->get('Cache-Control');
        $this->assertEquals('public, s-maxage=20', $cacheControl);
    }

    public function testIsPrivate()
    {
        $response = new Response();
        $response->headers->set('Cache-Control', 'max-age=100');
        $response->setPrivate();
        $this->assertEquals(100, $response->headers->getCacheControlDirective('max-age'), '->isPrivate() adds the private Cache-Control directive when set to true');
        $this->assertTrue($response->headers->getCacheControlDirective('private'), '->isPrivate() adds the private Cache-Control directive when set to true');

        $response = new Response();
        $response->headers->set('Cache-Control', 'public, max-age=100');
        $response->setPrivate();
        $this->assertEquals(100, $response->headers->getCacheControlDirective('max-age'), '->isPrivate() adds the private Cache-Control directive when set to true');
        $this->assertTrue($response->headers->getCacheControlDirective('private'), '->isPrivate() adds the private Cache-Control directive when set to true');
        $this->assertFalse($response->headers->hasCacheControlDirective('public'), '->isPrivate() removes the public Cache-Control directive');
    }

    public function testExpire()
    {
        $response = new Response();
        $response->headers->set('Cache-Control', 'max-age=100');
        $response->expire();
        $this->assertEquals(100, $response->headers->get('Age'), '->expire() sets the Age to max-age when present');

        $response = new Response();
        $response->headers->set('Cache-Control', 'max-age=100, s-maxage=500');
        $response->expire();
        $this->assertEquals(500, $response->headers->get('Age'), '->expire() sets the Age to s-maxage when both max-age and s-maxage are present');

        $response = new Response();
        $response->headers->set('Cache-Control', 'max-age=5, s-maxage=500');
        $response->headers->set('Age', '1000');
        $response->expire();
        $this->assertEquals(1000, $response->headers->get('Age'), '->expire() does nothing when the response is already stale/expired');

        $response = new Response();
        $response->expire();
        $this->assertFalse($response->headers->has('Age'), '->expire() does nothing when the response does not include freshness information');

        $response = new Response();
        $response->headers->set('Expires', -1);
        $response->expire();
        $this->assertNull($response->headers->get('Age'), '->expire() does not set the Age when the response is expired');
    }

    public function testGetTtl()
    {
        $response = new Response();
        $this->assertNull($response->getTtl(), '->getTtl() returns null when no Expires or Cache-Control headers are present');

        $response = new Response();
        $response->headers->set('Expires', $this->createDateTimeOneHourLater()->format(DATE_RFC2822));
        $this->assertLessThan(1, 3600 - $response->getTtl(), '->getTtl() uses the Expires header when no max-age is present');

        $response = new Response();
        $response->headers->set('Expires', $this->createDateTimeOneHourAgo()->format(DATE_RFC2822));
        $this->assertLessThan(0, $response->getTtl(), '->getTtl() returns negative values when Expires is in past');

        $response = new Response();
        $response->headers->set('Expires', $response->getDate()->format(DATE_RFC2822));
        $response->headers->set('Age', 0);
        $this->assertSame(0, $response->getTtl(), '->getTtl() correctly handles zero');

        $response = new Response();
        $response->headers->set('Cache-Control', 'max-age=60');
        $this->assertLessThan(1, 60 - $response->getTtl(), '->getTtl() uses Cache-Control max-age when present');
    }

    public function testSetClientTtl()
    {
        $response = new Response();
        $response->setClientTtl(10);

        $this->assertEquals($response->getMaxAge(), $response->getAge() + 10);
    }

    public function testGetSetProtocolVersion()
    {
        $response = new Response();

        $this->assertEquals('1.0', $response->getProtocolVersion());

        $response->setProtocolVersion('1.1');

        $this->assertEquals('1.1', $response->getProtocolVersion());
    }

    public function testGetVary()
    {
        $response = new Response();
        $this->assertEquals(array(), $response->getVary(), '->getVary() returns an empty array if no Vary header is present');

        $response = new Response();
        $response->headers->set('Vary', 'Accept-Language');
        $this->assertEquals(array('Accept-Language'), $response->getVary(), '->getVary() parses a single header name value');

        $response = new Response();
        $response->headers->set('Vary', 'Accept-Language User-Agent    X-Foo');
        $this->assertEquals(array('Accept-Language', 'User-Agent', 'X-Foo'), $response->getVary(), '->getVary() parses multiple header name values separated by spaces');

        $response = new Response();
        $response->headers->set('Vary', 'Accept-Language,User-Agent,    X-Foo');
        $this->assertEquals(array('Accept-Language', 'User-Agent', 'X-Foo'), $response->getVary(), '->getVary() parses multiple header name values separated by commas');

        $vary = array('Accept-Language', 'User-Agent', 'X-foo');

        $response = new Response();
        $response->headers->set('Vary', $vary);
        $this->assertEquals($vary, $response->getVary(), '->getVary() parses multiple header name values in arrays');

        $response = new Response();
        $response->headers->set('Vary', 'Accept-Language, User-Agent, X-foo');
        $this->assertEquals($vary, $response->getVary(), '->getVary() parses multiple header name values in arrays');
    }

    public function testSetVary()
    {
        $response = new Response();
        $response->setVary('Accept-Language');
        $this->assertEquals(array('Accept-Language'), $response->getVary());

        $response->setVary('Accept-Language, User-Agent');
        $this->assertEquals(array('Accept-Language', 'User-Agent'), $response->getVary(), '->setVary() replace the vary header by default');

        $response->setVary('X-Foo', false);
        $this->assertEquals(array('Accept-Language', 'User-Agent', 'X-Foo'), $response->getVary(), '->setVary() doesn\'t wipe out earlier Vary headers if replace is set to false');
    }

    public function testDefaultContentType()
    {
        $headerMock = $this->getMock('Symfony\Component\HttpFoundation\ResponseHeaderBag', array('set'));
        $headerMock->expects($this->at(0))
            ->method('set')
            ->with('Content-Type', 'text/html');
        $headerMock->expects($this->at(1))
            ->method('set')
            ->with('Content-Type', 'text/html; charset=UTF-8');

        $response = new Response('foo');
        $response->headers = $headerMock;

        $response->prepare(new Request());
    }

    public function testContentTypeCharset()
    {
        $response = new Response();
        $response->headers->set('Content-Type', 'text/css');

        // force fixContentType() to be called
        $response->prepare(new Request());

        $this->assertEquals('text/css; charset=UTF-8', $response->headers->get('Content-Type'));
    }

    public function testPrepareDoesNothingIfContentTypeIsSet()
    {
        $response = new Response('foo');
        $response->headers->set('Content-Type', 'text/plain');

        $response->prepare(new Request());

        $this->assertEquals('text/plain; charset=UTF-8', $response->headers->get('content-type'));
    }

    public function testPrepareDoesNothingIfRequestFormatIsNotDefined()
    {
        $response = new Response('foo');

        $response->prepare(new Request());

        $this->assertEquals('text/html; charset=UTF-8', $response->headers->get('content-type'));
    }

    public function testPrepareSetContentType()
    {
        $response = new Response('foo');
        $request = Request::create('/');
        $request->setRequestFormat('json');

        $response->prepare($request);

        $this->assertEquals('application/json', $response->headers->get('content-type'));
    }

    public function testPrepareRemovesContentForHeadRequests()
    {
        $response = new Response('foo');
        $request = Request::create('/', 'HEAD');

        $length = 12345;
        $response->headers->set('Content-Length', $length);
        $response->prepare($request);

        $this->assertEquals('', $response->getContent());
        $this->assertEquals($length, $response->headers->get('Content-Length'), 'Content-Length should be as if it was GET; see RFC2616 14.13');
    }

    public function testPrepareRemovesContentForInformationalResponse()
    {
        $response = new Response('foo');
        $request = Request::create('/');

        $response->setContent('content');
        $response->setStatusCode(101);
        $response->prepare($request);
        $this->assertEquals('', $response->getContent());

        $response->setContent('content');
        $response->setStatusCode(304);
        $response->prepare($request);
        $this->assertEquals('', $response->getContent());
    }

    public function testPrepareRemovesContentLength()
    {
        $response = new Response('foo');
        $request = Request::create('/');

        $response->headers->set('Content-Length', 12345);
        $response->prepare($request);
        $this->assertEquals(12345, $response->headers->get('Content-Length'));

        $response->headers->set('Transfer-Encoding', 'chunked');
        $response->prepare($request);
        $this->assertFalse($response->headers->has('Content-Length'));
    }

    public function testPrepareSetsPragmaOnHttp10Only()
    {
        $request = Request::create('/', 'GET');
        $request->server->set('SERVER_PROTOCOL', 'HTTP/1.0');

        $response = new Response('foo');
        $response->prepare($request);
        $this->assertEquals('no-cache', $response->headers->get('pragma'));
        $this->assertEquals('-1', $response->headers->get('expires'));

        $request->server->set('SERVER_PROTOCOL', 'HTTP/1.1');
        $response = new Response('foo');
        $response->prepare($request);
        $this->assertFalse($response->headers->has('pragma'));
        $this->assertFalse($response->headers->has('expires'));
    }

    public function testSetCache()
    {
        $response = new Response();
        //array('etag', 'last_modified', 'max_age', 's_maxage', 'private', 'public')
        try {
            $response->setCache(array("wrong option" => "value"));
            $this->fail('->setCache() throws an InvalidArgumentException if an option is not supported');
        } catch (\Exception $e) {
            $this->assertInstanceOf('InvalidArgumentException', $e, '->setCache() throws an InvalidArgumentException if an option is not supported');
            $this->assertContains('"wrong option"', $e->getMessage());
        }

        $options = array('etag' => '"whatever"');
        $response->setCache($options);
        $this->assertEquals($response->getEtag(), '"whatever"');

        $now = new \DateTime();
        $options = array('last_modified' => $now);
        $response->setCache($options);
        $this->assertEquals($response->getLastModified()->getTimestamp(), $now->getTimestamp());

        $options = array('max_age' => 100);
        $response->setCache($options);
        $this->assertEquals($response->getMaxAge(), 100);

        $options = array('s_maxage' => 200);
        $response->setCache($options);
        $this->assertEquals($response->getMaxAge(), 200);

        $this->assertTrue($response->headers->hasCacheControlDirective('public'));
        $this->assertFalse($response->headers->hasCacheControlDirective('private'));

        $response->setCache(array('public' => true));
        $this->assertTrue($response->headers->hasCacheControlDirective('public'));
        $this->assertFalse($response->headers->hasCacheControlDirective('private'));

        $response->setCache(array('public' => false));
        $this->assertFalse($response->headers->hasCacheControlDirective('public'));
        $this->assertTrue($response->headers->hasCacheControlDirective('private'));

        $response->setCache(array('private' => true));
        $this->assertFalse($response->headers->hasCacheControlDirective('public'));
        $this->assertTrue($response->headers->hasCacheControlDirective('private'));

        $response->setCache(array('private' => false));
        $this->assertTrue($response->headers->hasCacheControlDirective('public'));
        $this->assertFalse($response->headers->hasCacheControlDirective('private'));
    }

    public function testSendContent()
    {
        $response = new Response('test response rendering', 200);

        ob_start();
        $response->sendContent();
        $string = ob_get_clean();
        $this->assertContains('test response rendering', $string);
    }

    public function testSetPublic()
    {
        $response = new Response();
        $response->setPublic();

        $this->assertTrue($response->headers->hasCacheControlDirective('public'));
        $this->assertFalse($response->headers->hasCacheControlDirective('private'));
    }

    public function testSetExpires()
    {
        $response = new Response();
        $response->setExpires(null);

        $this->assertNull($response->getExpires(), '->setExpires() remove the header when passed null');

        $now = new \DateTime();
        $response->setExpires($now);

        $this->assertEquals($response->getExpires()->getTimestamp(), $now->getTimestamp());
    }

    public function testSetLastModified()
    {
        $response = new Response();
        $response->setLastModified(new \DateTime());
        $this->assertNotNull($response->getLastModified());

        $response->setLastModified(null);
        $this->assertNull($response->getLastModified());
    }

    public function testIsInvalid()
    {
        $response = new Response();

        try {
            $response->setStatusCode(99);
            $this->fail();
        } catch (\InvalidArgumentException $e) {
            $this->assertTrue($response->isInvalid());
        }

        try {
            $response->setStatusCode(650);
            $this->fail();
        } catch (\InvalidArgumentException $e) {
            $this->assertTrue($response->isInvalid());
        }

        $response = new Response('', 200);
        $this->assertFalse($response->isInvalid());
    }

    /**
     * @dataProvider getStatusCodeFixtures
     */
    public function testSetStatusCode($code, $text, $expectedText)
    {
        $response = new Response();

        $response->setStatusCode($code, $text);

        $statusText = new \ReflectionProperty($response, 'statusText');
        $statusText->setAccessible(true);

        $this->assertEquals($expectedText, $statusText->getValue($response));
    }

    public function getStatusCodeFixtures()
    {
        return array(
            array('200', null, 'OK'),
            array('200', false, ''),
            array('200', 'foo', 'foo'),
            array('199', null, ''),
            array('199', false, ''),
            array('199', 'foo', 'foo')
        );
    }

    public function testIsInformational()
    {
        $response = new Response('', 100);
        $this->assertTrue($response->isInformational());

        $response = new Response('', 200);
        $this->assertFalse($response->isInformational());
    }

    public function testIsRedirectRedirection()
    {
        foreach (array(301, 302, 303, 307) as $code) {
            $response = new Response('', $code);
            $this->assertTrue($response->isRedirection());
            $this->assertTrue($response->isRedirect());
        }

        $response = new Response('', 304);
        $this->assertTrue($response->isRedirection());
        $this->assertFalse($response->isRedirect());

        $response = new Response('', 200);
        $this->assertFalse($response->isRedirection());
        $this->assertFalse($response->isRedirect());

        $response = new Response('', 404);
        $this->assertFalse($response->isRedirection());
        $this->assertFalse($response->isRedirect());

        $response = new Response('', 301, array('Location' => '/good-uri'));
        $this->assertFalse($response->isRedirect('/bad-uri'));
        $this->assertTrue($response->isRedirect('/good-uri'));
    }

    public function testIsNotFound()
    {
        $response = new Response('', 404);
        $this->assertTrue($response->isNotFound());

        $response = new Response('', 200);
        $this->assertFalse($response->isNotFound());
    }

    public function testIsEmpty()
    {
        foreach (array(201, 204, 304) as $code) {
            $response = new Response('', $code);
            $this->assertTrue($response->isEmpty());
        }

        $response = new Response('', 200);
        $this->assertFalse($response->isEmpty());
    }

    public function testIsForbidden()
    {
        $response = new Response('', 403);
        $this->assertTrue($response->isForbidden());

        $response = new Response('', 200);
        $this->assertFalse($response->isForbidden());
    }

    public function testIsOk()
    {
        $response = new Response('', 200);
        $this->assertTrue($response->isOk());

        $response = new Response('', 404);
        $this->assertFalse($response->isOk());
    }

    public function testIsServerOrClientError()
    {
        $response = new Response('', 404);
        $this->assertTrue($response->isClientError());
        $this->assertFalse($response->isServerError());

        $response = new Response('', 500);
        $this->assertFalse($response->isClientError());
        $this->assertTrue($response->isServerError());
    }

    public function testHasVary()
    {
        $response = new Response();
        $this->assertFalse($response->hasVary());

        $response->setVary('User-Agent');
        $this->assertTrue($response->hasVary());
    }

    public function testSetEtag()
    {
        $response = new Response('', 200, array('ETag' => '"12345"'));
        $response->setEtag();

        $this->assertNull($response->headers->get('Etag'), '->setEtag() removes Etags when call with null');
    }

    /**
     * @dataProvider validContentProvider
     */
    public function testSetContent($content)
    {
        $response = new Response();
        $response->setContent($content);
        $this->assertEquals((string) $content, $response->getContent());
    }

    /**
     * @expectedException \UnexpectedValueException
     * @dataProvider invalidContentProvider
     */
    public function testSetContentInvalid($content)
    {
        $response = new Response();
        $response->setContent($content);
    }

    public function testSettersAreChainable()
    {
        $response = new Response();

        $setters = array(
            'setProtocolVersion' => '1.0',
            'setCharset' => 'UTF-8',
            'setPublic' => null,
            'setPrivate' => null,
            'setDate' => new \DateTime(),
            'expire' => null,
            'setMaxAge' => 1,
            'setSharedMaxAge' => 1,
            'setTtl' => 1,
            'setClientTtl' => 1,
        );

        foreach ($setters as $setter => $arg) {
            $this->assertEquals($response, $response->{$setter}($arg));
        }
    }

    public function validContentProvider()
    {
        return array(
            'obj'    => array(new StringableObject()),
            'string' => array('Foo'),
            'int'    => array(2),
        );
    }

    public function invalidContentProvider()
    {
        return array(
            'obj'   => array(new \stdClass),
            'array' => array(array()),
            'bool'   => array(true, '1'),
        );
    }

    protected function createDateTimeOneHourAgo()
    {
        $date = new \DateTime();

        return $date->sub(new \DateInterval('PT1H'));
    }

    protected function createDateTimeOneHourLater()
    {
        $date = new \DateTime();

        return $date->add(new \DateInterval('PT1H'));
    }

    protected function createDateTimeNow()
    {
        return new \DateTime();
    }

    protected function provideResponse()
    {
        return new Response();
    }
}

class StringableObject
{
    public function __toString()
    {
        return 'Foo';
    }
}
PK��ZAk�B#B#Otest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ParameterBagTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests;

use Symfony\Component\HttpFoundation\ParameterBag;

class ParameterBagTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Symfony\Component\HttpFoundation\ParameterBag::__construct
     */
    public function testConstructor()
    {
        $this->testAll();
    }

    /**
     * @covers Symfony\Component\HttpFoundation\ParameterBag::all
     */
    public function testAll()
    {
        $bag = new ParameterBag(array('foo' => 'bar'));
        $this->assertEquals(array('foo' => 'bar'), $bag->all(), '->all() gets all the input');
    }

    public function testKeys()
    {
        $bag = new ParameterBag(array('foo' => 'bar'));
        $this->assertEquals(array('foo'), $bag->keys());
    }

    public function testAdd()
    {
        $bag = new ParameterBag(array('foo' => 'bar'));
        $bag->add(array('bar' => 'bas'));
        $this->assertEquals(array('foo' => 'bar', 'bar' => 'bas'), $bag->all());
    }

    public function testRemove()
    {
        $bag = new ParameterBag(array('foo' => 'bar'));
        $bag->add(array('bar' => 'bas'));
        $this->assertEquals(array('foo' => 'bar', 'bar' => 'bas'), $bag->all());
        $bag->remove('bar');
        $this->assertEquals(array('foo' => 'bar'), $bag->all());
    }

    /**
     * @covers Symfony\Component\HttpFoundation\ParameterBag::replace
     */
    public function testReplace()
    {
        $bag = new ParameterBag(array('foo' => 'bar'));

        $bag->replace(array('FOO' => 'BAR'));
        $this->assertEquals(array('FOO' => 'BAR'), $bag->all(), '->replace() replaces the input with the argument');
        $this->assertFalse($bag->has('foo'), '->replace() overrides previously set the input');
    }

    /**
     * @covers Symfony\Component\HttpFoundation\ParameterBag::get
     */
    public function testGet()
    {
        $bag = new ParameterBag(array('foo' => 'bar', 'null' => null));

        $this->assertEquals('bar', $bag->get('foo'), '->get() gets the value of a parameter');
        $this->assertEquals('default', $bag->get('unknown', 'default'), '->get() returns second argument as default if a parameter is not defined');
        $this->assertNull($bag->get('null', 'default'), '->get() returns null if null is set');
    }

    public function testGetDoesNotUseDeepByDefault()
    {
        $bag = new ParameterBag(array('foo' => array('bar' => 'moo')));

        $this->assertNull($bag->get('foo[bar]'));
    }

    /**
     * @dataProvider getInvalidPaths
     * @expectedException \InvalidArgumentException
     */
    public function testGetDeepWithInvalidPaths($path)
    {
        $bag = new ParameterBag(array('foo' => array('bar' => 'moo')));

        $bag->get($path, null, true);
    }

    public function getInvalidPaths()
    {
        return array(
            array('foo[['),
            array('foo[d'),
            array('foo[bar]]'),
            array('foo[bar]d'),
        );
    }

    public function testGetDeep()
    {
        $bag = new ParameterBag(array('foo' => array('bar' => array('moo' => 'boo'))));

        $this->assertEquals(array('moo' => 'boo'), $bag->get('foo[bar]', null, true));
        $this->assertEquals('boo', $bag->get('foo[bar][moo]', null, true));
        $this->assertEquals('default', $bag->get('foo[bar][foo]', 'default', true));
        $this->assertEquals('default', $bag->get('bar[moo][foo]', 'default', true));
    }

    /**
     * @covers Symfony\Component\HttpFoundation\ParameterBag::set
     */
    public function testSet()
    {
        $bag = new ParameterBag(array());

        $bag->set('foo', 'bar');
        $this->assertEquals('bar', $bag->get('foo'), '->set() sets the value of parameter');

        $bag->set('foo', 'baz');
        $this->assertEquals('baz', $bag->get('foo'), '->set() overrides previously set parameter');
    }

    /**
     * @covers Symfony\Component\HttpFoundation\ParameterBag::has
     */
    public function testHas()
    {
        $bag = new ParameterBag(array('foo' => 'bar'));

        $this->assertTrue($bag->has('foo'), '->has() returns true if a parameter is defined');
        $this->assertFalse($bag->has('unknown'), '->has() return false if a parameter is not defined');
    }

    /**
     * @covers Symfony\Component\HttpFoundation\ParameterBag::getAlpha
     */
    public function testGetAlpha()
    {
        $bag = new ParameterBag(array('word' => 'foo_BAR_012'));

        $this->assertEquals('fooBAR', $bag->getAlpha('word'), '->getAlpha() gets only alphabetic characters');
        $this->assertEquals('', $bag->getAlpha('unknown'), '->getAlpha() returns empty string if a parameter is not defined');
    }

    /**
     * @covers Symfony\Component\HttpFoundation\ParameterBag::getAlnum
     */
    public function testGetAlnum()
    {
        $bag = new ParameterBag(array('word' => 'foo_BAR_012'));

        $this->assertEquals('fooBAR012', $bag->getAlnum('word'), '->getAlnum() gets only alphanumeric characters');
        $this->assertEquals('', $bag->getAlnum('unknown'), '->getAlnum() returns empty string if a parameter is not defined');
    }

    /**
     * @covers Symfony\Component\HttpFoundation\ParameterBag::getDigits
     */
    public function testGetDigits()
    {
        $bag = new ParameterBag(array('word' => 'foo_BAR_012'));

        $this->assertEquals('012', $bag->getDigits('word'), '->getDigits() gets only digits as string');
        $this->assertEquals('', $bag->getDigits('unknown'), '->getDigits() returns empty string if a parameter is not defined');
    }

    /**
     * @covers Symfony\Component\HttpFoundation\ParameterBag::getInt
     */
    public function testGetInt()
    {
        $bag = new ParameterBag(array('digits' => '0123'));

        $this->assertEquals(123, $bag->getInt('digits'), '->getInt() gets a value of parameter as integer');
        $this->assertEquals(0, $bag->getInt('unknown'), '->getInt() returns zero if a parameter is not defined');
    }

    /**
     * @covers Symfony\Component\HttpFoundation\ParameterBag::filter
     */
    public function testFilter()
    {
        $bag = new ParameterBag(array(
            'digits' => '0123ab',
            'email' => 'example@example.com',
            'url' => 'http://example.com/foo',
            'dec' => '256',
            'hex' => '0x100',
            'array' => array('bang'),
            ));

        $this->assertEmpty($bag->filter('nokey'), '->filter() should return empty by default if no key is found');

        $this->assertEquals('0123', $bag->filter('digits', '', false, FILTER_SANITIZE_NUMBER_INT), '->filter() gets a value of parameter as integer filtering out invalid characters');

        $this->assertEquals('example@example.com', $bag->filter('email', '', false, FILTER_VALIDATE_EMAIL), '->filter() gets a value of parameter as email');

        $this->assertEquals('http://example.com/foo', $bag->filter('url', '', false, FILTER_VALIDATE_URL, array('flags' => FILTER_FLAG_PATH_REQUIRED)), '->filter() gets a value of parameter as URL with a path');

        // This test is repeated for code-coverage
        $this->assertEquals('http://example.com/foo', $bag->filter('url', '', false, FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED), '->filter() gets a value of parameter as URL with a path');

        $this->assertFalse($bag->filter('dec', '', false, FILTER_VALIDATE_INT, array(
            'flags'   => FILTER_FLAG_ALLOW_HEX,
            'options' => array('min_range' => 1, 'max_range' => 0xff))
                ), '->filter() gets a value of parameter as integer between boundaries');

        $this->assertFalse($bag->filter('hex', '', false, FILTER_VALIDATE_INT, array(
            'flags'   => FILTER_FLAG_ALLOW_HEX,
            'options' => array('min_range' => 1, 'max_range' => 0xff))
                ), '->filter() gets a value of parameter as integer between boundaries');

        $this->assertEquals(array('bang'), $bag->filter('array', '', false), '->filter() gets a value of parameter as an array');

    }

    /**
     * @covers Symfony\Component\HttpFoundation\ParameterBag::getIterator
     */
    public function testGetIterator()
    {
        $parameters = array('foo' => 'bar', 'hello' => 'world');
        $bag = new ParameterBag($parameters);

        $i = 0;
        foreach ($bag as $key => $val) {
            $i++;
            $this->assertEquals($parameters[$key], $val);
        }

        $this->assertEquals(count($parameters), $i);
    }

    /**
     * @covers Symfony\Component\HttpFoundation\ParameterBag::count
     */
    public function testCount()
    {
        $parameters = array('foo' => 'bar', 'hello' => 'world');
        $bag = new ParameterBag($parameters);

        $this->assertEquals(count($parameters), count($bag));
    }
}
PK��Z��q��Jtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/RequestTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests;

use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Request;

class RequestTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Symfony\Component\HttpFoundation\Request::__construct
     */
    public function testConstructor()
    {
        $this->testInitialize();
    }

    /**
     * @covers Symfony\Component\HttpFoundation\Request::initialize
     */
    public function testInitialize()
    {
        $request = new Request();

        $request->initialize(array('foo' => 'bar'));
        $this->assertEquals('bar', $request->query->get('foo'), '->initialize() takes an array of query parameters as its first argument');

        $request->initialize(array(), array('foo' => 'bar'));
        $this->assertEquals('bar', $request->request->get('foo'), '->initialize() takes an array of request parameters as its second argument');

        $request->initialize(array(), array(), array('foo' => 'bar'));
        $this->assertEquals('bar', $request->attributes->get('foo'), '->initialize() takes an array of attributes as its third argument');

        $request->initialize(array(), array(), array(), array(), array(), array('HTTP_FOO' => 'bar'));
        $this->assertEquals('bar', $request->headers->get('FOO'), '->initialize() takes an array of HTTP headers as its fourth argument');
    }

    public function testGetLocale()
    {
        $request = new Request();
        $request->setLocale('pl');
        $locale = $request->getLocale();
        $this->assertEquals('pl', $locale);
    }

    public function testGetUser()
    {
        $request = Request::create('http://user_test:password_test@test.com/');
        $user = $request->getUser();

        $this->assertEquals('user_test', $user);
    }

    public function testGetPassword()
    {
        $request = Request::create('http://user_test:password_test@test.com/');
        $password = $request->getPassword();

        $this->assertEquals('password_test', $password);
    }

    public function testIsNoCache()
    {
        $request = new Request();
        $isNoCache = $request->isNoCache();

        $this->assertFalse($isNoCache);
    }

    public function testGetContentType()
    {
        $request = new Request();
        $contentType = $request->getContentType();

        $this->assertNull($contentType);
    }

    public function testSetDefaultLocale()
    {
        $request = new Request();
        $request->setDefaultLocale('pl');
        $locale = $request->getLocale();

        $this->assertEquals('pl', $locale);
    }

    /**
     * @covers Symfony\Component\HttpFoundation\Request::create
     */
    public function testCreate()
    {
        $request = Request::create('http://test.com/foo?bar=baz');
        $this->assertEquals('http://test.com/foo?bar=baz', $request->getUri());
        $this->assertEquals('/foo', $request->getPathInfo());
        $this->assertEquals('bar=baz', $request->getQueryString());
        $this->assertEquals(80, $request->getPort());
        $this->assertEquals('test.com', $request->getHttpHost());
        $this->assertFalse($request->isSecure());

        $request = Request::create('http://test.com/foo', 'GET', array('bar' => 'baz'));
        $this->assertEquals('http://test.com/foo?bar=baz', $request->getUri());
        $this->assertEquals('/foo', $request->getPathInfo());
        $this->assertEquals('bar=baz', $request->getQueryString());
        $this->assertEquals(80, $request->getPort());
        $this->assertEquals('test.com', $request->getHttpHost());
        $this->assertFalse($request->isSecure());

        $request = Request::create('http://test.com/foo?bar=foo', 'GET', array('bar' => 'baz'));
        $this->assertEquals('http://test.com/foo?bar=baz', $request->getUri());
        $this->assertEquals('/foo', $request->getPathInfo());
        $this->assertEquals('bar=baz', $request->getQueryString());
        $this->assertEquals(80, $request->getPort());
        $this->assertEquals('test.com', $request->getHttpHost());
        $this->assertFalse($request->isSecure());

        $request = Request::create('https://test.com/foo?bar=baz');
        $this->assertEquals('https://test.com/foo?bar=baz', $request->getUri());
        $this->assertEquals('/foo', $request->getPathInfo());
        $this->assertEquals('bar=baz', $request->getQueryString());
        $this->assertEquals(443, $request->getPort());
        $this->assertEquals('test.com', $request->getHttpHost());
        $this->assertTrue($request->isSecure());

        $request = Request::create('test.com:90/foo');
        $this->assertEquals('http://test.com:90/foo', $request->getUri());
        $this->assertEquals('/foo', $request->getPathInfo());
        $this->assertEquals('test.com', $request->getHost());
        $this->assertEquals('test.com:90', $request->getHttpHost());
        $this->assertEquals(90, $request->getPort());
        $this->assertFalse($request->isSecure());

        $request = Request::create('https://test.com:90/foo');
        $this->assertEquals('https://test.com:90/foo', $request->getUri());
        $this->assertEquals('/foo', $request->getPathInfo());
        $this->assertEquals('test.com', $request->getHost());
        $this->assertEquals('test.com:90', $request->getHttpHost());
        $this->assertEquals(90, $request->getPort());
        $this->assertTrue($request->isSecure());

        $request = Request::create('https://127.0.0.1:90/foo');
        $this->assertEquals('https://127.0.0.1:90/foo', $request->getUri());
        $this->assertEquals('/foo', $request->getPathInfo());
        $this->assertEquals('127.0.0.1', $request->getHost());
        $this->assertEquals('127.0.0.1:90', $request->getHttpHost());
        $this->assertEquals(90, $request->getPort());
        $this->assertTrue($request->isSecure());

        $request = Request::create('https://[::1]:90/foo');
        $this->assertEquals('https://[::1]:90/foo', $request->getUri());
        $this->assertEquals('/foo', $request->getPathInfo());
        $this->assertEquals('[::1]', $request->getHost());
        $this->assertEquals('[::1]:90', $request->getHttpHost());
        $this->assertEquals(90, $request->getPort());
        $this->assertTrue($request->isSecure());

        $json = '{"jsonrpc":"2.0","method":"echo","id":7,"params":["Hello World"]}';
        $request = Request::create('http://example.com/jsonrpc', 'POST', array(), array(), array(), array(), $json);
        $this->assertEquals($json, $request->getContent());
        $this->assertFalse($request->isSecure());

        $request = Request::create('http://test.com');
        $this->assertEquals('http://test.com/', $request->getUri());
        $this->assertEquals('/', $request->getPathInfo());
        $this->assertEquals('', $request->getQueryString());
        $this->assertEquals(80, $request->getPort());
        $this->assertEquals('test.com', $request->getHttpHost());
        $this->assertFalse($request->isSecure());

        $request = Request::create('http://test.com?test=1');
        $this->assertEquals('http://test.com/?test=1', $request->getUri());
        $this->assertEquals('/', $request->getPathInfo());
        $this->assertEquals('test=1', $request->getQueryString());
        $this->assertEquals(80, $request->getPort());
        $this->assertEquals('test.com', $request->getHttpHost());
        $this->assertFalse($request->isSecure());

        $request = Request::create('http://test.com:90/?test=1');
        $this->assertEquals('http://test.com:90/?test=1', $request->getUri());
        $this->assertEquals('/', $request->getPathInfo());
        $this->assertEquals('test=1', $request->getQueryString());
        $this->assertEquals(90, $request->getPort());
        $this->assertEquals('test.com:90', $request->getHttpHost());
        $this->assertFalse($request->isSecure());

        $request = Request::create('http://test:test@test.com');
        $this->assertEquals('http://test.com/', $request->getUri());
        $this->assertEquals('/', $request->getPathInfo());
        $this->assertEquals('', $request->getQueryString());
        $this->assertEquals(80, $request->getPort());
        $this->assertEquals('test.com', $request->getHttpHost());
        $this->assertEquals('test', $request->getUser());
        $this->assertEquals('test', $request->getPassword());
        $this->assertFalse($request->isSecure());

        $request = Request::create('http://testnopass@test.com');
        $this->assertEquals('http://test.com/', $request->getUri());
        $this->assertEquals('/', $request->getPathInfo());
        $this->assertEquals('', $request->getQueryString());
        $this->assertEquals(80, $request->getPort());
        $this->assertEquals('test.com', $request->getHttpHost());
        $this->assertEquals('testnopass', $request->getUser());
        $this->assertNull($request->getPassword());
        $this->assertFalse($request->isSecure());

        $request = Request::create('http://test.com/?foo');
        $this->assertEquals('/?foo', $request->getRequestUri());
        $this->assertEquals(array('foo' => ''), $request->query->all());
    }

    /**
     * @covers Symfony\Component\HttpFoundation\Request::create
     */
    public function testCreateCheckPrecedence()
    {
        // server is used by default
        $request = Request::create('/', 'DELETE', array(), array(), array(), array(
            'HTTP_HOST'     => 'example.com',
            'HTTPS'         => 'on',
            'SERVER_PORT'   => 443,
            'PHP_AUTH_USER' => 'fabien',
            'PHP_AUTH_PW'   => 'pa$$',
            'QUERY_STRING'  => 'foo=bar',
            'CONTENT_TYPE'  => 'application/json',
        ));
        $this->assertEquals('example.com', $request->getHost());
        $this->assertEquals(443, $request->getPort());
        $this->assertTrue($request->isSecure());
        $this->assertEquals('fabien', $request->getUser());
        $this->assertEquals('pa$$', $request->getPassword());
        $this->assertEquals('', $request->getQueryString());
        $this->assertEquals('application/json', $request->headers->get('CONTENT_TYPE'));

        // URI has precedence over server
        $request = Request::create('http://thomas:pokemon@example.net:8080/?foo=bar', 'GET', array(), array(), array(), array(
            'HTTP_HOST'   => 'example.com',
            'HTTPS'       => 'on',
            'SERVER_PORT' => 443,
        ));
        $this->assertEquals('example.net', $request->getHost());
        $this->assertEquals(8080, $request->getPort());
        $this->assertFalse($request->isSecure());
        $this->assertEquals('thomas', $request->getUser());
        $this->assertEquals('pokemon', $request->getPassword());
        $this->assertEquals('foo=bar', $request->getQueryString());
    }

    public function testDuplicate()
    {
        $request = new Request(array('foo' => 'bar'), array('foo' => 'bar'), array('foo' => 'bar'), array(), array(), array('HTTP_FOO' => 'bar'));
        $dup = $request->duplicate();

        $this->assertEquals($request->query->all(), $dup->query->all(), '->duplicate() duplicates a request an copy the current query parameters');
        $this->assertEquals($request->request->all(), $dup->request->all(), '->duplicate() duplicates a request an copy the current request parameters');
        $this->assertEquals($request->attributes->all(), $dup->attributes->all(), '->duplicate() duplicates a request an copy the current attributes');
        $this->assertEquals($request->headers->all(), $dup->headers->all(), '->duplicate() duplicates a request an copy the current HTTP headers');

        $dup = $request->duplicate(array('foo' => 'foobar'), array('foo' => 'foobar'), array('foo' => 'foobar'), array(), array(), array('HTTP_FOO' => 'foobar'));

        $this->assertEquals(array('foo' => 'foobar'), $dup->query->all(), '->duplicate() overrides the query parameters if provided');
        $this->assertEquals(array('foo' => 'foobar'), $dup->request->all(), '->duplicate() overrides the request parameters if provided');
        $this->assertEquals(array('foo' => 'foobar'), $dup->attributes->all(), '->duplicate() overrides the attributes if provided');
        $this->assertEquals(array('foo' => array('foobar')), $dup->headers->all(), '->duplicate() overrides the HTTP header if provided');
    }

    public function testDuplicateWithFormat()
    {
        $request = new Request(array(), array(), array('_format' => 'json'));
        $dup = $request->duplicate();

        $this->assertEquals('json', $dup->getRequestFormat());
        $this->assertEquals('json', $dup->attributes->get('_format'));

        $request = new Request();
        $request->setRequestFormat('xml');
        $dup = $request->duplicate();

        $this->assertEquals('xml', $dup->getRequestFormat());
    }

    /**
     * @covers Symfony\Component\HttpFoundation\Request::getFormat
     * @covers Symfony\Component\HttpFoundation\Request::setFormat
     * @dataProvider getFormatToMimeTypeMapProvider
     */
    public function testGetFormatFromMimeType($format, $mimeTypes)
    {
        $request = new Request();
        foreach ($mimeTypes as $mime) {
            $this->assertEquals($format, $request->getFormat($mime));
        }
        $request->setFormat($format, $mimeTypes);
        foreach ($mimeTypes as $mime) {
            $this->assertEquals($format, $request->getFormat($mime));
        }
    }

    /**
     * @covers Symfony\Component\HttpFoundation\Request::getFormat
     */
    public function testGetFormatFromMimeTypeWithParameters()
    {
        $request = new Request();
        $this->assertEquals('json', $request->getFormat('application/json; charset=utf-8'));
    }

    /**
     * @covers Symfony\Component\HttpFoundation\Request::getMimeType
     * @dataProvider getFormatToMimeTypeMapProvider
     */
    public function testGetMimeTypeFromFormat($format, $mimeTypes)
    {
        if (null !== $format) {
            $request = new Request();
            $this->assertEquals($mimeTypes[0], $request->getMimeType($format));
        }
    }

    public function getFormatToMimeTypeMapProvider()
    {
        return array(
            array(null, array(null, 'unexistent-mime-type')),
            array('txt', array('text/plain')),
            array('js', array('application/javascript', 'application/x-javascript', 'text/javascript')),
            array('css', array('text/css')),
            array('json', array('application/json', 'application/x-json')),
            array('xml', array('text/xml', 'application/xml', 'application/x-xml')),
            array('rdf', array('application/rdf+xml')),
            array('atom',array('application/atom+xml')),
        );
    }

    /**
     * @covers Symfony\Component\HttpFoundation\Request::getUri
     */
    public function testGetUri()
    {
        $server = array();

        // Standard Request on non default PORT
        // http://host:8080/index.php/path/info?query=string

        $server['HTTP_HOST'] = 'host:8080';
        $server['SERVER_NAME'] = 'servername';
        $server['SERVER_PORT'] = '8080';

        $server['QUERY_STRING'] = 'query=string';
        $server['REQUEST_URI'] = '/index.php/path/info?query=string';
        $server['SCRIPT_NAME'] = '/index.php';
        $server['PATH_INFO'] = '/path/info';
        $server['PATH_TRANSLATED'] = 'redirect:/index.php/path/info';
        $server['PHP_SELF'] = '/index_dev.php/path/info';
        $server['SCRIPT_FILENAME'] = '/some/where/index.php';

        $request = new Request();

        $request->initialize(array(), array(), array(), array(), array(), $server);

        $this->assertEquals('http://host:8080/index.php/path/info?query=string', $request->getUri(), '->getUri() with non default port');

        // Use std port number
        $server['HTTP_HOST'] = 'host';
        $server['SERVER_NAME'] = 'servername';
        $server['SERVER_PORT'] = '80';

        $request->initialize(array(), array(), array(), array(), array(), $server);

        $this->assertEquals('http://host/index.php/path/info?query=string', $request->getUri(), '->getUri() with default port');

        // Without HOST HEADER
        unset($server['HTTP_HOST']);
        $server['SERVER_NAME'] = 'servername';
        $server['SERVER_PORT'] = '80';

        $request->initialize(array(), array(), array(), array(), array(), $server);

        $this->assertEquals('http://servername/index.php/path/info?query=string', $request->getUri(), '->getUri() with default port without HOST_HEADER');

        // Request with URL REWRITING (hide index.php)
        //   RewriteCond %{REQUEST_FILENAME} !-f
        //   RewriteRule ^(.*)$ index.php [QSA,L]
        // http://host:8080/path/info?query=string
        $server = array();
        $server['HTTP_HOST'] = 'host:8080';
        $server['SERVER_NAME'] = 'servername';
        $server['SERVER_PORT'] = '8080';

        $server['REDIRECT_QUERY_STRING'] = 'query=string';
        $server['REDIRECT_URL'] = '/path/info';
        $server['SCRIPT_NAME'] = '/index.php';
        $server['QUERY_STRING'] = 'query=string';
        $server['REQUEST_URI'] = '/path/info?toto=test&1=1';
        $server['SCRIPT_NAME'] = '/index.php';
        $server['PHP_SELF'] = '/index.php';
        $server['SCRIPT_FILENAME'] = '/some/where/index.php';

        $request->initialize(array(), array(), array(), array(), array(), $server);
        $this->assertEquals('http://host:8080/path/info?query=string', $request->getUri(), '->getUri() with rewrite');

        // Use std port number
        //  http://host/path/info?query=string
        $server['HTTP_HOST'] = 'host';
        $server['SERVER_NAME'] = 'servername';
        $server['SERVER_PORT'] = '80';

        $request->initialize(array(), array(), array(), array(), array(), $server);

        $this->assertEquals('http://host/path/info?query=string', $request->getUri(), '->getUri() with rewrite and default port');

        // Without HOST HEADER
        unset($server['HTTP_HOST']);
        $server['SERVER_NAME'] = 'servername';
        $server['SERVER_PORT'] = '80';

        $request->initialize(array(), array(), array(), array(), array(), $server);

        $this->assertEquals('http://servername/path/info?query=string', $request->getUri(), '->getUri() with rewrite, default port without HOST_HEADER');

        // With encoded characters

        $server = array(
            'HTTP_HOST'       => 'host:8080',
            'SERVER_NAME'     => 'servername',
            'SERVER_PORT'     => '8080',
            'QUERY_STRING'    => 'query=string',
            'REQUEST_URI'     => '/ba%20se/index_dev.php/foo%20bar/in+fo?query=string',
            'SCRIPT_NAME'     => '/ba se/index_dev.php',
            'PATH_TRANSLATED' => 'redirect:/index.php/foo bar/in+fo',
            'PHP_SELF'        => '/ba se/index_dev.php/path/info',
            'SCRIPT_FILENAME' => '/some/where/ba se/index_dev.php',
        );

        $request->initialize(array(), array(), array(), array(), array(), $server);

        $this->assertEquals(
            'http://host:8080/ba%20se/index_dev.php/foo%20bar/in+fo?query=string',
            $request->getUri()
        );

        // with user info

        $server['PHP_AUTH_USER'] = 'fabien';
        $request->initialize(array(), array(), array(), array(), array(), $server);
        $this->assertEquals('http://host:8080/ba%20se/index_dev.php/foo%20bar/in+fo?query=string', $request->getUri());

        $server['PHP_AUTH_PW'] = 'symfony';
        $request->initialize(array(), array(), array(), array(), array(), $server);
        $this->assertEquals('http://host:8080/ba%20se/index_dev.php/foo%20bar/in+fo?query=string', $request->getUri());
    }

    /**
     * @covers Symfony\Component\HttpFoundation\Request::getUriForPath
     */
    public function testGetUriForPath()
    {
        $request = Request::create('http://test.com/foo?bar=baz');
        $this->assertEquals('http://test.com/some/path', $request->getUriForPath('/some/path'));

        $request = Request::create('http://test.com:90/foo?bar=baz');
        $this->assertEquals('http://test.com:90/some/path', $request->getUriForPath('/some/path'));

        $request = Request::create('https://test.com/foo?bar=baz');
        $this->assertEquals('https://test.com/some/path', $request->getUriForPath('/some/path'));

        $request = Request::create('https://test.com:90/foo?bar=baz');
        $this->assertEquals('https://test.com:90/some/path', $request->getUriForPath('/some/path'));

        $server = array();

        // Standard Request on non default PORT
        // http://host:8080/index.php/path/info?query=string

        $server['HTTP_HOST'] = 'host:8080';
        $server['SERVER_NAME'] = 'servername';
        $server['SERVER_PORT'] = '8080';

        $server['QUERY_STRING'] = 'query=string';
        $server['REQUEST_URI'] = '/index.php/path/info?query=string';
        $server['SCRIPT_NAME'] = '/index.php';
        $server['PATH_INFO'] = '/path/info';
        $server['PATH_TRANSLATED'] = 'redirect:/index.php/path/info';
        $server['PHP_SELF'] = '/index_dev.php/path/info';
        $server['SCRIPT_FILENAME'] = '/some/where/index.php';

        $request = new Request();

        $request->initialize(array(), array(), array(), array(), array(),$server);

        $this->assertEquals('http://host:8080/index.php/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with non default port');

        // Use std port number
        $server['HTTP_HOST'] = 'host';
        $server['SERVER_NAME'] = 'servername';
        $server['SERVER_PORT'] = '80';

        $request->initialize(array(), array(), array(), array(), array(), $server);

        $this->assertEquals('http://host/index.php/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with default port');

        // Without HOST HEADER
        unset($server['HTTP_HOST']);
        $server['SERVER_NAME'] = 'servername';
        $server['SERVER_PORT'] = '80';

        $request->initialize(array(), array(), array(), array(), array(), $server);

        $this->assertEquals('http://servername/index.php/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with default port without HOST_HEADER');

        // Request with URL REWRITING (hide index.php)
        //   RewriteCond %{REQUEST_FILENAME} !-f
        //   RewriteRule ^(.*)$ index.php [QSA,L]
        // http://host:8080/path/info?query=string
        $server = array();
        $server['HTTP_HOST'] = 'host:8080';
        $server['SERVER_NAME'] = 'servername';
        $server['SERVER_PORT'] = '8080';

        $server['REDIRECT_QUERY_STRING'] = 'query=string';
        $server['REDIRECT_URL'] = '/path/info';
        $server['SCRIPT_NAME'] = '/index.php';
        $server['QUERY_STRING'] = 'query=string';
        $server['REQUEST_URI'] = '/path/info?toto=test&1=1';
        $server['SCRIPT_NAME'] = '/index.php';
        $server['PHP_SELF'] = '/index.php';
        $server['SCRIPT_FILENAME'] = '/some/where/index.php';

        $request->initialize(array(), array(), array(), array(), array(), $server);
        $this->assertEquals('http://host:8080/some/path', $request->getUriForPath('/some/path'), '->getUri() with rewrite');

        // Use std port number
        //  http://host/path/info?query=string
        $server['HTTP_HOST'] = 'host';
        $server['SERVER_NAME'] = 'servername';
        $server['SERVER_PORT'] = '80';

        $request->initialize(array(), array(), array(), array(), array(), $server);

        $this->assertEquals('http://host/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with rewrite and default port');

        // Without HOST HEADER
        unset($server['HTTP_HOST']);
        $server['SERVER_NAME'] = 'servername';
        $server['SERVER_PORT'] = '80';

        $request->initialize(array(), array(), array(), array(), array(), $server);

        $this->assertEquals('http://servername/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with rewrite, default port without HOST_HEADER');
        $this->assertEquals('servername', $request->getHttpHost());

        // with user info

        $server['PHP_AUTH_USER'] = 'fabien';
        $request->initialize(array(), array(), array(), array(), array(), $server);
        $this->assertEquals('http://servername/some/path', $request->getUriForPath('/some/path'));

        $server['PHP_AUTH_PW'] = 'symfony';
        $request->initialize(array(), array(), array(), array(), array(), $server);
        $this->assertEquals('http://servername/some/path', $request->getUriForPath('/some/path'));
    }

    /**
     * @covers Symfony\Component\HttpFoundation\Request::getUserInfo
     */
    public function testGetUserInfo()
    {
        $request = new Request();

        $server['PHP_AUTH_USER'] = 'fabien';
        $request->initialize(array(), array(), array(), array(), array(), $server);
        $this->assertEquals('fabien', $request->getUserInfo());

        $server['PHP_AUTH_USER'] = '0';
        $request->initialize(array(), array(), array(), array(), array(), $server);
        $this->assertEquals('0', $request->getUserInfo());

        $server['PHP_AUTH_PW'] = '0';
        $request->initialize(array(), array(), array(), array(), array(), $server);
        $this->assertEquals('0:0', $request->getUserInfo());
    }

    /**
     * @covers Symfony\Component\HttpFoundation\Request::getSchemeAndHttpHost
     */
    public function testGetSchemeAndHttpHost()
    {
        $request = new Request();

        $server = array();
        $server['SERVER_NAME'] = 'servername';
        $server['SERVER_PORT'] = '90';
        $request->initialize(array(), array(), array(), array(), array(), $server);
        $this->assertEquals('http://servername:90', $request->getSchemeAndHttpHost());

        $server['PHP_AUTH_USER'] = 'fabien';
        $request->initialize(array(), array(), array(), array(), array(), $server);
        $this->assertEquals('http://servername:90', $request->getSchemeAndHttpHost());

        $server['PHP_AUTH_USER'] = '0';
        $request->initialize(array(), array(), array(), array(), array(), $server);
        $this->assertEquals('http://servername:90', $request->getSchemeAndHttpHost());

        $server['PHP_AUTH_PW'] = '0';
        $request->initialize(array(), array(), array(), array(), array(), $server);
        $this->assertEquals('http://servername:90', $request->getSchemeAndHttpHost());
    }

    /**
     * @covers Symfony\Component\HttpFoundation\Request::getQueryString
     * @covers Symfony\Component\HttpFoundation\Request::normalizeQueryString
     * @dataProvider getQueryStringNormalizationData
     */
    public function testGetQueryString($query, $expectedQuery, $msg)
    {
        $request = new Request();

        $request->server->set('QUERY_STRING', $query);
        $this->assertSame($expectedQuery, $request->getQueryString(), $msg);
    }

    public function getQueryStringNormalizationData()
    {
        return array(
            array('foo', 'foo', 'works with valueless parameters'),
            array('foo=', 'foo=', 'includes a dangling equal sign'),
            array('bar=&foo=bar', 'bar=&foo=bar', '->works with empty parameters'),
            array('foo=bar&bar=', 'bar=&foo=bar', 'sorts keys alphabetically'),

            // GET parameters, that are submitted from a HTML form, encode spaces as "+" by default (as defined in enctype application/x-www-form-urlencoded).
            // PHP also converts "+" to spaces when filling the global _GET or when using the function parse_str.
            array('him=John%20Doe&her=Jane+Doe', 'her=Jane%20Doe&him=John%20Doe', 'normalizes spaces in both encodings "%20" and "+"'),

            array('foo[]=1&foo[]=2', 'foo%5B%5D=1&foo%5B%5D=2', 'allows array notation'),
            array('foo=1&foo=2', 'foo=1&foo=2', 'allows repeated parameters'),
            array('pa%3Dram=foo%26bar%3Dbaz&test=test', 'pa%3Dram=foo%26bar%3Dbaz&test=test', 'works with encoded delimiters'),
            array('0', '0', 'allows "0"'),
            array('Jane Doe&John%20Doe', 'Jane%20Doe&John%20Doe', 'normalizes encoding in keys'),
            array('her=Jane Doe&him=John%20Doe', 'her=Jane%20Doe&him=John%20Doe', 'normalizes encoding in values'),
            array('foo=bar&&&test&&', 'foo=bar&test', 'removes unneeded delimiters'),
            array('formula=e=m*c^2', 'formula=e%3Dm%2Ac%5E2', 'correctly treats only the first "=" as delimiter and the next as value'),

            // Ignore pairs with empty key, even if there was a value, e.g. "=value", as such nameless values cannot be retrieved anyway.
            // PHP also does not include them when building _GET.
            array('foo=bar&=a=b&=x=y', 'foo=bar', 'removes params with empty key'),
        );
    }

    public function testGetQueryStringReturnsNull()
    {
        $request = new Request();

        $this->assertNull($request->getQueryString(), '->getQueryString() returns null for non-existent query string');

        $request->server->set('QUERY_STRING', '');
        $this->assertNull($request->getQueryString(), '->getQueryString() returns null for empty query string');
    }

    public function testGetHost()
    {
        $request = new Request();

        $request->initialize(array('foo' => 'bar'));
        $this->assertEquals('', $request->getHost(), '->getHost() return empty string if not initialized');

        $request->initialize(array(), array(), array(), array(), array(), array('HTTP_HOST' => 'www.example.com'));
        $this->assertEquals('www.example.com', $request->getHost(), '->getHost() from Host Header');

        // Host header with port number
        $request->initialize(array(), array(), array(), array(), array(), array('HTTP_HOST' => 'www.example.com:8080'));
        $this->assertEquals('www.example.com', $request->getHost(), '->getHost() from Host Header with port number');

        // Server values
        $request->initialize(array(), array(), array(), array(), array(), array('SERVER_NAME' => 'www.example.com'));
        $this->assertEquals('www.example.com', $request->getHost(), '->getHost() from server name');

        $request->initialize(array(), array(), array(), array(), array(), array('SERVER_NAME' => 'www.example.com', 'HTTP_HOST' => 'www.host.com'));
        $this->assertEquals('www.host.com', $request->getHost(), '->getHost() value from Host header has priority over SERVER_NAME ');
    }

    public function testGetPort()
    {
        $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
            'HTTP_X_FORWARDED_PROTO' => 'https',
            'HTTP_X_FORWARDED_PORT' => '443'
        ));
        $port = $request->getPort();

        $this->assertEquals(80, $port, 'Without trusted proxies FORWARDED_PROTO and FORWARDED_PORT are ignored.');

        Request::setTrustedProxies(array('1.1.1.1'));
        $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
            'HTTP_X_FORWARDED_PROTO' => 'https',
            'HTTP_X_FORWARDED_PORT'  => '8443'
        ));
        $port = $request->getPort();

        $this->assertEquals(8443, $port, 'With PROTO and PORT set PORT takes precedence.');

        $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
            'HTTP_X_FORWARDED_PROTO' => 'https'
        ));
        $port = $request->getPort();

        $this->assertEquals(443, $port, 'With only PROTO set getPort() defaults to 443.');

        $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
            'HTTP_X_FORWARDED_PROTO' => 'http'
        ));
        $port = $request->getPort();

        $this->assertEquals(80, $port, 'If X_FORWARDED_PROTO is set to HTTP return 80.');

        $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
            'HTTP_X_FORWARDED_PROTO' => 'On'
        ));
        $port = $request->getPort();
        $this->assertEquals(443, $port, 'With only PROTO set and value is On, getPort() defaults to 443.');

        $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
            'HTTP_X_FORWARDED_PROTO' => '1'
        ));
        $port = $request->getPort();
        $this->assertEquals(443, $port, 'With only PROTO set and value is 1, getPort() defaults to 443.');

        $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
            'HTTP_X_FORWARDED_PROTO' => 'something-else'
        ));
        $port = $request->getPort();
        $this->assertEquals(80, $port, 'With only PROTO set and value is not recognized, getPort() defaults to 80.');

        Request::setTrustedProxies(array());
    }

    /**
     * @expectedException \RuntimeException
     */
    public function testGetHostWithFakeHttpHostValue()
    {
        $request = new Request();
        $request->initialize(array(), array(), array(), array(), array(), array('HTTP_HOST' => 'www.host.com?query=string'));
        $request->getHost();
    }

    /**
     * @covers Symfony\Component\HttpFoundation\Request::setMethod
     * @covers Symfony\Component\HttpFoundation\Request::getMethod
     */
    public function testGetSetMethod()
    {
        $request = new Request();

        $this->assertEquals('GET', $request->getMethod(), '->getMethod() returns GET if no method is defined');

        $request->setMethod('get');
        $this->assertEquals('GET', $request->getMethod(), '->getMethod() returns an uppercased string');

        $request->setMethod('PURGE');
        $this->assertEquals('PURGE', $request->getMethod(), '->getMethod() returns the method even if it is not a standard one');

        $request->setMethod('POST');
        $this->assertEquals('POST', $request->getMethod(), '->getMethod() returns the method POST if no _method is defined');

        $request->setMethod('POST');
        $request->request->set('_method', 'purge');
        $this->assertEquals('POST', $request->getMethod(), '->getMethod() does not return the method from _method if defined and POST but support not enabled');

        $request = new Request();
        $request->setMethod('POST');
        $request->request->set('_method', 'purge');

        $this->assertFalse(Request::getHttpMethodParameterOverride(), 'httpMethodParameterOverride should be disabled by default');

        Request::enableHttpMethodParameterOverride();

        $this->assertTrue(Request::getHttpMethodParameterOverride(), 'httpMethodParameterOverride should be enabled now but it is not');

        $this->assertEquals('PURGE', $request->getMethod(), '->getMethod() returns the method from _method if defined and POST');
        $this->disableHttpMethodParameterOverride();

        $request = new Request();
        $request->setMethod('POST');
        $request->query->set('_method', 'purge');
        $this->assertEquals('POST', $request->getMethod(), '->getMethod() does not return the method from _method if defined and POST but support not enabled');

        $request = new Request();
        $request->setMethod('POST');
        $request->query->set('_method', 'purge');
        Request::enableHttpMethodParameterOverride();
        $this->assertEquals('PURGE', $request->getMethod(), '->getMethod() returns the method from _method if defined and POST');
        $this->disableHttpMethodParameterOverride();

        $request = new Request();
        $request->setMethod('POST');
        $request->headers->set('X-HTTP-METHOD-OVERRIDE', 'delete');
        $this->assertEquals('DELETE', $request->getMethod(), '->getMethod() returns the method from X-HTTP-Method-Override even though _method is set if defined and POST');

        $request = new Request();
        $request->setMethod('POST');
        $request->headers->set('X-HTTP-METHOD-OVERRIDE', 'delete');
        $this->assertEquals('DELETE', $request->getMethod(), '->getMethod() returns the method from X-HTTP-Method-Override if defined and POST');
    }

    /**
     * @dataProvider testGetClientIpsProvider
     */
    public function testGetClientIp($expected, $remoteAddr, $httpForwardedFor, $trustedProxies)
    {
        $request = $this->getRequestInstanceForClientIpTests($remoteAddr, $httpForwardedFor, $trustedProxies);

        $this->assertEquals($expected[0], $request->getClientIp());

        Request::setTrustedProxies(array());
    }

    /**
     * @dataProvider testGetClientIpsProvider
     */
    public function testGetClientIps($expected, $remoteAddr, $httpForwardedFor, $trustedProxies)
    {
        $request = $this->getRequestInstanceForClientIpTests($remoteAddr, $httpForwardedFor, $trustedProxies);

        $this->assertEquals($expected, $request->getClientIps());

        Request::setTrustedProxies(array());
    }

    public function testGetClientIpsProvider()
    {
        //        $expected                   $remoteAddr                $httpForwardedFor            $trustedProxies
        return array(
            // simple IPv4
            array(array('88.88.88.88'),              '88.88.88.88',              null,                        null),
            // trust the IPv4 remote addr
            array(array('88.88.88.88'),              '88.88.88.88',              null,                        array('88.88.88.88')),

            // simple IPv6
            array(array('::1'),                      '::1',                      null,                        null),
            // trust the IPv6 remote addr
            array(array('::1'),                      '::1',                      null,                        array('::1')),

            // forwarded for with remote IPv4 addr not trusted
            array(array('127.0.0.1'),                '127.0.0.1',                '88.88.88.88',               null),
            // forwarded for with remote IPv4 addr trusted
            array(array('88.88.88.88'),              '127.0.0.1',                '88.88.88.88',               array('127.0.0.1')),
            // forwarded for with remote IPv4 and all FF addrs trusted
            array(array('88.88.88.88'),              '127.0.0.1',                '88.88.88.88',               array('127.0.0.1', '88.88.88.88')),
            // forwarded for with remote IPv4 range trusted
            array(array('88.88.88.88'),              '123.45.67.89',             '88.88.88.88',               array('123.45.67.0/24')),

            // forwarded for with remote IPv6 addr not trusted
            array(array('1620:0:1cfe:face:b00c::3'), '1620:0:1cfe:face:b00c::3', '2620:0:1cfe:face:b00c::3',  null),
            // forwarded for with remote IPv6 addr trusted
            array(array('2620:0:1cfe:face:b00c::3'), '1620:0:1cfe:face:b00c::3', '2620:0:1cfe:face:b00c::3',  array('1620:0:1cfe:face:b00c::3')),
            // forwarded for with remote IPv6 range trusted
            array(array('88.88.88.88'),              '2a01:198:603:0:396e:4789:8e99:890f', '88.88.88.88',     array('2a01:198:603:0::/65')),

            // multiple forwarded for with remote IPv4 addr trusted
            array(array('88.88.88.88', '87.65.43.21', '127.0.0.1'), '123.45.67.89', '127.0.0.1, 87.65.43.21, 88.88.88.88', array('123.45.67.89')),
            // multiple forwarded for with remote IPv4 addr and some reverse proxies trusted
            array(array('87.65.43.21', '127.0.0.1'), '123.45.67.89',             '127.0.0.1, 87.65.43.21, 88.88.88.88', array('123.45.67.89', '88.88.88.88')),
            // multiple forwarded for with remote IPv4 addr and some reverse proxies trusted but in the middle
            array(array('88.88.88.88', '127.0.0.1'), '123.45.67.89',             '127.0.0.1, 87.65.43.21, 88.88.88.88', array('123.45.67.89', '87.65.43.21')),
            // multiple forwarded for with remote IPv4 addr and all reverse proxies trusted
            array(array('127.0.0.1'),                '123.45.67.89',             '127.0.0.1, 87.65.43.21, 88.88.88.88', array('123.45.67.89', '87.65.43.21', '88.88.88.88', '127.0.0.1')),

            // multiple forwarded for with remote IPv6 addr trusted
            array(array('2620:0:1cfe:face:b00c::3', '3620:0:1cfe:face:b00c::3'), '1620:0:1cfe:face:b00c::3', '3620:0:1cfe:face:b00c::3,2620:0:1cfe:face:b00c::3', array('1620:0:1cfe:face:b00c::3')),
            // multiple forwarded for with remote IPv6 addr and some reverse proxies trusted
            array(array('3620:0:1cfe:face:b00c::3'), '1620:0:1cfe:face:b00c::3', '3620:0:1cfe:face:b00c::3,2620:0:1cfe:face:b00c::3', array('1620:0:1cfe:face:b00c::3', '2620:0:1cfe:face:b00c::3')),
            // multiple forwarded for with remote IPv4 addr and some reverse proxies trusted but in the middle
            array(array('2620:0:1cfe:face:b00c::3', '4620:0:1cfe:face:b00c::3'), '1620:0:1cfe:face:b00c::3', '4620:0:1cfe:face:b00c::3,3620:0:1cfe:face:b00c::3,2620:0:1cfe:face:b00c::3', array('1620:0:1cfe:face:b00c::3', '3620:0:1cfe:face:b00c::3')),
        );
    }

    public function testGetContentWorksTwiceInDefaultMode()
    {
        $req = new Request();
        $this->assertEquals('', $req->getContent());
        $this->assertEquals('', $req->getContent());
    }

    public function testGetContentReturnsResource()
    {
        $req = new Request();
        $retval = $req->getContent(true);
        $this->assertInternalType('resource', $retval);
        $this->assertEquals("", fread($retval, 1));
        $this->assertTrue(feof($retval));
    }

    /**
     * @expectedException \LogicException
     * @dataProvider getContentCantBeCalledTwiceWithResourcesProvider
     */
    public function testGetContentCantBeCalledTwiceWithResources($first, $second)
    {
        $req = new Request();
        $req->getContent($first);
        $req->getContent($second);
    }

    public function getContentCantBeCalledTwiceWithResourcesProvider()
    {
        return array(
            'Resource then fetch' => array(true, false),
            'Resource then resource' => array(true, true),
            'Fetch then resource' => array(false, true),
        );
    }

    public function provideOverloadedMethods()
    {
        return array(
            array('PUT'),
            array('DELETE'),
            array('PATCH'),
            array('put'),
            array('delete'),
            array('patch'),

        );
    }

    /**
     * @dataProvider provideOverloadedMethods
     */
    public function testCreateFromGlobals($method)
    {
        $normalizedMethod = strtoupper($method);

        $_GET['foo1']    = 'bar1';
        $_POST['foo2']   = 'bar2';
        $_COOKIE['foo3'] = 'bar3';
        $_FILES['foo4']  = array('bar4');
        $_SERVER['foo5'] = 'bar5';

        $request = Request::createFromGlobals();
        $this->assertEquals('bar1', $request->query->get('foo1'), '::fromGlobals() uses values from $_GET');
        $this->assertEquals('bar2', $request->request->get('foo2'), '::fromGlobals() uses values from $_POST');
        $this->assertEquals('bar3', $request->cookies->get('foo3'), '::fromGlobals() uses values from $_COOKIE');
        $this->assertEquals(array('bar4'), $request->files->get('foo4'), '::fromGlobals() uses values from $_FILES');
        $this->assertEquals('bar5', $request->server->get('foo5'), '::fromGlobals() uses values from $_SERVER');

        unset($_GET['foo1'], $_POST['foo2'], $_COOKIE['foo3'], $_FILES['foo4'], $_SERVER['foo5']);

        $_SERVER['REQUEST_METHOD'] = $method;
        $_SERVER['CONTENT_TYPE'] = 'application/x-www-form-urlencoded';
        $request = RequestContentProxy::createFromGlobals();
        $this->assertEquals($normalizedMethod, $request->getMethod());
        $this->assertEquals('mycontent', $request->request->get('content'));

        unset($_SERVER['REQUEST_METHOD'], $_SERVER['CONTENT_TYPE']);

        Request::createFromGlobals();
        Request::enableHttpMethodParameterOverride();
        $_POST['_method']   = $method;
        $_POST['foo6']      = 'bar6';
        $_SERVER['REQUEST_METHOD'] = 'PoSt';
        $request = Request::createFromGlobals();
        $this->assertEquals($normalizedMethod, $request->getMethod());
        $this->assertEquals('POST', $request->getRealMethod());
        $this->assertEquals('bar6', $request->request->get('foo6'));

        unset($_POST['_method'], $_POST['foo6'], $_SERVER['REQUEST_METHOD']);
        $this->disableHttpMethodParameterOverride();
    }

    public function testOverrideGlobals()
    {
        $request = new Request();
        $request->initialize(array('foo' => 'bar'));

        // as the Request::overrideGlobals really work, it erase $_SERVER, so we must backup it
        $server = $_SERVER;

        $request->overrideGlobals();

        $this->assertEquals(array('foo' => 'bar'), $_GET);

        $request->initialize(array(), array('foo' => 'bar'));
        $request->overrideGlobals();

        $this->assertEquals(array('foo' => 'bar'), $_POST);

        $this->assertArrayNotHasKey('HTTP_X_FORWARDED_PROTO', $_SERVER);

        $request->headers->set('X_FORWARDED_PROTO', 'https');

        Request::setTrustedProxies(array('1.1.1.1'));
        $this->assertTrue($request->isSecure());
        Request::setTrustedProxies(array());

        $request->overrideGlobals();

        $this->assertArrayHasKey('HTTP_X_FORWARDED_PROTO', $_SERVER);

        $request->headers->set('CONTENT_TYPE', 'multipart/form-data');
        $request->headers->set('CONTENT_LENGTH', 12345);
        $request->overrideGlobals();
        $this->assertArrayHasKey('CONTENT_TYPE', $_SERVER);
        $this->assertArrayHasKey('CONTENT_LENGTH', $_SERVER);

        // restore initial $_SERVER array
        $_SERVER = $server;
    }

    public function testGetScriptName()
    {
        $request = new Request();
        $this->assertEquals('', $request->getScriptName());

        $server = array();
        $server['SCRIPT_NAME'] = '/index.php';

        $request->initialize(array(), array(), array(), array(), array(), $server);

        $this->assertEquals('/index.php', $request->getScriptName());

        $server = array();
        $server['ORIG_SCRIPT_NAME'] = '/frontend.php';
        $request->initialize(array(), array(), array(), array(), array(), $server);

        $this->assertEquals('/frontend.php', $request->getScriptName());

        $server = array();
        $server['SCRIPT_NAME'] = '/index.php';
        $server['ORIG_SCRIPT_NAME'] = '/frontend.php';
        $request->initialize(array(), array(), array(), array(), array(), $server);

        $this->assertEquals('/index.php', $request->getScriptName());
    }

    public function testGetBasePath()
    {
        $request = new Request();
        $this->assertEquals('', $request->getBasePath());

        $server = array();
        $server['SCRIPT_FILENAME'] = '/some/where/index.php';
        $request->initialize(array(), array(), array(), array(), array(), $server);
        $this->assertEquals('', $request->getBasePath());

        $server = array();
        $server['SCRIPT_FILENAME'] = '/some/where/index.php';
        $server['SCRIPT_NAME'] = '/index.php';
        $request->initialize(array(), array(), array(), array(), array(), $server);

        $this->assertEquals('', $request->getBasePath());

        $server = array();
        $server['SCRIPT_FILENAME'] = '/some/where/index.php';
        $server['PHP_SELF'] = '/index.php';
        $request->initialize(array(), array(), array(), array(), array(), $server);

        $this->assertEquals('', $request->getBasePath());

        $server = array();
        $server['SCRIPT_FILENAME'] = '/some/where/index.php';
        $server['ORIG_SCRIPT_NAME'] = '/index.php';
        $request->initialize(array(), array(), array(), array(), array(), $server);

        $this->assertEquals('', $request->getBasePath());
    }

    public function testGetPathInfo()
    {
        $request = new Request();
        $this->assertEquals('/', $request->getPathInfo());

        $server = array();
        $server['REQUEST_URI'] = '/path/info';
        $request->initialize(array(), array(), array(), array(), array(), $server);

        $this->assertEquals('/path/info', $request->getPathInfo());

        $server = array();
        $server['REQUEST_URI'] = '/path%20test/info';
        $request->initialize(array(), array(), array(), array(), array(), $server);

        $this->assertEquals('/path%20test/info', $request->getPathInfo());
    }

    public function testGetPreferredLanguage()
    {
        $request = new Request();
        $this->assertNull($request->getPreferredLanguage());
        $this->assertNull($request->getPreferredLanguage(array()));
        $this->assertEquals('fr', $request->getPreferredLanguage(array('fr')));
        $this->assertEquals('fr', $request->getPreferredLanguage(array('fr', 'en')));
        $this->assertEquals('en', $request->getPreferredLanguage(array('en', 'fr')));
        $this->assertEquals('fr-ch', $request->getPreferredLanguage(array('fr-ch', 'fr-fr')));

        $request = new Request();
        $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6');
        $this->assertEquals('en', $request->getPreferredLanguage(array('en', 'en-us')));

        $request = new Request();
        $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6');
        $this->assertEquals('en', $request->getPreferredLanguage(array('fr', 'en')));

        $request = new Request();
        $request->headers->set('Accept-language', 'zh, en-us; q=0.8');
        $this->assertEquals('en', $request->getPreferredLanguage(array('fr', 'en')));

        $request = new Request();
        $request->headers->set('Accept-language', 'zh, en-us; q=0.8, fr-fr; q=0.6, fr; q=0.5');
        $this->assertEquals('en', $request->getPreferredLanguage(array('fr', 'en')));
    }

    public function testIsXmlHttpRequest()
    {
        $request = new Request();
        $this->assertFalse($request->isXmlHttpRequest());

        $request->headers->set('X-Requested-With', 'XMLHttpRequest');
        $this->assertTrue($request->isXmlHttpRequest());

        $request->headers->remove('X-Requested-With');
        $this->assertFalse($request->isXmlHttpRequest());
    }

    public function testIntlLocale()
    {
        if (!extension_loaded('intl')) {
            $this->markTestSkipped('The intl extension is needed to run this test.');
        }

        $request = new Request();

        $request->setDefaultLocale('fr');
        $this->assertEquals('fr', $request->getLocale());
        $this->assertEquals('fr', \Locale::getDefault());

        $request->setLocale('en');
        $this->assertEquals('en', $request->getLocale());
        $this->assertEquals('en', \Locale::getDefault());

        $request->setDefaultLocale('de');
        $this->assertEquals('en', $request->getLocale());
        $this->assertEquals('en', \Locale::getDefault());
    }

    public function testGetCharsets()
    {
        $request = new Request();
        $this->assertEquals(array(), $request->getCharsets());
        $request->headers->set('Accept-Charset', 'ISO-8859-1, US-ASCII, UTF-8; q=0.8, ISO-10646-UCS-2; q=0.6');
        $this->assertEquals(array(), $request->getCharsets()); // testing caching

        $request = new Request();
        $request->headers->set('Accept-Charset', 'ISO-8859-1, US-ASCII, UTF-8; q=0.8, ISO-10646-UCS-2; q=0.6');
        $this->assertEquals(array('ISO-8859-1', 'US-ASCII', 'UTF-8', 'ISO-10646-UCS-2'), $request->getCharsets());

        $request = new Request();
        $request->headers->set('Accept-Charset', 'ISO-8859-1,utf-8;q=0.7,*;q=0.7');
        $this->assertEquals(array('ISO-8859-1', 'utf-8', '*'), $request->getCharsets());
    }

    public function testGetEncodings()
    {
        $request = new Request();
        $this->assertEquals(array(), $request->getEncodings());
        $request->headers->set('Accept-Encoding', 'gzip,deflate,sdch');
        $this->assertEquals(array(), $request->getEncodings()); // testing caching

        $request = new Request();
        $request->headers->set('Accept-Encoding', 'gzip,deflate,sdch');
        $this->assertEquals(array('gzip', 'deflate', 'sdch'), $request->getEncodings());

        $request = new Request();
        $request->headers->set('Accept-Encoding', 'gzip;q=0.4,deflate;q=0.9,compress;q=0.7');
        $this->assertEquals(array('deflate', 'compress', 'gzip'), $request->getEncodings());
    }

    public function testGetAcceptableContentTypes()
    {
        $request = new Request();
        $this->assertEquals(array(), $request->getAcceptableContentTypes());
        $request->headers->set('Accept', 'application/vnd.wap.wmlscriptc, text/vnd.wap.wml, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/html, multipart/mixed, */*');
        $this->assertEquals(array(), $request->getAcceptableContentTypes()); // testing caching

        $request = new Request();
        $request->headers->set('Accept', 'application/vnd.wap.wmlscriptc, text/vnd.wap.wml, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/html, multipart/mixed, */*');
        $this->assertEquals(array('application/vnd.wap.wmlscriptc', 'text/vnd.wap.wml', 'application/vnd.wap.xhtml+xml', 'application/xhtml+xml', 'text/html', 'multipart/mixed', '*/*'), $request->getAcceptableContentTypes());
    }

    public function testGetLanguages()
    {
        $request = new Request();
        $this->assertEquals(array(), $request->getLanguages());

        $request = new Request();
        $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6');
        $this->assertEquals(array('zh', 'en_US', 'en'), $request->getLanguages());
        $this->assertEquals(array('zh', 'en_US', 'en'), $request->getLanguages());

        $request = new Request();
        $request->headers->set('Accept-language', 'zh, en-us; q=0.6, en; q=0.8');
        $this->assertEquals(array('zh', 'en', 'en_US'), $request->getLanguages()); // Test out of order qvalues

        $request = new Request();
        $request->headers->set('Accept-language', 'zh, en, en-us');
        $this->assertEquals(array('zh', 'en', 'en_US'), $request->getLanguages()); // Test equal weighting without qvalues

        $request = new Request();
        $request->headers->set('Accept-language', 'zh; q=0.6, en, en-us; q=0.6');
        $this->assertEquals(array('en', 'zh', 'en_US'), $request->getLanguages()); // Test equal weighting with qvalues

        $request = new Request();
        $request->headers->set('Accept-language', 'zh, i-cherokee; q=0.6');
        $this->assertEquals(array('zh', 'cherokee'), $request->getLanguages());
    }

    public function testGetRequestFormat()
    {
        $request = new Request();
        $this->assertEquals('html', $request->getRequestFormat());

        $request = new Request();
        $this->assertNull($request->getRequestFormat(null));

        $request = new Request();
        $this->assertNull($request->setRequestFormat('foo'));
        $this->assertEquals('foo', $request->getRequestFormat(null));
    }

    public function testHasSession()
    {
        $request = new Request();

        $this->assertFalse($request->hasSession());
        $request->setSession(new Session(new MockArraySessionStorage()));
        $this->assertTrue($request->hasSession());
    }

    public function testGetSession()
    {
        $request = new Request();

        $request->setSession(new Session(new MockArraySessionStorage()));
        $this->assertTrue($request->hasSession());

        $session = $request->getSession();
        $this->assertObjectHasAttribute('storage', $session);
        $this->assertObjectHasAttribute('flashName', $session);
        $this->assertObjectHasAttribute('attributeName', $session);
    }

    public function testHasPreviousSession()
    {
        $request = new Request();

        $this->assertFalse($request->hasPreviousSession());
        $request->cookies->set('MOCKSESSID', 'foo');
        $this->assertFalse($request->hasPreviousSession());
        $request->setSession(new Session(new MockArraySessionStorage()));
        $this->assertTrue($request->hasPreviousSession());
    }

    public function testToString()
    {
        $request = new Request();

        $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6');

        $this->assertContains('Accept-Language: zh, en-us; q=0.8, en; q=0.6', $request->__toString());
    }

    public function testIsMethod()
    {
        $request = new Request();
        $request->setMethod('POST');
        $this->assertTrue($request->isMethod('POST'));
        $this->assertTrue($request->isMethod('post'));
        $this->assertFalse($request->isMethod('GET'));
        $this->assertFalse($request->isMethod('get'));

        $request->setMethod('GET');
        $this->assertTrue($request->isMethod('GET'));
        $this->assertTrue($request->isMethod('get'));
        $this->assertFalse($request->isMethod('POST'));
        $this->assertFalse($request->isMethod('post'));
    }

    /**
     * @dataProvider getBaseUrlData
     */
    public function testGetBaseUrl($uri, $server, $expectedBaseUrl, $expectedPathInfo)
    {
        $request = Request::create($uri, 'GET', array(), array(), array(), $server);

        $this->assertSame($expectedBaseUrl, $request->getBaseUrl(), 'baseUrl');
        $this->assertSame($expectedPathInfo, $request->getPathInfo(), 'pathInfo');
    }

    public function getBaseUrlData()
    {
        return array(
            array(
                '/foo%20bar',
                array(
                    'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php',
                    'SCRIPT_NAME'     => '/foo bar/app.php',
                    'PHP_SELF'        => '/foo bar/app.php',
                ),
                '/foo%20bar',
                '/',
            ),
            array(
                '/foo%20bar/home',
                array(
                    'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php',
                    'SCRIPT_NAME'     => '/foo bar/app.php',
                    'PHP_SELF'        => '/foo bar/app.php',
                ),
                '/foo%20bar',
                '/home',
            ),
            array(
                '/foo%20bar/app.php/home',
                array(
                    'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php',
                    'SCRIPT_NAME'     => '/foo bar/app.php',
                    'PHP_SELF'        => '/foo bar/app.php',
                ),
                '/foo%20bar/app.php',
                '/home',
            ),
            array(
                '/foo%20bar/app.php/home%3Dbaz',
                array(
                    'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php',
                    'SCRIPT_NAME'     => '/foo bar/app.php',
                    'PHP_SELF'        => '/foo bar/app.php',
                ),
                '/foo%20bar/app.php',
                '/home%3Dbaz',
            ),
            array(
                '/foo/bar+baz',
                array(
                    'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo/app.php',
                    'SCRIPT_NAME'     => '/foo/app.php',
                    'PHP_SELF'        => '/foo/app.php',
                ),
                '/foo',
                '/bar+baz',
            ),
        );
    }

    /**
     * @dataProvider urlencodedStringPrefixData
     */
    public function testUrlencodedStringPrefix($string, $prefix, $expect)
    {
        $request = new Request();

        $me = new \ReflectionMethod($request, 'getUrlencodedPrefix');
        $me->setAccessible(true);

        $this->assertSame($expect, $me->invoke($request, $string, $prefix));
    }

    public function urlencodedStringPrefixData()
    {
        return array(
            array('foo', 'foo', 'foo'),
            array('fo%6f', 'foo', 'fo%6f'),
            array('foo/bar', 'foo', 'foo'),
            array('fo%6f/bar', 'foo', 'fo%6f'),
            array('f%6f%6f/bar', 'foo', 'f%6f%6f'),
            array('%66%6F%6F/bar', 'foo', '%66%6F%6F'),
            array('fo+o/bar', 'fo+o', 'fo+o'),
            array('fo%2Bo/bar', 'fo+o', 'fo%2Bo'),
        );
    }

    private function disableHttpMethodParameterOverride()
    {
        $class = new \ReflectionClass('Symfony\\Component\\HttpFoundation\\Request');
        $property = $class->getProperty('httpMethodParameterOverride');
        $property->setAccessible(true);
        $property->setValue(false);
    }

    private function getRequestInstanceForClientIpTests($remoteAddr, $httpForwardedFor, $trustedProxies)
    {
        $request = new Request();

        $server = array('REMOTE_ADDR' => $remoteAddr);
        if (null !== $httpForwardedFor) {
            $server['HTTP_X_FORWARDED_FOR'] = $httpForwardedFor;
        }

        if ($trustedProxies) {
            Request::setTrustedProxies($trustedProxies);
        }

        $request->initialize(array(), array(), array(), array(), array(), $server);

        return $request;
    }

    public function testTrustedProxies()
    {
        $request = Request::create('http://example.com/');
        $request->server->set('REMOTE_ADDR', '3.3.3.3');
        $request->headers->set('X_FORWARDED_FOR', '1.1.1.1, 2.2.2.2');
        $request->headers->set('X_FORWARDED_HOST', 'foo.example.com, real.example.com:8080');
        $request->headers->set('X_FORWARDED_PROTO', 'https');
        $request->headers->set('X_FORWARDED_PORT', 443);
        $request->headers->set('X_MY_FOR', '3.3.3.3, 4.4.4.4');
        $request->headers->set('X_MY_HOST', 'my.example.com');
        $request->headers->set('X_MY_PROTO', 'http');
        $request->headers->set('X_MY_PORT', 81);

        // no trusted proxies
        $this->assertEquals('3.3.3.3', $request->getClientIp());
        $this->assertEquals('example.com', $request->getHost());
        $this->assertEquals(80, $request->getPort());
        $this->assertFalse($request->isSecure());

        // disabling proxy trusting
        Request::setTrustedProxies(array());
        $this->assertEquals('3.3.3.3', $request->getClientIp());
        $this->assertEquals('example.com', $request->getHost());
        $this->assertEquals(80, $request->getPort());
        $this->assertFalse($request->isSecure());

        // trusted proxy via setTrustedProxies()
        Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2'));
        $this->assertEquals('1.1.1.1', $request->getClientIp());
        $this->assertEquals('real.example.com', $request->getHost());
        $this->assertEquals(443, $request->getPort());
        $this->assertTrue($request->isSecure());

        // check various X_FORWARDED_PROTO header values
        $request->headers->set('X_FORWARDED_PROTO', 'ssl');
        $this->assertTrue($request->isSecure());

        $request->headers->set('X_FORWARDED_PROTO', 'https, http');
        $this->assertTrue($request->isSecure());

        // custom header names
        Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, 'X_MY_FOR');
        Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, 'X_MY_HOST');
        Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, 'X_MY_PORT');
        Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, 'X_MY_PROTO');
        $this->assertEquals('4.4.4.4', $request->getClientIp());
        $this->assertEquals('my.example.com', $request->getHost());
        $this->assertEquals(81, $request->getPort());
        $this->assertFalse($request->isSecure());

        // disabling via empty header names
        Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, null);
        Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, null);
        Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, null);
        Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, null);
        $this->assertEquals('3.3.3.3', $request->getClientIp());
        $this->assertEquals('example.com', $request->getHost());
        $this->assertEquals(80, $request->getPort());
        $this->assertFalse($request->isSecure());

        // reset
        Request::setTrustedProxies(array());
        Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, 'X_FORWARDED_FOR');
        Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, 'X_FORWARDED_HOST');
        Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, 'X_FORWARDED_PORT');
        Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, 'X_FORWARDED_PROTO');
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testSetTrustedProxiesInvalidHeaderName()
    {
        Request::create('http://example.com/');
        Request::setTrustedHeaderName('bogus name', 'X_MY_FOR');
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testGetTrustedProxiesInvalidHeaderName()
    {
        Request::create('http://example.com/');
        Request::getTrustedHeaderName('bogus name');
    }

    /**
     * @dataProvider iisRequestUriProvider
     */
    public function testIISRequestUri($headers, $server, $expectedRequestUri)
    {
        $request = new Request();
        $request->headers->replace($headers);
        $request->server->replace($server);

        $this->assertEquals($expectedRequestUri, $request->getRequestUri(), '->getRequestUri() is correct');

        $subRequestUri = '/bar/foo';
        $subRequest = Request::create($subRequestUri, 'get', array(), array(), array(), $request->server->all());
        $this->assertEquals($subRequestUri, $subRequest->getRequestUri(), '->getRequestUri() is correct in sub request');
    }

    public function iisRequestUriProvider()
    {
        return array(
            array(
                array(
                    'X_ORIGINAL_URL' => '/foo/bar',
                ),
                array(),
                '/foo/bar'
            ),
            array(
                array(
                    'X_REWRITE_URL' => '/foo/bar',
                ),
                array(),
                '/foo/bar'
            ),
            array(
                array(),
                array(
                    'IIS_WasUrlRewritten' => '1',
                    'UNENCODED_URL' => '/foo/bar'
                ),
                '/foo/bar'
            ),
            array(
                array(
                    'X_ORIGINAL_URL' => '/foo/bar',
                ),
                array(
                    'HTTP_X_ORIGINAL_URL' => '/foo/bar'
                ),
                '/foo/bar'
            ),
            array(
                array(
                    'X_ORIGINAL_URL' => '/foo/bar',
                ),
                array(
                    'IIS_WasUrlRewritten' => '1',
                    'UNENCODED_URL' => '/foo/bar'
                ),
                '/foo/bar'
            ),
            array(
                array(
                    'X_ORIGINAL_URL' => '/foo/bar',
                ),
                array(
                    'HTTP_X_ORIGINAL_URL' => '/foo/bar',
                    'IIS_WasUrlRewritten' => '1',
                    'UNENCODED_URL' => '/foo/bar'
                ),
                '/foo/bar'
            ),
            array(
                array(),
                array(
                    'ORIG_PATH_INFO' => '/foo/bar',
                ),
                '/foo/bar'
            ),
            array(
                array(),
                array(
                    'ORIG_PATH_INFO' => '/foo/bar',
                    'QUERY_STRING' => 'foo=bar',
                ),
                '/foo/bar?foo=bar'
            )
        );
    }

    public function testTrustedHosts()
    {
        // create a request
        $request = Request::create('/');

        // no trusted host set -> no host check
        $request->headers->set('host', 'evil.com');
        $this->assertEquals('evil.com', $request->getHost());

        // add a trusted domain and all its subdomains
        Request::setTrustedHosts(array('.*\.?trusted.com$'));

        // untrusted host
        $request->headers->set('host', 'evil.com');
        try {
            $request->getHost();
            $this->fail('Request::getHost() should throw an exception when host is not trusted.');
        } catch (\UnexpectedValueException $e) {
            $this->assertEquals('Untrusted Host "evil.com"', $e->getMessage());
        }

        // trusted hosts
        $request->headers->set('host', 'trusted.com');
        $this->assertEquals('trusted.com', $request->getHost());
        $this->assertEquals(80, $request->getPort());

        $request->server->set('HTTPS', true);
        $request->headers->set('host', 'trusted.com');
        $this->assertEquals('trusted.com', $request->getHost());
        $this->assertEquals(443, $request->getPort());
        $request->server->set('HTTPS', false);

        $request->headers->set('host', 'trusted.com:8000');
        $this->assertEquals('trusted.com', $request->getHost());
        $this->assertEquals(8000, $request->getPort());

        $request->headers->set('host', 'subdomain.trusted.com');
        $this->assertEquals('subdomain.trusted.com', $request->getHost());

        // reset request for following tests
        Request::setTrustedHosts(array());
    }

    public function testFactory()
    {
        Request::setFactory(function (array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null) {
            return new NewRequest();
        });

        $this->assertEquals('foo', Request::create('/')->getFoo());

        Request::setFactory(null);
    }
}

class RequestContentProxy extends Request
{
    public function getContent($asResource = false)
    {
        return http_build_query(array('_method' => 'PUT', 'content' => 'mycontent'));
    }
}

class NewRequest extends Request
{
    public function getFoo()
    {
        return 'foo';
    }
}
PK��Z%�bD�
�
Ptest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ApacheRequestTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests;

use Symfony\Component\HttpFoundation\ApacheRequest;

class ApacheRequestTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider provideServerVars
     */
    public function testUriMethods($server, $expectedRequestUri, $expectedBaseUrl, $expectedPathInfo)
    {
        $request = new ApacheRequest();
        $request->server->replace($server);

        $this->assertEquals($expectedRequestUri, $request->getRequestUri(), '->getRequestUri() is correct');
        $this->assertEquals($expectedBaseUrl, $request->getBaseUrl(), '->getBaseUrl() is correct');
        $this->assertEquals($expectedPathInfo, $request->getPathInfo(), '->getPathInfo() is correct');
    }

    public function provideServerVars()
    {
        return array(
            array(
                array(
                    'REQUEST_URI' => '/foo/app_dev.php/bar',
                    'SCRIPT_NAME' => '/foo/app_dev.php',
                    'PATH_INFO'   => '/bar',
                ),
                '/foo/app_dev.php/bar',
                '/foo/app_dev.php',
                '/bar'
            ),
            array(
                array(
                    'REQUEST_URI' => '/foo/bar',
                    'SCRIPT_NAME' => '/foo/app_dev.php',
                ),
                '/foo/bar',
                '/foo',
                '/bar',
            ),
            array(
                array(
                    'REQUEST_URI' => '/app_dev.php/foo/bar',
                    'SCRIPT_NAME' => '/app_dev.php',
                    'PATH_INFO'   => '/foo/bar',
                ),
                '/app_dev.php/foo/bar',
                '/app_dev.php',
                '/foo/bar',
            ),
            array(
                array(
                    'REQUEST_URI' => '/foo/bar',
                    'SCRIPT_NAME' => '/app_dev.php',
                ),
                '/foo/bar',
                '',
                '/foo/bar',
            ),
            array(
                array(
                    'REQUEST_URI' => '/app_dev.php',
                    'SCRIPT_NAME' => '/app_dev.php',
                ),
                '/app_dev.php',
                '/app_dev.php',
                '/',
            ),
            array(
                array(
                    'REQUEST_URI' => '/',
                    'SCRIPT_NAME' => '/app_dev.php',
                ),
                '/',
                '',
                '/',
            ),
        );
    }
}
PK��Z�1r�
�
Otest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/AcceptHeaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests;

use Symfony\Component\HttpFoundation\AcceptHeader;
use Symfony\Component\HttpFoundation\AcceptHeaderItem;

class AcceptHeaderTest extends \PHPUnit_Framework_TestCase
{
    public function testFirst()
    {
        $header = AcceptHeader::fromString('text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c');
        $this->assertSame('text/html', $header->first()->getValue());
    }

    /**
     * @dataProvider provideFromStringData
     */
    public function testFromString($string, array $items)
    {
        $header = AcceptHeader::fromString($string);
        $parsed = array_values($header->all());
        // reset index since the fixtures don't have them set
        foreach ($parsed as $item) {
            $item->setIndex(0);
        }
        $this->assertEquals($items, $parsed);
    }

    public function provideFromStringData()
    {
        return array(
            array('', array()),
            array('gzip', array(new AcceptHeaderItem('gzip'))),
            array('gzip,deflate,sdch', array(new AcceptHeaderItem('gzip'), new AcceptHeaderItem('deflate'), new AcceptHeaderItem('sdch'))),
            array("gzip, deflate\t,sdch", array(new AcceptHeaderItem('gzip'), new AcceptHeaderItem('deflate'), new AcceptHeaderItem('sdch'))),
            array('"this;should,not=matter"', array(new AcceptHeaderItem('this;should,not=matter'))),
        );
    }

    /**
     * @dataProvider provideToStringData
     */
    public function testToString(array $items, $string)
    {
        $header = new AcceptHeader($items);
        $this->assertEquals($string, (string) $header);
    }

    public function provideToStringData()
    {
        return array(
            array(array(), ''),
            array(array(new AcceptHeaderItem('gzip')), 'gzip'),
            array(array(new AcceptHeaderItem('gzip'), new AcceptHeaderItem('deflate'), new AcceptHeaderItem('sdch')), 'gzip,deflate,sdch'),
            array(array(new AcceptHeaderItem('this;should,not=matter')), 'this;should,not=matter'),
        );
    }

    /**
     * @dataProvider provideFilterData
     */
    public function testFilter($string, $filter, array $values)
    {
        $header = AcceptHeader::fromString($string)->filter($filter);
        $this->assertEquals($values, array_keys($header->all()));
    }

    public function provideFilterData()
    {
        return array(
            array('fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4', '/fr.*/', array('fr-FR', 'fr')),
        );
    }

    /**
     * @dataProvider provideSortingData
     */
    public function testSorting($string, array $values)
    {
        $header = AcceptHeader::fromString($string);
        $this->assertEquals($values, array_keys($header->all()));
    }

    public function provideSortingData()
    {
        return array(
            'quality has priority' => array('*;q=0.3,ISO-8859-1,utf-8;q=0.7',  array('ISO-8859-1', 'utf-8', '*')),
            'order matters when q is equal' => array('*;q=0.3,ISO-8859-1;q=0.7,utf-8;q=0.7',  array('ISO-8859-1', 'utf-8', '*')),
            'order matters when q is equal2' => array('*;q=0.3,utf-8;q=0.7,ISO-8859-1;q=0.7',  array('utf-8', 'ISO-8859-1', '*')),
        );
    }
}
PK��Z��?�Ltest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ServerBagTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\Tests;

use Symfony\Component\HttpFoundation\ServerBag;

/**
 * ServerBagTest
 *
 * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
 */
class ServerBagTest extends \PHPUnit_Framework_TestCase
{
    public function testShouldExtractHeadersFromServerArray()
    {
        $server = array(
            'SOME_SERVER_VARIABLE' => 'value',
            'SOME_SERVER_VARIABLE2' => 'value',
            'ROOT' => 'value',
            'HTTP_CONTENT_TYPE' => 'text/html',
            'HTTP_CONTENT_LENGTH' => '0',
            'HTTP_ETAG' => 'asdf',
            'PHP_AUTH_USER' => 'foo',
            'PHP_AUTH_PW' => 'bar',
        );

        $bag = new ServerBag($server);

        $this->assertEquals(array(
            'CONTENT_TYPE' => 'text/html',
            'CONTENT_LENGTH' => '0',
            'ETAG' => 'asdf',
            'AUTHORIZATION' => 'Basic '.base64_encode('foo:bar'),
            'PHP_AUTH_USER' => 'foo',
            'PHP_AUTH_PW' => 'bar',
        ), $bag->getHeaders());
    }

    public function testHttpPasswordIsOptional()
    {
        $bag = new ServerBag(array('PHP_AUTH_USER' => 'foo'));

        $this->assertEquals(array(
            'AUTHORIZATION' => 'Basic '.base64_encode('foo:'),
            'PHP_AUTH_USER' => 'foo',
            'PHP_AUTH_PW' => ''
        ), $bag->getHeaders());
    }

    public function testHttpBasicAuthWithPhpCgi()
    {
        $bag = new ServerBag(array('HTTP_AUTHORIZATION' => 'Basic '.base64_encode('foo:bar')));

        $this->assertEquals(array(
            'AUTHORIZATION' => 'Basic '.base64_encode('foo:bar'),
            'PHP_AUTH_USER' => 'foo',
            'PHP_AUTH_PW' => 'bar'
        ), $bag->getHeaders());
    }

    public function testHttpBasicAuthWithPhpCgiRedirect()
    {
        $bag = new ServerBag(array('REDIRECT_HTTP_AUTHORIZATION' => 'Basic '.base64_encode('foo:bar')));

        $this->assertEquals(array(
            'AUTHORIZATION' => 'Basic '.base64_encode('foo:bar'),
            'PHP_AUTH_USER' => 'foo',
            'PHP_AUTH_PW' => 'bar'
        ), $bag->getHeaders());
    }

    public function testHttpBasicAuthWithPhpCgiEmptyPassword()
    {
        $bag = new ServerBag(array('HTTP_AUTHORIZATION' => 'Basic '.base64_encode('foo:')));

        $this->assertEquals(array(
            'AUTHORIZATION' => 'Basic '.base64_encode('foo:'),
            'PHP_AUTH_USER' => 'foo',
            'PHP_AUTH_PW' => ''
        ), $bag->getHeaders());
    }

    public function testHttpDigestAuthWithPhpCgi()
    {
        $digest = 'Digest username="foo", realm="acme", nonce="'.md5('secret').'", uri="/protected, qop="auth"';
        $bag = new ServerBag(array('HTTP_AUTHORIZATION' => $digest));

        $this->assertEquals(array(
            'AUTHORIZATION' => $digest,
            'PHP_AUTH_DIGEST' => $digest,
        ), $bag->getHeaders());
    }

    public function testHttpDigestAuthWithPhpCgiRedirect()
    {
        $digest = 'Digest username="foo", realm="acme", nonce="'.md5('secret').'", uri="/protected, qop="auth"';
        $bag = new ServerBag(array('REDIRECT_HTTP_AUTHORIZATION' => $digest));

        $this->assertEquals(array(
            'AUTHORIZATION' => $digest,
            'PHP_AUTH_DIGEST' => $digest,
        ), $bag->getHeaders());
    }

    public function testOAuthBearerAuth()
    {
        $headerContent = 'Bearer L-yLEOr9zhmUYRkzN1jwwxwQ-PBNiKDc8dgfB4hTfvo';
        $bag = new ServerBag(array('HTTP_AUTHORIZATION' => $headerContent));

        $this->assertEquals(array(
            'AUTHORIZATION' => $headerContent,
        ), $bag->getHeaders());
    }
}
PK��Z���bppEtest/HttpFoundation/Symfony/Component/HttpFoundation/phpunit.xml.distnu�[���<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony HttpFoundation Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./Resources</directory>
                <directory>./Tests</directory>
                <directory>./vendor</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
PK��Z��J=�'�'Dtest/BrowserKit/Symfony/Component/BrowserKit/Tests/CookieJarTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\BrowserKit\Tests;

use Symfony\Component\BrowserKit\CookieJar;
use Symfony\Component\BrowserKit\Cookie;
use Symfony\Component\BrowserKit\Response;

class CookieJarTest extends \PHPUnit_Framework_TestCase
{
    public function testSetGet()
    {
        $cookieJar = new CookieJar();
        $cookieJar->set($cookie = new Cookie('foo', 'bar'));

        $this->assertEquals($cookie, $cookieJar->get('foo'), '->set() sets a cookie');

        $this->assertNull($cookieJar->get('foobar'), '->get() returns null if the cookie does not exist');

        $cookieJar->set($cookie = new Cookie('foo', 'bar', time() - 86400));
        $this->assertNull($cookieJar->get('foo'), '->get() returns null if the cookie is expired');
    }

    public function testExpire()
    {
        $cookieJar = new CookieJar();
        $cookieJar->set($cookie = new Cookie('foo', 'bar'));
        $cookieJar->expire('foo');
        $this->assertNull($cookieJar->get('foo'), '->get() returns null if the cookie is expired');
    }

    public function testAll()
    {
        $cookieJar = new CookieJar();
        $cookieJar->set($cookie1 = new Cookie('foo', 'bar'));
        $cookieJar->set($cookie2 = new Cookie('bar', 'foo'));

        $this->assertEquals(array($cookie1, $cookie2), $cookieJar->all(), '->all() returns all cookies in the jar');
    }

    public function testClear()
    {
        $cookieJar = new CookieJar();
        $cookieJar->set($cookie1 = new Cookie('foo', 'bar'));
        $cookieJar->set($cookie2 = new Cookie('bar', 'foo'));

        $cookieJar->clear();

        $this->assertEquals(array(), $cookieJar->all(), '->clear() expires all cookies');
    }

    public function testUpdateFromResponse()
    {
        $response = new Response('', 200, array('Set-Cookie' => 'foo=foo'));

        $cookieJar = new CookieJar();
        $cookieJar->updateFromResponse($response);

        $this->assertEquals('foo', $cookieJar->get('foo')->getValue(), '->updateFromResponse() updates cookies from a Response objects');
    }

    public function testUpdateFromSetCookie()
    {
        $setCookies = array('foo=foo');

        $cookieJar = new CookieJar();
        $cookieJar->set(new Cookie('bar', 'bar'));
        $cookieJar->updateFromSetCookie($setCookies);

        $this->assertInstanceOf('Symfony\Component\BrowserKit\Cookie', $cookieJar->get('foo'));
        $this->assertInstanceOf('Symfony\Component\BrowserKit\Cookie', $cookieJar->get('bar'));
        $this->assertEquals('foo', $cookieJar->get('foo')->getValue(), '->updateFromSetCookie() updates cookies from a Set-Cookie header');
        $this->assertEquals('bar', $cookieJar->get('bar')->getValue(), '->updateFromSetCookie() keeps existing cookies');
    }

    public function testUpdateFromEmptySetCookie()
    {
        $cookieJar = new CookieJar();
        $cookieJar->updateFromSetCookie(array(''));
        $this->assertEquals(array(), $cookieJar->all());
    }

    public function testUpdateFromSetCookieWithMultipleCookies()
    {
        $timestamp = time() + 3600;
        $date = gmdate('D, d M Y H:i:s \G\M\T', $timestamp);
        $setCookies = array(sprintf('foo=foo; expires=%s; domain=.symfony.com; path=/, bar=bar; domain=.blog.symfony.com, PHPSESSID=id; expires=%s', $date, $date));

        $cookieJar = new CookieJar();
        $cookieJar->updateFromSetCookie($setCookies);

        $fooCookie = $cookieJar->get('foo', '/', '.symfony.com');
        $barCookie = $cookieJar->get('bar', '/', '.blog.symfony.com');
        $phpCookie = $cookieJar->get('PHPSESSID');

        $this->assertInstanceOf('Symfony\Component\BrowserKit\Cookie', $fooCookie);
        $this->assertInstanceOf('Symfony\Component\BrowserKit\Cookie', $barCookie);
        $this->assertInstanceOf('Symfony\Component\BrowserKit\Cookie', $phpCookie);
        $this->assertEquals('foo', $fooCookie->getValue());
        $this->assertEquals('bar', $barCookie->getValue());
        $this->assertEquals('id', $phpCookie->getValue());
        $this->assertEquals($timestamp, $fooCookie->getExpiresTime());
        $this->assertNull($barCookie->getExpiresTime());
        $this->assertEquals($timestamp, $phpCookie->getExpiresTime());
    }

    /**
     * @dataProvider provideAllValuesValues
     */
    public function testAllValues($uri, $values)
    {
        $cookieJar = new CookieJar();
        $cookieJar->set($cookie1 = new Cookie('foo_nothing', 'foo'));
        $cookieJar->set($cookie2 = new Cookie('foo_expired', 'foo', time() - 86400));
        $cookieJar->set($cookie3 = new Cookie('foo_path', 'foo', null, '/foo'));
        $cookieJar->set($cookie4 = new Cookie('foo_domain', 'foo', null, '/', '.example.com'));
        $cookieJar->set($cookie4 = new Cookie('foo_strict_domain', 'foo', null, '/', '.www4.example.com'));
        $cookieJar->set($cookie5 = new Cookie('foo_secure', 'foo', null, '/', '', true));

        $this->assertEquals($values, array_keys($cookieJar->allValues($uri)), '->allValues() returns the cookie for a given URI');
    }

    public function provideAllValuesValues()
    {
        return array(
            array('http://www.example.com', array('foo_nothing', 'foo_domain')),
            array('http://www.example.com/', array('foo_nothing', 'foo_domain')),
            array('http://foo.example.com/', array('foo_nothing', 'foo_domain')),
            array('http://foo.example1.com/', array('foo_nothing')),
            array('https://foo.example.com/', array('foo_nothing', 'foo_secure', 'foo_domain')),
            array('http://www.example.com/foo/bar', array('foo_nothing', 'foo_path', 'foo_domain')),
            array('http://www4.example.com/', array('foo_nothing', 'foo_domain', 'foo_strict_domain')),
        );
    }

    public function testEncodedValues()
    {
        $cookieJar = new CookieJar();
        $cookieJar->set($cookie = new Cookie('foo', 'bar%3Dbaz', null, '/', '', false, true, true));

        $this->assertEquals(array('foo' => 'bar=baz'), $cookieJar->allValues('/'));
        $this->assertEquals(array('foo' => 'bar%3Dbaz'), $cookieJar->allRawValues('/'));
    }

    public function testCookieExpireWithSameNameButDifferentPaths()
    {
        $cookieJar = new CookieJar();
        $cookieJar->set($cookie1 = new Cookie('foo', 'bar1', null, '/foo'));
        $cookieJar->set($cookie2 = new Cookie('foo', 'bar2', null, '/bar'));
        $cookieJar->expire('foo', '/foo');

        $this->assertNull($cookieJar->get('foo'), '->get() returns null if the cookie is expired');
        $this->assertEquals(array(), array_keys($cookieJar->allValues('http://example.com/')));
        $this->assertEquals(array(), $cookieJar->allValues('http://example.com/foo'));
        $this->assertEquals(array('foo' => 'bar2'), $cookieJar->allValues('http://example.com/bar'));
    }

    public function testCookieExpireWithNullPaths()
    {
        $cookieJar = new CookieJar();
        $cookieJar->set($cookie1 = new Cookie('foo', 'bar1', null, '/'));
        $cookieJar->expire('foo', null);

        $this->assertNull($cookieJar->get('foo'), '->get() returns null if the cookie is expired');
        $this->assertEquals(array(), array_keys($cookieJar->allValues('http://example.com/')));
    }

    public function testCookieWithSameNameButDifferentPaths()
    {
        $cookieJar = new CookieJar();
        $cookieJar->set($cookie1 = new Cookie('foo', 'bar1', null, '/foo'));
        $cookieJar->set($cookie2 = new Cookie('foo', 'bar2', null, '/bar'));

        $this->assertEquals(array(), array_keys($cookieJar->allValues('http://example.com/')));
        $this->assertEquals(array('foo' => 'bar1'), $cookieJar->allValues('http://example.com/foo'));
        $this->assertEquals(array('foo' => 'bar2'), $cookieJar->allValues('http://example.com/bar'));
    }

    public function testCookieWithSameNameButDifferentDomains()
    {
        $cookieJar = new CookieJar();
        $cookieJar->set($cookie1 = new Cookie('foo', 'bar1', null, '/', 'foo.example.com'));
        $cookieJar->set($cookie2 = new Cookie('foo', 'bar2', null, '/', 'bar.example.com'));

        $this->assertEquals(array(), array_keys($cookieJar->allValues('http://example.com/')));
        $this->assertEquals(array('foo' => 'bar1'), $cookieJar->allValues('http://foo.example.com/'));
        $this->assertEquals(array('foo' => 'bar2'), $cookieJar->allValues('http://bar.example.com/'));
    }

    public function testCookieGetWithSubdomain()
    {
        $cookieJar = new CookieJar();
        $cookieJar->set($cookie1 = new Cookie('foo', 'bar', null, '/', '.example.com'));
        $cookieJar->set($cookie2 = new Cookie('foo1', 'bar', null, '/', 'test.example.com'));

        $this->assertEquals($cookie1, $cookieJar->get('foo','/','foo.example.com'));
        $this->assertEquals($cookie1, $cookieJar->get('foo','/','example.com'));
        $this->assertEquals($cookie2, $cookieJar->get('foo1','/','test.example.com'));
    }

    public function testCookieGetWithSubdirectory()
    {
        $cookieJar = new CookieJar();
        $cookieJar->set($cookie1 = new Cookie('foo', 'bar', null, '/test', '.example.com'));
        $cookieJar->set($cookie2 = new Cookie('foo1', 'bar1', null, '/', '.example.com'));

        $this->assertNull($cookieJar->get('foo','/','.example.com'));
        $this->assertNull($cookieJar->get('foo','/bar','.example.com'));
        $this->assertEquals($cookie1, $cookieJar->get('foo','/test','example.com'));
        $this->assertEquals($cookie2, $cookieJar->get('foo1','/','example.com'));
        $this->assertEquals($cookie2, $cookieJar->get('foo1','/bar','example.com'));
    }

    public function testCookieWithWildcardDomain()
    {
        $cookieJar = new CookieJar();
        $cookieJar->set(new Cookie('foo', 'bar', null, '/', '.example.com'));

        $this->assertEquals(array('foo' => 'bar'), $cookieJar->allValues('http://www.example.com'));
        $this->assertEmpty($cookieJar->allValues('http://wwwexample.com'));
    }
}
PK��ZN�4Z�c�cAtest/BrowserKit/Symfony/Component/BrowserKit/Tests/ClientTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\BrowserKit\Tests;

use Symfony\Component\BrowserKit\Client;
use Symfony\Component\BrowserKit\History;
use Symfony\Component\BrowserKit\CookieJar;
use Symfony\Component\BrowserKit\Request;
use Symfony\Component\BrowserKit\Response;

class SpecialResponse extends Response
{
}

class TestClient extends Client
{
    protected $nextResponse = null;
    protected $nextScript = null;

    public function setNextResponse(Response $response)
    {
        $this->nextResponse = $response;
    }

    public function setNextScript($script)
    {
        $this->nextScript = $script;
    }

    protected function doRequest($request)
    {
        if (null === $this->nextResponse) {
            return new Response();
        }

        $response = $this->nextResponse;
        $this->nextResponse = null;

        return $response;
    }

    protected function filterResponse($response)
    {
        if ($response instanceof SpecialResponse) {
            return new Response($response->getContent(), $response->getStatus(), $response->getHeaders());
        }

        return $response;
    }

    protected function getScript($request)
    {
        $r = new \ReflectionClass('Symfony\Component\BrowserKit\Response');
        $path = $r->getFileName();

        return <<<EOF
<?php

require_once('$path');

echo serialize($this->nextScript);
EOF;
    }
}

class ClientTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Symfony\Component\BrowserKit\Client::getHistory
     */
    public function testGetHistory()
    {
        $client = new TestClient(array(), $history = new History());
        $this->assertSame($history, $client->getHistory(), '->getHistory() returns the History');
    }

    /**
     * @covers Symfony\Component\BrowserKit\Client::getCookieJar
     */
    public function testGetCookieJar()
    {
        $client = new TestClient(array(), null, $cookieJar = new CookieJar());
        $this->assertSame($cookieJar, $client->getCookieJar(), '->getCookieJar() returns the CookieJar');
    }

    /**
     * @covers Symfony\Component\BrowserKit\Client::getRequest
     */
    public function testGetRequest()
    {
        $client = new TestClient();
        $client->request('GET', 'http://example.com/');

        $this->assertEquals('http://example.com/', $client->getRequest()->getUri(), '->getCrawler() returns the Request of the last request');
    }

    public function testGetResponse()
    {
        $client = new TestClient();
        $client->setNextResponse(new Response('foo'));
        $client->request('GET', 'http://example.com/');

        $this->assertEquals('foo', $client->getResponse()->getContent(), '->getCrawler() returns the Response of the last request');
        $this->assertInstanceOf('Symfony\Component\BrowserKit\Response', $client->getResponse(), '->getCrawler() returns the Response of the last request');
    }

    public function testGetInternalResponse()
    {
        $client = new TestClient();
        $client->setNextResponse(new SpecialResponse('foo'));
        $client->request('GET', 'http://example.com/');

        $this->assertInstanceOf('Symfony\Component\BrowserKit\Response', $client->getInternalResponse());
        $this->assertNotInstanceOf('Symfony\Component\BrowserKit\Tests\SpecialResponse', $client->getInternalResponse());
        $this->assertInstanceOf('Symfony\Component\BrowserKit\Tests\SpecialResponse', $client->getResponse());
    }

    public function testGetContent()
    {
        $json = '{"jsonrpc":"2.0","method":"echo","id":7,"params":["Hello World"]}';

        $client = new TestClient();
        $client->request('POST', 'http://example.com/jsonrpc', array(), array(), array(), $json);
        $this->assertEquals($json, $client->getRequest()->getContent());
    }

    /**
     * @covers Symfony\Component\BrowserKit\Client::getCrawler
     */
    public function testGetCrawler()
    {
        $client = new TestClient();
        $client->setNextResponse(new Response('foo'));
        $crawler = $client->request('GET', 'http://example.com/');

        $this->assertSame($crawler, $client->getCrawler(), '->getCrawler() returns the Crawler of the last request');
    }

    public function testRequestHttpHeaders()
    {
        $client = new TestClient();
        $client->request('GET', '/');
        $headers = $client->getRequest()->getServer();
        $this->assertEquals('localhost', $headers['HTTP_HOST'], '->request() sets the HTTP_HOST header');

        $client = new TestClient();
        $client->request('GET', 'http://www.example.com');
        $headers = $client->getRequest()->getServer();
        $this->assertEquals('www.example.com', $headers['HTTP_HOST'], '->request() sets the HTTP_HOST header');

        $client->request('GET', 'https://www.example.com');
        $headers = $client->getRequest()->getServer();
        $this->assertTrue($headers['HTTPS'], '->request() sets the HTTPS header');

        $client = new TestClient();
        $client->request('GET', 'http://www.example.com:8080');
        $headers = $client->getRequest()->getServer();
        $this->assertEquals('www.example.com:8080', $headers['HTTP_HOST'], '->request() sets the HTTP_HOST header with port');
    }

    public function testRequestURIConversion()
    {
        $client = new TestClient();
        $client->request('GET', '/foo');
        $this->assertEquals('http://localhost/foo', $client->getRequest()->getUri(), '->request() converts the URI to an absolute one');

        $client = new TestClient();
        $client->request('GET', 'http://www.example.com');
        $this->assertEquals('http://www.example.com', $client->getRequest()->getUri(), '->request() does not change absolute URIs');

        $client = new TestClient();
        $client->request('GET', 'http://www.example.com/');
        $client->request('GET', '/foo');
        $this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->request() uses the previous request for relative URLs');

        $client = new TestClient();
        $client->request('GET', 'http://www.example.com/foo');
        $client->request('GET', '#');
        $this->assertEquals('http://www.example.com/foo#', $client->getRequest()->getUri(), '->request() uses the previous request for #');
        $client->request('GET', '#');
        $this->assertEquals('http://www.example.com/foo#', $client->getRequest()->getUri(), '->request() uses the previous request for #');
        $client->request('GET', '#foo');
        $this->assertEquals('http://www.example.com/foo#foo', $client->getRequest()->getUri(), '->request() uses the previous request for #');

        $client = new TestClient();
        $client->request('GET', 'http://www.example.com/foo/');
        $client->request('GET', 'bar');
        $this->assertEquals('http://www.example.com/foo/bar', $client->getRequest()->getUri(), '->request() uses the previous request for relative URLs');

        $client = new TestClient();
        $client->request('GET', 'http://www.example.com/foo/foobar');
        $client->request('GET', 'bar');
        $this->assertEquals('http://www.example.com/foo/bar', $client->getRequest()->getUri(), '->request() uses the previous request for relative URLs');
    }

    public function testRequestReferer()
    {
        $client = new TestClient();
        $client->request('GET', 'http://www.example.com/foo/foobar');
        $client->request('GET', 'bar');
        $server = $client->getRequest()->getServer();
        $this->assertEquals('http://www.example.com/foo/foobar', $server['HTTP_REFERER'], '->request() sets the referer');
    }

    public function testRequestHistory()
    {
        $client = new TestClient();
        $client->request('GET', 'http://www.example.com/foo/foobar');
        $client->request('GET', 'bar');

        $this->assertEquals('http://www.example.com/foo/bar', $client->getHistory()->current()->getUri(), '->request() updates the History');
        $this->assertEquals('http://www.example.com/foo/foobar', $client->getHistory()->back()->getUri(), '->request() updates the History');
    }

    public function testRequestCookies()
    {
        $client = new TestClient();
        $client->setNextResponse(new Response('<html><a href="/foo">foo</a></html>', 200, array('Set-Cookie' => 'foo=bar')));
        $client->request('GET', 'http://www.example.com/foo/foobar');
        $this->assertEquals(array('foo' => 'bar'), $client->getCookieJar()->allValues('http://www.example.com/foo/foobar'), '->request() updates the CookieJar');

        $client->request('GET', 'bar');
        $this->assertEquals(array('foo' => 'bar'), $client->getCookieJar()->allValues('http://www.example.com/foo/foobar'), '->request() updates the CookieJar');
    }

    public function testRequestSecureCookies()
    {
        $client = new TestClient();
        $client->setNextResponse(new Response('<html><a href="/foo">foo</a></html>', 200, array('Set-Cookie' => 'foo=bar; path=/; secure')));
        $client->request('GET', 'https://www.example.com/foo/foobar');

        $this->assertTrue($client->getCookieJar()->get('foo', '/', 'www.example.com')->isSecure());
    }

    public function testClick()
    {
        $client = new TestClient();
        $client->setNextResponse(new Response('<html><a href="/foo">foo</a></html>'));
        $crawler = $client->request('GET', 'http://www.example.com/foo/foobar');

        $client->click($crawler->filter('a')->link());

        $this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->click() clicks on links');
    }

    public function testClickForm()
    {
        $client = new TestClient();
        $client->setNextResponse(new Response('<html><form action="/foo"><input type="submit" /></form></html>'));
        $crawler = $client->request('GET', 'http://www.example.com/foo/foobar');

        $client->click($crawler->filter('input')->form());

        $this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->click() Form submit forms');
    }

    public function testSubmit()
    {
        $client = new TestClient();
        $client->setNextResponse(new Response('<html><form action="/foo"><input type="submit" /></form></html>'));
        $crawler = $client->request('GET', 'http://www.example.com/foo/foobar');

        $client->submit($crawler->filter('input')->form());

        $this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->submit() submit forms');
    }

    public function testSubmitPreserveAuth()
    {
        $client = new TestClient(array('PHP_AUTH_USER' => 'foo', 'PHP_AUTH_PW' => 'bar'));
        $client->setNextResponse(new Response('<html><form action="/foo"><input type="submit" /></form></html>'));
        $crawler = $client->request('GET', 'http://www.example.com/foo/foobar');

        $server = $client->getRequest()->getServer();
        $this->assertArrayHasKey('PHP_AUTH_USER', $server);
        $this->assertEquals('foo', $server['PHP_AUTH_USER']);
        $this->assertArrayHasKey('PHP_AUTH_PW', $server);
        $this->assertEquals('bar', $server['PHP_AUTH_PW']);

        $client->submit($crawler->filter('input')->form());

        $this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->submit() submit forms');

        $server = $client->getRequest()->getServer();
        $this->assertArrayHasKey('PHP_AUTH_USER', $server);
        $this->assertEquals('foo', $server['PHP_AUTH_USER']);
        $this->assertArrayHasKey('PHP_AUTH_PW', $server);
        $this->assertEquals('bar', $server['PHP_AUTH_PW']);
    }

    public function testFollowRedirect()
    {
        $client = new TestClient();
        $client->followRedirects(false);
        $client->request('GET', 'http://www.example.com/foo/foobar');

        try {
            $client->followRedirect();
            $this->fail('->followRedirect() throws a \LogicException if the request was not redirected');
        } catch (\Exception $e) {
            $this->assertInstanceof('LogicException', $e, '->followRedirect() throws a \LogicException if the request was not redirected');
        }

        $client->setNextResponse(new Response('', 302, array('Location' => 'http://www.example.com/redirected')));
        $client->request('GET', 'http://www.example.com/foo/foobar');
        $client->followRedirect();

        $this->assertEquals('http://www.example.com/redirected', $client->getRequest()->getUri(), '->followRedirect() follows a redirect if any');

        $client = new TestClient();
        $client->setNextResponse(new Response('', 302, array('Location' => 'http://www.example.com/redirected')));
        $client->request('GET', 'http://www.example.com/foo/foobar');

        $this->assertEquals('http://www.example.com/redirected', $client->getRequest()->getUri(), '->followRedirect() automatically follows redirects if followRedirects is true');

        $client = new TestClient();
        $client->setNextResponse(new Response('', 201, array('Location' => 'http://www.example.com/redirected')));
        $client->request('GET', 'http://www.example.com/foo/foobar');

        $this->assertEquals('http://www.example.com/foo/foobar', $client->getRequest()->getUri(), '->followRedirect() does not follow redirect if HTTP Code is not 30x');

        $client = new TestClient();
        $client->setNextResponse(new Response('', 201, array('Location' => 'http://www.example.com/redirected')));
        $client->followRedirects(false);
        $client->request('GET', 'http://www.example.com/foo/foobar');

        try {
            $client->followRedirect();
            $this->fail('->followRedirect() throws a \LogicException if the request did not respond with 30x HTTP Code');
        } catch (\Exception $e) {
            $this->assertInstanceof('LogicException', $e, '->followRedirect() throws a \LogicException if the request did not respond with 30x HTTP Code');
        }
    }

    public function testFollowRedirectWithMaxRedirects()
    {
        $client = new TestClient();
        $client->setMaxRedirects(1);
        $client->setNextResponse(new Response('', 302, array('Location' => 'http://www.example.com/redirected')));
        $client->request('GET', 'http://www.example.com/foo/foobar');
        $this->assertEquals('http://www.example.com/redirected', $client->getRequest()->getUri(), '->followRedirect() follows a redirect if any');

        $client->setNextResponse(new Response('', 302, array('Location' => 'http://www.example.com/redirected2')));
        try {
            $client->followRedirect();
            $this->fail('->followRedirect() throws a \LogicException if the request was redirected and limit of redirections was reached');
        } catch (\Exception $e) {
            $this->assertInstanceof('LogicException', $e, '->followRedirect() throws a \LogicException if the request was redirected and limit of redirections was reached');
        }

        $client->setNextResponse(new Response('', 302, array('Location' => 'http://www.example.com/redirected')));
        $client->request('GET', 'http://www.example.com/foo/foobar');
        $this->assertEquals('http://www.example.com/redirected', $client->getRequest()->getUri(), '->followRedirect() follows a redirect if any');

        $client->setNextResponse(new Response('', 302, array('Location' => '/redirected')));
        $client->request('GET', 'http://www.example.com/foo/foobar');

        $this->assertEquals('http://www.example.com/redirected', $client->getRequest()->getUri(), '->followRedirect() follows relative URLs');

        $client = new TestClient();
        $client->setNextResponse(new Response('', 302, array('Location' => '//www.example.org/')));
        $client->request('GET', 'https://www.example.com/');

        $this->assertEquals('https://www.example.org/', $client->getRequest()->getUri(), '->followRedirect() follows protocol-relative URLs');

        $client = new TestClient();
        $client->setNextResponse(new Response('', 302, array('Location' => 'http://www.example.com/redirected')));
        $client->request('POST', 'http://www.example.com/foo/foobar', array('name' => 'bar'));

        $this->assertEquals('get', $client->getRequest()->getMethod(), '->followRedirect() uses a get for 302');
        $this->assertEquals(array(), $client->getRequest()->getParameters(), '->followRedirect() does not submit parameters when changing the method');
    }

    public function testFollowRedirectWithCookies()
    {
        $client = new TestClient();
        $client->followRedirects(false);
        $client->setNextResponse(new Response('', 302, array(
            'Location'   => 'http://www.example.com/redirected',
            'Set-Cookie' => 'foo=bar',
        )));
        $client->request('GET', 'http://www.example.com/');
        $this->assertEquals(array(), $client->getRequest()->getCookies());
        $client->followRedirect();
        $this->assertEquals(array('foo' => 'bar'), $client->getRequest()->getCookies());
    }

    public function testFollowRedirectWithHeaders()
    {
        $headers = array(
            'HTTP_HOST'       => 'www.example.com',
            'HTTP_USER_AGENT' => 'Symfony2 BrowserKit',
            'CONTENT_TYPE'    => 'application/vnd.custom+xml',
            'HTTPS'           => false,
        );

        $client = new TestClient();
        $client->followRedirects(false);
        $client->setNextResponse(new Response('', 302, array(
            'Location'    => 'http://www.example.com/redirected',
        )));
        $client->request('GET', 'http://www.example.com/', array(), array(), array(
            'CONTENT_TYPE' => 'application/vnd.custom+xml',
        ));

        $this->assertEquals($headers, $client->getRequest()->getServer());

        $client->followRedirect();

        $headers['HTTP_REFERER'] = 'http://www.example.com/';

        $this->assertEquals($headers, $client->getRequest()->getServer());
    }

    public function testFollowRedirectWithPort()
    {
        $headers = array(
            'HTTP_HOST'       => 'www.example.com:8080',
            'HTTP_USER_AGENT' => 'Symfony2 BrowserKit',
            'HTTPS'           => false
        );

        $client = new TestClient();
        $client->followRedirects(false);
        $client->setNextResponse(new Response('', 302, array(
            'Location'    => 'http://www.example.com:8080/redirected',
        )));
        $client->request('GET', 'http://www.example.com:8080/');

        $this->assertEquals($headers, $client->getRequest()->getServer());
    }

    public function testBack()
    {
        $client = new TestClient();

        $parameters = array('foo' => 'bar');
        $files = array('myfile.foo' => 'baz');
        $server = array('X_TEST_FOO' => 'bazbar');
        $content = 'foobarbaz';

        $client->request('GET', 'http://www.example.com/foo/foobar', $parameters, $files, $server, $content);
        $client->request('GET', 'http://www.example.com/foo');
        $client->back();

        $this->assertEquals('http://www.example.com/foo/foobar', $client->getRequest()->getUri(), '->back() goes back in the history');
        $this->assertArrayHasKey('foo', $client->getRequest()->getParameters(), '->back() keeps parameters');
        $this->assertArrayHasKey('myfile.foo', $client->getRequest()->getFiles(), '->back() keeps files');
        $this->assertArrayHasKey('X_TEST_FOO', $client->getRequest()->getServer(), '->back() keeps $_SERVER');
        $this->assertEquals($content, $client->getRequest()->getContent(), '->back() keeps content');
    }

    public function testForward()
    {
        $client = new TestClient();

        $parameters = array('foo' => 'bar');
        $files = array('myfile.foo' => 'baz');
        $server = array('X_TEST_FOO' => 'bazbar');
        $content = 'foobarbaz';

        $client->request('GET', 'http://www.example.com/foo/foobar');
        $client->request('GET', 'http://www.example.com/foo', $parameters, $files, $server, $content);
        $client->back();
        $client->forward();

        $this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->forward() goes forward in the history');
        $this->assertArrayHasKey('foo', $client->getRequest()->getParameters(), '->forward() keeps parameters');
        $this->assertArrayHasKey('myfile.foo', $client->getRequest()->getFiles(), '->forward() keeps files');
        $this->assertArrayHasKey('X_TEST_FOO', $client->getRequest()->getServer(), '->forward() keeps $_SERVER');
        $this->assertEquals($content, $client->getRequest()->getContent(), '->forward() keeps content');
    }

    public function testReload()
    {
        $client = new TestClient();

        $parameters = array('foo' => 'bar');
        $files = array('myfile.foo' => 'baz');
        $server = array('X_TEST_FOO' => 'bazbar');
        $content = 'foobarbaz';

        $client->request('GET', 'http://www.example.com/foo/foobar', $parameters, $files, $server, $content);
        $client->reload();

        $this->assertEquals('http://www.example.com/foo/foobar', $client->getRequest()->getUri(), '->reload() reloads the current page');
        $this->assertArrayHasKey('foo', $client->getRequest()->getParameters(), '->reload() keeps parameters');
        $this->assertArrayHasKey('myfile.foo', $client->getRequest()->getFiles(), '->reload() keeps files');
        $this->assertArrayHasKey('X_TEST_FOO', $client->getRequest()->getServer(), '->reload() keeps $_SERVER');
        $this->assertEquals($content, $client->getRequest()->getContent(), '->reload() keeps content');
    }

    public function testRestart()
    {
        $client = new TestClient();
        $client->request('GET', 'http://www.example.com/foo/foobar');
        $client->restart();

        $this->assertTrue($client->getHistory()->isEmpty(), '->restart() clears the history');
        $this->assertEquals(array(), $client->getCookieJar()->all(), '->restart() clears the cookies');
    }

    public function testInsulatedRequests()
    {
        $client = new TestClient();
        $client->insulate();
        $client->setNextScript("new Symfony\Component\BrowserKit\Response('foobar')");
        $client->request('GET', 'http://www.example.com/foo/foobar');

        $this->assertEquals('foobar', $client->getResponse()->getContent(), '->insulate() process the request in a forked process');

        $client->setNextScript("new Symfony\Component\BrowserKit\Response('foobar)");

        try {
            $client->request('GET', 'http://www.example.com/foo/foobar');
            $this->fail('->request() throws a \RuntimeException if the script has an error');
        } catch (\Exception $e) {
            $this->assertInstanceof('RuntimeException', $e, '->request() throws a \RuntimeException if the script has an error');
        }
    }

    public function testGetServerParameter()
    {
        $client = new TestClient();
        $this->assertEquals('localhost', $client->getServerParameter('HTTP_HOST'));
        $this->assertEquals('Symfony2 BrowserKit', $client->getServerParameter('HTTP_USER_AGENT'));
        $this->assertEquals('testvalue', $client->getServerParameter('testkey', 'testvalue'));
    }

    public function testSetServerParameter()
    {
        $client = new TestClient();

        $this->assertEquals('localhost', $client->getServerParameter('HTTP_HOST'));
        $this->assertEquals('Symfony2 BrowserKit', $client->getServerParameter('HTTP_USER_AGENT'));

        $client->setServerParameter('HTTP_HOST', 'testhost');
        $this->assertEquals('testhost', $client->getServerParameter('HTTP_HOST'));

        $client->setServerParameter('HTTP_USER_AGENT', 'testua');
        $this->assertEquals('testua', $client->getServerParameter('HTTP_USER_AGENT'));
    }

    public function testSetServerParameterInRequest()
    {
        $client = new TestClient();

        $this->assertEquals('localhost', $client->getServerParameter('HTTP_HOST'));
        $this->assertEquals('Symfony2 BrowserKit', $client->getServerParameter('HTTP_USER_AGENT'));

        $client->request('GET', 'https://www.example.com/https/www.example.com', array(), array(), array(
            'HTTP_HOST'       => 'testhost',
            'HTTP_USER_AGENT' => 'testua',
            'HTTPS'           => false,
            'NEW_SERVER_KEY'  => 'new-server-key-value'
        ));

        $this->assertEquals('localhost', $client->getServerParameter('HTTP_HOST'));
        $this->assertEquals('Symfony2 BrowserKit', $client->getServerParameter('HTTP_USER_AGENT'));

        $this->assertEquals('http://testhost/https/www.example.com', $client->getRequest()->getUri());

        $server = $client->getRequest()->getServer();

        $this->assertArrayHasKey('HTTP_USER_AGENT', $server);
        $this->assertEquals('testua', $server['HTTP_USER_AGENT']);

        $this->assertArrayHasKey('HTTP_HOST', $server);
        $this->assertEquals('testhost', $server['HTTP_HOST']);

        $this->assertArrayHasKey('NEW_SERVER_KEY', $server);
        $this->assertEquals('new-server-key-value', $server['NEW_SERVER_KEY']);

        $this->assertArrayHasKey('HTTPS', $server);
        $this->assertFalse($server['HTTPS']);
    }
}
PK��Z�ɹ(RRAtest/BrowserKit/Symfony/Component/BrowserKit/Tests/CookieTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\BrowserKit\Tests;

use Symfony\Component\BrowserKit\Cookie;

class CookieTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getTestsForToFromString
     */
    public function testToFromString($cookie, $url = null)
    {
        $this->assertEquals($cookie, (string) Cookie::fromString($cookie, $url));
    }

    public function getTestsForToFromString()
    {
        return array(
            array('foo=bar; path=/'),
            array('foo=bar; path=/foo'),
            array('foo=bar; domain=google.com; path=/'),
            array('foo=bar; domain=example.com; path=/; secure', 'https://example.com/'),
            array('foo=bar; path=/; httponly'),
            array('foo=bar; domain=google.com; path=/foo; secure; httponly', 'https://google.com/'),
            array('foo=bar=baz; path=/'),
            array('foo=bar%3Dbaz; path=/'),
        );
    }

    public function testFromStringIgnoreSecureFlag()
    {
        $this->assertFalse(Cookie::fromString('foo=bar; secure')->isSecure());
        $this->assertFalse(Cookie::fromString('foo=bar; secure', 'http://example.com/')->isSecure());
    }

    /**
     * @dataProvider getExpireCookieStrings
     */
    public function testFromStringAcceptsSeveralExpiresDateFormats($cookie)
    {
        $this->assertEquals(1596185377, Cookie::fromString($cookie)->getExpiresTime());
    }

    public function getExpireCookieStrings()
    {
        return array(
            array('foo=bar; expires=Fri, 31-Jul-2020 08:49:37 GMT'),
            array('foo=bar; expires=Fri, 31 Jul 2020 08:49:37 GMT'),
            array('foo=bar; expires=Fri, 31-07-2020 08:49:37 GMT'),
            array('foo=bar; expires=Fri, 31-07-20 08:49:37 GMT'),
            array('foo=bar; expires=Friday, 31-Jul-20 08:49:37 GMT'),
            array('foo=bar; expires=Fri Jul 31 08:49:37 2020'),
            array('foo=bar; expires=\'Fri Jul 31 08:49:37 2020\''),
            array('foo=bar; expires=Friday July 31st 2020, 08:49:37 GMT'),
        );
    }

    public function testFromStringWithCapitalization()
    {
        $this->assertEquals('Foo=Bar; path=/', (string) Cookie::fromString('Foo=Bar'));
        $this->assertEquals('foo=bar; expires=Fri, 31 Dec 2010 23:59:59 GMT; path=/', (string) Cookie::fromString('foo=bar; Expires=Fri, 31 Dec 2010 23:59:59 GMT'));
        $this->assertEquals('foo=bar; domain=www.example.org; path=/; httponly', (string) Cookie::fromString('foo=bar; DOMAIN=www.example.org; HttpOnly'));
    }

    public function testFromStringWithUrl()
    {
        $this->assertEquals('foo=bar; domain=www.example.com; path=/', (string) Cookie::FromString('foo=bar', 'http://www.example.com/'));
        $this->assertEquals('foo=bar; domain=www.example.com; path=/foo', (string) Cookie::FromString('foo=bar', 'http://www.example.com/foo/bar'));
        $this->assertEquals('foo=bar; domain=www.example.com; path=/', (string) Cookie::FromString('foo=bar; path=/', 'http://www.example.com/foo/bar'));
        $this->assertEquals('foo=bar; domain=www.myotherexample.com; path=/', (string) Cookie::FromString('foo=bar; domain=www.myotherexample.com', 'http://www.example.com/'));
    }

    public function testFromStringThrowsAnExceptionIfCookieIsNotValid()
    {
        $this->setExpectedException('InvalidArgumentException');
        Cookie::FromString('foo');
    }

    public function testFromStringThrowsAnExceptionIfCookieDateIsNotValid()
    {
        $this->setExpectedException('InvalidArgumentException');
        Cookie::FromString('foo=bar; expires=Flursday July 31st 2020, 08:49:37 GMT');
    }

    public function testFromStringThrowsAnExceptionIfUrlIsNotValid()
    {
        $this->setExpectedException('InvalidArgumentException');
        Cookie::FromString('foo=bar', 'foobar');
    }

    public function testGetName()
    {
        $cookie = new Cookie('foo', 'bar');
        $this->assertEquals('foo', $cookie->getName(), '->getName() returns the cookie name');
    }

    public function testGetValue()
    {
        $cookie = new Cookie('foo', 'bar');
        $this->assertEquals('bar', $cookie->getValue(), '->getValue() returns the cookie value');

        $cookie = new Cookie('foo', 'bar%3Dbaz', null, '/', '', false, true, true); // raw value
        $this->assertEquals('bar=baz', $cookie->getValue(), '->getValue() returns the urldecoded cookie value');
    }

    public function testGetRawValue()
    {
        $cookie = new Cookie('foo', 'bar=baz'); // decoded value
        $this->assertEquals('bar%3Dbaz', $cookie->getRawValue(), '->getRawValue() returns the urlencoded cookie value');
        $cookie = new Cookie('foo', 'bar%3Dbaz', null, '/', '', false, true, true); // raw value
        $this->assertEquals('bar%3Dbaz', $cookie->getRawValue(), '->getRawValue() returns the non-urldecoded cookie value');
    }

    public function testGetPath()
    {
        $cookie = new Cookie('foo', 'bar', 0);
        $this->assertEquals('/', $cookie->getPath(), '->getPath() returns / is no path is defined');

        $cookie = new Cookie('foo', 'bar', 0, '/foo');
        $this->assertEquals('/foo', $cookie->getPath(), '->getPath() returns the cookie path');
    }

    public function testGetDomain()
    {
        $cookie = new Cookie('foo', 'bar', 0, '/', 'foo.com');
        $this->assertEquals('foo.com', $cookie->getDomain(), '->getDomain() returns the cookie domain');
    }

    public function testIsSecure()
    {
        $cookie = new Cookie('foo', 'bar');
        $this->assertFalse($cookie->isSecure(), '->isSecure() returns false if not defined');

        $cookie = new Cookie('foo', 'bar', 0, '/', 'foo.com', true);
        $this->assertTrue($cookie->isSecure(), '->isSecure() returns the cookie secure flag');
    }

    public function testIsHttponly()
    {
        $cookie = new Cookie('foo', 'bar');
        $this->assertTrue($cookie->isHttpOnly(), '->isHttpOnly() returns false if not defined');

        $cookie = new Cookie('foo', 'bar', 0, '/', 'foo.com', false, true);
        $this->assertTrue($cookie->isHttpOnly(), '->isHttpOnly() returns the cookie httponly flag');
    }

    public function testGetExpiresTime()
    {
        $cookie = new Cookie('foo', 'bar');
        $this->assertNull($cookie->getExpiresTime(), '->getExpiresTime() returns the expires time');

        $cookie = new Cookie('foo', 'bar', $time = time() - 86400);
        $this->assertEquals($time, $cookie->getExpiresTime(), '->getExpiresTime() returns the expires time');
    }

    public function testIsExpired()
    {
        $cookie = new Cookie('foo', 'bar');
        $this->assertFalse($cookie->isExpired(), '->isExpired() returns false when the cookie never expires (null as expires time)');

        $cookie = new Cookie('foo', 'bar', time() - 86400);
        $this->assertTrue($cookie->isExpired(), '->isExpired() returns true when the cookie is expired');

        $cookie = new Cookie('foo', 'bar', 0);
        $this->assertFalse($cookie->isExpired());
    }
}
PK��ZK����Btest/BrowserKit/Symfony/Component/BrowserKit/Tests/HistoryTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\BrowserKit\Tests;

use Symfony\Component\BrowserKit\History;
use Symfony\Component\BrowserKit\Request;

class HistoryTest extends \PHPUnit_Framework_TestCase
{
    public function testAdd()
    {
        $history = new History();
        $history->add(new Request('http://www.example1.com/', 'get'));
        $this->assertSame('http://www.example1.com/', $history->current()->getUri(), '->add() adds a request to the history');

        $history->add(new Request('http://www.example2.com/', 'get'));
        $this->assertSame('http://www.example2.com/', $history->current()->getUri(), '->add() adds a request to the history');

        $history->add(new Request('http://www.example3.com/', 'get'));
        $history->back();
        $history->add(new Request('http://www.example4.com/', 'get'));
        $this->assertSame('http://www.example4.com/', $history->current()->getUri(), '->add() adds a request to the history');

        $history->back();
        $this->assertSame('http://www.example2.com/', $history->current()->getUri(), '->add() adds a request to the history');
    }

    public function testClearIsEmpty()
    {
        $history = new History();
        $history->add(new Request('http://www.example.com/', 'get'));

        $this->assertFalse($history->isEmpty(), '->isEmpty() returns false if the history is not empty');

        $history->clear();

        $this->assertTrue($history->isEmpty(), '->isEmpty() true if the history is empty');
    }

    public function testCurrent()
    {
        $history = new History();

        try {
            $history->current();
            $this->fail('->current() throws a \LogicException if the history is empty');
        } catch (\Exception $e) {
            $this->assertInstanceof('LogicException', $e, '->current() throws a \LogicException if the history is empty');
        }

        $history->add(new Request('http://www.example.com/', 'get'));

        $this->assertSame('http://www.example.com/', $history->current()->getUri(), '->current() returns the current request in the history');
    }

    public function testBack()
    {
        $history = new History();
        $history->add(new Request('http://www.example.com/', 'get'));

        try {
            $history->back();
            $this->fail('->back() throws a \LogicException if the history is already on the first page');
        } catch (\Exception $e) {
            $this->assertInstanceof('LogicException', $e, '->current() throws a \LogicException if the history is already on the first page');
        }

        $history->add(new Request('http://www.example1.com/', 'get'));
        $history->back();

        $this->assertSame('http://www.example.com/', $history->current()->getUri(), '->back() returns the previous request in the history');
    }

    public function testForward()
    {
        $history = new History();
        $history->add(new Request('http://www.example.com/', 'get'));
        $history->add(new Request('http://www.example1.com/', 'get'));

        try {
            $history->forward();
            $this->fail('->forward() throws a \LogicException if the history is already on the last page');
        } catch (\Exception $e) {
            $this->assertInstanceof('LogicException', $e, '->forward() throws a \LogicException if the history is already on the last page');
        }

        $history->back();
        $history->forward();

        $this->assertSame('http://www.example1.com/', $history->current()->getUri(), '->forward() returns the next request in the history');
    }
}
PK��Z{2�wCtest/BrowserKit/Symfony/Component/BrowserKit/Tests/ResponseTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\BrowserKit\Tests;

use Symfony\Component\BrowserKit\Response;

class ResponseTest extends \PHPUnit_Framework_TestCase
{
    public function testGetUri()
    {
        $response = new Response('foo');
        $this->assertEquals('foo', $response->getContent(), '->getContent() returns the content of the response');
    }

    public function testGetStatus()
    {
        $response = new Response('foo', 304);
        $this->assertEquals('304', $response->getStatus(), '->getStatus() returns the status of the response');
    }

    public function testGetHeaders()
    {
        $response = new Response('foo', 200, array('foo' => 'bar'));
        $this->assertEquals(array('foo' => 'bar'), $response->getHeaders(), '->getHeaders() returns the headers of the response');
    }

    public function testGetHeader()
    {
        $response = new Response('foo', 200, array(
            'Content-Type' => 'text/html',
            'Set-Cookie'   => array('foo=bar', 'bar=foo'),
        ));

        $this->assertEquals('text/html', $response->getHeader('Content-Type'), '->getHeader() returns a header of the response');
        $this->assertEquals('text/html', $response->getHeader('content-type'), '->getHeader() returns a header of the response');
        $this->assertEquals('text/html', $response->getHeader('content_type'), '->getHeader() returns a header of the response');
        $this->assertEquals('foo=bar', $response->getHeader('Set-Cookie'), '->getHeader() returns the first header value');
        $this->assertEquals(array('foo=bar', 'bar=foo'), $response->getHeader('Set-Cookie', false), '->getHeader() returns all header values if first is false');

        $this->assertNull($response->getHeader('foo'), '->getHeader() returns null if the header is not defined');
        $this->assertEquals(array(), $response->getHeader('foo', false), '->getHeader() returns an empty array if the header is not defined and first is set to false');
    }

    public function testMagicToString()
    {
        $response = new Response('foo', 304, array('foo' => 'bar'));

        $this->assertEquals("foo: bar\n\nfoo", $response->__toString(), '->__toString() returns the headers and the content as a string');
    }

    public function testMagicToStringWithMultipleSetCookieHeader()
    {
        $headers = array(
            'content-type' => 'text/html; charset=utf-8',
            'set-cookie'   => array('foo=bar', 'bar=foo')
        );

        $expected = 'content-type: text/html; charset=utf-8'."\n";
        $expected.= 'set-cookie: foo=bar'."\n";
        $expected.= 'set-cookie: bar=foo'."\n\n";
        $expected.= 'foo';

        $response = new Response('foo', 304, $headers);

        $this->assertEquals($expected, $response->__toString(), '->__toString() returns the headers and the content as a string');
    }
}
PK��Z|����Btest/BrowserKit/Symfony/Component/BrowserKit/Tests/RequestTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\BrowserKit\Tests;

use Symfony\Component\BrowserKit\Request;

class RequestTest extends \PHPUnit_Framework_TestCase
{
    public function testGetUri()
    {
        $request = new Request('http://www.example.com/', 'get');
        $this->assertEquals('http://www.example.com/', $request->getUri(), '->getUri() returns the URI of the request');
    }

    public function testGetMethod()
    {
        $request = new Request('http://www.example.com/', 'get');
        $this->assertEquals('get', $request->getMethod(), '->getMethod() returns the method of the request');
    }

    public function testGetParameters()
    {
        $request = new Request('http://www.example.com/', 'get', array('foo' => 'bar'));
        $this->assertEquals(array('foo' => 'bar'), $request->getParameters(), '->getParameters() returns the parameters of the request');
    }

    public function testGetFiles()
    {
        $request = new Request('http://www.example.com/', 'get', array(), array('foo' => 'bar'));
        $this->assertEquals(array('foo' => 'bar'), $request->getFiles(), '->getFiles() returns the uploaded files of the request');
    }

    public function testGetCookies()
    {
        $request = new Request('http://www.example.com/', 'get', array(), array(), array('foo' => 'bar'));
        $this->assertEquals(array('foo' => 'bar'), $request->getCookies(), '->getCookies() returns the cookies of the request');
    }

    public function testGetServer()
    {
        $request = new Request('http://www.example.com/', 'get', array(), array(), array(), array('foo' => 'bar'));
        $this->assertEquals(array('foo' => 'bar'), $request->getServer(), '->getServer() returns the server parameters of the request');
    }
}
PK��Z�p6ll=test/BrowserKit/Symfony/Component/BrowserKit/phpunit.xml.distnu�[���<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony BrowserKit Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./Resources</directory>
                <directory>./Tests</directory>
                <directory>./vendor</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
PK��Z?7��EE9test/Net_IDNA2/tests/draft-josefsson-idn-test-vectors.phpnu�[���<?php
require_once 'Net/IDNA2.php';

// Test cases from https://www.gnu.org/software/libidn/draft-josefsson-idn-test-vectors.html

define('IDNA_ACE_PREFIX', 'xn--');

class IDNATest extends PHPUnit_Framework_TestCase {

    public function setUp() {
        $this->idn = new Net_IDNA2();
    }

    static function unichr($chr) {
        return mb_convert_encoding('&#' . intval($chr) . ';', 'UTF-8', 'HTML-ENTITIES');
    }

    private function hexarray2string($arr) {
        return implode('', array_map(array('self', 'unichr'), $arr));
    }

    public function testDecode1() {
        // Arabic (Egyptian)
        $expected = $this->hexarray2string(array(
            0x0644, 0x064A, 0x0647, 0x0645, 0x0627, 0x0628, 0x062A, 0x0643,
	        0x0644, 0x0645, 0x0648, 0x0634, 0x0639, 0x0631, 0x0628, 0x064A,
	        0x061F
	    ));
        $result = $this->idn->decode(IDNA_ACE_PREFIX."egbpdaj6bu4bxfgehfvwxn");
        $this->assertSame($expected, $result);
    }

    public function testDecode2() {
        // Chinese (simplified)
        $expected = $this->hexarray2string(array(
            0x4ED6, 0x4EEC, 0x4E3A, 0x4EC0, 0x4E48, 0x4E0D, 0x8BF4, 0x4E2D, 0x6587
	    ));
        $result = $this->idn->decode(IDNA_ACE_PREFIX."ihqwcrb4cv8a8dqg056pqjye");
        $this->assertSame($expected, $result);
    }

    public function testDecode3() {
        // Chinese (traditional)
        $expected = $this->hexarray2string(array(
            0x4ED6, 0x5011, 0x7232, 0x4EC0, 0x9EBD, 0x4E0D, 0x8AAA, 0x4E2D, 0x6587
	    ));
        $result = $this->idn->decode(IDNA_ACE_PREFIX."ihqwctvzc91f659drss3x8bo0yb");
        $this->assertSame($expected, $result);
    }

    public function testDecode4() {
        // Czech
        $expected = $this->hexarray2string(array(
            0x0050, 0x0072, 0x006F, 0x010D, 0x0070, 0x0072, 0x006F, 0x0073,
	        0x0074, 0x011B, 0x006E, 0x0065, 0x006D, 0x006C, 0x0075, 0x0076,
	        0x00ED, 0x010D, 0x0065, 0x0073, 0x006B, 0x0079
	    ));
        $result = $this->idn->decode(IDNA_ACE_PREFIX."Proprostnemluvesky-uyb24dma41a");
        $this->assertSame($expected, $result);
    }

    public function testDecode5() {
        // Hebrew
        $expected = $this->hexarray2string(array(
            0x05DC, 0x05DE, 0x05D4, 0x05D4, 0x05DD, 0x05E4, 0x05E9, 0x05D5,
	        0x05D8, 0x05DC, 0x05D0, 0x05DE, 0x05D3, 0x05D1, 0x05E8, 0x05D9,
	        0x05DD, 0x05E2, 0x05D1, 0x05E8, 0x05D9, 0x05EA
	    ));
        $result = $this->idn->decode(IDNA_ACE_PREFIX."4dbcagdahymbxekheh6e0a7fei0b");
        $this->assertSame($expected, $result);
    }

      public function testDecode6() {
        // Hindi (Devanagari)
        $expected = $this->hexarray2string(array(
            0x092F, 0x0939, 0x0932, 0x094B, 0x0917, 0x0939, 0x093F, 0x0928,
        	0x094D, 0x0926, 0x0940, 0x0915, 0x094D, 0x092F, 0x094B, 0x0902,
	        0x0928, 0x0939, 0x0940, 0x0902, 0x092C, 0x094B, 0x0932, 0x0938,
	        0x0915, 0x0924, 0x0947, 0x0939, 0x0948, 0x0902
	    ));
        $result = $this->idn->decode(IDNA_ACE_PREFIX."i1baa7eci9glrd9b2ae1bj0hfcgg6iyaf8o0a1dig0cd");
        $this->assertSame($expected, $result);
    }

    public function testDecode7() {
        // Japanese (kanji and hiragana)
        $expected = $this->hexarray2string(array(
            0x306A, 0x305C, 0x307F, 0x3093, 0x306A, 0x65E5, 0x672C, 0x8A9E,
        	0x3092, 0x8A71, 0x3057, 0x3066, 0x304F, 0x308C, 0x306A, 0x3044,
        	0x306E, 0x304B
	    ));
        $result = $this->idn->decode(IDNA_ACE_PREFIX."n8jok5ay5dzabd5bym9f0cm5685rrjetr6pdxa");
        $this->assertSame($expected, $result);
    }

    public function testDecode8() {
        // Russian (Cyrillic)
        $expected = $this->hexarray2string(array(
            0x043F, 0x043E, 0x0447, 0x0435, 0x043C, 0x0443, 0x0436, 0x0435,
        	0x043E, 0x043D, 0x0438, 0x043D, 0x0435, 0x0433, 0x043E, 0x0432,
        	0x043E, 0x0440, 0x044F, 0x0442, 0x043F, 0x043E, 0x0440, 0x0443,
        	0x0441, 0x0441, 0x043A, 0x0438
	    ));
        $result = $this->idn->decode(IDNA_ACE_PREFIX."b1abfaaepdrnnbgefbadotcwatmq2g4l");
        $this->assertSame($expected, $result);
    }

    public function testDecode9() {
        // Spanish
        $expected = $this->hexarray2string(array(
            0x0050, 0x006F, 0x0072, 0x0071, 0x0075, 0x00E9, 0x006E, 0x006F,
        	0x0070, 0x0075, 0x0065, 0x0064, 0x0065, 0x006E, 0x0073, 0x0069,
        	0x006D, 0x0070, 0x006C, 0x0065, 0x006D, 0x0065, 0x006E, 0x0074,
        	0x0065, 0x0068, 0x0061, 0x0062, 0x006C, 0x0061, 0x0072, 0x0065,
        	0x006E, 0x0045, 0x0073, 0x0070, 0x0061, 0x00F1, 0x006F, 0x006C
	    ));
        $result = $this->idn->decode(IDNA_ACE_PREFIX."PorqunopuedensimplementehablarenEspaol-fmd56a");
        $this->assertSame($expected, $result);
    }

    public function testDecode10() {
        // Vietnamese
        $expected = $this->hexarray2string(array(
            0x0054, 0x1EA1, 0x0069, 0x0073, 0x0061, 0x006F, 0x0068, 0x1ECD,
        	0x006B, 0x0068, 0x00F4, 0x006E, 0x0067, 0x0074, 0x0068, 0x1EC3,
        	0x0063, 0x0068, 0x1EC9, 0x006E, 0x00F3, 0x0069, 0x0074, 0x0069,
        	0x1EBF, 0x006E, 0x0067, 0x0056, 0x0069, 0x1EC7, 0x0074
	    ));
        $result = $this->idn->decode(IDNA_ACE_PREFIX."TisaohkhngthchnitingVit-kjcr8268qyxafd2f1b9g");
        $this->assertSame($expected, $result);
    }

    public function testDecode11() {
        // Japanese
        $expected = $this->hexarray2string(array(
            0x0033, 0x5E74, 0x0042, 0x7D44, 0x91D1, 0x516B, 0x5148, 0x751F
	    ));
        $result = $this->idn->decode(IDNA_ACE_PREFIX."3B-ww4c5e180e575a65lsy2b");
        $this->assertSame($expected, $result);
    }

    public function testDecode12() {
        // Japanese
        $expected = $this->hexarray2string(array(
            0x5B89, 0x5BA4, 0x5948, 0x7F8E, 0x6075, 0x002D, 0x0077, 0x0069,
        	0x0074, 0x0068, 0x002D, 0x0053, 0x0055, 0x0050, 0x0045, 0x0052,
        	0x002D, 0x004D, 0x004F, 0x004E, 0x004B, 0x0045, 0x0059, 0x0053
	    ));
        $result = $this->idn->decode(IDNA_ACE_PREFIX."-with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n");
        $this->assertSame($expected, $result);
    }

    public function testDecode13() {
        // Japanese
        $expected = $this->hexarray2string(array(
            0x0048, 0x0065, 0x006C, 0x006C, 0x006F, 0x002D, 0x0041, 0x006E,
	        0x006F, 0x0074, 0x0068, 0x0065, 0x0072, 0x002D, 0x0057, 0x0061,
        	0x0079, 0x002D, 0x305D, 0x308C, 0x305E, 0x308C, 0x306E, 0x5834,
        	0x6240
	    ));
        $result = $this->idn->decode(IDNA_ACE_PREFIX."Hello-Another-Way--fc4qua05auwb3674vfr0b");
        $this->assertSame($expected, $result);
    }

    public function testDecode14() {
        // Japanese
        $expected = $this->hexarray2string(array(
            0x3072, 0x3068, 0x3064, 0x5C4B, 0x6839, 0x306E, 0x4E0B, 0x0032
	    ));
        $result = $this->idn->decode(IDNA_ACE_PREFIX."2-u9tlzr9756bt3uc0v");
        $this->assertSame($expected, $result);
    }

    public function testDecode15() {
        // Japanese
        $expected = $this->hexarray2string(array(
            0x004D, 0x0061, 0x006A, 0x0069, 0x3067, 0x004B, 0x006F, 0x0069,
        	0x3059, 0x308B, 0x0035, 0x79D2, 0x524D
	    ));
        $result = $this->idn->decode(IDNA_ACE_PREFIX."MajiKoi5-783gue6qz075azm5e");
        $this->assertSame($expected, $result);
    }

    public function testDecode16() {
        // Japanese
        $expected = $this->hexarray2string(array(
            0x30D1, 0x30D5, 0x30A3, 0x30FC, 0x0064, 0x0065, 0x30EB, 0x30F3, 0x30D0
	    ));
        $result = $this->idn->decode(IDNA_ACE_PREFIX."de-jg4avhby1noc0d");
        $this->assertSame($expected, $result);
    }

    public function testDecode17() {
        // Japanese
        $expected = $this->hexarray2string(array(
            0x305D, 0x306E, 0x30B9, 0x30D4, 0x30FC, 0x30C9, 0x3067
	    ));
        $result = $this->idn->decode(IDNA_ACE_PREFIX."d9juau41awczczp");
        $this->assertSame($expected, $result);
    }

    public function testDecode18() {
        // Greek
        $expected = $this->hexarray2string(array(
            0x03b5, 0x03bb, 0x03bb, 0x03b7, 0x03bd, 0x03b9, 0x03ba, 0x03ac
	    ));
        $result = $this->idn->decode(IDNA_ACE_PREFIX."hxargifdar");
        $this->assertSame($expected, $result);
    }

    public function testDecode19() {
        // Maltese (Malti)
        $expected = $this->hexarray2string(array(
            0x0062, 0x006f, 0x006e, 0x0121, 0x0075, 0x0073, 0x0061, 0x0127,
            0x0127, 0x0061
	    ));
        $result = $this->idn->decode(IDNA_ACE_PREFIX."bonusaa-5bb1da");
        $this->assertSame($expected, $result);
    }

    public function testDecode20() {
        // Russian (Cyrillic)
        $expected = $this->hexarray2string(array(
            0x043f, 0x043e, 0x0447, 0x0435, 0x043c, 0x0443, 0x0436, 0x0435,
            0x043e, 0x043d, 0x0438, 0x043d, 0x0435, 0x0433, 0x043e, 0x0432,
            0x043e, 0x0440, 0x044f, 0x0442, 0x043f, 0x043e, 0x0440, 0x0443,
            0x0441, 0x0441, 0x043a, 0x0438
	    ));
        $result = $this->idn->decode(IDNA_ACE_PREFIX."b1abfaaepdrnnbgefbadotcwatmq2g4l");
        $this->assertSame($expected, $result);
    }

    public function testEncode1() {
        // Arabic (Egyptian)
        $idna = $this->hexarray2string(array(
            0x0644, 0x064A, 0x0647, 0x0645, 0x0627, 0x0628, 0x062A, 0x0643,
	        0x0644, 0x0645, 0x0648, 0x0634, 0x0639, 0x0631, 0x0628, 0x064A,
	        0x061F
	    ));
        $result = $this->idn->encode($idna);
        $this->assertSame(IDNA_ACE_PREFIX."egbpdaj6bu4bxfgehfvwxn", $result);
    }

    public function testEncode2() {
        // Chinese (simplified)
        $idna = $this->hexarray2string(array(
            0x4ED6, 0x4EEC, 0x4E3A, 0x4EC0, 0x4E48, 0x4E0D, 0x8BF4, 0x4E2D, 0x6587
	    ));
        $result = $this->idn->encode($idna);
        $this->assertSame(IDNA_ACE_PREFIX."ihqwcrb4cv8a8dqg056pqjye", $result);
    }

    public function testEncode3() {
        // Chinese (traditional)
        $idna = $this->hexarray2string(array(
            0x4ED6, 0x5011, 0x7232, 0x4EC0, 0x9EBD, 0x4E0D, 0x8AAA, 0x4E2D, 0x6587
	    ));
        $result = $this->idn->encode($idna);
        $this->assertSame(IDNA_ACE_PREFIX."ihqwctvzc91f659drss3x8bo0yb", $result);
    }

    public function testEncode4() {
        // Czech
        $idna = $this->hexarray2string(array(
            0x0050, 0x0072, 0x006F, 0x010D, 0x0070, 0x0072, 0x006F, 0x0073,
	        0x0074, 0x011B, 0x006E, 0x0065, 0x006D, 0x006C, 0x0075, 0x0076,
	        0x00ED, 0x010D, 0x0065, 0x0073, 0x006B, 0x0079
	    ));
        $result = $this->idn->encode($idna);
        $this->assertSame(IDNA_ACE_PREFIX."proprostnemluvesky-uyb24dma41a", $result);
    }

    public function testEncode5() {
        // Hebrew
        $idna = $this->hexarray2string(array(
            0x05DC, 0x05DE, 0x05D4, 0x05D4, 0x05DD, 0x05E4, 0x05E9, 0x05D5,
	        0x05D8, 0x05DC, 0x05D0, 0x05DE, 0x05D3, 0x05D1, 0x05E8, 0x05D9,
	        0x05DD, 0x05E2, 0x05D1, 0x05E8, 0x05D9, 0x05EA
	    ));
        $result = $this->idn->encode($idna);
        $this->assertSame(IDNA_ACE_PREFIX."4dbcagdahymbxekheh6e0a7fei0b", $result);
    }

      public function testEncode6() {
        // Hindi (Devanagari)
        $idna = $this->hexarray2string(array(
            0x092F, 0x0939, 0x0932, 0x094B, 0x0917, 0x0939, 0x093F, 0x0928,
        	0x094D, 0x0926, 0x0940, 0x0915, 0x094D, 0x092F, 0x094B, 0x0902,
	        0x0928, 0x0939, 0x0940, 0x0902, 0x092C, 0x094B, 0x0932, 0x0938,
	        0x0915, 0x0924, 0x0947, 0x0939, 0x0948, 0x0902
	    ));
        $result = $this->idn->encode($idna);
        $this->assertSame(IDNA_ACE_PREFIX."i1baa7eci9glrd9b2ae1bj0hfcgg6iyaf8o0a1dig0cd", $result);
    }

    public function testEncode7() {
        // Japanese (kanji and hiragana)
        $idna = $this->hexarray2string(array(
            0x306A, 0x305C, 0x307F, 0x3093, 0x306A, 0x65E5, 0x672C, 0x8A9E,
        	0x3092, 0x8A71, 0x3057, 0x3066, 0x304F, 0x308C, 0x306A, 0x3044,
        	0x306E, 0x304B
	    ));
        $result = $this->idn->encode($idna);
        $this->assertSame(IDNA_ACE_PREFIX."n8jok5ay5dzabd5bym9f0cm5685rrjetr6pdxa", $result);
    }

    public function testEncode8() {
        // Russian (Cyrillic)
        $idna = $this->hexarray2string(array(
            0x043F, 0x043E, 0x0447, 0x0435, 0x043C, 0x0443, 0x0436, 0x0435,
        	0x043E, 0x043D, 0x0438, 0x043D, 0x0435, 0x0433, 0x043E, 0x0432,
        	0x043E, 0x0440, 0x044F, 0x0442, 0x043F, 0x043E, 0x0440, 0x0443,
        	0x0441, 0x0441, 0x043A, 0x0438
	    ));
        $result = $this->idn->encode($idna);
        $this->assertSame(IDNA_ACE_PREFIX."b1abfaaepdrnnbgefbadotcwatmq2g4l", $result);
    }

    public function testEncode9() {
        // Spanish
        $idna = $this->hexarray2string(array(
            0x0050, 0x006F, 0x0072, 0x0071, 0x0075, 0x00E9, 0x006E, 0x006F,
        	0x0070, 0x0075, 0x0065, 0x0064, 0x0065, 0x006E, 0x0073, 0x0069,
        	0x006D, 0x0070, 0x006C, 0x0065, 0x006D, 0x0065, 0x006E, 0x0074,
        	0x0065, 0x0068, 0x0061, 0x0062, 0x006C, 0x0061, 0x0072, 0x0065,
        	0x006E, 0x0045, 0x0073, 0x0070, 0x0061, 0x00F1, 0x006F, 0x006C
	    ));
        $result = $this->idn->encode($idna);
        $this->assertSame(IDNA_ACE_PREFIX."porqunopuedensimplementehablarenespaol-fmd56a", $result);
    }

    public function testEncode10() {
        // Vietnamese
        $idna = $this->hexarray2string(array(
            0x0054, 0x1EA1, 0x0069, 0x0073, 0x0061, 0x006F, 0x0068, 0x1ECD,
        	0x006B, 0x0068, 0x00F4, 0x006E, 0x0067, 0x0074, 0x0068, 0x1EC3,
        	0x0063, 0x0068, 0x1EC9, 0x006E, 0x00F3, 0x0069, 0x0074, 0x0069,
        	0x1EBF, 0x006E, 0x0067, 0x0056, 0x0069, 0x1EC7, 0x0074
	    ));
        $result = $this->idn->encode($idna);
        $this->assertSame(IDNA_ACE_PREFIX."tisaohkhngthchnitingvit-kjcr8268qyxafd2f1b9g", $result);
    }

    public function testEncode11() {
        // Japanese
        $idna = $this->hexarray2string(array(
            0x0033, 0x5E74, 0x0042, 0x7D44, 0x91D1, 0x516B, 0x5148, 0x751F
	    ));
        $result = $this->idn->encode($idna);
        $this->assertSame(IDNA_ACE_PREFIX."3b-ww4c5e180e575a65lsy2b", $result);
    }

    public function testEncode12() {
        // Japanese
        $idna = $this->hexarray2string(array(
            0x5B89, 0x5BA4, 0x5948, 0x7F8E, 0x6075, 0x002D, 0x0077, 0x0069,
        	0x0074, 0x0068, 0x002D, 0x0053, 0x0055, 0x0050, 0x0045, 0x0052,
        	0x002D, 0x004D, 0x004F, 0x004E, 0x004B, 0x0045, 0x0059, 0x0053
	    ));
        $result = $this->idn->encode($idna);
        $this->assertSame(IDNA_ACE_PREFIX."-with-super-monkeys-pc58ag80a8qai00g7n9n", $result);
    }

    public function testEncode13() {
        // Japanese
        $idna = $this->hexarray2string(array(
            0x0048, 0x0065, 0x006C, 0x006C, 0x006F, 0x002D, 0x0041, 0x006E,
	        0x006F, 0x0074, 0x0068, 0x0065, 0x0072, 0x002D, 0x0057, 0x0061,
        	0x0079, 0x002D, 0x305D, 0x308C, 0x305E, 0x308C, 0x306E, 0x5834,
        	0x6240
	    ));
        $result = $this->idn->encode($idna);
        $this->assertSame(IDNA_ACE_PREFIX."hello-another-way--fc4qua05auwb3674vfr0b", $result);
    }

    public function testEncode14() {
        // Japanese
        $idna = $this->hexarray2string(array(
            0x3072, 0x3068, 0x3064, 0x5C4B, 0x6839, 0x306E, 0x4E0B, 0x0032
	    ));
        $result = $this->idn->encode($idna);
        $this->assertSame(IDNA_ACE_PREFIX."2-u9tlzr9756bt3uc0v", $result);
    }

    public function testEncode15() {
        // Japanese
        $idna = $this->hexarray2string(array(
            0x004D, 0x0061, 0x006A, 0x0069, 0x3067, 0x004B, 0x006F, 0x0069,
        	0x3059, 0x308B, 0x0035, 0x79D2, 0x524D
	    ));
        $result = $this->idn->encode($idna);
        $this->assertSame(IDNA_ACE_PREFIX."majikoi5-783gue6qz075azm5e", $result);
    }

    public function testEncode16() {
        // Japanese
        $idna = $this->hexarray2string(array(
            0x30D1, 0x30D5, 0x30A3, 0x30FC, 0x0064, 0x0065, 0x30EB, 0x30F3, 0x30D0
	    ));
        $result = $this->idn->encode($idna);
        $this->assertSame(IDNA_ACE_PREFIX."de-jg4avhby1noc0d", $result);
    }

    public function testEncode17() {
        // Japanese
        $idna = $this->hexarray2string(array(
            0x305D, 0x306E, 0x30B9, 0x30D4, 0x30FC, 0x30C9, 0x3067
	    ));
        $result = $this->idn->encode($idna);
        $this->assertSame(IDNA_ACE_PREFIX."d9juau41awczczp", $result);
    }

    public function testEncode18() {
        // Greek
        $idna = $this->hexarray2string(array(
            0x03b5, 0x03bb, 0x03bb, 0x03b7, 0x03bd, 0x03b9, 0x03ba, 0x03ac
	    ));
        $result = $this->idn->encode($idna);
        $this->assertSame(IDNA_ACE_PREFIX."hxargifdar", $result);
    }

    public function testEncode19() {
        // Maltese (Malti)
        $idna = $this->hexarray2string(array(
            0x0062, 0x006f, 0x006e, 0x0121, 0x0075, 0x0073, 0x0061, 0x0127,
            0x0127, 0x0061
	    ));
        $result = $this->idn->encode($idna);
        $this->assertSame(IDNA_ACE_PREFIX."bonusaa-5bb1da", $result);
    }

    public function testEncode20() {
        // Russian (Cyrillic)
        $idna = $this->hexarray2string(array(
            0x043f, 0x043e, 0x0447, 0x0435, 0x043c, 0x0443, 0x0436, 0x0435,
            0x043e, 0x043d, 0x0438, 0x043d, 0x0435, 0x0433, 0x043e, 0x0432,
            0x043e, 0x0440, 0x044f, 0x0442, 0x043f, 0x043e, 0x0440, 0x0443,
            0x0441, 0x0441, 0x043a, 0x0438
	    ));
        $result = $this->idn->encode($idna);
        $this->assertSame(IDNA_ACE_PREFIX."b1abfaaepdrnnbgefbadotcwatmq2g4l", $result);
    }

}

PK��ZE��mm&test/Net_IDNA2/tests/Net_IDNA2Test.phpnu�[���<?php
require_once 'Net/IDNA2.php';

class Net_IDNA2Test extends PHPUnit_Framework_TestCase
{
    /**
     * Initialise tests
     *
     * @return void
     */
    public function setUp()
    {
        $this->idn = new Net_IDNA2();
    }

    /**
     * Test if a complete URL consisting also of port-number etc. will be decoded just fine, test 1
     *
     * @return void
     */
    public function testShouldDecodePortNumbersFragmentsAndUrisCorrectly1()
    {
        $result = $this->idn->decode('http://www.xn--ml-6kctd8d6a.org:8080/test.php?arg1=1&arg2=2#fragment');
        $this->assertSame("http://www.\xD0\xB5\xD1\x85\xD0\xB0m\xD1\x80l\xD0\xB5.org:8080/test.php?arg1=1&arg2=2#fragment", $result);
    }

    /**
     * Test if a complete URL consisting also of port-number etc. will be decoded just fine, test 2
     *
     * @return void
     */
    public function testShouldDecodePortNumbersFragmentsAndUrisCorrectly2()
    {
        $result = $this->idn->decode('http://xn--tst-qla.example.com:8080/test.php?arg1=1&arg2=2#fragment');
        $this->assertSame("http://täst.example.com:8080/test.php?arg1=1&arg2=2#fragment", $result);
    }

    /**
     * Test encoding of German letter Eszett according to the original standard (IDNA2003)
     *
     * @return void
     */
    public function testEncodingForGermanEszettUsingIDNA2003()
    {
        // make sure to use 2003-encoding
        $this->idn->setParams('version', '2003');
        $result = $this->idn->encode('http://www.straße.example.com/');

        $this->assertSame("http://www.strasse.example.com/", $result);
    }

    /**
     * Test encoding of German letter Eszett according to the "new" standard (IDNA2005/IDNAbis)
     *
     * @return void
     */
    public function testEncodingForGermanEszettUsingIDNA2008()
    {
        // make sure to use 2008-encoding
        $this->idn->setParams('version', '2008');
        $result = $this->idn->encode('http://www.straße.example.com/');
        // switch back for other testcases
        $this->idn->setParams('version', '2003');

        $this->assertSame("http://www.xn--strae-oqa.example.com/", $result);
    }
}
PK��Z.��
��"test/XML_RPC/tests/extra-lines.phpnu�[���<?php

/**
 * Tests how the XML_RPC server handles parameters with empty values.
 *
 * PHP versions 4 and 5
 *
 * @category   Web Services
 * @package    XML_RPC
 * @author     Daniel Convissor <danielc@php.net>
 * @copyright  2005-2010 The PHP Group
 * @license    http://www.php.net/license/3_01.txt  PHP License
 * @version    SVN: $Id: extra-lines.php 300958 2010-07-02 23:58:51Z danielc $
 * @link       http://pear.php.net/package/XML_RPC
 * @since      File available since Release 1.4.4
 */

/*
 * If the package version number is found in the left hand
 * portion of the if() expression below, that means this file has
 * come from the PEAR installer.  Therefore, let's test the
 * installed version of XML_RPC which should be in the include path.
 *
 * If the version has not been substituted in the if() expression,
 * this file has likely come from a SVN checkout or a .tar file.
 * Therefore, we'll assume the tests should use the version of
 * XML_RPC that has come from there as well.
 */
if ('1.5.5' == '@'.'package_version'.'@') {
    ini_set('include_path', '../'
            . PATH_SEPARATOR . '.' . PATH_SEPARATOR
            . ini_get('include_path')
    );
}
require_once 'XML/RPC.php';


$input = "First lfs\n\nSecond crlfs\r\n\r\nThird crs\r\rFourth line";

$expect_removed = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<methodCall>\r\n<methodName>nada</methodName>\r\n<params>\r\n<param>\r\n<value><string>First lfs\r\nSecond crlfs\r\nThird crs\r\nFourth line</string></value>\r\n</param>\r\n</params>\r\n</methodCall>\r\n";

$expect_not_removed = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<methodCall>\r\n<methodName>nada</methodName>\r\n<params>\r\n<param>\r\n<value><string>First lfs\r\n\r\nSecond crlfs\r\n\r\nThird crs\r\n\r\nFourth line</string></value>\r\n</param>\r\n</params>\r\n</methodCall>\r\n";

$msg = new XML_RPC_Message('nada', array(XML_RPC_encode($input)));
$msg->createPayload();
if ($msg->payload == $expect_removed) {
    echo "passed\n";
} else {
    echo "PROBLEM\n";
}

$msg = new XML_RPC_Message('nada', array(XML_RPC_encode($input)));
$msg->remove_extra_lines = false;
$msg->createPayload();
if ($msg->payload == $expect_not_removed) {
    echo "passed\n";
} else {
    echo "PROBLEM\n";
}
PK��Z|�E)test/XML_RPC/tests/empty-value-struct.phpnu�[���<?php

/**
 * Tests how the XML_RPC server handles a parameter with an empty struct without
 * any spaces in the XML after the empty value.
 *
 * PHP versions 4 and 5
 *
 * @category   Web Services
 * @package    XML_RPC
 * @author     Daniel Convissor <danielc@php.net>
 * @copyright  2005-2010 The PHP Group
 * @license    http://www.php.net/license/3_01.txt  PHP License
 * @version    SVN: $Id: empty-value-struct.php 300957 2010-07-02 23:55:00Z danielc $
 * @link       http://pear.php.net/package/XML_RPC
 * @since      File available since Release 1.4.4
 */

/*
 * If the package version number is found in the left hand
 * portion of the if() expression below, that means this file has
 * come from the PEAR installer.  Therefore, let's test the
 * installed version of XML_RPC which should be in the include path.
 *
 * If the version has not been substituted in the if() expression,
 * this file has likely come from a SVN checkout or a .tar file.
 * Therefore, we'll assume the tests should use the version of
 * XML_RPC that has come from there as well.
 */
if ('1.5.5' == '@'.'package_version'.'@') {
    ini_set('include_path', '../'
            . PATH_SEPARATOR . '.' . PATH_SEPARATOR
            . ini_get('include_path')
    );
}
require_once 'XML/RPC/Server.php';


$GLOBALS['HTTP_RAW_POST_DATA'] = <<<EOPOST
<?xml version="1.0"?>
<methodCall>
 <methodName>allgot</methodName>
  <params>
   <param>
    <value>
     <struct>
      <member>
      <name>fld1</name><value></value></member></struct></value>
   </param>
  </params>
 </methodCall>
EOPOST;

$expect = <<<EOEXP
<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
<params>
<param>
<value><string>param 0: array (
  'fld1' =&gt; '',
)
</string></value>
</param>
</params>
</methodResponse>
EOEXP;

include './allgot.inc';
PK��Z�3l�** test/XML_RPC/tests/protoport.phpnu�[���<?php

/**
 * Tests that properties of XML_RPC_Client get properly set
 *
 * Any individual tests that fail will have their name, expected result
 * and actual result printed out.  So seeing no output when executing
 * this file is a good thing.
 *
 * Can be run via CLI or a web server.
 *
 * PHP versions 4 and 5
 *
 * @category   Web Services
 * @package    XML_RPC
 * @author     Daniel Convissor <danielc@php.net>
 * @copyright  2005-2010 The PHP Group
 * @license    http://www.php.net/license/3_01.txt  PHP License
 * @version    SVN: $Id: protoport.php 300957 2010-07-02 23:55:00Z danielc $
 * @link       http://pear.php.net/package/XML_RPC
 * @since      File available since Release 1.2
 */

/*
 * If the package version number is found in the left hand
 * portion of the if() expression below, that means this file has
 * come from the PEAR installer.  Therefore, let's test the
 * installed version of XML_RPC which should be in the include path.
 *
 * If the version has not been substituted in the if() expression,
 * this file has likely come from a SVN checkout or a .tar file.
 * Therefore, we'll assume the tests should use the version of
 * XML_RPC that has come from there as well.
 */
if ('1.5.5' == '@'.'package_version'.'@') {
    ini_set('include_path', '../'
            . PATH_SEPARATOR . '.' . PATH_SEPARATOR
            . ini_get('include_path')
    );
}
require_once 'XML/RPC.php';


/**
 * Compare the test result to the expected result
 *
 * If the test fails, echo out the results.
 *
 * @param array  $expect     the array of object properties you expect
 *                            from the test
 * @param object $actual     the object results from the test
 * @param string $test_name  the name of the test
 *
 * @return void
 */
function compare($expect, $actual, $test_name) {
    $actual = get_object_vars($actual);
    if (count(array_diff($actual, $expect))) {
        echo "$test_name failed.\nExpect: ";
        print_r($expect);
        echo "Actual: ";
        print_r($actual);
        echo "\n";
    }
}

if (php_sapi_name() != 'cli') {
    echo "<pre>\n";
}


$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'http://',
    'port' => 80,
    'proxy' => '',
    'proxy_protocol' => 'http://',
    'proxy_port' => 8080,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'theserver');
compare($x, $c, 'defaults');

$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'http://',
    'port' => 80,
    'proxy' => '',
    'proxy_protocol' => 'http://',
    'proxy_port' => 8080,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'http://theserver');
compare($x, $c, 'defaults with http');

$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'ssl://',
    'port' => 443,
    'proxy' => '',
    'proxy_protocol' => 'http://',
    'proxy_port' => 8080,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'https://theserver');
compare($x, $c, 'defaults with https');

$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'ssl://',
    'port' => 443,
    'proxy' => '',
    'proxy_protocol' => 'http://',
    'proxy_port' => 8080,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'ssl://theserver');
compare($x, $c, 'defaults with ssl');


$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'http://',
    'port' => 65,
    'proxy' => '',
    'proxy_protocol' => 'http://',
    'proxy_port' => 8080,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'theserver', 65);
compare($x, $c, 'port 65');

$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'http://',
    'port' => 65,
    'proxy' => '',
    'proxy_protocol' => 'http://',
    'proxy_port' => 8080,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'http://theserver', 65);
compare($x, $c, 'port 65 with http');

$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'ssl://',
    'port' => 65,
    'proxy' => '',
    'proxy_protocol' => 'http://',
    'proxy_port' => 8080,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'https://theserver', 65);
compare($x, $c, 'port 65 with https');

$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'ssl://',
    'port' => 65,
    'proxy' => '',
    'proxy_protocol' => 'http://',
    'proxy_port' => 8080,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'ssl://theserver', 65);
compare($x, $c, 'port 65 with ssl');


$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'http://',
    'port' => 80,
    'proxy' => 'theproxy',
    'proxy_protocol' => 'http://',
    'proxy_port' => 8080,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'theserver', 0,
                        'theproxy');
compare($x, $c, 'defaults proxy');

$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'http://',
    'port' => 80,
    'proxy' => 'theproxy',
    'proxy_protocol' => 'http://',
    'proxy_port' => 8080,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'http://theserver', 0,
                        'http://theproxy');
compare($x, $c, 'defaults with http proxy');

$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'ssl://',
    'port' => 443,
    'proxy' => 'theproxy',
    'proxy_protocol' => 'ssl://',
    'proxy_port' => 443,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'https://theserver', 0,
                        'https://theproxy');
compare($x, $c, 'defaults with https proxy');

$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'ssl://',
    'port' => 443,
    'proxy' => 'theproxy',
    'proxy_protocol' => 'ssl://',
    'proxy_port' => 443,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'ssl://theserver', 0,
                        'ssl://theproxy');
compare($x, $c, 'defaults with ssl proxy');


$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'http://',
    'port' => 65,
    'proxy' => 'theproxy',
    'proxy_protocol' => 'http://',
    'proxy_port' => 6565,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'theserver', 65,
                        'theproxy', 6565);
compare($x, $c, 'port 65 proxy 6565');

$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'http://',
    'port' => 65,
    'proxy' => 'theproxy',
    'proxy_protocol' => 'http://',
    'proxy_port' => 6565,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'http://theserver', 65,
                        'http://theproxy', 6565);
compare($x, $c, 'port 65 with http proxy 6565');

$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'ssl://',
    'port' => 65,
    'proxy' => 'theproxy',
    'proxy_protocol' => 'ssl://',
    'proxy_port' => 6565,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'https://theserver', 65,
                        'https://theproxy', 6565);
compare($x, $c, 'port 65 with https proxy 6565');

$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'ssl://',
    'port' => 65,
    'proxy' => 'theproxy',
    'proxy_protocol' => 'ssl://',
    'proxy_port' => 6565,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'ssl://theserver', 65,
                        'ssl://theproxy', 6565);
compare($x, $c, 'port 65 with ssl proxy 6565');


$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'ssl://',
    'port' => 443,
    'proxy' => 'theproxy',
    'proxy_protocol' => 'ssl://',
    'proxy_port' => 443,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'theserver', 443,
                        'theproxy', 443);
compare($x, $c, 'port 443 no protocol and proxy port 443 no protocol');

$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'http://',
    'port' => 80,
    'proxy' => 'theproxy',
    'proxy_protocol' => 'ssl://',
    'proxy_port' => 6565,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'theserver', 0,
                        'ssl://theproxy', 6565);
compare($x, $c, 'port 443 no protocol and proxy port 443 no protocol');

echo "\nIf no other output was produced, these tests passed.\n";
PK��Z�B�test/XML_RPC/tests/allgot.incnu�[���<?php

/**
 * Parses the "return" value from some of our test scripts.
 *
 * PHP versions 4 and 5
 *
 * @category   Web Services
 * @package    XML_RPC
 * @author     Daniel Convissor <danielc@php.net>
 * @copyright  2005-2010 The PHP Group
 * @license    http://www.php.net/license/3_01.txt  PHP License
 * @version    SVN: $Id: allgot.inc 293223 2010-01-07 15:32:19Z danielc $
 * @link       http://pear.php.net/package/XML_RPC
 * @since      File available since Release 1.4.4
 */

ob_start();

function returnAllGot($params) {
    $out = '';
    $count = count($params->params);
    for ($i = 0; $i < $count; $i++) {
        $param = $params->getParam($i);
        if (!XML_RPC_Value::isValue($param)) {
            $out .= "parameter $i was error: $param\n";
            continue;
        }
        $got = XML_RPC_Decode($param);
        $out .= "param $i: " . var_export($got, true) . "\n";
    }
    $val = new XML_RPC_Value($out, 'string');
    return new XML_RPC_Response($val);
}

$server = new XML_RPC_Server(
    array(
        'allgot' => array(
            'function' => 'returnAllGot',
        ),
    )
);

$got = ob_get_clean();

if ($got == $expect) {
    echo "passed\n";
} else {
    echo "FAILED\n";
    echo "Expected:\n$expect\n";
    echo "Got:\n$got\n";
}
PK��Z��̢�	�	test/XML_RPC/tests/types.phpnu�[���<?php

/**
 * Tests how the XML_RPC server handles a bunch of different parameter
 * data types.
 *
 * PHP versions 4 and 5
 *
 * @category   Web Services
 * @package    XML_RPC
 * @author     Daniel Convissor <danielc@php.net>
 * @copyright  2005-2010 The PHP Group
 * @license    http://www.php.net/license/3_01.txt  PHP License
 * @version    SVN: $Id: types.php 300957 2010-07-02 23:55:00Z danielc $
 * @link       http://pear.php.net/package/XML_RPC
 * @since      File available since Release 1.4.4
 */

/*
 * If the package version number is found in the left hand
 * portion of the if() expression below, that means this file has
 * come from the PEAR installer.  Therefore, let's test the
 * installed version of XML_RPC which should be in the include path.
 *
 * If the version has not been substituted in the if() expression,
 * this file has likely come from a SVN checkout or a .tar file.
 * Therefore, we'll assume the tests should use the version of
 * XML_RPC that has come from there as well.
 */
if ('1.5.5' == '@'.'package_version'.'@') {
    ini_set('include_path', '../'
            . PATH_SEPARATOR . '.' . PATH_SEPARATOR
            . ini_get('include_path')
    );
}
require_once 'XML/RPC/Server.php';


$GLOBALS['HTTP_RAW_POST_DATA'] = <<<EOPOST
<?xml version="1.0"?>
<methodCall>
 <methodName>allgot</methodName>
  <params>
   <param><value>default to string</value></param>
   <param><value><string>inside string</string></value></param>
   <param><value><int>8</int></value></param>
   <param><value><datetime.iso8601>20050809T01:33:44</datetime.iso8601></value></param>

   <param>
    <value>
     <array>
      <data>
       <value>
        <string>a</string>
       </value>
       <value>
        <string>b</string>
       </value>
      </data>
     </array>
    </value>
   </param>

   <param>
    <value>
     <struct>
      <member>
       <name>a</name>
       <value>
        <string>ay</string>
       </value>
      </member>
      <member>
       <name>b</name>
       <value>
        <string>be</string>
       </value>
      </member>
     </struct>
    </value>
   </param>

  </params>
 </methodCall>
EOPOST;

$expect = <<<EOEXP
<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
<params>
<param>
<value><string>param 0: 'default to string'
param 1: 'inside string'
param 2: '8'
param 3: '20050809T01:33:44'
param 4: array (
  0 =&gt; 'a',
  1 =&gt; 'b',
)
param 5: array (
  'a' =&gt; 'ay',
  'b' =&gt; 'be',
)
</string></value>
</param>
</params>
</methodResponse>
EOEXP;

include './allgot.inc';
PK��ZJ����test/XML_RPC/tests/encode.phpnu�[���<?php

/**
 * Tests encoding values.
 *
 * PHP versions 4 and 5
 *
 * @category   Web Services
 * @package    XML_RPC
 * @author     Daniel Convissor <danielc@php.net>
 * @copyright  2005-2010 The PHP Group
 * @license    http://www.php.net/license/3_01.txt  PHP License
 * @version    SVN: $Id: extra-lines.php 293218 2010-01-07 14:20:08Z danielc $
 * @link       http://pear.php.net/package/XML_RPC
 * @since      File available since Release 1.5.3
 */

/*
 * If the package version number is found in the left hand
 * portion of the if() expression below, that means this file has
 * come from the PEAR installer.  Therefore, let's test the
 * installed version of XML_RPC which should be in the include path.
 *
 * If the version has not been substituted in the if() expression,
 * this file has likely come from a SVN checkout or a .tar file.
 * Therefore, we'll assume the tests should use the version of
 * XML_RPC that has come from there as well.
 */
if ('1.5.5' == '@'.'package_version'.'@') {
    ini_set('include_path', '../'
            . PATH_SEPARATOR . '.' . PATH_SEPARATOR
            . ini_get('include_path')
    );
}
require_once 'XML/RPC.php';


$input = array(10, 11, 12);

$expect = <<<EOT
<?xml version="1.0" encoding="UTF-8"?>
<methodCall>
<methodName>nada</methodName>
<params>
<param>
<value><array>
<data>
<value><int>10</int></value>
<value><int>11</int></value>
<value><int>12</int></value>
</data>
</array></value>
</param>
</params>
</methodCall>
EOT;

$expect = trim(preg_replace("/\r\n/", "\n", $expect));

$msg = new XML_RPC_Message('nada', array(XML_RPC_encode($input)));
$msg->createPayload();
$actual = trim(preg_replace("/\r\n/", "\n", $msg->payload));
if ($actual == $expect) {
    echo "passed\n";
} else {
    echo "PROBLEM\n";
    echo $actual;
}

$msg = new XML_RPC_Message('nada',
    array(
        new XML_RPC_Value(
            array(
                new XML_RPC_Value(10, 'int'),
                new XML_RPC_Value(11, 'int'),
                new XML_RPC_Value(12, 'int'),
            ),
            'array'
        )
    )
);
$msg->createPayload();
$actual = trim(preg_replace("/\r\n/", "\n", $msg->payload));
if ($actual == $expect) {
    echo "passed\n";
} else {
    echo "PROBLEM\n";
    echo $actual;
}
PK��Z���XX test/XML_RPC/tests/test_Dump.phpnu�[���<?php

/**
 * Actually performs an XML_RPC request.
 *
 * PHP versions 4 and 5
 *
 * @category   Web Services
 * @package    XML_RPC
 * @author     Daniel Convissor <danielc@php.net>
 * @copyright  2005-2010 The PHP Group
 * @license    http://www.php.net/license/3_01.txt  PHP License
 * @version    SVN: $Id: test_Dump.php 300962 2010-07-03 02:24:24Z danielc $
 * @link       http://pear.php.net/package/XML_RPC
 */

/*
 * If the package version number is found in the left hand
 * portion of the if() expression below, that means this file has
 * come from the PEAR installer.  Therefore, let's test the
 * installed version of XML_RPC which should be in the include path.
 *
 * If the version has not been substituted in the if() expression,
 * this file has likely come from a SVN checkout or a .tar file.
 * Therefore, we'll assume the tests should use the version of
 * XML_RPC that has come from there as well.
 */
if ('1.5.5' == '@'.'package_version'.'@') {
    ini_set('include_path', '../'
            . PATH_SEPARATOR . '.' . PATH_SEPARATOR
            . ini_get('include_path')
    );
}
require_once 'XML/RPC/Dump.php';


$val = new XML_RPC_Value(array(
    'title'    =>new XML_RPC_Value('das ist der Titel', 'string'),
    'startDate'=>new XML_RPC_Value(mktime(0,0,0,13,11,2004), 'dateTime.iso8601'),
    'endDate'  =>new XML_RPC_Value(mktime(0,0,0,15,11,2004), 'dateTime.iso8601'),
    'arkey'    => new XML_RPC_Value( array(
        new XML_RPC_Value('simple string'),
        new XML_RPC_Value(12345, 'int')
        ), 'array')
    )
    ,'struct');

XML_RPC_Dump($val);

echo '==============' . "\r\n";
$val2 = new XML_RPC_Value(44353, 'int');
XML_RPC_Dump($val2);

echo '==============' . "\r\n";
$val3 = new XML_RPC_Value('this should be a string', 'string');
XML_RPC_Dump($val3);

echo '==============' . "\r\n";
$val4 = new XML_RPC_Value(true, 'boolean');
XML_RPC_Dump($val4);

echo '==============' . "\r\n";
echo 'Next we will test the error handling...' . "\r\n";
$val5 = new XML_RPC_Value(array(
    'foo' => 'bar'
    ), 'struct');
XML_RPC_Dump($val5);

echo '==============' . "\r\n";
echo 'DONE' . "\r\n";
PK��Z$]���"test/XML_RPC/tests/empty-value.phpnu�[���<?php

/**
 * Tests how the XML_RPC server handles parameters with empty values.
 *
 * PHP versions 4 and 5
 *
 * @category   Web Services
 * @package    XML_RPC
 * @author     Daniel Convissor <danielc@php.net>
 * @copyright  2005-2010 The PHP Group
 * @license    http://www.php.net/license/3_01.txt  PHP License
 * @version    SVN: $Id: empty-value.php 300957 2010-07-02 23:55:00Z danielc $
 * @link       http://pear.php.net/package/XML_RPC
 * @since      File available since Release 1.4.4
 */

/*
 * If the package version number is found in the left hand
 * portion of the if() expression below, that means this file has
 * come from the PEAR installer.  Therefore, let's test the
 * installed version of XML_RPC which should be in the include path.
 *
 * If the version has not been substituted in the if() expression,
 * this file has likely come from a SVN checkout or a .tar file.
 * Therefore, we'll assume the tests should use the version of
 * XML_RPC that has come from there as well.
 */
if ('1.5.5' == '@'.'package_version'.'@') {
    ini_set('include_path', '../'
            . PATH_SEPARATOR . '.' . PATH_SEPARATOR
            . ini_get('include_path')
    );
}
require_once 'XML/RPC/Server.php';


$GLOBALS['HTTP_RAW_POST_DATA'] = <<<EOPOST
<?xml version="1.0"?>
<methodCall>
 <methodName>allgot</methodName>
  <params>
   <param><value><string></string></value></param>
   <param><value>first</value></param>
   <param><value>  </value></param>
   <param><value></value></param>
  </params>
 </methodCall>
EOPOST;

$expect = <<<EOEXP
<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
<params>
<param>
<value><string>param 0: ''
param 1: 'first'
param 2: '  '
param 3: ''
</string></value>
</param>
</params>
</methodResponse>
EOEXP;

include './allgot.inc';
PK��Zb��)))%test/XML_RPC/tests/actual-request.phpnu�[���<?php

/**
 * Actually performs an XML_RPC request.
 *
 * PHP versions 4 and 5
 *
 * @category   Web Services
 * @package    XML_RPC
 * @author     Daniel Convissor <danielc@php.net>
 * @copyright  2005-2010 The PHP Group
 * @license    http://www.php.net/license/3_01.txt  PHP License
 * @version    SVN: $Id: actual-request.php 300957 2010-07-02 23:55:00Z danielc $
 * @link       http://pear.php.net/package/XML_RPC
 * @since      File available since Release 1.5.3
 */

/*
 * If the package version number is found in the left hand
 * portion of the if() expression below, that means this file has
 * come from the PEAR installer.  Therefore, let's test the
 * installed version of XML_RPC which should be in the include path.
 *
 * If the version has not been substituted in the if() expression,
 * this file has likely come from a SVN checkout or a .tar file.
 * Therefore, we'll assume the tests should use the version of
 * XML_RPC that has come from there as well.
 */
if ('1.5.5' == '@'.'package_version'.'@') {
    ini_set('include_path', '../'
            . PATH_SEPARATOR . '.' . PATH_SEPARATOR
            . ini_get('include_path')
    );
}
require_once 'XML/RPC/Dump.php';


$debug = 0;

$params = array(
    new XML_RPC_Value('php.net', 'string'),
);
$msg = new XML_RPC_Message('domquery', $params);
$client = new XML_RPC_Client('/api/xmlrpc', 'www.adamsnames.com');
$client->setDebug($debug);

$resp = $client->send($msg);
if (!$resp) {
    echo 'Communication error: ' . $client->errstr;
    exit(1);
}
if ($resp->faultCode()) {
    /*
     * Display problems that have been gracefully cought and
     * reported by the xmlrpc.php script
     */
    echo 'Fault Code: ' . $resp->faultCode() . "\n";
    echo 'Fault Reason: ' . $resp->faultString() . "\n";
    exit(1);
}

$val = $resp->value();
XML_RPC_Dump($val);
PK��Zw�۴��Mtest/DomCrawler/Symfony/Component/DomCrawler/Tests/Fixtures/windows-1250.htmlnu�[���<html>
    <head>
        <meta http-equiv="content-type" content="text/html;charset=windows-1250">
    </head>
    <body>
        <p>���</p>
    </body>
</html>
PK��Z�x�Htest/DomCrawler/Symfony/Component/DomCrawler/Tests/Fixtures/no-extensionnu�[���Test
PK��Zl�#8��Btest/DomCrawler/Symfony/Component/DomCrawler/Tests/CrawlerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DomCrawler\Tests;

use Symfony\Component\CssSelector\CssSelector;
use Symfony\Component\DomCrawler\Crawler;

class CrawlerTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $crawler = new Crawler();
        $this->assertCount(0, $crawler, '__construct() returns an empty crawler');

        $crawler = new Crawler(new \DOMNode());
        $this->assertCount(1, $crawler, '__construct() takes a node as a first argument');
    }

    /**
     * @covers Symfony\Component\DomCrawler\Crawler::add
     */
    public function testAdd()
    {
        $crawler = new Crawler();
        $crawler->add($this->createDomDocument());
        $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->add() adds nodes from a \DOMDocument');

        $crawler = new Crawler();
        $crawler->add($this->createNodeList());
        $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->add() adds nodes from a \DOMNodeList');

        foreach ($this->createNodeList() as $node) {
            $list[] = $node;
        }
        $crawler = new Crawler();
        $crawler->add($list);
        $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->add() adds nodes from an array of nodes');

        $crawler = new Crawler();
        $crawler->add($this->createNodeList()->item(0));
        $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->add() adds nodes from an \DOMNode');

        $crawler = new Crawler();
        $crawler->add('<html><body>Foo</body></html>');
        $this->assertEquals('Foo', $crawler->filterXPath('//body')->text(), '->add() adds nodes from a string');
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testAddInvalidNode()
    {
        $crawler = new Crawler();
        $crawler->add(1);
    }

    /**
     * @covers Symfony\Component\DomCrawler\Crawler::addHtmlContent
     */
    public function testAddHtmlContent()
    {
        $crawler = new Crawler();
        $crawler->addHtmlContent('<html><div class="foo"></html>', 'UTF-8');

        $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addHtmlContent() adds nodes from an HTML string');

        $crawler->addHtmlContent('<html><head><base href="http://symfony.com"></head><a href="/contact"></a></html>', 'UTF-8');

        $this->assertEquals('http://symfony.com', $crawler->filterXPath('//base')->attr('href'), '->addHtmlContent() adds nodes from an HTML string');
        $this->assertEquals('http://symfony.com/contact', $crawler->filterXPath('//a')->link()->getUri(), '->addHtmlContent() adds nodes from an HTML string');
    }

    /**
     * @covers Symfony\Component\DomCrawler\Crawler::addHtmlContent
     */
    public function testAddHtmlContentCharset()
    {
        $crawler = new Crawler();
        $crawler->addHtmlContent('<html><div class="foo">Tiếng Việt</html>', 'UTF-8');

        $this->assertEquals('Tiếng Việt', $crawler->filterXPath('//div')->text());
    }

    /**
     * @covers Symfony\Component\DomCrawler\Crawler::addHtmlContent
     */
    public function testAddHtmlContentInvalidBaseTag()
    {
        $crawler = new Crawler(null, 'http://symfony.com');

        $crawler->addHtmlContent('<html><head><base target="_top"></head><a href="/contact"></a></html>', 'UTF-8');

        $this->assertEquals('http://symfony.com/contact', current($crawler->filterXPath('//a')->links())->getUri(), '->addHtmlContent() correctly handles a non-existent base tag href attribute');
    }

    /**
     * @covers Symfony\Component\DomCrawler\Crawler::addHtmlContent
     */
    public function testAddHtmlContentUnsupportedCharset()
    {
        $crawler = new Crawler();
        $crawler->addHtmlContent(file_get_contents(__DIR__.'/Fixtures/windows-1250.html'), 'Windows-1250');

        $this->assertEquals('Žťčýů', $crawler->filterXPath('//p')->text());
    }

    /**
     * @covers Symfony\Component\DomCrawler\Crawler::addHtmlContent
     */
    public function testAddHtmlContentCharsetGbk()
    {
        $crawler = new Crawler();
        //gbk encode of <html><p>中文</p></html>
        $crawler->addHtmlContent(base64_decode('PGh0bWw+PHA+1tDOxDwvcD48L2h0bWw+'), 'gbk');

        $this->assertEquals('中文', $crawler->filterXPath('//p')->text());
    }

    /**
     * @covers Symfony\Component\DomCrawler\Crawler::addHtmlContent
     */
    public function testAddHtmlContentWithErrors()
    {
        $internalErrors = libxml_use_internal_errors(true);

        $crawler = new Crawler();
        $crawler->addHtmlContent(<<<EOF
<!DOCTYPE html>
<html>
    <head>
    </head>
    <body>
        <nav><a href="#"><a href="#"></nav>
    </body>
</html>
EOF
        , 'UTF-8');

        $errors = libxml_get_errors();
        $this->assertCount(1, $errors);
        $this->assertEquals("Tag nav invalid\n", $errors[0]->message);

        libxml_clear_errors();
        libxml_use_internal_errors($internalErrors);
    }

    /**
     * @covers Symfony\Component\DomCrawler\Crawler::addXmlContent
     */
    public function testAddXmlContent()
    {
        $crawler = new Crawler();
        $crawler->addXmlContent('<html><div class="foo"></div></html>', 'UTF-8');

        $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addXmlContent() adds nodes from an XML string');
    }

    /**
     * @covers Symfony\Component\DomCrawler\Crawler::addXmlContent
     */
    public function testAddXmlContentCharset()
    {
        $crawler = new Crawler();
        $crawler->addXmlContent('<html><div class="foo">Tiếng Việt</div></html>', 'UTF-8');

        $this->assertEquals('Tiếng Việt', $crawler->filterXPath('//div')->text());
    }

    /**
     * @covers Symfony\Component\DomCrawler\Crawler::addXmlContent
     */
    public function testAddXmlContentWithErrors()
    {
        $internalErrors = libxml_use_internal_errors(true);

        $crawler = new Crawler();
        $crawler->addXmlContent(<<<EOF
<!DOCTYPE html>
<html>
    <head>
    </head>
    <body>
        <nav><a href="#"><a href="#"></nav>
    </body>
</html>
EOF
        , 'UTF-8');

        $this->assertTrue(count(libxml_get_errors()) > 1);

        libxml_clear_errors();
        libxml_use_internal_errors($internalErrors);
    }

    /**
     * @covers Symfony\Component\DomCrawler\Crawler::addContent
     */
    public function testAddContent()
    {
        $crawler = new Crawler();
        $crawler->addContent('<html><div class="foo"></html>', 'text/html; charset=UTF-8');
        $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addContent() adds nodes from an HTML string');

        $crawler = new Crawler();
        $crawler->addContent('<html><div class="foo"></html>', 'text/html; charset=UTF-8; dir=RTL');
        $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addContent() adds nodes from an HTML string with extended content type');

        $crawler = new Crawler();
        $crawler->addContent('<html><div class="foo"></html>');
        $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addContent() uses text/html as the default type');

        $crawler = new Crawler();
        $crawler->addContent('<html><div class="foo"></div></html>', 'text/xml; charset=UTF-8');
        $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addContent() adds nodes from an XML string');

        $crawler = new Crawler();
        $crawler->addContent('<html><div class="foo"></div></html>', 'text/xml');
        $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addContent() adds nodes from an XML string');

        $crawler = new Crawler();
        $crawler->addContent('foo bar', 'text/plain');
        $this->assertCount(0, $crawler, '->addContent() does nothing if the type is not (x|ht)ml');

        $crawler = new Crawler();
        $crawler->addContent('<html><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><span>中文</span></html>');
        $this->assertEquals('中文', $crawler->filterXPath('//span')->text(), '->addContent() guess wrong charset');
    }

    /**
     * @covers Symfony\Component\DomCrawler\Crawler::addDocument
     */
    public function testAddDocument()
    {
        $crawler = new Crawler();
        $crawler->addDocument($this->createDomDocument());

        $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addDocument() adds nodes from a \DOMDocument');
    }

    /**
     * @covers Symfony\Component\DomCrawler\Crawler::addNodeList
     */
    public function testAddNodeList()
    {
        $crawler = new Crawler();
        $crawler->addNodeList($this->createNodeList());

        $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addNodeList() adds nodes from a \DOMNodeList');
    }

    /**
     * @covers Symfony\Component\DomCrawler\Crawler::addNodes
     */
    public function testAddNodes()
    {
        foreach ($this->createNodeList() as $node) {
            $list[] = $node;
        }

        $crawler = new Crawler();
        $crawler->addNodes($list);

        $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addNodes() adds nodes from an array of nodes');
    }

    /**
     * @covers Symfony\Component\DomCrawler\Crawler::addNode
     */
    public function testAddNode()
    {
        $crawler = new Crawler();
        $crawler->addNode($this->createNodeList()->item(0));

        $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addNode() adds nodes from an \DOMNode');
    }

    public function testClear()
    {
        $crawler = new Crawler(new \DOMNode());
        $crawler->clear();
        $this->assertCount(0, $crawler, '->clear() removes all the nodes from the crawler');
    }

    public function testEq()
    {
        $crawler = $this->createTestCrawler()->filterXPath('//li');
        $this->assertNotSame($crawler, $crawler->eq(0), '->eq() returns a new instance of a crawler');
        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->eq() returns a new instance of a crawler');

        $this->assertEquals('Two', $crawler->eq(1)->text(), '->eq() returns the nth node of the list');
        $this->assertCount(0, $crawler->eq(100), '->eq() returns an empty crawler if the nth node does not exist');
    }

    public function testEach()
    {
        $data = $this->createTestCrawler()->filterXPath('//ul[1]/li')->each(function ($node, $i) {
            return $i.'-'.$node->text();
        });

        $this->assertEquals(array('0-One', '1-Two', '2-Three'), $data, '->each() executes an anonymous function on each node of the list');
    }

    public function testReduce()
    {
        $crawler = $this->createTestCrawler()->filterXPath('//ul[1]/li');
        $nodes = $crawler->reduce(function ($node, $i) {
            return $i == 1 ? false : true;
        });
        $this->assertNotSame($nodes, $crawler, '->reduce() returns a new instance of a crawler');
        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $nodes, '->reduce() returns a new instance of a crawler');

        $this->assertCount(2, $nodes, '->reduce() filters the nodes in the list');
    }

    public function testAttr()
    {
        $this->assertEquals('first', $this->createTestCrawler()->filterXPath('//li')->attr('class'), '->attr() returns the attribute of the first element of the node list');

        try {
            $this->createTestCrawler()->filterXPath('//ol')->attr('class');
            $this->fail('->attr() throws an \InvalidArgumentException if the node list is empty');
        } catch (\InvalidArgumentException $e) {
            $this->assertTrue(true, '->attr() throws an \InvalidArgumentException if the node list is empty');
        }
    }

    public function testMissingAttrValueIsNull()
    {
        $crawler = new Crawler();
        $crawler->addContent('<html><div non-empty-attr="sample value" empty-attr=""></div></html>', 'text/html; charset=UTF-8');
        $div = $crawler->filterXPath('//div');

        $this->assertEquals('sample value', $div->attr('non-empty-attr'), '->attr() reads non-empty attributes correctly');
        $this->assertEquals('', $div->attr('empty-attr'), '->attr() reads empty attributes correctly');
        $this->assertNull($div->attr('missing-attr'), '->attr() reads missing attributes correctly');
    }

    public function testText()
    {
        $this->assertEquals('One', $this->createTestCrawler()->filterXPath('//li')->text(), '->text() returns the node value of the first element of the node list');

        try {
            $this->createTestCrawler()->filterXPath('//ol')->text();
            $this->fail('->text() throws an \InvalidArgumentException if the node list is empty');
        } catch (\InvalidArgumentException $e) {
            $this->assertTrue(true, '->text() throws an \InvalidArgumentException if the node list is empty');
        }
    }

    public function testHtml()
    {
        $this->assertEquals('<img alt="Bar">', $this->createTestCrawler()->filterXPath('//a[5]')->html());
        $this->assertEquals('<input type="text" value="TextValue" name="TextName"><input type="submit" value="FooValue" name="FooName" id="FooId"><input type="button" value="BarValue" name="BarName" id="BarId"><button value="ButtonValue" name="ButtonName" id="ButtonId"></button>'
            , trim($this->createTestCrawler()->filterXPath('//form[@id="FooFormId"]')->html()));

        try {
            $this->createTestCrawler()->filterXPath('//ol')->html();
            $this->fail('->html() throws an \InvalidArgumentException if the node list is empty');
        } catch (\InvalidArgumentException $e) {
            $this->assertTrue(true, '->html() throws an \InvalidArgumentException if the node list is empty');
        }
    }

    public function testExtract()
    {
        $crawler = $this->createTestCrawler()->filterXPath('//ul[1]/li');

        $this->assertEquals(array('One', 'Two', 'Three'), $crawler->extract('_text'), '->extract() returns an array of extracted data from the node list');
        $this->assertEquals(array(array('One', 'first'), array('Two', ''), array('Three', '')), $crawler->extract(array('_text', 'class')), '->extract() returns an array of extracted data from the node list');

        $this->assertEquals(array(), $this->createTestCrawler()->filterXPath('//ol')->extract('_text'), '->extract() returns an empty array if the node list is empty');
    }

    /**
     * @covers Symfony\Component\DomCrawler\Crawler::filterXPath
     */
    public function testFilterXPath()
    {
        $crawler = $this->createTestCrawler();
        $this->assertNotSame($crawler, $crawler->filterXPath('//li'), '->filterXPath() returns a new instance of a crawler');
        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->filterXPath() returns a new instance of a crawler');

        $crawler = $this->createTestCrawler()->filterXPath('//ul');

        $this->assertCount(6, $crawler->filterXPath('//li'), '->filterXPath() filters the node list with the XPath expression');
    }

    public function testFilterXPathWithDefaultNamespace()
    {
        $crawler = $this->createTestXmlCrawler()->filterXPath('//default:entry/default:id');
        $this->assertCount(1, $crawler, '->filterXPath() automatically registers a namespace');
        $this->assertSame('tag:youtube.com,2008:video:kgZRZmEc9j4', $crawler->text());
    }

    public function testFilterXPathWithCustomDefaultNamespace()
    {
        $crawler = $this->createTestXmlCrawler();
        $crawler->setDefaultNamespacePrefix('x');
        $crawler = $crawler->filterXPath('//x:entry/x:id');

        $this->assertCount(1, $crawler, '->filterXPath() lets to override the default namespace prefix');
        $this->assertSame('tag:youtube.com,2008:video:kgZRZmEc9j4', $crawler->text());
    }

    public function testFilterXPathWithNamespace()
    {
        $crawler = $this->createTestXmlCrawler()->filterXPath('//yt:accessControl');
        $this->assertCount(2, $crawler, '->filterXPath() automatically registers a namespace');
    }

    public function testFilterXPathWithMultipleNamespaces()
    {
        $crawler = $this->createTestXmlCrawler()->filterXPath('//media:group/yt:aspectRatio');
        $this->assertCount(1, $crawler, '->filterXPath() automatically registers multiple namespaces');
        $this->assertSame('widescreen', $crawler->text());
    }

    public function testFilterXPathWithManuallyRegisteredNamespace()
    {
        $crawler = $this->createTestXmlCrawler();
        $crawler->registerNamespace('m', 'http://search.yahoo.com/mrss/');

        $crawler = $crawler->filterXPath('//m:group/yt:aspectRatio');
        $this->assertCount(1, $crawler, '->filterXPath() uses manually registered namespace');
        $this->assertSame('widescreen', $crawler->text());
    }

    public function testFilterXPathWithAnUrl()
    {
        $crawler = $this->createTestXmlCrawler();

        $crawler = $crawler->filterXPath('//media:category[@scheme="http://gdata.youtube.com/schemas/2007/categories.cat"]');
        $this->assertCount(1, $crawler);
        $this->assertSame('Music', $crawler->text());
    }

    /**
     * @covers Symfony\Component\DomCrawler\Crawler::filter
     */
    public function testFilter()
    {
        $crawler = $this->createTestCrawler();
        $this->assertNotSame($crawler, $crawler->filter('li'), '->filter() returns a new instance of a crawler');
        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->filter() returns a new instance of a crawler');

        $crawler = $this->createTestCrawler()->filter('ul');

        $this->assertCount(6, $crawler->filter('li'), '->filter() filters the node list with the CSS selector');
    }

    public function testFilterWithDefaultNamespace()
    {
        $crawler = $this->createTestXmlCrawler()->filter('default|entry default|id');
        $this->assertCount(1, $crawler, '->filter() automatically registers namespaces');
        $this->assertSame('tag:youtube.com,2008:video:kgZRZmEc9j4', $crawler->text());
    }

    public function testFilterWithNamespace()
    {
        CssSelector::disableHtmlExtension();

        $crawler = $this->createTestXmlCrawler()->filter('yt|accessControl');
        $this->assertCount(2, $crawler, '->filter() automatically registers namespaces');
    }

    public function testFilterWithMultipleNamespaces()
    {
        CssSelector::disableHtmlExtension();

        $crawler = $this->createTestXmlCrawler()->filter('media|group yt|aspectRatio');
        $this->assertCount(1, $crawler, '->filter() automatically registers namespaces');
        $this->assertSame('widescreen', $crawler->text());
    }

    public function testFilterWithDefaultNamespaceOnly()
    {
        $crawler = new Crawler('<?xml version="1.0" encoding="UTF-8"?>
            <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
                <url>
                    <loc>http://localhost/foo</loc>
                    <changefreq>weekly</changefreq>
                    <priority>0.5</priority>
                    <lastmod>2012-11-16</lastmod>
               </url>
               <url>
                    <loc>http://localhost/bar</loc>
                    <changefreq>weekly</changefreq>
                    <priority>0.5</priority>
                    <lastmod>2012-11-16</lastmod>
                </url>
            </urlset>
        ');

        $this->assertEquals(2, $crawler->filter('url')->count());
    }

    public function testSelectLink()
    {
        $crawler = $this->createTestCrawler();
        $this->assertNotSame($crawler, $crawler->selectLink('Foo'), '->selectLink() returns a new instance of a crawler');
        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->selectLink() returns a new instance of a crawler');

        $this->assertCount(1, $crawler->selectLink('Fabien\'s Foo'), '->selectLink() selects links by the node values');
        $this->assertCount(1, $crawler->selectLink('Fabien\'s Bar'), '->selectLink() selects links by the alt attribute of a clickable image');

        $this->assertCount(2, $crawler->selectLink('Fabien"s Foo'), '->selectLink() selects links by the node values');
        $this->assertCount(2, $crawler->selectLink('Fabien"s Bar'), '->selectLink() selects links by the alt attribute of a clickable image');

        $this->assertCount(1, $crawler->selectLink('\' Fabien"s Foo'), '->selectLink() selects links by the node values');
        $this->assertCount(1, $crawler->selectLink('\' Fabien"s Bar'), '->selectLink() selects links by the alt attribute of a clickable image');

        $this->assertCount(4, $crawler->selectLink('Foo'), '->selectLink() selects links by the node values');
        $this->assertCount(4, $crawler->selectLink('Bar'), '->selectLink() selects links by the node values');
    }

    public function testSelectButton()
    {
        $crawler = $this->createTestCrawler();
        $this->assertNotSame($crawler, $crawler->selectButton('FooValue'), '->selectButton() returns a new instance of a crawler');
        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->selectButton() returns a new instance of a crawler');

        $this->assertEquals(1, $crawler->selectButton('FooValue')->count(), '->selectButton() selects buttons');
        $this->assertEquals(1, $crawler->selectButton('FooName')->count(), '->selectButton() selects buttons');
        $this->assertEquals(1, $crawler->selectButton('FooId')->count(), '->selectButton() selects buttons');

        $this->assertEquals(1, $crawler->selectButton('BarValue')->count(), '->selectButton() selects buttons');
        $this->assertEquals(1, $crawler->selectButton('BarName')->count(), '->selectButton() selects buttons');
        $this->assertEquals(1, $crawler->selectButton('BarId')->count(), '->selectButton() selects buttons');

        $this->assertEquals(1, $crawler->selectButton('FooBarValue')->count(), '->selectButton() selects buttons with form attribute too');
        $this->assertEquals(1, $crawler->selectButton('FooBarName')->count(), '->selectButton() selects buttons with form attribute too');
    }

    public function testLink()
    {
        $crawler = $this->createTestCrawler('http://example.com/bar/')->selectLink('Foo');
        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Link', $crawler->link(), '->link() returns a Link instance');

        $this->assertEquals('POST', $crawler->link('post')->getMethod(), '->link() takes a method as its argument');

        $crawler = $this->createTestCrawler('http://example.com/bar')->selectLink('GetLink');
        $this->assertEquals('http://example.com/bar?get=param', $crawler->link()->getUri(), '->link() returns a Link instance');

        try {
            $this->createTestCrawler()->filterXPath('//ol')->link();
            $this->fail('->link() throws an \InvalidArgumentException if the node list is empty');
        } catch (\InvalidArgumentException $e) {
            $this->assertTrue(true, '->link() throws an \InvalidArgumentException if the node list is empty');
        }
    }

    public function testLinks()
    {
        $crawler = $this->createTestCrawler('http://example.com/bar/')->selectLink('Foo');
        $this->assertInternalType('array', $crawler->links(), '->links() returns an array');

        $this->assertCount(4, $crawler->links(), '->links() returns an array');
        $links = $crawler->links();
        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Link', $links[0], '->links() returns an array of Link instances');

        $this->assertEquals(array(), $this->createTestCrawler()->filterXPath('//ol')->links(), '->links() returns an empty array if the node selection is empty');
    }

    public function testForm()
    {
        $testCrawler = $this->createTestCrawler('http://example.com/bar/');
        $crawler = $testCrawler->selectButton('FooValue');
        $crawler2 = $testCrawler->selectButton('FooBarValue');
        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Form', $crawler->form(), '->form() returns a Form instance');
        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Form', $crawler2->form(), '->form() returns a Form instance');

        $this->assertEquals($crawler->form()->getFormNode()->getAttribute('id'), $crawler2->form()->getFormNode()->getAttribute('id'), '->form() works on elements with form attribute');

        $this->assertEquals(array('FooName' => 'FooBar', 'TextName' => 'TextValue', 'FooTextName' => 'FooTextValue'), $crawler->form(array('FooName' => 'FooBar'))->getValues(), '->form() takes an array of values to submit as its first argument');
        $this->assertEquals(array('FooName' => 'FooValue', 'TextName' => 'TextValue', 'FooTextName' => 'FooTextValue'), $crawler->form()->getValues(), '->getValues() returns correct form values');
        $this->assertEquals(array('FooBarName' => 'FooBarValue', 'TextName' => 'TextValue', 'FooTextName' => 'FooTextValue'), $crawler2->form()->getValues(), '->getValues() returns correct form values');

        try {
            $this->createTestCrawler()->filterXPath('//ol')->form();
            $this->fail('->form() throws an \InvalidArgumentException if the node list is empty');
        } catch (\InvalidArgumentException $e) {
            $this->assertTrue(true, '->form() throws an \InvalidArgumentException if the node list is empty');
        }
    }

    public function testLast()
    {
        $crawler = $this->createTestCrawler()->filterXPath('//ul[1]/li');
        $this->assertNotSame($crawler, $crawler->last(), '->last() returns a new instance of a crawler');
        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->last() returns a new instance of a crawler');

        $this->assertEquals('Three', $crawler->last()->text());
    }

    public function testFirst()
    {
        $crawler = $this->createTestCrawler()->filterXPath('//li');
        $this->assertNotSame($crawler, $crawler->first(), '->first() returns a new instance of a crawler');
        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->first() returns a new instance of a crawler');

        $this->assertEquals('One', $crawler->first()->text());
    }

    public function testSiblings()
    {
        $crawler = $this->createTestCrawler()->filterXPath('//li')->eq(1);
        $this->assertNotSame($crawler, $crawler->siblings(), '->siblings() returns a new instance of a crawler');
        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->siblings() returns a new instance of a crawler');

        $nodes = $crawler->siblings();
        $this->assertEquals(2, $nodes->count());
        $this->assertEquals('One', $nodes->eq(0)->text());
        $this->assertEquals('Three', $nodes->eq(1)->text());

        $nodes = $this->createTestCrawler()->filterXPath('//li')->eq(0)->siblings();
        $this->assertEquals(2, $nodes->count());
        $this->assertEquals('Two', $nodes->eq(0)->text());
        $this->assertEquals('Three', $nodes->eq(1)->text());

        try {
            $this->createTestCrawler()->filterXPath('//ol')->siblings();
            $this->fail('->siblings() throws an \InvalidArgumentException if the node list is empty');
        } catch (\InvalidArgumentException $e) {
            $this->assertTrue(true, '->siblings() throws an \InvalidArgumentException if the node list is empty');
        }
    }

    public function testNextAll()
    {
        $crawler = $this->createTestCrawler()->filterXPath('//li')->eq(1);
        $this->assertNotSame($crawler, $crawler->nextAll(), '->nextAll() returns a new instance of a crawler');
        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->nextAll() returns a new instance of a crawler');

        $nodes = $crawler->nextAll();
        $this->assertEquals(1, $nodes->count());
        $this->assertEquals('Three', $nodes->eq(0)->text());

        try {
            $this->createTestCrawler()->filterXPath('//ol')->nextAll();
            $this->fail('->nextAll() throws an \InvalidArgumentException if the node list is empty');
        } catch (\InvalidArgumentException $e) {
            $this->assertTrue(true, '->nextAll() throws an \InvalidArgumentException if the node list is empty');
        }
    }

    public function testPreviousAll()
    {
        $crawler = $this->createTestCrawler()->filterXPath('//li')->eq(2);
        $this->assertNotSame($crawler, $crawler->previousAll(), '->previousAll() returns a new instance of a crawler');
        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->previousAll() returns a new instance of a crawler');

        $nodes = $crawler->previousAll();
        $this->assertEquals(2, $nodes->count());
        $this->assertEquals('Two', $nodes->eq(0)->text());

        try {
            $this->createTestCrawler()->filterXPath('//ol')->previousAll();
            $this->fail('->previousAll() throws an \InvalidArgumentException if the node list is empty');
        } catch (\InvalidArgumentException $e) {
            $this->assertTrue(true, '->previousAll() throws an \InvalidArgumentException if the node list is empty');
        }
    }

    public function testChildren()
    {
        $crawler = $this->createTestCrawler()->filterXPath('//ul');
        $this->assertNotSame($crawler, $crawler->children(), '->children() returns a new instance of a crawler');
        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->children() returns a new instance of a crawler');

        $nodes = $crawler->children();
        $this->assertEquals(3, $nodes->count());
        $this->assertEquals('One', $nodes->eq(0)->text());
        $this->assertEquals('Two', $nodes->eq(1)->text());
        $this->assertEquals('Three', $nodes->eq(2)->text());

        try {
            $this->createTestCrawler()->filterXPath('//ol')->children();
            $this->fail('->children() throws an \InvalidArgumentException if the node list is empty');
        } catch (\InvalidArgumentException $e) {
            $this->assertTrue(true, '->children() throws an \InvalidArgumentException if the node list is empty');
        }

        try {
            $crawler = new Crawler('<p></p>');
            $crawler->filter('p')->children();
            $this->assertTrue(true, '->children() does not trigger a notice if the node has no children');
        } catch (\PHPUnit_Framework_Error_Notice $e) {
            $this->fail('->children() does not trigger a notice if the node has no children');
        }
    }

    public function testParents()
    {
        $crawler = $this->createTestCrawler()->filterXPath('//li[1]');
        $this->assertNotSame($crawler, $crawler->parents(), '->parents() returns a new instance of a crawler');
        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->parents() returns a new instance of a crawler');

        $nodes = $crawler->parents();
        $this->assertEquals(3, $nodes->count());

        $nodes = $this->createTestCrawler()->filterXPath('//html')->parents();
        $this->assertEquals(0, $nodes->count());

        try {
            $this->createTestCrawler()->filterXPath('//ol')->parents();
            $this->fail('->parents() throws an \InvalidArgumentException if the node list is empty');
        } catch (\InvalidArgumentException $e) {
            $this->assertTrue(true, '->parents() throws an \InvalidArgumentException if the node list is empty');
        }
    }

    public function testBaseTag()
    {
        $crawler = new Crawler('<html><base href="http://base.com"><a href="link"></a></html>');
        $this->assertEquals('http://base.com/link', $crawler->filterXPath('//a')->link()->getUri());

        $crawler = new Crawler('<html><base href="//base.com"><a href="link"></a></html>', 'https://domain.com');
        $this->assertEquals('https://base.com/link', $crawler->filterXPath('//a')->link()->getUri(), '<base> tag can use a schema-less URL');

        $crawler = new Crawler('<html><base href="path/"><a href="link"></a></html>', 'https://domain.com');
        $this->assertEquals('https://domain.com/path/link', $crawler->filterXPath('//a')->link()->getUri(), '<base> tag can set a path');
    }

    public function createTestCrawler($uri = null)
    {
        $dom = new \DOMDocument();
        $dom->loadHTML('
            <html>
                <body>
                    <a href="foo">Foo</a>
                    <a href="/foo">   Fabien\'s Foo   </a>
                    <a href="/foo">Fabien"s Foo</a>
                    <a href="/foo">\' Fabien"s Foo</a>

                    <a href="/bar"><img alt="Bar"/></a>
                    <a href="/bar"><img alt="   Fabien\'s Bar   "/></a>
                    <a href="/bar"><img alt="Fabien&quot;s Bar"/></a>
                    <a href="/bar"><img alt="\' Fabien&quot;s Bar"/></a>

                    <a href="?get=param">GetLink</a>

                    <form action="foo" id="FooFormId">
                        <input type="text" value="TextValue" name="TextName" />
                        <input type="submit" value="FooValue" name="FooName" id="FooId" />
                        <input type="button" value="BarValue" name="BarName" id="BarId" />
                        <button value="ButtonValue" name="ButtonName" id="ButtonId" />
                    </form>

                    <input type="submit" value="FooBarValue" name="FooBarName" form="FooFormId" />
                    <input type="text" value="FooTextValue" name="FooTextName" form="FooFormId" />

                    <ul class="first">
                        <li class="first">One</li>
                        <li>Two</li>
                        <li>Three</li>
                    </ul>
                    <ul>
                        <li>One Bis</li>
                        <li>Two Bis</li>
                        <li>Three Bis</li>
                    </ul>
                </body>
            </html>
        ');

        return new Crawler($dom, $uri);
    }

    protected function createTestXmlCrawler($uri = null)
    {
        $xml = '<?xml version="1.0" encoding="UTF-8"?>
            <entry xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:yt="http://gdata.youtube.com/schemas/2007">
                <id>tag:youtube.com,2008:video:kgZRZmEc9j4</id>
                <yt:accessControl action="comment" permission="allowed"/>
                <yt:accessControl action="videoRespond" permission="moderated"/>
                <media:group>
                    <media:title type="plain">Chordates - CrashCourse Biology #24</media:title>
                    <yt:aspectRatio>widescreen</yt:aspectRatio>
                </media:group>
                <media:category label="Music" scheme="http://gdata.youtube.com/schemas/2007/categories.cat">Music</media:category>
            </entry>';

        return new Crawler($xml, $uri);
    }

    protected function createDomDocument()
    {
        $dom = new \DOMDocument();
        $dom->loadXML('<html><div class="foo"></div></html>');

        return $dom;
    }

    protected function createNodeList()
    {
        $dom = new \DOMDocument();
        $dom->loadXML('<html><div class="foo"></div></html>');
        $domxpath = new \DOMXPath($dom);

        return $domxpath->query('//div');
    }
}
PK��Z��Ջ==Ptest/DomCrawler/Symfony/Component/DomCrawler/Tests/Field/ChoiceFormFieldTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DomCrawler\Tests\Field;

use Symfony\Component\DomCrawler\Field\ChoiceFormField;

class ChoiceFormFieldTest extends FormFieldTestCase
{
    public function testInitialize()
    {
        $node = $this->createNode('textarea', '');
        try {
            $field = new ChoiceFormField($node);
            $this->fail('->initialize() throws a \LogicException if the node is not an input or a select');
        } catch (\LogicException $e) {
            $this->assertTrue(true, '->initialize() throws a \LogicException if the node is not an input or a select');
        }

        $node = $this->createNode('input', '', array('type' => 'text'));
        try {
            $field = new ChoiceFormField($node);
            $this->fail('->initialize() throws a \LogicException if the node is an input with a type different from checkbox or radio');
        } catch (\LogicException $e) {
            $this->assertTrue(true, '->initialize() throws a \LogicException if the node is an input with a type different from checkbox or radio');
        }
    }

    public function testGetType()
    {
        $node = $this->createNode('input', '', array('type' => 'radio', 'name' => 'name', 'value' => 'foo'));
        $field = new ChoiceFormField($node);

        $this->assertEquals('radio', $field->getType(), '->getType() returns radio for radio buttons');

        $node = $this->createNode('input', '', array('type' => 'checkbox', 'name' => 'name', 'value' => 'foo'));
        $field = new ChoiceFormField($node);

        $this->assertEquals('checkbox', $field->getType(), '->getType() returns radio for a checkbox');

        $node = $this->createNode('select', '');
        $field = new ChoiceFormField($node);

        $this->assertEquals('select', $field->getType(), '->getType() returns radio for a select');
    }

    public function testIsMultiple()
    {
        $node = $this->createNode('input', '', array('type' => 'radio', 'name' => 'name', 'value' => 'foo'));
        $field = new ChoiceFormField($node);

        $this->assertFalse($field->isMultiple(), '->isMultiple() returns false for radio buttons');

        $node = $this->createNode('input', '', array('type' => 'checkbox', 'name' => 'name', 'value' => 'foo'));
        $field = new ChoiceFormField($node);

        $this->assertFalse($field->isMultiple(), '->isMultiple() returns false for checkboxes');

        $node = $this->createNode('select', '');
        $field = new ChoiceFormField($node);

        $this->assertFalse($field->isMultiple(), '->isMultiple() returns false for selects without the multiple attribute');

        $node = $this->createNode('select', '', array('multiple' => 'multiple'));
        $field = new ChoiceFormField($node);

        $this->assertTrue($field->isMultiple(), '->isMultiple() returns true for selects with the multiple attribute');
    }

    public function testSelects()
    {
        $node = $this->createSelectNode(array('foo' => false, 'bar' => false));
        $field = new ChoiceFormField($node);

        $this->assertTrue($field->hasValue(), '->hasValue() returns true for selects');
        $this->assertEquals('foo', $field->getValue(), '->getValue() returns the first option if none are selected');
        $this->assertFalse($field->isMultiple(), '->isMultiple() returns false when no multiple attribute is defined');

        $node = $this->createSelectNode(array('foo' => false, 'bar' => true));
        $field = new ChoiceFormField($node);

        $this->assertEquals('bar', $field->getValue(), '->getValue() returns the selected option');

        $field->setValue('foo');
        $this->assertEquals('foo', $field->getValue(), '->setValue() changes the selected option');

        try {
            $field->setValue('foobar');
            $this->fail('->setValue() throws an \InvalidArgumentException if the value is not one of the selected options');
        } catch (\InvalidArgumentException $e) {
            $this->assertTrue(true, '->setValue() throws an \InvalidArgumentException if the value is not one of the selected options');
        }

        try {
            $field->setValue(array('foobar'));
            $this->fail('->setValue() throws an \InvalidArgumentException if the value is an array');
        } catch (\InvalidArgumentException $e) {
            $this->assertTrue(true, '->setValue() throws an \InvalidArgumentException if the value is an array');
        }
    }

    public function testMultipleSelects()
    {
        $node = $this->createSelectNode(array('foo' => false, 'bar' => false), array('multiple' => 'multiple'));
        $field = new ChoiceFormField($node);

        $this->assertEquals(array(), $field->getValue(), '->setValue() returns an empty array if multiple is true and no option is selected');

        $field->setValue('foo');
        $this->assertEquals(array('foo'), $field->getValue(), '->setValue() returns an array of options if multiple is true');

        $field->setValue('bar');
        $this->assertEquals(array('bar'), $field->getValue(), '->setValue() returns an array of options if multiple is true');

        $field->setValue(array('foo', 'bar'));
        $this->assertEquals(array('foo', 'bar'), $field->getValue(), '->setValue() returns an array of options if multiple is true');

        $node = $this->createSelectNode(array('foo' => true, 'bar' => true), array('multiple' => 'multiple'));
        $field = new ChoiceFormField($node);

        $this->assertEquals(array('foo', 'bar'), $field->getValue(), '->getValue() returns the selected options');

        try {
            $field->setValue(array('foobar'));
            $this->fail('->setValue() throws an \InvalidArgumentException if the value is not one of the options');
        } catch (\InvalidArgumentException $e) {
            $this->assertTrue(true, '->setValue() throws an \InvalidArgumentException if the value is not one of the options');
        }
    }

    public function testRadioButtons()
    {
        $node = $this->createNode('input', '', array('type' => 'radio', 'name' => 'name', 'value' => 'foo'));
        $field = new ChoiceFormField($node);
        $node = $this->createNode('input', '', array('type' => 'radio', 'name' => 'name', 'value' => 'bar'));
        $field->addChoice($node);

        $this->assertFalse($field->hasValue(), '->hasValue() returns false when no radio button is selected');
        $this->assertNull($field->getValue(), '->getValue() returns null if no radio button is selected');
        $this->assertFalse($field->isMultiple(), '->isMultiple() returns false for radio buttons');

        $node = $this->createNode('input', '', array('type' => 'radio', 'name' => 'name', 'value' => 'foo'));
        $field = new ChoiceFormField($node);
        $node = $this->createNode('input', '', array('type' => 'radio', 'name' => 'name', 'value' => 'bar', 'checked' => 'checked'));
        $field->addChoice($node);

        $this->assertTrue($field->hasValue(), '->hasValue() returns true when a radio button is selected');
        $this->assertEquals('bar', $field->getValue(), '->getValue() returns the value attribute of the selected radio button');

        $field->setValue('foo');
        $this->assertEquals('foo', $field->getValue(), '->setValue() changes the selected radio button');

        try {
            $field->setValue('foobar');
            $this->fail('->setValue() throws an \InvalidArgumentException if the value is not one of the radio button values');
        } catch (\InvalidArgumentException $e) {
            $this->assertTrue(true, '->setValue() throws an \InvalidArgumentException if the value is not one of the radio button values');
        }
    }

    public function testRadioButtonIsDisabled()
    {
        $node = $this->createNode('input', '', array('type' => 'radio', 'name' => 'name', 'value' => 'foo', 'disabled' => 'disabled'));
        $field = new ChoiceFormField($node);
        $node = $this->createNode('input', '', array('type' => 'radio', 'name' => 'name', 'value' => 'bar'));
        $field->addChoice($node);

        $field->select('foo');
        $this->assertEquals('foo', $field->getValue(), '->getValue() returns the value attribute of the selected radio button');
        $this->assertTrue($field->isDisabled());

        $field->select('bar');
        $this->assertEquals('bar', $field->getValue(), '->getValue() returns the value attribute of the selected radio button');
        $this->assertFalse($field->isDisabled());
    }

    public function testCheckboxes()
    {
        $node = $this->createNode('input', '', array('type' => 'checkbox', 'name' => 'name'));
        $field = new ChoiceFormField($node);

        $this->assertFalse($field->hasValue(), '->hasValue() returns false when the checkbox is not checked');
        $this->assertNull($field->getValue(), '->getValue() returns null if the checkbox is not checked');
        $this->assertFalse($field->isMultiple(), '->hasValue() returns false for checkboxes');
        try {
            $field->addChoice(new \DOMNode());
            $this->fail('->addChoice() throws a \LogicException for checkboxes');
        } catch (\LogicException $e) {
            $this->assertTrue(true, '->initialize() throws a \LogicException for checkboxes');
        }

        $node = $this->createNode('input', '', array('type' => 'checkbox', 'name' => 'name', 'checked' => 'checked'));
        $field = new ChoiceFormField($node);

        $this->assertTrue($field->hasValue(), '->hasValue() returns true when the checkbox is checked');
        $this->assertEquals('1', $field->getValue(), '->getValue() returns 1 if the checkbox is checked and has no value attribute');

        $node = $this->createNode('input', '', array('type' => 'checkbox', 'name' => 'name', 'checked' => 'checked', 'value' => 'foo'));
        $field = new ChoiceFormField($node);

        $this->assertEquals('foo', $field->getValue(), '->getValue() returns the value attribute if the checkbox is checked');

        $node = $this->createNode('input', '', array('type' => 'checkbox', 'name' => 'name', 'checked' => 'checked', 'value' => 'foo'));
        $field = new ChoiceFormField($node);

        $field->setValue(false);
        $this->assertNull($field->getValue(), '->setValue() unchecks the checkbox is value is false');

        $field->setValue(true);
        $this->assertEquals('foo', $field->getValue(), '->setValue() checks the checkbox is value is true');

        try {
            $field->setValue('bar');
            $this->fail('->setValue() throws an \InvalidArgumentException if the value is not one from the value attribute');
        } catch (\InvalidArgumentException $e) {
            $this->assertTrue(true, '->setValue() throws an \InvalidArgumentException if the value is not one from the value attribute');
        }
    }

    public function testTick()
    {
        $node = $this->createSelectNode(array('foo' => false, 'bar' => false));
        $field = new ChoiceFormField($node);

        try {
            $field->tick();
            $this->fail('->tick() throws a \LogicException for select boxes');
        } catch (\LogicException $e) {
            $this->assertTrue(true, '->tick() throws a \LogicException for select boxes');
        }

        $node = $this->createNode('input', '', array('type' => 'checkbox', 'name' => 'name'));
        $field = new ChoiceFormField($node);
        $field->tick();
        $this->assertEquals(1, $field->getValue(), '->tick() ticks checkboxes');
    }

    public function testUntick()
    {
        $node = $this->createSelectNode(array('foo' => false, 'bar' => false));
        $field = new ChoiceFormField($node);

        try {
            $field->untick();
            $this->fail('->untick() throws a \LogicException for select boxes');
        } catch (\LogicException $e) {
            $this->assertTrue(true, '->untick() throws a \LogicException for select boxes');
        }

        $node = $this->createNode('input', '', array('type' => 'checkbox', 'name' => 'name', 'checked' => 'checked'));
        $field = new ChoiceFormField($node);
        $field->untick();
        $this->assertNull($field->getValue(), '->untick() unticks checkboxes');
    }

    public function testSelect()
    {
        $node = $this->createNode('input', '', array('type' => 'checkbox', 'name' => 'name', 'checked' => 'checked'));
        $field = new ChoiceFormField($node);
        $field->select(true);
        $this->assertEquals(1, $field->getValue(), '->select() changes the value of the field');
        $field->select(false);
        $this->assertNull($field->getValue(), '->select() changes the value of the field');

        $node = $this->createSelectNode(array('foo' => false, 'bar' => false));
        $field = new ChoiceFormField($node);
        $field->select('foo');
        $this->assertEquals('foo', $field->getValue(), '->select() changes the selected option');
    }

    public function testOptionWithNoValue()
    {
        $node = $this->createSelectNodeWithEmptyOption(array('foo' => false, 'bar' => false));
        $field = new ChoiceFormField($node);
        $field->select('foo');
        $this->assertEquals('foo', $field->getValue(), '->select() changes the selected option');
    }

    public function testDisableValidation()
    {
        $node = $this->createSelectNode(array('foo' => false, 'bar' => false));
        $field = new ChoiceFormField($node);
        $field->disableValidation();
        $field->setValue('foobar');
        $this->assertEquals('foobar', $field->getValue(), '->disableValidation() allows to set a value which is not in the selected options.');

        $node = $this->createSelectNode(array('foo' => false, 'bar' => false), array('multiple' => 'multiple'));
        $field = new ChoiceFormField($node);
        $field->disableValidation();
        $field->setValue(array('foobar'));
        $this->assertEquals(array('foobar'), $field->getValue(), '->disableValidation() allows to set a value which is not in the selected options.');
    }

    protected function createSelectNode($options, $attributes = array())
    {
        $document = new \DOMDocument();
        $node = $document->createElement('select');

        foreach ($attributes as $name => $value) {
            $node->setAttribute($name, $value);
        }
        $node->setAttribute('name', 'name');

        foreach ($options as $value => $selected) {
            $option = $document->createElement('option', $value);
            $option->setAttribute('value', $value);
            if ($selected) {
                $option->setAttribute('selected', 'selected');
            }
            $node->appendChild($option);
        }

        return $node;
    }

    protected function createSelectNodeWithEmptyOption($options, $attributes = array())
    {
        $document = new \DOMDocument();
        $node = $document->createElement('select');

        foreach ($attributes as $name => $value) {
            $node->setAttribute($name, $value);
        }
        $node->setAttribute('name', 'name');

        foreach ($options as $value => $selected) {
            $option = $document->createElement('option', $value);
            if ($selected) {
                $option->setAttribute('selected', 'selected');
            }
            $node->appendChild($option);
        }

        return $node;
    }
}
PK��Z�n���Rtest/DomCrawler/Symfony/Component/DomCrawler/Tests/Field/TextareaFormFieldTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DomCrawler\Tests\Field;

use Symfony\Component\DomCrawler\Field\TextareaFormField;

class TextareaFormFieldTest extends FormFieldTestCase
{
    public function testInitialize()
    {
        $node = $this->createNode('textarea', 'foo bar');
        $field = new TextareaFormField($node);

        $this->assertEquals('foo bar', $field->getValue(), '->initialize() sets the value of the field to the textarea node value');

        $node = $this->createNode('input', '');
        try {
            $field = new TextareaFormField($node);
            $this->fail('->initialize() throws a \LogicException if the node is not a textarea');
        } catch (\LogicException $e) {
            $this->assertTrue(true, '->initialize() throws a \LogicException if the node is not a textarea');
        }

        // Ensure that valid HTML can be used on a textarea.
        $node = $this->createNode('textarea', 'foo bar <h1>Baz</h1>');
        $field = new TextareaFormField($node);

        $this->assertEquals('foo bar <h1>Baz</h1>', $field->getValue(), '->initialize() sets the value of the field to the textarea node value');

        // Ensure that we don't do any DOM manipulation/validation by passing in
        // "invalid" HTML.
        $node = $this->createNode('textarea', 'foo bar <h1>Baz</h2>');
        $field = new TextareaFormField($node);

        $this->assertEquals('foo bar <h1>Baz</h2>', $field->getValue(), '->initialize() sets the value of the field to the textarea node value');
    }
}
PK��Z�!
D��Jtest/DomCrawler/Symfony/Component/DomCrawler/Tests/Field/FormFieldTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DomCrawler\Tests\Field;

use Symfony\Component\DomCrawler\Field\InputFormField;

class FormFieldTest extends FormFieldTestCase
{
    public function testGetName()
    {
        $node = $this->createNode('input', '', array('type' => 'text', 'name' => 'name', 'value' => 'value'));
        $field = new InputFormField($node);

        $this->assertEquals('name', $field->getName(), '->getName() returns the name of the field');
    }

    public function testGetSetHasValue()
    {
        $node = $this->createNode('input', '', array('type' => 'text', 'name' => 'name', 'value' => 'value'));
        $field = new InputFormField($node);

        $this->assertEquals('value', $field->getValue(), '->getValue() returns the value of the field');

        $field->setValue('foo');
        $this->assertEquals('foo', $field->getValue(), '->setValue() sets the value of the field');

        $this->assertTrue($field->hasValue(), '->hasValue() always returns true');
    }
}
PK��Z2$�G��Ntest/DomCrawler/Symfony/Component/DomCrawler/Tests/Field/FormFieldTestCase.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DomCrawler\Tests\Field;

class FormFieldTestCase extends \PHPUnit_Framework_TestCase
{
    protected function createNode($tag, $value, $attributes = array())
    {
        $document = new \DOMDocument();
        $node = $document->createElement($tag, $value);

        foreach ($attributes as $name => $value) {
            $node->setAttribute($name, $value);
        }

        return $node;
    }
}
PK��Z���QQOtest/DomCrawler/Symfony/Component/DomCrawler/Tests/Field/InputFormFieldTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DomCrawler\Tests\Field;

use Symfony\Component\DomCrawler\Field\InputFormField;

class InputFormFieldTest extends FormFieldTestCase
{
    public function testInitialize()
    {
        $node = $this->createNode('input', '', array('type' => 'text', 'name' => 'name', 'value' => 'value'));
        $field = new InputFormField($node);

        $this->assertEquals('value', $field->getValue(), '->initialize() sets the value of the field to the value attribute value');

        $node = $this->createNode('textarea', '');
        try {
            $field = new InputFormField($node);
            $this->fail('->initialize() throws a \LogicException if the node is not an input');
        } catch (\LogicException $e) {
            $this->assertTrue(true, '->initialize() throws a \LogicException if the node is not an input');
        }

        $node = $this->createNode('input', '', array('type' => 'checkbox'));
        try {
            $field = new InputFormField($node);
            $this->fail('->initialize() throws a \LogicException if the node is a checkbox');
        } catch (\LogicException $e) {
            $this->assertTrue(true, '->initialize() throws a \LogicException if the node is a checkbox');
        }

        $node = $this->createNode('input', '', array('type' => 'file'));
        try {
            $field = new InputFormField($node);
            $this->fail('->initialize() throws a \LogicException if the node is a file');
        } catch (\LogicException $e) {
            $this->assertTrue(true, '->initialize() throws a \LogicException if the node is a file');
        }
    }
}
PK��Z�5�||Ntest/DomCrawler/Symfony/Component/DomCrawler/Tests/Field/FileFormFieldTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DomCrawler\Tests\Field;

use Symfony\Component\DomCrawler\Field\FileFormField;

class FileFormFieldTest extends FormFieldTestCase
{
    public function testInitialize()
    {
        $node = $this->createNode('input', '', array('type' => 'file'));
        $field = new FileFormField($node);

        $this->assertEquals(array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => UPLOAD_ERR_NO_FILE, 'size' => 0), $field->getValue(), '->initialize() sets the value of the field to no file uploaded');

        $node = $this->createNode('textarea', '');
        try {
            $field = new FileFormField($node);
            $this->fail('->initialize() throws a \LogicException if the node is not an input field');
        } catch (\LogicException $e) {
            $this->assertTrue(true, '->initialize() throws a \LogicException if the node is not an input field');
        }

        $node = $this->createNode('input', '', array('type' => 'text'));
        try {
            $field = new FileFormField($node);
            $this->fail('->initialize() throws a \LogicException if the node is not a file input field');
        } catch (\LogicException $e) {
            $this->assertTrue(true, '->initialize() throws a \LogicException if the node is not a file input field');
        }
    }

    /**
     * @dataProvider getSetValueMethods
     */
    public function testSetValue($method)
    {
        $node = $this->createNode('input', '', array('type' => 'file'));
        $field = new FileFormField($node);

        $field->$method(null);
        $this->assertEquals(array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => UPLOAD_ERR_NO_FILE, 'size' => 0), $field->getValue(), "->$method() clears the uploaded file if the value is null");

        $field->$method(__FILE__);
        $value = $field->getValue();

        $this->assertEquals(basename(__FILE__), $value['name'], "->$method() sets the name of the file field");
        $this->assertEquals('', $value['type'], "->$method() sets the type of the file field");
        $this->assertInternalType('string', $value['tmp_name'], "->$method() sets the tmp_name of the file field");
        $this->assertFileExists($value['tmp_name'], "->$method() creates a copy of the file at the tmp_name path");
        $this->assertEquals(0, $value['error'], "->$method() sets the error of the file field");
        $this->assertEquals(filesize(__FILE__), $value['size'], "->$method() sets the size of the file field");

        $origInfo = pathinfo(__FILE__);
        $tmpInfo = pathinfo($value['tmp_name']);
        $this->assertEquals(
            $origInfo['extension'],
            $tmpInfo['extension'],
            "->$method() keeps the same file extension in the tmp_name copy"
        );

        $field->$method(__DIR__.'/../Fixtures/no-extension');
        $value = $field->getValue();

        $this->assertArrayNotHasKey(
            'extension',
            pathinfo($value['tmp_name']),
            "->$method() does not add a file extension in the tmp_name copy"
        );
    }

    public function getSetValueMethods()
    {
        return array(
            array('setValue'),
            array('upload'),
        );
    }

    public function testSetErrorCode()
    {
        $node = $this->createNode('input', '', array('type' => 'file'));
        $field = new FileFormField($node);

        $field->setErrorCode(UPLOAD_ERR_FORM_SIZE);
        $value = $field->getValue();
        $this->assertEquals(UPLOAD_ERR_FORM_SIZE, $value['error'], '->setErrorCode() sets the file input field error code');

        try {
            $field->setErrorCode('foobar');
            $this->fail('->setErrorCode() throws a \InvalidArgumentException if the error code is not valid');
        } catch (\InvalidArgumentException $e) {
            $this->assertTrue(true, '->setErrorCode() throws a \InvalidArgumentException if the error code is not valid');
        }
    }

    public function testSetRawFilePath()
    {
        $node = $this->createNode('input', '', array('type' => 'file'));
        $field = new FileFormField($node);
        $field->setFilePath(__FILE__);

        $this->assertEquals(__FILE__, $field->getValue());
    }

}
PK��Z�3��ʖʖ?test/DomCrawler/Symfony/Component/DomCrawler/Tests/FormTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DomCrawler\Tests;

use Symfony\Component\DomCrawler\Form;
use Symfony\Component\DomCrawler\FormFieldRegistry;
use Symfony\Component\DomCrawler\Field;

class FormTest extends \PHPUnit_Framework_TestCase
{
    public static function setUpBeforeClass()
    {
        // Ensure that the private helper class FormFieldRegistry is loaded
        class_exists('Symfony\\Component\\DomCrawler\\Form');
    }

    public function testConstructorThrowsExceptionIfTheNodeHasNoFormAncestor()
    {
        $dom = new \DOMDocument();
        $dom->loadHTML('
            <html>
                <input type="submit" />
                <form>
                    <input type="foo" />
                </form>
                <button />
            </html>
        ');

        $nodes = $dom->getElementsByTagName('input');

        try {
            $form = new Form($nodes->item(0), 'http://example.com');
            $this->fail('__construct() throws a \\LogicException if the node has no form ancestor');
        } catch (\LogicException $e) {
            $this->assertTrue(true, '__construct() throws a \\LogicException if the node has no form ancestor');
        }

        try {
            $form = new Form($nodes->item(1), 'http://example.com');
            $this->fail('__construct() throws a \\LogicException if the input type is not submit, button, or image');
        } catch (\LogicException $e) {
            $this->assertTrue(true, '__construct() throws a \\LogicException if the input type is not submit, button, or image');
        }

        $nodes = $dom->getElementsByTagName('button');

        try {
            $form = new Form($nodes->item(0), 'http://example.com');
            $this->fail('__construct() throws a \\LogicException if the node has no form ancestor');
        } catch (\LogicException $e) {
            $this->assertTrue(true, '__construct() throws a \\LogicException if the node has no form ancestor');
        }
    }

    /**
     * __construct() should throw \\LogicException if the form attribute is invalid
     * @expectedException \LogicException
     */
    public function testConstructorThrowsExceptionIfNoRelatedForm()
    {
        $dom = new \DOMDocument();
        $dom->loadHTML('
            <html>
                <form id="bar">
                    <input type="submit" form="nonexistent" />
                </form>
                <input type="text" form="nonexistent" />
                <button />
            </html>
        ');

        $nodes = $dom->getElementsByTagName('input');

        $form = new Form($nodes->item(0), 'http://example.com');
        $form = new Form($nodes->item(1), 'http://example.com');
    }

    public function testConstructorHandlesFormAttribute()
    {
        $dom = $this->createTestHtml5Form();

        $inputElements = $dom->getElementsByTagName('input');
        $buttonElements = $dom->getElementsByTagName('button');

        // Tests if submit buttons are correctly assigned to forms
        $form1 = new Form($buttonElements->item(1), 'http://example.com');
        $this->assertSame($dom->getElementsByTagName('form')->item(0), $form1->getFormNode(), 'HTML5-compliant form attribute handled incorrectly');

        $form1 = new Form($inputElements->item(3), 'http://example.com');
        $this->assertSame($dom->getElementsByTagName('form')->item(0), $form1->getFormNode(), 'HTML5-compliant form attribute handled incorrectly');

        $form2 = new Form($buttonElements->item(0), 'http://example.com');
        $this->assertSame($dom->getElementsByTagName('form')->item(1), $form2->getFormNode(), 'HTML5-compliant form attribute handled incorrectly');
    }

    public function testConstructorHandlesFormValues()
    {
        $dom = $this->createTestHtml5Form();

        $inputElements = $dom->getElementsByTagName('input');
        $buttonElements = $dom->getElementsByTagName('button');

        $form1 = new Form($inputElements->item(3), 'http://example.com');
        $form2 = new Form($buttonElements->item(0), 'http://example.com');

        // Tests if form values are correctly assigned to forms
        $values1 = array(
            'apples' => array('1', '2'),
            'form_name' => 'form-1',
            'button_1' => 'Capture fields',
            'outer_field' => 'success'
        );
        $values2 = array(
            'oranges' => array('1', '2', '3'),
            'form_name' => 'form_2',
            'button_2' => '',
            'app_frontend_form_type_contact_form_type' => array('contactType' => '', 'firstName' => 'John')
        );

        $this->assertEquals($values1, $form1->getPhpValues(), 'HTML5-compliant form attribute handled incorrectly');
        $this->assertEquals($values2, $form2->getPhpValues(), 'HTML5-compliant form attribute handled incorrectly');
    }

    public function testMultiValuedFields()
    {
        $form = $this->createForm('<form>
            <input type="text" name="foo[4]" value="foo" disabled="disabled" />
            <input type="text" name="foo" value="foo" disabled="disabled" />
            <input type="text" name="foo[2]" value="foo" disabled="disabled" />
            <input type="text" name="foo[]" value="foo" disabled="disabled" />
            <input type="text" name="bar[foo][]" value="foo" disabled="disabled" />
            <input type="text" name="bar[foo][foobar]" value="foo" disabled="disabled" />
            <input type="submit" />
        </form>
        ');

        $this->assertEquals(
            array_keys($form->all()),
            array('foo[2]', 'foo[3]', 'bar[foo][0]', 'bar[foo][foobar]')
        );

        $this->assertEquals($form->get('foo[2]')->getValue(), 'foo');
        $this->assertEquals($form->get('foo[3]')->getValue(), 'foo');
        $this->assertEquals($form->get('bar[foo][0]')->getValue(), 'foo');
        $this->assertEquals($form->get('bar[foo][foobar]')->getValue(), 'foo');

        $form['foo[2]'] = 'bar';
        $form['foo[3]'] = 'bar';

        $this->assertEquals($form->get('foo[2]')->getValue(), 'bar');
        $this->assertEquals($form->get('foo[3]')->getValue(), 'bar');

        $form['bar'] = array('foo' => array('0' => 'bar', 'foobar' => 'foobar'));

        $this->assertEquals($form->get('bar[foo][0]')->getValue(), 'bar');
        $this->assertEquals($form->get('bar[foo][foobar]')->getValue(), 'foobar');

    }

    /**
     * @dataProvider provideInitializeValues
     */
    public function testConstructor($message, $form, $values)
    {
        $form = $this->createForm('<form>'.$form.'</form>');
        $this->assertEquals(
            $values,
            array_map(function ($field) {
                    $class = get_class($field);

                    return array(substr($class, strrpos($class, '\\') + 1), $field->getValue());
                },
                $form->all()
            ),
            '->getDefaultValues() '.$message
        );
    }

    public function provideInitializeValues()
    {
        return array(
            array(
                'does not take into account input fields without a name attribute',
                '<input type="text" value="foo" />
                 <input type="submit" />',
                array(),
            ),
            array(
                'does not take into account input fields with an empty name attribute value',
                '<input type="text" name="" value="foo" />
                 <input type="submit" />',
                array(),
            ),
            array(
                'takes into account disabled input fields',
                '<input type="text" name="foo" value="foo" disabled="disabled" />
                 <input type="submit" />',
                array('foo' => array('InputFormField', 'foo')),
            ),
            array(
                'appends the submitted button value',
                '<input type="submit" name="bar" value="bar" />',
                array('bar' => array('InputFormField', 'bar')),
            ),
            array(
                'appends the submitted button value for Button element',
                '<button type="submit" name="bar" value="bar">Bar</button>',
                array('bar' => array('InputFormField', 'bar')),
            ),
            array(
                'appends the submitted button value but not other submit buttons',
                '<input type="submit" name="bar" value="bar" />
                 <input type="submit" name="foobar" value="foobar" />',
                 array('foobar' => array('InputFormField', 'foobar')),
            ),
            array(
                'turns an image input into x and y fields',
                '<input type="image" name="bar" />',
                array('bar.x' => array('InputFormField', '0'), 'bar.y' => array('InputFormField', '0')),
            ),
            array(
                'returns textareas',
                '<textarea name="foo">foo</textarea>
                 <input type="submit" />',
                 array('foo' => array('TextareaFormField', 'foo')),
            ),
            array(
                'returns inputs',
                '<input type="text" name="foo" value="foo" />
                 <input type="submit" />',
                 array('foo' => array('InputFormField', 'foo')),
            ),
            array(
                'returns checkboxes',
                '<input type="checkbox" name="foo" value="foo" checked="checked" />
                 <input type="submit" />',
                 array('foo' => array('ChoiceFormField', 'foo')),
            ),
            array(
                'returns not-checked checkboxes',
                '<input type="checkbox" name="foo" value="foo" />
                 <input type="submit" />',
                 array('foo' => array('ChoiceFormField', false)),
            ),
            array(
                'returns radio buttons',
                '<input type="radio" name="foo" value="foo" />
                 <input type="radio" name="foo" value="bar" checked="bar" />
                 <input type="submit" />',
                 array('foo' => array('ChoiceFormField', 'bar')),
            ),
            array(
                'returns file inputs',
                '<input type="file" name="foo" />
                 <input type="submit" />',
                 array('foo' => array('FileFormField', array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0))),
            ),
        );
    }

    public function testGetFormNode()
    {
        $dom = new \DOMDocument();
        $dom->loadHTML('<html><form><input type="submit" /></form></html>');

        $form = new Form($dom->getElementsByTagName('input')->item(0), 'http://example.com');

        $this->assertSame($dom->getElementsByTagName('form')->item(0), $form->getFormNode(), '->getFormNode() returns the form node associated with this form');
    }

    public function testGetFormNodeFromNamedForm()
    {
        $dom = new \DOMDocument();
        $dom->loadHTML('<html><form name="my_form"><input type="submit" /></form></html>');

        $form = new Form($dom->getElementsByTagName('form')->item(0), 'http://example.com');

        $this->assertSame($dom->getElementsByTagName('form')->item(0), $form->getFormNode(), '->getFormNode() returns the form node associated with this form');
    }

    public function testGetMethod()
    {
        $form = $this->createForm('<form><input type="submit" /></form>');
        $this->assertEquals('GET', $form->getMethod(), '->getMethod() returns get if no method is defined');

        $form = $this->createForm('<form method="post"><input type="submit" /></form>');
        $this->assertEquals('POST', $form->getMethod(), '->getMethod() returns the method attribute value of the form');

        $form = $this->createForm('<form method="post"><input type="submit" /></form>', 'put');
        $this->assertEquals('PUT', $form->getMethod(), '->getMethod() returns the method defined in the constructor if provided');

        $form = $this->createForm('<form method="post"><input type="submit" /></form>', 'delete');
        $this->assertEquals('DELETE', $form->getMethod(), '->getMethod() returns the method defined in the constructor if provided');

        $form = $this->createForm('<form method="post"><input type="submit" /></form>', 'patch');
        $this->assertEquals('PATCH', $form->getMethod(), '->getMethod() returns the method defined in the constructor if provided');
    }

    public function testGetSetValue()
    {
        $form = $this->createForm('<form><input type="text" name="foo" value="foo" /><input type="submit" /></form>');

        $this->assertEquals('foo', $form['foo']->getValue(), '->offsetGet() returns the value of a form field');

        $form['foo'] = 'bar';

        $this->assertEquals('bar', $form['foo']->getValue(), '->offsetSet() changes the value of a form field');

        try {
            $form['foobar'] = 'bar';
            $this->fail('->offsetSet() throws an \InvalidArgumentException exception if the field does not exist');
        } catch (\InvalidArgumentException $e) {
            $this->assertTrue(true, '->offsetSet() throws an \InvalidArgumentException exception if the field does not exist');
        }

        try {
            $form['foobar'];
            $this->fail('->offsetSet() throws an \InvalidArgumentException exception if the field does not exist');
        } catch (\InvalidArgumentException $e) {
            $this->assertTrue(true, '->offsetSet() throws an \InvalidArgumentException exception if the field does not exist');
        }
    }

    public function testSetValueOnMultiValuedFieldsWithMalformedName()
    {
        $form = $this->createForm('<form><input type="text" name="foo[bar]" value="bar" /><input type="text" name="foo[baz]" value="baz" /><input type="submit" /></form>');

        try {
            $form['foo[bar'] = 'bar';
            $this->fail('->offsetSet() throws an \InvalidArgumentException exception if the name is malformed.');
        } catch (\InvalidArgumentException $e) {
            $this->assertTrue(true, '->offsetSet() throws an \InvalidArgumentException exception if the name is malformed.');
        }
    }

    public function testDisableValidation()
    {
        $form = $this->createForm('<form>
            <select name="foo[bar]">
                <option value="bar">bar</option>
            </select>
            <select name="foo[baz]">
                <option value="foo">foo</option>
            </select>
            <input type="submit" />
        </form>');

        $form->disableValidation();

        $form['foo[bar]']->select('foo');
        $form['foo[baz]']->select('bar');
        $this->assertEquals('foo', $form['foo[bar]']->getValue(), '->disableValidation() disables validation of all ChoiceFormField.');
        $this->assertEquals('bar', $form['foo[baz]']->getValue(), '->disableValidation() disables validation of all ChoiceFormField.');
    }

    public function testOffsetUnset()
    {
        $form = $this->createForm('<form><input type="text" name="foo" value="foo" /><input type="submit" /></form>');
        unset($form['foo']);
        $this->assertFalse(isset($form['foo']), '->offsetUnset() removes a field');
    }

    public function testOffsetExists()
    {
        $form = $this->createForm('<form><input type="text" name="foo" value="foo" /><input type="submit" /></form>');

        $this->assertTrue(isset($form['foo']), '->offsetExists() return true if the field exists');
        $this->assertFalse(isset($form['bar']), '->offsetExists() return false if the field does not exist');
    }

    public function testGetValues()
    {
        $form = $this->createForm('<form><input type="text" name="foo[bar]" value="foo" /><input type="text" name="bar" value="bar" /><input type="submit" /></form>');
        $this->assertEquals(array('foo[bar]' => 'foo', 'bar' => 'bar'), $form->getValues(), '->getValues() returns all form field values');

        $form = $this->createForm('<form><input type="checkbox" name="foo" value="foo" /><input type="text" name="bar" value="bar" /><input type="submit" /></form>');
        $this->assertEquals(array('bar' => 'bar'), $form->getValues(), '->getValues() does not include not-checked checkboxes');

        $form = $this->createForm('<form><input type="file" name="foo" value="foo" /><input type="text" name="bar" value="bar" /><input type="submit" /></form>');
        $this->assertEquals(array('bar' => 'bar'), $form->getValues(), '->getValues() does not include file input fields');

        $form = $this->createForm('<form><input type="text" name="foo" value="foo" disabled="disabled" /><input type="text" name="bar" value="bar" /><input type="submit" /></form>');
        $this->assertEquals(array('bar' => 'bar'), $form->getValues(), '->getValues() does not include disabled fields');
    }

    public function testSetValues()
    {
        $form = $this->createForm('<form><input type="checkbox" name="foo" value="foo" checked="checked" /><input type="text" name="bar" value="bar" /><input type="submit" /></form>');
        $form->setValues(array('foo' => false, 'bar' => 'foo'));
        $this->assertEquals(array('bar' => 'foo'), $form->getValues(), '->setValues() sets the values of fields');
    }

    public function testMultiselectSetValues()
    {
        $form = $this->createForm('<form><select multiple="multiple" name="multi"><option value="foo">foo</option><option value="bar">bar</option></select><input type="submit" /></form>');
        $form->setValues(array('multi' => array("foo", "bar")));
        $this->assertEquals(array('multi' => array('foo', 'bar')), $form->getValues(), '->setValue() sets the values of select');
    }

    public function testGetPhpValues()
    {
        $form = $this->createForm('<form><input type="text" name="foo[bar]" value="foo" /><input type="text" name="bar" value="bar" /><input type="submit" /></form>');
        $this->assertEquals(array('foo' => array('bar' => 'foo'), 'bar' => 'bar'), $form->getPhpValues(), '->getPhpValues() converts keys with [] to arrays');

        $form = $this->createForm('<form><input type="text" name="fo.o[ba.r]" value="foo" /><input type="text" name="ba r" value="bar" /><input type="submit" /></form>');
        $this->assertEquals(array('fo.o' => array('ba.r' => 'foo'), 'ba r' => 'bar'), $form->getPhpValues(), '->getPhpValues() preserves periods and spaces in names');

        $form = $this->createForm('<form><input type="text" name="fo.o[ba.r][]" value="foo" /><input type="text" name="fo.o[ba.r][ba.z]" value="bar" /><input type="submit" /></form>');
        $this->assertEquals(array('fo.o' => array('ba.r' => array('foo', 'ba.z' => 'bar'))), $form->getPhpValues(), '->getPhpValues() preserves periods and spaces in names recursively');
    }

    public function testGetFiles()
    {
        $form = $this->createForm('<form><input type="file" name="foo[bar]" /><input type="text" name="bar" value="bar" /><input type="submit" /></form>');
        $this->assertEquals(array(), $form->getFiles(), '->getFiles() returns an empty array if method is get');

        $form = $this->createForm('<form method="post"><input type="file" name="foo[bar]" /><input type="text" name="bar" value="bar" /><input type="submit" /></form>');
        $this->assertEquals(array('foo[bar]' => array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0)), $form->getFiles(), '->getFiles() only returns file fields for POST');

        $form = $this->createForm('<form method="post"><input type="file" name="foo[bar]" /><input type="text" name="bar" value="bar" /><input type="submit" /></form>', 'put');
        $this->assertEquals(array('foo[bar]' => array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0)), $form->getFiles(), '->getFiles() only returns file fields for PUT');

        $form = $this->createForm('<form method="post"><input type="file" name="foo[bar]" /><input type="text" name="bar" value="bar" /><input type="submit" /></form>', 'delete');
        $this->assertEquals(array('foo[bar]' => array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0)), $form->getFiles(), '->getFiles() only returns file fields for DELETE');

        $form = $this->createForm('<form method="post"><input type="file" name="foo[bar]" /><input type="text" name="bar" value="bar" /><input type="submit" /></form>', 'patch');
        $this->assertEquals(array('foo[bar]' => array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0)), $form->getFiles(), '->getFiles() only returns file fields for PATCH');

        $form = $this->createForm('<form method="post"><input type="file" name="foo[bar]" disabled="disabled" /><input type="submit" /></form>');
        $this->assertEquals(array(), $form->getFiles(), '->getFiles() does not include disabled file fields');
    }

    public function testGetPhpFiles()
    {
        $form = $this->createForm('<form method="post"><input type="file" name="foo[bar]" /><input type="text" name="bar" value="bar" /><input type="submit" /></form>');
        $this->assertEquals(array('foo' => array('bar' => array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0))), $form->getPhpFiles(), '->getPhpFiles() converts keys with [] to arrays');

        $form = $this->createForm('<form method="post"><input type="file" name="f.o o[bar]" /><input type="text" name="bar" value="bar" /><input type="submit" /></form>');
        $this->assertEquals(array('f.o o' => array('bar' => array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0))), $form->getPhpFiles(), '->getPhpFiles() preserves periods and spaces in names');

        $form = $this->createForm('<form method="post"><input type="file" name="f.o o[bar][ba.z]" /><input type="file" name="f.o o[bar][]" /><input type="text" name="bar" value="bar" /><input type="submit" /></form>');
        $this->assertEquals(array('f.o o' => array('bar' => array('ba.z' => array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0), array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0)))), $form->getPhpFiles(), '->getPhpFiles() preserves periods and spaces in names recursively');
    }

    /**
     * @dataProvider provideGetUriValues
     */
    public function testGetUri($message, $form, $values, $uri, $method = null)
    {
        $form = $this->createForm($form, $method);
        $form->setValues($values);

        $this->assertEquals('http://example.com'.$uri, $form->getUri(), '->getUri() '.$message);
    }

    public function testGetBaseUri()
    {
        $dom = new \DOMDocument();
        $dom->loadHTML('<form method="post" action="foo.php"><input type="text" name="bar" value="bar" /><input type="submit" /></form>');

        $nodes = $dom->getElementsByTagName('input');
        $form = new Form($nodes->item($nodes->length - 1), 'http://www.foo.com/');
        $this->assertEquals('http://www.foo.com/foo.php', $form->getUri());
    }

    public function testGetUriWithAnchor()
    {
        $form = $this->createForm('<form action="#foo"><input type="submit" /></form>', null, 'http://example.com/id/123');

        $this->assertEquals('http://example.com/id/123#foo', $form->getUri());
    }

    public function testGetUriActionAbsolute()
    {
        $formHtml='<form id="login_form" action="https://login.foo.com/login.php?login_attempt=1" method="POST"><input type="text" name="foo" value="foo" /><input type="submit" /></form>';

        $form = $this->createForm($formHtml);
        $this->assertEquals('https://login.foo.com/login.php?login_attempt=1', $form->getUri(), '->getUri() returns absolute URIs set in the action form');

        $form = $this->createForm($formHtml, null, 'https://login.foo.com');
        $this->assertEquals('https://login.foo.com/login.php?login_attempt=1', $form->getUri(), '->getUri() returns absolute URIs set in the action form');

        $form = $this->createForm($formHtml, null, 'https://login.foo.com/bar/');
        $this->assertEquals('https://login.foo.com/login.php?login_attempt=1', $form->getUri(), '->getUri() returns absolute URIs set in the action form');

        // The action URI haven't the same domain Host have an another domain as Host
        $form = $this->createForm($formHtml, null, 'https://www.foo.com');
        $this->assertEquals('https://login.foo.com/login.php?login_attempt=1', $form->getUri(), '->getUri() returns absolute URIs set in the action form');

        $form = $this->createForm($formHtml, null, 'https://www.foo.com/bar/');
        $this->assertEquals('https://login.foo.com/login.php?login_attempt=1', $form->getUri(), '->getUri() returns absolute URIs set in the action form');
    }

    public function testGetUriAbsolute()
    {
        $form = $this->createForm('<form action="foo"><input type="submit" /></form>', null, 'http://localhost/foo/');
        $this->assertEquals('http://localhost/foo/foo', $form->getUri(), '->getUri() returns absolute URIs');

        $form = $this->createForm('<form action="/foo"><input type="submit" /></form>', null, 'http://localhost/foo/');
        $this->assertEquals('http://localhost/foo', $form->getUri(), '->getUri() returns absolute URIs');
    }

    public function testGetUriWithOnlyQueryString()
    {
        $form = $this->createForm('<form action="?get=param"><input type="submit" /></form>', null, 'http://localhost/foo/bar');
        $this->assertEquals('http://localhost/foo/bar?get=param', $form->getUri(), '->getUri() returns absolute URIs only if the host has been defined in the constructor');
    }

    public function testGetUriWithoutAction()
    {
        $form = $this->createForm('<form><input type="submit" /></form>', null, 'http://localhost/foo/bar');
        $this->assertEquals('http://localhost/foo/bar', $form->getUri(), '->getUri() returns path if no action defined');
    }

    public function provideGetUriValues()
    {
        return array(
            array(
                'returns the URI of the form',
                '<form action="/foo"><input type="submit" /></form>',
                array(),
                '/foo'
            ),
            array(
                'appends the form values if the method is get',
                '<form action="/foo"><input type="text" name="foo" value="foo" /><input type="submit" /></form>',
                array(),
                '/foo?foo=foo'
            ),
            array(
                'appends the form values and merges the submitted values',
                '<form action="/foo"><input type="text" name="foo" value="foo" /><input type="submit" /></form>',
                array('foo' => 'bar'),
                '/foo?foo=bar'
            ),
            array(
                'does not append values if the method is post',
                '<form action="/foo" method="post"><input type="text" name="foo" value="foo" /><input type="submit" /></form>',
                array(),
                '/foo'
            ),
            array(
                'does not append values if the method is patch',
                '<form action="/foo" method="post"><input type="text" name="foo" value="foo" /><input type="submit" /></form>',
                array(),
                '/foo',
                'PUT'
            ),
            array(
                'does not append values if the method is delete',
                '<form action="/foo" method="post"><input type="text" name="foo" value="foo" /><input type="submit" /></form>',
                array(),
                '/foo',
                'DELETE'
            ),
            array(
                'does not append values if the method is put',
                '<form action="/foo" method="post"><input type="text" name="foo" value="foo" /><input type="submit" /></form>',
                array(),
                '/foo',
                'PATCH'
            ),
            array(
                'appends the form values to an existing query string',
                '<form action="/foo?bar=bar"><input type="text" name="foo" value="foo" /><input type="submit" /></form>',
                array(),
                '/foo?bar=bar&foo=foo'
            ),
            array(
                'returns an empty URI if the action is empty',
                '<form><input type="submit" /></form>',
                array(),
                '/',
            ),
            array(
                'appends the form values even if the action is empty',
                '<form><input type="text" name="foo" value="foo" /><input type="submit" /></form>',
                array(),
                '/?foo=foo',
            ),
            array(
                'chooses the path if the action attribute value is a sharp (#)',
                '<form action="#" method="post"><input type="text" name="foo" value="foo" /><input type="submit" /></form>',
                array(),
                '/#',
            ),
        );
    }

    public function testHas()
    {
        $form = $this->createForm('<form method="post"><input type="text" name="bar" value="bar" /><input type="submit" /></form>');

        $this->assertFalse($form->has('foo'), '->has() returns false if a field is not in the form');
        $this->assertTrue($form->has('bar'), '->has() returns true if a field is in the form');
    }

    public function testRemove()
    {
        $form = $this->createForm('<form method="post"><input type="text" name="bar" value="bar" /><input type="submit" /></form>');
        $form->remove('bar');
        $this->assertFalse($form->has('bar'), '->remove() removes a field');
    }

    public function testGet()
    {
        $form = $this->createForm('<form method="post"><input type="text" name="bar" value="bar" /><input type="submit" /></form>');

        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Field\\InputFormField', $form->get('bar'), '->get() returns the field object associated with the given name');

        try {
            $form->get('foo');
            $this->fail('->get() throws an \InvalidArgumentException if the field does not exist');
        } catch (\InvalidArgumentException $e) {
            $this->assertTrue(true, '->get() throws an \InvalidArgumentException if the field does not exist');
        }
    }

    public function testAll()
    {
        $form = $this->createForm('<form method="post"><input type="text" name="bar" value="bar" /><input type="submit" /></form>');

        $fields = $form->all();
        $this->assertCount(1, $fields, '->all() return an array of form field objects');
        $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Field\\InputFormField', $fields['bar'], '->all() return an array of form field objects');
    }

    public function testSubmitWithoutAFormButton()
    {
        $dom = new \DOMDocument();
        $dom->loadHTML('
            <html>
                <form>
                    <input type="foo" />
                </form>
            </html>
        ');

        $nodes = $dom->getElementsByTagName('form');
        $form = new Form($nodes->item(0), 'http://example.com');
        $this->assertSame($nodes->item(0), $form->getFormNode(), '->getFormNode() returns the form node associated with this form');
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testFormFieldRegistryAddThrowAnExceptionWhenTheNameIsMalformed()
    {
        $registry = new FormFieldRegistry();
        $registry->add($this->getFormFieldMock('[foo]'));
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testFormFieldRegistryRemoveThrowAnExceptionWhenTheNameIsMalformed()
    {
        $registry = new FormFieldRegistry();
        $registry->remove('[foo]');
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testFormFieldRegistryGetThrowAnExceptionWhenTheNameIsMalformed()
    {
        $registry = new FormFieldRegistry();
        $registry->get('[foo]');
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testFormFieldRegistryGetThrowAnExceptionWhenTheFieldDoesNotExist()
    {
        $registry = new FormFieldRegistry();
        $registry->get('foo');
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testFormFieldRegistrySetThrowAnExceptionWhenTheNameIsMalformed()
    {
        $registry = new FormFieldRegistry();
        $registry->set('[foo]', null);
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testFormFieldRegistrySetThrowAnExceptionWhenTheFieldDoesNotExist()
    {
        $registry = new FormFieldRegistry();
        $registry->set('foo', null);
    }

    public function testFormFieldRegistryHasReturnsTrueWhenTheFQNExists()
    {
        $registry = new FormFieldRegistry();
        $registry->add($this->getFormFieldMock('foo[bar]'));

        $this->assertTrue($registry->has('foo'));
        $this->assertTrue($registry->has('foo[bar]'));
        $this->assertFalse($registry->has('bar'));
        $this->assertFalse($registry->has('foo[foo]'));
    }

    public function testFormRegistryFieldsCanBeRemoved()
    {
        $registry = new FormFieldRegistry();
        $registry->add($this->getFormFieldMock('foo'));
        $registry->remove('foo');
        $this->assertFalse($registry->has('foo'));
    }

    public function testFormRegistrySupportsMultivaluedFields()
    {
        $registry = new FormFieldRegistry();
        $registry->add($this->getFormFieldMock('foo[]'));
        $registry->add($this->getFormFieldMock('foo[]'));
        $registry->add($this->getFormFieldMock('bar[5]'));
        $registry->add($this->getFormFieldMock('bar[]'));
        $registry->add($this->getFormFieldMock('bar[baz]'));

        $this->assertEquals(
            array('foo[0]', 'foo[1]', 'bar[5]', 'bar[6]', 'bar[baz]'),
            array_keys($registry->all())
        );
    }

    public function testFormRegistrySetValues()
    {
        $registry = new FormFieldRegistry();
        $registry->add($f2 = $this->getFormFieldMock('foo[2]'));
        $registry->add($f3 = $this->getFormFieldMock('foo[3]'));
        $registry->add($fbb = $this->getFormFieldMock('foo[bar][baz]'));

        $f2
            ->expects($this->exactly(2))
            ->method('setValue')
            ->with(2)
        ;

        $f3
            ->expects($this->exactly(2))
            ->method('setValue')
            ->with(3)
        ;

        $fbb
            ->expects($this->exactly(2))
            ->method('setValue')
            ->with('fbb')
        ;

        $registry->set('foo[2]', 2);
        $registry->set('foo[3]', 3);
        $registry->set('foo[bar][baz]', 'fbb');

        $registry->set('foo', array(
            2     => 2,
            3     => 3,
            'bar' => array(
                'baz' => 'fbb'
             )
        ));
    }

    protected function getFormFieldMock($name, $value = null)
    {
        $field = $this
            ->getMockBuilder('Symfony\\Component\\DomCrawler\\Field\\FormField')
            ->setMethods(array('getName', 'getValue', 'setValue', 'initialize'))
            ->disableOriginalConstructor()
            ->getMock()
        ;

        $field
            ->expects($this->any())
            ->method('getName')
            ->will($this->returnValue($name))
        ;

        $field
            ->expects($this->any())
            ->method('getValue')
            ->will($this->returnValue($value))
        ;

        return $field;
    }

    protected function createForm($form, $method = null, $currentUri = null)
    {
        $dom = new \DOMDocument();
        $dom->loadHTML('<html>'.$form.'</html>');

        $nodes = $dom->getElementsByTagName('input');
        $xPath = new \DOMXPath($dom);
        $nodes = $xPath->query('//input | //button');

        if (null === $currentUri) {
            $currentUri = 'http://example.com/';
        }

        return new Form($nodes->item($nodes->length - 1), $currentUri, $method);
    }

    protected function createTestHtml5Form()
    {
        $dom = new \DOMDocument();
        $dom->loadHTML('
        <html>
            <h1>Hello form</h1>
            <form id="form-1" action="" method="POST">
                <div><input type="checkbox" name="apples[]" value="1" checked /></div>
                <input form="form_2" type="checkbox" name="oranges[]" value="1" checked />
                <div><label></label><input form="form-1" type="hidden" name="form_name" value="form-1" /></div>
                <input form="form-1" type="submit" name="button_1" value="Capture fields" />
                <button form="form_2" type="submit" name="button_2">Submit form_2</button>
            </form>
            <input form="form-1" type="checkbox" name="apples[]" value="2" checked />
            <form id="form_2" action="" method="POST">
                <div><div><input type="checkbox" name="oranges[]" value="2" checked />
                <input type="checkbox" name="oranges[]" value="3" checked /></div></div>
                <input form="form_2" type="hidden" name="form_name" value="form_2" />
                <input form="form-1" type="hidden" name="outer_field" value="success" />
                <button form="form-1" type="submit" name="button_3">Submit from outside the form</button>
                <div>
                    <label for="app_frontend_form_type_contact_form_type_contactType">Message subject</label>
                    <div>
                        <select name="app_frontend_form_type_contact_form_type[contactType]" id="app_frontend_form_type_contact_form_type_contactType"><option selected="selected" value="">Please select subject</option><option id="1">Test type</option></select>
                    </div>
                </div>
                <div>
                    <label for="app_frontend_form_type_contact_form_type_firstName">Firstname</label>
                    <input type="text" name="app_frontend_form_type_contact_form_type[firstName]" value="John" id="app_frontend_form_type_contact_form_type_firstName"/>
                </div>
            </form>
            <button />
        </html>');

        return $dom;
    }
}
PK��Zm�Y���?test/DomCrawler/Symfony/Component/DomCrawler/Tests/LinkTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DomCrawler\Tests;

use Symfony\Component\DomCrawler\Link;

class LinkTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \LogicException
     */
    public function testConstructorWithANonATag()
    {
        $dom = new \DOMDocument();
        $dom->loadHTML('<html><div><div></html>');

        new Link($dom->getElementsByTagName('div')->item(0), 'http://www.example.com/');
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testConstructorWithAnInvalidCurrentUri()
    {
        $dom = new \DOMDocument();
        $dom->loadHTML('<html><a href="/foo">foo</a></html>');

        new Link($dom->getElementsByTagName('a')->item(0), 'example.com');
    }

    public function testGetNode()
    {
        $dom = new \DOMDocument();
        $dom->loadHTML('<html><a href="/foo">foo</a></html>');

        $node = $dom->getElementsByTagName('a')->item(0);
        $link = new Link($node, 'http://example.com/');

        $this->assertEquals($node, $link->getNode(), '->getNode() returns the node associated with the link');
    }

    public function testGetMethod()
    {
        $dom = new \DOMDocument();
        $dom->loadHTML('<html><a href="/foo">foo</a></html>');

        $node = $dom->getElementsByTagName('a')->item(0);
        $link = new Link($node, 'http://example.com/');

        $this->assertEquals('GET', $link->getMethod(), '->getMethod() returns the method of the link');

        $link = new Link($node, 'http://example.com/', 'post');
        $this->assertEquals('POST', $link->getMethod(), '->getMethod() returns the method of the link');
    }

    /**
     * @dataProvider getGetUriTests
     */
    public function testGetUri($url, $currentUri, $expected)
    {
        $dom = new \DOMDocument();
        $dom->loadHTML(sprintf('<html><a href="%s">foo</a></html>', $url));
        $link = new Link($dom->getElementsByTagName('a')->item(0), $currentUri);

        $this->assertEquals($expected, $link->getUri());
    }

    /**
     * @dataProvider getGetUriTests
     */
    public function testGetUriOnArea($url, $currentUri, $expected)
    {
        $dom = new \DOMDocument();
        $dom->loadHTML(sprintf('<html><map><area href="%s" /></map></html>', $url));
        $link = new Link($dom->getElementsByTagName('area')->item(0), $currentUri);

        $this->assertEquals($expected, $link->getUri());
    }

    public function getGetUriTests()
    {
        return array(
            array('/foo', 'http://localhost/bar/foo/', 'http://localhost/foo'),
            array('/foo', 'http://localhost/bar/foo', 'http://localhost/foo'),
            array('
            /foo', 'http://localhost/bar/foo/', 'http://localhost/foo'),
            array('/foo
            ', 'http://localhost/bar/foo', 'http://localhost/foo'),

            array('foo', 'http://localhost/bar/foo/', 'http://localhost/bar/foo/foo'),
            array('foo', 'http://localhost/bar/foo', 'http://localhost/bar/foo'),

            array('', 'http://localhost/bar/', 'http://localhost/bar/'),
            array('#', 'http://localhost/bar/', 'http://localhost/bar/#'),
            array('#bar', 'http://localhost/bar/#foo', 'http://localhost/bar/#bar'),
            array('?a=b', 'http://localhost/bar/', 'http://localhost/bar/?a=b'),

            array('http://login.foo.com/foo', 'http://localhost/bar/', 'http://login.foo.com/foo'),
            array('https://login.foo.com/foo', 'https://localhost/bar/', 'https://login.foo.com/foo'),
            array('mailto:foo@bar.com', 'http://localhost/foo', 'mailto:foo@bar.com'),

            // tests schema relative URL (issue #7169)
            array('//login.foo.com/foo', 'http://localhost/bar/', 'http://login.foo.com/foo'),
            array('//login.foo.com/foo', 'https://localhost/bar/', 'https://login.foo.com/foo'),

            array('?foo=2', 'http://localhost?foo=1', 'http://localhost?foo=2'),
            array('?foo=2', 'http://localhost/?foo=1', 'http://localhost/?foo=2'),
            array('?foo=2', 'http://localhost/bar?foo=1', 'http://localhost/bar?foo=2'),
            array('?foo=2', 'http://localhost/bar/?foo=1', 'http://localhost/bar/?foo=2'),
            array('?bar=2', 'http://localhost?foo=1', 'http://localhost?bar=2'),

            array('foo', 'http://login.foo.com/bar/baz?/query/string', 'http://login.foo.com/bar/foo'),

            array('.', 'http://localhost/foo/bar/baz', 'http://localhost/foo/bar/'),
            array('./', 'http://localhost/foo/bar/baz', 'http://localhost/foo/bar/'),
            array('./foo', 'http://localhost/foo/bar/baz', 'http://localhost/foo/bar/foo'),
            array('..', 'http://localhost/foo/bar/baz', 'http://localhost/foo/'),
            array('../', 'http://localhost/foo/bar/baz', 'http://localhost/foo/'),
            array('../foo', 'http://localhost/foo/bar/baz', 'http://localhost/foo/foo'),
            array('../..', 'http://localhost/foo/bar/baz', 'http://localhost/'),
            array('../../', 'http://localhost/foo/bar/baz', 'http://localhost/'),
            array('../../foo', 'http://localhost/foo/bar/baz', 'http://localhost/foo'),
            array('../../foo', 'http://localhost/bar/foo/', 'http://localhost/foo'),
            array('../bar/../../foo', 'http://localhost/bar/foo/', 'http://localhost/foo'),
            array('../bar/./../../foo', 'http://localhost/bar/foo/', 'http://localhost/foo'),
            array('../../', 'http://localhost/', 'http://localhost/'),
            array('../../', 'http://localhost', 'http://localhost/'),

            array('/foo', 'file:///', 'file:///foo'),
            array('/foo', 'file:///bar/baz', 'file:///foo'),
            array('foo', 'file:///', 'file:///foo'),
            array('foo', 'file:///bar/baz', 'file:///bar/foo'),
        );
    }
}
PK��Z)q0�ll=test/DomCrawler/Symfony/Component/DomCrawler/phpunit.xml.distnu�[���<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony DomCrawler Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./Resources</directory>
                <directory>./Tests</directory>
                <directory>./vendor</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
PK��Z��H�77Ltest/CssSelector/Symfony/Component/CssSelector/Tests/XPath/Fixtures/ids.htmlnu�[���<html id="html"><head>
  <link id="link-href" href="foo" />
  <link id="link-nohref" />
</head><body>
<div id="outer-div">
 <a id="name-anchor" name="foo"></a>
 <a id="tag-anchor" rel="tag" href="http://localhost/foo">link</a>
 <a id="nofollow-anchor" rel="nofollow" href="https://example.org">
    link</a>
 <ol id="first-ol" class="a b c">
   <li id="first-li">content</li>
   <li id="second-li" lang="En-us">
     <div id="li-div">
     </div>
   </li>
   <li id="third-li" class="ab c"></li>
   <li id="fourth-li" class="ab
c"></li>
   <li id="fifth-li"></li>
   <li id="sixth-li"></li>
   <li id="seventh-li">  </li>
 </ol>
 <p id="paragraph">
   <b id="p-b">hi</b> <em id="p-em">there</em>
   <b id="p-b2">guy</b>
   <input type="checkbox" id="checkbox-unchecked" />
   <input type="checkbox" id="checkbox-disabled" disabled="" />
   <input type="text" id="text-checked" checked="checked" />
   <input type="hidden" />
   <input type="hidden" disabled="disabled" />
   <input type="checkbox" id="checkbox-checked" checked="checked" />
   <input type="checkbox" id="checkbox-disabled-checked"
          disabled="disabled" checked="checked" />
   <fieldset id="fieldset" disabled="disabled">
     <input type="checkbox" id="checkbox-fieldset-disabled" />
     <input type="hidden" />
   </fieldset>
 </p>
 <ol id="second-ol">
 </ol>
 <map name="dummymap">
   <area shape="circle" coords="200,250,25" href="foo.html" id="area-href" />
   <area shape="default" id="area-nohref" />
 </map>
</div>
<div id="foobar-div" foobar="ab bc
cde"><span id="foobar-span"></span></div>
</body></html>
PK��ZmiĪ:�:Stest/CssSelector/Symfony/Component/CssSelector/Tests/XPath/Fixtures/shakespear.htmlnu�[���<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" debug="true">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>
	<div id="test">
	<div class="dialog">
	<h2>As You Like It</h2>
	<div id="playwright">
	  by William Shakespeare
	</div>
	<div class="dialog scene thirdClass" id="scene1">
	  <h3>ACT I, SCENE III. A room in the palace.</h3>
	  <div class="dialog">
	  <div class="direction">Enter CELIA and ROSALIND</div>
	  </div>
	  <div id="speech1" class="character">CELIA</div>
	  <div class="dialog">
	  <div id="scene1.3.1">Why, cousin! why, Rosalind! Cupid have mercy! not a word?</div>
	  </div>
	  <div id="speech2" class="character">ROSALIND</div>
	  <div class="dialog">
	  <div id="scene1.3.2">Not one to throw at a dog.</div>
	  </div>
	  <div id="speech3" class="character">CELIA</div>
	  <div class="dialog">
	  <div id="scene1.3.3">No, thy words are too precious to be cast away upon</div>
	  <div id="scene1.3.4">curs; throw some of them at me; come, lame me with reasons.</div>
	  </div>
	  <div id="speech4" class="character">ROSALIND</div>
	  <div id="speech5" class="character">CELIA</div>
	  <div class="dialog">
	  <div id="scene1.3.8">But is all this for your father?</div>
	  </div>
	  <div class="dialog">
	  <div id="scene1.3.5">Then there were two cousins laid up; when the one</div>
	  <div id="scene1.3.6">should be lamed with reasons and the other mad</div>
	  <div id="scene1.3.7">without any.</div>
	  </div>
	  <div id="speech6" class="character">ROSALIND</div>
	  <div class="dialog">
	  <div id="scene1.3.9">No, some of it is for my child's father. O, how</div>
	  <div id="scene1.3.10">full of briers is this working-day world!</div>
	  </div>
	  <div id="speech7" class="character">CELIA</div>
	  <div class="dialog">
	  <div id="scene1.3.11">They are but burs, cousin, thrown upon thee in</div>
	  <div id="scene1.3.12">holiday foolery: if we walk not in the trodden</div>
	  <div id="scene1.3.13">paths our very petticoats will catch them.</div>
	  </div>
	  <div id="speech8" class="character">ROSALIND</div>
	  <div class="dialog">
	  <div id="scene1.3.14">I could shake them off my coat: these burs are in my heart.</div>
	  </div>
	  <div id="speech9" class="character">CELIA</div>
	  <div class="dialog">
	  <div id="scene1.3.15">Hem them away.</div>
	  </div>
	  <div id="speech10" class="character">ROSALIND</div>
	  <div class="dialog">
	  <div id="scene1.3.16">I would try, if I could cry 'hem' and have him.</div>
	  </div>
	  <div id="speech11" class="character">CELIA</div>
	  <div class="dialog">
	  <div id="scene1.3.17">Come, come, wrestle with thy affections.</div>
	  </div>
	  <div id="speech12" class="character">ROSALIND</div>
	  <div class="dialog">
	  <div id="scene1.3.18">O, they take the part of a better wrestler than myself!</div>
	  </div>
	  <div id="speech13" class="character">CELIA</div>
	  <div class="dialog">
	  <div id="scene1.3.19">O, a good wish upon you! you will try in time, in</div>
	  <div id="scene1.3.20">despite of a fall. But, turning these jests out of</div>
	  <div id="scene1.3.21">service, let us talk in good earnest: is it</div>
	  <div id="scene1.3.22">possible, on such a sudden, you should fall into so</div>
	  <div id="scene1.3.23">strong a liking with old Sir Rowland's youngest son?</div>
	  </div>
	  <div id="speech14" class="character">ROSALIND</div>
	  <div class="dialog">
	  <div id="scene1.3.24">The duke my father loved his father dearly.</div>
	  </div>
	  <div id="speech15" class="character">CELIA</div>
	  <div class="dialog">
	  <div id="scene1.3.25">Doth it therefore ensue that you should love his son</div>
	  <div id="scene1.3.26">dearly? By this kind of chase, I should hate him,</div>
	  <div id="scene1.3.27">for my father hated his father dearly; yet I hate</div>
	  <div id="scene1.3.28">not Orlando.</div>
	  </div>
	  <div id="speech16" class="character">ROSALIND</div>
	  <div title="wtf" class="dialog">
	  <div id="scene1.3.29">No, faith, hate him not, for my sake.</div>
	  </div>
	  <div id="speech17" class="character">CELIA</div>
	  <div class="dialog">
	  <div id="scene1.3.30">Why should I not? doth he not deserve well?</div>
	  </div>
	  <div id="speech18" class="character">ROSALIND</div>
	  <div class="dialog">
	  <div id="scene1.3.31">Let me love him for that, and do you love him</div>
	  <div id="scene1.3.32">because I do. Look, here comes the duke.</div>
	  </div>
	  <div id="speech19" class="character">CELIA</div>
	  <div class="dialog">
	  <div id="scene1.3.33">With his eyes full of anger.</div>
	  <div class="direction">Enter DUKE FREDERICK, with Lords</div>
	  </div>
	  <div id="speech20" class="character">DUKE FREDERICK</div>
	  <div class="dialog">
	  <div id="scene1.3.34">Mistress, dispatch you with your safest haste</div>
	  <div id="scene1.3.35">And get you from our court.</div>
	  </div>
	  <div id="speech21" class="character">ROSALIND</div>
	  <div class="dialog">
	  <div id="scene1.3.36">Me, uncle?</div>
	  </div>
	  <div id="speech22" class="character">DUKE FREDERICK</div>
	  <div class="dialog">
	  <div id="scene1.3.37">You, cousin</div>
	  <div id="scene1.3.38">Within these ten days if that thou be'st found</div>
	  <div id="scene1.3.39">So near our public court as twenty miles,</div>
	  <div id="scene1.3.40">Thou diest for it.</div>
	  </div>
	  <div id="speech23" class="character">ROSALIND</div>
	  <div class="dialog">
	  <div id="scene1.3.41">                  I do beseech your grace,</div>
	  <div id="scene1.3.42">Let me the knowledge of my fault bear with me:</div>
	  <div id="scene1.3.43">If with myself I hold intelligence</div>
	  <div id="scene1.3.44">Or have acquaintance with mine own desires,</div>
	  <div id="scene1.3.45">If that I do not dream or be not frantic,--</div>
	  <div id="scene1.3.46">As I do trust I am not--then, dear uncle,</div>
	  <div id="scene1.3.47">Never so much as in a thought unborn</div>
	  <div id="scene1.3.48">Did I offend your highness.</div>
	  </div>
	  <div id="speech24" class="character">DUKE FREDERICK</div>
	  <div class="dialog">
	  <div id="scene1.3.49">Thus do all traitors:</div>
	  <div id="scene1.3.50">If their purgation did consist in words,</div>
	  <div id="scene1.3.51">They are as innocent as grace itself:</div>
	  <div id="scene1.3.52">Let it suffice thee that I trust thee not.</div>
	  </div>
	  <div id="speech25" class="character">ROSALIND</div>
	  <div class="dialog">
	  <div id="scene1.3.53">Yet your mistrust cannot make me a traitor:</div>
	  <div id="scene1.3.54">Tell me whereon the likelihood depends.</div>
	  </div>
	  <div id="speech26" class="character">DUKE FREDERICK</div>
	  <div class="dialog">
	  <div id="scene1.3.55">Thou art thy father's daughter; there's enough.</div>
	  </div>
	  <div id="speech27" class="character">ROSALIND</div>
	  <div class="dialog">
	  <div id="scene1.3.56">So was I when your highness took his dukedom;</div>
	  <div id="scene1.3.57">So was I when your highness banish'd him:</div>
	  <div id="scene1.3.58">Treason is not inherited, my lord;</div>
	  <div id="scene1.3.59">Or, if we did derive it from our friends,</div>
	  <div id="scene1.3.60">What's that to me? my father was no traitor:</div>
	  <div id="scene1.3.61">Then, good my liege, mistake me not so much</div>
	  <div id="scene1.3.62">To think my poverty is treacherous.</div>
	  </div>
	  <div id="speech28" class="character">CELIA</div>
	  <div class="dialog">
	  <div id="scene1.3.63">Dear sovereign, hear me speak.</div>
	  </div>
	  <div id="speech29" class="character">DUKE FREDERICK</div>
	  <div class="dialog">
	  <div id="scene1.3.64">Ay, Celia; we stay'd her for your sake,</div>
	  <div id="scene1.3.65">Else had she with her father ranged along.</div>
	  </div>
	  <div id="speech30" class="character">CELIA</div>
	  <div class="dialog">
	  <div id="scene1.3.66">I did not then entreat to have her stay;</div>
	  <div id="scene1.3.67">It was your pleasure and your own remorse:</div>
	  <div id="scene1.3.68">I was too young that time to value her;</div>
	  <div id="scene1.3.69">But now I know her: if she be a traitor,</div>
	  <div id="scene1.3.70">Why so am I; we still have slept together,</div>
	  <div id="scene1.3.71">Rose at an instant, learn'd, play'd, eat together,</div>
	  <div id="scene1.3.72">And wheresoever we went, like Juno's swans,</div>
	  <div id="scene1.3.73">Still we went coupled and inseparable.</div>
	  </div>
	  <div id="speech31" class="character">DUKE FREDERICK</div>
	  <div class="dialog">
	  <div id="scene1.3.74">She is too subtle for thee; and her smoothness,</div>
	  <div id="scene1.3.75">Her very silence and her patience</div>
	  <div id="scene1.3.76">Speak to the people, and they pity her.</div>
	  <div id="scene1.3.77">Thou art a fool: she robs thee of thy name;</div>
	  <div id="scene1.3.78">And thou wilt show more bright and seem more virtuous</div>
	  <div id="scene1.3.79">When she is gone. Then open not thy lips:</div>
	  <div id="scene1.3.80">Firm and irrevocable is my doom</div>
	  <div id="scene1.3.81">Which I have pass'd upon her; she is banish'd.</div>
	  </div>
	  <div id="speech32" class="character">CELIA</div>
	  <div class="dialog">
	  <div id="scene1.3.82">Pronounce that sentence then on me, my liege:</div>
	  <div id="scene1.3.83">I cannot live out of her company.</div>
	  </div>
	  <div id="speech33" class="character">DUKE FREDERICK</div>
	  <div class="dialog">
	  <div id="scene1.3.84">You are a fool. You, niece, provide yourself:</div>
	  <div id="scene1.3.85">If you outstay the time, upon mine honour,</div>
	  <div id="scene1.3.86">And in the greatness of my word, you die.</div>
	  <div class="direction">Exeunt DUKE FREDERICK and Lords</div>
	  </div>
	  <div id="speech34" class="character">CELIA</div>
	  <div class="dialog">
	  <div id="scene1.3.87">O my poor Rosalind, whither wilt thou go?</div>
	  <div id="scene1.3.88">Wilt thou change fathers? I will give thee mine.</div>
	  <div id="scene1.3.89">I charge thee, be not thou more grieved than I am.</div>
	  </div>
	  <div id="speech35" class="character">ROSALIND</div>
	  <div class="dialog">
	  <div id="scene1.3.90">I have more cause.</div>
	  </div>
	  <div id="speech36" class="character">CELIA</div>
	  <div class="dialog">
	  <div id="scene1.3.91">                  Thou hast not, cousin;</div>
	  <div id="scene1.3.92">Prithee be cheerful: know'st thou not, the duke</div>
	  <div id="scene1.3.93">Hath banish'd me, his daughter?</div>
	  </div>
	  <div id="speech37" class="character">ROSALIND</div>
	  <div class="dialog">
	  <div id="scene1.3.94">That he hath not.</div>
	  </div>
	  <div id="speech38" class="character">CELIA</div>
	  <div class="dialog">
	  <div id="scene1.3.95">No, hath not? Rosalind lacks then the love</div>
	  <div id="scene1.3.96">Which teacheth thee that thou and I am one:</div>
	  <div id="scene1.3.97">Shall we be sunder'd? shall we part, sweet girl?</div>
	  <div id="scene1.3.98">No: let my father seek another heir.</div>
	  <div id="scene1.3.99">Therefore devise with me how we may fly,</div>
	  <div id="scene1.3.100">Whither to go and what to bear with us;</div>
	  <div id="scene1.3.101">And do not seek to take your change upon you,</div>
	  <div id="scene1.3.102">To bear your griefs yourself and leave me out;</div>
	  <div id="scene1.3.103">For, by this heaven, now at our sorrows pale,</div>
	  <div id="scene1.3.104">Say what thou canst, I'll go along with thee.</div>
	  </div>
	  <div id="speech39" class="character">ROSALIND</div>
	  <div class="dialog">
	  <div id="scene1.3.105">Why, whither shall we go?</div>
	  </div>
	  <div id="speech40" class="character">CELIA</div>
	  <div class="dialog">
	  <div id="scene1.3.106">To seek my uncle in the forest of Arden.</div>
	  </div>
	  <div id="speech41" class="character">ROSALIND</div>
	  <div class="dialog">
	  <div id="scene1.3.107">Alas, what danger will it be to us,</div>
	  <div id="scene1.3.108">Maids as we are, to travel forth so far!</div>
	  <div id="scene1.3.109">Beauty provoketh thieves sooner than gold.</div>
	  </div>
	  <div id="speech42" class="character">CELIA</div>
	  <div class="dialog">
	  <div id="scene1.3.110">I'll put myself in poor and mean attire</div>
	  <div id="scene1.3.111">And with a kind of umber smirch my face;</div>
	  <div id="scene1.3.112">The like do you: so shall we pass along</div>
	  <div id="scene1.3.113">And never stir assailants.</div>
	  </div>
	  <div id="speech43" class="character">ROSALIND</div>
	  <div class="dialog">
	  <div id="scene1.3.114">Were it not better,</div>
	  <div id="scene1.3.115">Because that I am more than common tall,</div>
	  <div id="scene1.3.116">That I did suit me all points like a man?</div>
	  <div id="scene1.3.117">A gallant curtle-axe upon my thigh,</div>
	  <div id="scene1.3.118">A boar-spear in my hand; and--in my heart</div>
	  <div id="scene1.3.119">Lie there what hidden woman's fear there will--</div>
	  <div id="scene1.3.120">We'll have a swashing and a martial outside,</div>
	  <div id="scene1.3.121">As many other mannish cowards have</div>
	  <div id="scene1.3.122">That do outface it with their semblances.</div>
	  </div>
	  <div id="speech44" class="character">CELIA</div>
	  <div class="dialog">
	  <div id="scene1.3.123">What shall I call thee when thou art a man?</div>
	  </div>
	  <div id="speech45" class="character">ROSALIND</div>
	  <div class="dialog">
	  <div id="scene1.3.124">I'll have no worse a name than Jove's own page;</div>
	  <div id="scene1.3.125">And therefore look you call me Ganymede.</div>
	  <div id="scene1.3.126">But what will you be call'd?</div>
	  </div>
	  <div id="speech46" class="character">CELIA</div>
	  <div class="dialog">
	  <div id="scene1.3.127">Something that hath a reference to my state</div>
	  <div id="scene1.3.128">No longer Celia, but Aliena.</div>
	  </div>
	  <div id="speech47" class="character">ROSALIND</div>
	  <div class="dialog">
	  <div id="scene1.3.129">But, cousin, what if we assay'd to steal</div>
	  <div id="scene1.3.130">The clownish fool out of your father's court?</div>
	  <div id="scene1.3.131">Would he not be a comfort to our travel?</div>
	  </div>
	  <div id="speech48" class="character">CELIA</div>
	  <div class="dialog">
	  <div id="scene1.3.132">He'll go along o'er the wide world with me;</div>
	  <div id="scene1.3.133">Leave me alone to woo him. Let's away,</div>
	  <div id="scene1.3.134">And get our jewels and our wealth together,</div>
	  <div id="scene1.3.135">Devise the fittest time and safest way</div>
	  <div id="scene1.3.136">To hide us from pursuit that will be made</div>
	  <div id="scene1.3.137">After my flight. Now go we in content</div>
	  <div id="scene1.3.138">To liberty and not to banishment.</div>
	  <div class="direction">Exeunt</div>
	  </div>
	</div>
	</div>
</div>
</body>
</html>
PK��Z�B�==Ltest/CssSelector/Symfony/Component/CssSelector/Tests/XPath/Fixtures/lang.xmlnu�[���<test>
  <a id="first" xml:lang="en">a</a>
  <b id="second" xml:lang="en-US">b</b>
  <c id="third" xml:lang="en-Nz">c</c>
  <d id="fourth" xml:lang="En-us">d</d>
  <e id="fifth" xml:lang="fr">e</e>
  <f id="sixth" xml:lang="ru">f</f>
  <g id="seventh" xml:lang="de">
    <h id="eighth" xml:lang="zh"/>
  </g>
</test>
PK��Z1�HCHCMtest/CssSelector/Symfony/Component/CssSelector/Tests/XPath/TranslatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Tests\XPath;

use Symfony\Component\CssSelector\XPath\Extension\HtmlExtension;
use Symfony\Component\CssSelector\XPath\Translator;

class TranslatorTest extends \PHPUnit_Framework_TestCase
{
    /** @dataProvider getXpathLiteralTestData */
    public function testXpathLiteral($value, $literal)
    {
        $this->assertEquals($literal, Translator::getXpathLiteral($value));
    }

    /** @dataProvider getCssToXPathTestData */
    public function testCssToXPath($css, $xpath)
    {
        $translator = new Translator();
        $translator->registerExtension(new HtmlExtension($translator));
        $this->assertEquals($xpath, $translator->cssToXPath($css, ''));
    }

    /** @dataProvider getXmlLangTestData */
    public function testXmlLang($css, array $elementsId)
    {
        $translator = new Translator();
        $document = new \SimpleXMLElement(file_get_contents(__DIR__.'/Fixtures/lang.xml'));
        $elements = $document->xpath($translator->cssToXPath($css));
        $this->assertEquals(count($elementsId), count($elements));
        foreach ($elements as $element) {
            $this->assertTrue(in_array($element->attributes()->id, $elementsId));
        }
    }

    /** @dataProvider getHtmlIdsTestData */
    public function testHtmlIds($css, array $elementsId)
    {
        $translator = new Translator();
        $translator->registerExtension(new HtmlExtension($translator));
        $document = new \DOMDocument();
        $document->strictErrorChecking = false;
        $internalErrors = libxml_use_internal_errors(true);
        $document->loadHTMLFile(__DIR__.'/Fixtures/ids.html');
        $document = simplexml_import_dom($document);
        $elements = $document->xpath($translator->cssToXPath($css));
        $this->assertCount(count($elementsId), $elementsId);
        foreach ($elements as $element) {
            if (null !== $element->attributes()->id) {
                $this->assertTrue(in_array($element->attributes()->id, $elementsId));
            }
        }
        libxml_clear_errors();
        libxml_use_internal_errors($internalErrors);
    }

    /** @dataProvider getHtmlShakespearTestData */
    public function testHtmlShakespear($css, $count)
    {
        $translator = new Translator();
        $translator->registerExtension(new HtmlExtension($translator));
        $document = new \DOMDocument();
        $document->strictErrorChecking = false;
        $document->loadHTMLFile(__DIR__.'/Fixtures/shakespear.html');
        $document = simplexml_import_dom($document);
        $bodies = $document->xpath('//body');
        $elements = $bodies[0]->xpath($translator->cssToXPath($css));
        $this->assertEquals($count, count($elements));
    }

    public function getXpathLiteralTestData()
    {
        return array(
            array('foo', "'foo'"),
            array("foo's bar", '"foo\'s bar"'),
            array("foo's \"middle\" bar", 'concat(\'foo\', "\'", \'s "middle" bar\')'),
            array("foo's 'middle' \"bar\"", 'concat(\'foo\', "\'", \'s \', "\'", \'middle\', "\'", \' "bar"\')'),
        );
    }

    public function getCssToXPathTestData()
    {
        return array(
            array('*', "*"),
            array('e', "e"),
            array('*|e', "e"),
            array('e|f', "e:f"),
            array('e[foo]', "e[@foo]"),
            array('e[foo|bar]', "e[@foo:bar]"),
            array('e[foo="bar"]', "e[@foo = 'bar']"),
            array('e[foo~="bar"]', "e[@foo and contains(concat(' ', normalize-space(@foo), ' '), ' bar ')]"),
            array('e[foo^="bar"]', "e[@foo and starts-with(@foo, 'bar')]"),
            array('e[foo$="bar"]', "e[@foo and substring(@foo, string-length(@foo)-2) = 'bar']"),
            array('e[foo*="bar"]', "e[@foo and contains(@foo, 'bar')]"),
            array('e[hreflang|="en"]', "e[@hreflang and (@hreflang = 'en' or starts-with(@hreflang, 'en-'))]"),
            array('e:nth-child(1)', "*/*[name() = 'e' and (position() = 1)]"),
            array('e:nth-last-child(1)', "*/*[name() = 'e' and (position() = last() - 0)]"),
            array('e:nth-last-child(2n+2)', "*/*[name() = 'e' and (last() - position() - 1 >= 0 and (last() - position() - 1) mod 2 = 0)]"),
            array('e:nth-of-type(1)', "*/e[position() = 1]"),
            array('e:nth-last-of-type(1)', "*/e[position() = last() - 0]"),
            array('div e:nth-last-of-type(1) .aclass', "div/descendant-or-self::*/e[position() = last() - 0]/descendant-or-self::*/*[@class and contains(concat(' ', normalize-space(@class), ' '), ' aclass ')]"),
            array('e:first-child', "*/*[name() = 'e' and (position() = 1)]"),
            array('e:last-child', "*/*[name() = 'e' and (position() = last())]"),
            array('e:first-of-type', "*/e[position() = 1]"),
            array('e:last-of-type', "*/e[position() = last()]"),
            array('e:only-child', "*/*[name() = 'e' and (last() = 1)]"),
            array('e:only-of-type', "e[last() = 1]"),
            array('e:empty', "e[not(*) and not(string-length())]"),
            array('e:EmPTY', "e[not(*) and not(string-length())]"),
            array('e:root', "e[not(parent::*)]"),
            array('e:hover', "e[0]"),
            array('e:contains("foo")', "e[contains(string(.), 'foo')]"),
            array('e:ConTains(foo)', "e[contains(string(.), 'foo')]"),
            array('e.warning', "e[@class and contains(concat(' ', normalize-space(@class), ' '), ' warning ')]"),
            array('e#myid', "e[@id = 'myid']"),
            array('e:not(:nth-child(odd))', "e[not(position() - 1 >= 0 and (position() - 1) mod 2 = 0)]"),
            array('e:nOT(*)', "e[0]"),
            array('e f', "e/descendant-or-self::*/f"),
            array('e > f', "e/f"),
            array('e + f', "e/following-sibling::*[name() = 'f' and (position() = 1)]"),
            array('e ~ f', "e/following-sibling::f"),
            array('div#container p', "div[@id = 'container']/descendant-or-self::*/p"),
        );
    }

    public function getXmlLangTestData()
    {
        return array(
            array(':lang("EN")', array('first', 'second', 'third', 'fourth')),
            array(':lang("en-us")', array('second', 'fourth')),
            array(':lang(en-nz)', array('third')),
            array(':lang(fr)', array('fifth')),
            array(':lang(ru)', array('sixth')),
            array(":lang('ZH')", array('eighth')),
            array(':lang(de) :lang(zh)', array('eighth')),
            array(':lang(en), :lang(zh)', array('first', 'second', 'third', 'fourth', 'eighth')),
            array(':lang(es)', array()),
        );
    }

    public function getHtmlIdsTestData()
    {
        return array(
            array('div', array('outer-div', 'li-div', 'foobar-div')),
            array('DIV', array('outer-div', 'li-div', 'foobar-div')),  // case-insensitive in HTML
            array('div div', array('li-div')),
            array('div, div div', array('outer-div', 'li-div', 'foobar-div')),
            array('a[name]', array('name-anchor')),
            array('a[NAme]', array('name-anchor')), // case-insensitive in HTML:
            array('a[rel]', array('tag-anchor', 'nofollow-anchor')),
            array('a[rel="tag"]', array('tag-anchor')),
            array('a[href*="localhost"]', array('tag-anchor')),
            array('a[href*=""]', array()),
            array('a[href^="http"]', array('tag-anchor', 'nofollow-anchor')),
            array('a[href^="http:"]', array('tag-anchor')),
            array('a[href^=""]', array()),
            array('a[href$="org"]', array('nofollow-anchor')),
            array('a[href$=""]', array()),
            array('div[foobar~="bc"]', array('foobar-div')),
            array('div[foobar~="cde"]', array('foobar-div')),
            array('[foobar~="ab bc"]', array('foobar-div')),
            array('[foobar~=""]', array()),
            array('[foobar~=" \t"]', array()),
            array('div[foobar~="cd"]', array()),
            array('*[lang|="En"]', array('second-li')),
            array('[lang|="En-us"]', array('second-li')),
            // Attribute values are case sensitive
            array('*[lang|="en"]', array()),
            array('[lang|="en-US"]', array()),
            array('*[lang|="e"]', array()),
            // ... :lang() is not.
            array(':lang("EN")', array('second-li', 'li-div')),
            array('*:lang(en-US)', array('second-li', 'li-div')),
            array(':lang("e")', array()),
            array('li:nth-child(3)', array('third-li')),
            array('li:nth-child(10)', array()),
            array('li:nth-child(2n)', array('second-li', 'fourth-li', 'sixth-li')),
            array('li:nth-child(even)', array('second-li', 'fourth-li', 'sixth-li')),
            array('li:nth-child(2n+0)', array('second-li', 'fourth-li', 'sixth-li')),
            array('li:nth-child(+2n+1)', array('first-li', 'third-li', 'fifth-li', 'seventh-li')),
            array('li:nth-child(odd)', array('first-li', 'third-li', 'fifth-li', 'seventh-li')),
            array('li:nth-child(2n+4)', array('fourth-li', 'sixth-li')),
            array('li:nth-child(3n+1)', array('first-li', 'fourth-li', 'seventh-li')),
            array('li:nth-child(n)', array('first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li')),
            array('li:nth-child(n-1)', array('first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li')),
            array('li:nth-child(n+1)', array('first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li')),
            array('li:nth-child(n+3)', array('third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li')),
            array('li:nth-child(-n)', array()),
            array('li:nth-child(-n-1)', array()),
            array('li:nth-child(-n+1)', array('first-li')),
            array('li:nth-child(-n+3)', array('first-li', 'second-li', 'third-li')),
            array('li:nth-last-child(0)', array()),
            array('li:nth-last-child(2n)', array('second-li', 'fourth-li', 'sixth-li')),
            array('li:nth-last-child(even)', array('second-li', 'fourth-li', 'sixth-li')),
            array('li:nth-last-child(2n+2)', array('second-li', 'fourth-li', 'sixth-li')),
            array('li:nth-last-child(n)', array('first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li')),
            array('li:nth-last-child(n-1)', array('first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li')),
            array('li:nth-last-child(n-3)', array('first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li')),
            array('li:nth-last-child(n+1)', array('first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li')),
            array('li:nth-last-child(n+3)', array('first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li')),
            array('li:nth-last-child(-n)', array()),
            array('li:nth-last-child(-n-1)', array()),
            array('li:nth-last-child(-n+1)', array('seventh-li')),
            array('li:nth-last-child(-n+3)', array('fifth-li', 'sixth-li', 'seventh-li')),
            array('ol:first-of-type', array('first-ol')),
            array('ol:nth-child(1)', array('first-ol')),
            array('ol:nth-of-type(2)', array('second-ol')),
            array('ol:nth-last-of-type(1)', array('second-ol')),
            array('span:only-child', array('foobar-span')),
            array('li div:only-child', array('li-div')),
            array('div *:only-child', array('li-div', 'foobar-span')),
            array('p:only-of-type', array('paragraph')),
            array('a:empty', array('name-anchor')),
            array('a:EMpty', array('name-anchor')),
            array('li:empty', array('third-li', 'fourth-li', 'fifth-li', 'sixth-li')),
            array(':root', array('html')),
            array('html:root', array('html')),
            array('li:root', array()),
            array('* :root', array()),
            array('*:contains("link")', array('html', 'outer-div', 'tag-anchor', 'nofollow-anchor')),
            array(':CONtains("link")', array('html', 'outer-div', 'tag-anchor', 'nofollow-anchor')),
            array('*:contains("LInk")', array()),  // case sensitive
            array('*:contains("e")', array('html', 'nil', 'outer-div', 'first-ol', 'first-li', 'paragraph', 'p-em')),
            array('*:contains("E")', array()),  // case-sensitive
            array('.a', array('first-ol')),
            array('.b', array('first-ol')),
            array('*.a', array('first-ol')),
            array('ol.a', array('first-ol')),
            array('.c', array('first-ol', 'third-li', 'fourth-li')),
            array('*.c', array('first-ol', 'third-li', 'fourth-li')),
            array('ol *.c', array('third-li', 'fourth-li')),
            array('ol li.c', array('third-li', 'fourth-li')),
            array('li ~ li.c', array('third-li', 'fourth-li')),
            array('ol > li.c', array('third-li', 'fourth-li')),
            array('#first-li', array('first-li')),
            array('li#first-li', array('first-li')),
            array('*#first-li', array('first-li')),
            array('li div', array('li-div')),
            array('li > div', array('li-div')),
            array('div div', array('li-div')),
            array('div > div', array()),
            array('div>.c', array('first-ol')),
            array('div > .c', array('first-ol')),
            array('div + div', array('foobar-div')),
            array('a ~ a', array('tag-anchor', 'nofollow-anchor')),
            array('a[rel="tag"] ~ a', array('nofollow-anchor')),
            array('ol#first-ol li:last-child', array('seventh-li')),
            array('ol#first-ol *:last-child', array('li-div', 'seventh-li')),
            array('#outer-div:first-child', array('outer-div')),
            array('#outer-div :first-child', array('name-anchor', 'first-li', 'li-div', 'p-b', 'checkbox-fieldset-disabled', 'area-href')),
            array('a[href]', array('tag-anchor', 'nofollow-anchor')),
            array(':not(*)', array()),
            array('a:not([href])', array('name-anchor')),
            array('ol :Not(li[class])', array('first-li', 'second-li', 'li-div', 'fifth-li', 'sixth-li', 'seventh-li')),
            // HTML-specific
            array(':link', array('link-href', 'tag-anchor', 'nofollow-anchor', 'area-href')),
            array(':visited', array()),
            array(':enabled', array('link-href', 'tag-anchor', 'nofollow-anchor', 'checkbox-unchecked', 'text-checked', 'checkbox-checked', 'area-href')),
            array(':disabled', array('checkbox-disabled', 'checkbox-disabled-checked', 'fieldset', 'checkbox-fieldset-disabled')),
            array(':checked', array('checkbox-checked', 'checkbox-disabled-checked')),
        );
    }

    public function getHtmlShakespearTestData()
    {
        return array(
            array('*', 246),
            array('div:contains(CELIA)', 26),
            array('div:only-child', 22), // ?
            array('div:nth-child(even)', 106),
            array('div:nth-child(2n)', 106),
            array('div:nth-child(odd)', 137),
            array('div:nth-child(2n+1)', 137),
            array('div:nth-child(n)', 243),
            array('div:last-child', 53),
            array('div:first-child', 51),
            array('div > div', 242),
            array('div + div', 190),
            array('div ~ div', 190),
            array('body', 1),
            array('body div', 243),
            array('div', 243),
            array('div div', 242),
            array('div div div', 241),
            array('div, div, div', 243),
            array('div, a, span', 243),
            array('.dialog', 51),
            array('div.dialog', 51),
            array('div .dialog', 51),
            array('div.character, div.dialog', 99),
            array('div.direction.dialog', 0),
            array('div.dialog.direction', 0),
            array('div.dialog.scene', 1),
            array('div.scene.scene', 1),
            array('div.scene .scene', 0),
            array('div.direction .dialog ', 0),
            array('div .dialog .direction', 4),
            array('div.dialog .dialog .direction', 4),
            array('#speech5', 1),
            array('div#speech5', 1),
            array('div #speech5', 1),
            array('div.scene div.dialog', 49),
            array('div#scene1 div.dialog div', 142),
            array('#scene1 #speech1', 1),
            array('div[class]', 103),
            array('div[class=dialog]', 50),
            array('div[class^=dia]', 51),
            array('div[class$=log]', 50),
            array('div[class*=sce]', 1),
            array('div[class|=dialog]', 50), // ? Seems right
            array('div[class!=madeup]', 243), // ? Seems right
            array('div[class~=dialog]', 51), // ? Seems right
        );
    }
}
PK��Zo,q��Mtest/CssSelector/Symfony/Component/CssSelector/Tests/Node/ElementNodeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Tests\Node;

use Symfony\Component\CssSelector\Node\ElementNode;

class ElementNodeTest extends AbstractNodeTest
{
    public function getToStringConversionTestData()
    {
        return array(
            array(new ElementNode(), 'Element[*]'),
            array(new ElementNode(null, 'element'), 'Element[element]'),
            array(new ElementNode('namespace', 'element'), 'Element[namespace|element]'),
        );
    }

    public function getSpecificityValueTestData()
    {
        return array(
            array(new ElementNode(), 0),
            array(new ElementNode(null, 'element'), 1),
            array(new ElementNode('namespace', 'element'),1),
        );
    }
}
PK��Z�BնVVJtest/CssSelector/Symfony/Component/CssSelector/Tests/Node/HashNodeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Tests\Node;

use Symfony\Component\CssSelector\Node\HashNode;
use Symfony\Component\CssSelector\Node\ElementNode;

class HashNodeTest extends AbstractNodeTest
{
    public function getToStringConversionTestData()
    {
        return array(
            array(new HashNode(new ElementNode(), 'id'), 'Hash[Element[*]#id]'),
        );
    }

    public function getSpecificityValueTestData()
    {
        return array(
            array(new HashNode(new ElementNode(), 'id'), 100),
            array(new HashNode(new ElementNode(null, 'id'), 'class'), 101),
        );
    }
}
PK��ZV=��hhKtest/CssSelector/Symfony/Component/CssSelector/Tests/Node/ClassNodeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Tests\Node;

use Symfony\Component\CssSelector\Node\ClassNode;
use Symfony\Component\CssSelector\Node\ElementNode;

class ClassNodeTest extends AbstractNodeTest
{
    public function getToStringConversionTestData()
    {
        return array(
            array(new ClassNode(new ElementNode(), 'class'), 'Class[Element[*].class]'),
        );
    }

    public function getSpecificityValueTestData()
    {
        return array(
            array(new ClassNode(new ElementNode(), 'class'), 10),
            array(new ClassNode(new ElementNode(null, 'element'), 'class'), 11),
        );
    }
}
PK��Zg$i���Ntest/CssSelector/Symfony/Component/CssSelector/Tests/Node/NegationNodeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Tests\Node;

use Symfony\Component\CssSelector\Node\ClassNode;
use Symfony\Component\CssSelector\Node\NegationNode;
use Symfony\Component\CssSelector\Node\ElementNode;

class NegationNodeTest extends AbstractNodeTest
{
    public function getToStringConversionTestData()
    {
        return array(
            array(new NegationNode(new ElementNode(), new ClassNode(new ElementNode(), 'class')), 'Negation[Element[*]:not(Class[Element[*].class])]'),
        );
    }

    public function getSpecificityValueTestData()
    {
        return array(
            array(new NegationNode(new ElementNode(), new ClassNode(new ElementNode(), 'class')), 10),
        );
    }
}
PK��Zj�
��Vtest/CssSelector/Symfony/Component/CssSelector/Tests/Node/CombinedSelectorNodeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Tests\Node;

use Symfony\Component\CssSelector\Node\CombinedSelectorNode;
use Symfony\Component\CssSelector\Node\ElementNode;

class CombinedSelectorNodeTest extends AbstractNodeTest
{
    public function getToStringConversionTestData()
    {
        return array(
            array(new CombinedSelectorNode(new ElementNode(), '>', new ElementNode()), 'CombinedSelector[Element[*] > Element[*]]'),
            array(new CombinedSelectorNode(new ElementNode(), ' ', new ElementNode()), 'CombinedSelector[Element[*] <followed> Element[*]]'),
        );
    }

    public function getSpecificityValueTestData()
    {
        return array(
            array(new CombinedSelectorNode(new ElementNode(), '>', new ElementNode()), 0),
            array(new CombinedSelectorNode(new ElementNode(null, 'element'), '>', new ElementNode()), 1),
            array(new CombinedSelectorNode(new ElementNode(null, 'element'), '>', new ElementNode(null, 'element')), 2),
        );
    }
}
PK��Z�(yآ�Ntest/CssSelector/Symfony/Component/CssSelector/Tests/Node/FunctionNodeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Tests\Node;

use Symfony\Component\CssSelector\Node\ElementNode;
use Symfony\Component\CssSelector\Node\FunctionNode;
use Symfony\Component\CssSelector\Parser\Token;

class FunctionNodeTest extends AbstractNodeTest
{
    public function getToStringConversionTestData()
    {
        return array(
            array(new FunctionNode(new ElementNode(), 'function'), 'Function[Element[*]:function()]'),
            array(new FunctionNode(new ElementNode(), 'function', array(
                new Token(Token::TYPE_IDENTIFIER, 'value', 0),
            )), "Function[Element[*]:function(['value'])]"),
            array(new FunctionNode(new ElementNode(), 'function', array(
                new Token(Token::TYPE_STRING, 'value1', 0),
                new Token(Token::TYPE_NUMBER, 'value2', 0),
            )), "Function[Element[*]:function(['value1', 'value2'])]"),
        );
    }

    public function getSpecificityValueTestData()
    {
        return array(
            array(new FunctionNode(new ElementNode(), 'function'), 10),
            array(new FunctionNode(new ElementNode(), 'function', array(
                new Token(Token::TYPE_IDENTIFIER, 'value', 0),
            )), 10),
            array(new FunctionNode(new ElementNode(), 'function', array(
                new Token(Token::TYPE_STRING, 'value1', 0),
                new Token(Token::TYPE_NUMBER, 'value2', 0),
            )), 10),
        );
    }
}
PK��Z�Y���Ntest/CssSelector/Symfony/Component/CssSelector/Tests/Node/AbstractNodeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Tests\Node;

use Symfony\Component\CssSelector\Node\NodeInterface;

abstract class AbstractNodeTest extends \PHPUnit_Framework_TestCase
{
    /** @dataProvider getToStringConversionTestData */
    public function testToStringConversion(NodeInterface $node, $representation)
    {
        $this->assertEquals($representation, (string) $node);
    }

    /** @dataProvider getSpecificityValueTestData */
    public function testSpecificityValue(NodeInterface $node, $value)
    {
        $this->assertEquals($value, $node->getSpecificity()->getValue());
    }

    abstract public function getToStringConversionTestData();
    abstract public function getSpecificityValueTestData();
}
PK��Z_�Ӵ�Ntest/CssSelector/Symfony/Component/CssSelector/Tests/Node/SelectorNodeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Tests\Node;

use Symfony\Component\CssSelector\Node\ElementNode;
use Symfony\Component\CssSelector\Node\SelectorNode;

class SelectorNodeTest extends AbstractNodeTest
{
    public function getToStringConversionTestData()
    {
        return array(
            array(new SelectorNode(new ElementNode()), 'Selector[Element[*]]'),
            array(new SelectorNode(new ElementNode(), 'pseudo'), 'Selector[Element[*]::pseudo]'),
        );
    }

    public function getSpecificityValueTestData()
    {
        return array(
            array(new SelectorNode(new ElementNode()), 0),
            array(new SelectorNode(new ElementNode(), 'pseudo'), 1),
        );
    }
}
PK��Z���uuMtest/CssSelector/Symfony/Component/CssSelector/Tests/Node/SpecificityTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Tests\Node;

use Symfony\Component\CssSelector\Node\Specificity;

class SpecificityTest extends \PHPUnit_Framework_TestCase
{
    /** @dataProvider getValueTestData */
    public function testValue(Specificity $specificity, $value)
    {
        $this->assertEquals($value, $specificity->getValue());
    }

    /** @dataProvider getValueTestData */
    public function testPlusValue(Specificity $specificity, $value)
    {
        $this->assertEquals($value + 123, $specificity->plus(new Specificity(1, 2, 3))->getValue());
    }

    public function getValueTestData()
    {
        return array(
            array(new Specificity(0, 0, 0), 0),
            array(new Specificity(0, 0, 2), 2),
            array(new Specificity(0, 3, 0), 30),
            array(new Specificity(4, 0, 0), 400),
            array(new Specificity(4, 3, 2), 432),
        );
    }
}
PK��Z� _ӽ�Otest/CssSelector/Symfony/Component/CssSelector/Tests/Node/AttributeNodeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Tests\Node;

use Symfony\Component\CssSelector\Node\AttributeNode;
use Symfony\Component\CssSelector\Node\ElementNode;

class AttributeNodeTest extends AbstractNodeTest
{
    public function getToStringConversionTestData()
    {
        return array(
            array(new AttributeNode(new ElementNode(), null, 'attribute', 'exists', null), 'Attribute[Element[*][attribute]]'),
            array(new AttributeNode(new ElementNode(), null, 'attribute', '$=', 'value'), "Attribute[Element[*][attribute $= 'value']]"),
            array(new AttributeNode(new ElementNode(), 'namespace', 'attribute', '$=', 'value'), "Attribute[Element[*][namespace|attribute $= 'value']]"),
        );
    }

    public function getSpecificityValueTestData()
    {
        return array(
            array(new AttributeNode(new ElementNode(), null, 'attribute', 'exists', null), 10),
            array(new AttributeNode(new ElementNode(null, 'element'), null, 'attribute', 'exists', null), 11),
            array(new AttributeNode(new ElementNode(), null, 'attribute', '$=', 'value'), 10),
            array(new AttributeNode(new ElementNode(), 'namespace', 'attribute', '$=', 'value'), 10),
        );
    }
}
PK��Z�WDLtest/CssSelector/Symfony/Component/CssSelector/Tests/Node/PseudoNodeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Tests\Node;

use Symfony\Component\CssSelector\Node\ElementNode;
use Symfony\Component\CssSelector\Node\PseudoNode;

class PseudoNodeTest extends AbstractNodeTest
{
    public function getToStringConversionTestData()
    {
        return array(
            array(new PseudoNode(new ElementNode(), 'pseudo'), 'Pseudo[Element[*]:pseudo]'),
        );
    }

    public function getSpecificityValueTestData()
    {
        return array(
            array(new PseudoNode(new ElementNode(), 'pseudo'), 10),
        );
    }
}
PK��Z�/D�Htest/CssSelector/Symfony/Component/CssSelector/Tests/CssSelectorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Tests;

use Symfony\Component\CssSelector\CssSelector;

class CssSelectorTest extends \PHPUnit_Framework_TestCase
{
    public function testCssToXPath()
    {
        $this->assertEquals('descendant-or-self::*', CssSelector::toXPath(''));
        $this->assertEquals('descendant-or-self::h1', CssSelector::toXPath('h1'));
        $this->assertEquals("descendant-or-self::h1[@id = 'foo']", CssSelector::toXPath('h1#foo'));
        $this->assertEquals("descendant-or-self::h1[@class and contains(concat(' ', normalize-space(@class), ' '), ' foo ')]", CssSelector::toXPath('h1.foo'));
        $this->assertEquals('descendant-or-self::foo:h1', CssSelector::toXPath('foo|h1'));
    }

    /** @dataProvider getCssToXPathWithoutPrefixTestData */
    public function testCssToXPathWithoutPrefix($css, $xpath)
    {
        $this->assertEquals($xpath, CssSelector::toXPath($css, ''), '->parse() parses an input string and returns a node');
    }

    public function testParseExceptions()
    {
        try {
            CssSelector::toXPath('h1:');
            $this->fail('->parse() throws an Exception if the css selector is not valid');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\Symfony\Component\CssSelector\Exception\ParseException', $e, '->parse() throws an Exception if the css selector is not valid');
            $this->assertEquals("Expected identifier, but <eof at 3> found.", $e->getMessage(), '->parse() throws an Exception if the css selector is not valid');
        }
    }

    public function getCssToXPathWithoutPrefixTestData()
    {
        return array(
            array('h1', "h1"),
            array('foo|h1', "foo:h1"),
            array('h1, h2, h3', "h1 | h2 | h3"),
            array('h1:nth-child(3n+1)', "*/*[name() = 'h1' and (position() - 1 >= 0 and (position() - 1) mod 3 = 0)]"),
            array('h1 > p', "h1/p"),
            array('h1#foo', "h1[@id = 'foo']"),
            array('h1.foo', "h1[@class and contains(concat(' ', normalize-space(@class), ' '), ' foo ')]"),
            array('h1[class*="foo bar"]', "h1[@class and contains(@class, 'foo bar')]"),
            array('h1[foo|class*="foo bar"]', "h1[@foo:class and contains(@foo:class, 'foo bar')]"),
            array('h1[class]', "h1[@class]"),
            array('h1 .foo', "h1/descendant-or-self::*/*[@class and contains(concat(' ', normalize-space(@class), ' '), ' foo ')]"),
            array('h1 #foo', "h1/descendant-or-self::*/*[@id = 'foo']"),
            array('h1 [class*=foo]', "h1/descendant-or-self::*/*[@class and contains(@class, 'foo')]"),
            array('div>.foo', "div/*[@class and contains(concat(' ', normalize-space(@class), ' '), ' foo ')]"),
            array('div > .foo', "div/*[@class and contains(concat(' ', normalize-space(@class), ' '), ' foo ')]"),
        );
    }
}
PK��Z�u̱��Ztest/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Shortcut/ElementParserTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Tests\Parser\Shortcut;

use Symfony\Component\CssSelector\Node\SelectorNode;
use Symfony\Component\CssSelector\Parser\Shortcut\ElementParser;

/**
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class ElementParserTest extends \PHPUnit_Framework_TestCase
{
    /** @dataProvider getParseTestData */
    public function testParse($source, $representation)
    {
        $parser = new ElementParser();
        $selectors = $parser->parse($source);
        $this->assertCount(1, $selectors);

        /** @var SelectorNode $selector */
        $selector = $selectors[0];
        $this->assertEquals($representation, (string) $selector->getTree());
    }

    public function getParseTestData()
    {
        return array(
            array('*', 'Element[*]'),
            array('testel', 'Element[testel]'),
            array('testns|*', 'Element[testns|*]'),
            array('testns|testel', 'Element[testns|testel]'),
        );
    }
}
PK��Z[�nы�Xtest/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Shortcut/ClassParserTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Tests\Parser\Shortcut;

use Symfony\Component\CssSelector\Node\SelectorNode;
use Symfony\Component\CssSelector\Parser\Shortcut\ClassParser;

/**
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class ClassParserTest extends \PHPUnit_Framework_TestCase
{
    /** @dataProvider getParseTestData */
    public function testParse($source, $representation)
    {
        $parser = new ClassParser();
        $selectors = $parser->parse($source);
        $this->assertCount(1, $selectors);

        /** @var SelectorNode $selector */
        $selector = $selectors[0];
        $this->assertEquals($representation, (string) $selector->getTree());
    }

    public function getParseTestData()
    {
        return array(
            array('.testclass', 'Class[Element[*].testclass]'),
            array('testel.testclass', 'Class[Element[testel].testclass]'),
            array('testns|.testclass', 'Class[Element[testns|*].testclass]'),
            array('testns|*.testclass', 'Class[Element[testns|*].testclass]'),
            array('testns|testel.testclass', 'Class[Element[testns|testel].testclass]'),
        );
    }
}
PK��Z>�]��^test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Shortcut/EmptyStringParserTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Tests\Parser\Shortcut;

use Symfony\Component\CssSelector\Node\SelectorNode;
use Symfony\Component\CssSelector\Parser\Shortcut\EmptyStringParser;

/**
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class EmptyStringParserTest extends \PHPUnit_Framework_TestCase
{
    public function testParse()
    {
        $parser = new EmptyStringParser();
        $selectors = $parser->parse('');
        $this->assertCount(1, $selectors);

        /** @var SelectorNode $selector */
        $selector = $selectors[0];
        $this->assertEquals('Element[*]', (string) $selector->getTree());

        $selectors = $parser->parse('this will produce an empty array');
        $this->assertCount(0, $selectors);
    }
}
PK��Z[N�eeWtest/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Shortcut/HashParserTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Tests\Parser\Shortcut;

use Symfony\Component\CssSelector\Node\SelectorNode;
use Symfony\Component\CssSelector\Parser\Shortcut\HashParser;

/**
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class HashParserTest extends \PHPUnit_Framework_TestCase
{
    /** @dataProvider getParseTestData */
    public function testParse($source, $representation)
    {
        $parser = new HashParser();
        $selectors = $parser->parse($source);
        $this->assertCount(1, $selectors);

        /** @var SelectorNode $selector */
        $selector = $selectors[0];
        $this->assertEquals($representation, (string) $selector->getTree());
    }

    public function getParseTestData()
    {
        return array(
            array('#testid', 'Hash[Element[*]#testid]'),
            array('testel#testid', 'Hash[Element[testel]#testid]'),
            array('testns|#testid', 'Hash[Element[testns|*]#testid]'),
            array('testns|*#testid', 'Hash[Element[testns|*]#testid]'),
            array('testns|testel#testid', 'Hash[Element[testns|testel]#testid]'),
        );
    }
}
PK��Z^���2�2Jtest/CssSelector/Symfony/Component/CssSelector/Tests/Parser/ParserTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Tests\Parser;

use Symfony\Component\CssSelector\Exception\SyntaxErrorException;
use Symfony\Component\CssSelector\Node\FunctionNode;
use Symfony\Component\CssSelector\Node\SelectorNode;
use Symfony\Component\CssSelector\Parser\Parser;
use Symfony\Component\CssSelector\Parser\Token;

class ParserTest extends \PHPUnit_Framework_TestCase
{
    /** @dataProvider getParserTestData */
    public function testParser($source, $representation)
    {
        $parser = new Parser();

        $this->assertEquals($representation, array_map(function (SelectorNode $node) {
            return (string) $node->getTree();
        }, $parser->parse($source)));
    }

    /** @dataProvider getParserExceptionTestData */
    public function testParserException($source, $message)
    {
        $parser = new Parser();

        try {
            $parser->parse($source);
            $this->fail('Parser should throw a SyntaxErrorException.');
        } catch (SyntaxErrorException $e) {
            $this->assertEquals($message, $e->getMessage());
        }
    }

    /** @dataProvider getPseudoElementsTestData */
    public function testPseudoElements($source, $element, $pseudo)
    {
        $parser = new Parser();
        $selectors = $parser->parse($source);
        $this->assertCount(1, $selectors);

        /** @var SelectorNode $selector */
        $selector = $selectors[0];
        $this->assertEquals($element, (string) $selector->getTree());
        $this->assertEquals($pseudo, (string) $selector->getPseudoElement());
    }

    /** @dataProvider getSpecificityTestData */
    public function testSpecificity($source, $value)
    {
        $parser = new Parser();
        $selectors = $parser->parse($source);
        $this->assertCount(1, $selectors);

        /** @var SelectorNode $selector */
        $selector = $selectors[0];
        $this->assertEquals($value, $selector->getSpecificity()->getValue());
    }

    /** @dataProvider getParseSeriesTestData */
    public function testParseSeries($series, $a, $b)
    {
        $parser = new Parser();
        $selectors = $parser->parse(sprintf(':nth-child(%s)', $series));
        $this->assertCount(1, $selectors);

        /** @var FunctionNode $function */
        $function = $selectors[0]->getTree();
        $this->assertEquals(array($a, $b), Parser::parseSeries($function->getArguments()));
    }

    /** @dataProvider getParseSeriesExceptionTestData */
    public function testParseSeriesException($series)
    {
        $parser = new Parser();
        $selectors = $parser->parse(sprintf(':nth-child(%s)', $series));
        $this->assertCount(1, $selectors);

        /** @var FunctionNode $function */
        $function = $selectors[0]->getTree();
        $this->setExpectedException('Symfony\Component\CssSelector\Exception\SyntaxErrorException');
        Parser::parseSeries($function->getArguments());
    }

    public function getParserTestData()
    {
        return array(
            array('*', array('Element[*]')),
            array('*|*', array('Element[*]')),
            array('*|foo', array('Element[foo]')),
            array('foo|*', array('Element[foo|*]')),
            array('foo|bar', array('Element[foo|bar]')),
            array('#foo#bar', array('Hash[Hash[Element[*]#foo]#bar]')),
            array('div>.foo', array('CombinedSelector[Element[div] > Class[Element[*].foo]]')),
            array('div> .foo', array('CombinedSelector[Element[div] > Class[Element[*].foo]]')),
            array('div >.foo', array('CombinedSelector[Element[div] > Class[Element[*].foo]]')),
            array('div > .foo', array('CombinedSelector[Element[div] > Class[Element[*].foo]]')),
            array("div \n>  \t \t .foo", array('CombinedSelector[Element[div] > Class[Element[*].foo]]')),
            array('td.foo,.bar', array('Class[Element[td].foo]', 'Class[Element[*].bar]')),
            array('td.foo, .bar', array('Class[Element[td].foo]', 'Class[Element[*].bar]')),
            array("td.foo\t\r\n\f ,\t\r\n\f .bar", array('Class[Element[td].foo]', 'Class[Element[*].bar]')),
            array('td.foo,.bar', array('Class[Element[td].foo]', 'Class[Element[*].bar]')),
            array('td.foo, .bar', array('Class[Element[td].foo]', 'Class[Element[*].bar]')),
            array("td.foo\t\r\n\f ,\t\r\n\f .bar", array('Class[Element[td].foo]', 'Class[Element[*].bar]')),
            array('div, td.foo, div.bar span', array('Element[div]', 'Class[Element[td].foo]', 'CombinedSelector[Class[Element[div].bar] <followed> Element[span]]')),
            array('div > p', array('CombinedSelector[Element[div] > Element[p]]')),
            array('td:first', array('Pseudo[Element[td]:first]')),
            array('td :first', array('CombinedSelector[Element[td] <followed> Pseudo[Element[*]:first]]')),
            array('a[name]', array('Attribute[Element[a][name]]')),
            array("a[ name\t]", array('Attribute[Element[a][name]]')),
            array('a [name]', array('CombinedSelector[Element[a] <followed> Attribute[Element[*][name]]]')),
            array('a[rel="include"]', array("Attribute[Element[a][rel = 'include']]")),
            array('a[rel = include]', array("Attribute[Element[a][rel = 'include']]")),
            array("a[hreflang |= 'en']", array("Attribute[Element[a][hreflang |= 'en']]")),
            array('a[hreflang|=en]', array("Attribute[Element[a][hreflang |= 'en']]")),
            array('div:nth-child(10)', array("Function[Element[div]:nth-child(['10'])]")),
            array(':nth-child(2n+2)', array("Function[Element[*]:nth-child(['2', 'n', '+2'])]")),
            array('div:nth-of-type(10)', array("Function[Element[div]:nth-of-type(['10'])]")),
            array('div div:nth-of-type(10) .aclass', array("CombinedSelector[CombinedSelector[Element[div] <followed> Function[Element[div]:nth-of-type(['10'])]] <followed> Class[Element[*].aclass]]")),
            array('label:only', array('Pseudo[Element[label]:only]')),
            array('a:lang(fr)', array("Function[Element[a]:lang(['fr'])]")),
            array('div:contains("foo")', array("Function[Element[div]:contains(['foo'])]")),
            array('div#foobar', array('Hash[Element[div]#foobar]')),
            array('div:not(div.foo)', array('Negation[Element[div]:not(Class[Element[div].foo])]')),
            array('td ~ th', array('CombinedSelector[Element[td] ~ Element[th]]')),
            array('.foo[data-bar][data-baz=0]', array("Attribute[Attribute[Class[Element[*].foo][data-bar]][data-baz = '0']]")),
        );
    }

    public function getParserExceptionTestData()
    {
        return array(
            array('attributes(href)/html/body/a', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, '(', 10))->getMessage()),
            array('attributes(href)', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, '(', 10))->getMessage()),
            array('html/body/a', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, '/', 4))->getMessage()),
            array(' ', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_FILE_END, '', 1))->getMessage()),
            array('div, ', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_FILE_END, '', 5))->getMessage()),
            array(' , div', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, ',', 1))->getMessage()),
            array('p, , div', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, ',', 3))->getMessage()),
            array('div > ', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_FILE_END, '', 6))->getMessage()),
            array('  > div', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, '>', 2))->getMessage()),
            array('foo|#bar', SyntaxErrorException::unexpectedToken('identifier or "*"', new Token(Token::TYPE_HASH, 'bar', 4))->getMessage()),
            array('#.foo', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, '#', 0))->getMessage()),
            array('.#foo', SyntaxErrorException::unexpectedToken('identifier', new Token(Token::TYPE_HASH, 'foo', 1))->getMessage()),
            array(':#foo', SyntaxErrorException::unexpectedToken('identifier', new Token(Token::TYPE_HASH, 'foo', 1))->getMessage()),
            array('[*]', SyntaxErrorException::unexpectedToken('"|"', new Token(Token::TYPE_DELIMITER, ']', 2))->getMessage()),
            array('[foo|]', SyntaxErrorException::unexpectedToken('identifier', new Token(Token::TYPE_DELIMITER, ']', 5))->getMessage()),
            array('[#]', SyntaxErrorException::unexpectedToken('identifier or "*"', new Token(Token::TYPE_DELIMITER, '#', 1))->getMessage()),
            array('[foo=#]', SyntaxErrorException::unexpectedToken('string or identifier', new Token(Token::TYPE_DELIMITER, '#', 5))->getMessage()),
            array(':nth-child()', SyntaxErrorException::unexpectedToken('at least one argument', new Token(Token::TYPE_DELIMITER, ')', 11))->getMessage()),
            array('[href]a', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_IDENTIFIER, 'a', 6))->getMessage()),
            array('[rel:stylesheet]', SyntaxErrorException::unexpectedToken('operator', new Token(Token::TYPE_DELIMITER, ':', 4))->getMessage()),
            array('[rel=stylesheet', SyntaxErrorException::unexpectedToken('"]"', new Token(Token::TYPE_FILE_END, '', 15))->getMessage()),
            array(':lang(fr', SyntaxErrorException::unexpectedToken('an argument', new Token(Token::TYPE_FILE_END, '', 8))->getMessage()),
            array(':contains("foo', SyntaxErrorException::unclosedString(10)->getMessage()),
            array('foo!', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, '!', 3))->getMessage()),
        );
    }

    public function getPseudoElementsTestData()
    {
        return array(
            array('foo', 'Element[foo]', ''),
            array('*', 'Element[*]', ''),
            array(':empty', 'Pseudo[Element[*]:empty]', ''),
            array(':BEfore', 'Element[*]', 'before'),
            array(':aftER', 'Element[*]', 'after'),
            array(':First-Line', 'Element[*]', 'first-line'),
            array(':First-Letter', 'Element[*]', 'first-letter'),
            array('::befoRE', 'Element[*]', 'before'),
            array('::AFter', 'Element[*]', 'after'),
            array('::firsT-linE', 'Element[*]', 'first-line'),
            array('::firsT-letteR', 'Element[*]', 'first-letter'),
            array('::Selection', 'Element[*]', 'selection'),
            array('foo:after', 'Element[foo]', 'after'),
            array('foo::selection', 'Element[foo]', 'selection'),
            array('lorem#ipsum ~ a#b.c[href]:empty::selection', 'CombinedSelector[Hash[Element[lorem]#ipsum] ~ Pseudo[Attribute[Class[Hash[Element[a]#b].c][href]]:empty]]', 'selection'),
        );
    }

    public function getSpecificityTestData()
    {
        return array(
            array('*', 0),
            array(' foo', 1),
            array(':empty ', 10),
            array(':before', 1),
            array('*:before', 1),
            array(':nth-child(2)', 10),
            array('.bar', 10),
            array('[baz]', 10),
            array('[baz="4"]', 10),
            array('[baz^="4"]', 10),
            array('#lipsum', 100),
            array(':not(*)', 0),
            array(':not(foo)', 1),
            array(':not(.foo)', 10),
            array(':not([foo])', 10),
            array(':not(:empty)', 10),
            array(':not(#foo)', 100),
            array('foo:empty', 11),
            array('foo:before', 2),
            array('foo::before', 2),
            array('foo:empty::before', 12),
            array('#lorem + foo#ipsum:first-child > bar:first-line', 213),
        );
    }

    public function getParseSeriesTestData()
    {
        return array(
            array('1n+3', 1, 3),
            array('1n +3', 1, 3),
            array('1n + 3', 1, 3),
            array('1n+ 3', 1, 3),
            array('1n-3', 1, -3),
            array('1n -3', 1, -3),
            array('1n - 3', 1, -3),
            array('1n- 3', 1, -3),
            array('n-5', 1, -5),
            array('odd', 2, 1),
            array('even', 2, 0),
            array('3n', 3, 0),
            array('n', 1, 0),
            array('+n', 1, 0),
            array('-n', -1, 0),
            array('5', 0, 5),
        );
    }

    public function getParseSeriesExceptionTestData()
    {
        return array(
            array('foo'),
            array('n+'),
        );
    }
}
PK��Z+��̭�Ytest/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/NumberHandlerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Tests\Parser\Handler;

use Symfony\Component\CssSelector\Parser\Handler\NumberHandler;
use Symfony\Component\CssSelector\Parser\Token;
use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns;

class NumberHandlerTest extends AbstractHandlerTest
{
    public function getHandleValueTestData()
    {
        return array(
            array('12', new Token(Token::TYPE_NUMBER, '12', 0), ''),
            array('12.34', new Token(Token::TYPE_NUMBER, '12.34', 0), ''),
            array('+12.34', new Token(Token::TYPE_NUMBER, '+12.34', 0), ''),
            array('-12.34', new Token(Token::TYPE_NUMBER, '-12.34', 0), ''),

            array('12 arg', new Token(Token::TYPE_NUMBER, '12', 0), ' arg'),
            array('12]', new Token(Token::TYPE_NUMBER, '12', 0), ']'),
        );
    }

    public function getDontHandleValueTestData()
    {
        return array(
            array('hello'),
            array('>'),
            array('+'),
            array(' '),
            array('/* comment */'),
        );
    }

    protected function generateHandler()
    {
        $patterns = new TokenizerPatterns();

        return new NumberHandler($patterns);
    }
}
PK��Z��˶]test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/IdentifierHandlerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Tests\Parser\Handler;

use Symfony\Component\CssSelector\Parser\Handler\IdentifierHandler;
use Symfony\Component\CssSelector\Parser\Token;
use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns;
use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerEscaping;

class IdentifierHandlerTest extends AbstractHandlerTest
{
    public function getHandleValueTestData()
    {
        return array(
            array('foo', new Token(Token::TYPE_IDENTIFIER, 'foo', 0), ''),
            array('foo|bar', new Token(Token::TYPE_IDENTIFIER, 'foo', 0), '|bar'),
            array('foo.class', new Token(Token::TYPE_IDENTIFIER, 'foo', 0), '.class'),
            array('foo[attr]', new Token(Token::TYPE_IDENTIFIER, 'foo', 0), '[attr]'),
            array('foo bar', new Token(Token::TYPE_IDENTIFIER, 'foo', 0), ' bar'),
        );
    }

    public function getDontHandleValueTestData()
    {
        return array(
            array('>'),
            array('+'),
            array(' '),
            array('*|foo'),
            array('/* comment */'),
        );
    }

    protected function generateHandler()
    {
        $patterns = new TokenizerPatterns();

        return new IdentifierHandler($patterns, new TokenizerEscaping($patterns));
    }
}
PK��Z��_/RRZtest/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/CommentHandlerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Tests\Parser\Handler;

use Symfony\Component\CssSelector\Parser\Handler\CommentHandler;
use Symfony\Component\CssSelector\Parser\Reader;
use Symfony\Component\CssSelector\Parser\Token;
use Symfony\Component\CssSelector\Parser\TokenStream;

class CommentHandlerTest extends AbstractHandlerTest
{
    /** @dataProvider getHandleValueTestData */
    public function testHandleValue($value, Token $unusedArgument, $remainingContent)
    {
        $reader = new Reader($value);
        $stream = new TokenStream();

        $this->assertTrue($this->generateHandler()->handle($reader, $stream));
        // comments are ignored (not pushed as token in stream)
        $this->assertStreamEmpty($stream);
        $this->assertRemainingContent($reader, $remainingContent);
    }

    public function getHandleValueTestData()
    {
        return array(
            // 2nd argument only exists for inherited method compatibility
            array('/* comment */', new Token(null, null, null), ''),
            array('/* comment */foo', new Token(null, null, null), 'foo'),
        );
    }

    public function getDontHandleValueTestData()
    {
        return array(
            array('>'),
            array('+'),
            array(' '),
        );
    }

    protected function generateHandler()
    {
        return new CommentHandler();
    }
}
PK��ZĈ���[test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/AbstractHandlerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Tests\Parser\Handler;

use Symfony\Component\CssSelector\Parser\Reader;
use Symfony\Component\CssSelector\Parser\Token;
use Symfony\Component\CssSelector\Parser\TokenStream;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
abstract class AbstractHandlerTest extends \PHPUnit_Framework_TestCase
{
    /** @dataProvider getHandleValueTestData */
    public function testHandleValue($value, Token $expectedToken, $remainingContent)
    {
        $reader = new Reader($value);
        $stream = new TokenStream();

        $this->assertTrue($this->generateHandler()->handle($reader, $stream));
        $this->assertEquals($expectedToken, $stream->getNext());
        $this->assertRemainingContent($reader, $remainingContent);
    }

    /** @dataProvider getDontHandleValueTestData */
    public function testDontHandleValue($value)
    {
        $reader = new Reader($value);
        $stream = new TokenStream();

        $this->assertFalse($this->generateHandler()->handle($reader, $stream));
        $this->assertStreamEmpty($stream);
        $this->assertRemainingContent($reader, $value);
    }

    abstract public function getHandleValueTestData();
    abstract public function getDontHandleValueTestData();
    abstract protected function generateHandler();

    protected function assertStreamEmpty(TokenStream $stream)
    {
        $property = new \ReflectionProperty($stream, 'tokens');
        $property->setAccessible(true);

        $this->assertEquals(array(), $property->getValue($stream));
    }

    protected function assertRemainingContent(Reader $reader, $remainingContent)
    {
        if ('' === $remainingContent) {
            $this->assertEquals(0, $reader->getRemainingLength());
            $this->assertTrue($reader->isEOF());
        } else {
            $this->assertEquals(strlen($remainingContent), $reader->getRemainingLength());
            $this->assertEquals(0, $reader->getOffset($remainingContent));
        }
    }
}
PK��Z ���]test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/WhitespaceHandlerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Tests\Parser\Handler;

use Symfony\Component\CssSelector\Parser\Handler\WhitespaceHandler;
use Symfony\Component\CssSelector\Parser\Token;

class WhitespaceHandlerTest extends AbstractHandlerTest
{
    public function getHandleValueTestData()
    {
        return array(
            array(' ', new Token(Token::TYPE_WHITESPACE, ' ', 0), ''),
            array("\n", new Token(Token::TYPE_WHITESPACE, "\n", 0), ''),
            array("\t", new Token(Token::TYPE_WHITESPACE, "\t", 0), ''),

            array(' foo', new Token(Token::TYPE_WHITESPACE, ' ', 0), 'foo'),
            array(' .foo', new Token(Token::TYPE_WHITESPACE, ' ', 0), '.foo'),
        );
    }

    public function getDontHandleValueTestData()
    {
        return array(
            array('>'),
            array('1'),
            array('a'),
        );
    }

    protected function generateHandler()
    {
        return new WhitespaceHandler();
    }
}
PK��Z�쓱��Ytest/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/StringHandlerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Tests\Parser\Handler;

use Symfony\Component\CssSelector\Parser\Handler\StringHandler;
use Symfony\Component\CssSelector\Parser\Token;
use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns;
use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerEscaping;

class StringHandlerTest extends AbstractHandlerTest
{
    public function getHandleValueTestData()
    {
        return array(
            array('"hello"', new Token(Token::TYPE_STRING, 'hello', 1), ''),
            array('"1"', new Token(Token::TYPE_STRING, '1', 1), ''),
            array('" "', new Token(Token::TYPE_STRING, ' ', 1), ''),
            array('""', new Token(Token::TYPE_STRING, '', 1), ''),
            array("'hello'", new Token(Token::TYPE_STRING, 'hello', 1), ''),

            array("'foo'bar", new Token(Token::TYPE_STRING, 'foo', 1), 'bar'),
        );
    }

    public function getDontHandleValueTestData()
    {
        return array(
            array('hello'),
            array('>'),
            array('1'),
            array(' '),
        );
    }

    protected function generateHandler()
    {
        $patterns = new TokenizerPatterns();

        return new StringHandler($patterns, new TokenizerEscaping($patterns));
    }
}
PK��ZC�U�rrWtest/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/HashHandlerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Tests\Parser\Handler;

use Symfony\Component\CssSelector\Parser\Handler\HashHandler;
use Symfony\Component\CssSelector\Parser\Token;
use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns;
use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerEscaping;

class HashHandlerTest extends AbstractHandlerTest
{
    public function getHandleValueTestData()
    {
        return array(
            array('#id', new Token(Token::TYPE_HASH, 'id', 0), ''),
            array('#123', new Token(Token::TYPE_HASH, '123', 0), ''),

            array('#id.class', new Token(Token::TYPE_HASH, 'id', 0), '.class'),
            array('#id element', new Token(Token::TYPE_HASH, 'id', 0), ' element'),
        );
    }

    public function getDontHandleValueTestData()
    {
        return array(
            array('id'),
            array('123'),
            array('<'),
            array('<'),
            array('#'),
        );
    }

    protected function generateHandler()
    {
        $patterns = new TokenizerPatterns();

        return new HashHandler($patterns, new TokenizerEscaping($patterns));
    }
}
PK��Z%9�j~~Jtest/CssSelector/Symfony/Component/CssSelector/Tests/Parser/ReaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Tests\Parser;

use Symfony\Component\CssSelector\Parser\Reader;

class ReaderTest extends \PHPUnit_Framework_TestCase
{
    public function testIsEOF()
    {
        $reader = new Reader('');
        $this->assertTrue($reader->isEOF());

        $reader = new Reader('hello');
        $this->assertFalse($reader->isEOF());

        $this->assignPosition($reader, 2);
        $this->assertFalse($reader->isEOF());

        $this->assignPosition($reader, 5);
        $this->assertTrue($reader->isEOF());
    }

    public function testGetRemainingLength()
    {
        $reader = new Reader('hello');
        $this->assertEquals(5, $reader->getRemainingLength());

        $this->assignPosition($reader, 2);
        $this->assertEquals(3, $reader->getRemainingLength());

        $this->assignPosition($reader, 5);
        $this->assertEquals(0, $reader->getRemainingLength());
    }

    public function testGetSubstring()
    {
        $reader = new Reader('hello');
        $this->assertEquals('he', $reader->getSubstring(2));
        $this->assertEquals('el', $reader->getSubstring(2, 1));

        $this->assignPosition($reader, 2);
        $this->assertEquals('ll', $reader->getSubstring(2));
        $this->assertEquals('lo', $reader->getSubstring(2, 1));
    }

    public function testGetOffset()
    {
        $reader = new Reader('hello');
        $this->assertEquals(2, $reader->getOffset('ll'));
        $this->assertFalse($reader->getOffset('w'));

        $this->assignPosition($reader, 2);
        $this->assertEquals(0, $reader->getOffset('ll'));
        $this->assertFalse($reader->getOffset('he'));
    }

    public function testFindPattern()
    {
        $reader = new Reader('hello');

        $this->assertFalse($reader->findPattern('/world/'));
        $this->assertEquals(array('hello', 'h'), $reader->findPattern('/^([a-z]).*/'));

        $this->assignPosition($reader, 2);
        $this->assertFalse($reader->findPattern('/^h.*/'));
        $this->assertEquals(array('llo'), $reader->findPattern('/^llo$/'));
    }

    public function testMoveForward()
    {
        $reader = new Reader('hello');
        $this->assertEquals(0, $reader->getPosition());

        $reader->moveForward(2);
        $this->assertEquals(2, $reader->getPosition());
    }

    public function testToEnd()
    {
        $reader = new Reader('hello');
        $reader->moveToEnd();
        $this->assertTrue($reader->isEOF());
    }

    private function assignPosition(Reader $reader, $value)
    {
        $position = new \ReflectionProperty($reader, 'position');
        $position->setAccessible(true);
        $position->setValue($reader, $value);
    }
}
PK��Z�}��qqOtest/CssSelector/Symfony/Component/CssSelector/Tests/Parser/TokenStreamTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\CssSelector\Tests\Parser;

use Symfony\Component\CssSelector\Parser\Token;
use Symfony\Component\CssSelector\Parser\TokenStream;

class TokenStreamTest extends \PHPUnit_Framework_TestCase
{
    public function testGetNext()
    {
        $stream = new TokenStream();
        $stream->push($t1 = new Token(Token::TYPE_IDENTIFIER, 'h1', 0));
        $stream->push($t2 = new Token(Token::TYPE_DELIMITER, '.', 2));
        $stream->push($t3 = new Token(Token::TYPE_IDENTIFIER, 'title', 3));

        $this->assertSame($t1, $stream->getNext());
        $this->assertSame($t2, $stream->getNext());
        $this->assertSame($t3, $stream->getNext());
    }

    public function testGetPeek()
    {
        $stream = new TokenStream();
        $stream->push($t1 = new Token(Token::TYPE_IDENTIFIER, 'h1', 0));
        $stream->push($t2 = new Token(Token::TYPE_DELIMITER, '.', 2));
        $stream->push($t3 = new Token(Token::TYPE_IDENTIFIER, 'title', 3));

        $this->assertSame($t1, $stream->getPeek());
        $this->assertSame($t1, $stream->getNext());
        $this->assertSame($t2, $stream->getPeek());
        $this->assertSame($t2, $stream->getPeek());
        $this->assertSame($t2, $stream->getNext());
    }

    public function testGetNextIdentifier()
    {
        $stream = new TokenStream();
        $stream->push(new Token(Token::TYPE_IDENTIFIER, 'h1', 0));

        $this->assertEquals('h1', $stream->getNextIdentifier());
    }

    public function testFailToGetNextIdentifier()
    {
        $this->setExpectedException('Symfony\Component\CssSelector\Exception\SyntaxErrorException');

        $stream = new TokenStream();
        $stream->push(new Token(Token::TYPE_DELIMITER, '.', 2));
        $stream->getNextIdentifier();
    }

    public function testGetNextIdentifierOrStar()
    {
        $stream = new TokenStream();

        $stream->push(new Token(Token::TYPE_IDENTIFIER, 'h1', 0));
        $this->assertEquals('h1', $stream->getNextIdentifierOrStar());

        $stream->push(new Token(Token::TYPE_DELIMITER, '*', 0));
        $this->assertNull($stream->getNextIdentifierOrStar());
    }

    public function testFailToGetNextIdentifierOrStar()
    {
        $this->setExpectedException('Symfony\Component\CssSelector\Exception\SyntaxErrorException');

        $stream = new TokenStream();
        $stream->push(new Token(Token::TYPE_DELIMITER, '.', 2));
        $stream->getNextIdentifierOrStar();
    }

    public function testSkipWhitespace()
    {
        $stream = new TokenStream();
        $stream->push($t1 = new Token(Token::TYPE_IDENTIFIER, 'h1', 0));
        $stream->push($t2 = new Token(Token::TYPE_WHITESPACE, ' ', 2));
        $stream->push($t3 = new Token(Token::TYPE_IDENTIFIER, 'h1', 3));

        $stream->skipWhitespace();
        $this->assertSame($t1, $stream->getNext());

        $stream->skipWhitespace();
        $this->assertSame($t3, $stream->getNext());
    }
}
PK��Z���Hmm?test/CssSelector/Symfony/Component/CssSelector/phpunit.xml.distnu�[���<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony CssSelector Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./Resources</directory>
                <directory>./Tests</directory>
                <directory>./vendor</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
PK��Z�X,�/�/Ttest/EventDispatcher/Symfony/Component/EventDispatcher/Tests/EventDispatcherTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\EventDispatcher\Tests;

use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class EventDispatcherTest extends \PHPUnit_Framework_TestCase
{
    /* Some pseudo events */
    const preFoo = 'pre.foo';
    const postFoo = 'post.foo';
    const preBar = 'pre.bar';
    const postBar = 'post.bar';

    /**
     * @var EventDispatcher
     */
    private $dispatcher;

    private $listener;

    protected function setUp()
    {
        $this->dispatcher = new EventDispatcher();
        $this->listener = new TestEventListener();
    }

    protected function tearDown()
    {
        $this->dispatcher = null;
        $this->listener = null;
    }

    public function testInitialState()
    {
        $this->assertEquals(array(), $this->dispatcher->getListeners());
        $this->assertFalse($this->dispatcher->hasListeners(self::preFoo));
        $this->assertFalse($this->dispatcher->hasListeners(self::postFoo));
    }

    public function testAddListener()
    {
        $this->dispatcher->addListener('pre.foo', array($this->listener, 'preFoo'));
        $this->dispatcher->addListener('post.foo', array($this->listener, 'postFoo'));
        $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
        $this->assertTrue($this->dispatcher->hasListeners(self::postFoo));
        $this->assertCount(1, $this->dispatcher->getListeners(self::preFoo));
        $this->assertCount(1, $this->dispatcher->getListeners(self::postFoo));
        $this->assertCount(2, $this->dispatcher->getListeners());
    }

    public function testGetListenersSortsByPriority()
    {
        $listener1 = new TestEventListener();
        $listener2 = new TestEventListener();
        $listener3 = new TestEventListener();
        $listener1->name = '1';
        $listener2->name = '2';
        $listener3->name = '3';

        $this->dispatcher->addListener('pre.foo', array($listener1, 'preFoo'), -10);
        $this->dispatcher->addListener('pre.foo', array($listener2, 'preFoo'), 10);
        $this->dispatcher->addListener('pre.foo', array($listener3, 'preFoo'));

        $expected = array(
            array($listener2, 'preFoo'),
            array($listener3, 'preFoo'),
            array($listener1, 'preFoo'),
        );

        $this->assertSame($expected, $this->dispatcher->getListeners('pre.foo'));
    }

    public function testGetAllListenersSortsByPriority()
    {
        $listener1 = new TestEventListener();
        $listener2 = new TestEventListener();
        $listener3 = new TestEventListener();
        $listener4 = new TestEventListener();
        $listener5 = new TestEventListener();
        $listener6 = new TestEventListener();

        $this->dispatcher->addListener('pre.foo', $listener1, -10);
        $this->dispatcher->addListener('pre.foo', $listener2);
        $this->dispatcher->addListener('pre.foo', $listener3, 10);
        $this->dispatcher->addListener('post.foo', $listener4, -10);
        $this->dispatcher->addListener('post.foo', $listener5);
        $this->dispatcher->addListener('post.foo', $listener6, 10);

        $expected = array(
            'pre.foo'  => array($listener3, $listener2, $listener1),
            'post.foo' => array($listener6, $listener5, $listener4),
        );

        $this->assertSame($expected, $this->dispatcher->getListeners());
    }

    public function testDispatch()
    {
        $this->dispatcher->addListener('pre.foo', array($this->listener, 'preFoo'));
        $this->dispatcher->addListener('post.foo', array($this->listener, 'postFoo'));
        $this->dispatcher->dispatch(self::preFoo);
        $this->assertTrue($this->listener->preFooInvoked);
        $this->assertFalse($this->listener->postFooInvoked);
        $this->assertInstanceOf('Symfony\Component\EventDispatcher\Event', $this->dispatcher->dispatch('noevent'));
        $this->assertInstanceOf('Symfony\Component\EventDispatcher\Event', $this->dispatcher->dispatch(self::preFoo));
        $event = new Event();
        $return = $this->dispatcher->dispatch(self::preFoo, $event);
        $this->assertEquals('pre.foo', $event->getName());
        $this->assertSame($event, $return);
    }

    public function testDispatchForClosure()
    {
        $invoked = 0;
        $listener = function () use (&$invoked) {
            $invoked++;
        };
        $this->dispatcher->addListener('pre.foo', $listener);
        $this->dispatcher->addListener('post.foo', $listener);
        $this->dispatcher->dispatch(self::preFoo);
        $this->assertEquals(1, $invoked);
    }

    public function testStopEventPropagation()
    {
        $otherListener = new TestEventListener();

        // postFoo() stops the propagation, so only one listener should
        // be executed
        // Manually set priority to enforce $this->listener to be called first
        $this->dispatcher->addListener('post.foo', array($this->listener, 'postFoo'), 10);
        $this->dispatcher->addListener('post.foo', array($otherListener, 'preFoo'));
        $this->dispatcher->dispatch(self::postFoo);
        $this->assertTrue($this->listener->postFooInvoked);
        $this->assertFalse($otherListener->postFooInvoked);
    }

    public function testDispatchByPriority()
    {
        $invoked = array();
        $listener1 = function () use (&$invoked) {
            $invoked[] = '1';
        };
        $listener2 = function () use (&$invoked) {
            $invoked[] = '2';
        };
        $listener3 = function () use (&$invoked) {
            $invoked[] = '3';
        };
        $this->dispatcher->addListener('pre.foo', $listener1, -10);
        $this->dispatcher->addListener('pre.foo', $listener2);
        $this->dispatcher->addListener('pre.foo', $listener3, 10);
        $this->dispatcher->dispatch(self::preFoo);
        $this->assertEquals(array('3', '2', '1'), $invoked);
    }

    public function testRemoveListener()
    {
        $this->dispatcher->addListener('pre.bar', $this->listener);
        $this->assertTrue($this->dispatcher->hasListeners(self::preBar));
        $this->dispatcher->removeListener('pre.bar', $this->listener);
        $this->assertFalse($this->dispatcher->hasListeners(self::preBar));
        $this->dispatcher->removeListener('notExists', $this->listener);
    }

    public function testAddSubscriber()
    {
        $eventSubscriber = new TestEventSubscriber();
        $this->dispatcher->addSubscriber($eventSubscriber);
        $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
        $this->assertTrue($this->dispatcher->hasListeners(self::postFoo));
    }

    public function testAddSubscriberWithPriorities()
    {
        $eventSubscriber = new TestEventSubscriber();
        $this->dispatcher->addSubscriber($eventSubscriber);

        $eventSubscriber = new TestEventSubscriberWithPriorities();
        $this->dispatcher->addSubscriber($eventSubscriber);

        $listeners = $this->dispatcher->getListeners('pre.foo');
        $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
        $this->assertCount(2, $listeners);
        $this->assertInstanceOf('Symfony\Component\EventDispatcher\Tests\TestEventSubscriberWithPriorities', $listeners[0][0]);
    }

    public function testAddSubscriberWithMultipleListeners()
    {
        $eventSubscriber = new TestEventSubscriberWithMultipleListeners();
        $this->dispatcher->addSubscriber($eventSubscriber);

        $listeners = $this->dispatcher->getListeners('pre.foo');
        $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
        $this->assertCount(2, $listeners);
        $this->assertEquals('preFoo2', $listeners[0][1]);
    }

    public function testRemoveSubscriber()
    {
        $eventSubscriber = new TestEventSubscriber();
        $this->dispatcher->addSubscriber($eventSubscriber);
        $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
        $this->assertTrue($this->dispatcher->hasListeners(self::postFoo));
        $this->dispatcher->removeSubscriber($eventSubscriber);
        $this->assertFalse($this->dispatcher->hasListeners(self::preFoo));
        $this->assertFalse($this->dispatcher->hasListeners(self::postFoo));
    }

    public function testRemoveSubscriberWithPriorities()
    {
        $eventSubscriber = new TestEventSubscriberWithPriorities();
        $this->dispatcher->addSubscriber($eventSubscriber);
        $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
        $this->dispatcher->removeSubscriber($eventSubscriber);
        $this->assertFalse($this->dispatcher->hasListeners(self::preFoo));
    }

    public function testRemoveSubscriberWithMultipleListeners()
    {
        $eventSubscriber = new TestEventSubscriberWithMultipleListeners();
        $this->dispatcher->addSubscriber($eventSubscriber);
        $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
        $this->assertCount(2, $this->dispatcher->getListeners(self::preFoo));
        $this->dispatcher->removeSubscriber($eventSubscriber);
        $this->assertFalse($this->dispatcher->hasListeners(self::preFoo));
    }

    public function testEventReceivesTheDispatcherInstance()
    {
        $dispatcher = null;
        $this->dispatcher->addListener('test', function ($event) use (&$dispatcher) {
            $dispatcher = $event->getDispatcher();
        });
        $this->dispatcher->dispatch('test');
        $this->assertSame($this->dispatcher, $dispatcher);
    }

    public function testEventReceivesTheDispatcherInstanceAsArgument()
    {
        $listener = new TestWithDispatcher();
        $this->dispatcher->addListener('test', array($listener, 'foo'));
        $this->assertNull($listener->name);
        $this->assertNull($listener->dispatcher);
        $this->dispatcher->dispatch('test');
        $this->assertEquals('test', $listener->name);
        $this->assertSame($this->dispatcher, $listener->dispatcher);
    }

    /**
     * @see https://bugs.php.net/bug.php?id=62976
     *
     * This bug affects:
     *  - The PHP 5.3 branch for versions < 5.3.18
     *  - The PHP 5.4 branch for versions < 5.4.8
     *  - The PHP 5.5 branch is not affected
     */
    public function testWorkaroundForPhpBug62976()
    {
        $dispatcher = new EventDispatcher();
        $dispatcher->addListener('bug.62976', new CallableClass());
        $dispatcher->removeListener('bug.62976', function () {});
        $this->assertTrue($dispatcher->hasListeners('bug.62976'));
    }
}

class CallableClass
{
    public function __invoke()
    {
    }
}

class TestEventListener
{
    public $preFooInvoked = false;
    public $postFooInvoked = false;

    /* Listener methods */

    public function preFoo(Event $e)
    {
        $this->preFooInvoked = true;
    }

    public function postFoo(Event $e)
    {
        $this->postFooInvoked = true;

        $e->stopPropagation();
    }
}

class TestWithDispatcher
{
    public $name;
    public $dispatcher;

    public function foo(Event $e, $name, $dispatcher)
    {
        $this->name = $name;
        $this->dispatcher = $dispatcher;
    }
}

class TestEventSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return array('pre.foo' => 'preFoo', 'post.foo' => 'postFoo');
    }
}

class TestEventSubscriberWithPriorities implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return array(
            'pre.foo' => array('preFoo', 10),
            'post.foo' => array('postFoo'),
            );
    }
}

class TestEventSubscriberWithMultipleListeners implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return array('pre.foo' => array(
            array('preFoo1'),
            array('preFoo2', 10)
        ));
    }
}
PK��Z���aa]test/EventDispatcher/Symfony/Component/EventDispatcher/Tests/ImmutableEventDispatcherTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\EventDispatcher\Tests;

use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\ImmutableEventDispatcher;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ImmutableEventDispatcherTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $innerDispatcher;

    /**
     * @var ImmutableEventDispatcher
     */
    private $dispatcher;

    protected function setUp()
    {
        $this->innerDispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
        $this->dispatcher = new ImmutableEventDispatcher($this->innerDispatcher);
    }

    public function testDispatchDelegates()
    {
        $event = new Event();

        $this->innerDispatcher->expects($this->once())
            ->method('dispatch')
            ->with('event', $event)
            ->will($this->returnValue('result'));

        $this->assertSame('result', $this->dispatcher->dispatch('event', $event));
    }

    public function testGetListenersDelegates()
    {
        $this->innerDispatcher->expects($this->once())
            ->method('getListeners')
            ->with('event')
            ->will($this->returnValue('result'));

        $this->assertSame('result', $this->dispatcher->getListeners('event'));
    }

    public function testHasListenersDelegates()
    {
        $this->innerDispatcher->expects($this->once())
            ->method('hasListeners')
            ->with('event')
            ->will($this->returnValue('result'));

        $this->assertSame('result', $this->dispatcher->hasListeners('event'));
    }

    /**
     * @expectedException \BadMethodCallException
     */
    public function testAddListenerDisallowed()
    {
        $this->dispatcher->addListener('event', function () { return 'foo'; });
    }

    /**
     * @expectedException \BadMethodCallException
     */
    public function testAddSubscriberDisallowed()
    {
        $subscriber = $this->getMock('Symfony\Component\EventDispatcher\EventSubscriberInterface');

        $this->dispatcher->addSubscriber($subscriber);
    }

    /**
     * @expectedException \BadMethodCallException
     */
    public function testRemoveListenerDisallowed()
    {
        $this->dispatcher->removeListener('event', function () { return 'foo'; });
    }

    /**
     * @expectedException \BadMethodCallException
     */
    public function testRemoveSubscriberDisallowed()
    {
        $subscriber = $this->getMock('Symfony\Component\EventDispatcher\EventSubscriberInterface');

        $this->dispatcher->removeSubscriber($subscriber);
    }
}
PK��ZYQ_AAbtest/EventDispatcher/Symfony/Component/EventDispatcher/Tests/ContainerAwareEventDispatcherTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\EventDispatcher\Tests;

use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Scope;
use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class ContainerAwareEventDispatcherTest extends \PHPUnit_Framework_TestCase
{
    public function testAddAListenerService()
    {
        $event = new Event();

        $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service');

        $service
            ->expects($this->once())
            ->method('onEvent')
            ->with($event)
        ;

        $container = new Container();
        $container->set('service.listener', $service);

        $dispatcher = new ContainerAwareEventDispatcher($container);
        $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'));

        $dispatcher->dispatch('onEvent', $event);
    }

    public function testAddASubscriberService()
    {
        $event = new Event();

        $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\SubscriberService');

        $service
            ->expects($this->once())
            ->method('onEvent')
            ->with($event)
        ;

        $container = new Container();
        $container->set('service.subscriber', $service);

        $dispatcher = new ContainerAwareEventDispatcher($container);
        $dispatcher->addSubscriberService('service.subscriber', 'Symfony\Component\EventDispatcher\Tests\SubscriberService');

        $dispatcher->dispatch('onEvent', $event);
    }

    public function testPreventDuplicateListenerService()
    {
        $event = new Event();

        $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service');

        $service
            ->expects($this->once())
            ->method('onEvent')
            ->with($event)
        ;

        $container = new Container();
        $container->set('service.listener', $service);

        $dispatcher = new ContainerAwareEventDispatcher($container);
        $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'), 5);
        $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'), 10);

        $dispatcher->dispatch('onEvent', $event);
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testTriggerAListenerServiceOutOfScope()
    {
        $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service');

        $scope = new Scope('scope');
        $container = new Container();
        $container->addScope($scope);
        $container->enterScope('scope');

        $container->set('service.listener', $service, 'scope');

        $dispatcher = new ContainerAwareEventDispatcher($container);
        $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'));

        $container->leaveScope('scope');
        $dispatcher->dispatch('onEvent');
    }

    public function testReEnteringAScope()
    {
        $event = new Event();

        $service1 = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service');

        $service1
            ->expects($this->exactly(2))
            ->method('onEvent')
            ->with($event)
        ;

        $scope = new Scope('scope');
        $container = new Container();
        $container->addScope($scope);
        $container->enterScope('scope');

        $container->set('service.listener', $service1, 'scope');

        $dispatcher = new ContainerAwareEventDispatcher($container);
        $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'));
        $dispatcher->dispatch('onEvent', $event);

        $service2 = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service');

        $service2
            ->expects($this->once())
            ->method('onEvent')
            ->with($event)
        ;

        $container->enterScope('scope');
        $container->set('service.listener', $service2, 'scope');

        $dispatcher->dispatch('onEvent', $event);

        $container->leaveScope('scope');

        $dispatcher->dispatch('onEvent');
    }

    public function testHasListenersOnLazyLoad()
    {
        $event = new Event();

        $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service');

        $container = new Container();
        $container->set('service.listener', $service);

        $dispatcher = new ContainerAwareEventDispatcher($container);
        $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'));

        $event->setDispatcher($dispatcher);
        $event->setName('onEvent');

        $service
            ->expects($this->once())
            ->method('onEvent')
            ->with($event)
        ;

        $this->assertTrue($dispatcher->hasListeners());

        if ($dispatcher->hasListeners('onEvent')) {
            $dispatcher->dispatch('onEvent');
        }
    }

    public function testGetListenersOnLazyLoad()
    {
        $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service');

        $container = new Container();
        $container->set('service.listener', $service);

        $dispatcher = new ContainerAwareEventDispatcher($container);
        $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'));

        $listeners = $dispatcher->getListeners();

        $this->assertTrue(isset($listeners['onEvent']));

        $this->assertCount(1, $dispatcher->getListeners('onEvent'));
    }

    public function testRemoveAfterDispatch()
    {
        $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service');

        $container = new Container();
        $container->set('service.listener', $service);

        $dispatcher = new ContainerAwareEventDispatcher($container);
        $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'));

        $dispatcher->dispatch('onEvent', new Event());
        $dispatcher->removeListener('onEvent', array($container->get('service.listener'), 'onEvent'));
        $this->assertFalse($dispatcher->hasListeners('onEvent'));
    }

    public function testRemoveBeforeDispatch()
    {
        $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service');

        $container = new Container();
        $container->set('service.listener', $service);

        $dispatcher = new ContainerAwareEventDispatcher($container);
        $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'));

        $dispatcher->removeListener('onEvent', array($container->get('service.listener'), 'onEvent'));
        $this->assertFalse($dispatcher->hasListeners('onEvent'));
    }
}

class Service
{
    public function onEvent(Event $e)
    {
    }
}

class SubscriberService implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return array(
            'onEvent' => 'onEvent',
            'onEvent' => array('onEvent', 10),
            'onEvent' => array('onEvent'),
        );
    }

    public function onEvent(Event $e)
    {
    }
}
PK��Z��nuJtest/EventDispatcher/Symfony/Component/EventDispatcher/Tests/EventTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\EventDispatcher\Tests;

use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventDispatcher;

/**
 * Test class for Event.
 */
class EventTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var \Symfony\Component\EventDispatcher\Event
     */
    protected $event;

    /**
     * @var \Symfony\Component\EventDispatcher\EventDispatcher
     */
    protected $dispatcher;

    /**
     * Sets up the fixture, for example, opens a network connection.
     * This method is called before a test is executed.
     */
    protected function setUp()
    {
        $this->event = new Event();
        $this->dispatcher = new EventDispatcher();
    }

    /**
     * Tears down the fixture, for example, closes a network connection.
     * This method is called after a test is executed.
     */
    protected function tearDown()
    {
        $this->event = null;
        $this->dispatcher = null;
    }

    public function testIsPropagationStopped()
    {
        $this->assertFalse($this->event->isPropagationStopped());
    }

    public function testStopPropagationAndIsPropagationStopped()
    {
        $this->event->stopPropagation();
        $this->assertTrue($this->event->isPropagationStopped());
    }

    public function testSetDispatcher()
    {
        $this->event->setDispatcher($this->dispatcher);
        $this->assertSame($this->dispatcher, $this->event->getDispatcher());
    }

    public function testGetDispatcher()
    {
        $this->assertNull($this->event->getDispatcher());
    }

    public function testGetName()
    {
        $this->assertNull($this->event->getName());
    }

    public function testSetName()
    {
        $this->event->setName('foo');
        $this->assertEquals('foo', $this->event->getName());
    }
}
PK��Z\2��
�
Qtest/EventDispatcher/Symfony/Component/EventDispatcher/Tests/GenericEventTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\EventDispatcher\Tests;

use Symfony\Component\EventDispatcher\GenericEvent;

/**
 * Test class for Event.
 */
class GenericEventTest extends \PHPUnit_Framework_TestCase
{

    /**
     * @var GenericEvent
     */
    private $event;

    private $subject;

    /**
     * Prepares the environment before running a test.
     */
    protected function setUp()
    {
        parent::setUp();

        $this->subject = new \stdClass();
        $this->event = new GenericEvent($this->subject, array('name' => 'Event'), 'foo');
    }

    /**
     * Cleans up the environment after running a test.
     */
    protected function tearDown()
    {
        $this->subject = null;
        $this->event = null;

        parent::tearDown();
    }

    public function testConstruct()
    {
        $this->assertEquals($this->event, new GenericEvent($this->subject, array('name' => 'Event')));
    }

    /**
     * Tests Event->getArgs()
     */
    public function testGetArguments()
    {
        // test getting all
        $this->assertSame(array('name' => 'Event'), $this->event->getArguments());
    }

    public function testSetArguments()
    {
        $result = $this->event->setArguments(array('foo' => 'bar'));
        $this->assertAttributeSame(array('foo' => 'bar'), 'arguments', $this->event);
        $this->assertSame($this->event, $result);
    }

    public function testSetArgument()
    {
        $result = $this->event->setArgument('foo2', 'bar2');
        $this->assertAttributeSame(array('name' => 'Event', 'foo2' => 'bar2'), 'arguments', $this->event);
        $this->assertEquals($this->event, $result);
    }

    public function testGetArgument()
    {
        // test getting key
        $this->assertEquals('Event', $this->event->getArgument('name'));
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testGetArgException()
    {
        $this->event->getArgument('nameNotExist');
    }

    public function testOffsetGet()
    {
        // test getting key
        $this->assertEquals('Event', $this->event['name']);

        // test getting invalid arg
        $this->setExpectedException('InvalidArgumentException');
        $this->assertFalse($this->event['nameNotExist']);
    }

    public function testOffsetSet()
    {
        $this->event['foo2'] = 'bar2';
        $this->assertAttributeSame(array('name' => 'Event', 'foo2' => 'bar2'), 'arguments', $this->event);
    }

    public function testOffsetUnset()
    {
        unset($this->event['name']);
        $this->assertAttributeSame(array(), 'arguments', $this->event);
    }

    public function testOffsetIsset()
    {
        $this->assertTrue(isset($this->event['name']));
        $this->assertFalse(isset($this->event['nameNotExist']));
    }

    public function testHasArgument()
    {
        $this->assertTrue($this->event->hasArgument('name'));
        $this->assertFalse($this->event->hasArgument('nameNotExist'));
    }

    public function testGetSubject()
    {
        $this->assertSame($this->subject, $this->event->getSubject());
    }

    public function testHasIterator()
    {
        $data = array();
        foreach ($this->event as $key => $value) {
            $data[$key] = $value;
        }
        $this->assertEquals(array('name' => 'Event'), $data);
    }
}
PK��Z�MqqGtest/EventDispatcher/Symfony/Component/EventDispatcher/phpunit.xml.distnu�[���<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony EventDispatcher Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./Resources</directory>
                <directory>./Tests</directory>
                <directory>./vendor</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
PK��Z��C	C	Htest/Console/Symfony/Component/Console/Tests/Command/ListCommandTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Command;

use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Component\Console\Application;

class ListCommandTest extends \PHPUnit_Framework_TestCase
{
    public function testExecuteListsCommands()
    {
        $application = new Application();
        $commandTester = new CommandTester($command = $application->get('list'));
        $commandTester->execute(array('command' => $command->getName()), array('decorated' => false));

        $this->assertRegExp('/help   Displays help for a command/', $commandTester->getDisplay(), '->execute() returns a list of available commands');
    }

    public function testExecuteListsCommandsWithXmlOption()
    {
        $application = new Application();
        $commandTester = new CommandTester($command = $application->get('list'));
        $commandTester->execute(array('command' => $command->getName(), '--format' => 'xml'));
        $this->assertRegExp('/<command id="list" name="list">/', $commandTester->getDisplay(), '->execute() returns a list of available commands in XML if --xml is passed');
    }

    public function testExecuteListsCommandsWithRawOption()
    {
        $application = new Application();
        $commandTester = new CommandTester($command = $application->get('list'));
        $commandTester->execute(array('command' => $command->getName(), '--raw' => true));
        $output = <<<EOF
help   Displays help for a command
list   Lists commands

EOF;

        $this->assertEquals($output, $commandTester->getDisplay(true));
    }

    public function testExecuteListsCommandsWithNamespaceArgument()
    {

        require_once(realpath(__DIR__.'/../Fixtures/FooCommand.php'));
        $application = new Application();
        $application->add(new \FooCommand());
        $commandTester = new CommandTester($command = $application->get('list'));
        $commandTester->execute(array('command' => $command->getName(), 'namespace' => 'foo', '--raw' => true));
        $output = <<<EOF
foo:bar   The foo:bar command

EOF;

        $this->assertEquals($output, $commandTester->getDisplay(true));
    }
}
PK��Zo�"�Z9Z9Dtest/Console/Symfony/Component/Console/Tests/Command/CommandTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\FormatterHelper;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\StringInput;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Console\Tester\CommandTester;

class CommandTest extends \PHPUnit_Framework_TestCase
{
    protected static $fixturesPath;

    public static function setUpBeforeClass()
    {
        self::$fixturesPath = __DIR__.'/../Fixtures/';
        require_once self::$fixturesPath.'/TestCommand.php';
    }

    public function testConstructor()
    {
        $command = new Command('foo:bar');
        $this->assertEquals('foo:bar', $command->getName(), '__construct() takes the command name as its first argument');
    }

    /**
     * @expectedException        \LogicException
     * @expectedExceptionMessage The command name cannot be empty.
     */
    public function testCommandNameCannotBeEmpty()
    {
        new Command();
    }

    public function testSetApplication()
    {
        $application = new Application();
        $command = new \TestCommand();
        $command->setApplication($application);
        $this->assertEquals($application, $command->getApplication(), '->setApplication() sets the current application');
    }

    public function testSetGetDefinition()
    {
        $command = new \TestCommand();
        $ret = $command->setDefinition($definition = new InputDefinition());
        $this->assertEquals($command, $ret, '->setDefinition() implements a fluent interface');
        $this->assertEquals($definition, $command->getDefinition(), '->setDefinition() sets the current InputDefinition instance');
        $command->setDefinition(array(new InputArgument('foo'), new InputOption('bar')));
        $this->assertTrue($command->getDefinition()->hasArgument('foo'), '->setDefinition() also takes an array of InputArguments and InputOptions as an argument');
        $this->assertTrue($command->getDefinition()->hasOption('bar'), '->setDefinition() also takes an array of InputArguments and InputOptions as an argument');
        $command->setDefinition(new InputDefinition());
    }

    public function testAddArgument()
    {
        $command = new \TestCommand();
        $ret = $command->addArgument('foo');
        $this->assertEquals($command, $ret, '->addArgument() implements a fluent interface');
        $this->assertTrue($command->getDefinition()->hasArgument('foo'), '->addArgument() adds an argument to the command');
    }

    public function testAddOption()
    {
        $command = new \TestCommand();
        $ret = $command->addOption('foo');
        $this->assertEquals($command, $ret, '->addOption() implements a fluent interface');
        $this->assertTrue($command->getDefinition()->hasOption('foo'), '->addOption() adds an option to the command');
    }

    public function testGetNamespaceGetNameSetName()
    {
        $command = new \TestCommand();
        $this->assertEquals('namespace:name', $command->getName(), '->getName() returns the command name');
        $command->setName('foo');
        $this->assertEquals('foo', $command->getName(), '->setName() sets the command name');

        $ret = $command->setName('foobar:bar');
        $this->assertEquals($command, $ret, '->setName() implements a fluent interface');
        $this->assertEquals('foobar:bar', $command->getName(), '->setName() sets the command name');
    }

    /**
     * @dataProvider provideInvalidCommandNames
     */
    public function testInvalidCommandNames($name)
    {
        $this->setExpectedException('InvalidArgumentException', sprintf('Command name "%s" is invalid.', $name));

        $command = new \TestCommand();
        $command->setName($name);
    }

    public function provideInvalidCommandNames()
    {
        return array(
            array(''),
            array('foo:')
        );
    }

    public function testGetSetDescription()
    {
        $command = new \TestCommand();
        $this->assertEquals('description', $command->getDescription(), '->getDescription() returns the description');
        $ret = $command->setDescription('description1');
        $this->assertEquals($command, $ret, '->setDescription() implements a fluent interface');
        $this->assertEquals('description1', $command->getDescription(), '->setDescription() sets the description');
    }

    public function testGetSetHelp()
    {
        $command = new \TestCommand();
        $this->assertEquals('help', $command->getHelp(), '->getHelp() returns the help');
        $ret = $command->setHelp('help1');
        $this->assertEquals($command, $ret, '->setHelp() implements a fluent interface');
        $this->assertEquals('help1', $command->getHelp(), '->setHelp() sets the help');
    }

    public function testGetProcessedHelp()
    {
        $command = new \TestCommand();
        $command->setHelp('The %command.name% command does... Example: php %command.full_name%.');
        $this->assertContains('The namespace:name command does...', $command->getProcessedHelp(), '->getProcessedHelp() replaces %command.name% correctly');
        $this->assertNotContains('%command.full_name%', $command->getProcessedHelp(), '->getProcessedHelp() replaces %command.full_name%');
    }

    public function testGetSetAliases()
    {
        $command = new \TestCommand();
        $this->assertEquals(array('name'), $command->getAliases(), '->getAliases() returns the aliases');
        $ret = $command->setAliases(array('name1'));
        $this->assertEquals($command, $ret, '->setAliases() implements a fluent interface');
        $this->assertEquals(array('name1'), $command->getAliases(), '->setAliases() sets the aliases');
    }

    public function testGetSynopsis()
    {
        $command = new \TestCommand();
        $command->addOption('foo');
        $command->addArgument('foo');
        $this->assertEquals('namespace:name [--foo] [foo]', $command->getSynopsis(), '->getSynopsis() returns the synopsis');
    }

    public function testGetHelper()
    {
        $application = new Application();
        $command = new \TestCommand();
        $command->setApplication($application);
        $formatterHelper = new FormatterHelper();
        $this->assertEquals($formatterHelper->getName(), $command->getHelper('formatter')->getName(), '->getHelper() returns the correct helper');
    }

    public function testGet()
    {
        $application = new Application();
        $command = new \TestCommand();
        $command->setApplication($application);
        $formatterHelper = new FormatterHelper();
        $this->assertEquals($formatterHelper->getName(), $command->getHelper('formatter')->getName(), '->__get() returns the correct helper');
    }

    public function testMergeApplicationDefinition()
    {
        $application1 = new Application();
        $application1->getDefinition()->addArguments(array(new InputArgument('foo')));
        $application1->getDefinition()->addOptions(array(new InputOption('bar')));
        $command = new \TestCommand();
        $command->setApplication($application1);
        $command->setDefinition($definition = new InputDefinition(array(new InputArgument('bar'), new InputOption('foo'))));

        $r = new \ReflectionObject($command);
        $m = $r->getMethod('mergeApplicationDefinition');
        $m->setAccessible(true);
        $m->invoke($command);
        $this->assertTrue($command->getDefinition()->hasArgument('foo'), '->mergeApplicationDefinition() merges the application arguments and the command arguments');
        $this->assertTrue($command->getDefinition()->hasArgument('bar'), '->mergeApplicationDefinition() merges the application arguments and the command arguments');
        $this->assertTrue($command->getDefinition()->hasOption('foo'), '->mergeApplicationDefinition() merges the application options and the command options');
        $this->assertTrue($command->getDefinition()->hasOption('bar'), '->mergeApplicationDefinition() merges the application options and the command options');

        $m->invoke($command);
        $this->assertEquals(3, $command->getDefinition()->getArgumentCount(), '->mergeApplicationDefinition() does not try to merge twice the application arguments and options');
    }

    public function testMergeApplicationDefinitionWithoutArgsThenWithArgsAddsArgs()
    {
        $application1 = new Application();
        $application1->getDefinition()->addArguments(array(new InputArgument('foo')));
        $application1->getDefinition()->addOptions(array(new InputOption('bar')));
        $command = new \TestCommand();
        $command->setApplication($application1);
        $command->setDefinition($definition = new InputDefinition(array()));

        $r = new \ReflectionObject($command);
        $m = $r->getMethod('mergeApplicationDefinition');
        $m->setAccessible(true);
        $m->invoke($command, false);
        $this->assertTrue($command->getDefinition()->hasOption('bar'), '->mergeApplicationDefinition(false) merges the application and the commmand options');
        $this->assertFalse($command->getDefinition()->hasArgument('foo'), '->mergeApplicationDefinition(false) does not merge the application arguments');

        $m->invoke($command, true);
        $this->assertTrue($command->getDefinition()->hasArgument('foo'), '->mergeApplicationDefinition(true) merges the application arguments and the command arguments');

        $m->invoke($command);
        $this->assertEquals(2, $command->getDefinition()->getArgumentCount(), '->mergeApplicationDefinition() does not try to merge twice the application arguments');
    }

    public function testRunInteractive()
    {
        $tester = new CommandTester(new \TestCommand());

        $tester->execute(array(), array('interactive' => true));

        $this->assertEquals('interact called'.PHP_EOL.'execute called'.PHP_EOL, $tester->getDisplay(), '->run() calls the interact() method if the input is interactive');
    }

    public function testRunNonInteractive()
    {
        $tester = new CommandTester(new \TestCommand());

        $tester->execute(array(), array('interactive' => false));

        $this->assertEquals('execute called'.PHP_EOL, $tester->getDisplay(), '->run() does not call the interact() method if the input is not interactive');
    }

    /**
     * @expectedException        \LogicException
     * @expectedExceptionMessage You must override the execute() method in the concrete command class.
     */
    public function testExecuteMethodNeedsToBeOverriden()
    {
        $command = new Command('foo');
        $command->run(new StringInput(''), new NullOutput());
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage The "--bar" option does not exist.
     */
    public function testRunWithInvalidOption()
    {
        $command = new \TestCommand();
        $tester = new CommandTester($command);
        $tester->execute(array('--bar' => true));
    }

    public function testRunReturnsIntegerExitCode()
    {
        $command = new \TestCommand();
        $exitCode = $command->run(new StringInput(''), new NullOutput());
        $this->assertSame(0, $exitCode, '->run() returns integer exit code (treats null as 0)');

        $command = $this->getMock('TestCommand', array('execute'));
        $command->expects($this->once())
             ->method('execute')
             ->will($this->returnValue('2.3'));
        $exitCode = $command->run(new StringInput(''), new NullOutput());
        $this->assertSame(2, $exitCode, '->run() returns integer exit code (casts numeric to int)');
    }

    public function testRunReturnsAlwaysInteger()
    {
        $command = new \TestCommand();

        $this->assertSame(0, $command->run(new StringInput(''), new NullOutput()));
    }

    public function testSetCode()
    {
        $command = new \TestCommand();
        $ret = $command->setCode(function (InputInterface $input, OutputInterface $output) {
            $output->writeln('from the code...');
        });
        $this->assertEquals($command, $ret, '->setCode() implements a fluent interface');
        $tester = new CommandTester($command);
        $tester->execute(array());
        $this->assertEquals('interact called'.PHP_EOL.'from the code...'.PHP_EOL, $tester->getDisplay());
    }

    public function testSetCodeWithNonClosureCallable()
    {
        $command = new \TestCommand();
        $ret = $command->setCode(array($this, 'callableMethodCommand'));
        $this->assertEquals($command, $ret, '->setCode() implements a fluent interface');
        $tester = new CommandTester($command);
        $tester->execute(array());
        $this->assertEquals('interact called'.PHP_EOL.'from the code...'.PHP_EOL, $tester->getDisplay());
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage Invalid callable provided to Command::setCode.
     */
    public function testSetCodeWithNonCallable()
    {
        $command = new \TestCommand();
        $command->setCode(array($this, 'nonExistentMethod'));
    }

    public function callableMethodCommand(InputInterface $input, OutputInterface $output)
    {
        $output->writeln('from the code...');
    }

    public function testAsText()
    {
        $command = new \TestCommand();
        $command->setApplication(new Application());
        $tester = new CommandTester($command);
        $tester->execute(array('command' => $command->getName()));
        $this->assertStringEqualsFile(self::$fixturesPath.'/command_astext.txt', $command->asText(), '->asText() returns a text representation of the command');
    }

    public function testAsXml()
    {
        $command = new \TestCommand();
        $command->setApplication(new Application());
        $tester = new CommandTester($command);
        $tester->execute(array('command' => $command->getName()));
        $this->assertXmlStringEqualsXmlFile(self::$fixturesPath.'/command_asxml.txt', $command->asXml(), '->asXml() returns an XML representation of the command');
    }
}
PK��Zb�y�11Htest/Console/Symfony/Component/Console/Tests/Command/HelpCommandTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Command;

use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Component\Console\Command\HelpCommand;
use Symfony\Component\Console\Command\ListCommand;
use Symfony\Component\Console\Application;

class HelpCommandTest extends \PHPUnit_Framework_TestCase
{
    public function testExecuteForCommandAlias()
    {
        $command = new HelpCommand();
        $command->setApplication(new Application());
        $commandTester = new CommandTester($command);
        $commandTester->execute(array('command_name' => 'li'));
        $this->assertRegExp('/list \[--xml\] \[--raw\] \[--format="\.\.\."\] \[namespace\]/', $commandTester->getDisplay(), '->execute() returns a text help for the given command alias');
    }

    public function testExecuteForCommand()
    {
        $command = new HelpCommand();
        $commandTester = new CommandTester($command);
        $command->setCommand(new ListCommand());
        $commandTester->execute(array());
        $this->assertRegExp('/list \[--xml\] \[--raw\] \[--format="\.\.\."\] \[namespace\]/', $commandTester->getDisplay(), '->execute() returns a text help for the given command');
    }

    public function testExecuteForCommandWithXmlOption()
    {
        $command = new HelpCommand();
        $commandTester = new CommandTester($command);
        $command->setCommand(new ListCommand());
        $commandTester->execute(array('--format' => 'xml'));
        $this->assertRegExp('/<command/', $commandTester->getDisplay(), '->execute() returns an XML help text if --xml is passed');
    }

    public function testExecuteForApplicationCommand()
    {
        $application = new Application();
        $commandTester = new CommandTester($application->get('help'));
        $commandTester->execute(array('command_name' => 'list'));
        $this->assertRegExp('/list \[--xml\] \[--raw\] \[--format="\.\.\."\] \[namespace\]/', $commandTester->getDisplay(), '->execute() returns a text help for the given command');
    }

    public function testExecuteForApplicationCommandWithXmlOption()
    {
        $application = new Application();
        $commandTester = new CommandTester($application->get('help'));
        $commandTester->execute(array('command_name' => 'list', '--format' => 'xml'));
        $this->assertRegExp('/list \[--xml\] \[--raw\] \[--format="\.\.\."\] \[namespace\]/', $commandTester->getDisplay(), '->execute() returns a text help for the given command');
        $this->assertRegExp('/<command/', $commandTester->getDisplay(), '->execute() returns an XML help text if --format=xml is passed');
    }
}
PK��Zu��d��Mtest/Console/Symfony/Component/Console/Tests/Fixtures/application_astext1.txtnu�[���<info>Console Tool</info>

<comment>Usage:</comment>
  [options] command [arguments]

<comment>Options:</comment>
  <info>--help</info>           <info>-h</info> Display this help message.
  <info>--quiet</info>          <info>-q</info> Do not output any message.
  <info>--verbose</info>        <info>-v|vv|vvv</info> Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
  <info>--version</info>        <info>-V</info> Display this application version.
  <info>--ansi</info>              Force ANSI output.
  <info>--no-ansi</info>           Disable ANSI output.
  <info>--no-interaction</info> <info>-n</info> Do not ask any interactive question.

<comment>Available commands:</comment>
  <info>afoobar  </info> The foo:bar command
  <info>help     </info> Displays help for a command
  <info>list     </info> Lists commands
<comment>foo</comment>
  <info>foo:bar  </info> The foo:bar command
PK��Z��c��Gtest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_3.mdnu�[���**option_name:**

* Name: `--option_name`
* Shortcut: `-o`
* Accept value: yes
* Is value required: yes
* Is multiple: no
* Description: option description
* Default: `NULL`
PK��Z���ooKtest/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_2.jsonnu�[���{"name":"argument_name","is_required":false,"is_array":true,"description":"argument description","default":[]}
PK��Z��f���Jtest/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_2.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<argument name="argument_name" is_required="0" is_array="1">
  <description>argument description</description>
  <defaults/>
</argument>
PK��Z9y�X��Btest/Console/Symfony/Component/Console/Tests/Fixtures/command_1.mdnu�[���descriptor:command1
-------------------

* Description: command 1 description
* Usage: `descriptor:command1`
* Aliases: `alias1`, `alias2`

command 1 help
PK��Z�S��Gtest/Console/Symfony/Component/Console/Tests/Fixtures/command_asxml.txtnu�[���<?xml version="1.0" encoding="UTF-8"?>
<command id="namespace:name" name="namespace:name">
  <usage>namespace:name</usage>
  <description>description</description>
  <help>help</help>
  <aliases>
    <alias>name</alias>
  </aliases>
  <arguments>
    <argument name="command" is_required="1" is_array="0">
      <description>The command to execute</description>
      <defaults/>
    </argument>
  </arguments>
  <options>
    <option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0">
      <description>Display this help message.</description>
    </option>
    <option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0">
      <description>Do not output any message.</description>
    </option>
    <option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0">
      <description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description>
    </option>
    <option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0">
      <description>Display this application version.</description>
    </option>
    <option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
      <description>Force ANSI output.</description>
    </option>
    <option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
      <description>Disable ANSI output.</description>
    </option>
    <option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0">
      <description>Do not ask any interactive question.</description>
    </option>
  </options>
</command>
PK��Z�^t�^^Ltest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_1.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<definition>
  <arguments/>
  <options/>
</definition>
PK��ZP����Gtest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_4.mdnu�[���**option_name:**

* Name: `--option_name`
* Shortcut: `-o`
* Accept value: yes
* Is value required: no
* Is multiple: yes
* Description: option description
* Default: `array ()`
PK��Z���Gtest/Console/Symfony/Component/Console/Tests/Fixtures/BarBucCommand.phpnu�[���<?php

use Symfony\Component\Console\Command\Command;

class BarBucCommand extends Command
{
    protected function configure()
    {
        $this->setName('bar:buc');
    }
}
PK��ZW'��Ltest/Console/Symfony/Component/Console/Tests/Fixtures/application_asxml2.txtnu�[���<?xml version="1.0" encoding="UTF-8"?>
<symfony>
  <commands namespace="foo">
    <command id="foo:bar" name="foo:bar">
  <usage>foo:bar</usage>
  <description>The foo:bar command</description>
  <help/>
  <aliases>
    <alias>afoobar</alias>
  </aliases>
  <arguments/>
    <options>
      <option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0">
        <description>Display this help message.</description>
      </option>
      <option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0">
        <description>Do not output any message.</description>
      </option>
      <option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0">
        <description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description>
      </option>
      <option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0">
        <description>Display this application version.</description>
      </option>
      <option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
        <description>Force ANSI output.</description>
      </option>
      <option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
        <description>Disable ANSI output.</description>
      </option>
      <option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0">
        <description>Do not ask any interactive question.</description>
      </option>
    </options>
</command>
  </commands>
</symfony>
PK��Z&���Vtest/Console/Symfony/Component/Console/Tests/Fixtures/application_renderexception1.txtnu�[���

                                 
  [InvalidArgumentException]     
  Command "foo" is not defined.  
                                 


PK��Z��XX��Htest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_3.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<option name="--option_name" shortcut="-o" accept_value="1" is_value_required="1" is_multiple="0">
  <description>option description</description>
  <defaults/>
</option>
PK��Z��G��Htest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_1.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<option name="--option_name" shortcut="-o" accept_value="0" is_value_required="0" is_multiple="0">
  <description></description>
</option>
PK��ZY'�A��Ltest/Console/Symfony/Component/Console/Tests/Fixtures/DescriptorCommand1.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Fixtures;

use Symfony\Component\Console\Command\Command;

class DescriptorCommand1 extends Command
{
    protected function configure()
    {
        $this
            ->setName('descriptor:command1')
            ->setAliases(array('alias1', 'alias2'))
            ->setDescription('command 1 description')
            ->setHelp('command 1 help')
        ;
    }
}
PK��ZCQu��Ltest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_4.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<definition>
  <arguments>
    <argument name="argument_name" is_required="1" is_array="0">
      <description></description>
      <defaults/>
    </argument>
  </arguments>
  <options>
    <option name="--option_name" shortcut="-o" accept_value="0" is_value_required="0" is_multiple="0">
      <description></description>
    </option>
  </options>
</definition>
PK��Z�!�"��Jtest/Console/Symfony/Component/Console/Tests/Fixtures/application_run3.txtnu�[���Usage:
 list [--xml] [--raw] [--format="..."] [namespace]

Arguments:
 namespace  The namespace name

Options:
 --xml      To output list as XML
 --raw      To output raw command list
 --format   To output list in other formats (default: "txt")

Help:
 The list command lists all commands:
 
   php app/console list
 
 You can also display the commands for a specific namespace:
 
   php app/console list test
 
 You can also output the information in other formats by using the --format option:
 
   php app/console list --format=xml
 
 It's also possible to get raw list of commands (useful for embedding command runner):
 
   php app/console list --raw
PK��Z�e�d��Etest/Console/Symfony/Component/Console/Tests/Fixtures/Foo4Command.phpnu�[���<?php

use Symfony\Component\Console\Command\Command;

class Foo4Command extends Command
{
    protected function configure()
    {
        $this->setName('foo3:bar:toh');
    }
}
PK��Zz�Ռ��Itest/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_2.mdnu�[���**argument_name:**

* Name: argument_name
* Is required: no
* Is array: yes
* Description: argument description
* Default: `array ()`
PK��Z�t;�aaHtest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_4.txtnu�[��� <info>--option_name</info> (-o) option description<comment> (multiple values allowed)</comment>
PK��Z a���Itest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_4.jsonnu�[���{"name":"--option_name","shortcut":"-o","accept_value":true,"is_value_required":false,"is_multiple":true,"description":"option description","default":[]}
PK��Z�F:cLtest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_3.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<definition>
  <arguments/>
  <options>
    <option name="--option_name" shortcut="-o" accept_value="0" is_value_required="0" is_multiple="0">
      <description></description>
    </option>
  </options>
</definition>
PK��ZoY���Htest/Console/Symfony/Component/Console/Tests/Fixtures/application_1.jsonnu�[���{"commands":[{"name":"help","usage":"help [--xml] [--format=\"...\"] [--raw] [command_name]","description":"Displays help for a command","help":"The <info>help<\/info> command displays help for a given command:\n\n  <info>php app\/console help list<\/info>\n\nYou can also output the help in other formats by using the <comment>--format<\/comment> option:\n\n  <info>php app\/console help --format=xml list<\/info>\n\nTo display the list of available commands, please use the <info>list<\/info> command.","aliases":[],"definition":{"arguments":{"command_name":{"name":"command_name","is_required":false,"is_array":false,"description":"The command name","default":"help"}},"options":{"xml":{"name":"--xml","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output help as XML","default":false},"format":{"name":"--format","shortcut":"","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"To output help in other formats","default":"txt"},"raw":{"name":"--raw","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output raw command help","default":false},"help":{"name":"--help","shortcut":"-h","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this help message.","default":false},"quiet":{"name":"--quiet","shortcut":"-q","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not output any message.","default":false},"verbose":{"name":"--verbose","shortcut":"-v|-vv|-vvv","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug","default":false},"version":{"name":"--version","shortcut":"-V","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this application version.","default":false},"ansi":{"name":"--ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Force ANSI output.","default":false},"no-ansi":{"name":"--no-ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Disable ANSI output.","default":false},"no-interaction":{"name":"--no-interaction","shortcut":"-n","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not ask any interactive question.","default":false}}}},{"name":"list","usage":"list [--xml] [--raw] [--format=\"...\"] [namespace]","description":"Lists commands","help":"The <info>list<\/info> command lists all commands:\n\n  <info>php app\/console list<\/info>\n\nYou can also display the commands for a specific namespace:\n\n  <info>php app\/console list test<\/info>\n\nYou can also output the information in other formats by using the <comment>--format<\/comment> option:\n\n  <info>php app\/console list --format=xml<\/info>\n\nIt's also possible to get raw list of commands (useful for embedding command runner):\n\n  <info>php app\/console list --raw<\/info>","aliases":[],"definition":{"arguments":{"namespace":{"name":"namespace","is_required":false,"is_array":false,"description":"The namespace name","default":null}},"options":{"xml":{"name":"--xml","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output list as XML","default":false},"raw":{"name":"--raw","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output raw command list","default":false},"format":{"name":"--format","shortcut":"","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"To output list in other formats","default":"txt"}}}}],"namespaces":[{"id":"_global","commands":["help","list"]}]}
PK��Z#��"��Dtest/Console/Symfony/Component/Console/Tests/Fixtures/command_2.jsonnu�[���{"name":"descriptor:command2","usage":"descriptor:command2 [-o|--option_name] argument_name","description":"command 2 description","help":"command 2 help","aliases":[],"definition":{"arguments":{"argument_name":{"name":"argument_name","is_required":true,"is_array":false,"description":"","default":null}},"options":{"option_name":{"name":"--option_name","shortcut":"-o","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"","default":false}}}}
PK��Z9�*A��Etest/Console/Symfony/Component/Console/Tests/Fixtures/TestCommand.phpnu�[���<?php

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class TestCommand extends Command
{
    protected function configure()
    {
        $this
            ->setName('namespace:name')
            ->setAliases(array('name'))
            ->setDescription('description')
            ->setHelp('help')
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $output->writeln('execute called');
    }

    protected function interact(InputInterface $input, OutputInterface $output)
    {
        $output->writeln('interact called');
    }
}
PK��Z�'�̒�Ctest/Console/Symfony/Component/Console/Tests/Fixtures/command_1.txtnu�[���<comment>Usage:</comment>
 descriptor:command1

<comment>Aliases:</comment> <info>alias1, alias2</info>

<comment>Help:</comment>
 command 1 help
PK��Z<|�4UUEtest/Console/Symfony/Component/Console/Tests/Fixtures/Foo1Command.phpnu�[���<?php

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class Foo1Command extends Command
{
    public $input;
    public $output;

    protected function configure()
    {
        $this
            ->setName('foo:bar1')
            ->setDescription('The foo:bar1 command')
            ->setAliases(array('afoobar1'))
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $this->input = $input;
        $this->output = $output;
    }
}
PK��ZLtest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_1.txtnu�[���PK��Z��<]]Ktest/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_1.jsonnu�[���{"name":"argument_name","is_required":true,"is_array":false,"description":"","default":null}
PK��Z۴�2��Itest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_2.jsonnu�[���{"name":"--option_name","shortcut":"-o","accept_value":true,"is_value_required":false,"is_multiple":false,"description":"option description","default":"default_value"}
PK��Z�q+��Ptest/Console/Symfony/Component/Console/Tests/Fixtures/DescriptorApplication1.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Fixtures;

use Symfony\Component\Console\Application;

class DescriptorApplication1 extends Application
{
}
PK��Z��[���Ktest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_2.mdnu�[���### Arguments:

**argument_name:**

* Name: argument_name
* Is required: yes
* Is array: no
* Description: <none>
* Default: `NULL`
PK��Z��#��Ftest/Console/Symfony/Component/Console/Tests/Fixtures/application_2.mdnu�[���My Symfony application
======================

* alias1
* alias2
* help
* list

**descriptor:**

* descriptor:command1
* descriptor:command2

help
----

* Description: Displays help for a command
* Usage: `help [--xml] [--format="..."] [--raw] [command_name]`
* Aliases: <none>

The <info>help</info> command displays help for a given command:

  <info>php app/console help list</info>

You can also output the help in other formats by using the <comment>--format</comment> option:

  <info>php app/console help --format=xml list</info>

To display the list of available commands, please use the <info>list</info> command.

### Arguments:

**command_name:**

* Name: command_name
* Is required: no
* Is array: no
* Description: The command name
* Default: `'help'`

### Options:

**xml:**

* Name: `--xml`
* Shortcut: <none>
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: To output help as XML
* Default: `false`

**format:**

* Name: `--format`
* Shortcut: <none>
* Accept value: yes
* Is value required: yes
* Is multiple: no
* Description: To output help in other formats
* Default: `'txt'`

**raw:**

* Name: `--raw`
* Shortcut: <none>
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: To output raw command help
* Default: `false`

**help:**

* Name: `--help`
* Shortcut: `-h`
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: Display this help message.
* Default: `false`

**quiet:**

* Name: `--quiet`
* Shortcut: `-q`
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: Do not output any message.
* Default: `false`

**verbose:**

* Name: `--verbose`
* Shortcut: `-v|-vv|-vvv`
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
* Default: `false`

**version:**

* Name: `--version`
* Shortcut: `-V`
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: Display this application version.
* Default: `false`

**ansi:**

* Name: `--ansi`
* Shortcut: <none>
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: Force ANSI output.
* Default: `false`

**no-ansi:**

* Name: `--no-ansi`
* Shortcut: <none>
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: Disable ANSI output.
* Default: `false`

**no-interaction:**

* Name: `--no-interaction`
* Shortcut: `-n`
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: Do not ask any interactive question.
* Default: `false`

list
----

* Description: Lists commands
* Usage: `list [--xml] [--raw] [--format="..."] [namespace]`
* Aliases: <none>

The <info>list</info> command lists all commands:

  <info>php app/console list</info>

You can also display the commands for a specific namespace:

  <info>php app/console list test</info>

You can also output the information in other formats by using the <comment>--format</comment> option:

  <info>php app/console list --format=xml</info>

It's also possible to get raw list of commands (useful for embedding command runner):

  <info>php app/console list --raw</info>

### Arguments:

**namespace:**

* Name: namespace
* Is required: no
* Is array: no
* Description: The namespace name
* Default: `NULL`

### Options:

**xml:**

* Name: `--xml`
* Shortcut: <none>
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: To output list as XML
* Default: `false`

**raw:**

* Name: `--raw`
* Shortcut: <none>
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: To output raw command list
* Default: `false`

**format:**

* Name: `--format`
* Shortcut: <none>
* Accept value: yes
* Is value required: yes
* Is multiple: no
* Description: To output list in other formats
* Default: `'txt'`

descriptor:command1
-------------------

* Description: command 1 description
* Usage: `descriptor:command1`
* Aliases: `alias1`, `alias2`

command 1 help

### Options:

**help:**

* Name: `--help`
* Shortcut: `-h`
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: Display this help message.
* Default: `false`

**quiet:**

* Name: `--quiet`
* Shortcut: `-q`
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: Do not output any message.
* Default: `false`

**verbose:**

* Name: `--verbose`
* Shortcut: `-v|-vv|-vvv`
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
* Default: `false`

**version:**

* Name: `--version`
* Shortcut: `-V`
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: Display this application version.
* Default: `false`

**ansi:**

* Name: `--ansi`
* Shortcut: <none>
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: Force ANSI output.
* Default: `false`

**no-ansi:**

* Name: `--no-ansi`
* Shortcut: <none>
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: Disable ANSI output.
* Default: `false`

**no-interaction:**

* Name: `--no-interaction`
* Shortcut: `-n`
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: Do not ask any interactive question.
* Default: `false`

descriptor:command2
-------------------

* Description: command 2 description
* Usage: `descriptor:command2 [-o|--option_name] argument_name`
* Aliases: <none>

command 2 help

### Arguments:

**argument_name:**

* Name: argument_name
* Is required: yes
* Is array: no
* Description: <none>
* Default: `NULL`

### Options:

**option_name:**

* Name: `--option_name`
* Shortcut: `-o`
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: <none>
* Default: `false`

**help:**

* Name: `--help`
* Shortcut: `-h`
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: Display this help message.
* Default: `false`

**quiet:**

* Name: `--quiet`
* Shortcut: `-q`
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: Do not output any message.
* Default: `false`

**verbose:**

* Name: `--verbose`
* Shortcut: `-v|-vv|-vvv`
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
* Default: `false`

**version:**

* Name: `--version`
* Shortcut: `-V`
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: Display this application version.
* Default: `false`

**ansi:**

* Name: `--ansi`
* Shortcut: <none>
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: Force ANSI output.
* Default: `false`

**no-ansi:**

* Name: `--no-ansi`
* Shortcut: <none>
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: Disable ANSI output.
* Default: `false`

**no-interaction:**

* Name: `--no-interaction`
* Shortcut: `-n`
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: Do not ask any interactive question.
* Default: `false`
PK��Z��$$Mtest/Console/Symfony/Component/Console/Tests/Fixtures/application_astext2.txtnu�[���<info>Console Tool</info>

<comment>Usage:</comment>
  [options] command [arguments]

<comment>Options:</comment>
  <info>--help</info>           <info>-h</info> Display this help message.
  <info>--quiet</info>          <info>-q</info> Do not output any message.
  <info>--verbose</info>        <info>-v|vv|vvv</info> Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
  <info>--version</info>        <info>-V</info> Display this application version.
  <info>--ansi</info>              Force ANSI output.
  <info>--no-ansi</info>           Disable ANSI output.
  <info>--no-interaction</info> <info>-n</info> Do not ask any interactive question.

<comment>Available commands for the "foo" namespace:</comment>
  <info>foo:bar  </info> The foo:bar command
PK��Zg��/11Jtest/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_2.txtnu�[��� <info>argument_name</info> argument description
PK��Z[��%��Dtest/Console/Symfony/Component/Console/Tests/Fixtures/command_1.jsonnu�[���{"name":"descriptor:command1","usage":"descriptor:command1","description":"command 1 description","help":"command 1 help","aliases":["alias1","alias2"],"definition":{"arguments":[],"options":[]}}
PK��Z�Z�o��Ftest/Console/Symfony/Component/Console/Tests/Fixtures/application_1.mdnu�[���UNKNOWN
=======

* help
* list

help
----

* Description: Displays help for a command
* Usage: `help [--xml] [--format="..."] [--raw] [command_name]`
* Aliases: <none>

The <info>help</info> command displays help for a given command:

  <info>php app/console help list</info>

You can also output the help in other formats by using the <comment>--format</comment> option:

  <info>php app/console help --format=xml list</info>

To display the list of available commands, please use the <info>list</info> command.

### Arguments:

**command_name:**

* Name: command_name
* Is required: no
* Is array: no
* Description: The command name
* Default: `'help'`

### Options:

**xml:**

* Name: `--xml`
* Shortcut: <none>
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: To output help as XML
* Default: `false`

**format:**

* Name: `--format`
* Shortcut: <none>
* Accept value: yes
* Is value required: yes
* Is multiple: no
* Description: To output help in other formats
* Default: `'txt'`

**raw:**

* Name: `--raw`
* Shortcut: <none>
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: To output raw command help
* Default: `false`

**help:**

* Name: `--help`
* Shortcut: `-h`
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: Display this help message.
* Default: `false`

**quiet:**

* Name: `--quiet`
* Shortcut: `-q`
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: Do not output any message.
* Default: `false`

**verbose:**

* Name: `--verbose`
* Shortcut: `-v|-vv|-vvv`
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
* Default: `false`

**version:**

* Name: `--version`
* Shortcut: `-V`
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: Display this application version.
* Default: `false`

**ansi:**

* Name: `--ansi`
* Shortcut: <none>
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: Force ANSI output.
* Default: `false`

**no-ansi:**

* Name: `--no-ansi`
* Shortcut: <none>
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: Disable ANSI output.
* Default: `false`

**no-interaction:**

* Name: `--no-interaction`
* Shortcut: `-n`
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: Do not ask any interactive question.
* Default: `false`

list
----

* Description: Lists commands
* Usage: `list [--xml] [--raw] [--format="..."] [namespace]`
* Aliases: <none>

The <info>list</info> command lists all commands:

  <info>php app/console list</info>

You can also display the commands for a specific namespace:

  <info>php app/console list test</info>

You can also output the information in other formats by using the <comment>--format</comment> option:

  <info>php app/console list --format=xml</info>

It's also possible to get raw list of commands (useful for embedding command runner):

  <info>php app/console list --raw</info>

### Arguments:

**namespace:**

* Name: namespace
* Is required: no
* Is array: no
* Description: The namespace name
* Default: `NULL`

### Options:

**xml:**

* Name: `--xml`
* Shortcut: <none>
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: To output list as XML
* Default: `false`

**raw:**

* Name: `--raw`
* Shortcut: <none>
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: To output raw command list
* Default: `false`

**format:**

* Name: `--format`
* Shortcut: <none>
* Accept value: yes
* Is value required: yes
* Is multiple: no
* Description: To output list in other formats
* Default: `'txt'`
PK��Zia����Jtest/Console/Symfony/Component/Console/Tests/Fixtures/definition_asxml.txtnu�[���<?xml version="1.0" encoding="UTF-8"?>
<definition>
  <arguments>
    <argument name="foo" is_required="0" is_array="0">
      <description>The foo argument</description>
      <defaults/>
    </argument>
    <argument name="baz" is_required="0" is_array="0">
      <description>The baz argument</description>
      <defaults>
        <default>true</default>
      </defaults>
    </argument>
    <argument name="bar" is_required="0" is_array="1">
      <description>The bar argument</description>
      <defaults>
        <default>bar</default>
      </defaults>
    </argument>
  </arguments>
  <options>
    <option name="--foo" shortcut="-f" accept_value="1" is_value_required="1" is_multiple="0">
      <description>The foo option</description>
      <defaults/>
    </option>
    <option name="--baz" shortcut="" accept_value="1" is_value_required="0" is_multiple="0">
      <description>The baz option</description>
      <defaults>
        <default>false</default>
      </defaults>
    </option>
    <option name="--bar" shortcut="-b" accept_value="1" is_value_required="0" is_multiple="0">
      <description>The bar option</description>
      <defaults>
        <default>bar</default>
      </defaults>
    </option>
  </options>
</definition>
PK��Z�_�n��Jtest/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_1.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<argument name="argument_name" is_required="1" is_array="0">
  <description></description>
  <defaults/>
</argument>
PK��Z�: 8��Jtest/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_3.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<argument name="argument_name" is_required="0" is_array="0">
  <description>argument description</description>
  <defaults>
    <default>default_value</default>
  </defaults>
</argument>
PK��Z��-��_test/Console/Symfony/Component/Console/Tests/Fixtures/application_renderexception3decorated.txtnu�[���

                           
  [Exception]              
  Third exception comment  
                           




                            
  [Exception]               
  Second exception comment  
                            




                                       
  [Exception]                          
  First exception <p>this is html</p>  
                                       


foo3:bar


PK��Z�@�]"]"Gtest/Console/Symfony/Component/Console/Tests/Fixtures/application_2.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<symfony name="My Symfony application" version="v1.0">
  <commands>
    <command id="help" name="help">
      <usage>help [--xml] [--format="..."] [--raw] [command_name]</usage>
      <description>Displays help for a command</description>
      <help>The &lt;info&gt;help&lt;/info&gt; command displays help for a given command:
 
   &lt;info&gt;php app/console help list&lt;/info&gt;
 
 You can also output the help in other formats by using the &lt;comment&gt;--format&lt;/comment&gt; option:
 
   &lt;info&gt;php app/console help --format=xml list&lt;/info&gt;
 
 To display the list of available commands, please use the &lt;info&gt;list&lt;/info&gt; command.</help>
      <aliases/>
      <arguments>
        <argument name="command_name" is_required="0" is_array="0">
          <description>The command name</description>
          <defaults>
            <default>help</default>
          </defaults>
        </argument>
      </arguments>
      <options>
        <option name="--xml" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>To output help as XML</description>
        </option>
        <option name="--format" shortcut="" accept_value="1" is_value_required="1" is_multiple="0">
          <description>To output help in other formats</description>
          <defaults>
            <default>txt</default>
          </defaults>
        </option>
        <option name="--raw" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>To output raw command help</description>
        </option>
        <option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Display this help message.</description>
        </option>
        <option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Do not output any message.</description>
        </option>
        <option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description>
        </option>
        <option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Display this application version.</description>
        </option>
        <option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Force ANSI output.</description>
        </option>
        <option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Disable ANSI output.</description>
        </option>
        <option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Do not ask any interactive question.</description>
        </option>
      </options>
    </command>
    <command id="list" name="list">
      <usage>list [--xml] [--raw] [--format="..."] [namespace]</usage>
      <description>Lists commands</description>
      <help>The &lt;info&gt;list&lt;/info&gt; command lists all commands:
 
   &lt;info&gt;php app/console list&lt;/info&gt;
 
 You can also display the commands for a specific namespace:
 
   &lt;info&gt;php app/console list test&lt;/info&gt;
 
 You can also output the information in other formats by using the &lt;comment&gt;--format&lt;/comment&gt; option:
 
   &lt;info&gt;php app/console list --format=xml&lt;/info&gt;
 
 It's also possible to get raw list of commands (useful for embedding command runner):
 
   &lt;info&gt;php app/console list --raw&lt;/info&gt;</help>
      <aliases/>
      <arguments>
        <argument name="namespace" is_required="0" is_array="0">
          <description>The namespace name</description>
          <defaults/>
        </argument>
      </arguments>
      <options>
        <option name="--xml" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>To output list as XML</description>
        </option>
        <option name="--raw" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>To output raw command list</description>
        </option>
        <option name="--format" shortcut="" accept_value="1" is_value_required="1" is_multiple="0">
          <description>To output list in other formats</description>
          <defaults>
            <default>txt</default>
          </defaults>
        </option>
      </options>
    </command>
    <command id="descriptor:command1" name="descriptor:command1">
      <usage>descriptor:command1</usage>
      <description>command 1 description</description>
      <help>command 1 help</help>
      <aliases>
        <alias>alias1</alias>
        <alias>alias2</alias>
      </aliases>
      <arguments/>
      <options>
        <option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Display this help message.</description>
        </option>
        <option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Do not output any message.</description>
        </option>
        <option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description>
        </option>
        <option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Display this application version.</description>
        </option>
        <option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Force ANSI output.</description>
        </option>
        <option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Disable ANSI output.</description>
        </option>
        <option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Do not ask any interactive question.</description>
        </option>
      </options>
    </command>
    <command id="descriptor:command2" name="descriptor:command2">
      <usage>descriptor:command2 [-o|--option_name] argument_name</usage>
      <description>command 2 description</description>
      <help>command 2 help</help>
      <aliases/>
      <arguments>
        <argument name="argument_name" is_required="1" is_array="0">
          <description></description>
          <defaults/>
        </argument>
      </arguments>
      <options>
        <option name="--option_name" shortcut="-o" accept_value="0" is_value_required="0" is_multiple="0">
          <description></description>
        </option>
        <option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Display this help message.</description>
        </option>
        <option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Do not output any message.</description>
        </option>
        <option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description>
        </option>
        <option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Display this application version.</description>
        </option>
        <option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Force ANSI output.</description>
        </option>
        <option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Disable ANSI output.</description>
        </option>
        <option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Do not ask any interactive question.</description>
        </option>
      </options>
    </command>
  </commands>
  <namespaces>
    <namespace id="_global">
      <command>alias1</command>
      <command>alias2</command>
      <command>help</command>
      <command>list</command>
    </namespace>
    <namespace id="descriptor">
      <command>descriptor:command1</command>
      <command>descriptor:command2</command>
    </namespace>
  </namespaces>
</symfony>
PK��Z�K@�bbHtest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_2.txtnu�[��� <info>--option_name</info> (-o) option description<comment> (default: "default_value")</comment>
PK��Zp�����Ktest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_3.mdnu�[���### Options:

**option_name:**

* Name: `--option_name`
* Shortcut: `-o`
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: <none>
* Default: `false`
PK��Z�A�(ffCtest/Console/Symfony/Component/Console/Tests/Fixtures/command_2.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<command id="descriptor:command2" name="descriptor:command2">
  <usage>descriptor:command2 [-o|--option_name] argument_name</usage>
  <description>command 2 description</description>
  <help>command 2 help</help>
  <aliases/>
  <arguments>
    <argument name="argument_name" is_required="1" is_array="0">
      <description></description>
      <defaults/>
    </argument>
  </arguments>
  <options>
    <option name="--option_name" shortcut="-o" accept_value="0" is_value_required="0" is_multiple="0">
      <description></description>
    </option>
  </options>
</command>
PK��Z��,���Ktest/Console/Symfony/Component/Console/Tests/Fixtures/definition_astext.txtnu�[���<comment>Arguments:</comment>
 <info>foo       </info> The foo argument
 <info>baz       </info> The baz argument<comment> (default: true)</comment>
 <info>bar       </info> The bar argument<comment> (default: ["http://foo.com/"])</comment>

<comment>Options:</comment>
 <info>--foo</info> (-f) The foo option
 <info>--baz</info>      The baz option<comment> (default: false)</comment>
 <info>--bar</info> (-b) The bar option<comment> (default: "bar")</comment>
 <info>--qux</info>      The qux option<comment> (default: ["http://foo.com/","bar"])</comment><comment> (multiple values allowed)</comment>
 <info>--qux2</info>     The qux2 option<comment> (default: {"foo":"bar"})</comment><comment> (multiple values allowed)</comment>
PK��Z�I���Htest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_4.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<option name="--option_name" shortcut="-o" accept_value="1" is_value_required="0" is_multiple="1">
  <description>option description</description>
  <defaults/>
</option>
PK��Zu$´!!Htest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_1.txtnu�[��� <info>--option_name</info> (-o)
PK��Z���$$Mtest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_4.jsonnu�[���{"arguments":{"argument_name":{"name":"argument_name","is_required":true,"is_array":false,"description":"","default":null}},"options":{"option_name":{"name":"--option_name","shortcut":"-o","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"","default":false}}}
PK��Z3�P���Ltest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_2.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<definition>
  <arguments>
    <argument name="argument_name" is_required="1" is_array="0">
      <description></description>
      <defaults/>
    </argument>
  </arguments>
  <options/>
</definition>
PK��ZѸ�;;Ltest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_2.txtnu�[���<comment>Arguments:</comment>
 <info>argument_name </info>
PK��Z��a66Gtest/Console/Symfony/Component/Console/Tests/Fixtures/application_1.txtnu�[���<info>Console Tool</info>

<comment>Usage:</comment>
  [options] command [arguments]

<comment>Options:</comment>
  <info>--help</info>           <info>-h</info> Display this help message.
  <info>--quiet</info>          <info>-q</info> Do not output any message.
  <info>--verbose</info>        <info>-v|vv|vvv</info> Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
  <info>--version</info>        <info>-V</info> Display this application version.
  <info>--ansi</info>              Force ANSI output.
  <info>--no-ansi</info>           Disable ANSI output.
  <info>--no-interaction</info> <info>-n</info> Do not ask any interactive question.

<comment>Available commands:</comment>
  <info>help  </info> Displays help for a command
  <info>list  </info> Lists commands
PK��Z����Mtest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_1.jsonnu�[���{"arguments":[],"options":[]}
PK��ZX� �,,Jtest/Console/Symfony/Component/Console/Tests/Fixtures/application_run2.txtnu�[���Usage:
 help [--xml] [--format="..."] [--raw] [command_name]

Arguments:
 command               The command to execute
 command_name          The command name (default: "help")

Options:
 --xml                 To output help as XML
 --format              To output help in other formats (default: "txt")
 --raw                 To output raw command help
 --help (-h)           Display this help message.
 --quiet (-q)          Do not output any message.
 --verbose (-v|vv|vvv) Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
 --version (-V)        Display this application version.
 --ansi                Force ANSI output.
 --no-ansi             Disable ANSI output.
 --no-interaction (-n) Do not ask any interactive question.

Help:
 The help command displays help for a given command:
 
   php app/console help list
 
 You can also output the help in other formats by using the --format option:
 
   php app/console help --format=xml list
 
 To display the list of available commands, please use the list command.
PK��Z󚲱}}Ktest/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_3.jsonnu�[���{"name":"argument_name","is_required":false,"is_array":false,"description":"argument description","default":"default_value"}
PK��Z1"8MMPtest/Console/Symfony/Component/Console/Tests/Fixtures/DescriptorApplication2.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Fixtures;

use Symfony\Component\Console\Application;

class DescriptorApplication2 extends Application
{
    public function __construct()
    {
        parent::__construct('My Symfony application', 'v1.0');
        $this->add(new DescriptorCommand1());
        $this->add(new DescriptorCommand2());
    }
}
PK��Z#ɤb��Mtest/Console/Symfony/Component/Console/Tests/Fixtures/application_gethelp.txtnu�[���<info>Console Tool</info>

<comment>Usage:</comment>
  [options] command [arguments]

<comment>Options:</comment>
  <info>--help</info>           <info>-h</info> Display this help message.
  <info>--quiet</info>          <info>-q</info> Do not output any message.
  <info>--verbose</info>        <info>-v|vv|vvv</info> Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
  <info>--version</info>        <info>-V</info> Display this application version.
  <info>--ansi</info>              Force ANSI output.
  <info>--no-ansi</info>           Disable ANSI output.
  <info>--no-interaction</info> <info>-n</info> Do not ask any interactive question.PK��Z�(���Gtest/Console/Symfony/Component/Console/Tests/Fixtures/application_2.txtnu�[���<info>My Symfony application</info> version <comment>v1.0</comment>

<comment>Usage:</comment>
  [options] command [arguments]

<comment>Options:</comment>
  <info>--help</info>           <info>-h</info> Display this help message.
  <info>--quiet</info>          <info>-q</info> Do not output any message.
  <info>--verbose</info>        <info>-v|vv|vvv</info> Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
  <info>--version</info>        <info>-V</info> Display this application version.
  <info>--ansi</info>              Force ANSI output.
  <info>--no-ansi</info>           Disable ANSI output.
  <info>--no-interaction</info> <info>-n</info> Do not ask any interactive question.

<comment>Available commands:</comment>
  <info>alias1               </info> command 1 description
  <info>alias2               </info> command 1 description
  <info>help                 </info> Displays help for a command
  <info>list                 </info> Lists commands
<comment>descriptor</comment>
  <info>descriptor:command1  </info> command 1 description
  <info>descriptor:command2  </info> command 2 description
PK��Z;`�MLtest/Console/Symfony/Component/Console/Tests/Fixtures/application_asxml1.txtnu�[���<?xml version="1.0" encoding="UTF-8"?>
<symfony>
  <commands>
    <command id="help" name="help">
  <usage>help [--xml] [--format="..."] [--raw] [command_name]</usage>
  <description>Displays help for a command</description>
  <help>The &lt;info&gt;help&lt;/info&gt; command displays help for a given command:
 
   &lt;info&gt;php app/console help list&lt;/info&gt;
 
 You can also output the help in other formats by using the &lt;comment&gt;--format&lt;/comment&gt; option:
 
   &lt;info&gt;php app/console help --format=xml list&lt;/info&gt;
 
 To display the list of available commands, please use the &lt;info&gt;list&lt;/info&gt; command.</help>
  <aliases />
  <arguments>
    <argument name="command_name" is_required="0" is_array="0">
      <description>The command name</description>
      <defaults>
        <default>help</default>
      </defaults>
    </argument>
  </arguments>
  <options>
    <option name="--xml" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
      <description>To output help as XML</description>
    </option>
    <option name="--format" shortcut="" accept_value="1" is_value_required="1" is_multiple="0">
      <description>To output help in other formats</description>
      <defaults>
        <default>txt</default>
      </defaults>
    </option>
    <option name="--raw" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
      <description>To output raw command help</description>
    </option>
    <option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0">
      <description>Display this help message.</description>
    </option>
    <option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0">
      <description>Do not output any message.</description>
    </option>
    <option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0">
      <description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description>
    </option>
    <option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0">
      <description>Display this application version.</description>
    </option>
    <option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
      <description>Force ANSI output.</description>
    </option>
    <option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
      <description>Disable ANSI output.</description>
    </option>
    <option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0">
      <description>Do not ask any interactive question.</description>
    </option>
  </options>
</command>
    <command id="list" name="list">
  <usage>list [--xml] [--raw] [--format="..."] [namespace]</usage>
  <description>Lists commands</description>
  <help>The &lt;info&gt;list&lt;/info&gt; command lists all commands:
 
   &lt;info&gt;php app/console list&lt;/info&gt;
 
 You can also display the commands for a specific namespace:
 
   &lt;info&gt;php app/console list test&lt;/info&gt;
 
 You can also output the information in other formats by using the &lt;comment&gt;--format&lt;/comment&gt; option:
 
   &lt;info&gt;php app/console list --format=xml&lt;/info&gt;
 
 It's also possible to get raw list of commands (useful for embedding command runner):
 
   &lt;info&gt;php app/console list --raw&lt;/info&gt;</help>
  <aliases/>
  <arguments>
    <argument name="namespace" is_required="0" is_array="0">
      <description>The namespace name</description>
      <defaults/>
    </argument>
  </arguments>
  <options>
    <option name="--xml" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
      <description>To output list as XML</description>
    </option>
    <option name="--raw" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
      <description>To output raw command list</description>
    </option>
    <option name="--format" shortcut="" accept_value="1" is_value_required="1" is_multiple="0">
      <description>To output list in other formats</description>
      <defaults>
        <default>txt</default>
      </defaults>
    </option>
  </options>
</command>
    <command id="foo:bar" name="foo:bar">
  <usage>foo:bar</usage>
  <description>The foo:bar command</description>
  <help/>
  <aliases>
    <alias>afoobar</alias>
  </aliases>
  <arguments/>
    <options>
      <option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0">
        <description>Display this help message.</description>
      </option>
      <option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0">
        <description>Do not output any message.</description>
      </option>
      <option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0">
        <description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description>
      </option>
      <option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0">
        <description>Display this application version.</description>
      </option>
      <option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
        <description>Force ANSI output.</description>
      </option>
      <option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
        <description>Disable ANSI output.</description>
      </option>
      <option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0">
        <description>Do not ask any interactive question.</description>
      </option>
    </options>
</command>
  </commands>
  <namespaces>
    <namespace id="_global">
      <command>afoobar</command>
      <command>help</command>
      <command>list</command>
    </namespace>
    <namespace id="foo">
      <command>foo:bar</command>
    </namespace>
  </namespaces>
</symfony>
PK��ZW��،�Itest/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_3.mdnu�[���**argument_name:**

* Name: argument_name
* Is required: no
* Is array: no
* Description: argument description
* Default: `'default_value'`
PK��Z��X��Itest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_1.jsonnu�[���{"name":"--option_name","shortcut":"-o","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"","default":false}
PK��Z�
c�Dtest/Console/Symfony/Component/Console/Tests/Fixtures/FooCommand.phpnu�[���<?php

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class FooCommand extends Command
{
    public $input;
    public $output;

    protected function configure()
    {
        $this
            ->setName('foo:bar')
            ->setDescription('The foo:bar command')
            ->setAliases(array('afoobar'))
        ;
    }

    protected function interact(InputInterface $input, OutputInterface $output)
    {
        $output->writeln('interact called');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $this->input = $input;
        $this->output = $output;

        $output->writeln('called');
    }
}
PK��ZG u=��Vtest/Console/Symfony/Component/Console/Tests/Fixtures/application_renderexception3.txtnu�[���

                           
  [Exception]              
  Third exception comment  
                           




                            
  [Exception]               
  Second exception comment  
                            




                                       
  [Exception]                          
  First exception <p>this is html</p>  
                                       


foo3:bar


PK��ZKtest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_1.mdnu�[���PK��Z���==Ltest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_3.txtnu�[���<comment>Options:</comment>
 <info>--option_name</info> (-o)
PK��Z�����Htest/Console/Symfony/Component/Console/Tests/Fixtures/command_astext.txtnu�[���<comment>Usage:</comment>
 namespace:name

<comment>Aliases:</comment> <info>name</info>
<comment>Arguments:</comment>
 <info>command              </info> The command to execute

<comment>Options:</comment>
 <info>--help</info> (-h)           Display this help message.
 <info>--quiet</info> (-q)          Do not output any message.
 <info>--verbose</info> (-v|vv|vvv) Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
 <info>--version</info> (-V)        Display this application version.
 <info>--ansi</info>                Force ANSI output.
 <info>--no-ansi</info>             Disable ANSI output.
 <info>--no-interaction</info> (-n) Do not ask any interactive question.

<comment>Help:</comment>
 help
PK��Z�J�2Htest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_2.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<option name="--option_name" shortcut="-o" accept_value="1" is_value_required="0" is_multiple="0">
  <description>option description</description>
  <defaults>
    <default>default_value</default>
  </defaults>
</option>
PK��Zl�T���Gtest/Console/Symfony/Component/Console/Tests/Fixtures/application_1.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<symfony>
  <commands>
    <command id="help" name="help">
      <usage>help [--xml] [--format="..."] [--raw] [command_name]</usage>
      <description>Displays help for a command</description>
      <help>The &lt;info&gt;help&lt;/info&gt; command displays help for a given command:
 
   &lt;info&gt;php app/console help list&lt;/info&gt;
 
 You can also output the help in other formats by using the &lt;comment&gt;--format&lt;/comment&gt; option:
 
   &lt;info&gt;php app/console help --format=xml list&lt;/info&gt;
 
 To display the list of available commands, please use the &lt;info&gt;list&lt;/info&gt; command.</help>
      <aliases/>
      <arguments>
        <argument name="command_name" is_required="0" is_array="0">
          <description>The command name</description>
          <defaults>
            <default>help</default>
          </defaults>
        </argument>
      </arguments>
      <options>
        <option name="--xml" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>To output help as XML</description>
        </option>
        <option name="--format" shortcut="" accept_value="1" is_value_required="1" is_multiple="0">
          <description>To output help in other formats</description>
          <defaults>
            <default>txt</default>
          </defaults>
        </option>
        <option name="--raw" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>To output raw command help</description>
        </option>
        <option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Display this help message.</description>
        </option>
        <option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Do not output any message.</description>
        </option>
        <option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description>
        </option>
        <option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Display this application version.</description>
        </option>
        <option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Force ANSI output.</description>
        </option>
        <option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Disable ANSI output.</description>
        </option>
        <option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Do not ask any interactive question.</description>
        </option>
      </options>
    </command>
    <command id="list" name="list">
      <usage>list [--xml] [--raw] [--format="..."] [namespace]</usage>
      <description>Lists commands</description>
      <help>The &lt;info&gt;list&lt;/info&gt; command lists all commands:
 
   &lt;info&gt;php app/console list&lt;/info&gt;
 
 You can also display the commands for a specific namespace:
 
   &lt;info&gt;php app/console list test&lt;/info&gt;
 
 You can also output the information in other formats by using the &lt;comment&gt;--format&lt;/comment&gt; option:
 
   &lt;info&gt;php app/console list --format=xml&lt;/info&gt;
 
 It's also possible to get raw list of commands (useful for embedding command runner):
 
   &lt;info&gt;php app/console list --raw&lt;/info&gt;</help>
      <aliases/>
      <arguments>
        <argument name="namespace" is_required="0" is_array="0">
          <description>The namespace name</description>
          <defaults/>
        </argument>
      </arguments>
      <options>
        <option name="--xml" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>To output list as XML</description>
        </option>
        <option name="--raw" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>To output raw command list</description>
        </option>
        <option name="--format" shortcut="" accept_value="1" is_value_required="1" is_multiple="0">
          <description>To output list in other formats</description>
          <defaults>
            <default>txt</default>
          </defaults>
        </option>
      </options>
    </command>
  </commands>
  <namespaces>
    <namespace id="_global">
      <command>help</command>
      <command>list</command>
    </namespace>
  </namespaces>
</symfony>
PK��Z�Y-͡�Gtest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_1.mdnu�[���**option_name:**

* Name: `--option_name`
* Shortcut: `-o`
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: <none>
* Default: `false`
PK��Z(?hJtest/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_1.txtnu�[��� <info>argument_name</info>
PK��Z�e::Jtest/Console/Symfony/Component/Console/Tests/Fixtures/application_run1.txtnu�[���Console Tool

Usage:
  [options] command [arguments]

Options:
  --help           -h Display this help message.
  --quiet          -q Do not output any message.
  --verbose        -v|vv|vvv Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
  --version        -V Display this application version.
  --ansi              Force ANSI output.
  --no-ansi           Disable ANSI output.
  --no-interaction -n Do not ask any interactive question.

Available commands:
  help   Displays help for a command
  list   Lists commands
PK��Z��x�44Htest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_3.txtnu�[��� <info>--option_name</info> (-o) option description
PK��Z6 �_AAEtest/Console/Symfony/Component/Console/Tests/Fixtures/Foo3Command.phpnu�[���<?php

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class Foo3Command extends Command
{
    protected function configure()
    {
        $this
            ->setName('foo3:bar')
            ->setDescription('The foo3:bar command')
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        try {
            try {
                throw new \Exception("First exception <p>this is html</p>");
            } catch (\Exception $e) {
                throw new \Exception("Second exception <comment>comment</comment>", 0, $e);
            }
        } catch (\Exception $e) {
            throw new \Exception("Third exception <fg=blue;bg=red>comment</>", 0, $e);
        }
    }
}
PK��Z��I��Itest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_3.jsonnu�[���{"name":"--option_name","shortcut":"-o","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"option description","default":null}
PK��ZXz�??Ltest/Console/Symfony/Component/Console/Tests/Fixtures/DescriptorCommand2.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Fixtures;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;

class DescriptorCommand2 extends Command
{
    protected function configure()
    {
        $this
            ->setName('descriptor:command2')
            ->setDescription('command 2 description')
            ->setHelp('command 2 help')
            ->addArgument('argument_name', InputArgument::REQUIRED)
            ->addOption('option_name', 'o', InputOption::VALUE_NONE)
        ;
    }
}
PK��Z*[Ǿ44Ktest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_4.mdnu�[���### Arguments:

**argument_name:**

* Name: argument_name
* Is required: yes
* Is array: no
* Description: <none>
* Default: `NULL`

### Options:

**option_name:**

* Name: `--option_name`
* Shortcut: `-o`
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: <none>
* Default: `false`
PK��Z	�Ӹ�Gtest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_2.mdnu�[���**option_name:**

* Name: `--option_name`
* Shortcut: `-o`
* Accept value: yes
* Is value required: no
* Is multiple: no
* Description: option description
* Default: `'default_value'`
PK��Z��U���Btest/Console/Symfony/Component/Console/Tests/Fixtures/command_2.mdnu�[���descriptor:command2
-------------------

* Description: command 2 description
* Usage: `descriptor:command2 [-o|--option_name] argument_name`
* Aliases: <none>

command 2 help

### Arguments:

**argument_name:**

* Name: argument_name
* Is required: yes
* Is array: no
* Description: <none>
* Default: `NULL`

### Options:

**option_name:**

* Name: `--option_name`
* Shortcut: `-o`
* Accept value: no
* Is value required: no
* Is multiple: no
* Description: <none>
* Default: `false`
PK��Z8�UT

Jtest/Console/Symfony/Component/Console/Tests/Fixtures/application_run4.txtnu�[���Console Tool
PK��Z1G~"//Gtest/Console/Symfony/Component/Console/Tests/Fixtures/FoobarCommand.phpnu�[���<?php

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class FoobarCommand extends Command
{
    public $input;
    public $output;

    protected function configure()
    {
        $this
            ->setName('foobar:foo')
            ->setDescription('The foobar:foo command')
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $this->input = $input;
        $this->output = $output;
    }
}
PK��Z�/""��Etest/Console/Symfony/Component/Console/Tests/Fixtures/Foo5Command.phpnu�[���<?php

use Symfony\Component\Console\Command\Command;

class Foo5Command extends Command
{
    public function __construct()
    {
    }
}
PK��Z�Xl��Vtest/Console/Symfony/Component/Console/Tests/Fixtures/application_renderexception4.txtnu�[���

                               
  [InvalidArgumentException]   
  Command "foo" is not define  
  d.                           
                               


PK��Z*�q��Mtest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_3.jsonnu�[���{"arguments":[],"options":{"option_name":{"name":"--option_name","shortcut":"-o","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"","default":false}}}
PK��Z��EOOCtest/Console/Symfony/Component/Console/Tests/Fixtures/command_1.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<command id="descriptor:command1" name="descriptor:command1">
  <usage>descriptor:command1</usage>
  <description>command 1 description</description>
  <help>command 1 help</help>
  <aliases>
    <alias>alias1</alias>
    <alias>alias2</alias>
  </aliases>
  <arguments/>
  <options/>
</command>
PK��Z�NY__Jtest/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_3.txtnu�[��� <info>argument_name</info> argument description<comment> (default: "default_value")</comment>
PK��Z�����Mtest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_2.jsonnu�[���{"arguments":{"argument_name":{"name":"argument_name","is_required":true,"is_array":false,"description":"","default":null}},"options":[]}
PK��Zh����Ctest/Console/Symfony/Component/Console/Tests/Fixtures/command_2.txtnu�[���<comment>Usage:</comment>
 descriptor:command2 [-o|--option_name] argument_name

<comment>Arguments:</comment>
 <info>argument_name     </info> 

<comment>Options:</comment>
 <info>--option_name</info> (-o) 

<comment>Help:</comment>
 command 2 help
PK��Z�	���Etest/Console/Symfony/Component/Console/Tests/Fixtures/Foo2Command.phpnu�[���<?php

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class Foo2Command extends Command
{
    protected function configure()
    {
        $this
            ->setName('foo1:bar')
            ->setDescription('The foo1:bar command')
            ->setAliases(array('afoobar2'))
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
    }
}
PK��Z,D���Vtest/Console/Symfony/Component/Console/Tests/Fixtures/application_renderexception2.txtnu�[���

                                      
  [InvalidArgumentException]          
  The "--foo" option does not exist.  
                                      


list [--xml] [--raw] [--format="..."] [namespace]


PK��Z.p�~~Ltest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_4.txtnu�[���<comment>Arguments:</comment>
 <info>argument_name     </info> 

<comment>Options:</comment>
 <info>--option_name</info> (-o)
PK��Z��M��Htest/Console/Symfony/Component/Console/Tests/Fixtures/application_2.jsonnu�[���{"commands":[{"name":"help","usage":"help [--xml] [--format=\"...\"] [--raw] [command_name]","description":"Displays help for a command","help":"The <info>help<\/info> command displays help for a given command:\n\n  <info>php app\/console help list<\/info>\n\nYou can also output the help in other formats by using the <comment>--format<\/comment> option:\n\n  <info>php app\/console help --format=xml list<\/info>\n\nTo display the list of available commands, please use the <info>list<\/info> command.","aliases":[],"definition":{"arguments":{"command_name":{"name":"command_name","is_required":false,"is_array":false,"description":"The command name","default":"help"}},"options":{"xml":{"name":"--xml","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output help as XML","default":false},"format":{"name":"--format","shortcut":"","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"To output help in other formats","default":"txt"},"raw":{"name":"--raw","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output raw command help","default":false},"help":{"name":"--help","shortcut":"-h","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this help message.","default":false},"quiet":{"name":"--quiet","shortcut":"-q","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not output any message.","default":false},"verbose":{"name":"--verbose","shortcut":"-v|-vv|-vvv","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug","default":false},"version":{"name":"--version","shortcut":"-V","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this application version.","default":false},"ansi":{"name":"--ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Force ANSI output.","default":false},"no-ansi":{"name":"--no-ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Disable ANSI output.","default":false},"no-interaction":{"name":"--no-interaction","shortcut":"-n","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not ask any interactive question.","default":false}}}},{"name":"list","usage":"list [--xml] [--raw] [--format=\"...\"] [namespace]","description":"Lists commands","help":"The <info>list<\/info> command lists all commands:\n\n  <info>php app\/console list<\/info>\n\nYou can also display the commands for a specific namespace:\n\n  <info>php app\/console list test<\/info>\n\nYou can also output the information in other formats by using the <comment>--format<\/comment> option:\n\n  <info>php app\/console list --format=xml<\/info>\n\nIt's also possible to get raw list of commands (useful for embedding command runner):\n\n  <info>php app\/console list --raw<\/info>","aliases":[],"definition":{"arguments":{"namespace":{"name":"namespace","is_required":false,"is_array":false,"description":"The namespace name","default":null}},"options":{"xml":{"name":"--xml","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output list as XML","default":false},"raw":{"name":"--raw","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output raw command list","default":false},"format":{"name":"--format","shortcut":"","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"To output list in other formats","default":"txt"}}}},{"name":"descriptor:command1","usage":"descriptor:command1","description":"command 1 description","help":"command 1 help","aliases":["alias1","alias2"],"definition":{"arguments":[],"options":{"help":{"name":"--help","shortcut":"-h","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this help message.","default":false},"quiet":{"name":"--quiet","shortcut":"-q","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not output any message.","default":false},"verbose":{"name":"--verbose","shortcut":"-v|-vv|-vvv","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug","default":false},"version":{"name":"--version","shortcut":"-V","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this application version.","default":false},"ansi":{"name":"--ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Force ANSI output.","default":false},"no-ansi":{"name":"--no-ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Disable ANSI output.","default":false},"no-interaction":{"name":"--no-interaction","shortcut":"-n","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not ask any interactive question.","default":false}}}},{"name":"descriptor:command2","usage":"descriptor:command2 [-o|--option_name] argument_name","description":"command 2 description","help":"command 2 help","aliases":[],"definition":{"arguments":{"argument_name":{"name":"argument_name","is_required":true,"is_array":false,"description":"","default":null}},"options":{"option_name":{"name":"--option_name","shortcut":"-o","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"","default":false},"help":{"name":"--help","shortcut":"-h","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this help message.","default":false},"quiet":{"name":"--quiet","shortcut":"-q","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not output any message.","default":false},"verbose":{"name":"--verbose","shortcut":"-v|-vv|-vvv","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug","default":false},"version":{"name":"--version","shortcut":"-V","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this application version.","default":false},"ansi":{"name":"--ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Force ANSI output.","default":false},"no-ansi":{"name":"--no-ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Disable ANSI output.","default":false},"no-interaction":{"name":"--no-interaction","shortcut":"-n","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not ask any interactive question.","default":false}}}}],"namespaces":[{"id":"_global","commands":["alias1","alias2","help","list"]},{"id":"descriptor","commands":["descriptor:command1","descriptor:command2"]}]}
PK��Z��ttItest/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_1.mdnu�[���**argument_name:**

* Name: argument_name
* Is required: yes
* Is array: no
* Description: <none>
* Default: `NULL`
PK��ZQ��d	d	Mtest/Console/Symfony/Component/Console/Tests/Tester/ApplicationTesterTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Tester;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Output\Output;
use Symfony\Component\Console\Tester\ApplicationTester;

class ApplicationTesterTest extends \PHPUnit_Framework_TestCase
{
    protected $application;
    protected $tester;

    protected function setUp()
    {
        $this->application = new Application();
        $this->application->setAutoExit(false);
        $this->application->register('foo')
            ->addArgument('foo')
            ->setCode(function ($input, $output) { $output->writeln('foo'); })
        ;

        $this->tester = new ApplicationTester($this->application);
        $this->tester->run(array('command' => 'foo', 'foo' => 'bar'), array('interactive' => false, 'decorated' => false, 'verbosity' => Output::VERBOSITY_VERBOSE));
    }

    protected function tearDown()
    {
        $this->application = null;
        $this->tester = null;
    }

    public function testRun()
    {
        $this->assertFalse($this->tester->getInput()->isInteractive(), '->execute() takes an interactive option');
        $this->assertFalse($this->tester->getOutput()->isDecorated(), '->execute() takes a decorated option');
        $this->assertEquals(Output::VERBOSITY_VERBOSE, $this->tester->getOutput()->getVerbosity(), '->execute() takes a verbosity option');
    }

    public function testGetInput()
    {
        $this->assertEquals('bar', $this->tester->getInput()->getArgument('foo'), '->getInput() returns the current input instance');
    }

    public function testGetOutput()
    {
        rewind($this->tester->getOutput()->getStream());
        $this->assertEquals('foo'.PHP_EOL, stream_get_contents($this->tester->getOutput()->getStream()), '->getOutput() returns the current output instance');
    }

    public function testGetDisplay()
    {
        $this->assertEquals('foo'.PHP_EOL, $this->tester->getDisplay(), '->getDisplay() returns the display of the last execution');
    }

    public function testGetStatusCode()
    {
        $this->assertSame(0, $this->tester->getStatusCode(), '->getStatusCode() returns the status code');
    }
}
PK��Z�x0mBBItest/Console/Symfony/Component/Console/Tests/Tester/CommandTesterTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Tester;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Output\Output;
use Symfony\Component\Console\Tester\CommandTester;

class CommandTesterTest extends \PHPUnit_Framework_TestCase
{
    protected $command;
    protected $tester;

    protected function setUp()
    {
        $this->command = new Command('foo');
        $this->command->addArgument('command');
        $this->command->addArgument('foo');
        $this->command->setCode(function ($input, $output) { $output->writeln('foo'); });

        $this->tester = new CommandTester($this->command);
        $this->tester->execute(array('foo' => 'bar'), array('interactive' => false, 'decorated' => false, 'verbosity' => Output::VERBOSITY_VERBOSE));
    }

    protected function tearDown()
    {
        $this->command = null;
        $this->tester = null;
    }

    public function testExecute()
    {
        $this->assertFalse($this->tester->getInput()->isInteractive(), '->execute() takes an interactive option');
        $this->assertFalse($this->tester->getOutput()->isDecorated(), '->execute() takes a decorated option');
        $this->assertEquals(Output::VERBOSITY_VERBOSE, $this->tester->getOutput()->getVerbosity(), '->execute() takes a verbosity option');
    }

    public function testGetInput()
    {
        $this->assertEquals('bar', $this->tester->getInput()->getArgument('foo'), '->getInput() returns the current input instance');
    }

    public function testGetOutput()
    {
        rewind($this->tester->getOutput()->getStream());
        $this->assertEquals('foo'.PHP_EOL, stream_get_contents($this->tester->getOutput()->getStream()), '->getOutput() returns the current output instance');
    }

    public function testGetDisplay()
    {
        $this->assertEquals('foo'.PHP_EOL, $this->tester->getDisplay(), '->getDisplay() returns the display of the last execution');
    }

    public function testGetStatusCode()
    {
        $this->assertSame(0, $this->tester->getStatusCode(), '->getStatusCode() returns the status code');
    }

    public function testCommandFromApplication()
    {
        $application = new Application();
        $application->setAutoExit(false);

        $command = new Command('foo');
        $command->setCode(function ($input, $output) { $output->writeln('foo'); });

        $application->add($command);

        $tester = new CommandTester($application->find('foo'));

        // check that there is no need to pass the command name here
        $this->assertEquals(0, $tester->execute(array()));
    }
}
PK��Z�����Ftest/Console/Symfony/Component/Console/Tests/Input/StringInputTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Input;

use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\StringInput;

class StringInputTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getTokenizeData
     */
    public function testTokenize($input, $tokens, $message)
    {
        $input = new StringInput($input);
        $r = new \ReflectionClass('Symfony\Component\Console\Input\ArgvInput');
        $p = $r->getProperty('tokens');
        $p->setAccessible(true);
        $this->assertEquals($tokens, $p->getValue($input), $message);
    }

    public function testInputOptionWithGivenString()
    {
        $definition = new InputDefinition(
            array(new InputOption('foo', null, InputOption::VALUE_REQUIRED))
        );

        // call to bind
        $input = new StringInput('--foo=bar');
        $input->bind($definition);
        $this->assertEquals('bar', $input->getOption('foo'));

        // definition in constructor
        $input = new StringInput('--foo=bar', $definition);
        $this->assertEquals('bar', $input->getOption('foo'));
    }

    public function getTokenizeData()
    {
        return array(
            array('', array(), '->tokenize() parses an empty string'),
            array('foo', array('foo'), '->tokenize() parses arguments'),
            array('  foo  bar  ', array('foo', 'bar'), '->tokenize() ignores whitespaces between arguments'),
            array('"quoted"', array('quoted'), '->tokenize() parses quoted arguments'),
            array("'quoted'", array('quoted'), '->tokenize() parses quoted arguments'),
            array("'a\rb\nc\td'", array("a\rb\nc\td"), '->tokenize() parses whitespace chars in strings'),
            array("'a'\r'b'\n'c'\t'd'", array('a','b','c','d'), '->tokenize() parses whitespace chars between args as spaces'),
            array('\"quoted\"', array('"quoted"'), '->tokenize() parses escaped-quoted arguments'),
            array("\'quoted\'", array('\'quoted\''), '->tokenize() parses escaped-quoted arguments'),
            array('-a', array('-a'), '->tokenize() parses short options'),
            array('-azc', array('-azc'), '->tokenize() parses aggregated short options'),
            array('-awithavalue', array('-awithavalue'), '->tokenize() parses short options with a value'),
            array('-a"foo bar"', array('-afoo bar'), '->tokenize() parses short options with a value'),
            array('-a"foo bar""foo bar"', array('-afoo barfoo bar'), '->tokenize() parses short options with a value'),
            array('-a\'foo bar\'', array('-afoo bar'), '->tokenize() parses short options with a value'),
            array('-a\'foo bar\'\'foo bar\'', array('-afoo barfoo bar'), '->tokenize() parses short options with a value'),
            array('-a\'foo bar\'"foo bar"', array('-afoo barfoo bar'), '->tokenize() parses short options with a value'),
            array('--long-option', array('--long-option'), '->tokenize() parses long options'),
            array('--long-option=foo', array('--long-option=foo'), '->tokenize() parses long options with a value'),
            array('--long-option="foo bar"', array('--long-option=foo bar'), '->tokenize() parses long options with a value'),
            array('--long-option="foo bar""another"', array('--long-option=foo baranother'), '->tokenize() parses long options with a value'),
            array('--long-option=\'foo bar\'', array('--long-option=foo bar'), '->tokenize() parses long options with a value'),
            array("--long-option='foo bar''another'", array("--long-option=foo baranother"), '->tokenize() parses long options with a value'),
            array("--long-option='foo bar'\"another\"", array("--long-option=foo baranother"), '->tokenize() parses long options with a value'),
            array('foo -a -ffoo --long bar', array('foo', '-a', '-ffoo', '--long', 'bar'), '->tokenize() parses when several arguments and options'),
        );
    }

    public function testToString()
    {
        $input = new StringInput('-f foo');
        $this->assertEquals('-f foo', (string) $input);

        $input = new StringInput('-f --bar=foo "a b c d"');
        $this->assertEquals('-f --bar=foo '.escapeshellarg('a b c d'), (string) $input);

        $input = new StringInput('-f --bar=foo \'a b c d\' '."'A\nB\\'C'");
        $this->assertEquals('-f --bar=foo '.escapeshellarg('a b c d').' '.escapeshellarg("A\nB'C"), (string) $input);
    }
}
PK��Z��p���@test/Console/Symfony/Component/Console/Tests/Input/InputTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Input;

use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;

class InputTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $input = new ArrayInput(array('name' => 'foo'), new InputDefinition(array(new InputArgument('name'))));
        $this->assertEquals('foo', $input->getArgument('name'), '->__construct() takes a InputDefinition as an argument');
    }

    public function testOptions()
    {
        $input = new ArrayInput(array('--name' => 'foo'), new InputDefinition(array(new InputOption('name'))));
        $this->assertEquals('foo', $input->getOption('name'), '->getOption() returns the value for the given option');

        $input->setOption('name', 'bar');
        $this->assertEquals('bar', $input->getOption('name'), '->setOption() sets the value for a given option');
        $this->assertEquals(array('name' => 'bar'), $input->getOptions(), '->getOptions() returns all option values');

        $input = new ArrayInput(array('--name' => 'foo'), new InputDefinition(array(new InputOption('name'), new InputOption('bar', '', InputOption::VALUE_OPTIONAL, '', 'default'))));
        $this->assertEquals('default', $input->getOption('bar'), '->getOption() returns the default value for optional options');
        $this->assertEquals(array('name' => 'foo', 'bar' => 'default'), $input->getOptions(), '->getOptions() returns all option values, even optional ones');
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage The "foo" option does not exist.
     */
    public function testSetInvalidOption()
    {
        $input = new ArrayInput(array('--name' => 'foo'), new InputDefinition(array(new InputOption('name'), new InputOption('bar', '', InputOption::VALUE_OPTIONAL, '', 'default'))));
        $input->setOption('foo', 'bar');
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage The "foo" option does not exist.
     */
    public function testGetInvalidOption()
    {
        $input = new ArrayInput(array('--name' => 'foo'), new InputDefinition(array(new InputOption('name'), new InputOption('bar', '', InputOption::VALUE_OPTIONAL, '', 'default'))));
        $input->getOption('foo');
    }

    public function testArguments()
    {
        $input = new ArrayInput(array('name' => 'foo'), new InputDefinition(array(new InputArgument('name'))));
        $this->assertEquals('foo', $input->getArgument('name'), '->getArgument() returns the value for the given argument');

        $input->setArgument('name', 'bar');
        $this->assertEquals('bar', $input->getArgument('name'), '->setArgument() sets the value for a given argument');
        $this->assertEquals(array('name' => 'bar'), $input->getArguments(), '->getArguments() returns all argument values');

        $input = new ArrayInput(array('name' => 'foo'), new InputDefinition(array(new InputArgument('name'), new InputArgument('bar', InputArgument::OPTIONAL, '', 'default'))));
        $this->assertEquals('default', $input->getArgument('bar'), '->getArgument() returns the default value for optional arguments');
        $this->assertEquals(array('name' => 'foo', 'bar' => 'default'), $input->getArguments(), '->getArguments() returns all argument values, even optional ones');
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage The "foo" argument does not exist.
     */
    public function testSetInvalidArgument()
    {
        $input = new ArrayInput(array('name' => 'foo'), new InputDefinition(array(new InputArgument('name'), new InputArgument('bar', InputArgument::OPTIONAL, '', 'default'))));
        $input->setArgument('foo', 'bar');
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage The "foo" argument does not exist.
     */
    public function testGetInvalidArgument()
    {
        $input = new ArrayInput(array('name' => 'foo'), new InputDefinition(array(new InputArgument('name'), new InputArgument('bar', InputArgument::OPTIONAL, '', 'default'))));
        $input->getArgument('foo');
    }

    /**
     * @expectedException        \RuntimeException
     * @expectedExceptionMessage Not enough arguments.
     */
    public function testValidateWithMissingArguments()
    {
        $input = new ArrayInput(array());
        $input->bind(new InputDefinition(array(new InputArgument('name', InputArgument::REQUIRED))));
        $input->validate();
    }

    public function testValidate()
    {
        $input = new ArrayInput(array('name' => 'foo'));
        $input->bind(new InputDefinition(array(new InputArgument('name', InputArgument::REQUIRED))));

        $this->assertNull($input->validate());
    }

    public function testSetGetInteractive()
    {
        $input = new ArrayInput(array());
        $this->assertTrue($input->isInteractive(), '->isInteractive() returns whether the input should be interactive or not');
        $input->setInteractive(false);
        $this->assertFalse($input->isInteractive(), '->setInteractive() changes the interactive flag');
    }
}
PK��Z�9I;;Dtest/Console/Symfony/Component/Console/Tests/Input/ArgvInputTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Input;

use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;

class ArgvInputTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $_SERVER['argv'] = array('cli.php', 'foo');
        $input = new ArgvInput();
        $r = new \ReflectionObject($input);
        $p = $r->getProperty('tokens');
        $p->setAccessible(true);

        $this->assertEquals(array('foo'), $p->getValue($input), '__construct() automatically get its input from the argv server variable');
    }

    public function testParseArguments()
    {
        $input = new ArgvInput(array('cli.php', 'foo'));
        $input->bind(new InputDefinition(array(new InputArgument('name'))));
        $this->assertEquals(array('name' => 'foo'), $input->getArguments(), '->parse() parses required arguments');

        $input->bind(new InputDefinition(array(new InputArgument('name'))));
        $this->assertEquals(array('name' => 'foo'), $input->getArguments(), '->parse() is stateless');
    }

    /**
     * @dataProvider provideOptions
     */
    public function testParseOptions($input, $options, $expectedOptions, $message)
    {
        $input = new ArgvInput($input);
        $input->bind(new InputDefinition($options));

        $this->assertEquals($expectedOptions, $input->getOptions(), $message);
    }

    public function provideOptions()
    {
        return array(
            array(
                array('cli.php', '--foo'),
                array(new InputOption('foo')),
                array('foo' => true),
                '->parse() parses long options without a value'
            ),
            array(
                array('cli.php', '--foo=bar'),
                array(new InputOption('foo', 'f', InputOption::VALUE_REQUIRED)),
                array('foo' => 'bar'),
                '->parse() parses long options with a required value (with a = separator)'
            ),
            array(
                array('cli.php', '--foo', 'bar'),
                array(new InputOption('foo', 'f', InputOption::VALUE_REQUIRED)),
                array('foo' => 'bar'),
                '->parse() parses long options with a required value (with a space separator)'
            ),
            array(
                array('cli.php', '-f'),
                array(new InputOption('foo', 'f')),
                array('foo' => true),
                '->parse() parses short options without a value'
            ),
            array(
                array('cli.php', '-fbar'),
                array(new InputOption('foo', 'f', InputOption::VALUE_REQUIRED)),
                array('foo' => 'bar'),
                '->parse() parses short options with a required value (with no separator)'
            ),
            array(
                array('cli.php', '-f', 'bar'),
                array(new InputOption('foo', 'f', InputOption::VALUE_REQUIRED)),
                array('foo' => 'bar'),
                '->parse() parses short options with a required value (with a space separator)'
            ),
            array(
                array('cli.php', '-f', ''),
                array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL)),
                array('foo' => ''),
                '->parse() parses short options with an optional empty value'
            ),
            array(
                array('cli.php', '-f', '', 'foo'),
                array(new InputArgument('name'), new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL)),
                array('foo' => ''),
                '->parse() parses short options with an optional empty value followed by an argument'
            ),
            array(
                array('cli.php', '-f', '', '-b'),
                array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputOption('bar', 'b')),
                array('foo' => '', 'bar' => true),
                '->parse() parses short options with an optional empty value followed by an option'
            ),
            array(
                array('cli.php', '-f', '-b', 'foo'),
                array(new InputArgument('name'), new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputOption('bar', 'b')),
                array('foo' => null, 'bar' => true),
                '->parse() parses short options with an optional value which is not present'
            ),
            array(
                array('cli.php', '-fb'),
                array(new InputOption('foo', 'f'), new InputOption('bar', 'b')),
                array('foo' => true, 'bar' => true),
                '->parse() parses short options when they are aggregated as a single one'
            ),
            array(
                array('cli.php', '-fb', 'bar'),
                array(new InputOption('foo', 'f'), new InputOption('bar', 'b', InputOption::VALUE_REQUIRED)),
                array('foo' => true, 'bar' => 'bar'),
                '->parse() parses short options when they are aggregated as a single one and the last one has a required value'
            ),
            array(
                array('cli.php', '-fb', 'bar'),
                array(new InputOption('foo', 'f'), new InputOption('bar', 'b', InputOption::VALUE_OPTIONAL)),
                array('foo' => true, 'bar' => 'bar'),
                '->parse() parses short options when they are aggregated as a single one and the last one has an optional value'
            ),
            array(
                array('cli.php', '-fbbar'),
                array(new InputOption('foo', 'f'), new InputOption('bar', 'b', InputOption::VALUE_OPTIONAL)),
                array('foo' => true, 'bar' => 'bar'),
                '->parse() parses short options when they are aggregated as a single one and the last one has an optional value with no separator'
            ),
            array(
                array('cli.php', '-fbbar'),
                array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputOption('bar', 'b', InputOption::VALUE_OPTIONAL)),
                array('foo' => 'bbar', 'bar' => null),
                '->parse() parses short options when they are aggregated as a single one and one of them takes a value'
            )
        );
    }

    /**
     * @dataProvider provideInvalidInput
     */
    public function testInvalidInput($argv, $definition, $expectedExceptionMessage)
    {
        $this->setExpectedException('RuntimeException', $expectedExceptionMessage);

        $input = new ArgvInput($argv);
        $input->bind($definition);
    }

    public function provideInvalidInput()
    {
        return array(
            array(
                array('cli.php', '--foo'),
                new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_REQUIRED))),
                'The "--foo" option requires a value.'
            ),
            array(
                array('cli.php', '-f'),
                new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_REQUIRED))),
                'The "--foo" option requires a value.'
            ),
            array(
                array('cli.php', '-ffoo'),
                new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_NONE))),
                'The "-o" option does not exist.'
            ),
            array(
                array('cli.php', '--foo=bar'),
                new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_NONE))),
                'The "--foo" option does not accept a value.'
            ),
            array(
                array('cli.php', 'foo', 'bar'),
                new InputDefinition(),
                'Too many arguments.'
            ),
            array(
                array('cli.php', '--foo'),
                new InputDefinition(),
                'The "--foo" option does not exist.'
            ),
            array(
                array('cli.php', '-f'),
                new InputDefinition(),
                'The "-f" option does not exist.'
            ),
            array(
                array('cli.php', '-1'),
                new InputDefinition(array(new InputArgument('number'))),
                'The "-1" option does not exist.'
            )
        );
    }

    public function testParseArrayArgument()
    {
        $input = new ArgvInput(array('cli.php', 'foo', 'bar', 'baz', 'bat'));
        $input->bind(new InputDefinition(array(new InputArgument('name', InputArgument::IS_ARRAY))));

        $this->assertEquals(array('name' => array('foo', 'bar', 'baz', 'bat')), $input->getArguments(), '->parse() parses array arguments');
    }

    public function testParseArrayOption()
    {
        $input = new ArgvInput(array('cli.php', '--name=foo', '--name=bar', '--name=baz'));
        $input->bind(new InputDefinition(array(new InputOption('name', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY))));

        $this->assertEquals(array('name' => array('foo', 'bar', 'baz')), $input->getOptions(), '->parse() parses array options ("--option=value" syntax)');

        $input = new ArgvInput(array('cli.php', '--name', 'foo', '--name', 'bar', '--name', 'baz'));
        $input->bind(new InputDefinition(array(new InputOption('name', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY))));
        $this->assertEquals(array('name' => array('foo', 'bar', 'baz')), $input->getOptions(), '->parse() parses array options ("--option value" syntax)');

        $input = new ArgvInput(array('cli.php', '--name=foo', '--name=bar', '--name='));
        $input->bind(new InputDefinition(array(new InputOption('name', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY))));
        $this->assertSame(array('name' => array('foo', 'bar', null)), $input->getOptions(), '->parse() parses empty array options as null ("--option=value" syntax)');

        $input = new ArgvInput(array('cli.php', '--name', 'foo', '--name', 'bar', '--name', '--anotherOption'));
        $input->bind(new InputDefinition(array(
            new InputOption('name', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY),
            new InputOption('anotherOption', null, InputOption::VALUE_NONE),
        )));
        $this->assertSame(array('name' => array('foo', 'bar', null), 'anotherOption' => true), $input->getOptions(), '->parse() parses empty array options as null ("--option value" syntax)');
    }

    public function testParseNegativeNumberAfterDoubleDash()
    {
        $input = new ArgvInput(array('cli.php', '--', '-1'));
        $input->bind(new InputDefinition(array(new InputArgument('number'))));
        $this->assertEquals(array('number' => '-1'), $input->getArguments(), '->parse() parses arguments with leading dashes as arguments after having encountered a double-dash sequence');

        $input = new ArgvInput(array('cli.php', '-f', 'bar', '--', '-1'));
        $input->bind(new InputDefinition(array(new InputArgument('number'), new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL))));
        $this->assertEquals(array('foo' => 'bar'), $input->getOptions(), '->parse() parses arguments with leading dashes as options before having encountered a double-dash sequence');
        $this->assertEquals(array('number' => '-1'), $input->getArguments(), '->parse() parses arguments with leading dashes as arguments after having encountered a double-dash sequence');
    }

    public function testParseEmptyStringArgument()
    {
        $input = new ArgvInput(array('cli.php', '-f', 'bar', ''));
        $input->bind(new InputDefinition(array(new InputArgument('empty'), new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL))));

        $this->assertEquals(array('empty' => ''), $input->getArguments(), '->parse() parses empty string arguments');
    }

    public function testGetFirstArgument()
    {
        $input = new ArgvInput(array('cli.php', '-fbbar'));
        $this->assertEquals('', $input->getFirstArgument(), '->getFirstArgument() returns the first argument from the raw input');

        $input = new ArgvInput(array('cli.php', '-fbbar', 'foo'));
        $this->assertEquals('foo', $input->getFirstArgument(), '->getFirstArgument() returns the first argument from the raw input');
    }

    public function testHasParameterOption()
    {
        $input = new ArgvInput(array('cli.php', '-f', 'foo'));
        $this->assertTrue($input->hasParameterOption('-f'), '->hasParameterOption() returns true if the given short option is in the raw input');

        $input = new ArgvInput(array('cli.php', '--foo', 'foo'));
        $this->assertTrue($input->hasParameterOption('--foo'), '->hasParameterOption() returns true if the given short option is in the raw input');

        $input = new ArgvInput(array('cli.php', 'foo'));
        $this->assertFalse($input->hasParameterOption('--foo'), '->hasParameterOption() returns false if the given short option is not in the raw input');

        $input = new ArgvInput(array('cli.php', '--foo=bar'));
        $this->assertTrue($input->hasParameterOption('--foo'), '->hasParameterOption() returns true if the given option with provided value is in the raw input');
    }

    public function testToString()
    {
        $input = new ArgvInput(array('cli.php', '-f', 'foo'));
        $this->assertEquals('-f foo', (string) $input);

        $input = new ArgvInput(array('cli.php', '-f', '--bar=foo', 'a b c d', "A\nB'C"));
        $this->assertEquals('-f --bar=foo '.escapeshellarg('a b c d').' '.escapeshellarg("A\nB'C"), (string) $input);
    }

    /**
     * @dataProvider provideGetParameterOptionValues
     */
    public function testGetParameterOptionEqualSign($argv, $key, $expected)
    {
        $input = new ArgvInput($argv);
        $this->assertEquals($expected, $input->getParameterOption($key), '->getParameterOption() returns the expected value');
    }

    public function provideGetParameterOptionValues()
    {
        return array(
            array(array('app/console', 'foo:bar', '-e', 'dev'), '-e', 'dev'),
            array(array('app/console', 'foo:bar', '--env=dev'), '--env', 'dev'),
            array(array('app/console', 'foo:bar', '-e', 'dev'), array('-e', '--env'), 'dev'),
            array(array('app/console', 'foo:bar', '--env=dev'), array('-e', '--env'), 'dev'),
            array(array('app/console', 'foo:bar', '--env=dev', '--en=1'), array('--en'), '1'),
        );
    }

    public function testParseSingleDashAsArgument()
    {
        $input = new ArgvInput(array('cli.php', '-'));
        $input->bind(new InputDefinition(array(new InputArgument('file'))));
        $this->assertEquals(array('file' => '-'), $input->getArguments(), '->parse() parses single dash as an argument');
    }
}
PK��Z��@�H�HJtest/Console/Symfony/Component/Console/Tests/Input/InputDefinitionTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Input;

use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;

class InputDefinitionTest extends \PHPUnit_Framework_TestCase
{
    protected static $fixtures;

    protected $foo, $bar, $foo1, $foo2;

    public static function setUpBeforeClass()
    {
        self::$fixtures = __DIR__.'/../Fixtures/';
    }

    public function testConstructorArguments()
    {
        $this->initializeArguments();

        $definition = new InputDefinition();
        $this->assertEquals(array(), $definition->getArguments(), '__construct() creates a new InputDefinition object');

        $definition = new InputDefinition(array($this->foo, $this->bar));
        $this->assertEquals(array('foo' => $this->foo, 'bar' => $this->bar), $definition->getArguments(), '__construct() takes an array of InputArgument objects as its first argument');
    }

    public function testConstructorOptions()
    {
        $this->initializeOptions();

        $definition = new InputDefinition();
        $this->assertEquals(array(), $definition->getOptions(), '__construct() creates a new InputDefinition object');

        $definition = new InputDefinition(array($this->foo, $this->bar));
        $this->assertEquals(array('foo' => $this->foo, 'bar' => $this->bar), $definition->getOptions(), '__construct() takes an array of InputOption objects as its first argument');
    }

    public function testSetArguments()
    {
        $this->initializeArguments();

        $definition = new InputDefinition();
        $definition->setArguments(array($this->foo));
        $this->assertEquals(array('foo' => $this->foo), $definition->getArguments(), '->setArguments() sets the array of InputArgument objects');
        $definition->setArguments(array($this->bar));

        $this->assertEquals(array('bar' => $this->bar), $definition->getArguments(), '->setArguments() clears all InputArgument objects');
    }

    public function testAddArguments()
    {
        $this->initializeArguments();

        $definition = new InputDefinition();
        $definition->addArguments(array($this->foo));
        $this->assertEquals(array('foo' => $this->foo), $definition->getArguments(), '->addArguments() adds an array of InputArgument objects');
        $definition->addArguments(array($this->bar));
        $this->assertEquals(array('foo' => $this->foo, 'bar' => $this->bar), $definition->getArguments(), '->addArguments() does not clear existing InputArgument objects');
    }

    public function testAddArgument()
    {
        $this->initializeArguments();

        $definition = new InputDefinition();
        $definition->addArgument($this->foo);
        $this->assertEquals(array('foo' => $this->foo), $definition->getArguments(), '->addArgument() adds a InputArgument object');
        $definition->addArgument($this->bar);
        $this->assertEquals(array('foo' => $this->foo, 'bar' => $this->bar), $definition->getArguments(), '->addArgument() adds a InputArgument object');
    }

    /**
     * @expectedException        \LogicException
     * @expectedExceptionMessage An argument with name "foo" already exists.
     */
    public function testArgumentsMustHaveDifferentNames()
    {
        $this->initializeArguments();

        $definition = new InputDefinition();
        $definition->addArgument($this->foo);
        $definition->addArgument($this->foo1);
    }

    /**
     * @expectedException        \LogicException
     * @expectedExceptionMessage Cannot add an argument after an array argument.
     */
    public function testArrayArgumentHasToBeLast()
    {
        $this->initializeArguments();

        $definition = new InputDefinition();
        $definition->addArgument(new InputArgument('fooarray', InputArgument::IS_ARRAY));
        $definition->addArgument(new InputArgument('anotherbar'));
    }

    /**
     * @expectedException        \LogicException
     * @expectedExceptionMessage Cannot add a required argument after an optional one.
     */
    public function testRequiredArgumentCannotFollowAnOptionalOne()
    {
        $this->initializeArguments();

        $definition = new InputDefinition();
        $definition->addArgument($this->foo);
        $definition->addArgument($this->foo2);
    }

    public function testGetArgument()
    {
        $this->initializeArguments();

        $definition = new InputDefinition();
        $definition->addArguments(array($this->foo));
        $this->assertEquals($this->foo, $definition->getArgument('foo'), '->getArgument() returns a InputArgument by its name');
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage The "bar" argument does not exist.
     */
    public function testGetInvalidArgument()
    {
        $this->initializeArguments();

        $definition = new InputDefinition();
        $definition->addArguments(array($this->foo));
        $definition->getArgument('bar');
    }

    public function testHasArgument()
    {
        $this->initializeArguments();

        $definition = new InputDefinition();
        $definition->addArguments(array($this->foo));

        $this->assertTrue($definition->hasArgument('foo'), '->hasArgument() returns true if a InputArgument exists for the given name');
        $this->assertFalse($definition->hasArgument('bar'), '->hasArgument() returns false if a InputArgument exists for the given name');
    }

    public function testGetArgumentRequiredCount()
    {
        $this->initializeArguments();

        $definition = new InputDefinition();
        $definition->addArgument($this->foo2);
        $this->assertEquals(1, $definition->getArgumentRequiredCount(), '->getArgumentRequiredCount() returns the number of required arguments');
        $definition->addArgument($this->foo);
        $this->assertEquals(1, $definition->getArgumentRequiredCount(), '->getArgumentRequiredCount() returns the number of required arguments');
    }

    public function testGetArgumentCount()
    {
        $this->initializeArguments();

        $definition = new InputDefinition();
        $definition->addArgument($this->foo2);
        $this->assertEquals(1, $definition->getArgumentCount(), '->getArgumentCount() returns the number of arguments');
        $definition->addArgument($this->foo);
        $this->assertEquals(2, $definition->getArgumentCount(), '->getArgumentCount() returns the number of arguments');
    }

    public function testGetArgumentDefaults()
    {
        $definition = new InputDefinition(array(
            new InputArgument('foo1', InputArgument::OPTIONAL),
            new InputArgument('foo2', InputArgument::OPTIONAL, '', 'default'),
            new InputArgument('foo3', InputArgument::OPTIONAL | InputArgument::IS_ARRAY),
        //  new InputArgument('foo4', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, '', array(1, 2)),
        ));
        $this->assertEquals(array('foo1' => null, 'foo2' => 'default', 'foo3' => array()), $definition->getArgumentDefaults(), '->getArgumentDefaults() return the default values for each argument');

        $definition = new InputDefinition(array(
            new InputArgument('foo4', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, '', array(1, 2)),
        ));
        $this->assertEquals(array('foo4' => array(1, 2)), $definition->getArgumentDefaults(), '->getArgumentDefaults() return the default values for each argument');
    }

    public function testSetOptions()
    {
        $this->initializeOptions();

        $definition = new InputDefinition(array($this->foo));
        $this->assertEquals(array('foo' => $this->foo), $definition->getOptions(), '->setOptions() sets the array of InputOption objects');
        $definition->setOptions(array($this->bar));
        $this->assertEquals(array('bar' => $this->bar), $definition->getOptions(), '->setOptions() clears all InputOption objects');
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage The "-f" option does not exist.
     */
    public function testSetOptionsClearsOptions()
    {
        $this->initializeOptions();

        $definition = new InputDefinition(array($this->foo));
        $definition->setOptions(array($this->bar));
        $definition->getOptionForShortcut('f');
    }

    public function testAddOptions()
    {
        $this->initializeOptions();

        $definition = new InputDefinition(array($this->foo));
        $this->assertEquals(array('foo' => $this->foo), $definition->getOptions(), '->addOptions() adds an array of InputOption objects');
        $definition->addOptions(array($this->bar));
        $this->assertEquals(array('foo' => $this->foo, 'bar' => $this->bar), $definition->getOptions(), '->addOptions() does not clear existing InputOption objects');
    }

    public function testAddOption()
    {
        $this->initializeOptions();

        $definition = new InputDefinition();
        $definition->addOption($this->foo);
        $this->assertEquals(array('foo' => $this->foo), $definition->getOptions(), '->addOption() adds a InputOption object');
        $definition->addOption($this->bar);
        $this->assertEquals(array('foo' => $this->foo, 'bar' => $this->bar), $definition->getOptions(), '->addOption() adds a InputOption object');
    }

    /**
     * @expectedException        \LogicException
     * @expectedExceptionMessage An option named "foo" already exists.
     */
    public function testAddDuplicateOption()
    {
        $this->initializeOptions();

        $definition = new InputDefinition();
        $definition->addOption($this->foo);
        $definition->addOption($this->foo2);
    }

    /**
     * @expectedException        \LogicException
     * @expectedExceptionMessage An option with shortcut "f" already exists.
     */
    public function testAddDuplicateShortcutOption()
    {
        $this->initializeOptions();

        $definition = new InputDefinition();
        $definition->addOption($this->foo);
        $definition->addOption($this->foo1);
    }

    public function testGetOption()
    {
        $this->initializeOptions();

        $definition = new InputDefinition(array($this->foo));
        $this->assertEquals($this->foo, $definition->getOption('foo'), '->getOption() returns a InputOption by its name');
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage The "--bar" option does not exist.
     */
    public function testGetInvalidOption()
    {
        $this->initializeOptions();

        $definition = new InputDefinition(array($this->foo));
        $definition->getOption('bar');
    }

    public function testHasOption()
    {
        $this->initializeOptions();

        $definition = new InputDefinition(array($this->foo));
        $this->assertTrue($definition->hasOption('foo'), '->hasOption() returns true if a InputOption exists for the given name');
        $this->assertFalse($definition->hasOption('bar'), '->hasOption() returns false if a InputOption exists for the given name');
    }

    public function testHasShortcut()
    {
        $this->initializeOptions();

        $definition = new InputDefinition(array($this->foo));
        $this->assertTrue($definition->hasShortcut('f'), '->hasShortcut() returns true if a InputOption exists for the given shortcut');
        $this->assertFalse($definition->hasShortcut('b'), '->hasShortcut() returns false if a InputOption exists for the given shortcut');
    }

    public function testGetOptionForShortcut()
    {
        $this->initializeOptions();

        $definition = new InputDefinition(array($this->foo));
        $this->assertEquals($this->foo, $definition->getOptionForShortcut('f'), '->getOptionForShortcut() returns a InputOption by its shortcut');
    }

    public function testGetOptionForMultiShortcut()
    {
        $this->initializeOptions();

        $definition = new InputDefinition(array($this->multi));
        $this->assertEquals($this->multi, $definition->getOptionForShortcut('m'), '->getOptionForShortcut() returns a InputOption by its shortcut');
        $this->assertEquals($this->multi, $definition->getOptionForShortcut('mmm'), '->getOptionForShortcut() returns a InputOption by its shortcut');
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage The "-l" option does not exist.
     */
    public function testGetOptionForInvalidShortcut()
    {
        $this->initializeOptions();

        $definition = new InputDefinition(array($this->foo));
        $definition->getOptionForShortcut('l');
    }

    public function testGetOptionDefaults()
    {
        $definition = new InputDefinition(array(
            new InputOption('foo1', null, InputOption::VALUE_NONE),
            new InputOption('foo2', null, InputOption::VALUE_REQUIRED),
            new InputOption('foo3', null, InputOption::VALUE_REQUIRED, '', 'default'),
            new InputOption('foo4', null, InputOption::VALUE_OPTIONAL),
            new InputOption('foo5', null, InputOption::VALUE_OPTIONAL, '', 'default'),
            new InputOption('foo6', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY),
            new InputOption('foo7', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, '', array(1, 2)),
        ));
        $defaults = array(
            'foo1' => null,
            'foo2' => null,
            'foo3' => 'default',
            'foo4' => null,
            'foo5' => 'default',
            'foo6' => array(),
            'foo7' => array(1, 2),
        );
        $this->assertEquals($defaults, $definition->getOptionDefaults(), '->getOptionDefaults() returns the default values for all options');
    }

    public function testGetSynopsis()
    {
        $definition = new InputDefinition(array(new InputOption('foo')));
        $this->assertEquals('[--foo]', $definition->getSynopsis(), '->getSynopsis() returns a synopsis of arguments and options');
        $definition = new InputDefinition(array(new InputOption('foo', 'f')));
        $this->assertEquals('[-f|--foo]', $definition->getSynopsis(), '->getSynopsis() returns a synopsis of arguments and options');
        $definition = new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_REQUIRED)));
        $this->assertEquals('[-f|--foo="..."]', $definition->getSynopsis(), '->getSynopsis() returns a synopsis of arguments and options');
        $definition = new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL)));
        $this->assertEquals('[-f|--foo[="..."]]', $definition->getSynopsis(), '->getSynopsis() returns a synopsis of arguments and options');

        $definition = new InputDefinition(array(new InputArgument('foo')));
        $this->assertEquals('[foo]', $definition->getSynopsis(), '->getSynopsis() returns a synopsis of arguments and options');
        $definition = new InputDefinition(array(new InputArgument('foo', InputArgument::REQUIRED)));
        $this->assertEquals('foo', $definition->getSynopsis(), '->getSynopsis() returns a synopsis of arguments and options');
        $definition = new InputDefinition(array(new InputArgument('foo', InputArgument::IS_ARRAY)));
        $this->assertEquals('[foo1] ... [fooN]', $definition->getSynopsis(), '->getSynopsis() returns a synopsis of arguments and options');
        $definition = new InputDefinition(array(new InputArgument('foo', InputArgument::REQUIRED | InputArgument::IS_ARRAY)));
        $this->assertEquals('foo1 ... [fooN]', $definition->getSynopsis(), '->getSynopsis() returns a synopsis of arguments and options');
    }

    public function testAsText()
    {
        $definition = new InputDefinition(array(
            new InputArgument('foo', InputArgument::OPTIONAL, 'The foo argument'),
            new InputArgument('baz', InputArgument::OPTIONAL, 'The baz argument', true),
            new InputArgument('bar', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, 'The bar argument', array('http://foo.com/')),
            new InputOption('foo', 'f', InputOption::VALUE_REQUIRED, 'The foo option'),
            new InputOption('baz', null, InputOption::VALUE_OPTIONAL, 'The baz option', false),
            new InputOption('bar', 'b', InputOption::VALUE_OPTIONAL, 'The bar option', 'bar'),
            new InputOption('qux', '', InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'The qux option', array('http://foo.com/', 'bar')),
            new InputOption('qux2', '', InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'The qux2 option', array('foo' => 'bar')),
        ));
        $this->assertStringEqualsFile(self::$fixtures.'/definition_astext.txt', $definition->asText(), '->asText() returns a textual representation of the InputDefinition');
    }

    public function testAsXml()
    {
        $definition = new InputDefinition(array(
            new InputArgument('foo', InputArgument::OPTIONAL, 'The foo argument'),
            new InputArgument('baz', InputArgument::OPTIONAL, 'The baz argument', true),
            new InputArgument('bar', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, 'The bar argument', array('bar')),
            new InputOption('foo', 'f', InputOption::VALUE_REQUIRED, 'The foo option'),
            new InputOption('baz', null, InputOption::VALUE_OPTIONAL, 'The baz option', false),
            new InputOption('bar', 'b', InputOption::VALUE_OPTIONAL, 'The bar option', 'bar'),
        ));
        $this->assertXmlStringEqualsXmlFile(self::$fixtures.'/definition_asxml.txt', $definition->asXml(), '->asText() returns a textual representation of the InputDefinition');
    }

    protected function initializeArguments()
    {
        $this->foo = new InputArgument('foo');
        $this->bar = new InputArgument('bar');
        $this->foo1 = new InputArgument('foo');
        $this->foo2 = new InputArgument('foo2', InputArgument::REQUIRED);
    }

    protected function initializeOptions()
    {
        $this->foo = new InputOption('foo', 'f');
        $this->bar = new InputOption('bar', 'b');
        $this->foo1 = new InputOption('fooBis', 'f');
        $this->foo2 = new InputOption('foo', 'p');
        $this->multi = new InputOption('multi', 'm|mm|mmm');
    }
}
PK��Z1E��<<Etest/Console/Symfony/Component/Console/Tests/Input/ArrayInputTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Input;

use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;

class ArrayInputTest extends \PHPUnit_Framework_TestCase
{
    public function testGetFirstArgument()
    {
        $input = new ArrayInput(array());
        $this->assertNull($input->getFirstArgument(), '->getFirstArgument() returns null if no argument were passed');
        $input = new ArrayInput(array('name' => 'Fabien'));
        $this->assertEquals('Fabien', $input->getFirstArgument(), '->getFirstArgument() returns the first passed argument');
        $input = new ArrayInput(array('--foo' => 'bar', 'name' => 'Fabien'));
        $this->assertEquals('Fabien', $input->getFirstArgument(), '->getFirstArgument() returns the first passed argument');
    }

    public function testHasParameterOption()
    {
        $input = new ArrayInput(array('name' => 'Fabien', '--foo' => 'bar'));
        $this->assertTrue($input->hasParameterOption('--foo'), '->hasParameterOption() returns true if an option is present in the passed parameters');
        $this->assertFalse($input->hasParameterOption('--bar'), '->hasParameterOption() returns false if an option is not present in the passed parameters');

        $input = new ArrayInput(array('--foo'));
        $this->assertTrue($input->hasParameterOption('--foo'), '->hasParameterOption() returns true if an option is present in the passed parameters');
    }

    public function testParseArguments()
    {
        $input = new ArrayInput(array('name' => 'foo'), new InputDefinition(array(new InputArgument('name'))));

        $this->assertEquals(array('name' => 'foo'), $input->getArguments(), '->parse() parses required arguments');
    }

    /**
     * @dataProvider provideOptions
     */
    public function testParseOptions($input, $options, $expectedOptions, $message)
    {
        $input = new ArrayInput($input, new InputDefinition($options));

        $this->assertEquals($expectedOptions, $input->getOptions(), $message);
    }

    public function provideOptions()
    {
        return array(
            array(
                array('--foo' => 'bar'),
                array(new InputOption('foo')),
                array('foo' => 'bar'),
                '->parse() parses long options'
            ),
            array(
                array('--foo' => 'bar'),
                array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL, '', 'default')),
                array('foo' => 'bar'),
                '->parse() parses long options with a default value'
            ),
            array(
                array('--foo' => null),
                array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL, '', 'default')),
                array('foo' => 'default'),
                '->parse() parses long options with a default value'
            ),
            array(
                array('-f' => 'bar'),
                array(new InputOption('foo', 'f')),
                array('foo' => 'bar'),
                '->parse() parses short options'
            )
        );
    }

    /**
     * @dataProvider provideInvalidInput
     */
    public function testParseInvalidInput($parameters, $definition, $expectedExceptionMessage)
    {
        $this->setExpectedException('InvalidArgumentException', $expectedExceptionMessage);

        new ArrayInput($parameters, $definition);
    }

    public function provideInvalidInput()
    {
        return array(
            array(
                array('foo' => 'foo'),
                new InputDefinition(array(new InputArgument('name'))),
                'The "foo" argument does not exist.'
            ),
            array(
                array('--foo' => null),
                new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_REQUIRED))),
                'The "--foo" option requires a value.'
            ),
            array(
                array('--foo' => 'foo'),
                new InputDefinition(),
                'The "--foo" option does not exist.'
            ),
            array(
                array('-o' => 'foo'),
                new InputDefinition(),
                'The "-o" option does not exist.'
            )
        );
    }

    public function testToString()
    {
        $input = new ArrayInput(array('-f' => null, '-b' => 'bar', '--foo' => 'b a z', '--lala' => null, 'test' => 'Foo', 'test2' => "A\nB'C"));
        $this->assertEquals('-f -b=bar --foo='.escapeshellarg('b a z').' --lala Foo '.escapeshellarg("A\nB'C"), (string) $input);
    }
}
PK��ZKU�#�#Ftest/Console/Symfony/Component/Console/Tests/Input/InputOptionTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Input;

use Symfony\Component\Console\Input\InputOption;

class InputOptionTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $option = new InputOption('foo');
        $this->assertEquals('foo', $option->getName(), '__construct() takes a name as its first argument');
        $option = new InputOption('--foo');
        $this->assertEquals('foo', $option->getName(), '__construct() removes the leading -- of the option name');
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.
     */
    public function testArrayModeWithoutValue()
    {
        new InputOption('foo', 'f', InputOption::VALUE_IS_ARRAY);
    }

    public function testShortcut()
    {
        $option = new InputOption('foo', 'f');
        $this->assertEquals('f', $option->getShortcut(), '__construct() can take a shortcut as its second argument');
        $option = new InputOption('foo', '-f|-ff|fff');
        $this->assertEquals('f|ff|fff', $option->getShortcut(), '__construct() removes the leading - of the shortcuts');
        $option = new InputOption('foo', array('f', 'ff', '-fff'));
        $this->assertEquals('f|ff|fff', $option->getShortcut(), '__construct() removes the leading - of the shortcuts');
        $option = new InputOption('foo');
        $this->assertNull($option->getShortcut(), '__construct() makes the shortcut null by default');
    }

    public function testModes()
    {
        $option = new InputOption('foo', 'f');
        $this->assertFalse($option->acceptValue(), '__construct() gives a "InputOption::VALUE_NONE" mode by default');
        $this->assertFalse($option->isValueRequired(), '__construct() gives a "InputOption::VALUE_NONE" mode by default');
        $this->assertFalse($option->isValueOptional(), '__construct() gives a "InputOption::VALUE_NONE" mode by default');

        $option = new InputOption('foo', 'f', null);
        $this->assertFalse($option->acceptValue(), '__construct() can take "InputOption::VALUE_NONE" as its mode');
        $this->assertFalse($option->isValueRequired(), '__construct() can take "InputOption::VALUE_NONE" as its mode');
        $this->assertFalse($option->isValueOptional(), '__construct() can take "InputOption::VALUE_NONE" as its mode');

        $option = new InputOption('foo', 'f', InputOption::VALUE_NONE);
        $this->assertFalse($option->acceptValue(), '__construct() can take "InputOption::VALUE_NONE" as its mode');
        $this->assertFalse($option->isValueRequired(), '__construct() can take "InputOption::VALUE_NONE" as its mode');
        $this->assertFalse($option->isValueOptional(), '__construct() can take "InputOption::VALUE_NONE" as its mode');

        $option = new InputOption('foo', 'f', InputOption::VALUE_REQUIRED);
        $this->assertTrue($option->acceptValue(), '__construct() can take "InputOption::VALUE_REQUIRED" as its mode');
        $this->assertTrue($option->isValueRequired(), '__construct() can take "InputOption::VALUE_REQUIRED" as its mode');
        $this->assertFalse($option->isValueOptional(), '__construct() can take "InputOption::VALUE_REQUIRED" as its mode');

        $option = new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL);
        $this->assertTrue($option->acceptValue(), '__construct() can take "InputOption::VALUE_OPTIONAL" as its mode');
        $this->assertFalse($option->isValueRequired(), '__construct() can take "InputOption::VALUE_OPTIONAL" as its mode');
        $this->assertTrue($option->isValueOptional(), '__construct() can take "InputOption::VALUE_OPTIONAL" as its mode');
    }

    /**
     * @dataProvider provideInvalidModes
     */
    public function testInvalidModes($mode)
    {
        $this->setExpectedException('InvalidArgumentException', sprintf('Option mode "%s" is not valid.', $mode));

        new InputOption('foo', 'f', $mode);
    }

    public function provideInvalidModes()
    {
        return array(
            array('ANOTHER_ONE'),
            array(-1)
        );
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testEmptyNameIsInvalid()
    {
        new InputOption('');
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testDoubleDashNameIsInvalid()
    {
        new InputOption('--');
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testSingleDashOptionIsInvalid()
    {
        new InputOption('foo', '-');
    }

    public function testIsArray()
    {
        $option = new InputOption('foo', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY);
        $this->assertTrue($option->isArray(), '->isArray() returns true if the option can be an array');
        $option = new InputOption('foo', null, InputOption::VALUE_NONE);
        $this->assertFalse($option->isArray(), '->isArray() returns false if the option can not be an array');
    }

    public function testGetDescription()
    {
        $option = new InputOption('foo', 'f', null, 'Some description');
        $this->assertEquals('Some description', $option->getDescription(), '->getDescription() returns the description message');
    }

    public function testGetDefault()
    {
        $option = new InputOption('foo', null, InputOption::VALUE_OPTIONAL, '', 'default');
        $this->assertEquals('default', $option->getDefault(), '->getDefault() returns the default value');

        $option = new InputOption('foo', null, InputOption::VALUE_REQUIRED, '', 'default');
        $this->assertEquals('default', $option->getDefault(), '->getDefault() returns the default value');

        $option = new InputOption('foo', null, InputOption::VALUE_REQUIRED);
        $this->assertNull($option->getDefault(), '->getDefault() returns null if no default value is configured');

        $option = new InputOption('foo', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY);
        $this->assertEquals(array(), $option->getDefault(), '->getDefault() returns an empty array if option is an array');

        $option = new InputOption('foo', null, InputOption::VALUE_NONE);
        $this->assertFalse($option->getDefault(), '->getDefault() returns false if the option does not take a value');
    }

    public function testSetDefault()
    {
        $option = new InputOption('foo', null, InputOption::VALUE_REQUIRED, '', 'default');
        $option->setDefault(null);
        $this->assertNull($option->getDefault(), '->setDefault() can reset the default value by passing null');
        $option->setDefault('another');
        $this->assertEquals('another', $option->getDefault(), '->setDefault() changes the default value');

        $option = new InputOption('foo', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY);
        $option->setDefault(array(1, 2));
        $this->assertEquals(array(1, 2), $option->getDefault(), '->setDefault() changes the default value');
    }

    /**
     * @expectedException        \LogicException
     * @expectedExceptionMessage Cannot set a default value when using InputOption::VALUE_NONE mode.
     */
    public function testDefaultValueWithValueNoneMode()
    {
        $option = new InputOption('foo', 'f', InputOption::VALUE_NONE);
        $option->setDefault('default');
    }

    /**
     * @expectedException        \LogicException
     * @expectedExceptionMessage A default value for an array option must be an array.
     */
    public function testDefaultValueWithIsArrayMode()
    {
        $option = new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY);
        $option->setDefault('default');
    }

    public function testEquals()
    {
        $option = new InputOption('foo', 'f', null, 'Some description');
        $option2 = new InputOption('foo', 'f', null, 'Alternative description');
        $this->assertTrue($option->equals($option2));

        $option = new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL, 'Some description');
        $option2 = new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL, 'Some description', true);
        $this->assertFalse($option->equals($option2));

        $option = new InputOption('foo', 'f', null, 'Some description');
        $option2 = new InputOption('bar', 'f', null, 'Some description');
        $this->assertFalse($option->equals($option2));

        $option = new InputOption('foo', 'f', null, 'Some description');
        $option2 = new InputOption('foo', '', null, 'Some description');
        $this->assertFalse($option->equals($option2));

        $option = new InputOption('foo', 'f', null, 'Some description');
        $option2 = new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL, 'Some description');
        $this->assertFalse($option->equals($option2));
    }
}
PK��ZF�5��Htest/Console/Symfony/Component/Console/Tests/Input/InputArgumentTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Input;

use Symfony\Component\Console\Input\InputArgument;

class InputArgumentTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $argument = new InputArgument('foo');
        $this->assertEquals('foo', $argument->getName(), '__construct() takes a name as its first argument');
    }

    public function testModes()
    {
        $argument = new InputArgument('foo');
        $this->assertFalse($argument->isRequired(), '__construct() gives a "InputArgument::OPTIONAL" mode by default');

        $argument = new InputArgument('foo', null);
        $this->assertFalse($argument->isRequired(), '__construct() can take "InputArgument::OPTIONAL" as its mode');

        $argument = new InputArgument('foo', InputArgument::OPTIONAL);
        $this->assertFalse($argument->isRequired(), '__construct() can take "InputArgument::OPTIONAL" as its mode');

        $argument = new InputArgument('foo', InputArgument::REQUIRED);
        $this->assertTrue($argument->isRequired(), '__construct() can take "InputArgument::REQUIRED" as its mode');
    }

    /**
     * @dataProvider provideInvalidModes
     */
    public function testInvalidModes($mode)
    {
        $this->setExpectedException('InvalidArgumentException', sprintf('Argument mode "%s" is not valid.', $mode));

        new InputArgument('foo', $mode);
    }

    public function provideInvalidModes()
    {
        return array(
            array('ANOTHER_ONE'),
            array(-1)
        );
    }

    public function testIsArray()
    {
        $argument = new InputArgument('foo', InputArgument::IS_ARRAY);
        $this->assertTrue($argument->isArray(), '->isArray() returns true if the argument can be an array');
        $argument = new InputArgument('foo', InputArgument::OPTIONAL | InputArgument::IS_ARRAY);
        $this->assertTrue($argument->isArray(), '->isArray() returns true if the argument can be an array');
        $argument = new InputArgument('foo', InputArgument::OPTIONAL);
        $this->assertFalse($argument->isArray(), '->isArray() returns false if the argument can not be an array');
    }

    public function testGetDescription()
    {
        $argument = new InputArgument('foo', null, 'Some description');
        $this->assertEquals('Some description', $argument->getDescription(), '->getDescription() return the message description');
    }

    public function testGetDefault()
    {
        $argument = new InputArgument('foo', InputArgument::OPTIONAL, '', 'default');
        $this->assertEquals('default', $argument->getDefault(), '->getDefault() return the default value');
    }

    public function testSetDefault()
    {
        $argument = new InputArgument('foo', InputArgument::OPTIONAL, '', 'default');
        $argument->setDefault(null);
        $this->assertNull($argument->getDefault(), '->setDefault() can reset the default value by passing null');
        $argument->setDefault('another');
        $this->assertEquals('another', $argument->getDefault(), '->setDefault() changes the default value');

        $argument = new InputArgument('foo', InputArgument::OPTIONAL | InputArgument::IS_ARRAY);
        $argument->setDefault(array(1, 2));
        $this->assertEquals(array(1, 2), $argument->getDefault(), '->setDefault() changes the default value');
    }

    /**
     * @expectedException        \LogicException
     * @expectedExceptionMessage Cannot set a default value except for InputArgument::OPTIONAL mode.
     */
    public function testSetDefaultWithRequiredArgument()
    {
        $argument = new InputArgument('foo', InputArgument::REQUIRED);
        $argument->setDefault('default');
    }

    /**
     * @expectedException        \LogicException
     * @expectedExceptionMessage A default value for an array argument must be an array.
     */
    public function testSetDefaultWithArrayArgument()
    {
        $argument = new InputArgument('foo', InputArgument::IS_ARRAY);
        $argument->setDefault('default');
    }
}
PK��Z��Ĕ���@test/Console/Symfony/Component/Console/Tests/ApplicationTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Helper\FormatterHelper;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Console\Output\Output;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Output\StreamOutput;
use Symfony\Component\Console\Tester\ApplicationTester;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\Console\Event\ConsoleExceptionEvent;
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
use Symfony\Component\EventDispatcher\EventDispatcher;

class ApplicationTest extends \PHPUnit_Framework_TestCase
{
    protected static $fixturesPath;

    public static function setUpBeforeClass()
    {
        self::$fixturesPath = realpath(__DIR__.'/Fixtures/');
        require_once self::$fixturesPath.'/FooCommand.php';
        require_once self::$fixturesPath.'/Foo1Command.php';
        require_once self::$fixturesPath.'/Foo2Command.php';
        require_once self::$fixturesPath.'/Foo3Command.php';
        require_once self::$fixturesPath.'/Foo4Command.php';
        require_once self::$fixturesPath.'/Foo5Command.php';
        require_once self::$fixturesPath.'/FoobarCommand.php';
        require_once self::$fixturesPath.'/BarBucCommand.php';
    }

    protected function normalizeLineBreaks($text)
    {
        return str_replace(PHP_EOL, "\n", $text);
    }

    /**
     * Replaces the dynamic placeholders of the command help text with a static version.
     * The placeholder %command.full_name% includes the script path that is not predictable
     * and can not be tested against.
     */
    protected function ensureStaticCommandHelp(Application $application)
    {
        foreach ($application->all() as $command) {
            $command->setHelp(str_replace('%command.full_name%', 'app/console %command.name%', $command->getHelp()));
        }
    }

    public function testConstructor()
    {
        $application = new Application('foo', 'bar');
        $this->assertEquals('foo', $application->getName(), '__construct() takes the application name as its first argument');
        $this->assertEquals('bar', $application->getVersion(), '__construct() takes the application version as its second argument');
        $this->assertEquals(array('help', 'list'), array_keys($application->all()), '__construct() registered the help and list commands by default');
    }

    public function testSetGetName()
    {
        $application = new Application();
        $application->setName('foo');
        $this->assertEquals('foo', $application->getName(), '->setName() sets the name of the application');
    }

    public function testSetGetVersion()
    {
        $application = new Application();
        $application->setVersion('bar');
        $this->assertEquals('bar', $application->getVersion(), '->setVersion() sets the version of the application');
    }

    public function testGetLongVersion()
    {
        $application = new Application('foo', 'bar');
        $this->assertEquals('<info>foo</info> version <comment>bar</comment>', $application->getLongVersion(), '->getLongVersion() returns the long version of the application');
    }

    public function testHelp()
    {
        $application = new Application();
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_gethelp.txt', $this->normalizeLineBreaks($application->getHelp()), '->setHelp() returns a help message');
    }

    public function testAll()
    {
        $application = new Application();
        $commands = $application->all();
        $this->assertInstanceOf('Symfony\\Component\\Console\\Command\\HelpCommand', $commands['help'], '->all() returns the registered commands');

        $application->add(new \FooCommand());
        $commands = $application->all('foo');
        $this->assertCount(1, $commands, '->all() takes a namespace as its first argument');
    }

    public function testRegister()
    {
        $application = new Application();
        $command = $application->register('foo');
        $this->assertEquals('foo', $command->getName(), '->register() registers a new command');
    }

    public function testAdd()
    {
        $application = new Application();
        $application->add($foo = new \FooCommand());
        $commands = $application->all();
        $this->assertEquals($foo, $commands['foo:bar'], '->add() registers a command');

        $application = new Application();
        $application->addCommands(array($foo = new \FooCommand(), $foo1 = new \Foo1Command()));
        $commands = $application->all();
        $this->assertEquals(array($foo, $foo1), array($commands['foo:bar'], $commands['foo:bar1']), '->addCommands() registers an array of commands');
    }

    /**
     * @expectedException \LogicException
     * @expectedExceptionMessage Command class "Foo5Command" is not correctly initialized. You probably forgot to call the parent constructor.
     */
    public function testAddCommandWithEmptyConstructor()
    {
        $application = new Application();
        $application->add(new \Foo5Command());
    }

    public function testHasGet()
    {
        $application = new Application();
        $this->assertTrue($application->has('list'), '->has() returns true if a named command is registered');
        $this->assertFalse($application->has('afoobar'), '->has() returns false if a named command is not registered');

        $application->add($foo = new \FooCommand());
        $this->assertTrue($application->has('afoobar'), '->has() returns true if an alias is registered');
        $this->assertEquals($foo, $application->get('foo:bar'), '->get() returns a command by name');
        $this->assertEquals($foo, $application->get('afoobar'), '->get() returns a command by alias');

        $application = new Application();
        $application->add($foo = new \FooCommand());
        // simulate --help
        $r = new \ReflectionObject($application);
        $p = $r->getProperty('wantHelps');
        $p->setAccessible(true);
        $p->setValue($application, true);
        $command = $application->get('foo:bar');
        $this->assertInstanceOf('Symfony\Component\Console\Command\HelpCommand', $command, '->get() returns the help command if --help is provided as the input');
    }

    public function testSilentHelp()
    {
        $application = new Application();
        $application->setAutoExit(false);
        $application->setCatchExceptions(false);

        $tester = new ApplicationTester($application);
        $tester->run(array('-h' => true, '-q' => true), array('decorated' => false));

        $this->assertEmpty($tester->getDisplay(true));
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage The command "foofoo" does not exist.
     */
    public function testGetInvalidCommand()
    {
        $application = new Application();
        $application->get('foofoo');
    }

    public function testGetNamespaces()
    {
        $application = new Application();
        $application->add(new \FooCommand());
        $application->add(new \Foo1Command());
        $this->assertEquals(array('foo'), $application->getNamespaces(), '->getNamespaces() returns an array of unique used namespaces');
    }

    public function testFindNamespace()
    {
        $application = new Application();
        $application->add(new \FooCommand());
        $this->assertEquals('foo', $application->findNamespace('foo'), '->findNamespace() returns the given namespace if it exists');
        $this->assertEquals('foo', $application->findNamespace('f'), '->findNamespace() finds a namespace given an abbreviation');
        $application->add(new \Foo2Command());
        $this->assertEquals('foo', $application->findNamespace('foo'), '->findNamespace() returns the given namespace if it exists');
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage The namespace "f" is ambiguous (foo, foo1).
     */
    public function testFindAmbiguousNamespace()
    {
        $application = new Application();
        $application->add(new \BarBucCommand());
        $application->add(new \FooCommand());
        $application->add(new \Foo2Command());
        $application->findNamespace('f');
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage There are no commands defined in the "bar" namespace.
     */
    public function testFindInvalidNamespace()
    {
        $application = new Application();
        $application->findNamespace('bar');
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage Command "foo1" is not defined
     */
    public function testFindUniqueNameButNamespaceName()
    {
        $application = new Application();
        $application->add(new \FooCommand());
        $application->add(new \Foo1Command());
        $application->add(new \Foo2Command());

        $application->find($commandName = 'foo1');
    }

    public function testFind()
    {
        $application = new Application();
        $application->add(new \FooCommand());

        $this->assertInstanceOf('FooCommand', $application->find('foo:bar'), '->find() returns a command if its name exists');
        $this->assertInstanceOf('Symfony\Component\Console\Command\HelpCommand', $application->find('h'), '->find() returns a command if its name exists');
        $this->assertInstanceOf('FooCommand', $application->find('f:bar'), '->find() returns a command if the abbreviation for the namespace exists');
        $this->assertInstanceOf('FooCommand', $application->find('f:b'), '->find() returns a command if the abbreviation for the namespace and the command name exist');
        $this->assertInstanceOf('FooCommand', $application->find('a'), '->find() returns a command if the abbreviation exists for an alias');
    }

    /**
     * @dataProvider provideAmbiguousAbbreviations
     */
    public function testFindWithAmbiguousAbbreviations($abbreviation, $expectedExceptionMessage)
    {
        $this->setExpectedException('InvalidArgumentException', $expectedExceptionMessage);

        $application = new Application();
        $application->add(new \FooCommand());
        $application->add(new \Foo1Command());
        $application->add(new \Foo2Command());

        $application->find($abbreviation);
    }

    public function provideAmbiguousAbbreviations()
    {
        return array(
            array('f', 'Command "f" is not defined.'),
            array('a', 'Command "a" is ambiguous (afoobar, afoobar1 and 1 more).'),
            array('foo:b', 'Command "foo:b" is ambiguous (foo:bar, foo:bar1 and 1 more).')
        );
    }

    public function testFindCommandEqualNamespace()
    {
        $application = new Application();
        $application->add(new \Foo3Command());
        $application->add(new \Foo4Command());

        $this->assertInstanceOf('Foo3Command', $application->find('foo3:bar'), '->find() returns the good command even if a namespace has same name');
        $this->assertInstanceOf('Foo4Command', $application->find('foo3:bar:toh'), '->find() returns a command even if its namespace equals another command name');
    }

    public function testFindCommandWithAmbiguousNamespacesButUniqueName()
    {
        $application = new Application();
        $application->add(new \FooCommand());
        $application->add(new \FoobarCommand());

        $this->assertInstanceOf('FoobarCommand', $application->find('f:f'));
    }

    public function testFindCommandWithMissingNamespace()
    {
        $application = new Application();
        $application->add(new \Foo4Command());

        $this->assertInstanceOf('Foo4Command', $application->find('f::t'));
    }

    /**
     * @dataProvider             provideInvalidCommandNamesSingle
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage Did you mean this
     */
    public function testFindAlternativeExceptionMessageSingle($name)
    {
        $application = new Application();
        $application->add(new \Foo3Command());
        $application->find($name);
    }

    public function provideInvalidCommandNamesSingle()
    {
        return array(
            array('foo3:baR'),
            array('foO3:bar')
        );
    }

    public function testFindAlternativeExceptionMessageMultiple()
    {
        $application = new Application();
        $application->add(new \FooCommand());
        $application->add(new \Foo1Command());
        $application->add(new \Foo2Command());

        // Command + plural
        try {
            $application->find('foo:baR');
            $this->fail('->find() throws an \InvalidArgumentException if command does not exist, with alternatives');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->find() throws an \InvalidArgumentException if command does not exist, with alternatives');
            $this->assertRegExp('/Did you mean one of these/', $e->getMessage(), '->find() throws an \InvalidArgumentException if command does not exist, with alternatives');
            $this->assertRegExp('/foo1:bar/', $e->getMessage());
            $this->assertRegExp('/foo:bar/', $e->getMessage());
        }

        // Namespace + plural
        try {
            $application->find('foo2:bar');
            $this->fail('->find() throws an \InvalidArgumentException if command does not exist, with alternatives');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->find() throws an \InvalidArgumentException if command does not exist, with alternatives');
            $this->assertRegExp('/Did you mean one of these/', $e->getMessage(), '->find() throws an \InvalidArgumentException if command does not exist, with alternatives');
            $this->assertRegExp('/foo1/', $e->getMessage());
        }

        $application->add(new \Foo3Command());
        $application->add(new \Foo4Command());

        // Subnamespace + plural
        try {
            $a = $application->find('foo3:');
            $this->fail('->find() should throw an \InvalidArgumentException if a command is ambiguous because of a subnamespace, with alternatives');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e);
            $this->assertRegExp('/foo3:bar/', $e->getMessage());
            $this->assertRegExp('/foo3:bar:toh/', $e->getMessage());
        }
    }

    public function testFindAlternativeCommands()
    {
        $application = new Application();

        $application->add(new \FooCommand());
        $application->add(new \Foo1Command());
        $application->add(new \Foo2Command());

        try {
            $application->find($commandName = 'Unknown command');
            $this->fail('->find() throws an \InvalidArgumentException if command does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->find() throws an \InvalidArgumentException if command does not exist');
            $this->assertEquals(sprintf('Command "%s" is not defined.', $commandName), $e->getMessage(), '->find() throws an \InvalidArgumentException if command does not exist, without alternatives');
        }

        // Test if "bar1" command throw an "\InvalidArgumentException" and does not contain
        // "foo:bar" as alternative because "bar1" is too far from "foo:bar"
        try {
            $application->find($commandName = 'bar1');
            $this->fail('->find() throws an \InvalidArgumentException if command does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->find() throws an \InvalidArgumentException if command does not exist');
            $this->assertRegExp(sprintf('/Command "%s" is not defined./', $commandName), $e->getMessage(), '->find() throws an \InvalidArgumentException if command does not exist, with alternatives');
            $this->assertRegExp('/afoobar1/', $e->getMessage(), '->find() throws an \InvalidArgumentException if command does not exist, with alternative : "afoobar1"');
            $this->assertRegExp('/foo:bar1/', $e->getMessage(), '->find() throws an \InvalidArgumentException if command does not exist, with alternative : "foo:bar1"');
            $this->assertNotRegExp('/foo:bar(?>!1)/', $e->getMessage(), '->find() throws an \InvalidArgumentException if command does not exist, without "foo:bar" alternative');
        }
    }

    public function testFindAlternativeCommandsWithAnAlias()
    {
        $fooCommand = new \FooCommand();
        $fooCommand->setAliases(array('foo2'));

        $application = new Application();
        $application->add($fooCommand);

        $result = $application->find('foo');

        $this->assertSame($fooCommand, $result);
    }

    public function testFindAlternativeNamespace()
    {
        $application = new Application();

        $application->add(new \FooCommand());
        $application->add(new \Foo1Command());
        $application->add(new \Foo2Command());
        $application->add(new \foo3Command());

        try {
            $application->find('Unknown-namespace:Unknown-command');
            $this->fail('->find() throws an \InvalidArgumentException if namespace does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->find() throws an \InvalidArgumentException if namespace does not exist');
            $this->assertEquals('There are no commands defined in the "Unknown-namespace" namespace.', $e->getMessage(), '->find() throws an \InvalidArgumentException if namespace does not exist, without alternatives');
        }

        try {
            $application->find('foo2:command');
            $this->fail('->find() throws an \InvalidArgumentException if namespace does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->find() throws an \InvalidArgumentException if namespace does not exist');
            $this->assertRegExp('/There are no commands defined in the "foo2" namespace./', $e->getMessage(), '->find() throws an \InvalidArgumentException if namespace does not exist, with alternative');
            $this->assertRegExp('/foo/', $e->getMessage(), '->find() throws an \InvalidArgumentException if namespace does not exist, with alternative : "foo"');
            $this->assertRegExp('/foo1/', $e->getMessage(), '->find() throws an \InvalidArgumentException if namespace does not exist, with alternative : "foo1"');
            $this->assertRegExp('/foo3/', $e->getMessage(), '->find() throws an \InvalidArgumentException if namespace does not exist, with alternative : "foo3"');
        }
    }

    public function testFindNamespaceDoesNotFailOnDeepSimilarNamespaces()
    {
        $application = $this->getMock('Symfony\Component\Console\Application', array('getNamespaces'));
        $application->expects($this->once())
            ->method('getNamespaces')
            ->will($this->returnValue(array('foo:sublong', 'bar:sub')));

        $this->assertEquals('foo:sublong', $application->findNamespace('f:sub'));
    }

    public function testSetCatchExceptions()
    {
        $application = $this->getMock('Symfony\Component\Console\Application', array('getTerminalWidth'));
        $application->setAutoExit(false);
        $application->expects($this->any())
            ->method('getTerminalWidth')
            ->will($this->returnValue(120));
        $tester = new ApplicationTester($application);

        $application->setCatchExceptions(true);
        $tester->run(array('command' => 'foo'), array('decorated' => false));
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception1.txt', $tester->getDisplay(true), '->setCatchExceptions() sets the catch exception flag');

        $application->setCatchExceptions(false);
        try {
            $tester->run(array('command' => 'foo'), array('decorated' => false));
            $this->fail('->setCatchExceptions() sets the catch exception flag');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\Exception', $e, '->setCatchExceptions() sets the catch exception flag');
            $this->assertEquals('Command "foo" is not defined.', $e->getMessage(), '->setCatchExceptions() sets the catch exception flag');
        }
    }

    public function testAsText()
    {
        $application = new Application();
        $application->add(new \FooCommand());
        $this->ensureStaticCommandHelp($application);
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_astext1.txt', $this->normalizeLineBreaks($application->asText()), '->asText() returns a text representation of the application');
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_astext2.txt', $this->normalizeLineBreaks($application->asText('foo')), '->asText() returns a text representation of the application');
    }

    public function testAsXml()
    {
        $application = new Application();
        $application->add(new \FooCommand());
        $this->ensureStaticCommandHelp($application);
        $this->assertXmlStringEqualsXmlFile(self::$fixturesPath.'/application_asxml1.txt', $application->asXml(), '->asXml() returns an XML representation of the application');
        $this->assertXmlStringEqualsXmlFile(self::$fixturesPath.'/application_asxml2.txt', $application->asXml('foo'), '->asXml() returns an XML representation of the application');
    }

    public function testRenderException()
    {
        $application = $this->getMock('Symfony\Component\Console\Application', array('getTerminalWidth'));
        $application->setAutoExit(false);
        $application->expects($this->any())
            ->method('getTerminalWidth')
            ->will($this->returnValue(120));
        $tester = new ApplicationTester($application);

        $tester->run(array('command' => 'foo'), array('decorated' => false));
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception1.txt', $tester->getDisplay(true), '->renderException() renders a pretty exception');

        $tester->run(array('command' => 'foo'), array('decorated' => false, 'verbosity' => Output::VERBOSITY_VERBOSE));
        $this->assertContains('Exception trace', $tester->getDisplay(), '->renderException() renders a pretty exception with a stack trace when verbosity is verbose');

        $tester->run(array('command' => 'list', '--foo' => true), array('decorated' => false));
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception2.txt', $tester->getDisplay(true), '->renderException() renders the command synopsis when an exception occurs in the context of a command');

        $application->add(new \Foo3Command());
        $tester = new ApplicationTester($application);
        $tester->run(array('command' => 'foo3:bar'), array('decorated' => false));
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception3.txt', $tester->getDisplay(true), '->renderException() renders a pretty exceptions with previous exceptions');

        $tester->run(array('command' => 'foo3:bar'), array('decorated' => true));
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception3decorated.txt', $tester->getDisplay(true), '->renderException() renders a pretty exceptions with previous exceptions');

        $application = $this->getMock('Symfony\Component\Console\Application', array('getTerminalWidth'));
        $application->setAutoExit(false);
        $application->expects($this->any())
            ->method('getTerminalWidth')
            ->will($this->returnValue(32));
        $tester = new ApplicationTester($application);

        $tester->run(array('command' => 'foo'), array('decorated' => false));
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception4.txt', $tester->getDisplay(true), '->renderException() wraps messages when they are bigger than the terminal');
    }

    public function testRun()
    {
        $application = new Application();
        $application->setAutoExit(false);
        $application->setCatchExceptions(false);
        $application->add($command = new \Foo1Command());
        $_SERVER['argv'] = array('cli.php', 'foo:bar1');

        ob_start();
        $application->run();
        ob_end_clean();

        $this->assertInstanceOf('Symfony\Component\Console\Input\ArgvInput', $command->input, '->run() creates an ArgvInput by default if none is given');
        $this->assertInstanceOf('Symfony\Component\Console\Output\ConsoleOutput', $command->output, '->run() creates a ConsoleOutput by default if none is given');

        $application = new Application();
        $application->setAutoExit(false);
        $application->setCatchExceptions(false);

        $this->ensureStaticCommandHelp($application);
        $tester = new ApplicationTester($application);

        $tester->run(array(), array('decorated' => false));
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_run1.txt', $tester->getDisplay(true), '->run() runs the list command if no argument is passed');

        $tester->run(array('--help' => true), array('decorated' => false));
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_run2.txt', $tester->getDisplay(true), '->run() runs the help command if --help is passed');

        $tester->run(array('-h' => true), array('decorated' => false));
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_run2.txt', $tester->getDisplay(true), '->run() runs the help command if -h is passed');

        $tester->run(array('command' => 'list', '--help' => true), array('decorated' => false));
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_run3.txt', $tester->getDisplay(true), '->run() displays the help if --help is passed');

        $tester->run(array('command' => 'list', '-h' => true), array('decorated' => false));
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_run3.txt', $tester->getDisplay(true), '->run() displays the help if -h is passed');

        $tester->run(array('--ansi' => true));
        $this->assertTrue($tester->getOutput()->isDecorated(), '->run() forces color output if --ansi is passed');

        $tester->run(array('--no-ansi' => true));
        $this->assertFalse($tester->getOutput()->isDecorated(), '->run() forces color output to be disabled if --no-ansi is passed');

        $tester->run(array('--version' => true), array('decorated' => false));
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_run4.txt', $tester->getDisplay(true), '->run() displays the program version if --version is passed');

        $tester->run(array('-V' => true), array('decorated' => false));
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_run4.txt', $tester->getDisplay(true), '->run() displays the program version if -v is passed');

        $tester->run(array('command' => 'list', '--quiet' => true));
        $this->assertSame('', $tester->getDisplay(), '->run() removes all output if --quiet is passed');

        $tester->run(array('command' => 'list', '-q' => true));
        $this->assertSame('', $tester->getDisplay(), '->run() removes all output if -q is passed');

        $tester->run(array('command' => 'list', '--verbose' => true));
        $this->assertSame(Output::VERBOSITY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if --verbose is passed');

        $tester->run(array('command' => 'list', '--verbose' => 1));
        $this->assertSame(Output::VERBOSITY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if --verbose=1 is passed');

        $tester->run(array('command' => 'list', '--verbose' => 2));
        $this->assertSame(Output::VERBOSITY_VERY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to very verbose if --verbose=2 is passed');

        $tester->run(array('command' => 'list', '--verbose' => 3));
        $this->assertSame(Output::VERBOSITY_DEBUG, $tester->getOutput()->getVerbosity(), '->run() sets the output to debug if --verbose=3 is passed');

        $tester->run(array('command' => 'list', '--verbose' => 4));
        $this->assertSame(Output::VERBOSITY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if unknown --verbose level is passed');

        $tester->run(array('command' => 'list', '-v' => true));
        $this->assertSame(Output::VERBOSITY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if -v is passed');

        $tester->run(array('command' => 'list', '-vv' => true));
        $this->assertSame(Output::VERBOSITY_VERY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if -v is passed');

        $tester->run(array('command' => 'list', '-vvv' => true));
        $this->assertSame(Output::VERBOSITY_DEBUG, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if -v is passed');

        $application = new Application();
        $application->setAutoExit(false);
        $application->setCatchExceptions(false);
        $application->add(new \FooCommand());
        $tester = new ApplicationTester($application);

        $tester->run(array('command' => 'foo:bar', '--no-interaction' => true), array('decorated' => false));
        $this->assertSame('called'.PHP_EOL, $tester->getDisplay(), '->run() does not call interact() if --no-interaction is passed');

        $tester->run(array('command' => 'foo:bar', '-n' => true), array('decorated' => false));
        $this->assertSame('called'.PHP_EOL, $tester->getDisplay(), '->run() does not call interact() if -n is passed');
    }

    /**
     * Issue #9285
     *
     * If the "verbose" option is just before an argument in ArgvInput,
     * an argument value should not be treated as verbosity value.
     * This test will fail with "Not enough arguments." if broken
     */
    public function testVerboseValueNotBreakArguments()
    {
        $application = new Application();
        $application->setAutoExit(false);
        $application->setCatchExceptions(false);
        $application->add(new \FooCommand());

        $output = new StreamOutput(fopen('php://memory', 'w', false));

        $input = new ArgvInput(array('cli.php', '-v', 'foo:bar'));
        $application->run($input, $output);

        $input = new ArgvInput(array('cli.php', '--verbose', 'foo:bar'));
        $application->run($input, $output);
    }

    public function testRunReturnsIntegerExitCode()
    {
        $exception = new \Exception('', 4);

        $application = $this->getMock('Symfony\Component\Console\Application', array('doRun'));
        $application->setAutoExit(false);
        $application->expects($this->once())
             ->method('doRun')
             ->will($this->throwException($exception));

        $exitCode = $application->run(new ArrayInput(array()), new NullOutput());

        $this->assertSame(4, $exitCode, '->run() returns integer exit code extracted from raised exception');
    }

    public function testRunReturnsExitCodeOneForExceptionCodeZero()
    {
        $exception = new \Exception('', 0);

        $application = $this->getMock('Symfony\Component\Console\Application', array('doRun'));
        $application->setAutoExit(false);
        $application->expects($this->once())
             ->method('doRun')
             ->will($this->throwException($exception));

        $exitCode = $application->run(new ArrayInput(array()), new NullOutput());

        $this->assertSame(1, $exitCode, '->run() returns exit code 1 when exception code is 0');
    }

    /**
     * @expectedException \LogicException
     * @dataProvider getAddingAlreadySetDefinitionElementData
     */
    public function testAddingAlreadySetDefinitionElementData($def)
    {
        $application = new Application();
        $application->setAutoExit(false);
        $application->setCatchExceptions(false);
        $application
            ->register('foo')
            ->setDefinition(array($def))
            ->setCode(function (InputInterface $input, OutputInterface $output) {})
        ;

        $input = new ArrayInput(array('command' => 'foo'));
        $output = new NullOutput();
        $application->run($input, $output);
    }

    public function getAddingAlreadySetDefinitionElementData()
    {
        return array(
            array(new InputArgument('command', InputArgument::REQUIRED)),
            array(new InputOption('quiet', '', InputOption::VALUE_NONE)),
            array(new InputOption('query', 'q', InputOption::VALUE_NONE)),
        );
    }

    public function testGetDefaultHelperSetReturnsDefaultValues()
    {
        $application = new Application();
        $application->setAutoExit(false);
        $application->setCatchExceptions(false);

        $helperSet = $application->getHelperSet();

        $this->assertTrue($helperSet->has('formatter'));
        $this->assertTrue($helperSet->has('dialog'));
        $this->assertTrue($helperSet->has('progress'));
    }

    public function testAddingSingleHelperSetOverwritesDefaultValues()
    {
        $application = new Application();
        $application->setAutoExit(false);
        $application->setCatchExceptions(false);

        $application->setHelperSet(new HelperSet(array(new FormatterHelper())));

        $helperSet = $application->getHelperSet();

        $this->assertTrue($helperSet->has('formatter'));

        // no other default helper set should be returned
        $this->assertFalse($helperSet->has('dialog'));
        $this->assertFalse($helperSet->has('progress'));
    }

    public function testOverwritingDefaultHelperSetOverwritesDefaultValues()
    {
        $application = new CustomApplication();
        $application->setAutoExit(false);
        $application->setCatchExceptions(false);

        $application->setHelperSet(new HelperSet(array(new FormatterHelper())));

        $helperSet = $application->getHelperSet();

        $this->assertTrue($helperSet->has('formatter'));

        // no other default helper set should be returned
        $this->assertFalse($helperSet->has('dialog'));
        $this->assertFalse($helperSet->has('progress'));
    }

    public function testGetDefaultInputDefinitionReturnsDefaultValues()
    {
        $application = new Application();
        $application->setAutoExit(false);
        $application->setCatchExceptions(false);

        $inputDefinition = $application->getDefinition();

        $this->assertTrue($inputDefinition->hasArgument('command'));

        $this->assertTrue($inputDefinition->hasOption('help'));
        $this->assertTrue($inputDefinition->hasOption('quiet'));
        $this->assertTrue($inputDefinition->hasOption('verbose'));
        $this->assertTrue($inputDefinition->hasOption('version'));
        $this->assertTrue($inputDefinition->hasOption('ansi'));
        $this->assertTrue($inputDefinition->hasOption('no-ansi'));
        $this->assertTrue($inputDefinition->hasOption('no-interaction'));
    }

    public function testOverwritingDefaultInputDefinitionOverwritesDefaultValues()
    {
        $application = new CustomApplication();
        $application->setAutoExit(false);
        $application->setCatchExceptions(false);

        $inputDefinition = $application->getDefinition();

        // check whether the default arguments and options are not returned any more
        $this->assertFalse($inputDefinition->hasArgument('command'));

        $this->assertFalse($inputDefinition->hasOption('help'));
        $this->assertFalse($inputDefinition->hasOption('quiet'));
        $this->assertFalse($inputDefinition->hasOption('verbose'));
        $this->assertFalse($inputDefinition->hasOption('version'));
        $this->assertFalse($inputDefinition->hasOption('ansi'));
        $this->assertFalse($inputDefinition->hasOption('no-ansi'));
        $this->assertFalse($inputDefinition->hasOption('no-interaction'));

        $this->assertTrue($inputDefinition->hasOption('custom'));
    }

    public function testSettingCustomInputDefinitionOverwritesDefaultValues()
    {
        $application = new Application();
        $application->setAutoExit(false);
        $application->setCatchExceptions(false);

        $application->setDefinition(new InputDefinition(array(new InputOption('--custom', '-c', InputOption::VALUE_NONE, 'Set the custom input definition.'))));

        $inputDefinition = $application->getDefinition();

        // check whether the default arguments and options are not returned any more
        $this->assertFalse($inputDefinition->hasArgument('command'));

        $this->assertFalse($inputDefinition->hasOption('help'));
        $this->assertFalse($inputDefinition->hasOption('quiet'));
        $this->assertFalse($inputDefinition->hasOption('verbose'));
        $this->assertFalse($inputDefinition->hasOption('version'));
        $this->assertFalse($inputDefinition->hasOption('ansi'));
        $this->assertFalse($inputDefinition->hasOption('no-ansi'));
        $this->assertFalse($inputDefinition->hasOption('no-interaction'));

        $this->assertTrue($inputDefinition->hasOption('custom'));
    }

    public function testRunWithDispatcher()
    {
        $application = new Application();
        $application->setAutoExit(false);
        $application->setDispatcher($this->getDispatcher());

        $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) {
            $output->write('foo.');
        });

        $tester = new ApplicationTester($application);
        $tester->run(array('command' => 'foo'));
        $this->assertEquals('before.foo.after.', $tester->getDisplay());
    }

    /**
     * @expectedException        \LogicException
     * @expectedExceptionMessage caught
     */
    public function testRunWithExceptionAndDispatcher()
    {
        $application = new Application();
        $application->setDispatcher($this->getDispatcher());
        $application->setAutoExit(false);
        $application->setCatchExceptions(false);

        $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) {
            throw new \RuntimeException('foo');
        });

        $tester = new ApplicationTester($application);
        $tester->run(array('command' => 'foo'));
    }

    public function testRunDispatchesAllEventsWithException()
    {
        $application = new Application();
        $application->setDispatcher($this->getDispatcher());
        $application->setAutoExit(false);

        $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) {
            $output->write('foo.');

            throw new \RuntimeException('foo');
        });

        $tester = new ApplicationTester($application);
        $tester->run(array('command' => 'foo'));
        $this->assertContains('before.foo.after.caught.', $tester->getDisplay());
    }

    public function testTerminalDimensions()
    {
        $application = new Application();
        $originalDimensions = $application->getTerminalDimensions();
        $this->assertCount(2, $originalDimensions);

        $width = 80;
        if ($originalDimensions[0] == $width) {
            $width = 100;
        }

        $application->setTerminalDimensions($width, 80);
        $this->assertSame(array($width, 80), $application->getTerminalDimensions());
    }

    protected function getDispatcher()
    {
        $dispatcher = new EventDispatcher();
        $dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) {
            $event->getOutput()->write('before.');
        });
        $dispatcher->addListener('console.terminate', function (ConsoleTerminateEvent $event) {
            $event->getOutput()->write('after.');

            $event->setExitCode(128);
        });
        $dispatcher->addListener('console.exception', function (ConsoleExceptionEvent $event) {
            $event->getOutput()->writeln('caught.');

            $event->setException(new \LogicException('caught.', $event->getExitCode(), $event->getException()));
        });

        return $dispatcher;
    }
}

class CustomApplication extends Application
{
    /**
     * Overwrites the default input definition.
     *
     * @return InputDefinition An InputDefinition instance
     */
    protected function getDefaultInputDefinition()
    {
        return new InputDefinition(array(new InputOption('--custom', '-c', InputOption::VALUE_NONE, 'Set the custom input definition.')));
    }

    /**
     * Gets the default helper set with the helpers that should always be available.
     *
     * @return HelperSet A HelperSet instance
     */
    protected function getDefaultHelperSet()
    {
        return new HelperSet(array(new FormatterHelper()));
    }
}
PK��Z�r�HwwStest/Console/Symfony/Component/Console/Tests/Formatter/OutputFormatterStyleTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Formatter;

use Symfony\Component\Console\Formatter\OutputFormatterStyle;

class OutputFormatterStyleTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $style = new OutputFormatterStyle('green', 'black', array('bold', 'underscore'));
        $this->assertEquals("\033[32;40;1;4mfoo\033[0m", $style->apply('foo'));

        $style = new OutputFormatterStyle('red', null, array('blink'));
        $this->assertEquals("\033[31;5mfoo\033[0m", $style->apply('foo'));

        $style = new OutputFormatterStyle(null, 'white');
        $this->assertEquals("\033[47mfoo\033[0m", $style->apply('foo'));
    }

    public function testForeground()
    {
        $style = new OutputFormatterStyle();

        $style->setForeground('black');
        $this->assertEquals("\033[30mfoo\033[0m", $style->apply('foo'));

        $style->setForeground('blue');
        $this->assertEquals("\033[34mfoo\033[0m", $style->apply('foo'));

        $this->setExpectedException('InvalidArgumentException');
        $style->setForeground('undefined-color');
    }

    public function testBackground()
    {
        $style = new OutputFormatterStyle();

        $style->setBackground('black');
        $this->assertEquals("\033[40mfoo\033[0m", $style->apply('foo'));

        $style->setBackground('yellow');
        $this->assertEquals("\033[43mfoo\033[0m", $style->apply('foo'));

        $this->setExpectedException('InvalidArgumentException');
        $style->setBackground('undefined-color');
    }

    public function testOptions()
    {
        $style = new OutputFormatterStyle();

        $style->setOptions(array('reverse', 'conceal'));
        $this->assertEquals("\033[7;8mfoo\033[0m", $style->apply('foo'));

        $style->setOption('bold');
        $this->assertEquals("\033[7;8;1mfoo\033[0m", $style->apply('foo'));

        $style->unsetOption('reverse');
        $this->assertEquals("\033[8;1mfoo\033[0m", $style->apply('foo'));

        $style->setOption('bold');
        $this->assertEquals("\033[8;1mfoo\033[0m", $style->apply('foo'));

        $style->setOptions(array('bold'));
        $this->assertEquals("\033[1mfoo\033[0m", $style->apply('foo'));

        try {
            $style->setOption('foo');
            $this->fail('->setOption() throws an \InvalidArgumentException when the option does not exist in the available options');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->setOption() throws an \InvalidArgumentException when the option does not exist in the available options');
            $this->assertContains('Invalid option specified: "foo"', $e->getMessage(), '->setOption() throws an \InvalidArgumentException when the option does not exist in the available options');
        }

        try {
            $style->unsetOption('foo');
            $this->fail('->unsetOption() throws an \InvalidArgumentException when the option does not exist in the available options');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->unsetOption() throws an \InvalidArgumentException when the option does not exist in the available options');
            $this->assertContains('Invalid option specified: "foo"', $e->getMessage(), '->unsetOption() throws an \InvalidArgumentException when the option does not exist in the available options');
        }
    }
}
PK��Z� R�wwXtest/Console/Symfony/Component/Console/Tests/Formatter/OutputFormatterStyleStackTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Formatter;

use Symfony\Component\Console\Formatter\OutputFormatterStyleStack;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;

class OutputFormatterStyleStackTest extends \PHPUnit_Framework_TestCase
{
    public function testPush()
    {
        $stack = new OutputFormatterStyleStack();
        $stack->push($s1 = new OutputFormatterStyle('white', 'black'));
        $stack->push($s2 = new OutputFormatterStyle('yellow', 'blue'));

        $this->assertEquals($s2, $stack->getCurrent());

        $stack->push($s3 = new OutputFormatterStyle('green', 'red'));

        $this->assertEquals($s3, $stack->getCurrent());
    }

    public function testPop()
    {
        $stack = new OutputFormatterStyleStack();
        $stack->push($s1 = new OutputFormatterStyle('white', 'black'));
        $stack->push($s2 = new OutputFormatterStyle('yellow', 'blue'));

        $this->assertEquals($s2, $stack->pop());
        $this->assertEquals($s1, $stack->pop());
    }

    public function testPopEmpty()
    {
        $stack = new OutputFormatterStyleStack();
        $style = new OutputFormatterStyle();

        $this->assertEquals($style, $stack->pop());
    }

    public function testPopNotLast()
    {
        $stack = new OutputFormatterStyleStack();
        $stack->push($s1 = new OutputFormatterStyle('white', 'black'));
        $stack->push($s2 = new OutputFormatterStyle('yellow', 'blue'));
        $stack->push($s3 = new OutputFormatterStyle('green', 'red'));

        $this->assertEquals($s2, $stack->pop($s2));
        $this->assertEquals($s1, $stack->pop());
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testInvalidPop()
    {
        $stack = new OutputFormatterStyleStack();
        $stack->push(new OutputFormatterStyle('white', 'black'));
        $stack->pop(new OutputFormatterStyle('yellow', 'blue'));
    }
}
PK��Z]6\���Ntest/Console/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Formatter;

use Symfony\Component\Console\Formatter\OutputFormatter;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;

class OutputFormatterTest extends \PHPUnit_Framework_TestCase
{
    public function testEmptyTag()
    {
        $formatter = new OutputFormatter(true);
        $this->assertEquals("foo<>bar", $formatter->format('foo<>bar'));
    }

    public function testLGCharEscaping()
    {
        $formatter = new OutputFormatter(true);

        $this->assertEquals("foo<bar", $formatter->format('foo\\<bar'));
        $this->assertEquals("<info>some info</info>", $formatter->format('\\<info>some info\\</info>'));
        $this->assertEquals("\\<info>some info\\</info>", OutputFormatter::escape('<info>some info</info>'));

        $this->assertEquals(
            "\033[33mSymfony\\Component\\Console does work very well!\033[0m",
            $formatter->format('<comment>Symfony\Component\Console does work very well!</comment>')
        );
    }

    public function testBundledStyles()
    {
        $formatter = new OutputFormatter(true);

        $this->assertTrue($formatter->hasStyle('error'));
        $this->assertTrue($formatter->hasStyle('info'));
        $this->assertTrue($formatter->hasStyle('comment'));
        $this->assertTrue($formatter->hasStyle('question'));

        $this->assertEquals(
            "\033[37;41msome error\033[0m",
            $formatter->format('<error>some error</error>')
        );
        $this->assertEquals(
            "\033[32msome info\033[0m",
            $formatter->format('<info>some info</info>')
        );
        $this->assertEquals(
            "\033[33msome comment\033[0m",
            $formatter->format('<comment>some comment</comment>')
        );
        $this->assertEquals(
            "\033[30;46msome question\033[0m",
            $formatter->format('<question>some question</question>')
        );
    }

    public function testNestedStyles()
    {
        $formatter = new OutputFormatter(true);

        $this->assertEquals(
            "\033[37;41msome \033[0m\033[32msome info\033[0m\033[37;41m error\033[0m",
            $formatter->format('<error>some <info>some info</info> error</error>')
        );
    }

    public function testAdjacentStyles()
    {
        $formatter = new OutputFormatter(true);

        $this->assertEquals(
            "\033[37;41msome error\033[0m\033[32msome info\033[0m",
            $formatter->format('<error>some error</error><info>some info</info>')
        );
    }

    public function testStyleMatchingNotGreedy()
    {
        $formatter = new OutputFormatter(true);

        $this->assertEquals(
            "(\033[32m>=2.0,<2.3\033[0m)",
            $formatter->format('(<info>>=2.0,<2.3</info>)')
        );
    }

    public function testStyleEscaping()
    {
        $formatter = new OutputFormatter(true);

        $this->assertEquals(
            "(\033[32mz>=2.0,<a2.3\033[0m)",
            $formatter->format('(<info>'.$formatter->escape('z>=2.0,<a2.3').'</info>)')
        );
    }

    public function testDeepNestedStyles()
    {
        $formatter = new OutputFormatter(true);

        $this->assertEquals(
            "\033[37;41merror\033[0m\033[32minfo\033[0m\033[33mcomment\033[0m\033[37;41merror\033[0m",
            $formatter->format('<error>error<info>info<comment>comment</info>error</error>')
        );
    }

    public function testNewStyle()
    {
        $formatter = new OutputFormatter(true);

        $style = new OutputFormatterStyle('blue', 'white');
        $formatter->setStyle('test', $style);

        $this->assertEquals($style, $formatter->getStyle('test'));
        $this->assertNotEquals($style, $formatter->getStyle('info'));

        $style = new OutputFormatterStyle('blue', 'white');
        $formatter->setStyle('b', $style);

        $this->assertEquals("\033[34;47msome \033[0m\033[34;47mcustom\033[0m\033[34;47m msg\033[0m", $formatter->format('<test>some <b>custom</b> msg</test>'));
    }

    public function testRedefineStyle()
    {
        $formatter = new OutputFormatter(true);

        $style = new OutputFormatterStyle('blue', 'white');
        $formatter->setStyle('info', $style);

        $this->assertEquals("\033[34;47msome custom msg\033[0m", $formatter->format('<info>some custom msg</info>'));
    }

    public function testInlineStyle()
    {
        $formatter = new OutputFormatter(true);

        $this->assertEquals("\033[34;41msome text\033[0m", $formatter->format('<fg=blue;bg=red>some text</>'));
        $this->assertEquals("\033[34;41msome text\033[0m", $formatter->format('<fg=blue;bg=red>some text</fg=blue;bg=red>'));
    }

    public function testNonStyleTag()
    {
        $formatter = new OutputFormatter(true);

        $this->assertEquals("\033[32msome \033[0m\033[32m<tag>\033[0m\033[32m styled \033[0m\033[32m<p>\033[0m\033[32msingle-char tag\033[0m\033[32m</p>\033[0m", $formatter->format('<info>some <tag> styled <p>single-char tag</p></info>'));
    }

    public function testFormatLongString()
    {
        $formatter = new OutputFormatter(true);
        $long = str_repeat("\\", 14000);
        $this->assertEquals("\033[37;41msome error\033[0m".$long, $formatter->format('<error>some error</error>'.$long));
    }

    public function testNotDecoratedFormatter()
    {
        $formatter = new OutputFormatter(false);

        $this->assertTrue($formatter->hasStyle('error'));
        $this->assertTrue($formatter->hasStyle('info'));
        $this->assertTrue($formatter->hasStyle('comment'));
        $this->assertTrue($formatter->hasStyle('question'));

        $this->assertEquals(
            "some error", $formatter->format('<error>some error</error>')
        );
        $this->assertEquals(
            "some info", $formatter->format('<info>some info</info>')
        );
        $this->assertEquals(
            "some comment", $formatter->format('<comment>some comment</comment>')
        );
        $this->assertEquals(
            "some question", $formatter->format('<question>some question</question>')
        );

        $formatter->setDecorated(true);

        $this->assertEquals(
            "\033[37;41msome error\033[0m", $formatter->format('<error>some error</error>')
        );
        $this->assertEquals(
            "\033[32msome info\033[0m", $formatter->format('<info>some info</info>')
        );
        $this->assertEquals(
            "\033[33msome comment\033[0m", $formatter->format('<comment>some comment</comment>')
        );
        $this->assertEquals(
            "\033[30;46msome question\033[0m", $formatter->format('<question>some question</question>')
        );
    }

    public function testContentWithLineBreaks()
    {
        $formatter = new OutputFormatter(true);

        $this->assertEquals(<<<EOF
\033[32m
some text\033[0m
EOF
            , $formatter->format(<<<EOF
<info>
some text</info>
EOF
        ));

        $this->assertEquals(<<<EOF
\033[32msome text
\033[0m
EOF
            , $formatter->format(<<<EOF
<info>some text
</info>
EOF
        ));

        $this->assertEquals(<<<EOF
\033[32m
some text
\033[0m
EOF
            , $formatter->format(<<<EOF
<info>
some text
</info>
EOF
        ));

        $this->assertEquals(<<<EOF
\033[32m
some text
more text
\033[0m
EOF
            , $formatter->format(<<<EOF
<info>
some text
more text
</info>
EOF
        ));
    }
}
PK��Z����Htest/Console/Symfony/Component/Console/Tests/Output/StreamOutputTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Output;

use Symfony\Component\Console\Output\Output;
use Symfony\Component\Console\Output\StreamOutput;

class StreamOutputTest extends \PHPUnit_Framework_TestCase
{
    protected $stream;

    protected function setUp()
    {
        $this->stream = fopen('php://memory', 'a', false);
    }

    protected function tearDown()
    {
        $this->stream = null;
    }

    public function testConstructor()
    {
        $output = new StreamOutput($this->stream, Output::VERBOSITY_QUIET, true);
        $this->assertEquals(Output::VERBOSITY_QUIET, $output->getVerbosity(), '__construct() takes the verbosity as its first argument');
        $this->assertTrue($output->isDecorated(), '__construct() takes the decorated flag as its second argument');
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage The StreamOutput class needs a stream as its first argument.
     */
    public function testStreamIsRequired()
    {
        new StreamOutput('foo');
    }

    public function testGetStream()
    {
        $output = new StreamOutput($this->stream);
        $this->assertEquals($this->stream, $output->getStream(), '->getStream() returns the current stream');
    }

    public function testDoWrite()
    {
        $output = new StreamOutput($this->stream);
        $output->writeln('foo');
        rewind($output->getStream());
        $this->assertEquals('foo'.PHP_EOL, stream_get_contents($output->getStream()), '->doWrite() writes to the stream');
    }
}
PK��Z;�!��Ftest/Console/Symfony/Component/Console/Tests/Output/NullOutputTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Output;

use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Console\Output\OutputInterface;

class NullOutputTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $output = new NullOutput();

        ob_start();
        $output->write('foo');
        $buffer = ob_get_clean();

        $this->assertSame('', $buffer, '->write() does nothing (at least nothing is printed)');
        $this->assertFalse($output->isDecorated(), '->isDecorated() returns false');
    }

    public function testVerbosity()
    {
        $output = new NullOutput();
        $this->assertSame(OutputInterface::VERBOSITY_QUIET, $output->getVerbosity(), '->getVerbosity() returns VERBOSITY_QUIET for NullOutput by default');

        $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
        $this->assertSame(OutputInterface::VERBOSITY_QUIET, $output->getVerbosity(), '->getVerbosity() always returns VERBOSITY_QUIET for NullOutput');
    }
}
PK��Z}�R��Itest/Console/Symfony/Component/Console/Tests/Output/ConsoleOutputTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Output;

use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\Console\Output\Output;

class ConsoleOutputTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $output = new ConsoleOutput(Output::VERBOSITY_QUIET, true);
        $this->assertEquals(Output::VERBOSITY_QUIET, $output->getVerbosity(), '__construct() takes the verbosity as its first argument');
    }
}
PK��Z�����Btest/Console/Symfony/Component/Console/Tests/Output/OutputTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Output;

use Symfony\Component\Console\Output\Output;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;

class OutputTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $output = new TestOutput(Output::VERBOSITY_QUIET, true);
        $this->assertEquals(Output::VERBOSITY_QUIET, $output->getVerbosity(), '__construct() takes the verbosity as its first argument');
        $this->assertTrue($output->isDecorated(), '__construct() takes the decorated flag as its second argument');
    }

    public function testSetIsDecorated()
    {
        $output = new TestOutput();
        $output->setDecorated(true);
        $this->assertTrue($output->isDecorated(), 'setDecorated() sets the decorated flag');
    }

    public function testSetGetVerbosity()
    {
        $output = new TestOutput();
        $output->setVerbosity(Output::VERBOSITY_QUIET);
        $this->assertEquals(Output::VERBOSITY_QUIET, $output->getVerbosity(), '->setVerbosity() sets the verbosity');

        $this->assertTrue($output->isQuiet());
        $this->assertFalse($output->isVerbose());
        $this->assertFalse($output->isVeryVerbose());
        $this->assertFalse($output->isDebug());

        $output->setVerbosity(Output::VERBOSITY_NORMAL);
        $this->assertFalse($output->isQuiet());
        $this->assertFalse($output->isVerbose());
        $this->assertFalse($output->isVeryVerbose());
        $this->assertFalse($output->isDebug());

        $output->setVerbosity(Output::VERBOSITY_VERBOSE);
        $this->assertFalse($output->isQuiet());
        $this->assertTrue($output->isVerbose());
        $this->assertFalse($output->isVeryVerbose());
        $this->assertFalse($output->isDebug());

        $output->setVerbosity(Output::VERBOSITY_VERY_VERBOSE);
        $this->assertFalse($output->isQuiet());
        $this->assertTrue($output->isVerbose());
        $this->assertTrue($output->isVeryVerbose());
        $this->assertFalse($output->isDebug());

        $output->setVerbosity(Output::VERBOSITY_DEBUG);
        $this->assertFalse($output->isQuiet());
        $this->assertTrue($output->isVerbose());
        $this->assertTrue($output->isVeryVerbose());
        $this->assertTrue($output->isDebug());
    }

    public function testWriteWithVerbosityQuiet()
    {
        $output = new TestOutput(Output::VERBOSITY_QUIET);
        $output->writeln('foo');
        $this->assertEquals('', $output->output, '->writeln() outputs nothing if verbosity is set to VERBOSITY_QUIET');
    }

    public function testWriteAnArrayOfMessages()
    {
        $output = new TestOutput();
        $output->writeln(array('foo', 'bar'));
        $this->assertEquals("foo\nbar\n", $output->output, '->writeln() can take an array of messages to output');
    }

    /**
     * @dataProvider provideWriteArguments
     */
    public function testWriteRawMessage($message, $type, $expectedOutput)
    {
        $output = new TestOutput();
        $output->writeln($message, $type);
        $this->assertEquals($expectedOutput, $output->output);
    }

    public function provideWriteArguments()
    {
        return array(
            array('<info>foo</info>', Output::OUTPUT_RAW, "<info>foo</info>\n"),
            array('<info>foo</info>', Output::OUTPUT_PLAIN, "foo\n"),
        );
    }

    public function testWriteWithDecorationTurnedOff()
    {
        $output = new TestOutput();
        $output->setDecorated(false);
        $output->writeln('<info>foo</info>');
        $this->assertEquals("foo\n", $output->output, '->writeln() strips decoration tags if decoration is set to false');
    }

    public function testWriteDecoratedMessage()
    {
        $fooStyle = new OutputFormatterStyle('yellow', 'red', array('blink'));
        $output = new TestOutput();
        $output->getFormatter()->setStyle('FOO', $fooStyle);
        $output->setDecorated(true);
        $output->writeln('<foo>foo</foo>');
        $this->assertEquals("\033[33;41;5mfoo\033[0m\n", $output->output, '->writeln() decorates the output');
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage Unknown output type given (24)
     */
    public function testWriteWithInvalidOutputType()
    {
        $output = new TestOutput();
        $output->writeln('<foo>foo</foo>', 24);
    }

    public function testWriteWithInvalidStyle()
    {
        $output = new TestOutput();

        $output->clear();
        $output->write('<bar>foo</bar>');
        $this->assertEquals('<bar>foo</bar>', $output->output, '->write() do nothing when a style does not exist');

        $output->clear();
        $output->writeln('<bar>foo</bar>');
        $this->assertEquals("<bar>foo</bar>\n", $output->output, '->writeln() do nothing when a style does not exist');
    }
}

class TestOutput extends Output
{
    public $output = '';

    public function clear()
    {
        $this->output = '';
    }

    protected function doWrite($message, $newline)
    {
        $this->output .= $message.($newline ? "\n" : '');
    }
}
PK��ZgO��
�
Ktest/Console/Symfony/Component/Console/Tests/Helper/FormatterHelperTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Helper;

use Symfony\Component\Console\Helper\FormatterHelper;

class FormatterHelperTest extends \PHPUnit_Framework_TestCase
{
    public function testFormatSection()
    {
        $formatter = new FormatterHelper();

        $this->assertEquals(
            '<info>[cli]</info> Some text to display',
            $formatter->formatSection('cli', 'Some text to display'),
            '::formatSection() formats a message in a section'
        );
    }

    public function testFormatBlock()
    {
        $formatter = new FormatterHelper();

        $this->assertEquals(
            '<error> Some text to display </error>',
            $formatter->formatBlock('Some text to display', 'error'),
            '::formatBlock() formats a message in a block'
        );

        $this->assertEquals(
            '<error> Some text to display </error>'."\n" .
            '<error> foo bar              </error>',
            $formatter->formatBlock(array('Some text to display', 'foo bar'), 'error'),
            '::formatBlock() formats a message in a block'
        );

        $this->assertEquals(
            '<error>                        </error>'."\n" .
            '<error>  Some text to display  </error>'."\n" .
            '<error>                        </error>',
            $formatter->formatBlock('Some text to display', 'error', true),
            '::formatBlock() formats a message in a block'
        );
    }

    public function testFormatBlockWithDiacriticLetters()
    {
        if (!extension_loaded('mbstring')) {
            $this->markTestSkipped('This test requires mbstring to work.');
        }

        $formatter = new FormatterHelper();

        $this->assertEquals(
            '<error>                       </error>'."\n" .
            '<error>  Du texte à afficher  </error>'."\n" .
            '<error>                       </error>',
            $formatter->formatBlock('Du texte à afficher', 'error', true),
            '::formatBlock() formats a message in a block'
        );
    }

    public function testFormatBlockLGEscaping()
    {
        $formatter = new FormatterHelper();

        $this->assertEquals(
            '<error>                            </error>'."\n" .
            '<error>  \<info>some info\</info>  </error>'."\n" .
            '<error>                            </error>',
            $formatter->formatBlock('<info>some info</info>', 'error', true),
            '::formatBlock() escapes \'<\' chars'
        );
    }
}
PK��Z�L��"�"Htest/Console/Symfony/Component/Console/Tests/Helper/DialogHelperTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Helper;

use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Helper\DialogHelper;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Helper\FormatterHelper;
use Symfony\Component\Console\Output\StreamOutput;

class DialogHelperTest extends \PHPUnit_Framework_TestCase
{
    public function testSelect()
    {
        $dialog = new DialogHelper();

        $helperSet = new HelperSet(array(new FormatterHelper()));
        $dialog->setHelperSet($helperSet);

        $heroes = array('Superman', 'Batman', 'Spiderman');

        $dialog->setInputStream($this->getInputStream("\n1\n  1  \nFabien\n1\nFabien\n1\n0,2\n 0 , 2  \n\n\n"));
        $this->assertEquals('2', $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes, '2'));
        $this->assertEquals('1', $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes));
        $this->assertEquals('1', $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes));
        $this->assertEquals('1', $dialog->select($output = $this->getOutputStream(), 'What is your favorite superhero?', $heroes, null, false, 'Input "%s" is not a superhero!', false));

        rewind($output->getStream());
        $this->assertContains('Input "Fabien" is not a superhero!', stream_get_contents($output->getStream()));

        try {
            $this->assertEquals('1', $dialog->select($output = $this->getOutputStream(), 'What is your favorite superhero?', $heroes, null, 1));
            $this->fail();
        } catch (\InvalidArgumentException $e) {
            $this->assertEquals('Value "Fabien" is invalid', $e->getMessage());
        }

        $this->assertEquals(array('1'), $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes, null, false, 'Input "%s" is not a superhero!', true));
        $this->assertEquals(array('0', '2'), $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes, null, false, 'Input "%s" is not a superhero!', true));
        $this->assertEquals(array('0', '2'), $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes, null, false, 'Input "%s" is not a superhero!', true));
        $this->assertEquals(array('0', '1'), $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes, '0,1', false, 'Input "%s" is not a superhero!', true));
        $this->assertEquals(array('0', '1'), $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes, ' 0 , 1 ', false, 'Input "%s" is not a superhero!', true));
    }

    public function testAsk()
    {
        $dialog = new DialogHelper();

        $dialog->setInputStream($this->getInputStream("\n8AM\n"));

        $this->assertEquals('2PM', $dialog->ask($this->getOutputStream(), 'What time is it?', '2PM'));
        $this->assertEquals('8AM', $dialog->ask($output = $this->getOutputStream(), 'What time is it?', '2PM'));

        rewind($output->getStream());
        $this->assertEquals('What time is it?', stream_get_contents($output->getStream()));
    }

    public function testAskWithAutocomplete()
    {
        if (!$this->hasSttyAvailable()) {
            $this->markTestSkipped('`stty` is required to test autocomplete functionality');
        }

        // Acm<NEWLINE>
        // Ac<BACKSPACE><BACKSPACE>s<TAB>Test<NEWLINE>
        // <NEWLINE>
        // <UP ARROW><UP ARROW><NEWLINE>
        // <UP ARROW><UP ARROW><UP ARROW><UP ARROW><UP ARROW><TAB>Test<NEWLINE>
        // <DOWN ARROW><NEWLINE>
        // S<BACKSPACE><BACKSPACE><DOWN ARROW><DOWN ARROW><NEWLINE>
        // F00<BACKSPACE><BACKSPACE>oo<TAB><NEWLINE>
        $inputStream = $this->getInputStream("Acm\nAc\177\177s\tTest\n\n\033[A\033[A\n\033[A\033[A\033[A\033[A\033[A\tTest\n\033[B\nS\177\177\033[B\033[B\nF00\177\177oo\t\n");

        $dialog = new DialogHelper();
        $dialog->setInputStream($inputStream);

        $bundles = array('AcmeDemoBundle', 'AsseticBundle', 'SecurityBundle', 'FooBundle');

        $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles));
        $this->assertEquals('AsseticBundleTest', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles));
        $this->assertEquals('FrameworkBundle', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles));
        $this->assertEquals('SecurityBundle', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles));
        $this->assertEquals('FooBundleTest', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles));
        $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles));
        $this->assertEquals('AsseticBundle', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles));
        $this->assertEquals('FooBundle', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles));
    }

    /**
     * @group tty
     */
    public function testAskHiddenResponse()
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->markTestSkipped('This test is not supported on Windows');
        }

        $dialog = new DialogHelper();

        $dialog->setInputStream($this->getInputStream("8AM\n"));

        $this->assertEquals('8AM', $dialog->askHiddenResponse($this->getOutputStream(), 'What time is it?'));
    }

    public function testAskConfirmation()
    {
        $dialog = new DialogHelper();

        $dialog->setInputStream($this->getInputStream("\n\n"));
        $this->assertTrue($dialog->askConfirmation($this->getOutputStream(), 'Do you like French fries?'));
        $this->assertFalse($dialog->askConfirmation($this->getOutputStream(), 'Do you like French fries?', false));

        $dialog->setInputStream($this->getInputStream("y\nyes\n"));
        $this->assertTrue($dialog->askConfirmation($this->getOutputStream(), 'Do you like French fries?', false));
        $this->assertTrue($dialog->askConfirmation($this->getOutputStream(), 'Do you like French fries?', false));

        $dialog->setInputStream($this->getInputStream("n\nno\n"));
        $this->assertFalse($dialog->askConfirmation($this->getOutputStream(), 'Do you like French fries?', true));
        $this->assertFalse($dialog->askConfirmation($this->getOutputStream(), 'Do you like French fries?', true));
    }

    public function testAskAndValidate()
    {
        $dialog = new DialogHelper();
        $helperSet = new HelperSet(array(new FormatterHelper()));
        $dialog->setHelperSet($helperSet);

        $question ='What color was the white horse of Henry IV?';
        $error = 'This is not a color!';
        $validator = function ($color) use ($error) {
            if (!in_array($color, array('white', 'black'))) {
                throw new \InvalidArgumentException($error);
            }

            return $color;
        };

        $dialog->setInputStream($this->getInputStream("\nblack\n"));
        $this->assertEquals('white', $dialog->askAndValidate($this->getOutputStream(), $question, $validator, 2, 'white'));
        $this->assertEquals('black', $dialog->askAndValidate($this->getOutputStream(), $question, $validator, 2, 'white'));

        $dialog->setInputStream($this->getInputStream("green\nyellow\norange\n"));
        try {
            $this->assertEquals('white', $dialog->askAndValidate($this->getOutputStream(), $question, $validator, 2, 'white'));
            $this->fail();
        } catch (\InvalidArgumentException $e) {
            $this->assertEquals($error, $e->getMessage());
        }
    }

    public function testNoInteraction()
    {
        $dialog = new DialogHelper();

        $input = new ArrayInput(array());
        $input->setInteractive(false);

        $dialog->setInput($input);

        $this->assertEquals('not yet', $dialog->ask($this->getOutputStream(), 'Do you have a job?', 'not yet'));
    }

    protected function getInputStream($input)
    {
        $stream = fopen('php://memory', 'r+', false);
        fputs($stream, $input);
        rewind($stream);

        return $stream;
    }

    protected function getOutputStream()
    {
        return new StreamOutput(fopen('php://memory', 'r+', false));
    }

    private function hasSttyAvailable()
    {
        exec('stty 2>&1', $output, $exitcode);

        return $exitcode === 0;
    }
}
PK��Z+��vvEtest/Console/Symfony/Component/Console/Tests/Helper/HelperSetTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Helper;

use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Command\Command;

class HelperSetTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers \Symfony\Component\Console\Helper\HelperSet::__construct
     */
    public function testConstructor()
    {
        $mock_helper = $this->getGenericMockHelper('fake_helper');
        $helperset = new HelperSet(array('fake_helper_alias' => $mock_helper));

        $this->assertEquals($mock_helper, $helperset->get('fake_helper_alias'), '__construct sets given helper to helpers');
        $this->assertTrue($helperset->has('fake_helper_alias'), '__construct sets helper alias for given helper');
    }

    /**
     * @covers \Symfony\Component\Console\Helper\HelperSet::set
     */
    public function testSet()
    {
        $helperset = new HelperSet();
        $helperset->set($this->getGenericMockHelper('fake_helper', $helperset));
        $this->assertTrue($helperset->has('fake_helper'), '->set() adds helper to helpers');

        $helperset = new HelperSet();
        $helperset->set($this->getGenericMockHelper('fake_helper_01', $helperset));
        $helperset->set($this->getGenericMockHelper('fake_helper_02', $helperset));
        $this->assertTrue($helperset->has('fake_helper_01'), '->set() will set multiple helpers on consecutive calls');
        $this->assertTrue($helperset->has('fake_helper_02'), '->set() will set multiple helpers on consecutive calls');

        $helperset = new HelperSet();
        $helperset->set($this->getGenericMockHelper('fake_helper', $helperset), 'fake_helper_alias');
        $this->assertTrue($helperset->has('fake_helper'), '->set() adds helper alias when set');
        $this->assertTrue($helperset->has('fake_helper_alias'), '->set() adds helper alias when set');
    }

    /**
     * @covers \Symfony\Component\Console\Helper\HelperSet::has
     */
    public function testHas()
    {
        $helperset = new HelperSet(array('fake_helper_alias' => $this->getGenericMockHelper('fake_helper')));
        $this->assertTrue($helperset->has('fake_helper'), '->has() finds set helper');
        $this->assertTrue($helperset->has('fake_helper_alias'), '->has() finds set helper by alias');
    }

    /**
     * @covers \Symfony\Component\Console\Helper\HelperSet::get
     */
    public function testGet()
    {
        $helper_01 = $this->getGenericMockHelper('fake_helper_01');
        $helper_02 = $this->getGenericMockHelper('fake_helper_02');
        $helperset = new HelperSet(array('fake_helper_01_alias' => $helper_01, 'fake_helper_02_alias' => $helper_02));
        $this->assertEquals($helper_01, $helperset->get('fake_helper_01'), '->get() returns correct helper by name');
        $this->assertEquals($helper_01, $helperset->get('fake_helper_01_alias'), '->get() returns correct helper by alias');
        $this->assertEquals($helper_02, $helperset->get('fake_helper_02'), '->get() returns correct helper by name');
        $this->assertEquals($helper_02, $helperset->get('fake_helper_02_alias'), '->get() returns correct helper by alias');

        $helperset = new HelperSet();
        try {
            $helperset->get('foo');
            $this->fail('->get() throws \InvalidArgumentException when helper not found');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->get() throws \InvalidArgumentException when helper not found');
            $this->assertContains('The helper "foo" is not defined.', $e->getMessage(), '->get() throws \InvalidArgumentException when helper not found');
        }
    }

    /**
     * @covers \Symfony\Component\Console\Helper\HelperSet::setCommand
     */
    public function testSetCommand()
    {
        $cmd_01 = new Command('foo');
        $cmd_02 = new Command('bar');

        $helperset = new HelperSet();
        $helperset->setCommand($cmd_01);
        $this->assertEquals($cmd_01, $helperset->getCommand(), '->setCommand() stores given command');

        $helperset = new HelperSet();
        $helperset->setCommand($cmd_01);
        $helperset->setCommand($cmd_02);
        $this->assertEquals($cmd_02, $helperset->getCommand(), '->setCommand() overwrites stored command with consecutive calls');
    }

    /**
     * @covers \Symfony\Component\Console\Helper\HelperSet::getCommand
     */
    public function testGetCommand()
    {
        $cmd = new Command('foo');
        $helperset = new HelperSet();
        $helperset->setCommand($cmd);
        $this->assertEquals($cmd, $helperset->getCommand(), '->getCommand() retrieves stored command');
    }

    /**
     * @covers \Symfony\Component\Console\Helper\HelperSet::getIterator
     */
    public function testIteration()
    {
        $helperset = new HelperSet();
        $helperset->set($this->getGenericMockHelper('fake_helper_01', $helperset));
        $helperset->set($this->getGenericMockHelper('fake_helper_02', $helperset));

        $helpers = array('fake_helper_01', 'fake_helper_02');
        $i = 0;

        foreach ($helperset as $helper) {
            $this->assertEquals($helpers[$i++], $helper->getName());
        }
    }

   /**
     * Create a generic mock for the helper interface. Optionally check for a call to setHelperSet with a specific
     * helperset instance.
     *
     * @param string    $name
     * @param HelperSet $helperset allows a mock to verify a particular helperset set is being added to the Helper
     */
    private function getGenericMockHelper($name, HelperSet $helperset = null)
    {
        $mock_helper = $this->getMock('\Symfony\Component\Console\Helper\HelperInterface');
        $mock_helper->expects($this->any())
            ->method('getName')
            ->will($this->returnValue($name));

        if ($helperset) {
            $mock_helper->expects($this->any())
                ->method('setHelperSet')
                ->with($this->equalTo($helperset));
        }

        return $mock_helper;
    }
}
PK��Z]_Դ3)3)Gtest/Console/Symfony/Component/Console/Tests/Helper/TableHelperTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Helper;

use Symfony\Component\Console\Helper\TableHelper;
use Symfony\Component\Console\Output\StreamOutput;

class TableHelperTest extends \PHPUnit_Framework_TestCase
{
    protected $stream;

    protected function setUp()
    {
        $this->stream = fopen('php://memory', 'r+');
    }

    protected function tearDown()
    {
        fclose($this->stream);
        $this->stream = null;
    }

    /**
     * @dataProvider testRenderProvider
     */
    public function testRender($headers, $rows, $layout, $expected)
    {
        $table = new TableHelper();
        $table
            ->setHeaders($headers)
            ->setRows($rows)
            ->setLayout($layout)
        ;
        $table->render($output = $this->getOutputStream());

        $this->assertEquals($expected, $this->getOutputContent($output));
    }

    /**
     * @dataProvider testRenderProvider
     */
    public function testRenderAddRows($headers, $rows, $layout, $expected)
    {
        $table = new TableHelper();
        $table
            ->setHeaders($headers)
            ->addRows($rows)
            ->setLayout($layout)
        ;
        $table->render($output = $this->getOutputStream());

        $this->assertEquals($expected, $this->getOutputContent($output));
    }

    /**
     * @dataProvider testRenderProvider
     */
    public function testRenderAddRowsOneByOne($headers, $rows, $layout, $expected)
    {
        $table = new TableHelper();
        $table
            ->setHeaders($headers)
            ->setLayout($layout)
        ;
        foreach ($rows as $row) {
            $table->addRow($row);
        }
        $table->render($output = $this->getOutputStream());

        $this->assertEquals($expected, $this->getOutputContent($output));
    }

    public function testRenderProvider()
    {
        $books = array(
            array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'),
            array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'),
            array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'),
            array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'),
        );

        return array(
            array(
                array('ISBN', 'Title', 'Author'),
                $books,
                TableHelper::LAYOUT_DEFAULT,
<<<TABLE
+---------------+--------------------------+------------------+
| ISBN          | Title                    | Author           |
+---------------+--------------------------+------------------+
| 99921-58-10-7 | Divine Comedy            | Dante Alighieri  |
| 9971-5-0210-0 | A Tale of Two Cities     | Charles Dickens  |
| 960-425-059-0 | The Lord of the Rings    | J. R. R. Tolkien |
| 80-902734-1-6 | And Then There Were None | Agatha Christie  |
+---------------+--------------------------+------------------+

TABLE
            ),
            array(
                array('ISBN', 'Title', 'Author'),
                $books,
                TableHelper::LAYOUT_COMPACT,
<<<TABLE
 ISBN          Title                    Author           
 99921-58-10-7 Divine Comedy            Dante Alighieri  
 9971-5-0210-0 A Tale of Two Cities     Charles Dickens  
 960-425-059-0 The Lord of the Rings    J. R. R. Tolkien 
 80-902734-1-6 And Then There Were None Agatha Christie  

TABLE
            ),
            array(
                array('ISBN', 'Title', 'Author'),
                $books,
                TableHelper::LAYOUT_BORDERLESS,
<<<TABLE
 =============== ========================== ================== 
  ISBN            Title                      Author            
 =============== ========================== ================== 
  99921-58-10-7   Divine Comedy              Dante Alighieri   
  9971-5-0210-0   A Tale of Two Cities       Charles Dickens   
  960-425-059-0   The Lord of the Rings      J. R. R. Tolkien  
  80-902734-1-6   And Then There Were None   Agatha Christie   
 =============== ========================== ================== 

TABLE
            ),
            array(
                array('ISBN', 'Title'),
                array(
                    array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'),
                    array('9971-5-0210-0'),
                    array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'),
                    array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'),
                ),
                TableHelper::LAYOUT_DEFAULT,
<<<TABLE
+---------------+--------------------------+------------------+
| ISBN          | Title                    |                  |
+---------------+--------------------------+------------------+
| 99921-58-10-7 | Divine Comedy            | Dante Alighieri  |
| 9971-5-0210-0 |                          |                  |
| 960-425-059-0 | The Lord of the Rings    | J. R. R. Tolkien |
| 80-902734-1-6 | And Then There Were None | Agatha Christie  |
+---------------+--------------------------+------------------+

TABLE
            ),
            array(
                array(),
                array(
                    array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'),
                    array('9971-5-0210-0'),
                    array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'),
                    array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'),
                ),
                TableHelper::LAYOUT_DEFAULT,
<<<TABLE
+---------------+--------------------------+------------------+
| 99921-58-10-7 | Divine Comedy            | Dante Alighieri  |
| 9971-5-0210-0 |                          |                  |
| 960-425-059-0 | The Lord of the Rings    | J. R. R. Tolkien |
| 80-902734-1-6 | And Then There Were None | Agatha Christie  |
+---------------+--------------------------+------------------+

TABLE
            ),
            array(
                array('ISBN', 'Title', 'Author'),
                array(
                    array("99921-58-10-7", "Divine\nComedy", "Dante Alighieri"),
                    array("9971-5-0210-2", "Harry Potter\nand the Chamber of Secrets", "Rowling\nJoanne K."),
                    array("9971-5-0210-2", "Harry Potter\nand the Chamber of Secrets", "Rowling\nJoanne K."),
                    array("960-425-059-0", "The Lord of the Rings", "J. R. R.\nTolkien"),
                ),
                TableHelper::LAYOUT_DEFAULT,
<<<TABLE
+---------------+----------------------------+-----------------+
| ISBN          | Title                      | Author          |
+---------------+----------------------------+-----------------+
| 99921-58-10-7 | Divine                     | Dante Alighieri |
|               | Comedy                     |                 |
| 9971-5-0210-2 | Harry Potter               | Rowling         |
|               | and the Chamber of Secrets | Joanne K.       |
| 9971-5-0210-2 | Harry Potter               | Rowling         |
|               | and the Chamber of Secrets | Joanne K.       |
| 960-425-059-0 | The Lord of the Rings      | J. R. R.        |
|               |                            | Tolkien         |
+---------------+----------------------------+-----------------+

TABLE
            ),
            array(
                array('ISBN', 'Title'),
                array(),
                TableHelper::LAYOUT_DEFAULT,
<<<TABLE
+------+-------+
| ISBN | Title |
+------+-------+

TABLE
            ),
            array(
                array(),
                array(),
                TableHelper::LAYOUT_DEFAULT,
                '',
            ),
            'Cell text with tags used for Output styling' => array(
                array('ISBN', 'Title', 'Author'),
                array(
                    array('<info>99921-58-10-7</info>', '<error>Divine Comedy</error>', '<fg=blue;bg=white>Dante Alighieri</fg=blue;bg=white>'),
                    array('9971-5-0210-0', 'A Tale of Two Cities', '<info>Charles Dickens</>'),
                ),
                TableHelper::LAYOUT_DEFAULT,
<<<TABLE
+---------------+----------------------+-----------------+
| ISBN          | Title                | Author          |
+---------------+----------------------+-----------------+
| 99921-58-10-7 | Divine Comedy        | Dante Alighieri |
| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
+---------------+----------------------+-----------------+

TABLE
            ),
            'Cell text with tags not used for Output styling' => array(
                array('ISBN', 'Title', 'Author'),
                array(
                    array('<strong>99921-58-10-700</strong>', '<f>Divine Com</f>', 'Dante Alighieri'),
                    array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'),
                ),
                TableHelper::LAYOUT_DEFAULT,
<<<TABLE
+----------------------------------+----------------------+-----------------+
| ISBN                             | Title                | Author          |
+----------------------------------+----------------------+-----------------+
| <strong>99921-58-10-700</strong> | <f>Divine Com</f>    | Dante Alighieri |
| 9971-5-0210-0                    | A Tale of Two Cities | Charles Dickens |
+----------------------------------+----------------------+-----------------+

TABLE
            ),
        );
    }

    public function testRenderMultiByte()
    {
        if (!function_exists('mb_strlen')) {
            $this->markTestSkipped('The "mbstring" extension is not available');
        }

        $table = new TableHelper();
        $table
            ->setHeaders(array('■■'))
            ->setRows(array(array(1234)))
            ->setLayout(TableHelper::LAYOUT_DEFAULT)
        ;
        $table->render($output = $this->getOutputStream());

        $expected =
<<<TABLE
+------+
| ■■   |
+------+
| 1234 |
+------+

TABLE;

        $this->assertEquals($expected, $this->getOutputContent($output));
    }

    protected function getOutputStream()
    {
        return new StreamOutput($this->stream, StreamOutput::VERBOSITY_NORMAL, false);
    }

    protected function getOutputContent(StreamOutput $output)
    {
        rewind($output->getStream());

        return str_replace(PHP_EOL, "\n", stream_get_contents($output->getStream()));
    }
}
PK��Z"
U���Jtest/Console/Symfony/Component/Console/Tests/Helper/ProgressHelperTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Helper;

use Symfony\Component\Console\Helper\ProgressHelper;
use Symfony\Component\Console\Output\StreamOutput;

class ProgressHelperTest extends \PHPUnit_Framework_TestCase
{
    public function testAdvance()
    {
        $progress = new ProgressHelper();
        $progress->start($output = $this->getOutputStream());
        $progress->advance();

        rewind($output->getStream());
        $this->assertEquals($this->generateOutput('    1 [->--------------------------]'), stream_get_contents($output->getStream()));
    }

    public function testAdvanceWithStep()
    {
        $progress = new ProgressHelper();
        $progress->start($output = $this->getOutputStream());
        $progress->advance(5);

        rewind($output->getStream());
        $this->assertEquals($this->generateOutput('    5 [----->----------------------]'), stream_get_contents($output->getStream()));
    }

    public function testAdvanceMultipleTimes()
    {
        $progress = new ProgressHelper();
        $progress->start($output = $this->getOutputStream());
        $progress->advance(3);
        $progress->advance(2);

        rewind($output->getStream());
        $this->assertEquals($this->generateOutput('    3 [--->------------------------]').$this->generateOutput('    5 [----->----------------------]'), stream_get_contents($output->getStream()));
    }

    public function testCustomizations()
    {
        $progress = new ProgressHelper();
        $progress->setBarWidth(10);
        $progress->setBarCharacter('_');
        $progress->setEmptyBarCharacter(' ');
        $progress->setProgressCharacter('/');
        $progress->setFormat(' %current%/%max% [%bar%] %percent%%');
        $progress->start($output = $this->getOutputStream(), 10);
        $progress->advance();

        rewind($output->getStream());
        $this->assertEquals($this->generateOutput('  1/10 [_/        ]  10%'), stream_get_contents($output->getStream()));
    }

    public function testPercent()
    {
        $progress = new ProgressHelper();
        $progress->start($output = $this->getOutputStream(), 50);
        $progress->display();
        $progress->advance();
        $progress->advance();

        rewind($output->getStream());
        $this->assertEquals($this->generateOutput('  0/50 [>---------------------------]   0%').$this->generateOutput('  1/50 [>---------------------------]   2%').$this->generateOutput('  2/50 [=>--------------------------]   4%'), stream_get_contents($output->getStream()));
    }

    public function testOverwriteWithShorterLine()
    {
        $progress = new ProgressHelper();
        $progress->setFormat(' %current%/%max% [%bar%] %percent%%');
        $progress->start($output = $this->getOutputStream(), 50);
        $progress->display();
        $progress->advance();

        // set shorter format
        $progress->setFormat(' %current%/%max% [%bar%]');
        $progress->advance();

        rewind($output->getStream());
        $this->assertEquals(
            $this->generateOutput('  0/50 [>---------------------------]   0%') .
            $this->generateOutput('  1/50 [>---------------------------]   2%') .
            $this->generateOutput('  2/50 [=>--------------------------]     '),
            stream_get_contents($output->getStream())
        );
    }

    public function testSetCurrentProgress()
    {
        $progress = new ProgressHelper();
        $progress->start($output = $this->getOutputStream(), 50);
        $progress->display();
        $progress->advance();
        $progress->setCurrent(15);
        $progress->setCurrent(25);

        rewind($output->getStream());
        $this->assertEquals(
            $this->generateOutput('  0/50 [>---------------------------]   0%') .
            $this->generateOutput('  1/50 [>---------------------------]   2%') .
            $this->generateOutput(' 15/50 [========>-------------------]  30%') .
            $this->generateOutput(' 25/50 [==============>-------------]  50%'),
            stream_get_contents($output->getStream())
        );
    }

    /**
     * @expectedException        \LogicException
     * @expectedExceptionMessage You must start the progress bar
     */
    public function testSetCurrentBeforeStarting()
    {
        $progress = new ProgressHelper();
        $progress->setCurrent(15);
    }

    /**
     * @expectedException        \LogicException
     * @expectedExceptionMessage You can't regress the progress bar
     */
    public function testRegressProgress()
    {
        $progress = new ProgressHelper();
        $progress->start($output = $this->getOutputStream(), 50);
        $progress->setCurrent(15);
        $progress->setCurrent(10);
    }

    public function testRedrawFrequency()
    {
        $progress = $this->getMock('Symfony\Component\Console\Helper\ProgressHelper', array('display'));
        $progress->expects($this->exactly(4))
                 ->method('display');

        $progress->setRedrawFrequency(2);

        $progress->start($output = $this->getOutputStream(), 6);
        $progress->setCurrent(1);
        $progress->advance(2);
        $progress->advance(2);
        $progress->advance(1);
    }

    public function testMultiByteSupport()
    {
        if (!function_exists('mb_strlen') || (false === $encoding = mb_detect_encoding('■'))) {
            $this->markTestSkipped('The mbstring extension is needed for multi-byte support');
        }

        $progress = new ProgressHelper();
        $progress->start($output = $this->getOutputStream());
        $progress->setBarCharacter('■');
        $progress->advance(3);

        rewind($output->getStream());
        $this->assertEquals($this->generateOutput('    3 [■■■>------------------------]'), stream_get_contents($output->getStream()));
    }

    public function testClear()
    {
        $progress = new ProgressHelper();
        $progress->start($output = $this->getOutputStream(), 50);
        $progress->setCurrent(25);
        $progress->clear();

        rewind($output->getStream());
        $this->assertEquals(
            $this->generateOutput(' 25/50 [==============>-------------]  50%') . $this->generateOutput(''),
            stream_get_contents($output->getStream())
        );
    }

    public function testPercentNotHundredBeforeComplete()
    {
        $progress = new ProgressHelper();
        $progress->start($output = $this->getOutputStream(), 200);
        $progress->display();
        $progress->advance(199);
        $progress->advance();

        rewind($output->getStream());
        $this->assertEquals($this->generateOutput('   0/200 [>---------------------------]   0%').$this->generateOutput(' 199/200 [===========================>]  99%').$this->generateOutput(' 200/200 [============================] 100%'), stream_get_contents($output->getStream()));
    }

    protected function getOutputStream()
    {
        return new StreamOutput(fopen('php://memory', 'r+', false));
    }

    protected $lastMessagesLength;

    protected function generateOutput($expected)
    {
        $expectedout = $expected;

        if ($this->lastMessagesLength !== null) {
            $expectedout = str_pad($expected, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT);
        }

        $this->lastMessagesLength = strlen($expectedout);

        return "\x0D".$expectedout;
    }
}
PK��ZK� 99Ntest/Console/Symfony/Component/Console/Tests/Descriptor/TextDescriptorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Descriptor;

use Symfony\Component\Console\Descriptor\TextDescriptor;

class TextDescriptorTest extends AbstractDescriptorTest
{
    protected function getDescriptor()
    {
        return new TextDescriptor();
    }

    protected function getFormat()
    {
        return 'txt';
    }
}
PK��Z1H�DDDRtest/Console/Symfony/Component/Console/Tests/Descriptor/MarkdownDescriptorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Descriptor;

use Symfony\Component\Console\Descriptor\MarkdownDescriptor;

class MarkdownDescriptorTest extends AbstractDescriptorTest
{
    protected function getDescriptor()
    {
        return new MarkdownDescriptor();
    }

    protected function getFormat()
    {
        return 'md';
    }
}
PK��ZoW��::Ntest/Console/Symfony/Component/Console/Tests/Descriptor/JsonDescriptorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Descriptor;

use Symfony\Component\Console\Descriptor\JsonDescriptor;

class JsonDescriptorTest extends AbstractDescriptorTest
{
    protected function getDescriptor()
    {
        return new JsonDescriptor();
    }

    protected function getFormat()
    {
        return 'json';
    }
}
PK��Z���66Mtest/Console/Symfony/Component/Console/Tests/Descriptor/XmlDescriptorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Descriptor;

use Symfony\Component\Console\Descriptor\XmlDescriptor;

class XmlDescriptorTest extends AbstractDescriptorTest
{
    protected function getDescriptor()
    {
        return new XmlDescriptor();
    }

    protected function getFormat()
    {
        return 'xml';
    }
}
PK��Z�ž_JJKtest/Console/Symfony/Component/Console/Tests/Descriptor/ObjectsProvider.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Descriptor;

use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Tests\Fixtures\DescriptorApplication1;
use Symfony\Component\Console\Tests\Fixtures\DescriptorApplication2;
use Symfony\Component\Console\Tests\Fixtures\DescriptorCommand1;
use Symfony\Component\Console\Tests\Fixtures\DescriptorCommand2;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class ObjectsProvider
{
    public static function getInputArguments()
    {
        return array(
            'input_argument_1' => new InputArgument('argument_name', InputArgument::REQUIRED),
            'input_argument_2' => new InputArgument('argument_name', InputArgument::IS_ARRAY, 'argument description'),
            'input_argument_3' => new InputArgument('argument_name', InputArgument::OPTIONAL, 'argument description', 'default_value'),
        );
    }

    public static function getInputOptions()
    {
        return array(
            'input_option_1' => new InputOption('option_name', 'o', InputOption::VALUE_NONE),
            'input_option_2' => new InputOption('option_name', 'o', InputOption::VALUE_OPTIONAL, 'option description', 'default_value'),
            'input_option_3' => new InputOption('option_name', 'o', InputOption::VALUE_REQUIRED, 'option description'),
            'input_option_4' => new InputOption('option_name', 'o', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL, 'option description', array()),
        );
    }

    public static function getInputDefinitions()
    {
        return array(
            'input_definition_1' => new InputDefinition(),
            'input_definition_2' => new InputDefinition(array(new InputArgument('argument_name', InputArgument::REQUIRED))),
            'input_definition_3' => new InputDefinition(array(new InputOption('option_name', 'o', InputOption::VALUE_NONE))),
            'input_definition_4' => new InputDefinition(array(
                new InputArgument('argument_name', InputArgument::REQUIRED),
                new InputOption('option_name', 'o', InputOption::VALUE_NONE),
            )),
        );
    }

    public static function getCommands()
    {
        return array(
            'command_1' => new DescriptorCommand1(),
            'command_2' => new DescriptorCommand2(),
        );
    }

    public static function getApplications()
    {
        return array(
            'application_1' => new DescriptorApplication1(),
            'application_2' => new DescriptorApplication2(),
        );
    }
}
PK��Z}�
��Rtest/Console/Symfony/Component/Console/Tests/Descriptor/AbstractDescriptorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Descriptor;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\BufferedOutput;

abstract class AbstractDescriptorTest extends \PHPUnit_Framework_TestCase
{
    /** @dataProvider getDescribeInputArgumentTestData */
    public function testDescribeInputArgument(InputArgument $argument, $expectedDescription)
    {
        $this->assertDescription($expectedDescription, $argument);
    }

    /** @dataProvider getDescribeInputOptionTestData */
    public function testDescribeInputOption(InputOption $option, $expectedDescription)
    {
        $this->assertDescription($expectedDescription, $option);
    }

    /** @dataProvider getDescribeInputDefinitionTestData */
    public function testDescribeInputDefinition(InputDefinition $definition, $expectedDescription)
    {
        $this->assertDescription($expectedDescription, $definition);
    }

    /** @dataProvider getDescribeCommandTestData */
    public function testDescribeCommand(Command $command, $expectedDescription)
    {
        $this->assertDescription($expectedDescription, $command);
    }

    /** @dataProvider getDescribeApplicationTestData */
    public function testDescribeApplication(Application $application, $expectedDescription)
    {
        // Replaces the dynamic placeholders of the command help text with a static version.
        // The placeholder %command.full_name% includes the script path that is not predictable
        // and can not be tested against.
        foreach ($application->all() as $command) {
            $command->setHelp(str_replace('%command.full_name%', 'app/console %command.name%', $command->getHelp()));
        }

        $this->assertDescription($expectedDescription, $application);
    }

    public function getDescribeInputArgumentTestData()
    {
        return $this->getDescriptionTestData(ObjectsProvider::getInputArguments());
    }

    public function getDescribeInputOptionTestData()
    {
        return $this->getDescriptionTestData(ObjectsProvider::getInputOptions());
    }

    public function getDescribeInputDefinitionTestData()
    {
        return $this->getDescriptionTestData(ObjectsProvider::getInputDefinitions());
    }

    public function getDescribeCommandTestData()
    {
        return $this->getDescriptionTestData(ObjectsProvider::getCommands());
    }

    public function getDescribeApplicationTestData()
    {
        return $this->getDescriptionTestData(ObjectsProvider::getApplications());
    }

    abstract protected function getDescriptor();
    abstract protected function getFormat();

    private function getDescriptionTestData(array $objects)
    {
        $data = array();
        foreach ($objects as $name => $object) {
            $description = file_get_contents(sprintf('%s/../Fixtures/%s.%s', __DIR__, $name, $this->getFormat()));
            $data[] = array($object, $description);
        }

        return $data;
    }

    private function assertDescription($expectedDescription, $describedObject)
    {
        $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
        $this->getDescriptor()->describe($output, $describedObject, array('raw_output' => true));
        $this->assertEquals(trim($expectedDescription), trim(str_replace(PHP_EOL, "\n", $output->fetch())));
    }
}
PK��Z?�UHii7test/Console/Symfony/Component/Console/phpunit.xml.distnu�[���<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony Console Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./Resources</directory>
                <directory>./Tests</directory>
                <directory>./vendor</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
PK��Ze�>��4�4/test/XML_Util/tests/CreateTagFromArrayTests.phpnu�[���<?php

class CreateTagFromArrayTests extends AbstractUnitTests
{
    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQname()
    {
        $original = array(
            "qname" => "foo:bar",
        );
        $expected = "<foo:bar />";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameAndNamespace()
    {
        $original = array(
            "qname" => "foo:bar",
            "namespaceUri" => "http://foo.com",
        );
        $expected = "<foo:bar xmlns:foo=\"http://foo.com\" />";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameAndNamespaceAndAttributes()
    {
        $original = array(
            "qname" => "foo:bar",
            "namespaceUri" => "http://foo.com",
            "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
        );
        $expected = "<foo:bar argh=\"fruit&amp;vegetable\" key=\"value\" xmlns:foo=\"http://foo.com\" />";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameAndNamespaceAndAttributesAndContent()
    {
        $original = array(
            "qname" => "foo:bar",
            "namespaceUri" => "http://foo.com",
            "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
            "content"      => "I'm inside the tag",
        );
        $expected = "<foo:bar argh=\"fruit&amp;vegetable\" key=\"value\" xmlns:foo=\"http://foo.com\">I&apos;m inside the tag</foo:bar>";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameAndAttributesAndContent()
    {
        $original = array(
            "qname" => "foo:bar",
            "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
            "content"      => "I'm inside the tag",
        );
        $expected = "<foo:bar argh=\"fruit&amp;vegetable\" key=\"value\">I&apos;m inside the tag</foo:bar>";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameAndNamespaceAndContent()
    {
        $original = array(
            "qname" => "foo:bar",
            "namespaceUri" => "http://foo.com",
            "content"      => "I'm inside the tag",
        );
        $expected = "<foo:bar xmlns:foo=\"http://foo.com\">I&apos;m inside the tag</foo:bar>";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameAndNamespaceAndAttributesAndContentWithEntitiesNone()
    {
        $original = array(
            "qname" => "foo:bar",
            "namespaceUri" => "http://foo.com",
            "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
            "content"      => "I'm inside the tag",
        );
        $expected = "<foo:bar argh=\"fruit&amp;vegetable\" key=\"value\" xmlns:foo=\"http://foo.com\">I'm inside the tag</foo:bar>";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original, XML_UTIL_ENTITIES_NONE));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameAndNamespaceAndAttributesAndContentWithReplaceEntities()
    {
        $original = array(
            "qname" => "foo:bar",
            "namespaceUri" => "http://foo.com",
            "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
            "content"      => "I'm inside the tag",
        );
        $expected = "<foo:bar argh=\"fruit&amp;vegetable\" key=\"value\" xmlns:foo=\"http://foo.com\">I&apos;m inside the tag</foo:bar>";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original, XML_UTIL_REPLACE_ENTITIES));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameAndNamespaceAndAttributesAndContentWithReplaceEntitiesAndMultilineFalse()
    {
        $original = array(
            "qname" => "foo:bar",
            "namespaceUri" => "http://foo.com",
            "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
            "content"      => "I'm inside the tag",
        );
        $multiline = false;
        $expected = "<foo:bar argh=\"fruit&amp;vegetable\" key=\"value\" xmlns:foo=\"http://foo.com\">I&apos;m inside the tag</foo:bar>";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original, XML_UTIL_REPLACE_ENTITIES, $multiline));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameAndNamespaceAndAttributesAndContentWithReplaceEntitiesAndMultilineTrue()
    {
        $original = array(
            "qname" => "foo:bar",
            "namespaceUri" => "http://foo.com",
            "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
            "content"      => "I'm inside the tag",
        );
        $multiline = true;
        $expected =
<<< EOF
<foo:bar argh="fruit&amp;vegetable"
         key="value"
         xmlns:foo="http://foo.com">I&apos;m inside the tag</foo:bar>
EOF;
        $this->assertEquals($expected, XML_Util::createTagFromArray($original, XML_UTIL_REPLACE_ENTITIES, $multiline));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameAndNamespaceAndAttributesAndContentWithReplaceEntitiesAndMultilineTrueAndIndent()
    {
        $original = array(
            "qname" => "foo:bar",
            "namespaceUri" => "http://foo.com",
            "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
            "content"      => "I'm inside the tag",
        );
        $multiline = true;
        $indent = "  ";
        $expected =
<<< EOF
<foo:bar argh="fruit&amp;vegetable"
  key="value"
  xmlns:foo="http://foo.com">I&apos;m inside the tag</foo:bar>
EOF;
        $this->assertEquals($expected, XML_Util::createTagFromArray($original, XML_UTIL_REPLACE_ENTITIES, $multiline, $indent));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameAndNamespaceAndAttributesAndContentWithReplaceEntitiesAndMultilineTrueAndIndentAndLinebreak()
    {
        $original = array(
            "qname" => "foo:bar",
            "namespaceUri" => "http://foo.com",
            "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
            "content"      => "I'm inside the tag",
        );
        $multiline = true;
        $indent = "  ";
        $linebreak = "^";
        $expected = "<foo:bar argh=\"fruit&amp;vegetable\"^  key=\"value\"^  xmlns:foo=\"http://foo.com\">I&apos;m inside the tag</foo:bar>";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original, XML_UTIL_REPLACE_ENTITIES, $multiline, $indent, $linebreak));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameAndNamespaceAndAttributesAndContentWithReplaceEntitiesAndMultilineTrueAndIndentAndLinebreakAndSortAttributesTrue()
    {
        $original = array(
            "qname" => "foo:bar",
            "namespaceUri" => "http://foo.com",
            "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
            "content"      => "I'm inside the tag",
        );
        $multiline = true;
        $indent = "  ";
        $linebreak = "^";
        $sortAttributes = true;
        $expected = "<foo:bar argh=\"fruit&amp;vegetable\"^  key=\"value\"^  xmlns:foo=\"http://foo.com\">I&apos;m inside the tag</foo:bar>";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original, XML_UTIL_REPLACE_ENTITIES, $multiline, $indent, $linebreak, $sortAttributes));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameAndNamespaceAndAttributesAndContentWithReplaceEntitiesAndMultilineTrueAndIndentAndLinebreakAndSortAttributesFalse()
    {
        $original = array(
            "qname" => "foo:bar",
            "namespaceUri" => "http://foo.com",
            "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
            "content"      => "I'm inside the tag",
        );
        $multiline = true;
        $indent = "  ";
        $linebreak = "^";
        $sortAttributes = false;
        $expected = "<foo:bar key=\"value\"^  argh=\"fruit&amp;vegetable\"^  xmlns:foo=\"http://foo.com\">I&apos;m inside the tag</foo:bar>";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original, XML_UTIL_REPLACE_ENTITIES, $multiline, $indent, $linebreak, $sortAttributes));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithInvalidArray()
    {
        $badArray = array(
            "foo" => "bar",
        );
        $expectedError = "You must either supply a qualified name (qname) or local tag name (localPart).";
        $this->assertEquals($expectedError, XML_Util::createTagFromArray($badArray));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithNamespaceAndAttributesAndContentButWithoutQname()
    {
        $original = array(
            "namespaceUri" => "http://foo.com",
            "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
            "content"      => "I'm inside the tag",
        );
        $expectedError = "You must either supply a qualified name (qname) or local tag name (localPart).";
        $this->assertEquals($expectedError, XML_Util::createTagFromArray($original));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithNonScalarContent()
    {
        $badArray = array(
            'content' => array('foo', 'bar'),
        );
        $expectedError = "Supplied non-scalar value as tag content";
        $this->assertEquals($expectedError, XML_Util::createTagFromArray($badArray));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithArrayOfNamespaces()
    {
        $original = array(
            'qname'        => 'foo:bar',
            'namespaces'   => array('ns1' => 'uri1', 'ns2' => 'uri2'),
        );
        $expected = "<foo:bar xmlns:ns1=\"uri1\" xmlns:ns2=\"uri2\" />";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameDerivedFromNamespaceUriAndLocalPart()
    {
        $original = array(
            'namespaceUri' => 'http://bar.org',
            'localPart'    => 'foo'
        );
        $expected = "<foo xmlns=\"http://bar.org\" />";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameDerivedFromNamespaceAndLocalPart()
    {
        $original = array(
            'namespace'    => 'http://foo.org',
            'localPart'    => 'bar'
        );
        $expected = "<http://foo.org:bar />";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameDerivedFromLocalPart()
    {
        $original = array(
            'namespace'    => '',
            'localPart'    => 'bar'
        );
        $expected = "<bar />";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithImplicitlyEmptyContentAndCollapseNoneDoesNotCollapseTag()
    {
        $original = array('qname' => 'tag1');
        $expected = "<tag1></tag1>";
        $actual = XML_Util::createTagFromArray(
            $original,
            XML_UTIL_REPLACE_ENTITIES,  // default $replaceEntities
            false,                      // default $multiline
            '_auto',                    // default $indent
            "\n",                       // default $linebreak
            true,                       // default $sortAttributes
            XML_UTIL_COLLAPSE_NONE
        );
        $this->assertEquals($expected, $actual);
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayForCdataWithExplicitlyEmptyContentDoesNotCollapseTag()
    {
        $original = array('qname' => 'tag1', 'content' => '');
        $expected = "<tag1><![CDATA[]]></tag1>";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original, XML_UTIL_CDATA_SECTION));
    }
}
PK��Z�C���,test/XML_Util/tests/ReplaceEntitiesTests.phpnu�[���<?php

class ReplaceEntitiesTests extends AbstractUnitTests
{
    protected function getSimpleData()
    {
        return 'This string contains < & >.';
    }

    protected function getUtf8Data()
    {
        return 'This data contains special chars like <, >, & and " as well as ä, ö, ß, à and ê';
    }

    /**
     * @covers XML_Util::replaceEntities()
     */
    public function testReplaceEntitiesForSimpleData()
    {
        $expected = "This string contains &lt; &amp; &gt;.";
        $this->assertEquals($expected, XML_Util::replaceEntities($this->getSimpleData()));
    }

    /**
     * @covers XML_Util::replaceEntities()
     */
    public function testReplaceEntitiesForSimpleDataWithInvalidOptionReturnsOriginalData()
    {
        $expected = "This string contains < & >.";
        $this->assertEquals($expected, XML_Util::replaceEntities($this->getSimpleData(), 'INVALID_OPTION'));
    }

    /**
     * @covers XML_Util::replaceEntities()
     */
    public function testReplaceEntitiesForSimpleDataWithEntitiesXml()
    {
        $expected = "This string contains &lt; &amp; &gt;.";
        $this->assertEquals($expected, XML_Util::replaceEntities($this->getSimpleData(), XML_UTIL_ENTITIES_XML));
    }

    /**
     * @covers XML_Util::replaceEntities()
     */
    public function testReplaceEntitiesForSimpleDataWithEntitiesXmlAndEncoding()
    {
        $encoding = "UTF-8";
        $expected = "This string contains &lt; &amp; &gt;.";
        $this->assertEquals($expected, XML_Util::replaceEntities($this->getSimpleData(), XML_UTIL_ENTITIES_XML, $encoding));
    }

    /**
     * @covers XML_Util::replaceEntities()
     */
    public function testReplaceEntitiesForUtf8DataWithEntitiesXmlAndEncoding()
    {
        $encoding = "UTF-8";
        $expected = "This data contains special chars like &lt;, &gt;, &amp; and &quot; as well as ä, ö, ß, à and ê";
        $this->assertEquals($expected, XML_Util::replaceEntities($this->getUtf8Data(), XML_UTIL_ENTITIES_XML, $encoding));
    }

    /**
     * @covers XML_Util::replaceEntities()
     */
    public function testReplaceEntitiesForSimpleDataWithEntitiesXmlRequired()
    {
        $expected = "This string contains &lt; &amp; >.";
        $this->assertEquals($expected, XML_Util::replaceEntities($this->getSimpleData(), XML_UTIL_ENTITIES_XML_REQUIRED));
    }

    /**
     * @covers XML_Util::replaceEntities()
     */
    public function testReplaceEntitiesForSimpleDataWithEntitiesXmlRequiredAndEncoding()
    {
        $encoding = "UTF-8";
        $expected = "This string contains &lt; &amp; >.";
        $this->assertEquals($expected, XML_Util::replaceEntities($this->getSimpleData(), XML_UTIL_ENTITIES_XML_REQUIRED, $encoding));
    }

    /**
     * @covers XML_Util::replaceEntities()
     */
    public function testReplaceEntitiesForUtf8DataWithEntitiesXmlRequiredAndEncoding()
    {
        $encoding = "UTF-8";
        $expected = "This data contains special chars like &lt;, >, &amp; and &quot; as well as ä, ö, ß, à and ê";
        $this->assertEquals($expected, XML_Util::replaceEntities($this->getUtf8Data(), XML_UTIL_ENTITIES_XML_REQUIRED, $encoding));
    }

    /**
     * @covers XML_Util::replaceEntities()
     */
    public function testReplaceEntitiesForSimpleDataWithEntitiesHtml()
    {
        $expected = "This string contains &lt; &amp; &gt;.";
        $this->assertEquals($expected, XML_Util::replaceEntities($this->getSimpleData(), XML_UTIL_ENTITIES_HTML));
    }

    /**
     * @covers XML_Util::replaceEntities()
     */
    public function testReplaceEntitiesForSimpleDataWithEntitiesHtmlAndEncoding()
    {
        $encoding = "UTF-8";
        $expected = "This string contains &lt; &amp; &gt;.";
        $this->assertEquals($expected, XML_Util::replaceEntities($this->getSimpleData(), XML_UTIL_ENTITIES_HTML, $encoding));
    }

    /**
     * @covers XML_Util::replaceEntities()
     */
    public function testReplaceEntitiesForUtf8DataWithEntitiesHtmlAndEncoding()
    {
        $encoding = "UTF-8";
        $expected = "This data contains special chars like &lt;, &gt;, &amp; and &quot; as well as &auml;, &ouml;, &szlig;, &agrave; and &ecirc;";
        $this->assertEquals($expected, XML_Util::replaceEntities($this->getUtf8Data(), XML_UTIL_ENTITIES_HTML, $encoding));
    }
}
PK��Zیu���'test/XML_Util/tests/ApiVersionTests.phpnu�[���<?php

class ApiVersionTests extends AbstractUnitTests
{
    /**
     * @covers XML_Util::apiVersion()
     */
    public function testApiVersion()
    {
        $this->assertEquals('1.4', XML_Util::apiVersion());
    }
}PK��Z�Gs���$test/XML_Util/tests/Bug5392Tests.phpnu�[���<?php

/**
 * Bug #5392 "encoding of ISO-8859-1 is the only supported encoding"
 *
 * Original characters of the given encoding that are "replaced"
 * should then "reverse" back to perfectly match the original.
 *
 * @link https://pear.php.net/bugs/bug.php?id=5392
 */
class Bug5392Tests extends AbstractUnitTests
{
    public function testReplaceEntitiesForBug5392()
    {
        $original = 'This data contains special chars like <, >, & and " as well as ä, ö, ß, à and ê';
        $replacedResult = XML_Util::replaceEntities($original, XML_UTIL_ENTITIES_HTML, "UTF-8");
        $reversedResult = XML_Util::reverseEntities($replacedResult, XML_UTIL_ENTITIES_HTML, "UTF-8");
        $this->assertEquals($original, $reversedResult, "Failed bugcheck.");
    }
}
PK��Z4e��jj/test/XML_Util/tests/CreateCDataSectionTests.phpnu�[���<?php

class CreateCDataSectionTests extends AbstractUnitTests
{
    /**
     * @covers XML_Util::createCDataSection()
     */
    public function testCreateCDataSectionBasicUsage()
    {
        $original = "I am content.";
        $expected ="<![CDATA[I am content.]]>";
        $this->assertEquals($expected, XML_Util::createCDataSection($original));
    }
}
PK��Z|�\5.test/XML_Util/tests/CollapseEmptyTagsTests.phpnu�[���<?php

class CollapseEmptyTagsTests extends AbstractUnitTests
{
    /**
     * @covers XML_Util::collapseEmptyTags()
     */
    public function testCollapseEmptyTagsBasicUsage()
    {
        $emptyTag = "<foo></foo>";
        $expected = "<foo />";
        $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag));
    }

    /**
     * @covers XML_Util::collapseEmptyTags()
     */
    public function testCollapseEmptyTagsBasicUsageAlongsideNonemptyTag()
    {
        $emptyTag = "<foo></foo>";
        $otherTag = "<bar>baz</bar>";
        $expected = "<foo /><bar>baz</bar>";
        $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag . $otherTag));
    }

    /**
     * @covers XML_Util::collapseEmptyTags()
     */
    public function testCollapseEmptyTagsOnOneEmptyTagWithCollapseAll()
    {
        $emptyTag = "<foo></foo>";
        $expected = "<foo />";
        $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag, XML_UTIL_COLLAPSE_ALL));
    }

    /**
     * @covers XML_Util::collapseEmptyTags()
     */
    public function testCollapseEmptyTagsOnOneEmptyTagAlongsideNonemptyTagWithCollapseAll()
    {
        $emptyTag = "<foo></foo>";
        $otherTag = "<bar>baz</bar>";
        $expected = "<foo /><bar>baz</bar>";
        $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag . $otherTag, XML_UTIL_COLLAPSE_ALL));
    }

    /**
     * @covers XML_Util::collapseEmptyTags()
     */
    public function testCollapseEmptyTagsOnOneEmptyTagAlongsideNonemptyTagAlongsideEmptyTagWithCollapseAll()
    {
        $emptyTag = "<foo></foo>";
        $otherTag = "<bar>baz</bar>";
        $expected = "<foo /><bar>baz</bar><foo />";
        $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag . $otherTag . $emptyTag, XML_UTIL_COLLAPSE_ALL));
    }

    /**
     * @covers XML_Util::collapseEmptyTags()
     */
    public function testCollapseEmptyTagsOnOneEmptyPrefixedTagAlongsideNonemptyTagAlongsideEmptyPrefixedTagWithCollapseAll()
    {
        $emptyTag = "<foo:foo2></foo:foo2>";
        $otherTag = "<bar>baz</bar>";
        $expected = "<foo:foo2 /><bar>baz</bar><foo:foo2 />";
        $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag . $otherTag . $emptyTag, XML_UTIL_COLLAPSE_ALL));
    }

    /**
     * @covers XML_Util::collapseEmptyTags()
     */
    public function testCollapseEmptyTagsOnOneEmptyNsPrefixedTagAlongsideNonemptyTagAlongsideEmptyNsPrefixedTagWithCollapseAll()
    {
        $emptyTag = "<http://foo.com:foo2></http://foo.com:foo2>";
        $otherTag = "<bar>baz</bar>";
        $expected = "<http://foo.com:foo2 /><bar>baz</bar><http://foo.com:foo2 />";
        $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag . $otherTag . $emptyTag, XML_UTIL_COLLAPSE_ALL));
    }

    /**
     * @covers XML_Util::collapseEmptyTags()
     */
    public function testCollapseEmptyTagsOnOneEmptyTagWithCollapseXhtml()
    {
        $emptyTag = "<foo></foo>";
        $expected = "<foo></foo>";
        $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag, XML_UTIL_COLLAPSE_XHTML_ONLY));
    }

    /**
     * @covers XML_Util::collapseEmptyTags()
     */
    public function testCollapseEmptyTagsOnOneEmptyTagAlongsideNonemptyTagWithCollapseXhtml()
    {
        $emptyTag = "<foo></foo>";
        $otherTag = "<bar>baz</bar>";
        $xhtmlTag = "<br></br>";
        $expected = "<foo></foo><br /><bar>baz</bar>";
        $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag . $xhtmlTag . $otherTag, XML_UTIL_COLLAPSE_XHTML_ONLY));
    }

    /**
     * @covers XML_Util::collapseEmptyTags()
     */
    public function testCollapseEmptyTagsOnOneEmptyTagWithCollapseNone()
    {
        $emptyTag = "<foo></foo>";
        $expected = "<foo></foo>";
        $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag, XML_UTIL_COLLAPSE_NONE));
    }

    /**
     * @covers XML_Util::collapseEmptyTags()
     */
    public function testCollapseEmptyTagsOnOneEmptyTagAlongsideNonemptyTagWithCollapseNone()
    {
        $emptyTag = "<foo></foo>";
        $otherTag = "<bar>baz</bar>";
        $expected = "<foo></foo><bar>baz</bar>";
        $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag . $otherTag, XML_UTIL_COLLAPSE_NONE));
    }
}
PK��Z��GG/test/XML_Util/tests/SplitQualifiedNameTests.phpnu�[���<?php

class SplitQualifiedNameTests extends AbstractUnitTests
{
    /**
     * @covers XML_Util::splitQualifiedName()
     */
    public function testSplitQualifiedNameWithoutNamespace()
    {
        $original = "xslt:stylesheet";
        $expected = array(
            'namespace' => 'xslt',
            'localPart' => 'stylesheet',
        );
        $this->assertEquals($expected, XML_Util::splitQualifiedName($original));
    }

    /**
     * @covers XML_Util::splitQualifiedName()
     */
    public function testSplitQualifiedNameWithNamespace()
    {
        $original = "stylesheet";
        $namespace = "myNs";
        $expected = array(
            'namespace' => 'myNs',
            'localPart' => 'stylesheet',
        );
        $this->assertEquals($expected, XML_Util::splitQualifiedName($original, $namespace));
    }
}
PK��ZYq���%test/XML_Util/tests/Bug21184Tests.phpnu�[���<?php

/**
 * Bug #21184
 *
 * PREG returns NULL when it encounters an error.
 * In this case, it was encountering PREG_BACKTRACK_LIMIT_ERROR.
 *
 * @link https://pear.php.net/bugs/bug.php?id=21177
 */
class Bug21184 extends AbstractUnitTests
{
    public function testBug21184()
    {
        $xml = '<XML_Serializer_Tag>one</XML_Serializer_Tag>';
        $this->assertEquals($xml, XML_Util::collapseEmptyTags($xml, XML_UTIL_COLLAPSE_ALL));
    }
}
PK��Z>�M���$test/XML_Util/tests/Bug4950Tests.phpnu�[���<?php

/**
 * Bug #4950 "Incorrect CDATA serializing"
 *
 * Content that looks like CDATA end characters and tags
 * should still be recognized solely as content text.
 *
 * @link https://pear.php.net/bugs/bug.php?id=4950
 */
class Bug4950Tests extends AbstractUnitTests
{
    public function testCreateTagForBug4950()
    {
        $qname = "test";
        $attributes = array();
        $content = "Content ]]></test> here!";
        $namespaceUrl = null;
        $expected = "<test><![CDATA[Content ]]]]><![CDATA[></test> here!]]></test>";
        $result = XML_Util::createTag($qname, $attributes, $content, $namespaceUrl, XML_UTIL_CDATA_SECTION);
        $this->assertEquals($expected, $result, "Failed bugcheck.");
    }
}
PK��Z�YR�""/test/XML_Util/tests/CreateStartElementTests.phpnu�[���<?php

class CreateStartElementTests extends AbstractUnitTests
{
    /**
     * @covers XML_Util::createStartElement()
     */
    public function testCreateStartElementForTagOnly()
    {
        $original = "myNs:myTag";
        $expected = "<myNs:myTag>";
        $this->assertEquals($expected, XML_Util::createStartElement($original));
    }

    /**
     * @covers XML_Util::createStartElement()
     */
    public function testCreateStartElementForTagWithAttributes()
    {
        $originalTag = "myNs:myTag";
        $originalAttributes = array("foo" => "bar");
        $expected = "<myNs:myTag foo=\"bar\">";
        $this->assertEquals($expected, XML_Util::createStartElement($originalTag, $originalAttributes));
    }

    /**
     * @covers XML_Util::createStartElement()
     */
    public function testCreateStartElementForTagWithEmptyAttributes()
    {
        $originalTag = "myNs:myTag";
        $originalAttributes = "";
        $expected = "<myNs:myTag>";
        $this->assertEquals($expected, XML_Util::createStartElement($originalTag, $originalAttributes));
    }

    /**
     * @covers XML_Util::createStartElement()
     */
    public function testCreateStartElementForTagWithAttributesAndNamespace()
    {
        $originalTag = "myNs:myTag";
        $originalAttributes = array("foo" => "bar");
        $originalNamespace = "http://www.w3c.org/myNs#";
        $expected = "<myNs:myTag foo=\"bar\" xmlns:myNs=\"http://www.w3c.org/myNs#\">";
        $this->assertEquals($expected, XML_Util::createStartElement($originalTag, $originalAttributes, $originalNamespace));
    }

    /**
     * @covers XML_Util::createStartElement()
     */
    public function testCreateStartElementForTagWithEmptyAttributesAndNonUriNamespace()
    {
        $originalTag = "myTag";
        $originalAttributes = "";
        $originalNamespace = "foo";
        $expected = "<myTag xmlns=\"foo\">";
        $this->assertEquals($expected, XML_Util::createStartElement($originalTag, $originalAttributes, $originalNamespace));
    }

    /**
     * @covers XML_Util::createStartElement()
     */
    public function testCreateStartElementForTagWithAttributesAndNamespaceWithMultiline()
    {
        $originalTag = "myNs:myTag";
        $originalAttributes = array("foo" => "bar");
        $originalNamespace = "http://www.w3c.org/myNs#";
        $expected =
<<< EOF
<myNs:myTag foo="bar"
            xmlns:myNs="http://www.w3c.org/myNs#">
EOF;
        $multiline = true;
        $this->assertEquals($expected, XML_Util::createStartElement($originalTag, $originalAttributes, $originalNamespace, $multiline));
    }

    /**
     * @covers XML_Util::createStartElement()
     */
    public function testCreateStartElementForTagWithAttributesAndNamespaceWithMultilineAndIndent()
    {
        $originalTag = "myNs:myTag";
        $originalAttributes = array("foo" => "bar");
        $originalNamespace = "http://www.w3c.org/myNs#";
        $expected =
<<< EOF
<myNs:myTag foo="bar"
  xmlns:myNs="http://www.w3c.org/myNs#">
EOF;
        $multiline = true;
        $indent = "  ";
        $this->assertEquals($expected, XML_Util::createStartElement($originalTag, $originalAttributes, $originalNamespace, $multiline, $indent));
    }

    /**
     * @covers XML_Util::createStartElement()
     */
    public function testCreateStartElementForTagWithAttributesAndNamespaceWithMultilineAndIndentAndLinebreak()
    {
        $originalTag = "myNs:myTag";
        $originalAttributes = array("foo" => "bar");
        $originalNamespace = "http://www.w3c.org/myNs#";
        $expected = "<myNs:myTag foo=\"bar\"^  xmlns:myNs=\"http://www.w3c.org/myNs#\">";
        $multiline = true;
        $indent = "  ";
        $linebreak = "^";
        $this->assertEquals($expected, XML_Util::createStartElement($originalTag, $originalAttributes, $originalNamespace, $multiline, $indent, $linebreak));
    }

    /**
     * @covers XML_Util::createStartElement()
     */
    public function testCreateStartElementForTagWithAttributesAndNamespaceWithMultilineAndIndentAndLinebreakAndSortAttributesIsTrue()
    {
        $originalTag = "myNs:myTag";
        $originalAttributes = array("foo" => "bar", "boo" => "baz");
        $originalNamespace = "http://www.w3c.org/myNs#";
        $expected = "<myNs:myTag boo=\"baz\"^  foo=\"bar\"^  xmlns:myNs=\"http://www.w3c.org/myNs#\">";
        $multiline = true;
        $indent = "  ";
        $linebreak = "^";
        $sortAttributes = true;
        $this->assertEquals($expected, XML_Util::createStartElement($originalTag, $originalAttributes, $originalNamespace, $multiline, $indent, $linebreak, $sortAttributes));
    }

    /**
     * @covers XML_Util::createStartElement()
     */
    public function testCreateStartElementForTagWithAttributesAndNamespaceWithMultilineAndIndentAndLinebreakAndSortAttributesIsFalse()
    {
        $originalTag = "myNs:myTag";
        $originalAttributes = array("foo" => "bar", "boo" => "baz");
        $originalNamespace = "http://www.w3c.org/myNs#";
        $expected = "<myNs:myTag foo=\"bar\"^  boo=\"baz\"^  xmlns:myNs=\"http://www.w3c.org/myNs#\">";
        $multiline = true;
        $indent = "  ";
        $linebreak = "^";
        $sortAttributes = false;
        $this->assertEquals($expected, XML_Util::createStartElement($originalTag, $originalAttributes, $originalNamespace, $multiline, $indent, $linebreak, $sortAttributes));
    }
}
PK��Zܬ$���2test/XML_Util/tests/GetDocTypeDeclarationTests.phpnu�[���<?php

class GetDocTypeDeclarationTests extends AbstractUnitTests
{
    /**
     * @covers XML_Util::getDocTypeDeclaration()
     */
    public function testGetDocTypeDeclarationUsingRoot()
    {
        $expected = "<!DOCTYPE rootTag>";
        $this->assertEquals($expected, XML_Util::getDocTypeDeclaration("rootTag"));
    }

    /**
     * @covers XML_Util::getDocTypeDeclaration()
     */
    public function testGetDocTypeDeclarationUsingRootAndStringUri()
    {
        $expected = "<!DOCTYPE rootTag SYSTEM \"myDocType.dtd\">";
        $this->assertEquals($expected, XML_Util::getDocTypeDeclaration("rootTag", "myDocType.dtd"));
    }

    /**
     * @covers XML_Util::getDocTypeDeclaration()
     */
    public function testGetDocTypeDeclarationUsingRootAndArrayUri()
    {
        $uri = array(
            'uri' => 'http://pear.php.net/dtd/package-1.0',
            'id' => '-//PHP//PEAR/DTD PACKAGE 0.1'
        );
        $expected = "<!DOCTYPE rootTag PUBLIC \"-//PHP//PEAR/DTD PACKAGE 0.1\" \"http://pear.php.net/dtd/package-1.0\">";
        $this->assertEquals($expected, XML_Util::getDocTypeDeclaration("rootTag", $uri));
    }

    /**
     * @covers XML_Util::getDocTypeDeclaration()
     */
    public function testGetDocTypeDeclarationUsingRootAndArrayUriAndInternalDtd()
    {
        $uri = array(
            'uri' => 'http://pear.php.net/dtd/package-1.0',
            'id' => '-//PHP//PEAR/DTD PACKAGE 0.1'
        );
        $dtdEntry = '<!ELEMENT additionalInfo (#PCDATA)>';
        $expected =
<<< EOF
<!DOCTYPE rootTag PUBLIC "-//PHP//PEAR/DTD PACKAGE 0.1" "http://pear.php.net/dtd/package-1.0" [
<!ELEMENT additionalInfo (#PCDATA)>
]>
EOF;
        $this->assertEquals($expected, XML_Util::getDocTypeDeclaration("rootTag", $uri, $dtdEntry));
    }
}
PK��Z��G%test/XML_Util/tests/Bug21177Tests.phpnu�[���<?php

/**
 * Bug #21177 "XML_Util::collapseEmptyTags() can return NULL"
 *
 * PREG returns NULL when it encounters an error.
 * In this case, it was encountering PREG_BACKTRACK_LIMIT_ERROR.
 *
 * @link https://pear.php.net/bugs/bug.php?id=21177
 */
class Bug21177Tests extends AbstractUnitTests
{
    public function getTestCandidate()
    {
        $expected = '<id_mytest_yesorno />';

        return array(
            array('<idmytestyesorno></idmytestyesorno>',        '<idmytestyesorno />'),
            array('<idmytestyesorno />',                        '<idmytestyesorno />'),

            array('<id_mytest_yesorno></id_mytest_yesorno>',    '<id_mytest_yesorno />'),
            array('<id_mytest_yesorno />',                      '<id_mytest_yesorno />'),
        );
    }

    /**
     * @dataProvider getTestCandidate()
     */
    public function testCollapseEmptyTagsForBug21177($original, $expected)
    {
        $this->assertEquals($expected, XML_Util::collapseEmptyTags($original, XML_UTIL_COLLAPSE_ALL), "Failed bugcheck.");
    }
}
PK��Z��۩��%test/XML_Util/tests/Bug18343Tests.phpnu�[���<?php

/**
 * Bug #18343 "Entities in file names decoded during packaging"
 *
 * No matter what flags are given to createTagFromArray(),
 * an attribute must *always* be at least ENTITIES_XML encoded.
 *
 * @link https://pear.php.net/bugs/bug.php?id=18343
 */
class Bug18343Tests extends AbstractUnitTests
{
    private $tagArray = array(
        "qname"      => "install",
        "attributes" => array(
            "as"    => "Horde/Feed/fixtures/lexicon/http-p.moreover.com-cgi-local-page%2Fo=rss&s=Newsweek",
            "name"  => "test/Horde/Feed/fixtures/lexicon/http-p.moreover.com-cgi-local-page%2Fo=rss&s=Newsweek",
        )
    );

    public function getFlagsToTest()
    {
        new XML_Util(); // for constants to be declared

        return array(
            array('no flag', null),
            array('false', false),
            array('ENTITIES_NONE', XML_UTIL_ENTITIES_NONE),
            array('ENTITIES_XML', XML_UTIL_ENTITIES_XML),
            array('ENTITIES_XML_REQUIRED', XML_UTIL_ENTITIES_XML_REQUIRED),
            array('ENTITIES_HTML', XML_UTIL_ENTITIES_HTML),
            array('REPLACE_ENTITIES', XML_UTIL_REPLACE_ENTITIES),
        );
    }

    /**
     * @dataProvider getFlagsToTest()
     */
    public function testCreateTagFromArrayForBug18343($key, $flag)
    {
        // all flags for the candidate input should return the same result
        $expected =
<<< EOF
<install as="Horde/Feed/fixtures/lexicon/http-p.moreover.com-cgi-local-page%2Fo=rss&amp;s=Newsweek" name="test/Horde/Feed/fixtures/lexicon/http-p.moreover.com-cgi-local-page%2Fo=rss&amp;s=Newsweek" />
EOF;
        $this->assertEquals($expected, XML_Util::createTagFromArray($this->tagArray, $flag), "Failed bugcheck for $key.");
    }
}
PK��Zz��t��,test/XML_Util/tests/ReverseEntitiesTests.phpnu�[���<?php

class ReverseEntitiesTests extends AbstractUnitTests
{
    protected function getSimpleData()
    {
        return 'This string contains &lt; &amp; &gt;.';
    }

    protected function getUtf8Data()
    {
        return 'This data contains special chars like &lt;, &gt;, &amp; and &quot; as well as &auml;, &ouml;, &szlig;, &agrave; and &ecirc;';
    }

    /**
     * @covers XML_Util::reverseEntities()
     */
    public function testReverseEntitiesForSimpleData()
    {
        $expected = "This string contains < & >.";
        $this->assertEquals($expected, XML_Util::reverseEntities($this->getSimpleData()));
    }

    /**
     * @covers XML_Util::reverseEntities()
     */
    public function testReverseEntitiesForSimpleDataWithInvalidOptionReturnsOriginalData()
    {
        $expected = "This string contains &lt; &amp; &gt;.";
        $this->assertEquals($expected, XML_Util::reverseEntities($this->getSimpleData(), 'INVALID_OPTION'));
    }

    /**
     * @covers XML_Util::reverseEntities()
     */
    public function testReverseEntitiesForSimpleDataWithEntitiesXml()
    {
        $expected = "This string contains < & >.";
        $this->assertEquals($expected, XML_Util::reverseEntities($this->getSimpleData(), XML_UTIL_ENTITIES_XML));
    }

    /**
     * @covers XML_Util::reverseEntities()
     */
    public function testReverseEntitiesForSimpleDataWithEntitiesXmlAndEncoding()
    {
        $encoding = "UTF-8";
        $expected = "This string contains < & >.";
        $this->assertEquals($expected, XML_Util::reverseEntities($this->getSimpleData(), XML_UTIL_ENTITIES_XML), $encoding);
    }

    /**
     * @covers XML_Util::reverseEntities()
     */
    public function testReverseEntitiesForUtf8DataWithEntitiesXmlAndEncoding()
    {
        $encoding = "UTF-8";
        $expected = "This data contains special chars like <, >, & and \" as well as &auml;, &ouml;, &szlig;, &agrave; and &ecirc;";
        $this->assertEquals($expected, XML_Util::reverseEntities($this->getUtf8Data(), XML_UTIL_ENTITIES_XML), $encoding);
    }

    /**
     * @covers XML_Util::reverseEntities()
     */
    public function testReverseEntitiesForSimpleDataWithEntitiesXmlRequired()
    {
        $expected = "This string contains < & &gt;.";
        $this->assertEquals($expected, XML_Util::reverseEntities($this->getSimpleData(), XML_UTIL_ENTITIES_XML_REQUIRED));
    }

    /**
     * @covers XML_Util::reverseEntities()
     */
    public function testReverseEntitiesForSimpleDataWithEntitiesXmlRequiredAndEncoding()
    {
        $encoding = "UTF-8";
        $expected = "This string contains < & &gt;.";
        $this->assertEquals($expected, XML_Util::reverseEntities($this->getSimpleData(), XML_UTIL_ENTITIES_XML_REQUIRED, $encoding));
    }

    /**
     * @covers XML_Util::reverseEntities()
     */
    public function testReverseEntitiesForUtf8DataWithEntitiesXmlRequiredAndEncoding()
    {
        $encoding = "UTF-8";
        $expected = "This data contains special chars like <, &gt;, & and \" as well as &auml;, &ouml;, &szlig;, &agrave; and &ecirc;";
        $this->assertEquals($expected, XML_Util::reverseEntities($this->getUtf8Data(), XML_UTIL_ENTITIES_XML_REQUIRED, $encoding));
    }

    /**
     * @covers XML_Util::reverseEntities()
     */
    public function testReverseEntitiesForSimpleDataWithEntitiesHtml()
    {
        $expected = "This string contains < & >.";
        $this->assertEquals($expected, XML_Util::reverseEntities($this->getSimpleData(), XML_UTIL_ENTITIES_HTML));
    }

    /**
     * @covers XML_Util::reverseEntities()
     */
    public function testReverseEntitiesForSimpleDataWithEntitiesHtmlAndEncoding()
    {
        $encoding = "UTF-8";
        $expected = "This string contains < & >.";
        $this->assertEquals($expected, XML_Util::reverseEntities($this->getSimpleData(), XML_UTIL_ENTITIES_HTML, $encoding));
    }

    /**
     * @covers XML_Util::reverseEntities()
     */
    public function testReverseEntitiesForUtf8DataWithEntitiesHtmlAndEncoding()
    {
        $encoding = "UTF-8";
        $expected = "This data contains special chars like <, >, & and \" as well as ä, ö, ß, à and ê";
        $this->assertEquals($expected, XML_Util::reverseEntities($this->getUtf8Data(), XML_UTIL_ENTITIES_HTML, $encoding));
    }
}
PK��Z~�$[ee-test/XML_Util/tests/CreateEndElementTests.phpnu�[���<?php

class CreateEndElementTests extends AbstractUnitTests
{
    /**
     * @covers XML_Util::createEndElement()
     */
    public function testCreateEndElementBasicUsage()
    {
        $original = "myTag";
        $expected = "</myTag>";
        $this->assertEquals($expected, XML_Util::createEndElement($original));
    }

    /**
     * @covers XML_Util::createEndElement()
     */
    public function testCreateEndElementWithNamespacedTag()
    {
        $original = "myNs:myTag";
        $expected = "</myNs:myTag>";
        $this->assertEquals($expected, XML_Util::createEndElement($original));
    }
}
PK��Z���!��)test/XML_Util/tests/AbstractUnitTests.phpnu�[���<?php

/*
 * Allow for PHPUnit 4.* while XML_Util is still usable on PHP 5.4
 */
if (!class_exists('PHPUnit_Framework_TestCase')) {
    class PHPUnit_Framework_TestCase extends \PHPUnit\Framework\TestCase {}
}

abstract class AbstractUnitTests extends \PHPUnit_Framework_TestCase
{
    public function setUp()
    {
        // ensure the class is defined, and thus its constants are declared
        new XML_Util();
    }
}
PK��Z�m4�**&test/XML_Util/tests/CreateTagTests.phpnu�[���<?php

class CreateTagTests extends AbstractUnitTests
{
    /**
     * @covers XML_Util::createTag()
     */
    public function testCreateTagForTagWithAttributes()
    {
        $originalTag = "myNs:myTag";
        $originalAttributes = array("foo" => "bar");
        $expected = "<myNs:myTag foo=\"bar\" />";
        $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes));
    }

    /**
     * @covers XML_Util::createTag()
     */
    public function testCreateTagForTagWithAttributesAndContent()
    {
        $originalTag = "myNs:myTag";
        $originalAttributes = array("foo" => "bar");
        $originalContent = "This is inside the tag";
        $expected = "<myNs:myTag foo=\"bar\">This is inside the tag</myNs:myTag>";
        $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes, $originalContent));
    }

    /**
     * @covers XML_Util::createTag()
     */
    public function testCreateTagForTagWithAttributesAndContentAndNamespace()
    {
        $originalTag = "myNs:myTag";
        $originalAttributes = array("foo" => "bar");
        $originalContent = "This is inside the tag";
        $originalNamespace = "http://www.w3c.org/myNs#";
        $expected = "<myNs:myTag foo=\"bar\" xmlns:myNs=\"http://www.w3c.org/myNs#\">This is inside the tag</myNs:myTag>";
        $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes, $originalContent, $originalNamespace));
    }


    /**
     * @covers XML_Util::createTag()
     */
    public function testCreateTagForTagWithAttributesAndContentAndNamespaceWithCDataSection()
    {
        $originalTag = "myNs:myTag";
        $originalAttributes = array("foo" => "bar");
        $originalContent = "This is inside the tag and has < & @ > in it";
        $originalNamespace = "http://www.w3c.org/myNs#";
        $expected = "<myNs:myTag foo=\"bar\" xmlns:myNs=\"http://www.w3c.org/myNs#\"><![CDATA[This is inside the tag and has < & @ > in it]]></myNs:myTag>";
        $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes, $originalContent, $originalNamespace, XML_UTIL_CDATA_SECTION));
    }

    /**
     * @covers XML_Util::createTag()
     */
    public function testCreateTagForTagWithAttributesAndContentAndNamespaceWithReplaceEntities()
    {
        $originalTag = "myNs:myTag";
        $originalAttributes = array("foo" => "bar");
        $originalContent = "This is inside the tag and has < & @ > in it";
        $originalNamespace = "http://www.w3c.org/myNs#";
        $expected = "<myNs:myTag foo=\"bar\" xmlns:myNs=\"http://www.w3c.org/myNs#\">This is inside the tag and has &lt; &amp; @ &gt; in it</myNs:myTag>";
        $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes, $originalContent, $originalNamespace, XML_UTIL_REPLACE_ENTITIES));
    }

    /**
     * @covers XML_Util::createTag()
     */
    public function testCreateTagForTagWithAttributesAndContentAndNamespaceWithReplaceEntitiesAndMultilineFalse()
    {
        $originalTag = "myNs:myTag";
        $originalAttributes = array("foo" => "bar");
        $originalContent = "This is inside the tag and has < & @ > in it";
        $originalNamespace = "http://www.w3c.org/myNs#";
        $multiline = false;
        $expected = "<myNs:myTag foo=\"bar\" xmlns:myNs=\"http://www.w3c.org/myNs#\">This is inside the tag and has &lt; &amp; @ &gt; in it</myNs:myTag>";
        $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes, $originalContent, $originalNamespace, XML_UTIL_REPLACE_ENTITIES, $multiline));
    }

    /**
     * @covers XML_Util::createTag()
     */
    public function testCreateTagForTagWithAttributesAndContentAndNamespaceWithReplaceEntitiesAndMultilineTrue()
    {
        $originalTag = "myNs:myTag";
        $originalAttributes = array("foo" => "bar");
        $originalContent = "This is inside the tag and has < & @ > in it";
        $originalNamespace = "http://www.w3c.org/myNs#";
        $multiline = true;
        $expected =
<<< EOF
<myNs:myTag foo="bar"
            xmlns:myNs="http://www.w3c.org/myNs#">This is inside the tag and has &lt; &amp; @ &gt; in it</myNs:myTag>
EOF;
        $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes, $originalContent, $originalNamespace, XML_UTIL_REPLACE_ENTITIES, $multiline));
    }

    /**
     * @covers XML_Util::createTag()
     */
    public function testCreateTagForTagWithAttributesAndContentAndNamespaceWithReplaceEntitiesAndMultilineTrueAndIndent()
    {
        $originalTag = "myNs:myTag";
        $originalAttributes = array("foo" => "bar");
        $originalContent = "This is inside the tag and has < & @ > in it";
        $originalNamespace = "http://www.w3c.org/myNs#";
        $multiline = true;
        $indent = "  ";
        $expected =
<<< EOF
<myNs:myTag foo="bar"
  xmlns:myNs="http://www.w3c.org/myNs#">This is inside the tag and has &lt; &amp; @ &gt; in it</myNs:myTag>
EOF;

        $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes, $originalContent, $originalNamespace, XML_UTIL_REPLACE_ENTITIES, $multiline, $indent));
    }

    /**
     * @covers XML_Util::createTag()
     */
    public function testCreateTagForTagWithAttributesAndContentAndNamespaceWithReplaceEntitiesAndMultilineTrueAndIndentAndLinebreak()
    {
        $originalTag = "myNs:myTag";
        $originalAttributes = array("foo" => "bar");
        $originalContent = "This is inside the tag and has < & @ > in it";
        $originalNamespace = "http://www.w3c.org/myNs#";
        $multiline = true;
        $indent = "  ";
        $linebreak = "^";
        $expected = "<myNs:myTag foo=\"bar\"^  xmlns:myNs=\"http://www.w3c.org/myNs#\">This is inside the tag and has &lt; &amp; @ &gt; in it</myNs:myTag>";
        $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes, $originalContent, $originalNamespace, XML_UTIL_REPLACE_ENTITIES, $multiline, $indent, $linebreak));
    }

    /**
     * @covers XML_Util::createTag()
     */
    public function testCreateTagForTagWithAttributesAndContentAndNamespaceWithReplaceEntitiesAndMultilineTrueAndIndentAndLinebreakAndSortAttributesTrue()
    {
        $originalTag = "myNs:myTag";
        $originalAttributes = array("foo" => "bar", "boo" => "baz");
        $originalContent = "This is inside the tag and has < & @ > in it";
        $originalNamespace = "http://www.w3c.org/myNs#";
        $multiline = true;
        $indent = "  ";
        $linebreak = "^";
        $sortAttributes = true;
        $expected = "<myNs:myTag boo=\"baz\"^  foo=\"bar\"^  xmlns:myNs=\"http://www.w3c.org/myNs#\">This is inside the tag and has &lt; &amp; @ &gt; in it</myNs:myTag>";
        $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes, $originalContent, $originalNamespace, XML_UTIL_REPLACE_ENTITIES, $multiline, $indent, $linebreak, $sortAttributes));
    }

    /**
     * @covers XML_Util::createTag()
     */
    public function testCreateTagForTagWithAttributesAndContentAndNamespaceWithReplaceEntitiesAndMultilineTrueAndIndentAndLinebreakAndSortAttributesFalse()
    {
        $originalTag = "myNs:myTag";
        $originalAttributes = array("foo" => "bar", "boo" => "baz");
        $originalContent = "This is inside the tag and has < & @ > in it";
        $originalNamespace = "http://www.w3c.org/myNs#";
        $multiline = true;
        $indent = "  ";
        $linebreak = "^";
        $sortAttributes = false;
        $expected = "<myNs:myTag foo=\"bar\"^  boo=\"baz\"^  xmlns:myNs=\"http://www.w3c.org/myNs#\">This is inside the tag and has &lt; &amp; @ &gt; in it</myNs:myTag>";
        $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes, $originalContent, $originalNamespace, XML_UTIL_REPLACE_ENTITIES, $multiline, $indent, $linebreak, $sortAttributes));
    }
}
PK��ZDf:��.test/XML_Util/tests/GetXmlDeclarationTests.phpnu�[���<?php

class GetXMLDeclarationTests extends AbstractUnitTests
{
    /**
     * @covers XML_Util::getXMLDeclaration()
     */
    public function testGetXMLDeclarationUsingVersion()
    {
        $version = "1.0";
        $expected = "<?xml version=\"1.0\"?>";
        $this->assertEquals($expected, XML_Util::getXMLDeclaration($version));
    }

    /**
     * @covers XML_Util::getXMLDeclaration()
     */
    public function testGetXMLDeclarationUsingVersionAndEncodingAndStandalone()
    {
        $version = "1.0";
        $encoding = "UTF-8";
        $standalone = true;
        $expected = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";
        $this->assertEquals($expected, XML_Util::getXMLDeclaration($version, $encoding, $standalone));
    }

    /**
     * @covers XML_Util::getXMLDeclaration()
     */
    public function testGetXMLDeclarationUsingVersionAndStandalone()
    {
        $version = "1.0";
        $encoding = null;
        $standalone = true;
        $expected = "<?xml version=\"1.0\" standalone=\"yes\"?>";
        $this->assertEquals($expected, XML_Util::getXMLDeclaration($version, $encoding, $standalone));
    }
}
PK��ZZ�t�/test/XML_Util/tests/AttributesToStringTests.phpnu�[���<?php

class AttributesToStringTests extends AbstractUnitTests
{
    /**
     * @covers XML_Util::attributesToString()
     */
    public function testAttributesToStringBasicUsage()
    {
        $original = array('foo' => 'bar','boo' => 'baz',);
        $expected = " boo=\"baz\" foo=\"bar\"";
        $this->assertEquals($expected, XML_Util::attributesToString($original));
    }

    /**
     * @covers XML_Util::attributesToString()
     */
    public function testAttributesToStringWithExplicitSortTrue()
    {
        $original = array('foo' => 'bar','boo' => 'baz',);
        $expected = " boo=\"baz\" foo=\"bar\"";
        $sort = true;
        $this->assertEquals($expected, XML_Util::attributesToString($original, $sort));
    }

    /**
     * @covers XML_Util::attributesToString()
     */
    public function testAttributesToStringWithExplicitSortFalse()
    {
        $original = array('foo' => 'bar','boo' => 'baz',);
        $expected = " foo=\"bar\" boo=\"baz\"";
        $sort = false;
        $this->assertEquals($expected, XML_Util::attributesToString($original, $sort));
    }

    /**
     * @covers XML_Util::attributesToString()
     */
    public function testAttributesToStringWithMultilineFalse()
    {
        $original = array('foo' => 'bar','boo' => 'baz',);
        $expected = " boo=\"baz\" foo=\"bar\"";
        $sort = true;
        $multiline = false;
        $this->assertEquals($expected, XML_Util::attributesToString($original, $sort, $multiline));
    }

    /**
     * @covers XML_Util::attributesToString()
     */
    public function testAttributesToStringWithMultilineTrue()
    {
        $original = array('foo' => 'bar','boo' => 'baz',);
        $expected =
<<< EOF
 boo="baz"
    foo="bar"
EOF;
        $sort = true;
        $multiline = true;
        $this->assertEquals($expected, XML_Util::attributesToString($original, $sort, $multiline));
    }

    /**
     * @covers XML_Util::attributesToString()
     */
    public function testAttributesToStringWithExplicitIndent()
    {
        $original = array('foo' => 'bar','boo' => 'baz',);
        $expected = " boo=\"baz\"\n        foo=\"bar\"";
        $sort = true;
        $multiline = true;
        $indent = '        '; // 8 spaces
        $this->assertEquals($expected, XML_Util::attributesToString($original, $sort, $multiline, $indent));
    }

    /**
     * @covers XML_Util::attributesToString()
     */
    public function testAttributesToStringWithExplicitLinebreak()
    {
        $original = array('foo' => 'bar','boo' => 'baz',);
        $expected = " boo=\"baz\"\n^foo=\"bar\"";
        $sort = true;
        $multiline = true;
        $linebreak = '^'; // some dummy character
        $this->assertEquals($expected, XML_Util::attributesToString($original, $sort, $multiline, $linebreak));
    }

    /**
     * @covers XML_Util::attributesToString()
     */
    public function testAttributesToStringWithOptionsThatIncludesSort()
    {
        $original = array('foo' => 'bar','boo' => 'baz',);
        $options = array(
            'multiline' => true,
            'indent'    => '----',
            'linebreak' => "^",
            'entities'  => XML_UTIL_ENTITIES_XML,
            'sort'      => true,
        );

        $expected = " boo=\"baz\"\n----foo=\"bar\"";
        $this->assertEquals($expected, XML_Util::attributesToString($original, $options));
    }

    /**
     * @covers XML_Util::attributesToString()
     */
    public function testAttributesToStringWithOptionsThatExcludesSort()
    {
        $original = array('foo' => 'bar','boo' => 'baz',);
        $options = array(
            'multiline' => true,
            'indent'    => '----',
            'linebreak' => "^",
            'entities'  => XML_UTIL_ENTITIES_XML,
        );

        $expected = " boo=\"baz\"\n----foo=\"bar\"";
        $this->assertEquals($expected, XML_Util::attributesToString($original, $options));
    }

    /**
     * @covers XML_Util::attributesToString()
     */
    public function testAttributesToStringWithEntitiesNone()
    {
        $original = array("foo" => "b@&r", "boo" => "b><z");
        $expected = " boo=\"b><z\" foo=\"b@&r\"";
        $sort = true;
        $multiline = false;
        $linebreak = '    ';
        $this->assertEquals($expected, XML_Util::attributesToString($original, $sort, $multiline, $linebreak, PHP_EOL, XML_UTIL_ENTITIES_NONE));
    }

    /**
     * @covers XML_Util::attributesToString()
     */
    public function testAttributesToStringWithEntitiesXml()
    {
        $original = array("foo" => "b@&r", "boo" => "b><z");
        $expected = " boo=\"b&gt;&lt;z\" foo=\"b@&amp;r\"";
        $sort = true;
        $multiline = false;
        $linebreak = '    ';
        $this->assertEquals($expected, XML_Util::attributesToString($original, $sort, $multiline, $linebreak, PHP_EOL, XML_UTIL_ENTITIES_XML));
    }

    /**
     * @covers XML_Util::attributesToString()
     */
    public function testAttributesToStringWithEntitiesXmlRequired()
    {
        $original = array("foo" => "b@&r", "boo" => "b><z");
        $expected = " boo=\"b>&lt;z\" foo=\"b@&amp;r\"";
        $sort = true;
        $multiline = false;
        $linebreak = '    ';
        $this->assertEquals($expected, XML_Util::attributesToString($original, $sort, $multiline, $linebreak, PHP_EOL, XML_UTIL_ENTITIES_XML_REQUIRED));
    }

    /**
     * @covers XML_Util::attributesToString()
     */
    public function testAttributesToStringWithEntitiesHtml()
    {
        $original = array("foo" => "b@&r", "boo" => "b><z");
        $expected = " boo=\"b&gt;&lt;z\" foo=\"b@&amp;r\"";
        $sort = true;
        $multiline = false;
        $linebreak = '    ';
        $this->assertEquals($expected, XML_Util::attributesToString($original, $sort, $multiline, $linebreak, PHP_EOL, XML_UTIL_ENTITIES_HTML));
    }

    /**
     * Tag attributes should not be treated as CDATA,
     * so the operation will instead quietly use XML_UTIL_ENTITIES_XML.
     *
     * @covers XML_Util::attributesToString()
     */
    public function testAttributesToStringWithCDataSectionForSingleAttribute()
    {
        $original = array('foo' => 'bar'); // need exactly one attribute here
        $options = array(
            'sort'      => true,   // doesn't matter for this testcase
            'multiline' => false,  // doesn't matter for this testcase
            'indent'    => null,   // doesn't matter for this testcase
            'linebreak' => null,   // doesn't matter for this testcase
            'entities'  => XML_UTIL_CDATA_SECTION, // DOES matter for this testcase
        );
        $expected = " foo=\"bar\"";
        $this->assertEquals($expected, XML_Util::attributesToString($original, $options));
    }

    /**
     * Tag attributes should not be treated as CDATA,
     * so the operation will instead quietly use XML_UTIL_ENTITIES_XML.
     *
     * @covers XML_Util::attributesToString()
     */
    public function testAttributesToStringWithCDataSectionForMultipleAttributesAndMultilineFalse()
    {
        $original = array('foo' => 'bar', 'boo' => 'baz'); // need more than one attribute here
        $options = array(
            'sort'      => true,   // doesn't matter for this testcase
            'multiline' => false,  // DOES matter for this testcase, must be false
            'indent'    => null,   // doesn't matter for this testcase
            'linebreak' => null,   // doesn't matter for this testcase
            'entities'  => XML_UTIL_CDATA_SECTION, // DOES matter for this testcase
        );
        $expected = " boo=\"baz\" foo=\"bar\"";
        $this->assertEquals($expected, XML_Util::attributesToString($original, $options));
    }
}
PK��Zݑh���(test/XML_Util/tests/IsValidNameTests.phpnu�[���<?php

class IsValidNameTests extends AbstractUnitTests
{
    /**
     * @covers XML_Util::isValidName()
     */
    public function testIsValidNameForTagNameThatIsValid()
    {
        $tagName = "alpha-x_y_z.123";
        $result = XML_Util::isValidName($tagName);
        $this->assertTrue($result);
    }

    /**
     * @covers XML_Util::isValidName()
     */
    public function testIsValidNameForTagNameWithInvalidCharacter()
    {
        $tagName = "invalidTag?";
        $result = XML_Util::isValidName($tagName);
        $this->assertInstanceOf('PEAR_Error', $result);
        $expectedError = "XML names may only contain alphanumeric chars, period, hyphen, colon and underscores";
        $this->assertEquals($expectedError, $result->getMessage());
    }

    /**
     * @covers XML_Util::isValidName()
     */
    public function testIsValidNameForTagNameWithInvalidStartingCharacter()
    {
        $tagName = "1234five";
        $result = XML_Util::isValidName($tagName);
        $this->assertInstanceOf('PEAR_Error', $result);
        $expectedError = "XML names may only start with letter or underscore";
        $this->assertEquals($expectedError, $result->getMessage());
    }

    /**
     * @covers XML_Util::isValidName()
     */
    public function testIsValidNameForInt()
    {
        $tagName = 1;
        $result = XML_Util::isValidName($tagName);
        $this->assertInstanceOf('PEAR_Error', $result);
        $expectedError = "XML names may only start with letter or underscore";
        $this->assertEquals($expectedError, $result->getMessage());
    }

    /**
     * @covers XML_Util::isValidName()
     */
    public function testIsValidNameForEmptyString()
    {
        $tagName = '';
        $result = XML_Util::isValidName($tagName);
        $this->assertInstanceOf('PEAR_Error', $result);
        $expectedError = "XML names may only start with letter or underscore";
        $this->assertEquals($expectedError, $result->getMessage());
    }
}
PK��Z���TT*test/XML_Util/tests/CreateCommentTests.phpnu�[���<?php

class CreateCommentTests extends AbstractUnitTests
{
    /**
     * @covers XML_Util::createComment()
     */
    public function testCreateCommentBasicUsage()
    {
        $original = "I am comment.";
        $expected = "<!-- I am comment. -->";
        $this->assertEquals($expected, XML_Util::createComment($original));
    }
}
PK��Z�rv��'test/XML_Util/tests/RaiseErrorTests.phpnu�[���<?php

class RaiseErrorTests extends AbstractUnitTests
{
    /**
     * @covers XML_Util::raiseError()
     */
    public function testRaiseError()
    {
        $code = 12345;
        $message = "I am an error";
        $error = XML_Util::raiseError($message, $code);
        $this->assertInstanceOf('PEAR_Error', $error);
        $this->assertEquals($message, $error->getMessage());
        $this->assertEquals($code, $error->getCode());
    }
}
PK��ZF1y��A�ATtest/OptionsResolver/Symfony/Component/OptionsResolver/Tests/OptionsResolverTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\OptionsResolver\Tests;

use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\OptionsResolver\Options;

class OptionsResolverTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var OptionsResolver
     */
    private $resolver;

    protected function setUp()
    {
        $this->resolver = new OptionsResolver();
    }

    public function testResolve()
    {
        $this->resolver->setDefaults(array(
            'one' => '1',
            'two' => '2',
        ));

        $options = array(
            'two' => '20',
        );

        $this->assertEquals(array(
            'one' => '1',
            'two' => '20',
        ), $this->resolver->resolve($options));
    }

    public function testResolveLazy()
    {
        $this->resolver->setDefaults(array(
            'one' => '1',
            'two' => function (Options $options) {
                return '20';
            },
        ));

        $this->assertEquals(array(
            'one' => '1',
            'two' => '20',
        ), $this->resolver->resolve(array()));
    }

    public function testResolveLazyDependencyOnOptional()
    {
        $this->resolver->setDefaults(array(
            'one' => '1',
            'two' => function (Options $options) {
                return $options['one'].'2';
            },
        ));

        $options = array(
            'one' => '10',
        );

        $this->assertEquals(array(
            'one' => '10',
            'two' => '102',
        ), $this->resolver->resolve($options));
    }

    public function testResolveLazyDependencyOnMissingOptionalWithoutDefault()
    {
        $test = $this;

        $this->resolver->setOptional(array(
            'one',
        ));

        $this->resolver->setDefaults(array(
            'two' => function (Options $options) use ($test) {
                /* @var \PHPUnit_Framework_TestCase $test */
                $test->assertFalse(isset($options['one']));

                return '2';
            },
        ));

        $options = array(
        );

        $this->assertEquals(array(
            'two' => '2',
        ), $this->resolver->resolve($options));
    }

    public function testResolveLazyDependencyOnOptionalWithoutDefault()
    {
        $test = $this;

        $this->resolver->setOptional(array(
            'one',
        ));

        $this->resolver->setDefaults(array(
            'two' => function (Options $options) use ($test) {
                /* @var \PHPUnit_Framework_TestCase $test */
                $test->assertTrue(isset($options['one']));

                return $options['one'].'2';
            },
        ));

        $options = array(
            'one' => '10',
        );

        $this->assertEquals(array(
            'one' => '10',
            'two' => '102',
        ), $this->resolver->resolve($options));
    }

    public function testResolveLazyDependencyOnRequired()
    {
        $this->resolver->setRequired(array(
            'one',
        ));
        $this->resolver->setDefaults(array(
            'two' => function (Options $options) {
                return $options['one'].'2';
            },
        ));

        $options = array(
            'one' => '10',
        );

        $this->assertEquals(array(
            'one' => '10',
            'two' => '102',
        ), $this->resolver->resolve($options));
    }

    public function testResolveLazyReplaceDefaults()
    {
        $test = $this;

        $this->resolver->setDefaults(array(
            'one' => function (Options $options) use ($test) {
                /* @var \PHPUnit_Framework_TestCase $test */
                $test->fail('Previous closure should not be executed');
            },
        ));

        $this->resolver->replaceDefaults(array(
            'one' => function (Options $options, $previousValue) {
                return '1';
            },
        ));

        $this->assertEquals(array(
            'one' => '1',
        ), $this->resolver->resolve(array()));
    }

    /**
     * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
     */
    public function testResolveFailsIfNonExistingOption()
    {
        $this->resolver->setDefaults(array(
            'one' => '1',
        ));

        $this->resolver->setRequired(array(
            'two',
        ));

        $this->resolver->setOptional(array(
            'three',
        ));

        $this->resolver->resolve(array(
            'foo' => 'bar',
        ));
    }

    /**
     * @expectedException \Symfony\Component\OptionsResolver\Exception\MissingOptionsException
     */
    public function testResolveFailsIfMissingRequiredOption()
    {
        $this->resolver->setRequired(array(
            'one',
        ));

        $this->resolver->setDefaults(array(
            'two' => '2',
        ));

        $this->resolver->resolve(array(
            'two' => '20',
        ));
    }

    public function testResolveSucceedsIfOptionValueAllowed()
    {
        $this->resolver->setDefaults(array(
            'one' => '1',
        ));

        $this->resolver->setAllowedValues(array(
            'one' => array('1', 'one'),
        ));

        $options = array(
            'one' => 'one',
        );

        $this->assertEquals(array(
            'one' => 'one',
        ), $this->resolver->resolve($options));
    }

    public function testResolveSucceedsIfOptionValueAllowed2()
    {
        $this->resolver->setDefaults(array(
            'one' => '1',
            'two' => '2',
        ));

        $this->resolver->setAllowedValues(array(
            'one' => '1',
            'two' => '2',
        ));
        $this->resolver->addAllowedValues(array(
            'one' => 'one',
            'two' => 'two',
        ));

        $options = array(
            'one' => '1',
            'two' => 'two',
        );

        $this->assertEquals(array(
            'one' => '1',
            'two' => 'two',
        ), $this->resolver->resolve($options));
    }

    public function testResolveSucceedsIfOptionalWithAllowedValuesNotSet()
    {
        $this->resolver->setRequired(array(
            'one',
        ));

        $this->resolver->setOptional(array(
            'two',
        ));

        $this->resolver->setAllowedValues(array(
            'one' => array('1', 'one'),
            'two' => array('2', 'two'),
        ));

        $options = array(
            'one' => '1',
        );

        $this->assertEquals(array(
            'one' => '1',
        ), $this->resolver->resolve($options));
    }

    /**
     * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
     */
    public function testResolveFailsIfOptionValueNotAllowed()
    {
        $this->resolver->setDefaults(array(
            'one' => '1',
        ));

        $this->resolver->setAllowedValues(array(
            'one' => array('1', 'one'),
        ));

        $this->resolver->resolve(array(
            'one' => '2',
        ));
    }

    public function testResolveSucceedsIfOptionTypeAllowed()
    {
        $this->resolver->setDefaults(array(
            'one' => '1',
        ));

        $this->resolver->setAllowedTypes(array(
            'one' => 'string',
        ));

        $options = array(
            'one' => 'one',
        );

        $this->assertEquals(array(
            'one' => 'one',
        ), $this->resolver->resolve($options));
    }

    public function testResolveSucceedsIfOptionTypeAllowedPassArray()
    {
        $this->resolver->setDefaults(array(
            'one' => '1',
        ));

        $this->resolver->setAllowedTypes(array(
            'one' => array('string', 'bool'),
        ));

        $options = array(
            'one' => true,
        );

        $this->assertEquals(array(
            'one' => true,
        ), $this->resolver->resolve($options));
    }

    public function testResolveSucceedsIfOptionTypeAllowedPassObject()
    {
        $this->resolver->setDefaults(array(
            'one' => '1',
        ));

        $this->resolver->setAllowedTypes(array(
            'one' => 'object',
        ));

        $object = new \stdClass();
        $options = array(
            'one' => $object,
        );

        $this->assertEquals(array(
            'one' => $object,
        ), $this->resolver->resolve($options));
    }

    public function testResolveSucceedsIfOptionTypeAllowedPassClass()
    {
        $this->resolver->setDefaults(array(
            'one' => '1',
        ));

        $this->resolver->setAllowedTypes(array(
            'one' => '\stdClass',
        ));

        $object = new \stdClass();
        $options = array(
            'one' => $object,
        );

        $this->assertEquals(array(
            'one' => $object,
        ), $this->resolver->resolve($options));
    }

    public function testResolveSucceedsIfOptionTypeAllowedAddTypes()
    {
        $this->resolver->setDefaults(array(
            'one' => '1',
            'two' => '2',
        ));

        $this->resolver->setAllowedTypes(array(
            'one' => 'string',
            'two' => 'bool',
        ));
        $this->resolver->addAllowedTypes(array(
            'one' => 'float',
            'two' => 'integer',
        ));

        $options = array(
            'one' => 1.23,
            'two' => false,
        );

        $this->assertEquals(array(
            'one' => 1.23,
            'two' => false,
        ), $this->resolver->resolve($options));
    }

    public function testResolveSucceedsIfOptionalWithTypeAndWithoutValue()
    {
        $this->resolver->setOptional(array(
            'one',
            'two',
        ));

        $this->resolver->setAllowedTypes(array(
            'one' => 'string',
            'two' => 'int',
        ));

        $options = array(
            'two' => 1,
        );

        $this->assertEquals(array(
            'two' => 1,
        ), $this->resolver->resolve($options));
    }

    /**
     * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
     */
    public function testResolveFailsIfOptionTypeNotAllowed()
    {
        $this->resolver->setDefaults(array(
            'one' => '1',
        ));

        $this->resolver->setAllowedTypes(array(
            'one' => array('string', 'bool'),
        ));

        $this->resolver->resolve(array(
            'one' => 1.23,
        ));
    }

    /**
     * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
     */
    public function testResolveFailsIfOptionTypeNotAllowedMultipleOptions()
    {
        $this->resolver->setDefaults(array(
            'one' => '1',
            'two' => '2',
        ));

        $this->resolver->setAllowedTypes(array(
            'one' => 'string',
            'two' => 'bool',
        ));

        $this->resolver->resolve(array(
            'one' => 'foo',
            'two' => 1.23,
        ));
    }

    /**
     * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
     */
    public function testResolveFailsIfOptionTypeNotAllowedAddTypes()
    {
        $this->resolver->setDefaults(array(
            'one' => '1',
        ));

        $this->resolver->setAllowedTypes(array(
            'one' => 'string',
        ));
        $this->resolver->addAllowedTypes(array(
            'one' => 'bool',
        ));

        $this->resolver->resolve(array(
            'one' => 1.23,
        ));
    }

    /**
     * @expectedException \Symfony\Component\OptionsResolver\Exception\OptionDefinitionException
     */
    public function testSetRequiredFailsIfDefaultIsPassed()
    {
        $this->resolver->setRequired(array(
            'one' => '1',
        ));
    }

    /**
     * @expectedException \Symfony\Component\OptionsResolver\Exception\OptionDefinitionException
     */
    public function testSetOptionalFailsIfDefaultIsPassed()
    {
        $this->resolver->setOptional(array(
            'one' => '1',
        ));
    }

    public function testFluidInterface()
    {
        $this->resolver->setDefaults(array('one' => '1'))
            ->replaceDefaults(array('one' => '2'))
            ->setAllowedValues(array('one' => array('1', '2')))
            ->addAllowedValues(array('one' => array('3')))
            ->setRequired(array('two'))
            ->setOptional(array('three'));

        $options = array(
            'two' => '2',
        );

        $this->assertEquals(array(
            'one' => '2',
            'two' => '2',
        ), $this->resolver->resolve($options));
    }

    public function testKnownIfDefaultWasSet()
    {
        $this->assertFalse($this->resolver->isKnown('foo'));

        $this->resolver->setDefaults(array(
            'foo' => 'bar',
        ));

        $this->assertTrue($this->resolver->isKnown('foo'));
    }

    public function testKnownIfRequired()
    {
        $this->assertFalse($this->resolver->isKnown('foo'));

        $this->resolver->setRequired(array(
            'foo',
        ));

        $this->assertTrue($this->resolver->isKnown('foo'));
    }

    public function testKnownIfOptional()
    {
        $this->assertFalse($this->resolver->isKnown('foo'));

        $this->resolver->setOptional(array(
            'foo',
        ));

        $this->assertTrue($this->resolver->isKnown('foo'));
    }

    public function testRequiredIfRequired()
    {
        $this->assertFalse($this->resolver->isRequired('foo'));

        $this->resolver->setRequired(array(
            'foo',
        ));

        $this->assertTrue($this->resolver->isRequired('foo'));
    }

    public function testNotRequiredIfRequiredAndDefaultValue()
    {
        $this->assertFalse($this->resolver->isRequired('foo'));

        $this->resolver->setRequired(array(
            'foo',
        ));
        $this->resolver->setDefaults(array(
            'foo' => 'bar',
        ));

        $this->assertFalse($this->resolver->isRequired('foo'));
    }

    public function testNormalizersTransformFinalOptions()
    {
        $this->resolver->setDefaults(array(
            'foo' => 'bar',
            'bam' => 'baz',
        ));
        $this->resolver->setNormalizers(array(
            'foo' => function (Options $options, $value) {
                return $options['bam'].'['.$value.']';
            },
        ));

        $expected = array(
            'foo' => 'baz[bar]',
            'bam' => 'baz',
        );

        $this->assertEquals($expected, $this->resolver->resolve(array()));

        $expected = array(
            'foo' => 'boo[custom]',
            'bam' => 'boo',
        );

        $this->assertEquals($expected, $this->resolver->resolve(array(
            'foo' => 'custom',
            'bam' => 'boo',
        )));
    }

    public function testResolveWithoutOptionSucceedsIfRequiredAndDefaultValue()
    {
        $this->resolver->setRequired(array(
            'foo',
        ));
        $this->resolver->setDefaults(array(
            'foo' => 'bar',
        ));

        $this->assertEquals(array(
            'foo' => 'bar'
        ), $this->resolver->resolve(array()));
    }

    public function testResolveWithoutOptionSucceedsIfDefaultValueAndRequired()
    {
        $this->resolver->setDefaults(array(
            'foo' => 'bar',
        ));
        $this->resolver->setRequired(array(
            'foo',
        ));

        $this->assertEquals(array(
            'foo' => 'bar'
        ), $this->resolver->resolve(array()));
    }

    public function testResolveSucceedsIfOptionRequiredAndValueAllowed()
    {
        $this->resolver->setRequired(array(
            'one', 'two',
        ));
        $this->resolver->setAllowedValues(array(
            'two' => array('2'),
        ));

        $options = array(
            'one' => '1',
            'two' => '2'
        );

        $this->assertEquals($options, $this->resolver->resolve($options));
    }

    public function testClone()
    {
        $this->resolver->setDefaults(array('one' => '1'));

        $clone = clone $this->resolver;

        // Changes after cloning don't affect each other
        $this->resolver->setDefaults(array('two' => '2'));
        $clone->setDefaults(array('three' => '3'));

        $this->assertEquals(array(
            'one' => '1',
            'two' => '2',
        ), $this->resolver->resolve());

        $this->assertEquals(array(
            'one' => '1',
            'three' => '3',
        ), $clone->resolve());
    }
}
PK��Zν�3;3;Ltest/OptionsResolver/Symfony/Component/OptionsResolver/Tests/OptionsTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\OptionsResolver\Tests;

use Symfony\Component\OptionsResolver\Options;

class OptionsTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var Options
     */
    private $options;

    protected function setUp()
    {
        $this->options = new Options();
    }

    public function testArrayAccess()
    {
        $this->assertFalse(isset($this->options['foo']));
        $this->assertFalse(isset($this->options['bar']));

        $this->options['foo'] = 0;
        $this->options['bar'] = 1;

        $this->assertTrue(isset($this->options['foo']));
        $this->assertTrue(isset($this->options['bar']));

        unset($this->options['bar']);

        $this->assertTrue(isset($this->options['foo']));
        $this->assertFalse(isset($this->options['bar']));
        $this->assertEquals(0, $this->options['foo']);
    }

    public function testCountable()
    {
        $this->options->set('foo', 0);
        $this->options->set('bar', 1);

        $this->assertCount(2, $this->options);
    }

    /**
     * @expectedException \OutOfBoundsException
     */
    public function testGetNonExisting()
    {
        $this->options->get('foo');
    }

    /**
     * @expectedException \Symfony\Component\OptionsResolver\Exception\OptionDefinitionException
     */
    public function testSetNotSupportedAfterGet()
    {
        $this->options->set('foo', 'bar');
        $this->options->get('foo');
        $this->options->set('foo', 'baz');
    }

    /**
     * @expectedException \Symfony\Component\OptionsResolver\Exception\OptionDefinitionException
     */
    public function testRemoveNotSupportedAfterGet()
    {
        $this->options->set('foo', 'bar');
        $this->options->get('foo');
        $this->options->remove('foo');
    }

    /**
     * @expectedException \Symfony\Component\OptionsResolver\Exception\OptionDefinitionException
     */
    public function testSetNormalizerNotSupportedAfterGet()
    {
        $this->options->set('foo', 'bar');
        $this->options->get('foo');
        $this->options->setNormalizer('foo', function () {});
    }

    public function testSetLazyOption()
    {
        $test = $this;

        $this->options->set('foo', function (Options $options) use ($test) {
           return 'dynamic';
        });

        $this->assertEquals('dynamic', $this->options->get('foo'));
    }

    public function testSetDiscardsPreviousValue()
    {
        $test = $this;

        // defined by superclass
        $this->options->set('foo', 'bar');

        // defined by subclass
        $this->options->set('foo', function (Options $options, $previousValue) use ($test) {
            /* @var \PHPUnit_Framework_TestCase $test */
            $test->assertNull($previousValue);

            return 'dynamic';
        });

        $this->assertEquals('dynamic', $this->options->get('foo'));
    }

    public function testOverloadKeepsPreviousValue()
    {
        $test = $this;

        // defined by superclass
        $this->options->set('foo', 'bar');

        // defined by subclass
        $this->options->overload('foo', function (Options $options, $previousValue) use ($test) {
            /* @var \PHPUnit_Framework_TestCase $test */
            $test->assertEquals('bar', $previousValue);

            return 'dynamic';
        });

        $this->assertEquals('dynamic', $this->options->get('foo'));
    }

    public function testPreviousValueIsEvaluatedIfLazy()
    {
        $test = $this;

        // defined by superclass
        $this->options->set('foo', function (Options $options) {
            return 'bar';
        });

        // defined by subclass
        $this->options->overload('foo', function (Options $options, $previousValue) use ($test) {
            /* @var \PHPUnit_Framework_TestCase $test */
            $test->assertEquals('bar', $previousValue);

            return 'dynamic';
        });

        $this->assertEquals('dynamic', $this->options->get('foo'));
    }

    public function testPreviousValueIsNotEvaluatedIfNoSecondArgument()
    {
        $test = $this;

        // defined by superclass
        $this->options->set('foo', function (Options $options) use ($test) {
            $test->fail('Should not be called');
        });

        // defined by subclass, no $previousValue argument defined!
        $this->options->overload('foo', function (Options $options) use ($test) {
            return 'dynamic';
        });

        $this->assertEquals('dynamic', $this->options->get('foo'));
    }

    public function testLazyOptionCanAccessOtherOptions()
    {
        $test = $this;

        $this->options->set('foo', 'bar');

        $this->options->set('bam', function (Options $options) use ($test) {
            /* @var \PHPUnit_Framework_TestCase $test */
            $test->assertEquals('bar', $options->get('foo'));

            return 'dynamic';
        });

        $this->assertEquals('bar', $this->options->get('foo'));
        $this->assertEquals('dynamic', $this->options->get('bam'));
    }

    public function testLazyOptionCanAccessOtherLazyOptions()
    {
        $test = $this;

        $this->options->set('foo', function (Options $options) {
            return 'bar';
        });

        $this->options->set('bam', function (Options $options) use ($test) {
            /* @var \PHPUnit_Framework_TestCase $test */
            $test->assertEquals('bar', $options->get('foo'));

            return 'dynamic';
        });

        $this->assertEquals('bar', $this->options->get('foo'));
        $this->assertEquals('dynamic', $this->options->get('bam'));
    }

    public function testNormalizer()
    {
        $this->options->set('foo', 'bar');

        $this->options->setNormalizer('foo', function () {
            return 'normalized';
        });

        $this->assertEquals('normalized', $this->options->get('foo'));
    }

    public function testNormalizerReceivesUnnormalizedValue()
    {
        $this->options->set('foo', 'bar');

        $this->options->setNormalizer('foo', function (Options $options, $value) {
            return 'normalized['.$value.']';
        });

        $this->assertEquals('normalized[bar]', $this->options->get('foo'));
    }

    public function testNormalizerCanAccessOtherOptions()
    {
        $test = $this;

        $this->options->set('foo', 'bar');
        $this->options->set('bam', 'baz');

        $this->options->setNormalizer('bam', function (Options $options) use ($test) {
            /* @var \PHPUnit_Framework_TestCase $test */
            $test->assertEquals('bar', $options->get('foo'));

            return 'normalized';
        });

        $this->assertEquals('bar', $this->options->get('foo'));
        $this->assertEquals('normalized', $this->options->get('bam'));
    }

    public function testNormalizerCanAccessOtherLazyOptions()
    {
        $test = $this;

        $this->options->set('foo', function (Options $options) {
            return 'bar';
        });
        $this->options->set('bam', 'baz');

        $this->options->setNormalizer('bam', function (Options $options) use ($test) {
            /* @var \PHPUnit_Framework_TestCase $test */
            $test->assertEquals('bar', $options->get('foo'));

            return 'normalized';
        });

        $this->assertEquals('bar', $this->options->get('foo'));
        $this->assertEquals('normalized', $this->options->get('bam'));
    }

    /**
     * @expectedException \Symfony\Component\OptionsResolver\Exception\OptionDefinitionException
     */
    public function testFailForCyclicDependencies()
    {
        $this->options->set('foo', function (Options $options) {
            $options->get('bam');
        });

        $this->options->set('bam', function (Options $options) {
            $options->get('foo');
        });

        $this->options->get('foo');
    }

    /**
     * @expectedException \Symfony\Component\OptionsResolver\Exception\OptionDefinitionException
     */
    public function testFailForCyclicDependenciesBetweenNormalizers()
    {
        $this->options->set('foo', 'bar');
        $this->options->set('bam', 'baz');

        $this->options->setNormalizer('foo', function (Options $options) {
            $options->get('bam');
        });

        $this->options->setNormalizer('bam', function (Options $options) {
            $options->get('foo');
        });

        $this->options->get('foo');
    }

    /**
     * @expectedException \Symfony\Component\OptionsResolver\Exception\OptionDefinitionException
     */
    public function testFailForCyclicDependenciesBetweenNormalizerAndLazyOption()
    {
        $this->options->set('foo', function (Options $options) {
            $options->get('bam');
        });
        $this->options->set('bam', 'baz');

        $this->options->setNormalizer('bam', function (Options $options) {
            $options->get('foo');
        });

        $this->options->get('foo');
    }

    public function testAllInvokesEachLazyOptionOnlyOnce()
    {
        $test = $this;
        $i = 1;

        $this->options->set('foo', function (Options $options) use ($test, &$i) {
            $test->assertSame(1, $i);
            ++$i;

            // Implicitly invoke lazy option for "bam"
            $options->get('bam');
        });
        $this->options->set('bam', function (Options $options) use ($test, &$i) {
            $test->assertSame(2, $i);
            ++$i;
        });

        $this->options->all();
    }

    public function testAllInvokesEachNormalizerOnlyOnce()
    {
        $test = $this;
        $i = 1;

        $this->options->set('foo', 'bar');
        $this->options->set('bam', 'baz');

        $this->options->setNormalizer('foo', function (Options $options) use ($test, &$i) {
            $test->assertSame(1, $i);
            ++$i;

            // Implicitly invoke normalizer for "bam"
            $options->get('bam');
        });
        $this->options->setNormalizer('bam', function (Options $options) use ($test, &$i) {
            $test->assertSame(2, $i);
            ++$i;
        });

        $this->options->all();
    }

    public function testReplaceClearsAndSets()
    {
        $this->options->set('one', '1');

        $this->options->replace(array(
            'two' => '2',
            'three' => function (Options $options) {
                return '2' === $options['two'] ? '3' : 'foo';
            }
        ));

        $this->assertEquals(array(
            'two' => '2',
            'three' => '3',
        ), $this->options->all());
    }

    public function testClearRemovesAllOptions()
    {
        $this->options->set('one', 1);
        $this->options->set('two', 2);

        $this->options->clear();

        $this->assertEmpty($this->options->all());

    }

    /**
     * @covers Symfony\Component\OptionsResolver\Options::replace
     * @expectedException \Symfony\Component\OptionsResolver\Exception\OptionDefinitionException
     */
    public function testCannotReplaceAfterOptionWasRead()
    {
        $this->options->set('one', 1);
        $this->options->all();

        $this->options->replace(array(
            'two' => '2',
        ));
    }

    /**
     * @covers Symfony\Component\OptionsResolver\Options::overload
     * @expectedException \Symfony\Component\OptionsResolver\Exception\OptionDefinitionException
     */
    public function testCannotOverloadAfterOptionWasRead()
    {
        $this->options->set('one', 1);
        $this->options->all();

        $this->options->overload('one', 2);
    }

    /**
     * @covers Symfony\Component\OptionsResolver\Options::clear
     * @expectedException \Symfony\Component\OptionsResolver\Exception\OptionDefinitionException
     */
    public function testCannotClearAfterOptionWasRead()
    {
        $this->options->set('one', 1);
        $this->options->all();

        $this->options->clear();
    }

    public function testOverloadCannotBeEvaluatedLazilyWithoutExpectedClosureParams()
    {
        $this->options->set('foo', 'bar');

        $this->options->overload('foo', function () {
            return 'test';
        });

        $this->assertNotEquals('test', $this->options->get('foo'));
        $this->assertTrue(is_callable($this->options->get('foo')));
    }

    public function testOverloadCannotBeEvaluatedLazilyWithoutFirstParamTypeHint()
    {
        $this->options->set('foo', 'bar');

        $this->options->overload('foo', function ($object) {
            return 'test';
        });

        $this->assertNotEquals('test', $this->options->get('foo'));
        $this->assertTrue(is_callable($this->options->get('foo')));
    }

    public function testOptionsIteration()
    {
        $this->options->set('foo', 'bar');
        $this->options->set('foo1', 'bar1');
        $expectedResult = array('foo' => 'bar', 'foo1' => 'bar1');

        $this->assertEquals($expectedResult, iterator_to_array($this->options, true));
    }

    public function testHasWithNullValue()
    {
        $this->options->set('foo', null);

        $this->assertTrue($this->options->has('foo'));
    }

    public function testRemoveOptionAndNormalizer()
    {
        $this->options->set('foo1', 'bar');
        $this->options->setNormalizer('foo1', function (Options $options) {
            return '';
        });
        $this->options->set('foo2', 'bar');
        $this->options->setNormalizer('foo2', function (Options $options) {
            return '';
        });

        $this->options->remove('foo2');
        $this->assertEquals(array('foo1' => ''), $this->options->all());
    }

    public function testReplaceOptionAndNormalizer()
    {
        $this->options->set('foo1', 'bar');
        $this->options->setNormalizer('foo1', function (Options $options) {
            return '';
        });
        $this->options->set('foo2', 'bar');
        $this->options->setNormalizer('foo2', function (Options $options) {
            return '';
        });

        $this->options->replace(array('foo1' => 'new'));
        $this->assertEquals(array('foo1' => 'new'), $this->options->all());
    }

    public function testClearOptionAndNormalizer()
    {
        $this->options->set('foo1', 'bar');
        $this->options->setNormalizer('foo1', function (Options $options) {
            return '';
        });
        $this->options->set('foo2', 'bar');
        $this->options->setNormalizer('foo2', function (Options $options) {
            return '';
        });

        $this->options->clear();
        $this->assertEmpty($this->options->all());
    }

    public function testNormalizerWithoutCorrespondingOption()
    {
        $test = $this;

        $this->options->setNormalizer('foo', function (Options $options, $previousValue) use ($test) {
            $test->assertNull($previousValue);

            return '';
        });
        $this->assertEquals(array('foo' => ''), $this->options->all());
    }
}
PK��Z��*/AAGtest/OptionsResolver/Symfony/Component/OptionsResolver/phpunit.xml.distnu�[���<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony OptionsResolver Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./Resources</directory>
                <directory>./Tests</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
PK��Z<ȸB!!test/Net_SMTP/tests/auth.phptnu�[���--TEST--
Net_SMTP: SMTP Authentication
--SKIPIF--
<?php if (!@include('config.php')) die("skip\n");
--FILE--
<?php

require_once 'Net/SMTP.php';
require_once 'config.php';

if (! ($smtp = new Net_SMTP(TEST_HOSTNAME, TEST_PORT, TEST_LOCALHOST))) {
	die("Unable to instantiate Net_SMTP object\n");
}

if (PEAR::isError($e = $smtp->connect())) {
	die($e->getMessage() . "\n");
}

if (PEAR::isError($e = $smtp->auth(TEST_AUTH_USER, TEST_AUTH_PASS))) {
	die("Authentication failure\n");
}

$smtp->disconnect();

echo 'Success!';

--EXPECT--
Success!
PK��Z�߁Q��"test/Net_SMTP/tests/quotedata.phptnu�[���--TEST--
Net_SMTP: quotedata()
--FILE--
<?php

require_once 'Net/SMTP.php';

$tests = array(
    /* Newlines */
    "\n"               => "\r\n",
    "\r\n"             => "\r\n",
    "\nxx"             => "\r\nxx",
    "xx\n"             => "xx\r\n",
    "xx\nxx"           => "xx\r\nxx",
    "\n\nxx"           => "\r\n\r\nxx",
    "xx\n\nxx"         => "xx\r\n\r\nxx",
    "xx\n\n"           => "xx\r\n\r\n",
    "\r\nxx"           => "\r\nxx",
    "xx\r\n"           => "xx\r\n",
    "xx\r\nxx"         => "xx\r\nxx",
    "\r\n\r\nxx"       => "\r\n\r\nxx",
    "xx\r\n\r\nxx"     => "xx\r\n\r\nxx",
    "xx\r\n\r\n"       => "xx\r\n\r\n",
    "\r\n\nxx"         => "\r\n\r\nxx",
    "\n\r\nxx"         => "\r\n\r\nxx",
    "xx\r\n\nxx"       => "xx\r\n\r\nxx",
    "xx\n\r\nxx"       => "xx\r\n\r\nxx",
    "xx\r\n\n"         => "xx\r\n\r\n",
    "xx\n\r\n"         => "xx\r\n\r\n",
    "\r"               => "\r\n",
    "\rxx"             => "\r\nxx",
    "xx\rxx"           => "xx\r\nxx",
    "xx\r"             => "xx\r\n",
    "\r\r"             => "\r\n\r\n",
    "\r\rxx"           => "\r\n\r\nxx",
    "xx\r\rxx"         => "xx\r\n\r\nxx",
    "xx\r\r"           => "xx\r\n\r\n",
    "xx\rxx\nxx\r\nxx" => "xx\r\nxx\r\nxx\r\nxx",
    "\r\r\n\n"         => "\r\n\r\n\r\n",

    /* Dots */
    "."                 => "..",
    "xxx\n."            => "xxx\r\n..",
    "xxx\n.\nxxx"       => "xxx\r\n..\r\nxxx",
    "xxx.\n.xxx"        => "xxx.\r\n..xxx",
);

function literal($x)
{
    return str_replace(array("\r", "\n"), array('\r', '\n'), $x);
}

$smtp = new Net_SMTP();
$error = false;
foreach ($tests as $input => $expected) {
    $output = $input;
    $smtp->quotedata($output);
    if ($output != $expected) {
        printf("Error: '%s' => '%s' (expected: '%s')",
            literal($input), literal($output), literal($expected));
        $error = true;
    }
}

if (!$error) {
    echo "success\n";
}

--EXPECT--
success
PK��Z�*�W��test/Net_SMTP/tests/basic.phptnu�[���--TEST--
Net_SMTP: Basic Functionality
--SKIPIF--
<?php if (!@include('config.php')) die("skip\n");
--FILE--
<?php

require_once 'Net/SMTP.php';
require_once 'config.php';

if (! ($smtp = new Net_SMTP(TEST_HOSTNAME, TEST_PORT, TEST_LOCALHOST))) {
    die("Unable to instantiate Net_SMTP object\n");
}

if (PEAR::isError($e = $smtp->connect())) {
    die($e->getMessage() . "\n");
}

if (PEAR::isError($e = $smtp->auth(TEST_AUTH_USER, TEST_AUTH_PASS))) {
    die("Authentication failure\n");
}

if (PEAR::isError($smtp->mailFrom(TEST_FROM))) {
    die('Unable to set sender to <' . TEST_FROM . ">\n");
}

if (PEAR::isError($res = $smtp->rcptTo(TEST_TO))) {
    die('Unable to add recipient <' . TEST_TO . '>: ' .
        $res->getMessage() . "\n");
}

$headers = 'Subject: ' . TEST_SUBJECT;
if (PEAR::isError($smtp->data(TEST_BODY, $headers))) {
    die("Unable to send data\n");
}

$smtp->disconnect();

echo 'Success!';

--EXPECT--
Success!
PK��Z�6����#test/Net_SMTP/tests/config.php.distnu�[���<?php
/**
 * Copy this file to config.php and customize the following values to
 * suit your configuration.
 */

define('TEST_HOSTNAME',     'localhost');
define('TEST_PORT',         25);
define('TEST_LOCALHOST',    'localhost');
define('TEST_AUTH_USER',    'jon');
define('TEST_AUTH_PASS',    'secret');
define('TEST_FROM',         'from@example.com');
define('TEST_TO',           'to@example.com');
define('TEST_SUBJECT',      'Test Subject');
define('TEST_BODY',         'Test Body');
PK��Z�iH���Ftest/Config/Symfony/Component/Config/Tests/Definition/EnumNodeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition;

use Symfony\Component\Config\Definition\EnumNode;

class EnumNodeTest extends \PHPUnit_Framework_TestCase
{
    public function testFinalizeValue()
    {
        $node = new EnumNode('foo', null, array('foo', 'bar'));
        $this->assertSame('foo', $node->finalize('foo'));
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testConstructionWithOneValue()
    {
        new EnumNode('foo', null, array('foo', 'foo'));
    }

    /**
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
     * @expectedExceptionMessage The value "foobar" is not allowed for path "foo". Permissible values: "foo", "bar"
     */
    public function testFinalizeWithInvalidValue()
    {
        $node = new EnumNode('foo', null, array('foo', 'bar'));
        $node->finalize('foobar');
    }
}
PK��Zhͼ��Ktest/Config/Symfony/Component/Config/Tests/Definition/NormalizationTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition;

use Symfony\Component\Config\Definition\NodeInterface;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;

class NormalizationTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getEncoderTests
     */
    public function testNormalizeEncoders($denormalized)
    {
        $tb = new TreeBuilder();
        $tree = $tb
            ->root('root_name', 'array')
                ->fixXmlConfig('encoder')
                ->children()
                    ->node('encoders', 'array')
                        ->useAttributeAsKey('class')
                        ->prototype('array')
                            ->beforeNormalization()->ifString()->then(function ($v) { return array('algorithm' => $v); })->end()
                            ->children()
                                ->node('algorithm', 'scalar')->end()
                            ->end()
                        ->end()
                    ->end()
                ->end()
            ->end()
            ->buildTree()
        ;

        $normalized = array(
            'encoders' => array(
                'foo' => array('algorithm' => 'plaintext'),
            ),
        );

        $this->assertNormalized($tree, $denormalized, $normalized);
    }

    public function getEncoderTests()
    {
        $configs = array();

        // XML
        $configs[] = array(
            'encoder' => array(
                array('class' => 'foo', 'algorithm' => 'plaintext'),
            ),
        );

        // XML when only one element of this type
        $configs[] = array(
            'encoder' => array('class' => 'foo', 'algorithm' => 'plaintext'),
        );

        // YAML/PHP
        $configs[] = array(
            'encoders' => array(
                array('class' => 'foo', 'algorithm' => 'plaintext'),
            ),
        );

        // YAML/PHP
        $configs[] = array(
            'encoders' => array(
                'foo' => 'plaintext',
            ),
        );

        // YAML/PHP
        $configs[] = array(
            'encoders' => array(
                'foo' => array('algorithm' => 'plaintext'),
            ),
        );

        return array_map(function ($v) {
            return array($v);
        }, $configs);
    }

    /**
     * @dataProvider getAnonymousKeysTests
     */
    public function testAnonymousKeysArray($denormalized)
    {
        $tb = new TreeBuilder();
        $tree = $tb
            ->root('root', 'array')
                ->children()
                    ->node('logout', 'array')
                        ->fixXmlConfig('handler')
                        ->children()
                            ->node('handlers', 'array')
                                ->prototype('scalar')->end()
                            ->end()
                        ->end()
                    ->end()
                ->end()
            ->end()
            ->buildTree()
        ;

        $normalized = array('logout' => array('handlers' => array('a', 'b', 'c')));

        $this->assertNormalized($tree, $denormalized, $normalized);
    }

    public function getAnonymousKeysTests()
    {
        $configs = array();

        $configs[] = array(
            'logout' => array(
                'handlers' => array('a', 'b', 'c'),
            ),
        );

        $configs[] = array(
            'logout' => array(
                'handler' => array('a', 'b', 'c'),
            ),
        );

        return array_map(function ($v) { return array($v); }, $configs);
    }

    /**
     * @dataProvider getNumericKeysTests
     */
    public function testNumericKeysAsAttributes($denormalized)
    {
        $normalized = array(
            'thing' => array(42 => array('foo', 'bar'), 1337 => array('baz', 'qux')),
        );

        $this->assertNormalized($this->getNumericKeysTestTree(), $denormalized, $normalized);
    }

    public function getNumericKeysTests()
    {
        $configs = array();

        $configs[] = array(
            'thing' => array(
                42 => array('foo', 'bar'), 1337 => array('baz', 'qux'),
            ),
        );

        $configs[] = array(
            'thing' => array(
                array('foo', 'bar', 'id' => 42), array('baz', 'qux', 'id' => 1337),
            ),
        );

        return array_map(function ($v) { return array($v); }, $configs);
    }

    /**
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
     * @expectedExceptionMessage The attribute "id" must be set for path "root.thing".
     */
    public function testNonAssociativeArrayThrowsExceptionIfAttributeNotSet()
    {
        $denormalized = array(
            'thing' => array(
                array('foo', 'bar'), array('baz', 'qux')
            )
        );

        $this->assertNormalized($this->getNumericKeysTestTree(), $denormalized, array());
    }

    public function testAssociativeArrayPreserveKeys()
    {
        $tb = new TreeBuilder();
        $tree = $tb
            ->root('root', 'array')
                ->prototype('array')
                    ->children()
                        ->node('foo', 'scalar')->end()
                    ->end()
                ->end()
            ->end()
            ->buildTree()
        ;

        $data = array('first' => array('foo' => 'bar'));

        $this->assertNormalized($tree, $data, $data);
    }

    public static function assertNormalized(NodeInterface $tree, $denormalized, $normalized)
    {
        self::assertSame($normalized, $tree->normalize($denormalized));
    }

    private function getNumericKeysTestTree()
    {
        $tb = new TreeBuilder();
        $tree = $tb
            ->root('root', 'array')
                ->children()
                    ->node('thing', 'array')
                        ->useAttributeAsKey('id')
                        ->prototype('array')
                            ->prototype('scalar')->end()
                        ->end()
                    ->end()
                ->end()
            ->end()
            ->buildTree()
        ;

        return $tree;
    }
}
PK��Z�hE--Gtest/Config/Symfony/Component/Config/Tests/Definition/ArrayNodeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition;

use Symfony\Component\Config\Definition\ArrayNode;
use Symfony\Component\Config\Definition\ScalarNode;

class ArrayNodeTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidTypeException
     */
    public function testNormalizeThrowsExceptionWhenFalseIsNotAllowed()
    {
        $node = new ArrayNode('root');
        $node->normalize(false);
    }

    /**
     * @expectedException        \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
     * @expectedExceptionMessage Unrecognized options "foo" under "root"
     */
    public function testExceptionThrownOnUnrecognizedChild()
    {
        $node = new ArrayNode('root');
        $node->normalize(array('foo' => 'bar'));
    }

    /**
     * Tests that no exception is thrown for an unrecognized child if the
     * ignoreExtraKeys option is set to true.
     *
     * Related to testExceptionThrownOnUnrecognizedChild
     */
    public function testIgnoreExtraKeysNoException()
    {
        $node = new ArrayNode('roo');
        $node->setIgnoreExtraKeys(true);

        $node->normalize(array('foo' => 'bar'));
        $this->assertTrue(true, 'No exception was thrown when setIgnoreExtraKeys is true');
    }

    /**
     * @dataProvider getPreNormalizationTests
     */
    public function testPreNormalize($denormalized, $normalized)
    {
        $node = new ArrayNode('foo');

        $r = new \ReflectionMethod($node, 'preNormalize');
        $r->setAccessible(true);

        $this->assertSame($normalized, $r->invoke($node, $denormalized));
    }

    public function getPreNormalizationTests()
    {
        return array(
            array(
                array('foo-bar' => 'foo'),
                array('foo_bar' => 'foo'),
            ),
            array(
                array('foo-bar_moo' => 'foo'),
                array('foo-bar_moo' => 'foo'),
            ),
            array(
                array('foo-bar' => null, 'foo_bar' => 'foo'),
                array('foo-bar' => null, 'foo_bar' => 'foo'),
            )
        );
    }

    /**
     * @dataProvider getZeroNamedNodeExamplesData
     */
    public function testNodeNameCanBeZero($denormalized, $normalized)
    {
        $zeroNode = new ArrayNode(0);
        $zeroNode->addChild(new ScalarNode('name'));
        $fiveNode = new ArrayNode(5);
        $fiveNode->addChild(new ScalarNode(0));
        $fiveNode->addChild(new ScalarNode('new_key'));
        $rootNode = new ArrayNode('root');
        $rootNode->addChild($zeroNode);
        $rootNode->addChild($fiveNode);
        $rootNode->addChild(new ScalarNode('string_key'));
        $r = new \ReflectionMethod($rootNode, 'normalizeValue');
        $r->setAccessible(true);

        $this->assertSame($normalized, $r->invoke($rootNode, $denormalized));
    }

    public function getZeroNamedNodeExamplesData()
    {
        return array(
            array(
                array(
                    0 => array(
                        'name'    => 'something',
                    ),
                    5 => array(
                        0         => 'this won\'t work too',
                        'new_key' => 'some other value',
                    ),
                    'string_key'  => 'just value',
                ),
                array(
                    0 => array (
                        'name' => 'something',
                    ),
                    5 => array (
                        0 => 'this won\'t work too',
                        'new_key' => 'some other value',
                    ),
                    'string_key' => 'just value',
                ),
            ),
        );
    }

    /**
     * @dataProvider getPreNormalizedNormalizedOrderedData
     */
    public function testChildrenOrderIsMaintainedOnNormalizeValue($prenormalized, $normalized)
    {
        $scalar1 = new ScalarNode('1');
        $scalar2 = new ScalarNode('2');
        $scalar3 = new ScalarNode('3');
        $node = new ArrayNode('foo');
        $node->addChild($scalar1);
        $node->addChild($scalar3);
        $node->addChild($scalar2);

        $r = new \ReflectionMethod($node, 'normalizeValue');
        $r->setAccessible(true);

        $this->assertSame($normalized, $r->invoke($node, $prenormalized));
    }

    public function getPreNormalizedNormalizedOrderedData()
    {
        return array(
            array(
                array('2' => 'two', '1' => 'one', '3' => 'three'),
                array('2' => 'two', '1' => 'one', '3' => 'three'),
            ),
        );
    }
}
PK��Z����Itest/Config/Symfony/Component/Config/Tests/Definition/IntegerNodeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition;

use Symfony\Component\Config\Definition\IntegerNode;

class IntegerNodeTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getValidValues
     */
    public function testNormalize($value)
    {
        $node = new IntegerNode('test');
        $this->assertSame($value, $node->normalize($value));
    }

    public function getValidValues()
    {
        return array(
            array(1798),
            array(-678),
            array(0),
        );
    }

    /**
     * @dataProvider getInvalidValues
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidTypeException
     */
    public function testNormalizeThrowsExceptionOnInvalidValues($value)
    {
        $node = new IntegerNode('test');
        $node->normalize($value);
    }

    public function getInvalidValues()
    {
        return array(
            array(null),
            array(''),
            array('foo'),
            array(true),
            array(false),
            array(0.0),
            array(0.1),
            array(array()),
            array(array('foo' => 'bar')),
            array(new \stdClass()),
        );
    }
}
PK��Z&]��Gtest/Config/Symfony/Component/Config/Tests/Definition/FloatNodeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition;

use Symfony\Component\Config\Definition\FloatNode;

class FloatNodeTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getValidValues
     */
    public function testNormalize($value)
    {
        $node = new FloatNode('test');
        $this->assertSame($value, $node->normalize($value));
    }

    public function getValidValues()
    {
        return array(
            array(1798.0),
            array(-678.987),
            array(12.56E45),
            array(0.0),
            // Integer are accepted too, they will be cast
            array(17),
            array(-10),
            array(0)
        );
    }

    /**
     * @dataProvider getInvalidValues
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidTypeException
     */
    public function testNormalizeThrowsExceptionOnInvalidValues($value)
    {
        $node = new FloatNode('test');
        $node->normalize($value);
    }

    public function getInvalidValues()
    {
        return array(
            array(null),
            array(''),
            array('foo'),
            array(true),
            array(false),
            array(array()),
            array(array('foo' => 'bar')),
            array(new \stdClass()),
        );
    }
}
PK��Z�-1��Qtest/Config/Symfony/Component/Config/Tests/Definition/Builder/ExprBuilderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition\Builder;

use Symfony\Component\Config\Definition\Builder\TreeBuilder;

class ExprBuilderTest extends \PHPUnit_Framework_TestCase
{

    public function testAlwaysExpression()
    {
        $test = $this->getTestBuilder()
            ->always($this->returnClosure('new_value'))
        ->end();

        $this->assertFinalizedValueIs('new_value', $test);
    }

    public function testIfTrueExpression()
    {
        $test = $this->getTestBuilder()
            ->ifTrue()
            ->then($this->returnClosure('new_value'))
        ->end();
        $this->assertFinalizedValueIs('new_value', $test, array('key'=>true));

        $test = $this->getTestBuilder()
            ->ifTrue( function ($v) { return true; })
            ->then($this->returnClosure('new_value'))
        ->end();
        $this->assertFinalizedValueIs('new_value', $test);

        $test = $this->getTestBuilder()
            ->ifTrue( function ($v) { return false; })
            ->then($this->returnClosure('new_value'))
        ->end();
        $this->assertFinalizedValueIs('value',$test);
    }

    public function testIfStringExpression()
    {
        $test = $this->getTestBuilder()
            ->ifString()
            ->then($this->returnClosure('new_value'))
        ->end();
        $this->assertFinalizedValueIs('new_value', $test);

        $test = $this->getTestBuilder()
            ->ifString()
            ->then($this->returnClosure('new_value'))
        ->end();
        $this->assertFinalizedValueIs(45, $test, array('key'=>45));

    }

    public function testIfNullExpression()
    {
        $test = $this->getTestBuilder()
            ->ifNull()
            ->then($this->returnClosure('new_value'))
        ->end();
        $this->assertFinalizedValueIs('new_value', $test, array('key'=>null));

        $test = $this->getTestBuilder()
            ->ifNull()
            ->then($this->returnClosure('new_value'))
        ->end();
        $this->assertFinalizedValueIs('value', $test);
    }

    public function testIfArrayExpression()
    {
        $test = $this->getTestBuilder()
            ->ifArray()
            ->then($this->returnClosure('new_value'))
        ->end();
        $this->assertFinalizedValueIs('new_value', $test, array('key'=>array()));

        $test = $this->getTestBuilder()
            ->ifArray()
            ->then($this->returnClosure('new_value'))
        ->end();
        $this->assertFinalizedValueIs('value', $test);
    }

    public function testIfInArrayExpression()
    {
        $test = $this->getTestBuilder()
            ->ifInArray(array('foo', 'bar', 'value'))
            ->then($this->returnClosure('new_value'))
        ->end();
        $this->assertFinalizedValueIs('new_value', $test);

        $test = $this->getTestBuilder()
            ->ifInArray(array('foo', 'bar'))
            ->then($this->returnClosure('new_value'))
        ->end();
        $this->assertFinalizedValueIs('value', $test);
    }

    public function testIfNotInArrayExpression()
    {
        $test = $this->getTestBuilder()
            ->ifNotInArray(array('foo', 'bar'))
            ->then($this->returnClosure('new_value'))
        ->end();
        $this->assertFinalizedValueIs('new_value', $test);

        $test = $this->getTestBuilder()
            ->ifNotInArray(array('foo', 'bar', 'value_from_config' ))
            ->then($this->returnClosure('new_value'))
        ->end();
        $this->assertFinalizedValueIs('new_value', $test);
    }

    public function testThenEmptyArrayExpression()
    {
        $test = $this->getTestBuilder()
            ->ifString()
            ->thenEmptyArray()
        ->end();
        $this->assertFinalizedValueIs(array(), $test);
    }

    /**
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
     */
    public function testThenInvalid()
    {
        $test = $this->getTestBuilder()
            ->ifString()
            ->thenInvalid('Invalid value')
        ->end();
        $this->finalizeTestBuilder($test);
    }

    public function testThenUnsetExpression()
    {
        $test = $this->getTestBuilder()
            ->ifString()
            ->thenUnset()
        ->end();
        $this->assertEquals(array(), $this->finalizeTestBuilder($test));
    }

    /**
     * Create a test treebuilder with a variable node, and init the validation
     * @return TreeBuilder
     */
    protected function getTestBuilder()
    {
        $builder = new TreeBuilder();

        return $builder
            ->root('test')
            ->children()
            ->variableNode('key')
            ->validate()
       ;
    }

    /**
     * Close the validation process and finalize with the given config
     * @param TreeBuilder $testBuilder The tree builder to finalize
     * @param array       $config      The config you want to use for the finalization, if nothing provided
     *                       a simple array('key'=>'value') will be used
     * @return array The finalized config values
     */
    protected function finalizeTestBuilder($testBuilder, $config = null)
    {
        return $testBuilder
            ->end()
            ->end()
            ->end()
            ->buildTree()
            ->finalize($config === null ? array('key'=>'value') : $config)
        ;
    }

    /**
     * Return a closure that will return the given value
     * @param $val The value that the closure must return
     * @return Closure
     */
    protected function returnClosure($val)
    {
        return function ($v) use ($val) {
            return $val;
        };
    }

    /**
     * Assert that the given test builder, will return the given value
     *
     * @param mixed       $value       The value to test
     * @param TreeBuilder $treeBuilder The tree builder to finalize
     * @param mixed       $config      The config values that new to be finalized
     */
    protected function assertFinalizedValueIs($value, $treeBuilder, $config = null)
    {
        $this->assertEquals(array('key'=>$value), $this->finalizeTestBuilder($treeBuilder, $config));
    }
}
PK��Z<�C��Xtest/Config/Symfony/Component/Config/Tests/Definition/Builder/EnumNodeDefinitionTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition\Builder;

use Symfony\Component\Config\Definition\Builder\EnumNodeDefinition;

class EnumNodeDefinitionTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \InvalidArgumentException
     * @expectedExceptionMessage ->values() must be called with at least two distinct values.
     */
    public function testNoDistinctValues()
    {
        $def = new EnumNodeDefinition('foo');
        $def->values(array('foo', 'foo'));
    }

    /**
     * @expectedException \RuntimeException
     * @expectedExceptionMessage You must call ->values() on enum nodes.
     */
    public function testNoValuesPassed()
    {
        $def = new EnumNodeDefinition('foo');
        $def->getNode();
    }

    public function testGetNode()
    {
        $def = new EnumNodeDefinition('foo');
        $def->values(array('foo', 'bar'));

        $node = $def->getNode();
        $this->assertEquals(array('foo', 'bar'), $node->getValues());
    }
}
PK��ZwX��Ytest/Config/Symfony/Component/Config/Tests/Definition/Builder/ArrayNodeDefinitionTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition\Builder;

use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use Symfony\Component\Config\Definition\Processor;
use Symfony\Component\Config\Definition\Builder\ScalarNodeDefinition;
use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException;

class ArrayNodeDefinitionTest extends \PHPUnit_Framework_TestCase
{
    public function testAppendingSomeNode()
    {
        $parent = new ArrayNodeDefinition('root');
        $child = new ScalarNodeDefinition('child');

        $parent
            ->children()
                ->scalarNode('foo')->end()
                ->scalarNode('bar')->end()
            ->end()
            ->append($child);

        $this->assertCount(3, $this->getField($parent, 'children'));
        $this->assertTrue(in_array($child, $this->getField($parent, 'children')));
    }

    /**
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidDefinitionException
     * @dataProvider providePrototypeNodeSpecificCalls
     */
    public function testPrototypeNodeSpecificOption($method, $args)
    {
        $node = new ArrayNodeDefinition('root');

        call_user_func_array(array($node, $method), $args);

        $node->getNode();
    }

    public function providePrototypeNodeSpecificCalls()
    {
        return array(
            array('defaultValue', array(array())),
            array('addDefaultChildrenIfNoneSet', array()),
            array('requiresAtLeastOneElement', array()),
            array('useAttributeAsKey', array('foo'))
        );
    }

    /**
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidDefinitionException
     */
    public function testConcreteNodeSpecificOption()
    {
        $node = new ArrayNodeDefinition('root');
        $node
            ->addDefaultsIfNotSet()
            ->prototype('array')
        ;
        $node->getNode();
    }

    /**
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidDefinitionException
     */
    public function testPrototypeNodesCantHaveADefaultValueWhenUsingDefaultChildren()
    {
        $node = new ArrayNodeDefinition('root');
        $node
            ->defaultValue(array())
            ->addDefaultChildrenIfNoneSet('foo')
            ->prototype('array')
        ;
        $node->getNode();
    }

    public function testPrototypedArrayNodeDefaultWhenUsingDefaultChildren()
    {
        $node = new ArrayNodeDefinition('root');
        $node
            ->addDefaultChildrenIfNoneSet()
            ->prototype('array')
        ;
        $tree = $node->getNode();
        $this->assertEquals(array(array()), $tree->getDefaultValue());
    }

    /**
     * @dataProvider providePrototypedArrayNodeDefaults
     */
    public function testPrototypedArrayNodeDefault($args, $shouldThrowWhenUsingAttrAsKey, $shouldThrowWhenNotUsingAttrAsKey, $defaults)
    {
        $node = new ArrayNodeDefinition('root');
        $node
            ->addDefaultChildrenIfNoneSet($args)
            ->prototype('array')
        ;

        try {
            $tree = $node->getNode();
            $this->assertFalse($shouldThrowWhenNotUsingAttrAsKey);
            $this->assertEquals($defaults, $tree->getDefaultValue());
        } catch (InvalidDefinitionException $e) {
            $this->assertTrue($shouldThrowWhenNotUsingAttrAsKey);
        }

        $node = new ArrayNodeDefinition('root');
        $node
            ->useAttributeAsKey('attr')
            ->addDefaultChildrenIfNoneSet($args)
            ->prototype('array')
        ;

        try {
            $tree = $node->getNode();
            $this->assertFalse($shouldThrowWhenUsingAttrAsKey);
            $this->assertEquals($defaults, $tree->getDefaultValue());
        } catch (InvalidDefinitionException $e) {
            $this->assertTrue($shouldThrowWhenUsingAttrAsKey);
        }
    }

    public function providePrototypedArrayNodeDefaults()
    {
        return array(
            array(null, true, false, array(array())),
            array(2, true, false, array(array(), array())),
            array('2', false, true, array('2' => array())),
            array('foo', false, true, array('foo' => array())),
            array(array('foo'), false, true, array('foo' => array())),
            array(array('foo', 'bar'), false, true, array('foo' => array(), 'bar' => array())),
        );
    }

    public function testNestedPrototypedArrayNodes()
    {
        $node = new ArrayNodeDefinition('root');
        $node
            ->addDefaultChildrenIfNoneSet()
            ->prototype('array')
                  ->prototype('array')
        ;
        $node->getNode();
    }

    public function testEnabledNodeDefaults()
    {
        $node = new ArrayNodeDefinition('root');
        $node
            ->canBeEnabled()
            ->children()
                ->scalarNode('foo')->defaultValue('bar')->end()
        ;

        $this->assertEquals(array('enabled' => false, 'foo' => 'bar'), $node->getNode()->getDefaultValue());
    }

    /**
     * @dataProvider getEnableableNodeFixtures
     */
    public function testTrueEnableEnabledNode($expected, $config, $message)
    {
        $processor = new Processor();
        $node = new ArrayNodeDefinition('root');
        $node
            ->canBeEnabled()
            ->children()
                ->scalarNode('foo')->defaultValue('bar')->end()
        ;

        $this->assertEquals(
            $expected,
            $processor->process($node->getNode(), $config),
            $message
        );
    }

    public function getEnableableNodeFixtures()
    {
        return array(
            array(array('enabled' => true, 'foo' => 'bar'), array(true), 'true enables an enableable node'),
            array(array('enabled' => true, 'foo' => 'bar'), array(null), 'null enables an enableable node'),
            array(array('enabled' => true, 'foo' => 'bar'), array(array('enabled' => true)), 'An enableable node can be enabled'),
            array(array('enabled' => true, 'foo' => 'baz'), array(array('foo' => 'baz')), 'any configuration enables an enableable node'),
            array(array('enabled' => false, 'foo' => 'baz'), array(array('foo' => 'baz', 'enabled' => false)), 'An enableable node can be disabled'),
            array(array('enabled' => false, 'foo' => 'bar'), array(false), 'false disables an enableable node'),
        );
    }

    protected function getField($object, $field)
    {
        $reflection = new \ReflectionProperty($object, $field);
        $reflection->setAccessible(true);

        return $reflection->getValue($object);
    }
}
PK��Z
Kmޮ
�
Qtest/Config/Symfony/Component/Config/Tests/Definition/Builder/NodeBuilderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition\Builder;

use Symfony\Component\Config\Definition\Builder\NodeBuilder as BaseNodeBuilder;
use Symfony\Component\Config\Definition\Builder\VariableNodeDefinition as BaseVariableNodeDefinition;

class NodeBuilderTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \RuntimeException
     */
    public function testThrowsAnExceptionWhenTryingToCreateANonRegisteredNodeType()
    {
        $builder = new BaseNodeBuilder();
        $builder->node('', 'foobar');
    }

    /**
     * @expectedException \RuntimeException
     */
    public function testThrowsAnExceptionWhenTheNodeClassIsNotFound()
    {
        $builder = new BaseNodeBuilder();
        $builder
            ->setNodeClass('noclasstype', '\\foo\\bar\\noclass')
            ->node('', 'noclasstype');
    }

    public function testAddingANewNodeType()
    {
        $class = __NAMESPACE__.'\\SomeNodeDefinition';

        $builder = new BaseNodeBuilder();
        $node = $builder
            ->setNodeClass('newtype', $class)
            ->node('', 'newtype');

        $this->assertInstanceOf($class, $node);
    }

    public function testOverridingAnExistingNodeType()
    {
        $class = __NAMESPACE__.'\\SomeNodeDefinition';

        $builder = new BaseNodeBuilder();
        $node = $builder
            ->setNodeClass('variable', $class)
            ->node('', 'variable');

        $this->assertInstanceOf($class, $node);
    }

    public function testNodeTypesAreNotCaseSensitive()
    {
        $builder = new BaseNodeBuilder();

        $node1 = $builder->node('', 'VaRiAbLe');
        $node2 = $builder->node('', 'variable');

        $this->assertInstanceOf(get_class($node1), $node2);

        $builder->setNodeClass('CuStOm', __NAMESPACE__.'\\SomeNodeDefinition');

        $node1 = $builder->node('', 'CUSTOM');
        $node2 = $builder->node('', 'custom');

        $this->assertInstanceOf(get_class($node1), $node2);
    }

    public function testNumericNodeCreation()
    {
        $builder = new NodeBuilder();

        $node = $builder->integerNode('foo')->min(3)->max(5);
        $this->assertInstanceOf('Symfony\Component\Config\Definition\Builder\IntegerNodeDefinition', $node);

        $node = $builder->floatNode('bar')->min(3.0)->max(5.0);
        $this->assertInstanceOf('Symfony\Component\Config\Definition\Builder\FloatNodeDefinition', $node);
    }
}

class SomeNodeDefinition extends BaseVariableNodeDefinition
{
}
PK��Z�����Qtest/Config/Symfony/Component/Config/Tests/Definition/Builder/TreeBuilderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition\Builder;

use Symfony\Component\Config\Tests\Definition\Builder\NodeBuilder as CustomNodeBuilder;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\Builder\NodeBuilder;

require __DIR__.'/../../Fixtures/Builder/NodeBuilder.php';
require __DIR__.'/../../Fixtures/Builder/BarNodeDefinition.php';
require __DIR__.'/../../Fixtures/Builder/VariableNodeDefinition.php';

class TreeBuilderTest extends \PHPUnit_Framework_TestCase
{
    public function testUsingACustomNodeBuilder()
    {
        $builder = new TreeBuilder();
        $root = $builder->root('custom', 'array', new CustomNodeBuilder());

        $nodeBuilder = $root->children();

        $this->assertInstanceOf('Symfony\Component\Config\Tests\Definition\Builder\NodeBuilder', $nodeBuilder);

        $nodeBuilder = $nodeBuilder->arrayNode('deeper')->children();

        $this->assertInstanceOf('Symfony\Component\Config\Tests\Definition\Builder\NodeBuilder', $nodeBuilder);
    }

    public function testOverrideABuiltInNodeType()
    {
        $builder = new TreeBuilder();
        $root = $builder->root('override', 'array', new CustomNodeBuilder());

        $definition = $root->children()->variableNode('variable');

        $this->assertInstanceOf('Symfony\Component\Config\Tests\Definition\Builder\VariableNodeDefinition', $definition);
    }

    public function testAddANodeType()
    {
        $builder = new TreeBuilder();
        $root = $builder->root('override', 'array', new CustomNodeBuilder());

        $definition = $root->children()->barNode('variable');

        $this->assertInstanceOf('Symfony\Component\Config\Tests\Definition\Builder\BarNodeDefinition', $definition);
    }

    public function testCreateABuiltInNodeTypeWithACustomNodeBuilder()
    {
        $builder = new TreeBuilder();
        $root = $builder->root('builtin', 'array', new CustomNodeBuilder());

        $definition = $root->children()->booleanNode('boolean');

        $this->assertInstanceOf('Symfony\Component\Config\Definition\Builder\BooleanNodeDefinition', $definition);
    }

    public function testPrototypedArrayNodeUseTheCustomNodeBuilder()
    {
        $builder = new TreeBuilder();
        $root = $builder->root('override', 'array', new CustomNodeBuilder());

        $root->prototype('bar')->end();
    }

    public function testAnExtendedNodeBuilderGetsPropagatedToTheChildren()
    {
        $builder = new TreeBuilder();

        $builder->root('propagation')
            ->children()
                ->setNodeClass('extended', 'Symfony\Component\Config\Tests\Definition\Builder\VariableNodeDefinition')
                ->node('foo', 'extended')->end()
                ->arrayNode('child')
                    ->children()
                        ->node('foo', 'extended')
                    ->end()
                ->end()
            ->end()
        ->end();
    }

    public function testDefinitionInfoGetsTransferredToNode()
    {
        $builder = new TreeBuilder();

        $builder->root('test')->info('root info')
            ->children()
                ->node('child', 'variable')->info('child info')->defaultValue('default')
            ->end()
        ->end();

        $tree = $builder->buildTree();
        $children = $tree->getChildren();

        $this->assertEquals('root info', $tree->getInfo());
        $this->assertEquals('child info', $children['child']->getInfo());
    }

    public function testDefinitionExampleGetsTransferredToNode()
    {
        $builder = new TreeBuilder();

        $builder->root('test')
            ->example(array('key' => 'value'))
            ->children()
                ->node('child', 'variable')->info('child info')->defaultValue('default')->example('example')
            ->end()
        ->end();

        $tree = $builder->buildTree();
        $children = $tree->getChildren();

        $this->assertTrue(is_array($tree->getExample()));
        $this->assertEquals('example', $children['child']->getExample());
    }
}
PK��ZEj~�jj[test/Config/Symfony/Component/Config/Tests/Definition/Builder/NumericNodeDefinitionTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition\Builder;

use Symfony\Component\Config\Definition\Builder\IntegerNodeDefinition as NumericNodeDefinition;
use Symfony\Component\Config\Definition\Builder\IntegerNodeDefinition;
use Symfony\Component\Config\Definition\Builder\FloatNodeDefinition;

class NumericNodeDefinitionTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \InvalidArgumentException
     * @expectedExceptionMessage You cannot define a min(4) as you already have a max(3)
     */
    public function testIncoherentMinAssertion()
    {
        $def = new NumericNodeDefinition('foo');
        $def->max(3)->min(4);
    }

    /**
     * @expectedException \InvalidArgumentException
     * @expectedExceptionMessage You cannot define a max(2) as you already have a min(3)
     */
    public function testIncoherentMaxAssertion()
    {
        $node = new NumericNodeDefinition('foo');
        $node->min(3)->max(2);
    }

    /**
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
     * @expectedExceptionMessage The value 4 is too small for path "foo". Should be greater than or equal to 5
     */
    public function testIntegerMinAssertion()
    {
        $def = new IntegerNodeDefinition('foo');
        $def->min(5)->getNode()->finalize(4);
    }

    /**
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
     * @expectedExceptionMessage The value 4 is too big for path "foo". Should be less than or equal to 3
     */
    public function testIntegerMaxAssertion()
    {
        $def = new IntegerNodeDefinition('foo');
        $def->max(3)->getNode()->finalize(4);
    }

    public function testIntegerValidMinMaxAssertion()
    {
        $def = new IntegerNodeDefinition('foo');
        $node = $def->min(3)->max(7)->getNode();
        $this->assertEquals(4, $node->finalize(4));
    }

    /**
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
     * @expectedExceptionMessage The value 400 is too small for path "foo". Should be greater than or equal to 500
     */
    public function testFloatMinAssertion()
    {
        $def = new FloatNodeDefinition('foo');
        $def->min(5E2)->getNode()->finalize(4e2);
    }

    /**
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
     * @expectedExceptionMessage The value 4.3 is too big for path "foo". Should be less than or equal to 0.3
     */
    public function testFloatMaxAssertion()
    {
        $def = new FloatNodeDefinition('foo');
        $def->max(0.3)->getNode()->finalize(4.3);
    }

    public function testFloatValidMinMaxAssertion()
    {
        $def = new FloatNodeDefinition('foo');
        $node = $def->min(3.0)->max(7e2)->getNode();
        $this->assertEquals(4.5, $node->finalize(4.5));
    }
}
PK��ZjO灃�Htest/Config/Symfony/Component/Config/Tests/Definition/ScalarNodeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition;

use Symfony\Component\Config\Definition\ScalarNode;

class ScalarNodeTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getValidValues
     */
    public function testNormalize($value)
    {
        $node = new ScalarNode('test');
        $this->assertSame($value, $node->normalize($value));
    }

    public function getValidValues()
    {
        return array(
            array(false),
            array(true),
            array(null),
            array(''),
            array('foo'),
            array(0),
            array(1),
            array(0.0),
            array(0.1),
        );
    }

    /**
     * @dataProvider getInvalidValues
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidTypeException
     */
    public function testNormalizeThrowsExceptionOnInvalidValues($value)
    {
        $node = new ScalarNode('test');
        $node->normalize($value);
    }

    public function getInvalidValues()
    {
        return array(
            array(array()),
            array(array('foo' => 'bar')),
            array(new \stdClass()),
        );
    }
}
PK��Z�y���Xtest/Config/Symfony/Component/Config/Tests/Definition/Dumper/YamlReferenceDumperTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition\Dumper;

use Symfony\Component\Config\Definition\Dumper\YamlReferenceDumper;
use Symfony\Component\Config\Tests\Fixtures\Configuration\ExampleConfiguration;

class YamlReferenceDumperTest extends \PHPUnit_Framework_TestCase
{
    public function testDumper()
    {
        $configuration = new ExampleConfiguration();

        $dumper = new YamlReferenceDumper();

        $this->markTestIncomplete('The Yaml Dumper currently does not support prototyped arrays');
        $this->assertEquals($this->getConfigurationAsString(), $dumper->dump($configuration));
    }

    private function getConfigurationAsString()
    {
      return <<<EOL
acme_root:
    boolean:              true
    scalar_empty:         ~
    scalar_null:          ~
    scalar_true:          true
    scalar_false:         false
    scalar_default:       default
    scalar_array_empty:   []
    scalar_array_defaults:

        # Defaults:
        - elem1
        - elem2
    scalar_required:      ~ # Required
    enum:                 ~ # One of "this"; "that"

    # some info
    array:
        child1:               ~
        child2:               ~

        # this is a long
        # multi-line info text
        # which should be indented
        child3:               ~ # Example: example setting
    parameters:

        # Prototype
        name:                 ~
    connections:
        # Prototype
        - { user: ~, pass: ~ }

EOL;
    }
}
PK��Z~�P+Wtest/Config/Symfony/Component/Config/Tests/Definition/Dumper/XmlReferenceDumperTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition\Dumper;

use Symfony\Component\Config\Definition\Dumper\XmlReferenceDumper;
use Symfony\Component\Config\Tests\Fixtures\Configuration\ExampleConfiguration;

class XmlReferenceDumperTest extends \PHPUnit_Framework_TestCase
{
    public function testDumper()
    {
        $configuration = new ExampleConfiguration();

        $dumper = new XmlReferenceDumper();
        $this->assertEquals($this->getConfigurationAsString(), $dumper->dump($configuration));
    }

    public function testNamespaceDumper()
    {
        $configuration = new ExampleConfiguration();

        $dumper = new XmlReferenceDumper();
        $this->assertEquals(str_replace('http://example.org/schema/dic/acme_root', 'http://symfony.com/schema/dic/symfony', $this->getConfigurationAsString()), $dumper->dump($configuration, 'http://symfony.com/schema/dic/symfony'));
    }

    private function getConfigurationAsString()
    {
      return <<<EOL
<!-- Namespace: http://example.org/schema/dic/acme_root -->
<!-- scalar-required: Required -->
<!-- enum: One of "this"; "that" -->
<config
    boolean="true"
    scalar-empty=""
    scalar-null="null"
    scalar-true="true"
    scalar-false="false"
    scalar-default="default"
    scalar-array-empty=""
    scalar-array-defaults="elem1,elem2"
    scalar-required=""
    enum=""
>

    <!-- some info -->
    <!--
        child3: this is a long
                multi-line info text
                which should be indented;
                Example: example setting
    -->
    <array
        child1=""
        child2=""
        child3=""
    />

    <!-- prototype -->
    <parameter name="parameter name">scalar value</parameter>

    <!-- prototype -->
    <connection
        user=""
        pass=""
    />

</config>

EOL;
    }
}
PK��ZD�99Ctest/Config/Symfony/Component/Config/Tests/Definition/MergeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition;

use Symfony\Component\Config\Definition\Builder\TreeBuilder;

class MergeTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \Symfony\Component\Config\Definition\Exception\ForbiddenOverwriteException
     */
    public function testForbiddenOverwrite()
    {
        $tb = new TreeBuilder();
        $tree = $tb
            ->root('root', 'array')
                ->children()
                    ->node('foo', 'scalar')
                        ->cannotBeOverwritten()
                    ->end()
                ->end()
            ->end()
            ->buildTree()
        ;

        $a = array(
            'foo' => 'bar',
        );

        $b = array(
            'foo' => 'moo',
        );

        $tree->merge($a, $b);
    }

    public function testUnsetKey()
    {
        $tb = new TreeBuilder();
        $tree = $tb
            ->root('root', 'array')
                ->children()
                    ->node('foo', 'scalar')->end()
                    ->node('bar', 'scalar')->end()
                    ->node('unsettable', 'array')
                        ->canBeUnset()
                        ->children()
                            ->node('foo', 'scalar')->end()
                            ->node('bar', 'scalar')->end()
                        ->end()
                    ->end()
                    ->node('unsetted', 'array')
                        ->canBeUnset()
                        ->prototype('scalar')->end()
                    ->end()
                ->end()
            ->end()
            ->buildTree()
        ;

        $a = array(
            'foo' => 'bar',
            'unsettable' => array(
                'foo' => 'a',
                'bar' => 'b',
            ),
            'unsetted' => false,
        );

        $b = array(
            'foo' => 'moo',
            'bar' => 'b',
            'unsettable' => false,
            'unsetted' => array('a', 'b'),
        );

        $this->assertEquals(array(
            'foo' => 'moo',
            'bar' => 'b',
            'unsettable' => false,
            'unsetted' => array('a', 'b'),
        ), $tree->merge($a, $b));
    }

    /**
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
     */
    public function testDoesNotAllowNewKeysInSubsequentConfigs()
    {
        $tb = new TreeBuilder();
        $tree = $tb
            ->root('config', 'array')
                ->children()
                    ->node('test', 'array')
                        ->disallowNewKeysInSubsequentConfigs()
                        ->useAttributeAsKey('key')
                        ->prototype('array')
                            ->children()
                                ->node('value', 'scalar')->end()
                            ->end()
                        ->end()
                    ->end()
                ->end()
            ->end()
            ->buildTree();

        $a = array(
            'test' => array(
                'a' => array('value' => 'foo')
            )
        );

        $b = array(
            'test' => array(
                'b' => array('value' => 'foo')
            )
        );

        $tree->merge($a, $b);
    }

    public function testPerformsNoDeepMerging()
    {
        $tb = new TreeBuilder();

        $tree = $tb
            ->root('config', 'array')
                ->children()
                    ->node('no_deep_merging', 'array')
                        ->performNoDeepMerging()
                        ->children()
                            ->node('foo', 'scalar')->end()
                            ->node('bar', 'scalar')->end()
                        ->end()
                    ->end()
                ->end()
            ->end()
            ->buildTree()
        ;

        $a = array(
            'no_deep_merging' => array(
                'foo' => 'a',
                'bar' => 'b',
            ),
        );

        $b = array(
            'no_deep_merging' => array(
                'c' => 'd',
            )
        );

        $this->assertEquals(array(
            'no_deep_merging' => array(
                'c' => 'd',
            )
        ), $tree->merge($a, $b));
    }

    public function testPrototypeWithoutAKeyAttribute()
    {
        $tb = new TreeBuilder();

        $tree = $tb
            ->root('config', 'array')
                ->children()
                    ->arrayNode('append_elements')
                        ->prototype('scalar')->end()
                    ->end()
                ->end()
            ->end()
            ->buildTree()
        ;

        $a = array(
            'append_elements' => array('a', 'b'),
        );

        $b = array(
            'append_elements' => array('c', 'd'),
        );

        $this->assertEquals(array('append_elements' => array('a', 'b', 'c', 'd')), $tree->merge($a, $b));
    }
}
PK��ZA�RRJtest/Config/Symfony/Component/Config/Tests/Definition/FinalizationTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition;

use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\Processor;
use Symfony\Component\Config\Definition\NodeInterface;

class FinalizationTest extends \PHPUnit_Framework_TestCase
{
    public function testUnsetKeyWithDeepHierarchy()
    {
        $tb = new TreeBuilder();
        $tree = $tb
            ->root('config', 'array')
                ->children()
                    ->node('level1', 'array')
                        ->canBeUnset()
                        ->children()
                            ->node('level2', 'array')
                                ->canBeUnset()
                                ->children()
                                    ->node('somevalue', 'scalar')->end()
                                    ->node('anothervalue', 'scalar')->end()
                                ->end()
                            ->end()
                            ->node('level1_scalar', 'scalar')->end()
                        ->end()
                    ->end()
                ->end()
            ->end()
            ->buildTree()
        ;

        $a = array(
            'level1' => array(
                'level2' => array(
                    'somevalue' => 'foo',
                    'anothervalue' => 'bar',
                ),
                'level1_scalar' => 'foo',
            ),
        );

        $b = array(
            'level1' => array(
                'level2' => false,
            ),
        );

        $this->assertEquals(array(
            'level1' => array(
                'level1_scalar' => 'foo',
            ),
        ), $this->process($tree, array($a, $b)));
    }

    protected function process(NodeInterface $tree, array $configs)
    {
        $processor = new Processor();

        return $processor->process($tree, $configs);
    }
}
PK��Z{���Itest/Config/Symfony/Component/Config/Tests/Definition/BooleanNodeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition;

use Symfony\Component\Config\Definition\BooleanNode;

class BooleanNodeTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getValidValues
     */
    public function testNormalize($value)
    {
        $node = new BooleanNode('test');
        $this->assertSame($value, $node->normalize($value));
    }

    public function getValidValues()
    {
        return array(
            array(false),
            array(true),
        );
    }

    /**
     * @dataProvider getInvalidValues
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidTypeException
     */
    public function testNormalizeThrowsExceptionOnInvalidValues($value)
    {
        $node = new BooleanNode('test');
        $node->normalize($value);
    }

    public function getInvalidValues()
    {
        return array(
            array(null),
            array(''),
            array('foo'),
            array(0),
            array(1),
            array(0.0),
            array(0.1),
            array(array()),
            array(array('foo' => 'bar')),
            array(new \stdClass()),
        );
    }
}
PK��Z%Jbx��Qtest/Config/Symfony/Component/Config/Tests/Definition/PrototypedArrayNodeTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition;

use Symfony\Component\Config\Definition\PrototypedArrayNode;
use Symfony\Component\Config\Definition\ArrayNode;
use Symfony\Component\Config\Definition\ScalarNode;

class PrototypedArrayNodeTest extends \PHPUnit_Framework_TestCase
{
    public function testGetDefaultValueReturnsAnEmptyArrayForPrototypes()
    {
        $node = new PrototypedArrayNode('root');
        $prototype = new ArrayNode(null, $node);
        $node->setPrototype($prototype);
        $this->assertEmpty($node->getDefaultValue());
    }

    public function testGetDefaultValueReturnsDefaultValueForPrototypes()
    {
        $node = new PrototypedArrayNode('root');
        $prototype = new ArrayNode(null, $node);
        $node->setPrototype($prototype);
        $node->setDefaultValue(array('test'));
        $this->assertEquals(array('test'), $node->getDefaultValue());
    }

    // a remapped key (e.g. "mapping" -> "mappings") should be unset after being used
    public function testRemappedKeysAreUnset()
    {
        $node = new ArrayNode('root');
        $mappingsNode = new PrototypedArrayNode('mappings');
        $node->addChild($mappingsNode);

        // each item under mappings is just a scalar
        $prototype = new ScalarNode(null, $mappingsNode);
        $mappingsNode->setPrototype($prototype);

        $remappings = array();
        $remappings[] = array('mapping', 'mappings');
        $node->setXmlRemappings($remappings);

        $normalized = $node->normalize(array('mapping' => array('foo', 'bar')));
        $this->assertEquals(array('mappings' => array('foo', 'bar')), $normalized);
    }

    /**
     * Tests that when a key attribute is mapped, that key is removed from the array:
     *
     *     <things>
     *         <option id="option1" value="foo">
     *         <option id="option2" value="bar">
     *     </things>
     *
     * The above should finally be mapped to an array that looks like this
     * (because "id" is the key attribute).
     *
     *     array(
     *         'things' => array(
     *             'option1' => 'foo',
     *             'option2' => 'bar',
     *         )
     *     )
     */
    public function testMappedAttributeKeyIsRemoved()
    {
        $node = new PrototypedArrayNode('root');
        $node->setKeyAttribute('id', true);

        // each item under the root is an array, with one scalar item
        $prototype = new ArrayNode(null, $node);
        $prototype->addChild(new ScalarNode('foo'));
        $node->setPrototype($prototype);

        $children = array();
        $children[] = array('id' => 'item_name', 'foo' => 'bar');
        $normalized = $node->normalize($children);

        $expected = array();
        $expected['item_name'] = array('foo' => 'bar');
        $this->assertEquals($expected, $normalized);
    }

    /**
     * Tests the opposite of the testMappedAttributeKeyIsRemoved because
     * the removal can be toggled with an option.
     */
    public function testMappedAttributeKeyNotRemoved()
    {
        $node = new PrototypedArrayNode('root');
        $node->setKeyAttribute('id', false);

        // each item under the root is an array, with two scalar items
        $prototype = new ArrayNode(null, $node);
        $prototype->addChild(new ScalarNode('foo'));
        $prototype->addChild(new ScalarNode('id')); // the key attribute will remain
        $node->setPrototype($prototype);

        $children = array();
        $children[] = array('id' => 'item_name', 'foo' => 'bar');
        $normalized = $node->normalize($children);

        $expected = array();
        $expected['item_name'] = array('id' => 'item_name', 'foo' => 'bar');
        $this->assertEquals($expected, $normalized);
    }

    public function testAddDefaultChildren()
    {
        $node = $this->getPrototypeNodeWithDefaultChildren();
        $node->setAddChildrenIfNoneSet();
        $this->assertTrue($node->hasDefaultValue());
        $this->assertEquals(array(array('foo' => 'bar')), $node->getDefaultValue());

        $node = $this->getPrototypeNodeWithDefaultChildren();
        $node->setKeyAttribute('foobar');
        $node->setAddChildrenIfNoneSet();
        $this->assertTrue($node->hasDefaultValue());
        $this->assertEquals(array('defaults' => array('foo' => 'bar')), $node->getDefaultValue());

        $node = $this->getPrototypeNodeWithDefaultChildren();
        $node->setKeyAttribute('foobar');
        $node->setAddChildrenIfNoneSet('defaultkey');
        $this->assertTrue($node->hasDefaultValue());
        $this->assertEquals(array('defaultkey' => array('foo' => 'bar')), $node->getDefaultValue());

        $node = $this->getPrototypeNodeWithDefaultChildren();
        $node->setKeyAttribute('foobar');
        $node->setAddChildrenIfNoneSet(array('defaultkey'));
        $this->assertTrue($node->hasDefaultValue());
        $this->assertEquals(array('defaultkey' => array('foo' => 'bar')), $node->getDefaultValue());

        $node = $this->getPrototypeNodeWithDefaultChildren();
        $node->setKeyAttribute('foobar');
        $node->setAddChildrenIfNoneSet(array('dk1', 'dk2'));
        $this->assertTrue($node->hasDefaultValue());
        $this->assertEquals(array('dk1' => array('foo' => 'bar'), 'dk2' => array('foo' => 'bar')), $node->getDefaultValue());

        $node = $this->getPrototypeNodeWithDefaultChildren();
        $node->setAddChildrenIfNoneSet(array(5, 6));
        $this->assertTrue($node->hasDefaultValue());
        $this->assertEquals(array(0 => array('foo' => 'bar'), 1 => array('foo' => 'bar')), $node->getDefaultValue());

        $node = $this->getPrototypeNodeWithDefaultChildren();
        $node->setAddChildrenIfNoneSet(2);
        $this->assertTrue($node->hasDefaultValue());
        $this->assertEquals(array(array('foo' => 'bar'), array('foo' => 'bar')), $node->getDefaultValue());
    }

    public function testDefaultChildrenWinsOverDefaultValue()
    {
        $node = $this->getPrototypeNodeWithDefaultChildren();
        $node->setAddChildrenIfNoneSet();
        $node->setDefaultValue(array('bar' => 'foo'));
        $this->assertTrue($node->hasDefaultValue());
        $this->assertEquals(array(array('foo' => 'bar')), $node->getDefaultValue());
    }

    protected function getPrototypeNodeWithDefaultChildren()
    {
        $node = new PrototypedArrayNode('root');
        $prototype = new ArrayNode(null, $node);
        $child = new ScalarNode('foo');
        $child->setDefaultValue('bar');
        $prototype->addChild($child);
        $prototype->setAddIfNotSet(true);
        $node->setPrototype($prototype);

        return $node;
    }
}
PK��Z�b�..Dtest/Config/Symfony/Component/Config/Tests/Fixtures/Util/invalid.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<root>
PK��Zc=���Jtest/Config/Symfony/Component/Config/Tests/Fixtures/Util/document_type.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE scan [<!ENTITY test SYSTEM "php://filter/read=convert.base64-encode/resource={{ resource }}">]>
<scan></scan>
PK��ZGɩ�SSKtest/Config/Symfony/Component/Config/Tests/Fixtures/Util/invalid_schema.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<root2 xmlns="http://example.com/schema" />
PK��Z\�XXBtest/Config/Symfony/Component/Config/Tests/Fixtures/Util/valid.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="http://example.com/schema">
</root>
PK��Z�&�Ctest/Config/Symfony/Component/Config/Tests/Fixtures/Util/schema.xsdnu�[���<?xml version="1.0" encoding="UTF-8"?>

<xsd:schema xmlns="http://example.com/schema"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://example.com/schema"
    elementFormDefault="qualified">

  <xsd:element name="root" />
</xsd:schema>
PK��Z�r_���Qtest/Config/Symfony/Component/Config/Tests/Fixtures/Builder/BarNodeDefinition.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition\Builder;

use Symfony\Component\Config\Definition\Builder\NodeDefinition;

class BarNodeDefinition extends NodeDefinition
{
    protected function createNode()
    {
    }
}
PK��Z��@��Vtest/Config/Symfony/Component/Config/Tests/Fixtures/Builder/VariableNodeDefinition.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition\Builder;

use Symfony\Component\Config\Definition\Builder\VariableNodeDefinition as BaseVariableNodeDefinition;

class VariableNodeDefinition extends BaseVariableNodeDefinition
{
}
PK��Z�u�;ssKtest/Config/Symfony/Component/Config/Tests/Fixtures/Builder/NodeBuilder.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition\Builder;

use Symfony\Component\Config\Definition\Builder\NodeBuilder as BaseNodeBuilder;

class NodeBuilder extends BaseNodeBuilder
{
    public function barNode($name)
    {
        return $this->node($name, 'bar');
    }

    protected function getNodeClass($type)
    {
        switch ($type) {
            case 'variable':
                return __NAMESPACE__.'\\'.ucfirst($type).'NodeDefinition';
            case 'bar':
                return __NAMESPACE__.'\\'.ucfirst($type).'NodeDefinition';
            default:
                return parent::getNodeClass($type);
        }
    }
}
PK��Z�����
�
Ztest/Config/Symfony/Component/Config/Tests/Fixtures/Configuration/ExampleConfiguration.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Fixtures\Configuration;

use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;

class ExampleConfiguration implements ConfigurationInterface
{
    public function getConfigTreeBuilder()
    {
        $treeBuilder = new TreeBuilder();
        $rootNode = $treeBuilder->root('acme_root');

        $rootNode
            ->fixXmlConfig('parameter')
            ->fixXmlConfig('connection')
            ->children()
                ->booleanNode('boolean')->defaultTrue()->end()
                ->scalarNode('scalar_empty')->end()
                ->scalarNode('scalar_null')->defaultNull()->end()
                ->scalarNode('scalar_true')->defaultTrue()->end()
                ->scalarNode('scalar_false')->defaultFalse()->end()
                ->scalarNode('scalar_default')->defaultValue('default')->end()
                ->scalarNode('scalar_array_empty')->defaultValue(array())->end()
                ->scalarNode('scalar_array_defaults')->defaultValue(array('elem1', 'elem2'))->end()
                ->scalarNode('scalar_required')->isRequired()->end()
                ->enumNode('enum')->values(array('this', 'that'))->end()
                ->arrayNode('array')
                    ->info('some info')
                    ->canBeUnset()
                    ->children()
                        ->scalarNode('child1')->end()
                        ->scalarNode('child2')->end()
                        ->scalarNode('child3')
                            ->info(
                                "this is a long\n".
                                "multi-line info text\n".
                                "which should be indented"
                            )
                            ->example('example setting')
                        ->end()
                    ->end()
                ->end()
                ->arrayNode('parameters')
                    ->useAttributeAsKey('name')
                    ->prototype('scalar')->end()
                ->end()
                ->arrayNode('connections')
                    ->prototype('array')
                        ->children()
                            ->scalarNode('user')->end()
                            ->scalarNode('pass')->end()
                        ->end()
                    ->end()
                ->end()
            ->end()
        ;

        return $treeBuilder;
    }
}
PK��ZAtest/Config/Symfony/Component/Config/Tests/Fixtures/Again/foo.xmlnu�[���PK��Z;test/Config/Symfony/Component/Config/Tests/Fixtures/foo.xmlnu�[���PK��Z������Mtest/Config/Symfony/Component/Config/Tests/Resource/DirectoryResourceTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Resource;

use Symfony\Component\Config\Resource\DirectoryResource;

class DirectoryResourceTest extends \PHPUnit_Framework_TestCase
{
    protected $directory;

    protected function setUp()
    {
        $this->directory = sys_get_temp_dir().'/symfonyDirectoryIterator';
        if (!file_exists($this->directory)) {
            mkdir($this->directory);
        }
        touch($this->directory.'/tmp.xml');
    }

    protected function tearDown()
    {
        if (!is_dir($this->directory)) {
            return;
        }
        $this->removeDirectory($this->directory);
    }

    protected function removeDirectory($directory)
    {
        $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($directory), \RecursiveIteratorIterator::CHILD_FIRST);
        foreach ($iterator as $path) {
            if (preg_match('#[/\\\\]\.\.?$#', $path->__toString())) {
                continue;
            }
            if ($path->isDir()) {
               rmdir($path->__toString());
            } else {
               unlink($path->__toString());
            }
        }
        rmdir($directory);
    }

    public function testGetResource()
    {
        $resource = new DirectoryResource($this->directory);
        $this->assertSame($this->directory, $resource->getResource(), '->getResource() returns the path to the resource');
        $this->assertSame($this->directory, (string) $resource, '->__toString() returns the path to the resource');
    }

    public function testGetPattern()
    {
        $resource = new DirectoryResource('foo', 'bar');
        $this->assertEquals('bar', $resource->getPattern());
    }

    public function testIsFresh()
    {
        $resource = new DirectoryResource($this->directory);
        $this->assertTrue($resource->isFresh(time() + 10), '->isFresh() returns true if the resource has not changed');
        $this->assertFalse($resource->isFresh(time() - 86400), '->isFresh() returns false if the resource has been updated');

        $resource = new DirectoryResource('/____foo/foobar'.rand(1, 999999));
        $this->assertFalse($resource->isFresh(time()), '->isFresh() returns false if the resource does not exist');
    }

    public function testIsFreshUpdateFile()
    {
        $resource = new DirectoryResource($this->directory);
        touch($this->directory.'/tmp.xml', time() + 20);
        $this->assertFalse($resource->isFresh(time() + 10), '->isFresh() returns false if an existing file is modified');
    }

    public function testIsFreshNewFile()
    {
        $resource = new DirectoryResource($this->directory);
        touch($this->directory.'/new.xml', time() + 20);
        $this->assertFalse($resource->isFresh(time() + 10), '->isFresh() returns false if a new file is added');
    }

    public function testIsFreshDeleteFile()
    {
        $resource = new DirectoryResource($this->directory);
        unlink($this->directory.'/tmp.xml');
        $this->assertFalse($resource->isFresh(time()), '->isFresh() returns false if an existing file is removed');
    }

    public function testIsFreshDeleteDirectory()
    {
        $resource = new DirectoryResource($this->directory);
        $this->removeDirectory($this->directory);
        $this->assertFalse($resource->isFresh(time()), '->isFresh() returns false if the whole resource is removed');
    }

    public function testIsFreshCreateFileInSubdirectory()
    {
        $subdirectory = $this->directory.'/subdirectory';
        mkdir($subdirectory);

        $resource = new DirectoryResource($this->directory);
        $this->assertTrue($resource->isFresh(time() + 10), '->isFresh() returns true if an unmodified subdirectory exists');

        touch($subdirectory.'/newfile.xml', time() + 20);
        $this->assertFalse($resource->isFresh(time() + 10), '->isFresh() returns false if a new file in a subdirectory is added');
    }

    public function testIsFreshModifySubdirectory()
    {
        $resource = new DirectoryResource($this->directory);

        $subdirectory = $this->directory.'/subdirectory';
        mkdir($subdirectory);
        touch($subdirectory, time() + 20);

        $this->assertFalse($resource->isFresh(time() + 10), '->isFresh() returns false if a subdirectory is modified (e.g. a file gets deleted)');
    }

    public function testFilterRegexListNoMatch()
    {
        $resource = new DirectoryResource($this->directory, '/\.(foo|xml)$/');

        touch($this->directory.'/new.bar', time() + 20);
        $this->assertTrue($resource->isFresh(time() + 10), '->isFresh() returns true if a new file not matching the filter regex is created');
    }

    public function testFilterRegexListMatch()
    {
        $resource = new DirectoryResource($this->directory, '/\.(foo|xml)$/');

        touch($this->directory.'/new.xml', time() + 20);
        $this->assertFalse($resource->isFresh(time() + 10), '->isFresh() returns false if an new file matching the filter regex is created ');
    }

    public function testSerializeUnserialize()
    {
        $resource = new DirectoryResource($this->directory, '/\.(foo|xml)$/');

        $unserialized = unserialize(serialize($resource));

        $this->assertSame($this->directory, $resource->getResource());
        $this->assertSame('/\.(foo|xml)$/', $resource->getPattern());
    }
}
PK��Z�D-��Htest/Config/Symfony/Component/Config/Tests/Resource/FileResourceTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Resource;

use Symfony\Component\Config\Resource\FileResource;

class FileResourceTest extends \PHPUnit_Framework_TestCase
{
    protected $resource;
    protected $file;

    protected function setUp()
    {
        $this->file = realpath(sys_get_temp_dir()).'/tmp.xml';
        touch($this->file);
        $this->resource = new FileResource($this->file);
    }

    protected function tearDown()
    {
        unlink($this->file);
    }

    public function testGetResource()
    {
        $this->assertSame(realpath($this->file), $this->resource->getResource(), '->getResource() returns the path to the resource');
    }

    public function testToString()
    {
        $this->assertSame(realpath($this->file), (string) $this->resource);
    }

    public function testIsFresh()
    {
        $this->assertTrue($this->resource->isFresh(time() + 10), '->isFresh() returns true if the resource has not changed');
        $this->assertFalse($this->resource->isFresh(time() - 86400), '->isFresh() returns false if the resource has been updated');

        $resource = new FileResource('/____foo/foobar'.rand(1, 999999));
        $this->assertFalse($resource->isFresh(time()), '->isFresh() returns false if the resource does not exist');
    }

    public function testSerializeUnserialize()
    {
        $unserialized = unserialize(serialize($this->resource));

        $this->assertSame(realpath($this->file), $this->resource->getResource());
    }
}
PK��Z��s@test/Config/Symfony/Component/Config/Tests/Util/XmlUtilsTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Loader;

use Symfony\Component\Config\Util\XmlUtils;

class XmlUtilsTest extends \PHPUnit_Framework_TestCase
{
    public function testLoadFile()
    {
        $fixtures = __DIR__.'/../Fixtures/Util/';

        try {
            XmlUtils::loadFile($fixtures.'invalid.xml');
            $this->fail();
        } catch (\InvalidArgumentException $e) {
            $this->assertContains('ERROR 77', $e->getMessage());
        }

        try {
            XmlUtils::loadFile($fixtures.'document_type.xml');
            $this->fail();
        } catch (\InvalidArgumentException $e) {
            $this->assertContains('Document types are not allowed', $e->getMessage());
        }

        try {
            XmlUtils::loadFile($fixtures.'invalid_schema.xml', $fixtures.'schema.xsd');
            $this->fail();
        } catch (\InvalidArgumentException $e) {
            $this->assertContains('ERROR 1845', $e->getMessage());
        }

        try {
            XmlUtils::loadFile($fixtures.'invalid_schema.xml', 'invalid_callback_or_file');
            $this->fail();
        } catch (\InvalidArgumentException $e) {
            $this->assertContains('XSD file or callable', $e->getMessage());
        }

        $mock = $this->getMock(__NAMESPACE__.'\Validator');
        $mock->expects($this->exactly(2))->method('validate')->will($this->onConsecutiveCalls(false, true));

        try {
            XmlUtils::loadFile($fixtures.'valid.xml', array($mock, 'validate'));
            $this->fail();
        } catch (\InvalidArgumentException $e) {
            $this->assertContains('is not valid', $e->getMessage());
        }

        $this->assertInstanceOf('DOMDocument', XmlUtils::loadFile($fixtures.'valid.xml', array($mock, 'validate')));
    }

    /**
     * @dataProvider getDataForConvertDomToArray
     */
    public function testConvertDomToArray($expected, $xml, $root = false, $checkPrefix = true)
    {
        $dom = new \DOMDocument();
        $dom->loadXML($root ? $xml : '<root>'.$xml.'</root>');

        $this->assertSame($expected, XmlUtils::convertDomElementToArray($dom->documentElement, $checkPrefix));
    }

    public function getDataForConvertDomToArray()
    {
        return array(
            array(null, ''),
            array('bar', 'bar'),
            array(array('bar' => 'foobar'), '<foo bar="foobar" />', true),
            array(array('foo' => null), '<foo />'),
            array(array('foo' => 'bar'), '<foo>bar</foo>'),
            array(array('foo' => array('foo' => 'bar')), '<foo foo="bar"/>'),
            array(array('foo' => array('foo' => 0)), '<foo><foo>0</foo></foo>'),
            array(array('foo' => array('foo' => 'bar')), '<foo><foo>bar</foo></foo>'),
            array(array('foo' => array('foo' => 'bar', 'value' => 'text')), '<foo foo="bar">text</foo>'),
            array(array('foo' => array('attr' => 'bar', 'foo' => 'text')), '<foo attr="bar"><foo>text</foo></foo>'),
            array(array('foo' => array('bar', 'text')), '<foo>bar</foo><foo>text</foo>'),
            array(array('foo' => array(array('foo' => 'bar'), array('foo' => 'text'))), '<foo foo="bar"/><foo foo="text" />'),
            array(array('foo' => array('foo' => array('bar', 'text'))), '<foo foo="bar"><foo>text</foo></foo>'),
            array(array('foo' => 'bar'), '<foo><!-- Comment -->bar</foo>'),
            array(array('foo' => 'text'), '<foo xmlns:h="http://www.example.org/bar" h:bar="bar">text</foo>'),
            array(array('foo' => array('bar' => 'bar', 'value' => 'text')), '<foo xmlns:h="http://www.example.org/bar" h:bar="bar">text</foo>', false, false),
            array(array('attr' => 1, 'b' => 'hello'), '<foo:a xmlns:foo="http://www.example.org/foo" xmlns:h="http://www.example.org/bar" attr="1" h:bar="bar"><foo:b>hello</foo:b><h:c>2</h:c></foo:a>', true),
        );
    }

    /**
     * @dataProvider getDataForPhpize
     */
    public function testPhpize($expected, $value)
    {
        $this->assertSame($expected, XmlUtils::phpize($value));
    }

    public function getDataForPhpize()
    {
        return array(
            array('', ''),
            array(null, 'null'),
            array(true, 'true'),
            array(false, 'false'),
            array(null, 'Null'),
            array(true, 'True'),
            array(false, 'False'),
            array(0, '0'),
            array(1, '1'),
            array(-1, '-1'),
            array(0777, '0777'),
            array(255, '0xFF'),
            array(100.0, '1e2'),
            array(-120.0, '-1.2E2'),
            array(-10100.1, '-10100.1'),
            array('-10,100.1', '-10,100.1'),
            array('1234 5678 9101 1121 3141', '1234 5678 9101 1121 3141'),
            array('1,2,3,4', '1,2,3,4'),
            array('11,22,33,44', '11,22,33,44'),
            array('11,222,333,4', '11,222,333,4'),
            array('1,222,333,444', '1,222,333,444'),
            array('11,222,333,444', '11,222,333,444'),
            array('111,222,333,444', '111,222,333,444'),
            array('1111,2222,3333,4444,5555', '1111,2222,3333,4444,5555'),
            array('foo', 'foo'),
            array(6, '0b0110'),
        );
    }

    public function testLoadEmptyXmlFile()
    {
        $file = __DIR__.'/../Fixtures/foo.xml';
        $this->setExpectedException('InvalidArgumentException', 'File '.$file.' does not contain valid XML, it is empty.');
        XmlUtils::loadFile($file);
    }

    // test for issue https://github.com/symfony/symfony/issues/9731
    public function testLoadWrongEmptyXMLWithErrorHandler()
    {
        $originalDisableEntities = libxml_disable_entity_loader(false);
        $errorReporting = error_reporting(-1);

        set_error_handler(function ($errno, $errstr) {
            throw new \Exception($errstr, $errno);
        });

        $file = __DIR__.'/../Fixtures/foo.xml';
        try {
            XmlUtils::loadFile($file);
            $this->fail('An exception should have been raised');
        } catch (\InvalidArgumentException $e) {
            $this->assertEquals(sprintf('File %s does not contain valid XML, it is empty.', $file), $e->getMessage());
        }

        restore_error_handler();
        error_reporting($errorReporting);

        $disableEntities = libxml_disable_entity_loader(true);
        libxml_disable_entity_loader($disableEntities);

        libxml_disable_entity_loader($originalDisableEntities);

        $this->assertFalse($disableEntities);

        // should not throw an exception
        XmlUtils::loadFile(__DIR__.'/../Fixtures/Util/valid.xml', __DIR__.'/../Fixtures/Util/schema.xsd');
    }
}

interface Validator
{
    public function validate();
}
PK��Z Z��^^>test/Config/Symfony/Component/Config/Tests/ConfigCacheTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests;

use Symfony\Component\Config\ConfigCache;
use Symfony\Component\Config\Resource\FileResource;

class ConfigCacheTest extends \PHPUnit_Framework_TestCase
{
    private $resourceFile = null;

    private $cacheFile = null;

    private $metaFile = null;

    public function setUp()
    {
        $this->resourceFile = tempnam(sys_get_temp_dir(), '_resource');
        $this->cacheFile = tempnam(sys_get_temp_dir(), 'config_');
        $this->metaFile = $this->cacheFile.'.meta';

        $this->makeCacheFresh();
        $this->generateMetaFile();
    }

    public function tearDown()
    {
        $files = array($this->cacheFile, $this->metaFile, $this->resourceFile);

        foreach ($files as $file) {
            if (file_exists($file)) {
                unlink($file);
            }
        }
    }

    public function testToString()
    {
        $cache = new ConfigCache($this->cacheFile, true);

        $this->assertSame($this->cacheFile, (string) $cache);
    }

    public function testCacheIsNotFreshIfFileDoesNotExist()
    {
        unlink($this->cacheFile);

        $cache = new ConfigCache($this->cacheFile, false);

        $this->assertFalse($cache->isFresh());
    }

    public function testCacheIsAlwaysFreshIfFileExistsWithDebugDisabled()
    {
        $this->makeCacheStale();

        $cache = new ConfigCache($this->cacheFile, false);

        $this->assertTrue($cache->isFresh());
    }

    public function testCacheIsNotFreshWithoutMetaFile()
    {
        unlink($this->metaFile);

        $cache = new ConfigCache($this->cacheFile, true);

        $this->assertFalse($cache->isFresh());
    }

    public function testCacheIsFreshIfResourceIsFresh()
    {
        $cache = new ConfigCache($this->cacheFile, true);

        $this->assertTrue($cache->isFresh());
    }

    public function testCacheIsNotFreshIfOneOfTheResourcesIsNotFresh()
    {
        $this->makeCacheStale();

        $cache = new ConfigCache($this->cacheFile, true);

        $this->assertFalse($cache->isFresh());
    }

    public function testWriteDumpsFile()
    {
        unlink($this->cacheFile);
        unlink($this->metaFile);

        $cache = new ConfigCache($this->cacheFile, false);
        $cache->write('FOOBAR');

        $this->assertFileExists($this->cacheFile, 'Cache file is created');
        $this->assertSame('FOOBAR', file_get_contents($this->cacheFile));
        $this->assertFileNotExists($this->metaFile, 'Meta file is not created');
    }

    public function testWriteDumpsMetaFileWithDebugEnabled()
    {
        unlink($this->cacheFile);
        unlink($this->metaFile);

        $metadata = array(new FileResource($this->resourceFile));

        $cache = new ConfigCache($this->cacheFile, true);
        $cache->write('FOOBAR', $metadata);

        $this->assertFileExists($this->cacheFile, 'Cache file is created');
        $this->assertFileExists($this->metaFile, 'Meta file is created');
        $this->assertSame(serialize($metadata), file_get_contents($this->metaFile));
    }

    private function makeCacheFresh()
    {
        touch($this->resourceFile, filemtime($this->cacheFile) - 3600);
    }

    private function makeCacheStale()
    {
        touch($this->cacheFile, time() - 3600);
    }

    private function generateMetaFile()
    {
        file_put_contents($this->metaFile, serialize(array(new FileResource($this->resourceFile))));
    }
}
PK��ZK�OCC>test/Config/Symfony/Component/Config/Tests/FileLocatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests;

use Symfony\Component\Config\FileLocator;

class FileLocatorTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getIsAbsolutePathTests
     */
    public function testIsAbsolutePath($path)
    {
        $loader = new FileLocator(array());
        $r = new \ReflectionObject($loader);
        $m = $r->getMethod('isAbsolutePath');
        $m->setAccessible(true);

        $this->assertTrue($m->invoke($loader, $path), '->isAbsolutePath() returns true for an absolute path');
    }

    public function getIsAbsolutePathTests()
    {
        return array(
            array('/foo.xml'),
            array('c:\\\\foo.xml'),
            array('c:/foo.xml'),
            array('\\server\\foo.xml'),
            array('https://server/foo.xml'),
            array('phar://server/foo.xml'),
        );
    }

    public function testLocate()
    {
        $loader = new FileLocator(__DIR__.'/Fixtures');

        $this->assertEquals(
            __DIR__.DIRECTORY_SEPARATOR.'FileLocatorTest.php',
            $loader->locate('FileLocatorTest.php', __DIR__),
            '->locate() returns the absolute filename if the file exists in the given path'
        );

        $this->assertEquals(
            __DIR__.'/Fixtures'.DIRECTORY_SEPARATOR.'foo.xml',
            $loader->locate('foo.xml', __DIR__),
            '->locate() returns the absolute filename if the file exists in one of the paths given in the constructor'
        );

        $this->assertEquals(
            __DIR__.'/Fixtures'.DIRECTORY_SEPARATOR.'foo.xml',
            $loader->locate(__DIR__.'/Fixtures'.DIRECTORY_SEPARATOR.'foo.xml', __DIR__),
            '->locate() returns the absolute filename if the file exists in one of the paths given in the constructor'
        );

        $loader = new FileLocator(array(__DIR__.'/Fixtures', __DIR__.'/Fixtures/Again'));

        $this->assertEquals(
            array(__DIR__.'/Fixtures'.DIRECTORY_SEPARATOR.'foo.xml', __DIR__.'/Fixtures/Again'.DIRECTORY_SEPARATOR.'foo.xml'),
            $loader->locate('foo.xml', __DIR__, false),
            '->locate() returns an array of absolute filenames'
        );

        $this->assertEquals(
            array(__DIR__.'/Fixtures'.DIRECTORY_SEPARATOR.'foo.xml', __DIR__.'/Fixtures/Again'.DIRECTORY_SEPARATOR.'foo.xml'),
            $loader->locate('foo.xml', __DIR__.'/Fixtures', false),
            '->locate() returns an array of absolute filenames'
        );

        $loader = new FileLocator(__DIR__.'/Fixtures/Again');

        $this->assertEquals(
            array(__DIR__.'/Fixtures'.DIRECTORY_SEPARATOR.'foo.xml', __DIR__.'/Fixtures/Again'.DIRECTORY_SEPARATOR.'foo.xml'),
            $loader->locate('foo.xml', __DIR__.'/Fixtures', false),
            '->locate() returns an array of absolute filenames'
        );
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testLocateThrowsAnExceptionIfTheFileDoesNotExists()
    {
        $loader = new FileLocator(array(__DIR__.'/Fixtures'));

        $loader->locate('foobar.xml', __DIR__);
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testLocateThrowsAnExceptionIfTheFileDoesNotExistsInAbsolutePath()
    {
        $loader = new FileLocator(array(__DIR__.'/Fixtures'));

        $loader->locate(__DIR__.'/Fixtures/foobar.xml', __DIR__);
    }
}
PK��ZL��{Dtest/Config/Symfony/Component/Config/Tests/Loader/FileLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Loader;

use Symfony\Component\Config\Loader\FileLoader;
use Symfony\Component\Config\Loader\LoaderResolver;
use Symfony\Component\Config\Exception\FileLoaderImportCircularReferenceException;

class FileLoaderTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Symfony\Component\Config\Loader\FileLoader
     */
    public function testImportWithFileLocatorDelegation()
    {
        $locatorMock = $this->getMock('Symfony\Component\Config\FileLocatorInterface');

        $locatorMockForAdditionalLoader = $this->getMock('Symfony\Component\Config\FileLocatorInterface');
        $locatorMockForAdditionalLoader->expects($this->any())->method('locate')->will($this->onConsecutiveCalls(
                array('path/to/file1'),                    // Default
                array('path/to/file1', 'path/to/file2'),   // First is imported
                array('path/to/file1', 'path/to/file2'),   // Second is imported
                array('path/to/file1'),                    // Exception
                array('path/to/file1', 'path/to/file2')    // Exception
                ));

        $fileLoader = new TestFileLoader($locatorMock);
        $fileLoader->setSupports(false);
        $fileLoader->setCurrentDir('.');

        $additionalLoader = new TestFileLoader($locatorMockForAdditionalLoader);
        $additionalLoader->setCurrentDir('.');

        $fileLoader->setResolver($loaderResolver = new LoaderResolver(array($fileLoader, $additionalLoader)));

        // Default case
        $this->assertSame('path/to/file1', $fileLoader->import('my_resource'));

        // Check first file is imported if not already loading
        $this->assertSame('path/to/file1', $fileLoader->import('my_resource'));

        // Check second file is imported if first is already loading
        $fileLoader->addLoading('path/to/file1');
        $this->assertSame('path/to/file2', $fileLoader->import('my_resource'));

        // Check exception throws if first (and only available) file is already loading
        try {
            $fileLoader->import('my_resource');
            $this->fail('->import() throws a FileLoaderImportCircularReferenceException if the resource is already loading');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\Component\Config\Exception\FileLoaderImportCircularReferenceException', $e, '->import() throws a FileLoaderImportCircularReferenceException if the resource is already loading');
        }

        // Check exception throws if all files are already loading
        try {
            $fileLoader->addLoading('path/to/file2');
            $fileLoader->import('my_resource');
            $this->fail('->import() throws a FileLoaderImportCircularReferenceException if the resource is already loading');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\Component\Config\Exception\FileLoaderImportCircularReferenceException', $e, '->import() throws a FileLoaderImportCircularReferenceException if the resource is already loading');
        }
    }
}

class TestFileLoader extends FileLoader
{
    private $supports = true;

    public function load($resource, $type = null)
    {
        return $resource;
    }

    public function supports($resource, $type = null)
    {
        return $this->supports;
    }

    public function addLoading($resource)
    {
        self::$loading[$resource] = true;
    }

    public function removeLoading($resource)
    {
        unset(self::$loading[$resource]);
    }

    public function clearLoading()
    {
        self::$loading = array();
    }

    public function setSupports($supports)
    {
        $this->supports = $supports;
    }
}
PK��Z5bc�@@@test/Config/Symfony/Component/Config/Tests/Loader/LoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Loader;

use Symfony\Component\Config\Loader\Loader;

class LoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testGetSetResolver()
    {
        $resolver = $this->getMock('Symfony\Component\Config\Loader\LoaderResolverInterface');

        $loader = new ProjectLoader1();
        $loader->setResolver($resolver);

        $this->assertSame($resolver, $loader->getResolver(), '->setResolver() sets the resolver loader');
    }

    public function testResolve()
    {
        $resolvedLoader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface');

        $resolver = $this->getMock('Symfony\Component\Config\Loader\LoaderResolverInterface');
        $resolver->expects($this->once())
            ->method('resolve')
            ->with('foo.xml')
            ->will($this->returnValue($resolvedLoader));

        $loader = new ProjectLoader1();
        $loader->setResolver($resolver);

        $this->assertSame($loader, $loader->resolve('foo.foo'), '->resolve() finds a loader');
        $this->assertSame($resolvedLoader, $loader->resolve('foo.xml'), '->resolve() finds a loader');
    }

    /**
     * @expectedException \Symfony\Component\Config\Exception\FileLoaderLoadException
     */
    public function testResolveWhenResolverCannotFindLoader()
    {
        $resolver = $this->getMock('Symfony\Component\Config\Loader\LoaderResolverInterface');
        $resolver->expects($this->once())
            ->method('resolve')
            ->with('FOOBAR')
            ->will($this->returnValue(false));

        $loader = new ProjectLoader1();
        $loader->setResolver($resolver);

        $loader->resolve('FOOBAR');
    }

    public function testImport()
    {
        $resolvedLoader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface');
        $resolvedLoader->expects($this->once())
            ->method('load')
            ->with('foo')
            ->will($this->returnValue('yes'));

        $resolver = $this->getMock('Symfony\Component\Config\Loader\LoaderResolverInterface');
        $resolver->expects($this->once())
            ->method('resolve')
            ->with('foo')
            ->will($this->returnValue($resolvedLoader));

        $loader = new ProjectLoader1();
        $loader->setResolver($resolver);

        $this->assertEquals('yes', $loader->import('foo'));
    }

    public function testImportWithType()
    {
        $resolvedLoader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface');
        $resolvedLoader->expects($this->once())
            ->method('load')
            ->with('foo', 'bar')
            ->will($this->returnValue('yes'));

        $resolver = $this->getMock('Symfony\Component\Config\Loader\LoaderResolverInterface');
        $resolver->expects($this->once())
            ->method('resolve')
            ->with('foo', 'bar')
            ->will($this->returnValue($resolvedLoader));

        $loader = new ProjectLoader1();
        $loader->setResolver($resolver);

        $this->assertEquals('yes', $loader->import('foo', 'bar'));
    }
}

class ProjectLoader1 extends Loader
{
    public function load($resource, $type = null)
    {
    }

    public function supports($resource, $type = null)
    {
        return is_string($resource) && 'foo' === pathinfo($resource, PATHINFO_EXTENSION);
    }

    public function getType()
    {
    }
}
PK��Zoq*,��Jtest/Config/Symfony/Component/Config/Tests/Loader/DelegatingLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Loader;

use Symfony\Component\Config\Loader\LoaderResolver;
use Symfony\Component\Config\Loader\DelegatingLoader;

class DelegatingLoaderTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Symfony\Component\Config\Loader\DelegatingLoader::__construct
     */
    public function testConstructor()
    {
        $loader = new DelegatingLoader($resolver = new LoaderResolver());
        $this->assertTrue(true, '__construct() takes a loader resolver as its first argument');
    }

    /**
     * @covers Symfony\Component\Config\Loader\DelegatingLoader::getResolver
     * @covers Symfony\Component\Config\Loader\DelegatingLoader::setResolver
     */
    public function testGetSetResolver()
    {
        $resolver = new LoaderResolver();
        $loader = new DelegatingLoader($resolver);
        $this->assertSame($resolver, $loader->getResolver(), '->getResolver() gets the resolver loader');
        $loader->setResolver($resolver = new LoaderResolver());
        $this->assertSame($resolver, $loader->getResolver(), '->setResolver() sets the resolver loader');
    }

    /**
     * @covers Symfony\Component\Config\Loader\DelegatingLoader::supports
     */
    public function testSupports()
    {
        $loader1 = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface');
        $loader1->expects($this->once())->method('supports')->will($this->returnValue(true));
        $loader = new DelegatingLoader(new LoaderResolver(array($loader1)));
        $this->assertTrue($loader->supports('foo.xml'), '->supports() returns true if the resource is loadable');

        $loader1 = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface');
        $loader1->expects($this->once())->method('supports')->will($this->returnValue(false));
        $loader = new DelegatingLoader(new LoaderResolver(array($loader1)));
        $this->assertFalse($loader->supports('foo.foo'), '->supports() returns false if the resource is not loadable');
    }

    /**
     * @covers Symfony\Component\Config\Loader\DelegatingLoader::load
     */
    public function testLoad()
    {
        $loader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface');
        $loader->expects($this->once())->method('supports')->will($this->returnValue(true));
        $loader->expects($this->once())->method('load');
        $resolver = new LoaderResolver(array($loader));
        $loader = new DelegatingLoader($resolver);

        $loader->load('foo');
    }

    /**
     * @expectedException \Symfony\Component\Config\Exception\FileLoaderLoadException
     */
    public function testLoadThrowsAnExceptionIfTheResourceCannotBeLoaded()
    {
        $loader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface');
        $loader->expects($this->once())->method('supports')->will($this->returnValue(false));
        $resolver = new LoaderResolver(array($loader));
        $loader = new DelegatingLoader($resolver);

        $loader->load('foo');
    }
}
PK��Z�YHtest/Config/Symfony/Component/Config/Tests/Loader/LoaderResolverTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Loader;

use Symfony\Component\Config\Loader\LoaderResolver;

class LoaderResolverTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Symfony\Component\Config\Loader\LoaderResolver::__construct
     */
    public function testConstructor()
    {
        $resolver = new LoaderResolver(array(
            $loader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface'),
        ));

        $this->assertEquals(array($loader), $resolver->getLoaders(), '__construct() takes an array of loaders as its first argument');
    }

    /**
     * @covers Symfony\Component\Config\Loader\LoaderResolver::resolve
     */
    public function testResolve()
    {
        $loader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface');
        $resolver = new LoaderResolver(array($loader));
        $this->assertFalse($resolver->resolve('foo.foo'), '->resolve() returns false if no loader is able to load the resource');

        $loader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface');
        $loader->expects($this->once())->method('supports')->will($this->returnValue(true));
        $resolver = new LoaderResolver(array($loader));
        $this->assertEquals($loader, $resolver->resolve(function () {}), '->resolve() returns the loader for the given resource');
    }

    /**
     * @covers Symfony\Component\Config\Loader\LoaderResolver::getLoaders
     * @covers Symfony\Component\Config\Loader\LoaderResolver::addLoader
     */
    public function testLoaders()
    {
        $resolver = new LoaderResolver();
        $resolver->addLoader($loader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface'));

        $this->assertEquals(array($loader), $resolver->getLoaders(), 'addLoader() adds a loader');
    }
}
PK��Z�Y�hh5test/Config/Symfony/Component/Config/phpunit.xml.distnu�[���<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony Config Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./Resources</directory>
                <directory>./Tests</directory>
                <directory>./vendor</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
PK��Z����$test/Net_Sieve/tests/largescript.sivnu�[���require ["fileinto", "reject", "vacation", "regex", "relational", "comparator-i;ascii-numeric"];
if header :is ["X-Spam-Flag", "X-Spam-Status"] ["YES","Yes"] {
fileinto "INBOX.Spam";
stop;
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["cvs-all.freebsd.org"] {
fileinto "INBOX.FreeBSD.CVS All";
}
if header :contains ["List-Id"] ["freebsd-acpi.freebsd.org"] {
fileinto "INBOX.FreeBSD.ACPI";
}
if header :contains ["List-Id"] ["freebsd-current.freebsd.org"] {
fileinto "INBOX.FreeBSD.Current";
}
if header :contains ["List-Id"] ["freebsd-hackers.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hackers";
}
if header :contains ["List-Id"] ["freebsd-multimedia.freebsd.org"] {
fileinto "INBOX.FreeBSD.Multimedia";
}
if header :contains ["List-Id"] ["freebsd-questions.freebsd.org"] {
fileinto "INBOX.FreeBSD.Questions";
}
if header :contains ["List-Id"] ["freebsd-stable.freebsd.org"] {
fileinto "INBOX.FreeBSD.Stable";
}
if header :contains ["List-Id"] ["freebsd-mobile.freebsd.org"] {
fileinto "INBOX.FreeBSD.Mobile";
}
if header :contains ["List-Id"] ["wine-devel.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Devel";
}
if header :contains ["List-Id"] ["wine-users.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Users";
}
if header :contains ["List-Id"] ["dri-devel.lists.sourceforge.net"] {
fileinto "INBOX.FreeBSD.dri-devel";
}
if header :contains ["List-Id"] ["freebsd-threads.freebsd.org"] {
fileinto "INBOX.FreeBSD.Threads";
}
if header :contains ["List-Id"] ["freebsd-hardware.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hardware";
}
if header :contains ["List-Id"] ["freebsd-usb.freebsd.org"] {
fileinto "INBOX.FreeBSD.USB";
}
if header :contains ["List-Id"] ["freebsd-ports.freebsd.org"] {
fileinto "INBOX.FreeBSD.Ports";
}
if header :contains ["To"] ["amistry@php.net"] {
fileinto "INBOX.PEAR.Account";
}
if header :contains ["list-post"] ["pear-qa@lists.php.net"] {
fileinto "INBOX.PEAR.QA";
}
if header :contains ["Delivered-To"] ["php-general@lists.php.net"] {
fileinto "INBOX.PHP.General";
}
if header :contains ["Delivered-to"] ["internals@lists.php.net"] {
fileinto "INBOX.PEAR.Internals";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["cvs-all.freebsd.org"] {
fileinto "INBOX.FreeBSD.CVS All";
}
if header :contains ["List-Id"] ["freebsd-acpi.freebsd.org"] {
fileinto "INBOX.FreeBSD.ACPI";
}
if header :contains ["List-Id"] ["freebsd-current.freebsd.org"] {
fileinto "INBOX.FreeBSD.Current";
}
if header :contains ["List-Id"] ["freebsd-hackers.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hackers";
}
if header :contains ["List-Id"] ["freebsd-multimedia.freebsd.org"] {
fileinto "INBOX.FreeBSD.Multimedia";
}
if header :contains ["List-Id"] ["freebsd-questions.freebsd.org"] {
fileinto "INBOX.FreeBSD.Questions";
}
if header :contains ["List-Id"] ["freebsd-stable.freebsd.org"] {
fileinto "INBOX.FreeBSD.Stable";
}
if header :contains ["List-Id"] ["freebsd-mobile.freebsd.org"] {
fileinto "INBOX.FreeBSD.Mobile";
}
if header :contains ["List-Id"] ["wine-devel.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Devel";
}
if header :contains ["List-Id"] ["wine-users.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Users";
}
if header :contains ["List-Id"] ["dri-devel.lists.sourceforge.net"] {
fileinto "INBOX.FreeBSD.dri-devel";
}
if header :contains ["List-Id"] ["freebsd-threads.freebsd.org"] {
fileinto "INBOX.FreeBSD.Threads";
}
if header :contains ["List-Id"] ["freebsd-hardware.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hardware";
}
if header :contains ["List-Id"] ["freebsd-usb.freebsd.org"] {
fileinto "INBOX.FreeBSD.USB";
}
if header :contains ["List-Id"] ["freebsd-ports.freebsd.org"] {
fileinto "INBOX.FreeBSD.Ports";
}
if header :contains ["To"] ["amistry@php.net"] {
fileinto "INBOX.PEAR.Account";
}
if header :contains ["list-post"] ["pear-qa@lists.php.net"] {
fileinto "INBOX.PEAR.QA";
}
if header :contains ["Delivered-To"] ["php-general@lists.php.net"] {
fileinto "INBOX.PHP.General";
}
if header :contains ["Delivered-to"] ["internals@lists.php.net"] {
fileinto "INBOX.PEAR.Internals";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["cvs-all.freebsd.org"] {
fileinto "INBOX.FreeBSD.CVS All";
}
if header :contains ["List-Id"] ["freebsd-acpi.freebsd.org"] {
fileinto "INBOX.FreeBSD.ACPI";
}
if header :contains ["List-Id"] ["freebsd-current.freebsd.org"] {
fileinto "INBOX.FreeBSD.Current";
}
if header :contains ["List-Id"] ["freebsd-hackers.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hackers";
}
if header :contains ["List-Id"] ["freebsd-multimedia.freebsd.org"] {
fileinto "INBOX.FreeBSD.Multimedia";
}
if header :contains ["List-Id"] ["freebsd-questions.freebsd.org"] {
fileinto "INBOX.FreeBSD.Questions";
}
if header :contains ["List-Id"] ["freebsd-stable.freebsd.org"] {
fileinto "INBOX.FreeBSD.Stable";
}
if header :contains ["List-Id"] ["freebsd-mobile.freebsd.org"] {
fileinto "INBOX.FreeBSD.Mobile";
}
if header :contains ["List-Id"] ["wine-devel.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Devel";
}
if header :contains ["List-Id"] ["wine-users.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Users";
}
if header :contains ["List-Id"] ["dri-devel.lists.sourceforge.net"] {
fileinto "INBOX.FreeBSD.dri-devel";
}
if header :contains ["List-Id"] ["freebsd-threads.freebsd.org"] {
fileinto "INBOX.FreeBSD.Threads";
}
if header :contains ["List-Id"] ["freebsd-hardware.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hardware";
}
if header :contains ["List-Id"] ["freebsd-usb.freebsd.org"] {
fileinto "INBOX.FreeBSD.USB";
}
if header :contains ["List-Id"] ["freebsd-ports.freebsd.org"] {
fileinto "INBOX.FreeBSD.Ports";
}
if header :contains ["To"] ["amistry@php.net"] {
fileinto "INBOX.PEAR.Account";
}
if header :contains ["list-post"] ["pear-qa@lists.php.net"] {
fileinto "INBOX.PEAR.QA";
}
if header :contains ["Delivered-To"] ["php-general@lists.php.net"] {
fileinto "INBOX.PHP.General";
}
if header :contains ["Delivered-to"] ["internals@lists.php.net"] {
fileinto "INBOX.PEAR.Internals";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["cvs-all.freebsd.org"] {
fileinto "INBOX.FreeBSD.CVS All";
}
if header :contains ["List-Id"] ["freebsd-acpi.freebsd.org"] {
fileinto "INBOX.FreeBSD.ACPI";
}
if header :contains ["List-Id"] ["freebsd-current.freebsd.org"] {
fileinto "INBOX.FreeBSD.Current";
}
if header :contains ["List-Id"] ["freebsd-hackers.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hackers";
}
if header :contains ["List-Id"] ["freebsd-multimedia.freebsd.org"] {
fileinto "INBOX.FreeBSD.Multimedia";
}
if header :contains ["List-Id"] ["freebsd-questions.freebsd.org"] {
fileinto "INBOX.FreeBSD.Questions";
}
if header :contains ["List-Id"] ["freebsd-stable.freebsd.org"] {
fileinto "INBOX.FreeBSD.Stable";
}
if header :contains ["List-Id"] ["freebsd-mobile.freebsd.org"] {
fileinto "INBOX.FreeBSD.Mobile";
}
if header :contains ["List-Id"] ["wine-devel.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Devel";
}
if header :contains ["List-Id"] ["wine-users.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Users";
}
if header :contains ["List-Id"] ["dri-devel.lists.sourceforge.net"] {
fileinto "INBOX.FreeBSD.dri-devel";
}
if header :contains ["List-Id"] ["freebsd-threads.freebsd.org"] {
fileinto "INBOX.FreeBSD.Threads";
}
if header :contains ["List-Id"] ["freebsd-hardware.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hardware";
}
if header :contains ["List-Id"] ["freebsd-usb.freebsd.org"] {
fileinto "INBOX.FreeBSD.USB";
}
if header :contains ["List-Id"] ["freebsd-ports.freebsd.org"] {
fileinto "INBOX.FreeBSD.Ports";
}
if header :contains ["To"] ["amistry@php.net"] {
fileinto "INBOX.PEAR.Account";
}
if header :contains ["list-post"] ["pear-qa@lists.php.net"] {
fileinto "INBOX.PEAR.QA";
}
if header :contains ["Delivered-To"] ["php-general@lists.php.net"] {
fileinto "INBOX.PHP.General";
}
if header :contains ["Delivered-to"] ["internals@lists.php.net"] {
fileinto "INBOX.PEAR.Internals";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["cvs-all.freebsd.org"] {
fileinto "INBOX.FreeBSD.CVS All";
}
if header :contains ["List-Id"] ["freebsd-acpi.freebsd.org"] {
fileinto "INBOX.FreeBSD.ACPI";
}
if header :contains ["List-Id"] ["freebsd-current.freebsd.org"] {
fileinto "INBOX.FreeBSD.Current";
}
if header :contains ["List-Id"] ["freebsd-hackers.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hackers";
}
if header :contains ["List-Id"] ["freebsd-multimedia.freebsd.org"] {
fileinto "INBOX.FreeBSD.Multimedia";
}
if header :contains ["List-Id"] ["freebsd-questions.freebsd.org"] {
fileinto "INBOX.FreeBSD.Questions";
}
if header :contains ["List-Id"] ["freebsd-stable.freebsd.org"] {
fileinto "INBOX.FreeBSD.Stable";
}
if header :contains ["List-Id"] ["freebsd-mobile.freebsd.org"] {
fileinto "INBOX.FreeBSD.Mobile";
}
if header :contains ["List-Id"] ["wine-devel.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Devel";
}
if header :contains ["List-Id"] ["wine-users.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Users";
}
if header :contains ["List-Id"] ["dri-devel.lists.sourceforge.net"] {
fileinto "INBOX.FreeBSD.dri-devel";
}
if header :contains ["List-Id"] ["freebsd-threads.freebsd.org"] {
fileinto "INBOX.FreeBSD.Threads";
}
if header :contains ["List-Id"] ["freebsd-hardware.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hardware";
}
if header :contains ["List-Id"] ["freebsd-usb.freebsd.org"] {
fileinto "INBOX.FreeBSD.USB";
}
if header :contains ["List-Id"] ["freebsd-ports.freebsd.org"] {
fileinto "INBOX.FreeBSD.Ports";
}
if header :contains ["To"] ["amistry@php.net"] {
fileinto "INBOX.PEAR.Account";
}
if header :contains ["list-post"] ["pear-qa@lists.php.net"] {
fileinto "INBOX.PEAR.QA";
}
if header :contains ["Delivered-To"] ["php-general@lists.php.net"] {
fileinto "INBOX.PHP.General";
}
if header :contains ["Delivered-to"] ["internals@lists.php.net"] {
fileinto "INBOX.PEAR.Internals";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["cvs-all.freebsd.org"] {
fileinto "INBOX.FreeBSD.CVS All";
}
if header :contains ["List-Id"] ["freebsd-acpi.freebsd.org"] {
fileinto "INBOX.FreeBSD.ACPI";
}
if header :contains ["List-Id"] ["freebsd-current.freebsd.org"] {
fileinto "INBOX.FreeBSD.Current";
}
if header :contains ["List-Id"] ["freebsd-hackers.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hackers";
}
if header :contains ["List-Id"] ["freebsd-multimedia.freebsd.org"] {
fileinto "INBOX.FreeBSD.Multimedia";
}
if header :contains ["List-Id"] ["freebsd-questions.freebsd.org"] {
fileinto "INBOX.FreeBSD.Questions";
}
if header :contains ["List-Id"] ["freebsd-stable.freebsd.org"] {
fileinto "INBOX.FreeBSD.Stable";
}
if header :contains ["List-Id"] ["freebsd-mobile.freebsd.org"] {
fileinto "INBOX.FreeBSD.Mobile";
}
if header :contains ["List-Id"] ["wine-devel.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Devel";
}
if header :contains ["List-Id"] ["wine-users.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Users";
}
if header :contains ["List-Id"] ["dri-devel.lists.sourceforge.net"] {
fileinto "INBOX.FreeBSD.dri-devel";
}
if header :contains ["List-Id"] ["freebsd-threads.freebsd.org"] {
fileinto "INBOX.FreeBSD.Threads";
}
if header :contains ["List-Id"] ["freebsd-hardware.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hardware";
}
if header :contains ["List-Id"] ["freebsd-usb.freebsd.org"] {
fileinto "INBOX.FreeBSD.USB";
}
if header :contains ["List-Id"] ["freebsd-ports.freebsd.org"] {
fileinto "INBOX.FreeBSD.Ports";
}
if header :contains ["To"] ["amistry@php.net"] {
fileinto "INBOX.PEAR.Account";
}
if header :contains ["list-post"] ["pear-qa@lists.php.net"] {
fileinto "INBOX.PEAR.QA";
}
if header :contains ["Delivered-To"] ["php-general@lists.php.net"] {
fileinto "INBOX.PHP.General";
}
if header :contains ["Delivered-to"] ["internals@lists.php.net"] {
fileinto "INBOX.PEAR.Internals";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["cvs-all.freebsd.org"] {
fileinto "INBOX.FreeBSD.CVS All";
}
if header :contains ["List-Id"] ["freebsd-acpi.freebsd.org"] {
fileinto "INBOX.FreeBSD.ACPI";
}
if header :contains ["List-Id"] ["freebsd-current.freebsd.org"] {
fileinto "INBOX.FreeBSD.Current";
}
if header :contains ["List-Id"] ["freebsd-hackers.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hackers";
}
if header :contains ["List-Id"] ["freebsd-multimedia.freebsd.org"] {
fileinto "INBOX.FreeBSD.Multimedia";
}
if header :contains ["List-Id"] ["freebsd-questions.freebsd.org"] {
fileinto "INBOX.FreeBSD.Questions";
}
if header :contains ["List-Id"] ["freebsd-stable.freebsd.org"] {
fileinto "INBOX.FreeBSD.Stable";
}
if header :contains ["List-Id"] ["freebsd-mobile.freebsd.org"] {
fileinto "INBOX.FreeBSD.Mobile";
}
if header :contains ["List-Id"] ["wine-devel.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Devel";
}
if header :contains ["List-Id"] ["wine-users.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Users";
}
if header :contains ["List-Id"] ["dri-devel.lists.sourceforge.net"] {
fileinto "INBOX.FreeBSD.dri-devel";
}
if header :contains ["List-Id"] ["freebsd-threads.freebsd.org"] {
fileinto "INBOX.FreeBSD.Threads";
}
if header :contains ["List-Id"] ["freebsd-hardware.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hardware";
}
if header :contains ["List-Id"] ["freebsd-usb.freebsd.org"] {
fileinto "INBOX.FreeBSD.USB";
}
if header :contains ["List-Id"] ["freebsd-ports.freebsd.org"] {
fileinto "INBOX.FreeBSD.Ports";
}
if header :contains ["To"] ["amistry@php.net"] {
fileinto "INBOX.PEAR.Account";
}
if header :contains ["list-post"] ["pear-qa@lists.php.net"] {
fileinto "INBOX.PEAR.QA";
}
if header :contains ["Delivered-To"] ["php-general@lists.php.net"] {
fileinto "INBOX.PHP.General";
}
if header :contains ["Delivered-to"] ["internals@lists.php.net"] {
fileinto "INBOX.PEAR.Internals";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["cvs-all.freebsd.org"] {
fileinto "INBOX.FreeBSD.CVS All";
}
if header :contains ["List-Id"] ["freebsd-acpi.freebsd.org"] {
fileinto "INBOX.FreeBSD.ACPI";
}
if header :contains ["List-Id"] ["freebsd-current.freebsd.org"] {
fileinto "INBOX.FreeBSD.Current";
}
if header :contains ["List-Id"] ["freebsd-hackers.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hackers";
}
if header :contains ["List-Id"] ["freebsd-multimedia.freebsd.org"] {
fileinto "INBOX.FreeBSD.Multimedia";
}
if header :contains ["List-Id"] ["freebsd-questions.freebsd.org"] {
fileinto "INBOX.FreeBSD.Questions";
}
if header :contains ["List-Id"] ["freebsd-stable.freebsd.org"] {
fileinto "INBOX.FreeBSD.Stable";
}
if header :contains ["List-Id"] ["freebsd-mobile.freebsd.org"] {
fileinto "INBOX.FreeBSD.Mobile";
}
if header :contains ["List-Id"] ["wine-devel.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Devel";
}
if header :contains ["List-Id"] ["wine-users.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Users";
}
if header :contains ["List-Id"] ["dri-devel.lists.sourceforge.net"] {
fileinto "INBOX.FreeBSD.dri-devel";
}
if header :contains ["List-Id"] ["freebsd-threads.freebsd.org"] {
fileinto "INBOX.FreeBSD.Threads";
}
if header :contains ["List-Id"] ["freebsd-hardware.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hardware";
}
if header :contains ["List-Id"] ["freebsd-usb.freebsd.org"] {
fileinto "INBOX.FreeBSD.USB";
}
if header :contains ["List-Id"] ["freebsd-ports.freebsd.org"] {
fileinto "INBOX.FreeBSD.Ports";
}
if header :contains ["To"] ["amistry@php.net"] {
fileinto "INBOX.PEAR.Account";
}
if header :contains ["list-post"] ["pear-qa@lists.php.net"] {
fileinto "INBOX.PEAR.QA";
}
if header :contains ["Delivered-To"] ["php-general@lists.php.net"] {
fileinto "INBOX.PHP.General";
}
if header :contains ["Delivered-to"] ["internals@lists.php.net"] {
fileinto "INBOX.PEAR.Internals";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["cvs-all.freebsd.org"] {
fileinto "INBOX.FreeBSD.CVS All";
}
if header :contains ["List-Id"] ["freebsd-acpi.freebsd.org"] {
fileinto "INBOX.FreeBSD.ACPI";
}
if header :contains ["List-Id"] ["freebsd-current.freebsd.org"] {
fileinto "INBOX.FreeBSD.Current";
}
if header :contains ["List-Id"] ["freebsd-hackers.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hackers";
}
if header :contains ["List-Id"] ["freebsd-multimedia.freebsd.org"] {
fileinto "INBOX.FreeBSD.Multimedia";
}
if header :contains ["List-Id"] ["freebsd-questions.freebsd.org"] {
fileinto "INBOX.FreeBSD.Questions";
}
if header :contains ["List-Id"] ["freebsd-stable.freebsd.org"] {
fileinto "INBOX.FreeBSD.Stable";
}
if header :contains ["List-Id"] ["freebsd-mobile.freebsd.org"] {
fileinto "INBOX.FreeBSD.Mobile";
}
if header :contains ["List-Id"] ["wine-devel.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Devel";
}
if header :contains ["List-Id"] ["wine-users.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Users";
}
if header :contains ["List-Id"] ["dri-devel.lists.sourceforge.net"] {
fileinto "INBOX.FreeBSD.dri-devel";
}
if header :contains ["List-Id"] ["freebsd-threads.freebsd.org"] {
fileinto "INBOX.FreeBSD.Threads";
}
if header :contains ["List-Id"] ["freebsd-hardware.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hardware";
}
if header :contains ["List-Id"] ["freebsd-usb.freebsd.org"] {
fileinto "INBOX.FreeBSD.USB";
}
if header :contains ["List-Id"] ["freebsd-ports.freebsd.org"] {
fileinto "INBOX.FreeBSD.Ports";
}
if header :contains ["To"] ["amistry@php.net"] {
fileinto "INBOX.PEAR.Account";
}
if header :contains ["list-post"] ["pear-qa@lists.php.net"] {
fileinto "INBOX.PEAR.QA";
}
if header :contains ["Delivered-To"] ["php-general@lists.php.net"] {
fileinto "INBOX.PHP.General";
}
if header :contains ["Delivered-to"] ["internals@lists.php.net"] {
fileinto "INBOX.PEAR.Internals";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["cvs-all.freebsd.org"] {
fileinto "INBOX.FreeBSD.CVS All";
}
if header :contains ["List-Id"] ["freebsd-acpi.freebsd.org"] {
fileinto "INBOX.FreeBSD.ACPI";
}
if header :contains ["List-Id"] ["freebsd-current.freebsd.org"] {
fileinto "INBOX.FreeBSD.Current";
}
if header :contains ["List-Id"] ["freebsd-hackers.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hackers";
}
if header :contains ["List-Id"] ["freebsd-multimedia.freebsd.org"] {
fileinto "INBOX.FreeBSD.Multimedia";
}
if header :contains ["List-Id"] ["freebsd-questions.freebsd.org"] {
fileinto "INBOX.FreeBSD.Questions";
}
if header :contains ["List-Id"] ["freebsd-stable.freebsd.org"] {
fileinto "INBOX.FreeBSD.Stable";
}
if header :contains ["List-Id"] ["freebsd-mobile.freebsd.org"] {
fileinto "INBOX.FreeBSD.Mobile";
}
if header :contains ["List-Id"] ["wine-devel.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Devel";
}
if header :contains ["List-Id"] ["wine-users.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Users";
}
if header :contains ["List-Id"] ["dri-devel.lists.sourceforge.net"] {
fileinto "INBOX.FreeBSD.dri-devel";
}
if header :contains ["List-Id"] ["freebsd-threads.freebsd.org"] {
fileinto "INBOX.FreeBSD.Threads";
}
if header :contains ["List-Id"] ["freebsd-hardware.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hardware";
}
if header :contains ["List-Id"] ["freebsd-usb.freebsd.org"] {
fileinto "INBOX.FreeBSD.USB";
}
if header :contains ["List-Id"] ["freebsd-ports.freebsd.org"] {
fileinto "INBOX.FreeBSD.Ports";
}
if header :contains ["To"] ["amistry@php.net"] {
fileinto "INBOX.PEAR.Account";
}
if header :contains ["list-post"] ["pear-qa@lists.php.net"] {
fileinto "INBOX.PEAR.QA";
}
if header :contains ["Delivered-To"] ["php-general@lists.php.net"] {
fileinto "INBOX.PHP.General";
}
if header :contains ["Delivered-to"] ["internals@lists.php.net"] {
fileinto "INBOX.PEAR.Internals";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["cvs-all.freebsd.org"] {
fileinto "INBOX.FreeBSD.CVS All";
}
if header :contains ["List-Id"] ["freebsd-acpi.freebsd.org"] {
fileinto "INBOX.FreeBSD.ACPI";
}
if header :contains ["List-Id"] ["freebsd-current.freebsd.org"] {
fileinto "INBOX.FreeBSD.Current";
}
if header :contains ["List-Id"] ["freebsd-hackers.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hackers";
}
if header :contains ["List-Id"] ["freebsd-multimedia.freebsd.org"] {
fileinto "INBOX.FreeBSD.Multimedia";
}
if header :contains ["List-Id"] ["freebsd-questions.freebsd.org"] {
fileinto "INBOX.FreeBSD.Questions";
}
if header :contains ["List-Id"] ["freebsd-stable.freebsd.org"] {
fileinto "INBOX.FreeBSD.Stable";
}
if header :contains ["List-Id"] ["freebsd-mobile.freebsd.org"] {
fileinto "INBOX.FreeBSD.Mobile";
}
if header :contains ["List-Id"] ["wine-devel.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Devel";
}
if header :contains ["List-Id"] ["wine-users.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Users";
}
if header :contains ["List-Id"] ["dri-devel.lists.sourceforge.net"] {
fileinto "INBOX.FreeBSD.dri-devel";
}
if header :contains ["List-Id"] ["freebsd-threads.freebsd.org"] {
fileinto "INBOX.FreeBSD.Threads";
}
if header :contains ["List-Id"] ["freebsd-hardware.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hardware";
}
if header :contains ["List-Id"] ["freebsd-usb.freebsd.org"] {
fileinto "INBOX.FreeBSD.USB";
}
if header :contains ["List-Id"] ["freebsd-ports.freebsd.org"] {
fileinto "INBOX.FreeBSD.Ports";
}
if header :contains ["To"] ["amistry@php.net"] {
fileinto "INBOX.PEAR.Account";
}
if header :contains ["list-post"] ["pear-qa@lists.php.net"] {
fileinto "INBOX.PEAR.QA";
}
if header :contains ["Delivered-To"] ["php-general@lists.php.net"] {
fileinto "INBOX.PHP.General";
}
if header :contains ["Delivered-to"] ["internals@lists.php.net"] {
fileinto "INBOX.PEAR.Internals";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["cvs-all.freebsd.org"] {
fileinto "INBOX.FreeBSD.CVS All";
}
if header :contains ["List-Id"] ["freebsd-acpi.freebsd.org"] {
fileinto "INBOX.FreeBSD.ACPI";
}
if header :contains ["List-Id"] ["freebsd-current.freebsd.org"] {
fileinto "INBOX.FreeBSD.Current";
}
if header :contains ["List-Id"] ["freebsd-hackers.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hackers";
}
if header :contains ["List-Id"] ["freebsd-multimedia.freebsd.org"] {
fileinto "INBOX.FreeBSD.Multimedia";
}
if header :contains ["List-Id"] ["freebsd-questions.freebsd.org"] {
fileinto "INBOX.FreeBSD.Questions";
}
if header :contains ["List-Id"] ["freebsd-stable.freebsd.org"] {
fileinto "INBOX.FreeBSD.Stable";
}
if header :contains ["List-Id"] ["freebsd-mobile.freebsd.org"] {
fileinto "INBOX.FreeBSD.Mobile";
}
if header :contains ["List-Id"] ["wine-devel.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Devel";
}
if header :contains ["List-Id"] ["wine-users.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Users";
}
if header :contains ["List-Id"] ["dri-devel.lists.sourceforge.net"] {
fileinto "INBOX.FreeBSD.dri-devel";
}
if header :contains ["List-Id"] ["freebsd-threads.freebsd.org"] {
fileinto "INBOX.FreeBSD.Threads";
}
if header :contains ["List-Id"] ["freebsd-hardware.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hardware";
}
if header :contains ["List-Id"] ["freebsd-usb.freebsd.org"] {
fileinto "INBOX.FreeBSD.USB";
}
if header :contains ["List-Id"] ["freebsd-ports.freebsd.org"] {
fileinto "INBOX.FreeBSD.Ports";
}
if header :contains ["To"] ["amistry@php.net"] {
fileinto "INBOX.PEAR.Account";
}
if header :contains ["list-post"] ["pear-qa@lists.php.net"] {
fileinto "INBOX.PEAR.QA";
}
if header :contains ["Delivered-To"] ["php-general@lists.php.net"] {
fileinto "INBOX.PHP.General";
}
if header :contains ["Delivered-to"] ["internals@lists.php.net"] {
fileinto "INBOX.PEAR.Internals";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["cvs-all.freebsd.org"] {
fileinto "INBOX.FreeBSD.CVS All";
}
if header :contains ["List-Id"] ["freebsd-acpi.freebsd.org"] {
fileinto "INBOX.FreeBSD.ACPI";
}
if header :contains ["List-Id"] ["freebsd-current.freebsd.org"] {
fileinto "INBOX.FreeBSD.Current";
}
if header :contains ["List-Id"] ["freebsd-hackers.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hackers";
}
if header :contains ["List-Id"] ["freebsd-multimedia.freebsd.org"] {
fileinto "INBOX.FreeBSD.Multimedia";
}
if header :contains ["List-Id"] ["freebsd-questions.freebsd.org"] {
fileinto "INBOX.FreeBSD.Questions";
}
if header :contains ["List-Id"] ["freebsd-stable.freebsd.org"] {
fileinto "INBOX.FreeBSD.Stable";
}
if header :contains ["List-Id"] ["freebsd-mobile.freebsd.org"] {
fileinto "INBOX.FreeBSD.Mobile";
}
if header :contains ["List-Id"] ["wine-devel.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Devel";
}
if header :contains ["List-Id"] ["wine-users.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Users";
}
if header :contains ["List-Id"] ["dri-devel.lists.sourceforge.net"] {
fileinto "INBOX.FreeBSD.dri-devel";
}
if header :contains ["List-Id"] ["freebsd-threads.freebsd.org"] {
fileinto "INBOX.FreeBSD.Threads";
}
if header :contains ["List-Id"] ["freebsd-hardware.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hardware";
}
if header :contains ["List-Id"] ["freebsd-usb.freebsd.org"] {
fileinto "INBOX.FreeBSD.USB";
}
if header :contains ["List-Id"] ["freebsd-ports.freebsd.org"] {
fileinto "INBOX.FreeBSD.Ports";
}
if header :contains ["To"] ["amistry@php.net"] {
fileinto "INBOX.PEAR.Account";
}
if header :contains ["list-post"] ["pear-qa@lists.php.net"] {
fileinto "INBOX.PEAR.QA";
}
if header :contains ["Delivered-To"] ["php-general@lists.php.net"] {
fileinto "INBOX.PHP.General";
}
if header :contains ["Delivered-to"] ["internals@lists.php.net"] {
fileinto "INBOX.PEAR.Internals";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["cvs-all.freebsd.org"] {
fileinto "INBOX.FreeBSD.CVS All";
}
if header :contains ["List-Id"] ["freebsd-acpi.freebsd.org"] {
fileinto "INBOX.FreeBSD.ACPI";
}
if header :contains ["List-Id"] ["freebsd-current.freebsd.org"] {
fileinto "INBOX.FreeBSD.Current";
}
if header :contains ["List-Id"] ["freebsd-hackers.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hackers";
}
if header :contains ["List-Id"] ["freebsd-multimedia.freebsd.org"] {
fileinto "INBOX.FreeBSD.Multimedia";
}
if header :contains ["List-Id"] ["freebsd-questions.freebsd.org"] {
fileinto "INBOX.FreeBSD.Questions";
}
if header :contains ["List-Id"] ["freebsd-stable.freebsd.org"] {
fileinto "INBOX.FreeBSD.Stable";
}
if header :contains ["List-Id"] ["freebsd-mobile.freebsd.org"] {
fileinto "INBOX.FreeBSD.Mobile";
}
if header :contains ["List-Id"] ["wine-devel.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Devel";
}
if header :contains ["List-Id"] ["wine-users.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Users";
}
if header :contains ["List-Id"] ["dri-devel.lists.sourceforge.net"] {
fileinto "INBOX.FreeBSD.dri-devel";
}
if header :contains ["List-Id"] ["freebsd-threads.freebsd.org"] {
fileinto "INBOX.FreeBSD.Threads";
}
if header :contains ["List-Id"] ["freebsd-hardware.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hardware";
}
if header :contains ["List-Id"] ["freebsd-usb.freebsd.org"] {
fileinto "INBOX.FreeBSD.USB";
}
if header :contains ["List-Id"] ["freebsd-ports.freebsd.org"] {
fileinto "INBOX.FreeBSD.Ports";
}
if header :contains ["To"] ["amistry@php.net"] {
fileinto "INBOX.PEAR.Account";
}
if header :contains ["list-post"] ["pear-qa@lists.php.net"] {
fileinto "INBOX.PEAR.QA";
}
if header :contains ["Delivered-To"] ["php-general@lists.php.net"] {
fileinto "INBOX.PHP.General";
}
if header :contains ["Delivered-to"] ["internals@lists.php.net"] {
fileinto "INBOX.PEAR.Internals";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["cvs-all.freebsd.org"] {
fileinto "INBOX.FreeBSD.CVS All";
}
if header :contains ["List-Id"] ["freebsd-acpi.freebsd.org"] {
fileinto "INBOX.FreeBSD.ACPI";
}
if header :contains ["List-Id"] ["freebsd-current.freebsd.org"] {
fileinto "INBOX.FreeBSD.Current";
}
if header :contains ["List-Id"] ["freebsd-hackers.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hackers";
}
if header :contains ["List-Id"] ["freebsd-multimedia.freebsd.org"] {
fileinto "INBOX.FreeBSD.Multimedia";
}
if header :contains ["List-Id"] ["freebsd-questions.freebsd.org"] {
fileinto "INBOX.FreeBSD.Questions";
}
if header :contains ["List-Id"] ["freebsd-stable.freebsd.org"] {
fileinto "INBOX.FreeBSD.Stable";
}
if header :contains ["List-Id"] ["freebsd-mobile.freebsd.org"] {
fileinto "INBOX.FreeBSD.Mobile";
}
if header :contains ["List-Id"] ["wine-devel.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Devel";
}
if header :contains ["List-Id"] ["wine-users.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Users";
}
if header :contains ["List-Id"] ["dri-devel.lists.sourceforge.net"] {
fileinto "INBOX.FreeBSD.dri-devel";
}
if header :contains ["List-Id"] ["freebsd-threads.freebsd.org"] {
fileinto "INBOX.FreeBSD.Threads";
}
if header :contains ["List-Id"] ["freebsd-hardware.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hardware";
}
if header :contains ["List-Id"] ["freebsd-usb.freebsd.org"] {
fileinto "INBOX.FreeBSD.USB";
}
if header :contains ["List-Id"] ["freebsd-ports.freebsd.org"] {
fileinto "INBOX.FreeBSD.Ports";
}
if header :contains ["To"] ["amistry@php.net"] {
fileinto "INBOX.PEAR.Account";
}
if header :contains ["list-post"] ["pear-qa@lists.php.net"] {
fileinto "INBOX.PEAR.QA";
}
if header :contains ["Delivered-To"] ["php-general@lists.php.net"] {
fileinto "INBOX.PHP.General";
}
if header :contains ["Delivered-to"] ["internals@lists.php.net"] {
fileinto "INBOX.PEAR.Internals";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["cvs-all.freebsd.org"] {
fileinto "INBOX.FreeBSD.CVS All";
}
if header :contains ["List-Id"] ["freebsd-acpi.freebsd.org"] {
fileinto "INBOX.FreeBSD.ACPI";
}
if header :contains ["List-Id"] ["freebsd-current.freebsd.org"] {
fileinto "INBOX.FreeBSD.Current";
}
if header :contains ["List-Id"] ["freebsd-hackers.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hackers";
}
if header :contains ["List-Id"] ["freebsd-multimedia.freebsd.org"] {
fileinto "INBOX.FreeBSD.Multimedia";
}
if header :contains ["List-Id"] ["freebsd-questions.freebsd.org"] {
fileinto "INBOX.FreeBSD.Questions";
}
if header :contains ["List-Id"] ["freebsd-stable.freebsd.org"] {
fileinto "INBOX.FreeBSD.Stable";
}
if header :contains ["List-Id"] ["freebsd-mobile.freebsd.org"] {
fileinto "INBOX.FreeBSD.Mobile";
}
if header :contains ["List-Id"] ["wine-devel.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Devel";
}
if header :contains ["List-Id"] ["wine-users.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Users";
}
if header :contains ["List-Id"] ["dri-devel.lists.sourceforge.net"] {
fileinto "INBOX.FreeBSD.dri-devel";
}
if header :contains ["List-Id"] ["freebsd-threads.freebsd.org"] {
fileinto "INBOX.FreeBSD.Threads";
}
if header :contains ["List-Id"] ["freebsd-hardware.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hardware";
}
if header :contains ["List-Id"] ["freebsd-usb.freebsd.org"] {
fileinto "INBOX.FreeBSD.USB";
}
if header :contains ["List-Id"] ["freebsd-ports.freebsd.org"] {
fileinto "INBOX.FreeBSD.Ports";
}
if header :contains ["To"] ["amistry@php.net"] {
fileinto "INBOX.PEAR.Account";
}
if header :contains ["list-post"] ["pear-qa@lists.php.net"] {
fileinto "INBOX.PEAR.QA";
}
if header :contains ["Delivered-To"] ["php-general@lists.php.net"] {
fileinto "INBOX.PHP.General";
}
if header :contains ["Delivered-to"] ["internals@lists.php.net"] {
fileinto "INBOX.PEAR.Internals";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["cvs-all.freebsd.org"] {
fileinto "INBOX.FreeBSD.CVS All";
}
if header :contains ["List-Id"] ["freebsd-acpi.freebsd.org"] {
fileinto "INBOX.FreeBSD.ACPI";
}
if header :contains ["List-Id"] ["freebsd-current.freebsd.org"] {
fileinto "INBOX.FreeBSD.Current";
}
if header :contains ["List-Id"] ["freebsd-hackers.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hackers";
}
if header :contains ["List-Id"] ["freebsd-multimedia.freebsd.org"] {
fileinto "INBOX.FreeBSD.Multimedia";
}
if header :contains ["List-Id"] ["freebsd-questions.freebsd.org"] {
fileinto "INBOX.FreeBSD.Questions";
}
if header :contains ["List-Id"] ["freebsd-stable.freebsd.org"] {
fileinto "INBOX.FreeBSD.Stable";
}
if header :contains ["List-Id"] ["freebsd-mobile.freebsd.org"] {
fileinto "INBOX.FreeBSD.Mobile";
}
if header :contains ["List-Id"] ["wine-devel.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Devel";
}
if header :contains ["List-Id"] ["wine-users.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Users";
}
if header :contains ["List-Id"] ["dri-devel.lists.sourceforge.net"] {
fileinto "INBOX.FreeBSD.dri-devel";
}
if header :contains ["List-Id"] ["freebsd-threads.freebsd.org"] {
fileinto "INBOX.FreeBSD.Threads";
}
if header :contains ["List-Id"] ["freebsd-hardware.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hardware";
}
if header :contains ["List-Id"] ["freebsd-usb.freebsd.org"] {
fileinto "INBOX.FreeBSD.USB";
}
if header :contains ["List-Id"] ["freebsd-ports.freebsd.org"] {
fileinto "INBOX.FreeBSD.Ports";
}
if header :contains ["To"] ["amistry@php.net"] {
fileinto "INBOX.PEAR.Account";
}
if header :contains ["list-post"] ["pear-qa@lists.php.net"] {
fileinto "INBOX.PEAR.QA";
}
if header :contains ["Delivered-To"] ["php-general@lists.php.net"] {
fileinto "INBOX.PHP.General";
}
if header :contains ["Delivered-to"] ["internals@lists.php.net"] {
fileinto "INBOX.PEAR.Internals";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["cvs-all.freebsd.org"] {
fileinto "INBOX.FreeBSD.CVS All";
}
if header :contains ["List-Id"] ["freebsd-acpi.freebsd.org"] {
fileinto "INBOX.FreeBSD.ACPI";
}
if header :contains ["List-Id"] ["freebsd-current.freebsd.org"] {
fileinto "INBOX.FreeBSD.Current";
}
if header :contains ["List-Id"] ["freebsd-hackers.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hackers";
}
if header :contains ["List-Id"] ["freebsd-multimedia.freebsd.org"] {
fileinto "INBOX.FreeBSD.Multimedia";
}
if header :contains ["List-Id"] ["freebsd-questions.freebsd.org"] {
fileinto "INBOX.FreeBSD.Questions";
}
if header :contains ["List-Id"] ["freebsd-stable.freebsd.org"] {
fileinto "INBOX.FreeBSD.Stable";
}
if header :contains ["List-Id"] ["freebsd-mobile.freebsd.org"] {
fileinto "INBOX.FreeBSD.Mobile";
}
if header :contains ["List-Id"] ["wine-devel.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Devel";
}
if header :contains ["List-Id"] ["wine-users.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Users";
}
if header :contains ["List-Id"] ["dri-devel.lists.sourceforge.net"] {
fileinto "INBOX.FreeBSD.dri-devel";
}
if header :contains ["List-Id"] ["freebsd-threads.freebsd.org"] {
fileinto "INBOX.FreeBSD.Threads";
}
if header :contains ["List-Id"] ["freebsd-hardware.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hardware";
}
if header :contains ["List-Id"] ["freebsd-usb.freebsd.org"] {
fileinto "INBOX.FreeBSD.USB";
}
if header :contains ["List-Id"] ["freebsd-ports.freebsd.org"] {
fileinto "INBOX.FreeBSD.Ports";
}
if header :contains ["To"] ["amistry@php.net"] {
fileinto "INBOX.PEAR.Account";
}
if header :contains ["list-post"] ["pear-qa@lists.php.net"] {
fileinto "INBOX.PEAR.QA";
}
if header :contains ["Delivered-To"] ["php-general@lists.php.net"] {
fileinto "INBOX.PHP.General";
}
if header :contains ["Delivered-to"] ["internals@lists.php.net"] {
fileinto "INBOX.PEAR.Internals";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["cvs-all.freebsd.org"] {
fileinto "INBOX.FreeBSD.CVS All";
}
if header :contains ["List-Id"] ["freebsd-acpi.freebsd.org"] {
fileinto "INBOX.FreeBSD.ACPI";
}
if header :contains ["List-Id"] ["freebsd-current.freebsd.org"] {
fileinto "INBOX.FreeBSD.Current";
}
if header :contains ["List-Id"] ["freebsd-hackers.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hackers";
}
if header :contains ["List-Id"] ["freebsd-multimedia.freebsd.org"] {
fileinto "INBOX.FreeBSD.Multimedia";
}
if header :contains ["List-Id"] ["freebsd-questions.freebsd.org"] {
fileinto "INBOX.FreeBSD.Questions";
}
if header :contains ["List-Id"] ["freebsd-stable.freebsd.org"] {
fileinto "INBOX.FreeBSD.Stable";
}
if header :contains ["List-Id"] ["freebsd-mobile.freebsd.org"] {
fileinto "INBOX.FreeBSD.Mobile";
}
if header :contains ["List-Id"] ["wine-devel.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Devel";
}
if header :contains ["List-Id"] ["wine-users.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Users";
}
if header :contains ["List-Id"] ["dri-devel.lists.sourceforge.net"] {
fileinto "INBOX.FreeBSD.dri-devel";
}
if header :contains ["List-Id"] ["freebsd-threads.freebsd.org"] {
fileinto "INBOX.FreeBSD.Threads";
}
if header :contains ["List-Id"] ["freebsd-hardware.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hardware";
}
if header :contains ["List-Id"] ["freebsd-usb.freebsd.org"] {
fileinto "INBOX.FreeBSD.USB";
}
if header :contains ["List-Id"] ["freebsd-ports.freebsd.org"] {
fileinto "INBOX.FreeBSD.Ports";
}
if header :contains ["To"] ["amistry@php.net"] {
fileinto "INBOX.PEAR.Account";
}
if header :contains ["list-post"] ["pear-qa@lists.php.net"] {
fileinto "INBOX.PEAR.QA";
}
if header :contains ["Delivered-To"] ["php-general@lists.php.net"] {
fileinto "INBOX.PHP.General";
}
if header :contains ["Delivered-to"] ["internals@lists.php.net"] {
fileinto "INBOX.PEAR.Internals";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["cvs-all.freebsd.org"] {
fileinto "INBOX.FreeBSD.CVS All";
}
if header :contains ["List-Id"] ["freebsd-acpi.freebsd.org"] {
fileinto "INBOX.FreeBSD.ACPI";
}
if header :contains ["List-Id"] ["freebsd-current.freebsd.org"] {
fileinto "INBOX.FreeBSD.Current";
}
if header :contains ["List-Id"] ["freebsd-hackers.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hackers";
}
if header :contains ["List-Id"] ["freebsd-multimedia.freebsd.org"] {
fileinto "INBOX.FreeBSD.Multimedia";
}
if header :contains ["List-Id"] ["freebsd-questions.freebsd.org"] {
fileinto "INBOX.FreeBSD.Questions";
}
if header :contains ["List-Id"] ["freebsd-stable.freebsd.org"] {
fileinto "INBOX.FreeBSD.Stable";
}
if header :contains ["List-Id"] ["freebsd-mobile.freebsd.org"] {
fileinto "INBOX.FreeBSD.Mobile";
}
if header :contains ["List-Id"] ["wine-devel.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Devel";
}
if header :contains ["List-Id"] ["wine-users.winehq.org"] {
fileinto "INBOX.FreeBSD.Wine.Users";
}
if header :contains ["List-Id"] ["dri-devel.lists.sourceforge.net"] {
fileinto "INBOX.FreeBSD.dri-devel";
}
if header :contains ["List-Id"] ["freebsd-threads.freebsd.org"] {
fileinto "INBOX.FreeBSD.Threads";
}
if header :contains ["List-Id"] ["freebsd-hardware.freebsd.org"] {
fileinto "INBOX.FreeBSD.Hardware";
}
if header :contains ["List-Id"] ["freebsd-usb.freebsd.org"] {
fileinto "INBOX.FreeBSD.USB";
}
if header :contains ["List-Id"] ["freebsd-ports.freebsd.org"] {
fileinto "INBOX.FreeBSD.Ports";
}
if header :contains ["To"] ["amistry@php.net"] {
fileinto "INBOX.PEAR.Account";
}
if header :contains ["list-post"] ["pear-qa@lists.php.net"] {
fileinto "INBOX.PEAR.QA";
}
if header :contains ["Delivered-To"] ["php-general@lists.php.net"] {
fileinto "INBOX.PHP.General";
}
if header :contains ["Delivered-to"] ["internals@lists.php.net"] {
fileinto "INBOX.PEAR.Internals";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
if header :contains ["List-Id"] ["suphp.lists.marsching.biz"] {
fileinto "INBOX.suPHP";
}
PK��Z�g��-�-"test/Net_Sieve/tests/SieveTest.phpnu�[���<?php
/**
 * This file contains the PHPUnit test case for Net_Sieve.
 *
 * PHP version 5
 *
 * +-----------------------------------------------------------------------+
 * | All rights reserved.                                                  |
 * |                                                                       |
 * | Redistribution and use in source and binary forms, with or without    |
 * | modification, are permitted provided that the following conditions    |
 * | are met:                                                              |
 * |                                                                       |
 * | o Redistributions of source code must retain the above copyright      |
 * |   notice, this list of conditions and the following disclaimer.       |
 * | o Redistributions in binary form must reproduce the above copyright   |
 * |   notice, this list of conditions and the following disclaimer in the |
 * |   documentation and/or other materials provided with the distribution.|
 * |                                                                       |
 * | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   |
 * | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     |
 * | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
 * | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  |
 * | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
 * | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      |
 * | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
 * | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
 * | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   |
 * | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
 * | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  |
 * +-----------------------------------------------------------------------+
 *
 * @category  Networking
 * @package   Net_Sieve
 * @author    Anish Mistry <amistry@am-productions.biz>
 * @copyright 2006 Anish Mistry
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD
 * @version   SVN: $Id$
 * @link      http://pear.php.net/package/Net_Sieve
 */

require_once dirname(__FILE__) . '/../Sieve.php';

/**
 * PHPUnit test case for Net_Sieve.
 *
 * @category  Networking
 * @package   Net_Sieve
 * @author    Anish Mistry <amistry@am-productions.biz>
 * @copyright 2006 Anish Mistry
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/Net_Sieve
 */
class SieveTest extends PHPUnit\Framework\TestCase
{
    // contains the object handle of the string class
    protected $fixture;

    protected function setUp()
    {
        if (!file_exists(dirname(__FILE__) . '/config.php')) {
            $this->markTestSkipped('Test configuration incomplete. Copy config.php.dist to config.php.');
        }
        require_once dirname(__FILE__) . '/config.php';

        // Create a new instance of Net_Sieve.
        $this->_pear = new PEAR();
        $this->fixture = new Net_Sieve();
        $this->scripts = array(
            'test script1' => "require \"fileinto\";\r\nif header :contains \"From\" \"@cnba.uba.ar\" \r\n{fileinto \"INBOX.Test1\";}\r\nelse \r\n{fileinto \"INBOX\";}",
            'test script2' => "require \"fileinto\";\r\nif header :contains \"From\" \"@cnba.uba.ar\" \r\n{fileinto \"INBOX.Test\";}\r\nelse \r\n{fileinto \"INBOX\";}",
            'test"scriptäöü3' => "require \"vacation\";\nvacation\n:days 7\n:addresses [\"matthew@de-construct.com\"]\n:subject \"This is a test\"\n\"I'm on my holiday!\nsadfafs\";",
            'test script4' => file_get_contents(dirname(__FILE__) . '/largescript.siv'));
    }
    
    protected function tearDown()
    {
        // Delete the instance.
        unset($this->fixture);
    }
    
    protected function login()
    {
        $result = $this->fixture->connect(HOST, PORT);
        $this->assertTrue($this->check($result), 'Can not connect');
        $result = $this->fixture->login(USERNAME, PASSWORD, null, '', false);
        $this->assertTrue($this->check($result), 'Can not login');
    }

    protected function logout()
    {
        $result = $this->fixture->disconnect();
        $this->assertFalse($this->_pear->isError($result), 'Error on disconnect');
    }

    protected function clear()
    {
        // Clear all the scripts in the account.
        $this->login();
        $active = $this->fixture->getActive();
        if (isset($this->scripts[$active])) {
            $this->fixture->setActive(null);
        }
        foreach (array_keys($this->scripts) as $script) {
            $this->fixture->removeScript($script);
        }
        $this->logout();
    }

    protected function check($result)
    {
        if ($this->_pear->isError($result)) {
            throw new Exception($result->getMessage());
        }
        return $result;
    }

    public function testConnect()
    {
        $result = $this->fixture->connect(HOST, PORT);
        $this->assertTrue($this->check($result), 'Cannot connect');
    }
    
    public function testLogin()
    {
        $result = $this->fixture->connect(HOST, PORT);
        $this->assertTrue($this->check($result), 'Cannot connect');
        $result = $this->fixture->login(USERNAME, PASSWORD, null, '', false);
        $this->assertTrue($this->check($result), 'Cannot login');
    }

    public function testDisconnect()
    {
        $result = $this->fixture->connect(HOST, PORT);
        $this->assertFalse($this->_pear->isError($result), 'Cannot connect');
        $result = $this->fixture->login(USERNAME, PASSWORD, null, '', false);
        $this->assertFalse($this->_pear->isError($result), 'Cannot login');
        $result = $this->fixture->disconnect();
        $this->assertFalse($this->_pear->isError($result), 'Error on disconnect');
    }

    public function testListScripts()
    {
        $this->login();
        $scripts = $this->fixture->listScripts();
        $this->logout();
        $this->assertFalse($this->_pear->isError($scripts), 'Can not list scripts');
    }

    public function testInstallScript()
    {
        $this->clear();
        $this->login();

        // First script.
        $scriptname = 'test script1';
        $before_scripts = $this->fixture->listScripts();
        $result = $this->fixture->installScript($scriptname, $this->scripts[$scriptname]);
        $this->assertFalse($this->_pear->isError($result), 'Can not install script ' . $scriptname);
        $after_scripts = $this->fixture->listScripts();
        $diff_scripts = array_values(array_diff($after_scripts, $before_scripts));
        $this->assertTrue(count($diff_scripts) > 0, 'Script not installed');
        $this->assertEquals($scriptname, $diff_scripts[0], 'Added script has a different name');

        // Second script (install and activate)
        $scriptname = 'test script2';
        $before_scripts = $this->fixture->listScripts();
        $result = $this->fixture->installScript($scriptname, $this->scripts[$scriptname], true);
        $this->assertFalse($this->_pear->isError($result), 'Can not install script ' . $scriptname);
        $after_scripts = $this->fixture->listScripts();
        $diff_scripts = array_values(array_diff($after_scripts, $before_scripts));
        $this->assertTrue(count($diff_scripts) > 0, 'Script not installed');
        $this->assertEquals($scriptname, $diff_scripts[0], 'Added script has a different name');
        $active_script = $this->fixture->getActive();
        $this->assertEquals($scriptname, $active_script, 'Added script has a different name');
        $this->logout();
    }

    /**
     * There is a good chance that this test will fail since most servers have
     * a 32KB limit on uploaded scripts.
     */
    public function testInstallScriptLarge()
    {
        $this->clear();
        $this->login();
        $scriptname = 'test script4';
        $before_scripts = $this->fixture->listScripts();
        $result = $this->fixture->installScript($scriptname, $this->scripts[$scriptname]);
        $this->assertFalse($this->_pear->isError($result), 'Unable to upload large script (expected behavior for most servers)');
        $after_scripts = $this->fixture->listScripts();
        $diff_scripts = array_diff($after_scripts, $before_scripts);
        $this->assertEquals($scriptname, reset($diff_scripts), 'Added script has a different name');
        $this->logout();
    }

    /**
     * See bug #16691.
     */
    public function testInstallNonAsciiScript()
    {
        $this->clear();
        $this->login();

        $scriptname = 'test"scriptäöü3';
        $before_scripts = $this->fixture->listScripts();
        $result = $this->fixture->installScript($scriptname, $this->scripts[$scriptname]);
        $this->assertFalse($this->_pear->isError($result), 'Can not install script ' . $scriptname);
        $after_scripts = $this->fixture->listScripts();
        $diff_scripts = array_values(array_diff($after_scripts, $before_scripts));
        $this->assertTrue(count($diff_scripts) > 0, 'Script not installed');
        $this->assertEquals($scriptname, $diff_scripts[0], 'Added script has a different name');

        $this->logout();
    }

    public function testGetScript()
    {
        $this->clear();
        $this->login();
        $scriptname = 'test script1';
        $before_scripts = $this->fixture->listScripts();
        $result = $this->fixture->installScript($scriptname, $this->scripts[$scriptname]);
        $this->assertFalse($this->_pear->isError($result), 'Can not install script ' . $scriptname);
        $after_scripts = $this->fixture->listScripts();
        $diff_scripts = array_values(array_diff($after_scripts, $before_scripts));
        $this->assertTrue(count($diff_scripts) > 0);
        $this->assertEquals($scriptname, $diff_scripts[0], 'Added script has a different name');
        $script = $this->fixture->getScript($scriptname);
        $this->assertEquals(trim($this->scripts[$scriptname]), trim($script), 'Script installed is not the same script retrieved');
        $this->logout();
    }

    public function testGetActive()
    {
        $this->clear();
        $this->login();
        $active_script = $this->fixture->getActive();
        $this->assertFalse($this->_pear->isError($active_script), 'Error getting the active script');
        $this->logout();
    }

    public function testSetActive()
    {
        $this->clear();
        $scriptname = 'test script1';
        $this->login();
        $result = $this->fixture->installScript($scriptname, $this->scripts[$scriptname]);
        $result = $this->fixture->setActive($scriptname);
        $this->assertFalse($this->_pear->isError($result), 'Can not set active script');
        $active_script = $this->fixture->getActive();
        $this->assertEquals($scriptname, $active_script, 'Active script does not match');

        // Test for non-existant script.
        $result = $this->fixture->setActive('non existant script');
        $this->assertTrue($this->_pear->isError($result));
        $this->logout();
    }

    public function testRemoveScript()
    {
        $this->clear();
        $scriptname = 'test script1';
        $this->login();
        $result = $this->fixture->installScript($scriptname, $this->scripts[$scriptname]);
        $result = $this->fixture->removeScript($scriptname);
        $this->assertFalse($this->_pear->isError($result), 'Error removing active script');
        $this->logout();
    }
}
PK��Z�Y�npp$test/Net_Sieve/tests/config.php.distnu�[���<?php
define('HOST', 'localhost');
define('PORT', 4190);
define('USERNAME', 'user');
define('PASSWORD', 'pass');PK��Zҵ3��>test/Mail_mimeDecode/tests/semicolon_content_type_bug1724.phptnu�[���--TEST--
Bug #1724   Quoted Semicolons in Content-Type
--SKIPIF--
--FILE--
<?php
require_once('Mail/mime.php');

$Mime = new Mail_Mime();
$Mime->setTXTBody('Test message.');
$Mime->addAttachment('test file contents', 'text/plain; testparam="test1;semicolon"', 'test.txt', FALSE);

$body = $Mime->get();

$hdrs = '';
foreach ($Mime->headers() AS $name => $val) {
    $hdrs .= "$name: $val\n";
}
$hdrs .= "To: Receiver <receiver@example.com>\n";
$hdrs .= "From: Sender <sender@example.com>\n";
$hdrs .= "Subject: PEAR::Mail_Mime test mail\n";

require_once('Mail/mimeDecode.php');

$mime_message = "$hdrs\n$body";
$Decoder = new Mail_mimeDecode($mime_message);
$params = array(
    'include_bodies' => TRUE,
    'decode_bodies'  => TRUE,
    'decode_headers' => TRUE
);
$Decoded = $Decoder->decode($params);
$test_param = $Decoded->parts[1]->ctype_parameters['testparam'];

echo $test_param;

?>
--EXPECT--
test1;semicolon
PK��Zs��%��2test/Mail_mimeDecode/tests/parse_header_value.phptnu�[���--TEST--
Tests for _parseHeaderValue
--SKIPIF--
--FILE--
<?php
require_once 'Mail/mime.php';

$Mime = new Mail_Mime();
$Mime->setTXTBody('Test message.');
$contentAppend = 'testparam1="test1;semicolon";testparam2=two; testparam3="three"; '
                .'testparam4="four\;4\;four"; testparam5=five\;5\;five; '
                ."testparam6='six'; testparam7='seven;7';testparam8='eight\;8'; "
                .'testparam9="nine;9";testparam10="ten\;10"; '
                .'testparam11=\'a "double" quote\'; testparam12="a \'simple\' quote"; '
                .'testparam13=\'another " quote\'; testparam14="another \' quote";'
                .'testparam15=last';

$Mime->addAttachment('test file contents', "text/plain; $contentAppend", 'test.txt', FALSE);

$body = $Mime->get();

$hdrs = '';
foreach ($Mime->headers() AS $name => $val) {
    $hdrs .= "$name: $val\n";
}
$hdrs .= "To: Receiver <receiver@example.com>\n";
$hdrs .= "From: Sender <sender@example.com>\n";
$hdrs .= "Subject: PEAR::Mail_Mime test mail\n";

require_once 'Mail/mimeDecode.php';

$mime_message = "$hdrs\n$body";
$Decoder = new Mail_mimeDecode($mime_message);
$params = array(
    'include_bodies' => TRUE,
    'decode_bodies'  => TRUE,
    'decode_headers' => TRUE
);
$Decoded = $Decoder->decode($params);
$decodedParts = $Decoded->parts[1]->ctype_parameters;
//Bug #4057: Content-type params now have a name attribute.
unset($decodedParts['name']);
print_r($decodedParts);
?>
--EXPECT--
Array
(
    [testparam1] => test1;semicolon
    [testparam2] => two
    [testparam3] => three
    [testparam4] => four;4;four
    [testparam5] => five;5;five
    [testparam6] => six
    [testparam7] => seven;7
    [testparam8] => eight;8
    [testparam9] => nine;9
    [testparam10] => ten;10
    [testparam11] => a "double" quote
    [testparam12] => a 'simple' quote
    [testparam13] => another " quote
    [testparam14] => another ' quote
    [testparam15] => last
)
PK��Z�?7|�f�fAtest/HttpKernel/Symfony/Component/HttpKernel/Tests/KernelTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests;

use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest;
use Symfony\Component\HttpKernel\Tests\Fixtures\KernelForOverrideName;
use Symfony\Component\HttpKernel\Tests\Fixtures\FooBarBundle;

class KernelTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $env = 'test_env';
        $debug = true;
        $kernel = new KernelForTest($env, $debug);

        $this->assertEquals($env, $kernel->getEnvironment());
        $this->assertEquals($debug, $kernel->isDebug());
        $this->assertFalse($kernel->isBooted());
        $this->assertLessThanOrEqual(microtime(true), $kernel->getStartTime());
        $this->assertNull($kernel->getContainer());
    }

    public function testClone()
    {
        $env = 'test_env';
        $debug = true;
        $kernel = new KernelForTest($env, $debug);

        $clone = clone $kernel;

        $this->assertEquals($env, $clone->getEnvironment());
        $this->assertEquals($debug, $clone->isDebug());
        $this->assertFalse($clone->isBooted());
        $this->assertLessThanOrEqual(microtime(true), $clone->getStartTime());
        $this->assertNull($clone->getContainer());
    }

    public function testBootInitializesBundlesAndContainer()
    {
        $kernel = $this->getKernel(array('initializeBundles', 'initializeContainer'));
        $kernel->expects($this->once())
            ->method('initializeBundles');
        $kernel->expects($this->once())
            ->method('initializeContainer');

        $kernel->boot();
    }

    public function testBootSetsTheContainerToTheBundles()
    {
        $bundle = $this->getMock('Symfony\Component\HttpKernel\Bundle\Bundle');
        $bundle->expects($this->once())
            ->method('setContainer');

        $kernel = $this->getKernel(array('initializeBundles', 'initializeContainer', 'getBundles'));
        $kernel->expects($this->once())
            ->method('getBundles')
            ->will($this->returnValue(array($bundle)));

        $kernel->boot();
    }

    public function testBootSetsTheBootedFlagToTrue()
    {
        // use test kernel to access isBooted()
        $kernel = $this->getKernelForTest(array('initializeBundles', 'initializeContainer'));
        $kernel->boot();

        $this->assertTrue($kernel->isBooted());
    }

    public function testClassCacheIsLoaded()
    {
        $kernel = $this->getKernel(array('initializeBundles', 'initializeContainer', 'doLoadClassCache'));
        $kernel->loadClassCache('name', '.extension');
        $kernel->expects($this->once())
            ->method('doLoadClassCache')
            ->with('name', '.extension');

        $kernel->boot();
    }

    public function testClassCacheIsNotLoadedByDefault()
    {
        $kernel = $this->getKernel(array('initializeBundles', 'initializeContainer'));
        $kernel->expects($this->never())
            ->method('doLoadClassCache');

        $kernel->boot();
    }

    public function testClassCacheIsNotLoadedWhenKernelIsNotBooted()
    {
        $kernel = $this->getKernel(array('initializeBundles', 'initializeContainer', 'doLoadClassCache'));
        $kernel->loadClassCache();
        $kernel->expects($this->never())
            ->method('doLoadClassCache');
    }

    public function testBootKernelSeveralTimesOnlyInitializesBundlesOnce()
    {
        $kernel = $this->getKernel(array('initializeBundles', 'initializeContainer'));
        $kernel->expects($this->once())
            ->method('initializeBundles');

        $kernel->boot();
        $kernel->boot();
    }

    public function testShutdownCallsShutdownOnAllBundles()
    {
        $bundle = $this->getMock('Symfony\Component\HttpKernel\Bundle\Bundle');
        $bundle->expects($this->once())
            ->method('shutdown');

        $kernel = $this->getKernel(array(), array($bundle));

        $kernel->boot();
        $kernel->shutdown();
    }

    public function testShutdownGivesNullContainerToAllBundles()
    {
        $bundle = $this->getMock('Symfony\Component\HttpKernel\Bundle\Bundle');
        $bundle->expects($this->at(3))
            ->method('setContainer')
            ->with(null);

        $kernel = $this->getKernel(array('getBundles'));
        $kernel->expects($this->any())
            ->method('getBundles')
            ->will($this->returnValue(array($bundle)));

        $kernel->boot();
        $kernel->shutdown();
    }

    public function testHandleCallsHandleOnHttpKernel()
    {
        $type = HttpKernelInterface::MASTER_REQUEST;
        $catch = true;
        $request = new Request();

        $httpKernelMock = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernel')
            ->disableOriginalConstructor()
            ->getMock();
        $httpKernelMock
            ->expects($this->once())
            ->method('handle')
            ->with($request, $type, $catch);

        $kernel = $this->getKernel(array('getHttpKernel'));
        $kernel->expects($this->once())
            ->method('getHttpKernel')
            ->will($this->returnValue($httpKernelMock));

        $kernel->handle($request, $type, $catch);
    }

    public function testHandleBootsTheKernel()
    {
        $type = HttpKernelInterface::MASTER_REQUEST;
        $catch = true;
        $request = new Request();

        $httpKernelMock = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernel')
            ->disableOriginalConstructor()
            ->getMock();

        $kernel = $this->getKernel(array('getHttpKernel', 'boot'));
        $kernel->expects($this->once())
            ->method('getHttpKernel')
            ->will($this->returnValue($httpKernelMock));

        $kernel->expects($this->once())
            ->method('boot');

        $kernel->handle($request, $type, $catch);
    }

    public function testStripComments()
    {
        if (!function_exists('token_get_all')) {
            $this->markTestSkipped('The function token_get_all() is not available.');

            return;
        }
        $source = <<<'EOF'
<?php

$string = 'string should not be   modified';

$string = 'string should not be

modified';


$heredoc = <<<HD


Heredoc should not be   modified


HD;

$nowdoc = <<<'ND'


Nowdoc should not be   modified


ND;

/**
 * some class comments to strip
 */
class TestClass
{
    /**
     * some method comments to strip
     */
    public function doStuff()
    {
        // inline comment
    }
}
EOF;
        $expected = <<<'EOF'
<?php
$string = 'string should not be   modified';
$string = 'string should not be

modified';
$heredoc = <<<HD


Heredoc should not be   modified


HD;
$nowdoc = <<<'ND'


Nowdoc should not be   modified


ND;
class TestClass
{
    public function doStuff()
    {
        }
}
EOF;

        $output = Kernel::stripComments($source);

        // Heredocs are preserved, making the output mixing Unix and Windows line
        // endings, switching to "\n" everywhere on Windows to avoid failure.
        if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
            $expected = str_replace("\r\n", "\n", $expected);
            $output = str_replace("\r\n", "\n", $output);
        }

        $this->assertEquals($expected, $output);
    }

    public function testIsClassInActiveBundleFalse()
    {
        $kernel = $this->getKernelMockForIsClassInActiveBundleTest();

        $this->assertFalse($kernel->isClassInActiveBundle('Not\In\Active\Bundle'));
    }

    public function testIsClassInActiveBundleFalseNoNamespace()
    {
        $kernel = $this->getKernelMockForIsClassInActiveBundleTest();

        $this->assertFalse($kernel->isClassInActiveBundle('NotNamespacedClass'));
    }

    public function testIsClassInActiveBundleTrue()
    {
        $kernel = $this->getKernelMockForIsClassInActiveBundleTest();

        $this->assertTrue($kernel->isClassInActiveBundle(__NAMESPACE__.'\Fixtures\FooBarBundle\SomeClass'));
    }

    protected function getKernelMockForIsClassInActiveBundleTest()
    {
        $bundle = new FooBarBundle();

        $kernel = $this->getKernel(array('getBundles'));
        $kernel->expects($this->once())
            ->method('getBundles')
            ->will($this->returnValue(array($bundle)));

        return $kernel;
    }

    public function testGetRootDir()
    {
        $kernel = new KernelForTest('test', true);

        $this->assertEquals(__DIR__.DIRECTORY_SEPARATOR.'Fixtures', realpath($kernel->getRootDir()));
    }

    public function testGetName()
    {
        $kernel = new KernelForTest('test', true);

        $this->assertEquals('Fixtures', $kernel->getName());
    }

    public function testOverrideGetName()
    {
        $kernel = new KernelForOverrideName('test', true);

        $this->assertEquals('overridden', $kernel->getName());
    }

    public function testSerialize()
    {
        $env = 'test_env';
        $debug = true;
        $kernel = new KernelForTest($env, $debug);

        $expected = serialize(array($env, $debug));
        $this->assertEquals($expected, $kernel->serialize());
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testLocateResourceThrowsExceptionWhenNameIsNotValid()
    {
        $this->getKernel()->locateResource('Foo');
    }

    /**
     * @expectedException \RuntimeException
     */
    public function testLocateResourceThrowsExceptionWhenNameIsUnsafe()
    {
        $this->getKernel()->locateResource('@FooBundle/../bar');
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testLocateResourceThrowsExceptionWhenBundleDoesNotExist()
    {
        $this->getKernel()->locateResource('@FooBundle/config/routing.xml');
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testLocateResourceThrowsExceptionWhenResourceDoesNotExist()
    {
        $kernel = $this->getKernel(array('getBundle'));
        $kernel
            ->expects($this->once())
            ->method('getBundle')
            ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle'))))
        ;

        $kernel->locateResource('@Bundle1Bundle/config/routing.xml');
    }

    public function testLocateResourceReturnsTheFirstThatMatches()
    {
        $kernel = $this->getKernel(array('getBundle'));
        $kernel
            ->expects($this->once())
            ->method('getBundle')
            ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle'))))
        ;

        $this->assertEquals(__DIR__.'/Fixtures/Bundle1Bundle/foo.txt', $kernel->locateResource('@Bundle1Bundle/foo.txt'));
    }

    public function testLocateResourceReturnsTheFirstThatMatchesWithParent()
    {
        $parent = $this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle');
        $child = $this->getBundle(__DIR__.'/Fixtures/Bundle2Bundle');

        $kernel = $this->getKernel(array('getBundle'));
        $kernel
            ->expects($this->exactly(2))
            ->method('getBundle')
            ->will($this->returnValue(array($child, $parent)))
        ;

        $this->assertEquals(__DIR__.'/Fixtures/Bundle2Bundle/foo.txt', $kernel->locateResource('@ParentAABundle/foo.txt'));
        $this->assertEquals(__DIR__.'/Fixtures/Bundle1Bundle/bar.txt', $kernel->locateResource('@ParentAABundle/bar.txt'));
    }

    public function testLocateResourceReturnsAllMatches()
    {
        $parent = $this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle');
        $child = $this->getBundle(__DIR__.'/Fixtures/Bundle2Bundle');

        $kernel = $this->getKernel(array('getBundle'));
        $kernel
            ->expects($this->once())
            ->method('getBundle')
            ->will($this->returnValue(array($child, $parent)))
        ;

        $this->assertEquals(array(
            __DIR__.'/Fixtures/Bundle2Bundle/foo.txt',
            __DIR__.'/Fixtures/Bundle1Bundle/foo.txt'),
            $kernel->locateResource('@Bundle1Bundle/foo.txt', null, false));
    }

    public function testLocateResourceReturnsAllMatchesBis()
    {
        $kernel = $this->getKernel(array('getBundle'));
        $kernel
            ->expects($this->once())
            ->method('getBundle')
            ->will($this->returnValue(array(
                $this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle'),
                $this->getBundle(__DIR__.'/Foobar')
            )))
        ;

        $this->assertEquals(
            array(__DIR__.'/Fixtures/Bundle1Bundle/foo.txt'),
            $kernel->locateResource('@Bundle1Bundle/foo.txt', null, false)
        );
    }

    public function testLocateResourceIgnoresDirOnNonResource()
    {
        $kernel = $this->getKernel(array('getBundle'));
        $kernel
            ->expects($this->once())
            ->method('getBundle')
            ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle'))))
        ;

        $this->assertEquals(
            __DIR__.'/Fixtures/Bundle1Bundle/foo.txt',
            $kernel->locateResource('@Bundle1Bundle/foo.txt', __DIR__.'/Fixtures')
        );
    }

    public function testLocateResourceReturnsTheDirOneForResources()
    {
        $kernel = $this->getKernel(array('getBundle'));
        $kernel
            ->expects($this->once())
            ->method('getBundle')
            ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/FooBundle', null, null, 'FooBundle'))))
        ;

        $this->assertEquals(
            __DIR__.'/Fixtures/Resources/FooBundle/foo.txt',
            $kernel->locateResource('@FooBundle/Resources/foo.txt', __DIR__.'/Fixtures/Resources')
        );
    }

    public function testLocateResourceReturnsTheDirOneForResourcesAndBundleOnes()
    {
        $kernel = $this->getKernel(array('getBundle'));
        $kernel
            ->expects($this->once())
            ->method('getBundle')
            ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle', null, null, 'Bundle1Bundle'))))
        ;

        $this->assertEquals(array(
            __DIR__.'/Fixtures/Resources/Bundle1Bundle/foo.txt',
            __DIR__.'/Fixtures/Bundle1Bundle/Resources/foo.txt'),
            $kernel->locateResource('@Bundle1Bundle/Resources/foo.txt', __DIR__.'/Fixtures/Resources', false)
        );
    }

    public function testLocateResourceOverrideBundleAndResourcesFolders()
    {
        $parent = $this->getBundle(__DIR__.'/Fixtures/BaseBundle', null, 'BaseBundle', 'BaseBundle');
        $child = $this->getBundle(__DIR__.'/Fixtures/ChildBundle', 'ParentBundle', 'ChildBundle', 'ChildBundle');

        $kernel = $this->getKernel(array('getBundle'));
        $kernel
            ->expects($this->exactly(4))
            ->method('getBundle')
            ->will($this->returnValue(array($child, $parent)))
        ;

        $this->assertEquals(array(
            __DIR__.'/Fixtures/Resources/ChildBundle/foo.txt',
            __DIR__.'/Fixtures/ChildBundle/Resources/foo.txt',
            __DIR__.'/Fixtures/BaseBundle/Resources/foo.txt',
            ),
            $kernel->locateResource('@BaseBundle/Resources/foo.txt', __DIR__.'/Fixtures/Resources', false)
        );

        $this->assertEquals(
            __DIR__.'/Fixtures/Resources/ChildBundle/foo.txt',
            $kernel->locateResource('@BaseBundle/Resources/foo.txt', __DIR__.'/Fixtures/Resources')
        );

        try {
            $kernel->locateResource('@BaseBundle/Resources/hide.txt', __DIR__.'/Fixtures/Resources', false);
            $this->fail('Hidden resources should raise an exception when returning an array of matching paths');
        } catch (\RuntimeException $e) {
        }

        try {
            $kernel->locateResource('@BaseBundle/Resources/hide.txt', __DIR__.'/Fixtures/Resources', true);
            $this->fail('Hidden resources should raise an exception when returning the first matching path');
        } catch (\RuntimeException $e) {
        }
    }

    public function testLocateResourceOnDirectories()
    {
        $kernel = $this->getKernel(array('getBundle'));
        $kernel
            ->expects($this->exactly(2))
            ->method('getBundle')
            ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/FooBundle', null, null, 'FooBundle'))))
        ;

        $this->assertEquals(
            __DIR__.'/Fixtures/Resources/FooBundle/',
            $kernel->locateResource('@FooBundle/Resources/', __DIR__.'/Fixtures/Resources')
        );
        $this->assertEquals(
            __DIR__.'/Fixtures/Resources/FooBundle',
            $kernel->locateResource('@FooBundle/Resources', __DIR__.'/Fixtures/Resources')
        );

        $kernel = $this->getKernel(array('getBundle'));
        $kernel
            ->expects($this->exactly(2))
            ->method('getBundle')
            ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle', null, null, 'Bundle1Bundle'))))
        ;

        $this->assertEquals(
            __DIR__.'/Fixtures/Bundle1Bundle/Resources/',
            $kernel->locateResource('@Bundle1Bundle/Resources/')
        );
        $this->assertEquals(
            __DIR__.'/Fixtures/Bundle1Bundle/Resources',
            $kernel->locateResource('@Bundle1Bundle/Resources')
        );
    }

    public function testInitializeBundles()
    {
        $parent = $this->getBundle(null, null, 'ParentABundle');
        $child = $this->getBundle(null, 'ParentABundle', 'ChildABundle');

        // use test kernel so we can access getBundleMap()
        $kernel = $this->getKernelForTest(array('registerBundles'));
        $kernel
            ->expects($this->once())
            ->method('registerBundles')
            ->will($this->returnValue(array($parent, $child)))
        ;
        $kernel->boot();

        $map = $kernel->getBundleMap();
        $this->assertEquals(array($child, $parent), $map['ParentABundle']);
    }

    public function testInitializeBundlesSupportInheritanceCascade()
    {
        $grandparent = $this->getBundle(null, null, 'GrandParentBBundle');
        $parent = $this->getBundle(null, 'GrandParentBBundle', 'ParentBBundle');
        $child = $this->getBundle(null, 'ParentBBundle', 'ChildBBundle');

        // use test kernel so we can access getBundleMap()
        $kernel = $this->getKernelForTest(array('registerBundles'));
        $kernel
            ->expects($this->once())
            ->method('registerBundles')
            ->will($this->returnValue(array($grandparent, $parent, $child)))
        ;
        $kernel->boot();

        $map = $kernel->getBundleMap();
        $this->assertEquals(array($child, $parent, $grandparent), $map['GrandParentBBundle']);
        $this->assertEquals(array($child, $parent), $map['ParentBBundle']);
        $this->assertEquals(array($child), $map['ChildBBundle']);
    }

    /**
     * @expectedException \LogicException
     * @expectedExceptionMessage Bundle "ChildCBundle" extends bundle "FooBar", which is not registered.
     */
    public function testInitializeBundlesThrowsExceptionWhenAParentDoesNotExists()
    {
        $child = $this->getBundle(null, 'FooBar', 'ChildCBundle');
        $kernel = $this->getKernel(array(), array($child));
        $kernel->boot();
    }

    public function testInitializeBundlesSupportsArbitraryBundleRegistrationOrder()
    {
        $grandparent = $this->getBundle(null, null, 'GrandParentCBundle');
        $parent = $this->getBundle(null, 'GrandParentCBundle', 'ParentCBundle');
        $child = $this->getBundle(null, 'ParentCBundle', 'ChildCBundle');

        // use test kernel so we can access getBundleMap()
        $kernel = $this->getKernelForTest(array('registerBundles'));
        $kernel
            ->expects($this->once())
            ->method('registerBundles')
            ->will($this->returnValue(array($parent, $grandparent, $child)))
        ;
        $kernel->boot();

        $map = $kernel->getBundleMap();
        $this->assertEquals(array($child, $parent, $grandparent), $map['GrandParentCBundle']);
        $this->assertEquals(array($child, $parent), $map['ParentCBundle']);
        $this->assertEquals(array($child), $map['ChildCBundle']);
    }

    /**
     * @expectedException \LogicException
     * @expectedExceptionMessage Bundle "ParentCBundle" is directly extended by two bundles "ChildC2Bundle" and "ChildC1Bundle".
     */
    public function testInitializeBundlesThrowsExceptionWhenABundleIsDirectlyExtendedByTwoBundles()
    {
        $parent = $this->getBundle(null, null, 'ParentCBundle');
        $child1 = $this->getBundle(null, 'ParentCBundle', 'ChildC1Bundle');
        $child2 = $this->getBundle(null, 'ParentCBundle', 'ChildC2Bundle');

        $kernel = $this->getKernel(array(), array($parent, $child1, $child2));
        $kernel->boot();
    }

    /**
     * @expectedException \LogicException
     * @expectedExceptionMessage Trying to register two bundles with the same name "DuplicateName"
     */
    public function testInitializeBundleThrowsExceptionWhenRegisteringTwoBundlesWithTheSameName()
    {
        $fooBundle = $this->getBundle(null, null, 'FooBundle', 'DuplicateName');
        $barBundle = $this->getBundle(null, null, 'BarBundle', 'DuplicateName');

        $kernel = $this->getKernel(array(), array($fooBundle, $barBundle));
        $kernel->boot();
    }

    /**
     * @expectedException \LogicException
     * @expectedExceptionMessage Bundle "CircularRefBundle" can not extend itself.
     */
    public function testInitializeBundleThrowsExceptionWhenABundleExtendsItself()
    {
        $circularRef = $this->getBundle(null, 'CircularRefBundle', 'CircularRefBundle');

        $kernel = $this->getKernel(array(), array($circularRef));
        $kernel->boot();
    }

    public function testTerminateReturnsSilentlyIfKernelIsNotBooted()
    {
        $kernel = $this->getKernel(array('getHttpKernel'));
        $kernel->expects($this->never())
            ->method('getHttpKernel');

        $kernel->terminate(Request::create('/'), new Response());
    }

    public function testTerminateDelegatesTerminationOnlyForTerminableInterface()
    {
        // does not implement TerminableInterface
        $httpKernelMock = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')
            ->disableOriginalConstructor()
            ->getMock();

        $httpKernelMock
            ->expects($this->never())
            ->method('terminate');

        $kernel = $this->getKernel(array('getHttpKernel'));
        $kernel->expects($this->once())
            ->method('getHttpKernel')
            ->will($this->returnValue($httpKernelMock));

        $kernel->boot();
        $kernel->terminate(Request::create('/'), new Response());

        // implements TerminableInterface
        $httpKernelMock = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernel')
            ->disableOriginalConstructor()
            ->setMethods(array('terminate'))
            ->getMock();

        $httpKernelMock
            ->expects($this->once())
            ->method('terminate');

        $kernel = $this->getKernel(array('getHttpKernel'));
        $kernel->expects($this->exactly(2))
            ->method('getHttpKernel')
            ->will($this->returnValue($httpKernelMock));

        $kernel->boot();
        $kernel->terminate(Request::create('/'), new Response());
    }

    /**
     * Returns a mock for the BundleInterface
     *
     * @return BundleInterface
     */
    protected function getBundle($dir = null, $parent = null, $className = null, $bundleName = null)
    {
        $bundle = $this
            ->getMockBuilder('Symfony\Component\HttpKernel\Bundle\BundleInterface')
            ->setMethods(array('getPath', 'getParent', 'getName'))
            ->disableOriginalConstructor()
        ;

        if ($className) {
            $bundle->setMockClassName($className);
        }

        $bundle = $bundle->getMockForAbstractClass();

        $bundle
            ->expects($this->any())
            ->method('getName')
            ->will($this->returnValue(null === $bundleName ? get_class($bundle) : $bundleName))
        ;

        $bundle
            ->expects($this->any())
            ->method('getPath')
            ->will($this->returnValue($dir))
        ;

        $bundle
            ->expects($this->any())
            ->method('getParent')
            ->will($this->returnValue($parent))
        ;

        return $bundle;
    }

    /**
     * Returns a mock for the abstract kernel.
     *
     * @param array $methods Additional methods to mock (besides the abstract ones)
     * @param array $bundles Bundles to register
     *
     * @return Kernel
     */
    protected function getKernel(array $methods = array(), array $bundles = array())
    {
        $methods[] = 'registerBundles';

        $kernel = $this
            ->getMockBuilder('Symfony\Component\HttpKernel\Kernel')
            ->setMethods($methods)
            ->setConstructorArgs(array('test', false))
            ->getMockForAbstractClass()
        ;
        $kernel->expects($this->any())
            ->method('registerBundles')
            ->will($this->returnValue($bundles))
        ;
        $p = new \ReflectionProperty($kernel, 'rootDir');
        $p->setAccessible(true);
        $p->setValue($kernel, __DIR__.'/Fixtures');

        return $kernel;
    }

    protected function getKernelForTest(array $methods = array())
    {
        $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest')
            ->setConstructorArgs(array('test', false))
            ->setMethods($methods)
            ->getMock();
        $p = new \ReflectionProperty($kernel, 'rootDir');
        $p->setAccessible(true);
        $p->setValue($kernel, __DIR__.'/Fixtures');

        return $kernel;
    }
}
PK��Z6^P�Ytest/HttpKernel/Symfony/Component/HttpKernel/Tests/CacheClearer/ChainCacheClearerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\CacheClearer;

use Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface;
use Symfony\Component\HttpKernel\CacheClearer\ChainCacheClearer;

class ChainCacheClearerTest extends \PHPUnit_Framework_TestCase
{
    protected static $cacheDir;

    public static function setUpBeforeClass()
    {
        self::$cacheDir = tempnam(sys_get_temp_dir(), 'sf2_cache_clearer_dir');
    }

    public static function tearDownAfterClass()
    {
        @unlink(self::$cacheDir);
    }

    public function testInjectClearersInConstructor()
    {
        $clearer = $this->getMockClearer();
        $clearer
            ->expects($this->once())
            ->method('clear');

        $chainClearer = new ChainCacheClearer(array($clearer));
        $chainClearer->clear(self::$cacheDir);
    }

    public function testInjectClearerUsingAdd()
    {
        $clearer = $this->getMockClearer();
        $clearer
            ->expects($this->once())
            ->method('clear');

        $chainClearer = new ChainCacheClearer();
        $chainClearer->add($clearer);
        $chainClearer->clear(self::$cacheDir);
    }

    protected function getMockClearer()
    {
        return $this->getMock('Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface');
    }
}
PK��Z32ET��Stest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/TestEventDispatcher.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\Fixtures;

use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventDispatcher;

class TestEventDispatcher extends EventDispatcher implements TraceableEventDispatcherInterface
{
    public function getCalledListeners()
    {
        return array('foo');
    }

    public function getNotCalledListeners()
    {
        return array('bar');
    }
}
PK��Zg&��ktest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionAbsentBundle/ExtensionAbsentBundle.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionAbsentBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;

class ExtensionAbsentBundle extends Bundle
{
}
PK��Zx���itest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/Command/BarCommand.phpnu�[���<?php

namespace Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionPresentBundle\Command;

use Symfony\Component\Console\Command\Command;

/**
 * This command has a required parameter on the constructor and will be ignored by the default Bundle implementation.
 *
 * @see Symfony\Component\HttpKernel\Bundle\Bundle::registerCommands
 */
class BarCommand extends Command
{
    public function __construct($example, $name = 'bar')
    {

    }
}
PK��Z��W���itest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/Command/FooCommand.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionPresentBundle\Command;

use Symfony\Component\Console\Command\Command;

class FooCommand extends Command
{
    protected function configure()
    {
        $this->setName('foo');
    }

}
PK��Z`A�mtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/ExtensionPresentBundle.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionPresentBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;

class ExtensionPresentBundle extends Bundle
{
}
PK��ZO�g�VV�test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/DependencyInjection/ExtensionPresentExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionPresentBundle\DependencyInjection;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;

class ExtensionPresentExtension extends Extension
{
    public function load(array $configs, ContainerBuilder $container)
    {
    }
}
PK��ZGQ�>`
`
itest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/cache/test/MockObjectTestProjectContainer.phpnu�[���<?php
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
class MockObjectTestProjectContainer extends Container
{
    private $parameters;
    public function __construct()
    {
        $this->parameters = $this->getDefaultParameters();
        $this->services =
        $this->scopedServices =
        $this->scopeStacks = array();
        $this->set('service_container', $this);
        $this->scopes = array();
        $this->scopeChildren = array();
        $this->aliases = array();
    }
    public function getParameter($name)
    {
        $name = strtolower($name);
        if (!(isset($this->parameters[$name]) || array_key_exists($name, $this->parameters))) {
            throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name));
        }
        return $this->parameters[$name];
    }
    public function hasParameter($name)
    {
        $name = strtolower($name);
        return isset($this->parameters[$name]) || array_key_exists($name, $this->parameters);
    }
    public function setParameter($name, $value)
    {
        throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
    }
    public function getParameterBag()
    {
        if (null === $this->parameterBag) {
            $this->parameterBag = new FrozenParameterBag($this->parameters);
        }
        return $this->parameterBag;
    }
    protected function getDefaultParameters()
    {
        return array(
            'kernel.root_dir' => '/Users/fabien/Code/github/symfony/symfony/src/Symfony/Component/HttpKernel/Tests/Fixtures',
            'kernel.environment' => 'test',
            'kernel.debug' => false,
            'kernel.name' => 'MockObject',
            'kernel.cache_dir' => '/Users/fabien/Code/github/symfony/symfony/src/Symfony/Component/HttpKernel/Tests/Fixtures/cache/test',
            'kernel.logs_dir' => '/Users/fabien/Code/github/symfony/symfony/src/Symfony/Component/HttpKernel/Tests/Fixtures/logs',
            'kernel.bundles' => array(
                'Mock_Bundle_7fc4ae26' => 'Mock_Bundle_7fc4ae26',
            ),
            'kernel.charset' => 'UTF-8',
            'kernel.container_class' => 'MockObjectTestProjectContainer',
        );
    }
}
PK��Z#��Rtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/cache/test/classes.mapnu�[���<?php return array (
);PK��ZQtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Bundle2Bundle/foo.txtnu�[���PK��Zq�}VffUtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/KernelForOverrideName.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\Fixtures;

use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Config\Loader\LoaderInterface;

class KernelForOverrideName extends Kernel
{
    protected $name = 'overridden';

    public function registerBundles()
    {

    }

    public function registerContainerConfiguration(LoaderInterface $loader)
    {

    }
}
PK��ZYtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ChildBundle/Resources/foo.txtnu�[���PK��ZZtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ChildBundle/Resources/hide.txtnu�[���PK��ZQtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle/foo.txtnu�[���PK��ZQtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle/bar.txtnu�[���PK��Z[test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle/Resources/foo.txtnu�[���PK��ZWtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/FooBundle/foo.txtnu�[���PK��ZYtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/ChildBundle/foo.txtnu�[���PK��Z[test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/Bundle1Bundle/foo.txtnu�[���PK��ZYtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/BaseBundle/hide.txtnu�[���PK��ZXtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/BaseBundle/Resources/foo.txtnu�[���PK��ZYtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/BaseBundle/Resources/hide.txtnu�[���PK��Z&#�Jtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/TestClient.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\Fixtures;

use Symfony\Component\HttpKernel\Client;

class TestClient extends Client
{
    protected function getScript($request)
    {
        $script = parent::getScript($request);

        $autoload = file_exists(__DIR__.'/../../vendor/autoload.php')
            ? __DIR__.'/../../vendor/autoload.php'
            : __DIR__.'/../../../../../../vendor/autoload.php'
        ;

        $script = preg_replace('/(\->register\(\);)/', "$0\nrequire_once '$autoload';\n", $script);

        return $script;
    }
}
PK��Zy��h��Mtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/KernelForTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\Fixtures;

use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Config\Loader\LoaderInterface;

class KernelForTest extends Kernel
{
    public function getBundleMap()
    {
        return $this->bundleMap;
    }

    public function registerBundles()
    {
        return array();
    }

    public function registerContainerConfiguration(LoaderInterface $loader)
    {
    }

    public function isBooted()
    {
        return $this->booted;
    }
}
PK��Z�0����Ltest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/FooBarBundle.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\Fixtures;

use Symfony\Component\HttpKernel\Bundle\Bundle;

class FooBarBundle extends Bundle
{
    // We need a full namespaced bundle instance to test isClassInActiveBundle
}
PK��Z��?ɜ�ktest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionLoadedBundle/ExtensionLoadedBundle.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionLoadedBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;

class ExtensionLoadedBundle extends Bundle
{
}
PK��Z��_�TT�test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionLoadedBundle/DependencyInjection/ExtensionLoadedExtension.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionLoadedBundle\DependencyInjection;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;

class ExtensionLoadedExtension extends Extension
{
    public function load(array $configs, ContainerBuilder $container)
    {
    }
}
PK��Z���S��[test/HttpKernel/Symfony/Component/HttpKernel/Tests/CacheWarmer/CacheWarmerAggregateTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\CacheWarmer;

use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;
use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerAggregate;
use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmer;

class CacheWarmerAggregateTest extends \PHPUnit_Framework_TestCase
{
    protected static $cacheDir;

    public static function setUpBeforeClass()
    {
        self::$cacheDir = tempnam(sys_get_temp_dir(), 'sf2_cache_warmer_dir');
    }

    public static function tearDownAfterClass()
    {
        @unlink(self::$cacheDir);
    }

    public function testInjectWarmersUsingConstructor()
    {
        $warmer = $this->getCacheWarmerMock();
        $warmer
            ->expects($this->once())
            ->method('warmUp');
        $aggregate = new CacheWarmerAggregate(array($warmer));
        $aggregate->warmUp(self::$cacheDir);
    }

    public function testInjectWarmersUsingAdd()
    {
        $warmer = $this->getCacheWarmerMock();
        $warmer
            ->expects($this->once())
            ->method('warmUp');
        $aggregate = new CacheWarmerAggregate();
        $aggregate->add($warmer);
        $aggregate->warmUp(self::$cacheDir);
    }

    public function testInjectWarmersUsingSetWarmers()
    {
        $warmer = $this->getCacheWarmerMock();
        $warmer
            ->expects($this->once())
            ->method('warmUp');
        $aggregate = new CacheWarmerAggregate();
        $aggregate->setWarmers(array($warmer));
        $aggregate->warmUp(self::$cacheDir);
    }

    public function testWarmupDoesCallWarmupOnOptionalWarmersWhenEnableOptionalWarmersIsEnabled()
    {
        $warmer = $this->getCacheWarmerMock();
        $warmer
            ->expects($this->never())
            ->method('isOptional');
        $warmer
            ->expects($this->once())
            ->method('warmUp');

        $aggregate = new CacheWarmerAggregate(array($warmer));
        $aggregate->enableOptionalWarmers();
        $aggregate->warmUp(self::$cacheDir);
    }

    public function testWarmupDoesNotCallWarmupOnOptionalWarmersWhenEnableOptionalWarmersIsNotEnabled()
    {
        $warmer = $this->getCacheWarmerMock();
        $warmer
            ->expects($this->once())
            ->method('isOptional')
            ->will($this->returnValue(true));
        $warmer
            ->expects($this->never())
            ->method('warmUp');

        $aggregate = new CacheWarmerAggregate(array($warmer));
        $aggregate->warmUp(self::$cacheDir);
    }

    protected function getCacheWarmerMock()
    {
        $warmer = $this->getMockBuilder('Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface')
            ->disableOriginalConstructor()
            ->getMock();

        return $warmer;
    }
}
PK��Z���,%%Rtest/HttpKernel/Symfony/Component/HttpKernel/Tests/CacheWarmer/CacheWarmerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\CacheWarmer;

use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmer;

class CacheWarmerTest extends \PHPUnit_Framework_TestCase
{
    protected static $cacheFile;

    public static function setUpBeforeClass()
    {
        self::$cacheFile = tempnam(sys_get_temp_dir(), 'sf2_cache_warmer_dir');
    }

    public static function tearDownAfterClass()
    {
        @unlink(self::$cacheFile);
    }

    public function testWriteCacheFileCreatesTheFile()
    {
        $warmer = new TestCacheWarmer(self::$cacheFile);
        $warmer->warmUp(dirname(self::$cacheFile));

        $this->assertTrue(file_exists(self::$cacheFile));
    }

    /**
     * @expectedException \RuntimeException
     */
    public function testWriteNonWritableCacheFileThrowsARuntimeException()
    {
        $nonWritableFile = '/this/file/is/very/probably/not/writable';
        $warmer = new TestCacheWarmer($nonWritableFile);
        $warmer->warmUp(dirname($nonWritableFile));
    }
}

class TestCacheWarmer extends CacheWarmer
{
    protected $file;

    public function __construct($file)
    {
        $this->file = $file;
    }

    public function warmUp($cacheDir)
    {
        $this->writeCacheFile($this->file, 'content');
    }

    public function isOptional()
    {
        return false;
    }
}
PK��Z0��GGEtest/HttpKernel/Symfony/Component/HttpKernel/Tests/TestHttpKernel.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests;

use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
use Symfony\Component\EventDispatcher\EventDispatcher;

class TestHttpKernel extends HttpKernel implements ControllerResolverInterface
{
    public function __construct()
    {
        parent::__construct(new EventDispatcher(), $this);
    }

    public function getController(Request $request)
    {
        return array($this, 'callController');
    }

    public function getArguments(Request $request, $controller)
    {
        return array($request);
    }

    public function callController(Request $request)
    {
        return new Response('Request: '.$request->getRequestUri());
    }
}
PK��Zq��Atest/HttpKernel/Symfony/Component/HttpKernel/Tests/ClientTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests;

use Symfony\Component\HttpKernel\Client;
use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpKernel\Tests\Fixtures\TestClient;

class ClientTest extends \PHPUnit_Framework_TestCase
{
    public function testDoRequest()
    {
        $client = new Client(new TestHttpKernel());

        $client->request('GET', '/');
        $this->assertEquals('Request: /', $client->getResponse()->getContent(), '->doRequest() uses the request handler to make the request');
        $this->assertInstanceOf('Symfony\Component\BrowserKit\Request', $client->getInternalRequest());
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\Request', $client->getRequest());
        $this->assertInstanceOf('Symfony\Component\BrowserKit\Response', $client->getInternalResponse());
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $client->getResponse());

        $client->request('GET', 'http://www.example.com/');
        $this->assertEquals('Request: /', $client->getResponse()->getContent(), '->doRequest() uses the request handler to make the request');
        $this->assertEquals('www.example.com', $client->getRequest()->getHost(), '->doRequest() uses the request handler to make the request');

        $client->request('GET', 'http://www.example.com/?parameter=http://google.com');
        $this->assertEquals('http://www.example.com/?parameter='.urlencode('http://google.com'), $client->getRequest()->getUri(), '->doRequest() uses the request handler to make the request');
    }

    public function testGetScript()
    {
        $client = new TestClient(new TestHttpKernel());
        $client->insulate();
        $client->request('GET', '/');

        $this->assertEquals('Request: /', $client->getResponse()->getContent(), '->getScript() returns a script that uses the request handler to make the request');
    }

    public function testFilterResponseConvertsCookies()
    {
        $client = new Client(new TestHttpKernel());

        $r = new \ReflectionObject($client);
        $m = $r->getMethod('filterResponse');
        $m->setAccessible(true);

        $expected = array(
            'foo=bar; expires=Sun, 15 Feb 2009 20:00:00 GMT; domain=http://example.com; path=/foo; secure; httponly',
            'foo1=bar1; expires=Sun, 15 Feb 2009 20:00:00 GMT; domain=http://example.com; path=/foo; secure; httponly'
        );

        $response = new Response();
        $response->headers->setCookie(new Cookie('foo', 'bar', \DateTime::createFromFormat('j-M-Y H:i:s T', '15-Feb-2009 20:00:00 GMT')->format('U'), '/foo', 'http://example.com', true, true));
        $domResponse = $m->invoke($client, $response);
        $this->assertEquals($expected[0], $domResponse->getHeader('Set-Cookie'));

        $response = new Response();
        $response->headers->setCookie(new Cookie('foo', 'bar', \DateTime::createFromFormat('j-M-Y H:i:s T', '15-Feb-2009 20:00:00 GMT')->format('U'), '/foo', 'http://example.com', true, true));
        $response->headers->setCookie(new Cookie('foo1', 'bar1', \DateTime::createFromFormat('j-M-Y H:i:s T', '15-Feb-2009 20:00:00 GMT')->format('U'), '/foo', 'http://example.com', true, true));
        $domResponse = $m->invoke($client, $response);
        $this->assertEquals($expected[0], $domResponse->getHeader('Set-Cookie'));
        $this->assertEquals($expected, $domResponse->getHeader('Set-Cookie', false));
    }

    public function testFilterResponseSupportsStreamedResponses()
    {
        $client = new Client(new TestHttpKernel());

        $r = new \ReflectionObject($client);
        $m = $r->getMethod('filterResponse');
        $m->setAccessible(true);

        $response = new StreamedResponse(function () {
            echo 'foo';
        });

        $domResponse = $m->invoke($client, $response);
        $this->assertEquals('foo', $domResponse->getContent());
    }

    public function testUploadedFile()
    {
        $source = tempnam(sys_get_temp_dir(), 'source');
        $target = sys_get_temp_dir().'/sf.moved.file';
        @unlink($target);

        $kernel = new TestHttpKernel();
        $client = new Client($kernel);

        $files = array(
            array('tmp_name' => $source, 'name' => 'original', 'type' => 'mime/original', 'size' => 123, 'error' => UPLOAD_ERR_OK),
            new UploadedFile($source, 'original', 'mime/original', 123, UPLOAD_ERR_OK, true),
        );

        $file = null;
        foreach ($files as $file) {
            $client->request('POST', '/', array(), array('foo' => $file));

            $files = $client->getRequest()->files->all();

            $this->assertCount(1, $files);

            $file = $files['foo'];

            $this->assertEquals('original', $file->getClientOriginalName());
            $this->assertEquals('mime/original', $file->getClientMimeType());
            $this->assertEquals('123', $file->getClientSize());
            $this->assertTrue($file->isValid());
        }

        $file->move(dirname($target), basename($target));

        $this->assertFileExists($target);
        unlink($target);
    }

    public function testUploadedFileWhenSizeExceedsUploadMaxFileSize()
    {
        $source = tempnam(sys_get_temp_dir(), 'source');

        $kernel = new TestHttpKernel();
        $client = new Client($kernel);

        $file = $this
            ->getMockBuilder('Symfony\Component\HttpFoundation\File\UploadedFile')
            ->setConstructorArgs(array($source, 'original', 'mime/original', 123, UPLOAD_ERR_OK, true))
            ->setMethods(array('getSize'))
            ->getMock()
        ;

        $file->expects($this->once())
            ->method('getSize')
            ->will($this->returnValue(INF))
        ;

        $client->request('POST', '/', array(), array($file));

        $files = $client->getRequest()->files->all();

        $this->assertCount(1, $files);

        $file = $files[0];

        $this->assertFalse($file->isValid());
        $this->assertEquals(UPLOAD_ERR_INI_SIZE, $file->getError());
        $this->assertEquals('mime/original', $file->getClientMimeType());
        $this->assertEquals('original', $file->getClientOriginalName());
        $this->assertEquals(0, $file->getClientSize());

        unlink($source);
    }
}
PK��Z݂(�$�$Ytest/HttpKernel/Symfony/Component/HttpKernel/Tests/Debug/TraceableEventDispatcherTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\Debug;

use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher;
use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Stopwatch\Stopwatch;

class TraceableEventDispatcherTest extends \PHPUnit_Framework_TestCase
{
    public function testAddRemoveListener()
    {
        $dispatcher = new EventDispatcher();
        $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch());

        $tdispatcher->addListener('foo', $listener = function () { ; });
        $listeners = $dispatcher->getListeners('foo');
        $this->assertCount(1, $listeners);
        $this->assertSame($listener, $listeners[0]);

        $tdispatcher->removeListener('foo', $listener);
        $this->assertCount(0, $dispatcher->getListeners('foo'));
    }

    public function testGetListeners()
    {
        $dispatcher = new EventDispatcher();
        $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch());

        $tdispatcher->addListener('foo', $listener = function () { ; });
        $this->assertSame($dispatcher->getListeners('foo'), $tdispatcher->getListeners('foo'));
    }

    public function testHasListeners()
    {
        $dispatcher = new EventDispatcher();
        $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch());

        $this->assertFalse($dispatcher->hasListeners('foo'));
        $this->assertFalse($tdispatcher->hasListeners('foo'));

        $tdispatcher->addListener('foo', $listener = function () { ; });
        $this->assertTrue($dispatcher->hasListeners('foo'));
        $this->assertTrue($tdispatcher->hasListeners('foo'));
    }

    public function testAddRemoveSubscriber()
    {
        $dispatcher = new EventDispatcher();
        $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch());

        $subscriber = new EventSubscriber();

        $tdispatcher->addSubscriber($subscriber);
        $listeners = $dispatcher->getListeners('foo');
        $this->assertCount(1, $listeners);
        $this->assertSame(array($subscriber, 'call'), $listeners[0]);

        $tdispatcher->removeSubscriber($subscriber);
        $this->assertCount(0, $dispatcher->getListeners('foo'));
    }

    public function testGetCalledListeners()
    {
        $dispatcher = new EventDispatcher();
        $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch());
        $tdispatcher->addListener('foo', $listener = function () { ; });

        $this->assertEquals(array(), $tdispatcher->getCalledListeners());
        $this->assertEquals(array('foo.closure' => array('event' => 'foo', 'type' => 'Closure', 'pretty' => 'closure')), $tdispatcher->getNotCalledListeners());

        $tdispatcher->dispatch('foo');

        $this->assertEquals(array('foo.closure' => array('event' => 'foo', 'type' => 'Closure', 'pretty' => 'closure')), $tdispatcher->getCalledListeners());
        $this->assertEquals(array(), $tdispatcher->getNotCalledListeners());
    }

    public function testLogger()
    {
        $logger = $this->getMock('Psr\Log\LoggerInterface');

        $dispatcher = new EventDispatcher();
        $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch(), $logger);
        $tdispatcher->addListener('foo', $listener1 = function () { ; });
        $tdispatcher->addListener('foo', $listener2 = function () { ; });

        $logger->expects($this->at(0))->method('debug')->with("Notified event \"foo\" to listener \"closure\".");
        $logger->expects($this->at(1))->method('debug')->with("Notified event \"foo\" to listener \"closure\".");

        $tdispatcher->dispatch('foo');
    }

    public function testLoggerWithStoppedEvent()
    {
        $logger = $this->getMock('Psr\Log\LoggerInterface');

        $dispatcher = new EventDispatcher();
        $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch(), $logger);
        $tdispatcher->addListener('foo', $listener1 = function (Event $event) { $event->stopPropagation(); });
        $tdispatcher->addListener('foo', $listener2 = function () { ; });

        $logger->expects($this->at(0))->method('debug')->with("Notified event \"foo\" to listener \"closure\".");
        $logger->expects($this->at(1))->method('debug')->with("Listener \"closure\" stopped propagation of the event \"foo\".");
        $logger->expects($this->at(2))->method('debug')->with("Listener \"closure\" was not called for event \"foo\".");

        $tdispatcher->dispatch('foo');
    }

    public function testDispatchCallListeners()
    {
        $called = array();

        $dispatcher = new EventDispatcher();
        $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch());
        $tdispatcher->addListener('foo', $listener1 = function () use (&$called) { $called[] = 'foo1'; });
        $tdispatcher->addListener('foo', $listener2 = function () use (&$called) { $called[] = 'foo2'; });

        $tdispatcher->dispatch('foo');

        $this->assertEquals(array('foo1', 'foo2'), $called);
    }

    public function testDispatchNested()
    {
        $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
        $loop = 1;
        $dispatcher->addListener('foo', $listener1 = function () use ($dispatcher, &$loop) {
            ++$loop;
            if (2 == $loop) {
                $dispatcher->dispatch('foo');
            }
        });

        $dispatcher->dispatch('foo');
    }

    public function testDispatchReusedEventNested()
    {
        $nestedCall = false;
        $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
        $dispatcher->addListener('foo', function (Event $e) use ($dispatcher) {
            $dispatcher->dispatch('bar', $e);
        });
        $dispatcher->addListener('bar', function (Event $e) use (&$nestedCall) {
            $nestedCall = true;
        });

        $this->assertFalse($nestedCall);
        $dispatcher->dispatch('foo');
        $this->assertTrue($nestedCall);
    }

    public function testStopwatchSections()
    {
        $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), $stopwatch = new Stopwatch());
        $kernel = $this->getHttpKernel($dispatcher, function () { return new Response(); });
        $request = Request::create('/');
        $response = $kernel->handle($request);
        $kernel->terminate($request, $response);

        $events = $stopwatch->getSectionEvents($response->headers->get('X-Debug-Token'));
        $this->assertEquals(array(
            '__section__',
            'kernel.request',
            'kernel.request.loading',
            'kernel.controller',
            'kernel.controller.loading',
            'controller',
            'kernel.response',
            'kernel.response.loading',
            'kernel.terminate',
            'kernel.terminate.loading',
        ), array_keys($events));
    }

    public function testStopwatchCheckControllerOnRequestEvent()
    {
        $stopwatch = $this->getMockBuilder('Symfony\Component\Stopwatch\Stopwatch')
            ->setMethods(array('isStarted'))
            ->getMock();
        $stopwatch->expects($this->once())
            ->method('isStarted')
            ->will($this->returnValue(false));

        $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), $stopwatch);

        $kernel = $this->getHttpKernel($dispatcher, function () { return new Response(); });
        $request = Request::create('/');
        $kernel->handle($request);
    }

    public function testStopwatchStopControllerOnRequestEvent()
    {
        $stopwatch = $this->getMockBuilder('Symfony\Component\Stopwatch\Stopwatch')
            ->setMethods(array('isStarted', 'stop', 'stopSection'))
            ->getMock();
        $stopwatch->expects($this->once())
            ->method('isStarted')
            ->will($this->returnValue(true));
        $stopwatch->expects($this->once())
            ->method('stop');
        $stopwatch->expects($this->once())
            ->method('stopSection');

        $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), $stopwatch);

        $kernel = $this->getHttpKernel($dispatcher, function () { return new Response(); });
        $request = Request::create('/');
        $kernel->handle($request);
    }

    protected function getHttpKernel($dispatcher, $controller)
    {
        $resolver = $this->getMock('Symfony\Component\HttpKernel\Controller\ControllerResolverInterface');
        $resolver->expects($this->once())->method('getController')->will($this->returnValue($controller));
        $resolver->expects($this->once())->method('getArguments')->will($this->returnValue(array()));

        return new HttpKernel($dispatcher, $resolver);
    }
}

class EventSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return array('foo' => 'call');
    }
}
PK��Z���!/
/
Ytest/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/FragmentListenerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\EventListener;

use Symfony\Component\HttpKernel\EventListener\FragmentListener;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\UriSigner;

class FragmentListenerTest extends \PHPUnit_Framework_TestCase
{
    public function testOnlyTriggeredOnFragmentRoute()
    {
        $request = Request::create('http://example.com/foo?_path=foo%3Dbar%26_controller%3Dfoo');

        $listener = new FragmentListener(new UriSigner('foo'));
        $event = $this->createGetResponseEvent($request);

        $expected = $request->attributes->all();

        $listener->onKernelRequest($event);

        $this->assertEquals($expected, $request->attributes->all());
        $this->assertTrue($request->query->has('_path'));
    }

    /**
     * @expectedException \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
     */
    public function testAccessDeniedWithNonSafeMethods()
    {
        $request = Request::create('http://example.com/_fragment', 'POST');

        $listener = new FragmentListener(new UriSigner('foo'));
        $event = $this->createGetResponseEvent($request);

        $listener->onKernelRequest($event);
    }

    /**
     * @expectedException \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
     */
    public function testAccessDeniedWithNonLocalIps()
    {
        $request = Request::create('http://example.com/_fragment', 'GET', array(), array(), array(), array('REMOTE_ADDR' => '10.0.0.1'));

        $listener = new FragmentListener(new UriSigner('foo'));
        $event = $this->createGetResponseEvent($request);

        $listener->onKernelRequest($event);
    }

    /**
     * @expectedException \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
     */
    public function testAccessDeniedWithWrongSignature()
    {
        $request = Request::create('http://example.com/_fragment', 'GET', array(), array(), array(), array('REMOTE_ADDR' => '10.0.0.1'));

        $listener = new FragmentListener(new UriSigner('foo'));
        $event = $this->createGetResponseEvent($request);

        $listener->onKernelRequest($event);
    }

    public function testWithSignature()
    {
        $signer = new UriSigner('foo');
        $request = Request::create($signer->sign('http://example.com/_fragment?_path=foo%3Dbar%26_controller%3Dfoo'), 'GET', array(), array(), array(), array('REMOTE_ADDR' => '10.0.0.1'));

        $listener = new FragmentListener($signer);
        $event = $this->createGetResponseEvent($request);

        $listener->onKernelRequest($event);

        $this->assertEquals(array('foo' => 'bar', '_controller' => 'foo'), $request->attributes->get('_route_params'));
        $this->assertFalse($request->query->has('_path'));
    }

    private function createGetResponseEvent(Request $request)
    {
        return new GetResponseEvent($this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'), $request, HttpKernelInterface::MASTER_REQUEST);
    }
}
PK��Z�W:ttZtest/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/ExceptionListenerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\EventListener;

use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\EventListener\ExceptionListener;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Tests\Logger;

/**
 * ExceptionListenerTest
 *
 * @author Robert Schönthal <seroscho@googlemail.com>
 */
class ExceptionListenerTest extends \PHPUnit_Framework_TestCase
{
    public function testConstruct()
    {
        $logger = new TestLogger();
        $l = new ExceptionListener('foo', $logger);

        $_logger = new \ReflectionProperty(get_class($l), 'logger');
        $_logger->setAccessible(true);
        $_controller = new \ReflectionProperty(get_class($l), 'controller');
        $_controller->setAccessible(true);

        $this->assertSame($logger, $_logger->getValue($l));
        $this->assertSame('foo', $_controller->getValue($l));
    }

    /**
     * @dataProvider provider
     */
    public function testHandleWithoutLogger($event, $event2)
    {
        // store the current error_log, and disable it temporarily
        $errorLog = ini_set('error_log', file_exists('/dev/null') ? '/dev/null' : 'nul');

        $l = new ExceptionListener('foo');
        $l->onKernelException($event);

        $this->assertEquals(new Response('foo'), $event->getResponse());

        try {
            $l->onKernelException($event2);
        } catch (\Exception $e) {
            $this->assertSame('foo', $e->getMessage());
        }

        // restore the old error_log
        ini_set('error_log', $errorLog);
    }

    /**
     * @dataProvider provider
     */
    public function testHandleWithLogger($event, $event2)
    {
        $logger = new TestLogger();

        $l = new ExceptionListener('foo', $logger);
        $l->onKernelException($event);

        $this->assertEquals(new Response('foo'), $event->getResponse());

        try {
            $l->onKernelException($event2);
        } catch (\Exception $e) {
            $this->assertSame('foo', $e->getMessage());
        }

        $this->assertEquals(3, $logger->countErrors());
        $this->assertCount(3, $logger->getLogs('critical'));
    }

    public function provider()
    {
        if (!class_exists('Symfony\Component\HttpFoundation\Request')) {
            return array(array(null, null));
        }

        $request = new Request();
        $exception = new \Exception('foo');
        $event = new GetResponseForExceptionEvent(new TestKernel(), $request, 'foo', $exception);
        $event2 = new GetResponseForExceptionEvent(new TestKernelThatThrowsException(), $request, 'foo', $exception);

        return array(
            array($event, $event2)
        );
    }

    public function testSubRequestFormat()
    {
        $listener = new ExceptionListener('foo', $this->getMock('Psr\Log\LoggerInterface'));

        $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
        $kernel->expects($this->once())->method('handle')->will($this->returnCallback(function (Request $request) {
            return new Response($request->getRequestFormat());
        }));

        $request = Request::create('/');
        $request->setRequestFormat('xml');

        $event = new GetResponseForExceptionEvent($kernel, $request, 'foo', new \Exception('foo'));
        $listener->onKernelException($event);

        $response = $event->getResponse();
        $this->assertEquals('xml', $response->getContent());
    }
}

class TestLogger extends Logger implements DebugLoggerInterface
{
    public function countErrors()
    {
        return count($this->logs['critical']);
    }
}

class TestKernel implements HttpKernelInterface
{
    public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true)
    {
        return new Response('foo');
    }
}

class TestKernelThatThrowsException implements HttpKernelInterface
{
    public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true)
    {
        throw new \Exception('bar');
    }
}
PK��Z(��kkYtest/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/ProfilerListenerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\EventListener;

use Symfony\Component\HttpKernel\EventListener\ProfilerListener;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpKernel\Kernel;

class ProfilerListenerTest extends \PHPUnit_Framework_TestCase
{
    /**
     * Test to ensure BC without RequestStack
     *
     * @deprecated Deprecated since version 2.4, to be removed in 3.0.
     */
    public function testEventsWithoutRequestStack()
    {
        $profile = $this->getMockBuilder('Symfony\Component\HttpKernel\Profiler\Profile')
            ->disableOriginalConstructor()
            ->getMock();

        $profiler = $this->getMockBuilder('Symfony\Component\HttpKernel\Profiler\Profiler')
            ->disableOriginalConstructor()
            ->getMock();
        $profiler->expects($this->once())
            ->method('collect')
            ->will($this->returnValue($profile));

        $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');

        $request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')
            ->disableOriginalConstructor()
            ->getMock();

        $response = $this->getMockBuilder('Symfony\Component\HttpFoundation\Response')
            ->disableOriginalConstructor()
            ->getMock();

        $listener = new ProfilerListener($profiler);
        $listener->onKernelRequest(new GetResponseEvent($kernel, $request, Kernel::MASTER_REQUEST));
        $listener->onKernelResponse(new FilterResponseEvent($kernel, $request, Kernel::MASTER_REQUEST, $response));
        $listener->onKernelTerminate(new PostResponseEvent($kernel, $request, $response));
    }

    /**
     * Test a master and sub request with an exception and `onlyException` profiler option enabled.
     */
    public function testKernelTerminate()
    {
        $profile = $this->getMockBuilder('Symfony\Component\HttpKernel\Profiler\Profile')
            ->disableOriginalConstructor()
            ->getMock();

        $profiler = $this->getMockBuilder('Symfony\Component\HttpKernel\Profiler\Profiler')
            ->disableOriginalConstructor()
            ->getMock();

        $profiler->expects($this->once())
            ->method('collect')
            ->will($this->returnValue($profile));

        $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');

        $masterRequest = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')
            ->disableOriginalConstructor()
            ->getMock();

        $subRequest =  $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')
            ->disableOriginalConstructor()
            ->getMock();

        $response = $this->getMockBuilder('Symfony\Component\HttpFoundation\Response')
            ->disableOriginalConstructor()
            ->getMock();

        $onlyException = true;
        $listener      = new ProfilerListener($profiler, null, $onlyException);

        // master request
        $listener->onKernelRequest(new GetResponseEvent($kernel, $masterRequest, Kernel::MASTER_REQUEST));
        $listener->onKernelResponse(new FilterResponseEvent($kernel, $masterRequest, Kernel::MASTER_REQUEST, $response));

        // sub request
        $listener->onKernelRequest(new GetResponseEvent($kernel, $subRequest, Kernel::SUB_REQUEST));
        $listener->onKernelException(new GetResponseForExceptionEvent($kernel, $subRequest, Kernel::SUB_REQUEST, new HttpException(404)));
        $listener->onKernelResponse(new FilterResponseEvent($kernel, $subRequest, Kernel::SUB_REQUEST, $response));

        $listener->onKernelTerminate(new PostResponseEvent($kernel, $masterRequest, $response));
    }
}
PK��Z=v?�
�
Ttest/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/EsiListenerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\EventListener;

use Symfony\Component\HttpKernel\HttpCache\Esi;
use Symfony\Component\HttpKernel\EventListener\EsiListener;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\EventDispatcher\EventDispatcher;

class EsiListenerTest extends \PHPUnit_Framework_TestCase
{
    public function testFilterDoesNothingForSubRequests()
    {
        $dispatcher = new EventDispatcher();
        $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
        $response = new Response('foo <esi:include src="" />');
        $listener = new EsiListener(new Esi());

        $dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'onKernelResponse'));
        $event = new FilterResponseEvent($kernel, new Request(), HttpKernelInterface::SUB_REQUEST, $response);
        $dispatcher->dispatch(KernelEvents::RESPONSE, $event);

        $this->assertEquals('', $event->getResponse()->headers->get('Surrogate-Control'));
    }

    public function testFilterWhenThereIsSomeEsiIncludes()
    {
        $dispatcher = new EventDispatcher();
        $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
        $response = new Response('foo <esi:include src="" />');
        $listener = new EsiListener(new Esi());

        $dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'onKernelResponse'));
        $event = new FilterResponseEvent($kernel, new Request(), HttpKernelInterface::MASTER_REQUEST, $response);
        $dispatcher->dispatch(KernelEvents::RESPONSE, $event);

        $this->assertEquals('content="ESI/1.0"', $event->getResponse()->headers->get('Surrogate-Control'));
    }

    public function testFilterWhenThereIsNoEsiIncludes()
    {
        $dispatcher = new EventDispatcher();
        $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
        $response = new Response('foo');
        $listener = new EsiListener(new Esi());

        $dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'onKernelResponse'));
        $event = new FilterResponseEvent($kernel, new Request(), HttpKernelInterface::MASTER_REQUEST, $response);
        $dispatcher->dispatch(KernelEvents::RESPONSE, $event);

        $this->assertEquals('', $event->getResponse()->headers->get('Surrogate-Control'));
    }
}
PK��Zp�66Wtest/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\EventListener;

use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\EventListener\RouterListener;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Routing\RequestContext;

class RouterListenerTest extends \PHPUnit_Framework_TestCase
{
    private $requestStack;

    public function setUp()
    {
        $this->requestStack = $this->getMock('Symfony\Component\HttpFoundation\RequestStack', array(), array(), '', false);
    }

    /**
     * @dataProvider getPortData
     */
    public function testPort($defaultHttpPort, $defaultHttpsPort, $uri, $expectedHttpPort, $expectedHttpsPort)
    {
        $urlMatcher = $this->getMockBuilder('Symfony\Component\Routing\Matcher\UrlMatcherInterface')
                             ->disableOriginalConstructor()
                             ->getMock();
        $context = new RequestContext();
        $context->setHttpPort($defaultHttpPort);
        $context->setHttpsPort($defaultHttpsPort);
        $urlMatcher->expects($this->any())
                     ->method('getContext')
                     ->will($this->returnValue($context));

        $listener = new RouterListener($urlMatcher, null, null, $this->requestStack);
        $event = $this->createGetResponseEventForUri($uri);
        $listener->onKernelRequest($event);

        $this->assertEquals($expectedHttpPort, $context->getHttpPort());
        $this->assertEquals($expectedHttpsPort, $context->getHttpsPort());
        $this->assertEquals(0 === strpos($uri, 'https') ? 'https' : 'http', $context->getScheme());
    }

    public function getPortData()
    {
        return array(
            array(80, 443, 'http://localhost/', 80, 443),
            array(80, 443, 'http://localhost:90/', 90, 443),
            array(80, 443, 'https://localhost/', 80, 443),
            array(80, 443, 'https://localhost:90/', 80, 90),
        );
    }

    /**
     * @param string $uri
     *
     * @return GetResponseEvent
     */
    private function createGetResponseEventForUri($uri)
    {
        $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
        $request = Request::create($uri);
        $request->attributes->set('_controller', null); // Prevents going in to routing process

        return new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST);
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testInvalidMatcher()
    {
        new RouterListener(new \stdClass(), null, null, $this->requestStack);
    }

    public function testRequestMatcher()
    {
        $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
        $request = Request::create('http://localhost/');
        $event = new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST);

        $requestMatcher = $this->getMock('Symfony\Component\Routing\Matcher\RequestMatcherInterface');
        $requestMatcher->expects($this->once())
                       ->method('matchRequest')
                       ->with($this->isInstanceOf('Symfony\Component\HttpFoundation\Request'))
                       ->will($this->returnValue(array()));

        $listener = new RouterListener($requestMatcher, new RequestContext(), null, $this->requestStack);
        $listener->onKernelRequest($event);
    }

    public function testSubRequestWithDifferentMethod()
    {
        $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
        $request = Request::create('http://localhost/', 'post');
        $event = new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST);

        $requestMatcher = $this->getMock('Symfony\Component\Routing\Matcher\RequestMatcherInterface');
        $requestMatcher->expects($this->any())
                       ->method('matchRequest')
                       ->with($this->isInstanceOf('Symfony\Component\HttpFoundation\Request'))
                       ->will($this->returnValue(array()));

        $context = new RequestContext();
        $requestMatcher->expects($this->any())
                       ->method('getContext')
                       ->will($this->returnValue($context));

        $listener = new RouterListener($requestMatcher, new RequestContext(), null, $this->requestStack);
        $listener->onKernelRequest($event);

        // sub-request with another HTTP method
        $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
        $request = Request::create('http://localhost/', 'get');
        $event = new GetResponseEvent($kernel, $request, HttpKernelInterface::SUB_REQUEST);

        $listener->onKernelRequest($event);

        $this->assertEquals('GET', $context->getMethod());
    }
}
PK��Z���uu\test/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/TestSessionListenerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\EventListener;

use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpFoundation\Session\SessionInterface;

/**
 * SessionListenerTest.
 *
 * Tests SessionListener.
 *
 * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
 */
class TestSessionListenerTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var TestSessionListener
     */
    private $listener;

    /**
     * @var SessionInterface
     */
    private $session;

    protected function setUp()
    {
        $this->listener = $this->getMockForAbstractClass('Symfony\Component\HttpKernel\EventListener\TestSessionListener');
        $this->session  = $this->getSession();
    }

    public function testShouldSaveMasterRequestSession()
    {
        $this->sessionHasBeenStarted();
        $this->sessionMustBeSaved();

        $this->filterResponse(new Request());
    }

    public function testShouldNotSaveSubRequestSession()
    {
        $this->sessionMustNotBeSaved();

        $this->filterResponse(new Request(), HttpKernelInterface::SUB_REQUEST);
    }

    public function testDoesNotDeleteCookieIfUsingSessionLifetime()
    {
        $this->sessionHasBeenStarted();

        $params = session_get_cookie_params();
        session_set_cookie_params(0, $params['path'], $params['domain'], $params['secure'], $params['httponly']);

        $response = $this->filterResponse(new Request(), HttpKernelInterface::MASTER_REQUEST);
        $cookies = $response->headers->getCookies();

        $this->assertEquals(0, reset($cookies)->getExpiresTime());
    }

    public function testUnstartedSessionIsNotSave()
    {
        $this->sessionHasNotBeenStarted();
        $this->sessionMustNotBeSaved();

        $this->filterResponse(new Request());
    }

    private function filterResponse(Request $request, $type = HttpKernelInterface::MASTER_REQUEST)
    {
        $request->setSession($this->session);
        $response = new Response();
        $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
        $event = new FilterResponseEvent($kernel, $request, $type, $response);

        $this->listener->onKernelResponse($event);

        $this->assertSame($response, $event->getResponse());

        return $response;
    }

    private function sessionMustNotBeSaved()
    {
        $this->session->expects($this->never())
            ->method('save');
    }

    private function sessionMustBeSaved()
    {
        $this->session->expects($this->once())
            ->method('save');
    }

    private function sessionHasBeenStarted()
    {
        $this->session->expects($this->once())
            ->method('isStarted')
            ->will($this->returnValue(true));
    }

    private function sessionHasNotBeenStarted()
    {
        $this->session->expects($this->once())
            ->method('isStarted')
            ->will($this->returnValue(false));
    }

    private function getSession()
    {
        $mock = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\Session')
            ->disableOriginalConstructor()
            ->getMock();

        // set return value for getName()
        $mock->expects($this->any())->method('getName')->will($this->returnValue('MOCKSESSID'));

        return $mock;
    }
}
PK��Z�,ph
h
Ytest/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/ResponseListenerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\EventListener;

use Symfony\Component\HttpKernel\EventListener\ResponseListener;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventDispatcher;

class ResponseListenerTest extends \PHPUnit_Framework_TestCase
{
    private $dispatcher;

    private $kernel;

    protected function setUp()
    {
        $this->dispatcher = new EventDispatcher();
        $listener = new ResponseListener('UTF-8');
        $this->dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'onKernelResponse'));

        $this->kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');

    }

    protected function tearDown()
    {
        $this->dispatcher = null;
        $this->kernel = null;
    }

    public function testFilterDoesNothingForSubRequests()
    {
        $response = new Response('foo');

        $event = new FilterResponseEvent($this->kernel, new Request(), HttpKernelInterface::SUB_REQUEST, $response);
        $this->dispatcher->dispatch(KernelEvents::RESPONSE, $event);

        $this->assertEquals('', $event->getResponse()->headers->get('content-type'));
    }

    public function testFilterSetsNonDefaultCharsetIfNotOverridden()
    {
        $listener = new ResponseListener('ISO-8859-15');
        $this->dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'onKernelResponse'), 1);

        $response = new Response('foo');

        $event = new FilterResponseEvent($this->kernel, Request::create('/'), HttpKernelInterface::MASTER_REQUEST, $response);
        $this->dispatcher->dispatch(KernelEvents::RESPONSE, $event);

        $this->assertEquals('ISO-8859-15', $response->getCharset());
    }

    public function testFilterDoesNothingIfCharsetIsOverridden()
    {
        $listener = new ResponseListener('ISO-8859-15');
        $this->dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'onKernelResponse'), 1);

        $response = new Response('foo');
        $response->setCharset('ISO-8859-1');

        $event = new FilterResponseEvent($this->kernel, Request::create('/'), HttpKernelInterface::MASTER_REQUEST, $response);
        $this->dispatcher->dispatch(KernelEvents::RESPONSE, $event);

        $this->assertEquals('ISO-8859-1', $response->getCharset());
    }

    public function testFiltersSetsNonDefaultCharsetIfNotOverriddenOnNonTextContentType()
    {
        $listener = new ResponseListener('ISO-8859-15');
        $this->dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'onKernelResponse'), 1);

        $response = new Response('foo');
        $request = Request::create('/');
        $request->setRequestFormat('application/json');

        $event = new FilterResponseEvent($this->kernel, $request, HttpKernelInterface::MASTER_REQUEST, $response);
        $this->dispatcher->dispatch(KernelEvents::RESPONSE, $event);

        $this->assertEquals('ISO-8859-15', $response->getCharset());
    }
}
PK��ZK�(^��Wtest/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/LocaleListenerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\EventListener;

use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\EventListener\LocaleListener;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;

class LocaleListenerTest extends \PHPUnit_Framework_TestCase
{
    private $requestStack;

    protected function setUp()
    {
        $this->requestStack = $this->getMock('Symfony\Component\HttpFoundation\RequestStack', array(), array(), '', false);
    }

    public function testDefaultLocaleWithoutSession()
    {
        $listener = new LocaleListener('fr', null, $this->requestStack);
        $event = $this->getEvent($request = Request::create('/'));

        $listener->onKernelRequest($event);
        $this->assertEquals('fr', $request->getLocale());
    }

    public function testLocaleFromRequestAttribute()
    {
        $request = Request::create('/');
        session_name('foo');
        $request->cookies->set('foo', 'value');

        $request->attributes->set('_locale', 'es');
        $listener = new LocaleListener('fr', null, $this->requestStack);
        $event = $this->getEvent($request);

        $listener->onKernelRequest($event);
        $this->assertEquals('es', $request->getLocale());
    }

    public function testLocaleSetForRoutingContext()
    {
        // the request context is updated
        $context = $this->getMock('Symfony\Component\Routing\RequestContext');
        $context->expects($this->once())->method('setParameter')->with('_locale', 'es');

        $router = $this->getMock('Symfony\Component\Routing\Router', array('getContext'), array(), '', false);
        $router->expects($this->once())->method('getContext')->will($this->returnValue($context));

        $request = Request::create('/');

        $request->attributes->set('_locale', 'es');
        $listener = new LocaleListener('fr', $router, $this->requestStack);
        $listener->onKernelRequest($this->getEvent($request));
    }

    public function testRouterResetWithParentRequestOnKernelFinishRequest()
    {
        if (!class_exists('Symfony\Component\Routing\Router')) {
            $this->markTestSkipped('The "Routing" component is not available');
        }

        // the request context is updated
        $context = $this->getMock('Symfony\Component\Routing\RequestContext');
        $context->expects($this->once())->method('setParameter')->with('_locale', 'es');

        $router = $this->getMock('Symfony\Component\Routing\Router', array('getContext'), array(), '', false);
        $router->expects($this->once())->method('getContext')->will($this->returnValue($context));

        $parentRequest = Request::create('/');
        $parentRequest->setLocale('es');

        $this->requestStack->expects($this->once())->method('getParentRequest')->will($this->returnValue($parentRequest));

        $event = $this->getMock('Symfony\Component\HttpKernel\Event\FinishRequestEvent', array(), array(), '', false);

        $listener = new LocaleListener('fr', $router, $this->requestStack);
        $listener->onKernelFinishRequest($event);
    }

    public function testRequestLocaleIsNotOverridden()
    {
        $request = Request::create('/');
        $request->setLocale('de');
        $listener = new LocaleListener('fr', null, $this->requestStack);
        $event = $this->getEvent($request);

        $listener->onKernelRequest($event);
        $this->assertEquals('de', $request->getLocale());
    }

    private function getEvent(Request $request)
    {
        return new GetResponseEvent($this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'), $request, HttpKernelInterface::MASTER_REQUEST);
    }
}
PK��Z�o�M��\test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fragment/HIncludeFragmentRendererTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\Fragment;

use Symfony\Component\HttpKernel\Controller\ControllerReference;
use Symfony\Component\HttpKernel\Fragment\HIncludeFragmentRenderer;
use Symfony\Component\HttpKernel\UriSigner;
use Symfony\Component\HttpFoundation\Request;

class HIncludeFragmentRendererTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \LogicException
     */
    public function testRenderExceptionWhenControllerAndNoSigner()
    {
        $strategy = new HIncludeFragmentRenderer();
        $strategy->render(new ControllerReference('main_controller', array(), array()), Request::create('/'));
    }

    public function testRenderWithControllerAndSigner()
    {
        $strategy = new HIncludeFragmentRenderer(null, new UriSigner('foo'));

        $this->assertEquals('<hx:include src="/_fragment?_path=_format%3Dhtml%26_locale%3Den%26_controller%3Dmain_controller&amp;_hash=BP%2BOzCD5MRUI%2BHJpgPDOmoju00FnzLhP3TGcSHbbBLs%3D"></hx:include>', $strategy->render(new ControllerReference('main_controller', array(), array()), Request::create('/'))->getContent());
    }

    public function testRenderWithUri()
    {
        $strategy = new HIncludeFragmentRenderer();
        $this->assertEquals('<hx:include src="/foo"></hx:include>', $strategy->render('/foo', Request::create('/'))->getContent());

        $strategy = new HIncludeFragmentRenderer(null, new UriSigner('foo'));
        $this->assertEquals('<hx:include src="/foo"></hx:include>', $strategy->render('/foo', Request::create('/'))->getContent());
    }

    public function testRenderWithDefault()
    {
        // only default
        $strategy = new HIncludeFragmentRenderer();
        $this->assertEquals('<hx:include src="/foo">default</hx:include>', $strategy->render('/foo', Request::create('/'), array('default' => 'default'))->getContent());

        // only global default
        $strategy = new HIncludeFragmentRenderer(null, null, 'global_default');
        $this->assertEquals('<hx:include src="/foo">global_default</hx:include>', $strategy->render('/foo', Request::create('/'), array())->getContent());

        // global default and default
        $strategy = new HIncludeFragmentRenderer(null, null, 'global_default');
        $this->assertEquals('<hx:include src="/foo">default</hx:include>', $strategy->render('/foo', Request::create('/'), array('default' => 'default'))->getContent());
    }

    public function testRenderWithAttributesOptions()
    {
        // with id
        $strategy = new HIncludeFragmentRenderer();
        $this->assertEquals('<hx:include src="/foo" id="bar">default</hx:include>', $strategy->render('/foo', Request::create('/'), array('default' => 'default', 'id' => 'bar'))->getContent());

        // with attributes
        $strategy = new HIncludeFragmentRenderer();
        $this->assertEquals('<hx:include src="/foo" p1="v1" p2="v2">default</hx:include>', $strategy->render('/foo', Request::create('/'), array('default' => 'default', 'attributes' => array('p1' => 'v1', 'p2' => 'v2')))->getContent());

        // with id & attributes
        $strategy = new HIncludeFragmentRenderer();
        $this->assertEquals('<hx:include src="/foo" p1="v1" p2="v2" id="bar">default</hx:include>', $strategy->render('/foo', Request::create('/'), array('default' => 'default', 'id' => 'bar', 'attributes' => array('p1' => 'v1', 'p2' => 'v2')))->getContent());
    }

    public function testRenderWithDefaultText()
    {
        $engine = $this->getMock('Symfony\\Component\\Templating\\EngineInterface');
        $engine->expects($this->once())
            ->method('exists')
            ->with('default')
            ->will($this->throwException(new \InvalidArgumentException()));

        // only default
        $strategy = new HIncludeFragmentRenderer($engine);
        $this->assertEquals('<hx:include src="/foo">default</hx:include>', $strategy->render('/foo', Request::create('/'), array('default' => 'default'))->getContent());
    }
}
PK��Z�
��((\test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fragment/RoutableFragmentRendererTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\Fragment;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ControllerReference;

class RoutableFragmentRendererTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getGenerateFragmentUriData
     */
    public function testGenerateFragmentUri($uri, $controller)
    {
        $this->assertEquals($uri, $this->callGenerateFragmentUriMethod($controller, Request::create('/')));
    }

    /**
     * @dataProvider getGenerateFragmentUriData
     */
    public function testGenerateAbsoluteFragmentUri($uri, $controller)
    {
        $this->assertEquals('http://localhost'.$uri, $this->callGenerateFragmentUriMethod($controller, Request::create('/'), true));
    }

    public function getGenerateFragmentUriData()
    {
        return array(
            array('/_fragment?_path=_format%3Dhtml%26_locale%3Den%26_controller%3Dcontroller', new ControllerReference('controller', array(), array())),
            array('/_fragment?_path=_format%3Dxml%26_locale%3Den%26_controller%3Dcontroller', new ControllerReference('controller', array('_format' => 'xml'), array())),
            array('/_fragment?_path=foo%3Dfoo%26_format%3Djson%26_locale%3Den%26_controller%3Dcontroller', new ControllerReference('controller', array('foo' => 'foo', '_format' => 'json'), array())),
            array('/_fragment?bar=bar&_path=foo%3Dfoo%26_format%3Dhtml%26_locale%3Den%26_controller%3Dcontroller', new ControllerReference('controller', array('foo' => 'foo'), array('bar' => 'bar'))),
            array('/_fragment?foo=foo&_path=_format%3Dhtml%26_locale%3Den%26_controller%3Dcontroller', new ControllerReference('controller', array(), array('foo' => 'foo'))),
            array('/_fragment?_path=foo%255B0%255D%3Dfoo%26foo%255B1%255D%3Dbar%26_format%3Dhtml%26_locale%3Den%26_controller%3Dcontroller', new ControllerReference('controller', array('foo' => array('foo', 'bar')), array())),
        );
    }

    public function testGenerateFragmentUriWithARequest()
    {
        $request = Request::create('/');
        $request->attributes->set('_format', 'json');
        $request->setLocale('fr');
        $controller = new ControllerReference('controller', array(), array());

        $this->assertEquals('/_fragment?_path=_format%3Djson%26_locale%3Dfr%26_controller%3Dcontroller', $this->callGenerateFragmentUriMethod($controller, $request));
    }

    /**
     * @expectedException LogicException
     * @dataProvider      getGenerateFragmentUriDataWithNonScalar
     */
    public function testGenerateFragmentUriWithNonScalar($controller)
    {
        $this->callGenerateFragmentUriMethod($controller, Request::create('/'));
    }

    public function getGenerateFragmentUriDataWithNonScalar()
    {
        return array(
            array(new ControllerReference('controller', array('foo' => new Foo(), 'bar' => 'bar'), array())),
            array(new ControllerReference('controller', array('foo' => array('foo' => 'foo'), 'bar' => array('bar' => new Foo())), array())),
        );
    }

    private function callGenerateFragmentUriMethod(ControllerReference $reference, Request $request, $absolute = false)
    {
        $renderer = $this->getMockForAbstractClass('Symfony\Component\HttpKernel\Fragment\RoutableFragmentRenderer');
        $r = new \ReflectionObject($renderer);
        $m = $r->getMethod('generateFragmentUri');
        $m->setAccessible(true);

        return $m->invoke($renderer, $reference, $request, $absolute);
    }
}

class Foo
{
    public $foo;

    public function getFoo()
    {
        return $this->foo;
    }
}
PK��Z�v��Ztest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\Fragment;

use Symfony\Component\HttpKernel\Controller\ControllerReference;
use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\HttpKernel\Fragment\InlineFragmentRenderer;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\EventDispatcher\EventDispatcher;

class InlineFragmentRendererTest extends \PHPUnit_Framework_TestCase
{
    public function testRender()
    {
        $strategy = new InlineFragmentRenderer($this->getKernel($this->returnValue(new Response('foo'))));

        $this->assertEquals('foo', $strategy->render('/', Request::create('/'))->getContent());
    }

    public function testRenderWithControllerReference()
    {
        $strategy = new InlineFragmentRenderer($this->getKernel($this->returnValue(new Response('foo'))));

        $this->assertEquals('foo', $strategy->render(new ControllerReference('main_controller', array(), array()), Request::create('/'))->getContent());
    }

    public function testRenderWithObjectsAsAttributes()
    {
        $object = new \stdClass();

        $subRequest = Request::create('/_fragment?_path=_format%3Dhtml%26_locale%3Den%26_controller%3Dmain_controller');
        $subRequest->attributes->replace(array('object' => $object, '_format' => 'html', '_controller' => 'main_controller', '_locale' => 'en'));
        $subRequest->headers->set('x-forwarded-for', array('127.0.0.1'));
        $subRequest->server->set('HTTP_X_FORWARDED_FOR', '127.0.0.1');

        $strategy = new InlineFragmentRenderer($this->getKernelExpectingRequest($subRequest));

        $strategy->render(new ControllerReference('main_controller', array('object' => $object), array()), Request::create('/'));
    }

    public function testRenderWithObjectsAsAttributesPassedAsObjectsInTheController()
    {
        $resolver = $this->getMock('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolver', array('getController'));
        $resolver
            ->expects($this->once())
            ->method('getController')
            ->will($this->returnValue(function (\stdClass $object, Bar $object1) {
                return new Response($object1->getBar());
            }))
        ;

        $kernel = new HttpKernel(new EventDispatcher(), $resolver);
        $renderer = new InlineFragmentRenderer($kernel);

        $response = $renderer->render(new ControllerReference('main_controller', array('object' => new \stdClass(), 'object1' => new Bar()), array()), Request::create('/'));
        $this->assertEquals('bar', $response->getContent());
    }

    public function testRenderWithTrustedHeaderDisabled()
    {
        $trustedHeaderName = Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP);

        Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, '');

        $strategy = new InlineFragmentRenderer($this->getKernelExpectingRequest(Request::create('/')));
        $strategy->render('/', Request::create('/'));

        Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, $trustedHeaderName);
    }

    /**
     * @expectedException \RuntimeException
     */
    public function testRenderExceptionNoIgnoreErrors()
    {
        $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
        $dispatcher->expects($this->never())->method('dispatch');

        $strategy = new InlineFragmentRenderer($this->getKernel($this->throwException(new \RuntimeException('foo'))), $dispatcher);

        $this->assertEquals('foo', $strategy->render('/', Request::create('/'))->getContent());
    }

    public function testRenderExceptionIgnoreErrors()
    {
        $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
        $dispatcher->expects($this->once())->method('dispatch')->with(KernelEvents::EXCEPTION);

        $strategy = new InlineFragmentRenderer($this->getKernel($this->throwException(new \RuntimeException('foo'))), $dispatcher);

        $this->assertEmpty($strategy->render('/', Request::create('/'), array('ignore_errors' => true))->getContent());
    }

    public function testRenderExceptionIgnoreErrorsWithAlt()
    {
        $strategy = new InlineFragmentRenderer($this->getKernel($this->onConsecutiveCalls(
            $this->throwException(new \RuntimeException('foo')),
            $this->returnValue(new Response('bar'))
        )));

        $this->assertEquals('bar', $strategy->render('/', Request::create('/'), array('ignore_errors' => true, 'alt' => '/foo'))->getContent());
    }

    private function getKernel($returnValue)
    {
        $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
        $kernel
            ->expects($this->any())
            ->method('handle')
            ->will($returnValue)
        ;

        return $kernel;
    }

    /**
     * Creates a Kernel expecting a request equals to $request
     * Allows delta in comparison in case REQUEST_TIME changed by 1 second
     */
    private function getKernelExpectingRequest(Request $request)
    {
        $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
        $kernel
            ->expects($this->any())
            ->method('handle')
            ->with($this->equalTo($request, 1))
        ;

        return $kernel;
    }

    public function testExceptionInSubRequestsDoesNotMangleOutputBuffers()
    {
        $resolver = $this->getMock('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface');
        $resolver
            ->expects($this->once())
            ->method('getController')
            ->will($this->returnValue(function () {
                ob_start();
                echo 'bar';
                throw new \RuntimeException();
            }))
        ;
        $resolver
            ->expects($this->once())
            ->method('getArguments')
            ->will($this->returnValue(array()))
        ;

        $kernel = new HttpKernel(new EventDispatcher(), $resolver);
        $renderer = new InlineFragmentRenderer($kernel);

        // simulate a main request with output buffering
        ob_start();
        echo 'Foo';

        // simulate a sub-request with output buffering and an exception
        $renderer->render('/', Request::create('/'), array('ignore_errors' => true));

        $this->assertEquals('Foo', ob_get_clean());
    }

    public function testESIHeaderIsKeptInSubrequest()
    {
        $expectedSubRequest = Request::create('/');
        $expectedSubRequest->headers->set('Surrogate-Capability', 'abc="ESI/1.0"');

        if (Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP)) {
            $expectedSubRequest->headers->set('x-forwarded-for', array('127.0.0.1'));
            $expectedSubRequest->server->set('HTTP_X_FORWARDED_FOR', '127.0.0.1');
        }

        $strategy = new InlineFragmentRenderer($this->getKernelExpectingRequest($expectedSubRequest));

        $request = Request::create('/');
        $request->headers->set('Surrogate-Capability', 'abc="ESI/1.0"');
        $strategy->render('/', $request);
    }

    public function testESIHeaderIsKeptInSubrequestWithTrustedHeaderDisabled()
    {
        $trustedHeaderName = Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP);
        Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, '');

        $this->testESIHeaderIsKeptInSubrequest();

        Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, $trustedHeaderName);
    }
}

class Bar
{
    public $bar = 'bar';

    public function getBar()
    {
        return $this->bar;
    }
}
PK��Z;����
�
Stest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fragment/FragmentHandlerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\Fragment;

use Symfony\Component\HttpKernel\Fragment\FragmentHandler;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class FragmentHandlerTest extends \PHPUnit_Framework_TestCase
{
    private $requestStack;

    public function setUp()
    {
        $this->requestStack = $this->getMockBuilder('Symfony\\Component\\HttpFoundation\\RequestStack')
            ->disableOriginalConstructor()
            ->getMock()
        ;
        $this->requestStack
            ->expects($this->any())
            ->method('getCurrentRequest')
            ->will($this->returnValue(Request::create('/')))
        ;
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testRenderWhenRendererDoesNotExist()
    {
        $handler = new FragmentHandler(array(), null, $this->requestStack);
        $handler->render('/', 'foo');
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testRenderWithUnknownRenderer()
    {
        $handler = $this->getHandler($this->returnValue(new Response('foo')));

        $handler->render('/', 'bar');
    }

    /**
     * @expectedException \RuntimeException
     * @expectedExceptionMessage Error when rendering "http://localhost/" (Status code is 404).
     */
    public function testDeliverWithUnsuccessfulResponse()
    {
        $handler = $this->getHandler($this->returnValue(new Response('foo', 404)));

        $handler->render('/', 'foo');
    }

    public function testRender()
    {
        $handler = $this->getHandler($this->returnValue(new Response('foo')), array('/', Request::create('/'), array('foo' => 'foo', 'ignore_errors' => true)));

        $this->assertEquals('foo', $handler->render('/', 'foo', array('foo' => 'foo')));
    }

    protected function getHandler($returnValue, $arguments = array())
    {
        $renderer = $this->getMock('Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface');
        $renderer
            ->expects($this->any())
            ->method('getName')
            ->will($this->returnValue('foo'))
        ;
        $e = $renderer
            ->expects($this->any())
            ->method('render')
            ->will($returnValue)
        ;

        if ($arguments) {
            call_user_func_array(array($e, 'with'), $arguments);
        }

        $handler = new FragmentHandler(array(), null, $this->requestStack);
        $handler->addRenderer($renderer);

        return $handler;
    }
}
PK��Z�҃��	�	Wtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fragment/EsiFragmentRendererTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\Fragment;

use Symfony\Component\HttpKernel\Controller\ControllerReference;
use Symfony\Component\HttpKernel\Fragment\EsiFragmentRenderer;
use Symfony\Component\HttpKernel\HttpCache\Esi;
use Symfony\Component\HttpFoundation\Request;

class EsiFragmentRendererTest extends \PHPUnit_Framework_TestCase
{
    public function testRenderFallbackToInlineStrategyIfNoRequest()
    {
        $strategy = new EsiFragmentRenderer(new Esi(), $this->getInlineStrategy(true));
        $strategy->render('/', Request::create('/'));
    }

    public function testRenderFallbackToInlineStrategyIfEsiNotSupported()
    {
        $strategy = new EsiFragmentRenderer(new Esi(), $this->getInlineStrategy(true));
        $strategy->render('/', Request::create('/'));
    }

    public function testRender()
    {
        $strategy = new EsiFragmentRenderer(new Esi(), $this->getInlineStrategy());

        $request = Request::create('/');
        $request->setLocale('fr');
        $request->headers->set('Surrogate-Capability', 'ESI/1.0');

        $this->assertEquals('<esi:include src="/" />', $strategy->render('/', $request)->getContent());
        $this->assertEquals("<esi:comment text=\"This is a comment\" />\n<esi:include src=\"/\" />", $strategy->render('/', $request, array('comment' => 'This is a comment'))->getContent());
        $this->assertEquals('<esi:include src="/" alt="foo" />', $strategy->render('/', $request, array('alt' => 'foo'))->getContent());
        $this->assertEquals('<esi:include src="/_fragment?_path=_format%3Dhtml%26_locale%3Dfr%26_controller%3Dmain_controller" alt="/_fragment?_path=_format%3Dhtml%26_locale%3Dfr%26_controller%3Dalt_controller" />', $strategy->render(new ControllerReference('main_controller', array(), array()), $request, array('alt' => new ControllerReference('alt_controller', array(), array())))->getContent());
    }

    private function getInlineStrategy($called = false)
    {
        $inline = $this->getMockBuilder('Symfony\Component\HttpKernel\Fragment\InlineFragmentRenderer')->disableOriginalConstructor()->getMock();

        if ($called) {
            $inline->expects($this->once())->method('render');
        }

        return $inline;
    }
}
PK��Zp����=test/HttpKernel/Symfony/Component/HttpKernel/Tests/Logger.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests;

use Psr\Log\LoggerInterface;

class Logger implements LoggerInterface
{
    protected $logs;

    public function __construct()
    {
        $this->clear();
    }

    public function getLogs($level = false)
    {
        return false === $level ? $this->logs : $this->logs[$level];
    }

    public function clear()
    {
        $this->logs = array(
            'emergency' => array(),
            'alert' => array(),
            'critical' => array(),
            'error' => array(),
            'warning' => array(),
            'notice' => array(),
            'info' => array(),
            'debug' => array(),
        );
    }

    public function log($level, $message, array $context = array())
    {
        $this->logs[$level][] = $message;
    }

    public function emergency($message, array $context = array())
    {
        $this->log('emergency', $message, $context);
    }

    public function alert($message, array $context = array())
    {
        $this->log('alert', $message, $context);
    }

    public function critical($message, array $context = array())
    {
        $this->log('critical', $message, $context);
    }

    public function error($message, array $context = array())
    {
        $this->log('error', $message, $context);
    }

    public function warning($message, array $context = array())
    {
        $this->log('warning', $message, $context);
    }

    public function notice($message, array $context = array())
    {
        $this->log('notice', $message, $context);
    }

    public function info($message, array $context = array())
    {
        $this->log('info', $message, $context);
    }

    public function debug($message, array $context = array())
    {
        $this->log('debug', $message, $context);
    }

    /**
     * @deprecated
     */
    public function emerg($message, array $context = array())
    {
        trigger_error('Use emergency() which is PSR-3 compatible', E_USER_DEPRECATED);

        $this->log('emergency', $message, $context);
    }

    /**
     * @deprecated
     */
    public function crit($message, array $context = array())
    {
        trigger_error('Use critical() which is PSR-3 compatible', E_USER_DEPRECATED);

        $this->log('critical', $message, $context);
    }

    /**
     * @deprecated
     */
    public function err($message, array $context = array())
    {
        trigger_error('Use error() which is PSR-3 compatible', E_USER_DEPRECATED);

        $this->log('error', $message, $context);
    }

    /**
     * @deprecated
     */
    public function warn($message, array $context = array())
    {
        trigger_error('Use warning() which is PSR-3 compatible', E_USER_DEPRECATED);

        $this->log('warning', $message, $context);
    }
}
PK��Z��m*����Ntest/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\HttpCache;

use Symfony\Component\HttpKernel\HttpCache\HttpCache;
use Symfony\Component\HttpKernel\HttpCache\StoreInterface;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class HttpCacheTest extends HttpCacheTestCase
{
    public function testTerminateDelegatesTerminationOnlyForTerminableInterface()
    {
        $storeMock = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\HttpCache\\StoreInterface')
            ->disableOriginalConstructor()
            ->getMock();

        // does not implement TerminableInterface
        $kernelMock = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\HttpKernelInterface')
            ->disableOriginalConstructor()
            ->getMock();

        $kernelMock->expects($this->never())
            ->method('terminate');

        $kernel = new HttpCache($kernelMock, $storeMock);
        $kernel->terminate(Request::create('/'), new Response());

        // implements TerminableInterface
        $kernelMock = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\Kernel')
            ->disableOriginalConstructor()
            ->setMethods(array('terminate', 'registerBundles', 'registerContainerConfiguration'))
            ->getMock();

        $kernelMock->expects($this->once())
            ->method('terminate');

        $kernel = new HttpCache($kernelMock, $storeMock);
        $kernel->terminate(Request::create('/'), new Response());
    }

    public function testPassesOnNonGetHeadRequests()
    {
        $this->setNextResponse(200);
        $this->request('POST', '/');
        $this->assertHttpKernelIsCalled();
        $this->assertResponseOk();
        $this->assertTraceContains('pass');
        $this->assertFalse($this->response->headers->has('Age'));
    }

    public function testInvalidatesOnPostPutDeleteRequests()
    {
        foreach (array('post', 'put', 'delete') as $method) {
            $this->setNextResponse(200);
            $this->request($method, '/');

            $this->assertHttpKernelIsCalled();
            $this->assertResponseOk();
            $this->assertTraceContains('invalidate');
            $this->assertTraceContains('pass');
        }
    }

    public function testDoesNotCacheWithAuthorizationRequestHeaderAndNonPublicResponse()
    {
        $this->setNextResponse(200, array('ETag' => '"Foo"'));
        $this->request('GET', '/', array('HTTP_AUTHORIZATION' => 'basic foobarbaz'));

        $this->assertHttpKernelIsCalled();
        $this->assertResponseOk();
        $this->assertEquals('private', $this->response->headers->get('Cache-Control'));

        $this->assertTraceContains('miss');
        $this->assertTraceNotContains('store');
        $this->assertFalse($this->response->headers->has('Age'));
    }

    public function testDoesCacheWithAuthorizationRequestHeaderAndPublicResponse()
    {
        $this->setNextResponse(200, array('Cache-Control' => 'public', 'ETag' => '"Foo"'));
        $this->request('GET', '/', array('HTTP_AUTHORIZATION' => 'basic foobarbaz'));

        $this->assertHttpKernelIsCalled();
        $this->assertResponseOk();
        $this->assertTraceContains('miss');
        $this->assertTraceContains('store');
        $this->assertTrue($this->response->headers->has('Age'));
        $this->assertEquals('public', $this->response->headers->get('Cache-Control'));
    }

    public function testDoesNotCacheWithCookieHeaderAndNonPublicResponse()
    {
        $this->setNextResponse(200, array('ETag' => '"Foo"'));
        $this->request('GET', '/', array(), array('foo' => 'bar'));

        $this->assertHttpKernelIsCalled();
        $this->assertResponseOk();
        $this->assertEquals('private', $this->response->headers->get('Cache-Control'));
        $this->assertTraceContains('miss');
        $this->assertTraceNotContains('store');
        $this->assertFalse($this->response->headers->has('Age'));
    }

    public function testDoesNotCacheRequestsWithACookieHeader()
    {
        $this->setNextResponse(200);
        $this->request('GET', '/', array(), array('foo' => 'bar'));

        $this->assertHttpKernelIsCalled();
        $this->assertResponseOk();
        $this->assertEquals('private', $this->response->headers->get('Cache-Control'));
        $this->assertTraceContains('miss');
        $this->assertTraceNotContains('store');
        $this->assertFalse($this->response->headers->has('Age'));
    }

    public function testRespondsWith304WhenIfModifiedSinceMatchesLastModified()
    {
        $time = new \DateTime();

        $this->setNextResponse(200, array('Cache-Control' => 'public', 'Last-Modified' => $time->format(DATE_RFC2822), 'Content-Type' => 'text/plain'), 'Hello World');
        $this->request('GET', '/', array('HTTP_IF_MODIFIED_SINCE' => $time->format(DATE_RFC2822)));

        $this->assertHttpKernelIsCalled();
        $this->assertEquals(304, $this->response->getStatusCode());
        $this->assertEquals('', $this->response->headers->get('Content-Type'));
        $this->assertEmpty($this->response->getContent());
        $this->assertTraceContains('miss');
        $this->assertTraceContains('store');
    }

    public function testRespondsWith304WhenIfNoneMatchMatchesETag()
    {
        $this->setNextResponse(200, array('Cache-Control' => 'public', 'ETag' => '12345', 'Content-Type' => 'text/plain'), 'Hello World');
        $this->request('GET', '/', array('HTTP_IF_NONE_MATCH' => '12345'));

        $this->assertHttpKernelIsCalled();
        $this->assertEquals(304, $this->response->getStatusCode());
        $this->assertEquals('', $this->response->headers->get('Content-Type'));
        $this->assertTrue($this->response->headers->has('ETag'));
        $this->assertEmpty($this->response->getContent());
        $this->assertTraceContains('miss');
        $this->assertTraceContains('store');
    }

    public function testRespondsWith304OnlyIfIfNoneMatchAndIfModifiedSinceBothMatch()
    {
        $time = new \DateTime();

        $this->setNextResponse(200, array(), '', function ($request, $response) use ($time) {
            $response->setStatusCode(200);
            $response->headers->set('ETag', '12345');
            $response->headers->set('Last-Modified', $time->format(DATE_RFC2822));
            $response->headers->set('Content-Type', 'text/plain');
            $response->setContent('Hello World');
        });

        // only ETag matches
        $t = \DateTime::createFromFormat('U', time() - 3600);
        $this->request('GET', '/', array('HTTP_IF_NONE_MATCH' => '12345', 'HTTP_IF_MODIFIED_SINCE' => $t->format(DATE_RFC2822)));
        $this->assertHttpKernelIsCalled();
        $this->assertEquals(200, $this->response->getStatusCode());

        // only Last-Modified matches
        $this->request('GET', '/', array('HTTP_IF_NONE_MATCH' => '1234', 'HTTP_IF_MODIFIED_SINCE' => $time->format(DATE_RFC2822)));
        $this->assertHttpKernelIsCalled();
        $this->assertEquals(200, $this->response->getStatusCode());

        // Both matches
        $this->request('GET', '/', array('HTTP_IF_NONE_MATCH' => '12345', 'HTTP_IF_MODIFIED_SINCE' => $time->format(DATE_RFC2822)));
        $this->assertHttpKernelIsCalled();
        $this->assertEquals(304, $this->response->getStatusCode());
    }

    public function testValidatesPrivateResponsesCachedOnTheClient()
    {
        $this->setNextResponse(200, array(), '', function ($request, $response) {
            $etags = preg_split('/\s*,\s*/', $request->headers->get('IF_NONE_MATCH'));
            if ($request->cookies->has('authenticated')) {
                $response->headers->set('Cache-Control', 'private, no-store');
                $response->setETag('"private tag"');
                if (in_array('"private tag"', $etags)) {
                    $response->setStatusCode(304);
                } else {
                    $response->setStatusCode(200);
                    $response->headers->set('Content-Type', 'text/plain');
                    $response->setContent('private data');
                }
            } else {
                $response->headers->set('Cache-Control', 'public');
                $response->setETag('"public tag"');
                if (in_array('"public tag"', $etags)) {
                    $response->setStatusCode(304);
                } else {
                    $response->setStatusCode(200);
                    $response->headers->set('Content-Type', 'text/plain');
                    $response->setContent('public data');
                }
            }
        });

        $this->request('GET', '/');
        $this->assertHttpKernelIsCalled();
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertEquals('"public tag"', $this->response->headers->get('ETag'));
        $this->assertEquals('public data', $this->response->getContent());
        $this->assertTraceContains('miss');
        $this->assertTraceContains('store');

        $this->request('GET', '/', array(), array('authenticated' => ''));
        $this->assertHttpKernelIsCalled();
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertEquals('"private tag"', $this->response->headers->get('ETag'));
        $this->assertEquals('private data', $this->response->getContent());
        $this->assertTraceContains('stale');
        $this->assertTraceContains('invalid');
        $this->assertTraceNotContains('store');
    }

    public function testStoresResponsesWhenNoCacheRequestDirectivePresent()
    {
        $time = \DateTime::createFromFormat('U', time() + 5);

        $this->setNextResponse(200, array('Cache-Control' => 'public', 'Expires' => $time->format(DATE_RFC2822)));
        $this->request('GET', '/', array('HTTP_CACHE_CONTROL' => 'no-cache'));

        $this->assertHttpKernelIsCalled();
        $this->assertTraceContains('store');
        $this->assertTrue($this->response->headers->has('Age'));
    }

    public function testReloadsResponsesWhenCacheHitsButNoCacheRequestDirectivePresentWhenAllowReloadIsSetTrue()
    {
        $count = 0;

        $this->setNextResponse(200, array('Cache-Control' => 'public, max-age=10000'), '', function ($request, $response) use (&$count) {
            ++$count;
            $response->setContent(1 == $count ? 'Hello World' : 'Goodbye World');
        });

        $this->request('GET', '/');
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertEquals('Hello World', $this->response->getContent());
        $this->assertTraceContains('store');

        $this->request('GET', '/');
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertEquals('Hello World', $this->response->getContent());
        $this->assertTraceContains('fresh');

        $this->cacheConfig['allow_reload'] = true;
        $this->request('GET', '/', array('HTTP_CACHE_CONTROL' => 'no-cache'));
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertEquals('Goodbye World', $this->response->getContent());
        $this->assertTraceContains('reload');
        $this->assertTraceContains('store');
    }

    public function testDoesNotReloadResponsesWhenAllowReloadIsSetFalseDefault()
    {
        $count = 0;

        $this->setNextResponse(200, array('Cache-Control' => 'public, max-age=10000'), '', function ($request, $response) use (&$count) {
            ++$count;
            $response->setContent(1 == $count ? 'Hello World' : 'Goodbye World');
        });

        $this->request('GET', '/');
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertEquals('Hello World', $this->response->getContent());
        $this->assertTraceContains('store');

        $this->request('GET', '/');
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertEquals('Hello World', $this->response->getContent());
        $this->assertTraceContains('fresh');

        $this->cacheConfig['allow_reload'] = false;
        $this->request('GET', '/', array('HTTP_CACHE_CONTROL' => 'no-cache'));
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertEquals('Hello World', $this->response->getContent());
        $this->assertTraceNotContains('reload');

        $this->request('GET', '/', array('HTTP_CACHE_CONTROL' => 'no-cache'));
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertEquals('Hello World', $this->response->getContent());
        $this->assertTraceNotContains('reload');
    }

    public function testRevalidatesFreshCacheEntryWhenMaxAgeRequestDirectiveIsExceededWhenAllowRevalidateOptionIsSetTrue()
    {
        $count = 0;

        $this->setNextResponse(200, array(), '', function ($request, $response) use (&$count) {
            ++$count;
            $response->headers->set('Cache-Control', 'public, max-age=10000');
            $response->setETag($count);
            $response->setContent(1 == $count ? 'Hello World' : 'Goodbye World');
        });

        $this->request('GET', '/');
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertEquals('Hello World', $this->response->getContent());
        $this->assertTraceContains('store');

        $this->request('GET', '/');
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertEquals('Hello World', $this->response->getContent());
        $this->assertTraceContains('fresh');

        $this->cacheConfig['allow_revalidate'] = true;
        $this->request('GET', '/', array('HTTP_CACHE_CONTROL' => 'max-age=0'));
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertEquals('Goodbye World', $this->response->getContent());
        $this->assertTraceContains('stale');
        $this->assertTraceContains('invalid');
        $this->assertTraceContains('store');
    }

    public function testDoesNotRevalidateFreshCacheEntryWhenEnableRevalidateOptionIsSetFalseDefault()
    {
        $count = 0;

        $this->setNextResponse(200, array(), '', function ($request, $response) use (&$count) {
            ++$count;
            $response->headers->set('Cache-Control', 'public, max-age=10000');
            $response->setETag($count);
            $response->setContent(1 == $count ? 'Hello World' : 'Goodbye World');
        });

        $this->request('GET', '/');
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertEquals('Hello World', $this->response->getContent());
        $this->assertTraceContains('store');

        $this->request('GET', '/');
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertEquals('Hello World', $this->response->getContent());
        $this->assertTraceContains('fresh');

        $this->cacheConfig['allow_revalidate'] = false;
        $this->request('GET', '/', array('HTTP_CACHE_CONTROL' => 'max-age=0'));
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertEquals('Hello World', $this->response->getContent());
        $this->assertTraceNotContains('stale');
        $this->assertTraceNotContains('invalid');
        $this->assertTraceContains('fresh');

        $this->request('GET', '/', array('HTTP_CACHE_CONTROL' => 'max-age=0'));
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertEquals('Hello World', $this->response->getContent());
        $this->assertTraceNotContains('stale');
        $this->assertTraceNotContains('invalid');
        $this->assertTraceContains('fresh');
    }

    public function testFetchesResponseFromBackendWhenCacheMisses()
    {
        $time = \DateTime::createFromFormat('U', time() + 5);
        $this->setNextResponse(200, array('Cache-Control' => 'public', 'Expires' => $time->format(DATE_RFC2822)));

        $this->request('GET', '/');
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertTraceContains('miss');
        $this->assertTrue($this->response->headers->has('Age'));
    }

    public function testDoesNotCacheSomeStatusCodeResponses()
    {
        foreach (array_merge(range(201, 202), range(204, 206), range(303, 305), range(400, 403), range(405, 409), range(411, 417), range(500, 505)) as $code) {
            $time = \DateTime::createFromFormat('U', time() + 5);
            $this->setNextResponse($code, array('Expires' => $time->format(DATE_RFC2822)));

            $this->request('GET', '/');
            $this->assertEquals($code, $this->response->getStatusCode());
            $this->assertTraceNotContains('store');
            $this->assertFalse($this->response->headers->has('Age'));
        }
    }

    public function testDoesNotCacheResponsesWithExplicitNoStoreDirective()
    {
        $time = \DateTime::createFromFormat('U', time() + 5);
        $this->setNextResponse(200, array('Expires' => $time->format(DATE_RFC2822), 'Cache-Control' => 'no-store'));

        $this->request('GET', '/');
        $this->assertTraceNotContains('store');
        $this->assertFalse($this->response->headers->has('Age'));
    }

    public function testDoesNotCacheResponsesWithoutFreshnessInformationOrAValidator()
    {
        $this->setNextResponse();

        $this->request('GET', '/');
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertTraceNotContains('store');
    }

    public function testCachesResponsesWithExplicitNoCacheDirective()
    {
        $time = \DateTime::createFromFormat('U', time() + 5);
        $this->setNextResponse(200, array('Expires' => $time->format(DATE_RFC2822), 'Cache-Control' => 'public, no-cache'));

        $this->request('GET', '/');
        $this->assertTraceContains('store');
        $this->assertTrue($this->response->headers->has('Age'));
    }

    public function testCachesResponsesWithAnExpirationHeader()
    {
        $time = \DateTime::createFromFormat('U', time() + 5);
        $this->setNextResponse(200, array('Cache-Control' => 'public', 'Expires' => $time->format(DATE_RFC2822)));

        $this->request('GET', '/');
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertEquals('Hello World', $this->response->getContent());
        $this->assertNotNull($this->response->headers->get('Date'));
        $this->assertNotNull($this->response->headers->get('X-Content-Digest'));
        $this->assertTraceContains('miss');
        $this->assertTraceContains('store');

        $values = $this->getMetaStorageValues();
        $this->assertCount(1, $values);
    }

    public function testCachesResponsesWithAMaxAgeDirective()
    {
        $this->setNextResponse(200, array('Cache-Control' => 'public, max-age=5'));

        $this->request('GET', '/');
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertEquals('Hello World', $this->response->getContent());
        $this->assertNotNull($this->response->headers->get('Date'));
        $this->assertNotNull($this->response->headers->get('X-Content-Digest'));
        $this->assertTraceContains('miss');
        $this->assertTraceContains('store');

        $values = $this->getMetaStorageValues();
        $this->assertCount(1, $values);
    }

    public function testCachesResponsesWithASMaxAgeDirective()
    {
        $this->setNextResponse(200, array('Cache-Control' => 's-maxage=5'));

        $this->request('GET', '/');
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertEquals('Hello World', $this->response->getContent());
        $this->assertNotNull($this->response->headers->get('Date'));
        $this->assertNotNull($this->response->headers->get('X-Content-Digest'));
        $this->assertTraceContains('miss');
        $this->assertTraceContains('store');

        $values = $this->getMetaStorageValues();
        $this->assertCount(1, $values);
    }

    public function testCachesResponsesWithALastModifiedValidatorButNoFreshnessInformation()
    {
        $time = \DateTime::createFromFormat('U', time());
        $this->setNextResponse(200, array('Cache-Control' => 'public', 'Last-Modified' => $time->format(DATE_RFC2822)));

        $this->request('GET', '/');
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertEquals('Hello World', $this->response->getContent());
        $this->assertTraceContains('miss');
        $this->assertTraceContains('store');
    }

    public function testCachesResponsesWithAnETagValidatorButNoFreshnessInformation()
    {
        $this->setNextResponse(200, array('Cache-Control' => 'public', 'ETag' => '"123456"'));

        $this->request('GET', '/');
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertEquals('Hello World', $this->response->getContent());
        $this->assertTraceContains('miss');
        $this->assertTraceContains('store');
    }

    public function testHitsCachedResponsesWithExpiresHeader()
    {
        $time1 = \DateTime::createFromFormat('U', time() - 5);
        $time2 = \DateTime::createFromFormat('U', time() + 5);
        $this->setNextResponse(200, array('Cache-Control' => 'public', 'Date' => $time1->format(DATE_RFC2822), 'Expires' => $time2->format(DATE_RFC2822)));

        $this->request('GET', '/');
        $this->assertHttpKernelIsCalled();
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertNotNull($this->response->headers->get('Date'));
        $this->assertTraceContains('miss');
        $this->assertTraceContains('store');
        $this->assertEquals('Hello World', $this->response->getContent());

        $this->request('GET', '/');
        $this->assertHttpKernelIsNotCalled();
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertTrue(strtotime($this->responses[0]->headers->get('Date')) - strtotime($this->response->headers->get('Date')) < 2);
        $this->assertTrue($this->response->headers->get('Age') > 0);
        $this->assertNotNull($this->response->headers->get('X-Content-Digest'));
        $this->assertTraceContains('fresh');
        $this->assertTraceNotContains('store');
        $this->assertEquals('Hello World', $this->response->getContent());
    }

    public function testHitsCachedResponseWithMaxAgeDirective()
    {
        $time = \DateTime::createFromFormat('U', time() - 5);
        $this->setNextResponse(200, array('Date' => $time->format(DATE_RFC2822), 'Cache-Control' => 'public, max-age=10'));

        $this->request('GET', '/');
        $this->assertHttpKernelIsCalled();
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertNotNull($this->response->headers->get('Date'));
        $this->assertTraceContains('miss');
        $this->assertTraceContains('store');
        $this->assertEquals('Hello World', $this->response->getContent());

        $this->request('GET', '/');
        $this->assertHttpKernelIsNotCalled();
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertTrue(strtotime($this->responses[0]->headers->get('Date')) - strtotime($this->response->headers->get('Date')) < 2);
        $this->assertTrue($this->response->headers->get('Age') > 0);
        $this->assertNotNull($this->response->headers->get('X-Content-Digest'));
        $this->assertTraceContains('fresh');
        $this->assertTraceNotContains('store');
        $this->assertEquals('Hello World', $this->response->getContent());
    }

    public function testHitsCachedResponseWithSMaxAgeDirective()
    {
        $time = \DateTime::createFromFormat('U', time() - 5);
        $this->setNextResponse(200, array('Date' => $time->format(DATE_RFC2822), 'Cache-Control' => 's-maxage=10, max-age=0'));

        $this->request('GET', '/');
        $this->assertHttpKernelIsCalled();
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertNotNull($this->response->headers->get('Date'));
        $this->assertTraceContains('miss');
        $this->assertTraceContains('store');
        $this->assertEquals('Hello World', $this->response->getContent());

        $this->request('GET', '/');
        $this->assertHttpKernelIsNotCalled();
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertTrue(strtotime($this->responses[0]->headers->get('Date')) - strtotime($this->response->headers->get('Date')) < 2);
        $this->assertTrue($this->response->headers->get('Age') > 0);
        $this->assertNotNull($this->response->headers->get('X-Content-Digest'));
        $this->assertTraceContains('fresh');
        $this->assertTraceNotContains('store');
        $this->assertEquals('Hello World', $this->response->getContent());
    }

    public function testAssignsDefaultTtlWhenResponseHasNoFreshnessInformation()
    {
        $this->setNextResponse();

        $this->cacheConfig['default_ttl'] = 10;
        $this->request('GET', '/');
        $this->assertHttpKernelIsCalled();
        $this->assertTraceContains('miss');
        $this->assertTraceContains('store');
        $this->assertEquals('Hello World', $this->response->getContent());
        $this->assertRegExp('/s-maxage=10/', $this->response->headers->get('Cache-Control'));

        $this->cacheConfig['default_ttl'] = 10;
        $this->request('GET', '/');
        $this->assertHttpKernelIsNotCalled();
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertTraceContains('fresh');
        $this->assertTraceNotContains('store');
        $this->assertEquals('Hello World', $this->response->getContent());
    }

    public function testDoesNotAssignDefaultTtlWhenResponseHasMustRevalidateDirective()
    {
        $this->setNextResponse(200, array('Cache-Control' => 'must-revalidate'));

        $this->cacheConfig['default_ttl'] = 10;
        $this->request('GET', '/');
        $this->assertHttpKernelIsCalled();
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertTraceContains('miss');
        $this->assertTraceNotContains('store');
        $this->assertNotRegExp('/s-maxage/', $this->response->headers->get('Cache-Control'));
        $this->assertEquals('Hello World', $this->response->getContent());
    }

    public function testFetchesFullResponseWhenCacheStaleAndNoValidatorsPresent()
    {
        $time = \DateTime::createFromFormat('U', time() + 5);
        $this->setNextResponse(200, array('Cache-Control' => 'public', 'Expires' => $time->format(DATE_RFC2822)));

        // build initial request
        $this->request('GET', '/');
        $this->assertHttpKernelIsCalled();
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertNotNull($this->response->headers->get('Date'));
        $this->assertNotNull($this->response->headers->get('X-Content-Digest'));
        $this->assertNotNull($this->response->headers->get('Age'));
        $this->assertTraceContains('miss');
        $this->assertTraceContains('store');
        $this->assertEquals('Hello World', $this->response->getContent());

        # go in and play around with the cached metadata directly ...
        $values = $this->getMetaStorageValues();
        $this->assertCount(1, $values);
        $tmp = unserialize($values[0]);
        $time = \DateTime::createFromFormat('U', time());
        $tmp[0][1]['expires'] = $time->format(DATE_RFC2822);
        $r = new \ReflectionObject($this->store);
        $m = $r->getMethod('save');
        $m->setAccessible(true);
        $m->invoke($this->store, 'md'.hash('sha256', 'http://localhost/'), serialize($tmp));

        // build subsequent request; should be found but miss due to freshness
        $this->request('GET', '/');
        $this->assertHttpKernelIsCalled();
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertTrue($this->response->headers->get('Age') <= 1);
        $this->assertNotNull($this->response->headers->get('X-Content-Digest'));
        $this->assertTraceContains('stale');
        $this->assertTraceNotContains('fresh');
        $this->assertTraceNotContains('miss');
        $this->assertTraceContains('store');
        $this->assertEquals('Hello World', $this->response->getContent());
    }

    public function testValidatesCachedResponsesWithLastModifiedAndNoFreshnessInformation()
    {
        $time = \DateTime::createFromFormat('U', time());
        $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) use ($time) {
            $response->headers->set('Cache-Control', 'public');
            $response->headers->set('Last-Modified', $time->format(DATE_RFC2822));
            if ($time->format(DATE_RFC2822) == $request->headers->get('IF_MODIFIED_SINCE')) {
                $response->setStatusCode(304);
                $response->setContent('');
            }
        });

        // build initial request
        $this->request('GET', '/');
        $this->assertHttpKernelIsCalled();
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertNotNull($this->response->headers->get('Last-Modified'));
        $this->assertNotNull($this->response->headers->get('X-Content-Digest'));
        $this->assertEquals('Hello World', $this->response->getContent());
        $this->assertTraceContains('miss');
        $this->assertTraceContains('store');
        $this->assertTraceNotContains('stale');

        // build subsequent request; should be found but miss due to freshness
        $this->request('GET', '/');
        $this->assertHttpKernelIsCalled();
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertNotNull($this->response->headers->get('Last-Modified'));
        $this->assertNotNull($this->response->headers->get('X-Content-Digest'));
        $this->assertTrue($this->response->headers->get('Age') <= 1);
        $this->assertEquals('Hello World', $this->response->getContent());
        $this->assertTraceContains('stale');
        $this->assertTraceContains('valid');
        $this->assertTraceContains('store');
        $this->assertTraceNotContains('miss');
    }

    public function testValidatesCachedResponsesWithETagAndNoFreshnessInformation()
    {
        $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) {
            $response->headers->set('Cache-Control', 'public');
            $response->headers->set('ETag', '"12345"');
            if ($response->getETag() == $request->headers->get('IF_NONE_MATCH')) {
                $response->setStatusCode(304);
                $response->setContent('');
            }
        });

        // build initial request
        $this->request('GET', '/');
        $this->assertHttpKernelIsCalled();
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertNotNull($this->response->headers->get('ETag'));
        $this->assertNotNull($this->response->headers->get('X-Content-Digest'));
        $this->assertEquals('Hello World', $this->response->getContent());
        $this->assertTraceContains('miss');
        $this->assertTraceContains('store');

        // build subsequent request; should be found but miss due to freshness
        $this->request('GET', '/');
        $this->assertHttpKernelIsCalled();
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertNotNull($this->response->headers->get('ETag'));
        $this->assertNotNull($this->response->headers->get('X-Content-Digest'));
        $this->assertTrue($this->response->headers->get('Age') <= 1);
        $this->assertEquals('Hello World', $this->response->getContent());
        $this->assertTraceContains('stale');
        $this->assertTraceContains('valid');
        $this->assertTraceContains('store');
        $this->assertTraceNotContains('miss');
    }

    public function testReplacesCachedResponsesWhenValidationResultsInNon304Response()
    {
        $time = \DateTime::createFromFormat('U', time());
        $count = 0;
        $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) use ($time, &$count) {
            $response->headers->set('Last-Modified', $time->format(DATE_RFC2822));
            $response->headers->set('Cache-Control', 'public');
            switch (++$count) {
                case 1:
                    $response->setContent('first response');
                    break;
                case 2:
                    $response->setContent('second response');
                    break;
                case 3:
                    $response->setContent('');
                    $response->setStatusCode(304);
                    break;
            }
        });

        // first request should fetch from backend and store in cache
        $this->request('GET', '/');
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertEquals('first response', $this->response->getContent());

        // second request is validated, is invalid, and replaces cached entry
        $this->request('GET', '/');
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertEquals('second response', $this->response->getContent());

        // third response is validated, valid, and returns cached entry
        $this->request('GET', '/');
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertEquals('second response', $this->response->getContent());

        $this->assertEquals(3, $count);
    }

    public function testPassesHeadRequestsThroughDirectlyOnPass()
    {
        $that = $this;
        $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) use ($that) {
            $response->setContent('');
            $response->setStatusCode(200);
            $that->assertEquals('HEAD', $request->getMethod());
        });

        $this->request('HEAD', '/', array('HTTP_EXPECT' => 'something ...'));
        $this->assertHttpKernelIsCalled();
        $this->assertEquals('', $this->response->getContent());
    }

    public function testUsesCacheToRespondToHeadRequestsWhenFresh()
    {
        $that = $this;
        $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) use ($that) {
            $response->headers->set('Cache-Control', 'public, max-age=10');
            $response->setContent('Hello World');
            $response->setStatusCode(200);
            $that->assertNotEquals('HEAD', $request->getMethod());
        });

        $this->request('GET', '/');
        $this->assertHttpKernelIsCalled();
        $this->assertEquals('Hello World', $this->response->getContent());

        $this->request('HEAD', '/');
        $this->assertHttpKernelIsNotCalled();
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertEquals('', $this->response->getContent());
        $this->assertEquals(strlen('Hello World'), $this->response->headers->get('Content-Length'));
    }

    public function testSendsNoContentWhenFresh()
    {
        $time = \DateTime::createFromFormat('U', time());
        $that = $this;
        $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) use ($that, $time) {
            $response->headers->set('Cache-Control', 'public, max-age=10');
            $response->headers->set('Last-Modified', $time->format(DATE_RFC2822));
        });

        $this->request('GET', '/');
        $this->assertHttpKernelIsCalled();
        $this->assertEquals('Hello World', $this->response->getContent());

        $this->request('GET', '/', array('HTTP_IF_MODIFIED_SINCE' => $time->format(DATE_RFC2822)));
        $this->assertHttpKernelIsNotCalled();
        $this->assertEquals(304, $this->response->getStatusCode());
        $this->assertEquals('', $this->response->getContent());
    }

    public function testInvalidatesCachedResponsesOnPost()
    {
        $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) {
            if ('GET' == $request->getMethod()) {
                $response->setStatusCode(200);
                $response->headers->set('Cache-Control', 'public, max-age=500');
                $response->setContent('Hello World');
            } elseif ('POST' == $request->getMethod()) {
                $response->setStatusCode(303);
                $response->headers->set('Location', '/');
                $response->headers->remove('Cache-Control');
                $response->setContent('');
            }
        });

        // build initial request to enter into the cache
        $this->request('GET', '/');
        $this->assertHttpKernelIsCalled();
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertEquals('Hello World', $this->response->getContent());
        $this->assertTraceContains('miss');
        $this->assertTraceContains('store');

        // make sure it is valid
        $this->request('GET', '/');
        $this->assertHttpKernelIsNotCalled();
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertEquals('Hello World', $this->response->getContent());
        $this->assertTraceContains('fresh');

        // now POST to same URL
        $this->request('POST', '/helloworld');
        $this->assertHttpKernelIsCalled();
        $this->assertEquals('/', $this->response->headers->get('Location'));
        $this->assertTraceContains('invalidate');
        $this->assertTraceContains('pass');
        $this->assertEquals('', $this->response->getContent());

        // now make sure it was actually invalidated
        $this->request('GET', '/');
        $this->assertHttpKernelIsCalled();
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertEquals('Hello World', $this->response->getContent());
        $this->assertTraceContains('stale');
        $this->assertTraceContains('invalid');
        $this->assertTraceContains('store');
    }

    public function testServesFromCacheWhenHeadersMatch()
    {
        $count = 0;
        $this->setNextResponse(200, array('Cache-Control' => 'max-age=10000'), '', function ($request, $response) use (&$count) {
            $response->headers->set('Vary', 'Accept User-Agent Foo');
            $response->headers->set('Cache-Control', 'public, max-age=10');
            $response->headers->set('X-Response-Count', ++$count);
            $response->setContent($request->headers->get('USER_AGENT'));
        });

        $this->request('GET', '/', array('HTTP_ACCEPT' => 'text/html', 'HTTP_USER_AGENT' => 'Bob/1.0'));
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertEquals('Bob/1.0', $this->response->getContent());
        $this->assertTraceContains('miss');
        $this->assertTraceContains('store');

        $this->request('GET', '/', array('HTTP_ACCEPT' => 'text/html', 'HTTP_USER_AGENT' => 'Bob/1.0'));
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertEquals('Bob/1.0', $this->response->getContent());
        $this->assertTraceContains('fresh');
        $this->assertTraceNotContains('store');
        $this->assertNotNull($this->response->headers->get('X-Content-Digest'));
    }

    public function testStoresMultipleResponsesWhenHeadersDiffer()
    {
        $count = 0;
        $this->setNextResponse(200, array('Cache-Control' => 'max-age=10000'), '', function ($request, $response) use (&$count) {
            $response->headers->set('Vary', 'Accept User-Agent Foo');
            $response->headers->set('Cache-Control', 'public, max-age=10');
            $response->headers->set('X-Response-Count', ++$count);
            $response->setContent($request->headers->get('USER_AGENT'));
        });

        $this->request('GET', '/', array('HTTP_ACCEPT' => 'text/html', 'HTTP_USER_AGENT' => 'Bob/1.0'));
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertEquals('Bob/1.0', $this->response->getContent());
        $this->assertEquals(1, $this->response->headers->get('X-Response-Count'));

        $this->request('GET', '/', array('HTTP_ACCEPT' => 'text/html', 'HTTP_USER_AGENT' => 'Bob/2.0'));
        $this->assertEquals(200, $this->response->getStatusCode());
        $this->assertTraceContains('miss');
        $this->assertTraceContains('store');
        $this->assertEquals('Bob/2.0', $this->response->getContent());
        $this->assertEquals(2, $this->response->headers->get('X-Response-Count'));

        $this->request('GET', '/', array('HTTP_ACCEPT' => 'text/html', 'HTTP_USER_AGENT' => 'Bob/1.0'));
        $this->assertTraceContains('fresh');
        $this->assertEquals('Bob/1.0', $this->response->getContent());
        $this->assertEquals(1, $this->response->headers->get('X-Response-Count'));

        $this->request('GET', '/', array('HTTP_ACCEPT' => 'text/html', 'HTTP_USER_AGENT' => 'Bob/2.0'));
        $this->assertTraceContains('fresh');
        $this->assertEquals('Bob/2.0', $this->response->getContent());
        $this->assertEquals(2, $this->response->headers->get('X-Response-Count'));

        $this->request('GET', '/', array('HTTP_USER_AGENT' => 'Bob/2.0'));
        $this->assertTraceContains('miss');
        $this->assertEquals('Bob/2.0', $this->response->getContent());
        $this->assertEquals(3, $this->response->headers->get('X-Response-Count'));
    }

    public function testShouldCatchExceptions()
    {
        $this->catchExceptions();

        $this->setNextResponse();
        $this->request('GET', '/');

        $this->assertExceptionsAreCaught();
    }

    public function testShouldCatchExceptionsWhenReloadingAndNoCacheRequest()
    {
        $this->catchExceptions();

        $this->setNextResponse();
        $this->cacheConfig['allow_reload'] = true;
        $this->request('GET', '/', array(), array(), false, array('Pragma' => 'no-cache'));

        $this->assertExceptionsAreCaught();
    }

    public function testShouldNotCatchExceptions()
    {
        $this->catchExceptions(false);

        $this->setNextResponse();
        $this->request('GET', '/');

        $this->assertExceptionsAreNotCaught();
    }

    public function testEsiCacheSendsTheLowestTtl()
    {
        $responses = array(
            array(
                'status'  => 200,
                'body'    => '<esi:include src="/foo" /> <esi:include src="/bar" />',
                'headers' => array(
                    'Cache-Control'     => 's-maxage=300',
                    'Surrogate-Control' => 'content="ESI/1.0"',
                ),
            ),
            array(
                'status'  => 200,
                'body'    => 'Hello World!',
                'headers' => array('Cache-Control' => 's-maxage=300'),
            ),
            array(
                'status'  => 200,
                'body'    => 'My name is Bobby.',
                'headers' => array('Cache-Control' => 's-maxage=100'),
            ),
        );

        $this->setNextResponses($responses);

        $this->request('GET', '/', array(), array(), true);
        $this->assertEquals("Hello World! My name is Bobby.", $this->response->getContent());

        // check for 100 or 99 as the test can be executed after a second change
        $this->assertTrue(in_array($this->response->getTtl(), array(99, 100)));
    }

    public function testEsiCacheForceValidation()
    {
        $responses = array(
            array(
                'status'  => 200,
                'body'    => '<esi:include src="/foo" /> <esi:include src="/bar" />',
                'headers' => array(
                    'Cache-Control'     => 's-maxage=300',
                    'Surrogate-Control' => 'content="ESI/1.0"',
                ),
            ),
            array(
                'status'  => 200,
                'body'    => 'Hello World!',
                'headers' => array('ETag' => 'foobar'),
            ),
            array(
                'status'  => 200,
                'body'    => 'My name is Bobby.',
                'headers' => array('Cache-Control' => 's-maxage=100'),
            ),
        );

        $this->setNextResponses($responses);

        $this->request('GET', '/', array(), array(), true);
        $this->assertEquals('Hello World! My name is Bobby.', $this->response->getContent());
        $this->assertNull($this->response->getTtl());
        $this->assertTrue($this->response->mustRevalidate());
        $this->assertTrue($this->response->headers->hasCacheControlDirective('private'));
        $this->assertTrue($this->response->headers->hasCacheControlDirective('no-cache'));
    }

    public function testEsiRecalculateContentLengthHeader()
    {
        $responses = array(
            array(
                'status'  => 200,
                'body'    => '<esi:include src="/foo" />',
                'headers' => array(
                    'Content-Length'    => 26,
                    'Cache-Control'     => 's-maxage=300',
                    'Surrogate-Control' => 'content="ESI/1.0"',
                ),
            ),
            array(
                'status'  => 200,
                'body'    => 'Hello World!',
                'headers' => array(),
            ),
        );

        $this->setNextResponses($responses);

        $this->request('GET', '/', array(), array(), true);
        $this->assertEquals('Hello World!', $this->response->getContent());
        $this->assertEquals(12, $this->response->headers->get('Content-Length'));
    }

    public function testClientIpIsAlwaysLocalhostForForwardedRequests()
    {
        $this->setNextResponse();
        $this->request('GET', '/', array('REMOTE_ADDR' => '10.0.0.1'));

        $this->assertEquals('127.0.0.1', $this->kernel->getBackendRequest()->server->get('REMOTE_ADDR'));
    }

    /**
     * @dataProvider getXForwardedForData
     */
    public function testXForwarderForHeaderForForwardedRequests($xForwardedFor, $expected)
    {
        $this->setNextResponse();
        $server = array('REMOTE_ADDR' => '10.0.0.1');
        if (false !== $xForwardedFor) {
            $server['HTTP_X_FORWARDED_FOR'] = $xForwardedFor;
        }
        $this->request('GET', '/', $server);

        $this->assertEquals($expected, $this->kernel->getBackendRequest()->headers->get('X-Forwarded-For'));
    }

    public function getXForwardedForData()
    {
        return array(
            array(false, '10.0.0.1'),
            array('10.0.0.2', '10.0.0.2, 10.0.0.1'),
            array('10.0.0.2, 10.0.0.3', '10.0.0.2, 10.0.0.3, 10.0.0.1'),
        );
    }

    public function testXForwarderForHeaderForPassRequests()
    {
        $this->setNextResponse();
        $server = array('REMOTE_ADDR' => '10.0.0.1');
        $this->request('POST', '/', $server);

        $this->assertEquals('10.0.0.1', $this->kernel->getBackendRequest()->headers->get('X-Forwarded-For'));
    }

    public function testEsiCacheRemoveValidationHeadersIfEmbeddedResponses()
    {
        $time = new \DateTime;

        $responses = array(
            array(
                'status'  => 200,
                'body'    => '<esi:include src="/hey" />',
                'headers' => array(
                    'Surrogate-Control' => 'content="ESI/1.0"',
                    'ETag' => 'hey',
                    'Last-Modified' => $time->format(DATE_RFC2822),
                ),
            ),
            array(
                'status'  => 200,
                'body'    => 'Hey!',
                'headers' => array(),
            ),
        );

        $this->setNextResponses($responses);

        $this->request('GET', '/', array(), array(), true);
        $this->assertNull($this->response->getETag());
        $this->assertNull($this->response->getLastModified());
    }
}
PK��Z�t~		Otest/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpCache/TestHttpKernel.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\HttpCache;

use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
use Symfony\Component\EventDispatcher\EventDispatcher;

class TestHttpKernel extends HttpKernel implements ControllerResolverInterface
{
    protected $body;
    protected $status;
    protected $headers;
    protected $called = false;
    protected $customizer;
    protected $catch = false;
    protected $backendRequest;

    public function __construct($body, $status, $headers, \Closure $customizer = null)
    {
        $this->body = $body;
        $this->status = $status;
        $this->headers = $headers;
        $this->customizer = $customizer;

        parent::__construct(new EventDispatcher(), $this);
    }

    public function getBackendRequest()
    {
        return $this->backendRequest;
    }

    public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = false)
    {
        $this->catch = $catch;
        $this->backendRequest = $request;

        return parent::handle($request, $type, $catch);
    }

    public function isCatchingExceptions()
    {
        return $this->catch;
    }

    public function getController(Request $request)
    {
        return array($this, 'callController');
    }

    public function getArguments(Request $request, $controller)
    {
        return array($request);
    }

    public function callController(Request $request)
    {
        $this->called = true;

        $response = new Response($this->body, $this->status, $this->headers);

        if (null !== $this->customizer) {
            call_user_func($this->customizer, $request, $response);
        }

        return $response;
    }

    public function hasBeenCalled()
    {
        return $this->called;
    }

    public function reset()
    {
        $this->called = false;
    }
}
PK��Z`��uNNHtest/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\HttpCache;

use Symfony\Component\HttpKernel\HttpCache\Esi;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class EsiTest extends \PHPUnit_Framework_TestCase
{
    public function testHasSurrogateEsiCapability()
    {
        $esi = new Esi();

        $request = Request::create('/');
        $request->headers->set('Surrogate-Capability', 'abc="ESI/1.0"');
        $this->assertTrue($esi->hasSurrogateEsiCapability($request));

        $request = Request::create('/');
        $request->headers->set('Surrogate-Capability', 'foobar');
        $this->assertFalse($esi->hasSurrogateEsiCapability($request));

        $request = Request::create('/');
        $this->assertFalse($esi->hasSurrogateEsiCapability($request));
    }

    public function testAddSurrogateEsiCapability()
    {
        $esi = new Esi();

        $request = Request::create('/');
        $esi->addSurrogateEsiCapability($request);
        $this->assertEquals('symfony2="ESI/1.0"', $request->headers->get('Surrogate-Capability'));

        $esi->addSurrogateEsiCapability($request);
        $this->assertEquals('symfony2="ESI/1.0", symfony2="ESI/1.0"', $request->headers->get('Surrogate-Capability'));
    }

    public function testAddSurrogateControl()
    {
        $esi = new Esi();

        $response = new Response('foo <esi:include src="" />');
        $esi->addSurrogateControl($response);
        $this->assertEquals('content="ESI/1.0"', $response->headers->get('Surrogate-Control'));

        $response = new Response('foo');
        $esi->addSurrogateControl($response);
        $this->assertEquals('', $response->headers->get('Surrogate-Control'));
    }

    public function testNeedsEsiParsing()
    {
        $esi = new Esi();

        $response = new Response();
        $response->headers->set('Surrogate-Control', 'content="ESI/1.0"');
        $this->assertTrue($esi->needsEsiParsing($response));

        $response = new Response();
        $this->assertFalse($esi->needsEsiParsing($response));
    }

    public function testRenderIncludeTag()
    {
        $esi = new Esi();

        $this->assertEquals('<esi:include src="/" onerror="continue" alt="/alt" />', $esi->renderIncludeTag('/', '/alt', true));
        $this->assertEquals('<esi:include src="/" alt="/alt" />', $esi->renderIncludeTag('/', '/alt', false));
        $this->assertEquals('<esi:include src="/" onerror="continue" />', $esi->renderIncludeTag('/'));
        $this->assertEquals('<esi:comment text="some comment" />'."\n".'<esi:include src="/" onerror="continue" alt="/alt" />', $esi->renderIncludeTag('/', '/alt', true, 'some comment'));
    }

    public function testProcessDoesNothingIfContentTypeIsNotHtml()
    {
        $esi = new Esi();

        $request = Request::create('/');
        $response = new Response();
        $response->headers->set('Content-Type', 'text/plain');
        $esi->process($request, $response);

        $this->assertFalse($response->headers->has('x-body-eval'));
    }

    public function testProcess()
    {
        $esi = new Esi();

        $request = Request::create('/');
        $response = new Response('foo <esi:comment text="some comment" /><esi:include src="..." alt="alt" onerror="continue" />');
        $esi->process($request, $response);

        $this->assertEquals('foo <?php echo $this->esi->handle($this, \'...\', \'alt\', true) ?>'."\n", $response->getContent());
        $this->assertEquals('ESI', $response->headers->get('x-body-eval'));

        $response = new Response('foo <esi:include src="..." />');
        $esi->process($request, $response);

        $this->assertEquals('foo <?php echo $this->esi->handle($this, \'...\', \'\', false) ?>'."\n", $response->getContent());

        $response = new Response('foo <esi:include src="..."></esi:include>');
        $esi->process($request, $response);

        $this->assertEquals('foo <?php echo $this->esi->handle($this, \'...\', \'\', false) ?>'."\n", $response->getContent());
    }

    public function testProcessEscapesPhpTags()
    {
        $esi = new Esi();

        $request = Request::create('/');
        $response = new Response('foo <?php die("foo"); ?><%= "lala" %>');
        $esi->process($request, $response);

        $this->assertEquals('foo <?php echo "<?"; ?>php die("foo"); ?><?php echo "<%"; ?>= "lala" %>', $response->getContent());
    }

    /**
     * @expectedException \RuntimeException
     */
    public function testProcessWhenNoSrcInAnEsi()
    {
        $esi = new Esi();

        $request = Request::create('/');
        $response = new Response('foo <esi:include />');
        $esi->process($request, $response);
    }

    public function testProcessRemoveSurrogateControlHeader()
    {
        $esi = new Esi();

        $request = Request::create('/');
        $response = new Response('foo <esi:include src="..." />');
        $response->headers->set('Surrogate-Control', 'content="ESI/1.0"');
        $esi->process($request, $response);
        $this->assertEquals('ESI', $response->headers->get('x-body-eval'));

        $response->headers->set('Surrogate-Control', 'no-store, content="ESI/1.0"');
        $esi->process($request, $response);
        $this->assertEquals('ESI', $response->headers->get('x-body-eval'));
        $this->assertEquals('no-store', $response->headers->get('surrogate-control'));

        $response->headers->set('Surrogate-Control', 'content="ESI/1.0", no-store');
        $esi->process($request, $response);
        $this->assertEquals('ESI', $response->headers->get('x-body-eval'));
        $this->assertEquals('no-store', $response->headers->get('surrogate-control'));
    }

    public function testHandle()
    {
        $esi = new Esi();
        $cache = $this->getCache(Request::create('/'), new Response('foo'));
        $this->assertEquals('foo', $esi->handle($cache, '/', '/alt', true));
    }

    /**
     * @expectedException \RuntimeException
     */
    public function testHandleWhenResponseIsNot200()
    {
        $esi = new Esi();
        $response = new Response('foo');
        $response->setStatusCode(404);
        $cache = $this->getCache(Request::create('/'), $response);
        $esi->handle($cache, '/', '/alt', false);
    }

    public function testHandleWhenResponseIsNot200AndErrorsAreIgnored()
    {
        $esi = new Esi();
        $response = new Response('foo');
        $response->setStatusCode(404);
        $cache = $this->getCache(Request::create('/'), $response);
        $this->assertEquals('', $esi->handle($cache, '/', '/alt', true));
    }

    public function testHandleWhenResponseIsNot200AndAltIsPresent()
    {
        $esi = new Esi();
        $response1 = new Response('foo');
        $response1->setStatusCode(404);
        $response2 = new Response('bar');
        $cache = $this->getCache(Request::create('/'), array($response1, $response2));
        $this->assertEquals('bar', $esi->handle($cache, '/', '/alt', false));
    }

    protected function getCache($request, $response)
    {
        $cache = $this->getMock('Symfony\Component\HttpKernel\HttpCache\HttpCache', array('getRequest', 'handle'), array(), '', false);
        $cache->expects($this->any())
              ->method('getRequest')
              ->will($this->returnValue($request))
        ;
        if (is_array($response)) {
            $cache->expects($this->any())
                  ->method('handle')
                  ->will(call_user_func_array(array($this, 'onConsecutiveCalls'), $response))
            ;
        } else {
            $cache->expects($this->any())
                  ->method('handle')
                  ->will($this->returnValue($response))
            ;
        }

        return $cache;
    }
}
PK��Z���JJWtest/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpCache/TestMultipleHttpKernel.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\HttpCache;

use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
use Symfony\Component\EventDispatcher\EventDispatcher;

class TestMultipleHttpKernel extends HttpKernel implements ControllerResolverInterface
{
    protected $bodies = array();
    protected $statuses = array();
    protected $headers = array();
    protected $call = false;
    protected $backendRequest;

    public function __construct($responses)
    {
        foreach ($responses as $response) {
            $this->bodies[]   = $response['body'];
            $this->statuses[] = $response['status'];
            $this->headers[]  = $response['headers'];
        }

        parent::__construct(new EventDispatcher(), $this);
    }

    public function getBackendRequest()
    {
        return $this->backendRequest;
    }

    public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = false)
    {
        $this->backendRequest = $request;

        return parent::handle($request, $type, $catch);
    }

    public function getController(Request $request)
    {
        return array($this, 'callController');
    }

    public function getArguments(Request $request, $controller)
    {
        return array($request);
    }

    public function callController(Request $request)
    {
        $this->called = true;

        $response = new Response(array_shift($this->bodies), array_shift($this->statuses), array_shift($this->headers));

        return $response;
    }

    public function hasBeenCalled()
    {
        return $this->called;
    }

    public function reset()
    {
        $this->call = false;
    }
}
PK��Z�VPRtest/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTestCase.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\HttpCache;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpCache\Esi;
use Symfony\Component\HttpKernel\HttpCache\HttpCache;
use Symfony\Component\HttpKernel\HttpCache\Store;
use Symfony\Component\HttpKernel\HttpKernelInterface;

class HttpCacheTestCase extends \PHPUnit_Framework_TestCase
{
    protected $kernel;
    protected $cache;
    protected $caches;
    protected $cacheConfig;
    protected $request;
    protected $response;
    protected $responses;
    protected $catch;
    protected $esi;

    protected function setUp()
    {
        $this->kernel = null;

        $this->cache = null;
        $this->esi = null;
        $this->caches = array();
        $this->cacheConfig = array();

        $this->request = null;
        $this->response = null;
        $this->responses = array();

        $this->catch = false;

        $this->clearDirectory(sys_get_temp_dir().'/http_cache');
    }

    protected function tearDown()
    {
        $this->kernel = null;
        $this->cache = null;
        $this->caches = null;
        $this->request = null;
        $this->response = null;
        $this->responses = null;
        $this->cacheConfig = null;
        $this->catch = null;
        $this->esi = null;

        $this->clearDirectory(sys_get_temp_dir().'/http_cache');
    }

    public function assertHttpKernelIsCalled()
    {
        $this->assertTrue($this->kernel->hasBeenCalled());
    }

    public function assertHttpKernelIsNotCalled()
    {
        $this->assertFalse($this->kernel->hasBeenCalled());
    }

    public function assertResponseOk()
    {
        $this->assertEquals(200, $this->response->getStatusCode());
    }

    public function assertTraceContains($trace)
    {
        $traces = $this->cache->getTraces();
        $traces = current($traces);

        $this->assertRegExp('/'.$trace.'/', implode(', ', $traces));
    }

    public function assertTraceNotContains($trace)
    {
        $traces = $this->cache->getTraces();
        $traces = current($traces);

        $this->assertNotRegExp('/'.$trace.'/', implode(', ', $traces));
    }

    public function assertExceptionsAreCaught()
    {
        $this->assertTrue($this->kernel->isCatchingExceptions());
    }

    public function assertExceptionsAreNotCaught()
    {
        $this->assertFalse($this->kernel->isCatchingExceptions());
    }

    public function request($method, $uri = '/', $server = array(), $cookies = array(), $esi = false, $headers = array())
    {
        if (null === $this->kernel) {
            throw new \LogicException('You must call setNextResponse() before calling request().');
        }

        $this->kernel->reset();

        $this->store = new Store(sys_get_temp_dir().'/http_cache');

        $this->cacheConfig['debug'] = true;

        $this->esi = $esi ? new Esi() : null;
        $this->cache = new HttpCache($this->kernel, $this->store, $this->esi, $this->cacheConfig);
        $this->request = Request::create($uri, $method, array(), $cookies, array(), $server);
        $this->request->headers->add($headers);

        $this->response = $this->cache->handle($this->request, HttpKernelInterface::MASTER_REQUEST, $this->catch);

        $this->responses[] = $this->response;
    }

    public function getMetaStorageValues()
    {
        $values = array();
        foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator(sys_get_temp_dir().'/http_cache/md', \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
            $values[] = file_get_contents($file);
        }

        return $values;
    }

    // A basic response with 200 status code and a tiny body.
    public function setNextResponse($statusCode = 200, array $headers = array(), $body = 'Hello World', \Closure $customizer = null)
    {
        $this->kernel = new TestHttpKernel($body, $statusCode, $headers, $customizer);
    }

    public function setNextResponses($responses)
    {
        $this->kernel = new TestMultipleHttpKernel($responses);
    }

    public function catchExceptions($catch = true)
    {
        $this->catch = $catch;
    }

    public static function clearDirectory($directory)
    {
        if (!is_dir($directory)) {
            return;
        }

        $fp = opendir($directory);
        while (false !== $file = readdir($fp)) {
            if (!in_array($file, array('.', '..'))) {
                if (is_link($directory.'/'.$file)) {
                    unlink($directory.'/'.$file);
                } elseif (is_dir($directory.'/'.$file)) {
                    self::clearDirectory($directory.'/'.$file);
                    rmdir($directory.'/'.$file);
                } else {
                    unlink($directory.'/'.$file);
                }
            }
        }

        closedir($fp);
    }
}
PK��Z����Z&Z&Jtest/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\HttpCache;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpCache\Store;

class StoreTest extends \PHPUnit_Framework_TestCase
{
    protected $request;
    protected $response;
    protected $store;

    protected function setUp()
    {
        $this->request = Request::create('/');
        $this->response = new Response('hello world', 200, array());

        HttpCacheTestCase::clearDirectory(sys_get_temp_dir().'/http_cache');

        $this->store = new Store(sys_get_temp_dir().'/http_cache');
    }

    protected function tearDown()
    {
        $this->store = null;
        $this->request = null;
        $this->response = null;

        HttpCacheTestCase::clearDirectory(sys_get_temp_dir().'/http_cache');
    }

    public function testReadsAnEmptyArrayWithReadWhenNothingCachedAtKey()
    {
        $this->assertEmpty($this->getStoreMetadata('/nothing'));
    }

    public function testUnlockFileThatDoesExist()
    {
        $cacheKey = $this->storeSimpleEntry();
        $this->store->lock($this->request);

        $this->assertTrue($this->store->unlock($this->request));
    }

    public function testUnlockFileThatDoesNotExist()
    {
        $this->assertFalse($this->store->unlock($this->request));
    }

    public function testRemovesEntriesForKeyWithPurge()
    {
        $request = Request::create('/foo');
        $this->store->write($request, new Response('foo'));

        $metadata = $this->getStoreMetadata($request);
        $this->assertNotEmpty($metadata);

        $this->assertTrue($this->store->purge('/foo'));
        $this->assertEmpty($this->getStoreMetadata($request));

        // cached content should be kept after purging
        $path = $this->store->getPath($metadata[0][1]['x-content-digest'][0]);
        $this->assertTrue(is_file($path));

        $this->assertFalse($this->store->purge('/bar'));
    }

    public function testStoresACacheEntry()
    {
        $cacheKey = $this->storeSimpleEntry();

        $this->assertNotEmpty($this->getStoreMetadata($cacheKey));
    }

    public function testSetsTheXContentDigestResponseHeaderBeforeStoring()
    {
        $cacheKey = $this->storeSimpleEntry();
        $entries = $this->getStoreMetadata($cacheKey);
        list ($req, $res) = $entries[0];

        $this->assertEquals('en9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08', $res['x-content-digest'][0]);
    }

    public function testFindsAStoredEntryWithLookup()
    {
        $this->storeSimpleEntry();
        $response = $this->store->lookup($this->request);

        $this->assertNotNull($response);
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $response);
    }

    public function testDoesNotFindAnEntryWithLookupWhenNoneExists()
    {
        $request = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar'));

        $this->assertNull($this->store->lookup($request));
    }

    public function testCanonizesUrlsForCacheKeys()
    {
        $this->storeSimpleEntry($path = '/test?x=y&p=q');
        $hitsReq = Request::create($path);
        $missReq = Request::create('/test?p=x');

        $this->assertNotNull($this->store->lookup($hitsReq));
        $this->assertNull($this->store->lookup($missReq));
    }

    public function testDoesNotFindAnEntryWithLookupWhenTheBodyDoesNotExist()
    {
        $this->storeSimpleEntry();
        $this->assertNotNull($this->response->headers->get('X-Content-Digest'));
        $path = $this->getStorePath($this->response->headers->get('X-Content-Digest'));
        @unlink($path);
        $this->assertNull($this->store->lookup($this->request));
    }

    public function testRestoresResponseHeadersProperlyWithLookup()
    {
        $this->storeSimpleEntry();
        $response = $this->store->lookup($this->request);

        $this->assertEquals($response->headers->all(), array_merge(array('content-length' => 4, 'x-body-file' => array($this->getStorePath($response->headers->get('X-Content-Digest')))), $this->response->headers->all()));
    }

    public function testRestoresResponseContentFromEntityStoreWithLookup()
    {
        $this->storeSimpleEntry();
        $response = $this->store->lookup($this->request);
        $this->assertEquals($this->getStorePath('en'.hash('sha256', 'test')), $response->getContent());
    }

    public function testInvalidatesMetaAndEntityStoreEntriesWithInvalidate()
    {
        $this->storeSimpleEntry();
        $this->store->invalidate($this->request);
        $response = $this->store->lookup($this->request);
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $response);
        $this->assertFalse($response->isFresh());
    }

    public function testSucceedsQuietlyWhenInvalidateCalledWithNoMatchingEntries()
    {
        $req = Request::create('/test');
        $this->store->invalidate($req);
        $this->assertNull($this->store->lookup($this->request));
    }

    public function testDoesNotReturnEntriesThatVaryWithLookup()
    {
        $req1 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar'));
        $req2 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Bling', 'HTTP_BAR' => 'Bam'));
        $res = new Response('test', 200, array('Vary' => 'Foo Bar'));
        $this->store->write($req1, $res);

        $this->assertNull($this->store->lookup($req2));
    }

    public function testStoresMultipleResponsesForEachVaryCombination()
    {
        $req1 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar'));
        $res1 = new Response('test 1', 200, array('Vary' => 'Foo Bar'));
        $key = $this->store->write($req1, $res1);

        $req2 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Bling', 'HTTP_BAR' => 'Bam'));
        $res2 = new Response('test 2', 200, array('Vary' => 'Foo Bar'));
        $this->store->write($req2, $res2);

        $req3 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Baz', 'HTTP_BAR' => 'Boom'));
        $res3 = new Response('test 3', 200, array('Vary' => 'Foo Bar'));
        $this->store->write($req3, $res3);

        $this->assertEquals($this->getStorePath('en'.hash('sha256', 'test 3')), $this->store->lookup($req3)->getContent());
        $this->assertEquals($this->getStorePath('en'.hash('sha256', 'test 2')), $this->store->lookup($req2)->getContent());
        $this->assertEquals($this->getStorePath('en'.hash('sha256', 'test 1')), $this->store->lookup($req1)->getContent());

        $this->assertCount(3, $this->getStoreMetadata($key));
    }

    public function testOverwritesNonVaryingResponseWithStore()
    {
        $req1 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar'));
        $res1 = new Response('test 1', 200, array('Vary' => 'Foo Bar'));
        $key = $this->store->write($req1, $res1);
        $this->assertEquals($this->getStorePath('en'.hash('sha256', 'test 1')), $this->store->lookup($req1)->getContent());

        $req2 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Bling', 'HTTP_BAR' => 'Bam'));
        $res2 = new Response('test 2', 200, array('Vary' => 'Foo Bar'));
        $this->store->write($req2, $res2);
        $this->assertEquals($this->getStorePath('en'.hash('sha256', 'test 2')), $this->store->lookup($req2)->getContent());

        $req3 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar'));
        $res3 = new Response('test 3', 200, array('Vary' => 'Foo Bar'));
        $key = $this->store->write($req3, $res3);
        $this->assertEquals($this->getStorePath('en'.hash('sha256', 'test 3')), $this->store->lookup($req3)->getContent());

        $this->assertCount(2, $this->getStoreMetadata($key));
    }

    public function testLocking()
    {
        $req = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar'));
        $this->assertTrue($this->store->lock($req));

        $path = $this->store->lock($req);
        $this->assertTrue($this->store->isLocked($req));

        $this->store->unlock($req);
        $this->assertFalse($this->store->isLocked($req));
    }

    protected function storeSimpleEntry($path = null, $headers = array())
    {
        if (null === $path) {
            $path = '/test';
        }

        $this->request = Request::create($path, 'get', array(), array(), array(), $headers);
        $this->response = new Response('test', 200, array('Cache-Control' => 'max-age=420'));

        return $this->store->write($this->request, $this->response);
    }

    protected function getStoreMetadata($key)
    {
        $r = new \ReflectionObject($this->store);
        $m = $r->getMethod('getMetadata');
        $m->setAccessible(true);

        if ($key instanceof Request) {
            $m1 = $r->getMethod('getCacheKey');
            $m1->setAccessible(true);
            $key = $m1->invoke($this->store, $key);
        }

        return $m->invoke($this->store, $key);
    }

    protected function getStorePath($key)
    {
        $r = new \ReflectionObject($this->store);
        $m = $r->getMethod('getPath');
        $m->setAccessible(true);

        return $m->invoke($this->store, $key);
    }
}
PK��Z�`1Mtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Config/FileLocatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\Config;

use Symfony\Component\HttpKernel\Config\FileLocator;

class FileLocatorTest extends \PHPUnit_Framework_TestCase
{
    public function testLocate()
    {
        $kernel = $this->getMock('Symfony\Component\HttpKernel\KernelInterface');
        $kernel
            ->expects($this->atLeastOnce())
            ->method('locateResource')
            ->with('@BundleName/some/path', null, true)
            ->will($this->returnValue('/bundle-name/some/path'));
        $locator = new FileLocator($kernel);
        $this->assertEquals('/bundle-name/some/path', $locator->locate('@BundleName/some/path'));

        $kernel
            ->expects($this->never())
            ->method('locateResource');
        $this->setExpectedException('LogicException');
        $locator->locate('/some/path');
    }

    public function testLocateWithGlobalResourcePath()
    {
        $kernel = $this->getMock('Symfony\Component\HttpKernel\KernelInterface');
        $kernel
            ->expects($this->atLeastOnce())
            ->method('locateResource')
            ->with('@BundleName/some/path', '/global/resource/path', false);

        $locator = new FileLocator($kernel, '/global/resource/path');
        $locator->locate('@BundleName/some/path', null, false);
    }
}
PK��ZK�w��Htest/HttpKernel/Symfony/Component/HttpKernel/Tests/Bundle/BundleTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\Bundle;

use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConsoleCommandPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionAbsentBundle\ExtensionAbsentBundle;
use Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionPresentBundle\Command\FooCommand;
use Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionPresentBundle\ExtensionPresentBundle;

class BundleTest extends \PHPUnit_Framework_TestCase
{
    public function testRegisterCommands()
    {
        $cmd = new FooCommand();
        $app = $this->getMock('Symfony\Component\Console\Application');
        $app->expects($this->once())->method('add')->with($this->equalTo($cmd));

        $bundle = new ExtensionPresentBundle();
        $bundle->registerCommands($app);

        $bundle2 = new ExtensionAbsentBundle();

        $this->assertNull($bundle2->registerCommands($app));
    }

    public function testRegisterCommandsIngoreCommandAsAService()
    {
        $container = new ContainerBuilder();
        $container->addCompilerPass(new AddConsoleCommandPass());
        $definition = new Definition('Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionPresentBundle\Command\FooCommand');
        $definition->addTag('console.command');
        $container->setDefinition('my-command', $definition);
        $container->compile();

        $application = $this->getMock('Symfony\Component\Console\Application');
        // Never called, because it's the
        // Symfony\Bundle\FrameworkBundle\Console\Application that register
        // commands as a service
        $application->expects($this->never())->method('add');

        $bundle = new ExtensionPresentBundle();
        $bundle->setContainer($container);
        $bundle->registerCommands($application);
    }
}
PK��Z!�g���[test/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/MemcacheProfilerStorageTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\Profiler;

use Symfony\Component\HttpKernel\Profiler\MemcacheProfilerStorage;
use Symfony\Component\HttpKernel\Tests\Profiler\Mock\MemcacheMock;

class MemcacheProfilerStorageTest extends AbstractProfilerStorageTest
{
    protected static $storage;

    protected function setUp()
    {
        $memcacheMock = new MemcacheMock();
        $memcacheMock->addServer('127.0.0.1', 11211);

        self::$storage = new MemcacheProfilerStorage('memcache://127.0.0.1:11211', '', '', 86400);
        self::$storage->setMemcache($memcacheMock);

        if (self::$storage) {
            self::$storage->purge();
        }
    }

    protected function tearDown()
    {
        if (self::$storage) {
            self::$storage->purge();
            self::$storage = false;
        }
    }

    /**
     * @return \Symfony\Component\HttpKernel\Profiler\ProfilerStorageInterface
     */
    protected function getStorage()
    {
        return self::$storage;
    }
}
PK��Z�[���\test/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/MemcachedProfilerStorageTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\Profiler;

use Symfony\Component\HttpKernel\Profiler\MemcachedProfilerStorage;
use Symfony\Component\HttpKernel\Tests\Profiler\Mock\MemcachedMock;

class MemcachedProfilerStorageTest extends AbstractProfilerStorageTest
{
    protected static $storage;

    protected function setUp()
    {
        $memcachedMock = new MemcachedMock();
        $memcachedMock->addServer('127.0.0.1', 11211);

        self::$storage = new MemcachedProfilerStorage('memcached://127.0.0.1:11211', '', '', 86400);
        self::$storage->setMemcached($memcachedMock);

        if (self::$storage) {
            self::$storage->purge();
        }
    }

    protected function tearDown()
    {
        if (self::$storage) {
            self::$storage->purge();
            self::$storage = false;
        }
    }

    /**
     * @return \Symfony\Component\HttpKernel\Profiler\ProfilerStorageInterface
     */
    protected function getStorage()
    {
        return self::$storage;
    }
}
PK��ZT���
�
Wtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/FileProfilerStorageTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\Profiler;

use Symfony\Component\HttpKernel\Profiler\FileProfilerStorage;
use Symfony\Component\HttpKernel\Profiler\Profile;

class FileProfilerStorageTest extends AbstractProfilerStorageTest
{
    protected static $tmpDir;
    protected static $storage;

    protected static function cleanDir()
    {
        $flags = \FilesystemIterator::SKIP_DOTS;
        $iterator = new \RecursiveDirectoryIterator(self::$tmpDir, $flags);
        $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);

        foreach ($iterator as $file) {
            if (is_file($file)) {
                unlink($file);
            }
        }
    }

    public static function setUpBeforeClass()
    {
        self::$tmpDir = sys_get_temp_dir().'/sf2_profiler_file_storage';
        if (is_dir(self::$tmpDir)) {
            self::cleanDir();
        }
        self::$storage = new FileProfilerStorage('file:'.self::$tmpDir);
    }

    public static function tearDownAfterClass()
    {
        self::cleanDir();
    }

    protected function setUp()
    {
        self::$storage->purge();
    }

    /**
     * @return \Symfony\Component\HttpKernel\Profiler\ProfilerStorageInterface
     */
    protected function getStorage()
    {
        return self::$storage;
    }

    public function testMultiRowIndexFile()
    {
        $iteration = 3;
        for ($i = 0; $i < $iteration; $i++) {
            $profile = new Profile('token'.$i);
            $profile->setIp('127.0.0.'.$i);
            $profile->setUrl('http://foo.bar/'.$i);
            $storage = $this->getStorage();

            $storage->write($profile);
            $storage->write($profile);
            $storage->write($profile);
        }

        $handle = fopen(self::$tmpDir.'/index.csv', 'r');
        for ($i = 0; $i < $iteration; $i++) {
            $row = fgetcsv($handle);
            $this->assertEquals('token'.$i, $row[0]);
            $this->assertEquals('127.0.0.'.$i, $row[1]);
            $this->assertEquals('http://foo.bar/'.$i, $row[3]);
        }
        $this->assertFalse(fgetcsv($handle));
    }

    public function testReadLineFromFile()
    {
        $r = new \ReflectionMethod(self::$storage, 'readLineFromFile');

        $r->setAccessible(true);

        $h = tmpfile();

        fwrite($h, "line1\n\n\nline2\n");
        fseek($h, 0, SEEK_END);

        $this->assertEquals("line2", $r->invoke(self::$storage, $h));
        $this->assertEquals("line1", $r->invoke(self::$storage, $h));
    }
}
PK��Z�,���)�)[test/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/AbstractProfilerStorageTest.phpnu�[���<?php
/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\Profiler;

use Symfony\Component\HttpKernel\Profiler\Profile;

abstract class AbstractProfilerStorageTest extends \PHPUnit_Framework_TestCase
{
    public function testStore()
    {
        for ($i = 0; $i < 10; $i ++) {
            $profile = new Profile('token_'.$i);
            $profile->setIp('127.0.0.1');
            $profile->setUrl('http://foo.bar');
            $profile->setMethod('GET');
            $this->getStorage()->write($profile);
        }
        $this->assertCount(10, $this->getStorage()->find('127.0.0.1', 'http://foo.bar', 20, 'GET'), '->write() stores data in the storage');
    }

    public function testChildren()
    {
        $parentProfile = new Profile('token_parent');
        $parentProfile->setIp('127.0.0.1');
        $parentProfile->setUrl('http://foo.bar/parent');

        $childProfile = new Profile('token_child');
        $childProfile->setIp('127.0.0.1');
        $childProfile->setUrl('http://foo.bar/child');

        $parentProfile->addChild($childProfile);

        $this->getStorage()->write($parentProfile);
        $this->getStorage()->write($childProfile);

        // Load them from storage
        $parentProfile = $this->getStorage()->read('token_parent');
        $childProfile  = $this->getStorage()->read('token_child');

        // Check child has link to parent
        $this->assertNotNull($childProfile->getParent());
        $this->assertEquals($parentProfile->getToken(), $childProfile->getParentToken());

        // Check parent has child
        $children = $parentProfile->getChildren();
        $this->assertCount(1, $children);
        $this->assertEquals($childProfile->getToken(), $children[0]->getToken());
    }

    public function testStoreSpecialCharsInUrl()
    {
        // The storage accepts special characters in URLs (Even though URLs are not
        // supposed to contain them)
        $profile = new Profile('simple_quote');
        $profile->setUrl('http://foo.bar/\'');
        $this->getStorage()->write($profile);
        $this->assertTrue(false !== $this->getStorage()->read('simple_quote'), '->write() accepts single quotes in URL');

        $profile = new Profile('double_quote');
        $profile->setUrl('http://foo.bar/"');
        $this->getStorage()->write($profile);
        $this->assertTrue(false !== $this->getStorage()->read('double_quote'), '->write() accepts double quotes in URL');

        $profile = new Profile('backslash');
        $profile->setUrl('http://foo.bar/\\');
        $this->getStorage()->write($profile);
        $this->assertTrue(false !== $this->getStorage()->read('backslash'), '->write() accepts backslash in URL');

        $profile = new Profile('comma');
        $profile->setUrl('http://foo.bar/,');
        $this->getStorage()->write($profile);
        $this->assertTrue(false !== $this->getStorage()->read('comma'), '->write() accepts comma in URL');
    }

    public function testStoreDuplicateToken()
    {
        $profile = new Profile('token');
        $profile->setUrl('http://example.com/');

        $this->assertTrue($this->getStorage()->write($profile), '->write() returns true when the token is unique');

        $profile->setUrl('http://example.net/');

        $this->assertTrue($this->getStorage()->write($profile), '->write() returns true when the token is already present in the storage');
        $this->assertEquals('http://example.net/', $this->getStorage()->read('token')->getUrl(), '->write() overwrites the current profile data');

        $this->assertCount(1, $this->getStorage()->find('', '', 1000, ''), '->find() does not return the same profile twice');
    }

    public function testRetrieveByIp()
    {
        $profile = new Profile('token');
        $profile->setIp('127.0.0.1');
        $profile->setMethod('GET');
        $this->getStorage()->write($profile);

        $this->assertCount(1, $this->getStorage()->find('127.0.0.1', '', 10, 'GET'), '->find() retrieve a record by IP');
        $this->assertCount(0, $this->getStorage()->find('127.0.%.1', '', 10, 'GET'), '->find() does not interpret a "%" as a wildcard in the IP');
        $this->assertCount(0, $this->getStorage()->find('127.0._.1', '', 10, 'GET'), '->find() does not interpret a "_" as a wildcard in the IP');
    }

    public function testRetrieveByUrl()
    {
        $profile = new Profile('simple_quote');
        $profile->setIp('127.0.0.1');
        $profile->setUrl('http://foo.bar/\'');
        $profile->setMethod('GET');
        $this->getStorage()->write($profile);

        $profile = new Profile('double_quote');
        $profile->setIp('127.0.0.1');
        $profile->setUrl('http://foo.bar/"');
        $profile->setMethod('GET');
        $this->getStorage()->write($profile);

        $profile = new Profile('backslash');
        $profile->setIp('127.0.0.1');
        $profile->setUrl('http://foo\\bar/');
        $profile->setMethod('GET');
        $this->getStorage()->write($profile);

        $profile = new Profile('percent');
        $profile->setIp('127.0.0.1');
        $profile->setUrl('http://foo.bar/%');
        $profile->setMethod('GET');
        $this->getStorage()->write($profile);

        $profile = new Profile('underscore');
        $profile->setIp('127.0.0.1');
        $profile->setUrl('http://foo.bar/_');
        $profile->setMethod('GET');
        $this->getStorage()->write($profile);

        $profile = new Profile('semicolon');
        $profile->setIp('127.0.0.1');
        $profile->setUrl('http://foo.bar/;');
        $profile->setMethod('GET');
        $this->getStorage()->write($profile);

        $this->assertCount(1, $this->getStorage()->find('127.0.0.1', 'http://foo.bar/\'', 10, 'GET'), '->find() accepts single quotes in URLs');
        $this->assertCount(1, $this->getStorage()->find('127.0.0.1', 'http://foo.bar/"', 10, 'GET'), '->find() accepts double quotes in URLs');
        $this->assertCount(1, $this->getStorage()->find('127.0.0.1', 'http://foo\\bar/', 10, 'GET'), '->find() accepts backslash in URLs');
        $this->assertCount(1, $this->getStorage()->find('127.0.0.1', 'http://foo.bar/;', 10, 'GET'), '->find() accepts semicolon in URLs');
        $this->assertCount(1, $this->getStorage()->find('127.0.0.1', 'http://foo.bar/%', 10, 'GET'), '->find() does not interpret a "%" as a wildcard in the URL');
        $this->assertCount(1, $this->getStorage()->find('127.0.0.1', 'http://foo.bar/_', 10, 'GET'), '->find() does not interpret a "_" as a wildcard in the URL');
    }

    public function testStoreTime()
    {
        $dt = new \DateTime('now');
        $start = $dt->getTimestamp();

        for ($i = 0; $i < 3; $i++) {
            $dt->modify('+1 minute');
            $profile = new Profile('time_'.$i);
            $profile->setIp('127.0.0.1');
            $profile->setUrl('http://foo.bar');
            $profile->setTime($dt->getTimestamp());
            $profile->setMethod('GET');
            $this->getStorage()->write($profile);
        }

        $records = $this->getStorage()->find('', '', 3, 'GET', $start, time() + 3 * 60);
        $this->assertCount(3, $records, '->find() returns all previously added records');
        $this->assertEquals($records[0]['token'], 'time_2', '->find() returns records ordered by time in descendant order');
        $this->assertEquals($records[1]['token'], 'time_1', '->find() returns records ordered by time in descendant order');
        $this->assertEquals($records[2]['token'], 'time_0', '->find() returns records ordered by time in descendant order');

        $records = $this->getStorage()->find('', '', 3, 'GET', $start, time() + 2 * 60);
        $this->assertCount(2, $records, '->find() should return only first two of the previously added records');
    }

    public function testRetrieveByEmptyUrlAndIp()
    {
        for ($i = 0; $i < 5; $i++) {
            $profile = new Profile('token_'.$i);
            $profile->setMethod('GET');
            $this->getStorage()->write($profile);
        }
        $this->assertCount(5, $this->getStorage()->find('', '', 10, 'GET'), '->find() returns all previously added records');
        $this->getStorage()->purge();
    }

    public function testRetrieveByMethodAndLimit()
    {
        foreach (array('POST', 'GET') as $method) {
            for ($i = 0; $i < 5; $i++) {
                $profile = new Profile('token_'.$i.$method);
                $profile->setMethod($method);
                $this->getStorage()->write($profile);
            }
        }

        $this->assertCount(5, $this->getStorage()->find('', '', 5, 'POST'));

        $this->getStorage()->purge();
    }

    public function testPurge()
    {
        $profile = new Profile('token1');
        $profile->setIp('127.0.0.1');
        $profile->setUrl('http://example.com/');
        $profile->setMethod('GET');
        $this->getStorage()->write($profile);

        $this->assertTrue(false !== $this->getStorage()->read('token1'));
        $this->assertCount(1, $this->getStorage()->find('127.0.0.1', '', 10, 'GET'));

        $profile = new Profile('token2');
        $profile->setIp('127.0.0.1');
        $profile->setUrl('http://example.net/');
        $profile->setMethod('GET');
        $this->getStorage()->write($profile);

        $this->assertTrue(false !== $this->getStorage()->read('token2'));
        $this->assertCount(2, $this->getStorage()->find('127.0.0.1', '', 10, 'GET'));

        $this->getStorage()->purge();

        $this->assertEmpty($this->getStorage()->read('token'), '->purge() removes all data stored by profiler');
        $this->assertCount(0, $this->getStorage()->find('127.0.0.1', '', 10, 'GET'), '->purge() removes all items from index');
    }

    public function testDuplicates()
    {
        for ($i = 1; $i <= 5; $i++) {
            $profile = new Profile('foo'.$i);
            $profile->setIp('127.0.0.1');
            $profile->setUrl('http://example.net/');
            $profile->setMethod('GET');

            ///three duplicates
            $this->getStorage()->write($profile);
            $this->getStorage()->write($profile);
            $this->getStorage()->write($profile);
        }
        $this->assertCount(3, $this->getStorage()->find('127.0.0.1', 'http://example.net/', 3, 'GET'), '->find() method returns incorrect number of entries');
    }

    /**
     * @return \Symfony\Component\HttpKernel\Profiler\ProfilerStorageInterface
     */
    abstract protected function getStorage();
}
PK��Z�.�\��Rtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/Mock/MemcachedMock.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\Profiler\Mock;

/**
 * MemcachedMock for simulating Memcached extension in tests.
 *
 * @author Andrej Hudec <pulzarraider@gmail.com>
 */
class MemcachedMock
{
    private $connected = false;
    private $storage = array();

    /**
     * Set a Memcached option
     *
     * @param integer $option
     * @param mixed   $value
     *
     * @return boolean
     */
    public function setOption($option, $value)
    {
        return true;
    }

    /**
     * Add a memcached server to connection pool
     *
     * @param string  $host
     * @param integer $port
     * @param integer $weight
     *
     * @return boolean
     */
    public function addServer($host, $port = 11211, $weight = 0)
    {
        if ('127.0.0.1' == $host && 11211 == $port) {
            $this->connected = true;

            return true;
        }

        return false;
    }

    /**
     * Add an item to the server only if such key doesn't exist at the server yet.
     *
     * @param string  $key
     * @param mixed   $value
     * @param integer $expiration
     *
     * @return boolean
     */
    public function add($key, $value, $expiration = 0)
    {
        if (!$this->connected) {
            return false;
        }

        if (!isset($this->storage[$key])) {
            $this->storeData($key, $value);

            return true;
        }

        return false;
    }

    /**
     * Store data at the server.
     *
     * @param string  $key
     * @param mixed   $value
     * @param integer $expiration
     *
     * @return boolean
     */
    public function set($key, $value, $expiration = null)
    {
        if (!$this->connected) {
            return false;
        }

        $this->storeData($key, $value);

        return true;
    }

    /**
     * Replace value of the existing item.
     *
     * @param string  $key
     * @param mixed   $value
     * @param integer $expiration
     *
     * @return boolean
     */
    public function replace($key, $value, $expiration = null)
    {
        if (!$this->connected) {
            return false;
        }

        if (isset($this->storage[$key])) {
            $this->storeData($key, $value);

            return true;
        }

        return false;
    }

    /**
     * Retrieve item from the server.
     *
     * @param string   $key
     * @param callable $cache_cb
     * @param float    $cas_token
     *
     * @return boolean
     */
    public function get($key, $cache_cb = null, &$cas_token = null)
    {
        if (!$this->connected) {
            return false;
        }

        return $this->getData($key);
    }

    /**
     * Append data to an existing item
     *
     * @param string $key
     * @param string $value
     *
     * @return boolean
     */
    public function append($key, $value)
    {
        if (!$this->connected) {
            return false;
        }

        if (isset($this->storage[$key])) {
            $this->storeData($key, $this->getData($key).$value);

            return true;
        }

        return false;
    }

    /**
     * Delete item from the server
     *
     * @param string $key
     *
     * @return boolean
     */
    public function delete($key)
    {
        if (!$this->connected) {
            return false;
        }

        if (isset($this->storage[$key])) {
            unset($this->storage[$key]);

            return true;
        }

        return false;
    }

    /**
     * Flush all existing items at the server
     *
     * @return boolean
     */
    public function flush()
    {
        if (!$this->connected) {
            return false;
        }

        $this->storage = array();

        return true;
    }

    private function getData($key)
    {
        if (isset($this->storage[$key])) {
            return unserialize($this->storage[$key]);
        }

        return false;
    }

    private function storeData($key, $value)
    {
        $this->storage[$key] = serialize($value);

        return true;
    }
}
PK��Zi�]��Qtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/Mock/MemcacheMock.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\Profiler\Mock;

/**
 * MemcacheMock for simulating Memcache extension in tests.
 *
 * @author Andrej Hudec <pulzarraider@gmail.com>
 */
class MemcacheMock
{
    private $connected = false;
    private $storage = array();

    /**
     * Open memcached server connection
     *
     * @param string  $host
     * @param integer $port
     * @param integer $timeout
     *
     * @return boolean
     */
    public function connect($host, $port = null, $timeout = null)
    {
        if ('127.0.0.1' == $host && 11211 == $port) {
            $this->connected = true;

            return true;
        }

        return false;
    }

    /**
     * Open memcached server persistent connection
     *
     * @param string  $host
     * @param integer $port
     * @param integer $timeout
     *
     * @return boolean
     */
    public function pconnect($host, $port = null, $timeout = null)
    {
        if ('127.0.0.1' == $host && 11211 == $port) {
            $this->connected = true;

            return true;
        }

        return false;
    }

    /**
     * Add a memcached server to connection pool
     *
     * @param string   $host
     * @param integer  $port
     * @param boolean  $persistent
     * @param integer  $weight
     * @param integer  $timeout
     * @param integer  $retry_interval
     * @param boolean  $status
     * @param callable $failure_callback
     * @param integer  $timeoutms
     *
     * @return boolean
     */
    public function addServer($host, $port = 11211, $persistent = null, $weight = null, $timeout = null, $retry_interval = null, $status = null, $failure_callback = null, $timeoutms = null)
    {
        if ('127.0.0.1' == $host && 11211 == $port) {
            $this->connected = true;

            return true;
        }

        return false;
    }

    /**
     * Add an item to the server only if such key doesn't exist at the server yet.
     *
     * @param string  $key
     * @param mixed   $var
     * @param integer $flag
     * @param integer $expire
     *
     * @return boolean
     */
    public function add($key, $var, $flag = null, $expire = null)
    {
        if (!$this->connected) {
            return false;
        }

        if (!isset($this->storage[$key])) {
            $this->storeData($key, $var);

            return true;
        }

        return false;
    }

    /**
     * Store data at the server.
     *
     * @param string  $key
     * @param string  $var
     * @param integer $flag
     * @param integer $expire
     *
     * @return boolean
     */
    public function set($key, $var, $flag = null, $expire = null)
    {
        if (!$this->connected) {
            return false;
        }

        $this->storeData($key, $var);

        return true;
    }

    /**
     * Replace value of the existing item.
     *
     * @param string  $key
     * @param mixed   $var
     * @param integer $flag
     * @param integer $expire
     *
     * @return boolean
     */
    public function replace($key, $var, $flag = null, $expire = null)
    {
        if (!$this->connected) {
            return false;
        }

        if (isset($this->storage[$key])) {
            $this->storeData($key, $var);

            return true;
        }

        return false;
    }

    /**
     * Retrieve item from the server.
     *
     * @param string|array  $key
     * @param integer|array $flags
     *
     * @return mixed
     */
    public function get($key, &$flags = null)
    {
        if (!$this->connected) {
            return false;
        }

        if (is_array($key)) {
            $result = array();
            foreach ($key as $k) {
                if (isset($this->storage[$k])) {
                    $result[] = $this->getData($k);
                }
            }

            return $result;
        }

        return $this->getData($key);
    }

    /**
     * Delete item from the server
     *
     * @param string $key
     *
     * @return boolean
     */
    public function delete($key)
    {
        if (!$this->connected) {
            return false;
        }

        if (isset($this->storage[$key])) {
            unset($this->storage[$key]);

            return true;
        }

        return false;
    }

    /**
     * Flush all existing items at the server
     *
     * @return boolean
     */
    public function flush()
    {
        if (!$this->connected) {
            return false;
        }

        $this->storage = array();

        return true;
    }

    /**
     * Close memcached server connection
     *
     * @return boolean
     */
    public function close()
    {
        $this->connected = false;

        return true;
    }

    private function getData($key)
    {
        if (isset($this->storage[$key])) {
            return unserialize($this->storage[$key]);
        }

        return false;
    }

    private function storeData($key, $value)
    {
        $this->storage[$key] = serialize($value);

        return true;
    }
}
PK��Ze��K

Ntest/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/Mock/RedisMock.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\Profiler\Mock;

/**
 * RedisMock for simulating Redis extension in tests.
 *
 * @author Andrej Hudec <pulzarraider@gmail.com>
 */
class RedisMock
{
    private $connected = false;
    private $storage = array();

    /**
     * Add a server to connection pool
     *
     * @param string  $host
     * @param integer $port
     * @param float   $timeout
     *
     * @return boolean
     */
    public function connect($host, $port = 6379, $timeout = 0)
    {
        if ('127.0.0.1' == $host && 6379 == $port) {
            $this->connected = true;

            return true;
        }

        return false;
    }

    /**
     * Set client option.
     *
     * @param integer $name
     * @param integer $value
     *
     * @return boolean
     */
    public function setOption($name, $value)
    {
        if (!$this->connected) {
            return false;
        }

        return true;
    }

    /**
     * Verify if the specified key exists.
     *
     * @param string $key
     *
     * @return boolean
     */
    public function exists($key)
    {
        if (!$this->connected) {
            return false;
        }

        return isset($this->storage[$key]);
    }

    /**
     * Store data at the server with expiration time.
     *
     * @param string  $key
     * @param integer $ttl
     * @param mixed   $value
     *
     * @return boolean
     */
    public function setex($key, $ttl, $value)
    {
        if (!$this->connected) {
            return false;
        }

        $this->storeData($key, $value);

        return true;
    }

    /**
     * Sets an expiration time on an item.
     *
     * @param string  $key
     * @param integer $ttl
     *
     * @return boolean
     */
    public function setTimeout($key, $ttl)
    {
        if (!$this->connected) {
            return false;
        }

        if (isset($this->storage[$key])) {
            return true;
        }

        return false;
    }

    /**
     * Retrieve item from the server.
     *
     * @param string $key
     *
     * @return boolean
     */
    public function get($key)
    {
        if (!$this->connected) {
            return false;
        }

        return $this->getData($key);
    }

    /**
     * Append data to an existing item
     *
     * @param string $key
     * @param string $value
     *
     * @return integer Size of the value after the append.
     */
    public function append($key, $value)
    {
        if (!$this->connected) {
            return false;
        }

        if (isset($this->storage[$key])) {
            $this->storeData($key, $this->getData($key).$value);

            return strlen($this->storage[$key]);
        }

        return false;
    }

    /**
     * Remove specified keys.
     *
     * @param string|array $key
     *
     * @return integer
     */
    public function delete($key)
    {
        if (!$this->connected) {
            return false;
        }

        if (is_array($key)) {
            $result = 0;
            foreach ($key as $k) {
                if (isset($this->storage[$k])) {
                    unset($this->storage[$k]);
                    ++$result;
                }
            }

            return $result;
        }

        if (isset($this->storage[$key])) {
            unset($this->storage[$key]);

            return 1;
        }

        return 0;
    }

    /**
     * Flush all existing items from all databases at the server.
     *
     * @return boolean
     */
    public function flushAll()
    {
        if (!$this->connected) {
            return false;
        }

        $this->storage = array();

        return true;
    }

    /**
     * Close Redis server connection
     *
     * @return boolean
     */
    public function close()
    {
        $this->connected = false;

        return true;
    }

    private function getData($key)
    {
        if (isset($this->storage[$key])) {
            return unserialize($this->storage[$key]);
        }

        return false;
    }

    private function storeData($key, $value)
    {
        $this->storage[$key] = serialize($value);

        return true;
    }

    public function select($dbnum)
    {
        if (!$this->connected) {
            return false;
        }

        if (0 > $dbnum) {
            return false;
        }

        return true;
    }
}
PK��Z`ej��Ztest/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/MongoDbProfilerStorageTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\Profiler;

use Symfony\Component\HttpKernel\Profiler\MongoDbProfilerStorage;
use Symfony\Component\HttpKernel\Profiler\Profile;
use Symfony\Component\HttpKernel\DataCollector\DataCollector;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class DummyMongoDbProfilerStorage extends MongoDbProfilerStorage
{
    public function getMongo()
    {
        return parent::getMongo();
    }
}

class MongoDbProfilerStorageTestDataCollector extends DataCollector
{
    public function setData($data)
    {
        $this->data = $data;
    }

    public function getData()
    {
        return $this->data;
    }

    public function collect(Request $request, Response $response, \Exception $exception = null)
    {
    }

    public function getName()
    {
        return 'test_data_collector';
    }
}

class MongoDbProfilerStorageTest extends AbstractProfilerStorageTest
{
    protected static $storage;

    public static function setUpBeforeClass()
    {
        if (extension_loaded('mongo')) {
            self::$storage = new DummyMongoDbProfilerStorage('mongodb://localhost/symfony_tests/profiler_data', '', '', 86400);
            try {
                self::$storage->getMongo();
            } catch (\MongoConnectionException $e) {
                self::$storage = null;
            }
        }
    }

    public static function tearDownAfterClass()
    {
        if (self::$storage) {
            self::$storage->purge();
            self::$storage = null;
        }
    }

    public function getDsns()
    {
        return array(
            array('mongodb://localhost/symfony_tests/profiler_data', array(
                'mongodb://localhost/symfony_tests',
                'symfony_tests',
                'profiler_data'
            )),
            array('mongodb://user:password@localhost/symfony_tests/profiler_data', array(
                'mongodb://user:password@localhost/symfony_tests',
                'symfony_tests',
                'profiler_data'
            )),
            array('mongodb://user:password@localhost/admin/symfony_tests/profiler_data', array(
                'mongodb://user:password@localhost/admin',
                'symfony_tests',
                'profiler_data'
            )),
            array('mongodb://user:password@localhost:27009,localhost:27010/?replicaSet=rs-name&authSource=admin/symfony_tests/profiler_data', array(
                'mongodb://user:password@localhost:27009,localhost:27010/?replicaSet=rs-name&authSource=admin',
                'symfony_tests',
                'profiler_data'
            ))
        );
    }

    public function testCleanup()
    {
        $dt = new \DateTime('-2 day');
        for ($i = 0; $i < 3; $i++) {
            $dt->modify('-1 day');
            $profile = new Profile('time_'.$i);
            $profile->setTime($dt->getTimestamp());
            $profile->setMethod('GET');
            self::$storage->write($profile);
        }
        $records = self::$storage->find('', '', 3, 'GET');
        $this->assertCount(1, $records, '->find() returns only one record');
        $this->assertEquals($records[0]['token'], 'time_2', '->find() returns the latest added record');
        self::$storage->purge();
    }

    /**
     * @dataProvider getDsns
     */
    public function testDsnParser($dsn, $expected)
    {
        $m = new \ReflectionMethod(self::$storage, 'parseDsn');
        $m->setAccessible(true);

        $this->assertEquals($expected, $m->invoke(self::$storage, $dsn));
    }

    public function testUtf8()
    {
        $profile = new Profile('utf8_test_profile');

        $data = 'HЁʃʃϿ, ϢorЃd!';
        $nonUtf8Data = mb_convert_encoding($data, 'UCS-2');

        $collector = new MongoDbProfilerStorageTestDataCollector();
        $collector->setData($nonUtf8Data);

        $profile->setCollectors(array($collector));

        self::$storage->write($profile);

        $readProfile = self::$storage->read('utf8_test_profile');
        $collectors = $readProfile->getCollectors();

        $this->assertCount(1, $collectors);
        $this->assertArrayHasKey('test_data_collector', $collectors);
        $this->assertEquals($nonUtf8Data, $collectors['test_data_collector']->getData(), 'Non-UTF8 data is properly encoded/decoded');
    }

    /**
     * @return \Symfony\Component\HttpKernel\Profiler\ProfilerStorageInterface
     */
    protected function getStorage()
    {
        return self::$storage;
    }

    protected function setUp()
    {
        if (self::$storage) {
            self::$storage->purge();
        } else {
            $this->markTestSkipped('MongoDbProfilerStorageTest requires the mongo PHP extension and a MongoDB server on localhost');
        }
    }
}
PK��Zp3hNNYtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/SqliteProfilerStorageTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\Profiler;

use Symfony\Component\HttpKernel\Profiler\SqliteProfilerStorage;

class SqliteProfilerStorageTest extends AbstractProfilerStorageTest
{
    protected static $dbFile;
    protected static $storage;

    public static function setUpBeforeClass()
    {
        self::$dbFile = tempnam(sys_get_temp_dir(), 'sf2_sqlite_storage');
        if (file_exists(self::$dbFile)) {
            @unlink(self::$dbFile);
        }
        self::$storage = new SqliteProfilerStorage('sqlite:'.self::$dbFile);
    }

    public static function tearDownAfterClass()
    {
        @unlink(self::$dbFile);
    }

    protected function setUp()
    {
        if (!class_exists('SQLite3') && (!class_exists('PDO') || !in_array('sqlite', \PDO::getAvailableDrivers()))) {
            $this->markTestSkipped('This test requires SQLite support in your environment');
        }
        self::$storage->purge();
    }

    /**
     * @return \Symfony\Component\HttpKernel\Profiler\ProfilerStorageInterface
     */
    protected function getStorage()
    {
        return self::$storage;
    }
}
PK��Z�FE��Xtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/RedisProfilerStorageTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\Profiler;

use Symfony\Component\HttpKernel\Profiler\RedisProfilerStorage;
use Symfony\Component\HttpKernel\Tests\Profiler\Mock\RedisMock;

class RedisProfilerStorageTest extends AbstractProfilerStorageTest
{
    protected static $storage;

    protected function setUp()
    {
        $redisMock = new RedisMock();
        $redisMock->connect('127.0.0.1', 6379);

        self::$storage = new RedisProfilerStorage('redis://127.0.0.1:6379', '', '', 86400);
        self::$storage->setRedis($redisMock);

        if (self::$storage) {
            self::$storage->purge();
        }
    }

    protected function tearDown()
    {
        if (self::$storage) {
            self::$storage->purge();
            self::$storage = false;
        }
    }

    /**
     * @return \Symfony\Component\HttpKernel\Profiler\ProfilerStorageInterface
     */
    protected function getStorage()
    {
        return self::$storage;
    }
}
PK��Z�&2TTLtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/ProfilerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\Profiler;

use Symfony\Component\HttpKernel\DataCollector\RequestDataCollector;
use Symfony\Component\HttpKernel\Profiler\SqliteProfilerStorage;
use Symfony\Component\HttpKernel\Profiler\Profiler;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class ProfilerTest extends \PHPUnit_Framework_TestCase
{
    public function testCollect()
    {
        if (!class_exists('SQLite3') && (!class_exists('PDO') || !in_array('sqlite', \PDO::getAvailableDrivers()))) {
            $this->markTestSkipped('This test requires SQLite support in your environment');
        }

        $request = new Request();
        $request->query->set('foo', 'bar');
        $response = new Response();
        $collector = new RequestDataCollector();

        $tmp = tempnam(sys_get_temp_dir(), 'sf2_profiler');
        if (file_exists($tmp)) {
            @unlink($tmp);
        }
        $storage = new SqliteProfilerStorage('sqlite:'.$tmp);
        $storage->purge();

        $profiler = new Profiler($storage);
        $profiler->add($collector);
        $profile = $profiler->collect($request, $response);

        $profile = $profiler->loadProfile($profile->getToken());
        $this->assertEquals(array('foo' => 'bar'), $profiler->get('request')->getRequestQuery()->all());

        @unlink($tmp);
    }
}
PK��Z�Uu֝�Dtest/HttpKernel/Symfony/Component/HttpKernel/Tests/UriSignerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests;

use Symfony\Component\HttpKernel\UriSigner;

class UriSignerTest extends \PHPUnit_Framework_TestCase
{
    public function testSign()
    {
        $signer = new UriSigner('foobar');

        $this->assertContains('?_hash=', $signer->sign('http://example.com/foo'));
        $this->assertContains('&_hash=', $signer->sign('http://example.com/foo?foo=bar'));
    }

    public function testCheck()
    {
        $signer = new UriSigner('foobar');

        $this->assertFalse($signer->check('http://example.com/foo?_hash=foo'));
        $this->assertFalse($signer->check('http://example.com/foo?foo=bar&_hash=foo'));
        $this->assertFalse($signer->check('http://example.com/foo?foo=bar&_hash=foo&bar=foo'));

        $this->assertTrue($signer->check($signer->sign('http://example.com/foo')));
        $this->assertTrue($signer->check($signer->sign('http://example.com/foo?foo=bar')));
    }
}
PK��Zbҏ�^^\test/HttpKernel/Symfony/Component/HttpKernel/Tests/DataCollector/MemoryDataCollectorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\DataCollector;

use Symfony\Component\HttpKernel\DataCollector\MemoryDataCollector;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class MemoryDataCollectorTest extends \PHPUnit_Framework_TestCase
{
    public function testCollect()
    {
        $collector = new MemoryDataCollector();
        $collector->collect(new Request(), new Response());

        $this->assertInternalType('integer', $collector->getMemory());
        $this->assertInternalType('integer', $collector->getMemoryLimit());
        $this->assertSame('memory', $collector->getName());
    }

    /** @dataProvider getBytesConversionTestData */
    public function testBytesConversion($limit, $bytes)
    {
        $collector = new MemoryDataCollector();
        $method = new \ReflectionMethod($collector, 'convertToBytes');
        $method->setAccessible(true);
        $this->assertEquals($bytes, $method->invoke($collector, $limit));
    }

    public function getBytesConversionTestData()
    {
        return array(
            array('2k', 2048),
            array('2 k', 2048),
            array('8m', 8 * 1024 * 1024),
            array('+2 k', 2048),
            array('+2???k', 2048),
            array('0x10', 16),
            array('0xf', 15),
            array('010', 8),
            array('+0x10 k', 16 * 1024),
            array('1g', 1024 * 1024 * 1024),
            array('1G', 1024 * 1024 * 1024),
            array('-1', -1),
            array('0', 0),
            array('2mk', 2048), // the unit must be the last char, so in this case 'k', not 'm'
        );
    }
}
PK��Z�C���Ztest/HttpKernel/Symfony/Component/HttpKernel/Tests/DataCollector/TimeDataCollectorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\DataCollector;

use Symfony\Component\HttpKernel\DataCollector\TimeDataCollector;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class TimeDataCollectorTest extends \PHPUnit_Framework_TestCase
{
    public function testCollect()
    {
        $c = new TimeDataCollector();

        $request = new Request();
        $request->server->set('REQUEST_TIME', 1);

        $c->collect($request, new Response());

        $this->assertEquals(1000, $c->getStartTime());

        $request->server->set('REQUEST_TIME_FLOAT', 2);

        $c->collect($request, new Response());

        $this->assertEquals(2000, $c->getStartTime());

        $request = new Request();
        $c->collect($request, new Response());
        $this->assertEquals(0, $c->getStartTime());

        $kernel = $this->getMock('Symfony\Component\HttpKernel\KernelInterface');
        $kernel->expects($this->once())->method('getStartTime')->will($this->returnValue(123456));

        $c = new TimeDataCollector($kernel);
        $request = new Request();
        $request->server->set('REQUEST_TIME', 1);

        $c->collect($request, new Response());
        $this->assertEquals(123456000, $c->getStartTime());
    }
}
PK��Z���	�	\test/HttpKernel/Symfony/Component/HttpKernel/Tests/DataCollector/ConfigDataCollectorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\DataCollector;

use Symfony\Component\HttpKernel\DataCollector\ConfigDataCollector;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class ConfigDataCollectorTest extends \PHPUnit_Framework_TestCase
{
    public function testCollect()
    {
        $kernel = new KernelForTest('test', true);
        $c = new ConfigDataCollector();
        $c->setKernel($kernel);
        $c->collect(new Request(), new Response());

        $this->assertSame('test',$c->getEnv());
        $this->assertTrue($c->isDebug());
        $this->assertSame('config',$c->getName());
        $this->assertSame('testkernel',$c->getAppName());
        $this->assertSame(PHP_VERSION,$c->getPhpVersion());
        $this->assertSame(Kernel::VERSION,$c->getSymfonyVersion());
        $this->assertNull($c->getToken());

        // if else clause because we don't know it
        if (extension_loaded('xdebug')) {
            $this->assertTrue($c->hasXdebug());
        } else {
            $this->assertFalse($c->hasXdebug());
        }

        // if else clause because we don't know it
        if (((extension_loaded('eaccelerator') && ini_get('eaccelerator.enable'))
                ||
                (extension_loaded('apc') && ini_get('apc.enabled'))
                ||
                (extension_loaded('Zend OPcache') && ini_get('opcache.enable'))
                ||
                (extension_loaded('xcache') && ini_get('xcache.cacher'))
                ||
                (extension_loaded('wincache') && ini_get('wincache.ocenabled')))) {
            $this->assertTrue($c->hasAccelerator());
        } else {
            $this->assertFalse($c->hasAccelerator());
        }
    }
}

class KernelForTest extends Kernel
{
    public function getName()
    {
        return 'testkernel';
    }

    public function registerBundles()
    {
    }

    public function init()
    {
    }

    public function getBundles()
    {
        return array();
    }

    public function registerContainerConfiguration(LoaderInterface $loader)
    {
    }
}
PK��Z�}#��_test/HttpKernel/Symfony/Component/HttpKernel/Tests/DataCollector/ExceptionDataCollectorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\DataCollector;

use Symfony\Component\HttpKernel\DataCollector\ExceptionDataCollector;
use Symfony\Component\HttpKernel\Exception\FlattenException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class ExceptionDataCollectorTest extends \PHPUnit_Framework_TestCase
{
    public function testCollect()
    {
        $e = new \Exception('foo',500);
        $c = new ExceptionDataCollector();
        $flattened = FlattenException::create($e);
        $trace = $flattened->getTrace();

        $this->assertFalse($c->hasException());

        $c->collect(new Request(), new Response(),$e);

        $this->assertTrue($c->hasException());
        $this->assertEquals($flattened,$c->getException());
        $this->assertSame('foo',$c->getMessage());
        $this->assertSame(500,$c->getCode());
        $this->assertSame('exception',$c->getName());
        $this->assertSame($trace,$c->getTrace());
    }

}
PK��Z�J�֌�]test/HttpKernel/Symfony/Component/HttpKernel/Tests/DataCollector/RequestDataCollectorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\DataCollector;

use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\DataCollector\RequestDataCollector;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\EventDispatcher\EventDispatcher;

class RequestDataCollectorTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider provider
     */
    public function testCollect(Request $request, Response $response)
    {
        $c = new RequestDataCollector();

        $c->collect($request, $response);

        $this->assertSame('request', $c->getName());
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\HeaderBag', $c->getRequestHeaders());
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag', $c->getRequestServer());
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag', $c->getRequestCookies());
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag', $c->getRequestAttributes());
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag', $c->getRequestRequest());
        $this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag', $c->getRequestQuery());
        $this->assertSame('html', $c->getFormat());
        $this->assertSame('foobar', $c->getRoute());
        $this->assertSame(array('name' => 'foo'), $c->getRouteParams());
        $this->assertSame(array(), $c->getSessionAttributes());
        $this->assertSame('en', $c->getLocale());

        $this->assertInstanceOf('Symfony\Component\HttpFoundation\HeaderBag', $c->getResponseHeaders());
        $this->assertSame('OK', $c->getStatusText());
        $this->assertSame(200, $c->getStatusCode());
        $this->assertSame('application/json', $c->getContentType());
    }

    /**
     * Test various types of controller callables.
     *
     * @dataProvider provider
     */
    public function testControllerInspection(Request $request, Response $response)
    {
        // make sure we always match the line number
        $r1 = new \ReflectionMethod($this, 'testControllerInspection');
        $r2 = new \ReflectionMethod($this, 'staticControllerMethod');
        // test name, callable, expected
        $controllerTests = array(
            array(
                '"Regular" callable',
                array($this, 'testControllerInspection'),
                array(
                    'class' => 'Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest',
                    'method' => 'testControllerInspection',
                    'file' => __FILE__,
                    'line' => $r1->getStartLine()
                ),
            ),

            array(
                'Closure',
                function () { return 'foo'; },
                array(
                    'class' => __NAMESPACE__.'\{closure}',
                    'method' => null,
                    'file' => __FILE__,
                    'line' => __LINE__ - 5,
                ),
            ),

            array(
                'Static callback as string',
                'Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest::staticControllerMethod',
                'Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest::staticControllerMethod',
            ),

            array(
                'Static callable with instance',
                array($this, 'staticControllerMethod'),
                array(
                    'class' => 'Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest',
                    'method' => 'staticControllerMethod',
                    'file' => __FILE__,
                    'line' => $r2->getStartLine()
                ),
            ),

            array(
                'Static callable with class name',
                array('Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest', 'staticControllerMethod'),
                array(
                    'class' => 'Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest',
                    'method' => 'staticControllerMethod',
                    'file' => __FILE__,
                    'line' => $r2->getStartLine()
                ),
            ),

            array(
                'Callable with instance depending on __call()',
                array($this, 'magicMethod'),
                array(
                    'class' => 'Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest',
                    'method' => 'magicMethod',
                    'file' => 'n/a',
                    'line' => 'n/a'
                ),
            ),

            array(
                'Callable with class name depending on __callStatic()',
                array('Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest', 'magicMethod'),
                array(
                    'class' => 'Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest',
                    'method' => 'magicMethod',
                    'file' => 'n/a',
                    'line' => 'n/a'
                ),
            ),
        );

        $c = new RequestDataCollector();

        foreach ($controllerTests as $controllerTest) {
            $this->injectController($c, $controllerTest[1], $request);
            $c->collect($request, $response);
            $this->assertSame($controllerTest[2], $c->getController(), sprintf('Testing: %s', $controllerTest[0]));
        }
    }

    public function provider()
    {
        if (!class_exists('Symfony\Component\HttpFoundation\Request')) {
            return array(array(null, null));
        }

        $request = Request::create('http://test.com/foo?bar=baz');
        $request->attributes->set('foo', 'bar');
        $request->attributes->set('_route', 'foobar');
        $request->attributes->set('_route_params', array('name' => 'foo'));

        $response = new Response();
        $response->setStatusCode(200);
        $response->headers->set('Content-Type', 'application/json');
        $response->headers->setCookie(new Cookie('foo','bar',1,'/foo','localhost',true,true));
        $response->headers->setCookie(new Cookie('bar','foo',new \DateTime('@946684800')));
        $response->headers->setCookie(new Cookie('bazz','foo','2000-12-12'));

        return array(
            array($request, $response)
        );
    }

    /**
     * Inject the given controller callable into the data collector.
     */
    protected function injectController($collector, $controller, $request)
    {
        $resolver = $this->getMock('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface');
        $httpKernel = new HttpKernel(new EventDispatcher(), $resolver);
        $event = new FilterControllerEvent($httpKernel, $controller, $request, HttpKernelInterface::MASTER_REQUEST);
        $collector->onKernelController($event);
    }

    /**
     * Dummy method used as controller callable
     */
    public static function staticControllerMethod()
    {
        throw new \LogicException('Unexpected method call');
    }

    /**
     * Magic method to allow non existing methods to be called and delegated.
     */
    public function __call($method, $args)
    {
        throw new \LogicException('Unexpected method call');
    }

    /**
     * Magic method to allow non existing methods to be called and delegated.
     */
    public static function __callStatic($method, $args)
    {
        throw new \LogicException('Unexpected method call');
    }

}
PK��Z���i	i	\test/HttpKernel/Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\DataCollector;

use Symfony\Component\HttpKernel\DataCollector\LoggerDataCollector;
use Symfony\Component\HttpKernel\Debug\ErrorHandler;

class LoggerDataCollectorTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getCollectTestData
     */
    public function testCollect($nb, $logs, $expectedLogs, $expectedDeprecationCount)
    {
        $logger = $this->getMock('Symfony\Component\HttpKernel\Log\DebugLoggerInterface');
        $logger->expects($this->once())->method('countErrors')->will($this->returnValue($nb));
        $logger->expects($this->exactly(2))->method('getLogs')->will($this->returnValue($logs));

        $c = new LoggerDataCollector($logger);
        $c->lateCollect();

        $this->assertSame('logger', $c->getName());
        $this->assertSame($nb, $c->countErrors());
        $this->assertSame($expectedLogs ? $expectedLogs : $logs, $c->getLogs());
        $this->assertSame($expectedDeprecationCount, $c->countDeprecations());
    }

    public function getCollectTestData()
    {
        return array(
            array(
                1,
                array(array('message' => 'foo', 'context' => array())),
                null,
                0
            ),
            array(
                1,
                array(array('message' => 'foo', 'context' => array('foo' => fopen(__FILE__, 'r')))),
                array(array('message' => 'foo', 'context' => array('foo' => 'Resource(stream)'))),
                0
            ),
            array(
                1,
                array(array('message' => 'foo', 'context' => array('foo' => new \stdClass()))),
                array(array('message' => 'foo', 'context' => array('foo' => 'Object(stdClass)'))),
                0
            ),
            array(
                1,
                array(
                    array('message' => 'foo', 'context' => array('type' => ErrorHandler::TYPE_DEPRECATION)),
                    array('message' => 'foo2', 'context' => array('type' => ErrorHandler::TYPE_DEPRECATION))
                ),
                null,
                2
            ),
        );
    }
}
PK��Zg�]�>*>*Etest/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpKernelTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests;

use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\EventDispatcher\EventDispatcher;

class HttpKernelTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \RuntimeException
     */
    public function testHandleWhenControllerThrowsAnExceptionAndRawIsTrue()
    {
        $kernel = new HttpKernel(new EventDispatcher(), $this->getResolver(function () { throw new \RuntimeException(); }));

        $kernel->handle(new Request(), HttpKernelInterface::MASTER_REQUEST, true);
    }

    /**
     * @expectedException \RuntimeException
     */
    public function testHandleWhenControllerThrowsAnExceptionAndRawIsFalseAndNoListenerIsRegistered()
    {
        $kernel = new HttpKernel(new EventDispatcher(), $this->getResolver(function () { throw new \RuntimeException(); }));

        $kernel->handle(new Request(), HttpKernelInterface::MASTER_REQUEST, false);
    }

    public function testHandleWhenControllerThrowsAnExceptionAndRawIsFalse()
    {
        $dispatcher = new EventDispatcher();
        $dispatcher->addListener(KernelEvents::EXCEPTION, function ($event) {
            $event->setResponse(new Response($event->getException()->getMessage()));
        });

        $kernel = new HttpKernel($dispatcher, $this->getResolver(function () { throw new \RuntimeException('foo'); }));
        $response = $kernel->handle(new Request());

        $this->assertEquals('500', $response->getStatusCode());
        $this->assertEquals('foo', $response->getContent());
    }

    public function testHandleExceptionWithARedirectionResponse()
    {
        $dispatcher = new EventDispatcher();
        $dispatcher->addListener(KernelEvents::EXCEPTION, function ($event) {
            $event->setResponse(new RedirectResponse('/login', 301));
        });

        $kernel = new HttpKernel($dispatcher, $this->getResolver(function () { throw new AccessDeniedHttpException(); }));
        $response = $kernel->handle(new Request());

        $this->assertEquals('301', $response->getStatusCode());
        $this->assertEquals('/login', $response->headers->get('Location'));
    }

    public function testHandleHttpException()
    {
        $dispatcher = new EventDispatcher();
        $dispatcher->addListener(KernelEvents::EXCEPTION, function ($event) {
            $event->setResponse(new Response($event->getException()->getMessage()));
        });

        $kernel = new HttpKernel($dispatcher, $this->getResolver(function () { throw new MethodNotAllowedHttpException(array('POST')); }));
        $response = $kernel->handle(new Request());

        $this->assertEquals('405', $response->getStatusCode());
        $this->assertEquals('POST', $response->headers->get('Allow'));
    }

    /**
     * @dataProvider getStatusCodes
     */
    public function testHandleWhenAnExceptionIsHandledWithASpecificStatusCode($responseStatusCode, $expectedStatusCode)
    {
        $dispatcher = new EventDispatcher();
        $dispatcher->addListener(KernelEvents::EXCEPTION, function ($event) use ($responseStatusCode, $expectedStatusCode) {
            $event->setResponse(new Response('', $responseStatusCode, array('X-Status-Code' => $expectedStatusCode)));
        });

        $kernel = new HttpKernel($dispatcher, $this->getResolver(function () { throw new \RuntimeException(); }));
        $response = $kernel->handle(new Request());

        $this->assertEquals($expectedStatusCode, $response->getStatusCode());
        $this->assertFalse($response->headers->has('X-Status-Code'));
    }

    public function getStatusCodes()
    {
        return array(
            array(200, 404),
            array(404, 200),
            array(301, 200),
            array(500, 200),
        );
    }

    public function testHandleWhenAListenerReturnsAResponse()
    {
        $dispatcher = new EventDispatcher();
        $dispatcher->addListener(KernelEvents::REQUEST, function ($event) {
            $event->setResponse(new Response('hello'));
        });

        $kernel = new HttpKernel($dispatcher, $this->getResolver());

        $this->assertEquals('hello', $kernel->handle(new Request())->getContent());
    }

    /**
     * @expectedException \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
     */
    public function testHandleWhenNoControllerIsFound()
    {
        $dispatcher = new EventDispatcher();
        $kernel = new HttpKernel($dispatcher, $this->getResolver(false));

        $kernel->handle(new Request());
    }

    /**
     * @expectedException \LogicException
     */
    public function testHandleWhenTheControllerIsNotACallable()
    {
        $dispatcher = new EventDispatcher();
        $kernel = new HttpKernel($dispatcher, $this->getResolver('foobar'));

        $kernel->handle(new Request());
    }

    public function testHandleWhenTheControllerIsAClosure()
    {
        $response = new Response('foo');
        $dispatcher = new EventDispatcher();
        $kernel = new HttpKernel($dispatcher, $this->getResolver(function () use ($response) { return $response; }));

        $this->assertSame($response, $kernel->handle(new Request()));
    }

    public function testHandleWhenTheControllerIsAnObjectWithInvoke()
    {
        $dispatcher = new EventDispatcher();
        $kernel = new HttpKernel($dispatcher, $this->getResolver(new Controller()));

        $this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request()));
    }

    public function testHandleWhenTheControllerIsAFunction()
    {
        $dispatcher = new EventDispatcher();
        $kernel = new HttpKernel($dispatcher, $this->getResolver('Symfony\Component\HttpKernel\Tests\controller_func'));

        $this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request()));
    }

    public function testHandleWhenTheControllerIsAnArray()
    {
        $dispatcher = new EventDispatcher();
        $kernel = new HttpKernel($dispatcher, $this->getResolver(array(new Controller(), 'controller')));

        $this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request()));
    }

    public function testHandleWhenTheControllerIsAStaticArray()
    {
        $dispatcher = new EventDispatcher();
        $kernel = new HttpKernel($dispatcher, $this->getResolver(array('Symfony\Component\HttpKernel\Tests\Controller', 'staticcontroller')));

        $this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request()));
    }

    /**
     * @expectedException \LogicException
     */
    public function testHandleWhenTheControllerDoesNotReturnAResponse()
    {
        $dispatcher = new EventDispatcher();
        $kernel = new HttpKernel($dispatcher, $this->getResolver(function () { return 'foo'; }));

        $kernel->handle(new Request());
    }

    public function testHandleWhenTheControllerDoesNotReturnAResponseButAViewIsRegistered()
    {
        $dispatcher = new EventDispatcher();
        $dispatcher->addListener(KernelEvents::VIEW, function ($event) {
            $event->setResponse(new Response($event->getControllerResult()));
        });
        $kernel = new HttpKernel($dispatcher, $this->getResolver(function () { return 'foo'; }));

        $this->assertEquals('foo', $kernel->handle(new Request())->getContent());
    }

    public function testHandleWithAResponseListener()
    {
        $dispatcher = new EventDispatcher();
        $dispatcher->addListener(KernelEvents::RESPONSE, function ($event) {
            $event->setResponse(new Response('foo'));
        });
        $kernel = new HttpKernel($dispatcher, $this->getResolver());

        $this->assertEquals('foo', $kernel->handle(new Request())->getContent());
    }

    public function testTerminate()
    {
        $dispatcher = new EventDispatcher();
        $kernel = new HttpKernel($dispatcher, $this->getResolver());
        $dispatcher->addListener(KernelEvents::TERMINATE, function ($event) use (&$called, &$capturedKernel, &$capturedRequest, &$capturedResponse) {
            $called = true;
            $capturedKernel = $event->getKernel();
            $capturedRequest = $event->getRequest();
            $capturedResponse = $event->getResponse();
        });

        $kernel->terminate($request = Request::create('/'), $response = new Response());
        $this->assertTrue($called);
        $this->assertEquals($kernel, $capturedKernel);
        $this->assertEquals($request, $capturedRequest);
        $this->assertEquals($response, $capturedResponse);
    }

    public function testVerifyRequestStackPushPopDuringHandle()
    {
        $request = new Request();

        $stack = $this->getMock('Symfony\Component\HttpFoundation\RequestStack', array('push', 'pop'));
        $stack->expects($this->at(0))->method('push')->with($this->equalTo($request));
        $stack->expects($this->at(1))->method('pop');

        $dispatcher = new EventDispatcher();
        $kernel = new HttpKernel($dispatcher, $this->getResolver(), $stack);

        $kernel->handle($request, HttpKernelInterface::MASTER_REQUEST);
    }

    protected function getResolver($controller = null)
    {
        if (null === $controller) {
            $controller = function () { return new Response('Hello'); };
        }

        $resolver = $this->getMock('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface');
        $resolver->expects($this->any())
            ->method('getController')
            ->will($this->returnValue($controller));
        $resolver->expects($this->any())
            ->method('getArguments')
            ->will($this->returnValue(array()));

        return $resolver;
    }

    protected function assertResponseEquals(Response $expected, Response $actual)
    {
        $expected->setDate($actual->getDate());
        $this->assertEquals($expected, $actual);
    }
}

class Controller
{
    public function __invoke()
    {
        return new Response('foo');
    }

    public function controller()
    {
        return new Response('foo');
    }

    public static function staticController()
    {
        return new Response('foo');
    }
}

function controller_func()
{
    return new Response('foo');
}
PK��Zz*V%%Xtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\Controller;

use Symfony\Component\HttpKernel\Controller\ControllerResolver;
use Symfony\Component\HttpKernel\Tests\Logger;
use Symfony\Component\HttpFoundation\Request;

class ControllerResolverTest extends \PHPUnit_Framework_TestCase
{
    public function testGetControllerWithoutControllerParameter()
    {
        $logger = $this->getMock('Psr\Log\LoggerInterface');
        $logger->expects($this->once())->method('warning')->with('Unable to look for the controller as the "_controller" parameter is missing');
        $resolver = new ControllerResolver($logger);

        $request = Request::create('/');
        $this->assertFalse($resolver->getController($request), '->getController() returns false when the request has no _controller attribute');
    }

    public function testGetControllerWithLambda()
    {
        $resolver = new ControllerResolver();

        $request = Request::create('/');
        $request->attributes->set('_controller', $lambda = function () {});
        $controller = $resolver->getController($request);
        $this->assertSame($lambda, $controller);
    }

    public function testGetControllerWithObjectAndInvokeMethod()
    {
        $resolver = new ControllerResolver();

        $request = Request::create('/');
        $request->attributes->set('_controller', $this);
        $controller = $resolver->getController($request);
        $this->assertSame($this, $controller);
    }

    public function testGetControllerWithObjectAndMethod()
    {
        $resolver = new ControllerResolver();

        $request = Request::create('/');
        $request->attributes->set('_controller', array($this, 'controllerMethod1'));
        $controller = $resolver->getController($request);
        $this->assertSame(array($this, 'controllerMethod1'), $controller);
    }

    public function testGetControllerWithClassAndMethod()
    {
        $resolver = new ControllerResolver();

        $request = Request::create('/');
        $request->attributes->set('_controller', array('Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest', 'controllerMethod4'));
        $controller = $resolver->getController($request);
        $this->assertSame(array('Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest', 'controllerMethod4'), $controller);
    }

    public function testGetControllerWithObjectAndMethodAsString()
    {
        $resolver = new ControllerResolver();

        $request = Request::create('/');
        $request->attributes->set('_controller', 'Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest::controllerMethod1');
        $controller = $resolver->getController($request);
        $this->assertInstanceOf('Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest', $controller[0], '->getController() returns a PHP callable');
    }

    public function testGetControllerWithClassAndInvokeMethod()
    {
        $resolver = new ControllerResolver();

        $request = Request::create('/');
        $request->attributes->set('_controller', 'Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest');
        $controller = $resolver->getController($request);
        $this->assertInstanceOf('Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest', $controller);
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testGetControllerOnObjectWithoutInvokeMethod()
    {
        $resolver = new ControllerResolver();

        $request = Request::create('/');
        $request->attributes->set('_controller', new \stdClass());
        $resolver->getController($request);
    }

    public function testGetControllerWithFunction()
    {
        $resolver = new ControllerResolver();

        $request = Request::create('/');
        $request->attributes->set('_controller', 'Symfony\Component\HttpKernel\Tests\Controller\some_controller_function');
        $controller = $resolver->getController($request);
        $this->assertSame('Symfony\Component\HttpKernel\Tests\Controller\some_controller_function', $controller);
    }

    /**
     * @dataProvider      getUndefinedControllers
     * @expectedException \InvalidArgumentException
     */
    public function testGetControllerOnNonUndefinedFunction($controller)
    {
        $resolver = new ControllerResolver();

        $request = Request::create('/');
        $request->attributes->set('_controller', $controller);
        $resolver->getController($request);
    }

    public function getUndefinedControllers()
    {
        return array(
            array('foo'),
            array('foo::bar'),
            array('stdClass'),
            array('Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest::bar'),
        );
    }

    public function testGetArguments()
    {
        $resolver = new ControllerResolver();

        $request = Request::create('/');
        $controller = array(new self(), 'testGetArguments');
        $this->assertEquals(array(), $resolver->getArguments($request, $controller), '->getArguments() returns an empty array if the method takes no arguments');

        $request = Request::create('/');
        $request->attributes->set('foo', 'foo');
        $controller = array(new self(), 'controllerMethod1');
        $this->assertEquals(array('foo'), $resolver->getArguments($request, $controller), '->getArguments() returns an array of arguments for the controller method');

        $request = Request::create('/');
        $request->attributes->set('foo', 'foo');
        $controller = array(new self(), 'controllerMethod2');
        $this->assertEquals(array('foo', null), $resolver->getArguments($request, $controller), '->getArguments() uses default values if present');

        $request->attributes->set('bar', 'bar');
        $this->assertEquals(array('foo', 'bar'), $resolver->getArguments($request, $controller), '->getArguments() overrides default values if provided in the request attributes');

        $request = Request::create('/');
        $request->attributes->set('foo', 'foo');
        $controller = function ($foo) {};
        $this->assertEquals(array('foo'), $resolver->getArguments($request, $controller));

        $request = Request::create('/');
        $request->attributes->set('foo', 'foo');
        $controller = function ($foo, $bar = 'bar') {};
        $this->assertEquals(array('foo', 'bar'), $resolver->getArguments($request, $controller));

        $request = Request::create('/');
        $request->attributes->set('foo', 'foo');
        $controller = new self();
        $this->assertEquals(array('foo', null), $resolver->getArguments($request, $controller));
        $request->attributes->set('bar', 'bar');
        $this->assertEquals(array('foo', 'bar'), $resolver->getArguments($request, $controller));

        $request = Request::create('/');
        $request->attributes->set('foo', 'foo');
        $request->attributes->set('foobar', 'foobar');
        $controller = 'Symfony\Component\HttpKernel\Tests\Controller\some_controller_function';
        $this->assertEquals(array('foo', 'foobar'), $resolver->getArguments($request, $controller));

        $request = Request::create('/');
        $request->attributes->set('foo', 'foo');
        $request->attributes->set('foobar', 'foobar');
        $controller = array(new self(), 'controllerMethod3');

        if (version_compare(PHP_VERSION, '5.3.16', '==')) {
            $this->markTestSkipped('PHP 5.3.16 has a major bug in the Reflection sub-system');
        } else {
            try {
                $resolver->getArguments($request, $controller);
                $this->fail('->getArguments() throws a \RuntimeException exception if it cannot determine the argument value');
            } catch (\Exception $e) {
                $this->assertInstanceOf('\RuntimeException', $e, '->getArguments() throws a \RuntimeException exception if it cannot determine the argument value');
            }
        }

        $request = Request::create('/');
        $controller = array(new self(), 'controllerMethod5');
        $this->assertEquals(array($request), $resolver->getArguments($request, $controller), '->getArguments() injects the request');
    }

    public function testCreateControllerCanReturnAnyCallable()
    {
        $mock = $this->getMock('Symfony\Component\HttpKernel\Controller\ControllerResolver', array('createController'));
        $mock->expects($this->once())->method('createController')->will($this->returnValue('Symfony\Component\HttpKernel\Tests\Controller\some_controller_function'));

        $request = Request::create('/');
        $request->attributes->set('_controller', 'foobar');
        $mock->getController($request);
    }

    public function __invoke($foo, $bar = null)
    {
    }

    public function controllerMethod1($foo)
    {
    }

    protected function controllerMethod2($foo, $bar = null)
    {
    }

    protected function controllerMethod3($foo, $bar = null, $foobar)
    {
    }

    protected static function controllerMethod4()
    {
    }

    protected function controllerMethod5(Request $request)
    {
    }
}

function some_controller_function($foo, $foobar)
{
}
PK��Ze�
֮�ntest/HttpKernel/Symfony/Component/HttpKernel/Tests/DependencyInjection/MergeExtensionConfigurationPassTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\DependencyInjection;

use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass;

class MergeExtensionConfigurationPassTest extends \PHPUnit_Framework_TestCase
{
    public function testAutoloadMainExtension()
    {
        $container = $this->getMock('Symfony\\Component\\DependencyInjection\\ContainerBuilder');
        $params = $this->getMock('Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBag');

        $container->expects($this->at(0))
            ->method('getExtensionConfig')
            ->with('loaded')
            ->will($this->returnValue(array(array())));
        $container->expects($this->at(1))
            ->method('getExtensionConfig')
            ->with('notloaded')
            ->will($this->returnValue(array()));
        $container->expects($this->once())
            ->method('loadFromExtension')
            ->with('notloaded', array());

        $container->expects($this->any())
            ->method('getParameterBag')
            ->will($this->returnValue($params));
        $params->expects($this->any())
            ->method('all')
            ->will($this->returnValue(array()));
        $container->expects($this->any())
            ->method('getDefinitions')
            ->will($this->returnValue(array()));
        $container->expects($this->any())
            ->method('getAliases')
            ->will($this->returnValue(array()));
        $container->expects($this->any())
            ->method('getExtensions')
            ->will($this->returnValue(array()));

        $configPass = new MergeExtensionConfigurationPass(array('loaded', 'notloaded'));
        $configPass->process($container);
    }
}
PK��ZV���^^dtest/HttpKernel/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterListenersPassTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\DependencyInjection;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\DependencyInjection\RegisterListenersPass;

class RegisterListenersPassTest extends \PHPUnit_Framework_TestCase
{
    /**
     * Tests that event subscribers not implementing EventSubscriberInterface
     * trigger an exception.
     *
     * @expectedException \InvalidArgumentException
     */
    public function testEventSubscriberWithoutInterface()
    {
        // one service, not implementing any interface
        $services = array(
            'my_event_subscriber' => array(0 => array()),
        );

        $definition = $this->getMock('Symfony\Component\DependencyInjection\Definition');
        $definition->expects($this->atLeastOnce())
            ->method('isPublic')
            ->will($this->returnValue(true));
        $definition->expects($this->atLeastOnce())
            ->method('getClass')
            ->will($this->returnValue('stdClass'));

        $builder = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');
        $builder->expects($this->any())
            ->method('hasDefinition')
            ->will($this->returnValue(true));

        // We don't test kernel.event_listener here
        $builder->expects($this->atLeastOnce())
            ->method('findTaggedServiceIds')
            ->will($this->onConsecutiveCalls(array(), $services));

        $builder->expects($this->atLeastOnce())
            ->method('getDefinition')
            ->will($this->returnValue($definition));

        $registerListenersPass = new RegisterListenersPass();
        $registerListenersPass->process($builder);
    }

    public function testValidEventSubscriber()
    {
        $services = array(
            'my_event_subscriber' => array(0 => array()),
        );

        $definition = $this->getMock('Symfony\Component\DependencyInjection\Definition');
        $definition->expects($this->atLeastOnce())
            ->method('isPublic')
            ->will($this->returnValue(true));
        $definition->expects($this->atLeastOnce())
            ->method('getClass')
            ->will($this->returnValue('Symfony\Component\HttpKernel\Tests\DependencyInjection\SubscriberService'));

        $builder = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');
        $builder->expects($this->any())
            ->method('hasDefinition')
            ->will($this->returnValue(true));

        // We don't test kernel.event_listener here
        $builder->expects($this->atLeastOnce())
            ->method('findTaggedServiceIds')
            ->will($this->onConsecutiveCalls(array(), $services));

        $builder->expects($this->atLeastOnce())
            ->method('getDefinition')
            ->will($this->returnValue($definition));

        $builder->expects($this->atLeastOnce())
            ->method('findDefinition')
            ->will($this->returnValue($definition));

        $registerListenersPass = new RegisterListenersPass();
        $registerListenersPass->process($builder);
    }

    /**
     * @expectedException \InvalidArgumentException
     * @expectedExceptionMessage The service "foo" must be public as event listeners are lazy-loaded.
     */
    public function testPrivateEventListener()
    {
        $container = new ContainerBuilder();
        $container->register('foo', 'stdClass')->setPublic(false)->addTag('kernel.event_listener', array());
        $container->register('event_dispatcher', 'stdClass');

        $registerListenersPass = new RegisterListenersPass();
        $registerListenersPass->process($container);
    }

    /**
     * @expectedException \InvalidArgumentException
     * @expectedExceptionMessage The service "foo" must be public as event subscribers are lazy-loaded.
     */
    public function testPrivateEventSubscriber()
    {
        $container = new ContainerBuilder();
        $container->register('foo', 'stdClass')->setPublic(false)->addTag('kernel.event_subscriber', array());
        $container->register('event_dispatcher', 'stdClass');

        $registerListenersPass = new RegisterListenersPass();
        $registerListenersPass->process($container);
    }

    /**
     * @expectedException \InvalidArgumentException
     * @expectedExceptionMessage The service "foo" must not be abstract as event listeners are lazy-loaded.
     */
    public function testAbstractEventListener()
    {
        $container = new ContainerBuilder();
        $container->register('foo', 'stdClass')->setAbstract(true)->addTag('kernel.event_listener', array());
        $container->register('event_dispatcher', 'stdClass');

        $registerListenersPass = new RegisterListenersPass();
        $registerListenersPass->process($container);
    }
}

class SubscriberService implements \Symfony\Component\EventDispatcher\EventSubscriberInterface
{
    public static function getSubscribedEvents() {}
}
PK��Z�C�hhgtest/HttpKernel/Symfony/Component/HttpKernel/Tests/DependencyInjection/ContainerAwareHttpKernelTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpKernel\Tests\DependencyInjection;

use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\EventDispatcher\EventDispatcher;

class ContainerAwareHttpKernelTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getProviderTypes
     */
    public function testHandle($type)
    {
        $request = new Request();
        $expected = new Response();
        $controller = function () use ($expected) {
            return $expected;
        };

        $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
        $this
            ->expectsEnterScopeOnce($container)
            ->expectsLeaveScopeOnce($container)
            ->expectsSetRequestWithAt($container, $request, 3)
            ->expectsSetRequestWithAt($container, null, 4)
        ;

        $dispatcher = new EventDispatcher();
        $resolver = $this->getResolverMockFor($controller, $request);
        $stack = new RequestStack();
        $kernel = new ContainerAwareHttpKernel($dispatcher, $container, $resolver, $stack);

        $actual = $kernel->handle($request, $type);

        $this->assertSame($expected, $actual, '->handle() returns the response');
    }

    /**
     * @dataProvider getProviderTypes
     */
    public function testVerifyRequestStackPushPopDuringHandle($type)
    {
        $request = new Request();
        $expected = new Response();
        $controller = function () use ($expected) {
            return $expected;
        };

        $stack = $this->getMock('Symfony\Component\HttpFoundation\RequestStack', array('push', 'pop'));
        $stack->expects($this->at(0))->method('push')->with($this->equalTo($request));
        $stack->expects($this->at(1))->method('pop');

        $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
        $dispatcher = new EventDispatcher();
        $resolver = $this->getResolverMockFor($controller, $request);
        $kernel = new ContainerAwareHttpKernel($dispatcher, $container, $resolver, $stack);

        $kernel->handle($request, $type);
    }

    /**
     * @dataProvider getProviderTypes
     */
    public function testHandleRestoresThePreviousRequestOnException($type)
    {
        $request = new Request();
        $expected = new \Exception();
        $controller = function () use ($expected) {
            throw $expected;
        };

        $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
        $this
            ->expectsEnterScopeOnce($container)
            ->expectsLeaveScopeOnce($container)
            ->expectsSetRequestWithAt($container, $request, 3)
            ->expectsSetRequestWithAt($container, null, 4)
        ;

        $dispatcher = new EventDispatcher();
        $resolver = $this->getMock('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface');
        $resolver = $this->getResolverMockFor($controller, $request);
        $stack = new RequestStack();
        $kernel = new ContainerAwareHttpKernel($dispatcher, $container, $resolver, $stack);

        try {
            $kernel->handle($request, $type);
            $this->fail('->handle() suppresses the controller exception');
        } catch (\PHPUnit_Framework_Exception $exception) {
            throw $exception;
        } catch (\Exception $actual) {
            $this->assertSame($expected, $actual, '->handle() throws the controller exception');
        }
    }

    public function getProviderTypes()
    {
        return array(
            array(HttpKernelInterface::MASTER_REQUEST),
            array(HttpKernelInterface::SUB_REQUEST),
        );
    }

    private function getResolverMockFor($controller, $request)
    {
        $resolver = $this->getMock('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface');
        $resolver->expects($this->once())
            ->method('getController')
            ->with($request)
            ->will($this->returnValue($controller));
        $resolver->expects($this->once())
            ->method('getArguments')
            ->with($request, $controller)
            ->will($this->returnValue(array()));

        return $resolver;
    }

    private function expectsSetRequestWithAt($container, $with, $at)
    {
        $container
            ->expects($this->at($at))
            ->method('set')
            ->with($this->equalTo('request'), $this->equalTo($with), $this->equalTo('request'))
        ;

        return $this;
    }

    private function expectsEnterScopeOnce($container)
    {
        $container
            ->expects($this->once())
            ->method('enterScope')
            ->with($this->equalTo('request'))
        ;

        return $this;
    }

    private function expectsLeaveScopeOnce($container)
    {
        $container
            ->expects($this->once())
            ->method('leaveScope')
            ->with($this->equalTo('request'))
        ;

        return $this;
    }
}
PK��Z��x99=test/HttpKernel/Symfony/Component/HttpKernel/phpunit.xml.distnu�[���<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony HttpKernel Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./Tests</directory>
                <directory>./vendor</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
PK��Z;�{��'test/Mail_Mime/tests/test_Bug_GH19.phptnu�[���--TEST--
Bug GH-19  Test boundary value with different headers()/get() call order
--SKIPIF--
--FILE--
<?php
include "Mail/mime.php";

// Test get() before headers()

$mime = new Mail_mime("\r\n");
$mime->setHTMLBody('html');
$mime->setTXTBody('text');

$body = $mime->get();
$hdrs = $mime->headers(array(
        'From'    => 'test@domain.tld',
        'Subject' => 'Subject',
        'To'      => 'to@domain.tld'
));

preg_match('/boundary="([^"]+)/', $hdrs['Content-Type'], $matches);
$boundary = $matches[1];

echo substr_count($body, "--$boundary") . "\n";

// Test headers() before get()

$mime = new Mail_mime("\r\n");
$mime->setHTMLBody('html');
$mime->setTXTBody('text');

$hdrs = $mime->headers(array(
        'From'    => 'test@domain.tld',
        'Subject' => 'Subject',
        'To'      => 'to@domain.tld'
));
$body = $mime->get();

preg_match('/boundary="([^"]+)/', $hdrs['Content-Type'], $matches);
$boundary = $matches[1];

echo substr_count($body, "--$boundary");
--EXPECT--
3
3
PK��Z�E�oo(test/Mail_Mime/tests/test_Bug_13962.phptnu�[���--TEST--
Bug #13962  Multiple header support
--SKIPIF--
--FILE--
<?php
require_once('Mail/mime.php');

$mime = new Mail_mime();

$mime->setFrom('user@from.example.com');
$r = $mime->txtHeaders(array('Received' => array('Received 1', 'Received 2')));

print_r($r); 
?>
--EXPECT--
Received: Received 1
Received: Received 2
MIME-Version: 1.0
From: user@from.example.com
PK��ZԢ��``(test/Mail_Mime/tests/test_Bug_21255.phptnu�[���--TEST--
Bug #21255  Boundary gets added twice
--SKIPIF--
--FILE--
<?php
include "Mail/mime.php";

$mime = new Mail_mime("\r\n");
$mime->setHTMLBody('html');
$mime->setTXTBody('text');
$mime->setContentType('multipart/alternative', array('boundary' => 'something'));

$msg = $mime->getMessage();

echo substr_count($msg, 'boundary=');

?>
--EXPECT--
1
PK��Zi;���)test/Mail_Mime/tests/test_Bug_7561_1.phptnu�[���--TEST--
Bug #7561   Mail_mimePart::quotedPrintableEncode() misbehavior with mbstring overload
--INI--
mbstring.language=Neutral
mbstring.func_overload=6
mbstring.internal_encoding=UTF-8
mbstring.http_output=UTF-8
--SKIPIF--
<?php
include "PEAR.php";
if (!extension_loaded('mbstring')){
    if (!PEAR::loadExtension('mbstring')){
        print('SKIP could not load mbstring module');
    }
}
--FILE--
<?php
include("Mail/mimePart.php");
// string is UTF-8 encoded
$input = "Micha\xC3\xABl \xC3\x89ric St\xC3\xA9phane";
$rv = Mail_mimePart::quotedPrintableEncode($input, 76, "\n");
echo $rv, "\n";
--EXPECT--
Micha=C3=ABl =C3=89ric St=C3=A9phane
PK��Ze;�I(test/Mail_Mime/tests/test_Bug_21205.phptnu�[���--TEST--
Bug #21205  Handling ISO-2022-JP headers
--SKIPIF--
<?php
include "PEAR.php";
if (!extension_loaded('mbstring')) {
    if (!PEAR::loadExtension('mbstring')) {
        print('SKIP could not load mbstring module');
    }
}
--FILE--
<?php
require_once('Mail/mimePart.php');
$tests = array(
    '□京都府□',
    '∠∠∠∠',
);
$addr = ' <aaa@bbb.ccc>';
$charset = 'ISO-2022-JP';
$encoding = 'base64';
foreach ($tests as $test) {
    $test = mb_convert_encoding($test, $charset, 'UTF-8');
    print Mail_mimePart::encodeHeader("subject", $test,       $charset, $encoding) . PHP_EOL;
    print Mail_mimePart::encodeHeader("to",      $test.$addr, $charset, $encoding) . PHP_EOL;
    $test = '"' . $test . '"';
    print Mail_mimePart::encodeHeader("subject", $test,       $charset, $encoding) . PHP_EOL;
    print Mail_mimePart::encodeHeader("to",      $test.$addr, $charset, $encoding) . PHP_EOL;
}
?>
--EXPECT--
=?ISO-2022-JP?B?GyRCIiI1fkVUSVwiIhsoQg==?=
=?ISO-2022-JP?B?GyRCIiI1fkVUSVwiIhsoQg==?= <aaa@bbb.ccc>
=?ISO-2022-JP?B?GyRCIiI1fkVUSVwiIhsoQg==?=
=?ISO-2022-JP?B?GyRCIiI1fkVUSVwiIhsoQg==?= <aaa@bbb.ccc>
=?ISO-2022-JP?B?GyRCIlwiXCJcIlwbKEI=?=
=?ISO-2022-JP?B?GyRCIlwiXCJcIlwbKEI=?= <aaa@bbb.ccc>
=?ISO-2022-JP?B?GyRCIlwiXCJcIlwbKEI=?=
=?ISO-2022-JP?B?GyRCIlwiXCJcIlwbKEI=?= <aaa@bbb.ccc>
PK��ZY�����'test/Mail_Mime/tests/test_Bug_GH26.phptnu�[���--TEST--
Bug GH-26  Backward slash is getting added in headers
--SKIPIF--
--FILE--
<?php

require_once('Mail/mime.php');

$mail_mime = new Mail_mime("\n");

$from = '"George B@@Z"<george@cort.org.au>';
$to = <<<EOT
"austin test"<austinn@cort.org>,<reno@cort.org>,t@mail.com
EOT;
$subject = "Test mime";
$mailbody = "hello world";

$mail_mime->setTxtBody($mailbody);
$mail_mime->setHTMLBody($mailbody);
$mail_mime->setSubject($subject);
$mail_mime->setFrom($from);

$body = $mail_mime->get();

$extra_headers = array();
$extra_headers["To"] = $to;

$arr_hdrs = $mail_mime->headers($extra_headers);

echo $arr_hdrs['From'] . "\n" . $arr_hdrs['To'];

--EXPECT--
"George B@@Z" <george@cort.org.au>
"austin test" <austinn@cort.org>, <reno@cort.org>, t@mail.comPK��Z��RoUU(test/Mail_Mime/tests/test_Bug_20226.phptnu�[���--TEST--
Bug #20226  Mail_mimePart::encodeHeader() and ISO-2022-JP encoding
--SKIPIF--
--FILE--
<?php
include("Mail/mimePart.php");

$subject = base64_decode("GyRCJT8lJCVIJWsbKEI=");
$mime    = new Mail_mimePart();

echo $mime->encodeHeader('subject', $subject, 'ISO-2022-JP', 'base64');
?>
--EXPECT--
=?ISO-2022-JP?B?GyRCJT8lJCVIJWsbKEI=?=
PK��Zg��+��(test/Mail_Mime/tests/test_Bug_13444.phptnu�[���--TEST--
Bug #9725   multipart/related & alternative wrong order
--SKIPIF--
--FILE--
<?php
include("Mail/mime.php");

$mime = new Mail_mime();
$mime->setTXTBody("test");
$mime->setHTMLBody("test");
$mime->addHTMLImage("test", 'application/octet-stream', '', false);
$body = $mime->get();
$head = $mime->headers();
$headCT = $head['Content-Type'];
$headCT = explode(";", $headCT);
$headCT = $headCT[0];

$ct = preg_match_all('|Content-Type: ([^;\r\n]+)|', $body, $matches);
print($headCT);
print("\n");
foreach ($matches[1] as $match){
    print($match);
    print("\n");
}
--EXPECT--
multipart/alternative
text/plain
multipart/related
text/html
application/octet-stream
PK��Z%��BB'test/Mail_Mime/tests/test_Bug_GH16.phptnu�[���--TEST--
Bug GH-16  Test methods that write to a file
--SKIPIF--
--FILE--
<?php
include "Mail/mime.php";

$mime = new Mail_mime("\r\n");
$mime->setHTMLBody('html');
$mime->setTXTBody('text');
$mime->setContentType('multipart/alternative', array('boundary' => 'something'));

$temp_filename = dirname(__FILE__) . "/output1.tmp";
touch($temp_filename);
$msg = $mime->saveMessageBody($temp_filename);
echo file_get_contents($temp_filename);

$temp_filename = dirname(__FILE__) . "/output2.tmp";
touch($temp_filename);
$msg = $mime->saveMessage($temp_filename);
echo file_get_contents($temp_filename);

$temp_filename = dirname(__FILE__) . "/output3.tmp";
$mimePart = new Mail_mimePart('abc', array(
        'content_type' => 'text/plain',
        'encoding'     => 'quoted-printable',
));
$mimePart->encodeToFile($temp_filename);
echo file_get_contents($temp_filename);

?>
--CLEAN--
<?php
    for ($i = 1; $i < 4; $i++) {
        @unlink(dirname(__FILE__) . "/output{$i}.tmp");
    }
?>
--EXPECT--
--something
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=ISO-8859-1

text
--something
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=ISO-8859-1

html
--something--
MIME-Version: 1.0
Content-Type: multipart/alternative;
 boundary="something"

--something
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=ISO-8859-1

text
--something
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=ISO-8859-1

html
--something--
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain

abc
PK��Z�-7c77)test/Mail_Mime/tests/test_Bug_3513_2.phptnu�[���--TEST--
Bug #3513   Support of RFC2231 in header fields. (UTF-8)
--SKIPIF--
--FILE--
<?php
require_once('Mail/mime.php');

$test = "Süper gröse tolle tolle grüße.txt";
$Mime = new Mail_Mime();
$Mime->addAttachment('testfile',"text/plain", $test, FALSE, 'base64', 'attachment', 'UTF-8', 'de');

$content = $Mime->get();
$content = str_replace("\n", '', $content);

if (preg_match_all('/filename([^\s]+)/i', $content, $matches)) {
    echo implode("\n", $matches[1]);
}

--EXPECT--
*0*=UTF-8'de'S%C3%BCper%20gr%C3%B6se%20tolle%20tolle%20gr%C3%BC;
*1*=%C3%9Fe.txt;
PK��Z�(V,��(test/Mail_Mime/tests/test_Bug_12411.phptnu�[���--TEST--
Bug #12411  RFC2047 encoded attachment filenames
--SKIPIF--
--FILE--
<?php
include "Mail/mime.php";
$Mime = new Mail_mime();

// some text with polish Unicode letter at the beginning
$filename = base64_decode("xZtjaWVtYQ==");
$Mime->addAttachment('testfile', "text/plain", $filename, FALSE,
    'base64', 'attachment', 'ISO-8859-1', 'pl', '',
    'quoted-printable', 'base64');

$content = $Mime->get();
$content = str_replace("\n", '', $content);

if (preg_match_all('/(name|filename)=([^\s]+)/i', $content, $matches)) {
    echo implode("\n", $matches[2]);
}

?>
--EXPECT--
"=?ISO-8859-1?Q?=C5=9Bciema?="
"=?ISO-8859-1?B?xZtjaWVtYQ==?=";
PK��Z��qS��*test/Mail_Mime/tests/test_Bug_10999_1.phptnu�[���--TEST--
Bug #10999  Bad Content-ID(cid) format
--SKIPIF--
--FILE--
<?php
$from='user@from.example.com';

require_once('Mail/mime.php');

$mime=new Mail_mime();

$body='<img src="test.gif"/>';

$mime->setHTMLBody($body);
$mime->setFrom($from);
$mime->addHTMLImage('','image/gif', 'test.gif', false);
$msg=$mime->get();

$header = preg_match('|Content-ID: <[0-9a-fA-F]+@from.example.com>|', $msg);
if (!$header){
    print("FAIL:\n");
    print($msg);
}else{
    print("OK");
}
--EXPECT--
OK
PK��Z29r���'test/Mail_Mime/tests/encoding_case.phptnu�[���--TEST--
Bug #2364   Tabs in Mail_mimePart::quotedPrintableEncode()
--SKIPIF--
--FILE--
<?php
$test = "Here's\t\na tab\n";
require_once('Mail/mimePart.php');
print Mail_mimePart::quotedPrintableEncode($test, 7);
?>
--EXPECT--
Here's=
=09
a tab
PK��ZM�-\��(test/Mail_Mime/tests/test_Bug_17175.phptnu�[���--TEST--
Bug #17175  Content-Description support+ecoding
--SKIPIF--
--FILE--
<?php
require_once('Mail/mime.php');

$Mime = new Mail_Mime();
$Mime->setTXTBody('Test message.');
$Mime->addAttachment('test file contents', "text/plain",
    'test.txt', FALSE, 'base64', NULL, 'UTF-8', NULL, NULL, NULL, NULL,
    'desc');
$Mime->addAttachment('test file contents', "text/plain",
    'test2.txt', FALSE, 'base64', NULL, 'UTF-8', NULL, NULL, NULL, NULL,
    'test unicode żąśź');

$body = $Mime->getMessage();
preg_match_all('/Content-Description: (.*)/', $body, $matches);
foreach ($matches[1] as $value)
    echo $value."\n";
?>
--EXPECT--
desc
=?UTF-8?Q?test_unicode_=C5=BC=C4=85=C5=9B=C5=BA?=
PK��ZّB�
�
*test/Mail_Mime/tests/qp_encoding_test.phptnu�[���--TEST--
qp comprehensive test
--SKIPIF--
--FILE--
<?php
error_reporting(E_ALL); // ignore E_STRICT

include("Mail/mimePart.php");

/**
 * Convenience function to make qp encoded output easier to verify
 *
 * @param string $text Input text to be encoded and printed
 * @param int $begin Start character to visibly print from
 * @param int $end Stop character to visibly print to
 * @param bool $special_chars Convert character such as linebreaks
 *     etc. to visible replacements.
 * @param int $break Line length before soft break
 *
 */
function debug_print($text, $begin=False, $end=False, $special_chars=True, $break=76) {
    $begin = $begin ? $begin : strlen($text);
    $end = $end ? $end : strlen($text);

    for ($i=$begin; $i <= $end; $i++) {
        $input = substr($text, 0, $i);
        $output = Mail_mimePart::quotedPrintableEncode($input, $break);

        if ($special_chars) {
            $input_vis = str_replace("\t", '\t', str_replace("\n", '\n', str_replace("\r", '\r', $input)));
        } else {
            $input_vis = $input;
        }
        printf("input: %02d: %s\n", strlen($input), $input_vis);

        $lines = explode("\r\n", $output);
        for($j=0; $j < count($lines); $j++) {
            $line = $lines[$j];
            if ($j + 1 < count($lines) && $special_chars) {
                $line_vis = str_replace("\t", '\t', $line).'\r\n';
            } else {
                $line_vis = $line;
            }
            printf("output:%02d: %s\n", strlen($line), $line_vis);
        }
        print("---\n");
    }
}

// Test linebreaks on regular long lines
$text = '12345678901234567890123456789012345678901234567890123456789012345678901234567890';
debug_print($text, 74);

// Test linebreaks on long line with dot at end.
$text = '123456789.12';
debug_print($text, 10, False, False, 10);

$text = "\tHere's\t\na tab.\n";
debug_print($text, False, False, True, 8);

--EXPECT--
input: 74: 12345678901234567890123456789012345678901234567890123456789012345678901234
output:74: 12345678901234567890123456789012345678901234567890123456789012345678901234
---
input: 75: 123456789012345678901234567890123456789012345678901234567890123456789012345
output:75: 123456789012345678901234567890123456789012345678901234567890123456789012345
---
input: 76: 1234567890123456789012345678901234567890123456789012345678901234567890123456
output:76: 1234567890123456789012345678901234567890123456789012345678901234567890123456
---
input: 77: 12345678901234567890123456789012345678901234567890123456789012345678901234567
output:76: 123456789012345678901234567890123456789012345678901234567890123456789012345=\r\n
output:02: 67
---
input: 78: 123456789012345678901234567890123456789012345678901234567890123456789012345678
output:76: 123456789012345678901234567890123456789012345678901234567890123456789012345=\r\n
output:03: 678
---
input: 79: 1234567890123456789012345678901234567890123456789012345678901234567890123456789
output:76: 123456789012345678901234567890123456789012345678901234567890123456789012345=\r\n
output:04: 6789
---
input: 80: 12345678901234567890123456789012345678901234567890123456789012345678901234567890
output:76: 123456789012345678901234567890123456789012345678901234567890123456789012345=\r\n
output:05: 67890
---
input: 10: 123456789.
output:10: 123456789.
---
input: 11: 123456789.1
output:10: 123456789=
output:04: =2E1
---
input: 12: 123456789.12
output:10: 123456789=
output:05: =2E12
---
input: 16: \tHere's\t\na tab.\n
output:08: \tHere's=\r\n
output:03: =09\r\n
output:06: a tab.\r\n
output:00: 
---
PK��Z)#��pp(test/Mail_Mime/tests/test_Bug_18772.phptnu�[���--TEST--
Bug #18772  Text/calendar message
--SKIPIF--
--FILE--
<?php
include "Mail/mime.php";

$mime = new Mail_mime;
$mime->setSubject('test');

// A message with text/calendar only
$mime->setCalendarBody('VCALENDAR');

echo $mime->getMessage();
echo "\n---\n";

// A message with alternative text
$mime->setTXTBody('vcalendar');
$msg = $mime->getMessage();

echo preg_replace('/=_[0-9a-z]+/', '*', $msg);
--EXPECT--
MIME-Version: 1.0
Subject: test
Content-Type: text/calendar; charset=UTF-8; method=request
Content-Transfer-Encoding: quoted-printable

VCALENDAR
---
MIME-Version: 1.0
Subject: test
Content-Type: multipart/alternative;
 boundary="*"

--*
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=ISO-8859-1

vcalendar
--*
Content-Transfer-Encoding: quoted-printable
Content-Type: text/calendar; method=request; charset=UTF-8

VCALENDAR
--*--
PK��Z2!�B��,test/Mail_Mime/tests/test_linebreak_dot.phptnu�[���--TEST--
Test for correct "." encoding when doing linebreaks
--SKIPIF--
--FILE--
<?php
error_reporting(E_ALL); // ignore E_STRICT
include("Mail/mime.php");
$text     = '0123456789012345678901234567890123456789012345678901234567890123456789012...6';
$params   = Array(
    'content_type' => 'text/plain',
    'encoding'     => 'quoted-printable',
);

for ($i=74; $i <= strlen($text); $i++) {
    $input = substr($text, 0, $i);
    $mimePart = new Mail_mimePart($input, $params);
    $encoded  =  $mimePart->encode();
    $output = $encoded['body'];
    printf("input: %02d: %s\n", strlen($input), $input);

    $lines = explode("\r\n", $output);
    for($j=0; $j < count($lines); $j++) {
        $line = $lines[$j];
        if ($j + 1 < count($lines)) {
            $line_vis = $line.'\r\n';
        } else {
            $line_vis = $line;
        }
        printf("output:%02d: %s\n", strlen($line), $line_vis);
    }

    print("---\n");

}
--EXPECT--
input: 74: 0123456789012345678901234567890123456789012345678901234567890123456789012.
output:74: 0123456789012345678901234567890123456789012345678901234567890123456789012.
---
input: 75: 0123456789012345678901234567890123456789012345678901234567890123456789012..
output:75: 0123456789012345678901234567890123456789012345678901234567890123456789012..
---
input: 76: 0123456789012345678901234567890123456789012345678901234567890123456789012...
output:76: 0123456789012345678901234567890123456789012345678901234567890123456789012...
---
input: 77: 0123456789012345678901234567890123456789012345678901234567890123456789012...6
output:76: 0123456789012345678901234567890123456789012345678901234567890123456789012..=\r\n
output:04: =2E6
---
PK��ZB&���(test/Mail_Mime/tests/test_Bug_12466.phptnu�[���--TEST--
Bug #12466  Content-Transfer-Encoding checking
--SKIPIF--
--FILE--
<?php
include("Mail/mime.php");

$params = array(
    'text_encoding' => '7bit',
    'html_encoding' => '7bit',
);
$mime = new Mail_mime($params);
$mime->setTXTBody("ż");
$mime->setHTMLBody("z");
$body = $mime->getMessage();

preg_match_all('/Content-Transfer-Encoding: (.*)/', $body, $m);
echo trim($m[1][0])."\n".trim($m[1][1]);

?>
--EXPECT--
quoted-printable
7bit
PK��Z�M�U..(test/Mail_Mime/tests/test_Bug_20273.phptnu�[���--TEST--
Bug #20273  Mail_mimePart::encodeHeader() and TAB character
--SKIPIF--
--FILE--
<?php
include("Mail/mimePart.php");

$refs = "<test@domain.tld>\t<test2@domain.tld>";
$mime = new Mail_mimePart();
echo $mime->encodeHeader('References', $refs);
?>
--EXPECT--
<test@domain.tld> <test2@domain.tld>
PK��Z[��b��3test/Mail_Mime/tests/content_transfer_encoding.phptnu�[���--TEST--
Test empty Content-Transfer-Encoding on multipart messages
--SKIPIF--
--FILE--
<?php
include "Mail/mime.php";
$mime = new Mail_mime("\r\n");
$mime->setParam('text_encoding', 'quoted-printable');
$mime->setParam('html_encoding', 'quoted-printable');
$mime->setParam('head_encoding', 'quoted-printable');

// This specific order used to set Content-Transfer-Encoding: quoted-printable
// which is invalid according to RFC 2045 on multipart messages
$mime->setTXTBody('text');
$mime->headers(array('From' => 'from@domain.tld'));
$mime->addAttachment('file.pdf', 'application/pdf', 'file.pdf', false, 'base64', 'inline');
echo $mime->txtHeaders();
list ($header, $body) = explode("\r\n\r\n", $mime->getMessage());
echo $header;
?>
--EXPECTF--
MIME-Version: 1.0
From: from@domain.tld
Content-Type: multipart/mixed;
 boundary="=_%x"
MIME-Version: 1.0
From: from@domain.tld
Content-Type: multipart/mixed;
 boundary="=_%x"
PK��Z�k�0(test/Mail_Mime/tests/test_Bug_20564.phptnu�[���--TEST--
Bug #20564  Unsetting headers
--SKIPIF--
--FILE--
<?php
include("Mail/mime.php");

$mime = new Mail_mime;
$mime->setSubject('test');

$headers = $mime->headers(array('Subject' => null), true);
echo array_key_exists('Subject', $headers) ? '1' : '0';
--EXPECT--
0PK��Z�a�[��(test/Mail_Mime/tests/class-filename.phptnu�[���--TEST--
Test class filename (bug #24)
--SKIPIF--
<?php
echo "skip This will be broken until Mail_Mime2";
?>
--FILE--
<?php
@include('Mail/Mime.php');
echo class_exists('Mail_Mime') ? 'Include OK' : 'Include failed';
?>
--EXPECT--
Include OK
PK��Z���o		(test/Mail_Mime/tests/test_Bug_14529.phptnu�[���--TEST--
Bug #14529  basename() workaround
--SKIPIF--
--FILE--
<?php
include "Mail/mime.php";

$Mime = new Mail_mime();
// some text with polish Unicode letter at the beginning
$filename = base64_decode("xZtjaWVtYQ==");
$Mime->addAttachment('testfile', "text/plain", $filename, FALSE, 'base64', 'attachment', 'ISO-8859-1');

$content = $Mime->get();
$content = str_replace("\n", '', $content);

if (preg_match('/filename([^\s]+)/i', $content, $matches)) {
    echo $matches[1];
}
?>
--EXPECT--
*=ISO-8859-1''%C5%9Bciema;
PK��ZCz2�}}(test/Mail_Mime/tests/test_Bug_12165.phptnu�[���--TEST--
Bug #12165  Dot at the end of the line disappeared
--SKIPIF--
--FILE--
<?php
include ("Mail/mime.php");
$string='http://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com';
$mime = new Mail_mime();
$mime->setHTMLBody($string);
print_r($mime->get());
    
--EXPECT--
http://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=
=2Ecom
PK��ZYa�k!!8test/Mail_Mime/tests/sleep_wakeup_EOL-bug3488-part1.phptnu�[���--TEST--
Bug #3488   Sleep/Wakeup EOL Consistency - Part 1
--SKIPIF--
--FILE--
<?php
require_once('Mail/mime.php');
$mm = new Mail_mime("\n");
$mm->setHTMLBody('<html></html>');
$mm->setTxtBody('Blah blah');

if (version_compare(phpversion(), "5.0.0", '<')) {
    $mmCopy = $mm;
} else {
    $mmCopy = clone($mm);
}

$mm->get();
$x = $mm->headers();

$smm = serialize(array('mm' => $mmCopy, 'header' => $x['Content-Type']));
$fp = fopen('sleep_wakeup_data', 'w');
fwrite($fp, $smm);
fclose($fp);

echo "Data written";
?>
--EXPECT--
Data written
PK��Z@�/�NN(test/Mail_Mime/tests/test_Bug_21206.phptnu�[���--TEST--
Bug #21206  Handling quoted strings
--SKIPIF--
--FILE--
<?php
require_once('Mail/mimePart.php');
class X extends Mail_mimePart {
    public static function explodeQuotedString($delimiter, $string) {
        return Mail_mimePart::explodeQuotedString($delimiter, $string);
    }
}

$tests = array(
    '"a" <a@a.a>, b <b@b.b>',
    '"c\\\\" <c@c.c>, d <d@d.d>',
);
foreach ($tests as $test) {
    $addrs = X::explodeQuotedString('[\t,]', $test);
    foreach ($addrs as $addr) {
        print trim($addr) . PHP_EOL;
    }
}
?>
--EXPECT--
"a" <a@a.a>
b <b@b.b>
"c\\" <c@c.c>
d <d@d.d>
PK��Z�8��)test/Mail_Mime/tests/test_Bug_3513_1.phptnu�[���--TEST--
Bug #3513   Support of RFC2231 in header fields. (ISO-8859-1)
--SKIPIF--
--FILE--
<?php
require_once('Mail/mime.php');

$test = "F��b�r.txt";
$Mime = new Mail_Mime();
$Mime->addAttachment('testfile',"text/plain", $test, FALSE, 'base64', 'attachment', 'ISO-8859-1');

$content = $Mime->get();
$content = str_replace("\n", '', $content);

if (preg_match('/filename([^\s]+)/i', $content, $matches)) {
    echo $matches[1];
}

--EXPECT--
*=ISO-8859-1''F%F3%F3b%E6r.txt;
PK��Z5����(test/Mail_Mime/tests/test_Bug_21098.phptnu�[���--TEST--
Bug #21098  Handling of empty plain text parts
--SKIPIF--
--FILE--
<?php
include "Mail/mime.php";

$mime = new Mail_mime();
$mime->setTxtBody('');
$mime->setHTMLBody('<html></html>');

$headers1 = $mime->txtHeaders();
$body     = $mime->get();
$headers2 = $mime->txtHeaders();
print strpos($headers1, 'text/html') && strpos($headers2, 'text/html') ? 'OK' : 'NOT OK';
--EXPECT--
OK
PK��Z���v��)test/Mail_Mime/tests/test_Bug_8541_1.phptnu�[���--TEST--
Bug #8541   mimePart.php line delimiter is \r
--SKIPIF--
--FILE--
<?php
$mime = file_get_contents('Mail/mime.php', 1);
$mimePart = file_get_contents('Mail/mimePart.php', 1);
if (strpos($mime, "\r")){
    print("\\r found in mime.php\n");
}elseif (strpos($mime, "\t")){
    print("\\t found in mime.php\n");
}elseif (strpos($mimePart, "\r")){
    print("\\r found in mimePart.php\n");
}elseif (strpos($mimePart, "\t")){
    print("\\t found in mimePart.php\n");
}
print('OK');
--EXPECT--
OK
PK��ZUi�E!E!2test/Mail_Mime/tests/headers_without_mbstring.phptnu�[���--TEST--
Multi-test for headers encoding using base64 and quoted-printable
--SKIPIF--
<?php
if (function_exists('mb_substr') && function_exists('mb_strlen')) {
    die("skip mbstring functions found!");
}
?>
--FILE--
<?php
include("Mail/mime.php");
$mime = new Mail_mime();

$headers = array(
array('From', '<adresse@adresse.de>'),
array('From', 'adresse@adresse.de'),
array('From', 'Frank Do <adresse@adresse.de>'),
array('To', 'Frank Do <adresse@adresse.de>, James Clark <james@domain.com>'),
array('From', '"Frank Do" <adresse@adresse.de>'),
array('Cc', '"Frank Do" <adresse@adresse.de>, "James Clark" <james@domain.com>'),
array('Cc', ' <adresse@adresse.de>, "Kuśmiderski Jan Krzysztof Janusz Długa nazwa" <cris@domain.com>'),
array('From', '"adresse@adresse.de" <addresse@adresse>'),
array('From', 'adresse@adresse.de <addresse@adresse>'),
array('From', '"German Umlauts öäü" <adresse@adresse.de>'),
array('Subject', 'German Umlauts öäü <adresse@adresse.de>'),
array('Subject', 'Short ASCII subject'),
array('Subject', 'Long ASCII subject - multiline space separated words - too long for one line'),
array('Subject', 'Short Unicode ż subject'),
array('Subject', 'Long Unicode subject - zażółć gęślą jaźń - too long for one line'),
array('References', '<hglvja$jg7$1@nemesis.news.neostrada.pl>  <4b2e87ac$1@news.home.net.pl> <hgm5b1$3a7$1@atlantis.news.neostrada.pl>'),
array('To', '"Frank Do" <adresse@adresse.de>,, "James Clark" <james@domain.com>'),
array('To', '"Frank \\" \\\\Do" <adresse@adresse.de>'),
array('To', 'Frank " \\Do <adresse@adresse.de>'),
array('Subject', "A REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY /REALLY/ LONG test"),
array('Subject', "TEST Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir!!!?"),
array('Subject', "Update: Microsoft Windows-Tool zum Entfernen bösartiger Software 3.6"),
array('From', "test@nàme <user@domain.com>"),
array('From', "Test <\"test test\"@domain.com>"),
array('From', "\"test test\"@domain.com"),
array('From', "<\"test test\"@domain.com>"),
array('From', "Doe<test@domain.com>"),
array('From', "\"John Doe\"<test@domain.com>"),
array('Mail-Reply-To', 'adresse@adresse.de <addresse@adresse>'),
array('Mail-Reply-To', '"öäü" <adresse@adresse.de>'),
);

$i = 1;
foreach ($headers as $header) {
    $hdr = $mime->encodeHeader($header[0], $header[1], 'UTF-8', 'base64');
    printf("[%02d] %s: %s\n", $i, $header[0], $hdr);
    $hdr = $mime->encodeHeader($header[0], $header[1], 'UTF-8', 'quoted-printable');
    printf("[%02d] %s: %s\n", $i, $header[0], $hdr);
    $i++;
}
?>
--EXPECT--
[01] From: <adresse@adresse.de>
[01] From: <adresse@adresse.de>
[02] From: adresse@adresse.de
[02] From: adresse@adresse.de
[03] From: Frank Do <adresse@adresse.de>
[03] From: Frank Do <adresse@adresse.de>
[04] To: Frank Do <adresse@adresse.de>, James Clark <james@domain.com>
[04] To: Frank Do <adresse@adresse.de>, James Clark <james@domain.com>
[05] From: "Frank Do" <adresse@adresse.de>
[05] From: "Frank Do" <adresse@adresse.de>
[06] Cc: "Frank Do" <adresse@adresse.de>, "James Clark" <james@domain.com>
[06] Cc: "Frank Do" <adresse@adresse.de>, "James Clark" <james@domain.com>
[07] Cc: <adresse@adresse.de>, =?UTF-8?B?S3XFm21pZGVyc2tpIEphbiBLcnp5c3p0b2Yg?=
 =?UTF-8?B?SmFudXN6IETFgnVnYSBuYXp3YQ==?= <cris@domain.com>
[07] Cc: <adresse@adresse.de>,
 =?UTF-8?Q?Ku=C5=9Bmiderski_Jan_Krzysztof_Janusz_D?=
 =?UTF-8?Q?=C5=82uga_nazwa?= <cris@domain.com>
[08] From: "adresse@adresse.de" <addresse@adresse>
[08] From: "adresse@adresse.de" <addresse@adresse>
[09] From: "adresse@adresse.de" <addresse@adresse>
[09] From: "adresse@adresse.de" <addresse@adresse>
[10] From: =?UTF-8?B?R2VybWFuIFVtbGF1dHMgw7bDpMO8?= <adresse@adresse.de>
[10] From: =?UTF-8?Q?German_Umlauts_=C3=B6=C3=A4=C3=BC?= <adresse@adresse.de>
[11] Subject: =?UTF-8?B?R2VybWFuIFVtbGF1dHMgw7bDpMO8IDxhZHJlc3NlQGFkcmVzc2Uu?=
 =?UTF-8?B?ZGU+?=
[11] Subject: =?UTF-8?Q?German_Umlauts_=C3=B6=C3=A4=C3=BC_=3Cadresse=40adresse?=
 =?UTF-8?Q?=2Ede=3E?=
[12] Subject: Short ASCII subject
[12] Subject: Short ASCII subject
[13] Subject: Long ASCII subject - multiline space separated words - too long for
 one line
[13] Subject: Long ASCII subject - multiline space separated words - too long for
 one line
[14] Subject: =?UTF-8?B?U2hvcnQgVW5pY29kZSDFvCBzdWJqZWN0?=
[14] Subject: =?UTF-8?Q?Short_Unicode_=C5=BC_subject?=
[15] Subject: =?UTF-8?B?TG9uZyBVbmljb2RlIHN1YmplY3QgLSB6YcW8w7PFgsSHIGfEmcWb?=
 =?UTF-8?B?bMSFIGphxbrFhCAtIHRvbyBsb25nIGZvciBvbmUgbGluZQ==?=
[15] Subject: =?UTF-8?Q?Long_Unicode_subject_-_za=C5=BC=C3=B3=C5=82=C4=87_g=C4?=
 =?UTF-8?Q?=99=C5=9Bl=C4=85_ja=C5=BA=C5=84_-_too_long_for_one_line?=
[16] References: <hglvja$jg7$1@nemesis.news.neostrada.pl>
 <4b2e87ac$1@news.home.net.pl> <hgm5b1$3a7$1@atlantis.news.neostrada.pl>
[16] References: <hglvja$jg7$1@nemesis.news.neostrada.pl>
 <4b2e87ac$1@news.home.net.pl> <hgm5b1$3a7$1@atlantis.news.neostrada.pl>
[17] To: "Frank Do" <adresse@adresse.de>, "James Clark" <james@domain.com>
[17] To: "Frank Do" <adresse@adresse.de>, "James Clark" <james@domain.com>
[18] To: "Frank \" \\Do" <adresse@adresse.de>
[18] To: "Frank \" \\Do" <adresse@adresse.de>
[19] To: "Frank \" \\Do" <adresse@adresse.de>
[19] To: "Frank \" \\Do" <adresse@adresse.de>
[20] Subject: A REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY
 REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY
 REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY
 REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY /REALLY/ LONG test
[20] Subject: A REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY
 REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY
 REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY
 REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY /REALLY/ LONG test
[21] Subject: =?UTF-8?B?VEVTVCBTw7xwZXIgZ3LDtnNlIHRvbGxlIGdyw7zDn2Ugdm9uIG1p?=
 =?UTF-8?B?ciBTw7xwZXIgZ3LDtnNlIHRvbGxlIGdyw7zDn2Ugdm9uIG1pciBTw7xwZXIg?=
 =?UTF-8?B?Z3LDtnNlIHRvbGxlIGdyw7zDn2Ugdm9uIG1pciBTw7xwZXIgZ3LDtnNlIHRv?=
 =?UTF-8?B?bGxlIGdyw7zDn2Ugdm9uIG1pciBTw7xwZXIgZ3LDtnNlIHRvbGxlIGdyw7zD?=
 =?UTF-8?B?n2Ugdm9uIG1pciBTw7xwZXIgZ3LDtnNlIHRvbGxlIGdyw7zDn2Ugdm9uIG1p?=
 =?UTF-8?B?ciBTw7xwZXIgZ3LDtnNlIHRvbGxlIGdyw7zDn2Ugdm9uIG1pciBTw7xwZXIg?=
 =?UTF-8?B?Z3LDtnNlIHRvbGxlIGdyw7zDn2Ugdm9uIG1pciBTw7xwZXIgZ3LDtnNlIHRv?=
 =?UTF-8?B?bGxlIGdyw7zDn2Ugdm9uIG1pciEhIT8=?=
[21] Subject: =?UTF-8?Q?TEST_S=C3=BCper_gr=C3=B6se_tolle_gr=C3=BC=C3=9Fe_von_mir?=
 =?UTF-8?Q?_S=C3=BCper_gr=C3=B6se_tolle_gr=C3=BC=C3=9Fe_von_mir_S=C3=BCper_g?=
 =?UTF-8?Q?r=C3=B6se_tolle_gr=C3=BC=C3=9Fe_von_mir_S=C3=BCper_gr=C3=B6se_tol?=
 =?UTF-8?Q?le_gr=C3=BC=C3=9Fe_von_mir_S=C3=BCper_gr=C3=B6se_tolle_gr=C3=BC?=
 =?UTF-8?Q?=C3=9Fe_von_mir_S=C3=BCper_gr=C3=B6se_tolle_gr=C3=BC=C3=9Fe_von_m?=
 =?UTF-8?Q?ir_S=C3=BCper_gr=C3=B6se_tolle_gr=C3=BC=C3=9Fe_von_mir_S=C3=BCper?=
 =?UTF-8?Q?_gr=C3=B6se_tolle_gr=C3=BC=C3=9Fe_von_mir_S=C3=BCper_gr=C3=B6se_t?=
 =?UTF-8?Q?olle_gr=C3=BC=C3=9Fe_von_mir!!!=3F?=
[22] Subject: =?UTF-8?B?VXBkYXRlOiBNaWNyb3NvZnQgV2luZG93cy1Ub29sIHp1bSBFbnRm?=
 =?UTF-8?B?ZXJuZW4gYsO2c2FydGlnZXIgU29mdHdhcmUgMy42?=
[22] Subject: =?UTF-8?Q?Update=3A_Microsoft_Windows-Tool_zum_Entfernen_b=C3=B6sa?=
 =?UTF-8?Q?rtiger_Software_3=2E6?=
[23] From: =?UTF-8?B?dGVzdEBuw6BtZQ==?= <user@domain.com>
[23] From: =?UTF-8?Q?test=40n=C3=A0me?= <user@domain.com>
[24] From: Test <"test test"@domain.com>
[24] From: Test <"test test"@domain.com>
[25] From: "test test"@domain.com
[25] From: "test test"@domain.com
[26] From: <"test test"@domain.com>
[26] From: <"test test"@domain.com>
[27] From: Doe <test@domain.com>
[27] From: Doe <test@domain.com>
[28] From: "John Doe" <test@domain.com>
[28] From: "John Doe" <test@domain.com>
[29] Mail-Reply-To: "adresse@adresse.de" <addresse@adresse>
[29] Mail-Reply-To: "adresse@adresse.de" <addresse@adresse>
[30] Mail-Reply-To: =?UTF-8?B?w7bDpMO8?= <adresse@adresse.de>
[30] Mail-Reply-To: =?UTF-8?Q?=C3=B6=C3=A4=C3=BC?= <adresse@adresse.de>
PK��Z��(test/Mail_Mime/tests/test_Bug_21027.phptnu�[���--TEST--
Bug #21027  Calendar support along with attachments and html images
--SKIPIF--
--FILE--
<?php
require_once('Mail/mime.php');

$txtBody = 'Hi, this is Plain Text Body.';
$htmlBody = '<div>This is HTML body.</div>';
$icsText = 'BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//icalcreator//NONSGML iCalcreator 2.22//
METHOD:REQUEST
BEGIN:VEVENT
UID:77@localhost
DTSTAMP:20160208T170811Z
ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=
 TRUE;CN=Jacob Alvarez:MAILTO:fake1@mailinator.com
CREATED:20160208T170810Z
DTSTART:20160215T180000Z
DTEND:20160215T190000Z
ORGANIZER;CN=-:MAILTO:fake2@mailinator.com
SEQUENCE:1
STATUS:CONFIRMED
SUMMARY:Prueba 69
TRANSP:OPAQUE
URL:http://localhost/event/77
END:VEVENT
END:VCALENDAR';

function printPartsStartAndEnd($body) {
    $matches  = array();
    preg_match_all('/--(=_[a-z0-9]+)--|Content-Type: ([^;\r\n]+)/', $body, $matches);
    $tab = "    ";
    foreach ($matches[0] as $match){
        if (strpos($match, '--') === false) {
            printf("%s%s\n", $tab, $match);
            if (stripos($match, "multipart")) {
                $tab .= "    ";
            }
        } else {
            $tab = substr($tab, 0, -4);
            printf("%sEnd part\n", $tab);
        }
    }
}

function printHeaderContentType($headers) {
    $headerContentType = array();
    preg_match('/([^;\r\n]+)/', $headers['Content-Type'], $headerContentType);
    printf("Content-Type: %s\n", $headerContentType[0]);
}

print "TEST: text\n";
$mime = new Mail_mime();
$mime->setTXTBody($txtBody);
$headers = $mime->headers();
$body = $mime->get();
printHeaderContentType($headers);
printPartsStartAndEnd($body);
print("\n");

print "TEST: html\n";
$mime = new Mail_mime();
$mime->setHTMLBody($htmlBody);
$headers = $mime->headers();
$body = $mime->get();
printHeaderContentType($headers);
printPartsStartAndEnd($body);
print("\n");

print "TEST: attachments\n";
$mime = new Mail_mime();
$mime->addAttachment($icsText, 'application/ics', 'invite.ics', false);
$headers = $mime->headers();
$body = $mime->get();
printHeaderContentType($headers);
printPartsStartAndEnd($body);
print("\n");

print "TEST: text + attachments\n";
$mime = new Mail_mime();
$mime->setTXTBody($txtBody);
$mime->addAttachment($icsText, 'application/ics', 'invite.ics', false);
$headers = $mime->headers();
$body = $mime->get();
printHeaderContentType($headers);
printPartsStartAndEnd($body);
print("\n");

print "TEST: html + attachments\n";
$mime = new Mail_mime();
$mime->setHTMLBody($htmlBody);
$mime->addAttachment($icsText, 'application/ics', 'invite.ics', false);
$headers = $mime->headers();
$body = $mime->get();
printHeaderContentType($headers);
printPartsStartAndEnd($body);
print("\n");

print "TEST: html + inline images\n";
$mime = new Mail_mime();
$mime->setHTMLBody($htmlBody);
$mime->addHTMLImage("aaaaaaaaaa", 'image/gif', 'image.gif', false, 'contentid');
$headers = $mime->headers();
$body = $mime->get();
printHeaderContentType($headers);
printPartsStartAndEnd($body);
print("\n");

print("TEST: txt, html and attachment\n");
$mime = new Mail_mime();
$mime->setTXTBody($txtBody);
$mime->setHTMLBody($htmlBody);
$mime->addAttachment("test", 'application/octet-stream', 'attachment', false);
$headers = $mime->headers();
$body = $mime->get();
printHeaderContentType($headers);
printPartsStartAndEnd($body);
print("\n");

print "TEST: calendar\n";
$mime = new Mail_mime();
$mime->setCalendarBody($icsText);
$headers = $mime->headers();
$body = $mime->get();
printHeaderContentType($headers);
printPartsStartAndEnd($body);
print("\n");

print "TEST: txt + calendar\n";
$mime->setTXTBody($txtBody);
$headers = $mime->headers();
$body = $mime->get();
printHeaderContentType($headers);
printPartsStartAndEnd($body);
print("\n");

print "TEST: txt, html, calendar\n";
$mime = new Mail_mime();
$mime->setTXTBody($txtBody);
$mime->setHTMLBody($htmlBody);
$mime->setCalendarBody($icsText);
$headers = $mime->headers();
$body = $mime->get();
printHeaderContentType($headers);
printPartsStartAndEnd($body);
print("\n");

print "TEST: txt, html + html images, and calendar\n";
$mime = new Mail_mime();
$mime->setTXTBody($txtBody);
$mime->setHTMLBody($htmlBody);
$mime->addHTMLImage('testimage', 'image/gif', "bus.gif", false);
$mime->setCalendarBody($icsText);
$headers = $mime->headers();
$body = $mime->get();
printHeaderContentType($headers);
printPartsStartAndEnd($body);
print("\n");

print("TEST: txt, html, calendar and attachment\n");
$mime = new Mail_mime();
$mime->setTXTBody($txtBody);
$mime->setHTMLBody($htmlBody);
$mime->setCalendarBody($icsText);
$mime->addAttachment("test", 'application/octet-stream', 'attachment', false);
$headers = $mime->headers();
$body = $mime->get();
printHeaderContentType($headers);
printPartsStartAndEnd($body);
print("\n");

print "TEST: txt, html + html images, calendar, and attachment\n";
$mime = new Mail_mime();
$mime->setTXTBody($txtBody);
$mime->setHTMLBody($htmlBody);
$mime->addHTMLImage('testimage', 'image/gif', "bus.gif", false);
$mime->setCalendarBody($icsText);
$mime->addAttachment($icsText, 'application/ics', 'invite.ics', false);
$headers = $mime->headers();
$body = $mime->get();
printHeaderContentType($headers);
printPartsStartAndEnd($body);
print("\n");
?>
--EXPECT--
TEST: text
Content-Type: text/plain

TEST: html
Content-Type: text/html

TEST: attachments
Content-Type: multipart/mixed
    Content-Type: application/ics
End part

TEST: text + attachments
Content-Type: multipart/mixed
    Content-Type: text/plain
    Content-Type: application/ics
End part

TEST: html + attachments
Content-Type: multipart/mixed
    Content-Type: text/html
    Content-Type: application/ics
End part

TEST: html + inline images
Content-Type: multipart/related
    Content-Type: text/html
    Content-Type: image/gif
End part

TEST: txt, html and attachment
Content-Type: multipart/mixed
    Content-Type: multipart/alternative
        Content-Type: text/plain
        Content-Type: text/html
    End part
    Content-Type: application/octet-stream
End part

TEST: calendar
Content-Type: text/calendar

TEST: txt + calendar
Content-Type: multipart/alternative
    Content-Type: text/plain
    Content-Type: text/calendar
End part

TEST: txt, html, calendar
Content-Type: multipart/alternative
    Content-Type: text/plain
    Content-Type: text/html
    Content-Type: text/calendar
End part

TEST: txt, html + html images, and calendar
Content-Type: multipart/alternative
    Content-Type: text/plain
    Content-Type: multipart/related
        Content-Type: text/html
        Content-Type: image/gif
    End part
    Content-Type: text/calendar
End part

TEST: txt, html, calendar and attachment
Content-Type: multipart/mixed
    Content-Type: multipart/alternative
        Content-Type: text/plain
        Content-Type: text/html
        Content-Type: text/calendar
    End part
    Content-Type: application/octet-stream
End part

TEST: txt, html + html images, calendar, and attachment
Content-Type: multipart/mixed
    Content-Type: multipart/alternative
        Content-Type: text/plain
        Content-Type: multipart/related
            Content-Type: text/html
            Content-Type: image/gif
        End part
        Content-Type: text/calendar
    End part
    Content-Type: application/ics
End part
PK��Z`�~@*test/Mail_Mime/tests/test_Bug_12385_1.phptnu�[���--TEST--
Bug #12385  Bad regex when replacing css style attachments
--SKIPIF--
--FILE--
<?php
$from='user@from.example.com';

require_once('Mail/mime.php');

$mime=new Mail_mime();

$body="<style>
className {
    background-image: url('test.gif');
}
</script>
";

$mime->setHTMLBody($body);
$mime->setFrom($from);
$mime->addHTMLImage('','image/gif', 'test.gif', false);
$msg = $mime->get();

$cidtag = preg_match("|url\('cid:[^']*'\);|", $msg);
if (!$cidtag){
    print("FAIL:\n");
    print($msg);
}else{
    print("OK");
}
--EXPECT--
OK
PK��Z�zŬ�(test/Mail_Mime/tests/test_Bug_11731.phptnu�[���--TEST--
Bug #11731  Full stops after soft line breaks are not encoded
--SKIPIF--
--FILE--
<?php
include("Mail/mime.php");
// Second full stop will be at the start of the second line after quoted-printable
// encoding (full stop '=2E' + 72 characters + line-continuation '=' = 76)
$text     = '.123456789012345678901234567890123456789012345678901234567890123456789012.3456';
$params   = Array(
    'content_type' => 'text/plain',
    'encoding'     => 'quoted-printable',
);    
$mimePart = new Mail_mimePart($text, $params);
$encoded  =  $mimePart->encode();
echo $encoded['body'];
    
--EXPECT--
=2E123456789012345678901234567890123456789012345678901234567890123456789012=
=2E3456
PK��ZX��b��(test/Mail_Mime/tests/test_Bug_14779.phptnu�[���--TEST--
Bug #14779  Proper header-body separator for empty attachment
--SKIPIF--
--FILE--
<?php
include "Mail/mime.php";

$m = new Mail_mime();
$m->addAttachment('', "text/plain", 'file.txt', FALSE, 'base64', 'attachment');
$result = $m->get();

if (preg_match('/(Content.*)--=.*/s', $result, $matches)) {
    print_r($matches[1]."END");
}

?>
--EXPECT--
Content-Transfer-Encoding: base64
Content-Type: text/plain;
 name=file.txt
Content-Disposition: attachment;
 filename=file.txt


END
PK��Z�I�zz(test/Mail_Mime/tests/test_Bug_20563.phptnu�[���--TEST--
Bug #20563  isMultipart() method tests
--SKIPIF--
--FILE--
<?php
include("Mail/mime.php");

$mime = new Mail_mime;

echo ($mime->isMultipart() ? 'TRUE' : 'FALSE') . "\n";

$mime->setTXTBody('test');

echo ($mime->isMultipart() ? 'TRUE' : 'FALSE') . "\n";

$mime->setHTMLBody('test');

echo ($mime->isMultipart() ? 'TRUE' : 'FALSE') . "\n";

--EXPECT--
FALSE
FALSE
TRUE
PK��ZZX�Hww)test/Mail_Mime/tests/test_Bug_3513_3.phptnu�[���--TEST--
Bug #3513   Support of RFC2231 in header fields. (ISO-2022-JP)
--SKIPIF--
--FILE--
<?php
mb_internal_encoding('ISO-2022-JP');
$testEncoded="GyRCRnxLXDhsGyhCLnR4dA==";
$test = base64_decode($testEncoded); // Japanese filename in ISO-2022-JP charset.
require_once('Mail/mime.php');

$Mime = new Mail_Mime();
$Mime->addAttachment('testfile',"text/plain", $test, FALSE, 'base64', 'attachment', 'iso-2022-jp', '');

$content = $Mime->get();
$content = str_replace("\n", '', $content);

if (preg_match('/filename([^\s]+)/i', $content, $matches)) {
    echo $matches[1];
}
?>
--EXPECT--
*=iso-2022-jp''%1B$BF|K%5C8l%1B%28B.txt;

PK��Z������(test/Mail_Mime/tests/test_Bug_15320.phptnu�[���--TEST--
Bug #15320  Charset parameter in Content-Type of mail parts
--SKIPIF--
--FILE--
<?php
include "Mail/mime.php";

$Mime = new Mail_mime();
$Mime->addAttachment('testfile', "text/plain", 'file.txt', FALSE, 'base64', 'attachment', 'ISO-8859-1');

$content = $Mime->get();
//$content = str_replace("\n", '', $content);

if (preg_match('/Content-type:([^\n]+)/i', $content, $matches)) {
    echo $matches[1];
}

?>
--EXPECT--
text/plain; charset=ISO-8859-1;

PK��Z�-b2(test/Mail_Mime/tests/test_Bug_13032.phptnu�[���--TEST--
Bug #13032  Proper (different) boundary for nested parts
--SKIPIF--
--FILE--
<?php
include "Mail/mime.php";
$mime = new Mail_mime("\r\n");
$mime->setHTMLBody('html');
$mime->setTXTBody('text');
$mime->addAttachment('file.pdf', 'application/pdf', 'file.pdf', false, 'base64', 'inline');
$msg = $mime->getMessage();

if (preg_match_all('/boundary="([^"]+)"/', $msg, $matches)) {
    if (count($matches) == 2 && count($matches[1]) == 2 &&
        $matches[1][0] != $matches[1][1]) {
            print('OK');
    }
}
?>
--EXPECT--
OK
PK��Z%+2PP(test/Mail_Mime/tests/test_Bug_18083.phptnu�[���--TEST--
Bug #18083  Separate charset for attachment's content and headers
--SKIPIF--
--FILE--
<?php
include "Mail/mime.php";
$Mime = new Mail_mime();

$Mime->addAttachment('testfile', "text/plain",
    base64_decode("xZtjaWVtYQ=="), FALSE,
    'base64', 'attachment', 'ISO-8859-1', 'pl', '',
    'quoted-printable', 'base64', '', 'UTF-8');

$content = $Mime->get();
$content = str_replace("\n", '', $content);

if (preg_match_all('/(name|filename)=([^\s]+)/i', $content, $matches)) {
    echo implode("\n", $matches[2]);
}
?>
--EXPECT--
"=?UTF-8?Q?=C5=9Bciema?="
"=?UTF-8?B?xZtjaWVtYQ==?=";
PK��ZQi�"--(test/Mail_Mime/tests/test_Bug_11381.phptnu�[���--TEST--
Bug #11381  Domain name is attached to content-id, trailing greater-than sign is not removed
--SKIPIF--
--FILE--
<?php
$from='Test User <user@from.example.com>';

require_once('Mail/mime.php');

$mime=new Mail_mime();

$body='<img src="test.gif"/>';

$mime->setHTMLBody($body);
$mime->setFrom($from);
$mime->addHTMLImage('','image/gif', 'test.gif', false);
$msg=$mime->get();

$header = preg_match('|Content-ID: <[0-9a-fA-F]+@from.example.com>|', $msg);
if (!$header){
    print("FAIL:\n");
    print($msg);
}else{
    print("OK");
}
--EXPECT--
OK
PK��Z�X�##(test/Mail_Mime/tests/test_Bug_19497.phptnu�[���--TEST--
Bug #19497  Attachment filenames with a slash character
--SKIPIF--
--FILE--
<?php
include "Mail/mime.php";
$Mime = new Mail_mime();

$filename = "test/file.txt";
$Mime->addAttachment('testfile', "text/plain", $filename, FALSE,
    'base64', 'attachment', 'ISO-8859-1', '', '', 'quoted-printable', 'base64');

$content = $Mime->get();
$content = str_replace("\n", '', $content);

if (preg_match_all('/(name|filename)=([^\s]+)/i', $content, $matches)) {
    echo implode("\n", $matches[2]);
}
?>
--EXPECT--
"test/file.txt"
"test/file.txt";
PK��Z�'�'')test/Mail_Mime/tests/test_Bug_8386_1.phptnu�[���--TEST--
Bug #8386   HTML body not correctly encoded if attachments present
--SKIPIF--
--FILE--
<?php
$eol = "\n#";
include("Mail/mime.php");
$encoder = new Mail_mime(array('eol'=>$eol));
$encoder->setTXTBody('test');
$encoder->setHTMLBody('<b>test</b>');
$encoder->addAttachment('Just a test', 'application/octet-stream', 'test.txt', false);
$body = $encoder->get();
if (strpos($body, '--' . $eol . '--=')){
    print("FAILED\n");
    print("Single delimiter() between 2 parts found.\n");
    print($body);
}else{
    print("OK");
}
?>
--EXPECT--
OK
PK��Z��1d��(test/Mail_Mime/tests/test_Bug_17025.phptnu�[���--TEST--
Bug #16539  Headers longer than 998 characters
--SKIPIF--
--FILE--
<?php
include("Mail/mime.php");

$headers['From'] = 'aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffgggggggggghhhhhhhhhh';
# over than 76 chars
$mime = new Mail_mime();
$hdrs = $mime->headers($headers);
print_r($hdrs['From']); 
?>
--EXPECT--
aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffgggggggggghhhhhhhhhh
PK��Ze�@Q__(test/Mail_Mime/tests/test_Bug_14780.phptnu�[���--TEST--
Bug #14780  Invalid Content-Type when headers() is called before get()
--SKIPIF--
--FILE--
<?php
include("Mail/mime.php");

$mime = new Mail_mime();
$mime->setTXTBody("test");
$mime->setHTMLBody("test");

$head1 = $mime->headers();
$body = $mime->get();
$head2 = $mime->headers();

if ($head1 === $head2) {
    echo "OK";
}

?>
--EXPECT--
OK
PK��Z�
Ǟ		2test/Mail_Mime/tests/test_linebreak_larger_76.phptnu�[���--TEST--
Test for correct linebreaks for lines _longer_ than 76 chars.
--SKIPIF--
--FILE--
<?php
error_reporting(E_ALL); // ignore E_STRICT

include("Mail/mime.php");
$text     = '12345678901234567890123456789012345678901234567890123456789012345678901234567890';
$params   = Array(
    'content_type' => 'text/plain',
    'encoding'     => 'quoted-printable',
);

for ($i=74; $i <= strlen($text); $i++) {
    $input = substr($text, 0, $i);
    $mimePart = new Mail_mimePart($input, $params);
    $encoded  =  $mimePart->encode();
    $output = $encoded['body'];
    printf("input: %02d: %s\n", strlen($input), $input);

    $lines = explode("\r\n", $output);
    for($j=0; $j < count($lines); $j++) {
        $line = $lines[$j];
        if ($j + 1 < count($lines)) {
            $line_vis = $line.'\r\n';
        } else {
            $line_vis = $line;
        }
        printf("output:%02d: %s\n", strlen($line), $line_vis);
    }
    print("---\n");
}
--EXPECT--
input: 74: 12345678901234567890123456789012345678901234567890123456789012345678901234
output:74: 12345678901234567890123456789012345678901234567890123456789012345678901234
---
input: 75: 123456789012345678901234567890123456789012345678901234567890123456789012345
output:75: 123456789012345678901234567890123456789012345678901234567890123456789012345
---
input: 76: 1234567890123456789012345678901234567890123456789012345678901234567890123456
output:76: 1234567890123456789012345678901234567890123456789012345678901234567890123456
---
input: 77: 12345678901234567890123456789012345678901234567890123456789012345678901234567
output:76: 123456789012345678901234567890123456789012345678901234567890123456789012345=\r\n
output:02: 67
---
input: 78: 123456789012345678901234567890123456789012345678901234567890123456789012345678
output:76: 123456789012345678901234567890123456789012345678901234567890123456789012345=\r\n
output:03: 678
---
input: 79: 1234567890123456789012345678901234567890123456789012345678901234567890123456789
output:76: 123456789012345678901234567890123456789012345678901234567890123456789012345=\r\n
output:04: 6789
---
input: 80: 12345678901234567890123456789012345678901234567890123456789012345678901234567890
output:76: 123456789012345678901234567890123456789012345678901234567890123456789012345=\r\n
output:05: 67890
---
PK��Zܶg�hh)test/Mail_Mime/tests/test_Bug_9722_1.phptnu�[���--TEST--
Bug #9722   quotedPrintableEncode does not encode dot at start of line on Windows platform
--SKIPIF--
--FILE--
<?php
include("Mail/mimePart.php");
$text = "This
is a
test
...
    It is 
//really fun//
to make :(";

print_r(Mail_mimePart::quotedPrintableEncode($text, 76, "\n"));

--EXPECT--
This
is a
test
=2E..
    It is=20
//really fun//
to make :(
PK��Z�YcLYY(test/Mail_Mime/tests/test_Bug_16539.phptnu�[���--TEST--
Bug #16539  Headers longer than 998 characters
--SKIPIF--
--FILE--
<?php
include("Mail/mime.php");
$mime = new Mail_mime();

$headers = array(
'To' => 'jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com',
'Subject' => 'jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com',
);

echo $mime->txtHeaders($headers, true, true);
?>
--EXPECT--
MIME-Version: 1.0
To: jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com,
 jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com,
 jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com,
 jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com,
 jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com,
 jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com,
 jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com,
 jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com,
 jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com,
 jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com,
 jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com,
 jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com,
 jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com,
 jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com,
 jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com,
 jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com,
 jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com,
 jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com,
 jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com,
 jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com,
 jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com,
 jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com,
 jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com,
 jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com,
 jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com,
 jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com,
 jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com,
 jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com,
 jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com,
 jskibbie@schawk.com, jskibbie@schawk.com
Subject: jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.co
 m,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com
PK��Z��((*test/Mail_Mime/tests/test_Bug_10596_1.phptnu�[���--TEST--
Bug #10596  Incorrect handling of text and html '0' bodies
--SKIPIF--
--FILE--
<?php
include("Mail/mime.php");
$mime = new Mail_mime();
$mime->setTxtBody('0');
$mime->setHTMLBody('0');
$body = $mime->get();
if ($body){
    print("OK");
}else{
    print("NO BODY FOUND");
}
--EXPECT--
OK
PK��Z9��::*test/Mail_Mime/tests/test_Bug_10816_1.phptnu�[���--TEST--
Bug #10816  Unwanted linebreak at the end of output
--SKIPIF--
--FILE--
<?php
$eol = "#";
include("Mail/mime.php");
$encoder = new Mail_mime(array('eol'=>$eol));
$encoder->setTXTBody('test');
$encoder->setHTMLBody('<b>test</b>');
$encoder->addAttachment('Just a test', 'application/octet-stream', 'test.txt', false);
$body = $encoder->get();
$taillength = -1 * strlen($eol) * 2;
if (substr($body, $taillength) == ($eol.$eol)){
    print("FAILED\n");
    print("Body:\n");
    print("..." . substr($body, -10) . "\n");
}else{
    print("OK\n");
}
--EXPECT--
OK

PK��Z��᠗"�"/test/Mail_Mime/tests/headers_with_mbstring.phptnu�[���--TEST--
Multi-test for headers encoding using base64 and quoted-printable
--SKIPIF--
<?php
if (!function_exists('mb_substr') || !function_exists('mb_strlen')) {
    die "skip mbstring functions not found!";
}
?>
--FILE--
<?php
include("Mail/mime.php");
$mime = new Mail_mime();

$headers = array(
array('From', '<adresse@adresse.de>'),
array('From', 'adresse@adresse.de'),
array('From', 'Frank Do <adresse@adresse.de>'),
array('To', 'Frank Do <adresse@adresse.de>, James Clark <james@domain.com>'),
array('From', '"Frank Do" <adresse@adresse.de>'),
array('Cc', '"Frank Do" <adresse@adresse.de>, "James Clark" <james@domain.com>'),
array('Cc', ' <adresse@adresse.de>, "Kuśmiderski Jan Krzysztof Janusz Długa nazwa" <cris@domain.com>'),
array('From', '"adresse@adresse.de" <addresse@adresse>'),
array('From', 'adresse@adresse.de <addresse@adresse>'),
array('From', '"German Umlauts öäü" <adresse@adresse.de>'),
array('Subject', 'German Umlauts öäü <adresse@adresse.de>'),
array('Subject', 'Short ASCII subject'),
array('Subject', 'Long ASCII subject - multiline space separated words - too long for one line'),
array('Subject', 'Short Unicode ż subject'),
array('Subject', 'Long Unicode subject - zażółć gęślą jaźń - too long for one line'),
array('References', '<hglvja$jg7$1@nemesis.news.neostrada.pl>  <4b2e87ac$1@news.home.net.pl> <hgm5b1$3a7$1@atlantis.news.neostrada.pl>'),
array('To', '"Frank Do" <adresse@adresse.de>,, "James Clark" <james@domain.com>'),
array('To', '"Frank \\" \\\\Do" <adresse@adresse.de>'),
array('To', 'Frank " \\Do <adresse@adresse.de>'),
array('Subject', "A REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY /REALLY/ LONG test"),
array('Subject', "TEST Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir!!!?"),
array('Subject', "Update: Microsoft Windows-Tool zum Entfernen bösartiger Software 3.6"),
array('From', "test@nàme <user@domain.com>"),
array('From', "Test <\"test test\"@domain.com>"),
array('From', "\"test test\"@domain.com"),
array('From', "<\"test test\"@domain.com>"),
array('From', "Doe<test@domain.com>"),
array('From', "\"John Doe\"<test@domain.com>"),
array('Mail-Reply-To', 'adresse@adresse.de <addresse@adresse>'),
array('Mail-Reply-To', '"öäü" <adresse@adresse.de>'),
array('Subject', mb_convert_encoding('㈱山﨑工業', 'ISO-2022-JP-MS', 'UTF-8'), 'ISO-2022-JP'),
);

$i = 1;
foreach ($headers as $header) {
    $charset = isset($header[2]) ? $header[2] : 'UTF-8';
    $hdr = $mime->encodeHeader($header[0], $header[1], $charset, 'base64');
    printf("[%02d] %s: %s\n", $i, $header[0], $hdr);
    $hdr = $mime->encodeHeader($header[0], $header[1], $charset, 'quoted-printable');
    printf("[%02d] %s: %s\n", $i, $header[0], $hdr);
    $i++;
}
?>
--EXPECT--
[01] From: <adresse@adresse.de>
[01] From: <adresse@adresse.de>
[02] From: adresse@adresse.de
[02] From: adresse@adresse.de
[03] From: Frank Do <adresse@adresse.de>
[03] From: Frank Do <adresse@adresse.de>
[04] To: Frank Do <adresse@adresse.de>, James Clark <james@domain.com>
[04] To: Frank Do <adresse@adresse.de>, James Clark <james@domain.com>
[05] From: "Frank Do" <adresse@adresse.de>
[05] From: "Frank Do" <adresse@adresse.de>
[06] Cc: "Frank Do" <adresse@adresse.de>, "James Clark" <james@domain.com>
[06] Cc: "Frank Do" <adresse@adresse.de>, "James Clark" <james@domain.com>
[07] Cc: <adresse@adresse.de>, =?UTF-8?B?S3XFm21pZGVyc2tpIEphbiBLcnp5c3p0b2Yg?=
 =?UTF-8?B?SmFudXN6IETFgnVnYSBuYXp3YQ==?= <cris@domain.com>
[07] Cc: <adresse@adresse.de>, =?UTF-8?Q?Ku=C5=9Bmiderski_Jan_Krzysztof_Janusz?=
 =?UTF-8?Q?_D=C5=82uga_nazwa?= <cris@domain.com>
[08] From: "adresse@adresse.de" <addresse@adresse>
[08] From: "adresse@adresse.de" <addresse@adresse>
[09] From: "adresse@adresse.de" <addresse@adresse>
[09] From: "adresse@adresse.de" <addresse@adresse>
[10] From: =?UTF-8?B?R2VybWFuIFVtbGF1dHMgw7bDpMO8?= <adresse@adresse.de>
[10] From: =?UTF-8?Q?German_Umlauts_=C3=B6=C3=A4=C3=BC?= <adresse@adresse.de>
[11] Subject: =?UTF-8?B?R2VybWFuIFVtbGF1dHMgw7bDpMO8IDxhZHJlc3NlQGFkcmVzc2Uu?=
 =?UTF-8?B?ZGU+?=
[11] Subject: =?UTF-8?Q?German_Umlauts_=C3=B6=C3=A4=C3=BC_=3Cadresse=40adresse?=
 =?UTF-8?Q?=2Ede=3E?=
[12] Subject: Short ASCII subject
[12] Subject: Short ASCII subject
[13] Subject: Long ASCII subject - multiline space separated words - too long for
 one line
[13] Subject: Long ASCII subject - multiline space separated words - too long for
 one line
[14] Subject: =?UTF-8?B?U2hvcnQgVW5pY29kZSDFvCBzdWJqZWN0?=
[14] Subject: =?UTF-8?Q?Short_Unicode_=C5=BC_subject?=
[15] Subject: =?UTF-8?B?TG9uZyBVbmljb2RlIHN1YmplY3QgLSB6YcW8w7PFgsSHIGfEmcWb?=
 =?UTF-8?B?bMSFIGphxbrFhCAtIHRvbyBsb25nIGZvciBvbmUgbGluZQ==?=
[15] Subject: =?UTF-8?Q?Long_Unicode_subject_-_za=C5=BC=C3=B3=C5=82=C4=87_g?=
 =?UTF-8?Q?=C4=99=C5=9Bl=C4=85_ja=C5=BA=C5=84_-_too_long_for_one_line?=
[16] References: <hglvja$jg7$1@nemesis.news.neostrada.pl>
 <4b2e87ac$1@news.home.net.pl> <hgm5b1$3a7$1@atlantis.news.neostrada.pl>
[16] References: <hglvja$jg7$1@nemesis.news.neostrada.pl>
 <4b2e87ac$1@news.home.net.pl> <hgm5b1$3a7$1@atlantis.news.neostrada.pl>
[17] To: "Frank Do" <adresse@adresse.de>, "James Clark" <james@domain.com>
[17] To: "Frank Do" <adresse@adresse.de>, "James Clark" <james@domain.com>
[18] To: "Frank \" \\Do" <adresse@adresse.de>
[18] To: "Frank \" \\Do" <adresse@adresse.de>
[19] To: "Frank \" \\Do" <adresse@adresse.de>
[19] To: "Frank \" \\Do" <adresse@adresse.de>
[20] Subject: A REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY
 REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY
 REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY
 REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY /REALLY/ LONG test
[20] Subject: A REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY
 REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY
 REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY
 REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY /REALLY/ LONG test
[21] Subject: =?UTF-8?B?VEVTVCBTw7xwZXIgZ3LDtnNlIHRvbGxlIGdyw7zDn2Ugdm9uIG1p?=
 =?UTF-8?B?ciBTw7xwZXIgZ3LDtnNlIHRvbGxlIGdyw7zDn2Ugdm9uIG1pciBTw7xwZXIg?=
 =?UTF-8?B?Z3LDtnNlIHRvbGxlIGdyw7zDn2Ugdm9uIG1pciBTw7xwZXIgZ3LDtnNlIHRv?=
 =?UTF-8?B?bGxlIGdyw7zDn2Ugdm9uIG1pciBTw7xwZXIgZ3LDtnNlIHRvbGxlIGdyw7w=?=
 =?UTF-8?B?w59lIHZvbiBtaXIgU8O8cGVyIGdyw7ZzZSB0b2xsZSBncsO8w59lIHZvbiBt?=
 =?UTF-8?B?aXIgU8O8cGVyIGdyw7ZzZSB0b2xsZSBncsO8w59lIHZvbiBtaXIgU8O8cGVy?=
 =?UTF-8?B?IGdyw7ZzZSB0b2xsZSBncsO8w59lIHZvbiBtaXIgU8O8cGVyIGdyw7ZzZSB0?=
 =?UTF-8?B?b2xsZSBncsO8w59lIHZvbiBtaXIhISE/?=
[21] Subject: =?UTF-8?Q?TEST_S=C3=BCper_gr=C3=B6se_tolle_gr=C3=BC=C3=9Fe_von_m?=
 =?UTF-8?Q?ir_S=C3=BCper_gr=C3=B6se_tolle_gr=C3=BC=C3=9Fe_von_mir_S=C3=BCp?=
 =?UTF-8?Q?er_gr=C3=B6se_tolle_gr=C3=BC=C3=9Fe_von_mir_S=C3=BCper_gr=C3=B6?=
 =?UTF-8?Q?se_tolle_gr=C3=BC=C3=9Fe_von_mir_S=C3=BCper_gr=C3=B6se_tolle_gr?=
 =?UTF-8?Q?=C3=BC=C3=9Fe_von_mir_S=C3=BCper_gr=C3=B6se_tolle_gr=C3=BC?=
 =?UTF-8?Q?=C3=9Fe_von_mir_S=C3=BCper_gr=C3=B6se_tolle_gr=C3=BC=C3=9Fe_von?=
 =?UTF-8?Q?_mir_S=C3=BCper_gr=C3=B6se_tolle_gr=C3=BC=C3=9Fe_von_mir_S?=
 =?UTF-8?Q?=C3=BCper_gr=C3=B6se_tolle_gr=C3=BC=C3=9Fe_von_mir!!!=3F?=
[22] Subject: =?UTF-8?B?VXBkYXRlOiBNaWNyb3NvZnQgV2luZG93cy1Ub29sIHp1bSBFbnRm?=
 =?UTF-8?B?ZXJuZW4gYsO2c2FydGlnZXIgU29mdHdhcmUgMy42?=
[22] Subject: =?UTF-8?Q?Update=3A_Microsoft_Windows-Tool_zum_Entfernen_b=C3=B6?=
 =?UTF-8?Q?sartiger_Software_3=2E6?=
[23] From: =?UTF-8?B?dGVzdEBuw6BtZQ==?= <user@domain.com>
[23] From: =?UTF-8?Q?test=40n=C3=A0me?= <user@domain.com>
[24] From: Test <"test test"@domain.com>
[24] From: Test <"test test"@domain.com>
[25] From: "test test"@domain.com
[25] From: "test test"@domain.com
[26] From: <"test test"@domain.com>
[26] From: <"test test"@domain.com>
[27] From: Doe <test@domain.com>
[27] From: Doe <test@domain.com>
[28] From: "John Doe" <test@domain.com>
[28] From: "John Doe" <test@domain.com>
[29] Mail-Reply-To: "adresse@adresse.de" <addresse@adresse>
[29] Mail-Reply-To: "adresse@adresse.de" <addresse@adresse>
[30] Mail-Reply-To: =?UTF-8?B?w7bDpMO8?= <adresse@adresse.de>
[30] Mail-Reply-To: =?UTF-8?Q?=C3=B6=C3=A4=C3=BC?= <adresse@adresse.de>
[31] Subject: =?ISO-2022-JP?B?GyRCLWo7M3l1OSk2SBsoQg==?=
[31] Subject: =?ISO-2022-JP?Q?=24B-j=28B=24B=3B3=28B=24Byu=28B?=
 =?ISO-2022-JP?Q?=24B9=29=28B=24B6H=28B?=
PK��Z���|JJ8test/Mail_Mime/tests/sleep_wakeup_EOL-bug3488-part2.phptnu�[���--TEST--
Bug #3488   Sleep/Wakeup EOL Consistency - Part 2
--SKIPIF--
if (!is_readable('sleep_wakeup_data')) {
    echo "skip No data. Part 1 must run first.\n";
}
--FILE--
<?php
require_once('Mail/mime.php');
$filename = 'sleep_wakeup_data';
$fp = fopen($filename, 'r');
$smm = fread($fp, filesize($filename));
fclose($fp);
@unlink($filename);

$mmData = unserialize($smm);
$mmData['mm']->get();
$x = $mmData['mm']->headers();

list($h1) = explode("\n", $mmData['header']);
list($h2) = explode("\n", $x['Content-Type']);

echo ($h1 == $h2) ? "Match" : "No Match";

?>
--EXPECT--
Match
PK��Z�{�	�	*test/File_MARC/tests/marc_xml_rsinger.phptnu�[���--TEST--
marc_xml_rsinger2: iterate and pretty print a non-compliant MARC record (uppercase subfield codes)
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';
$marc_file = new File_MARCXML($dir . '/' . 'bad_example.xml');

while ($marc_record = $marc_file->next()) {
  print $marc_record;
  print "\n";
}
?>
--EXPECT--
LDR 01850    a2200517   4500
001     0000000044
003     EMILDA
008     980120s1998    fi     j      000 0 swe
005     20050204111518.0
020    _a9515008808
       _cFIM 72:00
035    _99515008808
040    _aNB
042    _9NB
       _9SEE
084    _aHcd,u
       _2kssb/6
084    _5NB
       _auHc
       _2kssb
084    _5SEE
       _aHcf
       _2kssb/6
084    _5Q
       _aHcd,uf
       _2kssb/6
100 1  _aJansson, Tove,
       _d1914-2001
245 0  _aDet osynliga barnet och andra bert̃telser /
       _cTove Jansson
250    _a7. uppl.
260    _aHelsingfors :
       _bSchildt,
       _c1998 ;
       _e(Falun :
       _fScandbook)
440  0 _aMumin-biblioteket,
       _x99-0698931-9
500    _aOriginaluppl. 1962
599    _aLi: S
740 4  _aDet osynliga barnet
775 1  _z951-50-0385-7
       _w9515003857
       _907
841    _5Li
       _axa
       _b0201080u    0   4000uu   |000000
       _e1
841    _5SEE
       _axa
       _b0201080u    0   4000uu   |000000
       _e1
841    _5L
       _axa
       _b0201080u    0   4000uu   |000000
       _e1
841    _5NB
       _axa
       _b0201080u    0   4000uu   |000000
       _e1
841    _5Q
       _axa
       _b0201080u    0   4000uu   |000000
       _e1
841    _5S
       _axa
       _b0201080u    0   4000uu   |000000
       _e1
852    _5NB
       _bNB
       _cNB98:12
       _hplikt
       _jR, 980520
852    _5Li
       _bLi
       _cCNB
       _hh,u
852    _5SEE
       _bSEE
852    _5Q
       _bQ
       _j98947
852    _5L
       _bL
       _c0100
       _h98/
       _j3043 H
852    _5S
       _bS
       _hSv97
       _j7235
900 1s _aYanson, Tobe,
       _d1914-2001
       _uJansson, Tove,
       _d1914-2001
900 1s _aJanssonov,̀ Tove,
       _d1914-2001
       _uJansson, Tove,
       _d1914-2001
900 1s _aJansone, Tuve,
       _d1914-2001
       _uJansson, Tove,
       _d1914-2001
900 1s _aJanson, Tuve,
       _d1914-2001
       _uJansson, Tove,
       _d1914-2001
900 1s _aJansson, Tuve,
       _d1914-2001
       _uJansson, Tove,
       _d1914-2001
900 1s _aJanssonova, Tove,
       _d1914-2001
       _uJansson, Tove,
       _d1914-2001
976  2 _aHcd,u
       _bSkn̲litteratur
PK��Za!���"test/File_MARC/tests/namespace.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<!-- edited with XML Spy v4.3 U (http://www.xmlspy.com) by Morgan Cundiff (Library of Congress) -->
<marc:collection xmlns:marc="http://www.loc.gov/MARC21/slim" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd">
	<marc:record>
		<marc:leader>00925njm  22002777a 4500</marc:leader>
		<marc:controlfield tag="001">5637241</marc:controlfield>
		<marc:controlfield tag="003">DLC</marc:controlfield>
		<marc:controlfield tag="005">19920826084036.0</marc:controlfield>
		<marc:controlfield tag="007">sdubumennmplu</marc:controlfield>
		<marc:controlfield tag="008">910926s1957    nyuuun              eng  </marc:controlfield>
		<marc:datafield tag="010" ind1=" " ind2=" ">
			<marc:subfield code="a">   91758335 </marc:subfield>
		</marc:datafield>
		<marc:datafield tag="028" ind1="0" ind2="0">
			<marc:subfield code="a">1259</marc:subfield>
			<marc:subfield code="b">Atlantic</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="040" ind1=" " ind2=" ">
			<marc:subfield code="a">DLC</marc:subfield>
			<marc:subfield code="c">DLC</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="050" ind1="0" ind2="0">
			<marc:subfield code="a">Atlantic 1259</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="245" ind1="0" ind2="4">
			<marc:subfield code="a">The Great Ray Charles</marc:subfield>
			<marc:subfield code="h">[sound recording].</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="260" ind1=" " ind2=" ">
			<marc:subfield code="a">New York, N.Y. :</marc:subfield>
			<marc:subfield code="b">Atlantic,</marc:subfield>
			<marc:subfield code="c">[1957?]</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="300" ind1=" " ind2=" ">
			<marc:subfield code="a">1 sound disc :</marc:subfield>
			<marc:subfield code="b">analog, 33 1/3 rpm ;</marc:subfield>
			<marc:subfield code="c">12 in.</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="511" ind1="0" ind2=" ">
			<marc:subfield code="a">Ray Charles, piano &amp; celeste.</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="505" ind1="0" ind2=" ">
			<marc:subfield code="a">The Ray -- My melancholy baby -- Black coffee -- There's no you -- Doodlin' -- Sweet sixteen bars -- I surrender dear -- Undecided.</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="500" ind1=" " ind2=" ">
			<marc:subfield code="a">Brief record.</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="650" ind1=" " ind2="0">
			<marc:subfield code="a">Jazz</marc:subfield>
			<marc:subfield code="y">1951-1960.</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="650" ind1=" " ind2="0">
			<marc:subfield code="a">Piano with jazz ensemble.</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="700" ind1="1" ind2=" ">
			<marc:subfield code="a">Charles, Ray,</marc:subfield>
			<marc:subfield code="d">1930-</marc:subfield>
			<marc:subfield code="4">prf</marc:subfield>
		</marc:datafield>
	</marc:record>
	<marc:record>
		<marc:leader>01832cmma 2200349 a 4500</marc:leader>
		<marc:controlfield tag="001">12149120</marc:controlfield>
		<marc:controlfield tag="005">20001005175443.0</marc:controlfield>
		<marc:controlfield tag="007">cr |||</marc:controlfield>
		<marc:controlfield tag="008">000407m19949999dcu    g   m        eng d</marc:controlfield>
		<marc:datafield tag="906" ind1=" " ind2=" ">
			<marc:subfield code="a">0</marc:subfield>
			<marc:subfield code="b">ibc</marc:subfield>
			<marc:subfield code="c">copycat</marc:subfield>
			<marc:subfield code="d">1</marc:subfield>
			<marc:subfield code="e">ncip</marc:subfield>
			<marc:subfield code="f">20</marc:subfield>
			<marc:subfield code="g">y-gencompf</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="925" ind1="0" ind2=" ">
			<marc:subfield code="a">undetermined</marc:subfield>
			<marc:subfield code="x">web preservation project (wpp)</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="955" ind1=" " ind2=" ">
			<marc:subfield code="a">vb07 (stars done) 08-19-00 to HLCD lk00; AA3s lk29 received for subject Aug 25, 2000; to DEWEY 08-25-00; aa11 08-28-00</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="010" ind1=" " ind2=" ">
			<marc:subfield code="a">   00530046 </marc:subfield>
		</marc:datafield>
		<marc:datafield tag="035" ind1=" " ind2=" ">
			<marc:subfield code="a">(OCoLC)ocm44279786</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="040" ind1=" " ind2=" ">
			<marc:subfield code="a">IEU</marc:subfield>
			<marc:subfield code="c">IEU</marc:subfield>
			<marc:subfield code="d">N@F</marc:subfield>
			<marc:subfield code="d">DLC</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="042" ind1=" " ind2=" ">
			<marc:subfield code="a">lccopycat</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="043" ind1=" " ind2=" ">
			<marc:subfield code="a">n-us-dc</marc:subfield>
			<marc:subfield code="a">n-us---</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="050" ind1="0" ind2="0">
			<marc:subfield code="a">F204.W5</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="082" ind1="1" ind2="0">
			<marc:subfield code="a">975.3</marc:subfield>
			<marc:subfield code="2">13</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="245" ind1="0" ind2="4">
			<marc:subfield code="a">The White House</marc:subfield>
			<marc:subfield code="h">[computer file].</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="256" ind1=" " ind2=" ">
			<marc:subfield code="a">Computer data.</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="260" ind1=" " ind2=" ">
			<marc:subfield code="a">Washington, D.C. :</marc:subfield>
			<marc:subfield code="b">White House Web Team,</marc:subfield>
			<marc:subfield code="c">1994-</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="538" ind1=" " ind2=" ">
			<marc:subfield code="a">Mode of access: Internet.</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="500" ind1=" " ind2=" ">
			<marc:subfield code="a">Title from home page as viewed on Aug. 19, 2000.</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="520" ind1="8" ind2=" ">
			<marc:subfield code="a">Features the White House. Highlights the Executive Office of the President, which includes senior policy advisors and offices responsible for the President's correspondence and communications, the Office of the Vice President, and the Office of the First Lady. Posts contact information via mailing address, telephone and fax numbers, and e-mail. Contains the Interactive Citizens' Handbook with information on health, travel and tourism, education and training, and housing. Provides a tour and the history of the White House. Links to White House for Kids.</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="610" ind1="2" ind2="0">
			<marc:subfield code="a">White House (Washington, D.C.)</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="610" ind1="1" ind2="0">
			<marc:subfield code="a">United States.</marc:subfield>
			<marc:subfield code="b">Executive Office of the President.</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="610" ind1="1" ind2="0">
			<marc:subfield code="a">United States.</marc:subfield>
			<marc:subfield code="b">Office of the Vice President.</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="610" ind1="1" ind2="0">
			<marc:subfield code="a">United States.</marc:subfield>
			<marc:subfield code="b">Office of the First Lady.</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="710" ind1="2" ind2=" ">
			<marc:subfield code="a">White House Web Team.</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="856" ind1="4" ind2="0">
			<marc:subfield code="u">http://www.whitehouse.gov</marc:subfield>
		</marc:datafield>
		<marc:datafield tag="856" ind1="4" ind2="0">
			<marc:subfield code="u">http://lcweb.loc.gov/staff/wpp/whitehouse.html</marc:subfield>
			<marc:subfield code="z">Web site archive</marc:subfield>
		</marc:datafield>
	</marc:record>
</marc:collection>PK��Z44�-��(test/File_MARC/tests/marc_field_003.phptnu�[���--TEST--
marc_field_003: Add subfields to an existing field
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';

// create some subfields
$subfields[] = new File_MARC_Subfield('a', 'nothing');
$subfields[] = new File_MARC_Subfield('z', 'everything');

// create a field
$field = new File_MARC_Data_Field('100', $subfields, '0');

// create some new subfields
$subfield1 = new File_MARC_Subfield('g', 'a little');
$subfield2 = new File_MARC_Subfield('k', 'a bit more');
$subfield3 = new File_MARC_Subfield('t', 'a lot');
$subfield4 = new File_MARC_Subfield('0', 'first post');

// append a new subfield to the existing set of subfields
// expected order: a-z-g
$field->appendSubfield($subfield1);

// insert a new subfield after the first subfield with code 'z'
// expected order: a-z-k-g
$sf = $field->getSubfields('z');
// we might get an array back; in this case, we want the first subfield
if (is_array($sf)) {
  $field->insertSubfield($subfield2, $sf[0]);
}
else {
  $field->insertSubfield($subfield2, $sf);
}

// insert a new subfield prior to the first subfield with code 'z'
// expected order: a-t-z-k-g
$sf = $field->getSubfields('z');
// we might get an array back; in this case, we want the first subfield
if (is_array($sf)) {
  $field->insertSubfield($subfield3, $sf[0], true);
}
else {
  $field->insertSubfield($subfield3, $sf, true);
}

// insert a new subfield at the very start of the field
$field->prependSubfield($subfield4);

// let's see the results
print $field;
print "\n";

?>
--EXPECT--
100 0  _0first post
       _anothing
       _ta lot
       _zeverything
       _ka bit more
       _ga little
PK��Z�c����(test/File_MARC/tests/marc_xml_16642.phptnu�[���--TEST--
marc_xml_16642: Fix bug 16642: ensure tag and subfield values are returned as strings
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';
// Retrieve a set of MARC records from a file
$marc_file = new File_MARCXML($dir . '/' . 'onerecord.xml');
// Iterate through the retrieved records
while ($record = $marc_file->next()) {
   foreach ($record->getFields() as $tag => $subfields) {
       // Skip everything except for 650 fields
       if ($tag == '650') {
           print "Subject:";
           foreach ($subfields->getSubfields() as $code => $value) {
               print " $value";
           }
           print "\n";
       }
   }
}
?>
--EXPECT--
Subject: [a]: Arithmetic [x]: Juvenile poetry.
Subject: [a]: Children's poetry, American.
Subject: [a]: Arithmetic [x]: Poetry.
Subject: [a]: American poetry.
Subject: [a]: Visual perception.
PK��Z�è{{"test/File_MARC/tests/marc_020.phptnu�[���--TEST--
marc_020: Test MARC binary output
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';

// Get ourselves a MARC record
$marc_file = new File_MARC($dir . '/' . 'example.mrc');
$marc_record = $marc_file->next();

// create some subfields
$subfields[] = new File_MARC_Subfield('a', 'nothing');
$subfields[] = new File_MARC_Subfield('z', 'everything');

// create a data field
$data_field = new File_MARC_Data_Field('100', $subfields, '0');

// append the data field
$marc_record->appendField($data_field);

// create a control field
$ctrl_field = new File_MARC_Control_Field('001', '01234567890');

// prepend the control field
$marc_record->prependField($ctrl_field);

// reproduce test case reported by Mark Jordan
$subfields_966_2[] = new File_MARC_Subfield('l', 'web');
$subfields_966_2[] = new File_MARC_Subfield('r', '0');
$subfields_966_2[] = new File_MARC_Subfield('s', 'b');
$subfields_966_2[] = new File_MARC_Subfield('i', '49');
$subfields_966_2[] = new File_MARC_Subfield('c', '1');
$field_966_2 = new File_MARC_Data_Field('966', $subfields_966_2, null, null);
$marc_record->appendField($field_966_2);

// let's see the results
print convert_uuencode($marc_record->toRaw());

?>
--EXPECT--
M,#$Y-#,@("`@(#(R,#`U-3,@("`T-3`P,#`Q,#`Q,C`P,#`P,#`Q,#`Q,3`P
M,#$R,#`S,#`P-S`P,#(S,#`X,#`S.3`P,#,P,#(P,#`R-C`P,#8Y,#,U,#`Q
M-3`P,#DU,#0P,#`P-S`P,3$P,#0R,#`Q,C`P,3$W,#@T,#`Q.#`P,3(Y,#@T
M,#`Q.#`P,30W,#@T,#`R,3`P,38U,#@T,#`R,C`P,3@V,3`P,#`S,#`P,C`X
M,C0U,#`V,C`P,C,X,C4P,#`Q,S`P,S`P,C8P,#`U.#`P,S$S,S`P,#`S,S`P
M,S<Q-#0P,#`S-S`P-#`T-3`P,#`R,S`P-#0Q-3DY,#`Q,#`P-#8T-S0P,#`R
M-#`P-#<T-S<U,#`S-#`P-#DX.#0Q,#`T.#`P-3,R.#0Q,#`T.3`P-3@P.#0Q
M,#`T-S`P-C(Y.#0Q,#`T.#`P-C<V.#0Q,#`T-S`P-S(T.#0Q,#`T-S`P-S<Q
M.#4R,#`S.#`P.#$X.#4R,#`R,3`P.#4V.#4R,#`Q,S`P.#<W.#4R,#`Q-C`P
M.#DP.#4R,#`R.#`P.3`V.#4R,#`R,3`P.3,T.3`P,#`U-C`P.34U.3`P,#`V
M,#`Q,#$Q.3`P,#`U-S`Q,#<Q.3`P,#`U-C`Q,3(X.3`P,#`U-S`Q,3@T.3`P
M,#`V,#`Q,C0Q.3<V,#`R-C`Q,S`Q,#`U,#`Q-S`Q,S(W,3`P,#`R-#`Q,S0T
M.38V,#`R,3`Q,S8X'C`Q,C,T-38W.#DP'C`P,#`P,#`P-#0>14U)3$1!'CDX
M,#$R,',Q.3DX("`@(&9I("`@("!J("`@("`@,#`P(#`@<W=E'B`@'V$Y-3$U
M,#`X.#`X'V-&24T@-S(Z,#`>("`?.3DU,34P,#@X,#@>("`?84Y"'B`@'SE.
M0A\Y4T5%'B`@'V%(8V0L=1\R:W-S8B\V'B`@'S5.0A]A=4AC'S)K<W-B'B`@
M'S53144?84AC9A\R:W-S8B\V'B`@'S51'V%(8V0L=68?,FMS<V(O-AXQ(!]A
M2F%N<W-O;BP@5&]V92P?9#$Y,30M,C`P,1XP-!]A1&5T(&]S>6YL:6=A(&)A
M<FYE="!O8V@@86YD<F$@8F5RY'1T96QS97(@+Q]C5&]V92!*86YS<V]N'B`@
M'V$W+B!U<'!L+AX@(!]A2&5L<VEN9V9O<G,@.A]B4V-H:6QD="P?8S$Y.3@@
M.Q]E*$9A;'5N(#H?9E-C86YD8F]O:RD>("`?83$V-BP@6S1=(',N(#H?8FEL
M;"X@.Q]C,C$@8VT>(#`?84UU;6EN+6)I8FQI;W1E:V5T+!]X.3DM,#8Y.#DS
M,2TY'B`@'V%/<FEG:6YA;'5P<&PN(#$Y-C(>("`?84QI.B!3'C0@'V%$970@
M;W-Y;FQI9V$@8F%R;F5T'C$@'WHY-3$M-3`M,#,X-2TW'W<Y-3$U,#`S.#4W
M'SDP-QX@(!\U3&D?87AA'V(P,C`Q,#@P=2`@("`P("`@-#`P,'5U("`@?#`P
M,#`P,!]E,1X@(!\U4T5%'V%X81]B,#(P,3`X,'4@("`@,"`@(#0P,#!U=2`@
M('PP,#`P,#`?93$>("`?-4P?87AA'V(P,C`Q,#@P=2`@("`P("`@-#`P,'5U
M("`@?#`P,#`P,!]E,1X@(!\U3D(?87AA'V(P,C`Q,#@P=2`@("`P("`@-#`P
M,'5U("`@?#`P,#`P,!]E,1X@(!\U41]A>&$?8C`R,#$P.#!U("`@(#`@("`T
M,#`P=74@("!\,#`P,#`P'V4Q'B`@'S53'V%X81]B,#(P,3`X,'4@("`@,"`@
M(#0P,#!U=2`@('PP,#`P,#`?93$>("`?-4Y"'V).0A]C3D(Y.#HQ,A]H<&QI
M:W0?:E(L(#DX,#4R,!X@(!\U3&D?8DQI'V-#3D(?:&@L=1X@(!\U4T5%'V)3
M144>("`?-5$?8E$?:CDX.30W'B`@'S5,'V),'V,P,3`P'V@Y."\?:C,P-#,@
M2!X@(!\U4Q]B4Q]H4W8Y-Q]J-S(S-1XQ<Q]A66%N<V]N+"!4;V)E+!]D,3DQ
M-"TR,#`Q'W5*86YS<V]N+"!4;W9E+!]D,3DQ-"TR,#`Q'C%S'V%*86YS<V]N
M;W;A+"!4;W9E+!]D,3DQ-"TR,#`Q'W5*86YS<V]N+"!4;W9E+!]D,3DQ-"TR
M,#`Q'C%S'V%*86YS;VYE+"!4=79E+!]D,3DQ-"TR,#`Q'W5*86YS<V]N+"!4
M;W9E+!]D,3DQ-"TR,#`Q'C%S'V%*86YS;VXL(%1U=F4L'V0Q.3$T+3(P,#$?
M=4IA;G-S;VXL(%1O=F4L'V0Q.3$T+3(P,#$>,7,?84IA;G-S;VXL(%1U=F4L
M'V0Q.3$T+3(P,#$?=4IA;G-S;VXL(%1O=F4L'V0Q.3$T+3(P,#$>,7,?84IA
M;G-S;VYO=F$L(%1O=F4L'V0Q.3$T+3(P,#$?=4IA;G-S;VXL(%1O=F4L'V0Q
M.3$T+3(P,#$>(#(?84AC9"QU'V)3:_9N;&ET=&5R871U<AXR,#`U,#(P-#$Q
M,34Q."XP'C`@'V%N;W1H:6YG'WIE=F5R>71H:6YG'B`@'VQW96(?<C`?<V(?
(:30Y'V,Q'AT`
`
PK��ZҔ��	�	$test/File_MARC/tests/marc_16783.phptnu�[���--TEST--
marc_16783: iterate and pretty print a non-compliant MARC record (tag = '30-')
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';
$marc_file = new File_MARC($dir . '/' . 'bad_example.mrc');

while ($marc_record = $marc_file->next()) {
  print $marc_record;
  print "\n";
}
?>
--EXPECT--
LDR 01853    a2200517   4500
001     0000000044
003     EMILDA
008     980120s1998    fi     j      000 0 swe
020    _a9515008808
       _cFIM 72:00
035    _99515008808
040    _aNB
042    _9NB
       _9SEE
084    _aHcd,u
       _2kssb/6
084    _5NB
       _auHc
       _2kssb
084    _5SEE
       _aHcf
       _2kssb/6
084    _5Q
       _aHcd,uf
       _2kssb/6
100 1  _aJansson, Tove,
       _d1914-2001
245 04 _aDet osynliga barnet och andra bert̃telser /
       _cTove Jansson
250    _a7. uppl.
260    _aHelsingfors :
       _bSchildt,
       _c1998 ;
       _e(Falun :
       _fScandbook)
440  0 _aMumin-biblioteket,
       _x99-0698931-9
500    _aOriginaluppl. 1962
599    _aLi: S
740 4  _aDet osynliga barnet
775 1  _z951-50-0385-7
       _w9515003857
       _907
841    _5Li
       _axa
       _b0201080u    0   4000uu   |000000
       _e1
841    _5SEE
       _axa
       _b0201080u    0   4000uu   |000000
       _e1
841    _5L
       _axa
       _b0201080u    0   4000uu   |000000
       _e1
841    _5NB
       _axa
       _b0201080u    0   4000uu   |000000
       _e1
841    _5Q
       _axa
       _b0201080u    0   4000uu   |000000
       _e1
841    _5S
       _axa
       _b0201080u    0   4000uu   |000000
       _e1
852    _5NB
       _bNB
       _cNB98:12
       _hplikt
       _jR, 980520
852    _5Li
       _bLi
       _cCNB
       _hh,u
852    _5SEE
       _bSEE
852    _5Q
       _bQ
       _j98947
852    _5L
       _bL
       _c0100
       _h98/
       _j3043 H
852    _5S
       _bS
       _hSv97
       _j7235
900 1s _aYanson, Tobe,
       _d1914-2001
       _uJansson, Tove,
       _d1914-2001
900 1s _aJanssonov,̀ Tove,
       _d1914-2001
       _uJansson, Tove,
       _d1914-2001
900 1s _aJansone, Tuve,
       _d1914-2001
       _uJansson, Tove,
       _d1914-2001
900 1s _aJanson, Tuve,
       _d1914-2001
       _uJansson, Tove,
       _d1914-2001
900 1s _aJansson, Tuve,
       _d1914-2001
       _uJansson, Tove,
       _d1914-2001
900 1s _aJanssonova, Tove,
       _d1914-2001
       _uJansson, Tove,
       _d1914-2001
976  2 _aHcd,u
       _bSkn̲litteratur
005     20050204111518.0
PK��ZF�-//(test/File_MARC/tests/marc_field_002.phptnu�[���--TEST--
marc_field_002: Create fields with invalid indicators
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';

// create some subfields
$subfields[] = new File_MARC_Subfield('a', 'nothing');
$subfields[] = new File_MARC_Subfield('z', 'everything');

// test constructor
try {
    $field = new File_MARC_Data_Field('100', $subfields, '$@');
}
catch (Exception $e) {
    print "Error: {$e->getMessage()}\n";
}
--EXPECT--
Error: Illegal indicator "$@" in field "100" forced to blank
PK��Z��	\��'test/File_MARC/tests/marc_lint_001.phptnu�[���--TEST--
marc_lint_001: Full test of Lint suite
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
<?php include('tests/skipif_noispn.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';
$marc_lint = new File_MARC_Lint();

print "Test records in camel.mrc\n";
$marc_file = new File_MARC($dir . '/' . 'camel.mrc');
while ($marc_record = $marc_file->next()) {
  $warnings = $marc_lint->checkRecord($marc_record);
  foreach ($warnings as $warning) {
    print $warning . "\n";
  }
}

print "\nTest from a constructed record\n";
$rec = new File_MARC_Record();
$rec->setLeader("00000nam  22002538a 4500");
$rec->appendField(
    new File_MARC_Data_Field(
        '041',
        array(
            new File_MARC_Subfield('a', 'end'),
            new File_MARC_Subfield('a', 'fren')
        ),
        "0", ""
    )
);
$rec->appendField(
    new File_MARC_Data_Field(
        '043',
        array(
            new File_MARC_Subfield('a', 'n-us-pn')
        ),
        "", ""
    )
);
$rec->appendField(
    new File_MARC_Data_Field(
        '082',
        array(
            new File_MARC_Subfield('a', '005.13/3'),
            // typo 'R' for 'W' and missing 'b' subfield
            new File_MARC_Subfield('R', 'all'),
            new File_MARC_Subfield('2', '21')
        ),
        "0", "4"
    )
);
$rec->appendField(
    new File_MARC_Data_Field(
        '082',
        array(
            new File_MARC_Subfield('a', '005.13'),
            new File_MARC_Subfield('b', 'Wall'),
            new File_MARC_Subfield('2', '14')
        ),
        "1", "4"
    )
);
$rec->appendField(
    new File_MARC_Data_Field(
        '100',
        array(
            new File_MARC_Subfield('a', 'Wall, Larry')
        ),
        "1", "4"
    )
);
$rec->appendField(
    new File_MARC_Data_Field(
        '110',
        array(
            new File_MARC_Subfield('a', "O'Reilly & Associates.")
        ),
        "1", ""
    )
);
$rec->appendField(
    new File_MARC_Data_Field(
        '245',
        array(
            new File_MARC_Subfield('a', 'Programming Perl / '),
            new File_MARC_Subfield('a', 'Big Book of Perl /'),
            new File_MARC_Subfield('c', 'Larry Wall, Tom Christiansen & Jon Orwant.')
        ),
        "9", "0"
    )
);
$rec->appendField(
    new File_MARC_Data_Field(
        '250',
        array(
            new File_MARC_Subfield('a', '3rd ed.')
        ),
        "", ""
    )
);
$rec->appendField(
    new File_MARC_Data_Field(
        '250',
        array(
            new File_MARC_Subfield('a', '3rd ed.')
        ),
        "", ""
    )
);
$rec->appendField(
    new File_MARC_Data_Field(
        '260',
        array(
            new File_MARC_Subfield('a', 'Cambridge, Mass. : '),
            new File_MARC_Subfield('b', "O'Reilly, "),
            new File_MARC_Subfield('r', '2000.')
        ),
        "", ""
    )
);
$rec->appendField(
    new File_MARC_Data_Field(
        '590',
        array(
            new File_MARC_Subfield('a', 'Personally signed by Larry.')
        ),
        "4", ""
    )
);
$rec->appendField(
    new File_MARC_Data_Field(
        '650',
        array(
            new File_MARC_Subfield('a', 'Perl (Computer program language)'),
            new File_MARC_Subfield('0', '(DLC)sh 95010633')
        ),
        "", "0"
    )
);
$rec->appendField(
    new File_MARC_Data_Field(
        '856',
        array(
            new File_MARC_Subfield('u', 'http://www.perl.com/')
        ),
        "4", "3"
    )
);
$rec->appendField(
    new File_MARC_Data_Field(
        '886',
        array(
            new File_MARC_Subfield('4', 'Some foreign thing'),
            new File_MARC_Subfield('q', 'Another foreign thing')
        ),
        "0", ""
    )
);
$warnings = $marc_lint->checkRecord($rec);
foreach ($warnings as $warning) {
  print $warning . "\n";
}

?>
--EXPECT--
Test records in camel.mrc
100: Indicator 1 must be 0, 1 or 3 but it's "2"
007: Subfields are not allowed in fields lower than 010

Test from a constructed record
1XX: Only one 1XX tag is allowed, but I found 2 of them.
041: Subfield _a, end (end), is not valid.
041: Subfield _a must be evenly divisible by 3 or exactly three characters if ind2 is not 7, (fren).
043: Subfield _a, n-us-pn, is not valid.
082: Subfield _R is not allowed.
100: Indicator 2 must be blank but it's "4"
245: Indicator 1 must be 0 or 1 but it's "9"
245: Subfield _a is not repeatable.
260: Subfield _r is not allowed.
856: Indicator 2 must be blank, 0, 1, 2 or 8 but it's "3"
PK��ZrP��&test/File_MARC/tests/marc_xml_004.phptnu�[���--TEST--
marc_xml_004: test conversion to XML of subfields that need to be escaped
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';
$marc_file = new File_MARC($dir . '/' . 'xmlescape.mrc');

while ($marc_record = $marc_file->next()) {
  print $marc_record->toXML();
  print "\n";
}
?>
--EXPECT--
<?xml version="1.0" encoding="UTF-8"?>
<collection xmlns="http://www.loc.gov/MARC21/slim">
 <record>
  <leader>00727nam  2200205 a 4500</leader>
  <controlfield tag="001">03-0016458</controlfield>
  <controlfield tag="005">19971103184734.0</controlfield>
  <controlfield tag="008">970701s1997    oru          u000 0 eng u</controlfield>
  <datafield tag="035" ind1=" " ind2=" ">
   <subfield code="a">(Sirsi) a351664</subfield>
  </datafield>
  <datafield tag="050" ind1="0" ind2="0">
   <subfield code="a">ML270.2</subfield>
   <subfield code="b">.A6 1997</subfield>
  </datafield>
  <datafield tag="100" ind1="1" ind2=" ">
   <subfield code="a">Anthony, James R.</subfield>
  </datafield>
  <datafield tag="245" ind1="0" ind2="0">
   <subfield code="a">French baroque music from Beaujoyeulx to Rameau</subfield>
  </datafield>
  <datafield tag="250" ind1=" " ind2=" ">
   <subfield code="a">Rev. and expanded ed.</subfield>
  </datafield>
  <datafield tag="260" ind1=" " ind2=" ">
   <subfield code="a">Portland, OR :</subfield>
   <subfield code="b">Amadeus Press,</subfield>
   <subfield code="c">1997.</subfield>
  </datafield>
  <datafield tag="300" ind1=" " ind2=" ">
   <subfield code="a">586 p. :</subfield>
   <subfield code="b">music</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="0">
   <subfield code="a">Music</subfield>
   <subfield code="&lt;">France</subfield>
   <subfield code="y">16th century</subfield>
   <subfield code="x">History and criticism.</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="0">
   <subfield code="a">Music</subfield>
   <subfield code="z">France</subfield>
   <subfield code="y">17th century</subfield>
   <subfield code="x">History and criticism.</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="0">
   <subfield code="a">Music</subfield>
   <subfield code="z">France</subfield>
   <subfield code="y">18th century</subfield>
   <subfield code="x">History and criticism.</subfield>
  </datafield>
  <datafield tag="949" ind1=" " ind2=" ">
   <subfield code="a">ML 270.2 A6 1997</subfield>
   <subfield code="w">LC</subfield>
   <subfield code="i">30007006841505</subfield>
   <subfield code="r">Y</subfield>
   <subfield code="t">BOOKS</subfield>
   <subfield code="l">HUNT-CIRC</subfield>
   <subfield code="m">HUNTINGTON</subfield>
  </datafield>
  <datafield tag="596" ind1=" " ind2=" ">
   <subfield code="a">1</subfield>
  </datafield>
 </record>
</collection>
PK��Z�0�S��+test/File_MARC/tests/marc_subfield_001.phptnu�[���--TEST--
marc_subfield_001: Exercise basic methods for File_MARC_Subfield class
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';

// test constructor
$subfield = new File_MARC_Subfield('a', 'wasssup');

// test get methods
print "Code: " . $subfield->getCode() . "\n";
print "Data: " . $subfield->getData() . "\n";

// test __toString implementation
print $subfield;
print "\n";

// test raw output implementation
print $subfield->toRaw() . "\n";

// test isEmpty()
if ($subfield->isEmpty()) {
    print "Subfield is empty\n";
}
else {
    print "Subfield is not empty\n";
}
?>
--EXPECT--
Code: a
Data: wasssup
[a]: wasssup
awasssup
Subfield is not empty
PK��Zx;��##"test/File_MARC/tests/marc_006.phptnu�[���--TEST--
marc_006: test read.php
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php

$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';

// Read MARC records from a stream (a file, in this case)
$marc_source = new File_MARC($dir . '/' . 'example.mrc');

// Retrieve the first MARC record from the source
$marc_record = $marc_source->next();

// Retrieve a personal name field from the record
$names = $marc_record->getFields('100');
foreach ($names as $name_field) {
    // Now print the $a subfield
    switch ($name_field->getIndicator(1)) {
    case 0:
	print "Forename: ";
	break;

    case 1:
	print "Surname: ";
	break;

    case 2:
	print "Family name: ";
	break;
    }
    $name = $name_field->getSubfields('a');
    if (count($name) == 1) {
	print $name[0]->getData() . "\n";
    }
    else {
	print "Error -- \$a subfield appears more than once in this field!";
    }
}

// Retrieve all series statement fields
// Series statement fields start with a 4 (PCRE)
$subjects = $marc_record->getFields('^4', true);

// Iterate through all of the returned series statement fields
foreach ($subjects as $field) {
    // print with File_MARC_Field_Data's magic __toString() method
    print $field;
}

?>
--EXPECT--
Surname: Jansson, Tove,
440  0 _aMumin-biblioteket,
       _x99-0698931-9
PK��Z}&�
GG'test/File_MARC/tests/marc_lint_004.phptnu�[���--TEST--
marc_lint_004: Tests check_245() called separately
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
<?php include('tests/skipif_noispn.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';

// Create test harness to allow direct calls to check methods:
class File_MARC_Lint_Test_Harness extends File_MARC_Lint
{
    public function check245($field)
    {
        return parent::check245($field);
    }

    // override warn method to echo instead of store in object:
    protected function warn($msg)
    {
        echo $msg . "\n";
    }
}

$marc_lint = new File_MARC_Lint_Test_Harness();

$testData = array(
    array(245, '0', '0', 'a', 'Subfield a.'),
    array(245, '0', '0', 'b', 'no subfield a.'),
    array(245, '0', '0', 'a', 'No period at end'),
    array(245, '0', '0', 'a', 'Other punctuation not followed by period!'),
    array(245, '0', '0', 'a', 'Other punctuation not followed by period?'),
    array(245, '0', '0', 'a', 'Precedes sub c', 'c', 'not preceded by space-slash.'),
    array(245, '0', '0', 'a', 'Precedes sub c/', 'c', 'not preceded by space-slash.'),
    array(245, '0', '0', 'a', 'Precedes sub c /', 'c', 'initials in sub c B. B.'),
    array(245, '0', '0', 'a', 'Precedes sub c /', 'c', 'initials in sub c B.B. (no warning).'),
    array(245, '0', '0', 'a', 'Precedes sub b', 'b', 'not preceded by proper punctuation.'),
    array(245, '0', '0', 'a', 'Precedes sub b=', 'b', 'not preceded by proper punctuation.'),
    array(245, '0', '0', 'a', 'Precedes sub b:', 'b', 'not preceded by proper punctuation.'),
    array(245, '0', '0', 'a', 'Precedes sub b;', 'b', 'not preceded by proper punctuation.'),
    array(245, '0', '0', 'a', 'Precedes sub b =', 'b', 'preceded by proper punctuation.'),
    array(245, '0', '0', 'a', 'Precedes sub b :', 'b', 'preceded by proper punctuation.'),
    array(245, '0', '0', 'a', 'Precedes sub b ;', 'b', 'preceded by proper punctuation.'),
    array(245, '0', '0', 'a', 'Precedes sub h ', 'h', '[videorecording].'),
    array(245, '0', '0', 'a', 'Precedes sub h-- ', 'h', '[videorecording] :', 'b', 'with elipses dash before h.'),
    array(245, '0', '0', 'a', 'Precedes sub h-- ', 'h', 'videorecording :', 'b', 'without brackets around GMD.'),
    array(245, '0', '0', 'a', 'Precedes sub n.', 'n', 'Number 1.'),
    array(245, '0', '0', 'a', 'Precedes sub n', 'n', 'Number 2.'),
    array(245, '0', '0', 'a', 'Precedes sub n.', 'n', 'Number 3.', 'p', 'Sub n has period not comma.'),
    array(245, '0', '0', 'a', 'Precedes sub n.', 'n', 'Number 3,', 'p', 'Sub n has comma.'),
    array(245, '0', '0', 'a', 'Precedes sub p.', 'p', 'Sub a has period.'),
    array(245, '0', '0', 'a', 'Precedes sub p', 'p', 'Sub a has no period.'),
    array(245, '0', 'a', 'a', 'Invalid filing indicator.'),
    array(245, '0', '0', 'a', 'The article.'),
    array(245, '0', '4', 'a', 'The article.'),
    array(245, '0', '2', 'a', 'An article.'),
    array(245, '0', '0', 'a', "L'article."),
    array(245, '0', '2', 'a', 'A la mode.'),
    array(245, '0', '5', 'a', 'The "quoted article".'),
    array(245, '0', '5', 'a', 'The (parenthetical article).'),
    array(245, '0', '6', 'a', '(The) article in parentheses).'),
    array(245, '0', '9', 'a', "\"(The)\" 'article' in quotes and parentheses)."),
    array(245, '0', '5', 'a', '[The supplied title].')
);

foreach ($testData as $current) {
    $subfields = array();
    for ($i = 3; $i < count($current); $i+=2) {
        $subfields[] = new File_MARC_Subfield($current[$i], $current[$i+1]);
    }

    $field = new File_MARC_Data_Field(
        $current[0], $subfields, $current[1], $current[2]
    );
    $marc_lint->check245($field);
}

?>
--EXPECT--
245: Must have a subfield _a.
245: First subfield must be _a, but it is _b
245: Must end with . (period).
245: MARC21 allows ? or ! as final punctuation but LCRI 1.0C, Nov. 2003 (LCPS 1.7.1 for RDA records), requires period.
245: MARC21 allows ? or ! as final punctuation but LCRI 1.0C, Nov. 2003 (LCPS 1.7.1 for RDA records), requires period.
245: Subfield _c must be preceded by /
245: Subfield _c must be preceded by /
245: Subfield _c initials should not have a space.
245: Subfield _b should be preceded by space-colon, space-semicolon, or space-equals sign.
245: Subfield _b should be preceded by space-colon, space-semicolon, or space-equals sign.
245: Subfield _b should be preceded by space-colon, space-semicolon, or space-equals sign.
245: Subfield _b should be preceded by space-colon, space-semicolon, or space-equals sign.
245: Subfield _h should not be preceded by space.
245: Subfield _h must have matching square brackets, videorecording :.
245: Subfield _n must be preceded by . (period).
245: Subfield _p must be preceded by , (comma) when it follows subfield _n.
245: Subfield _p must be preceded by . (period) when it follows a subfield other than _n.
245: Non-filing indicator is non-numeric
245: First word, the, may be an article, check 2nd indicator (0).
245: First word, an, may be an article, check 2nd indicator (2).
245: First word, l, may be an article, check 2nd indicator (0).
245: First word, a, does not appear to be an article, check 2nd indicator (2).
PK��Z�cܯ�&test/File_MARC/tests/marc_xml_006.phptnu�[���--TEST--
marc_xml_006: test getFields() in XML
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php

$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';

// Read MARC records from a stream (a file, in this case)
$marc_source = new File_MARCXML($dir . '/' . 'sandburg.xml');

// Retrieve the first MARC record from the source
$marc_record = $marc_source->next();

// Retrieve a personal name field from the record
$names = $marc_record->getFields('100');
foreach ($names as $name_field) {
    // Now print the $a subfield
    switch ($name_field->getIndicator(1)) {
    case 0:
	print "Forename: ";
	break;

    case 1:
	print "Surname: ";
	break;

    case 2:
	print "Family name: ";
	break;
    }
    $name = $name_field->getSubfields('a');
    if (count($name) == 1) {
	print $name[0]->getData() . "\n";
    }
    else {
	print "Error -- \$a subfield appears more than once in this field!";
    }
}

// Retrieve all subject and genre fields
// Series statement fields start with a 6 (PCRE)
$subjects = $marc_record->getFields('^6', true);

// Iterate through all of the returned subject fields
foreach ($subjects as $field) {
    // print with File_MARC_Field_Data's magic __toString() method
    print "$field\n";
}

?>
--EXPECT--
Surname: Sandburg, Carl,
650  0 _aArithmetic
       _xJuvenile poetry.
650  0 _aChildren's poetry, American.
650  1 _aArithmetic
       _xPoetry.
650  1 _aAmerican poetry.
650  1 _aVisual perception.
PK��Z���
��(test/File_MARC/tests/marc_field_005.phptnu�[���--TEST--
marc_field_005: Test method getContents
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';

// create some subfields
$subfields[] = new File_MARC_Subfield('a', 'nothing');
$subfields[] = new File_MARC_Subfield('z', 'everything');

// create a field
$field = new File_MARC_Data_Field('100', $subfields, '0');

// create some new subfields
$subfield1 = new File_MARC_Subfield('g', 'a little');

// test the fieldpost corner case by inserting prior to the first subfield
$sf = $field->getSubfields('a');
// we might get an array back; in this case, we want the first subfield
if (is_array($sf)) {
  $field->insertSubfield($subfield1, $sf[0], true);
}
else {
  $field->insertSubfield($subfield1, $sf, true);
}

// let's see the results
print $field->getContents();
print "\n";
print $field->getContents('###');
print "\n";

?>
--EXPECT--
a littlenothingeverything
a little###nothing###everything
PK��Z��%Hhh"test/File_MARC/tests/marc_003.phptnu�[���--TEST--
marc_003: getFields() with various regular expressions
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';
$marc_file = new File_MARC($dir . '/' . 'music.mrc');

print "Test with a simple string\n";
while ($marc_record = $marc_file->next()) {
  print "\nNext record:\n";
  $fields = $marc_record->getFields('650');
  foreach ($fields as $field) {
    print $field;
    print "\n";
  }
}

print "\nTest with regular expression\n";
$marc_file = new File_MARC($dir . '/' . 'music.mrc');
while ($marc_record = $marc_file->next()) {
  print "\nNext record:\n";
  $fields = $marc_record->getFields('00\d', true);
  foreach ($fields as $field) {
    print $field;
    print "\n";
  }
}

?>
--EXPECT--
Test with a simple string

Next record:
650  0 _aJazz.
650  0 _aMotion picture music
       _vExcerpts
       _vScores.

Next record:
650  0 _aJazz
       _y1971-1980.

Next record:
650  0 _aJazz.

Test with regular expression

Next record:
001     000073594
004     AAJ5802
005     20030415102100.0
008     801107s1977    nyujza                   

Next record:
001     001878039
005     20050110174900.0
007     sd fungnn|||e|
008     940202r19931981nyujzn   i              d

Next record:
001     001964482
005     20060626132700.0
007     sd fzngnn|m|e|
008     871211p19871957nyujzn                  d
PK��Z(���NNtest/File_MARC/tests/camel.mrcnu�[���00755cam  22002414a 4500001001300000003000600013005001700019008004100036010001700077020004300094040001800137042000800155050002600163082001700189100003100206245005400237260004200291300007200333500003300405650003700438630002500475630001300500fol05731351 IMchF20000613133448.0000107s2000    nyua          001 0 eng    a   00020737   a0471383147 (paper/cd-rom : alk. paper)  aDLCcDLCdDLC  apcc00aQA76.73.P22bM33 200000a005.13/32211 aMartinsson, Tobias,d1976-10aActivePerl with ASP and ADO /cTobias Martinsson.  aNew York :bJohn Wiley & Sons,c2000.  axxi, 289 p. :bill. ;c23 cm. +e1 computer  laser disc (4 3/4 in.)  a"Wiley Computer Publishing." 0aPerl (Computer program language)00aActive server pages.00aActiveX.00647pam  2200241 a 4500001001300000003000600013005001700019008004100036010001700077020001500094040001800109042000800127050002600135082001500161100002600176245006700202260003800269263000900307300001100316650003700327650002500364700001600389fol05754809 IMchF20000601115601.0000203s2000    mau           001 0 eng    a   00022023   a1565926994  aDLCcDLCdDLC  apcc00aQA76.73.P22bD47 200000a005.742211 aDescartes, Alligator.10aProgramming the Perl DBI /cAlligator Descartes and Tim Bunce.  aCmabridge, MA :bO'Reilly,c2000.  a1111  ap. cm. 0aPerl (Computer program language) 0aDatabase management.1 aBunce, Tim.00605cam  22002054a 4500001001300000003000600013005001700019008004100036010001700077040001800094042000800112050002700120082001700147100002100164245005500185260004500240300002600285504005100311650003700362fol05843555 IMchF20000525142739.0000318s1999    cau      b    001 0 eng    a   00501349   aDLCcDLCdDLC  apcc00aQA76.73.P22bB763 199900a005.13/32211 aBrown, Martin C.10aPerl :bprogrammer's reference /cMartin C. Brown.  aBerkeley :bOsborne/McGraw-Hill,cc1999.  axix, 380 p. ;c22 cm.  aIncludes bibliographical references and index. 0aPerl (Computer program language)00579cam  22002054a 4500001001300000003000600013005001700019008004100036010001700077020001500094040001800109042000800127050002700135082001700162100002100179245005500200260004500255300003600300650003700336fol05843579 IMchF20000525142716.0000318s1999    caua          001 0 eng    a   00502116   a0072120002  aDLCcDLCdDLC  apcc00aQA76.73.P22bB762 199900a005.13/32211 aBrown, Martin C.10aPerl :bthe complete reference /cMartin C. Brown.  aBerkeley :bOsborne/McGraw-Hill,cc1999.  axxxv, 1179 p. :bill. ;c24 cm. 0aPerl (Computer program language)00801nam  22002778a 4500001001300000003000600013005001700019008004100036010001700077020001500094040001300109042000800122050002600130082001800156100002000174245008800194250003200282260004100314263000900355300001100364650003700375650003600412650002600448700002500474700002400499fol05848297 IMchF20000524125727.0000518s2000    mau           001 0 eng    a   00041664   a1565924193  aDLCcDLC  apcc00aQA76.73.P22bG84 200000a005.2/7622211 aGuelich, Scott.10aCGI programming with Perl /cScott Guelich, Shishir Gundavaram & Gunther Birznieks.  a2nd ed., expanded & updated  aCambridge, Mass. :bO'Reilly,c2000.  a0006  ap. cm. 0aPerl (Computer program language) 0aCGI (Computer network protocol) 0aInternet programming.1 aGundavaram, Shishir.1 aBirznieks, Gunther.00665nam  22002298a 4500001001300000003000600013005001700019008004100036010001700077020001500094040001300109042000800122050002700130082001700157111005200174245008600226250001200312260004100324263000900365300001100374650005000385fol05865950 IMchF20000615103017.0000612s2000    mau           100 0 eng    a   00055759   a0596000138  aDLCcDLC  apcc00aQA76.73.P22bP475 200000a005.13/32212 aPerl Conference 4.0d(2000 :cMonterey, Calif.)10aProceedings of the Perl Conference 4.0 :bJuly 17-20, 2000, Monterey, California.  a1st ed.  aCambridge, Mass. :bO'Reilly,c2000.  a0006  ap. cm. 0aPerl (Computer program language)vCongresses.00579nam  22002178a 4500001001300000003000600013005001700019008004100036010001700077020001500094040001300109042000800122050002600130082001700156100002800173245006200201260004100263263000900304300001100313650003700324fol05865956 IMchF20000615102948.0000612s2000    mau           000 0 eng    a   00055770   a1565926099  aDLCcDLC  apcc00aQA76.73.P22bB43 200000a005.13/32211 aBlank-Edelman, David N.10aPerl for system administration /cDavid N. Blank-Edelman.  aCambridge, Mass. :bO'Reilly,c2000.  a0006  ap. cm. 0aPerl (Computer program language)00661nam  22002538a 4500001001300000003000600013005001700019008004100036010001700077020001500094040001300109042000800122050002600130082001700156100001700173245006700190250001200257260004100269263000900310300001100319650003700330700002300367700001700390fol05865967 IMchF20000615102611.0000614s2000    mau           000 0 eng    a   00055799   a0596000278  aDLCcDLC  apcc00aQA76.73.P22bW35 200000a005.13/32211 aWall, Larry.10aProgramming Perl /cLarry Wall, Tom Christiansen & Jon Orwant.  a3rd ed.  aCambridge, Mass. :bO'Reilly,c2000.  a0007  ap. cm. 0aPerl (Computer program language)1 aChristiansen, Tom.1 aOrwant, Jon.00603cam  22002054a 4500001001300000003000600013005001700019008004100036010001700077020001500094040001800109042000800127050002600135082001700161100003200178245006000210260005700270300003300327650003700360fol05872355 IMchF20000706095105.0000315s1999    njua          001 0 eng    a   00500678   a013020868X  aDLCcDLCdDLC  apcc00aQA76.73.P22bL69 199900a005.13/32211 aLowe, Vincentq(Vincent D.)10aPerl programmer's interactive workbook /cVincent Lowe.  aUpper Saddle River, NJ :bPrentice Hall PTP,cc1999.  axx, 633 p. :bill. ;c23 cm. 0aPerl (Computer program language)00696nam  22002538a 4500001001300000003000600013005001700019008004100036010001700077020002800094040001300122042000800135050002600143082001700169100002600186245004400212260005100256263000900307300001100316500002000327650003700347650001700384650004100401fol05882032 IMchF20000707091904.0000630s2000    cau           001 0 eng    a   00058174   a0764547291 (alk. paper)  aDLCcDLC  apcc00aQA76.73.P22bF64 200000a005.13/32212 aFoster-Johnson, Eric.10aCross-platform Perl /cEric F. Johnson.  aFoster City, CA :bIDG Books Worldwide,c2000.  a0009  ap. cm.  aIncludes index. 0aPerl (Computer program language) 0aWeb servers. 0aCross-platform software development.00399ngm  2200121 a 4500001001300000003000700013007002800020008004100048245005600089260003800145300006000183538003400243ttt05000099 TEST  avbfc dcebfaghhoiu050224s2005    ilu999            vleng d00aTest subfields in control fieldsh[videorecording].  aOregon, Ill. :bB. Baldus,c2005.  a1 videocassette (ca. 1000 min.) :bsd., col. ;c1/2 in.  aVHS format, SP playback mode.PK��Z�p�޸�"test/File_MARC/tests/marc_007.phptnu�[���--TEST--
marc_007: Use key=>value iteration for tags and codes
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';
$marc_file = new File_MARC($dir . '/' . 'example.mrc');

if ($marc_record = $marc_file->next()) {
    foreach ($marc_record->getFields() as $tag=>$value) {
        print "$tag: ";
	    if ($value instanceof File_MARC_Control_Field) {
                print $value->getData();
            }
	    else {
                foreach ($value->getSubfields() as $code=>$subdata) {
                    print "_$code";
                }
            }
        print "\n";
    }
}
?>
--EXPECT--
001: 0000000044
003: EMILDA
008: 980120s1998    fi     j      000 0 swe
020: _a_c
035: _9
040: _a
042: _9_9
084: _a_2
084: _5_a_2
084: _5_a_2
084: _5_a_2
100: _a_d
245: _a_c
250: _a
260: _a_b_c_e_f
300: _a_b_c
440: _a_x
500: _a
599: _a
740: _a
775: _z_w_9
841: _5_a_b_e
841: _5_a_b_e
841: _5_a_b_e
841: _5_a_b_e
841: _5_a_b_e
841: _5_a_b_e
852: _5_b_c_h_j
852: _5_b_c_h
852: _5_b
852: _5_b_j
852: _5_b_c_h_j
852: _5_b_h_j
900: _a_d_u_d
900: _a_d_u_d
900: _a_d_u_d
900: _a_d_u_d
900: _a_d_u_d
900: _a_d_u_d
976: _a_b
005: 20050204111518.0
PK��Z����1�1&test/File_MARC/tests/marc_xml_008.phptnu�[���--TEST--
marc_xml_008: generate a single collection of MARCXML records from a MARCXML record
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';

$records = new File_MARCXML($dir . '/' . 'music.xml');

// Add the XML header and opening <collection> element
$records->toXMLHeader();

// Iterate through the retrieved records
while ($record = $records->next()) {

    // Change each 852 $c to "Audio-Visual"
    $holdings = $record->getFields('852');
    foreach ($holdings as $holding) {

        // Get the $c subfields from this field
        $formats = $holding->getSubfields('c');
        foreach ($formats as $format) {
            if ($format->getData('AV')) {
                $format->setData('Audio-Visual');
            }
        }
    }

    // Generate the XML output for this record
    print $record->toXML('UTF-8', true, false);
}
// Add the </collection> closing element and dump the XMLWriter contents
print $records->toXMLFooter();
--EXPECT--
<?xml version="1.0" encoding="UTF-8"?>
<collection xmlns="http://www.loc.gov/MARC21/slim">
 <record xmlns="http://www.loc.gov/MARC21/slim">
  <leader>01145ncm a2200277 i 4500</leader>
  <controlfield tag="001">000073594</controlfield>
  <controlfield tag="004">AAJ5802</controlfield>
  <controlfield tag="005">20030415102100.0</controlfield>
  <controlfield tag="008">801107s1977    nyujza                   </controlfield>
  <datafield tag="010" ind1=" " ind2=" ">
   <subfield code="a">   77771106 </subfield>
  </datafield>
  <datafield tag="035" ind1=" " ind2=" ">
   <subfield code="a">(CaOTUIC)15460184</subfield>
  </datafield>
  <datafield tag="035" ind1="9" ind2=" ">
   <subfield code="a">AAJ5802</subfield>
  </datafield>
  <datafield tag="040" ind1=" " ind2=" ">
   <subfield code="a">LC</subfield>
  </datafield>
  <datafield tag="050" ind1="0" ind2="0">
   <subfield code="a">M1366</subfield>
   <subfield code="b">.M62</subfield>
   <subfield code="d">M1527.2</subfield>
  </datafield>
  <datafield tag="245" ind1="0" ind2="4">
   <subfield code="a">The Modern Jazz Quartet :</subfield>
   <subfield code="b">The legendary profile. --</subfield>
  </datafield>
  <datafield tag="260" ind1=" " ind2=" ">
   <subfield code="a">New York :</subfield>
   <subfield code="b">M.J.Q. Music,</subfield>
   <subfield code="c">c1977.</subfield>
  </datafield>
  <datafield tag="300" ind1=" " ind2=" ">
   <subfield code="a">score (72 p.) ;</subfield>
   <subfield code="c">31 cm.</subfield>
  </datafield>
  <datafield tag="500" ind1=" " ind2=" ">
   <subfield code="a">For piano, vibraphone, drums, and double bass.</subfield>
  </datafield>
  <datafield tag="505" ind1="0" ind2=" ">
   <subfield code="a">Lewis, J. Django.--Lewis, J. Plastic dreams (music from the film Kemek).--Lewis, J. Dancing (music from the film Kemek).--Lewis, J. Blues in A minor.--Lewis, J. Blues in B́Ư.--Lewis, J. Precious joy.--Jackson, M. The martyr.--Jackson, M. The legendary profile.</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="0">
   <subfield code="a">Jazz.</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="0">
   <subfield code="a">Motion picture music</subfield>
   <subfield code="v">Excerpts</subfield>
   <subfield code="v">Scores.</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2="2">
   <subfield code="a">Lewis, John,</subfield>
   <subfield code="d">1920-</subfield>
   <subfield code="t">Selections.</subfield>
   <subfield code="f">1977.</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2="2">
   <subfield code="a">Jackson, Milt.</subfield>
   <subfield code="t">Martyrs.</subfield>
   <subfield code="f">1977.</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2="2">
   <subfield code="a">Jackson, Milt.</subfield>
   <subfield code="t">Legendary profile.</subfield>
   <subfield code="f">1977.</subfield>
  </datafield>
  <datafield tag="740" ind1="4" ind2=" ">
   <subfield code="a">The legendary profile.</subfield>
  </datafield>
  <datafield tag="852" ind1="0" ind2="0">
   <subfield code="b">MUSIC</subfield>
   <subfield code="c">Audio-Visual</subfield>
   <subfield code="k">folio</subfield>
   <subfield code="h">M1366</subfield>
   <subfield code="i">M62</subfield>
   <subfield code="9">1</subfield>
   <subfield code="4">Marvin Duchow Music</subfield>
   <subfield code="5"></subfield>
  </datafield>
 </record>
 <record xmlns="http://www.loc.gov/MARC21/slim">
  <leader>01293cjm a2200289 a 4500</leader>
  <controlfield tag="001">001878039</controlfield>
  <controlfield tag="005">20050110174900.0</controlfield>
  <controlfield tag="007">sd fungnn|||e|</controlfield>
  <controlfield tag="008">940202r19931981nyujzn   i              d</controlfield>
  <datafield tag="024" ind1="1" ind2=" ">
   <subfield code="a">7464573372</subfield>
  </datafield>
  <datafield tag="028" ind1="0" ind2="2">
   <subfield code="a">JK 57337</subfield>
   <subfield code="b">Red Baron</subfield>
  </datafield>
  <datafield tag="035" ind1=" " ind2=" ">
   <subfield code="a">(OCoLC)29737267</subfield>
  </datafield>
  <datafield tag="040" ind1=" " ind2=" ">
   <subfield code="a">SVP</subfield>
   <subfield code="c">SVP</subfield>
   <subfield code="d">LGG</subfield>
  </datafield>
  <datafield tag="100" ind1="1" ind2=" ">
   <subfield code="a">Desmond, Paul,</subfield>
   <subfield code="d">1924-</subfield>
  </datafield>
  <datafield tag="245" ind1="1" ind2="0">
   <subfield code="a">Paul Desmond &amp; the Modern Jazz Quartet</subfield>
   <subfield code="h">[sound recording]</subfield>
  </datafield>
  <datafield tag="260" ind1=" " ind2=" ">
   <subfield code="a">New York, N.Y. :</subfield>
   <subfield code="b">Red Baron :</subfield>
   <subfield code="b">Manufactured by Sony Music Entertainment,</subfield>
   <subfield code="c">p1993.</subfield>
  </datafield>
  <datafield tag="300" ind1=" " ind2=" ">
   <subfield code="a">1 sound disc (39 min.) :</subfield>
   <subfield code="b">digital ;</subfield>
   <subfield code="c">4 3/4 in.</subfield>
  </datafield>
  <datafield tag="511" ind1="0" ind2=" ">
   <subfield code="a">Paul Desmond, alto saxophone; Modern Jazz Quartet: John Lewis, piano; Milt Jackson, vibraphone; Percy Heath, bass; Connie Kay, drums.</subfield>
  </datafield>
  <datafield tag="500" ind1=" " ind2=" ">
   <subfield code="a">All arrangements by John Lewis.</subfield>
  </datafield>
  <datafield tag="518" ind1=" " ind2=" ">
   <subfield code="a">Recorded live on December 25, 1971 at Town Hall, NYC.</subfield>
  </datafield>
  <datafield tag="500" ind1=" " ind2=" ">
   <subfield code="a">Originally released in 1981 by Finesse as LP FW 27487.</subfield>
  </datafield>
  <datafield tag="500" ind1=" " ind2=" ">
   <subfield code="a">Program notes by Irving Townsend, June 1981, on container insert.</subfield>
  </datafield>
  <datafield tag="505" ind1="0" ind2=" ">
   <subfield code="a">Greensleeves -- You go to my head -- Blue dove -- Jesus Christ Superstar -- Here's that rainy day -- East of the sun -- Bags' new groove.</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="0">
   <subfield code="a">Jazz</subfield>
   <subfield code="y">1971-1980.</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2=" ">
   <subfield code="a">Lewis, John,</subfield>
   <subfield code="d">1920-</subfield>
  </datafield>
  <datafield tag="710" ind1="2" ind2=" ">
   <subfield code="a">Modern Jazz Quartet.</subfield>
  </datafield>
  <datafield tag="740" ind1="0" ind2=" ">
   <subfield code="a">Paul Desmond and the Modern Jazz Quartet.</subfield>
  </datafield>
 </record>
 <record xmlns="http://www.loc.gov/MARC21/slim">
  <leader>01829cjm a2200385 a 4500</leader>
  <controlfield tag="001">001964482</controlfield>
  <controlfield tag="005">20060626132700.0</controlfield>
  <controlfield tag="007">sd fzngnn|m|e|</controlfield>
  <controlfield tag="008">871211p19871957nyujzn                  d</controlfield>
  <datafield tag="024" ind1="1" ind2=" ">
   <subfield code="a">4228332902</subfield>
  </datafield>
  <datafield tag="028" ind1="0" ind2="1">
   <subfield code="a">833 290-2</subfield>
   <subfield code="b">Verve</subfield>
  </datafield>
  <datafield tag="033" ind1="0" ind2=" ">
   <subfield code="a">19571027</subfield>
   <subfield code="b">6299</subfield>
   <subfield code="c">D56</subfield>
  </datafield>
  <datafield tag="033" ind1="0" ind2=" ">
   <subfield code="a">196112--</subfield>
   <subfield code="b">3804</subfield>
   <subfield code="c">N4</subfield>
  </datafield>
  <datafield tag="033" ind1="0" ind2=" ">
   <subfield code="a">19571019</subfield>
   <subfield code="b">4104</subfield>
   <subfield code="c">C6</subfield>
  </datafield>
  <datafield tag="033" ind1="0" ind2=" ">
   <subfield code="a">197107--</subfield>
   <subfield code="b">6299</subfield>
   <subfield code="c">V7</subfield>
  </datafield>
  <datafield tag="035" ind1=" " ind2=" ">
   <subfield code="a">(OCoLC)17222092</subfield>
  </datafield>
  <datafield tag="040" ind1=" " ind2=" ">
   <subfield code="a">CPL</subfield>
   <subfield code="c">CPL</subfield>
   <subfield code="d">OCL</subfield>
   <subfield code="d">LGG</subfield>
  </datafield>
  <datafield tag="048" ind1=" " ind2=" ">
   <subfield code="a">pz01</subfield>
   <subfield code="a">ka01</subfield>
   <subfield code="a">sd01</subfield>
   <subfield code="a">pd01</subfield>
  </datafield>
  <datafield tag="110" ind1="2" ind2=" ">
   <subfield code="a">Modern Jazz Quartet.</subfield>
   <subfield code="4">prf</subfield>
  </datafield>
  <datafield tag="245" ind1="1" ind2="4">
   <subfield code="a">The Modern Jazz Quartet plus</subfield>
   <subfield code="h">[sound recording].</subfield>
  </datafield>
  <datafield tag="260" ind1=" " ind2=" ">
   <subfield code="a">[New York] :</subfield>
   <subfield code="b">Verve,</subfield>
   <subfield code="c">p1987.</subfield>
  </datafield>
  <datafield tag="300" ind1=" " ind2=" ">
   <subfield code="a">1 sound disc :</subfield>
   <subfield code="b">digital ;</subfield>
   <subfield code="c">4 3/4 in.</subfield>
  </datafield>
  <datafield tag="440" ind1=" " ind2="0">
   <subfield code="a">Compact jazz</subfield>
  </datafield>
  <datafield tag="511" ind1="0" ind2=" ">
   <subfield code="a">Modern Jazz Quartet (principally) ; Milt Jackson, vibraphone (2nd and 8th works) ; Oscar Peterson, piano (2nd and 8th works) ; Ray Brown, bass (2nd and 8th works) ; Ed Thigpen (2nd work), Louis Hayes (8th work), drums.</subfield>
  </datafield>
  <datafield tag="518" ind1=" " ind2=" ">
   <subfield code="a">Recorded live, Oct. 27, 1957, at the Donaueschingen Jazz Festival (1st, 5th, 7th, and 10th works); Dec. 1961, in New York (2nd work); live, Oct. 19, 1957, at the Opera House, Chicago (3rd, 4th, 6th, and 9th works); July 1971, in Villingen, Germany (8th work).</subfield>
  </datafield>
  <datafield tag="500" ind1=" " ind2=" ">
   <subfield code="a">Compact disc.</subfield>
  </datafield>
  <datafield tag="500" ind1=" " ind2=" ">
   <subfield code="a">Analog recording.</subfield>
  </datafield>
  <datafield tag="505" ind1="0" ind2=" ">
   <subfield code="a">The golden striker (4:08) -- On Green Dolphin Street (7:28) -- D &amp; E (4:55) -- I'll remember April (4:51) -- Cort©·ge (7:15) -- Now's the time (4:43) -- J.B. blues (5:09) -- Reunion blues (6:35) -- 'Round midnight (3:56) -- Three windows (7:20).</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="0">
   <subfield code="a">Jazz.</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2=" ">
   <subfield code="a">Jackson, Milt.</subfield>
   <subfield code="4">prf</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2=" ">
   <subfield code="a">Peterson, Oscar,</subfield>
   <subfield code="d">1925-</subfield>
   <subfield code="4">prf</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2=" ">
   <subfield code="a">Brown, Ray,</subfield>
   <subfield code="d">1926-2002.</subfield>
   <subfield code="4">prf</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2=" ">
   <subfield code="a">Thigpen, Ed.</subfield>
   <subfield code="4">prf</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2=" ">
   <subfield code="a">Hayes, Louis,</subfield>
   <subfield code="d">1937-</subfield>
   <subfield code="4">prf</subfield>
  </datafield>
  <datafield tag="852" ind1="8" ind2="0">
   <subfield code="b">MUSIC</subfield>
   <subfield code="c">Audio-Visual</subfield>
   <subfield code="h">CD 1131</subfield>
   <subfield code="4">Marvin Duchow Music</subfield>
   <subfield code="5">Audio-Visual</subfield>
  </datafield>
 </record>
</collection>
PK��Z)�]�
�
"test/File_MARC/tests/marc_005.phptnu�[���--TEST--
marc_005: Ensure a duplicated record is a deep copy; test deleteFields()
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';
$marc_file = new File_MARC($dir . '/' . 'example.mrc');

$marc_record = $marc_file->next();
$copy_record = $marc_record;
$duplicate_record = clone $marc_record;

$num_deleted1 = $marc_record->deleteFields('020');
print "Deleted $num_deleted1 fields from the original record.\n";

$num_deleted2 = $copy_record->deleteFields('8\\d\\d', true);
print "Deleted $num_deleted2 fields from the shallow copy record.\n";

$num_deleted3 = $duplicate_record->deleteFields('9\\d\\d', true);
print "Deleted $num_deleted3 fields from the duplicate record.\n";

print "Original:\n";
print $marc_record;

print "\nCopy:\n";
print $copy_record;

print "\nDuplicate:\n";
print $duplicate_record;
print "\n";

?>
--EXPECT--
Deleted 1 fields from the original record.
Deleted 12 fields from the shallow copy record.
Deleted 7 fields from the duplicate record.
Original:
LDR 01850     2200517   4500
001     0000000044
003     EMILDA
008     980120s1998    fi     j      000 0 swe
035    _99515008808
040    _aNB
042    _9NB
       _9SEE
084    _aHcd,u
       _2kssb/6
084    _5NB
       _auHc
       _2kssb
084    _5SEE
       _aHcf
       _2kssb/6
084    _5Q
       _aHcd,uf
       _2kssb/6
100 1  _aJansson, Tove,
       _d1914-2001
245 04 _aDet osynliga barnet och andra ber�ttelser /
       _cTove Jansson
250    _a7. uppl.
260    _aHelsingfors :
       _bSchildt,
       _c1998 ;
       _e(Falun :
       _fScandbook)
300    _a166, [4] s. :
       _bill. ;
       _c21 cm
440  0 _aMumin-biblioteket,
       _x99-0698931-9
500    _aOriginaluppl. 1962
599    _aLi: S
740 4  _aDet osynliga barnet
775 1  _z951-50-0385-7
       _w9515003857
       _907
005     20050204111518.0

Copy:
LDR 01850     2200517   4500
001     0000000044
003     EMILDA
008     980120s1998    fi     j      000 0 swe
035    _99515008808
040    _aNB
042    _9NB
       _9SEE
084    _aHcd,u
       _2kssb/6
084    _5NB
       _auHc
       _2kssb
084    _5SEE
       _aHcf
       _2kssb/6
084    _5Q
       _aHcd,uf
       _2kssb/6
100 1  _aJansson, Tove,
       _d1914-2001
245 04 _aDet osynliga barnet och andra ber�ttelser /
       _cTove Jansson
250    _a7. uppl.
260    _aHelsingfors :
       _bSchildt,
       _c1998 ;
       _e(Falun :
       _fScandbook)
300    _a166, [4] s. :
       _bill. ;
       _c21 cm
440  0 _aMumin-biblioteket,
       _x99-0698931-9
500    _aOriginaluppl. 1962
599    _aLi: S
740 4  _aDet osynliga barnet
775 1  _z951-50-0385-7
       _w9515003857
       _907
005     20050204111518.0

Duplicate:
LDR 01850     2200517   4500
001     0000000044
003     EMILDA
008     980120s1998    fi     j      000 0 swe
035    _99515008808
040    _aNB
042    _9NB
       _9SEE
084    _aHcd,u
       _2kssb/6
084    _5NB
       _auHc
       _2kssb
084    _5SEE
       _aHcf
       _2kssb/6
084    _5Q
       _aHcd,uf
       _2kssb/6
100 1  _aJansson, Tove,
       _d1914-2001
245 04 _aDet osynliga barnet och andra ber�ttelser /
       _cTove Jansson
250    _a7. uppl.
260    _aHelsingfors :
       _bSchildt,
       _c1998 ;
       _e(Falun :
       _fScandbook)
300    _a166, [4] s. :
       _bill. ;
       _c21 cm
440  0 _aMumin-biblioteket,
       _x99-0698931-9
500    _aOriginaluppl. 1962
599    _aLi: S
740 4  _aDet osynliga barnet
775 1  _z951-50-0385-7
       _w9515003857
       _907
005     20050204111518.0
PK��Z	V�U,,*test/File_MARC/tests/marc_field_21246.phptnu�[���--TEST--
marc_field_21246: Delete multiple subfields
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';

$field = new File_MARC_Data_Field(650, [
    new File_MARC_Subfield('9', 'test1'),
    new File_MARC_Subfield('9', 'test2'),
    new File_MARC_Subfield('0', 'test3'),
    new File_MARC_Subfield('9', 'test4'),
  ]
);
echo "--- Before: ---\n$field\n\n";
foreach ($field->getSubfields('9') as $subfield) {
  echo "Deleting subfield: $subfield\n";
  $field->deleteSubfield($subfield);
}
echo "\n--- After: ---\n$field\n\n";
?>
--EXPECT--
--- Before: ---
650    _9test1
       _9test2
       _0test3
       _9test4

Deleting subfield: [9]: test1
Deleting subfield: [9]: test2
Deleting subfield: [9]: test4

--- After: ---
650    _0test3
PK��Z�_|6	6	'test/File_MARC/tests/marc_lint_002.phptnu�[���--TEST--
marc_lint_002: Tests check041() and check043() called separately
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
<?php include('tests/skipif_noispn.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';

// Create test harness to allow direct calls to check methods:
class File_MARC_Lint_Test_Harness extends File_MARC_Lint
{
    public function check041($field)
    {
        return parent::check041($field);
    }

    public function check043($field)
    {
        return parent::check043($field);
    }

    // override warn method to echo instead of store in object:
    protected function warn($msg)
    {
        echo $msg . "\n";
    }
}

$marc_lint = new File_MARC_Lint_Test_Harness();

$field = new File_MARC_Data_Field(
    '041',
    array(
        new File_MARC_Subfield('a', 'end'),             // invalid
        new File_MARC_Subfield('a', 'span'),            // too long
        new File_MARC_Subfield('h', 'far')              // obsolete
    ),
    "0", ""
);
$marc_lint->check041($field);

$field = new File_MARC_Data_Field(
    '041',
    array(
        new File_MARC_Subfield('a', 'endorviwo'),       // invalid
        new File_MARC_Subfield('a', 'spanowpalasba')    // too long and invalid
    ),
    "1", ""
);
$marc_lint->check041($field);

$field = new File_MARC_Data_Field(
    '043',
    array(
        new File_MARC_Subfield('a', 'n-----'),          // 6 chars vs. 7
        new File_MARC_Subfield('a', 'n-us----'),        // 8 chars vs. 7
        new File_MARC_Subfield('a', 'n-ma-us'),         // invalid code
        new File_MARC_Subfield('a', 'e-ur-ai')          // obsolete code
    ),
    "", ""
);
$marc_lint->check043($field);

?>
--EXPECT--
041: Subfield _a, end (end), is not valid.
041: Subfield _a must be evenly divisible by 3 or exactly three characters if ind2 is not 7, (span).
041: Subfield _h, far, may be obsolete.
041: Subfield _a, endorviwo (end), is not valid.
041: Subfield _a, endorviwo (orv), is not valid.
041: Subfield _a, endorviwo (iwo), is not valid.
041: Subfield _a must be evenly divisible by 3 or exactly three characters if ind2 is not 7, (spanowpalasba).
043: Subfield _a must be exactly 7 characters, n-----
043: Subfield _a must be exactly 7 characters, n-us----
043: Subfield _a, n-ma-us, is not valid.
043: Subfield _a, e-ur-ai, may be obsolete.
PK��Z�=O	
	
!test/File_MARC/tests/sandburg.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<collection xmlns="http://www.loc.gov/MARC21/slim">
 <record>
  <leader>01142cam  2200301 a 4500</leader>
  <controlfield tag="001">   92005291 </controlfield>
  <controlfield tag="003">DLC</controlfield>
  <controlfield tag="005">19930521155141.9</controlfield>
  <controlfield tag="008">920219s1993    caua   j      000 0 eng  </controlfield>
  <datafield tag="010" ind1=" " ind2=" ">
   <subfield code="a">   92005291 </subfield>
  </datafield>
  <datafield tag="020" ind1=" " ind2=" ">
   <subfield code="a">0152038655 :</subfield>
   <subfield code="c">$15.95</subfield>
  </datafield>
  <datafield tag="040" ind1=" " ind2=" ">
   <subfield code="a">DLC</subfield>
   <subfield code="c">DLC</subfield>
   <subfield code="d">DLC</subfield>
  </datafield>
  <datafield tag="042" ind1=" " ind2=" ">
   <subfield code="a">lcac</subfield>
  </datafield>
  <datafield tag="050" ind1="0" ind2="0">
   <subfield code="a">PS3537.A618</subfield>
   <subfield code="b">A88 1993</subfield>
  </datafield>
  <datafield tag="082" ind1="0" ind2="0">
   <subfield code="a">811/.52</subfield>
   <subfield code="2">20</subfield>
  </datafield>
  <datafield tag="100" ind1="1" ind2=" ">
   <subfield code="a">Sandburg, Carl,</subfield>
   <subfield code="d">1878-1967.</subfield>
  </datafield>
  <datafield tag="245" ind1="1" ind2="0">
   <subfield code="a">Arithmetic /</subfield>
   <subfield code="c">Carl Sandburg ; illustrated as an anamorphic adventure by Ted Rand.</subfield>
  </datafield>
  <datafield tag="250" ind1=" " ind2=" ">
   <subfield code="a">1st ed.</subfield>
  </datafield>
  <datafield tag="260" ind1=" " ind2=" ">
   <subfield code="a">San Diego :</subfield>
   <subfield code="b">Harcourt Brace Jovanovich,</subfield>
   <subfield code="c">c1993.</subfield>
  </datafield>
  <datafield tag="300" ind1=" " ind2=" ">
   <subfield code="a">1 v. (unpaged) :</subfield>
   <subfield code="b">ill. (some col.) ;</subfield>
   <subfield code="c">26 cm.</subfield>
  </datafield>
  <datafield tag="500" ind1=" " ind2=" ">
   <subfield code="a">One Mylar sheet included in pocket.</subfield>
  </datafield>
  <datafield tag="520" ind1=" " ind2=" ">
   <subfield code="a">A poem about numbers and their characteristics. Features anamorphic, or distorted, drawings which can be restored to normal by viewing from a particular angle or by viewing the image's reflection in the provided Mylar cone.</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="0">
   <subfield code="a">Arithmetic</subfield>
   <subfield code="x">Juvenile poetry.</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="0">
   <subfield code="a">Children's poetry, American.</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="1">
   <subfield code="a">Arithmetic</subfield>
   <subfield code="x">Poetry.</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="1">
   <subfield code="a">American poetry.</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="1">
   <subfield code="a">Visual perception.</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2=" ">
   <subfield code="a">Rand, Ted,</subfield>
   <subfield code="e">ill.</subfield>
  </datafield>
 </record>
</collection>
PK��Z�s}���3test/File_MARC/tests/marc_xml_namespace_prefix.phptnu�[���--TEST--
marc_xml_namespace: iterate and pretty print a MARC record
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';
$marc_file = new File_MARCXML($dir . '/' . 'namespace.xml',File_MARC::SOURCE_FILE,"marc",true);
while ($marc_record = $marc_file->next()) {
  print $marc_record->getLeader();
  print "\n";
  $field = $marc_record->getField('050');
  print $field->getIndicator(1);
  print "\n";
  print $field->getIndicator(2);
  print "\n";
  $subfield = $field->getSubfield('a');
  print $subfield->getData();
  print "\n";
}
?>
--EXPECT--
00925njm  22002777a 4500
0
0
Atlantic 1259
01832cmma 2200349 a 4500
0
0
F204.W5
PK��Z!Ņ\��&test/File_MARC/tests/marc_xml_001.phptnu�[���--TEST--
marc_xml_001: iterate and pretty print a MARC record
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';
$marc_file = new File_MARC($dir . '/' . 'example.mrc');

while ($marc_record = $marc_file->next()) {
  /* Note that this adds characters to the leader to satisfy MARCXML schema */
  print $marc_record->toXML();
  print "\n";
}
?>
--EXPECT--
<?xml version="1.0" encoding="UTF-8"?>
<collection xmlns="http://www.loc.gov/MARC21/slim">
 <record>
  <leader>01850na   2200517   4500</leader>
  <controlfield tag="001">0000000044</controlfield>
  <controlfield tag="003">EMILDA</controlfield>
  <controlfield tag="008">980120s1998    fi     j      000 0 swe</controlfield>
  <datafield tag="020" ind1=" " ind2=" ">
   <subfield code="a">9515008808</subfield>
   <subfield code="c">FIM 72:00</subfield>
  </datafield>
  <datafield tag="035" ind1=" " ind2=" ">
   <subfield code="9">9515008808</subfield>
  </datafield>
  <datafield tag="040" ind1=" " ind2=" ">
   <subfield code="a">NB</subfield>
  </datafield>
  <datafield tag="042" ind1=" " ind2=" ">
   <subfield code="9">NB</subfield>
   <subfield code="9">SEE</subfield>
  </datafield>
  <datafield tag="084" ind1=" " ind2=" ">
   <subfield code="a">Hcd,u</subfield>
   <subfield code="2">kssb/6</subfield>
  </datafield>
  <datafield tag="084" ind1=" " ind2=" ">
   <subfield code="5">NB</subfield>
   <subfield code="a">uHc</subfield>
   <subfield code="2">kssb</subfield>
  </datafield>
  <datafield tag="084" ind1=" " ind2=" ">
   <subfield code="5">SEE</subfield>
   <subfield code="a">Hcf</subfield>
   <subfield code="2">kssb/6</subfield>
  </datafield>
  <datafield tag="084" ind1=" " ind2=" ">
   <subfield code="5">Q</subfield>
   <subfield code="a">Hcd,uf</subfield>
   <subfield code="2">kssb/6</subfield>
  </datafield>
  <datafield tag="100" ind1="1" ind2=" ">
   <subfield code="a">Jansson, Tove,</subfield>
   <subfield code="d">1914-2001</subfield>
  </datafield>
  <datafield tag="245" ind1="0" ind2="4">
   <subfield code="a">Det osynliga barnet och andra ber�ttelser /</subfield>
   <subfield code="c">Tove Jansson</subfield>
  </datafield>
  <datafield tag="250" ind1=" " ind2=" ">
   <subfield code="a">7. uppl.</subfield>
  </datafield>
  <datafield tag="260" ind1=" " ind2=" ">
   <subfield code="a">Helsingfors :</subfield>
   <subfield code="b">Schildt,</subfield>
   <subfield code="c">1998 ;</subfield>
   <subfield code="e">(Falun :</subfield>
   <subfield code="f">Scandbook)</subfield>
  </datafield>
  <datafield tag="300" ind1=" " ind2=" ">
   <subfield code="a">166, [4] s. :</subfield>
   <subfield code="b">ill. ;</subfield>
   <subfield code="c">21 cm</subfield>
  </datafield>
  <datafield tag="440" ind1=" " ind2="0">
   <subfield code="a">Mumin-biblioteket,</subfield>
   <subfield code="x">99-0698931-9</subfield>
  </datafield>
  <datafield tag="500" ind1=" " ind2=" ">
   <subfield code="a">Originaluppl. 1962</subfield>
  </datafield>
  <datafield tag="599" ind1=" " ind2=" ">
   <subfield code="a">Li: S</subfield>
  </datafield>
  <datafield tag="740" ind1="4" ind2=" ">
   <subfield code="a">Det osynliga barnet</subfield>
  </datafield>
  <datafield tag="775" ind1="1" ind2=" ">
   <subfield code="z">951-50-0385-7</subfield>
   <subfield code="w">9515003857</subfield>
   <subfield code="9">07</subfield>
  </datafield>
  <datafield tag="841" ind1=" " ind2=" ">
   <subfield code="5">Li</subfield>
   <subfield code="a">xa</subfield>
   <subfield code="b">0201080u    0   4000uu   |000000</subfield>
   <subfield code="e">1</subfield>
  </datafield>
  <datafield tag="841" ind1=" " ind2=" ">
   <subfield code="5">SEE</subfield>
   <subfield code="a">xa</subfield>
   <subfield code="b">0201080u    0   4000uu   |000000</subfield>
   <subfield code="e">1</subfield>
  </datafield>
  <datafield tag="841" ind1=" " ind2=" ">
   <subfield code="5">L</subfield>
   <subfield code="a">xa</subfield>
   <subfield code="b">0201080u    0   4000uu   |000000</subfield>
   <subfield code="e">1</subfield>
  </datafield>
  <datafield tag="841" ind1=" " ind2=" ">
   <subfield code="5">NB</subfield>
   <subfield code="a">xa</subfield>
   <subfield code="b">0201080u    0   4000uu   |000000</subfield>
   <subfield code="e">1</subfield>
  </datafield>
  <datafield tag="841" ind1=" " ind2=" ">
   <subfield code="5">Q</subfield>
   <subfield code="a">xa</subfield>
   <subfield code="b">0201080u    0   4000uu   |000000</subfield>
   <subfield code="e">1</subfield>
  </datafield>
  <datafield tag="841" ind1=" " ind2=" ">
   <subfield code="5">S</subfield>
   <subfield code="a">xa</subfield>
   <subfield code="b">0201080u    0   4000uu   |000000</subfield>
   <subfield code="e">1</subfield>
  </datafield>
  <datafield tag="852" ind1=" " ind2=" ">
   <subfield code="5">NB</subfield>
   <subfield code="b">NB</subfield>
   <subfield code="c">NB98:12</subfield>
   <subfield code="h">plikt</subfield>
   <subfield code="j">R, 980520</subfield>
  </datafield>
  <datafield tag="852" ind1=" " ind2=" ">
   <subfield code="5">Li</subfield>
   <subfield code="b">Li</subfield>
   <subfield code="c">CNB</subfield>
   <subfield code="h">h,u</subfield>
  </datafield>
  <datafield tag="852" ind1=" " ind2=" ">
   <subfield code="5">SEE</subfield>
   <subfield code="b">SEE</subfield>
  </datafield>
  <datafield tag="852" ind1=" " ind2=" ">
   <subfield code="5">Q</subfield>
   <subfield code="b">Q</subfield>
   <subfield code="j">98947</subfield>
  </datafield>
  <datafield tag="852" ind1=" " ind2=" ">
   <subfield code="5">L</subfield>
   <subfield code="b">L</subfield>
   <subfield code="c">0100</subfield>
   <subfield code="h">98/</subfield>
   <subfield code="j">3043 H</subfield>
  </datafield>
  <datafield tag="852" ind1=" " ind2=" ">
   <subfield code="5">S</subfield>
   <subfield code="b">S</subfield>
   <subfield code="h">Sv97</subfield>
   <subfield code="j">7235</subfield>
  </datafield>
  <datafield tag="900" ind1="1" ind2="s">
   <subfield code="a">Yanson, Tobe,</subfield>
   <subfield code="d">1914-2001</subfield>
   <subfield code="u">Jansson, Tove,</subfield>
   <subfield code="d">1914-2001</subfield>
  </datafield>
  <datafield tag="900" ind1="1" ind2="s">
   <subfield code="a">Janssonov�, Tove,</subfield>
   <subfield code="d">1914-2001</subfield>
   <subfield code="u">Jansson, Tove,</subfield>
   <subfield code="d">1914-2001</subfield>
  </datafield>
  <datafield tag="900" ind1="1" ind2="s">
   <subfield code="a">Jansone, Tuve,</subfield>
   <subfield code="d">1914-2001</subfield>
   <subfield code="u">Jansson, Tove,</subfield>
   <subfield code="d">1914-2001</subfield>
  </datafield>
  <datafield tag="900" ind1="1" ind2="s">
   <subfield code="a">Janson, Tuve,</subfield>
   <subfield code="d">1914-2001</subfield>
   <subfield code="u">Jansson, Tove,</subfield>
   <subfield code="d">1914-2001</subfield>
  </datafield>
  <datafield tag="900" ind1="1" ind2="s">
   <subfield code="a">Jansson, Tuve,</subfield>
   <subfield code="d">1914-2001</subfield>
   <subfield code="u">Jansson, Tove,</subfield>
   <subfield code="d">1914-2001</subfield>
  </datafield>
  <datafield tag="900" ind1="1" ind2="s">
   <subfield code="a">Janssonova, Tove,</subfield>
   <subfield code="d">1914-2001</subfield>
   <subfield code="u">Jansson, Tove,</subfield>
   <subfield code="d">1914-2001</subfield>
  </datafield>
  <datafield tag="976" ind1=" " ind2="2">
   <subfield code="a">Hcd,u</subfield>
   <subfield code="b">Sk�nlitteratur</subfield>
  </datafield>
  <controlfield tag="005">20050204111518.0</controlfield>
 </record>
</collection>
PK��ZF;�Re%e%"test/File_MARC/tests/marc_004.phptnu�[���--TEST--
marc_004: Delete fields and subfields
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';
$marc_file = new File_MARC($dir . '/' . 'music.mrc');

print "\nDelete all fields with tag 650\n";
while ($marc_record = $marc_file->next()) {
  print "\nNext record:\n";
  $fields = $marc_record->getFields('650');
  foreach ($fields as $field) {
    $field->delete();
  }
  print $marc_record;
}

$marc_file = null;
$marc_file = new File_MARC($dir . '/' . 'music.mrc');

print "\nDelete all subfields with code 'a' from fields with tag 650\n";
while ($marc_record = $marc_file->next()) {
  print "\nNext record:\n";
  $fields = $marc_record->getFields('650');
  foreach ($fields as $field) {
    $sf = $field->getSubfields('a');
    foreach ($sf as $subfield) {
      $field->deleteSubfield($subfield);
    }
  }
  print $marc_record;
}

?>
--EXPECT--
Delete all fields with tag 650

Next record:
LDR 01145ncm  2200277 i 4500
001     000073594
004     AAJ5802
005     20030415102100.0
008     801107s1977    nyujza                   
010    _a   77771106 
035    _a(CaOTUIC)15460184
035 9  _aAAJ5802
040    _aLC
050 00 _aM1366
       _b.M62
       _dM1527.2
245 04 _aThe Modern Jazz Quartet :
       _bThe legendary profile. --
260    _aNew York :
       _bM.J.Q. Music,
       _cc1977.
300    _ascore (72 p.) ;
       _c31 cm.
500    _aFor piano, vibraphone, drums, and double bass.
505 0  _aLewis, J. Django.--Lewis, J. Plastic dreams (music from the film Kemek).--Lewis, J. Dancing (music from the film Kemek).--Lewis, J. Blues in A minor.--Lewis, J. Blues in B♭.--Lewis, J. Precious joy.--Jackson, M. The martyr.--Jackson, M. The legendary profile.
700 12 _aLewis, John,
       _d1920-
       _tSelections.
       _f1977.
700 12 _aJackson, Milt.
       _tMartyrs.
       _f1977.
700 12 _aJackson, Milt.
       _tLegendary profile.
       _f1977.
740 4  _aThe legendary profile.
852 00 _bMUSIC
       _cMAIN
       _kfolio
       _hM1366
       _iM62
       _91
       _4Marvin Duchow Music
       _5

Next record:
LDR 01293cjm  2200289 a 4500
001     001878039
005     20050110174900.0
007     sd fungnn|||e|
008     940202r19931981nyujzn   i              d
024 1  _a7464573372
028 02 _aJK 57337
       _bRed Baron
035    _a(OCoLC)29737267
040    _aSVP
       _cSVP
       _dLGG
100 1  _aDesmond, Paul,
       _d1924-
245 10 _aPaul Desmond & the Modern Jazz Quartet
       _h[sound recording]
260    _aNew York, N.Y. :
       _bRed Baron :
       _bManufactured by Sony Music Entertainment,
       _cp1993.
300    _a1 sound disc (39 min.) :
       _bdigital ;
       _c4 3/4 in.
511 0  _aPaul Desmond, alto saxophone; Modern Jazz Quartet: John Lewis, piano; Milt Jackson, vibraphone; Percy Heath, bass; Connie Kay, drums.
500    _aAll arrangements by John Lewis.
518    _aRecorded live on December 25, 1971 at Town Hall, NYC.
500    _aOriginally released in 1981 by Finesse as LP FW 27487.
500    _aProgram notes by Irving Townsend, June 1981, on container insert.
505 0  _aGreensleeves -- You go to my head -- Blue dove -- Jesus Christ Superstar -- Here's that rainy day -- East of the sun -- Bags' new groove.
700 1  _aLewis, John,
       _d1920-
710 2  _aModern Jazz Quartet.
740 0  _aPaul Desmond and the Modern Jazz Quartet.

Next record:
LDR 01829cjm  2200385 a 4500
001     001964482
005     20060626132700.0
007     sd fzngnn|m|e|
008     871211p19871957nyujzn                  d
024 1  _a4228332902
028 01 _a833 290-2
       _bVerve
033 0  _a19571027
       _b6299
       _cD56
033 0  _a196112--
       _b3804
       _cN4
033 0  _a19571019
       _b4104
       _cC6
033 0  _a197107--
       _b6299
       _cV7
035    _a(OCoLC)17222092
040    _aCPL
       _cCPL
       _dOCL
       _dLGG
048    _apz01
       _aka01
       _asd01
       _apd01
110 2  _aModern Jazz Quartet.
       _4prf
245 14 _aThe Modern Jazz Quartet plus
       _h[sound recording].
260    _a[New York] :
       _bVerve,
       _cp1987.
300    _a1 sound disc :
       _bdigital ;
       _c4 3/4 in.
440  0 _aCompact jazz
511 0  _aModern Jazz Quartet (principally) ; Milt Jackson, vibraphone (2nd and 8th works) ; Oscar Peterson, piano (2nd and 8th works) ; Ray Brown, bass (2nd and 8th works) ; Ed Thigpen (2nd work), Louis Hayes (8th work), drums.
518    _aRecorded live, Oct. 27, 1957, at the Donaueschingen Jazz Festival (1st, 5th, 7th, and 10th works); Dec. 1961, in New York (2nd work); live, Oct. 19, 1957, at the Opera House, Chicago (3rd, 4th, 6th, and 9th works); July 1971, in Villingen, Germany (8th work).
500    _aCompact disc.
500    _aAnalog recording.
505 0  _aThe golden striker (4:08) -- On Green Dolphin Street (7:28) -- D & E (4:55) -- I'll remember April (4:51) -- Cortège (7:15) -- Now's the time (4:43) -- J.B. blues (5:09) -- Reunion blues (6:35) -- 'Round midnight (3:56) -- Three windows (7:20).
700 1  _aJackson, Milt.
       _4prf
700 1  _aPeterson, Oscar,
       _d1925-
       _4prf
700 1  _aBrown, Ray,
       _d1926-2002.
       _4prf
700 1  _aThigpen, Ed.
       _4prf
700 1  _aHayes, Louis,
       _d1937-
       _4prf
852 80 _bMUSIC
       _cAV
       _hCD 1131
       _4Marvin Duchow Music
       _5Audio-Visual

Delete all subfields with code 'a' from fields with tag 650

Next record:
LDR 01145ncm  2200277 i 4500
001     000073594
004     AAJ5802
005     20030415102100.0
008     801107s1977    nyujza                   
010    _a   77771106 
035    _a(CaOTUIC)15460184
035 9  _aAAJ5802
040    _aLC
050 00 _aM1366
       _b.M62
       _dM1527.2
245 04 _aThe Modern Jazz Quartet :
       _bThe legendary profile. --
260    _aNew York :
       _bM.J.Q. Music,
       _cc1977.
300    _ascore (72 p.) ;
       _c31 cm.
500    _aFor piano, vibraphone, drums, and double bass.
505 0  _aLewis, J. Django.--Lewis, J. Plastic dreams (music from the film Kemek).--Lewis, J. Dancing (music from the film Kemek).--Lewis, J. Blues in A minor.--Lewis, J. Blues in B♭.--Lewis, J. Precious joy.--Jackson, M. The martyr.--Jackson, M. The legendary profile.
650  0 _vExcerpts
       _vScores.
700 12 _aLewis, John,
       _d1920-
       _tSelections.
       _f1977.
700 12 _aJackson, Milt.
       _tMartyrs.
       _f1977.
700 12 _aJackson, Milt.
       _tLegendary profile.
       _f1977.
740 4  _aThe legendary profile.
852 00 _bMUSIC
       _cMAIN
       _kfolio
       _hM1366
       _iM62
       _91
       _4Marvin Duchow Music
       _5

Next record:
LDR 01293cjm  2200289 a 4500
001     001878039
005     20050110174900.0
007     sd fungnn|||e|
008     940202r19931981nyujzn   i              d
024 1  _a7464573372
028 02 _aJK 57337
       _bRed Baron
035    _a(OCoLC)29737267
040    _aSVP
       _cSVP
       _dLGG
100 1  _aDesmond, Paul,
       _d1924-
245 10 _aPaul Desmond & the Modern Jazz Quartet
       _h[sound recording]
260    _aNew York, N.Y. :
       _bRed Baron :
       _bManufactured by Sony Music Entertainment,
       _cp1993.
300    _a1 sound disc (39 min.) :
       _bdigital ;
       _c4 3/4 in.
511 0  _aPaul Desmond, alto saxophone; Modern Jazz Quartet: John Lewis, piano; Milt Jackson, vibraphone; Percy Heath, bass; Connie Kay, drums.
500    _aAll arrangements by John Lewis.
518    _aRecorded live on December 25, 1971 at Town Hall, NYC.
500    _aOriginally released in 1981 by Finesse as LP FW 27487.
500    _aProgram notes by Irving Townsend, June 1981, on container insert.
505 0  _aGreensleeves -- You go to my head -- Blue dove -- Jesus Christ Superstar -- Here's that rainy day -- East of the sun -- Bags' new groove.
650  0 _y1971-1980.
700 1  _aLewis, John,
       _d1920-
710 2  _aModern Jazz Quartet.
740 0  _aPaul Desmond and the Modern Jazz Quartet.

Next record:
LDR 01829cjm  2200385 a 4500
001     001964482
005     20060626132700.0
007     sd fzngnn|m|e|
008     871211p19871957nyujzn                  d
024 1  _a4228332902
028 01 _a833 290-2
       _bVerve
033 0  _a19571027
       _b6299
       _cD56
033 0  _a196112--
       _b3804
       _cN4
033 0  _a19571019
       _b4104
       _cC6
033 0  _a197107--
       _b6299
       _cV7
035    _a(OCoLC)17222092
040    _aCPL
       _cCPL
       _dOCL
       _dLGG
048    _apz01
       _aka01
       _asd01
       _apd01
110 2  _aModern Jazz Quartet.
       _4prf
245 14 _aThe Modern Jazz Quartet plus
       _h[sound recording].
260    _a[New York] :
       _bVerve,
       _cp1987.
300    _a1 sound disc :
       _bdigital ;
       _c4 3/4 in.
440  0 _aCompact jazz
511 0  _aModern Jazz Quartet (principally) ; Milt Jackson, vibraphone (2nd and 8th works) ; Oscar Peterson, piano (2nd and 8th works) ; Ray Brown, bass (2nd and 8th works) ; Ed Thigpen (2nd work), Louis Hayes (8th work), drums.
518    _aRecorded live, Oct. 27, 1957, at the Donaueschingen Jazz Festival (1st, 5th, 7th, and 10th works); Dec. 1961, in New York (2nd work); live, Oct. 19, 1957, at the Opera House, Chicago (3rd, 4th, 6th, and 9th works); July 1971, in Villingen, Germany (8th work).
500    _aCompact disc.
500    _aAnalog recording.
505 0  _aThe golden striker (4:08) -- On Green Dolphin Street (7:28) -- D & E (4:55) -- I'll remember April (4:51) -- Cortège (7:15) -- Now's the time (4:43) -- J.B. blues (5:09) -- Reunion blues (6:35) -- 'Round midnight (3:56) -- Three windows (7:20).
700 1  _aJackson, Milt.
       _4prf
700 1  _aPeterson, Oscar,
       _d1925-
       _4prf
700 1  _aBrown, Ray,
       _d1926-2002.
       _4prf
700 1  _aThigpen, Ed.
       _4prf
700 1  _aHayes, Louis,
       _d1937-
       _4prf
852 80 _bMUSIC
       _cAV
       _hCD 1131
       _4Marvin Duchow Music
       _5Audio-Visual
PK��Z�jS�"test/File_MARC/tests/marc_015.phptnu�[���--TEST--
marc_015: ensure that pandemonium does not occur if a record doesn't have a given field
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';
$marc_file = new File_MARC($dir . '/' . 'music.mrc');

while ($marc_record = $marc_file->next()) {

  // Record #2 doesn't contain an 852; getField() returns false
  $mfhd = $marc_record->getField('852');
  if ($mfhd) {
    $mfhd = $mfhd->getSubfield('b');
  }

  print $marc_record;
  print "\n";
}
?>
--EXPECT--
LDR 01145ncm  2200277 i 4500
001     000073594
004     AAJ5802
005     20030415102100.0
008     801107s1977    nyujza                   
010    _a   77771106 
035    _a(CaOTUIC)15460184
035 9  _aAAJ5802
040    _aLC
050 00 _aM1366
       _b.M62
       _dM1527.2
245 04 _aThe Modern Jazz Quartet :
       _bThe legendary profile. --
260    _aNew York :
       _bM.J.Q. Music,
       _cc1977.
300    _ascore (72 p.) ;
       _c31 cm.
500    _aFor piano, vibraphone, drums, and double bass.
505 0  _aLewis, J. Django.--Lewis, J. Plastic dreams (music from the film Kemek).--Lewis, J. Dancing (music from the film Kemek).--Lewis, J. Blues in A minor.--Lewis, J. Blues in B♭.--Lewis, J. Precious joy.--Jackson, M. The martyr.--Jackson, M. The legendary profile.
650  0 _aJazz.
650  0 _aMotion picture music
       _vExcerpts
       _vScores.
700 12 _aLewis, John,
       _d1920-
       _tSelections.
       _f1977.
700 12 _aJackson, Milt.
       _tMartyrs.
       _f1977.
700 12 _aJackson, Milt.
       _tLegendary profile.
       _f1977.
740 4  _aThe legendary profile.
852 00 _bMUSIC
       _cMAIN
       _kfolio
       _hM1366
       _iM62
       _91
       _4Marvin Duchow Music
       _5

LDR 01293cjm  2200289 a 4500
001     001878039
005     20050110174900.0
007     sd fungnn|||e|
008     940202r19931981nyujzn   i              d
024 1  _a7464573372
028 02 _aJK 57337
       _bRed Baron
035    _a(OCoLC)29737267
040    _aSVP
       _cSVP
       _dLGG
100 1  _aDesmond, Paul,
       _d1924-
245 10 _aPaul Desmond & the Modern Jazz Quartet
       _h[sound recording]
260    _aNew York, N.Y. :
       _bRed Baron :
       _bManufactured by Sony Music Entertainment,
       _cp1993.
300    _a1 sound disc (39 min.) :
       _bdigital ;
       _c4 3/4 in.
511 0  _aPaul Desmond, alto saxophone; Modern Jazz Quartet: John Lewis, piano; Milt Jackson, vibraphone; Percy Heath, bass; Connie Kay, drums.
500    _aAll arrangements by John Lewis.
518    _aRecorded live on December 25, 1971 at Town Hall, NYC.
500    _aOriginally released in 1981 by Finesse as LP FW 27487.
500    _aProgram notes by Irving Townsend, June 1981, on container insert.
505 0  _aGreensleeves -- You go to my head -- Blue dove -- Jesus Christ Superstar -- Here's that rainy day -- East of the sun -- Bags' new groove.
650  0 _aJazz
       _y1971-1980.
700 1  _aLewis, John,
       _d1920-
710 2  _aModern Jazz Quartet.
740 0  _aPaul Desmond and the Modern Jazz Quartet.

LDR 01829cjm  2200385 a 4500
001     001964482
005     20060626132700.0
007     sd fzngnn|m|e|
008     871211p19871957nyujzn                  d
024 1  _a4228332902
028 01 _a833 290-2
       _bVerve
033 0  _a19571027
       _b6299
       _cD56
033 0  _a196112--
       _b3804
       _cN4
033 0  _a19571019
       _b4104
       _cC6
033 0  _a197107--
       _b6299
       _cV7
035    _a(OCoLC)17222092
040    _aCPL
       _cCPL
       _dOCL
       _dLGG
048    _apz01
       _aka01
       _asd01
       _apd01
110 2  _aModern Jazz Quartet.
       _4prf
245 14 _aThe Modern Jazz Quartet plus
       _h[sound recording].
260    _a[New York] :
       _bVerve,
       _cp1987.
300    _a1 sound disc :
       _bdigital ;
       _c4 3/4 in.
440  0 _aCompact jazz
511 0  _aModern Jazz Quartet (principally) ; Milt Jackson, vibraphone (2nd and 8th works) ; Oscar Peterson, piano (2nd and 8th works) ; Ray Brown, bass (2nd and 8th works) ; Ed Thigpen (2nd work), Louis Hayes (8th work), drums.
518    _aRecorded live, Oct. 27, 1957, at the Donaueschingen Jazz Festival (1st, 5th, 7th, and 10th works); Dec. 1961, in New York (2nd work); live, Oct. 19, 1957, at the Opera House, Chicago (3rd, 4th, 6th, and 9th works); July 1971, in Villingen, Germany (8th work).
500    _aCompact disc.
500    _aAnalog recording.
505 0  _aThe golden striker (4:08) -- On Green Dolphin Street (7:28) -- D & E (4:55) -- I'll remember April (4:51) -- Cortège (7:15) -- Now's the time (4:43) -- J.B. blues (5:09) -- Reunion blues (6:35) -- 'Round midnight (3:56) -- Three windows (7:20).
650  0 _aJazz.
700 1  _aJackson, Milt.
       _4prf
700 1  _aPeterson, Oscar,
       _d1925-
       _4prf
700 1  _aBrown, Ray,
       _d1926-2002.
       _4prf
700 1  _aThigpen, Ed.
       _4prf
700 1  _aHayes, Louis,
       _d1937-
       _4prf
852 80 _bMUSIC
       _cAV
       _hCD 1131
       _4Marvin Duchow Music
       _5Audio-Visual
PK��Z7�"test/File_MARC/tests/marc_009.phptnu�[���--TEST--
marc_009: Parse a record where leader record length != real record length
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';
$marc_file = new File_MARC($dir . '/' . 'wronglen.mrc');

while ($marc_record = $marc_file->next()) {
  print $marc_record;
  print "\n";
  print "WARNINGS:\n";
  foreach ($marc_record->getWarnings() as $warning) {
    print "  * $warning\n";
  }
}
?>
--EXPECT--
LDR 00727nam  2200205 a 4500
001     03-0016458
005     19971103184734.0
008     970701s1997    oru          u000 0 eng u
035    _a(Sirsi) a351664
050 00 _aML270.2
       _b.A6 1997
100 1  _aAnthony, James R.
245 00 _aFrench baroque music from Beaujoyeulx to Rameau
250    _aRev. and expanded ed.
260    _aPortland, OR :
       _bAmadeus Press,
       _c1997.
300    _a586 p. :
       _bmusic
650  0 _aMusic
       _<France
       _y16th century
       _xHistory and criticism.
650  0 _aMusic
       _zFrance
       _y17th century
       _xHistory and criticism.
650  0 _aMusic
       _zFrance
       _y18th century
       _xHistory and criticism.
949    _aML 270.2 A6 1997
       _wLC
       _i30007006841505
       _rY
       _tBOOKS
       _lHUNT-CIRC
       _mHUNEXTRALON

WARNINGS:
  * Invalid record length: Leader says "00727" bytes; actual record length is "741"
  * Field for tag "949" does not end with an end of field character
  * Field for tag "596" does not end with an end of field character
  * Invalid indicators "GSTUFF" forced to blanks for tag "596"
PK��Z(Y����"test/File_MARC/tests/xmlescape.mrcnu�[���00727nam  2200205 a 450000100110000000500170001100800410002803500200006905000220008910000220011124500520013325000260018526000420021130000200025365000560027365000560032965000560038594900740044159600060051503-001645819971103184734.0970701s1997    oru          u000 0 eng u  a(Sirsi) a35166400aML270.2b.A6 19971 aAnthony, James R.00aFrench baroque music from Beaujoyeulx to Rameau  aRev. and expanded ed.  aPortland, OR :bAmadeus Press,c1997.  a586 p. :bmusic 0aMusic<Francey16th centuryxHistory and criticism. 0aMusiczFrancey17th centuryxHistory and criticism. 0aMusiczFrancey18th centuryxHistory and criticism.  aML 270.2 A6 1997wLCi30007006841505rYtBOOKSlHUNT-CIRCmHUNTINGTON  a1
PK��Z�2�.ii"test/File_MARC/tests/marc_018.phptnu�[���--TEST--
marc_018: iterate and print a MARC record to JSON MARC-HASH format
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';
$marc_file = new File_MARC($dir . '/' . 'example.mrc');

while ($marc_record = $marc_file->next()) {
  print $marc_record->toJSONHash();
  print "\n";
}
?>
--EXPECT--
{"type":"marc-hash","version":[1,0],"leader":"01850     2200517   4500","fields":[["001","0000000044"],["003","EMILDA"],["008","980120s1998    fi     j      000 0 swe"],["020"," "," ",[["a","9515008808"],["c","FIM 72:00"]]],["035"," "," ",[["9","9515008808"]]],["040"," "," ",[["a","NB"]]],["042"," "," ",[["9","NB"],["9","SEE"]]],["084"," "," ",[["a","Hcd,u"],["2","kssb\/6"]]],["084"," "," ",[["5","NB"],["a","uHc"],["2","kssb"]]],["084"," "," ",[["5","SEE"],["a","Hcf"],["2","kssb\/6"]]],["084"," "," ",[["5","Q"],["a","Hcd,uf"],["2","kssb\/6"]]],["100","1"," ",[["a","Jansson, Tove,"],["d","1914-2001"]]],["245","0","4",[["a","Det osynliga barnet och andra ber\u00e4ttelser \/"],["c","Tove Jansson"]]],["250"," "," ",[["a","7. uppl."]]],["260"," "," ",[["a","Helsingfors :"],["b","Schildt,"],["c","1998 ;"],["e","(Falun :"],["f","Scandbook)"]]],["300"," "," ",[["a","166, [4] s. :"],["b","ill. ;"],["c","21 cm"]]],["440"," ","0",[["a","Mumin-biblioteket,"],["x","99-0698931-9"]]],["500"," "," ",[["a","Originaluppl. 1962"]]],["599"," "," ",[["a","Li: S"]]],["740","4"," ",[["a","Det osynliga barnet"]]],["775","1"," ",[["z","951-50-0385-7"],["w","9515003857"],["9","07"]]],["841"," "," ",[["5","Li"],["a","xa"],["b","0201080u    0   4000uu   |000000"],["e","1"]]],["841"," "," ",[["5","SEE"],["a","xa"],["b","0201080u    0   4000uu   |000000"],["e","1"]]],["841"," "," ",[["5","L"],["a","xa"],["b","0201080u    0   4000uu   |000000"],["e","1"]]],["841"," "," ",[["5","NB"],["a","xa"],["b","0201080u    0   4000uu   |000000"],["e","1"]]],["841"," "," ",[["5","Q"],["a","xa"],["b","0201080u    0   4000uu   |000000"],["e","1"]]],["841"," "," ",[["5","S"],["a","xa"],["b","0201080u    0   4000uu   |000000"],["e","1"]]],["852"," "," ",[["5","NB"],["b","NB"],["c","NB98:12"],["h","plikt"],["j","R, 980520"]]],["852"," "," ",[["5","Li"],["b","Li"],["c","CNB"],["h","h,u"]]],["852"," "," ",[["5","SEE"],["b","SEE"]]],["852"," "," ",[["5","Q"],["b","Q"],["j","98947"]]],["852"," "," ",[["5","L"],["b","L"],["c","0100"],["h","98\/"],["j","3043 H"]]],["852"," "," ",[["5","S"],["b","S"],["h","Sv97"],["j","7235"]]],["900","1","s",[["a","Yanson, Tobe,"],["d","1914-2001"],["u","Jansson, Tove,"],["d","1914-2001"]]],["900","1","s",[["a","Janssonov\u00e1, Tove,"],["d","1914-2001"],["u","Jansson, Tove,"],["d","1914-2001"]]],["900","1","s",[["a","Jansone, Tuve,"],["d","1914-2001"],["u","Jansson, Tove,"],["d","1914-2001"]]],["900","1","s",[["a","Janson, Tuve,"],["d","1914-2001"],["u","Jansson, Tove,"],["d","1914-2001"]]],["900","1","s",[["a","Jansson, Tuve,"],["d","1914-2001"],["u","Jansson, Tove,"],["d","1914-2001"]]],["900","1","s",[["a","Janssonova, Tove,"],["d","1914-2001"],["u","Jansson, Tove,"],["d","1914-2001"]]],["976"," ","2",[["a","Hcd,u"],["b","Sk\u00f6nlitteratur"]]],["005","20050204111518.0"]]}
PK��Z8��11)test/File_MARC/tests/marc_record_001.phptnu�[���--TEST--
marc_record_001: create a MARC record from scratch
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';
$marc = new File_MARC_Record();

$marc->appendField(new File_MARC_Data_Field('245', array(
        new File_MARC_Subfield('a', 'Main title: '),
        new File_MARC_Subfield('b', 'subtitle'),
        new File_MARC_Subfield('c', 'author')
    ), null, null
));

print $marc;

?>
--EXPECT--
LDR                         
245    _aMain title: 
       _bsubtitle
       _cauthor
PK��Z2���test/File_MARC/tests/skipif.incnu�[���<?php

// Stash the current error_reporting value
$error_reporting = error_reporting();

// Restore the error reporting to previous value
error_reporting($error_reporting);

?>
PK��Z\.i�vv!test/File_MARC/tests/sandburg.mrcnu�[���01142cam  2200301 a 4500001001300000003000400013005001700017008004100034010001700075020002500092040001800117042000900135050002600144082001600170100003200186245008600218250001200304260005200316300004900368500004000417520022800457650003300685650003300718650002400751650002100775650002300796700002100819   92005291 DLC19930521155141.9920219s1993    caua   j      000 0 eng    a   92005291   a0152038655 :c$15.95  aDLCcDLCdDLC  alcac00aPS3537.A618bA88 199300a811/.522201 aSandburg, Carl,d1878-1967.10aArithmetic /cCarl Sandburg ; illustrated as an anamorphic adventure by Ted Rand.  a1st ed.  aSan Diego :bHarcourt Brace Jovanovich,cc1993.  a1 v. (unpaged) :bill. (some col.) ;c26 cm.  aOne Mylar sheet included in pocket.  aA poem about numbers and their characteristics. Features anamorphic, or distorted, drawings which can be restored to normal by viewing from a particular angle or by viewing the image's reflection in the provided Mylar cone. 0aArithmeticxJuvenile poetry. 0aChildren's poetry, American. 1aArithmeticxPoetry. 1aAmerican poetry. 1aVisual perception.1 aRand, Ted,eill.PK��Z#c����"test/File_MARC/tests/onerecord.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
 <record xmlns="http://www.loc.gov/MARC21/slim">
  <leader>01142cam  2200301 a 4500</leader>
  <controlfield tag="001">   92005291 </controlfield>
  <controlfield tag="003">DLC</controlfield>
  <controlfield tag="005">19930521155141.9</controlfield>
  <controlfield tag="008">920219s1993    caua   j      000 0 eng  </controlfield>
  <datafield tag="010" ind1=" " ind2=" ">
   <subfield code="a">   92005291 </subfield>
  </datafield>
  <datafield tag="020" ind1=" " ind2=" ">
   <subfield code="a">0152038655 :</subfield>
   <subfield code="c">$15.95</subfield>
  </datafield>
  <datafield tag="040" ind1=" " ind2=" ">
   <subfield code="a">DLC</subfield>
   <subfield code="c">DLC</subfield>
   <subfield code="d">DLC</subfield>
  </datafield>
  <datafield tag="042" ind1=" " ind2=" ">
   <subfield code="a">lcac</subfield>
  </datafield>
  <datafield tag="050" ind1="0" ind2="0">
   <subfield code="a">PS3537.A618</subfield>
   <subfield code="b">A88 1993</subfield>
  </datafield>
  <datafield tag="082" ind1="0" ind2="0">
   <subfield code="a">811/.52</subfield>
   <subfield code="2">20</subfield>
  </datafield>
  <datafield tag="100" ind1="1" ind2=" ">
   <subfield code="a">Sandburg, Carl,</subfield>
   <subfield code="d">1878-1967.</subfield>
  </datafield>
  <datafield tag="245" ind1="1" ind2="0">
   <subfield code="a">Arithmetic /</subfield>
   <subfield code="c">Carl Sandburg ; illustrated as an anamorphic adventure by Ted Rand.</subfield>
  </datafield>
  <datafield tag="250" ind1=" " ind2=" ">
   <subfield code="a">1st ed.</subfield>
  </datafield>
  <datafield tag="260" ind1=" " ind2=" ">
   <subfield code="a">San Diego :</subfield>
   <subfield code="b">Harcourt Brace Jovanovich,</subfield>
   <subfield code="c">c1993.</subfield>
  </datafield>
  <datafield tag="300" ind1=" " ind2=" ">
   <subfield code="a">1 v. (unpaged) :</subfield>
   <subfield code="b">ill. (some col.) ;</subfield>
   <subfield code="c">26 cm.</subfield>
  </datafield>
  <datafield tag="500" ind1=" " ind2=" ">
   <subfield code="a">One Mylar sheet included in pocket.</subfield>
  </datafield>
  <datafield tag="520" ind1=" " ind2=" ">
   <subfield code="a">A poem about numbers and their characteristics. Features anamorphic, or distorted, drawings which can be restored to normal by viewing from a particular angle or by viewing the image's reflection in the provided Mylar cone.</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="0">
   <subfield code="a">Arithmetic</subfield>
   <subfield code="x">Juvenile poetry.</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="0">
   <subfield code="a">Children's poetry, American.</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="1">
   <subfield code="a">Arithmetic</subfield>
   <subfield code="x">Poetry.</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="1">
   <subfield code="a">American poetry.</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="1">
   <subfield code="a">Visual perception.</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2=" ">
   <subfield code="a">Rand, Ted,</subfield>
   <subfield code="e">ill.</subfield>
  </datafield>
 </record>
PK��Z�_X���(test/File_MARC/tests/marc_field_004.phptnu�[���--TEST--
marc_field_004: Add subfields to an existing field (corner case)
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';

// create some subfields
$subfields[] = new File_MARC_Subfield('a', 'nothing');
$subfields[] = new File_MARC_Subfield('z', 'everything');

// create a field
$field = new File_MARC_Data_Field('100', $subfields, '0');

// create some new subfields
$subfield1 = new File_MARC_Subfield('g', 'a little');

// test the fieldpost corner case by inserting prior to the first subfield
$sf = $field->getSubfields('a');
// we might get an array back; in this case, we want the first subfield
if (is_array($sf)) {
  $field->insertSubfield($subfield1, $sf[0], true);
}
else {
  $field->insertSubfield($subfield1, $sf, true);
}

// let's see the results
print $field;
print "\n";

?>
--EXPECT--
100 0  _ga little
       _anothing
       _zeverything
PK��Z.%�``"test/File_MARC/tests/marc_010.phptnu�[���--TEST--
marc_010: iterate and pretty print MARC records from a stream
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';

$marc_file = new File_MARC("compress.zlib://$dir/compressed.mrc.gz");

while ($marc_record = $marc_file->next()) {
  print $marc_record;
  print "\n";
}
?>
--EXPECT--
LDR 01145ncm  2200277 i 4500
001     000073594
004     AAJ5802
005     20030415102100.0
008     801107s1977    nyujza                   
010    _a   77771106 
035    _a(CaOTUIC)15460184
035 9  _aAAJ5802
040    _aLC
050 00 _aM1366
       _b.M62
       _dM1527.2
245 04 _aThe Modern Jazz Quartet :
       _bThe legendary profile. --
260    _aNew York :
       _bM.J.Q. Music,
       _cc1977.
300    _ascore (72 p.) ;
       _c31 cm.
500    _aFor piano, vibraphone, drums, and double bass.
505 0  _aLewis, J. Django.--Lewis, J. Plastic dreams (music from the film Kemek).--Lewis, J. Dancing (music from the film Kemek).--Lewis, J. Blues in A minor.--Lewis, J. Blues in B♭.--Lewis, J. Precious joy.--Jackson, M. The martyr.--Jackson, M. The legendary profile.
650  0 _aJazz.
650  0 _aMotion picture music
       _vExcerpts
       _vScores.
700 12 _aLewis, John,
       _d1920-
       _tSelections.
       _f1977.
700 12 _aJackson, Milt.
       _tMartyrs.
       _f1977.
700 12 _aJackson, Milt.
       _tLegendary profile.
       _f1977.
740 4  _aThe legendary profile.
852 00 _bMUSIC
       _cMAIN
       _kfolio
       _hM1366
       _iM62
       _91
       _4Marvin Duchow Music
       _5

LDR 01293cjm  2200289 a 4500
001     001878039
005     20050110174900.0
007     sd fungnn|||e|
008     940202r19931981nyujzn   i              d
024 1  _a7464573372
028 02 _aJK 57337
       _bRed Baron
035    _a(OCoLC)29737267
040    _aSVP
       _cSVP
       _dLGG
100 1  _aDesmond, Paul,
       _d1924-
245 10 _aPaul Desmond & the Modern Jazz Quartet
       _h[sound recording]
260    _aNew York, N.Y. :
       _bRed Baron :
       _bManufactured by Sony Music Entertainment,
       _cp1993.
300    _a1 sound disc (39 min.) :
       _bdigital ;
       _c4 3/4 in.
511 0  _aPaul Desmond, alto saxophone; Modern Jazz Quartet: John Lewis, piano; Milt Jackson, vibraphone; Percy Heath, bass; Connie Kay, drums.
500    _aAll arrangements by John Lewis.
518    _aRecorded live on December 25, 1971 at Town Hall, NYC.
500    _aOriginally released in 1981 by Finesse as LP FW 27487.
500    _aProgram notes by Irving Townsend, June 1981, on container insert.
505 0  _aGreensleeves -- You go to my head -- Blue dove -- Jesus Christ Superstar -- Here's that rainy day -- East of the sun -- Bags' new groove.
650  0 _aJazz
       _y1971-1980.
700 1  _aLewis, John,
       _d1920-
710 2  _aModern Jazz Quartet.
740 0  _aPaul Desmond and the Modern Jazz Quartet.

LDR 01829cjm  2200385 a 4500
001     001964482
005     20060626132700.0
007     sd fzngnn|m|e|
008     871211p19871957nyujzn                  d
024 1  _a4228332902
028 01 _a833 290-2
       _bVerve
033 0  _a19571027
       _b6299
       _cD56
033 0  _a196112--
       _b3804
       _cN4
033 0  _a19571019
       _b4104
       _cC6
033 0  _a197107--
       _b6299
       _cV7
035    _a(OCoLC)17222092
040    _aCPL
       _cCPL
       _dOCL
       _dLGG
048    _apz01
       _aka01
       _asd01
       _apd01
110 2  _aModern Jazz Quartet.
       _4prf
245 14 _aThe Modern Jazz Quartet plus
       _h[sound recording].
260    _a[New York] :
       _bVerve,
       _cp1987.
300    _a1 sound disc :
       _bdigital ;
       _c4 3/4 in.
440  0 _aCompact jazz
511 0  _aModern Jazz Quartet (principally) ; Milt Jackson, vibraphone (2nd and 8th works) ; Oscar Peterson, piano (2nd and 8th works) ; Ray Brown, bass (2nd and 8th works) ; Ed Thigpen (2nd work), Louis Hayes (8th work), drums.
518    _aRecorded live, Oct. 27, 1957, at the Donaueschingen Jazz Festival (1st, 5th, 7th, and 10th works); Dec. 1961, in New York (2nd work); live, Oct. 19, 1957, at the Opera House, Chicago (3rd, 4th, 6th, and 9th works); July 1971, in Villingen, Germany (8th work).
500    _aCompact disc.
500    _aAnalog recording.
505 0  _aThe golden striker (4:08) -- On Green Dolphin Street (7:28) -- D & E (4:55) -- I'll remember April (4:51) -- Cortège (7:15) -- Now's the time (4:43) -- J.B. blues (5:09) -- Reunion blues (6:35) -- 'Round midnight (3:56) -- Three windows (7:20).
650  0 _aJazz.
700 1  _aJackson, Milt.
       _4prf
700 1  _aPeterson, Oscar,
       _d1925-
       _4prf
700 1  _aBrown, Ray,
       _d1926-2002.
       _4prf
700 1  _aThigpen, Ed.
       _4prf
700 1  _aHayes, Louis,
       _d1937-
       _4prf
852 80 _bMUSIC
       _cAV
       _hCD 1131
       _4Marvin Duchow Music
       _5Audio-Visual
PK��ZB�1��
�
'test/File_MARC/tests/marc_lint_005.phptnu�[���--TEST--
marc_lint_005: Tests check_020() called separately
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
<?php include('tests/skipif_noispn.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';

// Create test harness to allow direct calls to check methods:
class File_MARC_Lint_Test_Harness extends File_MARC_Lint
{
    public function check020($field)
    {
        return parent::check020($field);
    }

    // override warn method to echo instead of store in object:
    protected function warn($msg)
    {
        echo $msg . "\n";
    }
}

$marc_lint = new File_MARC_Lint_Test_Harness();

$testData = array(
    array('a' => "154879473"), //too few digits
    array('a' => "1548794743"), //invalid checksum
    array('a' => "15487947443"), //11 digits
    array('a' => "15487947443324"), //14 digits
    array('a' => "9781548794743"), //13 digit valid
    array('a' => "9781548794745"), //13 digit invalid
    array('a' => "1548794740 (10 : good checksum)"), //10 digit valid with qualifier
    array('a' => "1548794745 (10 : bad checksum)"), //10 digit invalid with qualifier
    array('a' => "1-54879-474-0 (hyphens and good checksum)"), //10 digit invalid with hyphens and qualifier
    array('a' => "1-54879-474-5 (hyphens and bad checksum)"), //10 digit invalid with hyphens and qualifier
    array('a' => "1548794740(10 : unspaced qualifier)"), //10 valid without space before qualifier
    array('a' => "1548794745(10 : unspaced qualifier : bad checksum)"), //10 invalid without space before qualifier
    array('z' => "1548794743"), //subfield z
);

foreach ($testData as $current) {
    $subfields = array();
    foreach ($current as $key => $value) {
        $subfields[] = new File_MARC_Subfield($key, $value);
    }
    $field = new File_MARC_Data_Field('020', $subfields, '', '');
    $marc_lint->check020($field);
}

?>
--EXPECT--
020: Subfield a has the wrong number of digits, 154879473.
020: Subfield a has bad checksum, 1548794743.
020: Subfield a has the wrong number of digits, 15487947443.
020: Subfield a has the wrong number of digits, 15487947443324.
020: Subfield a has bad checksum (13 digit), 9781548794745.
020: Subfield a has bad checksum, 1548794745 (10 : bad checksum).
020: Subfield a may have invalid characters.
020: Subfield a may have invalid characters.
020: Subfield a has bad checksum, 1-54879-474-5 (hyphens and bad checksum).
020: Subfield a qualifier must be preceded by space, 1548794740(10 : unspaced qualifier).
020: Subfield a qualifier must be preceded by space, 1548794745(10 : unspaced qualifier : bad checksum).
020: Subfield a has bad checksum, 1548794745(10 : unspaced qualifier : bad checksum).
PK��Zye@��&test/File_MARC/tests/marc_xml_007.phptnu�[���--TEST--
marc_xml_007: test getTag(), isControlField(), and isDataField() convenience methods on MARCXML
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';
$marc_file = new File_MARCXML($dir . '/' . 'bigarchive.xml');

while ($marc_record = $marc_file->next()) {
  $fields = $marc_record->getFields();
  foreach ($fields as $field) {
    print $field->getTag();
    if ($field->isControlField()) {
      print "\tControl field!";
    }
    if ($field->isDataField()) {
      print "\tData field!";
    }
    print "\n";
  }
}

?>
--EXPECT--
001	Control field!
003	Control field!
005	Control field!
006	Control field!
007	Control field!
008	Control field!
037	Data field!
040	Data field!
245	Data field!
246	Data field!
260	Data field!
300	Data field!
500	Data field!
500	Data field!
500	Data field!
510	Data field!
510	Data field!
533	Data field!
651	Data field!
830	Data field!
856	Data field!
909	Data field!
PK��Z�����"test/File_MARC/tests/marc_008.phptnu�[���--TEST--
marc_008: Attempt to open a file that does not exist
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';

try {
    $marc_file = new File_MARC('super_bogus_file');
}
catch (File_MARC_Exception $fme) {
    print $fme->getMessage();
}

?>
--EXPECTF--
Warning: fopen(super_bogus_file): failed to open stream: No such file or directory in %sMARC.php on line %d
Invalid input file "super_bogus_file"
PK��Z+W��
�
#test/File_MARC/tests/bigarchive.xmlnu�[���<?xml version="1.0"?>
<record xmlns="http://www.loc.gov/MARC21/slim"><leader>00000nam  2200277   4500</leader><controlfield tag="001">99865026e</controlfield><controlfield tag="003">UnM</controlfield><controlfield tag="005">19961010163452.0</controlfield><controlfield tag="006">m    g   d</controlfield><controlfield tag="007">cr bn |||a|bb|</controlfield><controlfield tag="008">940112s1649    enk     s     00| | eng d</controlfield><datafield tag="037" ind1=" " ind2=" "><subfield code="a">CL0051000003</subfield><subfield code="b">ProQuest Information and Learning. 300 N. Zeeb Rd., Ann Arbor, MI 48106</subfield></datafield><datafield tag="040" ind1=" " ind2=" "><subfield code="a">Cu-RivES</subfield><subfield code="c">Cu-RivES</subfield><subfield code="d">CStRLIN</subfield><subfield code="e">dcrb</subfield><subfield code="d">WaOLN</subfield></datafield><datafield tag="245" ind1="0" ind2="4"><subfield code="a">The VVelsh embassador, or the happy newes his vvorship hath brought to London.</subfield><subfield code="h">[electronic resource] :</subfield><subfield code="b">Togetherwith her thirteen articles of acreements, which her propounds to all her cousens in her principality of Wales,and her Cities of London.</subfield></datafield><datafield tag="246" ind1="2" ind2=" "><subfield code="a">Happy newes his vvorship hath brought to London</subfield></datafield><datafield tag="260" ind1=" " ind2=" "><subfield code="a">[London] :</subfield><subfield code="b">Printed for George Roberts, and are to be soldat the Maiden Head on Snow-Hill neer Holborn Conduit,</subfield><subfield code="c">1649.</subfield></datafield><datafield tag="300" ind1=" " ind2=" "><subfield code="a">[2], 6 p.</subfield></datafield><datafield tag="500" ind1=" " ind2=" "><subfield code="a">Place of publication from Wing.</subfield></datafield><datafield tag="500" ind1=" " ind2=" "><subfield code="a">Annotation on Thomason copy: "May 4th".</subfield></datafield><datafield tag="500" ind1=" " ind2=" "><subfield code="a">Reproduction of the original in the British Library.</subfield></datafield><datafield tag="510" ind1="4" ind2=" "><subfield code="a">Wing (2nd ed.)</subfield><subfield code="c">W1315.</subfield></datafield><datafield tag="510" ind1="4" ind2=" "><subfield code="a">Thomason</subfield><subfield code="c">E.552[19].</subfield></datafield><datafield tag="533" ind1=" " ind2=" "><subfield code="a">Electronic reproduction.</subfield><subfield code="b">Ann Arbor, Mich. :</subfield><subfield code="c">UMI,</subfield><subfield code="d">1999-</subfield><subfield code="f">(Early English books online)</subfield><subfield code="n">Digital version of: (Thomason Tracts ; 85:E552[19])</subfield><subfield code="7">s1999    miun s</subfield></datafield><datafield tag="651" ind1=" " ind2="4"><subfield code="a">Great Britain</subfield><subfield code="x">Politics and government</subfield><subfield code="y">1642-1649</subfield><subfield code="v">Early works to 1800.</subfield></datafield><datafield tag="830" ind1=" " ind2="0"><subfield code="a">Early English books online.</subfield></datafield><datafield tag="856" ind1="4" ind2="0"><subfield code="z">E-book (Onsite access at NYPL Research Libraries)</subfield><subfield code="u">http://gateway.proquest.com/openurl?ctx_ver=Z39.88-2003&amp;res_id=xri:eebo&amp;rft_val_fmt=&amp;rft_id=xri:eebo:image:117259</subfield></datafield><datafield tag="909" ind1=" " ind2=" "><subfield code="a">Not for export in OCLC Reclamation Project</subfield></datafield></record>
PK��Z��ԛ�
�
"test/File_MARC/tests/marc_014.phptnu�[���--TEST--
marc_014: Add fields to a MARC record
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';

// Get ourselves a MARC record
$marc_file = new File_MARC($dir . '/' . 'example.mrc');
$marc_record = $marc_file->next();

// create some subfields
$subfields[] = new File_MARC_Subfield('a', 'nothing');
$subfields[] = new File_MARC_Subfield('z', 'everything');

// create a data field
$data_field = new File_MARC_Data_Field('100', $subfields, '0');

// append the data field
$marc_record->appendField($data_field);

// create a control field
$ctrl_field = new File_MARC_Control_Field('001', '01234567890');

// prepend the control field
$marc_record->prependField($ctrl_field);

// reproduce test case reported by Mark Jordan
$subfields_966_2[] = new File_MARC_Subfield('l', 'web');
$subfields_966_2[] = new File_MARC_Subfield('r', '0');
$subfields_966_2[] = new File_MARC_Subfield('s', 'b');
$subfields_966_2[] = new File_MARC_Subfield('i', '49');
$subfields_966_2[] = new File_MARC_Subfield('c', '1');
$field_966_2 = new File_MARC_Data_Field('966', $subfields_966_2, null, null);
$marc_record->appendField($field_966_2);

// let's see the results
print utf8_encode($marc_record);
print "\n";

?>
--EXPECT--
LDR 01850     2200517   4500
001     01234567890
001     0000000044
003     EMILDA
008     980120s1998    fi     j      000 0 swe
020    _a9515008808
       _cFIM 72:00
035    _99515008808
040    _aNB
042    _9NB
       _9SEE
084    _aHcd,u
       _2kssb/6
084    _5NB
       _auHc
       _2kssb
084    _5SEE
       _aHcf
       _2kssb/6
084    _5Q
       _aHcd,uf
       _2kssb/6
100 1  _aJansson, Tove,
       _d1914-2001
245 04 _aDet osynliga barnet och andra berättelser /
       _cTove Jansson
250    _a7. uppl.
260    _aHelsingfors :
       _bSchildt,
       _c1998 ;
       _e(Falun :
       _fScandbook)
300    _a166, [4] s. :
       _bill. ;
       _c21 cm
440  0 _aMumin-biblioteket,
       _x99-0698931-9
500    _aOriginaluppl. 1962
599    _aLi: S
740 4  _aDet osynliga barnet
775 1  _z951-50-0385-7
       _w9515003857
       _907
841    _5Li
       _axa
       _b0201080u    0   4000uu   |000000
       _e1
841    _5SEE
       _axa
       _b0201080u    0   4000uu   |000000
       _e1
841    _5L
       _axa
       _b0201080u    0   4000uu   |000000
       _e1
841    _5NB
       _axa
       _b0201080u    0   4000uu   |000000
       _e1
841    _5Q
       _axa
       _b0201080u    0   4000uu   |000000
       _e1
841    _5S
       _axa
       _b0201080u    0   4000uu   |000000
       _e1
852    _5NB
       _bNB
       _cNB98:12
       _hplikt
       _jR, 980520
852    _5Li
       _bLi
       _cCNB
       _hh,u
852    _5SEE
       _bSEE
852    _5Q
       _bQ
       _j98947
852    _5L
       _bL
       _c0100
       _h98/
       _j3043 H
852    _5S
       _bS
       _hSv97
       _j7235
900 1s _aYanson, Tobe,
       _d1914-2001
       _uJansson, Tove,
       _d1914-2001
900 1s _aJanssonová, Tove,
       _d1914-2001
       _uJansson, Tove,
       _d1914-2001
900 1s _aJansone, Tuve,
       _d1914-2001
       _uJansson, Tove,
       _d1914-2001
900 1s _aJanson, Tuve,
       _d1914-2001
       _uJansson, Tove,
       _d1914-2001
900 1s _aJansson, Tuve,
       _d1914-2001
       _uJansson, Tove,
       _d1914-2001
900 1s _aJanssonova, Tove,
       _d1914-2001
       _uJansson, Tove,
       _d1914-2001
976  2 _aHcd,u
       _bSkönlitteratur
005     20050204111518.0
100 0  _anothing
       _zeverything
966    _lweb
       _r0
       _sb
       _i49
       _c1
PK��Z�����,test/File_MARC/tests/marc_xml_namespace.phptnu�[���--TEST--
marc_xml_namespace: iterate and pretty print a MARC record
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';
$marc_file = new File_MARCXML($dir . '/' . 'namespace.xml',File_MARC::SOURCE_FILE,"http://www.loc.gov/MARC21/slim");
while ($marc_record = $marc_file->next()) {
  print $marc_record->getLeader();
  print "\n";
  $field = $marc_record->getField('050');
  print $field->getIndicator(1);
  print "\n";
  print $field->getIndicator(2);
  print "\n";
  $subfield = $field->getSubfield('a');
  print $subfield->getData();
  print "\n";
}
?>
--EXPECT--
00925njm  22002777a 4500
0
0
Atlantic 1259
01832cmma 2200349 a 4500
0
0
F204.W5
PK��Zf��~(test/File_MARC/tests/marc_field_001.phptnu�[���--TEST--
marc_field_001: Exercise basic methods for File_MARC_Field class
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';

// create some subfields
$subfields[] = new File_MARC_Subfield('a', 'nothing');
$subfields[] = new File_MARC_Subfield('z', 'everything');

// test constructor
$field = new File_MARC_Data_Field('100', $subfields, '0');

// test basic getter methods
print "Tag: " . $field->getTag() . "\n";
print "Get Ind1: " . $field->getIndicator(1) . "\n";
print "Get Ind2: " . $field->getIndicator(2) . "\n";

// test basic setter methods
print "Set Ind1: " . $field->setIndicator(1, '3') . "\n";

// test pretty print
print $field;
print "\n";

// test raw print
print $field->toRaw();
?>
--EXPECT--
Tag: 100
Get Ind1: 0
Get Ind2:  
Set Ind1: 3
100 3  _anothing
       _zeverything
3 anothingzeverything
PK��Z���YY&test/File_MARC/tests/marc_xml_009.phptnu�[���--TEST--
marc_xml_009: convert a MARCXML record with an overly long leader to MARC
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';
$marc_file = new File_MARCXML($dir . '/' . 'bad_leader.xml');

while ($marc_record = $marc_file->next()) {
  print $marc_record->toRaw();
}
?>
--EXPECT--
00749cam a2200241 454500001001400000003000600014005001700020008004100037020001800078020001500096035002100111040003600132050002400168100002500192245007800217260003700295300002100332504004100353650001700394650002200411852004800433901002600481LIBN539044247OCoLC20081030150430.0070630|||||    |||           000 0 eng d  a9781856075442  a1856075443  a(OCoLC)156822300  aBTCTAcBTCTAdYDXCPdBAKERdEMT 4aBL2747.2b.W45 20061 aWhite, Stephen Ross.10aSpace for unknowing :bthe place of agnosis in faith /cStephen R. White.  aDublin :bColumba Press,cc2006.  a160 p. ;c22 cm.  aIncludes bibliographical references. 0aAgnosticism. 0aBelief and doubt.  a1h230 WHIp11111027105040t65112549p26.95  aLIBN539044247bSystem
PK��Z~N0�:: test/File_MARC/tests/example.mrcnu�[���01850     2200517   45000010011000000030007000110080039000180200026000570350015000830400007000980420012001050840018001170840018001350840021001530840022001741000030001962450062002262500013002882600058003013000033003594400037003925000023004295990010004527400024004627750034004868410048005208410049005688410047006178410048006648410047007128410047007598520038008068520021008448520013008658520016008788520028008948520021009229000056009439000060009999000057010599000056011169000057011729000060012299760026012890050017013150000000044EMILDA980120s1998    fi     j      000 0 swe  a9515008808cFIM 72:00  99515008808  aNB  9NB9SEE  aHcd,u2kssb/6  5NBauHc2kssb  5SEEaHcf2kssb/6  5QaHcd,uf2kssb/61 aJansson, Tove,d1914-200104aDet osynliga barnet och andra ber�ttelser /cTove Jansson  a7. uppl.  aHelsingfors :bSchildt,c1998 ;e(Falun :fScandbook)  a166, [4] s. :bill. ;c21 cm 0aMumin-biblioteket,x99-0698931-9  aOriginaluppl. 1962  aLi: S4 aDet osynliga barnet1 z951-50-0385-7w9515003857907  5Liaxab0201080u    0   4000uu   |000000e1  5SEEaxab0201080u    0   4000uu   |000000e1  5Laxab0201080u    0   4000uu   |000000e1  5NBaxab0201080u    0   4000uu   |000000e1  5Qaxab0201080u    0   4000uu   |000000e1  5Saxab0201080u    0   4000uu   |000000e1  5NBbNBcNB98:12hpliktjR, 980520  5LibLicCNBhh,u  5SEEbSEE  5QbQj98947  5LbLc0100h98/j3043 H  5SbShSv97j72351saYanson, Tobe,d1914-2001uJansson, Tove,d1914-20011saJanssonov�, Tove,d1914-2001uJansson, Tove,d1914-20011saJansone, Tuve,d1914-2001uJansson, Tove,d1914-20011saJanson, Tuve,d1914-2001uJansson, Tove,d1914-20011saJansson, Tuve,d1914-2001uJansson, Tove,d1914-20011saJanssonova, Tove,d1914-2001uJansson, Tove,d1914-2001 2aHcd,ubSk�nlitteratur20050204111518.0PK��Z}۶\pp$test/File_MARC/tests/bad_example.xmlnu�[���<collection xmlns="http://www.loc.gov/MARC21/slim">
<record>
  <leader>01850    a2200517   4500</leader>
  <controlfield tag="001">0000000044</controlfield>
  <controlfield tag="003">EMILDA</controlfield>
  <controlfield tag="008">980120s1998    fi     j      000 0 swe</controlfield>
  <datafield tag="020" ind1=" " ind2=" ">
    <subfield code="a">9515008808</subfield>
    <subfield code="c">FIM 72:00</subfield>
  </datafield>
  <datafield tag="035" ind1=" " ind2=" ">
    <subfield code="9">9515008808</subfield>
  </datafield>
  <datafield tag="040" ind1=" " ind2=" ">
    <subfield code="a">NB</subfield>
  </datafield>
  <datafield tag="042" ind1=" " ind2=" ">
    <subfield code="9">NB</subfield>
    <subfield code="9">SEE</subfield>
  </datafield>
  <datafield tag="084" ind1=" " ind2=" ">
    <subfield code="a">Hcd,u</subfield>
    <subfield code="2">kssb/6</subfield>
  </datafield>
  <datafield tag="084" ind1=" " ind2=" ">
    <subfield code="5">NB</subfield>
    <subfield code="a">uHc</subfield>
    <subfield code="2">kssb</subfield>
  </datafield>
  <datafield tag="084" ind1=" " ind2=" ">
    <subfield code="5">SEE</subfield>
    <subfield code="a">Hcf</subfield>
    <subfield code="2">kssb/6</subfield>
  </datafield>
  <datafield tag="084" ind1=" " ind2=" ">
    <subfield code="5">Q</subfield>
    <subfield code="a">Hcd,uf</subfield>
    <subfield code="2">kssb/6</subfield>
  </datafield>
  <datafield tag="100" ind1="1" ind2=" ">
    <subfield code="a">Jansson, Tove,</subfield>
    <subfield code="d">1914-2001</subfield>
  </datafield>
  <datafield tag="245" ind1="0">
    <subfield code="a">Det osynliga barnet och andra bert̃telser /</subfield>
    <subfield code="c">Tove Jansson</subfield>
  </datafield>
  <datafield tag="250" ind1=" " ind2=" ">
    <subfield code="a">7. uppl.</subfield>
  </datafield>
  <datafield tag="260" ind1=" " ind2=" ">
    <subfield code="a">Helsingfors :</subfield>
    <subfield code="b">Schildt,</subfield>
    <subfield code="c">1998 ;</subfield>
    <subfield code="e">(Falun :</subfield>
    <subfield code="f">Scandbook)</subfield>
  </datafield>
  <datafield tag="30-" ind1=" " ind2=" ">
    <subfield code="a">166, [4] s. :</subfield>
    <subfield code="b">ill. ;</subfield>
    <subfield code="c">21 cm</subfield>
  </datafield>
  <datafield tag="440" ind1=" " ind2="0">
    <subfield code="a">Mumin-biblioteket,</subfield>
    <subfield code="x">99-0698931-9</subfield>
  </datafield>
  <datafield tag="500" ind1=" " ind2=" ">
    <subfield code="a">Originaluppl. 1962</subfield>
  </datafield>
  <datafield tag="599" ind1=" " ind2=" ">
    <subfield code="a">Li: S</subfield>
  </datafield>
  <datafield tag="740" ind1="4" ind2=" ">
    <subfield code="a">Det osynliga barnet</subfield>
  </datafield>
  <datafield tag="775" ind1="1" ind2=" ">
    <subfield code="z">951-50-0385-7</subfield>
    <subfield code="w">9515003857</subfield>
    <subfield code="9">07</subfield>
  </datafield>
  <datafield tag="841" ind1=" " ind2=" ">
    <subfield code="5">Li</subfield>
    <subfield code="a">xa</subfield>
    <subfield code="b">0201080u    0   4000uu   |000000</subfield>
    <subfield code="e">1</subfield>
  </datafield>
  <datafield tag="841" ind1=" " ind2=" ">
    <subfield code="5">SEE</subfield>
    <subfield code="a">xa</subfield>
    <subfield code="b">0201080u    0   4000uu   |000000</subfield>
    <subfield code="e">1</subfield>
  </datafield>
  <datafield tag="841" ind1=" " ind2=" ">
    <subfield code="5">L</subfield>
    <subfield code="a">xa</subfield>
    <subfield code="b">0201080u    0   4000uu   |000000</subfield>
    <subfield code="e">1</subfield>
  </datafield>
  <datafield tag="841" ind1=" " ind2=" ">
    <subfield code="5">NB</subfield>
    <subfield code="a">xa</subfield>
    <subfield code="b">0201080u    0   4000uu   |000000</subfield>
    <subfield code="e">1</subfield>
  </datafield>
  <datafield tag="841" ind1=" " ind2=" ">
    <subfield code="5">Q</subfield>
    <subfield code="a">xa</subfield>
    <subfield code="b">0201080u    0   4000uu   |000000</subfield>
    <subfield code="e">1</subfield>
  </datafield>
  <datafield tag="841" ind1=" " ind2=" ">
    <subfield code="5">S</subfield>
    <subfield code="a">xa</subfield>
    <subfield code="b">0201080u    0   4000uu   |000000</subfield>
    <subfield code="e">1</subfield>
  </datafield>
  <datafield tag="852" ind1=" " ind2=" ">
    <subfield code="5">NB</subfield>
    <subfield code="b">NB</subfield>
    <subfield code="c">NB98:12</subfield>
    <subfield code="h">plikt</subfield>
    <subfield code="j">R, 980520</subfield>
  </datafield>
  <datafield tag="852" ind1=" " ind2=" ">
    <subfield code="5">Li</subfield>
    <subfield code="b">Li</subfield>
    <subfield code="c">CNB</subfield>
    <subfield code="h">h,u</subfield>
  </datafield>
  <datafield tag="852" ind1=" " ind2=" ">
    <subfield code="5">SEE</subfield>
    <subfield code="b">SEE</subfield>
  </datafield>
  <datafield tag="852" ind1=" " ind2=" ">
    <subfield code="5">Q</subfield>
    <subfield code="b">Q</subfield>
    <subfield code="j">98947</subfield>
  </datafield>
  <datafield tag="852" ind1=" " ind2=" ">
    <subfield code="5">L</subfield>
    <subfield code="b">L</subfield>
    <subfield code="c">0100</subfield>
    <subfield code="h">98/</subfield>
    <subfield code="j">3043 H</subfield>
  </datafield>
  <datafield tag="852" ind1=" " ind2=" ">
    <subfield code="5">S</subfield>
    <subfield code="b">S</subfield>
    <subfield code="h">Sv97</subfield>
    <subfield code="j">7235</subfield>
  </datafield>
  <datafield tag="900" ind1="1" ind2="s">
    <subfield code="a">Yanson, Tobe,</subfield>
    <subfield code="d">1914-2001</subfield>
    <subfield code="u">Jansson, Tove,</subfield>
    <subfield code="d">1914-2001</subfield>
  </datafield>
  <datafield tag="900" ind1="1" ind2="s">
    <subfield code="a">Janssonov,̀ Tove,</subfield>
    <subfield code="d">1914-2001</subfield>
    <subfield code="u">Jansson, Tove,</subfield>
    <subfield code="d">1914-2001</subfield>
  </datafield>
  <datafield tag="900" ind1="1" ind2="s">
    <subfield code="a">Jansone, Tuve,</subfield>
    <subfield code="d">1914-2001</subfield>
    <subfield code="u">Jansson, Tove,</subfield>
    <subfield code="d">1914-2001</subfield>
  </datafield>
  <datafield tag="900" ind1="1" ind2="s">
    <subfield code="a">Janson, Tuve,</subfield>
    <subfield code="d">1914-2001</subfield>
    <subfield code="u">Jansson, Tove,</subfield>
    <subfield code="d">1914-2001</subfield>
  </datafield>
  <datafield tag="900" ind1="1" ind2="s">
    <subfield code="a">Jansson, Tuve,</subfield>
    <subfield code="d">1914-2001</subfield>
    <subfield code="u">Jansson, Tove,</subfield>
    <subfield code="d">1914-2001</subfield>
  </datafield>
  <datafield tag="900" ind1="1" ind2="s">
    <subfield code="a">Janssonova, Tove,</subfield>
    <subfield code="d">1914-2001</subfield>
    <subfield code="u">Jansson, Tove,</subfield>
    <subfield code="d">1914-2001</subfield>
  </datafield>
  <datafield tag="976" ind1=" " ind2="2">
    <subfield code="a">Hcd,u</subfield>
    <subfield code="b">Skn̲litteratur</subfield>
  </datafield>
  <controlfield tag="005">20050204111518.0</controlfield>
</record>
</collection>
PK��Z9�DD"test/File_MARC/tests/marc_017.phptnu�[���--TEST--
marc_017: iterate and print a MARC record to JSON format
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';
$marc_file = new File_MARC($dir . '/' . 'example.mrc');

while ($marc_record = $marc_file->next()) {
  print $marc_record->toJSON();
  print "\n";
}
?>
--EXPECT--
{"leader":"01850     2200517   4500","fields":[{"001":"0000000044"},{"003":"EMILDA"},{"008":"980120s1998    fi     j      000 0 swe"},{"020":{"ind1":" ","ind2":" ","subfields":[{"a":"9515008808"},{"c":"FIM 72:00"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"9":"9515008808"}]}},{"040":{"ind1":" ","ind2":" ","subfields":[{"a":"NB"}]}},{"042":{"ind1":" ","ind2":" ","subfields":[{"9":"NB"},{"9":"SEE"}]}},{"084":{"ind1":" ","ind2":" ","subfields":[{"a":"Hcd,u"},{"2":"kssb\/6"}]}},{"084":{"ind1":" ","ind2":" ","subfields":[{"5":"NB"},{"a":"uHc"},{"2":"kssb"}]}},{"084":{"ind1":" ","ind2":" ","subfields":[{"5":"SEE"},{"a":"Hcf"},{"2":"kssb\/6"}]}},{"084":{"ind1":" ","ind2":" ","subfields":[{"5":"Q"},{"a":"Hcd,uf"},{"2":"kssb\/6"}]}},{"100":{"ind1":"1","ind2":" ","subfields":[{"a":"Jansson, Tove,"},{"d":"1914-2001"}]}},{"245":{"ind1":"0","ind2":"4","subfields":[{"a":"Det osynliga barnet och andra ber\u00e4ttelser \/"},{"c":"Tove Jansson"}]}},{"250":{"ind1":" ","ind2":" ","subfields":[{"a":"7. uppl."}]}},{"260":{"ind1":" ","ind2":" ","subfields":[{"a":"Helsingfors :"},{"b":"Schildt,"},{"c":"1998 ;"},{"e":"(Falun :"},{"f":"Scandbook)"}]}},{"300":{"ind1":" ","ind2":" ","subfields":[{"a":"166, [4] s. :"},{"b":"ill. ;"},{"c":"21 cm"}]}},{"440":{"ind1":" ","ind2":"0","subfields":[{"a":"Mumin-biblioteket,"},{"x":"99-0698931-9"}]}},{"500":{"ind1":" ","ind2":" ","subfields":[{"a":"Originaluppl. 1962"}]}},{"599":{"ind1":" ","ind2":" ","subfields":[{"a":"Li: S"}]}},{"740":{"ind1":"4","ind2":" ","subfields":[{"a":"Det osynliga barnet"}]}},{"775":{"ind1":"1","ind2":" ","subfields":[{"z":"951-50-0385-7"},{"w":"9515003857"},{"9":"07"}]}},{"841":{"ind1":" ","ind2":" ","subfields":[{"5":"Li"},{"a":"xa"},{"b":"0201080u    0   4000uu   |000000"},{"e":"1"}]}},{"841":{"ind1":" ","ind2":" ","subfields":[{"5":"SEE"},{"a":"xa"},{"b":"0201080u    0   4000uu   |000000"},{"e":"1"}]}},{"841":{"ind1":" ","ind2":" ","subfields":[{"5":"L"},{"a":"xa"},{"b":"0201080u    0   4000uu   |000000"},{"e":"1"}]}},{"841":{"ind1":" ","ind2":" ","subfields":[{"5":"NB"},{"a":"xa"},{"b":"0201080u    0   4000uu   |000000"},{"e":"1"}]}},{"841":{"ind1":" ","ind2":" ","subfields":[{"5":"Q"},{"a":"xa"},{"b":"0201080u    0   4000uu   |000000"},{"e":"1"}]}},{"841":{"ind1":" ","ind2":" ","subfields":[{"5":"S"},{"a":"xa"},{"b":"0201080u    0   4000uu   |000000"},{"e":"1"}]}},{"852":{"ind1":" ","ind2":" ","subfields":[{"5":"NB"},{"b":"NB"},{"c":"NB98:12"},{"h":"plikt"},{"j":"R, 980520"}]}},{"852":{"ind1":" ","ind2":" ","subfields":[{"5":"Li"},{"b":"Li"},{"c":"CNB"},{"h":"h,u"}]}},{"852":{"ind1":" ","ind2":" ","subfields":[{"5":"SEE"},{"b":"SEE"}]}},{"852":{"ind1":" ","ind2":" ","subfields":[{"5":"Q"},{"b":"Q"},{"j":"98947"}]}},{"852":{"ind1":" ","ind2":" ","subfields":[{"5":"L"},{"b":"L"},{"c":"0100"},{"h":"98\/"},{"j":"3043 H"}]}},{"852":{"ind1":" ","ind2":" ","subfields":[{"5":"S"},{"b":"S"},{"h":"Sv97"},{"j":"7235"}]}},{"900":{"ind1":"1","ind2":"s","subfields":[{"a":"Yanson, Tobe,"},{"d":"1914-2001"},{"u":"Jansson, Tove,"},{"d":"1914-2001"}]}},{"900":{"ind1":"1","ind2":"s","subfields":[{"a":"Janssonov\u00e1, Tove,"},{"d":"1914-2001"},{"u":"Jansson, Tove,"},{"d":"1914-2001"}]}},{"900":{"ind1":"1","ind2":"s","subfields":[{"a":"Jansone, Tuve,"},{"d":"1914-2001"},{"u":"Jansson, Tove,"},{"d":"1914-2001"}]}},{"900":{"ind1":"1","ind2":"s","subfields":[{"a":"Janson, Tuve,"},{"d":"1914-2001"},{"u":"Jansson, Tove,"},{"d":"1914-2001"}]}},{"900":{"ind1":"1","ind2":"s","subfields":[{"a":"Jansson, Tuve,"},{"d":"1914-2001"},{"u":"Jansson, Tove,"},{"d":"1914-2001"}]}},{"900":{"ind1":"1","ind2":"s","subfields":[{"a":"Janssonova, Tove,"},{"d":"1914-2001"},{"u":"Jansson, Tove,"},{"d":"1914-2001"}]}},{"976":{"ind1":" ","ind2":"2","subfields":[{"a":"Hcd,u"},{"b":"Sk\u00f6nlitteratur"}]}},{"005":"20050204111518.0"}]}
PK��Z�&��cc"test/File_MARC/tests/marc_002.phptnu�[���--TEST--
marc_002: iterate and pretty print MARC records from a file with multiple records
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';
$marc_file = new File_MARC($dir . '/' . 'music.mrc');

while ($marc_record = $marc_file->next()) {
  print $marc_record;
  print "\n";
}
?>
--EXPECT--
LDR 01145ncm  2200277 i 4500
001     000073594
004     AAJ5802
005     20030415102100.0
008     801107s1977    nyujza                   
010    _a   77771106 
035    _a(CaOTUIC)15460184
035 9  _aAAJ5802
040    _aLC
050 00 _aM1366
       _b.M62
       _dM1527.2
245 04 _aThe Modern Jazz Quartet :
       _bThe legendary profile. --
260    _aNew York :
       _bM.J.Q. Music,
       _cc1977.
300    _ascore (72 p.) ;
       _c31 cm.
500    _aFor piano, vibraphone, drums, and double bass.
505 0  _aLewis, J. Django.--Lewis, J. Plastic dreams (music from the film Kemek).--Lewis, J. Dancing (music from the film Kemek).--Lewis, J. Blues in A minor.--Lewis, J. Blues in B♭.--Lewis, J. Precious joy.--Jackson, M. The martyr.--Jackson, M. The legendary profile.
650  0 _aJazz.
650  0 _aMotion picture music
       _vExcerpts
       _vScores.
700 12 _aLewis, John,
       _d1920-
       _tSelections.
       _f1977.
700 12 _aJackson, Milt.
       _tMartyrs.
       _f1977.
700 12 _aJackson, Milt.
       _tLegendary profile.
       _f1977.
740 4  _aThe legendary profile.
852 00 _bMUSIC
       _cMAIN
       _kfolio
       _hM1366
       _iM62
       _91
       _4Marvin Duchow Music
       _5

LDR 01293cjm  2200289 a 4500
001     001878039
005     20050110174900.0
007     sd fungnn|||e|
008     940202r19931981nyujzn   i              d
024 1  _a7464573372
028 02 _aJK 57337
       _bRed Baron
035    _a(OCoLC)29737267
040    _aSVP
       _cSVP
       _dLGG
100 1  _aDesmond, Paul,
       _d1924-
245 10 _aPaul Desmond & the Modern Jazz Quartet
       _h[sound recording]
260    _aNew York, N.Y. :
       _bRed Baron :
       _bManufactured by Sony Music Entertainment,
       _cp1993.
300    _a1 sound disc (39 min.) :
       _bdigital ;
       _c4 3/4 in.
511 0  _aPaul Desmond, alto saxophone; Modern Jazz Quartet: John Lewis, piano; Milt Jackson, vibraphone; Percy Heath, bass; Connie Kay, drums.
500    _aAll arrangements by John Lewis.
518    _aRecorded live on December 25, 1971 at Town Hall, NYC.
500    _aOriginally released in 1981 by Finesse as LP FW 27487.
500    _aProgram notes by Irving Townsend, June 1981, on container insert.
505 0  _aGreensleeves -- You go to my head -- Blue dove -- Jesus Christ Superstar -- Here's that rainy day -- East of the sun -- Bags' new groove.
650  0 _aJazz
       _y1971-1980.
700 1  _aLewis, John,
       _d1920-
710 2  _aModern Jazz Quartet.
740 0  _aPaul Desmond and the Modern Jazz Quartet.

LDR 01829cjm  2200385 a 4500
001     001964482
005     20060626132700.0
007     sd fzngnn|m|e|
008     871211p19871957nyujzn                  d
024 1  _a4228332902
028 01 _a833 290-2
       _bVerve
033 0  _a19571027
       _b6299
       _cD56
033 0  _a196112--
       _b3804
       _cN4
033 0  _a19571019
       _b4104
       _cC6
033 0  _a197107--
       _b6299
       _cV7
035    _a(OCoLC)17222092
040    _aCPL
       _cCPL
       _dOCL
       _dLGG
048    _apz01
       _aka01
       _asd01
       _apd01
110 2  _aModern Jazz Quartet.
       _4prf
245 14 _aThe Modern Jazz Quartet plus
       _h[sound recording].
260    _a[New York] :
       _bVerve,
       _cp1987.
300    _a1 sound disc :
       _bdigital ;
       _c4 3/4 in.
440  0 _aCompact jazz
511 0  _aModern Jazz Quartet (principally) ; Milt Jackson, vibraphone (2nd and 8th works) ; Oscar Peterson, piano (2nd and 8th works) ; Ray Brown, bass (2nd and 8th works) ; Ed Thigpen (2nd work), Louis Hayes (8th work), drums.
518    _aRecorded live, Oct. 27, 1957, at the Donaueschingen Jazz Festival (1st, 5th, 7th, and 10th works); Dec. 1961, in New York (2nd work); live, Oct. 19, 1957, at the Opera House, Chicago (3rd, 4th, 6th, and 9th works); July 1971, in Villingen, Germany (8th work).
500    _aCompact disc.
500    _aAnalog recording.
505 0  _aThe golden striker (4:08) -- On Green Dolphin Street (7:28) -- D & E (4:55) -- I'll remember April (4:51) -- Cortège (7:15) -- Now's the time (4:43) -- J.B. blues (5:09) -- Reunion blues (6:35) -- 'Round midnight (3:56) -- Three windows (7:20).
650  0 _aJazz.
700 1  _aJackson, Milt.
       _4prf
700 1  _aPeterson, Oscar,
       _d1925-
       _4prf
700 1  _aBrown, Ray,
       _d1926-2002.
       _4prf
700 1  _aThigpen, Ed.
       _4prf
700 1  _aHayes, Louis,
       _d1937-
       _4prf
852 80 _bMUSIC
       _cAV
       _hCD 1131
       _4Marvin Duchow Music
       _5Audio-Visual
PK��Z�����&test/File_MARC/tests/marc_xml_005.phptnu�[���--TEST--
marc_xml_005: Round-trip a MARCXML record with a root element of "record" to MARC21
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';
$marc_file = new File_MARCXML($dir . '/' . 'onerecord.xml');

while ($marc_record = $marc_file->next()) {
  print $marc_record->toRaw();
}
?>
--EXPECT--
01142cam  2200301 a 4500001001300000003000400013005001700017008004100034010001700075020002500092040001800117042000900135050002600144082001600170100003200186245008600218250001200304260005200316300004900368500004000417520022800457650003300685650003300718650002400751650002100775650002300796700002100819   92005291 DLC19930521155141.9920219s1993    caua   j      000 0 eng    a   92005291   a0152038655 :c$15.95  aDLCcDLCdDLC  alcac00aPS3537.A618bA88 199300a811/.522201 aSandburg, Carl,d1878-1967.10aArithmetic /cCarl Sandburg ; illustrated as an anamorphic adventure by Ted Rand.  a1st ed.  aSan Diego :bHarcourt Brace Jovanovich,cc1993.  a1 v. (unpaged) :bill. (some col.) ;c26 cm.  aOne Mylar sheet included in pocket.  aA poem about numbers and their characteristics. Features anamorphic, or distorted, drawings which can be restored to normal by viewing from a particular angle or by viewing the image's reflection in the provided Mylar cone. 0aArithmeticxJuvenile poetry. 0aChildren's poetry, American. 1aArithmeticxPoetry. 1aAmerican poetry. 1aVisual perception.1 aRand, Ted,eill.
PK��Z�5;�-�-test/File_MARC/tests/music.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<collection xmlns="http://www.loc.gov/MARC21/slim">
<record>
  <leader>01145ncm a2200277 i 4500</leader>
  <controlfield tag="001">000073594</controlfield>
  <controlfield tag="004">AAJ5802</controlfield>
  <controlfield tag="005">20030415102100.0</controlfield>
  <controlfield tag="008">801107s1977    nyujza                   </controlfield>
  <datafield tag="010" ind1=" " ind2=" ">
    <subfield code="a">   77771106 </subfield>
  </datafield>
  <datafield tag="035" ind1=" " ind2=" ">
    <subfield code="a">(CaOTUIC)15460184</subfield>
  </datafield>
  <datafield tag="035" ind1="9" ind2=" ">
    <subfield code="a">AAJ5802</subfield>
  </datafield>
  <datafield tag="040" ind1=" " ind2=" ">
    <subfield code="a">LC</subfield>
  </datafield>
  <datafield tag="050" ind1="0" ind2="0">
    <subfield code="a">M1366</subfield>
    <subfield code="b">.M62</subfield>
    <subfield code="d">M1527.2</subfield>
  </datafield>
  <datafield tag="245" ind1="0" ind2="4">
    <subfield code="a">The Modern Jazz Quartet :</subfield>
    <subfield code="b">The legendary profile. --</subfield>
  </datafield>
  <datafield tag="260" ind1=" " ind2=" ">
    <subfield code="a">New York :</subfield>
    <subfield code="b">M.J.Q. Music,</subfield>
    <subfield code="c">c1977.</subfield>
  </datafield>
  <datafield tag="300" ind1=" " ind2=" ">
    <subfield code="a">score (72 p.) ;</subfield>
    <subfield code="c">31 cm.</subfield>
  </datafield>
  <datafield tag="500" ind1=" " ind2=" ">
    <subfield code="a">For piano, vibraphone, drums, and double bass.</subfield>
  </datafield>
  <datafield tag="505" ind1="0" ind2=" ">
    <subfield code="a">Lewis, J. Django.--Lewis, J. Plastic dreams (music from the film Kemek).--Lewis, J. Dancing (music from the film Kemek).--Lewis, J. Blues in A minor.--Lewis, J. Blues in B́Ư.--Lewis, J. Precious joy.--Jackson, M. The martyr.--Jackson, M. The legendary profile.</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="0">
    <subfield code="a">Jazz.</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="0">
    <subfield code="a">Motion picture music</subfield>
    <subfield code="v">Excerpts</subfield>
    <subfield code="v">Scores.</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2="2">
    <subfield code="a">Lewis, John,</subfield>
    <subfield code="d">1920-</subfield>
    <subfield code="t">Selections.</subfield>
    <subfield code="f">1977.</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2="2">
    <subfield code="a">Jackson, Milt.</subfield>
    <subfield code="t">Martyrs.</subfield>
    <subfield code="f">1977.</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2="2">
    <subfield code="a">Jackson, Milt.</subfield>
    <subfield code="t">Legendary profile.</subfield>
    <subfield code="f">1977.</subfield>
  </datafield>
  <datafield tag="740" ind1="4" ind2=" ">
    <subfield code="a">The legendary profile.</subfield>
  </datafield>
  <datafield tag="852" ind1="0" ind2="0">
    <subfield code="b">MUSIC</subfield>
    <subfield code="c">MAIN</subfield>
    <subfield code="k">folio</subfield>
    <subfield code="h">M1366</subfield>
    <subfield code="i">M62</subfield>
    <subfield code="9">1</subfield>
    <subfield code="4">Marvin Duchow Music</subfield>
    <subfield code="5"></subfield>
  </datafield>
</record>
<record>
  <leader>01293cjm a2200289 a 4500</leader>
  <controlfield tag="001">001878039</controlfield>
  <controlfield tag="005">20050110174900.0</controlfield>
  <controlfield tag="007">sd fungnn|||e|</controlfield>
  <controlfield tag="008">940202r19931981nyujzn   i              d</controlfield>
  <datafield tag="024" ind1="1" ind2=" ">
    <subfield code="a">7464573372</subfield>
  </datafield>
  <datafield tag="028" ind1="0" ind2="2">
    <subfield code="a">JK 57337</subfield>
    <subfield code="b">Red Baron</subfield>
  </datafield>
  <datafield tag="035" ind1=" " ind2=" ">
    <subfield code="a">(OCoLC)29737267</subfield>
  </datafield>
  <datafield tag="040" ind1=" " ind2=" ">
    <subfield code="a">SVP</subfield>
    <subfield code="c">SVP</subfield>
    <subfield code="d">LGG</subfield>
  </datafield>
  <datafield tag="100" ind1="1" ind2=" ">
    <subfield code="a">Desmond, Paul,</subfield>
    <subfield code="d">1924-</subfield>
  </datafield>
  <datafield tag="245" ind1="1" ind2="0">
    <subfield code="a">Paul Desmond &amp; the Modern Jazz Quartet</subfield>
    <subfield code="h">[sound recording]</subfield>
  </datafield>
  <datafield tag="260" ind1=" " ind2=" ">
    <subfield code="a">New York, N.Y. :</subfield>
    <subfield code="b">Red Baron :</subfield>
    <subfield code="b">Manufactured by Sony Music Entertainment,</subfield>
    <subfield code="c">p1993.</subfield>
  </datafield>
  <datafield tag="300" ind1=" " ind2=" ">
    <subfield code="a">1 sound disc (39 min.) :</subfield>
    <subfield code="b">digital ;</subfield>
    <subfield code="c">4 3/4 in.</subfield>
  </datafield>
  <datafield tag="511" ind1="0" ind2=" ">
    <subfield code="a">Paul Desmond, alto saxophone; Modern Jazz Quartet: John Lewis, piano; Milt Jackson, vibraphone; Percy Heath, bass; Connie Kay, drums.</subfield>
  </datafield>
  <datafield tag="500" ind1=" " ind2=" ">
    <subfield code="a">All arrangements by John Lewis.</subfield>
  </datafield>
  <datafield tag="518" ind1=" " ind2=" ">
    <subfield code="a">Recorded live on December 25, 1971 at Town Hall, NYC.</subfield>
  </datafield>
  <datafield tag="500" ind1=" " ind2=" ">
    <subfield code="a">Originally released in 1981 by Finesse as LP FW 27487.</subfield>
  </datafield>
  <datafield tag="500" ind1=" " ind2=" ">
    <subfield code="a">Program notes by Irving Townsend, June 1981, on container insert.</subfield>
  </datafield>
  <datafield tag="505" ind1="0" ind2=" ">
    <subfield code="a">Greensleeves -- You go to my head -- Blue dove -- Jesus Christ Superstar -- Here&apos;s that rainy day -- East of the sun -- Bags&apos; new groove.</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="0">
    <subfield code="a">Jazz</subfield>
    <subfield code="y">1971-1980.</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2=" ">
    <subfield code="a">Lewis, John,</subfield>
    <subfield code="d">1920-</subfield>
  </datafield>
  <datafield tag="710" ind1="2" ind2=" ">
    <subfield code="a">Modern Jazz Quartet.</subfield>
  </datafield>
  <datafield tag="740" ind1="0" ind2=" ">
    <subfield code="a">Paul Desmond and the Modern Jazz Quartet.</subfield>
  </datafield>
</record>
<record>
  <leader>01829cjm a2200385 a 4500</leader>
  <controlfield tag="001">001964482</controlfield>
  <controlfield tag="005">20060626132700.0</controlfield>
  <controlfield tag="007">sd fzngnn|m|e|</controlfield>
  <controlfield tag="008">871211p19871957nyujzn                  d</controlfield>
  <datafield tag="024" ind1="1" ind2=" ">
    <subfield code="a">4228332902</subfield>
  </datafield>
  <datafield tag="028" ind1="0" ind2="1">
    <subfield code="a">833 290-2</subfield>
    <subfield code="b">Verve</subfield>
  </datafield>
  <datafield tag="033" ind1="0" ind2=" ">
    <subfield code="a">19571027</subfield>
    <subfield code="b">6299</subfield>
    <subfield code="c">D56</subfield>
  </datafield>
  <datafield tag="033" ind1="0" ind2=" ">
    <subfield code="a">196112--</subfield>
    <subfield code="b">3804</subfield>
    <subfield code="c">N4</subfield>
  </datafield>
  <datafield tag="033" ind1="0" ind2=" ">
    <subfield code="a">19571019</subfield>
    <subfield code="b">4104</subfield>
    <subfield code="c">C6</subfield>
  </datafield>
  <datafield tag="033" ind1="0" ind2=" ">
    <subfield code="a">197107--</subfield>
    <subfield code="b">6299</subfield>
    <subfield code="c">V7</subfield>
  </datafield>
  <datafield tag="035" ind1=" " ind2=" ">
    <subfield code="a">(OCoLC)17222092</subfield>
  </datafield>
  <datafield tag="040" ind1=" " ind2=" ">
    <subfield code="a">CPL</subfield>
    <subfield code="c">CPL</subfield>
    <subfield code="d">OCL</subfield>
    <subfield code="d">LGG</subfield>
  </datafield>
  <datafield tag="048" ind1=" " ind2=" ">
    <subfield code="a">pz01</subfield>
    <subfield code="a">ka01</subfield>
    <subfield code="a">sd01</subfield>
    <subfield code="a">pd01</subfield>
  </datafield>
  <datafield tag="110" ind1="2" ind2=" ">
    <subfield code="a">Modern Jazz Quartet.</subfield>
    <subfield code="4">prf</subfield>
  </datafield>
  <datafield tag="245" ind1="1" ind2="4">
    <subfield code="a">The Modern Jazz Quartet plus</subfield>
    <subfield code="h">[sound recording].</subfield>
  </datafield>
  <datafield tag="260" ind1=" " ind2=" ">
    <subfield code="a">[New York] :</subfield>
    <subfield code="b">Verve,</subfield>
    <subfield code="c">p1987.</subfield>
  </datafield>
  <datafield tag="300" ind1=" " ind2=" ">
    <subfield code="a">1 sound disc :</subfield>
    <subfield code="b">digital ;</subfield>
    <subfield code="c">4 3/4 in.</subfield>
  </datafield>
  <datafield tag="440" ind1=" " ind2="0">
    <subfield code="a">Compact jazz</subfield>
  </datafield>
  <datafield tag="511" ind1="0" ind2=" ">
    <subfield code="a">Modern Jazz Quartet (principally) ; Milt Jackson, vibraphone (2nd and 8th works) ; Oscar Peterson, piano (2nd and 8th works) ; Ray Brown, bass (2nd and 8th works) ; Ed Thigpen (2nd work), Louis Hayes (8th work), drums.</subfield>
  </datafield>
  <datafield tag="518" ind1=" " ind2=" ">
    <subfield code="a">Recorded live, Oct. 27, 1957, at the Donaueschingen Jazz Festival (1st, 5th, 7th, and 10th works); Dec. 1961, in New York (2nd work); live, Oct. 19, 1957, at the Opera House, Chicago (3rd, 4th, 6th, and 9th works); July 1971, in Villingen, Germany (8th work).</subfield>
  </datafield>
  <datafield tag="500" ind1=" " ind2=" ">
    <subfield code="a">Compact disc.</subfield>
  </datafield>
  <datafield tag="500" ind1=" " ind2=" ">
    <subfield code="a">Analog recording.</subfield>
  </datafield>
  <datafield tag="505" ind1="0" ind2=" ">
    <subfield code="a">The golden striker (4:08) -- On Green Dolphin Street (7:28) -- D &amp; E (4:55) -- I&apos;ll remember April (4:51) -- Cort©·ge (7:15) -- Now&apos;s the time (4:43) -- J.B. blues (5:09) -- Reunion blues (6:35) -- &apos;Round midnight (3:56) -- Three windows (7:20).</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="0">
    <subfield code="a">Jazz.</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2=" ">
    <subfield code="a">Jackson, Milt.</subfield>
    <subfield code="4">prf</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2=" ">
    <subfield code="a">Peterson, Oscar,</subfield>
    <subfield code="d">1925-</subfield>
    <subfield code="4">prf</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2=" ">
    <subfield code="a">Brown, Ray,</subfield>
    <subfield code="d">1926-2002.</subfield>
    <subfield code="4">prf</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2=" ">
    <subfield code="a">Thigpen, Ed.</subfield>
    <subfield code="4">prf</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2=" ">
    <subfield code="a">Hayes, Louis,</subfield>
    <subfield code="d">1937-</subfield>
    <subfield code="4">prf</subfield>
  </datafield>
  <datafield tag="852" ind1="8" ind2="0">
    <subfield code="b">MUSIC</subfield>
    <subfield code="c">AV</subfield>
    <subfield code="h">CD 1131</subfield>
    <subfield code="4">Marvin Duchow Music</subfield>
    <subfield code="5">Audio-Visual</subfield>
  </datafield>
</record>
</collection>
PK��Z��`��"test/File_MARC/tests/marc_012.phptnu�[���--TEST--
marc_012: test isControlField() and isDataField() convenience methods
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';
$marc_file = new File_MARC($dir . '/' . 'music.mrc');

while ($marc_record = $marc_file->next()) {
  $fields = $marc_record->getFields();
  foreach ($fields as $field) {
    print $field->getTag();
    if ($field->isControlField()) {
      print "\tControl field!";
    }
    if ($field->isDataField()) {
      print "\tData field!";
    }
    print "\n";
  }
}

?>
--EXPECT--
001	Control field!
004	Control field!
005	Control field!
008	Control field!
010	Data field!
035	Data field!
035	Data field!
040	Data field!
050	Data field!
245	Data field!
260	Data field!
300	Data field!
500	Data field!
505	Data field!
650	Data field!
650	Data field!
700	Data field!
700	Data field!
700	Data field!
740	Data field!
852	Data field!
001	Control field!
005	Control field!
007	Control field!
008	Control field!
024	Data field!
028	Data field!
035	Data field!
040	Data field!
100	Data field!
245	Data field!
260	Data field!
300	Data field!
511	Data field!
500	Data field!
518	Data field!
500	Data field!
500	Data field!
505	Data field!
650	Data field!
700	Data field!
710	Data field!
740	Data field!
001	Control field!
005	Control field!
007	Control field!
008	Control field!
024	Data field!
028	Data field!
033	Data field!
033	Data field!
033	Data field!
033	Data field!
035	Data field!
040	Data field!
048	Data field!
110	Data field!
245	Data field!
260	Data field!
300	Data field!
440	Data field!
511	Data field!
518	Data field!
500	Data field!
500	Data field!
505	Data field!
650	Data field!
700	Data field!
700	Data field!
700	Data field!
700	Data field!
700	Data field!
852	Data field!
PK��Z�S3"test/File_MARC/tests/marc_021.phptnu�[���--TEST--
marc_021: test MARC-in-JSON serialization with subfield 0
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';
$marc_file = new File_MARC($dir . '/' . 'example.mrc');

while ($marc_record = $marc_file->next()) {
  // create some subfields
  $subfields[] = new File_MARC_Subfield('0', 'nothing');
  $subfields[] = new File_MARC_Subfield('1', 'everything');
  $field = new File_MARC_Data_Field('999', $subfields, '', '');
  $marc_record->appendField($field);
  
  $subfields = null;
  $field = null;
  $subfields[] = new File_MARC_Subfield('a', 'bee');
  $subfields[] = new File_MARC_Subfield('0', 'cee');
  $subfields[] = new File_MARC_Subfield('d', 'eee');
  $field = new File_MARC_Data_Field('999', $subfields, '', '');

  $marc_record->appendField($field);

  print $marc_record->toJSON();
  print "\n";
}
?>
--EXPECT--
{"leader":"01850     2200517   4500","fields":[{"001":"0000000044"},{"003":"EMILDA"},{"008":"980120s1998    fi     j      000 0 swe"},{"020":{"ind1":" ","ind2":" ","subfields":[{"a":"9515008808"},{"c":"FIM 72:00"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"9":"9515008808"}]}},{"040":{"ind1":" ","ind2":" ","subfields":[{"a":"NB"}]}},{"042":{"ind1":" ","ind2":" ","subfields":[{"9":"NB"},{"9":"SEE"}]}},{"084":{"ind1":" ","ind2":" ","subfields":[{"a":"Hcd,u"},{"2":"kssb\/6"}]}},{"084":{"ind1":" ","ind2":" ","subfields":[{"5":"NB"},{"a":"uHc"},{"2":"kssb"}]}},{"084":{"ind1":" ","ind2":" ","subfields":[{"5":"SEE"},{"a":"Hcf"},{"2":"kssb\/6"}]}},{"084":{"ind1":" ","ind2":" ","subfields":[{"5":"Q"},{"a":"Hcd,uf"},{"2":"kssb\/6"}]}},{"100":{"ind1":"1","ind2":" ","subfields":[{"a":"Jansson, Tove,"},{"d":"1914-2001"}]}},{"245":{"ind1":"0","ind2":"4","subfields":[{"a":"Det osynliga barnet och andra ber\u00e4ttelser \/"},{"c":"Tove Jansson"}]}},{"250":{"ind1":" ","ind2":" ","subfields":[{"a":"7. uppl."}]}},{"260":{"ind1":" ","ind2":" ","subfields":[{"a":"Helsingfors :"},{"b":"Schildt,"},{"c":"1998 ;"},{"e":"(Falun :"},{"f":"Scandbook)"}]}},{"300":{"ind1":" ","ind2":" ","subfields":[{"a":"166, [4] s. :"},{"b":"ill. ;"},{"c":"21 cm"}]}},{"440":{"ind1":" ","ind2":"0","subfields":[{"a":"Mumin-biblioteket,"},{"x":"99-0698931-9"}]}},{"500":{"ind1":" ","ind2":" ","subfields":[{"a":"Originaluppl. 1962"}]}},{"599":{"ind1":" ","ind2":" ","subfields":[{"a":"Li: S"}]}},{"740":{"ind1":"4","ind2":" ","subfields":[{"a":"Det osynliga barnet"}]}},{"775":{"ind1":"1","ind2":" ","subfields":[{"z":"951-50-0385-7"},{"w":"9515003857"},{"9":"07"}]}},{"841":{"ind1":" ","ind2":" ","subfields":[{"5":"Li"},{"a":"xa"},{"b":"0201080u    0   4000uu   |000000"},{"e":"1"}]}},{"841":{"ind1":" ","ind2":" ","subfields":[{"5":"SEE"},{"a":"xa"},{"b":"0201080u    0   4000uu   |000000"},{"e":"1"}]}},{"841":{"ind1":" ","ind2":" ","subfields":[{"5":"L"},{"a":"xa"},{"b":"0201080u    0   4000uu   |000000"},{"e":"1"}]}},{"841":{"ind1":" ","ind2":" ","subfields":[{"5":"NB"},{"a":"xa"},{"b":"0201080u    0   4000uu   |000000"},{"e":"1"}]}},{"841":{"ind1":" ","ind2":" ","subfields":[{"5":"Q"},{"a":"xa"},{"b":"0201080u    0   4000uu   |000000"},{"e":"1"}]}},{"841":{"ind1":" ","ind2":" ","subfields":[{"5":"S"},{"a":"xa"},{"b":"0201080u    0   4000uu   |000000"},{"e":"1"}]}},{"852":{"ind1":" ","ind2":" ","subfields":[{"5":"NB"},{"b":"NB"},{"c":"NB98:12"},{"h":"plikt"},{"j":"R, 980520"}]}},{"852":{"ind1":" ","ind2":" ","subfields":[{"5":"Li"},{"b":"Li"},{"c":"CNB"},{"h":"h,u"}]}},{"852":{"ind1":" ","ind2":" ","subfields":[{"5":"SEE"},{"b":"SEE"}]}},{"852":{"ind1":" ","ind2":" ","subfields":[{"5":"Q"},{"b":"Q"},{"j":"98947"}]}},{"852":{"ind1":" ","ind2":" ","subfields":[{"5":"L"},{"b":"L"},{"c":"0100"},{"h":"98\/"},{"j":"3043 H"}]}},{"852":{"ind1":" ","ind2":" ","subfields":[{"5":"S"},{"b":"S"},{"h":"Sv97"},{"j":"7235"}]}},{"900":{"ind1":"1","ind2":"s","subfields":[{"a":"Yanson, Tobe,"},{"d":"1914-2001"},{"u":"Jansson, Tove,"},{"d":"1914-2001"}]}},{"900":{"ind1":"1","ind2":"s","subfields":[{"a":"Janssonov\u00e1, Tove,"},{"d":"1914-2001"},{"u":"Jansson, Tove,"},{"d":"1914-2001"}]}},{"900":{"ind1":"1","ind2":"s","subfields":[{"a":"Jansone, Tuve,"},{"d":"1914-2001"},{"u":"Jansson, Tove,"},{"d":"1914-2001"}]}},{"900":{"ind1":"1","ind2":"s","subfields":[{"a":"Janson, Tuve,"},{"d":"1914-2001"},{"u":"Jansson, Tove,"},{"d":"1914-2001"}]}},{"900":{"ind1":"1","ind2":"s","subfields":[{"a":"Jansson, Tuve,"},{"d":"1914-2001"},{"u":"Jansson, Tove,"},{"d":"1914-2001"}]}},{"900":{"ind1":"1","ind2":"s","subfields":[{"a":"Janssonova, Tove,"},{"d":"1914-2001"},{"u":"Jansson, Tove,"},{"d":"1914-2001"}]}},{"976":{"ind1":" ","ind2":"2","subfields":[{"a":"Hcd,u"},{"b":"Sk\u00f6nlitteratur"}]}},{"005":"20050204111518.0"},{"999":{"ind1":" ","ind2":" ","subfields":[{"0":"nothing"},{"1":"everything"}]}},{"999":{"ind1":" ","ind2":" ","subfields":[{"a":"bee"},{"0":"cee"},{"d":"eee"}]}}]}
PK��Z<��--+test/File_MARC/tests/marc_subfield_002.phptnu�[���--TEST--
marc_subfield_002: Exercise setter and isEmpty() methods for File_MARC_Subfield class
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';

function testEmpty($testSubfield) {
  print "Subfield is ";
  if ($testSubfield->isEmpty()) {
    print "empty.\n";
  }
  else {
    print "not empty.\n";
  }

}

$subfield = new File_MARC_Subfield('a', 'wasssup');

// test isEmpty() scenarios
testEmpty($subfield);

$subfield->setData(null);
testEmpty($subfield);

$subfield->setData('just hangin');
testEmpty($subfield);

// test setCode() scenarios
print "\nSet code to 'z'...";
if ($subfield->setCode('z')) {
  print "\n";
  print $subfield;
}

print "\nSet code to ''...";
if ($subfield->setCode('')) {
  print "\n";
  print $subfield;
}

print "\nSet code to null...";
if ($subfield->setCode(null)) {
  print "\n";
  print $subfield;
}

?>
--EXPECT--
Subfield is not empty.
Subfield is empty.
Subfield is not empty.

Set code to 'z'...
[z]: just hangin
Set code to ''...
Set code to null...
PK��Z�f==$test/File_MARC/tests/bad_example.mrcnu�[���01853    a2200517   450000100110000000300070001100800390001802000260005703500150008304000070009804200120010508400180011708400180013508400210015308400220017410000300019624500630022625000130028926000580030230-0033003604400037003935000023004305990010004537400024004637750034004878410048005218410049005698410047006188410048006658410047007138410047007608520038008078520021008458520013008668520016008798520028008958520021009239000056009449000061010009000057010619000056011189000057011749000060012319760027012910050017013180000000044EMILDA980120s1998    fi     j      000 0 swe  a9515008808cFIM 72:00  99515008808  aNB  9NB9SEE  aHcd,u2kssb/6  5NBauHc2kssb  5SEEaHcf2kssb/6  5QaHcd,uf2kssb/61 aJansson, Tove,d1914-200104aDet osynliga barnet och andra bert̃telser /cTove Jansson  a7. uppl.  aHelsingfors :bSchildt,c1998 ;e(Falun :fScandbook)  a166, [4] s. :bill. ;c21 cm 0aMumin-biblioteket,x99-0698931-9  aOriginaluppl. 1962  aLi: S4 aDet osynliga barnet1 z951-50-0385-7w9515003857907  5Liaxab0201080u    0   4000uu   |000000e1  5SEEaxab0201080u    0   4000uu   |000000e1  5Laxab0201080u    0   4000uu   |000000e1  5NBaxab0201080u    0   4000uu   |000000e1  5Qaxab0201080u    0   4000uu   |000000e1  5Saxab0201080u    0   4000uu   |000000e1  5NBbNBcNB98:12hpliktjR, 980520  5LibLicCNBhh,u  5SEEbSEE  5QbQj98947  5LbLc0100h98/j3043 H  5SbShSv97j72351saYanson, Tobe,d1914-2001uJansson, Tove,d1914-20011saJanssonov,̀ Tove,d1914-2001uJansson, Tove,d1914-20011saJansone, Tuve,d1914-2001uJansson, Tove,d1914-20011saJanson, Tuve,d1914-2001uJansson, Tove,d1914-20011saJansson, Tuve,d1914-2001uJansson, Tove,d1914-20011saJanssonova, Tove,d1914-2001uJansson, Tove,d1914-2001 2aHcd,ubSkn̲litteratur20050204111518.0PK��Z�kP�"test/File_MARC/tests/marc_023.phptnu�[���--TEST--
marc_023: test extended Record interface
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';

class MyRecord extends File_MARC_Record {
  public function myNewMethod() {
    return $this->getField('040')->getSubfield('a')->getData();
  }
}

$marc_file = new File_MARC($dir . '/' . 'example.mrc', File_MARC::SOURCE_FILE, MyRecord::class);

$rec = $marc_file->next();
print get_class($rec) . "\n";
print $rec->myNewMethod() . "\n";

?>
--EXPECT--
MyRecord
NB
PK��ZW��))"test/File_MARC/tests/marc_019.phptnu�[���--TEST--
marc_019: generate a MARCXML record not in a collection element
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';

$records = new File_MARC($dir . '/' . 'music.mrc');

// Iterate through the retrieved records
$record = $records->next();

// Change each 852 $c to "Audio-Visual"
$holdings = $record->getFields('852');
foreach ($holdings as $holding) {

    // Get the $c subfields from this field
    $formats = $holding->getSubfields('c');
    foreach ($formats as $format) {
        if ($format->getData('AV')) {
            $format->setData('Audio-Visual');
        }
    }
}

// Generate the XML output for this record
print($record->toXML('UTF-8', true, true));
--EXPECT--
<?xml version="1.0" encoding="UTF-8"?>
<collection xmlns="http://www.loc.gov/MARC21/slim">
 <record>
  <leader>01145ncm  2200277 i 4500</leader>
  <controlfield tag="001">000073594</controlfield>
  <controlfield tag="004">AAJ5802</controlfield>
  <controlfield tag="005">20030415102100.0</controlfield>
  <controlfield tag="008">801107s1977    nyujza                   </controlfield>
  <datafield tag="010" ind1=" " ind2=" ">
   <subfield code="a">   77771106 </subfield>
  </datafield>
  <datafield tag="035" ind1=" " ind2=" ">
   <subfield code="a">(CaOTUIC)15460184</subfield>
  </datafield>
  <datafield tag="035" ind1="9" ind2=" ">
   <subfield code="a">AAJ5802</subfield>
  </datafield>
  <datafield tag="040" ind1=" " ind2=" ">
   <subfield code="a">LC</subfield>
  </datafield>
  <datafield tag="050" ind1="0" ind2="0">
   <subfield code="a">M1366</subfield>
   <subfield code="b">.M62</subfield>
   <subfield code="d">M1527.2</subfield>
  </datafield>
  <datafield tag="245" ind1="0" ind2="4">
   <subfield code="a">The Modern Jazz Quartet :</subfield>
   <subfield code="b">The legendary profile. --</subfield>
  </datafield>
  <datafield tag="260" ind1=" " ind2=" ">
   <subfield code="a">New York :</subfield>
   <subfield code="b">M.J.Q. Music,</subfield>
   <subfield code="c">c1977.</subfield>
  </datafield>
  <datafield tag="300" ind1=" " ind2=" ">
   <subfield code="a">score (72 p.) ;</subfield>
   <subfield code="c">31 cm.</subfield>
  </datafield>
  <datafield tag="500" ind1=" " ind2=" ">
   <subfield code="a">For piano, vibraphone, drums, and double bass.</subfield>
  </datafield>
  <datafield tag="505" ind1="0" ind2=" ">
   <subfield code="a">Lewis, J. Django.--Lewis, J. Plastic dreams (music from the film Kemek).--Lewis, J. Dancing (music from the film Kemek).--Lewis, J. Blues in A minor.--Lewis, J. Blues in B♭.--Lewis, J. Precious joy.--Jackson, M. The martyr.--Jackson, M. The legendary profile.</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="0">
   <subfield code="a">Jazz.</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="0">
   <subfield code="a">Motion picture music</subfield>
   <subfield code="v">Excerpts</subfield>
   <subfield code="v">Scores.</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2="2">
   <subfield code="a">Lewis, John,</subfield>
   <subfield code="d">1920-</subfield>
   <subfield code="t">Selections.</subfield>
   <subfield code="f">1977.</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2="2">
   <subfield code="a">Jackson, Milt.</subfield>
   <subfield code="t">Martyrs.</subfield>
   <subfield code="f">1977.</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2="2">
   <subfield code="a">Jackson, Milt.</subfield>
   <subfield code="t">Legendary profile.</subfield>
   <subfield code="f">1977.</subfield>
  </datafield>
  <datafield tag="740" ind1="4" ind2=" ">
   <subfield code="a">The legendary profile.</subfield>
  </datafield>
  <datafield tag="852" ind1="0" ind2="0">
   <subfield code="b">MUSIC</subfield>
   <subfield code="c">Audio-Visual</subfield>
   <subfield code="k">folio</subfield>
   <subfield code="h">M1366</subfield>
   <subfield code="i">M62</subfield>
   <subfield code="9">1</subfield>
   <subfield code="4">Marvin Duchow Music</subfield>
   <subfield code="5"></subfield>
  </datafield>
 </record>
</collection>
PK��Z�泮�test/File_MARC/tests/music.mrcnu�[���01145ncm  2200277 i 4500001001000000004000800010005001700018008004100035010001700076035002200093035001200115040000700127050002500134245005700159260003800216300002800254500005100282505026600333650001000599650004400609700004400653700003600697700004600733740002700779852006100806000073594AAJ580220030415102100.0801107s1977    nyujza                     a   77771106   a(CaOTUIC)154601849 aAAJ5802  aLC00aM1366b.M62dM1527.204aThe Modern Jazz Quartet :bThe legendary profile. --  aNew York :bM.J.Q. Music,cc1977.  ascore (72 p.) ;c31 cm.  aFor piano, vibraphone, drums, and double bass.0 aLewis, J. Django.--Lewis, J. Plastic dreams (music from the film Kemek).--Lewis, J. Dancing (music from the film Kemek).--Lewis, J. Blues in A minor.--Lewis, J. Blues in B♭.--Lewis, J. Precious joy.--Jackson, M. The martyr.--Jackson, M. The legendary profile. 0aJazz. 0aMotion picture musicvExcerptsvScores.12aLewis, John,d1920-tSelections.f1977.12aJackson, Milt.tMartyrs.f1977.12aJackson, Milt.tLegendary profile.f1977.4 aThe legendary profile.00bMUSICcMAINkfoliohM1366iM62914Marvin Duchow Music5
01293cjm  2200289 a 450000100100000000500170001000700150002700800410004202400150008302800240009803500200012204000180014210000260016024500620018626000850024830000510033351101380038450000360052251800580055850000590061650000700067550501420074565000210088770000240090871000250093274000460095700187803920050110174900.0sd fungnn|||e|940202r19931981nyujzn   i              d1 a746457337202aJK 57337bRed Baron  a(OCoLC)29737267  aSVPcSVPdLGG1 aDesmond, Paul,d1924-10aPaul Desmond & the Modern Jazz Quarteth[sound recording]  aNew York, N.Y. :bRed Baron :bManufactured by Sony Music Entertainment,cp1993.  a1 sound disc (39 min.) :bdigital ;c4 3/4 in.0 aPaul Desmond, alto saxophone; Modern Jazz Quartet: John Lewis, piano; Milt Jackson, vibraphone; Percy Heath, bass; Connie Kay, drums.  aAll arrangements by John Lewis.  aRecorded live on December 25, 1971 at Town Hall, NYC.  aOriginally released in 1981 by Finesse as LP FW 27487.  aProgram notes by Irving Townsend, June 1981, on container insert.0 aGreensleeves -- You go to my head -- Blue dove -- Jesus Christ Superstar -- Here's that rainy day -- East of the sun -- Bags' new groove. 0aJazzy1971-1980.1 aLewis, John,d1920-2 aModern Jazz Quartet.0 aPaul Desmond and the Modern Jazz Quartet.
01829cjm  2200385 a 450000100100000000500170001000700150002700800410004202400150008302800210009803300240011903300230014303300230016603300230018903500200021204000230023204800270025511000300028224500530031226000330036530000410039844000170043951102230045651802640067950000180094350000220096150502500098365000100123370000240124370000330126770000330130070000220133370000300135585200580138500196448220060626132700.0sd fzngnn|m|e|871211p19871957nyujzn                  d1 a422833290201a833 290-2bVerve0 a19571027b6299cD560 a196112--b3804cN40 a19571019b4104cC60 a197107--b6299cV7  a(OCoLC)17222092  aCPLcCPLdOCLdLGG  apz01aka01asd01apd012 aModern Jazz Quartet.4prf14aThe Modern Jazz Quartet plush[sound recording].  a[New York] :bVerve,cp1987.  a1 sound disc :bdigital ;c4 3/4 in. 0aCompact jazz0 aModern Jazz Quartet (principally) ; Milt Jackson, vibraphone (2nd and 8th works) ; Oscar Peterson, piano (2nd and 8th works) ; Ray Brown, bass (2nd and 8th works) ; Ed Thigpen (2nd work), Louis Hayes (8th work), drums.  aRecorded live, Oct. 27, 1957, at the Donaueschingen Jazz Festival (1st, 5th, 7th, and 10th works); Dec. 1961, in New York (2nd work); live, Oct. 19, 1957, at the Opera House, Chicago (3rd, 4th, 6th, and 9th works); July 1971, in Villingen, Germany (8th work).  aCompact disc.  aAnalog recording.0 aThe golden striker (4:08) -- On Green Dolphin Street (7:28) -- D & E (4:55) -- I'll remember April (4:51) -- Cortège (7:15) -- Now's the time (4:43) -- J.B. blues (5:09) -- Reunion blues (6:35) -- 'Round midnight (3:56) -- Three windows (7:20). 0aJazz.1 aJackson, Milt.4prf1 aPeterson, Oscar,d1925-4prf1 aBrown, Ray,d1926-2002.4prf1 aThigpen, Ed.4prf1 aHayes, Louis,d1937-4prf80bMUSICcAVhCD 11314Marvin Duchow Music5Audio-Visual
PK��ZE4kL�	�	"test/File_MARC/tests/marc_001.phptnu�[���--TEST--
marc_001: iterate and pretty print a MARC record
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';
$marc_file = new File_MARC($dir . '/' . 'example.mrc');

while ($marc_record = $marc_file->next()) {
  print $marc_record;
  print "\n";
}
?>
--EXPECT--
LDR 01850     2200517   4500
001     0000000044
003     EMILDA
008     980120s1998    fi     j      000 0 swe
020    _a9515008808
       _cFIM 72:00
035    _99515008808
040    _aNB
042    _9NB
       _9SEE
084    _aHcd,u
       _2kssb/6
084    _5NB
       _auHc
       _2kssb
084    _5SEE
       _aHcf
       _2kssb/6
084    _5Q
       _aHcd,uf
       _2kssb/6
100 1  _aJansson, Tove,
       _d1914-2001
245 04 _aDet osynliga barnet och andra ber�ttelser /
       _cTove Jansson
250    _a7. uppl.
260    _aHelsingfors :
       _bSchildt,
       _c1998 ;
       _e(Falun :
       _fScandbook)
300    _a166, [4] s. :
       _bill. ;
       _c21 cm
440  0 _aMumin-biblioteket,
       _x99-0698931-9
500    _aOriginaluppl. 1962
599    _aLi: S
740 4  _aDet osynliga barnet
775 1  _z951-50-0385-7
       _w9515003857
       _907
841    _5Li
       _axa
       _b0201080u    0   4000uu   |000000
       _e1
841    _5SEE
       _axa
       _b0201080u    0   4000uu   |000000
       _e1
841    _5L
       _axa
       _b0201080u    0   4000uu   |000000
       _e1
841    _5NB
       _axa
       _b0201080u    0   4000uu   |000000
       _e1
841    _5Q
       _axa
       _b0201080u    0   4000uu   |000000
       _e1
841    _5S
       _axa
       _b0201080u    0   4000uu   |000000
       _e1
852    _5NB
       _bNB
       _cNB98:12
       _hplikt
       _jR, 980520
852    _5Li
       _bLi
       _cCNB
       _hh,u
852    _5SEE
       _bSEE
852    _5Q
       _bQ
       _j98947
852    _5L
       _bL
       _c0100
       _h98/
       _j3043 H
852    _5S
       _bS
       _hSv97
       _j7235
900 1s _aYanson, Tobe,
       _d1914-2001
       _uJansson, Tove,
       _d1914-2001
900 1s _aJanssonov�, Tove,
       _d1914-2001
       _uJansson, Tove,
       _d1914-2001
900 1s _aJansone, Tuve,
       _d1914-2001
       _uJansson, Tove,
       _d1914-2001
900 1s _aJanson, Tuve,
       _d1914-2001
       _uJansson, Tove,
       _d1914-2001
900 1s _aJansson, Tuve,
       _d1914-2001
       _uJansson, Tove,
       _d1914-2001
900 1s _aJanssonova, Tove,
       _d1914-2001
       _uJansson, Tove,
       _d1914-2001
976  2 _aHcd,u
       _bSk�nlitteratur
005     20050204111518.0
PK��Z�#"�
)
)"test/File_MARC/tests/marc_022.phptnu�[���--TEST--
marc_022: Insert fields
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';
$marc_file = new File_MARC($dir . '/' . 'music.mrc');

print "\nInsert a new 100 field before the first 650\n";
while ($record = $marc_file->next()) {
  print "\nNext record:\n";
  // Create the new field
  $subfields = null;
  $subfields[] = new File_MARC_Subfield('a', 'Scott, Daniel.');
  $new_field = new File_MARC_Data_Field('100', $subfields, 0, null);

  // Retrieve the target field for our insertion point
  $subject = $record->getFields('650');

  // Insert the new field
  if (is_array($subject)) {
    $record->insertField($new_field, $subject[0], true);
  }
  elseif ($subject) {
    $record->insertField($new_field, $subject, true);
  }
  print $record;
}

$record = null;
$marc_file = new File_MARC($dir . '/' . 'music.mrc');
print "\nInsert a new 100 field after the first 650\n";
while ($record = $marc_file->next()) {
  print "\nNext record:\n";
  // Create the new field
  $subfields = null;
  $subfields[] = new File_MARC_Subfield('a', 'Scott, Daniel.');
  $new_field = new File_MARC_Data_Field('100', $subfields, 0, null);

  // Retrieve the target field for our insertion point
  $subject = $record->getFields('650');

  // Insert the new field
  if (is_array($subject)) {
    $record->insertField($new_field, $subject[0]);
  }
  elseif ($subject) {
    $record->insertField($new_field, $subject);
  }
  print $record;
}
?>
--EXPECT--
Insert a new 100 field before the first 650

Next record:
LDR 01145ncm  2200277 i 4500
001     000073594
004     AAJ5802
005     20030415102100.0
008     801107s1977    nyujza                   
010    _a   77771106 
035    _a(CaOTUIC)15460184
035 9  _aAAJ5802
040    _aLC
050 00 _aM1366
       _b.M62
       _dM1527.2
245 04 _aThe Modern Jazz Quartet :
       _bThe legendary profile. --
260    _aNew York :
       _bM.J.Q. Music,
       _cc1977.
300    _ascore (72 p.) ;
       _c31 cm.
500    _aFor piano, vibraphone, drums, and double bass.
505 0  _aLewis, J. Django.--Lewis, J. Plastic dreams (music from the film Kemek).--Lewis, J. Dancing (music from the film Kemek).--Lewis, J. Blues in A minor.--Lewis, J. Blues in B♭.--Lewis, J. Precious joy.--Jackson, M. The martyr.--Jackson, M. The legendary profile.
100    _aScott, Daniel.
650  0 _aJazz.
650  0 _aMotion picture music
       _vExcerpts
       _vScores.
700 12 _aLewis, John,
       _d1920-
       _tSelections.
       _f1977.
700 12 _aJackson, Milt.
       _tMartyrs.
       _f1977.
700 12 _aJackson, Milt.
       _tLegendary profile.
       _f1977.
740 4  _aThe legendary profile.
852 00 _bMUSIC
       _cMAIN
       _kfolio
       _hM1366
       _iM62
       _91
       _4Marvin Duchow Music
       _5

Next record:
LDR 01293cjm  2200289 a 4500
001     001878039
005     20050110174900.0
007     sd fungnn|||e|
008     940202r19931981nyujzn   i              d
024 1  _a7464573372
028 02 _aJK 57337
       _bRed Baron
035    _a(OCoLC)29737267
040    _aSVP
       _cSVP
       _dLGG
100 1  _aDesmond, Paul,
       _d1924-
245 10 _aPaul Desmond & the Modern Jazz Quartet
       _h[sound recording]
260    _aNew York, N.Y. :
       _bRed Baron :
       _bManufactured by Sony Music Entertainment,
       _cp1993.
300    _a1 sound disc (39 min.) :
       _bdigital ;
       _c4 3/4 in.
511 0  _aPaul Desmond, alto saxophone; Modern Jazz Quartet: John Lewis, piano; Milt Jackson, vibraphone; Percy Heath, bass; Connie Kay, drums.
500    _aAll arrangements by John Lewis.
518    _aRecorded live on December 25, 1971 at Town Hall, NYC.
500    _aOriginally released in 1981 by Finesse as LP FW 27487.
500    _aProgram notes by Irving Townsend, June 1981, on container insert.
505 0  _aGreensleeves -- You go to my head -- Blue dove -- Jesus Christ Superstar -- Here's that rainy day -- East of the sun -- Bags' new groove.
100    _aScott, Daniel.
650  0 _aJazz
       _y1971-1980.
700 1  _aLewis, John,
       _d1920-
710 2  _aModern Jazz Quartet.
740 0  _aPaul Desmond and the Modern Jazz Quartet.

Next record:
LDR 01829cjm  2200385 a 4500
001     001964482
005     20060626132700.0
007     sd fzngnn|m|e|
008     871211p19871957nyujzn                  d
024 1  _a4228332902
028 01 _a833 290-2
       _bVerve
033 0  _a19571027
       _b6299
       _cD56
033 0  _a196112--
       _b3804
       _cN4
033 0  _a19571019
       _b4104
       _cC6
033 0  _a197107--
       _b6299
       _cV7
035    _a(OCoLC)17222092
040    _aCPL
       _cCPL
       _dOCL
       _dLGG
048    _apz01
       _aka01
       _asd01
       _apd01
110 2  _aModern Jazz Quartet.
       _4prf
245 14 _aThe Modern Jazz Quartet plus
       _h[sound recording].
260    _a[New York] :
       _bVerve,
       _cp1987.
300    _a1 sound disc :
       _bdigital ;
       _c4 3/4 in.
440  0 _aCompact jazz
511 0  _aModern Jazz Quartet (principally) ; Milt Jackson, vibraphone (2nd and 8th works) ; Oscar Peterson, piano (2nd and 8th works) ; Ray Brown, bass (2nd and 8th works) ; Ed Thigpen (2nd work), Louis Hayes (8th work), drums.
518    _aRecorded live, Oct. 27, 1957, at the Donaueschingen Jazz Festival (1st, 5th, 7th, and 10th works); Dec. 1961, in New York (2nd work); live, Oct. 19, 1957, at the Opera House, Chicago (3rd, 4th, 6th, and 9th works); July 1971, in Villingen, Germany (8th work).
500    _aCompact disc.
500    _aAnalog recording.
505 0  _aThe golden striker (4:08) -- On Green Dolphin Street (7:28) -- D & E (4:55) -- I'll remember April (4:51) -- Cortège (7:15) -- Now's the time (4:43) -- J.B. blues (5:09) -- Reunion blues (6:35) -- 'Round midnight (3:56) -- Three windows (7:20).
100    _aScott, Daniel.
650  0 _aJazz.
700 1  _aJackson, Milt.
       _4prf
700 1  _aPeterson, Oscar,
       _d1925-
       _4prf
700 1  _aBrown, Ray,
       _d1926-2002.
       _4prf
700 1  _aThigpen, Ed.
       _4prf
700 1  _aHayes, Louis,
       _d1937-
       _4prf
852 80 _bMUSIC
       _cAV
       _hCD 1131
       _4Marvin Duchow Music
       _5Audio-Visual

Insert a new 100 field after the first 650

Next record:
LDR 01145ncm  2200277 i 4500
001     000073594
004     AAJ5802
005     20030415102100.0
008     801107s1977    nyujza                   
010    _a   77771106 
035    _a(CaOTUIC)15460184
035 9  _aAAJ5802
040    _aLC
050 00 _aM1366
       _b.M62
       _dM1527.2
245 04 _aThe Modern Jazz Quartet :
       _bThe legendary profile. --
260    _aNew York :
       _bM.J.Q. Music,
       _cc1977.
300    _ascore (72 p.) ;
       _c31 cm.
500    _aFor piano, vibraphone, drums, and double bass.
505 0  _aLewis, J. Django.--Lewis, J. Plastic dreams (music from the film Kemek).--Lewis, J. Dancing (music from the film Kemek).--Lewis, J. Blues in A minor.--Lewis, J. Blues in B♭.--Lewis, J. Precious joy.--Jackson, M. The martyr.--Jackson, M. The legendary profile.
650  0 _aJazz.
100    _aScott, Daniel.
650  0 _aMotion picture music
       _vExcerpts
       _vScores.
700 12 _aLewis, John,
       _d1920-
       _tSelections.
       _f1977.
700 12 _aJackson, Milt.
       _tMartyrs.
       _f1977.
700 12 _aJackson, Milt.
       _tLegendary profile.
       _f1977.
740 4  _aThe legendary profile.
852 00 _bMUSIC
       _cMAIN
       _kfolio
       _hM1366
       _iM62
       _91
       _4Marvin Duchow Music
       _5

Next record:
LDR 01293cjm  2200289 a 4500
001     001878039
005     20050110174900.0
007     sd fungnn|||e|
008     940202r19931981nyujzn   i              d
024 1  _a7464573372
028 02 _aJK 57337
       _bRed Baron
035    _a(OCoLC)29737267
040    _aSVP
       _cSVP
       _dLGG
100 1  _aDesmond, Paul,
       _d1924-
245 10 _aPaul Desmond & the Modern Jazz Quartet
       _h[sound recording]
260    _aNew York, N.Y. :
       _bRed Baron :
       _bManufactured by Sony Music Entertainment,
       _cp1993.
300    _a1 sound disc (39 min.) :
       _bdigital ;
       _c4 3/4 in.
511 0  _aPaul Desmond, alto saxophone; Modern Jazz Quartet: John Lewis, piano; Milt Jackson, vibraphone; Percy Heath, bass; Connie Kay, drums.
500    _aAll arrangements by John Lewis.
518    _aRecorded live on December 25, 1971 at Town Hall, NYC.
500    _aOriginally released in 1981 by Finesse as LP FW 27487.
500    _aProgram notes by Irving Townsend, June 1981, on container insert.
505 0  _aGreensleeves -- You go to my head -- Blue dove -- Jesus Christ Superstar -- Here's that rainy day -- East of the sun -- Bags' new groove.
650  0 _aJazz
       _y1971-1980.
100    _aScott, Daniel.
700 1  _aLewis, John,
       _d1920-
710 2  _aModern Jazz Quartet.
740 0  _aPaul Desmond and the Modern Jazz Quartet.

Next record:
LDR 01829cjm  2200385 a 4500
001     001964482
005     20060626132700.0
007     sd fzngnn|m|e|
008     871211p19871957nyujzn                  d
024 1  _a4228332902
028 01 _a833 290-2
       _bVerve
033 0  _a19571027
       _b6299
       _cD56
033 0  _a196112--
       _b3804
       _cN4
033 0  _a19571019
       _b4104
       _cC6
033 0  _a197107--
       _b6299
       _cV7
035    _a(OCoLC)17222092
040    _aCPL
       _cCPL
       _dOCL
       _dLGG
048    _apz01
       _aka01
       _asd01
       _apd01
110 2  _aModern Jazz Quartet.
       _4prf
245 14 _aThe Modern Jazz Quartet plus
       _h[sound recording].
260    _a[New York] :
       _bVerve,
       _cp1987.
300    _a1 sound disc :
       _bdigital ;
       _c4 3/4 in.
440  0 _aCompact jazz
511 0  _aModern Jazz Quartet (principally) ; Milt Jackson, vibraphone (2nd and 8th works) ; Oscar Peterson, piano (2nd and 8th works) ; Ray Brown, bass (2nd and 8th works) ; Ed Thigpen (2nd work), Louis Hayes (8th work), drums.
518    _aRecorded live, Oct. 27, 1957, at the Donaueschingen Jazz Festival (1st, 5th, 7th, and 10th works); Dec. 1961, in New York (2nd work); live, Oct. 19, 1957, at the Opera House, Chicago (3rd, 4th, 6th, and 9th works); July 1971, in Villingen, Germany (8th work).
500    _aCompact disc.
500    _aAnalog recording.
505 0  _aThe golden striker (4:08) -- On Green Dolphin Street (7:28) -- D & E (4:55) -- I'll remember April (4:51) -- Cortège (7:15) -- Now's the time (4:43) -- J.B. blues (5:09) -- Reunion blues (6:35) -- 'Round midnight (3:56) -- Three windows (7:20).
650  0 _aJazz.
100    _aScott, Daniel.
700 1  _aJackson, Milt.
       _4prf
700 1  _aPeterson, Oscar,
       _d1925-
       _4prf
700 1  _aBrown, Ray,
       _d1926-2002.
       _4prf
700 1  _aThigpen, Ed.
       _4prf
700 1  _aHayes, Louis,
       _d1937-
       _4prf
852 80 _bMUSIC
       _cAV
       _hCD 1131
       _4Marvin Duchow Music
       _5Audio-Visual
PK��Z�p̎u1u1"test/File_MARC/tests/marc_016.phptnu�[���--TEST--
marc_016: generate a single collection of MARCXML records from a MARC record
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';

$records = new File_MARC($dir . '/' . 'music.mrc');

// Add the XML header and opening <collection> element
$records->toXMLHeader();

// Iterate through the retrieved records
while ($record = $records->next()) {

    // Change each 852 $c to "Audio-Visual"
    $holdings = $record->getFields('852');
    foreach ($holdings as $holding) {

        // Get the $c subfields from this field
        $formats = $holding->getSubfields('c');
        foreach ($formats as $format) {
            if ($format->getData('AV')) {
                $format->setData('Audio-Visual');
            }
        }
    }

    // Generate the XML output for this record
    print $record->toXML('UTF-8', true, false);
}
// Add the </collection> closing element and dump the XMLWriter contents
print $records->toXMLFooter();
--EXPECT--
<?xml version="1.0" encoding="UTF-8"?>
<collection xmlns="http://www.loc.gov/MARC21/slim">
 <record xmlns="http://www.loc.gov/MARC21/slim">
  <leader>01145ncm  2200277 i 4500</leader>
  <controlfield tag="001">000073594</controlfield>
  <controlfield tag="004">AAJ5802</controlfield>
  <controlfield tag="005">20030415102100.0</controlfield>
  <controlfield tag="008">801107s1977    nyujza                   </controlfield>
  <datafield tag="010" ind1=" " ind2=" ">
   <subfield code="a">   77771106 </subfield>
  </datafield>
  <datafield tag="035" ind1=" " ind2=" ">
   <subfield code="a">(CaOTUIC)15460184</subfield>
  </datafield>
  <datafield tag="035" ind1="9" ind2=" ">
   <subfield code="a">AAJ5802</subfield>
  </datafield>
  <datafield tag="040" ind1=" " ind2=" ">
   <subfield code="a">LC</subfield>
  </datafield>
  <datafield tag="050" ind1="0" ind2="0">
   <subfield code="a">M1366</subfield>
   <subfield code="b">.M62</subfield>
   <subfield code="d">M1527.2</subfield>
  </datafield>
  <datafield tag="245" ind1="0" ind2="4">
   <subfield code="a">The Modern Jazz Quartet :</subfield>
   <subfield code="b">The legendary profile. --</subfield>
  </datafield>
  <datafield tag="260" ind1=" " ind2=" ">
   <subfield code="a">New York :</subfield>
   <subfield code="b">M.J.Q. Music,</subfield>
   <subfield code="c">c1977.</subfield>
  </datafield>
  <datafield tag="300" ind1=" " ind2=" ">
   <subfield code="a">score (72 p.) ;</subfield>
   <subfield code="c">31 cm.</subfield>
  </datafield>
  <datafield tag="500" ind1=" " ind2=" ">
   <subfield code="a">For piano, vibraphone, drums, and double bass.</subfield>
  </datafield>
  <datafield tag="505" ind1="0" ind2=" ">
   <subfield code="a">Lewis, J. Django.--Lewis, J. Plastic dreams (music from the film Kemek).--Lewis, J. Dancing (music from the film Kemek).--Lewis, J. Blues in A minor.--Lewis, J. Blues in B♭.--Lewis, J. Precious joy.--Jackson, M. The martyr.--Jackson, M. The legendary profile.</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="0">
   <subfield code="a">Jazz.</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="0">
   <subfield code="a">Motion picture music</subfield>
   <subfield code="v">Excerpts</subfield>
   <subfield code="v">Scores.</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2="2">
   <subfield code="a">Lewis, John,</subfield>
   <subfield code="d">1920-</subfield>
   <subfield code="t">Selections.</subfield>
   <subfield code="f">1977.</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2="2">
   <subfield code="a">Jackson, Milt.</subfield>
   <subfield code="t">Martyrs.</subfield>
   <subfield code="f">1977.</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2="2">
   <subfield code="a">Jackson, Milt.</subfield>
   <subfield code="t">Legendary profile.</subfield>
   <subfield code="f">1977.</subfield>
  </datafield>
  <datafield tag="740" ind1="4" ind2=" ">
   <subfield code="a">The legendary profile.</subfield>
  </datafield>
  <datafield tag="852" ind1="0" ind2="0">
   <subfield code="b">MUSIC</subfield>
   <subfield code="c">Audio-Visual</subfield>
   <subfield code="k">folio</subfield>
   <subfield code="h">M1366</subfield>
   <subfield code="i">M62</subfield>
   <subfield code="9">1</subfield>
   <subfield code="4">Marvin Duchow Music</subfield>
   <subfield code="5"></subfield>
  </datafield>
 </record>
 <record xmlns="http://www.loc.gov/MARC21/slim">
  <leader>01293cjm  2200289 a 4500</leader>
  <controlfield tag="001">001878039</controlfield>
  <controlfield tag="005">20050110174900.0</controlfield>
  <controlfield tag="007">sd fungnn|||e|</controlfield>
  <controlfield tag="008">940202r19931981nyujzn   i              d</controlfield>
  <datafield tag="024" ind1="1" ind2=" ">
   <subfield code="a">7464573372</subfield>
  </datafield>
  <datafield tag="028" ind1="0" ind2="2">
   <subfield code="a">JK 57337</subfield>
   <subfield code="b">Red Baron</subfield>
  </datafield>
  <datafield tag="035" ind1=" " ind2=" ">
   <subfield code="a">(OCoLC)29737267</subfield>
  </datafield>
  <datafield tag="040" ind1=" " ind2=" ">
   <subfield code="a">SVP</subfield>
   <subfield code="c">SVP</subfield>
   <subfield code="d">LGG</subfield>
  </datafield>
  <datafield tag="100" ind1="1" ind2=" ">
   <subfield code="a">Desmond, Paul,</subfield>
   <subfield code="d">1924-</subfield>
  </datafield>
  <datafield tag="245" ind1="1" ind2="0">
   <subfield code="a">Paul Desmond &amp; the Modern Jazz Quartet</subfield>
   <subfield code="h">[sound recording]</subfield>
  </datafield>
  <datafield tag="260" ind1=" " ind2=" ">
   <subfield code="a">New York, N.Y. :</subfield>
   <subfield code="b">Red Baron :</subfield>
   <subfield code="b">Manufactured by Sony Music Entertainment,</subfield>
   <subfield code="c">p1993.</subfield>
  </datafield>
  <datafield tag="300" ind1=" " ind2=" ">
   <subfield code="a">1 sound disc (39 min.) :</subfield>
   <subfield code="b">digital ;</subfield>
   <subfield code="c">4 3/4 in.</subfield>
  </datafield>
  <datafield tag="511" ind1="0" ind2=" ">
   <subfield code="a">Paul Desmond, alto saxophone; Modern Jazz Quartet: John Lewis, piano; Milt Jackson, vibraphone; Percy Heath, bass; Connie Kay, drums.</subfield>
  </datafield>
  <datafield tag="500" ind1=" " ind2=" ">
   <subfield code="a">All arrangements by John Lewis.</subfield>
  </datafield>
  <datafield tag="518" ind1=" " ind2=" ">
   <subfield code="a">Recorded live on December 25, 1971 at Town Hall, NYC.</subfield>
  </datafield>
  <datafield tag="500" ind1=" " ind2=" ">
   <subfield code="a">Originally released in 1981 by Finesse as LP FW 27487.</subfield>
  </datafield>
  <datafield tag="500" ind1=" " ind2=" ">
   <subfield code="a">Program notes by Irving Townsend, June 1981, on container insert.</subfield>
  </datafield>
  <datafield tag="505" ind1="0" ind2=" ">
   <subfield code="a">Greensleeves -- You go to my head -- Blue dove -- Jesus Christ Superstar -- Here's that rainy day -- East of the sun -- Bags' new groove.</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="0">
   <subfield code="a">Jazz</subfield>
   <subfield code="y">1971-1980.</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2=" ">
   <subfield code="a">Lewis, John,</subfield>
   <subfield code="d">1920-</subfield>
  </datafield>
  <datafield tag="710" ind1="2" ind2=" ">
   <subfield code="a">Modern Jazz Quartet.</subfield>
  </datafield>
  <datafield tag="740" ind1="0" ind2=" ">
   <subfield code="a">Paul Desmond and the Modern Jazz Quartet.</subfield>
  </datafield>
 </record>
 <record xmlns="http://www.loc.gov/MARC21/slim">
  <leader>01829cjm  2200385 a 4500</leader>
  <controlfield tag="001">001964482</controlfield>
  <controlfield tag="005">20060626132700.0</controlfield>
  <controlfield tag="007">sd fzngnn|m|e|</controlfield>
  <controlfield tag="008">871211p19871957nyujzn                  d</controlfield>
  <datafield tag="024" ind1="1" ind2=" ">
   <subfield code="a">4228332902</subfield>
  </datafield>
  <datafield tag="028" ind1="0" ind2="1">
   <subfield code="a">833 290-2</subfield>
   <subfield code="b">Verve</subfield>
  </datafield>
  <datafield tag="033" ind1="0" ind2=" ">
   <subfield code="a">19571027</subfield>
   <subfield code="b">6299</subfield>
   <subfield code="c">D56</subfield>
  </datafield>
  <datafield tag="033" ind1="0" ind2=" ">
   <subfield code="a">196112--</subfield>
   <subfield code="b">3804</subfield>
   <subfield code="c">N4</subfield>
  </datafield>
  <datafield tag="033" ind1="0" ind2=" ">
   <subfield code="a">19571019</subfield>
   <subfield code="b">4104</subfield>
   <subfield code="c">C6</subfield>
  </datafield>
  <datafield tag="033" ind1="0" ind2=" ">
   <subfield code="a">197107--</subfield>
   <subfield code="b">6299</subfield>
   <subfield code="c">V7</subfield>
  </datafield>
  <datafield tag="035" ind1=" " ind2=" ">
   <subfield code="a">(OCoLC)17222092</subfield>
  </datafield>
  <datafield tag="040" ind1=" " ind2=" ">
   <subfield code="a">CPL</subfield>
   <subfield code="c">CPL</subfield>
   <subfield code="d">OCL</subfield>
   <subfield code="d">LGG</subfield>
  </datafield>
  <datafield tag="048" ind1=" " ind2=" ">
   <subfield code="a">pz01</subfield>
   <subfield code="a">ka01</subfield>
   <subfield code="a">sd01</subfield>
   <subfield code="a">pd01</subfield>
  </datafield>
  <datafield tag="110" ind1="2" ind2=" ">
   <subfield code="a">Modern Jazz Quartet.</subfield>
   <subfield code="4">prf</subfield>
  </datafield>
  <datafield tag="245" ind1="1" ind2="4">
   <subfield code="a">The Modern Jazz Quartet plus</subfield>
   <subfield code="h">[sound recording].</subfield>
  </datafield>
  <datafield tag="260" ind1=" " ind2=" ">
   <subfield code="a">[New York] :</subfield>
   <subfield code="b">Verve,</subfield>
   <subfield code="c">p1987.</subfield>
  </datafield>
  <datafield tag="300" ind1=" " ind2=" ">
   <subfield code="a">1 sound disc :</subfield>
   <subfield code="b">digital ;</subfield>
   <subfield code="c">4 3/4 in.</subfield>
  </datafield>
  <datafield tag="440" ind1=" " ind2="0">
   <subfield code="a">Compact jazz</subfield>
  </datafield>
  <datafield tag="511" ind1="0" ind2=" ">
   <subfield code="a">Modern Jazz Quartet (principally) ; Milt Jackson, vibraphone (2nd and 8th works) ; Oscar Peterson, piano (2nd and 8th works) ; Ray Brown, bass (2nd and 8th works) ; Ed Thigpen (2nd work), Louis Hayes (8th work), drums.</subfield>
  </datafield>
  <datafield tag="518" ind1=" " ind2=" ">
   <subfield code="a">Recorded live, Oct. 27, 1957, at the Donaueschingen Jazz Festival (1st, 5th, 7th, and 10th works); Dec. 1961, in New York (2nd work); live, Oct. 19, 1957, at the Opera House, Chicago (3rd, 4th, 6th, and 9th works); July 1971, in Villingen, Germany (8th work).</subfield>
  </datafield>
  <datafield tag="500" ind1=" " ind2=" ">
   <subfield code="a">Compact disc.</subfield>
  </datafield>
  <datafield tag="500" ind1=" " ind2=" ">
   <subfield code="a">Analog recording.</subfield>
  </datafield>
  <datafield tag="505" ind1="0" ind2=" ">
   <subfield code="a">The golden striker (4:08) -- On Green Dolphin Street (7:28) -- D &amp; E (4:55) -- I'll remember April (4:51) -- Cortège (7:15) -- Now's the time (4:43) -- J.B. blues (5:09) -- Reunion blues (6:35) -- 'Round midnight (3:56) -- Three windows (7:20).</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="0">
   <subfield code="a">Jazz.</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2=" ">
   <subfield code="a">Jackson, Milt.</subfield>
   <subfield code="4">prf</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2=" ">
   <subfield code="a">Peterson, Oscar,</subfield>
   <subfield code="d">1925-</subfield>
   <subfield code="4">prf</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2=" ">
   <subfield code="a">Brown, Ray,</subfield>
   <subfield code="d">1926-2002.</subfield>
   <subfield code="4">prf</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2=" ">
   <subfield code="a">Thigpen, Ed.</subfield>
   <subfield code="4">prf</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2=" ">
   <subfield code="a">Hayes, Louis,</subfield>
   <subfield code="d">1937-</subfield>
   <subfield code="4">prf</subfield>
  </datafield>
  <datafield tag="852" ind1="8" ind2="0">
   <subfield code="b">MUSIC</subfield>
   <subfield code="c">Audio-Visual</subfield>
   <subfield code="h">CD 1131</subfield>
   <subfield code="4">Marvin Duchow Music</subfield>
   <subfield code="5">Audio-Visual</subfield>
  </datafield>
 </record>
</collection>
PK��ZO~iK!K!"test/File_MARC/tests/marc_013.phptnu�[���--TEST--
marc_013: test formatField() convenience method
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';
$marc_file = new File_MARC($dir . '/' . 'music.mrc');

while ($marc_record = $marc_file->next()) {
  $fields = $marc_record->getFields();
  foreach ($fields as $field) {
    print $field;
    print "\n";
    print $field->formatField();
    print "\n";
    print $field->formatField(array('a', '2', 'c'));
    print "\n";
  }
}

?>
--EXPECT--
001     000073594
000073594
000073594
004     AAJ5802
AAJ5802
AAJ5802
005     20030415102100.0
20030415102100.0
20030415102100.0
008     801107s1977    nyujza                   
801107s1977    nyujza                   
801107s1977    nyujza                   
010    _a   77771106 
77771106

035    _a(CaOTUIC)15460184
(CaOTUIC)15460184

035 9  _aAAJ5802
AAJ5802

040    _aLC
LC

050 00 _aM1366
       _b.M62
       _dM1527.2
M1366 .M62 M1527.2
.M62 M1527.2
245 04 _aThe Modern Jazz Quartet :
       _bThe legendary profile. --
The Modern Jazz Quartet : The legendary profile. --
The legendary profile. --
260    _aNew York :
       _bM.J.Q. Music,
       _cc1977.
New York : M.J.Q. Music, c1977.
M.J.Q. Music,
300    _ascore (72 p.) ;
       _c31 cm.
score (72 p.) ; 31 cm.

500    _aFor piano, vibraphone, drums, and double bass.
For piano, vibraphone, drums, and double bass.

505 0  _aLewis, J. Django.--Lewis, J. Plastic dreams (music from the film Kemek).--Lewis, J. Dancing (music from the film Kemek).--Lewis, J. Blues in A minor.--Lewis, J. Blues in B♭.--Lewis, J. Precious joy.--Jackson, M. The martyr.--Jackson, M. The legendary profile.
Lewis, J. Django.--Lewis, J. Plastic dreams (music from the film Kemek).--Lewis, J. Dancing (music from the film Kemek).--Lewis, J. Blues in A minor.--Lewis, J. Blues in B♭.--Lewis, J. Precious joy.--Jackson, M. The martyr.--Jackson, M. The legendary profile.

650  0 _aJazz.
Jazz.

650  0 _aMotion picture music
       _vExcerpts
       _vScores.
Motion picture music -- Excerpts -- Scores.
-- Excerpts -- Scores.
700 12 _aLewis, John,
       _d1920-
       _tSelections.
       _f1977.
Lewis, John, 1920- Selections. 1977.
1920- Selections. 1977.
700 12 _aJackson, Milt.
       _tMartyrs.
       _f1977.
Jackson, Milt. Martyrs. 1977.
Martyrs. 1977.
700 12 _aJackson, Milt.
       _tLegendary profile.
       _f1977.
Jackson, Milt. Legendary profile. 1977.
Legendary profile. 1977.
740 4  _aThe legendary profile.
The legendary profile.

852 00 _bMUSIC
       _cMAIN
       _kfolio
       _hM1366
       _iM62
       _91
       _4Marvin Duchow Music
       _5
MUSIC MAIN folio M1366 M62 1 Marvin Duchow Music
MUSIC folio M1366 M62 1 Marvin Duchow Music
001     001878039
001878039
001878039
005     20050110174900.0
20050110174900.0
20050110174900.0
007     sd fungnn|||e|
sd fungnn|||e|
sd fungnn|||e|
008     940202r19931981nyujzn   i              d
940202r19931981nyujzn   i              d
940202r19931981nyujzn   i              d
024 1  _a7464573372
7464573372

028 02 _aJK 57337
       _bRed Baron
JK 57337 Red Baron
Red Baron
035    _a(OCoLC)29737267
(OCoLC)29737267

040    _aSVP
       _cSVP
       _dLGG
SVP SVP LGG
LGG
100 1  _aDesmond, Paul,
       _d1924-
Desmond, Paul, 1924-
1924-
245 10 _aPaul Desmond & the Modern Jazz Quartet
       _h[sound recording]
Paul Desmond & the Modern Jazz Quartet [sound recording]
[sound recording]
260    _aNew York, N.Y. :
       _bRed Baron :
       _bManufactured by Sony Music Entertainment,
       _cp1993.
New York, N.Y. : Red Baron : Manufactured by Sony Music Entertainment, p1993.
Red Baron : Manufactured by Sony Music Entertainment,
300    _a1 sound disc (39 min.) :
       _bdigital ;
       _c4 3/4 in.
1 sound disc (39 min.) : digital ; 4 3/4 in.
digital ;
511 0  _aPaul Desmond, alto saxophone; Modern Jazz Quartet: John Lewis, piano; Milt Jackson, vibraphone; Percy Heath, bass; Connie Kay, drums.
Paul Desmond, alto saxophone; Modern Jazz Quartet: John Lewis, piano; Milt Jackson, vibraphone; Percy Heath, bass; Connie Kay, drums.

500    _aAll arrangements by John Lewis.
All arrangements by John Lewis.

518    _aRecorded live on December 25, 1971 at Town Hall, NYC.
Recorded live on December 25, 1971 at Town Hall, NYC.

500    _aOriginally released in 1981 by Finesse as LP FW 27487.
Originally released in 1981 by Finesse as LP FW 27487.

500    _aProgram notes by Irving Townsend, June 1981, on container insert.
Program notes by Irving Townsend, June 1981, on container insert.

505 0  _aGreensleeves -- You go to my head -- Blue dove -- Jesus Christ Superstar -- Here's that rainy day -- East of the sun -- Bags' new groove.
Greensleeves -- You go to my head -- Blue dove -- Jesus Christ Superstar -- Here's that rainy day -- East of the sun -- Bags' new groove.

650  0 _aJazz
       _y1971-1980.
Jazz -- 1971-1980.
-- 1971-1980.
700 1  _aLewis, John,
       _d1920-
Lewis, John, 1920-
1920-
710 2  _aModern Jazz Quartet.
Modern Jazz Quartet.

740 0  _aPaul Desmond and the Modern Jazz Quartet.
Paul Desmond and the Modern Jazz Quartet.

001     001964482
001964482
001964482
005     20060626132700.0
20060626132700.0
20060626132700.0
007     sd fzngnn|m|e|
sd fzngnn|m|e|
sd fzngnn|m|e|
008     871211p19871957nyujzn                  d
871211p19871957nyujzn                  d
871211p19871957nyujzn                  d
024 1  _a4228332902
4228332902

028 01 _a833 290-2
       _bVerve
833 290-2 Verve
Verve
033 0  _a19571027
       _b6299
       _cD56
19571027 6299 D56
6299
033 0  _a196112--
       _b3804
       _cN4
196112-- 3804 N4
3804
033 0  _a19571019
       _b4104
       _cC6
19571019 4104 C6
4104
033 0  _a197107--
       _b6299
       _cV7
197107-- 6299 V7
6299
035    _a(OCoLC)17222092
(OCoLC)17222092

040    _aCPL
       _cCPL
       _dOCL
       _dLGG
CPL CPL OCL LGG
OCL LGG
048    _apz01
       _aka01
       _asd01
       _apd01
pz01 ka01 sd01 pd01

110 2  _aModern Jazz Quartet.
       _4prf
Modern Jazz Quartet. prf
prf
245 14 _aThe Modern Jazz Quartet plus
       _h[sound recording].
The Modern Jazz Quartet plus [sound recording].
[sound recording].
260    _a[New York] :
       _bVerve,
       _cp1987.
[New York] : Verve, p1987.
Verve,
300    _a1 sound disc :
       _bdigital ;
       _c4 3/4 in.
1 sound disc : digital ; 4 3/4 in.
digital ;
440  0 _aCompact jazz
Compact jazz

511 0  _aModern Jazz Quartet (principally) ; Milt Jackson, vibraphone (2nd and 8th works) ; Oscar Peterson, piano (2nd and 8th works) ; Ray Brown, bass (2nd and 8th works) ; Ed Thigpen (2nd work), Louis Hayes (8th work), drums.
Modern Jazz Quartet (principally) ; Milt Jackson, vibraphone (2nd and 8th works) ; Oscar Peterson, piano (2nd and 8th works) ; Ray Brown, bass (2nd and 8th works) ; Ed Thigpen (2nd work), Louis Hayes (8th work), drums.

518    _aRecorded live, Oct. 27, 1957, at the Donaueschingen Jazz Festival (1st, 5th, 7th, and 10th works); Dec. 1961, in New York (2nd work); live, Oct. 19, 1957, at the Opera House, Chicago (3rd, 4th, 6th, and 9th works); July 1971, in Villingen, Germany (8th work).
Recorded live, Oct. 27, 1957, at the Donaueschingen Jazz Festival (1st, 5th, 7th, and 10th works); Dec. 1961, in New York (2nd work); live, Oct. 19, 1957, at the Opera House, Chicago (3rd, 4th, 6th, and 9th works); July 1971, in Villingen, Germany (8th work).

500    _aCompact disc.
Compact disc.

500    _aAnalog recording.
Analog recording.

505 0  _aThe golden striker (4:08) -- On Green Dolphin Street (7:28) -- D & E (4:55) -- I'll remember April (4:51) -- Cortège (7:15) -- Now's the time (4:43) -- J.B. blues (5:09) -- Reunion blues (6:35) -- 'Round midnight (3:56) -- Three windows (7:20).
The golden striker (4:08) -- On Green Dolphin Street (7:28) -- D & E (4:55) -- I'll remember April (4:51) -- Cortège (7:15) -- Now's the time (4:43) -- J.B. blues (5:09) -- Reunion blues (6:35) -- 'Round midnight (3:56) -- Three windows (7:20).

650  0 _aJazz.
Jazz.

700 1  _aJackson, Milt.
       _4prf
Jackson, Milt. prf
prf
700 1  _aPeterson, Oscar,
       _d1925-
       _4prf
Peterson, Oscar, 1925- prf
1925- prf
700 1  _aBrown, Ray,
       _d1926-2002.
       _4prf
Brown, Ray, 1926-2002. prf
1926-2002. prf
700 1  _aThigpen, Ed.
       _4prf
Thigpen, Ed. prf
prf
700 1  _aHayes, Louis,
       _d1937-
       _4prf
Hayes, Louis, 1937- prf
1937- prf
852 80 _bMUSIC
       _cAV
       _hCD 1131
       _4Marvin Duchow Music
       _5Audio-Visual
MUSIC AV CD 1131 Marvin Duchow Music Audio-Visual
MUSIC CD 1131 Marvin Duchow Music Audio-Visual
PK��Ze����
�
"test/File_MARC/tests/marc_011.phptnu�[���--TEST--
marc_011: iterate and pretty print a MARC record (SOURCE_STRING)
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';

// Pull the MARC records into a string (as though we got it from YAZ)
$marc_string = file_get_contents($dir . '/' . 'example.mrc');

// Use the File_MARC::SOURCE_STRING flag to indicate that our source is a, uh, string
$marc_file = new File_MARC($marc_string, File_MARC::SOURCE_STRING);

while ($marc_record = $marc_file->next()) {
  print $marc_record;
  print "\n";
}
?>
--EXPECT--
LDR 01850     2200517   4500
001     0000000044
003     EMILDA
008     980120s1998    fi     j      000 0 swe
020    _a9515008808
       _cFIM 72:00
035    _99515008808
040    _aNB
042    _9NB
       _9SEE
084    _aHcd,u
       _2kssb/6
084    _5NB
       _auHc
       _2kssb
084    _5SEE
       _aHcf
       _2kssb/6
084    _5Q
       _aHcd,uf
       _2kssb/6
100 1  _aJansson, Tove,
       _d1914-2001
245 04 _aDet osynliga barnet och andra ber�ttelser /
       _cTove Jansson
250    _a7. uppl.
260    _aHelsingfors :
       _bSchildt,
       _c1998 ;
       _e(Falun :
       _fScandbook)
300    _a166, [4] s. :
       _bill. ;
       _c21 cm
440  0 _aMumin-biblioteket,
       _x99-0698931-9
500    _aOriginaluppl. 1962
599    _aLi: S
740 4  _aDet osynliga barnet
775 1  _z951-50-0385-7
       _w9515003857
       _907
841    _5Li
       _axa
       _b0201080u    0   4000uu   |000000
       _e1
841    _5SEE
       _axa
       _b0201080u    0   4000uu   |000000
       _e1
841    _5L
       _axa
       _b0201080u    0   4000uu   |000000
       _e1
841    _5NB
       _axa
       _b0201080u    0   4000uu   |000000
       _e1
841    _5Q
       _axa
       _b0201080u    0   4000uu   |000000
       _e1
841    _5S
       _axa
       _b0201080u    0   4000uu   |000000
       _e1
852    _5NB
       _bNB
       _cNB98:12
       _hplikt
       _jR, 980520
852    _5Li
       _bLi
       _cCNB
       _hh,u
852    _5SEE
       _bSEE
852    _5Q
       _bQ
       _j98947
852    _5L
       _bL
       _c0100
       _h98/
       _j3043 H
852    _5S
       _bS
       _hSv97
       _j7235
900 1s _aYanson, Tobe,
       _d1914-2001
       _uJansson, Tove,
       _d1914-2001
900 1s _aJanssonov�, Tove,
       _d1914-2001
       _uJansson, Tove,
       _d1914-2001
900 1s _aJansone, Tuve,
       _d1914-2001
       _uJansson, Tove,
       _d1914-2001
900 1s _aJanson, Tuve,
       _d1914-2001
       _uJansson, Tove,
       _d1914-2001
900 1s _aJansson, Tuve,
       _d1914-2001
       _uJansson, Tove,
       _d1914-2001
900 1s _aJanssonova, Tove,
       _d1914-2001
       _uJansson, Tove,
       _d1914-2001
976  2 _aHcd,u
       _bSk�nlitteratur
005     20050204111518.0
PK��Z�>���&test/File_MARC/tests/marc_xml_003.phptnu�[���--TEST--
marc_xml_003: Round-trip a MARCXML record to MARC21 (LOC standard)
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';
$marc_file = new File_MARCXML($dir . '/' . 'sandburg.xml');

while ($marc_record = $marc_file->next()) {
  print $marc_record->toRaw();
}
?>
--EXPECT--
01142cam  2200301 a 4500001001300000003000400013005001700017008004100034010001700075020002500092040001800117042000900135050002600144082001600170100003200186245008600218250001200304260005200316300004900368500004000417520022800457650003300685650003300718650002400751650002100775650002300796700002100819   92005291 DLC19930521155141.9920219s1993    caua   j      000 0 eng    a   92005291   a0152038655 :c$15.95  aDLCcDLCdDLC  alcac00aPS3537.A618bA88 199300a811/.522201 aSandburg, Carl,d1878-1967.10aArithmetic /cCarl Sandburg ; illustrated as an anamorphic adventure by Ted Rand.  a1st ed.  aSan Diego :bHarcourt Brace Jovanovich,cc1993.  a1 v. (unpaged) :bill. (some col.) ;c26 cm.  aOne Mylar sheet included in pocket.  aA poem about numbers and their characteristics. Features anamorphic, or distorted, drawings which can be restored to normal by viewing from a particular angle or by viewing the image's reflection in the provided Mylar cone. 0aArithmeticxJuvenile poetry. 0aChildren's poetry, American. 1aArithmeticxPoetry. 1aAmerican poetry. 1aVisual perception.1 aRand, Ted,eill.
PK��ZN���&&&test/File_MARC/tests/marc_xml_002.phptnu�[���--TEST--
marc_xml_002: iterate and pretty print a MARC record (LOC standard)
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';
$marc_file = new File_MARC($dir . '/' . 'sandburg.mrc');

while ($marc_record = $marc_file->next()) {
  print $marc_record->toXML();
  print "\n";
}
?>
--EXPECT--
<?xml version="1.0" encoding="UTF-8"?>
<collection xmlns="http://www.loc.gov/MARC21/slim">
 <record>
  <leader>01142cam  2200301 a 4500</leader>
  <controlfield tag="001">   92005291 </controlfield>
  <controlfield tag="003">DLC</controlfield>
  <controlfield tag="005">19930521155141.9</controlfield>
  <controlfield tag="008">920219s1993    caua   j      000 0 eng  </controlfield>
  <datafield tag="010" ind1=" " ind2=" ">
   <subfield code="a">   92005291 </subfield>
  </datafield>
  <datafield tag="020" ind1=" " ind2=" ">
   <subfield code="a">0152038655 :</subfield>
   <subfield code="c">$15.95</subfield>
  </datafield>
  <datafield tag="040" ind1=" " ind2=" ">
   <subfield code="a">DLC</subfield>
   <subfield code="c">DLC</subfield>
   <subfield code="d">DLC</subfield>
  </datafield>
  <datafield tag="042" ind1=" " ind2=" ">
   <subfield code="a">lcac</subfield>
  </datafield>
  <datafield tag="050" ind1="0" ind2="0">
   <subfield code="a">PS3537.A618</subfield>
   <subfield code="b">A88 1993</subfield>
  </datafield>
  <datafield tag="082" ind1="0" ind2="0">
   <subfield code="a">811/.52</subfield>
   <subfield code="2">20</subfield>
  </datafield>
  <datafield tag="100" ind1="1" ind2=" ">
   <subfield code="a">Sandburg, Carl,</subfield>
   <subfield code="d">1878-1967.</subfield>
  </datafield>
  <datafield tag="245" ind1="1" ind2="0">
   <subfield code="a">Arithmetic /</subfield>
   <subfield code="c">Carl Sandburg ; illustrated as an anamorphic adventure by Ted Rand.</subfield>
  </datafield>
  <datafield tag="250" ind1=" " ind2=" ">
   <subfield code="a">1st ed.</subfield>
  </datafield>
  <datafield tag="260" ind1=" " ind2=" ">
   <subfield code="a">San Diego :</subfield>
   <subfield code="b">Harcourt Brace Jovanovich,</subfield>
   <subfield code="c">c1993.</subfield>
  </datafield>
  <datafield tag="300" ind1=" " ind2=" ">
   <subfield code="a">1 v. (unpaged) :</subfield>
   <subfield code="b">ill. (some col.) ;</subfield>
   <subfield code="c">26 cm.</subfield>
  </datafield>
  <datafield tag="500" ind1=" " ind2=" ">
   <subfield code="a">One Mylar sheet included in pocket.</subfield>
  </datafield>
  <datafield tag="520" ind1=" " ind2=" ">
   <subfield code="a">A poem about numbers and their characteristics. Features anamorphic, or distorted, drawings which can be restored to normal by viewing from a particular angle or by viewing the image's reflection in the provided Mylar cone.</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="0">
   <subfield code="a">Arithmetic</subfield>
   <subfield code="x">Juvenile poetry.</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="0">
   <subfield code="a">Children's poetry, American.</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="1">
   <subfield code="a">Arithmetic</subfield>
   <subfield code="x">Poetry.</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="1">
   <subfield code="a">American poetry.</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="1">
   <subfield code="a">Visual perception.</subfield>
  </datafield>
  <datafield tag="700" ind1="1" ind2=" ">
   <subfield code="a">Rand, Ted,</subfield>
   <subfield code="e">ill.</subfield>
  </datafield>
 </record>
</collection>
PK��Zy���
�
'test/File_MARC/tests/marc_lint_003.phptnu�[���--TEST--
marc_lint_003: Tests for field 880 and for subfield 6
--SKIPIF--
<?php include('tests/skipif.inc'); ?>
<?php include('tests/skipif_noispn.inc'); ?>
--FILE--
<?php
$dir = dirname(__FILE__);
require __DIR__ . '/bootstrap.php';

$marc_lint = new File_MARC_Lint();

$rec = new File_MARC_Record();
$rec->setLeader("00000nam  22002538a 4500");
$rec->appendField(
    new File_MARC_Control_Field(
        '001', 'ttt07000001 '
    )
);
$rec->appendField(
    new File_MARC_Control_Field(
        '003', 'TEST '
    )
);
$rec->appendField(
    new File_MARC_Control_Field(
        '008', '070520s2007    ilu           000 0 eng d'
    )
);
$rec->appendField(
    new File_MARC_Data_Field(
        '040',
        array(
            new File_MARC_Subfield('a', 'TEST'),
            new File_MARC_Subfield('c', 'TEST')
        ),
        "", ""
    )
);
$rec->appendField(
    new File_MARC_Data_Field(
        '050',
        array(
            new File_MARC_Subfield('a', 'RZ999'),
            new File_MARC_Subfield('b', '.J66 2007')
        ),
        "", "4"
    )
);
$rec->appendField(
    new File_MARC_Data_Field(
        '082',
        array(
            new File_MARC_Subfield('a', '615.8/9'),
            new File_MARC_Subfield('2', '22')
        ),
        "0", "4"
    )
);
$rec->appendField(
    new File_MARC_Data_Field(
        '100',
        array(
            new File_MARC_Subfield('a', 'Jones, John')
        ),
        "1", ""
    )
);
$rec->appendField(
    new File_MARC_Data_Field(
        '245',
        array(
            new File_MARC_Subfield('6', '880-02'),
            new File_MARC_Subfield('a', 'Test 880.')
        ),
        "1", "0"
    )
);
$rec->appendField(
    new File_MARC_Data_Field(
        '260',
        array(
            new File_MARC_Subfield('a', 'Mount Morris, Ill. :'),
            new File_MARC_Subfield('b', "B. Baldus,"),
            new File_MARC_Subfield('c', '2007.')
        ),
        "", ""
    )
);
$rec->appendField(
    new File_MARC_Data_Field(
        '300',
        array(
            new File_MARC_Subfield('a', '1 v. ;'),
            new File_MARC_Subfield('c', '23 cm.')
        ),
        "", ""
    )
);
$rec->appendField(
    new File_MARC_Data_Field(
        '880',
        array(
            new File_MARC_Subfield('6', '245-02/$1'),
            new File_MARC_Subfield('a', '<Title in CJK script>.')
        ),
        "1", "0"
    )
);
$rec->appendField(
    new File_MARC_Data_Field(
        '880',
        array(
            new File_MARC_Subfield('6', '245-02/$1'),
            new File_MARC_Subfield('a', 'Illegal duplicate field.')
        ),
        "1", "0"
    )
);
$warnings = $marc_lint->checkRecord($rec);
foreach ($warnings as $warning) {
  print $warning . "\n";
}

?>
--EXPECT--
245: Field is not repeatable.
PK��Z]�Q�� � Rtest/ClassLoader/Symfony/Component/ClassLoader/Tests/ClassCollectionLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\ClassLoader\Tests;

use Symfony\Component\ClassLoader\ClassCollectionLoader;

require_once __DIR__.'/Fixtures/ClassesWithParents/GInterface.php';
require_once __DIR__.'/Fixtures/ClassesWithParents/CInterface.php';
require_once __DIR__.'/Fixtures/ClassesWithParents/B.php';
require_once __DIR__.'/Fixtures/ClassesWithParents/A.php';

class ClassCollectionLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testTraitDependencies()
    {
        if (version_compare(phpversion(), '5.4', '<')) {
            $this->markTestSkipped('Requires PHP > 5.4');

            return;
        }

        require_once __DIR__.'/Fixtures/deps/traits.php';

        $r = new \ReflectionClass('Symfony\Component\ClassLoader\ClassCollectionLoader');
        $m = $r->getMethod('getOrderedClasses');
        $m->setAccessible(true);

        $ordered = $m->invoke('Symfony\Component\ClassLoader\ClassCollectionLoader', array('CTFoo'));

        $this->assertEquals(
            array('TD', 'TC', 'TB', 'TA', 'TZ', 'CTFoo'),
            array_map(function ($class) { return $class->getName(); }, $ordered)
        );

        $ordered = $m->invoke('Symfony\Component\ClassLoader\ClassCollectionLoader', array('CTBar'));

        $this->assertEquals(
            array('TD', 'TZ', 'TC', 'TB', 'TA', 'CTBar'),
            array_map(function ($class) { return $class->getName(); }, $ordered)
        );
    }

    /**
     * @dataProvider getDifferentOrders
     */
    public function testClassReordering(array $classes)
    {
        $expected = array(
            'ClassesWithParents\\GInterface',
            'ClassesWithParents\\CInterface',
            'ClassesWithParents\\B',
            'ClassesWithParents\\A',
        );

        $r = new \ReflectionClass('Symfony\Component\ClassLoader\ClassCollectionLoader');
        $m = $r->getMethod('getOrderedClasses');
        $m->setAccessible(true);

        $ordered = $m->invoke('Symfony\Component\ClassLoader\ClassCollectionLoader', $classes);

        $this->assertEquals($expected, array_map(function ($class) { return $class->getName(); }, $ordered));
    }

    public function getDifferentOrders()
    {
        return array(
            array(array(
                'ClassesWithParents\\A',
                'ClassesWithParents\\CInterface',
                'ClassesWithParents\\GInterface',
                'ClassesWithParents\\B',
            )),
            array(array(
                'ClassesWithParents\\B',
                'ClassesWithParents\\A',
                'ClassesWithParents\\CInterface',
            )),
            array(array(
                'ClassesWithParents\\CInterface',
                'ClassesWithParents\\B',
                'ClassesWithParents\\A',
            )),
            array(array(
                'ClassesWithParents\\A',
            )),
        );
    }

    /**
     * @dataProvider getDifferentOrdersForTraits
     */
    public function testClassWithTraitsReordering(array $classes)
    {
        if (version_compare(phpversion(), '5.4', '<')) {
            $this->markTestSkipped('Requires PHP > 5.4');

            return;
        }

        require_once __DIR__.'/Fixtures/ClassesWithParents/ATrait.php';
        require_once __DIR__.'/Fixtures/ClassesWithParents/BTrait.php';
        require_once __DIR__.'/Fixtures/ClassesWithParents/CTrait.php';
        require_once __DIR__.'/Fixtures/ClassesWithParents/D.php';
        require_once __DIR__.'/Fixtures/ClassesWithParents/E.php';

        $expected = array(
            'ClassesWithParents\\GInterface',
            'ClassesWithParents\\CInterface',
            'ClassesWithParents\\ATrait',
            'ClassesWithParents\\BTrait',
            'ClassesWithParents\\CTrait',
            'ClassesWithParents\\B',
            'ClassesWithParents\\A',
            'ClassesWithParents\\D',
            'ClassesWithParents\\E',
        );

        $r = new \ReflectionClass('Symfony\Component\ClassLoader\ClassCollectionLoader');
        $m = $r->getMethod('getOrderedClasses');
        $m->setAccessible(true);

        $ordered = $m->invoke('Symfony\Component\ClassLoader\ClassCollectionLoader', $classes);

        $this->assertEquals($expected, array_map(function ($class) { return $class->getName(); }, $ordered));
    }

    public function getDifferentOrdersForTraits()
    {
        return array(
            array(array(
                'ClassesWithParents\\E',
                'ClassesWithParents\\ATrait',
            )),
            array(array(
                'ClassesWithParents\\E',
            )),
        );
    }

    /**
     * @dataProvider getFixNamespaceDeclarationsData
     */
    public function testFixNamespaceDeclarations($source, $expected)
    {
        $this->assertEquals('<?php '.$expected, ClassCollectionLoader::fixNamespaceDeclarations('<?php '.$source));
    }

    public function getFixNamespaceDeclarationsData()
    {
        return array(
            array("namespace;\nclass Foo {}\n", "namespace\n{\nclass Foo {}\n}"),
            array("namespace Foo;\nclass Foo {}\n", "namespace Foo\n{\nclass Foo {}\n}"),
            array("namespace   Bar ;\nclass Foo {}\n", "namespace Bar\n{\nclass Foo {}\n}"),
            array("namespace Foo\Bar;\nclass Foo {}\n", "namespace Foo\Bar\n{\nclass Foo {}\n}"),
            array("namespace Foo\Bar\Bar\n{\nclass Foo {}\n}\n", "namespace Foo\Bar\Bar\n{\nclass Foo {}\n}"),
            array("namespace\n{\nclass Foo {}\n}\n", "namespace\n{\nclass Foo {}\n}"),
        );
    }

    /**
     * @dataProvider getFixNamespaceDeclarationsDataWithoutTokenizer
     */
    public function testFixNamespaceDeclarationsWithoutTokenizer($source, $expected)
    {
        ClassCollectionLoader::enableTokenizer(false);
        $this->assertEquals('<?php '.$expected, ClassCollectionLoader::fixNamespaceDeclarations('<?php '.$source));
        ClassCollectionLoader::enableTokenizer(true);
    }

    public function getFixNamespaceDeclarationsDataWithoutTokenizer()
    {
        return array(
            array("namespace;\nclass Foo {}\n", "namespace\n{\nclass Foo {}\n}\n"),
            array("namespace Foo;\nclass Foo {}\n", "namespace Foo\n{\nclass Foo {}\n}\n"),
            array("namespace   Bar ;\nclass Foo {}\n", "namespace   Bar\n{\nclass Foo {}\n}\n"),
            array("namespace Foo\Bar;\nclass Foo {}\n", "namespace Foo\Bar\n{\nclass Foo {}\n}\n"),
            array("namespace Foo\Bar\Bar\n{\nclass Foo {}\n}\n", "namespace Foo\Bar\Bar\n{\nclass Foo {}\n}\n"),
            array("namespace\n{\nclass Foo {}\n}\n", "namespace\n{\nclass Foo {}\n}\n"),
        );
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testUnableToLoadClassException()
    {
        if (is_file($file = sys_get_temp_dir().'/foo.php')) {
            unlink($file);
        }

        ClassCollectionLoader::load(array('SomeNotExistingClass'), sys_get_temp_dir(), 'foo', false);
    }

    public function testCommentStripping()
    {
        if (is_file($file = sys_get_temp_dir().'/bar.php')) {
            unlink($file);
        }
        spl_autoload_register($r = function ($class) {
            if (0 === strpos($class, 'Namespaced') || 0 === strpos($class, 'Pearlike_')) {
                require_once __DIR__.'/Fixtures/'.str_replace(array('\\', '_'), '/', $class).'.php';
            }
        });

        ClassCollectionLoader::load(
            array('Namespaced\\WithComments', 'Pearlike_WithComments'),
            sys_get_temp_dir(),
            'bar',
            false
        );

        spl_autoload_unregister($r);

        $this->assertEquals(<<<EOF
namespace Namespaced
{
class WithComments
{
public static \$loaded = true;
}
\$string ='string shoult not be   modified {\$string}';
\$heredoc = (<<<HD


Heredoc should not be   modified {\$string}


HD
);
\$nowdoc =<<<'ND'


Nowdoc should not be   modified {\$string}


ND
;
}
namespace
{
class Pearlike_WithComments
{
public static \$loaded = true;
}
}
EOF
        , str_replace("<?php \n", '', file_get_contents($file)));

        unlink($file);
    }
}
PK��Zh4A!AAOtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike2/Bar.phpnu�[���<?php

class Pearlike2_Bar
{
    public static $loaded = true;
}
PK��Z��2[AAOtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike2/Baz.phpnu�[���<?php

class Pearlike2_Baz
{
    public static $loaded = true;
}
PK��Z���	AAOtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike2/Foo.phpnu�[���<?php

class Pearlike2_Foo
{
    public static $loaded = true;
}
PK��Z�Cq�""Utest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeParent.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace ClassMap;

abstract class SomeParent
{

}
PK��Z�֡Z  Xtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeInterface.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace ClassMap;

interface SomeInterface
{

}
PK��ZKG9Ո�Utest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/multipleNs.phpnu�[���<?php
namespace {
    class A {}
}

namespace Alpha {
    class A {}
    class B {}
}

namespace Beta {
    class A {}
    class B {}
}
PK��Z�Қ`test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/sameNsMultipleClasses.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Foo\Bar;

class A {}
class B {}
PK��Z.~�oDDTtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeClass.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace ClassMap;

class SomeClass extends SomeParent implements SomeInterface
{

}
PK��Z�R��Ttest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/notPhpFile.mdnu�[���This file should be skipped.
PK��Z��iTtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/notAClass.phpnu�[���<?php

$a = new stdClass();
PK��Z�{�tKK^test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/C/B/Bar.phpnu�[���<?php

class PrefixCollision_C_B_Bar
{
    public static $loaded = true;
}
PK��ZP�F\KK^test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/C/B/Foo.phpnu�[���<?php

class PrefixCollision_C_B_Foo
{
    public static $loaded = true;
}
PK��Z�Lk�KK^test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/A/B/Bar.phpnu�[���<?php

class PrefixCollision_A_B_Bar
{
    public static $loaded = true;
}
PK��Zv�գKK^test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/A/B/Foo.phpnu�[���<?php

class PrefixCollision_A_B_Foo
{
    public static $loaded = true;
}
PK��Z��cZZatest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/C/B/Bar.phpnu�[���<?php

namespace NamespaceCollision\C\B;

class Bar
{
    public static $loaded = true;
}
PK��ZLVAKZZatest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/C/B/Foo.phpnu�[���<?php

namespace NamespaceCollision\C\B;

class Foo
{
    public static $loaded = true;
}
PK��ZKa�AAatest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/A/B/Bar.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace NamespaceCollision\A\B;

class Bar
{
    public static $loaded = true;
}
PK��Z����AAatest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/A/B/Foo.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace NamespaceCollision\A\B;

class Foo
{
    public static $loaded = true;
}
PK��Z��@OOQtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced2/Bar.phpnu�[���<?php

namespace Namespaced2;

class Bar
{
    public static $loaded = true;
}
PK��Z
Z3bOOQtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced2/Baz.phpnu�[���<?php

namespace Namespaced2;

class Baz
{
    public static $loaded = true;
}
PK��Zd�0OOQtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced2/Foo.phpnu�[���<?php

namespace Namespaced2;

class Foo
{
    public static $loaded = true;
}
PK��Z��55Ptest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Bar.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Namespaced;

class Bar
{
    public static $loaded = true;
}
PK��Zᒟ�55Ptest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Baz.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Namespaced;

class Baz
{
    public static $loaded = true;
}
PK��Z��R�55Ptest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Foo.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Namespaced;

class Foo
{
    public static $loaded = true;
}
PK��Z�UX�Ytest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/WithComments.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Namespaced;

class WithComments
{
    /** @Boolean */
    public static $loaded = true;
}

$string = 'string shoult not be   modified {$string}';

$heredoc = (<<<HD


Heredoc should not be   modified {$string}


HD
);

$nowdoc = <<<'ND'


Nowdoc should not be   modified {$string}


ND;
PK��Z�d�Qtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/includepath/Foo.phpnu�[���<?php

class Foo
{
}
PK��Zl�@@Ntest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/Bar.phpnu�[���<?php

class Pearlike_Bar
{
    public static $loaded = true;
}
PK��Z��q�@@Ntest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/Baz.phpnu�[���<?php

class Pearlike_Baz
{
    public static $loaded = true;
}
PK��Z�Ӽ�@@Ntest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/Foo.phpnu�[���<?php

class Pearlike_Foo
{
    public static $loaded = true;
}
PK��Z5J�DDWtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/WithComments.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

class Pearlike_WithComments
{
    /** @Boolean */
    public static $loaded = true;
}
PK��Z�>�X��Mtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/deps/traits.phpnu�[���<?php

trait TD
{}

trait TZ
{
    use TD;
}

trait TC
{
    use TD;
}

trait TB
{
    use TC;
}

trait TA
{
    use TB;
}

class CTFoo
{
    use TA;
    use TZ;
}

class CTBar
{
    use TZ;
    use TA;
}
PK��Z:5T+Otest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/php5.4/traits.phpnu�[���<?php
namespace {
    trait TFoo
    {
    }

    class CFoo
    {
        use TFoo;
    }
}

namespace Foo {
    trait TBar
    {
    }

    interface IBar
    {
    }

    trait TFooBar
    {
    }

    class CBar implements IBar
    {
        use TBar, TFooBar;
    }
}
PK��Z�
N�77[test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/ATrait.phpnu�[���<?php

namespace ClassesWithParents;

trait ATrait
{
}
PK��Z��`�RR_test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/CInterface.phpnu�[���<?php

namespace ClassesWithParents;

interface CInterface extends GInterface
{
}
PK��Z��;;Vtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/A.phpnu�[���<?php

namespace ClassesWithParents;

class A extends B {}
PK��Z ��LLVtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/D.phpnu�[���<?php

namespace ClassesWithParents;

class D extends A
{
    use BTrait;
}
PK��Zt��LLVtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/E.phpnu�[���<?php

namespace ClassesWithParents;

class E extends D
{
    use CTrait;
}
PK��Z��HGG[test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/BTrait.phpnu�[���<?php

namespace ClassesWithParents;

trait BTrait
{
    use ATrait;
}
PK��Z��LqGGVtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/B.phpnu�[���<?php

namespace ClassesWithParents;

class B implements CInterface {}
PK��Z[�"�77[test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/CTrait.phpnu�[���<?php

namespace ClassesWithParents;

trait CTrait
{
}
PK��Z���Z??_test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/GInterface.phpnu�[���<?php

namespace ClassesWithParents;

interface GInterface
{
}
PK��Z�6S�II]test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/C/Bar.phpnu�[���<?php

class PrefixCollision_C_Bar
{
    public static $loaded = true;
}
PK��Z	���II]test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/C/Foo.phpnu�[���<?php

class PrefixCollision_C_Foo
{
    public static $loaded = true;
}
PK��Z&F�II]test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/A/Bar.phpnu�[���<?php

class PrefixCollision_A_Bar
{
    public static $loaded = true;
}
PK��Z���II]test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/A/Foo.phpnu�[���<?php

class PrefixCollision_A_Foo
{
    public static $loaded = true;
}
PK��Z�]�>XX`test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/C/Bar.phpnu�[���<?php

namespace NamespaceCollision\C;

class Bar
{
    public static $loaded = true;
}
PK��Z~�(XX`test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/C/Foo.phpnu�[���<?php

namespace NamespaceCollision\C;

class Foo
{
    public static $loaded = true;
}
PK��Z99A??`test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/A/Bar.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace NamespaceCollision\A;

class Bar
{
    public static $loaded = true;
}
PK��Z���i??`test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/A/Foo.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace NamespaceCollision\A;

class Foo
{
    public static $loaded = true;
}
PK��Zn��DD[test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Pearlike2/FooBar.phpnu�[���<?php

class Pearlike2_FooBar
{
    public static $loaded = true;
}
PK��Z�gy�RR]test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Namespaced2/FooBar.phpnu�[���<?php

namespace Namespaced2;

class FooBar
{
    public static $loaded = true;
}
PK��Z[�“88\test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Namespaced/FooBar.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Namespaced;

class FooBar
{
    public static $loaded = true;
}
PK��Zx�wCCZtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Pearlike/FooBar.phpnu�[���<?php

class Pearlike_FooBar
{
    public static $loaded = true;
}
PK��Z>\oNNitest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/ApcPrefixCollision/A/B/Bar.phpnu�[���<?php

class ApcPrefixCollision_A_B_Bar
{
    public static $loaded = true;
}
PK��Z���GNNitest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/ApcPrefixCollision/A/B/Foo.phpnu�[���<?php

class ApcPrefixCollision_A_B_Foo
{
    public static $loaded = true;
}
PK��Z�F�EEitest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/NamespaceCollision/A/B/Bar.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Apc\NamespaceCollision\A\B;

class Bar
{
    public static $loaded = true;
}
PK��Z]�[�EEitest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/NamespaceCollision/A/B/Foo.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Apc\NamespaceCollision\A\B;

class Foo
{
    public static $loaded = true;
}
PK��Z/5�<<Wtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/FooBar.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Apc\Namespaced;

class FooBar
{
    public static $loaded = true;
}
PK��Zے�99Ttest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Bar.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Apc\Namespaced;

class Bar
{
    public static $loaded = true;
}
PK��Z$�y99Ttest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Baz.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Apc\Namespaced;

class Baz
{
    public static $loaded = true;
}
PK��Z0- +99Ttest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Foo.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Apc\Namespaced;

class Foo
{
    public static $loaded = true;
}
PK��ZyQUmDDRtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike/Bar.phpnu�[���<?php

class Apc_Pearlike_Bar
{
    public static $loaded = true;
}
PK��Z��&DDRtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike/Baz.phpnu�[���<?php

class Apc_Pearlike_Baz
{
    public static $loaded = true;
}
PK��Z���EDDRtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike/Foo.phpnu�[���<?php

class Apc_Pearlike_Foo
{
    public static $loaded = true;
}
PK��Z�7LLhtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/ApcPrefixCollision/A/Bar.phpnu�[���<?php

class ApcPrefixCollision_A_Bar
{
    public static $loaded = true;
}
PK��Z.��&LLhtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/ApcPrefixCollision/A/Foo.phpnu�[���<?php

class ApcPrefixCollision_A_Foo
{
    public static $loaded = true;
}
PK��Z4���CChtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/NamespaceCollision/A/Bar.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Apc\NamespaceCollision\A;

class Bar
{
    public static $loaded = true;
}
PK��Z�qo�CChtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/NamespaceCollision/A/Foo.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Apc\NamespaceCollision\A;

class Foo
{
    public static $loaded = true;
}
PK��Z/5�<<`test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/fallback/Namespaced/FooBar.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Apc\Namespaced;

class FooBar
{
    public static $loaded = true;
}
PK��Z���GGbtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/fallback/Apc/Pearlike/FooBar.phpnu�[���<?php

class Apc_Pearlike_FooBar
{
    public static $loaded = true;
}
PK��Z�M��� � Htest/ClassLoader/Symfony/Component/ClassLoader/Tests/ClassLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\ClassLoader\Tests;

use Symfony\Component\ClassLoader\ClassLoader;

class ClassLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testGetPrefixes()
    {
        $loader = new ClassLoader();
        $loader->addPrefix('Foo', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
        $loader->addPrefix('Bar', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
        $loader->addPrefix('Bas', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
        $prefixes = $loader->getPrefixes();
        $this->assertArrayHasKey('Foo', $prefixes);
        $this->assertArrayNotHasKey('Foo1', $prefixes);
        $this->assertArrayHasKey('Bar', $prefixes);
        $this->assertArrayHasKey('Bas', $prefixes);
    }

    public function testGetFallbackDirs()
    {
        $loader = new ClassLoader();
        $loader->addPrefix(null, __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
        $loader->addPrefix(null, __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
        $fallback_dirs = $loader->getFallbackDirs();
        $this->assertCount(2, $fallback_dirs);
    }

    /**
     * @dataProvider getLoadClassTests
     */
    public function testLoadClass($className, $testClassName, $message)
    {
        $loader = new ClassLoader();
        $loader->addPrefix('Namespaced2\\', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
        $loader->addPrefix('Pearlike2_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
        $loader->loadClass($testClassName);
        $this->assertTrue(class_exists($className), $message);
    }

    public function getLoadClassTests()
    {
        return array(
            array('\\Namespaced2\\Foo', 'Namespaced2\\Foo',   '->loadClass() loads Namespaced2\Foo class'),
            array('\\Pearlike2_Foo',    'Pearlike2_Foo',      '->loadClass() loads Pearlike2_Foo class'),
        );
    }

    /**
     * @dataProvider getLoadNonexistentClassTests
     */
    public function testLoadNonexistentClass($className, $testClassName, $message)
    {
        $loader = new ClassLoader();
        $loader->addPrefix('Namespaced2\\', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
        $loader->addPrefix('Pearlike2_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
        $loader->loadClass($testClassName);
        $this->assertFalse(class_exists($className), $message);
    }

    public function getLoadNonexistentClassTests()
    {
        return array(
            array('\\Pearlike3_Bar', '\\Pearlike3_Bar', '->loadClass() loads non existing Pearlike3_Bar class with a leading slash'),
        );
    }

    public function testAddPrefix()
    {
        $loader = new ClassLoader();
        $loader->addPrefix('Foo', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
        $loader->addPrefix('Foo', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
        $prefixes = $loader->getPrefixes();
        $this->assertArrayHasKey('Foo', $prefixes);
        $this->assertCount(2, $prefixes['Foo']);
    }

    public function testUseIncludePath()
    {
        $loader = new ClassLoader();
        $this->assertFalse($loader->getUseIncludePath());

        $this->assertNull($loader->findFile('Foo'));

        $includePath = get_include_path();

        $loader->setUseIncludePath(true);
        $this->assertTrue($loader->getUseIncludePath());

        set_include_path(__DIR__.'/Fixtures/includepath'.PATH_SEPARATOR.$includePath);

        $this->assertEquals(__DIR__.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR.'includepath'.DIRECTORY_SEPARATOR.'Foo.php', $loader->findFile('Foo'));

        set_include_path($includePath);
    }

    /**
     * @dataProvider getLoadClassFromFallbackTests
     */
    public function testLoadClassFromFallback($className, $testClassName, $message)
    {
        $loader = new ClassLoader();
        $loader->addPrefix('Namespaced2\\', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
        $loader->addPrefix('Pearlike2_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
        $loader->addPrefix('', array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/fallback'));
        $loader->loadClass($testClassName);
        $this->assertTrue(class_exists($className), $message);
    }

    public function getLoadClassFromFallbackTests()
    {
        return array(
            array('\\Namespaced2\\Baz',    'Namespaced2\\Baz',    '->loadClass() loads Namespaced2\Baz class'),
            array('\\Pearlike2_Baz',       'Pearlike2_Baz',       '->loadClass() loads Pearlike2_Baz class'),
            array('\\Namespaced2\\FooBar', 'Namespaced2\\FooBar', '->loadClass() loads Namespaced2\Baz class from fallback dir'),
            array('\\Pearlike2_FooBar',    'Pearlike2_FooBar',    '->loadClass() loads Pearlike2_Baz class from fallback dir'),
        );
    }

    /**
     * @dataProvider getLoadClassNamespaceCollisionTests
     */
    public function testLoadClassNamespaceCollision($namespaces, $className, $message)
    {
        $loader = new ClassLoader();
        $loader->addPrefixes($namespaces);

        $loader->loadClass($className);
        $this->assertTrue(class_exists($className), $message);
    }

    public function getLoadClassNamespaceCollisionTests()
    {
        return array(
            array(
                array(
                    'NamespaceCollision\\C' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha',
                    'NamespaceCollision\\C\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta',
                ),
                'NamespaceCollision\C\Foo',
                '->loadClass() loads NamespaceCollision\C\Foo from alpha.',
            ),
            array(
                array(
                    'NamespaceCollision\\C\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta',
                    'NamespaceCollision\\C' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha',
                ),
                'NamespaceCollision\C\Bar',
                '->loadClass() loads NamespaceCollision\C\Bar from alpha.',
            ),
            array(
                array(
                    'NamespaceCollision\\C' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha',
                    'NamespaceCollision\\C\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta',
                ),
                'NamespaceCollision\C\B\Foo',
                '->loadClass() loads NamespaceCollision\C\B\Foo from beta.',
            ),
            array(
                array(
                    'NamespaceCollision\\C\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta',
                    'NamespaceCollision\\C' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha',
                ),
                'NamespaceCollision\C\B\Bar',
                '->loadClass() loads NamespaceCollision\C\B\Bar from beta.',
            ),
            array(
                array(
                    'PrefixCollision_C_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha',
                    'PrefixCollision_C_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta',
                ),
                'PrefixCollision_C_Foo',
                '->loadClass() loads PrefixCollision_C_Foo from alpha.',
            ),
            array(
                array(
                    'PrefixCollision_C_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta',
                    'PrefixCollision_C_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha',
                ),
                'PrefixCollision_C_Bar',
                '->loadClass() loads PrefixCollision_C_Bar from alpha.',
            ),
            array(
                array(
                    'PrefixCollision_C_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha',
                    'PrefixCollision_C_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta',
                ),
                'PrefixCollision_C_B_Foo',
                '->loadClass() loads PrefixCollision_C_B_Foo from beta.',
            ),
            array(
                array(
                    'PrefixCollision_C_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta',
                    'PrefixCollision_C_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha',
                ),
                'PrefixCollision_C_B_Bar',
                '->loadClass() loads PrefixCollision_C_B_Bar from beta.',
            ),
        );
    }
}
PK��Ze:{a��Ttest/ClassLoader/Symfony/Component/ClassLoader/Tests/ApcUniversalClassLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\ClassLoader\Tests;

use Symfony\Component\ClassLoader\ApcUniversalClassLoader;

class ApcUniversalClassLoaderTest extends \PHPUnit_Framework_TestCase
{
    protected function setUp()
    {
        if (!extension_loaded('apc')) {
            $this->markTestSkipped('The apc extension is not available.');
        }

        if (!(ini_get('apc.enabled') && ini_get('apc.enable_cli'))) {
            $this->markTestSkipped('The apc extension is available, but not enabled.');
        } else {
            apc_clear_cache('user');
        }
    }

    protected function tearDown()
    {
        if (ini_get('apc.enabled') && ini_get('apc.enable_cli')) {
            apc_clear_cache('user');
        }
    }

    public function testConstructor()
    {
        $loader = new ApcUniversalClassLoader('test.prefix.');
        $loader->registerNamespace('Apc\Namespaced', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');

        $this->assertEquals($loader->findFile('\Apc\Namespaced\FooBar'), apc_fetch('test.prefix.\Apc\Namespaced\FooBar'), '__construct() takes a prefix as its first argument');
    }

   /**
    * @dataProvider getLoadClassTests
    */
   public function testLoadClass($className, $testClassName, $message)
   {
       $loader = new ApcUniversalClassLoader('test.prefix.');
       $loader->registerNamespace('Apc\Namespaced', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
       $loader->registerPrefix('Apc_Pearlike_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
       $loader->loadClass($testClassName);
       $this->assertTrue(class_exists($className), $message);
   }

   public function getLoadClassTests()
   {
       return array(
           array('\\Apc\\Namespaced\\Foo', '\\Apc\\Namespaced\\Foo',   '->loadClass() loads Apc\Namespaced\Foo class'),
           array('Apc_Pearlike_Foo',    'Apc_Pearlike_Foo',      '->loadClass() loads Apc_Pearlike_Foo class'),
           array('\\Apc\\Namespaced\\Bar', '\\Apc\\Namespaced\\Bar', '->loadClass() loads Apc\Namespaced\Bar class with a leading slash'),
           array('Apc_Pearlike_Bar',    '\\Apc_Pearlike_Bar',    '->loadClass() loads Apc_Pearlike_Bar class with a leading slash'),
       );
   }

   /**
    * @dataProvider getLoadClassFromFallbackTests
    */
   public function testLoadClassFromFallback($className, $testClassName, $message)
   {
       $loader = new ApcUniversalClassLoader('test.prefix.fallback');
       $loader->registerNamespace('Apc\Namespaced', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
       $loader->registerPrefix('Apc_Pearlike_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
       $loader->registerNamespaceFallbacks(array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/fallback'));
       $loader->registerPrefixFallbacks(array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/fallback'));
       $loader->loadClass($testClassName);
       $this->assertTrue(class_exists($className), $message);
   }

   public function getLoadClassFromFallbackTests()
   {
       return array(
           array('\\Apc\\Namespaced\\Baz',    '\\Apc\\Namespaced\\Baz',    '->loadClass() loads Apc\Namespaced\Baz class'),
           array('Apc_Pearlike_Baz',       'Apc_Pearlike_Baz',       '->loadClass() loads Apc_Pearlike_Baz class'),
           array('\\Apc\\Namespaced\\FooBar', '\\Apc\\Namespaced\\FooBar', '->loadClass() loads Apc\Namespaced\Baz class from fallback dir'),
           array('Apc_Pearlike_FooBar',    'Apc_Pearlike_FooBar',    '->loadClass() loads Apc_Pearlike_Baz class from fallback dir'),
       );
   }

   /**
    * @dataProvider getLoadClassNamespaceCollisionTests
    */
   public function testLoadClassNamespaceCollision($namespaces, $className, $message)
   {
       $loader = new ApcUniversalClassLoader('test.prefix.collision.');
       $loader->registerNamespaces($namespaces);

       $loader->loadClass($className);

       $this->assertTrue(class_exists($className), $message);
   }

   public function getLoadClassNamespaceCollisionTests()
   {
       return array(
           array(
               array(
                   'Apc\\NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha',
                   'Apc\\NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta',
               ),
               '\Apc\NamespaceCollision\A\Foo',
               '->loadClass() loads NamespaceCollision\A\Foo from alpha.',
           ),
           array(
               array(
                   'Apc\\NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta',
                   'Apc\\NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha',
               ),
               '\Apc\NamespaceCollision\A\Bar',
               '->loadClass() loads NamespaceCollision\A\Bar from alpha.',
           ),
           array(
               array(
                   'Apc\\NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha',
                   'Apc\\NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta',
               ),
               '\Apc\NamespaceCollision\A\B\Foo',
               '->loadClass() loads NamespaceCollision\A\B\Foo from beta.',
           ),
           array(
               array(
                   'Apc\\NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta',
                   'Apc\\NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha',
               ),
               '\Apc\NamespaceCollision\A\B\Bar',
               '->loadClass() loads NamespaceCollision\A\B\Bar from beta.',
           ),
       );
   }

   /**
    * @dataProvider getLoadClassPrefixCollisionTests
    */
   public function testLoadClassPrefixCollision($prefixes, $className, $message)
   {
       $loader = new ApcUniversalClassLoader('test.prefix.collision.');
       $loader->registerPrefixes($prefixes);

       $loader->loadClass($className);
       $this->assertTrue(class_exists($className), $message);
   }

   public function getLoadClassPrefixCollisionTests()
   {
       return array(
           array(
               array(
                   'ApcPrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha/Apc',
                   'ApcPrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta/Apc',
               ),
               'ApcPrefixCollision_A_Foo',
               '->loadClass() loads ApcPrefixCollision_A_Foo from alpha.',
           ),
           array(
               array(
                   'ApcPrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta/Apc',
                   'ApcPrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha/Apc',
               ),
               'ApcPrefixCollision_A_Bar',
               '->loadClass() loads ApcPrefixCollision_A_Bar from alpha.',
           ),
           array(
               array(
                   'ApcPrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha/Apc',
                   'ApcPrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta/Apc',
               ),
               'ApcPrefixCollision_A_B_Foo',
               '->loadClass() loads ApcPrefixCollision_A_B_Foo from beta.',
           ),
           array(
               array(
                   'ApcPrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta/Apc',
                   'ApcPrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha/Apc',
               ),
               'ApcPrefixCollision_A_B_Bar',
               '->loadClass() loads ApcPrefixCollision_A_B_Bar from beta.',
           ),
       );
   }
}
PK��Z8`�##Qtest/ClassLoader/Symfony/Component/ClassLoader/Tests/UniversalClassLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\ClassLoader\Tests;

use Symfony\Component\ClassLoader\UniversalClassLoader;

class UniversalClassLoaderTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getLoadClassTests
     */
    public function testLoadClass($className, $testClassName, $message)
    {
        $loader = new UniversalClassLoader();
        $loader->registerNamespace('Namespaced', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
        $loader->registerPrefix('Pearlike_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
        $this->assertTrue($loader->loadClass($testClassName));
        $this->assertTrue(class_exists($className), $message);
    }

    public function getLoadClassTests()
    {
        return array(
            array('\\Namespaced\\Foo', 'Namespaced\\Foo',   '->loadClass() loads Namespaced\Foo class'),
            array('\\Pearlike_Foo',    'Pearlike_Foo',      '->loadClass() loads Pearlike_Foo class'),
        );
    }

    public function testUseIncludePath()
    {
        $loader = new UniversalClassLoader();
        $this->assertFalse($loader->getUseIncludePath());

        $this->assertNull($loader->findFile('Foo'));

        $includePath = get_include_path();

        $loader->useIncludePath(true);
        $this->assertTrue($loader->getUseIncludePath());

        set_include_path(__DIR__.'/Fixtures/includepath'.PATH_SEPARATOR.$includePath);

        $this->assertEquals(__DIR__.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR.'includepath'.DIRECTORY_SEPARATOR.'Foo.php', $loader->findFile('Foo'));

        set_include_path($includePath);
    }

    public function testGetNamespaces()
    {
        $loader = new UniversalClassLoader();
        $loader->registerNamespace('Foo', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
        $loader->registerNamespace('Bar', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
        $loader->registerNamespace('Bas', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
        $namespaces = $loader->getNamespaces();
        $this->assertArrayHasKey('Foo', $namespaces);
        $this->assertArrayNotHasKey('Foo1', $namespaces);
        $this->assertArrayHasKey('Bar', $namespaces);
        $this->assertArrayHasKey('Bas', $namespaces);
    }

    public function testGetPrefixes()
    {
        $loader = new UniversalClassLoader();
        $loader->registerPrefix('Foo', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
        $loader->registerPrefix('Bar', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
        $loader->registerPrefix('Bas', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
        $prefixes = $loader->getPrefixes();
        $this->assertArrayHasKey('Foo', $prefixes);
        $this->assertArrayNotHasKey('Foo1', $prefixes);
        $this->assertArrayHasKey('Bar', $prefixes);
        $this->assertArrayHasKey('Bas', $prefixes);
    }

    /**
     * @dataProvider getLoadClassFromFallbackTests
     */
    public function testLoadClassFromFallback($className, $testClassName, $message)
    {
        $loader = new UniversalClassLoader();
        $loader->registerNamespace('Namespaced', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
        $loader->registerPrefix('Pearlike_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
        $loader->registerNamespaceFallbacks(array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/fallback'));
        $loader->registerPrefixFallbacks(array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/fallback'));
        $this->assertTrue($loader->loadClass($testClassName));
        $this->assertTrue(class_exists($className), $message);
    }

    public function getLoadClassFromFallbackTests()
    {
        return array(
            array('\\Namespaced\\Baz',    'Namespaced\\Baz',    '->loadClass() loads Namespaced\Baz class'),
            array('\\Pearlike_Baz',       'Pearlike_Baz',       '->loadClass() loads Pearlike_Baz class'),
            array('\\Namespaced\\FooBar', 'Namespaced\\FooBar', '->loadClass() loads Namespaced\Baz class from fallback dir'),
            array('\\Pearlike_FooBar',    'Pearlike_FooBar',    '->loadClass() loads Pearlike_Baz class from fallback dir'),
        );
    }

    public function testRegisterPrefixFallback()
    {
        $loader = new UniversalClassLoader();
        $loader->registerPrefixFallback(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/fallback');
        $this->assertEquals(array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/fallback'), $loader->getPrefixFallbacks());
    }

    public function testRegisterNamespaceFallback()
    {
        $loader = new UniversalClassLoader();
        $loader->registerNamespaceFallback(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/Namespaced/fallback');
        $this->assertEquals(array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/Namespaced/fallback'), $loader->getNamespaceFallbacks());
    }

    /**
     * @dataProvider getLoadClassNamespaceCollisionTests
     */
    public function testLoadClassNamespaceCollision($namespaces, $className, $message)
    {
        $loader = new UniversalClassLoader();
        $loader->registerNamespaces($namespaces);

        $this->assertTrue($loader->loadClass($className));
        $this->assertTrue(class_exists($className), $message);
    }

    public function getLoadClassNamespaceCollisionTests()
    {
        return array(
            array(
                array(
                    'NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha',
                    'NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta',
                ),
                'NamespaceCollision\A\Foo',
                '->loadClass() loads NamespaceCollision\A\Foo from alpha.',
            ),
            array(
                array(
                    'NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta',
                    'NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha',
                ),
                'NamespaceCollision\A\Bar',
                '->loadClass() loads NamespaceCollision\A\Bar from alpha.',
            ),
            array(
                array(
                    'NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha',
                    'NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta',
                ),
                'NamespaceCollision\A\B\Foo',
                '->loadClass() loads NamespaceCollision\A\B\Foo from beta.',
            ),
            array(
                array(
                    'NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta',
                    'NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha',
                ),
                'NamespaceCollision\A\B\Bar',
                '->loadClass() loads NamespaceCollision\A\B\Bar from beta.',
            ),
        );
    }

    /**
     * @dataProvider getLoadClassPrefixCollisionTests
     */
    public function testLoadClassPrefixCollision($prefixes, $className, $message)
    {
        $loader = new UniversalClassLoader();
        $loader->registerPrefixes($prefixes);

        $this->assertTrue($loader->loadClass($className));
        $this->assertTrue(class_exists($className), $message);
    }

    public function getLoadClassPrefixCollisionTests()
    {
        return array(
            array(
                array(
                    'PrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha',
                    'PrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta',
                ),
                'PrefixCollision_A_Foo',
                '->loadClass() loads PrefixCollision_A_Foo from alpha.',
            ),
            array(
                array(
                    'PrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta',
                    'PrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha',
                ),
                'PrefixCollision_A_Bar',
                '->loadClass() loads PrefixCollision_A_Bar from alpha.',
            ),
            array(
                array(
                    'PrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha',
                    'PrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta',
                ),
                'PrefixCollision_A_B_Foo',
                '->loadClass() loads PrefixCollision_A_B_Foo from beta.',
            ),
            array(
                array(
                    'PrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta',
                    'PrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha',
                ),
                'PrefixCollision_A_B_Bar',
                '->loadClass() loads PrefixCollision_A_B_Bar from beta.',
            ),
        );
    }
}
PK��Z\|����Ntest/ClassLoader/Symfony/Component/ClassLoader/Tests/ClassMapGeneratorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\ClassLoader\Tests;

use Symfony\Component\ClassLoader\ClassMapGenerator;

class ClassMapGeneratorTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var string $workspace
     */
    private $workspace = null;

    public function prepare_workspace()
    {
        $this->workspace = rtrim(sys_get_temp_dir(), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.time().rand(0, 1000);
        mkdir($this->workspace, 0777, true);
        $this->workspace = realpath($this->workspace);
    }

    /**
     * @param string $file
     */
    private function clean($file)
    {
        if (is_dir($file) && !is_link($file)) {
            $dir = new \FilesystemIterator($file);
            foreach ($dir as $childFile) {
                $this->clean($childFile);
            }

            rmdir($file);
        } else {
            unlink($file);
        }
    }

    /**
     * @dataProvider getTestCreateMapTests
     */
    public function testDump($directory, $expected)
    {
        $this->prepare_workspace();

        $file = $this->workspace.'/file';

        $generator = new ClassMapGenerator();
        $generator->dump($directory, $file);
        $this->assertFileExists($file);

        $this->clean($this->workspace);
    }

    /**
     * @dataProvider getTestCreateMapTests
     */
    public function testCreateMap($directory, $expected)
    {
        $this->assertEqualsNormalized($expected, ClassMapGenerator::createMap($directory));
    }

    public function getTestCreateMapTests()
    {
        $data = array(
            array(__DIR__.'/Fixtures/Namespaced', array(
                'Namespaced\\Bar'          => realpath(__DIR__).'/Fixtures/Namespaced/Bar.php',
                'Namespaced\\Foo'          => realpath(__DIR__).'/Fixtures/Namespaced/Foo.php',
                'Namespaced\\Baz'          => realpath(__DIR__).'/Fixtures/Namespaced/Baz.php',
                'Namespaced\\WithComments' => realpath(__DIR__).'/Fixtures/Namespaced/WithComments.php',
                )
            ),
            array(__DIR__.'/Fixtures/beta/NamespaceCollision', array(
                'NamespaceCollision\\A\\B\\Bar' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/A/B/Bar.php',
                'NamespaceCollision\\A\\B\\Foo' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/A/B/Foo.php',
                'NamespaceCollision\\C\\B\\Bar' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/C/B/Bar.php',
                'NamespaceCollision\\C\\B\\Foo' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/C/B/Foo.php',
            )),
            array(__DIR__.'/Fixtures/Pearlike', array(
                'Pearlike_Foo'          => realpath(__DIR__).'/Fixtures/Pearlike/Foo.php',
                'Pearlike_Bar'          => realpath(__DIR__).'/Fixtures/Pearlike/Bar.php',
                'Pearlike_Baz'          => realpath(__DIR__).'/Fixtures/Pearlike/Baz.php',
                'Pearlike_WithComments' => realpath(__DIR__).'/Fixtures/Pearlike/WithComments.php',
            )),
            array(__DIR__.'/Fixtures/classmap', array(
                'Foo\\Bar\\A'             => realpath(__DIR__).'/Fixtures/classmap/sameNsMultipleClasses.php',
                'Foo\\Bar\\B'             => realpath(__DIR__).'/Fixtures/classmap/sameNsMultipleClasses.php',
                'A'                       => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php',
                'Alpha\\A'                => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php',
                'Alpha\\B'                => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php',
                'Beta\\A'                 => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php',
                'Beta\\B'                 => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php',
                'ClassMap\\SomeInterface' => realpath(__DIR__).'/Fixtures/classmap/SomeInterface.php',
                'ClassMap\\SomeParent'    => realpath(__DIR__).'/Fixtures/classmap/SomeParent.php',
                'ClassMap\\SomeClass'     => realpath(__DIR__).'/Fixtures/classmap/SomeClass.php',
            )),
        );

        if (version_compare(PHP_VERSION, '5.4', '>=')) {
            $data[] = array(__DIR__.'/Fixtures/php5.4', array(
                'TFoo' => __DIR__.'/Fixtures/php5.4/traits.php',
                'CFoo' => __DIR__.'/Fixtures/php5.4/traits.php',
                'Foo\\TBar' => __DIR__.'/Fixtures/php5.4/traits.php',
                'Foo\\IBar' => __DIR__.'/Fixtures/php5.4/traits.php',
                'Foo\\TFooBar' => __DIR__.'/Fixtures/php5.4/traits.php',
                'Foo\\CBar' => __DIR__.'/Fixtures/php5.4/traits.php',
            ));
        }

        return $data;
    }

    public function testCreateMapFinderSupport()
    {
        $finder = new \Symfony\Component\Finder\Finder();
        $finder->files()->in(__DIR__.'/Fixtures/beta/NamespaceCollision');

        $this->assertEqualsNormalized(array(
            'NamespaceCollision\\A\\B\\Bar' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/A/B/Bar.php',
            'NamespaceCollision\\A\\B\\Foo' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/A/B/Foo.php',
            'NamespaceCollision\\C\\B\\Bar' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/C/B/Bar.php',
            'NamespaceCollision\\C\\B\\Foo' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/C/B/Foo.php',
        ), ClassMapGenerator::createMap($finder));
    }

    protected function assertEqualsNormalized($expected, $actual, $message = null)
    {
        foreach ($expected as $ns => $path) {
            $expected[$ns] = strtr($path, '\\', '/');
        }
        foreach ($actual as $ns => $path) {
            $actual[$ns] = strtr($path, '\\', '/');
        }
        $this->assertEquals($expected, $actual, $message);
    }
}
PK��Z�)mm?test/ClassLoader/Symfony/Component/ClassLoader/phpunit.xml.distnu�[���<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony ClassLoader Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./Resources</directory>
                <directory>./Tests</directory>
                <directory>./vendor</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
PK��Zy�MV����]test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests;

require_once __DIR__.'/Fixtures/includes/classes.php';
require_once __DIR__.'/Fixtures/includes/ProjectExtension.php';

use Symfony\Component\Config\Resource\ResourceInterface;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
use Symfony\Component\DependencyInjection\Loader\ClosureLoader;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\DependencyInjection\Scope;
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\ExpressionLanguage\Expression;

class ContainerBuilderTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::setDefinitions
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getDefinitions
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::setDefinition
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getDefinition
     */
    public function testDefinitions()
    {
        $builder = new ContainerBuilder();
        $definitions = array(
            'foo' => new Definition('FooClass'),
            'bar' => new Definition('BarClass'),
        );
        $builder->setDefinitions($definitions);
        $this->assertEquals($definitions, $builder->getDefinitions(), '->setDefinitions() sets the service definitions');
        $this->assertTrue($builder->hasDefinition('foo'), '->hasDefinition() returns true if a service definition exists');
        $this->assertFalse($builder->hasDefinition('foobar'), '->hasDefinition() returns false if a service definition does not exist');

        $builder->setDefinition('foobar', $foo = new Definition('FooBarClass'));
        $this->assertEquals($foo, $builder->getDefinition('foobar'), '->getDefinition() returns a service definition if defined');
        $this->assertTrue($builder->setDefinition('foobar', $foo = new Definition('FooBarClass')) === $foo, '->setDefinition() implements a fluid interface by returning the service reference');

        $builder->addDefinitions($defs = array('foobar' => new Definition('FooBarClass')));
        $this->assertEquals(array_merge($definitions, $defs), $builder->getDefinitions(), '->addDefinitions() adds the service definitions');

        try {
            $builder->getDefinition('baz');
            $this->fail('->getDefinition() throws an InvalidArgumentException if the service definition does not exist');
        } catch (\InvalidArgumentException $e) {
            $this->assertEquals('The service definition "baz" does not exist.', $e->getMessage(), '->getDefinition() throws an InvalidArgumentException if the service definition does not exist');
        }
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::register
     */
    public function testRegister()
    {
        $builder = new ContainerBuilder();
        $builder->register('foo', 'FooClass');
        $this->assertTrue($builder->hasDefinition('foo'), '->register() registers a new service definition');
        $this->assertInstanceOf('Symfony\Component\DependencyInjection\Definition', $builder->getDefinition('foo'), '->register() returns the newly created Definition instance');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::has
     */
    public function testHas()
    {
        $builder = new ContainerBuilder();
        $this->assertFalse($builder->has('foo'), '->has() returns false if the service does not exist');
        $builder->register('foo', 'FooClass');
        $this->assertTrue($builder->has('foo'), '->has() returns true if a service definition exists');
        $builder->set('bar', new \stdClass());
        $this->assertTrue($builder->has('bar'), '->has() returns true if a service exists');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::get
     */
    public function testGet()
    {
        $builder = new ContainerBuilder();
        try {
            $builder->get('foo');
            $this->fail('->get() throws an InvalidArgumentException if the service does not exist');
        } catch (\InvalidArgumentException $e) {
            $this->assertEquals('The service definition "foo" does not exist.', $e->getMessage(), '->get() throws an InvalidArgumentException if the service does not exist');
        }

        $this->assertNull($builder->get('foo', ContainerInterface::NULL_ON_INVALID_REFERENCE), '->get() returns null if the service does not exist and NULL_ON_INVALID_REFERENCE is passed as a second argument');

        $builder->register('foo', 'stdClass');
        $this->assertInternalType('object', $builder->get('foo'), '->get() returns the service definition associated with the id');
        $builder->set('bar', $bar = new \stdClass());
        $this->assertEquals($bar, $builder->get('bar'), '->get() returns the service associated with the id');
        $builder->register('bar', 'stdClass');
        $this->assertEquals($bar, $builder->get('bar'), '->get() returns the service associated with the id even if a definition has been defined');

        $builder->register('baz', 'stdClass')->setArguments(array(new Reference('baz')));
        try {
            @$builder->get('baz');
            $this->fail('->get() throws a ServiceCircularReferenceException if the service has a circular reference to itself');
        } catch (\Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException $e) {
            $this->assertEquals('Circular reference detected for service "baz", path: "baz".', $e->getMessage(), '->get() throws a LogicException if the service has a circular reference to itself');
        }

        $builder->register('foobar', 'stdClass')->setScope('container');
        $this->assertTrue($builder->get('bar') === $builder->get('bar'), '->get() always returns the same instance if the service is shared');
    }

    /**
     * @covers                   \Symfony\Component\DependencyInjection\ContainerBuilder::get
     * @expectedException        \Symfony\Component\DependencyInjection\Exception\RuntimeException
     * @expectedExceptionMessage You have requested a synthetic service ("foo"). The DIC does not know how to construct this service.
     */
    public function testGetUnsetLoadingServiceWhenCreateServiceThrowsAnException()
    {
        $builder = new ContainerBuilder();
        $builder->register('foo', 'stdClass')->setSynthetic(true);

        // we expect a RuntimeException here as foo is synthetic
        try {
            $builder->get('foo');
        } catch (RuntimeException $e) {
        }

        // we must also have the same RuntimeException here
        $builder->get('foo');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::get
     */
    public function testGetReturnsNullOnInactiveScope()
    {
        $builder = new ContainerBuilder();
        $builder->register('foo', 'stdClass')->setScope('request');

        $this->assertNull($builder->get('foo', ContainerInterface::NULL_ON_INVALID_REFERENCE));
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::get
     */
    public function testGetReturnsNullOnInactiveScopeWhenServiceIsCreatedByAMethod()
    {
        $builder = new ProjectContainer();

        $this->assertNull($builder->get('foobaz', ContainerInterface::NULL_ON_INVALID_REFERENCE));
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getServiceIds
     */
    public function testGetServiceIds()
    {
        $builder = new ContainerBuilder();
        $builder->register('foo', 'stdClass');
        $builder->bar = $bar = new \stdClass();
        $builder->register('bar', 'stdClass');
        $this->assertEquals(array('foo', 'bar', 'service_container'), $builder->getServiceIds(), '->getServiceIds() returns all defined service ids');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::setAlias
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::hasAlias
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getAlias
     */
    public function testAliases()
    {
        $builder = new ContainerBuilder();
        $builder->register('foo', 'stdClass');
        $builder->setAlias('bar', 'foo');
        $this->assertTrue($builder->hasAlias('bar'), '->hasAlias() returns true if the alias exists');
        $this->assertFalse($builder->hasAlias('foobar'), '->hasAlias() returns false if the alias does not exist');
        $this->assertEquals('foo', (string) $builder->getAlias('bar'), '->getAlias() returns the aliased service');
        $this->assertTrue($builder->has('bar'), '->setAlias() defines a new service');
        $this->assertTrue($builder->get('bar') === $builder->get('foo'), '->setAlias() creates a service that is an alias to another one');

        try {
            $builder->getAlias('foobar');
            $this->fail('->getAlias() throws an InvalidArgumentException if the alias does not exist');
        } catch (\InvalidArgumentException $e) {
            $this->assertEquals('The service alias "foobar" does not exist.', $e->getMessage(), '->getAlias() throws an InvalidArgumentException if the alias does not exist');
        }
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getAliases
     */
    public function testGetAliases()
    {
        $builder = new ContainerBuilder();
        $builder->setAlias('bar', 'foo');
        $builder->setAlias('foobar', 'foo');
        $builder->setAlias('moo', new Alias('foo', false));

        $aliases = $builder->getAliases();
        $this->assertEquals('foo', (string) $aliases['bar']);
        $this->assertTrue($aliases['bar']->isPublic());
        $this->assertEquals('foo', (string) $aliases['foobar']);
        $this->assertEquals('foo', (string) $aliases['moo']);
        $this->assertFalse($aliases['moo']->isPublic());

        $builder->register('bar', 'stdClass');
        $this->assertFalse($builder->hasAlias('bar'));

        $builder->set('foobar', 'stdClass');
        $builder->set('moo', 'stdClass');
        $this->assertCount(0, $builder->getAliases(), '->getAliases() does not return aliased services that have been overridden');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::setAliases
     */
    public function testSetAliases()
    {
        $builder = new ContainerBuilder();
        $builder->setAliases(array('bar' => 'foo', 'foobar' => 'foo'));

        $aliases = $builder->getAliases();
        $this->assertTrue(isset($aliases['bar']));
        $this->assertTrue(isset($aliases['foobar']));
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::addAliases
     */
    public function testAddAliases()
    {
        $builder = new ContainerBuilder();
        $builder->setAliases(array('bar' => 'foo'));
        $builder->addAliases(array('foobar' => 'foo'));

        $aliases = $builder->getAliases();
        $this->assertTrue(isset($aliases['bar']));
        $this->assertTrue(isset($aliases['foobar']));
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::addCompilerPass
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getCompilerPassConfig
     */
    public function testAddGetCompilerPass()
    {
        $builder = new ContainerBuilder();
        $builder->setResourceTracking(false);
        $builderCompilerPasses = $builder->getCompiler()->getPassConfig()->getPasses();
        $builder->addCompilerPass($this->getMock('Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface'));
        $this->assertEquals(sizeof($builderCompilerPasses) + 1, sizeof($builder->getCompiler()->getPassConfig()->getPasses()));
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService
     */
    public function testCreateService()
    {
        $builder = new ContainerBuilder();
        $builder->register('foo1', 'FooClass')->setFile(__DIR__.'/Fixtures/includes/foo.php');
        $this->assertInstanceOf('\FooClass', $builder->get('foo1'), '->createService() requires the file defined by the service definition');
        $builder->register('foo2', 'FooClass')->setFile(__DIR__.'/Fixtures/includes/%file%.php');
        $builder->setParameter('file', 'foo');
        $this->assertInstanceOf('\FooClass', $builder->get('foo2'), '->createService() replaces parameters in the file provided by the service definition');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService
     */
    public function testCreateProxyWithRealServiceInstantiator()
    {
        $builder = new ContainerBuilder();

        $builder->register('foo1', 'FooClass')->setFile(__DIR__.'/Fixtures/includes/foo.php');
        $builder->getDefinition('foo1')->setLazy(true);

        $foo1 = $builder->get('foo1');

        $this->assertSame($foo1, $builder->get('foo1'), 'The same proxy is retrieved on multiple subsequent calls');
        $this->assertSame('FooClass', get_class($foo1));
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService
     */
    public function testCreateServiceClass()
    {
        $builder = new ContainerBuilder();
        $builder->register('foo1', '%class%');
        $builder->setParameter('class', 'stdClass');
        $this->assertInstanceOf('\stdClass', $builder->get('foo1'), '->createService() replaces parameters in the class provided by the service definition');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService
     */
    public function testCreateServiceArguments()
    {
        $builder = new ContainerBuilder();
        $builder->register('bar', 'stdClass');
        $builder->register('foo1', 'FooClass')->addArgument(array('foo' => '%value%', '%value%' => 'foo', new Reference('bar'), '%%unescape_it%%'));
        $builder->setParameter('value', 'bar');
        $this->assertEquals(array('foo' => 'bar', 'bar' => 'foo', $builder->get('bar'), '%unescape_it%'), $builder->get('foo1')->arguments, '->createService() replaces parameters and service references in the arguments provided by the service definition');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService
     */
    public function testCreateServiceFactoryMethod()
    {
        $builder = new ContainerBuilder();
        $builder->register('bar', 'stdClass');
        $builder->register('foo1', 'FooClass')->setFactoryClass('FooClass')->setFactoryMethod('getInstance')->addArgument(array('foo' => '%value%', '%value%' => 'foo', new Reference('bar')));
        $builder->setParameter('value', 'bar');
        $this->assertTrue($builder->get('foo1')->called, '->createService() calls the factory method to create the service instance');
        $this->assertEquals(array('foo' => 'bar', 'bar' => 'foo', $builder->get('bar')), $builder->get('foo1')->arguments, '->createService() passes the arguments to the factory method');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService
     */
    public function testCreateServiceFactoryService()
    {
        $builder = new ContainerBuilder();
        $builder->register('baz_service')->setFactoryService('baz_factory')->setFactoryMethod('getInstance');
        $builder->register('baz_factory', 'BazClass');

        $this->assertInstanceOf('BazClass', $builder->get('baz_service'));
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService
     */
    public function testCreateServiceMethodCalls()
    {
        $builder = new ContainerBuilder();
        $builder->register('bar', 'stdClass');
        $builder->register('foo1', 'FooClass')->addMethodCall('setBar', array(array('%value%', new Reference('bar'))));
        $builder->setParameter('value', 'bar');
        $this->assertEquals(array('bar', $builder->get('bar')), $builder->get('foo1')->bar, '->createService() replaces the values in the method calls arguments');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService
     */
    public function testCreateServiceConfigurator()
    {
        $builder = new ContainerBuilder();
        $builder->register('foo1', 'FooClass')->setConfigurator('sc_configure');
        $this->assertTrue($builder->get('foo1')->configured, '->createService() calls the configurator');

        $builder->register('foo2', 'FooClass')->setConfigurator(array('%class%', 'configureStatic'));
        $builder->setParameter('class', 'BazClass');
        $this->assertTrue($builder->get('foo2')->configured, '->createService() calls the configurator');

        $builder->register('baz', 'BazClass');
        $builder->register('foo3', 'FooClass')->setConfigurator(array(new Reference('baz'), 'configure'));
        $this->assertTrue($builder->get('foo3')->configured, '->createService() calls the configurator');

        $builder->register('foo4', 'FooClass')->setConfigurator('foo');
        try {
            $builder->get('foo4');
            $this->fail('->createService() throws an InvalidArgumentException if the configure callable is not a valid callable');
        } catch (\InvalidArgumentException $e) {
            $this->assertEquals('The configure callable for class "FooClass" is not a callable.', $e->getMessage(), '->createService() throws an InvalidArgumentException if the configure callable is not a valid callable');
        }
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService
     * @expectedException \RuntimeException
     */
    public function testCreateSyntheticService()
    {
        $builder = new ContainerBuilder();
        $builder->register('foo', 'FooClass')->setSynthetic(true);
        $builder->get('foo');
    }

    public function testCreateServiceWithExpression()
    {
        $builder = new ContainerBuilder();
        $builder->setParameter('bar', 'bar');
        $builder->register('bar', 'BarClass');
        $builder->register('foo', 'FooClass')->addArgument(array('foo' => new Expression('service("bar").foo ~ parameter("bar")')));
        $this->assertEquals('foobar', $builder->get('foo')->arguments['foo']);
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::resolveServices
     */
    public function testResolveServices()
    {
        $builder = new ContainerBuilder();
        $builder->register('foo', 'FooClass');
        $this->assertEquals($builder->get('foo'), $builder->resolveServices(new Reference('foo')), '->resolveServices() resolves service references to service instances');
        $this->assertEquals(array('foo' => array('foo', $builder->get('foo'))), $builder->resolveServices(array('foo' => array('foo', new Reference('foo')))), '->resolveServices() resolves service references to service instances in nested arrays');
        $this->assertEquals($builder->get('foo'), $builder->resolveServices(new Expression('service("foo")')), '->resolveServices() resolves expressions');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::merge
     */
    public function testMerge()
    {
        $container = new ContainerBuilder(new ParameterBag(array('bar' => 'foo')));
        $container->setResourceTracking(false);
        $config = new ContainerBuilder(new ParameterBag(array('foo' => 'bar')));
        $container->merge($config);
        $this->assertEquals(array('bar' => 'foo', 'foo' => 'bar'), $container->getParameterBag()->all(), '->merge() merges current parameters with the loaded ones');

        $container = new ContainerBuilder(new ParameterBag(array('bar' => 'foo')));
        $container->setResourceTracking(false);
        $config = new ContainerBuilder(new ParameterBag(array('foo' => '%bar%')));
        $container->merge($config);
        $container->compile();
        $this->assertEquals(array('bar' => 'foo', 'foo' => 'foo'), $container->getParameterBag()->all(), '->merge() evaluates the values of the parameters towards already defined ones');

        $container = new ContainerBuilder(new ParameterBag(array('bar' => 'foo')));
        $container->setResourceTracking(false);
        $config = new ContainerBuilder(new ParameterBag(array('foo' => '%bar%', 'baz' => '%foo%')));
        $container->merge($config);
        $container->compile();
        $this->assertEquals(array('bar' => 'foo', 'foo' => 'foo', 'baz' => 'foo'), $container->getParameterBag()->all(), '->merge() evaluates the values of the parameters towards already defined ones');

        $container = new ContainerBuilder();
        $container->setResourceTracking(false);
        $container->register('foo', 'FooClass');
        $container->register('bar', 'BarClass');
        $config = new ContainerBuilder();
        $config->setDefinition('baz', new Definition('BazClass'));
        $config->setAlias('alias_for_foo', 'foo');
        $container->merge($config);
        $this->assertEquals(array('foo', 'bar', 'baz'), array_keys($container->getDefinitions()), '->merge() merges definitions already defined ones');

        $aliases = $container->getAliases();
        $this->assertTrue(isset($aliases['alias_for_foo']));
        $this->assertEquals('foo', (string) $aliases['alias_for_foo']);

        $container = new ContainerBuilder();
        $container->setResourceTracking(false);
        $container->register('foo', 'FooClass');
        $config->setDefinition('foo', new Definition('BazClass'));
        $container->merge($config);
        $this->assertEquals('BazClass', $container->getDefinition('foo')->getClass(), '->merge() overrides already defined services');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::merge
     * @expectedException \LogicException
     */
    public function testMergeLogicException()
    {
        $container = new ContainerBuilder();
        $container->setResourceTracking(false);
        $container->compile();
        $container->merge(new ContainerBuilder());
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::findTaggedServiceIds
     */
    public function testfindTaggedServiceIds()
    {
        $builder = new ContainerBuilder();
        $builder
            ->register('foo', 'FooClass')
            ->addTag('foo', array('foo' => 'foo'))
            ->addTag('bar', array('bar' => 'bar'))
            ->addTag('foo', array('foofoo' => 'foofoo'))
        ;
        $this->assertEquals($builder->findTaggedServiceIds('foo'), array(
            'foo' => array(
                array('foo' => 'foo'),
                array('foofoo' => 'foofoo'),
            )
        ), '->findTaggedServiceIds() returns an array of service ids and its tag attributes');
        $this->assertEquals(array(), $builder->findTaggedServiceIds('foobar'), '->findTaggedServiceIds() returns an empty array if there is annotated services');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::findDefinition
     */
    public function testFindDefinition()
    {
        $container = new ContainerBuilder();
        $container->setDefinition('foo', $definition = new Definition('FooClass'));
        $container->setAlias('bar', 'foo');
        $container->setAlias('foobar', 'bar');
        $this->assertEquals($definition, $container->findDefinition('foobar'), '->findDefinition() returns a Definition');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::addObjectResource
     */
    public function testAddObjectResource()
    {
        $container = new ContainerBuilder();

        $container->setResourceTracking(false);
        $container->addObjectResource(new \BarClass());

        $this->assertEmpty($container->getResources(), 'No resources get registered without resource tracking');

        $container->setResourceTracking(true);
        $container->addObjectResource(new \BarClass());

        $resources = $container->getResources();

        $this->assertCount(1, $resources, '1 resource was registered');

        /* @var $resource \Symfony\Component\Config\Resource\FileResource */
        $resource = end($resources);

        $this->assertInstanceOf('Symfony\Component\Config\Resource\FileResource', $resource);
        $this->assertSame(realpath(__DIR__.'/Fixtures/includes/classes.php'), realpath($resource->getResource()));
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::addClassResource
     */
    public function testAddClassResource()
    {
        $container = new ContainerBuilder();

        $container->setResourceTracking(false);
        $container->addClassResource(new \ReflectionClass('BarClass'));

        $this->assertEmpty($container->getResources(), 'No resources get registered without resource tracking');

        $container->setResourceTracking(true);
        $container->addClassResource(new \ReflectionClass('BarClass'));

        $resources = $container->getResources();

        $this->assertCount(1, $resources, '1 resource was registered');

        /* @var $resource \Symfony\Component\Config\Resource\FileResource */
        $resource = end($resources);

        $this->assertInstanceOf('Symfony\Component\Config\Resource\FileResource', $resource);
        $this->assertSame(realpath(__DIR__.'/Fixtures/includes/classes.php'), realpath($resource->getResource()));
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::compile
     */
    public function testCompilesClassDefinitionsOfLazyServices()
    {
        $container = new ContainerBuilder();

        $this->assertEmpty($container->getResources(), 'No resources get registered without resource tracking');

        $container->register('foo', 'BarClass');
        $container->getDefinition('foo')->setLazy(true);

        $container->compile();

        $classesPath       = realpath(__DIR__.'/Fixtures/includes/classes.php');
        $matchingResources = array_filter(
            $container->getResources(),
            function (ResourceInterface $resource) use ($classesPath) {
                return $resource instanceof FileResource && $classesPath === realpath($resource->getResource());
            }
        );

        $this->assertNotEmpty($matchingResources);
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getResources
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::addResource
     */
    public function testResources()
    {
        $container = new ContainerBuilder();
        $container->addResource($a = new FileResource(__DIR__.'/Fixtures/xml/services1.xml'));
        $container->addResource($b = new FileResource(__DIR__.'/Fixtures/xml/services2.xml'));
        $resources = array();
        foreach ($container->getResources() as $resource) {
            if (false === strpos($resource, '.php')) {
                $resources[] = $resource;
            }
        }
        $this->assertEquals(array($a, $b), $resources, '->getResources() returns an array of resources read for the current configuration');
        $this->assertSame($container, $container->setResources(array()));
        $this->assertEquals(array(), $container->getResources());
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::registerExtension
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getExtension
     */
    public function testExtension()
    {
        $container = new ContainerBuilder();
        $container->setResourceTracking(false);

        $container->registerExtension($extension = new \ProjectExtension());
        $this->assertTrue($container->getExtension('project') === $extension, '->registerExtension() registers an extension');

        $this->setExpectedException('LogicException');
        $container->getExtension('no_registered');
    }

    public function testRegisteredButNotLoadedExtension()
    {
        $extension = $this->getMock('Symfony\\Component\\DependencyInjection\\Extension\\ExtensionInterface');
        $extension->expects($this->once())->method('getAlias')->will($this->returnValue('project'));
        $extension->expects($this->never())->method('load');

        $container = new ContainerBuilder();
        $container->setResourceTracking(false);
        $container->registerExtension($extension);
        $container->compile();
    }

    public function testRegisteredAndLoadedExtension()
    {
        $extension = $this->getMock('Symfony\\Component\\DependencyInjection\\Extension\\ExtensionInterface');
        $extension->expects($this->exactly(2))->method('getAlias')->will($this->returnValue('project'));
        $extension->expects($this->once())->method('load')->with(array(array('foo' => 'bar')));

        $container = new ContainerBuilder();
        $container->setResourceTracking(false);
        $container->registerExtension($extension);
        $container->loadFromExtension('project', array('foo' => 'bar'));
        $container->compile();
    }

    public function testPrivateServiceUser()
    {
        $fooDefinition     = new Definition('BarClass');
        $fooUserDefinition = new Definition('BarUserClass', array(new Reference('bar')));
        $container         = new ContainerBuilder();
        $container->setResourceTracking(false);

        $fooDefinition->setPublic(false);

        $container->addDefinitions(array(
            'bar'       => $fooDefinition,
            'bar_user'  => $fooUserDefinition
        ));

        $container->compile();
        $this->assertInstanceOf('BarClass', $container->get('bar_user')->bar);
    }

    /**
     * @expectedException \BadMethodCallException
     */
    public function testThrowsExceptionWhenSetServiceOnAFrozenContainer()
    {
        $container = new ContainerBuilder();
        $container->setResourceTracking(false);
        $container->setDefinition('a', new Definition('stdClass'));
        $container->compile();
        $container->set('a', new \stdClass());
    }

    /**
     * @expectedException \BadMethodCallException
     */
    public function testThrowsExceptionWhenAddServiceOnAFrozenContainer()
    {
        $container = new ContainerBuilder();
        $container->compile();
        $container->set('a', new \stdClass());
    }

    public function testNoExceptionWhenSetSyntheticServiceOnAFrozenContainer()
    {
        $container = new ContainerBuilder();
        $def = new Definition('stdClass');
        $def->setSynthetic(true);
        $container->setDefinition('a', $def);
        $container->compile();
        $container->set('a', $a = new \stdClass());
        $this->assertEquals($a, $container->get('a'));
    }

    public function testSetOnSynchronizedService()
    {
        $container = new ContainerBuilder();
        $container->register('baz', 'BazClass')
            ->setSynchronized(true)
        ;
        $container->register('bar', 'BarClass')
            ->addMethodCall('setBaz', array(new Reference('baz')))
        ;

        $container->set('baz', $baz = new \BazClass());
        $this->assertSame($baz, $container->get('bar')->getBaz());

        $container->set('baz', $baz = new \BazClass());
        $this->assertSame($baz, $container->get('bar')->getBaz());
    }

    public function testSynchronizedServiceWithScopes()
    {
        $container = new ContainerBuilder();
        $container->addScope(new Scope('foo'));
        $container->register('baz', 'BazClass')
            ->setSynthetic(true)
            ->setSynchronized(true)
            ->setScope('foo')
        ;
        $container->register('bar', 'BarClass')
            ->addMethodCall('setBaz', array(new Reference('baz', ContainerInterface::NULL_ON_INVALID_REFERENCE, false)))
        ;
        $container->compile();

        $container->enterScope('foo');
        $container->set('baz', $outerBaz = new \BazClass(), 'foo');
        $this->assertSame($outerBaz, $container->get('bar')->getBaz());

        $container->enterScope('foo');
        $container->set('baz', $innerBaz = new \BazClass(), 'foo');
        $this->assertSame($innerBaz, $container->get('bar')->getBaz());
        $container->leaveScope('foo');

        $this->assertNotSame($innerBaz, $container->get('bar')->getBaz());
        $this->assertSame($outerBaz, $container->get('bar')->getBaz());

        $container->leaveScope('foo');
    }

    /**
     * @expectedException \BadMethodCallException
     */
    public function testThrowsExceptionWhenSetDefinitionOnAFrozenContainer()
    {
        $container = new ContainerBuilder();
        $container->setResourceTracking(false);
        $container->compile();
        $container->setDefinition('a', new Definition());
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getExtensionConfig
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::prependExtensionConfig
     */
    public function testExtensionConfig()
    {
        $container = new ContainerBuilder();

        $configs = $container->getExtensionConfig('foo');
        $this->assertEmpty($configs);

        $first = array('foo' => 'bar');
        $container->prependExtensionConfig('foo', $first);
        $configs = $container->getExtensionConfig('foo');
        $this->assertEquals(array($first), $configs);

        $second = array('ding' => 'dong');
        $container->prependExtensionConfig('foo', $second);
        $configs = $container->getExtensionConfig('foo');
        $this->assertEquals(array($second, $first), $configs);
    }

    public function testLazyLoadedService()
    {
        $loader = new ClosureLoader($container = new ContainerBuilder());
        $loader->load(function (ContainerBuilder $container) {
                $container->set('a', new \BazClass());
                $definition = new Definition('BazClass');
                $definition->setLazy(true);
                $container->setDefinition('a', $definition);
            }
        );

        $container->setResourceTracking(true);

        $container->compile();

        $class = new \BazClass();
        $reflectionClass = new \ReflectionClass($class);

        $r = new \ReflectionProperty($container, 'resources');
        $r->setAccessible(true);
        $resources = $r->getValue($container);

        $classInList = false;
        foreach ($resources as $resource) {
            if ($resource->getResource() === $reflectionClass->getFileName()) {
                $classInList = true;
                break;
            }
        }

        $this->assertTrue($classInList);
    }
}

class FooClass {}

class ProjectContainer extends ContainerBuilder
{
    public function getFoobazService()
    {
        throw new InactiveScopeException('foo', 'request');
    }
}
PK��Z�[��Vtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/ParameterTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests;

use Symfony\Component\DependencyInjection\Parameter;

class ParameterTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Symfony\Component\DependencyInjection\Parameter::__construct
     */
    public function testConstructor()
    {
        $ref = new Parameter('foo');
        $this->assertEquals('foo', (string) $ref, '__construct() sets the id of the parameter, which is used for the __toString() method');
    }
}
PK��Z~O�99ktest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/LazyProxy/PhpDumper/NullDumperTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\LazyProxy\PhpDumper;

use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper;

/**
 * Tests for {@see \Symfony\Component\DependencyInjection\PhpDumper\NullDumper}
 *
 * @author Marco Pivetta <ocramius@gmail.com>
 *
 * @covers \Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper
 */
class NullDumperTest extends \PHPUnit_Framework_TestCase
{
    public function testNullDumper()
    {
        $dumper     = new NullDumper();
        $definition = new Definition('stdClass');

        $this->assertFalse($dumper->isProxyCandidate($definition));
        $this->assertSame('', $dumper->getProxyFactoryCode($definition, 'foo'));
        $this->assertSame('', $dumper->getProxyCode($definition));
    }
}
PK��ZI8�i��{test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/LazyProxy/Instantiator/RealServiceInstantiatorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\LazyProxy\Instantiator;

use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator;

/**
 * Tests for {@see \Symfony\Component\DependencyInjection\Instantiator\RealServiceInstantiator}
 *
 * @author Marco Pivetta <ocramius@gmail.com>
 *
 * @covers \Symfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator
 */
class RealServiceInstantiatorTest extends \PHPUnit_Framework_TestCase
{
    public function testInstantiateProxy()
    {
        $instantiator = new RealServiceInstantiator();
        $instance     = new \stdClass();
        $container    = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
        $callback     = function () use ($instance) {
            return $instance;
        };

        $this->assertSame($instance, $instantiator->instantiateProxy($container, new Definition(), 'foo', $callback));
    }
}
PK��Z���//\test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/simple.phpnu�[���<?php

$container->setParameter('foo', 'foo');
PK��ZG3G@��`test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.phpnu�[���<?php

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;

/**
 * ProjectServiceContainer
 *
 * This class has been auto-generated
 * by the Symfony Dependency Injection Component.
 */
class ProjectServiceContainer extends Container
{
    /**
     * Constructor.
     */
    public function __construct()
    {
        $this->parameters = $this->getDefaultParameters();

        $this->services =
        $this->scopedServices =
        $this->scopeStacks = array();

        $this->set('service_container', $this);

        $this->scopes = array();
        $this->scopeChildren = array();
        $this->methodMap = array(
            'test' => 'getTestService',
        );

        $this->aliases = array();
    }

    /**
     * Gets the 'test' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return stdClass A stdClass instance.
     */
    protected function getTestService()
    {
        return $this->services['test'] = new \stdClass(array('only dot' => '.', 'concatenation as value' => '.\'\'.', 'concatenation from the start value' => '\'\'.', '.' => 'dot as a key', '.\'\'.' => 'concatenation as a key', '\'\'.' => 'concatenation from the start key', 'optimize concatenation' => 'string1-string2', 'optimize concatenation with empty string' => 'string1string2', 'optimize concatenation from the start' => 'start', 'optimize concatenation at the end' => 'end'));
    }

    /**
     * {@inheritdoc}
     */
    public function getParameter($name)
    {
        $name = strtolower($name);

        if (!(isset($this->parameters[$name]) || array_key_exists($name, $this->parameters))) {
            throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name));
        }

        return $this->parameters[$name];
    }

    /**
     * {@inheritdoc}
     */
    public function hasParameter($name)
    {
        $name = strtolower($name);

        return isset($this->parameters[$name]) || array_key_exists($name, $this->parameters);
    }

    /**
     * {@inheritdoc}
     */
    public function setParameter($name, $value)
    {
        throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
    }

    /**
     * {@inheritDoc}
     */
    public function getParameterBag()
    {
        if (null === $this->parameterBag) {
            $this->parameterBag = new FrozenParameterBag($this->parameters);
        }

        return $this->parameterBag;
    }
    /**
     * Gets the default parameters.
     *
     * @return array An array of the default parameters
     */
    protected function getDefaultParameters()
    {
        return array(
            'empty_value' => '',
            'some_string' => '-',
        );
    }
}
PK��ZE�))atest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.phpnu�[���<?php
namespace Symfony\Component\DependencyInjection\Dump;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;

/**
 * Container
 *
 * This class has been auto-generated
 * by the Symfony Dependency Injection Component.
 */
class Container extends AbstractContainer
{
    /**
     * Constructor.
     */
    public function __construct()
    {
        parent::__construct();
    }
}
PK��Zo�Tb_test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.phpnu�[���<?php

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;

/**
 * ProjectServiceContainer
 *
 * This class has been auto-generated
 * by the Symfony Dependency Injection Component.
 */
class ProjectServiceContainer extends Container
{
    /**
     * Constructor.
     */
    public function __construct()
    {
        parent::__construct();
    }
}
PK��Z,�j���_test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.phpnu�[���<?php

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;

/**
 * ProjectServiceContainer
 *
 * This class has been auto-generated
 * by the Symfony Dependency Injection Component.
 */
class ProjectServiceContainer extends Container
{
    /**
     * Constructor.
     */
    public function __construct()
    {
        parent::__construct(new ParameterBag($this->getDefaultParameters()));
        $this->methodMap = array(
            'bar' => 'getBarService',
            'baz' => 'getBazService',
            'depends_on_request' => 'getDependsOnRequestService',
            'factory_service' => 'getFactoryServiceService',
            'foo' => 'getFooService',
            'foo.baz' => 'getFoo_BazService',
            'foo_bar' => 'getFooBarService',
            'foo_with_inline' => 'getFooWithInlineService',
            'inlined' => 'getInlinedService',
            'method_call1' => 'getMethodCall1Service',
            'request' => 'getRequestService',
        );
        $this->aliases = array(
            'alias_for_alias' => 'foo',
            'alias_for_foo' => 'foo',
        );
    }

    /**
     * Gets the 'bar' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return FooClass A FooClass instance.
     */
    protected function getBarService()
    {
        $this->services['bar'] = $instance = new \FooClass('foo', $this->get('foo.baz'), $this->getParameter('foo_bar'));

        $this->get('foo.baz')->configure($instance);

        return $instance;
    }

    /**
     * Gets the 'baz' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return Baz A Baz instance.
     */
    protected function getBazService()
    {
        $this->services['baz'] = $instance = new \Baz();

        $instance->setFoo($this->get('foo_with_inline'));

        return $instance;
    }

    /**
     * Gets the 'depends_on_request' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return stdClass A stdClass instance.
     */
    protected function getDependsOnRequestService()
    {
        $this->services['depends_on_request'] = $instance = new \stdClass();

        $instance->setRequest($this->get('request', ContainerInterface::NULL_ON_INVALID_REFERENCE));

        return $instance;
    }

    /**
     * Gets the 'factory_service' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return Bar A Bar instance.
     */
    protected function getFactoryServiceService()
    {
        return $this->services['factory_service'] = $this->get('foo.baz')->getInstance();
    }

    /**
     * Gets the 'foo' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return FooClass A FooClass instance.
     */
    protected function getFooService()
    {
        $a = $this->get('foo.baz');

        $this->services['foo'] = $instance = call_user_func(array('FooClass', 'getInstance'), 'foo', $a, array($this->getParameter('foo') => 'foo is '.$this->getParameter('foo').'', 'foobar' => $this->getParameter('foo')), true, $this);

        $instance->setBar($this->get('bar'));
        $instance->initialize();
        $instance->foo = 'bar';
        $instance->moo = $a;
        $instance->qux = array($this->getParameter('foo') => 'foo is '.$this->getParameter('foo').'', 'foobar' => $this->getParameter('foo'));
        sc_configure($instance);

        return $instance;
    }

    /**
     * Gets the 'foo.baz' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return object A %baz_class% instance.
     */
    protected function getFoo_BazService()
    {
        $this->services['foo.baz'] = $instance = call_user_func(array($this->getParameter('baz_class'), 'getInstance'));

        call_user_func(array($this->getParameter('baz_class'), 'configureStatic1'), $instance);

        return $instance;
    }

    /**
     * Gets the 'foo_bar' service.
     *
     * @return object A %foo_class% instance.
     */
    protected function getFooBarService()
    {
        $class = $this->getParameter('foo_class');

        return new $class();
    }

    /**
     * Gets the 'foo_with_inline' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return Foo A Foo instance.
     */
    protected function getFooWithInlineService()
    {
        $this->services['foo_with_inline'] = $instance = new \Foo();

        $instance->setBar($this->get('inlined'));

        return $instance;
    }

    /**
     * Gets the 'method_call1' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return FooClass A FooClass instance.
     */
    protected function getMethodCall1Service()
    {
        require_once '%path%foo.php';

        $this->services['method_call1'] = $instance = new \FooClass();

        $instance->setBar($this->get('foo'));
        $instance->setBar($this->get('foo2', ContainerInterface::NULL_ON_INVALID_REFERENCE));
        if ($this->has('foo3')) {
            $instance->setBar($this->get('foo3', ContainerInterface::NULL_ON_INVALID_REFERENCE));
        }
        if ($this->has('foobaz')) {
            $instance->setBar($this->get('foobaz', ContainerInterface::NULL_ON_INVALID_REFERENCE));
        }
        $instance->setBar(($this->get("foo")->foo() . $this->getParameter("foo")));

        return $instance;
    }

    /**
     * Gets the 'request' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @throws RuntimeException always since this service is expected to be injected dynamically
     */
    protected function getRequestService()
    {
        throw new RuntimeException('You have requested a synthetic service ("request"). The DIC does not know how to construct this service.');
    }

    /**
     * Updates the 'request' service.
     */
    protected function synchronizeRequestService()
    {
        if ($this->initialized('depends_on_request')) {
            $this->get('depends_on_request')->setRequest($this->get('request', ContainerInterface::NULL_ON_INVALID_REFERENCE));
        }
    }

    /**
     * Gets the 'inlined' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * This service is private.
     * If you want to be able to request this service from the container directly,
     * make it public, otherwise you might end up with broken code.
     *
     * @return Bar A Bar instance.
     */
    protected function getInlinedService()
    {
        $this->services['inlined'] = $instance = new \Bar();

        $instance->setBaz($this->get('baz'));
        $instance->pub = 'pub';

        return $instance;
    }

    /**
     * Gets the default parameters.
     *
     * @return array An array of the default parameters
     */
    protected function getDefaultParameters()
    {
        return array(
            'baz_class' => 'BazClass',
            'foo_class' => 'FooClass',
            'foo' => 'bar',
        );
    }
}
PK��Z$�oyy`test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services11.phpnu�[���<?php

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;

/**
 * ProjectServiceContainer
 *
 * This class has been auto-generated
 * by the Symfony Dependency Injection Component.
 */
class ProjectServiceContainer extends Container
{
    /**
     * Constructor.
     */
    public function __construct()
    {
        $this->services =
        $this->scopedServices =
        $this->scopeStacks = array();

        $this->set('service_container', $this);

        $this->scopes = array();
        $this->scopeChildren = array();
        $this->methodMap = array(
            'foo' => 'getFooService',
        );

        $this->aliases = array();
    }

    /**
     * Gets the 'foo' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return stdClass A stdClass instance.
     */
    protected function getFooService()
    {
        return $this->services['foo'] = new \stdClass();
    }
}
PK��Z��:A!!htest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.phpnu�[���<?php

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;

/**
 * ProjectServiceContainer
 *
 * This class has been auto-generated
 * by the Symfony Dependency Injection Component.
 */
class ProjectServiceContainer extends Container
{
    /**
     * Constructor.
     */
    public function __construct()
    {
        $this->parameters = $this->getDefaultParameters();

        $this->services =
        $this->scopedServices =
        $this->scopeStacks = array();

        $this->set('service_container', $this);

        $this->scopes = array();
        $this->scopeChildren = array();
        $this->methodMap = array(
            'bar' => 'getBarService',
            'baz' => 'getBazService',
            'depends_on_request' => 'getDependsOnRequestService',
            'factory_service' => 'getFactoryServiceService',
            'foo' => 'getFooService',
            'foo.baz' => 'getFoo_BazService',
            'foo_bar' => 'getFooBarService',
            'foo_with_inline' => 'getFooWithInlineService',
            'method_call1' => 'getMethodCall1Service',
            'request' => 'getRequestService',
        );
        $this->aliases = array(
            'alias_for_alias' => 'foo',
            'alias_for_foo' => 'foo',
        );
    }

    /**
     * Gets the 'bar' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return FooClass A FooClass instance.
     */
    protected function getBarService()
    {
        $this->services['bar'] = $instance = new \FooClass('foo', $this->get('foo.baz'), $this->getParameter('foo_bar'));

        $this->get('foo.baz')->configure($instance);

        return $instance;
    }

    /**
     * Gets the 'baz' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return Baz A Baz instance.
     */
    protected function getBazService()
    {
        $this->services['baz'] = $instance = new \Baz();

        $instance->setFoo($this->get('foo_with_inline'));

        return $instance;
    }

    /**
     * Gets the 'depends_on_request' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return stdClass A stdClass instance.
     */
    protected function getDependsOnRequestService()
    {
        $this->services['depends_on_request'] = $instance = new \stdClass();

        $instance->setRequest($this->get('request', ContainerInterface::NULL_ON_INVALID_REFERENCE));

        return $instance;
    }

    /**
     * Gets the 'factory_service' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return Bar A Bar instance.
     */
    protected function getFactoryServiceService()
    {
        return $this->services['factory_service'] = $this->get('foo.baz')->getInstance();
    }

    /**
     * Gets the 'foo' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return FooClass A FooClass instance.
     */
    protected function getFooService()
    {
        $a = $this->get('foo.baz');

        $this->services['foo'] = $instance = call_user_func(array('FooClass', 'getInstance'), 'foo', $a, array('bar' => 'foo is bar', 'foobar' => 'bar'), true, $this);

        $instance->setBar($this->get('bar'));
        $instance->initialize();
        $instance->foo = 'bar';
        $instance->moo = $a;
        $instance->qux = array('bar' => 'foo is bar', 'foobar' => 'bar');
        sc_configure($instance);

        return $instance;
    }

    /**
     * Gets the 'foo.baz' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return BazClass A BazClass instance.
     */
    protected function getFoo_BazService()
    {
        $this->services['foo.baz'] = $instance = call_user_func(array('BazClass', 'getInstance'));

        call_user_func(array('BazClass', 'configureStatic1'), $instance);

        return $instance;
    }

    /**
     * Gets the 'foo_bar' service.
     *
     * @return FooClass A FooClass instance.
     */
    protected function getFooBarService()
    {
        return new \FooClass();
    }

    /**
     * Gets the 'foo_with_inline' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return Foo A Foo instance.
     */
    protected function getFooWithInlineService()
    {
        $a = new \Bar();

        $this->services['foo_with_inline'] = $instance = new \Foo();

        $a->setBaz($this->get('baz'));
        $a->pub = 'pub';

        $instance->setBar($a);

        return $instance;
    }

    /**
     * Gets the 'method_call1' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return FooClass A FooClass instance.
     */
    protected function getMethodCall1Service()
    {
        require_once '%path%foo.php';

        $this->services['method_call1'] = $instance = new \FooClass();

        $instance->setBar($this->get('foo'));
        $instance->setBar(NULL);
        $instance->setBar(($this->get("foo")->foo() . $this->getParameter("foo")));

        return $instance;
    }

    /**
     * Gets the 'request' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @throws RuntimeException always since this service is expected to be injected dynamically
     */
    protected function getRequestService()
    {
        throw new RuntimeException('You have requested a synthetic service ("request"). The DIC does not know how to construct this service.');
    }

    /**
     * Updates the 'request' service.
     */
    protected function synchronizeRequestService()
    {
        if ($this->initialized('depends_on_request')) {
            $this->get('depends_on_request')->setRequest($this->get('request', ContainerInterface::NULL_ON_INVALID_REFERENCE));
        }
    }

    /**
     * {@inheritdoc}
     */
    public function getParameter($name)
    {
        $name = strtolower($name);

        if (!(isset($this->parameters[$name]) || array_key_exists($name, $this->parameters))) {
            throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name));
        }

        return $this->parameters[$name];
    }

    /**
     * {@inheritdoc}
     */
    public function hasParameter($name)
    {
        $name = strtolower($name);

        return isset($this->parameters[$name]) || array_key_exists($name, $this->parameters);
    }

    /**
     * {@inheritdoc}
     */
    public function setParameter($name, $value)
    {
        throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
    }

    /**
     * {@inheritDoc}
     */
    public function getParameterBag()
    {
        if (null === $this->parameterBag) {
            $this->parameterBag = new FrozenParameterBag($this->parameters);
        }

        return $this->parameterBag;
    }
    /**
     * Gets the default parameters.
     *
     * @return array An array of the default parameters
     */
    protected function getDefaultParameters()
    {
        return array(
            'baz_class' => 'BazClass',
            'foo_class' => 'FooClass',
            'foo' => 'bar',
        );
    }
}
PK��Z��7/��_test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.phpnu�[���<?php

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;

/**
 * ProjectServiceContainer
 *
 * This class has been auto-generated
 * by the Symfony Dependency Injection Component.
 */
class ProjectServiceContainer extends Container
{
    /**
     * Constructor.
     */
    public function __construct()
    {
        parent::__construct(new ParameterBag($this->getDefaultParameters()));
    }

    /**
     * Gets the default parameters.
     *
     * @return array An array of the default parameters
     */
    protected function getDefaultParameters()
    {
        return array(
            'foo' => '%baz%',
            'baz' => 'bar',
            'bar' => 'foo is %%foo bar',
            'escape' => '@escapeme',
            'values' => array(
                0 => true,
                1 => false,
                2 => NULL,
                3 => 0,
                4 => 1000.3,
                5 => 'true',
                6 => 'false',
                7 => 'null',
            ),
        );
    }
}
PK��Z�(]

_test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services1.xmlnu�[���<?xml version="1.0" encoding="utf-8"?>
<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"/>
PK��Z�ibĤ�_test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services5.xmlnu�[���<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
  <services>
    <service id="foo" class="FooClass">
      <argument type="service">
        <service class="BarClass">
          <argument type="service">
            <service class="BazClass">
            </service>
          </argument>
        </service>
      </argument>
      <property name="p" type="service">
        <service class="BazClass" />
      </property>
    </service>
  </services>
</container>
PK��Z�![�`test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services10.xmlnu�[���<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
  <services>
    <service id="foo" class="BarClass">
        <tag name="foo_tag"
            some-option="cat"
            some_option="ciz"
            other-option="lorem"
            an_other-option="ipsum"
        />
    </service>
  </services>
</container>
PK��Zu�

_test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4.xmlnu�[���<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
  <imports>
    <import resource="services2.xml" />
    <import resource="services3.xml" />
    <import resource="../ini/parameters.ini" />
    <import resource="../ini/parameters2.ini" />
    <import resource="../yaml/services13.yml" />
  </imports>
</container>
PK��Z�_�+WW_test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services7.xmlnu�[���<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
  <services>
    <service id="foo" class="BarClass" />
  </services>
</container>
PK��Zx'�	11atest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/withdoctype.xmlnu�[���<?xml version="1.0"?>
<!DOCTYPE foo>
<foo></foo>
PK��Z�w�zhh_test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services8.xmlnu�[���<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
  <parameters>
    <parameter key="foo">%baz%</parameter>
    <parameter key="baz">bar</parameter>
    <parameter key="bar">foo is %%foo bar</parameter>
    <parameter key="escape">@escapeme</parameter>
    <parameter key="values" type="collection">
      <parameter>true</parameter>
      <parameter>false</parameter>
      <parameter>null</parameter>
      <parameter>0</parameter>
      <parameter>1000.3</parameter>
      <parameter type="string">true</parameter>
      <parameter type="string">false</parameter>
      <parameter type="string">null</parameter>
    </parameter>
  </parameters>
</container>
PK��Z���<ii`test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services13.xmlnu�[���<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
  <parameters>
    <parameter key="imported_from_xml">true</parameter>
  </parameters>
</container>
PK��Zp�Ԡ��_test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services6.xmlnu�[���<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
  <services>
    <service id="foo" class="FooClass" />
    <service id="baz" class="BazClass" />
    <service id="scope.container" class="FooClass" scope="container" />
    <service id="scope.custom" class="FooClass" scope="custom" />
    <service id="scope.prototype" class="FooClass" scope="prototype" />
    <service id="constructor" class="FooClass" factory-method="getInstance" />
    <service id="file" class="FooClass">
      <file>%path%/foo.php</file>
    </service>
    <service id="arguments" class="FooClass">
      <argument>foo</argument>
      <argument type="service" id="foo" />
      <argument type="collection">
        <argument>true</argument>
        <argument>false</argument>
      </argument>
    </service>
    <service id="configurator1" class="FooClass">
      <configurator function="sc_configure" />
    </service>
    <service id="configurator2" class="FooClass">
      <configurator service="baz" method="configure" />
    </service>
    <service id="configurator3" class="FooClass">
      <configurator class="BazClass" method="configureStatic" />
    </service>
    <service id="method_call1" class="FooClass">
      <call method="setBar" />
      <call method="setBar">
        <argument type="expression">service("foo").foo() ~ parameter("foo")</argument>
      </call>
    </service>
    <service id="method_call2" class="FooClass">
      <call method="setBar">
        <argument>foo</argument>
        <argument type="service" id="foo" />
        <argument type="collection">
          <argument>true</argument>
          <argument>false</argument>
        </argument>
      </call>
    </service>
    <service id="alias_for_foo" alias="foo" />
    <service id="another_alias_for_foo" alias="foo" public="false" />
    <service id="factory_service" factory-method="getInstance" factory-service="baz_factory" />
    <service id="request" class="Request" synthetic="true" synchronized="true" lazy="true"/>
  </services>
</container>
PK��Z˕n%%^test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/nonvalid.xmlnu�[���<?xml version="1.0" ?>

<nonvalid />
PK��Z��Pggjtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4_bad_import.xmlnu�[���<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
  <imports>
    <import resource="foo_fake.xml" ignore-errors="true" />
  </imports>
</container>
PK��Z\_���_test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services3.xmlnu�[���<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
  <parameters>
    <parameter key="foo">foo</parameter>
    <parameter key="values" type="collection">
      <parameter>true</parameter>
      <parameter>false</parameter>
    </parameter>
  </parameters>
</container>
PK��Z]2�
��itest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extension2/services.xmlnu�[���<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
  <services>
    <service id="extension2.foo" class="FooClass2">
      <argument type="service">
        <service class="BarClass2">
        </service>
      </argument>
    </service>
  </services>
</container>
PK��Z	�_test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services2.xmlnu�[���<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
  <parameters>
    <parameter>a string</parameter>
    <parameter key="FOO">bar</parameter>
    <parameter key="values" type="collection">
      <parameter>0</parameter>
      <parameter key="integer">4</parameter>
      <parameter key="100">null</parameter>
      <parameter type="string">true</parameter>
      <parameter>true</parameter>
      <parameter>false</parameter>
      <parameter>on</parameter>
      <parameter>off</parameter>
      <parameter key="float">1.3</parameter>
      <parameter>1000.3</parameter>
      <parameter>a string</parameter>
      <parameter type="collection">
        <parameter>foo</parameter>
        <parameter>bar</parameter>
      </parameter>
    </parameter>
    <parameter key="foo_bar" type="service" id="foo_bar" />
    <parameter key="MixedCase" type="collection"> <!-- Should be lower cased -->
      <parameter key="MixedCaseKey">value</parameter> <!-- Should stay mixed case -->
    </parameter>
    <parameter key="constant" type="constant">PHP_EOL</parameter>
  </parameters>
</container>
PK��Z������itest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extension1/services.xmlnu�[���<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
  <services>
    <service id="extension1.foo" class="FooClass1">
      <argument type="service">
        <service class="BarClass1">
        </service>
      </argument>
    </service>
  </services>
</container>
PK��ZB�X�

_test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xmlnu�[���<?xml version="1.0" encoding="utf-8"?>
<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
  <parameters>
    <parameter key="baz_class">BazClass</parameter>
    <parameter key="foo_class">FooClass</parameter>
    <parameter key="foo">bar</parameter>
  </parameters>
  <services>
    <service id="foo" class="FooClass" factory-method="getInstance">
      <tag name="foo" foo="foo"/>
      <tag name="foo" bar="bar"/>
      <argument>foo</argument>
      <argument type="service" id="foo.baz"/>
      <argument type="collection">
        <argument key="%foo%">foo is %foo%</argument>
        <argument key="foobar">%foo%</argument>
      </argument>
      <argument>true</argument>
      <argument type="service" id="service_container"/>
      <property name="foo">bar</property>
      <property name="moo" type="service" id="foo.baz"/>
      <property name="qux" type="collection">
        <property key="%foo%">foo is %foo%</property>
        <property key="foobar">%foo%</property>
      </property>
      <call method="setBar">
        <argument type="service" id="bar"/>
      </call>
      <call method="initialize"/>
      <configurator function="sc_configure"/>
    </service>
    <service id="bar" class="FooClass">
      <argument>foo</argument>
      <argument type="service" id="foo.baz"/>
      <argument>%foo_bar%</argument>
      <configurator service="foo.baz" method="configure"/>
    </service>
    <service id="foo.baz" class="%baz_class%" factory-method="getInstance">
      <configurator class="%baz_class%" method="configureStatic1"/>
    </service>
    <service id="foo_bar" class="%foo_class%" scope="prototype"/>
    <service id="method_call1" class="FooClass">
      <file>%path%foo.php</file>
      <call method="setBar">
        <argument type="service" id="foo"/>
      </call>
      <call method="setBar">
        <argument type="service" id="foo2" on-invalid="null"/>
      </call>
      <call method="setBar">
        <argument type="service" id="foo3" on-invalid="ignore"/>
      </call>
      <call method="setBar">
        <argument type="service" id="foobaz" on-invalid="ignore"/>
      </call>
      <call method="setBar">
        <argument type="expression">service("foo").foo() ~ parameter("foo")</argument>
      </call>
    </service>
    <service id="factory_service" class="Bar" factory-method="getInstance" factory-service="foo.baz"/>
    <service id="foo_with_inline" class="Foo">
      <call method="setBar">
        <argument type="service" id="inlined"/>
      </call>
    </service>
    <service id="inlined" class="Bar" public="false">
      <property name="pub">pub</property>
      <call method="setBaz">
        <argument type="service" id="baz"/>
      </call>
    </service>
    <service id="baz" class="Baz">
      <call method="setFoo">
        <argument type="service" id="foo_with_inline"/>
      </call>
    </service>
    <service id="request" class="Request" synthetic="true" synchronized="true"/>
    <service id="depends_on_request" class="stdClass">
      <call method="setRequest">
        <argument type="service" id="request" on-invalid="null" strict="false"/>
      </call>
    </service>
    <service id="alias_for_foo" alias="foo"/>
    <service id="alias_for_alias" alias="foo"/>
  </services>
</container>
PK��Z�^����jtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services1.xmlnu�[���<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:project="http://www.example.com/schema/project">

    <parameters>
        <parameter key="project.parameter.foo">BAR</parameter>
    </parameters>

    <services>
        <service id="project.service.foo" class="BAR" />
    </services>

    <project:bar babar="babar">
        <another />
        <another2>%project.parameter.foo%</another2>
    </project:bar>

</container>
PK��Z����jtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services5.xmlnu�[���<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:project="http://www.example.com/schema/projectwithxsd"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
                        http://www.example.com/schema/projectwithxsd http://www.example.com/schema/projectwithxsd/project-1.0.xsd">

    <project:foobar />

</container>
PK��Zҗ'y��jtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services4.xmlnu�[���<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:project="http://www.example.com/schema/not_registered_extension">
  <project:bar />
</container>
PK��Z��	jtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services7.xmlnu�[���<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:project="http://www.example.com/schema/projectwithxsdinphar"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
                        http://www.example.com/schema/projectwithxsdinphar http://www.example.com/schema/projectwithxsdinphar/project-1.0.xsd">

    <project:bar bar="foo" />

</container>
PK��Zix�C��jtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services6.xmlnu�[���<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:project="http://www.example.com/schema/projectwithxsdinphar"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
                        http://www.example.com/schema/projectwithxsdinphar http://www.example.com/schema/projectwithxsdinphar/project-1.0.xsd">

    <project:bar />

</container>
PK��Z>U���jtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services3.xmlnu�[���<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:project="http://www.example.com/schema/projectwithxsd"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
                        http://www.example.com/schema/projectwithxsd http://www.example.com/schema/projectwithxsd/project-1.0.xsd">

    <parameters>
        <parameter key="project.parameter.foo">BAR</parameter>
    </parameters>

    <services>
        <service id="project.service.foo" class="BAR" />
    </services>

    <project:bar bar="bar" />

</container>
PK��Z�}��jtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services2.xmlnu�[���<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:project="http://www.example.com/schema/projectwithxsd"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
                        http://www.example.com/schema/projectwithxsd http://www.example.com/schema/projectwithxsd/project-1.0.xsd">

    <parameters>
        <parameter key="project.parameter.foo">BAR</parameter>
    </parameters>

    <services>
        <service id="project.service.foo" class="BAR" />
    </services>

    <project:bar />

</container>
PK��Z��33etest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services10.dotnu�[���digraph sc {
  ratio="compress"
  node [fontsize="11" fontname="Arial" shape="record"];
  edge [fontsize="9" fontname="Arial" color="grey" arrowhead="open" arrowsize="0.5"];

  node_foo [label="foo\nFooClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
  node_service_container [label="service_container\nSymfony\\Component\\DependencyInjection\\ContainerBuilder\n", shape=record, fillcolor="#9999ff", style="filled"];
  node_bar [label="bar\n\n", shape=record, fillcolor="#ff9999", style="filled"];
  node_foo -> node_bar [label="" style="filled"];
}
PK��Zh	�	�	dtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dotnu�[���digraph sc {
  ratio="compress"
  node [fontsize="11" fontname="Arial" shape="record"];
  edge [fontsize="9" fontname="Arial" color="grey" arrowhead="open" arrowsize="0.5"];

  node_foo [label="foo (alias_for_foo)\nFooClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
  node_bar [label="bar\nFooClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
  node_foo_baz [label="foo.baz\nBazClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
  node_foo_bar [label="foo_bar\nFooClass\n", shape=record, fillcolor="#eeeeee", style="dotted"];
  node_method_call1 [label="method_call1\nFooClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
  node_factory_service [label="factory_service\nBar\n", shape=record, fillcolor="#eeeeee", style="filled"];
  node_foo_with_inline [label="foo_with_inline\nFoo\n", shape=record, fillcolor="#eeeeee", style="filled"];
  node_inlined [label="inlined\nBar\n", shape=record, fillcolor="#eeeeee", style="filled"];
  node_baz [label="baz\nBaz\n", shape=record, fillcolor="#eeeeee", style="filled"];
  node_request [label="request\nRequest\n", shape=record, fillcolor="#eeeeee", style="filled"];
  node_depends_on_request [label="depends_on_request\nstdClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
  node_service_container [label="service_container\nSymfony\\Component\\DependencyInjection\\ContainerBuilder\n", shape=record, fillcolor="#9999ff", style="filled"];
  node_foo2 [label="foo2\n\n", shape=record, fillcolor="#ff9999", style="filled"];
  node_foo3 [label="foo3\n\n", shape=record, fillcolor="#ff9999", style="filled"];
  node_foobaz [label="foobaz\n\n", shape=record, fillcolor="#ff9999", style="filled"];
  node_foo -> node_foo_baz [label="" style="filled"];
  node_foo -> node_service_container [label="" style="filled"];
  node_foo -> node_foo_baz [label="" style="dashed"];
  node_foo -> node_bar [label="setBar()" style="dashed"];
  node_bar -> node_foo_baz [label="" style="filled"];
  node_method_call1 -> node_foo [label="setBar()" style="dashed"];
  node_method_call1 -> node_foo2 [label="setBar()" style="dashed"];
  node_method_call1 -> node_foo3 [label="setBar()" style="dashed"];
  node_method_call1 -> node_foobaz [label="setBar()" style="dashed"];
  node_foo_with_inline -> node_inlined [label="setBar()" style="dashed"];
  node_inlined -> node_baz [label="setBaz()" style="dashed"];
  node_baz -> node_foo_with_inline [label="setFoo()" style="dashed"];
  node_depends_on_request -> node_request [label="setRequest()" style="dashed"];
}
PK��ZՁ1*,,gtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services10-1.dotnu�[���digraph sc {
  ratio="normal"
  node [fontsize="13" fontname="Verdana" shape="square"];
  edge [fontsize="12" fontname="Verdana" color="white" arrowhead="closed" arrowsize="1"];

  node_foo [label="foo\nFooClass\n", shape=square, fillcolor="grey", style="filled"];
  node_service_container [label="service_container\nSymfony\\Component\\DependencyInjection\\ContainerBuilder\n", shape=square, fillcolor="green", style="empty"];
  node_bar [label="bar\n\n", shape=square, fillcolor="red", style="empty"];
  node_foo -> node_bar [label="" style="filled"];
}
PK��Z&�WWdtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services1.dotnu�[���digraph sc {
  ratio="compress"
  node [fontsize="11" fontname="Arial" shape="record"];
  edge [fontsize="9" fontname="Arial" color="grey" arrowhead="open" arrowsize="0.5"];

  node_service_container [label="service_container\nSymfony\\Component\\DependencyInjection\\ContainerBuilder\n", shape=record, fillcolor="#9999ff", style="filled"];
}
PK��ZŏD�;;etest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services13.dotnu�[���digraph sc {
  ratio="compress"
  node [fontsize="11" fontname="Arial" shape="record"];
  edge [fontsize="9" fontname="Arial" color="grey" arrowhead="open" arrowsize="0.5"];

  node_foo [label="foo\nFooClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
  node_bar [label="bar\nBarClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
  node_service_container [label="service_container\nSymfony\\Component\\DependencyInjection\\ContainerBuilder\n", shape=record, fillcolor="#9999ff", style="filled"];
  node_foo -> node_bar [label="" style="filled"];
}
PK��Z��8BBetest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services14.dotnu�[���digraph sc {
  ratio="compress"
  node [fontsize="11" fontname="Arial" shape="record"];
  edge [fontsize="9" fontname="Arial" color="grey" arrowhead="open" arrowsize="0.5"];

  node_service_container [label="service_container\nContainer14\\ProjectServiceContainer\n", shape=record, fillcolor="#9999ff", style="filled"];
}
PK��Z�N�{rrytest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectWithXsdExtensionInPhar.pharnu�[���<?php require_once "phar://ProjectWithXsdExtensionInPhar.phar/ProjectWithXsdExtensionInPhar.php"; __HALT_COMPILER(); ?>
�"ProjectWithXsdExtensionInPhar.phar!ProjectWithXsdExtensionInPhar.php~�akM~� ���schema/project-1.0.xsd��akM�Qp���<?php

class ProjectWithXsdExtensionInPhar extends ProjectExtension
{
    public function getXsdValidationBasePath()
    {
        return __DIR__.'/schema';
    }

    public function getNamespace()
    {
        return 'http://www.example.com/schema/projectwithxsdinphar';
    }

    public function getAlias()
    {
        return 'projectwithxsdinphar';
    }
}<?xml version="1.0" encoding="UTF-8" ?>

<xsd:schema xmlns="http://www.example.com/schema/projectwithxsdinphar"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://www.example.com/schema/projectwithxsdinphar"
    elementFormDefault="qualified">

  <xsd:element name="bar" type="bar" />

  <xsd:complexType name="bar">
    <xsd:attribute name="foo" type="xsd:string" />
  </xsd:complexType>
</xsd:schema>W��]ʯ�`�5,,)E��Y�GBMBPK��Z�
��^test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/foo.phpnu�[���<?php

class FooClass
{
    public $foo, $moo;

    public $bar = null, $initialized = false, $configured = false, $called = false, $arguments = array();

    public function __construct($arguments = array())
    {
        $this->arguments = $arguments;
    }

    public static function getInstance($arguments = array())
    {
        $obj = new self($arguments);
        $obj->called = true;

        return $obj;
    }

    public function initialize()
    {
        $this->initialized = true;
    }

    public function configure()
    {
        $this->configured = true;
    }

    public function setBar($value = null)
    {
        $this->bar = $value;
    }
}
PK��Z��]���etest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/createphar.phpnu�[���<?php

$file = __DIR__.'/ProjectWithXsdExtensionInPhar.phar';
if (is_file($file)) {
    @unlink($file);
}

$phar = new Phar($file, 0, 'ProjectWithXsdExtensionInPhar.phar');
$phar->addFromString('ProjectWithXsdExtensionInPhar.php',<<<EOT
<?php

class ProjectWithXsdExtensionInPhar extends ProjectExtension
{
    public function getXsdValidationBasePath()
    {
        return __DIR__.'/schema';
    }

    public function getNamespace()
    {
        return 'http://www.example.com/schema/projectwithxsdinphar';
    }

    public function getAlias()
    {
        return 'projectwithxsdinphar';
    }
}
EOT
);
$phar->addFromString('schema/project-1.0.xsd', <<<EOT
<?xml version="1.0" encoding="UTF-8" ?>

<xsd:schema xmlns="http://www.example.com/schema/projectwithxsdinphar"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://www.example.com/schema/projectwithxsdinphar"
    elementFormDefault="qualified">

  <xsd:element name="bar" type="bar" />

  <xsd:complexType name="bar">
    <xsd:attribute name="foo" type="xsd:string" />
  </xsd:complexType>
</xsd:schema>
EOT
);
$phar->setStub('<?php require_once "phar://ProjectWithXsdExtensionInPhar.phar/ProjectWithXsdExtensionInPhar.php"; __HALT_COMPILER(); ?>');
PK��Z.Y<ҿ�ktest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectExtension.phpnu�[���<?php

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;

class ProjectExtension implements ExtensionInterface
{
    public function load(array $configs, ContainerBuilder $configuration)
    {
        $config = call_user_func_array('array_merge', $configs);

        $configuration->setDefinition('project.service.bar', new Definition('FooClass'));
        $configuration->setParameter('project.parameter.bar', isset($config['foo']) ? $config['foo'] : 'foobar');

        $configuration->setDefinition('project.service.foo', new Definition('FooClass'));
        $configuration->setParameter('project.parameter.foo', isset($config['foo']) ? $config['foo'] : 'foobar');

        return $configuration;
    }

    public function getXsdValidationBasePath()
    {
        return false;
    }

    public function getNamespace()
    {
        return 'http://www.example.com/schema/project';
    }

    public function getAlias()
    {
        return 'project';
    }

    public function getConfiguration(array $config, ContainerBuilder $container)
    {
        return null;
    }
}
PK��ZAov:ZZbtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.phpnu�[���<?php

function sc_configure($instance)
{
    $instance->configure();
}

class BarClass
{
    protected $baz;
    public $foo = 'foo';

    public function setBaz(BazClass $baz)
    {
        $this->baz = $baz;
    }

    public function getBaz()
    {
        return $this->baz;
    }
}

class BazClass
{
    protected $foo;

    public function setFoo(Foo $foo)
    {
        $this->foo = $foo;
    }

    public function configure($instance)
    {
        $instance->configure();
    }

    public static function getInstance()
    {
        return new self();
    }

    public static function configureStatic($instance)
    {
        $instance->configure();
    }

    public static function configureStatic1()
    {
    }
}

class BarUserClass
{
    public $bar;

    public function __construct(BarClass $bar)
    {
        $this->bar = $bar;
    }
}
PK��ZRK:��mtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/schema/project-1.0.xsdnu�[���<?xml version="1.0" encoding="UTF-8" ?>

<xsd:schema xmlns="http://www.example.com/schema/projectwithxsd"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://www.example.com/schema/projectwithxsd"
    elementFormDefault="qualified">

  <xsd:element name="bar" type="bar" />

  <xsd:complexType name="bar">
    <xsd:attribute name="foo" type="xsd:string" />
  </xsd:complexType>
</xsd:schema>
PK��Z��[[rtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectWithXsdExtension.phpnu�[���<?php

class ProjectWithXsdExtension extends ProjectExtension
{
    public function getXsdValidationBasePath()
    {
        return __DIR__.'/schema';
    }

    public function getNamespace()
    {
        return 'http://www.example.com/schema/projectwithxsd';
    }

    public function getAlias()
    {
        return 'projectwithxsd';
    }
}
PK��Z����`test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services8.ymlnu�[���parameters:
    foo: '%baz%'
    baz: bar
    bar: 'foo is %%foo bar'
    escape: '@@escapeme'
    values: [true, false, null, 0, 1000.3, 'true', 'false', 'null']

PK��Z�|��DD`test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services3.ymlnu�[���parameters:
    foo: foo
    values:
        - true
        - false
PK��Z6�e3��`test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services6.ymlnu�[���services:
    foo: { class: FooClass }
    baz: { class: BazClass }
    scope.container: { class: FooClass, scope: container }
    scope.custom: { class: FooClass, scope: custom }
    scope.prototype: { class: FooClass, scope: prototype }
    constructor: { class: FooClass, factory_method: getInstance }
    file: { class: FooClass, file: %path%/foo.php }
    arguments: { class: FooClass, arguments: [foo, @foo, [true, false]] }
    configurator1: { class: FooClass, configurator: sc_configure }
    configurator2: { class: FooClass, configurator: [@baz, configure] }
    configurator3: { class: FooClass, configurator: [BazClass, configureStatic] }
    method_call1:
        class: FooClass
        calls:
            - [ setBar, [] ]
            - [ setBar ]
            - [ setBar, ['@=service("foo").foo() ~ parameter("foo")'] ]
    method_call2:
        class: FooClass
        calls:
            - [ setBar, [ foo, @foo, [true, false] ] ]
    alias_for_foo: @foo
    another_alias_for_foo:
        alias: foo
        public: false
    factory_service: { class: BazClass, factory_method: getInstance, factory_service: baz_factory }
    request:
        class: Request
        synthetic: true
        synchronized: true
        lazy: true
PK��ZV�v�==`test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4.ymlnu�[���imports:
    - { resource: services2.yml }
    - { resource: services3.yml }
    - { resource: "../php/simple.php" }
    - { resource: "../ini/parameters.ini", class: Symfony\Component\DependencyInjection\Loader\IniFileLoader }
    - { resource: "../ini/parameters2.ini" }
    - { resource: "../xml/services13.xml" }
PK��Z#�&#`test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/nonvalid1.ymlnu�[���foo:
  bar
PK��Zy��??ktest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4_bad_import.ymlnu�[���imports:
    - { resource: foo_fake.yml, ignore_errors: true }
PK��Z�*_6��^test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag3.ymlnu�[���services:
    foo_service:
        class:    FooClass
        tags:
          # tag-attribute is not a scalar
          - { name: foo, bar: { foo: foo, bar: bar } }
PK��Zzb��nn^test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag1.ymlnu�[���services:
    foo_service:
        class:    FooClass
        # tags is not an array
        tags:     string
PK��Z����''`test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services7.ymlnu�[���services:
    foo: { class: BarClass }
PK��Z�%/���atest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services10.ymlnu�[���parameters:
    project.parameter.foo: BAR

services:
    project.service.foo:
        class: BAR

project:
    test: %project.parameter.foo%
PK��Z��2`test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services1.ymlnu�[���
PK��Z�MuAatest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services11.ymlnu�[���foobarfoobar: {}
PK��Z}�>���^test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag2.ymlnu�[���services:
    foo_service:
        class:    FooClass
        tags:
          # tag is missing the name key
          foo_tag:   { foo: bar }
PK��Z:�Ʋ��`test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services2.ymlnu�[���parameters:
    FOO: bar
    values:
        - true
        - false
        - 0
        - 1000.3
    bar: foo
    escape: @@escapeme
    foo_bar: @foo_bar
    MixedCase:
        MixedCaseKey: value
PK��ZW�%`test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/nonvalid2.ymlnu�[���false
PK��Z|�w���`test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.ymlnu�[���parameters:
    baz_class: BazClass
    foo_class: FooClass
    foo: bar

services:
    foo:
        class: FooClass
        tags:
            - { name: foo, foo: foo }
            - { name: foo, bar: bar }
        factory_class: FooClass
        factory_method: getInstance
        arguments: [foo, '@foo.baz', { '%foo%': 'foo is %foo%', foobar: '%foo%' }, true, '@service_container']
        properties: { foo: bar, moo: '@foo.baz', qux: { '%foo%': 'foo is %foo%', foobar: '%foo%' } }
        calls:
            - [setBar, ['@bar']]
            - [initialize, {  }]

        configurator: sc_configure
    bar:
        class: FooClass
        arguments: [foo, '@foo.baz', '%foo_bar%']
        configurator: ['@foo.baz', configure]
    foo.baz:
        class: %baz_class%
        factory_class: %baz_class%
        factory_method: getInstance
        configurator: ['%baz_class%', configureStatic1]
    foo_bar:
        class: %foo_class%
        scope: prototype
    method_call1:
        class: FooClass
        file: %path%foo.php
        calls:
            - [setBar, ['@foo']]
            - [setBar, ['@?foo2']]
            - [setBar, ['@?foo3']]
            - [setBar, ['@?foobaz']]
            - [setBar, ['@=service("foo").foo() ~ parameter("foo")']]

    factory_service:
        class: Bar
        factory_method: getInstance
        factory_service: foo.baz
    foo_with_inline:
        class: Foo
        calls:
            - [setBar, ['@inlined']]

    inlined:
        class: Bar
        public: false
        properties: { pub: pub }
        calls:
            - [setBaz, ['@baz']]

    baz:
        class: Baz
        calls:
            - [setFoo, ['@foo_with_inline']]

    request:
        class: Request
        synthetic: true
        synchronized: true
    depends_on_request:
        class: stdClass
        calls:
            - [setRequest, ['@?request']]

    alias_for_foo: @foo
    alias_for_alias: @foo
PK��Z����GGatest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services13.ymlnu�[���# used to test imports in XML
parameters:
    imported_from_yaml: true
PK��Z۴)�++^test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/nonvalid.ininu�[���{NOT AN INI FILE}
{JUST A PLAIN TEXT FILE}
PK��Zpu��((atest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters2.ininu�[���[parameters]
  imported_from_ini = true
PK��Zs4��''`test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters.ininu�[���[parameters]
  foo = bar
  bar = %foo%
PK��Z5l%%atest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters1.ininu�[���[parameters]
  FOO = foo
  baz = baz
PK��Z�Fm��htest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/interfaces2.phpnu�[���<?php

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;

$container = new ContainerBuilder();

$factoryDefinition = new Definition('BarClassFactory');
$container->setDefinition('barFactory', $factoryDefinition);

$definition = new Definition();
$definition->setFactoryService('barFactory');
$definition->setFactoryMethod('createBarClass');
$container->setDefinition('bar', $definition);

return $container;

class BarClass
{
    public $foo;

    public function setBar($foo)
    {
        $this->foo = $foo;
    }
}

class BarClassFactory
{
    public function createBarClass()
    {
        return new BarClass();
    }
}
PK��Z4h���gtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container8.phpnu�[���<?php

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;

$container = new ContainerBuilder(new ParameterBag(array(
    'FOO'    => '%baz%',
    'baz'    => 'bar',
    'bar'    => 'foo is %%foo bar',
    'escape' => '@escapeme',
    'values' => array(true, false, null, 0, 1000.3, 'true', 'false', 'null'),
)));

return $container;
PK��Z�	Z��gtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.phpnu�[���<?php

require_once __DIR__.'/../includes/classes.php';

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Parameter;
use Symfony\Component\ExpressionLanguage\Expression;

$container = new ContainerBuilder();
$container->
    register('foo', 'FooClass')->
    addTag('foo', array('foo' => 'foo'))->
    addTag('foo', array('bar' => 'bar'))->
    setFactoryClass('FooClass')->
    setFactoryMethod('getInstance')->
    setArguments(array('foo', new Reference('foo.baz'), array('%foo%' => 'foo is %foo%', 'foobar' => '%foo%'), true, new Reference('service_container')))->
    setProperties(array('foo' => 'bar', 'moo' => new Reference('foo.baz'), 'qux' => array('%foo%' => 'foo is %foo%', 'foobar' => '%foo%')))->
    addMethodCall('setBar', array(new Reference('bar')))->
    addMethodCall('initialize')->
    setConfigurator('sc_configure')
;
$container->
    register('bar', 'FooClass')->
    setArguments(array('foo', new Reference('foo.baz'), new Parameter('foo_bar')))->
    setScope('container')->
    setConfigurator(array(new Reference('foo.baz'), 'configure'))
;
$container->
    register('foo.baz', '%baz_class%')->
    setFactoryClass('%baz_class%')->
    setFactoryMethod('getInstance')->
    setConfigurator(array('%baz_class%', 'configureStatic1'))
;
$container->
    register('foo_bar', '%foo_class%')->
    setScope('prototype')
;
$container->getParameterBag()->clear();
$container->getParameterBag()->add(array(
    'baz_class' => 'BazClass',
    'foo_class' => 'FooClass',
    'foo' => 'bar',
));
$container->setAlias('alias_for_foo', 'foo');
$container->setAlias('alias_for_alias', 'alias_for_foo');
$container->
    register('method_call1', 'FooClass')->
    setFile(realpath(__DIR__.'/../includes/foo.php'))->
    addMethodCall('setBar', array(new Reference('foo')))->
    addMethodCall('setBar', array(new Reference('foo2', ContainerInterface::NULL_ON_INVALID_REFERENCE)))->
    addMethodCall('setBar', array(new Reference('foo3', ContainerInterface::IGNORE_ON_INVALID_REFERENCE)))->
    addMethodCall('setBar', array(new Reference('foobaz', ContainerInterface::IGNORE_ON_INVALID_REFERENCE)))->
    addMethodCall('setBar', array(new Expression('service("foo").foo() ~ parameter("foo")')))
;
$container->
    register('factory_service', 'Bar')->
    setFactoryService('foo.baz')->
    setFactoryMethod('getInstance')
;

$container
    ->register('foo_with_inline', 'Foo')
    ->addMethodCall('setBar', array(new Reference('inlined')))
;
$container
    ->register('inlined', 'Bar')
    ->setProperty('pub', 'pub')
    ->addMethodCall('setBaz', array(new Reference('baz')))
    ->setPublic(false)
;
$container
    ->register('baz', 'Baz')
    ->addMethodCall('setFoo', array(new Reference('foo_with_inline')))
;
$container
    ->register('request', 'Request')
    ->setSynthetic(true)
    ->setSynchronized(true)
;
$container
    ->register('depends_on_request', 'stdClass')
    ->addMethodCall('setRequest', array(new Reference('request', ContainerInterface::NULL_ON_INVALID_REFERENCE, false)))
;

return $container;
PK��Z���33htest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container11.phpnu�[���<?php

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;

$container = new ContainerBuilder();
$container->
    register('foo', 'FooClass')->
    addArgument(new Definition('BarClass', array(new Definition('BazClass'))))
;

return $container;
PK��Z��|htest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/interfaces1.phpnu�[���<?php

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;

$container = new ContainerBuilder();
$container->setParameter('cla', 'Fo');
$container->setParameter('ss', 'Class');

$definition = new Definition('%cla%o%ss%');
$container->setDefinition('foo', $definition);

return $container;

if (!class_exists('FooClass')) {
    class FooClass
    {
        public $bar;

        public function setBar($bar)
        {
            $this->bar = $bar;
        }
    }
}
PK��ZC�ݲ;;htest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container10.phpnu�[���<?php

require_once __DIR__.'/../includes/classes.php';

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

$container = new ContainerBuilder();
$container->
    register('foo', 'FooClass')->
    addArgument(new Reference('bar'))
;

return $container;
PK��ZBreOOhtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container13.phpnu�[���<?php

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

$container = new ContainerBuilder();
$container->
    register('foo', 'FooClass')->
    addArgument(new Reference('bar'))
;
$container->
    register('bar', 'BarClass')
;
$container->compile();

return $container;
PK��Z�*�EEhtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container12.phpnu�[���<?php

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;

$container = new ContainerBuilder();
$container->
    register('foo', 'FooClass\\Foo')->
    addArgument('foo<>&bar')->
    addTag('foo"bar\\bar', array('foo' => 'foo"barřž€'))
;

return $container;
PK��Z�1�v��htest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container14.phpnu�[���<?php

namespace Container14;

use Symfony\Component\DependencyInjection\ContainerBuilder;

class ProjectServiceContainer extends ContainerBuilder
{
}

return new ProjectServiceContainer();
PK��Z
�^��ltest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/ParameterBag/FrozenParameterBagTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\ParameterBag;

use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;

class FrozenParameterBagTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag::__construct
     */
    public function testConstructor()
    {
        $parameters = array(
            'foo' => 'foo',
            'bar' => 'bar',
        );
        $bag = new FrozenParameterBag($parameters);
        $this->assertEquals($parameters, $bag->all(), '__construct() takes an array of parameters as its first argument');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag::clear
     * @expectedException \LogicException
     */
    public function testClear()
    {
        $bag = new FrozenParameterBag(array());
        $bag->clear();
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag::set
     * @expectedException \LogicException
     */
    public function testSet()
    {
        $bag = new FrozenParameterBag(array());
        $bag->set('foo', 'bar');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag::add
     * @expectedException \LogicException
     */
    public function testAdd()
    {
        $bag = new FrozenParameterBag(array());
        $bag->add(array());
    }
}
PK��Z$����9�9ftest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/ParameterBag/ParameterBagTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\ParameterBag;

use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;

class ParameterBagTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::__construct
     */
    public function testConstructor()
    {
        $bag = new ParameterBag($parameters = array(
            'foo' => 'foo',
            'bar' => 'bar',
        ));
        $this->assertEquals($parameters, $bag->all(), '__construct() takes an array of parameters as its first argument');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::clear
     */
    public function testClear()
    {
        $bag = new ParameterBag($parameters = array(
            'foo' => 'foo',
            'bar' => 'bar',
        ));
        $bag->clear();
        $this->assertEquals(array(), $bag->all(), '->clear() removes all parameters');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::remove
     */
    public function testRemove()
    {
        $bag = new ParameterBag(array(
            'foo' => 'foo',
            'bar' => 'bar',
        ));
        $bag->remove('foo');
        $this->assertEquals(array('bar' => 'bar'), $bag->all(), '->remove() removes a parameter');
        $bag->remove('BAR');
        $this->assertEquals(array(), $bag->all(), '->remove() converts key to lowercase before removing');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::get
     * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::set
     */
    public function testGetSet()
    {
        $bag = new ParameterBag(array('foo' => 'bar'));
        $bag->set('bar', 'foo');
        $this->assertEquals('foo', $bag->get('bar'), '->set() sets the value of a new parameter');

        $bag->set('foo', 'baz');
        $this->assertEquals('baz', $bag->get('foo'), '->set() overrides previously set parameter');

        $bag->set('Foo', 'baz1');
        $this->assertEquals('baz1', $bag->get('foo'), '->set() converts the key to lowercase');
        $this->assertEquals('baz1', $bag->get('FOO'), '->get() converts the key to lowercase');

        try {
            $bag->get('baba');
            $this->fail('->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException', $e, '->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist');
            $this->assertEquals('You have requested a non-existent parameter "baba".', $e->getMessage(), '->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist');
        }
    }

    public function testGetThrowParameterNotFoundException()
    {
        $bag = new ParameterBag(array(
            'foo' => 'foo',
            'bar' => 'bar',
            'baz' => 'baz',
        ));

        try {
            $bag->get('foo1');
            $this->fail('->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException', $e, '->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist');
            $this->assertEquals('You have requested a non-existent parameter "foo1". Did you mean this: "foo"?', $e->getMessage(), '->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException with some advices');
        }

        try {
            $bag->get('bag');
            $this->fail('->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException', $e, '->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist');
            $this->assertEquals('You have requested a non-existent parameter "bag". Did you mean one of these: "bar", "baz"?', $e->getMessage(), '->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException with some advices');
        }

        try {
            $bag->get('');
            $this->fail('->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException', $e, '->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist');
            $this->assertEquals('You have requested a non-existent parameter "".', $e->getMessage(), '->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException with some advices');
        }
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::has
     */
    public function testHas()
    {
        $bag = new ParameterBag(array('foo' => 'bar'));
        $this->assertTrue($bag->has('foo'), '->has() returns true if a parameter is defined');
        $this->assertTrue($bag->has('Foo'), '->has() converts the key to lowercase');
        $this->assertFalse($bag->has('bar'), '->has() returns false if a parameter is not defined');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::resolveValue
     */
    public function testResolveValue()
    {
        $bag = new ParameterBag(array());
        $this->assertEquals('foo', $bag->resolveValue('foo'), '->resolveValue() returns its argument unmodified if no placeholders are found');

        $bag = new ParameterBag(array('foo' => 'bar'));
        $this->assertEquals('I\'m a bar', $bag->resolveValue('I\'m a %foo%'), '->resolveValue() replaces placeholders by their values');
        $this->assertEquals(array('bar' => 'bar'), $bag->resolveValue(array('%foo%' => '%foo%')), '->resolveValue() replaces placeholders in keys and values of arrays');
        $this->assertEquals(array('bar' => array('bar' => array('bar' => 'bar'))), $bag->resolveValue(array('%foo%' => array('%foo%' => array('%foo%' => '%foo%')))), '->resolveValue() replaces placeholders in nested arrays');
        $this->assertEquals('I\'m a %%foo%%', $bag->resolveValue('I\'m a %%foo%%'), '->resolveValue() supports % escaping by doubling it');
        $this->assertEquals('I\'m a bar %%foo bar', $bag->resolveValue('I\'m a %foo% %%foo %foo%'), '->resolveValue() supports % escaping by doubling it');
        $this->assertEquals(array('foo' => array('bar' => array('ding' => 'I\'m a bar %%foo %%bar'))), $bag->resolveValue(array('foo' => array('bar' => array('ding' => 'I\'m a bar %%foo %%bar')))), '->resolveValue() supports % escaping by doubling it');

        $bag = new ParameterBag(array('foo' => true));
        $this->assertTrue($bag->resolveValue('%foo%'), '->resolveValue() replaces arguments that are just a placeholder by their value without casting them to strings');
        $bag = new ParameterBag(array('foo' => null));
        $this->assertNull($bag->resolveValue('%foo%'), '->resolveValue() replaces arguments that are just a placeholder by their value without casting them to strings');

        $bag = new ParameterBag(array('foo' => 'bar', 'baz' => '%%%foo% %foo%%% %%foo%% %%%foo%%%'));
        $this->assertEquals('%%bar bar%% %%foo%% %%bar%%', $bag->resolveValue('%baz%'), '->resolveValue() replaces params placed besides escaped %');

        $bag = new ParameterBag(array('baz' => '%%s?%%s'));
        $this->assertEquals('%%s?%%s', $bag->resolveValue('%baz%'), '->resolveValue() is not replacing greedily');

        $bag = new ParameterBag(array());
        try {
            $bag->resolveValue('%foobar%');
            $this->fail('->resolveValue() throws an InvalidArgumentException if a placeholder references a non-existent parameter');
        } catch (ParameterNotFoundException $e) {
            $this->assertEquals('You have requested a non-existent parameter "foobar".', $e->getMessage(), '->resolveValue() throws a ParameterNotFoundException if a placeholder references a non-existent parameter');
        }

        try {
            $bag->resolveValue('foo %foobar% bar');
            $this->fail('->resolveValue() throws a ParameterNotFoundException if a placeholder references a non-existent parameter');
        } catch (ParameterNotFoundException $e) {
            $this->assertEquals('You have requested a non-existent parameter "foobar".', $e->getMessage(), '->resolveValue() throws a ParameterNotFoundException if a placeholder references a non-existent parameter');
        }

        $bag = new ParameterBag(array('foo' => 'a %bar%', 'bar' => array()));
        try {
            $bag->resolveValue('%foo%');
            $this->fail('->resolveValue() throws a RuntimeException when a parameter embeds another non-string parameter');
        } catch (RuntimeException $e) {
            $this->assertEquals('A string value must be composed of strings and/or numbers, but found parameter "bar" of type array inside string value "a %bar%".', $e->getMessage(), '->resolveValue() throws a RuntimeException when a parameter embeds another non-string parameter');
        }

        $bag = new ParameterBag(array('foo' => '%bar%', 'bar' => '%foobar%', 'foobar' => '%foo%'));
        try {
            $bag->resolveValue('%foo%');
            $this->fail('->resolveValue() throws a ParameterCircularReferenceException when a parameter has a circular reference');
        } catch (ParameterCircularReferenceException $e) {
            $this->assertEquals('Circular reference detected for parameter "foo" ("foo" > "bar" > "foobar" > "foo").', $e->getMessage(), '->resolveValue() throws a ParameterCircularReferenceException when a parameter has a circular reference');
        }

        $bag = new ParameterBag(array('foo' => 'a %bar%', 'bar' => 'a %foobar%', 'foobar' => 'a %foo%'));
        try {
            $bag->resolveValue('%foo%');
            $this->fail('->resolveValue() throws a ParameterCircularReferenceException when a parameter has a circular reference');
        } catch (ParameterCircularReferenceException $e) {
            $this->assertEquals('Circular reference detected for parameter "foo" ("foo" > "bar" > "foobar" > "foo").', $e->getMessage(), '->resolveValue() throws a ParameterCircularReferenceException when a parameter has a circular reference');
        }

        $bag = new ParameterBag(array('host' => 'foo.bar', 'port' => 1337));
        $this->assertEquals('foo.bar:1337', $bag->resolveValue('%host%:%port%'));
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::resolve
     */
    public function testResolveIndicatesWhyAParameterIsNeeded()
    {
        $bag = new ParameterBag(array('foo' => '%bar%'));

        try {
            $bag->resolve();
        } catch (ParameterNotFoundException $e) {
            $this->assertEquals('The parameter "foo" has a dependency on a non-existent parameter "bar".', $e->getMessage());
        }

        $bag = new ParameterBag(array('foo' => '%bar%'));

        try {
            $bag->resolve();
        } catch (ParameterNotFoundException $e) {
            $this->assertEquals('The parameter "foo" has a dependency on a non-existent parameter "bar".', $e->getMessage());
        }
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::resolve
     */
    public function testResolveUnescapesValue()
    {
        $bag = new ParameterBag(array(
            'foo' => array('bar' => array('ding' => 'I\'m a bar %%foo %%bar')),
            'bar' => 'I\'m a %%foo%%',
        ));

        $bag->resolve();

        $this->assertEquals('I\'m a %foo%', $bag->get('bar'), '->resolveValue() supports % escaping by doubling it');
        $this->assertEquals(array('bar' => array('ding' => 'I\'m a bar %foo %bar')), $bag->get('foo'), '->resolveValue() supports % escaping by doubling it');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::escapeValue
     */
    public function testEscapeValue()
    {
        $bag = new ParameterBag();

        $bag->add(array(
            'foo' => $bag->escapeValue(array('bar' => array('ding' => 'I\'m a bar %foo %bar', 'zero' => null))),
            'bar' => $bag->escapeValue('I\'m a %foo%'),
        ));

        $this->assertEquals('I\'m a %%foo%%', $bag->get('bar'), '->escapeValue() escapes % by doubling it');
        $this->assertEquals(array('bar' => array('ding' => 'I\'m a bar %%foo %%bar', 'zero' => null)), $bag->get('foo'), '->escapeValue() escapes % by doubling it');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::resolve
     * @dataProvider stringsWithSpacesProvider
     */
    public function testResolveStringWithSpacesReturnsString($expected, $test, $description)
    {
        $bag = new ParameterBag(array('foo' => 'bar'));

        try {
            $this->assertEquals($expected, $bag->resolveString($test), $description);
        } catch (ParameterNotFoundException $e) {
            $this->fail(sprintf('%s - "%s"', $description, $expected));
        }
    }

    public function stringsWithSpacesProvider()
    {
        return array(
            array('bar', '%foo%', 'Parameters must be wrapped by %.'),
            array('% foo %', '% foo %', 'Parameters should not have spaces.'),
            array('{% set my_template = "foo" %}', '{% set my_template = "foo" %}', 'Twig-like strings are not parameters.'),
            array('50% is less than 100%', '50% is less than 100%', 'Text between % signs is allowed, if there are spaces.'),
        );
    }
}
PK��Z��
�
Wtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/CrossCheckTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;

class CrossCheckTest extends \PHPUnit_Framework_TestCase
{
    protected static $fixturesPath;

    public static function setUpBeforeClass()
    {
        self::$fixturesPath = __DIR__.'/Fixtures/';

        require_once self::$fixturesPath.'/includes/classes.php';
        require_once self::$fixturesPath.'/includes/foo.php';
    }

    /**
     * @dataProvider crossCheckLoadersDumpers
     */
    public function testCrossCheck($fixture, $type)
    {
        $loaderClass = 'Symfony\\Component\\DependencyInjection\\Loader\\'.ucfirst($type).'FileLoader';
        $dumperClass = 'Symfony\\Component\\DependencyInjection\\Dumper\\'.ucfirst($type).'Dumper';

        $tmp = tempnam('sf_service_container', 'sf');

        file_put_contents($tmp, file_get_contents(self::$fixturesPath.'/'.$type.'/'.$fixture));

        $container1 = new ContainerBuilder();
        $loader1 = new $loaderClass($container1, new FileLocator());
        $loader1->load($tmp);

        $dumper = new $dumperClass($container1);
        file_put_contents($tmp, $dumper->dump());

        $container2 = new ContainerBuilder();
        $loader2 = new $loaderClass($container2, new FileLocator());
        $loader2->load($tmp);

        unlink($tmp);

        $this->assertEquals($container2->getAliases(), $container1->getAliases(), 'loading a dump from a previously loaded container returns the same container');
        $this->assertEquals($container2->getDefinitions(), $container1->getDefinitions(), 'loading a dump from a previously loaded container returns the same container');
        $this->assertEquals($container2->getParameterBag()->all(), $container1->getParameterBag()->all(), '->getParameterBag() returns the same value for both containers');

        $this->assertEquals(serialize($container2), serialize($container1), 'loading a dump from a previously loaded container returns the same container');

        $services1 = array();
        foreach ($container1 as $id => $service) {
            $services1[$id] = serialize($service);
        }
        $services2 = array();
        foreach ($container2 as $id => $service) {
            $services2[$id] = serialize($service);
        }

        unset($services1['service_container'], $services2['service_container']);

        $this->assertEquals($services2, $services1, 'Iterator on the containers returns the same services');
    }

    public function crossCheckLoadersDumpers()
    {
        $tests = array(
            array('services1.xml', 'xml'),
            array('services2.xml', 'xml'),
            array('services6.xml', 'xml'),
            array('services8.xml', 'xml'),
            array('services9.xml', 'xml'),
        );

        if (class_exists('Symfony\Component\Yaml\Yaml')) {
            $tests = array_merge($tests, array(
                array('services1.yml', 'yaml'),
                array('services2.yml', 'yaml'),
                array('services6.yml', 'yaml'),
                array('services8.yml', 'yaml'),
                array('services9.yml', 'yaml'),
            ));
        }

        return $tests;
    }
}
PK��Z2+`��	�	^test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Dumper;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Dumper\YamlDumper;

class YamlDumperTest extends \PHPUnit_Framework_TestCase
{
    protected static $fixturesPath;

    public static function setUpBeforeClass()
    {
        self::$fixturesPath = realpath(__DIR__.'/../Fixtures/');
    }

    public function testDump()
    {
        $dumper = new YamlDumper($container = new ContainerBuilder());

        $this->assertStringEqualsFile(self::$fixturesPath.'/yaml/services1.yml', $dumper->dump(), '->dump() dumps an empty container as an empty YAML file');

        $container = new ContainerBuilder();
        $dumper = new YamlDumper($container);
    }

    public function testAddParameters()
    {
        $container = include self::$fixturesPath.'/containers/container8.php';
        $dumper = new YamlDumper($container);
        $this->assertStringEqualsFile(self::$fixturesPath.'/yaml/services8.yml', $dumper->dump(), '->dump() dumps parameters');
    }

    public function testAddService()
    {
        $container = include self::$fixturesPath.'/containers/container9.php';
        $dumper = new YamlDumper($container);
        $this->assertEquals(str_replace('%path%', self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR, file_get_contents(self::$fixturesPath.'/yaml/services9.yml')), $dumper->dump(), '->dump() dumps services');

        $dumper = new YamlDumper($container = new ContainerBuilder());
        $container->register('foo', 'FooClass')->addArgument(new \stdClass());
        try {
            $dumper->dump();
            $this->fail('->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\RuntimeException', $e, '->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources');
            $this->assertEquals('Unable to dump a service container if a parameter is an object or a resource.', $e->getMessage(), '->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources');
        }
    }
}
PK��Zv��btest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Dumper/GraphvizDumperTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Dumper;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Dumper\GraphvizDumper;

class GraphvizDumperTest extends \PHPUnit_Framework_TestCase
{
    protected static $fixturesPath;

    public static function setUpBeforeClass()
    {
        self::$fixturesPath = __DIR__.'/../Fixtures/';
    }

    public function testDump()
    {
        $dumper = new GraphvizDumper($container = new ContainerBuilder());

        $this->assertStringEqualsFile(self::$fixturesPath.'/graphviz/services1.dot', $dumper->dump(), '->dump() dumps an empty container as an empty dot file');

        $container = include self::$fixturesPath.'/containers/container9.php';
        $dumper = new GraphvizDumper($container);
        $this->assertEquals(str_replace('%path%', __DIR__, file_get_contents(self::$fixturesPath.'/graphviz/services9.dot')), $dumper->dump(), '->dump() dumps services');

        $container = include self::$fixturesPath.'/containers/container10.php';
        $dumper = new GraphvizDumper($container);
        $this->assertEquals(str_replace('%path%', __DIR__, file_get_contents(self::$fixturesPath.'/graphviz/services10.dot')), $dumper->dump(), '->dump() dumps services');

        $container = include self::$fixturesPath.'/containers/container10.php';
        $dumper = new GraphvizDumper($container);
        $this->assertEquals($dumper->dump(array(
            'graph' => array('ratio' => 'normal'),
            'node'  => array('fontsize' => 13, 'fontname' => 'Verdana', 'shape' => 'square'),
            'edge'  => array('fontsize' => 12, 'fontname' => 'Verdana', 'color' => 'white', 'arrowhead' => 'closed', 'arrowsize' => 1),
            'node.instance' => array('fillcolor' => 'green', 'style' => 'empty'),
            'node.definition' => array('fillcolor' => 'grey'),
            'node.missing' => array('fillcolor' => 'red', 'style' => 'empty'),
        )), str_replace('%path%', __DIR__, file_get_contents(self::$fixturesPath.'/graphviz/services10-1.dot')), '->dump() dumps services');
    }

    public function testDumpWithFrozenContainer()
    {
        $container = include self::$fixturesPath.'/containers/container13.php';
        $dumper = new GraphvizDumper($container);
        $this->assertEquals(str_replace('%path%', __DIR__, file_get_contents(self::$fixturesPath.'/graphviz/services13.dot')), $dumper->dump(), '->dump() dumps services');
    }

    public function testDumpWithFrozenCustomClassContainer()
    {
        $container = include self::$fixturesPath.'/containers/container14.php';
        $dumper = new GraphvizDumper($container);
        $this->assertEquals(str_replace('%path%', __DIR__, file_get_contents(self::$fixturesPath.'/graphviz/services14.dot')), $dumper->dump(), '->dump() dumps services');
    }
}
PK��Z�)���]test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Dumper;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Dumper\XmlDumper;

class XmlDumperTest extends \PHPUnit_Framework_TestCase
{
    protected static $fixturesPath;

    public static function setUpBeforeClass()
    {
        self::$fixturesPath = realpath(__DIR__.'/../Fixtures/');
    }

    public function testDump()
    {
        $dumper = new XmlDumper($container = new ContainerBuilder());

        $this->assertXmlStringEqualsXmlFile(self::$fixturesPath.'/xml/services1.xml', $dumper->dump(), '->dump() dumps an empty container as an empty XML file');

        $container = new ContainerBuilder();
        $dumper = new XmlDumper($container);
    }

    public function testExportParameters()
    {
        $container = include self::$fixturesPath.'//containers/container8.php';
        $dumper = new XmlDumper($container);
        $this->assertXmlStringEqualsXmlFile(self::$fixturesPath.'/xml/services8.xml', $dumper->dump(), '->dump() dumps parameters');
    }

    public function testAddParameters()
    {
        $container = include self::$fixturesPath.'//containers/container8.php';
        $dumper = new XmlDumper($container);
        $this->assertXmlStringEqualsXmlFile(self::$fixturesPath.'/xml/services8.xml', $dumper->dump(), '->dump() dumps parameters');
    }

    public function testAddService()
    {
        $container = include self::$fixturesPath.'/containers/container9.php';
        $dumper = new XmlDumper($container);
        $this->assertEquals(str_replace('%path%', self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR, file_get_contents(self::$fixturesPath.'/xml/services9.xml')), $dumper->dump(), '->dump() dumps services');

        $dumper = new XmlDumper($container = new ContainerBuilder());
        $container->register('foo', 'FooClass')->addArgument(new \stdClass());
        try {
            $dumper->dump();
            $this->fail('->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\RuntimeException', $e, '->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources');
            $this->assertEquals('Unable to dump a service container if a parameter is an object or a resource.', $e->getMessage(), '->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources');
        }
    }

    public function testDumpAnonymousServices()
    {
        include self::$fixturesPath.'/containers/container11.php';
        $dumper = new XmlDumper($container);
        $this->assertEquals("<?xml version=\"1.0\" encoding=\"utf-8\"?>
<container xmlns=\"http://symfony.com/schema/dic/services\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd\">
  <services>
    <service id=\"foo\" class=\"FooClass\">
      <argument type=\"service\">
        <service class=\"BarClass\">
          <argument type=\"service\">
            <service class=\"BazClass\"/>
          </argument>
        </service>
      </argument>
    </service>
  </services>
</container>
", $dumper->dump());
    }

    public function testDumpEntities()
    {
        include self::$fixturesPath.'/containers/container12.php';
        $dumper = new XmlDumper($container);
        $this->assertEquals("<?xml version=\"1.0\" encoding=\"utf-8\"?>
<container xmlns=\"http://symfony.com/schema/dic/services\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd\">
  <services>
    <service id=\"foo\" class=\"FooClass\Foo\">
      <tag name=\"foo&quot;bar\bar\" foo=\"foo&quot;barřž€\"/>
      <argument>foo&lt;&gt;&amp;bar</argument>
    </service>
  </services>
</container>
", $dumper->dump());
    }
}
PK��Z�"��."."]test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Dumper;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Definition;

class PhpDumperTest extends \PHPUnit_Framework_TestCase
{
    protected static $fixturesPath;

    public static function setUpBeforeClass()
    {
        self::$fixturesPath = realpath(__DIR__.'/../Fixtures/');
    }

    public function testDump()
    {
        $dumper = new PhpDumper($container = new ContainerBuilder());

        $this->assertStringEqualsFile(self::$fixturesPath.'/php/services1.php', $dumper->dump(), '->dump() dumps an empty container as an empty PHP class');
        $this->assertStringEqualsFile(self::$fixturesPath.'/php/services1-1.php', $dumper->dump(array('class' => 'Container', 'base_class' => 'AbstractContainer', 'namespace' => 'Symfony\Component\DependencyInjection\Dump')), '->dump() takes a class and a base_class options');

        $container = new ContainerBuilder();
        new PhpDumper($container);
    }

    public function testDumpFrozenContainerWithNoParameter()
    {
        $container = new ContainerBuilder();
        $container->setResourceTracking(false);
        $container->register('foo', 'stdClass');

        $container->compile();

        $dumper = new PhpDumper($container);

        $dumpedString = $dumper->dump();
        $this->assertStringEqualsFile(self::$fixturesPath.'/php/services11.php', $dumpedString, '->dump() does not add getDefaultParameters() method call if container have no parameters.');
        $this->assertNotRegexp("/function getDefaultParameters\(/", $dumpedString, '->dump() does not add getDefaultParameters() method definition.');
    }

    public function testDumpOptimizationString()
    {
        $definition = new Definition();
        $definition->setClass('stdClass');
        $definition->addArgument(array(
            'only dot' => '.',
            'concatenation as value' => '.\'\'.',
            'concatenation from the start value' => '\'\'.',
            '.' => 'dot as a key',
            '.\'\'.' => 'concatenation as a key',
            '\'\'.' =>'concatenation from the start key',
            'optimize concatenation' => "string1%some_string%string2",
            'optimize concatenation with empty string' => "string1%empty_value%string2",
            'optimize concatenation from the start' => '%empty_value%start',
            'optimize concatenation at the end' => 'end%empty_value%',
        ));

        $container = new ContainerBuilder();
        $container->setResourceTracking(false);
        $container->setDefinition('test', $definition);
        $container->setParameter('empty_value', '');
        $container->setParameter('some_string', '-');
        $container->compile();

        $dumper = new PhpDumper($container);
        $this->assertStringEqualsFile(self::$fixturesPath.'/php/services10.php', $dumper->dump(), '->dump() dumps an empty container as an empty PHP class');
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testExportParameters()
    {
        $dumper = new PhpDumper(new ContainerBuilder(new ParameterBag(array('foo' => new Reference('foo')))));
        $dumper->dump();
    }

    public function testAddParameters()
    {
        $container = include self::$fixturesPath.'/containers/container8.php';
        $dumper = new PhpDumper($container);
        $this->assertStringEqualsFile(self::$fixturesPath.'/php/services8.php', $dumper->dump(), '->dump() dumps parameters');
    }

    public function testAddService()
    {
        // without compilation
        $container = include self::$fixturesPath.'/containers/container9.php';
        $dumper = new PhpDumper($container);
        $this->assertEquals(str_replace('%path%', str_replace('\\','\\\\',self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR), file_get_contents(self::$fixturesPath.'/php/services9.php')), $dumper->dump(), '->dump() dumps services');

        // with compilation
        $container = include self::$fixturesPath.'/containers/container9.php';
        $container->compile();
        $dumper = new PhpDumper($container);
        $this->assertEquals(str_replace('%path%', str_replace('\\','\\\\',self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR), file_get_contents(self::$fixturesPath.'/php/services9_compiled.php')), $dumper->dump(), '->dump() dumps services');

        $dumper = new PhpDumper($container = new ContainerBuilder());
        $container->register('foo', 'FooClass')->addArgument(new \stdClass());
        try {
            $dumper->dump();
            $this->fail('->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\Symfony\Component\DependencyInjection\Exception\RuntimeException', $e, '->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources');
            $this->assertEquals('Unable to dump a service container if a parameter is an object or a resource.', $e->getMessage(), '->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources');
        }
    }

    /**
     * @expectedException \InvalidArgumentException
     * @expectedExceptionMessage Service id "bar$" cannot be converted to a valid PHP method name.
     */
    public function testAddServiceInvalidServiceId()
    {
        $container = new ContainerBuilder();
        $container->register('bar$', 'FooClass');
        $dumper = new PhpDumper($container);
        $dumper->dump();
    }

    public function testAliases()
    {
        $container = include self::$fixturesPath.'/containers/container9.php';
        $container->compile();
        $dumper = new PhpDumper($container);
        eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Aliases')));

        $container = new \Symfony_DI_PhpDumper_Test_Aliases();
        $container->set('foo', $foo = new \stdClass);
        $this->assertSame($foo, $container->get('foo'));
        $this->assertSame($foo, $container->get('alias_for_foo'));
        $this->assertSame($foo, $container->get('alias_for_alias'));
    }

    public function testFrozenContainerWithoutAliases()
    {
        $container = new ContainerBuilder();
        $container->compile();

        $dumper = new PhpDumper($container);
        eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Frozen_No_Aliases')));

        $container = new \Symfony_DI_PhpDumper_Test_Frozen_No_Aliases();
        $this->assertFalse($container->has('foo'));
    }

    public function testOverrideServiceWhenUsingADumpedContainer()
    {
        require_once self::$fixturesPath.'/php/services9.php';
        require_once self::$fixturesPath.'/includes/foo.php';

        $container = new \ProjectServiceContainer();
        $container->set('bar', $bar = new \stdClass());
        $container->setParameter('foo_bar', 'foo_bar');

        $this->assertEquals($bar, $container->get('bar'), '->set() overrides an already defined service');
    }

    public function testOverrideServiceWhenUsingADumpedContainerAndServiceIsUsedFromAnotherOne()
    {
        require_once self::$fixturesPath.'/php/services9.php';
        require_once self::$fixturesPath.'/includes/foo.php';
        require_once self::$fixturesPath.'/includes/classes.php';

        $container = new \ProjectServiceContainer();
        $container->set('bar', $bar = new \stdClass());

        $this->assertSame($bar, $container->get('foo')->bar, '->set() overrides an already defined service');
    }

    /**
     * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException
     */
    public function testCircularReference()
    {
        $container = new ContainerBuilder();
        $container->register('foo', 'stdClass')->addArgument(new Reference('bar'));
        $container->register('bar', 'stdClass')->setPublic(false)->addMethodCall('setA', array(new Reference('baz')));
        $container->register('baz', 'stdClass')->addMethodCall('setA', array(new Reference('foo')));
        $container->compile();

        $dumper = new PhpDumper($container);
        $dumper->dump();
    }
}
PK��Z����Vtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/ReferenceTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests;

use Symfony\Component\DependencyInjection\Reference;

class ReferenceTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Symfony\Component\DependencyInjection\Reference::__construct
     */
    public function testConstructor()
    {
        $ref = new Reference('foo');
        $this->assertEquals('foo', (string) $ref, '__construct() sets the id of the reference, which is used for the __toString() method');
    }

    public function testCaseInsensitive()
    {
        $ref = new Reference('FooBar');
        $this->assertEquals('foobar', (string) $ref, 'the id is lowercased as the container is case insensitive');
    }
}
PK��Zł``atest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Loader/ClosureLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Loader;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\ClosureLoader;

class ClosureLoaderTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Symfony\Component\DependencyInjection\Loader\ClosureLoader::supports
     */
    public function testSupports()
    {
        $loader = new ClosureLoader(new ContainerBuilder());

        $this->assertTrue($loader->supports(function ($container) {}), '->supports() returns true if the resource is loadable');
        $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Loader\ClosureLoader::load
     */
    public function testLoad()
    {
        $loader = new ClosureLoader($container = new ContainerBuilder());

        $loader->load(function ($container) {
            $container->setParameter('foo', 'foo');
        });

        $this->assertEquals('foo', $container->getParameter('foo'), '->load() loads a \Closure resource');
    }
}
PK��ZSR���atest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Loader;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\Loader\Loader;
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
use Symfony\Component\Config\FileLocator;

class PhpFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Symfony\Component\DependencyInjection\Loader\PhpFileLoader::supports
     */
    public function testSupports()
    {
        $loader = new PhpFileLoader(new ContainerBuilder(), new FileLocator());

        $this->assertTrue($loader->supports('foo.php'), '->supports() returns true if the resource is loadable');
        $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Loader\PhpFileLoader::load
     */
    public function testLoad()
    {
        $loader = new PhpFileLoader($container = new ContainerBuilder(), new FileLocator());

        $loader->load(__DIR__.'/../Fixtures/php/simple.php');

        $this->assertEquals('foo', $container->getParameter('foo'), '->load() loads a PHP file resource');
    }
}
PK��Z�kV�0�0btest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Loader;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\Config\Loader\Loader;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
use Symfony\Component\Config\Loader\LoaderResolver;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\ExpressionLanguage\Expression;

class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    protected static $fixturesPath;

    public static function setUpBeforeClass()
    {
        self::$fixturesPath = realpath(__DIR__.'/../Fixtures/');
        require_once self::$fixturesPath.'/includes/foo.php';
        require_once self::$fixturesPath.'/includes/ProjectExtension.php';
    }

    public function testLoadFile()
    {
        $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/ini'));
        $r = new \ReflectionObject($loader);
        $m = $r->getMethod('loadFile');
        $m->setAccessible(true);

        try {
            $m->invoke($loader, 'foo.yml');
            $this->fail('->load() throws an InvalidArgumentException if the loaded file does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the loaded file does not exist');
            $this->assertEquals('The service file "foo.yml" is not valid.', $e->getMessage(), '->load() throws an InvalidArgumentException if the loaded file does not exist');
        }

        try {
            $m->invoke($loader, 'parameters.ini');
            $this->fail('->load() throws an InvalidArgumentException if the loaded file is not a valid YAML file');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the loaded file is not a valid YAML file');
            $this->assertEquals('The service file "parameters.ini" is not valid.', $e->getMessage(), '->load() throws an InvalidArgumentException if the loaded file is not a valid YAML file');
        }

        $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));

        foreach (array('nonvalid1', 'nonvalid2') as $fixture) {
            try {
                $m->invoke($loader, $fixture.'.yml');
                $this->fail('->load() throws an InvalidArgumentException if the loaded file does not validate');
            } catch (\Exception $e) {
                $this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the loaded file does not validate');
                $this->assertStringMatchesFormat('The service file "nonvalid%d.yml" is not valid.', $e->getMessage(), '->load() throws an InvalidArgumentException if the loaded file does not validate');
            }
        }
    }

    public function testLoadParameters()
    {
        $container = new ContainerBuilder();
        $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
        $loader->load('services2.yml');
        $this->assertEquals(array('foo' => 'bar', 'mixedcase' => array('MixedCaseKey' => 'value'), 'values' => array(true, false, 0, 1000.3), 'bar' => 'foo', 'escape' => '@escapeme', 'foo_bar' => new Reference('foo_bar')), $container->getParameterBag()->all(), '->load() converts YAML keys to lowercase');
    }

    public function testLoadImports()
    {
        $container = new ContainerBuilder();
        $resolver = new LoaderResolver(array(
            new IniFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')),
            new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')),
            new PhpFileLoader($container, new FileLocator(self::$fixturesPath.'/php')),
            $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')),
        ));
        $loader->setResolver($resolver);
        $loader->load('services4.yml');

        $actual = $container->getParameterBag()->all();
        $expected = array('foo' => 'bar', 'values' => array(true, false), 'bar' => '%foo%', 'escape' => '@escapeme', 'foo_bar' => new Reference('foo_bar'), 'mixedcase' => array('MixedCaseKey' => 'value'), 'imported_from_ini' => true, 'imported_from_xml' => true);
        $this->assertEquals(array_keys($expected), array_keys($actual), '->load() imports and merges imported files');

        // Bad import throws no exception due to ignore_errors value.
        $loader->load('services4_bad_import.yml');
    }

    public function testLoadServices()
    {
        $container = new ContainerBuilder();
        $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
        $loader->load('services6.yml');
        $services = $container->getDefinitions();
        $this->assertTrue(isset($services['foo']), '->load() parses service elements');
        $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Definition', $services['foo'], '->load() converts service element to Definition instances');
        $this->assertEquals('FooClass', $services['foo']->getClass(), '->load() parses the class attribute');
        $this->assertEquals('container', $services['scope.container']->getScope());
        $this->assertEquals('custom', $services['scope.custom']->getScope());
        $this->assertEquals('prototype', $services['scope.prototype']->getScope());
        $this->assertEquals('getInstance', $services['constructor']->getFactoryMethod(), '->load() parses the factory_method attribute');
        $this->assertEquals('%path%/foo.php', $services['file']->getFile(), '->load() parses the file tag');
        $this->assertEquals(array('foo', new Reference('foo'), array(true, false)), $services['arguments']->getArguments(), '->load() parses the argument tags');
        $this->assertEquals('sc_configure', $services['configurator1']->getConfigurator(), '->load() parses the configurator tag');
        $this->assertEquals(array(new Reference('baz'), 'configure'), $services['configurator2']->getConfigurator(), '->load() parses the configurator tag');
        $this->assertEquals(array('BazClass', 'configureStatic'), $services['configurator3']->getConfigurator(), '->load() parses the configurator tag');
        $this->assertEquals(array(array('setBar', array()), array('setBar', array()), array('setBar', array(new Expression('service("foo").foo() ~ parameter("foo")')))), $services['method_call1']->getMethodCalls(), '->load() parses the method_call tag');
        $this->assertEquals(array(array('setBar', array('foo', new Reference('foo'), array(true, false)))), $services['method_call2']->getMethodCalls(), '->load() parses the method_call tag');
        $this->assertEquals('baz_factory', $services['factory_service']->getFactoryService());

        $this->assertTrue($services['request']->isSynthetic(), '->load() parses the synthetic flag');
        $this->assertTrue($services['request']->isSynchronized(), '->load() parses the synchronized flag');
        $this->assertTrue($services['request']->isLazy(), '->load() parses the lazy flag');

        $aliases = $container->getAliases();
        $this->assertTrue(isset($aliases['alias_for_foo']), '->load() parses aliases');
        $this->assertEquals('foo', (string) $aliases['alias_for_foo'], '->load() parses aliases');
        $this->assertTrue($aliases['alias_for_foo']->isPublic());
        $this->assertTrue(isset($aliases['another_alias_for_foo']));
        $this->assertEquals('foo', (string) $aliases['another_alias_for_foo']);
        $this->assertFalse($aliases['another_alias_for_foo']->isPublic());
    }

    public function testExtensions()
    {
        $container = new ContainerBuilder();
        $container->registerExtension(new \ProjectExtension());
        $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
        $loader->load('services10.yml');
        $container->compile();
        $services = $container->getDefinitions();
        $parameters = $container->getParameterBag()->all();

        $this->assertTrue(isset($services['project.service.bar']), '->load() parses extension elements');
        $this->assertTrue(isset($parameters['project.parameter.bar']), '->load() parses extension elements');

        $this->assertEquals('BAR', $services['project.service.foo']->getClass(), '->load() parses extension elements');
        $this->assertEquals('BAR', $parameters['project.parameter.foo'], '->load() parses extension elements');

        try {
            $loader->load('services11.yml');
            $this->fail('->load() throws an InvalidArgumentException if the tag is not valid');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the tag is not valid');
            $this->assertStringStartsWith('There is no extension able to load the configuration for "foobarfoobar" (in', $e->getMessage(), '->load() throws an InvalidArgumentException if the tag is not valid');
        }
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Loader\YamlFileLoader::supports
     */
    public function testSupports()
    {
        $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator());

        $this->assertTrue($loader->supports('foo.yml'), '->supports() returns true if the resource is loadable');
        $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable');
    }

    public function testNonArrayTagThrowsException()
    {
        $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
        try {
            $loader->load('badtag1.yml');
            $this->fail('->load() should throw an exception when the tags key of a service is not an array');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the tags key is not an array');
            $this->assertStringStartsWith('Parameter "tags" must be an array for service', $e->getMessage(), '->load() throws an InvalidArgumentException if the tags key is not an array');
        }
    }

    public function testTagWithoutNameThrowsException()
    {
        $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
        try {
            $loader->load('badtag2.yml');
            $this->fail('->load() should throw an exception when a tag is missing the name key');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if a tag is missing the name key');
            $this->assertStringStartsWith('A "tags" entry is missing a "name" key for service ', $e->getMessage(), '->load() throws an InvalidArgumentException if a tag is missing the name key');
        }
    }

    public function testTagWithAttributeArrayThrowsException()
    {
        $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
        try {
            $loader->load('badtag3.yml');
            $this->fail('->load() should throw an exception when a tag-attribute is not a scalar');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if a tag-attribute is not a scalar');
            $this->assertStringStartsWith('A "tags" attribute must be of a scalar-type for service "foo_service", tag "foo", attribute "bar"', $e->getMessage(), '->load() throws an InvalidArgumentException if a tag-attribute is not a scalar');
        }
    }
}
PK��ZQ&I�8a8aatest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Loader;

use Symfony\Component\DependencyInjection\ContainerInterface;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\Config\Loader\Loader;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
use Symfony\Component\Config\Loader\LoaderResolver;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\ExpressionLanguage\Expression;

class XmlFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    protected static $fixturesPath;

    public static function setUpBeforeClass()
    {
        self::$fixturesPath = realpath(__DIR__.'/../Fixtures/');
        require_once self::$fixturesPath.'/includes/foo.php';
        require_once self::$fixturesPath.'/includes/ProjectExtension.php';
        require_once self::$fixturesPath.'/includes/ProjectWithXsdExtension.php';
    }

    public function testLoad()
    {
        $loader = new XmlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/ini'));

        try {
            $loader->load('foo.xml');
            $this->fail('->load() throws an InvalidArgumentException if the loaded file does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the loaded file does not exist');
            $this->assertStringStartsWith('The file "foo.xml" does not exist (in:', $e->getMessage(), '->load() throws an InvalidArgumentException if the loaded file does not exist');
        }
    }

    public function testParseFile()
    {
        $loader = new XmlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/ini'));
        $r = new \ReflectionObject($loader);
        $m = $r->getMethod('parseFile');
        $m->setAccessible(true);

        try {
            $m->invoke($loader, self::$fixturesPath.'/ini/parameters.ini');
            $this->fail('->parseFile() throws an InvalidArgumentException if the loaded file is not a valid XML file');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException', $e, '->parseFile() throws an InvalidArgumentException if the loaded file is not a valid XML file');
            $this->assertRegExp(sprintf('#^Unable to parse file ".+%s".$#', 'parameters.ini'), $e->getMessage(), '->parseFile() throws an InvalidArgumentException if the loaded file is not a valid XML file');

            $e = $e->getPrevious();
            $this->assertInstanceOf('InvalidArgumentException', $e, '->parseFile() throws an InvalidArgumentException if the loaded file is not a valid XML file');
            $this->assertStringStartsWith('[ERROR 4] Start tag expected, \'<\' not found (in', $e->getMessage(), '->parseFile() throws an InvalidArgumentException if the loaded file is not a valid XML file');
        }

        $loader = new XmlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/xml'));

        try {
            $m->invoke($loader, self::$fixturesPath.'/xml/nonvalid.xml');
            $this->fail('->parseFile() throws an InvalidArgumentException if the loaded file does not validate the XSD');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException', $e, '->parseFile() throws an InvalidArgumentException if the loaded file does not validate the XSD');
            $this->assertRegExp(sprintf('#^Unable to parse file ".+%s".$#', 'nonvalid.xml'), $e->getMessage(), '->parseFile() throws an InvalidArgumentException if the loaded file is not a valid XML file');

            $e = $e->getPrevious();
            $this->assertInstanceOf('InvalidArgumentException', $e, '->parseFile() throws an InvalidArgumentException if the loaded file does not validate the XSD');
            $this->assertStringStartsWith('[ERROR 1845] Element \'nonvalid\': No matching global declaration available for the validation root. (in', $e->getMessage(), '->parseFile() throws an InvalidArgumentException if the loaded file does not validate the XSD');
        }

        $xml = $m->invoke($loader, self::$fixturesPath.'/xml/services1.xml');
        $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\SimpleXMLElement', $xml, '->parseFile() returns an SimpleXMLElement object');
    }

    public function testLoadParameters()
    {
        $container = new ContainerBuilder();
        $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
        $loader->load('services2.xml');

        $actual = $container->getParameterBag()->all();
        $expected = array(
            'a string',
            'foo' => 'bar',
            'values' => array(
                0,
                'integer' => 4,
                100 => null,
                'true',
                true,
                false,
                'on',
                'off',
                'float' => 1.3,
                1000.3,
                'a string',
                array('foo', 'bar'),
            ),
            'foo_bar' => new Reference('foo_bar'),
            'mixedcase' => array('MixedCaseKey' => 'value'),
            'constant' => PHP_EOL,
        );

        $this->assertEquals($expected, $actual, '->load() converts XML values to PHP ones');
    }

    public function testLoadImports()
    {
        $container = new ContainerBuilder();
        $resolver = new LoaderResolver(array(
            new IniFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')),
            new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')),
            $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')),
        ));
        $loader->setResolver($resolver);
        $loader->load('services4.xml');

        $actual = $container->getParameterBag()->all();
        $expected = array(
            'a string',
            'foo' => 'bar',
            'values' => array(
                0,
                'integer' => 4,
                100 => null,
                'true',
                true,
                false,
                'on',
                'off',
                'float' => 1.3,
                1000.3,
                'a string',
                array('foo', 'bar'),
            ),
            'foo_bar' => new Reference('foo_bar'),
            'mixedcase' => array('MixedCaseKey' => 'value'),
            'constant' => PHP_EOL,
            'bar' => '%foo%',
            'imported_from_ini' => true,
            'imported_from_yaml' => true
        );

        $this->assertEquals(array_keys($expected), array_keys($actual), '->load() imports and merges imported files');

        // Bad import throws no exception due to ignore_errors value.
        $loader->load('services4_bad_import.xml');
    }

    public function testLoadAnonymousServices()
    {
        $container = new ContainerBuilder();
        $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
        $loader->load('services5.xml');
        $services = $container->getDefinitions();
        $this->assertCount(4, $services, '->load() attributes unique ids to anonymous services');

        // anonymous service as an argument
        $args = $services['foo']->getArguments();
        $this->assertCount(1, $args, '->load() references anonymous services as "normal" ones');
        $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Reference', $args[0], '->load() converts anonymous services to references to "normal" services');
        $this->assertTrue(isset($services[(string) $args[0]]), '->load() makes a reference to the created ones');
        $inner = $services[(string) $args[0]];
        $this->assertEquals('BarClass', $inner->getClass(), '->load() uses the same configuration as for the anonymous ones');

        // inner anonymous services
        $args = $inner->getArguments();
        $this->assertCount(1, $args, '->load() references anonymous services as "normal" ones');
        $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Reference', $args[0], '->load() converts anonymous services to references to "normal" services');
        $this->assertTrue(isset($services[(string) $args[0]]), '->load() makes a reference to the created ones');
        $inner = $services[(string) $args[0]];
        $this->assertEquals('BazClass', $inner->getClass(), '->load() uses the same configuration as for the anonymous ones');

        // anonymous service as a property
        $properties = $services['foo']->getProperties();
        $property = $properties['p'];
        $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Reference', $property, '->load() converts anonymous services to references to "normal" services');
        $this->assertTrue(isset($services[(string) $property]), '->load() makes a reference to the created ones');
        $inner = $services[(string) $property];
        $this->assertEquals('BazClass', $inner->getClass(), '->load() uses the same configuration as for the anonymous ones');
    }

    public function testLoadServices()
    {
        $container = new ContainerBuilder();
        $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
        $loader->load('services6.xml');
        $services = $container->getDefinitions();
        $this->assertTrue(isset($services['foo']), '->load() parses <service> elements');
        $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Definition', $services['foo'], '->load() converts <service> element to Definition instances');
        $this->assertEquals('FooClass', $services['foo']->getClass(), '->load() parses the class attribute');
        $this->assertEquals('container', $services['scope.container']->getScope());
        $this->assertEquals('custom', $services['scope.custom']->getScope());
        $this->assertEquals('prototype', $services['scope.prototype']->getScope());
        $this->assertEquals('getInstance', $services['constructor']->getFactoryMethod(), '->load() parses the factory-method attribute');
        $this->assertEquals('%path%/foo.php', $services['file']->getFile(), '->load() parses the file tag');
        $this->assertEquals(array('foo', new Reference('foo'), array(true, false)), $services['arguments']->getArguments(), '->load() parses the argument tags');
        $this->assertEquals('sc_configure', $services['configurator1']->getConfigurator(), '->load() parses the configurator tag');
        $this->assertEquals(array(new Reference('baz', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false), 'configure'), $services['configurator2']->getConfigurator(), '->load() parses the configurator tag');
        $this->assertEquals(array('BazClass', 'configureStatic'), $services['configurator3']->getConfigurator(), '->load() parses the configurator tag');
        $this->assertEquals(array(array('setBar', array()), array('setBar', array(new Expression('service("foo").foo() ~ parameter("foo")')))), $services['method_call1']->getMethodCalls(), '->load() parses the method_call tag');
        $this->assertEquals(array(array('setBar', array('foo', new Reference('foo'), array(true, false)))), $services['method_call2']->getMethodCalls(), '->load() parses the method_call tag');
        $this->assertNull($services['factory_service']->getClass());
        $this->assertEquals('getInstance', $services['factory_service']->getFactoryMethod());
        $this->assertEquals('baz_factory', $services['factory_service']->getFactoryService());

        $this->assertTrue($services['request']->isSynthetic(), '->load() parses the synthetic flag');
        $this->assertTrue($services['request']->isSynchronized(), '->load() parses the synchronized flag');
        $this->assertTrue($services['request']->isLazy(), '->load() parses the lazy flag');

        $aliases = $container->getAliases();
        $this->assertTrue(isset($aliases['alias_for_foo']), '->load() parses <service> elements');
        $this->assertEquals('foo', (string) $aliases['alias_for_foo'], '->load() parses aliases');
        $this->assertTrue($aliases['alias_for_foo']->isPublic());
        $this->assertTrue(isset($aliases['another_alias_for_foo']));
        $this->assertEquals('foo', (string) $aliases['another_alias_for_foo']);
        $this->assertFalse($aliases['another_alias_for_foo']->isPublic());
    }

    public function testParsesTags()
    {
        $container = new ContainerBuilder();
        $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
        $loader->load('services10.xml');

        $services = $container->findTaggedServiceIds('foo_tag');
        $this->assertCount(1, $services);

        foreach ($services as $id => $tagAttributes) {
            foreach ($tagAttributes as $attributes) {
                $this->assertArrayHasKey('other_option', $attributes);
                $this->assertEquals('lorem', $attributes['other_option']);
                $this->assertArrayHasKey('other-option', $attributes, 'unnormalized tag attributes should not be removed');

                $this->assertEquals('ciz', $attributes['some_option'], 'no overriding should be done when normalizing');
                $this->assertEquals('cat', $attributes['some-option']);

                $this->assertArrayNotHasKey('an_other_option', $attributes, 'normalization should not be done when an underscore is already found');
            }
        }
    }

    public function testConvertDomElementToArray()
    {
        $doc = new \DOMDocument("1.0");
        $doc->loadXML('<foo>bar</foo>');
        $this->assertEquals('bar', XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array');

        $doc = new \DOMDocument("1.0");
        $doc->loadXML('<foo foo="bar" />');
        $this->assertEquals(array('foo' => 'bar'), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array');

        $doc = new \DOMDocument("1.0");
        $doc->loadXML('<foo><foo>bar</foo></foo>');
        $this->assertEquals(array('foo' => 'bar'), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array');

        $doc = new \DOMDocument("1.0");
        $doc->loadXML('<foo><foo>bar<foo>bar</foo></foo></foo>');
        $this->assertEquals(array('foo' => array('value' => 'bar', 'foo' => 'bar')), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array');

        $doc = new \DOMDocument("1.0");
        $doc->loadXML('<foo><foo></foo></foo>');
        $this->assertEquals(array('foo' => null), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array');

        $doc = new \DOMDocument("1.0");
        $doc->loadXML('<foo><foo><!-- foo --></foo></foo>');
        $this->assertEquals(array('foo' => null), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array');

        $doc = new \DOMDocument("1.0");
        $doc->loadXML('<foo><foo foo="bar"/><foo foo="bar"/></foo>');
        $this->assertEquals(array('foo' => array(array('foo' => 'bar'), array('foo' => 'bar'))), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array');
    }

    public function testExtensions()
    {
        $container = new ContainerBuilder();
        $container->registerExtension(new \ProjectExtension());
        $container->registerExtension(new \ProjectWithXsdExtension());
        $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));

        // extension without an XSD
        $loader->load('extensions/services1.xml');
        $container->compile();
        $services = $container->getDefinitions();
        $parameters = $container->getParameterBag()->all();

        $this->assertTrue(isset($services['project.service.bar']), '->load() parses extension elements');
        $this->assertTrue(isset($parameters['project.parameter.bar']), '->load() parses extension elements');

        $this->assertEquals('BAR', $services['project.service.foo']->getClass(), '->load() parses extension elements');
        $this->assertEquals('BAR', $parameters['project.parameter.foo'], '->load() parses extension elements');

        // extension with an XSD
        $container = new ContainerBuilder();
        $container->registerExtension(new \ProjectExtension());
        $container->registerExtension(new \ProjectWithXsdExtension());
        $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
        $loader->load('extensions/services2.xml');
        $container->compile();
        $services = $container->getDefinitions();
        $parameters = $container->getParameterBag()->all();

        $this->assertTrue(isset($services['project.service.bar']), '->load() parses extension elements');
        $this->assertTrue(isset($parameters['project.parameter.bar']), '->load() parses extension elements');

        $this->assertEquals('BAR', $services['project.service.foo']->getClass(), '->load() parses extension elements');
        $this->assertEquals('BAR', $parameters['project.parameter.foo'], '->load() parses extension elements');

        $container = new ContainerBuilder();
        $container->registerExtension(new \ProjectExtension());
        $container->registerExtension(new \ProjectWithXsdExtension());
        $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));

        // extension with an XSD (does not validate)
        try {
            $loader->load('extensions/services3.xml');
            $this->fail('->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
            $this->assertRegExp(sprintf('#^Unable to parse file ".+%s".$#', 'services3.xml'), $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');

            $e = $e->getPrevious();
            $this->assertInstanceOf('InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
            $this->assertContains('The attribute \'bar\' is not allowed', $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
        }

        // non-registered extension
        try {
            $loader->load('extensions/services4.xml');
            $this->fail('->load() throws an InvalidArgumentException if the tag is not valid');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the tag is not valid');
            $this->assertStringStartsWith('There is no extension able to load the configuration for "project:bar" (in', $e->getMessage(), '->load() throws an InvalidArgumentException if the tag is not valid');
        }
    }

    public function testExtensionInPhar()
    {
        if (extension_loaded('suhosin') && false === strpos(ini_get('suhosin.executor.include.whitelist'), 'phar')) {
            $this->markTestSkipped('To run this test, add "phar" to the "suhosin.executor.include.whitelist" settings in your php.ini file.');
        }

        require_once self::$fixturesPath.'/includes/ProjectWithXsdExtensionInPhar.phar';

        // extension with an XSD in PHAR archive
        $container = new ContainerBuilder();
        $container->registerExtension(new \ProjectWithXsdExtensionInPhar());
        $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
        $loader->load('extensions/services6.xml');

        // extension with an XSD in PHAR archive (does not validate)
        try {
            $loader->load('extensions/services7.xml');
            $this->fail('->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
            $this->assertRegExp(sprintf('#^Unable to parse file ".+%s".$#', 'services7.xml'), $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');

            $e = $e->getPrevious();
            $this->assertInstanceOf('InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
            $this->assertContains('The attribute \'bar\' is not allowed', $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
        }
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Loader\XmlFileLoader::supports
     */
    public function testSupports()
    {
        $loader = new XmlFileLoader(new ContainerBuilder(), new FileLocator());

        $this->assertTrue($loader->supports('foo.xml'), '->supports() returns true if the resource is loadable');
        $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable');
    }

    public function testNoNamingConflictsForAnonymousServices()
    {
        $container = new ContainerBuilder();

        $loader1 = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml/extension1'));
        $loader1->load('services.xml');
        $services = $container->getDefinitions();
        $this->assertCount(2, $services, '->load() attributes unique ids to anonymous services');
        $loader2 = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml/extension2'));
        $loader2->load('services.xml');
        $services = $container->getDefinitions();
        $this->assertCount(4, $services, '->load() attributes unique ids to anonymous services');

        $services = $container->getDefinitions();
        $args1 = $services['extension1.foo']->getArguments();
        $inner1 = $services[(string) $args1[0]];
        $this->assertEquals('BarClass1', $inner1->getClass(), '->load() uses the same configuration as for the anonymous ones');
        $args2 = $services['extension2.foo']->getArguments();
        $inner2 = $services[(string) $args2[0]];
        $this->assertEquals('BarClass2', $inner2->getClass(), '->load() uses the same configuration as for the anonymous ones');
    }

    public function testDocTypeIsNotAllowed()
    {
        $container = new ContainerBuilder();

        $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));

        // document types are not allowed.
        try {
            $loader->load('withdoctype.xml');
            $this->fail('->load() throws an InvalidArgumentException if the configuration contains a document type');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration contains a document type');
            $this->assertRegExp(sprintf('#^Unable to parse file ".+%s".$#', 'withdoctype.xml'), $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration contains a document type');

            $e = $e->getPrevious();
            $this->assertInstanceOf('InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration contains a document type');
            $this->assertSame('Document types are not allowed.', $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration contains a document type');
        }
    }
}
PK��Z���
�
atest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Loader/IniFileLoaderTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Loader;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
use Symfony\Component\Config\FileLocator;

class IniFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    protected static $fixturesPath;

    protected $container;
    protected $loader;

    public static function setUpBeforeClass()
    {
        self::$fixturesPath = realpath(__DIR__.'/../Fixtures/');
    }

    protected function setUp()
    {
        $this->container = new ContainerBuilder();
        $this->loader    = new IniFileLoader($this->container, new FileLocator(self::$fixturesPath.'/ini'));
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Loader\IniFileLoader::__construct
     * @covers Symfony\Component\DependencyInjection\Loader\IniFileLoader::load
     */
    public function testIniFileCanBeLoaded()
    {
        $this->loader->load('parameters.ini');
        $this->assertEquals(array('foo' => 'bar', 'bar' => '%foo%'), $this->container->getParameterBag()->all(), '->load() takes a single file name as its first argument');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Loader\IniFileLoader::__construct
     * @covers Symfony\Component\DependencyInjection\Loader\IniFileLoader::load
     *
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage The file "foo.ini" does not exist (in:
     */
    public function testExceptionIsRaisedWhenIniFileDoesNotExist()
    {
        $this->loader->load('foo.ini');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Loader\IniFileLoader::__construct
     * @covers Symfony\Component\DependencyInjection\Loader\IniFileLoader::load
     *
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage The "nonvalid.ini" file is not valid.
     */
    public function testExceptionIsRaisedWhenIniFileCannotBeParsed()
    {
        @$this->loader->load('nonvalid.ini');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Loader\IniFileLoader::supports
     */
    public function testSupports()
    {
        $loader = new IniFileLoader(new ContainerBuilder(), new FileLocator());

        $this->assertTrue($loader->supports('foo.ini'), '->supports() returns true if the resource is loadable');
        $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable');
    }
}
PK��Z'����	�	rtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInvalidReferencesPassTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Compiler;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Compiler\ResolveInvalidReferencesPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class ResolveInvalidReferencesPassTest extends \PHPUnit_Framework_TestCase
{
    public function testProcess()
    {
        $container = new ContainerBuilder();
        $def = $container
            ->register('foo')
            ->setArguments(array(new Reference('bar', ContainerInterface::NULL_ON_INVALID_REFERENCE)))
            ->addMethodCall('foo', array(new Reference('moo', ContainerInterface::IGNORE_ON_INVALID_REFERENCE)))
        ;

        $this->process($container);

        $arguments = $def->getArguments();
        $this->assertNull($arguments[0]);
        $this->assertCount(0, $def->getMethodCalls());
    }

    public function testProcessIgnoreNonExistentServices()
    {
        $container = new ContainerBuilder();
        $def = $container
            ->register('foo')
            ->setArguments(array(new Reference('bar')))
        ;

        $this->process($container);

        $arguments = $def->getArguments();
        $this->assertEquals('bar', (string) $arguments[0]);
    }

    public function testProcessRemovesPropertiesOnInvalid()
    {
        $container = new ContainerBuilder();
        $def = $container
            ->register('foo')
            ->setProperty('foo', new Reference('bar', ContainerInterface::IGNORE_ON_INVALID_REFERENCE))
        ;

        $this->process($container);

        $this->assertEquals(array(), $def->getProperties());
    }

    public function testStrictFlagIsPreserved()
    {
        $container = new ContainerBuilder();
        $container->register('bar');
        $def = $container
            ->register('foo')
            ->addArgument(new Reference('bar', ContainerInterface::NULL_ON_INVALID_REFERENCE, false))
        ;

        $this->process($container);

        $this->assertFalse($def->getArgument(0)->isStrict());
    }

    protected function process(ContainerBuilder $container)
    {
        $pass = new ResolveInvalidReferencesPass();
        $pass->process($container);
    }
}
PK��Z��'{{qtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/CheckCircularReferencesPassTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Compiler;

use Symfony\Component\DependencyInjection\Reference;

use Symfony\Component\DependencyInjection\Compiler\CheckCircularReferencesPass;

use Symfony\Component\DependencyInjection\Compiler\AnalyzeServiceReferencesPass;

use Symfony\Component\DependencyInjection\Compiler\Compiler;

use Symfony\Component\DependencyInjection\ContainerBuilder;

class CheckCircularReferencesPassTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException
     */
    public function testProcess()
    {
        $container = new ContainerBuilder();
        $container->register('a')->addArgument(new Reference('b'));
        $container->register('b')->addArgument(new Reference('a'));

        $this->process($container);
    }

    /**
     * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException
     */
    public function testProcessWithAliases()
    {
        $container = new ContainerBuilder();
        $container->register('a')->addArgument(new Reference('b'));
        $container->setAlias('b', 'c');
        $container->setAlias('c', 'a');

        $this->process($container);
    }

    /**
     * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException
     */
    public function testProcessDetectsIndirectCircularReference()
    {
        $container = new ContainerBuilder();
        $container->register('a')->addArgument(new Reference('b'));
        $container->register('b')->addArgument(new Reference('c'));
        $container->register('c')->addArgument(new Reference('a'));

        $this->process($container);
    }

    /**
     * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException
     */
    public function testDeepCircularReference()
    {
        $container = new ContainerBuilder();
        $container->register('a')->addArgument(new Reference('b'));
        $container->register('b')->addArgument(new Reference('c'));
        $container->register('c')->addArgument(new Reference('b'));

        $this->process($container);
    }

    public function testProcessIgnoresMethodCalls()
    {
        $container = new ContainerBuilder();
        $container->register('a')->addArgument(new Reference('b'));
        $container->register('b')->addMethodCall('setA', array(new Reference('a')));

        $this->process($container);
    }

    protected function process(ContainerBuilder $container)
    {
        $compiler = new Compiler();
        $passConfig = $compiler->getPassConfig();
        $passConfig->setOptimizationPasses(array(
            new AnalyzeServiceReferencesPass(true),
            new CheckCircularReferencesPass(),
        ));
        $passConfig->setRemovingPasses(array());

        $compiler->compile($container);
    }
}
PK��Z>�"��ptest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/CheckReferenceValidityPassTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Compiler;

use Symfony\Component\DependencyInjection\Scope;

use Symfony\Component\DependencyInjection\Compiler\CheckReferenceValidityPass;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class CheckReferenceValidityPassTest extends \PHPUnit_Framework_TestCase
{
    public function testProcessIgnoresScopeWideningIfNonStrictReference()
    {
        $container = new ContainerBuilder();
        $container->register('a')->addArgument(new Reference('b', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false));
        $container->register('b')->setScope('prototype');

        $this->process($container);
    }

    /**
     * @expectedException \RuntimeException
     */
    public function testProcessDetectsScopeWidening()
    {
        $container = new ContainerBuilder();
        $container->register('a')->addArgument(new Reference('b'));
        $container->register('b')->setScope('prototype');

        $this->process($container);
    }

    public function testProcessIgnoresCrossScopeHierarchyReferenceIfNotStrict()
    {
        $container = new ContainerBuilder();
        $container->addScope(new Scope('a'));
        $container->addScope(new Scope('b'));

        $container->register('a')->setScope('a')->addArgument(new Reference('b', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false));
        $container->register('b')->setScope('b');

        $this->process($container);
    }

    /**
     * @expectedException \RuntimeException
     */
    public function testProcessDetectsCrossScopeHierarchyReference()
    {
        $container = new ContainerBuilder();
        $container->addScope(new Scope('a'));
        $container->addScope(new Scope('b'));

        $container->register('a')->setScope('a')->addArgument(new Reference('b'));
        $container->register('b')->setScope('b');

        $this->process($container);
    }

    /**
     * @expectedException \RuntimeException
     */
    public function testProcessDetectsReferenceToAbstractDefinition()
    {
        $container = new ContainerBuilder();

        $container->register('a')->setAbstract(true);
        $container->register('b')->addArgument(new Reference('a'));

        $this->process($container);
    }

    public function testProcess()
    {
        $container = new ContainerBuilder();
        $container->register('a')->addArgument(new Reference('b'));
        $container->register('b');

        $this->process($container);
    }

    protected function process(ContainerBuilder $container)
    {
        $pass = new CheckReferenceValidityPass();
        $pass->process($container);
    }
}
PK��Z]����ttest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Compiler;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\DefinitionDecorator;
use Symfony\Component\DependencyInjection\Compiler\ResolveDefinitionTemplatesPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class ResolveDefinitionTemplatesPassTest extends \PHPUnit_Framework_TestCase
{
    public function testProcess()
    {
        $container = new ContainerBuilder();
        $container->register('parent', 'foo')->setArguments(array('moo', 'b'))->setProperty('foo', 'moo');
        $container->setDefinition('child', new DefinitionDecorator('parent'))
            ->replaceArgument(0, 'a')
            ->setProperty('foo', 'bar')
            ->setClass('bar')
        ;

        $this->process($container);

        $def = $container->getDefinition('child');
        $this->assertNotInstanceOf('Symfony\Component\DependencyInjection\DefinitionDecorator', $def);
        $this->assertEquals('bar', $def->getClass());
        $this->assertEquals(array('a', 'b'), $def->getArguments());
        $this->assertEquals(array('foo' => 'bar'), $def->getProperties());
    }

    public function testProcessAppendsMethodCallsAlways()
    {
        $container = new ContainerBuilder();

        $container
            ->register('parent')
            ->addMethodCall('foo', array('bar'))
        ;

        $container
            ->setDefinition('child', new DefinitionDecorator('parent'))
            ->addMethodCall('bar', array('foo'))
        ;

        $this->process($container);

        $def = $container->getDefinition('child');
        $this->assertEquals(array(
            array('foo', array('bar')),
            array('bar', array('foo')),
        ), $def->getMethodCalls());
    }

    public function testProcessDoesNotCopyAbstract()
    {
        $container = new ContainerBuilder();

        $container
            ->register('parent')
            ->setAbstract(true)
        ;

        $container
            ->setDefinition('child', new DefinitionDecorator('parent'))
        ;

        $this->process($container);

        $def = $container->getDefinition('child');
        $this->assertFalse($def->isAbstract());
    }

    public function testProcessDoesNotCopyScope()
    {
        $container = new ContainerBuilder();

        $container
            ->register('parent')
            ->setScope('foo')
        ;

        $container
            ->setDefinition('child', new DefinitionDecorator('parent'))
        ;

        $this->process($container);

        $def = $container->getDefinition('child');
        $this->assertEquals(ContainerInterface::SCOPE_CONTAINER, $def->getScope());
    }

    public function testProcessDoesNotCopyTags()
    {
        $container = new ContainerBuilder();

        $container
            ->register('parent')
            ->addTag('foo')
        ;

        $container
            ->setDefinition('child', new DefinitionDecorator('parent'))
        ;

        $this->process($container);

        $def = $container->getDefinition('child');
        $this->assertEquals(array(), $def->getTags());
    }

    public function testProcessHandlesMultipleInheritance()
    {
        $container = new ContainerBuilder();

        $container
            ->register('parent', 'foo')
            ->setArguments(array('foo', 'bar', 'c'))
        ;

        $container
            ->setDefinition('child2', new DefinitionDecorator('child1'))
            ->replaceArgument(1, 'b')
        ;

        $container
            ->setDefinition('child1', new DefinitionDecorator('parent'))
            ->replaceArgument(0, 'a')
        ;

        $this->process($container);

        $def = $container->getDefinition('child2');
        $this->assertEquals(array('a', 'b', 'c'), $def->getArguments());
        $this->assertEquals('foo', $def->getClass());
    }

    public function testSetLazyOnServiceHasParent()
    {
        $container = new ContainerBuilder();

        $container->register('parent','stdClass');

        $container->setDefinition('child1',new DefinitionDecorator('parent'))
            ->setLazy(true)
        ;

        $this->process($container);

        $this->assertTrue($container->getDefinition('child1')->isLazy());
    }

    public function testSetLazyOnServiceIsParent()
    {
        $container = new ContainerBuilder();

        $container->register('parent','stdClass')
            ->setLazy(true)
        ;

        $container->setDefinition('child1',new DefinitionDecorator('parent'));

        $this->process($container);

        $this->assertTrue($container->getDefinition('child1')->isLazy());
    }

    protected function process(ContainerBuilder $container)
    {
        $pass = new ResolveDefinitionTemplatesPass();
        $pass->process($container);
    }
}
PK��Z}1H@@xtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/ReplaceAliasByActualDefinitionPassTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Compiler;

use Symfony\Component\DependencyInjection\Compiler\ReplaceAliasByActualDefinitionPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;

class ReplaceAliasByActualDefinitionPassTest extends \PHPUnit_Framework_TestCase
{
    public function testProcess()
    {
        $container = new ContainerBuilder();

        $container->register('a', '\stdClass');

        $bDefinition = new Definition('\stdClass');
        $bDefinition->setPublic(false);
        $container->setDefinition('b', $bDefinition);

        $container->setAlias('a_alias', 'a');
        $container->setAlias('b_alias', 'b');

        $this->process($container);

        $this->assertTrue($container->has('a'), '->process() does nothing to public definitions.');
        $this->assertTrue($container->hasAlias('a_alias'));
        $this->assertFalse($container->has('b'), '->process() removes non-public definitions.');
        $this->assertTrue(
            $container->has('b_alias') && !$container->hasAlias('b_alias'),
            '->process() replaces alias to actual.'
        );
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testProcessWithInvalidAlias()
    {
        $container = new ContainerBuilder();
        $container->setAlias('a_alias', 'a');
        $this->process($container);
    }

    protected function process(ContainerBuilder $container)
    {
        $pass = new ReplaceAliasByActualDefinitionPass();
        $pass->process($container);
    }
}
PK��Z��f00rtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Compiler;

use Symfony\Component\DependencyInjection\Scope;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Compiler\AnalyzeServiceReferencesPass;
use Symfony\Component\DependencyInjection\Compiler\RepeatedPass;
use Symfony\Component\DependencyInjection\Compiler\InlineServiceDefinitionsPass;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class InlineServiceDefinitionsPassTest extends \PHPUnit_Framework_TestCase
{
    public function testProcess()
    {
        $container = new ContainerBuilder();
        $container
            ->register('inlinable.service')
            ->setPublic(false)
        ;

        $container
            ->register('service')
            ->setArguments(array(new Reference('inlinable.service')))
        ;

        $this->process($container);

        $arguments = $container->getDefinition('service')->getArguments();
        $this->assertInstanceOf('Symfony\Component\DependencyInjection\Definition', $arguments[0]);
        $this->assertSame($container->getDefinition('inlinable.service'), $arguments[0]);
    }

    public function testProcessDoesNotInlineWhenAliasedServiceIsNotOfPrototypeScope()
    {
        $container = new ContainerBuilder();
        $container
            ->register('foo')
            ->setPublic(false)
        ;
        $container->setAlias('moo', 'foo');

        $container
            ->register('service')
            ->setArguments(array($ref = new Reference('foo')))
        ;

        $this->process($container);

        $arguments = $container->getDefinition('service')->getArguments();
        $this->assertSame($ref, $arguments[0]);
    }

    public function testProcessDoesInlineServiceOfPrototypeScope()
    {
        $container = new ContainerBuilder();
        $container
            ->register('foo')
            ->setScope('prototype')
        ;
        $container
            ->register('bar')
            ->setPublic(false)
            ->setScope('prototype')
        ;
        $container->setAlias('moo', 'bar');

        $container
            ->register('service')
            ->setArguments(array(new Reference('foo'), $ref = new Reference('moo'), new Reference('bar')))
        ;

        $this->process($container);

        $arguments = $container->getDefinition('service')->getArguments();
        $this->assertEquals($container->getDefinition('foo'), $arguments[0]);
        $this->assertNotSame($container->getDefinition('foo'), $arguments[0]);
        $this->assertSame($ref, $arguments[1]);
        $this->assertEquals($container->getDefinition('bar'), $arguments[2]);
        $this->assertNotSame($container->getDefinition('bar'), $arguments[2]);
    }

    public function testProcessInlinesIfMultipleReferencesButAllFromTheSameDefinition()
    {
        $container = new ContainerBuilder();

        $a = $container->register('a')->setPublic(false);
        $b = $container
            ->register('b')
            ->addArgument(new Reference('a'))
            ->addArgument(new Definition(null, array(new Reference('a'))))
        ;

        $this->process($container);

        $arguments = $b->getArguments();
        $this->assertSame($a, $arguments[0]);

        $inlinedArguments = $arguments[1]->getArguments();
        $this->assertSame($a, $inlinedArguments[0]);
    }

    public function testProcessInlinesOnlyIfSameScope()
    {
        $container = new ContainerBuilder();

        $container->addScope(new Scope('foo'));
        $a = $container->register('a')->setPublic(false)->setScope('foo');
        $b = $container->register('b')->addArgument(new Reference('a'));

        $this->process($container);
        $arguments = $b->getArguments();
        $this->assertEquals(new Reference('a'), $arguments[0]);
        $this->assertTrue($container->hasDefinition('a'));
    }

    public function testProcessDoesNotInlineWhenServiceIsPrivateButLazy()
    {
        $container = new ContainerBuilder();
        $container
            ->register('foo')
            ->setPublic(false)
            ->setLazy(true)
        ;

        $container
            ->register('service')
            ->setArguments(array($ref = new Reference('foo')))
        ;

        $this->process($container);

        $arguments = $container->getDefinition('service')->getArguments();
        $this->assertSame($ref, $arguments[0]);
    }

    public function testProcessDoesNotInlineWhenServiceReferencesItself()
    {
        $container = new ContainerBuilder();
        $container
            ->register('foo')
            ->setPublic(false)
            ->addMethodCall('foo', array($ref = new Reference('foo')))
        ;

        $this->process($container);

        $calls = $container->getDefinition('foo')->getMethodCalls();
        $this->assertSame($ref, $calls[0][1][0]);
    }

    protected function process(ContainerBuilder $container)
    {
        $repeatedPass = new RepeatedPass(array(new AnalyzeServiceReferencesPass(), new InlineServiceDefinitionsPass()));
        $repeatedPass->process($container);
    }
}
PK��ZO����atest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Compiler;

use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * This class tests the integration of the different compiler passes
 */
class IntegrationTest extends \PHPUnit_Framework_TestCase
{
    /**
     * This tests that the following dependencies are correctly processed:
     *
     * A is public, B/C are private
     * A -> C
     * B -> C
     */
    public function testProcessRemovesAndInlinesRecursively()
    {
        $container = new ContainerBuilder();
        $container->setResourceTracking(false);

        $a = $container
            ->register('a', '\stdClass')
            ->addArgument(new Reference('c'))
        ;

        $b = $container
            ->register('b', '\stdClass')
            ->addArgument(new Reference('c'))
            ->setPublic(false)
        ;

        $c = $container
            ->register('c', '\stdClass')
            ->setPublic(false)
        ;

        $container->compile();

        $this->assertTrue($container->hasDefinition('a'));
        $arguments = $a->getArguments();
        $this->assertSame($c, $arguments[0]);
        $this->assertFalse($container->hasDefinition('b'));
        $this->assertFalse($container->hasDefinition('c'));
    }

    public function testProcessInlinesReferencesToAliases()
    {
        $container = new ContainerBuilder();
        $container->setResourceTracking(false);

        $a = $container
            ->register('a', '\stdClass')
            ->addArgument(new Reference('b'))
        ;

        $container->setAlias('b', new Alias('c', false));

        $c = $container
            ->register('c', '\stdClass')
            ->setPublic(false)
        ;

        $container->compile();

        $this->assertTrue($container->hasDefinition('a'));
        $arguments = $a->getArguments();
        $this->assertSame($c, $arguments[0]);
        $this->assertFalse($container->hasAlias('b'));
        $this->assertFalse($container->hasDefinition('c'));
    }

    public function testProcessInlinesWhenThereAreMultipleReferencesButFromTheSameDefinition()
    {
        $container = new ContainerBuilder();
        $container->setResourceTracking(false);

        $container
            ->register('a', '\stdClass')
            ->addArgument(new Reference('b'))
            ->addMethodCall('setC', array(new Reference('c')))
        ;

        $container
            ->register('b', '\stdClass')
            ->addArgument(new Reference('c'))
            ->setPublic(false)
        ;

        $container
            ->register('c', '\stdClass')
            ->setPublic(false)
        ;

        $container->compile();

        $this->assertTrue($container->hasDefinition('a'));
        $this->assertFalse($container->hasDefinition('b'));
        $this->assertFalse($container->hasDefinition('c'), 'Service C was not inlined.');
    }
}
PK��Z@|޵��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/CheckExceptionOnInvalidReferenceBehaviorPassTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Compiler;

use Symfony\Component\DependencyInjection\Definition;

use Symfony\Component\DependencyInjection\Compiler\CheckExceptionOnInvalidReferenceBehaviorPass;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class CheckExceptionOnInvalidReferenceBehaviorPassTest extends \PHPUnit_Framework_TestCase
{
    public function testProcess()
    {
        $container = new ContainerBuilder();

        $container
            ->register('a', '\stdClass')
            ->addArgument(new Reference('b'))
        ;
        $container->register('b', '\stdClass');
    }

    /**
     * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException
     */
    public function testProcessThrowsExceptionOnInvalidReference()
    {
        $container = new ContainerBuilder();

        $container
            ->register('a', '\stdClass')
            ->addArgument(new Reference('b'))
        ;

        $this->process($container);
    }

    /**
     * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException
     */
    public function testProcessThrowsExceptionOnInvalidReferenceFromInlinedDefinition()
    {
        $container = new ContainerBuilder();

        $def = new Definition();
        $def->addArgument(new Reference('b'));

        $container
            ->register('a', '\stdClass')
            ->addArgument($def)
        ;

        $this->process($container);
    }

    private function process(ContainerBuilder $container)
    {
        $pass = new CheckExceptionOnInvalidReferenceBehaviorPass();
        $pass->process($container);
    }
}
PK��Z@�w��qtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/CheckDefinitionValidityPassTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Compiler;

use Symfony\Component\DependencyInjection\Compiler\CheckDefinitionValidityPass;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class CheckDefinitionValidityPassTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
     */
    public function testProcessDetectsSyntheticNonPublicDefinitions()
    {
        $container = new ContainerBuilder();
        $container->register('a')->setSynthetic(true)->setPublic(false);

        $this->process($container);
    }

    /**
     * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
     */
    public function testProcessDetectsSyntheticPrototypeDefinitions()
    {
        $container = new ContainerBuilder();
        $container->register('a')->setSynthetic(true)->setScope(ContainerInterface::SCOPE_PROTOTYPE);

        $this->process($container);
    }

    /**
     * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
     */
    public function testProcessDetectsNonSyntheticNonAbstractDefinitionWithoutClass()
    {
        $container = new ContainerBuilder();
        $container->register('a')->setSynthetic(false)->setAbstract(false);

        $this->process($container);
    }

    public function testProcess()
    {
        $container = new ContainerBuilder();
        $container->register('a', 'class');
        $container->register('b', 'class')->setSynthetic(true)->setPublic(true);
        $container->register('c', 'class')->setAbstract(true);
        $container->register('d', 'class')->setSynthetic(true);

        $this->process($container);
    }

    public function testValidTags()
    {
        $container = new ContainerBuilder();
        $container->register('a', 'class')->addTag('foo', array('bar' => 'baz'));
        $container->register('b', 'class')->addTag('foo', array('bar' => null));
        $container->register('c', 'class')->addTag('foo', array('bar' => 1));
        $container->register('d', 'class')->addTag('foo', array('bar' => 1.1));

        $this->process($container);
    }

    /**
     * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
     */
    public function testInvalidTags()
    {
        $container = new ContainerBuilder();
        $container->register('a', 'class')->addTag('foo', array('bar' => array('baz' => 'baz')));

        $this->process($container);
    }

    protected function process(ContainerBuilder $container)
    {
        $pass = new CheckDefinitionValidityPass();
        $pass->process($container);
    }
}
PK��Z�~�``rtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/AnalyzeServiceReferencesPassTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Compiler;

use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Compiler\Compiler;
use Symfony\Component\DependencyInjection\Compiler\AnalyzeServiceReferencesPass;
use Symfony\Component\DependencyInjection\Compiler\RepeatedPass;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class AnalyzeServiceReferencesPassTest extends \PHPUnit_Framework_TestCase
{
    public function testProcess()
    {
        $container = new ContainerBuilder();

        $a = $container
            ->register('a')
            ->addArgument($ref1 = new Reference('b'))
        ;

        $b = $container
            ->register('b')
            ->addMethodCall('setA', array($ref2 = new Reference('a')))
        ;

        $c = $container
            ->register('c')
            ->addArgument($ref3 = new Reference('a'))
            ->addArgument($ref4 = new Reference('b'))
        ;

        $d = $container
            ->register('d')
            ->setProperty('foo', $ref5 = new Reference('b'))
        ;

        $e = $container
            ->register('e')
            ->setConfigurator(array($ref6 = new Reference('b'), 'methodName'))
        ;

        $graph = $this->process($container);

        $this->assertCount(4, $edges = $graph->getNode('b')->getInEdges());

        $this->assertSame($ref1, $edges[0]->getValue());
        $this->assertSame($ref4, $edges[1]->getValue());
        $this->assertSame($ref5, $edges[2]->getValue());
        $this->assertSame($ref6, $edges[3]->getValue());
    }

    public function testProcessDetectsReferencesFromInlinedDefinitions()
    {
        $container = new ContainerBuilder();

        $container
            ->register('a')
        ;

        $container
            ->register('b')
            ->addArgument(new Definition(null, array($ref = new Reference('a'))))
        ;

        $graph = $this->process($container);

        $this->assertCount(1, $refs = $graph->getNode('a')->getInEdges());
        $this->assertSame($ref, $refs[0]->getValue());
    }

    public function testProcessDoesNotSaveDuplicateReferences()
    {
        $container = new ContainerBuilder();

        $container
            ->register('a')
        ;
        $container
            ->register('b')
            ->addArgument(new Definition(null, array($ref1 = new Reference('a'))))
            ->addArgument(new Definition(null, array($ref2 = new Reference('a'))))
        ;

        $graph = $this->process($container);

        $this->assertCount(2, $graph->getNode('a')->getInEdges());
    }

    protected function process(ContainerBuilder $container)
    {
        $pass = new RepeatedPass(array(new AnalyzeServiceReferencesPass()));
        $pass->process($container);

        return $container->getCompiler()->getServiceReferenceGraph();
    }
}
PK��Z��I�
�
qtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/RemoveUnusedDefinitionsPassTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Compiler;

use Symfony\Component\DependencyInjection\Compiler\AnalyzeServiceReferencesPass;
use Symfony\Component\DependencyInjection\Compiler\Compiler;
use Symfony\Component\DependencyInjection\Compiler\RepeatedPass;
use Symfony\Component\DependencyInjection\Compiler\RemoveUnusedDefinitionsPass;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class RemoveUnusedDefinitionsPassTest extends \PHPUnit_Framework_TestCase
{
    public function testProcess()
    {
        $container = new ContainerBuilder();
        $container
            ->register('foo')
            ->setPublic(false)
        ;
        $container
            ->register('bar')
            ->setPublic(false)
        ;
        $container
            ->register('moo')
            ->setArguments(array(new Reference('bar')))
        ;

        $this->process($container);

        $this->assertFalse($container->hasDefinition('foo'));
        $this->assertTrue($container->hasDefinition('bar'));
        $this->assertTrue($container->hasDefinition('moo'));
    }

    public function testProcessRemovesUnusedDefinitionsRecursively()
    {
        $container = new ContainerBuilder();
        $container
            ->register('foo')
            ->setPublic(false)
        ;
        $container
            ->register('bar')
            ->setArguments(array(new Reference('foo')))
            ->setPublic(false)
        ;

        $this->process($container);

        $this->assertFalse($container->hasDefinition('foo'));
        $this->assertFalse($container->hasDefinition('bar'));
    }

    public function testProcessWorksWithInlinedDefinitions()
    {
        $container = new ContainerBuilder();
        $container
            ->register('foo')
            ->setPublic(false)
        ;
        $container
            ->register('bar')
            ->setArguments(array(new Definition(null, array(new Reference('foo')))))
        ;

        $this->process($container);

        $this->assertTrue($container->hasDefinition('foo'));
        $this->assertTrue($container->hasDefinition('bar'));
    }

    protected function process(ContainerBuilder $container)
    {
        $repeatedPass = new RepeatedPass(array(new AnalyzeServiceReferencesPass(), new RemoveUnusedDefinitionsPass()));
        $repeatedPass->process($container);
    }
}
PK��Z
T^�??ttest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveReferencesToAliasesPassTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Compiler;

use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Compiler\ResolveReferencesToAliasesPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class ResolveReferencesToAliasesPassTest extends \PHPUnit_Framework_TestCase
{
    public function testProcess()
    {
        $container = new ContainerBuilder();
        $container->setAlias('bar', 'foo');
        $def = $container
            ->register('moo')
            ->setArguments(array(new Reference('bar')))
        ;

        $this->process($container);

        $arguments = $def->getArguments();
        $this->assertEquals('foo', (string) $arguments[0]);
    }

    public function testProcessRecursively()
    {
        $container = new ContainerBuilder();
        $container->setAlias('bar', 'foo');
        $container->setAlias('moo', 'bar');
        $def = $container
            ->register('foobar')
            ->setArguments(array(new Reference('moo')))
        ;

        $this->process($container);

        $arguments = $def->getArguments();
        $this->assertEquals('foo', (string) $arguments[0]);
    }

    protected function process(ContainerBuilder $container)
    {
        $pass = new ResolveReferencesToAliasesPass();
        $pass->process($container);
    }
}
PK��Z���e�5�5Wtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/DefinitionTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests;

use Symfony\Component\DependencyInjection\Definition;

class DefinitionTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Symfony\Component\DependencyInjection\Definition::__construct
     */
    public function testConstructor()
    {
        $def = new Definition('stdClass');
        $this->assertEquals('stdClass', $def->getClass(), '__construct() takes the class name as its first argument');

        $def = new Definition('stdClass', array('foo'));
        $this->assertEquals(array('foo'), $def->getArguments(), '__construct() takes an optional array of arguments as its second argument');
    }

    public function testSetGetFactoryClass()
    {
        $def = new Definition('stdClass');
        $this->assertNull($def->getFactoryClass());
        $this->assertSame($def, $def->setFactoryClass('stdClass2'), "->setFactoryClass() implements a fluent interface.");
        $this->assertEquals('stdClass2', $def->getFactoryClass(), "->getFactoryClass() returns current class to construct this service.");
    }

    public function testSetGetFactoryMethod()
    {
        $def = new Definition('stdClass');
        $this->assertNull($def->getFactoryMethod());
        $this->assertSame($def, $def->setFactoryMethod('foo'), '->setFactoryMethod() implements a fluent interface');
        $this->assertEquals('foo', $def->getFactoryMethod(), '->getFactoryMethod() returns the factory method name');
    }

    public function testSetGetFactoryService()
    {
        $def = new Definition('stdClass');
        $this->assertNull($def->getFactoryService());
        $this->assertSame($def, $def->setFactoryService('foo.bar'), "->setFactoryService() implements a fluent interface.");
        $this->assertEquals('foo.bar', $def->getFactoryService(), "->getFactoryService() returns current service to construct this service.");
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Definition::setClass
     * @covers Symfony\Component\DependencyInjection\Definition::getClass
     */
    public function testSetGetClass()
    {
        $def = new Definition('stdClass');
        $this->assertSame($def, $def->setClass('foo'), '->setClass() implements a fluent interface');
        $this->assertEquals('foo', $def->getClass(), '->getClass() returns the class name');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Definition::setArguments
     * @covers Symfony\Component\DependencyInjection\Definition::getArguments
     * @covers Symfony\Component\DependencyInjection\Definition::addArgument
     */
    public function testArguments()
    {
        $def = new Definition('stdClass');
        $this->assertSame($def, $def->setArguments(array('foo')), '->setArguments() implements a fluent interface');
        $this->assertEquals(array('foo'), $def->getArguments(), '->getArguments() returns the arguments');
        $this->assertSame($def, $def->addArgument('bar'), '->addArgument() implements a fluent interface');
        $this->assertEquals(array('foo', 'bar'), $def->getArguments(), '->addArgument() adds an argument');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Definition::setMethodCalls
     * @covers Symfony\Component\DependencyInjection\Definition::addMethodCall
     * @covers Symfony\Component\DependencyInjection\Definition::hasMethodCall
     * @covers Symfony\Component\DependencyInjection\Definition::removeMethodCall
     */
    public function testMethodCalls()
    {
        $def = new Definition('stdClass');
        $this->assertSame($def, $def->setMethodCalls(array(array('foo', array('foo')))), '->setMethodCalls() implements a fluent interface');
        $this->assertEquals(array(array('foo', array('foo'))), $def->getMethodCalls(), '->getMethodCalls() returns the methods to call');
        $this->assertSame($def, $def->addMethodCall('bar', array('bar')), '->addMethodCall() implements a fluent interface');
        $this->assertEquals(array(array('foo', array('foo')), array('bar', array('bar'))), $def->getMethodCalls(), '->addMethodCall() adds a method to call');
        $this->assertTrue($def->hasMethodCall('bar'), '->hasMethodCall() returns true if first argument is a method to call registered');
        $this->assertFalse($def->hasMethodCall('no_registered'), '->hasMethodCall() returns false if first argument is not a method to call registered');
        $this->assertSame($def, $def->removeMethodCall('bar'), '->removeMethodCall() implements a fluent interface');
        $this->assertEquals(array(array('foo', array('foo'))), $def->getMethodCalls(), '->removeMethodCall() removes a method to call');
    }

    /**
     * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
     * @expectedExceptionMessage Method name cannot be empty.
     */
    public function testExceptionOnEmptyMethodCall()
    {
        $def = new Definition('stdClass');
        $def->addMethodCall('');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Definition::setFile
     * @covers Symfony\Component\DependencyInjection\Definition::getFile
     */
    public function testSetGetFile()
    {
        $def = new Definition('stdClass');
        $this->assertSame($def, $def->setFile('foo'), '->setFile() implements a fluent interface');
        $this->assertEquals('foo', $def->getFile(), '->getFile() returns the file to include');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Definition::setScope
     * @covers Symfony\Component\DependencyInjection\Definition::getScope
     */
    public function testSetGetScope()
    {
        $def = new Definition('stdClass');
        $this->assertEquals('container', $def->getScope());
        $this->assertSame($def, $def->setScope('foo'));
        $this->assertEquals('foo', $def->getScope());
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Definition::setPublic
     * @covers Symfony\Component\DependencyInjection\Definition::isPublic
     */
    public function testSetIsPublic()
    {
        $def = new Definition('stdClass');
        $this->assertTrue($def->isPublic(), '->isPublic() returns true by default');
        $this->assertSame($def, $def->setPublic(false), '->setPublic() implements a fluent interface');
        $this->assertFalse($def->isPublic(), '->isPublic() returns false if the instance must not be public.');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Definition::setSynthetic
     * @covers Symfony\Component\DependencyInjection\Definition::isSynthetic
     */
    public function testSetIsSynthetic()
    {
        $def = new Definition('stdClass');
        $this->assertFalse($def->isSynthetic(), '->isSynthetic() returns false by default');
        $this->assertSame($def, $def->setSynthetic(true), '->setSynthetic() implements a fluent interface');
        $this->assertTrue($def->isSynthetic(), '->isSynthetic() returns true if the service is synthetic.');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Definition::setSynchronized
     * @covers Symfony\Component\DependencyInjection\Definition::isSynchronized
     */
    public function testSetIsSynchronized()
    {
        $def = new Definition('stdClass');
        $this->assertFalse($def->isSynchronized(), '->isSynchronized() returns false by default');
        $this->assertSame($def, $def->setSynchronized(true), '->setSynchronized() implements a fluent interface');
        $this->assertTrue($def->isSynchronized(), '->isSynchronized() returns true if the service is synchronized.');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Definition::setLazy
     * @covers Symfony\Component\DependencyInjection\Definition::isLazy
     */
    public function testSetIsLazy()
    {
        $def = new Definition('stdClass');
        $this->assertFalse($def->isLazy(), '->isLazy() returns false by default');
        $this->assertSame($def, $def->setLazy(true), '->setLazy() implements a fluent interface');
        $this->assertTrue($def->isLazy(), '->isLazy() returns true if the service is lazy.');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Definition::setAbstract
     * @covers Symfony\Component\DependencyInjection\Definition::isAbstract
     */
    public function testSetIsAbstract()
    {
        $def = new Definition('stdClass');
        $this->assertFalse($def->isAbstract(), '->isAbstract() returns false by default');
        $this->assertSame($def, $def->setAbstract(true), '->setAbstract() implements a fluent interface');
        $this->assertTrue($def->isAbstract(), '->isAbstract() returns true if the instance must not be public.');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Definition::setConfigurator
     * @covers Symfony\Component\DependencyInjection\Definition::getConfigurator
     */
    public function testSetGetConfigurator()
    {
        $def = new Definition('stdClass');
        $this->assertSame($def, $def->setConfigurator('foo'), '->setConfigurator() implements a fluent interface');
        $this->assertEquals('foo', $def->getConfigurator(), '->getConfigurator() returns the configurator');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Definition::clearTags
     */
    public function testClearTags()
    {
        $def = new Definition('stdClass');
        $this->assertSame($def, $def->clearTags(), '->clearTags() implements a fluent interface');
        $def->addTag('foo', array('foo' => 'bar'));
        $def->clearTags();
        $this->assertEquals(array(), $def->getTags(), '->clearTags() removes all current tags');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Definition::clearTags
     */
    public function testClearTag()
    {
        $def = new Definition('stdClass');
        $this->assertSame($def, $def->clearTags(), '->clearTags() implements a fluent interface');
        $def->addTag('1foo1', array('foo1' => 'bar1'));
        $def->addTag('2foo2', array('foo2' => 'bar2'));
        $def->addTag('3foo3', array('foo3' => 'bar3'));
        $def->clearTag('2foo2');
        $this->assertTrue($def->hasTag('1foo1'));
        $this->assertFalse($def->hasTag('2foo2'));
        $this->assertTrue($def->hasTag('3foo3'));
        $def->clearTag('1foo1');
        $this->assertFalse($def->hasTag('1foo1'));
        $this->assertTrue($def->hasTag('3foo3'));
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Definition::addTag
     * @covers Symfony\Component\DependencyInjection\Definition::getTag
     * @covers Symfony\Component\DependencyInjection\Definition::getTags
     * @covers Symfony\Component\DependencyInjection\Definition::hasTag
     */
    public function testTags()
    {
        $def = new Definition('stdClass');
        $this->assertEquals(array(), $def->getTag('foo'), '->getTag() returns an empty array if the tag is not defined');
        $this->assertFalse($def->hasTag('foo'));
        $this->assertSame($def, $def->addTag('foo'), '->addTag() implements a fluent interface');
        $this->assertTrue($def->hasTag('foo'));
        $this->assertEquals(array(array()), $def->getTag('foo'), '->getTag() returns attributes for a tag name');
        $def->addTag('foo', array('foo' => 'bar'));
        $this->assertEquals(array(array(), array('foo' => 'bar')), $def->getTag('foo'), '->addTag() can adds the same tag several times');
        $def->addTag('bar', array('bar' => 'bar'));
        $this->assertEquals($def->getTags(), array(
            'foo' => array(array(), array('foo' => 'bar')),
            'bar' => array(array('bar' => 'bar')),
        ), '->getTags() returns all tags');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Definition::replaceArgument
     */
    public function testSetArgument()
    {
        $def = new Definition('stdClass');

        $def->addArgument('foo');
        $this->assertSame(array('foo'), $def->getArguments());

        $this->assertSame($def, $def->replaceArgument(0, 'moo'));
        $this->assertSame(array('moo'), $def->getArguments());

        $def->addArgument('moo');
        $def
            ->replaceArgument(0, 'foo')
            ->replaceArgument(1, 'bar')
        ;
        $this->assertSame(array('foo', 'bar'), $def->getArguments());
    }

    /**
     * @expectedException \OutOfBoundsException
     */
    public function testGetArgumentShouldCheckBounds()
    {
        $def = new Definition('stdClass');

        $def->addArgument('foo');
        $def->getArgument(1);
    }

    /**
     * @expectedException \OutOfBoundsException
     */
    public function testReplaceArgumentShouldCheckBounds()
    {
        $def = new Definition('stdClass');

        $def->addArgument('foo');
        $def->replaceArgument(1, 'bar');
    }

    public function testSetGetProperties()
    {
        $def = new Definition('stdClass');

        $this->assertEquals(array(), $def->getProperties());
        $this->assertSame($def, $def->setProperties(array('foo' => 'bar')));
        $this->assertEquals(array('foo' => 'bar'), $def->getProperties());
    }

    public function testSetProperty()
    {
        $def = new Definition('stdClass');

        $this->assertEquals(array(), $def->getProperties());
        $this->assertSame($def, $def->setProperty('foo', 'bar'));
        $this->assertEquals(array('foo' => 'bar'), $def->getProperties());
    }
}
PK��Z+��E�
�
`test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/DefinitionDecoratorTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests;

use Symfony\Component\DependencyInjection\DefinitionDecorator;

class DefinitionDecoratorTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $def = new DefinitionDecorator('foo');

        $this->assertEquals('foo', $def->getParent());
        $this->assertEquals(array(), $def->getChanges());
    }

    /**
     * @dataProvider getPropertyTests
     */
    public function testSetProperty($property, $changeKey)
    {
        $def = new DefinitionDecorator('foo');

        $getter = 'get'.ucfirst($property);
        $setter = 'set'.ucfirst($property);

        $this->assertNull($def->$getter());
        $this->assertSame($def, $def->$setter('foo'));
        $this->assertEquals('foo', $def->$getter());
        $this->assertEquals(array($changeKey => true), $def->getChanges());
    }

    public function getPropertyTests()
    {
        return array(
            array('class', 'class'),
            array('factoryClass', 'factory_class'),
            array('factoryMethod', 'factory_method'),
            array('factoryService', 'factory_service'),
            array('configurator', 'configurator'),
            array('file', 'file'),
        );
    }

    public function testSetPublic()
    {
        $def = new DefinitionDecorator('foo');

        $this->assertTrue($def->isPublic());
        $this->assertSame($def, $def->setPublic(false));
        $this->assertFalse($def->isPublic());
        $this->assertEquals(array('public' => true), $def->getChanges());
    }

    public function testSetLazy()
    {
        $def = new DefinitionDecorator('foo');

        $this->assertFalse($def->isLazy());
        $this->assertSame($def, $def->setLazy(false));
        $this->assertFalse($def->isLazy());
        $this->assertEquals(array('lazy' => true), $def->getChanges());
    }

    public function testSetArgument()
    {
        $def = new DefinitionDecorator('foo');

        $this->assertEquals(array(), $def->getArguments());
        $this->assertSame($def, $def->replaceArgument(0, 'foo'));
        $this->assertEquals(array('index_0' => 'foo'), $def->getArguments());
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testReplaceArgumentShouldRequireIntegerIndex()
    {
        $def = new DefinitionDecorator('foo');

        $def->replaceArgument('0', 'foo');
    }

    public function testReplaceArgument()
    {
        $def = new DefinitionDecorator('foo');

        $def->setArguments(array(0 => 'foo', 1 => 'bar'));
        $this->assertEquals('foo', $def->getArgument(0));
        $this->assertEquals('bar', $def->getArgument(1));

        $this->assertSame($def, $def->replaceArgument(1, 'baz'));
        $this->assertEquals('foo', $def->getArgument(0));
        $this->assertEquals('baz', $def->getArgument(1));

        $this->assertEquals(array(0 => 'foo', 1 => 'bar', 'index_1' => 'baz'), $def->getArguments());
    }

    /**
     * @expectedException \OutOfBoundsException
     */
    public function testGetArgumentShouldCheckBounds()
    {
        $def = new DefinitionDecorator('foo');

        $def->setArguments(array(0 => 'foo'));
        $def->replaceArgument(0, 'foo');

        $def->getArgument(1);
    }
}
PK��Z�K5��W�WVtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/ContainerTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests;

use Symfony\Component\DependencyInjection\Scope;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;

class ContainerTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Symfony\Component\DependencyInjection\Container::__construct
     */
    public function testConstructor()
    {
        $sc = new Container();
        $this->assertSame($sc, $sc->get('service_container'), '__construct() automatically registers itself as a service');

        $sc = new Container(new ParameterBag(array('foo' => 'bar')));
        $this->assertEquals(array('foo' => 'bar'), $sc->getParameterBag()->all(), '__construct() takes an array of parameters as its first argument');
    }

    /**
     * @dataProvider dataForTestCamelize
     */
    public function testCamelize($id, $expected)
    {
        $this->assertEquals($expected, Container::camelize($id), sprintf('Container::camelize("%s")', $id));
    }

    public function dataForTestCamelize()
    {
        return array(
            array('foo_bar', 'FooBar'),
            array('foo.bar', 'Foo_Bar'),
            array('foo.bar_baz', 'Foo_BarBaz'),
            array('foo._bar', 'Foo_Bar'),
            array('foo_.bar', 'Foo_Bar'),
            array('_foo', 'Foo'),
            array('.foo', '_Foo'),
            array('foo_', 'Foo'),
            array('foo.', 'Foo_'),
            array('foo\bar', 'Foo_Bar'),
        );
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Container::compile
     */
    public function testCompile()
    {
        $sc = new Container(new ParameterBag(array('foo' => 'bar')));
        $sc->compile();
        $this->assertInstanceOf('Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag', $sc->getParameterBag(), '->compile() changes the parameter bag to a FrozenParameterBag instance');
        $this->assertEquals(array('foo' => 'bar'), $sc->getParameterBag()->all(), '->compile() copies the current parameters to the new parameter bag');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Container::isFrozen
     */
    public function testIsFrozen()
    {
        $sc = new Container(new ParameterBag(array('foo' => 'bar')));
        $this->assertFalse($sc->isFrozen(), '->isFrozen() returns false if the parameters are not frozen');
        $sc->compile();
        $this->assertTrue($sc->isFrozen(), '->isFrozen() returns true if the parameters are frozen');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Container::getParameterBag
     */
    public function testGetParameterBag()
    {
        $sc = new Container();
        $this->assertEquals(array(), $sc->getParameterBag()->all(), '->getParameterBag() returns an empty array if no parameter has been defined');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Container::setParameter
     * @covers Symfony\Component\DependencyInjection\Container::getParameter
     */
    public function testGetSetParameter()
    {
        $sc = new Container(new ParameterBag(array('foo' => 'bar')));
        $sc->setParameter('bar', 'foo');
        $this->assertEquals('foo', $sc->getParameter('bar'), '->setParameter() sets the value of a new parameter');

        $sc->setParameter('foo', 'baz');
        $this->assertEquals('baz', $sc->getParameter('foo'), '->setParameter() overrides previously set parameter');

        $sc->setParameter('Foo', 'baz1');
        $this->assertEquals('baz1', $sc->getParameter('foo'), '->setParameter() converts the key to lowercase');
        $this->assertEquals('baz1', $sc->getParameter('FOO'), '->getParameter() converts the key to lowercase');

        try {
            $sc->getParameter('baba');
            $this->fail('->getParameter() thrown an \InvalidArgumentException if the key does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->getParameter() thrown an \InvalidArgumentException if the key does not exist');
            $this->assertEquals('You have requested a non-existent parameter "baba".', $e->getMessage(), '->getParameter() thrown an \InvalidArgumentException if the key does not exist');
        }
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Container::getServiceIds
     */
    public function testGetServiceIds()
    {
        $sc = new Container();
        $sc->set('foo', $obj = new \stdClass());
        $sc->set('bar', $obj = new \stdClass());
        $this->assertEquals(array('service_container', 'foo', 'bar'), $sc->getServiceIds(), '->getServiceIds() returns all defined service ids');

        $sc = new ProjectServiceContainer();
        $this->assertEquals(array('scoped', 'scoped_foo', 'inactive', 'bar', 'foo_bar', 'foo.baz', 'circular', 'throw_exception', 'throws_exception_on_service_configuration', 'service_container'), $sc->getServiceIds(), '->getServiceIds() returns defined service ids by getXXXService() methods');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Container::set
     */
    public function testSet()
    {
        $sc = new Container();
        $sc->set('foo', $foo = new \stdClass());
        $this->assertEquals($foo, $sc->get('foo'), '->set() sets a service');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Container::set
     */
    public function testSetWithNullResetTheService()
    {
        $sc = new Container();
        $sc->set('foo', null);
        $this->assertFalse($sc->has('foo'));
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testSetDoesNotAllowPrototypeScope()
    {
        $c = new Container();
        $c->set('foo', new \stdClass(), 'prototype');
    }

    /**
     * @expectedException \RuntimeException
     */
    public function testSetDoesNotAllowInactiveScope()
    {
        $c = new Container();
        $c->addScope(new Scope('foo'));
        $c->set('foo', new \stdClass(), 'foo');
    }

    public function testSetAlsoSetsScopedService()
    {
        $c = new Container();
        $c->addScope(new Scope('foo'));
        $c->enterScope('foo');
        $c->set('foo', $foo = new \stdClass(), 'foo');

        $services = $this->getField($c, 'scopedServices');
        $this->assertTrue(isset($services['foo']['foo']));
        $this->assertSame($foo, $services['foo']['foo']);
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Container::get
     */
    public function testGet()
    {
        $sc = new ProjectServiceContainer();
        $sc->set('foo', $foo = new \stdClass());
        $this->assertEquals($foo, $sc->get('foo'), '->get() returns the service for the given id');
        $this->assertEquals($sc->__bar, $sc->get('bar'), '->get() returns the service for the given id');
        $this->assertEquals($sc->__foo_bar, $sc->get('foo_bar'), '->get() returns the service if a get*Method() is defined');
        $this->assertEquals($sc->__foo_baz, $sc->get('foo.baz'), '->get() returns the service if a get*Method() is defined');
        $this->assertEquals($sc->__foo_baz, $sc->get('foo\\baz'), '->get() returns the service if a get*Method() is defined');

        $sc->set('bar', $bar = new \stdClass());
        $this->assertEquals($bar, $sc->get('bar'), '->get() prefers to return a service defined with set() than one defined with a getXXXMethod()');

        try {
            $sc->get('');
            $this->fail('->get() throws a \InvalidArgumentException exception if the service is empty');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException', $e, '->get() throws a ServiceNotFoundException exception if the service is empty');
        }
        $this->assertNull($sc->get('', ContainerInterface::NULL_ON_INVALID_REFERENCE));
    }

    public function testGetThrowServiceNotFoundException()
    {
        $sc = new ProjectServiceContainer();
        $sc->set('foo', $foo = new \stdClass());
        $sc->set('bar', $foo = new \stdClass());
        $sc->set('baz', $foo = new \stdClass());

        try {
            $sc->get('foo1');
            $this->fail('->get() throws an Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException if the key does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException', $e, '->get() throws an Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException if the key does not exist');
            $this->assertEquals('You have requested a non-existent service "foo1". Did you mean this: "foo"?', $e->getMessage(), '->get() throws an Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException with some advices');
        }

        try {
            $sc->get('bag');
            $this->fail('->get() throws an Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException if the key does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException', $e, '->get() throws an Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException if the key does not exist');
            $this->assertEquals('You have requested a non-existent service "bag". Did you mean one of these: "bar", "baz"?', $e->getMessage(), '->get() throws an Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException with some advices');
        }
    }

    public function testGetCircularReference()
    {

        $sc = new ProjectServiceContainer();
        try {
            $sc->get('circular');
            $this->fail('->get() throws a ServiceCircularReferenceException if it contains circular reference');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException', $e, '->get() throws a ServiceCircularReferenceException if it contains circular reference');
            $this->assertStringStartsWith('Circular reference detected for service "circular"', $e->getMessage(), '->get() throws a \LogicException if it contains circular reference');
        }
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Container::get
     */
    public function testGetReturnsNullOnInactiveScope()
    {
        $sc = new ProjectServiceContainer();
        $this->assertNull($sc->get('inactive', ContainerInterface::NULL_ON_INVALID_REFERENCE));
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Container::has
     */
    public function testHas()
    {
        $sc = new ProjectServiceContainer();
        $sc->set('foo', new \stdClass());
        $this->assertFalse($sc->has('foo1'), '->has() returns false if the service does not exist');
        $this->assertTrue($sc->has('foo'), '->has() returns true if the service exists');
        $this->assertTrue($sc->has('bar'), '->has() returns true if a get*Method() is defined');
        $this->assertTrue($sc->has('foo_bar'), '->has() returns true if a get*Method() is defined');
        $this->assertTrue($sc->has('foo.baz'), '->has() returns true if a get*Method() is defined');
        $this->assertTrue($sc->has('foo\\baz'), '->has() returns true if a get*Method() is defined');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Container::initialized
     */
    public function testInitialized()
    {
        $sc = new ProjectServiceContainer();
        $sc->set('foo', new \stdClass());
        $this->assertTrue($sc->initialized('foo'), '->initialized() returns true if service is loaded');
        $this->assertFalse($sc->initialized('foo1'), '->initialized() returns false if service is not loaded');
        $this->assertFalse($sc->initialized('bar'), '->initialized() returns false if a service is defined, but not currently loaded');
    }

    public function testEnterLeaveCurrentScope()
    {
        $container = new ProjectServiceContainer();
        $container->addScope(new Scope('foo'));

        $container->enterScope('foo');
        $scoped1 = $container->get('scoped');
        $scopedFoo1 = $container->get('scoped_foo');

        $container->enterScope('foo');
        $scoped2 = $container->get('scoped');
        $scoped3 = $container->get('scoped');
        $scopedFoo2 = $container->get('scoped_foo');

        $container->leaveScope('foo');
        $scoped4 = $container->get('scoped');
        $scopedFoo3 = $container->get('scoped_foo');

        $this->assertNotSame($scoped1, $scoped2);
        $this->assertSame($scoped2, $scoped3);
        $this->assertSame($scoped1, $scoped4);
        $this->assertNotSame($scopedFoo1, $scopedFoo2);
        $this->assertSame($scopedFoo1, $scopedFoo3);
    }

    public function testEnterLeaveScopeWithChildScopes()
    {
        $container = new Container();
        $container->addScope(new Scope('foo'));
        $container->addScope(new Scope('bar', 'foo'));

        $this->assertFalse($container->isScopeActive('foo'));

        $container->enterScope('foo');
        $container->enterScope('bar');

        $this->assertTrue($container->isScopeActive('foo'));
        $this->assertFalse($container->has('a'));

        $a = new \stdClass();
        $container->set('a', $a, 'bar');

        $services = $this->getField($container, 'scopedServices');
        $this->assertTrue(isset($services['bar']['a']));
        $this->assertSame($a, $services['bar']['a']);

        $this->assertTrue($container->has('a'));
        $container->leaveScope('foo');

        $services = $this->getField($container, 'scopedServices');
        $this->assertFalse(isset($services['bar']));

        $this->assertFalse($container->isScopeActive('foo'));
        $this->assertFalse($container->has('a'));
    }

    public function testEnterScopeRecursivelyWithInactiveChildScopes()
    {
        $container = new Container();
        $container->addScope(new Scope('foo'));
        $container->addScope(new Scope('bar', 'foo'));

        $this->assertFalse($container->isScopeActive('foo'));

        $container->enterScope('foo');

        $this->assertTrue($container->isScopeActive('foo'));
        $this->assertFalse($container->isScopeActive('bar'));
        $this->assertFalse($container->has('a'));

        $a = new \stdClass();
        $container->set('a', $a, 'foo');

        $services = $this->getField($container, 'scopedServices');
        $this->assertTrue(isset($services['foo']['a']));
        $this->assertSame($a, $services['foo']['a']);

        $this->assertTrue($container->has('a'));
        $container->enterScope('foo');

        $services = $this->getField($container, 'scopedServices');
        $this->assertFalse(isset($services['a']));

        $this->assertTrue($container->isScopeActive('foo'));
        $this->assertFalse($container->isScopeActive('bar'));
        $this->assertFalse($container->has('a'));
    }

    public function testLeaveScopeNotActive()
    {
        $container = new Container();
        $container->addScope(new Scope('foo'));

        try {
            $container->leaveScope('foo');
            $this->fail('->leaveScope() throws a \LogicException if the scope is not active yet');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\LogicException', $e, '->leaveScope() throws a \LogicException if the scope is not active yet');
            $this->assertEquals('The scope "foo" is not active.', $e->getMessage(), '->leaveScope() throws a \LogicException if the scope is not active yet');
        }

        try {
            $container->leaveScope('bar');
            $this->fail('->leaveScope() throws a \LogicException if the scope does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\LogicException', $e, '->leaveScope() throws a \LogicException if the scope does not exist');
            $this->assertEquals('The scope "bar" is not active.', $e->getMessage(), '->leaveScope() throws a \LogicException if the scope does not exist');
        }
    }

    /**
     * @expectedException \InvalidArgumentException
     * @dataProvider getBuiltInScopes
     */
    public function testAddScopeDoesNotAllowBuiltInScopes($scope)
    {
        $container = new Container();
        $container->addScope(new Scope($scope));
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testAddScopeDoesNotAllowExistingScope()
    {
        $container = new Container();
        $container->addScope(new Scope('foo'));
        $container->addScope(new Scope('foo'));
    }

    /**
     * @expectedException \InvalidArgumentException
     * @dataProvider getInvalidParentScopes
     */
    public function testAddScopeDoesNotAllowInvalidParentScope($scope)
    {
        $c = new Container();
        $c->addScope(new Scope('foo', $scope));
    }

    public function testAddScope()
    {
        $c = new Container();
        $c->addScope(new Scope('foo'));
        $c->addScope(new Scope('bar', 'foo'));

        $this->assertSame(array('foo' => 'container', 'bar' => 'foo'), $this->getField($c, 'scopes'));
        $this->assertSame(array('foo' => array('bar'), 'bar' => array()), $this->getField($c, 'scopeChildren'));
    }

    public function testHasScope()
    {
        $c = new Container();

        $this->assertFalse($c->hasScope('foo'));
        $c->addScope(new Scope('foo'));
        $this->assertTrue($c->hasScope('foo'));
    }

    public function testIsScopeActive()
    {
        $c = new Container();

        $this->assertFalse($c->isScopeActive('foo'));
        $c->addScope(new Scope('foo'));

        $this->assertFalse($c->isScopeActive('foo'));
        $c->enterScope('foo');

        $this->assertTrue($c->isScopeActive('foo'));
        $c->leaveScope('foo');

        $this->assertFalse($c->isScopeActive('foo'));
    }

    public function testGetThrowsException()
    {
        $c = new ProjectServiceContainer();

        try {
            $c->get('throw_exception');
            $this->fail();
        } catch (\Exception $e) {
            $this->assertEquals('Something went terribly wrong!', $e->getMessage());
        }

        try {
            $c->get('throw_exception');
            $this->fail();
        } catch (\Exception $e) {
            $this->assertEquals('Something went terribly wrong!', $e->getMessage());
        }
    }

    public function testGetThrowsExceptionOnServiceConfiguration()
    {
        $c = new ProjectServiceContainer();

        try {
            $c->get('throws_exception_on_service_configuration');
            $this->fail('The container can not contain invalid service!');
        } catch (\Exception $e) {
            $this->assertEquals('Something was terribly wrong while trying to configure the service!', $e->getMessage());
        }
        $this->assertFalse($c->initialized('throws_exception_on_service_configuration'));

        try {
            $c->get('throws_exception_on_service_configuration');
            $this->fail('The container can not contain invalid service!');
        } catch (\Exception $e) {
            $this->assertEquals('Something was terribly wrong while trying to configure the service!', $e->getMessage());
        }
        $this->assertFalse($c->initialized('throws_exception_on_service_configuration'));
    }

    public function getInvalidParentScopes()
    {
        return array(
            array(ContainerInterface::SCOPE_PROTOTYPE),
            array('bar'),
        );
    }

    public function getBuiltInScopes()
    {
        return array(
            array(ContainerInterface::SCOPE_CONTAINER),
            array(ContainerInterface::SCOPE_PROTOTYPE),
        );
    }

    protected function getField($obj, $field)
    {
        $reflection = new \ReflectionProperty($obj, $field);
        $reflection->setAccessible(true);

        return $reflection->getValue($obj);
    }

    public function testAlias()
    {
        $c = new ProjectServiceContainer();

        $this->assertTrue($c->has('alias'));
        $this->assertSame($c->get('alias'), $c->get('bar'));
    }
}

class ProjectServiceContainer extends Container
{
    public $__bar, $__foo_bar, $__foo_baz;

    public function __construct()
    {
        parent::__construct();

        $this->__bar = new \stdClass();
        $this->__foo_bar = new \stdClass();
        $this->__foo_baz = new \stdClass();
        $this->aliases = array('alias' => 'bar');
    }

    protected function getScopedService()
    {
        if (!isset($this->scopedServices['foo'])) {
            throw new \RuntimeException('Invalid call');
        }

        return $this->services['scoped'] = $this->scopedServices['foo']['scoped'] = new \stdClass();
    }

    protected function getScopedFooService()
    {
        if (!isset($this->scopedServices['foo'])) {
            throw new \RuntimeException('invalid call');
        }

        return $this->services['scoped_foo'] = $this->scopedServices['foo']['scoped_foo'] = new \stdClass();
    }

    protected function getInactiveService()
    {
        throw new InactiveScopeException('request', 'request');
    }

    protected function getBarService()
    {
        return $this->__bar;
    }

    protected function getFooBarService()
    {
        return $this->__foo_bar;
    }

    protected function getFoo_BazService()
    {
        return $this->__foo_baz;
    }

    protected function getCircularService()
    {
        return $this->get('circular');
    }

    protected function getThrowExceptionService()
    {
        throw new \Exception('Something went terribly wrong!');
    }

    protected function getThrowsExceptionOnServiceConfigurationService()
    {
        $this->services['throws_exception_on_service_configuration'] = $instance = new \stdClass();

        throw new \Exception('Something was terribly wrong while trying to configure the service!');
    }
}
PK��Z`��=�	�	`test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Extension/ExtensionTest.phpnu�[���<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Extension;

class ExtensionTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getResolvedEnabledFixtures
     */
    public function testIsConfigEnabledReturnsTheResolvedValue($enabled)
    {
        $pb = $this->getMockBuilder('Symfony\Component\DependencyInjection\ParameterBag\ParameterBag')
            ->setMethods(array('resolveValue'))
            ->getMock()
        ;

        $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')
            ->setMethods(array('getParameterBag'))
            ->getMock()
        ;

        $pb->expects($this->once())
            ->method('resolveValue')
            ->with($this->equalTo($enabled))
            ->will($this->returnValue($enabled))
        ;

        $container->expects($this->once())
            ->method('getParameterBag')
            ->will($this->returnValue($pb))
        ;

        $extension = $this->getMockBuilder('Symfony\Component\DependencyInjection\Extension\Extension')
            ->setMethods(array())
            ->getMockForAbstractClass()
        ;

        $r = new \ReflectionMethod('Symfony\Component\DependencyInjection\Extension\Extension', 'isConfigEnabled');
        $r->setAccessible(true);

        $r->invoke($extension, $container, array('enabled' => $enabled));
    }

    public function getResolvedEnabledFixtures()
    {
        return array(
            array(true),
            array(false)
        );
    }

    /**
     * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
     * @expectedExceptionMessage The config array has no 'enabled' key.
     */
    public function testIsConfigEnabledOnNonEnableableConfig()
    {
        $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')
            ->getMock()
        ;

        $extension = $this->getMockBuilder('Symfony\Component\DependencyInjection\Extension\Extension')
            ->setMethods(array())
            ->getMockForAbstractClass()
        ;

        $r = new \ReflectionMethod('Symfony\Component\DependencyInjection\Extension\Extension', 'isConfigEnabled');
        $r->setAccessible(true);

        $r->invoke($extension, $container, array());
    }
}
PK��Z���uuOtest/DependencyInjection/Symfony/Component/DependencyInjection/phpunit.xml.distnu�[���<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony DependencyInjection Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./Resources</directory>
                <directory>./Tests</directory>
                <directory>./vendor</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
PK��Z�'7,����PEAR.phpnu�[���<?php
/**
 * PEAR, the PHP Extension and Application Repository
 *
 * PEAR class and PEAR_Error class
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Sterling Hughes <sterling@php.net>
 * @author     Stig Bakken <ssb@php.net>
 * @author     Tomas V.V.Cox <cox@idecnet.com>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2010 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 0.1
 */

/**#@+
 * ERROR constants
 */
define('PEAR_ERROR_RETURN',     1);
define('PEAR_ERROR_PRINT',      2);
define('PEAR_ERROR_TRIGGER',    4);
define('PEAR_ERROR_DIE',        8);
define('PEAR_ERROR_CALLBACK',  16);
/**
 * WARNING: obsolete
 * @deprecated
 */
define('PEAR_ERROR_EXCEPTION', 32);
/**#@-*/

if (substr(PHP_OS, 0, 3) == 'WIN') {
    define('OS_WINDOWS', true);
    define('OS_UNIX',    false);
    define('PEAR_OS',    'Windows');
} else {
    define('OS_WINDOWS', false);
    define('OS_UNIX',    true);
    define('PEAR_OS',    'Unix'); // blatant assumption
}

$GLOBALS['_PEAR_default_error_mode']     = PEAR_ERROR_RETURN;
$GLOBALS['_PEAR_default_error_options']  = E_USER_NOTICE;
$GLOBALS['_PEAR_destructor_object_list'] = array();
$GLOBALS['_PEAR_shutdown_funcs']         = array();
$GLOBALS['_PEAR_error_handler_stack']    = array();

if(function_exists('ini_set')) {
    @ini_set('track_errors', true);
}

/**
 * Base class for other PEAR classes.  Provides rudimentary
 * emulation of destructors.
 *
 * If you want a destructor in your class, inherit PEAR and make a
 * destructor method called _yourclassname (same name as the
 * constructor, but with a "_" prefix).  Also, in your constructor you
 * have to call the PEAR constructor: $this->PEAR();.
 * The destructor method will be called without parameters.  Note that
 * at in some SAPI implementations (such as Apache), any output during
 * the request shutdown (in which destructors are called) seems to be
 * discarded.  If you need to get any debug information from your
 * destructor, use error_log(), syslog() or something similar.
 *
 * IMPORTANT! To use the emulated destructors you need to create the
 * objects by reference: $obj =& new PEAR_child;
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Tomas V.V. Cox <cox@idecnet.com>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2006 The PHP Group
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/package/PEAR
 * @see        PEAR_Error
 * @since      Class available since PHP 4.0.2
 * @link        http://pear.php.net/manual/en/core.pear.php#core.pear.pear
 */
class PEAR
{
    /**
     * Whether to enable internal debug messages.
     *
     * @var     bool
     * @access  private
     */
    var $_debug = false;

    /**
     * Default error mode for this object.
     *
     * @var     int
     * @access  private
     */
    var $_default_error_mode = null;

    /**
     * Default error options used for this object when error mode
     * is PEAR_ERROR_TRIGGER.
     *
     * @var     int
     * @access  private
     */
    var $_default_error_options = null;

    /**
     * Default error handler (callback) for this object, if error mode is
     * PEAR_ERROR_CALLBACK.
     *
     * @var     string
     * @access  private
     */
    var $_default_error_handler = '';

    /**
     * Which class to use for error objects.
     *
     * @var     string
     * @access  private
     */
    var $_error_class = 'PEAR_Error';

    /**
     * An array of expected errors.
     *
     * @var     array
     * @access  private
     */
    var $_expected_errors = array();

    /**
     * List of methods that can be called both statically and non-statically.
     * @var array
     */
    protected static $bivalentMethods = array(
        'setErrorHandling' => true,
        'raiseError' => true,
        'throwError' => true,
        'pushErrorHandling' => true,
        'popErrorHandling' => true,
    );

    /**
     * Constructor.  Registers this object in
     * $_PEAR_destructor_object_list for destructor emulation if a
     * destructor object exists.
     *
     * @param string $error_class  (optional) which class to use for
     *        error objects, defaults to PEAR_Error.
     * @access public
     * @return void
     */
    function __construct($error_class = null)
    {
        $classname = strtolower(get_class($this));
        if ($this->_debug) {
            print "PEAR constructor called, class=$classname\n";
        }

        if ($error_class !== null) {
            $this->_error_class = $error_class;
        }

        while ($classname && strcasecmp($classname, "pear")) {
            $destructor = "_$classname";
            if (method_exists($this, $destructor)) {
                global $_PEAR_destructor_object_list;
                $_PEAR_destructor_object_list[] = $this;
                if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
                    register_shutdown_function("_PEAR_call_destructors");
                    $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
                }
                break;
            } else {
                $classname = get_parent_class($classname);
            }
        }
    }

    /**
     * Only here for backwards compatibility.
     * E.g. Archive_Tar calls $this->PEAR() in its constructor.
     *
     * @param string $error_class Which class to use for error objects,
     *                            defaults to PEAR_Error.
     */
    public function PEAR($error_class = null)
    {
        self::__construct($error_class);
    }

    /**
     * Destructor (the emulated type of...).  Does nothing right now,
     * but is included for forward compatibility, so subclass
     * destructors should always call it.
     *
     * See the note in the class desciption about output from
     * destructors.
     *
     * @access public
     * @return void
     */
    function _PEAR() {
        if ($this->_debug) {
            printf("PEAR destructor called, class=%s\n", strtolower(get_class($this)));
        }
    }

    public function __call($method, $arguments)
    {
        if (!isset(self::$bivalentMethods[$method])) {
            trigger_error(
                'Call to undefined method PEAR::' . $method . '()', E_USER_ERROR
            );
        }
        return call_user_func_array(
            array(__CLASS__, '_' . $method),
            array_merge(array($this), $arguments)
        );
    }

    public static function __callStatic($method, $arguments)
    {
        if (!isset(self::$bivalentMethods[$method])) {
            trigger_error(
                'Call to undefined method PEAR::' . $method . '()', E_USER_ERROR
            );
        }
        return call_user_func_array(
            array(__CLASS__, '_' . $method),
            array_merge(array(null), $arguments)
        );
    }

    /**
    * If you have a class that's mostly/entirely static, and you need static
    * properties, you can use this method to simulate them. Eg. in your method(s)
    * do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar');
    * You MUST use a reference, or they will not persist!
    *
    * @param  string $class  The calling classname, to prevent clashes
    * @param  string $var    The variable to retrieve.
    * @return mixed   A reference to the variable. If not set it will be
    *                 auto initialised to NULL.
    */
    public static function &getStaticProperty($class, $var)
    {
        static $properties;
        if (!isset($properties[$class])) {
            $properties[$class] = array();
        }

        if (!array_key_exists($var, $properties[$class])) {
            $properties[$class][$var] = null;
        }

        return $properties[$class][$var];
    }

    /**
    * Use this function to register a shutdown method for static
    * classes.
    *
    * @param  mixed $func  The function name (or array of class/method) to call
    * @param  mixed $args  The arguments to pass to the function
    *
    * @return void
    */
    public static function registerShutdownFunc($func, $args = array())
    {
        // if we are called statically, there is a potential
        // that no shutdown func is registered.  Bug #6445
        if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
            register_shutdown_function("_PEAR_call_destructors");
            $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
        }
        $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args);
    }

    /**
     * Tell whether a value is a PEAR error.
     *
     * @param   mixed $data   the value to test
     * @param   int   $code   if $data is an error object, return true
     *                        only if $code is a string and
     *                        $obj->getMessage() == $code or
     *                        $code is an integer and $obj->getCode() == $code
     *
     * @return  bool    true if parameter is an error
     */
    public static function isError($data, $code = null)
    {
        if (!is_a($data, 'PEAR_Error')) {
            return false;
        }

        if (is_null($code)) {
            return true;
        } elseif (is_string($code)) {
            return $data->getMessage() == $code;
        }

        return $data->getCode() == $code;
    }

    /**
     * Sets how errors generated by this object should be handled.
     * Can be invoked both in objects and statically.  If called
     * statically, setErrorHandling sets the default behaviour for all
     * PEAR objects.  If called in an object, setErrorHandling sets
     * the default behaviour for that object.
     *
     * @param object $object
     *        Object the method was called on (non-static mode)
     *
     * @param int $mode
     *        One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
     *        PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
     *        PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION.
     *
     * @param mixed $options
     *        When $mode is PEAR_ERROR_TRIGGER, this is the error level (one
     *        of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
     *
     *        When $mode is PEAR_ERROR_CALLBACK, this parameter is expected
     *        to be the callback function or method.  A callback
     *        function is a string with the name of the function, a
     *        callback method is an array of two elements: the element
     *        at index 0 is the object, and the element at index 1 is
     *        the name of the method to call in the object.
     *
     *        When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is
     *        a printf format string used when printing the error
     *        message.
     *
     * @access public
     * @return void
     * @see PEAR_ERROR_RETURN
     * @see PEAR_ERROR_PRINT
     * @see PEAR_ERROR_TRIGGER
     * @see PEAR_ERROR_DIE
     * @see PEAR_ERROR_CALLBACK
     * @see PEAR_ERROR_EXCEPTION
     *
     * @since PHP 4.0.5
     */
    protected static function _setErrorHandling(
        $object, $mode = null, $options = null
    ) {
        if ($object !== null) {
            $setmode     = &$object->_default_error_mode;
            $setoptions  = &$object->_default_error_options;
        } else {
            $setmode     = &$GLOBALS['_PEAR_default_error_mode'];
            $setoptions  = &$GLOBALS['_PEAR_default_error_options'];
        }

        switch ($mode) {
            case PEAR_ERROR_EXCEPTION:
            case PEAR_ERROR_RETURN:
            case PEAR_ERROR_PRINT:
            case PEAR_ERROR_TRIGGER:
            case PEAR_ERROR_DIE:
            case null:
                $setmode = $mode;
                $setoptions = $options;
                break;

            case PEAR_ERROR_CALLBACK:
                $setmode = $mode;
                // class/object method callback
                if (is_callable($options)) {
                    $setoptions = $options;
                } else {
                    trigger_error("invalid error callback", E_USER_WARNING);
                }
                break;

            default:
                trigger_error("invalid error mode", E_USER_WARNING);
                break;
        }
    }

    /**
     * This method is used to tell which errors you expect to get.
     * Expected errors are always returned with error mode
     * PEAR_ERROR_RETURN.  Expected error codes are stored in a stack,
     * and this method pushes a new element onto it.  The list of
     * expected errors are in effect until they are popped off the
     * stack with the popExpect() method.
     *
     * Note that this method can not be called statically
     *
     * @param mixed $code a single error code or an array of error codes to expect
     *
     * @return int     the new depth of the "expected errors" stack
     * @access public
     */
    function expectError($code = '*')
    {
        if (is_array($code)) {
            array_push($this->_expected_errors, $code);
        } else {
            array_push($this->_expected_errors, array($code));
        }
        return count($this->_expected_errors);
    }

    /**
     * This method pops one element off the expected error codes
     * stack.
     *
     * @return array   the list of error codes that were popped
     */
    function popExpect()
    {
        return array_pop($this->_expected_errors);
    }

    /**
     * This method checks unsets an error code if available
     *
     * @param mixed error code
     * @return bool true if the error code was unset, false otherwise
     * @access private
     * @since PHP 4.3.0
     */
    function _checkDelExpect($error_code)
    {
        $deleted = false;
        foreach ($this->_expected_errors as $key => $error_array) {
            if (in_array($error_code, $error_array)) {
                unset($this->_expected_errors[$key][array_search($error_code, $error_array)]);
                $deleted = true;
            }

            // clean up empty arrays
            if (0 == count($this->_expected_errors[$key])) {
                unset($this->_expected_errors[$key]);
            }
        }

        return $deleted;
    }

    /**
     * This method deletes all occurrences of the specified element from
     * the expected error codes stack.
     *
     * @param  mixed $error_code error code that should be deleted
     * @return mixed list of error codes that were deleted or error
     * @access public
     * @since PHP 4.3.0
     */
    function delExpect($error_code)
    {
        $deleted = false;
        if ((is_array($error_code) && (0 != count($error_code)))) {
            // $error_code is a non-empty array here; we walk through it trying
            // to unset all values
            foreach ($error_code as $key => $error) {
                $deleted =  $this->_checkDelExpect($error) ? true : false;
            }

            return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
        } elseif (!empty($error_code)) {
            // $error_code comes alone, trying to unset it
            if ($this->_checkDelExpect($error_code)) {
                return true;
            }

            return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
        }

        // $error_code is empty
        return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME
    }

    /**
     * This method is a wrapper that returns an instance of the
     * configured error class with this object's default error
     * handling applied.  If the $mode and $options parameters are not
     * specified, the object's defaults are used.
     *
     * @param mixed $message a text error message or a PEAR error object
     *
     * @param int $code      a numeric error code (it is up to your class
     *                  to define these if you want to use codes)
     *
     * @param int $mode      One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
     *                  PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
     *                  PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION.
     *
     * @param mixed $options If $mode is PEAR_ERROR_TRIGGER, this parameter
     *                  specifies the PHP-internal error level (one of
     *                  E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
     *                  If $mode is PEAR_ERROR_CALLBACK, this
     *                  parameter specifies the callback function or
     *                  method.  In other error modes this parameter
     *                  is ignored.
     *
     * @param string $userinfo If you need to pass along for example debug
     *                  information, this parameter is meant for that.
     *
     * @param string $error_class The returned error object will be
     *                  instantiated from this class, if specified.
     *
     * @param bool $skipmsg If true, raiseError will only pass error codes,
     *                  the error message parameter will be dropped.
     *
     * @return object   a PEAR error object
     * @see PEAR::setErrorHandling
     * @since PHP 4.0.5
     */
    protected static function _raiseError($object,
                         $message = null,
                         $code = null,
                         $mode = null,
                         $options = null,
                         $userinfo = null,
                         $error_class = null,
                         $skipmsg = false)
    {
        // The error is yet a PEAR error object
        if (is_object($message)) {
            $code        = $message->getCode();
            $userinfo    = $message->getUserInfo();
            $error_class = $message->getType();
            $message->error_message_prefix = '';
            $message     = $message->getMessage();
        }

        if (
            $object !== null &&
            isset($object->_expected_errors) &&
            count($object->_expected_errors) > 0 &&
            count($exp = end($object->_expected_errors))
        ) {
            if ($exp[0] === "*" ||
                (is_int(reset($exp)) && in_array($code, $exp)) ||
                (is_string(reset($exp)) && in_array($message, $exp))
            ) {
                $mode = PEAR_ERROR_RETURN;
            }
        }

        // No mode given, try global ones
        if ($mode === null) {
            // Class error handler
            if ($object !== null && isset($object->_default_error_mode)) {
                $mode    = $object->_default_error_mode;
                $options = $object->_default_error_options;
            // Global error handler
            } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) {
                $mode    = $GLOBALS['_PEAR_default_error_mode'];
                $options = $GLOBALS['_PEAR_default_error_options'];
            }
        }

        if ($error_class !== null) {
            $ec = $error_class;
        } elseif ($object !== null && isset($object->_error_class)) {
            $ec = $object->_error_class;
        } else {
            $ec = 'PEAR_Error';
        }

        if ($skipmsg) {
            $a = new $ec($code, $mode, $options, $userinfo);
        } else {
            $a = new $ec($message, $code, $mode, $options, $userinfo);
        }

        return $a;
    }

    /**
     * Simpler form of raiseError with fewer options.  In most cases
     * message, code and userinfo are enough.
     *
     * @param mixed $message a text error message or a PEAR error object
     *
     * @param int $code      a numeric error code (it is up to your class
     *                  to define these if you want to use codes)
     *
     * @param string $userinfo If you need to pass along for example debug
     *                  information, this parameter is meant for that.
     *
     * @return object   a PEAR error object
     * @see PEAR::raiseError
     */
    protected static function _throwError($object, $message = null, $code = null, $userinfo = null)
    {
        if ($object !== null) {
            $a = $object->raiseError($message, $code, null, null, $userinfo);
            return $a;
        }

        $a = PEAR::raiseError($message, $code, null, null, $userinfo);
        return $a;
    }

    public static function staticPushErrorHandling($mode, $options = null)
    {
        $stack       = &$GLOBALS['_PEAR_error_handler_stack'];
        $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
        $def_options = &$GLOBALS['_PEAR_default_error_options'];
        $stack[] = array($def_mode, $def_options);
        switch ($mode) {
            case PEAR_ERROR_EXCEPTION:
            case PEAR_ERROR_RETURN:
            case PEAR_ERROR_PRINT:
            case PEAR_ERROR_TRIGGER:
            case PEAR_ERROR_DIE:
            case null:
                $def_mode = $mode;
                $def_options = $options;
                break;

            case PEAR_ERROR_CALLBACK:
                $def_mode = $mode;
                // class/object method callback
                if (is_callable($options)) {
                    $def_options = $options;
                } else {
                    trigger_error("invalid error callback", E_USER_WARNING);
                }
                break;

            default:
                trigger_error("invalid error mode", E_USER_WARNING);
                break;
        }
        $stack[] = array($mode, $options);
        return true;
    }

    public static function staticPopErrorHandling()
    {
        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
        $setmode     = &$GLOBALS['_PEAR_default_error_mode'];
        $setoptions  = &$GLOBALS['_PEAR_default_error_options'];
        array_pop($stack);
        list($mode, $options) = $stack[sizeof($stack) - 1];
        array_pop($stack);
        switch ($mode) {
            case PEAR_ERROR_EXCEPTION:
            case PEAR_ERROR_RETURN:
            case PEAR_ERROR_PRINT:
            case PEAR_ERROR_TRIGGER:
            case PEAR_ERROR_DIE:
            case null:
                $setmode = $mode;
                $setoptions = $options;
                break;

            case PEAR_ERROR_CALLBACK:
                $setmode = $mode;
                // class/object method callback
                if (is_callable($options)) {
                    $setoptions = $options;
                } else {
                    trigger_error("invalid error callback", E_USER_WARNING);
                }
                break;

            default:
                trigger_error("invalid error mode", E_USER_WARNING);
                break;
        }
        return true;
    }

    /**
     * Push a new error handler on top of the error handler options stack. With this
     * you can easily override the actual error handler for some code and restore
     * it later with popErrorHandling.
     *
     * @param mixed $mode (same as setErrorHandling)
     * @param mixed $options (same as setErrorHandling)
     *
     * @return bool Always true
     *
     * @see PEAR::setErrorHandling
     */
    protected static function _pushErrorHandling($object, $mode, $options = null)
    {
        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
        if ($object !== null) {
            $def_mode    = &$object->_default_error_mode;
            $def_options = &$object->_default_error_options;
        } else {
            $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
            $def_options = &$GLOBALS['_PEAR_default_error_options'];
        }
        $stack[] = array($def_mode, $def_options);

        if ($object !== null) {
            $object->setErrorHandling($mode, $options);
        } else {
            PEAR::setErrorHandling($mode, $options);
        }
        $stack[] = array($mode, $options);
        return true;
    }

    /**
    * Pop the last error handler used
    *
    * @return bool Always true
    *
    * @see PEAR::pushErrorHandling
    */
    protected static function _popErrorHandling($object)
    {
        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
        array_pop($stack);
        list($mode, $options) = $stack[sizeof($stack) - 1];
        array_pop($stack);
        if ($object !== null) {
            $object->setErrorHandling($mode, $options);
        } else {
            PEAR::setErrorHandling($mode, $options);
        }
        return true;
    }

    /**
    * OS independent PHP extension load. Remember to take care
    * on the correct extension name for case sensitive OSes.
    *
    * @param string $ext The extension name
    * @return bool Success or not on the dl() call
    */
    public static function loadExtension($ext)
    {
        if (extension_loaded($ext)) {
            return true;
        }

        // if either returns true dl() will produce a FATAL error, stop that
        if (
            function_exists('dl') === false ||
            ini_get('enable_dl') != 1
        ) {
            return false;
        }

        if (OS_WINDOWS) {
            $suffix = '.dll';
        } elseif (PHP_OS == 'HP-UX') {
            $suffix = '.sl';
        } elseif (PHP_OS == 'AIX') {
            $suffix = '.a';
        } elseif (PHP_OS == 'OSX') {
            $suffix = '.bundle';
        } else {
            $suffix = '.so';
        }

        return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix);
    }

    /**
     * Get SOURCE_DATE_EPOCH environment variable
     * See https://reproducible-builds.org/specs/source-date-epoch/
     *
     * @return int
     * @access public
     */
    static function getSourceDateEpoch()
    {
        if ($source_date_epoch = getenv('SOURCE_DATE_EPOCH')) {
            if (preg_match('/^\d+$/', $source_date_epoch)) {
                return (int) $source_date_epoch;
            } else {
            //  "If the value is malformed, the build process SHOULD exit with a non-zero error code."
            self::raiseError("Invalid SOURCE_DATE_EPOCH: $source_date_epoch");
            exit(1);
            }
        } else {
            return time();
        }
    }
}

function _PEAR_call_destructors()
{
    global $_PEAR_destructor_object_list;
    if (is_array($_PEAR_destructor_object_list) &&
        sizeof($_PEAR_destructor_object_list))
    {
        reset($_PEAR_destructor_object_list);

        $destructLifoExists = PEAR::getStaticProperty('PEAR', 'destructlifo');

        if ($destructLifoExists) {
            $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list);
        }

        foreach ($_PEAR_destructor_object_list as $k => $objref) {
            $classname = get_class($objref);
            while ($classname) {
                $destructor = "_$classname";
                if (method_exists($objref, $destructor)) {
                    $objref->$destructor();
                    break;
                } else {
                    $classname = get_parent_class($classname);
                }
            }
        }
        // Empty the object list to ensure that destructors are
        // not called more than once.
        $_PEAR_destructor_object_list = array();
    }

    // Now call the shutdown functions
    if (
        isset($GLOBALS['_PEAR_shutdown_funcs']) &&
        is_array($GLOBALS['_PEAR_shutdown_funcs']) &&
        !empty($GLOBALS['_PEAR_shutdown_funcs'])
    ) {
        foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) {
            call_user_func_array($value[0], $value[1]);
        }
    }
}

/**
 * Standard PEAR error class for PHP 4
 *
 * This class is supserseded by {@link PEAR_Exception} in PHP 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Tomas V.V. Cox <cox@idecnet.com>
 * @author     Gregory Beaver <cellog@php.net>
 * @copyright  1997-2006 The PHP Group
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.10.16
 * @link       http://pear.php.net/manual/en/core.pear.pear-error.php
 * @see        PEAR::raiseError(), PEAR::throwError()
 * @since      Class available since PHP 4.0.2
 */
class PEAR_Error
{
    var $error_message_prefix = '';
    var $mode                 = PEAR_ERROR_RETURN;
    var $level                = E_USER_NOTICE;
    var $code                 = -1;
    var $message              = '';
    var $userinfo             = '';
    var $backtrace            = null;
    var $callback             = null;

    /**
     * PEAR_Error constructor
     *
     * @param string $message  message
     *
     * @param int $code     (optional) error code
     *
     * @param int $mode     (optional) error mode, one of: PEAR_ERROR_RETURN,
     * PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER,
     * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION
     *
     * @param mixed $options   (optional) error level, _OR_ in the case of
     * PEAR_ERROR_CALLBACK, the callback function or object/method
     * tuple.
     *
     * @param string $userinfo (optional) additional user/debug info
     *
     * @access public
     *
     */
    function __construct($message = 'unknown error', $code = null,
                        $mode = null, $options = null, $userinfo = null)
    {
        if ($mode === null) {
            $mode = PEAR_ERROR_RETURN;
        }
        $this->message   = $message;
        $this->code      = $code;
        $this->mode      = $mode;
        $this->userinfo  = $userinfo;

        $skiptrace = PEAR::getStaticProperty('PEAR_Error', 'skiptrace');

        if (!$skiptrace) {
            $this->backtrace = debug_backtrace();
            if (isset($this->backtrace[0]) && isset($this->backtrace[0]['object'])) {
                unset($this->backtrace[0]['object']);
            }
        }

        if ($mode & PEAR_ERROR_CALLBACK) {
            $this->level = E_USER_NOTICE;
            $this->callback = $options;
        } else {
            if ($options === null) {
                $options = E_USER_NOTICE;
            }

            $this->level = $options;
            $this->callback = null;
        }

        if ($this->mode & PEAR_ERROR_PRINT) {
            if (is_null($options) || is_int($options)) {
                $format = "%s";
            } else {
                $format = $options;
            }

            printf($format, $this->getMessage());
        }

        if ($this->mode & PEAR_ERROR_TRIGGER) {
            trigger_error($this->getMessage(), $this->level);
        }

        if ($this->mode & PEAR_ERROR_DIE) {
            $msg = $this->getMessage();
            if (is_null($options) || is_int($options)) {
                $format = "%s";
                if (substr($msg, -1) != "\n") {
                    $msg .= "\n";
                }
            } else {
                $format = $options;
            }
            printf($format, $msg);
            exit($code);
        }

        if ($this->mode & PEAR_ERROR_CALLBACK && is_callable($this->callback)) {
            call_user_func($this->callback, $this);
        }

        if ($this->mode & PEAR_ERROR_EXCEPTION) {
            trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_Exception for exceptions", E_USER_WARNING);
            eval('$e = new Exception($this->message, $this->code);throw($e);');
        }
    }

    /**
     * Only here for backwards compatibility.
     *
     * Class "Cache_Error" still uses it, among others.
     *
     * @param string $message  Message
     * @param int    $code     Error code
     * @param int    $mode     Error mode
     * @param mixed  $options  See __construct()
     * @param string $userinfo Additional user/debug info
     */
    public function PEAR_Error(
        $message = 'unknown error', $code = null, $mode = null,
        $options = null, $userinfo = null
    ) {
        self::__construct($message, $code, $mode, $options, $userinfo);
    }

    /**
     * Get the error mode from an error object.
     *
     * @return int error mode
     * @access public
     */
    function getMode()
    {
        return $this->mode;
    }

    /**
     * Get the callback function/method from an error object.
     *
     * @return mixed callback function or object/method array
     * @access public
     */
    function getCallback()
    {
        return $this->callback;
    }

    /**
     * Get the error message from an error object.
     *
     * @return  string  full error message
     * @access public
     */
    function getMessage()
    {
        return ($this->error_message_prefix . $this->message);
    }

    /**
     * Get error code from an error object
     *
     * @return int error code
     * @access public
     */
     function getCode()
     {
        return $this->code;
     }

    /**
     * Get the name of this error/exception.
     *
     * @return string error/exception name (type)
     * @access public
     */
    function getType()
    {
        return get_class($this);
    }

    /**
     * Get additional user-supplied information.
     *
     * @return string user-supplied information
     * @access public
     */
    function getUserInfo()
    {
        return $this->userinfo;
    }

    /**
     * Get additional debug information supplied by the application.
     *
     * @return string debug information
     * @access public
     */
    function getDebugInfo()
    {
        return $this->getUserInfo();
    }

    /**
     * Get the call backtrace from where the error was generated.
     * Supported with PHP 4.3.0 or newer.
     *
     * @param int $frame (optional) what frame to fetch
     * @return array Backtrace, or NULL if not available.
     * @access public
     */
    function getBacktrace($frame = null)
    {
        if (defined('PEAR_IGNORE_BACKTRACE')) {
            return null;
        }
        if ($frame === null) {
            return $this->backtrace;
        }
        return $this->backtrace[$frame];
    }

    function addUserInfo($info)
    {
        if (empty($this->userinfo)) {
            $this->userinfo = $info;
        } else {
            $this->userinfo .= " ** $info";
        }
    }

    function __toString()
    {
        return $this->getMessage();
    }

    /**
     * Make a string representation of this object.
     *
     * @return string a string with an object summary
     * @access public
     */
    function toString()
    {
        $modes = array();
        $levels = array(E_USER_NOTICE  => 'notice',
                        E_USER_WARNING => 'warning',
                        E_USER_ERROR   => 'error');
        if ($this->mode & PEAR_ERROR_CALLBACK) {
            if (is_array($this->callback)) {
                $callback = (is_object($this->callback[0]) ?
                    strtolower(get_class($this->callback[0])) :
                    $this->callback[0]) . '::' .
                    $this->callback[1];
            } else {
                $callback = $this->callback;
            }
            return sprintf('[%s: message="%s" code=%d mode=callback '.
                           'callback=%s prefix="%s" info="%s"]',
                           strtolower(get_class($this)), $this->message, $this->code,
                           $callback, $this->error_message_prefix,
                           $this->userinfo);
        }
        if ($this->mode & PEAR_ERROR_PRINT) {
            $modes[] = 'print';
        }
        if ($this->mode & PEAR_ERROR_TRIGGER) {
            $modes[] = 'trigger';
        }
        if ($this->mode & PEAR_ERROR_DIE) {
            $modes[] = 'die';
        }
        if ($this->mode & PEAR_ERROR_RETURN) {
            $modes[] = 'return';
        }
        return sprintf('[%s: message="%s" code=%d mode=%s level=%s '.
                       'prefix="%s" info="%s"]',
                       strtolower(get_class($this)), $this->message, $this->code,
                       implode("|", $modes), $levels[$this->level],
                       $this->error_message_prefix,
                       $this->userinfo);
    }
}

/*
 * Local Variables:
 * mode: php
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 */
PK��Z�o�P�P
System.phpnu�[���<?php
/**
 * File/Directory manipulation
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    System
 * @author     Tomas V.V.Cox <cox@idecnet.com>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 0.1
 */

/**
 * base class
 */
require_once 'PEAR.php';
require_once 'Console/Getopt.php';

$GLOBALS['_System_temp_files'] = array();

/**
* System offers cross platform compatible system functions
*
* Static functions for different operations. Should work under
* Unix and Windows. The names and usage has been taken from its respectively
* GNU commands. The functions will return (bool) false on error and will
* trigger the error with the PHP trigger_error() function (you can silence
* the error by prefixing a '@' sign after the function call, but this
* is not recommended practice.  Instead use an error handler with
* {@link set_error_handler()}).
*
* Documentation on this class you can find in:
* http://pear.php.net/manual/
*
* Example usage:
* if (!@System::rm('-r file1 dir1')) {
*    print "could not delete file1 or dir1";
* }
*
* In case you need to to pass file names with spaces,
* pass the params as an array:
*
* System::rm(array('-r', $file1, $dir1));
*
* @category   pear
* @package    System
* @author     Tomas V.V. Cox <cox@idecnet.com>
* @copyright  1997-2006 The PHP Group
* @license    http://opensource.org/licenses/bsd-license.php New BSD License
* @version    Release: 1.10.16
* @link       http://pear.php.net/package/PEAR
* @since      Class available since Release 0.1
* @static
*/
class System
{
    /**
     * returns the commandline arguments of a function
     *
     * @param    string  $argv           the commandline
     * @param    string  $short_options  the allowed option short-tags
     * @param    string  $long_options   the allowed option long-tags
     * @return   array   the given options and there values
     */
    public static function _parseArgs($argv, $short_options, $long_options = null)
    {
        if (!is_array($argv) && $argv !== null) {
            /*
            // Quote all items that are a short option
            $av = preg_split('/(\A| )--?[a-z0-9]+[ =]?((?<!\\\\)((,\s*)|((?<!,)\s+))?)/i', $argv, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE);
            $offset = 0;
            foreach ($av as $a) {
                $b = trim($a[0]);
                if ($b[0] == '"' || $b[0] == "'") {
                    continue;
                }

                $escape = escapeshellarg($b);
                $pos = $a[1] + $offset;
                $argv = substr_replace($argv, $escape, $pos, strlen($b));
                $offset += 2;
            }
            */

            // Find all items, quoted or otherwise
            preg_match_all("/(?:[\"'])(.*?)(?:['\"])|([^\s]+)/", $argv, $av);
            $argv = $av[1];
            foreach ($av[2] as $k => $a) {
                if (empty($a)) {
                    continue;
                }
                $argv[$k] = trim($a) ;
            }
        }

        return Console_Getopt::getopt2($argv, $short_options, $long_options);
    }

    /**
     * Output errors with PHP trigger_error(). You can silence the errors
     * with prefixing a "@" sign to the function call: @System::mkdir(..);
     *
     * @param mixed $error a PEAR error or a string with the error message
     * @return bool false
     */
    protected static function raiseError($error)
    {
        if (PEAR::isError($error)) {
            $error = $error->getMessage();
        }
        trigger_error($error, E_USER_WARNING);
        return false;
    }

    /**
     * Creates a nested array representing the structure of a directory
     *
     * System::_dirToStruct('dir1', 0) =>
     *   Array
     *    (
     *    [dirs] => Array
     *        (
     *            [0] => dir1
     *        )
     *
     *    [files] => Array
     *        (
     *            [0] => dir1/file2
     *            [1] => dir1/file3
     *        )
     *    )
     * @param    string  $sPath      Name of the directory
     * @param    integer $maxinst    max. deep of the lookup
     * @param    integer $aktinst    starting deep of the lookup
     * @param    bool    $silent     if true, do not emit errors.
     * @return   array   the structure of the dir
     */
    protected static function _dirToStruct($sPath, $maxinst, $aktinst = 0, $silent = false)
    {
        $struct = array('dirs' => array(), 'files' => array());
        if (($dir = @opendir($sPath)) === false) {
            if (!$silent) {
                System::raiseError("Could not open dir $sPath");
            }
            return $struct; // XXX could not open error
        }

        $struct['dirs'][] = $sPath = realpath($sPath); // XXX don't add if '.' or '..' ?
        $list = array();
        while (false !== ($file = readdir($dir))) {
            if ($file != '.' && $file != '..') {
                $list[] = $file;
            }
        }

        closedir($dir);
        natsort($list);
        if ($aktinst < $maxinst || $maxinst == 0) {
            foreach ($list as $val) {
                $path = $sPath . DIRECTORY_SEPARATOR . $val;
                if (is_dir($path) && !is_link($path)) {
                    $tmp    = System::_dirToStruct($path, $maxinst, $aktinst+1, $silent);
                    $struct = array_merge_recursive($struct, $tmp);
                } else {
                    $struct['files'][] = $path;
                }
            }
        }

        return $struct;
    }

    /**
     * Creates a nested array representing the structure of a directory and files
     *
     * @param    array $files Array listing files and dirs
     * @return   array
     * @static
     * @see System::_dirToStruct()
     */
    protected static function _multipleToStruct($files)
    {
        $struct = array('dirs' => array(), 'files' => array());
        settype($files, 'array');
        foreach ($files as $file) {
            if (is_dir($file) && !is_link($file)) {
                $tmp    = System::_dirToStruct($file, 0);
                $struct = array_merge_recursive($tmp, $struct);
            } else {
                if (!in_array($file, $struct['files'])) {
                    $struct['files'][] = $file;
                }
            }
        }
        return $struct;
    }

    /**
     * The rm command for removing files.
     * Supports multiple files and dirs and also recursive deletes
     *
     * @param    string  $args   the arguments for rm
     * @return   mixed   PEAR_Error or true for success
     * @static
     * @access   public
     */
    public static function rm($args)
    {
        $opts = System::_parseArgs($args, 'rf'); // "f" does nothing but I like it :-)
        if (PEAR::isError($opts)) {
            return System::raiseError($opts);
        }
        foreach ($opts[0] as $opt) {
            if ($opt[0] == 'r') {
                $do_recursive = true;
            }
        }
        $ret = true;
        if (isset($do_recursive)) {
            $struct = System::_multipleToStruct($opts[1]);
            foreach ($struct['files'] as $file) {
                if (!@unlink($file)) {
                    $ret = false;
                }
            }

            rsort($struct['dirs']);
            foreach ($struct['dirs'] as $dir) {
                if (!@rmdir($dir)) {
                    $ret = false;
                }
            }
        } else {
            foreach ($opts[1] as $file) {
                $delete = (is_dir($file)) ? 'rmdir' : 'unlink';
                if (!@$delete($file)) {
                    $ret = false;
                }
            }
        }
        return $ret;
    }

    /**
     * Make directories.
     *
     * The -p option will create parent directories
     * @param    string  $args    the name of the director(y|ies) to create
     * @return   bool    True for success
     */
    public static function mkDir($args)
    {
        $opts = System::_parseArgs($args, 'pm:');
        if (PEAR::isError($opts)) {
            return System::raiseError($opts);
        }

        $mode = 0777; // default mode
        foreach ($opts[0] as $opt) {
            if ($opt[0] == 'p') {
                $create_parents = true;
            } elseif ($opt[0] == 'm') {
                // if the mode is clearly an octal number (starts with 0)
                // convert it to decimal
                if (strlen($opt[1]) && $opt[1][0] == '0') {
                    $opt[1] = octdec($opt[1]);
                } else {
                    // convert to int
                    $opt[1] += 0;
                }
                $mode = $opt[1];
            }
        }

        $ret = true;
        if (isset($create_parents)) {
            foreach ($opts[1] as $dir) {
                $dirstack = array();
                while ((!file_exists($dir) || !is_dir($dir)) &&
                        $dir != DIRECTORY_SEPARATOR) {
                    array_unshift($dirstack, $dir);
                    $dir = dirname($dir);
                }

                while ($newdir = array_shift($dirstack)) {
                    if (!is_writeable(dirname($newdir))) {
                        $ret = false;
                        break;
                    }

                    if (!mkdir($newdir, $mode)) {
                        $ret = false;
                    }
                }
            }
        } else {
            foreach($opts[1] as $dir) {
                if ((@file_exists($dir) || !is_dir($dir)) && !mkdir($dir, $mode)) {
                    $ret = false;
                }
            }
        }

        return $ret;
    }

    /**
     * Concatenate files
     *
     * Usage:
     * 1) $var = System::cat('sample.txt test.txt');
     * 2) System::cat('sample.txt test.txt > final.txt');
     * 3) System::cat('sample.txt test.txt >> final.txt');
     *
     * Note: as the class use fopen, urls should work also
     *
     * @param    string  $args   the arguments
     * @return   boolean true on success
     */
    public static function &cat($args)
    {
        $ret = null;
        $files = array();
        if (!is_array($args)) {
            $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY);
        }

        $count_args = count($args);
        for ($i = 0; $i < $count_args; $i++) {
            if ($args[$i] == '>') {
                $mode = 'wb';
                $outputfile = $args[$i+1];
                break;
            } elseif ($args[$i] == '>>') {
                $mode = 'ab+';
                $outputfile = $args[$i+1];
                break;
            } else {
                $files[] = $args[$i];
            }
        }
        $outputfd = false;
        if (isset($mode)) {
            if (!$outputfd = fopen($outputfile, $mode)) {
                $err = System::raiseError("Could not open $outputfile");
                return $err;
            }
            $ret = true;
        }
        foreach ($files as $file) {
            if (!$fd = fopen($file, 'r')) {
                System::raiseError("Could not open $file");
                continue;
            }
            while ($cont = fread($fd, 2048)) {
                if (is_resource($outputfd)) {
                    fwrite($outputfd, $cont);
                } else {
                    $ret .= $cont;
                }
            }
            fclose($fd);
        }
        if (is_resource($outputfd)) {
            fclose($outputfd);
        }
        return $ret;
    }

    /**
     * Creates temporary files or directories. This function will remove
     * the created files when the scripts finish its execution.
     *
     * Usage:
     *   1) $tempfile = System::mktemp("prefix");
     *   2) $tempdir  = System::mktemp("-d prefix");
     *   3) $tempfile = System::mktemp();
     *   4) $tempfile = System::mktemp("-t /var/tmp prefix");
     *
     * prefix -> The string that will be prepended to the temp name
     *           (defaults to "tmp").
     * -d     -> A temporary dir will be created instead of a file.
     * -t     -> The target dir where the temporary (file|dir) will be created. If
     *           this param is missing by default the env vars TMP on Windows or
     *           TMPDIR in Unix will be used. If these vars are also missing
     *           c:\windows\temp or /tmp will be used.
     *
     * @param   string  $args  The arguments
     * @return  mixed   the full path of the created (file|dir) or false
     * @see System::tmpdir()
     */
    public static function mktemp($args = null)
    {
        static $first_time = true;
        $opts = System::_parseArgs($args, 't:d');
        if (PEAR::isError($opts)) {
            return System::raiseError($opts);
        }

        foreach ($opts[0] as $opt) {
            if ($opt[0] == 'd') {
                $tmp_is_dir = true;
            } elseif ($opt[0] == 't') {
                $tmpdir = $opt[1];
            }
        }

        $prefix = (isset($opts[1][0])) ? $opts[1][0] : 'tmp';
        if (!isset($tmpdir)) {
            $tmpdir = System::tmpdir();
        }

        if (!System::mkDir(array('-p', $tmpdir))) {
            return false;
        }

        $tmp = tempnam($tmpdir, $prefix);
        if (isset($tmp_is_dir)) {
            unlink($tmp); // be careful possible race condition here
            if (!mkdir($tmp, 0700)) {
                return System::raiseError("Unable to create temporary directory $tmpdir");
            }
        }

        $GLOBALS['_System_temp_files'][] = $tmp;
        if (isset($tmp_is_dir)) {
            //$GLOBALS['_System_temp_files'][] = dirname($tmp);
        }

        if ($first_time) {
            PEAR::registerShutdownFunc(array('System', '_removeTmpFiles'));
            $first_time = false;
        }

        return $tmp;
    }

    /**
     * Remove temporary files created my mkTemp. This function is executed
     * at script shutdown time
     */
    public static function _removeTmpFiles()
    {
        if (count($GLOBALS['_System_temp_files'])) {
            $delete = $GLOBALS['_System_temp_files'];
            array_unshift($delete, '-r');
            System::rm($delete);
            $GLOBALS['_System_temp_files'] = array();
        }
    }

    /**
     * Get the path of the temporal directory set in the system
     * by looking in its environments variables.
     * Note: php.ini-recommended removes the "E" from the variables_order setting,
     * making unavaible the $_ENV array, that s why we do tests with _ENV
     *
     * @return string The temporary directory on the system
     */
    public static function tmpdir()
    {
        if (OS_WINDOWS) {
            if ($var = isset($_ENV['TMP']) ? $_ENV['TMP'] : getenv('TMP')) {
                return $var;
            }
            if ($var = isset($_ENV['TEMP']) ? $_ENV['TEMP'] : getenv('TEMP')) {
                return $var;
            }
            if ($var = isset($_ENV['USERPROFILE']) ? $_ENV['USERPROFILE'] : getenv('USERPROFILE')) {
                return $var;
            }
            if ($var = isset($_ENV['windir']) ? $_ENV['windir'] : getenv('windir')) {
                return $var;
            }
            return getenv('SystemRoot') . '\temp';
        }
        if ($var = isset($_ENV['TMPDIR']) ? $_ENV['TMPDIR'] : getenv('TMPDIR')) {
            return $var;
        }
        return realpath(function_exists('sys_get_temp_dir') ? sys_get_temp_dir() : '/tmp');
    }

    /**
     * The "which" command (show the full path of a command)
     *
     * @param string $program The command to search for
     * @param mixed  $fallback Value to return if $program is not found
     *
     * @return mixed A string with the full path or false if not found
     * @author Stig Bakken <ssb@php.net>
     */
    public static function which($program, $fallback = false)
    {
        // enforce API
        if (!is_string($program) || '' == $program) {
            return $fallback;
        }

        // full path given
        if (basename($program) != $program) {
            $path_elements[] = dirname($program);
            $program = basename($program);
        } else {
            $path = getenv('PATH');
            if (!$path) {
                $path = getenv('Path'); // some OSes are just stupid enough to do this
            }

            $path_elements = explode(PATH_SEPARATOR, $path);
        }

        if (OS_WINDOWS) {
            $exe_suffixes = getenv('PATHEXT')
                                ? explode(PATH_SEPARATOR, getenv('PATHEXT'))
                                : array('.exe','.bat','.cmd','.com');
            // allow passing a command.exe param
            if (strpos($program, '.') !== false) {
                array_unshift($exe_suffixes, '');
            }
        } else {
            $exe_suffixes = array('');
        }

        foreach ($exe_suffixes as $suff) {
            foreach ($path_elements as $dir) {
                $file = $dir . DIRECTORY_SEPARATOR . $program . $suff;
                // It's possible to run a .bat on Windows that is_executable
                // would return false for. The is_executable check is meaningless...
                if (OS_WINDOWS) {
                    if (file_exists($file)) {
                        return $file;
                    }
                } else {
                    if (is_executable($file)) {
                        return $file;
                    }
                }
            }
        }
        return $fallback;
    }

    /**
     * The "find" command
     *
     * Usage:
     *
     * System::find($dir);
     * System::find("$dir -type d");
     * System::find("$dir -type f");
     * System::find("$dir -name *.php");
     * System::find("$dir -name *.php -name *.htm*");
     * System::find("$dir -maxdepth 1");
     *
     * Params implemented:
     * $dir            -> Start the search at this directory
     * -type d         -> return only directories
     * -type f         -> return only files
     * -maxdepth <n>   -> max depth of recursion
     * -name <pattern> -> search pattern (bash style). Multiple -name param allowed
     *
     * @param  mixed Either array or string with the command line
     * @return array Array of found files
     */
    public static function find($args)
    {
        if (!is_array($args)) {
            $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY);
        }
        $dir = realpath(array_shift($args));
        if (!$dir) {
            return array();
        }
        $patterns = array();
        $depth = 0;
        $do_files = $do_dirs = true;
        $args_count = count($args);
        for ($i = 0; $i < $args_count; $i++) {
            switch ($args[$i]) {
                case '-type':
                    if (in_array($args[$i+1], array('d', 'f'))) {
                        if ($args[$i+1] == 'd') {
                            $do_files = false;
                        } else {
                            $do_dirs = false;
                        }
                    }
                    $i++;
                    break;
                case '-name':
                    $name = preg_quote($args[$i+1], '#');
                    // our magic characters ? and * have just been escaped,
                    // so now we change the escaped versions to PCRE operators
                    $name = strtr($name, array('\?' => '.', '\*' => '.*'));
                    $patterns[] = '('.$name.')';
                    $i++;
                    break;
                case '-maxdepth':
                    $depth = $args[$i+1];
                    break;
            }
        }
        $path = System::_dirToStruct($dir, $depth, 0, true);
        if ($do_files && $do_dirs) {
            $files = array_merge($path['files'], $path['dirs']);
        } elseif ($do_dirs) {
            $files = $path['dirs'];
        } else {
            $files = $path['files'];
        }
        if (count($patterns)) {
            $dsq = preg_quote(DIRECTORY_SEPARATOR, '#');
            $pattern = '#(^|'.$dsq.')'.implode('|', $patterns).'($|'.$dsq.')#';
            $ret = array();
            $files_count = count($files);
            for ($i = 0; $i < $files_count; $i++) {
                // only search in the part of the file below the current directory
                $filepart = basename($files[$i]);
                if (preg_match($pattern, $filepart)) {
                    $ret[] = $files[$i];
                }
            }
            return $ret;
        }
        return $files;
    }
}
PK��ZZ�Vdccpeclcmd.phpnu�[���<?php
/**
 * PEAR, the PHP Extension and Application Repository
 *
 * Command line interface
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Tomas V.V.Cox <cox@idecnet.com>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @link       http://pear.php.net/package/PEAR
 */

/**
 * @nodep Gtk
 */
//the space is needed for windows include paths with trailing backslash
// http://pear.php.net/bugs/bug.php?id=19482
if ('/opt/alt/php74/usr/share/pear ' != '@'.'include_path'.'@ ') {
    ini_set('include_path', trim('/opt/alt/php74/usr/share/pear '). PATH_SEPARATOR .  get_include_path());
    $raw = false;
} else {
    // this is a raw, uninstalled pear, either a cvs checkout, or php distro
    ini_set('include_path', __DIR__ . PATH_SEPARATOR . get_include_path());
    $raw = true;
}
define('PEAR_RUNTYPE', 'pecl');
require_once 'pearcmd.php';
/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * indent-tabs-mode: nil
 * mode: php
 * End:
 */
// vim600:syn=php

?>
PK��Z��j��data/Base/design/design.txtnu�[���Base
====

Purpose
-------
This is the base package of the eZ publish components, offering the basic
support that all Components need. In the first version this will be the
autoload support.

PK��Zu+��S�S�"data/Base/design/class_diagram.pngnu�[����PNG


IHDR���|�bKGD������� IDATx���y|M���Wd4s
S|%Um5I[�EiiS\�T��!���⪡U������&�1�4����*1D(� �R��� "���|srN"�C�~>���^{�>k� >�{-�0DDDDDDDDD$���#�_(Y&""""""""r��e"""""""""w(Y&""""""""r��e"""""""""w(Y&""""""""r��e"""""""""w(Y&""""""""r��e"""""""""w(Y&""""""""r������ݻ�;�G"""�������<@�0��Ƚ���@�n������+V��DDDDD�b�d��e���h�0D�����ӫW/{�!"""""�Y&""""""""r��,Ak����h�2)
%�D�������ȃ���XDDDDD�(�,�Ck��<شF�������Y&""""""""r��e"""""""""w(Y&""""""""r��e"����`����H�ʕiڴ)ӦM#==�ޡ�������}F�2�������ի�޽�#FвeKRSS���������G�,�?-�0,>\�x��+WR�vm�����ɓ���������G�,��gggz�!�t���ŋX�h�������e"RdgΜ���ԭ[WWW����ի��Y?�5Ųr����[�nT�V
<==5jׯ_/T��<�.\�:�������iѢU�T��ɉ�U���+��u�V��%&&������T�T	___>��#�^�j�Λ�������<�0{!r�988F``��cɿ�۷Ӿ}{�]�fu��͍U�V`Qn+�]�ҥ-�[�p!o���nݲ���O�}�vʖ-k�~^��ܹ��͛Ӹqc:d.ONN�U�V���ڼ�����Hڷoo.ۻw/mڴ!99��5���c׮]<��C��̛�-<<�^�z��{�c�|�ѓe"RhW�\�k׮$''3l�0IKK#::��}����A``���[9�3�b������S�0`�n�"88�S�N�����?���������O?�W�YYY����\��=z��;�X��O�����ۛ�~����T���ٵk͚5�0>��c�k�
Frr2���#11���RSSٲe�5����|��GE�7��� ��X�g���`�3��aÆ�y�$::�prr2cĈ�F�iƫ��ju�޽{
��W��E9p�O�R��Q�FY����aƾ}���%&&�Q�L�r7770���Z]gF͚5�e�5ob),,���Z�c�|ث'�D��֮]��!Cl��۷/6lȵ���$z��Iff&�ڵcʔ)�7m���A�������0N�:U��
�`߾}���[��>}�0������HKK�(�S������/���y{{c�ϟ7�Ǽ������H�p�w"��2-D���g����\��ߟӧO����ҥKqtt�8��q�x��g�X�*++�k׮q��af͚Exx8����޽��
Z]��I���ٳg�w��6�=z4}��!::���h�v�M�6t�Ё������b�_�&""""""%C�2)4[�����_MDD�˗�o��r��VuL�]�+W���Q�T)*U����?���xxx0e�F�Ś5k��/_��ѣ9y�d���ݻ7+VdҤI�~��,X�����dÆ
ԯ_(��������H��k�"Rh�(�^�js�~���.�			���888�d�5j�g��Yq1b[�l1����ӣGN�<IÆ
7n!!!|��7;v,׶���o�>Μ9Chh(AAA4h��'N0t�P�1f�DDDDDD�d)Y&"�����Ν;t]zz:=z� 55��>���;�Z��������z7n�0m��rΜ9$$$0a�����ر���mYYY6۪[�.}��!$$��G�����u�Vs��Λ�������<%�D��^z�%�v�)33��|DDX�>��ҹsgƎ�g�?�<!!!V����ppp�^�z��ѢE��zh�5�^�u��������׫W�������
;o""""""R�,�B4h+Vdǎ���K�ٳ���t�l�€x���qrrb����k"##�5k�?�8�-��!�>���+���g�����o����y�fz���^3,�2339y�$�1#G��w�1��[�.p;���o�q��-���y�7�6m����˗�_����nݺ�q�FRRR���$..���@�d��7�7��ۺ��888fNd�<������k׮OZe��_2p�@󱟟���k��j


�o߾V�P4k֌͛7���f.�[.��}�2o�<��y��߿�ͺ�ƍcٲe$&&�r�J�t��^��iӦ$$$ؼ�V�Z�رsYA�M�.<<�^�z��Or�������C��,�"	�Q�N����X�"/��"6l�J��8q��}�m�6^~�e*U����
6d�ĉlٲ�"Qv7���ԫW�=z�n�:�D@�~�X�p!M�4��Օ
*��/��w�1a�ƍ�^�̤B�
DGG��ӨQ#J�.���^^^��d����2(��������Ƚ�'��/IO������2)z�LDDDDDDDD�D�2�;�,�C�2�;�,�C�2�;�,�C�2�;�����W�^�Y���a�H!�X���!�����ȟ��e"@�n�����������HqP�L����w"""""""rP�Lppp�w"RLðw"""""�S�L�N�:h�0D����õ������e"wt��Mk�<�n޼�d������Y){ """"""""r�Гe"�p��%�T��6m�ܹst�ԉ�ի���111v��V����)h�G��G)�5�Za��T?��u#""صkM�6�{��EjODDDDDD���e"������q�ƍ�����d۶mvK
>����̙3Y�|9�a�ꫯҠA�4ib��DDDDDD�%�D�!�d��~W���m۶[[����(�d`ZZ�ƍ�k׮���йsgƎˊ+(]�t��'""""""��5�Dr���g�,Z���s����Dze��1cF�_u������s��%z��a.�ٳ'�.]b���v�LDDDDDD�S�L�%''��g���+�дiSڷo����׭���ӪU+s�iӦ���jQ����L�0�6m�����رc��Ƙ1c���3��f�����ǨQ�,��D�Ijj*3f̠cǎ4k֌:��_���aў���XZ�nMpp�E����4h�>�,mڴaʔ)���j��"�l���Y�lO=�իW7�רQÜ|MNN.��EDDDDD����H.L��;v���@<<<X�jqqq��ݛ
��ׯ_筷���ɓ沋/Ξ={

�L�2̞=�����/^�Ȳe˸v�&Ln']���8�����OJJJ��;j�(����ԩS���F�\�x�O>���ի3z�h6m�d�ڌ����9|����…����̙3)U�27��矓��l�<0`III����j�*���3f���*i��IMM���ߪ���Æ
�ҥ�=�]DDDDDDr�'�D�"�b��]�ѢE�<y�Z�jJtt4!!!ԬY��Ǐ�`�sݥK��V;v�`�Ν|��Wl߾�\o��Ŝ?�:u�p�B����;w.���yƒ��Ҝ������G����|@VV~�!)))�?�
*X��c>^�d	��q�Ƅ���{�n"""hҤ	{��!22�*����c��䖇��W�fǎ�e˖�Ua� 
2�;v�裏Z�c*3��R�L�.
���)�3f��q���y�'=z4�7o6���ٻw/�5bݺu|��|���lnݺ�ѣG��퍳�3>>>�����0Rxꩧ$66���z�}��ѣG�~��<�۸q#�'O�A�8::R�~}Ə`�j'�k������U�ȑ#�[�.�������k׮���w�JZA�|��Q�v"0�z��Y���k�"����ԩS�:u��x�ĉL�8��s��U�'�x¢��'���_5����6����v�0}��9�q�m� ;;<�ݻws��!�ׯ��o�}�kΞ=@ǎm�?~��U�)I�������
*���e.��\�8v�,Ș�\��~z/'S���������ؗ�e"�X�ď�ԩSIHH�N�:�l�OOO����޽�E=S2(gR��ɾ���ė�������_;88X���\�����4���e/�5V���,�ELL�����ߟƍ�`����y�����a�ܹy^_�fMN�>́x�g������\�k�.BCC�\�2������899Q�NN�<Ill��b�WC�ìY�8~�8�5����̜9���{/�k���9s��~��ŸJB~窤d�U�T��ŋ$%%Q�J�s��r��������}h�2�<vq�V�Z�״:x� ���<x�)S���s�Y]MFFG�a�ر�rӚ]/�����X233�����?.�-�ݻ���p�4iBhh(>>>,]���{��똞�2�������g;r��n�����|�����\,�ew��*i�#�<��3g��1��ꈈ�����}��2�<%Y��o�y�fΞ=k��Ѥnݺe�Z�"**�>��>����#G�����k���?��ѣG�߿��|�v�l&bL��cLL��Ɍ?�2e�0a����?~<={���?d���/_�ʕ+s��:w�;�~�-�{�f�֭<x��^{͢m777�
�g��߹*is���ٶmqqq���X�5}O�J�������Ƚ�'�D�39oq�����3�|�w�N���qtt�z����ٓ��1bm۶�t�Ҹ�����͔)S�	��˗���;w.]�v�r�ʸ����/2f̘"���O>��~c�ȑԬY��*�ȑ#�t��|�	Ç�V�Z8::���@�r�

%00www�P��Z�b����T~窤d��ڵ�L�2l߾ݪ��۷S�\9^|��{�����������q""���h�X��͙3���֬YC�Z���;�v�ԉзo_;G���W�^��r�������C��,��|�MjԨAXX��,,,www��8EDDDDD�~�,�J�.��㉌��…\�p���HƏ�������;�����=���ˠA��6m��Z�_DDDDDD�K�2�{(00Pk㉈�����������������J����������ܡd����������Z�L�+V���l�0D��V�Xa�DDDDD�O@�2�;֬YÚ5k���������ؑ�e"�a�ADDDDDDD�J��ݻw�w"RL"""�������<��,��:�֭��#��Қe"""""R�,�#,,���@{�!"�N�^��������<�J�;����e"""""""""w�5L�|�t�T�T�M�6q��9:u�D��Չ����������h�SY^L�s^_\㉈�`׮]4m�T�)�������}M�2�|��������q��v��A��~fΜ����1�W_}�
ФI{�&""""""b��e"��[��t|����a�D\ZZ�ƍ�k׮���йsgƎˊ+(]�t��'"��.]��z�j{�!"@HHAAA�CDD$OJ�����+�s��e�ܹ��3f0c���zy?�?>�.]�G�沞={�t�R�ϟϠA������8991}�t{�!��o�;�|Q�L�%''3w�\6o���˗�Z�*�[�����+W΢�?���+8r����T�Z�V�Z1h� ʔ)c�w��ef͚Ŷm�HKK�u�֌=�ȱ�g����TBBBظq#���;U�V��_�o߾���X�{ٲe<��ST�^�\^�F
���X�l���:�˗/r�""�@@@����KS�LDDJ���”4:v����xxx�j�*����ݻ7
4 <<<��_��[o��ɓ'�e/^$<<�={�jN�͞=�����/^�Ȳe˸v�&Ln'����8�����OJJJ��;7s��asم

%..��3gR���
vׯ_Ojj*���V���g�6l�@�.]J<n��P�L�.r.���-Z�ɓ'�U�'N��G���Ì7��Ǐ�`��K�.`ԨQt��:Āؾ}���ŋs��y�ԩäI�hР��>�3��v�,��K�,����4nܘѣG���ə3g�<y2{��!22�N�:�c�}�Q�vLe;v�P�LD�bذaDFF�;����ӧӱcG{�!""R J���Ea�߲ecƌ����'�`���2�͛7��e?��#�a�����u�HLLd�޽��'�L�n�
��ѣ����������ps�q�F&O�L͚5�_�>�Ǐ�S�NDEE��eG����ê�z��Y���a&R��ڥ��<��,�EΧ��N��ԩS��'Nd�ĉ��'�L�J>���O>�$������?�`ذa$$$X�c���s����o9��Mql@p��Y�\;|��q��W�\��&���TGD����H�S�LDDTJ���cYYYVeS�N%!!�:u�вeK<==�{���L���	4���DI��gNٟ�spp0�a����TGDDDDDD�~�d�H.bbb������4nܘ��o����s����5kr��i8�3�<c.?p�����]�vJ�ʕ,6�����ɉ:u�p��Ibcc-�7�Z����9s��~��E�T�R��/���D�*U,�%%%�눈�����T�V��a����֏}��Ya�hժp{���������2e
�=���5���dddp��Ǝk.�v�/�����X233�����?.����n��v��nݺ��˗��/���#88�\��G�̙3V��LuDD$o���6??�0O>�$]�ta޼yܸq�ޡHn����aÆ4mڔ�� ����Oe�L�Ųe�h۶m1ET���c,"""z�L$EI����l޼��g�dq�nݺe�Z�"**�>���ΖG���ߟ�^{�~���G�ҿ�v���LL�޽{�u�V<�k��fq��͍aÆ���7oζmۈ�����Ǣ�im%ED$�����v���[����0J�.m�Њ��͛����l۶�m۶�~�zfΜi�ݘ1c��������C��L����[�|��̟?��ݻS�zu�^�:={�d��T�P�\wĈ�mۖҥK��₷�7S�L1'Ė/_���s�Υk׮T�\^|��{�v�r�

%00www�P��Z�b��O��k׎2eʰ}�v�v�o�N�r�x��K<f�?�'NX|�=��ݻ�5k5j���f�����r��ĉ;v�]�v1q�Dʔ)���Y�t��C�b�WDDD�\�d�H���,�7mڔk][;NV�X��#G2r��<�)_�<�'O�y.�de˖eԨQ�5�d̜um][�B�{�=�{�<�*[�,������p��yjժ��!�0�2e��;6����DժUy饗�\�2����^���G?�V�������2r�H�-[F�^�������(Y&"%��7�d�ڵ������aaa���[��)"r?9�<_~�%۶m�?��R�J4k֌�����eU??�<�|��СC|��W�ڵ���d���	`Ȑ!��e�O<��K���ݸq���06l�@bb"��ɔ/_�&M�п�MhLN�>��_͎;�p�nnnԭ[�^x�޽{[<mR�y˯�_~��#G���X�>M���d��<y�f͚1o޼B���^����6r~�d?6�W�{��ڵk�1c�N��jժ<��sS�^�<�˩���J�2)�K�f������DFF�777;G'"b�޽{�۷/ׯ_7�����DFF�~�z���K�.����իW3j�(nݺe.��_�ꫯؾ};˗//p����Àu&%%��={��0�z�*[�ne۶m̝;�֭[�ϙ֦LII1��e��% IDAT�y���x���Y�j�V��jժ��%1o�puu�(/J���׿�sbZ�0�Ω8�0)̽�.<<�q�ƙ�/^�Ȋ+���o�3gN��-�{+""r�Қe"Rb|}}4hӦMcڴi<�j����իW<x0)))�y�f>�ʕ+y��W�y�&C��zz�֚[Ç7�7���bcƌ�֭[�m�6�=ʲe��������|��W��7++������[��w�y��Tovs��!>>��~������IHH`ժU<�����_~iqͤI�HII�G�l޼��G�Oxx8^^^�;w����?E�����ox�NJ��ӧO�n�:~��g��-i#�zgٿ�p�.g,͚5#22�#G��~�zڶmKzz:C��ʕ+w�����"""�+%�D�D��g���g�ѳgO{�#"���K�r��e
Ę1c����Օ'�|�ɓ'ӻwo���Y�dI���߿��ӧЯ_?:v�h>NFF���
'N�v��899��SO��_�f���zzzZ|~�a���2d�����������S���>���777\\\hҤ	�}�p{���L���_����'''���x�g�9s&`��gq�[v���;v��ӧ���ЧO�b�sȐ!4hЀr����CjܶG&��w�5jԈ���퍳�3^^^|����s���|m�P��� <<}��G}�����"�k�""""��-[̯���ꫯ���s]D?99��C�r��-Z�h��#,��ر��ڍ�=�X�wV4���8y����?��c��Ԯ]������ݝӧO�믿��O?���;?��U�E�����ַo_ڴiSl}>���Ve�-�цIa�]v����Ѣ���~���s�N�l����8�L��EDD�;���(%�DDDD8~�8M�6ͳ��ӧs=7f�Ν;�������k��8s��>�h��˙h�����?~�ŋI׮]Y�z���/��±c��������aQoРA�9������~�v��ߟ6m�кuk�����c�rruu�F�<��t�ڕ�͛[�/j��Vv�-�ц-��w����?���$��I�n�����+�'��J�������慩�|�r֮]Kٲe�;w.+V�����
P�/s*U�*T���jժ��ٳ�:u�źgk׮���7���K���ҥ�˗g�̙���/\�`^��nݺ,Z��:u�E���<MW�>M��gW�q�RmdW�{�]�r�l��/_������Q�yyP)Y&rG�^��GAED��.]��ׯs�sB!��?�ĉqpp���?���+�>RRRHMM-pwӯ_?fϞͮ]��e���6�����/�L�ڵ�\�2^^^�6f׶m[ڶm˯���Ν;���!&&�S�Nq��Y&N��ܹs�c*�VI�Y�q�dP�{g��صk��P��]c�ǽ}����gH�|$,,��a䋒e"h�	��㉍��e˖���ƍ����1l�0^x�<�8|�0ǎ��׷8¶���a�z֬Y��sn��}ì�,J����f͚t�ڕ�]��y�f���g��+�EI���q�tE�w			6�f۷o
4�k���2�<)"���
J�����-[�$>>�Y�f���Z�7�v�Z�y�Z�lIhh��|ʔ)9r�v���u��M�r��a"""��eǎ��_�V�Zy.����`��i��N�:Y��>���t�-Z���|������u�
;oEQ}t��Ն���aX%�
s���yꩧppp0�ݺu�9s���5�ǽ}�i
3����k��d�н{w{� "�$��E���k��x�b���G�޽>|8
6d���|��Z�
GGG�n�fӦM,^���
2m�4�Ą-�z�bɒ%�\��jժѻwoʖ-ˁ�裏���^�׭[����_���dƌ�����5k��̙3L�2�w�y�ʕ+s��I���+sr
��ի�K��3gC�aܸq������ʉ'�2e
��SF����*�>:��j�L�2����~�zڶmKVV��΅�w����0l�0�y��ԩCbb"S�La���ԬY3_?���ފ����,�#,,���@{�!"��5c��z�!�������s�N:w�lUg„	4j��|lJP9r��{,׶M��׫W�	&��3{�lfϞmQ��'�$88�f�v����W_���������3���0�5B��w�}��ӧ9x� 5k�`�lڴ��Ǐ[$�Lz�!F�eq\�y+��賠�.�67n��ݻ2d���ĉ��w�}�ᇼ��{|�����ߘ3ge˖�s,�x�y�]�x�5j�;�"���C���8��jժ�}�ݺu���'''ʗ/ϳ�>�…��gϞ-pݺuc�ҥ�lْ
*��쌧�'���Ḻ��-j׮M���?>�'O�8ߣG�M�F�F�pqq�\�r4oޜ����aÆ�4����kʕ+�ʕ+8p ^^^�����與�}���ᆪV�Z�tފCq�Y�qGS�N�E��)SGGG�Ns���Ό3�����ɉ5jЫW/֮]���w����VJ����͏��#�+W�iӦL�6���t{�Z ���0f�~���<��ό3�����݋��y��Y�
_T��''''*W�̓O>����9u�T��	�n�����[XXYYY��oq�k�{����|@RR���͓)nɝ���U�/����I���"��1=Yf�g-�uu�҅��L�O�`�a�t,"%��ӓ�ӧӱcG�qHHAAAv��h����?�O?�4[�l����(�����z��\�v�ԉo���|\���q}/�>���1o�<^{�b�^��s�άX����%�V�q4lؐ]�vQ�b������+���s�gb��@��ХK����3/�{��9����sdw��營�_����'��+����{�=�{�=�@%"""R@�aX|222�x�"+W��v���ٳ������7n��8�7n�i�&<<<�qd�c�>���olڴ�:����o��ڵk�j�r��0n޼Ʌ�={6e˖e���|��W�5O�Ƒ�����			�Z�j9r��'�;T)%�D�!..��ڂ�q��v��n���̜9�#F0|�pf̘����������ٙ�z�.]��x�b-Zd�
.  ��ׯ纳�֭[IIIy ~�m���3իW�M�6DFF2r�H�`��ܸq�����5���`fΜ	�ܹs�U�9::R�fM���X�|9�~���S�L$rK�d�{���!&&��۷�)����7n]�v��ݝ�5kҹsgƎKZZZ��#"""RΜ9C����[��y��^�zq��a���Z)���bbb�֭ժU���OOOF�����3�<���Υ��3}�tZ�hA�*Uprr�jժ���+lݺ�f{�����八�+�*U��ח�>���W�ڼ���fbJ�����nɲ����غO�����2e
>>>�?��+WZ�+H��G׮]l�߂~/&N�XϜ9���/e˖�C�GӦM�ۛ$�r/��7z�7pww��ٙ�~�/�����﫢��F�a����k�s�ε�Mnj3�1cF�&�����t�=z�0���ٓ�K�2�|
d��DDDD����i߾=׮]3�]�x���pV�^ͪU�
��S�ҥ-�.\�[o�ŭ[��e'O���O?eÆ
l߾=_;�f��~��K�%''ӪU+bcc-�/_�LTT�֭#22���ۛ��ݻ�6mڐ��l.��� 66���X,X��]�x衇��2o�Z��L�2�]���k׮��͍֭[�:��o����(U��
�o߾DFF�ׂ*�~Kz7o�n���]A�EQ�

2_[�?7QQQ67��Wc����k׮?~��C��pAQ��:o�=Y&RLL�p���Һuk�����RSS�1c;v�Y�ft�Ё/����:
�.]b�ر<���<��sL�<����|����Šga�&/��;99�e˖��SOQ�zusy�5���cٲe?������˕+W�ڵ+���6���D��҈���o߾dddh��5������_��>u��֭[s��)222������b���|���7++�?����+W�)��;�X��O�����ۛ�~����T���ٵk͚5�0>��c�k�
Frr2���#11���RSSٲe�5����|��GE�7WWWZ�nMbb"����8y�$-[��uも�o�G&��[a笠�}�Y��JA���8L�g�Ca��gbb"�"))��>�,_�߸q���D�����oX�|����HZZ���*G��ƍ�߿�_|1ױ��]a��~�d�H.L���d��� &&�РA��~���$''�9�p�B~��W�"����:�b{�W�ҧO���{���IKKc���L�6���W�8�[A�^�~=������[����Ojj*6l(�XEDDD�뫯��ҥK�=��?�///���hڴ)�����w�%))�Y�f��ή]���1b���s���ƍ���̞=�z������s�=�ҥK�����NGGG�U�F�n�8�<�F��_�~ט�-�y��.]WWW�y��f��f߾}L�:///���)]�4�Z�2��}g�☷�^���+��uߊ2gU�N~����$Ƒ��F\\|��C�5�/̽(j�cǎ�q��T�P���a�^�vss�A��9���Z�j�رc-��Wc�ꫯHJJ"  �e˖��#����B�&M������9�~��m�4J���E��ﶸ���ٱc&L`ɒ%>|�ƍ��ݻ����I�&�ٳ���H�-��~�N�:,\����hfΜ���EQ�8���N��Q��w�����>jՎ��TGDDDĞL��!C��<߷o_�<ї��DϞ=��̤]�vL�2��M�l.C���a�:u������}�����(?}�4�a���cu���X��eJ��/��b>���a�?�\V�fJ�}��w�㼒e��v����2���}�����J2�)S��{��'r��M���Z�wU�{Q�8[�l�빼�)S�-Z0o�<6n�h�:���S�1;'''����쿨�������,���.��k����b>޸q#�'O�f͚��D����ԩQQQt��	��@��ѣ��7mڔ�#G2r��bWQ�,n��ѣ6���W��E{2-����g���
f׿N�>���K�.��������x�'
_�W��k�׮]����̚5���p���ٽ{���ep{]���x�����ݻ�;��lw�����Ӈ��h�����	�6m�СCڷoo�siq̛�����l߾���dʗ/ORR;v������+�k�����w�
*%%�
*ܓ~��=777j׮��O?M�>}x�,��^&NSr77�k
��?�`��Z�
���s}��^�%!!___��6 (��6o%�Dr��騩S�2u�T��ĉ�8q"�ū�����ٳg�ر��~L?�=6���[���/��(J�����ʕ+�/_ު���TGDDDĞ�/�]�z_�5�/_�o���ʕ+[�1�vY�\��zG�R��T����������)S5jk֬1�[�|9�G���ɓ�j�w��T�X�I�&����_X�`,��ӓ
6P�~}���f����o6n�H�Ν������̼����v���2==�3QS����$�
{/�gnk�����@�j�

%66���:w��O?�����]c�MQ�bZ�����T���~��I~��A�d�H1�[1��?
ٷ�vtt$33��'����a�ι �%��V��Mc-U�-rS����ED������r��R�lY�]��իW�X�b��MHH��w����%K�ШQ�\�HNN����nF���)Sزe��,<<ܼpyÆ
�֭��գjժ<��4h�f[���?��?��ٳg���駟�駟8v�'N�`�С濗�2oٙ�ek׮�s��Z��8�7)���
���~����ȩ0��^�Y�B/^L�-سg�ƍ�O>��XLOQ&%%����)����L�2�\���K���iܸ1, ::���~�Ν��v���9s��~��]i�W�G�%66�b�C�Y�upp�0RRR̿I���⎳���*U�p��E����~+���d�#"��7�|�_|��a��%4i���!ؕ������ܹ��_~9�ץ��ӣGRSS�0aB�O�xzzr����h޼yq�m%�:X����̙À,�e�%/++��/7�֭K�>}�ӧp{
�:��=P�y���g��B�
�[��0X�~=e˖���J�տIQ��nnݺe��I�����ߒ�-�����y��<�3f����Ν;[$.�ލ�Q�FDGG�k�.����;�5�?3-�/���.�o���?��1c8r��n�����|�����l�ۮ];&M�ľ}����$..�I�&Y�kz͚5���q��I���(�8�[A�~�G8s�U;�2S{z饗�����̴:�����h����ܹ�Վz9�~�
		�:�������e�m/�zh�_ξ���V�?��s����W�V�6w8/�����ċ/�ȅ�ҥK�n�WW�<�+l���r�"_�9+��c�����۷/r���-����n���ݝ��,�}�]��g��X������'�p��-��M�f3��s��a��FXXX��&#F�0|}}�u���a�����k���Vu}}}
___����d�K�.���?͛77�9b�{��
�O�>V�������㏭���V��v\�8�jǖ��P��W�Ze���.��g�…�����f͚|�%.aaaF��r�_W�Ν��;'N�0N�8at�����G�{�>}���`������"+ȿ7�Ν3*V�hF�6m�ݻwiii��͛����...������~�5�|��?��q�����s��1�������߸x񢑒�b�������~���5��c�͛7�'N�&M2\\\�X�d������4.^�hdffqqq�믿nq�Ϝ9c�fԨQ`<��Ɔ
��ׯ7o�4:d�k���nݺi�rWHH����7c���w�����/_��+V7o�4nܸQ�9��>ݼy���_���H�m۶`8;;۶m��W�~��8�0������8�,Yb����ͽKRR����nF�v�7n�0�nݺ��ߊ��>��700���>��0���������0m�p��%֬YC�ڵy��z�*QQQT�^ݢ�iC[�_�v�����-[�p��%ʖ-������V;񤧧3o�<֭[���_�5kƇ~H�6m,�OKK�/�`�ƍ������Ǹq�̏̚�匫��̫���C~�NII��_�Ga޼y���׏��D����tL�ݙ�t0����X���t�Bff&ӧO`ذa�c)���L�>�
���'!!!�9��)�7QQQt��5קX���Kh>���c߾}w�#{�������f͚5c��͸����
��k߾}-~�7o����Ywܸq,[����DV�\I�.]��?�5m�ԼK_N�j�bǎ��t޲�+�<\�p�Z�j��Μ9Cݺu󼦰�?�������-̜e��nʕ+��ŋ�v�/l�%5��LV�{QRq�w-Z�`���Ԯ]��G�Z���^�e׮]����\�z��E���o�Kq���Ŵ�ZXX���L��e��d�� ɩ?�9s�š5k�;��?�N�:1`����k���,��(Y&bJ���cǎ�駟�q�F.^�H�2ex��1b����+W��ܜr��}�v�L�Btt4���ԯ_�^�z1b����J¸�����NӦMy��7ͯfe�h�"�O�NBB���<���:�W^y�ŋ��o��/�q�F�5III|��|��7�:u��7oR�^=�������jժi޲�+��������yY��]S��O�>��پ};7nܠF����/������*U�A��mۖ��`z�!�u�oI��(?��^1Tr� IDAT�D��ǡC����!33�q��1a„{>��g�2i�$���;~��w~�aƍGϞ=���^�2�?%�liiit�ޝ�{��#G0u�T~��'""",~s*J�In�,�%�DD��AK�i7Ly�.]������������?���e""���ӧ�`xI�����s��A�q�OĈ���܍�e"�@�eРA��\��������:u*111DDD�W}'$$�g�}�a>�z��Ѱa�{����<ؔ,y@�Kk�������""F���(����ә1cm۶5�{��/���?�\O���H���w""""���ݻӽ{w{�!��f��\�B@@��,  �+W��f�;F&""""=Y&"""r�|�2K�.e������R�V-:v�H�-,ꥤ��b�
v���իW�\�2�<�ݺu�ئޔ�6m.�رc8;;ӬY3^�u�SWYYY�X���;w�����Dݺuy���iӦ�E[ٿ���0=~�x�M����~��E��l��mܹ����BTT�7�o���NժU�&**�:P�lق���R�LDDD�>�����ѣ���k.;{�,3g�$++�V�Z���ʸq�8w���ڵk9t��&M�z�p���\�~�7n�q�Fà�����"##�3339v�ǎ#--�����5�����B�*UJdܶ�ر���t�4ibu�I�&:t��;w���^DDD�%�D��ٻ�������r��|ç�Ć��|��g���1r��mf�������Ú���9-�a
Y�	��s� K2����>���u]u])��ۭ�~�_�w�z{�_��k�HY�!DQ�]�m߾��w�booϴi�hР������/DFF*A�;vp��u����6mvvv\�t�U�Vq��5�m�ưa��궱�aʔ)4jԈ��H"##��ߔ`�/�����7���*�����İ~�z���0`��,2mI�mmmY�x15k�,�q�j��?����N�^{{{��˄B�/	�	���;�!�S�����ҕ����������;kkk�{�=%���ĉiٲ%���
�._~�%����F�l���J� 22��*�MMM���䧟~��t�ܙ�}�ҷo_��?`��e�����|�2P,JuLUF!�B,��B����T����[��?�
d�988��S�����*W^^�rl��ѬY����Dٲeo��6������D��7i�D�rE�;nm�ݻ�5'�ꘪ�B!�>$X&P�Z��������WtD�O���G��_Eը��>m�8;;Ӷm[~��w���Ϲs�c׮]>\�e��f����+m���h��q���^]s�w�1��ς�9B��1����7	�	�_�
�R��
!ԅ��J�AQ�5jԈ[�nq��5%ߖ6VVVܸq��g�Ҷm[�ٳg���,U�u�ԡgϞ��ٓK�.q��Q�o�Ά
J��Z�j��瓕����y��5�r��[���듖�FFF���W;�������t��MV)!��6mZ�]Л˄��w�yGr	Q����H�LTy���:�w�&00�3fP�n]BBB����q�Ƭ\��N�:q��
����6m���\�t����бcG�۞:u*���L�0��ݻӬY3nݺh�J���'%%E�/����9���c߾}��曤��)},͸��ݼys��Ҹy�FP��͛J!�B}I�L!���x������L�<Y����������HIIa�ܹj嬭�y��
n{РA����~�z��V�֭��U��ӧcii��իu�٩S'~��6n��ƍh߾�F9}ǭ��:����ŋ�	p��E�t�C!�u��!F�Y��B�JoĈ���Tt7�"�2!��������_~��4+++���ʵ�s��i$pvtt�(W�zu�իG���8q"/��r��I�~BBB��Q��'ccc,,,prrb̘1���fl���=z'''�;�	!���XVU�~}/^Lhh(���<z�M�2h� ����r�k���/�$<<���x���/�ׯ�����N�:�ݧO��������4nܘ�;��榔;v,������i�?V��ѣ�^�:G��ѣG�iӆI�&1iҤR�[[�]�v%88�cǎ���V�c�033�����!��$g�B�V�^*H�L=�>}�6mڨ}~��W˵ݏ?����������ݻ8p���x6n�X�ք?+�?��͛DFF����Z�C�������e����:t(-[��:sB!�aeeŌ3J,W�NƍǸq�-�+��*_Yq���5�O��055e„	L�0���[[۵jբ��DFF������P���ٳ2SS�b�B!�(Ls� !�]�2���r��b�'$$(���dz}�v^�u>|�5'̋��}:|�0�6m��ɉ��L>��S���4��#++�y��1x�`��������ݝ�s��)��|���aaa��]��c�v���ҒT`τBQ��2!tж����???��U�X�jU�X�X�zu�4i§�~ʰa���*�K����	�Z�b���xyyq��yv��Y���������2l�0�����ټy3���yw�χ�Zj-�镞��)S�L᫯�b�8p��>��
�Kߔ�jբe˖�?�B�.M�Q�III�=KKK~��'�W�=G$//777RRR���C�O�{�=�&�6D���2!�H^^�֭��ݝ.]�н{wƎ�uw���LV�Z���+]�ta��Y��Ǐ+e
?�8::j}�ѦY�fܻwO�}��4i=z��ɉ��7ߐ���V��?�d�����'''�
�W^�+VЫW/V�Xap�iii̟?�^�zѥK<==ٳg��q�s��Q�fMƌ@LL�r�h���Ǐ�W�^J��������ԩ���
�8::FFF�A}BQz�[�fذa����5�������Ebb"3f� >>��{V�Z�n����o��СCŖUm�bgg��eϚ*m�'�|�̙3Y�j'N���n	Q���2!tP��9�<#F��Y�flݺ�ӧO3f�Z�lIhh�R��ח��`�sNN�N��ԩS<|�PyPy��1�&M"))I)���B@@�O���׷ط_%�r�
�5R��]��r�n�",,������_������iiiJ��/2�|�<y���/j��億�ЦM�{�=��|��!&LP�I�={ooo�v�ީ�]�p�IJ>>>ddd(�������L�o^������gϞ=xxx��!D� 3�*����ӿ�����>)=�`s��w����ˎ;�����ܹ��b����`���l۶��ݻ�,��?����<�eEӆJڐ��jժ�L�!DU#3˄(A�d����GFFK3��∉�a���lٲE)�i�&���x��W	

��~#<<����ώ;�/P}�h���r��-Z@�.]�s�7o`���>|�#G���w���۰aiii�nݚ��Hbbbx���ڮ��!!!��ٱj�*���j3$$��ׯcccC@@qqq������2���aÆ���_%��������J�����888h�US�B!�0d���V�Z56lȴi�����]�=zz����v��>|X�Epa������`jj���u�
IMM%00�{&D�&3˄(������x��!!!$''ӣG�����ݻ�%K�`ccb.\ȠA����bРAz�M����9�ǏW>��Đ��ϙ3gؽ{7.\���J9�4�O>�D�IsΜ9̙3Gk;>>>���bnn��ի1777��(�v��Сs��U�T���<y��5J�����ccc��s�-{-�y��je�B!J����ʕ+9t�YYY���3z�he�}���������w�^n߾���o��&LP�W���(Z�6��u��Q;��z]����������ɓ���ЧOf̘�6��Ν;�^������E�^���,�F��v�
g�Ν�;V��]�v������u��ջ��c���c�̙�lْu�֑�����{��!%%��5kboo�����s��{����������Ν;XXXЫW/�{�=�߉��Y��!�F�R�.��	�	�C�@Բe�X�l��yѢE�,���f̘���ѣG9z�(k׮eܸq�1Bm�k׮��ꪵ݋/���FFF4lؐ�;���*Ӭ�����?�̙3����+?߼y@#	�.�e�ܽ{KKK�ۼz�*����Zm9#�ީ�26hРIJ��Jzz:�և�1U!�B��TdZ
��w�r�J�`�٧1q�D%nvv6[�n%//Oy�����q�q�rMtt4>,�nC����Axx8;v�`̘1T�VM�.Una�����ۢ�:�M�Rԃ?~<���ʱ[�nJ||<�
��
��$X&D�۷/NNN���l߾���D֬YæM��2e��%T8P�M�YW%�7��e�8s���������ޞ6m�h�S��$#F� 22���l֭[�����m��/�R������jժIJ��$����aTu��)�xvv��AnnnEwC!���/���S�N1w�\RSS��NK��퍽�=W�^eɒ%JZ�A����P�2m�\]]���լY3.\�K/����?8p@	�lܸ�7n`kk��ŋiٲ%�N�b���%֭����i׮���;vLm�Ǐ�ڵk888(��R����ʳb��,�������ҥKٲe��`Ypp0���4i҄E����@RR�����ŋi�^�}�7m�˄�$9˄�!!!???� ?YBB�V�
f=��~�077�����������jA$Ռ��;w�ա��<vRm��34������K/���裏�������p��ikk@bb�����l�]NN�23�G�z_���@�讣���dAQy�o�����=%m‹H��L�Nۅ�MKQ�fM%-EQ��R�l�###%-��.��9{��ҟҚ5kM�6���D	ݿ_9�믿���M�6m��~��g%�m�U���;ԫ�N�R�{[4U�j�WHH���ܽ{������Pl~]mڵk��.ܿ��5%�gI"D���2!��or(��~��
fϞ���-Z��?��5k�T��ٓ�� �̙ìY�hѢ���6mb�ƍ8::�n�:�`fR~~>׮]Sr�=���8���Crr���
�T6lH׮]	�o�aɒ%ԯ_��+W�����PQ�ȑ#�����ŋ�]�V	(���o�ɥK��ꫯX�h�Z��̙3|��Wmr�ty��.\`�ڵ\�p�&M�Я_?Co%���
�n���իA1��R}��
!�-///���*�B�����_�>|���~��o��ooo�߿��{W_����Ϫ��yyy�1�rSU�Z��������Ӈo������s��}��͹�>���N�:jρ���ESu蛚�(Ւ�v�کW�U���J�ϒ6D�ғ`��0$X���Œ%KX�t)K�.U;W�Ag̘1��믜<yOOO�r���|����
������;����ܹ�T��ѣQQQ̟?_��g�����رcٻw/'O�d��je�}�]�u�����㉋�#11�v�����ȑ#����ʕ+�3��qr�
+n#����Z-����]�r��AN�>�� ��s��o\���}���+�(��˗�<<�JJ��ME��P�]�6�z���_����`Y~~�ҧǏ묫�Uqc(:}6]2t����8�M�6�{�n���ݻy��1o���Z�4��h�}S��p𫨒
��$X&D1��T�hk����S�F
��ÕĜ������j3�ԩC@@�ׯ����R�vm:t�I�x�嗕�3g�d���ܺu����|��'���˓'OhѢ���\�|???�lق��3�5"00___��������_f̘1���[g�m۶���&22��kײn�:�۬U�~~~���Ã�����ӓ���=�r�t166��ښ.]�0j�(e驡���NJ+���e���j�bcc�S�o��f��B��5j�|���ϵ>����Pe���r��%�ܹ�r\WZ��W��s�N�
�ʊj����T�>|��/�TP0���d�?��|^��]�Ҍ��ݝ���o��СCپ};�Fબ�*5���+III�۷�
6���3XfccÕ+W8q���ߕ�'N�P�f�F�q��-�ݻ��B҆Q<	�	Q��y	~��b˫�Kbnn�G}�G}Tl��}�ҷo_��&�W�[�.K�,�z�hW�e�k���[m�&C�lذ��쳔�,,,Ԏ�{�t���kt�Q�vmF����?7nܠI�&@��'N0q�D���������-��I�L啖�yyy\�~]y�ЦM�j�öm���� %%Ec%�!����f��,Y�_|A۶m9w�_~�e�ז&-GӦM�ԩ�������СvvvO]wQ��f)�G��d�-ZD�֭IJJR��fł�
��$X&��Pݻw'33�ٳgӷo_�ԩ�իW����rWT///~��'BBB�5kP�����Zc��B!�.啖����RUԬYSm��=zɊ+X�b�ڌ0Cyzz�o�>Ν;���_�~JG�Ҧ���� >>�e˖h��Vں�75�����ϵk�7n�ڹ�M�jӇ�
��d7L!D�R��X�t)�z��s�μ��;$$$РA��޺�<ժU���c�RRRHIIaǎ,\����BQ�+W�h=���J@@ӧOg�ȑxyy1k�,"""����U���P���,[��e˖]&u
QU�E�0UZ
WWW�ׯO�5hٲ��9���#F����###��͕�I�g
͜9�&M�`ddTbJ�5j`iiI�^�����i߾�r��?d��ԫWccc����7o^��1~~~<�
`ll̛o�ɜ9sJ�֐�֣G5j�_�EÆ
�ٳg��]���;��ϧU�Vcll���=cƌ���?�y]ݺu	dȐ!XYYadd���Ç'((HI�o�~��affFll��9I"D�嗔�P��P�j�		aĈZ?�g'//���0v����˗y��1/��]�ta„	XYYUtKʱcǀ�7�Ç����BCC9r�����g����� 77WYZ��Ps�-[�������Վ_�r������:KKK-ZDÆ
���i�`(��o�����|fΜ���7�Z�z�zE�aoo�������R͐�L��MJJ
���F6&��n�:���ٶm�ZڐA�1q�D&L�P�=/��#G+q�}�dd��BU�^�#FT�@eU����5�$((���,ڶm���'�����撜�LPP�/_&44��S�[�����٬Z���}�bii	@�>}X�r%>>>2�V�"�rZ
Q�I�!JG�a
!�Bh1d��R����L�>��͛cdd���	̘1��ǏWd�l۶���t�M\\\��BuU9-���$m��#3˄B!J��ݻ���p��q���������MI~]xcvv6[�n%..���t4h�o������;Z��gU����Ν;ܽ{��u����Z����9z�(?��3�/_�ѣG4hЀN�:1|�pLMM��V�1<|����(^}�UeY(�nܦM���8p �k�6���5kM�6��i)D�ձcG&O��7�|��)S��l@!�2!�B�eee1�|���O���˗�@Ya999|���\�tI9v��m"##�p�s�̡z��'�{xx����…�ݻ7:t�E�Ԩ���\XX���j����ؽ{7>T�pjc�>Lvv�Zrp����s��)�9"I��(�yHK!*7��%�a$X&�EDD��BT-��ٵk��'VVVL�6
;;;Ο?�ʕ+IOOW+�s�N.]�D�-x��wiڴ)7o���ϏS�Nq�z��Mxx��l.�>}�`ff��͛پ};۷o�f͚���+t�ܙ޽{+�a�ꉊ�`„	��уjժq��.\�lR��Z}���`gg�q����2,B!De%�2!�k۶m�GE!^`��=N||<�-[��u��L�4�%K������
򍩖R���S�L�> 66V	4���ggg���9yI�]> IDAT�$III�={�ӧO���?3o�<�e�E���Orr2���\�z�ӧO���Ylۆ��������hԣ:�*#�BQI�L(����B<�n޼	������RRRt.s�v�Am���aggǠA����a۶mDDD����w���_����q���AC�p��=�9�T�Te�B!*#	�	���B�����5!�U�ώ�%��
2U�V��2E�4�k���dgg�n�:��c5k���͍����'  ���d7nL�N������_棏>*�:CǠ��򰩎i�OBTu�<)��EDDT��y,���:z�w*�'B�Ғ�e�Yjܸ1���8w�����r�ܹse---�y�&�W���������HJJbϞ=6L�j�[I���i�/�����ׯ+�<y�����k
C���IKK###���뫝���P��hڴ�<C
!D	�y�����Wt7�&�2!�+$$�JE���BCC9rdEwC� ���ٲe��=|�vvv\�t��^�l�Νٶm��׿?~<͚5���ڵ�;vЦM,X̸���'%%kkk\\\HJJ��$33�>}�`mmMNNIII)�h�G�ĉt�҅�ׯ�v�Z��W���k
C���IKK��͛A1U`�y��Oq���\�u�F�n�*�B!ʐ˄B!Կ:č7�3gN�e
�������O�Ι�����|677�޽{L�>KKKV�^M�ΝquueǎDGG�ц��
���%����/���u\�|����k�֐1t�Ё��.^�H�֭��^�x��;{τ�J�e�B�gĈ���Tt7�"�2!�B-��Ufjj�…	

%!!���Llmm0`���ԬYS)kffƢE�غu+���ܹs333:t(M�6Uʎ;���P������Q�{zz��k��g�.]��_����M�4���	LMM��g�ر���r��q�<yB�f�0`7n� ""�ݻwӾ}{��2��]�̱c�puuU�oǎ���gg�R�V���$g�B�V�^*H�L�J��������*{�v�����o<x@�V��իnnnԭ[��m�7U_�211�Y�f�9����?�^�m��ܹs���+�%����ѣ899I�b!�T�^=��}�c�o��A�j��ԩ�����,m���u�ڵkG�v��꛶zj׮͌3��/�oIW�C�Z��߿?������bee@jj*gϞeȐ!j�=!���L!t۶m[Ew� ,�9�����ٳ9r���'Or��I�?>=z��ңG�8�<,�N�:�����.���?���Vh��?���ח-[�����СCiٲ%�۷��>	Q�v��0a��Θ��q��M���hժU��b���î]�7n�v���ҒTp�B!�'�2!�#s���ȑ#XYY��ӵkW�իǟ�Idd$���|�駬_�^m��ʦh�(==�+V�ƍ�l���<XA=)���ży�<x�����ݝ�s�A�Z�*�BTfݻwgϞ=�_����׫�377�gh���2e����+�z���011���	�b)n�!�����ж�������3f666Ϫ��Te\��"+;*��B�qttԹT��:t���X6lHPP�aÆacc�ԩS�4iO�<a͚5�]�4lؐ�3gp�̙
���#00���T�
�>|8���V`τ��ƍ���vvv���P�zu,--�ӧ˖-S���Z�nͰa�$00��Çk$�B���?�Xk����L�M��'�|Bll,���<~���'O�b�
�����_�}��c�~�<~���7oɰa�8y�d9�N<K���|�	3g�dժU�8q���%���eB��}���ٳg�����‚=z0y�d��̔rw��a���<x���,z�ꅷ���:�-�s�NF���iC�%??���A��#//???���CJJ
5k����777
�ԥo�����P�Z5�s�������w�^n߾���o��&L���X)�
t>|��K��w�^����֭ӦM���B�ތ����ؿ?w���‚^�z��{�Q�N��X��U�k�7Y������Ϗ�3gbmm���iР���T����!׮]��ݝ&M��}�v222�S�Nj^7n���#aaa�5J�*�C����߿�Σ�,�=�b����F�JJZQPxFӣG��|�2���=z�O?����H��_��Ռ2Y�QuH�L�2�v�Z%W�ʭ[���|��@A dܸqܸqC)�Ç5�4��S���]�t�]�6�Ǐ/�q���������ԩS�:u��*o��-�K~~>���|���i�F��Ǐ�4iIIIʱ��8}�4���jA#����Z	.fggʼn'شi���<x���Ǔ���vBCC���'  @	>�3�]222�֭]�v%  �_~���}�*ebbb���c?��3���Z�x;;;Ϟ={���л�B!�Э�,9+���K3�j333֬YÚ5kX�vm���dbbB�V�X�|9^^^�?��;w�R�瀮��7o&00�ɓ'W`�Da�S�2�y�ffϞ��Ç9r��}����J��7r��
lmmٰaqqq���q���:
){���4i�L�	��U����#&&�ٳg�e����Z����H�N��ׯ{���Ȉw�}W��M�HJJ��W_%44��~����pڷoO||<;v�Ш�СC�\����8�����͛lڴI)Lrr2M�4!  ���8��������ŋ=�?('$$(�
iW��ΎÇ��_0r�H���4ʩ�eo��P0����A�>�1U!�B����4�ϟO�^��ҥ����ٳGk���LV�Z���+]�ta��Y��Ǐ+e��bW}�w5�ᅬ��������[�����LJ��S����˲e��޽;�z�bݺuܻwooo�u�FϞ=Y�`���`��=���?�[�n��Ջ��瓖���_C�u��E&O�L�n��ݻ7_}�YYY�c}���(I͚53f�g��O�{Y��V�s�_|��{���ٙ�s璙��u�����ɂ�ӧNNN6���(����/yyy�[�www�t�B���;v���������z_ij'3˄(��/������!??�3gΰ{�n.\�����E�����̒�С�}�ӧOW�א�FFF<y򄼼��
������< $$���dz���<x�Z}��+���m۶e�ĉ�~�޽,Y�DI~jgg�…4hQQQ�=gϞ�̨j۶-s��aʔ)8p@y�s��`�B۶mh׮���L�:����+e�b�*������,7�W��&88�#G����LFF���Ԯ]�:	f�5k�ч�͛��B!D�z��!&L��ʱ�g�jM�Q�Y���v5Bif�/[�Ly��~�z�4iBDD����l~��'�W�΂Ԯ/��*'N�޽{J�[�n%//�9s����%�YZ���,/���1nCVʔG����xyy�/^����y�䉲	���E�U&���j�`�e$--�?�Pk���|�g�C�*���k\gHY+++�_�NJJ
vvvZ�����Ç��^�v3f����?��ѣ=z��k�2n�8F�������
SͲ��>�>W�^孷����v����Z�x��1'''�Ϫ�����/�v�ک�U��7o>�u1�]UpK��ӓ-[����3G��ɓ't�҅5
��OOOК�LuLUF��QTTo��fEwC!		����ذx�b8u�s��%55U�l�Y�������s��U�,Y�̪4h�Z���3�K����E����@RR���Sf�}�w��i6o�L�f�fݺu,]���-[�u�V7n̆
���Ә9�[
ЩS'Μ9�ܹs����Jӯf͚�p�B^z�%���	�J�E�{�o��~�hذ!���r�4���^���A}���ŋiٲ%�N�b���c-��7l�@ZZ�[�f���XXX�|�r~��Gt��K�U&�������ҥKٲe�,�we��*	�	Q��_f�}�-[��3g�`kk�?�����iӦ�FnU��p�	P��-۶m[�_�Α#Gt���3v�Xڴi���?FFF�G߾}qrr��_e���$&&�f�6m�Ĕ)S���-����9�����ˋ����
гgO��H����A�f���h�žf��*n�`�M����Ã��PN�>�,�U-���m��m̪c�6S�y����|P��B<�Y��mfy��;w.ӦMS+_�Y���v5Bif�Ϟ=�-Z0b�֭[ǣG��Vf��5
???evP���r5�ʬY�hڴ)#G�$  ����+�Ks�K����<y�?���ʊ��!+eʣ�C���'�(��̙S�?C���*Y�Q�H�L�2r��QhР��t���\jԨ���-���?~\m
��ӧ5�4��[o�ETT!!!���(o�TTk�����߿��@�!。`���+���$%%�o�>6l؀���Z�H�rڴjՊQ�FĒ%K�ر�2U��ښ�W��s�NeG���<yR�A��?��o��r��Ɔ+W�p��	����+�U�:m�i�X����2j�(~���l�‘#G�^���r�F�q��-�ݻG�F�ԮU=�=.��b���,_����!���W���T�
+ͬ��J��4��_y����K!��핟����Whk_�\Y8xX�{\R���Z>�z./m���1nCVʔG����?��0�/��2��U�˄(cqqq��Ӈ��de�H(XRذaC����f��,Y�_|A۶m9w�_~��F]���ҥ:t���3��S�ҥKLMM9�<�}�G��k׮z��*innnܸq�ٳg���B�-���$#Uѷ\qƏ�޽{�q�~~~̜9S9׳gO����3g�f͢E����_lڴ��7���$�U���/Y�h�Z��ԩS,Y��~��)ez���-ZD�֭IJJ⫯��gi�v�ժU#??�k׮)o�i�8��������?���O�v�_��r��W^�֭[\�zU#(�z`7�B��bÆ
��/
///���?oY��RtƼ�Yޥ�U_XY�FP). dbb���>����W�~>+�{\R��u��q���Jy��(�q�fUMY�_�߅!}�w����Z$X&D�ѣQQQ̟?_���g���쌧�'����ܹs���{�~��)A
C�,]�����K�.iM۳gO-ZT�_����ˋ%K��t�R�.]�V��[P}��V�Z,X���'����2l̘1��믜<yRc�&SSS>��C��6l��,�Һuk�����s��5ƍ�V�iӦj�J;�
������;����ܹӠvK2z�h"""� [׮]9x� �O���j梾�9!��'N���KEwE���ԟ��-�.]"11�Ν;+�5ʖfV}a�]�PV��
Q�������
<����ʊ��!+eʣ��^z����?\�x�֭[�}��}�g����Z$X&��{��'����Kll,O�<�E�xzzr��e���زe������ǪU�طo>���s����V�Ӑ�P
&<<�_~��˗/S�Z5������P{�z�q���S�F
��Õe�������xyy)��[�$:t`Ȑ!lٲ�o��___�ԩC@@�ׯ����*�>N�4��_~Y�.,X�ѣG��~&LP�U�n]����_�s��5�w�޼��jKAK;ƙ3g�z�jnݺ�lAmH�%�]���s������׏+V��ѣ�����R�N��x�����RL!�YTTTEw��x��7�t�_}��2��̙3�����U�m{iW#���wC��j}�f�BI��.ty��.\`�ڵ\�p�&M�����VV�Ǹ
Y)S�w�ڕ��0����,YB���Y�r%��������?j�ΐ���DVvT-��K�_(�s�Z�j���0b����󩴻UU���|��4k֌�[�j�_�n���l۶M��ƍ4��'2a„g���ȑ#�i�E?�������JpL5�T�eB�/{{{�/_�������ߠYҕQi�o�{���bԨQ\�rE��<x��1c��555���_�w߾}�H�Y�P�I�A�j���222���Rr9ִiS�����z�ƪ�q��v��i̮kݺ5�ׯW^r�G���֩�wQ�2esss֬Y���4���^�Ǹ?~�رc5���Oy�_���Ν;�1B���/��B�e�4"##��cQݻw���G�ܴi�4^V�r�J�͛����ֺ�:ծ�!!!Z?W2	�-BQedffr�����{� ٿ6^^^4n�X�*$$kkk�%�B!�x:			:_�ժU???\]]�_�>5jԠe˖J��³�U��G����5FFF���+3�
�L�9s&M�4���H���[�0}�tڴi����kצw�ެY�������Z��7�}Ȑ!XYYadd���ÇWH�%�u�F�5���b��Ѭ[�N�j���!�X_�~�ӬY3�
��͛�e��>��<ƭZ)3x�`4h���1o�����(ˣ�F�H߾}�[�.5k���������t����ݝ���ӪU+���166��ޞ1c���+�뇙���S}a����e�$3�^L/�̲�o([�l�ƍu&�=v�ӧOWr����;�\�R�|r���,�T��eW�\Q��/,55�]�v���HZZ5j�ॗ^�S�N���[j;�W���P��ќ<y(H(�����U��,{z)))8v��Q�WV/�3۳ ��ry�VvBf�	!��PVVV���еkWV�XQ�V;vd���|��7|��7L�2�Jʄx,[��Y�fi�r�
�|�	��Ѥ�����CVVW�\!""�O?�Tm�y]�<Mu��BCC;v,cƌ!44��g�>u�B<��w�#?�����'//�˗/+�R^��
��,�ʎ�C�!^/�5C*�1BfU
Q	�;*((���,ڶm���'�����撜�LPP�/_&44��S�[�����٬Z���}�bii	@�>}X�r%>>>K������?��ug�
��.���jժ�…�>}��*eǎ�\�R�+�Y&�B�Ő!C2dHEw����0}�t�7o���&&&8880c��?^�]T�m�6����r�������ζm�*�gBT^�f�⣏>��SSS�W����5���(˵�U���df�B!����򈈈�ȑ#ܾ}�5jдiSz��I�޽��fgg�u�V���HOO�A����xxx([�ʩ~�^�zܹs��w�R�n]������r%�s��Q~��g._�̣G�hР�:ub��ᘚ�{�>cx��!QQQ���4l�P9naaA�6m���b�Ԯ]۠�-��z��2ӻ�e5�� ��r���+?�Y&�Ba���P�n�JJJ
���dggs��y���;v�ڥ�������?g���������۷���d�ҥ���ؖ��.$$$�3gΐ��kP���������7���<y򄴴4v����닽֐1>|���lڷo�QO�������ȑ#�]!��Y��eB��ȑ#�9�B����/x{{�ꫯ���KLL�ׯ'::��s�N.]�D�-x��wiڴ)7o���ϏS�Nq�z��Mxx��l.�>}�`ff��͛پ};۷o�f͚���+t�ܙ޽{+��tգ�e8a�z��A�jոp�.�رc�^��������4��R��7�,��B!�(o,��!�x���OV�xxx8���dff��O?q��u:w�L߾}�۷�Zٸ�8� ߘ�����ǔ)S������X�����3���$''s��I���8{�,�O���f޼yj��
&??���dbcc�z�*�O� 33�ض
��˗���ѨGuLUF!����`�B!��F�͚5kHLL$11�-[���oӿLLL�r)))�N�E]�v͠v��찳�cРA���m�6"""��?�y�ݻw���INN�8���_l����޽{Zs�����񼉈���.!D��;�S��Л˄@�l!D�S�?��Х�,c]�"�`�W�� IDAT۶m����ٿ?�Ν#,,�]�v1|�pe�aIK��5z�h���Y�n��̱�5k���FDD�����@rr2�7�S�N������/��G{��c�V�P���(�1U!�7�<)��	�	�_!!!�#�UXhh���T�:u�ٳ'={��ҥK=z��۷�a�%Xfii�͛7Y�z5����aggGRR{��aذa�o޼	hN�
�-^�sss�_�����	FFFZ�5d���'--����ׯ�v.##C)#��Dv�B��˄B!4u�TRSS�0aݻw�Y�fܺu�5��xչsg�m�ƿ��/ƏO�f͸�>�v�bǎ�iӆ3����III�����������̤O�>X[[���CRRAAAJ;*��Q9q�]�t��]�V9���ի��ZC�мys��Ҹy�FPL�k޼���~!*�C��r�ʊ�BTzݺucڴi�
�H�L!��@�
��Ϗ��׳~�z�s�[�V+���s��y>��S�r&&&xyy)���͹w�ӧO��ҒիWӹsg\]]ٱc���DGGk����OO�뉉����___�:._�L���^k�:t�@BB/^T�/^�cǎ:�Uѵkת\.!�x�"""�ݻ�	�	Q��;w�W^y�T�:::���P�]*�����9z�(NNN��CQ)�Sr�>}022"::ZY�ظqc:v숛��R��̌E��u�V���s�fff8880t�P�6m��;v,���������������^cϞ=\�t����###�4i���...���[�رc������<y�f͚1`�nܸADD�w�}��Z�5d]�v%88�cǎ���vώ;�����Υ�uQ����B�[UK�"�2!*��?���VX����������e����:t(-[��}���5!�0�*_YI�ԩ�����,m���u�ڵkG�v��ꗶzj׮͌3��/<FW�C�Z��߿?������bee@jj*gϞeȐ!j�=!�B�ʨ�l�B�
s���B����b޼y<kkklllpwwg�ܹdeeUt��B�777,,,صk�rl׮]XZZ2`��
�B!�~$X&����p���������6|�pRSS	���	!�(+���L�2�p��mn߾́�<y2&&&�=!^8�Ν�y�|�����gggƍǦM���kE�R�.���ptt䭷�"//��k���8p ���?~�Ytx���	磏>⣏>�%͢R�e�B��}���ٳg�����‚=z0y�d���ݹ�
/��T�|FF~~~�߿�;w�`aaA�^�x��S�N��3�Z}�p��V�^����ʢW�^x{{km;,,�N�:)�r� Ǐ��#aaa�5��u���BTz�[�fذaʋ��Çk$�B�?]i=233�={6G�Q;~��IN�<I@@��ϧG�ϰ�Ϸ¿�֭[���3g8t�ݻw�y�o��FJJ
vvvt�����ّ4-�2�`�ed�ڵ�����u�aaaܿ�/����x���Ǐ'99Y����P���	Pd��Z}ǒ����q�q�R.::��j����?����5���3����ٳ�B�ʪ����߿��!�MWZ�9s�p�����x����ڵ+�����?�$22���`>��S֯_�k����{�|*�����`���l۶��`ُ?����{����g�7�h�@I�A�Z��I?�(J�a
QF6o���ٳ9|�0G��� 66֠�
9%$$(����INN�I�&���?666\�x��� �ur��cٸq#7n��֖
6���.\�h����888h�SS�B!�x�T�t�"66��
��iذ!FFF���0u�T&M�ē'OX�fMEw��կ_?j׮��ÇIKK�Z&==���LMM�ۗ��ETV2�L�b�z�)z<!!������9s��w��…����@����p���m`۶m��Ҽ���:u*���g���O}��c���_�M�6t�Ё�>���ӧ�����ЬY3��5o�\��B!ċ&--��+Wr��!������g���Jz��/S333�g�޽ܾ}�z�-&L����1�δ;w�`ԨQj�1
:t(����j�J�)=T�=zv��E�52d�&M�޽{|������P�fM�w�άY��]����f�ҥ�ݻccc�u�ƴiӰ��x�~�������ɓ'111�O�>̘1Cm�>�X�:u�.���Oxx8;w�d�ر��]�v�����g�â����bAE�Wt�%�QQK��KK�![\[	��"�	qc#l�
++1�(v�QTl�(�Z(����wof���|���[�9s���}�9�8PNU�m�6m����i֬������i�&>Lrr2XZZ2d��������"M��:�2A(#�=b�ܹ$$$��S(eR�4ݱM�6J�۶m��{���\M_˟�	 �
��ߓ'O�~�IۤcAA�%L�<Y�np���y`����6m������d|||���cݺu��>�(66�.]�zL�j՘4i�Ҷ��Y�z5AAA��[�l�A��������������*����)����

%&&___LLLJܮ�S����*��o�>���X�p!P�>.�Lu�N@@!!!888����������ٕ�]^^^�����u�ֱs�NyNN�����ƒ����1cԶ�<�Y�i^g"X&E(*	A�W�&!!��
���ciiI�V�9r�ڲ
������]�v�����j�Z��Y�`����鵪��&m+�A�����R��A��Ϗ?��sssV�XA�-�����͍�*���K||<~�!���XZZ������;QQQ���0t�P�E��w}��1
4Ъ��Sz,_��-ZϢE��g8��ű{�n5j�Ν;���Ãf͚�o�>��}v���M�8y�J��O����C�$$$���ƽ{���*I�5jĒ%K�_�>[�n��LJ��09��ikZfa���Ғ6m�p��E~��w�h���ܹs�-Z����]M�4���Gu&/׮]���5999������޽{
��G?k��E˄� �e�PF"""���v��JO^rss���GGG�BAFF�<\�����ann��۷����S�N�9)fi���4lؐ�7o��D(..N��:u�p��}RSS�S���>�S�� �a„	��ӧ��!�wy5;m�y�K�Ѯ];��ܘ5k���G����sss�U@dɒ%:���P��I~zzz�|�R뇭%I���BӦM�����ۛ/^���*��7n�6m��<_��ٺuk.\�W_}EXX�\WI���쌅�cƌ��LJ��4yI���23|�p.^������RbiTYI�5v�X��U�V�ٳg���q��Mz�聝��R=�G?�4-��L������ӻwon޼��fZZ���Ԯ]�'O���~�Nrr2*�HA�;w��2=z�`�����|�rZ�lI||<�V��[�n���$��Z���φ
pwwgٲe�nݚ�W��r�J��>���߿ORR�JP,))I>F��}��G��
� ��P�T�ڵS9�Ν;<XmY�=��W���'���4i�D�1�B�ҁ�n��������V;���Q�]�۝�jIڕ�~i:g��aI���2ӻwo���{�;FZZ&&&���q��Q�W�N�~�J�.)�$�3gK�.%""���6n܈��#���T�R��v�G?�4-��L��)e�G�,^�[[[Ǝ˵k��W�\Q:n͚5t�֍�#GR�V-��]Æ
cРA���ܽ{GGGlllptt�޽{XXX���Xh��9W��2v�X96e�lll�0a�J2X�+/��QgҶ��}� � oiE�+��TS[�KQQ\.����F�={��c._�LϞ=qpp��˗E�WT@���H�r��W0��T�&��.��e��ŕYCCC
Dvv6��СCdgg�駟*�JҮ������ˡC�X�x1mڴ!++�
60p�@��ۧq�%��g��Ex���e��u��$NNN���r��)^�|IӦM;v,�n�bӦM�ݻ[[[�Ν���.G����X[[�h�"�T���Y�~=��ߗs�ըQ�m۶��O?q��q?~L�:u��O���/�'6�hs�����АM�6�v�Z�=JFF�1.��_U��_�~�Y��S�N1~�x�}�N��z��bZ� �F�(�uְaCnܸ�ŋ�ر����ŋ*ǚ�����ā�L�Q�������Ti^^���(
>��S���ҥ)�K�.)MM�p�����m�Ѯ����
�������5���`�\]e�.�������ѣ�ر//�B�G?�4-��L���ԨQwww���L�"����\\\��)��۷/}��U)�f͚8;;���\d{��4=W���VK��T�V
{{{�n��ݻw夲w��%&&��S����#�P�Ν��^��Ԯz'@�>}�q��V�b���4oޜ��9]F~={�d���,\�ggg�6mJJJ
����ڵkkk����i=:w�L�v툎�����3gҹsg�T�µk�駟����K�.Jy�J���V�\)�Gll���4����h�6}�)u�BbaaA����]�F�v�T�ɖE���ݻwqqqa�4mڔ?��P	VPy�H�"��D�L�
3a�<����������̌�c�Vr�Ax[u�ڕ�]�Vv3A
5f�~��n߾���C��:88p��q.]���J�*̝;W�]ʕ;l�0���8p�L�>�7n���RGϞ=Y�|���	&p��1�ܹ�����t %ejj��-[�dԨQ��.m�XS�]���É��b���j�E�&L����;*y�����^Y�s�.]8q�qqq*u�4-Be9�A�0���,Y�������INN&$$�%K��PTA�M�.G���ؘM�61x�`jժ���>͚5�Xʟw�z���`oo���zzz����#�ę?>
4@OOON���P;w�d��ٴjՊ�U�R�Z5>��6l����/��fRJ��#GR�^=���W�_|�۷o/2HIyyyѵkW�W��Ǐ���[�?ʣ]��
��=zP�NRRR055�gϞ�ҮaÆ�x�b�7o���!���XZZ���ҥK=�<��_�~T�Z�S�N��iZ�ʦ�(.K� ��ttt������^��B����^-���_Tr������?cƌ����]A�BE~�$''3h� ���ߩ��R����oooo�n�����Ҵ:��S�2y��Jn�PVƌ��Y����RO�<}�4?��cY4Fxt�ڕY�fUv3�Jfoo/�� � ��{��dff���B߾}�^�:IIIxzzжm�Jn� ���Ex]�z�;w,��o���@"##+�� � ��Z8p �*�X�^��ر##F���Ԯ][e�%Ax[�4-�����UQ�[Jf)� � �_�������СCܺu���l�ׯO�Ν�<y2��ի�&
B�i߾=3f���૯�*r�A�b5LAAA�J���+�T�#r��{�_xݔy�L�0�{�r��3����Wv3A(!�@AA��P�2)�و#ʺh�
���Ae7C#�*o>�XAA��Pn�0E3�M�Q&ޯ� � � � ��Y&���TvA(#
���� � ���IA���Iy�D�L��СCߨ��� (�yA�
׵kW1KAA����`�P*����߯�f��#F��G������2AAAJ��6\ZWW>�����9s&U�T��֕���j:���6oތ��3O�>-�:AA�Ms���7*W� Be�����ϯ����w>XV���<RRR���$22���@��¨Z�je7�1eʔ�n�������Ͽ�uK��ghhHݺu������ss�rice���SZDDD`cc�ȑ#+�E� ���93A
��=T��.
��Ovv6����?����߈����ݽ��Yi�~�]���ܻw��� F�ͥK�*�IB>.\`ݺu8991�|֮]KLLLe7KAA�#�e�000�~��>�]�v�s��Jn� T�����?gΜ���233Y�`ϟ?��&
����Y�hvvv���annΰa�pss�HAAAK,KJJbʔ)XXX`dd���cƌ!>>^��:::�t��yF��{g��!��������ٳ��S�N$''������~�{��ԩS}}}�֭˧�~����Ֆ���ȴiӰ����ȈZ�jѾ}{�.]JJJ��s�����s��ѫW/����]�6�&**���
�{Q��mcmm�v���Ȉ�͛��?ЬY3����q��n�l۶��2z�hy�_|�Çٶm[%�LA��v��U�m�wڂ?]�t��ޞ�VBK�V����է��:v�H�>}prr�����x���0`yyyE���ǠA����&::�L��DE_����͛Ǽy�Ċ�B���`٩S�hݺ5�7o�?���:���Ӿ}{BCC�.���X�;v`cc���=zDNN7o���ӓ�ݻ����u.\�y��J�����ҥ����ԩS<y�/_��cBCC�ի?����9�Ν�}�����Oܸq���lRSS���fɒ%�mۖ(�S�I���	#++���8@�n�׺<����һwolll=zt��'33�ŋӽ{w��틗�/^�P9f�ڵ<�Ν;3h� 6l�@vvv���o͚5��Ջ5k�h�
ppp��ɓ%j��A����.]J׮]�ի�/�ѣG*uj[��י1c]�v�O>aժU*#�?~̲e��O�����͍��L���<�/�z������3t�P�/Cw���ښ!C����ٳ�:P�^=����kkk���Czz���%� ���믿�*OЋ/�v��~�-'N�(ǖ�=���x��)aaaL�4�;w�K=-[��E��������EIrr2M�4�]�v�Ҟ�&R��‚eO�<��Ύ��t�ΝKbb"ϟ?'<<�ɓ'��������譂��
�R�-[���u�S�N��˗L�6�[�n����ɓ'����…xzzj�޼�<=z���y�ƬY������ ::�V�Zq��i233���"""�Ν;�P(X�r��9s��%==�/�����D������$,,��-[r��m�.]Z�~+���#����dddp��q,--���fŊE�[0Y�k�.{��	&L�����������Y�x��X...������ɓ'O������?;;�iӦ�c��ݻGNN�����0g�� ��uK~��|}}iذ�V6|��G��Q�%i���ӓ���EZZ���8::���V�r�N�JTTYYY����o�>�������8::Bjj*�����/,\�P��򨿸�U�F
F�ş��o���T���޽;���+�����ڪ���֖��L>��OA��_q��)7Ο?��Ç8p ����u!��u��Ϣ���m۶ddd(ݟ���Ç���"������a�ʭ-�T�5)H��Pa���~�����ꊗ�VVVT�R6o���ٳIMMe���E���ŋprr���^����͋/5j7n�q��Э[7v��
�G���N===�{�=F��ݻwqqq��/�T:GZ�t�Νt��ccc����ԩ��߬`����իWcee���������C:\�VP���	

�K�.T�Z��?��͛7p��Y��^ٱc�=�e˖q��I>��s|||T���)�:uJȆ���}}}�����?��ߟ��H�裏���"$$��uxyy���G�&MX�v�V+����(M֦��ӧO��?������ܻw__�R�ۨQ#���8s����*}�k�.�޽KÆ
ٱc���lڴI)�W��kr�ƌCժUپ}�R�R��[�n�9s�-Z��C�&#� B�y�y���2�|*�5o]]]4h���W���K�~��V�gΜQ;^=�=y�$U�T�P�F IDAT�O?-��T&��D�,��Ϝ9S�ɓ'9"55�/�����\���ǪU���K#0f̘�r���5
��[�ni�v�B����˗��߾}�B�vh���w��vÆ
8p ~~~����V�Z�P(�{����,�M����Je[ǎ�F���
�$(j�4���	�V��…9���t'�o���&M�`ll,b?~,�?r����4k�===�4i’%K��Xj[����������~�zLLL�ꗗ/_���_��J\\\������֭[�#���JR������O�z��}-�tuu�U�VЮ];�����ʣ~M�W͚5����ڵkr;==��/R�Z5���Q�F*�hܸ��1� � ��=z��ŋ�ի�;wf�ر>|Xm�M�꾻j"77@m>bmR�<|�777z��I�n�pww';;����w��{tt4�z�bڴi%j�6�9�"}KMMU�W\�MS��駟����Bg��������ҷo_jԨ�U֧yyyx{{3l�0:w�L��ݙ8q��7u�2==���O?�>��3���T�k��D� *�~�
)���Y�ǩ�!�2e
�o���ʊݻw�����_J�ئM��Wp
a^^iii��dz~�z������%22R%w�͛7�|�2QQQDFF�������ĉ	�s�5lؐO>��A���g�ahh(_������ʶjժ�0RP�޽{|���ԬYP�{)��՞�?���u����>l�>}�{ァ�y�C�v��%j����F�wiz��Y�r---�K���}+�ߺuk��ڶm�RVyԯ�;v,{��e۶m���r��Y^�|I�Ν�@�'O�/C�IۤcAAx=edd0y�d��@W�\���U�X)ED����qqq�[�]]��D(
�<y���z�_�zSRR�8q�R.栠 �ۤ	///����6�Rs����/��(��۷�S���>��gff&���������t���^-$JLL����w��Ç@HH*AM)�egg�uH
��u��S999���KFFF�y�={ƤI��y�Mʽ�����얩S��Ǭ�,���G^^��P��$QQQ>|X��*%Ua�2MG+vܖ-[�F�+ݤK��t���K�����K�Z������֖F��j�*\\\�"�{�����U�@Q�Y�&+V��W&��?ؾ};۷o��ҒÇӤI��V�*U�hu����{�I����ڮ�?(�Nq9��?�Ѷn{{{���������[)��&��n���6�����`��\���F*�`��S^�kz�LMM>|8������q��)�)���R��X�.�T+�e�ȑ��A�T�f͢k׮��AЊ����'���X��-Z���>T:6�WWW,--IJJ���]N1t�PΟ?_�wW���fzzz*)h4�^��y��
6dŊ4k֌��]�_��4i������Z�v�O�!�366VN�����\�YO�;wV9FJ�bff���ٳgaaa*�2)EI�HHH���MNQ"͞����M�6\�x���]�FGGs��Z�hA˖-���T
t�]�kkkrrr

��Ã�{�,۹s'7oޤA�,_��-ZϢE��~�:۷oW�֨Q#�,YB���ٺu+>>>����2MS��`�PZ6
S�����6i��#M��/!!�ٳg����������:�ݼ�����<=��ߟѣGs��M�7o΢E�غu+���\�v�в>��s~��w�������ёf͚p��
�̙��J�oBŪ_�>�~�QIH�	8��|UJ&ZҺ�͛''�?y�ғ������#�z��Q��J
��V���1����Hӡ.��rlyԯ�7n����ݻ��gϢ��K�.]���KuC��m�p
o���@+��P)�m%:AЖ6�<�{��Һuk9E����J�%I�)===ڶm���Ui�ԫ.免��Jp�,�;V�!ti�YXj���_?ƍG||<&&&L�4I��үH4IQ�'���yH�ʴ�I�>�F����ӧO�����j�JԽ�۴i#��<v��9ť3)H��Ra#ˬ�������ٳ0@�󲲲=z4���,[��ЩP�*�C\\���dY�?�\Z���ۛ�S�*�uʼ�<��>,,,�8q"'N^�/4h��GJ�oB��ҥ{������ݝZ�j��?@Æ
��+JϞ=پ};.��ٙ�M�������/�v����oo��=f�BCC�~�:7nd�ڵE��ŋ$&&�q�FiР���+Q{%+W�d���4oޜ��Xy��Җ[�����a����Y�l�[���ի*�זW��\���{�!C���BA�6m�U�����>��$%%�Œ���c�w�����8��#i�7��]0%����%IQi�YZZӧO'))��qV�!S^L�Q��D�vj���0zzz���Ҿ}{���K��s�K�"�$E	@�޽����9v�iii�������ѣG�^���w钼_
��9sX�t)DDD�q�F���/rƒ4��`�$���I~ť3)H��Ra������ʕ+�ӧ��t���F�ŀ�������ҥK�R�E�ٳ'111lݺU%X�?��5j$�'׆4G;�t�˸q�T��?������ƍ���D\\�Ju�K�oAGG�BQh0�]3q�D�9¥K���ϔ�Ʈ	�?ΥK�;v�Ҿ*U�0w��Rխ�����+�&M"<<��/�|�64���OOO��ڴWbjj����Ҷ�-[2jԨR�[��c�r��Q�^�*���WA:��jy֯�?~�<R(�Lxx;q�qqq*_���r�A��i��CR0�CQ�$
S�Y6&&&,Z��	&�j�*j׮MϞ=K\���������_��z�%�/L��&ڴS���u
�).�Ja��KQ"�7h� |}}9t��F��СCdgg��+�J�~)�޾}�bcc����	��ŋlذ___���+��<�#[�t&"�P�*,X6c�֯_ϙ3g�߿?���nݚ��p��������חG�����~�zZ�n�Ν;�}�O�>�
6�m�6��}fϞM�5���`֬Y*7�E����Ν;�޽�e˖���aׯ_g���|��ԭ[�+W����ɮ]���?~,˾��<<<1b���������Ȉ+W���4��߿T�VQ�W�Nzz:AAA:���<�?�TE}0֩S�m۶�n�:���������
>����^�:>>>lٲ���0>|(��8m�4�'T%��u��|����q��"GHbffF�Ν7n�<��$�xyy������)���g���J�[CCC6m��ڵk9z�(|���,\��_��ԯ�8�^/��@��ݕ���׏5k�p��)Ə���ԩST�^�>}�h�F��!r�	o;��Lx4lؐ7np��Ey�z��/�kffFRR(v0m4oޜq�Ʊ}�v���i߾�Ҋ���۸qc�^�Jtt�Ҁ���X�c��r��Ҥ5Ѧ�
6��͛*�T���"\�tI�a��%�aÆ���Gpp0�F�"88@%pUV��������ѣ�ر//�B�e���ܾ}���:u�$o��+I{�ԩ���IMMU�U!R�e�‚e
4���;;;�=��E�a�y�) �.]�Td�~)Z޴iS6l��ɓY�j��dQҹsg\\\Ԗ�I�y���J�����2e
7nd�ƍJ�.Z��={����ȹs簰�^�W&!!��}���ѠA���)��m�U����s��qF�!o+������ܼ�ea7u�MLL�7o���+��]]]UVZ�i�D��«a�k֬)�r���jժ����7�4�A��5�^�r�F���?$ժU��ޞ�[�r��]4h���ԩSUV�-Ҩ���m���Z�D}���ƍ�Z�JNQ����r?ڥ��Qw�ܑ�G�2i�$�9�ݻwٴi��0_�z����իWY�b˗/�M�6\�r�+V��Y�vm�<y���>|8���xxx��+�j�6�9*�&)J$t��A^��ڵk�k�N�bY�2dw����Ņ�ҴiS���@y$XA=z�˗/�e˖�������~)H��Ra�2�����'G���T�Z��;���2��ƍZ����HӦMY�j���dffҤIƌ���FFF�edd���666L�0Ai���.edd�?�@BBFFFt�ؑ9s��駟ҴiSƏ����m711!<<OOO����u�9994nܘ!C��`��{�R�[EٶmӧO�ԩS�x���R�!o���L�?��͛�S�&L���������aff�2uTx7�f��JL��cƌ�_~����΄�&E��6lfff8p�Ȳ������o�:u*���>\դM��G���͟۹M�6r�EңG���X�f��U]zMi�NmRsTMR��7|�p���X�z5���_R)E&L����;*�Luy��w��1�ܹ�����>�m�)H��Rቦ�5k�֭[�s���٤��p��a���O����SP�n�

��ӧ�x�B^vW]���r����u��w�V	�IƏυ���"55�#G��駟�nl
����f͚���s��e233���!11��N%PV�~��4�^��7n̡C�x��999*|� �N����ׯ���4k֌A��=��ؘ%K�Brr2��Ʉ���dɒ"��
� �Pq����166fӦM<�Z�j���O�f��6�RT���cff���&&&�(���j�ϟO�
����8X�v�9r$/_���/Q����lذ�	&P�^=�޽�R^g�ܹs����f͚bkkˢE�4j�:ڶsӦM���Q�vm

�ӧ��
eE���k׮���S�^=y�Ea�nz��A�:uHII���T%�h��6l�/�y��bhh���%,]����jԨ��m�9r$���COO�z����_�}�v�i���ׯU�V�ԩS*�D
�,U��2AAs���#55kkk.\���^�Ƕoߞ3f��w���W_��OA�׋��)�/Vږ��@ݺu��k�"�o߾jS��r���	'''��ڤܨR�
���?��?�Y�q�����(��S��ڦ*�&Eh��D�����oW�Ҧ�|eڞ_�fM�������]p�HA"T,�•4'ڻF�n����T;A�t��}�6A^Cݻw'33���K���IJJ�����m�Vr�!R��§a
� � FGGG폞��k���Ɔ������nj�%$$0�|ڷoO͚5��קv��t��	777n߾].�n޼�-Z��'�� �c�xxxЫW/:v�Ȉ#8�<�k�Vʧ%�:��D�bd� � ����<RRR���$22���@���ި�YYY|���x{{�����/%%���(������dΜ9����ʘ��Ͷ ���������СCܺu���l�ׯO�Ν�<y2��ի�&
�kE� ʛ�	� ���)��LNNO�<����̙3���(���Y�bE%�P;YYY��ߟ'N```�رc����]�vԮ]���4������c׮]|��w\�x���i��0E-�#B����}g�)�t�D��̻�F�"X&�/00�BnHA(������P�~}�N�:u�ٳ';w�|c�es���ĉXZZ����Ԕ޽{ӻwofΜ��9r�,P�z� � �P~D�L����ٿe7C�B%%%�r�J~��<x���)�z�b�…�l�R�xM�Z�t��y<==9~�8���4lؐ#F���F��յns�N���V��/++��7����˗/���J�Z��ԩNNN���C���D���{~��7���������d��̞=�Z�j���M�%$$�i�&�W�Α#G���^��k߾=�cǎ���̜9�&M���k�P(ضm��׿HLL�V�Z��ՋE������w�Z�/3�+W��j�*~��7������{�ѧO.\HӦMUڞ��s�α`���éR�
ݺu��͍�;��W�k � �Pn�����_L�߅w������޾��+�����f�P���ϣ�ߊ�{w��I����P��R����j�/����X��۷+����۶m[ųg�Ԗ_�3g�(Ň~��=--MѮ]�Bۦ���8p��9QQQ�5jzN�ƍ���/U�999)���|]M�:U(\]]���ին���H�uu�
���?��066V{^�j�G�Qi��?""BQ�J��

gϞ-�5�_���wA(+�GA{�s|@�s�6�l�ȑ�U��|c搋�� �=*�	o�'O�`ggGzz:s��eƌ��o#&&��[���ヽ�=			�����)��Z�j���lٲE�~��-�N��˗/�6m,�A�DDD���ȅ���dٲeŶ7//�'O�p��q�͛��Y������ ::�V�Z��O?Ѯ];tuu���a�ܹ����r�J>��3���s璞�Η_~���3�5"77���H���+���Y�t)6l(q�?~��C�jrid�F�⧟~��~c�ʕ*�]]]���a͚5|��Gܸq�o�����ƎKbb"�^���Թ�>�G����2��+WҴiSY�p!����9���x��}��0`_�5m۶�ܹsL�4�7n�b�
<X�k �+�}R�poR|@�����`Ĉe]��1b�<U�u(�	�N�?��O?��Çquu���+++�T����
�7of��٤���~��"ˉ��`���899)}	��ŋ�5��7Ҹqc�֭�w�`׮]j����Q������cĈܽ{���K�s���عs']�t���###:u��Ν;�t��9���;�W����
����ѣ�x
.U�%&&���Z�6m�p��5���7oαc��ԩFFF�lْ������ٓ��T�����/��k����3z��IPP�Z���АV�ZDϞ=y��)�֭S{~���	

�K�.T�Z��?��͛7p��Y�c�����?� �{��@�O��¼N�,�6�#�ż��߷.]�(Err��r._��:t(����E�ƍ��_�~���\��Ҕ�'Nh��~ttt}��Q���i\nnn�|n~M�6U�Ν;+|}}w��)�����P�|�R�*
ENN�P���)m��a�޽j��_��S�Nj�S��:(šC����]�vjˉ��U9�ٳg
@�����]�kP�>�y.T�w��E�,�N�5�~���?cƌ)�b�7������_Ax}���(M�TG�Δ)S�}�6VVV�޽===��ׯ_�!�
E���yyy���������֖��H�7o�r�͛7�|�2QQQDFF��\WWW&N�Hxx8���4lؐO>��A���g�ahh(_�~�Z�*Ϟ=#==��5kj�)))�.������ޡC�Ur���گ.���5.���Je[�jՀW�2?m�� �n�� �fޤ�@��,9c�A���V��l�B@@5j� 88�ڵk����3��`�6tuu�U�������ҨQ#V�Z�����J�{����Օ�7ojT���5k�dŊDGG���}�v�oߎ��%��W�,I�5k֌��h����ܹ��/Y�2�n�I��u��nbb��%���Php�F�ddd��_�J�����J�� �M��[�L���߼�s��U>���m����?����D����_�~4oޜ>���}���p��u>�իW�r�
���k�����;M� ""�X�0ժU#--����F;$$$0{�lttt�-4W�j�HOO�ٳgZ�Q'''V�ZEXX��-���͛3b�7nLݺuiѢ͚5S[����Ν;w8z�(�O�����\�v�7n0g�BBB�פm���Ӈ��h�
�I9�>�����WiDZ�Z�4���5j���Bjj*�����!�+-m�� ���� B�޴�@�'��l}��ו�/Ϻ?~̙3g���a�֭j�ٲe>>>�9s�Ǐ������\�p�u��������Y�v�<ULʛ�.�l�8YYY�=���L��^�) IDAT.]��=��������7�/^���-����MBB˖-��ё��+�n+8
Pbaa�ĉٺu+W�^��_�YB�m���������q_�����ヮ�.���j���$�K2�U"]���(��###��++�\AA����>|����1������T��W���nkkky$����˜;w.}�����GGG|}}�iA]��䵨��y�7o�b^�N�8�V�mnnNdd���k^^���ԯ_�T�Wf����,Z�;;;���077gذa������n���߿?�*������?  ��}���\�tI~��gϞj�qqq���иq��_Z�2@Hʟ5n�8�㽼���?ָqcttt�|���9���*�J�oVVV̜9���,���_�֨�(Hvv6ӧO/tD������˗xzz0|�p�}:::@������Z�R����(|ԛ6����6*����ȻDݽfY�{��nMl_y���r�}��xm�ennn������Avv6�=��M���ɬY�prr�ԩS<y���l.]�Ě5k2dH�=
-m�F�~�KE}�KlllHKK#66Vi��K�HOO���¶m�x��!�G���}��<|��m۶Ub˄wŌ3�Y�&gΜ���DEE���EXXS�Neܸq������.����iݺ5;w/��>}:FFFl۶
WWW<x@ff&ǎ���977��7o�r�J����5k�����x�{��/_����ˌ?^�J#U������#G����Ann.qqq����J�o�*�Իwo�޽���-'N��~����������#>���]�t!99�=z�
�IBCC5jW�\��{|��g�>}�����*#Ҥ�uAAA��撝�]h�ӧO�F����1l�0������&>>�aÆq��q�V��̙3-CS�^A��N�#u�Gy��›��r�����v�ƍ�o�^��ۢT�h��r��Y�ի�����ҥ5k���s�N,X��-[��?�Q�mQ�gK�,)U�G��h���@���K��ʣG����9}�4ϟ?��Ғ������
(����d�֭9r����ԭ[�0y�dyկ�O~
�Q�t̞={����ҥKѻwo�̙#_���<6m���ÇINN��KKK��СC����ѣr������[�.=z�`ƌT�ZU�>�ԩAAA�9sFi��4ũcǎj�ԔE�eff�����ǩR�
���端����H>&==�M�6q��1?~Lݺu�իS�LQIZ���c֯_ω'x��9�z���}~����ٳ�:P�^=y��ᅬ��5{��aܸqrmA(
4���;;;�=�60�a�>��#��e˖�>o�J�/�8ٴiS6l��ɓY�j�V�R:�s�θ���-��@��ޘ����ٙ)S��q�F6nܨt�E�سg����;wN�}��7���@߾}U�hР��׿�~׶�

9x� ,`�ڵr�zu���={6���J�

`�ԩ*O���}���U��oߞ�Ǐ+�U*�:��o�~~~�1���`��������G�F�
m������6*M���~�]��(�Rx�T�Ȳ�F�H�1kkktuu_�%�O�>ͩS�055e���4SSS���077g�̙L�6��/_�aÆroOy������&O�Lhh(iii���p�������l�M�Ǝ;�w�999$''���Ü9s4�"S��S�ʣRSSٷo���u�ֱe��ܹCNN�����ƲbŊb��ݸq#,��<{����\�߿Ϟ={���к�:t@WWW%���ӧ��ѡcǎ*�U����Jff&O�<��ߟ����gϞ1i�$v��̓�������ɓ��̔�MOO��ё��RSS����_~a�…*����dff��^dkkKff&���5Bi8���iذ!ԬY�>}�p��a�O��t��7����ё'N0`�jժ���!͛7g��儅�i�j����7f���:t�͛7+���/ٱc}�FFF���лwo~��g�-[ƢE��W9�$&&&�����7�вeK��������ʊ����.����7���!?��W�\���kkkLLL��ӣV�Zt��	777Y�fM��2x5���X[[���O�&Mprr"66V�
�m��߿?ժUC__����oE�?h� ���;v,fff���cff���p�p��Jr
�MT3^��A(����4��Ȳ�":t�z�R��$<`Æ
�9s�gϞѸqcƏ���E���Q'R��q��)��oԨQ(
�7o��]��*��*��ԍ��t���???���O���Y�b-Z� 66777>|�t���/���|�ᇸ��biiIRR���DEE�СC���iԨK�,�~��lݺ����MPPk׮��ښ��BCC���`�޽�3�кw��
�
4
4bcc�:u*�N�Һ�LLLh޼9			<~��:u����#���R�
[Y��ӧO	��̌��׳g������];w���͛4hЀ�˗ӢE���Y�hׯ_g���̘1�]�vq��]6lȊ+h֬���,^�X��3g�ТE�}Ҷ3gΨ���ЬY�B�(��ӧ%��[�nt��M�c餩���3~�x��ƍ�6�Y͚5qwwW�:Ym�� +++�#�J�u�֜;wN�c7n̡C���+��[�lɮ]�4nOqׯ��%���6)�}E�YP��#xyy���?����ȑ#�6m���xzzr��I�޽;����j��gΜ��Ã#G�`hhH׮]�5ku��-U���O��!5-�m���i_��U!��^�`Ya��$����6i4I\\�֭CW��rO�<a„	J���_���ŋy��%�
R:���E풙����?���򍴔c�K�.��Y�Z5&M���M�r��My�4Z%**
�?hS�N%55x�پ}����S;j�(��?��S�V���F�DEEq���������?���0��P�֭[Ю];��ܔr�9rwww���hҤ	K�,a�С����ꉽ���<�h̘1������&�Z�*Ϟ=��Ϗ�7oңG��찳�+��'O�P(HHH�СC�&x��.�N�:�ٳg4hgϞE�P������o��I�&��){��Q�e�i�WWWfΜɱc��`����ՕV�Z���7�|��ٳ�ꕒ��)!%;/i�VAA�|�֭�2���!66���X222�)�y?�z�j��+�Z��A��gYYY<x]]]���[��===��^VV��������닉�I��U�}RI�!���K�25���lܸQ��4�#--MN�Pm�J�Uq��]��_~�����r�}��&z-��̟?^�=�h"##	࣏>�G�u��;x��-[�$((��'O������i�ɩS�����3�� �A�Z����U|||g�֭���ˣU
jԨ���IJ؛�-����~��޴i��'Q��~^IJJ�m۶J�۵k�r�;w<x�<$���Z�H+�������o��G���s���Ȉ��~��F����YYYŖ���#y�Ɗ+ػw�����#B���Rp:�2uʪ�����׬YP�'��?.5��߻wO�&���Z�c�{��	�ڧg�6�AA�=�g���s��I9��޽{��*�~$..�ݻws��Y�M����zzz�۷�3g�0e����ՂN�>͏?�Hxx8>>>���s��=|}}Kծ��4��ԴLMﻴm�&׼����8s�gϞ姟~�j�6}�VŎ;����D�r�}��&��`Y�Zu��j2�?�h�f͚���'�&�W�B����899aaaAժUY�p!�ϟ�����Ҩccc���K@y-===@�%��+8Z��@�p��1�s��BFFF�S��#�JS�4�� 1������mՀ��$���J:BKb``Pd�}���СC,^��6mڐ��ņ
8p ���+��իW���@Æ
;v,�~�m��}nӦ�����!22R~o�SV�WҼ~��Km*�6}}���5Q7VڦIrsAA^_����FO����ӧO�����J���qqq�iӦ�+վx�WWW5j����<�]AU�|[[[hݺ�<�*��<�JrYV�^ڔ��5W��ɓ�;w��-[r��!������	hw_�M_�U!}w��oT���›荚��4�:ō&�F�|��Wܨ�z����{����?�BE]xxYI�Ԧ�X��b�,�E�T
�~�R�%���Ȕ��EB4��&�%�ME�R�-3�M~��O3�300������9|���s�}�ljs��QTT�n媮����ׯ��7%ZEQW���L�~���t�֍�~��Ç�DD>|X����3gΜa����i0M���|||8z�(;v�`����������TEc:88�ʗ��\ ����
�
b���dddPZZ��kL��T������ӧ9t�ΖP�k�u��ɓ'���tB�

�۹sg.^��իW�ܹ��sʛ���B!��w̜9�%K����Knn.�1S�L!  @�QS�G��P�[!��)��h����X95X;=Lc̓�3�4��˔k��r��ef͚űc��3e�)c%�*DK�d�e��Щ���$�Fj�u��a�~�����#F;wj�^m��2�1�O�b�g�y���h


(//�ȑ#8�1������ܹs�+W�����h��v�c�����a̘1h46l�@YY�{����0��f���s��-�?��X�OݔF�4���AӍ���P��Z~~>�����端�v���oj�����r���{�y���*o6��kmJ����B�{Oeee�BB4�����Д�N�-g����*m�
�'�gi1׼v~�2V��B�t�*����$]�v���������7�?�>�,[�l!%%�Q�F��WQQ��U������SäM�V17S��$��4���|��ל>}����Z놄��{�n���	

�y�]�v̚5K}���@qq1~~~8;;��Q"88���(bbb����yN;��P�^^^lٲ���H�'=?~�`�κ(���-�5��s�NΞ=��Pt��]�,((�;vp��	5_�ȑ#�ņ
FVVzQ�J$��'
!��e2f@s������l;=x� ��ղ���ݰ��X��a�Xɮ
��ݕ	�k��h唘�K�r��En޼�{gF�Q��b�С4�_����233)--���|���̜9���\�
�sʠ)�*�fJ�D���@[[[��������u�ָ�����hG*��ّ��H@@���X[[coo������:�:g�\]]����֭[f�???"##�۷/666������FHHK�,���s���퍭�-666<��DGG�D�IgMѻwo�
^ǎ
&U4�u�ؑ��$Ə������8991q�D����z�z}�������y���&�9����L����������*�B�{�����|�w�Q�$**
�z_Ԙ�2ei����Ô��]��kV�e
�&�<y2۷o'??��^�������W^᧟~ROj1bo���NX�)�*�fJ�D�����Q/ڪ���.]�����3{�lfϞ]�5�����+7�hW�B��r�S+S��ر���:툪�m���ʊ��L��5����)�ԩS'�͛Ǽy�jm��f�?�zrQM��С$$$p��y�����s��!����EB!Ľ��]�|�#���z��3a„F�)sHc�ԝ����-��ˌ=bW�M�駟�k�..]�D�4hӦM�I�?g�>��#.^��F�t�ܙ��$���ؿ?7o�� $$���z�^����Ț5kHOO�o��ԩSXYY���رcu�:*�h�O>��ݻws��:w��SO=�K/���bnJ�S\\{���ڵk��Ջ�� "##u��F�ɲe������_Թ�D��>|8eee̟?ooo���8s�z��d����W_}EJJ���������ޛ!*00��7Z�BqO3e����G�֭IOOW��u�֍'�x���`���e>�o�Ann.�����o#44Tg���2ei,Cs͆2�57�ܹs)//';;�;w�лwo���8u����[�Ψ�2S�J�U�b�
v������_�JDD۶mӹ��+EsdU���������?�CQQ�G����E�h�U�V����ƍu�_|}}	#44��k*G"���|lIVVV�����^W\111lذ��s$''�c(���f̘����7n˗/7x:����T��߳���[�GB4��ӧ���\���7�Q��'XB�
�W���n^0 �Ym�
gj�D�o޼yt�ޝ�[�r��)nݺE׮]:t(���899Y���.3x�`���Y�t)����,�	���iXB!��$�J���b�=fԨQlذ��^x���P�ms���̘1�I�&�i�&�/_N�v횬��A�V��O��I�gF469�]�tI&�w?�W��F��1��~��!�h�|}}e1A�H��X!��W��D��1��~��!�h�ƍǸq�,�
!�� �U&�ɼR4�,�!�B!�B!�Y&��'r!Ľ�ҥK�5��o���s����닓�[�l�t��
'N��O�>w]����������![�B!�D˄@N�Bܻ


x�u?��C�����_'++�"ۈjk����űn�:*++�0a���8��)�B��4�b����Ң�X�~���B��\M�e��{]VV�]��7X�h���8;;����…Y�~=���M�M!��G!j���m�L���D~^�h9*++-݅��F��+���'>>^}�b�
V�X!���BIII\�t�^xA-�8q"��9III���[�wBܻ�B�f_,��-Ds���"?�B4c����w���_X�r%999\�v��={��/2j�(�z�����dzs�N�\�B�.]x��'y�嗱��S�)�iii��ƒ��O۶my�駙9s�uUQQA||<���ѦM���3f���:��://O�:>>�9s����ΪU�t�h3T^�}��vii)iii2'''���ߏF�!--�I�&ѱcG�^!D��G!Z�/��ݻ��˗�����z��Ǚ>}���!�B��h��?@�=��/((( $$wwwRSS����s��e�������H�ܹ��ѣ�v�S�N��ɓj��/���ʁHLL�}��:���իܼy�/�����
"""���c͚5j�۷os���9��׍Zx������Tg�ʜ�mȶm�(++���S�9OOO8@ff&cǎ5�OB�����B�9��2�Ϟ=+��P�'��o��t7�BԠz2��N�z�j._�L������`Ϟ=��� 11Q��f�N�<���+����߿���\\\(,,$99Y��=z� ##����L���]���322�����gϞ=̟?�u����`yyyzc�z�"''�7�|��]S�999���O�J�RG�4d�#�ukn����LN��|N�8A�>}t�j���m�z����}h�{7�שU�Vt�ԉ��<P�k�����������Cr��Y:��޽{�;w.ݻw ""B��R(�\<���0���k��s�N�<]���S�Hbb"%%%���۷�ڵk���p��I���������accc�]߆�8q�Z��gϞ:u�MK�?BQ��>`��2!�y������bɶ�>h�����~c׮]L�:��gϚ|
s������c�ܹ̙3�+Vp�С]S�;4
��M�6��{��h���x뭷�:��…u.ȟ?�Z ��#��\G��������=P����9s&m۶%77�>��	&����͛7�8e*c�ې��b�9ɔ2��B!��Y,�.���uO�][m�jLJ{yyy8p�/���Gy��ׯ�駟�|����7X�h���8;;��₟�.�ƍ
��M��ʪA߯��U]�6mjm��ۛ�[�ɀ�y�&+W�dԨQ|��F�_ST�����n��{��� IDAT!��|o�V�oᔲ���B!Ľ��.�նa׮]̚5ooo<==�2e
k׮������U����M�Զ��ә={6�gϖp�j,�:��C�V�puu����E��'%%q��%^x��l�ĉ\�t����&�h~��򈏏�����b�

��@ܘ�v�
T%������^����ٹ^�������CBBk֬!88���bcc�u=e���j��{3��
�ܹ3�zx�6�L�#�w#Kn��m�	!���Ų��8���1}�t�ΝKvv6���ܺu���|�-[Ƙ1cؽ{w�w�."[�����DFF��O2t�P������4��VVVƊ+���a�С�=��+W�D!����),,$<<�����z���h�����
V�Z���C�e���L�<��7��;�6m^^^xxx��ϳt�R���L���SS�Eii)�>�=��z���X�]�V�1���/�������(++#22��Ç���Mll,�����}���1d����~4
iii
Z��K'�6lK�.��ŋܼyS��$���� **���|������'::�'�x��nj�F�aÆ
���ѻwo����Qi�l�vpp`�ƍܸq��'OS�6Զ�u�̙3z�U�곽S!��ݚ^D�@B��-��%մ�)""�}������+��°a��ԩ����Y����|���/i�^[^��]���k������Z��w��ׯʹs�Բ�Ǐ�`����n�bڴi=zT-+**"11������n�1VXX���s��M���***���qqq�Y�F���m�9‘#G�~�z�ob>��ct�.^�HZZ%%%F�
g��\�v��S�r��I�k���r�i߾���5Fu9}�4��a�{�?>�����RSS)//g޼yl۶���2<==����ӓ����رc��q��&O����������y^R�f�Ν�={V=�Rѽ{w�2cELL�ނ֠A�ԯ(..���ggg6o�\�5������`ٲe,[���缾�m��aÆ���EAA�N?�װ>��B����"2B�"#�ٻw/���8::�����ѣqtt���^{�5�M�Ɲ;wX�r���k���aRRR8w�...$&&��~���u�k׮��ѣ<��C�����ߒ����9p�t[{�)[�z��AFF999�$R9M ##�+V��~������X�n]�m���@բNNN����O> ;;ۨ�{c�͚5�<yWWWu�pqq������d�Ǩ&���;v���z��C����~��7������V�����@�~��)u��M�ű�^�qS�ܹ3IIIx{{ӱcGڴiC�~�x��w5j�Z�cǎ$%%1~�x��������ɉ�'����&�7���������lllpss#$$�%K����̙���+����i�5k���t��	<==Y�hQ���P�#G��}����fggcgg�3�<c�x!ĽJ�@BC,YVQQA||<���ѦM���3f���:u���HHH`����t�҅g�}���P5�n�-NP5!U>	�4i����	&PYYI߾}u�w�����9~�87oޤK�.xyy��R���2�����ʢ]�v>�W^yE/���m���/�\�����]�FϞ=y��u�l�l�26mڄ��3g�4jkפI���Ւմ�zy^^�����?TE',\���ӧ��߾};P��H��ӫW//^���/[�l��7ży��޽;PuDobb"%%%���۷�ڵk���p��I������߿�k�ٳ���J�;�֭[�������
���)���`�^{�5v��Ixx���5F�j�9���g�ԩf���������0IKK�ʕ+��J�
e�6�d>K��ǖ-[t��7釋�QQQu��ԩ���S�,kRӢ��r|||j����7���F�akk����j�o�}j�C��������quu�N=t�aaa&�7B���
JKK���g�Ν\�r�.]���O���/cgg��S����K~~>m۶�駟f�̙jԕ1s���i�����̙3wwwV�Z�SG����e$����ˌ���mkG���bH�t&�`ޭbP5�W>
.++c�ƍ���&%%E����6���	����j���B"##�s��G�6؇>����|�A^~�e@�v���+�G�)��M��?S�$�>I������_+ڧ�͜9�%K����Knn.�1S�L!  �v���z�˗/3k�,�;����	pu1�u�j�Udڔ��…z�S�����GGG�K/���X����_w��I�_���ߴ)eJ!D��W_}EJJ��x������3AAA��R��4F�����P���RZZZc`CC���	!jb��2��`��۷o�e�bbbX�n���U{�ڂpss�̙3DEE���|}}u>���A��P>�5����ѣGceeő#G3i˙�ĉ|���8�cǎ�h�"Ο?�g�}�+��bR��W�������ߟ��~�.]�������D��1��ƒ��J�^�X�b����[��(��$���"J����TgjdUu��Sk���Ãݻw��_r��aV�\�ڵky��Wk}��{�=�;F�n��_����>� �Ǐ7���Nmj[��k�������D��D髡����GS4�	��}�fKfkk��ŋ�1c�&M`ӦM,_���<�-��s��o�������ѣ,Z�HM_Q="�G�,^���]����@bb"�v�Rˌ���4OS��Ջ���:���kj[�@B��X|����`
ݶfmm͝;w���fέbPY6d�~�a"""g׮]�b��m�ݻ��s���"""jLP�,������G��x��]
׭[7~��'>̣�>��>|X����3gΜa���:�IM���^݂t��Qv���ի�����
Ann.�����oڟL���Ӻu�Z�u���t��i:�c�=��+�5���jҹsg.^��իW��o+��V/B�<�&<<��K��ꫯ�dB�;��4F�����P��P�ω��HQ�&Y,3��o�v��n[srr�ܹs���������:��͹U��B�6�}���m*[ˌ=">55��Q��o��?�I}N�v5�3�<�O?�Dtt4o��}���رcDGG��1b���DDD0o�<z�����_֮]�g�}�F�aժU@U�Pee%gϞU�4Ԙ1c8�<���gԨQ��ݛ��Џ��������Os��I���%%%8::ݗ��c�{yy���LTTo�������ѣ��7��p渧���Ӈ�/r���E1e+���0�D�ݽ�t7��6�i,��
#}ECR|(��)S�:'�&s !DM,~���7[�n%22�p��MV�\ɨQ���/�z
ݶ�|j�o߾�|����1����ܹ�n�


�7� ==����S}{�r_���j��m���J�Ϫ��R]��~-��U�����ٓ�����<<<�<y���-$$��={���OPP�=�#G���>�]�v̚5K��D(���՚s�������0|�p��~���`�m///"##���$((�~�A���Ǐ�c�c�ӽ{wΟ?ϔ)S���`ʔ)\�p��ݻ��]66s�SM����I�ڔ��^B!��5�zC�W;��MMQe��@C�7�e$��I�,�����ӦlKHH`͚5SRRBll�ZG�F�y�f��;p�@�}x��g����>���`ժUTVV��sϩ�W�۪fΜ�7�-//7i,���{������-|
c��ڵ+`|2�ٳg�	���٣sX���l��&[��`��WakkK||<>>>�w�}�n�www5�H�
��������쌵�5���j���'cs����kkk�o���Ϗ��H��틍�
666���’%Kjm{�ܹx{{ckk���
>� �����ֺu�ꃱ�1�;v�HRR�Ǐ���	kkk����8q"���:[��9�&#G��}��s&fggcgg�3�<��B!D��5�i��
��6J�
EC�W3�3��Hu��u��н�:'�&s !DM,�����`
ݶ6t�P
�w�}GHH���C��]�v���|��'���2l�0�{�͵�쭷���7ߤO�>�����;����O���a�HKKc�ҥDEEq�}��|�r����֭��׿�Ȗ-[(,,��?fŊ�l�2GGG"##uʊ���ҥ�N���=�g�f��ٵ^���ooo�rCo�jz#f�\�Wfj�;v$**�`}eQ�P��{C}0t?�:ub޼y��p51e�L}ck�{2TޡCHHH���%�ϟ�СC����`%�B���عAc��0G���(..f�ƍ�;���"bbb�}߆ږ9��&_,&**����?~��BBBؽ{��mM��mk����������͛��-g���
?��,��ˈ#x뭷tBm���زe���z� P����Q�5�߿?!!!:e}���9N��6'O���������ש��K/l��ښ0u�T�����Ç0`Æ
#++��������8Ç���������퍝�gΜ��w���!DC��W_����.�������Q�����LV�B�<��
���ٹs'gϞ�KUQ�����j�����EFF˖-cٲe�]�޷��e$�������hݺ5����qݺu�'�P�*���>��Sv��ťK��С�
bڴi<�j�9s���Gq��E�-N����Y����t���N�:����;V�C�ܹs)//';;�;w�лwo���8u����[�ΤŲPYYɮ]���R���m���6;w�LRRqqq�߿��7o��SO=Uc~�a���������̪U�9r$˖-#;;�_|Q��l�2ΨQ�ذa��7	:�EB4���-�/fƌL�4	�M�6�|�r���{�ƍٸq���!��;7P�W|��'�޽�+W�йsg�z�)^z�z��0vNW�<͐Y�fѪU+�o�΍7�h4,Z�HM�c�}j[�@B��XU��HG-������?�ǪU�HHH`�ƍ:[�|}}	#44Ԥ�)�r)))[���)))�)b��GEEiiilݺ�S�Nq��-�v��СC	

����\���{��=�h4L�8��=�,����9��	�\�Ͽh
�M�b�9�°�y}��<�G����l�j�V�Z o�E���7a����[�B4��ӧ��[�B�fJ�@BCd�L�dk�B�<�ׯ`ܸq��~�z|}}-�
!���h�Mq�fK%s !�!�X&t<���p�.]
�������R!D�"��DK�}(�Bԗ́���b��#[��B!�0?��{�H�M˄����@9-N�fL�n(�B!�
!�eB �|�h	�Xh;q�}��1�\zz:���xxx�!B!�B�,�	A��I!D��믓��ep������cݺuTVV2a����8p�z*�B!�F��X&	W�l���ϫ-Gee��� ,,++�`��7X�h���8;;����…Y�~=���M�M!D#�'��v�e}a�����(��޽���`4__�f��+�Е��*y@��-;�tRR�.]�^P�&N���NRR���������B�9��}��{���j�P�7Nr	ьݾ}[˚�˗/�|�r���ˍ7pss��_d�����]YY			l߾�_��.]�������
�Ǣ���yyy������Ɛ!CprrR����h4��Ҙ4i;vl��B� 2�B�����; �B�{���	

e˖-���p��m�?�.�i�u�ӦMc���\�p�۷oSTTDbb"3gΤ���ֶ�m�FYY���z�yzzRVVFff���M!�B4_f�,�=���ͱ~��=��m۶��у��@�{�^�0�%���횪?�lll�ҥ������b�{,���1ƫ��IN-l�RRR8w�...������׏#G��p�B.]��Sw�ڵ=z��z����ƙ3g����lڴ	___��������Я_?�~(e999�;��nW���G!�n^h�b�����u��v��!���;?��o��vvv���m�6
Sǡ)ܺu�.�����_M\\?����ܝ�e*9��qմ�^��1�v��@DD���3h� .\����u�n߾���(ua�W�^,^�___�lق��o�m�8q�=z�=׳gO�:BQ��!�y���
^,�=�B4��NuST���l�2�l��g�}�l˪�W]��T�����s��)����������z�\�j��j�{�S�
gΜ�G�)4h�^ݳg����c�Z�����U\\`0'�R��B���G!Z>�Y&�	4M��wGGG�̙��c�,ܛ��m۶��ۗ>�www~��W6o�l�n�5�Zx��%���,س�#//O�_]卩��R籡�M��Tw�ڵZ�W�٪��[�L�T	!�Bh��0���5թnu)//O��iW����bbbؾ};666<���L�>�.]��\������xv��ɕ+W�ҥO>�$/��2vvvj���
�����̤���6m����Ƙ1ct�Pi�om�`l�����3g����9w�ddd�L�Ϟ=������|��u�w�6m		a���ٳGͫU������ΪU�Lz]~��V�\INN׮]�gϞ��⋌5J�s���WC?�����^N-�wt�֍�~��Ç�裏��֫���̙3gؼy�mh�Ν;s��E�^�J�Νu��z��ZG!�B�,�L��T��TVVr���.]
��>��v�}�]6o��͛7)))a˖-L�2����εkט:u*��9������\�x���TBCC)++S�����駟r��Yn߾MYYG����&%%Ť�5�]Ell,������1a�Ν;�7�|�SgϞ=>��(y�~���:�*}P�Ly]���	櫯���/���YgT[C�K{�J�)}7���S��<����P^^Α#G���֫;b��*����ǹs�W�\��?D��0m�4���A��uP�P�~jS�,u��B!����b�f�}�[bb"���'>>��"���n���|����3p�@�T7��֨ꔭ���!C�0r�H233���楗^�W��������ٿ?������p��֮]��Y�f
'O����U����\\\(,,$99Y������+ؿ?{��a����[�����4����ի999���Ҿ}{�z�b�O<a�?�8::����κ�}�^�իWs��e���OFF{�����;����)�9^���wc_{cO-�_`` ={���&$$&O���?��W7$$��={���OPP�=�#G���>�]�v̚5K����T�=z4Æ
���@��J�)��B!����2!j��U}k[��ꧺ�i�F=խ:�S���ݱ��VOuزeK��lmm�#�<�G}��_�>�Ο?OOOڴi��?LDD���t�P��v�ܩ�m߾=P������o�����?yyy�jcJ���� uk`�N���~`߾}@��ÇӡC�I�kr��Z��{w�v���e�޽̝;��ݻӾ}{"""����_��W��6t�1��ƾ�rj�e4e�2���-���p�}�Ѻuk�����Y�=;;;	���kkk������"99Y'*lΜ9���bmmͭ[�9r$�۷';;[������٩�nB!���&9˄0��<�M�2�-))�W^�̙3<��"�O�:����ΝS�Ο?��t�*cq���l�̙,Y����\rss��㏙2e
�k׮���Ɣv�b�"((�u�֑�����'����Ν;:Ԩ�/��˗�?"ZjS���.�=�g��9ƫ:S�n�k/��[����)+**�ˍhoo��ٳ�={v������[��C��������quu�~/:DXX���+�B!�mY&D-�sZ\S��f���=�-���DGG�D~5���FJ*C'�Ug(���7[�n%22�p��MV�\ɨQ���/꼦1j�V=J��ё�c�r��A


ԨS�c�� IDAT}��w��۷κ�`������2^ՙ�wc_{9���1|�p4
6l������
N�:Œ%K�*88���_'G^JJ
�����-!�B�|Id�fҔ��դo߾L�4���d���<x0���
j7??_'J�����V�\\\8}�4���S�:������|||8z�(;v�`������2v�X����vk2i�$6l��u�طo�Z�R���ۤ�����e�)Ly]�v���?�Laa!���7�s�W}�ƽ�rj���P��9���1j�(6l�@LL111:�;88���/��M[[[/^̌3�4i�6mb���&G�
!�B��K"˄0��<խ6S�N��Օ�~�����z��x�w�9x� QQQ@U���@E~~>��������5f�5�����޽{���@�6mj�/C�`J���ӟ�Ę1c���)))�/���w_����SPP�̙3���quu�c��(�xK�.��ŋܼy���{�F�&���������^N-�w̛7�ٳgӯ_?ڵkG�V�pvv��Ϗ��u��9
<���p�.]�ҥKy��WM�O(�B!Z>�,�L���9}�4!!!��
		a����n���V\\������l޼��k�����o���;v�fJ�
GGG���߿?&LP�s�NΞ=˔)St�v��]�,88���(��$�MX
��)����_d���@�F5E�������ֺ�WS^�ɓ'�}�v���y���u�j�~���U����6���,


�~&��¦טI�[�jE@@�ֆ!�hS!�B4Y&�	j;-�)Ou�ˠA�?~<w���߯W����X�qZ�n���/��"�V�ҹ��;������qrr���'''&N�Hrr��VP???"##�۷/666������FHH����C�`J�u�С�����Í�z��/���nT�2CLy]:w�LRR���t�ؑ6m�Я_?�}�]F���k��Oߍ}���B!�B!�%YU֕�Y���ʊ��5���cs***b��Ѹ���i�&�_��(T�Ur7���f֬Y����l
��[�j			lܸQ��B___���

����T�C�?�W4��7!,M~ޅB��$�L3i�S݄y���q����@M�-,KN-B!�BX��,�L��T7a�[.���=z�{#rj�yh�n!�B�,�b�f2o�<�w��֭[9u��nݢk׮:���P���,�Ea���W�^E��������$�G��B@N-����tKwA�F��c�Y�B!�had�L3�ԩn��^�U�e�KwAԢ%�N	!�B!�Y,B!Z����[�B4*I�/�Bs��2!������RYYYY�B!�h��4L!�B!�B!�G"˄�����ӦMKwCQO�ׯ�t�B!�-�,�	�?7nd�ƍ��B�34
p�(r��	���c���trss���\pB!�-�,�	TVVZ�B!,��_'++��������cݺuTVV2a����8p�z*�B!�,�	��'DK���n�.#�-eYYY�oܸ��E�����???.\��뱵�m�n
!�B�& 	���*ב�;�y����h4�H񇤤$.]��/���M�8�K�.���d��	!�B��"�eB�OJJ
����RSS	�t7�	��,��� >>���L���hӦ
nnn�3___����PVVFBB۷o��_�K�.<�쳄��bcc�ӏ�}*--%--�!C����ֹ����h4���1i�$:v��8$�B!,B˄BqW���c͚5��۷os���9�����Pc�ݺu�iӦq��Q�nQQ���G�V5�o۶���2<==������dff2v��߻B!��{�6L!�B�222X�b���gϞ=̟?�u�֙\o�ڵ=z��z���T���[���8p `ӦM�n�<�qNN�����R��B!�-�D�	��8q�>}��Ք[�m۶��у��@�{�F��ȑ#�۷/}���ۛx@�Naa!����8q��Ǐ�m�6����6��JOO'779�A�x5�
�^ޔI�۷oϵk�HII��ɓxyy�����m߾���(\\\�ի�/��ח-[��m��v��	z��\Ϟ=u�!�B��C˄�˽���dee=a�����x�7�����k���ʕ+��䐓���?�Ltt�^�O?��o����`$..�u��QYYɄ	pwwg������3g�d�rss�����?fʔ)Ю];��={���ڟ��b�9ɔ2��B!�h9d�w����Z�W�)�2335j�}�YSt���[***t�+**���o�ڵk��>nܸ��E��������X�p!7nܰt��h4�v�U����ٺu+���0��7o�r�JF��_|ar����Zۻv�Z��[YY�k��)u�B!D�!�eB�@��Ըu�n���Ȝ9s8v�X�����AII	G��)��ϧ����{�I�QIII\�t�^xA-�8q"�.]"))ɂ=��doo���			�Y����`JJJ���5����3�7o�[�������s��\�zU�9�L�#�B!ZY,Œ._�Ldd$O>�$C�%((���L��leee�X����ѣY�r%�n�R�h�)u���~�CMר^�<.,,$<<�����z���h��V�bX�D�����G5����R��}�{�9<<<x��牍�5�q���|�M�z�)<==Y�p!eee�k��*��1d��������FCZZ����B�ߘ1c�h4lذ���2z��;mڴ1�ވ#������ܹs�+W�����h�6m�ZW�{�l��\�gΜ��RV=��B!�h�$g�fr��uBCC9w�Zv��q,X�W�֭[L�6��G��eEEE$&&RPP@\\��m?u����������|�w򇰰05z��͛|��TTT�SoȐ!�jՊ}�����ݻ+++��e׮]c�ԩ�<yR-�x�"���8p���DڷoT-jM�2���ϫu���k�_��w]S�v۶m������wOOO8@ff&cǎ5j��
LTT111����<7h� �년��{�n���	

ҩ׮];f͚�>vpp���???���ټy3Æ
#++�������O4즅B!�]G"˄0���Ν;�������߿���x��%�ڵk9z�(=����|����3p�@8��M���N��h42��#G������5/��R��G�ddd���Ô)Sصk�^={{{���ˉ'�r�
Pe��?����=k֬��ɓ����㕐�������$''�u?��3Ο?O�n�X�z�:�?����u�[�#�_�~z�QʪG�	�RY"GYu~~~DFFҷo_lll�����͍���,Ybr=;;;	���kkk������"99Y'*lΜ9���bmm�F��9���ۓ�������l���x�gqD�B!�%Hd���i�c��<u)""��~��pX�p!ӧOש�}�v���pqq�W�^,^�___�lق��o��lmm��?LXXX��͛7��ݻHbb"%%%�>��c=z�}��1z�h���Geee����׀X�`���;w�T��v��
���h�A�����3f�\ה�=q�P�(X]Ϟ=u�!���✏�O��W֧���=�g�f��ٵ�����[��C��������quu��:t���05V!�B��X&��(�ky����[w�85M�
�nW�l�����+�p���}�Y�D���~moo�w���G%))Ig�L)7D�R9`��re�.\���)[[�E��u��2����t��Q��R��Bܛ����ꫯHIIa޼y@U$������N!�B�2�b�����,@նU���R�q�$���Tg(�}]���Y�h���DGG���&�6Ծү�I�i'�6t�@۶m������|��i���bam-�)�U}�Z��f��*�d(?�RV�}��5�	����i,[[[/^̌3�4i�6mb���k��½B!��A˄0�nݺ��O?q��a�h�Ç��uvv�̙3l޼ggg���o߾L�4���d���<x�U?���\�~;;;��(�����0h� ���OFF���<��ɤ���O��СC:[5:�3.ݺu��ɓ|��w:����L�Ν;s��E�^�J�Νu�S6�^.���<���p�.]
����j�B!�����B����9::������9r����zu������?Ν;w�r�
~�!��iӦ�u��&e{a]�N����+������:�988�q�Fnܸ�ɓ'�N�ke�0))	��|e^^^@Un���|������W�K������oj�����r���{�y���2�Jroe�6�L;��"%�57��������L�8���B!��H"˄0���@���kN�>MHHH�uCBBؽ{7���z9oڵkǬY�����燳�3�7o��ڶ���������~�zƎ˟��g�j�*##�e˖�l�2�H��R�._���ؐ��`v���ٳgՓ6ݻw�)

bǎ�8q��_~Y-9r��B�)c;l�0���(((ЋQ�ִ�B!�B�|Y&�	j�����%>>��>Z�n���;o��&P�MQaggGbb"8;;cmm���=^^^$''�D3͙3WWW���k�/�mРA�?�;w����f���ߟN�:acc���'�-��PԻwo��������nǎIJJb���899amm���'N$99Yg����
�������
�<�z�5elG�I������ֻNvv6vvvjĠB!�B�{�Ue]ٰ�h����HII!  ��cs***b��Ѹ���i�&�__4̪U�HHH`�ƍ���U'u���Fhh��{(����J``�z�C������&���ϻB!A�l��L�NYY������;;;Μ9û��#�<b�
C����ꫯHIIa޼y�����쬷�S��*00��7Z�B!�B4�X&���5�
6��4��A'ז�{��ڲx�bf̘��I�شi˗/��$O!��q��Y�B4�q��ѽ{wKwC!�-�,�	a&��ͣ{��lݺ�S�Nq��-�v��СC	

�����]5<x0���,]��W_}U/��Uzz��� �B!D�"�eB�I�V��<)͔�v������t�hT��L!��&�eB!D���+�	�E?~��� �B�H˄B�nܸq��L!�B#��t�B!�B!��[Hd��H``���!���N�8A�>}>���Nnn.��O!�B��2!�����x������"//O﹃Ǻu먬�d„	���3p�@�T��%�Pڮ���X���<��#��Ba�
S!�-FVV���7n�h�"���qvv���???.\ȍ7���B��|}}4h���!�BX�D�	���%DKҒ";��F�0��$%%q��%^x��l�ĉ|���$%%n��	s����htYK��_Z�B!�E�b�����B@@���!�����T�;��TTTOff&EEE�i�777ƌ����Nݲ�2ؾ};���+]�t��g�%44�?����(--%--�!C����ֹ����h4���1i�$:v��w-�B!�v�
S!�ǧ�~�ٳg�}�6eee9r���~����ޭ[��6m�W��…ܾ}���"�9s&���m�6�������{��ӓ��2233�~�iU�*�����ʊ۷o�����GGG"##�r�
/��:t������`JJJ�ƍL�<�:���ȤI�(**��?׮]c�����}�Eu��JQ���ֵ*�1�D�� �JԈ�K԰b�d7j��(��2�TT�h쉱��E F�1��H�(" ��:��y�y�̹�����r�{�iҤ	&&&���@zzz��Y��y뭷�V�u��a„	<~�X�>j�CNr{�ܹ�h��W�N׮]Y�n]��B!�x���2!�BT���V�\�������ݻ�E��u�Ve��M�8{�,m۶e���4mڔ+W��`�bccٵk�
"..N�r���HZ�j���-22������1y�d������?hҤ	�W���/�3sq�ƍ�s����~�6m�ĉ�:u�Z�j�3==�^�zi}�=p�����.i�%�W�^ܹsG9�ڵky���y�����Ky���Att4���<|���ӧ�{�B񲑙eB�'''�%@%96����777,X��7�8Z]���L�2�իWs��E�}.^���ի�2e
���eCi�an���L�>��ӧ�N�B�#����˃��9��><<�{�����A\\�v�R�:t�`oo���M�4a����ݻ��qΟ?�����kvvvZ}D�˙3gx��	�~�)'N��Ȉs�Α��Ƽy�ؽ{���{��a߾}<}����H���|�2K�,�w�%K�G�.]8}�4������Ot�ޝ��JUfq�d�-Z��/����F@@����j�Zy�I��߿��O������ի����BQ�H�L�TFF7n� ""��Ç���P��ݹs���HT*���z��[��JEdd�����ӧ	d�̙̘1��+W_�a	!�:u*&&&DGG�l�2�
�J��Y:v��U��ܴy��f�%�5�޽��&��M�GT>�V��]�v���2u�T gwԯ���-Z`ff�̙3�۶z�j�~�m���qqqQ�F����h�P�y�f:t�@�*Uhݺ�2CmӦMegI�Z�r%͛7��̌iӦ��XXX�t�RIIIa„	��j~���B!^6�,����ŕz9�9��∌�dӦM8;;����G}ē'O�(�����S(;;����ׯ_�1�ԓ'O����������ݙ3g�s�wB�Lr����+���зo_����ܹsi߾=���^��~���c��_a;�>z��55��.E��&�(V^;vT�Ν0mӦ��u�j��=�o߾Zϻw�������1.\�I�&J�/�5k@bbb��Y��ڶm�|meePh�ŋcff�������_�ʂHKK+�8!��e$�2!��y,K�011�e˖,[�{{{�����Cʚ��3>��uBB���t�ҥ�c(���RRR>|�����IJJ�N
!ċ���777���ٸq�R�|�ҥJkkk g�Y�d^\\����Q�vm<x��M�GT>fffzۍ���t|�*�%~5I���/,��{��q�d,��P�D���ù~�:*��nݺ)K8�򗿰v��"�C!�xYH�L�2�_ݟ�/2q�D�w�N�>}X�pa�f9U�Z___�;��ZZZ+W���͍�]�2`�V�^MFF��t�S�N����=����ԩ׮]S�4�0MAl���(:w�\���,Y���������;��ҥK���s��~�)}���Ņ9s���®1��[�l�S�NԫWOioРNNNlٲ���T�c!*��qrrb����Ѽys��큜�}�z�   �s�����3�ܹ×_~����ǏW�j>�k�nBN}&�)z���M�G��N�<��\�o��
#44��._�������*����X�j����ĉ�����Gq��=)�/��ґd����Ϗ��X���y��;v�К1Q:t�\j95�Əφ
�q����ܼy�J�ԩS��Φq��899q��U��g			\�~�Ν;ӨQ#��S�N*�1�'N```�7Y���#ƌ��͛�u�YYY$''�رc�a����=�]�v��222ؿ�R`8��\�ƁHKK���E�<...���q���n��95j�-�G�t��U�]�������Ύ��|||�ҥ���|��ט��*5�ewBwww@�n�HJJ҉A��믗���`ܸq��Đ�����Ǖ䬧�g�Ǽ��xyyq��)��ř3gb``@�޽�,��K�t��_���M�b�GcM IDAT``��5kHMM�}���o�О�&�BT�,�����Add$�G��~(�94�D�߿��mڴ��g�Ҷm[��ˆ��!<<�:��$7x�` g7��4��yxxh�[ZZҲeKΟ?��}�6.\�Y�fJ,�mܸ�K�.ѰaCT*'O�$88.^����믹~�:�5bÆ
�<y��� �D`q���	��/������z5��rwwg�ܹ�l�ccc���iڴ)���|��'J?T*^^^X[[cdd���%={�d���Z��f̘AÆ
122Rf����bnn����ub8~�8���[���T�~}���166�G�\�z'''&O���1����lْ��(�Z�*���,^�ss�w�,���nݺ@ΌK�̵Y�f9;tZZZbbb���o��r�ӧO�]�6Ԯ]��O���
����B��C�eB ��k��X��٬Y�hܸ1&&&x{{����b����3@�nʡC�X�`���ѤI�ϟ���ٳ'VVV:t���L���8t���գG�:�u���Z��.���B�V�[�L���]�vT�Z����3{�l>��=r��gϦM�6T�Z����뜷��p��y '9���?��>B�����6m"**���(�n���ɓuv����d����޽���>��ŋ�"�}���o�!&&�9Eѽ�������J��ׯ�����������7�п�V�JÆ
�9s&����4�cjԨATTS�N��֖*U�`eeŠA�����*�_Z�1֗_~I�&M�R���<���#88LMM155�m۶����a�����?�Κw��e�Νes���e�W!��Q��.B��hڴ�򵥥%Px1޼n߾
�����������/9	�������ݻ7QQQ<x�q���-ܹsgBBB���b����+�|��,����ƍJ��@�v��ͭ��ny��v�6M!īgԨQ�ٳ���Pe�Lhh(�����Tpt�,��j�b���Z�ڵk���:v^�j�bٲe,[��������4����,�9���Y���ѣ�Y�Q�T@��܆
P�T6��c*���B��C�eB �$�,��,U�]���;N�u��)Z�l���^�܅��}�]6l���~K�޽ٻw/���4H��۷��Ą��h233���Qf�����&����mL_��r_����N�մ���*+�����O333�ϟϔ)S1b�v�bŊ��ew��)<ȢE�hӦ
���xyy��k���XW�^�￧nݺ�Z��={���w�q��5���/��-^!�Ϗ,�����IXX���R����ݻw+��r?bcc��6668;;IRRǎ�7���527cccHMM%""���Tڵk��J����5�5��>5	@
}���s��k��:�Ѵi�!^M���L�8�ŋ�x�b&M�T�?�S�����8q��={�b�
�6mJ׮]Y�b���e6VHH�����(˟���			��k``���G��v���F��l߾�޽{S�fM������eʔ)<z��S�F
�5k�����_000К�_�x�]�ƨQ��[�.��ƴk׎�����=z���?M�4���;;;HOO�ꗝ��ܹsiѢ&&&T�^��]��nݺ�BQj!^A�:444��qttT;::���k�ז���NLLTO�8Q���vssSgdd(��\�R���~��?���:++K}��m����Վ��j???��9rD���Q]`7nT;::�]]]Վ������|�jbqssS�9sF����>s�z��jGGG��e˔����jGGGu����?���:33S����vww��E���ӧ��?����=���Վ���?�P�5Qy����s���������߄x��;P)~�xyy�����癙��}���G�����T����V�T��x���l����P�9sF�V�էO�V��^{M�����_s�j���̙����1b��Z�V���͛��Z�x�PO�2���&''������R�~O�<Q;99���o��={��9sf�׾dɒb�BQ����2!^ �7
�֭������`ii��������;;;���K�.�����_cjjʴiӴ���+3�5j�o�1
M1M�����CN��ƍs��uF����3�G��ƍ4n�X�����-Z� 99�q�����̨Q�������u�蟡�i{����f!�BC�VZ�eT�J�~�m6l�@rr2�7o�Z�jL�0����3x�`v���'O�u�Çs��e:t��%�С:t��~�w'�֭[����3�*o����X�z5iii���+�ܽ{7ӦM��‚E�i�K�;�S�x���n޼�������������|��g��d�����ҥ�O�&33��~���ݻ��w�)�����ؿ?O�>%55�իW�r��b�BQ8I�	Q��σfy����ټy�N2����J������aiiIϞ=Y�~=-Z��ꟻF���{����7o����S �U�V���^�:!!!:�z��addD�z����d�������


��ÃZ�jall�[o�E@@��y�s�������s��q��?~�z��Y!�(�gϞq��=�޽˥K��t�����g�>��s-Z���?���L�0???���u��5v�X�6m�<����,4n333�BDD�n���>#""��͙2e
iiiE��䎯��V��f���z��1c��2y�SSS��ΦS�N���2s�L&O�h�[�0agΜa߾}ܿ���H,--y�7J�={���S��ͱ�� ((�Zͅ��/<<�͛7ӡC�T�B�֭Y�~=�6mR�ZXX�t�RIIIa„	��j~��b�BQ8ue����000 44///����i�ڵ�s�N6l���9h� ���;vlG(�SXX����L���_�M�JJ�b�
N�8Azz��,���������~;��G�IDD�?�����<xp�Ǐ=��G�P�F


�^�:U�T��ܜ�>��|�߱c�֮Ж��Z;\���bkk���7����>�?f׮]l޼�`ddD�N�7n�����������֩�����7oޤF�����<y�D+)�_�͛70`?�����k~�ߺu��^{
'''�;��͛���bȐ!J��$񚘘���Azzz����������geeŝ;wزe�G�V�����ԩS177W�)j?!�����0��ƨQ�سg���̚5�p`mm���OG'D�ٶm��2n!ğ�W������A����KϞ=�^�:ԬY�3񕷘|^��ٕDA���dffr�6o�̮]�x��)o��&�֭cРAT�^�X�+0�9ɯ��0&L��՞��Ay�����f͚1p�@ڶmK�ΝiӦ�V����������ˉ����o���`�$ޢ�]�~�v�-��EÇ��Օ�;wLdd$,^��0~��b�BQT,M�
��������ݺuS߸qC}��
u�n������ϡ�<�Q���y�4��={�>r����Omee�600Pw��]�j�*uJJJ��pttT�}���}}߾}j@��䤴i޿��k���PZ�&%%)�so�t��u�������[mee�644T������Y�fj@[��(z�-Z���˗�Oll����>Rj33�R�B�C
�!*GGG&N���ŋY�x1�&M������¨�W�\�Yb\����-={�$::._����Ǚ8q"u��-����iժ���z����ҢE���HHH(�8�[���'==�S�N)KL�ݻ�|mccØ1c��ݻt�ڕ:u�*�~��0u�T�^�JZZ�'O����͛+��߻�����N�"++���dfΜ����{�V�6m�֬YCjj*�۷�}��@N-��BQ8Y�)��t����Ó�3t�ЊA�r��н{��ㅥ�U��닧�'�[�.��k
���.A400�>`ҤI�T*eg��8p �6mb�ȑ�9R�S�Ni՘�5k��d�%�%����;���DEEakk��޼y��E�����Ν;������Q����9K�,Ѻ����3q�D&N���7��E�'��p2�L!��Ķm�ƶm�*:!�Ŷm۸z�jE��B���/Q����(�DYFF���XYY�M`�6j�(j֬Ihh(�k�ʕ6�jժajjJ�Νٺu+���W^�-�N�(u�
4��ɓ6��5kbll���#۶mӪ�Z�~5j� **��S�bkkK�*U���bРADGGӱcG�������888`jj���)m۶��ߟ
6��B����2!�����0EeU�b꯲���%cccn߾]��ժU�Z*�V���˯�f͚lٲE�k�gliDFFТEe���`gg�o%�W�V-�-[Ʋe�
�;z�hF�]f��BL�eB!�B�J!55�Ǐ�駟0cƌ
�H!��H�eB����7;w��0�%$K
�B�^~١C|}}+.!�/-I�	2��CB�����
'::ggg�A���_���ܹC�^��ꫯ�RE>�!�(>��Cr> 	!�xu�>}���@�n݊Z�fذa���ӡC��MQ׮]���BT�,),De�_qh!����>��c<<<�b����̙3�m۶affV�
!�B��I�eB�ϠA�d�8!^baaaRw���������H����RRR>|�������͛			a�ĉ�B!�x�$Y&�2Dj	���̔dY9�$Ң��Y�t)�~�-U�Ta�С�?���s��1�V�J�=�5kժUSΑ��Fpp0��?��N�:��oc�ر�Č3���g�ڵܾ}�+Vp��	�<yBӦM9r$�g��}E/55�-[�ЩS'�ի��7h�'''�l�ˆ#�^�z9�Y!�B�"�d�B!��/� ""By�n�:6lȶm�8{�,����ٳCCC�͛@FF�ǏW�ܼy�JERR���j��t�RRSS���Ǐ;v,������ܹsJ�,��w����pqq�9������<x����~	!�B���$˄x��?�-Zh�if^�ebb���-�����߿\�ruu�e˖�hт�}�ҬY3�>/^���?�s��q�2������xBMRR�7o��֖�7�v�Z-Z���=;v�A�lذ��� �;��i�&Ξ=K۶m�={6M�6�ʕ+,X����Xv��ŠA���jҤ	*�J������
���?iժ���̙3����c�3^dd$�Z�ҹ^M[dd�$˄B!^!��wBT�?�oo�"���)��������ѣ�ܹs���HT*���z��[��JEdd$w��)�xJJ��̙3�1c+W�$>>�����999i=
k�y��+5�>}��ٳ�����Ą#F���C��`����122�I�&̟?��{�����㣵\�~   �v��Q�jU�3g�α����������N��B!�x5��2!^`�%��Ψ�{�.˗/g�޽|��׼���666��Đ�����*;;����ׯϭ[��=����(�ܳ\��͕��6m�|�����ի����=�ŋu�4�*�+W�бcG�v�R�w��]�5�4m�>B!��� 3˄(}3-^$VVV̘1����������ÇILL�jOHH 55�.]�<�8J"��RRR		��Ȅ(qqqZ���!g��>y��V�|�ѣG:m�g�t.�R��9^�5h��!�B!*/�Y&D���&((��r��M�V�JӦM8p�N-���ҖwY�6WVV���.�s�m�<߲eK�.%!!�|�M�N��3k�K�.DDDI�����(:w�̮]�t�LMM%((�Çs���ԩC�޽7nZ}�ܹêU�8z�(O�<�w��z�z��'ċ��ښ+W��{�negq5jԈ_��3g�йsg��̙3��v��$''��j׮���f)i�v!�BQ���2!�H`` �֭��իdff���Fbb"���?	

U�ivi۰a7n� 33S٥m�ԩdgg�h|�Z͝;wX�x1mڴ)����Kzz:<`ǎ,]�T�_�N�044T�c'N����@�C�ƣG�3f�7o�֭[dee���LXXcǎ%--M雚���ѣٵk< ##�����s�����v�KKK��źgB�z����;w�Ϟ=�Ν;|��8991~��B���[o�p�B������"11���j<��R�2��4my7YB!���$˄(#�\���'Or��1���غu��/�.maaa���N��]��ˢ��]��S�N���r��A���x���Ku=���ʌ�ѣG����Ғ�-[r��y����۷�p�͚5���J瘍7r��%6l�J���ɓccc�ŋY�~��믿��4jԈ
6p��I����p��y�zo��;�	!J���;;;���K�.�����_cjjʴi�
=���7vvv\�v
___���y��v�Z���֭���g^���_���.�B!^B�,���-NS�:44���p�ݻ���qqqZI���
WTFFFt�ؑU�V���ڬY�hܸ1&&&ʎ�>�۷K�.��jevYTTj�:�ze�v�k߾�������J�#G�0{�lڴi�����]缲�%�_R�,XXX�R�������###,--�ٳ'�ׯ/��-333���pss�f͚T�R{{{>��S@��Yq�suu��ܜ�Ǐ�y��q,,,�YmB!��� 5˄(#S�N�O>!::���h֬Y��ѣ������T�W�]��`���C&L���+W���V&������� �%��;w&$$���(�U�L��ׯh�8�?w��q����Ю];�}s��(�%ъ�nii���ә>}z�Ƃ�ML�Ν��v��M�ԩS��U�������\�~��
9����������S!�BT~2�L�g���}��o�>�ΝK���IOOg�����׏;v(ǖdW��XZZ�������…�.��7~FFF���V��|]�Np�۷��Ą��h233���Qf���d�&޼��J�\��'D�գG���ؾ};>$;;��~��O>�П@/�Q�FѠA������X[[���S�؅B!��Ef�	Q�,--qss��͍�g��߳a��.]�����N��-[2b�֯_ςpttTf�AN�G�V��ce����b+���1�<y���RSSqttԚQ����
�/_&>>^k�f||<��}iԨ�.]�ԩSZ�����������Y�h�-�z�V�Z�7���633c���L�2�#F�k�.V�X���1!�BQy��2!����Yiii4o�{{{@{�Vqvi��l�,/,̘1chذ!���#((H�Z�j�s�N�<y¥K�t>p��f�eHH@���z��	��KHH ++���eW��Ŵ�~�m��S����⧟~��>�9��'D�5k�,�O�N�V�055���kkk���	

U�O����#'Nd���,^��I�&{v�B!��df�edԨQ,X�@﬇��|}}9r䈲K[nywi�U�w�����kkkv��]`fff̛7???�m���y�׀�UDD˗/g���Z3�JK��}���s}F���Ç�z���ӦF�ƍ��|||����9����WWW�DWq�m�n�8z�(III:�e<!^<���xyy���Unc����B!��Af�	Q�����ܹsiٲ%���ӴiS|}}��:P�]�f̘AÆ
122*��Xn:�gϞ�d��}ڴixxxP�F
���qqq��?.��ռys�������Z�ʷo���			a�СԫW###�ի���'�ׯ�Z>jllLPPԪUccc�z�-t�+;�	!�B!�(-ua����

Uf�}.^
k׮%88��;wj�7h� ���;vlG(�#,,oooe����_�M�J�]!�� Nf�	!^Y��B!�B���f��%;�W���7����B!�/���� IDATI�	!^i�w�d<Q鄇�WtB���6�B!�(	I�	!^y��B!�B
I�	!���СC+:!ʕ�B!DY�d�BQ�I2ATV�B!*!�
S!�B!�B����eB�϶mۨZ�jE�!�(�m۶UtB!�B�J@�eB��Ν;ٹsgE�!�/������Kff&^^^L�<9��p��yZ�h�����T�c���<���9FC_��Ntt4���R�N!��H�L@�VWtBQi̙3�S�N)�o߾]`{Y���9z�h�X�KY�x��iٺu+j��aÆaooO��0R!�B�W�$˄@v��2	��^y			�Y�GGG���
l/kG�-�L���\��X�'O������ၵ�5���̙3�m۶affV��!�B�ʤ����:�zGB����t�����L�0�$�������.�/$$������yzz���BHHHF&�B��eB�Ohh(^^^��������0*���T���8|�0w�ܡN�:��ݛq��aaa��˝p�ԩ�3�*����l���8x� 7oޤjժ4mڔ�2h� �����СC���ԩS����o�;VI���4��8p��~�)���S���Ϝ9sx��7Y�h��E���b,�HMMe˖-t�ԉz��)�
4��ɉ-[�0b��W�^��B!��,B!D!=zĘ1c�t�Җ��LXX����T*���Kt�@6nܨ<���$11���D?~�$@322?~<gϞU�޼y�JERR����݄yN�>�_|���
4 99�E�Q�^=fϞ]��)ͱ --
�s�����<xpI/_!��&�0�BQ��7r��%6l�J���ɓccc�ŋY�~��7�,���8�y~��\���'Or��1���غu�r̦M�8{�,m۶%,,�������С����ڵ��qr�,9�Ш^�:�|�	�?f�ܹdgg3o�<?~��󱴴�{��r=������j�Jg|M���B!�(>�Y&���h����~�۷o���ҠA�~W�^���]y�g��ׯ����8��u�o߾2��(˜J��$��fllL�:upvv����
�-?��ߊNtt4��β��+"��dy����������ڵ�}��̞=�ɓ's��a&N�X�8���y�����\�t��={��၇��V�C��`���I�&̟?�A��w�^�e��թS'���

e̘1$&&���I�ΝK}=�9�����������N��B!�(>�Y&���?�Z�Ӻuk�eH'N�P��U��O?i��U�����7���`����n|/���oE8}�4���̜9�3f�r�J���+4&��~�:�� ˭cǎܸq���:u*&&&DGG�l�2�
�J�"==]��իWpssӚ	�I�]�x��cjfs�{�5i�$�5kFbb"M�4����zJs�ݻw��$Ӵi�!�B��d�/��G�j=oӦ
Pp�L�|�<�Ms��N��!��Nj��#22�M�6���LZZ}�O�<���r��>oO�<��?���kkklllpwwgΜ9Z�HTN�%�
K喝�]�8���˾}��;w.�۷'==�իWӯ_?v�ء�S����ѣG���,�zJs�����m�6M!�BQ|�,��ִy��Y�����ӧ177����ܜ��X222��UT��"���вeK�-[���=���w��^!!!���0|�p���ӓ��BBB*02��,{�;�P���ںT練���͍��`6n�ȨQ�x��!K�.U�h�ؽ{��a�����!?�V���ŋ�nݚK�.X&�S�ck׮
��t�״i�!�B��d�e$;;��k����N׮]�ѣ�;w��雖��ʕ+qss�k׮0�իWk%�r'�4I:M����:_ll,���t��sss���IOOך���͹s��dYjj*K�,���8;;��;�t�R�Y�N�:E�޽?~|��b�����ݛ�˗k��\/^d�ĉt�ޝ>}��p�B�M�o�f�ܹ��ݛ�]����������Z�*���;vL'��\gQ�7�[�n1o�<�|�M���>|8{���'�J��x{{��o0h� �?W�^��ɉ�*clٲ�N�:Q�^=�_�
prrb˖-����ފʯgϞ@N�������HHH`�…����%>���qrrb����Ѽys��큜�[�^�z9u�Ν;dzgϸs�_~�%NNNZ?��YU���%������0:t�J����͛7�����ף/Ƣ��sx����5m]Q!��e&��(#���lܸQy���Ibb"���<~�XY�������f�ݼy�JERR���z��ԨQ��
r��u�]�F�F��?�u��
��ݻs��aN�8����/_&--
jԨ�,[3f�.]R�HNN&,,���XT*���Z1,]����T�Kn˖-#44�6m�0nܸ��2"==�;v���M@@�?f�ر�����1�Νc����7?:t�…���{��y��޽˨Q��}����ŋ̝;�gϞ1`��|�-�{ҽ{w�u�J��ᆪo߾JM��G�8p���4�#7bcc9x� �.�^��oԨQ>|��W�2z�h��7n��V�s/X��E��h�"����}}}9r�			���h�355eڴi��Z�jq��]��ݱ��֙MZX�=..���T�ϟ���9�~�)U�Ta���xzz2o�<�nݪ�fXQ�G_�E=�[�n=z���$�v���$�t	L!�B�W��,��DDD�r�JN�<ɱc��`�֭J�M�6q��YڶmKXX111���ӡCbccٵk��B��nY�dY�n�000Ъ[�o	�ƍ�t�
6D�Rq��I��������ŋ�_�^�:�4iBdd$�~���kK�.%44�&M��r�J��N^���DDD�|���������_PPP����XYYp���B��΢�o6l��۴nݚ���;ƻ��J��K��x{{cnn��O�,�|��|ϴj�J�|�6}�D�ʫ�eիW'$$��C�R�^=����W�����_�KK������ܹsiٲ%���ӴiS|}}��O�~�T*���������KKKz�����fR͘1��
bdd�w�gQ,Z��[�n1k�,e���
�f�"%%E'�U���cQ�uuu��ܜ�Ǐ���q,,,x뭷Jt�B!�Bf�	Q��f�m�����ܜG�ʥK��ٳ'xxxh�=t����I��I�&̟?�A��w�^ew7}Z�j��9{�,������/���`ooOݺu��Z5-[�����~��^ӛ,�$�h׮�����ٳ�<y2�f�ĉZ��(;n�t�R��°��dժUE��<k�,7n�lL�R�x��a��9880g�>��Bϟ׳g��R��_}y��8�&I9s�L��s)�{R�F
<<<ظq#QQQ������ʙ3g�V��2��@N�2/;;;�>B@�֬Y��5kV�}�K�����憛�[�絴�d���L�>��~}��՚YY��|��g|��g:�������(ד_�E9�Z�jxyy���iذ!��ki||<~~~���B!�B�Of�	QF�N����	���,[��aÆ�R�HOO�ꧩO���ԜrrrR-/^,p��3�4���ݻk��<׼��O?i9� '�[ǎ�q���DJ^aaa@N-�{��x
M�6U��$�r������ģ�w�QQi�E֪U�оy��8�澕�fPY�'>>>���(E����x��]�vU�w��л�LӦ�#�x�5�
�����bmm��LU!�B�$˄(@���
j�۷/���c�ܹ�oߞ��tV�^M�~�رc�r�Z�.p̼E��jٲ%����;w���le�\Aɲ��,.\������ewy�-���Ye^^^����V�Y�vm�c��b��g�-ȩS���{X���Y������8������$%%)K�r�0�Ĩ�>���<�CQ6��̘?>�v���ܼ͛y�]�v1�|LMM+:<!�B���,��YZZ*KhΞ=��φ
X�t�R(��ښ+W��{�n����=���9vvv\�t���x����m۶Z�Z�n��������Ǔ��������._�L||<]�tQ����X�j���ԩS�+Vp��1Ξ=���$5jį��ʙ3g�ܹ��~�̙b�+33S����ٯ8��կ_�k׮q���b߃�zOF�����ٺu+QQQ*5� g�nrr2<�v��Z�j6]��.�x�8::2q�D/^��I�J<�V!�B�If�	QF���۷o'--��͛coohϠ�ի�S��ܹs<{��;w���_�����㕾��=�%��Lpp0��ٸ����200��ŅgϞ)E��&n4I����@VV			,\�(�nj���4k��5k��X}4�.\HRRYYY$&&*��ӧOIJJb�ԩ\�p��
���Z�X��i�R�/&99���t�������B����-���nݺ8�������C��׿R�fM�u�Q�R��4m%YF*�x����X�d	K�,��ӳ��B!��df�edԨQ,X��E��쒖�/����9r�����2���L�6My^�V-�޽���;����޽�Iz}�����h�ʭ{��|�����*�����\�zUٍR�q��:m�122b��ٌ3��'Or����[��������|�2���E>.��,--���ϵ��EU�����СC$$$��;�h�}��������e���9�m۶�I�nݺq��Q���tf�$%%�=F!�"?��s!DE2dH��!�2!�������ݩR�
���\�t	�YF���3j�(����*��u����?�����R8~�xef��3X�j���ddd(�����7&ggg�T�BVV��,�^�:!!!|��W9r�;w�P�vm�����_�-�j׮�.�Y�����133#((���@�;ƣG�hҤ	>>>̝;7�i�cmmM׮]1b���/Q,�y�j׮MHH����<y���t�5k���/}��Q��{��=�V���u�=�^suue���?~��#Gj�v��q,,,��}B!��:thE� �@���@]g�%c``@hh(^^^z���͛70`666�ڵ���ya?~�iӦakk��Ʉ�ڵk	f�Ν4l��ٍsРA���1v���r����������B~��W�|��␟?!DE+�����2!��G�������O߾}����ʕ+|���t�ر�#|1���������9��5j{��!44�Y�f�����RS�r�f�Ν�B!�/I�	!^X���c���z�ժU�q��UPd/��K.���0`��~fff̟?�)S�(	�]�v�b�
LMM�K����E�!^TC��q���B�a&�x^���,B��f͚E�ƍٷo���ԯ_��]�2v�X�իW�!���իǃprr"  ##�|�:::2q�D/^��I�t
���[xxxE� ��$5̄�Ky�]�d��ehh����Ծ(��{����������C�\I�$!^\��)�(O�e�A�eB!D%7h� ��"*%��"�B�� �2!���2d��.B!���+:!�B!�B�����\�!���r/
�Y&�x{{��zg!�x���������X233���b���������ӢE���:u�o�����x����j5���t��ooolll�m���p���pvv�e�B!�$�����XZZҢE<<<�<y�K�����5;v�cǎ:������̙3���s��iN�>�͛7K=����of͚Ž{�J}.�}222�z�����ѧO&M��k��V&cB�_��d���'�eiΜ9�:uJy~�����ڇ~�ѣG����j�����>c���:�\�z��W���7߰p�B^��2�����u�V�j5Æ
��ޞ:�h,!�";;����CLL۶m�~��ܼ�C+���d���Ǿ}���矉��ȷ�y��o�t�q�ƕ�����3�߿O||<���Z�����������u�Jd�B!�TBBk֬!66�ٳg�^֎=��}����޽ƌÖ-[������ѣG���	(q"/���<y��������������Μ9sx��I��B��Q��Z������پ};��_���e��f�5k֌C��������O���w�akk��#+}�ӭ[����0`���9�={�Tt�"2�Ld7-!*�Z]�!������Έ*���,��<���/�رccc���+ڶm�����|��G|����ر??�2?$$������yzz�y�fBBB�8qb��%���Q�jU�ׯ���]�6�z�b�ƍ���Њ�_�~�X��cǎ��o�~��?~�ȑ#Y�fMDX:U�V�^�z��Ӈ>}���G��_���ǯ�����IE�(�eB�Ohh��_�!y�<���Њ�5R�����d����3��K�.�ѣGZ�4I7�N�:)��k���f�ڵ���ӵkWz��{��Ν;ubHKKc�ʕ���ѵkW��ի��
�{'''�;P��xzz�$�r���_�~�jժ��NMMe˖-t�ԉz��)}4h���[�l!555ߘ�B<W�\aܸq4n�������ٳz���+..�!C�P�n]���iڴ)���:��U�.]���JOOgٲe��уڵkS�J�ԩC���9r���]�p����ӬY3LLL�Y�&���|��'ܿ_�1Žo����w���]�/?E?�{��}*�=+�������پ}��k�����2��eB!�(УG�3f�.]Rڒ��	#66�JU��(���lܸQy���Ibb"�����ޝ��x��H!b��&iג�n��ډ��Ј"֪�[��*��-���� Q����DhBS""��ZJREId���7ϝ��d�l��z�E�s���䙙3�RRRԍW222�8q�ޛ݄�������e�ʕXX��P�b�W�^y��~��|��GziE�{߾}���Ү];�c�ڵ�ĉ�߿����6!��#<<��}������i_�v����������Z�
6��o�����]�|�O?�����N�j�
UǩS�hܸ�^zrr2���zqC�ܹÞ={ػw/������W=��/�Э[7�/s2228y�$'O�$  ���H�}�Y�xQ���Օ�U��{�n>��s��w�J�*t���d���q3g�
��‚ɓ'3v�XBCC�;�]oI��<��eB!���ƍ�|�2��������������ս�3**J��T�6��+����ȑ#̞=���`����@���h֬�7o��㄄�ТEN�8Ahhh��h�e�W�^��_Ժ�;`�ZM7M�G!Dٺ{�.$''����ŋIKK#""��cǒ��������-c��uc�}��7���w&L�@vv6'N��'##�#G�аaCN�:ŧ�~Z�����p��m�mۦ���;���Y�x1'O�䥗^��ѣ������Ndd$m۶EQ.\�w�����Ɍ7��/���Ajj*��iӦ\�r�?����U�re�v��ŋ�x�ޱ�~��˗/ӹsg�_��~�c�����;f�աC�����8��R�x
JPP����ʹs�LS����=z(�[�V�w�xyy)���%R�F�Q4M��]����///���K	.���HPP��������EA�oڿ�~EQ<<<�F�?~\����E��(4Z��:u���[�h4ʔ)S���@�?�0گ!C�(�F�q�^�����F��7.�zZ�n�h4%##��cQ\uk�x��m��o߾�h4�O�>F�-���4*/�>>>
�x{{=����q����bŊ
����{z�f͚���
��_@�W��^:���2{�l�2���@���_
�]�xQ��U��W�RE��������XP����4s�M�vEQ�U�V)�����Y�d�(_~���9�Y�.s�,��III1(���5��'E	���EV�	�x��w�巺>|��ό38r�w��%++�����#�q�s IDATG�0}�t>���;����ͩS�X�r%�3g�dŊDGG�u��(�nܸ@����_y�n޼iv�ӧO�r��DFF��3x�`���IOO��w��5����x`...0����<���
�~�z��XԺ�޽@���
�iӴy�B�-ml��S�=>v�X���o�����3t�P����ի�-�;��O?�����EQ�����vEQ���_9{��^��+WP��-[�����`g�^xx#,((H��^BQ��ϸio��������=�[(��~]�YaU�Rx�y���-�~�W�L��DXX���r�lll;v,]�v��g���DFF�f�~��G*U�dg�(uǎx�)--�y����ၝ����̝;��[�āB�-�߸9�a����={��M�6>|��;wr��iV�ZE`` S�LQ�x):��_0d�F�͛7�駟?~��1Sc�UԺ�Av��5Ӧ�,���i�Sj�o���VA]�Ǐ�ʕ+4lؐo��KKK���/Yr	U�_�rrrHJJ"..�����͛7Ӯ];�?n��E;{�,'N�����Ϲ˝3go��DDD�&кu�F�~��۷�ޮ��1nNNN���K������L��չ�>ǎ�Q�F4l����Q�)��JII��ֶT�-�~�W2Y&�c,::�={�`kk����^��ڵkӧOڴiÐ!Cسg����e���~�znݺ��b:t(�~�-�ׯ7�͜�x���s�����՝��MV~oL�ckk���nnn���q�6l؀���:Yfgg�իWٵk�Y�����k�.6n�H���y饗��3����uשS���D�߿O�:u�ݿ_�#�����7'�7�|CHHիWg�ΝԪU� ��K���,,,�Y�&�ڵ�]�v899�h�"fϞ���tpp0s���۬'/�G��F�|��'jL��ׯ@@@
4`���ԯ_(��i��Ӈ%K���?����?�@VVV�����~]���Үtpp(�zK��܆)�rrrX�f
���mۖN�:��[o� i����b�
���h۶-���cժUz�M�b����s�NF�i2(u�ڵ>|8�}��A9>��?�C�t�ڕ���s���|���Vrr2˖-��_�M�6���___�U�s���<y2:t�[�n,Z�Ho�oA�199�-[�ЪU+�V*��{�l٢�S��x������CLLYYY��Ĩ��t������۶m#55�F����@�J��|]�t��ۛs�Α��͝;w���/qqqa�ĉj^�*-����׿��� ==�q�Ʊ|�rΟ?OFF����lݺ�#F�Qu������sӦi�!�([�(�ݻg4h��GwK��~��iӦQ�Biڴi�u�2���R�6o�̐!C�|�2�7f޼y����s�N.\�`��7�x�_���W����Ϙ1c���K�.1}�t�>�3n���b��*���7YV\�k�;f�q��a^}����4�Q^��2!̰r�J6nܨ����ə3g8s�)))j����&N��.�G;�����ʕ+�ޖ�u��i:u�g{:t������u}���ڵ���t���Ctt4���&�����~�m�o$�[1�8q��i&L����HOOg���������
|���Gjj*�ڵ3hW�v�8q����WW�!�רQ�8x� ׮]c̘1z�
�
[����/f���z�t�k�=�Ç�~A�U�J�����kժ�ݻwqww���N����{T�X���`6nܨw���/�;rG��۷',,���X��!���@�&�B��
r��I~��gz��]�����2d���|��G�����۠A�������}����l�q����Y��	&���ݝ2''��gGGG�z�-�z�-�Q�~����=`���֡Clmmٻw/���o�>�U�F�Ν�<����*��';;�u��Я_�����Q��ha�;v�b�
"""8r��*88X�H\\͚5c���?~���Z�h��'

���DEE�����_@��8=���ܺu���ѣGY�|9���coo�͛7	̳��6n���˗qpp��ߟ��������'>>����s���رcǎS?L�~�U�q<v�M�41�C���#�0O^�իWg������ԭ[KKK�֭�СC	(��{n���̟?�ƍcee���
4`���z[�������'vvvXZZbkk���+z+�fΜ������z�x---�9s&AAA4���T�\�֭���+>>>l۶M�vӢ�ݫW/�V�Jxx�A���ñ���G�f��B����k��&�������P�B��N3g�$&&F����e???�c���T�P��]%��~�M#M�zZ������;@�իG�
6�~�m��V�bEz��ABB�7o�֭[t�ڕʕ+�y���kW���jΘ�ܹs9{�,
6�o߾E����Q�Ǟ�B<i(��ֽ{�V4�2e�%00P��?��2d���h�7n�_�~]�h4ʸq��4�F�h4�|������h����<ۓ���h4�M�6�8p@/odd���h�<�Ν���h4���z�"""�F�8����~�MM�w�h�V�Z�iGm�۷o�}����h�>}�=W<=Jp��'JQ�o�d�^�Zqqqѻ���������_�a˞l�|��Q^�����F�
�t��M9~������<xP?~�bee�T�XQ9u�z�Ν;@y�嗕�[Dž�ʕ++��(���JJJ�r�套^R�?����9��5���ʥK��O>�D���R%00P=ްaCP&M��$&&*YYYJll�2b��\@�z��z��ٳ@iҤ���~�Jff�r���W�^
�4�H�f�_~~~
�ԯ__�իW�{���W�^]��[�*����Ç������L��͛Jhh�ҳgOP*U�������3����Ǔ�����}�B)؋�v�G�Gk߾}J�v�����+~~~JZZ�^�y��t��Š>]}��U4M��K�.)�Fqss3(/%%E/o^k��նm[E��(���F�k۶�����|999f�c�֭�F�^�u=|�Р?��$�e���+�Mjj�ҷo_��O?U�>��S�_�~�<Qp�|��Q��w�ޭX[[�M&�Z�J/�F�1�W�G����R�B��ڶmk��P��?cǎ�;wݺu&�Λ7OiԨ�(۶mSϹ��ҤI��988(W�\)Ҹ�K�͛7�Ʀ�R�����j�q2g�
�8���(�}��A{̭����(��2�
S3��ٓ�{�2�|�7oNzz:�V��O�>l߾]ͧ�
o~A=_y�8�g>�qm~]+�&�.�-�{�s/�ե�[7X�VA�Q{��6kӌ�/��kkk,X@hh(			$$$ʂ�R�JY7O!��>}�͘1cx��T�5jԠG��߿�I�&��t�R��3faaa��ݛ�5kbeeE�ƍ���9t�P�^*W�L�z�2d{���믿�;>n�86l�@�-�\�2���t�ޝ����|��G̛7x�J��֖��>���6m���5+V�aÆ��:u
'''�z
;n���٩�k^z�%t�9��_���^{�jժQ�bE5��9c���+��3�Ю];,X@||<0�gn��Տ����S�{�lmmqss��͍��88��
�U����q��Uv�ڕo�1cȞ={X�~=;v�aÆy.\���&0v�������R�	�?���B���ޞ+W���'::�?��)�:uꐘ�����S����
r�!��F��0y�d�.]
��)S�!�x<8;;�)f���mV;v,�/�}	���#G2r�H��F�a4�U�5����ǧ��f�t�~���B�cN����c�޽F��3fE}�̭���!$��f�߿?...l۶���T5j�n����J���ۛs�Α��͝;w���/qqqa�ĉj^�ʨk׮�i͛7��_'55��cDzy�f���O���HLL$00�q�Ƒ���k��F�-ںp�Bbcc����ԩS�]�^��;7WWW|||���!++���-Z���[A�Q<��իeh�tl!����ӓe˖�l�2�Z��B!�F��2!�0j�(|||X�x1�/�;��J`���>|�������J�*xyy��תU��w�����v�M�=|���~�	___�]K��t�.�ͭv�ڌ=Z/�iӦ<8ߺs���\�vM��R���� � 
:��۷',,���X�U����y�uB!�B!Dn��L3���3�|7n���VVV4hЀѣG����lll����;;;,--�����Օ����P3g���KKK222�t+++/^���/;v�f͚XXXP�V-:uꄯ�/K�,1�����/:t�bŊԭ[��#G�f�����[W���Y�~=o��&u����Ғ�u�2t�P���-�q�իU�V%<<ܠ���plll�ѣG��B!�B!r��eB�Ig+?���̘1�3f䙯gϞ������N�:ѩS�B��F�|�����X̶5j0k�,f͚�gy��K/�8V�V
OOO����q�ܸq���h&L�@ժU�,C!�B!�(�,B<F���ݻ	

R'낂����3��U�o�֭zq�B!���d��`mm͂�6m��cKhh(˗//���B<����{�����n�B!�O�,B<14
�'Of�ҥL�2� �B_qla.�B!��D&˄(�L�
{�yzz���Y�����o�u�(Q��:t(�f!����2!��ۺu+�
*�Q��n�ʀʺB$f��$i���,B!ʹ�� Y�)ʥ
*�u�y���B�'�L�	!�B!�(V3S�$��2!�߰a��/!�`%�[!��#13��%$$��˔�2!�X>B��w���u�K�,�ĉdff����ԩSM��������/�߼y���@"##ILL�R�J<���t�ܙ!C�`kk[�u£7q����i�F>D
!�=��)�(i�L�V3�B�;w.'O�T�}�v�����w�%,,�`W�.0n�8RRRԴ��Ο?���ٵk~~~ԭ[���8u�+W�$88EQ<x0��δhѢ�B�'���B��͛73lذ)[&˄BQ�bbbX�z5�����<Ӌ[XX���e˖���B�֭�6m���'++��~��e˖q��9V�\�G}Tlu���1o�<<<<�����ݝ�s�u�V���]�B!�(Y2Y&�Z�L��Mb�����ѕQ���sqq�B�
XYY�^Z��u.�f͚T�X�W^y���9z�h�ֹ~�znݺŐ!CԴ�C���߲~�z&O�\��	!�B����2�T��	B��w^����Y�n�Ν;<��3t�ڕ���ccc���N��j�
x4g*=''�u�ֱ�~�T�
4���0@�
��������?��_��3�лwoƎ�N��֓{�v����ܾ}[�,�rtt4:QX�:���ٲe�Z�һ�����Ņ-[�0b��W����!�x*��,�8��i �e�$1ʄ��<x��o���˗մ��D6o�̉'�jժf��r�J6nܨ����ə3g8s�)))j���&N�H\\��7!!bccY�r%y�5v�X.\���y�7�С͚5�R�JF���}�����J�v���k׎'N��~�g��B<}�Y�uKN��]�B!�z7n����888���ODD~~~���O@@��W��uTT�����;v�b�
"""8r��g� 88X='00���8�5k��͛9~�8!!!�hт'N�g=o��>>>��ڲa�ƍG�Ν�4i!!!ddd��u;v�&M���6M�G!��e*fY֝;�����3--��[)Dɒ�2!��)����W��C����_�R�J4oޜ9s�p��A�ۡ]�DHH��7DEE��Q?��#>>>8;;ciiI���Y�`{��)P}={���gӦML�:bcc������䯿�*�:ϟ?������z����B��U��!�2��֭[�_��[&D��0�B��7nмys��W^y��7o�]���������$22�իW3f�<==�R����ڵk���-'>>�P�6i҄&M�0z�h222`ݺu,Y���>��X�{�.�јd�4m!����?�dժU;v�P�^=F�I�>}��6f�-[�%&&�ʕ+ӽ{w�O���~\�X��baj��n�:fΜ���3k֬1�I���-q8�xD&˄B��PA�P�'''����ٳ'mڴ�����ܹ�ӧO�j�*�2e��KQ�<�y��A��;v�HZZ{���{�`eeŨQ�X�n���8�P��Ѹf�4m!����ݻ�5�۷o�i���̟?���l�����s„	ܿ���t�o�NNN���@�cu���ח��d�׳��1�S<m�6L!�B�������h�t��vvvE*���777���ظq#�F�"))	___5���]�v�q�tN�8�g�a۷o7z��ի���VQ�S����I�6M�G!D�ٰa�oߦiӦ�ر�#G���o����+L�N-'''v���c�3f�pP�X�y���_�>ǎ㣏>*�~KN!��2!�B����x�+&&���,bbbX�h�hՖ����۶m#55�F������Ke�.]�Gq�Ν;Gvv6w����/���Ņ�'�y�����Q£�*����%K���'##�p���{�=�z���_|��D�.m�6�B<-
3��=z���{GGG�V����7QQQ|��wj>sbvΚ5GGG*W���KJJR�4Vg^����U�����)�6r�B!�4j�(<ȵk��oɵ
�
[����/f���z�Z�l�����>|�������J�*xyy��תU��w�����v�K�.�1�M�6��Ӧ�����N��پ}{��ˆ����@ll,P��F!�������sbv6h�@����-�����:󢝜*������)�6��L!�Fo�Ъ^�:�ׯ��7ߤnݺXZZR�n]�J@@��a����̟?�ƍcee���
4`���|��j>���������KKKlmmquu%  @�̙3qpp��Ғ��5}ڴi�\�WWW��`aa������L�4�M�6Q�V�b��W�^T�Z���p�~���cccC�=�;!�x徥=��P�x�y���]m���={�w�^�ϟO���IOOgժU����d���L�*Ӎ�����W{
J�p����,B!D�jԨ��Y��5kV�yM}�1����fr�I]���̘1�3f䙯gϞ�����6m�ЦM�|�*�:�U����'~~~ܸq��J���h&L�`Z!D�{��g�~�:���4m��d>{{{�\�Btt4�[�VӋ�S���͍��88��
�5+@~�
P���u�Nc;6���ԩS���D�߿ooS�p��HV�	!�B��Q�F��s���agggpk�B��Ѿ}{�.]Jbb"���|��g�����dbv4V��X��hWE������q��e������B&˄B!J���5, 44���

e���M#��x���[ԩS������K�		`ܸqj�Q�F���ȍ73fmڴa̘1ܼy�옝�F�`���t�ԉ�m����
����N����ӯ_�<��N�}��t�ؑ7�|��5k��ocuk'ڴ17uINQ�d�B!D	�h4L�<��K��t�R�L�b�_!�V��,�:u�~�zz��I��թT�M�4��O?�O�>j����Y�X���o��兇�5j��ʊv��1o�<��-q8���eB!�%���OOϲn�B��goo���O��
��0�:��X,LSuX[[3{�lfϞ�o���[�p
!+˄B!�B���)�&��L!�B!�c��ťD�-�[>�m�iӦ1b�BCCY�|����L�	!�B!�"_�q8��)�-�,B!ʹaÆ1lذ�n�BQ`���%q8��@&˄B�rL�%��U�֭˺	B!�(g$��B}#� IDAT!�B!��OV�	!��؛o�Y�M�D��@B!�(V2Y&�B�s2� ʫ
*�u�y���B�'�L�	!�B!�(V3S�$��eB!�B!�B�?YY&�B�bu��-�,Y‰'�����ӓ�S��L/	�ϟ��_Twqq **��9�S�r�AWHH����i�Fb�	!;r]B�EQ��L�,B!D��;w.'O�T�}�v�����w�%,,챙�2G^}8u�+W�$88EQ<x0��δhѢZ*��I�L!DIڼys��E��2!�B���V�^�F�!+++���V"�&S}HKKc޼yxxx`gg���;s��e�֭X[[�f3�B!�%�Y&�B\\\���J;	��₅�VVVy���[�~=�n�bȐ!j�СC�u��ׯ/Ö	!�B���L!��JNNfݺu<x�;w���3�еkWƏ�����Ow­U�V��`��srrX�n���'!!�J�*ѠA���π�ڐ�����?��#���<��{�f�ر�ěn=E�A�=˖-���C�ʕ�޽;ӧOWWq�V���ٲe�Z��nݺj��{�l�ˆ#�^��Y�B������ƾ4�����ٙ��~�v�ڕV��~M3�5...��#G���ݻwcaaz�LNN���'!!�u��Ѳe�"���J;~����d�B!����~�m._���%&&�y�fN�8���?U�V5��+W�q�F����LΜ9Ù3gHIIQ�Pddd0q�D���Լ			����ʕ+�|�_&L������}�vrrr�.�>�۷���T��ڵklj'ؿ?,�~!DyU�ؖiii�>}��ӧ�r�J^}��Rha�hڴ)M�4��~��ѣt���d��Ǐ���@���Km���IP��
S!�yڸq#�/_��"""�����ޞ��xԼ�<�����M��ر�+V��#G�={6����9������ѬY36o�����			�E��8q����<�)
'''v���c�3f�R��V�;@�&MڨM��BaZ~�-���_~��������FNN_�u)���h�P�������w���b���z��O�����jд���_<�d�L!�x
ic��Uf,];1�����/�L�J�h޼9s����f�C�"-((������o<<<���R'�~��G|||pvv��Ғ���`����cv�3k�,�\���J,))��p��y���]n�����#�O�⌙Y�*T�@�ڵy�w8{�l���z��E�j�8v��]��޽ˑ#G�R�
���z)��tHP��
S!�y�q�͛7�K�W�y��eO�>�?����H"##Y�z5cƌ��ӓ*U����]������r������Ғ��l233�T������t5_n
4P�okk<��R�}�{�.�јd�4m!�(/n߾����9z�(iii4hЀ�#G�_��B*�ؖ�[�uct�u���b���s�_}�aaa���ѵkW���)H����y���			a׮]���[���%++�>}���/)[���֭c�̙8;;�f͚�46������8KPQ2YV�����o�u3���swwg���e݌��}A�N��gϞ�iӆÇ�s�NN�>ͪU�dʔ)��"���Y΃�<^�F
�޽˭[�ppp08������Mwr�B�
e�m���iӌ�O!�T)))�;�?��CM;w��ɣ��m����|�r���oF/�'����Ɍ3F��
�~ %%%߲��Bhh(�G�6x��ޢ���Q貵|}}INNV'�
�37s��7�T�L�=%V�XQ�MB�r��˫��P����r�
��Ѵn�ZM�����ήH������憛�qqq8p�
6��뫾Q�����ի�ڵˬ��ׯ�ݻw���=z��q�
6|l�P�N��>u���;��P�;]!�dAAA��������'�ФIΜ9�ܹs�u�^^ݸ�s�̡A�\�z5.��vh6����B���?~|�����Ăx��g�����ߟC���8�6m�ƍ���|��'8;;s���ϟ�o��?<Z1ݼysN�>ͯ����ߓ'Or��5�4iBӦM]�V����WW���tqq!33�={��x�b���MN���M���iҤ	qqq̛7O��:y��B�sAc��d��M&˞}��)�&!D���EU^�������1M�6%..�E�бcG���߿?7n�`�����ӇF�q��u@EW�.]��ۛY�fѨQ#�ݻG`` �6m��Ņ5k��VW)�µk�ptt�G�DEE�v�Z,--y�ר]�6w���|��7���k�m^|�E�z�����իW�<B�83�,wzTT�A�L��-[2w�\5���n\H{{{5.�سg���Na�;w�C�ѳgO����6l���z10>��9sx饗�G����6mZ�e������|���zc�
�]UfN�Ç׻=�jժ<x� ._����+z�c�9���:u�T<h0Y��8KPQ2Y&�B�<�5��r��5u7H-GGG��–�����ŋY�x��1ݭ�G���Ç���a���z��T�����V�Zܽ{www���صk�СCDFF��_��_��o߾�����C���	#66V�\���X�h�B��~������E��Kw�YJJ
Ǐgٲe̙3����|'xL�/��vS�V�S�w�ޝe˖q��A������%))�`ccC�^��.�7�U����75�q��� d��)Z�oB�������^��(6y�*�^�:�ׯg�ڵ>|�;w�P�N�u�Ƹq��7��pww�bŊ�����H^x�:v�ȨQ��|666�����7�p��!nݺE�j�hٲ%'NԻ}r�̙|��W$&&���<
��_�c�~��.]�Djj*6664k�:u��X��W�^|�����3r�H�6���cccC�=��B�sbf�h,>cQ�B�R�Z5�v�JÆ
qww����`�LQ�M�k�1���!w_*V�c{a�oeeE�~�d�޽<��{�����o��7�e���*���,����7�T�L�=�$��B��i�ҡF�̚5�Y�f���S��X_����eƌ̘1#�|={�4z����%�
bРA�֕W{���F�U����'~~~ܸqCݨ�ƍDGG3a�� �B�${��t��O���W_U�O�>m���q!��uQ�v>�-�)))��¬`��^���˜<yR/��v�p^�鿻�;AAA�ܹ����s�N����ۂ�̭$�JPQ2Y���fBa���L<�F���ݻ	

R'.������3��S!�t=z��ҥK,Z���?��ƍ��o��13u5.�)999����jrm,1��-���=$!!��v��x��X�j>>>|��G���˜?���{na�����H�V���/\�@˖-�_�~��έ��=s+���T�L�	!�B<!���Y�`ӦMcĈ��˗/�3�B<��
�?���+W��d���q!u�ڄ�R�Jz��]]]ٱc_|�_|��ފ��>|8��z;o���K��1�0��5p�@N�8�g�}`4��e�*h|Oc�w�T�*
��&]!��������P�����8�h4L�<��K��t�R�L���
!�x�EEE�����ښu�����F͚5�X�"���|��G�~\,m\HOOO��찴����V]���Rh�̙888`ii�g�1x/���]�v�믿�E��1///<<<�Q�VVV�k׎y��=VVV�[�jժ���=z���;�s�]���ԩS�{��Q�vm�t�Rle�rwwg���4n�+++���hР�G���?4y�6n�o�Iݺu����nݺ:������Ջ�U�npLb�
-YY&{���貰���Ɔ�����k�1r�H*W�\ʭ+QQQ�ر���(nܸAvv6u�ԡE�xxx}�*m�����?�!22���4j׮�7�|C�f����ҥKe���e�>��SN�:ep���\�+�4�o���_!w���xzz�u3���ծ]�����%$$��3��5�e^�cmm��ٳ�={v��&f�j��.����eiiɾ}���Wв�Â�4v~A�t�%�(YY&�X999$%%��ŋ:t(iiieݬB�s�cƌa��s��%������$11�~���c���o���Oq�1c?��< ;;�����g�}�L�TҼ�����>m���!��lu��	�m�FRR999�����J�W^y��[(�T�F���#((HM��B��,O��+L����w�QQQ|��ǜ>}�իWꛔ�t��m<<<�~�:�>�,cƌ��Օ�KKK�_��޽{Y�v-�f���lڴ	KK�2iﯿ�
�ڵk�ҥ���j|��q�Oy�sa�S�/o�+�B���ӧ۶m3�V�Zzq��(�*�#�e�U�bE�y�^{�5jժ���';v�xb&�f͚���iݺ5k֬1�߾~��L�2�=z0x�`�?NPP#G�,��feeЭ[7*T�Pf�vB!���0k�,ٻw/���;<�쳴mۖ�c�R�nݲn�x���$��#�e��7X�jaaaܾ}��5kҶm[�L�BÆ

�)�+�*�3gΰv�Z"##INN��Ύ>}�0u�T��o޼9�n�28���C���ؿ?/^$99��իӢEƏO�֭
ιr�
�|�
ǎ#!!�*U����H���=z��@���_~����0j׮ͪU��L���̬Y��;w.����e�.]b������ܹs�:u�о}{�L�B�z��Ӎ�Ƥ�\�2�Z�bʔ)�x�����q5_*>>�+V���?������3ӧO�[�nfǪ��#G�0i�$._�L۶m��믁�=r�Y����\ҏG~�-O�<s�o��ZA�a���~<̽��z=��
��_��B!
���Bb4�%�/a�L�	=���cǎՋ���_ʾ}�X�j����*3�2�;v0{�l���մ�ׯ�v�Z���	.�Y\\`�a:%%��C�r��Y��{��q��a���X�n]�vU�i�DNIIQ�2339{�,gϞe���l߾]/�ha�M����ӓ�5k�ۿ�ҨQ#�I�C�1u�T���մ?���;v��?�f�ڷoo����h<==y��!�h��9r�o����1 �=ʄ	��DŽ	�ooJ�￯>���րy�s<N�GI?�����%���(�3cϣ'ՠA�ʺ	B��A����X��B!D9#�eBu��=�L�BJJ
cƌa���<��s��űu�V�n�����ٿ�ޒgc+�V�^�N�,Z�HM�~�:���dgg���Ʉ	x��8u��>qqq�]�//�|ۛ��������d�…��@��֬Y�ٳgiԨ.䥗^��‚��8>��N�:ŪU��>���'���0d�Ə���YYY�>}���������-��7�,�����
������w�y���t�w��̙3�W�W�\a�ҥ���O���f߾}���0(�ߧs�Ό;��M���ٳ�v�+W�����%�1IIIL�>]m�{g��/^dѢEE�R;?W�\a�޽��۫��}����z<
�(��s��
�0�s�gZƞGO�����n���S�N�i@�
*�(J��A!����0���o��Ν;L�<ooo����\�2���
>>>�=���d�,�ԩS|����7No{�͛7����믿�����?OŊiժ_~�%��[�4h��ӨQ#\\\�:u*��''NdȐ!z��ܹ�e˖��h�R�
VVV�hтe˖p��9�sbcc�G�
NNNT�X�*U�кukV�\	�O?�T�q�y�&���
j�ƍ���ҦMV�^M�F��T��5b��մiӆ���i�&��ꫬ^��F���5�[�V'N�<iv�������i۶-�W��aÆT�T��M���/�X���2u�T������Qw�4�yPX���Q���1�1ƹ�u�)����H�d0`�ĢB!D���2�:t���Hn���ߟ��p�A��>}:���t�ԉ��{O�c��n������E!66��/ҨQ#5�ȑ#&�y����n�����ʕ+�3�#F�ꫯbgg@�F��hθi�4'>��ѣG�0a���L�0���H>l��2�ޗ_~@�5s8p�d�,--�4iR��^�ꫯ���<(����(��ט�c]�]k�z=3�<z�H�2!i'���G^��%i�֭%V�L�	U||<mڴ�3ߕ+WL��?���ɉ/���`�īW�ФI�B�/�$UNN< >>�M�6���;v�0����\�p�ӧOs��i5�Y�[!&O�̬Y�8u��N�M��k׎nݺѵkW*U���7g�lllHJJ"%%��ի|�����M�L;�999�i'�rrr�j�օ�l[I~����4��σ�z���||�SRc�+�kMQ�g�=�g�L<�$���y=B������d�Pt���|����޽�jժ�n�:jԨa�'55(ڊ*-lmmiٲ%-[����իW��g��v�Z5��ݻY�d	ׯ_/P��z��\�R
𝐐��wttd�ƍ����y����ę3g�t�-Z�(����z�8J�&�lllHKK3z�r����ھjې[^���`�}��x���kJI��VA�5E��=�A�%F�(O<x�'�|BHH7n��ΎaÆ1o�<uSOOO���[6nܨ��t���6�A��}�;nXA��=/&&�3f���?cmm͠A�X�t)ժUS�&&&2g�BCCIII���]iVNN, 88�+W�`eeE�f�x��;vl1���O^��O2�,*kkk<x@ttt�W;������S�B|}}M�Ⲷ�&%%���T�WT�2n�8V�^Mdd���nРAz�����?O�Z�hذ!ݺu3ZVϞ=�ٳ'7o���&**���(~��w�]���̺u��>v�Z�jř3g/�d��΀�֭���T�V���$�����������׶���|�PE�`���ٱ��}��x���c(ܵ����񐞞N�.]�Mq���\N�8��}����`ժU�������Ν;���ȵkט<y2�]���m�CW�.]�s���K�5k֐����/�w��۷�����9�7oV_t͞=�%K���gddIdd$III&�^�$�>N!JJIl�#�eB����ٳg9y�$�;w.�y>dڴi������E����#..�.��h���222���W��.����֭[�srr������၇�dܸqzr�[߾}�'((�1c��}m���y��ޛGGGbcc����S�N�DGG��J���3QQQ�9s��;���1y���999����@�v�Y�)�� �ǣ4���Zc�L�X�lQQQ�l�???�5kƅ�0a?������;��5k�a��w��ȑ#9p��F�"))�m۶Q�V-�/`t�Pk�hݺ5k֬1Y��_|�����y.\�…����ɲ�K�r��e6lHPP-Z� 22�hE�9?��]�t!##�M�61y�dV�X!�e�7`�<==˺B�rj���%Q&˄�s�Μ={�����:�ڽ{7���;w���_M_�h�Ν�W�^L�2%�:ڴiC\\!!!�e.\�w��888�,ܔ�Џ���5`����}HOOW'f:u�č7���6㱶���͛ӡC�=ʿ��o���+�+���믱���{�ީS'bccY�v-:tЛ�����믿�}��F�-I={�$**
???:t�7ɧ(
�|��smmm�w�111��
�h��}#�(J�&x���\�鿹c\��֘{=B<>��pU�^KKK*V���ܰaC��Ů]���兯�/:t 22�iӦ�9��[Ƿ�~�?��O�uh�X�B}����…�{��z\��}�ڵ�f!�:ub��ռ���ze���p��}|}}9{�,`ҤIL�4ɬ1�q3h� �]&�(1���%6Yf���\>|8իW��_e��ќ>}�����7�.���̜9S=租~bӦM4nܘ�K���zذ!� IDATaXYY�m�6�.]��۷IKK#""�w�yx3������~�:_}��/`ԨQ�q{{{�ч�۷o����ŋ�9s�:y�n���ׯS�N��ѣ������ͅ���tW��3n.�V�Z���ѻwo6m�������&==�.��_ӿ���o�L��78l�0�U�Fdd$�&M">>���L���4iǏ�����n�%iȐ!<�쳄��3u�T������">>�ɓ'�'�����9s�����Ç\�v��hV{�y��b��۷���l233M��8?�*L���*��ܿK!����ŋ������/S�B*T���~}����>>>��_�"22��M���
RG�������Y��c�â:ڇ�A`-ذD �XP�#FA%��$�.���y,�n��h"�#�(h0��"H���QD
�����s��Ev�ܟ����3�ά[fg�mccho��l0���u��YNj/�P�B�۷�����ԩS�y��9^�B�?df�P���;|��3�'NеkW�2_~�%����m///.]�D�:u^[�ɲR�J|��|��������Z�4h�ȑ#�^C��Y��Ջ.]����δi�������O��رcٱc7o���ٳ�Q�Fq��^��5�x�w���Ժml������3j�(n޼��ٳ�>�
�����k/W�K�.e�ر8p�h�oee�ҥK����{ݼT�H������`Ϟ=�ٳG�2e���>��/���ܺu�^�zi�7w�\�M�ft<�< ��ɓ';v�z,뮬�W�?Le��7��s���S�]
!^�۹������i�$S갲�ʶe�g�)�w�V��ݛ?���[����MHHӦMc���̛7��g"!ċ���?�^���>LPP.\�ɓ'ԨQ�V�ZѥKɅ���zfVVV�.]�&M����a�g�ׁ��3���//;���5�Q�&M�ٳ�K�W�Y&��hт;vУGlmm����hѢ4k֌u��ѯ_?����ѣ7n�>�X�bXZZR�J>��s��������ʊw�}��;�f��͛�u�޽Y�x1���XYYammMӦMY�z5&LP����s�����_5jU�V�`��(P��+2l�0v�ء3�al�)ؽ{7s����͍�e�baa�F��ޣO�>l߾]g�LѺuk�o���Lٲe)P�e˖�O>a���m�6�m��6lȎ;��O�تU���Oǎ�vSԩS�͛7ӦM�/���%���g������ۤXLy,Z�777
.L�(W�\����a
c��m�S��֘��R�j�T��:;u�С����餤�h��:u*�Ν�Q�F\�p�/��"�uܼy���t���֑�ͬ)%2�;ͬdɒ<��ǏΔ)Sx���+"�����9 !!�q��1i�$������%99��g����ҥK�9��~��}����{�.������;�<��s��i�/_ΤI��8q"^^^j��`����W���C�Ug[(;��"��p��mZ�l�{ァ3K�ׁ�${�ҥ�m�lْ�a	�F��/X�`NNN�:u���`<���nѢ�26�iӦ
M�6U���j�
��@&==�?���:\]]���nݺ�����7߰x�bZ�lɡC��n��ܹs�>}:*T`������p��iȟ��U�J�*\�~�+Vп4
[�l�o߾/^���B�333���Ԅ�Yo�J͖�0a����-[�Q�FѴiS�/�?��C`` �������z��lg���3���'%%q��
�/_NXXeʔ!00��m�U�Y��<}��=zЮ];5=�ҥK9x� �7o6�������O}_�z�D��2!D��U�U�T��͛z���/B!Df���ԨQ�S�Nмys�����$%%���#<<<(Z�(�ׯ��Ғu��Q�hQ
�8�)S���R�Q��q��	6l���%���,^��…��7��ĉiР�o��>��ʊƍ��$h����=�bŊ��hԁ��W�-����.�{َ?Npp0666�]��N�:accC����c�ر�9���TV�X��ᾕ4
5j�`�ҥ888p��}�oߞ�a�\�f��ݻ����O�>ܻw�5k��KL2X&��u����?������&	7o�d�…���@��B�O���9q��ǏG��`nn���
�1�W���~�}��6����///u�R�Jxyyq��F�
�w�}G�ʕ��� ))I���+baa��F�
��[��p��F�E�2e�h4���S}��lĈx{{���D��)X� �k���ӓu�֙�xB�Abbb�9s&�Z���Ņ����o�>��l			xyyѹsg\\\�ԩ+V� 99Y-�����P]@ٲe��ҫW/F�E����������7����N�&M�ر#K�,�ɓ'Z�RRR�t�Z�b�ʕ@F�ĩS�ҬY3Z�lɬY�����9?))�9s�ЬY3Z�j�̙3���щ�ظ�͸�5kF�֭�?>O�>5��szMC}�<���xxx�Kލ�/�m���[�����KZ�n���+ӧO7��K^��?�0k�,ڴiC�&M�ݻ7�v��{=SbIKKc�ʕt�����<x���qqqlڴ�F�i��+W����lڴ���8�풗$��"�M�6������a2��O�<�ƍ�CtB!^%K�d�ҥ���q��M����>}�111���_���Z�8����{��7��R����CK:�/V�+V�Й}���!C2dH�u񶊏�gذaܹsG=v��%�N��S699��#G������LJ��ϳ|�r��
�Qv�mڴ��2E�a�СZǞ<y�СC�~��z,::������QwW,Z����@���ի���g���j�����ܹsssf͚�u�…����Dv��ř3gذaŊ39�#F��$&&�e�����
�Li��]�T����������-��q���1d����o��={�h
����z^����4Hk`��ի̜9���T:uꤧՍ�e������={ƹs�8w����j���{��������N}�������o�>�u�7��"3˄��V�Z�޽���km�P�\9:v���͛1bD~�)��5���ȅ��թS���P���quu���"����q��������!44�U�V��a�"##�]�6����<y����ׯOxx8AAA�v�������޹��ח�ׯcoo����퍝�W�^e�ڵ:�?��7r��	u��P�@�l�BHHÇtgNAƒ�e˖���vvvܽ{�
6�P\+V$00���u_�
	9o�^�P_䄍�
�VnGS��I[��X�~=��7�˗gݺu�s;��_^ֿn�:bbbptt$00�cǎ��'�y�
1&e@��ˋ��P�;���'�<!!!ԬYS�>�R�e��2!D�(W�ӧOg�޽\�p�˗/�w�}gҲ!�o�:u�������/_���`�{�=���8z�h>E(��)eYW��]��+_�M�Fݺu�����ɉ�ӧ�\w���̛7
(@�ʕ�\�Y��eU�@ c�1��X�^=u���IHf���T�V
+++5OaRRS�N�bŊh4���z���+���ԭ[W�-�y0Ĕ�&O�L�
�h4꬟��W�ߔ6~�5M���
���˙_N�2/����ԩS�U����ַ�s^���q&M�D�
(\�0ӦM#""�_�U�z�Ģ�\���#  ��ҽ{w"""�Ք�o*V��S��^A)�2�2L!�B�JS6��p�-Z�к�dɒl߾��ŋӢE���.B�^nݺ��C��
3n߾
@�Ν�^��ի��U�lY�ܹCTT�+W�[&==���x����c�2:%g�B���ݻ:ש^���w楐U�TQ��n��&M�h�V�$f^�jJ\��W� f<4���wMS)�K�,�B��-��q+ׯ[���y�&�E�J�g~.�1��?�9s�FXX?��C��o߾,XP-@ѢEu��SʼL2�L!�B��lmm����Yj����ƍ�_�>�����Ӳe�|�R��r�����|fff:�5�WP�5�}Vʠʼn'��p�-[����C��dHvB�F���r�e�y6U�rr~vqYZZ��V?RvJ�Q��z̔�rҖy�kf�v�x�~S�˜Xڵk��ݻ�9s&���#11�+VСC�l٢���r,7�;9%3˄B!�+�N�:jn��_2q�D������`��ٔ/_>#B����s��5�����}����S��֖[�n�}�vlmm��룏>b׮]���ѡC5'�B��/==wwwu٦��7o��̙3Z�W�9sF�+��={Vk	��ӧx��cy׋�qny�����Z��M�/'m���|��\�~�S�Ni%�ח3/��w�믿�z�*���9>��X�+F�Ν�ܹ3���<x�u�ֱd�5a�R�������ǔ*UJ�|er��/��,B!���Z�j�իW�ڵ+͚5�p��DDD���-eB��ڶm����9�<)))�;w�����Uf�N�6�K�.���ʃ���pvvV��f�(K�\\\prr��xxx�o�>���x��.\`��񄅅ѴiS�wﮞ��̛7��gϒ���ٳg��7o���̝;Wm�ӧO3o�<>���<�˘6�)}}aHRR�ϟg���\�r{{{��lJ|9i˼x��۷2��ԩS���p���Ν�S6/�Wv}]�x1���$&&�h�"����D��K�.]pvv�_~!!!�jժ���h�|S��*ˮ3S��\47�̲�T�5�B!�g(W�"oԮ]�+VP�V-�V���ݻ�/B�7S�~�سg7o����#۲9r��g�ҿ��
,Ȅ	��%K�$66��]�bkk��ہ�)G�ŵk��D���lْ���JkIؠA�8t��o�VwTT�PA�Xn����iGGGz�ꕧq��9e�/�g}eV�X1.\�5�bJ|9i˼x���������Χ�1H�u�(/�<x0�����ٳt��Q�O?���y��2h� �͛ǂX�`�V��y�6m�ѣG9��N>Be�]^:?���e��������0��ggg��!�V�S�K�.e���z�!^?Y�eV�P!V�Z����9v�O�<�r����ߟ�3gbee�������LJիWs��a�ݻG�"Eprrb�ȑT�ZU-;q�D���{���INNV�������K@@�ƍ���ѤI�u릵TQ�hQ֬YÏ?�ȑ#Gx���J��u��|��jr�ܴd�f͚EXX666�oߞaÆi�G^�eL甡�����
[[[\\\0`���Ǘ��̋�meeŪU����������0m�4����yJ�*Ś5kX�|9���$&&R�jU<<<hݺ��󌉥k׮XXX���ׁ��͛7gРAj�?��o�����`�U_pp0����,ӗ�,�y��k��LJ�C�r��5 c�e��B���٩;&M�0�d�B�ܕ��HJJ��.tB�W���~~~���W���E�N����#(((ׯ��RfYe7�(rF��ղr�J���ٺu+���@Ǝ��1#F�`ذaz��_�~��Yo���I�-a�4M!��:w��	!�^�m�o777���]�vX[[s��-.\@�
�9B!Dn4h;w���Ϗɓ'��燭���rϗE��R�L3!�Ɠ^o���Sw�B���o߾����w��:��/���yT�dI�\OB��W�B��={6�}� ((�e˖�ۏe2X&�B������|YB�t�����^+�'O�B�
�޽�7n����;#��Æ
�lٲ��"�4lؐѣG�x�bƌ���e��2!�B�uz��A�=�;!�[f�֭��k��ܜ�}��I޳ב���=Җ��W�߻���Nll,>>>�;w��������]�EDDp��!�\�“'O(R��i�F�zϞ=��=Fcʾ��7oR�R%���ٳ��g�P�n]ڷo���!�B!��A��kgٲeDFF��>|���/99��˗�u���%""���\]]3f������-Z�����r/^��ߟo�����t&N�H�J��Q�F>D*�ٓfB��$9ʄ�#�e���0s�LIMMe̘1�UέZ����0
.L�n�hܸ1�K�&..�?�����N�8���cǎ5���1�������D���h׮eʔ�M�6,[��%K��nfB�W��0B��Q&��',z��e|�HMM�V�Z���ann���ܥK�8v����|��W��۫�/^777�ի�ĉ9v��ڵ��!#6�֭[����C��:�k�.�n�J�޽�1:!��Or�	!��۞�l��ͯ�J	!��m���yvm,&y��7n����$$$`ooO�Νqss�*��͛9y�$�=�dɒ4nܘ=zP�pa��28�x�b֭[��˗�����Ņ����r�z�2��
�=|�???N�:Ebb"�˗�K�.|��Ze

f=�ܞ={6�/�bŊ̚5ȘM�e�BCC����dɒ4oޜnݺi}@8t��;w�(ˬx��t�ԉ
6p������D~��'~��74
�����Ջ%J�ݘ���2�Ϯ]��]�6666j�ҥKS�V-v��E�N�(R����.�B!�[�n}���',F{��1S�N��v��m�/_NZZ-Z� !!�3fp���\LL;w��ܹs|���:K�fϞ͓'OHJJb������3|�p�b|��)3g���Q�ݸqC({�֭#>>�R�J���3�̙õk��2���'00�+W�0m�4u�������9�:���ذa/^Թ����2�<ȹs�X�h��df�Ę��'$$���D�ׯ�s_���9w�'N��m۶�>~!��e����\�r��@��M�����!!��d�Lm۶m<|��*U�0n�8J�,���/ 00PL	

�Ν;�-[�q��Q�re�]�����o�ֻ$��Ύ1c�P�T)	��ɓ�`��YdY�ر���G��˗/�l�2bcc_��/_����Z���}�v�]�F�j���O�P�w��eժU�;w�ÇӺuk���.]:�:�y���޸q��3gR�F
�_�βe˸w�AAA�8cN��P?�>}�ʕ+��P�J���	!ċ133�{��ܜbŊQ�zu�w��رc_�\������ڒ�����QQQZ��s�O?���ɓsm� �o^Ձ���w��E���9|�0W�^%>>��E����@۶m6l��ݰ_Dv}񪷫Еy%�B䥼H��${y�gϞZ�ew�ԩS<[[[
,����	`ٲe�����1,,,�^�:�~�)'O�ԉc�С���beeEǎ�����R�>|�Z���##G�4�ZYu��Qk�bhh(�}��*U��ܜw�}W�t 88X-�����E����A}G�A�ڵ�������#F�{�cN�W�7n��Y)ǔ2B!r_ZZ�=��ɓL�4�>�������$����frr27n̓z�ΣG���گ���DƌC�ڵ��o8u����/���<z���p�ΝK�j՘4iϞ=���/�,�7o��|BB���32�L�޽{���{ٖS�@V�^]�x͚5���Y���տ��ViiiF�x��]����"�����0�s��۷տK�*�����>����P�F�/�j�Һ��o�%�YcN�W�Ǐ��I�S�!�xqYTy�����?~����μy���)Bӭ]�������ڵk_�ݯ_7����oߞ�G�biiI����۷/NNN�,Y����S�N������Y�x1��;w�|)	�eF����Ϗ�}��wB�7�����:,�ex~r��-�ȩ��2ϸz�z@��Uv�LOOW���Ҭ���-�/�5k��������'�<',,L-�U�Ǡ�_�@��3&�iw�\};�*�r�_�B�gii�;�C�n�(U�-[�����,;�<���;�K�fŊ�ر���.\����&L��ѣT�R�͛7ӠA��mllhӦ
mڴa�رt�ܙ���3e��,Y�OQ!�yC�a
�E� IDAT�)��3�Fҧlٲ\�tI�r�L�2y]%1��P_��6�o���ӧ��=�̔�����ߦM�ԲJ��_��`7o�$((@�#��իW�nGFFd�טsڿ�(;r����ܧ˼k�B�.nݺ���éP��[[[��맾geff�������G��)S+++�T�������7n�ovqf���,]�777J�*����K���ݝ#G��ޕ+W9r$U�VE��P�D	6lȜ9s.�3���֭�O�>)RD�ɩ��P�����׸t��
���+++�������ʕ+�>}���)���3p�@lmm����Z�j|��w�_�x�U�Vamm���uʲjذ�:�lٲe\�~]���f�����L�2��Ջ���,��vv����Ӧ����o�ѪU+
*Dɒ%�ܹ����<��B��d�LM��f�bbbHJJ��LJ�={2n�8�\�F�X�j�/_&55�˗/�z�j �V^quu2�^�rE����~�)[�X1<Hbb"w��Qc̉���إ�ƍj��
6гgO�̙���^�:nnn$&&2s�Lv��ɃHMM%&&��۷3k�,i֬5j�Щo�ʕ\�r���"##���hҤI�Ę�U>hf��$�U��f�ˋ��B������[�.?�������DGG���OÆ
ٵk���,T����u��ѤI~��bbbx��ׯ_g�…������S�t%�{I\\M�6���?'88���XRSSy���v�U�V�رC��~���
��?r��5���y��1�N�b���4h�@'��햚�ʆ
��%����a�RSS�nS�ܹ'''|}}�{�.Ϟ=��ݻ�[��
p�<��)��k�.���X�~=��Ѥ��p��UƏς�ƶf����9rd��0ԯ_�!C���������2���ǐ!C�x�")))��������؍�"�s��I���8|�0���<z��۷Ӽys5׫”�x��]q��a&L�@�v�puueȐ!lذA����)}���3}��sS񤥥ѩS'���՜�/���3���/����>��s>���<Ib/��2a�O>��%Jp��eF�̀سgݻwW�u��[[[�ݻ�����ӧӧO�޽{���f��E���cooOtt4ӦMS뎎��)��_�����S�h����coo��˗�2e
�{�f�����h4h�V�#F���BBB�֭cԨQ��ӇѣG�~�z�>}��op3�*U�0m�4�����ٳ����R�J�/cN�Wd����2NNN������r�T!r[ll,ݻw'..�	&p���>}Jhh(Æ
#99��}����JOO�o޼y���q�#F� 55��#Gr��
���9v�U�V����,\�0G񦥥�/������C��8u��j����$$$���HXX...���3w�\�s&L�@\\�~�)W�\!99���>���#7o�����vسg���ԬYS�BҸqc���b�޽9j��Q�%�m�Xtt4�{���ӧt�҅��ϓ������ҥ������S�g��L��)�t��}����ӧO�ի�.]"))I݉:ky�2K��?6�
{��`pPj�ԩ4i҄��0�p��;w&))����s��}�}�ϋ�ϐ!C�裏8~�8���9r�*U������l���x�����՛�(!!�q��1i�$u�:99��g����ҥK�lgu
�e�GGG5m���dz=��ɓDEEQ�re�;ț����,_��I�&1q�D���8s�L~��֐�2���<O�%J��_���J�"E����r��|��縹���)�ܹsi߾=666���cccC��;w.���y���={6-[��hѢ(P�J�*�	�3�8p �ڵ���KKK�ׯoԮ��櫯���ݝ2e�`nn���5�5b�ܹ:3�,--�0a�'O�aÆ-Zsss�+���3�'Of�ĉXYY�o���4m�KKK�/N���3g����Ƙ�<x0e˖���\��ִiS
,�����N�…�YB�:����w�S�Neɒ%T�Z��ҤI~��'>��3?~����u��˜9s&�&M�Jx�r�J����ի?���*U��Ғ�͛�;@�_�^�u�.�,P�eʔ�G�����xzz��P+����iӦ*T�FC�ƍ���ٳZ�(��-�jժXZZR�P!Z�h�~^ضm[�������ZǕ��y��ˋ'O�вeK�U�VVVԪU���@Z�l�ÇY�|y�\˔~���y��1:t`ӦMT�^+++�ׯϮ]��S����%����F�Q�z��|���kԨ��C�hܸ1�GGG~��WZ�l��ǏY�r�Q�e������F`` M�6�p��|��
�'Nh�5��/^}G��{|ڴi�8q��e�2k�,����ɓ'	

��Ã'O�0e�Ν;��#~se�nݺ�u��l���_�ڵk�f@DDy^�ӧO�1cݻw���;;;�v����ӵ���c�.[˼�|||:t(׮] ((�	&���6���g̘1�-[6Gn_Giii���333~���^��?�L`` ^^^j޺{�����={�o�B��&L��ҥK��lٲ%?�9����Fd��Y�f�		!**Jon���HjժE�F��:z��1�����͛|���ܹSkS��
r��)�=���Dvr�Y���mڴa�ҥ9N�������fffZK`�r�
...�3777���2��>|���-���ܼy�
*��ݺu���{+++���(Y����Û��������~��ݻwӾ}{���ݻ�������#���z-C����aaa8p@o��m۶���2�W�@���HMMջI�!)))XZZR�@RRR��J�����Q�o�ƍ�M�2�������s��9j׮�uN||<��֘��k-�5����1�7�;333��/��6D�A�2 ��S�E��Ɔ
6��c3���aŊ4jԈ~���&��O�>�}��$&&�s�NJ�.�sNll,:t��‚ݻw�*�u�b�
֮]ˎ;��btt4�;w��ÃѣG�s��e7L�!��!3��i���ٓ}�������Ҹs�+V�t�)�={ƍ7���u��K�.�.]Z+Ɏ;(S�L�KE��U�$����՛�_��.���ùy�&U�Ve�ƍ:�+�ԕY:�Ⱥ�355��B�>}ؿ?���:��(�_���ۙ1c�ڵ���V�nfS�N 44����S�B*T���	$99Y����q�F���hѢ��@@Ŋ��HJJ�ژ&�(�)y?�R��K=����i?]�x0��P~�…�7�Ɏ����j�>�@�q%���eN�h�V�ZU�X�"Eݝۍ}����̙3iժ...��ߟ}�����������;w��ŅN�:�b�
�>�|N�kl߾ȘŪo�2��5����k����o���ݝ&M�бcG�,Y��A�R_JJ
�-��͍V�Z��,?~�ԩSi֬-[�d֬YZ9+�󓒒�3g͚5�U�V̜9����x����ի�=�f͚Ѻuk�ϟ�3�)'m��k��B�
���Njj��'Y�ر���ڵk��שS�hժ���(--��+WҵkW\\\pssc��:3��=�r�����شi�5�z.�+Wggg6m�$��^��@�����ƾ}�X�z�N��bŊ��M�v�Z���@�ʕ�%��2f��ϟO�N���$�_|��&_bBS���/Tn���P�hQ�mۦ3
P?L�FzsssJ�(���+���T�X����������f�ԩ:����A������D���k׮e�ڵT�R�}����=����������Ξ[�v-�F��Q�R��/^\����l�`굌�'�C�,���rpp�ԩSDFF��⒣���@�U���~}3B�yOM��^���Q����=���6�;w��.]��`f����ȑ#�vۍ����LJ��ϳ|��lgN*K+�6mj�L�"E:t�ֱ'O�0t�P���f&�����ҊE���^�z5���l޼Y�_�YennάY���_�p�:����Ȯ]�8s�6l��el\#F������u�l�BZZӦMLk��]S�nݺ�.�~���)��M�kɒ%��ũ�Q˗/W��C�$�s��q��9���渃�i�{�����7}���+����۷OV��1�Y&�HC�aРAT�\�F���9eʔ�M�6,Z���E����X5?���-GGGz��͚5kX�f
}��1:�B�
��&�=қ�?󌮬.^��g�}���6l0�:���"�L�4	�|R���ӻwo�_�N�5�1c���l۶�`�)�����֭[���0d��v��Ǐ�yLƴ[dd$���[�Wxx�:�*+}K/st�̔��MVʬ*��L���ch�m۶Fﴶy�f�K>��sZy�%J�0���r�r˜��=~~~ܹs;;;|||

eժUz?�oذ���Hj׮���?'O�$  ����NPP���2s��`oooT����\�~{{{5Fooo���z���<��ϟg�ƍ�8qB�ٴ`�
(��-[		a���;vL��Ǐ�l�2BCC����Ύ�w�;	�WŊ	$$$�!C���9m�^�P_T�R�z����_�,M?u��oߦf͚�)qU�\������Ku���ˋ��P�;���'@��m�CBB�Y��ι�1���;2X&�H��渻��`�֯_ϦM�����>|8666�^��2e
7ndѢE:�W^6www&O���ɓ�СC��"��R�jeM��<�����ݛ���̙C�Ν
��R�
���)�$%%�+;"�\���/��_2d�:w�5�-�R4�����ۛ?��S�ݐy�8S�mݺu@���ؔ�OJy�2k !!A�ڦ�jU��P.��'Oj���k��O���y�2SfEe5l�0
(�ʕ+s�<<s�>>>����_��2�M�ϔ�NJ��c��/��,E˺�M�qeaڴiԭ[KKK����>}��u��������
P�refϞ
��]���KY"o��}1֫WO��v��!�s<==�V�VVVjN���$�N�JŊ�h4�&��===quu��Ғ�u�3�2����ɓ�P��F�I�y�)m��kb(ѿ��_�Ufj\����� M�����G@@>�{��DDD�lS�E;���@ƠZV��lJ�wd�L!��%q�ܹs��+033�Q`�ĉ�={Vݹ*;-[����[����cff���rN)KJ2J(9���6	�R��T�T	333.\��s��e"ƶ[jj�:#Bٹ�%���f�)K\�
��������'��?��X.�����4/^�U���2���t�d�P�7�Q�'��U�2v�Xi߾�s����ӡC���5j�:�*�o��F�Xjj*.�YBd�/���yc��"�ܺu�
hwrr�){��m:w�5�lj��l���(�e���ufL���߀���ݻwu�S�zu���K�2�*T�`Y�֯_@k��)qe�_YΙ�ߗ)m��kҦM�/ΡC�ԁ�����bmm���W����ǣ�hc�ҥ������L΋v����/�W�)eDޑ�2!�BF�M���			�}����������Ç1b��‚y�����S�n]|}}��s�Q��h4�Y���S���?������C��ݻ7��3)�RRR�~�:s��e����7N�_�y<q�D���RSS�p��LQ�$����=z��~���III��꬈�;�n�����ݻ8;;Lخpqq�A�ܽ{W�M;pBƆ
Ǐ'11�k׮�矫����
$%%EM=j�(�-��Ç�ڵ+���$''I׮]9r��~���2��F����-�����������̥K��ٳ��g�1�ԦM���o\]]<x0����þ}����iӦDEEѢE�b�]�vѫW/.]�Drr2gϞ�cǎ?~���{OgF���ȭ65����=e�]�ew�û�fW&��-u�[�.����.вeK<<<�Hg�݀��<�9ݍ��B;��RWN��..KKK���j��]�+++:u�Drr2�w�`���$''��wД�2�*h׮�w�f�̙ԫW���DV�XA�L��E�Y9��?�cƴ�0��	!�B`oo���?�
��4nܘB�
ѪU+V�ZErr2˖-S��'gϞ���Z�n��?�V�V�+V`ff���)W�E��u��\�p5oJV��kiiI�*U�>}:���6L+1�2���?P�\9,,,�]�6�ׯgƌj���þ��j֬�ŋi׮���XZZR�N��݋��=���gr�)9]ƌ��~Qf�e�3}�t
,�իWi޼9�
�jժ,]��e˖���sd�=���T�ľ������hضm�j�B��P�V-�mۆF����O�2��L��)�T�X1)Q�{��~��h4j֬��͛���o
�hee�Ν;?~<iii�]���m�R�ti,--)S�~�!�֭#==��>��={�d�yO@@���f͚h4�իǞ={(W�۶m�I�o�/r�MMe��_������h�zPw�ݾ}��[DD��%���>��X��o֎�[bzz:����M;;; cirf�m%�ܤl��8}�4��z,/�z�66V׮]133c۶m��Jͭ��+F�Ν���חA���j���*/�YٌE�\嘡
[D��0�R����;!�xm�ڵ+�T��ҡCΜ9�…ٿ?���.\����I�&������2dժUc���������@�ʕ�ׯ�&M2j7a�F���-M�4aРA:3^>��S4
K�.��ŋh4��}Ə���;ժUc��\�R�BR�X1BCCY�p!۶m�ƍ<{��J�*ѥK�L�B�2eLj�G�D�R�ԙt�ӷo_&M�Ķm�x��%J���ٙ���̙Cpp0���4hЀ3f���&��j͚5�5���`���(W��z_�N�8u������ܿ�2e�жm[<==�&_6��k��O��<�?��믿fǎܿ�jժ1c������
�hee�ҥK3f���8p�˗/OѢE�^�:m۶eȐ!Z_�
�ѣիWg�С�9s�
*Э[7&O��w���"7��T�<�E�h۶-׮]c���|��WԨQ��/2�|��-[�d�ڵL�6�ɓ'S�Z5=zĆ
X�~=��ά\���!==�۷o��8]\\prr�ԩSxxx0v�X\\\(X� �/_��$,,��M�j��jѢk׮e޼y|��W8::��ؼy�\o��s��q��9u�n楉y�1m�S��BQ�B5j��x��e���tv�͍��t�������':t�Z�j���_��L��򢝫W�Ntt4�n��S�&g^�+�Y���,�ך��C�U?�GDD�$�Ba<ggg
��	���0i��x��YV~~~zo!^�2sR�f�]�7fff����KS��6DI�/W�ӧO0`7o�4x�rޓ'O����[�`��x{{��ڵSg���ڪ5���2j�(�?z�lْ���JkVd\\�
R�feV�B֮]��2�Xsz\�]�^=��u����^�Z]^�q��9����P<x�)S�P�D	=zļy�h׮�V�܈+00P+�Bfnnn�첬��E;+��7N�___�-[ƌ3�<�o3��맾�d��"df�[&�3B!�B�_��P�P�B�Z���˗s��1�<yB�ʕ�߿?3g���;emm����W�����ܻw�"E�����ȑ#�]z!#��Ott�Vn<|}}	�ܸq333�4iB�n���T,Z�(k֬���ȑ#<x�R�JѺuk>��Su�$7-Y��Y�f���
�۷gذaZ�q��9e�/-Z��T�R<x�uS�܎�k׮XXX���ׁ�e�͛7W�'/��?��o�%88Xg�,88kkk�Y�"��̲7\֙eB!r��,{��M3=��2��ަ�Sg��"**�N�:aggGPPP�_�U��,<�fY�r%���lݺ{{{ c�͏?��#F0lذ|��� 3���eB�wv��E׮]�;!�����FBB�����
�n�b�…4h� �#qe�� IDAT"o4��;w���n���燭�-�������2X���T��:u��0��֩S'�K3�Ba�:��/��`�,X�u_ɒ%
n�!��P�B̞=��>��IJe�tvyC��p�Z��U�V��B!�xK��K�[&O�L�
ؽ{77n� 99�w�y�
Fٲe�;D!�LÆ
=z4�/`̘1899�sTo,B!�B��177�o߾y���u$���>��?��B!�B!��
,B!�B!���2!�B!�B!�?�Y&�B�����?������
�6��ׯ�����0��h2X&�B��ڸq���;!��B�
�B�����d�S!�B!�B��Of�	!�⭶l�2Y�)��3}�����/��x�z���!!����~M,B!�[�m�2+��[o{�.??��:g�"o������,�B!�B!���2!�B!�B!�?Y�)�B!^ȟ�I���_���I�&�CI�����쬷�F��bŊ���ww��^�)1GDD�[}����ܜ�ŋS�~}F�AժU����"##8p eʔa�Ν������F�.]���bժU899�p�9�H�r��	!�B�������ѣ/�K@N�>}�4˗/��&==�^�z���@���_z�B�W���[III\�|�Y�famm�|�������x��!�&<<����S�B�\���ё�5kr��E�?������'O�$**�ʕ+�����M�r�,�B!�&;z��+W�ӧO�1cݻw���;;;�v�����y���K�R�y��VDD�����C��_��e��cJ����mζm�hР���^�:���֭[�nͶܯ��
@׮]�,}^V�{_�2!�B�pvv6�DG�Z֬Yý{��ݻ�z�O�>ܻw�5k��cdB��^��V&N��ŋ�9�׃��9���L�2ȘՕW>��C�)BHH111z����r��1
,��-��-�ޗ�d�B!�+��aŊ������*U����Y���8V�ZšC�x���K��U�V>kkk���tӦM,Y���gϢ�hhӦ
�Ǐ�P�B@��U�V�o�>�������J�*t�҅�?�X�Z�����P�^�j'N����+W�ۢ��������شi�5�lٲj�r�����̦M�0`E�5�#��"&&�e˖q��q�>}J�*U8p S�N�_7�f���ܿ�ҥK��G1l�0���ïϓ�������}9�Wq��=�-[FHH)))|��GL�8WWW�Xr�zi�v��_c�|����=G���ӧ�j�JmscT�X�Ǐ�m�p��
,H���3f�F뱄���`���ߏ��͚5cܸq�.]�B�
���N@@۷og��:u�ر���:t蠾��=�iN�'3���/s�=[�r��	!�B��bcc4h��/�W�^e�̙���ҩS'�<y�СC�~��Z.::������p��Z�1b���%11�-[����ƴi�X�|9���j�gϞq��9Ν;G||<���{n�K�,!..N�{n>n}���KBB���33WWW���ٷo��lG�ꊏ�gذaܹsG=v��%��6��Ɍ9���H�XTT>>>�?��˗g��ݐ��tbcc��o�U���>z���?��e��)'���g\\C���V��ٳ���x��y�&�J�ҹ��ӓ'NW������0y�d�r.d���@�ծ]�8s�6l�X�b@�R̀���������T�hv����PdmSS�'��=[�r�,�B!�xE�[����	�رc|��'�����|}}�~�:���������7vvv\�z��k��\�bŊ!C8|��z����ˋ��P�;���'?��3��+���,�+W&$$�/��2����CBB�Y���u�cJ!ī��Ϗ;w�`gg����Z�J���
����v����s��I�_�>����݂�-
���y|L���Wd�AUhB%v�%*vڢ�Pbj�%�����ھT�R��V�bM�����R{�"�D��V�DG���i&3IfFb���c2�{����kΜs�����գu���ر[[[hQ���Z�����Ɋ+���d����߿?��L'�ל8W�Z����\�d	�ϟ7��Ǐs��i�N�
@�
�߬_���f�iEDD0w�\"##	

�L�2ܸq�իW��x{{S�V-���~��7���9�իW�Z�*ժU3�=�jSS����=[�}�O:˄B!��a)�c�y!""��?�///\\\?~<��������0�?��5kbooO�Z�t�/v��mP��1c������Q��wRR�n��[�0֯_���M`` ���F?DӫW/��=�y�Ɯ={�w�OF�˗��#�x�̹���խ[�	&��s�NBBB�T����T�P�ɓ'�}�v�c����N�:,X���oN�{��`ܸqT�^{{{���
FR���ߧ��nݺ|��'�֙��ӻwoN�:�����A�O>��
*����LHH0�7v�X6l���=5k�ԍ��ܱ��B���vT����M-�O��=[�}�O�a
!�B�S7n��r�����N��U��^z�:u������[��vKzz�.mĈL�2���(�����o�߿?AAA899���?��2����{�.��uY�i�<B���ʕ+���2��u��z�*F����M�W;�,))�!C�p��ڴic�s��^�j֬��������L���kN��i����|�ckkK����e�xxx�����\�hQ@�>���}j׮���[o��_|��ݻIJJ��͍��$v�څ��+�[����%s�Zz�̋{��r�t�	!�Ba�"�y��B��0��C���>�zZ�j���?{��e˖-?~���z�j�
fҺ'Y�*SJ��LMM5�4ǭ����Dڴ�mW!��,��*����Μ'��������'N�O�>L�>wwwZ�haq����<~��`;��?��t��J��9qj�'�4u�q�z�����yڷo��ի�駟�֭?��������zX���d�77�Ǝ˘���r��}2
S!�"�z�嗁�GD�)S�cǎ�k��F�nnn�t�RV�\I�>}HJJbΜ9����z�E�����m�vicO^Ӧ[hZ��xzzp��q�������ܶm�tk�e|���XC�*U�ݻ7J)BBB�[�vdґ#G��8q�A��^/MeN��v�g||��?���8��G���W_5�۩S'lllزe����W���b�}2/��r��}2�LX�իW����vB���ˋ���[;!��Q�F�]��ٳgB�bŘ;w.�ׯ���S�K���Y�|9!!!L�:�jժq��)�O�@�&M̮�C�\�~��c�Ҷm[*V���~í���իxyye[���;w��e���t�ܙ�7o2c����Xݕ+W�֭[\�r��vJ�%�;��^˖-�p�ӧOg�ԩT�R�ӧO�m�hт�˗3~�xƌCŊ�w��W�fժU����h�"�������Ν;�~�:K�,a����ۺukΞ=�g�}�ԩS�U�gΜ��>3���륩̉���f�…����駟R�fMΞ=˴i�,��iL�6Mw�O�8AHH�޴J-///�ի�{��s�[�.*T��gN{d��dfyqϖ{_��2aU&=z^�� ((���0k�!�x���׏�;wG�v��e|"[�>}ؽ{7W�^�=%K���� �}��!$$�3f|@˸^��]�N����`۶mY�ټys6m��W_}�W_}`�1�����5jľ}����7X�H;*’"B�g�gϞ����\�|��}�f��o߾�ݻ���8z�ꥷ��ɉ�#G�ޛs�pvv��<x06l�s�κQM��۽{w]���ҵOq���륩̉�W�^�ڵ��g�2h� ]z�֭u/�R���
��j��֭���;w&&&�Y�f��k��Y1�>il�ܾg˽/��4L�/(��%�|�


�����ʴS3��%J�l�2Z�jE�"E����jժ̜9��m���)R�e˖ѵkWJ�*���-�J��G�,_�\��9:u�ĤI��R�
888���M߾}�2e�.��ѣ)[�,���9��3r�H)Z�(4lؐ�'Z|���nݺ5...8p������J˖-�n!D�������̒%K�X�b���Q�R%>��S@
)WWWBCC	

���[[[���t�x2��1纥U�n]�v�JZZ_|�E�:88�p�B���C�R�����iӦF��z�4��q.Y����@���qpp�e˖��P>ks�̡q�����Q�T)�{�=-Z��g͛7�D�ܻw��ŋ�3�GVL�Of��l���>�T�+�	������ٳ'�k(�;�HY&D����Y���?�-b�ҥl޼��e�O�>ֱcG̀��xQ�H����t_0f~��n޼I���)S�[�n�����M��"�2�'�b�B�L����a&�Y�L!
�>}���?Ƙ1c�'��m��WӦM�h4�;�V�Z���ʕ+W�9s&u�Աr�B�r��]�Y&�Y�L�'�F���o�s�|�n9ggg&O������ݻ7[�ne�ܹ899Y9:!��ڶm�ƍ��	����/:���.�,��L��&��BQ����2t�PfϞ
��aò]pY���3///~��'.]�Djj*/��2
4`���*U��!
��Ƚ/�Hg�B!�S�`�WPP�<�E��P�B/�߱�KI�X�E���k�4L!�B!�B!�?�,B�[�nY;���B!�B<[�Y&�S���1�������fϞMJJ��C�Hll,���T�V
���(Y�$�7fڴiܾ}��~�~�-U�V}�њ� �(�B!��ٓ5˄����ܻw���h���ٰa{�����ڡ���?�/�0x�BBB��̚5���P:w� <�� �(�xv���y�葵�B<g6l��B�ԳgO6o�l�0�ϩ
6�Y�2�L�\���{���r��-6n��+��BLL!!!��d�~�-�g���ɉɓ'���y��1�����+�.III���C�Bh��קK�.�C��ҥ��׷vVѥK��
!�T^^gdd�y��ޞ�_~�Ν;S�D	Z�h�ʕ+��Ϭ�I���K֮]K@@�޶%J��o��o��ŋ����[C!D�����Z;!�x��_���!!��dd�(P�\� A�������z��ɩS����jM����bcc�ҥ/��x{{3v�X�߿oQ��oo޼i�-%%�/����M�R�D	ݚ`��{��5Z���	���GGG�+���/S�L�޽{F�1��Ο?@�֭�=�q���b�ܦ��Y��ʕ+���R�paڷoo�=+�m7�ܙ���ҳgO��򒗼�eɫgϞ־�Y���]^�׋��2�L�]�v$%%��nݺExx8�6m�￧m۶f����~Ŋ���������.^��̙3ٱc�p��f�q��Q�T������L���9r�^zBB۷o租~b�֭�k�N����ü��$''��RSS9r�G�a���DEE���/�[�n^^^\�x�+Vd��������f��߿����mSc���	!^������Y;!�s�E�(��ر��f�"o�����'%����������k%$$�R�J)5r�Hu��y����
*��-�nܸ�c�!!!
P�
ӥ_�xQ9::*@�K�.���T��~���5q�D����d�����ܹ�6lؠ<==��,Y��gܸq
PիWWJ�Ѩ���4h���ﯷO�F���Ο?�RSS�F�Q{��QժUS�2d�S�ۗ_~�;���zK-\�P�<yR����ؾٵK�m����ĉ*11Q]�vͤ}�ڞ��N+((He�^Qp�߷�Yy��7��o���B�6S�,pX�a�a���ܾ}�q��1g�|||prr��ߟo����Ç���Ȃ�-'**�I�&O����E����C�u��7�|C��屷��I�&�Y��U�V-7�0P[[[^z�%�t����;v,��G;�a�ʕ4j�ggg�_�>+W� ..No��~�
�Y�f��ヽ�=���4o�\�.Ė-[��݆��L�B����_:t(իW�hѢ4oޜq�Ʊ{�n�Q\�0a5j��͍�e�Z\<ݹB!�B!2��2Q �����?�1�}���ر#�2�ѣ�?�u��L�>]o����
�СC
����C)ťK�̎])�o���ɓ'��/_��R��u���ꫯ���tOOOڶmKXX��n[���QJq��u]���fccìY����c���ԨQ�߿Ͼ}��>}:o��&�+Wf���&�Cf͚5�h?c���	!����ٳYn[�~=�F�bԨQ�@�ª������{�2����ȑ#iժ
6����^�ZoY�{��_r�<ZZ�)2ǗW�fW��{�Y�Lڅ�=<<�ͧ]�ޘA�q��e|||X�f
���z���wjժev|*Ӻ]���$%%q��),X@xx8
6$::�`�2x���ɓ'���!::�cǎ-wܸq��׏��H"##�'ho��&�۷�]�v888��?m�U�^��?���?��{��CLLd���\�p�֭[���o��O�����	!ċ棏>b߾}���l;z�(���gݺu(��֭�*U�v��V�T!,��h;v,��K���#..���P&M�D��ͭ�s(����\�Ӓ{o�$#�D��qqzK�}��w�_��"E��e����
�h�����jy��_�B�(V�
6$,,�O>����$Ǝ��oݺux{{���M@@�}�;w��Ν;F��۷/�6m�����|�r:w�L�jոx�n�Ӷ[FŊ�U�VL�0��~��[�n1`�RRR�8q�I�d���b�>Y��s'�ϻ}��M��'N$00ʔ)C�N��0a��Hg!�xbcc-�?~<��T�R���;v� ::��[�ҷo_�߿���_N�8��Q�����<�u?
���_�Y&
�S�ݻ�R*˗�5�N�>���ñ��a���T�V-�:�/���?��
�{��\�x�*U�0q�D�.]ʖ-[8w�\�e�����o\�r���P���O�J��p�#F�08&s�����]���1)R���"""�l��eU���b4o^�;!��zV�H�eٲeܾ}��ݻ��z���۷Y�l�#B<������(^�8˗/�}��/^[[[ʔ)������IKKc�…�Z��{o�%�0E����Ñ#G8t�mڴ1y����w�F���O?%   ˼���;v���x5j�ax����iӦO�<x�^��7o�~NOO�P!�~m///���G�~���h߾={���層�jժšC�����|�m^��Ǐ�T�)
*Dzz:�F�	�u����<�s'�֐��Β%Kرc7o����ooo:t�@ǎ��j4�.]��\�dIڴiÀt���k������ɬ]��z��Q�T)]�ҥK����ڵk�ݻ7E�yG-�Od�N����m۶лwo�kZFݺuC)e�DJrr2K�,a���$$$P�dI�x�

�7�ATs���~��Ύ�]�Lbb"3g�d������ӴiSƌ����v��2c�v�܉���7��?�dɒO�ڵk�3gqqq8::��[o1b����uyM�o�ZfV�����)�<��w��ņ
8s�)))�,Y��͛3t�P�f���V			,X��}�����x�
ƍgP��{�7Y&
���~x�d�cf������жm[��ѣG�ʚ�-Z�t�R�m������P�|y���>�2�Z�u�z��m�Μ9��3�-_�<666hذ�A�%�ַo_�L�b�4�̴Ihܸ�^���
���f.�٘��m���F����=M�B�̟?����W����#4
'N���>�=U 55���`V�X��7x��7o�$44�#F�x���_�h4F�%
6D��d�!�xL�&j�Vf�%j�…y�����ܿY(�L IDAT����5k�����cnݺExx8@���3k�,֯_�F�!))���m۶��c�RRRHNN��d����Ϝ9�m۶���BRR۷o���zˤX�����!%%���D���{����7r*�9�i�97�o���/���ܿ_�nk׮eƌ&�hN[%''ӿ�n�Jbb"������ό?ޠ\���o�Y&
��C�R�hQ<��o�����ٳ���ӻwo���t��n�ʂ�Y�&+W��u�deȐ!8::�l�2ƍǟ��F�a��ݺa�ڎ$S<~���/2m�4ƌ��~�����<����?IKK��ɓ���{z7҄���=z��K�.�ܹ����ǏOPP�o���֯_?6lHBB���:|�$%%���Ɲ;wؾ};�:ub�̙���1e��c�~��i�&?~Ljj����x4h���p��F���0yK����(��ʦM��7o����߿_���u�t�V�^ͩS��Q����DGG�~�zj׮MLL[�n��ϸ���Z��A�4m!��S���?�-[֬�W�\�ŋ)[�,���DFF�t�Rʔ)������
����g͚5:t���`f̘���-��=dРAF�"�ܹs���$44�2e�p��
V�^�Tq�+W�M�6q��A����/	c�}��2����$�8M9�Yսf�Ǝ��9t��/�&��ժU��~�:����X����H�,Yb�jr���V�2�f~�я?�����`�p�B�����Y���h�ҥ����h�
���7�|�k��z�.Y�$˼'NT+VT�ڸq�n���DU�j�,�+[���|��S��RJݽ{W�j�*�crssS6l0ؿy��Y���v���������h}�,3s�]v1*�TPP�


����2�����פW^jӦ��UÆ
S�W�V׮]3��{�����W]�~]/��?�P���j��e�����ˠ��K�����m���	�by��?����,�k�sm�|�2��ؠA���4�Y��|}}Utt�^zdd��U�;w68��Ǐ����]��s�t����X��w�ڥWWTT��U���O��ӧui���S����^�z�4K�9���}�X��e�zγ�;==]�<yR���S�f�R]�tQ������/�}3�7��������午���Y3�?�L�ed�(0ڶm˱c��߿?������S�hQZ�lɎ;2d�^��ַ�N���ٷomڴ�X�b888P�J�N�ʞ={prr2�,GGGʗ/O���駟���o��8�+VP�vmqss㭷��~��O?�=arѢE�}��܈���O>�Z�j8;;cgg���}�G��\�rz���n�d*�/����?�L�޽�\�2...*T777�ׯϔ)S8w�����/[����~�…cgg�+��br����q��Apww��������?0p�,�3��=M�B�1GGG������/�֭���<�z�*�Ų���t�h��g��ݻF�EѦi�!���zMԮ��q�̔R��~�:��t
@�:u�q�A9�+W��q
,ooo���	����_�}�ڵ��eI\�wss��侑S��ȩLSϹ1�����}��֭��ŋ��eŜ�Ҟ��5kꕡ=Wɽ7��E�R�R%��R��[TG�&MhҤ�Iy͹���xӻwo��-Z������91��2jݺ5�[�6{������O?�fJ�խ[�-[����9�.��&6e���֪U+���ٻw/[�l���,\��իW3l�0:w��|m��i�ڥ
�=PF���rBa�����zM�Y�&׮]�СCT�P�hY'O��_�~T�^��K�bkk�e��u9::M7v=5��N�#��.S��..{{{��Ʈߖ�7r*�9�i�97f֬Y�>}OOO�5k���7իW�k׮f�hN[i�f�'�y���w�Y&�B�����@@@�N�b׮]�X��9s��>$xxxp���mۆ����u�(Q�[�n���H�%�%&&��!���rMlӦ
۷o',,��m�R�xq�2���Y�hJ)�y�]GY�2e�|�2ǎ�~����ǎ�����8��9=z�W_}U��q=�}�Y2�<yH��!bڑe�d�ic�X���V���\�x�#G��-�o�W��L�B!�ȧ:t耟�7nD��P�bE*U���}*���9s�iii$$$��_���[t���Z;���Ft����i�	!�5�zMlРu���Ν;��ۗ;v���̣G�8y�$#F� **�F��-)ҼysBBB�����������o�sL�6���x?~�ѣGu�G2��ȋ�̹o����i�zγ�;22���TΜ9Ä	t��8�s�J������9��Ǐ9y�$ӦM3(W���,B!�ȧ���CHH3f�0x�}ݺuu?��ۗ�{�G�^���9991r�H�{www�޽K�N����`۶m4jԈ}���W.��mx^|HBs�zM�'O�2d.\`ܸqe�hт�S��Ms�ӧ�w���ի�'3jyyy���ŋ<��Z�jt��-O�2�a*c���e�97Vw���پ};�&MbҤIe�9sFo�WV�i�^�z�k�.Ξ=�{
*<���)&��MF�	!�B� ��蟕N�:1i�$�T����x{{ӷo_�L������Jhh(AAAxxx`kk���͛7g���z�L�=��e�bkkKjj*��?�...8p� ����J˖-�/s���^�I'�ʕ+>|8իW��Ņ…��o�p�B>��s�@)R�e˖ѵkWJ�*���-�J��G�,_�\�}n�3g�7��ΎR�J��{�h�"�4.s��2vyZ��scu��Ǵj�
ggg�^�:ӧO�ub�[�Τ�i+�,YB``��ae-[�d����ʽ7�QO�B�O!<<��={�@�^k�ٳ'aaaF�!
.��6nѢE,]��͛7S�lY���:v���0`��#��y��7666���d��g��ƈ�G�O'�bed�B!��O�>�.]Z�C|XX�N�B���ޛɚeB!�O!�S�rӳm�����ɓ>|8�{�`�̝֭;�`��B!���{�/�,B!����2t�PfϞ
��a�B!D�{o�$�e"_ڰa��C/�
6ХKk�!�(���f���d�!!��c�۽C<���?�Y&�]�Z;!�B!�B����L�+ң.�B!�Bk��2��DDD0w�\k�!�7��?�vB!�B!�!�,��իWe�(�/lذ{{{k�!�xF6l�@ǎ���9�V�?%��Ky�ֹt��|i����A��z��i���УG�d�L!��e�7of����C!�&�eB!�x����f�0�⹢��vBa�B�@!�B!�B��BF�	��={�ʕ+ݶ~�z����iBB�d�2!�5<�k��eBk��5̤�L+�裏طo���ێ=���Y�nJ)�u�F�J��]��"B�燬Q&��O�(B</��L+۷o���0q�D����S�NL�0�
6���,�B�熬Q&��O�(B<Od�2Q ������g�0�Բe˸}�6ݻwץ��у۷o�l�2+F&�B!�B<���L3���_L�4�7�x�
ЫW/v��a��N��0o�<hР�۷g�…�����d�'c��ɬ]��z��Q�T)]�ҥK����ڵkINN��B!�B!^<�Y&���������IJJ�ѣG�9s�q���MMM%88�+Vp��
=z�͛7	

eĈ���g[�/���F��aÆ�6l�F�aǎ�vlB!�B!�xB:˄0QXX׮]�L�2���ɒ%K�F~i�^��S�NQ�F
��É��f���Ԯ]����n�
���ll����Z��A��4m!�B!�B�Y�_Y�O�9��%s˞={?~<5k��nݺL�0�?�P/�Ν;		�L�2T�P�ɓ'ӱcG�o�Nǎ����ٳ�+W�`[����!�B!�"�Hg�&�r�
u���K�[��AޫW�`����=ۺ�޽@�"E�iӴy�B!�B�{��L�G�iG���H��d~,���M�y2��~�۵e*d8SZ�f�^!�B!�B<�,�D���\�p��Ǐ���ҏ?n���Ã+W��m�6<<<̮�D�ܺu���DJ�(��-11Q�G!�B!��K��D-[�`��������cN�8����
�h�x��ٙ3gHKK#!!����???���uy�#ĴS7*W��;�3#m�6�B!�B!r��,�D={����������7ۼ}��e�޽���ѫW/�mNNN�9R���ݝ�w�ҩS'<<<ضm�5b߾}�����@�&Mr�B!�B�##�D����+svvfɒ%P�X1���T��~�)�����������������Ѽys�/_�7*l��є-[[[[RSShݺ5...8p� �����&�G��j�666��B!�B #˄0K��ř4i�^�͛7(Y��^����F�bԨQٖ٪U+Z�j��V�pa���X�t)ׯ_�lٲ\�~�cǎ1x�`\\\��pD>ѱcG�lْ�!�B!�B�=Y&���6m���7n$))���t.]�Ĕ)S�S�N��קOJ�.MXX�.-,,����`۲e��CB!�B���2�\���˓rccci۶-7ndƌ̘1Co���;�
��:����<y2Ç�w��lݺ��s���䔫u	!�B!��	Y&��ƌèQ��Z�*NNN*T:u�DXX�n�dn�e�С̞=�ٳg3l�0���uܿ��c�R�B)_�<�Ǐ'%%E�'((V�Z��oxx8666t��Uo���놙RG�N�8A˖-)\�0%K�dȐ!���?zyoݺE���)Y�$�����ٓ���_zz:�&M�r��8::R�H4h�w�}�T�&�B!�����Er����ӳgO�ZM��a-={��M��>%%�&M�}��[o��/��B�B��w��������������իW�Y�&����8q��ŋ���2�@�V�D	��8�%K�p��=|}}�x�^�v����?��'�ß��Ѷ��/r\�O!�B!
�XY&�f��/����~��=z�G�q��I7n̯��Jhh(ŊcŊ$%%��{�F�>}HJJb��帻��u+�t�M�#�ʕ+s��94
�Ǐ����n��ٳ�x�">>>DGG���C���G\\�AY����������…�7o^.��B!�B�?�Y&�fZ�~=k֬�v�����Q�Z5�/_��իuy�x�
F�ɾ}�hܸ1{����?䭷�ʵ:��͛GŊqvvf�ȑܽ{W�}���,^���_�6m�7�|cP���+s��a���ܾ}�!C����ҥK�4�B!�BH�Y&�f:�<*TЭfcc���'N����k��FTTժU3x@Dn�P�F
������麴���
��״iS��fϞ���3;v�࣏>��^#$$�F�c�B!�BQ�Ig�ȗ2v�K^�x���g����ʘ���l�MaI�֣��yM@{{{��ݻw�넆�ҨQ#���W^y�E��tB!�BQ�Y;!2jܸ�n������e4�|��={�˗/S�\��7n'N��^�z>|�O>��/��2�}̭�+V��ɓ�߿���~[�e4���;����_�~>|����3g2j�(���s%&!�B!��odd�B���w� ((�#G���cnݺ�����
o��.��ݻ���/iܸ1�iӦ|����޽[�G;
�ܹs�a�=z0x�`���ϣG����a��y�������o�!99�Z�jQ�V-@�B!�B<olT�8B<C������S7-L�^�� ((���0��eXX������s���}\\\����N�:ܻw��5k�������)_�<�/_�V�Z���q��	�+��/���۷(W��/_6����-��<s�ÇiРG���ףG֬Y��w���Y�`˖-95�B!�BD�2�L�KJ)y�˪����,?�-ʡC�1b�ʕ��Ύ�ŋӱcG���t�XC��?�`޼y�/_x2�r޼y\�v��C���_S�B���x��Yu���ё�{�2d�^z�%�ڵ+�/6�;x�`�.]Jݺuqrr��ɉ5j0v�XV�Xav�B!�BQP��2aUY�,�_KamG�{/�B!��$#˄B!�B!�В�a
aegϞ�r��F��_�^��B�v�,CB!�B!^8�Y&�}��G�۷���X�mG�e����[��ݺu�R�JԮ]�
��ܔ��FRR����$''���̃(Y�$��ճv�B�B�>E!�BXXX���
!��,Š���g4���L�8���@<<<�ԩ&L`Æ
8;;?�0��RRR�9s&�����ѣԩS���D4
< 11�������,��믥�L!��cǎ�aV��d���t������般�e˸}�6ݻwץ��у5kְl�2�SE����İa�X�h��7�w�f��Ѹ����쌛����8;;S�H�)���3������ot�ڕw�y�ڇ�s��U������9S�~}����F��t�B�.]��B!�H:˄0Qzz:K�,aǎܼy{{{����С;v�˫�hX�t);w��Ν;�,Y�6m�0`��;�2�Krr2k׮�^�z�*UJ��t�����v�Zz��M�"E��Qs�,Y�7n0�|ƌ��ÇY�j�����`�jԨ����3�4g���
!Dn�iHB!��盧L͟?��+W��?z�'Np��	���]�Bjj*����:uJ���͛������)T(����/h46lh��aÆ��İc�:wG'r���
|�M�6�G�ԩS��ΠS5�-[��ۑJ)k� �xN�5�
Z�B��E����2!L�i�&�͛����=b���̘1�u���:�V�^ͩS��Q��ƍ��ۛ+W�BLL[�n�cǎ����Nz��A�V�j�6���YVԪU���X�λ�ː!C�3gNNNz�Μ9Å�x�"�/��^��^�уB��fBK�eBl�Y&
��S�K��5�\\\��>aaa\�x��͛H``�^��;wB�2e�P��'O�cǎl߾=�FgϞ�\�r�ʗ/��G�...|��nݚ�r�֬YC�5ty~��GJ�,ɵk�3fIII����ꫯR�V-^{�5�ׯO�&M�ځ&k�	!,���(ˉ�a&�B�x��L�1�)S�ETT�|�
���'((Ho��իW0Z���m=w��0�)�M��G`` ��գgϞ����̙3���`���w�y��˗p��%���8q�qqq�]��O?�[[[�ԩCӦMi֬M�4������a&���LCB!DA#�e�@�<b�O�lժ����ݻ�-[�p��q.\��ի6l�nZdN�;ݿ?���Q��k�M�5T
�r�ʱw�^�L����v���Y�8t�|�.߫��ʫ��J�ti�o�f����߿��;w��W_O�z���ۼ���4l�;�����fBS�J�u��K��vBQ�d�ʸ€��,]���+WҧO����3g�.���۶m#66���m%J� 11�`�6M�G<vvvL�:�]�vq��a*V�HZZ�Z��v�R�J�ܹs����Ν;lڴ�F��a��5kFɒ%�޽;˗/�֭[�舄B�����}������?�g�&%%�ڡ�%����e
�~���up�BdO:˄0Q����c�ƍh4*V�H�J������kѢ�Ǐ�̙3��������_����n�����v�&@�ʕ�r�A�4mQp5k֌cǎ�����OѢE�ڿx��t�Ёy��q��yΟ?��ɓ���2deʔ��חI�&IZZZ�Ba���t�ݻGtt4�1͚5C��X;��ʠA��w�B�G:P[� IDAT˄0Q�>}�1cM�6�A��?��u����ۗ���G�^��_�>�[�fժU8991r�H]^�zS�:u�}��4j����x��iM�4Ƀ#�Z�%���f͚5O]���#F��_~!!!�m۶�믳j�*6lH�R�

",,�;w��B�B��š#Ie�0�RJ�ʭ[�ظq#���
111���X;L�e>��^B!
�,�vJ�ԩS'&M�D�*Uppp���ooo���˔)St�\]]	

%((lmmqss�y��,_�\oT��ѣ)[�,������кuk\\\8p�A��Օ�-[��gF��������;��7�|åK�8}�4�ƍ��?��������L�1��cjZ~�-��RWDD�jժ�����舧�'�������$ΜXs��L�O��ޞ�_~�Ν;�j�*V�\i娄B�,�,�^��C�q��!֭[����'W���1j�(�m�Ftt4�w�f�������kժ[�l!::�_~��…ıcǸ~��.���9v��z����%�V<7�T��G}Į]�HHH`�����d����۷i۶-M�4���̙3<x���T�]���O�v�x�wHJJ�j�֜b%ӻ�+W�0h� ���ptt��Ã�={r��)��-Yo+66�.]���K/�@;vl�2�J����y������K�6mJ�%����dɒ���;�ݻ�hy�ϟ'88)V����L�2%��[s��i�[�9��;�9}i��vm��+W�p�º��%�K!�Š���T�_���_T�F�k�N͜9S�6s�Lվ}{��+F��

RAAAY�<��јSSSխ[��ƍ�+���5~�x+Dh���+?��۱啬�u떪P��T�2e��ٳ�ɓ'�F�Q>TgΜQS�NUE�Q�j֬�z����	k��)u*,,,��MA�ט���+777��rrrR?����>��f|9;;��_�|����5��N�:��F�����jԨ�������֭�el666j۶mz�����F��ʗ/�nݺ�k�f	s�3��;��Ɵ�vm�o����[�n�%� x�'B����2�\���˓׳�����ɓٺu+7o���͛lݺ�ɓ'�������y#SDV����ŋi֬'O�䣏>�Z�j8;;���@�ʕ�0a��X�b�۷�E�Y;l!�{�.���$''3r�HΟ?σ���d�����d0zKY_+��a�}����K�.1x�`����ҥK�����~|||8z�(3g�4)���t���/6n�H��������̘1�#G�P�zu"""�h4���E�
PJ1m�4�}F�Irr2�󤦦��hسgժU����zKhX�n���>s�AeZ'M��i�ϟ�ĉ$&&��_X|l�/!�x&��I'��=r���7O^��F��F����íNjHF�Y��y��e5p�@���T�ҥUPP�:y���0��X}�V����dɒ���^U�PA����U���Y���F�eggg��jΜ9�I�&�x�����V�(QB�m�V�ٳ�hy�ΝS�V�����A-ZTխ[WM�<Y����F����,al����O���Ĩ-Z('''U�X1վ}{�ey�O�V�{�V�K�Vvvv���G}��WYֵ�~��^zI%$$��E��j֬i���{O�)SF��۫2eʨ>}��s���x���3���.]�(@
:�h|���
P�*U2��6���śYHH���Gʎ92��Z������N��?��6f���DZ�֍�Ȕk}�B��رc
�,W���o��f���
P...z�NNN
0z͍��W�d䨖��f�q�۰�>K�!c���t����P�/6�fɱ�{�
��~=�wX:˄U=Ӽ��I:�����?c�ONR�5���(���/u��!��~��G���l4��ӧ�kРA
P'N4)ޔ�u����C��~�!˺.�v�ܙ屛z��|(7�ݹsG�*UJ���t_�vM���+;;;cr��6΂�a��śY�F��n޼it�ɓ'��ի�e���S�˗W�jݺ�z����v�uq߾}&Ǖӵ^{Mmٲ����7��Ǐ�ͨbŊ
P
4P�W�VW�^ͶK�͔�2����)���!c���t����PgΜ1�fɱ�{�
��~=�'�eº��L�W�Yf��gBB��ȑ#���ՃTdd�0`�*T��*Z���q�F��j����ʋ/*GGG���`u��%������߯|||�vrd����4u���a�����d��<�ƍS��^�����P�F������(ՠA(�}��Ο?�RSS�F�Q{��QժUS�2d�S�۳�,�o�U�VM���*""B���?j�޽���[�m۶z�ܾ}[-ZT���/gΜQ>TG�U-[�T���F�Ҟ���(��WJ��7o���С����W>T���C�
P���$-9ά�L)������ꫯ�:����U˖-�&O�lRݙ���-�����M�)V�X�et��U���Gݽ{�`���޽{&Ǖݵ��VTAAA
Pnnn����F˹p�ںu��0a�jٲ�z饗���l�2�c���T}��U���A���f��iϓ��S�O�Y��?��ʱ�{�
��~=�'�eº��L�W�Yf�ߧL�y"�O�ɸoNi�-���`���w�6��r�ԩ
�w.=z�H�ٙ��…+@%&&=fSh;Y[�h�������-Zd�n�g�2��i;,��1�͛����<������a��śYV#o�]�����o��)��T�B�
)�`�YvL�T��O<�h�h�ڵ�o�z=ٴiS������Յty-m7S�+3K볤��1��-)��c3�|�z"�N:˄uIg�ȯ��̼�O���D~���qߜ��[l'N�0���}������~��W��o޼�h]�N�̝\�W���O?�dt��?��U�n]�tK�3�~�Yz��������Qs��U...���E�={��3�)HZ��Y2�K�ԩS���E��ب-[�d�O;�<7F�ev��]OF�ii�=��R���8q�Z�t�ڲe�:w�\�e_�rE�������뭹׾}{]K����2K곴L�,KOO7����|��A�L;_EA���;l��P׮]��x�mذ��� k�Q`�:u
�l�?>�m�
�������f�lmm������ԪU��T��������ĩS�X�`���4lؐ��h�T�b��ŋ9y�$111DGGs��1��7�~��Idd$�����更oߞv�������햹�ܔ�b���1H+\�0��|ft��i|}}�����o4��͍{��LѢE-�S��������t��sf�gv,=ŋg����J8�|*U�dr��z|||8r���M�6&�B����h4|��d���ۛcǎO�F��{wU����.(�@"�Kb���K��.���(�*WBQDKE?���Bn ��KZ��LTLD1	4�l"��91�3�2 ��u�u�9�9��3�������e���?�ג'<�رnnnR�J?Q������2�255Ō30c��/����#G�ܹsbU���T鯪�AMMM#??_����{��B�(���R��EDT�$%�%����0a��� „	гgOu�QodggW�ݏ?����0�ȑ#hѢ�L���\@�&MT�hjj�y��ppp@pp0�.]���lxzzJ�;p�,,,`aa�Q�F�믿FDD���o��>}::[[[q۟��]�vaܸq���Djj����׭&յ�5j�pۜ�������Z���]2Q����p_EEEr�.o�MS^^��ʌ�"U�#G�Āo��6�͛W-1Q�6l������M���F�!�}���HHH�رc�|��
��߿?   @f_RR444`ff�R�{�� �G���ԩSe�oܸQ��ŋ��fff����7d�qpp�٦�uS�*��r@CC���vɿ����2�+�<��M�EDT+Ի��:�]R}�4̊^��#�.���w��mu9��K��?y�D�1Ϟ=�{���תU������BӦMgggq[���+���y��7E����*?����b�@r�z�H̒6�)
���[�Ç�����˗//^�Μ9#̞=[��������W���9rD XYY�<QX�?��C|��ҥK���L!//O8}��Э[7��r�J�c*z��|�R�{����_���a߾}�~�\�Ν+dff
EEEBRR�0u�T��4�OOO�еkW�ԩSBnn����K!11Q:t�@�0aB��[e㪈*��r��;��Å�/_J˗<t�cǎBdd����!%%EX�`��Sy˪hܪ�M�U_����5�H�8YF�'�*�y��;q�R}�x�B����W�������@�x���Wv�LOOO�&y2�;d���_��ou��1()�-��u��	��[e�%�˛��/{��˗B�v����J��...�6;;;(�f�/��"�}��Jǡ��z����.]��ٳg@�C)�=��eu����}}}�	�үm۶I���g+{� hhh�m׻wo�ŋR�9��駟J���_n�+V��"<(�s�k׮�gbb"ܿ�J׭�j�>�rA˽�qqqR�b�_��Sv�ʎM��U��'D
k�Q�eTױ�Yņ
���k֬����-��KXX&M���Ç�ĉ�veS�]�����:9III�޽;:t���+US$�^��̐�����$t��M��RT�n��.�V�ѣG#::���:t�L�;???�ǽ��{<x0"""0i�$<xr�>|�~~~�����ŋ��C�ŕ+W�a�2D�vPqq�����:L%)V� ��)R��-Y��o���ɓ�s�N��~���9��ݫPߤ^#F���kװ~�zDDD 33x��d�<X��*��fΜ�N�:aݺu���F~~>������%K�@OOO�s������z�������'1k�,���aӦM�u������{�a������ѩS'L�6
;v�q���������q��ܻw/_����F��/��mڴ��u�*e�S�:@PP�Ν���H���?h׮�����QQQX�j"##����w�}+V���~�ٳg���T�_DD5MCj�:0Q%.^��͛7�;"����W,x�������Y,�^������ѭ[7<��ڵkaee���h���b׮](..F\\lllG���ѣaee�K�.�.�Ν;�޽;���,]�_|�

��?�7n�ʕ+���##��"/梢"<x������իQXX�}�����ЩS'���`�ܹX�r%Z�n���d�_�^j� --
�����K����]�v�w�}���!99�/�ɓ'1a�����|�*We�+o[]���c�����o###C����ѵkW�������O��ӧO�����ѣ�����[oaѢE>|8LMM���Kܽ{���+���<z����X�j�x�Çaii����=k׮Eǎ����e˖�ȑ#000�͛7ѡC�*�(�%3''���3f��������;u��
###$%%�E����;#��Ƙ1c*�l�����~_�Էx�����	Q��7""�K�4LA`� ԏ�yǖw��[e�����ae_{��𼉉��-便�%x{{�=��ѣbM��/===��Vx��(�J�����S���D���N�<)�GDD����!���BVV�B}���>�!շx�����	Q�ƚeDD$���e�PR�|�̙B����Y�f���S�Nɴ-o"��_�/\� >\h޼����+�����W_}%ȴ��zzz����0y��r�K�޽[������M�
�
~��Aq�eРAR�<{�LX�t�`ii)������Bǎ�E�	�?��u+=.U(;!U�c�lZZ�0k�,���H����v�*���(tނ����_6l�`dd$����5:w�,���				��ƍ����ط���0m�4��͛J��������
&4n�X����|�M���޿ɓ'�y�����ܹa�ĉ
�-��>��X��%����'D�Z�0��?���;wVwT�)��ID$O}KC�o�Q����z-��X���;w��ɓ���������N�dQ���aÆ��Qw(DDDDDDDu'ˈ�M�6�;""""""�:��eD
Pqq1���ЩS'�Y�������������N�dQ���C`���hӦ
<<<�Q���2���ݻ�w�y7n����樈�������O[�Q�s��6m�7�xcƌ����#>>ZZZ������pvv������ ""�Z��2���ݻ077�߼y3����m�6|��gj������SwDT����S�!��8YF�����S�N�]�t�����ɓ'�M�6j�����pu�@DDDDDTc8YF����`ĈRۼ���w�^,[�?��"��`�ĉ����V�󎈪"88NNN���T��2�(55;v��֤IlذS�N��������UNNN�58�e��T�������
8YF����_��͕�,�)S�`ǎ���p��%�#OR.^��͛7�;"�g>��s���W�a)LS�Q�{�.���Bf���6oތ���ڵ��#����WFDJ	ǃ��R������{�.�abb����իWq����f�����͛�3\���t8"RW(+NR� >>^͑@�R��Z��ݾ}]�tQ�������ի��Q�8YF�ܼy/^�����\��;w��Z�BϞ=1q�D����ΎeDDD�V�-���4�x��Ulݺ� �4i:w��j����^'�,#j`$�0Ϟ='��ϟ��ӧc�ʕj�������\��Ο?_�~_�x�+V`���022�;˗/Gxx8�t~""z=q����ٹs'BCC���۷ׯ_WSDD
Gu��D�LO"����BI҂����cL�<Y�6e��߿AAApwwWctDDTWq����i֬�̶�ݻc���j���ᨎT����ID5�ѣGضm������333L�6
#F���ӧO#<<���(((@�֭���www������S�N!##:::�����ѣ1f��\��S���N�<�իWK���~����1h� ����L(*O��i��Wt,999

E�=жm[q{�v�`oo���PL�:���*����^O�,#"�����999�#Q
�j*QM���$�����S���"++Kܖ��ooo�z�
#G��{��� �-33��������ի[�nŞ={�6/_�Dbb"���ggg��)���W�^ņ
`kk�v��!33���h۶-�-[&���ģ�'O�D~~>d������X�:u
�ƍSi�DD��TwD�~VVV���T-���~��Wy�I�?FPP�##z}�޽YYY���ġC�p��|�������r�ۿ?��ɨ��(\�t	;w�DFF��:زe���q��xzz8�t��$���^���X�j��������b�\�yyy���AӦM�[�xJ������Wt,QQQ��]���/�&iCDDTW����ЬY3\�~}��Uw8D*Q4�)''���8s��<y�֭[c���={6�4i"���2��7"!!zzz4h�ϟ/���J*��k,^��;wƎ;ʭ$o{e�.�o�'���?����/�,YSSS%��^^^�q����[�n��_ŝ;w���� 77���HMM���#Ə����K�O�v��ѣ����O>�����2e
�{�r��J<�{��m@�d�aff&Ն���4N���T̄�u�A�EӜrss��'� 55Ul���������"00P�$����ϟ


��O?���X�E�:R�6n܈���I���<LO"���(�p���,,X��nݒ�'������j�*��� &&۷o�̙3���F�)ݮ4ejl�� IDAT,Λ7�/_Fbb"�����g�U�^�x�=��ӧ w�_�M҆���4�a��T�k׮�;"�(��g�������������F@@�������]�vɜ�C�8t����0s�L�ٳg�UI%�077GTT�X��:�]^�LO"R��g��ϳ��*��a�ܺu�۷���V�\���0�vC�����
oooX[[���۶mÈ#��O?)ݮ�T%E��\{MM�_y$�T�?DD�z�d���q��
�z�JݡP=S^��ׄ�iN���B||<~��g��d����VVV��с���X��̙32���)����Ub����~�J���`������Ə���x=zT��]\\���[c㖇�ID��7�P��S111J&��ϟ/�R���H��iӦ5j�g����";;7n�:F�v�����KKK���b�֭�S�x9�U�V �.M�M҆���4N���ɲ��<��3OT(�攞���^ڻ�+u��,,,į%������m��χ��bbb�i�&L�4	���(((P8~�䔲TM���DT[������Cff&


�a���ۋ+A+���B$''c����vɤ��ѣaoo��"??�:uB�Ν:::b{E۩"..!!!���A`` lmm��~�ƚ<��#Y������|6�����/٦��'��X���ݺu����_��8�R)B_Ӫ�FSz�,y���6d�����ΝÑ#Gp��ul۶
���üy���Uު2A�>e�We�LO"�3f�@DD��GI�5kV��9::�ĉ�������d888���k׮���/|}}����ڊ_+ڮ��VK����^�������)S�r�J8p@��h�O�>�رcadd�cǎ)|l�>}p��y$%%Ɍ1))	��W8F""j���������ҥ��S��h����1���|odd�R�՝�$����������]ӓ����Z��Z�BPP�CCC���k׮X�~���zK[�d	�}}}���[�nX�nfϞ
�ߚ�cǎ���7�~�m���BWW�>}:V�Z%�O�v��ţG����!~�����?���R6�ŋ���ZZZ�
=v�С000@dd�L����hҤ	��؉��ŕeD$b��������P���a�ڵh޼96oތ��0�o�^�����]�va�ڵ�ꫯ`ii��7obݺuT[a0z�h������#F�@�N����]�&<xSS�
�)YIq��a�7r�Tt���ҥ233���&3)��$��ell��k�Vئ�d���a��H&�$F��Q�FU���Y�f��Y�Ff��~�?���s*ϐ!C0d���mܸ1������t���(Iɿv����d��LDDpe�bmm͕eT/͘1�Z�Ӝ���+>5�t����+LMM�����3g�W�^�9s&���/����O�T���+������C�޽���@6�(YQ�PwY����o���>&N���͛�<ny}K�(IR�Jcz�.\]]Ѯ];�ۂ��add5FFDDu'ˈHdcc�?����E��^�ZM�FCC���Ԩ�t���h����!���0q�D�m�ZZZh۶-�L��]�v���Q�T��,X��ǏG�f͠���X�B�q���ID�������G�EFF222p��Q����Q�F�����(�a����
p��u���_�s�3G�� �Q�Is�f͚����+o¯:S���C__������"��7ӓ���������;������+��DDDW�Q)���hӦM�R1�9R�QMbz5NNN��o��7�`ʔ)�����8�,#")���,�O5��޾F�[�)��Iz�_|��S��=�͛73=�����,�,#"���������8{�,BBB��兂�����444�w�^�cCBB�����'J�	+[7�tzzz033���q���<x07n�֭[c�ܹ��˓j�����3g�u����ׇ��3rsse�W\\ooot��zzz044D�޽��?V��J�'���1=�����<�,#j�


п��9�^��ڵk��'OBSS۶mCdd$>��3|�055Ń����ܹ���
����&�Gi���Ǔ'O���رc^�z��g�ЧO����DŽ�� ;;[�OOO��?��/,,DLLbbb������p�HY\Vw999���I�a�	�,#j����ǣgϞ℔��=lmm���������OѼys�޽�
´i�p��i���";;D�- ����t���}���;��?���&�Gi]�t��]���ob͚5X�f
~��gq��������ر#���acc���1��4�1��������B�ݻ���زe'ˈ��\���8|���� ""�Z�4L�.,,��~�����
:::pvv�۷Ol;`�,X��ϟG߾}q��9|���4h�R}hkk����v��Cb˖-�ԩ�`��ӧO��_\v�܉��{����ׯ�o�.s�&M�6n܈�[����ǘ;w.A��{��NDD��L�0&LPwDTM�0������TĕeD
ܝ;w���R�-ZHLL�ھv�ZDDD &&����U���}�;�#~ݲeK%��$RRR�{��:�_�~2�����̙3q��)�:u
+V�����ϟ�J�'"��I��"""jX8YF����������+]������խ�I�g�tO��ёi;y�d:�F@@������???�]�s��QhTB�NDT��󎈪"88�5A��)N�5pfff�}�6�߿�:(IW��������˖-Cbb"z�聸�8,]��6mR����ԩnܸ�.`ذa����[�h�3f`ƌ����O?�����c�…�,SP߾}�ʂ��ֳgOu�P%cƌ�/�D���'�;"�N�5p�1|}}���-[����
o��&233��������̙3�3g�`ӦM�۷/Μ9�A����ȑ#1`�%���:w�\nYYY��o���'Շ��L���˗���
{��E�޽q��U���ɴ���@jj*�m�X[[�i��W��źeDDD
'ˈ8OOO>|�.]�����>===|��7�gϞa���044�޽{����ݻw������HLLD���ѦM<~�]�tA�p���
�000�P��ŋ��O?��ի����S�L��۷��zxx`Μ9pww����Ծ��R�.^�(>���HQLC"""����eD
\�f�p��%�^�?��3���ѴiS�������.�����'v��
333%�[�l���+�����^^^x�����
��ׯV�^��ݻ+���Ν;OOO<x���=z4v�܉���K�uss������{ܼyбcG|��G���/�p���u∈�Ú_%?~����?����˗/���$>:>>������9�d[e�3��v��mt��E���]��h[�Ǘ����f͚���nnn�ر�J�.{�T�5,,L,}ѫW/��k��eD�-Z`ӦMR�dž�G��߇�� $$D��iӦaڴi�'O��ɓ�C��&b�moڴ)�mۆm۶U�v�̙�9sf�}Մ�˗������Rc4�ۢE�p���z5�W]����gϞEll,���SSS��Q���իغu+8A0i�$t��666*������d�ecc��Ǐ�;""�z/!!�}�v��١��>>>���2�t��yu�P�J߷��bddd���W�^ŏ?��իW+u��^�/^`Ŋ?~<���cǎ����}}�*������TwDT7Y[[�֭[b*%QCT��]]짺b�…�p�B>��HI����;��455�pR���&LLL��/_�������c�,�)S�����

��x��j
'ˈH.+++�5���E���
��Ou�(I�Y�d	/^�-[��ڵkU>/Iמ�ѣ��}�	6�)))pwwG߾}1p�@�[�/^��:�'O�z�j8X�|9���������q��	���������)n���ǖ-[0j�(���#G�Ķm�PXX(s�G�a�ʕ4hz��ɓ'��Qބc�����ӧ1g�8::�W�^�裏���'�����cŊ�ׯ�����O�<��(3fy����С���R�+�]?������q�F�?���� 44=z�@۶m���ڵ���=BCC�����8���2�a�\]�t���>�_�.�'jHj+է*�TG�L�!�[����I������O(..�����	��3g"==]<��~C^^^������իW�a���ڢ]�v��̄��/ڶm�e˖
1g��?�edd 00IIIغu+45K�&���S���J�iKII���7^�z��#GV9��۷#  @j[ff&BCC���-�������H%D�F\\���ѤI�}(3��Tv�+s��}@�V��m�^y<==q��%%�%$$EEE����<y���ppp�9�����8u�ƍ��8���2�,#"����Э[7\�~]ݡP=SY:�-L�!�Y�kN���WZ;�C�8t�����Ӝ={Vܿw�^����}��ؽ{7������;w�Tx^�g������!V�Z���<x{{���+W�D^^|||дiS��}�p��M���;		��˗�����ѣ�9w�ލ��,XZZ�СC�p�>��c@``��W���W�k���`{zz"**
�.]�Ν;@�+���ؾ};������c�޽�̘+S�=.OQQnݺ����
лwoq�"נ����?���!22R�7�t\QQQ��]���&�&iCDT�qe����Z,JLT�����N�BFFttt`aa�ѣGc̘1Rm����������hݺ5��O?�T�#T6UP�8�"1U���ӧ���d�u��ptt���;*<V�1���L�:���J���uW��nW��������Cggg";;[���9��e�Э[7���-�.]�/��B���ѣ����O>�����2e
�{�=�MDD`�ڵ066������cƌ��'�Ϲ�/�,Y"����K�UT��p�A��[��믿�Ν;������ʴ���B�=�����򂻻;Ξ=��s���C�1W��{\ZyﵦM��O>�W�ȳt�R���f͚���P��TI�LIhifffRm���;N�Q�������?�;�Jmݺ{�����%������<��Wu��TWL�T%�F�12��������*..�=|�@ɿѥUV2A���y������HLL���9>��3��<�5J��)))�������5%++,��[�d�	� ������5���<ʌ�2����hii�e˖���ìY���y@�k Oǎů�5k&�ӧO@�P$�$m���;N�Q�������S<|�o�����!*סC�[�l���=^�|�'N���'�J��,[�HKK�ڵk�4�1c� >>^�e��T^?��iF�	


$&&���M*�Fޱ��P<���eD��~.T��4�k


������ �ڵ���&_J�d�7���-9F��6l��[�о}{|����@�n�0q�D����$���V�qUD��[@�4E�S�^y*{J�$VyT�lS�~�U�,#�rI��z��uN�Q�j2IQ���Epp0RSS������c���R�3���b��*�4ʌ�)5D�O��푚����]jUhRRR����#%%����y�&�n݊����������cǎI�n��7���)��<yyyb�}EWk���(��֢E@jj�����Hj2�ƍR+�\���ږG�1����@�Z�Bff&�?.�p��'s��NDT_��?��y���С�]���P�*4�|���!&&�6m¤I�����v��hJ��L)�FS]1ɓ���iӦaڴi���q���V7(3F���?Æ
P2!�� ̄��7n��5k��qqq		���
akk������п%��������+<y��}����1g��m�>}~~~���DAA6l�{{{��?q�����x��RSS���+�d�䳮���h"99˗/�����W_!))	/_�ĕ+W�k7hРr��2cV�ʮAEׯ2�Tڴ�4�}�m5�nKDT�����*�"�T��LGRԐ!CЫW/�;wG����ױm�6�۷�����3���b��*�4��G1����pqq��ӧq��m̞=[�>t�P���=�8>>999��񁁁V�^
mmm���`ʔ)X�r%8CCCL�>�ΝCBB\\\��ӨQ#,X�@�~ƌ���@BB>��#���f��vttġC������o���[�h��O�b�ر022±c����'N������2�$''K����ӧO�jӥK�
kI*3fuP�Ȼ~��ӧΟ?���$���J퓬l|����6"�:�+ˈ�B��ָ~���� �TӦM1j�(`Ϟ=puuEvv66n�(����;v���2����Z�I���4����ȑ#���{�2c���H�gJcJ
��$?_�AWW���?~<Z�h]]]<�Z�.���G����CL�666���?~,��jҤ	���###hii�iӦpttĮ]��V�j�
AAA2d

�����]�b���1b��n��?~<�5k]]]888`Ŋ21.^�&&&���k�-Y�C����>tuuѭ[7�[�N�L<p��9�-[��C�BWW-[�ĤI����==�r��2cVE���맨�C���@��YZdd$�4i���W}0DDu�@DT���pAKKK���Uw(T˂����L���<vvv���]M�&cԨQ����.���	����o��&���	|��n˖-����0c��֭[BQQ����%|��������&������섴���I^?��`gg'?~\���[�n	S�L��'O�=V�1.\�P����\�"��+W;;;aѢE*��H�\�uM}����m߾]���>|(n{��`oo/���j�����	Q�ǕeDT!�z�
7n�Pw(D�ruuP�*�_�~�ݻ��ʢt�����aff&�����C��޽{e�h$�sƎ+���:c�׏��#���pqq��!���\�ʌQRKH^ap��QY���h׮����m���022�IO%"��8YFD277G�&MX�V��Hcǎ���7�~�m���BWW�>}:V�Z%�S&��*�*��T��"y�*3F���2���ャG�"##8z�(|||ШQ#u�GDTmX�*�����ݻ��?�y�F�¨Q�*m״iS,\�.��ݐ!C0dȐ�I^?���X�v���z���clܸ1������t������q��5��������sQ�bggwww����͛'S🈨��dU�E��^_���8~�8�������)5DDT1'''899�;"���2"����5BBB 444��S���5r��J�T&��NC�
IJ�_|��S��=�͛73������$N�Q�����������㭷�Rw8DT͘RCDDDD�/N�Q��w�MMM\�v��e�����J��e�RCDDDDT��eDT�&M����			����Q�	������ ""�Z��2"R���
��Q�s��a>|X�aQ-�d)�{��ؽ{��� ""�5� �;"""RN��Blll��ボ��;R��'�;"�Z��;"���?�}��UwD�Mu@D����A`*ffjj�	&�;"�G&L�SSSu�����p����;"�������u�AD*��2"R����5k��ׯ�/d
T߾}y�	�b�Hi�����+ˈHa666HHHPwDDDDDDD5�+ˈHaVVV�|���àZƚ=DDDDDԐp���fmm���@�z�
ZZZ��jk�Qu��5��۷o�K�.R���������Ɲ={G�ō7������~��ѣ_�Ut+S�q*B��zu�\���!&&ЫW/�A��5��2"R���5��򐒒��jDT+� IDAT�~a�2"��kѢE8�|������|xzz�ҥKR�������@x{{���Q=V��r��8�^���[���&MB�Νacc��Ј�p���֭[7hii��,#""R���ϫ;�Z���K�.�m۶�;w.���f͚�ѣG8t���ك/��?��#�w��p����[&�Q_��/^���+0~�xƎ��˗#<<���j��������ѥK�'""*���^��8R�ŋ��-[b׮]9r$Z�l	---����9s��իWضm��å�PPP?~�ɓ'�ۦL��Ǐ#((H��QM��2"R����]���0���ꍬ�,l޼/^ċ/`aa�iӦaٲe�W	���#  ���Ѻuk>�~�)tuuH׭R���MLL6n܈_~���ژ8q"�̙��ϟc����p�tttЯ_?xxx�q���9N�>���p$''����[����#���a``Pcc�cǎ�N���m���I� �~�m��999�Ǚ3g����n���ٳѤI�k��7"!!zzz4h�ϟ�����ƍC���q��!��G������B�����_,^��;w��FU����兓'Ob���1b�����~����1h� ���P�^��G��m�6DEE!77fff�6m�T��]z{E�cE�o��׭[���ϣQ�F�ׯ�Ν�V�ZUx}sNNBCCѣG��_�v�`oo���PL�:����G��q����bmmͿ�)(//�~�)>|(nKNN'�J+,,Ĝ9sp��Mq[FF�����[�BSS�Đ
6HM��011Axx��gAA�?MMM�\��}�vH�+33��������իkt�����>}��;�ƍ�O>�ږ���O>����Rq��� 66���2/nnnx���x-~��'���������CBB����c�����={�}��*�Ǎ7"''���@Uxzz��իذalmmѮ];dff���m۶�2�>}�������ۦ������^��ȑ#����7	///DFF(�;|�0���,5!Z�2c>y�$������ s����ԩS7n\��MDu�0�H)666���?���Su�BDDT���Ç066F`` ������/wRd߾}�y�&�y�����������
bccq��Qҫu���^u��������ҥK�3g���ZZZ�駟�ٳg.\� ��~%�/QQQ�t�v��	�$EM��<y011Qh�{��Ajj*LLL�x`ll����ڵK�:�СC����̙3�<��8r��q�cN�8?~��c�077GTTV�^������{IbժU��˃��7����r�J�����M�6U:�ݻw#++���8t�.\���?�X��V�8}�Iܾ}۷oGtt4abb���t�ݻ�ܾ�sTT�k׮2�l��!��'ˈH)VVV�����۷�
�Z�79!o�d����VVV��с��-�/_.sވ��ڵkѹsghii���>>>���Q���':u�]]]899���,[�:t����N�
��*�d�,..������_��w�a���JVoI��X������J�W^<���⊪3g�����SSS��������
pttD˖-��/_�����mۢ_�~J�M���E&ݱ:���NNN������'��ʕ+�<y2�{�=��2�^�x�d������^^^�����?�\-1+�~����B�=���+++xyy���ˣ̘%���С��y��̤���i�D�cccdggˤ-����4���+����V���F��{����*�R�I֥�������T���,,X��nݒ�'��uM��m۶x��!222`nn.�� ��˓J�KOOPRB�4I|����yJ_��+�$���6F���� DFFb���t��?�ٳg��z��Gɤ����a6o�<\�|���077�g�}&�_�x%׬&����M���5$��t:pYʌY�M!�&�d3.�^?�,#"�q�����������/���)Kުe�����^Y�
6�֭[h߾=>��XXX�[�n�8q���=V+++<|��.]*w��ƍ�1c�u놀�q�J��V����T���ݻw�_~��p��	hjjb̘1*�M�&V�)J�x�]���-9���P�c�}���I2�����Y�ωd��ׅ��>N�Ր�����ݻ�~��T����e�!--
ǎ���Qm�Y���%5�Z�hRE󋊊���]cc>|8N�8���`�1-[���_\\�;v@|���$���1�߿�k׮�gϞb{�S�U������ի�������.�>���V�������XZZ��͛غu+.\(�W&�7�x���x��hhhȬ�Ste���7�7nH�f�r�
�����(3�V�Z!33ϟ?�y¦$]��'oQ�ÚeDDDDD5d���u��!))	EEEHLLĺu�d���@I
���d�z�
O�<�w�}{{{�(?��JI:Ym���Faa!�����Ijz��X{��
[[[���ߘ>}:N�:����|�7n�����>}��E���c@I]���!!!A���W�:�7�^�����QXX(է�c+Ou�߸�8����������������R��'����!33ذa����B��I�Ç�ŋHMM����R��&��W_!))	/_�ĕ+W�f���A�ʽ.ʌY�r*I3.M��&�R�H=���5��\�|Y�aժ�={���T�a�������߿��ӧW�v���8w����"��Q�FX�`��}�-���S�;FFF8v�XM��d��ĉ�������d888��X���vΝ;w���ֿ|��WR�p���8s�<x >�R���Tf����}�m��?F���Vѩ26y*��e�t�����������W����6|||0e��\�����R�Θ1HHH�G}$�v֬Y�׎��8t����[|���Ʃ�M���R�֥K�
�(3�>}���HJJ������@��W"��8Y���x�b��P������'�մ�j�������[�nŅ���sss������[�VU�&M��gϞ��ǏѸqc���bΜ9�ر��v�������p-(U-Y�EEE���īW�ЩS'����޽{�ǁ���Pcc��-[bϞ=���_ܻw�իƍ'3a�_

�Ν;q��9<y��Z���1k�,����$5���1v�X�zUʎM�긿���x��V�Zccc%i�X�r%|}}�f���mժ����u�VDGG���;v����1p�@�݂�������x����X�b�^�8}�I,[�� ��ٳhҤ	ww�rk��ݣ�C���o�Edd$�M�&u���H�O"z�h�U7�z-$$��Ε�$"z]hhhp���TR��&?O2220r�H��ѣ�~���!��^O;v�@@@>%O[3f����駟�S��'DT��Y��������������8x� ���Q\\�{��aժU U���kHc������ڵCpp��-88FFF2i�D�z`f�fD�:b�2"��F������W��y�-0{�l5EV��X�a��ׇ�����L�:p��Ql޼�5RstDT8Y�������@Du���LMM�믿�޽{(,,�o��޽{��O?E۶m�b�iHc�����������̛7O��?�>8Y�@���.�V&"�K455���� &��X�a���`�2""""""""����2""""""""����2"��233�B��kODDDDD

'˨���А����B�-ЫW/������@ݡ*��qihh@[[-Z��������su�[+$�/�~@׮]�Q�*���./^�{��Uz����_{"�����\��|��_�^DT���?�[���x��._��˗/#<<gϞ�����C��W�^�ٳg������#<<111h֬��C�u��1�{x��5\�v
��=~������;4���kODT]�����c={�TwD�"�,�zC�Waa!233q��A��曈���ڵk���ʎK!==hӦ
�����W_�;�'}$���#�����ȑ#QPP�iӦ����KDDDDDD�ǕeTo����7��q�ЪU+���{���_��ЪLKK��Ƙ9s&�z�-0aaa���Swh� �m�����_bÆ
pss�ݻw��������'NTwDT����I�a�
���d���a���055��������쌛7o�m�J�~||<&L��6m�@WW���Dnn�J1K�8gdd��+((��M�Я_?�j�
���hݺ5>��C�;wN��ܹ�9s�cǎ���C���agg�U�V�ٳgr�Q��)�W�^�/������ XZZBGGmڴ��I����Tn,���puu���	tuuabb��ӧ�Ν;r�+{K�V��S�I٘$�HKK���7n��#G"..�ܹ���n߾



�i�����^��[����HOO���weq���{N������UEpp��U�|��_�����,���e�/�…BӦM2�F�	Ǐ�9F^��/}}}���v�����}��w���\��HTT�@x�w��ggg����Ʀ��!;vL���X��а�c��̄���j�n�9x��oYU�wÆ
r���ӓ�&� ��򋠯�/��ƍU����IE�)Uc*}��_O�4IAx뭷���ޝ�UU�����<]��9`j�ɩ�P˛`8��Sڽ�M��C�h�-55n�� `zJK��Hi��e��@� ���޽�px���<��s��k�u�]{�w�<i�ߢE�@�-3�;���O@6l��Q^��b�go����%�U�{!�0��>BT�}"�}��=��,�r����XYY)ӦMS~��G�ƍJBB�2n�8���ZiР�r���;�788X��p�?
���J͚5@�4i����?+�����m�*�2g��c�5QTT�����ʆ
gggP�����̜9S�N�:)T���|%11Q�޽�(ݺu�ۧG�
��?^������%//O��o��;*���W���d���W~��e���J�:u@�5k�^������F�֭��������+'N�P<==@iР�r��em�K�.)u��U���KIMMUn޼����*^^^
�4j�H�t��XV���O��T�x������Ǖ��,��(J``�(.48�ڞ�9�����)�Ҷm[��m,NK>��٫.}_�r1*���DQY��5,{Й3X�p��QM�6�������F�3f�m0�!�:r�6㨤�f���������@�c�l�R�o���`ۏ?��J�ڵ��kժ�ʵk��IMMU���I+���Li�����]�q��=��?�����m+**R���ʂ�ruбO�>JQQQ���<���X2�;�YS��}��'���@�޽�^��˗kkk���Z���4)>crss�~��k��8-��+�WZu�Ǖ�Q!De��~��������*���U��en��U?�������~S�O�����[�޽��l�2����N��'ƾ��0����/���ʴiӔiӦ)���f�{��>B�9"9˄F}J�o�at��q�عsg�����b�ȑҿ.\�������<y���:�EQ���͎]Q���[N�8�W��/��(
]�v5���G�ƍz����0���(~��Wm[�N�P�.he��o�Ԯ]�޽{��]�vQ�V-��=�9s����+����_�����v��@@@���e�c����~4�%1���s��=��S�k׎Çs��e���/�����g�}�&M�X��޼y��}��i�g_�?{�c�!ă歷���׷��x���̞=�o�����\


��̼�UO����ѣ,_��3f0}�t�-[ƱcǪ:,!�="O�5)���c���J�
0a�~��ڶm���Q���3g�йsg��SJ%�,..&;;��'O���������3�?==�'N�����Ç�?v��;s�L^}�UHHHn���׏����/cgg�կh���W���L^�u6n�H˖-����y��F���y�
X<��������3��G-W?_0��eIL%��y�
>�w�}�m۶��k��e��_E���P�~}��1�%�}E~��:��B�ٷo_U���3�$''�����r�J\]]),,4�\Ǝ{?�_��7n�`Μ92D���f���lذ���#3˄&;;�B�>��S���W�[�l�Q�Fu�'�խ[��@���ښ�
���FTTo��6����Ջ���M�6�i�OOO�}�]v����n�~~~lڴIo6گ����ի<x0;v$==]�V�~S�O������G�ԩSx{{s��-��w�zM�65Z��|:bNN
40�O�z��?���~4�%1�T�vm��Æ
������fRUt�F��U��1��䳯̟�����n��t�t��CTS��N���ںB7Ž��˗1b�V6r�H._�LdddF&��Wd�Lh�ԩ��Q�c�����=u�o��&VVV�[���;�{��1�eƌ|��7ZYtt4#F� ==��{�9s�Ζ-[���<�+��·�~�ٳg������~��'�N�j�&K�͘�����g�ammMRRs��1Z���-�3��?hذ�V�~dee����ʜ~4��1��O<A�ؾ};'O�d߾}�������SO=eq�{��ʞ�e*K>��ٻ�^!�Rff&AAA��ۗ�ݻ3j�(v��it�-//�e˖���I���8p +V����@�SrS��:���,^��޽{ӷo_V�Z�}>s�Lz��I�>}�;w��
�ݻw3i�$����֭/��2K�,!//﮶�N�\�‚�ׯnnn̞=� &sϧ�z��&O�LϞ=�ׯ.��w���ng��O?�4:���{�A�Q\\�w�s�Ρ�����2��%͚5�N���ʿ��+t:��
es����~c�ܹ<���t�֍#F����a�)����/5�9s�лwo<<<x��w�r�����6�����O?����VެY3t:111ڍC!ăK˄�m۶:tȬ����1byyy̟?OO�2�i����T�������{�=V�ZũS�X�`���xzz�Ͱ)}��jѢ���*���>}�m۶z��V�=z0e���}����T��~������D@���������z�J3��Uј�3|�p����.�^|�E���,����`�,��+�g�~�{!��J����7��۷���ͭ[�HKKc�̙u

�4ik֬��ŋܺu�K�.�ԩS˼^1��ŋ���#//���l>��S�m����wv��I~~>999|��,Y�D�o�ʕ��_�"99��ׯSXXHFF111���TY[srr�g�֭deeQPP�W_}ŬY�*�|'N$))���|���ظq#����vw�����|�����лwo������/&##���BBBppp�>s���ի�;�/���?�����BΜ9CPP�v=WQ�~�T�f�bǎ���q��U6oތ���7�i��_M^^nnn�qss#//��\�B����	͋/��`2�K!..+++��PӧO'%%E[�_�>}�n�-55+++Z�jeQ�k׮�yԜI�G�6�_�b�d��V�Zaeee���MK��N�}�])..��7�4ȭV��~�eEEE,Z����k��n_d���,..�.���맕�ۏeQIJ�ג�L�.ܼy3�>P�e��g��ĉ�mۖ�_~�BDz䳷�g�A�{!��JQQQ�?'''"""HHH ,,LoƊjݺu�<y�����h>L\\]�t!))��[�������M�g������9t��&M $$�5j�q�F���0a��
����ۃ1���:t�O>����/L{� IDAT����>�…8;;�f��|��Zr��-[�i�&�����\�`�g`����/�k�f���zu�>�ի��qԙX���ի������%((���bm��y�T��Ś5k��̤cǎlڴ������+�a��e)��L�~�N�>�ʕ+IHH ""��͛s��>��2�mN�����С��q�2���v�)����(���\�}I�ϟW4h�J�~��Ç+7n�P��٣L�0A���Slll��G�j�lٲE�'�|R�~������5k*���o+Jnn��{�n�S�N
�̝;Wo�̘oݺ����Oʻᆱ���)��n�:m{۶m@y��ו�����PIMMUF��PΞ=���J���;w*ׯ_Wnݺ�?~\�߿�(C��P�ݩ]�u��i�J��2�(Æ
SN�:�ܼyS����_|Q�G}T�qㆶϯ���ԫWO///�ĉ�͛7�'N(^^^
�Ԯ][��_,�Dz�D=�
�[�n)7o޴8&S�]Q�'������(YYYF�u�[�n)/^T�nݪxxx(�bkk��۷Ϥc��%��%?{ս�KW�.����>quu5韢(ʈ#WWW%11Q����z�Jֽp�^�_�UquuUƏoCY�+���ﵲ��\���~��������X9q����WY�x�2t�P���U��t�Wv[�j�CRR�^���+�oO�:������������O���e}�������+��(����3�<����[�u��w�������*~~~�����d����􅷷���ꪤ����Nm4V^V=S�_�����Ê����ueE>��^zIquuU233
����T\]]���������#�4L�i޼9���2�ݻw����Y�b]�t��/X�������+��ծ];V�X��q�X�p!.ԫ׽{w��*S�a�7N�q�L�0��+W�r�J��s��!&&���#G�ТE�~�m�l�©S����08G��͵/�{s��T���|��'8p���@^y�-9zE��ĉ����+o֬[�l�V�ZZ�_��W���:t([�l���j֬ITT-[�����Dz����w�^���)�bQL�>|8Ǐn/���,��[�.�}���K+J�䳷�g�~�{!���Ξ=`�{��pT�Ν(3�EYO6U����%�Rrټ���eff2m�4N�:e�M)1�^�����<��z���\Zr�����-��RXըQ����%22777:DQQݻw����h�<
sʔ)>|��ǏӺuk�����m7�/.^��w*���/U��h���`�9m�z�*�g�֒�2���%�0��p��1���qvv��֖
��/�s�N^�u��?�����g߾}���K4l�;;;{�1�y�����A�;�Y�&�Z�bĈ�ر����?z�ǏϚ5k�ҥ5k֤~��<���|��,X�@K��&���C			����t��{{{lllh۶-o��G�50������ccc���
�6T�C�e�޽�t:lllhݺ53f����<����w�}ǨQ�ptt���GGGƌ�ѣG4h�^}K�ј��H^|�E�ԩ���
��_-���r@�l���
M�6��͍y��q�̙
�S�%���?{�k�!�ݦ.!+����r0�O���,�J��CZj֬i��ں��,^��S�N���̨Q��;w��Ͷ��U[�c�>���&K�gkk����ܙ�7f��=z���Tm���%��͜�0��%�m��~��I=g�5L��cm6�s��I.U!|2�Lpqq1��Șk׮Yt�^�z�|1p�?nw2f�ƌct��ѣ��3kР����|s�
Lo�O<��[�*�%=��9r��;v,7Di��>iժ;v쨴�L�w�I�VVV��T�Y�1L9�%��9?{ս��~����O?�����4��ޠ���#gϞe۶m8::��0˥>�'""�F�����m/,,���枷��ٙ��t���;�|��fS�v���|������r��!����ѣG�����s��:v��ɓ'Y�|9���?�����#�<¯����,VVV(�Bnn����ԙ��~�T'N�Л=�>���ٹ�s���&M����AVVM�4�ۦ>	�t��#3˄����
��ť��y�H�!$/��.$55���B�?n��|ˬY�HKK����+W���G��鴤����uyٽ���@AAiiizu����^[ˢ>�&88�����BN�8�=
���WZE?����/xyy��W_����O<AÆ
-:��ȑ#DGGӥK"""�ڵ+�ׯ׻9jN_��wK�,!##���|/^�N���� ��͛�q����F�dY^���z�wHMM�֭[|�����ϗ�/�Y]r�.+.I-���R�Ճ�,B��]�����e�����B<�|}}�ꫯ��_���+����{��%%%�Q�F�m�U�ӦM��7jԈ�W���퍣�#۶m��������	

"((�`{ZZnnnw��e5j�w������S<�S�KtT�J���`̘1lذ(	f�<]�%''���üy�]�6,��Ɔy��1r�H�ΝKll,���3�/^}�Uv��EJJ��ӼǏ��vwwgӦM|��|�ᇀ��3S�_��;|�ڷo����4s�ܣG���Gjj�A�=u��X.+��Z2�L!Jhܸ1�[��_~����h�`qwH�!�W�r�����	��ӓ�
bcc������$;;;�nݺu������GGGjԨA���qwwg���z�Y�O�N��ͩQ��ɹ�,5c�<<<�����ΎN�:�p�Bm�*66����,vvv���1d�5j���/���f�2�[�+�2>�:u�h�+����~��7prr��ɉ��._����2�/�4iBdd$ԫW[[[:t�E���N�6�!C�РA���pss3z��X����R͜9����cggG�ƍ>|8aaae��3�����v��Z��8@ݺu�Y�B���R	wD������+��{��Q���w��-Zp��U���X�j��'!���Ҿ���"**
���T��ɥK�8p NNNlݺ�ҏ_�<Lm5ׁ�6m-[�d�ƍU���U�V��͛i޼9.\`РAL�8�q����r}"�}-Yf�	�QE��q��9�_�NTT���c�B�Q�޽��t|���dggS\\��?�����Y�S[+*//�+W�hOr7��)QuƎK�f͈���ʢ��ptt4X�)�x0I�2!�B!���b��Q�Fz���wS[+��KX�ш����7oo���6��u�V�.]J�Z��8:!Ľ �eB!�B�%�hт;v���?SPP�#�<B���7nUb�y��ZQdee���5k5jԨ�D)���L�<�%K�0e����B���	!�Bq�X[[����P�)z��ZQ۷o���	�,��K�R�#��B!�B!ğd��!5lذ�A!�B!��ڑ����L%B!�B!�(��=d<�ҥK�:!��T���?�ٳgU�!�x����y��C!���uU �s��I�2!�eÆ
�;w���B<���СC�:!�}h�С�hѢ��BXHf�=����:!��VVVU��%�KB!��I˄B!�0B�%����O�`�B!�e4h��gWa�aÆUuB�
��2!�t��iڷo_��Gbb"ݺu�?�B!D%��eB!��G˄0�[o�ž}�HNN�V�>z�(˗/'66EQ>|8...t����)�B!�B��d�L3�۷�ڝ�ƍ̙3�!C�������7�g�fÆ
�����0�BQ�N���m����تr�}i��/^�Ⱥu�HLL$##[[[��׿��s�1b��ׯ�c��dU��ae]���I�ә|�%�Vdd$�/_fĈZ�ȑ#�|�2���U�B!4o�����U�=��?0r�H���8w����r��i��������Uf�*�VW5̘1��ӧ�l�2�;v�#B��Gf��j��~cŊ���s��uZ�jŘ1c0`�^������سgW�\�iӦ��ۗ	&P�n]��:�Chh()))ԬY����S�j�����	c�Ν\�t	[[[ڴi����
�;V������배0�O�����V�*�N���;���s�����O?����V�Y�f�t:bbb=z4���3�B!��2g]U�,{c�Ռ�>����\�}�Y�|�MZ�nMaa!�N��> --��˗�`��{Ͻ ��3�Y&���W�2v�X���K���
9s�AAAl۶M�w��u^{�5֯_�o��Faa!DGG3n�8����=q�D������'++��7�m_�|9�~�)�Ν�֭[���q��q�}�]���L�?44����A��l�1_�5yyy���lsss#//��;w��B!�#3�|)))���{���`ccC�Z�xꩧ��U�=#��,�ƚ5k��̤cǎlڴ������+���[�v-���4oޜ����ɉ3gΰz�j�c�lْM�6���?�|�}ӦM,[�������O`` ���������d�;��[�&>>��;�����s���СC��ej!�BT���<����ݻ7���r��M�:�w�fҤI���ӭ[7^~�e�,Y�w#����U�V���M����ݻ7���*�7o�P|�f�B�ӱ}�v��
�NG``��L������X�l���t�ޝ��b�



��w��&O�LϞ=�ׯ.�ƍf���@eNN|���ߴ~

���иqc233
��E�$''�gϞr�2V���y�&��ϧgϞ��ۗ�� �s�Sג~����۷/�&M*�6eUCNN�A,Bq��e�(;l��9�]�7c�Z�hܾp�5k�^=u�k֬Y<��t�ܙ�3g��o�g�&O���O@@�vL___"""���ֶ׮]��ׯEzz:���2�!C����Q����3�զ�ۘӧO�Kkժ�^!�BT���@:�X���������V�\Ixx��>��Đ���݌[�|9k׮��ܺu��Ǐs��qrss-�'�ѣGY�x1]�v�Y�fddd���3g����[PP��I�8y�Vv��%"""HMMe���X[�ߣ�8q"YYY���q�F�����K۩�@HOO���IIIDDDP�vm�b7n�&L�W^�gϞ<������ޱoM�h�"mEA~~>۷o�رc�[����Ե�LY%q�U
III�ܹ���[�BQM��2Qm\�x�OW�p�p{�����zJ�8%�i�F{�^DkeS�N�f͚$&&�����ÇA~~���S�2���\�z�hN2�L�#�B��s��5���8p�|��,���������9t��|�	��2�4uf���z��1�|rss	

�����s璛�˼y�_�~�3�׭[�ɓ'y��lj���������ѥK���غu�AL�1�ߘ���W^!88����f�Ə�s�=�믿N\\��:s<x��K����@DDNNN��7-�kI?�\%!��;,��K//,��n�����%�J+y���y<<<رcAAAt�ܙ��|V�X��ظq�I�/kV��(�kcRi��o黵%�*گB!��WրSY�o��6�[���ޞ���p��m����9r�;vdǎ|��G,Z�@oٜ:(**���8�]�Ɛ!CHNN6:(e���~���;^{�5���[F��3�<S�~�v� 88jԨA�֭�7o���N�s�͚5�Yb�g�[���+lmm���RIScQyxx�y�f>��3�x�
t:���,^�~���r��<������akk˓O>��j+=hgj]K���U��A�e���x�G���_9s�;v,�������ǎ��g�����U�O�1W��������ӓ�'O�{�n֬YChh�ESɭ��P���\�	�gΜ1�gj��iҤ	deeѤI�m�r���B!���ڶm��nР��/33�iӦq��)�}K�x�:u*���'11���DV�\���?>>>ԪU��͹�9e�>����iݺ5����Ϲs����4����)���m'ܝ�u�Ё:���GAA�W�&,,����ŋ��_y�u��K�.�?ޢ���)�$dU��a!3�D�ѣG�,YBFF���,^��N�%�pwwn߽LII������.\@�^��>���:���?����<ڵk���`|V�zQX�F��y�fnܸAzz:!!!��عե�gϞ58�Zf��N!�B�͒�w���x�bN�:���3�F�b�ܹ���ԫ����`�1��ý��_REV ����N��˗
����1v�X
��i����F������-��~0%���jB<,d�LT���*M�4!%%��_~��={j��r��c�ҢE.\����?ݺu��ߟ�/ҢE-ׄ9ԋ���z��M��ݵ)�]�v��`���8��c��z~�!�z�bذa4l���v;�:Ж��jp\�̒�C!�B�[�@KDDS�N5��(,,�^������Y�v-cǎ%;;����
����k�����Y�|��Qg�o۶�`�099���$�b���NNN��+TY����*k�N�AYrI0����ʌͰS����?z�(�>��Eu�F?��+�%ɪ!ăD˄Q�"GYiM�4!22�ի���-:t`ѢE0@�W�^="##6lԨQF���ի
�d
ooo���x�ǰ����Ύ6m�������zӧO�y��ԨQ㎉\�M�Ɛ!ChРvvv���1g���m�����v��z�U�nݺ���f��B!�FBB���1{�l�\͡e�lxK9r���h�t�BDD]�ve���9rD�cl�{�>}������(**�ʕ+|��G�t:&M�dv,���n�@9r$p{ ���̙3p��u���ό3�?�L_a�z�HMM�����G�ֳܾ�ne�jB<�$g��V����?��iР����Rր��r5_Yy<<<���0����jOn*��)�6v�:u����Cxx8.\�y���<ǎc�ĉ�B!D�������	

"((�`{ZZnnn�;���`BBB_JΆ/���JKNN&''�y��Q�vm,X���
���c�ȑ̝;���X�իG�F��z�*���8::�m�6���ػw/)))�5J�صj�bڴif��S�oϞ=�;w�`���+�����ѣ��ψ��5�4Ζ-[��C{���ΦM�������pss+��7���O��cǎ>ܢ����>�=z�o�>RSS
>Y� �x���2!�scǎ�Y�fDEEieQQQ8::\�
!���Uƌ�3f��ၽ�=vvvt�ԉ�2a�m������
		��~#  @[����D@@�/_����t�[�.������H�5�_�>���^�ڢ�F���n�@x��7Y�|9����/���;;;\\\x����ϴ�d`�
Uhh(={����ƌêU���3�ne�jB<̬�;e�����h|}}�䢥ߛ�Nw&-u��|>h���[�|�M6l��СCY�ti�w^�xPXYY�����Ba*�}"�5��ڔkas��M�V�"<<�͛7�j4h'NdܸqU_u!�O���%��2!���L�<�%K��d��L�"eB!���ɪ!��@r�	�T��,Q6�S%�B!�*{{{�͛Ǜo���ѣغu+K�.�V�ZU�BT,B!�Ba���Y� �x��`�B!�BTsVmT���A� ��eB!�B!�B���,{HYYYUuB!�B!�Վ�=dz��I\\\U�!����g����B!�,B!��6l��ֶ��B!�=$�e�����[�a!D�����$�B��b���l޼���B!�=$�e)EQ�:!����Qq���B�p��2!�B!�6lXU� �������gϞU���U�B!��ц
ذaCU�!��mذ�s��UuB��2�;}�4�۷kC� IDAT��穬���HLL�[�nrG\!�� ɉ(������&�e��[o�o�>�����y*+ƣG��|�rbccQ��Ç���B�.]*t\!�B!��a"�0�m߾}�<��7�3gC����'''����={67nܨ��B!�B����,F�t:��>#KT���H._�̈#���#G�~�z"##�<yrF'�B<���J=wy�õ^�t���$��B��d�LT��ń���s�N.]����-mڴ��ˋA������#<<�]�v��ӴiS^z�%ƍ�����h�E�)1�w�ݻw�a������ϧiӦ���3y�dj׮]� ''����~�i��f͚��鈉�a���ԫWϬ�!�B�m�*eFY$��Bcd�LT˗/g�ڵ�[�nq��q�?Nnn.���0i�$N�<�սt�����|�r��+g���1�r�J����222���!;;����9m�����������8nnn$%%�s�Nlr��B�����b,Ž��t@Kc�a�����IB!��Y&��M�6�l�2ؿ?������j�֭[�ɓ'y��lj���������ѥK���غu+�����lх�)1�u����H||<��O>���kj����С�A�j�ZG!��O�ә��QT/e���|�2���U�B��&3�PvN���w�N_�ڵ�~�:QQQ������ΐ!C2d�^�]�v����[�f޼y4��۷,ۼ�1��~E�ԩS�ر���#G�p���r�5���O��e˖�iժ�^!�BT���<BBBػw/�j���_dʔ)ԬYS�s��
`^�
s����t��>&&���PRRR�Y�&�?�<S�N՛���o��b�
���~�:�Z�b̘10@�X��c,������سgW�\�iӦ��ۗ	&P�n]���)>Ic!��<2X&���S�2�|ILLd�ʕ������C�Z��z�Ν�����qΜ9s�c2&33�iӦq��)�m�����9m�z�*�ы9�L�#�B��ȡC���g�������")"*�ĉ��� ??��7R\\̬Y����cǎ%33S��̙3QTT��M>���y��HOO��222���&))���m0��$��B���2L����rŲ��v��APP�;w&??�+V0`�6nܨջ�@ӝfmݍ��Y�x1�N���ٙQ�F1w�\���L:�9m���0��M-S�!��j\�v���88�-���o��o��V��.-��"Z�lɦM�������ߠ=k֬!33��;�i�&����+��@DD`zʌ�kג��N��͉�� !!���p���8s��W�6;>Ic!��<2�LT+������OOON�<��ݻY�f
���ڝ=GGGΞ=˶m۴d�U�1�#�#""hԨ�����Bll�����&M����AVVM�4�ۦ�Q-].�B�Y����ߦu���?����\��m75}CERDT���Z�h���/dggk�<��3�z�f��fv�C�5kO>�$�;wf�̙����ٳ�ɓ'����BQ�Y&�
///t:��9yyy�k�lmm�z}��n_0���QTTĕ+W�裏��tL�4I��ΨR�5ޭ��;OBB���1{�l�\�`3��9ml߾=gϞ58�Z��B!D�h۶���A���c���LƌØ1cx��w����n���q>u�Tj֬Ibb"����>|8���y��+*c�@�6m����7h�ŋ�ʹ�p�p{�����zJ�\��'i,�B�Gf��jc�رBHH�޶�]�j����ػw/)))�5J�^�Z��6m���Q�F\�zoooٶm�]���y���پ};AAA;--
777�����=z�o�>RSS�bHMM�W�^f�[!�e�S|c����=f��
�=�mڴ�S�N6L����ݺuc�޽lٲ���+V�n�:�L�R�[��h7�


ʬg�aI�"D���L�O�X!�0Ff�	��E��Ҽ��	

�����;;;ڴi��������խ[���|||ptt�F�ԯ_wwwV�^�ws���4oޜ5j�{�Wј��gƌxxx`oo����:ub�…L�0�3���}�ic����]��^>Ձ�[�./���mB!ĽS2}�ԩS
�j�����]���cǒ��Mhh���W�rss���<4�G��1T��;�W���$-���BMYQ���B!3�D�����������������������d�<���#88�h}u���Mmc�:u���!<<�.мys��cǎ1q�D�'D	!��zJHH��'==]{&�N�иqc����p����0�v���믿���̥�t߼y3��ҥK���ѣGbbbX�d	���4lؐ�K����3����ۃt��p��9-�Xi�����`�y�:v��ɓ'Y�p!`����ۓ���ٳg
�$��B�Y&�`�ر4k֌��(�,**
GGG�e�B!��~���

��͍Q�F��?h���Ҁ��BBB�ݻ7ݻwג�N�`�?��Cz��Űa�hذ���{��WiҤ	)))�������S{*����z�C����
fөƎK�-�p����t��
.^�H�-��]��G���)+J�4B!df�0KE3^�{��Ӝ��2Ԋ���g޼y��曌=��[��t�RjժU��	!��ʸf�1c���8p���"ڵkǨQ����	#66777������!..N{���3�z���,1m�4���ٵk7n�@��1g�^z�%��פI"##Y�|9			���Ӷm[����ׯ�Vo���|���ddd��2�^�zDFF��'��w�^�\�B�&M�ׯ�Ǐ������|��8p�1c��m�4B!d�L����+�'Ofɒ%L�2�Bw��BQqe
��.75}���œA<{{{	,���n�+�M*c�(��A�P��L�O�X!�(��	��O������|||�:!�B�jo�ر|��DEEi�p��B!H�2!�B!�CHMc�u�V.]�ĥK�غu+��͓4B񐓙eB!�B�����Ba��	!�B!Z��B!Di2X��6lXU� �B!�BQ�Hβ�L�-:thU�!��f�С�hѢ��B!�B< df�C�gϞ��ٳ��B!�B!���d�L!�B�2������[�a!��������(B!�0O\\\U� ���=��U��B���'9ʄ�a&�B!���Y���eB!�����B�������ǧ��BX@˄B!�(��gWa	++��AQ�S!�B!�B����2!�B!�B!�G�a
!�Bq��t:����s��|�
[�n�ĉ\�~��{��}����E�z��:�Ju��iڷoot[\\���t��Mr�	!D%��2!�B!�}#//���@:�W���BJJ
���^5V���z�}���<z�(˗/'66EQ>|8...t�ҥ
"B��,�B!�B�7f͚šC�ppp`�ܹ�ܹ�Ç�u�V����~�:��׿8~�xU�Z)���g��ƍ̙3�!C���舓����̞=�7n��(��"�eB!�BT�N�Ӗ<����8p�ƍ�z�jH�ƍ�Q�NNN���L�4���"V�XQ���U���\�|�#Fhe#G�����DFFVadBq��e�B!�B�eyyy����w�^jժŋ/�Ȕ)S�Y��Vg���lذ���4���iڴ)���L�<�ڵkP\\LXX;w��ҥK���ҦM���4h��P�	

�/���ƆaÆ1i�$���X�h�����֖޽{@�:ů 33��K�r��AnܸA�6m3f3g��s����ή]�����iڴ)/���ƍ���N��m�6F������6>EQx����srrcϞ=\�r��M�ҷo_&L�@ݺu
�(&&���PRRR�Y�&�?�<S�N��g��8;;�i�&��{yyq��E6mڄ����mS�����qqq�룒9�rrr����駟��f͚��鈉�a���\�6!��Wd�L!�B���d����<���),,$  ��+W��OFF111dgg�`��/_�ڵk�:�n����?~���\|}}M�g���z=�~�)͛7gÆ
�<y���|���K����;w�Yq���2n�8Ο?��KKK��J*((`ҤI�y.]�DDD���,_�k��bԥ�=z�(�mu����^�+�~�:������zqGGG���DDD��@�ĉ����b�ƍ3k�,t:G�!%%�'�|R�'%%�.������lV�T������9��_��������6777���عs'�.�B!�&�0�B!��ˮ]�F\\Ж�}��7���������9t��|�	��\˖-#!!����@ll��񤦦�~�z:ĤI�		�F�lܸ���x&L�����͎3**�������DDD			���Z�n'O����'::�ÇG�.]HJJb�֭Z�+W�мys��
�v�Z���i޼�Oxx8NNN�9s�իW�ӲeK6m�D||<�������:��_��}�v�bv�T�[�&>>���,KNN�����СC���2��B��`�B!�fPs���UVV9��o�M�֭���g���?p{@�ȑ#t�ؑ;v��G�h�"�(�:�)**���8�]�Ɛ!CHNN6:�R���@ڵk���>>>ܼy��3gҲeKj֬��ѣ��U�ĩ*͚5�'�|[[[�v���ٳ
bٵk������P�F
Z�nͼy�?�jԨ�^�jc�t��Y��g��}hѢ5k��f�egg���N�ƍٵk�n�����]�v���@�޽�n�jԨQz�3�9}�4p{@��V�Z��Ba>Y�)�B!�]ֶm[�u�
����L�M�ƩS��UE{=u�T�ϟObb"����\�|||�U����o�^{]r�a�6m�������ٳgxꩧ��t���`�s�����i4�3g�h�8�<�.]�u��F�+�Bnn�^�.йsg��j|/^48Nɾ�_�>��gfcc������8p��}�r��!����0a�6�gN�T�`Wy�^�
`4'�Z��Ba>�Y&�B!���p%�ŕW�q���ŋ9u���Ό5��s�gP��Ã;vD�Ν���gŊ0��7�܆�(�t�,K�T�@����c��J�XS�ߌ9q�}���Ϗ���r�]�5[[[��_y������/�۳Ĭ����`N�Tw������祖�Y!�idf�B!�U,11���5j�������ۗ������OOON�<��ݻY�f
���w=���q:;;��O?����3�hۿ��{�c:::r��Y�mۆ��c��饗ؾ};QQQ0�ƍ�m/..fժU(����7m�������ǎ��g���;vL��\NNNt�֍��xRSSٿ?�=��^^6s�f�&M����AVVM�4�ۦ.�-].��t2�L!�B�j"!!��������{��������t|������Ѯ];\\\��PU�/��…IMM�����Ǐ�p�B�c�����O,--���"�\��G}�N��@н{w�v������;w�$''�[�nq��	�N�Jbb"=z�В���cp;wXJJ
������h����ˢ~<x0EEE���QPP�wNs�Vu�����\F�.w-I-+��V!�ydf�B!�U��ݝ�۷DPP�����4���;v,�������W�X>�����ח����_~�??�r�����޽{IIIaԨQz�jժŴi���BBBx���駟��%��Ӈw�yGo�رcٳg�ΝӞl�jѢ�A��z�ꅃ��/_���Yo�%m3�Q�F\�zoooٶm=z�`߾}���|�ZlB!,#3˄B!��c9��5c�<<<�����ΎN�:�p�B&L�@ll,�����c�agg���mڴ��Ϗ���W�-����=aaaxzzҰaCl���;��)���J�D�f��Lh,�Ÿ�B�m�"�H)d���X�6�اaP&�2nCѐ���J"��e��I{�>�?��3w��ݺ����G}�9���{;}��?ZZ���ĪU����jذ!������
###hjj�����سg���f͚a߾}���бcG4h�����ׯ����q�F��5j�ݻwc̘1044���&

1n�8�ٳ��(�e...Rq�m�,��χ��	455QPP4h4h���h�����ѰaC~v!��i���NB!����ЀP(������I奤�`ذa066Fxx���S��ر���8r�LLL���9|�pL�6
^^^j��Ǎ�O���if!�B!D�����j���())��'O��o_}���kX�yxx��O?�P(�ӄB!�����$��,#�B!�����#��b�޽;F����x4mڔl�(OOO+W�Dxx8RRR������p�\�R�1TB!����B!��Z�p!���p��I<y���O`cc///���u�@ �̙3�i�&��Y��e�B��h��B!��R��Ճ��+�g��τ�z�&!�B!�B!�C�e�B!�B!��O�����UQB!U�1��*B!�BH����e!!!�ʊB�
�ȑ#�!��j�Ǐ��RB!�#����ѣG�*+B!*PXXH��BH%�-!DY�G�������AQ��I!�B���!��qR�`�0#���e���!�
�puuUw5!J���et'�B������ŋ���_�]
B�^�za����F�>|8��KQؘ1c�]BH%T�`�x ����({��9BCC��
!j
mmmuW�ʌ=��g!����,#�R��LfBԋ�oB!����2R�RSS�駟���VW�A!���eee�����ʮJ���������/�-����ظq#���PXXWWW|��
��˗/����q?B�4X����֫W��/0j�(|��_�~5�NyFFF�ꫯ��W_a̘1�ܹs��޺u!!!�q�nܸ����J��s�N,\�����(�<ijj�Q�Fhժ���Y�f���?WI���ڡl�`Uk��QA��*��tY��laa�!C���G�ƍU\cթ�~&�(�!է.�(#D��=.\�P��ҥKq��u���o�*T΍7�m�6<x�1�;����ҥ�R�&�"
������߿Ǖ+Wp������ܹshР���&���T�<y'O�Ľ{�V�+V��ѣGUZ�ԩSU�_Y����{ܼy7o���۱s�N����$��j)w��_���ׯ#44�/_��f�zQ3B�G]�QF�2.\� �&k�,!!����@���"�����òe�0j�(\\\�t�R���BOOO��B�D�e"$g��ݻw�x�"�̙���8�Y�?����j��6m� 22��ё�������077dzg��PC��:O���}�6�lقcǎa„	hڴ)���ZJ+k��@�&�/�����?��ԩSX�x1����z�jlڴI
5$5�0#�jQ�2iu�qG�z���444d^��e���x��5���>mܸq��?�{�n̜9S�%���U=uW�&����'�|��#G���۷O͵R���#���%s���瑓�GG�j��jhkk������Cxx8.\��M��>��zDE455all�I�&��hP�BH푛���˗��������uʙ3g0}�t������C�ŦM������SRR�;v���666����ĉ�^
���
VVV(**†
`gg�ر���ooo���}��Ŋ+����p=��G�/_�����
|$�g�֭prr���
�
???���iiiX�j���[[[,]�T�N����ѣG�9s&z��~��a�ڵ�����_�g��u�+++���ÇGII�X�ϟ?������YYY8p��u�CCC~�O?�VVV8p����wO�1 IDAT��+B!�S�`ٳg�0u�T���AWWFFF?~<�޽+s

�
_����1z�h�l�:::hݺ5/^���l��ܣG��+??������мyshii�E�2dΟ?/3��b���hӦ
tuuѤI���x����c�77v��q�۹���-_��:O��֮]��]���˗8t��6E�Uw;�͟��g� ����aÆ������/���SSSL�<>TY]����5��G�eQ�lے��0a�A[[m۶Ŗ-[*���߁�SB!5��ŋq��	����ݻw�����E�!>>���(**Bjj*8�u���m۶
�v�����QXX���\ܾ}?��#�B��ٰaBBB������L�ڵǎ���!""�����������fq�[Ϝ�xyy�ĉ���Daa!������-U���L�>{��ūW�PXX���aΜ9RI�deeaҤIGFF


p��)������iӦ!..�������Ç���+ow�i�رx�����o�t�&���������ͅ���T������EDDD��C!�X%	�B&�������� ��_�>;~���1��}����g����)s߯���egg�̿<111���/��333Y׮]ˬ���;v��1qqq�Q�FeӪU+�����~���g
4`m۶��6V�~}���Sf_(R~y�J�>�W�v�bؘ1c�4E˭�v�ۮ������رc�������y:}��J�R�tI��?+���(۶�Ǐ3===�Ǭ]�V%�%�~)�r�>��>��RS���2WW�2��0�PX��eL ����͍=~����沍72�@����k~�޽{3�@�BCCY~~>������g�������Ӈ	v��%VPP�rrrXhh(lذa֋K7n{�����۹s'��֖yzz��O����|��o�1�@��'w�a�ح[�XAA�v�<x�T��@ `������=~��M�<�	��Vخ�۷3�@�����R��c'N�Ȟ={������'W_�����{ֻwo6n�8���L���r�
c��9s�0�@��]��$q�?w�\�mD}��>!��W�ufٻw�0j�(deea�ܹx��!���///���Uj�cL�f�~��]����<y�iӦ���ӧOǓ'OPPP���(�i�7n�����oII	޾}�C��$W~Z�n�_���;��ŋ���E~~>._�0���O?�3w�\deeaʔ)x��!


����s�ΡC�x��)~��J�GWWx��Ԭ�{��!99}��)s�E���G�)�g��ի��6�h��nGe���!n߾�������R��Ν\�v
>|�ݻw1b����aܸqx����
>|�Ç�q�Fxxx�����gE���y��������رc����>�ƍ0`@�}Q��rE�U*k&���&�6m
kkklڴ	���ꮪB䙭^��uy�H��=^'�1;Y��d�XXX@OOS�LP�� '**
W�^E�p��Ilٲ��f}2��^
�		Azz:F����x����݆ŋ�m۶��с��+�ҿ����077���.����>��h=ϝ;���A�N������]�b�ҥRu����Y������Ԅ��V�\	8q�D���f�{{{�cǎ|yK�,QIy.�g�s����֫"�7ƨQ���\�t	@�,�[�nA__]�vܿ`nn.�G�V��!���nS���5k���#s�ܹs��Ή��eZZZ[�`�ض��9���ի2g���Dܫ^�zl���Ry���32��<|��`
4K�_�>���ӥ�ILLd���1��l�qug�1???����/b�lܸ�`[�l�:F��R����On��h>�.W��:.��~����lllXaa�ض��֯_?��^�ZeuQ4]����=���;^���2m[�z5���),,d666U�Y*�r>��V[{������ݻ���uWWn�|�H���M��hfٿ��*z�����yp޼y�����͋1�N�>�lmm��={���@�����M��ϗ�^\\��z����lw^^�Ծ���۷o���ʓlWNNN����


�����<��Y�ciii��֖yyy1�;u�lѢE�>=z�ٟ�1���&�����6�>�~�Bj��Y�����oen����r������q�PTT�A�a�ڵb۹�e�cee��<y�p�c�v��ܹ#����S0��>�>��s�rLMM��
�����o�ر#cx��%���~����_b�����+SE����3Eկ_�窺ܪnGe��ӧO�����@KK|A\


,X��x���8g�hР���s�NDFF�癣�{U��q�̛7O�---,Z�Hf���,UtN	�
LbfwAARSSq��!|��g�Jѵ�d��z�:����x�WE�*\�pÆ
�w�LMM���+V�\�f�8y�$�/_�Ν;#??~~~ptt��Ç�n������z���@�zr$?3�fbV�'�0��d^��:ʖ������٤͚5�ȑ#q��
$&&"::лwo�2e�.�f�B��H���B\�j##�r�++�8L�:O�>E�6m��@SSSl��G��;wV�~�8KJJ�����w�b������-�\��v��I����;w� ..W�\�͛7e���퍉'"66���J���aÆa�СbT��7ssst��������B�F��������m�mڴ)�XU�_y�LQܪM�RnU��2�s��e� (]�	(}DWUuQ���۷o1c�>|���������*�^��m\���p��~�SB���J�͛7G߾}�o�>����!���˗AAAhڴ)�ҿK���"~���NNNprr�ݻwq���ݻ���9rd�����)?~�[�n�{��[�nI�idd�gϞ�رc��,���)���q��u�k����*)O����q��!<x�.]B�z�гgO~{��͑�����4o�\�X�1Y�tB!ʫ֙e�>�_�~�v�BHH5j��G���Eqw�6l�|E��^�zhҤ	lmm!
�d�dffb���b�<x�[�F�֭�������b1�Dyzz",,Ll&���_�ٳ#G�D��.:*�oGGG�qN�:����
W�TU���3Eq�%UT]nU��2����S�@"�.��zU�U


�l�AAA����q��=������P�ʾWm�4{�F�dn/�b������)��h���])Z��'�κ��#66HJJ���mpvv���:���\�m�����g?���P�Jybb"���p��m��B�o߾Jg�'%%���iiiزe���0}��
���_(�Cv��u�Ν;2㈪�<I�w����>Z�l	ggg�:u
�������&M��ۿ����+��4nB!�W�3�������ߣq��
{��=|��w������ѡC�2����Bvv��eTd��X�v-����� ��ڵ��ѣѪU+�h��۷�/^$�1#F�����q��\�x/^ă��c̙3��Z�~��舍7���pqq�	�h�LU�s��3Ep�����Tu�Uݎ�ο�����Zu�����������l�2���9ʼW�i733##͚5����lTE���!::C�(MMMEpp0���p���
��%����w�^L�<���|Zrr2֯_���DGGC___�2nܸR�����`oo/��
P�ĉ8y�$���1t�P~�իWѯ_?~0


p��u\�~{���˗��'��۫��T�&׍�L���8q��/_��˗KmOJJ���-<<<�f��[�N�o�������q��)<}������������#!!nnnb��ׯ��s�VX/777�9s����ԩS��A�I
0��<IM�6Żw����###;vL�<&L����P�`@Ϟ=q��$&&J�gn���1�B�W�3˸G���^䕟��o����������T澭[� {ʵ�����V�ر���êU�0i�$899��n+))�����&N����@ܿ���*z�]�~�ԫW/��ɓ`�������ׯ0����T��*R\\�����aê�ܪnGU�/�1����_V[]�ѳgO̚5�q�F���I��{U��q��ܣ(�$*S?R��Jѥ�{��T��F���e�Z�`===���cǎX�v-?�s��A����/_�v��AGG��%���)��*��SOOprrB�&M���KKK�Z�
�x��
"((���022���&`oo�={��5cJGG5j�6m
0>>>R���<I��χ��	455QPP����nX��ىm4h4h��3��
�!��@e�Pd52ooo����Sj>�;x� �,�>k�,��������r�í&7q�D�m�o�f����X:�\�j����_@�J`���������ӹ���IKKcX�F��4e�MV�F������3lذa�l��ԪJ��YYu�e���kӦ�X}�-W��TV������Æ
��<2kkk�����(�����`FFF������2�Ueڶn�:���ݛI����ϒ��muȺ�^Z)�Tu�-�K��tYi�:�5��I*�իWL H]�Ƣ���@ `...2����3+++���>�ŋ��ʊ�ܹ���I�D�'��jW�u��ŋ�q���ׯ�r�
���cgϞeS�Ne:::LKK�ݸq�?��ѣ�ԩS���1�������%K����T����Μ9�:v���+V�S�?�����������޿?��M�6�1cKMMeEEE,11�����]p?{��?��i߾=���`��٬���ݾ}�
4�`�G��T��ծ��@�YXX0��߿�c�-�Q�F

e����R���Yy穰���z�������2L[[�]�pAl?e�Uu;$��.U���M��q�Ʊ��$���v��u֯_?��������*����e�1~�W�Șr�Ue�&:h7h� v��M���v��=6z�h֬Y3�~�h�L���ޞ={2,%%E�;w�0�[�ne��{֪U+�=)9�۵kW@�{�<�&ihh�ȼ�S���"�XQm۶e���
ۿ?{��y��(�o�1X��sZ��`�G�޽�@ `���,##����d6m�4&�����]�#''��}�����3�@����O����没C������i�ׯgÆ
cyyy�U]"'�>!�V��2�;~�8���+�����Ol�@��m`` ?H�ecc#��D�g///�c��wٲe���C��c222X����<��Ą=}��R�&�.Q�^��y7�)���^�yR��9O
6�y��l��n�<�I�TQy��N���-[J�Qu]M�Իwo�}��gR3�}�*۶��X֤I���۷O��%y���ɫ���iӦr}�5iҤ�<ƌÀ���޽��n``������]���w���,==����0WWW��{��������,<<�-]��
0��l�Rf޻w�j���)���d��oTp��7y?O�4U�Ӛ�ˈ<֮]���W����fG}�D�fܸq2g�s���YϞ=٫W�ثW�XϞ=e��%�G�'��j�?X�c���g�&Mb���L[[�5nܘ
0�EDDH�[�?��/IQQQl��I�&LGG��k׎�^�����K�[^�����U�V�o�a'O��ٞ�{��.]�0]]]f``�������/��i�߿��1�߿gK�,a:t`zzzLKK��iӆ}�����ו�7�vI�ft��Q�c�)�ɓ'�믿f���LKK�}��g�곲Α��kѢ���e+W�d���2�l��n���2�$Oy!!!�C�L[[�}��glƌ�իWU^���%$$�-[�Lj���Ue��g�ؔ)S������b�۷g����EU�eIue�H^u�����r���W����w��ɀ���ܹ#s�z��1�&I�ݒ%K���,�~�~�������Q��֭[�Ǐ�*�o�1XV�sZ��`�Gqq1
���͍��ٓu�֍
:����O��Qw�j���3[[[6{�l��F(�y��y�������Bj���1�J�V�㲑��BH��ؾ��J{7n\����������#G���������*CCC*����t4k���� �*�e�-k�h�t�n�he�M�v�{���ʜ�ڀ;�B�P�ﵙ���B!\]]e�N!��Bj��j]
�B!�h�hiչRtU��u#�B!��2B!D����k�LEEER�CBB���GGG����#!!...X�ti�e���(�-11hժ�R�߷o�s��|ڣG����R�����?����?�j�
�s��1���Ri�[u��u#�B!��2B!D�fΜ�ƍ#&&_�5��␟��s��aڴipww���֬Y���۷�S�Nطo�(`Yf̘]]]�޽���������g��o�xzz�]碢"$''㧟~�…�g�淛��(��P\\�;w�`„	شi�_ZZ��q��G�Fdd$rrrPTT���D��nJ�~�.5�n�B!�bZ�!��1311App0F��3gΠG�R�����K�.��V�$$$�=�(���նm[������k׮�ڵk������ŋe�Q�@xyy�q�`�…�:u*������/��e�p�<|�W�^�֖,Y��G��޽{8p�T&&&ظq���[u��u#�

������A!��jD�e�B��9::��͛X�~="##����
�{��X�` ���Ǐ.cҤIh۶-֮]���X�������Ǐǂ���+w^���022���5<<<�f|��)S����_~���݃��.�w�9s�`Ȑ!h۶-&L��;v`�ȑJ!������q��Q<y����hժ����h�"�lٲR�V�jr݈b�9�#G����B�F4XF!�����2c�ɒ���T�{�F�޽�ڷ���N�0&L�����]f<�ƍc͚5
=��H��k��c��OѺ������K!�ՠ�2B!�Bd3f���@��fϞ�^�z���%P�B!�Bd

Ehh���A��BCC�suW��$�YF!�BH�B!�"+!��K�r!5W�
�ї!�B!�B�mT>X֫W/����:[B!�B!�B�=�I!�BH-�˗/���iQB!DT>Xv��E�?^��B�cL�U �R
nܸ�m۶��`�a�ر���D�.]�]5B!�V���e��!�T���`�YA!���<,[��F�������K�.Ehh(����\CB!����0	!��)�!U+44�V��`ee�����2w�ލׯ_�o���ƍ�?���w��̙3��.�BH]C�e�B�333�=Z�� ��=z4z���j�*YYY�ٳg����-Z���S�NEÆ
��JJJ������@[[�[����3�.�߁Э[7��~�)���p�����Q�F��NB!������߿�/��B,��(JOO����<y2lmm��zR$�T*s���ݻ�0aZ�l��Ǐ�^�ze�[RRggg���   ]�v�D��W�wd).!uO�^�ЫW/uW�B�dggc���HNN��RSS���8�A��m۶a߾}�~����}�6n߾����Q�ӧO#77W�5���-�����#GVq�!�����Q�:�ᅲ;�O^^nݺ�9s� ..��kV�:t����͛7�x�b��^�r)))����������]�`�ϟ��[���͛�!��������A/zѫ^Q~���Crr2LLL���X����=ž={�}���[�nEll,����x�b�����bbb�۷�*�K�!�B��>��e.\(w;7��1���tl۶
���عs'�w�^U�2#G�ď?��#G���ή����O�b�Su�(�`���}!!!�!u
��~*AVz||<Ν;���A�N��;w���7���[�={��E�
J IDAT/֠AdggC("99���5jF�%������Ruhժ��>�BQ����U^h֬fϞ���pܹsG�U��A��_~ALL޾}�-ZH����;DEE�~��2d�jY�(.!u�-#�j9rD�U�U^�|	�t�L�W_}x���6g�����|�2._�L�4	����_�>�߻w�@fL2.�ۇB!���3�޾}�_�/^D^^Z�n�	&����� [nn.�7oޠE�<x0������@�N��u\l/���_V|����			���E���1g��YLiiiؾ};.\����<888�m��<����Ð!C�cǎa�ĉR����_(**���#�%Oޢm
����aii�;v��VV��W�~�`��BQ����QRR"�6p�@X[[��8z�(nݺ???�߿�f��c�ihh��8�\�!�BW#�rrr���/^�iIII2�


0}�tܽ{�OKIIAPP�m۶rڗ%==���+���Y�V�kڴi����������())�����A�I�&�w�ԩS��ɩ0oE�?r�H��� <<���RQܝbn��2}��달�,~0J�@��	�˩��).!�ׯ_���M�4����/^`���044ĉ'�۸q#���PXXWWW>��*gC�纬G�tuuann����ש���9�ܹs�l���l�k�pvvV�&IE��s��e��7U���O�>�͛7�V��ra!8prr����޽�3g�`�޽��Q�7o���Tddd�y��b�s�B��B�_��/
����P�fq��ߏ�w���/�Dpp0�\����t��qqq ~�/����ʊ
0ǎ����N�Z�����#,,111�4i��+���˗/ajj��{���}��a�y��~hݺ5:w�����v�X>ׯ_����Ѿ}{t��A�9�����U���V�"�p��g
�K��-11бcG�߿��K���.]�s��!''x��m�VT�>�X�bE��7����\̞=,@tt4޽{���$$$`���pvv����]M���o����=`͚5HHH@QQ�v�Z@�޽�}���aee�C�!77m۶���%@[[�ߏ[�ٳgR�qi���B!D~�6X&:%�H�d�d Tmmmt��K�.��722@����%455aaa��+W��le$%%�
�(c�…033���.?�*33���]�{{{�cǎ|{�,YRaފ���#)o��/@V��uss{<���%
���t�5
���2�8��\0\8{���1�3�%��V�`�;'!!���8x{{�y���p�q���8::(��RWTG�����ҥK044Ċ+�+W�𳬳���h�"ܾ}�J�QSI.|cll�/|�������	033�˗/1i�$X[[cҤIx�����|ܾ�n�:����Ɔ�!/�JyϞ=��=&�K�#�B�bj�c��1.�)G�"��s����̼=z$w���999�r�
~��gx{{#33Sj%"y�nݚ����x�
�qSn�$�d�eQ�������?���g�"33���ę3gаaC4H鼁�8����H0\NE�L�p	���z�1  ��[�n�֭[��EEE��b7ԥY�f�?>N�8�{�:��ŋ�f͚aϞ=b3ԍ����ߢA���󃟟����X[���oT��A�F�a�����p��y����y���ׯ�L��_��+tkii!$$�Eajj�޽{�i@��M�7oFtt4&L� V^tt46l�����B�ǣ�˔	���]V�R�}$egg�[E1���ppp@�6m����@��2�_����2��6_^$ۢ�U��Q��:::6l��ߏ�'Ob�ر8y�$


0b��,e�V�Jy��KV0\NE�L�p	!\�֭�ҿS�Z�E7�'�{J��X�����bbb����V�Za„	��5�ɻ�Mew	�ȑ#ajj�?�/����^�BXXLMM�n�c����2C9�رc�C�v���Ϝ9���P$%%!??-Z����=fΜ)3�"���X�v-.\��������3f̐�)%o��CY6oތ��p899aΜ9��M5jܸ1.\��V�/��<���puuE`` ^�|	�7o޼�iӦ)�>%�Bȿj��2SSS<~��n�B����[�nI�kdd�gϞ�رcRRU�[uQ�q>


0Ɛ���oWd�$SSS$''��b��eM���L�]\\ 
q��Q�;G���+U��<�j%)W���7����������Fbb"<==aii���`���\8�1�{�?��3��FY��ݻw�������#,_����6l��=P����������
W�^EBB��L넄�|�=z􀩩�B����Y�E__�'OK�G``�XZjj*8���L>.��|||
�t��ȑ#�z�*�B!!o�ʞ�_~�B�;v�c���7�����?�P��	�B���M͵#�Bj��6�v�Z$&&����o�����۷/��Ѥ�$#--
[�l����O����ݍ�/,OII	�?�իW��iӦJ�~���!99�֭S����_
�46���QTT�;w�য়~��XE��133C�n���DDD��ڵ+,,,*��$y�JR$��(.!/�`�e��g1QU���h,�nݺaРA������&�L�"��"���ݻo߾E����(�1Tn�ʣ��]���Ǐ��s�1��݊�7--
�Y7��?�/FLL.]���~�
�A/Eܿ������EPPLLL���K��s��9�P(����n���8��oj7===�\����HIIAJJ
��ñr��rC]B!�b5rf���q��)<}������������#!!A�.Z���1w�\���M��ݻwpqq����xGVl�tPG4f���=��°y�fl޼dޕ����Μ9����9h� �;�i���#G"..6l��ؔ�[���֬Y�u��I
(ʊA'z�ٳg�s������ʫgϞ�p��ʦ`���m��W��P��+((��\��|��wr�����N�:aڴiR�Dc166~1��Ç�ĉ���/^,X������?NY�w��ΆP(Drr2���1jԨrc��ۣY�f�����󡭭���"DFF���vvv
�WSS����>�/KTTc�w�N�<����ի������?�۩S'���`�̙8w�f̘�P���C___��۷o��E��~�3g�ĦM��f�*���B!�Q�`Yyw����m۶!**
��ٰ������/_.vAްaCa׮]8w�^�~
}}}t��ӧOG�6m�}�ϟ��۷#55��c@i���M��?��&L� 6�`�ܹ�W�"##���+++,[��V�/ttt��[��̙3���A�>}���ӧO�{�"�eoo��͛#--
͚5�g��"oQ����H0\yQ0\B>>�K6l�o��ի��ʬ�XU�pu���Č3���3<X�MEc�GQ�,ZU,�ggg�޽���ppp��K������S�BSS�b�544ċ/���"5{�#V޾}��s��\L��x��H�7n��H���C�1㬬,����e˖�6Z��npuu������A!��)5rfP��������RRR-Z�K700��y�0o޼r�8p (���?HzzzX�x1�HIY�����t}}}���455+�S$��P�@����7���L�p	!�V����˖-���֮]��M�J��Pd1E1�w!U-�2b��ݻ��p��	ԫWOlQE�۩S'�x��.]*s��Ν;�8q":v��@hjjbÆ
�w�LMMѧO�n�;vĘ1c�-�,��ε� w���CWWW���!??;v쀯��T^��
!�B�����Ύ�s������<y�?������R|��
�|�%��G@@��d���غu+���!��d��*����)��b��,��i׮���Ú5k���]��رcb��^qqq���|�	����HD"Pt!nq���@�۷�����dllkkk��� 11QQQ�ӧ��J������-
eΐ*))��;�Ð!C���˗/(�6g�����ʤ�s���׮]��C�2�=��y���!����F����E�B!�cV#˸��׭[t���G�F||<�6m*׋EP0\B>>���
�Y�E��ɓabb���t~��b,ܪ��6mBjj*���a�XYY�A��/d���.@iL���bxzz���@*Ι"��A׮]���xzz"""YYY(,,ĝ;w0g�\�|={��O-66HJJ�ҥK�t�ˊ�^����(,,ĵk��߿�˔��?~<:��ߟO��o!�Bd���ar�O�<�'O�����|�	lll���%v��EQ0\B>.�,��.����b�
L�6
���9r$>��s�-�2q�DDFF"!!C��Wt���.d���.@�B+���x��5LMMѽ{w��.>�n�:̘1�?����Ty}����ի�7���lj'�|�r������Pt��Aj��/���ǏW�Lyϡ(MMMx{{c��Ɉ��ŭ[�йsgZ�FN�Ǐ;W�B��j�`Y�z�(X)�R�"��!98�=W�e�Y�ER׮]1f�<x?��3�m�@��X�7o�ݻwc۶m���E~~>ڴiOOO��׏߯��(��>FY@@\\\�bf)��L�fͰo�>�����Ɠ'O���kkk�9Rj0(]i������(..F۶m���'O�   Th�����1�;w�_Lf�̙���U�Lyϡ�N�:aĈ���?v��A��!$$D�U ��b=z�Pw!J�`�,�$"88�Ǐ��J�N!�z|l��[{	�
;v�@`` �9"������1m�4xyyI�Ͳ��J�^�ihh@(�7�BCC�\#BHm֣G�����~!��h�5rf!�B�z8~�8�B!��4-|�/eW@%�48FH-F�e�B!)n��������p��믴���?��eH� ��.U6XFw�!�z��B�e��7�B!�T>Xfff�ѣG�:[B!��^B��h�B!���|��W�^�ի���%�B!�������_���˗/����B!��q��BQZ
�BHE���{\�p���R�nܸ�m۶��`�a�ر���D�.]�PSB!��UY̲����ʚB����8r䈺�A!��p���<,[��F�������K�.Ehh(����B�ZT�`��!���UXXH�e���j���t�'���
d�Ҫmv�ލׯ_�o���ƍ�?���w��̙3�X;B!�zT�`!��W�R�pi�?>,--�c�@nn.�7oޠE�<x0��������QRR���DDD %%���hݺ5���1|�p���ɓ����������Э[7�|�駰�����F�UMgB!5�G7XV^ �s��!<<w��Avv6ڵk8;;�EA�u.D/�8:::hѢ������	cc��b��Iw���.D����G��|}}����B`���{�.�OJJ
�������m۶�^�z�m۶a߾}�~����}�6n߾���>^�"y�r��i������Vj���-�����#GV�3!���,++�inn./^�K�.��'$$ !!AAAX�|9����u[yAe%�իWéS��m�6t�ԩjI�&�r��E����!�^�za����F�baa��� ~v���q��]|���F�֭���3�Y�qqq�g�����n�
+++�ĉX�n<��ɛg||��c111����K՟K�����2B!u^ٷ�꠲�����ҥK044Ċ+�+W� <<������ƢE�p���j�q�Uֹ����󯘘�߿������ŢE����WM5�8q}_�$��A��E=���R
BCCq��uWC�����^�����أ�����5k����������ʕ+'N��mР@("$$���5j����T��ܿ`nn.��U�Vb�B!u��f�ՔG�.^����h4k�{����`ll�o��
4�����������~�tuuѮ];���/���p��1zT�� ¤*�j̄T-nQ7��y��9���I�=��3g~��\�|�/_���?&M�WWWԯ__�<ey���?¥q�B!uY�}��۷���_q��E���u�֘0a�����U&��c����be�Ǝ�ڵk'��������={iiihѢ0u�T4l�P��˗/��������0f�L�>X�~=������
;;;,\����b����`ݺu�������D�-*U����			���E���1g�����
@+O�e���hkk�����ވ��,S�~�*��IKK���q�������_K�������!&&���hժ&L�GG�rϋ��SaB!���u�<�3�+�1Vn�������5Ο?��G��֭[������1k�,��HE�ECCd�5�Ҹ}!����F������/^��Ӓ��d(T6�)�heϞ=��G__�'OK�����ɓ���̧���"88qqq

��s6l�ǜ�]�v������|����q��qԫW+V�;~�����^~~>N�8��7ob���000P�^ӦMCFF���ÇQRR�qEy*��c���C>M���ӗU�,L�4	/_��9u�rrr��Z�{�x��-̣G��|�rcذa2z�j�SaB!3###<{�ǎ���Q�����	NNN�{�.Μ9��{���ח�[�h���7o���Tddd�y��b۸��tB!�.��1˄B!^�xccc!662g~�2
ƕ+W�.]��L�;}�����&&&
�q߾}HNN���	_��@�ѣGسg��1�����?p��%L�>�n�:hjj���È���ԩSQQQR�s��cccccc�z�
���T�������L�4	@�ʠy�X�<�:�h֬�����<}��v����/_���{����ۢ�UY�޽{��[t��aaa���ˆ#AAAe��"u
B���(,^�p��A~?y�R�Ɋ[TS�l�!��LܫgϞpuu����U��2$�V��A��W���1`�,X�����ʣ�����`޼y�7o=�\C���@i�ܤ�$#--
[�l������ΰ��¡C������m����@��{e��f�q�n�W)��T}���V�'�B�j,S$*�Ͻ��:u�mmmt��K�.�ʷ��L555�>:�Yu�ܹ3?���ٳR�,^�m۶���\]]>|���7��͡��www�޽�<�������ԩ?[Ht0D�z-\�fff����g�dff�ە���TVqq1@K��I���O����v�?��퍎;���%K�H�U�_�x�`�����A����A||<���O������A�)�0!���WYܩ>�X�bE���T��l��JJJ����s��a���b��RE{�U�,X����c�֭�y�f��$����V�Z!!!nnn�ѣ
�������ܹs�}=<<��d������
�ҵkW��lڴ)��Ņ�Y�=i���(U_.�w�ު�B!�F���arw����+�tыNe��ŋHII�����}c������=F׹sg�}�:�z�J*�;q��B�nݚ�Y4��$kkk�߹GEWU�^��s� �*���,��A�O��ӗU�n.�N�:�'�^�����]�BLA�	QUbI�~��6oތ'N��G�>}TV�<d��:-���)))X�r%nܸ�]�vaժU
�W�s%��0~�����r�;���y�5l�AAAصkΝ;m�kD IDAT�ׯ_C__]�v����ѦM~_�?{�U����)'C
��`[O}��05Ő<�y´]ZhlQ�]��)���xHP�ܦ�۳(���e�H-�L-A�����3��00���uy]Κ{ֺ�5:���eccCbb�Zj��Ņ~���i��344��+W���Kqq1�&::�Ç3q�D��>|�f͚��s�=V!��nSo�e�B�\�T_A��2�֭���G��r���o���_�k׮�]�V]��OuB�7ֻ���j�4WSiː�W�/���:�5��T'O��
[0���˺�����ܟ�:���E]!�"��RJ���ё��P������,������m۶���[�;��Ǐ�{$u��qppPo���R��&������mM�6%  ��kג����)������ӄ���ԾB!�E
re���?��#gΜ�g�Q��9sF�mm�2���$���:t�ZKQVV��ի)//gذa�D���3/^�������Km���`J_j����u�S���_��n��~��KII				xyy��M�!�.����BVV'O��*l��v��8��?��?�̅�ҥ�����"�RDX4T�$��ݻ�m۶��STTD�֭���bƌ�2ij"muۍ�Wu�Ć��֤���?�]�c�:6��۷ogԨQ���h�(|}}�r�
۷o����l�C�ݼr��ڼWʹ\�d	���g�̙��9I�

b������3w�\���B�6m�0a��{'�BԏY�_Y޽x�b233)--��ٳ,^�X�mm���ݛ=z��o�Lrr2���������2k�,����۷/�����ɚ��H222(--%##C�c]�sx���q��)"##��%�u�/cα��U���?���d֬Y�����m۶Zc6���˺���?T�?'O�����o�����{O�m]_�E�t�Rrss)**�>���]-�O]!�"¢!Rcw����Aii���$�|��'���[�8q�[�nQZZJnn.[�laɒ%�޿�L��/�vÆ
\�r���5�v֬Y�J_^^���Y�t)]�v5�1j36���+���\�|�����222����g�����,�Cq��E@��9�FRR���ܸq���>��c���R�INN6x�`ooϢE�عs'999���s�N-Z�UNA!���5ȕe�Ǐ端���ŋW�688���L5�+dz��
���hӦ���ɒ%Kx�W����B���;Cu�<((�}��q��e5uP��ꪳ�u�G�.]3fL��˘sl���EU)_����Z�.��ϐsY�0a{����j�)TL�U�4����ˤ������/����ԩS�|�1}	

"22�%K��§Yw�o߾<x���L�z�RDXX�fb��K�֭�裏�׿�E\\�Z{���@�d����iԨgϞ%$$�Ç�z��2�_�+�4W)i��Λ7�:p��%"##��ۑ#G����kkkk��S�Q۱i5j�|�
�w�֪��(�j�WEii)����V�{�6�x~��wiӦ
+W�d˖-�߿_]
dh갲�W��O?͌3ԉ�3g�,�Bܫ,���ĉU~����'66�#FТElllpssS��j��2
�M�6X[[�����ׯ�Z�J۶m���V�B���ƍy����ڵ+M�4�iӦ4�U�V���\I{�Y�n�G����	kkk���7n�ׯW���STT����������ĉY�z����~s�
U�{�����ڵc�رl޼Y�^���3�\�Ÿ��숍���ߟ�-[bgg�s�=�&Z�v\5iժ�֭��LJ|[[[:w��￯s���}���#""�N�:agg���:t 88���~[m7x�`�4i�wbA�s2&�����C���7�ХK�������T_+��DZC��/�}����ښ��z��+W�L�����&///III������JII��ɉ���ת����<<<�ܹs8880y�d���o��۷���^���~�������`ٲe,[��q��Y�;B!D�j�+ˠb+""Bk[NN�[���^�B��ƍH``��}l޼9s��U��V��IAc�7oޜ��h����sl�>�z/L-�mL�\0�\�{�PQ<7,,�������񝝝��N�ٟ��Ka��{��5fϞ���}u��&���~������E^^���
�.]bȐ!zW��&��6c�dcc���/�֭����x{{s��Qn޼ɴi��ڤ�Mۆ��CGGG�~�i�N��U����L6l޼9��#��B!��i��e���������0|||h֬�.]R��>��S��������74���>����ŅСC�v���ѣ�}��	�����kjZ�[�~)ǪNM��X�`AAA,^���-[���q�ڌ��_|�
6��_���MRRVVVZ�U��WC/��c<5�H�B!�i�d�СC�����<jٲ�V�'!��K)"��믫�:w�����˥���Cc�������e˖dee�ϗ��bc��#��7jԈ��r


h֬`�J&S��I��ԩ����_����H�~�i��ks�ڌ�2ggg<<<HMM%33�C�1`���ȺN�6�x�"��B!��i��es����Օ={���O?Q\\��?L�޽�2e�֗Y!��M����o߾lٲ��K�I�-X�|9��������;v��>�,YYYj]M��%�����+!(;v�`ԨQ�����hH��ɸ˗/���
T�٬_����p�Ν��?����M����Oqwwg���5{��ɤ�����Mll,����s�8�)c�gԨQ=zT
{�L�6���ƣOǎ����ҥK:�b�:l���dzc�KwC!���AN�YYY@@@���� �Z�K�s�0�w�P����ERR:�5���{���S��o߾���h�����Ufh��%�+���ޞ�¶m�5j��_�ڥ��fl����'''�^�����<���u�H\���GR�k綾^�t�w��^z��B���AN�	!�u��Is%16&&�cǎQTT�c�=Fpp0�
R�͙3���R>̝;wx��Ǚ0a?�����lݺU�䖡��={6VVV���p��m���Y�`C��vl��+44��+W�����BSRo׬Y����z�*M�6�G�L�>]��|Mz���ѣٺu+˖-#&&��Ǩ���Qj�������S�˜�>ƣ���������L�8Q�9I6Lbb��� �BhTnL��			�?^-�[��B��q�}�o���W�f�ڵ�رC+ux�ȑ���0e���9~�x�"�E��Y�F����WW;K��6*�h>B4h'de�B!�=JR�ko�ȑ�˭�h��5!�:�,۶m[]�Z!��+��LR�k綾^��eB!�}��&�d&]!���$uX!��8f�,�T;!�B��E����r��y:v�h��\�¦M�HKK#77[[[���0��c����`������9U��v�}]bb"iiixxx�"!��f�,;r�˗/7�n�BH�ۄBX›o�����,R���L�:���u[qq1�ϟ���ڵ��k����d�.�uN�:ELL[�n����1c����ƓO>i�	!�=���;�|����Bضm�|�
!������˖-����^�z���@ZZG���'�:u"''���3��N�8a�D�!n߾͂�M�68;;������}�v�W!�GuV�LV6!D�JHH`����B�wL��Nh����ޣE������SO���G��d-jݺu\�z��cǪ�ƍ��͛Y�n3f̰`���Rg�eB!�%4j���]�'��WVVFll,������`kkK��e�ȑj��&�*oW����d�RRR�����ӓ�^{�֭[�֐������Ʋo�>�_�N�֭�fڴi4k�Lg�����������o�>:~GGG~��W�]��N�)\]]�c�����/вeK�oߎ��n��|�2~~~�mۖ/��B�KZZQQQ|�����0z�h�O��͛7y���9t������ߟ�s�ҴiӪ��*U�^mٲ���(222hܸ1�>�,�f���޾�}EGG�s�NF���Y����g˖-���S�6�Gywww�l�B`` >���B�K&˄B�<==eU�������]�k��İq�F�qII	gϞ��ٳ��"����g׮]�����ӧٴi�N|C�޺u�ɓ'�����.77�����Ӊ���I�&Z����"??��bƌʔ)���{L�6�_|OOO�x�	lmm����2f�����������ܡC��߿��k>���o߮>^�f
m۶e۶m�;wN=7�w���ʊ�V9&c���p��M���9eee����m��GO׮]�6m_�5������G�}�>}HOO'99�Q�F���Bq?3{Ͳ���U>��~fϞ���}��aҤIlڴ����z��Cy/Ν;���;C������ה��1|�p���9y�d}t��2�\�����������˿BqS&hV�X��c�8t�aaalݺ��*�Zǎ#..ggg5IҔ�7n$++��m�DZc�X�v-���\�p������}������]ke�f�.c��/���6l`�ԩ0�W^y���D���ն�Ǐ�I�&:�R&��맵=33�͛7s��Q�O���%K������?'55U��R�a.�ڵc����2i�$��}�������}���X�B��LMM�s��:�Q�)m�B��}��������B���8z����222���#""//�z��M��ҥ�;w���ȑ#:W5?~���ڷoO�=��GR��0͑#G�f��$  ���xKw�b���Vy��'hҤ	�n�">>���,������߿V}SWu�֍��pfΜ���ujW�V��	�[�nt�ޝy���ꫯ�o�>��N�0;;�j�i�}||��������<y�S�N��7ߐ���'�|�C=D����g�ƍ=z�>}����ϙ3ghڴ��İ�0�q�����ի���?�7o�ڵ 00���Xu��̝;W]�9~�x�������iEBB�\�Rk��r�Y髦G}T��B�ڻ�V�U���ѣGqrrb�…$''s��qv��Ipp0�n�⭷���ٳ���{W�BY2�cǎj_���??���X�:�H!)GB�^yy���?��H�2�̚5�ƍ����G}��>XTTT��zxxh=V.����/&����*&�4=��S\�rEg��$MuL�Ν	f����ݻ�iӦq��E>��C�̈́	hܸ1�֭��ѣܹs�޽{cc��&�cǎ��5o'�С����j�Ն�1�	0}wS$$$5�~��w��nܸ��&��Mi#���,6YV߷�U�ȑ#>|GGG֯_����qtt���ggg^}�U�O�Ν;wX�j���{�<x0M�6%55�k׮�ms��
:�<��a�깇������W��_�BaY�E����m���aϞ=DDDн{w���X�jC����?��wyy��w��+�<�L�h�7�meՕȨiU>�~������իW�'((�(ԯpttdԨQ�:u���L>�ƍ��!砶4k�UB�<@yy9�W��zNy���*�$�F!̧��,�v�x{{ӻwo&L�@rr��I���BV�X��#�ݻ7ÇgժUZ_04_����i```��Inj�+��„	�����l�2�
���/��QQQܺuK��r���R>�������C��̛͛7OOO�…)((�y�����o����'���DDD�X2�_.\`ƌxzz2h� /^���ɐsl�>�����6�;w��Ie_~�%�������WЌ��ɓ'�VkU����z�j����ݻ7�����_�Y��ߝ�ϳ!)GR?O!���8880b�֮]�ƍ	

"//���(��2ѡ��…U�3##C��S���_�bR[gggN�>��VyܦM�*�RCƯ���7�p��%@w�(00;;;�n��ѣG����o߾&�Ւ�x�
��iJ�@�V���"�lS�!���9YVPP��)SHJJ"//������{�͛�Ӷ����ӧ�a��\�BII	999���1k֬�+�VV�C�iӦL�<Y����y�f~��WJKK�Ġ)S�PXX���>����D
���c͚5�ڵ�����$''STTD~~>�w�f�ҥ:�W��������#))�I�&i�<0�_!!!���STT�͛7���ϵ���r�kڧ>ʭ�;w�Ժ��P&����rjSLLk֬���˔��PXX�ٳgy��w���R繦����B����;�B���2	_�O߾}	`��ݖ�Y��jt	X���닻�;�}����<��㸹��+�Z�l	T|߹}�6YYY,Y������{dffRZZʩS����*V��V��IFF���ddd�x�b@�j�ʔ	�˗/=�q��LJ~ȅ(..�֭[:t�9s�0p�@�c>��C�����W_������ѢE���P�?��{�O>�Dݮ�F�LjR�i�j*��v�dY||<������jOll�ޕ_�6m�ܹs<��$$$p��qy��'IOOg�ΝU&�\�~��m��GS�j��SWIF5%�z�
�gU�E��޽;?��3�����w��I._�L�Ν�ҥ���Lm����<Kʑ�����O~��.\Xe�NQ5%`eΜ9����b�
�U6BK�}pɒ%��ߟ޽{�U�^������_�~�=��IGGG������`�ԩ���ҥKƌcR۠� \]]���fҤIxxx0i�$�\������ݥ:ʄ���Ç7j�$00���r�n��رc�ӧ^^^���dggӮ];^{�5��N�8Q��jȤ����PaN���̛7�F�q��1Μ9���~ff��k�mu9v!�����dYU?T�m���ckkK�=�?��~SRR���`nnnX[[Ӿ}{-Z@RRR�������Ǡ��>*�A����y���cgg���L�iܸ1�����%�J������d��S��$�4n�XM��\�f�9�i�U��пR�_39ɔ~UNmR
���Ǔ�������?'N��;٦���,)GBcU������СC���O-�;󩏐	X�QݿQ???"""�ԩvvv���ѡC���y���v�g���ߟ�͛cggG�>}X�`A�nj���������8q"�W��[G̐�>� �֭c���899amm����ƍc���ZɌU	

�m۶X[[�%1?�믿NLL^^^<��CXYYagg������
�~��:!��iӦ�߫KU�[t�֍_|����ӤI�.��ÇӬY3�{�z�B��ljnR����J���r4�o���#�ZNNN���/���о}{�m���)((�Y�f�6S�j��SWIF5%�r�
M����g�eٲe�۷���<���c�޽4k�L�vS�U9�i֬Y���ۤ������'�|¤I���U���,)GB���L}$��7GGGBCCIJJ�ᄈtw�*U�l޼�u��1c��N��F�Q����=aaa�
wEU�U͛7'::ڠ�ڶy��̝;��s�Vۮ�>�����㣳ݐ�+<<<t���DY}ծ];���U�՘������c�k7o�<�4M�6%  ��kג���������ӧ			��B!D����2cR���V�Kx�W�JS�b�u��
����ʷ�~��	�Ν;�	�ڦ��U�QM	=��cCS*���c����g����Cqq1Æ
Ӛ�2�_����PU�ڜgI9�a���_Y�p!�>�,�;V�JUcC>�i���g���9R�s���˸�����kP�KKK�����z����U�
Y�|�2={����O��}}}�ٳ'?���Q㕀!�N���\�~�������� y�������i�F'�L!D�4ȕe...��㏜9s�g�yFݮ\5�ԦM.]�Į]�LJ�2dIII���3t�P��W�ȗ��3l�0��Mggg.^���ӧ�ի����AU����壪$#s�����X~~~�����_0f������h��_JBӈ#8w�{��eÆ
DEE��օv IDATSQ�U�V���r��M�4#I9�~ܸq��� ���.��;w�<J�GVV��N	�HOO'..N�
��PTTDRR�O�fӦM8880f��������2C�aYӭE���ܸq�e˖еkW��P�t5%%33���ub���`,}!+7nT�/))��ٳ�={�����u���+���|��7ddd����gdvv6�z����Ũ������Nrrr�?��������f�g����ޞE��믫�;w�d�����!��x
���r���ŋ�䞳gϪi<��D���p���{�ܹ�����qwwW�^����޽{ӣG~��7���INN&??������[f͚EZZ}��ժ�e�� c�W�QeƜcC�{/�����ٓ~����d~��z�衳���24����8ϒr$��mذ�k׮ѥK�o�ΡC�Ժ1qqqj;SB>j
i?~<M�4�y�2Y��sE��gϞ=<x0���X[[3u�T��Ƅ�z�e��eªr⧲�M�Ym�x%`E������7�o߾DGG���eO?�43f�`�ҥ,]���3g�-U#��v�ʲ�����W_q��E����ḿ����Y~��0{�l�q˖-�q�~~~�i�F�¿d�^y�~��G������;�h��ľ}��|��N:���A�R��4�K22w��9dž��P�5���t>��@���9�Ddd$K�,щg��G]��}�r��A233u�-)GB�������O�8��#G�3g���@ń������!���*���өq���jH�̙3ٿ?3f̠y����q�F�=J�>}����̙34m�Ԡ_�����֭!!!:��EqvvPCQF�IRR#G�0�<K_�ʭ[����'++///����~�+���ptt$%%���Plmm)--%%%'''u��1㕀q71���X�QSMA^����5,L!Dݰ�ʲ�R���퉍�eĈ�h�����+њ_��5kF\\�i�kkk���b���Z+q�%�@�$�ƍy����ڵ+M�4�iӦ4�U�V���,m6Gb���+ɨ2cα��z/^^^�jՊ?��GGGu���eLB���8ϒr$��)�5}~��aHH˄	hܸ1�֭*�i޹s�޽{�ԭ���,ݷo;v��֖!C�� �E�\��Li��z��/d�q�Ƥ����G���U�|}}���S?/�=�͛79r���Ę�J��B!��� W�A�VDD�ֶ��Z�n�����7�x�7�x��}V����*Z�� c��W���톞cC�Y�{�#����j�e�~�a	M�^o��,)GBԍ�תKìm�Fu!���8::2j�(���T'�jZU���

b��Ŵl�R�"�1�(ƞ���r�5�.�(�xxxp����Μ9êU�شi3gά�F؋/�Ȇ
���/�&))	+++u"L�Su�WV�B!4Кe���W�H���QVV�O?����Q��q���#!,���W��֧�z(������z�/�*�����غu+G���ʊ�}���N�:Hyy9������i=��i׮]:I�'N� ==]mk�yP&�


�m5��2%de�ڵlܸ��� ��򈊊��5���xxx���Jff&�b��ZI�ƌW	OQ�T4I��B!��A�,:t(�}���:R-[�dڴi�uKR�����}��e��.]Jdd$-Z�`���$&&���¿��/�v���H�y��t�¹s�
�x�x�w�ԩgϞ����C����g�}Fyy9ݻw�E����ɤ�����Mll,����sd������3w�\�q���6m�ħ�~���;�W�6�<(�'w���Q������]___���	c�С<�����@�!+PQ���ѣj-��uΌoǎ����ҥK:�b�"�m�V�G!�B�[�d�ܹsquueϞ=���O���ӻwo�L��u�X�{�f� )GBԣ�_~���222x����L�4%�Ð��ĉٶm`\����=.$$$�m۶1j�(u�1�(��///�o�Ntt�Z&@	10��!+Pq^����z�*...<��3Z�3^	X�ٱc;v�t7�BQ��d������h�ד��.��/Dݩ�3�U�V�[�����;FQQ�=����4Hm��|����\�~�V�Z1h� �N��7�#**��������#�?�<S�Lѩ�5J���z���ѣٺu+˖-#&&�_(ʚ5kؿ?W�^US6�O��c�=f�y�={6VVV���p��m���Y�`C�1��~~~��ؐ��HVV...��׏���j_��(������O���1�<x0���>|��'j�GV�o5վB!Ľ�AN�	!������"YCC>4��p��ڵkG���u���"ʜ9s�3g��vCCQ���`ooOXXaaa��.BV�M�VmiC�++�*�G��t�w��^{
OOOKwCa�Y�_!��r��u�����,jGV�>۶mSo�Bcl۶�˗/[�B��2!���м���͍�Ç[�7�	XU�����B�U. �����d�|8!��qrr��͛���������t_��!�Bu0Y���Ibb��w+�Bܕ�	iIJJ�ÞCH��B!���0�B!�fq��y:v�h����݁�/0Ҧ.{���'&&��������I!Dc�ɲ#G�0~�xs�V!�����-�!���7�|��Zl2�nq��)bbbغu+���3777�|�IKwM!���V��/kBQ��b�B�9x𠥻��ݾ}����O�6m���c���l۶
{{{�P!�m�B!�1r+�uk۶mR׭K�(��֭��ի�;V�6n�86o�̺u�1c�{'�B!�eB!�	������K�����^z�^�zY�w���2bccINN&''[[[:t耯�/#G�T�U5�Vy��855�%K�������������k�n�Z絆����'66�}��q��uZ�n���7ӦM�Y�f:����%44777�~k����˜}�v�ZRRR���hݺ5C�aʔ)���U;�իWWۏ�ׯ�r�J<��۷�f޼y:����ٲe={����I��#����Ζ-[���iBa��d�������7nL�v�?~<Æ
������`�;���feeE���y��'			���v�:w�'N䡇b���XYYUٶ��___rrr����G��>�!�=�B��~��鉧����!�Zbbbظq�������g�r��Y


L�}����g׮]�����ӧٴiF��u��'O&++K}]nn.			���G�&M��E~~���O}�ߘ}3}�tΝ;�����!..���Lbbbt�K26���4i���궯�������_�5������G�>}����Nrr2�F�2�!��3U�0܃�|�M�~ �����,\�Pj0����������3y�d._�\'��ҥ�;w��~�ȑ#ն=~�8999�o߾�&��R(vΜ9����b�
N�>m�n	Q�hԨ���?��H}D�m߾�+Vp��1:DXX[�n5y�G�a���;v���8����r�
�6m2��ƍ��ʢm۶���q��1֮]���3.\`���:�m߾=������׺8x��	�q]�ߘ}oڴ�s����O�������ILL��'�$==��;wV;��|��dgg���†
8v���������i���
@�Νu�S�)m�BX�}����	��+�nܸAtt4III|��0�.�g��TC�/eee���h�"N�:Ś5kj��a�Q�F���c����_e���_@E��T_��B[bb��� �=M&ʪ�+��'NФInݺE||<YYYxyy�������P�֭���̜9�����Խ2����[�nt�ޝy���ꫯ�o�>��N�0A�F}�j���;%%���H�����ɰE�1r�H���tn�4dl`޼yt���=z���_]����h׮��~}�Q�6B!,�b�ewC!TGGGBCCIJJ�ᄈtw�
VVV�mۖ��z��c�r���:;���裏HMM�ڵk:u7�b��СC<�
�VZs�B�Bh��eBԭ;vX�w�Y�f��o���FZZ�|�	�&M"  �x��zxxh=~��'��_Lj��Fؽ{w��O=�W�\�ٯ2�SC�omm͝;w())���Vg?EEEj;c����0b��}�p�Ic���Ce�Q��7M7n��[�L٦�BaY
�6�k׮���7�{�f„	$''���sծ���+V0b�z������Y�j���j����GUJKKhԨ��s�Wq��U�ϟ���ׯ�������Ny|��I����>}�I��~�:���4h}��a���t�4)W�n޼��\aa!���������?u�����o��鉷�7\�vMmgooϰaøs�Z���/�����R|||�/!�����iYY�W���Ϗ޽{ӿ^~�e�_���,[��aÆ���/�@TT�n���.0c�<==4h�/���Z���Pl~~��s#�B�(�j�nX�v���CDDݻw����U�V1t�P>��s�}�����]Mac�}ͻ��@oWc�V���ǐ�W���y��@�wf}rrr���o�s�O��a��Msߕ�Q���~��wޕm�~�BQ��m�L�2E�j���7UƔ���(//�ƍ,[�@]Vm�q���^~�e~��W��Rc��*#5���(��ŋhժ��saaa=z���JHH�����s�j�3��Q�HLLd�Ν�|�P&����(�jj�ZS
熄���EEE|��甕�H�X!��իW���IOO�������V�9WC�
;p�6�s����Krpp`Ĉ�1�s�αw�^6l�@TT��3�Q�F���SPP�&O�[������8u���_Lj����ŋ9}��VکRU)�`
C�߾}{nܸAJJ
���:�Pn��2t�mڴ�ҥK�ڵ�V����Ņ��,N�<��},33S�m�V������͛:ߑ��{��;!��
reY||<������j����X�i4�쬪�&e5���;={�d��$''cmm�ԩSM:.TL���_�
���p��!s�2U�b���Ә�U)--���w��w��:m~��w9|��z��H�!�h;t�@�����������'Or��e:w�L�.]�>U�SS՚R8�]�vl߾���T&M��s��P��7�|���OAA���Z+Z-EgjGBP�%�������g�}Faa!�?�8nnnZ��l����w��m���X�dI��}���̤���S�N	T��0����PQ�+##���R222X�x1����q��EK̀'C��s����O?���~��;w�p��U6o�̚5kx��������zl��=w����|��Ǹ��kݑa,�?����<y���R���[�{�=��;v�ҥK:�)۔6B!,��&�4'���>���r�Q[[[z����u��Y����
kkk�`'@RR��}���橧�b�ʕ:W��9n�Ÿ���xxx謤2���Hk�O�@iu4�?9w�L�<Y����7ڷo����:	y��u�vJ1Z[[[�-�N�)W
+����,�jʿ���TY�Obb"���;����8qB�d�B߿k�p.��}�t^3w�\\]]iܸ��b-//O}^
�
a~|��'���3o޼*/�ԕʷr%''3t�P���ƽ�>�k�ggg5E�v!�JPPK�,������[�N��ҭLVEGGӯ_?F�M�-�ܯ��#���xxx0u�Trss�ҥcƌ1�mPP���dgg3i�$<<<�4iW�\���U�hWe���Ϗ�Ç5��#G���AII	�1C��W�^:�e˖Q\\�/���ט}�裏�����	�ի���O?�`���5��*&L�cǎ���2m�4<<<

�S�N:m����_u�l3dRR!D�k��a*WV*����0�`gU�/�yyy���+\�t�!C��-Ƙ�*Q+��\l�*#5���(����5���<���L�:U�Rw���J�	}�0-\��ϲl�2���G^^���w�^�5k�u��^M-�kJ��:�Wn=�<WR(V��t�R���ݝF�\��.I��$Eԇ�&}������!11Q-����B�~����ٳgceeEJJ
�o���ݝ0d������b�…���������?ϔ)S�~f��dݺu����\�~�V�Z1h� �N��~�Nhh(+W�$77W��f������پ};_}�?��#���4k֌'�x��sC�ݬY3���X�f
�����ի4mڔ=z0}�t�[;�aggGll,+V�`�޽0`�����믵�<���h>�ĉ��;|�0͚5SW�	!���z�,��%:%�e�+xiJ�Κ888�`����X�x1-[�T�o�r\kkkJKK
*���e��w���$c�iL�RMƮ
0�OC�����1|�p6m�Ğ={3f{�졸��_|Qk�^}||����|���9s�U�V�i�&fΜit}��
�j�B��߿�¼4/���������3Ky�e������Ƞq��<��̚5{{{u?ׯ_g�ʕ<x�۷o���gMj
�Y�v-)))���o�nݚ!C����_eժU���r��-}�Q&N���\�_M?��DZ����������ի)++#66���drrr����C����2r�H��m߾�Q�F��⢷����/W�\a����<^CBP�^pœ��Zձ��',,L-��{V��͉��6��m޼9s�έ����ハ���vC�ߙ_z�%�R�
ݷ��o��o��F��^[�sM�65�kڴ)�]����lڶmT\P=}�4!!!:�k�BXF�\Y���?�ș3gx�g��gΜ�i[W;;u�D`` �ׯ'22���~Z늚1�}��G9��N�ϳg��5��kM��1J�1�k�������/�`̘1|��:W�bH1���p��²j
�0Gp�9gnܸAPP�V�.��;w�no2Fm�P\]]qww�o�!##Ck�sFF��������+!(B��&((�ݻw�NJ���ӦM&L�`��	!�P4�����ŋ��HϞ=��dL�N}EG�3y�dڶm��Nll���Un|��w���Cii)������:�4��kM��1J�1�k]]]�ٳ'?���������у���k�3G�WC��Vf�¹�I�X!�ː0M5�p��RW�36l�ڵkt�҅�۷s��!^|�E���;Iz�#E��ڽ{��v���RҘ�J������gѢE�ܹ���rrrعs'�-����B��� W��?������/ꍎ�́Ԃ��*�lٲ%7n��Ϗ6mڰk׮j�moo�…			a۶m�5J]�d�qǎ��
		Q�+)�����ؾ};����ry}W�
eL?'L��޽{9�<ӦMS�<X�dL]S��j��p-T������|h�Ws>�Ddd$K�,љ��WWO�u�������:Er
-�[Y߾}9x� ���:ǖB�BT�WwR�vS
�+!P�+..N+��rp
��������ښnݺRm��3�\2r�H����[�9��9s�~����+�L�/�֭[��Ǔ��������z?�^^^8::���Bhh(�������������Z�Ș�J��!z�駙1cK�.`�̙�~�BQ�,����+�������2b�Z�h���
nnn�k�/�J�΀�ڴi���5xyy�~�z�U5����m�kkk���уѣGs���c�kggǪU�

���	[[[���OTT���fϞ���?͛7��Ύ>}��`������������ߟ�-[bgg�s�=W�_�L���'6668991q�DV�^]e�3///Z�j������N�90�|T��Ϗ��:uꄝ�vvvt�Ё��`�~��*_��=z4NNNX[[���ĸq�X�~�A�s+<x0M�4����:�I�X!�^M!��(?#���Gǎ���5(pFsE�2a�/p��+N��4nܘ��4>��#ƌC\\EEEU�����צ IDAT___����ϴ�G�r��MF����5`�x%E܋�I���$_a����-[Ʋe�7n���#�����*VEDDhm����u��Z�
-�YU�њ�D̙3�9s��l7�P�j��+��_�mghqך��OC��tL}�jo�µP��r�>�(�jH1Y}��m�\)+��L	�1TM!��(�8cl�a3�
By��ٰa_~�%���$%%aee�
`�x%E!�B�A�,�߿�Z*//���2~��'u�NMW䅸���#��n�B�B4...�<yRk�1�)J�Lyy9���Z�y��Av�ڥ�"������}�ᇁ��c�	$� c�f� ��kײq�F������ӻ�Z��쌇����dffr��!��di�x��%�A���!�B��4��2%�~ɒ%x{{��3���K/q��	Z�l�UOK������2Wp��g����ҥK��ͥ���>�www��?�>l�� ��?y�����)..֩sf�x%E!�B��Aކ�L޳g?�����<�����ݛ)S�h]aBH�X!*s��+p��_&%%���^x����)��
�15*BI����z�*...<��3Z�3^	A�0~�xƏo�n!��5��2+++�tW�]�%��4��!j�>?c��+V�w�^


0`����XԤ�lݺ�e˖�/�d͚5�߿��W�ҴiSz�����y���}�jՊu��ñc�(**��#88�A���fϞ���)))ܾ}www,X��!C꫟�666$&&���Tܒگ_?����}�R�,66???��bƌw��DGGs��a&N���	A�HLL�t�w�^�zY�B5*��Rn
?~�Zp��c!���~�<���+L�z�j֮]ˎ;�BPF�IHHS�L�p�>�*+�Vf��w�F��^|ڶm��{$������WWW@��EѠ�h�+˄B!�!((�ݻw�&K�0��ѣ-�!�]L&DŽ�{�d�B!�YJ�믿N`` ;w�d����""��
!LQ�����Rg�er%N!��.$�~�"�B!�a��2WWW^z�%s�V!D
�W��I�B!�0��'�<==���4�n�B!�
����ر�I�uwwjN(6�]m_���HZZr��B���>Y���	!��I�BQ��|�M<h�$VCt��)bbbغu+���3777�|�IKwM!���YͲ��ĺڵB=رc���!��>p��z9N]O�ݾ}����O�6m���c���l۶
{{�:=�B����&ˤv�Bԯ���,C���k۶m��y➱n�:�^��رc�m�ƍc��ͬ[��3fX�wB!,��&˄BK�:3BK)++#66���drrr����C����2r�H�]U��*oW����d�RRR�����ӓ�^{�֭[�֐������Ʋo�>�_�N�֭�fڴi4k�Lg�����������o�>:~cTuN�l�BTT4nܘg�}�Y�fU�,::��;w2b�f͚E~~>[�l�gϞ899��y����ٲe���<��&�]!�ݫAN��Z�S���ٹs'�~�-�nݢS�Nx{{���+?�ꀾ��xM=�!���e�V�_)&+��Hڡ��bbbظq�������g�r��Y


L����k�.���HJJ����lڴ	��޺u�ɓ'�����.77�����Ӊ���I�&Z����"??_kR��ƯOHH7o�T���SVVFxx��}����t�ڕiӦ��_SXXH�>}t��Ӈ��t���5j��-���� '�j������0�=��=##�����∈�����2�Y����\\V��
a^G�a�����e��ж}�vV�X���;%%%$%%�d��n�j�d��ֳgO���;�ϟϕ+Wشi��m���ݸq#YYY�mۖw�y�Ν;s��9,X��X�~��~۷oO\\vvv����{1��ƯO�v�X�h?�0k׮%..�����,���"!!���۳b�
u"055�Ν;�Fٖ��*�eBq��t�9q�ɓ���=z'''.\Hrr2Ǐg�Νs��-�z�-Ξ=k�^߿�kC;vmT.&�����}����'�]����R�L�z�m�6�?n�n4H�$L||<��������s��	v��i�~����ӧ���t��M�ڿ�Im�����ӭ[7lmm�޽;���`߾}:��0avvv���Ư�ܹsquu�q���$\^^�N;e�����+Wj��;�<P1�V٣�>��F!��b+��▷#G�p��aY�~��2qggg^}�U�4iªU�X�j�|�َ-�1���uGҘ��[�\t7R��jR��Κ5���~���4����O�4i<�&���C뱲
��_~1�mvv6ݻw�j��SOp�c���k:�>��H"����P��C��b��QShCBk(ڢ�#5���gQ%A��Ɩ�XCI��Ps���"��g���������\������;ɽ��/]�8�)y���~kJ�,i�ݔ{��Ÿ��P�q��[�nQ�@㵛7oX-�b�f#""ϗ�rf�D���BM�:u�d=�v��O�r�̶�[�t߾}L�<���ד-[6����ٳ'�o�f����ܹggg�֭ˠA�ș3���U|Ֆb����,\��-[����?~�4i��o���-�L��-	P[��'w�~���+Wr��qbbbȟ??��գW�^58�c��q��f�bǎܿ�
��&�b�"""�&ooo���ؾ};�|�
�f���,]��޽{[,狏����$y�l��d7%�-��361k�&��f����$�������5����^�����Ν��ɓ-��voLے;���<���dYb�5-��U�V��ʙ3'��ٶ�9�0a�Q�`��)R��+W	<.6�a�1b���U|5�b�<�gϞF��/_&88�#G�0s�L��-�j����$b�̙�…Ͷ]�r��˗s��F�eS��ܫ��(�v�j|R���r��=�㪘���H֕Ҫwww|||���!22�~��ŋ3y�d�{������ܻw���ԩSI3""��Cƒ�ꫯ�jl�…9w���z���C�P�P�d�19�\F�߿?���g����ܹ���Hʗ/@�|��r�
�o�&_�|f��~NM�]DD�OeͲ�ݻw/;w�dȐ!�X��w��
�)b��9
f�޽,\��…EN;r�˖-cϞ=����q�����ĪU�ؽ{��ig�Ν�����ݻ���`
.l_}���/��իٽ{7]�v�kT,]����H^{�5BCC�駟�R�J�߿�j=�䎙�F{jͥ�-�<�s/[�x\�c����ٳ�y���k�.����Ւ%K�x�"E�e����ݻ����s��I���ZLVD2�����%V�x��
4��ӓ
$9[$-�$��OZ��t��x�
�z�-�l���Rs�aaa��ߟ���kY�إe˖xzz��_M�ҥ)S�`>*O�<�Y�����s��ƍ��q����9�Ç9x� cƌ�q�Ʃkjt5f�"""x��!�;�:u�x��W�ϟ���3Z�(U��YS7����bӶ�t\��/Òe�(Ni{B�urr��BnMj��2�ҥK��₿�?��7C��x�⸺�ҩS'��L%�?=���T�t˖-���ʔ)���%J�`�ȑlܸ��c�FJ�|��;w���/_�M�61m�4Ə<��g+{����:t(*T��ٙ*U�����*&+�l۾}��~v����Y��'��KͪG�q��-�m��{�g�xF�f�T<p�@��3��6")	�Z�n]jԨa��W�Jc�)Y5u�T�ԩ���/��b��͛7/���xyyѭ[7�\�B���i׮]��P�X1.^�H׮]���k׮\�t�bŊd&ǔ��E�v]B֒�i�A���C�����{�r��a��Q�9b��i�-�Cy�d��e}����Օ}��1e�ڵkGpp0111f�L��._������-&�)r��S��K!MX',��*��R�S�/>>>f?���Y�4����H阶>sk�_�N�Ν�ܹ3��9+V�0�������=����*V�hvӳJH�dE�^Oҍ��o��y��i�.��eb�g���|��7T�\�{��`���M���I���2|�pʕ+���...�,Y���@>��3c\�~�hӦ
/��...ԬY�aÆ%y�ɓ'S�vm�eˆ���;wf�ܹV��26w��,Z�???<<<prr��Ãw�}�/��ҬcdR@�"Eprr2f��z���bŊ���;��f�5nܘ9rX]y�k�.r���[o���q����!�j�%��Þn���X�"��{��D�V�u��Q�t�B�
X�p�1͚�B���V��R<ү�jJ�NSJY�yekU{�t�');a��;FѢEy��7)Y�$*T���Ϯ�W����I��A�dE2[ztc6�r�
 O�<<������s��U^z�4?߳��ё"E�0x�`ڷo�O?���1�S��S��丹�1d��ĄIR�K/��S�N���}�4h�
Jv\R1y{{���m�ݖ�O�)�Kj?[�
:Ԭ�RΜ9�g�…\�x�(�r��E:D�=�j%""ώ,1��W,t�…|��Wp����6M�4/ݳ63�ѣG̝;���x�5kf$�
.`��"-��&%""��뤊��u\�}֭[g��~�O���<sk���@pp0}��5��<|�Ц��s��-
�/��bvk�M�b�-�U1Y�̕x�����/5jԠnݺt�҅5k�X��ڵ<z�&M������o�ͣG���]Ͱaè[�.���|���F
���ŤI�h֬^^^4oޜɓ'��=��O	�[+���:f̘���5jԠE�̞=;�֘��'~����ٳ'���3�k�ĉDGG��)��Ç�y��������t*�����ZD��@��			1����P�P!:v옉���Hf��2[��֨Q�*U�����͛���"66��G�ҷo_���G�Z�hӦ��_Z9�WF_M�~����:hǏ'..�7n0m�4<==�f��V�I�̓;�޽{y��Ǐ��O?5��Zo͞{���o���/���Ç9z�(_|��qULV$�9s&,�����ͯ����n��<�Y�~�z#Io�]�nݺ$g��i�&����y�&k֬�k׮f�-[�0uQ^�lW�^��ÇF���H,�5S��ŋs��%bcc��}���k�s��
�̙��	��ݻ�u-_�<٢�	
2��7�944�iӦ��ԩ8::�͛7�|"�5���1r�H֮]��˗�|�2k׮e�ȑdϞ=���L�%�e�7n%K��ҥK:����S�F
سg���g���f��Ңȩ�2��jb������+DDDбcG�W�N�ƍY�d	ٳg�_�~v�Z��'e�3�vnS�q���ԬY��;r��	c��Ǐ��=��cǎ�-[�+W�н{w����\�r�U1Y����n��ҥK�)S�ҥKP�Lʔ)åK��\:��o�1g��;r�"E�x�"K�,�;��tQ�GR]�S�i9��r��1F�
<��Ė.�)ug�u�aaa�ڵ�Xf����:�<��V�J�^��8q"'N�w��I6$��C�%��)�lO�мy���W_���S�Br��AΜ9iذ!�g���,>%J�"��ʨ⫉�ʕ���`���)T�NNN���S�^=����T�h�V�I�̭�{�x{{��憋�*T`�رt����7)��+�ϟO�6mȓ'...���[F�/!��Xэ�W�?�-[��W�?��� �U��lwd[�HM崐�N�`�����ԩ��������{��Ң��/J�(���ݺu0[�N��4����hP�<�gҤIL�4�w�}7���L�a��a����B�q�N�:ѩS'���EN�ݞQ�W�mwww������?M��T�Wk���-��ڹs��m,kM̔0�v�'�W�H�-�zULV$��۷/�}����c߾}̙3��]����o��KTT���2���ضm۸{�.�r�2۞8Qgꀜ�;��q���rZH�=�k��srr"o޼T�Z�nݺ���~�:����رc����T�R��_x���a�:������S�,y��a�BBB�D��Ɋ������ߦ8�����o�5��	��oMɟ�ݚ��C0$�E9���x#&[g���2��
/-�'��m�:�������e"��TL��?6f@�]���ӧ����S�ԙ��LJ��H~��/^��ɓ�$�i)���ӭ�߳g}�k׮�H�=zԘ����?��kO��ܹs:t��ի���E�����x�ݻg�~�eF�鸿��;�֭K��	��jU�9s�x��Çd�d?��˗�+W�p��m����T,"""�|Q�L$�$,&����S�e˖\�x�!C�дiSJ�.ͅ��u�=y�$ǎ��W_5+J�P�5(^�8����<y�h0z�hF�Eٲe���0��6j�Ȯ8���1c=z4�˗'22Ҧ.�y��1�q�nݚ˗/[�4iJ��?�bŊ����1h� J�.�_��ҥKY�d	���̝;7����{�ҨQ#Μ9èQ���w��!o޼Vc���I��n�S���[�X�fMf�!"""Hɲ�«����?������$!  �1c�0n�8�đ)�m*�߾}�$��988о}{Ə�ڵk��O��ʗ/O``���e�ҡC��0�ۺu+�ϟ�蘜R�z��z�j�N�j�Դ6KΔT�P�B�[����@�o�ntN(���Ƕq�F�����-^?~�85kִ��jժŎ;8r���T��j۶mf� "YT۶m��FD�J����sŞ-|}}ɖ-aaaƲ��E�R�N���eӦM���ӬY�d�ռysfϞͦM��裏��C�%>>�m۶�p{�ꅫ���q���(ϛ7��۷s��
���GÆ
�֭[�]���뇣�#[�l��xzz2l�0�4ib6n��̚5�+W�5�L݃,X��m۸v�9s�J�*���Ӭ�~j8���k�.���(]�4;v��ٳ̟?�+VP�fM��٪q��L�:�]�vѹsg��ԩ����!���H&p����TBCC�С�Q�7��""�1������z%�͝;���f��NŭZ��G��������4�1$$���Y���!!!��-"iN�/"YJ�f������N��j����H�%�V�\�^�+�+�dԩXT�LDҋj��d-�,���K�C�����u*~��F����@:$���ODDD�2�,#"""�|K�dُ?�������""b#͌I=Ǵ>���U7GD$�\�R�""""""O(�j�if��H�


�C��������H��n�2������!�<�T�MDDD�eJ����3�v�ښ�,�A�+��!�����%�2�o��Fٲe��s����o�>���������DDDDDDDD2��e��O>aǎ���?U�>x� 3g�dŊ���Ӯ];ʔ)C�J�2<N[��㏪�&�A���			��0DDDD҅�e�hǎOݹ�߿ϰa�hӦ
�
��חO?���+W��斑a���->>>�Cy�))-"""�:��@�.�-�ڵk�o�����r��5-Z�������������gzf�իW�={6�w���ݻ���+t�ܙ�M������b���lݺ�7n�?~4h@���ɕ+�1�����˗3y�d"""puu�Q�F���טu���#�ϟ��͛�|�2��Δ,Y��-[ҪU+�c%�{xx����3`�ʔ)�ܹs��$dm{JםԹ���X�|9ժU����S�`A<==Y�|9�:u"w��=�,�M�ݼy����_�nl;u�Ç'..�-Zp��]�{�=Μ9c��r�
����߿���`r��av�=zp��mbbbX�j�="((��3g��W_�ccc���_���_�w�M�&O�LTT�Y�*-�ۚ����hj֬i�Z͚5ٿ?�7o�u��v�$""YG�Truu�x��t�Ёf͚epT�'��҃�*�Y IDAT�爈��d
��2�ŋs��uʗ/��իٹs'�����Ƹ����3g�P�H���ٻw/.�p�œ:u�/�����ŋg����޽��]��m�6�իW0c�����Ν;2d+V��(��!�D��޽�Q�F��u'u�ݻw���⸦m�1""�|���9q�#F��Ԛ�Y��y��0`3f��СC������X��&�~��GH�b�ȑ#AAA�����gJrQ�bE���y���:t([�n�8��A�(V�����,�;w���f����ƭ[�hӦ
���]�֦�;v숋�K�]�5����8��+��b6FDD�m�SL6o�l,�_�dI&G�v�}`��7�)\���<���zn�_�$�<==-���K�.P�l�d�]�x��_�l{�ʕ͎�Pɒ%������딙���WWW���ǔ)Sh׮��������)9e/[�ۚ�7oX�If�f#"�Ue��gM޼y0`ǎ��h�5��Z�ٙeO���Wb���ɞ��ۛM�61|�p^�ubbb�={6M�6eժU6�?�Ye�����<x`�\�i_GG��mOz_ED�f�D�/��B�
�ٳ��Ztt43f��LJ5jТEfϞm�^l:�Ç�0au�֥A�̝;�۷o3t�Pj׮M���1b���3;FTT�&M�Y�fxyyѼys&O��ݻw8�<ժU�����u�lْjժq���bO�Ç���9�իW1b�5��ˋ��۳q�F��1��ۓzf�=b�ܹ���R�F
�֭K�.]X�f����=��yNTT��s����H�Ȑ�Q47��^z�.p��)ʗ/��…s��9:D��Ս�:"�
J��������LJ��H~��/^��ɓSU �����x�ݻgt�<u��8[�ۚ|��q��n߾M�|��^354H�]D�Y���ʃ�ٳ'���Ƙ˗/̑#G�9s��
&L0jX,X��"E��r�J�8111lذGGGF���x�X�bxzzr�"""�X��16""��/R�zu�-��������͛L�4	�
*��n�9��Mr?3{���=U���癝YV�V-&N�ȕ+W���a„	xzz��ի��1c�����ÇDDD0v�X�ԩc��[�l���'_�5��є.]�2e��g��?>�c�ɓ�5k�p��}Μ9øq�R}���mZ����[״-5�;ED���MV�.]Jdd$���������O���Q�R%���o��#GX�l{��1f;�7'''V�Z��ݻ�޽;;w�4����)��a���fh�i�&ձ�y	�jժѸqc6oތ��ݺu3k�9lm�c���̖f;���=U����M�u�҅|��A��ͩ]�6aaaf?�P�X1.^�H׮]���k׮\�t�bŊ�.�<���nݺԨQ��� �T�b�3%�|}}S�$ݔԛ:u*u���Ϗ_|1��m�ܦDۑ#G,�kږ�䡈HfJ�ffr�47Yٲe�2e����D�%9r$��B�!C�P�ti\\\�w�:t(ŋ��ՕN�:����7��W�y��e˖-�����Inٲ�֭��حqrr�r��̚5��~�s�'iD����,5�v�㞪y����H���&����ǢE��&w��8;;������ݼ�q�E���燇�NNNxxx�����_���������)W�...���P�dI��όq�H�"899�X7�_�~�iӆ^xj֬ɰa�R}���ݸqcr���]�,��k�.r���[o�e���j7Y1����1K��j�
��,>�L\S�̛ĸ��Y�gk�lٲѲeK�ܹc�o�ٳ�۷oӪU+���R;��K�֭[)[�,���4i��j1{��$�h�������Nz�S5��z2�fYf)\�0cƌIq�/���A�4hP�㒪�fm��^Yr�����nnn2�XB��x[��ڹs�̉��?.��ŋ)Rx��ۡC��ѣ��/|""YA�IS�'�z����$l�b���~B���VǦT,)�ϼ��;,^�����ӠA6n܈�������Ş���;Æ
#  ��cǒ'O�ׯo6ƞs��(&>>��'��?3ooo���ؾ};�|�
�f���,]��޽{'Y#,�署爈��d=�t�L���
		1��!!!*T��;frt""��P�B����[�.Ս_leO�…�����ݻ9r�;w���7�4뺘��+W�N�:��_2f��V�j6�ڞs�ڈ���6�IM�����j�#"""��d�2��b�ꏤ���#G�d�ڵ\�|�˗/�v�ZF�I���3;<�La�I���lj���ƍL�6
OOO��Z���L�֭���#00�E��:���{�"E�p��-�ϟ��s�ڈ���6I��َ5iyO�<GDDD$���2�P�jUz���ĉ�ݻ�Yc��M`` ۷o'""�b�m����ׯ_��+  ��[�r��y�&3��ԩS�]�FѢEy�7�%v777F�A�=X�r%�[���W_��]�ta˖-F#��6��W��W�f�ԩL�:��5k�+<��cƌaܸqI������=�U�;v��ȑ#�U���S�&˒�#�������&"�,I��\�r̂ضm׮]#gΜT�R��={R�T�4���xf޼yl߾�7n�/_>6lH�n�,Ϙ�i͟?___��Wi{�*U���cŊL�4��3g�}S#��3g�w�^bbb(U����4l��ׯ_?ٲe�����ӓaÆѤI�b���%[�l���q���-J�:u���II�{ڸqc�N�ʮ]��ܹ��q�<GDDD����R�����ҡC��m�ED$c<o����J�5w�\.\Ț5k̚�jՊ=z��gr���С𸦩��EDDD���L�Y&"""��`��f�$5�yz)Y&"""���<GDDD$kI��e��{����<��<GDDD$�H�dY�ڵ	K�Ê���dij�#"""�5�y��X�b+V,�+""""""""��T�LDDDDDDDD��lf�j�����HV��gE2�…�ڵkf�!"���2�(�����_f� �L[�r�3]{�����'��y�|�ᇙ���ቓe�Q&""O�bŊѶm��C�׶m[�W���a���M�Ҵi��C乣d��<MҼ����Hf�]�6�k���0DDDDD$�S�LDD�	���t��!��y.�����a���%Kfv"ϴ)S�hٳ�<��,�g��h����-)�f"�C�.E�i�d���<ST�L$}�Y�&�C�P�a&�>�,���cf """"""""���2����	@xx�կS�/1WWW�/N�h֬YF��l�/i!,,�}����兟�_��SD���'
��0DD�;J����dA��7'N�`Ĉ�ʕ�7�|3�C�R<�̙3Y�b���k׎2e�P�R��M$ՒjH���H�\�(Q�o��6�;w���5��K��4Z8}�t:D���/_���9x�`��t�7��OD$+S�LDD$H<���͛L�:��7�dɒg&Y�3��߿ϰa�hӦ
�
��חO?���+W����1�d�G�q��:ġC�شi!!!����

��DD�[J����s%#�����y�2`�6n�ȱc�2;�,eѢE\�v������}�]�-[ƢE��իW&F'���z��!�����=�Ç3g����I��f6��HFQ�y�}��Wxzzh�}���xzz�e���>>>xzz�y�f~��z��I�z����y��L�8���h��:u*
4`�ԩ6���!�EGG3c�|||�Q�-Z�`���<x�b�իW1b�5��ˋ��۳q�F�1���V�%�n���_~�A����x<�e�ܹ���R�F
�֭K�.],:+��?�<ժU����굷lْjժq����7**��˗S�Z5<<<����ӓ�˗e��"YU�l�ȟ??o��6�'O`��ՙ�����K3�DD��[o1}�t�;Ftt49r�0�a��=o���x��K�pqq�v��̙3����ʕ+,_��;w�0j�(�b�2e
!!!T�P��ݻ';6>>��7o2i�$*T�`����ٳ'���ƶ˗/̑#G�9s&����p��uc�S�>|8qqq�h�¦��<y2QQQFBj�̙|��W�뱱������ܻw�:��_�X1<==9p�T�X�x-""��/R�zu�-j�~��wDGGS�fM��k֬���ټy3�[�N�u����ŋ̞=�;vp��u^|�EjԨA�޽)U���x[jo%�=�믿2o�<���GTT�
�iӦ����x���믿��k�,^���			a��͜<y���(r��M�J��޽;իW���ܹs,X��ݻws��e�g�N�b�hԨ������[�c�}K�?���7ұcG>��3��׭[G߾}y��WY�nnnnf�����k���s��Y��ݩY�&}��L�2V�w��i�̙Þ={�q����V�Z��ݛW^y�b��\;w��>�̙3ԨQ��[�Zg:��Y%�a�f̘�ٳgɟ??u�ԡgϞV�LNF=K����e""��+T����?����СC��Y[[�n��ёݻw��#Gx�7ȑ#˖-`Ȑ!�޽�={�0o�<v��e�'O�LHH%J�`ƌV6͸���Z�j4nܘ͛7���D�n���.]����H^{�5BCC�駟�R�J�߿��k�c/^���)_�<�W�f�Ν���;�s͔(Q�ݻw�B�,�3f�w�^v��ɐ!CX�b��c�V6l0�n��֦M��w�������8�i�i�Hr8@ӦMY�|9�/_&66�?����k��������>f���;^�z5�[�fӦMܺu��r���͛G�v�잽
I�ĉ�{��Ѷm[���8�_�E\\��۷o�C�I���|||X�l�ϟ'66���(�=ʴi�hѢ�Y"��%eԨQ�˗���~��'��L3j����<y�E�����<�S�Nǭ[�ذa-[���۶m��LJ���?\�z��r��UV�^M�-�}_<x0G���6ՑKͳJ(44��>���'O���C�\��ʕ+i֬��߷ c���HFS�LDD�i	�L֖���f��j����Oܹs��-[Ï?��/YV�~}��P�|y6m�Ĵi�?~<w��M1�ɓ'���;�fͲ:�'''*W�̬Y�,�G����3�2e����D�%9r$��K�u
8�bŊ�#G����?���M�XӱcG\\\��M	�����¸u�mڴ!<<�,��P�z�ț7/[�l!66x��ܲeԭ[�����(^���L3*LcD���_ѻwo�ݻG׮]ٺu+���|��״k׎��X���k1{����`�>v�X��.\ ((���8���ٱc���˗/�x��DFF���<z�[�n�i�&>��#��̝;��G�R�ti���8z�(ǎcժUT�\���xfϞm���ν{�h߾=[�n��~��ѣ���R�T)����O���-������ѣ���g��Fr1>>�A�q��m���c6s���\�2�V��رc|��w4jԈпn޼i����?�裏����Q�F|��?~�o���F�͇~ȟ�i5�s�αi�&>LPP��o�$�HݳJ���?�F��]���Ǐ��w����MLL}��5���d��hJ�����5���H�m޼WWWz�ꅳ�3��=�8Y���h$j�_�N�Ν�ܹ3��9+V��̙3��_�R
<��u�֭$Dž���֭[)[�,���4i��j�������f�ӪU+��2K�K�.P�l�c�G�<}����Օ}��1e�ڵkGpp�1cϚlٲѲeK�ܹc�vسg�oߦU�V899�]��ܹs[�ϴ͖_�l�2nܸA�^�

�x�⸺�R�reƌC`` QQQ,]�4��<x�)S�Э[7|||��BCCy��͚5c��Ѽ���d˖�jժ1m�4��&%K�4�S�ti<==�ӧW�^�gϞf
.���&M�DժUɞ=;...T�T�X�}��q�}L<��ŋ�-[6�g�N��ՙ9s&��ޙ�-�u%�'�ƍ���Å�2�,Y?��믿N�޽�<�ҥK�T�...�*U�9s����ETT���
��^FGG���Ŝ9s(]�4��Δ.]�����,Y���LK;s���K/�duLB�yV	�/_�ŋS�B���)U��gϦf͚���_ƌ�������e""�L3%�L�����믿���ǹy�&۷o�z���ɓ�ʕ+��?Mdd$�*U"O�<L�0�cǎQ�hQ:v�Ȉ#�9>�g�N||<s��Mq���;Æ
#66��cDzm�6�1)%��x�� 9	�m�Y�I�Ye���lڴ��Ç����ٳiڴ)�V�J�8������_�x<K����H�%��k�k�a��i���D�?��w�:u��z�v��bGEEѷo_���[�.4{ݴl�cǎ��������ر������9r�'O�4۾s�NN�>mQ��_�Hn*T��]���7�p��e�ҥKs��i���clK���#F���Ã�����+&L�����&M2�����bY���#=z�0{�5���ѣ��{K�}�Z���o�u=�yV	������%�־�$�Y�RD$�������y{{s��!/^̽{��]�6�k�f���̛7��w�K0���<��eJ��f���e�ٲ%�����ϟ��ӧ�s�N"##)_�|�q�+W�N�:��_2f��V�j�|�P�B����[��e6)/��.\�ԩSɞ�����x�ݻG�\��[�pww���"##��X�x1�'ON��~�…���b���9r��;w��o�u���z���Ǖ+W�}�6���3{�������{yy%;�ܹsI���A��ř:u�E������KI�&�=��ݻ�:u�%K��v�Zڴi��ի�6�p�'N�����>|بs�81ݫW/
��9x� �c͚5iذ!
4�������-�u���_���?�{��F���#G�ꫯ&�OR�MK6�b���rN�_S�3M,�������R����myoO��""O3�,���
���h�t2%�jժ`,M�W��ž{���?~�O?���~�Ν�ۡC�k؜9sl����ޣH�"ܺu���盽fJ�q��q���q�ӦM��ӓ�={cM�6q�D�\�BLL&L����(���5k�p��}Μ9øq�l��e˖xzz��_M�ҥ��r	���u�����ȃ����^�rSk�������Ty��R�0�q+V�`Æ
�̙������/X�1��JM���qww�J�*L�2�>���w�2a��q6l�^�zԫW��ݻ3k�,~���$�&�nݚ9s��p�|�2�V��W�^x{{s���'�oO�aÆԨQx��2�Q&����L˵6W�w��k��>`�����m)Ꟙ���Z<���O*΄2�Y��d�,��|��Q�J���)[��1{�x�������+W�l@�z�ظq#Çg����<~�85k�L��NNN:���{��{�r��ac&BR���1b=z�`�ʕ�n�ژ%��ۉ���X•={v���g|ݥK�l�BDD͛77���f�z�X�z5S�Ne�ԩ)^WB�3�q��Y$ْ��`R�N<<<�v�E��X�d�֪U�;vp�����/թS���瓛�w���СCI&H�r��)F�����'O6���q��=����>GJ�u�Ɯ9s���k׮5���,Y�&M����/�'OJ�*EÆ
����ooo.]�Ğ={���gϞ��=�H�?�}{R�߿x<+l���V?�0I꾛>I�ZΜ9�s�QQQ���I��5�}V&)]�-�f2�Y��d�,��J��e�y{{�	�,��K0�qIooo���pqq�B�
�;��ݻ�g�آbŊ�L.[g�U�R???��⌢��x�@pp0���*T'''��ݩW�_~���̩|��h�"���ɝ;7�����`���4m��ׯ_?ڴi�/����5k�dذa6�	�������)W�...��B�IDAT���P�dI�eQIIX����ע��=�۸qcr��a��ή]�ȕ+��U$)�n����]�����|���ܿ��}�ҨQ��q�ĉ����ug͚<y�f���G۶miԨ���G�Y=V�…iӦ
�ƍ�����7�YB.���I�����'�g46:t����S�<1�rӄ�c�+<N�Ys��!�qO�I�ձcǬn����Y��ɬg)"�Q4�LDD$___|}}-�0�Xlϝ;7cƌ�z,S��H�YK�
:��C��8.��Z��3���O���������5����1d���l|��k�W�����޽��L���͙3'���,\���/R�H.^�ȡC��ѣG�,{�gۛo��ѣG�5k�k׶�7�a�>��#�|�M�����cǎ���4n�8�.�&^^^DFFFժU�^;q�M�4�H�"�ܹ����	�2��3L^CLL���nݺ\�x�o���ҥK��cm�hj�ۓ7ngΜ�y��|��,_��Q�F�}АЂ�e�&qqq̛7���~��^�n]�9¼y�]��Y��G��CӲw[�jE>z��옩yV���Z�jf<���Mf�K�dֳ�(�Y&"""ϕ��
,HHH��-$$�B�
Y�<(�Xǎɝ;7?��3���>|�����}���'�|����Y����gɒ%�+W��'��u�C������_3q�D�_����ٻw/}�@��1�����…̚5�X
`�^�pa�qB�����q��I`${���/��-Z�w�4u����ĉ�2�7�|��ۓڵkK�.套^bԨQ��&
.̚5kزe���o��G}��ӧ�����������S�hQڶmk��С9s�d߾}|��:u���XN�:�|�O?����[�u�3%����;��∍�R��
�_�~�9s���X"##	��.\??�cˌg)"��4�LDDD�+nnn�9��?���u�ڵL�>��ٳgrt����KL�:�޽{�g���QG�e�avƌ��:����?�<����+��¨Q��׿�Ŝ9s,�gW�\٬yEB�:\&֮];Z�li|ݽ{w���		1K$��d���9w�F��>���ԩSf�7��^z�l6jj�er��in߾��?~��H!gΜ�7���>��S�U�fQklƌ|��lذ�l{��7o���ƶ�2e��������o����S�L1f����^㧟~�O�>fו�g�Ј#�߿?�֭3۞7o^�ΝKΜ9S��I�����N3�DDD�S�jUz���ĉ�8q"�{�N�рHB���c����mۖB�
�-[6r��M�ڵY�x1:t0��y��Ѷm[�-[ƛo����;��Δ,Y����j��I���/��2͛7gѢEK�۷o�ĉ)_�<...�ʕ�Z�j�`����g$lBCC�}r����_�|@�R�Ȟ=;NNN/^�������[$��oOb���\�z��;Zԡ�U����\�~�js��M��?��O���(Z�(ݺucӦMV;�6lؐu��ѪU+<<<prr��Ãw�y�u�֥��	�[�.9r��ɉ��{V	�lْ3fP�T)�e�F���С6l0�l���|�""�!>>>>���Whh(:t��m,��"�>L��f�$�:+spp`ʔ)Fm��%K�}-�>��5�?I?���,Y��ҵk�L�LD�p�,�/%�DDDDDDDDD�K�2��R7Ly��\�2�Cy��\���m�fv""""�F�2y����ev""�E�������e""�����?���,N5�DDDDDDDDD�K3�DD$KS�2�̥f"""�Q�LDD�4�(���d���dI�Q&"�_�~���/����d������3f���D�i�*U��DD�R�����2+>����A�6e�|||2;J������$A�̋���%Kfv""I�2L��R�LDDDDDDDD俴SDDDDD8w�����S}�����o�%""��+��o?�1ED�٠�e"""""„	4h�S}����رc���ҥK	

���O|\y6(Y&"""""���?��I�cbb�1c���(P5j���Ӊ��y�㋈H֧d������������/���Y���7oҴiSc[ӦM�y�&k֬���DD�i��e"""""ỴG�X�r%{����?�$[�l+V����ӰaC��111�Z���{�r��M���C�:uhݺ5���f�>������<��γo�>���;Ξ=���M�<y�V��.ٳgOv_[��޽{lܸ��^{��y�����O�
ظq#-Z� gΜv]���<[�,�bBCCY�v��Ç9q�'N���4o����X>��3N�>m����?Y�z5'O�$((GǴYlbkL�,_��իW�m�~�:�6m�޽{���'�}��ݻwC�J�,�S�R%~��W����[o�e�u��ȳG�2�,��`�С���k<|���;w�`����[#1�n�:N�>M�ҥ�֭Ŋ�ҥK̟?�_��m۶ѰaC���R=�̞��:�ƍx����W��<y��#G���?��k�5<x�%JX�_�dIc��e""�7%�DDDDD�T}���S�t�E��ى��fÆ
������x{{���m6n�޽|���xxx���/ӻwo>��Cv��e�l3�c�櫯�">>�3gΰk�.~��w�9@ttt���s�gϞ�p���1m3��痒e"""""YL�Ν�={6����ìX��w�y�f͚���j��|�2@��ϟ?��1Ys��-Əϙ3g,^���Ov_{����Vk����ƈ���K�2;$�1���S�f͚T�X��u�V~��7�/_���y��w�e�)%�R���1Y̙3g(X� ժU�hѢ�*U�����x^{����j�6�6�y~)Y&""""��ʕ����S�~}N�>;}���oX�x���*P��.]b֬Y(PੈɚÇ�������a������}��_|��ׯŋ/�h�ZTT�1FDD�oi�FDDDDD2L�>}���c������P�xq^y��e����o��ӦM��ٳ<z����K�����g�}f�5ͨ2-kL���;ϡC������ٳL�>��~���$���M�\�t��ܦm�1""���2�,�U�V̟?��`���ʗ/o6��8q�����suu%  ����ݝ۷o���S�@f͚�.1Y;�o��Ν;�9s&3gδ8�ٳg�T���}��*U�ΩS��b8u�U�V��ED�٣�e"""""O ,,,C�4jԈ>��W_}ggg���)Z�(�Z��w��Ƹ9r0z�h�5kF�ptt$W�\T�V�/���lU�.]����ё���t���y�t�B͚5ɞ=;��Δ*U��}�Ҷm[6mڔ�\c�Z�Ȟ=;?���E�?��39r�f͚v_���<[�S��)""""�ppp`ʔ)���P�dI���ٰb�
V�^͌3����ڵk|����Ѻu�L���Wɒ%Y�p!]�v���DD��2yn�lْ���~�zc���)P�͛7���DD�i��e"""""���/]��QK>�?���>��ٳӻwoƎK�-ضm��׿puu���DD�i�d������<Wʗ/O���Y�h��E�y~)Y&""""���l+k�z�)i͚֬5��0DD�)��e"""""""""��d��������s�6AE�6������r�=Ʉ&e�W��_��� �,�7��뺺g$���1F��Yc�ڶ�{�-�n���=h�g��2?���j��=�֜��}�PUU����_��g�X!�@�eb�X!�@�eb�X��&�J�J�0IEND�B`�PK��Zy��
�
#data/ConsoleTools/design/design.txtnu�[���eZ publish Enterprise Component: ConsoleTools, Requirements
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Introduction
============

Purpose of the ConsoleTools package
-----------------------------------

The ConsoleTools package will contain several classes to support comfortable
development of console based applications. These classes shall be designed as
independant as possible from each other to let the user flexibly choose, which
ones he likes to use and which not.

Aimed features are:

- Comfortable handling of options and parameters (long, short, values,...)
- Formatting assistance for console output (placing, colors,...)
- Convenience functionality to deal with Windoze and Unix based systems

Current implementation
----------------------

Included classes
^^^^^^^^^^^^^^^^

2 classes are directly involved in the CLI handling.

eZScript
    General initiallization and shutdown script functionality. Very eZ 
    publish specific. Handles initialization of database connection for 
    example, but also some CLI related actions like shutting down every
    thing cleanly and returning an exit code.

eZCLI
    Handles general console output, formating and option parsing.

External classes
^^^^^^^^^^^^^^^^

Beside that, there are dependencies to log/debug/whatever and the following
ones.

eZTextCodec
    Base clase for drivers that convert text between different output formats.
    Currently has 1 extending class: eZCodePageCodec. Part of the I18N
    package.

General involved classes:
eZPublishSDK, eZDebug, eZINI, eZDebugSetting, eZExecution, 
eZExtension, eZDB, eZSession, eZUser, eZModule

General notes
-------------

The functionality for console handling seems to be widly spread over the
current eZ publish classes. Beside that, it is not quite feature complete and
mixed around with web handling classes.

Requirenments
=============

Design goals
------------

The command line handling classes should be redesigned completly, since it's
currently messed up with web related stuff and fully integrated with eZ
publish.

Following functionality will be included:

- General in and output handling functionality

- Output strings

  - Style output (color, underline?, ...)
  - Position change
  - Error/notice/warning support

- Handling of options

  - Long / short options
  - Dealing with help output
  - Optional and required stuff
  - Dependencies and exclusion of options
  
- Handling of advanced output

  - Progress bars (single, keep multiple in mind)
  - Tables

All parts should be as independant as possible. Some parts depend quite hardly
on the output itself, this is ok. Option parsing and handling should _not_
depend on the output class.

Design
======

The design for this package has been splitted into 3 categories of classes:

Output
    This type of classes provide low level output functionality for console
    based applications (like styling text, line breaking,...).
Generation
    This type of classes provide more advanced outputing features (like
    generating structures of text automatically, providing advances
    tools,...). This type of classes depends on the Output classes described
    above, since they output data.
Handling
    This type of classes is independant of both above shown categories and
    provides features for handling common functions in console based
    applications. Since they do not have to output directly, there is no need
    to depend on output functionality.

PK��Z���?�T�T'data/ConsoleTools/design/design-1.3.txtnu�[���eZ component: ConsoleTools, Design, 1.3
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:Author: Tobias Schlitt
:Revision: $Rev$
:Date: $Date$
:Status: Draft

.. contents::

=====
Scope
=====

The scope of this document is to describe the enhancements of the ConsoleTools
component for version 1.3 of the component. The following features are part of
this design document:

- Basic dialog system to interact with a user through STDIN.
- Enhanced handling of arguments (including help output).

This document describes a new range of classes, which will be added to
ConsoleTools, to fulfill this needs.

=============
Dialog system
=============

Design overview
===============

The following section gives a brief introduction of the concept of a simple
dialog system that enables the developer of a console based application to
interact with the user through STDIN.

Clarification of terms
----------------------

User
^^^^

The "user" is the person using a program and interacting with it during
runtime. The user has no knowledge about the internals and must be guided
through the dialog system he is interacting with. The term "user" in case of
this document is _not_ the developer using the described component, but the
user who interacts with the final program.

Developer
^^^^^^^^^

In contrast to the "user", the term "developer" in this document refers to the
person who creates a program, using the described component.

Dialog
^^^^^^

The basic idea of a new mechanism to interact with the user through STDIN in
this document is called a "dialog".  A dialog is presented to the user by a
certain amount of output it generates and a certain amount of input it
requests afterwards.

Basic design
------------

The core of the new feature described in this document is a dialog. The dialog
is an object, must have the following capabilities:

- Presents itself to the user on the command line
- Requests data  from the user through STDIN.
- Validate the result for its purpose.
- Return the result to the developer.

A dialog is usually used in a loop, which displays the dialog over and over again
until it received a valid result.

Class design
============

The following classes will realize the idea of dialogs in ConsoleTools.

ezcConsoleDialog
----------------

This interface describes the external API, which is commonly used by developers
and other classes to interact with a dialog object. Each dialog class must
implement this interface.

__construct( ezcConsoleOutput $output, ezcConsoleDialogOptions $options )
  The constructor of a dialog receives an instance of ezcConsoleOutput, which
  it must use for presenting its output, when requested. In addition, it can
  receive an option object, which must be an instance or subclass instance of
  ezcConsoleDialogOptions.
hasValidResult()
  This method must return a boolean value, which indicates, if the dialog
  already received a result from the user, which is valid in its context.
getResult()
  After the hasValidResult() method returned true, this method will return the
  value received from the dialog.
display()
  Using this method, the developer can instruct the dialog object to display
  itself to the user. The dialog must use the instance of eczConsoleOutput it
  received in the constructor for displaying.
reset()
  This method resets the dialog internally to the state it had directly after
  construction, so that it can be reused by the developer.

In addition to this interface, an implementation of ezcConsoleDialog can
contain a set of static factory methods, which return a dialog in a
pre-configured state (for example a standard yes/no question, where only the
text needs to be set).

ezcConsoleDialogOptions
-----------------------

This is the base option class, which must be accepted by a dialog. It contains
options, which must be valid for each dialog class. A dialog class may request,
that the options it receives are instances of a subclass, if it expects
additional options. Each of the options defined in ezcConsoleDialogOptions must
also be available in this subclass. Every option defined must have a sensible
default value, so that there is no need for the developer to change it.

The base option class provides the following options:

format
  The name of the format this dialog uses to be displayed. The format
  identifier must be defined in the ezcConsoleOutput instance submitted to the
  constructor of the dialog.
validator
  An instance of ezcConsoleDialogValidator. This validator is responsible for
  validation and manipulation of the result a dialog received from the user. An
  implementation of ezcConsoleDialog may require a specific sub-class of
  ezcConsoleDialogValidator here (e.g. for a menu dialog, which requires a
  special validator object to work).

ezcConsoleDialogViewer
----------------------

The ezcConsoleDialogViewer class provides a set of static convenience methods
that can be used by a developer that works with dialogs and by a developer that
creates new dialogs. These methods are:

displayDialog( ezcConsoleDialog $dialog ) [static]
  This method is recommended to be used for displaying dialogs. It performs the
  typical loop: Display the dialog over and over again until it received a
  valid result. When this state is reached, it returns the dialogs value.
readLine( $trim = true ) [static]
  The readLine() method is commonly used in a dialog implementation to read a
  line from standard in. It returns the input provided by a user, optionally
  trimmed of leading and trailing white spaces.

ezcConsoleDialogValidator
-------------------------

The ezcConsoleValidator interface provides signatures for methods that can be used
by a dialog to validate the result it retrieved. The validator is configured by
the user and submitted to the dialog via an option (if a dialog supports this
mechanism).

__construct( ... )
  The signature of the constructor is left to the validator implementation to
  retrieve settings (e.g. the valid results).
validate( mixed $result )
  This method is responsible for validating a given result.  The dialog will
  submit the result it received to this method which will indicate if the
  result was valid by a boolean value. To manipulate / fix a retrieved result,
  the dialog implementation can call the fixup() method.
fixup( mixed $result )
  A validator can try to fix a given result to be valid. This manipulation can
  be omitted by simply returning the result again. An example for a fixup would
  be to convert a date information into a Unix timestamp using strtotime(). The
  validate method would then expect an integer value > 0. The dialog
  implementation is responsible for calling fixup() as it thinks is appropriate
  (e.g. always before calling validate(), only if validate() fails, never).

Dialog implementations
======================

The new feature set comes with a collection of basic dialog implementations,
which will be described in this section.

ezcConsoleQuestionDialog
------------------------

The ezcConsoleQuestionDialog is the most basic imaginable dialog. It asks the
user a simply question and expects a certain answer. A typical output from an
ezcConsoleQuestionDialog object could look like this: ::

    Do you want to continue? (y/n) 

This dialog implementation provides a set of rudimentary options, which can be
used to customize its appearance and enhance its capabilities. For this
purpose, it comes with a custom options class ezcConsoleQuestionDialogOptions,
that accepts the following options in addition to those provided by
ezcConsoleDialogOptions:

text
  This option defines the main "question" text, displayed to the user.
validator
  The validator is an instance of ezcConsoleQuestionDialogValidator. For
  implementation details, see further below.
showResults
  If this boolean option is set to true, the dialog will display the possible
  result values behind the question text itself (retrieved from the validator).
  If a default value is provided, it will also indicate, which one this is. For
  example: ::
    
    Do you want to continue? (y/n) [y]

  While here "y" and "n" are valid results and "y" is the default result, which
  is selected when simply skipping this question by hitting just <RETURN>.

ezcConsoleQuestionDialogValidator
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The interface if ezcConsoleQuestionValidator inherits from
ezcConsoleDialogValidator and adds the following methods:

getResultString()
  This method returns the result string to be displayed if the option
  "showResults" is true in the ezcConsoleQuestionDialogOptions object.

Concrete implementations of these interface are:

ezcConsoleQuestionDialogTypeValidator
  This validator checks the result to be of a given type (e.g. int, float). It
  optionally checks if the result is in a given range (e.g. [0-100]).
ezcConsoleQuestionDialogCollectionValidator
  This validator checks the result against a given collection of pre-defined
  values (e.g. "y" and "n"). Beside that, it can perform basic operations on
  the result before checking it (like strtolower()).
ezcConsoleQuestionDialogRegexValidator
  This validator checks the result against a given regex (e.g.
  "/([0-2]?[0-9])[:.]([0-6]?[0-9])/" for validation of a time value). In addition
  it can perform a manipulation using this regex with a given (e.g. "\1:\2" to
  unify the time value given).

ezcConsoleMenuDialog
--------------------

The second dialog implementation shipped with ConsoleTools is the menu dialog,
which is an enhanced version of the question dialog. The menu dialog will
display an ordered set of options and let the user select one of these. A
typical menu can look like this: ::

    You can choose one of the following actions.

    1)  Create something new
    2)  Edit something
    3)  Delete something
    4)  Do something else

    Please choose an action: 

The menu dialog also comes with its own set of options, the
ezcConsoleMenuDialogOptions:

text
  The text displayed before the menu.
selectionText
  The text displayed after the menu to indicate to the user that he should make
  a selection.
markerChar
  The marker character used to divide the marker of a menu entry (e.g. the
  number) from the menu value (the text of a menu entry).
validator
  The validator must be an instance of ezcConsoleMenuDialogValidator.

ezcConsoleMenuDialogValidator
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

In contrast to ezcConsoleQuestionDialogValidator, this is not an interface, but
a concrete implementation of ezcConsoleDialogValidator. The menu validator
offers 2 properties to determine the menu entries:

$entries
  An array of entries shown as the menu. The keys of this array represent the
  markers of the menu entries, the values represent the text shown.

In addition, the validator can be configured to perform a manipulation on the
result like the ezcConsoleQuestionDialogCollectionValidator (e.g.
strtolower()).

==============================
Enhanced handling of arguments
==============================

Design overview
===============

The current functionality for handling options and arguments for a console
based application in eZ Components (mainly the class ezcConsoleInput) has only
rudimentary support for dealing with arguments. The current possibility is to
either switch arguments on or off and does not allow to specify the following
things:

- How many arguments are possible
- Which arguments are mandatory/optional
- Names and types for the arguments.

The goal of this design section is to provide these 3 features for argument
handling.

Clarification of terms
----------------------

Parameter
^^^^^^^^^

The term parameter is a generic term, which covers options and arguments
together.

Option
^^^^^^

An option for a console based application is specified using a short or a long
name and can (optionally) carry a value of a given type. Short names are built
using "-<name>" syntax, long names use "--<name>". Options are already handled
by the ezcConsoleInput class, using objects of ezcConsoleOption.

Example: ::

    foo.php --save "bar.txt" -a

"--save" is a long name and the parameter carries a string value "bar.txt".
"-a" is a short name of an option, while this option does not carry any value.

Argument
^^^^^^^^

In contrast to an option, an argument is not specified using a specific name, but
by by the order of submission to the program. Arguments can only be given to a
program, after all options have been specified.

Example: ::

    foo.php --save "bar.txt" -a -- "baz" 23
    
"baz" is the value of the first argument, 23 the value of the second one.

Arguments separator
^^^^^^^^^^^^^^^^^^^

In some cases the semantic for specifying parameters on the console is not
deterministic. Since the algorithm used to parse parameters cannot handle
nondeterministic semantics, a separator must be used to determine the border
between options and arguments. The separator used is "-- ", which indicates
that anything following it is an argument and does not belong to the option
before it. The seperator is not mandatory and must only be used in cases where
the parsing would not be deterministic.

Example: ::

    foo.php --save "bar.txt" -a "baz" 23
    foo.php --save "bar.txt" -a -- "baz" 23

In the first line, it is not possible to determine if "baz" is the value for
the parameter "-a" or if it is an argument. The second line clarifies this.

Basic design
------------

The core of the new functionality is built upon 2 classes:

- ezcConsoleArguments
- ezcConsoleArgument

The first one is a collection class, which takes care of holding all arguments.
The second one is a struct class, which handles 1 specific argument.

Class design
============

ezcConsoleArgument
------------------

This struct class represents a single argument and defines the following
properties:

name
  A descriptive name for the argument. This name is used for 2 purposes:
  - Displaying it in the help text generated by ezcConsoleInput.
  - Identifying and retrieving the object from the argument collection.
  This property is mandatory and may not be left out.
type
  The data type of the argument. The type is used for validation purposes when
  the parameter string of the console application is parsed and is indicated to
  the user in the help text generated by ezcConsoleInput. The default for this
  property will be ezcConsoleInput::TYPE_STRING. ezcConsoleInput::TYPE_NONE
  will not be allowed.
shorthelp
  A short help text, which is used by ezcConsoleInput when generating a short
  help output. A sensible default will be set for this property.
longhelp
  A long help text, which is used by ezcConsoleInput when generating a long
  help output. A sensible default will be set for this property.
mandatory
  This boolean flag specifies if an argument is mandatory or optional. Since
  ezcConsoleArguments is an ordered collection, all arguments following an
  optional argument will be handled as optional, too. The default value for
  this property is true.
default
  This property carries the default value for optional arguments. If these are
  not submitted, the default value will be used as the value property. If no
  default value was explicitly defined, it is null and therefore the value
  property will be null, if the argument was not submitted.
multiple
  This booloan property determines, if an argument can carry multiple values.
  The default here is false. If this is set to true, no more arguments may
  follow the current argument, since multiple defines the number of values to
  be undefined. If arguments would follow, the parameter string would be
  non-deterministic. Therefore all following arguments are silently ignored.
  For arguments with this property true, the returned value is an array. The
  default value may be an array, too.
value
  This property is not meant to be set by the developer directly, but by
  ezcConsoleInput while parsing the parameter string of the application. It
  will contain the value submitted for the argument after parsing. If this
  argument was not submitted, the value of the default property will be set
  here.

ezcConsoleArguments
-------------------

This collection class carries the arguments for an application. It keeps track
of the order of the ezcConsoleArgument objects and offers 2 access methods for
them:

- By their order (using numeric identification)
- By their name

For these purpose, the ArrayAccess and Iterator interfaces provided by PHP will
be implemented in this class. ArrayAccess will be used for both variants of
access, while Iterator will iterate of the numeric order of the arguments.
Argument names must be unique. The registration of new arguments is only
allowed by number. The retrival is also allowed by name.

The class does not offer any additional methods to deal with arguments and
purely relies on the given interfaces.

Integration aspects
===================

The current design of ezcConsoleInput is not designed to handle arguments in
the planned way. Therefore its API must be changed slightly. Naturally this
will be done maintaining BC. The following changes are planned:

Property $argumentDefinition
----------------------------

Since ezcConsoleInput already has a property $arguments, which carries the
values of submitted arguments in an array, a new property will be introduced to
carry the instance of ezcConsoleArguments. By default, this property will be
null, which indicates, that the old manor of handling arguments is used.

If ezcConsoleArguments is used, the preferred way of retrieving argument values
is, to use the ezcConsoleArgument struct of the specific argument. The
$arguments property of ezcConsoleInput will still be set and contain the values
of the provided arguments.

Switching arguments on/off
--------------------------

The ezcConsoleOption class allows to switch arguments on or off for a console
call to the application using its property $arguments. This behaviour will not
be changed. If an option defines that arguments are not allowed, if it is
submitted, all defined arguments will not be allowed.

It is possible, that this behaviour will be enhanced in the future, so that
options can define a filter rule for arguments instead of a boolean on/off
switch. But this feature is not in scope of the design given here.

Usage example
=============

The following example shows the basic of the newly created API.

Using arguments
---------------

::

    $input = new ezcConsoleInput();
    $input->argumentDefinition = new ezcConsoleArguments();

    // First argument
    $input->argumentDefinition[] = new ezcConsoleArgument(
        "infile",
        ezcConsoleInput::TYPE_STRING,
        "The file to read from.",
        "The input file, from which the content to process is read.",
    );

    // Second argument
    $input->argumentDefinition[1] = new ezcConsoleArgument(
        "outfile"
    );
    $input->argumentDefinition[1]->shorthelp = "Output file.";
    $input->argumentDefinition[1]->longhelp  = "File to output generated
        content to. Output will be printed to STDOUT if left out.";
    $input->argumentDefinition[1]->mandatory = false;
    $input->argumentDefinition[1]->default   = "php://output;

    try
    {
        $input->process();
    }
    catch ( ezcConsoleMissingArgumentException $e )
    {
        // Only the first argument will possibly trigger this
        die( "Argument {$e->argument->name} missing!" );
    }

    // The first argument is always present if no exception occured
    $inFile  = fopen( $input->argumentDefinition["infile"]->value, "r" );
    // The second one is optional, but has a default
    $outFile = fopen( $input->argumentDefinition["infile"]->value, "w" );

Generating help
---------------
    
::
    
    $input = new ezcConsoleInput();
    $input->argumentDefinition = new ezcConsoleArguments();

    // First argument
    $input->argumentDefinition[] = new ezcConsoleArgument(
        "file",
        ezcConsoleInput::TYPE_STRING,
        "Output file.",
        "File to output generated
    );

    // Second argument
    $input->argumentDefinition[] = new ezcConsoleArgument(
        "bytes",
        ezcConsoleInput::TYPE_INT,
        "Bytes to write.",
        "The number of bytes written to the output file. If left out,
             everything will be written.",
        false,
        -1
    );

    echo $input->getHelpiText( "Some example program." );

Generates: ::

    Usage: test.php [--] <string:file> [<int:bytes>]
    Some example program

    Arguments:
    <string:file>       Output file.
    <int:bytes> = -1    Bytes to write.

Open issues
===========

- The access of arguments by number and name is comfortable, but (as described
  above) not reliable, if 2 parameters have the same name. It also makes
  implementation more complex (if a parameter is removed, namesake has to come
  in place. So, do we want this or not?
- The property name $argumentsDefinition is OK for the definition part, but
  does actually not make sense, if you access it later to retrieve the value.
  Any better naming solution?
- It is sometimes sensible to allow that for 1 argument multiple values are
  submitted (e.g. if you expect an undefined number of file names). To resolve
  this, we need to invent a property "multiple" for the ezcConsoleArgument
  struct. If multiple is defined for 1 argument, no more arguments must follow,
  since the algorithm could not determine easily where the multiple values for
  the argument end. Do we need this functionality (now)?


..
   Local Variables:
   mode: rst
   fill-column: 79
   End: 
   vim: et syn=rst tw=79
PK��Z�>�5AA$data/ConsoleTools/design/console.pngnu�[����PNG


IHDRHg3�X IDATx���ˑ�6�Ф���A1t��@�1A�Ȅ�Ɓ���!����8l�?A�3?f��x�`Ӷ��j�vo��7+5M�=�S4M���cXK`TO`TO`Tov`�4M���C��k�vtj�8��&���<��.�դ�>k1�XJ���w��'��šB�KA��o�m��q�p��j�
�M��I��g$s8�63�ּ�	��U�|7�MLE���}�?)�e�xV��uL6sO�g��ueΥ�Q
\J"��s)��)�ʏ��.�Z��cf��Ef��.%}��]m���y��
MӸA�<���g6+cQ
\ӳ�5D5pY�"��2��4Q
\�/�|��_^��.���@�LE�'��'��'��'��'��'��'��'��'��'��'��'��'��'��'���q`��_��j���߶m����g8���*γ������U1` ��n���y����a�.�ol���2�I���~�����va�e�7�}�&��r#�g��I�K���wo��+�ij���`�g�g�%c���㢑~�J�����Sц��J���5�k��))	`��&Hڔ�/�Ih{\@���6��	�d�g��ŵ23�^�9���LM۶MӴm{�HH����iܠ���
P7�6@�6@�v	l&w��u������|����d6�����V(��:ŋ�3������g:b*Z�m���wB#(��3���P'��Hf��(el���{�u�8��]�&Y�/�?�Z�Uv2�ؾt/u�Avu�0&h6��k��ǼP�]��m��5�O�0�:2Sф(���%��g]�g�Y�|��� v�e�&�H�K$'Y�]I�I}� A�����m�F�m�~�}�ivL��_��״m�4M۶g�`��iܠ�������������ޖ�MrM�5���_ݿ+Xi�垇�X���V&��&3�Y�[�9H�����d����
1�����v@}�0�����b���bQ
Tg�M����G򂖮��Y����ؼ�� qf`���x�Y��y��$���D;kb��xWP��WE8�q���G`TO`TO`TO`To���q.�>Yq�����d��\zM��3q��z_�_��-~
@E6l�S�+�c�̰�V��|�f��r��^��e�8mx�ܟ(���tO��)<|�ll�-D��X��z�vvn��|׫ ���l?-�;]�ϛ�LE��In�.O���~��X�Nr<�B�|�g���� GT@�
lzqR"��8xBT�}�d�eQMa��e��X��P���q|�z|J=VxW{,H�G���
ǝ�]��״m�4M۶���Z�kl��x5�`rT�TPx��XX59�ml��)�<3da��~��;�P��i�
l��4�t����������>6�7�̔/iV���+\�U8�L��WjO��
�S2Ԓ��@�4g g�Z�;ޠ�↧��x,~ie��X"�g�֜��)�
���ϳ��������Sњ���?9Vl��L��ùC���}Y���&��$W�i�wcVa��A�~�S��鶓�Ǫύ(�D5�����
�2��|�%x�$�2V�d�`?�?�w_�~�[�BS�2����
�s�I�S�G5+%�����T4�r��&����}��\E`}S�U)l'�_B�i۶i�5��-��!<���V����h�	oc���aV���P���;�e��jM�X<������o��ܩhM�l�$����W�2�q�N�zG6�5��dl��	l��]e�g���ml�����X�}�c��u3�A@`�8À���E��N6ur/��H�L2�F8�v�6��7���@`P�8�$F
�3�b�3��b����&/n
6u�]y������ئ��x`s,.�	l�V~�}�Y	�Yi�|� 	S�5$	l*6̢�R׽$�,�%٘��L��2�.�M۶MӴm{�H�}5M�t������o����_f�m��
:��	l��	l��	l��	l��	l��	l��A'<H��j$��q�N�V~�b*P=�
P=�
P=�
P=�
P=����x����u���?+����k���ñ��N����ϋ)
�w��`��N6�h�N��H&��{���%�;
���X4��N�p� 8��h@� -ө.#1l��x��
�
��
��@�dlࡆ'믍fj�m�	� ��L�����X;}/þ�nɼӬ��=lࡒӷ�js�d2CR���S����8���X2��Z�������=�\��m�0h��!/P� �;��gr&Xr
Yf�OO���m��i���j��pUo���>��/_�̪�4��
p�81b�0��8�0X�}l��	l�ꙊE��9{�mY�`=�
�������V.�o'�V��~^*�p��`;��,|�
4��6!��G+��L\+��{��Ҕ ~5���M�TLؖ�N���{�1��
�K3՝��
8��>L�^?Qu�'px���<8Yߤ�8B���iZ�PjV�x��Xk}�a#񔶹�Ku�TJ`՟�oxڝ��%���kN\�3��ʽ�w=ٗ�#�6�Lz����[���ZD5p$�
<��3�a�29O,^0`ٹ�0�_~-.Ό!��`��ha48LӶm�4VЇ��i,�������g����>ʀ+[�y�4��
p�81"��"��'�V����%c���ߓ[�����#���`F�Y�3�G��c`�4�~��dֺ�����������7c��9�{��l%Ƚ�Y�|rfi�ۙ�xIRh�ӱ�/��w��K!�ۙU�3k(O�
&(�ö7�˚�p���s/��y���&I�łg����^�c��bA��f�{�wll�y�e7��#��n>�	�i39��8*6y����ؕ���|���m�}�.%N֍0+O���܁�C��x��c��d�d0s����+�|��>�H.B`ԡ$G�yiֵ.���9 �1��I>H�x��d=8�ߤ�8r���o��܏d8�xJ۬�e�XF`T`��x�.I�,�e6�2��+ߗ��|���W
���3�1}+y�K|���b�� �^��\8�#��G��ņ3��L�Z��+�Kɗ_�ca;��d2�5<��3�-B��t-�����l�U=���'�à%y��P�`��0`���0L*�Ɩ�+�⠫|<����m����� M�����?>�}v�G.�xvr�ǚ�2���|6M#c�/N��~�l��	c��~9{k	l���t�6ovV����f�W��T�	�2��]syV�P�g6���������n{��5^I�v�'y����8����$��[�V=��f,�¸g%p�6�Il��I�d��z��㻪�w�.�x/�>��=�	���i"�����1�<��{���_�L�U�W�p$���
@�_ayֽ)��Qv���f����],������>?�pT�C<+��dQɗf]�2�
�Y}��#�� ���ł��|� ������GD�*cCJ;o2Ձ�zP`_��b�dr#~�$w���X�|?sl,�����'���&X
c�.�x
†Yٞ����p@�ؼRE�@a����*���/|iY_�؂e�d˶��e�
�ҀzV`�\���X^?�p
�a���L�8�M۶MӴm�}�M�6��������a�&�gk����v�?�>5��M���u�3�ۚ�jX����il嗳U^2;k������0��_M��:���WO6�����9��3�;�����H��
,d�T���7�q�G�Y#��mx����mK����pY�6�ZS�{�H�� 咼l&��d#ȴ̺Hf����x�G�X��!�a*T���z�x|E_�$W�A�Z�3��8l�U�׮���q!%PB`��+��賦Q%����=
N�
�LΧM���>�k���.�1`�"6�Px��~�;�glw\���k�e��iu�|k%�CZ@� �fH�V����	�Ww\���_�f0��ޟ�ĥp��mۦiڶݾ馉WE���&��������o����_�����)$����([��e�5�|6Ms���C>S�)���:��%�Q>��\�6֔̌ߚ��q<g��x��y�	}��|�j~9���~��Å#�MgN�5%3������Ļ6|u�x��X�d�1p:��du�3p��369��ݚ���x.�^^`�C�����~�̬�XS�����\��H~�|&�?��;�0 ?{'�}��p篚X3��a��u��+�xN�a��L��I�u}[�9�p�R�e��_��I��ւ���YS�����{���۸�r��=��x��ӗ{ج���Z���[�’�{��\��Xl�{��������*�����Vڌ��my�A��q� ވ��<S��a76�Y����<�x��&����g���R�s���|+48�p2hI.�8l�R�h'w9��{���䛐��5-3m�t���gչ�56�N���pF;�p�'W��U�.�'׼i��P��6�\�_]���e3�ZX�wA��w)~~�Y~EЕFp`�8ϐ�=���~�N�i�ӫ���#��Vp���+ǽL&d�*��q���ucoņ?���WE���+[��^�f���Iɛ�8�R��9�7���^XmW~5��ς�[�*��M}֟®��Ny�3���VE�Ú�e���5%k�x.�G�3<�/��ς�;.��!8wvG�҄�
'O�~���5%8����㸩h���W8��O���uY������5o��S�0��C��<����ۡ��nMɲZc�R����s�����x.��xp����e3�M^��N�<�OG�_*?cj���Y=c�L~�Tɔ��ONF{+6�Y܏�������w��:��Y\j��]9���ς]�{�g�r+�{>n����*���u�Y��=�?��[6�3	l��]}U4`Co��ܔ�Īh�e����T4�z�z�z�z�z���fMI���p��_��/�R^�/���dS[�ߣ�YXVv�o`cMI6wbt�x�p��&7;���9k����?�~�υs��
���_{
΃��������ϧ�Aj�5�"�鰑�V�;g<�x��o�dG��@?��!e�L�3@���L���ql�y8�w�7^x���k���8��Òd��zfT�.�1����iz\&xilJX\=��c%����!M�J&:�|�ܟi,xu�C��Cx���(ly��٩��v��hM�����_�o��cl���O ��R5-����2٘B�v�=:e������y�
<�'�����_�'/���%ۜ,7w46�1�6���q�o�+���L�J&�ƪ':�g�?��i\`l6Z��hڶm��m��n�*V�Z��Py��GҲ�1�?�[�Ŏ{�����m��e�.��c�.~<''����e���#?�j�([��ߚ]���)�z�Oc�X�y�4�����7۝�e;Xr��
�lo�;c��G�J�C�7���U���:�|.�w�?��&Sђ��87=��.��cd��q�N����L'��a�#/J
]Nj����?,츂�y�M��(8��w�dH�2���W�ۨ�(�b��Z�l���p�����˚��)�/�fa�2���c���}�i��q\`�?Oڰ��b�OF�|�0��u����[��NߋB��d;����oxmrH��o-�J���LE딟e.>+��D6��u�+|��t��p'��Y%��ݣ"�=������qr|�9�egr:��p0-'��d��������I��46�%3ھ��IMc��㟜����ӏ�X���̺�!M�U��&?72�;��X0�vA/�9����o^V�{��D<��W��d��~�nܬ�ws��y}��^n���u�����جXE`sp�pb�Xe�=�R�㹿�T��8�7�����J����mK��_�T��iz2E�o�%����~�3-{:��%p���v_�|ɐ
߫�|~0���E�V�L2�<�pl��yo�ҁM�k����^��m�V�I����w��u�"����8i�����̤��e3�S�����q��!�%�j���oVzy�a�ҁ
������Z�LK�$��y;%���^
��y�
�.����&�n�S�6�qDT�{+\�Q>R<���R���l�VV��g�{�O�����=����Ȳ�A�ᤦ�~�,Øl'~)n�"�VL�R'ی_���^��&���	����T&ߨ�V撘ɄLɅ=c���F ��U�2�<'_�ljYp�U��u.���:}U�����l]�wm>:�䧮[�*�/ۏ(똀{�ߙ�71<�a�D�'��l�W�I����̒	�u=FTî*��V��n�����?~^�1��Ir1���d/߻?[�����W4}�A�e�W|}��5���?�m�Cت)���?��Tgf�Z�,�����n��٫�� @��עF���2xf�+L!p$��e�,^c�
$c'��mN^W—O���x^@.� n��kl��/-XV=yY¬6W^ذr���r!�G_c���*8�����
�q�����:�g�q�L!p�%IWΆ]v����5��4�xؾ��*^�9c�O4Wp��gY�7��ӗ{��%��_�,nvn�|�6'�5�l��c��<6�G'�/�	p��)��ϳ-�[<,��"��L�a/񌌾���]ˏ9��lv�V�Lr���ñ���6*X�y����Pr.G ���\|�K�3r�'Ǿ�	ʗW��2��d��g�c��59lk`¤�6@��N��Yse�N,�
��s*��>/�����'ʼn��W��Jb��dl�ю\�4�z��N�N�ZVq8�xbX�GɄR��J�V��N&d�yzc#ڴ&��*Z����Ƥ�9eb�_m֜��?����*���tJI�{��]�U�*ڮ�%�I�S��c�9}$��:?\�pc'~��]�j`�
��[��~��/��䒋��}G���W�%J��H/>f��;ހۻ򉾅X�"���&8'+����&��j�b���
+��yE��+6���yl��a�/�x8.�Y��d,s7���u�O�g��c%�we���/n��
o@�\�|����L2��D%%�ǐ��M�xn��f���$��L�L���|���’Iqf��J->�3��+�4&�;u���?p�Sp�����¬ign��7��O�a.�Op��W�>��ޑ_��{��:roP�ӗ{��s�fqS�w��cv�����0+�{��T�m/\9R�#�F�7�HɩceJ�J���I6�!ɫd㗒��1�\P�9g��PrO�-��Q4V+x&��{86xb����WͿE���+X0�m��w�l����'���%L����ì��g�c)�L��8�V��Zpr��'c��Z�������2\_�
���SX�]���,K�L����-G���I�
�-�%�fH�Pˤ#J�I~�V\�a�U������Y"�oa򙱮'����ԏ�ʥ�v����ÁőX��XT���J�"�x$�2�f�e���ꫢ�H~�L�2o��k�w�U��ұ��e#9�KS���WE{�?�J��cx>����U�~�~DY{�]i����w{xa�VmR�Z~��U�0�G IDAT�T���S�Q
�rt`��ۯ�u��g��W��2���Hq��������-�u�]��v�P���L��y�C.�H�0�+��T��'�����;�;.������Y���`Fl�K/��/�8|X����ᰅ����Ȳ��܃#��PFcjr`�c;ɰpro����s�.�&@�q�l~eK����s��d��d�Tg����^^e���#��p��l��U��O%�R�
��k����-��Ϫ�.�9����9:����v<����Ґ���w1�Wr{�S)>���Â���:T♙���X�d����#�G��O\��md>-�_p��Y��ae�����il�'�\�՗{N~�]ĕ�vcw]�yW��~`�ӗ{��wn��<�?���j�M�;0��$�Ke�=��}�{�_�+�
�&s��E���,f�/T	��0����d��6�A#����]ǂ�h]�x�Ɋ��	�M6R>N��
�����ҕ�C{�~�F��|�/r<�4^kq�ij�L*���˻۰��vVv��+��;y���|�|#>ҩT�
����?�B�~�J6��3��oT/��Z���l��phn���
��,X��s�g�ؚ�d�F�"6�h����s��K�&_*Y�19�a�hlm�8zIVLv��Z�򮓽ۉ�	i��'�7����h�}U��I�ɗƞ|�	
�;}U��Y�]�BZ�\,�rU�}36o����'�dBBa�k�C���%2��Ż�s;6}��z�_���������&Nt�f�S��~�땜T0���q��8Z�����8��8�Wc��`�Ա� �������Ɏ��Z��1�
��������?7��;ԩ(��{X�
�M�T��#�#��F}&ǡ2�_�dqO�~~9{<H۶��$~��g�4G�g���o���[�oAq���GT�d1�����͕��Zؕ�hp���tc�l����ې�:Y�6�d�YM+^(���E�n��=��p!5&m��A�78�07gHƞ�Z�E��M%7��#�Cۈo�y'�f�0IƆCu7����� �VZ��c'��]���D<��f��
����b(?��,�u)�Dx�=))�`��	Q2��jY�#�J	l8Z>i��F���
@E�w^����Z��◾X��#����h��n� �0�0����JN*+��l�'�-���1��K�.��ȁ���s_�s�x����6W;&]����=�޷��Q��8�s���h��a�426�)�^��*Z�&<�k��5Q
\���k�C��%��|��~�H��_��������f�����
�M�<{pi_����!�Ul�.�
���ϯ���!SѸ�.n����P��_^p�
8��
W��6R7г���\���ߺ뛊K7�;Z��*�z*ж�ii�����QP�s�ƒ��$�_����7�^�����j�m�%]� qd���q�A$0,�m�闸���x)�N����ɽۈc�����	�������m &i�b�y���.��J�[����t�t����X��X�c#����3�`�'dž�ً|�a������E���������Hװ��Vm��)�Y�B���u�t�•	l�O���@�K���t��L�L���W,,�8��6���ʽ6T�;�s&�>�ƶ'��IyN��ᔰ`�bc��'�e˜x�[_���_��X8�����hL�j�^�&9M`C!��Z��rj.�����g�=�΁M�X<��YND5��e7�j��'��Qڶ}{�8{� ��c��H�<�
w��6�H�:n�m[����p+b����&]=�
w#�8]��ۯ�
�M��<�jed �>6ܐE̹=9�u	����v1����􁞌
�d9������n�$�2�B�p��3�Z̙�qi�_�.n�ry�9����.��J�g�F��򹔠���䜴������Cq�ɖ��3��3c`̆��&=f��6�"?w%���6{�
/�ټ�m�*"���6c�
��3}k�D��2hq�d�f��т�s�F�J5N�x��zG;�ࣛ����ן+9}Q��������g����Yu�����A��@��k�<p�5	lxYJ��N�(NpA�{�,
p3Jlp'���m�77 ���ڶ���ܲ�o�����_y����!��ҀG��I�����[��X�[:��p?x��6s9�a�%�oy�|wA#cU�/
ot�6��qi�_�t�b�i���Y��9�>��?,/<V&(0��L�f�n�����}l���]n�'��ч��״슝��%���t!�;x\Dw�is��%���.u#��`n$�O��\�򊢂��Icˠ�U��O�W�iW}���*�8��1~5�2�'4M��?����yn���3���o����_f�m�F�F	�j痀��@��ָB8q�1��3Lh��J�'��"b�+�@)�
�e	l`�
�5Y<汜P��������
�օ4V���j}��~L�_������M��
,�.7�>��t��& ����6�>��"������83���q
��4M����?��ޚ��*��};`�4���8��6ж����gʧk#��͈m��k�#	l`Kb�Q�k�����6/��p�{���?���kܵ8��vх4�n/c|��pؗ�/v���\��[�!p�c�s�
p?�l[Q
p؝���.[(��F`G�b�
P;s ���A�/8�6@�D5��	l�Pb�F]�YT\���&����
8�Kn�ZH��p�N8�;xׯ�|�@����LK���3�:8����d�F8���Q
P)��%��	�,>���	l�*,'�ȇP;S��ZLK�'�n@`�#���SKT܀��Hl����lࢺ�Fx�D���
\W�M��؜���
\��ؐ�j���@�6�&\Tܘ�� �V����
:�}l����G��Iw^�kW��O�!LE������!��*�m�I��Q6P+�
0ƚ���*f9 &��I���ݒB��j����m�π��M�m�ɺ�FT<���Cl�$Q���t����CTб*�Mw��\nϢ�C26pO������  ����]I��6pgb�k:�q�
�\�8��	i2dl���R7P5Q
@���Bl��L���m�:.�($��g�@E��PN`���6��8��Y6�D�����%������`�
<��.�E5�	l���6p5k��=�|}l�
N�`=�
�z�}F�c8��;�M����iip0Q
�V6�O�6pQ
��6@Hl{��3��\c$XN�#�؃�
���LC��%�؉���VL?ؕ�� �����FT��
0MlkH�@`�b�
�%�8�UрR�ə�4(diA�#���%\Tp0�
0���$6�'���@�5���`�>�q!
��dl��K�n�%�8��XKl���	l�
�mx,�\��؆؆��3�ul��t�������[����qo�� `{��qc��\��؅؆[���,�
��
7#��2��;�c��T�ap}`_��v�^�*����4*%����8�؆�t7e��B`GlC-��P�
p�.��pe55�G��pM��J	l�s�m��TM`�Fl�u���v�Lb�@��ܠ8Y�8��x�=�����N+}k�rw"��N�!fZ�,ޮ�v}EMG��~����C�Z���=�g�xP=�����Ɨ�_�	�����������������������y���fJ���+��=��x{���ן��5F`�D��肄a#x&E#�|;s�;,��=��n�p�8��`�8��əd��z���I���|#�Q��6K������)���\��3	l��dQɗ�S�kI��L���.D�&�,�%٘��L��J��J^Ó/Wдm�4M۶g����i��>��eo���>��/_��:��k��}l��	l��t
5����������s�N`T|OF�k��,���^�`������������'���ţ�x�*R��S8�垁����K����i�<d�`'`_��{�ޟ�O�s����V�̰b��|N����W�36���L��\`G�p�?�>�K&kU�r}�d;��i�L�d�0��
P$�6�(Ȑ̒-�36��� ��\$���)�c׷�.�^X؜��Q2��|&��O���L�F��.� c��
h�`&��?s�@�HӶm�4m۞=��4Ms���NG�m4M�c���g�['�1����?>�}v�_�~9u,��4�=36{����73v��d>Jl�r�N�P<��w��o�����{�a�������<��G�o�6�
�-m|��l�_���
�]�1��y����$��o�9\�y��@���q��?�أf�ѽ�|��9-��?��]��F�Z�����݌W=�t�{\�
�w�L6;,�vP}�����[�.f�K<�
�=
U�<Q`�I2�B��a�a<������0�H*�c����|�-)i*(����"��F<��zEA�TO#�y�d�$~2�iy��|b%e����A�����Փ�L����,���.E`�,ɠ"�B��Z��	s{�[�3v}�X/s��ٛ�	l'��G/]$�L��R9��|��Z<Mp����x`삙�$�`��
o�W�26���f�R�{��LN���^�hڶm��m۳G���i�I�g��do���>��/_�l�8��t�S��2<�O6�#5M�>6��ny�/u�8���yd�X�~Q�+�S��M�,�
P=�
P=�
P=�
P=�
P=�
P=��u�͹	Ƭ�p3�z�Ӽ�t����K��}ɒ��
�����Po�?��+�p���?��/+��Y��@-6�(�1,�{����TO����~;x��O0�[8��{؜&y����e�E5<��h@�6�x�<�
P��_[S��z_rA��k�6�7;;�������Z�t�n����l��[�E�&���;|��23q�a���4��`��Tl�y8�:�	bVEK�Wް�|��E��J�Z�yX8X!z�];r��iڶݵ��S�eY����ֺ��aW&Y ��U�� ��w�[Rk2#�:[��X-�%�I
��î��ڣ�e�����6D5g���wꢤ�����`�P{�3P�M�{�S"��L��kgn�I�dʥ{2��X���Ɯ��a?�Y��$�̣�GM���]����0)����^n��'�AP��I���g_�
:�7�*�.��7d�}/�e��e�i��,G��†�R����}��ioˆ��7d4m��종�i�W�L%��%��L�Ɂe:���DP�2�PK�4k$o���>_���~ힹ�Y���]e){�v��q����z}���Ա�_�47�ؼ�YO�i���Jj]�q,����C�C�� ���6�9���JR
��\߿Q
������!��a�d��#qF"hy�V�|����d�A�WY�%��c��T������\�26��#5]Hs���X6�~�?������*�6Gz�T4j��%1�M��6��~E8����@��o[]��Wx����_I�5� ��]ٝ���0*sbƦ���\�t�ޭ��u9�e��-�p_��LEvܡrx;�n;f$�wU��n���g���w��i��|-�N�o@���tY�~	��ap	P�Ұ�p��K��IY%'�cg�}~�$y2Y%h6��$��w�٣�øb�ĵ���F
�CF•���K���뵬��͗TKn)��3�
�g`܉�/��36]�}/׏m¡��q���o<!
�t��]��@4���¬3��B���U%�E���`^Q�0�!v�l|���
��F�
��{b�K��e��O!{
,��g��/���u��n��kx�_��I�em��v�O6�[j��r�0��*�?��	6�Œ/���I��ގ\�YT��׵ST0���݉j�0�z�z�z�d�K��~���WRe�2����}l����W|/�ɾfxL���
����30Ç��d~f��X��~�}0���y8C0$�8��(ҟ��:��B�8Ӈ�K%��|��ٸV_`n(ha�r�p0Sр"N�:%��E+����l������c������`X�6�sc��
��3}kc��8��&2�N'/�I�F��\GӶm�4m۞=��4M��?�3��|~�춿|�r�X��M~�6Y|l��ˬ���|��i`G�^ٲ��XF`�k}�S�!��;��3P=�
P=�
P=�
p�YK'���~�m�oA_�����B�&���jV��D`�뜹v��n�b��=L�#�#��dT�)����K�������e��u3�]�{1��į��q�c/�Δۣ�����&�0ο�����Y�d�.�2V�Ϻ��Ov�o��Շ�̭w$����'A�d��7-(<^I�oEa#�8��J�ɧ0���E�g�g�%'8��N�Ǽ��{}.HG,�`��+i�$��l<��3	l�[I�G
c��u�F}��5�d0�oŶ�	3`�
0����8]������t��9�2�k��n�k�
�C
:J�QP7��?���;ܝx�î�2��/�w/!
[hڶm��m۳G���i~���٣`�����o����_N�u��ґ����5kn[I��O�+w�}Y�'�����g�����!�6�ڛ�nI�]g�]����0c�����!0��5�C�֐�8R�4�{�'��w�kl:R��26�AƖ��,����o�:�or�r����#�	�
0�'��=U��\g���
y�
	l��� �WfI0,48�hx��a�ɺ{�K�d�M�E�N��U�LK�x��	�)}�|�A��������uwݗ�J��8Uu�\͝64ʫ��Ca�e��̺�沺�����l��
����/�eqݝ�%#�Mdl�f�����}������ĭLGA����v�`nX�n<�=�%����kڶm��m۳G\K�4?��s�ƏY�lM/�涕���m�����g��j{k�����;�_�Ȳ��"c�횱�ۓ�8��
p�z�z�{�����so��z}x`�Sn���.�|����5����;
B���Û]��-�:���]�=�o�9k<��6@��t��D,��7^�("~)�4�b��I����ɑ��.H`�㍒*�qd2Y}YG��O`�hY8���u��	i@6��r/��L�ex�����a�|@�X��p��
���mۦiڶ={$��4M��?���u�`o���>��/_��:��k�F���m/�� �nHHO��@�6@�6@�\c�o��e�u�˫[WnI���j�x��3y��^p#�6dl�ŷ�ެ3(�)�|����Hb'y_α����8��(ҟ��=���m�E�{kf^
"�|G�,M�G}��H�jg�E�b� X��#����ެ�6�,�
p�8%�)-N�4�2�4�:6������n#��?�(Y+�Q|UL> �C�䔹�ngiڶm��m۳G\K�4?����Ql,y�������g����S�pM�����%7�ul�g��-�A'P�J��IDAT=�
P=�
P=�
P=����?�@�
������sG0�T4�z�zM۶M��sN��4��
P=�
P=�
P=�
P=�
P=�
P=�
P=�
P=�
P=�
P=�
P=�
P=�
P=�
P=�
P��m��*�>�
�̺v�IEND�B`�PK��Z_x��!�!/data/ConsoleTools/design/console_parameters.pngnu�[����PNG


IHDR��� IDATx��ݱ�Ն��:םA�`G�v��T�!L$�/&�I��8��`�O�.�4,�@����ԩ��%X�6�@����q������hl*^����^��]�mA]V�.+P���z�^�ƓU�(k,�Ē�6�Շ�{=��N��rgh_69����?�3H���.%�V��K��rH�Qi���A]�Xl�*�fJL%��8���mL�u��?(�"���*�|؃������#9�]��[�Rv�h�ڏu���E���a���tV�ի��:��+����np�R�>�o��%W�z)UZ�K�r�3�J���1�%�B,]�c��C
|��AZ{�����Hk{�Wע �'������
�z�]���/�+H�9��?���@]V�.+P���
�`��uX���@]V�.+P���
�`��uX�X]���S�<!����k�a�zf���h?v-��Ϗ���[�°"
���\��ϿI��v?��r*��nz�A�!b�R��z�ۇ�쎞�4��bz��{�z���#�o���b����ծ&L��9�Ʈx�U4��v��ڕs�o�d�8E-�Rz����%�颙�k�e�����ix�R��[�X�+��O���/^o\�ȃ,Jz�z&��d�u�79�{Ж���`�x�C�0v���`��uXa���Ed�`ԍcg�Ս��
��e�(E���~׹�<����;i��":S�cf�w���ڃ�� �iU/+�
�T2��+�1����n���a��
>����\���_�q��
��h@[��a�s�TwE��^&~{�~f�Jly*��m����5�9=��cWpnvk��K|e��e�_�<|�G�va�/���kpB��
��`��uX���h��J�kϛ?7���4^��4��Გ����"�sEs����K�nT]Az��0�+�<bz��������<>�rċ�31W8�+���^����)_�`sL�5�T�Y{/ �.^p����@]V�.+P������2�j�<0�r�����1�!5YqH�qZ���a�>��j��_�z�������W>^V5�%�>EU�ә�F�|�����ޫ�ѽ�������r�_٫�x՜�N(ݞ{����?�yo��v��
���荢ʖ�^1��iH'u9����f�߸�"��{ҪDT]�1��Cu��Pj�#v�n?���Q�.Kf��v�����`oj�+5���t}�P���=�({�E��X�Ҫޫ��:u���9�xA]V�.+P������.�*��w��̾���gU����.^��ɞ�wEoϪB
G���Kzi�X;�.���VZ\�Us�x����wio����oCz�x�y�s��yq�6du�����5�(�9�\���x�;�.�T�xg�����"<\���
�	�]��.+P���
�`��uX���@]V�.+P���
�`��uX���@]V�.+P����fo}�^�B�C��Z������F�ۧ�5ٙX1�{����燿}�[i^�.+P��&���g��0f�\w�\ح<�_�F]0o�>p[��.����������3{*H��Y�Z�'��N��|5���4��┩\͚�0@%�oǜ#o��Is�S ��`F'����`�Y���)�`���h&N�R��@]0zG���\��'fLi.6�wX��`&�C]V�.+P���
�`���w����rJ<?4���
12z߫L���҄nfl�#�ՙ���ʽĺ2S5�1F]�YV��Î��̷���2��(! ��[�<gx�䨊�O����g�.s�GʆacWppEØh���?Ŀ�8}֩�A=��1z��N�8xjWб&9�G��]v%HÃ6jH�hf�?�V�X�����8}�������bC�!.?ȍėqD��,��fcu�'�̽1J�,ՀrjP�P*-+'W��<�Gz�9�1gQ��+��(?��WO�O<R~�.�5�xcθ��l���h�����%��F�H^|9��MLy}||�^��W�7��ߘ��_؃������o��v~.}���n2�c��7X��0vX���@]V�.+P�-�&��[h�*9@����!���
�`��uX1�ӓ�����@~��n�˔�.�?��O�����TĚ��ގٍ��p[u��H��;�*&�,1N������j�u+�(5Wb�7���ܷlļ3�v��V��,z�3�@���������'�‌Z�������{2�����iĹ�ٍl����w㺥r��Q� 9�GZ
�RWj�ԁ�3�#1���\�+5�d��M/b�뺇0ݪ�#_��4�sn��Z��)��zU�Xc���R�}�x�0�AN�d�҈�%'lQ��5RE{��I�zГ1�X��wB�;3lE|"gj}�_]h	F1�.��A]V�.+�����+����ڕۺ9�~��[b�FM_��f��{2Cvbޙ�.ޚ�fdnj��ENm��{���|㯘1g@n��=a�j.��]�5�)�Y3 W�x�V+��zviw�;[��s�����)��_��6�h{Y��"�RU?Ae�V��H���\�0��Յ�`�j���uX1�uWg�e^�� �h��/(�|�W����|�����+vz��q���b2�6�"��q�6t[ߤN=���w �u���͟��{+������M�.�����1�2{%�6߁?�ZL�����j~�n]����f��ts&����.�{y��A�K
B�]�o~}������\�0��Յ�`���X�`��b���.^�,���w�v��<��gTܱ�.�n�ʇ	�wf���+ƹ�H�㣽]=�.�HM�hq)}|�Hk!p��Xo�߫����L������B��6u	
�\o%q)}|���x���/�bu�%ż��VuX���x��D;�)�ꚪOUxs��>��xRև�_fFn^�n����V��X�]��-��~��� v[�4�.積��Ɍ�U�g����^i��.^E����X`Ej��K�\3���z酭	.r�LQ_UX��\��tA�p�:/�-͈mr����#0�.ާ����\�b��K];���@]V�.+P���
�`��uX����Q����x/lF���
�`��uX���x���~��&ˍ��2[�Su��n"�ꚶ�x����~]��,��������k"�t]�*nq_��q~8S���*E8|�)�	�T5պ���$��%�Ģ��T���G� ���ㆴ<��o����8��?~wǗ/������E;?_�z��~�Ҽ�.�E����v�7���l��^v����o�q|�����"�Ʈx40*"'��sҽ�'Z��&9�{s%Wi�x�U!?q��n2��O.93<ɗ�m��;;Y����$'ZJ��B�ɯ�Ѯ?k���"��X\�p94�W2~��|o���)�ŰJM��s���+EP��G�������TA�G�	s��wr�����:���iT[��u��hf�s"ۍⓟE�Cm�BBYHZ�0v$�=�����@]V�.+P���
�`��uX���@]V�.+P��(V4S�{���bnϗ�q8�~03�u
������芀͞M�R^�����%<�`��9w]0a�wB=
f�O���
�5&����অ�joP�0|m	��u��eýA]�I��39���e�b(��5��A]V�.+P�H����`��u��5ýA]V�.+P�HX3��`��u��5ýA]V�.+P�HX3��`��u��5ýA]V�.+P�HX3��`��u��5ýA]V�.+P�HX3��`��u��5ýA]V�.+P�HX3��`��u��5ýA]V�.+P�HX3��`��uX���@]&�Y��z2��
�՞s��/����?�Rwh	�j����.�������������z��]�F_`rD���A]
p�h~w����JA`K��f'�`�FW`�!�
_�C�ӌ�I�,��O&-I��_�������
�`�	k{���@]V����T�7��
�`�	k�{���@]V����f�7��
�`�	k�{���@]V����f�7��
�`�	k�{���@]V����f�7��
�`�	k�{���@]V����f�7��
�`�	k�{���@]V����f�7��
�`�	k�{���x��̩��a)-U��8��?~oR��>}]��XQ;vt��燿}��ؚ\��`��uX���@]V�.+P���
�&��3ڴux�}����=�eze�!���ݮsU.�����Q(�a���z���9ãP��K��rN��7aOuţ��=��C.�d��8�<�+��b�1Plc\�~�UC�T�!=��RQe���P�3���F��X�mե�'⮢럢��L��Μ�E%2R����ċ��xcθ��J]5�/ګ'�焙��ۼ>>>^�׽��_�?	�����o��v~��������d+P���
�`��uX�������� o���X�l���
�`��uX����|��W�~���>���R��O���S��Y����̂L���L{u���w]�@`�.ecił-�B�����R��pL;3t#��g�T�����_?}>���~2�/8�q��c��o��3}j����Bŀ�Jw��������^1��"-���#F�/.�x+M\�.����-�W5Bjuā��������̙�K�O/��A�8�2P�sK�%��X�P��!�IaCu�%��I�wl��uX1�����wB��h@�
x��W�a�INe0nƤ3�\�}��ic���#�����'\��,����/�ҡ���d���T:t�֮<��맼p:8t�奋|/L.^X	\���������L¤��6uX�������{H��b^��-��C�,���S\�b���D������<-��M]�������<���hM/ZO�����=}�祐�A.��n<�.�ˌ
�>��A�Ig�͹���}�~�{��̥d<��� oiqЇ��x�f�9�k��ܬ��yӠ�xa%p�/L†�BK0	OY����uX���D�P*e�����R����:��	{��4��nF#���f�[}oQ�3JَD�P`$�O��NB�Tm���z1{�թ��5���Wבx�H�0R�2�	����#��oa��l�!	��F��#��ĩ�Δ2�ޮ��!W���G��xƕ�+'�2.ʼnkj���=3
L�3C��'�9�y�/~:p�� �W�3��K/�Gj}e�̉�<�<!��E��A��d����&uX����V]⽲̔��ӷ3۪+�m�T}	N��_3����)�H�,�O��������W��"������ś���R�����#\�5�F��|��ڹx�k���fY�����Ż3�9}q�����xu�c��w8��M��uX���@]V�.+P���
�`E�W�
G6@�Zuջx�Y�l���
�`��uX���x���~��&��O?߈�^]�uķ�~~����~ݬ]ЁeƮ`��[΍��#1F������L���+�0�(Z�W#貮_6�|F;?_�4b� �R+�]	A(?W\�T.ؘ��{|s2#;aܨI��3R=�ef�'�����RC=�k�Va-ڿq͢3c�����#j,�8���QZ��^�ve��x'G�ƃQ�.�rN�c�t�%<���Z��.QI���V5uX���XL]�*H��H`�jN�� %�5}�)v#��Y��[��p�ص��n�X�]��O��]�zw�����>A����q��s���S���	���]9�]9b7�8sps��t��<���u�\S�xc�dj)���{�D�S\��]��ˢu#�z�Һ̞:bEqba��l�M�s�x3��^%�X��<��ܤ���'��}nw7"�>gȯ�C�l��c>3�x�K��2��.i8v]���/�W9�C|�RV� ��%�B�_6?U�q�v�pf�a�*C��xF�v�y���Z]�:�F���k^y�����XK]�y5uX���XL]�}i��\r�E��
oT�-zdi��V�[� ���t;�<���������2ޫ� ��r� u�4���<8J�]2=�rs6r��lL�?�6�-o
��ƿc�H.�S\�n˥�4��։���
9�3MCb.���-MZ�rf�AR���A.���/��H�
���xғ���g�>�����&@��\�>-�޿�d����oЇ�ɡ�z�G�����xvT�=���2�8[ӛ�٢���Y��
��	%N�Ұ���+�!�ZN���u̷�4�;�:2���b-u-��X�`��bCu�zƷ5��{/`e.�d1o5�W�|_�E{���x�wE���*tw�hHU���4�-q��hb}���97��8��>o��h��$ҟ)\�1E6V]K�WŐzH]�siBM��MY�*���A��s9��lb�T��3��7��9�b�ɱ�f�/�P帜Z�׭IM�Oꌟ���Rj/�O���	��q�2~eM�5�Q�w�]RǮ�Tv�2�}���Al�rŘ*+��n=�;�汱�w�&?z�P]9O��w�����[:��[���.x�]p[:�&uX���n�xŔ��^n�uY��\�?�n(��j�
g���j���
��%�d
ݺ8kW�����(��ȭ��v-p��	�ݸ��n]�n0��3�RL]��<-@��]�n
�ک��{�{����XP��X���َ�vf�wB�������P]����j%}��m���Q0v�ql���`��\x�^�[飭�RN�����f&�	��\sw��ź�"���]����B�j�V=Ū�-���?G���W�W;��T[,1n��i9v�9L�d�-���	��rD�|w�+�p�_�B_�.�0U���]b�E��
�+|�]�JU��xS�v+��|/��hP�z.ހyl������E5��2��+FȿB�t�fF��k�j�R�[92ڎ�w~pB]<�9Ʌ�<5N�ň}����#�Ea삕`����	�%�����f�b�EX��.�>T.�Ͷ�K0ޫ!����|U�t3WLD́�sl��h�S��7�u{y{�Y�ůG����R��J���q5Re�X��+*ǷP)v�|�~�P�|�Ɍ���iX|���$��E����>ڇ3��75DģG��x����'���ui��G:�P���w���1��N��YR���7?v�����('@gP�k��w��e�Ŷ� e�evV��d=�{ƛw��ja�/�L���1��]��1��㺴ަ��.�_8fp��}+���s�~|�,���Ud��Wl�1X~Ȥ.^ef%WҗNҚ�w�|r3����l�,{�G������]�����J��뮢]zze��n�zb�} �P�w�'
+0�-����;;�&�qfh��� �.8�U�P+���XC]�/��_;�������LK)�wl��L�^�J��ٍ?�s�qMR�F̻�h9v��Q�4ɝ��-~?D"��8��K8�$�ĥ�)+��,�8Hk�s�ξ2��u�2�ܕ)f�1J����P�����w7f%o<���C�$�1|���j��e�Lj�=k9�ƫ�h�J6��G�e
��b-u���X�`��b
u�v�x��>soњ�3[�g�g�����V��xv�)Ʈ����ל�"�l"&�`W��K\%�2����AAJ��
��W�*�-b��n�*�O�u��8H*l�z.^Qf����6�"���z.�&鏦�|��>��\��|Lq�`Hf'YIDAT�cԥ[W�R���>�P��8f�R��'T�}���j%i�%��.�|��8&���%���5�����HE$�\L� �8o�2��였!�)����GK�ޭSw~/��D[cPD9�@*��/�hN}�M�ra���#��[�5H�*0�u�^�,��cD�f>�S�c:�x��!��
u��\Y��0�����N��.�y�T�N�2:�x+�����Yk쪽�z��IU��J]n���{��l��.�]A]VT�j@�)V�vuX���@]V�.+P���
�`��uX���@]V�.+P�����0�BfQ��eIEND�B`�PK��Z�YǾ����$data/ConsoleTools/design/console.xmlnu�[���<?xml version="1.0"  encoding="windows-1252"?>
<XMI xmi.version="1.1" xmlns:UML="omg.org/UML1.3" timestamp="2005-08-22 11:12:54">
	<XMI.header>
		<XMI.documentation>
			<XMI.exporter>Enterprise Architect</XMI.exporter>
			<XMI.exporterVersion>2.5</XMI.exporterVersion>
		</XMI.documentation>
	</XMI.header>
	<XMI.content>
		<UML:Model name="EA Model" xmi.id="MX_EAID_4B0C57B6_268B_4109_8909_F7FD1E17C16A">
			<UML:Namespace.ownedElement>
				<UML:Class name="EARootClass" xmi.id="EAID_11111111_5487_4080_A7F4_41526CB0AA00" isRoot="true" isLeaf="false" isAbstract="false"/>
				<UML:Package name="ConsoleTools" xmi.id="EAPK_4B0C57B6_268B_4109_8909_F7FD1E17C16A" isRoot="false" isLeaf="false" isAbstract="false" visibility="public">
					<UML:ModelElement.stereotype>
						<UML:Stereotype xmi.idref="EAID_1D64E7C3_A572_4044_9F13_82E10C926C05"/>
					</UML:ModelElement.stereotype>
					<UML:ModelElement.taggedValue>
						<UML:TaggedValue tag="documentation" value="Provides functionality for working on the console. This means the
ability to parse options to scripts and output to consoles."/>
						<UML:TaggedValue tag="created" value="2005-08-12 00:00:00"/>
						<UML:TaggedValue tag="modified" value="2005-08-12 00:00:00"/>
						<UML:TaggedValue tag="iscontrolled" value="TRUE"/>
						<UML:TaggedValue tag="xmlpath" value="E:\src\ezcomponents\packages\ConsoleTools\trunk\design\console.xml"/>
						<UML:TaggedValue tag="lastloaddate" value="2005-08-18 14:20:20"/>
						<UML:TaggedValue tag="lastsavedate" value="2005-08-22 11:12:54"/>
						<UML:TaggedValue tag="isprotected" value="FALSE"/>
						<UML:TaggedValue tag="usedtd" value="FALSE"/>
						<UML:TaggedValue tag="owner" value="Jan Borsodi"/>
						<UML:TaggedValue tag="xmiver" value="Enterprise Architect XMI/UML 1.3"/>
						<UML:TaggedValue tag="logxml" value="FALSE"/>
						<UML:TaggedValue tag="codepath" value="E:\src\ezcomponents\ConsoleTools"/>
						<UML:TaggedValue tag="tpos" value="0"/>
						<UML:TaggedValue tag="packageFlags" value="CRC=0;"/>
						<UML:TaggedValue tag="batchsave" value="0"/>
						<UML:TaggedValue tag="batchload" value="0"/>
						<UML:TaggedValue tag="phase" value="1.0"/>
						<UML:TaggedValue tag="status" value="Proposed"/>
						<UML:TaggedValue tag="author" value="Tobias Schlitt"/>
						<UML:TaggedValue tag="complexity" value="1"/>
						<UML:TaggedValue tag="stereotype" value="ezcomponent"/>
						<UML:TaggedValue tag="ea_stype" value="Public"/>
						<UML:TaggedValue tag="tpos" value="0"/>
					</UML:ModelElement.taggedValue>
					<UML:Namespace.ownedElement>
						<UML:Collaboration xmi.id="EAID_4B0C57B6_268B_4109_8909_F7FD1E17C16A_Collaboration" name="Collaborations">
							<UML:Namespace.ownedElement>
								<UML:ClassifierRole name="console" xmi.id="EAID_9300B830_36D9_4e00_AE7D_EA3DA9B092B9" visibility="public" base="EAID_11111111_5487_4080_A7F4_41526CB0AA00">
									<UML:ModelElement.taggedValue>
										<UML:TaggedValue tag="isSpecification" value="false"/>
										<UML:TaggedValue tag="ea_stype" value="Package"/>
										<UML:TaggedValue tag="ea_ntype" value="0"/>
										<UML:TaggedValue tag="version" value="1.0"/>
										<UML:TaggedValue tag="package" value="EAPK_4B0C57B6_268B_4109_8909_F7FD1E17C16A"/>
										<UML:TaggedValue tag="date_created" value="2005-08-12 09:19:34"/>
										<UML:TaggedValue tag="date_modified" value="2005-08-12 09:19:34"/>
										<UML:TaggedValue tag="gentype" value="PHP"/>
										<UML:TaggedValue tag="tagged" value="0"/>
										<UML:TaggedValue tag="package2" value="EAID_9300B830_36D9_4e00_AE7D_EA3DA9B092B9"/>
										<UML:TaggedValue tag="package_name" value="ConsoleTools"/>
										<UML:TaggedValue tag="phase" value="1.0"/>
										<UML:TaggedValue tag="author" value="Jan Borsodi"/>
										<UML:TaggedValue tag="complexity" value="1"/>
										<UML:TaggedValue tag="status" value="Proposed"/>
										<UML:TaggedValue tag="style" value="BackColor=-1;BorderColor=-1;BorderWidth=-1;FontColor=-1;VSwimLanes=0;HSwimLanes=0;BorderStyle=0;"/>
									</UML:ModelElement.taggedValue>
								</UML:ClassifierRole>
							</UML:Namespace.ownedElement>
							<UML:Collaboration.interaction/>
						</UML:Collaboration>
						<UML:Package name="console" xmi.id="EAPK_9300B830_36D9_4e00_AE7D_EA3DA9B092B9" isRoot="false" isLeaf="false" isAbstract="false" visibility="public">
							<UML:ModelElement.taggedValue>
								<UML:TaggedValue tag="created" value="2005-08-12 00:00:00"/>
								<UML:TaggedValue tag="modified" value="2005-08-12 00:00:00"/>
								<UML:TaggedValue tag="iscontrolled" value="FALSE"/>
								<UML:TaggedValue tag="lastloaddate" value="2005-08-18 14:20:18"/>
								<UML:TaggedValue tag="lastsavedate" value="2005-08-18 14:20:18"/>
								<UML:TaggedValue tag="isprotected" value="FALSE"/>
								<UML:TaggedValue tag="usedtd" value="FALSE"/>
								<UML:TaggedValue tag="logxml" value="FALSE"/>
								<UML:TaggedValue tag="codepath" value="E:\src\ezcomponents\ConsoleTools\console"/>
								<UML:TaggedValue tag="batchsave" value="0"/>
								<UML:TaggedValue tag="batchload" value="0"/>
								<UML:TaggedValue tag="phase" value="1.0"/>
								<UML:TaggedValue tag="status" value="Proposed"/>
								<UML:TaggedValue tag="author" value="Jan Borsodi"/>
								<UML:TaggedValue tag="complexity" value="1"/>
								<UML:TaggedValue tag="ea_stype" value="Public"/>
							</UML:ModelElement.taggedValue>
							<UML:Namespace.ownedElement>
								<UML:Collaboration xmi.id="EAID_9300B830_36D9_4e00_AE7D_EA3DA9B092B9_Collaboration" name="Collaborations">
									<UML:Namespace.ownedElement>
										<UML:ClassifierRole name="parameter" xmi.id="EAID_4C33B478_0B96_4ef1_B7E8_0F64B60CC675" visibility="public" base="EAID_11111111_5487_4080_A7F4_41526CB0AA00">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="isSpecification" value="false"/>
												<UML:TaggedValue tag="ea_stype" value="Package"/>
												<UML:TaggedValue tag="ea_ntype" value="0"/>
												<UML:TaggedValue tag="version" value="1.0"/>
												<UML:TaggedValue tag="package" value="EAPK_9300B830_36D9_4e00_AE7D_EA3DA9B092B9"/>
												<UML:TaggedValue tag="date_created" value="2005-08-12 09:19:35"/>
												<UML:TaggedValue tag="date_modified" value="2005-08-12 09:19:35"/>
												<UML:TaggedValue tag="gentype" value="PHP"/>
												<UML:TaggedValue tag="tagged" value="0"/>
												<UML:TaggedValue tag="package2" value="EAID_4C33B478_0B96_4ef1_B7E8_0F64B60CC675"/>
												<UML:TaggedValue tag="package_name" value="console"/>
												<UML:TaggedValue tag="phase" value="1.0"/>
												<UML:TaggedValue tag="author" value="Jan Borsodi"/>
												<UML:TaggedValue tag="complexity" value="1"/>
												<UML:TaggedValue tag="status" value="Proposed"/>
												<UML:TaggedValue tag="style" value="BackColor=-1;BorderColor=-1;BorderWidth=-1;FontColor=-1;VSwimLanes=0;HSwimLanes=0;BorderStyle=0;"/>
											</UML:ModelElement.taggedValue>
										</UML:ClassifierRole>
										<UML:ClassifierRole name="output" xmi.id="EAID_4D026C21_9F61_4699_BBE9_ED9516605496" visibility="public" base="EAID_11111111_5487_4080_A7F4_41526CB0AA00">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="isSpecification" value="false"/>
												<UML:TaggedValue tag="ea_stype" value="Package"/>
												<UML:TaggedValue tag="ea_ntype" value="0"/>
												<UML:TaggedValue tag="version" value="1.0"/>
												<UML:TaggedValue tag="package" value="EAPK_9300B830_36D9_4e00_AE7D_EA3DA9B092B9"/>
												<UML:TaggedValue tag="date_created" value="2005-08-12 09:19:34"/>
												<UML:TaggedValue tag="date_modified" value="2005-08-12 09:19:34"/>
												<UML:TaggedValue tag="gentype" value="PHP"/>
												<UML:TaggedValue tag="tagged" value="0"/>
												<UML:TaggedValue tag="package2" value="EAID_4D026C21_9F61_4699_BBE9_ED9516605496"/>
												<UML:TaggedValue tag="package_name" value="console"/>
												<UML:TaggedValue tag="phase" value="1.0"/>
												<UML:TaggedValue tag="author" value="Jan Borsodi"/>
												<UML:TaggedValue tag="complexity" value="1"/>
												<UML:TaggedValue tag="status" value="Proposed"/>
												<UML:TaggedValue tag="style" value="BackColor=-1;BorderColor=-1;BorderWidth=-1;FontColor=-1;VSwimLanes=0;HSwimLanes=0;BorderStyle=0;"/>
											</UML:ModelElement.taggedValue>
										</UML:ClassifierRole>
									</UML:Namespace.ownedElement>
									<UML:Collaboration.interaction/>
								</UML:Collaboration>
								<UML:Class name="ezcConsoleStatusbar" xmi.id="EAID_4F677B5E_DCEC_4413_9FB2_A9753E5E62E8" visibility="public" namespace="EAPK_9300B830_36D9_4e00_AE7D_EA3DA9B092B9" isRoot="false" isLeaf="false" isAbstract="false" isActive="false">
									<UML:ModelElement.taggedValue>
										<UML:TaggedValue tag="documentation" value="Creating  and maintaining statusbars to be printed to the console. 
&lt;code&gt;  ... creating ezcConsoleOutput object  $opt = array( 'successChar'   =&gt; '+', 'failureChar'   =&gt; '-', ); $status = new ezcConsoleStatusbar($opt); foreach ($files as $file) { $res = $file-&gt;upload(); $status-&gt;add($res); // $res is true or false }  $msg = $status-&gt;getSuccess().' succeeded, '.$status-&gt;getFailure().' failed.'; $out-&gt;outputText(&quot;Finished uploading files. $msg \n&quot;); 
&lt;/code&gt;  
@package ConsoleTools
@link http://www.gnu.org/copyleft/lesser.html}"/>
										<UML:TaggedValue tag="isSpecification" value="false"/>
										<UML:TaggedValue tag="ea_stype" value="Class"/>
										<UML:TaggedValue tag="ea_ntype" value="0"/>
										<UML:TaggedValue tag="version" value="//autogen//
@copyright Copyright (C) 2005 eZ syst"/>
										<UML:TaggedValue tag="package" value="EAPK_9300B830_36D9_4e00_AE7D_EA3DA9B092B9"/>
										<UML:TaggedValue tag="date_created" value="2005-08-19 11:51:29"/>
										<UML:TaggedValue tag="date_modified" value="2005-08-19 11:51:50"/>
										<UML:TaggedValue tag="genfile" value="E:\src\ezcomponents\packages\ConsoleTools\trunk\src\console\statusbar.php"/>
										<UML:TaggedValue tag="gentype" value="PHP"/>
										<UML:TaggedValue tag="tagged" value="0"/>
										<UML:TaggedValue tag="package_name" value="console"/>
										<UML:TaggedValue tag="phase" value="1.0"/>
										<UML:TaggedValue tag="author" value="Jan Borsodi"/>
										<UML:TaggedValue tag="complexity" value="1"/>
										<UML:TaggedValue tag="status" value="Proposed"/>
										<UML:TaggedValue tag="eventflags" value="LNK=629e;"/>
										<UML:TaggedValue tag="style" value="BackColor=-1;BorderColor=-1;BorderWidth=-1;FontColor=-1;VSwimLanes=0;HSwimLanes=0;BorderStyle=0;"/>
									</UML:ModelElement.taggedValue>
									<UML:Classifier.feature>
										<UML:Attribute name="options" changeable="none" visibility="protected" ownerScope="instance" targetScope="instance">
											<UML:Attribute.initialValue>
												<UML:Expression body="array(
        'successChar' =&gt; '+',     // Char to indicate success
        'failureChar' =&gt; '-',     // Char to indicate failure
    )"/>
											</UML:Attribute.initialValue>
											<UML:StructuralFeature.type>
												<UML:Classifier xmi.idref="eaxmiid0"/>
											</UML:StructuralFeature.type>
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="description" value="Options 
&lt;code&gt; array( 'successChar' =&gt; '+',     // Char to indicate success 'failureChar' =&gt; '-',     // Char to indicate failure );
&lt;/code&gt; 
@var array(string)"/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="length" value="0"/>
												<UML:TaggedValue tag="ordered" value="0"/>
												<UML:TaggedValue tag="precision" value="0"/>
												<UML:TaggedValue tag="scale" value="0"/>
												<UML:TaggedValue tag="collection" value="false"/>
												<UML:TaggedValue tag="position" value="0"/>
												<UML:TaggedValue tag="lowerBound" value="1"/>
												<UML:TaggedValue tag="upperBound" value="1"/>
												<UML:TaggedValue tag="ea_guid" value="{F33A1CE4-BFEA-4f77-A62F-27EBE1039C85}"/>
												<UML:TaggedValue tag="styleex" value="volatile=0;"/>
											</UML:ModelElement.taggedValue>
										</UML:Attribute>
										<UML:Attribute name="outputHandler" changeable="none" visibility="protected" ownerScope="instance" targetScope="instance">
											<UML:Attribute.initialValue>
												<UML:Expression/>
											</UML:Attribute.initialValue>
											<UML:StructuralFeature.type>
												<UML:Classifier xmi.idref="EAID_65A37092_56CE_4e5a_8C30_366469BD8468"/>
											</UML:StructuralFeature.type>
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="description" value="The ezcConsoleOutput object to use. 
@var ezcConsoleOutput"/>
												<UML:TaggedValue tag="type" value="ezcConsoleOutput"/>
												<UML:TaggedValue tag="length" value="0"/>
												<UML:TaggedValue tag="ordered" value="0"/>
												<UML:TaggedValue tag="precision" value="0"/>
												<UML:TaggedValue tag="scale" value="0"/>
												<UML:TaggedValue tag="collection" value="false"/>
												<UML:TaggedValue tag="position" value="1"/>
												<UML:TaggedValue tag="lowerBound" value="1"/>
												<UML:TaggedValue tag="upperBound" value="1"/>
												<UML:TaggedValue tag="ea_guid" value="{AF891708-6CAF-47ce-AC06-786978028DEF}"/>
												<UML:TaggedValue tag="styleex" value="volatile=0;"/>
											</UML:ModelElement.taggedValue>
										</UML:Attribute>
										<UML:Operation name="__construct" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Creates a new status bar. 
@param ezcConsoleOutput $outHandler Handler to utilize for output
@param array(string) $settings      Settings
@param array(string) $options       Options 
@see ezcConsoleStatusbar::$options"/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="0"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{CBE6BEE8-62F4-4986-877A-DD4AB9BD61E5}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-62F4-4986-877A-DD4AB9BD61E5}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="outHandler" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="EAID_65A37092_56CE_4e5a_8C30_366469BD8468"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="ezcConsoleOutput"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="classifier" value="EAID_65A37092_56CE_4e5a_8C30_366469BD8468"/>
														<UML:TaggedValue tag="ea_guid" value="{39827121-CD9A-46ae-8A2E-DA9973EE4935}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="options" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="1"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{A4C17CAC-8160-482b-9A83-BC834F8E3656}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression body="array() "/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
										<UML:Operation name="add" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Add a status to the status bar. Adds a new status to the bar which is printed immediatelly. If the cursor is currently not at the beginning of a line, it will move to the next line. 
@param bool $status Print successChar on true, failureChar on false."/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="1"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{DEBB3332-5AFA-4648-89C4-ABC6B5ED6C94}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-5AFA-4648-89C4-ABC6B5ED6C94}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="status" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{5BB0E5EA-65A6-4426-A912-35384AB3F5F2}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
										<UML:Operation name="getSuccesses" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Returns number of successes during the run. Returns the number of success characters printed from this status bar. 
@returns int Number of successes."/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="2"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{81A9D66D-CD01-43b3-96F4-20C81BC8CA16}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-CD01-43b3-96F4-20C81BC8CA16}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
										<UML:Operation name="getFailures" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Returns number of failures during the run. Returns the number of failure characters printed from this status bar. 
@returns int Number of failures."/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="3"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{88FCD858-D6D5-434c-A23D-753DB261B31A}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-D6D5-434c-A23D-753DB261B31A}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
									</UML:Classifier.feature>
								</UML:Class>
								<UML:Association xmi.id="EAID_8273AECA_7516_4847_9960_34C4FF71F006" visibility="public" isRoot="false" isLeaf="false" isAbstract="false">
									<UML:ModelElement.taggedValue>
										<UML:TaggedValue tag="style" value="3"/>
										<UML:TaggedValue tag="ea_type" value="Aggregation"/>
										<UML:TaggedValue tag="direction" value="Source -&gt; Destination"/>
										<UML:TaggedValue tag="linemode" value="3"/>
										<UML:TaggedValue tag="linecolor" value="-1"/>
										<UML:TaggedValue tag="linewidth" value="0"/>
										<UML:TaggedValue tag="seqno" value="0"/>
										<UML:TaggedValue tag="headStyle" value="0"/>
										<UML:TaggedValue tag="lineStyle" value="0"/>
										<UML:TaggedValue tag="virtualInheritance" value="0"/>
									</UML:ModelElement.taggedValue>
									<UML:Association.connection>
										<UML:AssociationEnd visibility="public" aggregation="none" isOrdered="false" isNavigable="false" type="EAID_65A37092_56CE_4e5a_8C30_366469BD8468">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="containment" value="Unspecified"/>
											</UML:ModelElement.taggedValue>
										</UML:AssociationEnd>
										<UML:AssociationEnd visibility="public" aggregation="shared" isOrdered="false" isNavigable="true" type="EAID_4F677B5E_DCEC_4413_9FB2_A9753E5E62E8">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="containment" value="Unspecified"/>
											</UML:ModelElement.taggedValue>
										</UML:AssociationEnd>
									</UML:Association.connection>
								</UML:Association>
								<UML:Comment xmi.id="EAID_55B8BBC5_46DA_4e67_9A1D_1120F11D48E7" visibility="public" namespace="EAPK_9300B830_36D9_4e00_AE7D_EA3DA9B092B9">
									<UML:ModelElement.taggedValue>
										<UML:TaggedValue tag="isSpecification" value="false"/>
										<UML:TaggedValue tag="ea_stype" value="Text"/>
										<UML:TaggedValue tag="ea_ntype" value="18"/>
										<UML:TaggedValue tag="version" value="1.0"/>
										<UML:TaggedValue tag="package" value="EAPK_9300B830_36D9_4e00_AE7D_EA3DA9B092B9"/>
										<UML:TaggedValue tag="date_created" value="2005-08-12 09:20:09"/>
										<UML:TaggedValue tag="date_modified" value="2005-08-12 09:20:09"/>
										<UML:TaggedValue tag="gentype" value="&lt;none&gt;"/>
										<UML:TaggedValue tag="tagged" value="0"/>
										<UML:TaggedValue tag="package_name" value="console"/>
										<UML:TaggedValue tag="phase" value="1.0"/>
										<UML:TaggedValue tag="author" value="Jan Borsodi"/>
										<UML:TaggedValue tag="complexity" value="1"/>
										<UML:TaggedValue tag="status" value="Proposed"/>
										<UML:TaggedValue tag="style" value="BackColor=-1;BorderColor=-1;BorderWidth=-1;FontColor=-1;VSwimLanes=0;HSwimLanes=0;BorderStyle=0;"/>
									</UML:ModelElement.taggedValue>
								</UML:Comment>
								<UML:Class name="ezcConsoleOutput" xmi.id="EAID_65A37092_56CE_4e5a_8C30_366469BD8468" visibility="public" namespace="EAPK_9300B830_36D9_4e00_AE7D_EA3DA9B092B9" isRoot="false" isLeaf="false" isAbstract="false" isActive="false">
									<UML:ModelElement.taggedValue>
										<UML:TaggedValue tag="documentation" value="Class for handling console output. This class handles outputting text to the console. It deals with styling text in different ways and offers some comfortable options to deal with console text output. 
&lt;code&gt;  $opts = array( 'verboseLevel'  =&gt; 10,  // extremly verbose 'autobreak'     =&gt; 40,  // will break lines every 40 chars 'styles'        =&gt; array( 'default'   =&gt; 'green', // green default text 'success'   =&gt; 'white', // white success messages ), ); $out = new ezcConsoleOutput($opts);  $out-&gt;outputText('This is default text '); $out-&gt;outputText('including success message', 'success'); $out-&gt;outputText(&quot;and a manual linebreak.\n&quot;);  $out-&gt;outputText(&quot;Some verbose output.\n&quot;, null, 10); $out-&gt;outputText(&quot;And some not so verbose, bold output.\n&quot;, 'bold', 5); 
&lt;/code&gt; 
@package ConsoleTools
@link http://www.gnu.org/copyleft/lesser.html}"/>
										<UML:TaggedValue tag="isSpecification" value="false"/>
										<UML:TaggedValue tag="ea_stype" value="Class"/>
										<UML:TaggedValue tag="ea_ntype" value="0"/>
										<UML:TaggedValue tag="version" value="//autogen//
@copyright Copyright (C) 2005 eZ syst"/>
										<UML:TaggedValue tag="package" value="EAPK_9300B830_36D9_4e00_AE7D_EA3DA9B092B9"/>
										<UML:TaggedValue tag="date_created" value="2005-08-12 09:19:35"/>
										<UML:TaggedValue tag="date_modified" value="2005-08-19 11:42:35"/>
										<UML:TaggedValue tag="genfile" value="E:\src\ezcomponents\packages\ConsoleTools\trunk\src\console\output.php"/>
										<UML:TaggedValue tag="genoptions" value="nKill=0;sLang=PHP;bConstructor=1;bConInline=0;sConScope=Public;bCpyConstructor=0;bCpyConInline=0;sCpyConScope=Public;bDestructor=1;bDesVirtual=1;bDesInline=0;sDesScope=Public;CHeader=.h;CBody=.cpp;JBody=.java;VBody=.cls;VBNetBody=.vb;sAssocName=$LinkClass;bGetSet=1;bGenInterfaces=1;JCol=Vector;CCol=[];VCol=Collection;bVMultiuse=1;bVPersist=0;bVDatabind=0;bVDatasource=0;bVGlobal=0;bVCreatable=1;bVExposed=0;sMTS=0;sCRefType=*;sCGetPrefix=Get;sCSetPrefix=Set;sJGetPrefix=get;sJSetPrefix=set;sCSGetPrefix=Get;sCSSetPrefix=Set;sVVersion=6.0;CSBody=.cs;DBody=.pas;bJInnerClasses=1;sJCollection=;sCodePage=;sPHPBody=.php;sPHPVersion=5.0;sPHPGetPrefix=get;sPHPSetPrefix=set;nLang=-1;"/>
										<UML:TaggedValue tag="gentype" value="PHP"/>
										<UML:TaggedValue tag="tagged" value="0"/>
										<UML:TaggedValue tag="package_name" value="console"/>
										<UML:TaggedValue tag="phase" value="1.0"/>
										<UML:TaggedValue tag="author" value="Jan Borsodi"/>
										<UML:TaggedValue tag="complexity" value="1"/>
										<UML:TaggedValue tag="status" value="Proposed"/>
										<UML:TaggedValue tag="eventflags" value="LNK=f7da;"/>
										<UML:TaggedValue tag="$ea_attsclassified" value="{AF891708-6CAF-47ce-AC06-786978028DEF},{5DEF0E6B-4A38-4bc6-B053-6C114AE6EC99},{38166CA5-115F-4705-A391-4B122E210FED}"/>
										<UML:TaggedValue tag="style" value="BackColor=-1;BorderColor=-1;BorderWidth=-1;FontColor=-1;VSwimLanes=0;HSwimLanes=0;BorderStyle=0;"/>
									</UML:ModelElement.taggedValue>
									<UML:Classifier.feature>
										<UML:Attribute name="options" changeable="none" visibility="private" ownerScope="instance" targetScope="instance">
											<UML:Attribute.initialValue>
												<UML:Expression body="array(
        'verboseLevel'  =&gt; 1,
        'useStyles'     =&gt; true,
        'styles'        =&gt; array(
            'default'   =&gt; '',
            'error'     =&gt; 'red',
            'warning'   =&gt; 'yellow',
            'success'   =&gt; 'green',
            'file'      =&gt; 'blue',
            'dir'       =&gt; 'green',
            'link'      =&gt; 'blue',
        ),
    )"/>
											</UML:Attribute.initialValue>
											<UML:StructuralFeature.type>
												<UML:Classifier xmi.idref="eaxmiid0"/>
											</UML:StructuralFeature.type>
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="description" value="Options Default: 
&lt;code&gt; array( 'verboseLevel'  =&gt; 1,       // Verbosity level 'autobreak'     =&gt; 0,       // Pos &lt;int&gt;. Break lines automatically after this ammount of chars 'useStyles'     =&gt; true,    // Whether to enable styles or not 'styles'        =&gt; array(   // Style alias definition {@link ezcConsoleOutput::outputText()} 'default'   =&gt; '',      // Default style. If blank, sys default 'error'     =&gt; 'red', 'warning'   =&gt; 'yellow', 'success'   =&gt; 'green', 'file'      =&gt; 'blue', 'dir'       =&gt; 'green', 'link'      =&gt; 'blue', ), );
&lt;/code&gt; 
@see ezcConsoleOutput::setOptions()
@see ezcConsoleOutput::getOptions() 
@var array(string)"/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="length" value="0"/>
												<UML:TaggedValue tag="ordered" value="0"/>
												<UML:TaggedValue tag="precision" value="0"/>
												<UML:TaggedValue tag="scale" value="0"/>
												<UML:TaggedValue tag="collection" value="false"/>
												<UML:TaggedValue tag="position" value="0"/>
												<UML:TaggedValue tag="lowerBound" value="1"/>
												<UML:TaggedValue tag="upperBound" value="1"/>
												<UML:TaggedValue tag="ea_guid" value="{2533A2BF-5CE1-4369-B243-0F1641634614}"/>
												<UML:TaggedValue tag="styleex" value="volatile=0;"/>
											</UML:ModelElement.taggedValue>
										</UML:Attribute>
										<UML:Attribute name="styles" changeable="none" visibility="private" ownerScope="instance" targetScope="instance">
											<UML:Attribute.initialValue>
												<UML:Expression body="array(
		'red' =&gt; &quot;\033[1;31m&quot;,
		'green' =&gt; &quot;\033[1;32m&quot;,
		'yellow' =&gt; &quot;\033[1;33m&quot;,
		'blue' =&gt; &quot;\033[1;34m&quot;,
		'magenta' =&gt; &quot;\033[1;35m&quot;,
		'cyan' =&gt; &quot;\033[1;36m&quot;,
		'white' =&gt; &quot;\033[1;37m&quot;,
		'gray' =&gt; &quot;\033[1;30m&quot;,
		
		'dark-red' =&gt; &quot;\033[0;31m&quot;,
		'dark-green' =&gt; &quot;\033[0;32m&quot;,
		'dark-yellow' =&gt; &quot;\033[0;33m&quot;,
		'dark-blue' =&gt; &quot;\033[0;34m&quot;,
		'dark-magenta' =&gt; &quot;\033[0;35m&quot;,
		'dark-cyan' =&gt; &quot;\033[0;36m&quot;,
		'dark-white' =&gt; &quot;\033[0;37m&quot;,
		'dark-gray' =&gt; &quot;\033[0;30m&quot;,
		
		'red-bg' =&gt; &quot;\033[1;41m&quot;,
		'green-bg' =&gt; &quot;\033[1;42m&quot;,
		'yellow-bg' =&gt; &quot;\033[1;43m&quot;,
		'blue-bg' =&gt; &quot;\033[1;44m&quot;,
		'magenta-bg' =&gt; &quot;\033[1;45m&quot;,
		'cyan-bg' =&gt; &quot;\033[1;46m&quot;,
		'white-bg' =&gt; &quot;\033[1;47m&quot;,
		
		'bold' =&gt; &quot;\033[1;38m&quot;,
		'italic' =&gt; &quot;\033[0;39m&quot;,
		'underline' =&gt; &quot;\033[0;39m&quot;,
    )"/>
											</UML:Attribute.initialValue>
											<UML:StructuralFeature.type>
												<UML:Classifier xmi.idref="eaxmiid0"/>
											</UML:StructuralFeature.type>
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="description" value="Stores the hard coded styles available on the console. 
@var array(string =&gt; string)"/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="length" value="0"/>
												<UML:TaggedValue tag="ordered" value="0"/>
												<UML:TaggedValue tag="precision" value="0"/>
												<UML:TaggedValue tag="scale" value="0"/>
												<UML:TaggedValue tag="collection" value="false"/>
												<UML:TaggedValue tag="position" value="1"/>
												<UML:TaggedValue tag="lowerBound" value="1"/>
												<UML:TaggedValue tag="upperBound" value="1"/>
												<UML:TaggedValue tag="ea_guid" value="{B0A8B63B-BF19-45f2-8901-CBEA9CA2D482}"/>
												<UML:TaggedValue tag="styleex" value="volatile=0;"/>
											</UML:ModelElement.taggedValue>
										</UML:Attribute>
										<UML:Operation name="__construct" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Create a new console output handler. 
@see ezcConsoleOutput::$options
@see ezcConsoleOutput::setOptions()
@see ezcConsoleOutput::getOptions() 
@param array(string) $options Options."/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="0"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{5EB221F1-7FE2-428d-B13B-468FC76062E3}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-7FE2-428d-B13B-468FC76062E3}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="options" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{BB692C63-8FFD-408a-B022-EF77A24C9F16}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression body="array() "/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
										<UML:Operation name="setOptions" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Set options. 
@see ezcConsoleOutput::getOptions()
@see ezcConsoleOutput::$options 
@param array(string) $options Options.
@return void"/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="1"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{6B166EA3-A27B-4e1a-9947-9AF5CF0B0D37}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-A27B-4e1a-9947-9AF5CF0B0D37}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="options" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{55EDB7C4-9E55-42a0-B4CA-A4F70D27151C}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
										<UML:Operation name="getOptions" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Returns options 
@see ezcConsoleOutput::setOptions()
@see ezcConsoleOutput::$options 
@return array(string) Options."/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="2"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{0EB8E49F-C9C5-4890-8875-6B4F4E7250F6}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-C9C5-4890-8875-6B4F4E7250F6}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
										<UML:Operation name="outputText" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Print text to the console. Output a string to the console. If $style parameter is ommited, the default style is chosen. Style can either be a special style {@link eczConsoleOutput::$options}, a style name {@link ezcConsoleOutput$styles} or 'none' to print without any styling. 
@param string $text      The text to print.
@param string $style     Style chosen for printing.
@param int $verboseLevel On which verbose level to output this message.
@param int Output this text only in a specific verbosity level"/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="3"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{0F861241-401A-4c5c-AC0E-3104A64E949F}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-401A-4c5c-AC0E-3104A64E949F}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="text" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{975F5355-C2EB-4fc5-A494-A8DF6D326BD9}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="style" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="1"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{41472B93-AF86-4fe0-A3F3-0860B3A242BE}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression body="'default'"/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="verboseLevel" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="2"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{A806171C-5D65-4ca3-9298-3A95FC79ED1F}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression body="1 "/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
										<UML:Operation name="styleText" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Returns a styled version of the text. Receive a styled version of the inputed text. If $style parameter is ommited, the default style is chosen. Style can either be a special style or a direct color name.  {@link ezcConsoleOutput::$options}, a style name {@link ezcConsoleOutput::$styles} or 'none' to print without any styling. 
@param string $text  Text to apply style to.
@param string $style Style chosen to be applied.
@return string"/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="4"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{2BC7FC3E-88AE-4cb8-99F8-872E0E6CCB9A}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-88AE-4cb8-99F8-872E0E6CCB9A}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="text" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{BEE56DE5-C4E6-42f9-981C-328F5CE4BA40}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="style" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="1"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{C32940AE-7E71-4e5d-B49A-0CB487D37932}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression body="'default' "/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
										<UML:Operation name="storePos" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Store the current cursor position. Saves the current cursor position to return to it using {@link ezcConsoleOutput::restorePos()}. Multiple calls to this method will override each other. Only the last position is saved. 
@todo Shall multiple markers be supported? Must be emulated by the class, since not directly supported by ANSI escape seqs. 
@return void"/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="5"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{D28A9B5A-586C-43d2-8EE7-62A375675E7D}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-586C-43d2-8EE7-62A375675E7D}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
										<UML:Operation name="restorePos" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Restore a cursor position. Restores the cursor position last saved using {@link ezcConsoleOutput::storePos()}. 
@return void "/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="6"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{6892A18F-3BCE-47bb-8A78-DB990F609A87}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-3BCE-47bb-8A78-DB990F609A87}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
									</UML:Classifier.feature>
								</UML:Class>
								<UML:Association xmi.id="EAID_8BBADE67_3C37_4c4a_8CD5_2911FACC538E" visibility="public" isRoot="false" isLeaf="false" isAbstract="false">
									<UML:ModelElement.taggedValue>
										<UML:TaggedValue tag="style" value="3"/>
										<UML:TaggedValue tag="ea_type" value="Aggregation"/>
										<UML:TaggedValue tag="direction" value="Source -&gt; Destination"/>
										<UML:TaggedValue tag="linemode" value="3"/>
										<UML:TaggedValue tag="linecolor" value="-1"/>
										<UML:TaggedValue tag="linewidth" value="0"/>
										<UML:TaggedValue tag="seqno" value="0"/>
										<UML:TaggedValue tag="headStyle" value="0"/>
										<UML:TaggedValue tag="lineStyle" value="0"/>
										<UML:TaggedValue tag="virtualInheritance" value="0"/>
									</UML:ModelElement.taggedValue>
									<UML:Association.connection>
										<UML:AssociationEnd visibility="public" aggregation="none" isOrdered="false" isNavigable="false" type="EAID_65A37092_56CE_4e5a_8C30_366469BD8468">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="containment" value="Unspecified"/>
											</UML:ModelElement.taggedValue>
										</UML:AssociationEnd>
										<UML:AssociationEnd visibility="public" aggregation="shared" isOrdered="false" isNavigable="true" type="EAID_A9F2232F_845A_4da2_A329_950ED3CDB676">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="containment" value="Unspecified"/>
											</UML:ModelElement.taggedValue>
										</UML:AssociationEnd>
									</UML:Association.connection>
								</UML:Association>
								<UML:Association xmi.id="EAID_D761BD7E_7981_43a2_823C_48DC2173761C" visibility="public" isRoot="false" isLeaf="false" isAbstract="false">
									<UML:ModelElement.taggedValue>
										<UML:TaggedValue tag="style" value="2"/>
										<UML:TaggedValue tag="ea_type" value="Aggregation"/>
										<UML:TaggedValue tag="direction" value="Source -&gt; Destination"/>
										<UML:TaggedValue tag="linemode" value="2"/>
										<UML:TaggedValue tag="linecolor" value="-1"/>
										<UML:TaggedValue tag="linewidth" value="0"/>
										<UML:TaggedValue tag="seqno" value="0"/>
										<UML:TaggedValue tag="headStyle" value="0"/>
										<UML:TaggedValue tag="lineStyle" value="0"/>
										<UML:TaggedValue tag="privatedata5" value="SX=0;SY=0;EX=0;EY=0;EDGE=1;"/>
										<UML:TaggedValue tag="virtualInheritance" value="0"/>
									</UML:ModelElement.taggedValue>
									<UML:Association.connection>
										<UML:AssociationEnd visibility="public" aggregation="none" isOrdered="false" isNavigable="false" type="EAID_65A37092_56CE_4e5a_8C30_366469BD8468">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="containment" value="Unspecified"/>
											</UML:ModelElement.taggedValue>
										</UML:AssociationEnd>
										<UML:AssociationEnd visibility="public" aggregation="shared" isOrdered="false" isNavigable="true" type="EAID_EE63FC0D_D590_4d0f_9F83_338683F8E000">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="containment" value="Unspecified"/>
											</UML:ModelElement.taggedValue>
										</UML:AssociationEnd>
									</UML:Association.connection>
								</UML:Association>
								<UML:Dependency client="EAID_65A37092_56CE_4e5a_8C30_366469BD8468" supplier="EAID_4B7CE667_749A_4dde_BE45_7CBFB5519DF5" xmi.id="EAID_E53B0D49_9955_449f_974D_2D23DBDB2610" visibility="public">
									<UML:ModelElement.stereotype>
										<UML:Stereotype name="throws"/>
									</UML:ModelElement.stereotype>
									<UML:ModelElement.taggedValue>
										<UML:TaggedValue tag="style" value="2"/>
										<UML:TaggedValue tag="ea_type" value="Dependency"/>
										<UML:TaggedValue tag="direction" value="Source -&gt; Destination"/>
										<UML:TaggedValue tag="linemode" value="2"/>
										<UML:TaggedValue tag="linecolor" value="-1"/>
										<UML:TaggedValue tag="linewidth" value="0"/>
										<UML:TaggedValue tag="seqno" value="0"/>
										<UML:TaggedValue tag="stereotype" value="throws"/>
										<UML:TaggedValue tag="headStyle" value="0"/>
										<UML:TaggedValue tag="lineStyle" value="0"/>
										<UML:TaggedValue tag="conditional" value="�throws�"/>
										<UML:TaggedValue tag="src_visibility" value="Public"/>
										<UML:TaggedValue tag="src_aggregation" value="0"/>
										<UML:TaggedValue tag="src_isOrdered" value="false"/>
										<UML:TaggedValue tag="src_isNavigable" value="false"/>
										<UML:TaggedValue tag="src_containment" value="Unspecified"/>
										<UML:TaggedValue tag="dst_visibility" value="Public"/>
										<UML:TaggedValue tag="dst_aggregation" value="0"/>
										<UML:TaggedValue tag="dst_isOrdered" value="false"/>
										<UML:TaggedValue tag="dst_isNavigable" value="true"/>
										<UML:TaggedValue tag="dst_containment" value="Unspecified"/>
										<UML:TaggedValue tag="privatedata5" value="SX=0;SY=0;EX=0;EY=0;EDGE=1;"/>
										<UML:TaggedValue tag="virtualInheritance" value="0"/>
										<UML:TaggedValue tag="mb" value="�throws�"/>
									</UML:ModelElement.taggedValue>
								</UML:Dependency>
								<UML:Comment xmi.id="EAID_7FBF19CD_D452_4a01_BF36_6591CF96D1D2" visibility="public" namespace="EAPK_9300B830_36D9_4e00_AE7D_EA3DA9B092B9">
									<UML:ModelElement.taggedValue>
										<UML:TaggedValue tag="isSpecification" value="false"/>
										<UML:TaggedValue tag="ea_stype" value="Text"/>
										<UML:TaggedValue tag="ea_ntype" value="18"/>
										<UML:TaggedValue tag="version" value="1.0"/>
										<UML:TaggedValue tag="package" value="EAPK_9300B830_36D9_4e00_AE7D_EA3DA9B092B9"/>
										<UML:TaggedValue tag="date_created" value="2005-08-19 11:59:22"/>
										<UML:TaggedValue tag="date_modified" value="2005-08-19 11:59:22"/>
										<UML:TaggedValue tag="gentype" value="&lt;none&gt;"/>
										<UML:TaggedValue tag="tagged" value="0"/>
										<UML:TaggedValue tag="package_name" value="console"/>
										<UML:TaggedValue tag="phase" value="1.0"/>
										<UML:TaggedValue tag="author" value="Jan Borsodi"/>
										<UML:TaggedValue tag="complexity" value="1"/>
										<UML:TaggedValue tag="status" value="Proposed"/>
										<UML:TaggedValue tag="style" value="BackColor=-1;BorderColor=-1;BorderWidth=-1;FontColor=-1;VSwimLanes=0;HSwimLanes=0;BorderStyle=0;"/>
									</UML:ModelElement.taggedValue>
								</UML:Comment>
								<UML:Class name="ezcConsoleParameter" xmi.id="EAID_A51EEA3E_1E35_4947_AFF6_4F0ED6B44ADC" visibility="public" namespace="EAPK_9300B830_36D9_4e00_AE7D_EA3DA9B092B9" isRoot="false" isLeaf="false" isAbstract="false" isActive="false">
									<UML:ModelElement.taggedValue>
										<UML:TaggedValue tag="documentation" value="Class for handling console parameters. This class allows the complete handling of parameters submitted to a console based application. 
&lt;code&gt;  $paramHandler = new ezcConsoleParameter();  $help = array( 'short' =&gt; 'Get help output.', 'long'  =&gt; 'Retreive help on the usage of this command.', ); $paramHandler-&gt;registerParam('h', 'help', $help);  $file = array( 'type'     =&gt; ezcConsoleParameter::TYPE_STRING 'short'    =&gt; 'Process a file.', 'long'     =&gt; 'Processes a single file.', 'excludes' =&gt; array('d'), ) $paramHandler-&gt;registerParam('f', 'file', $file);  $dir = array( 'type'     =&gt; ezcConsoleParameter::TYPE_STRING 'short'    =&gt; 'Process a directory.', 'long'     =&gt; 'Processes a complete directory.', 'excludes' =&gt; array('f'), ) $paramHandler-&gt;registerParam('d', 'dir', $dir);  $paramHandler-&gt;registerAlias('d', 'directory', 'd');  try { $paramHandler-&gt;processParams(); } catch (ezcConsoleParameterException $e) { if ($e-&gt;code === ezcConsoleParameterException::CODE_DEPENDENCY) { $consoleOut-&gt;outputText( 'Parameter '.$e-&gt;paramName.&quot; may not occur here.\n&quot;, 'error' ); } exit(1); } 
&lt;/code&gt; 
@package ConsoleTools
@link http://www.gnu.org/copyleft/lesser.html}"/>
										<UML:TaggedValue tag="isSpecification" value="false"/>
										<UML:TaggedValue tag="ea_stype" value="Class"/>
										<UML:TaggedValue tag="ea_ntype" value="0"/>
										<UML:TaggedValue tag="version" value="//autogen//
@copyright Copyright (C) 2005 eZ syst"/>
										<UML:TaggedValue tag="package" value="EAPK_9300B830_36D9_4e00_AE7D_EA3DA9B092B9"/>
										<UML:TaggedValue tag="date_created" value="2005-08-12 09:19:36"/>
										<UML:TaggedValue tag="date_modified" value="2005-08-19 11:59:18"/>
										<UML:TaggedValue tag="genfile" value="E:\src\ezcomponents\packages\ConsoleTools\trunk\src\console\parameter.php"/>
										<UML:TaggedValue tag="gentype" value="PHP"/>
										<UML:TaggedValue tag="tagged" value="0"/>
										<UML:TaggedValue tag="package_name" value="console"/>
										<UML:TaggedValue tag="phase" value="1.0"/>
										<UML:TaggedValue tag="author" value="Jan Borsodi"/>
										<UML:TaggedValue tag="complexity" value="1"/>
										<UML:TaggedValue tag="status" value="Proposed"/>
										<UML:TaggedValue tag="eventflags" value="LNK=c4ad;"/>
										<UML:TaggedValue tag="style" value="BackColor=-1;BorderColor=-1;BorderWidth=-1;FontColor=-1;VSwimLanes=0;HSwimLanes=0;BorderStyle=0;"/>
									</UML:ModelElement.taggedValue>
									<UML:Classifier.feature>
										<UML:Attribute name="TYPE_NONE" changeable="frozen" visibility="public" ownerScope="instance" targetScope="instance">
											<UML:Attribute.initialValue>
												<UML:Expression body="1"/>
											</UML:Attribute.initialValue>
											<UML:StructuralFeature.type>
												<UML:Classifier xmi.idref="eaxmiid0"/>
											</UML:StructuralFeature.type>
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="length" value="0"/>
												<UML:TaggedValue tag="ordered" value="0"/>
												<UML:TaggedValue tag="precision" value="0"/>
												<UML:TaggedValue tag="scale" value="0"/>
												<UML:TaggedValue tag="collection" value="false"/>
												<UML:TaggedValue tag="position" value="0"/>
												<UML:TaggedValue tag="lowerBound" value="1"/>
												<UML:TaggedValue tag="upperBound" value="1"/>
												<UML:TaggedValue tag="ea_guid" value="{D5D8FF80-8D6C-44c4-AD27-F0E0CB9B5BD9}"/>
												<UML:TaggedValue tag="styleex" value="volatile=0;"/>
											</UML:ModelElement.taggedValue>
										</UML:Attribute>
										<UML:Attribute name="TYPE_INT" changeable="frozen" visibility="public" ownerScope="instance" targetScope="instance">
											<UML:Attribute.initialValue>
												<UML:Expression body="2"/>
											</UML:Attribute.initialValue>
											<UML:StructuralFeature.type>
												<UML:Classifier xmi.idref="eaxmiid0"/>
											</UML:StructuralFeature.type>
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="length" value="0"/>
												<UML:TaggedValue tag="ordered" value="0"/>
												<UML:TaggedValue tag="precision" value="0"/>
												<UML:TaggedValue tag="scale" value="0"/>
												<UML:TaggedValue tag="collection" value="false"/>
												<UML:TaggedValue tag="position" value="1"/>
												<UML:TaggedValue tag="lowerBound" value="1"/>
												<UML:TaggedValue tag="upperBound" value="1"/>
												<UML:TaggedValue tag="ea_guid" value="{28F89EB9-A499-4648-90DC-3E8DCF434FB1}"/>
												<UML:TaggedValue tag="styleex" value="volatile=0;"/>
											</UML:ModelElement.taggedValue>
										</UML:Attribute>
										<UML:Attribute name="TYPE_STRING" changeable="frozen" visibility="public" ownerScope="instance" targetScope="instance">
											<UML:Attribute.initialValue>
												<UML:Expression body="3"/>
											</UML:Attribute.initialValue>
											<UML:StructuralFeature.type>
												<UML:Classifier xmi.idref="eaxmiid0"/>
											</UML:StructuralFeature.type>
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="length" value="0"/>
												<UML:TaggedValue tag="ordered" value="0"/>
												<UML:TaggedValue tag="precision" value="0"/>
												<UML:TaggedValue tag="scale" value="0"/>
												<UML:TaggedValue tag="collection" value="false"/>
												<UML:TaggedValue tag="position" value="2"/>
												<UML:TaggedValue tag="lowerBound" value="1"/>
												<UML:TaggedValue tag="upperBound" value="1"/>
												<UML:TaggedValue tag="ea_guid" value="{3F952DBF-89CE-42c6-92F8-40C2CD29F196}"/>
												<UML:TaggedValue tag="styleex" value="volatile=0;"/>
											</UML:ModelElement.taggedValue>
										</UML:Attribute>
										<UML:Attribute name="paramDefs" changeable="none" visibility="private" ownerScope="instance" targetScope="instance">
											<UML:Attribute.initialValue>
												<UML:Expression body="array()"/>
											</UML:Attribute.initialValue>
											<UML:StructuralFeature.type>
												<UML:Classifier xmi.idref="eaxmiid0"/>
											</UML:StructuralFeature.type>
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="length" value="0"/>
												<UML:TaggedValue tag="ordered" value="0"/>
												<UML:TaggedValue tag="precision" value="0"/>
												<UML:TaggedValue tag="scale" value="0"/>
												<UML:TaggedValue tag="collection" value="false"/>
												<UML:TaggedValue tag="position" value="3"/>
												<UML:TaggedValue tag="lowerBound" value="1"/>
												<UML:TaggedValue tag="upperBound" value="1"/>
												<UML:TaggedValue tag="ea_guid" value="{ABF6E2F3-BAF9-4475-993E-33F590591D7A}"/>
												<UML:TaggedValue tag="styleex" value="volatile=0;"/>
											</UML:ModelElement.taggedValue>
										</UML:Attribute>
										<UML:Attribute name="paramValues" changeable="none" visibility="private" ownerScope="instance" targetScope="instance">
											<UML:Attribute.initialValue>
												<UML:Expression body="array()"/>
											</UML:Attribute.initialValue>
											<UML:StructuralFeature.type>
												<UML:Classifier xmi.idref="eaxmiid0"/>
											</UML:StructuralFeature.type>
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="length" value="0"/>
												<UML:TaggedValue tag="ordered" value="0"/>
												<UML:TaggedValue tag="precision" value="0"/>
												<UML:TaggedValue tag="scale" value="0"/>
												<UML:TaggedValue tag="collection" value="false"/>
												<UML:TaggedValue tag="position" value="4"/>
												<UML:TaggedValue tag="lowerBound" value="1"/>
												<UML:TaggedValue tag="upperBound" value="1"/>
												<UML:TaggedValue tag="ea_guid" value="{8F8762C2-810F-4d79-A1BD-F849872FEFE3}"/>
												<UML:TaggedValue tag="styleex" value="volatile=0;"/>
											</UML:ModelElement.taggedValue>
										</UML:Attribute>
										<UML:Operation name="__construct" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Create parameter handler"/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="0"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{D4FC7B05-E3A7-4407-BA0D-7201BD7D247B}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-E3A7-4407-BA0D-7201BD7D247B}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
										<UML:Operation name="registerParam" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Register a new parameter. Register a new parameter to be recognized by the parser. The short option is a single character, the long option can be any string containing [a-z-]+. Via the options array several options can be defined for a parameter: 
&lt;code&gt; array( 'type'      =&gt; TYPE_NONE,  // option does not expect a value by default, use TYPE_* constants 'default'   =&gt; null,       // no default value by default 'multiple'  =&gt; false,      // are multiple values expected? 'short'     =&gt; '',         // no short description by default 'long'      =&gt; '',         // no help text by default 'depends'   =&gt; array(),    // no depending options by default 'excludes'  =&gt; array(),    // no excluded options by default 'arguments' =&gt; true,       // are arguments allowed? );
&lt;/code&gt;  Attention: Already existing parameter will be overwriten! If an already existing alias is attempted to be registered, the alias will be deleted and replaced by the new parameter.  Parameter shortcuts may only contain one character and will be used in an application call using &quot;-x &lt;value&gt;&quot;. Long parameter versions will be used like &quot;--long-parameter=&lt;value&gt;&quot;.  A parameter can have no value (TYPE_NONE), an integer/string value (TYPE_INT/TYPE_STRING) or multiple of those ('muliple' =&gt; true).  A parameter can also include a rule that disallows arguments, when it's used. Per default arguments are allowed and can be retrieved using the {ezcConsoleParameter::getArguments()} method. 
@see ezcConsoleParameter::unregisterParam() 
@param string $short          Short parameter
@param string $long           Long version of parameter
@param array(string) $options See description 
@return void"/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="1"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{4E5D9391-82C1-491b-8220-A30F1771C9AD}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-82C1-491b-8220-A30F1771C9AD}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="short" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{E7A0DD89-4134-4045-810F-CBA1DF7195A7}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="long" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="1"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{C77D434A-96A7-415f-9746-D0DCF5E9CC4A}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="options" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="2"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{74478E3D-49A7-4fb4-AD19-19A211A42A39}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression body="array() "/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
										<UML:Operation name="registerAlias" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Register an alias to a parameter. Registers a new alias for an existing parameter. Aliases may then be used as if they were real parameters. 
@see ezcConsoleParameter::unregisterAlias() 
@param string $short    Shortcut of the alias
@param string $long     Long version of the alias
@param strung $refShort Reference to an existing param (short) 
@return void"/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="2"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{7B98693A-A103-4d8b-AADF-A22492FA9A8C}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-A103-4d8b-AADF-A22492FA9A8C}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="short" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{164FCFA0-C49D-4256-8A55-2AC2A263BDEC}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="long" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="1"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{E48733E4-DA93-473f-A01D-78750A591EB3}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="refShort" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="2"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{CED82ED9-00BD-472d-9007-9F91CC856526}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
										<UML:Operation name="unregisterParam" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Remove a parameter to be no more supported. Using this function you will remove a parameter. Depending on the second option dependencies to this parameter are handled. Per default, just all dependencies to that actual parameter are removed (false value). Setting it to true will completely unregister all parameters that depend on the current one. 
@see ezcConsoleParameter::registerParam() 
@param string $short Short option name for the parameter to be removed.
@param bool $deps    Handling of dependencies while unregistering. 
@return void 
@link ezcConsoleParameterException::CODE_EXISTANCE}."/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="3"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{8136EE82-D67D-4bfd-91F1-E02566F8A818}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-D67D-4bfd-91F1-E02566F8A818}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="short" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{AD1A6E5D-57D3-43dc-8E4E-D456DECC0FC2}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="deps" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="1"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{A91EE54C-9830-41e7-8DCF-D1C859C4A1E3}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression body="false "/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
										<UML:Operation name="unregisterAlias" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Remove an alias  to be no more supported. Unregisteres an existing alias. 
@see ezcConsoleParameter::registerAlias() 
@param string $short Short option name for the parameter to be removed. 
@return void 
@link ezcConsoleParameterException::CODE_EXISTANCE}."/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="4"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{8B23DBB5-0766-4ac9-8542-032AC549652D}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-0766-4ac9-8542-032AC549652D}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="short" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{4BDC2167-2BE3-4f48-890A-96BDB4B55643}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
										<UML:Operation name="fromString" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Registeres parameters according to a string specification. Accepts a string like used in eZ publis 3.x to define parameters and registeres all parameters accordingly. String definitions look like this: 
&lt;code&gt; [s:|size:][u:|user:][a:|all:]
&lt;/code&gt;  This string will result in 3 parameters: -s / --size -u / --user -a / --all 
@param string $paramDef Parameter definition string."/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="5"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{5348AAEE-E3F2-4c9b-B9FE-2B1050E93D44}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-E3F2-4c9b-B9FE-2B1050E93D44}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="paramDef" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{3485F06D-23DA-4664-9921-45343D320684}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
										<UML:Operation name="process" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Process the input parameters. Actually process the input parameters according to the actual settings.  Per default this method uses $argc and $argv for processing. You can override this setting with your own input, if necessary, using the parameters of this method. (Attention, first argument is always the pro gram name itself!)  All exceptions thrown by this method contain an additional attribute &quot;param&quot; which specifies the parameter on which the error occured. 
@param array(int -&gt; string) $args The arguments 
@link ezcConsoleParameterException::CODE_DEPENDENCY}.
@link ezcConsoleParameterException::CODE_EXCLUSION}.
@link ezcConsoleParameterException::CODE_TYPE}. 
@see ezcConsoleParameterException"/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="6"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{D5BE7041-F87E-4bee-9B1F-C75291978BC5}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-F87E-4bee-9B1F-C75291978BC5}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="args" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{7632E404-565A-4001-8CAA-EC25E1FA6EB2}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression body="null "/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
										<UML:Operation name="getParam" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Receive the data for a specific parameter. Returns the data sumbitted for a specific parameter. 
@param string $short The parameter shortcut 
@return mixed String value of the parameter, true if set without value or false on not set."/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="7"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{F2658D07-C9FB-475f-9A79-ED7211E8BBC0}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-C9FB-475f-9A79-ED7211E8BBC0}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="short" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{E12581BF-6AE3-497f-A787-7EFD7C32C0AB}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
										<UML:Operation name="getArguments" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Returns arguments provided to the program. This method returns all arguments provided to a program in an integer indexed array. Arguments are sorted in the way they are submitted to the program. You can disable arguments through the 'arguments' flag of a parameter, if you want to disallow arguments.  Arguments are either the last part of the program call (if the last parameter is not a 'multiple' one) or divided via the '--' method which is commonly used on Unix (if the last parameter accepts multiple values this is required). 
@return array(int =&gt; string) Arguments."/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="8"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{56CDC70A-D8A8-465a-937B-DC4ED0B8A7BA}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-D8A8-465a-937B-DC4ED0B8A7BA}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
										<UML:Operation name="getHelp" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Returns array of help info on parameters. If given a parameter shortcut, returns an array of several help information: 
&lt;code&gt; array( 'short' =&gt; &lt;string&gt;, 'long'  =&gt; &lt;string&gt;, 'usage' =&gt; &lt;string&gt;, // Autogenerated from the rules for the parameter 'alias' =&gt; &lt;string&gt;, // Info on the aliases of a parameter );
&lt;/code&gt;  If no parameter shortcut given, returns an array of above described arrays with a key for every parameter shortcut defined. 
@param string $short Short cut value of the parameter.
@return array(string) See description. 
@link ezcConsoleParameterException::CODE_EXISTANCE}."/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="9"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{3375BF23-9AEF-42cd-907F-14FDF5CD7ECA}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-9AEF-42cd-907F-14FDF5CD7ECA}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="short" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{2835C2F3-898D-4063-94FC-1EA7A8AF9589}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression body="null "/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
										<UML:Operation name="getHelpText" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Returns string of help info on parameters. If given a parameter shortcut, returns a string of help information: 
&lt;code&gt;  Usage: -&lt;short&gt; / --&lt;long&gt;= &lt;type&gt; &lt;usageinfo&gt;
&lt;shortdesc&gt;
&lt;longdesc&gt;
&lt;dependencies&gt; / &lt;exclusions&gt; 
&lt;/code&gt;  If not given a parameter shortcut, returns a string of global help information: 
&lt;code&gt;  Usage: [-&lt;short&gt;] [-&lt;short&gt;] ... -&lt;short&gt; / --&lt;long&gt;  &lt;type&gt;  &lt;default&gt;   &lt;shortdesc&gt; ... 
&lt;/code&gt; 
@param string $short Shortcut of the parameter to get help text for. 
@return string See description. 
@link ezcConsoleParameterException::CODE_EXISTANCE}."/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="10"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{E66F0967-79A7-47a6-ADF3-079AAC380175}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-79A7-47a6-ADF3-079AAC380175}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="short" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{21F7BD1F-E7B3-4087-8C4C-60B766E57DB4}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression body="null "/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
									</UML:Classifier.feature>
								</UML:Class>
								<UML:Dependency client="EAID_A51EEA3E_1E35_4947_AFF6_4F0ED6B44ADC" supplier="EAID_C6C700C8_814F_49fc_9B9C_1123BB0B4815" xmi.id="EAID_F959A77C_CEDF_4555_A103_9EADB2730D13" visibility="public">
									<UML:ModelElement.stereotype>
										<UML:Stereotype name="throws"/>
									</UML:ModelElement.stereotype>
									<UML:ModelElement.taggedValue>
										<UML:TaggedValue tag="style" value="2"/>
										<UML:TaggedValue tag="ea_type" value="Dependency"/>
										<UML:TaggedValue tag="direction" value="Source -&gt; Destination"/>
										<UML:TaggedValue tag="linemode" value="2"/>
										<UML:TaggedValue tag="linecolor" value="-1"/>
										<UML:TaggedValue tag="linewidth" value="0"/>
										<UML:TaggedValue tag="seqno" value="0"/>
										<UML:TaggedValue tag="stereotype" value="throws"/>
										<UML:TaggedValue tag="headStyle" value="0"/>
										<UML:TaggedValue tag="lineStyle" value="0"/>
										<UML:TaggedValue tag="conditional" value="�throws�"/>
										<UML:TaggedValue tag="src_visibility" value="Public"/>
										<UML:TaggedValue tag="src_aggregation" value="0"/>
										<UML:TaggedValue tag="src_isOrdered" value="false"/>
										<UML:TaggedValue tag="src_isNavigable" value="false"/>
										<UML:TaggedValue tag="src_containment" value="Unspecified"/>
										<UML:TaggedValue tag="dst_visibility" value="Public"/>
										<UML:TaggedValue tag="dst_aggregation" value="0"/>
										<UML:TaggedValue tag="dst_isOrdered" value="false"/>
										<UML:TaggedValue tag="dst_isNavigable" value="true"/>
										<UML:TaggedValue tag="dst_containment" value="Unspecified"/>
										<UML:TaggedValue tag="privatedata5" value="SX=0;SY=0;EX=0;EY=0;EDGE=1;"/>
										<UML:TaggedValue tag="virtualInheritance" value="0"/>
										<UML:TaggedValue tag="mb" value="�throws�"/>
									</UML:ModelElement.taggedValue>
								</UML:Dependency>
								<UML:Class name="ezcConsoleTable" xmi.id="EAID_A9F2232F_845A_4da2_A329_950ED3CDB676" visibility="public" namespace="EAPK_9300B830_36D9_4e00_AE7D_EA3DA9B092B9" isRoot="false" isLeaf="false" isAbstract="false" isActive="false">
									<UML:ModelElement.taggedValue>
										<UML:TaggedValue tag="documentation" value="Creating tables to be printed to the console. 
&lt;code&gt;  ... creating ezcConsoleOutput object  $options = array( 'lineColorHead' =&gt; 'red',  // Make header rows surrounded by red lines );  $table = new ezcConsoleTable($out, array('width' =&gt; 60, 'cols' = 3), $options); Generate a header row: $table-&gt;addRowHead(array('First col', 'Second col', 'Third col')); Right column will be the largest $table-&gt;addRow(array('Data', 'Data', 'Very very very very very long data')); $table-&gt;output(); 
&lt;/code&gt;  
@see ezcConsoleOutput
@package ConsoleTools
@link http://www.gnu.org/copyleft/lesser.html}"/>
										<UML:TaggedValue tag="isSpecification" value="false"/>
										<UML:TaggedValue tag="ea_stype" value="Class"/>
										<UML:TaggedValue tag="ea_ntype" value="0"/>
										<UML:TaggedValue tag="version" value="//autogen//
@copyright Copyright (C) 2005 eZ syst"/>
										<UML:TaggedValue tag="package" value="EAPK_9300B830_36D9_4e00_AE7D_EA3DA9B092B9"/>
										<UML:TaggedValue tag="date_created" value="2005-08-12 09:19:36"/>
										<UML:TaggedValue tag="date_modified" value="2005-08-19 11:42:35"/>
										<UML:TaggedValue tag="genfile" value="E:\src\ezcomponents\packages\ConsoleTools\trunk\src\console\table.php"/>
										<UML:TaggedValue tag="gentype" value="PHP"/>
										<UML:TaggedValue tag="tagged" value="0"/>
										<UML:TaggedValue tag="package_name" value="console"/>
										<UML:TaggedValue tag="phase" value="1.0"/>
										<UML:TaggedValue tag="author" value="Jan Borsodi"/>
										<UML:TaggedValue tag="complexity" value="1"/>
										<UML:TaggedValue tag="status" value="Proposed"/>
										<UML:TaggedValue tag="eventflags" value="LNK=7154;"/>
										<UML:TaggedValue tag="style" value="BackColor=-1;BorderColor=-1;BorderWidth=-1;FontColor=-1;VSwimLanes=0;HSwimLanes=0;BorderStyle=0;"/>
									</UML:ModelElement.taggedValue>
									<UML:Classifier.feature>
										<UML:Attribute name="WRAP_AUTO" changeable="frozen" visibility="public" ownerScope="instance" targetScope="instance">
											<UML:Attribute.initialValue>
												<UML:Expression body="1"/>
											</UML:Attribute.initialValue>
											<UML:StructuralFeature.type>
												<UML:Classifier xmi.idref="eaxmiid0"/>
											</UML:StructuralFeature.type>
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="description" value="Automatically wrap text to fit into a column.
@see ezcConsoleTable::$options"/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="length" value="0"/>
												<UML:TaggedValue tag="ordered" value="0"/>
												<UML:TaggedValue tag="precision" value="0"/>
												<UML:TaggedValue tag="scale" value="0"/>
												<UML:TaggedValue tag="collection" value="false"/>
												<UML:TaggedValue tag="position" value="0"/>
												<UML:TaggedValue tag="lowerBound" value="1"/>
												<UML:TaggedValue tag="upperBound" value="1"/>
												<UML:TaggedValue tag="ea_guid" value="{0A51B2F7-3155-483c-A77F-CBAD7E46755C}"/>
												<UML:TaggedValue tag="styleex" value="volatile=0;"/>
											</UML:ModelElement.taggedValue>
										</UML:Attribute>
										<UML:Attribute name="WRAP_NONE" changeable="frozen" visibility="public" ownerScope="instance" targetScope="instance">
											<UML:Attribute.initialValue>
												<UML:Expression body="2"/>
											</UML:Attribute.initialValue>
											<UML:StructuralFeature.type>
												<UML:Classifier xmi.idref="eaxmiid0"/>
											</UML:StructuralFeature.type>
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="description" value="Do not wrap text. Columns will be extended to fit the largest text. ATTENTION: This is riscy!
@see ezcConsoleTable::$options"/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="length" value="0"/>
												<UML:TaggedValue tag="ordered" value="0"/>
												<UML:TaggedValue tag="precision" value="0"/>
												<UML:TaggedValue tag="scale" value="0"/>
												<UML:TaggedValue tag="collection" value="false"/>
												<UML:TaggedValue tag="position" value="1"/>
												<UML:TaggedValue tag="lowerBound" value="1"/>
												<UML:TaggedValue tag="upperBound" value="1"/>
												<UML:TaggedValue tag="ea_guid" value="{F2C5B9CA-43B7-4586-8854-7E9333D246E5}"/>
												<UML:TaggedValue tag="styleex" value="volatile=0;"/>
											</UML:ModelElement.taggedValue>
										</UML:Attribute>
										<UML:Attribute name="WRAP_CUT" changeable="frozen" visibility="public" ownerScope="instance" targetScope="instance">
											<UML:Attribute.initialValue>
												<UML:Expression body="3"/>
											</UML:Attribute.initialValue>
											<UML:StructuralFeature.type>
												<UML:Classifier xmi.idref="eaxmiid0"/>
											</UML:StructuralFeature.type>
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="description" value="Text will be cut to fit into a column.
@see ezcConsoleTable::$options"/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="length" value="0"/>
												<UML:TaggedValue tag="ordered" value="0"/>
												<UML:TaggedValue tag="precision" value="0"/>
												<UML:TaggedValue tag="scale" value="0"/>
												<UML:TaggedValue tag="collection" value="false"/>
												<UML:TaggedValue tag="position" value="2"/>
												<UML:TaggedValue tag="lowerBound" value="1"/>
												<UML:TaggedValue tag="upperBound" value="1"/>
												<UML:TaggedValue tag="ea_guid" value="{2F9D32F3-EFCD-4003-BB1E-294C6411C738}"/>
												<UML:TaggedValue tag="styleex" value="volatile=0;"/>
											</UML:ModelElement.taggedValue>
										</UML:Attribute>
										<UML:Attribute name="settings" changeable="none" visibility="protected" ownerScope="instance" targetScope="instance">
											<UML:Attribute.initialValue>
												<UML:Expression/>
											</UML:Attribute.initialValue>
											<UML:StructuralFeature.type>
												<UML:Classifier xmi.idref="eaxmiid0"/>
											</UML:StructuralFeature.type>
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="description" value="Settings for the table. 
&lt;code&gt; array( 'width' =&gt; &lt;int&gt;,       // Width of the table 'cols'  =&gt; &lt;int&gt;,       // Number of columns );
&lt;/code&gt; 
@var array(string)"/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="length" value="0"/>
												<UML:TaggedValue tag="ordered" value="0"/>
												<UML:TaggedValue tag="precision" value="0"/>
												<UML:TaggedValue tag="scale" value="0"/>
												<UML:TaggedValue tag="collection" value="false"/>
												<UML:TaggedValue tag="position" value="3"/>
												<UML:TaggedValue tag="lowerBound" value="1"/>
												<UML:TaggedValue tag="upperBound" value="1"/>
												<UML:TaggedValue tag="ea_guid" value="{76030D04-2AD9-406d-B80E-BFD3249F77C2}"/>
												<UML:TaggedValue tag="styleex" value="volatile=0;"/>
											</UML:ModelElement.taggedValue>
										</UML:Attribute>
										<UML:Attribute name="options" changeable="none" visibility="protected" ownerScope="instance" targetScope="instance">
											<UML:Attribute.initialValue>
												<UML:Expression body="array(
        'colWidth'  =&gt; 'auto',      // Automatically define column width. Else array of width
                                    // per column like array( 0 =&gt; 10, 1 =&gt; 15, 2 =&gt; 5,...);
        'colWrap'   =&gt; WRAP_AUTO,
        
        'lineTop'       =&gt; '-',
        'lineBottom'    =&gt; '-',
        'lineLeft'      =&gt; '|',
        'lineRight'     =&gt; '|',

        'cornerTopLeft'     =&gt; '+',
        'cornerBottomLeft'  =&gt; '+',
        'cornerTopRight'    =&gt; '+',
        'cornerBottomRight' =&gt; '+',

        'lineColor'     =&gt; 'default',
        'lineColorHead' =&gt; 'default',
    )"/>
											</UML:Attribute.initialValue>
											<UML:StructuralFeature.type>
												<UML:Classifier xmi.idref="eaxmiid0"/>
											</UML:StructuralFeature.type>
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="description" value="Options for the table. 
@var array(string)"/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="length" value="0"/>
												<UML:TaggedValue tag="ordered" value="0"/>
												<UML:TaggedValue tag="precision" value="0"/>
												<UML:TaggedValue tag="scale" value="0"/>
												<UML:TaggedValue tag="collection" value="false"/>
												<UML:TaggedValue tag="position" value="4"/>
												<UML:TaggedValue tag="lowerBound" value="1"/>
												<UML:TaggedValue tag="upperBound" value="1"/>
												<UML:TaggedValue tag="ea_guid" value="{86623909-E3BE-42e2-9592-C246FCA6B2E0}"/>
												<UML:TaggedValue tag="styleex" value="volatile=0;"/>
											</UML:ModelElement.taggedValue>
										</UML:Attribute>
										<UML:Attribute name="outputHandler" changeable="none" visibility="protected" ownerScope="instance" targetScope="instance">
											<UML:Attribute.initialValue>
												<UML:Expression/>
											</UML:Attribute.initialValue>
											<UML:StructuralFeature.type>
												<UML:Classifier xmi.idref="EAID_65A37092_56CE_4e5a_8C30_366469BD8468"/>
											</UML:StructuralFeature.type>
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="description" value="The ezcConsoleOutput object to use. 
@var ezcConsoleOutput"/>
												<UML:TaggedValue tag="type" value="ezcConsoleOutput"/>
												<UML:TaggedValue tag="length" value="0"/>
												<UML:TaggedValue tag="ordered" value="0"/>
												<UML:TaggedValue tag="precision" value="0"/>
												<UML:TaggedValue tag="scale" value="0"/>
												<UML:TaggedValue tag="collection" value="false"/>
												<UML:TaggedValue tag="position" value="5"/>
												<UML:TaggedValue tag="lowerBound" value="1"/>
												<UML:TaggedValue tag="upperBound" value="1"/>
												<UML:TaggedValue tag="ea_guid" value="{5DEF0E6B-4A38-4bc6-B053-6C114AE6EC99}"/>
												<UML:TaggedValue tag="styleex" value="volatile=0;"/>
											</UML:ModelElement.taggedValue>
										</UML:Attribute>
										<UML:Operation name="__construct" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Creates a new table. 
@param ezcConsoleOutput $outHandler Output handler to utilize
@param array(string) $settings      Settings
@param array(string) $options       Options 
@see ezcConsoleTable::$settings
@see ezcConsoleTable::$options"/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="0"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{0FAA4542-2113-4eb5-8BB0-F021ABAFE110}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-2113-4eb5-8BB0-F021ABAFE110}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="outHandler" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="EAID_65A37092_56CE_4e5a_8C30_366469BD8468"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="ezcConsoleOutput"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="classifier" value="EAID_65A37092_56CE_4e5a_8C30_366469BD8468"/>
														<UML:TaggedValue tag="ea_guid" value="{F8D81FCD-DA4E-4f98-9A86-FF9C68B7AD37}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="settings" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="1"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{7145A29B-B5D3-4bf4-93FB-00406EFA5604}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="options" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="2"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{1C4C87DC-B684-43de-B069-E72D7A2EBFFA}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression body="array() "/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
										<UML:Operation name="create" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Create an entire table. Creates an entire table from an array of data. 
&lt;code&gt; array( 0 =&gt; array( 0 =&gt; &lt;string&gt;, 1 =&gt; &lt;string&gt;, 2 =&gt; &lt;string&gt;,... ), 1 =&gt; array( 0 =&gt; &lt;string&gt;, 1 =&gt; &lt;string&gt;, 2 =&gt; &lt;string&gt;,... ), 2 =&gt; array( 0 =&gt; &lt;string&gt;, 1 =&gt; &lt;string&gt;, 2 =&gt; &lt;string&gt;,... ), ... );
&lt;/code&gt; 
@see ezcConsoleTable::__construct()
@see ezcConsoleTable::$settings
@see ezcConsoleTable::$options 
@param array(int -&gt; string) $data   Data for the table
@param ezcConsoleOutput $outHandler Output handler to utilize
@param array(string) $settings      Settings
@param array(string) $options       Options"/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="static" value="1"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="1"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{4B1BEFAA-1776-4886-874E-A2D27EB4DE58}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-1776-4886-874E-A2D27EB4DE58}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="data" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{251C8593-3B19-4008-9737-C38D262CD29E}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="outHandler" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="EAID_65A37092_56CE_4e5a_8C30_366469BD8468"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="1"/>
														<UML:TaggedValue tag="type" value="ezcConsoleOutput"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="classifier" value="EAID_65A37092_56CE_4e5a_8C30_366469BD8468"/>
														<UML:TaggedValue tag="ea_guid" value="{5D5A3932-3AB7-44fa-AA30-715F904FDE90}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="settings" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="2"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{B21906E2-A976-45b0-96F8-E38B83092EED}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="options" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="3"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{3C37112F-2CB2-4742-AEDE-C9D9EF42655A}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression body="array() "/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
										<UML:Operation name="addRow" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Add a row of data to the table. Add a row of data to the table. A row looks like this: 
&lt;code&gt; array( 0 =&gt; &lt;string&gt;, 1 =&gt; &lt;string&gt;,... );
&lt;/code&gt;  The options parameter overrides the globally set options. 
@param array(int =&gt; string) $rowData The data for the row
@param array(string) $options        Override {@link eczConsoleTable::$options}
@return int Number of the row."/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="2"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{D1FD2110-460D-4e2e-BEBF-9B635BBE64CF}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-460D-4e2e-BEBF-9B635BBE64CF}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="rowData" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{1A102984-09C4-4b64-9937-5874500BA97A}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="options" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="1"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{817380E2-F1B4-4cd6-966A-B554880456EB}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
										<UML:Operation name="addHeadRow" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Add a header row to the table. Add a header row to the table. Format {@link ezcConsoleTable::addRow()}.  The options parameter overrides the globally set options. 
@param array(int =&gt; string) $rowData The row data
@param array(string) $options        Override {@link eczConsoleTable::$options}
@return int Number of the row."/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="3"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{4191F84C-57D0-4efb-987F-390AC8CDB51E}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-57D0-4efb-987F-390AC8CDB51E}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="rowData" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{E5DDE536-85FC-4d85-BA57-E96ABD582AB4}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="options" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="1"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{D71BA1BF-7EDD-4083-83FE-EEF03380B706}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
										<UML:Operation name="setCell" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Set data for specific cell. Sets the data for a specific cell. If the row referenced does not exist yet, it's created with empty values. If previous rows do not exist, they are created with empty values. Existing cell data is overwriten. 
@param int $row         Row number.
@param int $column      Column number.
@param string $cellData Data for the cell."/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="4"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{7B0762B7-35D9-431a-BE70-5C62D5F82098}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-35D9-431a-BE70-5C62D5F82098}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="row" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{21C16A8B-D5CE-48d9-85AD-EAEFAEC0B6CB}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="column" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="1"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{C02E910F-C8D8-4aac-AA2C-05961B6C3438}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="cellData" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="2"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{10D31C1D-2079-4d76-9E16-B4706E1687FA}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
										<UML:Operation name="makeHeadRow" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Make a row to a header row. Defines the row with the specified number to be a header row. 
@param int $row Number of the row to affect. 
@see eczConsoleTable::setDefaultRow()"/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="5"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{361A1769-7311-461d-9AEC-A52D748E0D5D}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-7311-461d-9AEC-A52D748E0D5D}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="row" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{3EF5282D-89D7-4c18-B147-99E2ADA02740}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
										<UML:Operation name="makeDefaultRow" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Make a row to a default row. Defines the row with the specified number to be a default row. (Used to bring header rows back to normal.) 
@param int $row Number of the row to affect. 
@see eczConsoleTable::setHeadRow()"/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="6"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{786429A3-71B7-49a7-ADFB-68D3FADC61D4}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-71B7-49a7-ADFB-68D3FADC61D4}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="row" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{93466362-883D-4c69-A351-78B7C02F14E7}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
										<UML:Operation name="getTable" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Returns the table in a string. Returns the entire table as a string. 
@return string"/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="7"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{C7B4159C-0EBB-4626-B678-B213CAB8A270}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-0EBB-4626-B678-B213CAB8A270}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
										<UML:Operation name="outputTable" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Output the table. Prints the complete table to the console. 
@return void"/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="8"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{BF438275-C703-40a7-975E-3FD09369025D}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-C703-40a7-975E-3FD09369025D}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
									</UML:Classifier.feature>
								</UML:Class>
								<UML:Class name="ezcConsoleProgressbar" xmi.id="EAID_EE63FC0D_D590_4d0f_9F83_338683F8E000" visibility="public" namespace="EAPK_9300B830_36D9_4e00_AE7D_EA3DA9B092B9" isRoot="false" isLeaf="false" isAbstract="false" isActive="false">
									<UML:ModelElement.taggedValue>
										<UML:TaggedValue tag="documentation" value="Creating and maintaining progressbars to be printed to the console. 
@todo The author of the PEAR package &quot;Console_ProgressBar&quot; accepted us to take over his code from that package and improve it for our needs. {@link http://pear.php.net/package/console_progressbar} 
&lt;code&gt;  ... creating ezcConsoleOutput object  $set = array('max' =&gt; 150, 'step' =&gt; 5); $opt = array( 'emptyChar'     =&gt; '-', 'progressChar'  =&gt; '#', 'formatString'  =&gt; 'Uploading file '.$myFilename.' %act%/%max% kb [%bar%] %percent%%', ); $progress = new ezcConsoleProgressbar($out, $set, $opt);  while( $file-&gt;upload() ) { $progress-&gt;advance(); } $progress-&gt;finish(); $out-&gt;outputText(&quot;Successfully uploaded $myFilename.\n&quot;, 'success'); 
&lt;/code&gt;  
@package ConsoleTools
@link http://www.gnu.org/copyleft/lesser.html}"/>
										<UML:TaggedValue tag="isSpecification" value="false"/>
										<UML:TaggedValue tag="ea_stype" value="Class"/>
										<UML:TaggedValue tag="ea_ntype" value="0"/>
										<UML:TaggedValue tag="version" value="//autogen//
@copyright Copyright (C) 2005 eZ syst"/>
										<UML:TaggedValue tag="package" value="EAPK_9300B830_36D9_4e00_AE7D_EA3DA9B092B9"/>
										<UML:TaggedValue tag="date_created" value="2005-08-12 09:19:35"/>
										<UML:TaggedValue tag="date_modified" value="2005-08-19 11:42:35"/>
										<UML:TaggedValue tag="genfile" value="E:\src\ezcomponents\packages\ConsoleTools\trunk\src\console\progressbar.php"/>
										<UML:TaggedValue tag="gentype" value="PHP"/>
										<UML:TaggedValue tag="tagged" value="0"/>
										<UML:TaggedValue tag="package_name" value="console"/>
										<UML:TaggedValue tag="phase" value="1.0"/>
										<UML:TaggedValue tag="author" value="Jan Borsodi"/>
										<UML:TaggedValue tag="complexity" value="1"/>
										<UML:TaggedValue tag="status" value="Proposed"/>
										<UML:TaggedValue tag="eventflags" value="LNK=e6a3;"/>
										<UML:TaggedValue tag="style" value="BackColor=-1;BorderColor=-1;BorderWidth=-1;FontColor=-1;VSwimLanes=0;HSwimLanes=0;BorderStyle=0;"/>
									</UML:ModelElement.taggedValue>
									<UML:Classifier.feature>
										<UML:Attribute name="settings" changeable="none" visibility="protected" ownerScope="instance" targetScope="instance">
											<UML:Attribute.initialValue>
												<UML:Expression/>
											</UML:Attribute.initialValue>
											<UML:StructuralFeature.type>
												<UML:Classifier xmi.idref="eaxmiid0"/>
											</UML:StructuralFeature.type>
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="description" value="Settings for the progress bar. 
&lt;code&gt; array( 'max'   =&gt; &lt;int&gt;    // Value to progress to 'step'  =&gt; &lt;int&gt;    // Stepwidth );
&lt;/code&gt; 
@var array(string)"/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="length" value="0"/>
												<UML:TaggedValue tag="ordered" value="0"/>
												<UML:TaggedValue tag="precision" value="0"/>
												<UML:TaggedValue tag="scale" value="0"/>
												<UML:TaggedValue tag="collection" value="false"/>
												<UML:TaggedValue tag="position" value="0"/>
												<UML:TaggedValue tag="lowerBound" value="1"/>
												<UML:TaggedValue tag="upperBound" value="1"/>
												<UML:TaggedValue tag="ea_guid" value="{30C94C5C-E267-49fd-8491-19E7840E30FE}"/>
												<UML:TaggedValue tag="styleex" value="volatile=0;"/>
											</UML:ModelElement.taggedValue>
										</UML:Attribute>
										<UML:Attribute name="options" changeable="none" visibility="protected" ownerScope="instance" targetScope="instance">
											<UML:Attribute.initialValue>
												<UML:Expression body="array(
        'barChar'       =&gt; '+',     // Char to fill progress bar with
        'emptyChar'     =&gt; ' ',     // Char to fill empty space in progress bar with
        'progressChar'  =&gt; '&gt;',     // Right most char of the progress bar filling
        'formatString'  =&gt; '[%bar%] %percent% %',   // Format string
        'width'         =&gt; 100,     // Maximum width of the progressbar
    )"/>
											</UML:Attribute.initialValue>
											<UML:StructuralFeature.type>
												<UML:Classifier xmi.idref="eaxmiid0"/>
											</UML:StructuralFeature.type>
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="description" value="Options 
&lt;code&gt; array( 'barChar'       =&gt; '+',     // Char to fill progress bar with 'emptyChar'     =&gt; ' ',     // Char for empty space in progress bar 'progressChar'  =&gt; '&gt;',     // Progress char of the bar filling 'formatString'  =&gt; '[%bar%] %percent%%',   // == &quot;[+++++&gt;    ] 60%&quot; 'width'         =&gt; 10,      // Maximum width of the progressbar );
&lt;/code&gt;  'formatString' can contain the following placeholders: '%percent%' =&gt; Actual percent value '%max%'     =&gt; Maximum value '%act%'     =&gt; Actual value '%bar%'     =&gt; The actual progressbar 
@var array(string)"/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="length" value="0"/>
												<UML:TaggedValue tag="ordered" value="0"/>
												<UML:TaggedValue tag="precision" value="0"/>
												<UML:TaggedValue tag="scale" value="0"/>
												<UML:TaggedValue tag="collection" value="false"/>
												<UML:TaggedValue tag="position" value="1"/>
												<UML:TaggedValue tag="lowerBound" value="1"/>
												<UML:TaggedValue tag="upperBound" value="1"/>
												<UML:TaggedValue tag="ea_guid" value="{59522000-4D0E-4579-B25A-CBFCCB2A1B25}"/>
												<UML:TaggedValue tag="styleex" value="volatile=0;"/>
											</UML:ModelElement.taggedValue>
										</UML:Attribute>
										<UML:Attribute name="outputHandler" changeable="none" visibility="protected" ownerScope="instance" targetScope="instance">
											<UML:Attribute.initialValue>
												<UML:Expression/>
											</UML:Attribute.initialValue>
											<UML:StructuralFeature.type>
												<UML:Classifier xmi.idref="EAID_65A37092_56CE_4e5a_8C30_366469BD8468"/>
											</UML:StructuralFeature.type>
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="description" value="The ezcConsoleOutput object to use. 
@var ezcConsoleOutput"/>
												<UML:TaggedValue tag="type" value="ezcConsoleOutput"/>
												<UML:TaggedValue tag="length" value="0"/>
												<UML:TaggedValue tag="ordered" value="0"/>
												<UML:TaggedValue tag="precision" value="0"/>
												<UML:TaggedValue tag="scale" value="0"/>
												<UML:TaggedValue tag="collection" value="false"/>
												<UML:TaggedValue tag="position" value="2"/>
												<UML:TaggedValue tag="lowerBound" value="1"/>
												<UML:TaggedValue tag="upperBound" value="1"/>
												<UML:TaggedValue tag="ea_guid" value="{38166CA5-115F-4705-A391-4B122E210FED}"/>
												<UML:TaggedValue tag="styleex" value="volatile=0;"/>
											</UML:ModelElement.taggedValue>
										</UML:Attribute>
										<UML:Operation name="__construct" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Creates a new progress bar. 
@param ezcConsoleOutput $outHandler Handler to utilize for output
@param array(string) $settings      Settings
@param array(string) $options       Options 
@see ezcConsoleTable::$settings
@see ezcConsoleTable::$options"/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="0"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{025207AC-75F2-44ba-A143-ABDFD4688F5E}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-75F2-44ba-A143-ABDFD4688F5E}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="outHandler" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="EAID_65A37092_56CE_4e5a_8C30_366469BD8468"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="ezcConsoleOutput"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="classifier" value="EAID_65A37092_56CE_4e5a_8C30_366469BD8468"/>
														<UML:TaggedValue tag="ea_guid" value="{C82DE637-5B3C-439f-B9C5-348CB3BD2CB5}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="settings" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="1"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{92DDFC0F-A1B8-4511-B369-99A6DCB9E3B0}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="options" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="2"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{453DB7BB-CEA5-4f96-A0F5-F2CB80C3DC34}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression body="array() "/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
										<UML:Operation name="start" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Start the progress bar Starts the progess bar and sticks it to the current line. No output will be done yet. Call {@link ezcConsoleProgressbar::output()} to print the bar. 
@return void"/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="1"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{A1F4087D-6D9E-40dc-BC9B-03AA07E43B13}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-6D9E-40dc-BC9B-03AA07E43B13}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
										<UML:Operation name="output" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Draw the progress bar. Prints the progressbar to the screen. If start() has not been called yet, the current line is used for {@link ezcConsolProgressbar::start()}."/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="2"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{CDE2D0A5-705A-4ee3-8A73-BA1FC8FC287C}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-705A-4ee3-8A73-BA1FC8FC287C}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
										<UML:Operation name="advance" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Advance the progress bar. Advances the progress bar by one step. Redraws the bar by default, using the {@link ezcConsoleProgressbar::output()} method. 
@param bool Whether to redraw the bar immediatelly."/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="3"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{B5F4C6F1-1E03-4b51-8D29-FF055E2DBB4C}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-1E03-4b51-8D29-FF055E2DBB4C}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
												<UML:Parameter name="redraw" kind="in" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{C3DC4346-3E0A-4535-BF94-C15030FDA033}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression body="true "/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
										<UML:Operation name="finish" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="Finish the progress bar. Finishes the bar (jump to 100% if not happened yet,...) and jumps to the next line to allow new output. Also resets the values of the output handler used, if changed."/>
												<UML:TaggedValue tag="type" value="var"/>
												<UML:TaggedValue tag="const" value="false"/>
												<UML:TaggedValue tag="synchronised" value="0"/>
												<UML:TaggedValue tag="concurrency" value="Sequential"/>
												<UML:TaggedValue tag="position" value="4"/>
												<UML:TaggedValue tag="returnarray" value="0"/>
												<UML:TaggedValue tag="pure" value="0"/>
												<UML:TaggedValue tag="ea_guid" value="{AE268367-D849-4990-8415-A31BCD928C6C}"/>
											</UML:ModelElement.taggedValue>
											<UML:BehavioralFeature.parameter>
												<UML:Parameter kind="return" visibility="public">
													<UML:Parameter.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:Parameter.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="pos" value="0"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{RETURNID-D849-4990-8415-A31BCD928C6C}"/>
													</UML:ModelElement.taggedValue>
													<UML:Parameter.defaultValue>
														<UML:Expression/>
													</UML:Parameter.defaultValue>
												</UML:Parameter>
											</UML:BehavioralFeature.parameter>
										</UML:Operation>
									</UML:Classifier.feature>
								</UML:Class>
								<UML:Package name="output" xmi.id="EAPK_4D026C21_9F61_4699_BBE9_ED9516605496" isRoot="false" isLeaf="false" isAbstract="false" visibility="public">
									<UML:ModelElement.taggedValue>
										<UML:TaggedValue tag="created" value="2005-08-12 00:00:00"/>
										<UML:TaggedValue tag="modified" value="2005-08-12 00:00:00"/>
										<UML:TaggedValue tag="iscontrolled" value="FALSE"/>
										<UML:TaggedValue tag="lastloaddate" value="2005-08-18 14:20:19"/>
										<UML:TaggedValue tag="lastsavedate" value="2005-08-18 14:20:19"/>
										<UML:TaggedValue tag="isprotected" value="FALSE"/>
										<UML:TaggedValue tag="usedtd" value="FALSE"/>
										<UML:TaggedValue tag="logxml" value="FALSE"/>
										<UML:TaggedValue tag="codepath" value="E:\src\ezcomponents\ConsoleTools\console\output"/>
										<UML:TaggedValue tag="batchsave" value="0"/>
										<UML:TaggedValue tag="batchload" value="0"/>
										<UML:TaggedValue tag="phase" value="1.0"/>
										<UML:TaggedValue tag="status" value="Proposed"/>
										<UML:TaggedValue tag="author" value="Jan Borsodi"/>
										<UML:TaggedValue tag="complexity" value="1"/>
										<UML:TaggedValue tag="ea_stype" value="Public"/>
									</UML:ModelElement.taggedValue>
									<UML:Namespace.ownedElement>
										<UML:Class name="ezcConsoleOutputException" xmi.id="EAID_4B7CE667_749A_4dde_BE45_7CBFB5519DF5" visibility="public" namespace="EAPK_4D026C21_9F61_4699_BBE9_ED9516605496" isRoot="false" isLeaf="false" isAbstract="false" isActive="false">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="General exception for use in {@see ezcConsoleOutput} class. 
@package ConsoleTools
@link http://www.gnu.org/copyleft/lesser.html}
@todo Error codes to be defined."/>
												<UML:TaggedValue tag="isSpecification" value="false"/>
												<UML:TaggedValue tag="ea_stype" value="Class"/>
												<UML:TaggedValue tag="ea_ntype" value="0"/>
												<UML:TaggedValue tag="version" value="//autogen//
@copyright Copyright (C) 2005 eZ syst"/>
												<UML:TaggedValue tag="package" value="EAPK_4D026C21_9F61_4699_BBE9_ED9516605496"/>
												<UML:TaggedValue tag="date_created" value="2005-08-12 09:19:34"/>
												<UML:TaggedValue tag="date_modified" value="2005-08-19 11:42:36"/>
												<UML:TaggedValue tag="genfile" value="E:\src\ezcomponents\packages\ConsoleTools\trunk\src\console\output\exception.php"/>
												<UML:TaggedValue tag="gentype" value="PHP"/>
												<UML:TaggedValue tag="tagged" value="0"/>
												<UML:TaggedValue tag="package_name" value="output"/>
												<UML:TaggedValue tag="phase" value="1.0"/>
												<UML:TaggedValue tag="author" value="Jan Borsodi"/>
												<UML:TaggedValue tag="complexity" value="1"/>
												<UML:TaggedValue tag="status" value="Proposed"/>
												<UML:TaggedValue tag="eventflags" value="LNK=f7da;"/>
												<UML:TaggedValue tag="style" value="BackColor=-1;BorderColor=-1;BorderWidth=-1;FontColor=-1;VSwimLanes=0;HSwimLanes=0;BorderStyle=0;"/>
											</UML:ModelElement.taggedValue>
										</UML:Class>
										<UML:Generalization subtype="EAID_4B7CE667_749A_4dde_BE45_7CBFB5519DF5" supertype="EAID_94807F39_6924_4b6f_BABD_B861BF17BDEE" xmi.id="EAID_DAC016F2_428C_4cba_88D3_77BFF3833AA6" visibility="public">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="style" value="3"/>
												<UML:TaggedValue tag="ea_type" value="Generalization"/>
												<UML:TaggedValue tag="direction" value="Source -&gt; Destination"/>
												<UML:TaggedValue tag="linemode" value="3"/>
												<UML:TaggedValue tag="linecolor" value="-1"/>
												<UML:TaggedValue tag="linewidth" value="0"/>
												<UML:TaggedValue tag="seqno" value="0"/>
												<UML:TaggedValue tag="headStyle" value="0"/>
												<UML:TaggedValue tag="lineStyle" value="0"/>
												<UML:TaggedValue tag="src_visibility" value="Public"/>
												<UML:TaggedValue tag="src_aggregation" value="0"/>
												<UML:TaggedValue tag="src_isOrdered" value="false"/>
												<UML:TaggedValue tag="src_isNavigable" value="false"/>
												<UML:TaggedValue tag="src_containment" value="Unspecified"/>
												<UML:TaggedValue tag="dst_visibility" value="Public"/>
												<UML:TaggedValue tag="dst_aggregation" value="0"/>
												<UML:TaggedValue tag="dst_isOrdered" value="false"/>
												<UML:TaggedValue tag="dst_isNavigable" value="true"/>
												<UML:TaggedValue tag="dst_containment" value="Unspecified"/>
												<UML:TaggedValue tag="$ea_xref_property" value="$XREFPROP=$XID={1E9DFB38-D0E8-4d88-900A-3C771B1DF560}$XID;$NAM=CustomProperties$NAM;$TYP=connector property$TYP;$VIS=Public$VIS;$DES=@PROP=@NAME=isSubstitutable@ENDNAME;@TYPE=boolean@ENDTYPE;@VALU=@ENDVALU;@PRMT=@ENDPRMT;@ENDPROP;$DES;$CLT={DAC016F2-428C-4cba-88D3-77BFF3833AA6}$CLT;$SUP=&lt;none&gt;$SUP;$ENDXREF;"/>
												<UML:TaggedValue tag="virtualInheritance" value="0"/>
											</UML:ModelElement.taggedValue>
										</UML:Generalization>
									</UML:Namespace.ownedElement>
								</UML:Package>
								<UML:Package name="parameter" xmi.id="EAPK_4C33B478_0B96_4ef1_B7E8_0F64B60CC675" isRoot="false" isLeaf="false" isAbstract="false" visibility="public">
									<UML:ModelElement.taggedValue>
										<UML:TaggedValue tag="created" value="2005-08-12 00:00:00"/>
										<UML:TaggedValue tag="modified" value="2005-08-12 00:00:00"/>
										<UML:TaggedValue tag="iscontrolled" value="FALSE"/>
										<UML:TaggedValue tag="lastloaddate" value="2005-08-18 14:20:19"/>
										<UML:TaggedValue tag="lastsavedate" value="2005-08-18 14:20:19"/>
										<UML:TaggedValue tag="isprotected" value="FALSE"/>
										<UML:TaggedValue tag="usedtd" value="FALSE"/>
										<UML:TaggedValue tag="logxml" value="FALSE"/>
										<UML:TaggedValue tag="codepath" value="E:\src\ezcomponents\ConsoleTools\console\parameter"/>
										<UML:TaggedValue tag="batchsave" value="0"/>
										<UML:TaggedValue tag="batchload" value="0"/>
										<UML:TaggedValue tag="phase" value="1.0"/>
										<UML:TaggedValue tag="status" value="Proposed"/>
										<UML:TaggedValue tag="author" value="Jan Borsodi"/>
										<UML:TaggedValue tag="complexity" value="1"/>
										<UML:TaggedValue tag="ea_stype" value="Public"/>
									</UML:ModelElement.taggedValue>
									<UML:Namespace.ownedElement>
										<UML:Class name="ezcConsoleParameterException" xmi.id="EAID_C6C700C8_814F_49fc_9B9C_1123BB0B4815" visibility="public" namespace="EAPK_4C33B478_0B96_4ef1_B7E8_0F64B60CC675" isRoot="false" isLeaf="false" isAbstract="false" isActive="false">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="documentation" value="General exception for use in {@see ezcConsoleParameter} class. Adds an additional field 'param' to the exception which indicates with which parameter something went wrong. 
@package ConsoleTools
@link http://www.gnu.org/copyleft/lesser.html}"/>
												<UML:TaggedValue tag="isSpecification" value="false"/>
												<UML:TaggedValue tag="ea_stype" value="Class"/>
												<UML:TaggedValue tag="ea_ntype" value="0"/>
												<UML:TaggedValue tag="version" value="//autogen//
@copyright Copyright (C) 2005 eZ syst"/>
												<UML:TaggedValue tag="package" value="EAPK_4C33B478_0B96_4ef1_B7E8_0F64B60CC675"/>
												<UML:TaggedValue tag="date_created" value="2005-08-12 09:19:35"/>
												<UML:TaggedValue tag="date_modified" value="2005-08-19 11:42:36"/>
												<UML:TaggedValue tag="genfile" value="E:\src\ezcomponents\packages\ConsoleTools\trunk\src\console\parameter\exception.php"/>
												<UML:TaggedValue tag="gentype" value="PHP"/>
												<UML:TaggedValue tag="tagged" value="0"/>
												<UML:TaggedValue tag="package_name" value="parameter"/>
												<UML:TaggedValue tag="phase" value="1.0"/>
												<UML:TaggedValue tag="author" value="Jan Borsodi"/>
												<UML:TaggedValue tag="complexity" value="1"/>
												<UML:TaggedValue tag="status" value="Proposed"/>
												<UML:TaggedValue tag="eventflags" value="LNK=c4ad;"/>
												<UML:TaggedValue tag="style" value="BackColor=-1;BorderColor=-1;BorderWidth=-1;FontColor=-1;VSwimLanes=0;HSwimLanes=0;BorderStyle=0;"/>
											</UML:ModelElement.taggedValue>
											<UML:Classifier.feature>
												<UML:Attribute name="CODE_EXISTANCE" changeable="frozen" visibility="public" ownerScope="instance" targetScope="instance">
													<UML:Attribute.initialValue>
														<UML:Expression body="1"/>
													</UML:Attribute.initialValue>
													<UML:StructuralFeature.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:StructuralFeature.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="description" value="Required parameter/alias does not exist."/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="length" value="0"/>
														<UML:TaggedValue tag="ordered" value="0"/>
														<UML:TaggedValue tag="precision" value="0"/>
														<UML:TaggedValue tag="scale" value="0"/>
														<UML:TaggedValue tag="collection" value="false"/>
														<UML:TaggedValue tag="position" value="0"/>
														<UML:TaggedValue tag="lowerBound" value="1"/>
														<UML:TaggedValue tag="upperBound" value="1"/>
														<UML:TaggedValue tag="ea_guid" value="{789D7420-324A-40a7-A24D-329181F3DD7E}"/>
														<UML:TaggedValue tag="styleex" value="volatile=0;"/>
													</UML:ModelElement.taggedValue>
												</UML:Attribute>
												<UML:Attribute name="CODE_EXCLUSION" changeable="frozen" visibility="public" ownerScope="instance" targetScope="instance">
													<UML:Attribute.initialValue>
														<UML:Expression body="2"/>
													</UML:Attribute.initialValue>
													<UML:StructuralFeature.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:StructuralFeature.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="description" value="Exclusion rule defined for parameter not met."/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="length" value="0"/>
														<UML:TaggedValue tag="ordered" value="0"/>
														<UML:TaggedValue tag="precision" value="0"/>
														<UML:TaggedValue tag="scale" value="0"/>
														<UML:TaggedValue tag="collection" value="false"/>
														<UML:TaggedValue tag="position" value="1"/>
														<UML:TaggedValue tag="lowerBound" value="1"/>
														<UML:TaggedValue tag="upperBound" value="1"/>
														<UML:TaggedValue tag="ea_guid" value="{599F1D6D-F553-4e22-94CE-CADDE6D393C7}"/>
														<UML:TaggedValue tag="styleex" value="volatile=0;"/>
													</UML:ModelElement.taggedValue>
												</UML:Attribute>
												<UML:Attribute name="CODE_DEPENDENCY" changeable="frozen" visibility="public" ownerScope="instance" targetScope="instance">
													<UML:Attribute.initialValue>
														<UML:Expression body="3"/>
													</UML:Attribute.initialValue>
													<UML:StructuralFeature.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:StructuralFeature.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="description" value="Dependency rule defined for parameter not met."/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="length" value="0"/>
														<UML:TaggedValue tag="ordered" value="0"/>
														<UML:TaggedValue tag="precision" value="0"/>
														<UML:TaggedValue tag="scale" value="0"/>
														<UML:TaggedValue tag="collection" value="false"/>
														<UML:TaggedValue tag="position" value="2"/>
														<UML:TaggedValue tag="lowerBound" value="1"/>
														<UML:TaggedValue tag="upperBound" value="1"/>
														<UML:TaggedValue tag="ea_guid" value="{DFEB09B3-C95A-414e-ABDA-73ED66C4DCC2}"/>
														<UML:TaggedValue tag="styleex" value="volatile=0;"/>
													</UML:ModelElement.taggedValue>
												</UML:Attribute>
												<UML:Attribute name="CODE_TYPE" changeable="frozen" visibility="public" ownerScope="instance" targetScope="instance">
													<UML:Attribute.initialValue>
														<UML:Expression body="4"/>
													</UML:Attribute.initialValue>
													<UML:StructuralFeature.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:StructuralFeature.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="description" value="Type rule defined for parameter not met."/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="length" value="0"/>
														<UML:TaggedValue tag="ordered" value="0"/>
														<UML:TaggedValue tag="precision" value="0"/>
														<UML:TaggedValue tag="scale" value="0"/>
														<UML:TaggedValue tag="collection" value="false"/>
														<UML:TaggedValue tag="position" value="3"/>
														<UML:TaggedValue tag="lowerBound" value="1"/>
														<UML:TaggedValue tag="upperBound" value="1"/>
														<UML:TaggedValue tag="ea_guid" value="{D6FC51B1-396D-43b4-865B-B5C2267BB6E1}"/>
														<UML:TaggedValue tag="styleex" value="volatile=0;"/>
													</UML:ModelElement.taggedValue>
												</UML:Attribute>
												<UML:Attribute name="paramName" changeable="none" visibility="public" ownerScope="instance" targetScope="instance">
													<UML:Attribute.initialValue>
														<UML:Expression/>
													</UML:Attribute.initialValue>
													<UML:StructuralFeature.type>
														<UML:Classifier xmi.idref="eaxmiid0"/>
													</UML:StructuralFeature.type>
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="description" value="Parameter this exception is about. Shortcut name of the parameter this exception deals with. 
@see ezcConsoleParameter::registerParam() 
@var string"/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="length" value="0"/>
														<UML:TaggedValue tag="ordered" value="0"/>
														<UML:TaggedValue tag="precision" value="0"/>
														<UML:TaggedValue tag="scale" value="0"/>
														<UML:TaggedValue tag="collection" value="false"/>
														<UML:TaggedValue tag="position" value="4"/>
														<UML:TaggedValue tag="lowerBound" value="1"/>
														<UML:TaggedValue tag="upperBound" value="1"/>
														<UML:TaggedValue tag="ea_guid" value="{4E581A47-1F48-4a22-9472-D45D0EFA25C5}"/>
														<UML:TaggedValue tag="styleex" value="volatile=0;"/>
													</UML:ModelElement.taggedValue>
												</UML:Attribute>
												<UML:Operation name="__construct" visibility="public" ownerScope="instance" isQuery="false" concurrency="sequential">
													<UML:ModelElement.taggedValue>
														<UML:TaggedValue tag="documentation" value="Constructor The constructor additionally needs a parameter name, which is the shortcut name of the affected parameter. For error codes, see class constants! 
@param string string $message   Error message.
@param string string $paramName Name of affected parameter
@param int $code                Error code."/>
														<UML:TaggedValue tag="type" value="var"/>
														<UML:TaggedValue tag="const" value="false"/>
														<UML:TaggedValue tag="synchronised" value="0"/>
														<UML:TaggedValue tag="concurrency" value="Sequential"/>
														<UML:TaggedValue tag="position" value="0"/>
														<UML:TaggedValue tag="returnarray" value="0"/>
														<UML:TaggedValue tag="pure" value="0"/>
														<UML:TaggedValue tag="ea_guid" value="{DD73908D-0535-44c5-B522-C7B2D935E944}"/>
													</UML:ModelElement.taggedValue>
													<UML:BehavioralFeature.parameter>
														<UML:Parameter kind="return" visibility="public">
															<UML:Parameter.type>
																<UML:Classifier xmi.idref="eaxmiid0"/>
															</UML:Parameter.type>
															<UML:ModelElement.taggedValue>
																<UML:TaggedValue tag="pos" value="0"/>
																<UML:TaggedValue tag="type" value="var"/>
																<UML:TaggedValue tag="const" value="0"/>
																<UML:TaggedValue tag="ea_guid" value="{RETURNID-0535-44c5-B522-C7B2D935E944}"/>
															</UML:ModelElement.taggedValue>
															<UML:Parameter.defaultValue>
																<UML:Expression/>
															</UML:Parameter.defaultValue>
														</UML:Parameter>
														<UML:Parameter name="message" kind="in" visibility="public">
															<UML:Parameter.type>
																<UML:Classifier xmi.idref="eaxmiid0"/>
															</UML:Parameter.type>
															<UML:ModelElement.taggedValue>
																<UML:TaggedValue tag="pos" value="0"/>
																<UML:TaggedValue tag="type" value="var"/>
																<UML:TaggedValue tag="const" value="0"/>
																<UML:TaggedValue tag="ea_guid" value="{50BCB8F2-12C3-430e-8B7C-7D9FB7A88687}"/>
															</UML:ModelElement.taggedValue>
															<UML:Parameter.defaultValue>
																<UML:Expression/>
															</UML:Parameter.defaultValue>
														</UML:Parameter>
														<UML:Parameter name="paramName" kind="in" visibility="public">
															<UML:Parameter.type>
																<UML:Classifier xmi.idref="eaxmiid0"/>
															</UML:Parameter.type>
															<UML:ModelElement.taggedValue>
																<UML:TaggedValue tag="pos" value="1"/>
																<UML:TaggedValue tag="type" value="var"/>
																<UML:TaggedValue tag="const" value="0"/>
																<UML:TaggedValue tag="ea_guid" value="{9531843D-EB54-4eac-83F8-99156A608015}"/>
															</UML:ModelElement.taggedValue>
															<UML:Parameter.defaultValue>
																<UML:Expression/>
															</UML:Parameter.defaultValue>
														</UML:Parameter>
														<UML:Parameter name="code" kind="in" visibility="public">
															<UML:Parameter.type>
																<UML:Classifier xmi.idref="eaxmiid0"/>
															</UML:Parameter.type>
															<UML:ModelElement.taggedValue>
																<UML:TaggedValue tag="pos" value="2"/>
																<UML:TaggedValue tag="type" value="var"/>
																<UML:TaggedValue tag="const" value="0"/>
																<UML:TaggedValue tag="ea_guid" value="{30E6409F-F5EE-4156-8ACA-CBA8669F75B1}"/>
															</UML:ModelElement.taggedValue>
															<UML:Parameter.defaultValue>
																<UML:Expression/>
															</UML:Parameter.defaultValue>
														</UML:Parameter>
													</UML:BehavioralFeature.parameter>
												</UML:Operation>
											</UML:Classifier.feature>
										</UML:Class>
										<UML:Generalization subtype="EAID_C6C700C8_814F_49fc_9B9C_1123BB0B4815" supertype="EAID_94807F39_6924_4b6f_BABD_B861BF17BDEE" xmi.id="EAID_67DABE02_3EDE_4e4d_817C_E05BBF11BD21" visibility="public">
											<UML:ModelElement.taggedValue>
												<UML:TaggedValue tag="style" value="3"/>
												<UML:TaggedValue tag="ea_type" value="Generalization"/>
												<UML:TaggedValue tag="direction" value="Source -&gt; Destination"/>
												<UML:TaggedValue tag="linemode" value="3"/>
												<UML:TaggedValue tag="linecolor" value="-1"/>
												<UML:TaggedValue tag="linewidth" value="0"/>
												<UML:TaggedValue tag="seqno" value="0"/>
												<UML:TaggedValue tag="headStyle" value="0"/>
												<UML:TaggedValue tag="lineStyle" value="0"/>
												<UML:TaggedValue tag="src_visibility" value="Public"/>
												<UML:TaggedValue tag="src_aggregation" value="0"/>
												<UML:TaggedValue tag="src_isOrdered" value="false"/>
												<UML:TaggedValue tag="src_isNavigable" value="false"/>
												<UML:TaggedValue tag="src_containment" value="Unspecified"/>
												<UML:TaggedValue tag="dst_visibility" value="Public"/>
												<UML:TaggedValue tag="dst_aggregation" value="0"/>
												<UML:TaggedValue tag="dst_isOrdered" value="false"/>
												<UML:TaggedValue tag="dst_isNavigable" value="true"/>
												<UML:TaggedValue tag="dst_containment" value="Unspecified"/>
												<UML:TaggedValue tag="$ea_xref_property" value="$XREFPROP=$XID={4CD1C944-C639-4ffd-B050-6D6267E6B354}$XID;$NAM=CustomProperties$NAM;$TYP=connector property$TYP;$VIS=Public$VIS;$DES=@PROP=@NAME=isSubstitutable@ENDNAME;@TYPE=boolean@ENDTYPE;@VALU=@ENDVALU;@PRMT=@ENDPRMT;@ENDPROP;$DES;$CLT={67DABE02-3EDE-4e4d-817C-E05BBF11BD21}$CLT;$SUP=&lt;none&gt;$SUP;$ENDXREF;"/>
												<UML:TaggedValue tag="virtualInheritance" value="0"/>
											</UML:ModelElement.taggedValue>
										</UML:Generalization>
									</UML:Namespace.ownedElement>
								</UML:Package>
							</UML:Namespace.ownedElement>
						</UML:Package>
					</UML:Namespace.ownedElement>
				</UML:Package>
				<UML:Stereotype xmi.id="EAID_1D64E7C3_A572_4044_9F13_82E10C926C05" name="ezcomponent" isRoot="false" isLeaf="false" isAbstract="false">
					<UML:Stereotype.baseClass>Package</UML:Stereotype.baseClass>
				</UML:Stereotype>
				<UML:DataType xmi.id="eaxmiid0" name="var" visibility="private" isRoot="false" isLeaf="false" isAbstract="false"/>
			</UML:Namespace.ownedElement>
		</UML:Model>
		<UML:Diagram name="Console output" xmi.id="EAID_BECDD893_B0AC_4cb4_B9FC_E9BA9A6AB33D" diagramType="ClassDiagram" owner="EAPK_9300B830_36D9_4e00_AE7D_EA3DA9B092B9" toolName="Enterprise Architect 2.5">
			<UML:ModelElement.taggedValue>
				<UML:TaggedValue tag="version" value="0.1"/>
				<UML:TaggedValue tag="author" value="Tobias Schlitt"/>
				<UML:TaggedValue tag="created_date" value="2005-08-12 09:19:34"/>
				<UML:TaggedValue tag="modified_date" value="2005-08-19 11:59:58"/>
				<UML:TaggedValue tag="package" value="EAPK_9300B830_36D9_4e00_AE7D_EA3DA9B092B9"/>
				<UML:TaggedValue tag="type" value="Logical"/>
				<UML:TaggedValue tag="swimlanes" value="locked=false;orientation=0;width=0;inbar=false;names=false;color=0;bold=false;fcol=0;;cls=0;"/>
				<UML:TaggedValue tag="EAStyle" value="ShowPrivate=1;ShowProtected=1;ShowPublic=1;HideRelationships=0;Locked=0;Border=1;HighlightForeign=1;PackageContents=1;SequenceNotes=0;ScalePrintImage=0;PPgs.cx=1;PPgs.cy=1;DocSize.cx=1118;DocSize.cy=783;ShowDetails=0;Orientation=L;Zoom=100;ShowTags=0;OpParams=3;ShowIcons=1;CollabNums=0;HideProps=0;ShowReqs=0;ShowCons=0;PaperSize=9;HideParents=0;UseAlias=0;HideAtts=0;HideOps=0;HideStereo=0;HideElemStereo=0;ShowTests=0;ShowMaint=0;"/>
				<UML:TaggedValue tag="styleex" value="ExcludeRTF=0;DocAll=0;HideQuals=0;AttPkg=1;ShowTests=0;ShowMaint=0;Layout=;SuppressFOC=0;TDurLow=0;TDurHigh=100;TDurUnit=;TDurHide=0;"/>
			</UML:ModelElement.taggedValue>
			<UML:Diagram.element>
				<UML:DiagramElement geometry="Left=20;Top=139;Right=221;Bottom=266;" subject="EAID_4F677B5E_DCEC_4413_9FB2_A9753E5E62E8" seqno="1" style="DUID=7369F95F;LBL=;"/>
				<UML:DiagramElement geometry="Left=60;Top=460;Right=206;Bottom=540;" subject="EAID_4B7CE667_749A_4dde_BE45_7CBFB5519DF5" seqno="2" style="DUID=9861FA2C;LBL=;"/>
				<UML:DiagramElement geometry="Left=10;Top=20;Right=175;Bottom=95;" subject="EAID_55B8BBC5_46DA_4e67_9A1D_1120F11D48E7" seqno="3" style="DUID=4E2A8D6E;"/>
				<UML:DiagramElement geometry="Left=669;Top=80;Right=1066;Bottom=324;" subject="EAID_A9F2232F_845A_4da2_A329_950ED3CDB676" seqno="4" style="DUID=1AFCEFE0;LBL=;"/>
				<UML:DiagramElement geometry="Left=341;Top=419;Right=620;Bottom=585;" subject="EAID_65A37092_56CE_4e5a_8C30_366469BD8468" seqno="5" style="DUID=D116714F;LBL=;"/>
				<UML:DiagramElement geometry="Left=260;Top=126;Right=634;Bottom=279;" subject="EAID_EE63FC0D_D590_4d0f_9F83_338683F8E000" seqno="6" style="DUID=74DC55C1;LBL=;"/>
				<UML:DiagramElement geometry="SX=0;SY=0;EX=0;EY=0;EDGE=1;$LLB=;LLT=;LMT=;LMB=;LRT=;LRB=;Path=;" subject="EAID_8273AECA_7516_4847_9960_34C4FF71F006" style="Mode=3;EOID=7369F95F;SOID=D116714F;Hidden=0;"/>
				<UML:DiagramElement geometry="SX=0;SY=0;EX=0;EY=0;EDGE=1;$LLB=;LLT=;LMT=;LMB=;LRT=;LRB=;Path=;" subject="EAID_8BBADE67_3C37_4c4a_8CD5_2911FACC538E" style="Mode=3;EOID=1AFCEFE0;SOID=D116714F;Hidden=0;"/>
				<UML:DiagramElement geometry="SX=0;SY=0;EX=0;EY=0;EDGE=1;$LLB=;LLT=;LMT=;LMB=;LRT=;LRB=;Path=;" subject="EAID_D761BD7E_7981_43a2_823C_48DC2173761C" style="Mode=2;EOID=74DC55C1;SOID=D116714F;Hidden=0;"/>
				<UML:DiagramElement geometry="SX=0;SY=0;EX=0;EY=0;EDGE=4;$LLB=;LLT=;LMT=;LMB=CX=51:CY=15:OX=0:OY=0:HDN=0:BLD=0:ITA=0:UND=0:CLR=-1:ALN=0:DIR=0:ROT=0;LRT=;LRB=;Path=;" subject="EAID_E53B0D49_9955_449f_974D_2D23DBDB2610" style="Mode=2;EOID=9861FA2C;SOID=D116714F;Hidden=0;"/>
			</UML:Diagram.element>
		</UML:Diagram>
		<UML:Diagram name="Console parameters" xmi.id="EAID_70ED343C_42E2_4b49_8EE5_C19FBBA1BED9" diagramType="ClassDiagram" owner="EAPK_9300B830_36D9_4e00_AE7D_EA3DA9B092B9" toolName="Enterprise Architect 2.5">
			<UML:ModelElement.taggedValue>
				<UML:TaggedValue tag="version" value="0.1"/>
				<UML:TaggedValue tag="author" value="Tobias Schlitt"/>
				<UML:TaggedValue tag="created_date" value="2005-08-19 11:59:03"/>
				<UML:TaggedValue tag="modified_date" value="2005-08-19 12:00:03"/>
				<UML:TaggedValue tag="package" value="EAPK_9300B830_36D9_4e00_AE7D_EA3DA9B092B9"/>
				<UML:TaggedValue tag="type" value="Logical"/>
				<UML:TaggedValue tag="swimlanes" value="locked=false;orientation=0;width=0;inbar=false;names=false;color=0;bold=false;fcol=0;;cls=0;"/>
				<UML:TaggedValue tag="EAStyle" value="ShowPrivate=1;ShowProtected=1;ShowPublic=1;HideRelationships=0;Locked=0;Border=1;HighlightForeign=1;PackageContents=1;SequenceNotes=0;ScalePrintImage=0;PPgs.cx=0;PPgs.cy=0;DocSize.cx=780;DocSize.cy=1118;ShowDetails=0;Orientation=P;Zoom=100;ShowTags=0;OpParams=3;ShowIcons=1;CollabNums=0;HideProps=0;ShowReqs=0;ShowCons=0;PaperSize=9;HideParents=0;UseAlias=0;HideAtts=0;HideOps=0;HideStereo=0;HideElemStereo=0;ShowTests=0;ShowMaint=0;"/>
				<UML:TaggedValue tag="styleex" value="ExcludeRTF=0;DocAll=0;HideQuals=0;AttPkg=1;ShowTests=0;ShowMaint=0;Layout=;SuppressFOC=0;TDurLow=0;TDurHigh=100;TDurUnit=;TDurHide=0;"/>
			</UML:ModelElement.taggedValue>
			<UML:Diagram.element>
				<UML:DiagramElement geometry="Left=600;Top=20;Right=765;Bottom=95;" subject="EAID_7FBF19CD_D452_4a01_BF36_6591CF96D1D2" seqno="1" style="DUID=56EC20EC;"/>
				<UML:DiagramElement geometry="Left=34;Top=27;Right=277;Bottom=173;" subject="EAID_C6C700C8_814F_49fc_9B9C_1123BB0B4815" seqno="2" style="DUID=C9E410BA;LBL=;"/>
				<UML:DiagramElement geometry="Left=30;Top=280;Right=240;Bottom=533;" subject="EAID_A51EEA3E_1E35_4947_AFF6_4F0ED6B44ADC" seqno="3" style="DUID=2ED4E9E2;LBL=;"/>
				<UML:DiagramElement geometry="SX=0;SY=0;EX=0;EY=0;EDGE=1;$LLB=;LLT=;LMT=;LMB=CX=51:CY=15:OX=0:OY=0:HDN=0:BLD=0:ITA=0:UND=0:CLR=-1:ALN=0:DIR=0:ROT=0;LRT=;LRB=;Path=;" subject="EAID_F959A77C_CEDF_4555_A103_9EADB2730D13" style="Mode=2;EOID=C9E410BA;SOID=2ED4E9E2;Hidden=0;"/>
			</UML:Diagram.element>
		</UML:Diagram>
	</XMI.content>
	<XMI.difference/>
	<XMI.extensions xmi.extender="Enterprise Architect 2.5">
		<EAStub xmi.id="EAID_94807F39_6924_4b6f_BABD_B861BF17BDEE" name="Exception" UMLType="Class"/>
	</XMI.extensions>
</XMI>
PK��Z�>'�J
�J
*data/ConsoleTools/design/class_diagram.pngnu�[����PNG


IHDR\��R)bKGD������� IDATx���{t��/��pPk
l�EAvU�UQ[�x*�HD+:��]�֭�V;��:�U�P@�B1(�8�3

iZ-D��(��JՊ `@���JƐp�(׵V���������ߝ�Ieeee�ִ�	46
.6��`#
.6��`#
.6��`#
.6��`#
.6Ҽ�	|^̞=;��~{���f����N
.��e˖eʔ)�N�ަL��lD����_�>k&M���C�:
hTt�؈
d��ٹ�����&�����@Y�lY�L�R�4j�2e��O�:\40Ahl&M���C�:
h�t�؈���(����[o�U��5�\>�/ر\P��ٳs���{��iӦMZ�l����+�o��B���4i�$M�4���⋹ꪫr�a�e�]wM���ӡC�q�1bD^{��g��u�]�޽{��]_�˥�o��Π1=;�Y4/t4˗/�����裏֚{������L߾}�_�*�۷/@��]k׮͕W^�1c�dÆ
5����̛7/����-�ܒ�.�,�F�J�-��\p�v[��jL�|�_���p@�����QG�G}4�:uʭ�ޚ^x!�W��G}��^z)?��Ү]�<��#�ׯ_֯__�?3֮]��O>9w�yg�5k�o��y�Dz|��[�.�nf̘��Ç���2��zk��odݺu�N�`*++���!(� Ir�9�dɒ%��W��^x!W^yez��֭[���(p@F����w�m��2k֬�3��if\~��5kV�v�g�}6��sON:�|�_H����w�w9���3a„<���ԩSf̘�����N`����@�.]�.� ]�tI˖-S\\��C�f�…u�7i�d�?+++ˠA��/|!EEE�ڵk��暬Z��F��O?�G}4_��2u����n�̻gϞ��曓$w�uW���^z)g�}v:w��t��9Ç��ŋ7{]I��>_���Һu�t��!���˼y��<o��Ź袋��~��e˖�m��r�a���o��_�9��ms��^|�Ō;6m۶͌3r衇nv��;,���oӢE��~��Y�dI��M=�M�o�xS1&LH�=ҢE�|�_��S^^�U{m�\>�m}.]�4�vXv�e�|�߬3�1c�d���O�-������K��[�.7�pC��k��{��0aB���]�6?��O�|%;vL��ͳ����FfΜYgnrl[>��5��[`��4iR���������~��r�)��j͵j�*>�`���[c|K_HoݺuV�^]}|�=�������׊=��C���Og�]vI�\x�;vlF���n�i���G��}���/����z����m
�5k��:g�]v�C=��?���;wn��铵k�֘/**�̙3s�QGU������?��?d�ʕu��>�d�ܹ����]r���]}���O~����*?��O�̹.]tQ~��_��k����-浩�ͽw6��������V\˖-��SN��^�3�m�Jçy�_�����O$I�ɓ'ט������u�c�=�_��:uj�='O����W�\�2}������:�oҤI�M�V}��t��峐���t���{�80+W���_�ŋg͚5y�gr�y祢�"C�ɛo�Y����Z?�F��������ׯ��j.���|��ǹ袋�ꫯ���"O=�T��o�<��s��[��gϞ�$��7��U�вe�s�15�-�z뭜q�Y�fMN=�Ԕ��磏>JyyyN=��|��9�����[oչ�瞛���={v>���̜93]�vMEEE�����F��_��+W�����ŋSQQ�իW��'�L�=��k���o�n�}Ҷ<������ߪ�[�����Q��6V�~���/�_{�9��#3w�ܬ]�6/��B��뗏>�(Æ
�_���K}}��x��,X� +V�ȿ�˿Ԛ��/~�	&����o��SN9%���9��3��c�e���Y�re�-[��N:)Ir���X��o����t�A�={vV�^��k�f�ܹ9ꨣRYYY��fK����`�)��~��_f����ks�m�e���K�V�r�G殻�ʥ�^�+V����fי;wn����$����2�zn̘1�裏2x���k��g��h�"�{l~��_%I�����K�.M�t��}���;�ȪU�r�q�e�ԩ9蠃RTT��:(S�N�q������=zt���+_�ԩSs��G�M�6��W����+I���F���$�ư�~��E�iݺu������$�o~���'m��[�xq��G������$��\��>�<0O<�D�8∴l�2=z�ȯ��w�qY�bEƌ��riҤ�>��>�#F�gϞi߾}:w�\k~���>|xv�u����EK�^~���s�I۶m��^{��?�y�d��5֘8qb���{���G�֭[�e˖9�#r�&I�ϟ�����`�)��~���&I�����9�y�%I�O���5V�X�3�<3�ׯ�I'����G5�:"\|�ŵ�-))Ieee^}���5k�$Iڶm[�+�iƌI����:M����M���~���G��K.���ؗ���$�|Pc|���J����7'N���U�t�A����o���r��my~U���[\��ڷo�$Y�re��4F��֭[���=������>�~���]��c��qܭ[����1��&���^{�TVV�W�^������$��y���,[O���p��$Iqqq�����J�?]�r���^�~��_��Wi֬Y���_~9�tHؒ����|��$6V5^����o�Zc��K�dÆ
5Ư���$�3�<�aÆ�K�.�ҥK�9�L�:5�5�Oږ�צM�$����~�OWS_�*:8��Ó$/���˥��r�?��i�sU�¦t�ر�q��ͫ_טkѢ�f�J�%K����ȑ#s�'V���umN}?��Sp��mܭ��q��o����Ҵk�.���oҡC�Z1�V�J��_ԯ*v�ϗ�ׯ__㸪�`S]ڵk�$����oժ�V�=|��L�:�F��������wߝ�N;-=z�Ȓ%K�[n��-ϯ�BU��֚?~�d�����y����^�xUQN�{�1��Ϲ�0fS6WD�q�������ڵk�v�~�����3cƌ��/��5���l=;XU׆������?�u�/��K/�4M�4�}�ݗ=zlv���r����$y��Ƿ*���s:v�aÆU�U}�}Ŋu�Sխ�*�O�[�V��?d�ҥ?~|�=���†W^y%�]vY��-��NH�������L��$����:��ꄰv��z�M�g���n���r�����&M�g��%K���ȑ#3nܸ��7�ɟ���mZ�>�`�)����I��w���yk׮�g��իW��oL�~�6۵k�$Iyy�V�}�g$I��_���K��׿�|�&M���s޼yu����ֈ�^�t�s�9'�ƍˢE����'IfΜ� �m��;��ҬY��3f�����?���ǧiӦ9��sk�5m����_�zu��^y啭Ϋ.����;wn����a��W�ރ����0I2f̘��⋹馛r��_�~5:�lذ��ko�g�z
.v��O>9�߾x�~��Z󥥥iҤI���[c�������3`���1b�{w�qI�q��՚+//O�&M��>�T�}��_�	'����z+�����U^���z�iڴi�����N:)I����֗�7lؐ[o�5ɦ�5��>��&M��^�5׻w�Zc�3�my~��_����f�ڵ9��SVV��=�͛��}����"��w��T�СCu��Ə��u�
d6�e����5����[nI��v�i;,��ڑ�m���/'I�:�Zs��v[��5k�Ԙ����g�z
.v��/�8��k�̙��O>9����ڵk��O��/�Yg���͛gԨQ��L�6-���/�/})��{o��u��w���-[f„	���k��og���y�'��Y>��9cǎ���G}4={��/~�,Y�$�ׯϚ5kR^^����')))�;3#F��v��|'�ڵ˓O>�d�…����…3`��̜93mڴ�w���O}�<��$ɠA�2cƌ|��Y�~}���3dȐ$�S��sۖ�����o��޽{�s������w������;�d���>|x�>����ӧO��sL��.��ٳ�v�ڼ��+��+r�wn2��
S�N���SQQQ+�G����K/���"����)���ٳg���ku�h�\�kG��U�.]����������^x!����B���w߭qަ�W}?��kRYYYY�$>&M���C���a7>��Gy$��W��y��w�S}\RR�?��[��{�?>�w^��u�Qy�'ҪU�����0`@/^��=�5k�뮻.7�xc���~8�
�G}Tk�e˖�<yr���_c��xdS�}]�|�#�<2/��b��t��9s����{�� ���U��������q�����<7��=��w��[n�%-[��5_VV�c�=6k׮�57v��\p�u�}�q�e�̙5ƪb�����4^xa��׿ֈ�s�=3}����wX.����ֹ���ll�ȑ�<yr/^�x�F7�Mݯm�,$��};+.
�o߾y���s��f���J�-�뮻�N����k}Y��W^���{nf͚�����m��RTT�<0?����O�*�H��={f��;vlN>���E�iժU�u�/�0�=�\��I��o~3��3lذ�y��)..η���<��s��辭ڷo�g�y&������#�[�N��ͳ�~���+��s�=W���3��>�*EEE��O��^z)�\sMJJJҾ}�4k�,��[�8∌1"�/��~��:�-���̙3'���K�RTT�#�8"�����?�yO�0!'�|rv�e�4o�<����Z1�
�̙3SRR��͛g�}�����,X��V�EC�-v�{p[�����{r�!��e˖i߾}�?������{n�馌92I2f̘�m�~m�g�::\l'�b<�e����=~_���p�Qp�i^��«��,t
��Qp�i^�>�N?��B�PÔ)S
�4z
.H�.]2hРB�P��M�e
.�1��c�9��i�@�@�4iR�Z�46�����)@��������:�&M���z��i@�����
4��)԰n�:�M�@c���@�/_������I��_=%%%�۷o�3k<-Z�(�.--�W\�+��"���;0+v��N`gU^^�$9蠃j��ٳ`95&W^yef͚����F��s�=�ѣG��Oeee�nݺ�C��y�pt�(�M\T��f͚��^�fMF������8�:uʀ2bĈ�Y�fg	@CRp����T��{�I��cǦ��$�'ON��q�))))d�l„	�|��q��cg�yf�/_�	&03���N��x��s�wfΜ9Y�jU��g�|���N߾}kĭ\�2cǎ�O<�w�}7��{�����.H۶m�㪊D&O���n�-���O˖-s�����.K�֭�$6l�رc3}���iѢE�v�SO=5������'_���U�;vl���t��-cƌ��Iu�o�7��ʕ+3y��~���c�=�c��s�ꂙ��:+�ڵ�߃�QRp�U}���s�����;>�`���3|��t��-�&Mj�<�{|}��y�w��^~��\�������o~3I�jժ��?�c�,YR��[oeҤI�7o^Ə�6m��X��/̊+�$k׮̓>�
6��K��=���G��[�.,Ȃ��f�С[���n�ʕ+k>l����?�իW�w�޵�z��y��e���9����S�B'�3*//O���ٳ��v�=��w�I�=2u��<��S�ַ��$?~|uܽ�ޛ%K��s��?~|�y晌7.�:u��/���ᄏ��{�w�N��9s���s�M�<����S�NM��q�y�g��SO�k�I����Ijv�(++�չb�}�͜9sr�M7m�����s��I�t�޽ֺUcU1|�)�(����:���6{��$����t��%mڴ�u�]������׿���*�����/})-Z���k��6I��O�Z�ꫯN�.]Ҳe��n|�A�|UG��'���4��_3p���eڴi[���a�RTT�`�]�E�%�[A���g�1|�)�؁JJJRRRR]X���8%%%y�ǒ$?���c���'I8��ƽ��I��>����Zc�O�ڵk����'I6l�P=v�e��e˖�;wn~�ӟf��?~|֮]��W8���^w]�{�$I�v�j�U�U��٧�`'ԤI�Ou�'(6֢E���s�'��G��_��>8k׮͝wޙ�}��ܪ�7�ݢ����uEEE��Os�U�6mZ��ګ�>�}��Pp����e�رI��={���,w�qG��W�^)++��iH_���$/���f�:u�$y���k�Wo��۷O�~�2nܸ�{�9�����nۦ��
>���걺�mk��.;vL��X���\�XU�}
.v����$+���xG8�裓$��zk�z뭬]�6?��SRR�o}�[�q}��I��5*������3����G?J�{���SOMIIIx�^�:���u떤��˖-��:tH�<��CY�fM�,Y��o�y�����8�$�ҥKk�[5V�g_�B'��i�sNf̘�����SN�1w���W�>����Odٲe9��sk�u�ҥ���8��3jԨ�|�͵�"z��U��C�y�2`������}���ԩS�,?��ϒ$�{�����]��G}tf͚����y&������I��l��^x���бc�L�0!'�xbڵk�-Z�{���[ҷo��v��e„	9��ӳ�{�Y�f�c�=r�g���N�����r����LQQQ���ҵk�><7�xcu�UW]�Ν;�Y�f����욗_~y�]w�5EEE�ݻwF����]��'�tRڴi���~�ֺO?�tڶm�N8���ƩIeeee���<�4iR�������Ͼ1c�dܸqy衇ҹs�$�o�������/�y�W�a�}[��l���>;{�g&N�X=6q��gذa���y��n%%%
�nYYY���3hݺun��\z�9묳�$ӦM��ߞV�Z8;�'P�vX.����z�I�K.�$�z�*pVlo
.)�(�!C�dȐ!�N�Դ�	46
.6��~d� IDAT`#����ݔ)S
�@
~/��)�h`��~z�S�I�@2dH�R�4�m����̞=;��~{��ؤ���B��V�B'�y�lٲL�2��i�2e���`t�h`��<��L�4)C�-tШ�p�i^��|Y�hQ8�:�JKK3w��$ɑG��O?}G�[M��͕W^�Y�f������s�=�ѣG��Oeee�nݺ�C)@��yM���fͪs|͚59rd����t��)Ȉ#�f͚�%l���+))IIII��hP&L����s�gT��y�Y�|y&L�P���n
.vR��N����|�k_�QG�aÆe���u��^�:w�qG��뗣�:*��7s�w����:��|r��+Wf���9��ó�{T���)))��ɓ�r���Z�;�?�0�w^y�|�Y�n]^z�\{�b+**r�E�{����gݺuy��73~��\v�eٰa�f�z��dzz����ݻ�\�޽�z��L�>}�]l
.vB'N�믿�N�:e���y�g2v��(��w�}Y�paz��I�&��g�Miii9�̛7/ӦMK����U�SVVV}<gΜ$I���k�]5V�E�B'��)))٪�O0loO>�d���˗��$I�^�2bĈ��?�S��3f$IF��N�:%I��w��p�
�߿y�����{-Z�(I���{ך�g�}j�@c��`'�t��$ɡ�Zc�W�^�b�-[�$�ׯ_�k���˛���K��k׮�\�XU4
.v��;WTu�hȎ�RYYY�I�&[��تU�6;_�fӦMk�U�յ/�����^{�W^y%�ӟ��/�z�O�S�����,]�4?�p����Wǎ��[oeŊ�رc��+VT�@cR�χ�w�	'$I~����<�ׯς���V�q��$�����K/��?λロ����)))�E]T[թbٲe�cp@�d�ҥ�֮����B����СC��c���^����7;|��̜93���ϰa�j̵j�*�_~y�q���{�e��)..��?���>:�f�Jyyyz��U����$ɱ��}.�.
���,eee;t�֭[g�ر�ׯ_v�m�4o�<ݺu�M7ݔ$)**��m۶mƏ�!C����8͚5K���ӧO��}��5�S\u�U�ܹs�5k����$�I'��6m��駟����O?��m�Vw���B��������믯1��o&Iv�}���۷�W\�+��b�k�x�9��k���.2dHƍ�7�x#�;wN����y���s��M�6��r`���`'�|%%%%y��dÆ
y��Ws�7&I=�����g��=��3'N��8qb���3lذ�l:\4R%%%
�nYYY���x 7�|sn����:t�\�]�lݺun��\z�9묳�$ӦM��ߞV�Zm׽`{Pp����ӥK�<��y��WSQQ�/~�9ꨣr�y�e�=���{v�a���s뭷&I.�����k��ۃ��F������nڴi��!C�4�u)Ğ�-�:��F��F\l�y���kҤI�S�I�@9�cRZZZ�4�mд�	46:\4�ٳgg�С�N`�*++�4Z
.�/4�ͤI���4-t�����4/t�x%%%I����g�7�-�P�\iii�Ν�$9��#s������I)�������̚5����{.�G���ߟ���<8ݺu�!�R�Lؙ4-t�xeee���ŬY��_�fMF������8�:uʀ2bĈ�Y�fg	��F�@���������i4:&L����s�gT��y�Y�|y&L�P���4/t�xUU].6lؐ�c�f���y��7ӢE�t��5��zj���_}���%��ի3nܸ̘1#��_�����_�z�;���c�V�\�ɓ'����{�Q��{���$�'O�Yg��v��5�
`�����=:��{o��u�`��,X� ~�a�Z�����\t�EY�pau�o����ǧ��<�G�NӦM7���?�իW�w�޵�z��y��e���9��>��@]6��W�4�N��$��;��3�䩧��5�\�$�����w�}�e�…�ٳg&M��g�}6���9�C2o޼L�6-�tبz]u<gΜ$I���k�Z5V
A�����d��?Y���ڴi�U�Ve�ĉY�dI��铁f��7cƌ$ɨQ�ҩS�$ɾ��n�!����#�<����o2�E�%I��{�Zs��O�h:\��.�,-[��ܹs�ӟ�4����v��m�[�lY��_�~)))���*�x��7��{w$i׮]�����h:\�`w���l�#;Zl��ȎG��3g�7��M��?��;��}�ݗK.�$��vZ��*++7�ߪU�6;ߤI�$IӦ���`�XU4$Iڷo�~���_�~Y�pa��?�3��sOn���B���+..�ҥK�������޹t��1o��VV�X��;֘[�bEu4��
��Ω������<�Y�zu���t��-IҢE�z�w�qI�뮻./��R>����������\t�EձU�*�-[V=v�$I�.]Z+ת��h:\���>;�F���7ߜ�o���\�^��7|��̜93���ϰa�jĵj�*�_~y�q���{�e��)..��?���>:�f�Jyyy�u����<Ir��~�����������RVVV��믿>x`���RTT��]�f������׶mی?>C�Iqqq�5k���ۧO�>���kt��ꪫҹs�4k�,I��N:)mڴ��O?]+ק�~:m۶�	'�Ѐw���;��
<���~��m�ܭ�k߾}���\q���;��s�'��e�]2dȐ�7.o��F:w�$y�7�����/L�6m��l+.h��>���瞙8qb��ĉS\\�aÆ03v:\4R%%%
�n]�-�֭[�nȥ�^���:+I2mڴ�~��iժU����N���a���/�8��zk��K.I�^�
�;��g�EC2dH�R�4��4-t�����(��H�B'�yw��:��L�R���Sp�@�t�A�:
�Z�n�-Sp�@�9�s�1�N�
.ȤI�2t��B��I����N-
�����)�0iҤ<��C�N5
lРA�N��u��)��-hZ�.�n-Z�8�ι���̝;7Ir�G���Oߑ�@�(�`����+3k֬���՚{��2z����������ӭ[�r�!���i���a֬Yu��Y�&#G���S\\�N�:e��1bD֬Y���������JJJRRRR�4̄	�|��q��cg�yf�/_�	&03ش�N�oÆ
;vl�O��7�|3-Z�H׮]sꩧ���5bW�^�q��eƌ��_���w�=_���s�y票�(Ij�T�.++�ʕ+3y��~���c�=�c��sϔ��d���9묳Ү]�p���\�F��{キ�xݺuY�`A,X�?�0C�M�TTT䢋.�…�c�|�͌?>���=zt�6m��}��^�:�{��5׻w�̛7/ӧO�i����>�M���[S�NM��q�y�g��SO�k�I�����q��w_.\��={fҤIy��gSZZ�C9$���˴iӒ���E������9s�$I�w�^+����hLt��JJJ�j��E�[�6m�jժL�81K�,I�>}2p�8�F܌3�$�F�J�N��$��on�����?�<�H����}-Z�$�{�k���>5b�1Qp���{���<����A�@E��k�6������H�AM*�U��b�A��xCj�b`�`�bʉ��\D:��p�6�Z�P%Da�Y��a�{��g�Yk�������X��̳_8]u�U������K�f�ҥ�����\~�婪�J�֭�}�V�J�:t���X�b��Y�~}��C�M�j
=М�8��?���d��y���������?�y����+�2eJfΜ�+��2_��W�$�����g�ƍ�\/++K��hѢ�ZC������;f�С:th^{���3cƌL�4�8pQQQ��+W�'�HEE�?�s��Y�vm6lؐΝ;7Z۰aC����!�!���K�Pȣ�>����|�3�����$iժU���3�L��?>���z�nݚw�y'��{o
�BƎ[�m8�bժU�Z�޽�$+W�l�����͉.C�G��ĉs�w�;�h�֯_���K/�4?����ꫯfԨQ��Z�n�����xݩS��_�>ÇOEEE�x≜v�iy��|��F�&���˓$�
��o>6'\�XMMMjjj�3��[o�5���#�8"GqD�;�\z����]�k߾}�M�����TTT���<;v�g���z����]w]�w����lٲ%Ir�9�m۶Y�pa�.L���3x���`9��05t��:t�};v�5�\�k��f�}C�ɐ!C�ڵk����L�:5�W�N��ݓ$�W���/��1cƤm۶{�&`?q����ѣӵk�̚5�X�5kV***2jԨ&��s�@3U(�˾555�eߝiӦM&L����ۿ�%�\�$�?~�ᄡn��f�����)���q����;�L�\y��ׯ_�S���h��I�[UUU���J>�����؎���,u�C�ܹsK�?�`�\�g#F�(u`��O���RUUU��^0p��,Z�(��w_�c�Ԝ9sJ���p�Z�jU�Ν[�M̝;��'�
'\�g>Ahn���3r��R��f�	�1p�������7�H�޽w�6gΜ,]�4Iҿ��1�@F��b�����k��s�=����&k/��R&O��Gy$������s��ǧo߾%H
]�R���s��iӦ�r�-��RQQ�nݺe���曳iӦ�����+
)
����M�>=�֭�E]T�]|��Y�n]�O�^�d�{-K�]��o�)S�d���ٸqcz�왯}�k�җ�Ԩ���6���,��N>��O欳��W\������;jjjݿ}��z��ٙ4iR^}��y�9��s�UW�M�6�E�����̞=;��zj�t�R��ڵk
�BfϞ�K.�$:t�W�&ا\4c�ׯ��ѣ��ok+V�ȭ�ޚ�[���s�M�lܸ1_�����o�֮]����,[�,ӦMK۶m�*Ø1c�aÆ$��͛���8۶m���wzϓO>����TVV6Y���̲e���SO�+_��^e���E��s3f���o��N8!������?���??I2mڴb��?�7�|3ݻwϴi���/d�ԩ�֭[V�X��zh�3{챙7o^/^��/�<I���&i|JFMMM�z���I�>}�4ٯ���͑���P(4��U}ѢEI�믿>=z�H۶m3~����������6@�?>'�tRZ�j��}�s�馛�$?���:�
7ܐ=z��#��ȑ#�$��.�y�7��~Xc{={�l�͑��f쭷�J����{�}�W�N�|�s�kT?���7�;���;&I�m۶�{֯_�$�СC���ZC4G-K�pSSS���4���IRVV�����������[�l�i_�V��8OC_�M?���q��ON�h�>��O'IV�X�˾nݺ%I^~��F��늊�b�a���+�v����ܹs�dÆ
M�j
=��h�N;�$ɝwޙ�k�f����w��B����?��w�g$I&N��W_}5~�a^}���~��I�A�{;u�$y�DziӦ��曹�;�:c�ǪU���޽{'IV�\٤����͑��f��.K�Ν�ꫯ��_�r�9s�$I��/���7z�����#�W���_�������/�[o��=z���//�6g�s�=4hPF��O|�{��a�c���9��s�������˛�7�p�%VSS�����u��9ӧOϐ!CҡC��j�*}���w��|�K_*�u��!ӧOψ#ҥK�����K�.�����C�cǎ�ޫ��:\pA�:�q�����-�ܲ����t��=���ٲeK��s�I۶m�p��&�.L���3x��~&�oe�����p(����ȑ#��k��7>�`�N���{,ݻwO��^�:Æ
˘1c�o|��	�����.�/F���]�f֬Y�ڬY�RQQ�Q�F�0잁��6m�d„	�?~֬Y�5k�d����0aBZ�n]�x�K-K�C�)���q����;�L�\y��ׯ_�S���`����JUUU�c�iQ�͍�����N�R8ԕ���:��\�'̜9sJ�-J��q��~�hѢ�9��1v�������2p����f�����6�Ѣ���iY�~�x����{�ks���ҥK�$���ψ#d4Hb����k��s�=����&k/��R&O��Gy$������s��ǧo߾%H
��E�pxy��vXߴiSn��\p����H�n�2|���|��ٴi�N	���@�
�
�R�(��ӧgݺu�袋���/�8�֭����K��Ñ��f�m���o���N���s�Ee���zv6��}����e�:묌;v��$�����ߟ�C�f��9��s3eʔlٲe��Z�bEƍ���_�bn����	;ʒ$����={vN=��t�ҥ�ӵk�
�̞=;���{�-�=ֲ�ع���g���y���+V��[o�֭[s���վ�&MJmmm��շlْ�c���^+��Y�&ӦM����3y��h���ƌ�
6$I6ZI�# IDAToޜ���ٶm[Ə��<O>�d���RYY�d���2˖-�SO=��|�+{�~`O9���1cF�~��p�	�7o^������I�iӦ��z���ŋs�m��>s�̼��k9��S]]�_|1s��I߾}�lٲ̟?����{l�͛�ŋ���/O�<��I����b_MMM�z���I�>}�4ٯ����.�B���555Y�hQ���O�=�$�Ǐ��iŨQ�r�G���O'I&N��nݺ%��PƄ	2lذ,X� Æ
k��
7�P�:r��L�6-��.���I~?����={6����@3��[o%Iz��O�mb�]}ժUI��C��ŊMj�w\�uǎ�$۶m�e����'I:t��d������������u���ד���l�����/޳e˖����t�����w���76��jժ����o�kѢE���ڞ~/��0pЌ}�ӟ���dŊ9�v�WVV�������{i߾}��>��***�r��<��������L�Ν�v��lذ!�;wn��aÆb(M?�f��NK��y�Y�vm6oޜ�~��)
9���}�:uJ�<��cٴiS�|���q���g�yf�d���y��׳u�ּ��;���{S(2v��=޳ᤊU�Vk�{�N��\��IC��'\4c�]vY�~�����h�/��/���8�̛7/��sO��$Iee��~���^�����y��W3jԨFk�[���W_��{v��)�ׯ����SQQ�'�x"��vZ�{�,_�<���kԿ|��$ɠA�����r�@���Ԥ��f�k�;w����3dȐt��!�Z�J�>}��|'_�җ�}W_}u.��u�Q9�#RYY�[n��cgk߾}�M�����TTT���<;v�g���zh�N����ҽ{����g˖-I�s�9'm۶�…��/\�0�۷��?�����������!���9rd~
��5���f�ԩy��ҽ{�$��ի3lذ�3&��7J�~^��9��fa����ڵkf͚U�͚5+5jT	�p82p@�ЦM�L�0!���Ϛ5k�f͚̟??&LH�֭K��L�R���rJƍ�;�3Ir�W�_�~%N����JUUU���J��\�Rhn\l��vZ�:��nĈ����ܹsK�=�I�=�կ~��1��	v��~2p�8��1��`�`?����ȑ#K`����K�-�ٜ9sJ�����<��c��͚����_�j�#4����hQ�͍.��B��$���)���̙��K�&I���#F�$h.ء�^z)�'O�#�<����\x�9���ӷo�RG���E��lڴ)��rK.��TTT�[�n>|xn���lڴ���`�3pPb�B!�B��1�>}z֭[��.��X��⋳nݺL�>����0pp���{r�Yg�{�)����r���g�С0`@�=��L�2%[�lI��������3lذl۶��~�V�J�P�y�W�={vN=��t�ҥ�׵k�
�̞=;����@��8��}�ݙ9sf�9�\q�I�-[�d�ر�1cF�z�|�Y�fM�M�����*۶mK�r��?��?��3�4���O��~��I�'�|2uuu���l�������婧����J��AbҤI�5kVz���?m۶M�̜93���ZN<��TWW��_̜9sҷo�,[�,���O��92m۶�C=�h߆��A�%I/^�$�ӧO�
��8T�,u��M�P�H������I�&���:;v�<��;מ~��$�ĉӭ[�$I�^�2a„6,,Ȱa�r�QG�.��?�%K����2���y�WҮ]����/I��o$I�=��&{��٨U.���I�����w�˧>���ڪU��$C���+V�(�5jTy�L�>=���Y�dI�nݚ�e��
y���I�:4٫����*��\������PUUU�͛�͛7�̤I��k����|�ƍ���>��|�+_Iuuu�/_��&I
T�)++K��hѢ�^
��8T�8\s�5��'?���/�?�|^{�p�	I�����\�2O<�D***v��%�\�G}4�<�H�,Y�-Z��N+�w��9k׮͆
ҹs�F�nذ�����G@�4r��ɟ�I����3�<3I2~������ٺuk�y��{�)
;vl�}>��O����O�Ӽ���g?�O|��޽{'IV�\�$CC��U.v�^Ș1cr�uו:J����<7�tS�����/�W^I�\z��ٳg^}�Ռ5*_��r�9��?�aZ�n������^_���R__�$4hP����.�/_�來������x뭷��|'}��Ieee^x�|�3�ٯϬ��IMM�G�=餓r���'��S.ڷo�iӦ���*)//Oǎs�g䡇��i�ڵ+�>�����s�9i۶m.\�侅�}��<x�G~p0jY��V__��<�����O�}��9rdfΜ�SN9���v4�q�M7妛njT�رc���\s�5i߆�1�=����ի�Z�v�RUU��S�f����޽{�d���y��3f̘�m�vo�4�p����r�m�e˖-�1cF֬Y�x����C]]]�y�|���O�\r�%;�=zt�v�Y�fk�f�JEEEF�u@�@)9� �/��#�<��1���O?�����Ϲ瞻þ6m�d„	�ۿ���P���s�}��u��$+����m۶����MEE�N{�a�$�ҥK6lؐB����ǧ��|����rJƍ�;�3Ir�W�_�~**����o��o�1cFf̘�c�9&�-*u��[�`��WUU���j?����pHٸqc}��L�>=.LEEE.��\z饥�D\��+��2?�p����w�y��O~�s�9'��奎d\����>:��v[F��.]��:p3p2����vh�ܹ��Ј�K�{.����/����76lX���#F�:��\�ֆ
2s��L�>=���/2`���jࢪ�*UUU���@�R__��{.?��2o޼$Ʌ^�I�&eРA%N�g-Z���1vjΜ9��͖��Y2dH�y�|���=�ܓ/�0GuT�c�U�Ve�ܹ��W�Z�(�̝;����3p4+��73iҤ|���-u�}�'��MuuuF�Y�Ь�����>��Ң����ƍ��?7�pC���.��j����~�G}4|�A��կf۶mi����5wo��Fz��õ9s�d�ҥI����gĈ2�w.�}nݺu�>}zz衼����۷on���TUU�裏.u<>�k��6�=�\jjj�����K�<yry������/�����}�� )�.�}��F���\r�%�9sfN9�RGb=��s;�oڴ)��rK.��TTT$I���o�9s��M�6mdL�o���s<�@֬Y���߰�GP(R(J�#�>}z֭[��.��X��⋋�������s�1N:�G�1V�X�q��e������o�=�6mj�[WW���?C�̀r��fʔ)ٲeK�g���)
Y�`A�{�ӟ�P(��ol4��� ����={vN=��t�ҥ�ӵk�
�̞=;����������������v��_^z�RGH����Ș1cҷo�l۶��q+cƌɲe˲y��lذ!?��3iҤ�-[2v��̘1#o��V>��Y�&ӦM�UW]U�����ӥK�|����ڵk�$k׮�wܑ.]�䦛n�i�'�|2uuu���l�VYY����<��S���@i��fnذa�ׯ_ɞ�~��L�<9'�tR
�B����=:~�a�2��=��̛7/�/��_�$y��g��3g��k���O<1���y��3gΜ���7˖-���$:tȷ����{���[�m۶|�[��{w	&�cǎ���)�[SSS�^�xq��O�>M�5�z�`ײ�84��ח:�!���/�s�,Y�)S�d޼y)//ψ#���0`@I�J
��G�����
7ܐ=z$IF��iӦ��w�-�?���I��'�[�nI�^�ze„	6lX,X�aÆ%IN=��TUUe֬Y��׿�_��W�����~���x�$���^Ϟ=�����C�?�xV�X�{�'UUUi߾}�#֎;���;&I�m�V��Z�*I2t��޿bŊF�W^ye^|���W�J�^��7�7�Ͱ~��$�?%c{
��8ص(uMeee)++kr���o��oұc�}�ѹ��[�$��N.�袴k�.�:u��ѣ}z��6m�e�]�v���裏�%�\�5k��6�ƍs�7�W�^9��#ӳgό?>�7o�a�͹7�կ~����]�v��'?������{�W���t۶m���[ӻw�y��СC�����^|T����,]�4W\q�a�}��������IҪU���?��`w��lܸ�c����h��W�
�e���.8�����:�����w�^�zeʔ)����$I]]]~��h�"ӧOor�C=T�9sf-Z�_���ԩ���y��y晍��}�ʕ�8qb�-[�'�|����mνy֙g��w�y���>��[�6z��n�������[�l�ҥK�t�Ҽ��kvzo���~;���'w�޲�_'L***�r��<������m�<�+V�N�k���ɓ'�M�Ν�v��lذ!�;wn��aÆb
�p��lٲ���+ٴiSn��$ɸq�R^^��_=uuu�ַ��$y�'��O��O�?������ŋӳg��7��]wݵ�g�u�]��������K��������3�dڴi�,��<�w��������e���I���L�Ԃ����u�0�O�Ӽ������͔)S�$���N��~~�e��9�c����<��$�����g�֭y�wr��P(d�ر����Nuuu���iӦ�_�~�я~T&J����U�Vk�{�N�!��5�z�`g����I'��֭[窫�J�lڴ)����޽{�M�6����d��S�L�_��_�#�Heeeq�`޼y;}�9s�$?�яҷoߴl�2'�pB񤌙3g{��?���gҦM�\}��I������$I���$�&M��ɓ�nݺ��_�U������M���_�ꫯN�n�r�%��]�vy�G�O|b����q饗�gϞy��W3jԨ|�_�9眓��iݺu�Vmmm&L���m���nK˖-���ַR[[�$�c��s�=7Ir�i�%I�/_��
�A��
����O>���C����gV|ݮ]���?dȐF�L��ۿ��N���$�իW��ʊ_�'����*��<��O,�>�裓$۶m��I�;�3mڴ�SO=�k��6���g3q�����5��O~���ʜt�Iy�'r�u�eժUy��2t�Д����9555����X{�o�>ӦMKUUU***R^^��;�3��C=T<y�;��o���p�
�֭[��[�n���nݺ�q�I�뮻.ݻwOyyy�lْ$9�sҶm�,\����.\����g���}@sQV��g�>RVV�$i�u��;����6mJ�֭�}�^ڷo�6m��
���u��y���w����<~��>ɹ?������wy��2u��,^�8��O%�8qbƎ�$����?��?��_�z�<���^����9rd��j��C��>��S���K��ݓ$�W�ΰa�2f̘|��(qB�8~^���*/��B���>IҧO���ӳg�$�o~����7�j���:u��.�,�-ʲe���o~3����r�5�{���2k֬�u�Y�-�'F���]�f֬Y�ڬY�RQQ�Q�F�0�[.8�\q�y���d�…œ.����s���'���/��|��Y�vm�������嬳��g��dz%��_��X;��RVV�k��6������>��}�sI�#�8b�ر6m�d„	�?~֬Y�5k�d����0aB��g�`ײ�`O|�ӟN����
�B����z���x�y�Dzdɒ�r�)��ڶm���k����ԧ>�u�֥w��9��c�dɒ�x�y��73iҤL�4�Q��������s�)�dܸq���;�$W^ye���W�T�o9�����?���?�GZ�j��ݻ����~��]~��QG�%K�䪫�ʱ���-[�裏ΰaòt�Ҝ|��,�xֽ�ޛ?��?Nyyy֮]�=zdɒ%2dHN8ᄴn�:�[�Ή'��o�13f��g�v���*w�uW��]�0+'\�_�����zo�;w�O~�=zv�t��)w�}w��=�wO�Y�[��￟���4(W\qE��#�<r����\@3w����_�z.����q��\@3w��'��O.u�Ê�(�
6dΜ9���J�v�J��������=d���B}}}�#�SK�,����<��ٺukz���O?�Ա���9s�:�Z�:.֭[���;}���i���W^y%��~{֬Yc���q�,����Ӻu�\t�E�9sfN9�R�b?[�hQF�Y�;u�� ���8���|0#F�H۶mK��4�Muu��0�
p}�ѹ��KK���E�����_�7��ͼ�����>���6m�ܹs3u��,\�0�sL�>����ݻ��`�(
I������9s�t��$I���3bĈ}�\�.`����ԩSS]]����6,,Ȑ!CҢ��ao���K�<yry������/�����}��:�1�-Y�$��vZ��O�4��rK.��t�ҥԱ`�ؗ'[�ʦM�r�-��.HEEE�d����3w�ܴi��������%K��_��_r���`�)
)
��QӧOϺu�r�Ek_|q֭[��ӧ�0�;����e�����a�a㗿�e�:묌;��VWW���?C�̀r��fʔ)ٲeK���N�Pȥ�^�h�e˖�P(�駟nT:th
�B�z�&C 
�+V�ȸq�2p�|�_��ߞM�65��w��m�ݖ/~񋩬���7ߜ���&ﭶ�6�g�Ω���h��k׮)
�={vjkk��{��{[�n͂2lذ<��㥎;4iҤ����lْ�c�fƌy뭷�d͚5�6mZ���l۶-�N��˿�K�����z*I��3�k�ׯ�[o��#�8"�i�1c�dٲeټys6l��H� IDATؐ��Ǚ4iRq���6�_~y�ϟ�
6d˖-��O����7���'�L]]]*++��UVV�����4��|���z��ѣG���/gÆ
9ꨣJv�W�^Y�xqn��$�̙3��k���OLuuu^|��̙3'}��Ͳe�2��TTT䳟�l�nݚ�_~9I���g?�YZ�h�ŋg���I��˗'I>��ϧm۶;�q��f޼yY�xq.���$ɳ�>[\���իW�c�Ɍ3��/�{�^~��_7�k���I�>}�4Yk�5���f����￟ٳgg���g>��S��k_�Z~��_��g��g�Q�
�B���ՓdԨQ9�#��O?�t�d�ĉ9���S^^�^�ze„	I�$I񔋚��$ɋ/��w�}7�w^6oޜE�%�3�<s��o�����#GydF��$y��w��?��ϓ$7�tS���,�Z�J�~��?��l��o���C��ٳg�8�Z�:H��_��ѣG�/��/2o޼|��_Nyyy�c�n5 4X�jU�d�С;�_�bE������w�]�xꩧr�Gfܸq��O~�g�y&g�}v�/_�-Z���O�e��;���cǎI�m۶k�����$9餓�w��'7�k���I�:4Yk�5���f������e�ڵ�ԩS��pk~h�p���?�[$I}��gᆪ����3�8(vjl�(FF��=64XDL�A��)�k��\�&k����KbBT"� €�"�vcl(����.�q@)�0<�Z�����~?��֜y�.}�3f�H��i�&;�SƎ�?�0Æ
ˮ��u�]7;�s�~��|��'y���կ~�K��Xu�U��������>���������///opm�؂���A��f��O?m���Iق�`��6�믿�?���h���p��^x!�
�̙3���'Iv�}��92Ȍ3��>�,u�v����^˘1cҽ{������7�����g��ə6mZ�_�zצM�V7���kB`4eʔ\u�U�رc~��_������;/�&M�g�}�>� �\sM���r��'���w�}S^^���?I�
��[����N���K�렃J�\z�3fLjkk3a„\r�%
�o�>I��7�6l�Xޜp�
k޼y:th~�����Neee�=��v�aEG�e�NȰa�2v����۷޵����G?�{����s�Ω��I���ӦM�$��o�M7�4o��f:t��'e,��}�f�С��?�����׍x�
���[����g����ܹs�k�O��c�=�:,	'\�™9sf~���e�-�����~;7�xc�z�0 �:u*:",�������,�=�Z�ʭ�ޚ޽{g��6�*�����Z+{�wn��'Cp�I�v1�Č�բE��t�M�իW�]wݴh�"���;�s<���yꩧ\{ꩧҪU�����WY�T*�ܹsӹs�p���w��:	�$�N�>}2�c�Ͽ��o�1��rK|�l��&I���z+={��I'��O<���<y��/�V8���jƍ�+��R�Vp���ˆn��n쮻��Fm��}������MάY���[oXZ�l��.�(?�p�y睼��;y��s�E�����x��*��=:7�|s��r�!���h�v�e�|�{��W\�$�����Ν;�
������:uj����r�-y�ҡC�\x��ӧO�р�w���ݻw�1��������	'��?��Ye�UҫW���׿N��݋�
���"�Z���W_�c�=6k��vё����������p�2�ꫯ��K�n݊��;�c��PϽ��[th�.h4s����ߟ�f�С�o���裏
��f��裏.:@ޛ��)\��ƍ�������C9$>�`9䐢�A�v�}���E����K�G�y�'���欳��7���l���Eǂ&a���ӧO�1�T*�,��J�~�r�Ee�=�HYYY�q�I���_t�z�|��Ф)\�T���Wth�>��#�3w�\���E�i�3gN�뮻��(��9��zF���n�-�����s�q�	h$UUUI�����^�{������1"Iҵk�s�1����p@>���<8̘1cҡC��u�Y9����Fhž��\�����~�R��c�=6�n�m��կ
���9�3iҤ���+�]w]�w�^t$`9X��-�ȬY�r��W�^u嬣�:*�~�޴lٲ1b@!ʋ@�n������;8p�����*UUUE�Xl�{w�;�n��F�{�8��d��.�v�m�V�Z�����ӥK�u�Q�~�G�K�.y�7�$C���'�����;]�v͡��+��"�|��B�XP��>�O�����޽{�?���1}���s�=�ҥKڴiS7�����*��sO�O��$�MBE�XvF���n�-��׿��?���8�b�l��RUU�Q�Fe�ر�ԩSݵ�c�歷�ʮ��v���7��Mn��z�O�<9��sO>����?]�=�O��o��y뭷�Ɔ��3g6��׿�5�|��O��޽{F��G}4_������Iq�@3��o���/OǎSUU��<{�wJ�R�р�4����#����$�իW����N��s�9y�g2|��0 I��SO-�~w�qG�z뭴k�.�
ʳ�>��n�)/��r���<�L��;!���͟+"'\4>�`~�����kZ�j�c�=67�|s�u�Vt4�s���i|ĈYo����c��3�Ȫ������<��ciӦM��s�$ɓO>�R���'�/�K^~��5*I2cƌE�5lذ$ɹ瞛�;&I:w����~�zs���&I6�|��l������H������$w�yg�8∴lٲ�D�Ҫ���G��橧�J�=2|��L�6-����*���$y�����('Nl���n��o&I:u�To|�wn0��?L����
���?VD
���MEE�}\s������������z��l��$9��#3hР��OJ�=��?�9����ٳgݜ_���8qbڵk����+[m�U:v�c�9f�r�/g|���������$Y����s`E�'�>|x8�E�?gΜ�7��([@����k׮y�g2~��<���k��ҦM��9#F�H��z����;�������W�v�$cƌ�7>~��s�_�$ɴi�\�?6����`9{��dz�n��'�Ȱaþp��ѣsꩧf�7΁�y��-��@��=�}�YN8�|���ի��=����O3iҤ���u���"�s�A%I.��Ҍ3&����0aB.��s۷o�$y���\�?6��.��x �zh��铪��\}��
��{�ꪫҩS�TUU����Yg��#F8�VR{�G݉�ڵKuuu��{�w��'?�I�w}�楗^��>iҤEڧo߾i߾}&O������k׮�ׯ_:t��`�n��d��_��c�=i_h��D`9��;r��G��r�w������Ǽ��+usN;�l�馹��ӭ[�><'N��g���6۬��TSS�����^///OϞ=�$GuT����]?��3s��e˖iѢE:v옟����߿��w���"�hѢEn�����+뮻nZ�h����?�w^��x`V_}�<��S
�=��SiժU���E����R�T*:@sw�
7�SN��g������I�y��}��9��s��&I�R����:*-[�,22��>}�d�ǰ����x㍹�[��f�M6I����[�ٳgN:餜x�'fe{��%��e�K.�)�������ue������N��3u��$I�޽ӧOe`�Я_�l�ᆹ뮻����l��F�۷o��`�)\,#�R)g�}v~��n��g��`η���TTT��o. !��iٲe.��<���y�w��;����E]���ʢ��R�(:@s��g��SN��7ߜ�o�=}��Y�V�Z��O̵�^��N;--Z�X�I��.���}�{��+�$���ӹs�S��S�hds��M�~����������+��"w�}w��뷜R4�޽{�w��E��F�pЈfϞ�C=4C��e�]�����~��y���3eʔ���y�������㏓$�_~��4
�d���9�C��SO%I�9�$IeeeZ�n�
6� m۶M�֭��V[�u��i۶m6�`��n�:�[�μy�R^^^�cQ�h4555��������d�MҦM�l��iժU���Ťp�H��g��#MԽ��[t�z�/��S�XƎ9昢#�I�`�ݻwz��]t`	���q�@#���{���X�o@C
��c�):���J�R��MIy�����Q���`�}��G����S[[[t�eB�Xlo��f������`�P��f��a���mۦe˖�m��r�Wf�ԩEGk��_�����RVV��s���~���kd���EGX&�J�R��@�>}z�9�2d���[o��r�-�ٳ�rN�`={��C=�%��b~�bQ�]����s�=��v�e��EGhtN��f�w��2dH6�d�80�n�Ν��^{-�sN�N����>:#F�(:j�䡇*:�����RSSSt�e�	�=��#9��CӦM��=:�n�i�9�^zi�;����#C�- e}Ks�.�w�}w�?��L�>=���E�hTN��f��nK��y�,[$�)������g9����O�:5?����f��E��|�����8ӦM�7�������E��_�7.���Xc��n�:��w3s�̺9�����K�=��:���~�3f4�{ƌ�۷o�\sʹm�6��w2y��/�����9�l��Ym�ղ�[�����ٳ��^X�u��%�����?�Qt�F�h�ڵk�7�|3&L��o��M�6-ݻwϋ/���ڎ;�g�y&k��f������_�|���~�;��M7ݴ��F�T�\�����Y`�o~�����q衇�O�S�y[n�eƌ���^{��fϞ�=��#555
��o���׿�5���
�T*�u�ֹ袋rꩧ�Q�t����:|�+_Y��~�_��_̖[n��ÇgΜ9y�駳�[dܸq��˖8S�����K/�O>�y睗$y���/m�J���W_}u��n�'�|�ٳg�'�H���l����?��C�fΜ9>|x��r˼��k��+���+�LMMMv�u�<���;wn&L���w�=�?�xn���%~fh����r���S�NEGhtN��f���2s��Ɍ3��k,�}�o�}&N���{,��_���>�<0:t�ĉ�,�	�G�N�Ν�$|�AZ�n����|��g_�^�T��ѣ��/d�ر����	&���,��ͫw�#�<��}�ku�>������ӱcnj?~����N;vl^{�z�W_}5[o�u��k�6l����A������:���jƏ��;.pN�T�����^�n�e˖�={v>�䓴lٲn|֬YY}�ճ�j�e���I�p1gΜ�hѢ�Zyy���z��N;찌=z���.I��W_=�f�Z�I��z��>X�u�y*/:��w�$2d�B�92뮻n�v����$
���?IbA��9s�,t��E�K_��SO��ѣ���[���O��3a„�����UTT,�/z�$�6m�"e��h����$�կ~���{���y���'?�IJ�R�?���B�W��$��O?]o���[l�E��r��\76nܸ�{�$��_�$Ç�W\�N8�^�c�ܹ��5���aÆ%I��f���1������T*5�3���\.�:���^{���N׮]s�=�d�ԩ���O3r��z�y��G�}-��w���ٳg���Oγ�>��s�f���9�䓓$�zh��6m�$In���̜93&L����_�x饗�
2$�g�Θ1c��$I��G�[��O�s�=�O?�4Æ
�I'��$�ի�B�=��#�$�{�Θ1cR[[�ɓ'��3�LYYYz�������J;X�����o��2~��^?��#s�wf��W��:ujv�u�z�����f�<��sYw�u��_)c����t�A2dH�ԝD1�4�$>?޶mۺ�86�|��_��7����y�}ƿ��/9蠃���ݻw\o��;�g�y&-[�\�ӦMK׮]3iҤ믾��y�駳��;/4�<9����m�f�ȑ��/���ꬹ�Yk��ҫW�<��c���P�l�$묳N��SN9%�l�I***�馛�?�AF�QW�H�+��2��w���맲�2|pn��%�{�5�d�-�LEEE�̙�$���r��f�5�Heee�����.]tQ��4`��|��Heeeڶm�SO=5Æ
�+[,��k���Ç�?�a6�|�TTTd���KϞ=3b�eXI9�X*����ׯ_N:���E�hN��JEEE�{�6��(�F�Xj��KF�Ut�F�p,���������(\K���*�'O�o�Qt�F�p,�]v�%���5jT�Q����Z�j�:�����(�B�h]�tq��l��J�R�!����E��d�M����.>���M����(\|����(\|����fΜYt���p��;�l0��dΜ9_x����̝;wY�����O?��KE�(��_�ѣG�2dH~��_}�}�ǏO�=2}��eXB�m�]jjj���T.�B�92���J.���z�7�tS�=����^�:t��O?�:d����:*�����2v��̞=��(KL�(���$/��B�͛W7޶m�$�g���{w�y�$��o���ݻ祗^Z�I��եK�̝;7���?����.����>��~��{�y�7��SO%IfϞ�)S����v��<����
6H�6mr���M�6�޽{F��<�[o�u�]w݌5��(KL�X���g��ɹ���կ~��^{-����~�r�!9��R[[��5v�a����;�����ݻg�}���?�<X����TUU�����(KL�X��]v�%�۷O�޽s�}�e�ܹy��W�$[n�e��ꪼ�T_ IDAT�˹��Ǝ;����g��W�<�>}�䨣�ʍ7޸<X�����9��KL�X��̙���?�{�N�s�1�裏�裏��_��o�V�Ze�m�ɏ~�\xᅙ2eJ�u��~����)�JYe�Ur�M7�'?�I�����.H�TZޏ���]��E��;wn�Q�HYɧ
�r��W�^y�7���'I��c�l��fYg�u2nܸ<��I�3fd��O�=r�m��[��g�M�����k��+_�J���ӿ����77�tSV]u��l@��`���{��{֕-��w��y衇��K/e����oժU�����~��1bD�uv�a�$Ʉ	��[���?���/�~xf̘��h�.��f���ӟ��o|��Ə>��|��;vl��z���{�z꩙7o^��k���6�,�Ǐo������oy���뮻��w�]64[
�r�����6�z��7޺u����#S�LiP�H�k��6/��Bn���z�;�cƍ���6�t�t��1/��b����7�C+�`�<xp:蠬��z
���)�JiӦM�k;�C������s��ԩS�O�0���Y�f�K.ɶ�n�W^y%�
������YS�����?�?�x�;�^�j���$���?\����׿��L�2%?����;v�I�&���6���˭�ޚ���*�]vY�9�L�4)�|��}$,���+�{�7����3gN��ׇ�$����ӣG��=���?��̚5+I2v��|���Yk����;fΜ9����A�eܸq9����z���K˖-��3�GY�T*h���c�<��Ӌ<��W�N;�]v٥��v�m�����}R�gϮ+Uz衹��˳�6ۤ��*m۶ͣ�>���,��^z)���?s�a�`�(\M�\�)S��[�n�ܹs�r��|���I'����޻nlĈ�m��2hР���w��̕W^�+��"��N�Q���dM�2%#G��!����r�)�����'f���_��E1lذ��>�����v��`��Xy���e�����O�gϞ��O{�K/�4-Z��g��4��TUU����5��(�E�h����S[[����žw����u�]�A��'�X��EѪU�t��a��=(���dm��i۶����G��?<'�|rfϞ����EU]]�`��p4i���y��g���믿>���OEEE#��.�쒚���J���,2��I[�o��t�Ms��+\@����3u�Լ���EGXd
@��뮻��_��ɓ��,�N�:�3��j��Vt�E�p4i]�tIYYYF�Yt`	UVV旿�e6�|�,2��0-[���9묳N�<��l���!��)+�J��C4%N�VJӧO/:Є)\+��o�9�:uʌ3��4Q
�J��˴i�r�h�.��N۶ms����k����?_t�	R�VJ'�xb�u�����>+:�ƍ�#�8"�g�.:
��R�VJeee0`@ƍ�믿��8�RXm�����g�رEG�R
�
a�̙9���/4ښ�m�]�>����y�7m]`���f����:9rd�Q���P�u�Y'���oi�k��?���y�'5ù瞛M6�$w�yg��4TVV�����=��(_��������ѿ{��V�3�<���_�Q��K�.y衇���p�0�v��腋$��UUUeҤI�1cF�Q����¨���k���)S�XB]�tɼy�RSSSt�/�p�0���SVV��{��(�j׮]6�pÌ=��(_H�Xa���z�j��2jԨ��KaȐ!9�����*��8�v�#FX
;�S�����B��RYY����;ҭ[�l����|/��)+�J��C4%������J�֭��c������H�rV^t�����"7�tS�
�;�8@�p���vZ��L�81�[�.:�)\,���ӳ�v�e�}�͠A���,G�Eh��\s�\w�u��;2t�Т�@�S[[�O?����p��<��~���w��ٳg��Y�fe�u��#�<Rt�R�VX�f�Z.�\��9����g�-��`eвe�l��f���):
���J�R�!�q������y�EG��	'����~;�>�h�Qp�P��7�<�]v��۾}�<��s��X����RSS�	4E
�
���:���J>��â�K�K�.�裏��+���`�T]]�$N���N;�UW]5�F�*:
@
�
i�
6Ȗ[n�4`VYY�N�:�����(
(\+����1����Ν[���\���5kV�1P�VX��Յ}#�<�v�!3f�(dh.����7�):@
�
�k׮Yw�u3eʔ�n���?^x�r�X�.�V�n����3l��r߻M�6��/~�k��&cƌY��VY�T*`ET*���>�d���9rdVYe��#��	K���,Ȅ	r�5�hD
K�}��9��ss���_/:�H�J�R��+�9s�d�w��+����8@#P�ho��F6�x㬲�*EG���O?����TUU ������t�M3p��$Iʋ���~��<���R�ҥKF�Yt�:
�
���&}���ԩS��,�.]�dҤI�1cF�Q�(\�ԩS.�첥^���:�R)�F�j�T@���2o޼��� ���l���b�-��s�XB�ڵˆn�p4
@��Ν�(�TUUe�ȑ��Vc:th^~��c�
�K�.M��s`�p�O>i�u�u�#F4�Z�a޼y9묳r�I'�T*VUUU=zt�1�(\�D׮]3eʔ���+EGI����g��y��'3hР���
�C�	'��y��@�h:w�-Z4�S.���r�)��3�Ȕ)S��M�.��.� ��~�(��P�Beee.��t�С�(���g?K˖-�����(�bP���3�8#UUUEǨg�5���_�;�3�?�x�q�ETV*�JE�h�:ꨌ7.�ƍKeee�q�/�����K�n�2s�̢���	����Q���{�'g�yf�1����ФL�2%��zkJ�R�Q����Ь̛7/G}t{챢�K���:~�a^}�բ�+1��Y)//ϋ/��'�x��(��7w@C;�S***2jԨ��+1��0;�S������׭���s�=���6�aÆe�wΌ3��MJeee:u�pJ�(�Zk��L��ڵkF���>�l���X:v�7�|3�~�Q�ɩ��JMMM�1������t��53f���㋎�6�`�\q�����B)|Nuuuƌ���@�p4;;�CZ�j��{��(_�_�~�s�=ӿ���������̜93/��b�Q�����쬲�*����ȑ#������r�7f�ĉ��꫋�MFǎ3r��t�С�(�JJ�h����3bĈ�c,�m��6�w^.���_�*:4	�ҥKV]uբ�+)��P����d����6l�2Y{Y8묳����?�i�Q�$EVn3g�\&�m�v�����h�"=�P�{�u���5�J��B��8��TT,��
	,E%��
h�/v�"�e)ұ�,JWt�@L��tp������2K�HHr'��㜜��������a��4H��l6��Τ��Ά���Pp�Zff���Qp�ֆ
���t�Q����Tk:~���e�{�n<x�t�i޼�rss���d:
p1\�j-::Z=��e��O��'���f3#n��&]��JLL4�
.@�֦M���O���6�Lf̘�-[�h�…��`LXX����M�.��`L�Ν5r��
�#<<\���ھ}{��SQ�V��~�i�;V'N�0#��”��d:p1\�j-88X�^{����LG)�W^yE~~~=z��(�C��ԩS��B�����ët�����fΜ�%K�h�����P�V�$)11�p�J(�Ƹ��W�>aaaJHH���*�C=�>}�h�ȑ���4�Ju���j���ɓ��B�0��ϯR�	�ѣG���R)�U�w�}W���:u��(T���
0�t�B*�c�j۶��V��?���뛎Sf7�p�֯_o:.��P�ծ][			�c�*�����b��l�C8:\\����PpP���㏺��;���f:
.''G�V�����MG.���*��oԞ={c:
�f��o߾ڸq��(�Pp\ƩS�4m�4�����Rn�ի�iӦi֬Y���7�
���V�Z)!!�t�,6��f:@eHIIQ``�6lؠ�]���Snl6��v���]���rww7	�
���Y����(����p���WPP��m�f:J��X,�={���ۧ��z�t*TXX��o߮��ϛ��9
.�1=z�Pddd������Jݳ2k„	�4i�>l:�j�*##C{��1Ts\�Ү];%&&��Q!���ոqc�7�t*LHH�|}}���s�<(�.�m۶:y�<h:J�����ҥK����t*����Z�n����Q@5�n:@e


�������l:N�kٲ��T��#G����tP����ooo��OR\\��(�����tP������'�V�Z�c'F�0����Ⱦݻw7�/�:j�\�����Yl6��tT��~�MYYYjܸ��(T\Ts��s������w��b���@�P�tT�7�|S[�n���MG�ʠ���

ճ�>�^xA'N�0�r3~�x-^��tPMQp�&M��Z�ji��Ѧ�Pnv�ܩ�kך��)
.��>|�^~�e�1*����fΜ�%K�h�����P.��”��h:��(�.+??_�|����{��z��4r�Heff���UӡC�t��i�Q@5D�pY�۷WRR�Ο?o:J�y�wT�N���/��p����$�.�BPp����T�=��o�Z������dc*[``����Լys�Q�j�^{�5j���x�Q@5D�pY!!!�W\\��(������p*�e����m۶\P����)!!�tP
Qp@5f�Xd�X\n��׶mۮh�;*8
(���_����������m��ȑ#��ȸ�^�z)44��R�+�[o��tP
��*��f3��=��:s�|}}/9o��Օ�8:\����y�b���СCz�G���j:
N���1��"��R�8//O�<�jժ��u�j�ĉ��S�N�_�~���S@@�
T�M��볲�4d�����nݺ8p�~����IOO׸q�Ըqcyyyi���ڷo�����.kNG{)&&�Ľv�ڥ�]����O���ӈ#���a���1-((�ĉլY3yyy�f͚j߾��ϟ��™Ԯ][[�l���MG���Oq��+ʎ;LG�ڱ��%@�U�F��(<6l��Ν[d�E�4k�,%$$<x�-ZTd�СC�p��"󂂂�}�v8�;;;[�;wVbbb����{�֯_�5j�Kβ�u�5��ԩSE�>��S�;w��7d�l6�;Vo��f�s�4m�4�3��9g��jȐ!���Uxx��8p��
��wE�ի�V�^]m�gA�\P||�~��'eee饗^�$�9Rnnnڻw�233����M��v��b���[�N999���UPP��=�iӦ���iӔ���v��iǎ�����ݻթS'}��7�
8�&gY�j֬���߯��L���H�V�\)��1m6����䫯�RNN����4k�,I����K|,���եKEEE)//�t���g*���իMG�Z���XI.bccաCIRZZ�jժ%I�駟ԪU+IRFF�����_�|�z��m��믿�}�ݧ�͛kϞ=�nݺ�v�ܩÇ��o��=t萂��u�wjӦM咳,{%%%)44T�t��)իWO5j����ޏ$�x���_u�}���W�^�Ըq�K=%N�jժ�&M���cǚ�@�eee�����[���v?8:\�ڴic��f͚��[�li���ϯ���w_��N�:I����$�$5n�X��,IڵkW��,�^!!!���֭+I*(((�~$i�ԩ���ц
��s���n�k������K�sV��r�bbb4i�$>|�t@5W���㼼<=��3�U���֭��'J�� �_�~���S@@�
����"�}}}����!C����Ou������o�]6Ozz�ƍ�ƍ���KAAA���Qvv���e�Y��v�ڥ�]����O���ӈ#���a���1-((�ĉլY3yyy�f͚j߾��ϟ����Tc%u�����t��8++K���y�]&|||������VNNN�Y��ܔ��_.9˲WVV���֭ۧ[_��/�̙3Z�j�,X���XIR@@�^{�5
>���*77WmڴQ�&M�f��q�XI?k�
��s���h�"͚5K			E��E�Y?d��X��� m߾]����V�Ν���X,�ޫ��׫F�咳,{]s͖u�) IDAT5:u�T��O=���Ν[�࢐�f�رc��o;'IӦMӘ1c��C�Pj۶m+r����K��7o^⚠� I�ѣGe�ي}@����j�*Y��Rw�А!C�e�����^Й3g��===��Gi��ɦ�\T||�~��'eee饗^�$�9Rnnnڻw�233����M��v��b�׬Y�u��)''G���


�ѣG5mڴ��6m�ծ];�رCyyyڽ{�:u�o��F.,��e٫Y�fڿ�233#IZ�r���Š���H��|��W���QZZ�f͚%I�>}z���
.@�
6L?�����y�f{'�������G�$EDDh������WJJ����e�Xt��w�[������|��6-������okҤ�,��{�=����u������v?�-44T-Z�0�fΜ�V�Z���[�F���G'�9s�Y�f���Qtt�$� I����< OOOu��^x�bŊ�\�l�$�O>џ��'����E�z���%I�q��,�^ӧO�-��"�=Z�t����G����%Io���f̘�'NhĈ��l:r��%��?Xl���Fa�@�\|\Ҽ˭�ر�bcc�̵Z�ڼy�����=w���õw��b9}}}�e��iӦ\r�u���@�=Zcǎ-v�믿^'N��$5j�HG�՜9s��&�ٳ�V�^��(�����L�������/77�ˮ��'5o�<����,������S999���*++�Ĭu�ֵM\mβ앓�c/��l�Q���{��w��K�j�С��|}}�Q�F��׷��������իս{wyxx�A�����ƍ���Ԯ][[�nըQ�ԨQ#������K���S\\���<8ګnݺ�ի�%�j߾�����{��wոqc����߬�(44T����VHH�ƍ�>����WraÅ.,b���۷9.((���9%9w�\����,�^v�*,���~����_�…ձcGeff*&&F7�x�fϞ}E�����\��:L��ȑ#�k�.m޼�\�w��L����~[�����(T{Չ���]�"�u�֩[�n


URR�õ��z���ۧ�G��Q�F��]����J~GKHH�����o���G��������.<<\)))���c:
�
������y�f
>\�Կ��?��#����m߾]���JIIQtt�,���r�V{\�߿�>֤IY,���{JKKS�֭պukIE;f����\����"==]u���ҥKէO�q�Jzz�RSSu�
7���&*��Eǎ��j��͛����p�s���{�����-[��M�6咳"�����u��	IR�F�t��Q͙3�^lr��={j������������������t�ӿ
0�܊m�(�W�V������
(::Z7n�[8R�vmmݺU�F�R�F���u�W�^����@������w�U�ƍ���IRTT�,X���Py{{���[!!!7n�>��r��3:\c���J�:h���<x��8Sޝ��p��j۶�F���^'O�4�
G���+��"ooo=��s��P�,6zi�
�\�R�>�����k�s�=��`g�X$I�
�
.P*�z���ݻ�k�.y{{��@��a:��3f(??_�w�6�RRR�|�r�1@G��Z~~����M���5k֨W�^:s�j׮m:���pp�ͦI�&)..�t�E����m�V6�M������*����X,}��'Z�v��(��ׯ�
Pp�
�oߞTaaaaJHH0Ta�z�<��c�#�Y�l���g�}��������tPJV�U���3Tat��|����OM���P��O�Z�2á��p���+99�tPaaa��_t��I�Q@E�`��ŋa:8�d�EFF����������~P�֭M�qz)))����iӦ����td�Z%I			�֭��4�*���nnn
S||��(U��f�?��O���7IRݺu5~�x���(:\���c�����e˖���I����/�0�J��ɓ���O+""Bmڴ1	��ꫦ#�*���4>��SIR߾}
'�
��BO<�z��a:F�1l�0}��G���Ҷm����f:eF�p*�/VDD��\Ԓ%Ki:'ҴiS5m��t�*�b�h���


լY���3Ϙ�@��0�GHH�����cǎ��@�Qp�r5a�]��t�Ti�p~)))�_������_]�����(g���Z�p����MG���p�"�l٢��zJ͛7�������t�M7�O�>��/Lǫ4�E���e¼y�Լys�1UL�ΝեK�1(3
. I:q℺u�Ν;k���ڻw��������cǎi����ѣ��w���T�qQ��
��gϚ�er��qEFF��ѣ���*�����j߾�֭[�n�AS�N��ݻ�������ݻW/���j֬�/��R={�T~~���T*��f:(�ڵkkٲe���3T1\@C���Çu�wj���z��ԢE������S͚5Ӌ/���[��N�:���4{�lӱ�4ӦMS�N�L�e���V�Z)!!�tP�Pp`�/���aÆ�aÆ���R``�"##�g���-�e�.�����}���k������4i�q��)==�ȼ͛7kݺu���k�b�
թS���!!!�<y�$i޼y���ݻW�
R�
���
h��:p�%�K�t��w���G�ٳ�����;p����`yyy�N�:����5i�$�={���f���>%)�_�nѢEjѢ�<<<t�����Wrr�e�]���/u
��4h���xeff�����oWbb�������
�X,Z�x�"""WW�7oV�=���Z윷���/_�nݺ���}||���>�O<�����ۦMm޼Y~~~����(͝;W&L�K/�t�999JHHP۶m���i��/Էo_eee[���U�V��{�ux_qqq�뮻���]伧��6mڤ�����t�=�(--�a��� �����/�l�|v5����*�_�nʔ);vl�^^^���ԣG�+�Q�K����/+.Y�D���������:z�n��f}��w��;Lǩ�Ο?���T��p1���Ә1ct��Y������:\T�ӧO�O�>JKK��ѣu�eeei۶mz��'���������oE��l�b_�����������9rDQQQ:����#G�(77W�������c������[�l�$u������K�:u*Rl����~��)++K?�����������d=�������c�=�����:t�|�AmٲEڴi��4i���\���+E�=Ziiizꩧt����*33S�~��Z�h��G�jҤI��Be}�.�4�����+<<\qqq�����ݻճgO���h��:y�d�r\������pEAAA�_�����LG�����H�1.�j�*==]���3T!\T�9s��ĉ?~��z�-���[���7o��}�Y�;wN3gμ�u���4q�DIRttt�� �g�VNN��q���{


����:w�O>�D���G����/���͛����O����tu��E+V�P˖-��驖-[jŊ�ҥ�Μ9�3f8\�whŊ�ر�|}}u�wj޼y���[�����$�������𐏏���.-[�L��z��r�v��z���/t뭷j�ƍj׮����ԢE�\�R]�tѹs�4{��R�&O��F���qEڷoO��U1b����+-]��t���������x�Q@B�@%��/$IO?����O>��$iÆ
%^�ܹs�߿����u�����_/r��o��$�9��Z��*�ͦ#G��Dz��$I����������kI�رcU�Fї�jԨ�^xA��n�:���k۶�$)55��M7�$I�֭�/^����?�s-[���fӯ��Zn�.Tϟ#���M�0A>>>E�.��¼��Ѯ];%$$��Q�u��YO<�F���gϚ�p!���ӟ�d/��\T�={�H�e�X�}�l�R�t��1l�0=zT�����O���V��%I�[���L�jՒ$�����~
�-,�X�xa�����$?~�$i۶m0`�6l��
jȐ!Z�b�rss�5ۅ��s�4��;���xXX�$i�޽������0;vLǎ3�J{�7TPP�q�ƙ�p1���SLL���
���]�[��̛?��-[��5kj���
(6'==]ҕw�(|�iޜ���_丰X�v���׬YS�����𼷷��=x�`�X�B��������?z����裏�E�:|�p�e���>%)�_�^�z��h
�,�3+,0�
ڶm�Z�j���Eխ[Wo����Ν���X�q.$$$D���7T!\T��7��={V6��į���[���?��g���b���-Z\r�+}�}�Ν%I�ׯ�������5�\���
�Ν;�p�ٳg�d�Z�<򈒒���/�h�…:t��6m*I:t�F�U!ٮ�%=Dž�T�N��m6[����������n:����ӧեK�Q�����w�}6l����L��!
.*Qa7��[��j]vv������LM�4I={�,qn�&M$I���Wt�~��I��{�={7�KY�r�RSSe�X���p�?�Pd^yiذ���h߾}Z�v�$iӦM����_EIJJr8'Ijݺu��5�x9033�ؚC��s:�����LG�6fΜ�������[8
.*�< Iz��W���_�e�d�Xԭ[�"��?��v�ܩ޽{��_������`��b璓�e�Xdk۶��v��=���ߌ_�رc�:u�jԨ���>~���K��L�����"k


4u�TI�=��s��W"((H�E�w�.v�C����3[Y���2mڴbc�ϟ�o�!Iz��G����d�…%�SX\s�����ߩ���4i����n[8
.*�ȑ#U�vm����P||�������***J����^{�5��5k�h�̙jժ�>���"�%1b�����h�"�?^ǏWff�6n�h�f1x��"k�Ν�z��iݺu
		�̙3u��a���+++K���z��7e�Z�����_,�=aĈ�Y�����[���[{��Qnn���٣޽{kӦM���O?}Տa���%I}����_������+99Y��WQ����U�/��R�?����ݫ��\�ܹS=z�Ж-[t��7k�СE�w��I�4l�0mٲE���:t�ƌ�Y�f������$iŊ���Wnnn������a:�Y�����b��l�C�d�X�x�b���/>�����K���GYYY�Ϛ5K#F��[�V%%%]���̳p�B=��r��O���q�Fy{{ONNV�޽u��pssSLL�&M�T��ڵkշo_���;��奥K��W�^E��GJz�����T�����v��A����U�F�*$[i��K]�,��e��3g�9_�~}mذA��v[����Du��Y�����;w��
�p�.]�hӦMEƪ�ˊK�,Qdd���.>�:�pPɺu��QC��M7�$ծ][]�vՆ
��Y�СC��c�С������N�:���ԭ�ު�_~Y�~�m�bI
		Ѯ]�4w�\=�
�������մiSEEEiǎ�-$顇���5`����]�����;v+h(�Z�ji۶m����?�h�B>>>rwwWpp��{�9�ر�H�Eyg+��W����M�6�j����]�7Vtt�v��U��B��x'66V={�T@@�<==ծ];}���zꩧJ�gѢEz����'www�x�y[P����LGU.�1����Z�댁���P��r�-z�g�׿��t���pP
���Z�~�Ν;g:
(�ƍ+11�tPPpP
���z����ߛ�R��iҤI���6P��m�V			�c�*���R�[���6m���8�Q���g�j�ԩz��WMGTc��~���߯��T�Q������ڷoO�E�馛��K/iʔ)���M�TSaaa*((PRR��(��QpT16�M6��tpi��኏����MG�v��׿*$$DQQQ��T�
(00��pY\c�,Y�:u꘎Qj���JOO�CpssӼy�u�V͟?�t@5���x�1������Z�l)___�����TK���z��g��/������v��)33�t��(�F�;w�t�Rsww��jնm�LG��&M�$�3�t@54~�x}���c'�n:��"##�j�*�1��O?��tU�O<���ϛ�Qm���k޼y:q��(E�p}��5����!���?��t�j��7��(�Ncٲe�#H��8��b:H�l6����8�^�z)""�t.jɒ%Z�j��������W}��5����ˣ��d[�T�t�4���LGT?������M�N��Pe�8qBV�U��{�$�رc�Z��֭��d�c߾}N���e�4f��3F˖-��T��y��i:���:u�&N�h:pR\�*#99Y�Բe�"�!!!�29��{�؛/���;4c�EGG�������?VrB*λᆱw�y�t����k�ʕZ�f��(�j ,,LIII�c'E��2J*�(<vu�}���흕��	&�O�>
�
7ܠ޽{��_TVVV%��b9rD���.�k׮�����O?���t�qU��j���Ç�����Y�V�ׇ~(I�;w��V��.]*I�>}��V�ɘ(��E�t��	����>ֿ�8qB�-2�����~�I���������~[z��MGTqmڴ���;].�C\\��Ǐ�o���^����_�~���/��KKKӴi�Խ{w����G�z뭷�}sa!��5r�Hu��I��s�^��"�


4{�l���[�۷�wܡ!C�hժUE�u�u/�~����5|��bse*�}��wZZ��.]���0]w�u�9��׷̤��]��jW~~�MGq�]w��L��3f������Z�h���x�Q�r7�R
�@��~EDD�Q�FZ�|����5x�`5m�TK�,���O�֠A�����<��'��z衇$I���z�'t��a����-Y�D���Z�p�|}}�\;**J�Ν�$e8;� IDATggk���*((PLL�$iƌ�������]�vi׮]���Pdd�e��[JKK+R�P�����땙��:;סC���kÆ
z��GK�	g����+>>^w�q��8.c�С�裏4l�0����ݝ���MXX.�Ct�UBrr�$)$$��qE���→E�Z�b����{=��#�����}��:|��4h��j۶mZ�`�n��<xP�~�k7j�H+V�Pll��*I���o��W�X!I�>}��mۦ�^�ƍ�$���"�윘�X쓞7n���X���K�~�%�+Ij޼y������/��B��^|XU�m�V?���.�b�hΜ9������t@f�Z�������Q����T	�-[�tx\Ѷl�"I���VÆ
��뫘�%&&j�ʕ�y��111jժ�<<<Ժuk�?^��q��b�;v�6l(///{����T��Ž�/ֲe�t�����G���Z�f��0`�<==+�ٷo��?
J.TdU]�v�g:��i֬�<����t@v�]wi������68
.�S�Z��Z��‚)S��j�ꫯ��$����9����?��w)����$�u��E�۴iS�:jҤ���Z�jIR�O�5j�������~[�?��.\X�7�8�֕޷#�O��$լY�ع±�9Tu���:v옎;f:��iР���*��[oՔ)S�xP���+`�X�j������>��w�֭[��'�u�����֬Y�ԭ[7-_����/����f����[���w��5��U8v��+΢}��JJJR���MG儂��5w�\IRHH�5}�tIRhh��_�믗$<x��n��Iҏ?�Xd��800�L�תUK={�Ԃ��jРAJMM�[o�U��:ddd���ە޷#�\s�$�ܹs���������Qhh����MG儂��%�Qp��2t��Q�4u�T���(;;[S�L��j�#�<b�w�]wI�^{�5�ܹS���ڹs�^�uIR�ΝK���?,�ժ�>�L�����[ԴiSI��c�����5$I�V�RVV�>�ɓ'����ݬY3I�/��R캅c�s�����t���%���bȐ!��믵s�N��ѣȹ��z���A��q�F����СC��kذa��+1h� ���k�<yr�����P��:}��z���@�]���k�u�]Z�b��y����;��:�w���h�;��Srrr����ò�����pzX�޽��qe��k�h�"�w�}�Y��<<<Լys����֭�}^͚5�h�"=��c������뮻N����￯Z�j�z�޽{k�ĉ���[���)OOO5i�D�֤I����y5h�@nnn��ͽ�5G��>}��v�����T�4a„2߷���~���j���Ů�y�f����k׮�~<.%??_s��Q^^��(�*�b��l�C�d�X�x�bEDD8<F�7{�l-X�@�V�R�
$I����z�ꥨ�(=�䓆E-Y�D���*|���c��;r�Z�h�	&h�����0:\��4H�����ŋ�c�/V``�`0��n��fM�0A���:d:�
Y�~�F�e:p"����Z!�MLL������׳�>��J�֬Y����6��������5k���Ң����'�hĈڰa��8�*�ԩS�5k�&O�̿Y�$:\���~��9r��N���S��/��BCCM��BlڴIu���ɓ'MGqi�3g������?6PE���)//O;w�48	:\�j�N�+""B�cP�Z�j%�ͦ��8=��C�㸴:(**Jcƌу>�k���t$��V�:���;����?�>�D%@�󐘉�xT$5����S��%�n�V^�b�v2��Zy��C��C��Р��Ǚ�ҜSo�"!��~�\TPdC����yt��k����9�]���jҤ��q@����S>>>���3:
$M�4I%J��[o�et@1`2�d�X�s�N���"���ԬY3
.��GyD3f̐����Qń�bQ||��1@A�@jڴ�v�ܩ��L��@R�n�4j�(�c��ƍ�СC�r��Q@�dt��-]�T%J�0:���ҥK��<tbccռys�8qBU�T1:N�hܸ����t��Aխ[��8 ,�nܸ��;wꩧ�2:0�HY�r�V�\itPH��܌�P����ꪸ�8
.(f�T��o��F���(���YYYFG�oNNNz�g���jtpZ�jetPDPp���={$I111FGP�-_����>Qp���K�J�z��ap+��C
_JJ�����ʒ�d2:���)QQQ


2:��Ttt������<�233�����;C��Y���7:
�s0:P�����`�mܸ��(�"��<T:w�^xA�ֵk׌�(�(��ƅd�X���OK�N�:%�Ţ:��x:t��}�����6m��b��M�6JOOϵ��b��b��qqq��1111b�F�����BN�W�z�����z����3g��_��㍎(�nܸat`0
.@���� I�[�n�c___�2Wo�񆂃��{�o��V��ɒ���d}��=fq�{�n͚5Ko����|�M͜9S{��1:���+j„	�6m����ot@�}�v�.]Z/^4:
0�ظ]���y��w��8�V��$=���իWȸ�ɵk���o�{���V�
ԵkW�3F׮]3:�`+W��Ν;����<x�6l�A�)33��8�"�V�ZJKK��qr\�"�b��_,�$EDD�b�h��Œ��3g�b��t��9�رC��?�!www�����FG+Ts��ՅԫW/{�K/��.h�ܹ&�&M�σ"���Q���ך5k��(Bʕ+��իkǎFG����l޼Y�
R�V���^S�NUjj�����c׮]jӦ�
d?w��E����M�6j֬�BBB�a��5��q�����Д)SԲeK�i�F�gϖ$%%%i���j޼�Z�n�w�yGW�^�6fjj�fΜ�N�:�Y�f�ر�>��c����:�ѣG5d�5o�\��_5i�$�n�����L͞=[]�vU�f�ԲeK���O+W��u�W�^���L=��*Y���y�eff��.)))�6m��{�9��m���r�$i���X,�۷o�����e�X�q��l�:u��bц
򵆒t��%�?^��_�1c�d���9��ŋոqcyyy��}�Q{QPJJ�=��ϡY�f���3:���OV�U�;w6:
���g�rNF���*I:|�����T�jU-_�\			�۷�|||m��'�hΜ9��8w�/^���d�?>۹�ӧ+%%���իW�S�N�$&&j���}/S�Lъ+�ǟ~��*V���K������4}��rpp�;�#IJOOנA��}$��ٳ���TBB�f͚%�쟫1p�@%%%��\�|�233v�|�fͲ�""Iׯ_�����~]�zU����sYYY��/$I;v��G���ŋ�f�����d2�ym�\�����o:~����ܹs���V||�"##նm[͘1CTjj�\]]%�^P�i�&�m�V�t��e�9sFf�Y͛7��������:}�����s�H�W_}���T�8���xmذAݺu��Z�\��Ge��E�����E��b�G}dt` v��BBB�$���7�c�E�I�F����Xm۶M����%I[�n�1n�5k/Ĉ��ҩS�T�BEFFj��튈�ȶ{���âE��m�6���'O�����/_���X
0@��e��u.ԁ�����h������Q�
��U�VՊ+����K����I�+b���ۊAfΜ��۷k˖-5j�$iɒ%��߱c�Μ9#ժUK����#�9s&�y�`�?~\+V����9sT�B=zT��͓����ի�7nhϞ=����}���rppPll�����k-IM�4���k����>��ӧU�re͟?�=p�ȑ�ccc%Iu���q��f�x85m�T�?�@�a�Xt��)�?��(� \�b��}ݺus=�ٲe�v�ء'�xB�֭Ӈ~���{O��(�*$$Df��~l+JS���U�D	���k̘1�}�F�R�Z�d6�$I����5z�hU�ZU����ݻ�$�w����7J�&N�(9::�F�;v�$i�ڵ9�9r��T�"ggg�����w�g���(�������w�.�՚���vl��¦s�Β�U�V�}An�ۺ����w���%ɾ�����~Prr�:w�4}�������ѺukI�[�o��V�4z�hխ[�=���9r:tH�.��V�Z�>��S���U�|y����S�F�d2�������wb�X�O�2ES�L����z��w%���ŋ5|�p<x0�XYYY9�l�ۜ8qB�԰a�l�����f�k׶��7HR͚5��K�,�㺓'OJ�:u��G���v�nnn�����;�6l�ƍ���8����O>Q���${���{Ĵi�4mڴc}��7�r�J�.}�9mN�>-I�����n�:�9sF����O�>�?�a�9;;kȐ!��/�i�&=���JHH����Z�l))kx��)IR���s�r�˗/K�ʔ)�㜭�����'O�jժںu��7ont�"  @۷o7:�'իWOgϞ5:
0;\�?�)S����\��BBB��;�(&&�o���f�g�L�ێqs�����svvε���?�ɭP�f���Q�D	��;e�Y�v�n�:������Oiii���աC-_���o���w�O鏝;֯_��y���"///���)11Q�/_ַ�~��M����C
6�����T8p@
4�����������89�����5���u�^�p@1�w�^����.@�f�Z�k�.
0@����7o��o߮�^{M���������0cdd��a��Ǐ��gdd��M�ʕu��1�ݻWM�4���ݻ7G_�ɤ��,]�zվ�Cn�M�/ooo�8qBk֬���w��3777u��I�:uҁ�y�f͟?_ӧOW�n�$I�W��$͘1C���9�ضm���իW�{��y��B�
��矵g�5m��޾g�I�v��ڵӞ={4�|]�z�i�͛7W||�����ʕ+jݺ�����a�ʕu��q�ڵ+�%$$��[�lY�;wNIII*[�l�sIII�>��[�Ν���7n�����8ȣ/��B�>�,_3x���(�l�����z���۷+==]���3f��=99��s�m�V�4i�$%$$(##C���פI�r�t�\�R׮]����5y��|�Y��
��”���7n�ҥK���e�X4hР|�i�u��ɓ��Ν;�b�hٲeJMMU�Z����#�;f9rDT���լY�\�n֬��V���ȑ#y�ӪU+I�ĉ�o�>eddh߾}�uoѢ���_��W988�wݰ\<�䓒�E�eS��>��3�,�v�RFF�~��GM�0!G�ڵkK�N�8�㜭����[��������~1��O?�[�n�5k��Q��y�)��=d���@�������󉉉w�+88XժU�/����}�*  @����/��r۹����E��ٳ�����}wӷo_U�VM���SHH��6m������>�������1m�"]�vUǎ%I}��$M�<Y-[�T�f�&I�$�Z�J�ԫW/{�ƭL&�z��%��a�M�>}T�J�>}Z���W@@����3gΨJ�*�߿��oٲe��ﯴ�4ծ][^^^���U��R�J�����?�m'���aHH�j׮�s��i��
P�>}����m+��m�[���"�x�^��F��1c��@�Á�P��Z`��?f;��[o��v�کdɒ2�ͪ[��&M��H��,YrǹJ�,���u��I���rrr����Ə/I2���ÇW����#��l6+00Po������-J�.���H���[���rssS�V�4o޼{�A��7�TŊ�����tI_��������l��lV͚5շo_�7Nׯ_׺u�����{��?���*S��֭[��ׯ�5O�2e4w�\���S^^^rtt����^z�%͛7Onnn��k�NR�b�n�-l�f�Y�޽�<<<d6�նm[{���ڷo/WWWmݺ5ǹ�[��t��]S@��
*��W_5:
� ����,�C����dRTT����r=.JΞ=��;�B�
y޵�ٳgkΜ9Z�r�*V�(I:}���t颁*44��ȏ��h�c�[���'O�jժںu��p(*���k=���Z�l��v�jt@!c����l�R�E˖-Srr�233��O?iܸq���
�EM�>}�裏***��%ooo�������w���6mڨw��:t������(d\ܤC���ɓ'�M�6jҤ�z��!��*
0��(jJ�,��c�j���:{��Ξ=�իWk�رrqq1:y�>�������Eִi���k���FG��ڴi�.]�dtPȜ�P��9RU�TѺu���O?)==]��_ԬY3��������(�5j�!C�h�ԩ��W_}U�����\�r�>}���㕕�%��dt$@!�����3�(&&F]�v5:(D\���AAAA


2:
��ow�r�J}���/���|�ݻ�z��mt�AJ�.�ڵk�j�Rp�C��ggg}����_���q�ƲZ�F�����BдiS�L&����S�F��s�N�c�BF�@!������㍎�q�ƺ|���;ftP���p���`�hڴ�~���c�|��󓓓�v�ܩ�5k
.@�ct��I�&
Sff�؈��dɒ�Վ;ԳgO���B�O��a���d2���_�P())I4:
�ӬY�4t�P�c
Qhh������
;\�"�O�PTdee������\]]�c�խ[��8��ʕ�СCգG�h���8�B�ꫯ2
.@���� �cxHEGG+88���Ĝ��t��!U�T��(�O�z�҂4p�@�޽[���FG0���W�R���P�(����u��I���{FG<\�89�7��jժ)<<\�&M��Ç��(`�+(6.\��:���]�6mҩS�ԥKyyyi�ڵFǻ�C��v��=Ζ-[�r�J%$$(99YeʔQ�z�ԵkW5o޼�sZ,I��j����̙3Z�p����t��9�(QB�*U�SO=�^�z����g0BA�qLL����$I�ٳg�dw7b�EGGkРAڼy�L&�ё��Pl$$$H��֭�����װLy��o�ᄏ����w���k�������=и� IDATj˖-ڲe�ڶm�q���l6��^>|X���^�joKOOסC�t��!�Y�Fs�̑��W�g+�v�ޭY�fiɒ%���ҋ/�(5h��h�/׮]3:pO������@�X�Bݺu3:��Pp���\؎����ǘ0a�6oެҥK+44Tmڴ�_��%%%)..N�g��ƍU�D	�?��rV�Ŵi�t��U5m�T����jԨ���<xPӦMSbb�f͚u�V���_�vMo����w�.oooIR׮]5f�-]�T%K�,�����gM�4ц
ԲeK��
�����b��_,�$EDD�b�h��Œ��3g�b��ڳg�֮]+777͛7O!!!�P�����:h޼y����ڵk�o�>�#�-�	���#'''����aÆ�8q�$��72b�4w�\]�pA�z������K�p��Νk`2ȟ��,�/mڴ���u���0mذ����S_�s��y}��NJ��Օ+WT�Z5�����С����@#""Bo���|||4{�lIRjj��̙��7��_U�r����*44Tf�9�\�7o�ҥK������4�+WN�Z�Ґ!C��ꚭ�޶�A^�Y�j�$��_V�j�r�gOOO���hƌ����U�~�ls���j���ڸq��f��7o��C��\�r�ݚ��̒������}��׺t�ʕ+�6m�h��*]�t�q/^��ӧk߾}rvv��O?�aÆe�}���S�ϟ�ŋ����ުT�b�?%%E�?��<<<�b�
98���DN�<��]��bŊZ�jU����=�m=%)33Sڰa�Ξ=�%J�f͚�ܹ��t��z�纔�-^�X�7�������G�$���[eʔ�h:}�������bfӦM�r�ڵkgt��(ҬV��V����%IU�V��jռy�$I>>>�>�t��e���G_~��~��7edd��ѣ
ך5kr�?}�t����XOOOנA�4�|�9sFׯ_�ٳg�aÆ)33�~�'�|����Z��r�222t��9-^�X�'O��}�g��{�J�Z�ly�1�7o.Iڽ{w�s��֬Y���4%''k�ڵ�߿�����8歮\�����oZ�h�Ο?o����h���*555�5T||���Ҕ����˗k�������J���3gj��ݺ~�z��ʔ)�_|Q�N�ҦM���۲e����t����򲞳f�ҧ�~��'O��JMM������SQQQ�]�^��W_)55U���9�Tjj*��
EXZZ�jԨa/�Ň�bю;��
�XHHH�$����zl3�|]�xQO<�V�X�-[��^�$EFF��F�������%I.ԁ�����h������Q�
�իWۯ]�h�$iԨQ���նm����[��u�VI�w���0$?�믒$oo�;�Q�J�$I.\�q��׌3�}�vEFF�B�
:s�.\xǜ�Z�`��?��+*22R۷oל9sT�B=z�^s��U�jŊ���U���%I�|�M�>/��&N�(777͟?_���z�)
<X111JOO��
���k��l-Z����rOw[OIZ�b�$i�̙ھ}��l٢Q�FI��,Y������XIR�:ur�ak��=...jР���⌎��b�h�޽���0:
x�(�ł���nݺ��|�������zKU�T�������d�Z����7$$Df��~�q�FI�ĉ���#GGGըQCcǎ�$�]���w˖-ڱc��x�	�[�N~���{�=I�p'���Vl���t�1������f�F�R``�J�(����+,,LR�‡���S���U�D	���i��ђ����:�5#G�T�*U�����`I�ug�v��i�ʕ����]�E			�2e�����'�<�w�Çk۶m�����ݻW�J�����濗{��z���J����������޽��Vk���[�C�I����VժU��P45k�L?���1@>Y,����FG؝���`�%��)S4e���ᆱw�}W�;3�9sF�T�v�<�o{0���ɓ��N�:���ѣ��/^����u���r+z��y���t��Y�={VU�T�혧O����U@@@��
H�N�:uǜ�����/[{Æ
%ɾ�7�Y�������$)33�sԩSGu��Q߾}����y��)""B���k�%K�h�ܹ
Զm�t��
5k�,Ga��濗{��z6L�ƍS\\������'����


����m�?��]�|Y�T�L�c��l}ES�&M��'�(--�6���Z�jԨ�L&��Q�N�:ruu��jU����� v�*�}����-��JܼsŔ)St��AU�\Y!!!z�w��y�3��͛7���y[���Z�`+8pp(�ݩ��D����}}Z�h!�Ţ.�8g6�էOIR\\�����Sݺu��ݻ�����[�����s�{��z�k�N�֭Sxx���������?�X:t����o;v^���Kn_C[w@�֤I���k׮]FG�p��)*""��(����$???�ܹ��(���iV��������V�fΜ)I��j��$�/����;D䇷��$i͚5�ƶ�����}m���6l�:v�m������[�n���s���>�H��t��}���޽[�T�z��f�M�
$I{����n;��W~ԩSG�n[�p��	I9z��-�٬%K�h۶mrppГO>�����nnn�ԩ��̙��O�>JNN�����)/ו-[V������z[���hz��T�|�lE���T��^�u�5JgϞ5:��5n�����E�(�$�Qp����l�O�:U�ΝSZZ��L�"�Ţ^x�s�n�Z����DݸqC�.]҇~(�ŢA��f���JOOWbb�ƌcoONN��]N�<yO���Sjj�BCC����+##C�Ν�…��+��ڵkz�gԠA�'L����eddh��ݚ8q�$�}���>��U�V�$I'NԾ}�����}��iҤI�r�a�n^z�%I�����:z����u��mٲEo��V�5�)_��:w���+99Y��Փ��{�翗{��zv��Y�E˖-Sjj�jժ%I�wݸU^��]��������f�E���������a���m߾��x@Ǝ+www
6��(�6d�͞=���s2:����_�~ڸq���ۧ�>۹W^y�s���W�~����ۧ���l�\\\4|�p�q�V��v�Z���+<<<�X���
����._���]����[k֬��<������6mڤ�ӧ�CB�֭���o�z_����۷o��'�xB/����8����ӧ����k�<yR����v�J�*9��u���ݻ�>��3-Y�DK�,�ѧjժ:th���_~YK�.�to�ҽ�S^ֳO�>�8q�&O��ɓ'g�����<y���'��w�}������~���
���?��H�R���G��S߾}���	P@(p���Ȼ�����v|��e�j�ܹj׮�ʔ)�%J�N�:z�ԡC���U�tiEFF*((H���rtt����Z�j�y��e{�⭷�R�v�T�dI��fխ[W�&MҀ$�^8��o�bŊrttTzzz��$�٬ɓ'k���jѢ������� �l�RӧO��/gg�\�k���j޼������套_~Y�gϖ�l���-�ʔ)��s�gϞ��򒣣������K/i޼yrss�����_׬Y�ԪU+�/_^2���������g����#�u�J���oٲ�=�}/�����ڵ�������l6�l6�f͚�۷�ƍw�<y��}��ruu�֭[s��u�V�.]Zm۶��5#�����|`t<@:tPϞ=5d�]�z��8�|0eeee<�L&������1��b�$Y�V��<[�n����U�jU-_����W��s��ٚ3g�V�\��+J�N�>�.]�h�


58a����`�~lz�1����]�&M����<gϞ�O<���P����F��;\��IMMեK��G�Իwo��O�>z��Geo�������BBBLn���ɓ'�رc�@1�dt �Z�li��㣎;��8%K��رc���ۋNV�^�3f�����t�f�����
.P�xyy)))I�Eaaartt4:�a5j�!C�h�ԩ��W_}U�����⏂�?1��jt�b�ڵ��[T�3((HAAAF���RVV�L&��1�@�0�o��ft�{ү_?�(QBFG���v_}��"##���|�����
.�m�6M�4�� �7n�(55��(�p2:�͂���r�J�cxH-]���R?~�~��W�/_��8($111JHH��㍎�G�5RFF���ݫf͚0v�EF�=ԣG�cx���4m�T�d�Z
N�”����'*>>��(�{T�F
yzzjǎFG;\�"#&&�������c�=���8=��F�A!�ӧ�,X��j��ɉ���Q�Fڵk��1��Om@�a2�������,�#xh���F�@!2�L��O�����_z��7����E�V�2:x(�EJ�.]dt���h�\���R
Sff����BR�vm�=ZcǎU���U�Z5�#��b�(22R���2��F���P����C=z�0:�����)�P�jU
<X�F�2:��������nݺF�A!��?��ŋkȐ!Z�v��q�Թsgu��������???͟?_*T0:

��d��d�S_ggg͞=[�ׯ����u��b���FG��rtt��OII�֭[���W�^�ꫯL�;\�СC�]�v��bbb'�O��ٳgaF����I/����1`��-[*::Z�ڵ3:J�ӥK�Z�JYYYFG�lRRR�{�n�ܹ�:|��233�}^{�5��E����x�
}��w�Z�9��޽[�f�Ғ%K����_|Q>>>jР�I��RЫW����[�j�� �
6�}���c///5j�HݻwW�F�ԨQ#;vL�[�V͚5
L
����rm�v��~�mu��]��ޒ��]�j̘1Z�t�J�,Y�1��ײeKI����U�r�}֯_�ҥK��G-�x�9 �,�,��1��s��…�>��^҅4w�\�P��f���g2�d2�r_�~]������������pIҥK�ԫW/�*UJ�ӧ����s\��5���O�J�����z�g��5ϕ+W4j�(ըQC��ΪV����”���k�{�y/s�߿_m۶U�R�T�\9
<XW�^���mM333�ڵk���YeʔQ�f��駟�u-�~������?׵k����?���رc�n���)�^�3(&�IQQQ


��vl�V���g��ŋ5c�}����v�j֬��_~Y�G�Α'55Us���ƍ�믿�\�rz��gj�4���ժ��=��s�W��>��l����}��*S���[�����`�~lz�1�{g����%00P>>>��ഴ4�h�"׿�?���ꫯ����g�ي'ʖ-�K�.e��+�("""[��MVV�F����?�LӦMӈ#�� /ڷo�.�j����1۹=zH��.]jD4P@��P\�zU���:uꔽ-11�^lq���t
4H���={V���JHHЬY����櫯�Rjj�s�T||�6lؠnݺ��]P�bbb�������S��f�{۴i�d�ZմiS͞=[���:|���M�6)22R����Ʃ]���͛�J�*i„	�0a�>��sEDD(++�^tqsdDD�$i���jݺ�����g�iȐ!�9s&
Ň~����+""B��v�ȑ#z�gJ

y�S�N�B�
��?��:u�h���3f�.\����…u����j��ѪY��N�8��'*>>^�W�V�.]d�Zsݭ#66V�T�N�9lm���\�%ۧ=��yw
[QբE�T�zuI�O<�y�����…s\̜9S�jՒ$
>\&L��˗�8g�ҥ�����ӧ��T�.]4x��<����k�Сz��ճgO�-[�~�رc�Y����@A��G)�%��n��7�|#I
S���U�D	���k̘19�nܸQ�4q�D������Q5j��رc%Ik׮��\��$U�Z5ǹjժe�%G��$ըQC&��z��$I����q���������$)33��L�:U%K�Ԇ
��o�^�z�8q�RSS�V O������������;wNW�\������@A�� N�8!Ijذa�v�}O�<)I�ԩS���.]�H��=zǹl��[�L��lmw��_�����lc��ūx�����k�n�III9��f����d���!�z���ӧ�'�|R���
S�J�4{��<����M���̙c߽���5j�02(NF��6��,nm/YYYَs{ ��>��r�����tp�Y���>�@QctyԳgϻ��V��:���9��
�������~��iǎZ�|��{�=�1B�
z�s��^z�%͞=[�����mۦcǎ���E�*U2:�O\�A�ʕu��1�ݻWM�4���ݻ7G_ooo�8qBk֬���w��*[��Ν;���$�-[6�9�'��@qգG�#(@/��&O���� ͜9S����ŋ5m�4M�:U�[���_��1M&����t��a���H�j֬��Ǐ��?VHH�����(�PL&�f̘!�Ţ�ȑ#�Y�&���@ΏI@m۶�$M�4I			������5iҤ}[�n-I
Sbb�nܸ�K�.��?��b�i���/N�<io�]��$�ĉ9ƶ��EɨQ���k۶mjԨ�J�(!oooM�:U����6mZ��,_���?�\�Z5I�ȑ#%IC��������$Izꩧ
�f 4h�hԨQڳg�j֬it$P(�ȃ��`U�VM��������O���K��}��U�jմo�>����iӦj߾�>��3���h������]��cǎ��'�|R�����cl[[�-
�����#�h۶m6l��V�*'''yzz�K�.���SÆ
�=�~�5j���I����$i��3g�������"���jԨQ�?~A��ɻᆱ�ׯ��/�T�Z���
�رZ��Z��:gɒ%�N�:���]NNN������%If��޷t�Ҋ��TPP�������(777�j�J���˶;śo���+���Q��钤������U[�n͑c�֭*]��}�
P����{���+�S��\]]���ʕ+�{����/��WhL&�}���#����Z�x�X��������F�)<<\III2gax��W��������C|�~��g]�~]�.]���z��e뗕������{��cǎ��:{������ڹs��]��k׮�w�sww/���)[�����J�<==
N
����OOO���gk�=�U�\�l�nnn1b�F�q�1۵k�v��ek+U�����4g��>}Z+V�$�>}Z{�������z����…�۷�֭[��ܩS�t��)-_�\:tТE����f@JG7n�(m IDAT��o���]�vi׮]Z�t������#�
�OМ9sԸqc����yвeKY,-[�L�������O?��q��I�6lX����G�>������mQQQ�VHHH�����j֬�֭[�
*h�ԩ���������]���z��wU�L�]�V�:uRFF�ѱ�<�N���z�8��~222t��i͙3G�˗�?�͜9S�j�2:
(�p�4,��j��C�Z�l�&O��ɓ'g;����%K��رc��믫w�ޒ�իWkƌrqq)й����OǏ�SO=��+W���=�ڵkk̘1�ҥ�Z�h��N�g����w��8qttT�
ԿU�^]mڴQLL��N�jt4�=0:( �p�#G�Ԉ#T�N�����A����ڵ����T�b���Q�F2d��N���S���W_�����@Qt��	
0@U�T�����������d2�u+�ժ=z�|��2�ͪY��F��+W�d�u�V�[�N�˗׊+r[�����^�����'���D���G+V��lVŊշo_9r�%I;v�P�6mT�dIyxx�S�N�����#G�hРAz�����,www5j�H�ƍ�o����5��v'����GZZ�>���l�Re˖����ʕ+��{N�~��]�_�d�|}}e6�U�re��o+R�h{H�ܹs�����iٲe2�Lj׮]�c>|XڱcG��;v�(�ɤe˖�׽@qg�*�.�b�d2)�w��5]����	��"��Q�U4��Ek�[Db�Z�mͭ��t�P�mR%%�$��B�j������֥��DA���s����������yܳ���>��f��?{EE)000�cxآ��$�M�=�y��ھ}�^�u]�v͢��A˗/W��ڳ+���������L�,�?��Oݾ}�"�~��ھ}����%ITxx������<�\oܸ��Q/������M��}���v���t�1���Z�j�^}��l�+..N-[�TFF�Y�����nݪƍ��~��G���+JII�6?www��ũB�
�۽�0?��^9͝����-[j���9�����믿��|_��l1���Q�V��(P(�s�i�{-_�\���rww��ӧ�r{����U�BݸqC�.]����Y�СC5s�L���G���7�~��ʕ+��ŋ��ŋrtt4;~�$a�Pd\�|Y���JIIш#t��	���k���0`�233���ϛ�3�ɓ'���̙cz��i
8P�o�֠A�t��ieff���<==u�M�2��c�I�?��\�C�%ԬY3�b�.(  @����ԩ�u��
%&&�S�N�~���u������k���;v��ںu��U����L}��Gf�#F�PJJ��x�
�8qB���JKKӖ-[T�V-�9sF�&M*�����[!!!ڿ�j׮�;v(--M���S�ƍe0����8~Ĉjݺ���ۧ7n())I�;wVzz�z�����*�x��
�8qB�~�����#I


2���urtt����233�~�z�y�\��H���ǥK��7lؠ������[����Pd̞=[/^�￯�>�L���rppP�F���7�hذa�z�������	&H�ƌc��Y�f�ƍ�޽����k������N͛7��ŋ%I�-2�'''K�j֬���


Ujj�Z�j�+V�v�ڲ��W�ڵ�b�
�j�J�����²ߢE�X�BM�6���������o��$�ڵ�,v߾}���S����SvvvrttT˖-#IZ�zu��v���~9����$-\�PM�6����J�(��
j�…��Ç�8�~��Z�~�4h {{{լYS˗/�+���˗/k��م~�666/yyy�w����ղeK�?�l\^�S@@�$)66�l�o��Fׯ_Wǎ�����s����޽�?x�Qp���N���+�H����\�zU=z�Э[�Ԯ];}��'f��6m�$
2�b�����N�>mjKOO�$�,Y2gbn�ƍ��w�yG��������}�]I���l�:Ԣ��_�$]�vͬ��g��$u��AQQQ��_L}�kז�`йs�
,�����3g��`0�A�}�=�����^�7n��/n�fcc�1c�H���藺����I-Z��7�|��7����?�ש]�v*S��֭[�۷oK�n߾���09::���?�������keee��׮]�R�J�]�vy�G���,[�Lvvv�N�jٲe�Nx�%%%I�����w�ĉ��|�M�9sF���Z�x��+f���II�/����\]]u������T�R��S��"�{ۍ�����Ӣ���Y�L7������ׯ�v�ޭݻwK�S���+��cǎz���eoo_`�ݭ �_n�:uJG��޽{�g�<xP�d0rӤI�l�_z�%I�O?��u��9�3�t���˗�jժ���V�ʕ�;_n��������4w�\�޽[͚5����u��Yu��Yz����k����G;w����>}��D��$��G�(RV�Z�U�VY;
`%��֐׸9s�(&&F...Z�z�ʔ)c���*)�;Vxzz*>>^G�UÆ
s5�֭[f;)���HR�...���ׯg��n�ӷo_�*UJ}���/I��_4�|͟?_ժUӆ
���Q ���^��X�t���}�:u*�c]]]�۞����9
�mll���O+""B����O?�$???�ر#��\���͝;W���j֬�>��sIR�.]$I]�vU||���������XIR���su��}p��a0x��ūH�X�q׆+W������c��'
6L666���T�Z����A�7o.IZ�~}��?��e˪gϞ�6���W�^�v̕+W�r��:w�}��)99Y�߿����$I?����^(�������
ЩS����+88Xs����իu������ϱt���������U�-������ݫ���l��s�Z�j�
*h͚5ڿ�v��-{{{u��Q�ԭ[7IҦM����?+66VO=��^}��\��;v�E��/����k�<�<==��~�ڵK���Z��edd(  @iii�����cl�j�t��A%&&�iӦ�;  @3f���_�#F�n|��ʕ+u��5��ؘ��o�>�ݻW�۷��g�S\A�R�����~��I�֮]��;j�֭��[~�_n}��ǒ�Y�fi�f}�ϟ7���ʒ���s�:�-ZX��ڵK�T�N��P�شiS
:T������O��秗_~�,&?שX�b��W_}�M�6I�ڴic�����]
6Ԟ={�'Nh����O"v�EƲe˴l�2k��	�!���7���Ǻu�ELL�lllԡC��ѣG�����������F�V�$Is�ε�KLL�������Mm/���ڴi�.�{��JKK�q�_�UӦM����F�mjo׮�$i�ԩ���2����iӦI�^y�����ё#G,��4ib�V�����ɓ'%I�z�����L���ӳ?m�4���nݺ�O>�D��[�cTX��G���MYYY6l�E���N���N����o�߽{wI�…͎�V"���1<lQQQ���lz�1�����ׯ��j(U��A��W^1�ٳǐ��nؼy���7�4����/n8p�i��ի
�u��5���>0��ǏJ�(a�dx�.\0\�~���?j׮m�d����m6���ӆr��$�{�9CXX���6ܼyӐ��fHHH0L�:�P�B�$Ä	����/�$C�N�G�1ܸq�p��C�N��NNN�3gΘ��t��C��;� �P�fMÆ
�����7o�ڵ3H2t�ڵPr����y����A�a��.nݺeHLL4����4F�!999�ʔ)c�ѣ���ѣ�7n���ox�W�U�T1\�v����A��`0"##Mq���f}��NYYY�g�}�P�X1������������$ʗ/o�u�V���;�'���p��qEEE)000�cxآ��dz�����//__�֭�����̜9S�6{{{k߾}���"""4`��l�oܸ�6o�,����D����ĉ9�Q�X1�7N�&M��[�f��v�7nX�(QBK�,����Y����E��v�5j��~�)�1�+W�Ν;U�j�B�-��/��%I�|��|��l�kɒ%:qℾ��[u���b���H����b��O?��^
4�U�9�]K�-Zh���z�gt��1999���s��;;�L�>]m۶���-��7o�;vh��9sf���;�'����[�t��A���_�>�����T�T)�i�F6l����������׶m���k��t�Ҳ�����?�?�P[�l�(���:u�(!!A���j߾����dgg'yyyi�:p�@���ԱcG�߿_={������/.777���[�F��puu��ݻ��{�V�ZrttT������Q�F�f��[^�_^���Z�`��ի�%J���U����֮]�>�@�����Y�fe;>((H111�U�������3�h��:t�E����񫯾R���믿*$$Ĭ/��)  @����m����p;\�y������-I����r&w;vL5j�ȶ/&&Fqqq��F��[�n35��@���x�=J��@n�ЁT�~}k�T$�����@ތ5J۶m˶��
�ҥKe0Խ{wyyy�^�zV��G����V�^m��Pk���Z;�GA|||���b۶mٶ���+88X���rssS�J�������+==�!g	��g���O������-oook�Q�̛7O/^T@@���G��x��͛g��x�Pp��ydeei֬Y���S�ƍբE���O�V�2��8IJKKShh�|||Ըqcu��Q3g�Tff�Y�唒��%K�襗^R���M1+V�����,Y�����<x���ؘ���855Ucǎ����J�(!www�7Ns���h۶m*[��Z�nm��oպuk�.]Z����Z���
�������
>\U�T1�9r��^���@��v����0-\��t|��M%$$(!!Aׯ_WPPP��2335h� %%%�bϟ?���%&&*,,L��9?;c���JKKS�&M,��4i��{�jÆ
�ҥ�_>w�$jժ����Mm��ɚ<y���ݫ���[��}�ȑ���?U�reIRpp�>��#���g���/�ԟ�i���{]�zUM�65���ٳg5c�mڴI;w��}�����b�
IRhh�v�ޭ����;v�$i�ҥy����TRR��ԩ���h�ٳG111�W����ݫ��XI2��#>>�t�s�NIR͚5-r5�c�%��`��x<}�t��ǫaÆ:p�n޼�#G��Y�fڴi�""",�U����Ҵh�"I��.I�9s���Ҕ���-[�H�֬Ys��N����$yxxh׮]�q�v��!www%$$($$����a�P�y{{��b�������TEEE�ԩSjٲ��������7J�&O��J�*I�<<<4q�D���jݺu��1�cǎI��V�j����nr/&&F��x�b=��s��4̟?_������Ԁ�ƌ=Z�㔔�۷OQQQ:|��6o�,����r�JI��ٳոqcIRӦM5{�l�k�N+V���|�@�Pp�ÇפI����8}����߿��nh�m�ٳg%I>>>ٮw����s��eI����E���r�ĉ��<!;			m5j�0;>��:v�}��Y�޽�EvN�>-�N��ݚ7on���@�Pp��{w�0�l�0w��W۶mըQ#mݺU�W�֡C�4s�LEFFj�С�ҥK��tsEjj�}�mll$I���}�6cȽ�����g�CŽ�K���[ڷo�<==թS'թSG/���j׮���s�����bw
����*���())I?��,X��>��TH��8777%''k͚5rss�s.e˖Յt��U�-[֬�x�ǽ������]ǎә3gT�j�|ͱ~�zIҮ]����OK��9b�y������s���ѣڱc�ڴicj߱c�)?P8(�ȇN�:�ܹs;v�:t��ի�_~�$�$rתU+͟?_�ƍ�;C�ի�ʕ+���ԢE����Y�fI�sc��`�ٳgU�JIR�5t��%''[V$''�b(*�5k���k� �6lh��P��}��qyyyI�:w�*44Tu��եK�4}�tM�6M�Z���͛8�$}����ڵ����ԿS�������g�����BBB4h� EFF���[?���
$Iz�����l�����O�>�����h�B�7ָq�$I
4�s\߾}���Ç�gϞjذ�ڵk�E���A#F�0Ŗ)SF���秎;J��6m*IJLL����ּy�9yS��'jԨa�9b�رz���k�.��⋲�������M�&'''M�>���v��I�Իwo9::��_ԡC�L�����q�w�}W^^^:uꔚ4i"{{{5m�TgΜQ���Mg�.�#'>>��)���OŋWLL�N�:%Iz��gռysS�E^�J�,���͙3G[�l�ŋ���
hРA���4Ŏ=Z_}��.\����LIR�v���k����ݻ�Y�۷oWɒ%զM�B�<ȫ;v(((��iȣ��(Z;
(4_|�ƍ��g��ƍ��R�Ji׮]���r�J�;wN���jѢ�>����o{༡���y�֮]�۷o�nݺ5j�~��'M�8Q���j߾}��.]Z�v��ĉ�r�J���o�X���t�	&��
���`0X;	�d���1�a��c�ͬY�4w�\�Z�J�+W�$�;wN���8p�`���/::ZAAA2����c������wO[k'��ѧOU�XQQQQ����(����gϞV��GOqk'PP���e���B���9::j�ĉ6l�z��%I���՗_~)+g������ȋ/��!C�hڴi���C��A�V�
���x�:t�ҥKkӦM���_������kݺu�N�H8v�jԨQ�֎��Q\\�$�Q�F�֭��L
�C�xl<*;Q���@Z;
����DIR�ڵ͎�ԩc����Q�Fi۶mV���~k8p@aaaZ�t���w�.///իW��	�_ek��S���I�m۶"�vzz�������/777U�TI~~~?~����r��u\�"�����Z�p�$)<<\���Z�d�$)44T����L9�7o�.^����S[�=t��E͛7ϊ��?ŭ�@Q��o�i�̙ڹs�RSS���޽{�C�fq)))
��͛���\�rjݺ��|�M�,Y�g,Y�d�>��3>|X%J�Ы����Ç���Q�������pmذA�ϟ�����U��N�:����l�����Ǜއ��k������ҬY��b�]���;��SRR�d����K*_��)�bŊ���^�z���%o+��)AAA


�v�
�7�?~\����Z���/_���D���W^^^���.�<._��>}��ҥK���'Oj„	�}��:v�(IJMM�?��O�:u�w��EGGk�޽����������իW%IZ�|����4n�8IRXX�iwI�y����٥. IDAT��ׯ���>�L)))f�y��Y�~����ԤI��&M�h�޽ڰa��t钧��&
.@�c�@���(I�S�N�Džm���t�jժ��>�H�ʕӌ3�r�JEDD�
.\�S�N�r����U�fM%%%)88X'O����5d����V���'�B�
�;w�"""�e�S�Ŋ+$I�����͛7�n�:���h�ҥ


2����]+$���C���/���i�;wJ�j֬i1��m�Ν\)��N�n��ڵkg{\�v��!I3f��T�"'''�7N���Z�r�)n˖-��q�Ʃnݺ����/����_��y�f���y�U�RE%J�0�Vq��5S�qG���(�����?�����������{���b���wv�;&�NAɽ����b((���:}����٣+Vh�������.@�ѭ[7k��$��`��'�q���S�j�ԩ��?�P~����wv((���$I5jԸoܹs�$I/��Y{�����[�j�L�]]]%IYYY���ÇkҤI���S\\����k���_���rpp�U������yg���˒$�>c�1��dee�ĉ�t�.]����]�����ҥK������ҥK���0߼ys}��wV�<�(�EJTT����'Ttt����\666i��������:m۶U�F��u�V�^�Z��̙3��C��K�.\?��-�i���L���r�Ʊ��������
x���ڪs��駟$�)N�P��ʕ+�r�����M�����O?mj;|���{�=���+Z�vm�r���V���pIR�:u���PIR�
oz�
*H�N�<y߸J�*I�<h�n<vss���������ܹs�p�B���G׮]�g�}�����ׯ_7�ewn�=��-[V�t��U�>c�1��y��w%IǏ�իWu��q�ڵK�������'�|��#G�w�޺u�&M��=z�?�����Qp����DIw
.�;~�6m*I�6m�.\����M�:U����ܹ�)�e˖��ɓ'���úu�>�O>�D�Լy�<�ݩS'y{{��o�UZZ��W�.///I��q����Y�LIҪU�����S�N)$$$����5jԐ$%''[�kl3�p?=z�г�>k*��ITT��t颾}�jѢEf?'

Vt�ر�bbb4r�H�9R1111+��(\���Oe˖��Ç��믫Y�f���o��)�O�>�R��Ν;�����Q�F�߿������J�*�߿���ӧ�$)$$D-Z�P�ƍ5n�8Iwv�02Q����cǎ���X�矫y���֭�J�.����nmc���z��ؖ������^o����̙����lcf͚�޽{k�ȑ�9s��+���O

.�dԨQ


ʶ�
Ә1c4z�h�����9C�{,�9bv�0�-[V���S۶m���";;;լYSS�LQ�Lq...�7o��u���˫X�b*_��z�������5�k���i„	z���eoo/{{{U�VM}��դI�Lq�G�V�ʕU�X1eff�w�#F���_�J������4i����|�wvk�k�NNNNھ}�ż۷oWɒ%զM�<�'��˗u��
���hΜ9�S�Lѐ!C�hʔ)���
���t���%$$�������O&EEE)000��ǝ���$)>>ެ===]]�vU۶m���oK�f̘�~�A˖-����C�xRDGG+((H�?��{ ���z�͚5Ks��ժU�T�reIҹs���뫁j��V�Փ��;�µs�N͞=[˖-�����V����T�<yR��w�%��{�iʔ)
Ӑ!C
%�'N�_�~�[��fΜY`��{��O>������.�#����T��8�7o�.^����S[�=t��E͛7ϊ��O�>�X�����LmQQQrssSϞ=����;}��Z�h���$}��:w�V�X���d�X�B�AC�է�~�J�ŕ+W4z�hyyyi�Ν8p`��m0����Mx��v����,���kÆ
:�����T�Z5u��I���f�iii�;w�6nܨ��]�ʕ�k������^��
F���"%%EK�,�K/����˛b*V�(ooo-Y�D�z�����C8k@A����$��dg͵Ka_޻�r���Q'N԰a�ԫW/IRll����K988X9;@Q��s�)))I5j�0�yzz�cǎ�2e�V�Z�o��V˖-S�Νt�[�n)<<\����Mm���z�
l��;w��o֬Y��

�����o޼���%$$��


�$effjРAJJJ2Ş?^JLLTXX�lms�tt���JKKS�&M,��4i��{�jÆ
�ҥK�@�x��5d�M�6M�4t�P5h��Yw[
>\�Z�R||�6nܨW_}�@����5j�(�<yRo���
�ڵk�K�.U�ڵM�)���A�@.�X�B�*oooݼyS�֭SHH��.]j*����TRR��ԩ���_ժUSrr�&O���{�*66V������7�����˚5kZ�`l۹s'�z�v�(
؉��
T``�����ٳU�n�<2�l�R�Z��G}��	�+))I�F����Ν;k������Դi�����ݻ�Z�n�RLL��~�mIҗ_~�3f�xqn��Q���@�g,LxP{a�x�����TEEE�ԩSjٲ�������o�q�FI��ɓU�R%I����&N�(___�[�N���9�s��1IRժU-�����b(���Ҵd�͞=[{��U͚5բE�|͵aÆ+N�t���+<<\��ߴe��l�Rҝ����p��ɩ@֓�M�6��W�=$I���ڴi�ڷo_`k��ck�ÇW�%�3f�{��PFF�Y�ٳg%I>>>�6��E'O���:�/_�$���X�ی1�G����lll,�o޼���zK���zꩧ4a�I�����9;;�L�2�ӧ��]�f1>==]��������z�)���K�ϟ`>���;v�<<<T�D	���kܸq?�j�Ƶv�ޝ��<���o�R�J2d��U���[�*)))߻D�Eff��O���իk�ʕ�={����M���y�f�8qB����-::Z�5����<<<ԨQ#EGG����(��ݹ¸�Ea�hq��m۪Q�Fںu�V�^�C�i�̙����СCեKIw��y?�����7ވkkk��c��7�}��׿n:�����ᡙ3g���t�)�.�����͛g1~�������H�رC���W�2e�]3##C�Z�2�Y����ɓ'k�޽Z�~��Ϣ��i\���>��xdff�e˖zꩧ4~�x���GO?��������^{M�4n�8�;V%K���W�&M���������ի�������988�Z�pPp�K�����񑏏������?h�����LnnnJNN֚5k����5ʖ-�.��ի*[��Y�իWM1���޽{u��!yyy��O?Մ	4d����:z�T��)S�hҤIZ�f���N���Ժuk���+((HgΜ�����Ge�������
j֬Y�S���?��jӦM���Ѐ
$O�Z~~~��ҭ[���������^qqq�V�Z�zP�����;����7�b��/jժU��o
t�k���f��t��M#G��ڵk���_����g��DX�ԩ�������*--MիW����$����תU+Iw��y��Qݾ}[���y{{kРA�X�
(gϞ5�ըQCҝ�����f�<���+խ[W>|�$)==]�g�V�5���1c�H������3g�T���eoo�&M��v�X�bE�k���H�/^�z��x��U��i������ӸV�6m��R���v��@�ѵkWU�R��i(�<==�T��$yyy��~S�z�Ըqc���Y�̛7O�����Itt�Z�n��+��*V��֭[+::�@���.r�O�>�<y�BBBb�נA��}�j�֭:|��z��i���#F��˔)�˗/���OnnnZ�f��6m�m۶)11�l^IJLL�$5o޼�O`E���7�wqq1��]��齳�s��۶mkvܬY3I��?���'NH��'>�+!!���4��h�"�<�����̙3
�͛7�駟Z;�<+_��6oެ�� �n�Z����ݷ�������[�����+W�n�:͚5ˢ/00P�
ҕ+WT�t�[<v�����x���?�5���4a�=��󲷷�����U���}�jҤI���%K*""B���rssS�b���ꪖ-[j���f�S�=Z�+WV�bŔ��)Ij׮�����}�v��o߮�%KZ<!�h��ƾbŊ�j|����V���z�xcLN�^�jі�<sZ+::Z666�x�z�^<�xrdee��SǎU�Z5-X�@�ʕ�vZ�����_]���?ԭ[7}����M�6���o�Q��\�R�L�w3�c@������#�ƹ��j�ȑ9r�}�ڶmk�Trgggj�ܹ:w�*W�,I:w�<�����)�'x��޽[�Z�2�����$լY3�1���:v�Μ9��U�j~Ƶz��]�vY�����
N�nݬ�����ŋ�;w���Õ���V�Z)&&F>>>����vz��A�i���jذ�F��3g�(99Y͚53۵� ,^�X:t����E����:t�ŋ�_�~�.(X\1}���w�}���(���;����(����gϞV�PԼ�曊��T�
�A�I�z���Ν;+$$D���


Uݺuu��%M�>]ӦMS�V��y���ϸ�ƍ���ڵk����Ο?�'N�E��N�_Թsg���O�ݻ�l�S�j�֭�ѣ��|�Mӿ��T���ݻK�-ZT��]�pA7nT�nݴlٲlc���q�F]�pA+V,�@���<6���e���B�7'����8q��
�^�zI��$�/��R5@�W�B5j�Ȭ���[��׿r3v�X�Z�J�v�ҋ/�h�����ӧX~ƵΟ?_`s(zBBB�d�=zTeʔ�v:������g������S)0�ԩ�BCCMmݺuS�J�ԫW/����zK�.�tg'���t�R
6�@����	�ҋ/��!C�hڴi�6m���
X;-@�z�j�������*W��1c�h���-�+U��v�ڥ�Ç�jժ*^���z�)���*..N���/���k���6��رc9����h�ȑ9r�o����'���F���S�U�^��*������+::ZŊ3ko֬��9R�76l��٫_�~z��,�)��hc���x�;Q���@Z;
@1�=�o{ٲe�v��<�-Ieʔь34cƌ<��k{�2eԬY3}���]�q7j�(m۶-��Y8���0-]�T�Aݻw�����իg�L��+S��>��s�w��j֬��Sp�7n(&&F;v���ٳ��N�������IIIy(k�����m۲mOOOWpp�������J�*���O�ǏWzz�C�ȿ���m�VTff����:uJ��y���ԟ���+pqqQjj���yD�(�������m�4
ռy�t��E��z�衋/j޼yV�Ȼ�3g�̙3�6m��S�h�o���իվ}{U�^]�/��o����d��������)>q���)t�D��=.]��	&�u��jܸ�z��
6d[������P����q���ر�fΜi������=GJJ��,Y��^zI�˗7�T�XQ���Z�d�RRR
�l�������`}��:y���X#G�T�Νe0����̙3
�����S{b999)--��i�<*n���U�VY;
O�e˖Y; ���Sxl]�~]Я��jj;z���}����L
4HIII�����+""B���
��m�ϿZ�~����ԤI��&M�h�޽ڰa��t���
xxF��={��ҥK���v:�����[o���}
N�2E���3f��S����k׮Y;
�G�p���]��k׮�N���C$)**J����*U�����޽[���f;PEFF*))Iu��Qtt���٣��իWO{��Ull�$)>>�4&>>�t�s�NIR͚5-�6�c�G����V�\�F�Y;�U�Z�'��bΜ9z�T�dIk��-WWW]�~��i�<b�Pd���X;`e��޹j�����mٲE�4n�8խ[W�ԠA�?^o���Y�ƍ%I�'OV�J�$I�8q�|}}�n�:����ֱc�$IU�V��sww7�@���߯y��i�ԩrtt�v:EBll�
�w�}W��v:�j֬�������#
.@�accc�@�d0��+JNN�$կ_߬�A��gϞ�$���d;�ɓ'���˗%I...}�6c��u��
-[�L_}�����T�V-���/���vjV�g����C��ɓ��N��T��*U�X;
�G\�"���W����N�*::Z�V��v��ޝ+�;[�9���*���h���޷�8����E����Txr%''k��ٚ3g��\��N�:i���jժ��S+N�<��;��W_�W_}��LP�(�EJ׮]յkWk��	u��M
.��g���?��C���_6�:t�"���M���Z�f�����Vٲeu��]�zUe˖5�z��)�x��5v��څ�;=l˗/W���U�|y
<Xo���*W�l՜��_�U�۷����/^�bŊY;%��|\��M�6��O>�D����u���'�X��0>n�8=zT�o����/��B���4h�)�xC�ٳgMm5jԐt�	�2�c����4h`�4�]QQQJNN֤I�(�������6m�5k���������;\�ұc�r��133S�۷׵k�����^���9�G�>�܊��Q\\�$�Q�F�֭[A��$)((H���Μ9��}��7�o߾ںu�>��={��988hĈ��2e�������󓛛�֬Y��M�j۶mJLL���711Q�Լy�91��Ο?��ݻkΜ9���v:���iw	k[�z��S�$�+WNݻw�vEV�2e�`�k�s�p��F�RPPP��[�nյk�$I׮]�֭[Rf��}��q����i̘1=z�BCCu���P����+>>��������p����t��*^������H�YQeɒ%���@����X�bruuU˖-5�|�"�ѣG�r��*V��233%I�ڵ�����o�n����U�dIӎ���駟ֵk�4h� 
I7n�PTT�ٮG(z(�ȅm۶ݷ���_]�[�9=��9>Hzz�������/777U�TI~~~?~����(K���zJ&LЦM����hկ__ҝ'�����U#G�Ԛ5k�g�m޼YӦM����Y\۶m�z�j�ٳG�ׯ�$9;;+00PԹs�L��Ν��ճgO999����x��
׶m۴p�Bk��X���������͛7��[o�����M�������YeʔQ�>}LE�w�OOOW�~���쬧�zJ�z�����Ojj�Ǝ+�(QB���7n�222��;�y�g����i�F���*W����ׯ�b��L���4a�ըQC%J�����7n�9s�<��ٳg5n�8U�RE}�{wVU��q�
�䀙e�9\gM���RoN�h��h9\s@����s(�
�+�f��b��U-5��(S�8%�ip�j"
�0�E IDAT�?|8yd�����<�����)����5d�w�.�x��Tp!"""""""'''�����aϏ?�H�
�2e
O<������5:�#g���$$$пSۀHHH`���&�GI���qrr�/��ڵkdffr��YfϞ
`*�(.��r���ڂ��pttdРA�:���Z�h��ѣ�4i�.]2:�cc�ر���������ܹsY�f
ݺuc�ƍ$''s��U֭[�;3�5k֐����A`` mڴ�?��s���T������ٳ������'=z� 33��re.gggv��Err2�/_f���L�0!�8u�T�Ν˩S�HKK��:t���~���;6++��;w��S�V-1bgϞe����GGrr2o��?����QDDDDDDD�Tp!"""""""��K�.��ӱcGZ�n͠A�˵P#99___\]]iݺ5=z��ߟ��4S����v���233�֭���t�ڕ���\w�����?ӱcGF�U��y���/##��>�����ӱcG�/_@bb"ӦM�m۶8;;��Vu-��}�_�ڶm���w�ϟo�y"�k���d��帹�Ѻukڷo�СCٲe��IIIlذ��^z�J�*��+W����6l )))�}�GS��%�������;v�E���ۗ��*T���#��Z���5k!!!���GHH�f���ήX�1���'���L�4��(����p�=JJJ
s�����+++N�8Arr2|����9�o۶�;vp��M8@͚59w�,�s�A˖-9r�����?��m۶�ڵ����b�Y���ׯϩS�HNNf���|��W���lYYY��+V��믿��͛$%%������o��"66�
йsg.]�D`` ���̝;�g�}6�qb��aeooϦM����5:���������
.DDDDDDD�r��
���۹v����8q�iӦ�蛖�ƨQ�X�v-���;����������s]	�NYYY����G������롐����d*(L��裏&99�k׮�r�JBCC��?�IXX���$%%�m�6|||L�rF�Ixx8���$&&��_�u�W???V�\���IOO'99���H�͛g��7�|Crr2mڴ�q�6mڐ��LXX�=�)�[&O��ĉiذ!vvvXZZ��舛�AAAT�Z���l޼9������Ø1ch֬Y��#b4/^̺u�ؽ{��qK�.�iӦ���1~�xRRR��O�_�>������{\�|9�x�v튍�
mڴ1l޼9�9�������y�(U��5b͚5[΢����Kݺu���7�lq�ʕ<��lٲ���r~~~$$$0z�h���8{�l��U����G�e߾}����|�s�}�m۶%11��(������(��������<J@DDDDDDD�8q���T�¼y�hذ!���̘1��������DGGӸqc�M�F�ڵ�����ӓ��pBBB�ի��#""����?��S�^=�֭@�z��W��N�"""��^z)G�Z�j`zЦ0�+**��?��5j�n�:�/_��������/��r�ʬ]��+V����ܮF�̚5�g�y�U�V��ݻ�>}z��1�A-___���HOOg���xyy�q�F��hذa�k�n;p��{����%""�;�N.N���������^bs�ƈ9E�ЧO�w��;��ѣGM!K�x��Mߗ+W��s�=g��L�2y��ܹ���m�p�̙<ǜ>}���'7���Ŗ�(s5n���O>	pׂ{�
FXXaaa̜9��ӧ3~�xJ�.��8KKK�ϟ��%oG���͍�ݻ���`t�{V�|yn޼it)�p!"""""""<'''���ڳWɝ>}:M�6��ښf͚1cƌ�ݹs'���ԫW+++jժŬY�ؾ}�]�����n��gϞlݺ5�q�
2[մ0�k�ԩԭ[�C�7o�dڴiԨQ[[[�|�M�C�r&O�L��ձ��5J\�v-�|�'��A�>}���0�_��'O��:�T�fM�>""""�`[�t)6lP��}`oo�k���U�Ɨ*e��_vaB~��V���NE�Y��n�,V�����ŋ	��_&99��ӧS�J�g$)^���+]�t�y��<2^���ADDDDDDD
A;\��������#%660_�Y�f9��?WW�\�믿�;WRR�}�,`��9��޽��ׯS�lY������.���뛾�}��ڵk����ᦢܟ�ϙ�����?~<�g��СC:t�e˖1l�0��ݱ��3��r�
`��m���>""""�`�V�����~�����M��w��m�l5k���ɓ�;w.ׂ��t?�P�C�eȐ!,[����_�:u�y��袘����[�nԨQ�͛7��<�ʗ/OFF��1DDDDDDD��Å�������<�"""̾�����e�:��0��s��ׯ�{�믿&---�>7o��믿�ў��"ɝ[�r�����ni�����r���M�t��Ν;�c���}��yRSS���Ņ/��2�r˝���x*""""�1b�&==�}��1j�(���_www~��g222�������‚�;[���+�sũS�Lm�k���‚~��ѠAƌc:vg��ܛ��d�.�۷o�|��'*^7n�0:���������v��GJ�j�8s�G��E����G������Hll,���8::z����,YB�6mr?x� �ƍ#$$�>}�[n����q�����Q�z
��WWW\]]�����o�e�ڵ,\��޽{P�bE���ILL�bŊf�M}DD��i�&�#��H>�y�Z�je�����رc�3u�T�l���i޼�ٱҥK�;`Q��\O?�4			ԯ_�5jC�jՈ��!88��/� �W^������L���OLL�駟6:��������<�Tp!"""""""��N�:q���ϟ�ܹsiРǏg���9�:;;�f��O���ɓ�[�.W�^%00����������ˁ��Ο?O���9}�4Ǐ�o��[��5K�֭�Q���ќ>}��u�K�
*p���l�B�޽�����˫�w,o��?u�}�ٳ'/^d�ԩ���P�n]~��7�|nj���Olll�Š��XSy����FG�|lݺ���F�J�pwwg�̙����9�|��<x�9s���W_q��Eh߾=s�̡I�&Ŗ�$�׿�����9�<7o���Ғ�{GGG�?�ɓ'�S�ݻwgʔ)�v=�;KKK�v����өS���q�ݲe˨U���1DDDDDDD�Tp!"""""""�����_s��9��o�!C��g��;ƠA�̎���1a����"777M+�����\�oaaA����&$$�w�}�Xrw�Ё͛7�x�b/^����0������<OOO���r�4k����/��޽{���2k����]�v��$""�pww�����""�����|_��bŊ���.��p���-bѢE�[�➫�����߬m�ҥ��[������J�����DDDDDDD��Tp!"""""""����<���۳b�
�������~�:�j�bРA������ؘ��-[���V�\��ݻIHH�L�24k֌Q�F���9i�$�.]J||<7n�`ǎ888��k�囵{����c�ƍW,�'L����%;w�$%%'''fΜI�n�
r�
�0���n��iii���Q�T)�������Z�j�k׎����v�҅ŋ�o�>�z�-���۷��e�ҩS�{�b�����ϒ%K��!"�4n�8ڶm["�~�:���
6,���%++�����U�EDDDDDDDD0Yy-�!"""""""R�,,,

2�n}���G�=�R�
!!!�~����.)˗/gժUlٲ��0�ŋ�ի#G�d���'���g�}��M��ZD�.������kp2)�M�6���G���ݻ9v�vvv�rN)���]�v�u�ֱl�2n޼ɩS����4:���������<@�Å�������<RڷoOrr2S�N�s�Δ-[���X���x��
N���5��6x�`�m�FPP�'O ((GGG
dp:)���`�#�He?�_Rf̘�g�}Ƈ~�ܹsKt.y�EEE���������d���3F�""""""""��~b$"""""""�����ر#-Z��o߾DDDP�BF�ap��=���7{{{f͚EHHqqq���¬Y��
�����C�Z�j̛7��>���Ǐ籗�����nB�hҤ	�v�b���\�p��+W���iiiFG�+�p!"""""""��ɓ'S�zuv��ٳgIKK�g��u��>�J�*1Wkn#4o�|||3f͚538�������cDzn�:F��޽{K|W
y�8p���k:u�-t��:t�+�ر��qDDDDDDDD�y�XZZ�����Q
�a�m�+)INNNDDD�䖓'OR�~�\�s��!Z�j�o�q?��;+++>��SZ�h��U�>|�ё����mt._�����K��y��F�ɗ
.DDDDDDDDDDDDP�.{��͵��ȑ#����q�F����ׯ����^0 �H�i֬���?�2e
�����M
,##�R��+�Yrr2�����?���˗7:�}��元�FG���""""""""""""����x`v�ػwo��)))̜9�>}����H�*Upsscƌ�����"�o�ܹT�V���h���C ::�1c�P�jU.]�dt�ß�ɀ���aǎ<��FG����ρ��!"""""""���y`999���dt���իIHH����������ի
L&R<ʖ-ˑ#G�С��Q�����_|Aǎy��c������M�����]�vJ�ƍ��#"""""""R �OUDDDDDDD(�6m�����"�ڴi��D��]��Eff&+V� ,,���8����]�6={��W�^�q����̪U�عs'���xꩧ�֭Ç����,ǝ����ذa/���*U2��\�2NNNlذ�7�|�r�ʕ�
�O,,,�� ���8V�X���~J\\...�ر�Ν;ci��T�-bŊl޼��-[�0e˖5:���������
.DDDDDDD䁲e��l�bt???֭[gz���Ndd$���ܸq���_ZZ�F�"::��7..������������o�����dڴi��X�6m',,�޽{�󵋈<h���k���6l�F��o��ё�z��I�J�puu5:������q��1DDDDDDD�Tp!"""""""���,�#�����y�f|}}qrr"==��۷����ƍM��Htt4�7fڴiԮ]���X<==	'$$�^�z�c�
�аa�Y��8��y$���3`���쌎"�P�V-jժet�BFF��DDDDDDD�Tp!�fɒ%�߿��"RBڶm˸q㌎!""""��7�x��""A䱕]`p���JZ�ҥ�~�:AAA���СC���C�>}��o�ΝxzzR�J�փ��f͢W�^l߾�^�z���ɓԨQ#DZ�5k��y����Aq@�,
��V%=�Q�9‹/�ht�"�ӼH!>|�M�6CDJ��M�8|���1DDDD�1�i�&}�C��!���㱵��СC,Z��~��@jjj���?WWW���L_�E���k�y�\�@�r�r�n��#"����d������O?G�D�+W���L�c�7�z��Y�fF��'��B����;AAAF��b6p�@�#�����c$((www�c��c��>��`�ݹsE���sG�;u�ܙV�Z�g��n��ѣG�'00�1c�лw�B��۪�ׯ_�x��׹���ݖ�G�Q��	&�`��y���H1�z�*���ë��jt$y̕��Ç'11����ٺu��DDDDDDD�
.DDDDDDDDDDDD���WWW\]]�����o�e�ڵ,\��THQ�~���������c��T�X���x�X��ٱ�8�ly��۳�~&L��g�}ft�Gǎ��Ϗ�>�+++�z�-ƌC�
��&������ceeet��v{y���BJ̒%Kؿ��1D��ڶm˸q㌎!""""""""b��={r��E�N����u����~��ں����Y�f
ӧOg���ԭ[��W����qrrb����*���8�<իW�~��������"66��G�QS�lY|}}quue��t����HRDQQQ<���4h�ooo�z�-ʕ+gt,�Giii��ٓ������ot�"��%*{����iiiL�8��k�R�T)Ǝ˜9s�|�2cƌ!44\]]����l|rr2ckk�k���G}t����ׯ3o�<����x�"���8��3gbgg�#wQse�cǎ1q�D<���=}����LJ2eʘ�u�=���d֬Ylܸ�s��accC�ƍ��?����Ë�������,\H�9|�0�6m�o߾FG�Bڴi��/�EDDDD䖓'O�=����@DDD�c
ҧ$��.88�C�ЪU+�x�{:�����f��xzz��兗��ٱ�W�.h�!C��g��;ƠA�����1a���
*p�����ptt$44��_~��{��c�쨨(ڵkwo-��ѣ}���Ã��(��퍎$Eиqc~��Z�li�P�<����O��O?���ŋ��S"Ǝˊ+L��ΝK�Z����nU�[�KKKV�^�c��5kL�ٿ??��3*T�u���T����~.���'���|��7XZZK΢������˗M�\�|9����w�:u*���uZZ��СC\�v��'�9VDDDDDD�*�����NPP��1D��ht�λ��޽{��~;r�~~~lܸ���,���G�z�x���&""R �߽nnn�*U���`bbb�V��ڵc���W�lYX�r%�w�&!!�2e�ЬY3F�E�:uL}'M��ҥK���'--
�.]��x�b����[o�e�u߾}�-[�N�:��1��ŋiԨs��a���FǑ"jժ������/�`ǎ4i���8%"<<��G�R�^=>��c��}<<<x���9q�իW��ۛٳg�c��m�رc;v$""��r��9,X��y�r�s��DDDвeK�/_N�ƍ9u�#G�d׮]����9�2W���Y�f
�>�,~�!~�!_}�+V� +++�n!���믿��ٙ��4֯_������*����ݻ���������޽{��Ph)))̜9�>}����H�*Upsscƌ���ODD������Օ��@<��ٸq#cǎ�\�rE����ĉ	

����|��w����[t�ܙ�[�r��a���ʔ)���;���/^4��x�"����
�t���yKD(U�V��ӓit�Cjj*�W�f���FG����ˋ+V�n�::v�ht��t�R�6m����Ǐn}��O�_�>������{�]n���O׮]����M�6�ƒ͛7�9gpp0��9/���J��Q�F��2�-gQ��nݺ��ۛv�r�J���
O.\���			�=���,Ξ=��X#��BDDDDDDD:NNN899ぷz�j�߿��m��$$$�z�j����Ƚ<x0�+W6�e:((GGG
d`2��c��Ѽ�⋦�t�x�Νcʔ)<�쳌=�����Hr1m�4|}}�ׯ��qJԋ/�h���B��{��}�2e�߹sg��m۶�̙3y�9}�4�j������]��[�YQse�ƍ����'�����z|||���',,�w�}�&M����Irrr��DDDDDDD�R��""���x*W�lt�ǥK�X�d	���'%%�ڵk��[o1m�4�����Y�j3|� IDAT;w����O=�ݺuc�������wd�ׅQ�9s�=�����b�Ν���жm[ƍ�SO=eꛔ�Ć
x饗�T����r��899�a��|���m���<,J���^�������5k��o��&!!!,Y�;;;�Ӊ�<KKKV�\��˗���0:�c+++�]�v�t�R���S�reƏ��o��3�<ct<)aG�eذaL�2�ѣG�������neeU��J�?��]����/$&&�h+j΢�u��0
�gq����ҥ[�laժU8p��ӧ��ョ�'�F�*�yDDDDDDD��p!RB�����o�MÆ
)]�4���T�V�>}��m�6���7�+���Ǐ3i�$�7oN���)U�*T�e˖̘1�s�����~�)
6�XI]������΍7>|8۷o�ڵk���s��	S������5jk׮��'==���8?~�]6(����ۛ��PRSS�v�۷ogذa\�v���o�!99�6m��ߦM���	+�k���y��xxx��ハ�cƌ�Y�fF��o�4iB�������̤y��t�ܙ�W��a�Ν;nj3Tl�hҤ	+W������(�~��-[�0i�$���{�<�P�fM��2YYY9�222�-���B�
:����Δ)S��?�8qb��!""""""R\�ÅH1KHH`Ȑ!�ر#DZ.p�����K\\\����qpp0 ��+55�w�}��˗�x��ի������7�Ǐ���kk�b�Ĉ�v.)AAA\�p�*U�0o�<6lHdd$3f� !!��o`` ���4nܘiӦQ�vmbcc���$<<���z��EDDD�;[f��Ι�����d�^z�%�?Ό3����	�������Fvہ�ݻw�����<H��(J���;���F��ǐ��%�ƍ�y��4i���8bKKK�.Krw#F��s��|������Ӵ�À�����养�;���4mڔK�.�`�|||pvv��+�|%1���YYY�:u�z��P�vmbbb�gРA<������)""""""b�p!R����Һukv��A�*U����?�����ܼy�'N0w�\ʕ+���quu-֕@u���t�����x뭷���IHH ==�˗/�s�N�BVV>>>���k���ߗ|٫������H�srr2�ʯ}���L�>��M�bmmM�f͘1cF���ܹOOO�ի����j�b֬Yl߾�د�8�:u*mڴ��ښ�M�2}�t�k8y�$5j��1>{���>""""""E1d�[��3�<���?QQQ�oߞ�������رc�3u�T4h���i޼9���8::���C�ҥY�`A��+���~�i�ׯo�Y��ɓ���[[[S��+��R<#""""""R��ÅH1:t(111���+lٲ�'�x��x����1c�z��]�v�ݻ��˗�C4�˄	ػw/�k�fӦM���fǟ|�I^}�U^}�UƎ���+;w�dʔ),\�Р�"""""r������ЬY�}ϟ?���k���^a�n�[a���/�c�V�Z��~��[;+f�r�
�ʕ�1>�-�������ȝ.]�Ddd$���FGy$lݺ��m�r��I�T����;3g����.�1�˗��̙3������/���@���3gN�<��\��׿�>}:�ϟ��͛�9kkk�.]Jtt4u�ԡ{��L�2�خGDDDDDD��h�y����2b��W����-���8��;YXX��N��ۗ��~j׮�ԩS�~��Y�}���c��~�i6oޜ���v�7����O?�4��'N0x�`�V����
U�VeȐ!�>}:������ر#���T�PWWW���sw��iF�E�:u����'��y��̞=��W��:����S�����X���e˲s��Nݩy��l۶
kkk�,YBLL�������իiԨ���<�����׏���<��:��;ݯ�SDDDD�Qa�u�v �t��{�n���ٯ8ǜ�J������	���_?�ɾ��۲e��vODDDDD���O?1l�0�U�ƈ#���<v���>�]��^�bEL�jոp�}�Q�Er[�B-ZĹs�HOO����|��W9
 �#gq�տΜ9Czz:qqq��aÆ��O?���BJJ
���̟??�߱�������E;\�Ck߾}t�ޝk׮�������ؼy3_~�%...�:������k����?�������7aaa�۷�2e���Q�x��'�:א!Cx��hѢ�Y��m��۷/)))������k���_�e�^}��\�y��a:t�@jj*��������7߰g�Z�nm��?����$S[ZZ?��3?��3k֬�СC<��3Œ�N�}�V�^Mff&�F��o�[��x�6l�|�	�V���?����?6m[�Vk
f�֭|��t�޽@s��~��"""""�jժq���=j����ѣ9�:::Khh(����%_q�y��1��3�9`�y�bŊ��Ǔ��HŊ��'&&�����M�"R�222�|����7��n޼ɗ_~���/��iӦ��_�b��sZ������jժFG��Tp!�+W�ЧO����0a<����/�Z�������9~����+���1�|�M��ʕ+M�gϞe�ȑ��矌5�)S�P�jU:İa�8r����̙3������k��lmmi۶�Y[||<���'%%��={��R�n]N�>����ٺu+o�����T�\9�9�
F�n�x��wy�������?���3g�7o۶m3��0aIII����L�<�5j�����Ç3f���̞=�b�v���{���W�^������'�|®]�r-��6m�Z�b��ż���9s�����#$$�A�q��i�~�i�;ٿT(�jN����t�ԉ3g�0�|�ΝK�
8~�8�������ٙ5k�0}�t&O�Lݺu�z�*����_�'''�/_�<������^�z��fμ|�ᇦk�������.]���ԯ_���xbccsV��ƚ�����m۶CD
�e˖FGȗ�����8p ���$�%K����ɕ+Wx�������W^1:�<@�M����9}�t��DDDDDDDDu�)�<�>���6m.�N�:���ѪU+>��S�y�Y�ti��9t��>����c˗/��͛��׏e˖Q�fM���i׮��9�ׯ7��~X�aÆE�.___�_����3�7o����Ɔ�{�͛7��������_��۷o��͛y��)]�4���
�~�)4��O?��GQ�N�������C��_rnݺ�زݮ(���ӧhԨQ!�(<����:u*��
4�ᆪe˖���ҨQ#���+���ILL��CN���杻�����e�ԬY��~��!C�ЪU+��o�����!C�Y�&ǎcРA�lْ.]��~�z���0a��o�
pss�G�E�W�9���O�����&>>�F�ѯ_?S��_~������ڵkW��y�;��~��e˖�Q�tiF��ٳgٸq��-Č�����x{{��BDDDDDDDK��BJ�+��;6��ÇgѢE���1o޼\�$&&2`�222�ҥK��Nw���Z	�NNNN9v8HII�lٲ�����ܹ�ɓ'�Xu��Ғ)S��{�nv�ؑ�u�3&G[�-�v�Y{�j�8}�4...�3����S�Z5�{��w��nW��/;����=��HJJ��̙3s�p���ٶm3g�,Ԝ���)""""򸉈��󘽽=+V���Ϗ���ׯS�V-
�ᅬ����oٲe	`�ʕ�޽���ʔ)C�f�5ju��1��4iK�.%>>����"g/̜yY�p!|����'��k׮>��ںt���ŋٷoo����}��Q�lY:u�T���W���g�F��B


2[��AӴiS&L�����y��שR��ёxÇ7:�<����7n����;��{�^�zѤIӈ������Ha��BJ���8::��/{W�܌1�s��Q�N>��s���̎���_;$܍��W�^%))��Ew��~��N������C9eʔ 33Ӭ}ڴi:�~��~��U���=zн{w�u�5���.]��ׯ��^�zȻ&�U�^z�%N�8Q��t?�O1��O�v4��SO=e����ĉ�8qb���ܹ3�;w6k˯�#�>�3��/_�ŋ�;�L�2����j�*.^�HժU�x�"���#G��t��w�/""R��\�ED\FG(�>��/���w�y�M�6�pqqqw���ȝ���;�
Ƹq�:u��q
4�A�F��B��{�OAW�ϫ�ʕ+	�\�rlݺ�
*��s��u��;Vd?_��322�^g�WAA�r��q�F�����
<��!Cؼy3͚53����o�Y��޽{ӨQ#bbb�-���իW��X���;@ݺus=~�Vٲw���(��)"""""i߾=NNN|��\�v���LΞ=��ٳx��
Nx�<�ʕ+dj

��ёA��LDDDD��.]???���Ӯۏ���Lv�؁��իW��ٳFG��Hdd$nnn��ۗE�GDDDDDDD�P*���R�*�W�^%+++ϯ?��3���Ǐ��;�`aaA`` �5�w��>p߮];����?u�+V4{�%�����\�d�֐��^������O�����a�L�
gΜa���%��(�_�N�.�5f�\����=��y������Oj����SDDDDDnqqq��ˋ�;ҢE���KDD*T`Ĉ'����5k!!!���GHH�f�R������<Һu�F���3f�=-��z�*.�^�z���kddd�i�&�W�nt4yHdddлwo�7oN@@�C����������HIQ��<��w�8x�`�ƥ��ҿ����={6���y��]�6QQQ:w���X�l�ig��|��W\�v�쇔�s����:����f��K���:t(�V���ɓ����gϞ�V��o���XYY�|���'���XZZ2lذ\����O��:t�����d�)""""�<y2'N�aÆ���aii���#nnnQ�jU�#�W͛7���|||3f��n�"""r��<y2�c���L�8��'z��ݢE��y��g���S�N1r�H�}�YfϞM׮]���&,,�^�zaeeetDyH�*U���׳y�flll��#"""""""b8\�C�k׮|��ddd�8����iU�l�&M�رc���1cƌ|�pvv`ժU9�EEEaaaA͚5Mm-Z��S�N���ӯ_?����<������ҒI�&�ڻt��G}Dff�٘��L|||��wk(��5kbaa����ڴi���8��S�cǎ%55��]�����Ḹ������ѣM;w�i��9���O����ݻ�ٱ��;�An��)"""""�����ݝ��׳�~���	

eڴiT�T��x�$""⮟�r���΂X�`(�d"""r7�.�ؑ#G�����cҤI�����/���"��ʕ+ë��jt�w��)���{����p�~~~4h��X�jٲ%�˗7:���������A�P���|��8p��]�Njj*�w�f�ȑ��曔*U
OOOӘ���.]JӦMY�n�]��=z4����^��iӦ������d���;�nC�1�b�
�z�)v��A�ƍY�t)111ddd���BTT�1NNN\�t�3f��0z�hʕ+��ݻqss#::���4���qsscϞ=�.]��c���=�~��o߾�ܹ�7n���ATT���_�ŝ�(��*\x��W�x�"mڴa�С�ڵ�˗/�����K�cȐ!�������ѡC�\�*�m߾�~��q��	���8v�ݻwg�����o˱3Fٲeؼy3����y�~���������ȃm�޽�����0s�L��郣�#U�T1-���r�S�<z��퍎p_���kDGG3f�ʕ+gt�GF)��EժU����ӧ�~�--[�����ߟ^x��zΜ9;v���|n����[�.���>����3�|�~�[�f�ԩfm5k�4=\���<������g���f��>�,AAA��ۗ�[��u�V�㶶�Q�F�<�����u�V�?N�Νs�Z�*�q�d+�`ccömۘ2e
����Y��5k��:������������%88��#Gl�^�re�n݊���Y{���ٳg}��5�e�7s���~���������<���������`���$$$���[�|���^�Ӊ���n����������H�h�yh�����/�0l�0�U����5�˗�S�N���1z�h��gΜ)�Æ
c�޽t�֍'�x4h�ܹsٽ{w���7nLdd$+V��k׮8::bmm������c�ȑ9r$G�E�=z���?3h� )U�������[9r�^�z�:r���?�����ѨQ#���)U�u����w��ȑ#9
�3[a߿l666,Z��'N0u�T���ppp��ʊ'�x��-[2c�N�>��ŋ�-��[;|�ٳ'''J�*E�Z�x�����I�&9��^���]�R�LJ�*ų�>����)"""""""""�'33��˗���F�֭i߾=C�e˖-9�&''��닫�+�[��G�����펛]4��}�뤤$6l�K/�D�J�L}*W����6l ))��TDt����^���͛�c����=
cȐ!F��B��P�W��V�*P�?���Hs�k׎v��j���-o��6o��v��lԨ�ׯ/p��vX��������鉧��!�
�ݩN�:��<RM�6��,Pߚ5k�����~��"""""���2p�@�c����c��Ϗu�֙^���Idd$7n�0�[%--�Q�Fm�G@@QQQ���ai���W�|�
��ɴi�&DZ6m�NXX�{�.ƫ����s�X�l$%%ѻwo�U�ft,y�����3g��Z�)""""""".\��������#88��""""l޼___���HOOg���xyy�q�FS�E`` ���4nܘiӦQ�vmbcc���$<<���z��EDD�iW����<�aÆ92d�8p@"����,���[�.]Jhh(�+W�w�����g�1:�<bBBBpssc�Ν8;;GDDDDDDD䁥�y`d&ܭ��…�V�ti�_�NPP111t�Ё>}�ЧO�~;w���ӓ*U�P�V-f͚E�^�ؾ};�z��s��'OP�F��j֬i�GD�GRR���L�:��e���ٳg�ҥ�ڵcÆ
���kkk�c�#����0�#F��BDDDDDDD�.Tp!"""""""�7�x��""���E��5~�xfϞ͡C�8t�˖-cذa���cggg�w��y\]]s=ϯ����<W�\�\�r9�e�e��⑒����?���,\���8fjժELLL�EX"�%22�.]��ꫯ���kt��
.DDDDDDD������1D�1��g�1p�@�c�<��ܹ"{g�����N�;w�U�V�ٳ��[�r��Q���	d̘1����{q����=naa���e�c�m�}D�xT�T	oooF�͠A�h֬�ё̨�BJ҅pqq�q��|���XYY���#"""""""w��y,i�Jɏ��������ͷ�~�ڵkY�p�����ё��XBCCqtt,�+V$>>���D*V�hv,11��GD�����Y�~=#F�������W��j�*�|�I�Z���)11*T���m�(]��ёK*ry��\2IDDDDDDDDDDD�1ֳgO�����{�����>�����)�����yإ�,����m(��qgy"_AEME��R�;�JA��IS+%4�(	�Ö,H��(D���?k=.9
�
�g�`�{�s^s�Fܿ9Mlܸ���lz�!Z�n
@�5,��z�)8v�W�^�?�୷��d2���k�k>�"--��֦MRSS�e0����H�R�
�V����Ä����\������l7� IDAT0o�<����t>�����m�6�֭kt�{�N�)��Ǐ[=�h2�HHH(���)�{o��c�$˝�QTT�k׮6��)�1cưp�B���	�����j���LJ={��������U�Z�j1y�d��z�ꑑ����;NNN���н{wbccINN��?�
гg��^���ڵ��ߟ��@���iڴi��}��U>��BBBؽ{7mڴa��Ō={{�R�G�$�x�
&N��<`t�J�G��]���"""""""R:�BDDDDDDD��N������1*�C����ә6m+W�$11��X""b����;.�+)wwwfϞ��?���
666�l��Νk�gggGhh(���899Q�Z5�ݻ7k׮�*Ԝ6mM�4�Z�j���зo_j׮M\\\�qqq�����ϖ��E*���7n�+��R��L&<<<�]�6�}�G�e�ĉ*�CթS�V�Z��sqqa��F���	R�"""�|���1D��������4:������]%66��%r󃩥u�Dy���a֬Y:'''�����DGGckkkpB�
ĠA�n����)S�0eʔ"�������f�V�N<==Y�f
�O��I�&�>}���DƏO�ڵo"R�Z�j��V��Λ7�v��Ѳe�RWDDDDDDDDDʟN��2�����at�
<���F�)��d�H��ٳg1b��m�ȑ�={���0������1c�иqc���-m���899���m`2����'�dԨQ�:�Ul!""""""""RA�)3�&MbҤIF��J�ܹs�X���{����C˖-=z43g��Oy���f͚5�ڵ����
Я_?Ǝ���
�UqGi�Q�9b�{߾}�k�.lll�ѣ�&M�A����/� ::�cǎq��%4h@�޽���˷�vvv6�-"66�Z�jѫW/&L����c��9++���H�t�BÆ
-�7�d2ɨQ���������H�QVŗ�}���-AAA��꫖���n�ʊ+�U�V�f�[KOO'>>�X'��������ȽORf������0:���&OOO�]�DDDDD�/^d�ر�:u��v��1K�ōrss��ȑ#��3g�Jrr2!!!T�Z���Ɯ�/&&&�K�.�m�6Y�n%����f�����t"##9�<��ͳ�@\\p��b˖-|��7���cggw�kޱc���t��-�8ݺu#>>��;w2dȐ�SDD�nֹsg���X�t)'N�����T"r��r�J6n�H�F����^d���Qqqq�~��FG�Tp!e�F�z`[����et��ΩS�pvv�7ޠm۶>|���@Ξ=k�wݺu9r�:0s�LZ�lIjj*.$>>��[�2x�`�<٢$;lw΢�ݻ�+VХK�=J`` ���+�֭��ϯ�Y֯_��38p U�T���Ì?�RXq��Ǐ���ұcG�=ʬY�8}�4}�&L��5�۷��m���ܶo�>\��H��DQ�<==���4:�����/������������+�V�b�ȑ*���RJJ
nnn�1�+VGDDDDDDD�BP���)<<<��!"%�e��#�����X)�����v��
\?��G��Օ��@&M�d�׮],\�gggZ�hAPP�f۶m�,~(�Ҙsƌ� y��8q"�w�.q��W_}E^^G�e���8q�o���.��@�.]����c��݅\�d�Ǐ�Y�f��i޼�U���z�j�믿2do��V�����-~��w���G�-6:��������H����PRSS�ԩ�U���k��iii4���RRR�5gQ;l�\Rsv����uǎ8u��-�ٹs�<y2G��w-///_���y��Go9wI֜�����}�~�6s��booτ	������8"E��̤O�>���P�vm�Ia�'VFEEEDDDDDDD�Ib��g�ҿ��>>��sN�:��iذ!۶m3:�]���i�殛;**���6lXyF�J���C�E:�\,P�J�[��YA'<ܩҘ�zu�_�\�v
��U��8ϒ%K8z�(M�6��'��e˖�o߾�׻�}4��Z�j��Q�5��/h-涂>K��2i�$~��g�n�jt�[�����ݝ��t������ot$)BZZ���F��P��&99����[��С�a��&S�N%66�ȇ����СC����a����>|8�[���*"""""b��M���?����c�Yڿ���|}���HMM%&&��v�-�9����N�8t�>�`��2ԇ��R�^=N�<i�~����~����o������$kvtt$==���L��effZ���Hš
]D��O��I�&^{���y�gظq#C�-�d"ŗ��Nj/�ȷ�~K\\�Z�2:��������H�S�mEJIa�ו]ll�]7wNN�f�b�С899��쌻�;������sJ��=��,Z����d�\���ÇY�hQ��O=�;v��W�����[oa2���5�����vG�J2ga,X`YۡC�X�p!}����\���'77�cǎhi?��U���瓜���˗���oY�`}��)t쒬�|�bjjj�q�mF�)""�����c�H	xxx���bt�ۖ���_|���?O�f��o
��SO1z�h^{�|�=,r7ٻw/7nd����o3:��������H��.�\ݸ����իY�z��ʕ+Y�r�!';H����8{�,#F����9����������DDDDDD������>����ǧȾ>>>�ٳ���$�����ժU�ɓ'[^׫W������qrr"&&��d��ԯ_?��ڵk����K��w��l۶�ٳg3{��|׏;F�nݬ�y�6m����U�%Ys��݉��%99WWW����z��Y���ݫG������"R	\�p��>�����9BϞ=���(���K�Ҷm[fΜIHHH9�)��={r�ĉ"O�;�.���ߘ3g}��k׮�1�m۶�뗕�ſ��/�{�9�v�ʀX�l.\��g2�0�L������G�=x�gX�h���׮]cժU�����OЫW/^x��l�b5�����w�}��O?m���>e*ɺ�;++���H�t�BÆ
-}7n��d"22����"�q�ғ��Ph����-�W�fРA�w�}T�^�֭[3o�<lll,}���

���'''�U�����{�f�ڵV')L�6�&M�P�Z5rsso;{I�,̲e��ѣիW�aÆ�=�U�VY����O����������о}{-Zĸq�ذa�U��3gҷo_lll�_�>Çg���ԬY�T�ܷo_j׮M\\\�q��ⰳ���b"""�����T��/}������0�_��/�0y�dx��N��O<��C��ꫯ6l5j�(��
�t�R�}�]����1�Hɨ�BDDDDDDD�l�)W�a�����I�f�شi�����кu�r�E}FFcƌ�ܹs����fϞ�իW8p p}ǣ�^z��'OZ����A||<���Ԯ]�j���Ǔ��	��K�شi׮]#  ���>��CK�˗/s��a>�ŋ���lٲedeeY>���c�����v55�֭����ܹ�!C��(������HY�_�~��Μ9\p�FL�2�)S�9���nnnVm�9���>ŝ����֭����o9wqƲ��g�…^3]�|��J<Wq�\�N<==Y�f
�O��I�&�>}���DƏ���ED��et)�aÆ�D~��W�l��̙3y饗ptt,��G��>`ܸq$$$P����*""""""""R�跂b���d:t�P���p��9ڵk�o�A�
x��7���	

�|�ᇜ<y�&M�0�|ڶmˑ#G�5k)))�]�???���5kFPP�5b͚5����{�nK���͛X�r%&��˗/�m�6���ٰa^^^$$$XN�(�!�-ZZ�K�����޷om۶�7��m߾}*���Ջ��lf̘���vvv����x�b:u�dpB��1c��駟���?���899���mp:)mFG�
���'%%�jժ��U�TaժU<��|����۷�����������ݮ���r2X�o߾��em�޽L�>j׮M@@			|��ǖ~�w�   �Gy�5j�裏2s�L����|c������B͚5-�U�?�rݼgxx8QQQ���:����n�Z�����%.�(ɺr��q�zA�͚7on�GDDDDD�H��� 88���~��{�W��թ
rw���%((��[�r��Μ9�֭[	

�V�ZF��{��[��nݚ�Q�"R*z��ӽDDDDDDD�1:�Bʕ���%K��d�����3�|��J˯��
@�6m��w��i}�Q�v�n��qnԲeK�\�v���k�1w�\8��x��wy�����,�C#���*�������}�k�6s#��o��O?�Dnn.�5�'�`�ر4l���R�;w��Ϗ�K�0q�D\]]
N%""r{�?^��e���8p�]�veذa�M�t��5������F�ŨQ��t>gg�2_�V233��o�ӧ��Q�������bt)\H�T�J�;�����ըQ��y����ڵ+{���O>���w�aݺuL�8�!C��r��N���˳̙������|oժ��1���*"""""R�V����'���FG)ue�9�ݨ�~�""R�L�:�����:t���6l�@^^Ç�u��t��р�"w�?���5k���;����?���ƃ>ht,�2������;?��#Ǐ�f͚FG�T�?9-R�X�z5:t !!��+W���JBB��,5j�����"��w,JLL�j7�vrr���4hk֬��?d̘1�?�e˖��x�B��/Z�
Z[q�]GGG�:73��������������u�������0k�,������θ��HNNN9���%%%1n�8x��ϟπ8v��}�=z�0:�H��z�*Ç��o�%&&F�""""""""P������d�z�EA��C���X�t)���\�t�%K�`2�x���-�z��
�…IJJ�ʕ+$%%�h�"z��Y��`2�ظq#���<��C�n�(�t����[�Y�^=�l�BNN'O�$88���]�����SSS�kn3�)-&�	��dt�R�ٳg1b��m�ȑ�={���0���]233�ڵ+qqq,Y��S�N�b�
��VD*�W^y�m۶�y�f����GDDDDDDD�R�nt�|�^x�]�v���Ā�����˖�nj×_~IZZ/���U?�|m�1f�.\Hppp��WWW����###www������)t�޽{�y�f�/_�����֭[�~�]wAsw�ޝ��X����r�}��S�""""""""""r'~��7�y����Džh޼9�G����V����X�z5_~�%��
4�駟fܸq���Y���;n>���v����H�-[FRR5k֤O�>���k���Z��xVV���t�҅�
Z�4n���Ddd$�F���޾��&�{Vݺu���oy��-F�T����^����(�~�i�㈈������TZ*��rws��?�`��<8::FHH����ҥK�j�
�y�K?{{{���x�سg�����<��3����888�xnwww�W�NTT'O��iӦ��ٓ1c�X�M�6���~���trss�s���T�Z�]�v�����db֬Y�����]��}��e������1z�h�q��ⰳ���g�-�!"""""r3///�l�bt������� "%�����1c8w-%%�ٳgs��U��x饗,��HOO'""���xBCC�]��me?~<���\�t�M�6q��5
�gǎdgg�qN�n݈��g�Ν2�2�T4m۶5:��+W��������"�%<<��3g��o���nt�JMR�m�f����?7$���3.�e��u������n���A�1hР"�sss��ͭXs���2c�f̘q��YwAsשSOOO֬Y��ӧiҤ	�O�&11�����$EDDDDD�<<<�� "���=$ro��8w��ڵ�7ޠA����|��DŽ��Z
.>��CN�<I�&M�?>m۶�ȑ#̚5���֮]����meh֬AAA4jԈ5k���ݻ	 !!��3������m߾}*��
����lڴ����___��[ZZ�&M"##��_��8R�\�|�y����3a��㈈������Tz*��b3f�~�)������p����68������TQQQFG��n՞���޽{�>}:...�;]b��ݖk�<��>�(3g���'_~��m\���[���"44����y���ǁ��7k޼�U��(==�իW�j�*Ξ=�K/�dt�iѢ̛7Z�hat$�@jԨ��_M�����"e`�޽�X�B������B�Z��Q�NvJ�ܚ��-AAA��꫌5
��[��b�
jժep:��T�bt��� "��믿ЦM�"��>}�^dq�N�:Y�s;Z�li����k׮yOFF��������}D*��r�J6n܈��cǎe„	���{���?�ׯg�ĉl߾��8R�8::A�HZZ���F��P����H�Ν���c�ҥL�8WWW�S�����HE2x�`<==��!"�TDD[�l1:�H�v�9��y
�L�N�5�*���˳����[h�5j�8��_ժU�]3��U*��C��i�&\]]Y�j#G���7s����ޣW�^DFF2b��#���������HP��ܵt�����S?�����H��������"RI]�|Y"��F���/����B�v�
������?�Lbb"�?���=11'''K[�*U�����ŋ������R��IOO'333�.晙��>"���S�L�[�nFG)5=z�`�ر���k��ۗz��IDDDDDDDDDJY���DDDDDDDDDDDD�ݻw`�ҥ���s��%�,Y��d�矷��ݻ7.$))�+W����ĢE��ٳ������-[�����ɓ'	���*���,mmڴ 555_s���HE1`��
Ula�x�b�����EDDDDDDDDDʀN�)��Ǐ[=�h2���Oi,N����V��ɛߧEEEq��v�ʰa�J}~�<^x�v��ERR�����/[�3f_~�%iii���V�\\\��z����͛Y�|9˗/�����իGFF���899C��݉��%99WWW����ɀu��ܽ�ի�ʕ+�駟��"���k���鉍���QDDDDDDDD�:�BDDDDDDD��N������1�zE�O�"$$��ӧ3m�4V�\Ibbb9'�{MBBB����������憽�=5jԠm۶,^�����[����ưa�hذ!ժU�aÆ�9��k����`�;y�d�Jݺu����[�n̚5��O�6�&M�P�Z5rss�۷/�k�&..._���8���x��go{N)_Æ
��_7:��cf͚�رc-�""""""""rw�	R����<x��1D��������0:������]%66��%r�wrZFI�>���0k�,����������m������ٙ�޲_ݺu���߿�~���̘1�3fX��3����7�������f�V�N<==Y�f
�O��I�&�>}���DƏO�ڵo�&�7�������;�����8""""""""R\H��|�2Æ
3:�������T0�U< �',,��g�2b�K�ȑ#Y�~=aaa����NDD���3�O?����pKHxx8NNNx{{�NDD��֭[y�W

b„	FǑr֣G�����!"""""""%��)3��ᄇ�CDDDDDD*�s�α�с� IDATb�
���KNN-[�d���̜9�.����f͚5�ڵ����
Я_?Ǝ���
�7~'�ř� ���Gpp0�v���Ɔ=z0i�$4hPfyرc��ͣ���{?��3�ӧ��y��			deeI�.]hذ��O�ƍ1�LDFF2j�(���o+���Ƚ��֖�� ^}�UF�\wŊԪU��t""R<�ȑ#7ns��1:�����c�������H	��Bʌ���7����\�x��c�r��)K۱c�,�7�����ח#G�X�Μ9Chh(��Ʉ��P�j�R�Ws.^����.]�Ķm�HLLdݺu888�I�3fp��!�,Y���+�7&==���`6l�̙3�
.n�c�����֭[�kݺu#>>��;w2dȐe��u��???�.]
�ĉquu58�������H�>}X�r��qDDDDDDDD��J���<x���h�c��m�����F��-���:u
gggBCCٿ?�W��:Y�lݺu9r�:�������cǎ��dzu�V��4����|�[�L�B�nw΢�ݻ�+V��~BCCqvv��_eݺu%}�����ޞ�s�r��EfϞ͵kט3g/^$((�Bߧ}��жm�|���}DDD*OOO�������#GGDJѵk׌� w�u��ѢE֯_O�jՌ�#""""""""Ť.�Lyzznt)!///�#�����X)�p�����v��
@@@�<�����;�m׮],\�gggZ�hAPP�f۶m<�T�RsΘ1�rZ�#�<B@@'Nd������Y�.]�X�_���^���Ì9��{��9�?@�f��]k޼�U�� 00������{��(r�

bڴiԮ]��(""""""""R*��
%55�N�:Y�����뛖���A�
+%%�Xs�|�ōn.
)�9�v�j��cǎ�:u�ެ�y&N���9|�0-Z��W^����S2nfn3��:t耧�'��������8r�������������(�4"R^��� """"""w@"""""""r׻���\�PT���̮R��-���…ōXl�1g��ֿҹv�U�V5$ϭ�����
�|DDDDD�U#F���?d���$&&bccct$� jԨAxx��1D�"""زe��1DDDDDD���B��?~�6m�x-**��w#6lXyF��6mʏ?����c�=fi�����urr"55�������%_i̙��durơC�x��<��o�MJJ
�ڵ�ȑ#���0eʔ"�qtt$==���L��effZ���H�mt�2���7�,YB``��q���������"R�/_V�������H���R4u�Tbcc�a�СC����a����>|8�[��cǎ$���}�Y~��G-Z���y��9z�(�-�����b�ڵ����C=�_�źu�裏0�L�Z�
�~C^^iii����v���Y�X�v��a.\@߾}�4�7�|CDD;vdժU����~�zz��I�.]��ߧ6mڐ��Njjj�Š��TK���1��TT-Z�`Μ9̙3��Ç��CIDDDDDDDDDJH"�(66�����f͚�СC-�����Htt4����SDDDDD�B�����>����ǧȾ>>>�ٳ���$�����ժU�ɓ'[^׫W������qrr"&&��d��ԯ_?��ڵk�����,OVVAAAԮ]�y��Q�zu���9r$s��aÆ
����>u�ޝ��X���quu��#99��={�8�����<==���4:��H��<y2���L�0�]�vQ�J�#I۸q#-[��S�Ne>���e>���L^^��DDDDDD���Bg2�
<����ٳ�1��6r�H֯_OXX~~~����������^�������+.\�@�-�f������X��������ݻ9{�,u����___Z�je�;m�4�~�m�����ͽ��%��0˖-cΜ98p�������c�Z������o�1w�\���pvv��ߟ9s�̂
|�������ˉ��c���V����aggdz�>[��""roۻw/+V�0:���ФI��ѣ��1�5j��ޣ{���ڵ777�#I���/�����g�\�������e.)ZDD[�l1:��������2\H�u��9V�X�޽{��ɡe˖�=��3g��dgg�f�v����N�
�ׯ���,�‘�OHH ++���H�t�BÆ
-}7n��d"22�Q�Faoo_���ׯ��ٳ��Μ9@�
���2e
S�L)rL77�|Gg�w��Ư[�.˗/������y,X���?��s<��s���Ou���ӓ5k�p��i�4i��ӧILLd���Ԯ]�D��{_ZZ���xxxED�)::����ӵkW����ܹ��Q�>|www���dɒr����C?KE��/_V�������H����.^��رc9uꔥ�رc�b�������ˑ#G,mgΜ!44���dBBB�Z�j�s�ر���l�u��Z�n݈��g�Ν2�W%""""""�z�";;�3f��憝����,^���vkcƌ��O?%<<���qrr�����t""b���(�#�H1U�R���,[Tl�N����t�ܙu��Q�Z5�#��������H))�)q�
,<<�S�N���Lhh(���g���V'P��[��#G�СC"""8x� QQQt�ؑ��x�n�
X����`y�o�>ڶm�ols���������ܹ�����O?�c�=���			ԫW�q����r���%((��[�r��Μ9�֭[	

�V�ZF��-�����ߟz��y�flll��$""""""""�H'\H�3�L�j������޽���y�\]]	dҤIV}w���…qvv�E�1x�`�m�V���Ǐ�Y�f��5o�ܪ��������9\\\ؾ};?�����4jԈ'�x��c�Xl/�s�����t�R&N�������DDDDDDnOnn.�����߿��u��Rڻw/|�{��%55��W�ҰaC�q^x��{�9�#��)Dyyyw<FI�t���Zk))\H����
@�N���z�#--
�A�8VJJJ�sedd`oo���GDDDDDD�\ժU��������(��,7'(/��)MǏ�M�6^����t�ڕaÆ�g4��?�@JJ
۶m�0:N�s��Y|||ؾ}{�k�N��ԩSlڴ�����~�zH)"""""""�:\H������F<4r����q��1.\�P�u�U�V�w��v�;�����������H�2u�Tbcc����C�		aÆ
���1|�pZ�nMǎ
H*""�:u�ĉ��������֭'O���ٙ)S�Я_?|�A�U��O?�Dtt4K�,a۶m4��?�����DQ
�۸N���,��"�@ӦM�����o~
���@LL			����㋜�������|��m�>""""""""""R����؞��ìY�:t(NNN8;;���N`` 999�RDJ�Ν;��r�bc����<y�'�|�~���S�Ү];lmm����M�6��_s�}�˪U���-"""""""� \H�����h�"����r�
�fѢE��>��Sp��1�^����[o���d�����׼�GZZ���|�{jjj���m�
/"""""""""RٙL&�IɕYXXgϞeĈ���#Gr��Y���L&"��ȑ#��ߟ>���("Œ��ʸq�pqq�f͚899���ő#G
�_�J�[~�,!!�~lllhٲ%3f��…V����ؾ};��?�7o��+4w����w��ǎc̘14i��4i���'N�(r]�|�
O?�4���ԫW�A��Y߉'�U�VԬY��Ν;3w�\����)i�����+�K�.��oҫW/�^�:
4��cϞ=��Æ
t���6m�K/�t׭QDDDDDD*7��)�����}�?��3>>>E����aϞ=$%%���mu�V�ZL�<��^�zddd���111t�ޝ��X���quu��?99��={���DDDDDD*���hjԨat������� "%��o���;�o�>.\�@���=z4�����1l$$$X�{s����ի�6m�[�fժU��dgg�f�v����N�
�ׯcǎ���<Fdd$˖-#))��5kҧO^{�5lmm�
Kn̖��Edd$]�t�aÆ�>�7�d2ɨQ����/�wTD�C�v��e���0�
I�Pqqq0����[���Ӊ��`���lڴ���nq���Z���x饗�z�����ɓ,^���;wG�:uX�n���ԯ_��s���о}{{�1��O?����~��W>��6n�Ȗ-[�ӧO�c<x�޽{s��%�z�ALL;v�`Ϟ=<�����|�
�<�YYY����\���;���;֮]ˁhԨQ�d�YY|~fYYY��ݛ�Ϊ��?�`۶ml߾��[�2`���_�j&L��>u�����_��-[����V�e�F\��n�Wy���e��Մ����W_q��Z�h���7�g϶�#�����������޽��g�R�N\]]-���M�6���~���trss�۷/˗/'..�ѣG[刋�����rↈ�������-[زe��1DDD������1c8w-%%�ٳgs��Ux[�.[����,�ↂ�sss��9�̙3������LHHU�Z6>~�x233��gnڴ�k׮Ph�;v���M�n��]�֭����ܹ�!C���zE�.d˖-L�:U']�]+##��C������ɓ���� 11�5k����'G�����r_^^^��-Z�̙3x���-�?���Ǐ��ի�����ӤI8��/�ȡC�X�x1���`�޽<��s�ZC͚5�ѣ�U[zz:#F� ''���,X���z�'N�'�|°a�8r��7�7�/�H�~��:u*�:u�o�ᥗ^���7���O?��<y2YYY������ӬY3�\����8q"G�a�ܹ���;���F���Wpp0�}��۷����Օ�U������ɓٿ?,(��b���<�����:t��$  ��?���#Gr��1�~C�(""""""R��]D*����3{�l>��s8@DD�:uȷ����S�L!&&����_�t�R�b777>��<Ȏ;�S����$&&r��iK�ӧO������7�k�.�Պ����������/}���{�|��s�h׮�7o櫯��� 44��mѢ���<�YX��u�8r�:t ""��Eǎ���g�֭��n֬�7of߾}����޽�ޠ(!!��z߾}�m�6�x�6s�w888��[o��GY�= w������+�'���{�={��3g�l�2Z�jE�Z��ڵ+����y��W������.r�0{�l�O������ڪU��������y��wi޼95jԠgϞ�_���>���?55(��bq�\��.��SO�y�fڷo���
�۷g���<��S��矄��x�^�ؼy3ݻw�v��<�����믿�����d�Z�jE�5����w��DEE��'��Z����W���p>��C�w�-5k������? ))��;u�Ď;puu��Ɔ�m۲i�&�y�222x�_��������N��J�W�^dgg3c���ܰ��#55�ŋX
/J˘1c���O	������''''���Ku.�{ٰaÌ� "`y�IDʟ�d*V{BB�e���ӧ���@@@@��E�����Iȅ��ڵ��K���3p�(#((����m�6l5����%�������?��<Ǐ�kܬy��V}D��2d����/��=�j�2:�����_�~�����+�P�N�#�+�I
���?�>v�X�|�Mv���o�Q`���LF�ɕ+W�۷/�-���������^�ɔ��%'';;��-�����N��Z�*���:�w�f����k�ĉ��{�1�|?כ6mʉ'�߿?'N�W�^4m������[ߝf�Qi|~E��������y$  ��խ[�R�
ӧO�/���O?%00��e�F\�]��?�ݩ������ƍ	&88��z�z�7n\��ikkKPP���*�F�`�֭�X�B�8�Att4'����!�7����iӦT�51ܪ=--
�A��?%%%_[˖--�;88p�ڵ"�ddd`oo���GD�=o��6�ڵcѢE̝;��8r���l�_|Q�-�9���S��N�8Q�q�����?ӪU+֯_O�jլ��^>�������_�EVVu��-�=��5I���^��r�V�Z�k3��q���3g��/��~���\/�x�g8p �*��l7*�ϯ�N�<�?�@||<$11�ȓa�u�V`{�.]8z��-�-�5������H夂���;�m߾��~����\5j�O<�رciذa��ٹsg���X�t)p}�WW�R�GDDDDD�^�����1D����������"�ZBB��k��<7���K"//�rOnnn��
:ݢ��� �p�B��5jX�/n~s��w������=�6m���-E\rw�z�*#G���ɓ|������FG2ĭNa�U������(����O�W�^�>柗�=��U�V$$$p��1��b�s�������
-�04^�x���%�T��LJ�u���o��w���/��v�Z֮]K˖-ٹs'-Z�(�l7��ϯ86l�̙39y�d��5�֞��}�1�c�""""""R���B�Z��T�ZOO�r�Lj9EDDDDDDDDD*�F���/����B�v�
�W�J���x��a���
}+NNN���s�]��#���dff���hu-33��GD�]������&���
��9_~�e��Tu�����_%>M��ѣ���T�R�u�����N�:deeq�…b�ѳgOرcG�
.��ХKȺu��E�����ԯ_?�=���%[ix���y���IKK�/�`�޽�ݻ����?��㏼��klݺ�Գ���W7�?���xxxмys4h@۶miݺu������x�}��2CY�QDDDDDD$�VH""""""""""""���ݻ�t�R��ӹt�K�,�d2���[��w�޲e999�<y����;�����   �cǎq��U����z�-L&���%�|Rō;ݷi�����|��m�>""r�,X��իY�~}�OP����&_�u��t�#F� ;;��s�2hРB��l�����b�=b��}�]�iE���9���iP�9������V�J���/��k֬�������gϞ2�v��_q-X��U�Vq��Q�͛Nj/�ȠA��N,�v�Z��������v����z�"""""""*�)��Ǐz��bʔ)���ѵkW�}�Y�L��޽{�dn�Ʉ�d*���#**�)S�0e�����m^�����8::���Ā�ѣ�����/�l�׻wo�/_NϞ=6lX�vL��7oNRR���<�����ۗ�>��Z�j1y���޽GEY�
��)j���xI3M�T�����H�7�vL��#�by����f�xɼ�Ĕ4o%(�̂�a�
50���5sT/��Z�Z������g�w�r_�X���O߾}���7��ֵk��
�…ؾ};���/�H�n��SO�'�_�p�����T�R�>}���O�<�={����ό3J�X�mї��I�*Uhܸ�����gϞ=z�A����_�>̼y󰱱a��ɦ�^�z��o[\�t�y����O��{Y4nܘ*U����ע���ˢ�f�v��_Yw6l�E_DD��낂�bϟ7oEEEfm.\`Μ9e�7X�(""""""���2x�W

�h��￙:u*!!!l߾�S�Nq��F IDAT������o��ĉ��?�Iaa�M���޽���(^}�U&O����IOO�Z>""rwIKK#--��>WWWbcc����ٙjժѲeK�Νk6�nҤIP�fM������b�̙7����111b0������ooo/^|]�NL�<777lmmM�?���GGGv��a�c�����ٳ�
ߏ��@ժUٰa/����S�%S�fMRRRxꩧصk�Ν㫯�b�ر6��U�f:g�ڵ|��iӆ%K���,Q�_|{{{bcc�>}:���;���lٲŴ��ȑ#��Y�hu��aÆ
�nݚ>��C�q��


����w��ӓ'N0c�ڶmk6���3_}����deeQXXHVV���lݺGGG^z�~���HNN毿��…dff��h�f�v=�_y4l�������ŋ�������M�!'O�,���;wā(,,d���<��S���ҰaC��y�ߣ������HUk' w�������\�xEDDDD�m۶��[o�y�f���=z4=z���{�%//���T.\Hrr2ժU��_�ic�4��f+((`�̙`0L+��X��J�CDD�$
4��:�M�ƴi��گ~?-���]�.P�)�}||���1k�Q����DGGs�����8r����;GG�R�����Ѻ�Fnnn$$$��͛�С�Ė~�#�<bzl��g����J��qg�f͚��2z�h�̙c���S�N��76$���O%���2k�,^{�5�����x��5kX�f�Y���=���4jԨ����'k֬a߾}��p�9~�w*$��y��cʔ)�3��`����3g����O?��w�}g*θ���:t(K�.5k�[�.��9����̡��QDDDDDDDRa&L���������T�=EDDDDn���@��$==���$\\\����q�Ʀ�ڵkӧO:v���IJJ"  �6m�X/��˱c�L�����9�.]Jll,���V�NDD��1b�֯_O||<S�L >>���СC���������Czz:s��%99��G�����c�=ƫ��j����?�\�1F�E�f͘3g�|�
���4i҄�� ^}�U���-�iݺ5{��eɒ%�Z����N�8���-
6�{��?��~��1����?���9sؼy3Ǐ�nݺ��ٓiӦѲe�r�Gq\\\��o�;w.k֬�_~��4nܘ~��1u�T�֭[a����+�^x{{{�}�]��ۇ��=�=�'N�駟�Y�f>��ҿ�󃂂���c�����O�{���ۗ�3g�}��=���������BDDDDDDD�8'N� 22��;wRPP���;Çg���y�F~~>���$''s��q�ԩC�޽=z4vvv��
<��:--ʹ�����͊-�T�vm�Jdd$������x������INN��Ύ.]�0a��ԩS�����9s�E��e�N�<I�:u�ѣcƌ1[U�xnbb"�ٳ{{{�|�I&N�hڵ�̙3$&&Ҿ}{�իg:�~��xzz���Ȱa�ʴ⤈���fϞ��/�̰a�X�v-���T�^��ىHE���������Pk�"B��͉��.S��q]ct�ڕ�]���{{{^x�^x���U�V|��e�7��Q��5kv�]�**��~����>|x�}Æ
3��R���n8��G����B*Ldd$			�NCD�S`` ����NCDDDD����/F���ÇMm���7[\����q�Ƒ��ej���%&&���L������)q����u�VjN]�t!22�ݻw[�͝;�u��p��9���HOO'..��o�
gϞ���СC���G������]��������윱cǒ��g���>�ҥK�	]7n$??///�񼼼صk�6m*v�J��}�Q����7o�Ǐ�����Y�HE�����_������/"""""""""�S��� 00���":t�fG``��|�����\���x>L�
����o�aѢEf;4��ő��E�֭IHH��o�e���<��#�ڵ��k��H����?~��PjN��wǎ��۹s'���|��7���РA~��7���J�jK�,�СC�����;::�
p��A/^lqN�F�X�j)))�5
�����ԟ��P��.c�1FDDD*G`` ��������͐!C����T��^z�֭[3v�X��J_U_ʯ���_|�#G�X;����BDDDDDDDny���fGi�Ƃ���PڴiC�j����`ƌ�MNN ,,��͛ckkK�&M�={6III��UXX@ժ�o"j�U�$�iӦ���E�j�hӦ�iw�+ʢ��n۶�ig�-[�X�3e�6l���=AAA�>}����ra��7nl#"""""7���-�1_�5����N�RTTĨQ�X�t)�������[X�DDDDDDDDn3����k�ά����"6''__�b�u��RǪW�������Ұa��+���Fǎ�?��#>|�ԱK�m۶f�����~�8������.]2��:u
ggg�s�m���<<<��?��ԩS�-�3������Y�b6l(�������������
.�d\�4--�ʙ\v�Z�hQl����IMM.O�8p`e�&"""""rK���[Y>�]��D�*U�s��gϖ�߮];rssټy3�=�\�q�7o6�_���1�667gc�+(�V�Z5���=?ƶ�r1�w�������<o���}�!!!���Y;��ނ�;w.�~�)=z�v:""""""""r�S�������+l۶��IB�w�&**�e˖QTTĠA�h޼�i�S�t������?����c�=fj��Ȱ�5dgg�n�:C���߿?III���ҵkW�6mj��?�d����,����c* �˟x�r�ҠA~��W����С��===����Օ�G��������Y_^^�)FDD�F�xOD�tNNNDEEѯ_?ƎK׮]���mk͚5��� ,,��� k�#""""""""�\�]�V��`۶mŶ0s�LL�b����1c+V�����2��m��ٓ���9s���o���o�>�̙c۽{w/^Lhh(S�L�Y�f�������駟����…�˓A�����ɡaÆ�mۖ��~����3z�hƌ�O<���+'N���/���?������z�����z˔�޽{	�W�^���ƾ���7�/&,,�7�x�V�Z���e��뙔բE�=Jvv�EaEvv�)FDD�zt�҅�˗[;
)�+�{���j�*:u�d�Tn[[�la��3�iӦY;�M��B�θ��Tq+����رc<��6d��.]Jll,���V�NDDDDD���_|�����ȑ#K�9r$[�neϞ=:Ԭ�z��L�4��V�Z�:u
�֭ 44�����/�����""",��޽;3g�,6�ڵk[�٪U+
tͱ�4b��l�BNN�F�2�kذ�E[Yt�ܙm۶�������Y_ff&p}�"""""R~�>���S�����o<��3̟?�ک���������mDrW����ҥK,Z��M�6���K�j�pww�_�~�����+k@~~>���$''s��q�ԩC�޽=z4vvvfy\�ә3gHLL�}��ԫW�S�~}<==ILLdذa8;;W�$"""""r�+�h���E����9{�,M�4a�С̚5����ɉ������W_q��1jԨ����ƍ�iӦ��ɓ'�p��Q
M�vvv����}�v>��s�����ӧ�Y�&?�0~~~t�֭�|#""�׿�Ejj*�k�橧�2��X��Wrvv&66��>���[�r��I\]]y�'x�pqq)�s{�^�z��{�c��nַc�����ٳg��+""�s�N��������S||<����NC�܆jQh/""""""""r-*����X�d�����ٻw/{��寿�2��_Y�
7nYYY����\bbb���$**
��ٸq#���xyyY�yyy�k�.6m�D���o��EDDDDD�D�k�f֬Yfm���ԩSǬ��Ņ��BBBJ����>>>%�w�֭�Š�ԬY���{��cWtR�fM�L�”)SJ�^I+W�רQ���@���9r�nnn9r���tƎ���c�c���\KQQ��S�2�R���S��$$$���`�4DDDDDDDD�X*�V�Z���������$%%βe�L�e����#++�֭[3}�t������&,,�]�v�v�Z���HKK��m %%��-[Z�jlKIIQ�������H1�u�F~~>ӦM���'''����;w.�ڵ�r���#F�~�z���M�����+"""""bE&L�����i����������Tp!��X`p���V۬����={���x:���7\W\rr2aaa4h��&M�0{�l���HJJ*����Q�F}�76�s}��a�ʕ���n�W�V-ƌc��nO̞=��_~�aÆ�v�Z"##�^�����8*�&N��k��Fjj*���,X��Q�Fh6y��q999���;��K��ԩS8;;[�ی1""""""bnʔ)4lؐ
6��/�PXXȽ��K�N�=z4��ճv���G}���`�͛�������rV"""��peZ�|9���t�ؑ�Z%�{8p�-ZX;
����H����\�����)�������M���tW�Ǘ��C��LJ�;�u�V֬YCFF~�!qqq�?�����+�Z@9{�l��U�T���Ƣ��f�s666h�TJe����vxNEDD*��ݻ���bٲe1h� �7o�#�<b��D�.������7n�gϞ�N���;�P�~}�}w���@��㭝��			Y;
��,gs�ܥ\\\�%::�%K�0b�N�>MDDD���֭#--��صkW��������g�gl3ƈ���������H�*((`�̙`0hР���̘1���k�'"w�Gy�g�}���`Ν;g�tn	���L�:���������������
.D�~������ʕ+��ϧY�f4o��jժ�;�{�������~.^��ɓ'y������dܸq�X�N999�6�������۴=�����������
<==M;%�*bcc9v��6�
2�cǎk��D�n��Λo�i�T�n˖-�5��S���/Z;�C��B1b���t�֍N�:
���G��F�I�ƍٳgC��C���ՋO?���ի3i�$Sl�Z��o߾t�����L�\�m]�v�97/"""""""""ry��ѣ���-??�������K�N��۷/~�!����9s��???.]�dv���<==�ׯ�)611����S�^=S\������$11�3g�T�����o����YYY�N�j��݋��? ,,���H;p�@�}˗/'$$����/_^�Y�������ȝJbuiii���Y5f͚Ń>���vvv���3r�H^{�r�999C`` �[[[\\\�f���f�SL�<777lmmM��׫W/ٱc�E�;v��ɉ�={V�3""""""b=AAAT�RE�:�rY�Ǡ�܀w�}���8�~ƌ@aa!�ƍ�O>��~������ĉ�t����4�Ç��_�]s���t��
��7��������^^^���iӦ
�S��	�M�6�7���"k�S�<�SO=ţ�>JLLU�T�vJR�^y�g߽{7QQQ���L�<���瓞�^��������ȝ������
<|}}��e�sqq1��R|||��jԨA`` ���9r777�9Bzz:cǎ����9�������n������\���hҤ	���7�
5..���,Z�n����qww';;���0v���ڵk���#((���D/^l�7[c��q�ᔔZ�li���-%%����W�������G��c����?o�*�����ݻ7����Z�
;;;k�$l۶mŶ0s�L0����f̘��+ppp��4EDDDDDD��.DnQ#F��~����Ǜ����1:Ԋ�����������TOOO��Z��b>��\\\L}������ѼyslmmiҤ	�g� ))	��5k��?���_
��3g��ȠF�xxxp�5jd�{�ƍ�bDD*���&L(v��;���M˖-IJJ�f͚�N�U�{�&66�cǎ1x�`Sې!C8v����V�LDDDDDDDnw��BnY�G��v��9880{�l^~�e�
�ڵk����z��V�NDDDDD�b8��)��PTTd�D�����u��5������s�M_:�e˖���_�5/^�S�NT�z��TN�:����ŵ�m�����;�`kkk�4*�}���ڵk�����ĉDFF�s�N


pwwg���L�>0���|���INN���ԩS�޽{3z�h��%Wb�q��i߾=���3�ԯ_OOO6lX���""""""""ע��[أ�>Jpp0���`���U�DDDDDD�T���Z;
�K%$$d�4D�jW/�s�ʒ�j�*Ν;�…���0�]����ٳ��k׮M���IHH 33ӴR|׮]M1U�T���rqc�1FD�2�m�rk�믿=z4�6��߿�Tlq���BƍGVV��-77���233���*�}�h�ƍ������e����Ů]�شi���������
.�u��DQ�5�HDDDDDDDDD�!!!ԩS���H�o�NVV�Z��`0���ͺu�0׼ְa�X�r%˖-�믿��ƆΝ;��]]]9z�(yyy��������g������s��a4h��o�I˖-ٻw/3f��رcf�qqqdeeѺuk�O����;��ل���k�.֮]���iii�b���вeK�<�m)))*���R�2""""""""""""���� �6m
��L�ݻw 44����s��EN�<�ᅬ��'�ƍ3�Nݺu�ׯ_|��O����{�1��h����l��m�k���4;��^���+��o�6m�V�̘1�"699���0�7o���-M�4a���$%%�:ցhԨ�E_�ƍ�bDDDDDDDD�K;\���������сJ�@�}�vV�^Mff&�O���ٙ�~�t�r��.nUϛ%++��ÇS�n]֯_��M�kv\�t�~�����ˢE�����+2��|�rRSS�ر#�rF""R���L�>���o�����ڶm�ȑ#ٺu+{��a�Сf�T�^�I�&Y\k���X���]���u�ܙm۶���i񾗙�Y�9"""wcb�v��ڋ�̘�����o��:x�`�c�:u
ggg�>c�1FDDDDDDD���Å�������H���+Y�����L�:����o�ΩS��p���۷og�ĉ�����]QZ�jE˖-9~�8;w�,5��o�%77�&M�����V�{�n���x��W�<y2���'==��i�����Z�צM�}�Y��\899C`` �[[[\\\�f����S֨Q��u�n��z�ꅣ�#;v�8oǎ899ѳg�2ߟ��\۷�~K�����Ϸv*��{���%�W���"��U�T�f��Ξ=[j���-`l+n\���R�8�����rZ�b����NCDDDD䖲m۶b��z�-6oތ���G��G��{���呚��…INN�Z�j����7m슞ӿ�|�MV�^m1��J��9����OE*((`�̙`0��3c�V�X�����3���~8}�t�O�n����BHH!!!e�nFF�5�I�&f}5j� 00���h�9���G�!==��c����x=�#"r����Q�jUl�T����۷/�:u������H�������ddd��c��ڍ�W2dgg�n�:�g��puu��ѣ������j֗��g��*��
ӡC[�ܦ@������m!''�o����i�e IDAT��m�C�4l���i��<==��/:����t���pqq!&&�ƍ��j׮M�>}�ر#�&))���ڴic��ˡW�^����p��	�ԩcs��)�o�N���y�駭���˱c��&�
2��K�Kpp���ʔ��OAA�1Æ
+6nĈ�_����x�L�@||<���C�VZ�""���w�ϓO>Y����Ǐӻwo�4i�ҥK����vJRF={���fΜ9���<���۷�9s�X�v�ޝŋʔ)Sh֬��'qqq|��xzz�p�B��NEEE����ҢE�=Jvv�EaEvv�)FDDDDDDD�z��B*̄	�0a����P;w�$((��i��m&>>^;�U�'N�Ν;)((��ݝ�Ç�V���P#??���h���9~�8u�ԡw�ތ=;;;�W~���ƚ5k>|�Y�ŕj׮�СC������?7\����Bxx8������ѥK&L�`�U�����9s�E��e�N�<I�:u�ѣcƌ�����:���DDD�g����y��'�8q"888���O�|�r֭[�s�=gqo���Dž�ӧ���l޼�+V��~Ν;G�:u�&88��վK*�)��,���K�X�h�6m"77�jժ���N�~����3{�i߾=���3�ׯ_OOO6l��DD��v�N͛7�o߾��9880{�l^~�eSQ�ڵk����z�ꕒ��HY���|��gL�<�ŋ[;�r��ˣw���[�N��f�����/���_9rd��#G�d�֭�ٳǢp�z��L�4��V�Z�:u
�֭�s��l۶���L<<<������k׮7��DDDDDDD�cc���D�*Ut��q��<,"R>EEE:t��Q�C*�_���ѣIJJ���Ӝ?������-�TXXȸq��O���8�<������0q�D.]�T�X�����t���ݻw[�͝;�u��q��9N�>MRR�F�����e�eΞ=���?�ҥK���߹p�G�%!!�ѣG���oq�رcٵk�Ν#//��>����S�����H���]�z5,X���S�����ٳgM9$&&^��)Ny^���(����������g�޽�����Ǜ�6n�H~~>^^^�yyy���ϦM�n8w�=ԫW{{{:w��{�W�J�>�(���̛7�y��1~�x�I�""����Ldd$K�,a�֭�N��
�'''�
6P�n]k�t[KKK��"X�h����s�=T�Z��͛����;99C`` �[[[\\\�f���f�SL�<777lmm),,.�����Ȏ;,�رcNNN��ٳ��XDDDDDDD�T��B*T�j��&1���A�""""r;�������4hЀ7�|��-[�w�^f̘��c��b�����ʢu��L�>www���	c׮]�]�??�w�8~�8��Ԝ��>����nI����oߞ}��1c�~��7���.q�-Y��C�����o�A˖-���b�̙<x�ŋlvN�F��={6��{/��������W_
���;m۶%##���l��~����Z�lI�V�X�t)ӦM�o߾T�R��{�2v��b'��WY_/�U�V0�|<==9�<III����l�2�瞔�Z�li1��-%%�T|"""w����r�j�2�����3�0n�8222����vJ�***bԨQ|���$''ӴiSk�$שv��̚5ˬ-77�������!!!����zM|||��jԨA`` ���9r777�9Bzz:cǎ�)"""""""r�Tp!j��0��i�H9W��������o��v"r��С
6�v��+'��֞���W_}@hh(mڴ��Ã3f0a�����d���hРM�4a��������d��_�j�U���'����1m�4��
mڴ!44������W_YH����n۶-ӧO祗^b˖-כ2e��{3((�����5���OFF�W�6{�?��s��[l߾���"���dž
�駟����;pܨ�^����={���x:���7f�8p�\|r�ƍ�ň����ܮ���x衇�_����ӹ�ƍ�j�*ڷoo�T�:u�֍��|�M����NNNdgg3w�\ڵkwS�1b�ׯ'>>�)S��d0:�%"""""""w\������D;w��NA"b!>>^+W���l�r򆇇�ElNN����^����U�^=rss���-���ȑ#���u�����#�<��ÇK��1ڶmk�n|~��7�s���M_���p��%��'�|����lٲ�ӧO�����ӧټy3NNN����{��	&M�ľ}�,�*�ؤ���zM�8��^{���TRSSY�`�F�"00��ի��N�:������m���UÆ
�={6���2��͛[;�U�R�7�|��i�JZ��F���ѧOV�\Ixx8���f��j�b̘17uLfϞ��/�̰a�X�v-���f�EDDDDDDD�K"7сhѢE�}˗/'55�<�f�������T��1�TD�U�T�v
w���4���I!W�_���Ž�y}�]ڵkGnn.�7o��+1n��ͦ��]�;����ƦԱ����+U�V��uI߫vvv��ۗ��86l��A�ذa���<��fW�~�m��������?���;=�P�?��0�rui�|�|||�ر#[�ne͚5ddd������߿��}�|���XDDDD�/��2.\�`0X;�wTܰa�������{�t�ԉѣG� ��z��G	f޼y�?���DDDDDDDD�C"7�+��¶mۊ��{�n���X�lEEE4��͛�V-������&##��{�Ԟ��ak0���fݺu�5���$%%K׮]iڴ�Ȅ?�Ȓ%K����߳g�٪��w��(W.
4��_%==�:�����nhR���?���Y��A��f�Sт�q����jժ��C�L�.\�(0��
EEE���_899��.R�����___|}}���b���|��'DDD�rwuu��ѣ������jv~^^�)FDD*���U�Ve�ԩ�NCn!�-bp�lll��?�1����������n�R�"¶mۊm/((`�̙`0hР���̘1����J�RDDDDD��׳gO�̙Cff&.\`�޽̙3�"�{�������~.^��ɓ'y������dܸq�X�.999���m����O�����ѣIHH���…=z���8^x�


xꩧ�-�뭷Ly�޽���0z��U��W� ,,�={�p�����c��]�^��+AÆ
i߾=?��#�6m����Ã&M���7�PXX����1c���������3V�^MAA�"<<�"�<�W�~����d�ʕ���ӬY3�7o���aܩ2;;�b<c[I�Y��ȍiذ!�v"R�aÆ�NCDDDDDDDDD��h��:�*����5���r��1lj2dK�.%66���`+f'"""""r�	

�/���_e�ȑ�Ǝ9��[��g��j�W�zu&M�dz\�V-N�:���?��u���'�����|��DDDa1N��ݙ9sf�9Ԯ]�"�V�Z1hРk�}�#F�e�rrr5j�Y_Æ
-�ʫ���ڵ���~����ooo����5k�fͲ�߿?^^^Ş�j�*�{�=�{�=�b���z�1���0���-�7<<<L_w�ܙm۶���i����	�X������K�.t����i�������������H;\�]�ҥK,\�:u�D�n�x��X�z�El~~>�����חN�:ѷo_>��C
M1Ƣ����gΜ!11����S�^=SL������$11�3g�T������Ν;y�hٲ%������s������뭝^��R��i%�e0�ӧ���ddd����Ahh(}��`0ܔ�+���Z�*�jբ]�vL�<�_~��׸Y�ȝ+--���}-Z���/��sU�V�y������ٙb������!00�����-...x{{�x�b��
&O�������f�	���'""��]�r�=�`ccC�Z��֭���;����oDD]�t�jժԫW��Ç�p�B�<K�J������2p�@�ի���-���cȐ!,^���?�����Օ?���ڵk�v��ҫ����������C1g�ƌ��eˊ���I��f͚������Ul�Jy^/f͚Ń>���vvv���3r�H^{�5S\�^�pttdǎ��ر'''Ӯ)""rs%$$��;�:n�#!!��?>������?Njj��S)�v���RTTK�,1=>�<{��e�޽���_PXXȸq����2����Cff&QQQ�ؔ\��q�F���]���ˋ]�v�i�&����NDDD�|�;�ȑ#ٰa�E��Ç9|�0�}�}��a�ҥ7<a�nr��Q6l��
طo�V�*1�_��k֬���*�ŋ���?IOO'==�>���?��buz���v��;,���P�N�vBBB		)��>>>�����߭[7�u�V�\k֬i�ա<cWpR�fM�L�”)SJ�^I�*��>ikk�ƍK����3aaa��.����iӦ1mڴk�S�����__�RcjԨA`` ���9r777�9Bzz:cǎ����c���[�|��S�28p��S�;Daa!���:t��������8����`Ŋ�NADDDDDD*�
.�d��6�|<==9�<III����l�2S�E\\YYY�nݚ�ӧ���Nvv6aaa�ڵ��k����GZZ�iW�+'����вeK��m)))*����������СC4hЀ��z���<���-���+V����&))	___���K�V�G��hڴ)�����Xo����_ҨQ#�������UTTd��������ݻ����u��1|�pjժ��O?]�"ף[�n���3m�4|||prr";;��s�Ю];+g(��#F�~�z���M�*������T�X;����ӧ+u���/��s��߳c�\܀:��B���kEDDDDD�L�%%��X�p���VռQ����={���x:���7��%''F�
hҤ	�g���Ϗ��$���J�4j�Ȣ�q��f1""""���s�q��!�qV�^�=��c�ߢEf̘���]�ve۶m,\���^z�Jߞ���Cdd$۷o��'���ߺu+��Çg��VȰbU�V�z����O��O0u�T�~�mƎ��?������S�;L�>}X�r%��ᄇ���ժU�l������ٳy��6lk׮%22��ի[9;�����B�>}HKK�Y�f�2�?��V�\Ɇ
x��+e�;Մ	�0a������X;k�8q"���������2h� bbb8w�Y\NN���xzz�c���K�ԩS8;;[�ی1"""rw���f̘14l�{{{AAAdee_�J�kWKKKc��ԭ[;;;��ݙ6mgϞ5�۱c6l�nݺ�Z�ʢ��J�[�6MZ���-����ψ#pss���777F��O?�T�}|��w���jժ���/�v�*���~��q��ѴiS����{x��Gy����?�=��������Q�>}X�~}���vc���z�璾���-s���Ã#G��r��k^�ܹs���t��
WWW�V�J�:ux��ٺuk�ǿ��,�B�z������Ãu�֕��Xה)S		�e˖T�^���������f���裏̼y�7o�Ǐ�����i���-���t�/_NHH!!!,_���)�:���/V�x���|��G���УG�J�NT���С�r��h��tW�\a�٢"w�����;vd�֭�Y����>��C���?~<���������\=i�j�?���X�6����ǎ;x�g8}�����ѣ$$$�j�*>��kN��������O>�����/��:�ܹsٴi;v�F����0n�8j׮}ͱF��C=�c�=f־~�z@AA����~�O>a�ʕ�^���]���[���M���Νcݺulܸ��[�ҩS'S�w�}�O<��3gLm���������,^����T�ޛ���n����ё������Z�_���ի�:��F�/��\lllf��Ѭ]�����cϜ9���7?��Y�ɓ'IJJbÆ
�]��g�y�Lc_�Drr2���3;g�����׏%K��i\�\666h�TJU����ln���5���+l۶���ݻwŲe�(**bРA4oޜGy�
�����jժ,\��Ν;�СC+l����O��|P���|�U�F||���.��[�z�����Lr�rqq���___���ؼy3�|�	����@vv6�֭�`0�{WWW�=J^^���f}yyy���:u���Μ9äI���#==���hbbbd߾}f�wW:g��O����S�/���رc�x�"�ƍc�ԩ������ʨQ�ؽ{7s����_`�Ν<���e�{{{�t�b�v��QLAA���㭷ޢY�f���O����f�HVV��׷��Q��ݻ7���
�ڵ��������7�4�bҤI�9s�^x�)S�ШQ#.\����~��������^��?�)�]�z_�+��=z������O4k��Էo�>:D�^�ptt�����<W��ՅW�~ࡇ⣏>�����ә4i�|�
o��V�
.��{��?�$00�tNXXM�6��/���j��*""""��m۶�^PP�̙3	0�n���ό3X�b�EѼ�ȭ�cǎ�;�W^y�>}��ia��Ѽys����Y�&0`�v"�?^""""""w �e�E������ӓ�+W���O�f�h޼9py��ݻ����x�"'O�����ӓq�ƙb�;U����Z�h@vv�E�6c������>��#�;���Ӊ���iӦT�^��;������/����|P�uRSS�5k�����*�.��fРA,X��ƍS�Z5�v��ҥK���OM���GZ�ly�5�|Ξ=K���Y�j=�vvv<��C�Z���ݻ��U�ݺucժUt��GGG�q>��c���k������~��M�R�Z5�f����Y���v���w���������Mnt��<ϕ��.�.Q�
�K�,�s��888`ooO�L�K�ٳ�Lc^���̉'�ѣ�V��U�V���Ѯ];���Z�n}=�/""""����i�)�V˱c�<x��mȐ!;v���X+f&"R�9s�`kk�ԩS+lOOO�M�Va��*���҈#�˫�v�֍N�:
����)n�ȑ4nܘ={�0t�P:t�@�^����O�^�:�&M2�֪U��ZY߾}�ܹ3���9ۺv�Zw("���{\����*�dĆ�aÒ��1s�$9'���ЬO�C��0#��ՕC%�aʙHkJ��S�j
�(�����z��:KWx�o�n�ޯ��z=���z]��BT4��gΜ��)S�X`)))�;�'O�0`��/_����ѣ���ikffFvv6����R������a	�DSPPT��9��\��r��СC�?c���w�}����k���<x0�����ʾ��ۓ��MBBB�Ŗ[Y�ꄊ�~�I�\�]X�ų�_��\^�U���Ǐ�w��M���5>������~��R�߉�G�===e�!�B��d���X����ٳ'}��e���Z����X�~=���{2��7�����qrr��̌���c>�<(�;�#w2Hjj*���t�ڕ
(u5j���������>�� �Ϭv��|��wxxx(��
�,*Z��+W
���燽�=�����.B!�B!�jz�@����r����
===����q���_�^��d�y�P�R�e�N�8Arr25k���Ԕ�ӧӲeK��ܹsٰaIII�
��v�ZΜ��� IDAT9Ä	4b8s������ׯ�X!�����q���]�VྩS�r��MZ�l�Ν;�R�����X:u�T������w����Ԯ]�X����������yJ�f͚deei�ϛ7�I�&q��yΟ?�|��۷/C��O>�����b˭,޿f͚Ѿ}{Μ9Cjj*�j�"%%���`Z�j��(��Kr���Ç�����q����+���\�p�������u|i~'ԉ�]�v����{�x��7n{���uB�W�����CB�´i�HII�ѣG�޽���,e�����O��|�HLLD�R����+W��ё��pV�\���)�5"))	WWW4h��y�d���9BZZ���Z����	

%00��Ç?�+ ��n���l۶�͛7ӳgO]�#D����/9u�T������qssc׮]dgg3z�hZ�nM�Νu�B!�B!*"I��,,,,��gdd��hR����ӿ���5kbmm���			4i����"""�6m5j�(�I!��Q�U
��e�����U����SV���@�W�hٲ%aaa\�|�nݺ�'O�����a�zvւ6jժ���ԫ�ĉ�]�6�|�
/^�?�`�֭lݺiѢE�Ė۳�j���o�%((+++>̓'O
]ݢ,�/�u./��Vԟ��k�.�͛�$K�Vi~'�״�Đ�^{�b�F�����8�wH�S�f�pvv�aÆxxx�R�8qℒp���ELL:t`޼y����������߿KKKjժ��ŋ���c�…l޼�E����CV�\���aaaʌݹ��m۶Z�˂��%�BQ�yyy�XW�	]L�W�S�N�[���΂1b�2щ�������ߟ�ի�g�B!�B!���$�B����֖���퍃����ccc���BQ^j֬����w�^�W���ߘ5k�*U��ˋv���Gjj*<(V�z�",,�#G�+���իt�ڕ!C�����<�~��=RRR�[���1���Sb+Æ
cذa���s��1Ξ=�ٳg�z�*ׯ_g����߿��c{��/7u��������Jyy�_R���T�TI��ѣGe�ɓ'��W�P���aܸq���[�9��͛S�~}ڶmK�֭��gi~'��ܻw�z��i��EY�???]� �BS'3U��AN�6m
䬖�R�4����pqq�q���h�ggg,--	����Y����ooo>��S���;vl��]�\��$�ռys�:BQQ�7^.���,*W�\ш��_��OOO���3f�R6v�Xv�܉��'vvv:�N!�B!��$\�
���jϪ��H�^�:���̚5������~֭[W!gB!��ѲeK.^�ȹs�4hP��{��cƌ!--�%K��B���	DGGӣG�"�3f�}��6mbΜ9����������&&&���/���2p�@�c.\���+KM�6eҤIL�4	��~��!C�(�ul�}���ٳ'FFF:t���l�9B͚5��ʥ��\�2YYY���i%�\�~�����)���2�к˖-`���L�6Mc_bb��8s��w�C��={�_~�EkE;����I>B�+��ٺAQ�?éW'���R����
S���jlϘ1�.E�-���ϋ���ݻ����e�:B�2�9s&իWg��պE�P�$���,���	$11}}}LLL:t���X�ziiixxx���M���4hS�L���@#��1������K׮]iР�R�Q�F����������T!�B!�/?I��t��;;;V�Z�ܬ355�qTB!�(O��ŋ,[��~������Q��ϏѣG3h� ��s��,e_�>}�����V�Ett4o��6͚5��͛@�����#((�ѣG����5j���[�X�j�+Wf�ܹJ����_X�r%����x�=++K��ӷoߢ/R�7oN\\��Ѵo�^c����V������_^zzz��׏ݻw���Crr2C��jժ��qթS�;w�J�>}4��T�gn�����믴lْO>��к����˹�Y�Fy���^�j%���6lgϞe������O# ;;[9F�-KKK���u������޽{u����I�ř�[___y�_gQIT<(I��R��_"��L�K�/;���ٳg��C���۷oW�333���"**��*+��^FFӧO'&&F�����J�"::77�B'�8r�iii�~�hnnNhh(���>���]!�B!�/6I���6S����<0$�B�����ذa���8:v�����e�֭��������~6l�@ǎپ}{���f�ƍxzzҨQ#f͚E�Z�		�/�`�ĉǸ��ӵkW:D����/4hM�6%33��ׯs��!V�^��۷Y�p!�:u��s����8q+++\\\hٲ%���̛7��'OR�F
fΜ���p�ر���2r�H���{��ͩZ�*�/_V�@r�ZP����+��ٽ{7.T�˳���ٳ'���c�ԩxzzbffFBB6l`ӦM%n�ɓ'���߄�����F`` ���xxxh%��մiSbcc�;w.�-�~��\�|�+V�c��ޝ;w�L�(���g�}ƚ5kd�ȑ,]���-[r��5�ϟ���K|=D�F��ȑ#u�����)	B���������YÆ
���Ү];bbbpss��޾�c�իGRR)))ԫWOc_JJ�RG!^V�6m��ɉ�7�J�x5��p֯_���������ʮ]��D������"&&�:0o�<LLL�����Ņ��P��ߏ��%aaa�&oжm[�X�e����p!�B!�BI�B!��<4i�F���c��֭�V��7ҹsge{ɒ%DFFbhhX`��Z[�j�ƍ�2e
˗/g�����{�=5ʚ7o�<|~�ڵ��T��…Y�x�F�믿���7#G�d߾}�۷OcժU�Y�f�_\_�5�����~���Z��4i·�~�\b+�W�A�Q�R%nܸ/�,�/����s��bcc�ի��>www�N�Z��E%�c����"cqpp`�ԩlڴI+�c�����r��5~��g�6mZh[����U��v�b���޽�ݻwk�R��<y2U�T)�\�B!����Ӈ�[���䄃��Z��޽{xyy�c����ؼy3?��3>>>t�ܙ͛7cgg�Ν;�ի]�vr>�fgg�|mӦ
III���i%V���)u��e��~>��s������p^y�����s�5j������q��{�fĈ�1�T������UU7n@�-pvv��Ғ��,--��ʕ+�~7ؼys�:B!�B!�x����B!��L
<���&O��o����>�kצ_�~j݌�~�z���<y2�N�bРA���k��[o�t�RN�8A�jմ��СQQQ���3p�@�����קZ�j�nݚiӦ��l�6d�.^����
������all̄	/��fIq��y���kڵkG�����ӣe˖|�嗄��k� -��J����ؘw�y�����$P�������XXXP�N�֭?���}�Y����ӣ~��������Llll���g�}ƶm��ܹ3U�V��Ȉ�>���~��%K��`��Ḣ��w�G�DDD0a��������1c�9�WCa[�>}{{{���O����ׯ����={���mffV�C4���燽�=�������:!��Y�y��DFFbccC�n�0`;v�Z�j̙3���T����Q�K�,AOOO�^�h���ԩS+++��|n�����_]�7�Y!^ǎ#44���.\`�رL�:Uk!�fϞMժU			��c��ѨT*=zT�z���XXX(�c333廝���B�{�.�3�F^�2u!�B!�B��d�!�B!�Q�֭���(V����T}��ի��T�Z��>��T��k׎;v��zU���]�6...����$�������/����755�Z����8�kc„	L�0!��Ǐg���%����-[�d۶mZ���(cc��'^L_~�%�N�Қ����,\��cǎi����?�>}�ӧOӯ_?/^���A��]ф�����Ʈ]����f��Ѵnݺ�V�B�j*������T*�l�‰'HNN�f͚���2}�tZ�l	���+���/Vf�nܸ1,Z�WWW�-[�ܹsٰaIIIddd0`�֮]˙3g�>��9sCCC�����"����o�%!!��/�������͛2��>������(B�W޿��d}]�)Փ�<y�}��q��%6n܈��3f�`���%�W�P<(t�z��ʕ��T����B!�B!^
�p!�+�2��XQ~���9r���B!�й5j����իWiժ��-[�ХK��M�S��-_�lǎ��А)S���ҰaCRRR		a������ϒ%Kʬ|���΂1b���dee����z��:�P!�˨�����)�0dٲe,[�L���?��?V����O���5�ԬYkkk<<<HHH�I�&$$$��i�de4!�iÆ
���۬^�GGG�}���L�>GGG�T���ŋ���,,,����رcl۶�5k�(�ŭgllL\\(�D���#))����ի��/%%E�#�B!�B!	����dԨQ�C!�B!J�[�n�<y�ѣG�j�*�u�FժU����ٲe�~�-S�N�q����0;'@DD�R�h޼���nݺ<��ݻ3f�1b;v�]�ϑ��'��Ɍ3F);v,;w����;;;F'�B�[[[<���7x{{cll������B��111a���,]��Q�FѢEe_ժUK�X.^-C�%!!GGGL�V���?4VN)n�>}��u�V���ppp�U�Vܻw///v�؁���7orV����&>>��M�ЦM�������J����S�!�B!�BH…xn�����uB!�BQj�W��o߾���ӷo_���*U��Օ޽{�p�P�o�fݺu�={���tLLL�0a���45������ ((��������3h� �L������ܯ���طo&L�H�ȭnݺ��ذn�:~��G%�B�Npp0���a``@Ϟ=��/�_�~�}�t������;Ǐ�Ν;ԯ_�?���S�bhh�Վ��/k֬!22��U���G1{�le5���,���	$11}}}LLL:t�Ɗ�������ҵkW4h��7j�333|}}?~<�j�*�mB!^xիW��ٙY�f1~�x���Ϻu�V����B��ꫯ���aƌ:tH�����-...�����ꪱ��Դ�&N��ɓ'����Jj�V�s��Q��ԩ�ݻw�����ؘУGN�:Ett�F���������NZ!�B!�/I�ύ��!ċI���B!ī��Ԕ��(V�^͑#G�y�&���4jԈ�={2k�,�w��0E>dʔ)ܺuK)�|���l�[FFӧO'&&F)KLLD�R����+W.��K�.��SϞ=Y�n���Z�V�X��x��DDD��兑�Q�'�˃���O�q�R����������T*jԨ�q̴i�HIIQ�޽{7YYY899�����ە����DEE�Ç7nG�!--
sss�����	

%00��Ç�|�B�U�.]���cժU̘1C�AN!�x������?ЫW/|}}5V���W����BOO???e��oЫW/lmmK\����JŖ-[8q����ԬYSSS�O�N˖-��s��eÆ
$%%�����X�v-gΜa„	��9sCCC���ܮ�B!�B!^�p!��.����ȑ#u������5�eB!�x�����|��w�C����7�nݢq��|��7�mۖ��(�ϟOrr�F]///bbb�С�����Ą��8\\\

e���XZZ�����
���q�1����Z��={�u��ѵkW~��7�ϟϟ����vvv����۹q�M�4a�ҥ�mۖ��,X@ll,[�n���N�f͚���LÆ
���@�Rq��	%�bϞ=�_�333233	��Օ]�v)	����m�V+.uYpp�$\!�xeX[[cmm��0��L��у)S�`oo��y��t�����ZXX`aaQ�ŭgdd���=������߿?����(�Y�&���xxx���@�&MHHH ""�iӦiMZ �B!�B�W�$\�����ooo]�!�(!�CSB!�BTꄃ�����8q�NNNt���Y�d���Z�����B�ƍhѢ���XZZ���e�q�g���+�+���l�����訬ѱcG����1c'N��J�(L~�ݩS'�͛�̙39~��V{4m���T*�߿��Q�<��ۛ7nлwoF���#4ڹr�
����W���5�!�B!^L������Se,$ċ��֖���퍃��3����1666:�N!�B!��$\!�B!���;CQnjj�U7>>���3ccc�A�$&&����$.�'!!A��W���5�;w���[�
�>:u�Q������1&&&�k###�����ٳg�x�bBBB		aӦML�<kkk�U��Ի{�.�j���C]��#�B!�x��߿��s�������e���
�Ua�3V$իW��ٙY�f1~�x �w}ݺuc^!�B!�B��$�B!�B!�^އ5���G��$*U�Td��<xP�w�y���D�;ƤI�
�w��1�~^yW�P'<T�\�о�+wE^�����O����޽;'O�d߾}\�t��7���Ō3>|�Ʊ�Ŭ.˯}!�B!D�w��qƌ�ĉ�[�����Lu��;;;V�Z��3�A!�B!��.I�/��<�SX�fv100�~��t�ޝ�'Ҹq�2��b)ɵ�h���		rf�5j��#B���uB��z�7�~�:�.]��w�U�/]��U��ؘ��88���q��>|8xzzҫW/Z�l�U��իl߾KKK�����c���p�|���Ҹqcn޼IDDݺuS�#""Ju~��򅅅���p��1�m�ƚ5k���z�ꑔ�DJJ
����8>%%E�#�B�G�OBQqEEEaeeE�~�X�~���e�E��<X[[cmm��0�B!�BQAI…�������ɞ={8|�0nnnt��Q�a��/<<777v��Evv6�G��u��t��Yס	!�x�H��B�N�~��~�:˗/g�ҥ���[���o,_�\�n�>}غu+NNN888ЪU+�ݻ���;v��̌͛79+4dggOӦM�ԩ�1dʔ)L�:��}�R�^=n߾�ѣG����?���8p`��e˖)qFEE������:���W�޽ٺu+...,]��v����w�^�J|-�JBB���<�V�Z����c�iӆ��$���+���:B!D~d�$�ӭ[�<x0]�ta�ΝT�RE�!	!�B!�BQ�$�B�b�=���Ǐ����qss#$$����?�ٳ��ի�0B���΂1b�2{���������_�#!�ϝ̆&��7n�8>�͛7�8qb�u'N��ɓ'������Fc_�j՘3g��]�N�޽������8p'''?~�ѣGY�f
k֬��O�>,X� ��֭�g�v�=zt�}�fkk���lj��g�����6m�UV��������ꊫ���>SSS�u�=8u��������@�>�B��d�$�WJJ
��N�:�ٳ�5j�:$!�B!�B!tB.�Ι��/֒�U�V孷�����֖�W�r�������$99�1c�(ecǎe�Νxzzbgg���B�
Ξ=˺u�t�����/�ٳ���x�6��^�:���q��i<x@�-���a�…(u


Q�Tlٲ�'N���L͚5155e���l�R�;w�\6l�@RRJ�������>}�����(�߿O�ڵy������/0�5kְh�"BBB�[�}/�� IDAT.dʔ)q�wn�j���ӓ~���'Or���իG߾}���022*ֵ����
===����q�o���z����V�7`�֮]˙3g�0a�FgΜ��А~����!�/7?	�b��ͫa�ȑ���?�?�ڵkY?++�ʕ+�CdB!�B!�B�/I�ޱc������<z��ӻwo���4fӹs�6l�ԩS�����2o޼|�,I�����3q�D�͛��ӧ5.������ ((��������3h� ��f�	'���������={��/��~��}��]___֬YCdd$U�V壏>b���+=��z<�����/6n�Hpp0<�y��L�0�������'�|�̠�����x���hҤ	���#55___�v�J�
�z�5���___ƏO�Z����
!�����?#G��u(B�
���KKK]��ʩ[�..�(KLL�gaoo���}�m��ߟ��������/4�� �k�f�ڵ%�;���ڵk����C�����_�����W�fM������ !!�&M����@DDӦM�q�Bh��/�TL�*U ;;��ڜ1c-Z���_/V��۷'88�X�]xx8���(6��R�����_�!!�B!�x$�BTh�6m���C�,))	___�߿ϒ%KHMMe���$$$(�>�Ç��,I���ܹ3׮]S�222�>}:111JYbb"*����h��ܴf�Y�b�ѣG����2iiڝ6m)))J��w�&++''�_���ݻw�������1���,\���O�2d�F��J���ѣ�>}@y��ȑ#���ann����9���2|�p��B!DY����uB�
B��(?�>iii8::ҿ

���cŊ/ԃ3/[[[<��������퍱�1666:�N!DE&�'!^2�yu:�D����qrr����9ET>,--ٷo_�&�<o�����	!�B!�B��%뺊
m�Ν8::̹s��8s�Roǎ$$$��o�m�6Ο?����FDi�Gݺu�w�R���ELL:t��LJ.���G�Ν	

e���Z�={�u��q��yT*�7��?������m֬{��!88�ɓ'p�ĉR]����m۸}�6�ڵcϞ=�>}�aÆ�R�7n5j�`�֭m�.z���жm[�8�e�:B!�B����puu��?��w�e�ȑ���Q�N�N���_NիW��ٙ������Hbb"�����ٙjժ�:<!�B!^Z���:OX�z5�6m"44T�q<�}���:��V�����8?B!�B!^.�…(wfff�*����dgg��o�q��!�]���?�����'O�`޼y�o�SSS���kf͚��nI��ӧO���NAAA���иqcZ�h���3���h-���訬�бcG����1c'N���ή��:88дiS 'qA�Rq���R]���ٳg�ꫯ�zNNN�
�k�fĈl߾�s��annNjj*�.]�f͚���p�� '�#��͛k�B!�B����C��ᅮ��AÆ
y��2e

4�u�/�.]�`ggǪU��1c�2fB!�B��lllضmS�N%,,L㾙x~֭[��kBT���B!�B�\�.Q�ݾ}�9s���o�i��=3ĭ[���D���y���JR��1ԩSG)������"�cbcc�ʺwﮱݹsg�xKۮ����������,��$��y��ЦM�|�T���a׮]xzzbnnιs�x��)���ݻw�U�����2u!�BW���<x0���G��֭[XZZҠAt^�p�ʕ"?�o???BBB���n�F�*�Є%P�re�������u(�
�u�ŋp�B��������o	

%33kkkfΜY`��߸�����*��u����Q�2C	Q~*U���ޙz;##{{{�mۆ��3g�dɒ%ܹs�3fp����`����}��iii������GժU���Y�r%���ưq�F:u�Ċ+HMM��Ϗ�����7n,�X��Yㄜ	ھ��b����=�Ν�z��9�U�VQ�fM�N�k������3�v���͛СC>��S�L���޳�p�����9R�q!r����:!�B!�ρ$\�r���Na7}V�\�o���o��|���	�۷׺1��9��͞S���q��E�z�-�>
�{u���W'%T�\������W^�8o�%�ve�~e��[�.Ç��LJ��hΜ9@�^����}���e��O!�x^��������:t�YLɗ_~ɩS�t�ra}������Ʈ]����f��Ѵn�ZI�B!�B��ϟ�|���P����1Oq�E�2��b�9s&����ҥKiѢ7nTV�OKKc���T�\OOO��nݪ������ٳ\�xQc"2�֭[��W_�p�B�ɷ���pqq!44�#G�h��)m��=�O�>�^�W�>}�s����͛y��F�y9::���*����������/���`mm����NcB����aܸq�C!�B!D�~*Y�
D=��J�b���2Dc��'Ox�74n���`̭$u��������{�V��3�8p���0����P��"##5����x��7��ݢ��z<��6l�:F^�Ǐ���]�vq��9*W�L�=����� %%E�Xu���B�+%\��_u�N��p}����`�F����1�7��ʊ��瓞�^�Q
!�B!���{�M�6ʼy�
-/kE�y��5�OI����XC	Qq���r��%���Y�d	vvvT�R�˗/E͚5��{?y<x�C���c���i޼97o�d����Y�J���hР���dff�믿ҳgO�=�J�*q�iii,Z�H+�իWF�n݊�W�6m�z�*iii899��?��egg+��d�Ç��cRSSٸq#�ׯ/�Z!�B!�B���$\�����������̟?_)��>��Ņ�/���~��W�-[��VI�����DGG3{�l�]�F�&M0`���O�>899q��e�>}ʝ;w����133c���Zm.[����h�<yBxx8...��nQJr=�G�ꄉU�V���ģG�X�r%fff6L���/���Ç��>o��6�����_��}\\�V?�2u!��<���)?۷ornԚ������ܜU��%*OOO���3f�R6v�X����f~B!�B�=�x�,�'�133�r��Z.JN�PBT6l�cǎT�V�ٳg9IQ?��u��eذa���(�>�q�F������J�={
�S��ĉt��===ڵk������U�8۴iC���ꫯ�����`�Ν��k����jՊ�ի3g��޽[��f����HNN���7������+�B!�B!^|z�@����ݛ��.\�…��_�|ssslll8v�W�\a�ԩ�h=|_���tC��Ȉ+V�����M�8��'O����F�jժ)_��V�n]&N��Q֮];F��L��$��y�?i�$�������O>���g�i՟0a������Kc_�=8u���ј��j�S���!��U��_�q�F���y��͛7g„	<X�^jj*���?~�;w�P�~}>��C�N���d��}F�e͚5DFFR�jU>��#fϞM��������ݝ��@�����Ą�C�bii��V��aaa�kwww�ΝK�֭ټy�F���+/��;55___�v�J�
�:�5RfƏO�Z�J�F!
���1�B���A��(��k׮��#oyq�1jiiixxx���M���4hS�LQ�7
w����G�aɒ%c�Ç3�|>��#\]]��x�qYq������X�y��u���|�M����ѣG5�ͭ���={����y��5���\����g�6�+q��W�-��W���u��r�},̪U��<y2����`�����={65j�(�XQ��\�R�k~~~���н{wF�U��	!�B!��%%	B�
����W_���Μ9�ӧOiժ666���︻��k�.���100��ݝ���s��1>|�|��xʭ$ub``���1��Ǐ�aÆ�


Q�Tlٲ�'N���L͚5155e���l�R��5kְh�"BBB�[�.ԸW�v�s.Žϣ�z����鉛��ϟ�ѣG�lْ�'ҷo_����P���5�
0��k�r��&L����̙3*7�B��s��U���i֬�w�&::��'Һuk|||�{w����֖۷o+e���,\���O�2d�<x���~ʍ7�zIII����J�Һ�<m�4RRRx���w�&++'''��ܔ�=233���"**��2nܸ"�_�f
���>�睟#G���������>sssBCC	d���%�IQ��{��w�^]�!�B�@i�/�U�qLFFӧO'&&F�����J�"::777*W.��	g�ʕ���ҨQ#���puu�A�̛7���Y��1��z"��lll�q��Ν�_��W����i�JV'&T�R��c�J^PT�8맴}��V�R�B�W3f`�޽xxx����V���ťT+�����/9u�T������qssc׮]dgg3z�hZ�nM�Νu�B!�B!^&�p!*�Z�j����ܫ1@΃����8::j��[I�f�1�Y����{{�bկ]�6k׮-�v��Y����q����y]�t	�f͚i�XT�fM������ !!�&M����@DDӦM����B�z�%�Lzy���m۶q��mڵk�7�|C��������Q�TJ��۹q�M�4a�ҥ�mۖ��,X@ll,[�n���N��f͚���LÆ
���@�Rq��	%�bϞ=�_�333233	��Օ]�v1n�8��e��ТET*�ƍ�:��m۶Z�˂���a!!�Pvv��CB!��$㗂>�T^�q���111t�Ёy��abbB\\...�����~,--��@�+-�>�V�Z,^�;;;.\��͛Y�h>d�ʕ�{���ˊ{-d%ċ��ѣ?~�ȉ�Ο?O�>}��ӧO��?�ּys�\��͛7i֬Y�\��S��&MbҤI�����޽�+V`oo/	��ԩS������`�F����1VVV̟?��z�B!�B!�C.�/���4������?Ə�o=[[[<���7x{{cll���M��+�B�G�`Ѿ}�|����g�9��5m�'''%)B�ĉʾ�;ЩS'�͛�̙39~��V…�����q�P�Tܿ_�_�F
<x���77nܠw�ތ1�#F;~�'[@��;?W�\��}���5�!�ƨQ�t�B�����xe�t��<,,�T��*�8&((7n�$�;;;ciiI@@������ ]�v���ooo>��S���;v,��3�ϳ+c(!^;w�[�nE֛:u*^^^����$�;��c�
���+��֬_���;r��mV�^ͪU��ӧǏ/��x}U�T���l�^�J�֭011�ƍlܸ:u�Dll,@���҅��^t���$''3f��l�ر�ܹOO�RB!�B!�I�B� ��}�u�֭���^�:���̚5KI�ؿ?�֭�Z�j��B�Wއ�V�\�ʕ+��K��t�R�����?hӦM������r{�w4�����Dy��M5++K)�={6�/&$$���6m���ɓ���.��h��9%U����ݻw��d�R���!ʆ��?#G��q$B�W���!!ċ�4��*�8&>>�|�Q?�[%Θ1�.E�-������,��+c(!^�{�WÆ
�޽�F���3g�,�GGG���˹s��ҥ�ƾ5j�z��\�}��_�"99�6m�ЬY3n޼���ӧO���N�>����e������;���$&&������	C��JDLKK��Ã�� ���o�ׯϠA��2e��Ԓ�;��	$������ҵkW4h��iԨfff���2~��|�6	!�B!�B�$\!^
4 %%333����R�J�u�t邝��V�rn<����W�B!D�U�R�g:>wE^�����ӿ�w��ɓ'ٷo�.]b�ƍxyy1c��^d����������Y�[}l�ʕ���˞��
!�y{{cmm��0��(ƍ��0�x��M:(ͬ܅�_�������B�y��3�R�e\V�ce%��e߾}���H�
���f���&iծ]�s�αd�~��G022�s��|���JB\Y(�����%K���o����'''���y��1ӦMC__�
6@˖-��O���Sf��qssc����vff&QQQDEE���C�3wFFӧOW�-@bb"*����h����v�����077��gnnNhh(�����Q!�B!�"?3!�(aaa/��e)  ���`���{��i
bmm��իY�zu�K[!��!,,www:t�@XX�ׯ���T�<�?4l�(zv�ƍ�Q��666.U�FFFXXX����۱�����Y��T��y��R�߹���S�^=RRR�����u�B!���y�_Ԋ3�Q�q���'44�b(Ȇ
����]�vܸq77�29�g9V�PB�Fvv�F�W��Җ׫W��~����nݺ�ʕ+�V	���:u���w�q��M233�}�6����}XYƙ��;w���?j%[��1c�p��u233ILLT�'O��/��Bzz:���DEE�|�r^{�5�6E�={��~�zΟ?��ӧqtt`׮]J=///bbb�С>>>\�p???:w�Lhh(���4/s�@۶m�bP���!�B!�B��$\!�BQ����������C�=X�jIII<z�+WbffưaÔz�{���Ņ��H�<yBdd$˗/�W�^%�{�С���������4Z�jE�֭��WLj��/��:u��w�^��ӹq�����>�nӦ
qqqZ���u�B!���y�_Ԋ;��ӧNNN\�|��O�r�����{��̘>}�R�$c�������йsgT*����ܹ������'��{������T��֭��ݻW�����4~�*jԨ�b����?��È#S�(�������[��J�*�h�ggg gR��\�r�f͚i�k޼�F!�B!�B����uB!�B�
*B�ŤI�

"22�O>�Dc�g�}�����������3y�d�zM�6�*+[[[\\\puu�J�055U^שS��w�bee���1(��޽{�g�֮]�ڵk077תW��ί�=zp��)���5��������s�ʕ|���?���"$$���$�y����3fFFF:���S?��,�4���@���5jT��&����<�/��.�8f�ĉ�<y���Hlll4�U�V�9s�(�E�y�z�5,,���T����Q�K�,AOOgggƎˢE�صk���%9��b,�2�B��?d���|������7����e���,^����BBBشi�'O��ښjժ)��	~��SԪ�w���wJ]��#�B!�BQ�…B!�� o�ů����]�ի���'����V�Z���Ӷm[V�X���z�j���ӓQ�FѠA�T�B�
;v,[�n-�C�VVV,\����z011a�ĉ,^�X�7w�\�4iB�*U���(��9s�0b�j׮������,X����_��F��9sF��3g�`hhH�~�J|=�/�/���q��i�_�z��c����G||<<|��+W����θq�HNN�A�_xx8nnn|��W̝;�����밄BT0aaa&�=��Zq�1����T*���166�J�*ѻwo�nݪ��Y�1OA\]]�믿ppp�q��4n���w�aUWy���@Q�<�&9R�h�����m#*����aA�f�0��GDǜ%-���iJ��S�n3oE`<4ʄ��
�����o7<�Q?���W����������������Wx�_M�{��P��{ IDAT"uÕ+W(**�v/^LQQQ���Ƚe��Y�whe���[�n%<<�.]�p��
�/_ΐ!Cظq��]YYY��\�v��z��L��[.}0�ۈ��������	�p!�Ubb"����CD�`�v""������K��Ѷm["""~�]�f�&88��v�}0[Q���w�;�yyy���U�1���		!$$��W�+�iӦbbb��ͥ]�v��撞���ɓiҤI�����c߾}���\�~��ݻ3e�:v�Hii)'N���?��ɓDEE1gΜZ�����:ƅV���8;;�s����~�z����U�""��j6����c�6mӦM��]E�Ư���?�E�+���+��Re�w:/�C�X_qq1#F��Y�flڴ����w�W���-"  ����[��#GGG���Ǐ�k�.V�ZŒ%K9r$������e��ܰ&Z�lI^^�l�Ҭ�����FDDDDDDD�N)�B�w�}��Ç[;�C...�ADD�N����;			�\			8;;3v�X+G'������n�������Z���c�аaC^x�"""������N���#??�ѣG����X�v-qqqZ1:�S�C�XOYY'N���*<i�.x���Y�j|���4h��!�}2l�0rss			aȐ!<��S|�����ؘ��ߟ�+WJpp0O=��������g͚5xxx��'��N�(++��ٳ�ϱ�~�i�����ɱH����1��SJ��C��ﵺ� �AeggǬY��2e
�ƍ`���,]��ƍ[9:��ŋY�t)���WWWƏό3󟋅����İs�N~��GZ�j���1i�$lmm���=Z�h�?��ŋM	F...�vW�^��=͛7gӦMԯ_����ٳ���Ю];����III,Y����5j�K/��ԩS�N�z�*����޽�K�.ѪU+@@@���q����Ν;����w�޼�j����͛DGG�c�.\����
���6�ls��Ϣ��]�z���$�u놓����M�6xxx���ĸq�ppp���YDDD�͡D�gƌ�_���[������T�^�z|��'q��EZ�nm��>�'""���H"##��n?�d„	�ݻ����ļƍ��{o޼9�/_���ggg�l�B�^�طoYYY��deeЧO�{}{"""""""�Q…�7K�.%11��a��2$$$X;�:��_$00�ŋd����ׯ_gҤI�;w�Tv��IS��튋�y뭷8~����…��ƒ��ETT�YbDE&M����	`Ĉ��ݛN�:���	���k��Fll,_~�%^^^�����зo_�k&O�LAA7n�`�ƍܼy���P�]��o�Avv�隼�<9t����4i�Ĭυ�e�S�)))������#QQQ�^��tMII	���dffr��uƌS᳨�u۷o���OOO�><==9t�;v�`�ȑ�#"""u��P"���?f�…�Y��X;�*����{�nk��H��f,>>>4lؐu�֙��۷�O�>���������g�}ƞ={��ϧiӦt�ڕ��z�'�|��v���|������Q\\���裏HMMe���f1���booϠA�j�EDDDDDD�a�����`[�T��)��tE�e00�CD�!!!�s��Ѷm[�͛���;���������o�6>>��ǏөS'f̘���+999DDDp��!6o�����9|���iF#F��iӦ,_��U�V�j�*lmm�ҥ���g��ᦓ2ƌCRR+W��0���O<��f͢u�����˞={L	�W�&;;�v��1w�\���9~�83g����Ӭ\����@�>8�ҥK�֭'N� ,,����oj�i�&�-[���%%%���Irrr�s��^����ZhU��,--M	"""0͡DjOBB�������R�x{{�����6mӦM�������\�iӦbbb��ͥ]�v��撞���ɓ-6"����h�<<<�^U��ٳ���P:w�
]�v%,,̢ߝ;w���
4�cǎ̚5����j������Κ5kx�w��� ++�E�a0���h֬���|��|��W\�z�cǎ�v�]pp0...4j�ȴp�ʕ+����K�.��<*�56$$OOOlll�ܹ�)y��`Z������u�駟�����l޼���P��N�:�J()�C�fmDDDDD�r�~�-'N���&$$���X���?mڴ1�0!!gggƎk��DDDDDDD�a�.DDDDDDD䡒���/�`V^>���ٳ��y�������;&L�����+W�_��-Z�رcINN&..OOO���+~��gz��IÆ�oո����vtt��͛����\�t�bv���ϟ?oc�=̾���8wl�ԩ̞=��r��AV�X�ĉ14nܸ���u�/_�����c��������T��͍M�61d�k�"��74��j�_;;;f͚Ŕ)S7n�7of�ҥU�aEDDDDDDD�C	��3�QX�7�*j[�7���5��.�_޺u�8x� pk�ϨQ�je\y𕟷Tg>SVVf�}�z�~�My׮]���O�>�������Y���-���DGG��B-Z�`�ȑ$&&���Ejj����lll���2�'e�W>��ض~��=��ˋ=z�w�^����;���ˉ��'((��#GV�wu�3���c�jr�"""""��W^y��!�X݋/�H`` �/ ((�DDDDDDDDjJ	"R+�=JTT��ɔ����k����f�IUDD�a�E�""�Ӿ}{Μ9ñc��ok*?v�E[gggrrrزe���5��ݝ#G��q�F�~�m�z�i�ƍdž
HNN櫯��~����ի��mۖ����t�w�n*OOO��222�68z�(������9::��퍷�7Ǐg׮]�Z��%K�T�pQ��Z�lI^^�l����Sy4h�$""b�}�f00�CDDDDDDD2J�����
G��{***b�̙����������뱳���8DDDjC�޽Y�n����:��r�
4�3gΰ`��Ν�3�<É'X�`�E����r�JBCC	橧����7���Y�>����bв�2Ξ=���~~~9r���X�]�ƈ#pqq����#G����ƹݯ~�+�
Ɔ
(++�K�.<��c5��~���r�J"""�;w.�>�,Ǐ7�kE�f̟?��\233���`��6Æ
#77�����SO=�����Q^u�{�����#''�"�˜����O�y��ȃE�'���7r?����l�2hР���1Q…X�qW͇1�An���#??�ѣG����X�v-qqqZ1:y،3�m۶��w�1a„*�N�0��{�����رc��7n�{�g��y��\�|���ٲe���gܸq�Y����d���-�x�'x��w-�Ǐ��끊#���ߟݻws��Y&N�hV���bQТE�������k���Add$���fm�v�Ze<չ�W�^�۷���,������;&"""""��i޼9�6mbŊ���;�GDDDDDDDD�D	R��ڵ����s��InܸA�V��ׯ���4i����ҥK|����۷���"��3*�&mk"44��۷3g��b*߶maaa���K�'?��˗/'--�k׮ѡCƏov]y�%��/�y�&����ر�.`cc���+Æ
c���U�w��U���ٽ{7�.]�U�V0������-�MJJbɒ%dddШQ#^z�%�N�j:���ի$%%ѭ[7���L׷i����7n�}�"""uځ3f����:&!!��`�0*U%����MTT����ڵkt�ؑ�c���������=���|��g�ٳ���|�6mJ׮]y뭷x��'Mm�O���L^^��Ŧ�)S�н{w6l�?��.]�DÆ
�С����l�jԴiS��}��������@\\�~�){���ҥK�lْ���o���hq͒%K����iѢ/��2�&M2{.>>>4lؐu�֑��
@����ӧ�����S���G}Djj*�Ǐ7�#55{{{
tG�DDD�?�<�4�����l:v�h�0�g�}�>����PF�A�v��������������V�XALL�YY^^III\�r�9s���O�8���\S�m۶q��u�>kҶ�BBB8z�(�-�k׮�iӆ��<"##qrr2%u\�|.^�h����ӄ�����?3t�л�#**�իW��/))!33���L�_�^釘׮]�7�0-��[�;11�C�k�Hh���p��
6n��͛7	

`������i1���'�bǎ�9��YDD��)++�v"RGԫW��!<�Z�hAxx�Yمhժ�Y���#ӦMcڴiU���兗�W�u=z�G�5��رc��0�/��,����f͚Lppp��m֬}��/����ۻ�6�S��6m��` &&���\�b���\��ә<yr�I*""�p�I����DFFAvv�Ŝ�aFrr2S�N5�(�,11���Dk�!"""""""��R…�ik׮n%2:�z�ꑙ���ɓIMM5�[�f
����oߞy�����Fff��⚚����D���8880{�l	�O>���3ׯ_gѢE��EW�Z�ŋy��g�7o�Z���+��߈���넋M�6�l�2<<<())!%%���H���+M�X�z5��ٴk׎�s�������Ǚ9s&�O�f�ʕ�]��O0k�,Z�nMLL����ٳǔp��������xƲ��4%\������=ӷo_
			���{{{rrrX�p!/��U�+,,�������/�ƍ�j<�������wL�"			8;;3v�X+G'""""Rw$$$0c�>���6�n�V�|�r����������{��w�N��{O	R�*K\(_~��a���OYY'N�`�֭���o�n��`�w�^f̘�s�=@׮]�ӟ�Ĕ)S��I�;ѭ[7			���dff����o�[S�����@hh�)I�n5i҄k׮���@vv6������__�*�۳g�)�Ν;ХKf̘�;���ݻ-.���M�0f�bcc�r助�ԩS��Č�:t�`�FDDDDD�^2d6l 22���H���͛`��n�۷��k77��N�P���1k�,�L�bJ:ټy3K�.�q��V�NDDDD�nؾ};'N��#o����ù\�����wޡ��4m���!���������#N	R�]�x���{�'NX��~��s�LIF�ZZ���3�bQAAA|���dffұcG��?�՟?���~��}��ԩS�={6���X���'b0�\�����J�����㾝����k�	7o�4�]�|�u�Gy�2cyp�:u�ҿm֭[���ѣ�F����D�dLߺu+��׿(..�u����ٓI�&���d����(((��Ã��P4h`�x���_$00�ŋ���]�v�rT""�0����/��������;�Si��P��ȑ#|�������?RVV���3={�d̘1�m������H���_���ë��JDD��é5��_qww'""����[;�:m�ҥ$&&Z;)�""""""��S…Ժ�Ɠ-*JhX�h'N��}����w���Օ�{����߸h���񚴽_�իwWח����(..�����G��ݻ�/���cǎ�|�r���	

b�ȑ5���lllL_Wt_Ʋ���[���y����u�����۷�¿�=JTT��ɔ����k�������?o�HE�QQ�~}��ڡT(%%�*��d#��T���DD��Ƒ#GL�_�x���{���Sii)���g˖-ל={��g���_�`����sO���D�ӧO3t�Pz��Mll�#�YJ�֭Y�~=�:u�v(��@BB��� 11�1c�X;��,W@��!�ݴbcc�:u*C�5�/--�}��f�deeY�Y��w��?����<��dggeVߺuk�֛�5a|3���릲�ptt��ۛ��V�^���?W�\aɒ%��o�-==ݬ����s��hٲ%u�2cy0�۷���"fΜ���/��δm����(**��(EDDDDD ##�+Vp��!f̘Qe��V�i���lٲ�F���o���DZZ���DGGӷo_nܸAhh�'�h�&�`;v,;v�o�������
8��y����������5)�B���Mqq1'O�$,,�T~��^~�e"""8r���������ᚴ��|�
���<������ҵkW֮]�7�|cjӫW/�ևhyyyܸq�E����#*�y��|������Mdd�E�aÆ���
(,,䩧����
0?���~����MFF���ddd�`��;�9�x<}NN�E����#�EDDf���Vqqq���3z�hS���������Y12y����q�ׯoZ�\Yym���oٸq#���|�駼���<��4j�;;;�v�ʒ%K8p ���lܸ񞎯��Hݴj�*�l�B�&M�����������#����J�~�HII!<<���p���'O����رcٵk�N�"  �T?x�`���5i{�_�@����\�z�Y�fѤI�̙CÆ
�5k~~~���&99^�uv��IFF�����y��7�|�6m⣏>⣏>���Ӣ���?DFFZ$dt�ڵ����ٽ{7gϞe�ĉfu...e�ѫW/���GVV����SE�$�CDDD��ŋY�t)���WWWƏoڽ���æ������İs�N~��GZ�j���1i�$���F2~m��())�nݺ���djӦM<<<HJJbܸq888��m������C��իDGG�{�n.]�D�V�0`��ۛ��>�֭pk�RY�͛7���fǎ\�p\]]6lÇ7��n�O7n���???:u�T�}N�<�F����~����M���fU�08u��]��|��y���9x� yyy��������ѣG���xGc���6�[���УGF�U+㊈��������	bu���>�///��찵���c���D���dlmm�����ח�͛ckkˠA�

��&mk*22�~����`ڶm@۶m	&??ߔ�вeK�����������Y�p!C������{___�5k���-���̜9Ӣ������<��3���bkk���+&L`��ٕ����@\\�F���ɉ
��䄟�+W��xò:L�&MHMM��KMM��ޞA�ո_���ׯ3i�$RRR�r�
%%%�<yҔlq���b�z�-V�Z���)))�…���2u�Tn޼Y�X۷o������POOO
ٱc�=�7y��3�z��饗^zY�5f�k���v�o��k׮�~������<�4i���w�wTT�}�gϞ������B233�7o			�vw;2�?>x��*�u�ؑ9s�зo�{6��n""r�����w�����~����֭��ٳs��uN�:Ett4cƌ!??���y?=z���(>���O�βe�HOO�vX"""""""RM:�B�4"""*���t
��M�BHH�YyE�5i[�]M�ϟ���-�_y�^y����m�Vzo��mggW����Q�͚5#88����_[QyӦM1��Đ��K�v����%==�ɓ'�8l�Z�����s�h۶-�����ݝ��L����>�������t�ԉ3f���JNN:t�͛73|�p��`o�; --
�b�������9r�]y@�[���!����d���dggӮ];�Ν���;Ǐg�̙�>}��+WP���M�6�l�2<<<())!%%���H���M:�v�t��:t�P���MDD�}���u~�!ׯ_�{��L�2��;RZZʉ'���9y�$QQQ̙3��c���EEE̜9___����[��i� IDAT���~�z���j%�s:�BD�;ڴic��[BB��Ό;֊�������/��{�� 44�Ν;cccC׮]	�h�s�N"""pss�A�t�ؑY�f���R�X�N��'���3."2��]M�O�s�t�b:�o���w�q����֭[�O?����/�f��ͦvw;2�BQ�^=���\��h�&"��.���E���x��~���nmz���FÆ
iܸ1/��ic�X3�_G~~>�G�6�������O\\�#���	"r����1k�,�L�¸q�ؼy3K�.�q��V�NDD�ё���/�`V޵kW��gϞ��ĬӧOW9��˗�['��g,3��ݨQ����eee�AD�!77�.]����=�ϟ�㾧N���ٳ9x� dŊL�8��`����Ο���8�<��=;v�Q����<�233�ԩS�IW�JJJ�ѣ��X;��&�O��z�*����޽�K�.ѪU+@@@���f��hт~���/��c��չ����RQ٘Ư����>}:nnn|��'q�OJJbɒ%dddШQ#^z�%�N�jv�ŋY�t)���WWWƏoJ���^����֭NNN��۴i���III�7����"""""""Rw(�BDjŋ/�H`` �/ ((��ŝ"""��Gԗ�@�6�_<X������ڵkU���_��P=c��He0�CDQ����3��a�<����xj�����G��ݻ�/���cǎ�|�r���	

b�ȑ��ϟ^|�EΟ?ϗ_~I@@�Y]e��Hs7���_̀�����_�v8u���
������{�3�N�:Y;$�׮]�7� ;;�T���Gbb"�"66�t���I��?>�1�޽{өS'lllj<��%K�z��Y�CE&O�LAA7n�`�ƍܼy���P�_�ΤI�8w�隓'O��-n�}�v
�������СC�ر��7���������MJ��Zc0�hJDDĊڷoϙ3g8v����oM�ǎ�h���LNN[�l��ٹ�c�lْ��<


hٲ�Y�����""""""5նm[���;����޽��<==��3�stt���ooo�?ή]�X�jK�,1-������[�la�����Ջ�{��v%Wh�&�����d�С���K�?���<�~�mV�^�[o�Ejj����O��=yp���dggӮ];�Ν���;Ǐg�̙�>}��+Whj?b��6m����Y�j�V���֖.]�п����m�cu�ؑ��XS��<��̚5�֭[Cll,{��1%\$$$p��9ڶm˼y�pww'33���0����JKK����bcYZZ�.DDDDDDD�8�-�DDDDD�4h� ,X@VV���dff�`������ 44��'O���?s��%���?xxx��[o��?�>{����駟 ''Ǣoc��������ȝ�ׯdddPZZJFF�i�ӧO�;�{ذaxxx�a�
yꩧpss0�Y�n�O���o��ƍ���,]��S�NQ\\Lqq1��׿X�~=�ƍ3��^�����u�;w�!C�бcG֮]K�
���~��|��|���|��g��N���0{�Rymٳgp�V�Ν����K�.��!v��mq�����9k֬�w��Ã��,-Z��`�����cǎ��d���`\\\hԨ���+W�Ty]�v%,,̢�S�N��8��С�Y��t…�����#b̘1l۶���	&T�v„	�ݻ���ƎkV׸qc�{�=�͛7���������̖-[�ի���#++��]��]������'��T��emٿ?��9YYY\�r~�����C�޽�S�N�-~��{^�n�G��5�V�)��ߟݻws��Y&N�hV���bQVӾ#""���$22Ҭ�y��Ο>��6lHrr2�W�f����Ծ}{BBB��ؚ��Ծ������#[�l�I�&��������°a�prr�vHR���t��Ŭ��^��^���;&L�����+W�_��-Z�c~�����kGGGn޼i*3&$c6*�{����888X�ˌmDDDDDDD���	"""�Q�z���K�{�z�>|��������7�=�
6��͍9s����fooOll,�ggg4h���#���c�ʕf�|�O�N�v�hР���<�&M����jGjj*����7DD&������ȴi�ؿ?�/_�����~�����3u�T��?�~^މ��ߴ˦5=z���(>���O�βe�HOO�Z<""��j����@\\�F���ɉ
��䄟�+W�4-��>>>�����3�`kk���-���L�0�ٳg����	�A�L�>���^}�U~��_ӨQ#�ׯ������#""�
6н{�{6��n"����~��'�o�ί~�+k��@�={6M�6�߷v(u��wg�ߡ��[��	
F}���Ã��|�:[[[���L����n�XU��tYY���5�կo�,�X�0��-""""""��	r_%&&RRRb�0D��֯_��`�v�A����m�0DX�7of�Ν��ѢE�����.\�@�V����6mӦM��O///����ʚ6m��` &&���\ڵk���.==�ɓ'kGy(͟?�]�vaooϤI�0`�[��������'��s�NlllL	o5�o�>���Z(STT�̙3������5,,����cggW+q���ܮY�f��m+��YY���w��׹������������ݫ�5w�]˗/���HMM����v8,{{{���x���)((�Y�f�I��m۶|��w����%����L�u�ő#Gظq#o���E_Ɠ&*Jf��ڷoϙ3g8v����oM�ǎ�h۲eK���(((�e˖fu�6"""""""R�)�B��ݻ+�B��ꫯ���-wgȐ!2��a�<�JKK�pq���ۗ��BBBB�����ޞ��.\�/�pO�����;			��O			8;;3v��{:��<z<<<��K4����tRRRptt$66�:��Z�h��!C�ѣ�G�&%%___:w�l���@\\����=�T����ڵk���#00Њщ��ȝ��M����`РA<��s�������iԨ��C�JԫW���2Ξ=���������Ν˳�>����Y�`p�T#???�9Bll,׮]cĈ���P\\̑#G����߿�c�k�
�̙3,X���s���3�p��	�=��駟&//�����
c���Q�������Hݤ��o�}�]�}�]k�!"""�@1. ��>̐!Cذa���DFF��7oޜ���{:����f�bʔ)�7�ub�ҥKiܸ�=KD�"���DFF�w�^7n��/�LPP�ق�]�v�~�zN�<ɍ7hժ���#00д��͛7���fǎ\�p\]]6lÇ7���_0~�x�d�۵hт�cDzt�R�����.�?���҈��d�Ν���һwo�}�]�)D����=餢��W���ݻ�t��Z�b��`ooo�ORRK�,!##�F���K/1u�TөW�^%))�nݺ���d��M�6xxx���ĸq�ppp�������X��n"��A�J����lQ�5oޜ˗/��ン�3[�l��ߟݻws��Y&N�h����Ŭ����7�5k֐��Lrr��O<�����y��3�m۶��w�1a„*��Ջ}�����E׮]�겲��$���p!�͘1cHLL�v"r�			�����j�DgΜ�v���`\\\غu+��׿(..�u����ٓI�&�-��W^|�EY�x1AAA.���/!!!|��W�����DJKKM;7�X�����k���HJJ�ʕ+̙3���(V�^mjSRRBff&���\�~�1c�p��1�։BU�ݻ7K�.��ѣu.4-�q�)))������c��ڵk���dgg��[bb"�"66֔Pb4y�d


Lcoܸ��7o
����),,����b<OOO:Ď;9rd����As7���5N��>}:�1yyy���@\\�~�){���ҥK�lْ���oZ�{�L�B���ٰa���?�t�
6�C�8???��mEc�kvvvDGG����v�;vd�ر���ckkkj;x�`>��#RSS?~�Y?������3hР����������;J������F�E@�cr4oook�!Rgm޼��;wZ;���~֯_����`�ocT�c�����O�[�ggg>��c���سg�)�b�ڵ��Č�C�R�^=233�<y2����~6m���e���𠤤���"##INN6����?���\e\�?�8���u`�ҥt�֍'N��牏�'00���,�[�z5��ٴk׎�s�������Ǚ9s&�O�f�ʕ�]��O0k�,Z�nMLL����ٳǔp��������xƲ��4%\���<�4w�{���///��f͚l����=zУG�;���s��궃[�W�����]�p�tB%@ӦM1��Đ��K�v����%==�ɓ'[l� """""""u�.�z��Wy��W������n�jC�aȐ!�C��*--}�.DD�b�$�_*�}!ğ��':v���o�IRR�.]2��߿���2N�8�֭[��?��7�|�:!¨I�&\�v�������ׯ��������m�=�aê�n)++3���BBBL'Ht�ܙ��P���سg�E�DU���@hh(�;w�K�.̘1�w�y�ݻw[�g<		n%a���r��S��S��[��u�����������èo߾���������p�B^x���������'!!��d������3cǎ���EDDDDDD��p!"""""""�'�|��u�f��y���ŋ���{�8q���ۓ!�N���ٳ9x� dŊL�8��@�ƍM휜��p�.\0%.T$77�Ծ��v>����;w��{�l�.]���~�?��WWW�׎�����|�2�ˌmDDDDDe�Ν���Ԕ�,RWU���ݺ���Zې!Cذa���DFF��5oޜ���2;;;f͚Ŕ)S7np��K���� """""""u�.�u��)�~�i����T����U�V��у	&жm��
�V�.�Z۱�[����7�5�V���+??�μ��ֶ�>-Zĉ'h߾=����puu�瞳�xyyѣG����_|��c�X�|9���1r�H�V2Åصk���z���ڵ�Ծ��c�ׯ_�T��	���ؘ��W��E����X�e]'""""�(���0`����پ}���y�ddd�m�6�)"���tȭ[������bZ�nMϞ=�4iR��+����x�b����ڵkm�."""""""wH	�Hz���ٷo_��s��y6m�Ķmۈ���s�ε�Ԇ�G�Err2eee���k����v���u��a6m���Ç������e˖<���ҿk�X+�;?�9s�U^�
hڴ)�?�8����;������x��}�-J�����ױ��4o����lS}ii�)���ooo���9~�8�v�bժU,Y�Ĕp1r�HRRR����O�>f'l}��^���Ç[�gdd�mp��Q~��_���ڶm�w�}Gzz:ݻw7�������\��Z�lI^^�l�Ҭ�����FDD��4��Eaa!C�������k���9y�$!!!xzzһwok��@��=h�ׯ��`�`0��;�FDDDDDDD�{�=��f߾}U�>|��JKK#>>�=zPXX���G���j)�G����oEEE̜9___���i۶->>>�����X�6�.]b�ĉ���k$''s��nܸAII	yyyl۶�I�&��op��5k��P��矹r�
Ǐ��>c��|����K���ŅW_}��a�H�ꫯ���b�0�
���Mqq1'O�$,,�T~���
���6l������z
777��T�.]���+�PXXȤI�HLL�~������<���y��7)**��_�0�{���deeQZZ�ѣG���`��6�S$Ξ=[�=������222(--%##�ЧO�?'�)�999uƲ�'I���TE�'���7�������#;;�]�v��[;�GΨQ�x�嗙<y2%%%�GDDDDDDDD:�B�θsg]�A�Q�F<��3�����ߟo���-[�h׵�@\\����=�T����ڵk���#00Њщ�
/^��ח��֭[3q�D�����?N�
����ٺu+�~�){��%  �5k�РAk��@)�Dii)�:u��+W�k�.�O�N�f�,NщuO�޽������_�~���Nxx�E�ɓ'�����ߟ��"##���4kӵkW��CCC���×_~ɒ%KX�d�E����g�̙�ԢE&L�`V�����k���o޼9�/_���ggg�l�bя��?�w���ٳL�8Ѭ���Ţ�:z��ž}���ʲ�שּׁ,��9DD�ѥ���<L��?��_�{�nS��Ծ��(~�߰x�b��?Y;y���.^�Hxx8�gϞ�;�;v���aJ�0*,,dٲex{{ӳgO�����)..6�����������i����k<����?�a�����ݛ�ŋ-Ƭi��O�&00�޽{3p�@,X`qRåK��3g��ӓ��0
+��1�?�����g^z�%z���ѣIII���;���͛|��'���гgO����믿n�3�իWIJJ�[�n899��۴i���III\�z���"�(	�￧{�,�|�I7n���
;v$((�
6�����_MBB���~�5lؐ�-[���Itt4���j�sO���D�ի��^z�e�JLL�����ν8�>���;;;lmmy��X�`$''���Cxx8�<����������ʄ	�={�Y����DFF�d�����c�=F���i޼9}��eɒ%��/�Q�Fƴd�z��MÆ
qrrb���|��'��ښ�L�>�v��ѠA�J�6ppp ..�Q�F���D�
prr��Ϗ�+W���X��5x�`�4iBjj�E]jj*���4����ȣK�'��z0_��X���$::��k�ҽ{wk��H�ر#aaa̝;���lk�#""""""""�p!u��י4i�Ν3��<y�3fX�-..歷���㦲.KVVQQQԯw9F�?�<���?�j܅�v �q�)))���oZ�r'�N�<���S�7n��͛�����&N�Hnn��m۶q��u�{��_�|��ӧO��?��СC+x�5�%**�իW�ڕ�����Iff&ׯ_g̘1l߾���B<==-�����СC�ر��#GV���������ٷo/^���gϞ��OZ�wuu��>˟����ɧ�~���z�*���2�w�y�&M���}��7�۷�-Z�|��*幹�LXX��Ɍ?�"�+V��W_q��%Z�lI�^�

�C���י3g���`�…=z�F�ѭ[7����ҥ��u�}��}�iii\�p�ƍ����K/�Ą	*����V����U�|@ZZ���?غu+Æ
3����������;��?��իWqpp��'  �����3:}�4˖-㫯��ʕ+���1u�TXa��u��Y;�#t:^�,�|����5&]y{{���]����K߾}��ިY�f|��GU�������ˬ��{n֬���W�_u�WӦM1��Đ��K�v�[���3y�d��'EDD�K�'���7����{fϞm�4J�o���$$$�֭[��}���HII���`����ADDDDDD�%\H������s�h۶-�����ݝ��L������7k�����ԩ3f��Օ��"""8t��7of���>|�tzBMwCmѢ����k<��8�ҥK�֭'N� ,,����O``����O0k�,Z�nMLL����ٳǔ�f�rssi߾=�����͍��L���-�~��j�*.^�ȳ�>˼y�hժ��_���Flll�	5�eӦM,[�JJ8�G0 IDATJHII!22���dS�EZZ�������Ҕp!��o�aҤI\�v�T��?�y�f�o������ׯ_��lܸ���6m"$$����T�����駟���Jrr�i���d���c�=��ٻ������!R22��9��C2�i�a�!aH�9�<3�!b��T����Ö�$
��d�ZdC'9������wx�o7���^�뺞��{���u=��о�N�-r%B3m�4��ӕ�����}��q��1�l�B�n��l3""+++?~d%�:u��gϲ{�n:v�ԍ�����Z-��ɓ'\�v�k׮�w�^���Kݺu�$��^��������5_}��N�RK��)%%�1c�p��5�����3g����;}��)R�%�G�ϟgҤIj�DGG3i�$V�^]�~_#G��tB!D�����ȑ#���(�>>>bmm���B��d�$�x�5jԈ��h�~�mM�"���U��e�z�쉿�?�F��tH/L�.]$�B�
D~�B!�B�W�$\�r�Jv(��ҥK���H�v�011a�…̘1C�~PP���Y�;99aaa�ѣGs%�j�r�*���)I����WvVh׮���888�$\���y��all�رc�����Ç��3g��`��}�] �~~��W̜9S�����灬��U�����'�5j�����������Ջ#F0b��6oܸd%��Z�]UG�������@JJ
�Ǐ��ښ
M`` ���̚5�'NP�^=弼vؼy�2�}ŊJ�����#Ϟ=��ʊI�&ѠA�����/���f�̞֭=�_RZ�޽�t
��ڹ~�߽{�3f���N�~��;w.M�4�֭[�^���'O2}�t�?Λo����/���?��	&ЦM"##�?>�o����
��e�HIIa������ӰaC�>}ʕ+WX�x1111�_��o���Lbˮ��_q��mTTT���l�µk�hѢ˗/��w�EKK���h�-[Fxx8�6m*R�EI��Ç�5k�r�_|A�ƍ����?V�X��E�Jt�B!��tttprrb�̙���p��!֯_�+�W!�B�ׅ$[T<ݻwg͚5���{�党1cF�g�B!�B!��lI…������V0��$��n߾
��v�111���޽{Ԯ]�T�������С��g��m֬�򵾾>ϟ?W�T�WTr���_�@�V��l3?ʼne֬Y,Y����PBCCټy3�Ǐ���Jm�����Y�f��Te�:B��ݻw������s��Q�;v�Hǎ������ooo��9����v�Z&N���}���KFF���X�t�R޹sg���;,,,8p�p���m޼y��k�Ν���bff��͛����E�l޼BCCٵkW������ڥKV�X�رc�|��Z]U"—_~���R�
]�t��͍�r��I%ᢴ�eWV�_A

r����X�f��\Y�5k֬�O�>\�~�H}�������?����ӦM�o�ΨQ�/�ŋ2S�]�^�7n�{A@@���@��N�|�Iy�&���:ub�ԩJ����C��t!��"JLLdժU����������6mZ��/B~c!�.ȡ��$$$P�jU�z�->��CF�����,�	!^]��u��Ǝ������B䐙����B!�B�!I��.���L���J�*Z'���䢆�/���w�y�T�f�!������Z�v�V��|]�=��v�x^T�y�Eqb177��̌3g�p��A�\�¦M������Ç�Œ�����J�%���G�JpN�F���ӓs���;a�ѣG̚5�gϞѳgO�����.\���:׹�^��2��Ӂ��cJJ��ͤI�r}�iii1i�$BCC9s�L�ו�P%��9dhhȭ[�?~<666����J�B�-r]_icˮ,޿�T�V
�����={6�co���0%�G�N���ʕ+3e����Կx�}��焄��;`xx8nnn������ɨQ�hٲ���*�����WTVVVXYYi:!���.\����j�����Z~c��7o2q�DRRR����nܸ��78|�0%�9S�_B�j�Z�*>>>�CA��g�tB!�B!ʘ$\�
�Q�F���o\�r���_)�r�J��������q��ae�mYz�䉲BL�^�J�odd��h(+}g�r�E\O�F��������t��U)W�
�݋�~��������ЦM�"�W�X�2dC�!::�S�N�c�\]]��x��j�?x�@�#DyQ�Ԓs��nݺ��1GGG���O7n̺u�\���qծA�[�.RLzzz<|�����<w�)
U�9w�Qi߾�Zl95n�8W�*$�:S�Ne޼y���+?W


�ڵ+}���O�>j�a��-��x�
���d�/E��p��M�\�•+W������RI��͛7<GV�֬�4�7$$$��4-ZĈ#��}KKK.\H`` :::��B!��	��͛�ԩO�>-����7Z�f
)))t�҅�3gҴiS�>}ʯ��ʚ5k�~�:nnn�Νeѧ�����0r�HF���0�d�)��!�B!�x��^�]�
����X����(�>}�իWY�bE���{��&_�~�gϞ����w�}���)�'OV�v.�}�v�1<~����(f͚���ѰaCP�~U�/_�\Oxx8����n�0��ٙ˗/���S�]�����s�}�w��
�իW���@zz:�~�-���6,���СC155eϞ=���ҢEZ�l	��ѪU+ �Ԫ2U!�CQw�ɯ���?G�AWWwwwjժ��Njj*P�+T�9w�(ȳg��^�Ve�/aC�<�J&�I��CQ>�͛7���*e����ݻ��S�bnn��Qf�eW��(T�ׯ_�кG��W�^���{{{6n�����~��,�=R]c~�!���Ŋ�Ufjj���)�xyy�����ѣ��1cƐ������#B!�BhJY��T����hii���]`yyQ%|,_���-[R�J�W�Nǎ���v�,+2��x2228x��B!�B!�B�3��BThcǎ�رcܺu;;�����q��"##���V;V�zufϞ���]�6������CCC>�V?��w����\�Rm�~q�U�S�N��iӦ
�F�*U������ԩSܸq{{{�|���^D��~�)AAADFF�����8qb��'[[[���qqq���E�n�Uջu�FHHQQQ�V[W�ѣG��]�����Crr2��M"&&��K�R�R%\]]i޼y�}������Z�>:w��իW9w�:t(������}�����]]]>|ȣG�x�7r����C%��`nn���9��?���.]�ҥK����ܾ}��K����^汕�+��/��U"?�R~.6k֌A���[oQ�vm�7oN߾}��gI�Qa�<z������G������qww�ĉ���S�jU�5k�СC���P�+j=�J���� ((��w�R�n]
Ą	�	K���ӣG����s��ԫWO�ӠALMM�������}�	!�B!^N�=��ݝӧO���Dݺu�ӧ���jd�t�����W^^c!�����ͽ{�r������ܱP�_B����LƏ����y�&
6�tHB�vnܸ��bi���Y;Q��'��B!�B!^q�p!4.�E*:::�������ٳgINN�iӦX[[�x�b�U�������d۶m������.&&&L�<Ym�ܹsٸq#			ddd���6���|�����ZY�8�������_J�:u8p��C���[mmm���ٰa�N�"%%�?�GGG�?^��*���^^^������?���N��ͱ��+ppqb����J�*@�F��ѣ���J��n�:Ν;Ǹq��;w�zzz�+B��ƍs��5._�̇~X��?~�̙3IKKc�����ׯ�>����y�&�:u*��?�OOO|||?~<����?q�����.B�5! **���Hz��뜈��^Y222bĈ�1�ӧO3q�D�KY�V����={��ݻ
M�ظq#˖-c̘1j����?��V������lْK�.q���<�T+v����͍�;w*��<y�իW�z�*)))�;�X�222�<y2���J��x<==�����ͭ���?Njj*]�v�u�k׮���q��	�^�kBTlcǎ��C�
�tB�bHNN��>S�������/aaaxzzy�Ϝ�k,0a��/_���=Æ
�{��m�Vm��d�%D�Z�`�������l�KKK+��D�����			��rxx8nnn������ɨQ�hٲe��B!�B!�(
I�^�:uX�x�ZY||<u��U+���gΜ9̙3��6U+��TP�GA�گJ�Z�X�n]���_�y����2�|�ϟ_h�ѿ������n�8�xȐ!2��:���XYY���;w�$w��!""�I�&��A�%��r��56n�H��ݩ\����#G�0c�>��C<==��+Vp��u���C�}���M@@@����7o2h� 6l�ٳg����w����>}:7n�ATBB��=ZZZL�0A)�ٳ'QQQlݺ��ݻ�=���9��=���Li��ٓ;w�p��1Z�h�v,�N6e[I߿�ruu��hܸ1}��)��jǢ�+mj}����s�$���ܜK�.���A����p233ٶm[�}��o�>6l؀��)O�<��ѣ������L*j=ooo���i۶-,�Y�f������LXX����Bm��.\�u�ֹbU�]�pA&��9r��CB����/��;wKÆ
Y�t)�[�&::�E���ۙ:u*@�c����k,0l�0tuuٴi;v�`ǎhkkӾ}{z���ڂ=2���l޼��+W�k�.Y��%��ҡC���;���pD1����Y���ƢE�1b���@��l.$00P�k�B!�BQ&$�BTh={�$55����cnn���qqq�\���;j8B�2����ȑ#���0o�<|||044���Z�щ׍��5�v���/vvv̝;�w�y���p>�޽{�\�2s��U�9y�$�v��w�a���j��2v�X���ٳgo��&vvv�����%Kr=D_�|9���0h� >��3z�ꅑ�O�<��ۄ���m�6����O����~�ر�ر���P�L��_|A�ƍ���cժU\�xlllJ}̖-[�6m�-��Ąjժ��o��b�
��'�2���y��III\�z�]�vq��9�T����K�d��������cŊ̘1�ڵk�֭[ٿ�R���-4�$�h���xxxp��9�M���ٳiҤ	�n�b͚5������T\
+/ihIԨQ���d|||����W�^j���^PP���дiS��������ѣy&�ܸq��5&�&M���B��4�B!4�8���`i׮���Ă�6m�O�V.����B*���~��W.^���˗	�_~!  �͛7��o�I�2��h:����qvvV�����7ޠG�L�>��}�������M~	/;///=z�R6f�v�ލ��W�B!�B!��N.D���G�g�\\\pqqQ;V�vm���5�x�������̙3��‡b���T�^]�щ�M���Y�n���OXZZ���7�ЦM�
�~�:�^�m���o@���o�������͛7�y�f�z;vd���jeo�����L�2�[�n���g�+Wf���̚5K��A��]��iӦq��IN�<�v\[[��k�*�̔Ɣ)S8y�$111����:^�~}��}�2����5k֬��kԨ���+�~�������舏�>>>jǦM��?���[����T&d�$�HWW�
6`ggDZc�8v��9+W���/�,4qD��Y�f�d�BCC	

e��͌?+++��¢ֻ}�6@�;M�������Y�f�c�2U!ī��$R!�(/����AQw����,�S-���_�����ԺukZ�n���l߾wwwV�Zŷ�~[&}�K�>}�1c�`oo�k�p��ruu�w�a��Ÿ��j:�
��fӦM\�p���d�4i¸q�裏��=z�wwwN�>MRRu�֥O�>��۫%���\����WWW"##�V����c֬Y���%\f?�ѣG���ѹsg�ի��iР������acc��g�B!�B!DqH…���͛���1?��#���;ԯ_�>��	&���L���ԩS�Ne���888`bb����W�^���lݺ����s��]ttth߾='N�{��j�U֋c�ȑ4i҄͛7NZZ���:��'����뜖-[��?�o�>�?��׹�>�+W���333lllhժU�}��ۗÇ�y�f~��'���000�[�nL�<��͛�:򢧧Ǟ={غu+AAA���<y��z����3i�$�ԩ��b+�W�ʕ+�����o�M�=����nݺE:w���T�V
OOObbb��֦}��|����ݛ&M�0w�\|}}8p`���u�ԉ~��
6p�����hڴ)�f͢W�^|�嗯eb[a5���333Μ9���r�
�6m���eכ��+lRbrrr��U�����rS��Dl!^XYYi:!�k��חh:!^ke1~z��y��(��P�=HKK��ѣ��歭����-���*�2���[�l���S���7�|��+W2e�lll����������޽{JYLL�/�ٳg<�l��ψ��U�%$$���KXX�����I�&�����ٻw/ϟ?���1�s�?Njj*]�v�u�k׮���q�ĉ\;{!�B!�B�$\�
MKK++�Wf�ͫ�M��U�L���~��\;��'<<�D}t�ܙΝ;�mmmF���-wq4oޜ5k���jW���Y�&s��e�ܹ��8�_am���aÆ1lذ<��w��X�{�7n�$�e�J��ɊC__�!C�0d����9u�;v���U�adQ���Ç144,v,$$$��Ԏ���,B��F��ȑ#5��5���I��%bddĭ[�����K�.JyDD@��&ٕ�X�u��\�|��{�2eʔ\������	��<x�ʕ+�N����>���۷3y�d~���=ޱc��ݣM�6,[���u�v�Z��ߏ����p�s�Nbcciذ!K�.�u��DGG�h�"bbbؾ};S�N-Q�7��ɉ�����ၧ�'���8::r�ҥ<�//\�d}��*�p�$\!�B!���r/]$�B!D	���4k֌[�n�y�����mۖcT"?C���Ԕ={����J�-hٲ%U�V-v�޽{������y��III|��w���2y�d��j����v�QM&�NU��n:B!�B��S�^�pvv&22��O�Ɋ+���#J���Bcƌ��ӓU�VCFF��ɜ={�/��B����S�_B�f͚%^�_Tl�*Ub�֭����e�M��B�����+�����|��S�F
%�a���ʹ���@�gO�v�Z�*�۷g���>}���Λ7ccc�U��رcx��a��ܸq�J�ȩI�&ju�B!�B!JCv�B!�e�}��\�x��ӧ�`�ڷoO�j��?����7�Dh���-��θ���ڝ��Ĥ����8s����X[[�ի^�:�g�V^׮]����cii���!��[�n�����.@TTP��RB��G^+_V�6Ϟ=ˁ�����ÇԬY���{KKK�w�^�8oܸ�69�E܋����_x{{JBBU�V孷���?d�����뗸�ו]@@��������'���!�/[[[N�>��۷?~��1cc�\e�m�<�B�{���Ɔ]�v���,V�]�ƍ�1cF��)�/!����w�e�ܹ���2i�$�Ty}����_@�vw�����]ǎ��)�f͚)_�Ǝϟ?/��Y�Q9��Tu�B!�B!J�ˑB!�(s���X[[�k�d�7o�<�t颁�*��ZKKK�T�B@@���4jԈ=z`kk[�zzzzxzz�m�6���ILLDWW&O�L��͕�s��� IDATe�ƍ$$$�����X�n�Νcܸqj��;w===�����B�H�?f��Ŝ:uJ������ٳ�={�����d����K���NHH�F>cn޼�ĉIIIQ�222�q�7n�����xxxP�^�b�]�u�����憿�?����5��-[ҡC�R]�B����϶�5k����֭[9s�IIIзo_&N�X����̜9�.]��g��]�FRRU�T�I�&��ۗ1cƨ��/�/!�(��2gΜW2�"�ggA����J��Ĉ��L���{9e�9����iii�:�*+�	!�B!�B�$\�,00M�!�(���@F���0�/�w�}���m۶q��9���O�<y›o����)vvvʊg���@uȐ!2��s�ZO__�9s�0gΜ뙛�cnn�V������ܹs��
Y��EDD0i�$�	FB�2Y�|9�N�BOO�	&ЧO�ׯσ

e˖-Q�jU���������/֬YCJJ
]�ta�̙4mڔ�O��믿�f��_����[��-��HKKcѢE�1CCC kb�…	DGG�T�$���Q�V-�͛Ǽy�
���gc~��1R133��̬оʢO	!ԨQC~�����?� &&�6m��[��Ȉ[�n���NDD�2.��D���LRRR��� &&�L�600 !!�```�v�J!�B!�B�Ғ��B=y�O>�D�a!��5hЀ�j:񒲵��ȑ#���(��|||044�s�!�뫠�9+����=���>���4i�D9V�N>��#���=z4G�eĈ�k�Ns�@dd$��X��oP�J:v숳�3����?�L����"11�ѣG+ecƌa���xyy1u��2�O!�x��K�,�w�fРA��B�n�u놟��W���ٙ7�x����@�F�ؿ?�z�b���8;;�t�RڴiCtt4+V��G�J��k���8p��Ç���K�cT%pܾ}cccZ�jEBBqqq�+���:B!�B!��%	������G�a!�B�TT����0!@GG'''fΜ���
�b���T�^]��	!^6������p���W���qpp�Z�jju<<<

��ݻԭ[�A�1a�����m[��…������6ݻwgƌԭ[W�{��Aƍ��l�]�:u���f����߿_I�(j?�??�'�䕘���#���9}�4IIIԭ[�>}�`oo��<��???\]]����Z�j��׏Y�f�� Q�N���o�ݻ�k����q��CE���]ףG����s��ԫWO�ӠALMM�����Ɔ�5k�y��B!�/! �Y���
���XYYi:!4��O?%((���H>��c�c'NT��������ܾ}���ǫ�366V+�ի���cݺu�[���]��8FU���%���>|�nݺBTT&&&j�����$!�B!�B�����¬_���W�B��.!���u�ԉ�S��z�jr=4B���?>?���5���ח�O�*+8gdd0y�d����s������$**
777���
�c�ʕ>|���t�=JDD������p��z��Y`[ݻwg����������HNN��>#66V)KHH��ח��0<==�Q���9�&M�J�{�����8::*u&L����˱��gذat�ޝ�m�R�j�<�(�?~�8���yN��ڵ+aaa�8q��Ç��!��)����ӧ?~<_~��$[�W^A����兛�?��3���4o�;;;���ԫY�&^^^lݺ�3gΐ�����}��e�ĉjc�ٳg���EPPiii����h�"
T���Ν�ƍIHH ##��n�:Ν;Ǹq���;w===���_���B!�B!�����\�x���@F���P�����(!�/�˲ŋfee%�����?����!7n��Ϗ��`%���ۛ��hڶm˂h֬qqq8;;ơC����(����ϳ~�z:w�̯���…�믿�f�ԩܽ{CC��z뭷HLL,v?��f��Ν;����aÆ,]��֭[͢E����a���J�*�7��ɉ�����ၧ�'���j	Æ
CWW�M�6�c�v�؁��6�۷�w��XXX��R�{��u]�p�֭[�FUم$�B!�(���իW���d�ȑ8;;k:!4��ȨH��j�b޼yʸ:?:::̟?���竕���7~�Ynnn����Z���.VVVxxxp��6l��;w���`ҤI�B!�B!�(	I�/���>>>�CQLcǎ�tB!�B�QM�/�<��������M�0q�D���HJJR���쌑�M�6���	�=Zh����]ڵk���#+���7�T)��0���j�-n?E���#�ڵ�}��,X��iӦq���\�͛7ccc k�����Çs����믿r��E._�Lxx8���l޼�7�|(���q����S�&M��!�B�]LL}���S�NxzzR�R%M�$*�?����ׯӯ_?M�"���֖#G����$����`hh������B!�B!īB.�B�r6{�lfϞ��0�B!^y͛7W��U�ϟ?W�n߾
��!C�<?&&��>����^w��Ț��R�^=��㉏�W�r���~I�)
U�۷W+�ر#��W�s�5k�|�����ǜZ�nM�֭���###��۷���ΪU����o������P�f�\�Te�:B!�B�ܽ{�A�ѠA��ۧ���ׯ��Ã�ׯ+	������ɉ�3gbcc��C�X�~=իW�ptB!�B!�xUH…BQ�6lؠ��B!^J�w����l��<��&O嵓Dv��Ʌƕs�
U"����RֱcG���9u��~�i�m�:uJ�_�~J����U�*_�o�=HKK��ѣ��E��������ݝ��P����^G^ׯ*����B!DN?���*U��ɓJR��-^��ݻw�石s�NM�#��S�NL�:�իW�������B!�B!īD.�k�ƍ�j�J�L5a�0M�)��L���T@@�2���̌O>�D�	!�e#00P�!!�(���!qqq>|CC���6����Vʆ�ѣG���G�j;o�ܼyS��caaQ�~���Ȉ[�nA�.]���֭݇[s��e���˔)Sr���ԓ#J{�
HHH��{��RG!��A�OB���駟2r�H���4������ذa������ѧOM�$����
+++M�!�B!�B�W�$\����NHHH�K>x݄����憿�?����5��-[ҡCM�&�3}�tM� �K㣏>�t�"I�BQ��ݛ�۷���ȼy�hѢ���/����ڵSSS�l�R`˗/g�ҥ���;\�zggg��i߾=���8r�&L��ޞ�}�b``��{�8y�$��=iii80�1QQ��T����ܾ}cc�<��ի۷o��ٙ�K�ҦM���Y�b��[Eq�3�˗/���Irr2Æ
��ؘ��._�̚5k����R�{��u�jՊ�����r%V�<r.� �����<I��(����fʔ)DFFR�Z5M�$�B!�B!4H.�k)$$���b"FE����4-ZĈ#��L---Y�p!������h8B!^��k�2d�M�!D�u��!fϞ��0JLVSB�����gΜ!22kkk�cիW/��Q�:u���S+kӦ
�F�R+stt���ǜ<yWWW\]]s�ջwo-ZT�~j׮��������АÇ�j��֖ӧOs��mƏ�v���8WYQ���v�څ��?�����4nܘ3f(��s��nݺBTT&&&j�GEE%KBQ�d�$���ڰa�....|��ךG!�B!�Bh�$\�355*^B�x����HLLd���J٘1cؽ{7^^^L�:U��	!�%w��y֯_��0�̌3�޽���x���ROOOOO�m�Fpp0������bbb��ɓi޼y�m�����_J�:u8p &L@[[[����6...�={����s��U>|H�Z�x�����gϞ��g�ܹlܸ���222�l�f͚xyy�u�VΜ9CRR��ۗ�'���_Ļ�n�̙t�҅={�p��5����R�
M�4�o߾�3�5j(��s���n�:Ν;Ǹq��b9w�zzz��߿D�"����I����o����'''3f-[��tHB!�B!�BC$�BTx���c����?���4�5kƸq�X�`�>�&55����{�.u��eРAj�PT	ٿ.�DGGG�?�7�|�G}��;v��ү_?\\\���ٴi.\ 99�&M�0n�8��r�/���ϟ?��ݝ'NOժUi֬C���¢��=z���;�O�&))��u�ҧO���ն�V���燫���}r�~��5k��EQcy��~~~t�ܙz��)�
4���???lll�Y�f��BQ�ܾ}���@F���P�D``�������o��W���>s��aΜ9%j�V�Z�[��ȱ��ٳ�Ċ��sss������V�Z̛7�y���^q�#���fff��]Q�}^ץ�����ܹs��
p��"""�4i�Z��B��I�OB�|d|#^'3g���ŋ<z�HӡH�/��85�B!�B�@.D����„	���?���ׯ+��edd0y�d�������x<==������
--�2�m���������bbbB�
HHH��Ņz��)1޿[[[�ݻ����ŋy���.Unnn�ܹSy����^��իWIIIa�رy�����g�}Fll�R������/aaaxzz暜2i�$<x@zz:{�����8::+��Ǐ���J׮]s�յkW���8q�Ç/�]��'�������E9v�����k׎����(��=!�xyT�TI�!�J����ȑ#���(�#>>>bmm���B����xy�,㛋/��\��BG�*U^�Ϩ'O�(�B!�B!�e��f�������bdd���'?��3���j�"�x{{M۶m���ŋСC���8t����K��\����4�*5k�dɒ%����x�b�?��_MJJ
NNN����c��ݻG�6mطogϞeذaxzz���۷�
6���?s��Y�ϟ������ܹ���X6l��[������a����iܸ1����…�?����b�r��Z�n��U���B������駟bgg���/ׯ_�tXB!�B�tttprr�СC���ϡC�prr�z��O!�BhHLL����t(B�p>>>dff�?�'�*�?!�B!����B���I�_�tI�����H�v�011a�…̘1C�~PP���дiS��������ѣe��n�Ν�����LJ�>���W�2f���}������/066V�G�+DiըQ���d|||����W�^�1�#Fx^^��}��,X��iӦq��i�N��vμy�k;v,���<|��رܸq�J�ȩI�&ju���2��U���t6l؀��9o��&���c�������d�
�Y�f���o�޷je�W�!Fxx8;v�tB!D�שS'�N���իppp���D�Q	!�BM���gРA4mڔ;vh:!^����+�"�ǫ�|N!�B!�H…�����rM8�k���۷2dH�m����߼v�ȏ��/^��ի4mڔ�ӧ��믿hժU��,�Y�f�d�BCC	

e��͌?++�'!߹s�J��Nu�Uqg��L(;x<��رܿ��%$'U����+���Y8p����磏>R�>��#�=ʁ=z����YXXp��*��ƍ���@hh(fff��7!�x�g�2��2������J�a!�xI$&&�j�*���x��	VVVL�6-��!�J�QA��E�S�d(*�0`�>L�54�/�ŋ	d�ȑ�Ej:!�B!�/�$\�r��PQ�p�Zɺ�:9%''5�2�W�ő��������븹�9fff�9s��r��6mڄ��7>�X�eO�ȩjժ��y]WQcQ������
UYi������ݻw��/���c�t邽�}�z97�?N`` ?��w�ޥJ�*ӻwo����<ooo�m���?�LժU111a�رԮ]���BCC9~�8���;�?�v��t�ܙ1c����3�N����>�}���ς��xfΜI�z�pss#%%��G�Ҷm[�ԩ�ԫ[�.�.G�e�����f�2���-^U�t������r��ḹ����Off&�F��e˖t��A�
!�B!,\��˗/+��ݻW`yY+h���q���222���$11����+;�
�:������G�a!___Ǝ��0�B!�B��ܳ���@5j��+W��s�044�V-�t�R�aaa/$ƍ7C�6m������M�x�������K8HIIQ��kC__�!C����Ν;�����Ç����۾��j�ת�Y\E����Zm*'U���"���.\Hpp0���<y������w�z���/{��%>>��O�����͛7ٺu+?��C���9s�Ǐ����ٳgY�hQ�Il~~~���r��5RSSy�������d۶m���2h� ���oe�CՃzU2ޅHOO��|�HOO租~*�/NHHH��iii,Z��#F`hh������,\�����r�R!�B!�DFF�y�f���X�`A��e-�1��DƁ�����d����%((��͛k:$!�B!�B!�+D.D�ֿV�XATTO�>��ի�X�"W�޽{������y��III|��w���2y�d��*���ۥ��_~��ח:��鉉����J�n�X�z5			������bjjʰa��m[�z��HKK#66�\�����){��!55�-ZвeK@}G��z�����3���<}����H���ѣx7���������Ն�,���Y�e���4h�ggg|}}qrr��{*��'O�`�|}}ٹs'&L�رc��_�|Y��l�2�իGbbb��*G�`„	x{{��ビ������㏩^�:P;Wu�S�N@֪�M�6��O�f����j֬��d���S�,YB�v�011a�ڵ@�.-3f̠m۶t�ؑ�s��J�i֬����޽�:u�`ccC|||��$''3�|�6mJ�j�hҤ	�������իT��*U�ɓ'L�>}}}�ԩ��ŋHJJb������R�vm%�0;U���fΜ�V����W�ҿ*W�LժU�2e��`�}�'U}�ڝf��ŴjՊjժQ�fM>���m�V��///=z�R6f�����`dB!�B�������8Ci=}�TiSKKmm��E��8PhJ||<?��3������t8���гgO~��wM�"�B!�B!�IM DAƎ˱cǸu�vvvֵ���̙3DFFbmm�v�z��̞=[y]�vm�߿���%���>|X�~a�.]�ģG�prr�F�|��7T�R'''ƌ��_���?5k���O?%((���H>��c�v&N��o�z�b߾}�[��u��еk�\�lmmqvv���%WB���I�����r��in߾���Վ�*+���ҭ[7BBB����cTTP��!^f�|�I���{�����ڴi�ĉ�LHˮz�ꤦ�r�����O��}���177ϳ��	��%Z�l���=˖-#,,L��yv;w�$33���XΝ;G\\�򽝚�
������:t���:t�@JJ
ׯ_GGG�6m�(�T��d�*�[��_��������
ccc�����C���ؿ?ZZZ|��j�;99)����?x{{s��y._��$'攞�N�޽�S +���ٙ��0�?���z��i�pwwW^/]���M��i�&%�255��;w����LIOOg����_�w��γ�޽{���d%Rlٲ�gϞ������Y�j��:##���PBCCy��!s�����?���;'N� >>��U�ҬY3�����Z���T<<<

��ݻԭ[�A�1a�e�Q�ߙT_�~��XB IDATO���s��ԫWO�ӠALMM�����Ɔ�5k)n!��'00��r!�x�5���=z���;�O�&))��u�ҧO������S�e�t�����W^^c��P���i422�jժѯ_?f͚��� �@�z022��_�D)Q.�ׯORR��C�b�q�F��(;p����F!�B!�$�BT=P�����777Ξ=Krr2M�6��ښŋ���\OOOOO�m�Fpp0������bbb��ɓն��;w.7n$!!�����������͒%K�I�FFF̛7�����/_���^^^������?���N��ͱ���o߾��?{�l���

"--
SSS-ZĠA���YZZR�J����Q�F���[[�|ۯY�&^^^lݺ�3gΐ�����}��e�ĉ�����5��n�:Ν;Ǹq���8w�zzz��&B����oe�֭[z�q�شiW�\�ʕ+���3l�0��P�Z�\�۷o����w� !!!�>���V�\���.33S�z��;v����ӡC"""x��9:t�r��<x�]]�\m��TuD�ɑ#Gx�����Y�v-�/�u��add�֭[Y�~=�N��u~pp0�&Mb�֭\�p��c�r��-֬Yòe���s͚5\�t�.]��e�ڶm�͛7�4i'O����S��E%,,�+W�вeKV�Z��ŋ�:u*�۷���r�J�,Y����f����pڶm�ڵk�7o^�}����{\���񇈐�b��3#�Z��s�`�0�2�g�V9��c!1k�r�T&dBH�fs�ON�eRm)i�����tuut���~�u�]��z�^�wt��~=_��mٴi�F�"55���v�܉��yyyʮ^�������ʊ���u�VY�vm�.���ٲe������ݻw;v,���1}�t��)))�T*�����J$)h���dgg�,jiiIll,`���e�[��ٵk��NXB!�E���⣏>Ҹ���J`` ����T*jԨ�Xm?�1ԓ�6m�ro$''�;v�������s�
]�d�T�Z�
6�"�+����=z���ЧO���ۛ��`���5jmڴQ�B!�B!�(L.D�gll�…5�RRR011�(722b�ܹ�N:,n5��&�|�reE�
ĠA�4�7n���{���z��8;;���\j�666��ؔ�}�ڵk3o�<�͛W�s�$��5kbgg���/���4i����dΜ9ôi��!�/������4�����N��$��XZZҡC~��g>�ŋ	

�~`̘1Z�N�����(��J���ի4jԈ.]�дiSZ�j���\�vm����޽{�|�2����;wV�'�՟�L]GTL�/Vu&N�ȪU����aٲe�l������ˋ���[�%K���?���}||���&44�؄��Ͷm�x��ׁ�]`6m�D�V���J�X�n:t`���,\��{�����*��}��g,^�Xٝ�`_��@N�{
(���k�Һuk���hР)))�����}444$##OOO���bkkˌ3�1cF����`aa����Ã��`e����?			�o����4v		���Vc%؂DGGE'��ˢ��e���H���B!�(ɖ-[�z�*M�4a�ҥ���$$$�`�ٴi���Ŏa�+^c�'Ѽys���hذ!����T*"##��
!��ףG&N�Ȝ9s�߿�c-b&���G�Y~��=,X��#055���?>۷oWv�B!�B!�(H.D��������3������Ċ+x�wt�x\�ݻ���%�#  SSS���u�[�F��~�:�ϟ�Xq����e:���+++����r�
111�޽�͛7k%\\�t�v��)�/\�hN(/��ٳ,[�Ly�t��u�G��D�!C�p����Ǚ3g����l�S��n�"33�:u�h���������N%�[�V^��dףG<���޽;W�\)��ς:�����8�����jժ��.�����V
����ST_S�LQ�V����xnn�2a�(+W�dҤI8p��`�\]]�={v��kԨAVV\�z��={2b�F��Q/""wwwe'��-[��憭�-��������ŋ���?��h�B��B&��
!*����Gq���N�"22WWW%������Ņ�3gr��a%ᢼ���I̛7�f͚0v�XT*w��y�� �@!ī櫯�bϞ=�������pJ���^T~~~���1z�h�l̘1l۶
??���A!�B!�/�g���O�����W�^���|�ᇜ:u��u�2u�TG(W���qss#,,���RRR���
]�'D���p���CBB�="11�Rϝ9s&#G�����мys塷z�wA�~�-�/_�ѣG�?^�[�n��u��<x�o������R�����666�W�^?~���,Z�n�1�]ۍ7��W��눊������RT=�.+%���S������V.+-����qve=z4��ɨT*�u�Fvv6������klذ���̞=�jժêU�5j*�����z׮]�w����P�ԓkK�G�cG��g5uYi�z!^]۷og���C�
��!!^,���@~�EA����)���C�Ǟ<(򸺿�ƨfff�k��Ǫ2B�g�^�z�\��
6���?�:�'���h�"���C׮]=z4���uԿ
+\�~�믿ҫW/�O�^b9@vv6k׮��Ɔ��{�!C��~�z�߿_d_���8::ҽ{wz��͗_~ɽ{��:EŖ��IPP]�t�A�J�F�aaaAPP��ГB!�B!DA�Å��ԫs�����oܿ��
��{�1y�d��a��ӹsgY�r%NNNt��I�Q	Q�
2���~��w��ܔ�nݺ�:����6n��ƍ5�܉@�v�ڸ��j����1`��b�x��w9v����E���o�i��acc�����υ�:u�ĩS�HLLԊO����9��r��i��ǎ��7�,��-Zp��E~���"W�|��}����رc����W�+jeV(>!�nݺL�8��'���?�c�V�X�ܹs5N���ښ�]�r��v���ٳgY�~=���8991|�p�k)N�ĩ���AOO;�[]�8�'B�WG@@vvv�C�R�='�Н«o?Ϊܥ%ȗ��Cծ]���t��Ҋ�U4%%E�W�����q����$##�U�V1��"��y7n~~~|��'�8qB��<���t�u�R����…y��C�y�v===����z�[�����L�>����NJJ
*����x����~�L�6MY�&''�;v�����<�������������1KKKbcc9p��Q!�B!�BMv����vvvlݺ��Ǐ�l�+�/;;;���k���kƌ��p��0BBB		)򘾾>�/���###���dڴi��ۧOf̘�믿���>���4m�[[[��������t�ԉʕ+cll���
�-�x�_�ĉ�����}}}Z�j��ٳ������5��Y���nݺa``�/�����/��B�5�|8"^...$%%�$��;�_����;��_��Ç�����g�Q�R%z����S�(}�����ݗzʥK��2333*U��7�|Cff&o����zkժU�վ��666����e��s����JSSS���éS���bccK�^�z@�;|���u�B!��I4n���i� �{���q=�1T˖-���(�xdd$�Z���� �@�egg+��N
B�*U��ƍټy��Cy"�7o�֭[���ʱcǔ��*���mٲ%���,Y���rh߾=������O���бcGbcc	�j�y�愆�ͤI�����,����=
����L]G!�B!�� Y�E!�xU�^�ɓ'3y�d���IE%mXYYaeeU�~

qvv.�N�>j֬��ٳ���N�(H�;@�ƍy��4�U�^�A�JZZ��l���ƅ9r$e��b211a�������@~b�̙3�=��ٙ]�vq��	�PjԨ��_���svvf˖-ܸq�U�~}���h۶-͛7��g޼yL�>GGG5��en{�С$''�����iݺ5����*����6m��Օy��Ѻuk���o���ٺu+lذ�����ǵk�h֬m۶%55���$�	5���mۖ�{#�B!����ٓM�6����ҥK177'!!�/���=z<v��kշo_N�:ŷ�~K�ʕ�߿?���ܾ}�C�)����߿�^��ų���#ƌ�ٳg����Q�F�I�����C(R�ō�+?u�Ǐ��>S>�]]]K�-�,���\,�p�:����]I�lٲ%nnn�������F���Sb;v,*��;w���YDQ�"�h�B��B!�B!DA�p!�B����!''����mɇʱc�����~���ׯ���[�B7|||7n			4i�;;;,XPb�M�ڵ9q�K�,a�Ν$''cdd��ϒ%Kx뭷�Z|�k���͍�S�Ҽys���100 ++������k͚5���r��5����M����>�֭#!!�_�t��|���en��www<<<����8֩S'�	8r��Ν���^����s��Q�׭[���t�
���){��[�n=z���x�v���'��$��Ʉ��@׮]9r��#B!�����ڵk�}�f͚i�����1����%22���֬YÚ5k�b<xp��N*�5�8P<K�1d�޽O���"ߍ7����Nb(��ڵk���Y?11Q��`�������%Ɠ��@�Z������u�B!�B!
��!�B�����-Z�(v�
������/�����|��T�V��*Jw�ʕ�?ny�:u�2e
s����E�����*�[�.�V�bժU%�]��-�Y�&���;����;Vk@�snm_��ѣ=z�V��I��h���aèR�
!!!\�z��M�ңG�z����T*6n�Hdd$iiiԬY�N�:1}�tZ�j����OY�n���ܿ�~���z�j���4~����044�o߾Ot-B!��ӧ�&88���<F�E�6m�ر��CB!�U�	�'H������r��n߾M�z��ݻ7S�LQ&a>��5��\�2k֬!44�}��q�����144�}���1B���^��ų��၏�������S����(��S��EQ�S+U�T�����sԿ�R��E�w/V-++K���.Me�_]OOOO똺���!�B!�B�$�B<S����:!�c����u�%gllLVV�ڵcڴiE>�P377g�����0f���͟W��%M�J�����u(υ��M���ddd�ܹs�;wn���������(�Y�&vvv������L�&MHNN�̙3L�6�5j<�E!�x,���c���1SSS ��پ};իW�q�B!��]�6���c޼y��-.y����1�����?��?��ԾJ���r�U@@...�[��L�����aÆ���$&&�x߽R�J���q��]

��w�(/SSS���سg�2V}�իGjj*ԫWO�XFF�RG!�B!��0I��̬Y�����uB��ԬY3]� t($$��aÆr�4h�
zFшWM^^{��eŊ?~�E��2	ϋ��{��%  @�����)���:�N�2(iuNQ4???���4vR3f۶m���GGGF'�B�����v��>��sf̘��P�x�u�֍�� V�\���;u���ˋ���6m�Ν;��]����ٵkÇ'%%�'���ʊM�6���ʼy�hݺ5��7���lݺ�r?OP'�\�vMy�նm[RSSIJJ�J�HJJR�!�B!�B&	B!�����m�������2p�@���HKK�uh
���yOH�^�:nnn|��'�7���0���000x��!^=�����h<<<����jժt�ޝY�fabb�U��LJO?��6m�(9233�������ܾ}z���ԩS��<���O֯_Ott4YYY�hт���3p�@�z������͛7111a��L�<��U�*�rss�������������C��Xܠ��233	

�K�.4h�@)oԨ1n�8jժ���~!�B��d(�6]� �c�s����h�Bס��ĉ����ܹs<X�ؔ)S��={�$44�իW�z�j����̈́	8r��Ν�J�300`Μ9�nS�2l�0LMMٳgݺu��ѣ���өS'����������/D!�B!�/-I�ό������C�����uB�Wؕ+W�Z[w��e�ƍxzzr��
F�M`` o��cƌ!55���%��s��8::�r�J����f
!ij�b�
���@NN���9s���4�zzz����$#dee��Gq��U�Njj*�����ƢR��Q����888p��-�nbb".�ѣG2����3}�t�z)))�T*����FOOooo�l٢�{��qqq���q��]Ǝ[�z���';;���0������r��^�o�B!�BƁ�i�T���C�L�8���dN�8���t���X�ի�����ޜ<y���Z�jń	�ݻ�RoΜ9�����{����`��0�b344D�R�q�F"##IKK�f͚t�ԉ�ӧӪU�r��駟�n�:RSS��>���c���DEE1~�x��QQQҷo�'�!�B!�B��$�B<S2a[��zR�B��nݺ���7���ܻw��>�����4o�\�cjj����u���ųfgg������B���?���]�t��̟?�7n����Fݖ-[�R��]&�l��իWiҤ	K�.��7�$!!����ȦM��66o�̭[�077gٲe����j�*v�܉J�R.���IHH�}�����`ffFRR��������J
�ڵk����������App��7{Y�EGG��oj}��e��ђp!�B�'&�@!ī��͍Ν;���2c�]�S&�7��ݽ�:իW���ggg���3���Y�}O###�Ν�ܹsK���m[[[cmm�QV�fM����%99�&M����̙3g�6m����B!�B!DA�p!�B<gs��!""B�aQa���?qIIIxzz���K�j՘9s&�1&&&Zu�4i��˗9r�Fy��ݙ5k��"��鰰�(Sy�I���ʎ:t���'''"##�.���d���H\]]�Сo��6...̜9�Ç+m��>��3�5k�����ч�o@www7n�'z���akkKxx��pQ�F
�����ի��ٓ#F0b��6�Z��ŋI�j-Z�Ш#�B!����[̙3lmm155�uH�spp`�޽0o�<055���^��	!�B!����{�
!����2p�@]�!D��$?'qqq�k׎-Z�k�.�-[Ƶk�X�xq�����Eff擄,����ڵ���;p��u������d ?ɢ�w�y�7n(e��m۶-1�k׮`cc�����N�HLLT�Ξ=�jժêU�5j*�����6�Z/==�Z�jiť.S�B!�B�d-ZD�:uJݱA<_իW��͍��0RRRHII!,,777t�B!�B!*(��BTh�JK�b�Y�]PժU111�k׮L�0AY��e���
		!&&ȟ\Ux�r!tm�ڵ�A�����?������^{�����'N`iiI͚5�<�Q�F<z�ooo4h�<CBQ��'e�T��y�#77==�'
�nQuU�T�L����x<++KymmmM׮]9r��w���ٳ�_����>|x��c,���ee�!�B!����<\]]����}���G���F��[��A�1a������׹sgY�r%NNNt��I�Q	!�B!��"��!���ܸq���P��ۇ��7:t�uX�;}�4������ǨQ�hӦ���������C�q�ʕrշ����X[ IDAT��ޞ��D�?�ѣG	`ɒ%T�Rz��A�=�޽;u���I�&@���O3�B&�
!��;wN#��������륞۸qc~��wΜ9���)�gΜ�wHRkذ!��������ۦ��)III�ٳG��acc���
			:t�͛7���$R��^�z�HMM%##�z��i���B!tA�OB��\\\����{�'	�3p�@F����qqqT�^]�!�����;;;]�!�B!�B��$\Q�������?���ox{{��Nhh�� ��ݻǂ1b�2qiذa̟?��۷˿��P��틍������
#""��oժ�Z�b„	$''űc�g�ʕT�T�������o����T��w�NHH��#�x���/���˗�t�R�x�
���pww(�ʢ={�dӦM����t�R���IHH��/��G�J�nݺ�ʕ+qww�N�:xyyBӦMٹs'VVVlڴ	WWW�͛G�֭����g�֭XXX�a��Jrr2���8�֭[�������]�zm۶%55���$�Ċ��$��B�<�I����|��7�X���T���Y�z5={��󲋂B!�B!�J.�ΩW-��PQU�V�7�x�U�V���K�سg#G��uh�<???���=z�R6f��mۆ�����:�NMd��C�
��ÇO�pQX�&M=z��;����QQQ|��7@~…B���������fnnΨQ�J=���Çs��5&M��q�Y�fe'N$""�s��1x�`��S�LQ^O�0�#G�p��9���5�0g�����������C�n�I:e�׭[7�=J||��$���x@3�D!�B�g),,��?�www&O���p�xf�4i�ŋ����u(B!�B!��1I…x!dgg���#G000���899Q�Z5�ΡC�ؾ};.\ ''z�쉣�#5j� 778@JJ
������1t�Plmm����>&L��Ņcǎi$\dgg���KDD7o���Ą0y�d�V���S'�DGG���ADDU�V�{��̚5��Ay�

��ӓs��Q�Z5�����ٳ5vz�}�6�֭��ѣܻw�^�z���R����?�d���DGG���E�-?~<$33���S�n]BCC5nD_�v�aÆѤIv��Mff&AAAt�҅
(�5j���AAA�7�Z�j��_W!�ˮ^�z:��C����ɉ'�[��Si����;���%�xy`gg��0^*eI���dѢE���`llL�����0ũU�~~~|��9r�۷oS�^=z��͔)S022R�֫W???���9y�$999�nK�{�V��R�ظq#������Q�fM:u�����iժ�RwذaT�R����^�
@ӦM�ѣ�ׯ_?V�^MTT�Ǐ׸֨�(

�۷o��!��i��/�'���O�3��S����#�b�d!�B!�B��$\����3'N��'����C�͛�o;���qNjj*AAAܹs�%K����͖-[�:< ..���8�޽[��{;v����J����>}:			JYJJ
*����x����n��X��={����Cxx8gΜ���_���8�N�6�����;v������+�?�tҤI$''+��۷��w�j]��?==nݺ������…y��C�aԨQ�T*<����R�رc�����߿���l,--�b���$66�0|�p��BM���;-Z��(+n��U�Ҹqc��<V�xCBB����Km߾}�;w�:п�g��XjժE�~��z�yyyO�M!ċ�R�J��U�vmV�^]b��7j׮ͼy�gI7n���{������;w.s��-����
666O�^͚5�����ח��d�4i@rr2gΜaڴi�bB!��&�'!^O:�9�<C��O�>�]��)E%ī-00���@]�!�B!�B�Ғ��B�믿		��Ԕu��Ddd�2�e۶m@~bƐ!C�T�qqqL�6���(����P֮]���< <<���˕pall�����������@���qqq��̌��$��݉��%,,Lk'��Ǐ���E�.]8�<����ƍ��������6o�7776l���/*����H%�a�֭$''ӴiS�-[F�6m���c�…Z�,�߼y3�n���ܜe˖abbªU�عs'*��!C�0v�X���شiS�	=z��w	x��7�bW�EGGK…��ꫯ8u�F�BI�߿�����75j�Pv��hJ�������_M^^�~�)-Z��7��A�B!�ϖ��{��%  @O`jj������B!�����d:t�mۨ\�����7k�,�gtB!�B!���K�sgaa��UZ9�_|A˖-�^�:S�L�����cǎ���?cnnΏ?�Ț5kX�bYYYJ=�j������_1b�N�:EXXX���ѣGT�򿼥�����iӦ
�+W�e˖����Վ��3������ӡC%!!22�ڝ7o͚5�Z�jJ"ɝ;w��G���Ņv�ڡ��O�N���/��z�?~��>��f͚Q�F
\]]9u�;w��W�1b�.]Rv8�����ٳԬY�N�:p��E ?ɣ0����:B�╴�3��Q���Sv�(�g��T�u���v�Z����_�>
4�O�>xyy����B!�x��W����aaa������BXXnnn�:<!�B�
�ӧ��ՄB!�B!�/��B�Z�j���]�6���J٭[��3g�ϟ�:��v�g�f�������7�|äI����+��[�nP�n]��ڵk���yNbb�VY׮]5�w����ׯ?Q�fff�k###@�{�n�C����;Zm=��oܸ@۶m�lS��ޞ��`�������ĉ<z��{OIvIOO�V�ZZ���u�xQ�9�̻M�B�ڵ�0aǎ��ի���v��Ezz:T�Hxx8�v�b���:�N��S��D��?�>����bbb����ԟ�B!��Ν;����ʕ+prrR�مBQv�b�TR�2^BQ///u����s�B!�B��$�B<w���TժUKl󫯾��4mڔ>�333ڵk�����ښ�]�r��v���ٳgY�~=���8991|��2_ǯ��
�o����v��njwȀ�%%��o��iW___y]�R%���6�]8�g�QeE166f���OTT=z��j��LM]V��xQ���_�믿���CӦM:t(�W�45rrrرc'O�$==��u�ңG������,O��z���~���/��m߾�'Np��M�T�B�fͰ���w�ޥ�UR��]�ݻw	�}��+uLLLh׮���2��5k��=B<�O���ۛ��`���5jmڴQ�Q��<�u�؋���;;;]�!�B�2��B�\���<<<���Z�jOܞ��O!2!ē
d�ر�C!�B!�S&	⥠^�K�R);N\m��ÇJ"���666��ؐ����C�ؼy3���eN�x��ZLϞ=�rSSS���سg���ej�ܹsJ�	�?<x��ן���4mڔ�W��믿bii�����k�}�7lؐ?�����D���K�;n�8���{���9q�zzzt��M9^�^=RSS��Ƞ^�z�fdd(u�xYܻw����*e�����lQЃX�x1W�\Q�n޼Ihh(�/_��յ�d����呑���M��]m��o`` aaaJ��r��%.]�Ľ{�<xp��+Mtt4999ENL�ر#qqq�8q��}�>���x�^�I���c���1B�[cذa̟?��۷S�zuG(�B!����XL�KB�����e���4jԈ�:!�B!�BQ��ϰ�;y�$����…̟?_)�s�C���‚����lZ�nM�6m����?���ٳ�|�2M�4�_�~�q+++\]]�p��=��۬Y��O������ˉ����Ç�>}www�'n�4�����ݝ_��������˗k�}��&V�\Ijj*999|��WXXX��K�n���:t(����Ν;���[ԩSG9޶m[�����Q����2�����?iР˖-#00777�����Õ+Whݺ5_}�AAAxzz��oGdd$��;DHHH��E��F��ԩS�$�?��8x� ...�e�&O���}���{U�u���Z�l�u�:yD]G�g���B#��U���GZZ�G�V�ƌCZZ~~~:�L!�BQ���'/	!�˧y��,Z�www._���p�B!�B!D)d��R�ٳ'���,\���j�p����888���u:u�Td��=�322bŊ�&L�ȑ#�;w{{{��̙3G�ccc&L��QfnnΨQ��������s��!.^��ԩS��~��i%.<��'N�HDD�Ν�Z�~ʔ)Z�Ǐ����ѣ�Ʊnݺq��Q����;v>G��f�ȑe*		!66��S�*Ic���L�>]I�R;y�$�|�	
4��^��ɉ�?����(z��X1���Ѷm[F�I�v��_���ٻw/ׯ_��w����kk�NJ�,~��77n�uL]��#��ܾ}�u��q��Q�ݻG�^�pqqѪ��[E��jnn.>>>8p����133c�С���j����T�Z��ݻ3k�,LLLJ��СCl߾�.������	={���ёG�1x�`�֭Khh��N:׮]cذa4i҄ݻw���IPP]�tQ>/5j���AAA�7�Z�j=�7S!�B��R�m|||���OiӦ
6l ;;___"""�y�&&&&0�ɓ'S�jU�lق���۷Wv������ё/��Rc�Knܸ����2>S���q��8w�ժU�O�>̞=[c'����d�$^d$%%�[s��!  GGG"""t�3s���bE;v��v�">>�;w�P�V-�z�-�
F��ݟz߅�V!!!���еk�b�	!�B!�Bw$�B��Ӹ���g����C���x���[���ޞ�~�
������dذaT�R����^�
@ӦM�ѣ��S�jULMMy�7n
6�8nhh�J�b�ƍDFF���F͚5�ԩӧO�U�VZmzzz�h�"bbb066�����'i�,�����ڵk9t�w���>��Օ���?�u��^�z�������ɓ'��ɡU�VL�0����5k�T^���������ի���b���Ǣ��044�x0*ċ�ƍ��������0s��"ۺv�Z��U����Œ%KHII�G�Z���w���_���g�r��Y����׿�ŠA��V�Z��+���@�EM]��#�.dff2i�$�����}��q���R���f˖-�G\\w��e�ر�W�X��={���!<<�3g����Q�}|��7���j����ĝ;wX�d	�F�B�Rq��A��cǎ��}��~����������Ғ��X8����K�v!��c�رZ�WB!�%���$33SIL��>ӧO'!!A�����J�">>ooo��틗��ϟ';;�5jp� WN�}���tnܸ�$�gڴi�=���v��Ann.���@��{2^/�Ç3i�$�Ν��P����T��7�|C���	x)�����9z�ֳ�����r��!���cǎq��1�����ŋ5��>��+�ӧO���Mpp0yyy�5�6m�бcG]�&�B!�B�$�BTh��+\^�V-�U��
��������<vߥ122b�ܹe~�P�vmV�^���-��';;;���\j�g��ƍ��w+��ٳ@�6�-[��8V�fM����%99�&M����̙3g�6m��T��J�̠�^��pyAyyy�+U�Tj�²������А3f��_��w�addĻ��ZZZҡC~��g>�ŋ	

�~`̘1Z	Syyyʵ>x�����WW�WS����yٺu+���4mڔe˖ѦM����ɫ���P֮]���< <<�����?~///�t����?>7n���GG�"�ضm���2�J�*Ǵiӈ���'K�iӦ".ԻOEGGE'��ˢ��e������B!�(N˖-Q�T��Lh߾=...���������;������akk�[o�E\\gΜ��Ғ�r��a��􈎎&''e'�w�}��{�͛7��͍�
���J�"22RI�(�xO�K�E��O?akkˇ~X�B���{�=�N��ܹs8p u���uHO�ѣG�,_�|9���Аɓ'ӫW/6lHFF111lذ����Y�d�S뻢%_ܻw�0b�LMM6l���g����c	!�B!�B��g
!D�����۷���7n\��hԨJY@@������?�X�x^5j�o�]P����`ݺu���h}=V���:666������CVV��khh���K�.��/�d�Сdee�y�f��:�޽{JYyv�(�N�:@�������u�xZ,,,4�J*?r�...�k�}}}:u��_|Qj?�?�����_1b�N�:EXX�V}ggg,--��קC��$����b�8v�?��3���㏬Y��+V(��k�fĈ\�t�'N�?_gϞUvʂ�}v5o�\��-Zh�B!�B��3~R����X;""wwwڴiC�ʕiٲ%nnn���(=�'a���Oܹs��C����������++�c�7o͚5�Z�jJ��;w�����xI�h2d]�tA�Rɂ&B���_~���^��=��~w�™3g��ȈM�6aooO�ƍ�\�2���8�M�6allLxx8�Ν�u�ό��iii�=Z)3fiii����02!�B!�B&;\!*���_yݦM�Rd��ի����'�|�$e�����允��s�U����Ғ��`���;>��cZ�lɕ+W�Ĥ��}�]v��Ś5k�裏h޼9w���~ ,,�v�ڱh�" ?�!//���e5��6�'N�����ۙ8q�c�;s�L��Ҙ<y2�>͛7'55��V]��Ȉ��:D߾}�u�7n,5΢��E�ܺu�7nh%VܸqC�#��\�~�:h����;��;{�l/^LLL111|��7L�4	;;�"'v��U�z�zuE�u�s����Z�
�pcooOpp0~~~XZZr��	=z�{ァ�|����;��.S�B��;}	!����s��b)<�W/�P�nlj����ӇU�V)	�Z�j8::��?p��A���C||<zzz�+�bff��622 77W)+�xO�K�Er��M@˖-ٽ{�F��xu��A�R�Y�<ݺu///�?ν{�033c��񸸸��Cdgg���KDD7o���Ą0y�d�g�p¤��ݻw0~��b�coo���;w�T~g�ۉ����Ã���V�J��ݙ5k&&&%�]�Zff&>>>>|�۷ocbbB�^��:u*���Z����ɹs�V�}��a����n������p�RRR�����̌�C�bkk��oPP]�t�A�Jy�F���� ((�q����B!�B!�I…�BkРXXX���J�ʕ��۹sgY�r%NNN���B�L
����INNVV�/���-?��3�.]���?�8V�Z5��ꄆO>�����nݺ�600��ёŋ��~����k��V�~mmm���a�ƍZ	�����.]�p��A�n��֭[��M/IQ�թS'N�:Ebb�F�	�;w.�m!ʣ�E=�SSO�+<ɯ`Rq����ڵ+G�a��ݜ={�������Ç/�M�D =��7�ꫯ8�<M�6�>��̌v��iM�666f���OTT=z�P�W�,�?u���)ī'  ;;;]�!�xE*��!t�<�'�“�KK�R��נA�~�mΝ;Gzz:G���[�.��Ǐ';;���:v�HݺuKlW___y]�X�<�=/��Ç�Œ��٣1IYQ���w�2y�d�X.\��$[t��}�O�NBB�R����J�">>oo��c� IDAT�+�={����ݻ�����ӧ���X��={����Cxx8gΜ���_Iv,���,>��#�^������Hll,*�J�MXmڴiddd(}�ر���\�Y���7[�lQ�?x�8���{��2�ؿ?���XZZj�eiiIll,к�+�B!�B�(�n��:u�T�E���p���Y�f��
/ű���믿�믿f̘1�!B!����BBB�<f``���VVVԪU�ʕ+ӢEfΜ	h>دQ�K�.eРAԯ_===

�ҥ˗/�XAj�ĉ4h�===<xP�8����ׯ���l޼����ӧ3f���_G__}}}�6m���-NNNJ����cmm���!���t�ؑ�ӧ�cQ�խ[7��_����/ԨQ��B</M�6��_�(���/�FFF������˖-[ppp�Ν;xzzj�=w��{�C��_��cbbP�T̞=[k��*�ǍGժU	�ĉ���ѭ[7�x�z������u�B!���Ի\�ٳG�[�+66V�kmm��۸{�.ݻw�'{�����ߒ�������U�񞌗ċ"77��^{�������:!D9p��u7n�J���ɓ����\��ߟ��ڷoO`` ?��!!!t�ؑ��X����$ɂ�Do޼	P�.��ŝ��Ҵ�?~///N�<�J��q��ܸq��.l˖-\�z�&M�(����K�ƍILLdӦMZ�4oޜ��P����4i�������P֮]�ɓ'9v����+����x��7��P���!�B!�B�d�!��T�vmf̘�Q�~PQx�ECCC4v�(���e�I�%~�M�4Iy��8�XYY�:i����ɓ'3y���+����^�:�
"44���4�QZZ.\`�ȑ���J���Y�~=���,Y��:p��E�/_^�C�%99gggH�֭��?̈́,��˗�t�R�x�
���pww�_�~��u��I����իWY�d�R~������_�>C���'//���~�:u�(u۶mKjj*IIIZ�����:B!�BQVVVlڴ	WWW�͛G�֭����g�֭XXX�a�z���ʕ+ٱc��pѭ[7<==ٶm={�|��3ޓ�xQT�Z��^�a!
P�UZ��S���WWW:t�@�N��?>�f�Ҩ���;�7�e˖���akkKxx8�����u��}��|��
���Y��ߡC\]]qrr"22�����|���R�����4��7�b	-�dc�$FE��c�����c���!?#2�X��_�u��Ze#�Z�V�V�����z�zU���d�����z<���x�U����Ty��ͻ{��̝;�>���G�j\o��ٴi�ooo"""���S�������Odd$��鸺���鉧���u.]��%pT�ڰJ�G!�B!��'.�B�zf�ر�9�Ç����Ç�q�k׮�S�Nz��~:t(VVV8p@i;p��<�o���#|||��5&L���	___�~�UIN!!!���лwo������F��͛��燓��Ǐ';;�.]���;�T:�j�QPP�������?*������;V�p�_�~j�T�.���j�x�B<i+]�R��^@QTT�k�����#���������sx�9�Ԯ]��1c3f̨6�W!�Е���ڵ#11^y��֭[166f���J�-Z���@aa!;vT6fh۶-�=�>�S�N��ƭ��<���B��A���K/��k{/�����+ύ���J���˗�K�76++��~���j��srrR��G�ܸq��kV6F�����U���͛����)�-,,��*?*ӦM�q��$$$����w�y���
ծs�����5�P���!�B!�B�$�B!��g\\\X�~=�ƍcԨQ̘1�~�F����ccce׫[�nq��-e�ƍ�;<�PU9{###���������###�$NT��Ã�� :uꄑ�FFF������ǢE�4����ҷo_5j���5cǎ�/���Ȩ�1f͚���&&&ѵkW�-[Ƅ	عs�Z�&M�(�U��T���)�������cffƀ���B�G}����u:���Ǖ�6���8~�x��WS�ϟ',,�Y�f1s�L֬YÅ��B�'LU�O�133#""///lllhذ!����i�&��nnn�f���Eu�9uU��=y^BQ[�����V���$4h�q]m'���ϯ�*�!..��~���@@�:�*���Y�P>�������777<HPPݻw�����k�2h� ��V�s�Ŭj�v}!�B!�B�Gյ:�xD۷o���X�a!j(::///}�!*1n�8lll���'33���bZ�hA������y�����ҥ�F�b�ƍ�=�.]��9*!�4i҄9s�0g�����j[t����N�4mڔU�VU٧����k�J�(��ŋ@���۷W;֤I���ذa����n�(�a�…L�8SSS��"��R��*'N���#Ѵo�>�~�m8@LL����*��SMܿ�����������A`` ��ј���yB!꿪�fYXX(U����၇��F�̙3�9sf��V��v]���yI!��`kk˕+W�x�"�z�R�U��gccCFF���U��Ç�ƍ�ׯ/��F���-[�(�3�KLLT��x��y����ҪU+�]�ƅx�W�v�&��leaa��?���B\\�7o&44��Çeյ�����ͥE�j����*}�B!�B�d�
�μ��+�1B�a!jaĈjo.�'����&$$��[���΄	$٢��ٳ�={6�
�w8B<U


��_����
��1c���e˖DFF*m����������XbB�?���j,����lΞ=���%���i֬gΜ���whlܸ���F����=���%!V!�����%!�uMU-iٲe$''SRRBRR˖-�諪�4o�<���x������}����L�4I髪�p��u��{��<������پ};?��3%%%dgg�m�6Ə���y��7�ѣ�FK�.U�<���1����"WWW���ILL������De��^�b�С8::�{�n


�С����zuU�����k��*V�B!�B!��H�Qg�L�”)S��B!��嵽�=C�����Ą�2u�T%)#&&�իWcll�XbB<]T����̜9{{{����,lÆ
9r�[�naee�[o����?FFFj׹}�6�W��ԩSܿ;;;Ǝ�ܹs�?v�V�����Ç���s��a���044��Ύ�C�*�s�O�x��1V5O(�]���C�z�-LLLx��7���"&&�����t��Gtt4iiibee���+��ں���ݻDEEѳgO������-[���HTTcƌ��ܼ�8�B���</	!��k���:t�k׮���We_???�?Nbb�F⟱�1ӧOW�����Ν;xxx`cc�����d������������1N����?���7o�g�.]x�w��<___�=���7n�ڱ6m�h����ח��`BBB		Q;��࠼�ӧ'N� 99Y� 99�]‡B!�B!�T�u��ۛ
ȗ|�W=����!�����5�7�O�>�Z���
V��_&  ��+W�r�J&O���a�B�Thh(w��U�1i�$6o��͛7)..&++����M��Ç�s�ݻ���?������Q\\LZZ��lQ���0֯_���)..������$�,Y��;�65���y���r�%��������SZZZ�<�[�n���9w������QQQj�Ht���_MAA���c9;;SPP��Çk�B��%!���ܹsj	�噘����;͚5�Q�F��۳x�b��333"""�����Ɔ�
baa���+�6mR��0s�LZ�nMÆ
)**Rڍ��		!44�~��ѬY3�����Ņ��P��иqc�񆆆ҷo_5j���5cǎ�/�P�����377g�ƍ�9kkk6l���5�G�fӦMXXX�~��ѩS'���022���???-Z��8p ������k\#>>333��B!�B!�O*\�:ehhX�b!ēG�-���W������������˫��B��oߞ��e�Ŷm�HII��_d�ܹ��ّ��App0gΜ!&&F��ɍ7hժK�,�s��$%%HNNN���ٳ�5k����Hqq1�������s�N���9w��*5���y�={��7obooO���jC�����㏜;w��={�|/w����9s2d
4 ))��'�-�e��O��s��c��N�>����u�Q!�x���B��Լys����ڲ�����Rk���`ƌ̘1��k������V�q�
��jڴ)�V������mڴ)�g�f���U^���R�����+T�I�&xyy�a�233iݺ5���\�p��'*�$�B!�B��p!�Ԉ#1b���B��޽{��S-66�F��O����"}!�
�����/v���QKB8r�����j�
(KVX�p!Æ
#66VIf8v���ͣ[�n888Ȕ)S����Ԕ��|"##IOO���OOO<==��gMb�l�111��-T��?�����W����'ORZZJjj*䧟~��ٳ����x�.]�m۶c�k�N��B!�B�����BAAs����
333222X�|9/��#|:�����W_�$|DFFbcc������B!�B!Dy��S!�x̎9�,�B!�uG�p_����4y��e�uFF�������q�M�ƢE�HHH !!�u��1n�8���066��ܚĨRq�w����ѣ|��|���;v���|��̪���۷�>}:����JKK�׺�Ν;���k\Oզ�#�B!���4�ݻwBHH��1KKK&L���Ȟn&&&,\���S�2f��l�իWW�ށB!�B!/I�O4�N���i}cW�.b��y?�k�.prrb�ȑ�e\!�DW�\�wB!��R��]�k*V}(��M�J
��ӠA�*���憓�Ǐg߾}\�x��kײm�6&O�����+=�61V��C�(**��:���;�ҩ���+HMM��֖W_};;;�v��|���U���@c,U�.�Z!�B!ģ�={6mڴ��\�z���"�}�Yz��?������/�ʕ+�<y�N=!�B!���!D�:�<aaa�ܹ���R�y�����ѣ��CB/>��C}� D��f�}��H$�P!�<666ddd��~lll��kkk˕+W�x�"�z�R�/^���X������NJJ
qqql޼����*.jcebbbX�z5���ǿ���L�BLL��	�$���,--HOOW����ШQ��L�̽E�dgg���K�-�����U�!��k��'!�B������KߡTI�=���!�B!�u��
!Ԝ;w�ʯ��q�~��}�ϟ���'666�j�
��~��/ē(66���X}�!������iӆ#F�;!�dĈ�i�F�a���̛7���4<x�/���g�}���#�&MR�0�e˖���LII	III,[���q����#�w裂��:`oo�����OU��뵊Q��~����T��yz�O�޽i۶-)))���O�Χ�o�����"���T����j4��;����1��M�G!��K�����F!�B!�B�W#.��9::O�$e7n$''�Q�F)m�G�fǎlܸ���=F'�������]�a��0`ӧO�w�ַo_����0�Bh�������ILL���G혱����ooo:ĵk�����8���BHH��1嵥�%w�������_��ٷo�F�R:*jР�F�b��������GU;'WWWbcc	

"((H�xZZ���:ϽO�>�8q���d�v���d���Wm\B!�7y~B!�B!�B!ēN*\�z������ \\\pss#44���]�O\\�&M���'''�~�mV�\IAA����Ç|��xxxлwo\\\x��wٻw�#�7o�<5v�>t����̙3Gi���Y�`o��NNN�5��]��Ĕ��u����ݽ{�O?����+�/44���|��^�|�������믿βe�ԪVܽ{���(z�쉵���޲eK�����ݻU�[!����o�N�
�K��K�Ծ�o߮�_OO��T�333#""///lllhذ!����i�&��
&&&������N�f�hԨ���,^�##�J���� ((�N�:add���vvv����h�"��̙3iݺ5
6�����1VT\\�����`��Uދ��~sss<Hqqq��n֬Y���abb���]�veٲeL�0��;w�h���Ԕ��x�����133S��!�xz��|�W����!�B!�B!�_�T��œ9s��o����۷SRR��ٳX�n6lP;';;���(���1aaalٲE�S\\LRRIIIܻwoo�Z�w��yV�X���-[�$;;�������;w.w���ח۷o+�^�|��� <x��!Cj5�Jm痟��{�Gzz�Җ�����9s������3q�Drss(,,��/���Ç̛7����������5�svv�̙3>|��Ç?Ҝ�B�'ծ]����	1r�H}��SU"���3f�`ƌ�^�y����������r<ww�j��������V�+�khhH\\\�稘��p�رJ�U�{sss����^K�t���ܛ4i���6l 33�֭[���Ʌ�8q��s�B���<?	Q��O��۷�H/��{���A!�B!D��Q/����ڵ>��s���8v옒p�c��,�aȐ!4hЀ��$&N���[�={X�f
���KHH;w�Ԛ������j���9�-"  ��� ���,X��{�X�bl޼�۷oӥK�,Y������?���CDD�#'\�f~[�l!==�֭[��'�йsgRRR�?>�/_fӦM��Ӷm[.\ȳ�>ˆ
����رcJ���ӧ�ܹ��x��ӧOK…���P�q-F�r�
�1͛7g�ڵT^ ��Ç|��ܺu��ҥK�j�_q>5�����}�kddD�V�x��qqq��ڏ��9\�v�v��i���!�֭o��f��(jgĈ�A!�#pqq����9s���憙�,_���^zI�����|��WDFF*������������B<N�$�B��+��"�B<A�ߵB!�B�t����U��P���n��1�۷`���DEE��/�(�O�<Iii)���<x��~���g�e�TLMM���'22���t\]]��������ճgO��������#))�ѣGӫW/�ϩS��5kmڴ`޼yJ�£��T��Λ7�nݺн{w�Ν�|�ѣG5.fϞ���ۛ������.]�3*R-"V�B<����h߾=���|���U&�%&&r��-�{�9��-���"�]�FXX���U�C�V�X��s�&�����}�v>��SJKK�9s&�ڵ�S�Nz�T!�x�
4�ݻwBHH��1KKK����LLLX�p!S�Ne̘1��İz�j�����B!�B<��L�”)S��B!�B!�SM.D���/(��6m
��r��m�O�Njj�ƹ�����iӦ�h�"HHH`ݺu�7//�Js�O����ɓ���GRR�۷��?T;~��M:v��5k�6����ʒ,�S�ت��<;;;嵪�G��O�ܹ�U��Hզ�#�x�
0���_=z��D���8�m�Y�;*^'77��[�r��Ibbb�؄����f����x�gx�7X�z5����(Q��ҥK����q�ƴm�ooo�8�Ӊ*��?/�楲k�.prr���B��J2?x� W�^����g�}�޽{�����C|*�����r�J����A�Q	!���������C�s˓g!�u���͏y IDATۛ�۷�;!D��(!�B!���$�B<v?p��C+##�*��b�
RSS�����W_��Ύ�]�j|p��憓�Ǐg߾}\�x��kײm�6&O�����k9+�4h���/--U�QTT�q�Ϟ_���

����j300�8�j{�!��L����J>xT}��a˖-|������XZZj�����ܹs4n�=DY��M�����ɓ'IOO�w85�w�^�ܹàA���A��޽{5j����G}ĉ'tN(������Y�`fff���ua�T5�����Ν;)--�w��ޞ=z�!R!D}b``���^^^��'�Y!��L�I�B�5CCC"##��ؾ};{���wB!�B!�d�p!�
��"""�E��Ӗ��ШQ��������NJJ
qqql޼����GN����Ϲ|�2]�t!%%���0f̘���g���)}tՠAJKK�w�fff\�|Yk��̯U�V\�v�.��+�(�.\���F�XUZ�hAvv6����h�B�Xnn��GQ{����_��3g�иqc�����ѣՒ���믹z�*���;�����ٓѣG+>|Htt4�|�
�nݢQ�F�iӆ�����`ll̫��ʡC�8~�8���4�9q�<��Ņ&M��<~EڒM~��7v��ٳg����y�W�0aB��ك�	_���|��|��ܹsKKK�������Ւ�t�_�ͣ����*��w�������4o�\�ceeE׮]���eȐ!�}�2'N���xń�;w�j�*bccٺu��pQټ�߿������T�=���A`` ��ј��<�0�B!��LM�k#�$B!�#F0b�}�!����%�B!�B!�B�[�Q�}�����F``�Ҟ���СCqttd���СC�����
�q��Y�o�N�=������AY�ҧOV�\Ivv6����X�GGG���UTI${��������ѯ��suu 88���DJJJHLLdٲe��ׯf7�ر#�Tm�>B��	

��ɓ����W_}Ŷm۔�QQQ�����?PPP���}�6d���J��۷��_���EII	�������_��J�p��1�����′j;5�:���#00�cǎ���Oqq1�N���>�������olܸ;;;�����,Z��}�����CII	�n�bϞ=����U��~��N�>Maa���/{��Aaa!�|�M��-ꎣ��R��IռysfΜ	@jj������7����Vf������(��B!�O���<�!�B!�B!���T�OWWWbcc	

"((H�xZZ�����LHH�F‚����kW�A޹s�{�..��ԔŋӨQ#.\��ѣY�`;w���ܜw�}�#G������o��v����W9�={��j�*V�Z����F���Ou�ѣG�~�:�ƍS;֦M�6]��Ӈ'N����1vrr2P�D!����

��ʊ;vp��AΜ9���������+
4য়~b�…|��w�u���0w�\^|�EJJJ8y�$�ׯ�СC��+[[[:v�ȥK�HII�k׮�5RRR��ʢ}��J2���Wg������вeK�L�B�v���	����"�300���k���\�r�:0~�xڴi�͛7	'))�cǎ)�+t�_��k�.�0Ο?@���5�Q�����+I1��p��mV�^ͩS���>vvv�;��s��;��a��9­[����⭷����_�zS��4�׺��ZRRh��˸PV&<<�Ç������!vvv:�aÆUWU�V6��w�EϞ=���V��l�GGG���3f�����!�B!ē��>[[[��٣q|�Сܼy�={�`kkK\\��Ѥ��QXX������`jj�um�"�����9'N������k�sZy�L"�B��K��6`�5�R�*S5y��&}��k�.prr��!�B!�B<=$�B�ݣ��0k�,JJJ����t���^�Jxx8;w����5jĮ]�HOO����__�Z���?�̢E�hժ�Z�b���,X�����.]J�-ظq#aaa|����/���,��f���p���߿���#���筷�R�W�����q�F���q��q~��Z�h�믿��㱰���=8p �V�">>��cǪ������LQNeo�Wl/����<��s@Y����o�)Ƿl�Bii)�����Ǔ���$<(����)((૯��ƍ���777�REy�ҥK��ũ%\T�nQ��s��&L��/�@�.]?~�R�Gt�ؑ�#G��e��N��,�x��<y2~�!������ܯ?�իW��1��T}���޽{���s��
�---M�"���"&M�DJJ�Җ��EDD��Ʉ��a`P��v���ܹs�O?�@��&ㆅ��e��_qq1III$%%q��=���k_u���k


�&�:;;s��>��������ۛ�{��;!�_Ttt��CB�M�68::r��Y�֭�r,11���L^y�lmmY�n6lP;?;;���(���X�x�Nc޽{�q�Ƒ����:t�{��i�g!�u}�'N��S>~R�?���0v��Iii)�����Z�S!�B!���!	�V�p����	��w„	j߻�����^뱵Y�t)K�.�h<x0�VkkժU��V6���	s��aΜ9�ƨ���״iSfϞ��ٳk|���&M����ņ
��̤u��dffr��&N�X��qBݴi�Fymff��"��믿�|�r%����R�رcY�v-/^��ŋ�ܹ����o<�ƍ��׻wo6m����?���133#??���LMM�ӧO�ǯ��?�����Z{�Ν�<O�������ŋ��ʢ_�~�ơl�8�|��Zׯ_W^��~�Yrss��߭��T}��!22�7nЪU+�,YB�ΝIJJ"00�����۶m#%%�_|��s�bggGFF����9s����
ƹs��ŭ��6l�Q�K�qe��5k����Hqq1�������s��GJ��l^�O����P��>}Z7	��X�J!7�=$D�1|�pΞ=�W_}��p������	��;�3gC��A�$%%1q�D���uo�֭dffbkk˒%K���'))Ik�ey&B�Ww��	���T�}�ܿ������鉍�
P�^`` ��ј���9B!�B!�B�I�B�___���+"##�D���Hlll����stB<Y�W��?*[Tl/��а�kFDD���N˖-�ٳ'������̘1C����3ݺu��ٳ=z�K�.Ł=z�Z5CCC������9u�o��&�N������_]-�@��JΨ��ѰaC��733����?���7���K��)_��&�Ku�
e��׆�|mU
Tm�>��UY2C�s��q��1�͛�,rpp 00�)S���?r����Jœ��۳p�B�
Fll���PS
6�[�nL�8Q#Κ�kjjJ~~>��������ꊧ�����.\�t	��m�jk׮�Z!ē���!��A�秄��7oΑ#G�9s&������p�����qqq��ɓ���������駟8{�,P�Q���?�ܹs�
��㏙:u�Z_y&B�$�O�
O��7���èQ���ѣG�c�6n�H@@��B!�B!D]��!D�111a�…L�:�1c���ի166�stB<�.^���%K����ƍ��(Ifff��ߟ���s��طo�7o�H x�78p�G���7���ѣ����z���lْ7n����V����~��F�?�<����ݻ���p�t�Tx�g�y�&��9�<�L����~5hЀ��R�߿�T�)_)�&�5k��۷�{�.͚5S;v��]��xzddd��K/��;88h�U�wUY��˗/�<��׼�<��}222x뭷�.v�ɸӦMcѢE$$$�����u�7n^^^u�o�;w�e��*R���!�,�D(�xRԤ2�B?5j�СCٸq#����k|��7���2a��}�۷o3}�tRSS5�Q��u��i���3�B����۬^��S�Nq��}���;v,s���5


ذaG��֭[XYY��[o�����$Y�d���8���IKK���+++\]]	P�s/Ӳe�8q���Ƹ����ӢE�*��e.P�>|TT={����Zioٲ%���DEE1f����B!�BQ�I…�N�����r�J&O��u����\�p�޽{s��
֭[�����ӴiS>��rrr���Ņ�mے��
�-\���Ɔ_|���$����]�F�.]x��j5~u���KTT���|�t�ؑ�W�^�����7�|CNN��Ѽ��ʱ^�z�w�^>��3�{�=ڶmK^^ &&��]��`���������1`�n߾��뫍S�������%o׮�o���͛�7o�T��'[�u�����m���[T��ZU,,,�?>���,[�KKK���_�q���prr����۷��/�v�Z�m���ɓ>|�ƵUs-**�q� �a���
������B�Em߾��{��;!��j���͛7s�^{�5bcc100P��b�
RSS�����W_��Ύ�]�*FuUYNm��3�B���޽{����m�����$[�WTTĤI�HIIQڲ����� 99���0��jjݺulذA�-;;���(���X�x�ڱy���%Q�ݻ��g����Rm���_SPP�����u���9s���x�S!�B!�OI�B�9///Y,%���Ջ�'OFXX���W�ңG�
Fxx8�ׯ�H�ҥ��k0���$����-j2~u�BBB׮]c�…J{�>}�d]��E����0`��$2l�0Ξ=ˏ?����w��7n������gϞ����e�֭lݺ@���5�N��3�<������Ν������������:��䳵��ʕ+\�x�^�z)��1���ؐ�������$�?C�N�3f�6m"88��_~Y�VS�q-,,pww��ݝ�����ؼy3��������{��)�֤BGy-Z� ;;���\���rss�>B�'ӈ#1b���B�EK…�H�V�prr����$''s��I^}�U�ݧ���������t�xII�֤��lmmIOO��W[p�����W�I�B����ܸq�V�Z�d�:w�LRR������ݶm)))���̝;;;;222�̙3���0l�0Ν;W��;v�`Μ92�
����ĉ�Ċ�.]�ĺu��ѣ���̟?���L�n��￯u]�p��i:w�qU��ӧ%�B!�B!�xJ=��B!����ڵ�]�v=�5�}�]���166��А^x�iӦ)�<�o�������?���!������2l�0&O���ڽz��Y�fܽ{��M��-���144dѢE���aaa���!���L�8���K�.8���y�f���ԔO>������3�```���={�d�ҥj�#t�_cǎ���
333

�ѣ�&M�6�w�}kkk(..ʒK������4���w���j�YK�_`ٲe$''SRRBRR˖-�諪<1o�<���x������}����j�ݩvO�~��Nq���{�nݚ_�U��LM�:t(����޽���:t耽�=P�3��Z��w�^�߿Ozz:!!!�Ʃm^;v ##C���M�G!�BQ�
>����GQQ���Z�}�����F``�Ҟ����8o��&���|��������?�t�R���L"�B�վ�j?v�P�>_�n�044��A�o�ʑ#G�������4lؐ���+�%���)�<y��g�ҥK<�g�}�����}�͛GϞ=144�[�n̛7Omn��d.�.]�m۶�Q}~��#�B!�B���T�B!��1*�7i҄iӦi�[q���+��ua``����"]ǯ����������}�KT7n�ƍ�h733���W��Eet�_���:�\�{ggg��	̞={���Qv����!--��#Gbll\mܢ���СC\�v
??�*����q��q���Q;fll���ӕ�---�s���ذ��*�mbb‚�8q"���>������LHH�F�������Օ={��j�*V�Z�S2��y��Ӈ'N����6���l�~����B��Qv�t�R�.�<y�${��%99���<������?<<<�۷�#_�b��r/jc׮]ʮ�NNN�9�+���ү_?��������VccWWWbcc	

"((H��4��=|||����ҥKL�0Ai8p�Fb�<�!��/T�^z�%�����
O��ݵ^���j+�}�6ӧO'55U�Xii�F[����ݻp�ƍJǨ�\�ܹ����F?U���B!�B!�>R�B!��:t(VVV8p@i;p��<�o���#�u�ܹJ�������;͚5�Q�F��۳x�b�����fffDDD��免�

6���WWW6mڤ�v�̙�nݚ�
RTT�S��9��駟�j\����ԩFFFagg����-R�M�>OOO�6m������̟?����k������?>>333���B��G}���w�\������;3f���ɓܹs���~��WN�<ɴi���u�{�M]Ư����ƬY��9s&k֬�…z�G!Dݩ�	�6�6lP������2k�,���011��Ȉ�]��l�2%ib�Ν:�addDxx8���XZZbddĀ�]�˓g!�����Y�ohe��P�勇>i�>Q+V� 55[[[|||X�`A��-U�UgÆ
+=�&sQ]�@sy��M�B!�B!��A*\�:�|�%��?���5* !���ؘɓ'�l�2���C���iܸ���u�y��;�fee`ee��naa��3�1cF��tss���M���]�g͚ŬY�4�u�v��l�8�̙Ü9s������դI���ذa����n����L.\��ĉ155�6n!��Em�9�8q�O��K�.%..333���y��x��g���%!!�/���#G�`hh�$�Ք��We����3�|<==���������c�C!ēc„	jU'�377'88���T�{���g
]�[�D!D}akk˕+W�x�Z���/j�!##����+�buAU�0""KKK��ӕ�%%%4j��R�~�A�B�w�}�ͭ25�K�-���&77�-Z����U�!�B!���$	�N3r�H}�!�B<�t�¨Q�ظq#�G��K�.z�J�


�3gnnn�����������><��嫯�"22�ٳg���
>>>z�N��Ƿ��>�p����XXXA�v�c͛7gРA8991j�(bcc���[�n��6n�HNN�F�R�F�͎;ظq#z�N!�(#�$B!�p���-[�'�|B�N�HMMeٲe}���ϦM��7o�gϦC����ol۶��[�����_|�U|(--��iӦV�}��������m���G��͕�?��/^LǎILLd�ҥ����^�&s�ر#���dddh$Vddd(}�B!�B�t��Qg"##����wB!�Se��<X�a�:6h� v��MHH!!!j�,--+ݵU�311a�…L�:�1c���ի166�stB���J�g�̙���+�$


ذaG��֭[XYY��[o�����un߾��ի9u������Ύ�c�2w�\�d���>$<<�Ç������!vvv:T��:G���X�<����رcՒ-�k޼9>>>�^�����?J…ꚧO�&$$�#G�`ddD߾}�2e�Re����%�ܽ{���p�=�/��������&L���L�:QQQ������H�ƍy�7�6m�R���ݻDEEѳgO�����[�l���#QQQ�3sss�sB!y&BQx{{s��!�]����_�}���8~�8���Ƀ���L�>]���Ғ;w���၍�
����9&WWWb3�"i IDATcc	

Ҩ��������}�.]4b�ر#����\���É'HNN��A�orr2����y~B!�B!��_$�B�բ!D��ZP%���={6mڴ��\�z���"�}�Yz�����RQ��_~���V�\	��ɓ5>B<�BCC�{���{����I�&��������"""���d���000�޽{���s��
�oZZ��lQ���0�l٢|_\\LRRIIIܻw��5���y^�x(��T��}��z�jΟ?�ql����b���Bbcc�p�۶m��¢�;�|�{�=��ӕ���l�o�Ι3g������T휉'�������_���C�͛��_MAA���gggΜ9��Ç>|��q
!�uE�I�B<	��ibbBxx8aaa�<y���|ڷo���AAAj��fffDDD�~�z�;FNNM�4����I�&��/(}gΜ��Nvv6EEE5�w֬Y���σ�С>>>\�z���pv�ܩ�L8w�\JKK9v�fff0���7n\�5���Y�j���;V�:���ʘB!�B!�x:I…�3������fĈ�EQC����;!���200���///}��T�{)�_W��퉈�P�l۶���^|�E�Ν���s��bbb�
���ܸq�V�Z�d�:w�LRR������T9�={X�f
���KHH;w���ۻ�j5���y޺u�*�|�����ԩS�^���={���J`` 7o�d۶mTE[�l!==�֭[��'�йsgRRR�?>�/_fӦM��Ӷm[.\ȳ�>ˆ
����رcJ���ӧ�ܹ��x��ӧOK…B�'�<�!�x�5o�\��DVV�R�P��‚3f0cƌ*���憛�[�}*{�477'88X���˟�t�����\�4i���6l 33�֭[���Ʌ�8q��fB!�B!�xzH…�S^^^DFF�;!D
U��B!���Z�_]{�>>>j;q9r���`Z�j�%+,\��aÆ�$3;v�y��ѭ[7�����)���DFF������+���xzzV;Ϛ�X�<U;�6jT��>���j�[ޜ9s��B�u�Ƽy�<y2ǎ�H�����ؽ{w�Ν�|�ѣG5����e�&���)�/]��%fTԮ];�>B!�B!����BAAs����
333222X�|9/��#|2�����W_��ٳ���lll����stB!�B!��K�p!�B<fӧOg���C!�⩧Z|�r��u��ݵ��|���:##�\X���P�ӦMcѢE$$$�����u�7n^^^WynMbT�8Okkk������R����T�W���}�=�q�F�W1F�����U���͛����)�-,,x���v���l�ӊTm�>B!�B!�6h� v��MHH!!!j�,--�*J������p�B�N�ʘ1c���a����>�!�B!��~��!��1Z�f��CB!����W��?*[Tl/�|��^ɡ���|����4hР�k����������ٷo/^d�ڵl۶�ɓ'3|��JϭM���K/���E\\�n�׊��S�WT�:�*����tU>��"CCC嵶��j���M����B!�B�Qe��\�z���"�}�Yz����$����_~���V�\	��ɓuژA!�B!���$\QO��o��������XT����-BR��gdd���NNN���ѪU������(�qyܱ�ڵ����l�ڑ#G>�q��*::Z�!!��޽��|��"%SNqs�a���6�09ME�!��ӝ�p[3
�I�4?r��)�j�i��P"r�Cug�l���Жr�����ӕ���x\�]}����~�����E�������Ν;177/����?��3�Ν�k׮J��s��u-ppp 55��i�&���JM��&ƒ8;;MPP=z�U�V}.^���͛prr�8�������̙3���Z�ҤI~��WΞ=K�nݔ��g�T�������"''333�c999J!����$�B莞��������:��̕B!�B��!�qqqܼy��7o���}��_PP��+W���dϞ=���ӱc�J_�֙3g�g�֭2b�����ܹ��C{�|��ǺA��ƠA�t���6!��zz���ƍ�����ӓ֭[��_̖-[���aݺu��׏���ŋ��_Ҷm[Ο?��ŋ˼���#̞=�A�Ѻuk~��7@�zCaa!���XZZjcI:u���ٽ{7&L`ҤI���333�_���������۷0`@��-Z��wrr2>>>��߿���ի7n��LJ/�����ۓ����c�=ʜϢڴiCVViii�iiiJ!����$�B!�B!�B��J.�xN�ر���{�]�v��	�WV�{�.������$&&��g�����]C��YU��}�6s�����E�=vذa|��DDD�X���kt�UVTT3f��u&;�	!D�5n�8���HJJ���M�X�Z���=z4{����_eܸqZ]���|}}�U;fmm�<�W����6sssv�ܩU�������ݻ�߿???���4���ݛ�s�{�����}�oߞ#F�Q���<x���tƏ�v���R��<�z�-:DJJ��|���K�B����'!�B!�B!�BTu�p!t���xv�ϟGYYY�<y�z����g�q��N�8��A�F�*�5k֤m۶|��׸��s��Ev��)�˽����z�*#G�T�F��7�|CPP:�N!^<G�a�ʕ�CQ�L�6���~[�a�P*���ؘ��@֯_Oll,W�^���kkk�L�B�V���������O||<yyy�h�777�͛���A��6l5j� <<�˗/`aaA�=pwwW�͚5�իW���EAA��1���___�����HNN��͛ԭ[��_'''z��Y�~~~̟?���DLMM0`&LP����/�N�:����8nܸ���}��e�ĉ�����~׿V�X��Ç;v�ڱÇcllL�~��W!�B!�B!�B!�(J.D��J�`֬YXYY�n�:���ٰa111\�v����3p�@� �1���c׮]ԨQ��Ç3e�rrrX�d	������ӳgO<==122R����%  ��r��
�ׯO�>}�4i��Ƥ����쌅��������ȕ+W�����¢ܱ�DEE���C���! ,,���(&N�X�s���ϸq�3g���j	��yBB������```��o�ʹiӨ_���5�7,,???����Y�&�.ӧOW��p��
V�^͡C��}�6}��aΜ9���Ӹ����5kHHH //��͛3v�X
�1�����Ç	`߾}dff���O˖-qtt���I闛�KXX]�t�aÆJ{�ƍ���!,,�1c�P�N�b�F!����Ӊ�����u(B�*"""B�=�x�JK�011a�̙̜9��qLMM�7o�Z[ff&�������PfU3{{�b+�7��$���ٳ�Ċ�ԭ[�+V�ڧ�����nݺxzz���Y�x%�O�v###\]]ٰa4m����Ξ=��ɓ�]�v��B�[�A!�xa����:�}�B!�B��$�B<������U�0e�RSS�>���������?zzzjc,]�T-b���4mڔ��e�;w�{�n���?>yyy|��ʮ���Dhh('N� 00KKKlll8y�$IIIt��Q雔�DFFݺu���B��ٵkC�-�	c�ΝL�0�jժ=�ѹsg~��'��"s�d�v��	<����hΞ=Kpp���iEƝ<y2999ʸ۶m��Çxyy��ƏOFF�rΞ={�u�ƽ>��ggg�����וs.]�ļy�x���}|�X���ټy���޽{$''���̭[�=z4{��%??;;;�����q��	��ۇ��s�1	��_���͛{lϞ=$%%бcG�#���uB�*��߯�g�gϞ���3{�l���166&--�%K���o�8—���;�w�&$$DI�		���777G'��,RUW!��<��ݓ[�B!�B!�"����{-Z� !!��Ljj*:t 44��ǏN�Ν9q�QQQc�����7�p��Q�L����/իWg۶m$$$0i�$����6o���˗iڴ)���;v�
6ФI.]��ƍ��w�V�ntt4...���ɓ\�r+++Z�n
���VVV\�r�\;�j�������Ki�Ȝ9r��+Wr��1iҤ	W�\!88���m֬���$$$0~�xbcc��[�l!##6m�ıc�PK y��ߴiׯ_�}��DFF�СC,q޵�E�<�j�*�;F||<�g�`�֭J���ڵk�q=U���Oj�ҥ%�Z|��yBCC��7n�������8B!�B��SU��O�>t�ڕ���S�NQ�^=���
CCC������"33���L����V�Z�O!D	\]]),,��<�Q�G�޽iժW�^�y,�=\]]u��E��VHH���C��|!�B!�x�H�����ؔ���D777��cbb���I�&���ooo�������(�;{�l%a��Օu��q��]�̙C�f�3fJ��{!����R��S�N̙3��>������A�^�055%&&�Y�f����������aÆ��ٳB��������ȿ��ov��A�.]��ӊz��5j��#��s���бcG����:u*���xxxTx\OOO,--=z4���ܼyS9��9sx��������?�O>Q�i\�ȑ#|��J?///�FI���v�������˗�ի...Jb�ʅ���TUT}�xR%%�ݹs�U�VaooO�
x��wY�r%~~~� N!�U��}����/��BAA�5�{��L�0A��(t��7���Ãe˖0u�T���u�B!D�Y�h
4P~�&�E�\�R�����
�B!�B�b���\P-WIOO������.]�hkӦ��v����-[*�


5����%Y<�7��ʕ+���GGG���8|�0}����ѣ���0i�$�W��u칹�<x��˗�|�r��������all\�xq��u�ի��Ud�mmmվ�ܹ3�������������*m��U	2*�����U���_s�M,ӧOg��$&&����ڵk?~<���j�׳���S���x�6UQ������ݾ};����.��h����h�o��ȑ#u�U�*�iT�*Njj*cǎ�A��޽=���=|�GGG233	(��֢���׷�ޚ5kҬY3F�����Y)�.\�P�{���p�G�T�&!�-===\]]_��z�տ=��e�	!���ѽ{w]� ���?NDD���CB�A!�B!�S 	�+�x�<��n�Y�3//O��f͚�-mAai_`�2t�P6m�Į]��ӧ������UH�&�={�PPPPj��w�g���O�����m�Vi�Ȝ?^!�����"����+ϫU��q\5fѱ���_\[yh���=�����űc�Ν;ǚ5kf�ԩ8;;��R��\�V�x���z{{�l�2�5k���G�$�m�Ʊc���Φ^�z���ggg���Ç�����ѣ\�v�5j`iiI�޽�۷���3�㋁O�u����t��SSS�O���y�׈��fȐ!=��B�K���i׮�ϟ�ȑ#Je��?~���LZ�hQ�v�{�./^d�����;��:�b��_��СCž�=s����lݺ���BF�������*�B!�B!��\]]			�uB 44�ѣG�:!�B!��L.�s��ܜ��4v�܉���S�V�&M���_9{�,ݺuS�Ϟ=���x_[[[HII!>>�w�y��
V(���(�Q9`;;;��G�eڴiDEEUZ�Ž{�

�W�^�[%))Im�3g��ꫯ>Ѹe������˜>}Zm�RRR4�>��7jԈ�~��K�.Ѿ}�r��m,&&&888���@jj*`ӦM���)	fffdee��������999J�|ڴi�n�R�����c������J�k׮�O?������h�����>/^��ŋܾ}���{O�1������;w�](ܹsg���9z�(���{��B<1ggg���+�o�^j��w�}��a�*|���=��8��٬X����h�l�Re.:Tl��۷�;w....�{�aÆ��_Ql56!�B!�O���?����*�
!�B!�B!�x9Tlk!t�w��xyy��?��nܸ����accÔ)S*�Z�������>III,^��=z��wvv��7����D����O?q��y^}��ˆw�ޝf͚����O?��D�y��]RRR�>}:?��M�6���Z��E�������9s�>>>O<nY<���>}������E�i�}�뭷X�lYYYܹs��K�bcc�СCK<O�X�����o�%??�֭[cee�W�hӦ
iii�S����珅����|��G�ܹ����֭[�t�R������m۶$''����~�̙Chh(�7of„	���:*�3<<\9'<<\�Z�hբE��[�l��G������Zb�����###�~�z�}�������V�Z<�GX6SSSf͚����u������z�*#G�T�F��իW	

�adB!�B�rg�ԩ�C!�B!�B!�H��\7nqqq$%%���v�V�Z̘1�Ү�����IOOg���j�,--5�z��AÆ
�z�*t�ڵB��ر��#GR�Z�bc�V�#G�dɒ%DEE��K�{+i����	K�,Q[�_�9755eܸqjm�۷gĈO4nY���8p�.\`ҤIJ{���5��?��bbbHJJR��L�8������|}}�U�kmm�<뭷8t�)))j��wŏ�ICB7�^����{�=��O�;�'�|�T��?��ԩS���9|�0}�������ٽ{7���;]�v���{{{��i3fq~���Q��Tm�>BM������G�Z�0`S�N�f͚J���?�ȝ;w�_�>�z���Ãڵk���Cطo������ӲeKqrr��А���Ν;��4�ٵk���gРAԩS���/J���
7n�`���:t�۷oӧO�̙���ݿ��O���lذ����]�F���8p &L���@�W��*�>Jk�X�~������ѥK��h�7��Ɔ��0ƌ�̻/�����9B�,EDD�:!^jG��G����aii��p���Ύ����E�ƍ+}��~�
�JW!ʣ��e=���$&&`kk[��K�B!�B!tE.��U�w����~�zbcc�z�*FFFX[[3e�Z�jUi�թS��� ��Ǎ7033�o߾L�8��zzz899��a�4��'�{����cbbR����k֬��gڴi�O����޽;cƌ�Q�FZ�]������'11SSS����i|/
`ժU8p�[�n��;�����޽{����bffFPP���;v�;w�ЪU+ƍW��tmb6l5j� <<�˗/�����www�_���Y�b�f�رj�;|�0������O�{UCӦMվ���P*^����<;v,k֬�ܹs�;w��[�2t�P���[�1���������1U���B��ٳ9z�(�(Y 44�������	�ڵkٰa��9YYY���q��M.\���?�7oV�ܻw���d����u��G�U�
'**�q��i��پ};�R����/Knn.�Ǐ'##Ci۳g�n�*����dgg�|�r^{�5��L�2���T�-33���@RRR�GO�Q���Weڻw/������i����ĉ�۷gg�J��U��ە�9B!�B蚭�-zzz;v��*����L�=X�v-�F��Ա���;s���m IDAT���lݺ���BF�����;w�uhB!�B!�
I�UZi�&&&̜9��3gVhm��֭�������,�&MR��PTY����s�r]��А��X���w?ݡ��s�R�n]V�XQi�j�=322b���̞=�̾O�M�4���G��cJ�cdd���+6l ##CY�����ٳg�<yr����g����we���+��saaa�����W����ѱcGN�<���p�aaa�ڵ�Q�F)�8ڌY�bm�"�ǩ�J��#��?�����p���Y�z5aaa���*�I����QbƐ!C�V����L�<�Ç+�DFF�j�*lll�w�������u�V%��e˖t�ԉs����?�Uc8}�4���k׎���ku��lٲ���,,,�ꫯ���"99�y��z^Iպ�W��QU*88���T:t�9shٲ%iii���p��	�����坯�8u�T��&$$Ю];�sTm			�p!^
e��B!��Y�[�.�ڵ#11�R.~��w
ěo�)���/�۷o3w�\\\\077m8��_�����#B!�B!�xD.�������ݻ			Q膄�`nn��������A�\�r�իWӠA�2�ӻwoz����?�Lbb";v�`ӦMJ…�c��+�p��urssy�WԎ���*}�x��P���E���9-Z�`�ĉ���q��
�x||<����?����~���'O�����]�6yyy���p��ez�ꅋ��R��q��Μ;w��۷���w���S��%..�9s�(�)��������O�=N����ر#�'O֘ט�|||hҤ	-Z����'''�����m櫲\�p�f͚ik޼�Z!^t��S!�е��B�|lmmILL���]�F�~��W����j��������q��UF����5�o����� <<<t�B!�B!��4��B�B144��ۛ��(233���$**
ooojժ���D%�ڵ+����/���Ç�믿f���,X�@��G1|�p���ǝ;wh֬����F�SU�"33SiS�y���xUm�>BM�Z�R�׭[��*mׯ_g�ر�;������[�r��e@}���ӧS�fM���1b���ܹsG��.u����ܼy��7or�����߿���/��@ǎ���x�R�;u��N����i�}}}XlrKzz:�B�����P%Y\�tI��|U���l�ԩ�qLզ�#ċ.""���]�!�x���!!t��*�BTݻw�ԩSܿ������gȐ!����|�B��bŊ���G��}~~>�V�����ݻ3d�֬YCAA�h��w�y'''��a£���������
�K�.4l�P�׸qclllS6mB!�B!��5�p!�/�7�|�-[�ԩS����qT��999q��I.^��g�}�v�f͚�����
`����_�^�o���+4���	999|��'4hЀիWcmmͩS��t�ڸ���7�|��n\��D���ʳ�\Y�[.]�����caa�;�C˖-y��4v������֖��8v���s�X�f
���L�:ggg�k2���`���{F����OAAC�UK�+�ˢJ�(���xXiLLL�;w.���,^��z��ѻw�b�Q��+rh3_��UIg�?0kKu~q��Tm�>B�BBBpuu�uB��Thh(�G��uB���KB�*���%??�s��=��<x��Q��|�2G����G%F)�O�믿&$$��^{�I�&�~�5e�RSS�~���������?u��Q6.ٿ?���J��xz��	�޽{������N�vvv�8q�}��i�N!�B!�Bd�(!D�S�6-�WWW�/_����5j���e'<<\�sj׮͗_~��iРzzzӥK-Z�VI��w���'���*������caa���S�N�И|�
6DOO�{����[oQ�V-~���x��j׮]�T�哘�@`` ӧOgȐ!j��u���6l��͛qww��͛���i�;l�0�U�Ǝ;����6�/����O�VkOII)�m۶e̘1���T�P177`�Ν�{��'N�P�_��R%@ܺuKi{�R�6�������8�jS�B!�B��k�///LMM�h���������s�N�ʖBQ���B�-X�j�k� 88���T:t�@hh(Ǐ'<<�Ν;s��	���=z4�k�f�ƍj�.z��@BB��gkQ�6U!�B!�B]�
B!�s��Dccc����*O��w��;�?ɘvvv����<���H�^����z�*?��#ÇW�-_Q1ǎ��w�����,\�Pi�y�&���8::�����ٳ4h�[���~@___c<KKK�t��$w��E���iѢE��_��f�|||X�p!;v�…,Z�H�y������!##���f͚��ݻ77n���OOOZ�n�_�Epp0[�l��Ɔu���{��իGvv6۷o��ٙ��L|}}ˌ�Z�j������%mڴ!++���4�Ċ��4��B!�/��&p������W_=�8���ѭ[�J�J!����[V���������	�W����D9���M�4�E�x{{���Dtt4NNNԭ[6o��ѣG���#77�s��add�T_�p�͚5ӈQ�ѓ��B!�B!��I�!�B<U���ԯ_�]�v)m�v�A����{:�L��_�^��7ovvv���q��E�?��$L���ҳgO�w���G΢T�,�.]
���K��_777%�`ҤI������N۶m�u����!��ϧZ�jDDD��/�(�ƍG���IJJ��͍nݺѿ�l�B�Z��1c�ҷ��+VУG��+��Rf����UQUy뭷��z��T;
!�����i/ ���g�̙���ckkK�~��9s&G�����$s��+W��t�R�
������G�&  @��Qq���Y�<J��9s&3g�ԺʝB��^�u
KL��y'_�UUhh(������j����pppP>3�������W}uss�f͚p��Q<x@��ݩQ��~����ԩSG#U���B!�B!��I…B!��Z�j1u�Tbcc�v�׮]#66j֬���ЙS�N�� W�~�)���b``�k����ŋ�4i[�n-�7om۶��Z�lɸq�X�`A�c���333���/LMM���S�������\\\�W����OIrІ��5Ç�,_�\i766&00WWW��ͩ^�:&&&��Ջ�7�U�(�|͘1�֭���vvv̝;��g͚EӦM�^�:��ߟڵks��a�����ؘ~��i=B���_���G�~*c߽{��>���3gOvv6�����?�$>>��ӧ��+?�*�i�_��/2j�(���IOO����[�nq��=z4W�^����̙3����駟2k�,V�Z�ٳgu�B!��9���c��A�����J�Z�(,,T*���z���<幩�)��Μ9s����]�o&R�Z5�Q���Tm�>B!�B!��VC��[hh����������}���9R��jԨQ�o�^�Q	Qu���Q��N�:����W������C�c�^�:{��-�Oy�_4�����Ȉٳg3{��2�����駟�駟j����(;���<�ehhX���~moo����Z������lذ����6m
@FFgϞe���Ԯ]�̸��Q��C�Ur$[�h��ؘ	&ЧO5jDNN����[�����Y�pa��Q\�O�LX^˗/�֭[t�֍O>��-Zp��}Ο?�������W�M��~V�p��m�Ν��������/�����

�IB!�B0s�L�ׯ�ʕ+���'55U�=���9iii�ܹS��R�1c���߲u�V�=����R���̌��,rrr033S;7''G�#�B!�BQH…xj�M����B<,--u�x�<����:!������ٽ{7!!!xzz���9nnn:�N�����xv��'gϞ%::i޼�r��ԔA�akk�ȑ#�����Ņ�;�.�
HJJ%����+ԨQ�7�x�
Ƒ#Gtb�����z�*#G�T�F��7�|CPP:�N!�B�2=z4���\�t��kײj�*z���ƍ�����ӓ֭[��_̖-[���Q��ѠA���o),,�S�N�g7�6mڐ��EZZ�FbEZZ��G!�B!��*Ь�)�B!��344��ۛ��(233���$**
ooojժ���x����`cc��ӧ�ӧS�LQ����j�*�޽;C�a͚5h�s��u�͛G�>}�޽;nnn�۷O��T>|Ⱥu�6lݻw�gϞ|�l߾]휒�/o�%��;;v�Z���LMM�d��Nc̻w�`��~�m���üy�~�z������\�/_���������Ϗ���b��ҥKxxx��oӷo_/^��۷5��bR����ԩS<x�\������剫�����\����ҥ
6T�7n���
aaa���jܛB!�ܸqC�a!�V�W�Μ9s�V�ǎ�ܹs�7��͛������ݺu���lٲ�Z�j1c���ƎKaa!=z�P;��v����q����9B!�B!��".�S�r�JBCCu���\]]			�uB!�K��7���Ãe˖0u�T���u��/???rss��L�2���T�Off&��������ޣ�)nݺń	���ߕ�?��#s��)��l޼Y��޽{$''���̭[�=zt��jcI��Zӳg�R�|��Y�r%gΜ�8�d�v��	��;w�����ٳcbbR��-//�?��˗/+mYYY���r��	�]���9�'O&''G���m�x��!^^^J�	&�h�"&M��СCy���С����M������y��ݻ���|���4����q��	��ۇ����#�B����a�XYY����:!�Ъ:dǎ:t(����]��u��allL`` �ׯ'66��W�bdd���5S�L�U�V�)ϋ~>�߿?+V����Ì;V���Ç166�_�~ZޥB!�B!��!.�S���Jaa�<�!�������B!�K��Օ�˗�|�rF���p�x��hт��.\@pp0���t�Ё��P�?Nxx8�;w�ĉDEE)熄���ӤI9v�e.����`ժU;v���xfϞ
�֭[��.�N�R��&ƒ��ڵk�����?���^��q�ȑ#�\��cǎH�&M�r�
�����_��͛�|�2M�6U�qÆ
4i҄K�.�q�F�s�5kFdd$			�?���X�>C����6m��ĉy�w��?�Ixx�Z5��b-:%)+.m^3			�k�N㘪M�G!�U˵k�8p`���ãje��?�dŊ�8:!��^q���̙éS�X�n��fbb�̙3ٹs'Ǐ��,[���d�{3�f͚ѢE�cFFF���r��Y222����Ξ=����Fr�B!�B!��H�!���1c111�C�*+::Z�!!���lll���"777��U�|||hҤ	�h����7NNNDGG��������ˋ�;`mm�_|��i�J��v�������˗�ի...����y���X�}��
j�(��>���j�}��ٳ��;v��ˋ�S����G���R�<v�ԉ9s���Gq��A��<==���`���r��M��������?~�ӧOs��N�<Ixx8k׮�A�e�Xt�JRV\ڼf.\�<ZxTT����!��j155�ȑ#$$$СC�c<`ԨQ\�x���8%�U!^&���ܾ}������3��~����޽���<==�G����渹�=�x�B!�B!�"	B!�34h� ]� D�'��!��,���*���888�ҥK��4�x�
�>���e^w���,X����DY�v-�Ǐ��ՕZ�j�z�61��φ
���Iff�� P�.��U`���U��s������%_�5:u�֮��+W�h�ӲeK幉�	>,��ڵ�]�v�7���6n�H@@����Y�ti�1�����6����l�ԩ�qLզ�#�/���t�5kFRR������BC����ڵ+���L�<Y������9x�~�/��={*ϭ��2dH��

��O>Q�2���X�re����B!�B!�%I��9QPP���y�&&&&�ٳ��8U���vu-���me)Z>�2��4~E������<Z�4|�pG$teժU�A!��T�=~y���T\%�����i�=�Z�j���*/���ǎ;8w�k֬!88��S����\����}���dffr�>���:p�ҿ���1T�zzz��W^�%P���+ϋ��=zp��m���5�Epww'  @�V��T�(O\*�yͨڊ�OU[y^kB�"{��C�D���l۶M���/�$  ���H�u릣ȄB�6lHNN666xyyQ�z�����xxx�l�2�N�Z���B!�B!�%I��9�͛7�y�&qqq����8*QgΜ��ߟ�[�RXXȈ#���Rv�B�b�E�BQ��������Ν;177/����?��3�Ν�k׮J��s��u-ppp 55��i�&���JM��&ƒ8;;MPP=z�U�V}.^���͛prr�8��������^}�U�biҤ	���+gϞU[xx��Y�
�c�v�8}�4۶m����qU���J)/m^3fffdee�������ڱ����B�̊K2�����e���dggcjjJRR���g���%V*B��Ett�V�]]]quu}J�!�B!�B<9I��9�c��{�=v��ETT�'\T�*������۷�;w....�B�aÆ��_�����#�Œ3����uB<��������ۄ���:!D#;�V
�{�f�ƍxyy���I�֭�믿f˖-��ذn�:�����?���ŋ���/i۶-�ϟg���e^��ё��fϞ͠A�hݺ5����Y%������t,--���$�:ub���޽�	&0i�$��틙�ׯ_g����������0��d�E�)����������/5��z���ƍ�����/��}�����*�أG�2糨Q�Fq��i���c�СXZZRPP��ӧY�|�2�����yʹiӆ��,���4+T	#mڴy*q
!������RXX����8p ;v�ܹs����M!�B!�B!D%���s�3��B��$++��'OR�^=>��3�9‰'��?hԨ����

��ի�9Ri5j�|�
AAAxxx�0:�,2D�!�ܓ���BT�q��GRRnnnj�jժŌ3��G�͞={���_7n�V�qww���___|}}ՎY[[+��իGvv6Æ
��ܜ�;wjci����{�.������???�>�{�f�ܹŞojj�q��۷gĈ��_���;$==���ǫ����h+�޽{3f��l��֭[ٺu�F�f͚1m�4�b}Rڼf�z�-:DJJ��k %%�X2�B!��
ЪU+8p �$[!�B!�B!�J.D��J�`֬YXYY);y���a�bbb�v����g�L�0�1���c׮]ԨQ��Ç3e�rrrX�d	������ӳgO<==122R����%  ��r��
�ׯO�>}�4i��Ƥ����쌅��������ȕ+W�����¢ܱ�DEE���C���! ,,���(&N�X�s^���{��e�…4Hi߳g_|������?�`͚5$$$���G���;v��yE��pS���Ç�o�>233��קe˖8::���T�xe}������IIIԬY�w�}��ӧ+�(�Knn.aaat�҅�
*�7��Ɔ��0ƌC�:u�>��WTT��CB<cG�a��ѺCQń������0^(I�766&00�����իW122��ښ)S�ЪU+����!���$y�$ IDATO^^-Z���͍y����MeذaԨQ���p._����=z���]�7k�,V�^MVVZ�X|}}�����#99��7oR�n]^�u����ٳg���1�|155e���Y����:u�������q�fff��ۗ�'bbbR��)�O>�[�n|�����ƍԨQ��͛ӷo_F�E�ڵ���Ii��߿?+V����Ì;Vm�ÇcllL�~��J�B!�����$&&�:!�B!�B!�O�$\�炟����ʢ����L�Bjj��'33���@RRR�GOOOm��K��%C�_���M���s��v�ލ����� //�?�PY$�*N���r��	�����Ɔ�'O���Dǎ��IIIdddЭ[7,,,������]�v�����@XX;w�d„	T�V��&��g��̙3,]�kkk7nLVV���4lؐ9s�������;ׯ_Wνt�����O�;���?�7oV��w����$''s�֭����"�ɓ'���<zMl۶�����U,{��%??;;;�����8q������ٹ��"��*+,,�uB�*�i�_�+-��Ą�3g2s��2�155e޼yjm���ԯ_���988���P������W8��$���ٳ�Ċ�ԭ[�+V�ڧ�����nݺxzz���Y�x%�OI����ږ:���׮M\�}����ʆ
��ȠiӦdddp��Y&O���YU!�U�ҥK+�<*��)44���P]�!�B!�B�’��\hѢ����n�������ҡC�̙C˖-IKK��LJ'N�Vi %%�o���f͚�y�f֭[���/VVVl۶�ƍ�i�&���W�ۼy3�/_�iӦ|�嗴k׎��T�Ν˥K�ظq#8;;s��Iv�ޭ�p
���K�b?y�$W�\��ʊ֭[`ee���/^�ԩSt�ҥB��P�‘:u�`�<<<�7o�֭c���ܺuK�J�6m��oߞ���������_��w���	�d�U�Vaccý{������ח�[���pQ����5k���7�5bÆ
�$\�7���ڵk���-!!A.�Z��?hԨ���B!^h={�$??�ٳgcoo���1iii,Y��7�xC���F�׌��;�w�&$$DIF			���77�g�B!�cnn����iӦi�MT!�B!�BT.���Q�lll�e����)�111���`eeE���iѢ����I��={6�[���WWW�޽˜9sh֬5k�d̘1Ju���X����ر#���t��I��p��Az�ꅩ�)111ܻw����CÆ
�E��=**
@#a����;v7͕�K�.���r��i>��C~��F�I׮]�>G���O?��Ғڵk���ũS����8�Ξ!!!��������©S��9*Ny�������Ғ�5k*�7o��:�.�8�j޼�Z!��F`` k׮�uB!�mРA���ҧO�v���ϩS��W��&M�q����5chh���7QQQdff���ITT���ԪUK� �U���%������ۺE
�o�V۰I!�B!�B!ċO*\��jq�Jzz:��t�F[�6m���-[�T�j����@�N���U;S^�r�5j���HPP��O�>=z���&M�D��յ�=77WIX�|9˗/��K^^���ŎWU��:u*Ǐ'99�-Z����W����\��O�΂HLL$11��k�2~�x\]]K]�R����M�*x<|�P�X����GUB�R���!�6Z�j���ùp�_�5ժU�uH�%r�…��'11[[[��,CB�J�J�����_(((�Q�Ft�ޝ	&аaC]�(����f�|�M<<<X�l�賷����]!����F�ɑ#G�|�2u���uHB�ʕ+	

�uB�"
u�B!�B�J$	�+��_U͢���W���A�����V�f�b���U�����U�ʦM�صk}��!::===�R��ľg�


J���]��ك����wP��t�oaa�2Fq�loo���-qqq�ر�s�αf�����;����?��r�+r�)��𘈳��)��!`"�68���-��:\�,Mp�y��Z��Hj�\M�Di"�
"�?���� �qx?��x����k}�9�0�>k�Z��ѣ8p`��+�3���5=.輊��؂�1c�I�Hi��.\ȅ�����~v�T���dz{���n;t�����]����<^}�U�7oN�6m,��H�Y[[���mZ!�AQ��|1W�k�A��DDD�E���|�
[�lQ����U�������t"DEE���c�0DDDDDD���n����999CBBB�->>���_�>�6+7>7�b����Fll,���|���t���l˒�
ܜ�����|�Y���x�b���iժ�N�"44�l�_�����E�bL8�|�����6���`���\��aÆq��E�ϟ_h�%y�J�8�ԩS����|�ˌuDDJ���{{{�W_}E߾}L6)o�w�.��ʕ+L�6�A����D���0`S�N�ʕ+��������H�
		aٲe�^���]�Z:�DJ��{R���������r��9.\��``ԨQ��W�n��ȑ#\�~�#G���Gйsg��$77???����<Q��O�<ɿ��/{�1:t�P`l:t�Q�F$%%q���r;��8p���(ڴiCXX����^����t����s璖��իW�3g��W^y�жkժ�ƍ�r�
�N�"$$$_�~��a0���NVV͚5�y��E��^��8�K�-HII�׆��XGD�$���iٲ%��_ٹs'��k׮���Y:4)��`Z��^Nzz:^^^��!C����Nxx�#)����L�¢E����t8""""""""""R��t"����Ǯ]�8r����f��V��رc˭�aÆ��w�q��i����5l�0_Y�Νqtt$==�
��ϖ*�M�6���eZ�vVVVxyy������Ktnw䙐�@ff&AAA���3k�,z�!���2d3f�`�ڵԬY��Ç�c��9B�>}��y�7
�[�nlذ����o��o���=_�aÆLHHH��WW�B�/�Wō�cǎ�޽����|1&&&�K�x��'9z�(���c�޽��⋸����_�����e��l�2&L�@���Y�t)YYY,_��;v��S�n]^z�%F�������7n�l�2�o��ٳg����I�&��׏�����W�6o������š5kh׮�٪^����`0�f��J͚5+��� ��ь1�I�&��[oX�ڵk�;wδڲ��߉'
��lݺu��������+34�p!���@BBB���Q�aaax{{��䄍�
t�֍���r]5�f͚���3x�`�����ё!C�����Y}kkk� ��K�(N�999lݺ^~��"��ӧ5k�d�֭����y�����o�1q�D�F���g�ĉ�����ԩCxx8={��f͚���ҲeK>��cz��]h�cǎeРA<���������δi���0`ӧO������;;;�4i���3g�,�����Q�Xz�ꅽ�={����ƞ={�Q�/��B��x�'HJJ��Ņ�{���舻���K(��͟?���LS"Cvv6�F�bŊ�9s���Ξ=KXXcƌ�ƍ�cCCC��/8}�4999deeq��Q>��C"##M�J�fA�m�FVVV�	����dee�}��rzED�A��フ��6mڴYd����A����2e��Nppp�����1bD%F&"r?~|�{:t���P��}&L���E�8|�p%G("""""""r�V���ZQ��7�q�ƕ����?���L�8��'ٗ�ȑ#9rd������-�~�m���V�;w�4=�=��Χ$	.�g�f����_~��|� ���/򋧂��V��'Of���w�����K���+�5Q�X�W����7˗/'55gggRSS9|�0o��&���E�!"R�֭[������]�6u������ˋ�{�իW����\\\3�2�j�*���hݺ5S�L�I�&���L||<��Ѧ��
6�h�"999lٲ���֮]k�2��m&$$��la@˖-��o,���e��*��fݺu�ADDDDv��E�Z���*xj�g�}�Y�f���Wd=1�{��˯\�´i�4hNNN���ЦN����V�Ze�)"""""""�.DD*ҰaèW���L⑑�899���k��D�nd�Q�8�|�IMe��������LJ��g�UH��C�Y:3��l�S9����)�`ǎӼyslllpqq!((�-[�����"##Y�n��'�
"!!����R�Y�'NШQ�|�7nlVGDDDDD�N222���b��͖E��u�bccSd�:p��y~���J�JD��
��x�
'==///Sِ!CHOO'<<܂��������ȃJ+\��T�jժ�{��СC����O>�jժ�ND�e���<���;v�.]���mllX�l��_y뭷HMMe�̙�]2ŝ��ߟM�6���g�P�Ę�`t��i�BW/INN6=3f3g�$..���8>��S����6�T�6r��yj֬�o���XGD�8l�DD�%ED�r�iӆ�U��o�>Z�ha�pDDJ̘��f��ϟϑ#G�R�
�?�<cƌ1[Q"++��˗�c�~��w�֭�K/�Ĉ#L��m�6f͚E�޽M�~���L�:���o��&_�			dff�f�ڵk�����N�z�0�Y���C�x/RDDDDDDD��(�BD���mۖ���Ν��ѣquu�pT"r7*逮'�|��G��o���$%%�p��Y>�����i�&K��OBB���[�H,̭�[����K�.����777v��ŦM��駟X�d	�V�b���8��mĘ�cm��<cك��#"e�������TTT>>>�CDD�vvv���������)�7�|����^��W_}ō7 ;;�Q�F���d:��ٳ������Hhh(���L�<�C�1g�\]]�W�iii������Ȕ)S�.n�m�6���pwwϷ��ݝ��x�o�n��)"""""""R��r���ͼy�7oC��t8"r�x��'ILL�W����K/��ڵk�ѣcǎ�@tR������!!!!�oV���/_�ʕ+6l/^d����n�vu��0}{+c��������ȝ<��ÖA����܈���t""eҨQ#6l�@ll,����ܹӴժU$%%Ѻuk���ؿ?�֭�M�6���
�\�v�̙\�|��ӧs��
f̘��˗	

���l�}H���XZ�l�/>c����������HeQ…����]����l%���y��]�6ӧOn~��~�W�N�Z�<x0~~~<�����o|��w<��c>��իS�vm��ٳg�ϥK��<y2...T�R�ƍ�իW���8ϝ;����)N���u��Q^x��W�Nݺuy뭷�|���NA��7�>}:-Z��J�*ԬY�:��_�t�����@�?Nnn.�Νc�…F�e�ۯ_?�����ʢY�f4o�[[�R�i|-O�>m*kѢ)))��5�눈�����܍��ùv�Z���С���w\%RD����N�'N�aÆT�RŴ�ۭ�qw��@pp0͛7������زe��n�v���������xyy�����'����o׸qc�:""""""""��!K """"E{��Y�l��|���dgg���MVV�ׯ�z�ꄅ���ネ�������X�j?���V�Z�y��U�w�n6�XJJ
�����dzm�6���sw�sɒ%8p��ʕ+���&<<��}u�ޝs�Ι�\�t)���f��n�������yvv6qqq���q��EƍW�w???v��ő#G�5�W�jU��L�
Fpp0!!!�����uuu-U��j���0'''bbb�ر#�w�&11Ѭ]��K�Ν�v�""��'N���n�:���nnn<�2C��ܸq��!�"$$��S�ҠA���R����FǎIOO�F����H�hҤ�鱃�`���8	���G��'''�==z4�����ѣ�����;��1����7Wɸ���XGDDDDDDD��h���\||<?��W�\a֬Y�}�ogg@�*U:t�Y���͛ٺu+׮]#66�ƍ�믿2o޼B��7o			�oߞC����ñc��ԩ�|�
aaaŎ��Ɔ�Ǐ���Ō3���)S_-Z���&++���@�����g����gznL��믹v����,Y��E��ZT����$��Q�aaax{{��䄍�
t�֍����`���<������aggG�&M���c�̙�js„	8;;cccCvv6�z���ޞ={��wϞ=ԨQ�^x��/���}i���YBow��!BCCy����0a�-���Õ�����#33��!� 22�)S��hѢR'[���e��ݸ���ct""�g��x�=���|U�[W6���kA�c�c��O�skYA���������T$�p!***���K�!"%�~�z���-����ŋ��SO0f��O�Ε+WX�|9�۷g��|��G4jԨ�ٽ�,Y‹/����;˖-�gϞlذ�?���>׭[��իy��hժ4mڔU�V1bĈb��g�����̜9Ӵ:Ei�Z�h͚5`�ر̞=��3�ըQ����ϟϱc��߿?o��o��V��YBQ��7�X+rxxx:�\i��ٳ'={�4+�^�:���,_����T���HMM���ü������1���ݻ,�r�
ӦMcРA8997�N����V�Ze�)"""�@زe���L�4鮼7 "r�qrr"%%�����EY�x1��ɴjՊ��$BCC�x��N�:������A�:u�edd�ꈈ������T&�p!�}��xzzZ:)OOOڷoo�0D�=��3�Ƿ.���O���Bdd$
6,���w��	�_~���cN�<	���VVV��iӦ=z�DqU�^�\�jݺ��q�ڵ���2w�\�U����?~<O>�$���deey��ٰaèW��������H����`d"r?3K�Q.���IOO����T6d����	�`d"""������@�B�߿OOO<==	�t8""���ݻ��������ܹs,\�����Q�Lu8@TTmڴ!,,WWWV�^́Lu�+U�>}�Tf��'%%%_�Ʋ[W��Z�B*̻�˻�k�0DDD�y��jmcc������!�?���	666�s���lb�**΢��/;;;���.!���E�^�ظq#˗/'66���@�ΝKpp���R2ժU#((���{��C��'�|BժU-��<���˖-c„	4oޜ�K��������ٱc���;u��套^bĈf�_nܸ��e�ؾ};gϞ��֖&M�Я_?���o�_qڼ59�8!!���L֬YC�v��~�׫W����5k:t�Y2������^rr2}����'<<��DDt~~~�ڵ�#G��d�jժ�;���L������g֬Y<��C1d�f̘�ڵk�Y�&�j���0'''bbb�ر#�w�&11WWW�>�ܹs地���������
Ra|||�f�֦M۽����X�Lj��ANN���}��}����lٲ��7n����J^^^����ke�U�V-��?�@||<�&M��?���R�rgm۶%  ��s�2w�\F���KQ��6�|233M���ٌ5�+Vp��rrr8{�,aaa�3�,	044�/���ӧO���CVVG���?4[ѧ$md۶mdee���o���;YYYl߾��^Y�z5...�^�[[[K�#"R)HHH(S5j� ,,ooo����������nݺaZy"���� IDAT$$��~���'R�~}�ׯ�ĉIOO'$$�	&��쌍�
������{{{��ٓ��={�P�F
^x�2���������HIi��P���fQD�ޠd�{߭F�ATT�����řVr2dH�ǿ��+������͢E�xꩧ��?�7os�Υ{��|��w�kE�eeeE^^?��3͛7�I�&�:u�%K������O?Mrr2`�b�����7��ޖCD���Ņ��0��U�V���D�֭�2e
M�4!%%���`��㉎�6�^�a�-Z��` ''�-[��ڵkM3�̈́���-�bcc��!�e���8��^%�˴i�;v,����ED�PX"FA��7��	lfϞ��ٳ��˼��˦�={��gϞfu�W����7˗/'55gggRSS9|�0o���~~�������H�S…T(OOO<==-����ƍ-������\�����o��v��L�<��7�w�^ڶmk���ޞy��[|�ף�>Jzz:-Z��Q�F���L�8�Q�F@@@�Y��]���DD����T~�___���;vl�e��Ņ�� ���ϖ-[L	���\�t���HN�:E�n�4h�
2�$m�ĉ4j�(�>�*P�:""����[:�KT�w5j�(�6ED�|6�͛7�ĉ������	___G'""""""""%\������.\�@Ϟ=ٹs'���x{{3m�4�V�Z�1?�0{��e֬Y��� 55�t�¬Y�x��'�-���k�…r��i�]���o����-�/&))	��M�ҧO&M�Tn�#""wc‚��ӧ���(��q�#�1c�0s�L��∋���O?���ooo�ߡ%i� �ϟ�f͚��ˌuDD$��t"r���˳tŖ��Ʋe˘0a�f`)�jժ�{��СC����O>)򞶈������HEQ…�]��Y\���[�.nnn����fQ��Ͻ����f�֭#..777
�b�}Aa
JZnkk��``۶m���V�Z,X��z\y�Y�}yyy��啯���?���E�!""w��/(���nw�w��%��={���Ʈ]�شi?��K�,aժU�=����͂XYY`mm�o���XGD�A��������������a��իW�1cݺu�K�.�GD�նm[�;w.�G������Q�������ȃJ	"����lΜ9Æ
���	

婧��tX�:Dhh(k׮%//�W_}��͛ӦMK�&"��'2}�t�~�m���,�C�v""w'''RRR���)��D<<<��� ))�o���+V0�|S�EIۼ]�:uHKK###�:u�����0���_�ƍ�W�qqqJ�)#ooo%ߊ�������]A	"��[gm�v�����	

%..�I�&�a��U�f��ʕ+L�6�A��[
0��S��~�z�G"b���-"$$��Z:��^Æ
���t"r���aÆ�C��ݻA`` 'N�Y�f\�p�U�V��_b0X�t)���#55�ɓ'ӻwo�5k������Q�i��ʊ��<N�>m�&Z�hAZZ)))�+RRRLuDDt�ׯ�t"RI��������B۶m˥���С�i�c��)�B,�`0�	R�*U��㏳`��
��?�LLL�fҾ�����������lȐ!�^����p,��<��V��ƍiڴ��Cy t�ԉN�:Y:)����v��ȑ#�����Z�*cǎ5=6l������bV��յTm֪U����3`��������cǎ�޽���D�v�ܹs�N\D�>��^"����2���w������ɓ+=���͍Tj�""""""""""Rq�-�HQ���ңGF�eڗ��ŢE����C���ۗ%K����]`ׯ_gΜ9t�҅=z�f���`ʔ)t�ԉ�ݻ3c�._�l�Fff&�����_��͍>}�0�|.]���ӧi׮(�<���G�v�L��7�;���������l_I_�k׮1s�L:u�D�=�>}:��G�>K�nrr2t�ԉ�{��>��+W���=w��f�����ݝ�S����U�9WD����3f������
///�l��|�v�J����q��q�O��`0Я_?S�5k�Ю];M��ի��``͚5dffx^""!//�4H���G$""R~J��_�F
�������	�֭f+I0��ӧ��cgg���M�4��Ϗ�3g���	&��쌍����^�zaooϞ={�Żg�jԨ�/�PҗGD�i�?G�6m��Y.?+���π���$((�\�,	777�����_+�o)Z�B�	���'33�4�=;;�Q�F���d�s��Y���HLL$44kk�|�9s�a���/��ggg֯_oj��իl޼kkkf̘��K�x���9u��ش�4������',,��
b08p�G�ᩧ�2�=r�����oߞ
�*���i���'O��J���LLL��uزe�fժU���i��7�$##���W_}ō7n&)������j:�믿Η�RQ��?�aÆ�%�$''3}�trss�۷/���*aaa|��7����TϘ�ҥK�m�FVV���bwww'>>��۷3p�|�ED�ާwED�E%b8880n�8ƍw�v<<<���c��ٳgO��)�W����7˗/'55gggRSS9|�0o��&���w�ADDDDn���۷/m۶%,,++�J��`0��CG�ƍ+�y�DEE���c�0DX�~��C�
�.����Bll,�f�`ժU$%%Ѻuk���ؿ?�֭�M�6��������DV�^�޽{M+e���`cc�W_}Ell,#G��W�X�r%�N���ٙ��0������˩_�>���DDD��o޼٬_�J	�
*u�E�]�6.\0����~��O>��}��F���9s��V�*S��5bÆ
�������Ν;M����KRSSiР+V�`߾},[��,��"�_�b���Z�bÆ
|������+�����ヽ���62^'�;w 66��-[��Xf�#""���
���i�0D����IÆ
-��E�
F�z��fu������	___F&"""r���y饗pqq!&&;;;��aoo��O?M\\�E��K���uoR�.���Ϥ������}H+\H�3�*�uFR___�/Gv��@pp0���n&eѿ�l�B����ڛ<y2͚5��ۛ�K�r��5�L�B�F�:t(˖-3���78?00дr��O?͔)Sx�����[�nԮ]�;v0a�lmm�~�:;v���Ѵ
Bib/Jnn.=��Ҿ>ƕ�z�)=z4;w�$  ���N�8�4���LJ��0.^�hڿk�.�L��O<���+��?�{�=��*��~�����T/00д��?̠A�X�r%{����ݝ��L~��'�W����+'N�0]O�2�df�#""��N�:ѩS'K�!""��jժ�{��СC����O>�jժ�NDDD�piiiԫW��ap��%���@LL��W�={6u�ֵh"�`x��wy��w-���������}M	rO�}��ӧO���Q`����|e-Z�0=��˖&M��W�V-�q�����$�[=��3�9s���Я_?���ٳg=z�`�޽ddd0r�HlllJ{Q���jժe*+Mnnnf�۴i����2�{�������7Le���,F��Vѿ��(���/k׮%<<www���Knn.:t0%��?��5k�;�Xf�#"""""r��m��ܹs=z�)�[DD�m?��+V��~ %%���\i߾=Ç��_�t�����
����rm����899������gϞ5�
,���?g�ĉ��矖��Ǐs��y�n�ʣ�>j�p�ի��C����QQQ�CDnS�󊈈����e)�B*ݭ+W���lq{��n_��N7(.]����J�*ֵ��.����:h��W^aŊ��G�lٲkkk�UJ{Q<��?^�>n]!��n}}JӮ�����K�[ۼ���㩨�*+H�ڵ8p QQQ$&&�g�:w���)cYq��׮]+���T>ooo���-�������t���غuk�}�������W_}E�޽Y�z�i�)���(������f��Ռ=��Q=F�i�LIII�W�����i�0D���nܸ��a������H9ӝg�'999���BLLNNN�W������_9|�0�۷7�>|�˭u��܈��%11����]����X!����f��֭[��8r�)��СC<��c�Q�
8u�����T�����nE������?$''ӪU�"�:�����]���{�bmmMǎM��ԩCZZԩS��،�S��ALL;vL�zDDDDDD��o�����;�N��~���7��^z��{����~�z�̙Ö-[����o��`�R�����^c�ʕDDD(���Ϗ�<�<==���t"����p!"""""r�)��"ֽ{w9~�8����;w��b05jT��eLd�ȑ#\�~�#G���G�+8���\������fРA���k�HLLd̘1�<yggg�%�K���ٳILL��:t���`�2�{'/��"p�=x� ׯ_�رc̞=;_݊�ߘ01w�\��Ҹz�*s��`0��+���}��G�ׯ_�5/^��'��G1�oѢ)))��1�눈XZǎ�|�2s�̱t(""""""���Çs��)�v�ʱc�?~<�Z��Z�j���ѢE�N��޽{y�Gؽ{7K�.�t����D~��G�֭˒%K�]�6			;v�ҡ������������}B	rO���q��9r___ڷoO�^����/�Z�*cǎ-���
FÆ
IMM���777���9s�
6���߬~�ΝM+Z4hЀg�}�\b7��cǎ�����~��㏱��-S�k����777�x�
���hժ���j�c/���/-Z� --��#G���ưa�x����խ���N�:u8r�}��S�N�[��7�x#_��^{���< ��1y���9�e�#"b)�k�fʔ),X��3g�X:�2IIIa�ȑ4lؐ*U���䄏�IIIַ����v���<==y��G����I�&L�<�K�.��۳g[�n��GeÆ
fvܮu�ք��������q�
���3vvv8;;����ɓ'�</�УG�U�F�Z���� >>���N�<ɨQ�hڴ)U�T�G�m۶̜9�.xLIc+JI�?�+V0d��W�����YyA��QJJ
m۶�z�����׬NRRC����;;;\]]���1;��v��oQ�K�.�Y�f���ҬY3V�Zܜ)9((�
`ggG˖-	/���~�x����R��4ה������y����ڵ+���Y^N�8�����R��J�4�cI�[��q��1n�8��"""""""R����X\BBB���Q�aaa|���ܹ���t�W������K��R�fM�����صk�Ν�N�:<��s���888�շ�����,[����<b�����ɉ:0t�P�򗿔�����3c����]�6/��"#F���ή\c/�\�-[ƢE����o�|�2]�v%00�m۶��kw�:u�Nhh(�����ի4m�???�{�|��W�nzܥK�}�z��o�{����^3۷g�jԨ�/�P�ED*��o�Mhh(ӧO�/��t8"""&>>>lܸ��a��j����AJhϞ=��Ӈ�/����҈��bÆ
|��W��ݻDmV�V��+x������5��:u��?���۷�g��}#� �Q�FQ�v�;�����O<�o�͛7���ɕ+WLegΜaŊ���g�ƍ<������~�u��իW�z�*111l۶�]�vѡCS���sϑ��i*�����<x��������A�%�ە�����5���{q���K�,aժU|��G���گ��?���ر�~����ۡC��ׯ+W�,�9�ƬY��1c��yrr2������|��glذ������cooo6a���P��(���DD��1u�T��P�?������6~�xv��]��+Ky�x��!BCCY�v-yyy���4oޜ6mڔc�"""""""RVyƩ�E������������8+��|S�n�g�ƎK�F��ꫯ��_�t)˗/g�ƍ8;;���J���y��71bDe�\*�<�<8V�\���??��O<���������x{{0x�`G$"r�q٨�(|||�m��u��۟�?��-[��3f���_���ÇY�|9aaaԬY���_899��G}Ĕ)S�����M˖-�v��F�bҤI8;;���?���L�6�Y�f��O���D\\�۷/����ѬY3.]�D�~��={6͚5��ɓ�i�&jժERR���3{�Z�jE�-?~<�<���_�_~�w��l޼�tL�N�����7�`�ĉ4jԈ�ׯ��~F�MRRo��K�,)��n�,��ۼy3}��e˖f+7�hт���͛7�X`��A�lٲ��
������3.\�Y�f�����׏��`�6mʱc�x���ٿ�iE��&t~��o,wtt��?�W^�ڵk�����v��\�z���P<==���?y�7ضm�����Ɩ��,�uS�9��2���~����w7|��������Oi۶-ׯ_��ή���V�w�w�w�e��ʕ+xzzҳgO�}�],X���~����%��Cψ�����ܟ�…�H1deeq��>��s�Z`�aÆ�y�f"##�8q"p�&���������Hq����`�&O�LLL���1
p)��>����t���M�nnn���Q�fM,X��ŋ��...��ӧ��%v,]��k׮�ꫯ�駟��;w���իi׮_~��)�"%%��-[���-ZĥK��޽;6l�����̱a���yv��Ihhh��եK�X�v���N�=ػw�Y���9s���#�`kkK�n�X�n�[�fӦM���e��Vey�"""����ʴiӈ��(re��S�Һuk�*Ɵ�9��=z�0;�g�y�����Ν;W�9��1����?��'�ϟg��>��
�…y���9z�Ye�<��)JI������éW�}�C�\y&#\�~�Ԧ���)���r)���p������2�
2�իWN@@��y�X[:�{A�.]�իIII4oޜ�}�X�Z�j�ٳg9{�,���Q�j�J�ZD�ά��M�8*jЈ��HIXYYiӦM�]�ɽ�8��o�]�~�j�۷o/���������իW����|�
@��yyy���6�]�r�90��v���ĉM�������4i[�n-�ѣG�+{��g�x�Yy�
�ݻ7�����?�1�{�'���#55��b�Ui߿?��������L3{
:+++������?�k׮�ʌL�4)߹=��C�P*B�Ν͞7o���xРAf�\\\���4+/��$�MQJzM�������,���eff2o�<^~�e����ӧ���7��ddL�h׮��ya�7n�`�ҥ0�:ХK��ƍ�Ő��ŢE����C���ۗ%K����]`����yIb0زe�Y��_��``����Q��),������Y��v�����h*�W���5k��@DDDDDDD*�V�)GGG2220bccShݶm��ܹs��_T���VV�""%ֳgO6o�lD!""bi���7�Y\D�2EEE8L�NIII899Y��ɓ��9r$���+M�6e����$''���O+&.\�@ff&?�p��),��O3�c�]ӦM�U�^�9��VS�La����۷�}��7�?��s��ۗ>}���P]��nU�o���\�v��ݻӰaC�}�5�k׮�ڵ�5k���[oئ1)�V����́��СC�q�E�:u̞?��}}s��ckk[`e�<��)JI���Y���/�z��&m篢 IDAT���֥K�x���9uꔩ,--���(���	��޾Tm����r�J���=�ѣG�|��)q2;;�Q�F�~��={���0	

͗Y�'O�СC̙3WWW�իGZZ!!!8::�dY��)˱۶m#++ww�|m������8p`iO_DDDDDDDJH	"��X:�Ap�7w���b"rO�ݻ��C1��������a��*''G	���κ_X�/���u��Q�fM6m�D�Z���1��\�+�6mJBBǏ�}���:��f썳��Q�fM._�\��������?����?�!""����4i����P��nU�/""��;w�"MDDD�	
5����P�1�<�Hq�-�’(�"'�UY?�P�k�~���Fvv6,pଈ��`�ʕ�:u
ggg>��Z�lIRRӦM#99����J_			�n�����
6�h�"999lٲ���֮]kJ2X�jIII�nݚ)S�ФIRRR&>>���h���_h?�*j��15k�d�̙0}�t�.]ʌ3�|�2s��)�o��OY_���XZ�l��cYll�.DDDDDDD*Q�M!""""""""""R����_�p����B����|��_�����ʊU�VѪU�"�0&^�I�Ν�����?�L�:u�5��222
<�…f���+��?�HJJ
aaa���Ӽys~��ƌS!���KJJ��:���x����.�߹��v�������]�z��1�EY>�$���iӦ<�����Y:y�����;w�SO=���-O?��i�����q###Y�n��'�
"!!���hS�;vL��ͱ����Ņ�� ���G�v���������xyy�tqϧ,Ǟ8q��j��7nlVGDDDDDDD*�.DDDDDDDD�"��)��t���M�=0��у����6��2�[��q��1n�8֭[W)}���4m���{��踫W����EVV3g���ãкM�4 11�Xm{yy�駟�V�(�?��.^�h�R������ٿ�Y��ҰaC�����9q�111�ڵ�Bb+��b�
�ZdR�1��X�8Z�n
��?�X�V����uKVVV�}���K�c(��~*Rq���������t""�JMM�駟6+�g8s�L��3fU�T!..��ꫯ�/����xxx�%��������b����P�v�ѣGӴiS�=�����N��OY�=�<����2�눈�����H�P…��������}`���Th�v���ŋ\�x�,y��!BCCy����0a�-���ÖKD*Ћ/���ٳ�~�z���֭��ʊ޽{��O�0�#G�0`��N�Zdݻw`���%&&beee�m��g��^ --�W_}���F����;w.���L�0�TޫW/�̙Í7̎�q�s����+2��hܸ1VVV;v,�>ww�|e�[I߿��\V�Z��o�]d�|���^��W^`޼y�V����3�[Ajժ��V��˪����2&	�~��߹��i��t�%�)�V��|/��={�u�V�O���O?�իWY�d	�{�櫯�2�+h��[w���V��)˱�߯�d�[�nM�����������M3��Ƚc���xzzZ:�ҝ�f����I~�6m�O�>��$::��={��ҞSI\�r�iӦ1h� ���L�ׯ_O�j�*<�|,^����X^|�E���yꩧطok֬!""��z���`�1���,^����z��+W�q��[o�Œ%K�^�z���{ԬY���8�}�]���̎Y�l�ڵc�֭�nݚ�����K/ѰaCrrr��_غu+����?�0
����E��s�N@pp0M�6%99�)S��k�.����tPC�!$$OOO.\���;U�T���$�@�򎭤����9s���g�}�ȶ;t�3�<áC�رc��9�7�`���l߾OOO>���6m�ɓ'�:uj��t�ԉM�61r�H���1����x�b>���;�]J�y(�5j���Ɇ
�߿?7n��ή�����͍ٳg���裏Z:�|�ׯϯ����Çi߾��ܘ�n��������Ã��$���[V�X����8p�����bbb��_I,^����dZ�jERR����7��c�s>e9�N�:������A�:u̎���0��ʣ��P999<��a���H)���i�,�k�r��Miii8p�Z�j1i�$~��������_�b��'==///Sِ!CX�z5��ᦙ�E����LTT�g���r>����I�0f��H���²Ɯ2��FrXY����a����a���id
9D�Ԕlm�h6����}���."���q?�}}��s����^>��.\]]ٷo��$A�+VЮ];�ٳgp��)���J<�b��f͚�b�
ƌüy�7o�J�Ν;���RָqceB¹s�JL>���gƌ̚5K���W_%<<����}�ve›���1���4jԨ�5��_�}�vΜ9Sl]�
X�p��M���	4���cǎ%,,L�	����l޼�޽{�u�V���CBB���@___����/{����8::�

bܸq�\���P�۷'66Ve���B�?SU�[o�Evv6�'9!ij��ɉ��0����3g�2�@���k�0`���������L�f�믿044T�{��	cڴix{{ӬY3n޼Ɇ
X�~=����Z�
x��Caa!/^�aÆ:�v��	"""h׮�V���ˋ�7���H��5��bԴm������"##C-�"##CYG!�B!�O��>�BT���p
�%/y=������6"��D�G�fڴi��B�{{{eBFi��ϟ��ˋ7�|�=z0o�<�ܹ�V��ɓt�ޝ���+����l�2\\\�ܹ3���gŊ����X��{��t��www���[b\
�Z���ҹsg�u��G}Ķm�Tڔ�^�K'<Z�����}�bbbB�>}((( ::��Qʵطo�Ǐ���	�}�]-ZD^^�Vc���aӦMt�Ёz��)��ׯ���=�6m"''��8��'ggg��������CCCj֬IϞ=ٻw/��J�.h݇���o߾ԪU###^�u�̙Á�^��Z�֭[���BPP}����CCC�W����-���$%%�%[(��ߟ�'O���%XZZ2b����*lga�;Ɨ_~I˖-111���>��3���Ԓ'*26M��͛7����N�:*�u�qss�V�Zl߾��7ojԦk׮$''3b���Z�j�������T����=qqq���P�vm����ԩ?��#cǎ��j����?�Ghh(}��F��ꫯ�}��2}}}I�B<�F�IÆ
������<<<�|�2
6��ã\��[�nt��Y�{g;;;e�Q�FѸqcN�:���;�:u�w�ެ_���ի3i�$e�ڵk�v4�߿�Z���?Kz���!���055e���(�Ϝ9�ğ5Oq1jڶk׮������(+O�B!�B!�'��O�ҥK9r�He�!��ћo������CQI^�uf͚ŧ�~�L�X-�B<I���dggp��]�n�JAA�Z���ŋ���QN����g��񤥥)�\�r���RSS	�Z�Gk]���2f�.]�����o�1u��2�dݺu����'%%���rss6lX�m����q£ժ��G�d6m�Ď;3f�V;c�\����`����,6m�ĭ[����k:�={����G�.]��ҥ			�ݻ�A�i��bkk��}�$7n�ЩGGG�'�3v�X�'ܷlْ���k\���P��5k�����J�M��W�V-��HM�����ﲮ���
k׮U+W$�XZZ����NmǏ��--]�i�CY�*�x�ƍٽ{w��t�L	!�xrJ���ܜ��P���;bcc�v�u�ԡG��;��8p DFF������5����333BBBX�f
��իԨQ;;;Ə������)SX�|9YYY�.v�������of͚���VVVx{{3s�L�;w���).FM��ݛ%K�p��aF����Ç133�gϞ:�[!�B!������?~�-[��l'.�x>lٲEe�b!ċ�O>aɒ%������Vv8B!�ըQ#���x�W&$$��%\4i҄�����ذaiii�nݚ�S�ҴiS222�'!!���h�
����\�t	+++���+Z�hAJJ
���\�z�����X�l���ܿ�]�v��͛6l���ʕ:�N��&ƒ�	p��	._����-͚5M洵���ٳ$&&ҡC���ƍ�������鑒����'��j�qqq�h�B�/EY\\�$\!�(���)w����ٳ��Z�f
�۷ڡ	!�OT͚5���ۻ̺%%o�T��₋�K�絰�`���L�<��z�z��W�^�_��s��Pѯ_?���W�95OI1jҶF����Lff&
4 33���d<==��mK!�B!�O�$\�'��͍����C���V�B�LLL�eҤIL�2kk��I!�N�LPV�6,���iذ!��Y8$$�[�n��swwWIB������_�"f�&M�����c׮]�d�0m�4ڴi<Z��׷̝�LMM�}�6��ᤧ���䄫�+���e�M�K'@tt4��-�…پ}�V	�����3gΰ{�nΝ;lj'�}���c���߁G�3�kܸ�J!��$�:u"66�?��E�ѩS'�����?X�f
.`ܸq��B!���#G�s�N��ÕI0���XZZ���^��	!�B!�/I�B!��=z4.d��٬^����B!���M�*�������@��b��ŋJ\���ʯ322x�7T���ٕ�ĉ�5k�����dzr�J<<<pss�z�ꥶ�&F��Ǚ������������8p�۷ocffV�x���_&M�ę3gԎ*��t�ׯ_���\�|�2E!��$_�5=z� ))�=z����#  ''���B!^&&&����駟2|�p��BK�.-�B!�B!��x�*;!�B�l222b�̙���q�ܹ�G!�.11Q�UV9�N����/�܆��ʯ���J����E�_��;5�Ԧ��z����ݻ�1cm۶��ݻ�X�ggg�n�Zj[]b||�?��S���޽{���O��)j���9skkk��ݙ9s&���j�4��:V����.E�&�Z!ċ��Ύ��&N�H�-011����W_}�!C�p��Q����S!�/�������ŢE�X�h&L�h�!�B!�BT<��B�g����F��XT�}?�s?��?.22���x���J�B�<swwg������^��!���ӣ�����\����P^���ddd�c�,--K�kmmͅ���_�ر����_ը/\\\pqq!--�}���v�Z/^̠A�*$ƒDGG�t�R�t�v��ѣ����%::WWW�Ω��,$$�ڵk����<����J��שS���,����S��J_����:B!DY^}�U����CTA�o��_~᭷ު�P�B<'���pss��0�B!�B���p!�x!$%%��Δ)SX�l��ɕ�B<��Y�|9�����B�1��m۶q�����	��~�~�m�M��o���Ç�v��~�-����?^Y�gϞ̛7���T<x@JJ
���+��`oo��O^^͚5���(~w��/�cqΝ;Ǚ3gx���ܹs�u:w�L�F�HKK�zW�cǎ����o��������֭[Z��y��ddd���(S�B!��ǎ��ɉ����E!�B!�B!�d�!�Ok���i��Ν;L�>WWW劮��ח-[�`bb�T�B��b��B�prr"**�%K��d��bwf(�Q�F˩S�pwwW9V�zu&M��|?l�0~��'���OF��U?#G���ߟ����;;;�׵k���8KKKv�ءU��پ};C�Q&t<NOO�!C�0�|�����������v�bƌ̘1C�o��F�.]4{׮]9x� ���*����8::��B!ēұcG�U�Ʊc�x���+;!�B!�B!��.D������޾��UXhh(W�^eȐ!ʲ�C�r��UBCC+12!�B!��KL�4i���ԬY###�t�����+<333BBBpss���}}},,,prr",,LeG���pqq�V�Z`kk��ٳ022*���2c�^�u���022�iӦ�5�Y�f)�M�2�
���O~~��1>���޽���W�x��w177g���ܿ��k���ӫW/LLL022�U�V̛7�q���y�f��޻woLMM9|��Z_����L�ˈB!De�Y�&-Z� >>��CB!�B!�B���B<��AAAL�2[[[V�Z@^^��������?�P�n]���˘1cT&�(���ŋ���100�>`���dgg3�|:���!ݺu��ۛ5j(ϑ��CPP����ڵkԭ[��ݻ3n�8��̸x�"�
��ښ��(�q0�˗/����Ʊkkڴi�ٳ�ٳg���,�駟��w�Q�����b�
���}�6�7fĈ*�J��Ojz������� ���˕+W044�iӦ0���{���u�o�i�&/^̩S�066�w�a�ĉ�]+rrrشi:t�^�z������ޞM�61|�p���5��B!�B�g���	>>>�����?��LI	�����`���L�<�̸^z�%���\�@ݺuK�����R�߫W/z��s���khhȾ}�Jm�`bbJ<�������/�\��M�^�F
���&33�
���Irr2������j4!ijk˖-VvB�'d˖-����� 	B�
�e����	!*ϋ�<#�B!�/"I�υŋ�����0������IKKSֹr�
!!!���H�j��,X�@%b͚54hЀ-[�(�s��]v��I�j՘9s&�o�f��Ѥ��+�feeABB!!!4l�{{{N�8��S�hӦ���S���̤S�NX[[���|||HJJb�����Q�~}����^�zL�:��ׯ3r�H���_e����3c�>|H���u�_!00�u��)�߿���RRR���eذaŶ��Z?>A��ӓ��l��ۺu+L�6
�={����G�.]��ҥ			�ݻ�A��k�B!�BQ�nݺ�������z���̌���ϟ�o�Q�>�F��Ν;	������p,--qww���a۶ml۶���B�u�ܙ�7���OtB��q��}>���C!�B!����mV�OY�&M���c���lذ���4Z�nMDDǏ'22�v�ڑ��@tt��9RSSٸq#G�e�������֭[���S��y��!e�u�֑��N�
		�رccee���	PN�߹s�J��v����U���ю%���͙5k���̘1���fΜInn.~~~XXX�v�Z���_Z�lITT��� $$D�;S<Eb˲e�8v��R�,�y���iz��jԨQQQ���������j\\-Z�Pk�(S�B�aÆ���'/y�K^�+""����
!�P�&@����ر#�&11�ڵk��� �gbb������\�r�+W����իW����TXX(/y��yUe����믿Vv(B�*"<<�ҿo�K^�R	!�B!��Zd���M(�<11Q����;FFF�111���cee<J������c׮]j[��ЬY3���X�j���c�ԩ4j���Ç��1�7yڴiʝ+ڶm�ԩS��Oؿ?^^^899��K/Ô)S044����P�^=�u�s���Сnnn���3z�hRRR:t(;vT�9r���9
6T�O�+Dy���r��m���IOO���	WWWe�II4��j�� IDATEy{{+�0l�0BBB�u������E5n�X��B(^�a!��dUC!�=��]v����A~~>���
�;wf̘1�E��o�///-Z��	����䨄A�o�xqDFFVvOL�-�Y�&���o߾��BTK�.U��O����3B!�B�"���\PL�W�x�"...��?��ZY��͕_���*�nڴ��k�v�������E���\�|@hh(��{��=z���lƍ����α�jJY&L�����III�I�&��?�Q9����5�H'Nd֬Y����ʕ+����ͭ�UE5��E��<


�eׯ_��8E���B(<���WvB!��B�U����nnn�J�'�Y��i˖-�U���Z�j��?���ں�CBTǏg˖-�$�3�Ex�B!�B��$\��������%��(s�۷o��[�Z�j���$E'�+�����]�����ݻ�k�.�U���c�.�W4==�r�/,,T�#??_�x�^�ppp 66��۷�믿�b�
6l��	4h�V�w�

�_7.EYq�YQV��!�B!�B!����pI��
���`ذa��7gΜ�AQŸ��Ɏ�B<#^��!�B!�x�H…x.YZZ�����;���|�}YYY�����L�N�������X��upp ..���T:�[o�E�z��j�˗/��lْ��4�<y��+���_����)===
������(yG\\\pqq!--�}���v�Z/^\b…6�ZSu��!++���l�ԩ�r,;;[YG!J2l�0"""*;!�(�L@B!�B!�B!�B!��bI…x.���ۄ��1m�4���i֬7o�dÆ
�_�{{{V�ZU!}999���?s��Q&1̛7GGG���
��ѣ�5
WWק��'����]�v�Z�
///6n܈��#:t�k׮lڴ�E����O�Z�X�t)���X[[��?{�ڵks��u�m�ƠA��r�
j�@ff&>>>8;;ӬY3���/@uG��i{�5Ѽys������PK����P�B���
aB�g�|P�!!�B!�B!�B!�BQ�H…x.�5���XN�:����ʱ�ի3iҤ
�k�ȑ�߿��/���r�aÆje���ԫW��W�bmmMǎ+$v{{�R�LLL$''???LMM�={6���1t�PfΜ��͛177磏>"&&�S�N��煮g�ر%����DTTK�,aɒ%t��E��ȑ#�'  @-!��ή��k{�5ѵkW<Hjj�Zߩ���n�B���<xpe�!�B�0�l�Rj��B<I[�l����^����3�j����ҥK���{ԫW�]�v�|΅�������qss�O>)��I�����)�
�����8�6m��Q[��������� 	�B!�3�Y}FR8y�$۷o'99������B,--�ܹ3Æ
����-�4B!�B!D�$	����G<333BBBX�f
��իԨQ;;;Ə���M��gnnNhh(�}����\�v�:u�УGƎ����J�jժ��{������{j���3k�,�/����f�̙0w�\�ԩChh(���;v��w�bccèQ��ѣG��4iժU#&&�;w�`oo�����۷�J��b``@dd$���X[[����ȑ#K<���Z�{�fɒ%>|�#F�;|�0fff���S��
!�B!��m۶�m۶�C!�sD��F�V�T޷n�Z�s���r��I�������g�q��A�~��TD�III�y�f
�������]�v�B!*ʳ�����Νˎ;��\�x��/�}�v�͛��bl�=��3�B!�BQuI…x����:&O���ɓu:�6�5k����oo�R�R7n�ƍ+񸦱�gq�Ν�ܹs����G�~�Tʬ���תo|||���)3F\\\�:?h~�5�5j��͍��`233iР���$''��鉩�i�}	!�/���,�ׯ_�a!^@�����B��PI	���8u�+W��}��<x���v��R�Wd"���*+Ʋܹs��ӧ��ꊥ�%�h1___�lق��I��/�B����>#-Z��;v`ll���;={���ښ��Μ9Æ
8t�ӦM#**��u�VX��L#�B!�BTm�p!���F��Ν;	W&r���cii���{%G'�OΑ#GX�v-G�!##��R�^=:u��G}���WU)v���	�.\ 88�}��q��Yrrr077�Y�f��ٓѣGӤI�
��iY�z5���ܸqC�ؓ���z|�0}}}���iܸ1=z�`„	���k����c��k!DU��TvB@ddde� �`oo�VDPP��e�X�l�N	�I�������addTj��^hh(W�^eȐ!ʲ�C��q�FBCC�����B��C��T	���3�ٳgٺu+FFF|��wj�����agg�_|��}�غu+���ֿ<�!�B!�U�$\!�<������O>|8���,]���իWrtBQ�^�ʨQ�ؽ{�ڱK�.q��%�n݊��37n��¢�|~ݻwooo)((P9v��MN�8��'�?>�|�	�����ظ���Mi;u=�>|�͛7INN&99��˗�z�jI��9�e�\ɑ!^T��C�j���!((����s��5�֭K���7nfff�zE�9:t�<��XRyAAAAA�ݻ�+W�`hhHӦM0`��Jyyy�?��Cݺu�۷/cƌQNL,�Oy&HN�6�={�0{�l�����?��������;����xJ�Q�k���æM��С���S�ׯ_{{{6m�����177�z�B<fΜI�����)Z!���i�֭2t�P�d��<==166�E�ַ<�!�B!�U�$\!^�۷��ˋE�0a����*9*!��x��7]�t!==+++&O�L߾}y������?�`˖-,X��]�v�����?����<j�޽{��Ӈ��X

9r$C��7ޠv��ܺu��'O����oINNfϞ=�]�EI������ܸq������[v���#�]���n.���%��ͭ��B��"""6lXe�!4�H8{�,nnn4jԈ�[����ʨQ����%""BY���ی=���teYVV$$$����N��n�:���BJJ
�����T~~>�Ǐ'--MY�ʕ+������J`` ժU�)������Ă����~��dee@�z��:uj��S��{��!//�.]����K�.$$$�w�^
���x�9r��/J…��U�g$�sa�޽K��I�&̞=[���}�3�B!�BQ�U�_n�������_��_�СC+;!�x">��#���y뭷8}�4�}�-[����###�7o���/G��V�Z<x�U�VUv��
ooobcciԨǏ'$$�^�z���/c``�K/��;�Chh(Ǐ��ʊ�2y�����344�^�z��у��h���),,��ӓ{��UvxB!��	JMMP�f��{�u�֑��N�
		�رccee���	S�-��Dbb��}I�QQQ,[��cǎq��!|||ؼy��͆
HKK�u��DDDp��q"##i׮			DGG��OQ���%���͙5k���̘1���fΜInn.~~~%�x��x�{-����V�.Z��#DU���c�*;!���HW�\�q��Z���}�3�B!�BQ�I…B!D9ddd0n�86l���1���6Le5������|=.11������/cddDӦM������*�>��ݻy�嗉���V�Z%�ݺukX�z����~���#GҠA���hР�F��ܹs���ĉt��j׮���			Ŷ;w��Ǐ���cccjժE���5k7o�,�����F��w��111aϞ=������}���ܹCCCV�Z���r�����qm?w�^��,�sYR\O�3��y��aggGff&��}�}+ܽ{�o���nݺQ�N�[�.���#66V�u�����1t�P�ի���vvv�ر�Ę�B!�#��V�Z�^�L�6�6m�`hhH۶m��<�߿_��>���ɍ7puu%11Q9I &&lmm��קI�&����k�.�c(I�pss��ɓ�=�_~��!C�бc�r��<m?#5j�H��ɒ��%DU���ٳg�~�ze�"���JJ�,��*<#����T�۷<�!�B!�U�Ae �B�:|�0�.�n�R�)�Z���b�֭8;;kuN��k׮e���<|�PY������ٻw/��F�����Ə�K/�Tf_�F��U�Vj�lv�����s玲���ˬ]����m۶��;�{��Ǐ����ݻw�G��w���={����s��ʺ'N��G����(����9y�$'O�$,,���x^y�
��q�޿��`


���y���Ѯ];<<<���X�f
.Ԩ]Eƭ�u����h�Z�jxyy1f����6lX�usrrprr��ɓ*�׮]c׮]�޽���h�}�]����z���0`��6III0�u��iԯ��PL�(n5����;��C��m�6RSS�u��������7�,����<�B�������&A~�O�_!�n�N�X�`,P��3gs��}����m۶*��ԗ/_�9��'2k�,��㉏�g�ʕxxx���F��Օ�.^����K��9���}j�q„	?~����4i���R�k:��UL2777W;��L&��������B�?N߾}+;!��*<#իW�˗/��_ѤI�b,o��L#�B!�BT}�ÅB!��_����+999L�4�s��q���;Ƙ1c������M���Baa�����_y|͚5ʯ���<==y��!�Ǐ�?� ??�C�accCRR���W�?r�����h��Ƽ��)˲��2dw��a�����r��=RSS0`���|�dee{N���ˑ#G���%66��M�����W_}�RwҤI���0v�XΝ;G~~>yyy8p��-[��2k֬
��(]�߾}�8p�F�WaȐ!@�V�+O��\g�gR���$O�3�-����)�ɓ'iժG�!//��w�O�Ν),,d�ܹ����y�&nnn�6�O��޽{�<y��ݻ����~�/��>�����w�_|��'O�СC\�~�p��
:�ĉ���/���׹�'�&������?gʔ),[�����J�G��(VD.�^�z�{�nf̘A۶m�{�.+V���ٙ�[�*�l
��dXY4Oy�*V��VM���2��MTe/��2666�dO!��H���*��ʋ�<=#�o����Y�XYc.o��L#�B!�BT}�p!��������%/y=g������!�3����իL�:�ŋcccC���qpp`���|��dgg�|��R�ό3����qssS[�j�����?d�ʕ4n�CCCٸq#�ׯW�����E�:�kٲeܾ}���~���(Z�j����Z�"**���~�7nXl�nݺE׮]155孷�b���=zT��/��<Z����CCCLLLprr"22��۷WXlE�r�۾�j�J�+����Y��"��:k�i~f�emm
��
_xx8�֭�k׮���`llL�N���K�:uJ�>u��W�����{��DEEѲeK���x�7�駟hݺ�.�B<�4��R��>�h�;w.�����̌�'����ٻw/�g���ʊ���r%����B[w��a��鸺�bii������We�!!ij%11��� Z�nMbb"˖-���Nmb����Z2�⽥�e�Ɒ���Ņ��`֭[�ȑ#�u��/V�Q�c������$$$�+��,_�����ӲeK���5��I��m�:u���Vk�(S���rpp�رc���W����[��ӧO�X����-�4B!�B!D�gP�����/�^e�!��QÆ
+;!�i;w��O>)���1c��oػwo����:t(<�w��̛7O�b5.///�����jRL433�n0E������"W�j��/8p��w�.v\&LP+�ر#�n�R)����ܹs8;;3a��u릜 ߪU+��7��t����,,,J=���sss�jW]��:k�i~f�U�zu�Ѫ���?K<��k�h<�V��c�����6L�:���Eboo�T&�蒓�ٵk���иqc屗^z	ggg2d�v���Օ6m�T^�:

��իʝ���ƍ	

-�yL�lHMMP&�>��('''����gΜ9�lْ��4��b���:�1`�233����ٙf͚��_`hh�����oƴi��Y�fܼy�
6�~�z���Y�j�h%���B.^�X��Ӝ8q���ڵkǪU����b�ƍ8::ҡC�r���5mۼys������P���XP�y��:�[�灃�ӦM����ؕх�i�
�H������+��=cǎeȐ!���[�����L�����UX��L#�B!�BT}�p!�B����4��սΝ;W�q����bcc�ƍ���W9��A�CBY,,,�y�&999ԬYS�6%ū��8EyI�5��ب�ըQP߂~�ԩ|��G;vL�����5=z������UXlE�r�������&;;[��rrr055ոMIt�[�묭���і"�E�$���tN�>MBBǏW��ib�.�C1)���n�;w�,x!�RI���+�oڴ�ŋs��)���y�w�8q"&&&*�����2e
�����yyy�?��Cݺu�۷/cƌQ�����t�R�9;whڴ)#F�`�ԩ�ƥx_PP@PP{���ʕ+ҴiS�\�@Ѧ����X�8RF���lQ�K/����;K�.�~P&\(�G@@111��o�����u�q�2''��� ���ϵkר[�.ݻwgܸq*����ߜ�6m�D��W���}������gӦM>ss�b�.��\�$\�9����s��E<<<T�5l�P�L#G���ߟ��T����)�5j����:u
www�zիWgҤI��k���8KKKe��B���ILL$''???LMM�={6���1t�PfΜ��͛�����x��QӶ]�v���������cy&x
�<puu�cǎ*��i�*�H��9l޼�u��)w�}���5>>>ַ<�!�B!�U�$\�'f�ҥDDDTvB���^�a���t��Y����H���پ};�k�V���QA�+lllHLL��~�S�N�y���{$T$������S�n
�41j�(j֬�W_}�ɓ'�믿#,,��M��w�^�4iR!�������ĉ������Q{����;%��.qk{���4?3��?hРA�u7o��ԩSIOO/W��\�*)1�V�Z�IQ6OOO����{�.[�n����iӦ��[�x1999�I�����?^�p��BBBHMM%00P�Rqnn.cƌ�ҥKʺ����2٢4���*E�߿OJJ
)))���2lذ�jcI��_�֭[�q���,]����$�c���WN��{�.�v�"99�
6h�w��mF���:++���		QKr,��ٳ���<�t��_�.]HHH`�޽4H�8�O��	�O�Vy_���9���|��w���r��5�ԩC�=;v�ֻ�5p�@���T~������ё�#G*뙙�š5k8p�W�^�F����1~�x���)S��|�r�������)������of͚���VVVx{{3s�L�;w���).FM��ݛ%K�p��aF����Ç133�gϞ:�[���+���+��R�a!^��YU���2e
...���$&&r��e�߿Oݺuiٲ%�z��G�*���oy�B!�B!�>I�O�L��Tڄ-!�#5j��֭[ܼyS��$Μ9ç�~���6l�e˖%������۷5���ё��D��٣Q��ٳg�С���gÆ
��?�ݼy���� IDATl^z�%�67o�T�V��}��}.^�Ⱦ}�8r�G���ٳ\�p��']��r�z��ɉ'����J����(v'<�9��,�޽[aq�v�Y[O�3����X���&"""�������<�ƍS�n]Z�h�����}�r=mn޼Y��)�I�B�'�Q�F�����+�LHHPK�hҤ	!!!�]!6l�@ZZ�[�f�ԩ4mڔ�����IHH ::Z�Exx8�.]��ʊ����-Z������/W�^-5���(�-[���=���g׮]�y�f�
V�n��X�8������^}�U�b�s���.]J�8s����\�|�
6���Ub��[�n���4hЀ9s�ТE��Ҙ>}:�ϟ',,///�6e�߸�8Z�h�֟�,..N.�xF�ڵK��?�\j��5k��퍷�w��.�QI�...����y^&O���ɓK�׫W/z��q�ř;wn�	����_�~��S���&mkԨ������dff*�333INN��ӳBv
B!D٪�3����-_|�E��UT��L#�B!�BT}�ʮ"�B!�X���ѣZ��{�.C�!//�Y�f�����M��[��,C�`�ʕ�U�K��?p��-���>�ms��q�z�aÆ|��G��+W�VL����t�cƌ����5k�{Orss����O>��ݻիW0t�P����������u�…
��(M���*�3S��@���K�����j�*Μ9��ٳ�����Ee�����2���z(V_��_�m�̈́:!�2{{{�WY���aÆ+���U���]�����?������ӤI����I�`ڴi�i�CCC����-3>�Č��p"##�q����$&&��0�M�%�S�jg�]��SXX��ߢ|||�ҥ����i�F�져.�*�:�m�V�S����ڔu�n7j�H�m�ƍU�!��X#G��~��*�����cii���{%F&�B�9y�B!�B!�6I�B!��A�>}�G�<x�v<22===���UʧL�©S�8p`�,�~�m���Վ���������V��ٳ'YYY|���N�W�t��-�Z�jL�2EY޻wo,X�6�����E�УG�Rc�D�ƍ�������jNJ�
�"c����kL�2�{������ɓ'Uڜ:u��7o�|�rZ�jń	�۷/����wޡ[�n*�k׮
?1?$$����:�$M��gF����>}�}��R�?��Ç�[�x���;w�ٯ.����믿V��\XX�l#�xr�&AYXX�,��.�ŋ�G�uM�P��������o��r;;�2�8q"��������7���R�H��X�8�ի��+WJ�+33S�~Q*�۵k<z&ц���m۪�+���˗�ڔu�_�<�q�q�2E!����???����r�
W�\!::???�W�^��	!�BhD�i�B!�B��M.��Qq�[>�����=]�t����b'~T�YM��=�X"##��GFF>�~����ˋ�5kG�>}HHH��ݻ8pOOO��������6���,_��6mڰn�:��%����cllLhh(S�N��&//����+w�5j�J��� �֭��ݻiݺ5˗/'==�p��RSSY�p!���������LX���177�8���4���IKKc����bjj�'�|R�k���a����Đ��˃HMM���
�_�AEǦ��ꫯx����믿ppp`������\�v�:���¸q�x��!+V��ҥKԮ]���P��|�MƍǑ#G�{�..\`��ɬX�����:�]���x��re��<��Li<x��+Wرc�{�&  CCC����\��aÆ���������r��iF����p�ڵ2���z�;�
�w�^̙3g��>iii4�cǎ�xU��ZU^e���N�}/344T~]ڿ�Ew}x��Ź}��Z��m�z�ի�w�fƌ�mۖ�w�b�
���ٺuk�mu���q*����W��O*��1	��ʫ�$����Xe��'!��i߾=^^^,Z��E�1a���B!�%�L#�B!�BT]��<B��>��j�y������˗���⧟~"00�6m�<�(�Ӑ��D`` �7o����?�[[[�j�B���A�DDD���ʾ}��ԩ�Z�+V�|?�={6�h'ń��(&F6k֌+V0f��͛Ǽy�T�u����ƍ+'z�;w��I��̘1�Y�f����꫄��3x�`�o����U�N�F�J�_S_~�%۷o�̙3���K�x�
X�p��M����ۖ-[�ꫯ�7o!!!%�F�p��
V�X��9s���W�����g�Ο?����J��� ƍW!qk{���ccc<x����	�O�3STY_���X�~���"��fܸq�\���+W��>}:�6m�ܹs�8qB��Q]����9�7o�w��lݺUm�tHH*�!D����(,,$77W�onq;9����%�رKK�R�Z[[s��~��W:v�,���_5����\\\HKKc߾}�]��ŋ3hР
��$�
b׮]�����舍��Z��gϲn�:��E�:uJ%1>))	x���6������?INNV�w099@�1֩S���,����S��ʱ��le!�O����2!\!��y%�4B!�B!D�$;\����z���qqqlذ����/�s��S���T�ʶO;w�>}:���XZZbee���{,���ٙ��d<<<�����А�5kҳgO������R�…Z������۷/�j���Ȉ�_�9s�p�b�#oݺ5)))ѧO,--144�z��������IRR�Z��B���9y�$���XZZb``���%#F� ))��I������رc|�嗴l������>#))Im�~EƦ�S���g�̙���|��W8::R�N�^�:�5�_�~,Z���3gbll̼y�;Z(�������k���ȈN�:��?2v��
�[��J�>}�Q�����޽�U]�*���y-�V�4j��P;��!3O�ݦf܎�a%�)��:~Ԁ�L�a�ϙå���\NРHJC (����{�7'7��q]\���>k�?�|��kUy/��g�*-Z��cǎxxxLzz��Κ5��;w2`�Z�l���O?�4������o�͊+غu�E���~:���d�M�f:���g߾}�m,�"Ү];8���׹p������ψ#

���֭[\�z�?����ܹsMu�y�֬YCjj*7o��ܹs�*+2f������GyWWW���233kce����/�@aa!3g�$&&�˗/s��M������b֬Y\�~�g�}���իW����ٳ�ݘF�]e�eyzzBJJ
7o�$%%�t�&1Z��G ##��1c������HC���_������������T@;\��W��䭡e˖<��c|���s��!&M�d�Ф�"##���1M��2e
�~�)���̛7ϊщ��������-����?ת��Ç�x�`˖-�5kV���ҧO>����W��Au�۶mKHH�i��ݎ�&�~e���DPPP��^y�֮]KZZZ�cnnn�v@0�ϸkz��w�Ο���u�>3՝W۾�M�ƴi�*�?u�T�N�Z�Xjz?z���Ν;˕��j�2����ӓ����a�6l����G��3}�t�;FJJ
���f�Z�jŢE�L�����?�����k�O@@!!!����Kqss3�n׮���������¡C�jcU������_��_�BXXaaa��1”�VV����]w�>}x�嗫������9Bff&3f�0;֭[�re�:t(Ǐ'55��~����K���Ν;Y�d	999���(""""""""""w�v��F�`0`08s�#G�4[y����M�6���͐!Cx饗ؼy3EEEfm����u�V|||2dO>�$���
(ן%mD�������%'N��q�w��믿�j�*�
�ȑ#Y�r%W�\����nzz:���cذa�5�5k֔۩��ի���ی5
�/_Naaa����_�|���z���~www&O�L\\\���&K?/����޽�A����l*�ܹ3��ݻw���_�}����?�G}�ѣG��4R4k֌�����������fX"�^U;�-Z��	&жm[������4�.������lllprr��ӓ;v��`oo϶m����E������o`ggWi?>>>�\���{;;;����ٳ'ӧO7۱jɒ%t����:5��*vvv�������y�h޼9�ڵ��'�$,,�����-[Vx~XXÆ
�E�8;;3m�4�n�jv��_V�6m���dҤI8;;ccc���3S�Laǎ899Yt=w=z4�<y�ܱ�'O���hڡDDDD�!��ݛ+W���[;)C;\H�F~~�ib{QQs��5[)�ҥKDDD���Jxx8͛��'
g׮]�z��Ŝ;w�s��q��5���j�fm
0�l2]m�}�L+}޸q���8������2M.�M�s��!//���g�}FII�i��|f̘AVV��?���\�v�ܵ6D�����%�����r�Jnݺ�K/�T�]o��˗_~Iaaa���zxx����W_}���+�IDDD�h��;v��_~�u��1x�`Z�l�?��O>��c��}fϞm�HE�{{{�.]�ҥK���&hT��ai='''/^��ŋ���}���\�Ҭ�ҥKt�ر������}///���j�%;O>��<����+�m۶��F*SQ��Զm[	��=K�}[�n���/۷o'++��]����Err2s�����ʾD�����3�nFD�^2`�Z�j��ӧ-N�1���!&&��a��������ܳ�p!MB�=���0�|EZZ}��eٲe��ٓ��BBBHLL���;�����i�&������ʞ={L���ͤ�$��	�LF�S�������m*�ɵ}���lܸ�A�����˗s��E����7o^��}��	�S�Nl߾����=jJx��O���⡇��w���Օs�Ε�0�P��ܹ�+W�ЧO�}�]:v��|��NDDD�	
�y9u�p{屲�e�N�R…���Tk����5��g�2jԨrǛ5kFhh(���w?8�7O>�$���,]�///������'��r��������?mJ䈎����+G'"����AD��������FBB�i�lK,X�����DDDDDDDD�~�m�~�Z0f_Օ�����-���		���z��App0qqq���U(��������f„	$%%q��Z�Y[�n��E���:զߥK���ၭ�-���3%$=z�N�ҭ[7Z�liJ,��_LǏ;��e�x��DZ����͍�����j�����k�|�M�u놃�AAA$%%�矗k�6�X�y9�<p;I���ݻ�������Νc�…���{{{Z�h��>��ɓ��o����k�)"u����ȑ#��o�ĉIJJ�]�v�������	��\�t�K�.q��A���iժ��������;			�CDDDDDDDDDD���$'�eff���]a���t���j�*HHH`˖-̘1___�I5i���\�@�v��ԯ�������N��������	���S���~����W�J�
�ŋj��zC|^rsshӦM���e�:""""�y������4 c�����'���RTTD�N�2d3g������!�ȼy�X�n��������Q��ѤI�����%�����*�‡~HAA����GD���7c�0D���u<#"""""r�R…�uIIIfY�-�ӝ�[@���(((0������ݝcǎ��_��߲y�f����?>�Ǐ�q��u��{�1SYm��s��ORB��ٴ�6���ښ^7k֬�qc�e�.OC�_Q�%��b���{nd,�m�"""""r�i޼9������Z;����������H�)����Q�{XLL�i����;�n�"11��#GZ;iB|}}����v"��3""""""�*%\H����BFF���ť�NNNx{{���MZZ�f�Ν����&�״͚*..6�0���Y�kHII1%��={������S��y衇�p�gΜ����T���Z�nC�ߩS'~��G����ӧ���5��C�dgg���G������3��΃>H�����ɱv(""""""""""r��K��4#F� ((���[�nq��U>��Cs��5�3f��}��QXX�#�<���+`��BM�4�\���Ym����+���,\�������k׮�=�V��^����Tn޼�ٳg			�s��y��g		�̙3ܼy�����^��\݆��С�[����lnܸ�ڵk1�7������裏���Q�?c�������������Hu����<y����;h�i��O�αc�HII�����X�V�X�h��}@@!!!���jV��ͭVm�k׎��\|||pqq�СCf���}�NNNN���{f�kүQ���>}�YY�>}x����nu���9|�0�ϟg��٦�ѣG�K<h��_y����III��_4;6k֬J�k���СC9~�8���f��?�^������+]�#66�����ݙ4i��MDDD�����})..��ח�^{���P�x��ŋDEE���@vv6���<��<��SL�<''�z�4F��)�B�.))���8::���ѣG��ɡu�ָ��1w�\z��e����C�-����…<��C>����Z��d�>��#���)**�2V;;;\\\2dS�N�S�N�����0�z�-h߾=�>�,3g���ήN�V��Ύm۶�i�&>̵k�xꩧ

��/���uU�C�DFF��ӧ�q��z�b���5�����2z�h6l�ɓ'�6m�Y'O���ёg�y���("�SLL111�CDD���營�������x�
�?^��LϞ=Kxx8{�존���_~WWW`�HEDD�~�|�rΜ9cz�ʕ*��[e���Y�fq��5SYQQ�ϟ��:t��۷���\o}��h"""""""�%\H�VU2����/f���ն��퍷�w��,m���//��[��mۖ
6�[���]Qy�֭Y�t)K�.��nC�ߥKBBBj�^}^Z�n���/۷o'++��]����Err2s�����ھD��[�`cǎ�v""�<x��C�����ADD�j�?^a����Y�b&L�����p����ٻw/���w3L������e��͛7�,�o���֯_ϵk�<x0���:=z���͛���`���|��w�����o�[�����������[;��*  �Ν;m*������+F&"""""""r2k�Q�"##���a��ɦ�)S����Cdd�#���>�H�D
��@��ͱ�����n1&|�^�WWWZ�hA�V�x�'L��}���ڧ�h"""""""��p!"RK�����3u�T<�ƍiժ������q�Fbbb���H�����v"u6i�$k� "@ii��C�p��e6o�̩S�(((�{��L�6��ެ^~~>۶m�ȑ#\�z��;2r�HfϞ������q�b�W˖��޽���0RRRhٲ%O?�4.����l�����{�n
�����N�Ν1�޽��S�ҦM���M"""r����`РA���Je�%%%l۶�����K�.akkKϞ=3fL���پ};�����Ot�ؑ�{��3g��7*/�oߞ˗/s��x����u�Vn�V�>5F�(�BD�ȼy�X�n��������Q�H}�5��FD��i֬��C�WJ k��������aH���%  �+W������Y�r%�n�⥗^����W_}�.��eggCbb'�� IDAT"888�*�9s搗���7���())!((��s���K
���(w��Ã��D���+Ə_��DDD�֐c���pv��ez_\\̹s�8w�׮]3������;w.iii���.]"""���T���i޼y�}͜9�իW3{�lƍǰa��۷/���֯k����������?�����4*III��"�������Y�~=S�L�v8""""""""R��;wr��������9q��ƍ ""�To׮]\�p��]���ӧپ};]�t!==�;v�:��~����s��)f̘�ѣG�]2�=�S��ݻw���e�:"������[;�O�d�S�x����i�&N�>͉'X�t){��1�EZZ}��%&&��������2`�9x�`���7������عs'�f�⩧��w������]w]��MDDDDDD��i���WU�_�5o��&ݺu����� �������M� ����ׯ�����ߟe˖p�ȑZ�H�n�hٲ�iE�_~���sΟ?�N�(�{��fuD��k֬,`߾}�ED�����r�c�#::���X~��g&L�@RR�)� >>���\]]����G�gQ^^^8p�O>���^{
��@jj*k׮��ח�~����MDDDDDD��������4e999<���<���/�_��cǎ�����?��Ο?ϣ�>����%!!www&M�t7C���8���Z���`�ԲeK~�a���x�4���笈4F/^��瓬�,���oV��O��S={�4�vrr�����srsshӦM�c�2c�7�����R""
�!�>.dժU$$$�����-[�1c����j��T/33oo�
�IOO�Q��{��w��L�>���"v���m�x���Y�vm��1��������C	""""u���
��?n��o߾V��1y�78~��U&�V�ٳg	gϞ=������/���ʀ�z�"""���_����y뭷ptt䩧��vHU�sVD�̚5kV���J�(--5�_TTTi=[[��c�׼y�
��eu�6i\�Bhh����&�&c��T�j	///���9v�_|��~�-�7o&**����3~�x�X�*U>|8ׯ_'..ggg�cvvv�m�6�d����1��������C	Ҡbbb(..�v"RC{�������a�4	�%\���?��~�:+V�`„	����������ٻw/���w3L�r�N����eÆ
�����'�4�=gE�1�ԩ?��#�����ӧ�z]�t�~ 99����ʓ��L���$���R�]����#P���ӡC�����ˣC�f����LuD������O?�Dzz:�z��v8"r���ا6������ۛ��4>�Ν;	3%\��������C�j�_�޽9s��}���������̓#�ڧ�h"""""""����-�ԓ��3q�Dk�!"�0q�D�_���9��`�ڵk۶m�`0�{�n6m�dZ5L���Hrrr�<y��lʔ)���i��DDD*־}{�,Y�?��+GS5=gE�1:t(�֭#;;�7n�v�Z�ƍ3���� $$���n޼IJJ
k֬n��lԮ];8���׹p�B�V�7�����i*{��G��L����XGD�
nnn��ٙ��."�Pj2���1c�`0طo���<��#����;�1��� ���;nݺ�իW���1̝;�T���Ҕ)S�����'==���"


8q�o���Y?�ѧ�h"""""""��p!
f��,X���a�����._���͛9u�t�ޝiӦ��ϛ����g۶m9r��W�ұcGF���ٳM�����߽{7aaa���вeK�~�i.\hZ�����m۶��W_q��%lmm�ٳ'cƌa�رfm�:))��z۶m,Y�WWW�n�Z��Wwݕ������ݻ4h����;w6%�L�:�6m���BDD����!@aa!���;v�V�Z���2�|Z�liVg��������O?ѱcG�{�9fΜ���]���ӆ
8x� ���,\���k�y�&�IF5y~�e�uZ����F�W^!>>���^|�E�c�f�2��ȑ#dff2c��zݺu3+���d���lذ�
6���Q�۵kGnn.>>>���p��!�����IMM���ͬ�q�źL��ƧU�V��ߟ����������j2��M�!!!����KJ�s\3}�t�;FJJJ��{�Z�bѢE����F��ԩS��Oسg{��)��?l����1��������C;\H����Y�f�җ��藟������4ZIII$%%�CMRR;v�����T�!������G���s��M���Y�r%�2�+((��W_��O?����ܼy���lbbb�9s&����ڞ3g���ܸq���<>��3���L��������̤�����BΝ;ǻ�Ktt�E񇅅���o6!�>��"_~�%���N���𠰰�����F񈈈u��t�R���(,,$77���>��C��"�Ν�Ν;�x�"���\�t���.\HIII��6�����⡇b���U^_ii)W�^eݺu<���5�E��uZ���sVD��~�С���xyyѦMlmm�ݻ7��Y�\�6m���dҤI8;;ccc���3S�Laǎ899��.Z��	&жm[������`Ŋ��ɒ%t�����=z4�<y�\��'O����3�<S�>E�q��o�.D��T5F��ا�|||X�r%�=�vvv���ѳgO�O�ΪU�L�������lllprr��ӓ;v��Q�x	��_'<<OOO~��мys���puu�w���|�iw���Sc4���v��ekkk�Ki<�l!b�*U}����}C۹s'W�\�O�>���t�ؑ>���?����^z�%v��Ņ�ڵ+���{�&--�+V���Ύ;�7o�Y�?�0���t�ԉ�۷�ѣG	

`���lڴ	��@qq1qqq����g�����v���y=z� ""��J�qݕ�}��)z��]�]c٩S�?~|�b��yh���?���}��w���ѣEZZ}��eٲe��ٓ��BBBHLL���]j�7�N8����G�lڴ	�ru�ܩ�N666f+��EM�Ӓ�>�9+"MC�.]		��^۶m	4=*coo�ҥKY�t�Yyٟ�*��X����///��֭[��������ʢk׮dee���̜9s*|��H�6y��zK����c�|\c��퍷�w��:99�x�b/^\e���KF���W�W}�1��������C	Ҡ&N��ĉ����Ё��H�`L�0������_��oҭ[7���LIFG�5�ׯ���gٲe���k9r�\�E``��M???"""��_L�((( ::�.���Ʉ	�0a����8�,�?��PRV����ꈈH�P�����{z����Y�ؽ{7W�^5��� $$�.]������;v,qqq�D���mL�prr⣏>�x�P���ǜ9s*Mƨ��\���}=gED�qG���h�D���h\\\�rt"��
ưaì���TAc4���.DDDDj��Dǵkײv�Z�w�y�w�y�|U��p��E���+����N���O<a�Νz��izm�ZRRb*[�p!�V�"!!����l�Œ3�U�V�o�xYS�^wErsshӦM�c�2ci<*J20>ck�\�ի��u۶m�g\ff&@��o����^״�����o~Sa=���/��w�###��{�ޒ-�f�i�s_�Y��cooOpp0���:S�N��lܸ��DDDD�~i�&""""""rP…H-�?�ܤK'�4��[c�
5���ۯ���X���O�4�����=͚5��wN.-��ֶ�~���pww�رc|��|��l޼���(�ϟ�����-JKKM}�;^��6�ۼy�rnjeu��""rw��vu�+���Vy�����}�����~nܸ�֭[	�����+V�   �5k�Ю];F�Qi�U=?+�_�;���羞�""
k�̛7�u��0�|��ܬ�����Mc4�{�.Dj�7����.��~s��Y���ٳg������˸��2`�k�&"����$Μ9��ٳ�۷/;v�������7nnnl۶��ѩS'~��G����ӧO���t��?�@rr2�6�'''���R��������ۛ��4>�Ν;	�(᢬f͚QZZʵk�ptt�W�6��+ҡC�����ˣC�f����LuDD�q��g��<*���BFF���YӾ/^Lǎٸq#'N� --���{�1�N�ʎ;		a��ݧ���g]�,{��9+"��|}}�v""""r��DDDDDDD�m��j?~���IIIU~5E�-��ׯ�b�
&L����]�t��LJ�˗s��uk�'"����T���[�a�С�[����lnܸ�ڵk1�7�T������RRR�y�&)))�Y���Ç׸�1c�`0طo���<��#�����Ym��ڵ�\�~�.Z�뮨o��T��5���JDD7K��2� �w�}ǭ[��z�*~�!���s�֩o???z����-[,���W_�k׮�����;-}~��:-}��9+""""""""""""""�%\����Ð&&22���&O�l*�2e
999DFFZ12�_4���W^y�:���‹/�ȰaÈ��`֬Y�zt�֍��,f̘���;3f���ŋt�֍3fԸBCCy��'2dAAAfۥ'������K/U٦11dÆ
>�I�&���+��81��u'cYmPDD�z,}.Xj���t�ޝ�����<x0�G��O>�U�V,Z��N}��ذl�2�5k��ӧ���o����ޞ��z�f͚�w�^�����Y����uZ���sVDDDDDDDDDDDDDD�5J��F͘�q��F�i��faa!�6m��ۛ!C���K/�y�f�����())a�֭���0d��|�I^y�8P�?Kڼ39�.�"AAA�������?c0X�t�����˼��[<��Ӹ��3y��r�UYle�-�?�������y�pww��_$,,����
�MOOg޼y6�Q�F�f���(,�%??�ݻw3h� ���M�;w�`0�{�n���?""uU6��������C�DFF���E�6m����w�޼��{<���zmڴ!22�I�&��쌍�
���L�2�;v���T�}||X�r%�=�vvv���ѳgO�O�ΪU�L��,YB׮]���)��.kѢEL�0��m�bgg���+V���uW��ѣqpp��ɓ��=y�$���<��35�""b=�>,���HDD������`cc�������ر�l���ݯ_?���r���ƤI��u��ׯ7�[����uZ���sVDDDDDDDDDDDDDD�5-���%������7M�/**b�ܹ�����\�t���RSS	�y��D����ڵ�T����s��q��9�]����_�۬K�.��ٳ�]�777:w�Lvv6���8;;�l�2rss	�ʕ+�s���Y�r%�nݪv���Xz�*((��W_�…����lbbbHLL$""�s�̙C^^7n���>���Ĵ2���|�����Q..�ꫯ?~|-H��&���/�J]�t!$$��zm۶%00����*�%%%Y\��퍷�w��yyy���eQ���,]��,鰲��\wE}�n�___�o�NVV]�v ++���d�̙S�%""��%υ�<㜜�X�x1�/n���-[f������|�M�|�M�2K��u�NK��zΊHC���p�7�ݻ��!4J�~�)�ӟ�~w."r����������񌈈���ȽJ;\H�УGN�:��o�
@TTiii��ۗ����׿ˀHLL���s�����M�8}�4'N�0MDٳg����m�9I%))��I+�*�2jӦ
�V��ڵk�\�����z�-�]�Fpp�i��;wr��������9q�i%Ԉ��:�[K�OY�v��…t�ڕ��N�>����ҥ����ر��9?�0����ԩS̘1��G��8�S�Nлw�r}ˌuDDD�
�s��DGG�ʢ��qqq���ߊ����4}zΊHC�8q"'N�v"Ҁ�b�n�bϞ=ܸq�ڡ�H#4x�`}�iD4��7i����L:����D���L����		�K�.����`ƎK\\cǎ����������p����L�0�	&��W�6�ˠA��%::�W_}�s��1e�~��ߚ�|����L�u�@PP�iW����eL�

�_�~��ߟe˖��k�q���͛gvN``���������_~�q,�ϟn'p�ս{w�:""�V�s���[[*gooOpp0���:S�N��lܸ�V�ZY9:��M�Yi(����AD�*���)**�̙3�,"���`�k�!"""""""rOS…4	�I�F���x{{WX?==��z�…�Z����زe3f����l�GMڬNM&�Ο?������;w�=z����f�/^����>jq�5a�)+++��dq�'�x�,�;�����ڸ�GIII�c���n�R���XGDD�"d޼y�[���<vss�rT"""�=gE�!4k���!��]RZZj��^�z�����%\�H9~~~���X;)C��{�.�+��`\���$�;w���AQPP`z��养�;ǎ�/���o�e���DEE1�|Ə_�6了�1�����FQQQ���Kݙ@Q�����uE�ei,�s�7o^�
c��/"��v�h�|}}�v"""�$=gE�!�;V�[D�a1118p��a4J���>}��a�H#ekkKtt���4��W)�B�$2228t�...��wrr���ooo���8|�0;w�$,,�4���m֗�>����t���CZZ���,^��t�S�N��㏦:�j֬���\�v
GGG��]:,�?eu�҅~����dl*ONN��=�$�:���M^^:t0;?//�TGDDDDDDDD�'Nd�ĉ�CDHqq�&(V��ݝ-[�X;i�4Fi<4��7�_^�	1bAAA|��wܺu��W���b0�;w���1c0�۷���By�\]]�jҦq�����:]���7bbb0`����駟��Tg�С�[����lnܸ�ڵk1�7�Ҷ۵k���~�:.\ 44�\=K�OY����������͛7IIIa͚5>�f7��<��ddd�k�Xf�#""""""""""Ҕ��������_�EDDDDDDDDD侣.�I�>}:ǎ#%%�c�Z�bѢE�����Z.��ͭVm�k׎��\|||pqq�СCf�
C��'%%���Opp0���۴hт��`�L��[o�Ş={hӦ
���
��񤤤��/��3k֬J����d���lذ�
6���Q�������9Bff&3f�0;֭[�re��4��C�r��qRSS�Ř��
�.�CDDDDDDDD��9�|�����ƒ��ܞ�=iҤ���ԓ�������׿��|����}.''������D������^���!���6���T�9�Թ�4�i:�p!VW�_j9::���ѣG��ɡu�ָ��1w�\z��e����C�-����…<��C>����Z��d�>��#���)**��u���r��eV�ZE�.]�ҥ������[����z�j:t�@dd$���>}�7nЫW/�O�ΨQ�*mѢE4oޜ��x�_���``Ŋ<��sf�,�?e�iӆ��H��?p��1�^�J�5j�f���ɩ���XF�͆
8y�$ӦM3k��ɓ8::��3�Ը�����P\\l�0DDD�~~~8p��a��}j�޽�A�bo��Ǐ��w�gϞ%<<�={�PZZ��/����+�B�"R���|��������Ca���9s��ʕ+U�׷��?M��p"""""""M�.�Q��eNNN,^��ŋWێ��7�ݚ�� IDAT���ֳ�M///���joY�W�f�����_x�^x���.]�Re{e����g�ҥ,]���-�?�׶m[	��u��u�����}�v����ڵ+YYY$''3g��lCD�R�V���4z'N�[�n�C�^L�8��!��}N߇�)9~�x��ׯ_gŊL�0�b'˗/g�޽�����0E������!�������-[8p 7oެ���U6�iJ4�iZ�p!"MR@@�����6%|DGG��₿�����{ɂX�`����o���Z;i�P�]u�%������0y�dSٔ)S���O���d޼yV�NDDD�#)͚5��ή�r���p"""""""��.D�I���'88��_��S�p��A6n�H�V�����K�������v""Պ�������a��Y�fͬ������A��˗ټy3�N������ݻ3m�4��yS��&$�-7�߶mK�,��Օ�[�VZPXX��ۉ��租~�cǎ<��s̜9�lR���ݻwFJJ
-[��駟f�…��ۛꔍ-??�ݻw3h� ���Mu:w�``���L�:�6m����{A~~>۶m�ȑ#\�z��;2r�HfϞ�����ޝ�A���������m�6���+.]����-={�d̘1�;�,K�I��jÒ�p׮Ac8��K	"�d
8�y��n�:�ϟ�������{���-����CD�R�&M�v"�j�رJ ������C@nn.\�r�T����ʕ+�u�/��R��
#??�lb\E�EEE̝;���4S�K�.Ajj*���4o�ܬ�9s搗���7���())!((��x���K
���(w��Ã��D���+Ə_���{KAA���*.\0�eggCbb"888Ԫ���pv��ez_\\̹s�8w�׮]�����8��T7޺[נ1�������H㥄i�|}}5KD�ĉ�8q����o��+"�T\\���{�Ν;�r�
}����wߥcǎ|�|���DDD�:�G�DDD��PQQyTTiii��ۗe˖ѳgO222		!11���[%��&88�N�:�}�v"""8z�(AAAf�I߹��S��ݻw�X�e�N��d=`׮]\�p��]���;�лwo���X�b����ر�y��T:���|���lڴ	��@qq1qqq����g�S���������[w�4�i�f�f0̾�*���x��7�֭�ą�?���1����K���<>>���\]]����G�W����@�u�F˖-M��~��*�9�<p{�`Yݻw7�#"""������=
@PP�����֖����l�2�9R�8�;cDGG��?�̄	HJJ���z�'՗��[w�4�i��Å���HZ�x1'N���Ã�7VXg��|��7<��S�_���c0��,00�I�&UY����=z�/�������������D�>}�fԨQ4k֬N�׷����裏����hՉ��%!!ww�J�}DD�:�>'�t��	8@jj*���mڴ���?|||6lX��}7�Q��Q�8j{��>˕+W���_:w�lv,33�?��t��ɬNVVcƌ�7��
�ӟ*��>�3g��/HNN槟~�������]�t����H�!��]�x����e�W]yff&����OOO/WֳgO�k'''JJJ��'77�6mڔ;f,3���';;'''�`��������f�O<��1Tm,\��U�V���@BB[�laƌ���ҪU+S�ڌ��dccí[�(..��ֶ��7n��U�x�n]��p"""""""��.DDDDP`` ����o8|�0�F�2;�7�|���=���
Kxx8���8;;�{�7n�`ٲe�8q¬���7�|�
�|�
����{�nݺ���7�x��ǏߵɄe�={���p���Cii)/��2���0�*񈈈�ʞ���++W�����f�?��3'N��ĉ<��3�Z���������O�>�8q����r	������(**�ԩSf	���M�T�����͛�^��C��;���Iff&_|�k֬a�����^��ԇ��w�J�ixii�霢��J�U���lyiii���+�s ���5o^~�kcYcK����/t�ڕ}��1n�8k�#"�XM�H��.��^^^���s��1������[6o�LTT���g���@��Iwj۶-������еk�r�/]�d�WVu㭻u
É������4^J���w�^Ǝk�0D������ĉ���=�s��̙3�
6�~�z�bZ��ڵk�-�Ν[n5�VXX�ڵkY�n]����;�p��	�={6#G��cǎ\�z���x���$$$�l�2>���z�6�?^��nMl�~�:+V�`„	����������ٻw/���w%�\E�	�իWs��a�9s&#G��S�N��呐��֭[�����֖��~�����/�qS��ȑ#͎.�������믿.�p����'�콬���R�֭�СC�l��y�z�!JJJ��?�ATT'N� ((����ӱc�:���4�{Y�N����IOO�4	nOd+--�ڵk8::կHl	2228t��s�:t�@vv6yyyt���X^^����4=NNN��ݛ��%\�H��ҥ?�����<�T���P�q������x{{�����Çٹs'aaa�d����z��Ann.���L�>���G�ЫW�F{
É������4^J��U\\̤I�����H��j��)S���ϖ-[x�7�裏�r�
���L�2��c4hǎ��ѣ�1���MNN��/��u��DDDУGӱN�:������1c�N���ɓ���Α�����0y�dSٔ)S���O���d޼yV�NDD*���L\\NNNDDDн{wӱ�����������ɓ���c„	����z�#�����F����={^y����Cbb"EEEf�ʗM��O��=�}�vvv���o߾f����pss���8|�0�}�s�̩�8�"������ݻY�n!!!<�lܸ���Xz�!>��sڵkGnn.`���\�t����:�?b�v��APP���<��#���&**�O>����֭[kԦ19$33�nݺ�裏���MFFF�Iy�:"�4������`�0D����Ɏ;		�wޡO�>����f��:�.w̘1dee�t�R��yy�~��G�|g����*�<��3$%%�?��}�Yڷo�իW9|�0�1�>�l����DDDDDDD/%\H����&::��a���X���
����1c{��aܸq��۳o�>�7oβe�̶	/,,d��������{\UU����h8Xjij�)"9�MM��-/cx�j_'���_�H�8��M�`&���#I���wD$/��!K����$�?|��s�������Y{�>{��^��l��o��u���7�!::ڬ��k�X�d	��9���4jԈ:��3�X]a��_��g���#�z�2Vڰ�ҥK,Y��-[�p��9Z�nM����0a�1�+����;v��`���^F�Œ%Kذa��G:[U���f���_�,k��[�}W�\IBB���4nܘ�{�^x����ҥK�\���~___c�;3�� V�\ɨQ�hѢ��K#""|��w$&&�����˗�С�G�f�̙���[ω���=�l�Ey>>>DEE������wc���8YYY̟?�M�6���Ahh(S�N5V=p�3���}FWdo��J>|�l��{�r��UBCCi֬���lٲ�}��\o9r��8��bz�s�?>۶m�I�&<��L�2�ƍ�v�Z���9r��`��&N�H�ƍ�ܹ�EyK�,aƌt����|�赭�-eo]W��=�{�E���Y~��߳i�&rss��ok�m����배0֭[�…Y�p!��Rcǎe۶m���e��I�&L�6��c��������Gzz:}��a������h�?//�Y�Iq�޽{��GQZZ�����'"57f��l�B~~>�ƍ3�ֶm[�4G����-��o�8�N��<x0[�n%;;���~��*˿��oy���9�
'""""""�p�7�RgL`���㍈Ԏx���p֮]���iҤ	׮]c�Сf��JJJ�4i��΅��$%%���ǢE����-b���F��W�r��A<ȏ?�Hdd�Ym۶%::����/,Z��������<��s?~�H+**"55��{����d�ؿ?p�SRe{�1�,Yb�q�uY/�q�L&N�h,�~��֮]˵k׈����>����j���������n,E/""�����������Fڑ#G���9�<����ׯҘBCCILL4���曤��ן���b�
���*?�r��U5�S��N���iӦ
��?�!  �>x��X��}˖-dff�ٓ'OR\\���?����_ll,�v���HMM����hG�8���oߞW_}�궄�.]�d<�ε�WM>U}~����dm�A�V�Z���̢E�ؽ{7W�\�{�a�ر��׿6�M�6
WWW6m���˗	

b����7��Ql���$%%���[�r��Y�7oN`` �&M�{�q��3f���wߥ������w�…ٹs'�G�6˿s�N<==y���kt."�<���s�z�!g�#"7���H-Z� 99����m۶q��9Z�jů�kƏ��Ϫ��������ի��q�۷/cƌ1�9�N��qss���fݺu|�������OOO�~�Z����>��DDDDDDD.
��:�g����6l��C����-�,"���g�֭Ɗ�Z���7˳b�
:����̙3�С�N�">>��{��a�c��u����;��իW���`����Z���ѣG�駟�f��|�I�31/_���ǏӦM^{�5:w�̡C��={6ǎcٲeL�<��g�ЦM�J���9��VY�Ջ���kR&w�us���;�`�ҥ$%%�u�V�3��sh��MLiYYY�`("b���N�>���?���:�;w��̚5�xF��<������o���4�_��W�dff�����?��Ç�5kgΜaŊL�<٩�(��>Tőg�-U�	@׮])((�СC6\���233��� ��-*������{V�^����.+W�d�֭��l�xb���ۓ��d�R�kk/{�ږ�>?�܋j�3���_i��M�Kll�Yz��	[�ӕ}{yy1}�t�O�^i�{��0�,�y��DDD�t�R


���


���a�ĉ��%"�׹sg������ր�5������T:I���m�A�1hР*�ko;�Z���6l���v�<��Ԇi�4�B�TDD)))�CD����"�*[+����L�-x���Ni�f�����,��M���������	o�ܹ<�����b�f��HII��ㄅ�1t�P�j3nwwwf͚�s�=�믿NJJ
nnn��n�
@\\ݺu�{��̜9���-[�8�ѯ����L舺�[�S111�m���}����ŋ��G��wZ���YӔGDD�f�:00�Y�fY������Ӭ���:������bcc�Y��u�F\\S�La�֭=[��U5�S��N:w���ΡC�8p _�5gϞ�cǎ�~������w��ĉ�k׮�Uy��i߾=�Ǐg�ʕ�;w��~��5\\\,���^��y'**ʬ}T�0��|����8r/�=$R�ƌ�ƍIII1:N������GTT�����puu�gϞdgg3e�g�#""�Hm8��I.DDDD�����f�����9[ֱcnj�/�����
���dgg��{�1n�8"""hҤ���u�Ɛ!CX�f
~�!cǎ��SPP\��Wރ>��3g���o��3g�p��i�C�5�}�u��J}ԋ5�ԃI���^^^�/�1�>Z�ha��)�:�����̬u\7uZ?u���w�I``��>�<O�������B��5�燯��Ŷ��`��=z����ӕ�m���|F�T63{�kQ�:��k׮�/+Vdffj�ohh(�&33�v����W_���{��x���
�י��/gΜ�?��O���T\�:��^5��U��q�^T{H��5mڔ�s��?��Q�F�a���HD����F;LDDnjÉ������4L��@DDD�F�o�>�U����L��������'�0g��w�Ε+W��_�“O>�ڵk+=���s���׿�ա��:e�:�m۶�,�����'O�7o�@XX��1ʟ�i�p[ۭ��z���z0iԨ����lצ4WW˦�)��~""R���
kߥ�<O�1u$7=�l1m���,W�0=S�=��&Ϩ�i��}ur�}����ʑ#G�v�YYY��p}@Fii)��׿pqq�s��U��U���C��_Xl��]h��_�]۪�R&5������^T{H�~<��CL�<��`��L�bu���x�N�ʂ�������DDDDDDD�p!��,��N�;��#�=J�N�ޯ�;v�~�z���x�"-Z�� <<ܢ�IuT��&�l/S111>��<uGmZ�z5�����Cm����-~~~�:u���t��������ŠA�4h�b���|�$$$0d���5oޜ�^z������-����s��Irrr�ի�����c�i2x�`222X�laaa������L�>��}�2l�0V�X���'Æ
3�uqq�����OOO��L�U/5�{�jՊ��".\�@�V�̶]�p��#""���灀����s�z��i�8p�"��ϓ��BFF�������l�������˗ן���暭��~ڵk�P,u񌪎��)�W'͚5���������p��A�������͎եK|||���!''����n�5kV�تNzz:˗/�O�>6WҨj`Jy�\[{�R&����Ƒ{Q�!��ADD����
'""""""Ұh��:��/Y�c���O���ӧOgǎ�?���R���{v��/���/�\���gM,Z���g�:��ڲ�~-Z�K/�Č3x�w�1""�z��G����ȑ#���Ϝ;w���~��� &M�d�}�g

b͚5s�ұcG�|b[���O�~�ػw��6�*������RZZJnn.o��}��5�2p�@���y��HMM�o��gϞ��İg��N�Jqq1�?�<���ƾ-[�`���\�|��Ǐ3��z�Ӭ���6�ȑz��i��S�,���jc���ȭ����7� //���R<h|W������s�{��<��Sm<�JKK)**bŊ�?�˗/��O�@�7o�<#���Xi���3�:�S[��>�`�ҥ\�v����\\\		��&))�l?[�o[x��ʕ+W?~<���=z���JJJ8q�iii�5ʬ��8rm�mK��[���Ƚ�����������������(�…ܲ�cń�۷����c���xzzM�����;�p����,^��M�6ѨQ#^}��Z��>W�(..歷޺��@�|�2�g�f�С�l����̚5���4�6m��E�F1v�X�m�Fnn.QQQfۚ4i´iӌ�cƌ!>>����[t��w����X���Gqq�Y��1cزe����7�l[۶m-��̙��˗ٱc			$$$X����]w�e�ƺu�X�p!. $$�bߺ���-[r��y������#==ݢ\G�}��a������Y\���<��:Ɋ��"##���O9y�$cǎ�4�#�[ω��8~��'����ϼG}�ٳg[�����"�.]�0bĈ*�.�.�Q��H��bO���>��c���\�Z��l*�j��=�]��^z	wwwV�Z���ˍN*
 66���9rm�mK��[���Ƚ�����������������(�…8]PPAAA��A���!##///�-[FTT���������ÓO>ɲe����!##���\g�\-?�0۶mc�֭��Mi�& IDATڒ��9{�,�>���6r�HΞ=Krr�#���o߾Z����IRR�����憗�aaa,[��l����p�̙�}�݇��t�Ё�c���+��U���/S�L�HoѢ���>___����e�ȑ,[�///���7&!!���z������puu��LJ��P�̙C`` ��_���/�l�7m�4����7���X�Z�2c�ڴi����͕��{8�f͚�s�N�m;w����Ә!ZDD�ִiS�,Y A����pww�cǎƀt#�#�[�	�ϟOBB}����n��Օ�-[ү_?���H�ƍ�ƛ��@hh(����2z�h/^l���Q��H��bO�t���x���js`App0���1RՀ{�2nnn̘1����
F�v�hܸ1������F||<k֬�W�^Uϑkko[��޺�G�E��DDDDDDDDDDDDD�F�RVVV�� ��	@JJ����[�駱��ϐ!C`ݺu�<��3�9s�u����͛IKK�ȑ#\�r�֭[��ɓi֬��r��{��9�}�]�o���˗�߿?3gΤ_�~y�*�� ����,]��M�6���Һuk~��m��W^!==�����!�/_Nbb"O?�4����kv~YYY̟?�M�6���Ahh(S�N�u��f�*�i�~.]�Ē%Kزe�Ν�u����ߟ	&���i�3�r�J��ͥq��<��c����j�|�֭��g���nc͚5�5�u������$$$���������Ù4i.\��7�dǎ4jԈ~��C��͍r�N�.]⩧����w�5��ɓ'����ƍiѢ��k��T�~���_�


����޽��Cq�ŋ�t�R֯_O�6m��u3x�`&N�Htt��#����)))DDDX}/Ґ��緰����~6l�P�ֈ��mnu����̺�u/6�Pjj*����~mZ��kχ���}#rKMMe���������_�����"
��3""""""7'����Կ�m�ė_~Inn.ݺu3����RPP@�^���c�ҥf��r�J.^�h̤X�K�.1n�8


��O?����"oM�,))aҤI:t�H+,,$))���<-Z����g8`��%44���D���o���7�$==�+W����ANN+V�ph��~���{��Ǐ��sjj*{��%))�l��ĉ�p�Q�ڵk�v�qqqf�ڶmKtt4��_X�h1116�p���z�-�A;���hӦ
iii�5�r�
7n�������u���(..�:�jHH{�����?gȐ!6�KD�VѦM�Cݭl̘1lܸ���㹗�����QQQN�ND��ү_?������e��xzzr��)�|�M|�A'G(rkp�^T{H�c����_���a����4(W�^e����CDDDDDDD����Dl1uN߸q�YzFFC�࣏> 66���,v�����Ν;�.��?������>��v��͒%K�׿�e�מ2���o�>�+8t���?����ٳ�իWӣG���k6���~���_����W���ٳ�233ILLd���$%%���ϙ3gX�bE�qV�|�r�?N�6mHJJb���,]��;Ʋe�,��뮻X�nYYY�7��[�Z=��ѣi߾=k֬!//��:z����裏صk�&M`�������v�Z����0a;v�0�s�:eeeйsg��Mi�<"""M�6e�ܹlذ���B
ٰas�ΥI�&�OD���O������gϞ6�}��ѲeK��/"u��{Q�!qTYY����"��~�6m"))��a�����8�{[��O�,���������E+\H�

�+=;;6m�Č3hԨ���lڴ	___cՇ;vPVV��Ç��O�׿�ŗ_~	\_��^۶m`�̙t�����@^~�e��?��I��6m >>ڷo�ܹs<x0<�����{巪�6�~yk��Э[7���2e
[�ne��ɕ�<�@���8cő�ݻ3s�L��y�l�bq���ڶm\_�8))��/Z=���;�f�����_'%%777�|��}ll,��{/,^���~���3gr�]w0j�(�,Yb���]��G��+���6�#""b��C1y�d,X��)StrT""7���|�	'N�����;޽{�����C�%T�^T{H�Y�En�W�vv7���L>��Cc�#��$&&�����0D��gDDDDDDn.p!
���;�<�����ܹ�����k�..\���	���}�ӦM�����pd��ӧO�	L|�A��5)3??�A�Y�~��1㵯��1ˣi�5F�����������|�e*�{��f�9s��>:t0^{yyp��5�et�֍!C��f�>��CƎk��Ѻ�ԩ��Y�fVckڴ��~�\����ТE�|�4S��"""���pv""74WW����j��2�I������x#ܿ�0���0l�0'G""u�t���BCCy��W)**��;�tv8"�{��!--Mm$�B����\H���G~��������>���?���������������[o���Ç	�G�C�t����Y�l�amu���YՀ��4<���y�f~�����g���F��*�o����Ze���lE�F���...v���پ};��_y��,�;Z��7��^�;r�L�f혦4{�_DDDDDDDD�KII���Xjj*�����ҳgO\]]ٽ{7������8IDD)))�CDP{FDDDDD�f�Ҡ���LVVyyy�ر�Gy�l%���l���hٲ%Ǐ7����Z4QQ@@Ǐ��'!!!Fz^^�Eޚ����ǩS�HOO��ϯҘ�BFF�����ۗ{��"��_�����������Z���@�v�*-�"N�<INN�z�2�srr��
͛7祗^"&&���x��u����ujժEEE\�p�V�Z�m�p႑GDDDDDDDDDD��x{{ӹsg���5�BDDDDDDDDD�����"uhȐ!���ό;����j5��ݻ)))�ȑ#̚5�H�x�]�<�����������R���+�͛gs���4�j���ol{��G����ȑ#���Ϝ;w���~��� &M�d��޽;O=����DGG����7�|Cii)EEE�X�����s��e�x�	z��a�y���ˣ�������h�gEaaaF����RZZJnn.o��}���������O�~�ػw��<5��Uq�:u��	�S�NYǔf�#""""""""""R[������DDDDDDDDDD��i�i�틯�/gϞ%  ��={�m###�9s�0g����9b�b�-QQQl޼��G�2a�#}���-�e˖�?���p���HOOg�رl۶���\����kҤ	ӦM3K���㧟~�/� !!�����}�QfϞm��|||;v�YZ�.]1b���Z��3�-[����ϸq�̶�m��"��bccٷo���f�u����u�ӧ۷o'//���@���Rjs@��Կ��4�����H�HKK�Q�F�CDnQiii�A�i�}��9��իW�����>|�S���K�޽IMM���g�#"b8z�h�LHV�S��*��	iC�V{S�F��E.������+�fɒ%����1����K����s�N~��g�^���8q�K�,aժUvu����`ɒ%���;l޼���Gy���8>��j�9c��}�]���())��ӓ��$�����u�VΞ=K���	dҤI�s�=q͟?�;v���r��E���y�<x0����y^			��/�������Om��kqVԢE���y���ٶm�Ν�U�V��׿f���xyyUYǎ�eʔ)��4K���]G���Y�p!;w�d���f�ٹs'���<���5�ID���ի�����H=Z�~=�ׯwv"""�f���,Z��U�VQVVƈ#�ر��kED��˗��ɱ��JD�Y^|�E�o�^�]뫜��v�������HãrC�0a�٪�hт��x���T�E��_�5oޜ��Xbcc+�ko�`��y����>}:ӧO�zk���W�
[���Y�pa�y��i�~������!&&������=נ�#F���տ��I��:5oޜ���.]JAAmڴ������&N�H�f�*=��4\)))���8;�[FYY��C�U�/_f���:???��Ù5kiii4m����ȍ�cǎ|��k��١���o��r*���٫�9B�F��I.DDj��1cظq#)))ƀ���������rrt"R���dff:;�*M�:���Pg�!RcZUJD�իW;;���ء.99��g����i#G�䣏>"99�ɓ';1:�ѹ��X��,"RQCl#�%�EDDDDDD&Wg "r3hڴ)s��eÆ
RXXȆ
�;w.M�4qvx"R{��!--��a��T*--���|g�!R+�������Эe�…����l����b�y�
D�޽y���_�BII	�.]�Ga��\�v��x�����3�yW�\��?�������;�$((��+Wr�ҥz8S�.]�ğ��'�z�)�����oKBB?��Y��� c����+���O?��+�J����3g�}�]���͛73i�$��Œ�^�`���y����={6���c������;w��2�j[���(""""""�pi��Z��C1y�d,X��)StrT"R"""HIIqv""6���8;�Z���BDD����[Tjj*����C���gRRR�ڵ+&L����I�&q��!#_aa!III���h�"Z�h��#HJJ�/�`��F�;vЯ_?>��3���			�(?$$��{���3dȐ�<U�~���{�9�?n�����޽{IJJ�Y�f�Vޛo�Izz:W�\!##���V�X���W��S���{��K����r�J.^�ȫ��j�-..��;w�Q�_��/�����<==��aO�����j7�������4\Z�B�&�o�>-���O�O�#G�tv8""""""""bEBB)))�oߞw�y��D�b�
:���Ojj*{��a�����у�{��a�"##i֬˖-3;�i�E߾}����s��1��LyDDDD�a���?~�6mڐ����ݻY�t)���;v̢�S���������Lٽ{7III���s��V�XQ��T壏> 66���,v����`�(��ѣ���{F�mڴ����?��f��-A�F��L.DDDDDDDDDD�d���t�>�"55///�}�]���7m�@||<;v��͍���3w�\222�f�С|����ڵ�K�.q��7on�zz��Q��.���n�<""""�ő6�֭[��+8t�֍F�ѽ{wfΜ	��-[j5���XBBBhԨݺu#..�,���c����K�t��'�|��o�͛o�	\_�����8~�a�⶷m	j7�������4d��@DDDD��G�ҩS'��V�^Mvv6���>�>C�7�=w����������ŋ�hтx���pBCCk�lSG��\�О2jGu�}�'���㏹��;Ͷ���n�߸q#w�q�Y����y�n��v>���q8��+S�g��'���?�����o����???z��Mdd$����m��w�
+奦��H|����~��ƶ��|
du�cǎ����X�j��Ʉ���k�.~��gz���_��?�-ZX˔f�#"""�t���,���̙3�Z^pp��=zp���Z-�*�}�ӦM��������,�*�5�Weq;ҶT�QDDDDDD��Ҁ1��/�}�v�����ϢE�X�jeee�1��;�Y�z���O̙3�͛7������ر�;v����+����Q�eߪ�t�Ž;8t�ŀ���L<<<())!++�l�W_}eǚ�V߶�)--e޼y���[쓟�O~~>���?x�7�۷o}�{CP��V�^�g0ODD�֭�ʕ+,^����c���u啟���LJ!C����J^^;w�0�]\\pu�\lڔf�#"""R[��F��ڵk6����m����b3
L�X���RMʩ�[o���Ç	�G�C�t������m6S�����f��-�ni�4�B�Tjj�1c���X"""���8��ۭ�_�|�ٳg3t�P���g֬Y���Ѵi�SDD�N�zΛ7�͛7���Itt4����;��…dgg�x�b6m�D�F�x��Wk��2��v�j��߿��6Ӏ���H�����̴pq��!���ֵv[�,X����t7nLTT�?�8\�v�Ç�b�
v��A\\�֭�u���c��3�6�X3}�tZ�nMbb��b������ԩS�����ʌ5�5kְj�*v�څ��+}��1��jՊ��".\�@�V���p႑GD�����BBB�裏�ٳ�������?'O�$''�^�z�999fm"���������Wi�Gnn��j����]�v�ZNUL+�%%%ѲeK�?nl/--5��W_�~���6�p�m�v�������HåRg�N������TS۶m���
�:3��h���9{�,�>���6r�H>��#����<y���{999ddd���ERRw�}����LJ'�|���`�}�Y222:t(ݺus^�7	S'h�	���b���O�f���ϪU�ػw/%%%f��Tpq#���Y�v-�������f�	���ؼy3k׮e�ĉN��aQVl���$##�cǎ��{���;��裏�l�2��∉���{����NJ+���	

b����qn��v�y�֬YCYYݻw��n3�w�ԉ��"N�:e�A�ԩSF����…deei���8$,,�e˖�k��F�.]8t�o��`�zW˖-9�<�ׯgȐ!2�|�c�L���[��i޼y���k�w�}<x���xX���k���<��c?~�lℋ/���c���x��W�ԩ���̛7��{��i[��(""""""�pi��ԙ^�z�͂""""���#11���L._�L�=z43g����t�R6m�ķ�~K�֭��o~Ctt��)���b��\�t��+W������k���;	

b�ʕ�5�-Z��i��������?��F�m6آ<���HLL����1��t���,�ϟϦM���� 44��S���*����K�.�d��l�¹s�hݺ5���g„	��右r�J��ͥq��<��c���5��ߞ:���:1
�8|���{����ի���ҬY3���ٲe���#$$�k׮q����X�׊���m���l۶�&M���O0e�7nl�q�:T�kO<k׮�����#GZ�(o�ĉ4nܘΝ;[gɒ%̘1��;zj3��﫺���k����{^mX����3g���c���8p��ݻ3v�X�m�Fnn.QQQf�4i҄iӦYk��Ѥ������������#00�l[^^��}DD���Ņ��v��e��JDĖ1cưe����7n�ٶ�mۚ�����n�:.\�…����3
���Ϗ��tc���cǎ5�ߥKF�Q��T%,,����̙Ü9s,�9rĬ�.]�X�ݩS'"##m��H�R�F���������H����DGG����ŋ�z�*G�1:��WRR¤I���8s�W�^������$^x��]�ViY�}����V��Bqq1��y���������yx����Wi���P���o���7�$==�+W�p��E2227n/^�����x��裏��o(--������T���)..��g�ĉ�ݻ�+W�p��֮]KBB�C�VT�:�����ۛ6m�p��%���eee�;��/����i�9y�$������������ƒ��Aqq1�ϟ'55���~��^��P��g|��}�����V?�			\�t�xP����s^��ԑ{^m�[Ӿ}��^y�[�n��w�����ӓ��$"""������
///c�gk��. IDAT�
7o��x]�8p ͚5c�Ν��ܹOOO�q��OD�2���dgg;;i�*k#�hт��d����/nnn���2r�H�-[�����wڴi:ooo<<<		a���ǜ1cmڴ��͍���m			������/�G�f���f�k������K0��M����A׮]y�7�0a�V�2�?s�L���>>>�1�%K��
ȯȑ��ڍ"""""""
�V��Z���Jjj����:��D����N�>���?���:�;w��̚5��gϚ�]�b���g�̙t�ЁS�N�޽{ٰa��9���Cc�ْMLiYYY2��NWDDĪ�|~�����Uӯ~�+���`���D~�a>̬Y�8s�+V�`���6ˮh���?~�6m���k�ѹsg:��ٳ9v�˖-c���f��u�]̝;�;�K�����֭[���3�W~����[����N�v�JAA�"  �pѧO\\\���$&&�C���nQQU����߳z�j���x��wY�r%[�n5�_��P[��\Y��۷'))���T۱�g�5���ϩ#��ڰR���|�̙v����>}:ӧO�븦yw�u�۷7�ּys"""X�t)�i����rrr�8q"͚5��鈈X&..�ӧOmR{x{{c��cKӦM���%66�,�b;k��0�fY�U+�[���hт��x��L�.*�?o�<�˲�m�v�������HåRk�N�Ze'
�q�m���!�4(�:"VL�wf��غu+qqqt��
���@f͚�ԩS��nڴ	���x�������Ν����Ȩ�9~��Q�z��L�LyDDD�S}>M�e��W�딲�2��ˋ��5f��֭qqqL�2��[�:Թ��yw�ޝ�3g��ϳe���������H���^Y����)�W'�;w���?�СC8������g�ұcGn��vZ�j�}����Ç9q��ڵ�r�EU^~�e�����Y�r%�Ν3�W�:T�i��m�ڥۡQQQf3��e�5��W�9u�WV�Zqq1�/_��+�F���o̘1lܸ����cJJ
~~~DEE�[�"r��ٳ'nnn�޽�aÆ9;q�ڍ"""""""
�\H��ի�z�rv"""��S�N����Z����`РAV�u�رJ�:�<p}֯�Li�<"""��Z�rSg�|���RXXHaaa��

�����ѣ�O���l[et���,�TgΜ�اC��k///���U6`�⵨i��}uҵkW�+233

5�744�Ç���I�v�ꫯ�w�=��c������:ס:|}}9s����,fϷW��1�2��|Ϋ��:rϫ
+u�_�~��;���O[�״iS�Ν���cPƆ
HLL�I�&����<==�֭YYYp!"rR�QDDDDDD�aҀ�j�����.W�������f>�6�vy?��C��M�tuu��fJ�V���H}����>Haa!�7o����|�7o6�WTquSGrk���6�¤Q�F���zn״N��:��puu�ȑ#\�v���,��������dff2r�H������B�Ν�:��ʯ�ʮCYY�Q��US���Cq�����&L�`��V��"{ϥ6b�����ϩ=��ڰR�|}}�p�AAA������f3�C=��ɓY�`S�L�:PHD��BBB8qℳ��jR�QDDDDDD��р�T@@����9p�={�4�8`���ϏS�N��������e�jՊ��".\�@�V�̶]�p��#""R*�X���!C����Arr2}��5[���믿f���<�b{nn�Y�����Ю];�b���ɓ��䘭6���P�󫎚�)�W'͚5���������p��A�������͎եK|||���!''����n�5kV�ت��upqq�����OOO��@���IOOg��������U
����k�sn�#��ڰR�222�ADDDE#"rݟ��g��""
�3&+�Q��(""""""Ұ���""""R��q�x�
���(--�����y}�Q���8r�?��3�Ν���&((�I�&yM�����i�:u�ԩS�6��򈈈ԧ�|v�ޝ��z���b���IMM�o�������"V�X����|�2O<�=z�a޼yF����'>>��VZvEaaa��Ǔ��Kii)����y��۷�ʫ�ԩ-��	\L�t�R�]�FHH���...������?���d��-�Է-�\��-[�~�z._����Ǚ?�]�<�:�+W�0~�x9z�(%%%���p��	���5j��1�;v{�iu8rϫ
+""�"
��]Z�BDDD�ɧ�~�ɓ';vl�yǎ˶m����%**�l[�&M�6m��e˖�?���p���HOO�O�>l߾���<��������)""R^}>���~��/�����,�y��G�={��|||,��ҥ#F�����ƌÖ-[���gܸqf�ڶmk�VW�S[�S��̞={�ӧ��ㅆ�����w�^c���S߶8r���X�n.d�…�����K/����;�V�b����J*��M콦���=�6��������������ԔV�����%ћ6mʒ%K4h��v���t�ؑW_}#���'IIIDDD��燛�^^^����l�2��}g̘A�6mpss����>q�f�عs�E;w����ӘmXDD�>����t���瓐�@߾}���puu�e˖��׏�����?Ҹqc��&$$���;����=�ŋ��i���Z�hArr2Ç���777|}}9r$˖-��˫F�j/G��{��k׮�kWWW�����qw�e���\�S߶8r�M��СC���Ã���sl����ƌ3HIIaذa�k׎ƍ��ꊯ�/aaa��dzf�z����M콦���=�6��������������ԔKYYY���i("##HII���FPXX��O?���?6l���.^���K��~�zڴi@AA�f�ĉDGG�ZY"�RRR�����^�!���o]=�+((��h6d����3���{�:m���T"##1�ڴ�{�֞"rk����m�~����̐D�
�gDDDDDDn.�Ug���_�~ˀ����ԩS���<��Zޘ1cظq#)))��������GTTT��%""b��~��s9zϫ
{�X�z��Cip�N�������������MM.DDDD�i��ڶo�>�|�I֬Y���?���-[2a„Z-�iӦ̝;�?���5
�
6���H�&Mj�,{��PD���{^mX�	
��A���жm[>��N�8AII	w�q�{�&::__�Z/�b���,X��)S�X�刈����Cq����j�����D�����9;��‰'���x�ᇝ��ԡ��DRSS���T����������E.DDDD�о}���خ��DDDQgeX�2EDDlq���Qu�&�Q�Nn>�qM�{���R���]G��Xjj*������?��/���={�8;�c���8;A��������ӻwo���Oqq��C��i���������������M�O�>\�zU������������Ԑ����=z�N�:Yݶz�j���f�����ܤ�n��N����ׯ����P��*;��\"""""""R]p!"""R���TRSS�����-#22���Hg�!""R+^|�E�o�n�����Y�h�V�����#FбcGz���HE�fӻwo�s��ȭLm.�	
���ԩS<x����R�^���H�X�z��C�U۷o��~��efϞ�СC��� <<�Y�f���FӦM�3L�	��?���a��XU�+[TFm.�)Wg """"""""""R���

rvvINN��ٳ<��F�ȑ#9{�,���N�LDn���q��Ig�""Nv#��j��\"""""""RSZ�BDDD�������:;�*�����0Djl����AD���2g� ����p�ʕ$$$���K�ƍy��x��f7...f�ҥl����{X�U��� �$��P0ʹ0�<�M<�NRY���Z��++���Z"�19�
P!Me��<�"�D�l')5-�����vsؠ��uy�^Ͻ�u?�֭����.\�@�f�x��g�6m��������7߰t�R�bz��_͂xꩧ���o-�OHH ++��7ңG���M1-Z��`0�q�F&L����c�����O���׭����`�e͚5̙3777V�^
�^�_����@:u�DHH�����̜9��˗3x�`S���'gϞ��Ϗ������<��ŋ����޽{�z�*�
2��f��DDDDDDD�2h�����H)���	�v""ŪS���S�TZ@$"���㭝�T��ӧ���	��k�ؼy3������ˌ3HMM5�'==��� RRRX�r%666̛7���D>���w�N�-�����ggg�ϟo���f�|�
999�����X�޽���gǎ�1�
�-L��EDJ@VV�iaBYj�������������;v��ߚ\\�t��g�booO߾}�ͣ�Z-++�)S�p���{���k�\�bq.�\"""""""Rl�������������Huy�زe���L�2�ݻw��������J�N�����DDDеkW���پ};���,Y��+W��h�"


x�w�r�
�/������f���f����X:t�`����#"""RڶmKll,K�.�V�����c�q��u������g׮]���˵k�HII�'�0-�(Ji��g�}ƙ3ghժ�֭�СC�Y����_�R�%"""""""�A.DDDDDDDDDD�V2fJk�;w.�[��^�z��L._�l:���nnn���Ҷm[/^@tt�)�G�x{{s���N����1v�X�x��>q�pcB�ڴic#"""R^��|||���7�.kMd�¸�����\�|�aÆq��58�w���K̽�ZmϞ=̟?�G};;;�w����X�K5��������T���N@DDDD*�����jM'N��}��E��� ..wwwF�]������2��ݻw�}�v���{���y�G4hÆ
��ѱ�R��[��['�����ZBD*W�v�L_;99PPP`jKKK��ӳ��<y��Y�8|�0ǎ�m۶�����J��ҥKE�3�6c����Hu0.@0*kM��SO���w�;vP�^=fΜ�?��O���[�z�)RRR������%�QZ���/�йsg��u����\��DDDDDDD�2h������ܶ��z��{�91311��+W�i�&
3fnnnt���
�����WNN�����f����$''ĢE�0`�u�%�ѵ�j	)ɭ?�ʲ�����u�:u,���gvvvyR,��_�M��mE�&"""R��n���^9;;ӥK����t�{��gϞ4nܘnݺq�rrrHMM�k׮4nܸ��V�5��u-�>���ʠ""""�TM�8�w��"ۯ^��…9r$...xyy�`�"##iРAu�)""w��}}}9x� ��μ��+��ӇF�q��9�l����y���?��c�=V�YW����L���"b
...�>}���(�Ϟ���o��ɓt�ؑ��TV�\ɛo�Y�{�6mJFF���4m���Xff�)FDDD�Z�Syxx���ĺu�r�
}���o߾�������lx�y�jՊS�Nq��z��mjOII��U�%"""""""���Q""""Rn��4YQ�+88����3v�XS۸q�8�<���V�LDD�v`���4i҄���J�&M�����ՕW_}�3fp��uV�Ze�t�Z�%D��}}}���~�:/^��?�`00c�S�w�}Gxx8]�v%((��ݻ�a����;S���iii�����p��i���m�k(OM�?�	6o�`ZpѧO6l�P);H>��3���q������Y�l�E�j.�Zp!"""RKݺȣ���իW���E�^��߿?/��"[�n5{_Y�rrr��O���W�^:�U�V���k�GQ9eee�q�Fz�聳��)�E�6n�HVVV���;Ut<���`„	f���ƌ�+������Y{VV}��=����<������]dnG�aРA��(ŵC��^�s����;���SO����رc���6뿸�T���,�|�I�NAA�ٱ��4Æ
3;����%K�۷/�
bѢE����.�5��k�<y2mڴ!99z����O?�g�}F���y�7�?�/^���K�.�nݺ�����gT�ƍ�;�:���â��ll�ׯ_�_���Ν;DŽ	�駟�����"e����.ݻw�ڵk�o���w�x��￟��y�2�VڷoOFF/��2���L�4�Gy�"V5��������T-��C�\����������GNNǎ��#,,��q���̘1�u��q��Y���HOO'((�ٳg[L���7�|CNN�ٶ�F�{�&''�;vT�
���ܱcǀ�N�(�=���ԩS�b����:u*6l�ܹs��瓑�Axx8ӦM#''��<deeY,층�<c�K��4i_~�%���;����<y�E����GGGƌ�/��·�~kvl߾}���߬����'**�k׮q��e����2e
�/_6Ŕ�UK�HE$$$���p[�hذ!AAAx{{��₭�-NNN0����S����9w�s�����WWW�Ν����`Μ9�l�[[[�ⲧ�~���o����iذ!����1jԨ8p�ک���T�F*kMd���X.`0�va�1�v��۳f�F�I�ƍ���g����ZĪ��ʠ""""w�-[���'�p��!���Ǽy�شiS��BCCIMM�S�N���s��a"""�ڵ+���l߾��u7��.66�:X�jl3ƈ��T���s/^�e˖�:����9u�-[�$((�C��v�Z\]]9y�$!!!�i۶-���,]�������֭��_�cǎlٲ�}����/?F����qpp��&る['�8p���@:DPP����={���PSLy�Q���T��~����ěo�ITT�f׮]�X���z��l�2x�����sϑ����eˀ��m���Ç��o������IJJ�̙3���9s���$|||ppp��k��[����޽�\�H�J��bYj"#///�vq��O�:uj����V��{�7o111<x��˗���`��KDDDDDDD*�\����T��`0�SZ{u0�b(,,���~��7F�IBB���Ų������燛�����mۖŋ]b>'N�nl�6mژň��T���s������t�ݻw���K�Ν����K�.̟?�]�vY����{{�R��3�'����u��888���KBB_|�E���8�5b�ȑ���<x���,�=�=��C������͛G�޽����s�Φ���Yy�Q�����&M�D�-�v`
���+f&"w�޽{g�4DD��j.�]Zp!"""r��={6���#..����/�3��� �]�V����4<==��>��'O��ϥK�ptt�8fl3ƈ������%-j,�8���@zzz��*,,$;;۬�D�.]���w��
��g�Z�Ǹ8�����~ڷo_l����LJz������~�:�z��nݺf����f��v�
�/��bj+�5���;]�
X�x1۷o'==���t�o���ŋ�_�����;L�^�HII��oED�t��DDDDDDD�vi�����H�&/n��a�*|��W,Z��.]�p��5V�ZŐ!Cؼys��
K쯴_�שS˒��f��,e�:w�`ڹ�(��=d���\�~��~K�)���-�z� IDAT�j/��[]ch�&M1b��������~���g{��=����5���;��?�̙3Y�b+V�`֬Y;��Twww�_�N||��S�v��DDDDDDD�v�-=DDDDDj'''<==���$55��;w�n�:1bD��\\\8}�4QQQ����;��M����Aff&M�65;���i�)My1�e�{��g���&,,�!C�ФI�s�z�j
y�簵���Օ�~����$z��i�OJJ�ИiT���y���Ϝ<y��;V�ϲ�0a��9�6m�����ЧO����d��Gx�Mm�F�"r�������i������'..�A�Y;�j��KDDDDDDD*J;\�����!�
��`���?'''��~777����7p�@|}}���~�:/^��?�`00c�S����iii�����p��i�\�m���R�q�W�^t�ޝ.0y�dv��AVVyyy|���̞=���8����ȑ#M�0`~~~$''���Orr2˗/�����3�<�X�����]��|��`�^0�5F��}��ǰa��믹|�2�=���{�Eܲe�HII!??���D���x��+t��%DDDD*���{�;������������%�p!"""r��4i~~~������ov�����7y�d���Crr2>>>fq����7�0�nܸ1�.]�������ӧ{��%%%�b{����&����������?���
�����?�ŹȻ�kZ�`<��]�HKKcʔ)f�[��h+��/��"111$''��ϛž��K����+b�ĉDFFŏ�M�4a���fm;vd̘1�F�""""���ߟ���[;
�ZE;\����T���������-�G���{{{ڵk��ɓY�dI��6lHPP��޸��`kk��� $$���s�̡e˖��ڒ���x��������u���4lؐ��W���QY�9��@`�������<��888p�=��?��U�V��ZLHstt$88�ѣG��쌭�-��Ό7������*�{y�ަM����������ѡC��}�b�+j���{���u�����	�o߾ԭ[ggg&N���ի�����5���\�ڵ�e˖�NCDDDDDDDDD�V�""""�TQ<<==���,��e�srr��7���7�,1�����{�ooo֮]˙3gL��?s�IIIL�>�Rs)�팇���c„	L�0��}6jԈ�s�2w��r�VR;�}�puu��ϯĘ�����ct��Qx�ڶm[dL�F���_�Z��z��%D�V�Ǐg�֭�NCD��q7-)���p��򬝆��zFDDDDD�N�""""Re&M�ė_~IXX�iRjXX...���X9;)MNNW�^���ʵ0�2���Q�FY;�b�>)��={j��H
�zFDDDDD�Τ""""U�`0T�y��$ꚠA�,^���_�4As���R�~}+g'"""��߿��k777�Z�������k� """R��k���k�NCDDDDDDD䎦""""R��qfΜɊ+�5kݻw�rV"""R���dffb0���ֶ�sP-!"u�Աv
"RM
����H�1~�x��í����B�������ȝE.DDDD�Pmى��y{{���m�4DDD�����K���zG���>\?D�`���lݺ��i���:vvv���Y;
A�������ȝJ.DDDDDDDDDD��5j�F��v"RE���4A�effҨQ#k�!"�@5�H͡zFDDDDD��dc�DDDDDDDDDDDDD�zL�6�q��Y;
�ZA;\��������������|����Ǔ�����7���j��U�ĉ�o߾�cG�a۶m$%%q��
qqq�W�^�?WW�*�;""���8���=z�m�%"����/����=�MD�FI�ľ}�غu+)))\�|GGG{�1����۷o��m0HHH��sW&�T"""""""��\�����"<<���<k�!""r�?~<[�n�v"r�����v
RC,X��#G��^���%�W���z��{�ZL���gٲeDEEY�'--���4�m������ׯ_��
����ʕ+ٴi����3777�v�Z��D����ӇK�.q��q}�Qk�#"w��j�?���E��s�N���~��}���o�>̒%K����Ծk�T"""""""��\������gϞZl!"5ިQ�hݺ�����F��v
"r���!1JNN��O?���'??��ʶw��"�W�XATT�����LJ��ӪU+


8~�8����۷___�l�B�f�*��W��p�BF����^^^,X����H4hP�D��u������BD�Dq�IJe�عs'
6dڴi4��͛���I\\�W�&&&;;;�.]Zi}״���DDDDDDDj-�)�k���k��f�4DDD��NADDj1��TΤ:�B
��@�:uLOY.��:���l޼{{{����өS'��ݻw�{�����ܹ�͛73}��J�?88����3v�XS۸q�ذa���̜9����S�n]�b�ԩ�NGD�Ae�H���Dtt4NNNѦMӱ&M�0d����;v,��ь9�Ν;[-ߪ��JDDDDDD�vт��?���pk�!"R���0�������m�S���S�����)H���b͚5�ڵ��/ҬY3
��/�LÆ
Mq�I�=z�nLP,�����5kְc���ӱ���]�v6��Ç�吓��ڵk����…4k֌g�}�iӦ�o����$7o�Laa!�ƍ�Xlq��ӧS�^=:t�Pi}gee�q�Fz�聳��)�E�6n�Ȅ	ptt,6/�9�����/������U�l۶
��'�-��Y�&M���!00�/��´��x���X��������ޞ�}���k��v�*�����.ܸq#$''S�^=�z�)fϞmڍ���Q5�������H�""""����#,,��i��k����NA�R
>\�D�j���ٺu��Ӑ*����ԩS9uꔩ-##���p���	

���B�^�r%�ׯ7�����رc;v�+W�0~�xrss�1c�������t���HIIa�ʕ���ۏq���O?]b>m۶e�ҥfm��7�|CNN�{��8ֻwo���ٱc#F�(17����Y�b���4j���鈈UWs��Q���_b>}��%00���D�c�>QQQ\�v���h���

��ɩ��\��p���dff��޼y3���e����DDDDDDDj-�)ŨQ�5j����kh�k���ӂ�;���9u�-[���wߥC�����p�BN�<IHH3g��rq�[�l�O>�`0���Gtt4���lڴ�4�.44���T:u����i׮�O���Ϗ��x�o����Ë�'==�اB��v������5����XM�%z��Eǎ9{��\��媫��p�...%�s���p��y�c 00�=zp��q,X�ٳg	

e�̙�}��ԅF<��/�y��]���� v��mZpQ���JDDDDDD��)�"""""""""""5��`0�SR��ݻ�s�����ѥK�ϟ��]�*���	�aaaDDD��o�1r�Hؾ}�).&&???��ܰ���m۶,^������)((�N�:�n��[���}��	��d�[�cD��kѢǎ+r¯��~婑�������nݒ�	YXXh�ߛ͛7�޽{cggG�ΝM��u^YU�.�;w.�[��^�z���/_6/�}TM%""""""R�h�1s��	ڷo_䱈����pwwg���ՙ�����Pey�hM�o�>�n�JJJ
�/_��ё�{///���{�翵���{��M�ҙ3g�ҥ�Y{�n�8{�l��={�l�,YB\\qqq|��L�2ooo�ׯo�KKK��ӳ��<y��~���9{�,?��3m۶-W����K�ptt�8fl3ƈ��H�Q�uLzz:���nݺ�8c����lq�����u׮]��_J컸>�S�k�����ŰP����JDDDDDD��т1y뭷ػwo�Y�r%�6m����1c����f������Hm���h�"v��i��o��o�>�����Y�d	���꣤��:�n��ɭ�gY�t�D������ݝ={��m�6�=ʪU�

e֬Y�1(�I�7���.��?�ٳg���oy��͎w/�n�o�66�gۊ�yCDDD�_yj��c�u�Fzz:;w���_,6�w5�⇛ݺ;���+�>����B;;;��E�<e����DDDDDDDj-���{��~��U.\�ȑ#qqq��ˋI�
�3M�
[�l;w�aÆL�6�A�Ѽys233���c������`gg�ҥK+�GQ5Uu-�P�&R<WWW~��'����ٳ��=))	��=SQNNNxzz���Ijj*;w�dݺu�&ع��p��i���*ԟ��QQQ�_��>}��裏WԄ���iӦddd���IӦM͎eff�bDDD����:fĈDGGL�~�x衇,b~��G֯_����-�'''�-*MLL�,W.UU��>���}*�Q""""w9��`���;Ipp0�ϟg�ر��q��q��y���������H�%%%���!!!�����ꊭ�-M�4aȐ!���ФI���INN�v�妺M�x��Ϗ��d���INNf�����ׯ��6l���?����~�a����!8___~���_��ŋ���1̘1�k|�qZZ����c�ȑ\�v��^z���@N�8Ann.�����?�!22�	&���2�n߾=�O���~c�1FDDDj��c�t��s�=GNNӦM#<<�s�Α��OFF������K\�z�g�y����-[FJJ
���$&&�����O?]b߷������Q5�������H�.DDDDj���֬YÎ;HOO��Ύv��1l�0�����v�Zbbb�p�͚5��g�eڴi����-�y����,6n�H�=pvv6Ŵh����ƍ�0a����p�"""�cVll,������`ooO߾}y��h֬�E�5k�3gnnn�^�(�XY��eee�f�v���ŋi֬�
��_�aÆf�x��9V�ZEll,��ٴiӆ�'2d����^CYk����Q�k7޿�7@rr2���㩧�b���f;5���r��^�J�v�8q"������Ķm��8q"mڴ)2�&M����C`` _|��;w6˧�Ͼ���毫�^�n)٤I�صkiiiL�2��X�֭-��{n???����7;ֽ{w�ד'OfϞ=$''���cW�~}�x�
��ƍs��%���pqq!**
�?���ԭ[�M�6�~�z�S�oժU+�͛Wi}��Ӈ�{����bvM)))��-Z��:��ח?���o�����,�8p .,2�&M�0y�d���;2f̘R����+�.,�}TM%""""""R�h��Zj�ʕ��� --���<rrr8v��aaa����\f̘��u�8{�,yyy�����ٳ)(((��o�����z��mq�w�����cǎJ�>��x�������ڵk\�|���h�L���˗-b���2MH��Xy;�egg3u�T6l�`�4���p�M�FNN�齗.]bҤI|��������s��I-Zd6i�<�P���q�Q�k7�>}:���\�v���L6o�l6)�ʕ+L�6���h._�L^^?��i��͎=
@���K̳o߾$&&Z+�g_�Bu�ȍEM7/l����#����=ggglmmqvvfܸq������T�~���X�h�<�������Ӯ];&O�̒%KLq
6$((ooo\\\�����ɉb�4�9s�вeKlmm���5����2g����5j>� ������ggg�����9={�����~�iؿ���߿��
2x��
�C�:%�H�Y�������O@@�����{���Ɔƍӿ����W�^��зo_�֭���3'Nd���f(��UE]X���JDDDDDD���""""�Ԗ-[��O0������?�6mb���������J�N��?>�ڵ���������>|x�O^����C�9�bcc1bD�^���HI8@`` =z����,X���g��̙3�b۶mKPP�iBFY����o����:u��-[���ҡCRSSY�p!'O�$$$�t�u���믿ұcG�{�=�5k�_��������:th����5DY�ʣ<�n��x�b�7o�ڵk	

b������/�����+�:t�رc,X����ϛ��…�������`�~(��/����{��M�t�5b�ܹ̝;���⾇�k�����ӳ��:99��o��o���၇�G�����x��K����{�f�ڵ�9s��-[p������>}:��GD���',,����s�Z;���c���_�B��4jԈ��������uayj²�G�T"""""""��v����`�����`��KXX���o�9����o�n�������777lmmi۶-�/ ::��~N�8ܘ�w�6mژň��X˼y��ݻ7vvvt���4}����>>>fO���Xy;�c|}}�ܹ3vvvt��Ŵ#î]�L����3�[���___��/*t
e�!�W�v��s�Һuk�իgZ�q�nE��{��,X���\Ƨ�֭[�3H
�{��|�%��{��MD�ڤI�hѢ��NGaaa������c��D�����x��W9t萵S�k���]�Å���H-5{�l�,YB\\qqq|��L�2ooo�ׯo�KKK(��Z'O�,��K�.7�Y����#""R�Z�x�$����^w���_~���Ɖ�F+o��3g�ХK��nݺp��YS�������Qy���5DY�ʣ<�nԮ];��NNN��N�>mv��ݻ[���ٙ��t���iݺu�y:;;[+�g_�����D��5hЀŋ��3a��o�N```������z�����Z;���j*��E.DDDD*��I�Ɖ��m/^<<<pwwgϞ=l۶��G��j�*BCC�5k#F��~2�Ͳ��K<^�Nll,7G3�cDDD�����Ћ�n�m*6V�NŹy�QY���\CYk���U���������uI���{PTl�n�HOOg�Ν���Şk�Ν��[�糯�۹��D�:<���̜9�+V0k֬"��H�ѧO<h�4DD�*��DDDDDDDj-��Ŝ�������ӓ��Tv��ɺu�0M�tqq����DEE���R�>�6mJFF���4m���Xff�)FDD���eAcrr��N���<����"c�������O?�DRR={�4�'%%��1j޼9?��3'O��cǎ�v
e�!�WV��jժ����9z�(O<��ѣ�#F� ::���`����C=d��?�~�z�nq�v>��UŽP�&"����oook�!"��W�^l޼��ׯckkk�tDD,T烎��j*�ڡr�'""""�nذa>��srrrx��qss̟~<p�@|}}���~�:/^��?�`00c�S���iii�����p��i��m�kY�l)))��瓘����O?�t��-�XY�
0???������'99��˗Я_?Sl�>}X�b\�v�>����/�P�k(k
Qָ�(ϵ���X�|��39v��7�ҥ�=�999L�6���pΝ;G~~>�����K/q��U�y��v�jq��|�E�T�q/T����HE������MJJ��S�q�Å���H-5i�$�����������[�O�<�={��������Y\���y�7L�7n̥K������Ņ��(����޽{III�������L�LM�4a���fm;vd̘1���<cee�7i�$v��EZZS�L1;ֺuk��_|������y����b_z�
]CYk������nf|iy���Ə��_�O?�d���ח?���o�����,b�…��B IDAT�|Y>��j�[UŽP�&"""ѩS'6lH\\]�t�v:""""""""""5�v��			վ�����-�G���{{{ڵk��ɓY�d�)�aÆ��퍋����8991`�BBB̞r<g�Z�l���-������5;88��~����OÆ
MO��������Kݺuqvvf�ĉ�^�{{�R�[���2�stt$88�ѣG��쌭�-��Ό7������L�M�6%88����C�����2�B�P���q�Q�k/�
�f�<==���{�[�.nnn,]���3�����ߟ�����ǽ�ދ��
�7�����R�^�"�+�g_TMU�Bu����T���-O<�qqq�NEDDDDDDDDD�ƩSXXXh�$DDDDj����V����իY�v-[�n�e˖�9s��Ç3}�t�M�f�E�nu��!,,oo�"_��d����qG��Z�X�Iť��3t�P\]]پ}�m���|���n_xx8�Ǐ�Ϧ����Q�0|�p�7"w���p�nݪ��V��W_akk�����S���ב��w��_���gDDDDDD�Lu��������|�&M��/�$,,��s�7~���₏������Y������a޼yxxxаaCN�>��@�nݬ�a�R�&w��[��u�Vk�!"rGz��g����TP^^�G��v""""""""w,-��B�'!W��~�r�
X�x1���:&L`���R�~�j�EDDD�fC����?����c�7��_�Rf֡�M�Tz"��������0�n!"""""""RŴ�BDDDD����g�̙�X��Y�fѽ{w+g%"""w��s�Һuk���+����K����իӦM�����)V;�mr'�S�E��NAD����NCDn�zFDDDDD�΢""""U��w��j���x{{[;
��kﴱ�N`ccS-5Jm��U�ɝ&22�Q�FY9�*��s)�Ç�I��P=#"""""rg҂����´�H���㭝��H����MXX���Tψ�����ܩl��������������������������HM�""""""""""""""""""""""""��k�DDDDj���H�n�4DDD�������Y;
�KEFFZ;�!Ο?χ~H||<yyyx{{�ꫯ�^N�8A���-�Ϟ=Khh(qqqddd`gg���ϓO>�رcqrr��>"""�����ݝѣGW����y�~��w>��ck�""���` !!����y��T���������5i�����H)�����j�u�V�n�j�4DD�.�`��9bz�믿��^��z�-���k1���䥗^�ʕ+����\N�8��'���b�ڵ8;;WZ�����\��M�6QXXȘ1cpss�k׮�8�Ѣ����BDj� """""""bmZp!"""R���0��¬�����]�����)���������~��?N~~~��m�޽E���G\�r��={��Ӷm[���9~�8}�?��+W�d�ҥ���իWY�p!#G����///,X@dd$
4(w_"R3����t�R.\��}��g�tD��+��%Q
""""""""5�\����� 00�X;
�R���k�����i��6�*%"5EDD��S�
0��O�L)u���޾��b\�l�2�^�֭K�n������˫����;v��mܸqlذ���`fΜY��������bcc>|����JR�5RuR
""""""""5�����>Ldd���)Qdd$iii�NC�RDFFj���ϡ;[VV}��=����<������mg��УG����

X�z5^^^��Ջ�����/�u�V�rrr��O���W�^:�U�V���[d����u�&M���_-�ݺukصkW������ƍ�ѣ��Φ�-Z`0ظq#YYY��H�ԤI:t�C�����T���4z�聗�W�LJ
F�=���عs'3f�`���:jŊ����ǭu�ŋY�t)�ӟ�ݻ7,(��ADDDDDDD���""""��&,,��i���N�:�NA�R������m�4D�.��㭝�T���l�N�ʩS�Lm���OPP:�ʕ+Y�~��u^^ǎ�رc\�r��Tnn.3f� 55����NPP)))�\�����4m�4�-[��/��/�@߾}�ԩvvvE��n��|�
999�����X�޽���gǎ�1�ļE��pww'..��i�Hkݺ5������d:w�l:���̙3g�ٳ'�Z���O?e�ڵf����`�ƍ\�|��K���Ϭ�,�L�™3gLm_�5W�\��U
""""""""5�v��;���9u�-[�$((�C��v�Z\]]9y�$!!!�؄������k߲e�|�	�b߾}̛7�M�6��Jjj*�:u"<<�ÇA׮]���g���%���/��燓��֭㥗^��'��W^!""�l׊��366�:X�Sc�1FD��z�"!!���|k�""U̸X��/�4k���`�ȑlذ�y��������������g�}ƙ3ghժ�֭�СC�Y����_��ADDDDDDD���Ri9p���V�NADDDDDD�e0�Ԟ����ݻ�5=��K�.̟?�W_}�]�v1s��
����@vv6aaa�:u�0r�H�$E������puu�m۶,^���Ç����K�����?��Ç9r����|��wDDD�駟r�}�UJ�'N���8֦M��3���s��5~��:u�d�tD��Z#���ѤIbbb�3gvvv������3���`߾}r��q���+�����w�7v+�={�0�|}�Q�w�����믛Ū��B.��>|���HF�e�TDD�\dd��S�;��\�'���:��*���7~Q?z��*�ODDD,�����3�p��e�����믱���vZ5҉'h߾�m�C��H�v����"��u��
��g�V�ܳg�fɒ%���ǧ�~ʔ)S�~������4<==�<�ɓ'��o��С�'O&77���֬YÇ~�|P)}^�t	GGG�c�6c���:t�K�hԨ��S�*V�n]�
Fpp0���gРA<x���L^~�elmm���_y�78~���9
���/��`Z�jd��n�DDDDDDDDj
-��J���MXX����r���?��i��X����\��M�6QXXȘ1cpss�k׮�NMDD䮲g�._���˗ٳgVΪ�y뭷ػw�m-HU�#b�~�Vd�yAA�m���ၻ�;{��a۶m=z�U�VʬY�1bP���Ҟݯ_?�^�Jtt4���f����4ik֬1-���>�ԩ�����1c�1FD�666Zl!R˕�Fz�X�n���?4h�����ؘ��p��qZ�jœO>I�v�x��G˽��X��Z�ԭk9mA5�����������:!""""V���P�;OT��W��p�BF�������xyy�`��^�j��DDD�*۶m��`����L��ڻw�m�_��H����
@RR�Y�񵋋�m����	OOO֮]���4i�/_&  �c�#**�����Ǘ�G�ؼys��O�>
�OL��>�6m
@ff��1c�1FDDDjWWW��݉��%%%�}����O�-�4.�

b���:�����e�U�V9rĬ=%%�"V5�����������B�L`` �v""�*""��)H
U���ީ���9�<cǎ5��7�
6�̙3�������###���ƍ��os����9w�͛7�vzw�?"�À		��Ϗw�}��;������ˁ�GT԰a�8s����cȐ!<��������ٙ�HHH���̝;��~������P>��3�W�n<�������4Z�n
��r���������^�u�����r��>��#S?���;���8�Fd0�L$��9\M�	��R��h��(JNW�㔚?Q�2ĮQ���G51��4牌����fidj)Π���9�r��pP?��9O��{��G�"�Z�A��f͚���r�ԩ5xԬY��m'"""�׭[7���K����޽�ٸ}����/p��I�z�-c�իW)[�l��y���7o����[ԫW�cǎ��;��UDDDDDDDD�
��B��߲j�*z��a�TDD�۪U�l��<�.]��G}Ď;�y�&�ڵc�ĉ9�ܸw�QQQlڴ�������@�j��ܹ�ɒ����CDD�7o��ё�-[2b�ʗ/�g~[�laժU=z�[�nQ�|yڴiðaø{�./��2eʔ!>>�d��ӧOӵkW���X�v-iii���Ѹqc��*V����qqq���ww��7���H��
�QQQ�;___��iiiDEE�u�V.]�D���i׮�����䜿�����cϞ=\�v
���G@@�I܍7X�`�7o���|����K8GGGc���{K�֭[ǽ{�x饗pqq��_$..�u��1h� ��h�m.^�h�T��͛T�V�~���2�~KnP��>'$$�_|Aɒ%�ٳ'C��ʕ+̜9��;w���@�֭?~<�J���m
犋�#22���$���x�5j...Ƙ�Z���<<BBBغu+�O�&44�d���w�2k�NDD&�6lh|߿�o�NRR���&q��Ό=��L�2\�|��]�������i۶-}��e�ҥ�X��+V�ȥJ�*�1⁝�E��ر���d����f����*"""b{�Z��B�
\�p�ʕ+ӤI��mڴaÆ
L�2�)S����ѣ����{���`�l�±c�<x���cǎ�Aꃈ������Hq�R��������u""�-66�>}��:
yH����ٳg�e_}�ׯ_�w߹s�d�����t>��Ç�~�z���̙3Y�~=�n�bÆ
<x�e˖���a��1,0)KMM%..��W���[oѫW/�����o�С�1n�Ν�n������7n��㚿�?���gӦMt��-ߺ���XÚ{`dd$iiiƇ�]��k���ɓ'�1�����Ʋ�~���quu���˄��p��Ec�'�2e
w�ޥS�Nܹs��C����b�;�<���$''3w�\� FK���233��/�9���8p vvv9�1{�\�~��r��c�ѣG��ֻ�K||���~����V�2�ۭ[����/)Q�o��&`]�2�+W���z�j�ݻGXXX��Y���/y�:����…�����۹t��ʕ��gРA���d��]�R�dIV�\i��T�\�V�Zb�sss#::�O?��m۶q��J�*EÆ
:t(իW7Ǝ;��>����T�ܹc,9r$M�6��>�~�ҥK�,Y��yz��m�o=�sv�ؑ>��]�vѯ_?�z�ڵ777ڷo_��—���%J��K�.DEEѵk��/�7���v���ݻw�Q��������DEE�b�
�\8::Ŝ9sزeׯ_��#,,�����$V}).4�BDDD��-]���g�R�re�O����/�6;Xv���̙������lذ���V�X�c���ݻ�={6�7�ȑ#L�4�s�αl�2�
f�˗/`„	t��	;;;>̐!Cصk}��!..�E��pa�IlϞ=ԪU+�ye{����""�Ys�Z�*���ƕ�,Y�ɓ'�����ߦV�Z���0y�dN�8��E���X�x1/^�v��L�>������f�������-[FJJ
u��e�ĉT�V�S�N���Y�n�q�K������;Ν;���/5j����___~��Giܸq�v��6111�9s�J�*1}�tjժ��Ç�4i.\��k������˩R�
K�,a���DDD�����ի�X�"�/&**��簶m
�T��ԩSyꩧX�`���l۶���0ͮ�ai{��#�p)]�4�Ǐg�����`bn偁��{\ƌØ1c��С���_Y5k֌f͚�{�q�R�JĂ8{�,^^^�={��2d��"""�p<x�ɪY�����~�I�M�J�b„	L�0!�X�ADDDDDDD��(������d���g�ʫ|���L�8�:u����@Æ
�����|�c��QLL+W��?��{��$&&�nݺ�&L����իg��y۶m��c�Ν|��wԮ]��7��2s�L��ᯇ��w�Ώ?��޽{��V�8t�qfT�cǎ=Ԙ����I���ȃd�=088�8� kLXX���������Wqغu�1v���_�{z{{���j|h͚5Ƹ͛7���/���T�Z��S��a�c���{k��φ �;w`�ڵf�ђ�iذ!�&M2��5&L�@�5ptt$((�۷o3q�D�T����}��0�Nֵ����������8P��իy�gi{��#"����*V�h��qLL����03)L|���&�숈%�ADDDDDDD�8�
""�PJMM�bŊ�NC�"gΜ�^�z&�
4�w�Q�F1m�4HHH��?&44��� ���s�g����g�5���/2z�h�9�c[ff��}pp0+V�`�…����w�^�޽K���)Y�n��˗��f<��Pf��T���g���hx���ٳԯ_ߤ�p�>w��f͚y�|��i�\g:?q��{K���Ҍ�D�{�=�{��߶m׮]���ͤ<{ۜ:uʤ-�-�G�6�:+i�jՌ�]\\r�gMۚ;�������3?K�[�y���0u�TF�i�n�:fϞm�wSy4���O4jԈo���&M��:y�""""""""ŁV����ݻ4h�j����'''*W�L�����/m�^�������������	OOO��������}���8t�P���",,���<==�(C��}?��jժe��D����h�ʫ�0h!���8H!/:t`�ƍL�2����s��-�͛G@@�W��������%J���{��w9r��+W&88�7�|��+W�+[�,ݺu�$''�k�.Z�je�1�{5w>Cك�����de�=0�
y1�{�������H��{K��|g!�}�6_}�U����&{}�j���y����d�<�~��\��ڶ��^CK�[�y\4jԈaÆ1k�,f͚�����<)�|}})[�,���u*"�SDDDDDDDDlM+\�ds������ƍsl;s�gΜa����|�r�̘r�ܹCjj*7nd�ƍ��dzjժ|��em�#G��k�o��ڵk�0;�<��)�X�r�ʜ<y��cyrr�E�{xxH`` )))lٲ�ŋI�n�Lb���Lf?p����r=~BB��є)S��'O�gddb�۷/�}�+V�`�޽�(Q�-Zc˕+Gjj*W�\�\�r&�r�1FDD��W�0� �@�J�*��/�p��A�6mj,?x� �� 䧞z�_��'NP�v�\����ɩS�X�~�E��-��[�n�:fϞm�0ػw/#F�`ݺut��=ϼ*W��O?�ġC�Lf567���Ύ��L�_�n\9��j��ڶ�����?"�8	

"((��i�H����iӦ$$$0r�H[�#"�1�ADDDDDDDĖ�$�H���͛7g�ƍT�T�Y�f��?p��
n߾�ѣGy��qwwgÆ
���a�:���9^���?��?��R�J���[��H�^�:�7o�u��۷o��7�P�J�"��<�wD�a��/��OFF?����N��v��???>��3nܸA�5�Lgj6x�wHNN&##�@ǎ�=׾}��s�G�eҤI��W��?��t�ܙ�����W���'�x¸�f͚�:u*��
e���~�mڴ��W'%%���ARR3f�LWs24�5k���ܺu�w�}???^y�c\۶m��ѣܽ{�K�.������СC�����-�;~�8G��o�͛77[��͛S�JRRR8~�x�mӾ}{f̘al�Ç(�� IDAT�&+���?���7or��I"""�<~AXӶ�2�@q��ic���E�y�����{�n[�!"""""""""b3p!�ŀ8y�$�=�?�����:�k����GGGj֬ɤI�ػw/O<�;v�`����N��P�dI*V��СC�;w.QQQ6�����k�عs���۷o��qf"����`j֬Ijj*��Y�f�����3��oHH�nݚ�͛`v��e�ҿ�5kƠA�HMM�v�����+�s2�2e
�����?�=z�$�_�~ƁPY@��=�jn�CY�}DDD���
BBB���ٳ���ҬY3BCC9w���ބ��c@�r�HJJ��_�e˖�\��A���IIIӴiS:v��ҥKqvvf���&���V�{��W��������W_��Fn��郏������}�����#�Ч��hժ={�4���XӶ�2�ڵ+�:u,�.���ȣ���߸�������������H.ĦN�:������	OOO���CJJ��x;;�|_�%&&ңG�|�I�V�&L�ڵk&q�v�b�ƍ<������PHݺu��t~��'9�=z������ptt��ˋ����:sh�ܿ��;ڵk���eʔ!00���������:��ի����O<A�F��6m����}��-/�^?Ku�� �q�t��)5jD�R����~)))��ݛ
*���HÆ
Y�~��9��$k����Y��R|��f���pQT��e����/hny]O��$&&���hv���#QQQt�ޝ2e����H�����k׮L�2�g�yGGG㽬��L�6-G|dd$-[��dɒT�P�~��1�|s=Ǹq��С�q�a�:u�1c�`Ŋ&�J�2�oݺ�ɶ�;���ʮ]�r�g׮]���g�y�
r4pwwg�…��ٓ
*`ooO�
�ݻ7�-����[�\9.\H�pww���Z�j1s�L�>��������鉽�=�iӆE���x`�>����t6n܈�����?���/����;7n$===�8����'��dɒ�����[o����ѣ�޽;�K����&O��o�[˚���رc������޸���E�y�5i�{{{l������������md�< AAA�AAA�~�n�Ν��@����s�_~�cs�Y_...&�-ʴ��7۠A��k׮c�	dN�<٢�޺u+s׮]��o�6)��/2]\\̞�T�R��7oε^			����9�stt�ܻw��>����twwϵ-|||2SSSXn������˗3�L���k���W�^�U�M�6�����.s�ҥ��_.ֶ��׳ �߰�֭[�����5j�0�U�V�tvvμ~�z��/��y���7�z��v=3333cbbLΓ��<:����5�lԨQ��k�Ν��5��ڵ����q���_�3g�egΜ������O�$G��
���g���~��Ey��9w�\f�F�2;u�d�T��-���x0w�K/����~�����3f����L���?���K��/�gDDDDDD
%��˗/ӽ{w���=z4Æ
�駟��,X��8S�#G���4���X3f�`�ĉ|������!C�p��]��o����			���r�fΜi��s�����j���D˖-M�RSSy��W�y�&�;w�wޡF�?~���0֮]KϞ=III�bŊ9��K/��믿N�
���x��駟�>}�Ɋ�G�&--�A�1~�x�T�BFF�~�-Ç'%%�iӦ1o޼�[V�~����������Ǐs��a���IKK+p����O��������S�zu~��ƍ�?���|s5�KA����im|VNNN�k׎/����ǏS�F
�#G�p��I����<;��Ê�&�on殧��ύ7�y�qu��}���		��/�$&&�����l���$88�����׺uknܸ��	�Сnnn�:u��3gРAgX<��#R�V�\i�DD[}�������i��#F��K�.�NCDDDDDDD�V��	���?��.\`�ĉDFFR�zu���i֬�|�	#G��ʕ+|��Gy'!!�)S�0n�8������ϟ��۷�ի�1>>>888ЪU+�/_�ҥK��N��V�Z�ל9s�v�m۶%>>�:u����H�:u����m۶���̝;��[�&>>�-Z����s�=g|�u�޽&����x��w�^�:���ЦM��׮]��r��A]��n޼Irr2S�La̘1�5�l�I��[�.xyy�~�|�	/^�]�v���S�vmiР_}�u���7os��}�����g�cp��a�9E�=���f�z���nݚ�;������/�:u2����ԩSY�n�ϟ��[���S����\�Y����0�nA�v�hҤ	=z� 11�2e�0x�`gX<��#"""���_���_�NCDDDDDDDDD�&�…؄������y���ٴiӧO7s��z��MFF;vdƌ&ۿ���
�c_??�3�߼y777�*���͛?~<%J��g*Q�o��۶mc�ƍf�5|��eM�4��ի&�+W���0|�pZ�nM�ʕ�S�N���onY��3�N���_=�y�{�e����x�7r�S�dI&N�H```�y�˥ �c�6>;�CS_|���/���d�9E�=���f�z��T�P�+W����GXX�����6jԈaÆ1k�,��
6,�TEDD�?~<���lܸ����;w���SOѼysH�
l�b����H��ٳ��S�"������={6����NCD�QFDDDDD�Ѣb)))xzz�w���\�
<�_~���ի�|��}�8q����[������'iii�.]ڢ}r����xv�rCn�U�^=GY�R��w�I�ĉ0`���c߾}�_�?���t�ԉ�_~GG��[V�e�����O?M�&M0`/��B������eM����hܸ��}�7o�o��r)H�X{=��ϮJ�*ԩS�]�v������;W�\aϞ=ԨQ��w1{�E�=���f�z�<,�6l�*>((�d�)��P���Y�%tO���J�p����ߘ�#,66�>}��:
��NPP111�NCDPFDDDDD�QU"����Y�s����OY�r%���]��2e�䈹v�`������=jQ<@FF��紴4�\l���p��u�۝��->w������7�-��_eѢEt�֍ڵks����[V�{�233s�n޼���lj���s����k����ϐ�����}�x�<��-��������xs�s�qU��������<W�����[�~s3w=EDDDDDDDDDDDDDDDDDDD��b����O��^w��ͱ�#G9r$vvv,[��ڵk�y����j�
����ڢ���r��l,3<�}�������&�ݯW^y������:u���hBCC�য়~bԨQ���\��R���1l�.�c姠�c�,H|v��_~����pQ��sk��DDDDDDDDDDDDDDDDDDDD��b��$���k�~�n���W_�ƍL�6����\c�U�@rr�E�~��W��㏍���e͚5\�z;;��ܿ��}���[����ۛ�`��;���ؾ}{��V��W�
R��u������>�����~�ǒ�y?�-[���Ã�7�����_M�R�x�����V�sK��DDDDDDD��r��ƍ�s�=���?s��ͳ�0;v�䳟�~~~y�cILQ�^��V�\ɘ1c3f+W�,¬DDD�q�W�Ė�V�HDDDDDD�xӀ��_|�w�y�����W�\���]���ǎKRR]�veҤIy��m۶,X� Ƕ��d������1�5i҄��ۓ��J�^��q�F��>s��f͢D��;�XޱcG�}�]�ݻg�Ͻ{��5k�?�|��[���;;;~�����s�=��
z�
SA��+���{�i�Off�qk�}����ƛS�dIڷo��牍��…�k�''�<�+��yn����8�&����X�����K/���K�QӧO����K/��W�>}l�cP��I�&�m�6�_�Ν;w�x�b���믿���Á�;w.�ƍc�ر̙3��q�"""�e�J}"��[I[' ��aÆ��G�g�^|�E��éW����#..�E�Q�dI��Í��[���>��z��d����~���'���c�…T�X��#G���NBB#F����&�DEEѸqc6n�Hݺuy���y饗�&==��~���7��{�q��E�L�B���M�9g��m�F׮]	�z��8q��'�}�v\]]�׿�u�mػwo"""�ѣ~�!���899q��Q� Ã�:��\��V��
4���H6m�D�=x��^�:ǏgҤI�۷�@��}������&  �իW3e����<7nnn���O�.]�w�����"7y�1�.]��:
�|5m���)�<��QDD����$�q5jd�X#��mǎ�rܢ�[n޼��ɓ�޽;����IvV�Z���KQ�)"Z�d	����:�ٲo�>���������M.�&�������{��lٲ���a�����g�5~~뭷��������
+ԨQ�y��1p�@f̘��3L�7o΄	L�|||�j?~<ׇ����2e
ӦM3)�駉���G��]���kךlwrr"&&�*U�䚿�����k�r��:t�c�������%��\��V������b�
:v���իY�z��>��ф��boooU.ik����y饗�����ɓ�e.��{��F��}�vz��a,���,��������������x��2�������GG�<��r.�…���Ʋ޽{�|�r.\Ȱa�l����f���|��wp!"�O$""""""�pЀ����<�̙3ټy3������ҤIƍG���M���'��J�5�1c����ƍT�Z�>}�0n�8���r�S�n]>̒%K����СC\�x{{{���i۶-Ç�����sv�ԉ��3f�e�~��w�|�Iڷoτ	�U���0��Ã}��1s�L֮]��?�Lzz:>>>t�ܙ7�x�'�|��r�����ԯE�<x���~�͛7��S�fM�M�F@@������Z����c�,�7��ӓ
��S�N���-�_Q}�s�p�B����k�.n߾MŊ�Mn��={6����NCD$_111�:
��ֳgO[� "�oRy�����֭[�t��˗�]�v<�d��
�ƍ
�ȭ�޽{DEE�i�&Ο?���ժU�s��9VM�q�,0��������K/1p�@����A$����∌�$))	'''^x�F�e�9��ꐖ�F\\�7�B�
Ƙ�+���G\\}����ݽ@���ӬY3>��nݺ�������b��~c޼y�ٳ�k׮���C�~�rL�em�A�ar��GEE1v�X|}}�?~��/s��[}"���\�M����`��b�����U�V�j�ʪ}���4h�
*�9k׮�ҥK-�����m/]�4��ᄇ��$7k�_~�zP�[[?��ի�x���A>�%|������zZ�[�������{n���LJ�7Yn"AAA����:
�\����:�J�DĖbcc�ӧ��ӐBp��5^{�5�J������Ʋ�~���4��ܹsY�d��szz:�����\�~���s�C�%%%�{��y���INNf�ܹ�(Q��5�ې!C�r�
�n�b���ܻw����"���_͍7�ϱ��ߟ����i�&�u�@�-"N�f͸s������"�|�2!!!\�x�Xv��	�L��ݻw�ԩP��؃���%22���4�����O$""""""��(��܈�<\]]������f���4jԨ(��B�d�N�<�������۷�P�R%N�8��E���Yg-NLL4~έ<>>�9s�o�>v��Ʉ	X�b�q�e˖���Bݺu�����o�e�ʕ<���߿�u���y��Q�J���ٳg���l۶͸���g�����1"R�T�^�'�|R�FE$�ŋs��Ej׮M||<;w��W^ ::�gM��A�a��[U�Z�={���[o=�z�O$""""""��Ӏyl5m��^�z�u�V�_�NFFǏ�7�`�̙<ؖi��������H.���L^y���^�z888P�~}&N��֭[��a&昘V�\��A���ILL4@ؼy3����booOժU�:u*6l(p�?~<���899gz�z�j���رc�_Of���c#"�O˖-ٷo����bf����7ooo\]]	#11�5k��
�{P}�����Xh�6G}"��GI[' "b+��?�<��ϱ��Ύ��ڴiS�ɉ�X�رcԬYӤ,�CFY999Q�J����?��H�"�|���e�^+W�$!!�f͚ѳg��ORDD�!�s�N>��s����z�*�����k׮�l�򾏟��m�^��/k�={���뛔7h��s���أF�bڴi$$$�����Lhh(AAA8;;�N�>
@``���8q"�����s��]���qppȱ�֭[Ƹ�U�f|�����{����/_���=�6C�!FD��f͚���:
Ƀ��?\ؿ��Q��?]����T&/�ֲ���O$""""""��Ѐyl5lؐÇ��{���_��/����NŊiٲ%#G��Y�f�NSD$W���:;v��e�o�����7���͍�{��3,���u��Νˊ+��̤W�^������� S�����L�2�-[�������ܹ��;wҾ}{�M�V�Y<���ȃ�~��@·2�+�{աC�5k���Y�v-�b޼y,[���Çӭ[7233�<εk���^�ti._�̅���ʱ����Ƹ�а���Y�.Q"�܆2s��H�ЬY3RSS��_
����<z�ޝW�A�a���ř���s޹s'�����D"""""""
�����O?�ٸD䡵cǎ<�g�����|�lذ��K������͛L�<��ݻ���	@׮]�4i�V���ť(�)��y��lق���]�v<��S\�r����ϟ��͛qpp୷�*�9�ݳ�j�"R�*U�_~��4m��X~��A�ϓ���� 00���@RRRزe�/&22�����'�N�b���:_ժU�|�2�7o���9�o۶
��ի�:�+W���T�\�B�r�L�]�r�#"�S�ƍٸq#+V�u*"�[�ꩧ���_9q��k��5���c��a�aggGff&ׯ_���
0�����6G}"��G��DDDD�j~~~f�j/Nʖ-�رc8r䈍���…�p�������w��\�p���03����lذ-ZDpp0�*U��ޞ�e���E�([�,6l ))��)[M�)�6m�NRR$%%1c�Z�jU�cw��???>��3nܸA�5�Lgen۶-aaa=z��w�r��%>��C���:t�1�0���ӧ�e�۷�?��K�.����ݻ\�p��˗�駟��/�:ԬY�S�N��Pf�����Ņ_|ggg[�""�H�-�5k���ܺu�w�}???^y�c\a��,�Ø��L�2|���ܼy��'OQ�z�O$""""""�p�
""""E��ŋ̞=�ݻws��M�U�F�~��8q"`:�؍7X�`�7o���|����K8и�y�����\����_�ܒ��_˻GEE�i�&Ο?���ժU�s��t��%߼��7�z���G�ƍ�P��1�bŊ���G߾}qwwϷ
DD��b�_�ٳ���6oތ��#-[�dĈ�/_>GlTTcǎ��ח������FTT[�n�ҥK�/_�v��1x�`�l�������cϞ=\�v
���G@@�I܃��Z�v�Z��뇏���v+[�,���̞=�5k�P�^=��3�{�����mk�7.�$r� IDAT.���H���prr�^`ԨQ�U+�/��
		a�֭�>}���P�m���9ʬ=vxx89�kذ��}���پ};III��9;;3z�h��2e�p��e�v튧�'�ׯ�K�.l۶���>��C>��������t�ԩ�֡E��ر���d��$''�7�EDDD�ހؼy3III����&�
d|_�1K�0�%�iӦ
���|�|����爳����������<ܴ…���H!�~�:dÆ
\�z���t�=jl�՝;w:t(�/�ܹs���s��y���5j���+P���\�t�Y�fP�N��w�ܹ|�駜>}���tnܸ��Ç�>}:111�/?_�57n�0�G-nܸ��M�
��""�p�9s&�ׯ�֭[\�z�
6�իWs�FFF���f|X�ڵk���k,_���~����RSS���e�ܸqø��˗			��/���?�$##�'N0e���5
��jiܡC�hݺu�mֲeK8p_�k��`Ȑ!�߿�[�nq��V�^Mdd�q��"�����\�����p�Bz��I�
����B�
��ݛE����Q��v�ڕ)S���3���舣�#ժU���L�6����Ftt4AAAxzzboo���mڴaѢE&��;///���s����|�ᇼ��ԯ_777J�(������DFF2u�T���K:v숫�+�v�ʑî]�pss3��!"""�r�ʱp�B:t耻�;ԪU��3g�LNP�1K�0�%�=z4ݻw�t��8::�����ɓ\o��DDDDDDDnZ�B
Ull,���NCD侭Z���)�C,&&�3g�P�R%�O�N�Z�8|�0�&M�…&�˖-#%%��u�2q�D�U�ƩS�g����[��.]��:�tVYg������dv-k���9s���#==�
6��+�ӧO��*�z�ٳ�Z�j���P�g��u�V�s����m���̞=�ƍs��&M�Ĺs�X�lÆ
3��Z�*����U&�,Y�ɓ'�����ߦV�Z���0y�dN�8��E���X�x1/^�v��L�>������f�����3�ƽ�Ҹ��OO�<��駟����=-�X۶U�Ta�ԩ<��S,X����h�m�FXX�~��ܟҥK3~�xƏ�oln?�r+$000��zxx0f�ƌ�g\��СC�r{{{z��A�=�=W^��+/�:�*U��� ,X�ٳg�����ٳ<x�!C����o"""R�T�T����|�,�=�>��~In�pqqa„	L�0!�xK�>���������M+\H�iڴ���)�y�A~~~&��ʷm�@XX�������
2iҤ�ݼy3����booOժU�:u*6l(p���4hЀ�>�(�`k�k�#OLL+W��?��{��$&&�nݺ痗cǎ=������I���<�&L����?ԫW�p��>�Upp�q�E֘����W�ںu�1v����7ooo\]]	#11�5k��
��ji�a�̒%�g#33��YYӞy��m
Ə���7NNN�A$YW�P�@D��BŊMVh�����ӓ��`f&"""Rt�'y8h�)4#F�`Ĉ�NCDD��N�:@�
L�6l�#�������u��	��k�m��ի���ԩS���KfW��漣F�bڴi$$$�����Lhh(AAA8;;[��5._����|v�2C���<z�ݻ��*٬Y3���>�,gΜɱ��|��g�P�~}�rý�ܹs�2��5k�sa�[-��P��ϟ��x{{皣��*Tȱ͚�̋5mkP�Z5�{�ݻg,S�@D������ԩS9r$}��`ݺu̞=��~�y��"��k�Cɛ�D"""""""
��BӧObccm����en�_y<e�#��Uy�q)�����.ߘ�]�fi�FL�<���f̘A�2eh۶m��ۡC�5k���Y�v-�b޼y,[���Çӭ[��6��0㶵��(�s�6C�����G��蛻wd]�"/Y�7��~S�VK�4h����ٲe�5�-[�㳳�=�\�888ߛko�DD
�5bذa̚5��Ç���@D�����|WU���O$""""""R��J�rpp0YUD�a��n�4�!U�re~��':D�&M������ɩS�X�~=���,�g�y��}��h�"���iԨ�q�肜��Ã��@IIIa˖-,^����H�Þvvvdffr��u����V�Ȫ\�r���r��ʕ+g��ʕ+�y4Y2[fRR��l��o�[��V�T�_~���ҴiSc���L�O=����+'N��v�ڹ�0�u�֍
6�p�BZ�jE���s���dɒ%t��%��iϬ�i[K�_ "��

"((��i�H$''ӬY3<h��)"ŏV�(��')�4�B
U�=�ѣ����o���p!־}{~��'f̘��o��3�<Ñ#G�1cF�ضm۲h�"���?~<5j���?�dٲe,]�???�ϟ�o@��ӧ��7��^{�͛7s��Y���;vl��۹sgΞ=˄	�F���므��eʔ����|���t�֍����o���U�fMRSS9u�T�(O�:e����;�c��>|���p:v��mڴ1J|��]�6)))�{u�V���-Z� ..�Y�f�O<��ٳY�r%�+Wf͚5@��[-��_�>���?���/8p ��矧\�r\�x�o���O>���7o��/����=-�XӶ�R�@DDD��W�Nzz:			p!"""""""""�4
�)d}��᫯��_~���y��ߟ�۷���Dpp��6gggF�m�l�еkW<==Y�~}��vqq��7�dȐ!�Z��nݺg���!!!����cE֥�۴iC||<|�|����y�[�Z�h��;HNNα�zrr2P�6ED��Q�l���ڵkӫW�|�
		a�֭�>}���P�m���&e`���$%%���/��4��0����q��m���"##����Q�m�2y�d�mbI{Z���m-�~������9;;��ϒ�����+"""""""""�()a���u�����x�8s�~~~�8���رc���+W�d̘1�3��+WaV""�Wbbb�K����E`` O<�%K���ח��zGGGc��������鉽�=�١���<v�X�������Ν;�ٰaCz���ݻwy�
tޮ]�2e��y�qtt�Z�j��ߟiӦ�F�M���)]�4�������PgV��ձcG\]]ٵkW��]�v���F���-jy4EFFҲeKJ�,I�
�ׯ���7�����ݝ�ҳgO*T����=*T�w��,Z�cl�r�X�p!:t���jժ�̙3M~�-�{��q�W�"""���HZ�j�O<A�%(S��[�&22����899�=-�XӶ�R�@DDD�xh޼9			�NCDDDDDDDDD�Pi��ì�u��1�\�n]��T������ر#ׇwmu�0w�\V�XAff&�z���חg�}���y��-[�)S����?���˛�{xx��C�t��!Gy~��q��1nܸ喞 00����<c\\\�0a&L�3���իT�R�`�Ξ=���gϞ��2WW�|��GW�ҥ�+*�&�{d�ҥ?~<�Ǐ�\�*U"<<<߸}o�&Πu�ִn���xK���=�\[ڶ�]�����<������n�4D���Z���)���7o�ܹs�v�nnn�NG�Kzz���ԟyTi����\>?�v��Q��}��M&O�L������R�Jt�ڕI�&q���"�RD��Ѻuk�����ϸz�*�����6�DݠAg�p		�bŊ����bbb���$88؆����HQS�@��ӣGz��a�4D���çE�ܽ{�����:��VӦM��S�QFDDDDD�Ѥ.�H����(���"**�yΜ9̙3�&+;H�.\ȅx��W�e�{�f���,\��aÆ�0;��+  ��>����"""L��)S����(�����S�Ne�ȑ����u��1{�l���m�����%�D?+W��u
""���O?��O?MBB�ڵ�u:"��#F0b�[�!"""""""�HӀyl���ơ7�={�p��5|||�ׯ&qiiiDEE�u�V.]�D���i׮�6Y"�0�$..���H���prr�^`ԨQ���p��=���شi�ϟ���jժѹsg�t�br�����;v,���̟?�$&+s��;�s���G�ƍ�P��1�bŊ���G߾}qww��B��<Ə���77n���Ν;<��S4oޜ���\��5jԈaÆ1k�,�NÆ
m�����؂�"�;;;[� "E$33��)��{�9._�l�4D[}��!66��i�H6�ψ�����<Z4�B������� �T���իINN��������|�2!!!\�x�Xv��	�L��ݻw�ԩ׮]��^��ɓƸ��Tbccٿ?��Ѹ���{Ȑ!\�r�[�n�z�j�ݻGXXs��eɒ%���t>��Ç�~�:}���7���H��Ҭ~@��z���_s��
���sl�g���lڴ�nݺY�����D�d�T	jK�J�#>X[{�_ �x�ҥ��͋<�bcc����m��Xiٲe�NA����@LL���ԟyTi���Drr2u��5���-^���/R�vm�O�N���y���Y�f
���ƁK�,��ɓxyy��oS�V-RRR�<y2'N�`ѢE6���U�T���=��*���C
q4��a�0�<������a��f���UZf��y
�Q255�#P
"L�Xh�gI$�#������
$�?��{ذ9�n��u�+���}���Ƚ�^fΜIݺuY�r%����رØp�n�:�,Y��d"//���DBBBX�v-�YX�ҤI���qrr��.�줤$�5kV�洤�$M���b�8��a��m�����""��>���C��������y�E�-�������;�CÆ
�Q�AAA����~�z#ߎ;

�e˖8::ҪU+�N�
���ۋ]{���4lؐjժ�Udee��;bDEE�/��€HMM%!!�\�Vx�EE�ۚ'N7'�ոqc�<""""""""""""""""""""""�:�p!w�y�����3�|�9s�3g`}g��r��Y�6mZj���Z�je�ަM�����i����
��7��	&0k�,���INNf���9�W�^���*���m��˗�Y�f�c�4s����lo�5cccINN��ۛA�UY�"""ro����P޸�~�lV�Z55jD@@/��R��W��_��h…<����n��(�rtt,��=z����Ν;ٰa�fٲe�^�����ӿ�2�/iw��������b�o������ǜv��*"r����&//��a���<0����u"򀊋��u"�v��A�.]�ڵk)((`��xyyѺuk[�&"""r�\�~�����{�{�9[�T"��DDDDDDD�=�GN��F��������SO���ʒ%Kh۶-�����v�[�.'O�,5_�z�8t�E�����G��wuu�O�>�\���>���Ç���Ehhh��g���믿i��m���;���Ŏ���yDD�'�>�,�u""�8p 
6�u"Ub�j{EĦ�9$U�N<��z�*ӧOg��xxxP�^=����6mW�^��勈���)��SNMMe˖-����U�V�8����&""""""ro�rǥ��7'\X{'t�Ё��,X@pp0�>�(�/&66�
�~�z|}}���$88�9s�мys��ә7o�:u�p�}��%##�)S�ЫW/�x�	����w�(((�̙3e�sss�������ӿΝ;GHHH���Z�M�6��>}��ĊӧOyDD�7o��o���y`����:���L&�;2��n��2d��6t�P֬YCDD�ƍ�at""""�O�Z��4i���;v���H�5�{�v��;�n�p�ꫯ���Α#Gx���ر�1���_7�
>��
����ȑ#�f�ȑ�={��
2r��
�=|�pBBB�ܹ3�۷'((��ˇ���~~~��ݻ�k����h�":u�ĠA�x��G+}����С��Wa��L@��`gg��^z�u׿���m��)R%l�oI/��������d�d2q��v��رc�c999,Y��>}�о}{z��Ͳe������>�d21b��k���`2�غu�Ez�>}0�Llٲ�(�h'O�dܸqt�ؑnݺ1o޼b+_�t�ٳgӭ[7|||�6m999��-;;���ڵkG�:u���{��DLL��ٕ�;���߿���$[�!"唓������ܹ3=z�`�ܹ\�t�"ϭ�
۶mcǎ���ooo^~�e,X`�OSآE��ڵ+�-*�=���X��ggg�p�B^z�%#���P�\��Z_�ƍ�X�???ڷoO�Νy��W���/��k"""""""�&�p!w\�	�}���;��ݝ���.]ʾ}��v��?�8#F��[�nF��5k�'�|�Ν;�t����t�֍�_WW�
�����C=Dll,�N��A�t��ɘ�0i�$>��cΟ?o��da'N��ޞ�[�r��UL&ӧO��_��}[+�gϞ,Z��={�0l�0���ٳ�w�^��8::e�0DDJ4h� [� R���뇿�����Tttt��Qr	

%;;�薛��رcIOO7�;w���p���X�t)ݻwg���;v���jԨ��-[��믍gc�/_��ٳ899ѱc��3f���\�v��?��7n��dgg3r�H222�s6o�̯��Z�Z_}�999���;���CJJ
[�l����+��Z�h���$&&�:)��� ���ܜ<Ϸ�~KTT...y+�w���������Y�r��Ο?OLLYYY̞=�j|~�!QQQ�hтѣG�z/\�|��ТE��W�\��^3��5�MJJ
�����[�t)�}��q�<�=�ѣG���_	�_��i…�qE����6��^�z���Ga���L�<��|����N�ӧ}��)�z=z�G��*��ٙ)S�0eʔ2�羭��������ʕ+��Ƞ~��dddp��!ƌc<|��8���:���^����<M���5i҄��p���X�z5���<��SL�:OOON�>Mpp0)))$$$Я_?�~�i�=ʡC����!??��۷cooORR׮]�z��Ƃ3��J}^֨Q#fΜIݺuY�r%����رØp�j�*222hРs����ˋ�G�2cƌb�2�*߬Y�b��iIII�'"����7�gϦ��@;E��N�8����iݺ5ǎc���ddd�j�*��?Y�l�	`͚5L�2�޽{cgg�ѣG3f�1ᣨ��P���iҤ	K�,�ڟ*�{Xa����i�}��N��~��̙3�f͚�������9y�$����7��}�u���d�L&yyy$&&�ڵk�	ꯉ������ܻ�m���;��c�=f��{TT�02y�L&�WY����ƀA��[����4i҄�3g�[@Ƽ��y��������E߾}�v�{�����o�.]J�}���4lؐjժ񲲲��;w�`�ԩ�h�GGGڶm�_��b�:q�psGQ�7��#"r;�oߞ˗/���:)��� ڵk���#-[�4&|�ر�X���v��ͷ�~K���ٴi}�|�ps牢̓-\]]���quu-�888ЦM>���b}?�=ѲeKiժS�N`���@�z�	!QQQ�����/�0`�RSSIHH0�PMDDDDDD�ޥ.�U��$���]"�l���̜9�7�|�W^y���/^L���m�����ܦݩ6(==�aÆ���/���ؾݚ7nзo_Ν;GXXm۶-�E�"�g-oIm~�j�hԨ���Ke^�N�v'N��iӦV���ƒ���\�@}� IDATqРA�?H����ݻ���'--���,j֬��O?���;v���m�t�����Ha�mfgΜ(qGړ'O������q[�l�Z�j�7�/�����������4����ܹs�qxzz?�޸q�H�駟hٲ��ymڴ)v�˗/P�f�b��i�<""�C�֭�^�:���+����֞���h�V�Z��Vپ�ŋ�8q"ǎ+�����XZtt4�����/��w��Z��~����ӟ���ӧy����{FF�{43��Ξ=T��7a�f͚Err2���,_���#G���o�k"""""""�.M��
y�g7n,`�����+""wN���i֬ǎc�޽��ٿ?�Ν�I�&w�������y�pqq�瞳uHV�����ڵ��҃�t�R֮]KAA���ˋ֭[� Ry�\�~�3f�m�6��_~��ݻw�{�n�w�άY�,V*�������c��[I�K�l*��gm�_a�՗�ԩC�V�8r��/_f�Ν<�쳸��ѦM���KNN���n�77�R����h�lggW�9���=�P����M�7�Y+CD��899a2�ػw/#F��u8"R���s���X����ϟϱc�hР�=�����hѢ�I��[��k׮�b�
BCCK-��Օ�ӧ3|�p�͛���[������
�����ooov��Ɇ
8|�0˖-c��Ռ?����ꯉ��������4�B�Zw������?����CDDJѿ�ΝK|||�.֯_���_�˪�6��u._�̢E�HLLdժUw턋]�vYM�z�*ӧOg��xxx7�yڴi������|'����϶m�pqqaԨQt�ڕ�u뒙�Irr2+V�`�֭8::2{��J�a�
���W{,"�����ӧٸq��YQ�=zp��!>��S~��Wc���;����'�|•+W�=Я4
4�ԩS8p#=--�X^wwwΟ?Off&����233�<"rk�a�l|��]^>>>|������A����ȭ)��e�}��ſ�����GY*�w2�4nLP8u�q<??�b2�[o�E�ڵY�x1�w�&==��͛�ZƓO>�+��Bdd$���<��3��a������СC<��F��C���1�l_��Օ>}�ЧO���ٶm�~�)���Ƅ��DDDDDDD�]ŗO�
3�LV�+���={�������ŋ��|�2�w�z����Kw8²ժU�I�&X�r�n��2d��6t�P.\�@DD�
#��ݡC�HLL��Օ��H�W�ԪU�^�zI�Z�HLL�ȑ#���Q{,"�a0�����߸t�}�&���c�y�u놽�=��9�1�C��Y�__�[��^ 88�����w�}��_,oӦM8}�t�c�4s����ۛcǎ�Kӯ_��n�U�ɜ9sHKK#//���F���/�܊����Gnn.ǏgڴiFzVVV��<���,_��\���k�Q�~}~�����,���e���9r���|�9¼y��ԩ���2}��}�b2����NNNO<�^^^��fꯉ������ܻ�Å�������CHH;w�z�����?�jժy�m�F\\Ǐ�ڵkԮ]___ƍG�5��[�����e�Ν;���#�����ۗ~������K/�Dll,7n��W_-�_|A~~>�z��f͚�.�(�D��+�]�t��?��]�vq��U�v��ԩS+\g�������srrX�r%[�n���v�ڼ�⋌5�b����WI�QZz�cE�eggC�v�S������d2�+��bԻ��T���7))����n݊��;v�7ޠv���򆅅1i�$���X�b��ل���}�v.]�D�ڵ�ڵ+�G����Ţ���?,[����$�\�B�ƍ6l�z���W�mUy�mذ�aÆѸqc��V�V-Y�x1�ׯ�e˖�ϒ�@k�fy��|nLL���9r�jժ���3a�c7��փ�c)�#F�s�N�9B``�ű�ի3q�D㽻�;m۶%55��M��/�5��駟x��'�\�<ٶm'N�`���FzϞ=�
��С�v�"--��f���H��ͻK�
:v�ȴiӌ�9�1�YE�6�7oΈ#,Қ6mJ@@@��V�����Kbb"3f�`ƌŮu��q����:u*���������ôjժԘ���y�3fqqq��ߟ���>��۷s��F�iq^Æ
-�*��>|8������bq��2��DDDDDDD�]��BDDD��2e
������p��e����裏��˗/��w�%55�+W������牉����f�ҥ��o�̙3��呓��ѣG�;w.QQQF>�V�			V���0`��
�_���lF�IBB������y�f����}���.]�ĂhѢ�����\Ǝ˧�~�ٳg����ܹs���3a�nܸa�-o}U��������b_������Ö-[nK�""�>���7r��5���HLLd�ȑVW�

%;;�8q��^{�5֬Y����
���fԨQ����^�|��Ç��_������|N�<Ɍ3ظq���v�U��w��a:w�\j��W�<x��-�gi*R�fcƌ!%%�k׮�����Nhhh��A�ȃ)55��d�Ҹ�����?888��ꊯ�/����V�ѣP|@��sռ��rrr",,���憓�ݻw���UϞ=�Q�{��)vlϞ=���н{�*�KD�$����5k���ED�0u�Tz�쉓��j�b����Y,T����y�z�聳�3NNN�hтy���I׮]k���-[��?�(�.m۶eРA���o,\��H�Y�&4�:u����@�:u:t(������Z\��}=???f̘��O>���NNNxzz2b�f͚e�SMDDDDDD�ޥ.䶊���X]RD�^g��>��/�����1111�ر�ɓ'�ێ|ʔ)���;;;�=ʘ1c,��Y�nK�,�d2���Gbb"!!!�]��X���ӓV�Zq��a��X�D}�Μ9C�f�h޼y��/˪U���ȠA�̝;///�=ju��
�W�������E��իIOO穧�b�ԩxzzr��i���III!!!�胔��*�������h֬Y�s�iIIIƤ�u{��e��Ŵk׎cǎ1m�4Ξ=��ի7n�E�&M�n�2��g�q��)�ׯϜ9sh֬���L�>��'Oi\��O?��ŋ4oޜ�s�R�vm>��C֯_Oxx8�{�nO[U�|?��3@������.\�p}��U��5kԨ3gΤnݺ�\����pv��a0.o=�=��J��ruu孷�⭷�*�:~~~���K�4i�&M*�ܒⰖ���3e��L�Rjއ~V�\IFF��� ##�C�1f̘w-��3�i^��>77���z�O?���z�?���̞=�K�.1~�x6n܈��}��aɒ%��^�999�7���X�U��K/�������]�r��s�KFF0}�t�W�^,���Y���9�[o��7�|���3d��<���;���7n0s�L֮]ˏ?����O=�����F���oLD�*܇x���˝���j֬Ipp��c�w�V�ԩS��\���w�y�w�y�X�#�<��ɓ�g�h_�O�>��ӧ�몿&""""""r�҄�����4h����r%M(�^�����/4i���_���.]�d߽{7;v�M�6��?���7��6�Q�W�\!**�S�N���ˀ��*
�߿?�&>>�"����X�S��˲s�N��b�)ڶm�_���|��r_����-[2f̘b��u�V����W�ps��̙3�ׯ���� ֊�WU9q�ps�hQ�7��#""Ucʔ)�N-[�$((���dzcǎb���;v� ((��-[ЪU+�N�ʟ��g�o�n\c�޽��A
64�+���h�ʛ/77��*���y�����*R���HݚM�<٨ۀ����-v�(o=�=��y���(c0aTT�8:��۟��g��Œ�s�̡I�&,[��x�����g�}���=�Ώ��4�^���{�r���ܬ�y��5�t�b���߯��
{{ˍ�+ge��ҥ���+''�+V��o�Y�_Ԕ)S��_�j����%99���d����5)ND�n���������Ƚɾ�,"�EAA�^z��}���?����#�<��7���/2l�0�
�ܹsY�v-�N�,BN�0�jժ���̇~��	�ڵk��|���y�Gؾ}�1P1++�m۶���BϞ=+\~Y~��'cP�Y�6mJ=/55���T�o�NӦMqtt��_�:��̙3�͕�L&��2\=y򤑷"�UU._��\��(s�9������g��U�����֭[�k�
3�7���nN(��v�={�H3�ܴi�Rc�mUy�թS�s�Ε�����H}����ԭ�����yU��}��փ�cy�8;;3s�L8w��Ν#!!��3gZ�>/"U/%%�Çs��UfϞ
��q�ppp��������{��q��b���lڴ��ׯ���D�ƍ���Y�pa�e.\����T�}�Y<H^^�}�;v�믿&<<���LYM�6��'''ǘ�l^��s���]͓16o�������fٲe����DD�uꯉ������ܛ�Å�6�/6V��_����:�Kݺ�<�-���m���9v�
4����ӓ-Z�-�G�x{{�s�N6l��ÇY�l�W�f������ߢ�޽{�z�j6m���ٴi�����������%y�Ie��m�������>|8�����͍.]�X-�$�w�H}��mgg�o��2�_tu��i�<""R5��3���>��j��^���~~ߎ����ڴiùs�ضm���j�1l۶��_TE�2�խ�����.o=�=��3�<øq�X�`�Ǐ�m۶6�J���OL�0�3fp��U>��c��;�ìY�,v;5[�l/��>>>���ѣG֭[�ܹs��i~N�f�~���мys"##y���Y�z5�F���8+S֒%Kx�'�8q"�~��]]\\���$44���~���?��?��O��'"r/QMDDDDDD�ޣ.�ٿ?qqq�CD�J����3Mn���d��Ù0a�{��8���o����J�>}X�r%�}�Ç'++����b�����Ύ
6�-:Ѡ"嗦A�8p�"=--�\�<�䓼��+l��a����\mѼ3F�WJJ�E��ԗy�寿�j�^}�"������,v̜f�#""e��Y_ԑ#G,�<x�V�z��p��!�t�{s�P�n]��6�v�U��gn�#""J�����>0v�(�V곰��mE����ȃ��ߟ��p�B�j�pD�'��]�E���?�p������}ǎ��?�Y�9?��M�4����x�wX=z�h��Y���z�)��Z�j�O�X�`���lٲ���~���~���`rrrJ=OD�^���������ȽE;\�m���OTT����e����:y@�۷���S�N1{�l#=++�Z�jѷo_222�2e
�z��'����7`�"�YÆ
i׮)))lٲ����m�ҤI�J�_�^x�e˖��ٳiٲ%'N��߯P=���klݺ�����˜4i�q�K�.DFF��ɓy�'�����իY�j&��+V�����ܸ|�2�����ߟs��Rf�vvvp��6l@ӦM9�<�O�.6�����F�:�>s����'���ѣгg�2���%22���`�̙C���IOOg޼yt����ۡCbbbX�`���<��,^����X4h������V�7_�V�x饗���/5j�G��[�n���s��E���k���\�z�^x�֭[W�>����R��U�zP{,"""w�����t�r�_��b��_��k�N+ge�*��\yw2d={�$>>��+W���DPP��;vl��#"""""""""R�4�BDDD�.���Kbb"3f�`ƌŎ?~�Npp0!!!�&���x���IIIa���0���%00�m۶q��	F�m������X��μ��{�3���8���o��=b�v��ɑ#G�8�z��L�8�x_��eݺu,Z��E���~�5������`�ƍt�Ё]�v���V�wb��2LED�d�j�bĈi͛7g��e�;|�p�o�Ι3g9r�ű�
Z����lݺ�#G����/[�}��׍�oG[U�>@PPׯ_�믿&44��.X]�ta���V�<�i�
,�"u[^���"""r�طo]�t1��޽�f͚�xN�ƍ9q�?��#�5���U��.]���~��
����ƫ��ʫ��ʷ�~���|�[o��	"""""""""b��@DDD�~���Jjj�-]�wޡG�8;;���D�-�7o�1ia�ڵ���1c��|�I���prr��ӓ#F0k�,������ݝ����ԪU��K���_'''���0`nnn899ѽ{w���*\'m۶eРA���o,\��Hwqq!<<<<<ppp����XE��j�孯�'2`�y�������)qja�&M�~��888���ܜ\R�F
���S,��={pqq�{���)Yhh(;v䡇�N�:6�+VX��[��5k��A��S�ԩS��C��������ݝ��z��A͚5qtt�Y�f|������w;ڪ�����		!44�N�:�裏boo����;w&44�����T�V��i�
���-��փ�c�W�=�������Ǟ={��C�-�?��͝�8@~~>�ϟ�w��Ύ�]�VY|�)k���$''�xM�������鉝�˗/';;�V�ZѪU+�r��EDDDDDDDDDn����[!���������P�8q�b�La�������4�N�&"� ::�����f�r�P{&UeŊ�\����x�ׯ@FF���c̘1�5�����Ύ��(���������&�	�'>�M�[}�=����wk�C�~�Կ��EGGW��'	�c*���|e�ߡC���,�L&���C��խ�������7Ǐ/g�5ػw/mڴ��8+SV�-�ݻ7��ͳzͺu�r��5jď?��'�|R�.}��aÆ
V��<H�=������k��ĽП��{����O�~�mv��eu`��Y�t)k׮���������E�֭m�����nÇ��/�$**�ɓ'7���� 00��щ��<���_��㉏��u""UnÆ
>�-[�P�N����>}�1�šGy�o���ٳg�~�z222puu�s��̞=���~���LY���|��7%^�>"((�3g�p��uƌ���#�1���<����˼��Uv?"����<-�&"""""""ri…Hڵk���W�2}�t���~~~L�6���8����d�"""r8;;3s�L�|�M^y�X�xq�&DDD��=�hEX��,*鳩�����|��*��͍?��?����V4��eEDD�f����ptt,v�!C�0dȐb�9��#G�Z���OTT�v���4�Bl�d2X��~��,�<:t(k֬!""�q���0:�]�y�ƍǂ?~<m۶�qT"""��"���,����uR|||��������u8"��ŋ�w�^[�!"E�?#"""""rфy`]�x�xy��U<==6lS�N,'����r�J�n���?�L�ڵy��5jNNN��&��955���lbbbh׮u��1�<��c�L&bbbx�W�Y�杸m�����u""���y�-ܯ���X�����m���.��r���V�Z�۷O.Dn�����>��]B����&\���_eԨQ���OF���Ǎ�����2v�X��Ӎ�s��NZZK�.��޾IJ���+rrr���)v��LJ���l�B���o�DDDDDDDDD�_QQQ�<%r���&  ��aH����C�$''��o�:�����?QQQ�CDPFDDP�x IDATDDD�~U�(q��XTT?�����#<<�}��f����իIOO穧�"::����K�֭III!!!�\455�x���@�f͊]ۜf�#"""""""""""���


l�m��'�i�0DDDDDDDDDDn�v��;�d2�+�����c����hٲ%m۶eڴi���y�n�
@pp0����I�&̜9�~�����H�~�J,�ĉ4jԨرƍ[��xxx�:�[�	�@:}�4mڴ�Ho۶m��gΜ�O�>V�u���R˺|�25k�,v̜f�#""w����R'׉��HՊ�������a��*..��!�=��x�yј��+rna���$''���͠A��$^��T�?c͉'hڴiU�t�n��**77�^x���,\]]ټy3NNNe�u��T�SDDDDDD�b4�B����Šn�mggWf���\�R�q�5���3�Y+WDD�yyy��ADD����'>>��a����Qd�ҥ�]��������[��uh""""�z��ٵk�M�{�ܹ���,���عs'=z�qT����8M��R�
��?���Ç���`�>|�X^N�>�ƍ+�����;�ϟ'33www�c���F�;EEEe�0DDDeMz����«W�2}�t`<����cڴi������\a������v�uV��	 6l��_�/� !!�\.�T��s�������T�&\��{���d޼y̙3�'�|�cǎ1o޼by�t�Bdd$AAAL�<�'�x������^��U�Va2�X�bps����Μ9CÆ
hڴ)�ϟ�����&V�>}��#""w�ŋ�w�^[�!"R�7�x��;�:�[�]�D�nk��l�����…2�H:t(k֬!""�q���0:)����oqss��w�e�޽������u��:<@}N�ʲ�u"�@�ƍ����͈#���W_���w��#F��q��9r���@�}�Yz��ɪU��^�:'N4򺹹7W�ݻ7:t --�ص�i�:u��{����~���l��H����8s挭��qqqj{EĦ�9t�9s��ڵ������}�Ү];���m�;v,���x{{���/�`�rrrJ,�d2�=�.]���ٳ�֭>>>L�6��5�������]�vԩS�H��0�L��Đ��]�[)��}����,YB�>}h߾=�{�fٲe���y
������s~��8@׮];v�Ez~~>��ϧs��t���X/33��S�ұcG�t��{�ǯ��Zb<�'O�dܸqt�ؑnݺ1o�<�^�Z�{/,!!�7n��/����/���7HHH(��a-N��/2c��v�J���	d˖-��'�9EDDDDDD*O;\���b�9ggg���X�t)�w��ʕ+4i҄��@f̘�������Ņ��p�����c�.\���?L۶m;v,�?���wҤI|��ǜ?�x�ֳgO-ZĞ={6l�E{���Ņ�ݻߙ�J�'**��a��������!�T���(���m��<����	�uR�6l��d��o��ȑ#�l��8v��222x��giР˗/g�ʕ�?�������={v�����f�ȑdddi�7o�h��W_������O�c>>>����e����_�[��\�z��/ҠA[�"�H%77��cǒ��n��;w���p���X�t)��%��X��CCC��ζ�0�|֭[g����F������3���5���K���y�J��1cƐ��i����s��
���*{AA_|���(_�>}���a�ƍ�5�B��~��WF��O?�d�?~��S�V�����<�p!�Z�j1c����k�������M�6Ԯ]�"���+o��7nd���l߾�XL��ѣ6l`���|��W<�����s��!���:t���@jԨq��VDDDDDDDD�e8��_Z�'&&0`�֬Y��)SHJJ�o��O>n.�R^�V�"##�
�駟�o�>������MJJ�Y�fŎ���yDD�EÇg���CD�Xe��դ����SO�������u�֤��;7^\/55�x_��kҤ	III�&�����f����c��������IJJb����޽��zhԨ�֭#))��#G�cǎ
߻ٷ�~�ٳg����'����///Ξ=[�����駟�W�������D��ܓ��"""""""��	�@�ܹ3&������deeq��
���1k�,c�EU>|8�=�����QQQxxxX�e���������<(L&�ū�t___jժ�֭[��� ??��[�R�N:w������Ҽys6m��G}�|��+W��Ν;�:u*-Z���ё�m���X�'N7�ոqc�<""�"���m��P�>�֭[����4i�̙3��M\-Ie���ɩX��)Sx�'prr2vļ~�:S�N�Q�FT�V�W^y���4�'O�aÆT�V���.++�ұ�'`�w�0�۷/6l(3���%���hٲ��{�6mZ��I}N��{�������U)55�^�z����BBB,����+�TgggfΜɛo�i<�KHH`���T�^�J���'NдiS��bcc�/ý��4hНMDDĦJk#w��M||<iiideeQ�fM�~�i����رc��m����+bV���Ý���]�6��ތ1�z���R.\��+)))������ϟ���[�fQ�ꫴ�gy�o$ro{衇�۷/�ٳ��]���7ߐ����ѣqpp��ŋL�8�cǎ�FAAA��駟hٲ�E���^._�@͚5�3���܋|||��矫�O&"e������QΜ9@�>}��s���R���E��Q��񳧧�񳳳s��V�<WWWnܸa�U$���l�o��…Y�pa��;v��ʕ+����+�ӧO�/m۶-��I}N��ӄy �W�شi��׿��ͥnݺ�oߞQ�F��ke=��3�7�0~��R�����no��6�v�:x��,]���k�RPP�����u��6�TDD��*���~�:3f�`۶m���w�f���t�ޝY�fY]��Vʶ���\Ξ=˺u�ؼy3K�.-60�"�M�Ɓ��/^��0KUu����ݫ���&�����O?�/��k׮$&&booO�~��<����رc4hЀ�{OOOZ�hQ�IV��E'i<�P�G�vvv��ߐڜf�#"r/jݺ5իWg߾}�p!bc飔5ٴ�ݿ*s~IKW�V�j���Sy8::?[�gU$�͛7���[j��ׯ�y�fP�8��QZ���{R�SDDDDDD��4�B�Z�sp���=���Ɩ�w�-�)ɮ]���_�z��ӧ3`�<<<���cڴi���Uh�0�{QIm��϶m�pqqaԨQt�ڕ�u뒙�Irr2+V�`�֭8::2{��*+�NO�(\���׿��ҥKINN��w�eݺu��9r��˗��3ϐ��_%1����gy�o$r��W����$%%�����ݻy��,_1�d����N�2����[�XT�
8u�����HOKK+���ݝ��ϓ������ű��L#��Ƚ��ɉv�ڑ��̈#l��}���!+�G�������lܸ�[�"n�|[�H�			,^�آN;���x�
�=�A��������0�>\����>�������H�Un��`2��n�~/����…2�H:t(.\ ""†�����ΡC�HLL��Օ��H�W�ԪU�^�zI�Z�HLL4&��U�ƓO>ɇ~���?��37n���,L&�����	�NR�H�ҿ~��7F�Annn�����Gnn.ǏgڴiFzVVV��y�������w����k^����Ŏ�Ӵ"����ڷo�޽{m���"}�.]������߸t�}�&���c�y�;#�9s�R��m��?���c���O���^�}��4jԈ��t~��r�߽{w�͛GZZ���=z�y��U�����<�p!"""r��'b���1i�$���X�b999�\���[����?S�vm^|�EF�e1�ƍ����e�Ν;���#�����ۗ~��Y�W�k�b�955���lbbbh׮��*��=�&����^y�j֬y{*KDD���T�a��
F�ƍ��R�V-Y�x1�ׯ�e˖�IJJ"$$��[����Dǎy�7�]�v�e��,;;���0�o�ΥK��]�6]�ve��Ѹ���NLL���9r�jժ���3a„r�����Ȉ#�:u*�w�fРA�ע�׮];�{ڶmqqq?~�k׮Q�vm|}}7n5j�(V'���^Z������D�?�:u�N�:\�p�
X����Kbb"3f�`ƌ��?~��Օ��
d۶m�8q�ѣG�={�,6ȭC��ڵ���4ڶmkq̼�t�N��}�""w#ooo,X@ff&�<��y`U��2b�v��ɑ#G�8V�zu&N�h�wss���������ƍ+t�ݦ����2ĘtR���C��> !!���~���ؼy3?��c���>�������H�i��;$44���lc�^nn.cǎ��O?��ٳ���q��9��Ù0a7n�0�]�t)���8s�yyy���p��Q�ΝKTT���"״櫯�"''��"rrrزeKՈ��ȭ�Sm��Ç�ܹs��:v�������ظq#׮]#++���DF�Y���ͮ\��k��ƚ5k���C~~>�ϟ'::�Q�F���S�1cƐ��µk�������?'44�B�n��bE�[�W��˗���ʕ+W�����!$$�B1�Wy��Q�H�ޓ��ju�����1���ϯ��w�y�=z��쌓�-Z�`޼yƀĵkז+'''���0`nnn899ѽ{w������ٳ'5j�`Ϟ=Ŏ�ٳc�c�{Uǎ�֭�/_�u("���Q\\\���puu��ח��H��&M�D���qpp 77����m�{^^�6m��Օ�^z�����ԬY�M�6���Wf���΄��ѧO}�Qz�!����={6@�v�T�SDDDDDD��Å�V���DGG�:��B�&M7�Y�z5���<��SL�:OOON�>Mpp0)))$$$�֭[��%K0�L��员�HHHk׮%  �B�,i�줤$�5kV,~sZRR����M�$""R1w��������(5������…Ŏ�ݻ�ŋӮ��޽�UU���H�e�/e��S����Ўڌ����t̔����f΄���ұ3�g�-5/d(�G
I�<N0���N��!����?ar_����#�w}�Z��N�{���W�N�RXX�~��gmڴI�����7��ٳj߾����?�{��:y�,Y�3g�hÆ
.�N�N��l�2=��Ê��Rtt����W�C5�y�$I��򋹭*�g�;���xIҢE�4j�(YYY�ĉ�1cF��TEy����F@�4}��#:ߩU�V
/w=��O���v˖-�h�"-Z��¾-[���������������K�rrrt��q͘1�<�ܫz�!
U����Q$���I���Ӽy�*�����5|��j�_޿�k�^��l��-�������S���o߾*�z�,f\;w�$�g�,oݲ��	@�Qp�:3k�,�C46����~�M����#O�޽[��v��I�]��l�2���hǎ�ߥ-Z�Е+W��g����K����-���l�,�O��t����:w�\�
A}��4��٬Y�_����-Zd�)��'�Thh�fΜ�}��YHT��Fhh��|�II�SO=�������ڻw��.\��;J�]�5n޼)��9��y��/��R���:u�>��3�����o$ݞͣ.T�}�g#�e���ھ}�bcc�p�BIRll�\\\hp:ԧ�����@�-������訬�,���뒤޽{Wk�|��z(��'���L���%I���e�?s��9s���W_UZZ���Ҵv�ZM�:U��������6�r��%I�Gu-��f�@})���T�X_�#۴i�s���ܹs�…��������Q�u�^�$I?��S��.oO=�T�v�?����:]�t1����$I�u�V��{��I��������մݹs��ԩS��*\�
�}���@}qppвe�4{�lM�4I��u�V�Y����Kh�~���飏>�ʕ+�r��˜��˝��n��	@�Pp�:�f����jU]=�{O��M��7}���[Hw?�9������������O?շ�~�w�}W�6m�̙35v��*o�,VVV�$kkk�e�6S���ٻwo�;wN{�����r��ٳ�ܿ�ҳc�
��[P��ښ����G�J��u�fn��y��U�V�ԩS�С��y�u��E=z�иq���_\\l>��#UU�
��ԧ>}�(88X�W��$͜9Snnn�@}3�R��g�����
�������6mZ��<T�9�:
.P����kt����8���������m�6���ܵ����������'OjϞ=��a~(���,�u�����U^^�Z�n]bY^^������F�~~G�;V;v�PLL�
��{̢����7J�|||,��������رc��Gy�JYڵk��QǏW�~���Ǐ��j��ܸq�<���������U����$I�����3Ξ=k^^TT�f͚���J��źz��%Un��T�}�g#����_���F��������s!�9���BU6d�IRhh�233u��M]�xQo������d�;z�h���룏>RAA��q���J*9buU�i�9;;��ֵkWIRVV�E^S��
A}��|ꩧ4r�Hhڴi����?��O)77W�6m�K/��k׮��S�^�,����k���PQQ��;���pI҈#*�wi�����p������H���Z�b�$iРA�?�w�믿*##Cs���?����ۗ�[��z7�Raa�233fn�|��$��1�l٢k׮��ٳZ�r�]�[�9���Fд1��A�L�����+==]���%����k�ܹ�ד'OVxx�V�\i�`��}We���κt�ƌ#m۶MPJJ�222,���ȐT�qPS��;R�]T�믿�/�PDD�""",�2DK�,)3�<�)S��h{�'4~�����1�ݻW��ٚ:uj�e;v�h��;gḓ���^��	U9�����Ҏ;�t�R-]��byff�<==��奏?�Xo����|�MI����]�_�9���Fд1��$ww�r 1��ӧ�]����y��i޼yJJJ��T��8r䈎9R�u-������FNNN���҆
J��<f�-]�Tݺu�������ԥKM�2E���j���`��o�^666*,,�t{��-Z�y8 GGG
6����:S_�#%���N+W�TDD�
���_���rvv�������j޼y�Y#""4p�@5k�Lmڴ�/��u�������S�V��q�ƩM�6���Q�6m4q�DmذANNN5=�%��S�N�0a����խ[�˫r^��?�IÇ�������ԣG�X�BӧO�$%&&J��Ν+___�w�}������g��-w*�V�}�g#��u������_����Q�R��������!  @�[���TlQ�c���󕒒Rf�cǎi���JLLTqq�Ə���~[�z�2 )д���)  @�_��_��~�Օu��)**J[�lQ���%I999���ь34m�4�(���J����/�5А5��oC�7(���FM��k���i����-//O<�>��#����7:p�)�븸8##(�g�qift�
�!����2ۯ]��%K����W...�n�����d988�gL@2y�dm߾]���Z�p���7�\\\hp:���g#�a`�Wh��>=��JKK����f�t�l� IDAT�����15
.`8F�,[LL�Ο?�	&��&N����x���(88�t����A˖-��ٳ5i�$I�֭[�f������~��h������%�����B����E�n����k�.�;wN����ҥ�F�]bT������EEEi���׿��|P���o5m�4��ٕ�Q:S~~�Էo_�i��ܧm۶rwwWBB�&M��V�Z��	4y}��Qpp�V�^-I�9s����N`>�}�*,,4�/P=k֬Q\\��1�R\\lt@-�����7�_߸qC'N�Љ't��UT�_aa����t��Is�s��)::Z������u�yv�ܩ��yzzZ,�����Ç�k�.�;���@y������ot�y���8������������_���Ǐ�駟6:p��Wll��1H�����0�QpH���%Io������u��
�رC+W�Tbb��K��۴i�N�<��={*$$D]�tQVV����u��amݺU>>>:r��l����*I�޽�EVS[jj*h�������#���z衇���J�����;S�����s�-Z�ʕ+����ٳg���%___���V���ݻ%I���j׮�$��Gղe����;v��ǧ�<�O��$u���bY�ΝK�???�#ꐇ��<��s�*D� iΜ9z��W������4�]�VS�N��������/;;[����]�Μ9Sa�K�.I�Z�je���f�p/	�����1�aɒ%�y����
�a����>}Z]�v��H5V�c��~���� WWW����������������T��*֦�޿IIIJKK�t�`pܸq�
�Pp�zW�K�����"Ç������߯O?�T�~���}�]mڴI3g��رc�ԯ����]�r���VVV�$kkk�e�6S@݋��S\\��1h2`tu�駟6:� ���Z�z�V�Xat��?�RRR�ه��µk����jΜ9���������c����Dk���ruuU�^�H
0
��qrr�������u��I�ٳG|�"""̅����⢬�,m۶M...U�Һuk���*//O�[�.�,//��P�f͚%�c�]�����@�HJJ2:����GU�fܾ�4,Z�H:t�̙3��R#)))FG(S}���W\\���ߊ���֭[��{�5����VXS��ڵkZ�d�|}}��nj���0%''���>c�7ր�ѣG+''G�-��~�;=����?�!I����r�!C�hÆ


�…����_~ѦM������]�֭�t{����begg�cǎ���]�*77WYYY�YYY�>��ׯ_?b����(((Ѐ��K/)<<��8P�<���$}��'%�3��gee�x@�f��֭[��w�	�����k„	涉'*>>^111
60�>Yh&O�,IZ�r�����+44T����V�~S�LQ�Ν������@���O#F�Ї~({{{͝;�����Y���0F�%I0`�$)##�"��mРA�s��E�Z�r�^�u�޽��8P����5o�<yyyi�����/j���z��g��驰�0�ٷ��@o������տ�5J��
�}���K�|��ʬ�zG��СCT����H�V���5t�P�vyyy
		��5d����+�z�j�yL�Ϝ9���`
8P�>��V�X�k׮U���������������oh�ȑ������?���]�r�R�F��ky��UUM����_���٣�� yyy�3�^��|��{����+!!A}��U�6m�}ڶm+www%$$(??���poa��!L9:f�5k�LIII:{��$�C�4h��Ȣ*����_������ղeK���)((H�=������;�(77��ֈ#��o�z�Jd=p�5lذ:;�����)..��4
0:��/jϞ=�4i��?��m�	�D||����z�O�����S�*''����[<�.I���


�ɓ'�m�ΝStt�222i.((Ku֏��P~~~��%iժU���ͯ��}�o�^�����_�~]۷o����^y�
�Ì3���g^o��ͺu�y����$���֚5k$ɢ��ʕ+z����%)77Wqqq:|�����բE�
�M]_��Ee��1�T���]�VQQQ%�������]�|Y˗//7�Ν;UPP OOO�e���:|��v�ڥ�c�V��e\�I*��Koooy{{�u��srrҼy�4o޼
�
>\Ç/�ֲeK���+**J999j߾�$)''GǏ׌3,��ԎY�f�����Pc���3:P)IIIFG@�n�:���iҤIڹs�]h�{͵k״x�bM�2E�{���}�����Q��E���:q№.]j�wӦM:y�z�쩐�u��EYYY
��Ç�u�V����ȑ#�Y�[���裏*::Zvvv%�322�N�:i�ƍZ�n�V�\)WWWm޼Ym۶�|������/���y�ԩ��-[��~XQQQ���־}����.��-����[ӧO/Ѷq�F�={V�۷ן��gu��]'O�Ԓ%Kt��mذA������������T���1�T�����K�-Z�Q�F���J'N�Ќ3t�s�޿������ݻ[��-55��h"(��ɓ'k��튍��…%I���rqqQ``������ׯ)P����������I�������믿�ŋ	u���XVVVF�ꍽ��V�\)//�z����%I!!!�ѣ�$���M�/��ٳK�ݽ{�$)<<\�ڵ�t���e˖���G;v�p��X���-��?.I�׺u��믿*$$D�:u�$M�4I�ׯ7�\Q���cǎ�nϺ�˗/�ڱ�)33S���+1߾}�$I���z��'%IO=��BBB���/k�޽���M]_��Ee��1�T����*..֩S���g��~�7�|#�9}��$���Ν;��h�(�@�U��5U�S�V�����-[�ٳgkҤI���[�j͚5���78u�O�>Z�j�,X�g�yF���FGBY�x�233��'��7VVV�8qb�m��{����?��$��7)k����lI�gh(˙3g*�Q��M��ֵkW��-Z�0�ܥK���ӝ�999I�nݺen���y��ի����o($$D�/_����$)''G���;����?�l���禮�ey�B����8F��^�.h�ܹ:u�Ų���
�K�.]�$�j��b�����Qp4`}��Qpp�V�^-I�9s����N@ݚ5k�������ltԡ�m�j����r��C�6o��򱁻=�~���~y3*4o޼�vkk�
�Q[[[��e��S�c���-[j�Сz��4f�EEE�.�sg�Gi��M]_˚�nQ���Iu���U�t��)u��A�<�t�=zhܸqw�iz_��S�����
ֽ2E]�����1�7VVVz�7���:ֿ]�tI��}��T_E�X;t蠳g���ѣ%f��Ȱ���⢬�,m۶M...U�Q��T��%I�/_6��k�N?����?�~���ۏ?n���絬��8ƚJKK�$EGG�8Ϟ=k^^TTTf��$�n�Z������S�֭K,���3�4
��j���M-Z�����4	�=��$)<<\G�UQQ����;���k}�"I


Uff�n޼��/ꭷޒ�������}M#�gggWk���6�ߺuK����,I�ѣ�y�������!==]EEEJOO׊+$I�
����Z֖�8��r��!*33Saaa�vSLY�_S`VV��Lm
@��]�f������T��0:��jϞ=:}���O�nn1b�Ń�S�L��������������5w�\�kggg]�tIcƌ�����m�V����fwww/����V����ד'O�޽{�����S���۱cG����յ�-�q�5���;vh�ҥZ�t�����Lyzz���0`�RRR���!77��f�Ϣ�����!��ﯴ�4�cu�����fvvvZ�~�|}}���,;;;
6L���}-������FNNN���҆
J��`��o�^666*,,��
Mmdo֬�z�!
:T��z��e^֪U+���hܸqjӦ�lllԦMM�8Q6l����]�_Wײ���1�ԟ��'
>\���S�=�b�
s�Jbb���߿#F�P�-t���8p@���6lX��a�*nH��� I���5�����������V$''K��7F���Рn���f۶m���х���lt�ֽ��JII�'�|R�m�u?���jϺu��-[��}���������hƌ�6m��:��r?f�@��ׯ�
???�NVPP�������Ejٲ�~�������ŋZ�|��u�ftU4y�d�m۶DASll�\\\h`2@}kft4^�f�ҬY������H-_�\G���F⡇�/��"kkƉC�|�r���i���FGPEZ�l�fϞ�I�&I��nݪ5k������t��D��L@@���⌎��)�̝;W�|�&L����4xl$(�@c�����k�*22RNNNF�P
}��Qpp�V�^-I�9s����N�o\�N��ږ�b�Uqqqڲe��1�&���V����ݻ��ϟ�w�y��HP���[�nz�����������ot��(�@���󓟟��1��nܸA��t��Y�����4t�P�;��HP�_|�m۶i׮]���1:j��ypO�UPP��M�����8`V\\�h�ȑ6l��qPC�pԢӧO�k׮e.KJJRZZ�$���C�ƍ��h4*JMM�ĉu�5k�m/Ƴ��Һu�Ժuk�����3PK�ϟ���9r�bٱc����Dk���ruuU�^�H
����AIII:|�0��z�W\\�nܸQo�P���d�#��>�$%%��k׮iɒ%����$i̘1
Srr��3&�F�n�ԭ[7�c�����/4`����F��	�����h@������\�p���T���ALL�Ο?�	&��&N����x���(88�t�+,,��ѣ�������F��	�f�ҬY���ШQp�&�֭[Z�~�v�ڥs�����V]�t��ѣ���S�oAA�����{�n��_�҃>�����6m����$����;>r���󕐐��}��M�6�>m۶����4i�$�jժ��ajժ�z�쩯������gt�P�(�@���7�_߸qC'N�Љ't��UH�=�RPP�N�<i�{��9EGG+##C������.w?;w�TAA�<==-�yzz����ڵk�Ǝ[�Gp��߿���Ҍ��Slmmkt����e��cjh�>��cI��o�-wwwݸqC;v��ʕ+���h.�شi�N�<��={*$$D]�tQVV����u��amݺU>>>:r�H��-LRSS%Iݻw��`jKMM��4yІ
t��u�������bݼyS͚s����O~~~��@I7nܠ����ꈻ�{�?wk�-Z��$���*))I�������#G�h�֭�~�w�$������U666z��G�l�2IҎ;*���ӧ%I�:u�Xֹs�}@툋�ӥK����*������u��Q�������޽{�ڵkFG@`�4Is��ѫ�����4���i�ڵ�:u����K�����-I�.s;gΜ�p?��9�Z��Xfj���ʕ+Z�x������'������H���{L?��������itம_��E�iȐ!rpp0:N���;r�H��?}���v�Z��j���T�T��3ԕ��kRR����$�.�7n\}F��Pp�zW�ˤ����NÇ������߯O?�T�~���}�]mڴI3g��رc%ݞ�"W�\�p��&����d2�6n�P{+///EFF���ёP����ꫯ4o�<��w�.��^3:���ϟ����{��e��;vL���JLLTqq�Ə/WWW���ˀ��-
.�d999���[���:y��٣>�@�eeei۶mrqq��>Z�n���\���u��%������3p�@���Z�`� 777�#��^x���_�2:pW���Z�r�.\�v���P)))FG(S}�4�����k״d�����3FaaaJNN��g{�4�a��&`���rww�G}���=���ruu�$��ښ�
2D����LݼyS/^�[o�%www���f����6���W��ʲ�`jkhS��,Z�HԄ	���otT����^z�%�cw�d����Z�`��Q�z����k„	涉'�󊉉10u��4I�'O�$�\�R�V���*I%F��2e�:w���t�_�~1b�>��C���k�ܹ���Βn��1j�(IҀ$ILm�
��#�i���ѦM�t��e�����q4"��銉��k���-Z�J.^���˗��g��������TPPPf߂������V���5j�(���*,,4�qww/��+����=zTC�5zgj/**ҪU�4x�`
:T�֭�$���)$$DԐ!C��+���ի��1�>s挂��5p�@=��Z�b��]�V�c����|���9r�<<<���+""BW�\���"I{��QPP�����V�^m~/�w]��󕐐��}��M�6�>m۶����(r4:͌1��1cԬY3%%%��ٳ��:hРA�bIrttTtt���}�۷O�ϟW˖-��榠� =��c�,�;C��\�m#F�Лo���^(��rtt԰a���hz\\\�q�F=��s=z�������X�x����ht�*����ԩS���cn����-Ɨ���B��ɓ�s��)::Z�����u��;Vg������x�_�V�Z��?������W��한�l���׵}�vY[[�W^��<̘1Cyyy�6oެ[�n���W�ʕ+z����%)77Wqqq:|�����-�xj���]�VQQQ%�������]�|Y˗//7�Ν;UPP OOO�e���:|��v�ڥ�c�V���1��,ooomڴI�������_~Y�Z�*����I���Ӷm���_k�޽Z�zu�bI>|�>��S}���ڹs�$�e˖�����K|q�����Ǐ+00���{���Õ����#G@#�v�ZEGG�����(U��*''G:t�|�C�i�����,�nڴI'O�TϞ=����ZIII�ի�>��[�J*9�ޑ#G̯+���}�Q���Z<👑���x<x�<��ʕ+ecc�͛7+55UӧO�$}��w=�:u�����TM�:U��o߾*{i�� J���ƍu��Y�o�^���:t萢��Ԯ];�9sF6l���/IZ�h�RSSu��A��o�t{�@��뚚�*I�޽�ENS���@�<y�ڶm���Xs[ll�\\\�Qo��;��Ԛ�;�gϞFǨ����K�BBBԣG������M�/��{�nIRxx�\]]ecc�G}T˖-�$�ر��}Ug���@���Y�/Z�H�?������ IDAT����/I���_�N�:�y��4i�$�g���…ձcG5o�\��˗/�ڱW�T��'�|R���zꩧ"Iڻw��:�}^���K}��7z�'��g�魷��믿.�9}����E+�u�ܹD�fF�Sz���r�h����A˖-��ٳ�_hmݺUk֬���}�f�x�u��t�~�$=��%�����b���lI���w��9s�L�9����Һv�j����.]��vpp�0ϝ�\���I�t��-s[u��2��srr$IO=�T�v�5���-֩��r��͝;W�N��XV\\\Az�ҥK��V�ZY,3����XPpԃ>}�(88X�W��$͜9Snnn��T��/�P}�f��
���̈́P��˚�A��7o^f���u��(�����g+++��5=�긳ࣴ�>/�V�ҩS�ԡC=��3�ҥ�z��q���5��|��S[Y��{h��{&�����o����t��q�����Q�{JE�X;t蠳g���ѣ���4�gddX�uqqQVV��m�&�*��F����ڵӏ?���Ǐ�_�~��Ǐ��]����$I���rvv�$�={ּ�����"Ijݺ�rss����֭[�X���g�@cR�!��\�|Y7n��H�*�瞓$�����ѣ***�w�}��^{͢�!C$I�������͛7u��E���[rwwWPP���iF����j����ev///I��Azz��������+VH�
T�u��!*33Saaa�˗/K*��v��U����e�=S���3\������޽{5k�,�������t�N�:�'�x��8h�\�"GGG�c�X``���٣ӧOk����#FX<@?e��߿_���
,����^s��5�vvv֥K�4f����h۶mUZ�����'O�޽{�����S��XֱcG������;vh�ҥZ�t�����Lyzz�y]���edd��ͭ�z��R�h���hr���Gs���g�}ft�ᩧ�R�-t��!����ۻw�:t���FG�1;;;�_�^���rvv�����
���P������������\\\dcc#'''yyyiÆ
%f1X�`�ڷo/Vy���.��j�J1117n�ڴi#�i�F'NԆ
���T�GR�?��O>|�dgg�=zhŊ�"���DIe_�#F�E�:p��v8 GGG
6�Ώ��dU�<��%����X����d�k�����i˖-�������t��=�^�Ν;u��q����:T�<򈢢����&�֭[�ӧ�\\\�c���y?���@}X�n�����e��o�^����#͘1CӦM38�qJ�?�~"4͌���ƍ7n��1,���rwwW``�v��%�#������͛���&lÆ
��Ƞ����ɓ�}�v���j�…�n����(00��t�>k��񊍍Uqq1���4�?GGG���+55U���F�A)������K�.MЕ+W�3f�'�0:�`888hٲeںu�Ν;�s��i�֭Z�l���퍎@�c�ԙ5k�諯�2:Ԫ��$�#�E�{���ի5g�=��3<x�ё�<==%I���?op45�����_��W^y��(@�ӧOk��Ւ��3g�����T�
.Pg���k%''�����(Pc���FGPGfΜ�={�襗^ҩS�dm�$�
�<�S�N���7:
����l���Z�|�z�!��
���������@���u���_���F�����S@@��1�+++EGG+77�b��k׮FG@�z�j�k�N������1�<gggu������_]۶mS��͍��Qp��qpp���fFꚻ��$�ȑ#��kj���l��ӧO��T�IIIJKK�$yxxhܸq���JNN�����1���Ƈ�� ���WJJJ�
5*r��1EFF*11Q���?~�\]]իW�Z�cݸq����@%�vaDJJJ�nO��]��%K����W...��1c�(,,L���rpp��}��������2���P����[��Qpù��K�����(&&F�ϟׄ	�m'NT||�bbbl`:@cakk�M<����#4X�;w��̙��ݻ�I�t����բE��
ƚ5k��W_@)IIIFG�"
.���ٳG�������������K���%�T�x��y�����ڵk:t�BBB��fU�V���$!!AJOOW������3g��}�������ׯׂ��⢟~�I�����emmm^/;;[cƌQ���駟*??_			�۷�ڴic�׶m[���+!!A�&MR�V�j�8M���������jɖ-[���`���)##C�Ǐ��_�L�)((��?���x�����?��O=���FǨ����Z���|_4���FG�
.Р�]�VQQQ%�rss����˗/k��咤��|M�:U999�~����^�j�ͪ�3f(//O�t��um޼Y�n�Rhh�]׍��P~~��(::Z_|�n���_J�,Iڹs�


���i�=OOO>|X�v��رck��h�5k���8���[s�����7�#5I-Z�PϞ=u��!
.P�N�8��}�*%%E���3:N����3#1�@���1�(4B\�A����$-Z�H�F�����N�8�3f��~~��rrrԡC��/����N�8��K�Zl�*}�t��9rĢ�S�NZ�l�~�aEEE)::Z���Shhh��,�Z��GUtt���씗����mذ�̂�A�I�RSS%��)�Mm���\jU@@���⌎��r*�S�N���Ҙ1c4t�P�?��HMҀt��A�c��?�~�ߨo߾FG@D��]y��ۏ9�/��R���:u�>��3�����o$IW�\1�ݿ�$)$$D=z�$���i��Ś={v��V�oM,\�P;v�t�a���h]�|�R����N�t�}����W7n������|}��jٲ����$I�O��t��Oi�;w.���dkk���Ci��~�����_֌3���O�G1:R�����{Oׯ_�����q�Hl߾]�w�VJJ���������4h.\�ܹsu��)�e������'IғO>Y�O�޽-֫J�;�5EE�t�b����I�t�֭J�k*�0	Tbb�bbb��驃��͛�߿��5����K�$I�Z��؞��������'???�c�Jڲe���I�W�Vjj�&L���NB�0`�
u��Qyzz�@QQ�,X��c�j��Fǩ7�ϟ�_��W>|X7nܐ���^~�e�cU��ӧյkW����+���{���NIIIJKK�t�hlܸq��P�(�@�+�E������Z�j�N�:�:�g�Q�.]ԣG�/�L�waH2#T�oM��ښ����Һ�o�<�;v���┑��H�
d���F�1�U5��y�抏�����6oެ�'�Iy�GԶm[}��W\�V�]�V������FG�Waaa:z��LSu���WJJJ�O�f�cǎ)22R���*..������^�z��h�L#~DGG���Y�t��Y��"5k�L:t�ٳg-F5��Ȱ�fU�6$�&M�G}���D<xP���0`�yy�֭������<�nݺĺyyy�>����\�m���@��m��6���]�*==]�<��Q�������5��/���W_������7���n����GEEE'��������W�Y$�ڵkZ�d�|}}���"I3f���”��,�:�j��P�@t��!*33Saaa�˗/K��{�9IRxx��=���"}��wz��,�U��u�4�Dvvv��?��C=z�>��s]�|Y���ot����������ʲX��V�t�4E_}��^z�%u��]-Z�P���աC���j���Fǫ7VVVu2���*$$D��������5k&ggg=���


-QD{�y�Խ{�2����,�K�1��޽{k�����~�m�V���>��/�؍<'
�}۳gOYYY�رc����QYYY�7��M��W�ץ6�YE�
��9r�|�A�c�������u���M������]��ֲ��38Q�����k„	涉'�󊉉10�
.РyyyI��.]*OOO��7/��̔$�k׮����������ɓ'�[�n۬J�;���W���L3v�3F�F���:/���%I�
*��4�EY3u��J�@St��y��w�ӠA���+33S׮]Saa�~��'m޼Y�?��F�i.�D�믚={�\]]�b�
>|X���n޼�_~�E�|�������9s���_5:r�M�>]����1��t��?�7�xCO<�6m�dt�z���5���ɓ%IQQQ��o�gZ��h��h�^|�E�_���h�Ν����3:J���f߾}K�����o���#G���C�?��"""t���m�����ѣ:t����J�iժU<x���u��I������jȐ!z�Wt����޳g�������eΰz�jX��=ڂ������V���5j�(���*,,4�	

����v��Qb��?�\���Z�hQ�Y��󕐐��}���c���r����?:�#�D51��Sm�1�sV9�dl>�br�)͇��5%VI36
Ü��Ri�rȤ�LEg��]�oW�AW.��q�ݮ��^��p]�~�_����X�m۶pssC\\JKKU���������4�.H�RRR.��G���FFF��ׇ��֮]�3fv�����Gxx8F�
���c�

�iS��O҂`kk�xʘ������#�7h� ����2�N�>
SSS8��&""z�ݼy�z���acc�����…(++Cee%rrr�j�*�������g|�G������q�F���`�ԩ8t�nݺ���j�ȑ#�2e
���?ǠA���A�� �m
qH^UUU�y�&~��6�4i�ܕ��6���
��c>q�D��� &&J�VTT 66����Uk��'"""""����҂�����h2�ݻ�iӦa�Ν�y�&jjjPXX���XL�>]�PWXXJKK���u����2���`�֭HHH��~�Ç������ؿ?֯_/�ꫯ�p�B����޽{bqqq

U�vVUUa�̙ؾ};nܸ���j 22s��Emm-`ѢE���ºu�PXX(,,Dhh(����x�b�}:teeepww��swwGYY>���!""""""��CW�)cff����y�A&&&X�h-Z$�.o0�*e
QDQ��鞞����T�����ڷo��;J噘������χ��- ??�������J�BDD��L�:�/_ƛo��~�-[����ԩ�,Y�#F�w��8y�$�lق>�@C?[q��	�o�{��E��ݥ�[�j�`������兓'O"  �7o�P��===XYY᭷��[o���bݺu�ǥK�```���~盶�m�bРA8p����ooo�e���{ܽ{C�E۶m�b�DDDDDDD�GJJ��C��;v��˗akk�U�V�s������ҥK������(̚5K���;"22���R�YYYعs'ڷo�;v`˖-

���#���{�m�۷oGxx8N�:%�۹s'����
---dff���_�pNQ�
���l8;;c��Ű��G^^BBBp��Y�۷#F����V�X�Y�faٲeزe��"Ǻu�`nn�0�3g�:w�,ӿ$�̙35j����fp��g@YY�����7�x8�<�'OF۶m#������Z�5D^^f̘;;;���>>>��Ζ[^KK둯�RRR0f���?����>���h�"���O�>���?�����#��u]����i������ɓakk}}}���bʔ)�믿�n�;w������,,,��关g�ʭ��_a�̙ppp���Z�l	WWW�X�w�ޕ[G�ؔQ�]�t	�6m���:$3آ>WWW�߿zzzزe.^�(���x7$_���~���KEq=�s��֮]���c���
��������~�>}��u����Յ��%��'N��c����lL�0VVV��ׇ��Ƭ��|c�z�
��k��dś����G�/)��sR�O�4	�������K/���?�\i[��Րc#��1�!//���011��a��7�������yt��q@PP�v�
===t��M\��رc2u|}}e[L���K���'W�����ŋѾ}{��:����z�N�¹s�ХK<x��9>������XG�������:::�ر#���˾��k�Fjj*�M�����Ǐ�믿���u�����u��A�=#"5����~��suu_&Ljjj�MII<<<�7n7n�<<<����)FK�<���u�٬���y�ʿ��N����2/CCCa���2u䕭�222�*%����-۽{w�޽{b�3f��K�6h[+**�ӧO���R�?��`dd$�O�ȑ#
�+99Y044�����/���RuΞ=+���)�:t
�[}���?�X ̝;�A�W���_ ,X��Aq�;nU���sSY\O�i�~�k�֭a�رJ�())\\\n���������X�?>,����������)|��ޘ�ˆ��5�󶢢B�������˗/˴)�p��%AKKKhժ�PYY��sR^����n�ڵk��Q5����9���ߏ7N��~'"""R���8���G�aQ3א����W�����իW/���U����J���\]]�^�z�ԯ
E�^�
I����q��m���Wn�u�ɋ�>Ee�������*���O�|ee�0n�8���U3f��m��G�r���=WWW�gϞJ�g�'5O\��`eexxx��>����²����5k֯_����c���pqqy��w���ѣQZZ�y��᯿�Byy9���0}�tTUU���R�A�y�����[�n�_�r���x��fΜ�+W����
�N��������� 110t��m����x�
�Y�
1~�x���c������Bee%���0|�pܿcǎEaa��6�����o#11���lj'`oo���*�^�Z��y�PZZ���{�����PVV��Ǐ�K�.�z�*V�X����j��;z�(`�ȑ
ڿ�Ǐ �<U5&nU��䜔�{�*�4�U������T��BCC���
'''$&&���HNNF�^� ֬YӠ>�?�޽ooo�΅PYY���T�����ܾ��w�!sު����[�?�  22Rn{���&L����Z�Iyn߾-�s�ƍCNN*++�����*l[ոul�8���_���Dqq16l���ADDDD
ӦM�����/��t(DDjS[[�0O���ÿ����V�hºu����]�v�������`@�@=+iHV�����4e+�Q�FvP��2��9�4D5�����$��y��)͗HJJtuu�G}$�(w�nA�s��	���	$LLLBqq��>�Y�x�@�ׯ�̌l<���'w��g�9s�L�ǎ-[��J���������666j�����-Z���"�u�s�@077d\O"nU��b���4ϙG�V��������6ڷo/��j�_�%�
E�4f�[�N���~���j�gϞr�j
���uު���,�q� IDAT&yyO������/� �_MM�`kk+Ν;'�z�Iy�V�C��)[]]-���Kn[��q���_-Ӧ�~'"""z2�.]*
����t钦CPu�='oU�Q�F	���Brr�T����*���
#G�TZ_�{�\]]�;w�i�.]�UWW+m�!}�9Rpuunܸ���DXX����*L�8Qpuu6l���~�*���
���L{������*���;
꟞=��HDDDDD�<q�""""R����>����ӧO>|Xa��Ř0ajjj0h� �]�V*��_~̚5K����A��+WĴ��r����
["�ȑ#���@�ʴ���p�B����֟={�L�믿())�Jo׮`Ȑ!������-�999A���-��s�$�����?���$��߿�R=y���YUO�Q���!���Ri��W�B��������(��			���������ŋ����
ј�V��?U=���_G�Νq��u:tH*�СC��χ��3�������GrLd�tuu��O�q=�qx��7���������q�ơ��L��4kIIIؼy��àg����W^yqqq����۷/ $$���AFF�xM�w��O-���$TUU!''K�,�%�$�C\�vM���

BNN<x���"|���pss�̙3Ų�ΝCll,^}�UDFF���;w�Ĺs��2�b�ԩ //O�I��=8�����.;;`mm
---����௿�R�ƌ3p��U888`�Ν��ё����t�֭A1I�/--Uy{$$�J�O�.��>�4@mm�T��!�$������vvv�:u*��ك��*��VWc������G�_��x�TO]q���U�4�UI��2H����HHH�ҥK���	kkk� 
�ߘ����x�����ի����o�Ɯ�����J���ɓR�ϒ������?�������ٳ�#�PG\�{$ʈ��������ALLn޼�9s�h:�f-55AAA���1=���ЦM���ɚ<y2��쐟�???���~~~�q��������c��X�l������?��S����XXXF��aÆ��ǔ)SСCddd���=z�A������������zRpp0����r�J��ꊟ�/_.^o��������U�$�i`!""""""���DDDD�v
�y_Q��[�">>fff����WuIVTh���%7����F��FZ�-�733�x�Ɋ
1e��ٳGj��QQQ5j�t�˗/�-��s����
�+!)/���q4&nU�����9�*�
����,�k�.������^^^X�z5�9�۷o��gc���x)ҲeK��M�;��9oU��S�&�ۉ'BGG���ϫ۷o#!!����*��sR�K���֭[+��θ�8�c �����������Ν;5N������bq�4�"�ΝCtt4>��h:�&���۶m�رcaeeXYYa„	���RyU��裏���	###������	k׮Ō3<��,X[[[���<Y���)"##���
kkk�����}��ETT���Dhh(n޼���@���lll�[�n!44Ta,�
���1N�>-��ӧajj��6n'�F�j:j�bcc��0����)311AII	�޽��AQE�������������ѥK�}����޽{
�w��HII��C�УG�G����?��k�aذa�������ݻwQ\\�V�Z�Թ{���:���x��wq��5=z���HLLğ��K�.a�ܹطo��ck��8p Ν;�ݻw���5D||<���]n� ��ҒJ���P[܀j�YUO��Qʼn'(�=_"66>>>��_~cƌA�`ii�Ν;��m�1�CR��ݻrtW��ʳ�o�y��4q����`���矱c�̟?;v�@uu5���mۊe�yN�cff���b�ۯh����jʿDDDD�������c��͘0a���i�^y����"11Q\��>Awww�=Z��4)))r�[�h���@6��㦛��!$$DnYɠ��􄧧g�bN�����e֬Y�5k�Ȥ:C�U���	������|q����|�����ߟ�$=c8��9s�`Ĉ�����4���������_��o7�^EEƏ���2�\�^^^
����#==YYY�2�ʌ?�~�)���+̛7O���{��EII����������q��Y<X��o��&�S';;;L�:S�N���O6l�����ck��>}:֭[��[�b�̙pvv�ʿ�>�w�OOO|���ԩ�����7���(��ڨ��EYY���ė.]R[�u5d?�JS�̣<x�����aÆ)-+���e����K���kkk���|���ggg$&&���{3]�
�g�;ߘ�V��?Ui꼝2e
~��gl߾���Ƕm����yN�ӥK$%%!99C���OMM�[O�q5��""""j�
6���V�a4[:::x��ב��,�o"��gΜ�o��&3�ѓ4y�d�߿111����X[[ˬ�IDDDDDDDM��O=���5k֠��F&?>>ZZZ2�.X�9r$�,Y���~��"""d򲲲����:�i���:���B�7eee
۾~�:֯_mmm,X�@L4h`ݺu2M���b������zKi�
ѡChii�…2y�V�Pgl�9~/��",X���J2D�䌌ܽ{�7o���fϞ���~���0`���#U���p��Y��###�����x��!�<�sFK�,�����w�yGi���\�ĉe���������1���w���a%A��� ֩�Y��7�U��x6���Ç�e˖���DLL.\��V�Z��S�9�(

Ńd��s��Kѱi��DDDD�0������	���@RR��à&���������k����p�9cdd���`�۷(((��}�CCCM�GDDDDDDD������[���/���Y�$bbb�>=/�{_����ׅ-Z���zK��߄��r�رcŒ3}}}AWWWHKK���k׮½{�˟�)��?�X(,,�߿/=zTprr˗/��s�����R ���¦M��K�.	���BYY����)�[�NhӦ�@X�l�T����[033Ç.\� TVV
.\�.�����W�Jի�R���E�	�Ν;��ݻ'TWW��� A�˜1c�Hl�9~� 555»�+���???�ȑ#�?��#TWW���Œ3�~W-,,����[f�HbvppN�>-������¼y�CCC�ŭ�~A���}��P]]-TVV*ܟO�Q�^]]-ܸqCطo����)��'O>�
������BMM����%L�8Q�X���=2��쏒����V �5J�������.��`bb�p���w^]�mc~���y[����@<n�gϖ)��sR^zqq�`mm-
$��������!�3Fhժ�ܶ��c󤎃 4��s""""����֭[�����Q011�]���PԊ�=[bbb���!  @����t8�Կ��DDDDDD���#��>"j�x���!U��߿�`dd�pӗ_~)U���U��O� �����r�z����e����^z�%�}����<x-�o�>�A�/a�޽2u�rqq�йsg�1����<d���T=~555Bpp��8�>��c���F��s��I
���
W[܍��}��Ux^ʋ�i�3u��255�ۯ������K��ߧݻw7(�����D��u_����V���W�M�߿�|�֕��$�׹s�dʨ�������$�l�Rn;v�[��q);6O�8�~'"""�桨�H�����ۧ�P��*((�tjǿ爚6�O$"""""j��ADDDD�2������C�v���-Z`�8|�0��}��.]R�???�<yo��6Z�l	}}}����X�j�?.wyvgggdff"<<����5���`hhGGG���#--
+V����a��
___X[[CWW��֘4i���0b���Csss$%%��?F�.]`dd]]]888`���HKKC���Xl�?	,_�W�\��իѻwo�n�:::044D���1t�P�_�˗/���֮]�7�xC�777�9s^^^������>z�聟~�	����n�~޶m����^P�/��9����.,--�����`���6���{۷oǫ��
���c���駟�r�J,]��e˖�ט������tL�4I����ݻwc���ccc��=��|�T��{V�۞={��_��ع��ɔQ�9�(��������s�Έ���ĉ��il\ʎMS�� """"j�Z�j������j:j�ڶm������������A�t�<���bbb�~&"z��������6�&z^��{R���<�[����8~���ágХK����GGG\�xQ��=��9�����B[��Q���9�����������']M@�)/^D�N���:u
?�����PRR333���+9r������[2kkJJ�c��N���HNN�p�ױc�j8""""jnڷo�͛7k:jŒ��Q^^�?��/��L�֭[�3�Q�w��M4[�lAϞ=55\�si���8y�����J,[�G��J���q��)�:u
Ċ+����־����4lڴ	�v� 7n�ꫯj:4""""z����'N���q�~�z����r�
�n݊����3fh8R""""""嬬�`cc�	& --
-[��tHD����"66V�a5[pAϥ�'O�M_�f
�=
SSSL�>���G�6mP\\���dlٲG����V�\��������r,]��G����5`�ȑX�d	���;i8B""""z^lذo�������[o��kii!44}��}���@KKQQQ�֭����k�.M�DDϸ9s�`Ĉ����������Y��tDnnnpss�tHOOǁ`nn���(������:::hժ����(�j�
@FF��C~b�mۆ[�na���bڄ	p��-l۶M�����������;w.:w�###����^�����믿b�…��������A������b����t8D�FVVjjj45C\ႚ���7nDbb"���aoo�I�&a����W�(++CDD�9�۷o���o��6�O�}}}��!y�����0i�$t��An,�Z����/6n܈�{��k׮R�9s���8r����o`Μ9���T�w����DZc�PTTKKK���3f̀���L;qqqCFF0`�̝;W\�������8|�0


���{{{>\j���R�����^�����޶m[���!..'N������FDDDD�6/��>��SM�ADDDDD��…1o�<xxx���I�!=��޽�~��!  ����y�6n܈��XM�AD����������H�8�����c���~������#�����
3g�Dvv��VPP���HdeeaӦM��V�����}��Q�o���7"--M&�O>ABB���@zz:���ann�|c�w��M��˗/�i�������ٳg	ccc�:���(..�����Q[[��� ��M��c��|uu5233����������p��!������]&.www�={�ƨQ��=DDDDDDDDDDD�V�\�'N`ܸq8w�8y�n������C�ooo���h:"+�w'"""""��C���DM@LL�_�DFF"))	���R+/HDGG#;;��Έ���o�����x���8{�,���@z������۷���Jcz��nݒ�KLL�ƍ������H����ƍ���V�w};v��˗akk+nwDDlll������(�:�۷Ǟ={p������?.��ٳ��_ ))	�N�¢E��v�˝9sйsg�>$i�2DDDDDDDDDDD�:]]]��Ƣ�����������+����t(��.]¦M���-[j:""""""""j�8�:777���tɀ��� t��zzzpqq��%Kd�=r� $$������Aǎ8p�Ҹ���<�ɡ�d�Oyˀ.Z�������C׮]��%�|hy�ݭ[7qe�cǎ��	����Y3JJJ�|Ɋ111���ǿ���ѣG#%%E�/^�pG}:t�*CDDDDDDDDDDD�ӡC������Cӡ<�ttt```�_�Uӡ��cǎ�9s��C!"""""""�fJ���D����޽�T����L�k׮���䶕����/+++���vvv
�������ٳ���W_}p��u�}+�[�nR�p��
�:����{sss@mm��6w�\�X����HNN�W_}???x{{���P,w������L�4I"""""""""""j<M��,���III����S�NaϞ=ؿ�#'T���ŋѩS�Fׯ;y����1m�4���?Nx��'%%剴���d�{�;���CDDDDDD��'z��_jȅ���Ihii=�L}���S�߽{w��ѣ�:u��rG���W�b�d����z��;��>===���鉞={�ĉ���q��y|�嗈����ٳ1j�(���b���k����_�������tDDD�oooM�@DDDD�6GYY���75o������1d�M�CM���q��I�N(//���1w�\lڴ	����Z�ה��4lڴ	�v� 7n�	��������gpAMZ�v�p��%�?^�b���e�Z[[#//			���V��Q�F�ضmz��
�2��'v��1b�L~FF��L'iii�_|Q�Xlllp��U����G�bzzz:4j���+_xyy������8z�(�oߎ��0q�E�֭QXX���b�n�Z�~qq�X����̙#��D"""jڔ��HDDDD��ٳ'�������>}�h:z
���������DM�BM�ɓ'�֖dІ ����i�&�۷�|�M�pQ^^��K�b����}�#Gbɒ%���`dd���������4K=��=!�]�YYY���Aff&֮]+S�_�~��� ����(**��777̜9S,+Y��ڵkbZ�n�0t�P���a��鈍��͛7QSS���BDGG��Cyy9,w6�5kֈq���!$$0h� �}�׷o_@HH222PSS���q�{���W�������ݻw���/��H��!YV7//O�
I��,�KDDDDDDDDDDD�N:t���
���5
=%��θ~�:���5
=G���ЪU+̙3p��
G�۶mí[�0~�x1m„	�u��mۦ�Ȉ��������pAM���~��g\�zS�LQZvʔ)8q�222���+�ghh�y�扟-,,p���9���HHH�p�Fee%~�����!,,L��~��a�ҥrchժ�L�]�t��q��w]�'OƱc�p��5���I����ɤ5��ɓ���P���J幸���=<<p��IdeeI�@VV��
� "��i�ƍ����tDDD�"ooo���h:""""R�����������3g�h:z�LMM5�3���ƍ������r���cҤIX�x1��[�����#G���۰����o���ӧC___,������CXX222```�`�ܹR+$��fxx8,XGGGlٲp��Q|��w���AEE,--ѷo_̚5���bݺ�H����+���p^Ky�`ii)���q��1������nj3��+۾��"l޼'O�Dyy9���/��w���"..��������m۶������0q�D���5h�5GpAW��]}FFFǦM�p��)ܻw;v@�� IDAT���/�-[&u�������غu+�?�[�n���...�9s&IJ,��͛QXX���*1]__���8u���݋��L����E�x�W0b��KQ���a���HNNF�V�0x�`��Y������۶m��_�'N����[��[o����{���
ڷu�9��������˗�ڵC�޽1y�d�ܠA���g����Ә4i�T�O��������6����5>>>�������X�h233��O?��fӣ���QQQ���I��>�O���ׯ�i999r毪��̙3���-� 22YYYشi�8�@����������Q[[����F����Rq0�W_}����2������CII	V�\�p��}���/6n�>|�T޽{�0m�4�^�$���X�={���066V�}������C~~�X�����ղ=��;t�������.Ӿ��;Ξ=�ÇcԨQJ�Qs���j�
˖-�J+((XZZJ����#  J���􄧧��>}�(X�H�-��g��ܷ�A'-Z�@`` ���h���t///xyy)m�����ވ��@~~>lmm���HOO����̅@"""""""""""R///lذ�~��#�w�������!&&ׯ_���
V�^�Ν;#33K�,��[���FGG#;;���X�x1��푗�����={���È#��o����hӦ
"""��Ǐ�.�fǎ)Np�s�N�
6ZZZ��̄��?N�>
��}�+[4�R+fHxyyaƌRi;v��˗akk�U�V�s������ҥK������(̚5K�}�����G�v�z�j8::"33S�~����de�Ν;˴/I;s�\�sM��D֧O���a���())Amm-�\��+V�w����ɓ'�m۶R�����������������������ysww�ʕ+���+]%�����i:�&������ t��zzzpqq��%Kd�9rGGG���cǎ8p@�N`` ���``` ��XRR�Xm������ԩS8w��t邃���?�'�|��
�4�Errr�)!o�v��M\A�رc�ܾ'N/^'''�}���jٞ��]�x��2�u��A���+\P�6d��޽���

�ʳ����5�������������'��ۇ�7���P��ѳ�֭[2dZ�l�_~�ׯ_Lj#`ee��ͫ���ŋ�ԩS��;>>�����={b�رO34""""""���…q��1�?���077�tHD􌐷�d�V^^�I�\\\d�\�v
�Õ���͕I����K~�jkk�M�C�����͛�?��C�� r�}���U2�߿��~�
6l��ŋQRR�ѣG���ݺu��/��7nܐi���]�~еkW�m<����Ν;333���4I""""""��\P�&����r�
���ЦM���ӧO�����Cl�\]]1k�,�_�0{�l�[�������899I}vvv�XLM���q��I��V��ﴴ4lڴ	�v� 7n�ꫯ>�8��������G�����oѭ[7̚5��њ�H�RSSaggKKKM��,�������2��[M��J3�j��j�n�:���h׮�|�M�����ɩA�4���LLLп888`�ȑ���\(Rw�I}��Oc�Xuue�P��'mmm���4yǒ�������y�Ԥikk�����ޚE�溤����iS4�B�yw���&�wyy9�.]�ѣG���0r�H,Y��}�����f�DDDDDDDϭ�m�"**
C�ŀ0e�M�D����;v,��틭[�j:�&O�}�v���ҥK8�<^�u1����2e����������:��RG��Uy###aaa�|���_SS#wp����055����i666�z�*���ѣG1===]�Qڵk�˗/#55���b���z]�؞֭[������hݺ�T^qq�X��������y&;M�cpss_;v�������
qqq�/��B���y۶mí[�0~�x1m„	�u��mۦ�Ȉ�������?o��6,X���]ӡi�_|�7n`ٲe��7p�@�ڵk������dffb�ڵ2e���

BNN<x���"|���pss�̙3U�_�m&%%���
999X�d��.!Y��ڵkj��׮]êU�HO.Էo_@HH222PSS���q������<Xl#55555�p�֬Y#SV�өS'@^^�L�$MR��������y�.�����ٺy�&���K�9s���C�0i�$2D�\ii)���q��1������nj3ę���D������`���;w���Cmm-���q��a@OO���>|8F�!�V�)))���p,X����زe�T���?j��]ZZ���8���k���˴m�V03q�D����v ���������BCC���9ԞE��Ax��V�۷oc��՘?>���`gg�鐞i>>>���q���G��3e��8q��344ļy�T�_m�����e�����Ɂ��;,,,p���9���HHHht��&���ìY��ϓ'OƱc�p��5���I�����I����G��ŋ1c�1}РA2�"Ա?=<<p��Idee���E*O��FC�5g�:KDDDDj���������ڷo���DEE�2Oҝ;w0y�d�߿w��EMM
rss�l�2$$$���ݻ�iӦa�Ν�y�&jjjPXX���XL�>eee2m�����ٳ���@qq1���{������6m�֭[q��5TWW������X�z5bbbXXJKK�>�s��9t���ʤ���pwwGYY>�R<DDDDDDD�x8�B57o�ıc�4�Ipp0������&�08����������B˖-���GGG�\����/�555Edd$���amm
����o߾���jԪ�h�>���'������'''�]�V��k�.��`kkTUU��]]]��?�A�����7���W_���̰m�6�;VVV��с��&L����(���?�}}}}���c��Ѱ�����>����'�?
ccc�>}Z&����055WF!""""""z^q�z�bccQ]]��0���w�}����9�ٯ����~~Ҷoߎ��]�t��իaii�O?�{��Edd$�
رc._�[[[�Z�
�;wFvv6�.]���\DEEI�R<D�6m� ""���8~��x�kϞ=�/��nnn���Ɓ�]�v���Gj5y�O:v���H�����nE}�9sйsg�v%igΜ��Q�T����������i���p�BAGGG��<�KhZvv6�����_cڴi���hժ���KKK�tsss   @i��&ב���m���!$$Dn^�!<==�����ŠL�-����F�mbb�E�aѢE��������ވ��@~~>lmm���HOO���?�����MDDDDDD��qJzbz��1c�h:""�3fӈT$`���$�󓖘���gvvv066FPPRRR�w�^�����AAA�ڵ+���Э[7,^��Έ;;;���PRR"�Kn@��� >>���/F�����۷�A��<�B����ŋ(��C�Re�����������={���X�EϮ����W^��)S4J�ѧO���a���())Amm-�\��+V�w��I&O���m�J��kkk���j02""""""���+\�3g�̙3G�a�S&Y9AbݺuX�n��yժUX�j����P7n��G.�����֭�T��梤�������e�kkkŴ�s�bŊHNNFrr2���+���������
�_2�AU
�ny�ܹ��,q�I�$e���������"ggg���!99Y�z�Ӧ���V��|���B@@�o�]]]|�X�r%���0{�l$$$@__^^^��/��O��eee�5k���a``��C�bݺu���VϽ{��z�j���#??������ҥK��Y=n���+##���_add�w�y.\���ۥV*��Okkk�]�v��ի��ׇ��3�M���ӧ7�5C���ݻ���P�<�"�add���`�����ĉ����ƍ|=��������9�zb|||��0��ԊK�=;$7_���������鉞={�ĉ���q��y|�嗈����ٳ1jԨG��huA�nz�8�-���-��$�q�+�GQQZ�n��0���������t8r}�?�Z�
;vė_~�s��x8�bǎ���ƶm�d�GEE�墣�������TXXX��������%//!!!8{�,:$sM��q6��~�����Hls���6m���p?.Z������UUU�(%%%PX�y%Y����r�
���ЦM���ӧO�����C$
quuŬY��~�z��ٳ���ᨈ���������'JOOOj�Q"�gUll,~��M�A�LHIIAjj*f̘gggDEE!))	~�!\\\�n�>Imڴ������\t��Ea9\�z����ѣ�������Psssxyy������8z�(�oߎ���
��OKK� ��055���ʔk�v�Ӻuk���X恍��b�i���=z !!o�����ir�����0:{�,Ο?GGG���òe�0k�,t��
999����'�|�+V !!A�����q��A���)))���իW�a��^�Zn�6l@JJ
z��-[������'�����/� 22RfU���٘�:uꄨ�(���X�f
֬Y��[�n�����H��?��3��뇪�*|��5k�����C[[�����t(��� """"""��.�3fƌ��0��[uu5\� ++���,�����ၸ�8�_�!!!hٲ%6n܈��x�k�{�����QQQ		��U�ХKdggc�ڵ�޽{����Ñ���E�aȐ!x饗���]C\�v
vvvJ۴����;w��?`ԨQ(((@hhh��[^ߝ:uBaa!���dV���e�������H�^~�e������HOO�	�xxx`Ŋ(,,D۶m5��͛7�k׮��s�bٲe(//��_-^{�裏�b�
qՇ����K<��%������Ğ={�����ܹ/��"�K�.���������eA46����_ॗ^̛7k֬��;w��GSSS#,,.\��#����WZ���������Hڏ.BDDDD���0�b�ԩhݺ5222��;��7�o����{b�ɓ'���������CϞ=���7n���~~~*�=y�d@hh(���^�z!((��a����9Æ
S�f߾}�}�z�cǢe˖��ny}{xx���U�$�1P�������H����	mmmL�:Uj�z����믚E��ݻ������NNN�{��===�>����ػ�������A@�3�R��(󂔊�-ŲqH��f�F=J�ȟ�yԯ�ɬ�,��E�
3EA
9�J��)Q��yE.��;�e�	���x�ǃY{��{�43��ؿ����/�l���`���.v��]c9�3W�
6l�ŋ�=��s����Lrr2�ƍ��'::����
��
\�Mi߾}��۴iҩS'���CDD���Wen���kd운j�*"""����|ISDD��JX���OV�����	�~��888�����ٳ�ׯ��_������g��4n�{{{7n��Y�x1nnnU�;$$�)S�p�=���舣�#���>�iӦY��?///���),,�p̱c�ҿ4h���#L�<���]��}����Ņ͛7�w��͸��ҧO�*_�y
6$!!���$�~�m[ǹ����1a�<==m�L���e����W�:u�X=6&Tt��N�:U���9�3�����g��P��f�
"77���8�t�B^^QQQ�~��,\��Rc���������\N��w�]ƍGJJ
V�L�2����[����_lڴ�M�6ѧO�M�f��oM�}�ٱc,`�ʕ�L&H�V�h׮������
"))���w�}g�M�6%::���4h@dd$����+���ڃ��

�p����Rw$,oggg&L���	.ۿ2�]�����h4Knn.^^^��撙�ɨQ�pqq�p\�v�v�ʔ)S���䡇�Z��f7s�L[G�j�n�JϞ=-�7m����o�Ǵhт}��q��A�7o~U�]˹���y��y��پ};�W�f���DDD0z��:��bٲe�:������� """"""W�V���NJJJ���:�ׯ��Օ1cưf�~������>}:M�6eݺuW�}Ysgdd\W�ϟg������OOO�6mJHH�&M��'"""Wٰa�hҤ				����<==2d�
��������HY����ܹ3���ٳ��#�s�=�?�@QQ�7o�<��c���`4����p�ǎ�W^�`0ЫW��W��233���.wL�?����������{�Ǚ3gh۶-m۶����n4;v$44��1D�����5)"""""Ri��9���9_���$%%���F\\-Z���kذ!����S�N4���$���O�6ml��j������4��6x�`�/_N||<���6L'""���v=3�h����:u*/��2C�`͚5̟?'''������IHH ,,�?��WWW[G����n�S�NVm�������3a�>��s�l�B��������o�X��������7�|S昷�z+Ǐ��LJ�͛s��A"##=z4���>��޽{���쥗^⥗^�u�ZM+\�u��ŋ,\����:w�L�n�x�����K�������&((�Ν;�����RXXh�S�K������_|�O=��U�Eq
6�����>+5NAAӦM�k׮��Ջ)S���\v��?��9s�7�x��{�N�:���y�敺3���_����p�v���?LLL��j���gΜaŊ<�4n���ޤI���Y�bgΜ)��H�ѡC��Ù;w.s���^����ֱDDDDDDD�M�6eÆ
�~�!��_|�c�=���^^^���+|����,�A�lٲ�1c�мys�ԩCÆ
	f۶m�o߾��Ug�;v0gΜr�|뭷hٲ%u�ԡ���Q�F���NNN899Ѻuk&L��G}Tc�s=�`0hӦ�:�DDDDDD�v�
r][�`���qQQ�w�f��ݜ;w���0
=z��R�G�%..���,,X��]��E;w��[�n��ڵ+���gǎ��͞=��k����ORR���,]�77�J��ٳgy�g���,mǎcٲe��������1�F��ԩS��W�^�ŋ���*���[���(�+  ���t���y��'+}>"""�J�/�ш�h�u���d��qu�=<<���/�47���;o��&o��f���j{e�:w�>>><��V�˗sРAV����1�#FT8Gm���@BB��c��lٲ2o)""""""76\�u��O?�����ߟ��"����5k+W��
,]����lZ�n�ĉ�&''���h���Y�f
���dddXV�(����OO�
��~��?~�Ծ��T�ϟ�<��={�4iG�a�ҥ����;wI�1���^^^̘1___����<y2���+�/.�,r��͙:u*��v�����űa�K�Ee�cZZ����r�����Tp!""""""""""""Wl�ܹ�>}��ӧ�:�
+44���P[�.�P""""""�O����J��������+9$$$�j�*���/���OFFk֬��n�:���iժ����lْ�S����Ta���B�ԩ��|7����3a�ppp�M�6�b�
6T8fI�QQQ�i�ڶm�ĉ����K�k� IDATI�fͨ[���x���Ӗ�������.p����!7���#G�0g�^}�U�4ib�8"""""""""e�
r]3fӦMc۶ml۶���{�#F`4qrr��;t�AAAe��믿V8O�ƍ9z�(G��Y�f���͵�/�S�NV�۵k��Ç+���9ڶmk�޾}{�қ�%y{{[~vss��ŋ���^�'NP�~�Rs���}DDDDDDDDDDDD�w�����ݛ��[G������� ""��Q��ڷo>>>�>�����[�.͛7',,��{���_�U�V�m�6��g��Y��Lr�eddX=6�QU� 00�N�:�q�F���v��ɻ��ҥKy�x��'��W�(��ٳ�o߾=G�e���<����[�~��I%W�0<����B2�(Jrpp��l0J��u4[Vfs[Y㋈��mٲe�:����TRbb"F���1DDDD�8w�yyy�z뭶�b3{�졠��V\\��Iaa!?��3�g϶�9�HM7n)))e~}�


���y��puu�{��5>���ر��r�JL&�U�V���������Hͩ�o��\Ennn��̰a�8}�4��ͳ����`�ڵddd�����+��\p_�j?��3�1������ڵ���;���;+y��4m����L�v�c�VUe�����N�*u����GDD�cǎ����:����TAhh(;v�u�
ĠA����m�fHKK�u)��ё��Th�(RK�����X%?{NNN�_�~,Y���橬���3y�d���'M�6%$$�I�&q���k�GDDDDDD���
r]{�'���e„	��׏�ロ���?���={�d���DEE��w��ɓ'Y�t)K�,��ߟ��Vh0�L:t�f͚жm[{�1���+F��s�=��?������}�|��ϟ�G)�� ���:3f��{�a���DGGзo_K���.�G�,^����hf̘����Kvv6111<��CW�:���p��1rrrJV���X��������K���K��!""""""""e�6m�;wf֬YDEE�:�Mt�ڕ��~����z���VU�UÆ
?~<III�ٳ������4h��m��,_����x��ïy&��Lr]6l���̚5�Y�fY����<|�p6n�Ȯ]�2d�U?'''Ǝky���Ή'		��ӓ�k�EAA�}���ͳZ���gϞL�<�̬
6d���Vm��{�՝yʛ��9���:t�#FX�k֬Y��ʨ�u�ҥ)))deeY�dee�+���+,,�e˖�:����T��h$!!��1DDDD�*���c֬YDFFҳgOl��ԩ��m۶���:�����̟?���TΟ?���7O=�'N.��`���Gll,�֭���Q�F<�裌9GGGK?V�X��y�صku�֥w�ތ3gg�j��h�"ƏO�V�,7�[�~=����ݻ���|5jD�=����rl�q��U�/�…@مCgΜaѢE|������4jԈ^�z��s���������iݺ5�/����Nxx8111�����đ#G����s�άX��x�ƍ[�4i�V�X�СC�_�~��EDDDDDDD*�����oڕB�:uX�j���w�q=�Æ
��suu%..�?��
6p��q�ի����G�殻��?~<��ǎ��������ȬY�شi�}��w�����4hЀ�￟��`�u�Vn�y����k��m�66l�#�<Rꍹ��.�~�������q�F���O<<<x��y��gqss��E��u�۷/��׿ؼy3O=����7o������=��Z���)""r��u��ƌ���1��رwww[G������%55Ur�;w�#G����Ö��{�Z�-�+,,d���dgg[ڎ=J\\YYY,X�;;;�cF�ũS����g���\�xѲ�NuƜ7ogΜ����{���Z�9v�+V�����L�>����%�L&N�8�o��}��g���ٳ<��3��d��-[Fzz:qqq��Ӈ���g����pqq 99�����'8r����t�ڕ��$����,� ==���d�|��
�CDDDDDDD*Or�

"((���܈�� ""��~������[�nV��A���_����e�4hЀ��H"##+��b���+s�ի��h$66���\������%33�Q�FY��1

%44��1DDD��>��s[G�k�`0�x�bڴió�>�'�|b�H�\�.]زe��c��\BB��iӦ̜9___v��ͤI�8~��UߥK����M�֭�8q"������Mzz:k֬!88���͛3u�Tn��6bcc���cÆ
����ٲeK���,7�[�|9&L����`0�{�nF���͛�K���\٢��V+fgooϳ�>k�����o����Ō3�%;;�ɓ'�믿�x�b��ù���ٽ{7���p�����{���HKK#??'''���x�qqq!--
__�Ry�miii*��AߞADn:Æ
�I�&Vw*OHH��ӓ!C��0������������TG�F�X�t)��9.�u�k.  ����rW�Ylذ���(ڴi���~~~L�4�T�u��M�V�����e˖L�:����R�DFFҬY3�֭kY]����W4�!C,��6mb����{�|��׼��[̞=���DE�3Y���i߾=��N�b���q۶m-��|����,�!?���O��'� ??���TK�EϞ=طop����-ZX����.DĊ��3S�N��_f�С�Y��������d�t"""ׇ}�����S�U�V�m�6:u�Ā�e4�2��Ջ�ӧS�~}[G�悃��޽�՗�������СC<��#��R땵��K�999�o��j���_�c:@PPP��믥ڼ��-?���p���+�\D`��0v�X���S���d*s�+���>}�����}��2�unn.m۶�j7_�#G�лwo�|�M�����ԭ[���p���K���;z��MVVvvvt��
�'N���rs�����������\�H):t <<��s���/��F�����hܸq���X-Eo�c�,X�ʕ+1�L8�V�ZѮ];$�f��ͦA�4h��1njcǎ�ĉbggg�87���	��}J*k5	��d�Ԝ9sسgw�qݻw��ۛ�R7���Ź��1y�d�
FLL��'.�x�	@�ƍi۶-�v��ĉlܸ��;���N���IMM%//���lڵk���;�׵�ב���k/"""""""է��+T֗-k�ш�h�u��NJJJ���ϟg������OOOBBB�4i���8;;_˘"""""""7%�L/����6�ղcǎRw�����$���ٴi��-���>���;ؿ?;w�����ܹ�T_OOOrrrX�v���+Uc�W����!���o��.\�N���Q��s�=:�ŋM�,�y4mڔ����Iǎ-홙��f���dff��Gq��9�v�
@׮]IOO����ٳVE;v�S�N���a��ԩS�>"""""""Rs􎖈���\u���e.�^����s��q
di<x0Ǐ'>>ކ�DDDDDDDD�.88X�_��p��ƍ���<��C��s��ӧ111deeq��v��MLLL���/�GEE�w�^���o���O�z�-���=zt���1�n�Jaa!{��eҤI��ӧO�Ww�С���g���ˋ����E�Y��ѣ����ڵ�.�k�.�5.�:x�ᇱ��c������.]��|�r�1|||���)���f�#"""""""5C+\����H���0�|RSS9�<���<��SL�8���[^^����[�����F��裏2r�H˲�ŋF�?gddp��V�X�<@�ƍ-}�4i���?+V�`�Сԯ_�Z���������M�6�.ak_|�#H-��{�q����lE���0���<����+�;|�p6n�Ȯ]�2d��>'''Ǝ[�kb�=z���Ĕ)S�2eJ��{��%  wwwN�8AHH����]������ٙ�^{�Q�F���ȓO>ɝw�	��a����9t�#F��:�Y�fVm�������������͛s��s��a���U1�t�BJJ
YYY��Ⲳ�T�$""""""Rô…�����J�Νc�ȑ$%%q��i���ػw��آ���BF��G}đ#G(**��ѣ���1f�.^�X�\�~�-yyy��@^^���5vn"""""""""׻����iӦ���/[��.����̢E�

�[n�N�:�jՊ�ӧXn<���J\\F�OOO���qss�G�,^��Z�(�Ę���
���8;;����}��GLL�=�+W�`���xyyaooOaaa��������7ް�ׯ_���x@�ƍ����q��<�ŋ���f5N`` P�H¼څyU��}������͛Keڼy3�����LDDDDDDD�fh���	�u�+���h�"RE			>|��M�2s�L|}}ٽ{7�&M���V}�.]Jvv6�[�f�ĉx{{���Ctt4���Y����`222�V�0KKK��׷Ts[ZZO>���:]�+]��G}D�:ux���>}:��'/��k׮��ё�� �~�m�b�����ΪU��[�.�=�s�̱��xYΞ=�̙3Y�j���xzz��ɓqrr*���9�3׮]����`˖-8880x�`�ΝK�z�,}J^Ӌ/2u�TV�\��qtt�u��<��3�9�Ϙ�fӧO��ޞ��([G�b6lXje��G�ШQ#�v777"""����p���^��JǬ_�>���e�3]��Bs1Cu�(��+���+��R��A�DFFy�9BBB		)�>~�xƏ_��^�z�Fbcc���������\2335j...��WDDDDDDD*OrU1`�[��k�\�p���}`u%6l�@TTmڴ.�ulҤI���KV}׭[@tt4M�6�e˖L�:���`���*,"ݷopi���Z�ha�GDDDDDDD��_|�E�YϘ1��-[���}�v�RQ��������_�x���ҥKIMM����ݽ�9����ٳ���o����bgg�}usVg��={��Z/\������j��&L�����X�m�6�m���ӧ+�f[;r����N�<�̙3K��_l�[�n���1a�quu%''�ٳgо}{'��6l_}�			�����<==2d��Ӊ�������>v��"R=			�L&mڴi�U���8rrr�������{��!����l�"�_��¹N�8\��ZI�6s�����ٹs'�ϟg������coo�޽{�����^`�ڵ���ꫯ���)(( --�-Zp��A�x�r�|�7��Ƞcǎ�ر���"~��'�v��w�}G\\\���\>>>�������YV�\�z5��{���5c|��7p���}�]�~��r��"))�;�'O�:�M!>>�g�}��1��~��0k�,z��Ń>Hhh(���[�!�/ggg�N�ʚ5k8z�(G�e͚5L�:�jE#�*�����a�]��j*Y,e0.ۧ��g�V��<f�;Eo+k^�6�y�ڴi���cƌ����������+��`��ٻ��#�<���#�ƒO?���9W�Z����i׮u����{ﵬ��t���Y���~�m�n������/�믿*|�����y��`��?���?��d��w�x��x�"[�n�u����$""___��������ӓ�����uD��:�ܹs�;w./��B�7�+W���vILL��	ZD�6KLL�u��;����s�N|�AK�Ν;K����$''��k����Y�<<<8v��N�����jߩS�,}DDDDDDD�6���Y|�����s�z��=>00��q׮]ؿ����/�lٲ��wﮱ�ՙ�u�֖���N��M)�͛Ǹq��g�ܹ�1���d����<y2QQQ�3�2����z����e�}�Q[������0��F[G���RDDDDDD��P��Ԩ��"`�""""��Ӈ���Ì3��{سg111����ٓŋEdd$w�}7'O�d�ҥ,Y�.\\Z��d2q��!�5k���ǎ#''�TaENN����������؆��s����:�N��.^�x���}�c�ICq��Y��-?_�s�ĉt�޽�q
D߾}���ω��%--���(�ΝKtt4�G��0��s��lٲ��1DDDDDDDDD�ag�R{$$$`2��iӦ��D�F�-��������ԩO?�4���J�>|8-Z�`׮]2��;ҷo_�,Y���cǎ��uww $$���.]����Ujls�C=T��("""""""��֭[�oڴ	__�r�iѢ,��.�X����[�n4�����<��Ӥ�����Ϋ���_�EDDĕ��5ѵkW�m�V��_DDDDDDDDDj/\�����U���AFF�5���ٙE��-��B�:uhժӧO������J\\F�OOO���qss�G�,^��ju������兽�=������6o�\*��͛quu�O�>W��EDDDDDD�jy���(**b��͖�\�1���?0����\�p�cǎ��+�`0�իW��ɹ�,Y��?nY�������`0��{�q��ڶmK۶m�Z�g�;w&//��;w�:������������\������ȍ�aÆL�2Ū��ѣ4j�Ȫ��͍����ލ100���@��z��a4���%77///rss���dԨQ���\�鈈��������v�mt��ɪ��ߟ_|��c&L���Ζ-[�С��>�x��W�s5i҄7�|�e˖q��q|||h޼9$22�ѣGNxx��qݻw��s��|}}iذ!������T߁���Oy饗ppp�u��Jbb"�����!"\z=������H����u�F^^&L 00WWWrrr�={6�۷���
�W_}EBB���$$$���ɐ!Cjt.������
Frr2�7�h42y�d����=�A�lٲ��ӧ��g�������ݺuc������5��j��[ošC�(((`ԨQ888��;�
�]w��?��^}��;���`00`��֭k�(�ʫ����ݻy��m�STTĀlCDDDDDDD��2�L&��C����ȍ!,,�THP����`%ddd0k�,>��2�����x�b�J5���7/����.V���̟???��GDD�J���""""���`@���/55�nݺ��_ү_?[ǩ��o"7�e˖��#DDDDDDnpZ�BDDDDj���H�5k��_́(,,��n�s�Ό9�ƍ��:t <<��s���/��BDDDDDDDDj-���رc�ӧ��-l`�������:����j�*[G���������6���F���x��(�-���%K����Ɏ;l���?���Hhh����XV���E"""""""""""""R���,n��n��v[G��D^^'Nd�ȑ�n���qnZF����[�`ٲe����:��������0\���������������d2�:�u�d21t�P4h���뱷��u$�̙3��g�2}�t[G�j�l@DDDDDDDDDDDDD�_����8�m��믿n�8r��_�>���:��z������������\5Z�BDDDD�Hbb"�����!"""����Hhh��c�����
�}��̝;�1c�УG�u�f�Hbc�ƍ�u�
�۷�j���_�~U�2��ҷ"�V�b۶mt�ԉ\�x"""""""7+\�����)**�5""""""""7�^x���d���ɥ� IDAT�;hذ��#]���D�֭KPP����H
7n)))W\�p�ڱc,`�ʕ�L&H�V�h׮�����������pTp!""""Ֆ��@BB��c����\5aaa,[���1DDDl*!!��h�r0���Ӯ];F��g�}��`�u�j[�f
���Up!R���\��%5jjՉk��L�<�������	@HH�&M"11ggg'����BDDDD�m�������:����TQ׮]y饗l����"S�iiUK)��Ã�K�����p�B��y[G��.]�0a����o���mGD�F���s��q
di<x0˗/'>>���p����BDDDD��~ 11���P[G�JJLL����1n(����{GDDD���ݻ��;�н{w[G�"�;w�ԩSdeeѶm[[��&���ˍtΟ?���7O=�'N�Wp���#66�u����ӨQ#}�QF�������y��+V0o�<v��Eݺu�ݻ7cƌ�ZQ��c.Z�����ӪU+.\����ILLd�޽���ӨQ#z��Axx8...�c��c>���_��S\^^111������D�n�x������p���>s�+V���q�Ɩ�&M����ϊ+:t(��ׯֹ�������܌Tp!""""W�h4��"""7���0[G�Z`ԨQ��p��~4h@ZZ�
.�p��9F���Ç-m{��[WXX��ѣ��ζ�=z���8���X�`vvvVnj5�S�N�����ի�x�"QQQ�s޼y�9s�R<��{�k��رc�X��ӧO3}��rϿ:�_NU�DEE�y�f�R�����IHH����s�����Pj������INN��'���y��������̪�n����������M,,,���M�6mڴ��mٲe��'W䚰���S�Nlݺ��Q�{ǎc̘1�>}��Q�
$$$p��a�6mJ\\[�neѢEV+!�-]����lZ�nͲe��X�j�ڵ#==�5k֔:�y��|�駤��1b�6l�pEc�lْ��4K������0aiiilٲ����R�P|��������9��Sܾ}�x�غu+qqqxyy���˒%Kʝ�*�����-5����GDDDDDDD*G+\���������T����V��Zk���� rMo�׽I�&�n�:bbblE����!**�6m����ǤI�x饗���[����h�6m
\*~�:u*���$%%luLdd$͚5.����Y�Tg�!C����hy�i�&L&{���믿�_~a����={�����S�<QQQ<��iӆ��(���ٰa�?���޷op����-ZX���Q�������J�������li߾}�����oժUl۶
�N�:��-"""׹��PBCCmCDDDDj@�.]x��8r���b-33���xpvv�u��ř�#����}��V����Js��!���ʜ��_-����m����
��/^ј�"�?����cDzgϞR}M&S��^��S�<%���m�p���r�J�'NP�~�R��m�>"""""""R9*���ƍGJJJ��;v�`���\�����iժ�ڵ�AR��K�N�HHH�|9\J;v,;vd���"5�d!��`�l���Z�������,����9sسgw�qݻw��ۛ�R7����S�<%��9���}�sT%�y|;;�R��me=7"""""""R>\����H�t��l���Rf����<y2���������&M�Dbb��(""""׍cǎѤI[����'7��g���7�п[G��z��a4m��g�����֭[�%�DE��q��߿��;w��Z�w��Y����'999�]����啪�1�+�������o��f�����)�kW㜪�租~�Za���7p�)OUr{xxp��1N�:����վS�NY��������H啾������H
�/s)��]||<ǏgРA����s��q���m�LDDDj���T�}�Y|}}qqq�nݺ�q���ߟ��������pU�,��~&N�Hǎqww�N�:�����e����|���o�����,�%7�o߾=�Ǐ������By��r��u��v��Q��?��#���￿Z�w=�s�j��V���^�]�����l�(R


����h4ұcG[ǑЧObbb����…�޽����R}{��	@TT{������?�䭷���ߟѣGWy��s�֭�w�^&M�di?}�4��8:t語Se�͘1���,��������믿@�޽��*�}||���)5����GDDDDDDD*G+\����H�d.�0����ŋ,Z����d�=������<��[��l?���<bccY�n���;�5��Ge�ȑ�����t��V�X�<@�ƍ-}�4i���?+V�`�Сԯ_��\ �i?~��Ç��_��w��a>��ի�ׯ˗/����)o\�/".X���/Z�;y�$۷og���̞=�_|�ٳgS�n]����{�������ɓdff����;��|��!ClM*aذaDFF˂.�?66�r\mr#��D�ڵkyꩧ����
-7�p�����mEjHXX�|�
d����>|87nd׮]���rrrb�رU��&��ѣIIIL�2�)S��ڿw�^pww�ĉ�������ڵk��9U6�ٽ��[����V�U�ݥKRRR������ϪoVV=�P��ODDDDDDD�…�����$,X��~ȡC�(**"//�ݻw3s�L�ܯ���ѣG��Gq�����8z�(qqq�3�ԗ�J���o��˳���,  ���<�
RDDD����_:w���_MӦM�;w.?��yyy�w�^f̘A���IJJ"((�.�:�
����Gy����coo��O?ͷ�~����)**��?�dݺu�/T���[��ۗ����A&�	��d��歰������|��w<��������SO����rW��<����:{{{��ϯ�o~~>˖-�N�:5^Ps�_'���…qqqaذaz
����Nbbbh֬���H
qvvfѢEq�-�P�NZ�j����,7�puu%..�ш��'������ѣG/^\�Ujb�W^y���@���qtt��#&&�R��r�JƏ������^�s�l��'ҷo_iذ!dѢEeW%w߾}qqqa��ͥ�ټy3�����NDDDDDDD�r�…�����>��S�~�m���)**"))�Y�f�r�J��*�o�ҥdggӺuk&N����7999DGG���Κ5k&##��jiii�����jnKKK��'��JWDDDDnO?�4���ݻw���?�[n�����äI�桇"%%����/�(�%22��7Ҽys>��3ڷoo��aÆ��ݛ޽{��/DJJ
���;6J}sppp�q��<���<��ü��̙3�Q�F���n���M�&M�۷/III|����r��^���'O��c��N�"�	777V�X�C=Ĝ9sx��WmI�)$$���*hذa���=
@�F�����܈�� ""��1���y��+�~��宺R|u���@�=M�)~�믿^�*��^�z�Fbcc���������\2335j...�!"""""""ִ…�����8��r�ׂ�C���V�Z�_�E������`͚5U�n�:���iժ����lْ�S����Ta�}��мy�R�Z�ha�GDDDn999<��s4k֌�u����IXX���e�7��J��� 44�[o�GGG����0agϞ��y�f���kn��V>���R�ŵnݚY�f��ڿw�^�
������xyy1|�p~��
�`������ggg���	

"==���~��F��]w�Eݺu��[�СӦM��ɓeS�l����~,X���3�~�m�b��:t�W_}���.,��^y�we�W����׹�e�^���Z��TVLL~~~�����'��;�Y~~>o��&ݺu��Ã:u�ШQ#{�16n�X��{�����iܸ1�������v��r3W���1�jժ�����`0p뭷Z��W|�x�^���[8p YYY��Y��U��0�����y��M>w�~?��Sxzz����w��[o�U�XU�U�מ9Gu^g999t�Ёz����W�j�T̓>�̙3�<y2?�����֭���|��'�>}��/r��M�pٿi��0l�0�4ib�bsBB���5�"��������M�$""""RIF��d4�}l֡C�JmWS�9���[S@@���K�.���X��筎�l��}��z��Yn��d�ر��C�����R�

L:t0u�ԩ&.������{.�T�zmڴ����fJmNNN������1e�-�9;;[�_�x���޾̾�۷7�={����3�ɓ'W�\���M�7o.��ɗ_~irvv.s�z��֭[W�ym۶����T�8GGGӖ-[��IOO7կ_��kѢEӱc�j,[IU}����&�4f̘J]_�Q�F����+���sW�:W�YQ�k�;S��V܇~hL�p�ӧO�����=w��`Z�vm��T�z$''�y��`0-Y����}�~w�y�	0egg��7{�l`
+s�9s�yNu��-�T�w5??����n2��~������7SÆ
M5�ܕ��W_��|��ĔyLUsU�w%��^�zY~8p`���},RY/^4���NS^^����
W��s111徟ٻwo��Ç�Fl����S�.]LG�19r�ԥKӿ��o[Ǫ���f+�XDDDDDDnLZ�BDDDDj\FF��v��k!00�����)S�жm[���y��w�ׯ�W��r?��T�|%�0]��Τvv��$7�]�kEDD��9q�����̙3�;�_~����ϳu�VF�Iaa!F���G�Zg2�Jm��і�~����0j�(���oF�́(,,dӦM�u�]�ر�ٳg[������c�U��֭K׮]qtt��;v�A�q��y�x�	���((( ++�'�x�s��1`��;V�#F���G%55�s�αq�F���),,d�̙V}ǎ˙3gx��g��_(,,$//�
6p�r��A˝wk"[q�y�֯_@HHH���٠A�����t\M��u6�N��=-ϵ�����]���?V�o֬Y����w�}������G~~>۶m�s�ΘL&^��J�Y��q��I�F�嘟~����~��Gz�����?_��P����/J�3��ׯ_�2��8q"�:ub۶m�����O?DAAC�������jݺu4h&�����23���a2�<x0���5�ܕ���<7d�޽�c����S��U�u��ޕ��~��v��ͩS�x�7�}=D.�`0���������\ց����駟lE䪉��$""___��������ӓ�����uD�!:t <<��s�2w�\^x����lKDDDDDD��tM�;DDDD�V�;�]�-�:�O?�d�?��C������}�5u����=����U�j��[DQ��B\h�kբUqkպ��Ώ
��h���8P(K�­D�
��~�-!	$!���ɹg��7��9�];��3�D�=z�S,�z�b���x�B)��/�D"a�{�.�nB!D[�…v4�K�2,$$De=S�N-s?'&&��D"�M�>]aߌ3��F~��~u���%�����l�,�g�fX�ΝYQQ�¾��"ֹsg�Dž��9}���Ju�:u�`5k�TH�V5x��R���$�իWOo�����Q��^�|���:���/�lllʍ�2�ֶ�ˋ��fʋ�����YXX�Y����r�[�n��C],���rD�.]��2777��pq��5����+�?{��1###��Y�:]\\�f�/yL�-��u�G^�t�`���W��\����v��Ƙ~ϝ��ŋ3���G)oaa!swwWY��������R����
�CTXXȬ���}�bH�!��pA!�B!�'Z�B!�|��� �J�o�>�d24m�͚5k��s�����������/_��ڵk!�J1~�x>/�R������͛�ݻ�+���!�BH�w��Q��ɓU�=z4�ĉj������!�����e˖)���?'NT*+�J�Ý;w����\����G���ɓ�΄[ze.###|��w��Ǐ�,?i�$��/���k��
x;�~xx8<x��svvc>�[l%�r���lllʭ�$.NN�V�T�%nm�Y[Uy�h������_f��w�1�r�O>�������|��wJeD"fϞ�QۚhӦ
�6m�K�.�ٳg|��#GP\\WWWԮ][eٹs�*�X_������#���899!##QQQ
�������C���@*���S�;�iӦ)��D�����*�>�ر��m�!�Dpuu���

!�B!�B!���B!�0b�����ѡC���#$$z�4_PP5j���:������?�333L�:��kkk�G�>}���$�X��������	!�R�RRRb��@isvvܺuKmcǎ�ݻw���_�B�Pa��۷�[��(&���l������=�^���V����R���%���X!�{�<&&C�EÆ
ѰaC�9���GAA�^c+I���
d���*�����aaa�U9}ŭm?k�*�mq�\�$����Çc�ܹ�޽;�b1�1�Qy]���}���?WY���]��54h� �=����QG�C�\ܩ��|ZE���h���
��kni=w�\�~ �HT�wss+�}�U�7������p����A�!##�СB!�B!�R�ЀB!�R�bcck����1o�<�h�&&&011A�&M��j����
aaa�X,�P(���
:u�;v(�N{{{�B�6oooXXX�ܹsJ��;wVVV����!�B�>i:�|۶mCdd$���q��A~�fI܊
��X�=�^�����r����5j��omm
@�j
܊�

����>x�;v�@�~�вeK����-��t9�*h�����p��Y�+B����gmU�5�-n{{�r��ٳM�4A�&M���%K���ɓx���Vm���R70�f͚Z�P���o�E^^��BY.�ԩ�2����g�G6B������8|�0D"���__�N�|r�4u���;�����1����������cC�R�-Z�ӧOk�z!�B!�B!�;�� �B!�2�����__�r�j����ӦMôi���׽{wt��]!������

�Ç���>|���x�7��!�B�!���x��5233�>������7�@ �_~A˖-ն����7o�h�F������(�������͛����ѧO���/�>�������,ԪUK�Lff&�>���}�������_!::��Ѹy�&���0e�:tH��r����p���۷�:u�###�ڵS��1�@���������Y[U}�h�̙3ԯ
������!C-Z���ШQ#ԩSNNN�`M��\���L��k��JyZ�j''';v)))x��d2�b1ڴi����{wL%�T�Y�^=xyy�?���]����b׮](,,D�^�`gg����S���YYYjϧ����:��y׹��C(���߿��é2�n����n�:p����@DD��� �B!�ByoрB!�BdĈ8z�(���1c�@xx8�b��,��B��q��5\�p={�Ը\^^ �ɰhѢ2}6i����HJJ���G�u��ĦM�0u�T�3�s8�ׯ_+<�ߤI\�z�/_F�=��\�t�ϧO
6�ȑ#1r�H��#GЧO��y}Ǧ�=z4V�X�m۶a���pqqQ؟���6mڠ{����y��HJJ�֭[�V�odd���b�d2�������wI��u͔���[�l��ӧ̼���G�H IDAT=`���7n�¾�3��Ȩ�E�u�DGG��իJ�Ճ�+jРAX�`�.]�~��z��4����W��K�.J�/^�nݚO���?��;w�ķ�~��۷��%��ܩҲeK�����ŋ*W��v��r����������ѵkW4l��С(���B�֭�A
��>}:�7o�ѣG:�����_~���� �B!�By�i�B!�B�D*�V��077ǂp��!<~��?ơC��`����:<B!�h�{�ᅦ\.W�	�@��npp0���9s��F�Ν���J���� ШQ#>�/�����<y�A�A&���;##�V��������tooo��+P\\�P����V�t�ڵ��5ѨQ#$''+�S��>c��}��'F~~>|||��NHH@ff&6l�gggL�4	={�D~~>�u�:(䷵�\�|Y����0�ŭm?��/�ϪT�5��9s� 99����ݻw�yo߾
6l�Ҿ5k��?���ۮ.�ѷo_��ի�S(���������;V�\	*��z�j����"�����t�Gr���P�fM$&&"<<��ɨU��� 5}�;uq����QTT��_ݹ�5.u��>#DS���X�r%���dh���x��è2�N����f��BC�C!�B!�BH��!�B�P`` T�Z[��R�wMxx8�6m�6m���0t8�B�s����}�iedd�5j0�k׮�ҥK,77��:u��;����0�H����2dا�~�޼ySn,7o�d����5k{��	���a��svvf����ܹs�թS�`�|�	[�~=KKKc���L&����D�b�
���3l޼y
�<x�������ǒ��Y~~>KNNf~~~���`w��U(���գ��3g�d���;q�{��
+,,d�����ۛ`���t9�1&��Y߾}fll�F��N�<�^�x�
ٓ'O�رc�60[[[���>�bvttd�Νc������l�ԩ���Loqk�ό1������
Y~~����k�����B���#v��!ֽ{w��={��:6a����&��YRR6l�¹�w�^�����_�f����ׯKIIa,99���ۗYZZ��_�*�Z���D"���Uf������Y~~>��X�=��Mnn._F�XI�ƍc�{ڤI�����ܩJ���bb��`���,>>�����ׯ��Z�j��K׸Խ�*�}V2_xx��ׄ�CBB377W��Q��rC�Pe�r9kݺ5�ݻ��C!R��I�Kh����q���^B!�By7�ov�B!Dc�&!���ϵ�M=z�����}�b�ƍ
�%�Vj0�Xhh(*󹻻+<��ILLdM�6-�
�P����C��=Jo����JeT�^���,���6F{{{�������#��ق�ơj�5k��ÜW�\QXQr۲e���֥�;u��TWU]3%��۬��T����]z�;w.�~ڷo�F1�����
+Jnaaa���<�kIK�,��w�ر�:###����R|vvv,!!A����1NLL�B�+W�(���S��j֬���]�v�,�k\e��*�}V2
� UaӦML(�S�N:��֭[���1KMM5t(DC�!�[�4�B!�B�F �B!�B!�T������1j�(4h���ƨQ����p��	L�0A!ZZ��m�5
gϞEϞ=Q�fM����E�X�x1N�>
333�2...HLLĖ-[УG��b���͚5øq����l�O�>�v��
�X�H�X��Ç#.._~���ǡ���
bbb0k�,�l�����Dpttķ�~���8888TZlڞ?�P(���q��,Y��۷G�ڵ!
aff����V����ajj�e˖���S��T����������011���+�9�1c��-n]�y����ѣ,--!�P�~�2�������D"ԩS�ڵÂp��m��3fv�܉�>�������A�n�p��,Z�s��l޼Y��t����c���|ggg�۷
{C3����)7��p��H�R�D"4n�ӧOGbb"Z�j��_����
-Z��&�J���ܩ�����1c�s��䄈�6Le]�*�W�g�T���ѷo_2Ϟ=3t8�O?�k֬A���

!�B!�B!Ֆ�1�*R����q��%}�C!��JаaC���:�2d <<\�kB!�T�v����ݻw+V�@JJ
N�>m�p�;(--
���h֬nܸ��zSSS����@���T4k�Le>�@��H5&���@��	ѧ��L�i�NNN8z�(�!��F��R�EDD`Ȑ!�g�ү	!�B!���D� ::��"�B!�S`` ���B!�B�lذ��a�j�������y�&�6m��۶m�D��v�;���/�� �}�Y�&~��Wt��۶m+sU'BH�v��
����>}�Brr2޼y�-Z�K�.��󃵵��mr+^��ƢG�x���9;;;�|��߇��?���ѣ����<|�~~~�裏p��q�����S�?��O[����x�"���q�\��B!�B!W��O!�TO40�T���DDD:B!�h�f�&������gΜ��A��j�*������w���m۰r�J�رc��ޫW�����u���Ν��z	!DSnnn8r�<==

!DG�~�-Ξ=�4�@&�a�̙�p�BzBB�y��S�N��e˖��￑���4�"::`bb����?^a$''�T����qqqX�~=����
�f͚��>��	!�B!����\B!����_�/����aB!DK
64t�B�X�z5�v트�8t��Ui�@ �����`"ԪU��900mڴ�K�����ݻ:BH�={VezHH.\���u�b„	���@�5���S�߿�v��w�}�m۶�U�V���ٙpѥK�}܀�!C�`��툎�Vp����,��?�-77s��E���!�����3g���ss�*��B!�By��}����q��%}WK!�-4l������B!�B!Zj۶-�z�jDEE��ݻ(,,���<==��7���Mo�5h����/����y�f��K!�;w�������2t(������q��9ԪU;v�@ݺu�}�����ɓaaa��7b�ƍشiS���Jp'82�qqq����ȑ#�g�\�|011��p�.ؾ};�={���>m����_�}�vL�8р�B!�B!������Ɛ!C�]-!�B����pC�A>?��"""!�B�D�	!�z�_�>~���*i��Z�g�UR$�R�DFFb�ڵx�葡C!D�^�x��~�	������E�&M0|�p̞=���2����8y�$�?�:u�gϞ=z4?XA*��cccq��a��a�[�4h� 0�ТE����llٲ�N��˗/Q�Nt��cǎ����ʺ��ׯ_WH�|�2
���	����ԩS���E�v����HMMU���p^�|�
6��ٳ���E�.]�~+����dX�|9Μ9333����&M���)˖-[p��	<~����hҤ	���V������ݻ��+��R)v�ލaÆ���ZeB!�B!Dszp��?�B!�AIU�6	!��w}^$�B!�|�9s&���ѸqcC�Sa2�>>>���ѦMC�C$''�G�FFF�����4h


0~�x�#?~���0$%%a���022R�Vbb"���%u,--��W_)��y�_}�����'O� ""�/_FXX,,,��Q�������C<x�
4�?^!OOO�:u
������w�B&��^�z�Q���X���1j�(<|��O��?������T�9s&.\���2""r�3f��_��v���"11������������L&㏡�v������8q����U|�B!�BQ��B!�B!�B!�B�I�R����k��V�X���8ԯ_�С
GFF�ի���0���`˖-*W���_���DDD�ҥK����g�}�˗/�СCWo����_�|�`oo�U��v�Bzz:���CCCQ�^=ܾ};v�P[�����p����@���h>��[�B���>D�
�s�N��nݺ��O]p^�z���H�;w�ӧO���X�nbbb��c�̙�={�(����R�\�r�"�B!�B�\B!�B!�B!�B����,Z��`훙�A*�*<������ʕ+1g�|��G���`HH>��S�m۶�3g�Rޓ'O�.]�f͚A(�q��X�`�رce�%
�����u��*�N�R[�h�
��y�&�={�f͚��~�ڵѢE<z�w��Q�_ր�3g�fϞ
ggg��f͚���͚5�7���9ƌ�)��;����W�^����������7Jm4j�H!!�B!�B*Fd�y_<y�vvv��R
����ˍ7мys��"##q��E���X��B!�B!��7�ܹ��iӦ<x�Ab���ѣG
Ҷ>͞=vvv���

�R�T)�[e�޽{�6m�(�o۶�R����|}}U�s���2�[�.222��c4n�Xe�rrr`eeŧ=|�кuk��\̏=R�f�.�S���
�<==q��uDGG�O>Arr�ByU222�~��ʸ4����\�F
��R�L�����ŋ�x�"6mڄQ�F!00fff|���`mm�����!�B!�BH��
%DGGc̘1prr���LMMѠA�����2US��@���a���puu���-D"lmm��_ $$���zo��lݺU�r�@����Ko\��i�����.eա�XI,���!!!�����?� $$>>>��U�~��]\\ �Q�k׮A �U�V:���Xu�}�[Y�BȻ��o�Ő!CT����1}�tcݺu�����	!�R"""��Mm��Fm�FHu���I�&a���HKK3H���HIIy�Z�r�
~���X������T�1�ת���͛2�s.\��6Orr2:w� �Y�&+e�h�FFFHMMEqq1Ο?@�����r��n݂@ (��9\���H�9.MLL��߽{w?~���C�֭�����7��������;gFFʏ|pi�:!�B!�����gϞ!((ǏWڗ��������o����
D�����nj3�~�z�/�233q��\�r?��&O��~���w�ر�AkEEE���D||<���a�lݺC�5th��ɓ'8~�8�?��ׯc���j�Ο?����/#F���3���ח�?44�/�>y���Ξ=�2=77s��E����Az����3g���ss��B!��믿Ɨ_~i�0!��J���j��Z�
.\@@@Ο?_��֮];o�ݻw����1L�::t@�~��"�j�4h�iii����_��&)�Ÿw�>���d={�ıc�ԪUKaqq16o��z���P�W��޽���x�����mʊ����5Bzz:��㑘����(�kٲ%jժ������5����ں4h���t\�v��7@RR�杢!������)))�믿�s�N�Y��/׮]O�<AVVj׮�P>++��C!�B!�����W�x��)���q��qԫW�V�Brr2d2��󑚚�ŋ���ǎ���/�r���~g���G��駟 
1r�HDEE�ٳg(,,�˗/q��I֮]ooo���6p=b��;LU�mx��)���O���yyy>|���\��1蓣�#N�<��������������#�/C��aÆA("<<yyye����CDDD"������/!�"�T�r)��������3�i�Ƴgϰ}�vFF!�B!���255��ݻq��
̚5��ۯ]�6�ϟ�
Ty��w�^���`͚5��T^^^�e˖!))	r����X�l�R�Ν;BBB������"�|�k׮�T*����J
��������Ѷm[<�AAA8q����QXX���dL�2/^������ϗ�ԩ`�ҥHHH�\.GBBc����<Ɩ-[x;�Wqq1ڵk��
�@ @�v�PTT���0�r���у��ڵk���HNN����WUh���R����L&CӦMѬY3���1��y���{��)��qy!�B!�R1�
#G�Dzz::v���5k�T�߼ys̙3_~�%ڷo��g�b��͘<y��"~�̘1gΜ���8�6m�(�U��u�nݺa�����ٳg1m�4lذ�@Q���Q�n]t��]�v�w�}�+V`ܸqHKK{�Vі��~��'�����֭��3g� ''ÇǦM��������8v���ߏ��@�y��7dff�W�^�����(	!���blٲ'N���Ǐall�&M����OiVj�L���P�<yϟ?G�:uгgO�=��9������Xdggc������Q�n]>����R)v�ލaÆ��ں
��B!��~BDD��� �B*Uxxx���R��6m�M�6aذa�ҥz��U��ϟ?�J�ӧ���#44m۶5t(��2d���ܽ{��O��� �9s			J�e���a�ԩ�k[[[����X,��Ç˗/DŽ	����ٳg+�ѹsg,^����]	�ԩS��>F����aÆJi��l�G���K�*�yzz�ȑ#�|�2_�,C��_��7n(�n���4�A]hbĈX�t)�/_��˗+�+�^���ٳg������V�(op
!�B!�B4S�+\ܻwcǎEÆ
ajj
�X�!C� %%Ee~�@P�VZll,��>�&&&hҤ	fΜ�7o�(�;w��?��>����WlQ������֭[�����bĈ������	����[�n�y\p��t����氵����/��Ni�n�������SSSԬY�.Dff��2��Vm�_ZZ֯_sssDEE)
�(M"���ѣ066��͛q��
���η&����4���m��.��UU׌��-[��m���Çطo�ڶ9yyy���ѡCԮ]"�u��A�^�p������:MII��Q�n]����m۶���]/>>>�rE���\>Ut郒qm߾-[����1>��#4H��(�*M�kI�>羬

U[g�\~}^_e���Xccc4m�k׮-�.m���š˽�޽{�H$���D�>}4�
B>,�ׯǶm�p��}B&�!11K�,Axx8�����Ǐ�Ν;���#����Ô)SP\\\f;QQQ��d
��sڵk�L�'N�!�b8���J+I�Fm��F��R
2#F���ɓi%z-���r�'ssslٲ����Y�&D"�5k�E�?�XYY!,,�����
����A�N��c������aoo�P���|�Z��k�.|��7pvv���,--ѵkWlܸ+W�����B����ؾ};��u�B(�nݺ<x0v���2���ٙ����H������)�pabb�-[����������	�����W]h������C�-`bb�?�����aaa�s��)�q��9XYY�+�B!�B!��X�����Ք~]����lll���̌=zT����%7sss��;v�`B�Pe�6mڰ7o��yǎ���s�jt�yyy�ܹs,??_!�ȑ#���\e������ɓj���ŋ���L����	�p�B�˗/3kkk�}ѨQ#�����V���o֬Y�2e�F��7n����5�K�qk��e]�e�UU׌&�VҶm�6p�2�x��5k۶��c����ǢK�8qBe�@�~��g�mq�y(� IDATyy��‚5m�Te_4nܘ�������uU�V�X�����i��S���K����1[[[&Xzz�ʾNKKc��ժU�����R�~��Q��ܲe��r�5�?T�^ХK��A�)�	d���j_R�^_��I$��MIǎ�D"a.\`,''��ݻ�I$֧O>_hh(�H$lĈ�ƍL.����4��W_1�D�8P�qL�2�I$v��U�bcc�D"aS�N��%�B�D��C�E!�C�����}M���y󆥦�:B��~?y������۴i�J�,##�O���`R��mݺՀ�}��y~�B!�BȻ��V����ѿdggc�ԩ�u�rss�ѣG������x���B9�bv��K��m��|���7EEE?~<�ܹ�������pttD\\~��>tt4h��)<==f�x��	���???$%%!??III���CNN�'O���sԨQ�ٳ'�������3gΠI�&(((��%K�N�:���3fnݺ����d2�>}-[��ݻwf��hl%�r����/og��F@@�ԩSZ��W���3+5��`���f����	�v�Z���/_�k׮�����ѐ�d����ŋ�������{��ԥ?233ȗINNF~~>�]��.]�`„	�kjj�.]��֭[J+	\�~����ر#,,,*�fϞ
777\�xyyyHNN���/���1t�P<�\��T��Zҵ�MMM����T�	c�����^�/U�?�ˠA�������|�����Km���U�����[�n!11YYYX�z��AHe�J�
[y镁�����#22�^�B����C��N�<	X�t)�5k�P�ƍc���cǎ���*����ҾF�)�!�B!�B!����T�Q���:@*�b߾}x��5���q���o�mڴ1p�D#F�����Š������:t�##�B!�B�3�����K�2,$$De=S�N-s?'&&��D"�M�>]aߌ3T���cW�\a���	8������*�Ͳ̞=�`�;wfEEE
����X�ΝU�oV����+�y��)�լYS!����իWJe���V�^=��V�.�F�{���2�����)7�ʈ[�~./����)/�Ҹ�,,,ʬ���P9���[�T֡.]��[�K�.Je
����F�lܸ�`?���B��+W2l�ڵj�h���0�L��x-Z��r�Ҵ��*��.]bX�������rfoo��+W�0��{}�J_�x1�|||��2ww�J9�U�^�O�N�K*����Dy[e���b�ڵ�����`���,77W!_�<��Ν;+WI���L"�(���c���L"�077��9HB!D�yQ;��ӧO�D"a]�ve�1��&�HXϞ=+=�w�!g�.��={���S���S��={�TaT�R��V� ��j����-[�L�ݺuSX)��bcc���{��{�����P��,R5h�B!�By?U�
G�L�<Y�ѣGN�8�����,<r����X�l��?��0q�D��R��1ܹs�O���XYYiq$���g̘##��422�w�}8~����&MRJ��/�_�VHoР������x�������1<|�Po����{��
��Ʀ�K�����hUN]�ֶ��U�׌�������e�{�.ch۶�ҾO>�������|��wJeD"fϞ�Q�>>>�#G�(�s����T��Νsss�����]��*��6�RE���/����222��/**
>���?ӽ>�/U�>�6m��>�H�ei�������;j�!�����^�w��Ǐc޼yhݺ5���q�F�����~��2V���L��@ ��r�4.!�B�III�~�P򵋋��b�N���[2�ڵ����c���ƺu�_�B!�R�f̘�iӦ���	fff022�X,���?���aooo���$	&N��U�VaժU�4i�ʿeB!�B!Dw��j(%% ���w��-��Ǝ��w�������+�B��۷oZ�n�QL666���Dvv6jԨ�Qu�r)�ƥs����訔fii	(..VH�={6F�������x;8�k׮�ӧz��
��V�.����
YYY���B�ڵ�m����
���и�:�ĭm?k�*�mq�\�$������d\�|�.]�F(��U�.��=��矫,���Q�pvvƹs琝�
kkkdee��hڴ�ʾVE�>P��<wL���z-��6�RE�|Ĉ�9s&BCCѳgO>=44�߯JE�/U�_���Ъ����[�>�轀F)���
|}}��닔����_عs'֬Y�~��x�9�޽{8|�p��T�]�6�<y��3OVV��B!u.����g�V��sss1w�\��ߟ�<���9s�`�޽JB!�TW�1����������4t(D��B!�B!���V��t�}u��mۆ��HX[[�����U���>������<�,��^s��
ذ���~�nEMa���
3R<x�;v�@�~�вeK����-��t9͚5$&&jT����f��]�ֶ��U�׌��`4��fϞ=hҤ	�4i___,Y�'O����ϵjS���Η��!5k�Ը}�
������e�n��HԩSGe:wL�fS׵�*�\K��aÆA(�СC|�<���H$�СC���R���k�����g\��cP!�;???H�R�۷2�M�6�?��:w�		Ajj*������K�]�R��Ǐ��r���>�ּys��{��b�Ҹ<�By?I�R~۵k`˖-�J�ؽ{7`ݺu��~�zپ};�={���>m��x���o�n��!�R��1��lW���ǎ3t(�B!�B!��W�l�7kzff&cj���"��ׯ_�7�|�@�_~�-[�,�
M8n߾= **J��7o�D�ڵ���f/.-33S!���۷/�^��{��!,,�F��LKKÔ)S*%6]Ο��`߾}Zcdd$�]�v*���A>//Ooq�������ƙ3g��q��������E��;w.BCCq��AܼyS�6u����4uu��
�8z�¿�
��h��OqǤn���*��}^�^=xyy�����h׮](,,���7�������:u1��︪󽀐��z����ѡC���#$$V�Q�FHHH�СC���
ooo����033�ԩS��ܠ_�������٫K�Ҹϝ�B!���ӧ�?>�u�777�|�.;;�W�F�^����޽{c͚5J�wrIn߾��'���]�vŲeː����+..��͛���wwwt��#G����PW�zK�|��5t�҅�Z2����9numgggc������Q�n]>���?`�0O!���'//AAA�����>|��ǏWz;�Z�~=������b�P!�B!�By�Tـn5�.hU.//��dX�p!|}}��mҤ	�����Z�i�&��pz��~�Za)^��˗/�,s��%�|�ҰaC�9����q�>���.�o����Dضm��s����f͚a��ɸq����n�֭��$X�����U&�)Օ�����KҤ��e�k�<EEEزe�����6oތ�ׯcѢE5j|}}V�)...�]]���c�իWU���+����������CTT,--ѱc�2�U���~��E@�֭�Z�����AAA��;w?K(����
7h��Ү]��2]�qU�{!�%66�J��]���?�͛�-Z���&&&hҤ	����p�B>�������X�Pt��	;v�PX�"88���
�(((x{{����ΝS��ܹs�����B!��}։��888 66;v��vЪ�<��bĈ8z�(233!��q��m̛7��Nx;�����¯����O�B.��ɓ'�����ѣU~�2n�8\�|yyy����o���5k��ׯ_�m۶��(,,�L&Cbb"�,Y���p��_�f
���>��U����L&S9�G�v� ��p��	��!�BH�155��Ǐ��������+�
]�x��/Fpp06lh�p!�B!�By�����=z�ڵk��������H����H4={�T�}.88			�ǜ9s�l�s�Έ��Ghh(?�0'))	�Z�����޽��,�^^^8y�$
�}�����Be�X�j���̧{{{��իX�b�w��
�>t�j�*@׮]��r4j����CRR��������>c��}��'���������]a6鄄dffbÆ
ؼy3ƍ�C�!??ݺuC�ڰ���˗/q��et��Ya_XX���ֶ�@ �1���b�~V�*�m̙3���pttD�޽��{��m��aÔ��|�"77���u鏾}�"::�W������ (�_F"�^^^����gϞ�O�>055-�\E�`����ҥ�BZQQ~��@�~�T��k���G�����f͚HLLDxx8���Q�V-��t�������˗���B�Pa��c�5.u���z/ ��|��rZ�__�2�rlll0m�4L�6��|ݻwG����,--���P<|������z�q�Ʃ��I!���7�7h���ʶs�N�x�-[�Ē%KP�N���8p����	v�څ��t���c���prrBJJ
�Ν�۷ocǎ�8q�B�X�`>��c���",,�O��Wۿ?`ݺu�J�(,,ıcǰ|�r�ٳC�All,�����'�7FXXLLL�~�����trrR��K;�|���M!���صk>��3�7���k�����E������ŕ֎.,X̘1�С���@aa��� �ػw��C �B!�R	�l���'�F�8�<z��ψw��i�7Æ
�H$�ҥK�2�†
�駟b׮]
��2a����b���={6�>}
�L�S�N�Y��I}˖-�S��?lذ��������ERRV�\	�T�/^`Μ9
3�O�0���8}�4���������������gΜ���&O�\�>�V|0`N�<�����r$%%!00����.��,Y��}��pss�W_}�?��/_������D�;EEEظq#222`kk��|_���'`�ر���F^^���0m�4lܸQoqk��������\��x�JU^3e���x��1>ooo,_����

U�R7;Rpp0�>}���"$''c���
��|���8t�1c���'N���p��u"%%���CLL�V}����7o�����cǎaРAHMMEAAлwoDGG�O>��Q��Z�����fff4h`ʔ)޾�J?H���K�	&@,�ܹs�ի��� 55T��q��?T�{y�dee���
�������q��a�z���a}F�;;;�ٛ���!�1t�PFF!����
��&p(���EGG�O���
���!!!���Ł�|�O������O?���1Z�n�ٳgN�:�T��3аaC���bȐ!�0�47�4<<���x�������X:tH�����`m�[n�U�}�5R�C!�����?��?����H~%������PX�V�HNN���?|���
�1����+`�0!�g���$�B!�������pV��үK:z�(377gTn7nT�/�H��-�����|���,77W)���Dִi�2�
�l޼y*��СC���Te9SSSv��2�b/oVVsrrR���=�{�n�Ŧ����r�`��q��f͚��r�B=W�\afff*�oٲEoq��ϝ:uR{]���������mVVV*�UUw�.�͝;�?�۷O�u���hfii��LXX��դ�=z�p߸w�^�e*�������V����KHHP����K�d��}^RLL�B�+W�(����*=&&�լYSe�v���9/�P��d���j_��Wqq1�jԨ�\\\�@ `FFF�U�Vl���lϞ=����jC�חD"���bcc���{��{�����`W�^5H,�BHY��v4���9��͍I$���_f>www&�HX^^�Bz^^�H$��ݝO��.((�ӊ����'**��k׎O���`���J�ũ�.�t��t��ǭ�>WWW�e���D"annne�K!�,<<\�kB��Y�f1���Tim�mۖ}��7�V�.����D"aEEE��T����wKY��B!�BywT�
��Y����1j�(4h���ƨQ����p��	L�0A!ZZ��m�5
gϞEϞ=Q�fM����E�X�x1N�>
333�2...HLLĖ-[УG��b���͚5øq����l�O�>�v��
�X�H�X��Ç#.._~���ǡ���
bbb0k�,�l�����Dpttķ�~���8������#
1�|ܹsK�,A���Q�vm�B�������z�ªU�0�|���bٲe���T����������011���+�9�1c��-n]�y����ѣ,--!�P�~�2�������D"ԩS�ڵÂp��m��3fv�܉�>�������A�n�p��,Z�s��l޼Y��t����c���|ggg�۷�_ц�]�<b�mڴ�v�Qn%����̙3�J��Dhܸ1�O����D�j�Jm����}�Z�h��W*�*����.������yXU����'
(8%���F����J?M����i�p8�4�"%	�y�JM���9KR�43�������>ndҍ�z\W{�׽��{�mI{�{��3r�Hӱ4oޜ��h���>E�+��>�������ʊG}���@�p��W�����o����'''�4iˆ#���O���_-��C�M�6���Jhh(o������NKDDDʐ�u���[�n����&�uz��ŦM�

�e˖\�~����/��_h���[dgg�^��U�8�mܷ\��_�NJ{^EDD�>}:�[�f�����ݓ5:w�l�Ulٲ�-[�0w��\���ʾ��eDGG���e��y�{��:s��>ǎ�o��t:���_hԨM�4���Nnj�&��7����/����E^^^DEE�^n�ڵ�S�N̝;7Ƕ��T�����ݻٵk�ƍt��OOO��o�|���<��y��|<x�7�x�.]���y��quue���%׾}���o��駟ҢE�<�<<<8}�4~�!�ڵ3�s�_���H�X(o6G^�Fǎc۶m,[��
*�w��<��k��mے��͎;�R��iޡC����s[��_&99�-[�P�V-��?���޽{�������WD�aceeETT�����)�iݺ5|��.�ccc�������~�ӽ���Ά
���t*r�xyyM�~�,���@ll,Pz�񊈈���H��Q'R�ԯ_�?�P���J�*aee��?���O>���I�R2t�EJ��7o���ġC����!)))׸�U�һwof̘��-[6m�믿x�gJŅb��ѣG�����~�ԩ���$''s��u��}}��5�u��
���`�9BVVG�a֬Yt�ҥ�k���>��s���hܸ1M�4r��x�9kԨ�ڵkIOO�ԩS�����s[�iӦ����q�#"""�_�z�HHH�'�/���Ν+5ߡ��٩آ�i׮��-D ���ӿ�""""""kK' "RX�ڵcǎ0���PڵkG�
���_��O�={6o��3}x蜋X���INN�ܹs�?��gϒ���ٳg9�<�Ν#99���n޼iگk׮y�y��%.\Ȃ�r�
�G�f�ĉ4l��~�����C�4\6�����#G����/�m9r�鵷�7۷o'11��Ç��իW/�XAx{{LHHH��WWW��5jp��E�����9�[�n�^�����3�|:v�#��ǝ�ڝ:ub�Ν=zB��� IDAT�,O��gX��gg�{6w�J�JM���Mcƌa̘1�NCDDDDDDD�LQ���<p�̙CϞ=9t�={�̱��ʊ���;��t�EJ��˗sQ���襤���(����t��~�<����899���ēO>������8;;S�N�/_ΪU�r����3�|/^L����e̘1ԩS�~�����C���~���P�V-"##	g���\�~�F����c��rU�V%22��?��;v��R�V-z���ȑ#���/�����X[[éS�x���ҥ��ަ��'�����LFFF�s�?�r����W_�����` 00�^x�Hǝ�ڽ{�f����޽��C��ͻ{�n�T����?_��!"""""""""""""\����Օ���̙Ö-[8}�4���8::ҹsgƎK���-��CE�\�����III!))�����.�:R$%%���Dzz�i?kkk�ԩc*�hذ!]�t�N�:ԭ[�֭K�:u����kO<��Ν3�����={6QQQ<��#1j�(�V�Zb�Mfff��'"""�Vll,����N㡳q�F��_��E�pvv&88��qժUc���L�<9߸�����������|�z��W�^Z�������_���m�ʕ+���ɒ%K8{�,u����ٳ>|�Q�F�)�"""""""""""""e�
.D��裏2o�<K�Qh���u���s��z�����…�;w�.�Vǯ^�j�o�*Upvv��GGGڴicVD�裏����VVV%����׮]c�֭|��G�[��ƍ�p�B�R����h׮��-DDD0����]�v�NC���fÆ
DEE�
P���prrb���NDDDDDDDDDDDDD,I"""R�\�t���ϓ��Brr2�ϟ�…f�)��w��Y�&u�ԡv��899���j*��}��;;;�����{��g�!66�>}�P�\�{�ޘ1c3f�=�[DDD�ad0�ɼyu������cڴi�;�!C��n�:,X@Ŋ-������dffbccc�4DDDDDDDDD�\�����?�0K�^8a|}��y����p�7n�0�geeE�ڵM�&���hР������:u����H�ڵK�;Ľ���L�޽��?�I����z^^^DGG��uDDD�dyzze�4DJ�6m����Khh(o������JDDDJJLL˖-cݺu�/_�l[VV7oޤB�
E�?55�C�����K/�T�tٶm��קQ�F���7oҡCF��ȑ#�������������
.DDD������…f�.\ 99�T8q{aEff�i���˛�(��&�5k����ٸ�Xtl޼���icc�6EDD ^^^�N�LS'�����OOOK�!"""�@�ƍٶm3g�$((�4������AAA���h��W����9u��}�'N��֭[:�D
.�����/�0aS�L�z��DFFr���t�R�EDDDDDDDD���Y�Ell콚ZDDD�K�~�,�F��]��o��FJJ���Ν�ё�…dee�����6�B������󄣣�鵃�VVV<ʲ�_�~��Ϝ����v�ZK� """"r_�nݚ9s�0v�X�u�F׮]ٰa���������Ypq��e"##ٷoG����ܺuڴi���mڴ��^�Y�f%���ӧ�X�"˖-#22???���x��7Kl
)�{Vpѿ�{5�����2W�^�����X`q��5�>���ԩS�T,���H�֭sV888P�vm����������<��z�-�mۆ��'������MÆ
�;w.����������ޞ��p~��0�iӆ�{��������5*v�7o��ĉ|��G��ۗٳg3s�L�T����+���z���������}T����xzz��"""b����={���dΞ=�gAEn�u����ё'�|��={������@�r�,xtR����0{�l8@ff&���,]����x�&w������h߾���EDDDDDDD �.:t�?�����p��)ٱc�?�|�}�������14nܘ>}��9u�7oޤq������_%==�'�|�jժ1c��x�
���>|8�-b޼y�o߾�k����������ݕx�Ş={X�`AIO+"""�йsgƌS�v��ԩSM�R�������>J�:upqq�gϞ���B�:u��	kRhS�L��������ݡC�gժUdgg3`��4iB�V�,������g���dffZ:
)�
6����O<��+pqq�A��lْ�k��ZpЪU+S�C߾}���7��/���*���ʕ+G�-Lc���#::�I�&���G�pssc���ԩS��k���������H�J��"11���X���W�S���H���bccS�}�V�����=�u�֥N�:������СC�n��b��Yvv��rx9r��>��6mڐ��Ŵi�,��m���	���'''��ݙ2e
������Y8C�_ڵk�by���׏z��Y:
�������?�����ۛ?��J�*����ۗŋ�gW�������0}�tBCCͶ�<y�:u��(�(��G�ҠA*W��c[�֭���`ǎԬY�Gy��뉈�������H�J���(&&�^M-"""����*�mڴ�M�6%��e��Ӈ/��R����` >>>��YYY�8+++lmm�[nIJJ
4�
4�+V�������i̘1E�&'""""��ܹsy����s�ީO�>L�6�о}�\�U�����;v,#F��Y�f�m'O��Q�F%��?�`���(;;���BBB�1c%������������/�G�����<���KK� `,�h۶��`0��`0�q�F�}7oތ�`���?�>w�q���7x��w�ܹ3=z� ((�?���l���TV�\I۶mqpp0�;::b0X�r%����<"""�������J?�я~��'::��劔���{�p��E�y�:�#�e˖4hЀ5k��;�o���O>�رc����4hP"�&$$��SO��eff���Chh(���*����Y������ϡC�x���quu��ё��dBBBppp�w�)Ҽ��ׯ��lܸ�Ç�|�r���زeiiit��1�;v�lݺ��^{��("""���,�����=ѿK� R����x��y��>|8�ڵ#  �w�yS\߾}Y�f
�^�s�/_���p�t�Bll,������C���533����'�|�4���������c�����ݻ�눈�������H���:~�8M�6-uk���@���u�EDDW�2c�bbb8{�,NNNxyyHŊ���dŊ|��2Ĵott4^^^��׏��XӸ�����^��9��������Ύ~��J�ʕM���ɼ��;�[��k׮�������nݺŴi�X�j�O����^�uF�Q�g�o�>�kLժUy��w�%((�E�1u�T�]���o*�(�={��`�ڶmˏ?�Ȕ)S8w�˗/�����{�мy����ݫ��2�_�~���DDDD�аaC���,X@@@_~�%����l����bΜ9���fw�ԩC�e�ĉ���K���r��5jT���'233qqq�����_$))�;vЦM�b�!"""""""""����Rf„	�ܹ3ϛ
-���C�gժUdgg3`��4iB�V��{�""��~�:ݻw7���̙3s��l�B�r�X�p!�w������g��^�z$&&���Kݺu����
.����w�Ο�	@ZZ�-��͛,^������N�:q��)�>���\�r%����̞=��>##���8���r�
~~~E8s�����n���m۶xzz�믿NBB�
�g�)r������O?�4���[|��7����ǏP�~��?���f1""""""""Rz�+W�q����K/1l�0�y��L�¿��/:t耣�#k֬ɷ� $$��M�������4lذ�%$$`ccC�f�8~�8������-����'�(��"""""""""Rx��"��Ν;K�������ၓ���θ��3e�����s�""�0�3g���k׎C�����?�@�Ν��믉���z��,[��+W�0t�Pn޼���7W�\a�ҥԨQ�����la|_�5n״iSN�8AZZ�Y�ƴ=44�S�NѨQ#���[nܸ�Ν;9r�H���E�7o�ƍ����p�B���J�L>��z�-5jDBB
4���.�|�۷7{o,&����Mc/^��q'�1FDDD�a�_�iLL~~~���s�)�ƍ�k�.f͚ŬY�h߾=ǎ�����{��8::��ٳٺu+@�t�8v�M�4!>>�N�:���b�X���`����R�DFF�����Mc�
"%%���Hf&""��Y+V��U�VX[[ӢE�.]
����M�=z�`����ܹ�Ν;�c�ƌ�s�=Wbk���Ѹqc���?~<`~��ڵk���y�g����k׮|��G9�R�
s��%<<����|�M������_r����f?w/i��ddd�gmm���֭[f]N���r�nj1""""�	&����6cW�I�&1q�D���8|��}�PDDD��ʕ+����������?���9s��]�3f�?�8o��&5k֤f͚��)!!��'OҳgO:u�ĶmۨU�V����+s.Ο?�ԩSy��h߾=d�ƍ9�RSS�3g/���۷��_f�ܹ\�z�,�X8r��I|}}�ܹ3={�d֬Yf�nݺŢE�pww�C�t�ڕaÆ�n�4�u缷�>x� =z�`���9br˩0ǝ�ک���\���m����`�qtt�`0�r�JRSS�9�"""���?РA���L?Ƨ�%$$����SOG�-		)�5\\\L��N�7��<y�:��׵k�s���bgg�֭[�0aO=��������5w�?���'OҢEN�:Exx��vc�õk�Lc��'7wv!9t���S��/_��c�.|�����L]QEDD�a֬Y3v��Ϳ��o�������
|�Pr�O׭[Ǎ7�f���T�T�D���+S/^��ۛ
6��_����ɓ'	

b������W��믳b�
Ο?OVV���DGG3bĈ\o�5j��\�|�/����s皶�����'����Hff&iii$$$0c����
��ܹsIMM5+|(���͖-[HKK�cǎ9�u�ؑ��4S�d�⺽�!7���nT�EY���6�u��n�_t���9{�,t�ԉ��4x��GY�hQ�������Ktt4�Z�"""WWWV�X���_SL�5�������s�ԩ|qfΜ�ѣG����СCлwoSLӦMr}��q�#"""bT���+����<,ʗ/ϤI�8z�({��)�~�z��aÆt�֭�9 ����G}D���=����������_�*�X�l��-Z�`����ڵ��}�a����O9u�u��%""�����d����9y�$K�.�1w���Y�z5{��e���|��7��W� ,,�����k�.���X�j����x����������K���Z�$��͛��8f�)���ӧO�����'++�,��w�!!!��m���?�����(�ƍ�k�.�񸸸\�kԨ��a�سg��'�.]��ϯ�k����L�6�J�*1}�t���M�N�j�e��=�|�t�B����^�z��֬Yڷo�ȑ#INN�E�0�өS'���Ǻt�RR�*"""R,��AAA��у:0x�`�nݚkHZZaaa���ѡC^y�.\HFF�)F]QEDD�,i޼9���xxx���m߾���Eu��	"##Y�|y����s�
.�dX���`|ͤI��W��*U"  ���x֬Yc�3J���OcccC˖-y�w���8���ɓ�W�*T����+W���[�FEEåK���� >>�u��(����=a���;7Ǐ�.(���Uc���Hq===9x��ԤI�����G����۷3o�<:w��޽{�ڵ+|�����n'N�(�5h� ��W�v�"33�0jԨ�
6��ʊ�>����TZ�lI˖-��"�b��		��L�<ggg����<y2)))�.�Ǐ��ÃjժakkKǎ	�s޹s�ҹsg���qpp`�С,Z����ݻ7�*Ub���9�߽{7U�T��/򱉈����k׮1b�6n�ȕ+W���䧟~2}�u���F�Ͳe�8w����$%%��q���N]QEDD�aemmͤI��V�Z���իǸq㊽n�V����)�<"""""""""R��-���t��9�6m�o�ٳgL7?�n��l��5l����������q�x��w���#..��>���Ç���IŊ������
zܹ�x�"U�Vͱ�8f�).֮]˾}�hӦ�ٶJ�*1g����/|||�Z�*�}�666,[���-[���MBBիW�v�ڤ��дiS�ׯ��ӧ�FaL�8�/���C���Ϛ�
��0q��Ɍ=___|}}ͶݾoY�[1��c3g�d�̙9b^z�%^z�%�{;;;���M����Z�j̟??��*W����'K�,��ٳԭ[��w�Ç3j�(Sq�����%EEE�����̌3h޼9			L�2������˗s��1\\\x�whذ!gΜ!88��n�:���C||��!)��NUЮ����ڽ:\�R����c|x�����������.��Å��w>�8��{��_T�d?�|��ի�6m"((��-[r��u.\ȋ/��_|Q���z�uvv��uFFF���9n����b��""RR�U�ƾ}�7n�����ښ�5kҧO���Lŏ������o����
�q������M�|�
4��ښ7nj�¨P�;v���7ߤv��T�P��������5jK�,��Օ�+R�bE\\\�gٲeE<sr�y{{���HTT�i,**
'''l��DDD��(
�]s�����ʔ)Sr�~��WӤIʗ/O�
�6m7n�w-uE���Lu��S����'O��E�y�9;;s��i>L�v�L���ɩH������憛�ǎc۶m,[���s��iVVVdggs��5�T��ɓ's��sS�V-����|�2�j�2�v��eS���HI�Q����c޼yy�DGG�c|�С:��~�8�Hk�yQ������Y�p!.�k����>|x�kK�bggǴi�;v,C�`ݺu,X��D�`("""RΜ9������5Glbb"nnn�Ε�wL�SWT)�[��ҠS�N���������y���1����׭[7��'�9r���,�9¬Y��ҥK��~��W1|��礥�Ѹqc�4i���x�;?5j�`�ڵ���s��)BBB�|ܹ�ݴiS��og3ƈ���<�ڴi���/��������[o�z󢈈��M����ѝE��u'ͫ����ի�nWWT)�T��aÆ��W_q��^~�e�m#G�4����f���$&&�x�t�z���Djooo���			�Qq��z5j���ŋ����������[�n�^�����3�|:v�#��ǝ�ڝ:ub�Ν=z4�
�G��V�""""bIE�����OO��FDDD�d<��c���/|���<��3���>G���gΜa���E�檮�"""""""""""""RX���|��Q�Z�����W�^T�Z�7o�{�Nj/�h��Z�*������ʗ/����
b�ҥ���zmwww���h֬������ҰaC|||x��wMq'N�nݺ�/_����|�?~<T�V
[[[:v�H```��;��{��M�J�ؽ{w�yw��M�*Ux���}>DDDDDDDD�d���5kG�%++���S���u�����~��'n޼ɟ�����N IDAT|��``��ѦXuE���Lu�pvv&88��qժUc���L�<9߸��Frwss���-�z��E�^�
�����������5� ǝ�ڕ+W��ӓ%K�p��Y�֭�ٳg9|�0�F��R�J��+""""""""�����7o����������Î;8r��6�V�bEƏoz���"""""""""""""RVY�Å<8���qtt$**�4���S��""""""""b��vvv,^�777�W����5M�4a�����ښb�T�BDD���899Q�|y����֭K�.5�N���"""""""""""""RV�����{�/p?L���6mcǎeȐ!�[��P�bEg'"""�K�>},�����Pll,����tr�ԬY��� ����$y��q{{{�������wNuE����\H�ԦM|}}	

୷������Y���Hi���I���-�����H�׵kW����W�^T�R�3g���{�кu�]��ۛ
6��ɓuE��K�+�P'�����OOOK�!"""�HTTQQQ�NCDDD�q/�����|��焄�b��F����%������������������î�\����ȃc���ٳ��i���H!u�ܙ1c�X:
)a�'O�^�zlڴ�_�����ԩC�1b%�������������������L""""Rd�~�-�������ҩ���H���bccc�4ʬ{�ݵ\�r�P���"""""""""""""�R���������'QQQ�NCDDD
�����)�������ƍ8;;s��Ej֬ɹs�P�����Ӄ������������=+�����WS����]��"""""""""� Z�f
/^��ŋ�]��X8��=h����������H�x�E�Ν���)�iEDD��իg�DDDDDDDDDD
-""ooo�-[FDDD�.`x���¹g.DDDDD,���4m��l�`0�[�B�ׯ���/���H�@����Ǜ�r;.�s�α|�r���HNN��ƆG}�g�}��booo��<��^���!..����ӿ������HA���ҧOK�!"""��ILLd۶mԮ]�?��
6��_��o���c�Y:��|EDDDDDDDD��J��bϞ=xyy��"""R���DEEY:
��0a;w�,p���78q�S�N�J�*<��8â��N�8�ȑ#�v�i,##��Ǐs��q֯_ϒ%Kppp�wK;t����Z����l@�&Mhժ��S1���TA�����=ɭ[�<x0�+W��ӓIPP�Y���;v��ݝ�-[�}��<�>��s.\��IKK��ɉ>}�0s�L����_�>�k����/_޴։'hڴ)
4�_~)R����S�La�ƍ\�|�f͚1i�$�R���W�2c�bbb8{�,NNNxyyHŊMq�n�bڴi�Z��ӧOckk������:#F�(t���������HYr�:\dgg߫�EDD$*|��Ν;��~g��ŋ�?>7n��>+�yל9s�v��ڵc�ر4hЀ��,~��G�̙�O?�Dxx8ӧO�w��ܯ����t�����	www�L�Bll,vvv�%��DEE��YDDD����f�ҥ���0l�0,X�ҥK	4S���ϏK�.Q�n�|��1c�YLbb",�ҥK|�駼���̜9���Xh�[�~=���J��=�<�ڵ#))�4����СC�y�i���]�~��ݻ�}os�����9p�[�l�\�r���3{�lS\FFqqq���q�����
'""""""""R�ܳ�#��ܿ���f͚L�8��7��?Z:�B;r�3gΤz��X[[Ӻuk���qwwgϞ=�L�"##III1��aРA�X����H|}}-������,XP�N)�1c�йsgK�!e���9}�4�Z��駟�U�V�jՊÇ��7�УG���hт�{��ut�m|���,\�ʕ+����޽���b���|�����Zp���/9�����$���899������fΜi*�(hܜ9s����]�v,Z�N�8��Q���믉��0u�X�x1�7o�{��ddd��g����KXX�����q"""""""""eI9K' """"��D�=�С�f�֭S��QZZaaa���ѡC^y�.\HFF�)�}r�#/YYY�>-� �ܺu�E����N��ڵ+Æ
c�ڵfqy�_��W͚5�����իG||<۷o�w��ңGF���Z�'O���חΝ;ӳgOf͚Ezz����lSSSY�r%m۶���4���``�ʕ����z^DDD�o�����XK�!""r���ƒ��h�4������-�h���,Y�$�&N����"����TnݺE۶m���bҤI�������ԪU�7�|���M�6��_�w�^����:�6�
6F�ƍ�R�
�/&;;�����q111�X��V�ZammM�-L]7�/_n��R�
s��%<<����|�M������_'""""""""R���E	8~�8M�6�u[LLqqq�oߞ������DDDDJ�k׮1b�~��w��O?��;3#6##�ѣGs��1�XRR=z���pʕ+|Mqvv6/^dΜ9<��E^7<<�O?�����IBB			\�v
//�B�W#F�`�̙�����ۗΝ;��₍�M��;w.���f��5j�醄�ׯ��_p��-��}�[�l!--��;��ֱcG8�֭[y��
}<"""%��ӓ��(K�!""rO��{��b����7�q���Y�f
�/_�Z�jf�y]��s<))�W^y��.Glvv��	g֬Y���lڴ���,z��m���(�Z�n��I��4�X|ѠA�\�'$$�^���2|�p�n��֭[	$  �q��Q�R�Blj���������%�pQL&L��C�ΤI��8q"aaa>|�>g("""R�EEE�����LDD���g��Ź��|�r�;������|�����ЪU+8��u����7�o����a�`0жm[z���֭[)_�<#G�,Һ��b{XX���g׮]����jժb�����o߾cooϲe�9r$�>�,o��&111f�8�v~4h�޽{�>}z��ԯ_�իW�w�^�������|�{���y��9�nj1"""""""�p�����Ƥ���c<��������|��w4jԈ	&�?��c�:u�0j�(v��ͷ�~�����_~�X�����q�n��w��!��ٳDDDЩS'�����GeѢE��)KTpQL;w��u<==���@<<<prr���www�L�Bzz�}�RDDD����`0�;n�A?  ���~\]]�2eJ�y���+���iҤ	�˗�A�L�6
��79����Ӻuk>��C�����iQQQ���p��%<<<���7+̸z���ڵk����?���`��ѣ����xzzr�…�3x�`lmm�7y�d�իG�
LE�W�\1m/�g{��q��"�;=���f1"""""""�p���`ӦMdgg�ٴi�Y\Qlٲ�}������Yg���L��I�&Q�B���ؼy3�ʕ��_,V��=�G��7ς��/9}�t�9dee��רQ�aÆ�g�8�?��O.]����_��DDDDDDDDD�
�\�y���&22���h4h)))DFFZ03���̙3�n��l���5Glbb"nnnf�}����ɓ^���a���4m�^x�\G-̺�ƍ�B�
���1o�<@DD�]�zX��7o���,`۶m����>}�ٳgh���iذ�鵽�=`�t��|�/^�jժ9�nj1"""���}[~Œ111������GLL�}�JDDDJ�#G���w�Ѽysz��kL�޽iڴ)���w-Dȋ�s��͛�~�:4�b��%�kggg^�u����x�":t�G)V�Ƃ�q�Ƒ��HZZ���?����q�Ʀ}׷o_<==9x� YYY$''3i�$����ѣ�)�aÆXYY��G���J˖-iٲ%��C7
'""""""""R����n�bѢE���ӡC�v�ʰa�X�vm�ش�4���pss�C����+,\����SLnOkHMMe�ʕ�m�S���#���+W���z�TDDDIJ��Ɵ��fO��]�/�NW�^-t�������ɬY�L]��n�^�شiAAA�lْ�ׯ�p�B^|�E���|�w���ҥ������lmm� ..�@�������un��QA>[�X�r9��8��"""R�L�0����:t���p&M��ĉ	����9C)-�,Y��1c�+++ƌ��ū��
�СC����M�6|�����4��<y��;��_~����_���ё}��Q�~}*W�̇~�ԩSM�4��ߟf͚�o�>ڴi���
NNN���R�R%�̙cv,������S�B<==x��g'""""""""R�������p>�����$--���f̘ATT�).##�ѣG�l�2Ν;Gff&IIIDDD0n�8����f˖-���ѱc��:v�HZZ[�n-��y=��cf�s{�������so���s�"�ЬY3�Bvv6���\�r�X�������ƒ%K���O��ʕ+̝;�c� ��5�Xa:tܮy���t��:M�V�p/泭U��/_α�8f����V�j);w��u<==���@<<<prr���www�L�Bzz�}�RDDD,-##���(j֬�СC���z��DEE�aaa0�ʕ+S�bE�y�V�ZŴi�L�og��	��+�;_GGG���π�^�:����iӆ��Xlگ�qժUc߾}�7����cmmM͚5�ӧqqqfGG�Œ%Kpuu�bŊT�X���Y�lY��DDDDDDDDDʒ2Up�z�j��/L���Ϯ]��`ժU���˗s��1\\\�����o�%&&�V�Zq�֭[��Ӛ�����Ʒ�nj1""""e���?��Y�8z�(YYY$$$0k֬�ݻw   ��~���7o���`0=z�)�XА��X�<^�u�֭˥K�X�xq��}��W1|��礥�Ѹqc�4i�w��Q�k׮%==�S�Nr�<s;�A�?1q��ٜ<y����^�ʮ]��4i��q�Ea>ۦM��+��q�#""� ����Odd$)))8�46h� RRR����`f"""b	���������T�T)��ʕ+s��%.\����-��ٹv%�k�z��\���W����η�~K����:u*���lذ�,�x-�iӦ<�������g�ʕ\�t�7n���G�}W�F
�͛��ӧ�����?�d͚5<��S9b��w�}Gzz:����h�W�^�8���~-���;���S�*U��իW����ԩSt��
�_P~��W���@�
�6m}��a�ƍ���'�u�?@���sl{����bDDDD�:///6o���ӧ����7��LJ;vp���'�T�X���Ǜ�רQ��/����ׯ�wn;;;�N�ʨQ������^�'�(������������[�n�^�����3�|�\;��)���޽;C���>cժUf��F���g̘1E>?EQ�϶S�N�ܹ��G���'��G�ХK��QDD�ab����ڭ[�X�x1[�n%))	6lȫ��j��VA����X�d	_}�.\�G�^`Ĉ�	o���RSSY�r%m۶������``�ʕ2��U�ޛ$"""R���\�v��ӧ0q�Dg$"""""""""�T�:\�7�
*Ǽy�0`\�~�,��_777��
���ɓ'�]��ŋ�^6�cDDDDʂۻ����Ύŋ���F��ձ���I�&������T�BDD���899Q�|y����֭K�.5�0q�D�֭K������(P������ߟ�7o2gΜ"����NPP͚5���[[[6l�����)n���xxxP�Z5lmm�ر#���w�1��;v,���t�֍ڵkS�\9lmmiҤ	o��&�}����FQ�Oa��ݻ7�*Ub���9�ٽ{7U�T1u���	�O>!11���L���HHH`ƌDEE:.##�ѣG�l�2Ν;Gff&IIIDDD0n�8nݺ�o>[�l!---�"ӎ;����֭[K��������=NNN�����U�Vw}�����������<��[��;o���{�C�^�h߾=;v���/���g�…,_����z��^{
 �6÷�z�j�ۭ��(W.g=�q�#""""P�fM����ƒ��x�G�����������/�9{��E�^�r����I�&1iҤ�]�.�uss�7����������y@���i߾�]��k�����r�o���m�ʕ���dɒ%�={��u�p��Y>̨Q��T��]�JDDDn�z�j���0dff�q�FBBBX�j^^^��[�|9ǎ��Ņw�y��
r�����9p��֭�O�>������޽{h޼y�\�c{�?��>��:��K�D�l6�7iy�t:����&�p��7[Ocj8cjF���gD*ṵgM7"4.Ó�N�I9i��t�eBd�(&�?��="����|��Z\��}}>�ko׊`��������'?�����[�;V�������nN��v�!����ĉ����e��]���\�ɤ��B�޽[&���k���[����p�z��]�܅�5�F����J���*88X*,,��/�,Iz衇N��j�{�w�}WV�U111�$��*�ɤ���v�@s�n6ޞqwwץK�d�Zu���3F���
oQݾ}�$I������$
0@			�0a����c�!�!�N��$��ׯ޹���ש0���w�#�@�o�Ѕ�?^f�Yo���*++u�}�iРA�$ggg{�رc%Iqqq:y��{}��z��d6�5g�{�m����"���%I����2��l5���\�����G}T?������<���K�f�28!Z��ﭛ�����������(;;[			ruu5����ϟ��ݻ+77W���o5y�d�������-����+44Tf��ek�8}�t�yΟ?/I�ٳg�s�1[
t��QQQJLLTRR��������?c�}�����ϯ�$]WWW-X��~ܫW/�?^aaa2�Lڽ{�F���������μ�TPP I5jTk�@���}���ӗ_~���j���?��?��3g�����h����ÇWtt�V�^-I�;wn���舮߹¶�E{�hq���`��?�;C�?�\o��mۦ�s��w{mj]mmm��]�t����88��m�V�a
F��9,,LNNN���ԙ3g$I}��ѨQ�e����Pjj���?裏>RYY�z��!???͙3G��{��vѢEڰa�JKKU]]-I
		Ѻu딓����~�N���yxxhܸq�p�����,�,��Q��Z�����������P����ĉ����e��]���H��:�ɤ��B�޽[&���Yz����R]�pA�{��s�…��(n�.$�p|3���Z�p�.\�h]pp�������C�E)))*..����$���Xǎ��ٳ�����nb���*..Vll��q�w�}���.Irvvnv�رc�y�f���)&&F��w����j۶mںu��f�6n�(針*jkkUTT��}�J����R�k�(,,��@G�`t��***J��޲Z��1��*�ɤ��H��v`��5))I�G���?���8I���_��f̘����+??_���
PHH��n�*WWW-X��^۫W/I?�8��OJ�F�!I*((���66jԨֹyhn����&����ɼ7��榄�=���>}�$);;[�ׯ���k�f@�j��E5$,,LNNN���ԙ3g$I}��ѨQ��Mͩ���Pjj���?�υ� IDAT裏>RYY�z��!???͙3G��{��vѢEڰa�JKKU]]-I
		Ѻu딓����~�N֜�yxxhܸqm�z@su����d��኎���ի%Is�έ�T@�� ==]���F��`�X���6�P�Ghh�BCCozmS�<==�p�B-\��Ѻ��`��ѣ�,�RRRT\\,___IRqq��;�ٳg������t�������d�X���͛�	&4S߾}����TTT��}�]Y�V���H��V�L&�"##
Nuu����2��m2ogy��������k��钤��l�_�^������h�@��_�^���F��d�Xd�Z���������իWK��Ν+???�S@}4\��M:�iӦ��Yv�hk�E���Ш6k��4iR[M
�����n�CkOطo_EDD�����"""`t�N��w�9r�F����7e6�%Iyyy
7���8u���뮗�����\IR`` ����Z��"==]ӦMk�i@3X,Y�V�c��^xA���oQ�Ƶ�=���d�رC����<y�
�aÆ�RR�Z��ӕ��nt@k�����̶�4��G�_n�	�)����sTUUiɒ%
��d�$���)>>^YYYrss��5@�7o�&L�`t�T@@���ڬ�"""����صk���z�f���i�����TVV�)S��ǦN���۷+--M������S�5\�)**�ĉէO�ܹ�������ٳڹs����?�PYYY:y�._����[cƌQtt����\��F�o��V6l���UUU�G}T�/n�i����*++����}���o���w߭�{L3gΔ�������redd���_^^^�qooo��feddh����ٳgS_ZІ֯_���t�cЦ�V�,��10\�m�(++ӫ���Ç���F�E�7o�Ա��������\IR``�&M�dp"�Ρo߾2��:r���������竸�X�ӧ��|�M���Թ���T�x�V�XѤ5����3Ϩ���>���﫢��^�Y]]�9s��ĉ����������@���rpp�$}����TPPP�y���t��a�ݻW'Nl�=��g�Xd�Z��@��֭���0�p#���裏TQQ���j�;w��H�=zT���z���h�"����:v�ѱ:
[���[g|Ϟ=����pI���%I���:x��?�w���$)''���mݺU����ӧ��l٢C�iӦM��_�Z��)k^����g?޶m�N�8�x@�����O����aÆ������ζ_w��AI�СC�e���j���p���/�'>\W�\QBB����QUU�%K�(<<\&�I����xeee������1��M����]wݥ}��iѢErvv֕+W�o�>yyyi��ђ�O>�D�����/��{�����9"I�t�R�s}��ǒ�ŋ�?��$���O��������ש��5���'IJLL����$i��JHHЄ	�g�M�0A�t��)IR�~���ӿ�:5��cXÅ��v�>�ZW�\��u��M...햭)���TVV�)S��ǦN���۷+--M��������4~�x���)''G�>�����?�…�5k�%I�Νӂ��_ԛ������}��W��|��C=T��V�,**�$���6x�����ϟ?/I�ٳg�:ۘ���N���<������\IR``�&M�Ԟ��M9�!�>�����~l6�������l6kϞ=u�}���e6�[��׸v�v��w�i���9r�}�Q-]�T�Ν�smyy�222���////������f�222T^^~��@畗�W竱�zJ���_IҞ={���`�B�^y�}���ӧ�"##�l�2eff6;��Q�	'��}ȷ���2��!�[�n�$��?���l5��^дi�<w��Q%''��_ԢE����رc�ڎa;\ܪ��X=zT���������R%%%���K�/nѼ/���v��-I�|����٣cǎi۶m���$}����TPPP�냂�t��a�ݻW'Nl�
�&|||�����@�|�y�:����&����W�^��3g���_�r�������GgΜ�g�}V�g����z�����dRaa�v��-���h�޽{���T.\P�޽뜻pႽ����op���JK�,Qxx��睰�0���+++Knnn��D��ᢡ� _�gϞZ�|�***�t�R]�zU˖-SEE����u��_�^�Rjj�|||t��Ym۶�^s��AI�СC�]o����&N���^3f�Puu�����;t萪��u��I�����/^�ؤu��?�S������>�LW�\���O+W���57[Ӷ�DQQ���رc%��+�ɓ'������o��k��&�٬9s��k,I*,,���m�V:���U������LS�L��M�:UeeeJKK30��vk������?6�h�)���e�X��g�������OS�L��~��猍�UPP������*..N���G�kN�:%I�ׯ_���_�77j�(��}���ܘ1c$IK�.UPP�"##�����~��ɓMZ'22R�Vii�f͚���@EEEiȐ!�j���m����0=�䓒�3f������Wdd���[����U,��3b�I
�a5jT���ޮ^���7*,,L?��F�����֮]���VVV��_Whh�~�a=��z�7T]]m�i�wx�T^^�������ٕ���[f�Y*//o�;���!w�h��s���{�����5`���W�����6L���W_��Ο?/�]6�g���ƻ��888h„	�~h\��a��/*88Xnnnrqq�O�S�Z�J�f͒$�ر�I9\\\�i�&����W�^rqqѸq��M�-YsѢE������JMM��b��d����<==5f�m޼�Ύ!!!rwwWNNN�999���иq�t����?��***RMM�*++u��q��7���j��UWWkΜ9ڲe�Ξ=������(55U����իW]�>Pee�����

Ree�������ͩ���v�'�5����T[[k��޵O껞�Sݗ�f�����v��6v��иY�fٛ�׳gO%&&��:���l�g�=z(66V�����6u���`׫����…�p���6��bQJJ�������+I*..ֱc�4{�l���7:�$�ܹS����l6���F{��QRR�v�ءiӦI��mۦ'N���ŋ5p�@*11Q�Vvv�&L������w��AI�СC�e��<xP'Nl�����w�ذa�N�>���_gΜQrrr��Ƈ��
���ӧo8_~~~��G�J����X�޽%I.\�w�m�V�LTT�����<y�j��d2)22�d���fs�����[���jUff���(<<\yyy��ζ��۷O�����A����QPBB�$iϞ=��s��)IR�~���߿���:u�ő#G����aÆ)55U~~~ھ}��9b��ի�$i׮]���ҙ3g���t�9W�\���]�rEG��?�8$$�^3x�`IRaaa��mc��f��ܔ�����l������D���JHH������@'1�|u��]�����o�ɓ'+55U�/_�SWTT$I


��2a�I�?�D�Ο?/���g��@g�dt��*//WBB���ݵb�
999)!!AS�Nղe˴c����Scƌ�Ν;�n�:�[�N�t�y��.͘1����߯ɓ'ۏG��������@~~~uj

$I�F�j�;��`��኎���ի%Is�έ��&������v��~�-+00P���y�}���z�7�m�6͝;W'N�$���6:ϥK�=o�Q����\lc�����"//�������Z111���$���(&&Feee�],,X���p�q�rqqQPP��,Yr�y׮]��#G���I^^^z�駵q�F����kBBB����z�������C�ƍk��d�X�f��Y�FS�N5:�<==������[����ŋ�v�Z{��d�$�޽�;�k�>���{��$]�p��9ۘ�:���EC�׎�\�R+W��W��O�'�����)66V���7�_����N7ңGY,������X�������b;vL�gϖ��{�s�i���*..Vll��q�w�}���.Irvv�׍;V�7oV\\�bbbt�}�����mۦ�[��l6k�ƍ�~ة���VEEE�۷�$i��*--Uaaa�Ɗ��B{
tv��p��EEE���[V��>f�Ze2�i`2܎���$��3��ѣ���+..N����g��1c�����|EFF*  @!!!ںu�\]]�`�{m�^�$Iaaaz��'%I#F��$��`5jT�!�/.Z���M			���VII�JJJ�����������˻��m%,,LK�.Ր!C���"
8P3f������uJMM��b��d����<==5f�m޼����-����U]]-I
		����rrr�e��ɑ���ƍ�7m���������իWK��Ν[�i�����t���4QVV�,��1�FBCCz�:OOO-\�P.l�.88X���u�z��!�Ţ�����W�T\\�cǎi���rwwo�M@A����O�X,|Hܶh������P@@��1��EEE��wߕ�jULL�$�j��d2)22��t�:h�@�͛7O���3:@�a6��dޖ>L����ܔ����^ӧO�$eggk���ruum�,�Vh��lÇWtt�V�^-I�;w����N���4Kzz�jjj��ZIVV�,��1n�E[�X,���e�Y�EVVV[M
�������c��
���.&""BF���i���I�&���0ȼy�4o�<�c��Z���b��b������v�����t�����Z��"++����(++KF������-]ZDD����kt:�Vk��4iRkM��ʕ+
		��ŋ���F�t`���Ӽy�h��pa�Xd�XZ#"55U999�ׯ��QܴiӔ��ntڔ�j�o?�w����ҥKZ�l��{�9�{�F�t��βZ�F��M��9�B�����իUYY���x��:���EDD���F)--՚5k���GF�Ё����ֲe�ԫW/͟?��(��LYY�^}�U>|X555�X,ڼy�$)//��p����Tnn�$)00P�&M28�.ܖ������jӦMrss3:�6��>��~|��9�4��ѣJNN֎;T[[�ɓ'kРA6l����]�p�d2��j�*EEEp��ϗ$���>|��\����cC]���JK�,Qxx�L&�$),,L�����ʢY�m���`�;�S�-���[h}f�Yf����\�b�spp���K{Ek���4���iʔ)���S����Liii&���'��vtm#�������&���8��f�ٳ�ε���f�bcc�]s�׎ێ���;-_�\#G�ԣ�>��K��ܹsu�-//WFF�������e�����lVFF����o�U�������������^y����J�JKK���$///-^��E���ڽ{�._���/jϞ=z�gt��E{�|���Jջ>((H���ڻwo�n:.�v���W�k�mz���˗���BK�.�իW�l�2UTT(!!A���-Z���Z�~�:���T�����ٳڶm�������C�ֻ�6f������@gg6��4�Psō����b��j������?��S��g?�Y�s����w�x���s�꣏>Rtt�$�ԩS��~��ջ���uj�+c����;w��^?~\Я~��[�/00���a�$I_}��}��~�e�z�1[
te�pධl�2���륗^2:
��~�
������V��֪[�n������99�u�իW%I�z.�m�k�llc�����@�WTT�W^yEݻw7:
Ͳa��>}Z���Μ9����:�m���ӧO�p����:�G��$�s�=��޽{K�.\�P�zۘ��2.ty����Utt��Qh�#G�(==]Æ
Sjj�����}�v9r�^ӫW/IҮ]�TUU�3g�())�s�\�R�r劎=���DIRHH��f������z���l5Е�p�K;z�V����bt����\			rww׊+���d?^�l����%Icƌ�$�[�N�F�ҤI�t�w�p޻�K3f�P``��}�Y�������ɓ�5#F��$Ի�66jԨֺU�h�Х����l6+""��(��H^^����Z|}RR����k������G���㣘�����w�X�`����u�w���EAAAZ�d�
�]�v�F�)'''yyy�駟�ƍ�4%������]999����ɑ���ƍ��{������V��}��O�'�|�nݺ���1�[�r�V�\Y��'��O<a?vssSll�bcco:�$�q�Z�n]��z��!�Ţ�����W�T\\�cǎi���rwwot�
��@�t��U���K


ըQ���@�%oooY�V���j��dRdd������p�K����/�K����FG��qssSBB����URR���egg+!!A���F��v�dth���z��g��@�5|�pEGGk��Ւ��s������T�~h������]g�Xd�XZ9
tF�hh��
�q2:Йdeei„	F��1.t	��f����[�ѣ��q]XMM�&M�dt@��@���/��Ņf@��Z��Z�F��.tz;w�ԡC��駟�ŭ_�^0:mj޼y9r��10����V����׿���L�"����O?�TYYYF���dee�����t�p�S������B���{FG�&,��V��1hݺu3:;\�.^���˗+::Z0:�.���֫�����j���@�dth�����2d���.���!�:uJ��3f6���޽����iӦ�'�h�xMb˛��gk�$��ٳڶm�rssUZZ*ggg��a� IDAT'?�#�<�)S���ӳN���iJ��������\IR``�&M��.�h
:�Gy��t/������&��N��_�l�2yxxt�������g�UEE�}���Z�N�ҩS��{�n�����˫�y�v��Q%''kǎ�����ɓ5h� 
6��h�m��n���=���W�k�޽z���%I[�nm��-r��Z�f�***���t��������!C����D���7��!�ר�UUUiɒ%
��d�����������6_@�h�Z��l��l6:F���.-Z�H���_������%I+W�ԠA����$WWW=��CJLL�$8p�Ȉ7������2M�2�>6u�T���)--�d$������ܹsZ�~�8���*
8PO?��/^,IuvW���TJJ���ۧo��Fw�}�{�1͜9S...�T���}Svh�r�$�[�n��5e]I�z��6mڤ�{����D���8p�Ə�	&�4Wcy����K_��Ν;�;S�u}���3ߍ�}�i�&-Z�H�
�ƍ�e;����ڵk�����ݻ��?���ϟ/777��M}o��˕��!yyyٯ�����lVFF��O���={�{]�.�vTQQ��3gꫯ����<y���kUWWkΜ9:q�}���D���*((Prr����mmm�Ο?�5k�H�~�ӟ�x���d���[����?~\ǏWEE��M���|M1s�L�\�R�f��SO=��#G����s��Z�v�����4>4d��ٺp�$��������W�*..NR���>�@���


�w.((H��޽{5q��f������h1�ժ���J>>>JMMաC��iӦ?�m�6�8qB<����駟*33SÆ
��Ç���-���yyy7�-���﯐��ݻW���z��g[��$�ܹS����СC��O+Iڱc�-�V���SO=���Dyzzj˖-z��g��#���Sff�����4�$
0@Ԋ+�ӯ_?�ܹS�3�<#I�裏����<xP�4t��z�lc�Ơ�@�p��e�?^FG��k��fs��������������_o�}��I�5h� 9::j��JHH�$�ٳ�ř��CiÆ
u27w]wwwI?4dff������Õ��W�1�-k׮]ںu�~��_�l6���@���,����&�)�����Ĩo߾�޽�}王/��7�=uꔤ�8�׿�:5��dth��_]�ӟ��o�[RXX(Iz衇���ի-**�$���68��ӧ���mW��/��Saa�{�z��]w���Z�|�rss����7�|S�<�,�\]]���V:TC�Ռ3T]]�͛7kӦMz��W��+���z[���8�����$��ի��漷�ϟ�$��ٳ�9ۘ��1��@�w��y�Z�J,�����q�'//�����%�����q�n���{}�.]��쬞��Z�d�jjj�j�*��-]788X���.]�����˗��o�������F箮�nv~I5j��f�����sqqQTT�$)77�I�5ewIrvv���eӔ��6��P�W������h����7�����bbb���-�ӧ�$���?�3~��$�L&I��ݻ�5o�������-�0d�M�>]���JLL�ŋoi]OOO���*%%Eo������t��E�]��^ck�����5g��k
:T�l���DC�m�9�m�޽%I.\�w�6f�`.th_~���x�
-]�T���F��7N��j�*�ʕ+:~��V�ZU�v�ر����8�<yR������[���k2�͚3g�����PTTԤ���/�����ڴiS��?~��f��~�mUVV��ӠA�$���W�^��]�v���JgΜQRR�Ms6t_S�N�$�����W_��ӧU]]�K�.�O>ы/�X�>Z�Ds���K�Wsȵlc��p2:4&..N���ӬY���@��6m���}��oӌ3��1c�>��c���+22��9WWW-X��~ܫW/�?^aaa2�Lڽ{w�s���iٲe�={����4q�D�s�=�^7**J���JJJ��@���g�~̘1ڹs�֭[�u��I�����x��;v��O���[�jǎڱcG���y���i�漷#F����UPPP�u����IҨQ�Z=#��c�֑#G����U�V�yB6]^^����<���M�6)44Tw�y����4h� �X�B����b����Pjj�,�L&����1c�h���uv@X�h�|}}������&����ӤI���k͚5-Z7,,LK�.Ր!C���"
8P3f������u,Pxx������(((HK�,�i�����?���d�3F?�я��� 
4H�=���n�j�U���Os5�
		����rrr�͓��#���ѭ�����А/��R���Z�b��u�ft�mhڴi�$����qk*))ѓO>)egg���0΍�ۍ7*%%E�v풯��$���X&L��ٳ5s�L�"��u��MV�U���cn'�p�ú�{�?��?4[��ѣG�l6����ŋu��U}��� z�!������FEE��ۻN��j��dRddd�fP�������?���~[IIIJJJ�s�W�^�5k�A�p���޺��)!!A�?���O�.I����������n�4�����Ĩo߾z���_���Z?����k�̙���2:"Z�%������իWK��Ν+??����4\���A�E���(he-}o��tLF����i�&�9s��(���ti555z�w!͟?_yyyF�tp4\�0�m�6�c��#G��W���|}}�s��i�ƍ*--դI�������M+V��ڵk���>��c�;VC������}�������JOOo��
:���x���W�>���Q]��ѣu��a��������ӄ	ZuN:����#�!�phEEE���O���
EDD]�ѣG�}�v�رC���F�t���$��ѱ����l���phдiӌ��
���]�K/�$M�8��(����?ז-[�����7*44�]�_�~�����uMڛ�j��b1:���Ц�@6�����P�V�o�>�۷O���W�n݌��Ξ=��۷k˖-:~���Y�fiذa��X,�Z���
@[���.��իz饗�_��_=z��q�����/�O��<==�7�|SAAA|��h�����"}��F�p"""���.���Z!!!���4:
����T��ݵ}�v����{��FG�Fh���hڴiF�pjkk���.���U�V�2:���ׯ��y��cthf�Y������qs�m�S�Ni��;�z�����͕$jҤI�<'�.�l�Ozz:
S�Օ��)33SO=��|}}���fx����5j\��ѣJNN֎;T[[�ɓ'kРA6lX+%�[C���w�}���lm۶M���w�{��Vt�MM���[����JK�,Qxx�L&�$),,L�����ʒ���-�����jkku�͞=[��ޚ:u����;����믿�O<at�6a6�e6����a������LS�L��M�:UeeeJKK30�;\�N���T���F��M�޽[�Ǐ׿�ۿiɒ%�2e�|||��e���"M�8Q}���Ν;�?~�Ξ=��;w�O�>��������'O���˺��5f�EGG��ݽ�5lM��t���jÆ
ڿ�����裏j���
^�5�m"�~���J���h߾}��ot��w���̙3���b����\����}���[f�Y�>}�z���ԗ��ػ�����þ(��F�9Jn�f���㒙i)R
).c9��)j.a�4f�[�&����������$�~#�e9����w�p<����z=����s����>$����-""""rW(�BDD�6���X�x1qqq�:u���*W�L�F�		�Ӿ��V�����Ғ����y�ؾ};'O��h4R�|y�֭���?O߾}-6`�̝;�w�y��/{λqŝ���E��|."""��־}{<�O<a�Pl�z����w�^<ȓO>i�;x� gϞ�Q�FT�V��3g2�|�����,_��+W�0a„"͙��Fhh(gϞ5�mذ�k׮Y���9�F#���'))�\�믿�`����O���y��ƍIOO����j���æM�x�嗋t�""""""""""""""w����_�;w�:ЬY3�͛Grr2�FΜ9�ʕ+�ر#/��W�\�u���ÇӰaCfϞ͑#G��� ''����Oxx8�?�8+W���ƥK�l��ܩ��D�y�233m������ׯs�ƍ띜��l��)�`ݺu��ׯ�k׮|���9���xv����ٳرcG��[�d	gϞ�Z�j,^��]�v1g�RRR��eμ'g$$$���.]JRR���,[��~����h�~�i���Ú5k�����W��U�2S[R…��H>~��7�4iBll,�<����>|���t���HNNf�ĉ�-[����өS'���m�c�ܹDFF����{����z�*�����lٲ��^z�+W�УG�M]w*77�f�8�����"#G���o�����֡���ڻw/o��&�<�����ñ9???����[�lI�
ؼy3ׯ_ ;;�͛7S�re�7o����ٻw/���'66�O>��)S�p���"ǵm�6F�������4hЀw�}ת�̹y�f"""�]�6���ԬY���{�_B	��?��c�=f5N�5,ڈ�������������ؒ������p��qZ�h��U�(_��E}�:u�K�.4k֌��Y�f1h� E�`���X�|9�:u���X�"�[��u����ߟٳg3i�$V�Ze�PE�m۶�u�ֱy�f����8}�4K�.eɒ%$''S�n]�Bݺum����Ν;�p�Bv��A�V�عs'�/_&,,{{{����‘#G��(NR�3gx��'-ʟy���w2��ӧ�~�7���k��…�-[֪����FDDDDDDDDDDDDDĖt…���N�:EXXիW���///z��IRRR��
�m�n���@�nݨT�NNNԪU��#GZ��uǎ���R�R%bbb��-���>n��p���dz��EժUqrr�jժ��ݛ���B�n�1�U�V������I�N�سgO��RRR�߿?���8;;S�|y�}�YƏϥK���S��
S�3�Ѯ]�B�5j��޺�����ԩS<�쳸����/Z��U�����D�=�\�2NNN4hЀ�k�8WI�d�Js}EJCnn.#F��m۶����u8""RL			�jՊ���o|������~�ȑ#�5
///[�hs			_�����K�����7�7O����K�.�~S�N�ȑ#T�V���`ƍGttt��2%Jܚ0��`��;��v	y��2��lgg�?M�ʔ�)"""""""""""""��p!""6�c�:v�ȕ+W�e���,[����V�\I��5������ŋy�7���1�?~�)S��i�&v�؁��;K�.���T�P�s���6lhQ�n�:�u�FFF����X�x1_}��V�*p��?�@˖-��� 33��kײq�F�m�F�&M�m���K�֭IKK3��F������Y�h�w�J�*�ۭJ�~իW���,^�����Ǯ^�z��ޛWhh(���0����l޼�Ν;[<�йsg>����}���Ui��Hi�ꫯHHH`߾}�EDDJ��͍�+C�ptt�uH�Gy�ƍObb"۷o�E�T�\��f���,X�OOO���0&���&MܪZ�j?~�������o.OLL�j{'szyyq��)֮]{���+�����˗�X��E��˗�mDDDDDDDDDDDDDDlM'\���M]�p��]����Ɛ!CHII!##�]�vѧO�F#AAA����rss��"""����3��	���GNN����ĉ�F�oߎ��7`ʔ)�qqq���E�ggg�6m�����,55��ݻ���A�ΝILL$++���D:w�̵k�x�WHMM�w���P��y���v�۶m�V�Z�F&M�d�vȐ!���ѷo_RRR0�����u�V�ׯ�ɓ'?~|�ŖWI���7��_�~�iӆ�3g���č7
�ϴַ^痔���¡C��|�2ӦM��@�K�

2?�Ç������iժ(Ҝ�)�Z�����ׯ3j�(���x��m����@���Y�b�;wV�E)y����ɡw���F�v�o�]�va4INN&<<�\�7�0�۷ ""���������Çy����s�9M�O�>}�\��ѣINN&''������'����G����m�ԩ�<)�V�2S[R…�����ٳ9w��F�⣏>���7n�ܹs<x0�/_fƌ���{�nƎ����	

2�͚5���,^}�UfΜI�5ptt�Y�f|��,Y���޴��^�z%���ӧs��U������'''|||���!  ��/�駟�ۿy�������s����F�-�;w.;w�hkz[�ԩS����WWWZ�lItt4�W�.���*�
<��Çcggǖ-[8p >>>�+W��-[2j�(���;�I�+<<___<<<�Z�j���ϝ;�?���V�ZC���qrr�g�aÆ
����8v���Ui��Hi�3g���U⒈�������H.\�`�P�R�5kf>ѢZ�jV'�l���c����Opp0G�5�'''i���`�ԩCjj*aaa4nܘ^�zQ�n]��E��t�E`` /��"p��5jp��A���iԨ�ڵcɒ%���0d��8�=���)��f͚�DDDDDDDDDDDDDD�&%\���M�[��A��[ߧO6m�T��/_�G�dggӮ];&O�lQ�e�h���Ϗ��\N�8a.����L�2ŸK�7o�w����[;;;F�@lll�����Z��6`�&�jժСC�����_�u>>>���r���R�-�����``�ԩ<x�aÆ���`��ի|���L�<�֭[S�N�o�~�8�ӢE�b�)�s_�v-#F��z��5���ߪ$kU��+RZz�!ƍ�c�=f�PDD�KOO'**����S�zu"""8x��SIHH !!��z;;;�t��L\0�a2|�pڶm����9�v��Ʉ����_)'''�̙C׮]�����ɉ6m�0z�h��E�sذaT�Z{{{�F#p��������xxxвeK-ZdqbE�v�psscǎV1�ر�2e�ЦM�"ݟ���������������d���͵u""��l�2z��韙[�M*T��ŋo;^���l�ꫯ���7{��1�mդ\�r\�r�K�.Q�\������ɥK��ܾ�1Ο?O�
��/^�H�
��������r�&���\\\�����>�E�bѮZ�j�nݚ_|��;���Tj�坻4���ҥK�ٳ�={����IOO��Ņ��8�}��Bc���ڵk���X��oI����/\�`����?�T�R�q�n|(�Z����YDDD�o7n�`۶m,Y��������,�-�& IDAT:t�@Ϟ=�ԩ��ζ�ԳgO���򽖒�5k���gժU��Ξ=K�.]�ׯ�9y[DD�=��@TT���[�EDDDDDDDDDD�Jt…���ԭ��ݼy󈎎�lٲ�^�:ߍ�W�^�~b���7���Ej���mq���P`�Fٲe��I��o�Az��MLL
40����/,Z���_~����s���R�-�;]��ʗ/O۶m	'66���T���Cff&cƌ)�<y�lq;�y�{���ȷ�|��Ş�V%Y��\_�sY�|9�[�&11�ɓ's��V�ZE�nݔl!�\�^�x��-W������"88؆�����������������.DDĦ��݁���������c�ȑ#<���ҥK�_�~�s�/n�Y�flܸ�H�=JŊ-6�6��=A �K�.Y�v�^z�%���ǩS�X�`���Ԯ]�cǎ����V��+S���3g�:vٲe��� ..�k��hz^�*�d��ս�쉈�ȃ�s��9r��{�2h� *W�l��/��Օ��{�5k��믿�믿�f��{�b%B���������������MJ��2�&�s��b���̤{��3~�x:u�T`�Z�j���X���w��̙3ͧ�믿�ʕ+�9��ٓo�~���]i�^�:!!!̟?�����k��m۶�[I�逸�n>��qrr�O�����o߾|��x�����>{"""b{YYY�ֻ��S�n�{���=��8���H"##��?�iqr����������������)�BDDl�}�������n�����`0СC��aÆq��A	/t����ϟoU�����`�F�沆
ҦMRSSy��WIOO/p�3g����Æ
3��k���S�r��
�>7n� 22�֭[{QԨQ����Ç�����J3���_�޽?~<,t�ɓ'дiS�rSr˭��K/��ӦM#77ע.77��DI��^~����E�_e���AD�O+77�;vЯ_?�T��޽{m�H�1m�4�M�F�=l���������������%\���M
8�r��O���ٳg���lݺ�~����k����@DD��Ϛ5k�1cO>�$���m7&0ggg.\ȨQ����HOO��3�faJ0�3g=�������2c��?Nvv6$&&�������Axx���Ӝe˖e�֭�����h$))���@�mۆ���
��ghڔԭ[76o�̵k����&11��� ���[I�/$$Ο?OÆ
y��7����ʕ+����￳~�z�2e
�?�b�2e�Cvv6F��cq��ۗ�U��i�&�u�Ƒ#G�~�:III�����ڵ��(�Z��ϞHQt��Eo���;Ƹq�x���i޼9�v�b�ر��"""""""""""""""rg����YDD�,[���={���u^�ׯ�k׮ddd�;�g�}ƀ��~~~�۷�1�k�����'��4i�w�}����Eybb"������8���=�G��JX�v-ݺu#++˪��ٙ�˗ӥK�rS�HA�<�W��7n̑#G��S�jU���y���Jl�]?��/ҽ{w6mڔo�ϟO׮]-�ضm�E�)��<Ò�����]�v\�vͪς

���>��?�2>�l�J��W��g�s��<>���			�V�Z���������;�{�n����޽;�{��'��uhZ={� ***�k�?��@TT��E�^����������������:��?J�j�ptt�\�r�iӆM�6Ym�?v�X��

���矧|��899Q�n]&N��֭[��-|}}9t�s�̡}��xyy��舋��kצ_�~8p �d�_|�������xyy��s��
�%���]�x��w�_�>���888�����o�́,�-J;�����'7ndÆ
���kԩS777������Q�F�?��G�Z%[,\���������>�h�\)x����y�������LJ����|z�����Q���W�=���Z����.\�`�PDD������Y�&�ׯ����L�6M�"""""""""""""""w�N�(%���C�RִiS�z�-[������رcx{{S�vm~��g[�sG��?Ϸ��`�6�:�ŋ���A��0a�ϟ��'k׮��ɉN�:1}�t<<<,����3p�@���qvv�^`�ԩxyy87�իW�4i��ќ={///z��ɘ1c,��4Β�u��A��Ν;quu�ƍ�r�Js��rss�q��_~�%'O����	___�x�
���S�e�+�;�bٲet��͖a����5+V��	"""""""""""������X�b���v�?�+V���h�0D�>���FFFG�������7o�>��M�A�1g��ĉ�Y�&�}�{��n&U|�����ٱp�B���-2�[�t)qqq�߿OO�|����$  ���s٩S����`Ϟ=lܸ;;˃�JgI�
���1��:r�H>��C��hd����޽�+W�0t��B����Y�>}���(�z�-���m��Q�F\�~��a����5ݺu�z��CDDDDDDDDDD侠��R�7<��y��`*"R�F��m�6^}�U"##iԨ��Μ8q�y��7�����8R)M{��᧟~�v��|�ᇌ;����SO���L��ՙ2e
�Ǐg�ڵV�׭[Gll,�Z�"!!��={r��I�M�ƤI��sڴi$$$ШQ#f͚���/G��_�~lٲ�X�
Q�8K2W�:uX�h*T�F�\�z�o���y�E~'v��A6l�@@@F��%K�0p�@�O����K�r�
111,^���۷S�bEZ�nMÆ
m�୷��i�""""""""""""""v�o"""""��6m�˗��nݚ2e����H�ڵ�:u*|�-[��m�R�f̘��O>�����׿���`���ԩSWWW�`>�!��>�������䄿��9� &&��9�����/x��qpp�~���2�.]Zjq�d��ӧ��3s�LsrŅ
��2e���G�駟r��9@nn.'N�(���ȟANN�ׯ'88��~����S�R%bbb8{���-DDDDDDDDDDDDDDD�:��.y�Wl��SӦM��R)�
p��!�M��ƍ9y�$ׯ_���iӦ<�ƍ�:L)e�<��e˚����1���^`��m�Z\7m��cǎ�'%%��5k�[�СR��$s�������2l�0ƍǍ7��oIhh(�6mbӦM�3�ѣG��77�B����̟?�������Ͽ��o�u놧���ÒB,[���ׯ�:�ǔpq��X��nݺ�8)�+V���h�0D��裏����:��\]]�-���/R�_�M�	���]���˗��JgI�rrr�?��y���ی7��1�w�N�v�X�j���'>>�ѣGIDD�����""�W_}�֭[S�V-[�"EШQ#%[���_Z�nݨ^�����	%\�EQQQ�:)��={�:�صk���۷P�^��ԨQ�����'O��c���J:W�z�X�vm�����$$$�������ʕ+�2e
C�U…�<�233qqq)��\�r�+W�F$w⭷��i�""""""""""""""Qv�@DDDD�",,�~���ׯ�c�sbA�=
���K/������&55��Çc0hժU��w7�2=z�\V�V-3g�$--���z���z
�yb��ȃ�ƍ|����P�R%���m�����������������!�p!""""r�T�R�ƍ[����1hР��9�U�V�s�N�}�Y�:777�M�Vj�ݍ�*U�Ĺs�S��=�'O��wޡ��8��Z�oѢ�݃�Ƚ�����ŋY�l�O���Ϗɓ'S�J[�&"""""""""""""""wH	"���T~��v<��Z�b��C�b��m�Y�z5�z�bӦMT�\��� ƌ���K�}ʕ+�Ν;�0a_�5gϞ��Ã�͛3a��x�R��n��'�0z�hN�>MVV�����ё3f������7;vdĈ�v?""w��͛y��wٷoիW�gϞ����ԭ[�֡���������������H)Q…X���c������q��)rrr�\�2�5"$$�^x��!������R3!!�y��}�vN�<��h�|��ԭ[����}�R�re�~s���w���ŋ�Gi�Ww�ʃ�W^�u""�u�O�{U��+��7�knOOO>��c>���b�-nyi�ս{w�w�n�.44����B���9;;��O0u�TZ�l�����C�R��1;w��{�&66֪�̙3�9s��+WҡC���<<<l�k���L�6�j��牏�'>>��S��`�^~�e�6aaa�Ki�'RAAA�:�RѼys�7on�0DDDDDDDDDDDDDDD�.R…��o��������y�G:t(�?�<��߰���ĉ�X���S��~�z:u�Ė-[pp�G�(�ΝKdd$����1���@j֬����.]��dƌ|�����у�;w���g�EJU\\���l��܁��h[� ��u�����D�6ml���]q��1�-[ƈ#prr�u8"""""""""""""""b#v�@�!!!?~�-Zp��a�~�m�ׯ���+NNNԩS���pv��I�����5k���~`|���,_��q����O���=+V�u�����Я_?�_�ΤI�l�H�;}�4+V��u"R+V��ϯ�eff2`�V�\i�PDDJՅ�={6���<���̚5���[�%"""""""""""""""6��	l�ԩS����lذ��~��
*ЪU+F�M������ێ���kq�����)Sضm�/_�Z�jt�֍��pʔ)cn�c�bcc�T�111�/_��9|}}���߿?s��eРA����L�<�-[���S�R%ڴi��ѣy�������\���ˈ#صk...4k֌��p6lh�/%%�iӦ�e�~��\]]�U��:ub���Cqc+Lq�ϴI�]�v��;j�(fϞͶm�,��I�k�zgff2s�L���k>��˗)_�<�5b���l�2���wM�SP}I����/�d�ĉ=z�*U�жm[F����~o���ɓ���L�V�X�vm�1�ݣ7�<x�-[FϞ=m���WD����p��ƍ�u(""w��_��%K���7�`ggG`` cǎ�M�6����:D�!C�i��
���

�:�;vбcG�\�bU����ʕ+�С���quu%==�|�x�b�x�
rrr��>��3�رwww���ǜ9s3f&L��fee�w�^6l�����|ݺut�֍���>���Z��������ݻiٲ%����NNNl۶�&M�����K�֭IKK�7�5j�{�n�T�R*��#R���U�Ǐg��ل���w~
[���\���hٲ%���/���5k�رc���ۦ8	%Y�83g�d��V}\]]Y�jm۶5��~o��U�V|��w���,_���ƴ�8***�k)>�m�g��kyp��YL.^�H�Z�4hP�~o��EFF2b�Z�h�믿��/�Lٲem�����������������'�l�_ͅ�ڵ+iii2���222صk}��h4į��j�/77��+""�\?o�<�'N��_�~���пN�8��hd���x{{s��L�bn�/�P�{pvv�iӦ����t�ޝ��:w�Lbb"YYY$&&ҹsg�]��+��Bjjj�c������ǵk�ضm�j��h42i�$��C�!--��}������h$==��[�R�~}N�<���K-��J�~o��&p3��M�6̜9���$nܸQ�|�����T����~|||���#==���Lv��M�&M�����/�x%U�5��o�V�طoYYY$%%��K/���A�=�����m�{��JII�СC\�|�iӦ��=����M�<�
f�PDDJEHH'N��ᆪw��J�J���fϞ͹s�5j}���޸��иqc�Ν���|�23f�(t�ݻw3v�X�nq�ƬY������W_e�̙ԨQGGG�5k�_|��%K��O�:@�z�J|_ӧO��ի���NNN���C@@/^��O?ͷ��͉������͍-Z0w�\v��i�v߾}L�:oooquu�e˖DGG�z��R�-�����>|8vvvlٲ�����C�r�hٲ%�F����D�˜N_����y��puu��ٙF���p��b�Y�]���y�6n�H�
prr�^�z�\��֭[s��fϞmn{�����/T�Z�T�]�_?��s����Y}5lؐ6m�0|�p����z|�y��СC:t��gHD��Μ9ç�~��ѣ���u8""E��)�yU�X��իߣhDDDDDDDDDDDDDDD�A���{lݺu4(�>}��iӦǸ|�2=z� ;;�v��1y�d��-[�0p�@��~~~���r��	s�iJ�2e�q'�6o��;#������Ύ#F�o���Ve
6�ʕ+�ժU�C�DEE��/���|||�����ٳ�[^%]?���ԩS9x� Æ
������իW����<y2�[��N�:l߾��q��<y���\4h`U����
����P�5�k���888X����Ý�o�-�xG�{���ٳ��q��
.^��֭[y�78}�t)EW��駟2|�p�
���������""�y��R�
����u("w�`0`0�rs�-�uVrrrX�~=���T�T�����P��=�������y�M�/RRR
#,,��'O����_|����E��M�O=�T�b2��8--��cb�ה$q+SyAo�����*swwnnz�kԨQ�ڵ���`�W�N���			!&&��X���u�����Ç~ȡC��p�7nd�ĉ�o�777�;F�v��'F����Y�v-cƌ�m۶xyy���[챊��k���������8r�H��%�_Sb���}���%ꗐ�`�ڳg�W��g��ڵk̛7���������1c�ڵ+^^^<��#~O��DD
r��
����8q"��ζGD�]�t�7�V~��'�J�j��ر#'N�࣏>�\�r�MDDDDDDDDDDDDDDDPJ���n=�����͛Gtt4e˖e���xzzZ��z�*P�+L����Ej���mqmJ�(h#Kٲe�v�Z��...E��w�����Xl��_X�h/��2������[^w�~y�/_��m�Nll,�����Ӈ��LƌS�y���KjժE�Z��ԩ�&Mb������E�NwM�2%�T���nQ~'����V�[��������a`ggGժUͧ���w}΅r��9�w�n.�ѣ�Νc�…w}~����ٱd����m����ͽ'I��W��u�]��'�|���~�5k�FJJ
��񄅅�7������������������(��3��p��%�F���rrr��9r���c0X�t)���/tS���4k���7��ѣG�X��ņ;S���˗��s��%����K/�ľ}�8u�, 44�ڵkp��1���ݕ�J�~eʔ�`0p�̙B�.[�,����6�e˖ѽ{w�?Nݺu3f���g���=z�Hc$�Mh����/Κ�U��Դ.�˗7����Í7�5k���4i҄�͛ªU��m�&k�M�0}��~Z�jE����4�c�=X�7��o�����lْƍӱcG"##���Ο?τ	hݺ5������[����a˗/���;�+W6�?������|��;:�HDDD����ё&M�GJJ
��jղuX"""""""""""""""�'���{�t��Ν;��/33��ݻ�������ԩS�mMK�4��M�3g�,�fޯ���+W�`0��ܳgO�}Lo�/�M/իW'$$�������?�v�Z�m�vWb+�^�	 IDAT�=��S���v;NNN��	"y����5kG�a„	���ҩS'�NnܸQ�x��n�g!�
�ǎ�m���I^?��S��g���k.��+�O?��y��q��i�_�Nzz:�bҤIDEEi��>����4���œ<y��+��fΜɈ#HHH��իdgg�������������

e͚5\�|��Ȇ
=z��<7n$==�:���ٴiS�b����eL�ׯ_��7���Ã
*0v�X�f�d���qww��ӓ^�zY�hgꟑ�AHH���T�P��^{�_����\�z��#GR�fM����Q��G��Jv��8K2סC�hӦ
���<��C0�|2`~�n�.>v�X�ԩ���3e˖�I�&̛7�Ϣ�ڷo��ٳy��,��SJ���ڷo��8�ߦ���h:t�(6l$00����B�`���Vu���jԨa.kذ!mڴ!55�W_}5ߍ�&gΜ!22;;;�
f.o׮S�N���~��
"##hݺu��E�50>|ت.��ʥ[I֯w���?��:��ɓhڴ�Ey��Ky������^�룏>2���Q��<==��T,X�o��]��"##�N����6?���E%�_�󈉉`����ڵ��۷3r�H���K��,�j֬I||<&L(t���l�9�ĉhҤ���/�`�ȑ��dzs�NfϞ
��;��,Y�ٳg�V��/f׮]̙3���������W��U����FDDDJߠA����OIKK��ŋL�8�E������_���ΥK�����<xp��-ZDzz:/^d�ҥ���s�������$  �)S�p��	�F#�N�"""�_|1���KgI�
`˖-���s��yf͚Ő!C
}�#G�d�ĉ=z���իWٽ{7}�����������8q���EDDDDDDDDDDDDDD�&�pq�
8�r��O���ٳg���lݺ�~����k����@DD��Ϛ5k�1cO>�$���m��9`����Y�p!�F���~#==���|��)	�dΜ9<��C������ˌ38~�8���ddd���ȇ~���������Ls�-[��[�HRRF����$ٶmnnn4莟a�=�֭�7o�ڵkdgg���HPP�ĈҎ�$����?�ϟ�aÆ������q��rrr����Y�~=���L�2Əo1��􆘘���1����$�fB�o��FNN���_7'��ͷ�e<�_�GXXqqqdffr��1��g�}V*k�W\\={����h4r�ڷo��ݻ�^�:o��mI�W�o~~~_�����Ett4/^�k׮$$$�f͚"�l>M��X7n�k��FRR���۷�w�^�ׯOll,�|�	S�Ln�9��t�˨Q�����ё
���Z���?��c�Yՙ��LmDDD���ٳ��~����sb����'99���tƍ`>�-�u��KVV���ԨQ��'O2mڴ�6m			4jԈp��u>LӦMٲeK�	�%��$sթS��G����n>��tr_ޤ���\�9sذaYYY�������>}z��"�s��1}�t����W�����ԩSE�+"""""""""""""""R����Z^J�`0e�\~�u^�ׯ�k׮�����>c���k???���w��.��ӧ���p�-��}�...剉���u{{{F�m�77�t�֍��,�:ggg�/_N�.],�M�#}�r�
�7�ȑ#���Z�*�����K3���ŋ�޽;�6mʷ������ϧk׮���&���̝;����|�3f˗/'%%������_~�����5kFff�՘s��1�w�kbz�K�.%88تO�J�ذa
40���~o�9�ٳ'ps#~�R|˖-�gϞ��~�I�$��$$$�i�&Əo�Yvqq!44��� ������{���l�ΝV	��`ooO�
x��g�۷���?�`Ȑ!~�M�c4�������\���N���-�6nܘ���|�3�������Ȯ]�
{L"wEQ�ED��nh����7�Ζ�����?��O>�$׮]3'/���ʕ��ټy3m۶�^�z$%%�;�SO=��9~�8����}�;���7-Z�0��~�q�d�}���?�<=�vvv����{?�>�(gϞ�m۶�k׎.]�P�f�–���,֬Y�ҥK�����ٙ�]���ӢE������c�:t�?�Hhh(ժU��ёr��ѦM6m�d�Y�رcŞ#44�����������Dݺu�8q"[�n�J���СC̙3������兣�#...Ԯ]�~��q�|�-^|�E���Opp0^^^888����믿΁�J��Ã]�v���R�~}\]]qpp��ۛ��~�X�!�4c+�xzz�q�F6l�k��F�:upss���5j���9z�U��…i߾=���888�裏зo_/^��O?���3����o�a„	�3�Y�fi<���<>>�N�:��鉓��5�o��o߾��&&={�$::�������ȣ�>ʀ�駟,�-��~���`�UXy۶m���e�ر<��Sdff��g�ѡCV�\Y��
:���9��bcc�4i���w�ԩ9r�jժ̸q㈎��ϴ���M�VmM��Lh*��	G""��h4�`����m��=��3Ϙ�/[���{�����o۶�ŵ����3%�׬Y��`���СC�gI��5_�BnܸQ�DFF���ʦM�x��y�'��� ==��~������…9w�.$  @�"""""""""""""""b3:ᢔ���脋�W�7��w:EA������oY�x1������8Fa�gN��͛�����͛��������+�޽^y��?�������o>��4gǎIMMe�ƍT�X�b����Ӯ];���X�vm�b)M:���O>a�ȑ=z�jժ�:�RU�	��7���댌��v�)����d�[�����{
�����9��N�s���ŋ�Z�����?���$""�����;�o��FNN�<�H�1�����������������kzM���<0:w�_}����<���Ԯ]GGGs;��ӧO��xv�څ�h$99���ps��+Wh߾=p����';;�Ç��[�U�NN�:eUg*3�����҈����7�T��H1�ڵ��z���ԫW��>5j���ɓ���Z}��)3�r.OOOBBB���cϞ=�1��/2t���T�RE�"""""""""""""""r�Q…��<0z���|@���iҤ	�G��A��v�S'y��K=��-[0v�X���	��ѣ���d����S�������Ѹqcz��Eݺu��|��HLL��3�5k֬�oED�Jdd$YYY�9�֡�<P�����~�:;v�0��УG�����K��3SSS>|8��V�Z�Z|wc.S�k�߃jժ��``�̙\�p�ӧO�u�V�2AVDDDDDDDDDDDDDDD�A����$$$����o]`` cǎ�nݺ899���D�Z��ݻ7�Ǐ7�6lU�V�����X�1>��m���ꊓ�>>>L�<���0���K����3g]�v���'''ڴicNɫ]�v����c���;vP�LڴiS�""�׹s��9r$*T�u8"�*U�иqc���h޼9�O���ϏA��g�ȑԭ[��;w�����舗�������1mڴR��n�U�R%��)\�4�y�HŊ�ڵ+{���<*"""""""""""""""[ ""R�:u�S�N��i۶-m۶�(+(��vu�)[�,�֙�.L���9r�՛�o���ݝ�� �ϟ�ٳg�Z�*gϞ���_�~���+N��4ieʔ᭷޲u("�իWӫW/6m�D�ʕ	

b̘1���ا\�r�ܹ�	&��_s��Y<<<h޼9&L�'�(����\�|�	�G�����dee�|�r������Bvv6���<���t�ؑ#F�������������������J��O��Ջu��e~;tTT^^^�8:��;q��g�f���J�?����B�KZ^�bE����ޝ�UQ����k��Z������]SS�v��ܲ���Vn��K����K������+��q�-��ܲ2D`~�;�x��q]纘�|f�5˙�=�m[�
,�3fhƌ)^6��i���;�cǎ��U�V�aÆZ�p��}��$��Pp@&�3gN�=Zo����v�*IZ�f�fΜ��۱ -X�VU�PA�z�2;
�,�M�6jӦ��1�d"5k�Ԁ4u�TI�믿�5j��
���]�v���+www��Ȅ<��k�j�ȑfG�0\��(  ��A[���˗�x�b-\�P�V�ҥէO+V��h���tԹsg�^����aŊ<��3��i***J�|�.\��~�I���S�v�4g�թSGnnnfG�0\��v�ڙ@
�k�N�k�6;`��Ç��O?U�fʹd��l�R^^^f�0�d���fG E��aÆ�H�"fG0������R(  @!!!f�x�q0OTT�r�ʕ�|oo�L��Qp��Z�n����cH�Ν;�������?���޽[O?��
*dv����Z�f�-Z�;v�…ʛ7�ٱ2=
.�Q�v�Ԯ];�cH�իW�������j߾��O�nv�0���ꫯ�Ҳe��F�i������2;@�@� C���2����av���3g*<<\���Q���� M�0A�O�V�*U4j�(u��Q>>>fG�R(�0ɵk�ԬY3(P@?���.^��֭[�hѢZ�n���2�'N�\�r�n�˗/׮]�$I���j߾}FF�<���ŋS0��~���L������7;�t�#G�j�J=z�P�*U̎�eQpa�#G�H�*U��0]�re�2e&��m�&�՚��}�͞=[˖-�a�С�ʖ-��իgxN�Ԙ4i��gϮw�y��(�I@@�̎�幛�Q�X��m�Q�m۶L����h�9Rm۶����|||ԦM�1B���� �~��w͞=[Æ
S�|�̎ ��ۧI�&��@�E�X,��…%Is�Ε�b�ҥK%I�f͒�b13&�k׮�cǎ��N�:�ڵk
613���ԴiSY,]�zթ߅�;��8��t�,�^z�tϝ��˗kРA4h��/_njik̘1*V�����ov)��k��ɪP��,�,X��7o��G��#�?��|��
���W;vԺu�EDDhڴij޼�|}}բEM�>]����l�:uJ����4h��':������9s�M�6�S��^x����S�W�vX׽����~������*SJ�;�mGDDh�ҥz��gU�hQ{�bŊ�f"""�8�+V�$;v�i^hh�$���S��s�N�>G�uX�8�ٳgkȐ!<x�f͚����@ڹu�~��'�3F^^^f�p���Z�`�5j�R�Jiʔ)jذ�����믿*��fGx�Qp���V��V�/^,I*Y���V��ϟ/I*[���Oz�~���w��^7n�P\\�N�:�Q�Fi�ڵ�~���z��W�d��������իW�x�b���[QQQN��ׯ���٣��ݼyS+W�������gϞ�y���…�s玢��t��a�?^!!!��?}�tEDD8>��~��a�EEE����i��������q�����T����.:w��0}7�rf\DGGk�ȑj۶�������6m�hĈ�s��ܹs�رc����m��ׯ�r�έU�V�ʕ+�5k�|}}͎�Ƞ��G��$U�\��tz[�`����/U�XQ�V�����+�H�����.\�3gΨx��


RXX����S�N�E�V�dI�Z�J;w�T�^�$I[�l��_�j�$i֬Y
����{�I��-[&I'�
P�z�)�ܹScǎM�Nl۶7�W�P�i��6Wo��r��Z�$6�ETT�8�\�r�gϞʕ+���٣��X�~f\�ڵk�ر���S�N�v횂��M� m�̙S���
F��˗/k���jժ�}�,d��2����&�{�ӛ��C�Q�%�+W.
>\V�U�|󍽟�Pb���Z���gϮjժiذa��͛7;�{�С*Q������oO��ϕ+�$)$$D˗/�?����m��j�j͚5��ߥK�T=l��v�ĉ��-(�W�R��H{.��bQ�=���#�ŢM�69��l�R��>�LDD��M���͛���W-Z�����鰜��c����_�����o����k�رjР����4b���~l�����S�;w�v��ʕ+�|}}�P䕐���Ǐ;�'�<?��ﯺu��i�ԩ�l�߾}[cƌ�����ׯ�Q�F鯿�r���K���g�uA�X�b�X,Z�t�"""�=5 ��7z�O<�B�
eP�B�E�=�j+,�2e�,�~��IҸq�2���/_�$�+W.�~�.]�$U�V͡��g�qX��J�.m�9_�|��}����ߖ���v�ڥ3f�C�


RLLL���
R*������%Iy��u�gk����5j$��B��
l?������|��<==�����H���Z�d���������իZ�x�z���T4!IӧOWDD��� ""B�z�Қ5kt��M����~�����˟?��/�������v�8�=��$���_�
�$�ܹs���������ϟd��?�\���V�"##�t�RM�4�i&O���k�*&&F���Z�n�z���P�a�EEE����iy???EEEُ7H�۷okŊz���O���fG@(�x���=��wP�+{��In�q��Z�~�F��jժ)&&F�}���5k��+W&k���na�����X���߶e�ݝ�2��=����*U�(>>^�$���i���rww�Ν;�[�Q�jժ�\�ri�…:s挊/��� ���)00P>>>:u��ϟﴽ��zJ;w��رc%I�-ҥK���Oh��
�ܹsu��I�em�;v��vo��s�='777��[��I�Y�d�$���Ν;���?�/��$�ر�i���P͜9Saaa


����._������)c�
�������3C;w�T�~��㏫S�N���״i�7@&G�E�Z��;w�$�r�ʲZ��5k�$�F��Z��Ozz���%I�N�J�����$�n��M{{{�j����S˖-���{��
����S�>�CJ�nݲ��ڷ��+��$ݼy�i����@��F��w��{�m�\�w�Vxx�Z�j���{��^�z��-[�H����U�*{��V���
&Iڼy�S�.]�8wmݺU�4l�0U�TIٳgW�5��;-k+N�P���o�v�ʖ-�"E�H��~Q�|y]�|YgϞu�����<۷o�޽{U�bE�_�^�|�&O�,I���tZ���ޓ����gϮ�U��G�I:q�$�dɒN��F���3o�<=����WXX�F��.hݺu�ܹs����(��`��+W��r:#�ް>u�T]�zU111�2e�,�^y�{��u�J�&L��C�)..N��ĉ%I�?�|��ݪU+Y,}��׊����O?��e�Jr=:ƅ�΂J�V�^���h�9sF�&MJ�~��v�r�$I�ϟwZ����@�hذ�����7n������ٳ�����}���]/�Hd� IDAT�$�ҥK��jժ9��g��$]�|�i[���/J��V��rw�w�[!����C?۴m�ѣG�O*�_��nݺ�[�n?~��-[�3g�Hr������a�z���%Iׯ_�$�͛�iy[����!66�B)�d���jٲ�<�C�iРA��vd~fx�d����={jӦM:t�Z�h�0�O�>���w�͛7�…�ի�C�%J8�%G���5a�M�4ɩ(�F���,��ׯ�M�6��ڵk]gݺu�j�*}�����%I~~~N���߮���s�i۶m:r�CN��05(�4��m�W��T�VM���׵u�Vծ][�3�<���PEEE�رc�^���+1			�λ�mӶ"�{�<<��3Z�|y������JHH�Ν;%�.����/�N�:��ɓrss����T�)S���_�O<�_|Q�K�V�J�Ծ}{��soN۾������Vlvw�����@���kĈ�t����gv�ԯ_?�#�0�E����F�,�(\�����ոqc�͛WٳgW�
4y�d5k���/o޼
V���U�hQe˖ME�U�N�4��T=�צM�5J�˗����<==U�ti���Ccƌ��<x��/�lٲ)666�u8Pm۶U������)???�92��j�M�4Q�\��c����رCy��Q�F�R|<�L�ƍ�����֭[�"����/�Pdd��իg_��:��6���}��>�������;����w˕+�J�*���h<xP�V�|����+VT�B�t��A<xP���*Y��r��u�<�v�$�����/��0?..�a�СC��$=���…K�n޼�=[����/""B&L�k��F��N��ۧY�f��.2غu����GSr���h„	��?~
:TC�M���7�'�޲eK�l�2�5n�X�7N�6r�̩��{O��}�'g�]m;w��
P``�.]���ŋK�.]����_�~�zH��iР��N���+WJ�ߨ�=���O��%K�H�w���u�j����0a�ƍ��+�رc�8q���NӴiS}��g�0a�Ǝ��U��ĉ���]��X��Μ9���@%$$����i�777�����SPP�}��SÆ
u���;���B�
٧?��C�7N�˗��Ç�&M���+WNW�^���
+Ο?o� k�:u�bcc������|��-Z���>|Xe˖ի��ʿR�p$S���U�X1�����BBB���.]���xt.\X5j�PLL�ʕ+��E�J�J�,����?JHHP���F��޽�J�(�K�.�W�^�U�^�t��e�(QB�z���v�t�b/H�۷�|}}ս{w�/_�e[���ݻ%�[⊭`dϞ=�ݏ��dԨQ���S�.]��o���?~ܡ�B�ԣG����O�>�z��*V��:��2���֖���v�f̘�w�}ס�
@�ܺuK!!!jԨ�J�(�)S����_?���N�8A��C�.2)�Œ.�Ml��_Μ95z�h���[�ڵ�$i͚5�9s�r��ar:��q��T�ƍe�Z������ҥKU�^=���y�*88X_|�nݪ���[�V�
ԧO�˗ル<==5w�\͚5K?��nݺ�_|QÇ׆
��W�T��������\����W��������!C�(..N;v�P||��~�iu��EgϞ�ܹs�l�2�mN�>]|�v�ڥB�
�iӦ�ݻ�<==�}�4i��?�X;v�P�n���c��ɓG�5JV>�7n���ͫ����3;
�P�ݻ�V�\�f͚iٲejѢ����̎��f�av������BBB�r:�(�ȼ/^�}��I��<u����DH�;w�$�&�N#�/^�Ν;���{���l�-I�Μ9
��իU�xqIҥK�Ժuk���O�{�N����>ggΜQ�
4k�,�����8�C��ٳʛ7�{�1�� �1�E&EaD���B�̺w��^!!!:t�������եK��H������'�T�^�̎d�o�NrĊ'�|2� 3q7;�r�̩ѣGk͚5�r劮\��5k�h���ʑ#���$Ø1c��O?�Ã�j )�o���_�֭[�|��JHH0;2!��v5k�Ԁ4u�TI�믿�5j��
@r����x��f�2���0-\�P˗/�͛7U�~}�?^			rw�}pD�)�՚����i0Ϝ9s4}�t�<yRU�T�СCյkW����
��hŊʞ=��1$Ê+Ԯ];�c DEE�E��ܹ�j֬ivd\��իWk���f��GڠA�̎�,���tb���w��AY�V�����(x�Pp�Nڷoov)������3;�C��#���X���Hğ��"E���p�/_֒%K�`�>|X�˗W�n����iv4<D(�H'�۵kgrɱb�
eϞ���%JpO�(���ӝ;wT�N���G���q�t�U�V)$$D7nT޼yվ}{͙3Gu�ԑ������"���(  ����s��fGx��������И7o�~��wu���(@����&M�hɒ%jٲ����̎��@�q�Ʃo߾*U���q�1q�D}��*Z���Q����ڷoovilŊfGx�͞=[���1b��Q�4�lٲ%:�|�����i�ĉ*W���y˗/׮]�$I���<�
<�J�(�v�ڙ@:�m��7ojҤIz���㏛x �o��?����`�<yRG�����ٱI\ 
���;ڶm��V�Ӽh���Z�l��P�T�lYU�^݄�2�������͎��>�H�4d�����ŋk��źq��ׯ�w�}W			I�rd$w���m�6�����9r�ڶm+ooo����M�61b����38%@��O>�DC�U���͎���ٳU�B���駟~�СCu��9mڴIݺu���
&�X,�X,f�HW����v�:v�ho�ԩ��]����`�d-���Ӷm���o�H���G
6��jձc�����'�0;��`����K3g�Thh����U�tiu��MÆ
�$Y�V{ߨ�(jӦM���?��c�饗^R�޽���)IE#���V�"""�t�R=��*Z���O�b�d�X�t�Ru��Uy��͈���jԨav �F�iv ���t��-���[�֭Sxx��ܹ��Ǐۋ-�����k���|���ܹ�+W�(((Ho�����ֆ
%???�y~~~����ƍ�l������Z�h��1�4C��#($$D/^���������s�:�@a��W_�رc�\��/^�ݻwk���^����٣5k�Hr�j�ڧw��)I�P��Ӻmm�>��k׮iƌ�^���V���>��E�@VA�E�X,�����-[�H����U�*{��Q��F���wӦM��	&�lٲʖ-��z�)�=Z��nݺ$�u��	IRɒ%��*Uʡ�����Z�b��7o��ŋk̘1�U���mۦ_~�E��3� �?^���3�8�רQé�$I-[�t��S�N%���ׯK�����4��f� �kݺ�6mڤ&M�h�…jݺ�r��iv,@�{�n�ߣ��ڵk�D�f��	�j�:L�F���=#��0���v�>����Lr�m���rkks�]�+>>^ٲe3;`7q�D�����(���̙3�x�b�cL����c��G�O<�ӧO�_~Q�Z����S_ooo�?^k׮���w��U�pa]�zU7o�T�…�ݼy���6oެ~��i���*T���qIR���͎x�($$����F@f�<�z�5���i�9���8>|X'Nt�[�^=I����u��q������'�|"�Ţ�����~	r����ʕ�$�?�iݶ6[��a6l�ʔ)C�ҝaھ}�z��^x��8@����Ν;�~йs�ԣG�$����C[�nաC�ԥK�y9r��������զMy{{k�ڵz��m�69rD5j�pX�ȑ#���>mv�!���jϞ=�Z�fG�C����Z�`�-Z�s�Ωf͚�ѣ���N}> ��޽���^��S�ڵU�D	�cp_\�̌�r�̩�s�j���ھ}�"##��SO�K�.5j�<==�}��ɣ�� ͛7O[�lѵkה;wnըQC���W�2e�}�O?�TW�^Ull�$�I�&��㏵c�u���!ǎ;�'O���WBB�F��6m�8�iaѢE�;w�v��)ooou��Y]�vU�*U̎x�͜9S�/6; ����(  �����B�
iԨQmW�\�$=��c���ӠA�4hР$�ٸqc5n�ء-w��
P``�.]���ŋK�.]����_�~ʕ+׃��Ceٲe:z�,Ybv<�v�ޭ���?���ԤIe˖��H�($$���t���fv�����x/��,����k���+!!AgϞ՘1c$I�<�L�n�{��*V���/�CBB���.]�������8}�
P�J�̎����ٳ�d�5k֌b �p�IY,�tY��jU�f���_kҤI�4i����o߾i�͜9sj���z뭷ԵkWIҚ5k4s�L�ȑ#M���-\�PgϞ���͎�,���_T�^=��Y���C��D�Z�~�Ξ=���X=���S��z�E���6k֬�h�ԩ���_]5j�H��duM�6�…U�ti�� �s�֭[����k���*R��Ο?/ww5���W��X�bf�@&���8�
���"��Z��nwww(   ݶ���j|||ԩS'�c �طo�-Z�%K�诿�R���5g��mۖb2Xhh�,X���P�?^���*Z��j׮��={�y��fG�nnn�$�0�l�V�U������u��9��ƪ@�*_��^z�%�����K��K
:T���O�eI�q�R+�,�)cj��*W���G�j���z�g����f͚�\��>��iyl��|d��	f�	Ȃ:t� �Ţu���7��ٳg�i�&���Cy��1;��k׮�Y�fz���5o�<?~\��ъ���ŋ�r�J�h�B͛7Wxx��q��!C��V�Z��/�믿*::Z���￵s�N�1BO?��V�\�l߾}u��
R#�qu-t��]���u�ٖ{X�= i\@Իwo������4r�H�(Q��H<r���թSG�ׯ�����N���G�***J�o�����5n�8�͛W�֭S˖-gv�,��/��ԩS�#G�=Z�Rdd������_���+�����pu��IV�����B�v�lٲ)$$D111I������ŋ���.]��i�0���!<
(��,�Q�F�S���1x����SgΜы/���G��w�QŊ�3gNyzz�\�r1b�~��g(P@۶mӜ9s̎�e̘1C��t�R}��R��r�έlٲ�p��jР�V�Z�~���Ν;?~�ɉ��+VLM�4э7�jժ$��\�R7n�P�&MT�X�J2
.�Q�Ν���Ƈ�,�Y�x�ٷI҅4n�8�����(d:�ϟW߾}U�D	yyy���[�;wֱc�\�O���e�Zծ];)RD���*]���{�=EFF:�۱c�֯_�"E�hժU*P�@��+W��I�&I�wԆ{?~\ݻwW�������ŋ�G�:y�d��%I{��U����3gN,XP-[�Ԟ={\.w��I���_eʔ����
(��5kj̘1�q��eR�-))=�m4i�$�6L��u�VIr:���wLL�f̘�^xA�����{�15o�ܾ�{���K��nݺ���[ٳg��O?�O>�$�z���ϟW͚5�;wn�����%1�=&w/��+*{��*R��:t�#G��w��̿ߵУGIR```��i�o럚s���6�}�$�{bˑ��SR� Y���ؔi���M!!!
�$�X���DR�D��]����$)$$��H��U�ViѢEڼy�{�1u��Q3f̐�;u���׽��O��;v�P�-�4/G�Z�r��5k�Оԃْ�3gNEEE٧,X�W_}U���N}�y��رC�s�$���Os���ȑ#5v��$�#I�o��޽{U�V-yzz�ۿ��{�k�N���N��Ν[�W�VÆ
]�׮]�T�n]���8����֭[F�ܻw�4h�����J�*�]�v���O�l��:5�t��:s挾������enW�:�a(""Bu�����]~͚5jѢ����KҺu�Զm[��q�ĉz�����l4c����y�fIR��t��Tg�{�����ؖ�2e������K_�u����c�οߵp��my{{�ƍ:}���|�I�~gΜQ�2eT�`A]�rE�o�~�s��c������`��ĮA[�����w�̄'w}����O͎�����gϞ�V�޽�;wn�Z�J/^�'�|B�����նm[EDDh�:y򤢣��޽{+66V�r��r�a8}&L�`�?o�<��gϞU�~�������ٳ������U�L8p@�'O��

�$5o�<Y����%�b��W��cǎ���V�V�t��ݾ}[G�Q�V�t��-�o�^W�^u��^�z饗^Rhh�nݺ��[��t�Ҋ������8P�ӧ�N�<���XEEEi˖-�X��Ν;�1cƤY�������曒�-niԨ�>��s;vL			In�v��M�4I���W�J����(���h׮]�S���Ї~��Sr���O(::Z:t����u��m8p@�5Jt;���ɓ:|��n޼�iӦ=P��H�1�۰a����]�v)&&FG�U˖-u��mu��E��g�3I�����ԱcG���� ��

�a�ԩ�<==���OF]3�;6zpu
�%H�����i>|�d�O@@��;�0
@z�z���+W.㣏>2;
LҾ}{�f͚ƬY�������8d�{����'L�`H2��r=Lr�MXX����aH2��0o�С�$�C�N��ݻאd�*U�ޖ;wnC�q���$���aÆ��z���������z���/��6�����͛7��
8��ȑÐd���?N�9rĐd����Y�����%$$C�1������'O��_4��}㧟~2���\��U�0��%K��}��9�;y�!�ȕ+W��K�q7n�!�h֬��2w��1�ԩ�2�f��/��6���M�=%����*W�lDEE9̻��;vl�r$7�+�w�6$��������8�x��$c�޽�a<���_�Y�̽�����Ͻ�W�=
@f��R�QHH�˷����'�}�`�?�P����믿nv�d���Z�z�7T�P!���i}�����7�x��޽{K�6nܘ�:n޼�N�:)..NM�4�ĉ�㏒�8-k�Xd�Ξ=ko����$�ɓ'{�hӦM���C�:�t���w�}W��~�z�˻��R�Z�$I����O<�$�Y�f
		��n�W�R%��K�.�Y��������iʔ):t��ʕ+���M���ڶm�&N��
�\�rھ}�}s؜;wN�a�F�N�[h� IDAT|�II�;�����}РAN�xxx؏cZg|����R�%9RrL�6r�H�̙ӡ���˖9=ժUK*T�ŋ�a��y6lХK�T�reY,I~n�Ǭk�^zpu
�y�x]�pAs��մiӜ����C||�N�:�r��%�'G�����رc�$oo�$��<y2�y}��չs�T�L-Y�Dٲes���)IR�jՒ�)_�|�q�"""�?�d-�X^ۃ��۲ݫL�2Nm�s�$%$$8�6L={�TXX����$�[�ѠA����jѢ�<==�,���U�TI}�>��#ݸqC{��ў={�s�Nm߾]�O�V�&M��5k�7��Μ9��G�jϞ=ڽ{�<(I2#�eRr���WIJ4���o�d�ؤu�Ĥ��-���}�YI����S�)%�w��{O���z饗�큁�������܏Y�̽��� +��0�������>}��i�ȑ#�ꫯ�h�"���/:��LRo�ON�y��i���ʛ7����[,XЩOdd���XQ�LY�V?~\�k�N�2qqq��ߟh#""$)т��y�J�nݺ�r~J^�УG�ϟ_�Ǐ���%I�����ϟ����t��ڸq��z�4�v�=w+P��7n�ƍ�s4H����ȑ#�nݺdmkٲe6l�Μ9���wK�q�G��W�…]�A2�ʕ+M��Oj_,��c��lϗ/���}/�[׮]5|�p�Y�F����)�?��Sk׮�����t���A���u�$�#��W� YO�<�,�}����ĉ��[�|�
�A�i����
 mL�6MӦMSll���ԩS
֨Q������={�,��T��%K���W_Վ;(� 
�ޔ��
���'>>�i�_�Uo��������W_�bŊIn#�x?���
6$��o���…;<�m{`��͛.��q�C���+�h߾}:�����ԫW/�-[V�t��i�����-5�/O�<rss�ŋ�\w޼y5a�IRhh�}�H��ŋձcG�9sF�˗�ȑ#�o��V���[�֑\�;��=��S�%=%�}�]_
p9��H
111�����F��Ν;Z�p�$i�…�s玚4i�bŊ�����Y����?�Y��L��;�s��.�8p@�g�֐!C4x�`͚5�>�)@V���j��T��V�\)�04z�h=��S�ڵ����|�My{{��W�*U�u�V�={VcǎU�ҥ͎�C�L�2����9E���Ĩcǎ���Ҙ1cԲe�D���ȑd��cǎ���?��&��|��7
�����6����r�ݻw;�K+%J�PϞ=�'Nh�ڵ���[��K�Ԝ�jժI���ݏ�&qqq�Z��~(I�3g�~��W�;V�z�R˖-F8IHHHv���
|v���r�m���Ș�,�i߾}.�mmׁ���&QQQN˜>}������C��`�IRpp�C�Mz_?��1�@fC��#�j��j��C��m�6�����9r�ڶm+ooo����M�61b����38%@�]�rE����jժ�������O�
Ҕ)S���av<�___}�嗺r劂����/2�i�iӦ��}���C�˗/�����5k��>x�`:t�w��ԫWO��4�ȑ#rssS�R��m�j�R�F�t��Uu����6/^�ԩS�����ۛ4i"I�2e��C�			�:u�$�A�IfO�R�J���MG�u�����Ԗ��Rs�l��3F�Jr�'N�$���;�ۊ[����)Ir�B��ӧ�N��K�j�J�4i�$�#�؎��#cj���iӦ9����k��ɒ������
,(�u@PPP��I�Z�[�V�T�@>|X!!!:z�
*�T����OF_3����?�����,�,��12���`]�v�f I�ԩ��]�f�@f�3gΨy��
		��jU�94{�l-Y��0dm�;wV�n���ր�?~�ܹSM�6՞={�-[��_�~�ڵ�<<<4a��2k֬ѧ�~��U�j�…#K���k����K���6l����EEEi����Y����s������U�re}��:s�����#G�裏>��b�_��#F8�����^S޼y�e��i�FǎSll��;�6m�h�֭ʕ+��x�>��:u�$�k�N�6mҭ[��#G�(  @�
#�:[j�_Ϟ=��秿��[�j�қo����P���+>>^���֭[�6m�h������И1c�k�}ͪU����XI���!�[���(>>^G�U�n�f���Ss����k�֎;Լys���/�������վ}�DG1H���͒�֭[�:��㊍�աC�ԢE�����'�T�^��ۊj�����P�������4h�>��D��صp�9r�C�����~[ҿ��*6�}�d�5�ر�����4!�		It:15k�4j֬������x���?7^y�����x���=z�|��r��g�q��-c�̙��/�l���-Z�0>��S���N9��a����?��1`������k���?o�������0���#   �iR�j����Ǐ;���7FŊ
OOO�w�1����")QQQ���ˍѣG���VJ~?����9s�4$��|��g�k֬�h߻?w4���\��S���������O?��6�e�f�5��~�Y�����r�����˿Ź�~��7o�4*T��h��ŋ�ΝK�l)=�aׯ_77n|�s�/_>cŊN�׭[��;wn��9r��|~���|�
�0��Œ
���…].�^S�%������ڗ/_n,X�)K�bŌC�9-�w�^#G�.��}��ص����g�޽N}�ܸj��k&�c��'[��<_���={��͛�.�Ν;�����Ç5~�x�����_ll�������˺s玮\���� ����I�*I6lPTT�ˡ������7��H'�VΜ9U�L��֭[�_~��ɓ5m�4)RD�/_6)���0}��'���O�raaa�ׯ����թS'�߿����_�f�t��A���KO<�gϮ���Q�Fڸq�^{�5���O�N�6z��m۶饗^R�������kܸqڲe�r���L�ʕu��a͝;WM�6�����gϮ9r�lٲ�ׯ�8�4����/������K�.�������խ[78p@�[�N�~��/_>�����WŊ�3gNyxx�L�2z�wt��,Y2ݲ��IR���a�����ڵ�ʕ+�\�r���]���S�ڵ5f����oj۶���jڴ�r��-��?��$���G,P������|��aÆ���4v�X�9R�4gΜ��D����_~Q�>}�DZB�
Z�x��v��r��ʘ�,�]�vںu�,�<<<��SOiȐ!:|���T����b�h�Νjٲ�
,(OOOծ][�}������v��������K���m�X��d����LR�&��Odfn�af�x���)$$�>��Ӊ����j��{�ĶY�n]EFFj֬Y�X,�s�֭[�I�&���Gk֬IQ��� }��g�\���
�ҥK��0a�<�#F���j��;vh�ܹ�Q��C�}���_�~z�4}���=Px�t��Y���C�N�C�Տ?����ޝ�՜�i�ggB�b0ֆ,�e1Ѡ	ɾ��`�������B#;e�d-Q�4�Ȯ"i���{�n�������>���9��|L�{��˗/�����ЫW/���9t����Z�����Klll���ۛ��ۧY��ݻlܸ��7r��-���
D߾}122ʥ��B!�B�/�|>/ė)_�|��ESė'��+�B!�Bm��v_M+`h:��	�
�իW���N�6m�ݻ��*0������9s(_�<ժUc�����ٓ���ō7�V��R��J!�B����իԭ[W�xdd$]�v��Ç\�xQ-�TdO@@�������s��t.F���K�������iܸqn�*�B!�B!�B!�B!���t��о�cǒ?~���X�d	}���Ņ���,ջ{�.VVV���)_�$����4�y��9E�U+SS�B!��ˮ]����}HH͚5�����J�Esqq�Y�fT�Zf͚ſ��KRRR��֮]���Y�x�$[!�B!�B!�B!�B!I��u/^Ty�w<7XZZr��A����ׯO\\�V��k׮�ڵ+����իWi�+����Q<�u�B!򪨨(�߿O�ڵ��|}}iѢ_}����T�ZU�~^���<x0C�a���9r�2e�`ccãG�ؿ��˗/���~.E+�{nnn�˗O^򒗼�����M�{B!�B!�B!�B�<CO������+++�����ѣlܸ�ŋӫW�L�322�Ν;�ݻ##�L�R�T)"##����T�R*eQQQ�:B!�y�իW�;\�޽[[[,--ٺu+�fx������^�z������I��ݕe����(Q�������K���]�����k;!��~�vB!�B!�B!�B��H…�G�DDD0y�d�v튉�	���PY�7��ڶmˆ
pttd�ĉ������K�l���͛133���x�SErr2w�ޥR�JԬY���H�ܹ��Xq��e!�B���ڵk+V�J�*����O?��СCY�b����ﳱ�~���R�
�.]�Z�jju�u����IJJBOO������F�!!�B!�B���dm� �B!�B�!:�@h���7o�Z��Y�f8::ШQ�L׳���J�*bggGӦM�ԩ�7o�@��7NY�D�X[[+W"nѢ�~�bJ�c9s�B!�IPP_�5����=��ӧ���$�9$))��S�ҽ{w���{Ξ=�1�`ڴi�x�S�N�r�B!�B!�B!�B!�B�O�,�e/^�vX[[������;���caa�L��L�"E�����ڵk9~�8�?�p��4jԈ#FP�F
e�	&�r�J"##����S�N,]�����E��cǎm<�B!r��˗����ҥK���`oo��>O�<��֖ӧO�f���f}SSS�ׯώ;h׮].E)D湹���?j;!����[[[m�!�B!�B!�B!�y�$\|�4%yXYYaee�nی�344d���?>�z���XZZ�+\�0����[����*T�@DD>�B�
��B!�6����g�:w��h>~~~4k������.p��ey�b����F~���P�B���s��V�X!���<���]�!!�?��CB!�B!�B!�B�<M.D�4p�@��ߏ��+'Nޯ�hdd������B!�H[dd$e˖e׮]�l�R��|6BCCY�b���ԬY�
(w^HNN��˗*mbccy��-���иq�\�[�̲���vB!�B�U;v�gϞ�C!�B!�B!$�"�233�(�մ�E^T�`A�O��/��B������C/[��
h9:!�B�����p��Y�U���P>+&&&lٲE�a!�B!��#KHH�ݸ�B!�B!�y�$\�<�q�ƌ5��0z�h5j�娄B!�gbb���B��W_}��0��˧@�K!��"WWW\]]��B!�B!�B�p�g}*;Q|l������j;!�B!��8}�47n����ܹs���$ʖ-KӦM4hݺu�v��"_�|$''��y�_�κu�8~�8aaa�~���E�bjjJǎ2dU�T��>���&N�ȋ/r��9�b�3*��O^���B!Df,[��ӧOk;!���?�L˖-��B!�B�.I�B!�����j;!��(;;;m� �Ǐcoo�����߿���ٵk]�ve�֭j!�OW\\���+��μ{�N���˗�?����3�|Ǝ˜9s���ϱ��
�c�ʮ�˧@�K!���s�αc�lll��B��dǎ���S�a!�B!�"	B!��ĉ<X�a!��DI…HͣG�h޼9���/_����ӥK�V����.���;v�`��8p+++����ӓ�#2"..�Ν;s��I�����֖F�Q�D	����|�2���l޼��r����ߟ�I��/a�
!�B�/���-����C!�G�ٝ*�B!�Bm�B!��֭[�A!�'dϞ=�7N�a�<lРA���Ӻukv��M���U�k֬�ԩS�ٳ'�<ygggƌ���?-�ƍ��ɓT�^�;vаaC��%KҡC:t�1c�����ˋI�&�x�b-E-�B!�B!�B!�B|>$��#���ٽ{���Bd��;����vB!�B��Ν;̞=�C����#J�,I�v�ptt�v��j�3�Z`�.^����9q�QQQccc�ԩS)R�������L�2xxx�%[|�nݺ̛7�#F��?��%\���0w�\���y��	eʔ�cǎ8::bbb��u%''s��&M��ٳg)P�L�:�&M���

eѢEx{{s��=
,H��ձ���_~�x
��--��ׯ_g͚5)R///�V���7n���iҤ	˖-c̘1T�VM�i��<����)�$''�~�z���/BCC)^�8�ڵcڴiԭ[7ݾr"����3x��m���			�]�v�ݻW����Y�h�oߦJ�*���vvv$$$0{�l֭[ǣG��^�:'NdРAj�������Ŀ��KPPQQQ/^��M���o�ѦM���g�D!�B!�B!�B!2G.>m� ���6m��0��5<   @�a!�ȣ�v���>>>|��wDGG+�EFF��憇��v���+X����7nd��$%%)����3�|�9����`˖-�1��%K�ۗ��=u��QK�ؿ?666�y�Fy�lܸ��;w�{�n:t���Ν�M�6����'��ݻ�Çs��	�5k��{��ڷoOLL��X||<�/_����lذ???ʕ+�#�����~�z޽{Lj#�M�PhР�^��u��1{���ˮ�����'*~��)���xzz�s�N���\�#��s��|�2���Ƈf̘����)c���-[�իW���,		����B�
ѧO��ڴi��G�ٳg8p���gϞ<?�B!��*333�}r���3�63nܸA͚53�.�S�N�{�n�]�Ftt4E��o���ښ�-[f��)���5L����`nn�?��刄B!�B!ħB.>wwwm� �B���ŋ�7N�a!�ȣ$�"�y��9�{�&&&�q��1j�(*V�H@@�֭���[[[�_�����������Ν˔)SX�v��������IJJbĈL�4�
*��燃����̟?�3fp��i�u떡kȟ?��d���H���˛7o�ѣ�g���Ą��P����~ 88����J�t�҅_���
r��̭[��5k���W�7n111:��'R�re9w��G�&88�?���U�V�Hl��;q�={���*��ӇիW��흭�M�X�fʔ)����t�R4h��[�����ٳgvvv���R�L�\�%��{�CCC�z�*�*URI�QX�r%�ׯ����۷<�}��ѯ_?���pqq��Ɔ/^0t�P>̲e�T.�͛��˗�S��W��Q�F�����q�8{�,�g�V&\|��B!����_��ɓ�JZx��-��G�U9���N�:ũS��ر#��'Z�37����b�
�o�Nrr2}���Ԕ
h;4!�B!�B�	����D���akk������"WݺuK�!!��C���#	yy��իy��1���̚5Ky���sss�-ʒ%KX�r�JyJ~~~������o���*˜��y��-}����Iy��‚�[���߲y�fe�ŝ;w��믳|]˗/�իW�m�ttt�S�t�Ё�Ǐ�b�
��ժU+�X[�n�?��C�v��U��
� IDAT�{��%,X@�����קM�6���S�n]<==�	ٍ�CY����Ԯ];�
ԯ_��7of�]vԪU�cǎ)wL�]�6����r�����6mZ�Ē��c>L@��}�:u*u�����P�|Ŋ*��Ο?�}���s�,Y A�(R���7�j���ի*�P�Oݴi�5Roڴ)�6m��Ą���t�[!�B��H.8y�d��1{�l�=J�"E2d�ڵ�\�rDEE��燳�3^^^���+���D�y-��͛7L�6�޽{+ܭ���:u*;v�P�Q!�B!�B��$��#�ٳ���!D��?j;!�B!R�ةa̘1ˇ’%K8r�H�������ׯ���t�ԉ�s窔{{{0j�(��fffj��y�x?Q<�����8q�r������&M���<xP�u�=Z�X�&M���V9nllLhh(]�ve��Ѵj�
ccc��ח��>������X�bi�;%ŤM�-|,ӦMS�����߿?�.2+���u��i����B�gSSS����[��Z�j����}�v��Z�*��B!�_333 �M��8p�������P�JeYɒ%�ڵ+�����ۗлwo�ի���?������c���<֯_?�n����5�B!�B!��C�p���ب�b(�Ȼv�ޭ��B!�HUpp0�r5��(vE�dذaܾ}�5j�u�VtuuU���€�퐐CCC^�|ILLL��RƫH�HIq\[J5j�P;V�pa޽{�r|ʔ)4��g�r��Y�}F����޽;�}�9ۇ�r�
*īW�2=�/_����Y�%|������Z,)gғ��H�IM�R�T~���Gq)�}}������	

��;w��� ��-�B�{�.�z������=z��<<<066��ѣ�ر������(]�4mڴaԨQ*THc�=�={�ʕ+9y�$o޼�]�vL�2Ec��T�_S_����[�///�<yB�ҥ�ҥC�Qy?���	��T�->T�dI���X�l����2�B��3g�7o^^^вeK~��gJ�.�R/e���'&&�5k�p��1�={F�ҥi׮Æ
Sy�h�m�6/^L`` ���C��;V����;֬YÑ#Gx��!���T�^�=zгgO�~�m�Ʒ�~Kٲe�ǿ��+���ضm����hѢ�H!�B!�B��!�B�y��	eʔ�vB�K�U񡔻5d��ڵkqww�hѢxzzR�D	�:�^�2>Q�F�\�x����6m��6���*�+���P����k��
�P����+V�Y�fq��e�ݻdž
ذaիW�ȑ#j�d5�e���r��e���i֬Y��`bb��6٥�p��b�
ų�e�>�6	O!�$��IOiپ};S�L!<<<�m�B!�D�*U��̌.��kC`` 4m�ccc���X�n�J���H�m�Ftt43f��P�111888�<v��!�Cf���xF��L�x��!...\�v�+V(wm�r�
�Z�J3��-[�l�2������ϟ�޽{�����e������+��ldd$nnn�?����NTT���]�v���;X�b�6mR�OHH��ի\�z�ׯ_+w5?|�0���4o�\-��͛s��y�9B�^�2|=B!�B!��ˣ�����ƍ�����3~�xƏ���{.F%��st��E�L����%u�ԡV�Z�hтѣGs��qm��k�W�N���s��w��e�…X[[ӰaCLMMiذ!��=�-�޽{9�gnٶm����>�xf����/�w�ޝ�s�9�9u
��Ν;S�zu��i	

�z��t��%K��v�Y�����U�eR�����K���S}%%%���~�:������c˖-Ԯ];�>2:9���x?�%#n޼I�R����SSLfWL�II�[�"����t�w����LMM�u�cǎ�(�e�u�� ��w��@���5�k�	!...S}���3���ŋ�Z,����`V���ѷo_��éU�ӦMcݺuxzzr��M��%�B�W)&��߿_��ݻ7[�n`��ɜ9s___V�^
���O��ۼy3�q�FΞ=˚5k4�@��>?���ŋʟ�l�Bpp0u����͍s�����N�
8�<{��Q�{��	��.{+V����je�O�fٲe�={ʗ/σزeK�q��i�&��éP�...�={�u��Q�|y���ذa�Z�ʕ+���3gpppP��W�{����9{�,�N�b����de�3g���_���8��#�B!�B!Dj$�B�_�U�ZLJ����X���~��	&�|�rr9B!���gϞ���@�>}ؾ};�n�"..���"##9t�C�a��yz%�*>>�3fо}{����r�
���$%%M`` �V��}��̜9���xm��i���^e<�P�pp0k׮�S�N�޽[�a}4�I�`��gmm��b҆O�YW�5��T���8���Kll,��'VVV��U$]�v-C��۷/�~�V�.i������&_�|j}�?^c�s�Ω��)�*UbРA�[��7n(Wm=q��G�-+�oȐ!�������{���:::�II
��nccc��ݺu+�qir��%�����_�~�ŒY�z3c���8;;s��uf̘���VVV*;Ҽ{�N[!
!�B�
333�Wj�۴iCɒ%���"!!x�۞��e˖U�p��).\�@�ڵ9x� ��7���2�K��}Ĕ)S�S����4jԈ��]�nv����`Μ9������K�j՘>}:�@��݇;j�H�֔=y�d�7o���>���S�.��o��W����ԯ_�)S�p��1�6'N�R�J�ϟ_��㇟�(v�puu��ݝ/^лwo.^���x�X,�r��j}T�RE��B!�B!�����#N�<��7o�6m�{���Ȉ���cmm�ԩSy��M.G)��S���Sz���ɓ')W����;�&((������?~<��ĉ6L�*�B���x���ٸq#:::��ݛ
6p��n޼ɥK�شi�r2��
����$�.Rs�֭\��V�׍78�<�7o�}���}��	&h�r;�\Cv���]]]<==y��m�u߾}˞={��եgϞ9��0���ҹsg�����D�rwww���G׮]U�O�0���@���m��u�֩�]�v�|��)'�4i҄�;I�>}4N�W��>.DGG�	&(�w��	��M��.R߭!3�T�B�|�

R+k޼�ڱ��-+��F��3���8:w��j�
�ϟ�k׮���3r�H��
%J�P�K���%��*dҚ̿h�"�cIIIʉc��r#����g0�����߿�Z��ŋ����s��1^B!��===z��Att�r�___�����;������5k۷o'<<М������P�^=��
6T���>�޽����J���3�ߍe˖��Çi�3""B������U~nР���(E)�����6&<�׎;�������ǒ%K�ӧ...j;�=����vRS�B!�B!�"5�p�e)W�ܬ_��Ǐ+W>�ׯ�?f���Z�L!ħf�ĉܻw��M�*w��Q�
@__�jժ1z�hv�܉��!�Ν���U�a2�͛ǹs�P����/�����‚�%K���K���iѢ,��Ãr��q��9������ӣT�R4oޜ5k�0l�0���qtt��^ʔ)������>|8ͺ�"::�V�ZQ�L�\�P�5jŊ�̙3t�ܙ�������>|8���GOO�9s�(��ٳ��+WR�^=6mڤ���&#G�$���_��)S����#bcc9v��=����J�5k�P�ti<HݺuY�r%���$&&����]��_����O�>e�ԩ*�lF�IѢE9~�8���Opp0��֜8q�B�
1f̘l�a�~������ˋׯ_���ȵkװ�����ӱe��$�:A���4h���<{����D�>}ʑ#G����E�<|��6m�hL�hٲ%Æ
�������q��-ƏϪU�R�]���������8p�>}�B||<���|��w�>}��U����1cɬ�|��R�J���G����DPPP&�����>�1�K!�B�.^���J���������ͪ����`Â�~�:����������q�C���iw���^BƇ;d(��=�fE��䐔�+;�eWZ��������^��Ғ���P�~}���X�j]�ve׮]jm5Ŭ8��{e!�B!�B!��GV|�޽{ǚ5k8r�>D__��իӣG���cccY�n^^^<y�ҥKӥK�����ڶ���혘�m�Ʒ�~��2�W_}���۶m���W�B�}�Z���'O���S�/N�f�=z45j�P���c�I�Z�իWY�z5~~~���`ddD׮]3f�r[x�.p��IJ�,ɪU����ibjj�ĉ�:u*۷og��j1899���˳g�(U�-Z�`���*�v���[�n����'��|��=Zmu6�۷o�v�ZΜ9�Ç)P��*U�C����k���Ɩ��ܿ�w�y�f
(��
�V�Z��[�.k׮����͍����p�4I�<��]F�9���ϊ8R�+�������8s�AAA<x�=zh�[��۷���r��BCC����hѢ4hЀaÆѴi�L����4,,��˗���Ktt4����;����k��W�^�8qwww���R�E1!A�rzN^kz���ӧy��9+Vd��j��?���2�~Gf��S�N1r�H���i֬���O��DhW�
pss�w��=zT��j�*劣3f� 00P9�ZŤV�ZŐ!C�;w.s��U�׬Y3&O��r�J�*ʉꡡ��NJ����?���?�T9^�bE\]]������OOO������J�ʕS�?�~��w<==�~�:���j�*T௿��(�e���~&M�����ٰa6l�؇��.������'��j�S�N���Ä��aaa�R�H�Ӥq�Ɯ8q屔����>|��D����
OOO
(�k�dVn>�Y5q�D�
���NNN*eӦMc۶m���r��er|��B!��T�/_sssΜ9õk�8u��[�V�����x�˚b6�n����&R266&<<�˗/��w��5������Ȉ;w�w�^���Ҍ�W�^8p����caa��s��7o�i�&�;��|���@ժU��;����s��mT�(�++

�����ʊ��`�=�ƍY�x��R�JITT�J�Ri��#�B!�B!DZd��/Њ+X�v-w��%!!���X�^�ʬY�TV���gĈlܸ�����Çqqqa�رi�<p��abccU>\Vh޼9���9r$ǯO!D�]�p��]��m�6>|HBBO�<aϞ=XYYq�ĉL�3�D;z����y�����ܻw�իWӧObcc�uw��
���-ŋO��^�z�}�ve;��Ǐceeſ��ˣG�HLL�ѣGxxxн{wΜ9��9�۷/~~~�}����h�=J�>}�_6*bee�֭[��ocbb

���{��<}�4�bK)����ݝw��ѯ_�t�-j׮���
�޽���9wV�9�r������W)|��5666̞=�.���K���x��%'N����رc�;+�q��iz��}�x��9���3|�p��
:t�X�b���q��=�u�ݻǹs�(^�8:t��k��ĉ����	IIIܹs��3g��쬱�Lj+;��I�

�͛7,X0S�
��ڵ+888`ll���>Ŋ�cǎ9r��#G��O-�--�<y�.]�P�xq�U�3g����j���}"�իWY�f
�;w���}}}
(���)Ç���_-�B�{��\�|;;;��������Ȉ���q�OVr��Y~��wj׮M����ӣF�������M����2{�X�d	!!!L�<333

�;P5mڔ�S��ҥK5&[��Μ9���%J������M��o�>��j��ׯ�s��.\===*V��V��Ɔ'N`ff���ժU��~��ի|��7�KV��3�UC�e�ƍ4hЀ���chhH�طo3f�`ڴij��>�x	!�B|*z��ERR������ӻwo��Ξ=K||<!!!L�:Uy<:::C�(vʛ3g�/_&11����4w�M�OŮw��U��m�GGGBBBHJJ�ٳg���ߘ��1b�e���ӭ[7bcc2dnnn��"##ٲeC��͛7t��Y-�`���\�v���D����;�u��IYGS�)�i�F9>���$&&�L�O���=z��̌�;w���	������5k��Ν;j�PS�B!�B!�"5�p����`���={�S�N)W)ݾ}��ޖ-[�nݺ���q��9���iР�ϟgϞ=�m�����k��23yT!D�x��%�G����888p��1���ٹs'}��!!!��c���c�v�n�R{M�0AY��*�����ё��$lmm9y�$7n�`۶mT�\���`V�^����ݢ�R1=����|����~��g����С�"$$�C�ѡCbcc�駟x���sN�4�֭[���εk�pss�R�J$$$�b�
���f������ۗcǎq��
���pss�F�ܿ�e˖�Xl���T�,͈�ݻ��ώ�ĝ�qV<�
>����g&��jZ)�C���abb���;AAA\�~�]�vѰaC���Y�jU����xDGG3v�Xe�Ç�޽{i֬�r�hJ|��w$''�c��uv��Arr2ݻwG__?G�U��ϟ+��[�nxyy)��e˖�\�Rc��ƕ޳������<x�+W�������cjjʺu�{�.���|��#G�бcG��/^� 999�WJ8p�/^��[�_��ԩSS���w:t(�������nܸ�����I��]�6�7oV&�?x�7j|?	�{z�ŊcΜ9KBB���,\��2e�|��2s�R�Q�s���…DEE���ȋ/���c�̙Ze�Q�Fxzz�s޾}���ݺuK3�*U�p��A^�zEBBB��p����…$$$p��-,X@�ҥs-�����3��2E�G\\QQQxyy)ǫ��$''����&��N!��seaa�����ؘ&M���+����7o���7o�T����d�;;;j֬Idd$Æ
��ܜ�R�V-���S�������38{{{�T�B`` vvv4mڔN�:)w�7n�J_���t�ЁW�^�x�b�u놹�9�}�K�.��״m�6��gJ�,���=���:���Hj׮M�>}�u4ř���T�888`nn���<�R�J888dd���	0o�<Z�jE�f͔�s4j�HY�E�����Dz��!�B!�B!�,�p�����T^��
*���+���x�޽{s��Ee���~Μ9������K�j՘>}:H��7n��
��B��c�֭<{��Q�F���H�ʕɟ??
6dΜ9���Ö-[�<���?K�,ޯ�kee�,sss#>>�nݺ1s�L*V�����~�-��7���<�O4̪M�6���9NNN���������	NNN�����͛5�oҤ	NNN4nܘ�ҴiSe��˗U�*���4i�+WFOO�
дiS�D{oo���CY�������dbDQ~i�i����Jܙ����g&������R���`ѢE4nܘ
```@�
X�h���Y��۷����5k���5j�@__�ڵk�aÆ4W�ի�v�R�Y-))��;w����k�d�֭���ЦM�-[F�jՔ������t\�}.nj���)E��\�r�!�B!�"�p0Mttt���Y[[+wcP��߰���`��P�N�Ν˰a��E��b``��5k�ݻ�r��;j\� �}N�0�
*���K||<E����[[[��������А6m�h�����y��x�b,,,(^�8:::�(Q�V�Z�x�b���T��/^L˖-��ӣlٲ��� IDAT0ggg�u4řRѢEY�~=?��e˖EWW��e�ү_?6l؀��a��C�����ԪU�^�:���*�+v�ԉB�
���v�)��x!�B!�B�e��v"��;�?��???���prr��[[[
(������	�
K���ϟ�?HMIqLQG!D�q��q�J�����|||?~��:111�;���$Z�j�o���R������N��7�|���@\\��8}�4ÇGGG5�TGG��Ç���lj'4^���W��^�R9ndd��۷qpp���4i�D9A���D�ۇ�r�bccͿ��R�H޼y��v�d%�̎sf��3�Y�/�S�"[�ԩS��U�X�߿��de<�=�j]]]F���P�R����Q�aaa���кuke����=���T�j~N^�&�gt��je����1��Ç���t\�}.S��)�B!�B|Ά
��gE�eΜ9��SH�ԡ)ɣp��L�<Y��|ju3ڧ��%���ju

?~|��~�U�V�j�*��+�ҥKӬ�)NM�S�X1&N��ĉ�<_j	4��[YY���B�…���eݺuDDDP�B"""`�����Y!�B!�B|$�"���@P��EZ+��4KKK���9q����\�r�U�V�e�F��\%8999��7QP�RPʉ`K���B�S$ԙ���Y��۩�9::r��}*W��ҥK���U)W���_g(�"E���ׯ3��2^ń���ׯ�[J�vlR|�r��Q�F1q�D�����'4oޜ���Ӯ];�s,�e�*T���bbb(^�x�}(�~�@%a3��wf�9�r��,E��"�%#�ݻ�͛7�r�
W�\!88H�o>����͛7�lӨQ�4����f������$\���+�5��j�xF�֭���A��#'���s�HJB!�y���!DnkѢ�&M�vBd��ٿ?���ʄWWW���4.$�B!�B!DJ�p�244T���ѣGٸq#�/V&\q����ݛ��Y�J�"22���(J�*�R��#�"o�����۾};���p�¬Y��bŊ��Q쨐���*W��իW�u�V�&5$%%�$z(�RK�Ho�ŎѫW/�-ʊ+

��Ç�ڵ�]�vQ�R%6mڄ��q����ܿ�U�ȍ7hڴi��ܸq@yّ��3;Ι���Lfݻw�r�ʥ[w������_�6Y���Pܯ�C

��gϞ,Z�ooo�?Nɒ%y��9G�EWW��={��ϩk�Dq���X^�D�T��d\�}.,���B!D�8�<{��k׮�E�9p�@��"/)X� ӧO�_~Q�H�g��-[�#�!�B!�B�ϟ$\|�z��ADD�'O�k׮���('}�z۶mٰa���L�8^�|ɖ-[ؼy3fff8;;�w�HNN��ݻT�T	��5kɝ;w�++�֬Y37.Y!D&,X�W�^���$��˜9s&���c���ԨQ#�>^�~Mlll�����o�z�*>>>J����ٳ'�۷g����I���ѩ����-'XZZbiiɃ���ŋ\�x������w�2s�L֬Y��e�lْ��@<������R�������۷os,n��8gVn?3�q��9���fϞ=�7��իӥK*V�H�%�Q��۷�p�Y�����Ĥ�g�r�hѢ�N���Ã!C����Abb"m۶�L�2�Z5)\�p�;�(�R����s)���dg� !�ceeŒ%K�����'_��K�ƍ5j.`�����*�B!�B!�����o�̛7�V�ZѬY3�	����T�R���@���hڴ)�:ub���(P@9q������5ݻw�o7
p��5��,,,>�
!�Ȏʕ+p���L�{��-���o޼a�رt��!�>n޼��s��w��������ȑ#�z�Je��"!000Pc����z9�|����ݛy������?������G�-+��~@WW��۷k�'����oߞ�ӧ��w۶mP��W��y�'����޽�cq(#�Y�zfғ���֭[ҝ��r�Jf͚ő#G7n666t��Ae��w�ޥ�oV������W�jl�ڹ>Իwo<<<عs'�rW6���VM	d��LI��JJ9W^}.�B!�B�yP,h򹱵�eѢE,Z��~��i;!�B!�B�	�%j�LXZ[[�������rҤ��1�d�"E�����ڵk9~�8�?�p��4jԈ#F��Z>a�V�\Idd$���t�ԉ�K����ÀTb���H�"t��1�X!Df�nݚ�� V�\I˖-���U)߿??��3�[����Ey|�ܹ���ЩS'F��f������N�ƍU�n޼I�.]�P��N�ޯ�߲eKN�>�O?��ʕ+S]�=22�����<ުU+�]���իiٲ�2)�OtVL�W$fG�V�����СC�����iZ9-'c��366f�С8;;����ի�S���͍7���f��͸��ѯ_?�������E�4i�D�CCC^�|I`` ���*e;v�ȱ�3;��]�޽{�2Κ��3��/&44�ʕ+Ӯ]�4�*v�ٳ�Zه�~���T&�k��񰴴��ŋ�[���-[�$A%''�v��4��С���ܸqOOOBCC)^��ZRWN^�&;v���ggg,,,ԞQ���ոR{V��s)�B!>��7~�`�y�����wDB!�B!�B!ޓ.�PVVVlٲ___|}}پ};cƌ�hѢ*�

?~<{���ܹs;v���$[���t����;w�ÇP�palmm	 ""BY7""������4�M!��eggGѢE�t����\�r��o���燣�#���+���L�0A���ۛ͛7S�V-.\�2�Z��v���…y��)o޼��ٳ���π��gϦD��<y�.]��y�f�ݻGRRqqqܼy����=z���F���_��g�…���c�ȑ������@XX#G��ܹs,X����g{;>�3�ӧOKRR7o�T�պu�[V����㱴���ÇX[[3y�dΜ9�˗/�W��o߾$%%�e�"##)V�,P�����)S�p��E޾}�ݻw�={6[�lɱ�3;΀�o�Ç���DBBB�c���LZ���x��1G����ggg���7o�ڤ��ʗ/�O�z��)III���2a����/_�GVƣo߾�+WƌCXX������1j�(�����7��t��
��3g�セ��G��Ԯ�lٲ\�p�!C�p��u�u�?��S�;_d5�Ԟռ�\
!�B�������3t�T��
!�B!�B!ėNv���ٿ?���L�8WWW�������rtB!4)W�K�.e�����bmm�VgƌԮ][�����		�o�I�ܷn��J�*̘1���'''���T�5lؐ#F��X�"nnn�9�۷o3}�t�}�����O?1v�X��_}�K�,a̘1x{{���Rn``��%K�P�B��g�ȑ#�&,,L�ʀ�ʕc���%���?x?n+V�`�ʕ899�cǎTw�P���b˖-�7Ne�1c����Ν;���G���ٳqtt̑�3;�u���ܹs�3FyL�\����̇�W��fy�B�X�x���"�6GGG\]]quuU)3f������*R���(\�0˗/��ޞC�q��!�6���gҤI�&���Ջ�[�������Z5)R��V����S�N)w�QX�p�Z"Sv�J�Y��s)�B!�+++�,Y��0��==��P!�B!�B!R#���Q���sZno9_�`A�O��/���\ewϞ=,[��
�j,B!2�M�6�۷�իWs��i�<yB���_�>C��e˖*��޽��>lll�R�
NNN������*U�D�=:t(jmLMM9x� >|����?���.�˗��ܜ���S�fM�}�oߞ�{���䄯�/Ϟ=�T�R�hт#F���UE�a�Ν�^�///�߿OBB+V�cǎ>��%K~��2{�tuu����۷/;v��LJ��Pbbb��ӣt�Ҙ��bnn��ׯqvv���	???v�ܩ<�7�|Î;X�l.\ 66�:u�0f�ڶm�1�"+qge�,X��iӔ;o�)S&ͱ̭g&-���R�jU,,,����t��j۷o_��Ϗ��aaaP�~}
D۶m�R�
&L��͍Ν;�{���G�ƍٷo˗/�̙3<{��jժ1v�Xڴ���;����Kܚ3Q�����rEY�3�ב
82s��+s�fZ�D�,A�$G�{�V�܈{��Td("�?����[�|<|<ι�뾮�}���s]����ϟ�sa�j�ppp�ܹs8::�M�J�kM,����3w�\�m��ݻw)S��l��l�EJ�J�"|.%}=o�(�W���>>>�����������Ybccc3;�WA�,Y�������zU.|||��?�g�ֹs�L�C$1nnnƕ��y�yyy��'�W�_�v-C�IteK\�v
OOOΜ9�?�K�\�|����S�L�;5H����^�����ホ���^�|�drT"�oS�vm����>KD�V�v�x��qG�!C�h�Is�2dٲecժU����8p E�����E�QyYh��Tf%F�WWW�rDDD�S�D	����C^`���DEE�u�VJ�.��ʕ+�T�RG&""""""������y��J�FDDDDDDDDD�š�IU�T�0��#GR�J�g�Ε+WX�r%.��g"�o���ƕ]ED2�V�����?AAA\�v���
*DժUi߾=�����3���@��8��me�+V0u�T>l,kڴ)gΜaݺu899=��'NЪU+���ߓCb�0%�6-���{�o3k�,�*"�/�񨈈�����,�p!"""""�bԨQ���s��I���ϒ%Ç�v�ڙ�ȋ+666�C��,Y�dv"�{�.�}�;w�Lp��͛lذ�
6P�^=���{��ɓ	QJf5jT��v��1e�|}}7n�s���m۶i^�2wo��\]]���0DD$�h<*""""""/��@DDDDD^M������|��ǔ+W�9r�5kV�+F�-���w�ޙ��������;w�Ю];v���믿�_|�ƍ9q����l޼��C��;wnv��A�^������%�iӆ�Y��f�=z�d�G��v�Z�f�J�6m�4�s�ν�;�����������H������kk��CD,���G�2;�WN�b�=ztf�!"""""l���\�r�ڵk��?�/_>��e˖���4jԈ�;r�����ڵk&E,��H�"ԭ[�;v�q�FZ�j�h�
6���ׯO�"E20J��Q�E:Z�z5�W���0DDDDDD�p��-�5k�k��Ɩ-[�z�*mڴ�hѢdvx/�ӧOS�B��o___���@�:u�裏224���v����c�Νܹs��^{���~����S�\����f�U��;Ƃؿ?aaa���ҬY3<<<ȕ+��ޡC�عs'd޼y	�-�rttd���=��+W&H�8w����g�޽ܽ{�B�
��;�пJ�.��u�;w��G�2u�T>L��٩Y�&����J�*	λx�"�-bϞ=ܸq�9r`ooOÆ
�޽��kHnlII��KLJ�?�y���.�…�˗<<<pttL����}��:�ڵcǎ���&�p���@�v�g;^x{{�i�&Μ9CXXy��jժ��Ջڵk'ږ��dx޻w�&44��%KҵkW�w�h[ɉ�y�&~���o߾�?���~��Z|O�MjԨ@PP���979R;�1����
��N�:t�ޝ�ŋ���Yj�{Z��X4��J�H'������������B�?�����J�*eZL/������ܹ3S&�$��Ç�3g+W�$66��;���HժU3<Nyu:t��={���Cc��۷Y�v-7nd޼yԫW/Ym�ȑ�使�?#F� &&�Xv��,X��]�X�r�1�°���+����s�j׮�˗O��}�v<<<���2��������a�~���y��m���_������#����[����˩V����ѣGqww'<<�X͉'8q��V�bժU.\8Mb�/=�_r�?��2e�������׳y�f�Ν�|��8��aÆ�ϟ����s�����Թr�
��^�aÆ���ӹsgN�8aR�޽{�ر��;w��陪�w��A���M���K��0a�IY\�Wj>w���1��9sZܧ����<~���ׯ?s�̡r��iڇd�5EDDDDDDD2�.҉Vy����80��1+�����;w�p}GFF2f�ڷo���-m۶e�����i������{��ѿ����ѣ���+V��'O��營��fӦM-Z�x��	�ϟ������믍�W�\aԨQ������J�޽)V�����?��ɓ,X��!C��[ٻ~��]���M���o߾������aÆ6�ҥKs��E�O�Ζ-[0`7n�H�"	����y����ٳ'NNN=z�#Fp��e�̙��ŋ�u'N�Hxx8�:u�W�^�(Q�'O�p��Ǝ�ٳg�5k�ǏO���J��{��\\�|�
ժUc���899q��e����l��СCٶm�8����t�shccC�-���Ϗ�C�&h��Ϗ��XZ�l���5�f��ĉ�/_�I�&��쌕�'O�d�ĉ>|�y��8�"44���E���<x0vvv�9s��S�2w�\����Ɋ�y�&����/��S�xq��"IZF$t��X&n��=�…̙3���������qH:ʨ4��XJ�H'~~~t��!�#K���amm��a�d�����ADD^ ����?����OOO�ٳg3{��L��A��d�nݺE�N��e�;wf���,Y��~��ebt""�X�|9w�ޥ��&�ӫU�F�j�ȝ;7^^^,[����u�Ç3s�L>��SZ�je<�����Ǐi޼9&L0�׬Y���6mڰz�jc����(W�\��맟~"""�:u�0�|���(_�<��ϧK�.�߿�����uժU�$�ڵk��_���Ɵ�iRא��矓/_>�e�F�ڵ�3gM�6e˖-Ƅ���WZ=��\\,[�̸�I�r�L������H�v�����ͪU�<x�������/���Y��o���$�jժ|��|��8��˗F�z��5k�����	///:v���Ç���q��s��ၣ�#y�䱸_yyeϞ��+2s�L�u�FHH�֭Ӣq��5EDDDDDDD2�.ґ��7������X���-�C���DDD�%��3o�<����Ç)]�4]�v�Y�f&�������d۶mܽ{�…�ЫW/��]�d�+V0c��=J���iذ!�6����S<==ٴi7n���Z�nM�6mLڊ�:((���ӓaÆ����?�`R'.s�ϻ��cŊԬY�d5�bŊQ�F
V�XA�.]ț7o����H<۷o�K�.f�w��///v�ڕ���0LLL��}����={������7�|3�J�QQQ�ʕ+y��ݻ�ݻ�Ʉ{+++z�����ٱc���2w?*W��ÇM�mmm�x�"=z�K�.ԪU˸bx���\_jc�+-��9ɹ��<<<��q�i����pQ�Jʕ+�ٳgٵk���خ]����qtt��7� 000ѶJ�,	��3��g��'�$8�5kV���C�޽K�R���U���}�,._�L�v�����?��֭[s��u������c�֭���LTT��^�z���/��̍�޽�ܹsٹs'���|��9����3��@DD�/f���ܾ}�…��ҳgOlll,�O���t�ޝ�#Gh�pai����Ô)Sؼy3666Ɲ�.l�gr�}޸0��==��dLl��bi,��}�5EDDDDDDD2�.DDD��Z�je�R�������4BBBpuu�T��J�� IDATR�Z���Ǐӽ{w���I�8BCC�֭w��1��={��c�C˖-�g��>��Ο?o�w��M|||8x� ^^^	&2��ݛ����&��Z���O�2j�(�̙�O?�d�ͱc�8v����%OϘ1���0��(iy��lܸ���\\\sqq��lڴɸ2���HJ�={�:u�$Y��ŋ�5jW�^�T�R|��wd͚��K�x�7,�)O�<<x����O�4�kH��J�*&��W�T�e��C�>}jRޯ_?���Ç�;������B�
��Lv�Mmlq���3'9�W�ڵ͖�5~�Izi۶-ӦM����$�����xܜ+W�‘#G8r�'O� 666ű�Q�J���Z��s�H��R��3$�J���Q����ѣ&���ѣ\�v�ڵkcgg���Y�x��7o�dŊ<x��󄅅ѣG�]�f,۰a���	ꦦ�ǏӧO�g�ƍxyyq��q�̙� �&)���3gR��ԩSY�n�l��_�Ųeˌ;�����s�ӣ���
���c_�5EDDDDDDD2�.DDD�����X�tif�!""/�ٳggv���ǁ�M�>�-]��;w�����ĉ)\�03g���_����8�䧟~��(Q�	&��op��Iƌ�ٳg����ׯ�IۥJ�bܸq����,^�///�o�n��bX�v���ԨQ���h�2e
+W�����d7���V�-[//�d�k�u'ַa%psS
e{���$I��v+���ʕ+Y�~=�s���ӓ���'�X�cE�R�8v��Ν�h2:@LL�I��amb	���"##�Ϟ=�E��k׎�y�2g�N�8<��j�*V�Z���=?��vvvi[\�}~�I��U�@��k5|�[�6m���oٲe���,X���P�n�J֬YMV{X�~=�|�
W�\I�X�;w��f�'v��:��~���*i׮�b���&	�o���˗0b�Z�lI�,Y8v��{�f׮]����?s��5���8q"���;v��c�&�kI���'�-[�ɓ'�T�#G����K�.1y�d<�ڵk|$�`��ܻw/U}�޽�Y�fQ�fMN�:��ѣ�~�:˖-3��R���ƅɹ��ѿ�c���b��4���/}"/�5j�lG�Һ���:��C�W�����׍t1���!�������{�n>��3���ɕ+�F�"((�_��Xo���U�+W����5U�Ta�ȑl۶-A�Ç��ޞ�ٳ'�<x�x�0����___���ڷoOPPk׮�(~ww�d'[$��9}�4`~u�ҥK��I
�$���s��%�/��gϞe„	dɒ�3fP�\�$��t�}͚5,��|���W��СC�e���aaaf�1���V��7n�ڵkٵkS�N�C��)S�˗/3a„t�-5�/=$��
ה�ds;5<z�(�q������;<y��8	��ߟ'O���{�Q�Hcݵk�2p�@�\����L�2��u���`���=K�2�k�eQ�^=
,��͛����ɓ'l޼��E���{�ȡC�prr����g�ԩ@��v���ȑ#qvv��ښ�ի��_$���>7o���ɓqtt$k֬�-[�q��${�@�l�[�/%}�1����\��1!�0Li��&羧G�)&'KǾk��������d<�p!�u��a�̙�ʕ+����cǎ8::Z�2�����������ըQ#���aH��M�ƴiӌ�'L�`��gng��r��u*T��d�k׮P�J��jժ�������u�|�x��l��|��W�߿����3�|z�聫�+9r�(~ä����	

�OJ4�ꈈ��F�R�8q���'����=z�A�ɐ!Chذa�}�<y����z��ݢE����G���`�i�&>|H�,Y�e���?~��G�'L��_륥�ŋӾ}{�۶m��O?e����[J�_z9~�8o��v��Ç	WT�����ӧDFF&����˩��}�����OϞ=��_��>w�\&N�H�ΝM�ݺu���ӧXY%�r��q��a���/�ի��aW���:���xQ�[0,((�lٲѺuk�,Y®]���ػw/��ߧW�^Ɲs�ܹÐ!C8u�T�v�%%��ի&�i���<q��O��O�V��?{��E�ƍLwdIIu��1yo�[�ᾤ����s�ӣ���
���c_�5EDDDDDDD2�v��$EFF2f�ڷo���-ŋ�m۶�=ڢ��EDDDDD��w�cJĝ����u��4nܘ����c�R�J����7o͚5cժU����q'9=~�8���\��\s��e���"""�q��ܹs�+�ǵ~�z�ѣ�I��_Mpp0M�4���I�a�`kn�㐐L&�W�R�w�}�۷o3`��$�|��M.\���={�4��[�`A��%�>}�…x�w����fw��^���i[J�_zY�hQ����,X@ӦMM�&&=z4�y~~~��c�9(��6lH�|�8}�4k֬�̙3���k	��.]�@�6m����e|�h_IiԨ?���gdx��4���MF~M�l��`ee�o��<�5������O�6�S�Nagg���;_~�e�vt7�!�'L��9"-�|^BFrv����?�X�b������b�qOJ�}޸09�==�O��-9�X:��XSDDDDDDD$�)�"�ըQ��</�%K�p��-:u�d,�ܹ3�n�bɒ%�������ȫ/((OOO*U�DPP�q���իd���^�u��/^��������)�?_�|�jՊŋ��O?ѭ[7<x��3RԞa�Ixx���ܵYz��*T����'8f(3�I
www�����A���9r��=b����5�����d͚�aÆ�ٲe?��3+Vd���ϝ���憍�
���ӧO�Ν;DFF�o�>$�u`ҤI(P��;w�����?s��bbb���"$$��Һuk������o�{����s�f�����ۗ�g��ٳg�۷/ gΜt��%��e˖xxx�{�n"""���!$$ĸ\��'�2��<��c�ȹs爎�&88��={���:t0�o���ȑ#	

�ѣG\�|�I�&�lٲD�1솱q�Fbbb���NP'{��4o����[˖-M&F�~��믹s�111�9s�aÆ�$Cܻw/��x���-ʡC��ٳ'�N�"::�s��1`��?��6���MF~M���}⏁�/N�:uسgǏ'00�����E��v����b��Ư{�'O�X������Ǐ'���>
c�u�֙���Z/@tt4>>>&�������U��oʔ)�.�$羧G�)&7Kƾk��������d<%\��n�J�>}�W�u�ԡE�L�>����zw��e���4h�F���Nr놅��b�
j֬i�K�bŊQ�F
V�XAXXX�^���p���e}�����>�����4	���2w]�n���ˋA����F�n�>|8~~~fW\K�KbHO6l`ڴiL�6�
6dX�""�:��J�*�}���N�>��7oŴiӨQ�������w&O��ѣGy��	G��믿�nݺ��u��ԨQ�_~����ʗ/���#`~�˗/?��
�z�j"##9�<S�LI�u��B�
��V6��Pf�#""����:�}�9r�`�޽�m�'''���X�b���|��899�1$p��o���`��A�ҥ?~<Y�da���Ԯ]�J�*���Ι3g�V�}��1��dɒ���P�ti�\�¸q�W����8;;��2e������M�/V�3g���Ɔ-[�ФI*V�H�&Mزe666̜9�%J����ۗr��q��Y�u�ƛo����#~�!�������1"]bK��KO�g�f���4nܘ�+Ҽys)R�, {��&�=<<Ȟ=;�.]�cǎ899Q�~}���;vl��~�������d���<�����z�����7�k���ё�M��믿���A�ҥ�pX"O�<̛7�|��H�-�X�"�7&  �ѣG�=/�q%vo2�k�eԮ];bbb�޽;�?�}��f��۷�Ǐl��<x`Q?�]^&O�̟�ɓ'O8q��&MJ��in<Q�~}F�Epp0111ܽ{���5j$�?לG�q��q̙3g(Q�M�4IU�&M���<y�Ç3y�d�T��<ɹ��ѿ�c���b��WcM���p�Uya̟?�ŋ��ݼy�+V��Ə<K��ѣ׮]3�۰a��J�ɩ�q�F"""pqqIp��Ņ��i�&��I�iӦ����E�?~�ŋ�3g�r�zaw�J�.^�ȗ_~Idd��,::��/r��Ev���	(X�`��d�S�N���÷�~Kll,Æ
�t�҉N�˽	�1�7o��ѣ�h���ا�~j|ݭ[7�m���˗�ѣ�I={{�e��֭�'Ofʔ)	�"�W�n|]�@BCCi۶-����[�.�6�ի���?�}��}��ٱ���m��w�y��;wr��q�8��0%	("""�ԫW��~���{�nn߾MΜ9�R�
�~�)��I}K��С�K�f���>|���H���iݺ5�~�)666	�qtt����ߟ�7Lhh(Y�f5�HߥK�D'�6hЀu��1�|����ݻw)T���}��\�rɾs����/��‚ؼy3W�^%::��%KҨQ#z��m��Gl�}~�Y�f�-[�#Fp��I�/NӦM�ݻ�1i5�7�|???f͚šC��������ׯϨQ��3m�4ƌc��H�"f�U�V
Ν;���#o��f�:�:u"{��xyyq��Ylll�R�
�1��קt��6���V��ׯg�ܹl۶��w�R�L<<<hٲ��HRWR�&��&^Fu�֥hѢܺu;;;jժer�^�z0v�X��@���f�񹻻�u�VN�>mL��g	�'�[ڧ��D���ٱcG������9rw߉/�ߍ�˗��S��L�OI�{��&eNNNt��1U�>Or�{z�o��0���b��WcM���������1b-[�$K�,;v�޽{�k�.c����k׮agg�ĉqtt�رcfy���{��0���P�g�%\��H�


J�x�D�������?�ڵk_؄�Į��$22�ʕ+���O�<���\�p<<<�lǜ�Jʈ��b���4n��8	�aÆ̚5�3f�#G��CD�U?��ĉ&�3B�B�X�d	s��a߾}DEEQ�\9�w�N�
�����˒%KX�`;v�0NkР�~�)���Kv�m۶%[�l���r��y���[�.ݺu3�6ls����͛<~�8�6�����7o&22�5j0f�>���]����4i�w�}Ǯ]��ڵ�I��v�"O�<4j�(�CDD$1eʔ1�c�9�NQ5k֤f͚�:��ƆN�:ѩS��Y�\9���[��;w.E����˰a��N�ψؒ�j+��WŊY�z�ű8;;�`��d�W�dI�,YbQ��6mzn����?��2�ر����ŋ'��Ab�$��ݛ���xUXYYѦM<==i۶�q���>��'O��k�.bbb(_�<���\�pOOOV�\iQ…��
���̞=��[���ϨQ�ظqc��47�ȓ'^^^,Z���۷s��-r��M���-N������֖��~�.]��믛OI3f���/�d���,X��M�ҳgO�����=5�==��tl_rb�t쫱��������H�S�EKlh�� ����ԩS����9s�C����Cc�;v0r�H����g+�|��4Ȥ���=}�4�J�J�a�kCy5}��G@�M�O����ӽ{w��z����0h� ���@֬Yy�7<x0�
��?����k��Մ��ҬY3cY�f�`���)�T#""���߲eK��Q�xq&O���z���g���><�z�%�+oժ�Z�J��ƍӸqc��ș3'#F�`Ĉϭo�u��;w�ܸ���x�b�]�F�%�v����{�&W�\I�+"""""��ի���q�͛7џ��L`n��;wn����in<�v�:t(C�5����Dr��g�=�.�i�nrƅ����ߒ�ajb�ƾk��������d<%\���ܹÐ!C8u�T�c�����W�^�r��&u�U�����


0N���Pf�#""�N��������DEEaggG�֭�t���ŪU�طo���(P��u�Ү];�V�����-I����H�r���<}�???�����۷ɖ-���ԯ_�d����J*ޤ�+��ܽ{���'��\[[[��k��zܸqL�>�R�J��_&���~���,]�����������݉��gN@@�*U�`����.���3�lْܹs'�/"""��nݺ�~�z����	(����������щ�������HcM�����e���V<�6m�N���Ύ�����M&[��/�&ad˖��&��aҪ��U�c�2s[ED��!22��c����.\�`v����h���+Ν;g,�}�6����9s�Q�F��~�<���ܿ��������ڵk���<yBHH!!!DFFҢE�d�g�v�����ɸq�hРիW�|��f�7?�ҥK	�P�BI�7n�q��G��y�fbcc�+�%���ٳ���(�V���XժU9v�{���6�"" �S+�+�ʳ�4ƍǠA��ҥk׮e֬Y&��"""""�G�e���|��י���IcM�����������@��?�x�ɓ'd˖
;;;Ο?ϟ��������������
��͛ܿ?�����눈ȿ�o�����MѢE8p e˖%$$�Y�f%�iݺu�;w�����駟boo�������رcl߾�
��֐���
����СC��زe#G��R�J<y�@-ZĆ
R�p��u5lؐ\�r�|�r֬YÚ5k����B�
ԪU�
w�x����c�ĉ&;w�S�xq���O�B����ߟ.��l>@ٲe�cH�9|��.DD�_뭷ޢ_�~L�>����S�z�L�JDDDD$�\�p�/_Ή'hܸq&G%�r�XSDDDDDDD$�(��%�o�>6l���?~�����,X��M�2o�<&O����\�2�O�fҤI	�JN�
*p��M.]�� ��ҥK�:""��H,�!~���/�W�^8::���D�>}�<y�I�}��0h� �-
@ɒ%�߿?`׮]�ć䲲��B�
|��G8;;���9r����z�*�jբq����_\\\8�<G���ɓs��q6n�Ș1c(X��s�iѢ�s�->��lmm���n<��g{���YG|�2CI_ډ����ꊫ�kf�!"""���������7o�������9p�E��C�,X���s�j���ƛ/&�5EDDDDDDD2�.^`���#  ��c�2v��ǃ��qqq��ݝ�[�r��i���M�41&F$��;��Ν;9~�x�Q;bԭ[7��)""/��ׯ��o���p��
<<<̶u��e��5�����CƏύ7�[�n�d��۵kW�͛Ǒ#G8r�+W��?��͛7'{��Ǘe˖�lٲ�iӆ��hV�^���K�,���s�/Q��E����_�Ν��O�˒�l
�^ډ�Pf�#""""""""��������ϊ+غu+�s�M�6|��4lؐlٞ�Yr޼y�������������2;�����DW����hܸ19s����ggg���kc��ʕ+�����ӓ���S�@lllhԨ�F�J�fr�6i҄\�r�k׮�v��E�<yhԨQj._DD^0���&��Wk����t�����X���C߾}���f�…�]Rگ��?��}���B�
<z�+Vзo_6oޜd����Ɏ�%y|��G���&8fmmM�֭8r�E�Y��`��6�^�<[C��U�+
eZ�PDDDDDDD��ɪU�h׮���:}��%w��,_���7o��Tm IDATt�R�6mj�(���~��˛7/�'O6{,���l�#F0b��rs���͝;7���,^��k׮W;v����{�&W�\ɾ.y5+V�+W�p��i�|�Mc��ӧ�-R�ׯ_g�ܹ)R$�b(S��Z�b���xzz���D�<yR�o�<y�_�>����ܹs�߿�5kְt�Rc�a�,Y���%22�}09;t�U�lYN�<ɦM��ԩS�㆝&�%3���<��^{�;w��k��fr,,,�XGDDDDDDDD^|��̚5�X6}�tz��I���312����IR�n�X�~=���>ooolmmqww���DD$3����r�J.\Ȁ([�,�Νc�…	�֪U�իW����'�P�T)<x�o���ڵkqvv��/����p��
lmm�G۶mٻw/�n���Ϗ�?�8E�zxxp��-z���{�G�R��y�&`�#D�|���>[�n�Q�Fܹs�E�=7Ns�լY3N�<ɯ��JDD
6��֖��hN�<ɏ?�h����Ik�y��K��Ν;\�~=Ab�!a�t�����ȫ꣏>��DDD��v�Z�<y��a��+&  �V�Z%�\�r1m�4jժ���'�b�ȑ�ܹ�Ν;ӪU+r�Ν�|||R������������HZR…$)gΜ�7�A�ѥK���f͚E�929:�L͛7g���\�v�Q�F%Y�M�6:t���>��s�cٳg�[�n����A�Q�H�Ν�d�9r�_�~|��Wlܸ�F�Q�d�d�ۦM<==Y�hQ�
'''��5k�e�~��g~��g�V��d��]W�Z�hժk׮eÆ
lذ!�yŋ7IrL�I��<��ի�ٳgM��ٳgx뭷�<F�W���=:t��0D�_�C����gv"b��U�*�BD�E�f�,��V|ٳg���
777���X�z5˗/�[�ndϞ�V�Zѹsg�4i������֮][�""�8�GEDDDDD�e��y���z�~��1}�t���O���39*�����ˑ#�ƍ��LJ�� """����E�̙3�䏨�r�b„	�Z���r��]r���o�AǎM~�������Ý;w,�ê��M�4aÆ
,]�Ԙ$��~6lH֬YٰaW�^�X�b���[�n��X�k׮XYY�w�^=z���3}��O�>IƘ�u�����o�i�&Ν;ǽ{�Ț5+%J��N�:4k��$�1%�'���l�y�~��'���+!����ʕ�t�SD�U������fv"""��֭���""/��y�ҥK�t���۷���c���jՊ
СC:w�Lݺu����8p`D-"""""""""�|J���������a���&�����פ���(P��<O�<Mqqq1;A?���=zУG��P�~}�ׯ�d�9rгgOz��d|��'v]U�T�J�*ύ/�v�7ϋ)�rK�mΜ9i޼9���ܺu��E�p��-����裏�+����|||pss��0D�_���[��yI2��k�fv"�jժ3g�L���)B�~��ׯ�/_f�ʕx{{�`�J�,�իWi޼y�绹����&���ȋK�QyY(�BDDDR�k׮DEEѳgO\\\ȕ+ׯ_g���T�X1�#��J�mݺ5������oƤ��~��"E�ТE��_D�e��$C����Gev"�LٲeK�	�"��0`�g�N�~�����ߟ,Y�����������8y�$˗/g�ĉ�ʕ+�󬭭�NU��]�p�2eʤi�""�2���������D	"""�"��6mbѢE,Z���X�|����Xr�m�9�߿?_�5-[�`���|��dϞ=��yUt��!�C�T�f�h֬Yf�!"Đp��_��7oN�
����0a&L�ƍI��СC���ڴiÚ5kR�@""""""""""�>J���ѣ����ڵ�k׮M�B��R�
�۷�`�����PJ�����:ubɒ%t��''��]DDDDDDD�q�ܹ�!����fhk֬��DDDDDDDDD�ա��t��憛�[f�!"ruu��D^*VVV4oޜ�͛gv(��R�l�y��8}�4*T0{��ח���P�N�%""�1|_���5�>9�&�ŋ)]�t�ϋ/((�m۶q��>|H�ܹqtt�aÆT�^=��Ǐ35ל�6l�ѣG�\�2M�6��D2W�5�g�G�{��s�#�q�%}�eccC�…�S�ݻw�x��)n�E�����4�y9(�"��h4�糷���DDDDD�U����s�N�c>̜9sX�r%���t��GGG�V��	����ȋ`ڴi���?fΜ9�	�< ((��� \\\�߿?��֙gF8u�>>>|�����2l�0J�.MŊ3;4���v�0�?}�4�&MbժUd˖�.]�0d��ݻ�رcٶm���4hЀq�Ƒ'O��O�8�رc	��Ɔ�y�Z�S�Ç�8q"���\�v
[[[���3f9r�0�˒%���m�С,]��lٲ�����{�.���gݺu���P�@�	O�<aĈ�u��Q��޽{ə3':t`����Ν�X'n���X�>}ʸq�X�r%/^��Ɔ��X
.����zI��R����\�~6l��9s�\�r��!)�1����������C	"""""""�)v��i�<22�1c�о}{lmmh۶-�G���Ϗ�9sfd�"""b��H.H��Ȟ���߿�\�rѮ];j׮M�…	�ȑ#����w�^����EK����b���4nܘ"E�аaCf͚Ō3L&�ˋ��/�dŊ�s���ޞe˖w,�����_��ʊiӦ��?n�8V�Ze�w��}BCC��>���7�gTT���7�|_�t�ɓ's��A6n܈����9xzz�O�0��e�2o�<:@DD���3I����a˖-���Z�W����{����~�������1b�|���Ǐgƌ:4CvMHl\�q�}��.\0&�}����k<�ИWDDDDDDD�墄�t�-_E^>���x{{gv"""""I2���2˒%K�u��:u2�u�ܙ�˗�d���뗉щ������~�&�����	$O�<L�0�%J��ϟ���{�*U�0l�0iܸ1����q�Y�z5���4k��X֬Y3X�z���a��9z�(�ׯ�L�2,\���3g2v�X�x�
6o�L���Y�`�f�b�֭	�߾};K�,����رct�֍��/^�СC����D�ڵ���T�!!!��ݛ-[����EϞ=M�9x� G���ёo����c�ү_?�T�Bpp0���L�:�����k׮�&444Y}U�P����%K2i�$&M�į�����'���&;[�16l�@���y��1���\�|�ٳg'z/^ٳg�bŊ̜9�nݺºu��7��Ƽ""""""""/%\�#ooo\]]3;����[f� �)2;yIܹs�Y�f�{�n"##qpp�k׮�90M1L�ڼy3�oߦp��|�������#q_Ɗ+�Y�&E�5�)V�5j�`Ŋt�҅�y�f�e����nܸ��)V���}��ܾ}���bŊ��~6n�ȅx��
�f͚t��9ѝ�%zܻw��˗s��!=zD�ڵ�ի����g�	���bժU�۷���P
(@ݺui׮�����m�@�V�L�-�ʟ??-[�dٲelٲŘpa�sٲe,Z��}��ammM���qss�@�&���i������ǁ�w�
�v��t�Ё\�r%hg���,]�������y���ҥ��<}�???�����۷ɖ-���ԯ_�
��@�J�(X����p��8;;@˖-ɝ;��{$�﫯��bŊ|���̜9���(&N�Hٲe���O�5k���Kp����y��^�:U�Ta߾}lܸ1�$�gw���)S'''~��Gʕ+Dze�$A̝;�ʕ+0x�`ƎKdd$,�B�
|��g|��W<z��xޥK�,������sfϞM���2d�&M��ݻԬYc�>}�LTT���o���'NЦM�)B�"E��s	�w��e�ܹ�ܹ���H>���(��[����g�p��ԫW�~���+W�D�E`ٸ����t�ޝ�#Gh�}b۳gS�La���������2p�@
.l�gr�]�b3f���ѣdϞ��
2x�`���s�ӣ�����y��g�>|H�ҥ�ڵ+͚5#,,�-ZP�@���Mv`�|�2m۶�D��Y�Fc^���.DDD��jԨ��ٳ3;yI���ӳgO�^�j,6;�������Ӈ�'O�nܸ���ǏgΜ9&�O�۸q#���$8�����ٴi�ڵK�U����{����������			1ٵ!$$�[�nQ�re�+Ɗ+L&'ó�������p<<<,�3<<�ѣGs��-c�!q3����W_}Źs�e�o���ߟ3g�0j�(���O�L?ͩ^�:˖-�ԩS	�-^��;v���#	fʔ)�ɓ'�v㊈�`̘1&?_ݹs����s��1&N�� �eܸq<|����͛���5&�����v�Zc�'O�BHH����h�x6a:**��U�&��jժ;v��{�ҨQ#��G2�����u��C�`��_ݺuM�o��9s���߱c��U�V�:��qggg�ks�=aaa�eooo,��s��zbcc�U�vvv�cq'lmm�t�[�ne�֭�3�
�L�7[�=Lv�ذa���	�Ο?�ŋ��ݼy�+V��Ə�h?�W�g�z7<ǔ�1u�T֭[<Kv௿�bٲe�˗/���ݛ����]�jO�>eԨQ@��{z�J�nݸs��g�2v�Xbbbhٲ%;v��ˋ-[�иqcc���@c��Ƽ""""""""/%\����/^��ŋgv"""����ի/^��'��op�ر�(�٪�'O��R�J�9.]���ɓ9x� k׮�M�6�]-vϞ=���	�0��ٳG�ODDD��Q�F?~��;w�$\&�&�гgO�իG�,Y8s��ƍ�?�����c���k�����$�C4$�pic�h�Cъ�+f%ƪ�h�K��-�m�VQ�%B���jQ�HL�!R��RC�544"���w�7'�$�	���#�欽�^�}N{�u��Ϛ5k�p�eʔ��wߥ|��=z�3fX��͘�U�X�f
'N��^୷���ˋs����ٲe�Q���/��N�Y�.]���6��{�2z�h�W�Nbb"ӧO�…�]���]�fgV�W���ٳ������R�BN�8��_~ə3gX�r%]�v5;��Ã�����ʊ+X�b�v�2.~��'#���4�m�Ɯ9s������}��������۷O	�Xv�f���su~v�r:?===�k��g��:@n���܎�a�j׮
@���N�:��5jmڴ�@�<x�~��q��M\]]���!%%���dfϞ��-��oHJJ��ӓ�?�ooo<Hpp�E�ŋ[s��DGGd;/��*�LI(�+���۷og���ԩS�Ç3v�XΝ;�…4h�=_�\�r�?�ҥK3w�\���ٲe����a�?�|.]�DժU���)U��}��}����iӆ�ݻ�d�"""�&\��4�y��~�y��v������?y���{�΃�e��
���?~~~��ۗ��&�'�^+���(�����s��NDDDDD_����w��[�l`̘1ԨQ|||;v�Eߍ70y�d�������B�
�?����1́ʕ+gq�|��f}DDD�t�b��]{ݺu)V�;v� --
�۷oKɒ%��',X�ҥK�X�"���|��7̙3�S�!�v��
@���y���)X� U�V孷޲�{?c�ر��C�R�|y���x��<x0�����zP�`�{Q�{[[�ݯ_?jժE���6�L��[����ۛ�R�R%�ٵk��9o��&���8::��ww7-�������z�*���DEE�%��<y��f�6Sy2��nL._��_5���O�:EFF�ŏ�}�A0U���X7n�֭[f�MUL�V��?��_|�ԩS�����ٙ�۷�{�nʔ)��۷>|���LnF�M�jՌ��|`�w۶m�ٳ�bL��V����Weu��m����^�5j~~~888P�F
#!�4g������E�B��޽;W�^5���y�o߾��#G��兓�cƌ!..���bŊѩS'�=Jll,p�2ǁx�g���4�y���S��'[�n5�)�i���¨Q��:M��㉏�'<<���`�6mj����ڷo3f�`�ҥddd�����m����IN_�����d�������f�#��9s�����:~�x�c�v�.Z���1S��ݦEDD$g���4oޜ��_~��z��o�>�_�N�Ν����?���_�N�Jbb��5��|f���;�Y5
������y��y�b���oWWW.^��ŋqww���
^��3�Y����ʕ+����c�Y���J�*������U�<==�ߟy����@�^��5k�,]�����Ӻuk
*d�3U0]#3S��
��=z4���T�^�}��q�ڴi��9�۷'$$���@���KjԨ��K����O��Oh֬�7o~ �=��s:t�l�ڵk����S�hQ���;;�z�*���4o���; S5�
���A�.]�䤄����/����v�5k�4�r8::Z���ٳԨQì=�\	�ҥK6�Ç[��{�Ϋ��P�D���~��f�M�I���{�n�ϭ]\\�<�c�s�����Y��у�K�2o�<���������4h�HvќWDDDDDDD�񣄋��֭[s<� 1�[Rǘ1c�����͍��~��
R�X1~��wV�X��x����3g���mn��Ս77n�:u2��Сcǎeٲeٖ���WӦM��ol����܃��*��Ӷ�oe]T�@�����n;���iZ��ڸ"""O���oMU.�U�}��Y�j[�n�^�zDGGcgg��/�l�	'11�2e�P�N<==y�����=;�U�0-~��~Ƽ���+dT�R��/�s�Nڷo��9;w�4�g�5~ӂ\k�܋�|�ʼ3��������Q�{��a�����o,Y���k�ҭ[7Z�hav���zz�*U��;��/^�^�ze{ΨQ�X�r%���Ԯ]�옓��~����Z�j�={��X�*6Y��ٱv�Z�7on��A�"EHII��_�D�̟?���xƎ˙3g�E�&/���ز{o�V9gڴi>|OOO^z�%*V�H�j�̪e�~�UY�ݻ��$�{#�}Z{���:88��4����0���{bɒ%�ر#�-"!!���Ըqc�k�=XDDDDDDD����B����ۉ���dɒDDD���f���`Ȑ!8991k�,f͚�W_}e�hs6o�<.\�@׮]��nݺ�x�b�͛ǠA�l���G*T�B�
�CDDDS����8q�P�n]�ݴnf���>}�5k��stv\]]INN�ʕ+����3��]DDDr��͍5j�w�^�;F\\���f�L���㏍șw.�}��դ��ʔ)�ٳg9|��YU�cǎY�1�}�YΝ;�̙3y��gs��E�l۶���ڵk���e��ԩS�^��,���ѣT�V�x|��ʖ-���Y������đ#G�vl7]�n��ggg�5kF�f�8q�;w�dժU̟?�H�(^�8�.]�ڵk/^��k׮}��ƈ#������ը��JVŊ#66��'��wߑ�����M�4a�ĉt+���y��r=V������!!!�m۶Y�����ɓܾ}�B�
ѦM�U�ƿ��o.^�h$(P�bŊ1�|��yzz����޽{���3�,������Í��+����YM���Wev��--Z`V�^ƈ��7�ۄ;������=��M��?��K�.����?NժUs�۳gO�/_�ҥK�����Ύ�
�5�y�<�-�䡹t����4oޜ
УG6l؀�����pg��/�����4h@�6m3�z� IDAT�5k���F���X�F^lڴ��ҴiS�ׯ�?��>�����6Fvdz���ݻ��͛3p�<�7��5k�;tfN����_��ߦG�f�׮]��O?�u��ƽ���Z삓�9~�8�
�Q�F����L�2�7n}����5�,YB�:u��L�2����d��K1���8oʔ)$$$������2e�E�f͚w*9r�۷os��e���|}}��s�];Ϝ9c�U�T	�ӧO[\��f�#"""y���Ozz:cƌ�֭[���[��~nݺ�ɓ'�>}�ў�]�5j�Y�}��!n߾����	����i�����1S2�_|�ɓ'IOO���.�K�.L�0��[�R%�4i�͛7	������ܾ}�K�.�f�>��Cn޼I�F��v�7���9v��o������d^Lk-ά�ԩc<?G����=z�9s�X��C��K�.lذ��7oR�\9ʗ/��oj;w��5Lm�>b['N��ĉ�>���ŋ3g�~��7bcc�Z����:XT
(Q��}��N��֭[\�|���""##�j����	4kstt��X;v�����Ӈ��Tv��i6ֳ�>K���Y�j�O��ȑ#�;�R�JQ�J����q�U�V�lٲ�&���L�<��{����Ư��ʤI���رc���Ƙ&W�^�ϋ�2���_�EBB�ǎ�lٲ�l��Ƙ4i�1'ܷo�'O����M^���1��=��O>!99��7o2m�4|}}-*&=�쳴mۖ���W�����'�yEDDDDDDD?�p���������l'�#G�0z�h�����8�C�m�ϟ'<<���f̘�J�|��W̝;׬-99�%K�p��U&N�����,44�k׮�y���_|e��3���o��]�~�7�|�lס��d-Z��ݻ	�����g���n57o���o�5������III1����Ϗݻw�a��r�"""r'�5..���I������TED�{��㏜:u�>}��طO�>�������[$�.\�aÆ�K�(��A�pwwg͚54lؐ�[�����������K7n�`nLDD�)���Cɒ%��?(S�����u�m�6f̘��3,�?y�YŊ�iӆ�;wr��)Əo�7l��b�n�tqq�ʕ+:�g�}��3gҮ];����ѣGy�����+T��{�6k0`�n�bǎ̟?��.�u���vAn�b�,>��X�"������Z�Y�mۖ]�vq��y��pgw��xs�]�v���1g�#q�$��>>>���Yݩ����%|��R�ƍqss�…xzz�U�;�֭[Gpp0����9r��.Y��уM�6��o�ѿ��e˖�s;��yQ^�U�e�	���S�N���h��1J�,i1'�Z�*����}]�n��?���x�
6n�H||<���?̎���[�{��Ųe����""""""""�U���"##9{�,����c���¬VgX�p!��z��,Z��]�vE�Z�ؽ{�Q=..�8'..�챉��B֟�/^��Q����!66���������dU�Bbbb�����7��˗���v_�`����-[�x�Ν���Ǐ'""��\�r�X���������-[��_����T�bq=S�����HNRSSY�d���x����K~��[��_���5k2i�$�jc"�d�n.�0)R���0(^�8���ۘ�9::}���	'00www���qqq�iӦDDD���9b�ʖ-����Q��e˖899Y�[FGG���lT�KQQQDEEe{��Ύ�_~�W^y��Y��7��Ϗ…�����?�{�G�Νr=�rpp`„	�����₃�~~~0��on�|�7pss��Ύ[�n����G}D�֭y��g�����ٙ:u�0i�$�J
6��� j׮MѢE������___���1b���7��������`ooOɒ%	��?4[�l-ά�y�&M�ī��Jɒ%����dɒ�jՊI�&��윫�9�W^y���~����o888����'�ڵc��F��
R�pa~���k���/899�j�H~bggG�v�;�9����9�)���#ժUcʔ)��K��jGGG����ԩ%J���ё-ZX�H+�cZ��e^�S��ʕ�k׮,^�آjϽ�J�F�(X� nnn��Ջٳg��0���?��]]]�7o���-Z�T��ԩSiժ�E�g�y��I�&f�4�y�ȰV�W�@�DFF%��>6�ng������֭ǎc�̙ԫW�8˻�k����W������{��Yڵk����Q��C�:w�-k���>�ѣG9v�{��!11�
�g��c��q�X��[�h���F��ܷ�����DGGS�H��5�Ν;s��If͚e�#�Ν;2d�˗g���t?.4>�r�
/��2vvv�޽;��jՊ.�~�z\]]�ƹ|�2-[��t��|�����G��c/�It��XD�I�q�F�����P���Cz�_�NѢE�;�<I��ӱ����ڣG`�S���/�-�{���{R�Ǐ����ӦM<<<�����ٳ�;w.+W�4�擒�h׮�_�~l,��Yn?���ر#iii|��gƎܦ��hu�� �d���ҥKY�b_~����Ӆx�w�ҥ�*(?�*V���'�ڳ��6�����>���|���_b]tt4Æ
�\�rV�;ҜWD�Qy��u�=S	�_|Ѭ=kyY�3g�`�Z�2๑�K/]�İa�8|��ű��8(�ndy�o777Ξ=���]T������i�{XRR5k�4�kz]Ν;��������)�wL��?�0�ffj3����ٳ>�e˖Ѷm[6l�@�r�l�#1w�\�+W�P�X1F�`��ٱe��5k���/7nd�̙���ѿ�t钧�S���4iBJJ
�F����gggN�>�ԩS�y��ݻ7��=���w[���ӣG�:�����Өm۶l۶��k�՗׮]˳�>�?��G'K�Dy�RRR�q������ٳ��~�󊈈�����<^�p�ݭ�5Y��A��'��ׯ�6�\�6m���ӓ�^z��+R�Z5c������0��T.ٚ�e��r�5j���ٳ���f�p�믿��oP�Z5�Νk�mMN�����e歽�֘����Y3��Z""��u���9'N�t�Ҭ]��֭[�:�G�֭[���ҵkW�.]JLL�Z��uXTӦMi߾=���			DGGF���6l={�d��T�Z�֡��C�ۊ�yG�V�X�|9!!!����/Q�����c)R����3t�Pc���ի�>}:�~�c����<�
.���2e
mڴ`˖-|�*T��щ�<��4ib����m��f�9����������E	����''N��ԭ[�h?p�E_wwwN�>͚5kpww��ܹ���pJ�(@bb�q<--���W�,�J�G^��^cݺuDFFҪU+J�,iv<==�ٳg���A�֭�dN�:����W������F�~r��Օ��d�\�����ٱ+W�}DDDL~��g�ɓ'	

���,^��s��1u�T8@tt��pw�b�U�FXX��y��\�p�����˜>}:�5b��t��I_�H�����?��ɓ'IMM�t��4hЀ~�����Ǭ]�6�
�O>`��V+>����Ƚ�Z�*]�ve޼yt��MI�""���͍+W����˘1cr��Ms^�LJ.�-Zp��	�L��G}D�ʕ9|�0S�L��۬Y3"""3fAAA������c�…|��7���2{�l�Μ9����}Ÿc�^y��8q��~��U��kJ�(���ʕ+�ر#�ϟ��-5'y��
����޽{�ӧC��A�.\��G���_�s�N6lH�N��1�6mJDD�'O棏>�jժ:t�x7n���'+k�U�J�HNN������O�6�����?��#G�h�"^{�5V�Z���?o�����M�F׮]���q��lݺ��a=�?�<C�a���t�ޝ�ŋ���FPP#G�䧟~",,��}�2t�P�v��;�C�ʕm��<9UN�_vvv��ư�c����Xe��֭[?U0E��<��dݺuy�9����������A	�X�����9u�}��ɱo�>}��矉���G�f�
.̰aÌǦ��:���Κ5k�[ӦMY�n���[?r�~~~��Ί+�������ru�I^� $$���~�'N0z�h��5k֌�>��
m�{�f��͜9s��}������2k�����kհaC�n�JBB��N7			�y���<}��Ҙ9s&~�!ŊcŊ�k���a��ڵk9t��/�I�&DDD���������{�ƍǂ�裏���O��
ТEZ�hArr2�۷g֬Yxzz2j�(F,"""""""""""""""""�?��:��]\\\���)R���0(^�8���ۨ$���h�uvv&<<���@��ݱ�����Ũΐ��#([�,�������S�#G���ߟ"E����H�j՘2e
���`�ҥ��ΰa��ԩŊ���???ƍ��8�r�%K�d��:�jժ����3�<��/�̬Y��׿�E�…��)Z�(��ͣK�.���aoo���ݺu#""�v?YY{�Z�l����������qvv�E��<���<�bbb�%((���s�ȑ�:�`�ԩ�jՊ��������Tv��e����ŋ3~�xfΜ���ǭ�9}�4����J�Ɇ*\�s%K��� q��yJ�*e��������>|x������ߢ=/個-��ɓ�3%]X�f��E�aԨQ��v^f��o�B�
ѳgOz�왫�Ŋ#((�������dm��Z=��32w�\���([�,III�߿�<��u��H�.^�HPP����W^!**
ooo[�es111��İu�V���ˋr�ʱm�6�5kf���0s�L���X�b�ٱ�ǏӦM^y����KE("""""""""""""""""��)�"kҤ	)))�5
���9}�4S�N��_�q�b+�{���'22�H�����ݝ=z�8:y������=z4���,]��Ν;�:�|c�ԩ4hЀ&M������KV�E=)
,ȧ�~J�V����iڴ)p'1��^�|��,^�{{{�*"V-[���!���H>�n�:U��nݺu�j���a�Y�l�S_�UDDDDDDDDD�%\�c�Z�b��億�bv�D�f�$��R�HƏ�СC�J�W�f���.\��щ�ȣ�{�n
D||<����8;;�:�|��_e�ڵ|��w�7n�СC�u�6���{��hٲ%Ç'..��7oҦM�N��|@hh��.D�.]��:ɧ���x�wl���Cw��-͍DDDDDDDDD$_P�E>���?��'O�$55�ҥKӠA��뇛���C�]�6�
�O>`�����8*y._���ѣ�3gM�4a���T�Z��a�;ӦM�J�*X3U����A�6�����O�U����Y����Dbccٻw/o��G�aɒ%�(Q�֡�H``����|��>��>�u""]dd$����CDDDDDDDDDP�E�fgg�7�#��!"�tIOO'<<�>�,X@`` 
�uh�Ι3gX�x1aaaV�oooJ�.Ͷm۞脋jժ��[o��[o���?o��mۖ���z�j*U�d�hEd���L�>��a��S��wߥQ�F�CDDD�0}�t�o�n�0DD�!�|TDDDDDDJ�y�۷�A����0aŊ�uX�Vhh(�n�b�…lݺ��e�R�L�֯_���h��}[��PM�0��������g�����g�ڷoO���Y�d	-[��a�"r���-[F�Νm��<%�-[F�v�l���`ݺu�h���a��SfݺuV+�>*�v���HD�	���������<N�p!"""�����c�ر̞=����G͚5mV�W�fM>��Ν;Grr2������\�xѢozz:vvv6���x��g9z�(/��ű2eʰe����O�֭�׿�Űa�l��de�D�)�Ji"�_ZZ���y�����u""�h>*""""""�%\�����C,X���� 222�3g�{�֗���oXmOMM%99���$�׮]{⫅XK�0)\�0,�z��9�_��Y�f���#�����[[� """""""""""��S��CԽ{wV�\i�0D$�-[F``��� >>���ˀ�<y2ŋ�uXOGGG������u(�NPPժU#00��~��o��777[�%"""""""""""""""""b3J�xH:w�l�D$:w�L�z�l��<�^�ʇ~Ȍ3���a���Ԯ]��a�S�u���ر����֭˪U��Y�����|������8Gr�o��F�J�����b�Νԯ_�.]�<��DDDDD�1�u��̛r���i�ys��=_|��Q�)EDDDDDDD$+%\<$QQQ�ADDD#�-bĈ���2s�L��뇝����zbL�0�����ɓ'�:�|�jժ�ڵ�Ν;ӨQ#�ϟO�l�����'[�n���f߾}̘1��K�����믿���7�jղA�""""""w��G-�)EDDDDDDD�%\<$
�u"�G���DFF�:y�:t�!C��u�V���˔)S(U����z�l۶��+�:�dž��+�ׯg�Сt�ԉ�'2f���+��O�n�j��ƍ�7�N�:���@�;v,˖-�H�"�2Ly<��Pvs�{���nʣ�'�)EDDDDDDD$;J�x�ڵkG``����\�޽��C�����裏���ϩV�111ԯ_��a=��?������x�8880k�,����3t�P�7o��\�|}}�'s!��7o.\�k׮F[�n�X�x1���cРA6�NDDDDDD�3�)EDDDDDDD$;J�x�:w�L�Νm����ʕ+m��<E�/_���ùv��~�)o��6�����u��MΞ=�/�`�PKo��6�+W�s��4nܘ�+W��s��:,yIJ&y���Ɔ
8�<T�X��m�Ү];��HIIa�ܹlܸ��/R�T)^{�5��뇣��YYc�v�K�,�N�:���}ʔ)���/K�,�gϞ-Z��<A"""""�ȝ9s��;���Ɋ+,��mۖs�αb�
<==ٴi˖-�ȑ#ܼy�R�JѴiS
�����1�%�_�|��3g�u�VnܸA���=z����6fvs���^�3����3q�DZ�je���㏌;�W^y���~��wf͚ELLׯ_�|������켬��$�^�֮w��5���ؼy3�/_�T�R4oޜ������lq�%K

%>>�B�
��+���{��hN)""""""""9Q…����#r��1��ƍ�ٳ'ӦM�t�Ҷ�w��	���y���m�c�Y�f�ڵ����֭ˊ+T�E�)7c�,X`<�u������F��KMMe�:t��{��y���IHH`ƌ���e���III����☟��w�fÆ
t����]DDDDD�///|}}ٳg���ԨQ�8ORR�����ӓ�����s皝���̒%K�z�*'N�՘׮]�o߾$%%m?��#���E��~�H95j���cڴi���P�L���			����H��?�ݻ7�.]2�=~�8���ܾ}�6m���&��/fu��u�|�M����d-Z��ݻ	�H�0`W�\�l���ߒ��Θ1c�)EDDDDDDD$g��I�<�~��l�m۶��Ç���O���iѢÇg���el___�|򋨨(����É���u8""��q��ƍ�z��?��[�2�|%[<"'N�P��}�X�";v��LJf͚��7��:$�!��_~�%;v�`۶m�5
��K���…9t�իWgѢE�ڵ���(jժ��ݻY�z5`��i\\��8&&�*U�X�jj3��'�i���.7� IDAT�o־n�::u���ŋ�;�111�����_����������d����ر���0�;f�77cf7���)+�wn�~L�-ʄ	���?	&==�?��?�������������t�U�VeŊl۶�������,;��/f�`�)[�,����ر��s������lj���8�\�r�X���������-[��S��������HNT��)�����[�Z��믿fӦMf��ٶm۶m�E�L�0�Kg7v~�o�>f̘�ҥK�����_��ۛZ�j�:4y̬^���C�r��eBBBx�w(XP�=JG��lٲ;�I޹���j�*F�M�^����_�<y�=�("��]�z�G9�rrr��DFF���HӦM�ԩ���)��6n���ɓ����B�
�?�v�ڱn�:ڵk�m<��r��Y+_��Yyr4mڔ�%K�q�FF����iiilܸ777�4i��l,##�Ç��?p��1���ܩ��[?��3�G��Z�j����0t�P���3�Α�N�:ɛo����֭u��5��6b9r$^^^�3ƨ
q�r;_�ʔ(1f���I͚5=z4C�a���4�유� ��w�Nxx8W�^5�kN)""""""""9�j���֭[��O�4�M�6���L�~�h޼9�K��ʕ+�ܹ�ٳg�q�Fr]Z97c���.�:u����:0v�X�-[F�"El���<:t(k׮�k׮����_�G�ĉ�n����3u�T�W�N������_Y�hE��uh"����{L�0��;w�s�N���+���K`` ��s�3g�`u��Ǐ���`����f�#"""""�k��qqq,X��m�2o�<���i޼9���\�r����coo��K�6l���NFFF��8{�,������_��{?c��)/߹
<�]�vq��A*T��;�cv�ܹsT�T)��̋���JJJ�$Ydfz
LqgV�bE�wS���t�MsJɉ�����e|me����[�"""�ѣ���S�dIZ�jEDD%K�dݺu����:�f޼y\�p��]�mݺu�…̛7φ�������͛L�8��ի���ȦM�X�x��-l��?������x���ٓ͛7G�
8qℭCyb��ř�ܭ�Q��~ 88��5kr��Mf͚E�V����o���n���k��V�1��������ȓ�}����ٱv�Z֭[����Y�iӦq��a<==�ѣ~�!QQQy�4w�:��V�~Ƽ�9҃p�s�����jq<����ʜ@������ҜRDDDDDDDDr�
�ܥK��>}:۷o�ƍT�X�^�z1z�h�|�����Ν�ƍ�x�"�J���^�_�~8::�;�~���cժU����(��Uɒ%�ѣӧO��3v�1]'&&���6n܈��#�5��wߥT�R9���w�k׮��͛�|�2�J��y�����ggg��,Y����P���)T����
��Q�"==���06l����qpp�bŊ�m����k׮�d��ԩ�����^�L|}}Y�d	={���""b�?����Krr2�Ǐ��3�,���ꊫ����x"5hЀ={�жm[�իDze�h֬����G��Ņ��8t��6mb������ұc�<�sww���ӬY�枒]]]INN�ʕ+�W�\1��������)�$s�ׯOLL			l۶��^z��{��;wN�%�;jM��Ҭ&Md���Ibb"{������hOHH��{?c��)7fΜ���ǩZ�*�bƌ>�8^�ti��}r�@�ddd����eW�#����<<<8u����^�zF����4��N.�?���~���n�:�^�ʭ[�8r䈑l�Yjj*d����;w�[�nq��y���y�r���4i�$�~�5`߾}ǦN�ʚ5k�y�&W�^eݺu��ۗ�W���;���,^�������4���Y�h���#%%���{�nn޼ɕ+W���o	

5�Ϙ1�9s�p��nݺEJJ
��?&22��~�zRRR�>$7���#%%�
6��~DD��w��:v�H�V��U��"((H��Tx�爎���_�e˖̞=��!��#жm[|}}Y�|9)))���x{{�;�涟)Yk̘19r�۷os��e���|}}8p��״��3g��J�*p��i�XMm�>"""""���ر#�oߦO�>���ҩS'��v��Ajj*G�a�رF{n��z��W�<y2{��%--�_��I�&e{��ƴ6����^�ٳ�E�Q�V-������a����ٳ��ӰaC>������y�&ӦM��ח���g{mSr�ʕ+�q�������X���|1��M�w^���x��҈��gʔ)4n�8oO�S��������HΔp��EFFr��Y<<<gǎ������c�p�B:D���Y�h�v�"**�Z�j�{�nV�^
��g<�x�"p�]_�{�9.\�`ql���L�>�;v����Νc�…9��ՂHLL�lٲ�}ϝ;�?NDD��9�ʕcŊ���зo_�l�b_�b_~�%;v�`۶m�5
��K��bbb�R����6S���TBBB�Z�*d���,[�OOO[�&�H999�d�ƍǠA�<x0iii�KD�޽{B�&MhРcƌ���'����C��剏��G�ԫW��-[��7�P�pa�
f�5-��Сmڴ�o!��]eMm���FDDDDD�76�?���nݺf�M�􃃃���G�=z�8~�ȑ\�ӣG*U�Drr2����~����ݛʕ+[�����8y�#e����ܩ�>~�x����8q"4��\�v
�7�xWWW����?�A�F����୷��92��N�ƍ�ҥŋ�����󼼼HJJ�o߾ԯ_��}�r��9�����	�BsJɉ.1klf�nJ3f5j�����oL6n�������{{{*T�����X�n]�q���ܵ\rFF��?35j~~~888P�F
�C�̉�a�k֬iT�ؼy��9AAAxyyQ�P!�w���F����Ib�����/�:u"..�HF��߀;	Y�/_ެ���<�6m�D͚5�8q"�F�"!![�%b3
`ܸq,_�����ӲeK���[�%�D�)��Q�С���T�\GGG�X�"}��a„	y����Lxx8������coo���M�6%""�l'�#FP�lY��퍹l˖-qrr"::�"���h���iѢ�C|FDDDDDĖ���h׮pgb�a2r�H���)R����T�V�)S�п�|s��8::F�N�(Q�����h��N�^ƴ6���)�BBB����	

�������p�Q���Օy�����OѢEqpp�J�*L�:�V�Ze{�aÆѩS'�+���#~~~�7΢_n�Y-Z�y��ѥK��ܰ����͍nݺ���K���)EDDDDDDD$'2����<+P����Z}l�9�"'qqq������Jll,���Ʊ�7oҨQ#���y寿��z...F��)��tڴi���Y�b^^^�^'11�.]�P�lYV�Zev�m۶�
��
6���;vd;v�6�}���P�P!��9::kv�;���ԩS��6l`„	�sT�pa���K`` �6ƨ_�>iii�9�IJ1%���G��D���H��EDLΝ;����Y�t)|��FR��ܱ�~ڶm����W��jժ�I$_Z�hݻw7ڳ>���={6s��e�ʕ�-[���$ڵkǀ�ׯ��#�r�y�����ä��%?МR���|TDDDDDD'�p�v"ͺ#iv�`YM"�<�du��������ݺsb:n�Y�����]���1%[�����ߟ~����`j֬�͛7�5k�Z���o��8�Z̦6k��'_ZZ���T�T�={��f�V�Z�d+jժŞ={(S�
4�￷uH"��ݻ7eʔ1[����;=z�ad""""""��iN)""""""""�)x�.b+����8q�P�n]����}���9}�4k֬���=�cu�ؑu��1o�<7n���?o���ѣ,X��(˜Y||�Y�}���-O�xxxp��)���O�z����������*p��!6m����	

�cǎ�������\�rWWW��\�b����֭[2dǏ'((�Q�FQ�H[�%������i�&
D۶m			aĈ�K䉖ۊ�y�uS���H�"�?��C�ҳgOV�^�����*�������d�9���������dG.�-Z0e�HKK��L�2Ţo�f�3fG����\�|�/��___h�5Uh8s��V�fMZ�nMJJ
���cѢE���拉�����…y뭷�q����*�jղ�aҤIF����c����l�2DZ�jڴ)�'O&>>���4���nܸ�ݟ�,ڶm���/˗/'%%�^xooo��:F�J�8}���5Lm�>""��;�<={��Y�fxzzr��A&L��d��H�ʕ����m�0�Z�
b�ܹ��_�bԨQ��ݛ�����a���v��4�O>��O>�������c�DDDDDD�1�9���������X�
�X�����9u�}��ɱo�>}��矉���(k[�pa�
f<.Q���:t��ݝ5k�w�5���/~��'BCC	

��Y�f�7�j%K����jժ����w;�޽{�y�fΜ9C߾}͎yyyY��F�޽�<y2!!!�����AiÆ
ٺu+			�&$$���!""����4f͚Ň~���˗/�C��K�(55�cǎQ�D	[���6lU�T�k׮;v�+VP�L[�%��y\*Q<l����:yiN)""""""""Y�…����e�(�H�"���@���)X� ���L�8GGG����3������=...4mڔ����#F��lٲ��ۓ��j�;::Bhh(�7�x�����Q�D	�4iBhh(��׿(T���xCCCiԨ��͍^�z1{�l�8�;��E�2o�<�t邛�������ѭ[7"""pqq���u�Ё��`*W����#���T�X�>}�0a��_˖-qrr"::�����8;;�GDD��K�:u9r$�СCJ�xL?~���t^x�[�"�����Ν;�t�u��a�޽�IDDDDDDDDDDDDDDDDD$G�p�ϕ,Y���`�����P�T)�v�����s����?����oҤ	M�4�s�Ŋ���?����N�+FPPAAA9^/�dk��x�g�y���@�ΝKRRe˖ ))����3`����r����<�.]�DPP4oޜP�re[�%��ĉT�X�Ƒ�I�ʕٵk���:�7&""�Ν;�:,�T�"kҤ	���,_���W�����ɓ'��/����#|2��ݛ2e�i�EFF���N�=l���<���̞=ooo֯_��ŋ�駟�l�8v����{���?~�H,�m�L�e9��B�r��o�qJ��T�Ü����f��u`
�%��ƈ��*�ff���ϐ��K�
yE����\z=_���y�߻Ԟo���ikk+kkk����ʕ�ƍ5p�@���SӦMSff�ѱ V�(�:t蠵k����W�����+WN�6(ٳ�dɒ�6m�F��w�}W��/��BVVV�<N{�쑗����߯�Çk���ܜ�IIIau�B�X�bZ�`��֭+ooo%''kٲez�猎
fffFGC���*44��@�Ea6n�8�����ׯ�����t����rrr��U�B�#>��x�
yyyi�ܹ�$ooo5j���T���…�4i����K9;;k߾}�[��ѱ𘥤��������A��F��֭�����~�z���0������Œ���iڴ���>|��t�bt@c>
xZPpQ�������CFG�����#����Off�5a�+VL����ݻ7OF����jժ��1�...���W�Νոqc}��7j֬�ѱ��P4�۷O���ڳg��
�3f�lٲF�B:x���Ӎ��<����?�ڵK�{�V�֭�x�b�����X��s�Nyzz@�'@���_(44����|��<���o���hѢEjܸ����հaC�c�	033S�%���<���Vxx��L�����+99Y�gϖ����р'.33���Vz�����BBB��( �GO
.�3)33S+V�иq㔑��ŋ���|�b����OT�N
0@ЪU����
@D�EZ�f��/nty�f�u�������dy{{k�Ν4h�fΜ����@yxx���^]�t����"##eooot,E(""BF���HMMմiӴ`�5l�Pqqqrpp0:��иqc�ٳ�Tt�z�j�i���X�#G��F���Sll�$���Q=z�x��AY�%&$$亝�c��~s����w��-�cĹ��sV��������it���k�jԨQ�r���4h� ����#���Utt����~[�}����}�cxLF���۷�z�̾}����իW+33S={�T���ՠA�@�����sV������SL�������nt�����>�@�6m�{ァ9s�襗^2:�����J+V�Pݺu5b�%%%���Oŋ7:�G�}��\ۯ^��)S����M666�$WWW}��GZ�f�J�,�$c(žDĽ�F�Y,�(l�Ĝ����d͚5Z�f��1�њ5kgt�p��5M�>]����N�:��۷+88�b��͛:{���1����i�ĉ
Whh�ڴi������X�a���`t��s�ΩW�^�6www�;wNAAA&u�Y�V�(@!!!���0:�<���4:�|ؼy����u��YM�>]�F�R�b�o
nKIIQ͚5�o�>5h��8x�:w�]�v�s��jҤ�"##U�n]�cE­[��t�Rm޼YgΜQ���U�Z5u��Y]�t��7--M���ҟ��_|Qo���(KKKI�V0��sBB�._��U�V�q�ƪP���OŊ���U�V��w�U�ҥ��U(�N�<�nݺ�r��
ϱ�s���?�ʕ+k˖-Z�f�>�k׮��_T˖-���R�J�:Ɲ�,�ϟ׿��/m߾]W�^U�֭5iҤ\�И��Iy�[=�ɓ'kӦM�1c�:t�`j����G�M�6�$��?�����bbb����*U����v��r{�rk��<3��]�|YK�.�֭[u��y���jݺ�,kk�ǮZ�J���Wbb�J�(�6m�h�ȑ��(�9+@�ĝ��q��i�5Jk֬�����nݪʕ+�̱c�$IU�V58	
B�z��nݺ�Y�fZ�b�:u�dt,�����˗��oܸ���$%%%�ʕ+����t
:T4�=s����,???���{��M�6)--M͚5˱�Y�f�����͛խ[��xu�FvvvrppО={�����_ݴ/11Q�O�VӦMU�re-Z�Hَ?{��V�Z�K�.iƌy�����߿�N�>mj��t�ʕ}e�G�[�τ	�o�>}��jԨ�*V���g����W*T0�\�pA}��ɶ�hJJ�|||t��Mu����ϒ�y��RSS5`�?~��v��Y���*>>^���9
h���/J��r�u�t��-M�<9_Y��M�M������>�L5k�Կ��o}��Z�n���/����+�L�2FGAy����?���]]�v����233��<Ӳ��p�B�޽[��њ0a�$i��զ~+V���U�n]���*..NaaajР����))��IL�111��Z�j�ȐՖ��nl��ﲵoܸQ����&IZ�r����111ڵk��,Y"I��<V IDATڱcG����u��iU�\Y˖-��ݻ�t�R�@1�57����n�|e)]���O��+W����G�n��ԩSu��M�6��ڲe���_�v��
Wtt��v�*I
��{v/y�g�m���:~��*U����@�޽[���UJJ����s�ꫯ*<<\111�߿�$駟~�w�E+\QG�Q�5r����Z�b�bccu��Y/^\���Z�h�^�zq��~��'EFF�JMMU͚5պuku�ܹ�-|��[����+IrttT�=�d4x���yyy����?~�&N�hZ���ѣGU�Z5�c��/^\K�,Q�:u4z�h%%%)  @VVVFG�;o��_��7�<n�J�Rjj�BBBt��q�l�Rnnn����DEEI�fΜ)[[[I�W�6m��t颍7�K�.��ȑ#�n�s�*U�d�-[�T����1cƨx�����PTT�*T� IRtt�233u��!}���:v���#�	y�m�6IҤI�T�NIR�F�4q�D�1"[�G�Q�VҸqcyxx($$DPRR����դIS��;wJ�Ǝ+;;;I��ɓM�B<���3�U(1y�dӪ&���פI���k�֭����v̸q�L�����@]�t)�Y��M\A�G����s܌s��Q
4(۲����:r䈎9�
6(  @*Txґ���4M�0A�v��֞�����D���G-[�4&�]�yKҾ}����իW+33S={�T���ՠA�@v���Ə��� ���[Z�f��W�nt,<�?.{{{�c�	>|�jժ��={���E�<>#G��������X-Z�H������G�B��'OJ�:u��yRRR�;΅$)�"����>���
�T�X1u��YAAAڱc�Z�n�]�v��ŋ<x�,,,$��qԨQ:t�P���g��S�NI��F�,
6��Q�|عU~
񽽽���$U�ZU|�A����$��^�*��̻�>}Z��"�;e}Y��t��Y�.w�֭|ga�
P4�O���sm�7o��\���M�*44T���ڹs����KլYSgΜ����N[�L�<Y�v�R�
4u�Tm޼Yqqq���T߾}�������+))�訒�y_�zUS�L����llldkk+WWW}��G�z��N	�s��-�ߞ�^+W�TTT�ȳ�G���^3:���m�*..N�/_V�&M
�)�����^ڵk��^>>>�_���]�&u��A�֭3�{�MCz�����$��<��YmY}@��v�*sss}����7���<�
�~��:�ʕ+�w�ޚ:u�����=V֜��O�b9�q�(c>���qxԹםא���c^�yug�݊/n�9���k�Espp��<FHLL�$}��'�^���+&+++5l�P3gΔ�僋��;wjǎ*_�����ձcG�/_^����￯�C���͛�7:�}�ܹs�ի�����]�ΝSPP���e�������Իwo>|X={�4:�"7n��ɓ')�(�����z�����E+W�4:��)S��:u꤀�-_�\}��ѥK�4�|SI҆
r�$$$(>>��c������/�ؗՖ�@ё�"�������dEGG�E��Vl����$j�ȑ�رc��gdd�)G�ʕ%I{���֞������s���׿����ծ][Ǐ��е�_~Y҃W*�[V���+WLm�:G^�w�Z�t����ڳ��޻��K�E��_�%�n�ZNNN�ݻ�6oޜk�FZZ�.\�N�:���I;v�������y���(_��i̻���)!!A[�n���k�����S��M�6rttT�^��q����_^�U��4�ŋ���UNNNrqqQ�~��P�6l� Iz��w�}Q��={jذa�ݻw��˗/k޼yz�w������?~���}��NII���������[oi֬Y�*�y_�|Y�V�R�ƍ�]GŊ���U�V���˹^�K�.i�ȑjܸ�$iϞ=����M˻y���Z�j��RD=����o5l�0yzzj���}�!���ܹ��v�Z���������'��j�J��>��7o��Z�`�4t�PS߬�pN�<ij�Q��$��~ˑ!�-�d�֭�n޼��}�*==]nnn��۽{����u��a}��G��K�.�i������$i�̙ڻw�222t�}��'�<�Ac�67����a�ٳG���jР�ըQ#�\�R{��1�i޼�$i�ܹ:{���]��O?�T�ڵ�=�]�\9IRDD��^���Ǐ���7G���3�ֲeKI�?���Dedd(11Q�f͒$���{3�9+@єs}[W�\��u��)S��Ç5iҤ}���5t�P<x��v��*99Y~~~�.o{���O>��յkW9;;�nݺ��R3/.\��>}�d+�HII����n޼iz�O^���Z����|�rS�7n())IIII�r�<==��/))I��d��s�=�dkKMMՀt��qS�ٳg���x�T�Ryy;s2d��9׮]Ӻu�t��-M�<���lڴIiiij֬Y�}͚5S||�6oެnݺ=T&ȏիWkԨQJOO�����Y���������Fǀ�,,,4o�<թSG^^^:p�V�X!kkk��O�>}�h�̙��q�L�F�L?���W۶mSbbb�"t+++�5ʴ]�\9]�pA������ц
Լysm߾]�����+�s��gۛo��
*�ܹs�\���4i�m˖-�q�F������'����L�ֻwomٲEG���M��۷�q~^��mn���՝r{�םt��eM�6M�J�Ҍ3T�X1M�6M���:u�V�^�ҥK�_�~���Rbb���d;ϠA��9F˖-��?�\���$���u���q[�n�ɓ'տ�l����r��E^�0g(����		ѩS�dkk���@�޽[K�.�ue�+V���[��BCC���05h�@��񊌌��lK,߽�r׮]5s�L�)SF˖-ӠA�ԢE
6Laaa9V�ȫe˖鯿�R�ڵ���hӓo��/��*I��ᒤ�j��݊��ք	$ݾ�7��Ο?/I�T�R�ރ�˗���T�������RRR������W_Uxx�bbbL_"���O��y���H�jժ��|YmY}��=zTm۶�����~�m>|X�
���cѿmٲE�w�V�f�t��	�#���s�'���U>>>�Y��,--eii�jժ�o߾�>}���������!YXX�L�2jٲ�����=�s̘1�T��,,,L���۫T�RڱcG�;v쐵��ڶm[��bnn�.]�H�=�Z5"�رcծ];�,YR����S��f͚e*���߂����RK�.����ʕ+'KKK�m�6ׇ`�u���F��[嗯����hܸq����t�!&�ƍӹs�L/���Ԯ];�.]ZŋW�Z�4{�lu����5j����������R͚5Ӕ)Sr���<�n�K�VPP�z��
*���B*T�������j��fa�
P4�efff�Y`ff���yxx亝�AO�ɒ�� www;vL��׿ԴiSӾ]�vi���~�L}###M_�JҩS�ԥK5j�HK�.͖�~7�:tHqqqڻw���ۧ�W��J�*Z�h�^z����nݺ��~SPP��իw�1��/?�ڡC�;wN���rrrR˖-s-��k�f͚)==];v�Pɒ%��nݻwׯ��*�lOU����￯*U�h�ڵ��fm�X�B5k֔$]�xQo��������e]�M���/d��j߾�^~�e}��wy�Ƨ]�*&!!!�nx|�^�*___͞=[5jԐ���}W�Gq��Iu��Y�O�ֺu�x� 
���Pyzz*kZ~�vQ�x�b(""�4/;}���t�!C�h�'�y�>� �<�&�Y�ǃ�(�i�#�����6l��=�etO�<)I�ԩ�L��������k�Z�j�o߾��/�e�
<X'N�М9s�}��$=�i;y헟k9r�J�(���X}��g�ٳ�u�ڵl��k���EΜ9s�|���JMM��v��iIR�����g}�Y�0�U�f�9�=�nݺ�1.\�t�)@w�j����ƍU�^=͟?_�f�ҿ��o�-(;;;�ܹS...jӦ����K�#x�>}��bŊ�n�
		����z��m`2@Qǜ��)ft���A���޽rn}�vw���|�M]�zU7n4d���T�>}�t�R����:vV�����77y헟km׮��m�6�_�^?�������b�
y{{�[�n����ԩSڵk��V���P�~�T�N����Y�W�5K���M?�67�Ys�Ֆ�s@^����5j�֭[��ݻ��>�u%!(�=��֬Y��S�jȐ!JNNּy�T��!<[�b~�o�ZJ�,�iӦiĈz��w%I�����/dee�D�p'�E+\b�+W�$�������ޖ$I҆
�����߱jժ%IZ�n]���V۸����\�bj�m%��_~����_~��L�2�ԩ��|�r���G�.]�������ߖt�I5��q��--^�X���z�wL���������g럵�uMR���G��/H�.^��c_V[Vx�3g�j׮���Y�6mRXX��8333͘1C�V��W_}�:���ѱ��o�!///͝;Ws�Ε��w��=�1g(Z(�(�ڶm+I�5k����������$͚5+G�V�ZI�&O��Ç��͛:��,X 
:��7��'O�����%I����3g�RRR������TEGGk�ر�Ƒ�r��I�"""t��U?~\���9�5o�\�4w�\�={V׮]ӧ�~*u��5��s��;w����֮]���4��۫z�꒲���~NNNjԨ����O���W�7o��˗u��
8p@#G�Tll��7o.777�q-[��$͜9S������Pbb��|��7��Un�w�5$����NYmY}�a�رC
6�ԩS5f�%%%�]�vF�P���C;v�СC����#G�	xlr+H/�xxxh޼y�7o�i�
@a����(ftܛ���~���8qB}���o߾}�j۶mJLLT�޽���ҨQ�L��ʕӅ���*mذA�Z�һᆱ���Z�W���իs��ꫯj����-[*<<\���>��sIR�f�rׯ_?EEE)11Q���?��4hP����Z��飙3g���7G�O��k?I�հa���/�hҤI9��U�V���M�Y�ߺu�N�<����g�ogg��-��k^�y7o�\۷oWrrr��KNN������?��رc�|�r�o�^�|�^{�5�c�8}��N�>�&M��\�F��g�������Q�V�R��퍎��a���%K��ҥKթS'�-[VŊS���5c�I������������!YXX�L�2jٲ������V0f�U�TIJOO7��1B~~~jٲ�^z�%������RիWװa���_�V_��Q�F���M�?��,--լY3M�2%�u���


R�v�T�ti/^\�j���ٳաC�|��ϵ������G5k֔���,--U�Z5���WӧO�w?I*_���/_�#F�N�:*U���{�9���[�ל9sdee��ҥK+((H=z�P�
daa�
*���]���*S�L��׼���n߾�J�*�;v��c�Y[[�VX���u떖,Y�5jh˖-
��O������E���T�XQ?��:v�w�yG�}��ё2f����F�x���)$$D�n?NgΜQǎekk�����~~
�/V@@�"""T�R%I��ޥK
2D48����)I
		�u���ݻWÆ
�޽{5b�M�6M���F�B�h�޽���1:
�2�~��&M��>}����_%J�0:����Pyzz*kZ~�6�'�}���<=�GO�bF�����(--M&LP�v�dmm��~�M�gϖ$5l���x����G�}��BBB4n�8I������F�{�68�����-������I{��U�z����"���V���1�7n��ԩ#=zT�֭S�
���"�G�FGC����ƍF���֡CI����Z�n�&M��{��JHHP�r�4x�`��iV�dIM�6M���:s�Μ9���HM�6MVVVF��		Q�ڵ�r�J}��W������:z���퍎���;Cݻw�̙3jҤ�~��g�#����S��ݍ���޽���쌎�MӦM��3��(�i�
�ظq�dgg��^���������/���I䩻xdo�񆼼�4w�\I����5jdp*���Ç���m۶i���U��华�".##C����^{�5���)V�vm��ǫ{��rvvֲe����jt,!���rvv6:j���>|��1@�����<<<���at<�o@^]�zU���͛�ڵkk�Νrrr2: I:q�nܸA�Y����?hĈrss�����G�����h�0
.�mذAÇׅ�駟���[Ŋ�(<RRR$I���'���x���W�z�4b�%''+88X%K�4:�Q=z�0:*44T7n�0:�`ntPx���o�ܹ�:uꤦM�����1b�(tJ�*%777�-[��(x�6L�6mҖ-[��o�ԩSFG�3���Nݻw7:�t��]vvvF�ELӦM�@�|P�q�$�!==]������W^yEQQQjӦ�ѱ�{rqq�����1�jժ����Թsg5i�D���rtt4:����rvv6:j���>|��1 W\ OOOyzz@yxx(~��'y{{�ĉ�8q�Ə/KKK�c�a�U��]�v���C�Z��ҥK���@�ࢀ���@>�L-���g�j�ر
		Q���ߪjժF��B�L�2Z�~�&M����{O��ɚ9s�,,,����Pp@w��-���kʔ)*S��֭[��]�
͞=[u����u��A����t��FGP(�( =z�0:�|���PHH��1�'*!!AÆ
��?��Q�Fiʔ)���6:j��������*'''�_�^ժU3:�����ϲ��eff����)xyxx�+x����oy{{�iӦ*U����ۧٳgSly����x�(QBM�6�O?�dt$�!������U�fM�]�VAAAڶm��ԩct4x���+ڱc��z�-�o�^�-2:�Lj�����U�V�۷��v�#G��ޓ����рG�-[�ET�R��j�*M�2E������RFF�ѱ<\�9r��������?TXX�L��o�>C�7333���ʕ+�0a�6l���T���jѢE*[�����?�\AAAF�@fff�)S�h�ڵ���վ}{]�p��XȷѣG���3�}��퓟��Ǝ�1c�h�…ڿ�N9u��E�52:��~�zծ][K�,Ѽy��ƍx�~��U�^���\]]�s�N����I�&:x�ё<
.�o۷oϵ��ի�2e����dcc#[[[���꣏>�իW�pJ�n���FGx�~��Wu��Q]�v����:���_���dz%##CǏW�jՌ�H��ׯ�={��bŊrrr�w�}gt$��.
��� �c<AAA:w�z��ejsww׹s�d`2(:����'��N�:��_�e�}��תX���р���ƍ���7:
`R�BmٲEnnn�ܹ��̙ct$���B,�c�޽jݺ��jڗ�!�*a IDAT����S�NrrrRǎ������l�u�/^,WWW999���E���SDDD���r�;�C�,�|��V�Z�ƍ�B�
�>+V����V�Z�˗/?��@ѐ���	&�jժ*Q���T��ɓ'�ڵk�>233��_�����P����G�2333����e���w�����m���Ӌ/��aÆ�ʕ+��={V���׋/���%K���S���9��֭[���Q�5T�D	�.]ZNNN�ꫯ�ڲe�^�u͜9S>>>ڿ�Z�j�P��G��$���k'�+Q��4g�M�8Q}����׍� �6�|]�|�TȐ����C����>gΜQ``�������'s�۵4~~~Z�|��ߍ7������$]�rE����>gn6mڤ��45k�,Ǿf͚)>>^�7oV�n���Pd\�vM�Z�RBB����~�̙3�M�6���\���ڱc�>���h�Bvvv:y򤼼�T�R%-Y�Dk֬y�1�ԪU+�?^��B�ŋ��͛Z�t�$��V���u��q�1����t�R��'L������銍�Ull�.]��?�0O�ՙ3g4z�h�\�R�:uҦM��ꫯ��X�iw��q�/_^�˗7:
��Q�F�v���ի��;���pV��p��Z��bbb4c�IҊ+t��Aխ[W������SXX�4h���xEFF��
�$-\�P�w�Vtt�&L� IZ�z��_^�y�M�			�혘IR�Z�r��j��y1o�<%$$�iӦڷo�nܸ����Y?���%Ie˖ղe�t��%���{�y���K�.)88X�ʕSff�鼙����q�5j��ѣJKK��ɓ%I�|�i�ܹsu��q���k�����׵}�v%&&�8WV��?���ׯ�����t����ddd�/�P�Z��k�.EFFj���[�H9z�W�nt�ڷo�ݻw믿�R�ƍ�w�^�#�
.�0�l��KR�޽eiiiڎ���$͜9SիW�����V��iӦI�6n�h�[�T)IRHH�������WnnnJHH�V���s��ȑ#���M�U�T���",,L��r�J5h�@ŊS�ڵ,�v�X�֭[kԨQھ}�����m�6
>\mڴylcdY�p����U�dI�5J�t�����IҒ%KԤIYZZ���E�-�q.kkkI�W2���ӹs�4l�0eff��_�o���85i�Dcǎհa�t��Au�����"
4���լYSqqq�U���|�M�� �W1��
��<yR�ԩS�\�����~9r��O����X���jѢE�߿�<<<dee�P��M��ƥK�α/�����A�;&�*?�IJJʶ=s�LEEE)66V�kז���cC��֭k��|��[�n�ڲ~_:99e;���%ǹ�Ν����k���ڼy��L��ɓ'k�ȑ����]�pA'N�W_}�-Zh�����.���FG�\�rڸq�F��^�z���:u���̌� �p�%$$d{=�]R��-$)33�c����~n׮����{����~���v���աC�[��Ι������s�'��ƍd���"��\�x���aƸ�wrn�d�>���j���s��ի�N�>���@5o�\iii�<y�^y�-^�8�y���U�F
EFFjٲeڲe��)V��,X�%K�h֬Y�޽��\�bt,����)dcc#IڰaC�B������g�_�Lu��IZ�|����K�.i���}λ����r�99�-��E��>'N�Pfff�WFFF���&MRRR�7n�h�ĉ�}������$EGGgk���͵�r�ԯ_?�ܹS���?~������?4�IJJ�����^�z�СC�ݻ7�l�4h�~��Gm߾]��Φ�\<�Z�j%I�<y�>��7o��Z�`�4t�PS�Ν;��Ak׮UZZ����U�zuIٟ���sf��{�Ma5jԐ$���o9�f�e����ڵ�$���C{��UFF�Ξ=��c����L�[�6�ݺu�>��39;;+&&F...Z�`��n�j����ѣ5F^���K�����hݸqC���2dH��ժU����-Z�˗/�~���_����+i���j̘1jԨ��_����x-\�Pe˖�w.@���o*>>^7o�T�ƍct$w0����4:ij���L!!!����u�^$I			yޗ����}��ĉ9����R@@���!<<\3g��ul�*�9g�v�t��I�W�ذa�i��Ç���v�����_hʔ)�ܹ��
�P��������\���]�xQ���:|�p�}�J��Ν;հaC����z���u��E���ϪR��N�8����L�2JJJRٲe���/�ܹs��W_}U'N����
6�yw�������}��e���+Wf�dɒlmwrpp�ٳg����Y�fi��27�N�E����ݻ�~��-Z�H���3:�…�r-��kkk���C666���P�2eԲeKg[I���U>>>�Y��,--eii�jժ�o߾�>}�C�s̘1�T��,,,���.Ij߾�J�*�;v�Ȼc�Y[[�m۶�}{a�?��v�ڥ�#G��W_U�b�T�|yu��E����B///����Z�p��T�"I�R��.\�S�N���K��`�U�ZUŊ����5F~�(QB۶mӰa���K/�D��ѣ��,Y���!C�F����JVVV�^���V�����jݺ��9��C�Rl�0kkk���k���0`�ƌ��7o(�X��1y�.�%�/V@@�"""T�R%I��ӧեK
2D48!po�p�]�~]�gϖ����V�*����\�RP�-�j�*=���FG�,��ǦO�>�X�b��CBBdcc�޽{�
���(իWOs��ѴiӴo�>�-�<���QLL��1�����]۷oWbb�u��1�#ExlJ�,�iӦ)22RgΜљ3g�iӦ�����xP����ٳ�ڵk��u��7n��/nt4�лy�fϞ�_���(�c׸qc�ٳG�K�VӦMet$�H����o�!///͝;Ws�Ε���5jdt,(T222�矫f͚JHHз�~���p���
xj����JOOW�jՌ�[[[EGG���V����gt$��)ft<{<<<���at(�v��%///:tH�Ǐ�ĉU�dI�cO�cǎI��W�np��XYYiŊ�W��F����$������O����5h� 9;;륗^RRR�f̘A��RRRT�lY���FG
����&L��o��F���jӦ����/�cE���L-[�L5k��w�}���PEEE�T~����������өS'�ڵK�����4i���$�#�<
.( P�-Կ������ի�ѱ�g±c���k�x��ի���xU�\Y͚5Sdd�ё�gZ1�<�<==aty�f�yxxψ��4͘1C�}��^�u�������X�3�_~�����1�'��_ԏ?����_]�v�'�|���������h�3���ҽ{w�#ȇ�ݻ�iӦF�3`Æ
>|����o͝;W���27gA)�q��?��
(��/�%K��^�z5j���� +++���
.
HXX��O�ɓ'5b�EDD�W�^�?�lll��<��v�jt�p��jԨ��={���E���5:������̌/^O������_x
eddh�ܹ�S��8�͛7k�ʕ[���m�*..N�/_V�ƍ�g��#�V�(@]�t�����1��x111����ѣG5~�xM�0AVVVF�1������U�^�ԢE�����X�S���Խ{wu����� ""��x��?^'N�W_}���zKk׮����ѱE���?�o��V�Ǐ�����������ܜE
��E�y�����˗k̘1*^��BCCիW/�c I����ܹsU�N
6LЊ+dmmmt4�D�Et��ըQ#�}��ъ��Prr�.]��ҥK�^�zruu����c��A�������~����+IrttT�=N�hаa�#///}���*[��ѱȡ_�~�^��\]]լY3�_�^���gt,�cnt<Y�G����g���ׯk������.(##C�����#Gj�ĉJOO�c6��퓟��Ǝ�1c�h�…ڿ�ѱ$--M'NT�F�������8-\��b@�ּys�ٳGjҤ�v��at$�C�E�}��\�?��mٲE���9r�"##�͛7kƌ���UTT����>ֱ
��W�^Ք)S���&������U}�^�jt<Oط�~�:u�hѢE�;w����M+�0��ӧծ];?~��(@�ggg��;w�E�jӦ����K�#O
.���`�ͻ����ƍU�L�w�޲������ʗ/�:(88X�˗�ƍ���hhނ�s�ΩW�^�6www�;wNAAA&�$�����ڵ�:v�(GGG:tH|����	�ȑ#���R�ҥ��<�{�9�Y�F'NԐ!C4�w��5]���#s��
ZJ̊c��*����PԬTMM
�Z�*��iQJP55d2�5U[��J���������8�N�y��\g���z��˩�>{�ۊ��3;�#ؚ)���.\�;v���˲��S�2eԶm[�k�.Q���H���h�Ν�r�
.�W_}U�������$%Z���ÇkӦM��^�z�T�R�f)T��z�衹s���SժU����>}�v��){{{yzzj���*\�p�}?��x�n��…�{�n]�zU�V�&M4`��˗/�y���͞=['O�����^~�e�1BNNN��[�n�o�Q�Z�T�H���E����������ٓ<�\,..N�}���L�"777�رC͚53;��>}Z...z��͎��E�'OV�J�ԧO���i͚5*X�����l���_|��˗'|�{������;w�{���X
4H���	u/_��ŋ�ԩS��/R}+��'$I/��R�y<==5w�\;v,I���͛7K�����������Z�r�\\\�|ͷo�֛o�����'�����ի�ŋ���9Q���ƍ	}�_�^������%�}�o߮��Hկ_?I����+((H;v�P��|=r???
<X?���������-GGG�cx���U�lY�c9R�Ν��m۪N�:�U�
̎d[)?��mذA������_��퓷��$i͚5	�V�\���PU�RE�W�V``�֮]��ի+((H�����"q����W�\�$������D���?��3Iف4w�\���k���*V�����j�ʕ�����˗��*^��/^,����X�b:{���.]��Mɒ%�a�<xP}���$�ٳ'�<��x��AIRŊ��,����ڵk0`�<==U�Hk���,�����Y���f�r�5j�СC*\���ի��۷�	ȶXp��<<<}R;��êU��v�Z�����ر�>���B�v��)I�:u�ʕ+'�.]Z�'O�$}����f����$�ڦ��a���A��ު_�����T�jՄ�%\���Ǐ��U����NժUӸq�$I�w�N�f�رz��g���[�͛7��:�?����p<�T�R����вe�T�|ymٲE�V��Ν;ys>�͝?��c*Z����٣6mڨU�V���O͎dK,���F�!��O?U�.]�x�bEGG'���o�I�ڴi�h�F�v�$IgϞM��"E�H�._��j�K�.%����u�&�^�zuI�ŋS=gJ}T�V-��^xA����7I�2e�$����E�t����ci�k׮I���ϟ���c�u�l!!!jԨ����]�*44Tݺu3;�G���Ξ=��(�
�l�2M�:Ucƌћo�����c�
.���Ç}R;��+�h۶m�����jժ)::Z���S˖-�~������8�۷o�Z����L�^|y|�=�;F���<y�3�\@�0;;��?[,�$�i���e�?������z�T�F
ݹsG����������jv4ip��%EGG��`EcǎզM���ߪiӦ���?͎d,���\\\ԦM���h���z�7t��M͞=;�����$i���In>|XAAA��ѡCIҒ%KR�
����Z�|�$%��'O&�~��1I�s�=��+�G�b�$IǏOt<�{���WZ�񩧞�$ݸq#I��c�u�<[�lQ�ʕ��W_i�̙
����ٱ�ÿ��/�F�fGr�V�Z���_�U��N�8av$ [`�E6ֶm[yxx��o�Udd�ʖ-�r��IJ��C�ƍ%I�ǏWxx��ݻ��W�jΜ9���РA�������o�%�V��Z�j���H���O�W������8EDDh�ʕ�߿����ԢEU�^=I֏>�H�N�R\\��;��S�J��7o�j�kԨ�$i�ԩ:y����t��IM�6M�ԠA���K�8�/_^��믿&9G���:r���]�۷W�֭U�N���iذa���1;�t���W�ڵ���dv שT��������.OOOmذ��H��l�������:u��O���ӧ'*{��ν{��޽{u��I���#Q=GGG���;	�,�k׮�}��rss��͛%��X#&&F�v���ٳ��q�ƚ8qb�Y*�޽{':V�R%u���}?|ͻw��o����}�&*{��g�K����/���~�I�N�J���S�NI�؂戋�Ӝ9s4y�d-ZT;v�P�f�̎@�U�P!m߾]ÇWǎ5e�M�0!a�4�a��>|X�N��}�������
*���^���*S��z��)S�$�˗/�/^,///������F...jԨ��.]�hW�ѣG�x�ⲱ�Qlll�q{{{M�>]�g�V�
���<y�`��z饗4{�l͘1C�f�={�<==ekk�"E��W�^�?��������ϯ%K��s��*R��lllT�Hu��MK�.���K��7=�ؼys9;;k���Iα�~�˗�������O5k����5j�(��4���ռy���_�>P׮]iv,��0�C��E�V����W��s+IJq�HN3�|���h�ƍ*^��$�ҥKj׮��~������{�U�V%�9õk����E��iӦ���/U�\9�c�#�ٳG�:uRɒ%�i�&�(Q��H@�b��o��-��!�U�V���M=z�01����e˖�B�
ڲe�V�\��;w����иqc*&&F�k�V@@�ّ�,ł�NNN�<y�|}}u��e]�|Y����<y�͎ ���jԨ����Ν;+444��.@V)S�����U�fM5n�X+V�0;�el�d75k�Ԑ!C4s�LI�СCU�F
�SxXTT���}͞=[�?�����av,r����k�ƍ7n�z��S�Niڴiʓ�����Xp��r��a�#d
///ސdc[�lѰa���k�̙2d�lll̎ -Y�D����=jv�dcc��?�XU�TQ����U�V)��fG2
�$�����:t�֭[�v��
Ӱa�Xl<~��g�av�׳gO�ٳG�R�����/��	�n� IDAT�4,�d{qqq�={�*U���'OjǎZ�f����̎ ��>}Ze˖5;I���SPP����T�vm�߿��H@�`� [���S͚55n�8�5J'O�T�f�̎ ��;wN���f��y��߿_
6��/��E��	�:[��f�֭�����1���u�ԩS'�c�׮]����|||ԤI�[�N�ʕ3;�X,I�aV?�a:{�l�;\df�f9v�^x��c 1{N$��,o޼Z�n�&M���ԩS�5k�lll̊	X.2�ƍ�q�F�c@�b��/_�1c����F+V�����ٱ��ҥK���|bv�h׮�6mڔ����d�9a�X��r���ӧ���õf�(P��h�cc�E&ɎC@v�A��<x�>��C����@d�}Ν;'IÔ�M�6��LN�]�tQ�2eԮ];խ[W���)�J�y�@TT��{�=U�^]w��Q@@����[�$�={V��哛���Q����CAAAʟ?��֭�]�v�	x,�paE�֭�����1X��u�ԩS'�c<�l٢�Ç�ڵk�1c��*�cH'��"�;]�����ȑ#�l�2���ꭷ��￯�W�j�Сڼy����զM}���rqqI�>22Rн{�T�P!�j�J�|��#_ܾ}[~��֮]�K�.���Mݻw�ĉ���$wFsf���'Oj�ȑ��󓓓�:uꤙ3g*o޼	u���k���Z�f�.\� {{{U�REo�����뗁;�̖�y��奯��Z˗/WϞ=ڮ^�ZݻwW�N��nݺ���=��܋�q�����Ww��Q���`��$חڜܷo����W_}Us��ѐ!C�8�@ֱ�O��<�p����K�V�2;F����kĈڰa�:w��>����9XJ.��&��d�͛7O�Jt�w��Z�dI��}����ŋ�+U���=��&�wtt�4h�Ç'���/k���ʓ'�Urf����zJW�^MT���Z�pa���4CcǎՌ3��IҬY�4r��d�`��΋�ׯ��׭[�t��I=����T�jU�˗O���*T�P�s�a��'Iׯ_W͚5u���Du^{�5mٲ%�oI�����N���'jРA�3g�����1;@na>|rه��#..N�g�V�J�t��Im߾]k֬a��K�ĉ�����/I2d�lll���HM�4I��y��$�nݪm۶)&&FT�R�t��͚5+�>g͚�Ç�N�::v��޽���yzzj׮]Ip<NΌ�U�|y�>}Z���?~�$�モ����=���~�A111�u��͛'I����S�#�����U˖-�͛7իW/ݻwOo��n޼��K��`��)�	k�=I�9s�Ο?/www*&&F?��N�<��\����E�Ǐ���b�
�h�B׮]��Y�.Y���OC�Qxx��}�]y{{�����X� �.<����K�nݺ%I҉'T�jUIҝ;w�/_�dۯ_�^�۷O�g�Νz�WT�bE���&�w�j�t��I�?^�=�\B�s�����]
6�޽{��3#}9rD5jԐ$]�zU�V�<yt�޽d�G�J�(�K�.�W^Q���ծ];�.]:�[�g^HҨQ�4{�lխ[Wz���g�%�'7'2c�U�RE!!!���դI��s~���jժU�陓ǏW۶meoo/___U�X1}
���Lw��5���{Z�h�7n�y��\�rf�`E)-����L��*�x\\�lll�֭[	�$)**J��β��WLLL�m����b�B�
��իVə��bbbdoo�p�<y�${��3��o�Q߾}�rvv���5b�9;;��?̑�y!�3'jժ���`U�TIG����cByrs"3枣��bbb��}�}����ϟ�nz�����_]!!!��oԢE���E�r/�0�|�rU�PA���Z�b�v���b�	��.6.bH���m����d��:)�q�F�c͙���x��� ��t��U�.]��ŋ��/*22R�ǏW�%4��4�Y'#�"^Z�Df̽���ɷ��KR7�s�H�"ڽ{�ڵk��^{M�g�N5?����)���ԨQ#���G�;wVXX����̎ ��O�}߾}���+�ئT�R��.�0�$���8���ʾ
,�>}��


һᆱ���[#G��Z���΋q��)88X�j�RHH��{�=���e˖��g�����9��ࠥK�jڴi;v�������t��
.V�q�Ʃz��}����_�����hr�~��)  @w�����5h� IR�n�Rl��K����t��Q���)""Bcƌ��bQ�&M��/3���y����	�ʔ)#�Ţ���J�n�R�j�T�Z5I�w-@���y�{�n}���������K/iΜ9ڽ{wB���Df̽��WԾ}�t��]i�I�>Μ3f�6mڤ�kתiӦ�r�J��Y�b�av@�u�V
6LW�^�|��C������X�@���|�{J�վp��믿���������l�7n�nݺ
O����Y�/�`����׿��/��矒��%K�…Z�`A�b���i�F�6mJ��H뼸~���V��7n�ĉ*U��.\��jժ���E���ruuMvNd�܋��Q�z�t�رD��u릯��:Q]k�ɐ��i�F�ahӦMz�����J�pxl/^T���k��V�Z
����Yl�+VL�K������/�1c�h���	�-�S�@���iĈ*Y��lmmU�P!�k�N	�[Cf�5g��.]Z��������ώ>>>�Q�����*U����[˖-���:�:/����]���J�*%I*U��>��s]�xQC�����Ȍ���࠽{�j��z�����Ν;k��I�ZcNV�\Y���z��gU�~}����;3�����aqqq�;w�&M���E���/��+��bv,�@���(��ӧ��&}9�ݻw��[oiѢE�裏���mv$@�dkv@����!C�(,,L�������ٱ�27nܐ����1d";;;-X�@�+W�ȑ#����?��dd�<f�,����
�p��
֔)SXl Ӕ-[����������k�֭jܸ�"""̎�'��0�����0�X�B�G�����fΜ��ݻ�@.e�X$I����������ɉd���Y�[�VTT�|}}��/�	O(v�<RXX�7n�>}��S�N
c��Le�&M��ҥK��x”/_^����X��4h�o����HxB������(�7NիW׭[��/��R���fG�������?ov&(X�����{���G�;w֔)S���j��V�غu��
��W��>А!Cdkkkv,�Y�`��
��_]K�.����ّ�`�@"/^Tǎ��k��V�Z
����YlL1p�@m߾]?���4h��/�	O\$Iqqq���OU�bE�8qB?��֬Y�bŊ�
<�7n���@EEE�N�:


2;��0�C�����+,,L�������ٱ�qㆼ���{�n��������H�ě;w�8`v����SÇ7;�d�pO����[����
.���`M�2�� [*P��|}}5t�P���C�Ǐ���͎O���@�[���Xպu�hv@6`kv�9V�X�ѣG+O�<Z�l�z��av$�G����̙3U�re
<X���Z�b����gv4xbyyyiժUf��j�w�nv@6��9s�^~�e���[�۷WXX�-@�ӧO�ڵK~~~���ԯ��jv$�2�pO���XM�6MӧOW�r�t�իW��X���Ǐ�dɒ*X���Qdc���


R�6mT�vmmذA/���ٱ�6w�\8p��������nv@6��سg��V��3f��ב#GXl [{��W�l�2�c�J�,���~��jڴ��.]jv$x�jݺuf� ]֭[���@�c�!v��\쯿�ҨQ��b�
�j�J?��J�*ev,H��۷!www���!��˧���k„	�۷�BBB4}�t��ؘ
�H^^^Z�j��1H��ݻ��M��r!�0�d��;V���Z�n�:t�`v,H��g�J�ʔ)cr9I�<y4u�TU�REo���BCC���_�����hȡ�`]aaajذ���ݻ+,,��r��g�*O�<,��!^^^ڻw��;�����ܹsfG@ł�%���4a�U�^]���
М9s�?~��@��;wN�<����͎ ��S��������:u�h�޽fG���0;B����\@.�s�N=���;w�>�������X�!gϞ�����1�p%J�о}�ԴiS���+Z�p�ّ9��ԿU�XQ���rpp�3�<��;j�֭f��2�E��*�rssS˖-5~�x�8q"պ'N����ղeK���Y���?vlmmU�`A���=z�~��G��ZY�d��Ȉ�/�]�v*P��lmm���#G�X���H���?�QŊ�R��,��;��s=zT�E�?��U�ed�Xs�%76����EDD���K���U����P���۲��1;dؙ3gXp�*�����7�h���4h�����8�c��?��S-[�T�
�h�"���+**J����x�֯_��^{M�Z��͛7͎��DDDh۶m�:u��L��j�I�&i�ԩڶm[�{��{�t��u?~\�f�R�J��r�J�c�&�ǣG�ڴi�n޼�{��)""Bŋ��׀t���D��x�
I���O��_/�]n���`&\@t��}͟?_+V����|}}�~�z�(Q��h��ʕ+��u�@.a�X4i�$�Y�F�/V˖-����������W���mۦbŊi�̙
		Qdd�bbb�>�@������6mڰ�/��ݵs�N���&[�]�v�dɒY�,s����?��C�v�R�֭�^�z%�sJ|���q�##���$I�6m�ݻw��E�Z�ܙ�gϞ���ѪU��j���h�^�Z����ѣ�Us����`��0'O������
�~��)$$D�[�6;X�…ջwo�c�e:u�}��),,Lu����ӧ͎�&�����ϫaÆ
		ѨQ�T�R%999���^�˗ׄ	���'WWW���O�?�ٱs��-[���ڷo_��{��՝;wԲe�,N�5���T�H5m�T���;v����cv�,���q��]IR�֭ekk+''��>gf+Z���7o��ׯkÆ
��]�~��_���͛g��$�t,���Ν;;v�j֬)�0t��a͘1Cy��5;@�P�F
�P�B�[��v��av$x"���0`��}�Y988���MݻwWhhh��-�#?;|��:uꤧ�~Z���*S�����u���D���߯m۶�駟ֆ
���b�*U�h��钤���?I�����o�x�ⲷ�W���ջwo�9s&�뒤C��I�&rrrR��զM%��̙34h������� WWWլYSS�L��דm��l�I���"��?j�EF珔�qNin���Q�M��5j�ҥK���oy���h}��z饗��SO���V�V�V��w��t���9�nݺ�H�"���W�5�y��3�Gj�!���?�#O�<I�ed,�5����X��|||R=O|y|}kΏ��%<<\�z��������T�lY͙3'�s�'ף�������_U�fM�͛�����d{�7o6J�*e������3�ݻgv$�+**��޽�akkk̝;��8��yyy^^^)~ؾ}�CR������u��$m�������)Q��K�666��}��۷o'�0`�!ɘ8qb��7::�ؿ���-[''�d�̛7��s���+  �pttL��������K�&((�ȟ?�cQ�T)#""�j��8�/::�pvv6ʖ-��ؖ.]�ptt4�ܹ�)��g�S�G�?�݃-ZdH2:w��9n޼iԨQ#�n�X�͛7�9KF�Ď;�mc�X�+Vd�x�羧�[�c���?*_tt�Q�`A�b��ϟO��s����(T��c�kJ�֭[S�3ӦMK�Mzs=jl��~Ϛ4i���.]�$������p�إK�ԱcG�n�Zu��Uhh��<y���(GGG�\�R|�F�����ݻf��\�ڵk�ر�nݺ�w�yGgΜQTT����կ_?������K�/_N��0�$��S�&�/Z�(�Ͽ���{��iРA��_�}�����]ǎ���P�����V�Z�����){{��c�ڵ����Զm[�:uJ111:u�ڶm�;w�s�Ί��H��}��ի����Ν;ڻw�ʔ)���X}�ᇉ���;�u���3g�(66V���ڳg�*U��.hʔ)V���޿ǮI�&:s�L�7ч����jذ����3���sV���$=z4�zӧO�ѣGU�re8p@������V@@��ի'�0��G��ό̉�ׯ���+�MHH�bbbt��Q5i�D�� < ��H�}�������dݱ̈G�sppP׮]e�/^��9/^,�0ԭ[7���g�5]�r%�w��E��኉�ѱc�ԬY�ϝ�\���=;s挂��u��
͚5+��xe��@����s��1���o�)S��̎�+mܸ�ȗ/�ѨQ#�ʕ+f��'=o�:u�!�?~|����N���
[[[C�1f̘DecǎM���2�v���7o^C�q�ƍT�L͸q�IF�ƍ��Hy��=�q���^���M�
Jr�ݻw�WW�D��wh��ᅮ�9u�!�(V��ղ=(���s͛7ϐd|�駉�̘1Ðd̙3'�O�8��!-�j����<���S=Gɒ%
IƑ#G���̙3ɞ#�,��|�I���{��Q�n�Lk̻Ys,�R��q	4$%J�H2�qqqF���
IơC�2�>�����-[&�{��]�^�zɞ�ڹ��l��I� v���W�@6s��խ[WcƌѰa���͛� Wj۶����t��խ[W!!!fG�\k�֭����z+��~��I�v�ؑ�9nܸ�nݺ)..N͛7״i���ڵK�4dȐ$m=<<d�~�嗄cQQQ��|���J۹s�$i�رIv�̓'��}�]IҶmےm?t��$�j׮-I�y�f���<�$�e˖Z�j�~�����ʕ+�0]�t�j�d��ײeKIҖ-[��_���g������$)&&&�z.\�a�Q�F���{N���ddNl޼Y����&ickk�q�ƥ��GIn<�1�dͱ�,�k�VŊu��Em߾=Q���u��%U�RE�2����ȑ#�����&̙�Y;��5l�0�}� [��q��-M�8Q_|��ׯ��G��r��f����y�C��_��V�^�V�Z�r���PI���[��Μ9�bـt������믿���M��g�J��U���L...�~��nݺ�
��MJy��X��lswwOr,o޼�����':>n�8���G������"��M��u��z��dooo�l��+Y��*W������֭[ʟ?�nܸ���lٲɎ���O�8g�;w�H����� IDATg������� ���$�0��>#s�ԩS��Z�j%ۦ^�zi�ɍ�5�]Jw,3�o�!ooo�����W_M8���P��̸���0IR͚5�-�[��#�a�\��{�`
��b�d6l��o����H-X�@}����b1;d���X�]�V-Z�P�…͎�	S�H���<x�ڶm��ӧk���f��\%���ToѢEZ�v���ϯM�6�`��I�ܾ}[R�w�pww��Ç�:uꤩM\\�lm���޺uK�R\��?~I�{��a�o�O�޽{�@����u��QI����K�j�ҥ*S��v�ءҥK[%ۃ���kٲ�f̘��;w�}���������?=�U�w[)^��#�Y�F�ƍ����ό̉�1Mia����ce���xXk�=�Zc��z��������WW�\��O?�+W�h��Ͳ��U�=���k��3�s�aO=�T�m���qϜ��;�ɔ��U���_U�6mԱcG5i�D���z��7Yl�t��y���S/^4;
�'����|||��'����[�{�VLL�ٱ ׈�M��2#�Ͻ{���
��o�-�Ţ�+W�R�J�����Q4h Iھ}{��>}ZO=�T�����q�F�m�_��(��z���u�����Z�x����r��I�Ν;�#FdJ�ǹ�_X�u��D�����?��{tt�Uνw�^I)��?��իյkW�?^*T�ĉ���M�6������3#s"�M|��R:Wz%7־�;��9T�X15k�Lw������%I˗/�ݻwռys-Z4��5�Gr5gRZ�`�\Y�[@<\�	���4s�LU�\Y�O�֮]��l�2=���fGӜ={V���f9r�6oެ�7�iӦ���?͎�����$���/]��յkWEFFjʔ)jӦM�u˔)#I:u�T��ݵkWI�W_}����|��w�y�f�%��l����D����g�U�>}��㣟�Y�7o��֭�-���a���rqqѶm�d��o߮�y�aÆY�Z����u���ܹs�}�{��i�…��֭[�Z���>�$͟?_aaaz���շo_�i�&�n.���d��U�T�$9r$�6�~d����xX��gt,3{>$�w�ޒ�e˖I��,Y��x<kΏ��/pH�<~���Y;�Y�����X@@�<<<4a��3F'N�P�&M̎�;w��������(�W_}U������P�Z�t��	�#@�עEI�<���|�ڵ�X,Iv:=z�N�<����k„	��ѸqcI���O��S�N�b��T�R	�j׮�f͚)""B]�tI�a�x/^�̙3�'O�=:�x���%I�|�I���߿��3gJ��6m�j��(U��,�BBB��կ_?�1kf��{�����5k�˗/k�����?դI988dI�iU�`AI�?ܽx���>��	"www���k�֍_�޳g�$e�g�N�sTT�#��Ȝx���%I�f�J�Ãa	mGJ�a�ѱ��|�_���b��m����U���Z�j�BBBT�P�$�ά9?R�!IӧOOv'���Fs�46Y�[��XpY��2d�^|�E.\X'O�ԤI��@<)Ξ=��R�*V���� �)SF���ڸq�ّ G2d�
(���E�


Rtt���٣��gϞ����ԩS�����/�TժU�|��D;K$g��rppВ%K4n�8��������ݻv�x���.T�…�m�6U�RE_~��Ο?���8EEE�ԩS�1c�<<<��_i„	�V�Z�>��ϯ={��}��


Ull�BCCվ}{�ݻW���z뭷{�u�&I�ԩ�v�ܩ;w�(..N�N�������=�n�l�)�8���w��Y�ZxzzJ��(::Z�Ν�ȑ#5o޼t�/..N�/_��͛ռysM�>]vvv��񑭭m�m�}�YI�,>��?t��=����W�^�v�z��#sddN���_ŋ׎;ԩS'�����ݻ


U����i�a�ѱ��|���aÆ
���Slll�:����ҥ�$iĈ���
�����5���������U�V:q�bcc�Ν;���EFs�46Y�[@" �}��׆������O˗/7�߿ov$�vZ�ha������Dll�1h� �b�}����xyy^^^)~�֭[
'''CR��y��%�_�f��>�y����a�X��W�^=#***I���`�lٲ��accc���N��|}}
�d�988�}�]�6�eT��7��+���x��ƅ2-[z�_J��������Y�Z�:d8::&��…Sl���*�ȗ/_�c�\��{�3q�Ą���ߦ��22'8`�͛7�6�/N�;��a��ѱ|��F�%9Or����9t�ծ)=����
WW�d�X�|y�m2�+��Ɍ��x������Ν;�-Z���K�Z�Rxx�z���7r����ٳ*[���1 	;;;}��W��/4i�$u��]���f���e˖:~�����g�yFvvv*P���5k�;vh���;w.�}���W?��^}�U������^*T�|�={����1I�*U�(88X.T�-���&;;;9::�\�r8p��;�)S�$�g�֭u��Q���Cnnn�������z��cǎ�]�v龎丸����_��*U�$'''������]�F�ұc�T�d�L˖��777�����ʕ+'�	?��O<xPmڴQ��eoo�:u�h˖-�߿��gkk�…�~���<y�Ξ=���߿��-[��ի��A...z�嗵e������8q�$i���i:_F�ċ/���Ǐ�W�^	m*W��o��6a�gg�4�F��Ú�=�ci�d��h�By�敭��J�(�l��u�B�
��������5�Gݺuu��	���?�W�XQ�W�VϞ=�m��\��MV��� �a��! �����̙3���t�Қ?�<==͎�V\\�����l�2u����8��]�v�s��*[�����;+V��H`��ݻK�V�Z��w�߹s����r����6;�!���v�+ۿ�jԨ�?�P'N�ѣGYl��A��F�fG�T����
�͛7U�vm9r��H����Y�EgΜI�|ѢE���5kfe,�,����k׮�_�~jذ��y��:uJ�����͎�^�|�4w�\�/_��(�He˖����*W��
h�ڵfG�4u�ԑ$u��E�w�֝;w�3g���w���,I0`��12��� �3C+V���ѣekk����Z]�t1;2�������{�5J]�vUHH�&O�,��bv4��5k��6m�cǎ�iӦI�-��O��F�e}8�L��N�>��_~Y}��Q�N��b�'����>��3-X�@ӧOW�N�t���cXU�5�#F�bŊrrr����J�(��]����O���12;\@���hڴi�>}�*T� ???թS��X0A���U�|yu��A
4����J�(av,�)Q��>��S�cd9v��t���U�jU͚5K}�>�b�'�K/����@ݽ{W�jՒ���ّ�Xpit�����K͚5S����Q�F�֖͂ �.]Z~~~���P�&M�r�J�#�1���0-Z�H*TО={�~�z�����g�5;�����k�ƍ6l�z��q���0�c x-;�"$$D�
R@@���?�P���3;�*!!!������ͮAr}��'�T��
���p�X�By��5;d�իW��ݻf� �֭['///�c�!v��dDEEiܸq�Q�������>����	��߯3f��@�ӻwo�ڵK����.^�hv$�tu��Q�N�̎@�t��Iu��1; �6x�?���C�꯿�Ҍ3��[o)O֧@f9�����͎����S���jӦ�jժ��7� �\m���>|��1�*Xp�����z�w�f�u��Qs��Q�b�̎�ޙ3gT�lY�c@�y�����nݺ�Q�FZ�x�w�aQU�����nf��� �Zf�⾛���������[��*K�,KsO�L�5�]1�HM�0�\�,wADp~��|���y�y��{���;,��C��ݭKD$G���l�"""����CPP��c����������H.�	"R�ݽ{�9s�@ɒ%Y�~=;v�v,�#66�N�:Y;��H�*V�k׮e̘1�������������d;ݰ*""y�����#����������H.�	"R������׏_~��#F���.\�ڱDD
���ɓ'�…�vvvL�:�g�}��âE�(R������d+ooo����CDD$�֬Yc�""""""""""�K�Z;���5ܼy��#G�������'O�d�G��?�$!!WWWkGyd�~�m�m���ݻi޼9�Ν�v$�@.D��Y�~=5k�d��|��7�۷���ڱDD
���X\\\��DD��j֬aaa$&&ҠA~��gkGy$.^����;mڴ�ܹs���ӡC+'�=�?�+�		aĈ�1����G�JDDDDDDDDDDDD�z4�BD
�s����內�'M�4!&&�~��ak�o�""�R�re���ʗ/o�(""�������v��4oޜe˖Y;��H�����f͚f۵jղZ����w����7�}��a���F��ȑ#�1cG�y�	EDDDDDDDDDDDD=�e,"�^rr2_�5�>�,ǎc�֭Q�lYkG)�*U�Ĉ#�CD�jJ�(�����ׯݻw��?�`0X;��H�Ik…q��۳gO��֭[�?��]�R�\9ʗ/����ƍ�֭[�8�������������ȣ�	"��EDD����ѣ6lG��m۶֎%""""bbggǴiӘ;w.'N�[�n��UD�www���`޼y�����?0c���ݭSҰp�B.^�H�n�Leݻw��ŋ,\�Њ�DDDDDDDDDDDDDr�&\�H�t��u�y�4h@�"E8r�&L������DDDDD,�ӧ[�la���4k֌?���ڑDD��������M�6xxxЭ[76nܘ�ݍ7��/x�W���cǎ|��ܼyӬ�q"Ill,�I�&�nݚI�&�M��{�.s���ˋ�
ҬY3z��Ś5k̎u�q��C�hժ���O��R�̌;��oܸ�?�@�z�x�'Lm�|�Iӄ�7n�s�EDDDDDDDDDDDD�6{k�n+V��w����|����accc�X"""""ԲeK����ԩ���g�ڵԭ[�ڱDDJDD���;>>>T�T��+W���nnn�x�˗/��[o����bcc��HII�S�Nܼy���~��'O��]�p���`<H`` �6;v�~��v�����\���w��7�|cZ��Ν;;v�cǎ�������ܸq�l�Cv�ے-[����@�F�R�5jԈ��u�V�t钩L"""""""""""""y�V��<�ܹs�ݻ7�6�N��S�N����mۖ��z���""""�����r�j֬I�f�X�b��#��d���Hjժeq;�-^�����5j�j�*����k��@``���w�}�ɓ'�P����8p�P�|ybccY�hQ�cW�T�U�V��~���صk��~ժU̘1��w�^Ǝ��eˀ�ML1���m�*U���~>���lwZ}�߿�g�}6�q�e�6"""""""""""""��&\�H�w��5�~�i�7oNrrr����d�L�B͚5���e�Ν,Z����
iEDDDD^ɒ%ٰa�������L�0��`�X""�8��f͚�sZhh(�F��bŊ.\���"""X�z���q�D@@�?�<Ԯ]�����;w�:��ѣ�X�"NNN��*�_�n�7��DHHW�\�k׮DDD�nݺ��ѣ���96nK�?�7��~�+W6k#""""""""""""��[;��Hz������2mҷo_�O?�Ā����y�;vl�n>�m���1c5k�dȐ!DGG�p�B
*d�h""����n�=e��L�bڞ0a&LH��Cv���?�V�Z��Ο?@�ڵ���ԩcv�{�����]�xq�޽k*6l}�aaa���1{�l��������u�����-�|�2ŊKUg,3������Kpp��c��d�%"""��&\�H�e0��_~��ѣ,X��>���ݻ����رc�?>�Z�bŊT�Z�ڑED$.\ȩS��裏�ED$W�߿?U�V��ۛ-Z�f��|�Ik��slllj�{'P���!�~ڵk����w�f�ڵ���̚5�%K�0h� �t���z���`0�������a�m���6�B�Ʋ�=�""""""b���AAA֎!"�@����Y���1DDDDr�&\�H�����|�r6m��s�=���Y�x1}��e���ܽ{�ŋӣGkG�,ضm���֎!"�'�nݚ��p:v�H�z�X�~=/��c��dHDD��o߾ԪU�E�q��‹/�ȼy�I��e�r��Ybcc�Q�F��ʗ/ϩS�8r�
40�9r�r��e���ŋ��鉧�'����ر�ŋ��_fh��lll0���S�hQbccS���-)]�4.\�ڵk�.]ڬ�ڵk�6""""""������v��s�&\���H����d""���)S�<y2����j�
����ƍc͚5�nݚ��M���bccquu�v�<�jժ���Q�zu�4i��ի�ID$�"##�U����G�q��L�:�.���Ȕ)Spww��^3�kѢ'N��ѣ$''s��Q&M�@ӦM3�������;+V� !!��U����X^�̙3<f�R�X�f
�n���ɓ|��gY����U���ӧS�Xfl#""""""""""""�i…��:AAA�;��'���kV7x�`ʕ+������ɛ���pqq�v�<�T�Rlڴ�7�|�.]�0i�$��c��<Pn�pѫW/J�.�ѣG�ر#M�4!$$�>}��ڽ��[T�X�������������T�X�L���[o��g�ѬY36lH@@/������///:u��1�C���+�6m�믿Nɒ%�<nK}'k�׽�eY��"""""""���닍��^z�W�z������ "r��;w���O���;vl�z'''&M����C��N�:VH)""�ʕ+\�|�*U�X;��H�cooϬY��Y�&Æ
#::����S�P!kGI�,���̶�ҥK�p�B���8@bb"������ѺukS�bŊ�p�B�Ν��ݻ�t��K��u����Ӈ�ŋg�o///���			��ɓ<���4m��4`�ȑ̜9�.�����1����-۶m�֭[���3~�x^~��,��R�/��_}������7�4;�}�(Z�(m۶����spp ((��1DDf͚5֎!"""����(L�%�;FӦM�ر#�}�����14lؐ…�s��G�RDD�CDD���#66V�\��<��[�ҭ[7�W���ի)[���#�Hc\��x��ے�͙3��f�*T������ܹ3����w��VN("����LDDDr�~""�Ypp0��������o,��,"�;w�:P�n]�&[$&&r��!���;ƌ�+��Bxx8�v�bÆ
VL-""Y���=+V�v�<�]�v���O���ԯ_�_��ڑDD$�y뭷x��'�n�	

�\�r���Ê�DDDDDDDDDDDDDr�����\�v�:P�X1>��֮]˱cLj����ѣ�<y�������Q�5j���>�f͚���֎/""Yp��I*V����������yիW',,ooo�4i’%Kx��W�KD$K���s�9r܂��ٙ?��w�y��={�n�:�O�N�B���NDDDDDDD��…<��֎�W� IDAT�,��|""""�6M��JJJ�dɒ��F�aoo����=�>>>ԪU�Z�j��ꊽ��m���>>>4k���1DD��{�͛73d�����8q"cƌ�v,�'�֭���:u*�
�C0DDDDDD$�BCCY�x1����>}����x�	4h@�^�x�W�񑰱��`0d�q��7,X��]����%>>�bŊ���F۶m�ݻ7�+W��>�ϟ��ѣ�r�J�;����s�S��>�sYD��`0���Ӽys{�1�t�bZ�������DD$U�\9G>�)��3g5j�`ĈDGG3o�<�n-"y�V�Ƚ|||���v�C.^�����6mJUw��9Ν;�ʕ+�СK�.�x��VH�w%&&���2g��޽kVw��U<���<y2Æ
c�ĉٺ�|߾}��X�AYt�DDDD�a�Z;��\666|��'�޽�U�V���K�:utC������C:t(6l`�ڵ�nݚ�/Z;����������0��7
6dӦM�/_��S�EBB�o�&&&�	&P�X16n܈��'���֎�g$&&Ҿ}{f͚���o��&�7o��ŋܹs�K�.�m�6���0L�:�W^y�;w�X;�#��ϕ�`��""""��&\��������3/���…xxxe�H"""""""""R���Ջ�'OҼys���x��w�Q����8::R�Z5ƍ�O?�Dɒ%ٳgs�̱v�<c����ٳ���Y�x1/��eʔ��ޞ�{�6mڰp�B���)_�<۶mc̘1֎���\������҄�|��g�%,,�
*иqc6m�d�H"""""""""�CN�>M߾}�X�"NNN�+W___���-����y��~x{{S�Lqqqa�رܼyӬݾ}�شieʔaժU�,Y2�ܵj���>`�����cbbx뭷�P����T�P???N�8��~��gZ�j���3�J���ӓ�Z��ĉ���WWW���(Y�$u��壏>��ի��l��d���ơ7��E��m�6�ԩ���֭ˆ
ppp`���<yҬ>��V}Z�i�Y�p!5j����2e���o���6KN����+���^���/"""R���ɚdK�,�v�L�\�2M�4�v��n߾M�������ꫯ<x��#�H>���@PP�i{���m�����ooo��g�~������X�����۷o;v���
*�ʕ+�С�Yyz7�8;;���`�^�x1o��6)))��֩S�}��Q�H���Ǽy�?~<�q����a����ԯ_GGGS��
��֭[��)R�k֬�M�6�F�-HLL4�wttd���4l��T���?Ӻuknܸa1_�ʕ	�lٲْ�[�2{�F����ȑ#����-f����̝;����O?��ҪO�s�)S�0z��T휜�X�b;vL���͒S�*���̹�w̹������)��""""��!���K/���������:EDDD��8q�����0p�@Ý;w�GD�	����ٶ�����^z饗^Yy����m�G������ҥK�'�x�`ccc>|��ĉ�[�n8`�ݻ�����P�D	ß���~'N�h��(((�T~��I����0���������{��5������M�kԨaaaaY>����hѢ��ꫯ"##
�o�6DFF^}�U`(U��᯿�2�Ϙ�F���^{�j���7�޽����b:t0ۧq���ЧOÉ'III���î]�Lc0`@�e�WV�_�z��!444S�t�Ν�P�~���H}z�����
���0Cbb�!**����i%J�0\�x1G��Թ��q�_���FAAAf����o��
666L�6
OOOkGy��Çcoo�ʕ+�EDDDD
�իWӳgO7nLHH%J��v$���pɏ��MDDD�-3+\L�4������>��T�#F�`ڴii����ѴiS���5jS�L1Ս3�)S���o��?��A�z��\�2��E�%>>�k׮Q�x�L��?L�8��-[�}�vlmmMuw�ޥM�6�ڵ+ո�O��߿?�g�6;�]�hժ%K��ʕ+�rggg�r�
%K�4�'**�Z�jQ�|yΟ?�-��U++ׯT�R\�z�˗/S�T��Q�|�2�K�N5�̮*����u�j���8;;���=G�1�Ǐϱ,9u��s\�����V������DDDD�`y��V���evED$g���k�ٳOOO7n�ڵkqqq�v,�G�O�Nhh��c���dZ�&M:t��c����dچ
<x��޽{3m�4�nݚ愋k׮ѽ{w���y饗�4i�Y����8p`�}���S�d}��-࿉Y�m�6F�mv�9���-cƌa׮]lڴ��
���~��\�~ݬ�駟�ĉt�ЁA�ѬY3�~�ij֬�j|��^Y�~��}��q�ˍ72���?~�٤0?G6l0����r�\��r�{_DDD��ʷ.6n�h�""fʗ/�/�`�""V�g��T�b�""Vݺu9x� ���*�^��&M�X;������,_�oookGɰ�˗���`�""""Y
@�r��mw�ĉ4��˩S�puue�ҥ��ٙ����P�v�e*^�8W�^�ƍY^eט�x������l�suuMUV�H�U���ӫW/8����nDoݺ5�:u�cǎ8::f[�{e�.\��7of��^�zx��0�ռys���� &&&G�ϩs������}��*�N�2d��#������Ԅ)𒓓9}��&\��XY�
سg={��M�6̟?��={Z;���>>>Y;���H����Z;����H���̶���o			�X�b�]��R�J�js��M �7껺�ALL
4��>������6&��i�$_�X1���-�*T(C����Q�D	>��:�ٳgY�h�-��Ņ�[�����������ơC�����aÆ���ѣT�Z5�<���b�q	�{+��Թ��q�����HA�o'\L�6
OOOk�a���֎ "�+�9s���d�OV�G�H�"�X�����|�M~��7>��Slll�MDDDDDDDDD2�H�"\�~��W�fz5��~��w�y�,YB�5���ƍܼy3C}4mڔ���lْ�	���;��գS�N,Y����W�r��5{�T�W 0>��a���k���k�9s�;vJhh(���;qqq6�u��e{��\��m�r��!BBB25�`����n��b��`H��pbbb��oIZ��9*Y�d�fɩs��qeDn~��T�� """"�q	\+'[[[&M��…��/x���3��5����駟2�_bb"ݺu#!!��>�(������cw��
�ٳg��֟�իWs��u��}<x��>���f�KŊ�ի,���_��ݻw�H��\�޽{cggǜ9s2|M�9B`` ����������w�XBBB�����2�˒_~��byXX�k���,�}��2;�����}��J.DDDD�9y�$�J���4�???�m���ݻi޼9����#���)ǏO�.$$�#F0b�BBBa*)ڷo���~Jrrr����lll�С�Y�ȑ#9z�(^^^�7.�>Z�l	��R�EFFbccC�ʕMe��קm۶\�p�7�x����F�Νc�ԩ���2r�HS�K/���)S�{���>w��e�ԩ@�+dF�ʕ���!***U]�F�R�eg��\?WWWLbb"�۷'"""�><H�HJJb������՗*U���~���i�8A�sp�/��"UYJJ
�'O�K�.9�%�ϕQfǕ�se���""""�&\�H���?�X;��H���-DDr�f͚F||<
4����֎$"�'�����Z�;|�0�|�
�F�b�ȑ̘1�#G�<�""""""��
8�%J��~ڷo��ILLd׮]��׏�={boo�ĉM��[���3g�����wߙ�,aɀprrb�…��������$$$�s�N�j~~~f�̛7���M�6Q�V-fΜ�ɓ'INN�֭[DFF�����ο��˸q��V0`Ŋc׮]xyyMRR���xyy�{�n
.���v��ooo�m�F||<���DFF����obDvg����n�oӦ
�ϟ�Q�F��Ջ�۷s��%������ٺu+~~~4nܘ����-ZX�(ФI���Khh(������1b�f͚�f��E��j�*���IJJJ�f�ƍ�����Đ���ѣG�ر#���<��3�V�ȉ,�y��:���+���)�l���!����
ӦM3-q���b���DDD�j�*"""8�<)))�.]�^x��]�����o�|��	�=����(R�O=��5�G�<���9�';ǕY�۷�ĉ�_��5j<�}TT�������iӦL���X�r����L�<���@6|�p�M�fڶ��g�ʕ�,��Hnйsg���Y�t�����H�\�B�n�ؿ?��=�����#�H.f�hdq� pwwH���[�n���M�v�:t(���;v�`���8;;?�""b�~����Hn���O6n�H׮]�u��Y�f1`�Ӷ��;����s�{KQ`` �{���mF
6d�Ν*TȬ<22///N�8�fvvv��G��[�~=���ܾ};U���?���;w6+7NI�v(K�ׯ_��Ã�~���>*T`���T�T)G�e��%%%1f�f̘AJJ��}�s<x�`&O����S�����6mJbbb��y��ѷo_��[�l��ݻ�ʌm�c
		�_�~\�rŬݓO>�֭[y��r<d߹��2r��͛����������u�����H~�.r�K�.����o���eˈ��#11�;w�p��6o�L�޽y��y���)))\�~���h���[^z�%֬Yc�X9ƸdaHHH���yyy�X&k��֎!"R -Z�(ݧ������*U�
6гgO�v���n�H"�����&*�W.��ŋ�'}�O
�x�".�b2�o:t�#G��駟���%Jжm[�nݚ�f��<���ߟ={����/S�dI�^�:&L`׮]�&[ԪU�cǎ1o�<ڷoO�r�ppp�P�B���ѯ_?>lq�@�N�8t�=z�\�r���S�\9�|�M>���*^�8�ޣF�8;;coo���+�.�Nu�yvf��3rttdڴi���0v�X���)^�8vvv�,Y�
0n�8N�8�W_}eq��9������T�R8::ҠA~��G���f�Ҿ}{�)���=O=�T�6����޽www���R�
�F��رc�&%�d��:WYWF�սr�{_DDD� �
�Ŀ��K׮]9{�,e˖��ߟ-Z��SOagg�ٳgٴis��%>>�
��cggg��9&'V���X���\�v��Ǐ�h�"v�؁��
���ϱ�D����?��C�ƍ)R�aaa����xxx���)S�L��{�����(�p!""""y��_ͻ�KϞ=�;w.���֎$"�LV��֪9���e��鄆�r��-\\\x��7y���S�IHH`��l۶�������_~�޽{��Z�4��7x�Wx��9s�Y������dÆ
+V,G+""�.DDD$���'��=h���*��+��…���4Z�"�=z4gϞ�A���,\]])T�T�R�A��b�
�/Nxx��#�
���)]�4�52-=h0 ))���]�2ehڴ)ׯ_g˖-�ݼy3ׯ_�Y�fY�l!"""""y�;����Y�r%�ڵ����֎$"�e�����ݛ�7r��u�ܹCLL�i�Ž����߿?�/��?��Ν;���_2l�0�޽�n_[�l!!!�F���kԨ			lݺ5��&"""""""""""""9��N�8�<4i҄�ի�����É�������偯�;v������N�j�hѢS�L!!!����?�̞={x�ǘ5kŋO3����G�`ٲe�����9r$�5�Z�j4jԈQ�Fq�ԩt�p��Q|}}�Q�u�ԡo߾����;u��ƍ�e˖T�^�^xOOO�O����-��l���˨Q�FQ�fM���o6m�dVg�:߾}���@�u�Fݺuqss�nݺ���ۄ��g�������X�y��իG�j��ԩ;v�H3s�.]		I7����>;ǚ�׌q����ѪU+-Z��2��~�����������V�Z�.e)""""�������߿�ӧOS�~}bbb�ID$K���8w��˗'00�0o�<�x�Tm�,YBtt4�j�"88���pBBBx�8x� �֭�WĈ��0m�߿�g�}6ձ�e�6"""""""""""""�{�[;�5������ݛ�7o����֭[ǖ-[�5k-Z���1*d��j�*ƎKJJ����ٳ̝;�}���l�2
.��5k���dɒ�K�.T�Z�ڵk���ڵ������h*���Y�j�7ofΜ94n���1�9����o����}ǎ�ݻ��K�R�NSۣG�ңG���Mew��!**���(V�\�ʕ+y��dz%�r����ңG�{�=v������f��x�w�NTT�Y�իWٽ{7{��a޼y�j�*C}g����ү_?�}����ׯS�N��O�6m(Q�aaa�={���~:U��g�Nɒ%iӦM��Ւݻw3h� ���>}�	&���+'r=�{u̘1�,����SDDDD$�{���s��4jԈ�˗Ӻukk��<���=C�N`�n�v�   ���_|�q��1t�P��۶m`�ĉ�/_�*U���ҹsg6n�H�Ν�����T�T)U]�ʕ�ڈ������������H�U�V��z�*�
">>v��Itt4+V��7��Ν;6��/����5r�HS��I�L�>{�,������Þ={8~�8?���*U"::��s����ܲe�����wwwLe���C�%11�6mڰy�fbbbؼy3mڴ!!!�!C���?�X<�1ch޼9!!!DFFLŊ�s��|�Y�O>����x�u��Ν;9~�8QQQ���ʹs�>}z�e�WV�_f���n�9s�EժU			!**��~���+WR�N�f��P�Y9Gׯ_gذa�}�l�BLL�ׯ�aÆ�?�b_���t��������-�Y�|9��N�:���c����˦����+l۶�4�&M�0s�L��e6��k��mc�þWO�:ŦM����_	��ɍ�x�	v��I���i߾=s�̱v$�L9}�4�كE�I�;s��������^�IZe����+V,U����FDDDDDDDDDDDDDr�7�b�ҥ\�t��@�J�prr�N�:L�8???nܸ��%K�=��Ç�6m}�����TLRR���
&L੧���ޞz����_�[���?����5����HHH��ÃٳgS�jU�Z�*�g���Ãk׮��[ܿ~��̞=��u����L�
L�H:d��8a̘1T�T	{{{
*D�
L�3�oߞm��]�/=�ʕxऍ�k���_P�n]
*���#/��_|�111�3+�hٲe\�r��
2{�l\]]qpp�F�,Z��jժ��_�.]X�r%w��5�KIIaŊf�s��,]��7nТE�O�N�*ULc	Ls,ٝ�a߫���͍�E�R�l�L��ܯP�B�0p�@F�a����HZ"""�^*�I��l����m�w�ʫ��ik���Wc��~EDDDDDDD�����W�:.I_��p�k�.z��i���7�`߾}i�ƍ6����5kƨQ�����@�=R��s�Ǟ={Le���.\8#1
@�~�R�!��֖~���{�n��[:�?�<����		����]������TW�jU���駟�-۽��=���III�ۻw/qqqԬY3U�SO=���>HV�ю;����Ύ��_�ڵquu�…��վ}����qss���w�����o�����Ύ���[�/�s=�{�~���KD� ������M666�?���`fϞ���'7n���� IDAT�v,�z�����_���߆�}��~��T�B"""8x�`�}�.]�k׮��3�ۈ������������H�eo��Zll,�;u�T�u�;w�J�*��W_agggV��i�}��e*Z�(ׯ_'>>�bŊeh���'Iܯv��f��W�R�Te�	 ��9p�@F���Ç9|�0���5jD�֭iժٖ�^�q��֭[��%�Ξ=��ί��ʯ��Jtt4��!e���������/�ۧ��S�L!$$��͛��CBBL��<�X-1^�Z�jY��x�����U��""bY�r���y��7�EDD�A�nݨR�
���*�7���bŊ֎%"���m�ǤI��0aիW��~3��z��-[�h�"=z4U�V��ի,Y���www�̙�7�`0p����jժq��N�>�jb��s��V'�ܡ�M����̶[�l6l�H�"̛7�%J�j���d|ŊJ�*q��1���2tc9@JJ��D���x�4'l''�ϸ�CFt�҅bŊ��7��_��ʕ+Y�r%+V��3=5�a���a�_F�={��e�>��
����M�dUVΑq�iM)^�x�}v�ܙ/����۷s��e{�1._�̎;����s��f�k���_�H���J�Js�����Ugg�� "�_]�r��/f�竈�����'<<�N�:Q�~}V�^MÆ
�KD�"___6o�̩S����K�����w���ѣ�V�-T�Ç7m�*U�˗/���E�r�X�~=�7fϞ=DFF�z(Fdd$M�6͞��������������H���v�G�xC�#G���K�u�ĉT����2a�lll���/quuM��ċ�W�����P�?���_|�#F�ʌ7�߸q��>ׯ_7��ڵkǺu�طo�'O��ۛg�y�3g�0a„�0�/���Á��f��u��1t�PΞ=������>c�ܹ�ر#S}f�=h��ʍʖ-K�ƍINNfժU�Z����d�5kF�2eLm�s��<h,i}-ew�G�u$"R�W3�Z������Hv�X�"���~���jՊ~��ڑD$��� ""����̼y����dɒ�������������mѢE	��LJr��aggG���iѢ�-2[�b�ȑT�P;;;���x饗(\�������GѢEi۶m�XDDDDDDDDDDDDDV�[�R�JDEEq��!�7o��n߾�;�í[�>|8mڴI����h~��w�֭��cw�ؑ��@����O�)�F[�n��͛��ؘ�*V�Hdd$G��Y�f��9r䈩]v*_�<]�v�k׮�ܹ�>}��#ٲz�2*%%��K�кu�t�Μ9�O>���ݻ��]�x���w�bk��ܦ��#777"""8v��'"=z4�>�v��޽{Y�j�{�fŊ����+;�j���+��ȑ#�h�"U�q%��ew.k}���������{��H>U�hQV�^ͨQ����y��׳�����c�������_<���f�ŋgĈf=��]�v�k�ά�H�"����`�Ο?O�
8�<G��_�~^WDDDDDD 88���`k�)p
܄��͛�̙3iҤ	vvvf�6l`�С4oޜ��@S��I����ᥗ^bРA����Att4!!!�&\������T�P��{����ФIBCC2d3g�L�	�.\`������һwoSy�f͈��d�ܹ4i���Ɩ�w�2�|7n�����f͚q��y6oޜ�)�/����ٕ-��/����KN�8A�J�hժU�mO�>
@�ΝS���wbb�����sԮ];"""X�`M�41��c0���o���M�6/^��Ǐ�v�ZN�8Aɒ%SM(�αZҶm[>̜9shڴi��j����������j"ƣ�:)hN�<I�J���/p�~��vvv|��ܾ}[�-D$Wj֬			�;�v��Q�hQN�>��ɓ�S�N����[o�a����=z4AAA�+W�=zdk_""""""��
:����EDDDDD$��;�z����/�����#G��z��>|���׳r�J���9r�i��۷��S�zu�N�jvc�%���,Y��+VP�L���(R�G�ᣏ>R� �駟ҹsg�����/���o�M�-(_�<w���̙3�ٳ�o���+W�0d��}�Y�>/^LXX`ԨQT�T�ӧO�����3={�|�sةS'�̙��?~</��"NNN���1i�$��'�3[V�_zRRR�t�ǎ��g߾}�����g����~�˗����L�4��C�R�T)N�<�ܹsY�z���իW8	!+�[�n,X��}��1x�`�N�ʕ9u�_|��~���x�WX�t)&L���96ִƿh�"~��gz����ѣquu�̙3|��W��%��\�&>>�-[�Ю];�޽����#�:)hN�8�j�����ONNN֎ "y���{�7""�:�b�
>��3>��3��R�Jѷo�l���ٙ?��w�y��Yºu�>}:�
�־DDDDDDDDD�`8s����֎!""y�����#�In�Eٲe�ꫯ4h?��^^^��|���ԨQô=c�bbbx���<v\\�+W��?��c���̞=۬]�:u�߿�Y�SO=Epp0�ԩS|������cȐ!6̬��'�dڴi<��۷�}�v�zGGG�M�F�
�̟Q`��������[o��/[�,cǎ͑lY�~�rqqI�����/��~���ҷo_

"((Ȭn���㏜:u��G�R�|�t���sT�Hf̘����7of���f�L�<�1c�<p�H�.]X�t)W�\1m��X-)Z�(�f���ߟ�{��V1�:u��I4Y�U�V-���<x��,..�~��4'O�L��(��6z�h*V�ȦM���?HJJ�lٲ4lؐ޽{��Od{�u��e�L�:�A�Y\!VDDDDDD$=ӧO'88��1DD�kG(�BCC�vɣ��;k
܄�-Z��?2w�\BCC��pvv�v����Ӈ&M���?s�L���r��̞=�Çs��-*V�ȫ��J�>}pttL�����6mbժUlٲ���._�����˗��Ã�={R�Z5�}�nݚ���3{�l~��'.]�D�ҥiܸ1������5�㰤hѢ�X���s�m�6Ν;ǝ;wxꩧh۶-�����˱l��~鱳��x��<��34m����ۭ[7���$66GGGj׮M�^�hٲ%�+Wf�ȑӾ}�/+�nݺ���̘1����s��%�T�°a�hѢcƌy��ԩ���qqq���Y�6�ǚV�
60s�Lv��ɥK�x�g<x0�:u�8�"���L���㉈���۔)S�T����DD
��/�{�����<PDDD����|||r�K�ѧ�������?>>>�D("b
�����?�
�""����pl��'���
ӦM����o%�{�E
�3g�вeK�y�T+5ȣ7|�p�M�fڶ��g�ʕ֌%"�H���<p�%ɛ�.��aݺu�~L���>�����LDDDr�~""���M�m��oK�����Ϗ�S W��j֬Ibb";v�r�ʩ�-[@�Z�q2�4�B$�Z�~=:t�r�d�ƍ֎ """"""""""9�̙3���[;����R���֎�/h…HU�vm���2d�>�k���ɉ�gϲl�2�ϟ@��ݭ�TDDDD
�0("�{�m�ִ򢈈�����HAt��q�U���		!,,^��GMD���P�JH"""�ӊ�C.D򨀀z��Att4=z�HUocc��ѣiР�҉������HALpp��c���d�����#����Hy��wٳg���Ç��7߰l�2o��nnn����<���}��VDD��	y�H.D�5k�i�&���[���ǹs�s�eʔ���???�ԩc�""""R
2��DD�1c�#�s�Сt����+""�*V�h�""""�C��ٓ�u��Ǐ�k׮�+W///ƍ����qvv~�1EDDDD$�p!��=�䓌7��1DDDDD�lܸ�:X9��H�d�>l�	"""""""b=���VY�A2g�…\�x�nݺ�ʺw��ҥKY�p!�b:��&\������H��6m���֎!"R �mۖ�Ç[���ӧl��EDD���AAA֎!"""�'�����ޝ��p�Gd�+�%�Pѯ-��S
ըP�T�jM-��6��U�ZZԾ�	�-	Kb��%�$�
b�,��������,7��
>���#�̙�ϙ��d�|�aѢE>|�gϞaii�g�}�1(O\\˖-c߾}<x��~�:0t�PJ�.���$�lܸ��s�r�����pttd�ر��^�x��e�سgw����+++�u릚�S�V��O�<��~ٲe�?kkk�,Y�eҊ��ڝվ���ظq#-Z��r�ʪ:U�V��֖�72p�@ʔ)�ۉB!�У���V�j�0
՛�f�;�p!�B!
LZZ�n��wޡX�b�G!�B�*��UӿC� �B��z��!�
"66VUɔ)SHKK�k׮<{���?����hU������9~�8�V��dɒj�6lO�< ))�-[����<==X�p!����~JJ
gϞ��ٳ������s������vk�{�nhժ�ƲV�Zq��q���CϞ=u�I!^5����]����P�_�NZZ�+W��Ύ��ӥKC�X(���HOO�۶�155�B�
4mڔ���ӯ_?�ǡg4mڔ�M�һwo7n�e������	�Ν;��:m����˙0a�=*�x.\��ʕ+ٿ?������S�L����ر#C����R�ͮ��9�&�[
!�B�s��U,--	7t(B!�B!�B!�B�֮]Kll,
6��Ϗ��駟�j�*U�?�����h�W�ΪU�8z�(+W��Z�jDFF�f��mתU???>���;���W-���`��=z������i�&@}F��'Oj�\Q�N>�O?���vg��Ç���jlW)S�!���޽{899Ѷm[V�X�ŋILL$99�[�n�e�>���t��ӧO
�k#99���0`...�x���a�V��;}�t~���l���ӧO'00����B�0����Ǐu�III�5�F�1g�N�:�ӧOIKK����?~�iӦQ�^=���RRR�C�Y�:^�.(^��n���1]�B�	"##���2p$B!��q��}*U�d�0�B!�B�����Uy�$}


�o��f͚xzz�f�P(��������q��|���xxx�o�>F���΄	T��߿?�V�R�x[�dI�={������888ЫW/z����������}���t��2�$3e�f��B�n�޽K�V�����Z�j|��W|���Ԯ]ccc�^����/�f�"  ggg��������Ÿ��Jll,[�ne����t�RF�a�_ou��%((���d��g<����`jժ���
���0kCRR�;w&$$���+͚5㭷���ӧ�:u
///֭[��ٳ�����Ĥ��+
�H�k��PPPAAA�C!��M�
(_���CB�\9y�$~~~�<y�۷o���FŊiҤ	�z��>0t��BI���������iذ!666899i�Mq��8�<����{��-�$CcccJ�*E�5hժ�w��v�=��<���ܹ3W�\aǎ4l�0��ϟ���kkku�_Vm��1��q۸q#3gΔپ���IAv2�ťK��_���e>>>�{���=�{�.�ЄB!�B�\�����Wq��m�e�EFM�6U�NF���-[@m$�c���?FXX�/���WWW���s��ࠫܶ[��P�L�eJ�RG!^7�&::���۳u�V�����gҤIt�ޝ�m�’%K���0Pį��ŋS�jU����9�fٲe�pQ����?>���Qc�������>c������7n!!!XYY���QQ�Bqtt���ggg����8q"s��5P��M��&\�3�B!�PI�z��B��|��7���h,���a׮]�ڵ~��wJ�.m�(_M���'$$���"##�}h��o�\�����4�>}JDD�[���ӧӽ{wC�V z��Ɍ3����~ȱ���=z�(��
WnF4o������������,\��M�6���N�>}����I�&�T!�B!DQ���JC6`dd���3&Pd�q�bm��ԩ���8p�m۶��?��h�"֯_ϨQ��ٳg���jv���t�>���5���ʺŊ�X���
!���L�6�]�vq��]*T�@�����:`Rn�?�Gz?y�$3g��<y�w�y&M���N�СCR�R%������Q�F̘1��Ç�|�r����/��/���i�cǎxzzj��+==�'N0q�D�=���9m۶eҤI�����]�r�9s��͛7)Q�VVV8;;3f��m�5���z�r�W�^<����r�8]�v�=zp��E:t�;�վ���N��޽{y��1�5���k׮j�F�Xt=>��ϼ��/����_k…����^v�N�:ϸ^�{@���Q^c�v>/\���e�(]�4AAAԮ];�cмys���y����?>ԩSGk{V�^ͯ��ʕ+W(_�<:t`���4j�Hk�jsV�iQ�	�zm.���KC� �jlmm4h���B�B��G�BE�����Ջ�7oR�J���qpp�F�s��MY�t)`�С�[�cccC��J�U�������h��599�#G�P�zu�hw���A������.]�Ě5kػw/�Ǐ�\�r3���Ht�ޝ_��m۶��w�aff�e��ϟ�}�v�������:K�?Eef@k�@bb"�'O�W�^XXX/�&M����/%J�(�0�B!�B�U�R��7o�m��jժq��5N�>������������uU�lY���qvv&""��{��v�Z�Ν����̌��HOO'>>^�I822R�^nۭMŊ����ɓ'T�XQmٓ'OTu�"�:�'�|�ӧOUe111x{{���ǖ-[prr�i���Q�]���?����4UYtt43g�dϞ=:t�R�J�~�z�N�
rܗ��666�����qqq!11QU���v�Z6o��֭[�vr8v�$%%���Ď;ؽ{7�e˖��'N���?$..NU���̩S�8u�k֬!,,�*U��%��
�)RRR����ݝS�N���}AAAt��Mm���p�u�Ɵ��c�YŢ���|��+(Y�$���̛7Oc���?���t��!�v�u���M�\�z5/^�`���9&[(�4i���;K�.e�ʕL�6M�ί��ʄ	T�ccc���a۶ml޼�O>�$�m֦(ߋ��i�J�&0tB��')���M�6ݳBE&L��͛��ٱk�.�Bݺu177��Ą:u�0j�(6o�Lٲe9v�^^^������@BBǏ׺<,,���
7�BR�xq*V�H�V�X�lC�%==OOO�#��*U�D۶my��)�w�ζ�]�x��)�ڵ�R�J��04[[[ը��?�W��޽{���WU֯_?�ݻ��ի
�B!�B�]�֭�={6111$%%1k�,lmm���OU���~ӧO�̙3���r��~��ڶm��u놭�-�7o&!!�z��amm
h��ƍ9n��`�֭$&&͌3��nm��_�>�rT�̔2��B��Ç�իqqq�7�+W�����ѣG2d��ɸ��r�������5��O��Z�b�
�W�^eذa���1|�p�^�Jrr2�nݺ���3s�LU���P�t钫6���ѦM�وbbb�۷/���t�֍s���sΝ;G�n݈���w�����hݦ��;�1������s����HNN��V�;n�8����/�r�
���$$$��~6lȵk����[Fy=������9��+W8{�,O�<aΜ9yn��ǏquuU�s��y�?ΩS�rZF� IDAT�С#F��1Vm����z>u�����:t�ʕ+\�rEmم����}���,YR�y�g���g����76m��:�֧O����.���ﱷ�',,���$Ο?���3ϟ?g��ܿ?Wm֦(ߋD�xmg��7o��ΆC!(^����
!�V���DEEQ�n]C�"�(bn߾͢E�		!66����ӲeKF������ị̆؟={��K�F\\899�����ĉ���P�B-ZDٲe�܇��5&L`ҤIlڴ��>�L#�ŋs��<x@Ŋiݺ5�F����2�vEEEq��fΜIxx8fff�hтQ�FѸqc���]�Ɗ+8|�0w���ܜ�5k��舛���6�[vt=
֮]���U/#3ڿ��^v	-y�~t=���&��9��o8|�0�ϟ'00�nݺe���ϟ���Ş={�r�
qqq�)S�&M�0t�P�Qs#/�Ddd$,�ȑ#<}�kkkƎˇ~�5�={r�|||�}>��㣪��fu���������CjԨ�g�}���[���%�����3ƒ���1b��Ѵlْ�˗��ɔG�L/^�`ٲe�ٳ�;w�`bb���ݺuS{���z			�\���� �߿��o���̐!CT/3���S\\7n�E�T�\YU�jժ��ڲq�FH�2e
�	!�B!�y0x�`���8s��(�_|��A��o�>nܸ����Z��5kj��ƠA��>}:3f��H�h֬���z��ңG,,,رcG��tpp��Ϗ�~���~�
�V�Zi��m���u�ք��p��9�8Ν;�-E!2Z�t)������S�󮽽=����)S�y����d�;,,�)S�/�m�����-Y���ϟӧO/^�*o۶-6l�E��[���~�	�/���w��s�,X��g�����X��c������燣�#���g�…Z�ծ];�X۷o�����СG�Q����0k�,ʗ/�L�spp��LJF��m�6-Z���2���(11���(|||T�o�;Vk�I�&ѨQ#ջǼ�o������ҡC�u�6mʮ]�h۶-aaa�ƭ-��]ϧ��3srrb�Ν����g���u���Ʀ�|*I)�����|����
4`߾}��y6l�_���qɒ%L�<Y�}*��H��v�!�BaX�?�A�4h�С!��'N����ƍ�s�)))ܿ��۷����B������gϞ���#RSS�y�&K�.�O�>$$$��nݺWWW�É���ٓM�6��S�߿ggg���/�޽Kjj*w����Ϗ�]�r���,�y��i���KXXϟ?��ӧ�ݻ�>}��V�̙38;;�a�nܸAJJ
qqq�?�����]����2������D��Ċ��ߏ��Y�S��g����P�X1�޽{�����ӦM�ĉ<~����4?~́�߿?������rM���ҭ[7v���ÇIMM%""�aÆi�<()W�aaaܼySk��7or��1ʗ/�����۪́T��>iii\�~��S��d���D\��ٜ8q"�ϟ'11Qc�v�{.dŊ��iBBgϞ��VK��m���d��ڵk���III�Ν;�Z���c���ŋl�ٽ{7			Z;q�jՊ����٣� �B!��s��I�@��bŊ�^��N�:Q�LLLLx��w�9s�ZG�2eʰz�jz��M�ʕ166�r����׏5k�d;NVz��)ShР������bee�����(��Ǐ�z���8��q��ի�ʕ��ԔV�Zi툗�vk�G}Dɒ%9t��v:D�ҥ�ر���C!2R:u{xxh]>d��l�9>y�~������G}���H��*?r�H�ummmIOO��ի����DJ�.�CK�/g�W:8+�+�ĉԺ��Q�4���}�>}�V��;�/;�{yy��백�!==�۷o�-���{����4�J�,�{��ԩSIII�믿�k׮Z�o߾�FY^ڧ$9N�8Qc��ŋ��k�N����z>u����Ν;�ʕ��%\�u���Ʀ�|*1�+WN�X�����.�<y��{��1*�Q^�{�(�p!�B!
�[o�Exx��#n!^_�?fԨQ������ξ}����`�����Ӈ��Ǝ˽{��֋���?~�jyƇ�7o���ӓ��4\]]			�ҥKlܸ�Z�j�ҥKU����|�A��`jj�����t���g���$%%���Ȯ]��x�"�v���ё�����KՔ��M�8�������ùs��f͚����p�B��?��3�����ۗ}��q��%Ο?���7u���֭[̟?_o�e����صlْk׮q��5�e���ܼy;;�,;��w���¢�l��Z��%K�p��y�ի����ϟ�…lٲ��M������K�rM<}���cǪ�ٽ{7/^dǎ�l�2ˑ_LMM��OHOO���Wk___����ڵ+&&&zm�6>T��K�.��ҦM�������r��Y)����k������3���M�������ѣ<x�o���M�6�\o���DDDШQ#���9v�>>>4i҄�Ǐ�}�v��/;�(I6�FwS�tI�B!�B!
K�j՘>}:�����ѣ�[��?�P�^�r�0a;v������k�d��G��;;;�~�z�9‘#Gشij3Dv�ԉm۶q��1v�ޝ�>J�(���~�޽{9r���ϧR�JZ����]�T)\]]9}��Z�۷os��i�6S�B�EDDZ;������,��СC�v�u��eÆ
�-����:��69u��
%^�crfJ�[f�fK/U��Ơ9J2�ѣG0`5k֤f͚<???�$��Ɩ�>�_f���ԭ[WWW����={v�u���}�;�-Zh]'��ز�%/�G��k��jժ���
�R]�O�<����ԫWO뵨(��\W��M�T~�����c �$.m���x��E���QQ���!	9x��!�g�fРA���oooz��M�޽
��]�v1k�,f͚Ů]��B!�Bhذa<`�ȑxzzR�V-���hڴ)ӧO��͍��8֯_��v��Ù7o�rjvggg�2ooo����ҥS�N�F�/^�-Z�������h�֟�IBB���,^��z��abbB�z�X�x1���<y�u��i]����g���4oޜ%J`gg�J"9u�Z]��ĉ�U�ŋ���;;;UҀ2��>b�H���@c�峲� ���q.,Y&�(�m���9sh޼9��昚�ҤI�̙�`^��M�6���#Z�l��ŋ�[�.&&&4lؐ5k�P�~�,�׳gO�l٢�p0--�͛7���g[�ٰaqqq8880�|�ԩ�j˪U��l�����Ϧ����֔.]�*U��x���V�+�� <������LJG�ѫW/N�<�J�Х�2����ӱ����ؘ:u���?�m<�.]^������R��B!�B!^m�
�jժj�gzyyaaa��W!�#���gUoŊ���P�L�m��[o��Q�ٳg@�g�P����<=55U��!;��𕄻��x�����s�o777���h֬����͛�Y���={ҰaC����[F�=���_���\�r///�ݮ�Ŀ��O�/���ʗ/�mYŒ���Ե�6NNN$''���ڵ����lg��½�u��ش�Okkk�D��:s����Ӻ����Z�\��=,/��HI�����9~�8���������#C���…x{{3x�`�����W�!�B!�(J���j]ާO�Ө+���;v,iii�k׎o��Fm�2�R�QQQ����ʒ���vr+44�aÆi�.tذa8p@�ڎ���?@�!��A��ݝm۶q��ղz��ő#G�[F�8JBž}��n;�����_��\X���ru��DEE�F�ɨF���rN�rM�ݻ7�u���1bD��kܸ1u��%&&F��:t��w�bmm�{�跭�(�������ؘ�Çk]O�q�g3��r�nƎ���aaa̛7�>}��j�*�s��z7n�^���1��{��@Σ�=|�@mN�R��B!�B!t�y�}}��+Q�?��۷o�Ν;ܹs��۷��?h'I!ěC)����Z;�+_iii�^�p�1c�`dd���iذa����{��m��f����˗�X���{?�Y�'O����x�Ė_�~�)��7ׯ_gժU����:�GEE1v���-?篠�}�:ʲ̲�VN�z|t9�y����X���oN	�}�� b�ر#>>>:�����uf5�ޤĘ�����{�(�p�eԸ)S��q�F������?�%))�ЩS'*U�D�ʕqttd����� �B!���t4������J�룏>�ڵkYn��ӓ[�nQ�V-~��7����_���ロ���wr3�LV�x���)�(+�e�m$s%$�#G�^����W_ѦMڴiÄ	ؽ{7)))z�-#}���իS�^=N�8�:�qqq�<yKKK��B_���8���D �#?���J����ܹs4h����ˑ�r#/���˗�]'�h*�����|H�|V�g�߶j�\G�5Һ�I�&9nCq�gSI�z��<yR�+���ЩS'�2e
�7&))�E����Ė-[t���5��KG###�$��eJ!�B!�B���7o�ȑ#�={6�g�fԨQ9>kB��Rf��8PWn$%%ѷo_����f�����
�o�������ŋ�F���_��ӧO՞�*�<~���u�;�VO_j֬��Y�r%�.]bǎ���I��-�� �}�����[�:y}/��㓛��6m�P�lYIOOg��ݔ*U����g������(�؆���1K�,�����ӬZ��bŊ��NV�]XX����(�"Q0���޽{ӻw�,�+n666+V��
-W�n��Ç�2ޜ��x��![�n5`dB!�B�.���dUoӦM���S�T)�-[�uz΄� �3V(�𣢢rU�	EI�6"9�י^�\��2�An��ٓŋ������l��ȑ#�ԩ7o��[l�)HIIQ����A��Ҳ��B���8�\U�R%Ǻ���888���СC��?

�y���\9M	��4Њ�ݻcllLpp�*އ�w�^���U��+��Vm��g5���)�"���l�(QB�}
�ʖ-���3+W���?�dРA<}���s��\OI�ٱc�F"�ɓ'�|讨X�"�}4$�L�#�B!�B�B�ߩ������ʜ9s�3g���3t8B��H�Ν�6m����}||022�i���9s�=z0iҤl���r�J�e�Ν���KKKU��Oǎ����O�>��z�ܺu�ٳgS�X1Ə�*W�5k�ƀZ/^�`���@�#�����###Ο?���U�Ve��-�� �}�~�)s����(==]����r|t=���צx��t�ؑ;w����ͽ{��СC��-�:ϊ��y�[ݺu��� ))�Ν;�{����qrr"99�#F�fz�lΜ9eiii̜9x��=��ڬMQ�����'\d'c"F�>}T�3&i������ݛ���J�޽�7o��:����\����̢E�8p ���,\��G���O@@�5�B�
���~�5J�B!�B��A����DEEe�u���u###�:u*FFF̝;W5jIV���mF-Z��СC����U�5k�W_}�*S:ng5�ӧO�b˯N�:�}�v:�̙3qqq�v��ܸq��S�Hl�9)��߯�oN	�ڿ���X���s�l[�$��S�o���ѣ�y�&VVVxxx0c��.]�޽{u�g^�����i�*U�кukRSS�����Ϗ��TڵkG�J�Tu��VmrjKV�}�U�
�]�nݰ��e���$$$P�^=�C����䶞r�����ŋ�����~��wlmm>|�����ƍ������g6Qʔ:B!�B!�B���#GR�\9>L�Ν9~�8III�߿�aÆ1p�@�/����U�l߾�?���������9θ;b����X�z5��=w��%!!�}���f�pssS[gٲe����ҨQ#������IMM%11�s���믿bkkKll,�&MR{�2b�ʔ)����ѣ$''A�=8p�%K����#��PI�sqq!((���xRSS9w�������[^�_A�K�����W�Ξ={pqq�…���AϞ=9z�h�b����|�Z?+J�ǔ)S�>g�0��(��)��4�Y�f�����۷iժ�&88����Jll,{���͍֭[s���&U(�ӧ/^$99�3g���'�J�ڵ5f�Ȫ���{�(�p�OC��B�
�Z����XbccY�b*T�/���vW�\Ɂx��9Ϟ=��L�<Ym��Ç���D�&M4�oҤ	IIIEjJ)!�B!ěM�M�ԩS:����sƌCbb"cǎ���1�}\�|9W��O����U��={x����5kp����>}Z���T�V�^�z1c����Y�|9�����-��/3[[[J�.MHH���<x��%KbggW(�ϭb�^>2�6�@��y���Ɔ
��G6��?���ٳg�ƍ���GGG��\r3�J^�	�c�ٳg���ն2�ի�*�b��̀��1�l�6J����̴�Sq�!�
4�3fЮ];Z�l���'͚5ӹ�������9s�`gg�G}ĺu�077gܸq���l*=z�k׮�n�@�t�JY۶m��x!�B!�B!�k�z��x{{S�D	��݋��%J��C�,[����d�ϟ���~^>�.]�4FFFZ����cѢE��/�P�jUJ�*Ň~���iٲ%�~��Z\����߿�z��q��U<<<�����Ą�%K��{�1a�bcc�2e
?����5j���333�mۆ��
fff��ذm�6������R�Wʏ��w�}�.ЩS'J�.���	��w�z���[^�_A�K�ʔ)æM�(U�[�l�aÆ���bcc�_�ł066�)��]ϧ������cddDtt4����¼γҼys�e'լ���)����;�/^�f�:v���o����	�*U⣏>b�ڵ���3f�v�ڕ�l!>>>���bffF�ƍٵkU�Ve۶m�������{�(�p�
��3~V�*U
Y�p!/^�`�…$&&2j�(UƓ�N�:�����7?��3�+W�޽{�ܹSU'<<�:u�h�oee�VG!��0ݻw��������i߾=�㲶����?VVV#I���/\�x��>��Q�Fe�{{{��]�|+++ڵk�*kܸ1mڴ��|��Z;�+bbbX�|9ŊcȐ!�re{K�.�:]���t�͏v��aee�u���~"����̌��iӦ
���c���<x�-[bjjZ(�ϭ�e��;����{�s���ʕ+ԪU�:d[Wپ{���V�Z��>)))����ԩ�rpm�=�X�"�:::R�lY.]�Ķm۸r�
�˗�H��g[��ر#K�,�z)��,�qe5�pa�7���'O�8%tA�ѣS�L�A����bjj���nnnj/�r[�t�ҬZ�
WWW,,,066�lٲ888�f���)ƏO���166V����GQ�dI��.:t�ҥK��a!�B!�B!�ȉ���O���ݝw�yʕ+Gǎٳg#F�P���>���			��?�|�򘚚ҠA�N����5:44jԈ�gϲl�2:w�&&&���cmmͰa��H�Pt�ڕS�N1`�,,,(^�8|��g���k}��e˖��ѣ|��w4lؐ%JP�xq�֭��_Mxx�Fgj}Ʀ�+yi_�֭9}�4�}��j6oެ�	%��V�����|��kcaaAӦM����`[�u�ge���t�ܙR�JQ�xqjԨQౙ��2o�<.^�ȷ�~���-e˖��ؘ���cggǤI��r�
���[�	�2q����R�xq�ԩ�7�|�ٳgy�tj�6E�^$�(l�{��U���9YiԨ]�ta�ΝL�2�˗/���2���ʮ���f�С����?~\���իW����T�c� IDATf��)u�B!
Spp0nnn$$$:!D2`�֭[�������Ǐ�A�����c��lق��1�ǏW�̺u�hР�g��q����~�z6o�L�J�pss�T�R�>}Z�P6�ӦM�{����9T�V���nܸAHH+V��ѣG|�嗼��j�\�v-aaa�1�o���Z�jq��u~��W�;F�%8p`��a׮]Y�d	L�<�f͚affFTT����_b��c��ˊ���v�b޼y�υ��ܰ��%88���Y�f��{�q��]֭[������KKK��={�u��q��!�/Ό3r��Z�j\�~�_~��ѣG��[o�ҥK�믿T�?~���\}��e�ʕ:tƍ���%׮]cΜ9���̌.]��a��N�
���MLL
��Y�͚5�8q�!C�0a��֭ˍ7��߲��"�q�,Y���xv��M�N�x��&&&�z��і���쌳�s���^ٲe�ꫯ�ꫯ��שS'U2��T�R����r�Jn߾M����}�6�O�fذay��B!�B����III1tB��A�Dᱶ�f�ʕ����ѣ<�m۶:��kff�_|�_|��}6lؐu���~��r��\�rL�>��ӧ$6]�_N�����^�@�v�Z�r%����"O��z|t=����*��[�u��sm喖�Zlխ[�_~�E��;?����q�ĉ\�ͮ�Y�_��EB�޸���ү_?Μ9��˗�Q������7n���A���UO�<^���L)S�!�B���h,--)^\~�B��J�*���o�5�#G�УG�:?��
6T}V���x�b�I���8KKK~��'���;/^��ŋ��5mڔ�Ç��ըQoooF���k������ؘ/����cǪ�W�Z�y�����App0���j˕�8����1b�������dРA˫T��65�>c���J���122��͛@�.������СC\�~�>}��-�6m���ٮ��<���%K2w�\���c:t(���xyyi${xxx�s�N�]�ƙ3g�ʐQ^��R�J�`����صk�v�R[g�̙L�81�đ�={�a�����O�n�6�K�fѢE���s��A<��|���Z�v�W�F�8v������B�o�WˠA����ˋ	&��充�0ptB!�B!���N�-�E�����CB�"J�,Ibb"�/_�^�z˕Yԛ7o^ء	!�N޸p�g�Pf��eF��HOOW�Ț�Ù;)�x��bŊ�ʔ�d,S(e9��*�BQ�\��cGS!ě����;w�t�RBCC��>%J��q��|���i�F���7tއ�����,^����p�Y�&ݺu�/����Tckkk���c���\�x��bllL�jհ��g�ԯ__�>?��Cv���ŋ9r�<�bŊ�nݚ�ÇS�n]�ۡM�ҥټy3K�.%((�[�n���B�5�ر#Æ
�B�
���/+�+W�aÆ�?�z���㼾������̟?�'N������
|�9&\dfllLٲe�]�6m۶��Օ��~;W���333V�ZEdd$���4nܘ���`ii����s��9n//�D���ٹs',����<x�:u�0v�X�8q��i�3jڴ)VVVDEEamm�5�J�m�*������ǃ�]�6t��Uk�E^�5k�'O��ɓ<��J�*���}�Uckk[ ��6�EQT�D	~��ƌ���d���̟??ǟ1!�B!���ѣG3z�hC�!�B�;;;8@�>}�={6vvv���q��UV�X����
��J!��7.ᢠlذ�7n�:x{{��6jddDzz:����,YȾ���˗���Q}�x�"��Ȇ�˗'66���8ʗ/��~\\���B!Da���֘�K!�k�fƌ����}�hт-Z贎��)}���o߾y�gݺu�3gN��+�r躼L�2�?^k��ˆM��ݶ�o�n��f���
K�.�i����ڶ�駟�駟j��ղ�b���U��g��(W�oT�\9�m�ٳ'�:�lkV�ժUcڴi:����jԨ��ի����o��C���9r���mԨQ4k��Q	!�B!�0�������m�0�BMzz��CBqs����?$<<�?�Pc���3f�����BH…�;w4h����1u�Th޼9�5�lٲ<y�{�ұcGbccU�!i�t�R���K�ԩ��˗Y�l�[�Vձ��$66���W#����U�B!�(lQQQ�����a!�BlllHJJb�޽Z�3lڴ	@�D��xUf�(h������:!�o����j�0�Bd���c�D`bb������B���ٺu���B��5k�ٳg�3g�w��ڵk���P�jUڴiØ1c���7t�B�#I�ȧ��x����������ؘ�#G��7߰p�B�̙C�R�hѢ����[��u��ФI�,�[�\9<==�ʬ�����U��5k�ɓ'����aÆju###��#�	!�B���x�ܹCݺu
�B!�q��;v�/�����ƍcff�͛7ٴi˗/�_�~�T!�B�ñc������С!������!�"���E�B	)))�p!�ȵ5j0o�<C�!� 2�(o|�E~G�X�b<��Ãʕ+P�re>��s.\Ȋ+3f�}�Ŋ�ȑ#<�����õnw�ĉ,\�����r��ѦMz�ꅉ���N�֭���?���qvvV[���dɒ�j�*_�B!��UTTu��1p$B!��OOO@DD�XnddĄ	���3@tB!�� �����BQx{{ӿC�!�B!�B������hK��X6f�ƌ�Q�]�v�k�N���ܜ!C�0dȐ�P�ti����lc+Q�]�t��Ϗ{��>�ݻ�ŋ�ݻ7����nC!�Bߊ+F�nݰ��2t(B!��Y�b��֭[���P�R%lmmqss�iӦ�S!�B!�B�F.]�D����.���!,,{{{z��]��	!�B!�0�p��֭d�Ν����s�N*U��'�|b��B�&jԨ�L!+�B�f�V�ʤI��xEx{{���b�0�B�\������aY���'44��a!�%���xS|��ׄ��p��I�e���,\��M�6���N�>}����I�&�T!�B�&���W���9�F��_~�k׮�߿��333G'�B!�B!�$vvv�l!����₝����(��;���/...�E!^{����A�"!$$Dkybb"�'O�W�^XXXУG&M����/%J�(�0��H��#�Bd$�/�$\�6lH߾}Y�z5����aÆ�J!�B!�B�iF���ѣ
�B!����///C�!��=ooo���o�0�+���@����իWs��=���*�ׯ6l`��Ռ9Ҁ�	!�a�����!!��-I�(b�:5h�.]�ҥ���B!�B!�"{III̟?�ѣGӿ���
�B�3I(B!�ț/^�l�2���Ý;w011��ʊnݺѽ{w��			�\���� �߿��o���̐!C055�K��ɓ'���c�ƍ�hтʕ+��T�Z[[[6n���)S�L!�Z!�WWW\]]
�B�Z��!��J2�B���k�va7nAAA�C!�H��'O����Ǿ}�������O5�����tXB�J��ąB!�n�…��矪�)))�={��g���]+99��Ç��{��V�ZŹs�X�p!Ŋ�r?�w�&!!�V�Zi,kժǏgϞ=���S��B��/44����:!�Eԫп�U 	B!
���/...�D!�x�(��uNNN�A!�huNLLd�ΝlذA��Q�re�y�n޼�����"�	!�x�lݺ��!!�ȇ���V�j�0�xc����`�lmmIII!  �3f�i�&U���뉈��Q�F|���XYYq��u�O�����پ};ݻw��ɓj3[(>��ᆱ�Rv��aI�B�qnܸ����<�B��U�_򪐄!�����K�3B!����yu���A!�����̆
غu+���|��,^��=z0r�H�]���p!�BQ�����v�ZBCC�~�:iiiT�\;;;L�.]b�022 ==]o����Ԕ
*дiS���O�~���\�N��R�.\��ʕ+ٿ?������S�L����ر#C����R�]�|9&L�ѣGˊ�B��Ą��3&.�[ɒ%y��^^^DGG���@�^��ի�Z=eF��ӧS�Z5�ԩ�?�@���	�{��Y��ҥKԪUKc�rQ�!ěHF0B�ѫҿ�U�Z'\�7�q��:!������!!�B
+++C� ������z���9r�
6���������c�ԩ���[F���ҥKԯ__�2�������w�ޅ�B�F�w�nnnj,�u��n�b˖-899�a�ʖ-k�(_?������H`` ~~~���J��k,))�����%K�����e�?���?~��3g2v�X�O������?t�P�mK�7cǎ��$,,���0/^���;��������ݸq��yddd��y��!eʔ�X��)u�B!�B�^ۄQUQ�(�tu��D!��٫8"Mǎ%�T!d���Q#uq��6l��3���a��Ѹ��R�vm}��Z���			�:Rhxx8.dӦM���ӧO���iҤ�"B!�,w�ޥU�VDGGS�Z5���+>��cj׮���1W�^��חY�f���3���/�ھ:-�f
HMM%66��[�2~�x���X�t)#F�0@���%%%ѹsgBBB011a�����ҬY3�z�-�>}ʩS����bݺu̞=����&]dEf�o���*3[��u��	{{{8��m��X�h�ׯgԨQ����g�ٳg�.Wf�іħ�e7�B!�B�<5BaP������8!���Q��|999���d�0�⍔�������H'�����h-OLLd������z��I��D���B��<x0��Ѵoߞ�[�R�|y����gҤIt�ޝ�m�’%K���0Pį��ŋS�jU����9�fٲe�p�7n!!!XYY���KӦMՖW�PGGG����ٙ�� &N��ܹs
�� �-[ggg������`�޽�]���s�.,,,�~�:;v�P�����+Ó'O�X��ڲ'O���!�Pw��=���(_�<���ܺu��ݻS�re^�Ȭ�B!
�k�p��_:!�P���,�Xf���WWWC�!�B9��������a��g����b_TR��H4M��4qO
Cs���%��[����wPQP1Q4W,HTPIMr���M~�f�E�g�g��s��s�̽��@ ����0�|N�8�֭[�駟�9s&�Z�b����׏5j����"ٰa)))����e`�֭lذ�ѣG��v�@ �=ׯ_����ܻw��U�ҩS'�O�N�&M��K}���gll,.$22���t�ԩ���3f̠bŊ�\TT��ښ��P5ge����eԨQ�[�N����ŋ,X��#G�������5]�ve���4l�P�y���s��i�L�Btt4���oߞ3f���V/99��K�r��nܸ���������0v�X�砫nE����?�OOO���Tʥ~�v����\�x�N�:�w��R�_RRs����_%--
;;;�̙������誋����x�3�۷og�ܹ\�t���z�nݺ1u�T�}�P(X�j�v�"11���t*W�L�V��4i;vT�ST�\�p��k�R�bE��Ë͊עE��ۇ��#?��cƌ�~��jm���a�/^Lrr2�+W�S�N̜9;;;5yM��8k��yn�"�{��֭[L�:��={ҰaCnܸ�����ɉ�72}�t&O�LÆ
IKKc˖-l޼V�^
̻��|���o�֭8L޽{��ׯ�9V\�~]��*			@AFc�m�{�W	�uX �k�p�l�2\\\�[
�@ `���孂@ ��s��5lllT�J�&$$DE^�~��/�r��AΝ;n��ѣ4/ڵkG�v���	g�̜֭9�	&��䄇����孪N<{���k�r��a�ܹ���	�����ݛ>}���fdd���Oxx8���T�V�O>��aÆajj
��4��=66�Ǐ�m�6Z�lI���e�5j���m�4h�*Uzg-��'**�O?��G��ew��%88���Pv�ܩs��٠6m�ė_~I^^�\v��.\��Ç����B�
lٲ�Q�FQ�j�b�:t(M�6U3�޷onnndff�e�o�fӦM�����޽�.]�h<�ɓ'�ر#
�(0t߻w/�"22�6m�Ȳ�O��s��<~�X.���&..���86n�HLLo��V��V��1~999���k����E\\�<~�����ӻwo�:gϞ�w����6]t�]�S��X�z�J搛7o�֭[ٽ{7ݺu��=~���;��(�����ρسg�~�i��gÆ
<{��Q�F�l!ѬY3���X�f
���|���j2�/f�����			!,,���Y��%�e����ʐ!C�?>�������쳷���:���HΝ;�_|�"gnn��N�J�*<|�WWWj֬�޽{i׮���;			*Dž��۷o_֧'�<�.��W
�uX �ay+ �@ ��bѢE*/��E�\�p���`<==:t(���\�x��4兑�=z�`ӦMܽ{��۷cee���7o��QQQ�����f�X�b�ׯ��&''���Ο?ϼy�

�岳�5j�6m������p��7nϞ=+��C����A۶m��mۖ��>\��'Ay���C>��s?~���INN&33���h�
Fvv6ܹsG�^~~��g�������߯^��ȑ#���cԨQ\�z���l�=J�
8{�,.��;@�^�Jtfff|��G�S%Ի�����I�޽IHH ++���z���ӧO�ׯw���xL///>���;�ӧO�����֖��l�͛�";~�x?~����INN&;;���"""hҤ	׮]cΜ9e��2��_I�U�INN�󤧧�t�R��/--
�Nbb"YYY���ѩS'�mh�E���u<u�Wf���t�ԉ3gΐ��ERR�}����0���TY��ח��8�6mʱc����@�PC�6m�����PT�DFF�9/G���8r��ӦM�u����ĠP(HLL��Ņ��,�������	��m��s[ (+bcc_x6IWWWf͚E�ƍ155���[[[��r�W�X���<<<�Y�&FFFXYYѱcG6nܨ��b�ĉԪU###����޽;���DEE��EŊ�ڵ��?a�@ xppp�?��ڵk�0˗/�z��*�-�pJJ
6l(G��@�: .�@ ʁ���/b���1$$����Ji_�*
�/_N�nݰ���z��t�҅�~�I��(�װ����ֶ\�~^Y-,,�۷/;w��޽{�Z����\n޼�\�S��ٳ�>Fhh(P�"1::��G�2u�T�o�.�mٲ���$�����ɓ���ЬY3N�:Ş={��Ne���Ǐ��{�� �I2�@ ��Y�����M��?�@�
077�u�֬[���cǒ�����_�lj��a֬YL�4	y��ի��ʢ���Z�
LLLh߾=[�n`��Ͳ������%e���<y�'''BCCiڴ)���4mڔ��P�����X�b��:t 44�v��aii��̺u�8qℊ�3g�G�
`bb���;v��C����L7e�j�����$!!�Y�f1a�ƍ�Qvƌ���aeeE�Z��>�u��q��}:u�Dhh(M�4��Ԕ�͛s��A����[�.��㩫�2͛7�СC���cjj�{��Ν;�ܹ3>d͚5���H�v����̌V�Z�xR�ʒ�Orr2M�4)������t���7]�K� IDAT��~�U�V���ѤIv�څ�����^�Z���y��@����–-[8q�'N�`���3F-����&L`�޽�<y��~��%K�РA�nݺ�ɓ'9t�P�a��Ã��xnݺ%�޺u���x���,--���
���<{��իW���J�6m�С����޽[M6##��˗���B�6mpvvf�ʕ���g��K�uX9�@ �".^����_�~Z�u��׮]ӫ^a<ȢE�X�h,�c
��αc�>|8�������Q�N>��s���W��0000(��^�|�iӦѪU+�T����1U�T��ё�ӧs�ʕ2o�E�n�:�/|�W�������7o�ĉ�z�j��(+]�m���'-Z�`֬Y�������;;;Jl������^�i{}���������(ͳ���b���<|���={�e={���Ç����o����'NNN�����O?)�QM�K�������{{�R�,]�?����Nll��D����y��w122�~��̞=�����Ο�	@�z����ب��@�#���3F�aÆ��)==����K���Y�`��~)
��ѣ��:88�����V���	D���~`�����N544dʔ)8p@c}�2GGG=z�R^�N��*((�7n��6mJ~~��QiiuS���i���Ғ����s璓��7�|�������Z�>�w�^�L��V��ؘiӦil�8]��]�SWye�O�����J����&MR�
����k��~�w��&4��t-���Z�i���
@���̙3���P)S�Ҽy��@ (C��F�*�*����Y�&_|�E9j&/R����`�`�266��7��ミ�H"�@ ^����,Z�����RGa�p����,]����|&N����
�7.#M���"%%��C�j\p�y�&7o�d�Ν��ٓ�[��/%#++�ɓ'�b�
��洴4N�>��ӧY�p!cƌa�…�������1bĈ�VAg���HKK#>>���x���X�n�z�Zꓸ�8���رc111:�`|2d�'O��߿D�����z����}��

"..�BA�:u�ݻ7�����P(عs'���<|��*U�о}{��틉�	��|�c�����֭[ٴi���ӽ{w���ϓ'OX�~=gΜ��ؘ-Z��_���֒%Kشi�.]��Ą6m�0h� ��͵�˳g�رc'N� 55ccc�֭����;w��<}�����cggGժU��jժѴiS��ߏ��3*T(��^._�\�*�0���ꫯ����*��q�3g111��İj�*��������\���￁�蜚�믿�l��ÇjQ<��$�@ ^u����Y�f�rR$|M�1�k׮ѠA�n݊����~�W��_VVV�����c��i$}%C��H���
G��g��k�ӦM��ӓ��h����C�Ν;���̧�~���i��LY�_a��ͩ]�6���xzzҥK���A���t9���Z�l��N�6m��[�.��㩫�2�����~�p��W�\!11�S�Nq��I�������z�����Ғ'O��<�����NQ��;���x�b��*��<��獶 ��y���‚ٳg3v�X
��={�駟T���@P�t�,e}+���Q�:���@NN�����ח�۷3p�@@5��iӰ����̟?_�:ܧObcc�4��f�۷�s=_�@ ����DHHH��h�,l
˗/�[�nX[[S�zu�t��O?��B�(-����޽{�iӆ��o�d���� ++��/2w�\*U����qqq!77���~e��ʢG����O���ɡC�HII!''��СC����޽;YYY�x���_䋭�������޽{9rggg
��M�e9���p��瓛�˭[�����Z���#�
��Ȉ���b�
�����C��xm	����ɬY�8z�(O�<!77��W�������0g����HII!77���TBCC�-6�MY�����<x�B��'Oعs'���|����8q���,�>}�ѣGٰaC�ښ={6�ϟ'++�'O�N```���Ν;�s����(
.]�Ě5k��_d��Ǐ�P(h֬��1�5k�B��ĉ�t�@ x
��������yЭ[78��Y����Q(�\���={�s�NY����'O��_ʮU8b�rYygr���(�]W����B�J��J�*j2�oI3VHѺe^Õ"�k3"��(�>}�q�.�C�%44T%�7ظq#}���I�&*�~K��2�?Mkf���$''T�����L}�O�O[�ʕ+��6]��]�SWye���T����R�}�vlmm�����Ņy��Njjj�稩�}�]�_ǔ�r��96l�q�j�4�K�U�xQ��s[ ��-Z0z�h�,Y’%K���)�̘�@�:"9X4m�T��Fd�����_�~*�<��޽��ҳgO��gϞ<|��ݻw��f�@P>xzzr��>��c��ohҤ	���ҨQ#f̘��'�\�2���;�W�.o�_&O�Ldd$�����ɓ�N���T�Z�.]��a�N�<��o���΄	�[���W�N�Νٳg�'O&??��#G�V/�`dd��o����۷o�6R��D�5�޽;iiirm�ܹ���4�w�N�5^���ב_~��{��Q�zu�͛Gpp0�g�Vɠ �w�^._�LÆ
Y�h۶m�~�q�Ɯ?���@u�js���5}���:(��_�x�b����߿?P`lddd����e����U�z}�z����ٲe����<y��~9r�P�188���@�
����:gϞ�~��j���ڪ��%$C��۹��̙3�>�{{{�-[Dy��믱���y��L�8QŐH��P(�<y2vvv�����7ߐ��R"��N�J���133��Ɔ�ӧ�9S```@NN_}�VVVT�Z�Y�f����ݩP�U�T!::����c��斨�3g�```�����ڵ+*T�Z�jx{{�Nʎ	�nP=v֬Y4j�333*U�D�6mX�~}�}`ee������2d�=z�?� �H���ݫ�˩S��l��7� ==]m�T&��@�#EvOKK�h|/}�����^�p��c�b``��-[hҤI�m��Ⱥ}��:t�D�.]��7�T	!]k�?�#�U&��>��3g�p��u����/_�̸q㞋n���>�'Ց�F۱�C��e<����6'�~Pv4	��ݝ+W�иqcfΜ���?aaa\�tI�ށ�]�����ر@%{�2������s[ x�hz�-�Oy���ҥKY�t)(7=��e��٩aѢE888��w�Ν+�<Oƍ���111,[�������V��uX����>}�"�@ ʟ��Å&�ܹC���;v��cƌ���ܽ{����̙�СC0`�G�fÆ
EF��d����ƪU����b�Ef�(�M�cnK�PĘ1c����LJm۶����)������NŨ�Z�j4mڔ����(:�@ ���ׯ3b��֭���5k�d�Z#&I8E}
�����֘��bkk�ԩS�����8p���ք����ogg���/�֭S���E�B�Z�055�V�Z:Tkjve�O�>M�N�����J�*���h5�INNfԨQ4h�333*W�L�-�3g�֗O��V����˗Y�b:t��͛y�-Z�o�>LLLX�z�Z4m�]���^w%���mj�.������`����u�?���ֶ%
˖-�C����S�Z5z��Edd����s�&%%1`��W����)����ݻW�κкuk���0�^S�ѷ�m���|||4g�֭ШQ#222��2���E���_�/˱/j~<��5kbbbBÆ
����<�.z�d�Jz�3O�_�N�-�P����%�Wm�ʥߩ#F���bllL�&M5j��q���;v,666R�vm�����zާ��Æ
�^�z���ЫW/���>|8o��6����5�|_�O[_~�%5k���ԔO?�(>ک�q߾}<x�G�ѭ[7BBBX�b�,w��U����0R�$#��o�%00��O����Ί+عs'����۷���L=zĮ]������Ϟ=��;w���Izz:�w���ͭH#2)b�…�z�*���r:vggg��qƌÊ+x��1���s��e�ƍ|��'l߾�����Ҹz�*gΜ�����q����rrr�ȑ#ddd��V�^����ǩS�2w�\.]�Dvv6O�<!&&��Ç�8O(ӻwo�����ȠaÆ�������>ӧO��ŋ�����~��GT����� @�F������He��@ �:R6	]��)
������`Μ9���h���X�H�������U��h�E�k�.=z��/��m
Mr`Wv�-�֭���'�������Z��ZEY��=O�9?;;;��Re�5.m��d<K#��h,����`���\�p��///\\\T���%tذa�z�����x044���K���q�����?,���y��@ ���:,���p���5kҴiS�ܹ���ҥK�����S�F
9�hbb"���q��}8PlD=e�>}ʌ3����ɓ'���p��1��b�i3''�9s�FJJ
�����������"����Q(4k�L�8͚5C�P�T���#**�>��u��q��
����{�.����hѢؔ�����P�޴i�[��������p��.\H�T�l���Q�4F�.�СC�������*����ޞ��@n߾MNN�o�fӦM4o�\�&���'OҡC"""P(����w�^ڷo/_J�>}�-Z�f�._�Lvv6������1{�l�7oν{��L���:~���<{���#G���Y�fxyy���3��w�Ro}�YW^�5�����=@%է&?~L�v�0aQQQ<|�P6Zۿ?�:u�_~)q��Gxx8l۶���Trrr8{�,�{���vi���Z�j����L_}uik�ʕT�^�U�V��ػu�>>>�e�,--qqq�J�*DDDh5��r�
���T�Z�2{M�߿{{{6o��ݻw���寿�bܸq��[a��^���^^^��ő��Qf��^n߾
�{ァR^x
��8X�q㫯�T�`�C���S�� �0���ԩ���4m)S�Ί3�<x0��������7����H2��t�Je�F^GΝ;Ǿ}�HJJ��
f͚������$&&��_�믿�Տ��`Æ
\�x�;vP�vmn޼Y�S����U�V�={����裏8r�juN�:��Aff��1z�h����x�"|��@����ŋy��Nm5jԈK�.������Ӂ�GP}�&EX�v-P�q'++�Ǐ�r�J�/_������/:t�M�6r{�����СC����ܹs|���jՊ�ݻ�y�f���U�A�T������$׮];@�Q�T&E���U�G�@�1���LHH*��&N�ȹs�puueƌE�!9Cj��IHH���@���ё�]�r��]���OFF��c߼y�%K�`hh�ĉ���ݻQ`?;={��%K��#�낍�
$&&��k۶�ZYY��=O�9��>���K��j����utE���u<u�Wfɒ%j盛�˂T�����
R;���rfff�m*ӠAƌ�B��G��:��:u��={��������\��K������p�B���O9^q��s[ ��,�����P��숍���M���_h�"�uX ���BR
���]���ѣ@��%�k\7l�0�l�BPP�g��G���޽{III�F�̟?���`fϞ�1^I�T6R6ڻw/�/_�aÆ,Z�Hv�hܸ1�ϟ�_��={����� E��d���y��!��9�?f���$''���Itt4Æ
#;;��PBS:�������^��ȑ#���cԨQr�գG�ҠAΞ=+/�;v@�@]fff|��G����ew����ݝ��Lz��MBBYYY$$$лwo�>}J�~��F����O>�رc<}����Hlmm���f޼y*��Ǐ����>���d������ ""�&M�p��5�̙Sf�)��I�d���%�_	)b�o���S���[�~V6S�.*ZË�ft壏> ..�H9___���hڴ)ǎ###�BALLmڴ!??_��V��GZZr���D�������S�Nx{{�u�YYY$''�x�b�xo�*2�\S��k[ժUcժU������%;��������?��Ì3hٲ%P����N~~�FCI������0`���e:��HMM�����\�x���,Ξ=K׮]�[W���������ɜ?���t�/�_'�90��P�7RS���e\SV裃�=�2��-ccc�{I#��mۖիW���M�F����b۶mx{{�v<5H (s�̡q�Ƙ�����	Dx�7o�����ܜ�Çh�J��w�ѡCLLL������:����x� �U�f��A7n�������|���9�ƍ
��֬YC�F����`ҤI*�X�ZVqm)��[�|9
6���Bvf(.�����~`Ŋ������M~~�V�PWWWf͚E�ƍ155�3:T�٨bŊ���A͚5122��ʊ�;�q�F�'R�V-������
��,--5f����bŊ�ڣ@ �:�G��7������уS�N�P(���`�ȑ4ccc�5�={������>/x{{cffƆ
�6m���###��~�M^�2mJ�]��jժq��������ʕ+��撙�IBB�/������3c�������T�T���\]]IJJ";;���$\]]�����Ғ1cƔ�������<}����\����5�/k����>�7|�pjժ��Çqss�…��䐔�D߾}�<�O��:���+s��1ȟ�Ivv6gϞ�G����P�n]���KY�nݺ@���{����#11����8�<x�@�>Z�h]�t�֭[�m�OOO�9ƒ�����>|��C�Ү];�ܹCǎ�\ۿ��֗��͹s���O9v���Zf�� 44���\��\/���@ (k��/R���/�uX ��ŋ�^��ׯD�[�n�7� ::OOO�������ĉT�Z����ʕ+DEEq��u��D��sĈrz�&M�0|�p9
�DiڔǎK����]�6>>>|��WDEE�;���o����q�2m/�����Y�����O��b޺ukZ�nM�J�X�l~~~E����0k�,&M�$/bCA�쬬,���ϪU����۳u�VZ�l��͛�h��C����%e���<y�'''BCCe#ĦM�J�.]���`ŊϫC�*�~��Ǭ[��N�:�e���-ZD�ʕ��֎;���aaa*Q`K��2��ߟ�)��ҋP)BWi�Go]�YW^�5�+R�t)
�6�����{���Z�"00��
r�ܹ��O�[�����өS'�:͛7���o�^NG���
w��Q-"�>ה���Ӗ��+3y�d������#<<GGG9��СCY�j7ndΜ9*��yyy�!�d�P�c��5k֐��NϞ=ٶm�\ެY3���O�4�P/k�J;Og̘!/lZYY���ם5jp��
���O��}�\��P��ښ۷o��燵���T�\tx�mU�X'''����|�2111����i�&�X�r��ܿ�Ǐ���?�eAM�4��+g�iذ�����Rk�™�5*M/�$RSS�A5Ο?�Vּys�{�J�����2�H�^���_�I���N�d����8|�0�f�̙L�>�q���...*�~�aeeń	�0aB�rݺu��HT�P����u떜�֭[���3r��"u��U�V�Z���믿ҪU+5��+W�dS��[ϝ;'JkBr6oذ!+W�dذa,X�@�Y�6m�:u�J����lP�����x���6�� IDAT�Y�f�8_B����� ���#,,Le���AAAԫWO��%���aaa\�pA�
�x����E7}��y��U�T��۷ӽ{wv���Ν;U���兑��N���?������,_��/����[���[[[�k�.���ɓ'3b�V�Z��^0s�L�m�Frr2�O���3J���)���cʔ),_���7�k��122b�ر,\�333��		a�ȑjA9jԨAXX�Z6�-Z����\�-X��<����c����S�j;v�(o%�ep�2d������___�}��GFF�Y��єu��Ç���R�fM���K�v���IHHP9.����@ (�s%��ȈN�:�k�.Μ9C�V�8{�,O�<���M6���X�p!W�\Q;FqQG��w��Z�TMF��iS�h�maY��SJ����T�)
�@ ������^
6�e˖q��a�����0���\�w�"�ȑ#@A���888���J���z	XR4�ɓ'�E�644dʔ)DDDp������V�����G�T��ԩCrr2={���LJ:��M�6U;��ꦌ>���@wccI^��_��[�~֕y���bK9��&�]��u�;��<U�>��w�^�L��V��ؘiӦ���N���8880h� ��A���W����˗��U�hܸ1S�N��Ғ͛7�����#�.\�СC|��'�C�q��-���d�ϲ{MH����ؘ)S�h|�T�z�v�~���%n�D۶mپ};�֭㫯��~��\�|�u�֩�:::�{�n~��G���K�իǣG���_سgM�6��o�
����s玜��,�E���-M�2f�RRR6l:t�^�zr����߿��۷�+$�<�R��@�zQ�8H���_��$DŽ��wO�i}��¢D�E[�J���ݝ�ݻ�{�n���9~�8ӧOgɒ%̟?_%�Yy0d����GPP�'O
�>k֬���P �W��={�…	��ݻXZZ���ȤI��2;]�|Y�6���hذ!, ::����ׯ���4i�F�m;;;Ο?O`` ������ܿ###�֭���>>>*N��8;;ǂ���_IMM��ښ�]�2u��R�Q��ʊ��h.\HXXW�^%''z��͔)SԜ��R7]��E���k׎��x�ΝKxx8���4jԈ9s�гgO����rzյtO}�_b����2{�l���y뭷pvvf�̙jkÇ��̌e˖q�����pttdܸq��Ջ�
2x�`V�^M߾}u�#SSS�-[������9r�K�.���S*U�D�F��ڵ+^^^��[Q���ѨQ#���K���[�.}��e���T�VMM~Æ
x{{EVV5j�(�/���#''Gk�Q�@ 
S�"11Qe�E��ꊱ�1!!!��c�:uh߾=C��夬��ׯ'""���*T����=�F��XCA�6???�޽��u������b��*:����@ (�s�#aH���:w�LXX���;�Z�"**
CCC9DD�r�
5jԠe˖ԩS�
��0����/�5��.M�Ž�Vΐ!��.l4�\Vҗ��@�+III�B&''k�7b��]�F�
غu��o��A9U|QXYY�����Ǐy�7JTG����{a�rm��"%$'��`�M����'���r��:u�йsg������OU�J��2��_ŊIOO'==�7�|��6$��e!V�u�g]y�׌�HN.�8�\�r���DN�:�ɓ'���JOHI-[��X�M�6Ŷ�|�v��}���ٹs'���#88X�Z\}�)}��w�jժ�Y����kV�X��,1d��N������Å����_�{M\�p(�b��֭[{��Ы��Tr��ҫW/�;ƭ[�Բ��O�>�>}�K�.1e��}fff*ץ�����;kkk���T�{a���QWJ��hKS���Ӈ�kײ~�z֯_�"����ޞ��X���/�r����6O��={V�?�������j�S�jURRR�v�Z�Dj-��+���#�ے7״�L�ƍIKK��ݻ�����n����Ki���`��ٌ;�A��g�~��'�N7�@ �ʼ����@q���?z�Ѿ}{�#����1|�p��W�M�4a���%�/n=A�7�x����3��r�M��+�XeU_�󃂵�M�6��KN>���J������x�*������Jf��<x���ĠA��VmmG�
4f�ч>�@~�)8�q�6�_�-h#((H��,AIؿ�ʶ��E#���u@ݒ^ S�zu>�����HNN&66�V�*���̛7�A�ѱcG�c��啨-)҆d4&�ɐ�4mJQ2���		Q�l۶M��"�J���He���
AYQ����֯_OHH�*U",,�*U���HJ��B2\�x�b��rssU���OmR�om�t1�:t(���*�oܸ�ƍ�۷/M�4QɖTZݔ�g�$����ϗ���$_��X��SR9]�YW^�5�+W�^��l���۱������͛'G��}�C/m�!���`mmM@@��.\��Օ����\S��[��Mggg:u�+jʌ"1h� ���سg�<~����ݻccc���e5����i�S��VY�U�y�_^ܓ�C4ann��ٳqrr�R�Jacc#gq111�e---�;w.�z����CCC*V�H˖-����U�+xzzR�zu

��]}�E���-M�ҥK���y�w011��Ą:u�ЧO�߉v��annΙ3gԎ{��,--i۶���+T�6m������r��if̘��kC�����A\\���ܽ{�I�&a`` ���k�~nm)
�{BBgΜ!55���<,--�/K��-Z0z�h�,Y’%K���QKg/�@ (=���h
�$9�`�@ ��ː!C�Q������:,���?��BW�u�F||�Q��w�D||<mڴ��͛�Z�J.��I�����Gl۶��k�2f�5j�իWY�v��:ŵi``@~~>w�ܑ#�8::�{�n~��G���K�իǣG���_سgM�6��o�
��ܿ�۷o��ݾ}[���A�
x��iii:g��p�cǎ���-[��EZVn����%��n߾=���:t�V�Z+��%Z�l���3[�l
�n���HOOWq�HKK�u+>��3>��3���o~��W�;ƱcǸt��/_fܸq�ٳ��u�g��v���ӧ���՜	�B2��fș���fp�l�UZ�A�~֕}��Bdd$�=��Dpp0
����ܰ���Z�j���{Z3)hB���ꤥ�i4�OOO/q�VVVl޼�:p��)fΜ������>ה����w����=z(p*ۿ?={��(���oӵkW<H`` �|�
������ЫW/ّ�v�5Q�R%93���A��CY�2��W�7�xooo�2�)��3eŊ2dH��ڶm��?C��64ɗTmm�R^�mi�'''����l��‚^�zJJJ
իW %%��/ү_?�] (C�U�F߾}U���}��j�����_�ĉjFf���,]����kڴ)7o�Ի���X��]�J��[o���Bbb"����ڵk�Y��Q�F������W�^�����9�<<<�[
�@ �ךV�ZI���Y�d	�Z���̌�W��~�z/^d��W�;vЧO��VC �eǎ孂��Y�4����@ x��`ooOժUy��!5jԐ#J8::r��QV�X��+��_�z�f͚ێ��3111\�v�ٳg���ڵ��tm��ʊ��tƎ���5~~~��ӇӧOs��%�L��R���L�X��ޞ��X���/5c���`��A����q��	>���S(�������w�}WdZB[[[���IHH�]�v���ݝe˖�j�*Ə�5��Į]�x�葊����-gΜ�ԩS���C��ɓ'e���nݺxzz���	�/������l0_ֺ�3~Æ
cѢE�_��Q�Fagg����ӧ4oޜnݺ��W_ѨQ#X�nP�744�ٳgddd�9K)��BoeJ�ϺR^�Lq���Ɏ�EES����X�z5#G�T�w�����g�04,:�>�aggDZc�8s�F�Y}zڵk���˗/g��Ÿ���9��sM髯��off&�
"77�#F�v�Z�NBB���@P����lڴ�o���
6��ʔ��k�I�&DGG��A$..Nc����e���:�F�P0l�0ڶm���%�o����(p��<��ݛ�G���/�����Z[[�駟��v���ڵk�8q"QQQ��書����W_aff����2iܸq�ڵ�[�naeeE�����ֻJ���	ݺu�v��e�֏?����������`�ȑ������GRRPp?�駟��y	�@ ^o�.]J�Ν9{�,�;wV�o``����N�~��e ''�~�����@ �2(gD�a�@ ��[5�f�������P^��ҥ�Z�lOOOڶm���9&&&4hЀq�������J����	s�̡[�nXYYabbB۶m��ti��ӓ�իchhHNNPIp�ܹ���kkk

�X�"-[���W�XѮ];���9s挚gΜ���Rk4q�@ (-����Onn�����l'N�ȹs�puueƌE�!Ek�7�IHH���@�w��ё�]�r��]���OFF��c߼y�%K�`hh�ĉ���ݻ�h�"�={�R�ٳg�C���B�bcc������j�4�~��n���;��ĉ��ʢgϞj���Ν#--
???�6m����|�	YYYt�҅:��K��N�Rk?  ���ֵ��~�p?k�E^3�0c�e����5�(�������b�է?>��3���k~~�J���|��>̛7��5k���3Ǝ�v|}�)}��wsҤI��矸���f����۷��믵�w�޽�\�2�ϟ'((���D�V����V�c�M___����k�+}��6w_�y��#���_�///��ݙ0a���XYY��/����Ajj*���DDD0z��"���י˗/�8��ַ�r�ʬ_��?���'N0u�T5�e˖i�iٲe\�v���<x��]�� �����A�*ה���ԴL�rww�������8Gzyyq��233�����,X�@-S�@ ����ޞ���3n�8�{�=,,,066�v�ڸ��s��	�+^9�����c���W�#x5���}.����Ã�K��t�R����@ ����$����1Jz�
7n���1�|ڶm+����;vhr�`ذa�_���� ƍ�����lI�l۶-+V�`۶mrj��+2d����ضmL�4��u��ӫW/.^�HJJ�\����ŋqvv��sc��Ѽ��?~�=zp��)
�9�A�all����:{���Ϗ>����@5'��x{{cffƆ
�6m���###��~�
www@=Z�ڵk�V����???�\�Bnn.���$$$�x�b��>3f���?Ti�R�JDDD���JRR���$%%���Jdd$����3��}(=8����ӧO���%!!A6�R��^���3~P`���g�q��
Z�n͗_~ɑ#Gx��-[���1���<V�\�͛7�R��]_��>�(H��1
�/_f„	�\����ֵ��� 44���\�����勼f�"77�;w�w�^�w�/&&&���cl\t�4�c�ĉܻw���<<x��A����C��>|8�j����ø��q��rrrHJJ�o߾DGG��+`ee��ŋ���!88Xe�>ה������ÇY�r%o���</�.]Jݺuٲe�w��ؖ��9���
"eC�\055U�+˱ׄ��75k�$**�^�z������ŋ�ׯ111�髗�������
///�B���133���kkk�t�¢E��^�zy�((D�&MpwwgÆ
lذ��eK�@ ��yP�vm�-[FRR���p��
�n�J�֭�[=A	���@ �@ ^V�_�U�-[&;E��ڪl�C�P��7�ТE�������qqq,]�TD*J������?cccv��Y�j�Ɇ腷�ٿ?������+W����[�vppИ��0�}6L�"~�6m���Ԝ�puu%99YkFFFL�>�9s��ۻw/nnndee��333c۶m���G�\r���i��G�hݺ5.\�X�V�Z?~�z��=�t?���<�͛ǂ4ꡉ���̝;###�,66���ۣP(��׮]ˈ#�Do}���ɉ��H9IM�������X�"�7oVkWӱ׭['�wafΜɶm�HNN���o߾��O?~��ݻ���S�:xyyadd����~��СQQQԮ]�?��KKKy�>sA_}ui�������<x�nݺ�rG��[�nT�^���D�|�M�c���ЦMy����888�Ȕ��k*����O>!--M����@�VG_�����c�3p�@Y��˂x�班�-�Ƭ�ٳg�Ǐ�e����1p�@� 򦴽c�y[ �W�������g��4��+o���
�@ (?��@ J���([�G,��cnn���,����������	g�@���ٳ'���,\����p�޽���%���L�4��]��ȗ��0^^^4lؐMFF���g�L�4I�o����ϟ'00���P����߿���u�����	��}�m:;;ǂ���_IMM��ښ�]�2u�T�{�=��CVVVDGG�p�B��¸z�*999���лwo�L�����s�M��022��o�eĈp��!���HKK��Ą��z;;;���x��1���,X������?~�9s��ӧOi޼93gΤW�^Z��u�[�~ްa���DEE���E�5���u����1�+W��wߥ[�n�5���z�Du����˖-�…������ȸq����w�aU����_� 8��vǓ�ۜ�)MP$��s��<�q�)%�$�9a2j��9���q֣��aV��`�������}]�{��_k�7����T�Z5���KK�.Mss{f��z4m�TǏ�̙3�c����/�^���O�.WWW���/M�ēZ�d�\\\��?���W3f̰�{��$s
<Xqqq2dH�bIjӦ�
�O>�D�ֺu���ըQ#ըQC�ΝS�:u�[H��g�Q�F:q�f͚�/��R���U��)S�����Rp������O�+���յkW�c���
Ȓ-[��̙3���������D@��
��$+\Y��s���ٳڵk��q�]�xQ/������u��y��<V~ˋ�'�<q��c��������.�8���w����Z�n��nt _���d�ϗك.�%nnnrss3:�T�XQK�,1:�bŊ)11Q�}���U��n����%I�����h�oy�x�b�۷��<�f͚q��#���(99��P�EDDrܩS�4b�U�RE:t0:��5k�L���F��@��ZÆ
�{�nu��M~~~jذ��-��^˗/��,I0`��I��������R�"|�#DEE6��Ç!///�2�"""dmmmt�<�aÆ[@.��gA�6m���aÆ�U�V*V��ё�|�B�
�P���1(и�ڼy�Ժuk;vL�[�N����J���jѢE��@~�dfǎڱc��10��
6:Y���ct�<m����l5�|լYS3f̐����q�G������N�:�y��i۶m�����,5k�L#F�P�F���i����x������G!!!F��gJJJ�� G988��?�ȑ#ճgOծ]��H@�ceeet���bԨQ<Q@�%www�c�3륗^҂���e�-/(ج��Y�
rAHH�6m�dt��
RPP����hn��Y�f
7:ϔ[p���jt�puuի��jt��"E
�GL�ע�����Į^���?�XG�Qrr��f�V�^-I���� IDAT��16����u��!IR�F�ԵkW��3������et(𒓓)���(T���.]�
hŊ�߿�ё�|�B�
�P���1x�ػa�����ό;v��  �L�<YG��l�����رc��u��)%%Eݺu���3\Ȣz��iذa�0a�:u�^x��H@:���;RRR��(`N�<)I��OT�~}ݽ{WӦM36�5e�u��E����$OOOM�<Y���38!���իruu�s�=��;w������ʕ+�/Wڒ���ϫz���c�+��5c�EDDhܸq�N���@\�5�'��������it�<��LJ��@DD���&�I���w�Z�YYY���&ײeŪU�t��Uu���������P�Z�J�60����Ӓ�ڵk�ٮS��a���1c�hϞ=�;���_ɒ%�h�"yyy�o߾z�7��ϴ�7o����
P�Eǎ��YֱcG���kF�������@���I���?�4h�@�_�iL�4I۶mӌ3���j��W_i���jӦ�|}}3-�x�=u{����Վ;dcc�f͚i���z���-�޼ySaaajР�ʕ+giwpp��dRXX�z�쩒%Kf�5 /ˬ�"u;�ٳgO��p�s:w�,WWW���{:~�x�{�<+�����榄��>}ZE��[��o)0�7���4:�)�����L�0Aǎ�ܹs���"]�rE���*W��&N��T�~��Gڼy�$�Ν;������ǵv�Z�*UJ��m�6%$$�I�&�oҤ��9��۷�s��O��q=�rٲeZ�l�e���_�����h�߰�@�
P�ڵ���Կ�<�3g����M���ںu+��BF<۬��x��ŋ/^�y�,y�̘��o�,Y���O��۷ok�ԩ���>��ݾ}[ӦM�G<�}��i���:x�V�\)'''���OZ�v�����%I5k�Lw|j[j���߿��K����S�7�믿��}�jӦM�&$$���_���jܸ�:v��@%%%Y�<XHb2�,�YY���͛9x�_�J�4u�T͚5K�.]2:<Sv�ޭ�͛륗^ҁT�re�#@�B	�p2��F� �			��&򛌞��Q��<�A�2��
�;CS�N���[����S�0a�e�W^yE�&MҐ!C�k�.�S�ϟ?/I�X�b��+U���U����Nf�Y+VԆ
t��i���G���
		��Z�f�e;99Y�N�ҩS�t��m���H����4h� �={��7>>^+W���ӧ�B�2N+\�ѣG��>�СCetx&����O�>rwwך5kdkkkt$�s(����K^^^F� �INN���G2d�>�S�N�J�*6l���Q�Fi�_}�UIҏ?�hi�v횤�V�xXj[j
�ӧOK��ԩ��vN۸q�$���_&�I��Ɋ������֭[g)�X�v�Ξ=�:u�h�ĉ�Z��bcc5{�l9rD������PLL�� �BЬ�pE���cmm��K���_WDD�@������k�ȑ���{���YF������Ș�RRRdee%�'\g�H���.���$��#S�8��)�-�]j�E�ڵ3��iŊӭ[��K�.�E��ҥ��t钦ߎ;$I�gϖ���$�J�*�6m�<<<%�L�a�+��ӬY3���W�F�R�v�T�T)�#@�s��=�9R���Z�`�F�at$��(G�iW�^��dR�6m$��TQ��$WWW���F�!�Qs���k���=z����s1�gŒ%Kt��ժUK�.]R@@@�����o߶�]�p!��N�<�f�رc��ʕ+[����%I7n�Hw|j[j
*��$�ɤ��HI�ܹse2���W_I�fΜi铓F���E��СCZ�`��u릕+W�Ν;i�]�|Y����n�e2�,E�����
W�m�ܹ���?5e���@�����.]�h���
�����@����rkI��n̘1����ss;vL7n�Ǝ+?~<�(Ⱦ��[�����W_�ʕ+�����P}��>eʔ�$mڴI����t�|}}3��?��ӧu��];vL�gϖ$�k��ҧz�꒤���tǧ���9�m۶ںu��N���u��Ν;
����6l�`闒���qnݺ���p�����5w�\-Y�D���gt(0~���l�R{���Ν;չsg�#@�@� O3zI��nϞ=yn���DM�2E]�t����������ɓ'+111�S(�n޼�iӦ�X�b�1c��)b��t��MIR�-$I.T���յkW=��s��[�lY���G�5һᆱ+W��V�Z�֭��OӦM%����Rۚ7o�]�
@��e˖I���8111�$���(&&���i�J�����V�X�5k֨w���?4�|KGGGI��͛�dK}9r�s��@��ӧ��6m���޽{F��|�…jҤ�~��8p��n��Qp�s\�}͚5��e˖�d2),,L���������Z�JW�^U���-m��޺z��V�Ze`2y�߽���W?���Ə/'''I����Ə��W�ZV�5j��t�ҥK���FM�4є)S2w���j֬��)�r�ʩW�^Z�t�lll,}ڵk�bŊ):::�����*Q���|�ͧ>7�W#6bu�N�:�d2i���JHHP�j����,I�����kٲ�$iҤI:w��ݻ��~�M�-��dҠA�,}SW��|�����r����>���<yR�|��q _;|���4i�2e��|��'T���e?�����~ݺuK�*UR�^���ꚦ�͛7�l�2}��7�����ϫU�V0`�J�(a�Z$������ɓ*Z��ڴi��#G���N�t��}-[�L۷oW||����U�jUu��Ii�z�똘��˖-�رc��쬥K�����wޙ�}��M����A�*W��������`�gϞ*Y�䓽�)c<����?L����Mnnn�m;;;M�0A&Lx�T�ti-\��ي/.�٬+V(..N�˗�$������8p��+��1(�B�E�޽5{�l���Z
.S���X��ӧ�v�ޭ�'O�G�i����jԨQ��2e��ڵk����6oެ�M�jϞ=:}�t�q%V��I�j��رc5i�$yzzZ�Ⱥ/��Bf�Y-[�Ժu�T�xq�#@��
�<'�I�!!!���+*&&F�W��$9;;��r�׮]S�޽�e�]�~]w��Յ4u�Tm޼���֭[z�w���Yw��Օ+W����+!!!��ԑ#Gt��ݸqC6lH��}@@��/_�˗/+99Y			:u�f͚����,�?�n޼���!;�;#۶mSBB��4i�n_�&M�����۷?Q�kz��-�4�ς������&N
��,Μ9�f;7xzzj�ԩ�Q��llldcc��U��O�>�>}��_�%�r�J��f9::�p��*U��Z�h�իW�y��رcU�|y.\XIII�X�
�H�'O����F�mt�wչsg���C_|���(��YF?!-((H����jժ��7j�޽z��%I+W���[�f�.]�����k�ʕ:x�V�X!''']�p�R(�+j�ƍڿ����'Iڵk�e�ƍ%I���:x���ky"�u�$�}"kF(U�T���5cƌl?���޿�$�f͚��MmK�������M����H���+>>^����6m�lmm��@����RLL�^z�%I�Ν;�������ݵv�Z8p@кu�4t��t��*UJ�G���͛u��a}��7�����/���_۶m��_����ڶm����pu��q���Y���pգGV��!Ŋ����֭[�;v򅔔����:t��O�����*\��ѱ ߢ��g�XԮ];�휶o�>IҸq�T�B+VL�&MRLL�>��sK��B�I�&�W^�����֭��'J����tc�?^*TPѢE���#I��?,�S�8���p�����ҥ�bbb���=z�M��wFΟ?/鯂��U�T)M���ׯ������O~~~2d�\\\��r+\���Mo�����?����8�����2��Z�p����4i�$�#@�W��<�d2�ٞ;w��Νkٞ9s�fΜ)I�Vu�N?��$�YN>#�O4�[�n��z���AU�V�|]�T)I���-m#G�����u��!:tH�|��'�ٜ姥�8<���wF�]�&I��`[j�+�����l��l��4,��7����3���Ո#ԳgOIRdd�/^�
W�`�…�U������y2�����Sǎ�֭[ժU+�#@��
d����o�`�ì��9O۶m�u�VM�:Uu��՝;w(WWWmذ!K�g��EJJ��뤤�t���y�[�P�b�����
F`�+�T�PAS�Lч~����8��\�|Y͛7ׅM�d#V��9111:z��:u�h���:x�
&-[�,Wr������…�U�V�������?���jذ������$GGǧ��T�Rrww����Ξ=����ZAAA�?�:w���YYY)%%E�o�V�%$I.\H�/��{{{]�rE7nܐ��}�}7nܰ��l��(r+\g���


���õy�f��@�q��	������^�K/�dt$(PX��'�>}Z�T�N��sCӦM%I~~~�r��ܹ��s��d2��߶�kѢ�$i���:y��޽��'OjΜ9���͛?�ܝ:u��d��땐��jժ���YRƫc\�|��c�)SF��i�&%&&�ҥK�}���h��իK�bccӍ�ږ������V``��l٢/����8�'l۶M͛7W�5M��V��Iy��o߾ڱc�N�<�:����Z��ݻ����]�|Y���KӯB�
�ڲ�w�ޚ={�|}}�E<�D}�2et��5yzz����O�hѢ�6nܨ�j�…��&M������h�M�jϞ=:}�t����ç)@����($$��<V,�-Z�l6kĈz��7U�X1�#�aV�Z���{��Z�|�lll���<���3gΤ��
���Z�j�t��AݹsG/������֭[[��,YR�V�ҿ��o�޽[�������պuk���*U������"E�(<<\�.]�$���P���ջwoK��c�jɒ%�r劒��9�Q�T�P!�رC���2�L�2e�ڷo�T����ڵ�…�^�z�7::Z%J�Лo����@�0|�pyxx�'V�B�#�"???լYS3g�Ԝ9s����>}��O���'j�̙���2:X\򤨨�4�;w�4$����fϞ��~�K����5~��G�����r�������9^۶mնm�,�agg�	&h„	�ퟕ��h��ŋ�l6kŊ���S���%Iqqq:~���F�|&""��J�FG�|���A3g�Ԙ1cԻwoըQ��H�k�޽��*((HK�.Հ�� [���[[�lQpp��%88X����ѣ����ŋ+$$��<1�٬��`�c�Y����ڵ��1���{O�V�����7�rŭ[������h}��rss3:<(��k&�)G��l�<�����M��#F�gϞ����H-^�X�����Ӹa����!O�g;�…+00PM�4QHH��f�ё G��ǫC����Ӯ]�ԠA�#�3�����ׯ������O�4d�����
PP4l�P���ט1cԡC�*U��H�#Ξ=+WWW�����R��ё�B� _c%���l6� ��������1�at��fϞ��?�\�'O��ŋ���n�޽���P�Z���e�	�9\x&�?^իWO�f2��tlj�j������˓
סC�$I�5R׮]�#� ���������|}}5`����O����ё ۄ���W�^�С�֮]+[[[�#�3��ޘ1c�gϞU(���;vLZ�n�RRRԭ[79;;s��S���
6:�e}���ʕ+��{�����2:�m���Ӹq�4|�p͟?_�
2:<�(�P��ٳ���B��]��ILLԔ)SԥK9::J�<==5y�dEDD���.;bd���JK�,��d������	�ڽ{�4j�(-Y�D���ӨQ����<
.���������1�s"""��@�0�L���"��dժU�z���w�ni�Vhh�V�Z����<+�֭�aÆ�_���<==eooot$xb���2��ꫯ&///�#D� شi�6m�dt@�믿j���ڷo�U�jU���K'N���P#!!A+V�Ў;��/���W���տ���H�_�ǃ_gg�GV2<8��C�4�|}��*R���v�A��ƍ�裏�w�^Y[[��_���U�x�+,,L����ɓ'U�hQ�i�F#G����]����Z�l��o߮��xY[[�jժ�ԩ�<<<,�ܼySaaajР�ʕ+giwpp��dRXX�z�쩒%Kf۵�̴i����_˗/7:<�_�U;v�w�}��;w�iӦFG��(�*%%���<����߿�~��GK۹s�,�JJJҠA�t��YK[||�V�\�ӧO+  @�
�ѼO�a�ܹڸq�e{���*_��""",�ܹsG[�lQ�B��<�\ԍ7,cnذA���פI�2=����Y�Ʋ����S�N�ԩS�}��|||$I۶mSBB��4i�n�&M��ȑ#ھ}�:w��<��_�Y�f�l6�s��*[��ёyP�R�4o�<y{{�w�Q�ƍ��Yr��E�o�^w��ՁT�zu�#@��P]�v5:y^xx���5���������Y�f�f͚:u�&O���W���v�Z�={Vu���ĉU�jU���j���:r�"##��ᡘ��Ǯl��j{�jY��ӧO+44T+VԚ5k�t�R������Y6l��������l�2�ݻ�o�U�bEM�6M/���V�X��+Wj׮]�4iR��%����_&�I��Ɋ������֭[g)�ؿ�$�f͚�Kj���)���V�ti���1b���v���l6���]Ŋ3: �֭��/_�����o�U�"� o;r�:v�
*h���rpp0:�!9�x7#""BF� O��$��0�Li^�jߵk�$iҤIz�Wdmm-M�<9ݸ;v�$͞=[���*\���T��iӦI����r�̞.Ä	T�Z5����l6K����OM�8Q+VTѢEճgOI��N�s�?^*TPѢE-����#�)�����`�����W�.]���HK����K����a�*UJ��;L&������?��O?Urr�z��_|Q>>>ڲe������	�#�,Y����?Z�d��Q�"##ժU+�L&�ڵ�bȣ(�.88�r�	����ˍ�<+bcc%I���K���⒮��˗%I����u�…,��U,�i2<���O�Z���k;;�l��1K�*%I��~�ǧ9r��O��C��СC��Oԯ_?��f���Z�]�vM�T�d�tc�����Cɒ%իW/���K��������;�lٲ��򒷷��5k�B�x�$<����5v�XM�:U^^^rrr2:���Ç�_�~
dE��
���vIJIII�mee�n܇�<�֭[#u�<M��E�f�q7�=�\��֖�3��i۶��nݪ�S��nݺ�s����
6�/�ܩmY�xR/���}�����رcu�����T��ƍ�cǎ`��'���^�ƍ'�5n IDAT3:
�����	&h�С�>}��-[F��q�_@���C/^ԉ'��k�Y�O�8������bcc�y�f9::�fLC2��\�J��������u��Y}���


���չsgI�����\��7n���>��7nܰ�rZŊ5a�M�0AgΜQhh�BBB��秚5k�{���V�jՌ�
�%ŊӢE�������e˖FG%%%�o߾Z�~�V�^�^�z	��p�Ο?����p�=Z�G�Vxxx.��曒�9s����Ӻ{��N�:�9s����I�&�ܹs�w�~��7-Z�H&�I�
��M]i����ٚ�I2�Ź2�.�:u��d��땐��jժ���YR�3�W�.I���M7nj[j �Ԯ][�f��ŋu��A�i�F���rvvVÆ
�p�B���OF�䂎;���MÆ
Srr��q<�_����zK_~���l�B��#�p@.3f���٣���t��;����[�N)))�֭�����ꫯ�r�������+����ӧ�#����G�w��ɓ'գG�4�lmm5j�(�v�2et��5yzz���Q�7oN��d2=r��>�=i��+'������[�gϖ���|}}��wqq�|ݴiS�ٳG�O�N�.I�O��$5o��3���J�5R�F��`�}���


մi�4f��h�Bf�Y���*S���q9���_�j���ŋ5f���xF]�|Ynnn�����W^y��H�'�
�={�d؞���)S��K�.rtt����<==5y�d%&&�rJ�9111�0���iٲerww�s�=�"E����Y3f̐$���X��(QB+W���l����
.�R�J�E�Z�zu��Ǝ���˫p��JJJʶsy�yq��������N��5j���F666�Z������ӧ[�m׮��+����t�FGG�D��K#.\Xm۶ժU�t��EDD�L�2:t����okݺu�=
�ʕ+��״i�gtϠ'N�q�ƒ��Rl��UJJJ��!�+++�l6g����'�fvCN~�ٹj�����/U�\9Iҕ+W���>}�h���`������(�c������G���vv���Wǎ������lOg�ҥZ�b�6mڤ���K������ᡁ���'���͟g���ƍڴi�BCC�s�N�����ߖ���ڴi#kkk�#���;wT�V-5j�H!!!F��ٱc�:w�
h�ƍ*]��ёO�.x�_�US�NU�V�Ըqc���C۷o��d�N�JHH�������ոqcu��Q���i����1�q��M����A��bIrpp��dRXX�n޼��g�{���e2��~�z���������{��
���38!Իwo988��)988X����ѣ�����+]��z���Jqqq�={�.^�(777999iȐ!ڷo@�|���V�/Vhh�v��etψ�� ����S�Nںu+���Qp@&n߾����+**J�񇒓�u��9M�81]ߤ�$
4HAAA�駟������x�\�R#G����9׶m۔���&M���פI%$$h����vn�W���J�|}}ժU+���k���RLL�ʔ)�����Ӵi����x���+22RӦM�������,{��5l�0�߿_/^ԨQ��w�^5o�\�*U�￯'N�:t�:h�СJNN6:�n�̙�۷�Ǝ�5k������H����2��QNNNZ�r�<�e˖�Y�"�ڵku��YթSG!!!:|�����ꫯ�ȑ#����$���X�����l�߿_�T�f�tc������l���=z�j֬)[[[*TH������Tpp�ʗ/otD<�~��<x�������!C������X�S�\��&N��S�N��ɓ���ݧv�ښ5k�.]�dtL�Z�x�.]��E�@u��]��>}�5{�lYYY�71:1�LYj��!��.%:i�$���+�$M�<YÇO�wǎ��ٳg���I�T�JM�6M������G�s�?^�T�b�t�*U���d�
��l��l6:
��
����?��?�PPhh����5e�5l�P����֭���
x�ʕ+k„	�>}����y��lu��-yyy)::Z���:v�ht$@6���L���J��ի��=��t^�|Y�����X.\x�\׮]�$�,Y2ݾԶ�>������V�B5l�������JM�6UӦM�h�"�رC����:u�ƌ��-[�l6���S�K�6:. �����4v�X���@q�����)..N�v�R�
���F\�W�H]�"'W��LJJJ�팖�{���nݺ���c*T(ݾ�6�$�/VHH��1Pf�Y���F�P��[o����zK���ڲe�BBB��{��ޓ����f����dgggt\�lmm���:h��jٲ�ё�s������*8p@U�T1: �Qp@&����ŋ:q�^{�5K��'�uttTll�6o�,GG�'����^W�\э7doo�fߍ7,}(H�!@N���1:�bgg�.]��K�.�q�6nܨ��u��]ŋ���������o�p��F�HrssSǎ5d��8qB���FG�OEGG���C5j�Pdd$��@E��x��7u��E͙3G3g�T�5�Gs��I׷e˖Z�z�&M����ǫZ�j�~��֮]��>�L&�IK�.���J)))�|��*T� I�^���\�����t�bcc-} �		Qrr��1Ȳ����f�c
�ҥK�o߾�۷��\����p����}��*W��������&M���9lѢE�U��.\�q��@>�^�z���Uk׮ee3(�(� >>>�ꫯ��?�O�>��ۧO�޽['O�T�=�쳵�ըQ�,�eʔѵk����)GGGm޼YM�6՞={t��i����9���Ӓ��͛gω�>|X�/_6:�|�B�
jذ��1 �aÆ[�///�-�v>|���K�.)44T!!!Z�d�*U�$ooou��]����Q�T�re��_�Ҍ3d6�U�|y�#�G�͛�q��iذa�?>+�@G� _����9���l�2h�޽�u떪T��=zh�ԩ�����-Q��V�\��˗k׮]�z���/.
4H/�����رc�d�]�rEIII��v��i�…���V�^��䈎�V�%��o�Ή`�ŋ+$$���)�٬��`�c@��L��*U�hҤI�4i�N�8���kΜ9�S��������ʕ+�)�ǏWPP�ƌ���0����ݻ�ѣG+  @~~~=z�ё����lٲ�:uj����xI���?���T�R=z�c?L�m�Vm۶M�V�xq��f�X�Bqqq��g������8p��+�wO�<��<
�#�>>>��%>�rKݺuU�n]���j���


Ղ4y�d5j�H����ڵ�^|�E��@�gkk�ŋ�C�8p�Z�lit$yXbb�z�表�(��������H�\B��x��ו���	&�m۶*Q��bcc��GI��ի�����[[�lQpp�Ə/I
����z�葭s@N����U@�B'�VVVj֬��5k��j�Ν


�ĉ5j�(�i�F������P�ҥ���������5x�`�<yR���FG����orww׹s�}�v5o���H�\D� _3�L92nLL�\]]�~�z������7�2e�h���:�����M��#F�gϞ����H-^�X����:�///���W6m�dt�3���Z�۷W��하����H���i�4h����d6�����ߌ ,\�P�j�҂,G�T�.]R��핔��}���f͚FG�BF �?~�F���5k���V�
����<==����g����������'???
2D...�>�;;;u��M���������]]�v��������۷�޽{FG��r�ʚ8q�fΜ���8���C�9�ƍ�D�:x� ��b�@��cc*THf�Yf�9��Ȉs���o�>i߾}���ս{�T�\95l�P}�������s����$)%%%��zX�…U�dIU�TI�[�֐!CT�r�͓���ԩ�3g���ѣ�W��c�=zT���W�:ut��)I�����ϫz��i�2[9�hѢ�X��|||���S�>�y8�󒤟~�Ik׮աC�t��Y[[륗^�o���ݻ�T�Ri�g6NV2���p:tH�ԨQ#u��5W��V�L���;z�w��O?)<<\���j׮�^|�Eu��Uf�Y
6��)��7n����4z�h�[���8�͛7���[o��֭[�%J	`V��)\�zU���j޼��/_�s��)11QIII����a�u��Annn��?��[ ܻwOׯ_����5o�<ժUKk׮5:V��ݻ�$iŊY��/�8i�3F>>>Y�����|�={��`��'���������p]�|YIII�}��Ο?�e˖���GW�^}�8F;v�4n�8�;V���:~��ѱ�\��䤑#G���������k�Νjܸ��V��I�&�̙3F��|���V�-Rxx������0�ҥK���o���[_|�����'���?�q��ںu�������3g�(!!A���Ν;��3g�dɒ��������޽kt�|'%%%�+))I?���v�ܩ�;�Ν;�ի��lْ�YϞ=U�pa�Ν;��{������H�"�ѣ��� \ �<�h"&&&�k���ruu�$}��g��dv^�����۷հaC����СCڷo�>��SըQC���
x�8I�F9-11QS�LQ�.]���('''yzzj���JLL������_�ԩSu��Y=zT�;w�g�}�:u�nݺ�Ull��1 �qssS�N�4d�%''�RRR4q�D
<X|�>��S)R��X�Qp��۷�.]��7�xCgΜј1cT�V-������FիW��ɓu�=��sڳg��.]jt�|���Z�ʕS�֭����+%%Eԟ�it�l���v����ڸq�#�nذAׯ_W�v����K	��g2�d2����He˖�رc%I���N��N�<)I������"E����V�����ٳ%I���32�c�Z�JW�^U���-m��޺z��V�Ze`2 �W��>��c���ڳg��4i"???U�\Y͚5Ӓ%K��/��(66V���7:
�\����^�z���O�V�Ҕ)S���#(����GVVV�x��ŋ��^>>>F���3bcc5`�U�PAE�����|||t����g�>,&&F^^^z�dcc��U�j„	�u�V�~���ںu�^x�mܸQ�=�\���ԩ#___Iҧ�~�n��s�Իwo�/_^666*_���������</I���oժU+��٩L�2rwwב#G2<���
��_~YE��s�=����k���~�z��<i�Gy�/��̙#���i���i�e�>߹sG,�믿.{{{)RD�?����ܴ{��'��i��ٳg���r�����F...ڼys�����#IZ�b�#���O�*��޳�_�^VVVj۶m�s~��w*T�������w��QVVViޛ��^���U���U�xqu����ï����S��U�Vjܸ�z���۷gX���� ����q���ر����d���1OR쑺:QF�GY�W��߿��K����S�7�믿��}�jӦMi�e��Qyu^e˖��׵|X�
�o����~}��Q�j�J�
�p���.h��j֬�Z�n�9s�[�"���͛7�
�\�r�v�L&�����͛^�YT�P!�����O�͛7�bŊ�0a����Ծ}{�Y��G�cT�\Y��׿4k�,���@.�~���z�-}��ڲe�z��mt$@�ZGC����q����С����Kە+W��7jÆ
ruu}�1����l�w�ѽ{�,m�.]�G}��۷+::Zŋ�$�]�V�4h� �ͬ�ҧOծ][���Z��-[����+͍�?����~�zmڴImڴ�p�Ç�E��s玤�
	6oެm۶i���jܸ����~�֭[��czRR��=��G�j���:t�^|��l���x�R*TH�V�����"��7o�E�:z�h���~�MQQQںu�"##աC�,�4�hǎ�ԩS�c�;�N�:i͚5����2e�h׮]����U�r�t}.]��ݻw�lٲrwwl���'nnn*Y����٣�7o�dɒi�Y�h�RRR�d��^�:;۷ok�Ν*Q����ܞhތ�����ޥ~/����w�q5����_�Jv��ױ�-�A�$��)�2��d��63vcF�

���FB�|%�0�� *%���3�S:��~>����ky��}��s��=������i�Ξ=���򦤤0x�`�A;7o�$((�S�N�p�BLM�>�R��w�2k�,�W���v.\��<55���bbbx��Q�
��߿?S�Ne�t�ڕ&M�P�F
,,,�\��ٳIHH����A�q��}�ߟM6l��ӧL�0�ڵݱc�������suu��ѣ�ܹ�nݺe�|�B!���,,,�ر#;v$11�-[�€<x0�:u��LJ:`eee�p��3f�V�Zň#�!�׮]�C����?DDDP�V-c�$��5#+\!�B!�xmݽ{///1b.\ ))�ÇӿRRR���͛:�Rz۴iӴ����/_�̠A�HKKc��\�|���8@�
8q�_}��6����/�g��ʊ&M�`ii�M�����ۛ��$�t�©S�x��1�N��K�.<z�=z�n�}���}��<x�G��o�>ʗ/OJJ
S�L��;b�0`.\ %%���D���K�j���?����s,�ge��eE�&M�R<oƌ?~��իs��AINN&**�F���b�ԩ���>�w�����2���<~�X;k��!C�m���
ooo�R��'((�>>>:�Yz�rM���qww'%%�;v��s��=V�\	��u��f�߹s'��ɸ��cmm��…�������E�L\\���q��a�.]���k֬����ԨQ����9���]�6G�e˖-���iDGG��khVXpqq�^�z����s�N���0`@��ظq#,����8p���@��?/�E�յkW�M�F��Y�r%�y��2�����đY��+W�C���_�0�2eʰq�F:D߾}ػw��xV��C��Z���1M�&�B!�"c666x{{�e�n޼�������dɒ��׏_�Ug"!�x��˗��s���ݻ��"�<yR;���Çe��B��)!��Tpp�ξl��&�l���M#88Xg�M���|}}3�ט6m�Ԅ	ҭgĈ/<�q��aenn�5f��ccǎU��ٳ�^�cǎ)@999i���ϯu�����"�ǏW�jٲ�JKK�9����Z�l��yi���չg��…��˗O���+s��)({{���Yٽ~�Օ�G�)@��ؼ��2e�(@���ozu\�p!�:2�%;}��_+@�j�J�Ljj�jذa��}���R�J�}��rppP�:v�X��g�����+@���['��|:w�5c����
P�7o�V����wߥ[N)ß'"w����mJ)�����UTT�N���l��ׯ��v�rvvVЋ����ׯ�������۾}{���>���f��n_f����9}��Z�|��裏T�&M�����֭��u���Ѥ�;wΠ�Μ9�M�w�rvvV���Ӧe��j����z�s��m���:t����BC��B!�Fqqqj֬Y���Y���N
6L�u!�x�yxx�*U����c�"���v�RT-[�L�{4!�BCV�BaM�@T IDATt�����B-�l��&�lo�l��F�u�V>���t�����w6��ܿ�<y���ӧO�9�믿0t�P��...(��|��6-))	[[�,���]�v0v�XLMu�4755�O>`��������ׯ��t��С���\�vM{�z��(��~�z�����~�ɗ/�?~a�?���u���;V�lY�k����Qxx8�|�^sssƏ�a{��קjժ����4�c��_�N�5pqq�4��^777�)¶m۴3]����p�B����;w.&&&,^���O�j�����*T77�l����͛gzn"�r�
u���IO��իWpww�Y������/ܮfe�={�P�re,,,h߾}��������ñ��"**�9s�гgO���HNN68��U�jU�?>�w�f����|��7�wrr2(_���.X� ���Y��w���@�z�4i�<B!�B��spp`�ȑDGGs��9
���iذ!*T`ҤI�>}��a
!�Q͞=��W�ʪ�B�A�V��cǎt�ԉ_~��…;$!��1p!�B!�ⵥ�R�����z��\�p!�:4/�V�P���P���t�k^�5t�`��			Y>
M��A�Ӥg�p�
�������
h_�?|�0~~~�.]�ҥKӧO6n�HJJJ�����~�y����u1ĥK�gҤI�m�;;;�R��N�:u
�z��[F�\uF���X�l�N�f_s<3Y�&xzzr��>��
�z�*�ڵ�\�r8;;s��~��g:ĝ;w�����*[�>O3pH��4�4[f����D����>|�0˱,X�I�&�������ٻw�K�۶m[�o���ɓ�U����,Z��:�aÆ��3�PM�6��Ņ[�n�����>3�������Ҡ|��w�4������=���6�B!���T��~�)�Ν#::�/_N��թS��|�v�B�Mʖ-K`` S�N%..���!rȔ)S`Ĉ�Y����?�B��d��B!�B����5d5�?�����)P��7o�H�"zy4/��b�f��ٳg
�����}�`�B�
��_3s�f0��4�:"  ��7��~��5V�XA�nݨV��.]ʱ؞������G2ͻn�:ʗ/O���qwwgʔ)�ڵ����;Kmf��4����fN�ݻ7ffflٲE���Mxx8����{v����7[�l`�ܹt��
��ݻ�p�B�|={�|�v�ecccPy�7h����N��v�Txx�����h�=���T�B�޽QJ1m�4�{3��,Xwww�-[ƪU���̞=[�G3x��gGVV�xVժU����4��`�ܔ�k[�X1�ߕ���I��B!�B�gggfΜ�իWٻw/���gƌ899ѬY3/^��۷��B�2cƌ��Ύ�#G;!�Kz��	��>��o�eƌ2��B�Ȁ!�"...���;�s��exl����9��#G�~��W�B��4�6ܻw�T�[ZZ�^�3g�0l�0LLLX�f
ժU{a�΂޴iSv��aP����S�X1��5/�)�{�����v��o��ƕ+W

�o߾T�T	�?����Ç�Jl/s��o�> ��&4BBB��ҥKT�R�I�&�l�26o�����fv�HSFs�yեaooO�6mHMMeժU���]������Fɒ%
�=;פe˖���#<<��Ǐs��a,--�ܹ3=z���_�?�`˖--Z�֭[�T���զM�O�ΩS�x��	111L�>]/o˖-�0agϞ%--�;w�0o�<\\\<x�6��3Cge�ׯ���?,]�4��v��~��G�X������A��6m"))�K�.1cƌL�L�|||

�o���ŋ������C8��1ct�#;��Y���+W��,M�&�B!�"癚�ҢE���;n޼��͛)U�cƌ��ޞ�;�f͚l�,(�o�|��1w�\���صkW��u�ĉ\�?3���ȋ��Ç�ҥ������O2$G�B��ɀ!��
0j�(z���'N�p�Bƌ��ѣY�`����+�P!����$"##�T.99ooo����qww�0o���8u�Aukf�_�x�v���駟x���Ú63�y�ȑ#:�rJ�ҥ�ӧ˖-�ܹs����
Z��ز{�����}	Z��F�N�
��%K8s�_|�}�����]gu��O�f�nv��F����o閉��δ݀�V�\	����u�
��kbff���gϞ��_�}iZ�Z���
4@)Ŗ-[�p����:/�� �^�z���ĵk��aÆ��Ӈk׮��
��ɉ�'O���G�
pssc����˗�#Fh�j4xzzf�������O?��Ą��0�:Ym����3fЬY35jĄ	tVjѢ��*2M�6�G���~��y�l�R�BǺu����Օ-Z0r�H�_�N�2e��㏳�?ّ�k۸qc ��Ϛ4� H!�B!D��L�B||<+V���Ԕ�}�R�D	���ٲe�?6v�B�+:t耇��1)))�҆����gEBK^����iٲ%����ٳ'�>�B�wɀ!�"������*�߿?��$&M����vvv�������ĉIJJz�Q
!�9�]�v��/�?y�D���111�C�:�G���ɓڟ�/���{ٲez�N�:���	NNNڴ���ӦM����ٳ'�����̙3155e����t777���k���>}�̙3x�^�!���011!66V��^ZNƖ��g��'K�
�ԩ��^�x�޽{��={��߆���>�ڵ+�f�B)�SF)�-�"]�t�p�����Lll,E�}ဢ�e��hmݺ///��={�Ю����vE�������Y�t)���.\sss*U��_|�������-AAA���bgg����E��X�Bg�ѣG������_�׭[�=z���ƬY��ծ��'�'O�J�*XZZbiiI���	���?��1b^^^*TKKK\]]�4iR�1ft^Æ
c�…�hтw�ySSS,--�T�C�a����A�ퟬ�ʵuss��Ɔ���z"""���ծ�!�B!�xulmm�%<<���xfϞM||<]�v��Ύ����w�^�&�B�7ɜ9s�z�����9i��͹R�Y����s������������t�t!�"]J!�x���~F������sn��Z����[U�^=��_i�n޼��ի�����W�B�\�����7������p_#..N*TH��SG�QIIIjϞ=j����R����'Nh�l޼Y�f͚��Ç��r��yeee�5n�8�=z�v�ޭ�W���駟ꔹ|��*^��Tٲe�…���RSSUbb����Q_������5y�d��׮]S
P��ҥ����U�?V����K�.
P666��?��)��H�x``�TժU�Ν;�ÇUjj����Qnnn
Pݻwϕزs�^t�����ƍj˖-�m۶
Pj�����E�
������Փ'OԩS�T�޽�yu�ʕLc�N=x�@988(@u��M�>}Z������XյkW�?�L��RJ
4H��>xa�����5y��rttTfff���Bݽ{W�OLLL�J�(��<y�s<��g�<��U���7�����ܹs��/�'�k�x�b������iqqq���E}����:L!D&�O!�/��ի�o�Qu��Q����WÇWG�5vhB�c���ekk��^���u�Yhn{b�:�9ÁTѢEUÆ
�����	!�x[�
B!D\\\pqq��?}��%K����I�F�h֬}��aӦM:�����Ȃpww�Q�Ft�ܙE���&�l�Ɣ���ڵk�W�%J���)Y�$...�]������!��		��ښݻwӠA���iժK�.%%%����S�vmm�,�'O�����t7��+�h�"LLL�>}:%K�$�����{���ҨQ#u�rrrb�޽T�X�˗/��R�|y,,,�����w�e�رܾ}�ɓ'��`P�T)������b���T�^+++�W���͛���"88�2eʼt�7��U�r��ڶm���-����ر���\�-;��Y�_3���qwwg�Ν��ڲ~�z�5k�i,cǎ`��Ŕ,YsssjԨ��ի�4i+V�رc�֕�>*P��֭#��lذ�jժaiiI���駟X�`fff/l;  �۷o��*�����D;�˖-uf���I�ƍ�֭��y�� �.͚5��Ņ�����S._��}�֩S���������dɒkӂ����������.�B!�x1GGGF�����9s����g�֭ԯ_�J�*�駟r��9c�)�/e�ر���1j�(>|H`` �ʕ���
'''&L�@rr�����/&&&�^�Z�������~g�w���l���ڴiC���)^�8C��ѣG:y����۷/ŋ��ښ^�z���C��}��)�'O�r��XYYQ�@5j�?���N�B�E}aaa�mۖ�͛�g��/nXg
!��1��!�oޠ.�os޼yڴ�5k�d9��ǏU�޽��7d�����dz�RJ����թ�z�j���~�����!����p�s�Ω�}�*GGGeaa�
*�ڴi�v�ܩ��p��:+d�=��}���p�����RU�RE}��*999ø����ҥKU�v픝�����P���S�*UR�
R'O�|a?���*???egg���͕���z�����ӧ�͟Q��w�7n��V�����V���B�
jԨQ�֭[�[V�߳u=������ŋ+WWW��g�����,��ʕ+U�ڵ����*X��jݺ���矕RJ�Z�J�u���WV�H)�.\����}m��ի��Q%&&*@(P òU�TQ��Q�F�y3�?��D)��;��t��t�/X�@j߾}֑�{�EdFj�ʍ��>}z�S�n�Zg��f�ε���V�7V7n�P7n�P�7V�����B�e�B�{�=��������ԩ����u��5c�&�ٲm�6���p����g٭[��~��?��R�J�B�
iWX�r�*T��rppPw����;���$��P��R�+��w���|���*W��^�N�:�};f̘?��5k֫�naC�^�={�255U��ފ�B!Dv�7u�B�1��͛7W���*22R����G�i=t��9��-[��������:w�z���?T�~������駟2�E)�������}�$::Z9;;�#F�d�!�x�d��o��/*@U�T�ء�q�yb\��iii*88X����ƍ�z��N�:��S������eCF��k�F��F��BBB^a�B����>!�B侴�4�g�կ_?U�Hejj��7o�/^��ܹc��"K<<<�;CՠAu��	����bccU�&M����{m�ݻw+ռys���բEebb�v�ڥ͓��3S�L1�
MyWWWu��y����&L��U�xqm>MZ�
ԑ#G��Ǐ���U�ҥ�b(T���/���?~�ԢE�����r�kE6d�>��bZZ�6l�211Q3g���~B�v3QJ)�B�W��Ą��`|}}���pqq1�������4mt�Ё[�nѰaC5jD�-ppp�+gh>.\���-[���צ������AݺuY�ti��<�Ύ;(V��N�w���͍���lݺ�%{B!�����ЫW/4�=��&�ի���������ؐ�����X����q��1c�|||		1B�o.y���B��@~�	!����Ǐٱc!!!lٲ�'O���憏�������;D!�x�+W�P�\9�>}ʥK�([�����A�
h޼9���Ӧ�5�ٳgӰaC���6ls���711��V�Z�<yҠ64���7�֭���@���155%--
�5j��ݻiժ���m۶ѱcG�J�*���i۶-nnnxxxP�\���?���r�@޽��������fժU���#{*�B����!�o��ÇceeETTs�̡gϞ�����|W�^��������ŋ_�ݻw(P���1M�&�B!�0�
гgO���ãG�x��	.\�O>᫯�`��S!�B!�"�YYY����ڵk�u�AAA<}����J�,���/��ᤤ�;T!�HW�2e033�\�r���h�
*�Sfڴi���DEEQ�Z5f̘�i;.\�R��K�E���ӧ�4�{�5�)׬Y3��fΜ���5;w�dԨQ���L�6����Lc�NVx/޹s�֭[�g�v��)�-�B�8p!����e��*�mۖ�۷3y�djժErr2�-�C�lذ!�2����Ç/<����T�ǹ&M�G!�B׬Y�(\�0'N������*U���_
��3hѢ�qB!�B!�x�lmm���c�ܸ֭q�o���k׮ѥK���4h����yAS!^�}O�����gx����3{��׆����Ѽ��
zy����~�:AAA4nܘ��D&L�@�R�X�d�A� r_v���p/N�2WWW���8x�`�6�B��%.�B�,(X� ���,[��U�V���σ�={v������7�$::��G��0�bŊ��I��B!��U�n]bbb>|8U�V���sssJ�*���7���|��'�S!�B!��h�/ΐ!C�����?�$00�#G�вeKJ�.��ѣ��ߌ�B�����;PJ�lO�<��?~�xbbb�W�����7��6���O���k�+V�:�QQQ��/R�}����=z�O>������#Gf�m�;�z��{q������jW�B!r���B!�]�t��ҡC*V�ȵk�����kٲ%+V�`„	�;��+r��=֬Y��իqqq��
abb�R��W�R�ti*W�L||<W�\�Xq��m!�B�z(U�s��1vB亰�0<<<��Ba���0�w�n�0�B�ҥK3f�ƌ��ӧ	

%44�Y�fQ�re|||���R�J�U��ڵ+3f̠hѢ8���X�5k3gΤe˖�ٳ�={�0g��4iž={hݺ5��ͣs�δj�
����k�m�6|}}Y�`5k�����a(&N�ȠA�X�z5�5�ĉ4H/o���t��-��ϏZ�jq��E@w�a\Y�O�ҽ���������e�Q!�x!p!�B��ߟiӦ1c�f̘�s�nݺY���}�8y�$~~~:����Lj#��E���ݻxzzbggGxx8�7f����:uJ�^�S�Nдiӗ;i!�B!�Ȣ��Tz��a�0�B!�B�ժU��/���/��ȑ#�����w���g���₏�={����ء
!�"���lڴ��g�r��]���mll�5k���#  �
�z�j,,,X�r%�j���ߟ��
.�;�í[��\�2eʔѮ�i�&"##qvv�i��6�b���lذ�'Nмysm����Ν��;v�X�СC:t�αg�
�2�>ɫ�b���e��B�\gj��BCDGGm�<==�<y2U�T���KKKʗ/O@@��y��������/vvv���Q�`AZ�h��+tV�=z4���������666DDD�����-mڴ��B!�B]����.)/�l��&�l��l��B!�0@�
�;w.׮]c׮]ԬY�/���ҥKӲeK~���޽k�0�o�B�
����)\�0���Ã��(�ԩ�СC�v�,���	''',X@\\����y��Q�\9���y���^eʔ��ܜ�E�굑VVV�۷�!C���;�`eeE�=�����4�e˖Q�n]���G�|��Q�����\�2;�&r���I^����c�D��jժ�t�B�%&J)e� �B�=LLL���7�}�5K�,aٲelڴI;k������`РA�����
!�x!!!���͟m���z���}��}!�0�<O���?>4fHB!D�4i҄�F(� IDAT?���'�B�7��Ǐٶm������Ϥ����憯�/������;D!D���c�}�]j֬ɏ?�h�p�ȓRRR�ׯ�֭�ᆪO�>�I!�[���!�"����ٺu+����;���`;;;�����B�5aaaxxx;!�&,,��ݻ;�9rD��B�7NXX�C!��deeE׮]�ڵ+			���O���һwo��ˇ��;����m�V~�!r���,�]�v�ܹ��m�;$!�����ɱc�غu+mڴ1vHB!�22�B!����%Wꍎ�Εzs���5�}�Æ
�w��lٲ����/_>#G'�BdMjj*=z�0vB!^�����.�⍢Y�B!�o�
����s��-���

�s��-Z��ݻ���C�&M0555v�B�<��͍�]���Gq��I�����yB\\:t�Ν;DDDP�V-c�$��-$.�B�7���3C�e�̙|�ԭ[��Q	!�Y,/�
!�B!�B!rL�%�����r�
!!!�]��%K����HϞ=�ի�k�6v�B�<b�ܹT�Z�9s�h�p�x����СC
*��Ç)]���CB�B!�ho�J����___c�!�Bd���9x��B���4i��l�0�B!�B�*S��ƍcܸq���Bhh(3gΤjժx{{���K�
���
V�ti&L���_~�����.�Kؽ{7ݺu�N�:lܸ�"E�;$!�o��pq��U�9��!�Rݻw7vB!��Ȏ9BXX��n(�Ȳ��0,,,��xM����
�~?+e��ܹsT�\9�垷~�z���hذ!=z�x�:�B!��mW�zu�N�ʔ)S8r�!!!,Z��O?��������C�=���7v�B�7ШQ�X�b�F�",,����FZ�j��ӓ+V`eee쐄B��^z����իWN�"�xK)���B!�x
���l�0�o�\J�nF����_zE�'N�p�B֭[�R��={R�R%j׮�C�
!�B!����Ą�
ҰaC�̙��ݻ	

��>c���4o�___<==eVm!������?>�۷g�Ν�m���!	�F�:u*�&Mb�رL�>c�$�B`�S)�d�M6ٲ���tB!�B!�x����_z Df����u$%%1i�$���������OOO&N�HRRRD)�B!��Yfff�mۖ�˗���)R�~�!vvvt�ڕu����dB��k��
FJJ���⍐��ƠA����OY�p!3f̐�B!^/�…B�z��ŦM���B�ڑ���B�U...�>��M�|�rnݺ����6��LJ��P�/_�СC��B!�B�m������OOO�߿ϦM�		�W�^X[[ӵkW|||hݺ5�W�;w.ժUc���;!^k�=�gϞ�ݻ�
6ХKc�$�B���W�^�ȑ#9]�"�޽��C���B����ɜ���E��nCS��,--)^�8
6$  {{���/F�_����(6lH�=^Y�B�z�*ݺu��ё�7��ҥ7n�`�ƍ8::�{�n���8{�,���/^�-Z0t�Plll�m#��ٝ;w���oٿ?III�jՊ��ǧ[>�6�}6?�Vbb"˖-c׮]����/^����ӿ,--��X�v-��գD���%K����ڵk�ݻ7
0�k�B!�BdS�B����ߟ�������Jǎ)V�=z��LJƍ�,�Beʔ!00��S����G�R�����[�nѹsg.]�Ğ={hР��CB!����ҫW���V��(���x��_���!!�B�)))ڗ���.\H͚5�V��8q���n�:�R��ٓJ�*Q�vmc�&��E�K���Ņcǎq��I���ɓ'�~�:
4��ёŋ�l�2�����]����_�fBB}����ڴ_~��G���}�6SRR<x0�O�֦ݼy��� N�:�…155`ǎ$&&���W���+G�e�Νt��͠sB!�B�3������G��Gq��eBCC	

eѢE�.]|||�U���CB�&Ǝ��ի9r��!D:.\�@�������bŊF�H!�H_��А����,�*ijd�!�"s�U�{�+5�g�����\�|���'�|�ƍ������JJJbҤIxyyagg���''N$,,L{.B���[�n;v��[���ضm^^^���H�Ν111!&&�A�ap{�W���8::2e�*U�DLL�'O��kH����鮢�f�N�>M�5?~<�˗�ʕ+L�6��G��e�<<<8t�U�VՋA�v��!p!�B!�FT�lYƏ���9y�$k׮%44�����jժ��닏��ʕ3v�B#���bΜ9t�ԉݻw��{�;$!^G��s�Δ-[���p��~�B��M�
�B!��ၯ����B!^;!!!lڴ��a�V�{�U���ʊ*U�0g����9�<�������ءl���ܺuooom������,_���C�1:!Dvi�ߙ�GEEQ�hQv����ѣ����ɓ'�ڵ�%JЬY38�R�3gΰ}�v.\���c�x��q�۷����S�zu�֭˸q�6l�Nޗis׮]L�6
{{{ʕ+�g�}���۶m��8w�eʔѫ���I'�B!�B�Y�&5k�d�ԩDFF���8q"
4��ח=zP�dIc�*�0��;ҥK>��CN�<�����C��6oތ��/-[�dݺu�ϟ��!	!�/$.�B]����޽���B!^;���2�"��ܹ÷�~���IJJ�U�V�?^/��7�>}�ҥKٹs'7o���‚���ӥK��ϖ;t�3f�`׮]XZZҤI>��c�/��v��MXXgϞ%99��ŋӢE�JZZ�:u�H�"lܸSSSm��W���鉃��7oδ,,,`���8p@;�"�+/����&�6X�t){���Ν;/^�V�Z1p�@lmmu�޾}����s��A���(_�<����h�IHH`�ڵԫWOg&��%K����ڵk�ݻ7
ȴ�o&sss�t����ˉ���U�VDFFr��}�����seĈ�9sF�������@�:u��L�W�^���=��/^���ݻ�>�4i�<B!�B!^&&&4nܘƍ3o�<v��Ehh(�&Mb�ȑ�l�___<==)T����B�Bs�̡Z�j̙3��c�;!�jɒ%|����׏E�i?�B!^g2�B!�B!D����@߾}�~��6�_~�ѣG��]�p!�V���CLL�=�W�^:����+���HNNf۶m����Y�������ŋY�l�NZ||<k׮�|����ٓ�� ~��Wڶm��w���]�6.\�0�!1���Ç��׏K�.�		��ѣik<z��k_j8{�l�av��Abb"���z�\]]9z�(;w�[�n/8s!����^�bQ׮]Y�r%?��3�Z�b۶m��������9s����4oޜ���S�z�,��(�	ss��M_���d<�B���	��;
M�&�B!�B�ד���ڵ�]�v$%%�u�VBBB2dC��C����ұcG�����"��-[������_ҫW/����R�	&0c�>��s&M�d쐄B��k�;x� �jժ���`ee���#^^^lݺ���2&&&9������6+++����С���<}�4G����k)��9�Ν�����9r$#G�d����0*!��ͷz�j�_����#+W�����,]��46n���8|�0 00�u����?x� �������aooύ7X�fM�m���ȡC������ ""�^�zaccÊ+t�j\4m�4�s�(Z�(���{��ҳj�*.]����AAA>|�e˖aoo�ŋu�&..{{{mޥK��`�q��!�V��wL���#�Ȼ���iذ!��ԩS8p��͛�<7���

b���t��Y��'O�Ԗ��#Ǐ�I?u�^ޗi������p������G�j�+V�����գI��B!�B����ˋ�7��_�h�"�dɒ����c���Ҍ�"�3�%J0z�hc�"�+������?3g�d���2�B!�G\�nݢC�4mڔ~���gϒ��DJJ
qqqlذ�N�:ѱcG<x`�p󌔔���پ};~~~t��]]!�Q�F�͐�q��	.\Ș1c=z4,���
!����E��`���T�^�֭˸q�2mG�Cpp0�ׯ����ˋ��h�l٢�?00WWW,,,�Y�&&L`�޽�q��;F�j�ؾ};���㫯���ټP�Bxyyq��y"##�W���?���Oݺu3=
����Ҟ��ң9�	&P�fM,,,�U��vՊ={��0oݺu�8q�^����eʔ�;��䤓G��u�֍��4HII���+�|�&%%��g��<W��]�vL�6��Ǐ���bcc�:uj�e2kS3��իW��Z�l	��,<{�,iiiܹs�y��������y+W���+W��֤i�!�B!�x�*T��}��k�.����/8w��ڵ��ޞ?�����LWJB�y������Y�v��K"�y��;vdӦM������;$!�"�����5b������3s�LbccILL���ǜ={�/���
�m�6���
�!O�G)�����r��M/^L���ٸq�v&U!�ȫ��ߟnzRR�&M���;;;������d�ĉ$%%��(�B�7S\\5k��I�S�N�e����QQQ̙3��={Drrr��6l��_�vm��s��m��}��}�L�ºu�t����~~~XYY�|�r"##IKK�Q�F/<�^{E�y阞w��ujժ�����7nh�4/?�<r��]
(�wL���#��ۚ6m�]���ё����oѢ�'O���???Ο?�=~��Y�����r�����3p�@6l���?U�T��kh��箧��v������8y�$~~~4h�777V�^M�|�1b���ƍ鯲�I�ʊGB!�B!^O%K�dذaDEE����G�w�^7nL�r�?~<111�S��:v�Hǎ���IMM5v8B��ׯӴiSbccٿ?m۶5vHB!D���.���åK�h޼9����5�jժamm���%�+Wf�ĉDFFR�pa���ϒ%K�v�`nnNɒ%<x0.`�ҥF�J�z~V�f���ܺuooom����n�Ҿl)�B�����u��k<?P��A
m۶e���L�<�Z�j���̢E��С6l��|���LM3�3�믿�̙38::���ǧ�~����-Z�nݺq��	N�:EDD���k�?��K�Y��P/Z��뢙>���Q��^9!ě���LMM������1c�жm[�gxիWg���8�u�����%K�.��ˋ"E�`iiI�6m�+e��ѣG����)))������/vvv���Q�`AZ�h��+tV�pss���F��VDD����i�Ơ�B!�B�f(W�'N$66����=zL͚5y��w�6m�/_6v�B��`�.]������*66WWWRSS9|��A�	!���W>��ʕ+8�ҥKcee����z�������711�t{^tt4ݻw�w��Ғ����Çu�EDD�}�v�y�6n�H�…3��F�̘1��^�ٳg���KKK�…/</�cǎѪU+���)R����=z4�r.\`��T�P+++
.���3��9���K�LVc{��^?Cyyy�գ�+W����L����3jd�N�>���%J���Ғ�u������%����뙝믱n�:jԨ���%������/�>JNNfΜ94k֌bŊannN����ر#���K��!�#ě��ӧ,Y�OOO5jD�f��ӧ�6m�˛��Ȃpww�Q�Ft�ܙE�i_�t�<;�$!!��k�R�^=����6...�]�����\<S!�"optt�h�����)X� ���,[��U�V���σ�={�^ޓ'O��8q��e�fXTTAAA>\��gWS�ݻ7����[����HLMM�3�"55�����_6�g������k����i�����:y��(V�����;�I��B�}$::�޽{�+P�ӦM#""���HV�\I�6m�e�͛��Ho�G���	d׮]DFF2}�tlll���f۶mټy3G�aǎ��d�ȑ���s������̙3�P��^<�������������~��w������y��B!�B�:�U�_}���'4k֌9s�P�|y7n̂�믿��"�ʖ-�رc����u>�"/ٷoM�6�L�2<x�2e�;$!�⥼�ԬY���k׮���B||<!!!8;;�m۶,�imm���r�J6lȏ?���۷IMM�ҥK|��W4k֌G�i�Y����S�h�L�
 ""�cǎ�oݺ��u�j�*nܸAjj*7n�`�ʕԩS�_�5�:�9B�f�ػw/���ܻw���p�6m��Çu�;vggg���;���RRR��>Ǐ��>�N�:zT�Ll�ˍ맡Y&/_�|��۷/Ǐ'11������ڵK����Mjj*'N��K�.�{�E2�%����뙝믱d�������%55���8����U�;w����ػ���㯤R�e�#��
�,e7L�Xu�l�!|g��
1�a�-2Ӑ��b�dFY3��i0����wΧ�S*t,���q?��}����}]WZZ�Z�b�رDEEq��m=zĭ[�رc;v��.���u�x�bV�Z��˗y��!���$$$0m�4���5�������bݺu���7nh\�o�g�ݻw������S�mNNN����z�
!�"�.]�0c��������ĉL�>������~����өS�666��?}�t����رc̘1x2*����Đ����ӧ�פ���j��X�"={�d׮]���ҠA�|	P���$11ooo����V���)'u'�3fp��q���9~�83g��g�P��>s�L�1KHH���I=��K�rmS��^!�T�
�J�*Z�=���������C��	!�B!�(.�nݚ%K�p��u�o�N�ڵ�Z�jt�҅u����D�j���y��w?~��C��K�.t�ԉ={��L!��UWl.n߾���+iii�3���$222���a�Сdee�T*�q��~*�*ע~�`ժU��/\�����y��^^^\�p���,��ߏ��5ǎc֬Y�����|��'j���	�[����X�������;��ٓ��D�.={�����׏��d�ezzz������ٷo�k�&++�iӦi�3fiii|��g$%%���Ezz:���;���\�x�)S����r*�+(��㜣�甔�DBBw��eΜ9Enߝ;wP*��}N�8Aff&���t�ؑ#F<3V]���|6Ncƌ�cǎ=z���LN�<I�޽���@�P��j�~�����cggGtt4���<x���XQ�T�>���񺊈��L�����������q�FN�<���=!!!:t���p>��>Ldd$@���8p�����A���#�B��yxxP�n]���6l-[�dРAԫW�4x�}�m۶8::���@�&Mr�P���e˖|��g$''ckk���[�u�;)L�4	'''<<<8{��f��ӧ��8�Jhw`x�z�,Z�j��9t�̚5Kg���Ƥ6h� ����v�����l�OOO�_�������������f͚\�rEs̆•+Wr����C׬$���B�)LMM	 22�7np��
"##	�s�!�B!�o.###>��c֯_OJJ
����*U��ÇS�J\]]�����UQ�J�b�������o�>}�#�3g�������",,L�e
!�xc[��+V������/s����ښR�JѲeKV��� IDAT�\��ѣ�{�.K�,ɷ���X&M���q�P*��m˗/'33777�-[F͚5122�M�6����a�M~�蘺p-�E�q��=:t�@DDvvvcggGDD:t��c���:�o۶-�j�
333ڵk�ʕ+8x�VޣG�0{�l���122��Ԕ����֭[_Xl9���SFF���L�4��c����3���?���XXXP�Z�"�o�ʕܼy��;���-���4nܘ]�vaoo�̸u�R��S��Y�95nܘݻwӤI����_�>?��#~�!�o�fŊ����/�ׯ�U�V���bbbB�-X�~=Ǐ/���(r>8��3V^�/�����u������+qqq�N�d�x2³��
���ԪU����g�t���S(֬YS+�B���i�i���|������R�|y����ܹ���D~\\\�4i������cccj׮��uvl�;w.�[��dɒT�T���|�r��O7n}������.3g�dذa�v�N@kƸ�m�>�
�cP�F
���	

}fg��ƤfnnΚ5k�ׯ�*U��АJ�*�P(X�v-�����|�����уr��Q�dIlll�:u�&f5ggg��̈���UgTTeʔ�̘!�o��M�2r�H	dԨQ:;
!�B!�x�������Ɩ-[�q��/���o߾T�ROOO���ãG���"=z�k׮|���dgg�;!���Ǐ�f���̙3����S�D�=�*�B�t%����۷���:�:�y��gϞ\3;�ݽ{�BAvv6���̜9Sk�/���ȑ#s����T-##�2e��19��?~|�/	%J�`„	�����ܹSg�F��+�y�����j�W�^���$�v�ʨQ�h۶-իW���.W��7������[>��_~I���unk׮]����o۶mL�0!�>%K���ח=z���X�r|
{>�?'???J��~�0n�8~��W�oߎ��?/^̳�����kG]�G�ו��7S�L!66���X�-[���'J�R���˗�|�8w�\��ܾ}x�����i�<B!��_�ҥ�����J��t'
]�6z�����je˖e�����y�sss�sRwp�鯿��tʬU��3�/��Ƥ���e�2~��My^�B��	j��}�]MZ�ҥQ*��^��k׮i:q_�v�?����Çk:�
!��@�Tj
8#�B!�B�T�|y>��S>��S�_�Nxx8���8;;S�re���P(�hѢ@�m!����iР.�V+���xxx���?J�~���B��[7“'O`ii���A��������<�6l/^��ښ��P

���hmԨQ�bR�����V���Uw�x�:=��m���s��G1}���V���/111xxx`ee���C�!""����[N/�=�T�RX[[�T*ٻw/���y�Uw,ȩ(�KLL�Y�f:�qtt|fܺb)��)�,l�����t���éS�tn?�<۶mc�ĉ|��GXZZ�۹C���(ԣW?=�u^�/�G}�Ν;�4i�5�,]���]���?j���w�^���7u��W��P!��푞�έ[�4�0@�=��m����?�@jj*�?�…��C7n��РAT�RE3�<�q����b�]!�B!�B��EժU��СC�={��#G�w�^�]�6����8qB�a
!r���fܸqL�2���d}�#D�ݾ}�Ν;��o��g��l!��Ul.������V�ZExx8���lݺ�����ʣ~���3V�;;�>}�@��\S��;k�-[Vg~�����׹=���2x�`"""hҤ�&�ʕ+�]��>}�`kk���_Xl9=�S�T��������S�N���kӢ�O�����ʕ+�oy�R��S��Y�9��^uzzz�V��M��]�6�kצG�L�6��{���>��2ڬx�XXXУGV�^���4h���̝;W�G�i۶m�:����q���|�x�w�'39=M���#�B�7_۶mqvv��ɓ����9��k׮|��t�ؑ�͛ӷo_���(_�|��=LMM	 22�7np��
"##	(�oh!�B!�B!�Vu��aҤI�<y���x�����뱷��Q�F|��\�tI�a
!*T���_~��P�(��/Һuk._�Ltt4m۶�wHB!�KSl.Գ6ܹsG����ѣG��=u��G�����7bkk�o�I\�M�6�޽�@�Ϟ=�;C5����~]�“���y��ݛ�G�r��%�������������oo��󜿗�(�S�����z���œϢ�W��5�>9;����������W�'Nd���lݺ��g�����ٳ�f4���t�ԩ�y�i�u��???N�>ͣG��u�,���///M^�L�/_֤խ[@�EMu�:�B!�|�*U��ĄV�Z1��\�;�nƏ�رc�_�>�J��D�XZZ���Bpp0ժU˵OӦM9r$���2j�(���B!�B!�B��iܸ1�}�/^�?���ɉ��@��}Z�n͒%KHII�w�B����̘7o���DEE�;!
$>>GGG��������yN!��MQl.ԳI<x�P�=x�www��ә2e
=z��3o�ڵHLL,P����,[�L3[B~~��'RSS5��3���:���E���bȐ!�^��3gΰm�6���Rb+�{���>{{{�=�s����"��ǧ ��y��_:�������X�|9�N�b�ԩxzzңG��c?~\�6
�:4h�d4�m���舟�����f͚?~Z�h���36l�T�R�3F�W=C����f��V�Z�?��i�N�B!��/�V/ӎ;8p�,�R�J/���P�D	�J%6l ::�Ç�m�6|}}�m�R�dΜ9̙3�BQ�!�WHH��"�,����,!!!���B!�x�J�(A۶mY�l�fV�5j���CժU�ҥ�֭+�@�B���ի]�ta�ȑdgg�;!�{�nڷo���=QQQT�ZU�!	!�/]�⪨K�.���3}�t:w�Lɒ�U��������̎;4�_}�Ǐ����|��С��'�W��<�����H�
�Q�/^�y��t�ܙ�{�����?�����β�^�J`` %J�૯�Ҥ;;;s��QfϞ�G}D������c����}���f͚\�t���D��촶999��"c+�{��Ҿ޽{͜9s�ܹ3��<�R�4�VQ�Oa�ga��H�6m�ڛ���̙3�:2�;w��*g�ܹ��322^��-B��~�QJ�,Ixx8�ϟ�z��i�F��L�2�j�*~��wRRR(]�4M�4���K�)�|�-Y����d����'�g���'**��j�E�2e�ܹs1�X!�B!��_|A�^���BQhVVV�A!���ѭ[7�u�Fzz:������2|�p����ڵ+J���]�bjj��p�x+,X��
�t�R���}�#�Nk֬a���(
V�\�����CB!���9�r���իWUe˖U�?�Pu��!UFF���~S
6Lell�*Y���رc�}�nݪT
6Tݻw�={Vebb�T_��*99Yu��}կ������S�ɓ'k�s��ջᆱT��j��Ū���[���CUzz�*!!A5{�lU�ʕU�jҤIZ�_�rEenn�T={�T�8qB����:qKgϞ*@eff��x��~����v��_��jϞ=�{��>|�JHHP9;;�U߾}_JlE9i��Qڗ����V��
P���Gu��IUVV��ĉ�޽{�J�.�g���R��S��Y�9c._��J�P�N�>����T��ǫ>��C����R���j����V�#F����U��٪��DՀ4��K�.����B��Uppp��o�e˖�TW�^դ]�zU���Z�r�#B�Oo�'�R�R*�y�!DA��~��B�&��7!�B��n߾�Z�j��cǎ*CCC����j���;w�>|���x���,,,T7n��w(B�2u�T�������O���c}�#�B+�J�z�!!!���u1O��c�\]]����Y�ҥK1b�f����G�>3��u1t�P��;::��o�Q�T)����D\\\HJJʳCCC����2eJ�m۶m�o߾dff��fbbBXXX����3
�u�umOMM�e˖�:uJ�>ժU�ԨQ��V��W�v>˳�/J�8���3���ϵOPP���暢�Y����|�c޸q#���X�"�v�I�&���+W2l�0�uL�8���0������ӧO���;ׅy�o.���Q*�:��V��׏6m�0~�xfϞMtt4���>��B����O��� 88X�B����o!�o"�|B!��7nNhh(��bŊ����BA�V�4�!^���t�ׯO���Y�n������lF���5kX�x1^^^�I!�(v%����]���2k�,���Krr2fff4oޜq��ѹsg����w�����N�:̜9�����өU����gܸq�������ޞ��֯_ODD��7o����+++:t�Q�hР��:�w�N||<3g���_����bŊt���ׯ_�v�baaALL�f�b�֭\�p��R�fMz��Ʉ	�X��K����8�}�Z���?��o�a�޽���ԭ[�)S�еkW<==133+t,�=>�=�E9�j�����ؘ������\�2ݻwg�ĉXZZj���011a޼y�:u
�7o���7�|�	u��a�,_�\�Å�����Rʍ��{)����Ԕ��F�̀���d�…��B!�[#$$���}�!�x
����M޿�B���B!�v����=�ѣGs��yBCC	

e�ҥXYY���R��>�w�B�1��̘7o���:�6m��;$��>nnn�۷��~���ݻ�;$!�B/�u�!^u��7������p��}��Ƒ�/~��7�ÅZHH�fv'
�^�B�jx��?==b�C��|��>CB�Ƭ��hѢ #R7y�B���B!�B�����	#44��/R�~}���Q(ԩSG��	�Fpvv&%%�#G�P�d���,��?��C��ݹx�"۶m���B!�j�L�U��������ٳ:�Z�
��M�whB�"�WLj�E�T��yB!�B��F�-�F�B!�B�iذ!
6d�������ҥK�<y2͚5���777�U���P�xm-Z���
�t�R���}�#�BIIIt�҅%Jp��A�����B�W��B�UZ�h��}�pss#00�-Z`bb…X�j�}�Æ
�s�B!�B�].\HHH���B���J��h!�B!�BQ�prr��ɉy���믿�ԩS7nm۶E�P���J�
���ƌ��ɓqww�R�J�I�Ebcc�޽;�j����bŊ�I!�л�@��4g�ʕ+DZc���)S�FFF���0{�l���[ڷo��@�B!�x)�JT*�,��"K��!N!�B!�B�

�裏

���~�bŊx{{S�J�w�NHH����w�B�6������`���E�E�l�Bǎqtt��~��B!�'.�[�I�&$$$���M���155�dɒ���{���s��A&L���0�B!�B!�B!�B!^;&&&��ݛ��p���V�^ͣG�<x0�+WF�PIff��C�V�tiY�~=�w8�-�t�R\]]8p ?���K��wHB!�+��������{̛7O�a!rؼy3FFF�C!�x�l޼Y�!!�B!�x\�|�C��;!�KԷo_}� �xM;v�ƍ�~T*U�m���0�p��M6o�Lhh(�{��lٲ����T*i׮��������}��j�*F�E\\��N�K�R���믙={6�|�
~~~�I!�x�H�!�z�e��l٢�0�B!^����M+�/Sxx8����lْ~��K�B!�B�‰������C��zPY!��W�^lݺ��xy��w1b#F��ʕ+lڴ���V�^���%���C�PТE}�*�+e��4lؐ�˗3j�(}�#�0YYY|�駄���v�Z�B�W�t�B�W���?!�B�7ѱc�X�x1�6mB�R��憍�
|�CB!�B�A��
��			�UB�"ۺu��C(��ի��W_��W_q��BCC	

e��ԪU�B�B����Nߡ
�w�����/���ߟ~��Q�bE}�$�w����Ņ#G����?ӹsg}�$�B���ÅB��Q��B�g�w����L�8WWW,--pqq��ߟ͛7cjjZ,q!�B!�B!�nu��%  ����=Jhh(�֭c���4l�www
5k��w�B荟�6l`„	�;��v�]�v��͛DEEѨQ#}�$�B��^Z��͛7�����)y_���/����H�B�W�|���(��	o�5k֐������&M�Pʚ5k9r��B!�B<��˗9t萾�B<�/"���޽{L�6���p�]����%���g�ĉ�*U
�RIhh(�ׯg���}ճ����W����ٰ
RG��?�رc9x� �����ۗ��@J�.�ɛ�����/���ܿV�X��}�?&  �M�6q��E��������O?e�С���M�ҴiSfϞMTTaaa̙3???qww�_�~T�\���]��Z�2e�7onnn6��-[�;$�KLL�k׮���s��AjԨ�B�W�K�p!#�!�(���`�J���B!^9�g�`ԝ1���{���+lllX�|9���^���{���������3t�P�������_ټy3�O����oߞ�#Gbff��w��-�,Y��AFF;v�����AݡD��ܹs9~�8&&&t��	ooo��(
�ƴ�4���h֬�*UҤW�R���0`�����!�B!��-��xͩ�B�]<x@����t�3f������޽�%J�t�R�������i׮VVV\�|��#GR�Z5V�X��=�#�:p��-��u��˗���#���{�ܹC�V�8��f���RSSs�����w�}�Y���"66���XRSS;v�3�S�%h׮�ڵc�…�ٳ���0|}}3f~�!���P�l�g�'ě�o߾,_��Q�Fq��a

��x
�۷�޽{ӰaC�l�B����B�Z(��,��T*Q�T��"�,y.B!�B�Ls��%--Mә ++///֭[���y��!7n� ((ooo?~��wٲeL�0���8�ݻGvv6��Ʉ�����j򥥥���Idd$w��%++�]�v���R�4|�p>̃�{�.?��#s���l/Lw��Mzz:NNN��qrr"==�={���v!�B!^,}_�EY
��C�Gs��!..�-Zp��1>|ȉ'hݺ5���AAA�+W�u�֑����y���
"55��k�R�|yT���{W������֭�ٳgIOO�\�駟4�9�<���:t���L����?��,u'�]�v���IZZK�.`ѢE�>fFFF|��'lذ������133cĈT�\6o�LFFF���u�d�4�3!
#,,�.]�йsg���#�-�B�Bx�3\DGG�p��]��
���B!��V�Zifuظq#'O����___j׮�5�[dd$�z� 44x2
[���100 !!��Ç��cÆ
\�v��ի3m�4lllHHH`ҤI/�M5j�   �ʕ+�z�j�������57?��P�~�\���8@�>}^J[�B!�B!�x[�����`kk�ڵk���f�ƍ:��;2f��ΝK�֭���e���t���ա�h�"�ԩ��1c�>}:�o��l߲e+V��y���mۖe˖��'�h�U�L�޽�ܹs9q��z�bĈ�1���)���������Ɲ;w��� 44�B����z�B�PЩS'�����>!^5���c��������JŊ��xM|��wL�0ooog�- IDATs�t$�B����O�˗/�9m���y�fy/MJJ
�ƍ�]�v899�x�bppp�whZ���;v,cǎ��GB!D�?ϟ�\�+���C��`�޽̘1

�U��رC�w���9r[[[v��ɂ�5k�����۷o������addD�&M���_h��Ə���&&&�������"��̙3��NO�Y��V!�B!�B!ċ���<4��@�X[[�����ƌ4hЀ��Xlmm�f�}Qu���k��P��֬��Ν���Qk��m��*+00SSS���×_~I�
�1c���ό�0ʕ+���'{����իL�6���$>���V��ȑ#����j�o�ɓ'cjj�����C��G�1z�h|||�;w.s�Ε�B!D��.��!R!��BBB4�	���Y�y����رc,^��M�6�R�pss��Ɔ>�@ߡ	!�ou��˗/УG���7��w�1c�p�ԩ\�T*���W�аaC�<�7.R��R�vm����
�´Q=2���y�|괜��	!�B!�����R����B�����ݻw��f``����9���z��Fs^#t�"���3[�la���8p???�1c^^^jGaT�R�/���/���.Jhh(˖-�z�긹��T*_�[!�S�2e��������O?�e˖�I��222���`ǎ���ѷo_}�$�B�����B�7����X�l���ח��8�����L�8WWW,--�Z�*...���������B�W�������A�� �	���3W̞=�S�NQ�zu<<<�<y���X���� ��nx�%g���H�VЛ�B!�BQ���|��gԯ_333LLL�^�:���l߾]�����/��۷111����T_�V�\I�������,��ŋ�T�\Kvv�V~___h֬'N�(����� �ԩ<�!8���X��˗/ϐ!C�������L�0������c����z���5�-!!���?ҤI�իǔ)S8{��K�C��I�PЮ];>��s��E�t��m:w�̾}�سg�t�B!��t�B�Zppp���!�����(Q"׃���f�RRRpwwפ)
RRRX�f�#B!�|���l۶-WG���8>�ɫ�A���7ݻw�*K���z��Z3l$&&��v�0m|�w�#٩��y�B!��EJII�k׮�iӆU�Vq��i222�����ի���t�֍O>����T}���
		!++���,BCC���cذaܹsG�a!^a�{�@�TOvv6��Ɍ7:v���o�1o�<Z�ńh۶-,��~��Qw��ف�0u�B�`����߿��r��a��+o�ڵ100`ٲe���ѨQ#5j�,�e���g��������������˩[�.̙3G3����E���_�b�
}�"^1.\��ɉ�W�E�6m��B��+�)))888ЩS'�^����]�v}iu>�!]}��̙"������ѣY�t)�Νә�ܹs,]��ѣG���\��&���;��c���V���ܬY3�z�g???رc�־�v����\�<]G�t�zff&S�L�u��t�ؑI�&q��M�}����Y�fT�TI�^�J#--�9��B!�ҡC���ӧO���#nݺłppp�9�}LLYYY�>}M����.]�0c��M�'N0}��bhQn�icݺu�t�R�r�i�<B!�B���?8::�s�N�V�J`` 'N� ==���LN�>�7�|���9;v�G�E�[�ڵk8p�ֺB����^�z<x��M�bdd���%������1g��ܹ��177gÆ
�n�:���4h��sWŊ�'���3[���ꫯhܸ1�/_�]�vӢE�4i�+���9r$����T*h׮]��~hٲ%,��ի�ݻ�F�1m�4jԨA���Y�|9�n��K|B���_|�'N��]����fff���`kk�B�7B�w�P��igg��noo_ܡ�ݗ_~I�������[�8p�AAA�^�Zg�U�Vā��u;v�ŋ3n�8���+-Zğ��ﰄ/����*Ub���$''���̷�~K�J��-R��f�b۶m<x���Tv�؁�����k�w�&==''�\�;99���Ξ={��0!�B<���Y�&Ǐ��Ã-Z���̆
(U�cƌ��m߾=�&M���	���N�>
���u��%99�aÆѲeK
D�z��E�i��8�تU+@�l�4�H!�B�
2����Ӯ];N�8��_~���-���S�n]���9x� �ʕ�?�`���������ѣGy��wY�t)*T ..�'N�;4!�@ٲe9x� ���ԨQ��%KR�Bz��Ell,�7�tV�r�
�-�t��Y�&�-��ի�9�P�V-J�,Ifff��(���Lj#�X�"&&&���O��Çg���4i҄R�JQ�T)������aݺuE<r/���!�:ub���$''��?R�JƎ���%ݺuc�ƍܻwOߡ
�L�&M�T�R|���E�v��E�v�hР��fvt!�B<�W�Åz�m����r�V�ʡC�x���V��Ǐ9t��+W~!���222�8q"���XZZR�jU\\\�'##C��	!���w�u5sss�L�����4i�?f���ܿ���,,,�Twtt4.$&&��� �V����ٸq�&ρ�_�~���i�<B!��_^���)S�AAA(�J,--144��‚��۳v�Z��ƍ�G}�y���Ύ�3g2l�06m����1��=����/_ccc:w�ߋk�Kj���3fffDEE�*'**�2e�йs��_!�B�\�t�aÆaee���	�����ߟ�'O��o``���iqqq��ۗ�+bllL�ڵ�����bTT;w�bŊDDDP�\�<㶷���o�`�ʕ���>}�A�Q�Z5����V��&)))�v9r��;bjjJ����ѣ�ֹ_RR^^^X[[cbbB�r�hڴ)S�Lь*���姰�OM� �B��t�Ҹ��k��>F�.]�iӦ�.]��ݻk�9y�$
��J�*allL�&Mضm��y���z�K_�|9u���Ȉ:u�h��?|�����W����1���g͚5y�U������B����3o�<.^��Ç�u�?��
4��			A�Rif+R8p *���������y��!7n�(T*�
�J�+F]�,]����<x��M�077י��ӓ�G����AFF			̜93���`bbB�^�#%%��� �I��*U��ݝ-[�h:�񪱰�`��٬^�:����f��w�N�>}ؾ};���I!�x��,�Jt�������k�-ZĢE�
���-[ABB�5Ҥ?~���4:t�@dd�#|=�Y����ͅgxr1:44�5k�hF�B��Fz~:�0�͚5C�Ţ�~JBB
���͛9N��
6��ϏQ�F��k�7Μ9@�5r��F�G!�E��Ǝ�رc�-��ܜ3f�ܦ�t�V�ti|||���yf���t���ӕ^�6�.]�R��ի�v�ժU�ڵk���>33��+�B!�x5EEEѭ[7��x���			!""����]��LSSS��u���駟���#M���5k{��!**�ҥKh����B�
Ϭk������v�}�v���5P���Y�n?��[�l�S�N:�<t��۷�<x�m۶�{�n��ۇ���&�#G���IKKӤeeeO||<k׮%66Vkг��iE=�=�k��d�ҥlܸ��3gbhh�g�������h��޽{�ٳ�Vێ;FϞ=Y�~}��TS�Ne��ɚ�s��1p�@*U�Ċ+����l;}�4���������U��
�#��V�L<<<����֭[l޼���0��郅�...(
:t����M�P�j�*F�Ell�����L�”)S���c�ԩ��W!�x	�}������<y2�:u�e˖����cǎ\�~��W���h߾=-[��[�n������;88�|�7���ĕs���KOOgѢE���GGG�w��ҥK����YW�-�ܣ�<x ��SOA���ǏY�|9...8::Ҷm[�–-[��*�qU����ӱcG���
{AcJKK#,,�f͚Q�R%Mz�*Uppp ,,L뢺�5j�(���IHH�V�Z|����U^˖-��?���^��I�}�6���i�<B!��aРAT�R���`MZpp0���xxx�12!�B!��}�6������1f������� &&��C�����R���7�u�%g��U�Vi��p�Ç�ѣGxyyq�����ؿ?���;v�Y�fi�GGG��'��
&&&�n�cccMZrr2���dddгgO���$11��={r��}���Grr��2===��㏉�����۷�ڵk���ŴiӴ�3���4>��3������"==���[[[.^�Ȕ)S^Xl9���ڵ���d�ׯ���֢Elll�q��w�η$�{�.s���Ν;(�JM�N�8Aff��݈#�٦�Z�d	k֬�Ν;���?t��
�J�B�`׮]�����˗qvv`�…Ze<���<=�{�בB���;#������ҥK�����_ѹsg�{�=F�Mll��ϋW����/毿���X�����:t(�|�
˗/�o���B!�KR,.��∋��LiX�F
���X�v-666�<���נA�ؾ};w��!;;�s��1i�$�Դ˖-c„	���q��=���INN&,,L3հ.-���<��ˋu��q��uʹ�AAAx{{���\�4k֌%Jh:X�EGGc``���Ea�)h{/^̪U��|�2>$==����M���Oa͝;���4MG���^Иv��Mzz�f������HOOgϞ=En���ԟ9?�K�r^˫�@ɒړE�߃J���G��m�45u���B!Dq255%  ���Hnܸ��7���$  �R�J�;<!�B!�sX�b)))���2w�\���)U�-[�d�ʕ�=��w�dɒ|ˉ��eҤI�7�R�ٶ|�r233qsscٲeԬY###ڴiChh(6l��t����/r�-ZĽ{��С���all���t�Ё����ŋ�ܿm۶DDDЪU+���h׮+W��u���ѣ̞=kkk���055�}������u��[N�s��^���^Woϋ��?���XXXhfC\�r%7oޤcǎDDD`kk���1�7f׮]���?�ME�x�bLٲe�T�����۷�>}:C��L�2T�^�����U��
�#�����{���_Ǚ3g���b���8::R�vm���HLL�w��-gkk���7~~~���G����ӫW/���زeK�YڅB�b���oO���[���7obkkKDD���w��i�/���p�<Ȋ+�'S�楠�UA���0<�R��ɓ���¡C��>����DFF���‚z��q��nݺ�͛7IJJ���Z��̅����Y=m�E����a�������iӦ�JjժŁ�:uj�c/hL��At]�W�==���d�Ν;���-�ϟ�u�K������s���Y���ǵ֏;��￯I{�w�{�n���i�<B!�ťiӦ�9���@5jM�4�wXB!�B��}�v��O�C��;��ݻwQ(dgg����̙3�����/�92׾�T*.\��I����L�2�h���{�0~��\�۔(Q�	&�s�N���5*W�zв��T���իеkW����r�f���*��k׮���r*��ضm���_kۀ000 22����/Ϻ۵k�+M=X݄	r��dɒ���>�EEצM�u�߮��Z�jժ�k��}=�F!ě��Ɔɓ's��i����ӧ6l�A�4hЀ3fh}�8M�4	333�wO����ر#���_�[�n�I!�x��Å����u5����ƍ���
333������㧟~��ۿ?G���֖�;w�`���&����3���_TE��wAvƌ���`hhH�Z�`ǎ:�kѢ*�J3���Q�T�h���)h{���&<<����WWW���tv)(�)�{Ac:s��d���լYS+��u��BBB��

�I�&���r��M�����e�2228�|��M�>���D���9v�3f��L_P�n]����NS�B!�(NJ��9s�0g�
���B!�B�'O�����\���\RRR�e6��/bmmMhh(���Z�Ճ�4jԨ@1YXX��/u��fvϙ��:��ֹ�J�.
�k�yu'���<<<�����ʊ!C��kV��-������P233i߾=VVVZ�jԨA�v����$,,,Ϻ�MrR��m֬��}�٦�zz���3N[ZZjm322�Y��
�#���Ҹqc���;.^����iӦ
��ͣv��8::�p�B�����x��)S�y��v�Zbbb��xI���o����y�&���@!�B�X%���988h�Ϟ=�ٳgkֿ�������lׯ_����͛73f�N�ʵM�R�_A�/���p��ez��s{^b�7oΚ5k8x� ݻw�t����na�)h{����2e
�����Ʋl�2<==Q*��*UJg=���P����۷077�U�:M�G�zJKK#  333�N�Jɒ%	@�P0y�d6mڄ��9�۷'""����3�|����,�B�
<X+���777�z�V���?HLL�5j��f��#u	!�B!�B!DQt���Z����p���ٺu�f����rt�
kkk���8}�t�����z�^�Y�lٲ:���䜽8��ܫ<x0e˖eڴi���p��֮]�ڵk�]�6{���5�BQc˩��o�ڵ����uY�v-#F�йM=���zԝf�V�\���[$yu�ru������B��C�%hӦ
mڴa�����/�������رc�С
�����)@߾}Y�r%#G�$..��ߙ���ȑ#t����w�q5g��_�J��0bЈ3FED�!BHi�(��Ɍmd����Ӑ�"dkc,!L��oc'c�Qiq��;ݺ�-���������|>��n�{�yS�re~��>��#]�$�B�7
4Å���	��̙3�t��+W��ۛ	&�o�+��T�qŚ��+c_�d�!�^�zs��1RRR8~�8������m��m۶�ڵ����S�^=���X�x1NNNlڴ)��;��[�6vmcR>'2�BN_���"EGG��g̘��G�1b+V�bŊ�1���XU��C����Jɒ%122��ޞq��e��9shڴ)E��|����ٓ�K���w9::bjjJddd��###)V�mڴ��	!�B!�B!��r����8
E�?iii���t��FOO��k�bee�m9evWR.8�g���_�z��e����*SNZx���}����b{]]�v��ɓܾ}��� z��%�jU�!C�����r�.^����9;'N�и�ZV�Ǧ<���:��4}�����u��u^B!DnҾ}{V�^ͣG�

�x���Q�B�v����ILL�u���`�.]���ŋu��G�v�U�Vԯ_�����d!���Ȅ���h�[�.���,\�kkk� Z�@Z�����;v��� �B�N�Զ���j�O���ӯ6�M�߼����ݾ}��yQ��8qB�~FFFX[[Oxx8���|��gY����~rs<%J���ٙ�˗�z�j|||x��s��Q���y��9�&&eJbM7��e�!
M2җM�:���h:t�V�C�DGG3u�TLLL9r$�����ѣ,X��r��e9�dɒ̛7�cǎ�s�N
�i�>�///Μ9���U����̙3x{{k\9L!�B!�B!r�z���l��JJJ��Ã��&M��e�q��9���enY� IDAT`ɒ%�l�ټy3Ϟ=S[K�gVߕ?~\�^~�R�
�z�b���\�r��۷p�7[^�ߪU����/��T��������u�p��I�۳[(I��YBBB�m����1�����B��ebb������<z�%K����@�=(_�<_~�%;v� %%Eס�wL�Z�:t(�Ǐ��Ç�G�+V��쌫�+۶m�:ӠB!�O�����
W�M����kҤ	�֭c���L�6�R�J�`���¨\�2�7oV��_|��7�<y���ٳg�)S&��.]�'O��e��u�FLL�jtm����
��;w�P�JZ�l�ʕ+3f#F��F���űv�Z֬Y���-K�.��_Æ
���bŊ٦d�K?9O�Ν��>#G���ɉ5jp��]@=�����ĮmL5k���Çܾ};�Ċ۷o��!D^����c����1b���������&�B��BBB��%!D�mذ///]�!�BQh�k׎S�N1u�TڴiC�"�_������N���ٹs��|���={Ǝ�m-[��̙3,_��&M��m;�<�~�)U�V�֭[���ڴiCDD���lܸ1�Eh�ݻ��ٳ���g���rGGGN�<�̙3i۶�Z��/_2{�lZ�n��Iʁ��9�o���ԩSGm���}���[n�_ZZk׮�믿ζm???�iS�N�� �x�v���Ç	�M�6j�`
���4)]�4��7'N��e˖jۂ��r�;?��W��_�|��<B�~+Y�$�z��W�^<z􈰰0֭[G�N�(S�nnnxxx��� ?D�7n!!!�1�իW�:�&O��ĉ3f�'OV�<.�B��S`��s3�W�^�-[��g�ұcG�6mJXX}��U�kѢ�Ǐ���ooo�^���~��e���y�����@���)U�T�Ǫm\�K����E�5���sssΞ=���7vvv8::�f��-�СC��W9�����j�5�M?����3f̠Y�f4nܘ1c��2�dl/��5/�k���M+1)˔鮅"/LLL�8q"۶m#&&����m��ĉ��F$�B�O���pss�uB�����[��@�B!�7~~~�,Y�#G�Ю];N�8ARR�����|��)R�iӦ��ٶm?��#�}��W��q�W_}���1+V�`���<z􈄄~��7U6___�}���ٵku�����ƍ���������5k���<~���c�R�^=�>�/���qqq��ŋ$''s��E\\\8p����9N:І��'��fDDϟ?'55���ϫ&��k��Ė��w�^<x���-
6̶�ƍS�~}<x@DD�V�o߾T�T��{����ƥK�HII��ŋt�֍���,�mڴ)�������$%%��2l�0/^�U��+/��ס\m8<<���T����]!�>��o���#G�p��
���[�=J�-�Z�*Ç�2���255e޼y�]����H]�#� --�~��1y�d/^��/�-�B�Y��.�=N�lٲ�X��E�ERRիW���Wm�RSS���$--�5j����͛7	d���W�Ѷ��C����ODD������2n�8ڷo��j������y���f[�b�

bٲe�߿���X>�����0`�*�&5jԠL�2<y��ŋS�v�,��m���Ņ"E�ƍ7�\�2���s^���19::2o�<"##�ٳ�Z���+V�6m�h�Bd���???Պ_T��%�B��
ĠA�t�B!�B��*U�DHH����۷O���ŋ�矫+3��={V5`\�B��Nj�����Ӈ�ӧ3}�t�z�7f�ȑje���		׮]�r򁁁�ǏgҤIj��1�������u�V�nݪ���ؘ��`�V��e��5j[�n�ҥK�m�6�J�*1k֬7[n��ʕ+�W������G߾}Y�r�ڤ��/^�������ȦM�شi���� z��1[�رcٳgׯ_ϴ�Y`` ����*�ב���백��j�J(_7B!DF���5�Q�Fq��BCC	

%  KKK<==���f͚�U���v�J�v�������ә2}��+!!���Gxx8��κI!�x��)^�OHH=z�P�(�X���ҥKY�|9[�l�R�Jܿ�.]�п�����~�~!�U:���`�*`!��?���=z��H��yB!Ļ(/�^�z�~����>|���)
6���?�"S�K�&...�82����Ӊ��"!!�jժѣG���166��Ƌ/X�z5�����<~��T�B˖-8p �~�i�1\�x��ӧ�o�>���/ʕ+G�6m9r���Ȕ��fu�����S~���n��͛7III��ܜΝ;��w�Q�\�7�6�/..333>���ݻ�U6億*U�DRR111�*U*�sp��u���{"""�믿�Y�&�&M���	SSS�/γg�2�w��)&M�Ddd$ϟ?�~���7�:d�ov��u[n^9���[�n��W_ɋ/�P�w��U��.��B�?�?Nhh(aaa���P�~}���pww�r�ʺO�E�]�Ƨ�~����:t���Zx��1;v����/4j�H�!	!���p!Da���Î;fĈ���fffx{{�8:!�B!�=!!!����:!�;fÆ
2�[!����d���Z���ԇ��C��9166�o߾���7O}ZYY�f����4�=��%K�dڴiL�6M'�is�J�*Ebb�����f����^�:�V��T��`ff�q?kk�L?r�7�x�-7�����n���9�v�Һ!�B;;;��������0m�4���;�4i���'nnn|�ᇺUr5j�`ĈL�8www*V���D6nܸA���III��ѣXZZ�:$!�B�?}] Daabb�ĉٶm111��İm�6&N��Պ@B!�B��������0�� 777���t�B!��SSS���v���˖-��Ʀ �B!��jՊe˖��͛�T�Ç�bŊ899�f����u�(�F�Eٲe��u("'O��I�&+VL&[!���d�"����={6���Z�Q	!�B��4h�
�uB!�B!�Ȇ����ݝٳgcgg���17o�dٲe̚5�~���8R!���fll���3�����l۶�u��ѧO���^^^899ɢ�B���	�����ٙ>}�вeK]�$2سg�����۳q�F�/�됄B��L�"///���t��=zУG]�!�B!�B!�B�thݺ5�O��u�֙����1c�Z�hQ�	!��bŊ�ƶ<y���pBBB�޽;|�]�t��ӓ/���"Edh��N�:ѱcG�������C�oժU���OOO�-[&�F!�(��S�B�
�uB!�B!�B!���ښs����={�u�)))T�P��M�2x�`5j��0�B��V�2e�ӧ}��!&&���0BCCqrr�lٲ������I�&M����u�B�,X���������_��`ڴi�;��#G2u�T���t�B!� .�B!�B!�B!�Bh���3w�\]�!�B����1x�`�͛7	

%44�%K�P�re�w�'666�U�'�|¨Q��<y2^^^T�TI�!������od�…8P�!	!�"2�B!�Nu��]�!!���B��uB!�B!�B!�xK|��'�=�ѣGs���䋀�,--����Ãڵk�:TQ�F���5k:t(aaa�罔�����{��aÆ
t��U�!	!�Bol…��B����`���t�BQ脄�УG]�!�B!�B!�;E�3!
///����H�u��aʔ)L�2�'Nʲe˘<y2���j�EժU�H���(Z�(��ϧC�DDDЦM]��^����ԩW�\!""�&M��:$!�Bh)�'\4m�Tf�
!�B!�B!�B!����ҥ�,&�(
r᥆
ҰaC8t����̜9�Q�Faoo���nnn|��G�(XNNNt�ڕ�r��9���u�{�֭[�k׎/^p��a�.#�B�e�X�!�B!�B!�B!ě�a�]� ��%y�nnn����:!�`˖-ާ��>-Z��E�,Z��={��~�zF�Ő!Chݺ5���P�T��O�Y��ͣN�:����?^���N�>���*T`�������:$!�B�R�O�8|�p�μB�}
��CBkW�\�f͚je����S�jUz��A�
"<�(㍎�V�i:.��v�Z�;�Ç144��?�y��xxxP�D	��Y��MoRXXǎ�Q�Ft�޽@�B!�B!�� �}/!�B�

�ر#;v$11��۷�n�:������}�������쌩������J�*�7�	&УG,,,t�;+""�nݺaggGxx8ŋ�uHB!�ȃ7��BT!2
		�	Y����r��A�'	�x�W�2a��+F����p�y��q]�z��}��sUYrr2W�\�ʕ+l߾��˗S�|�l�ѵӧO�h�"֯_�B����KKK>��s]�&�B!�B!D�������K�a!�;COOO�!!�3^^^�:�LLLL�޽;ݻw��ӧl޼�u����퍉�	���xzzҶm[���t�x
C�e͚5|��7�ܹS�ἓ֬YC�>}�޽;˗/�׌B�{c.�B�����ݞq���'O�7o;w�d͚5�v�EV����ϱ��c��T�V���T.]�D@@�/_fѢEL�<9�v4)�I����7WWWUNƎˆ
011)�8�B!�B!�x�>̂t��5����:�A�.]d2��@�-U�,Y___|}}���eÆ
�[�gggJ�.���^^^4k�]�+r��АŋӼys6m�D�n�t�;eƌ�=f̘!�;�B���L�B�V���
n�~^�)S��Ç�s�N.]���pr��ٳL�:�R�JP�H�ׯϴi�pqq���ú1G+V� 66U���'����X�???F'�B!�B!D��s�6l���Mס!riÆ
�Ad���M�W�b˖-�!�ʗ/��8p w��a�������l�2����޽;�������:T����0d�)V���Cz륥�1d��,Y����ot�B!�A�O������ɉR�J�믿r��=�t�B������dW�\�f͚����ŋ��ٓr�ʱc������K:w�LLL���X[[��~a�Ʊc�hԨݻw�qDB������,X��Ç������={�d��р��YBB˗/'""�����?�����ӧOU
G�`�ߵyOLMM4��֦_x���޽{������:w�L�.]r�+�x�;�2e����#?~��p�T�J���jG�{`` Ç��Ғ�K�f�K�xݺu̙3��g�bll�_|��!C�2Qh{m���Y�n
4�|��+T����-�֭��/��x��΋B!�B!�o#Y!_��OHH�[���B�I�*U���ߟ+W�ʺu�?>�|�	���xzzR�n]]�*�0s�LjժŤI��5k���y�%%%ѣGv�����%k�B��z��r��y�ԩ���}������醚���k�毿��q���ǏC�jմ�lQX�>}�E��������Y�p!gΜ�uXB�B�����Ӈ�;w���3RRR�|��j@~z���0�U�V��RRR���!((�!C�����<ŠP(��￙={6��߹��h�"�-[Ɲ;wHII!!!�s��1e������6���@�~�X�p!�O�&%%%Om͙3���x�����ߟ'N����ӧOٴis��Qm�͵ݳg			���g�fooOBB{�����!�B!�B!�B!t��Ç�AhP�fM&N���˗9u�ݺuc͚5|��ԭ[��S�r��
]�)�Q�\9�M�Ƽy�8w�yk=y�6mڰ�~���+�-�B�wL��p�q`���y�W��,�T��7o���%�}�Zbb"�ƍ���333*V����cǎ%11Q��	!t,88�{��Q�bE������"00P�`��k�r��E�֭KHHǏ',,��?��'N�m�6@=;Dttt��"�?
4��ё�{�b``@߾}��/@xx8.$**�C�1r�H֯_�Z�*���ڵ+ӦM�D��Z���}�Ҽys���+���HNN֪�jժq��&O��m<U�V%<<�#G�лwo��߯ڞ�k{��j׮�i��LYG!�B!�B!��]p��a���K�ڵ155��ؘʕ+���ʎ;t^����Ә��u��S�HJ�.M���>|87o�|����q�K�.1|�plll(Y������1v�Xnݺ�F����5~�����ׯϬY��}�6���4oޜ���caa��������Shзo_lll���C�P�:����۷qpp�Ν;>|]�$�B�|V .�H]�z5�����ڲn�:�ՠR[[ۂ�����|��#Gx����:O�<�СC-Z�:p��gŊ������*���$66�+V�02!ě��oG���ʕ�nj�g�}���!��֌;6S�L�6
KKK�V�'N`�Νy���������?f����~MMM�W�
����puu%::Zmbƛжm[�l�š5k��믱����̜9///���/������(�z#F��J�*�2>={�L�=7�ʕ+��I�����B!�B!��]���-_|�������'''GVx��^av}���1l�0�
FXXXF%�x������䄃�˖-����$&&���̽{�شi;v�C�j߽��KKK#..�3g����k׮�uX"))��R�n]8u�Ϟ=S��'N0u�TjԨ���?)))���~������6ś���GӦM������a���Ԯ]��'R�reZ�jE`` O�<�u�����d����X�r���y�������S�H�=�����CB!�P�.����cƏO�V�hܸ1����ݻ7�[���.\���3�7�S�N,^�Xm%n�o�������iӦ�nݚ�ӧgʒ��6O�:E�V�0`�j۾}�0`-Z��Q�Ft�ؑٳg�����7c;����Ą:������5��_~����TڶmK��ŵ�KM�=�rm��˗/Y�t)...4nܘf͚ѫW�L;���Y�n
4P[ѼB�
�I;���Y�.�x�ݾ}x�bFz��֙�޹sggg��]�t��Z������o�Q�fM

i߾�����;d����9v�s����ݝ�� ������uծ]___,X��}��ׯ�n�b֬YZ����%J�^�}P�͵UސS��KOY&7�B!�B!� ���u���YL�ɷ�~�Z�0�}��i-Z���?Çg�…�9s��#B�
=zD�ƍٵk+Vd���\�p���^�x��˗����)^�8;w���ٙ��T]���Q(j?���<z�_��N�:���DϞ=5fQ��.HJJ�]�v,^�z����ݻ���%%%�������|}}Q(̞=�:����K�]d``���#+W���Çlܸ�?��!C�P�B:u��ڵk���u�{�~�����1b����o]��Vطo͚5�f͚:t�J�*�:$!�B�!2�B9 5$$x��ttt�jF����������ӧ;w��ٳg���p��eF������d��U�x��)))���Đ!C�m*��ߟ'N����ӧOٴis��y�6�̙C||�jB��%K������%55���n�:f̘���M�ݺu`۶m��TN^puu}����-ZIJe˸s�)))$$$p��9�L�Bpp��ޞ={HHH���>S���$$$�w��׎]Q�(�.����]9��}PS�؜n���FN�%7n)))L�>]��!���mۖ]�v1~�x�իGRR�/��ɉM�6e�v��m�rpp��֖���Lی������رcZ��MvCCC��٥����*��3�Q�I:a!�B!�B�>�j…��O� IDAT�������Dƍ���+fffT�XƎ�i�8!��ի7nܠy��\�p�o��+++LLL022�f͚�;��G�R�T)<�ҥKu�[��А���Ӻuk�m�ƈ#P(��ߟ/^�:�7f�С<x�?ΪU�ptt�\�r)R�2e���_�b�
�?NŊ������u袐)Z�(]�v%,,�G��B��w�ޔ/_www6o�N��
�)S�`hhȨQ�tJ����:t`��ݔ,YR�!	!��
*�W��j5���`�ݻGŊ	

"**���@��Jk׮��ŋԭ[����?NXX��9'N�`۶m���Z�*���9r�޽{�
��K�ժU�ȑ#L�<���PF�ɑ#G8z�(?�������ի�ݻw9y�ZL�N��Ν;Ԯ][��L��^Gnb`�…DEEq��!F�	����U��9�Zm=#e����T�re�U���2>033`���&oDGGs�ĉ<�P�V-���K
ӦM˔�9���(Qggg�/_��ի����ٳgj���?�*�M���栗&t��&4Mfx�rsm˖-�ӧO3mS�)�!�B!�B�I�Yw������ë�d4e���b�
bcc���P�yzzˊ+t�^}Oү_?�T����1fff��у�/j������OF��Ѹ��Q�\9������`�ȑ����d׮]�+W���pJ�*�e�u��U-����?g�~��e|||�T�FFFT�T	___�]���q����j�
J�.���s�߳]�v�P�zu���)U�666L�4���8���6���ik���X[[s��}6nܨ�M�uNJJb�ܹ4k֌�e�R�H>��C:t�r�^��ŋ���|��amm��۳��ҥKR�X1"""2e����Ɔ;v`hhȂ�q���}�X�+++

)W����qD�����u�OA>�/^ooo~��bbb�7o��������Gѻwo���CZZ��C}��(Q����-[FTT���)�f͚ŗ_~ɠA��zAJ!�B��t2�"��t��ƌ�g�}���!��֌;6S�L�6
KKK�V�'N`�Ν��1b��ie���c�Ҧ���ڇ�C���ceeŮ]��?>?�������_��B��Bi����-^7.m�&vSSS�����0���\]]���V��q����D�������!�Omڴ^��<�<����;w��ӧg�۲eK��ߘ˗/��������󱵵e�����jw���*����T�T�������<�۹sglmmٸq#			ԨQKKK@=#D�ҥ�W���ܸqC�lE�������� f͚���INN����СC����G^�O^���֬Y�orHz�2e!�B!�B!ě���#&L��_|A�F������Z||<t�ЁF�ѱcG�̙��;+�D��ׯ���GӦMiݺ5ӧOW����K�.]����7�Y�f���K�;��N���ԩS�j�Ju�6}M1�渳�;>>�u��ѠA��*T���0��B�I���|��g����ܽ{���d>|HHH666��rbbb��xժU4jԈ�7��cRRR�q�?��͚5S[|k�ڵ0�2e��ؗ��/�������j�;v��ښիW��RRRx���V��~�����Y�y��q�5k���IJJ"..��۷���i������
?����'���<}��S�N1q�D�ׯϣG��-����S������@�����ӤI�
Fdd$O�<Q}_�s�NZ�j�/���u�y9G��+��)))�>}�Ν;��W�X���/_2`�>���b�����ݻ7iii,_�\c�Y�fѻwo.]�Djj*�?&,,[[�\�����Ȭlٲ��׏���s��&L���h׮+V�믿����(
]��^���u���������p
��/_2x�`F��ܹs�5k��	_B!�x�Ȅ�
C�?�3g���֖ݻw�߫�TT��83���:S��A����j+�t��мҷ����%J�>�N�ʁ�J�?�gϞ��ٓ)S��~�z�����m�_|�%K���~SMy�����X�b8::�K\��M�C���ؘcǎ1w�\���	

"))I��'O��f�g�,S�B��z�聹�9w����חF�ѫW/�޽�����/���={ooo���pttd͚5-Z��C���*'4���ЩS��011a„	���a�n޼��~}||�1c͚5�q�ƌ3P�[آE�͛���ݻw�v�쎫e˖��ׯ���{{{Z�h��aø�>U�VeРAy>?y��kۤI�L+ߤ/sppx#q
!�B!�B�k�l�!!!�������Y�r%���j�ߔ'O����Î;���#55��ׯ3~�x�
��j!����������#RSSU`���CBBB�����ω'HJJ��ӧlڴI-+�E�X�lw��!%%���Ν;ǔ)S�*�9s��6�!?�[�={�������}�m���$$$�w��\�#��O�<��Օ��x�ʵk�HLL$**�>}�������111j�)�L?ӦMSm_�l��7oҿ���0`7o�$99�C�Q�zuN�>�ZD����t��A�c066�iӦjH>|��ܹ3�ϟ�ŋ�?�Ν;�s�w��Ç5�ٻwoڷo��Çy��9��‚��d�L��Vw�С���ӷo_�]�Frr2			�߿+++nݺŤI��-���z�r�iӦ�:u*�z3f��ԩSԩS�Ç���@RRǎ�q��(
�N��U�y9Gqqqxyy���p�/^�PM4�ꫯ4��̼��-www�,'6�=�F�q��1����p���μx�ooo���/�גR��T~������[�R�J:��Ǐs��5
āppp��ܜ#Fp��]������t��-�u(�FRR�����O�[�����:$!�B��p�[�A�4#4�I��6�_<��̘l�̙\�t�ʕ+���̈́	˶ݼ�oddD�N�HNNf׮]�ڵ���d:t�@ѢE�%���%''�V�m۶e׮]�?�z�ꑔ���ŋqrrbӦM�z�k�����,���B����"��Ą��@���)U�E���Ғɓ'���Ŋ#((///���000�D��hт�+W�e@>|8�*U��@�{�&���t�ޝ��4�ԯ���Ǐ�V�Z��F����ݐ:t(����,Y###���7n\�1fu\�fѢE�hтr�ʡ��������|��W�Y�F5�"��'�rsm155%222S;���+VL�1C!�B!�B�w�r�u�j|���Z��ǏceeExx8��k׮���J�W��ƍT�T��� ���X�|9+V�몉"�U�Z���p�9B�޽ؿ�j{xx8.$**�C�1r�H֯_�v�Y�}�jժq���=�<�>r��k��Ԯ�LYGQ�~��'bcc=z4s�̡z��-Z�F����?3x�`�>}ʏ?��m;ǎc���������ڶt�R^�x���;K�,���CCC

`͚5���,5�ghk�…��￴lْ��p�ԩ���u��!<<��-[��?�d9жY�f���ӤILMMi޼9?��3G�U�{��I��X��իchh���	-Z�P�Uغuk�Ŗ^~]��T�\�d[O9�o���4i�������c����={V�>�r�~��g?~L�V����
###�ׯ��ݻ���p��5�����M�^�z\�zU�Z�j��o�agg���1VVVl޼��-[���S�.]����+��o�;իWg̘1�?�?��ooo6n�H����U��&M��9&^���%���L�0����mKLLTM�~_���?8::�o�>��ك����CB!DAS����`E�f2>V:y����F���P(��G�*lll}���T�{��
�����ʏ?����Q��ب�\\\666��k�}�*Ϗ6666�'O�����OU����,��M�J�o�V���*<==
�B��驰��Q����������F�*�p��k���.\��X�`����Faoo�*�С����F���L�<~�Xacc��رc��O��n���Y>�O<P���(:u��F���յ]�d����Vq��=Uٽ{����������B��&���B!�B(���pҤI
���
�B1f�����b˖-�򻢳g�f[���U�QQQ
E�n�Te��.]��*���S���(4h�*k߾����F1p�@�ڵk�����9eٕ+Wr���\���Ԟ2��srrʶ]�=����W5i�D(bbb4�s����^�Q\\����\(���jۭ�����ZŮ���iiiZ�פA�
@�k�.��w�ޭ���j�P�;w.�>����P��뫕רQC(7n�X�v��Ν;o4���z�4�����4�000�s���
@����i��v�r��bϞ=�ٶm�ƾ�|KII��(?�d�����4ɸ�0?�����^^^Y>Y{��"**J1h� ����Pԯ__1k�,�Ͽ�Nbb��Z�j
www�B��n�ʕ����*l�;�;w�(�ԩ��\���!�B�
,�EnV�Q�>=}�tΟ?Ojj*�Νc����l��1c�p��e����￙?>���0 ױ�g�QQQ$''s��eƎ�*���_f�;w�V�U�T�A�\�z��{�r��U����V�Z���H����-[HLL�ƍ̘1#S���޹sglmmٸq#			ԨQKKK@=�r�w�J�)�ү/�x�4k�L�~���3^�|�͛7U� �ׯ��E^����P�B�*A�j� 333���4v!�B!�B!
���-���l۶
x�Ҳ��-�w���W�y��+|��ݍr�\�
�J�{~�V
���P�^�D	^�|�*2d���;v��s����NPPIIIZ�onn�u��=nM�<y@���3mS�)�!
�ŋ033COO/�O�:u���hү_?nݺE���	

��@m���ׁ��YQ������x���6l�P�ve�2���W����>�ߗF�
�����M�*U�R�
�z�"<<<S�׍-���~9y��9��u�ƍ7ؾ};�ƍ�m۶����P(��?/�H9F�A��iܸ��rSSS �Ϸ��8�+�q{���5�+�|�r��K�0?�����ӣQ�F̟?��w�o�>����>}:U�V���ŋ��_�:Է^ѢEY�p!�ׯg������ҧO>��3@�8�����quu%---Ӷs��Ѹqc���8z�h�e
B!D�S('\���sss�޽���/�5�W�^ܽ{7S]___���9{�,���������Ț5k(Z�(C��u���f�-?~<���x{{���S�s������B�N�^��nݺ�n�����9����7ot�ޝR�Je����}||�1c͚5�q�ƌ3kkkU�&M��=g�S�988h�[�~prr^���jՊ�
���Ftt4�K��_�~:�P�Un����	'Nd۶m���ömۘ8q"E���!!�B!�B�^Q.6�W2��~�.M��mۖ]�v1~�x�իGRR�/��ɉM�6iտ������`5
�|��V���[e��W!D�d�`����-[FXXŋg�֭����@��3R�̀���T����%K��X_9�K9� ��|����Kxx����w�r�J�u놕�7n�ȷ��{�맍�7oP�R��_�,,,pvvfʔ)DDD�z`x^Α����i��Z4S9yE[gϞ�F����˕�)_yQ���"ЪU+�-[FLL[�n�r�ʌ1��+Ү];V�Z�ӧOu�[��ܜ:u�����G}����Ç����ܹs�/_0�͛7��7ߨ��߿�f͚Q�F
"##���u�B!
�M��p����LLL��ٙR�JQ�H,--�<y2�~��X�b��兙��(Q�-Z�r��<�"�m���Ӷm[LLL022�N�:L�>]50t���>�J�*a``��9��[�hAٲe����L�2�ly�+��C����Jɒ%122��ޞq�ƽֹsqqa���ԪU###���������W�r9���#���DFFf�/22�bŊ���!�O#F�`ذaԮ]��E�������...ku�SNy��666���1{�lfϞ���nr
!�B!�B�.���&00x��[tt4.^-t��y�>��# ��+V���3g�ʕ���}�V�%pvvf���^��={Ɯ9s�Ԟr�C�A���M��֤lٲ*˔u�K��}\\
�"�M�b_�t�������ڵk���ʶm�+#ܳg�V��^�Jٲe�2�+�g5Y��@���ڵ+'O����ѻwo�@�?���!C����^�i�@���BBB����ƍԪU�q�Ʊ|�r�nݪ�H�6�r���(�e�U[ʱaaa��qÆ
�n�Z����������o����:u"$$���X֬Y���1����B�
����a�u�[����8�z��add�޽{ٵkVVV/^sss��m~���=���?���̘1x5~�}���mۖݻw��{�B!�
E
���;w�=���_��_�LƏ�Vd��^�D	�
ưaòm3�Ț�_���ŋ3m�4��ү�ݶm[ڶm���300�񦊶qe<.F��ȑ#��_��8;;���m�>�///�/_���U�k�߿ϙ3g�߿�*��������^^^�E䳼^[y>!�B!�B��Qn2ο)M�4aݺu̞=�iӦQ�T),X@XX�+Wf����ź�M������/^d���@޲�w�ܙ���3r�H����Q�w��2g�P(ܹs�*U�d�f�ҥy��	[�l�[�n��Ĩb��5�]�fM>|��۷3M��}������U�^�S�Nq��Qڷo��~IIIxxx�����ɓ��N��‚3g�p��y�4i�c�̝;�%K�0t�P���l޼�gϞ�eʱ����ɓ�8q�v��e����z��J�*��Ջ^�z��v��I5i!�c���VZZ�j�c�N���;u�T�.]J���ն)���LO�2���sT�n]>�ɓ'5�Q�j�K�>}�={6K�.����V�)Μ9CPP������[c��'OҪU�L�ǎ�^�z9��������<<<���#<<���P<==155�s��xxxжm[�ψ��P(��d3f�`ԨQ�/_��~�	__�L�KVVV�Ŗ�V)))�������̙3�R�
�
"99��'2x�`r|OB!��P~"h֬���lܸ�gϞ���Kn޼��zP�~}G(
���*T 88XU�����JB!�B!�B!���0�W�^�-[��g�ұcG�6m�Z�o߾�z>>>T�R����ӻwo5jD�޽y��U�T�r�fv|||�W�Ě5kF�ƍ3f�Z�ҥK����4@�E�̛7�w�q�[m�[S��֚V	V��e��)kO�:����L����������I�|���={Ǝ�m-[�`��噶�?===���Ue
6�M�6<|�www�l�޽{̞=}}}��*wtt`�̙�|�Rm��/_2{�l ���ann����Ɓ�������3��^?m�;�.P�zu:v�m]e�/��2Ӷ�Y��Y}?/�k׮�P(�Q(�}2�^�:_�5III�k�.�LY'N���ɉ��d���+U���2������?Э[7�mʁ��W����T�R��ݛ���߿�ԩS�q��:u��̌p���[J)))�hт˗/���uG���nݺ���k�p�駟r�ܹ�-_-Y��[�n��w���k�?��ҥK�;w�L���ޝ�՘��%J���h�e��3c�V���HS�$#���mo܊o�nbflCTY�Z�ْH�eH�KFw�U)��9w�9�H���x�x�>��>��:��t��y!�*%�]�����өS'Z�l���qqq����Ub�###|||

%99���dBCC���|��O!�B!�B!�B�^N�PN�+΄�*U�H�n�05�s!� IDAT5�\�r4lؐ�Mh555%00�~��aaa���>8��k�bffV豝���1c
4������pwwW-�/&BרQ}}}����=�	�۷/+V��;;;�O���׭m��ݻcllLTT��y���011�k׮��B�77z�h*V�Htt4��9���<y�C�1b�Lٲe�;w����P�/_��̯�����G����!���L�6�[�n������0`���j���Q�jU���C�&MX�|9W�^%;;���L���������ݻx{{�U5j���:t'''���"!!'''>���1cǎ}�{8p�@\\\�������dgg��V��
AQ�:�_~���INN&,,��ݻ3�|ʕ+���?e˖�XeU�ɓ's��-rrr8�<_}��Z�ý{�^��ܣaÆQ�F
��ۇ��.\�ٳg$$$��������o�…t�҅��$���:t(����޽{dggs��]��ۇ��;���$''ӡC�IJ�����ߟ�/����JX<z�(~��F⥉�	۷o';;;���%��-t����o�%::��W�2e�bbb�ر#�j�b�ĉ��ƾ�<G��ȑ#4l�Pk�\i������9{�,�;w�Ν;}>��#.^��5��4x����=�ƍ��?T�/]��.]����J�B!�@񆂂��O������Q)�������-Z(���Ŝ9s�n�zӐE)��8q�b�ĉ��7�:QHo�B�>�"(((�m!�B���B!�B�P�߇�_~�Eakk��y���͛
[[[��իu�(j�d(�U�w�V)�?+V�P�߼y�<������_�����_�6m���q�;wNamm������3fh����P������

;v��z��{�j۟���hذa�1֨QCq����[a���zՏ����X������y�O��z,�n�Z��z�{t��QE�
��z�h���S�������|΍7N��ɓ|�Kpp����\��ի+Ξ=�q\��?�����B�P���*\]]�����3f��֫WO��奈����_����A���S�*ʔ)��ׯ�����w��%Eݺu��֊+W���;}��P�?^Gѽ����+�{�=Ejj�ƾǏ+Z�j��W�����:�N!�%Q�)�:R�L\]]U��B(��B��A��s�N]�!�B�8!!!�A!�B!��`Ȑ!�޽��� <==

���777G'Ļ�gϞ�9s�AJJ
��ƴlْ)S�hT��r�J������ښy��q��q222�[�.�
bʔ)jӤIΝ;ǯ������?�{�.���ԪU��;2f�>��#�c��ݛS�N1o�<8��;w�V�]�ve�ԩ4lذ�ס���Ǐg���ڵ�k׮���3�ԩC�>}���V��[����_~ʖ-K�J�����[�n�9���{�@�6CCC~��G.\����!-[�d������kkk���+V�\����+�:���ޞ3g�0k�,"""�s����g�̙��������g``��?�Ș1c�g���\�|�ǏcjjJ����ڵ+j�����Ņ�����_s��jժ���3���T�ZU�`` �F�"**��O�R�z�"�?��u�ߢ�iԨ3g�d�̙��űy�f֭[ǜ9s���0`P=�w�ލ����ͣK�.<��M��q�F���t|5E��Ɔ��h�����������-
6�lٲ�;w�F��8�¹|�2˗/gٲeZ���k�.�W�N�z�HNN��Q!��=�B�x�lܸ�A��<���B�$�@OO��� U�T�~�t�BQ��I!�B!�UE���r�TQ���{+�}W�<y�q�Ʃ`pqqaɒ%4k�LǑ��$ߗ�/_���+W�P�^=lll�t��[GOO��4h�"�R۶н�ϟŖ-[		�޽{�jՊ^�z1}�tbbbhժw���Ã�~�
�N���������<z�}�Mpp0=z�^$���ۗ�^�N�>}�v��O��x�nݺE`` k֬�ʕ+ԩS��[�ҼysE+�B���DV�B��PN B!�B!�B!�e͛7g�����0f�I�BQ$����������X[[k�_�f
�L*�+S��۷�}�������߿�͛7�w�^,,,hѢ��o�j�

eɒ%|��w�߿�
6P�F
^A�111!,,�a����C��q������:�B9p����DDD��-
dժU�ܹSSS̈#���B!J?I�B�S�UL�B��w}�/!�B!�EK*Q�\����¾B�"תU+>L����U�Vr��5֬Y�?�����u�%O�r��ѣ=z�]�v��у2eʨ����cܸq�oߞ���'����O�>}tu�*W����ԬY������7o��G�~�z]�V`999L�8�޽{ӥKn߾�ڵkY�z5������Y����t�B!J���pѯ_��uj!D)�,�-���$!�B��7�s�N]�!�B!�B!��[�h�;w����t��Yc�����ϧC�������9~�8&LȳOӦM���cܸq|�嗪�e�˗/�H�===f͚E�5;v,�+W�Ν;dff�����@5j`�Ν��Y4n�X�!
!��+�Z�j���RԧB��k�ȋ���<?�B-�={&	B!�B!�B!�H�f�8w��-b�޽\�~�gϞQ�zuڶm˸q�hݺ����D�lٲt��M��233IMMeܸqT�X�ŋ�|�rΟ?O�F��9�c�ȑXZZ����ٳgiժ����_ZZÆ
`ԨQ�iӆ�+Wҿ�R�,"�B�+򄋶m�Ҷmۢ>�B!�B!�B!�B!��5|����:�A�P�t|!�ĺu�x��)=z� 33����Iff&>�X;;;����ׯ_1E�v��Ӈ�G�Ҷm[.\�P�.�ϟ���������㈄BQ�y��ƍ4hPQ�V�"���������8�ۅ9�0.]�D���}�˂������u���l�B!�B!�����t�B!��+++,--�V�FFFT�T	ccc����X�"*T���333LLL022���SSSʖ-�)z:gooϥK�8p�C�WVVM�4�ѣGT�PA��!���zk�悃��֩���ƍٹs����ę4i���������ӧY�l[�lA�PпlllhڴiE*�B!�B!�(	ڶm+��	!�BQ�V�^��J���uF�puu�uB!�(��Z…����:���z��$\�R�M� 
"22�ϑ�������۷/���899���MHHFFFo<�B!�B!�B!�B!��T�B!Ļ�W�L!�?���-P<	�Q`` �o�f������i�&=z��B!�B!�B��G�2h� ]�!�x
�B�!!�B!�B�(���۷oӳgO*U�����y�&���XXX��I��.]�~��$$$��W_Q�Z5v��M�2e�<�����Ӈ��d���h֬�+�)��#88���Z�nM�~�t��]s��
����Y�&۷o��ߧO����}�vj֬Ɂ		��ŋ<y�U�ҡCF������1��߻w��˗Iff&�:ubڴiZ�՘��k+##"""�s�U�V�G�|��7��KOOg��ʹh�U{��ձ��e���<SSӂ�Z!�B!�B�duD!ޮ�� \]]u�(2a[��g�ƍ�0UB
4H!D����B!�B�Şp@�ƍն�4iRܡ��I�&I\\�5�aÆ\�p��G���g��y܉'HNN�nݺJ�(�N�>Ͳe�زe
�����cccCӦMu��R�V-lmm����9{�,��j�ٳgIJJ�U�VԬY�_~���SRRؼy3iii|���3==���Tm����?��&cfee1r�HTm���ϲe�T	~{��%##;;;�����˾}�pvv.�5
!�B!�%����L@�-�œ�BM����A�U���CB!�BP�I�PnCɫ�Mdd�ڶ��3�g�f�Ν�&\�ر''���۔�������۷/�������&$$###G(�x�8;;�￳{�n��eդ�}��i�&�N�J�޽����ܹs�1������~�z����Y�&�g���Ɔs��1c���3..Nk�
6���@�&M�6mVVV$&&2w�\bcc	

������h6l���-::Z.�B!�B�*...����:!�B!�B!�B�+���D�������Sm/]���K���dm�w�Ώ?�Htt4w�ޥjժ}�߿ϑ#G(_�<�z��A�E#00�۷o3`�U��ٴi����=Z��	!�)�����C�ʕ���`��ɔ+W���l"""���P%�9r�B��سg��'���;�=*p\�`ڴi�d�f͚����q�Ʃ�}�1#""�;w.�>u�����GGG���U	�.]�v���S��Z!�B!�B!�(�.]�D�����&&&�֭[K5!D��k��������0�B!�P�.
�啾�ۛ7of��Ŝ={CCC�t����U�?������#99�r��aeeE�>}T�R�222�'""�;w�P�jUz��7�|����F,~~~L�<���ܱ��Ջ��`���:t��u��?�!;;��={bjj
��		��ŋ<y�U�ҡCF����q��O~��΂޻��t6o�L�-���P�W�^[[[6o���U�'�o[ٲe�ӧ���DEEѩS'�;Fjj*ÇG__��w�2a�.\��q�BQ��n޼	�VM��O?��&c޸q�����/տ�߿���W٦�#�B!�B�Fzzz�A�R-((WWW]�!��4i���Zo;}�4˖-c˖-(
���
M�6�A�B��J~_
!�ˠA�t�B!���%�B����˗quu�v��l۶���x��ݱ��a�ƍ�<ψ#HMM�ɓ'l۶��ϟ�����e���_U��={ƹs�8w��?V������ȑ#IHHP�MNN&  ���x�-[F�2e��^�x1���jI/svv&88���P���5�ܹs'}���_~���_�OJJ
�7o&--�����$?��΂޻�{���������xvvv��Ʋo�>����(v!�(HR�җ_~ɺu���C�N��L�2j	c.�…ԬY����ceeE�ƍ�b�2Q�儉�e5��ɘ�J��]!C�����]��db�B!�B�����Q&�	�d�n�O��=33��ӧӷo_,--prr��ۛ����mB!�B!�B�:���E||<M�4Ѻ�*�k���LJ��{8t�*�b���,]�[[[�={Fxx8���g˖-���
6���@�&M�6mVVV$&&2w�\bcc	

ը�Q�n]000���:���ʊO>��?����'O���:u�7nаaC5j��M��:u*�{�FOO�s��1b����
qg�+�u��EGGаaC��m��ђp!�(V�>�[�&::���x�9B���Ւ䔥�077��ի�����Z�&^V�fM�^�ʩS�Ԓϔ��r{�1---ILL$,,L�%a^�T�BJJ
���T�REm�2Q��v!�B!���qqq���E�a!D���B6����ܾ}���ȦM�d���:�N!�B!�BQ�i.��)'�6n�X�xzzR�V-

U	iii������R����<x�}�Ghh��_DDs�����}}}�֭������c���a``�����jJ;v��W��ȑ#����4jԈ={����?�`�@}���U��,轻t��"��eu��Q�#����ٙ��������R{�����deeq��E���U������?^���:u���lΟ?Ϝ9s�<�Uc*�OܸqC��cǎxyyq��Errr�w�?��3����9Rշ~��$&&j��lS�B!�B!�B����ݻ̘1�N�:ѦM���طo���j�ddd�t�RhӦ
�{�fŊdee���>&�9���ټy3-Z�P[��z����ڲy�f������
!��o���֖.]�p��Mlmm�ٳ��#{}�}��ĉ�8q"�����B!�BQ�K���?8]�p!.TmϚ5�Y�f���cee�����ϟ?W��?��3gCLL������R�|yU?�V���_m�d�W�ҥ�-�����affFZZ��Ą�ݻ��޽{�	&p����(�����\gA����055�8��M�G!�S�v�����ԬY��-[���С���̘1�3fh��E��yqss�\�t��Ç�ڻwﮑ�P�1��͹�>NNNXZZ���;���ٳ����W�|y&L��ڶ��'22���x�5k��W��خ]�W^�B!�B!�(����W���0����?�o���͛���/2m�4��YYY�9���U[rr2��dzl�2ʔ�{���{�������];;;bccٷo�TfB����lҤ��bz�&M"22R�ӧO�l�2�lقB�������дiSD*�xَ;����‚�U��~,,,�V��j�J�*�6]�]��ر�Z�jѼys]�"�B!J�bI�(*�ʕS�[�xnݺu�u��>|�]�v���b�
6l��1cT��*�A[u��T�P��ݻ76l`Ϟ=��ߟ={����ŗ_~����p�B.\�@͚5i߾=VVV4nܘ~��h,�B���W�ɽ??�����N9����m�!�xS�*y_�L������I�hʔ)dggENN��ָ��q��5���زeK�.���c�ҥ8p�ǏӾ}{���ػw�k�9y�d�/_NJJ����Ą��֬YáC��}�6*T�Y�f�9�z����޽;?��QQQ|��Wj1DEEabbB׮]_ymB!Di�d��=��0�B�CV�-9�=ʺu�8z�(������`aaA�V�:t(�z��u��B�YMQ,6�ۅ��СC���_<~�SSSlll�ڵ+�|�M�T*�իW���Ƀ��ܥ9!�E5��7o��3{�l6lȹs�����j}7l�@BBM�4aڴiXYY����ܹs���%44GGG���T��8::��
jġl�����!��+�B�]�DFFjm���d������KKK����&$$##��S�E�f͘?>w����ݻܽ{���$N�:��~���1�˗W%b���{jI����ͩT��*UҺ�?ժU�ػw/���g�8]�%�B!J�bI�����ԩS>�&M��v�Z�?η�~K�f����+�����ppp������8��u�X�x���TKKK	S}HP����

b׮]��ߟ]�vh|�@@@���\�zU�?;;��e5"===
�?Ve�k��Q��,Ƚ�R�
)))���R�J��SSSU}�B��Vu"7SSS�Ν��qJ/'vhK�P�S�Ne�ԩ��-�ݺu�[�n}���T��S�B\]]�'))�5j���ę3g1b����C!�(�N�8AHH...�E!�Щ��]� ��۷o���Ξ={4�ݼy��7o�m�6z��ɦM�TU�E�<y�I�&�r�J�J�>$66���X,X����;w�ڢNo*�Ϡt�$�"t���y��j��7q��!�����㏁����׿���7""��s���P�n]|||ptt$<<GG�<Ǻt��k��اL�R�B�������6�a�ҥ,]�����@n߾̀TmdӦM2z�hF'���{F��o�Ǐs��]nݺ�J¸{�.w�����ܻw��ׯ���߿�q��e�R�R%�$������m���N%U�*U�W���9�V����[[[H���U߿!�B�wW���}����(�٧O����:u*={���ښ���P��ѱcG֮]������X[
��� IDAT[���C6l���뱵�e�ʕ���Lz�q��j�R�W�V-Z�h�*S|��e�5kFݺu�����t�҅�W��߫���Ҩ\��Fsss�߿�Ν;qvv&99����k�+�u��կ_���5+U}�B�!C��{�n������^�$gii������B!����+AAA�C!�Щ�72h� ]��λu�vvv\�z�����'ңG>��C�v�!!!,\����pؿ����KO�<���?'22�r����憫�+͚5��ܜ��4N�:EPP�ׯ��ח?���ݻwi҅B;�E�~��Z{�f�4�޸q��Ҷ�Xn�Ɂ�V`V�i�@(���������c߾}$''S�\9����ӧ�FRZFF���DDDp���V�J�=��o000�IrWJOOg��ʹh�U��իckk��͛<x�;���U�
�P��֤Tm����{�.>�<|�P�߹ۮ\��jS�k�dhbb�J�011Qm�����MMM�T����&&&T�XQ�Oqhٲ%?���-"22��� f͚Ŕ)S���puu���Y�<��NYq2�
*дiS����ѣ��z���P���9q���ߧR�J�nݚ#FI��ӧO����*s
!����p1d��Ν���5r������Ç9{���$����3a„W��Lzprr��Ғ��0�������Ʋp�B���q�:Ό3�1c���/bgg����۷��O?��O?h�W��,轳��'22���x�ƕ�i�v�4bB�v���øq�<x0���%K�P�|yG'�B!�B�[��իWi߾=;w�R�Jj��ׯ���7����k׎��HV�\�رcuq�2a�"##���"$$DcRw�ʕ�ҥ]�ta�ر888�w�}��ŋu�����sO�-n/OT�6��U��=z��~�9˔)��O٦m\!�(�k��˗quu�v��l۶���x��ݱ��a�ƍo=�e˖�믿���={ƹs�8w��?V%\gee1r�HT}���	 >>�e˖i}�Tڻw/Z���٩�tvv.«B�e˖�z��T�^���W&c䕤���#���IMM��͛<z�H���C���y��Y��ϝ��LʨX��Z���2q���L��2��U��ԩ�:ubŊ�ٳ�͛73n�8ƎK���8p }������WI��c�����/طo�;w�uH*���|��WlݺU��Ν;���F�~�X�n�kυpttd׮]�\!�B��Y����ն����e˖%88��W�P�fMڵkǐ!CT�LLL`͚5:t�۷oS�B�5k�ȑ#�W��+ǚ<y2˗/'%%���,��:t�J�*ܻw�ʕ+ӱcG�>S�L!;;���(rrr�����͍k׮���ǖ-[�~�1a�ʔ)CDD������2}�t����\gA�]���駟���⫯�R/**
�v��'���5oޜѣG�����1c��'�B��,Y�ѣGu�BQl���u�N%&&2g�~��7nݺE�ʕ�ԩ^^^4j�H�A&߾��{\\,���ä��R�fM\\\����D�/**�={�P�Z5�oߞ&M�0�|F���ի5..^�ȼy�ؿ?w�ܡZ�jt��///����.�B���w�}����)_�<�ڵ��ۛ�-[j���h�"���������VVV8880n�8��P���S���…���abbBDD~�a��n޼9�w�e˖,Y���cǪU�~�
�/����{��>
����@~�����O*U�D�N��>}���F�F,B�B͚5�r�
���k������Ғ��D��°��,�XU�T!%%���T��쩩��>B�&�cq�l߾��K�bkk˳g�g���lٲE�p�a�hҤ	ӦM��ʊ��D�ΝKll,���8::�5!/::��
jĠl�����!��J�*(�!?O�>�ѣG������Fzz�*1�jIiii���r��]�_���<&333�q�	ʤ�J�*q��%ڶm�����GGGIOOg�Νlڴ	WWWZ�n���ݻw/��'*
�ܹÿ��o�9sf�J�>|8[�n�bŊL�>ggg>���ݻGDD3f� 88CCC����صk�F��-�B��[�Exx��������*;y������!ϲù���1q�D&N��o����֭ݺu��8}}}��ݛ�MMM�;w��}Ç�3###�N��ԩS_kA�
v�*T����+���$%%Q�F
���8s�#F�(��BQڹ���>�B!�e'N� $$]�"�B�U!!!�A碢���/HKKS�����q�F�o�ζm��ٳg��idd���n�:���krrrTmW�^e���۷���(*T����0r�H*W��ʱ���iܸ�F"��ݻqqqQ�(����u�ֱu�Vv��I�.]���ĉt�Ё'O�������ػw/��M�6�����;�;w&==]Ֆ��ũS�8u�k׮%&&���{�Hb{Ya���@�?�ȑ#_�l�ԴiS<<<X�j���̙3�@ǽ�~�OOO�ݻw	f׮]lݺ�/���X���u�ڕ+W�0o�<f͚E�
�p������۱cG֮]������X[[���C6l���뱵�e�ʕ���"�B��7�U��bPJJ
��������>B�&�	�7ֺ�����#����z�*:t�o߾���W�_DDs�����nݺ������Hxx8���y�s��%j׮���N�:j}���bhhX$ɲ999���܉�j��
e��k׮�[�FOO,X@@@����I��ѣlذsss�;F�
T��{�=����֭�1�ׯg�ȑZ3B!�(jŖp!�9���ݻ	

R}Y���%nnn:�N!�B!^puu%((H�a!�o�ƍU+ھ��߿O߾}IOOg„	�=�>��3g����O@@���\�pAm�tm�Λ7�iӦ�f�U��k�1b999�9���5j����O�f��|����*[�z�*�5j�����€��̤O�>̙3kkk���O���صk���#!!��իk���Ã=z0i�$>��S~��w���k�\���ٳٽ{���	HOOgذaxzzR�vm���9q�cƌ!!!��3g�bŊ"�-��y�>��dAm���ϪU�ؿ�%\h�b��iӦѺuk~��'�6mʕ+W����Mhh(nnn���T�V�Xb�8
4��~���ׯ���o_www>�ٳg5�c*_�<&LPm���s��}������$,,{{{"##���ר���ݮ]���0!�;GYBi�…,\�P�=k�,f͚佐cQ?~<3g�$&&���~��<<<puu�|��~7n��s�ſ��+�q�߿�X8�e�6e!�(��177��ܼ@��\��ӧ�ٳ�͛7JNNݻwg�ƍ��ӧ��>z�ٳgLRR���4��ӧ�����*��o����ooo���IMM�A�L�2���(e�IŊ5�mݺ�+Vp��)222�����ё9s横|>��l����100�I�&|���|��7�u��xzz�%[�faa��I����d��ժ��}���`��Ѫ*�z�b�…��r���Ok���Ç����}�vRRR�����ٙ����S�o�cϞ=�ĉ9v�FFF������Z��0�L!�%˻��+����>>>������Lrr2��������	B!�B!�B��iժUܾ}�iӦ�x�b�իG���iݺ5�W�fܸq����|��|�Ì3�2e�Z�ȕ+W���S����/��B�:u(W��ڵcӦM�_�^�_��zÆ
_���.]ʣG��ر#۷o�q��иqc�o�Nǎy��˖-�z�g�}��۱����ؘ��۳z�j�;���ɓ��	���գ\�rѡC���صkW�Ŗ��<~��'�5*��O>��˗/�7ѠA<H�V�044�Q�F�ر��;����Z�_��)..�N����???�T�e˖���F��f``��kbb�J����D__333:t�ڵkժSL�<�5j���OVVݻw��ؘ��(�8���011�k׮o������֭{��aƌ|��'<y�+VгgO�mۦ���G��_9YT�*�ʶWMB��.''����_S�zu����u�?���j~���l���:v�Ȃ�v�YYY$&&2w�\z������u�[�nѪU+~��W�޽˳g�8w�_}�k׮}��w��aҤI|���j��O�����"55�gϞq��
�,Y��ѣU��N�ʬY��|�2YYY<z􈘘�
��ŋ_�ڕ�Y���;���\h�;`�ر�]����<x��
������/����boo��?������?��#�ڵS��ԱcG���OFF���c�ʕjI��gB!�(y$�B���͛3z�h|}}�e̘1+	!�B!�B!�ۤ��0v�X�����۷/�s���2p�@����޽;���Sۿ�~�IJ���(
�]��j���P���:"""�+:�<�L�2|��w�ٳG��cƌ�hkٲ%iiij�5k��gϞ����5n��BARRR�Ŗ��<~�����333�"ޖ�ӧcdd�֖��4"�?M�ʕ�1c���'&&��7�駟P�jU��fffL�8���0N�8����^�zj��u�Ʈ]�8q�{���B�
���r���ת��$Μ9���[�'�	!�R\\~~~4i҄��8�.]
@�f�TImő�fff���������2���4�əʕ�����bS�����;F�*U��_�lS�BmN�>�����^;1,66����S�fM:w��ٳg�>}:7n��СC6�ʕ+�vl�-"..�V�Zq��i�={���i۶-���'  @�W�P������>cP.�p�B���������˪ʕ@�U��GOO֮]�СC���Q��O?�b�
222x��	�^��QR�����x��)�����ߗ��v�{�:u��{?����y�ƾݻw�g��>}Jtt4u����,Z�Hu���X�����@ݺu9v�O�>��ѣԩS�s��1�|�c�ׯ��˗������;v��	!���)��D���ꪶқB����ʕ+��0�B�'$$D�!!J����W�^��-ĻH�O������򢬊����ù~�:���cӦM����믿��UHx333>|Hzzz��^�W�$�2e�2���<I^LJ4V͜6mC����?~@5��w��|��j�ѿil����glḷG�
}>|�Y"La�o�^k{�-�x�b��"Dq������`�ԩt��
Y�`�*�2�ݻw���'AAAXZZ���V�c	!�=���m�šO�>$%%1u�Tz�쉵��*I6��k;vd�ڵxyy��鉵�5>dÆ
�_�[[[U�-===
7nܠV�Z��I�)))$&&j$V(���<$��9::�k׮WV�)��ݻ�_��o��ƈ#8p 666E:����M������׮]K�z�ذa�jс�-Z���'ϟ?�G��J����K�bmm
��̯��_P�O�fǎ���_Ֆ���B���ɓq��Y<�'噘������ŋ9�<����5�Q�F���?}���G��mh{��X���?�;;;����֭۷og����7�D�U�VѦM���Y�jݻwg����-��	&0g��߿��_�{&�B��G.�B��Ν;ٹs���B!�(�=ʺu�8z�(������`aaA�V�:t��T�?�r%�����(ϥ�W����3ߒ�qqq�Y��#G�p��u����T�
4�G�6��:wIP�üb)L���}��E֭[ǡC����?IKK���:u�жm[����]��[����S�$/Wk(l�5k����)�v����\�ϣG���OԯW�qqq\�x�V�Z���lʖ����*y%�����c��˗/_�q��ݩX�"�g��ԩS���߬]���k�beež}��[�n�Ė��<~666�:u���Մ��8{�,�j�Cqxy%e�
�sK]���}+獋��gϞlݺ����k��jnn���ËtL###|||7n� 44�%K��P!�)		C�a�ܹZ_W�5k�����;���ٳ	g�˗g„	�msss�߿���������aooOdd$���j�]w�v����v��u�mĈ̙3��͛��1�	(��~ٹs�Զ�={ƨQ��`�ĉ����J��J��If��aZZL�0�p��}դ���dz���ɓ'�=���/�۷�}��1}�t���?~�Z���\{�5HLL$111߿߯^�
�|���[�nj�m۶�ʕ+y�O�=���WkW�.�]�T)��eE��_�	!���)��.B!���r9L���������۷oӳgOڵkǚ5k�x�"���deeq��M�m��_|A�^�
<9Q�3>\�*�6S�L�e˖�Z��.���INN���#::ooo���ٶm[��-�M�?��ÃF�1�|N�8�������&##�����������ť@������)�6<|�0�S999�^�p�q�ơ��dž
hԨQ�ctr��{����˗�R��ڤ8e�B�#sS>ϔ���/����'O���H@@��<�\�����Jl��u����
���׹sg�����~��I��xY^��=�T�R��"Dq���d�ĉ4lؐ���S�L,--qrr"((�5j��͛7g��������˘1c4&!��x9���j���ɉ3fРA000���
wwwfΜ��gbbB@@���XZZ������:t`�ڵj�)&O�L�5���'++��ݻcllLTT�FQQQ����ދ	!�?ɗ_~�V�-@����r��}��}�v튿�?�h�"U��o��eff���3P�����r��I�իǤI�T���m��$%%���=xyy��**A���>`�֭����[["`�-r��rE�W����'w�Pm�QA�B!JI�B!�B!t�֭[�iӆ={��������������ӧ\�x�Y�fajjJxx8dgg�:lQ�^�___ʗ/���gϞ�ѣGdggs��]���ϗ_~IZZ$..N�!�.##�N�:���!#G�d߾}ܺu���,<x��#G�8q"���lݺWWW]�-�a����رc�:�ɓ'0���fΜ���C�}�����M�{���/���A�gǎ����}�366V�1'N�P�WTjժ�СC��ҥK���p�����<~�|�
����\����ə3g�L�2xxx��SNX����8���_�L�j�111|��'��/���{+?��������9z�(������1m�4�U׊���+�-bѢE8�#�x�����ZA{�����Ž��3mذaǎ�رclٲ��cǪ�a���̘8q"aaa�8q�����zߥԭ[7v��ʼn'T��*T��Օ3gΐ���ꛔ�ę3gpss�շ���y��S�N�nݺR�N�����]]]���c���j�nܸ===���������vA��}ܹs��ڵ+*T�jժ�5Jc����<<<�Z�*FFF4Hk���ϙ1c������SSSڴiÚ5k�辽�:u�p��u�
(?�t��Z�"22<�СC5�W�fM��_��c�j���ǎ���www��gϞ��mnn�СCU���;<x�ĉ}�����y�4�~(���,\�x��ˎ?��}��6l������?^T%�M�����*�=B!D�S��]^�r�(!�P���B�r�t�BQ�����C�r��Uڷo�Ν;5V;�_�>���8::Ү];"##Y�r%cǎ�QĢ����ؼy��d�*U�йsg:w��ȑ#Y�j�g�f�Ν�U��&M"66�:u���Ed�J�h׮�ڵ��Ã�m��޽{�޽�����?��S�N1g��v��app0����G������'O��ٳgqrr���;�1:v�ș3g����^m_||<}��k����lْ�]����4 IDATA���ٺuk��n޼���/eʔa��ɪ��ݻs��I.\H�n��V�|��9���@��
�N�:$&&O�ƍ����i�/��^��W�cǎ�����?g�Ν����9Fll,���dee1f�U�%sss�ݻGll,;vT���y���P(<�\��h�":u�֖��Âpvv.�X�B!
bȐ!�޽��� <==

���R�"���{��	;vT[�%11��s��޽{)S�+V� **�o������S�V-nܸ��ѣ�Q��V��󻋂��[ǎ�w��"}�ʕ��������hoo�իWU�lܸQkU�S���?��������!&&����b���c���c���"b�%T�H%��/��X�ml�V,	�ڒ>���JyPb���&� jo)�!�PI��jO-!�,��~3O�Lb&���5/���{��{f��{�9ݺ1k�,���X�x1u��!>>�y��1w�\���9x� M�6��Ç�����P�J��u�Ё���#G�a�,--7nK�.��ΎK�.eϳgϸ|�2�|�
��Z���������+�ϟ����/_[[[�\����/}���nݺ����3=�[w��͛ӿ֬YC�-���K�=�P��n�b���L�6���D���prrҪ�СCY�n
4 ,,��Çht�V�����պN�ҵkWf͚����Y�n����:uJ��g�}��1�E�c&�B�Hɡ���+�Q-�K^�Wf��>?Ļ!�۟��%/y�K^o�KhsssS���2]~�իW�!C�(�+WV��̔
*(nnnJtt����9/�N�Rz��XZZ*���JժU����+�?�Hw��Pʕ+���￯�����@�S��ֶ.(���W*V�����*+VT<<<����,�(�r��I���Y)R��R�T)�S�Nʉ't��6L���U����A�ʔ)S���''��,��/��q�����A111Q,--��={*����I�v}ڛ���(O�>�4_EQ�k׮)�baa�w�������-Z(eʔQ�����e�*:tP:��:rL�E�ׯ�R�B���D���S.\���I�W�^U4h����+�}�Y�c1�3�u�o}�i\\�R�P!���4�v���*�2|��\���m(�ee�i_�~?d��0�����7��_�>�e���G���P��?VN�8�$''+T�����)&&&ʙ3g��رC�]��ɓW��.\X�o��V�}������8p@�Y��(���5��믿KKKP>��eɒ%��˗���4%))I���T�̙����{
�L�<Yc��ׯ+%J�P�K�.Jtt�����DGG+]�tQ���\�z���q3�FQe„	
�888(���S�<y����)���J۶m@quu͓زs�EQRRR�O>�DSSSe��������x%--M�ww�^���C�]ٺuk�ߗ����씐�%99Y���SF��)R$�c�:�7oV��Ҕ����JϞ=�.()))ʟ���k�N�.����<U<���D���~��.��s���ߏ
6̓W~W�7o�ܼyS�y�Ҽys�����o+C�g��ӧ+�ҤI�̙3JZZ��899)���O?��8p@122RZ�j����+�[�V����������bH���5k����*III����(����t�uvvvʉ'������Ê���V�ߛ��������<~�X�U���&/k�>|�|��:����+��Uךnݺ�T�PA�k�j������̔��u��}�f�~Ϟ=����^��W�Ν
���ӧOWW�,c�֭�������͛7�J�����|���mU�T��_�������U��ܿ_�엽�^�c&�B��'�;\!����C!�B�CnP9rD)Y����E�Q~��7�}^uC�hѢ�W�Z��L[�~}��;��ʤI���ӧO�����~��W�hѢ:�,V���ͯ����_�-ǎ����ɓ�t�lll�۷o�Zl/��ˍ�g�oΜ9:�(\���k�.���l{VmN�jժ
��X�"�|�*+���
d����(�:zL��L��̙3u���ئM�߽z��Q,�5�,/ڷ!���Se�Сz�CQ^���g��ܖ��چrR���`h�������ګ�����e��___��
6���z_���+FFF:�}��GZ�+��DFF*ժU˲ccc��*;w�Tw��޶m����׵�ѣG���C�1V�TI��Dn�f�SIIIQF���2�#Fd�9�ԩS:?o���/Ӹ[�n�i�Q-)�K��JW�B�ܹs�%U<�����~��.��s���ߏoS�Ey�.G���=Z	̷8�x[�u��Q�ʕ+����@iժ��ѣG+�ҴiSPF���]�oC�Pퟱ�W||�(�
R�S
|p��<��7�*U������2o�<���˯>0y���ȑ#�*U�(&&&J�2e��]�j�>4�z�_�����K)U��bff�4l�Pټy�V���P
��+aaa�<x����K)V��R�H�q��ʦM��)S�(�ҡCuZ�A�J�"E�"E�(�j�R&L��50�>u�Ν;��>�L���T����r��)�:uRv�ء3��n���JǎSSS�R�J�رc�����6lP�V�����(*T��?���x�?���R�R%���Dy����#Fh
����̮1�s̄BQ�)�������������ѣ���9�R�

�??�B!��.www֯_�sY��888p��=F�����>gϞ��ߟ��J�(�����ʲ̙3g2q�Du9nnn���_888�������?~<�*U",,�A�ǤI��6m5k��󄅅ѤI�l����T�V�'O�ХKf̘A�jոt�����ر�ҥKs��y*T���O55x�5�^�:�|�
����ԩS|��\�|�:��o���qrr"44�!C�0n�8�T�Bzz:'N���/���xzz���+�e�����+���?�~&&&8::�p�B�ի��˗���oٹs'\�t�r�ʽ2}�Ե�…5j�|�	ݻw�U�V|��*THg9����퍏�5k�dŊ4hЀB�
q��YF�����iڴ)Ǐי�!��޽{T�V�G�ѫW/�N��|����7nǏ�ɓ'Zq�4�ʕ+�{�n���y��1�*U�v,�:O���j߆�ӏ>����08@�6m^Y���>�������-�}�|>r�Y�+F�����-�[���4�__^~Yll,�g�f���ܾ}sss7n�رc���O5Җ.]���2���aHH3g����$%%Q�jU���;v,�֙GJJ
k֬a�֭������cll���5���|��Ԯ];�Ο?�̙39p���ݣ\�r|��L�0����y���g�fǎ���_���accC�.]?~��Y^�f�{Y\\��������ƒ��H�%�^�:�~�)�
�>�2����N�JHH���ԯ_�I�&ѱc�L�z�*���������B�
�~��V]ϝ;�_|�ٳg������?gܸqXZZ��XT��~Sf��������P�7ox�����G!D~�zv^277'999��eʔ���U/���ШQ#"##�Q��O��H�"��~�R�j�������y��q��-R�)))$%%Q�hQu^O�<�D�i7n�ȠA��1�������ȑ#177��7�!�g�B!��.��"3rY!�B�}oP�:Ix{{3}�t�|F�͂2ݮF�-HOOg�ر̙3G�m���̙3�^�z�q�F�����iԨ666���_/^���D=zDɒ%�Q��=x�����������O8t�V�T7 �βe�4�<t�mڴ�T�R<x�@��hѢ<}��P�T)�}����U�+V�ƍ�[���=�z ݐ�gܯV�Z�<yR��^�:M�6�I�&�2}�Ե��(�?�y���s���ŋӰaC�5k�'�|B�V�066ֻL�]���ӧiР�ƶ��8�U����9���:�3�N�>�I�&��ܒ��N˖-��g�3�1�X���C�jl�n,�5��h߆�S�C��/eʔ1�>�>�������-�}e։)����bT�B<�!y?�d4!�>2@Y���G!D~*.T2cllLzz�z9c���5k�������…���Jbb�F����u<�x��۷o��ߟ��P��50��il��S�~�!��-��)2d�S!����B!�B�}�`o޼�(�n�ҙOtt�(�5ʴ��*666
��m�VIOO��ޠAP>�W�
R�ٳgz�ץQ�F
��ٳG���]�
h���������ɓ'Zӵ+��T�VM��>�HY�n����ile����+�zC�q�M�6eY�&M����qf%**J3f�R�V-���Hk�x[[[�mR��_�������Q��rL�6m�������۷�>1^�xQk[Nby�����(�ڷ!����X�>��gn�ǐ6�Ӳt����Ӿ^���¬b|[�����3]� ��k^�����m�|Bh��w���G!D~�zv^�^��(W�^�+��ѣ��We�ȑ�u�2�}��֬YS�5����W�;y�2~�xP�-�ʘě���B!���C�	!�B!�o����`ee����֫f͚\�t)�<��իW���cÆ
Z����P�n]�bR�j��c�룢��q��:��֫b{����ֺbŊh̚0q�D�?N߾}�����ښ��u�VRSSs5��r��bH�3jժ���5��ŋő5k��~ 22����w�^���{ڵk���9�/_�m۶�>}�༯\�®]��4i...XYYY�f�1�p�
6ԙWӦM�$�ʕ+k�ˍXEy�K��j߆�S�9z��Ae��҆rZ����Qv���r�Y���B�{u~��K^�zs^B!D~�֭nnnDDD�����۷;v,FFF�i�F���,X�'''BCCiٲ%�-���4�����l���>}�0l�0�9BZZ'O�dذaZimmm122bٲe<~���u몯ۛ��\�B!�xw��wB!�B!�뒐���t?��3AAA�(Q�;vP�ti�4���/�WYvvv���s��E�4i��>��阘��'���������%J� 11Q�S��ʀ���`���DDDp��uV�ZŪU����e߾}T�Z5Wb�(��/3��?#KKK��U�hr��(U�...���/��ѣ��矙4i�w��+�M�61q�D�\�bp�SUQ����-[6�}s���y�ƒSyվ
i�vvvDDDp��y>��#����d��a���ǐ6�Ӳt��Y�zYN?3�Q!�

���
d�������]΍�ؼy3nnn�Ä	ؾ};ǎ�|��ܜy�����C@�%X�v-����^���u����Add$�J��\�rܽ{��իS�J�^��w�3f[�l�̙3���Ӈ�����ƍc���xyy��奱-�AJěː�Q�B!��;\ܽ{�:P�T)�������v�J����QLLիWe:GGG���
.#����7o�dݺu���q��mLMMy���iժ�{�V߬y+((���0���={��爄B!�x3+V���>|��C���p�#F���Ȉu��Q�F�L�x��1O�<ѫ�-Z�޽{��pK�F��ԩ�֭^<����C=zD�2e��y��:��Э[7�u����́8z�(G�%66�˗/3r�Hv�ܙ�����α�N�J�ҹ��(Z�?}����/Nbb"ׯ_���4]�%�������ѣz����;~�!������`ii������ǛU|�=ʴ�d�z^Ę�XrC^�oC�i�6m���`�֭�v����|��EY�ݾ^��B�w���k~� �0PZZ�<�_���uruu�{�baa��cǘ6m۶m�ƍ�,Y��-[2m�4j׮
���ׯ_g������`cc��ŋ����ˋ��@-Z���7��7)))�a�…̄	��_HHH�K�.�X��
6h�6l���,]�T=C����}��Ǐ��B!�����"**
��5kj,תU�༾��>��wr((bcc2d���������î]��|�����̙3,Y��M�6�(
�z���ޞz���whB!�Bx��ۏ;F������ӧ��ݛ��$�M�F�Ν3Mkkk�ٳg����y��̻w��,X��e˖1jԨLG�Wٶm			����r��iN�<I�v�9q�:]n���f�8�_��N�:�'�e���ӧO�^�A^5=�J�B�x��9IIIZU_�|����֭˱c�ضm_}�U�i��̀���cƌ,_��aÆil�u���ϟS�P!C��R�F
�?NXX:t�ڮ�I�uĘ�XrC^�oC��_|��y�X�|9Ç��g��|��EY�ݾ��sZ�?dTM!���#3	!�E�K�f��,X� �4���j��߿?���W/��ݛ޽{g��w���%K����__�W�4h�
ʲl!�B!^%gwij!��eC>|X�����1C�Of��ټy�HLL�I�&�ѣG�駟����u�K�,��0�j���L�4�=z`eeEŊ�޽;�}�����B!���!�3f�|�<((###��njùs���Ί��3���Zۢ��022R�иqc>��Sn߾M�^�HJJ�4�����s�R�P!ƌ�^߶m[�̙����5�y��9s����?�2v}���`ddDtt�ֶf͚i���ز{��)�={��ٳ����5��.]��'Oj��i9��5/�0u�TΝ;�e�3g����I������ׯ�V^���W���E�t���Y�x���vUyY^Ę�XrC^�oC��~�СCy��	m۶U������t-Z�s��|��EY�m_���^��B����9�u����t[PP�G�f����B!�B!�B��2Å���~~~�����/^��ŋ�No2��3f̠T�R���P�~}|||�޽;G����z+W���ݻ���Ӈ
6�r�J����1:!�B!
>///�.]Jhh(�ڵ��LJ:u�p��q6n�ȪU�011���G��Ν;Y�t)u��a͚53K���鉯�/+W��B�
�1�%J��_
��Ay???5jĞ={�U��|�
�۷��ښ��4._�̞={�7o���L�<YcTzOOO/^̡C��޽;>>>����ĉ	��ܜ���?9>�}��a֬Y����h�"�5kF�…�x�H���s3�윿��{�nz���ԩS�Z�*/^d���=z�>�@k�4'''v��СCY�r%���ܸq��K��lٲL�)^�8�?f�֭t�ڕ�ϟcff��Y�jǎ�q��2�^�zQ�N�+���9u�?��3۶m��Ą�S�ꕷ��5qqq�3�����XZZr��EfϞ�ڵk����Z�u��ӓE�Bǎ�={6\�r�ɓ'�gbxY^Ę�XrC^�oC��…���!88�z��ѷo_\]]iذ!e˖%99��/�����?s��5��^�5/��n���=�:?��B�?�|�
��y�QfB����}���C!ؼy3nnn��B!�"FJ����]=-��ˠ��Ef���y��9~~~�۷�[�najj���-]�t�k׮���^���ǘ1c���g���������Pf͚���133��ɉ���KKK��_�U�ʝ;w�%44�'O�`ccC����F�;p��7o��ŋ<}�KKKZ�n������٪WRR����߿�{��aiiI���<x0fffi;v�ȝ;wظq#vvvzC�{�.?��#������Ӿ}{ƌ�!��s��е^��U�nܸ����s��9
.�'�|�ȑ#)Z��:���K߲�m+�?�cǎԮ]��K�j����ETT���%J�����}>/�B!��www֯_�s9�ݻwӣG�LG�������S������ӧ_C��0x�`���裏8x� E��XE���p5s. IDAT�t�R�e����<��]�puu%%%Ek[�…ٸq���QU��O�k{BBM�6�…:��T����T�R%Ob3�e�Wv�q}PPÆ
��+T���}��]�����pZ�h�ӧO�����c�С:�svv&88Xc�*̓�ݻ7����Y��%K���O�=����~R��I�&�q�F.]��/���1CBv�iXX�۷��ÇZ��Y�����k�W1f'}��'m^�oC�)@jj*'NdѢE:g�ȨJ�*����|( 7���]Vv�WV�׼�����z����ׯW�����������m���k��SJNN���u����e�/$Dn��s�гg�A!4���B!�B<�e��E���X��ܨR�
[�l!**�`ooO``�:��%KX�f�z9--���H"##ILLT?8�������cʗ/�e�ٳg�k�.�>}��ݻ9{�,�֭�dɒ٩�Au��>��ǫ����1y�d�={F�N�X�l���eܾ}��7�����i��Wjj*Ç���nݺE@@QQQ,Y��B�
��
<�3f0t�P�u놓��j����T�10$��2p�@�ܹ�N�u��W�,Z?�aÆ���#��q۲eϟ?����|R��me�޽$%%�;�dԬY3N�<ɾ}�4n�!�B!�u�Ё�g�2{�l�����۷177�q�ƌ;�O?�T#��˗
.cРAT�V��3gr��q����Z�*���;�…k�S�V-"##Y�f
[�n��?�$>>ccc���qvv��/��p4@�N����`�̙8p�{��Q�\9>��S&L�������Хdɒ?~�ٳg�c����/��Ұ���K�.�?�r���Yl�������J����/8{�,���|���7Nk�x�Whh(S�N%$$���D�ׯϤI��رc�w�\�OOOBBBHII�B�
�m�K�f�޽�ݻ����s��I�_��ӧO)^�8t�ЁaÆ��{���!C(\�0,�….\�ƍ3r�H:v�H�j��߿?˗/ϕߡM�6��?�d����ܻw�jժ1i�$�����Q^Ř�XrK^�oC�)���s��e�ȑ�^��?�����h<x���1�+W�I�&t�ޝΝ;cb����|��vY�m_Y�__��B�����+dFq!DPPP~� �B!r�̙3ԯ_?��7d&!�o����B%**
x���eՃ��/��ё��4v��ͬY�شi����Y�H\�jU�fQx�ѣG���iԨ.\����͛�[�N��Ԭf���>uX�z5���ԨQ��ӧciiɂضm��7l���	�ԩFFFDFF2l�0BBB�U�u��q��yjժ�ĉ����ڵk���p��Iv�ܩ1�^�n�(V�����^��իWcffFݺuqvv�k׮�ې�׬YÝ;w�\�2ӧO��ޞӧO3eʔ,�_V���qʔ)���{�����C��.�=_���o[	

�y�]�.44T:\!�B�{{{�N�yyTx}�hт-Z�O�…2dC��V�5j�`�ڵz��E�̶[XX��ハ�O��f��*���?�:u�p��)�ciР;v�0�<��ٓe�m۶�m۶zǡO���ϴsA�~��ׯ���Skkk����//b�n,��Ty�;#C۩�ᅬ�����Hv�v}^��N�z�5�?��5���z
�#�"�|�Nߙ�
�=^�Y�3�����Ǐٸq#�5���B�
8::�q�F���W�gB!�B�wY׮]ٱc�\?B���K���5k�\V177�ɓ'�_��+W�кukz��A�=�.�o߾��l/:0�f�S����|��:t(G���[��G�0v�X���t��>r���p�����åK��7ʟ<y��z�߿*V���2e��v���ݻ�.`������…8q��9s�S�NIJe��#��pp0'NT���M�2n�8ƍ���� ;�7n��<���@BB�z���ː��m+111��N!/����H#�B!�B!��DF "g�4i��!�w��3}�.;3�g$3�!�((�]���B!���VB!D^y-.^�bΜ9̙3G�������/F�9r$S�N%,,���0�-[ƠA�pss�H�"z��z�U�6m��\�^=�����rY�:ܼy��իg�_||<�F��…Z�t��ԧ^��7�;w�Yf\\\��888���HMMeժU�����?�ϭ!���C�:u���!�S?[[[��%K�^���r��:_���o[��>���T�Ti�B!�B!�B!
}g��7�������kͶ2��B����;v���Έ#�;�|̭[��0aB~�"�B!�"�u�}���дiS���ٱc��'����[��/��R����n`b�yT�g5�>���^�͙3�.P�reZ�j���-5k֤gϞ:��S�WM��q�-Z�����ݻ5�W�����???��²����1���Z��\��EQ���T��-_���T���s��2�lCۊ���Z�o|B!�B!�B�I2�*�����qss��0�k�� h���w��ܠ�L�����Ɍ�B�z��İm�6�n�ʩS��3������[*W���X(�B��ѣG$''����ÇINN&99���~��!III$''s��RRR�<y25j�x��>y��ӧč7�����ݝI�&�%vsscÆ
�Y��~����
���WWW6oެ^�zVN���>ed��ܹs�=�cǎQ�hQ\]]�;w.ŊS��}�6'Nd�Ν$&&ҽ{wV�X�U��ϟ3e�6m��իW133�V�Z|��<8��B���Z:\����СC�U��V����|��W4h�???�}J�,I�Ν�ܹ3�ϟ��^�������2�ΝӸ�|��>���O�{�=�_�N\\\���Qud�t��\�rE�===]�s�>�����ڵk�ڵ++�,����@DD[�l���Sk��k�����occCLLS8GFFj�522BQ)^�8�{�
C�ח���в�i+e˖���<z�e�j���#u!�B!�B!�F��#�����L����� 3�!D^S����n�ʶm۸p�����{����T�P!��,ʔ)@߾}����M�6��B���ҥK��ӇӧOg���ܜ�E�baaA�b�(Z�('O�`�ʕ�#T
O�>���Y��ƙ
���K�B��%$$�����V�Zamm�������*UbŊ.�SFF�����$%%�|�r�={�~���Ç4o�\�9��@�ʟ0a?��z955U��6!!�ѣGg��	!�((r6������U���区t那�#���IIIT�V
{{{@����1c����HOO�̙3���жm�l�	�סy��̝;�۷o���S�̙���#ݺu����㤦�r��E���;���������3���\�x�gϞ���h�">|�:m�>}�>~�����HMM�ɓ'9r��c�j�ih����O���ӧIOO'**��ӧkU���۷���̕+W�5k�V:C�ח��ː��m+իW�׹%#�:U!�B!�yGQ�W�l(D~�v*�B�����5^�Z�:����g�&O�Lݺuy��)���t�Ё-[��.;3�g$3�!D�{������1Y�n...s��%����֭�
��pڴiC���uH)�B�ݻw�;�|U�Z5>�~�N�:=z�˗/s��M<x��8>>�˗/s��9N�8A׮]�ԩE�}�qϛ7���p�4i™3gHKK#::'''���(U��W�&!!�������3<<<HHH`ժU�.]Z�7a����Q��Չ��%))	ooo�mۦ�>w�\�\����'N� %%�Çs��9��T�4~��wRRRx��1���,^�8���B���Zf��:\xxx���ìY���oР���ҥKs��}�w��v�28�2e�0`��u5jԠW�^:�g6���"��u8p ����ܹs|��g����u���޽�ɓ'3y�d�r/^��13�>�0`����;w��}�j�-R��F�R/;;;ӯ_?֮]˦M�شi�VU�T�믿�V��{�V�6l�z}ݺu�~��ƾ�[�f�֭,\���h�=;��K��eH����͛s��a���4���O-Z�0�NB!�B!�B!�yIߙ�I���eFq!��O�>e���l߾��;wO�5�ׯݺu�aÆ�Ç����,[�,#.x���X�d	���t�Ё�Ǐ���sdBQpyxx0g�j׮�ߡ�bŊɦM�>|8���lܸ��U�f�Orr2���W?k���a�>���ų��V���Ύu��1x�`�EG�Q�F1�|���cĈ|��'�V���ŋ�V��F�bƌ3n߾�+VиqcZ�lɲe��ر�F^ŋ�ѣG̟?���h�v튧�'����0!�N��p���Q��ݙ<y2~�!fff���akkˀ�:u�:ݘ1c�T���Ƥ��f+.����	�˗���,_�33�l�ghʖ-�ʕ+qqq�D��������ٳ�С�:�رcqqq�hѢ���Q�fMfΜ�СC�:@�S��ŋ���VVVS�dIZ�nͪU��fK1bK�,�u�֔+W�B�
aff���=����]�V=���������닇��˗��Ԕ�-[2�|�c;j�(z�聅�fff4k֌I�&i�3�~��|R��m�m۶����WHHŋ��O?5�NB!�B!�B���޽�������?�������5;GG�W�c���4����޼y�9s�н{w�5kF�V�pww���Ok�ca��� F���ѣ�7�yKߙ��Mg�,㪙*���o�:�Q\!r.11�>��Ν;͘1c���!::��ӧkt�ؿ?~~~,Y����{/�.xT.���ټy3E��s��$%%�sdBQp���?ԩS�C��w(��W�^�9s��ŋӨQ#V�X�iڃ����q��u�t�U�V���H����К���LJڵkF�5�1΍2@���2e��s����8>��#��Z�l���ܹs)Z�(����o��v������B�%^��w��X��?�L��&+...���h��l���[XX��s3;�+�S��+���e�%Jd�F��"#}�U�dI��%}4mڔ�M�����)�W_}�W_}�e��E�2a�&L���^�9ҷ|Cڍ>�ː�A��R�X1�����ƍT�T	�7np��Y�
�� #�B!�B!ĻD5�O͚55�u
�S����2d���RSS���!&&�]�v���O����1�7י3gX�d	�6mBQz�ꅽ�=�����Єx��;ӷ���e�t��ܿ��ݻceeŮ]�dFq!��Ŋ㧟~�S�Nxzz���3��Ǐ<x0��9�z�z�Q|����=�v���ٳ�f͚ѧO�n݊��q>G(�O�=����}���^����~����ȑ#L�2///����O?��1h2�o�����-�ڵ�U�V899ѢE*V��Z��؉A�l���:��E��U��(��d@�w�޴mۖ�۷���Ohh(���̝;���B�y^[�!D�yxx��o��~�zƍ���뱲�Һ� �B!Ļ.00�����C!��S�7o��
��:\���Jv��ʼy�HLL�I�&�1��U����΅�7o/^dɒ%L�6-W�}$''3i�$z�聕��b����͛7S�h�|�P���۟S�ѽ{wLLL

�ʕ+T�\�-Zh<��o:�,�?��3���ݻ+V�
0|�p��cƌa�ҥܾ}���T�Ō�.$$$����k�*3�!��>��3Ǝ����5�F�ZiF��ӧOY�ti>DX�YXX�G����c׮]�iӆ���
__�O!
����зo_����͛75:]��LLL�>}:�1����^�z�_�'''�Eg�_��Ν;cff�ѣGY�|9���������D˖-iѢժU˓mll�����իT�R��'N�Hdd$�5�ԩS|��,X� W��G�jՈ���ȑ#�k�N�>,,Lg�ҥK3p�@ȩS�زe�g�f�����B!�p��;!���-ʔ)Sعs'�n��֭[�ܹ�)S�P�H��O!�B��I�&����wB!D�suu}g��կ5k���燣�#7n`���8::�g�9w�3f����)B���ճ�=z4?C|c�\���w�һwo��>}�p��]V�\���	�	���ѹsg֭[DZc�8v��6m�?��%J��V:�,�v��ĉ<x��s�jt�pqqaǎ�8q��{���Q��ٳܸqC�V5�x߾}eFq!��ӌ3�W�����Ӏ�޽{	`�ҥ2C[&T�7�]�&Mذa~~~Z3>	!��ڵk��_0w�\���F����
������ԫWggg�N�ʳg�8s�ׯ_gРA̟?��'O����ۇ��;W�^�?�����XYYѳgO/^�ٳgy��Y��֭[7��܈�� ==�۷o3v�X���hӦ�:�Y�`NNN���ҲeK-Z���iT�Q���f�}����aÆq�����8y�$Æ
�Jkkk���˖-����ԭ[��u��3i!�x3�B�a6l���s����/�Ԛ�Z!�B�w��_��_��a!��JJJb�̙>|�"E�вeK<==)[��:�������>�t���,]��Ç���L�6m�8q�δeʔ�Ν;���S�T)�m���:�IJJ��ߟ���s��=,--i߾=�ֺ�{��]~��GBCCIOO�}���3�f͚�U/]�-_��ƍ�?>�Ν�p��|��'�9Rc��;w����Khh(O�<��Ɔ���ӡC�l����lܸ�F�i<�W�Bu�~��i=�-�x{Ɍ�B�;�={F�J�8y�$^^^�Z�
�G�1x�`z��I�=�7����SSS��*�;wf���|��T�\ww�|�P!
�/Ntt4�G��bŊxxxp��
֬YC�…�;�|U�lY�oߎ��/cƌ�����S�bE�� �zf?��~������BHH�'O��ÇXXX��䄓�-Z��q�Ƙ��ׄ	ؾ};ǎ�aÆ���͙7o>d���(Q��k�bjj��ի�[�.DFFR�T)ʕ+�ݻw�^�:U�T��իz�a�1cưe�Μ9C�V�����CLL�F�q��1|�p�������ؖq_!�o�w��EA�B9/���z�Snnn����wB!�BX����wB!�k�(J~��ک�������F�*UزeQQQ0{{{���&$$x���9u��ׯ�x����Ǐ4h����;���:�<�3f0t�P�u놓��j���Fvjj*Ç���u�n�"  ���(�,YB�B/&�~��!�Ν;�[�n�Q�)_eذa<z���O��e��?���7�����Ã��x�>qqqL�<�gϞѩS'��޻w/III�%5k֌�'O�o�>>���!�$y5�ϛrOG5���#�ׯ;w����ŅBO�.]�gϞ�g̘���3�5���4�,Y��ax����g���Ill,�
���*[�r!����Ȉ5j@�޽y��޽;�ڵc۶mZ�X�k������/iѢ}���ȑ#0@=+�.fff4k֌f͚1~�x�?Ndd$G���ѣ���|��+V��͛ӲeKZ�n�w�;ƴi�ضm7nܠdɒ�lْiӦ�g.�����^��E'�ŋ��ၗ����,Z�ooo���oRRR*��&88�	&��/����@�.]X�b6l�H;l�0LMMY�t��z����}��Ǐ7�l!��;��B!�B!����Ԕ����wB!D�
d���F�R�`�U������İl�2�իDž�4i7n�`�ڵxzz�jlk׮�ƍT�\��ӧcooOdd$�'O֙�[�n+V___V�^��ի133�nݺ8;;ӵkW��֭[���U�'N��֖k׮����ɓ'ٹs']�v`͚5ܹsG#�ӧO3eʔl�ϐ�U�T�”)Sx��'  �C��;\�^����xjԨ���ӱ��d��l۶����oD IDATu�C�

���A��u�����B�w��(.�ٷe�
���=|�������E||<+W�d�֭XZZ�w������*s��aɒ%|���\�t	;;���BL�k�V_�pvv�ȑ#�oߞ-Z�g����|��`�S��N�b�ȑt��Š}*Dݺu�[�._}��bГ��`>���/�}��A0J�.͂X�`A���@������_�ܻwoz�2 �kt�/Y�$�������2�A�4hP�e!�x3I�!�B!�o%WWW\]]�;!�"O���I�����^�fM��/�Q�F������xyyq�С\�p�ĉ��4hЀo���#F�����.\���'����̙3�:u��� �-[F�r�ؿ?>>>T�X��U�2e��v���ݻ՝t�ҴiSƍǸq�U?C�W7n����Y�HHHPo?z�(cǎU��Vw��N�111���/S���J#Ļ�M��"�Ɍ�Ba���4Ə�…2d?��#�`ƌ���0f�����֭[>G�f077��pq��M������IOO��ښk׮I�!��5j���~�XW�vm�?N���i֬�w��t0�w���9~~~�����=���:�_�#G�ht�h֬�Z�2h!����B!�B!�B!�8����s��aΜ9������|����֭�?����1��S������r_0`����Z�
???~��u=���o:w�3���8��7o��KӦM���6C�W���U�]�dI�?�g���s���P�D	�t�u�4B!�B�7nУG���X�v-����MMMٴi�ڵc����G���������믿R�lY<<<2dժU��0��@�]�6�o��޽{�A)*W�LHH]�v�e˖l۶�V�Z�c�o7C;`8;;ӸqcLL�U!�o�<��222ʫ��B!�B��bbb^�`�>RSSi׮			�,Y���33�\�����1W=��h��ɋ}3


",,x�nϞ=s��B�n/_�Vccc�����ӧ��\�*oտ*�n,�hт��dv��M���5������ၟ���3XW�/{��occc����%c�Y�ߐ�U2�j��>���)[�g�B��ҩ��=
!�B���۷��}�R�lY���2�M��ښӧOS�h���+--�Y�f���qvvf�ĉ|�駴h�"��B�I5sEtt4�[���V�tiv�څ���[�f�Νt��)�|���q��a>��Q�D	Z�j��L�6m�]��\�B�F�NNN�v�B!�xC͞=����C!�y#G��M�6��(����>������IHH !!���`\\\r���&7���t���,Y¦M�P�^�zaooO�z��;4!�;(<<����J�Z�X�jǏ端��A������/::Zc��ӧO/FAT122BQ)^�8�{��W�\�2W�\!""�f͚��GEEi�upp ""�-[���驵�ڵk�f�+++�]�Ʈ]�����2bbb�b����J�o�
)__�ׯ_'..�5jd�ΐ�˖-��۷y��e˖����#u!�B����L�6���>}��|�r��3#�-����W�^��,:v�ȉ'ػwo>G'����eʔ!**J�Å�(lܸo�c���j��Ǐ?�h�0���4a�S#�	۬��
�F*��V1��mFR!L�
4L�D.&�\f
�0���U���;��qN騜�y�����ޯ��|�ާ�y]�P�R%ƌC�n�t�kN1��/��.BKll,~~~L�0�ڵkӭ[7�w�N���UvFB!JٟI!�%�СCDFFҧO]�"���;v`gg��0D)Wlemݺ�O>��_��m۶Ʉ
���_����3u�T���[��뇯�/2�B�����
�}����3f̠iӦ���0k�,z���S�F
n޼ɖ-[�߿?W�^eΜ9Z�׫W/�gƌ�nݚ3g�(��kȐ!=z���P�޽��N�
x��!G��~P(Э[7V�\������4i҄�����0V�^���9AAA���r��fΜ���mڴ����̜9S-�¶_���s�ά[��������ϛo��…ٰa��������u7mڔ��,222�&V(&��N_B�BDD��CBhI�nEYq��u�����������C�!��-Z��O�J��i�����ّ��.O�"�Z�RYD"11�I�&q��!����>}���B��6mJӦMqss#''���dbccٽ{7&L ;;��
*'_X[[S�n]]�-�B%0�b߾}8::w�B�WHnn��CB�d}��姟~�uB��ڱc��C(������.�UVV��F�L�2�}��q��!���/�~�m]�'�hŊ\�v���+ӆ�ڵkY�bnnn:�N�z�	�>���*iM�6U��mee��͛Y�`,P����������̙3�5J�nkk��Э[7���իY�~=�ׯW+�aÆ�7N���ٙ�{��������J�ʕ+3a���+�=Z�ަM.]��rnaۯM��5b����III�O>Q9�XQۺ;w�L\\��������U�f>��C�c�48p��CB�
:p�@__�}��)�w�=�>}���;��ܹsu�B�~-Z� %%����������?�}�]�
����u�x===ڷoO��������Ç$%%�{�nbccY�z5�=�E��	}�իW�u�B!^Sz���brss�!y�C�^Ro9B!�B��7n0m�4��������ɉ��(����~h���fѢE���KKK>��Sy��J>Ź�ϟ��͍.]�н{wfϞ����T�ѣG������Uy,66WWW����ر#�|�	���';;[y��h[�¶m���ɡw��ЫW/rrrضm�Zނb.l�k����?~̼y��ڵ+����U�oݺ���7]�t�[�n|��ܻw�Hע��[�6hC���l�<�ᆪK�.X[[3m�4nܸ���Ν;�[��ԩ�L�[�.���[��;w��B�"��`q��I��x{{ckk���>5k�dРA�����(;a����^�:���t�ԉ�S�j���>!!!���S�F
������Gc��������k�FOO}}}LMM3f�W��F�������������˗�Z�jXYY�r�J�]�	d���ԩS��+ҵkW~��G�8
�~m�/�Z�j�b�
z��IժU�X�"͛7g�ܹ*�gjS���-o��			j�%$$`hh����ֱ
�K:��/yȣh!J���\~��'>��#ڶm��Çe���/_BCCy���B�R�e˖�۷�-Zp��v����ɓ	W�/e���>]�ve���$$$p��Mv��A�^�������?�V�Zt��bbb�~SB!JR��p!�BQ�U�V�*�B�>\~-�{�������˗�i�O����[-�Çquu%--M�v��UBCCIMM%  ==�5F�ͭ[���شi999��/R�?�ȝ;w��,Y���SVV�֭���̘1#�k[nn.���+�~�)�t��u������ʕS��٘��wm͛7�͛7+�/[��z���l�����������o�}����_���"�=k�ܹDFF*cݱcǎ#,,�jժ�k�.���5�nީS':DTT���/��	!��=��WLLL�y�~�5kV����兗�W�e�9@�*U
U�Bǎ�رc���U�Z5&N��ĉ���r�ʌ;��c�����צ��ګ)�����Ӧ�*U������˹r�
����ʕ+;v�ѣG��o<�>!J�}���p�B]�!�(�
6�:!Tܾ}�#F�u�Vf͚�����{9��pqqaƌlܸQe7>!�O�j�
��~��Q�FQ�Brrr

e�ر�޽[�+�

�ݻ7�{��.Եg�bcc�����ߟʕ+cii����ܜ
d8�B��Qb;\!�Bhr��1�1B!�׎;���?uF���˗166&44�����BXXiii�lْ5k�p��A6l�@۶m9t��6l��͛ILLd�ȑ�ٳ�He6nܘ��D�D��k����Ebb"���'88@��s�A�G�Q>׶�Ç��bjjJ�&M055��Ԕ?��3�A��ƬM�k+55��kײ�~�s�̡|��lڴ���DF�@||��⾾����b�	M�g�Hl�R�;p�������̓��@�����W�)�!�����é[���.��������Ȅx1���DDD�:!������_Q�;vsss���Ott4S�L�A�:fdd�g�}�ܡU!�*sss�ܹ����r�����/&>>^���x5���[0��� Ξ=KFF���ԫW�ŋciiI�Z��۷/?��3������B�b%S��ə3g��}Æ
$%%OW'8p��M!�(u����O?���0��%��߮Ϧ9rD98��LJ֭[`ff���/�ƍS�
���?���ӉӧO��Ύ;v`gg�r���'
4��ё��Pn߾]�2������W>���'77�S�N�s�NΝ;��Ç�{�n�}�m������->��3���{�n݊���Z=�ƬM�k���K9����� <x���7
6`�С���(w�x����_���"�=���K�sE�֭����ݝ={����<��(�)�F���B!J#�O����:t(����…�\�������
�B�=k֬���E��b�
����ر#k׮�nݺ�I������ؐ��J˖-u�B�*�}�����/����O��8�WK�
1b#F��ԩS�޽���X���;���+�~�m����޽;��ּ��:�Z!DY&.���_M\\���:���	`������2h� LMMi۶�"B!�BQX�k�N%���L-off&�tR�&�ϟWK311Q�[q�?''�He*�+ܸq�	&p��)���[�G���ܹ��ݻ�������ٳ��w�bhhX`����.���o(���Z��W׷ ��꓃^$�gu��Q����˗�i7o��jժj�+�y�B�Ҫ}�����1�|��݋�3�B!DY������;�V���ӓ�3g*W�C���iҤ	AAA�:!�(3fϞ��͛���oe!��D���i޼9���<y���dbcc���eܸqdggӸqc�w�N�=�޽;�j��u�B!���\���4�߿��S�boo��������ח����8�B!�B��g�+�4��ى	�ʕ{n�gi�M�bŊ�^fޝ"�͛ǩS��_�>}�&&&�hѢP;/jS�o���Ç��~��7����9��5�Q޼���Q�R%��zzz���)�g��-./۳�L����_m��W���l�B��U�g�W����C!�B�Ν;���=�.]"22��?�X�!	
ʕ+��ѣ���cΜ9j�!�ЬV�Z̞=777F�I�V�t�x�ʗ/���9���L�2�p�����Prss133��Ɔ=zйs�|CB!@�.
3���[�b׮]c��ʴ!C��v�Z嶜B!��l�~�:�k��u���H�U�~}���9~�8|�2����jy������ 22R9ᾨ��̤�$BCC�Q�.\P��q�+jS��m�X�p!�:uR;��~ƍǶm��&\<K�~/W����ܻwO��savt�VI\��R�����윑�����v�Z�����֭[j�>ݺuK�G!�B��r���]��ڰa��Oǎ5�\!^W���`jj����_�>Ç��חu������p����/X�l������ɂA��J�*aee���~~~ܺu�ݻwMDD�g��7ޠk׮��ٓ=z�$!�j
^��t��
�M����5���899��՘Wvv6�-�o߾XZZ�駟��Zf�s�q��֭[���u��Q�[�.���[��;w�pk�BQ��9���7={��E�4k֌Ν;���Ξ={t�Kcbb���I�+K֭[GϞ=5Ӧme�O�������߿?�۷��Ԕ�-[bkk���G�-�z˲�^#���n=�����Ǐ9q��g�V�ۭ[7|||8}�4O�<�������WWW��/�28�Ç9}�4�����۷o��3Aff���;w�S�N���bii��~KKK6lHZZ�Ν+0Vm�]1�d˖-ܿ�.0gΜB��6J�j�s]�6k�,e_'''�������2�b`[FF������	!�BQT_�5����%''��ɓ�4i�-�رc/9B!�(�=zĄ	8p NNN�۷O&[�o������:!�(S���X�x1�������:Q�T�^��?����@Ν;�����Z�*3gΤu��1l�0V�^MVV��CBQ
�l�]�w�...\�|Y�v��i�����>|�WWW��ҔiW�^%44���T����ʮ]����ָ�g�N�8t�QQQ��߿��B!DI��￙<y2qqqjDz������߰�����-�_#>>>�������cӦM�����>�ϟ��[��޽{3o�<�x�
E[��.��W���#���/^��ٹ������ݻ������T�U�\�	&h]q�ieeŎ;�6mӦMS;~��i:u�D�5�y�&�����Ȉ���B׿u�V��
Q�ʕc��̝;�m۶��_��6�nee��͛Y�`,�=��J�j�s]�V�fM��~���4h��y�Ν���#55333�����|��/�!�B!�G�}9xz_b�ԩ���+w|�ׯ���DDD```�2�B�R+33�A����JXXX���D����J�.]8|�0�G!�sssF����'�~�)o����C�P�F����/���/�����'::���h\\\x��!�Z��G������G�o�B�z�&\���s��e����9s&͛7�ĉ���r��5��aaa���ѲeK���111!##:Ķm۰���ȑ#�]-�9�<?11��͛�šHKLL�	B!D)w��
���t�o��6#G���ʊw�y����s��%v��Ipp0{��eԨQ�^������:t!����qrr���T�T����ckkK��ͩ^�:��ٜ9s���h֬Y�Ν;y������]�B�=�Y���@||<w�ޥq��8991m�4�y


	

eٲe�ٳ�k׮Q�J���puu���:��(s���<~�����<yB�&Mprr�?� $$����өS'&M���ŋ���R��X��=z�Ν;�V��q��|��'�s�Nƍ�o>m�}„	������177g�ԩ��ݻ��\8%q}5���b������oIJJ�f͚��������e��$$$0l�0��044T�N"�%��ё-[��:!�(S4���*Y�b׮]c��ʴ!C��v�ZV�X�����B��!**
GGGj׮��Çi֬��CZ�ܹ3�Z�"((H&\!��fΜ�ƍ���o���u�(�������ooo�ݻG\\111DGG��O?���O�Ν����G��o߾����B�^ڄ�
�祗�
�={�OW�mݺ5fff����
�������ccc7n���ӱ��cǎ����[י3ghذ�ڱF���B!D����ɥK��СAAAT�VM�x�ƍqww��ƆA�q��A����"
QV���s��q�y��/_�6p�Z�jʛN`����O׮]u�ŧf͚j;C\�z���zK%�Z�jL�8��'Xf~�{5��̪U�����بQ����ٳ'={�Ժ��+[`l
������w������R�l���y~��}}5�yaDlիWW���*U������˹r�
����ʕ+;v�ѣGˊNB�5`�]� D�5`�4h��0�k$''�������z�*+V��Ą�>�L���l�/_Ntt4ׯ_筷ޢw��*��wɝ;wX�nԩSG��nݺ����n�:�JժU_B����y��	�}��f�b�0�j IDAT�!��e���+�'O�~�څB5k�d��ٌ=�#Fжm[]�$ʐ*U�ЧO���<��J���…�f͚t��lll�cC�B�Z^�.222h׮�J����Z���L�������X�͛74��U�)�!��\�r���@���q�o��&������k\�����e����<?q����$%%q������ӧ*>L\\5k�$00Pm�E^���xzz�������&\����d�������M�Z��ܹ3����p+ڕ��NJJ
s��%99�J�*aaa���;mڴQ;��ŋ,[����D�^�J�ʕiР=z���Yc��� �^���h��q�F�.]��A�j��ԩ���x���������J�O�7����[��
*�t����פIƏ������'\��߸�����Ϙ1c�p����,]��NTT�Ν�Ν;T�Z��m�2j�(:t�V���y_#/�ސ_��xu�ڕ��l����ٳ'���ddd0w�\@���(������پ};���xzzOw522���I��	!^u6l�uB!
)  �_~�E��ѣG�8q�'Np��=x��!������)�^�z���PRSS	(p��]�v���M�N�Ԏu�ԉC�%��!^Kׯ_��ё��x/^�����CE���Ĕ)S��_
�=V!���#G�l�2<<<HHH�\�r�I�QFFF6�aÆ���Kjj�r�W_}Evv6�={���ƆnݺQ�zu]�-����	Ϯ���-�sssU�k��l�gݽ{���25�V�ɇ7!�B��ÇqqqQ�����l۶�]�v����VeV�\Y��͛����ɓ'ʴK�.LBB�ׯWN�زe�Z-���4i�Dm�={�����S����_l޼��~���� :w�cǎ������ccc���g�ڵ*�NSRRprr�޽{ʴG�q��IN�<ɦM�شi����E��Y%q��i^K�.eΜ9���۷o'::�ŋcmm�U�R}�M�lܸ����q��&�C�4o޼Xۣ�k�(uM�2��'OOW��w�C�Q�+����ݻ���8BBB�zm��OS�����Ӈ�72g����5j��!���{�e``����?~<C�`۶m,\�P�3�B7��*Dф������0�kb���,Z�sss=zĎ;�3g�ׯWN�#--��-[��퍉�	���s��!�mۆ��G���bbb"��{����D�p!�x�$$$0d��ٷo��NA��V�˄!��R�r���‚U�V�����+�\�r�jՊV�Z1q�D<x@bb"111DEE�����/:v�H�
���B��x�޽�ׯOzz:Ǐ�>P�?~\-���DFFbdd�u]�j�"++�[�nQ�V-�c�n�R�B!�S���/���ܻw��#G���DݺuIKK#""������+����S���<M�	,Y�����0{�le��K�����ɓ'8880z�h�֭Krr2S�L!--���`&L����ݺu+T��~��~�:�ƍ���G�L�4�F�q��E�ϟOLLcǎe׮]Ԯ][��)S���G�����OJJ
^^^dff���˕ygΜɽ{�<x0�F��^�z<~���Ǐ3m�4Ο?�…�1cF�Ė׋^��Ѧ�y}����k�___��}233����a�ĉ�޽��5k:�g=��Eq�j%ק�������O
]~�*U4t(j{�y-���/�s�N��������8y�$M�4a֬Y�h�===��Ҙ9s&���*'\<�5RԿ?M1�����I�
عs'��>���������D�I��n�۷���M�Y���]�ΡBQ���d��/`��A�D�
�}6�$D{�7�{�.���\�p+++����W�
���?���4nܘ�ӧcggǎ;���˷�3g�аaC�c�]#y��u���˂�2e
����^��P�I��c��ф���q�i!��k׮���xzzbgg'�G�bW�R%��������ߟ7nKLL�V�bƌT�Z�nݺ)'`4m�T�a!�(��j…��
���̞=???�5kƩS�Tb*t�֍�+W��ョ�'M�4���%,,�իWcnnNPP�t�bnn.���4h���M����EFF��Ċ��e!�B<�v�Z���o��ݙ8q�2�]�v�k׎*U�JXX���g%''��O?��_ҷo_�5k����C>��c�����������ٱe�儋?�����{���/����MǎY�d�r��&M��d��JRR�W��خ>�@%�:0{�l9z�J���T���jժP�B:t�@@@�z�"&&F9ᢨ��U\ׯ(����Ą��0�j���J�֬Y���G��(
ŀ{m�T�j�7�I�&P��h�Z(j]�=

غu+?��-Z�P�m۶-?����֜>}��QԿ?M1�⧧������|ɤ�_�d'�G�+`���C!�s|��W|��w$%%���Ē%K9r$*;�eff�ܿ����s��M�V��vL���#������#F�믿2s�L<==e��W���|�AAA2�B!^�̙3ٰa>>>,^�X��W�[o�ŠA�4hgϞ%::���h|}};v,�5�G����bmm]�E#�B�,=]�29::ҨQ#.]����3;vdĈ\�tI-���3�5"%%''':t�\�r��ʁ�5j��_�~|��t������y)�>���bo�BQV�ٳ��C�j<������ow��᫯��ɓ't�ڕɓ'�OLL���I��V�Z���N\\�2���������<]uH1�ZAOO�ѣG�w�^��k�֭[p��]�tŮ\#G�d�֭\�zUy�I�&���+w,(���*�막6�����C�|Pm�"�Ҭ��T��Q유i���I���l�6���֕w7<���x���U&[(���;���gFQ��4�(�B!�B9rD���гgOv��ɴi�hӦ
��������ӇM�6)����XNA�~�@�g�W�M���B���c��HJJ"66�)S���+��ՕM�6q��u]�"�eΛo���Opp0��ɺG�fLMMqwwg˖-ܸq����Jjj*��N�:t�ؑiӦ��Ǐu�B�<t��EI�������������ݻ4n�'''�M�����2���!���,[��={�p��5�T�������*+]O�4�ŋ����Ç���e��$$$0l�0�8044�����4\!�(+�u�ر�|/^�����/_�aÆ,X����˫W�2U��


�}�6���+p�ya�UV�6mTb{VÆ
��@rrrT�������$99Yy���ȈN�:ѽ{w����X�b�ŖWq\?M�i^:tИ�h�b熗�0ui����T��100��ݻdgg��߀BQۣ�k��u)&/��ҥK�={��Ǐs��q��Ҁ��T����=/F!�B��͵k��ӧo��&111\�|;;;�ԩÎ;J��3gΨ�hlnn���tq��8hj�ž={ضm'O���ݻ4k�kkk>��"�ȏ���ڟ6l ))	x�}b�E�M��U�j��۷/}��%--���XV�Zŏ?�H������m322���|�﹵j�"++�[�n��6��-e!�x�-]��q��aiiɚ5k�[���C%l��L�8���P�L���p���6lK�.��͍����$E�*T�K�.t�҅3f��?��{�n���X�z5~~~T�Zkkklll���U�*����ل]�Y�&ӦMSIS����[o��W�V��'2q����ٳ'={�TI�R�
,_��+W�P�^=�\�±c�=zt�V�B!^5�[��y�֯_��۩R�
!!!T�^]-Ovv6P�+6lȉ'HOO�m۶�:�ɓ'*=��C���!����x�R�J�����T�Z���N�<	<���i�&6m�D�
��_�_�~�ĖWQ�_~�i^�Ȟ�h��P��T�j�7
6��ɓ�?�v��i<OӄMH��m^E���@c�������5������B!��J���bG2��-[�x�_�5qqqev��kovv6^^^*;+������Bhh(ӦM����%F[x����~�zrss4h����� ��?�}�W�\��ˋ>}�ФI�w鼋�t�֍�+W��ョ�'M�4���%,,�իWcnnNPP�t����\233iРM�6%++�������&�e]vv6���Z�
///������&�NHH�'OָӓB���+W���,,,X�|9...�IjԨA�����;w�]�v�7�|����5��������_!D�x�&\t��U��OϞ=144$##��s��;��E
>��۷���'������T�u	!�e�b%�cǎi��������\�r�����700�޽{�^���‚'N���P���vvvt�ޝ�x:	���ܹs�7�|S�۷o+c+�����'����ȑ#9r�?�����L���		)�؊r�JB~�XѦ�b���U[���`!�T�j�7�:u��ɓ�ڵ�ȟ�_�k�$�ڶm&L�N(�ݻ7��5j��ޣ{��Z����^W����:!��DEDD�:�R!�	��%)..����D����������S�cƌ�s��T�^�����͛7��/�0e��-[F�V�^r���>S�N���^��~�~��%""B>����Ç���Ϝ9s�3g��1333忝��ٻw/)))j��U�\Y�=�>�y�&�����Ȉ��H:w�L\\���*���?��w�B�Μ9���=W�^%22��?�X�!��l���,\����(z���p���i۶-nnnx{{����x��iҤ	M�4��ÃǏ��~bbbصk˖-�>�G����ҡC*Tx��!�KW��e���8r�}��a�ƍo�֨Q�Q�Fk�L�>����3t�P��@��R�r�b�K!�(�+�=z��>����=x����s��}&L�@�=
�#--��g�Ҿ}���'�Jxx8#G��J�*揊���ݻ*�4h@jj*)))t��U�cǎ)�'ccc����`���|��$%%�Hl/z�JJjj*���j����4o�\%]OO����߿��Jfff�Z���Sm�f��,[����p��:}�����k���̜9�!C���v���999�ZQLW�
��G�1p�@]�!�B���^rHH�r�9��E�X�h�+7顴ٷo			ԬY��+WR�N�1ccc<<<x�7$00�%K��0Zu+V��ڵk<X�6d�֮]ˊ+pss�atB�.����G�
ذa.\�~��|��>\���А��P�-[ƞ={�v�U�T���WWW�EU&M���ŋ�����Ç��ڲ`�6l�J			bcc�Z,�/ODD...�����ӰaC]�$t�y��t�ڕ��`�p!�/hƌlذ��S���p��W�
�ڵ+]�veƌܼy���X�����_���z��t��
[[[z���"�B!^�k�����''N�y��T�\===����ׯ���ԫW���l߾=nnn̟?������ʎB!P�^�x1O�<Q;�}�vLLL9r�J��ٳ9}�4������XGǎذa�ڱ�g�bbb�2�M�6t�҅�ׯ3v�X�߿�o�YYY,]�===�mG�����rNNNK�.�s���^]�v��Ąs�Ω��8c{��WR�:�������~��V�)))j��b�brͳ�WJ�O��Lvv6Ç������V�\����|��D]wK

U�����S9��k�e�7�������͕�<�!y��y�¹q�ӦM���KKK���������\mGvv6�-�o߾XZZ�駟����>4���;w���?���ӱcG>��~��G�޽��OQ�ѣG������U%����̛7��]�bmmMPP�n���ۛ.]�Э[7���[�ݻ�Rvll,���XYY)c�?>����722��C��L��kРA�3Fm�¶��fƌt�ޝN�:��뫌�Y��~��׭[����J�u����ܜu��q���u!�׷o_���ؿ?���g���xxx��DY�Z5&N�Hdd$d���̟?_mpHϞ=ٺu+d׮]���#8v�W�\Q�r�
ǎ���Ima
!�(�<x�رc8p Æ
c߾}2��5���ʯ����˗u�B�IիWg޼y�B�L�Y�&`�ҥ\�x�ӧO3s�L�<y��ɓiҤ	&&&�3�͛7s��-]�,���R��EI~��������C]�)�B�5NNN�^����ggg&M�D�f�HNN&22�M�6Q�|y&M��<'&&�իWӬY3�ϟ����&�������q�Fj׮���3U�T�رc|��w���_�Y�faggG\\�{��/����
ccc=zDff&qqq,[������cǪ����ȪU�HJJb̘1L�<��
��������100P�U�~�)AAAxxx0u�T��̨T����̞=@e����E�_Iڻw/�ƍc���4hЀ��t�Νˑ#G�_�>P�onnNLL���̛7�V�Z��_�z�j�����7��޽{�ڵ��={���CŊ��
%է��ԩS�p���?��Ύ>}�вeK�|�M<x@zz:���_�^9����f^�k�$�266&##�ٳg3n�8jԨ������2߿���2�#����|ox]-\��}���:!���4��U���|��Yhذ!�6m"55gggLMMY�f�2��{�pqqQ�t��i�����~��!������)Ӯ^�Jhh(���jg�º{�._|�r%xx:�͚5:t���P�A�?��#w��Q��0o�<6oެ|�l�2�իGDD��=���۷oGOO�o���%K��|�r�����X�n�o�fƌ����	��	�U�T�/�x�v߹s��#G������&��v�o׮]dggөS'�r:u�ġC����R�_ �(����	���x:���Hm��B�U����ٳlذA��x=��׏��dzl�2�O���p��Lrrrb�ҥ���s�b��#��ҴiS�6m���>$))�]�vMHHzzzXXX`kkKϞ=����B�R7lX!J=y�B!D���o�`����ٿ?���S�3c���}��E�Oȴj�*߲���hԨ3f��o�aɒ%,Y�D%_�v�+�*���;�Y��1c�p���|oZ�/_��c���W_��׭[��~�	bbb���Q9����O?�T,;m�3���Ο?����Վ����xyy�Hl/r�JҢE��e���*�k�&88�J�*��{xx���@FF�
R96k�,|||4�ӲeK<����2M�z+���Sm��R�J�Z�����b�
6n��ƍ�-�^�zL�4��}����hRu�5
����&�xxx�믿r��ERRR066V��5�2�^W$""B~�B��+hG��Ejj*���
���\�|cccfΜI���9q����\�vM%oXXiii�l�oooLLL����ߟC��m�6���8r�r����o׋����.\�@�z����y�椥�1u�TΟ?�ʕ+qssS9�q�Ƅ�������k׮�aÆ���/1g�LMMٴiu��eժU����<o�ڵxyy�駟R�\9N�8��ѣIHHPƬ����7�֟_�i��ի�r�
���g�̙���r��	�M��Vna�@bb"���	
����D�p!^9Eّ� /{eX�O���㕋l۶��R�r��B��-[�0b�6lȑ#GhҤ��C����>#G�dٲe����I!�x�ʕc��Ř���l�2F��됄(}}}�v�J׮]�5k������˗3}�t�W�N��ݱ��gȐ!�Y!���%�B�R��ʊ_����`������100�M�6|��t��E%ff��u0�F��d������>
4��>��/�T�`jj�Ν;ټy3�v�����ܼy����cllLǎ:t(M���j� IDAT6�Xg��݉��dɒ%�߿�����Z�jѹsg\]]y��n�&���lܸ���`����|�2�=�w��ƆѣGS�f��M��W����C�ƍ���"--
cccz����ѣ�Q��Z�V�Z�…9|�0��ٴh��u�y��1u�T�9ƒ�]�v���$�T۾�X�"�|�
#F�`ӦM$&&r��9nݺE���122�m۶���ңGʗ/��ړ��k��T�T���PΟ?���>mڴaĈt�֍F�1i�$֬YC�^����yY�
�3�w�B!^k֬���Q�a�b�E�-4>Wسg>>>�n�333|}}7n�J���h����j7n���ӱ��cǎ���ASlmڴ���v�ޭ6����I�wX///�@<���x�����4l���C�­[�����Ǔ��˩S�عs'�Ν����ӝ(
R�|y�<yBNNN��{�޽x{{+�����|�
�ǏW)W��w��e��ըQ#�<B�ҩ}�����1�|���133�qTBQ4�=bʔ),X���Ç�x�b�τ5j���#22��?�\��!D�ԪU+Ǝ���7����V�Z�I�bS�V-
�\t����DEE�k�.���/.�B2�B!��ʻ�˜9s
�799��갰����B�s�<x0�~�:�{�=~��B��.	��Z�*�&MbҤI:�M��WPY/���5kƖ-[
K�-֪�w�y�+V�p���[\}���}�P�n]���qww�\��n����?�<���;V�k���A!��u�������c޼y��~~~���OW\�����n���A��	���ܦp���B�Y��ޯ\�<�l��"�?��S��d�g�] �<�
�λq�&L�ԩSj�rss��ԩ��˗�z�*�7֘'77�{��ahh�LӦݗ/_PN�x6o^�\��7oO�O?K���#ī�e�DQ�ppp�uBQ,�\���9z�(���8;;�:$QJ������$.���O�κu��o		�u8B��f͚ѬY3��g�B<_�M�8p`I-�(�"""t�B!�B!�x�=;y�\�r�����P\
�1B���*UҘ���W`]����ԩSԯ_��>�Z�hQ�{��[������߿?�	'O�dĈ�hт�˗�3hn��<{m*TP��C�맸���G���5"�BQ���prr�V�Z<x��-[�:$Qʹ���矓���2�Z!D�U�V����3t�P\\\��t�B!J�b�pѠAP��
!^�� �B!D�u����_�ѣGٺu+ǎ�����bdd���%���C�e�b�uM+��dze�RSS�}�6U�V�U�V��׏.]���g�iA����Q�8��
6l ))	��;��!B�QG���ѣ�5��-[�r�J8�رc133S[��~�����s��q�Ώ?�V���DFFbddT�m166��ŋ;v�:(ӏ;����)�CCC�Q�.\P�����
�{�fǎ���ӧOj֬�r<''��� rss��㏕�-�iw����p�G��S�N����T�x��~�j�"++�[�nQ�V-�c�n�R�B!�(IO�<��c֬Y2��� �����O�>}�W�!!!̝;W��!D�5d��.]���;III.!�B��O�O��ҥK�
B!�B!����_W�A�?f֬YDFF����$33��[�2{�l>��â�[�=x�iӦ����?�O||<666|��w��^�<�qM_U����~�zrss4h����m�Vס	!^�b��b��g��eccCzz:�g���Ϗf͚q��)fϞ���[�n�\�<==iҤ	���/aaa�^�sss��������撙�I�
^�VVV�\����x���IKKS�2��<p�=z��…̘1C�~��mj֬���������q��Q�������Ғʕ+s��Y���IJJ�s����ۿP�{��E`` ���̘1�֭[s��f͚��m�_ӦM���"##CmbEFF�2�B!DI�������d�F���DR�B\\\X�h~~~/|/I!^w�ʕ#  �v��˜1ct�B!J�b�p�f���X!�+$77W�!!�B!򈋋+r���'22�J�*��䄍�
���'''�S�NF||<>>>l޼���z�"/�f͚Ell,������`mm��o�ͭ[�HJJ"((���h*V��2�U���L�����3u�T���+����___"""000�q�Bmi3���ё�~���/���\`�����ݻ������T�U�\�	&(�רQ��7oү_?���4N>|��Ç�{�n2339r�ʱ
���+++v���iӘ6m���ӧOөS�|�;g�ƌCzz:���j�w��
???ʕ+�LӦ�NNN���r���A����ʉ
�\�Ν;Gjj*fff*y���}��(��M	!�({��ك��U�V���x!...����q�Ft�B�Y-Z�`ܸq���booO�ڵu�rttd͚5�C!J����"W*�	
6l(���eԚ5kزe���B�
KOO�u�������2��Ξ=˦M����'88Xm���c���jL�Ǐ������hL�C�eg�3C"�lI��!�0�)�X�GL҆J2�g��D��}�1�GR�D�?|�t:�T�$���q�\�u_����4g���ef���ӦMc���l޼��c�j)Z�:s�������G�ڵ��*U�D�>}hӦ
C�!<<��ҴiS�\�������,���aÆ
���������=���ŋ*ϳ*S����xzzr���>}���	vvv̚5Ke&X��������<x�r��aff���u��Q֝2e
+W�$11������|���z�j:ģG��\�2ݺuc̘1���:u*=z�/^P�n]���u����lܸ��[�R%֭[Ghh(ܺuڴiÀhժ��[__oooV�X����III�S�N����g��v�s�z���/���ѣG>|�J;G�����ݻ�i�дo�^~�B���˗/qwwgΜ9��ۗ���w�OO5jԠ_�~xyyI…B��ٳg�?�����������

�vBQd
4�P�yk	���o�i!�{���p!�B!�+>d���DFF���3LMM>|�r�欉�������o�>���o�T�B�޽qppP��H�		a�ҥ�;w�R�J��_��wߩ̰��6����2e
�����������i�&���HKK�J�*t��gggʖ-��7k;�~��7o&33�\ƎK�R�hذa�bONN��ۛ���#�T�B׮]qtt�� Ǹs*W<���b���۷}}}ڷoτ	�V��k�=z�ʕ+9|�0Ϟ=�k׮g�޶mÇWI�ȪR�J��ٱ|�r�l٢L��k�9]SM�)��8/�mA��\g��k���LHH-[��Z�j���իcnnNHHÆ
�|��o�!Ļ��<"""��*UR[�!!!@����L�<�ɓ'��f�=�ѣ�Zy~:?��#\\\pqqɵ^N�iy�������X7�9��T�R6�aÆiܮI^�
P�\9�O�����U�5�1�ׯ\�r������K||<5k� >>�3g�0v�Xʖ-���cll��0�B��G����������|��w�b�xcNNNt�ޝ�/Ҹqcm�#��-/^���-�i�F�!	�+kkk�+��[K�B!�B!�g)))888p��=eY\\��A����899q��%eYBB~~~\�pOOOtuuU�;v,III����y�f^�|���[��\�t)������+���*u			�ɓ'̝;7���A�={�̱=���=��O�2z�hn޼�{pp0111���x��…ٱc��܇��s����I�����������ᅮ���v�g�бc�\cl߾=˗/�����?/
r�_w�DA���rN���Cjj*j�[XX�޽{0`@��"�(�:v�Hjj*ӧO�G�p��.\@��͵�Ж#F�k�.�����AAAagg���BQ�?~���p���)
M�nݨ[�.^^^�X�B��!�{mȐ!�Y��q��K�%��B!�,�_��sss�Y��ʕ+9n

Uξ%KB!�B!ĻĽ{��Q�~~~DGG���23�B`` �.]�I�&s��	BCCi֬111l߾]m�O>����0��������oԦ��	QQQʤ�
60}�t���8v��W���ѣ��б����9�bf�Vlȋ챯[���7oR�fM����F�\�~����+22��˗���5j���*���ׯ'>>�Z�j�v�Z�r��5�c����������N�4�����ݷ
��`4=�+Ƚ��s�V�TVXQP�)�!��>}��`��v�J�V����&66��+��� >,eʔa���l߾���ؾ};�gϦt���O:::�<��c�С��"ށ��L�-[Fǎ���8u�$[�B����رc	�8	�B��Y�r%/^T��-�`�СZ�|#y�CE�\�ce�-����9|���A�O���ӓ�7������W�͚5�B�B!D�۾};�C!�(�$��山��A�nnn4m�333f̘��	T��۷jԨ�J �={6������cii���������/@���x����igg�����#G��������޽�k׮q��I�������_�|	��a7���y����c�t�?��s\]]��o8p���ι�!'ӧOW�rдiS���?~<T����:tWWW7n��W~��&N��r���tJ��+���L���7��(�9~�}[�׳��9QL|��'���_����r�C�S�
۽{7�n�"==����?�m��I���ѢE���Y�x1�Ǐ���L�Q	�?�۷�	���=���cF��Ν;�駟pqq��ojĈ̘1���F���p��֠A&O�̌34hU�V�vHB䉞�AAA�C!�fРAo��*�"������˟={�̙38p�r�K+++f̘��M�(S�̻S!�(t͚5�d!�x����,
�Ν;4o�\�\���w�зo_�m]�~]����T�oCCC��m�v�&>|ȤI��|��Z]M�����U�������?111ɵݜd�=>>x����zܿ�@��f�TLpp��=eY~���O���=֬�U���9[���������%��(�9~�}���w0ٓp
r�g��s��?�P�|y��e�:B��IWW[[[lmm��(��E���q���BM���4���t8@���(ƪT������!�(3f� ((��S��Ѫ�B�K���X[[k;!�(v��p��q�(%A���<x�!C�(�lllذa�����S!�(*F���#��B�T�Ϡy�l�=1A���K^д����^���u��E�q��ejժE�N�055�q��y��!?�oѢ���'""GGG�z9���ŞM��233��R���&�W�P������Vn��?��(4�bѼysؿ?�F�ʱ����+�$�7��9~�}[�׳��9Qī�<)�d�Q!�B!����ӓ)S�ЩS'efl�N899Ѿ}{bccs�N!D��t�R����۷�vHB!�Вj���i^�|���7{��%!!===LMM�ׯ�����Z 55___������M�*U�ݻ7�#Y?�f�)99���Z�l�2�e���177'$$�aÆi��Q!�x_L�4��۷k;!�(��-[��l�"ojժō78{�,�Z�R��={V����w��aǎ��
�Ta�y��q����X�"7o�Tn���И���[YY�c�֭[G�v�hܸ��z�X�U�5�}�6gΜ�u����3g�(�S���!33�����WE8w��g�ӧO�駟*���Z�jq��MN�:������…ju@xx8���t�Ё:u�չz�*�֭P��!���E~���T�z^�I�ʕILL$))�ʕ+�쟔���#�B!�B��'O�����͛qss���D��K| ڵk�g�}Ư��������B�����5>>>|��<y2��T���JLL�z��E�=���������S9����?���ϓ���СC�U/=='''.]���������.\���3��&���Cjj���bbbػw/x�!��T�dI�-[��0�����o�B�н{wnܸ����7o
4����̟?_�n�.]���
�֭��Ǐ	d��������啯�f����|��ܼy��s�*˟<yB�J��	w�����8����8p ���cƌaȐ!���S9�=>>���X�m��m�Ν;�����ͣQ�F\�tIy�;t蠬[�bE����n�ʀHHH`��9�����ϟ�����={��ՋU�V���ܹsiڴ)W�\���]�؟�9_~�%�v���GGG�u�F�ʕy��!�Y��gϞѫW/�5kV��5]�79�oSa��y9'���'11�;w�%VܹsGYG!�B!�(�.0`�����{�nz������ɉ�S��d�*T���p�⽷|�r>��sV�Zń	���Vdd$k׮%22�;w�����U�F�֭5j_~���C|'���g"�׉����LJ#G�p��m��өP�
4�w�ތ3Fe�x�5k��������B����+��q~��˗���\�~���ʗ/O�z��޽;Ԯ]�Џ��5)��J[>脋��0V�X���9ϟ?'<<��q�Fe"E^�r��%�4i���+���ܹsbbbؾ};���*K7*V�����aÆj�*ʢ��$�B!�{�O�>���G�a!D�%	�c�С����ܾ}��#G�Zw�ȑ:t�s��agg���t��L�4)��/�6;w�Lxx8�f�b֬Yj���ⰰ�P&,XYYaddĎ;�}��S�R�dI6n�Ⱥu�T&.ȪV�ZL�>����1�p��]���U���u�ܙ��0~��~����(T�TI�6jԈ��+��vvv�߿�+W����,�ٳ�r Vnnn���DDD�t�R�.]�V�K�.̜9���k������M�q��圴k׎Çs�����T�*V#yWI&B��ٴizzz�C!�B�?~<-Z��ԬYS�!����ӦMcݺu20X!
A����4i�f�bРA2����9�ݻw�m�w����c�����Ӈ
6`hh��(�_�D���=zDTTQQQ,Z�???���Y�,��^q��������/_�T���cbbb���a�…|��wxxx��$rM��%\(^W�5�m+[�,O�>%((��7oҹsg��To߾}xxxP�F
LLL�={6������cii�c<W�\�O>Qۦ�LR�B!�B��r�Z�L�������ȑ#<}����5k���ʺ��������y���ʕ���'''�ԩ���
�ͩS�����ѣGy��u����Ύ[�n����ƍ���`ʔ)�\����D���t�%J0e����˖-[�����<��*U�ШQ#z��A�n�(Q��kc/_�<����^��C����#*W�L�n�3f�ʗ��&MBWW�}�����3��͙9s&�{���ҥK���9~�8�*U�W�^888��������͊+ؿ?)))t��	777��٣v|}}},X��#Gزe�ϟ�ɓ'|��G|��gXZZұc��M^��tM���M�q�����ٓ_~���G�2|�p���=���ݻw/�	!
�֭[ٺu���B!�BEjj*�Ǐg�ڵ�����O?Q��=���2CCClmmY�z�$\!D!�9s&�������8�"����/,,,�y�&5j�`�����ݛO?��%Jp��-6m�ĢE��o߾DDD��<Z�f
�/�L�2L�6
+++LLL(]�4�?�̙3�\��-[�`ccñc�r�-
_ZZ�z��������agg���-f�S�� IDATffT�X�'O�p��)���X�~=�/��ٳ�ڵ�LN%+[���|�3�СC�'6�s����f�E�U%���˜9s����W�&���ckkK�ҥ���^�v�u4144�chӦ
;vLe@@zz:���]�s �6���x0`,[�@9C��ȿ۷o��e���ؿ��;�Ν�iӦ����F&����Ԕe˖ѷo_�s__�w6[�6(V

��0%$$��_S�F
�o�^�틷G�g���ې�s��兯�/[�nU�4���%cǎ����*��R\�o���!(([[[m�"D�#�/!������ammMBBk׮��/��vHBp��)Z�h��Çs��C!Dޅ��1p�@>,�%�"�]�>����ӇݻwөS'�n�J�
4ֻp�:t���ǬX��o���G������3ؽQ�F\�|�m۶)�h�����ի�ׯ�ʤG���h�}�AaܸqxyyajjʦM�h޼y�u����������4iK�.-���(,ٿ�.����Y�W���� �=zЦM:Ķm�8{�,�V�"00����+���k���pO�>�u������Uۦ(S�B!ćiѢE���Z��}��e�����N�2�ڵkӠA�w�B��;��������ѣܹs�����h1b�v�"((��FFF���i9:!Dn
���x�M�0����k;!��X	

��ɉ&M�p��)�����Jfff�j�
///I�B�BbeeEϞ=qvv����2þx/ݹswww~��w���/*U�D׮]qss�Q�Fj��2^5�����X.\ȡC�HJJ�V�ZX[[3c����=��ݻ�Z�*aaa9&[4i҄���Ě5k�.���?>����T�Z��ݻ���Fݺus�Wff&'O�dڴiDGGS�ti:t�3hժ��~׮]cɒ%DDD��R�LLMM�۷/'N�؇�Ɩ��^�k׮�V�ύ��+�W��СC*�G!�s�NKK��_e˖-\�x���$*T�@�֭�:u*�;wָN�n�N�rM6n�ȼy�z�*����ѣӧO�x]����1߾}+++����ڵ+;v�����x{{c``��}����Os��E��ڵ�V�Z�|�r���LLL4�~��g�]�F�
�ڵ+3gΤI�&j�5=�5)ʯ��I}d���А�}����˺u�1bO�<Q��K=###v��All��#&&&�X*W�@RR��6E���B!>L�LV���iii�X��=zP�jU�U��_|����IKK{�Q
!D��ӧ,�k׮�j�
kkkbcc�X�"���Z�P�_eʔa���l߾���ؾ};�g�VY�TQ�lڴ�M�6i;!�K�6m��ݻ�C!�(6���;v,vvv�=�#G�H��(����ؼy3����CB�bc���\�v�U�Vi;!���ѣ4mڔ5k������Nbb"����hт���|�Y�L��k׮�M�6���o<|���ϟs��M.\HǎIIIQ�
^�g�T��k�5r�H�=�ɓ'U�w�څ���֭��<�����v�Z�7oNDDD�m�8q��;r��A���x��1;v�C�DGG��=y�$-Z�`���ܸq���t���8u��gϦy���_�[v�~��)k׮͵mccc233y��q�bINN�]�vL�<��G���?����=zDxx8]�ve�Νy�[A�(xyy1d�.^����Ϲw�~~~|����ݻ�P�kooϩS�HMM�\�r������K���^�l�ЬY3���y�����������s��e222x��!�������5)ʯ���N��ׯ���L�>�>}�P�n]���O����]�K�.��憋�u�������~�z������^e�dffr��]����듘�ȝ;w�+�ܹ��#�B|��jc%�?[�n��QL�W�����ٺu+C��btBQp...�{�nnݺEzz:���h۶-T�VM�!
!
�E�8;;�x�bƏ������B�Ea,�,ćHV�B!
��ױ����͛���bmm�퐄�ѐ!C�<y2~~~L�6M��!D�P�n]&M�ď?����
U�V�vHB��?����INNfҤI8;;���s��|}}�����֖˗/+'ͫ
̟?WWW|||��n�b�ر�x�'''�M�F͚59~�8����>}��2w�\"##���/�ԇR�J����Ȑ!Cx�������ݝ�u�r��5���ضm�
�ҥKT�^]�M{{{z����O���9y�$�G��ƍ���O�ڵKYwҤI$''3f�\\\��O����ĉ�?�K�.1g�eB֛ƖUA�߷�~ˤI�;v,�6m��ʊN�:ѠAtus���u+,X��S�NѸqcV�^�������9s�I�&���;_}�U��+��^��v�ڕ���&M�p��
���زe666���)��緿�]�v����cllLrr2�r5KK�|�y��^�������ն���ҦM~���5kƍ7��ؾ};vvv\�v��U����ۻ�A�p1b��Ջ�cǎ�m�777���Zo�ȑԮ]�s��aggG�֭�ٳ'�ׯ�t��L�4IY�bŊ���ƾ��kڵk���bU�u�Сp:/�B�=z���'�G���Ɔ)S�p���z)))0n�8lllpvvf�ڵ�����4h�
��ݻ̛7�aÆaooϚ5kTVx��%7nd�ĉ���2|�pf̘����U���n�_�t	{{{�̙�VGSL��wN�NII!<<�&M���8P�J7nLxx��B�>�����֖���ILL;v���U�-�S�(�W�{�oCAω��-K�,aɒ%��ؼ�ȄB!�B7[�n�e˖��ϣ�l!��2e�0b����y���B�b��͍r��I2�x��^������ҥK�S��K��M�6�Y���'����ʕ+sm���̚5��S��L����ſ�������_�]�6zzzt�Ё
6�~�ze}�$�
6,p�V�X�ӧO�ҥaaa4n�}}}7nLXX]�t��/�����ر#aaa�k׎�e�ҩS'֬Y��c�T���,Z��:uꠧ�G�2e�ܹ�r2�m۶ZlY�M�8��S����KDD���4nܘ�>��Ν;���ʁx��E�O:�&GX�n�ڵ�L�2�*U�֭[�n�:Ν;��6"��$��͛�g������קaÆl޼�nݺ��?��z�je�7��3hҤ	���ԬYx��ШQ�|����?��ի�7hЀкukJ�*E�F�زe]�t!))I�h@A��ۻ�����0H��ʊY�fѠA������Ԕ�#G**槞���2S��Ȉ%J`hhH�Ν	PY�bʔ)ԬY�%J���@Ϟ=)[�,G�U���ѣн{��xF�B�[RR���9r���d^�x�ݻw���Tf���2s�L���y��/^���Ç�ڵ�Y�f�$R(̞=���������S��ۧ|�
��͛IHH ##���4�^���ի��ڵkIIIQ[)����ITTiii4k�Lm[�f�HKKS{S,�B!�B!�B�/�?��ɓ���bРADGGS�n]m�%D��;�[�n�w�^m�"�ņ��K�,!  ��Ǐk;!�D1s�7�|�q���@��������!##��={2�|��8;;��knnNff&�n�R�={�x��*�}����⢶b����21j����?~�ZY�V�x��Jy�Z��ӧAAA����m�7&33����B�-��^?-ZĹs�2e
M�4AGG��O�r��a�ϟO�nݨ_����hsr��m2335� �駟���oS~�IVnnn�,YR�LGG��S������ԩ�Z��裏r�OCCC�J�͜9�2eʨ�e�߲�+�����](��*Ň���}�ҷo����z���L�<�ɓ'�Z�G����C��\�r������K||�2�)>>�3g�0v�Xʖ-���BQ0۶m��/���L�0��+�n�:"""�s��l߾�{��Q�Z5&L����	7n�`Ŋܽ{��[�2d���kԨ����\�2aaa���q��	��}�tuu�I�&dddp��|||����ꫯ

U�,���ͪV�Z���O���z�s:��ӧ011Qk���TYG�F�B!�"��\��2�OV�����۴i�q�C!�B�f�޽���p��ׯg�С�I�|iذ!;vd������K��!D�1x�`V�^ͷ�~ˉ'��
Q�\�t	##�\�)f����ё۷oS�N6l�@�%T�_�~����chh��ǏINN�����*mg�(WĖ]�:u��ʕ+��B���+�F�"::���h��8�nݺ��_��W_���_h�e��ׯq��������<~����bbb����ȑ#ܸq��={I�-^OV7o���ŋ���p��	Μ9@fff��)��^��,,,4�+V5�|�����"y ��e�����|��?rNTҔ���W\\\���]Q~��T��`Ĉ�ڵ��� \\\�W��agg���B��'��!��5%�S�N0j�(�GGGeR�BLL�jV�z��P�~}ƌ���;'N�PK�=z��ͯ�����0RRR��K�.Mjj*�v��޽{�j�Jc�fn���|'[@���b��5j�mS�e��@!�B!D�|���>|X�DB�O���ӓ�7������W�����B!D��ڵ�#F`dd�ɓ'iР��C�@���6l�����?�v8BQl,_���͛��秜]^��*������Chh(�˗g۶mT�XQ��ӧO���XQ�Nbcc����u��y�'##CeU�,�9
X/_�<����J�.����9��>���~�I9���?�$  ���LMMٻw�r��7�-�7�~YU�PAe<Rrr2�'O��LJ�3g��cmܸWWWn޼���oC~�IV��"r*OMMU)��j�h�^�z�:u�K�.Ѷm�<�u��9�W]�R���rE��ӂ(ʯ�w��%\�����v5�(U�)S�ٳg3q�D�
��E{���لB�<���[N���/�YF6l��NVY��5e�>�U�Vq��YΞ=�ƍ�߿?_~�%�J��S��ձ�+���$))	�_��R�)�!ĻLpp���B!�(�Çk,��3g�d�ʤy+++f̘��M�ԖB!�������3X�h#F�`�ʕ�񾰲�b�ĉ���0{�lm�#��F�&Mpvv�~���T�\Y�!	��r�����?~���$._��ĉ���!00�F��x���d�>}��ct�Ё��X��ٓ����W�ҲeK���k�W�?~LRR�*UR�G���1-ѿ����ݻwٿ?���DFFr��Unܸ�w�}���=��\?RRR���?sM�-_�<������������5h�kkkj׮M�*Uhذ�r�ڂ���DGGG�,---���&Y�t�*�K�
�eo��ݻw�ԩS����+�bӦMt��M��+�����](r	Z�h���3�/`��񘙙i9*!���ʾr�be����Ev�߰�W��Ͳʚa��84mڔ�'Or��\�BHH;w���Ɔ�ݻ���9�n�������ն�I��jZ"UQ���U!
b„	XZZj;!�B�c�	}ޗ	x
��ߟ���hccÆ
����Y��	!�B����㱱���ɓ�Y��ѣGk;$!ޘ��>������0c��߬�B��y���̙3Y�j���"Gu���ԩS;v�޽{�y���4�Bjj*s�Υo߾9�555�̙3\�p�v�ڽ��!C��l�2~��W&M���?'[�l�ɓ'*cPLMM��?����W�^j��8qBY�03j�(F��Ν;���9t��[�� ����?�رclٲ�o��6׺�������pww��ˋ�cǪlKHHP���˗�i����˗/IMMU��ƍ�k��ٳg�ر�Z��cǀWIu
o��,^�///F��r���9s???tuu����X�?��k׮j�Ǐ^�U�_o�Bޮ�;�V�[[[�,Y’%K����v8B!�A1��ݻws�W�Z5���T�ϫV�Z��ХK�͛����ׯO�>e�ڵjO�!�ٳg�2M}�k�5Qd>+���JQ�&��B!�B�>x��!�f͢k׮�m�;;;��݋���ڪΩ���X���}�Ҷm[���kV�ZEzz��N�}�����LHH-[�T~6�^�:��愄�h�|&�B!^�4oޜ��D���%�B+���$$$�c�m�"�Ŋ��!,��ۛ3g�h;!r����qP}hh(:::���G�|ʔ)�;wN��nn�t�����ڶ.���C�ڵ�e�Z��{��$&&2x�`RSSsl�޽{,^�]]]�L��,�ٳ'�-R�$��˗�I�sZ
 ?j׮���/^T�faa�VV���9�9s�p�ܹ\۟?>�۷W)W�;�����6l�Z[K�.U�;�x����X�"111j���4Ɲ�k���ŋ���T)���P����E�on�ԩ�7�|CZZ�z�z�8������Czz:�ƍ�qU�%K����x�0`��m�]�����]��u!�B��Ӽysv�ލ��?�}��˗'((�����ի�|�rZ�lI||<���L�0SSSnܸ����j�����ox��t�ؑO>����D@}u���L022ʵMCCC���ؿ?ݻw��Ç��oMǮ]�6>��j����W�B�wm���k;!���ÀxwRRRppp�޽{ʲ��8\]]�ꦧ����ĥK��e			���q��<==s�kϞ=���j�A��‚����ݫ���B!���˗/qwwgΜ9XYY��メ�����P}�����///����p��X>|8^^^L�0�Ç�̾/DQ����ʕ+����W�^xxxдiS���			!  ��%K����g���\���M��nݺ����ƍcժU���S�zu&N�H���9~�8&L������M˖-ٽ{7M�4�￧w���snܸ��ݻY�d�rқ�3�7�+Vp��A������N�:\�~WWW:Dٲe��o���ذ`�������aaaA�R����S&�d���0c+�5j;v�V�Z1f�LӦM)W����'O���LJ-[�P�dI�̙�r\���	��Ғ�/_������1ׯ_gʔ)���T�R���8.\���?z�He���ڃW�۶m�����͉��g�ʕ��믅rM����d�С���|��\�x��S�r��q���U����Y�h/^$""��СCi޼9}��?�ԩSDFF�;w֘T����3g&&&���1m�4"##���O�V���dW�_o�$\!�B������իWqvvV�6p�@���lj'HHHP��722*�Ֆ��x{{��㣖ѨQ#�I'N�jժ�\�2�6[�lIDD�ׯW��o֬�Z���[ӱ��̈����*q�2���"����֖�� m�!�B�U���:T�a|Ђ���w�5j�য়~�aÆ�?�3f�������\�t�&M���ꊩ�)w���Ã���oߎ��%����U-��l@Æ
��P�EEEI…B!D�������q��a~��B"DQ���D����q�����G!�
<==iݺ5�֭cĈ�I55k�$88����~Z�n�VgժU*cJ�Ν��s�000ȱm�d@u��eժU8880�|�J
m۶e���*e�k�V޾v�Z���K�(��Y��>��c������f۶ml۶Me{�R�

�O>�1����ضm�/_�G�j�k֬��?��Vb+�+Y�$;w�dȐ!�ݻOOO<==5�ohh���/m۶U)oѢ����ZY������������j�3g�$$$�k׮q��I���_���3سgׯ_�C�*mz{{���w~�IV+V���Ύ
6��W�Z�-[�P�|yeYA��:����ڵ�iӦ�b�
�X�D�L�8��R�T��

e�ر�����W�^�m۶Q�ti��ܮIvE���.�<U�B!�������{�*T��O?�����ʕ�dɒ���0y�d:v쨬W�\9����ճu�� IDAT��*UBWW�J�*ѧO���s����/���q���駟�������j���Ғ���+�5�jժ�������sms���������h֬NNNc�k׎ҥK������P�lY�-�&�B!�(����U�+<���M�6EOO333�}�}�����A�z�(Q�&&&̞=x5�Tn�\����ꂊ:B!�"wG��y��\�v���HI��^�>}�Y�&����E!��-Z�������y�䉶�B�>}�p�����U�zzz|��Gt�ޝ�{�2n�8��7n��1���9|�0�{��B�
���ӠA�͛���{4i҄������M�^�022BOO�ҥKS�^=Ǝ��ӧՒ-���kN�:���FFF�,Y###���ӧ����w?4144$::�~��F�Q�LJ�,I�:u����9}�����[~�@Ŋٳg���;Æ
�~���-[]]]

iݺ5s����ի*�*���ӫW/�X��?��1cưv�Z�5kF�R�044�/�`�Ν̝;��3g��啧���w�QQQ��ۗ�+���O�֭ٹs'cƌ)�k�0t�PBCCiԨzzz|��nj7��g�bff�R����}}}�-[F\\ӧO���CCCJ�(A�
hݺ53f��ڵk���/�&[X[[s��!��͕㿦N���������vM4)ʯ��M'�
ךW̠�hF�]�B}���lݺU����Bq ##�e˖0i�$�s�۸q#aaa�X��jժ�����[
$3�
����,[���}�*�����-Y�(f�V�h���BQ\���}���AAA���j|���d���D6���9v��R�iii�o�^��ڵ���ͱ-CCC8�q��6mڐ���v,���t,,,���#::�p:'������B�Eff&�/��Օ�={H�
����ܹsY�b���j�)�B��G�Q�~}F���ŋ�����B ��)>$o���&�
z[M!�B�"�_�~9r��;w*s�ܹ��U���W_i9:!�yu���ׯ�Fmܿ���@�?Nbb�r6�N�:1d�

)ڢEӀ�


������B�M�����7��������#�:�=}�4��6uu��V�i:�B!�x���nj5��;w��O?���"�����y����o�I�B�ʕ+3o�<&N����=�5�vHB!�($��pakk+ʄB�ּ����:W��.]����3�|���k<�?��ڥ�B
��=�~���W�^e̘1���(���ӹr�
W�\aǎ���*WC�s��i<==ٸq#���<�z��ѬY3m�&�"jժō78{�,�Z�R��={V����w��aǎ�X�+W&11���$*W���-))IYG!�B����eРA���s�:t�퐄x�jԨA߾}���=B�8::����7�|�\�T!��BO����d���ݬ��A�BQ�4jԈ!C����������!��Ç�qK�,!%%�֭[3q�DLLL�������,Y����8<==�;wn!D\��I�ʳgϘ9s&T����bƌlڴ�2e�V�B!ޒ�ݻs��
�ϟϼy�hР�/_f���ju�t�B@@nnn���P�n]?~L`` �ׯ���///��J���ܽ{ccc�ׯObb"w��QK��s玲�B!�P���ɔ)S�ԩ���T�ZU�!	�5NNN��у�/Ҹqcm�#��J�%X�r%lڴ	kkkm�$�B�BP�	w�ޕ7B�6mڤ��ŀ$m]_~�%_~����B�|177�l��x�ܹs���S�BJ�,I�������ʊ��Hm�X$�������,���aÆ
��������B��СC���߹}�6#G�̵�ȑ#9t��Ν���Ne[�ҥ�4i��yŊ�������Ȉ;vЮ];>̅033S�…2S�B!DO�<����͛73k�,fΜ���n��:}�4͛7/��NGG���L�� ��/���:u����Ŋ+��B;mڴa���L�2�/����e�j;$!�B��BO�P���B�삃�:t���B!�"�>|���ˉ���ٳg���2|�p\]]�D���T|}}ٷo��7U�T�w��888������H�		a�ҥ�;w�R�J��_��wߩ�h��6����2e
���SΎ��~6m�D\\iiiT�R�Ν;���Lٲe��fmGѯ��R�J���_<|�P�p�`ll�l399������+�2���ݻXYYQ�fM�mۖ�s������7�ѣGT�R��]���舁��Z���X�`���C__����3a��T������K���ٻw/			���ajjJ�~�������u���dBBBhٲ%ժUS�W�^sssBBB6l�˗G!D�h#��L�2x{{���ɑ#Gx��)&&&���1k�,��g��燏���+W333����S����)SX�r%������гgO~���=����U�8z�(t���t\!����p����<z�ݻwӣG��eiiɶm�$�A:::8::���(W���CB�bg��ԯ_www��ݵ�B�bN>��}o-�B!�B!�x�������{��eqqq�d�����qrr�ҥKʲ������p����j�'�;���$���ؼy3/_���ͭ�m.]����d��_�___�:����������Ν�c��{|���qtt����oߞ&M������n���<x0~~~DDD�v8r�;v�׹z��)�G���͛*�&&&???��.\Ȏ;�m���s��144��ӓu��)�y��9�ϟ�󤤤�P�����Cjj*jmXXX�޽{0`���!�(:*U�ĬY�T�T��

�<y2�'Oε�=z�
,W�������O͚5����̙3�;VfMB!�?~<-Z� ""B�����m�VH�	Q4�5��3g��ѣ��B;իWg�ܹL�6��#GR�n]m�$�B�7P��2�B!�B�b.((�{��Q�F
���������[e%���@.]�D�&M�ĉ���ҬY3bbbؾ}��>�|�	aaaDEEaoo���ߨM�����6l`���DEEq��1V�^
��Tg���U>��������]��1c�ЩS'ƍGhh�rfn��C�R�lYT�P$\t��!_�jݺuܼy��5k*����/5j���j����d���DGG���G�5��>����:aaa�X����h�9����ظq�Z���/**
��
���(S�BQtu��sss~��7�<y�˗/�u�s���y��z�#�?{��S�?~�5(�DnG�[�I�r�19�H��RR��d�☎��\4�I�jB��.�1dN�2���#�1Q#|
�%I.���|N��|��x|����{�����g�^˙֭[�,�����GG�mK!��U���ǔ)Spqqa�̙�ݻ���-���Z�h����r�\!�5oƌt�ܙ�s�;!�B<'Y��;w�.]���/..���d���ϸq�^dhB!�K)!!���{O�a!�x
���U�<55U9���ۛ��~SSS-ZĬY�T��޽___ڴi<K~����Ɔ��lllT�Y�`�۷�% ���s����:���#�����RXX�/���O?�į��ʱcǀg�B��:�+f��_8z�(Ǐ'--�cǎNJ+hٲ%M�4��Ύ��ד����������ɓ4j�SS�*�Ui��W�^,\���?���{����rN///��o��6���̘1�}��)���萛�KTT���:;;;������w��9�YBIq���*u�B<���x^����9�͛7��營���~}}}�M�V�mjkk�����ٳ�4i������U�m	!�B�JΞ=�رc�r�
۷ogȐ!,Z����8rrr000`�ĉ,^�X�w���111�_�^��@tt4'Nd�رlڴIY��oPXX<{���_��F��N�:���'IIIhkk3v�X���iԨ���k�X�p!���ܿ[[[�E=}�bcc�t�������0u�T\]]k�gE]���ΠA�HMM���LB�:kРAAA6����?�5J�!	!���$��9͛7�������FHH���2~�x����ݻ�"B!^�?f�̙�C!�(WVVPrV������X[[�z�.�(322R����<{Q�<�T�W�q�s���_~)QW10�,�i_�[�nt�֍ɓ'SPP��u��o�a�ҥ�����X֮]���III<y�sss4P}\QQ_���ϒ,�Rܻ+W������*ۊ��/_V�͙3��>����d���Y�b...888�;����ݺu�ƍ�8��LQG!��K���O?q��E


��_����9����������郇������K�E!��u�ԩS�ڵ+���(�+dee���KJJ
;w�^�z�������̙32d�۷';;ڶm˪U�T.������Ҳ�6������͛���8V�\ɓ'O���0���L�1���*O(xyy��7�(�

��"�޽���g5zR�N���	+W�d����G!�$KKKƍǬY���_�*�e!��(I�xN(����,^�;;;���eѢElڴ	mm��B��$00P�a!�xMO�W��VZ�B��Ō���)���$444j��EW�X�t)����ڵcȐ!ѣG�J��X��
ăHHH(1�TSSggg��”+@4k֌�>����h222HLLT������,E�2�+�ԡ�[t ������g���l۶��'OJdd$3f�࣏>*�ܕ=Nq-�_-��
!�([y��?�z������C��Qu�)�B�y��!���'$$��?�6lȒ%KHMM�_�~�\�Ο?���?��3��Ḻ�ҴiS""">|8NNN�ٳggg�޽��͛��ק�����˖-�TEu�҅u����o�d��,Y�?��L��'33�N�:E�޽INNVY}CAq̎;�������
6���App�$\�Jqww�O>��ߟ�M��;!����ڵ+�|�
�/Vw8�����&::Z�a!D������jy��]���ׯ3a�e���=111�]�5F'�B�ODDD���_!^&��β�sj׮���'O���w�U��<y�D]���ؾ}�2�y��9	�������̐������i�[�n?~����ӧ�دX-�xb��I�ؼy3���$%%Q�^=P���ڴiåK�8q����S��8qBy-ŝ:uJ忑��4�z�-�zzzzX[[cmm͙3gسg��pQ��7oεk׸s�͛7W9�Ν;�:B!�B!�(��ŋ�7�����رc��������Q~��޽;�֭�S�NDFF*�!�
�ܹs	`�$''3{�l�^n�UiC!88�Ν;0w�\�,Y����֭[X�j��y��Y�b�F�R9���.w��!  �ӧOccc����K}6#DY���"22��?�X��!D�Զm[�����/pvv�}���I�Q�f����F�a!��3PSJN�X�=}���+Wbkk���9�fʔ)ʇE������5���=���P


�u��033Sn߻w��7ҷo_��=[�n���7n�޽{�x�B!���ĉ$$$�;!����r劺�x��{|��Wddd��c���ꫯJԵ����ۛ�g����n޼����133��ݽ����9�9BAAgϞeѢE��w��[E!;;�Z�����;���.\�@AA���<x���*�Thٲ%cƌaǎܽ{��={Vk&��C����˩S�x��1�N�Rޫ�V�X�d�򾦥������#�uƌ����7o&//�Ν;cll���Q\e��ҥ𿄔�e�:B!�B!����[�bjj��ǏIMMUI����_�ر#o���өS'���U��ҳgO����޽;~~~�P�6LLL�?7k�P]��…����7x����G[[�]�v1o�<z�쉯�/yyy�.�B�&Mppp`�ʕ�E!괹s�Ҷm[�͛��P�BQ
j[�BBBBX�~�r�ѣG����������8q"���s��eݫW�NFF!!!%f�,j�Ν���aaaQb���)))�ڵ�ܙ0�B����ښ��@u�!�u�$�Ռ�'�c�.]���ɓ˭;y�d���ϩS�pttT٧���ܹs��~M�s�С$$$�駟�駟����Y,,,����֭[���b``���۫Ծ��%�&MbÆ
���[��:0k֬�NNNlڴ	(=1�2���ٻw/��ٸ����k߾}�2x6���}�޽;�ǏW9���/~~~%Z����Oe�0` ##��222��B!�BQ=~�///pvv&44mm���&1�F��diST�:mhjj��Naa��*�6�Ä	1b[�ne͚5>|ooo����� ����FXX����,J!jIÆ
���o5j�v���ʪV�IKK�wީ�sW����ˈ#((���hu�!�j���C���Z�b˖-��e:�9�����Pə3g011!::��G�G�޽III!>>���T�1�����ÇЭ[�1(�u�B!�B�O��r�ikk���5M�6�A����/�uuu	���ׯ���C�eݺu�Z��&���+++�����ԤG�|��WL�6
��w���Ӷm[�ׯ�\ٱ��Ϟ=����J˖-�W����3}�t6l؀��~�5j�����+�q�Ƭ]��q��ѪU+�ׯO�V����gݺu���8&  ��ҠAZ�j���+W�T�����|��t��MMM455122b���|��ge�S��F�������%Α������r�!�ϒ!��,�ȧr!������aذa�X����p֮][j����!�.]���������*�.\Hzz:}�������0���Q�;w��*���ɥ����gʔ):t���>�����O<==�ܶx}�������*BQ�F����
�g��ѣG5~~�r'���R�6��|�#���S[^�
fff�*/k�KM���!77���(233:t(vvv��٩�۽{7�l��6m�ϖ����Ɔ��lll�l�ܹs���;�S<tQ�B!�B��j֬Y��!�^�
@�-T�������vY�{K+�s6n�__�R�)�.���J�M���+��ߟ���W���ɓ'�gߡ;v쨲�*}դI,X��*�n�&M���o+�gmm���u�uJ��2�5j�֬YCNNm۶�
 9q�nnn���T�B��������~���;!���ڵGGG�7o�ѣG111)���~�����os��
�-[���?����ݻ��{���ٻw/Çg���=�aÆ�fk.,,��W��ʲ��gѢE����a����IKK��ͭD]###233	

��ё^�zq��@u�!*���www�/_^⹧B��@���	

b޼y5z�m۶��B�?��
s�̡aÆ$''���	'??_�^vv6�lp�����H�P<�(˭[��g[�S�)�!�BT�ҥK5r�G����¸q�pqq��Y3��}>n�8ƍW�1��S��c��.]�ҥKٱc�s�O����133c���ܽ{��O�r��E�
�\��.�����͛���`ҤIj�H=���iݺ5QQQʲ��(pttTcdB!�B!��=y�O?����+++�;Va����]�v%))�>}�������������l�2n߾��ɓiܸ16l@CC���7n���3�o��e˖t��E9�beۨ������;�͐!C��Ԥ_�~��V��t���===6l���C��r��6a�tttWw(BQ����[������?�ʕ+�G!����V�(>ۣbe��\Ѣ8+++������ٶm'O�$44���Hf̘�G}P�"�����W,_Ã� IDAT�]�^�|E�,�-�B��X�t)���52��cǔ����r��1,,,���uMM�����/�Ͳe�(,,d���ҵkWu�&�+k�ȑl޼???���T���뫬!�n��ʟ���=z��Qmmm|||�={�2�$>>��� �����B�<j"AY��YTT�r�B���?���IJJ"$$��ӧW��&M�������?�@NNzzz<��?���={ϒ~��w"""�������쌇����,_�ooo���y��a�ڨ��
��~�������3�U�V�R���



���;Μ9@�N�����O�ܶx�ikk���LXX���/u��B�����Edd$���?X�j_~�%qqq���```�ĉY�x�����111�_�^e���h&N��رcٴi��\1.Q1277��6�w��)<==IJJB[[��c����O�F��u�]��…�������ڲjժ���S|||����ҥKhjjbbb�ԩSquu��^�q��uF�IӦM��矹|�2666�jՊ��u�W-�Ν�K�.��#99�����3f!�sya	/===�������̙3�ٳ����	dee�}�v��F��͹v�w�ܡy��*��ܹ��#�BQ��LNU,]>d�8��}�$�/2!���������r���ÇD@@����,X@���駟�x�"��/���WWWZ�j��_i�Z��Ν;������M�������������1cF�3W
!��N�Q=2�B�WQbb"���hjjr��!儎U���O`` ���e։��&::�D���NNN��	&0a„j�eO�XZ���������VX����r������

b��݌1B��!D����C@@���?~��g�*�eee���KJJ
;w�^�z�������̙32d�۷';;ڶm˪U�T.�������R�ximeii�͛7�g���\��'O�<[!l��dff*������ݻ%����o�Qn���Lrr2w����ӳ=(�+##�=z�lWf��Ѽy�8p�@�c<���		!66���BƏ���1�{�VC�B���JI3ffffl޼���<:w�1�z���x{{s��Y�<y�͛7Y�|9fff���+�*^Tdgg+�sYYY%bP���U'�B�gƍ'��5�ƍddd����ԩSiܸ1����%�նu�Vnݺ�ȑ#�e#G��֭[lݺU��	�j�W�lذ�C�������Y�p�$[Ԁ��>����_h������u,[��e˖aoo��p�B!�B�(,,�믿fذa��ۗ�ǏW+�BQuݺuc��\�Rݡ!D�gcc���gϞ��w�%--�G�q��i��?�Lxx8M�6%""��w����ē'Opvv��ݻ�[�}}}�����B�e�HMM�_�~�QT�.]8�<yyyx{{��?(�������I�N�8z�(>��:u�ĹI;v���ÇܻwO�T\C�)*��������?x�ŋcgg���mڴ��֖E������x�V�pvv���???���T��9r����߿�S�N���ROKK��s�*�����u�����}�v�����(1#���A����	!���?�����(�?N~~>�ڵc̘1|��������9r��n�B__�A���G�$]*<��������hhh`nnΤI�TV	��9}||�C���_� 99��;wr��E>|���>}�����---���ϊ�l�
�����ӧ4---�O?�ľ}����S�[^̕���u�혘"""ؿ?
4`Ĉ�?���\V�^���_4h@�>}�:u*��ڵr�����}*�vdd$�W��ȑ#hhh`jj�ĉ���Wֽ�>			���ЬY3ey�-�ѣ			�=Ze�W!�B!�B!�x�ܼygggv���ҥK�3g���$����ΤI��|�2o�����B�:M��ȑ#���w�ޝu��ѩS'"##quu`ذa̝;���Hrr2�g�f���嶡x��[o�Un
���t����s�d�nݺ�ܯ��oժU���<�+V0j�(�s���r��8}�4666L�>��ӧW��D�����L��g�<88�����:֮]���UV����'&&��k�������*��p��%mmm���O�ڵ+���hjjbdd��ɓ��ϔ�tuu	���ׯ���C�eݺu*�S̟?��m�R�~}


1b:::$&&��!11]]]�{�ڿ`!���z���~�)$77�Ǐs��E��=z�g�}ƶm۸~�:�?�?�`˖-��������������Ç���e��ݬ_��������i޼97nT>T����ɓ'ܸq��~��իW�{�Um���P��?t�P�+z�߿�̥̋�\�~��5kְc���������g���,Y����$>|���9x� k׮�v_@���T'��֬Y�����<x�ŋ�����s��a���K]��w����瓔�T��&�B!��33��j��s�Ε�/..OOO<==�+�\!���%''cjjʉ'8x� s�Εd!��֖f͚U��J!��������~�7��N�:����R��ח�={���L���KL8]�_���;V�
�ϊ	���۾p����*�
<�Ĺ������f׮]̛7��={���K^^^������ӧ�\�[[[���<x0S�LQ&����Gpp0��֘��3z�hBCC��sA5�����{��q�F���K�V��uZ�n���7n�޽{�x�B���Z����kk�
����)_<����
+++��F����5k��ɡm۶���p��	�����ѩ�E!����������U�V̚5��;r��y���TfVؾ};����;w���;�۷�ʕ+������ξ}���_��rL�6m�1c͛7g˖-lٲ��G�2mڴj��]�v|���U
puue�С�����������x6��U��~FFׯ_��А:`hh���!�.]����*Mʊ�*�^U.\�o��M�6�����ի144��o��E�l۶�M�6�$���-�����Q���V����Y�p!&&&dff�������1�����gdd��#	�B!�B�}�����Nv���FHH���2~�x���KM�B!�x�BBB�7oC�%22��-[�;$!^[�������z�j-ZD��ݰ"!�xa*���Ν;e�lbju����,�ń��'vT�+(j„	�1��[��f�>���7���������^��էxNx��y�С��=L�<ccc���k=���������������8q"���s��eݫW�NFF!!!ԫW�<�;w�$//��,,,HIIa׮]|��G5xuB�ׁ|3�%����?�!**�������j�N!�x��5��xy\\)))L�6
ccc�ٲ�������?r��g�Vf����̘1��3g���Xb�ԩS100�>`˖-ܿ�����<`X�~=���dff���HVV��P�����ou�aÆ�޽{KM�(sU���\]]�� �F�"66�������ӦMF�ͦM�TVw���[S�[q����O���L�6�/�����e��ŋ��T��LQG��Mtt4�=RwB!D�ڴi��Cx�蕜ˣXݰ��x�b���߇lmmY�h�6mB[[�E�)�B�ݻwquue˖-��_���ۻ�SB�cڴi,]���۷���;!���

9w�˗/g�ܹ=z��UT.\Hzz:}���رc��$00�Rm\�tI�>�yu�ܙӧOs��A����)˓��K����ϔ)S�2e
ǎ���믿���S.^ �x�ؐ�۵m˖-cffƣG�HHH��Ϗ��Xe�Edd$gΜ��Ą�bddDVV���������
����^�>�=|�0ݺu+�����Òp!����.ᢶ�^�/�������a���L�4	���x������z��!�u͕+W��_�J��t��U>���RϥX���v��)nԨ�:�CuΩX�J��?��믿&33�D��3AW���߿�ѣGX�n�֭+Q?%%����+p��*�^U���ʟ���T�^��7Tm����B����V\�^�T��v�
��kהe�YG�R�����O������'�B!^cǎUw/��^�	X�v-ׯ_W&n����ڵk���PctB!�x�8q�q��q��=v�ލ����CB����x�w�־b���B�z�-F��ʕ+%�B!jч~�lޫW/�O�ζm����KKK����޽{	d��ݻ��Ç�|�rF�ͰaÀg�_^XX���(*�ppp 88���~�7n�lٲmT���=�-��͍
6`nnNZZnnn%����Ihh(�����Ջ.�+i�ڧH��ѣG�۵MGG���\������d�С���agg�Ro������*'��ر#>>>��ؐ�����M��;w��#ŸE!����.�.�ӧ���0c�LMM��B�r*>�]1x�����[β,��&Qty�:g��3�����̤u����ۗv��ѩS'<==�=wU�?t�P��

8t�VVV��\V��-WZXX��_^e=L�h6�ڸ�5�:�W�~}�mEbH�~Q\Ci}�(����e5k�,f͚��0�B�(�����S���صkW�^ECC###ƌ��2������5kְ{�n���Z�h��ᅬ����T�Ɍ��t��=6n�H߾}����n�3336n�ȤI�hܸq�t�B!D1aaa̞=sss���iݺ��CB�lllضm[��^$www>��C~��7�����B�I^^^lݺ���$e�bRD�-[��۷�<y2�7fÆ
hhhA�^�pvv&==��M�ҲeK�_�N�.]�С�.]Ri�O�>*�m�*�ϟ��OZZC�Q���ۗȾ`�������(1�G�cE�)>�ҥKY�t�r��/��/�jw�9s���g����Lrr2+V������7WZ[[�zE�NYnݺP�NE���BT�K�pQ�fspp���A�a!�uJ�֭����9w�={�T����޲eK�\��w�}G˖-k���8�ɓ'���/��������O�<)1ؾ:��۷x��h�޽K�?q�����۷�D�EqU�w��<P��Q���6�oM���Ο?�2��ٳg��G�6mʍ7�w�M�6U9�޽{�:B�n&N�Htt���B!^��i`��.$$����+�=zDzz:���ܿ��'V�^AA���9sFY��ի������AHHH���;w�$//��,,,HIIa׮]|��G�}�B!�������ݝ��H,X��_~�2A���m۶�;�F�I۶m	�믿Vw8BQ'5i҄��$>��s~��~��w
9r$_}��򝼇����;��


	������Y�|9���dgg����R����AOO����矫�����
��~���ؼy3w��e̘1�Z������nnnhhh��w�)�mu�ԉ>��O>��9zO�j����߿?���g۶m�<y���P"##�1c���dEϹsss��/V
!j�<�B!�+��‚��X���3s�L:v��o��ƿ���u�}�]�n����˙:u*:t��ݻ������ӣG���U���<�'077���ˬX�BY���K�&M��W�^���J�gee���ɛo�I�^�Jm�W�^�iӆ�~�����R�UT�J����q������{�Ǎ7X�zu���*j����mժUʾ>�<aaa0@Y��А7np�ʕ�W�\Q��u���ATT���B!jUtt4[�nUw��-[�����="!!???bcc����ə3g011a�…������/)))���cccCjjj��6>@�n�JĪ(;|��$\!��V�={��c�r��U�o�ΨQ����
4��Օ��`���2W*B�|�	$00�۷ocllLǎU!���K�d���	'''�	�0aB�m�������Jhhh�u]\\pqq)�mQ{RSS9~�8ӦM��Ąu��q��fΜ����r‹������5��֜9s�={�A@@��٤��YYYl߾�Z�5�7oεk׸s�͛7W�w��e!��*I�B!�+gԨQ:t������˭kccñc�8�|�6l���s�ۯ�s���<x���BBBJ�x�"�{�V&.̞=��-[��w�U���{�����o��f������ɓˌ�*�޷o_~��g6l��
J]a�y��-���[�&MJ���r��Ԕ��T.\�@���U�*��,�<����c�2v�Xu�!�BԪG���	����_���:::���Eff&C����;;�j�۽{7����i���;��ネ�
			��ؔ�bU����٥�\(�BQS���:u*&&&?~���۫;$!�[nn._~�%qqq���```�ĉY�x1ZZZ888���4i�����h&N��رcٴi��\�.G1X�2m=�ԩSxzz������6cǎ��ߟF�)�^�v��������eժU%���ӧ���ܼy�F�������	S�N��յ{R!�BӦM���cڴi�����u�z�����Ĥ��a̘1�������ȑ#�ܹ3���;�l=KKK֭[���7,�s��ܾ}���H6l؀��+W��7�fvv��;F�.]�v�YYY%+����u����^g\!�B���∋�+u���>>>XZZҸqc�ׯ���!�1��eLGG�/���Q�FѲeK�ի���.}��eɒ%՚��&�9e�,,,���BCC�N�:1g���~�IY�U�VԫW�G�U��Ǐ������.�.7�!C�ШQ#y��q�����NNNXYY�������{���ݽ�~��ڸ�����b��O055�~��4k�kkk����������o���������E��C!�BQ5s�̡aÆ$''���	'??�Z����������L�Q$Y(��r��-7n\b��LQG!��&=z�ٳg3~�x&O����%�B�	���XZZ��_s��E


��Ѝ=��O�ʛo��̙3��ggg���A۶mKMt�jEYZZ���?����͛7Y�r%s��U�}�6`�ڵܼy���|������/q.///���[
y��1���$''�������B!�e�2e
}��e֬Ye�8!DU�	�	)���<x0�����'MMM��&O����!�N���ё~��1b�6l؀�����6������2z�h��	��5�(4hP-\�����.ʚEY!��&4i҄�ӧ��������T)������\�e%x�V���lԨs��)u_���-,,J,_Q�
4 <<������X�vm�1C�]KKWW��?wU���򚾿��yy}R��������U���ڌ5�-[�p��uZ�j����9{�,�ƍS��J!�r�ܹj�袘E����+SG���><x� [�n%##��w�Ҹqcz�쉭�-|�~���YۿW5u
qqq$''пƍ�\�BTM�_�o����߿?���g۶m�<y���P"##�1c}�Q��U�r=77���g��ꕜIQ&��BQ�._��رc���(s@���e˖���J�~�X�r%&&&�?777~��g���quu�iӦDDD0|�p���سg���ܽ{�͛7���Oaaa��-��FQ]�taݺu���,Y��%K���?���?���t�ԉ��(z��Mrr���
�c������"99��Ǐ���App0����սB�Z{�7�_�~�������DP<�����*�/���-
4 ..���LڵkǠA�T�S�����իٷoׯ_�Q�F������N�N��u�ϟ�w�}ǵk�(((`Ĉ|��$&&����b���{�\����񄋁Vj@�B!Du999������+���p��֬Y@׮]�a�$���3fGKP� IDAT���������-[��9:�:x��yyy%�e��y��q�I�x=|��O?��={������<x����{���g����Y�6�liii���Kaa!�Ǐ���X�zB������5��֜9s�={�A@@�2�������b���T9��͛s��5�ܹS��;w�(�!�BԔ]�v���H���III�[�n�I���[o�@���Y�n�:u"22R�1l�0�ΝK@@$99�ٳg3|��kC!88�Ν;0w�\�,Y����֭[X�j�.�fŊ�5J�\���ܹs��{�ҪU+������,1)�B��gff���,�>@OOO�!�W\BB���?���8�A+������g�	�VVVXYY��5j�֬YCNNm۶ ''�'N��憎�N�/B��*9��B!�Kn���^�&L����'�O�FOOOf�%��//---f̘��}���?��?طo4l�P��:�ɓ'�ܹgggtttعs��C���ATӒ%Kسg���̙3���x�=ʮ]�����iӦ
�w���/��v��~�����	<`������a``@�6m���eѢE<x�@��	!�h̘1����y�f����ܹ3���hhhT����%��ޜ={�'O�p��M�/_������ʺ��q����e�����JĪ(��*WB!�E=}��/����#G�׿��cǎI����~��W:v��o���(f\NOOW����KϞ=INN�{����x�:Ku�f̀g�]*\�psss�����G[[�]�vq��u������!//��؅B<?___��������gggZ�nMTT��,**
���UV�+\:t��'��i�uHѥP��:\\\000 11���=zD����իvvvʇȢfI��ܺw�΄	X�v-���t��]�Q��������$bbbشiׯ_����빘�����ū�ĉ$$$���Gxx8����}͚5c�ȑ��ߟ	&������o�����c֮]��י0a����ޞ��֮]�����B����3�������HejjZ�z�'Of����:u��A---�Ν������֭[���b``����0` ##C�4�.Z!����7o2i�$���÷�~����5E�J�XI�4�$��h��ꦥ��xO_�}}фo�	&0b��n�ʪU�8z�(�}�AAA����$~!��y-[��/�`��ٸ��ҵkWu�$^���5�E�������LJٳg3i�$���	

BKK��"��;j<�BAT!������,!D��W��F�*����]��/�b��#j˩S����!&&���,z��Y����WΰVWݸq��� :ă022��ɉ�����X�f
�w��?��E�����������T<�ܸq#�:u��
2|�p�̙���v�����166f�ʕ�ٳ�M�6q��Y���iѢC��������P*�~uT�*{��{���޽{�y�&-Z�`ذaL�6
]]�2���r��Ç���c���hjj2p�@f͚E�-T��J_޼y������
��֢�m�����J�EQ͚5��ё�� ~��e�Ee�/��~�jW��WGuo�rO�ݻ�ƍ�۷/�Z�R��n�3336n�ȤI�hܸ�s]���^�$J[[[4h@\\����k׎A����\�z�������z�j������iԨ������+g��?>�}�׮]����#F��ߒ������J���������{��Z!���KMM壏>�����O�!DE

9w��.]�C��_�p!�����ۗcǎ�������m�2:w���ӧ9x� ��ߔ���ɥ����gʔ)L�2�1c�p�����<==%�B!^�iӦ��ٳe�y!��O�>xxx�����3JLF#�UQk	B!�B!^]����$�ӧOӡC����mfȿ�>���\�|YYv���R����Ι3g�eW�^%<<���BBB�W���1nnnʙ�����y��)����>g@@���S_�bk֬Q�s��56n��ݻw�]��:�WGE�P���P�rss�:u�r0+<���hRRRGGG�Z����l߾]BB'N� 22===�j}y��=\\\���Q�ݱc���/�ɓ'<xp�18��� ��ҪeT��+���Q���铝;w������E��-,,HIIa׮]�GB����$kkk���+<�����������ӳ�zVVVXYY��5j�֬YCNNm۶ ''�'N���V��B!BCC���dȐ!DEE���@����?������y��q�˖-���KKK����޽{	d��ݻ��Ç�|�rF�ͰaÀg�Qr��y�����Fe��۳h�"���ذa��椥����V������������舗���9��N�"��r�ׯOPPC��ᅲ�ֽ͢���$����x��B!�B!�k׮�`�LMM122"((��C�r��!.^��W_}Uf��ѣGٴiS�Ovvv�m�u\e��MQQQ\�|�6m�Α#GS��^!22�3g�`bbBtt4G�%..�޽{���B|||�c:t�-[8|�0...�۷��ٱcG>�L������ˋÇ���ĪU��g3Z������T�vuگ����*���~X�~=����m�Vy�5k�ЦM.\���u���C�

�ȑ#���ӦM�\�Bdd��NU�rÆ
���Ю];"""��믿�h��?�������|�M�_�^���(�:}\ѽW033+�S\M��V�>|�nݺ�8^Q��#�/gggZ�nMTT��,**
��B!^U���8::2s�L>��~��'I��
///�v�JRR}��ACC������aٲeܾ}�ɓ'Ӹqc6l؀��4n�gggn߾
@˖-�ҥ�r�ʶQ����w�!;;�!C����I�~�J��y��xxx����2�Đ!C�ܶB��4h�&M��ӓ��<u�#�B���l�EY/�뒸�8�fqqq�G!�B�
��_ptt�o�!--��m۲a��/_΀x�7�=>((�q�ƕ�:t�Z�U���*k�vi劁���޼���hhh`jjʢE�J�w������bllL����ر#>>>$$$�8f���oߞ�
2q�D�޽�\�tttT�a��;v��ݻ��O?�|�r���k����T��ꨨ�r��Ci��ի�r����X�bv?


�~�m��E�җ���`�…���Cy����?K�]PP@��/`ZXX��U��2����ꨉ����ɹs�gI#�)F(�!^�%o=��U���������\�z��W����ZZZ�O!����g�bnnΎ;HHH��>��U0�xU4i҄��$�̙C�hР͚5��Ɔ��d�y��Y���Npp��y���!���\�|�/_NǎiР>�RUѰaC�������iٲ%
6dܸq�	Z�rssc͚5���������m۶�~���J�BQ}_�5�o����Oݡ!�����ȋ�VZZ!!!���RXX���166�w���M!��P|||�͊-��ft�֍�����bccٸq##F�����q��aooO�~��<>**�ZK�FEE�̴�2���(���+qX[[�z�.�(322R�����ӧO�뜊�
7n�`�ܹ���/%�6�����_�~}�<y£G����(Q7??_Y�����*�A�x?���ЫW/�r�9�\�R�*ҿ�m��˗/+˪җ�㊯&S�K�V�Z)Ͷo߾��_ڪ ���2����{��.>ع:��W�>�u��7.q��LQG!^}����f̘QB!��ٴi...��у�Ǐ��}T��L__���@ˬMttt�r'''�����&L`„	�j�~�WZ���������VX���E�*)��h۶-�7o��˫ܘ�BԜ���{���?�(��!�쓙�43��Of�1��Q9�9�0d�|��0̊DD��-�9D��9�Yd���D����ޟ���T���y��v�u�߯�z�_׻���z֭�̙3�1c#F���w��uHB!D�#	%�ӧO���SSS���ό3���H�
!�9svv�{��C!J��&c����J%�+W��i�&6m�IJe�077gРA4KK�B���Ⱦp[�X;���ب��ǫ��U�Ț�PX}f���x�b.^����;v��ܜ�����w~�뭷x��III����m�ܹ����U�S<���>9Ѷ�?�x�1T�$��^]B�g֝=�3�9U��VŢe˖ܹs�}��1bĈ�߷o�Ҿ ���8��}~��&��̉*^m�:VX�$�(��[_�899(IV!�"==�iӦ����ĉY�d	*T�uXB�7��Ȉ�Ç�z�j��ܤ��B�A�&Mb�ڵL�:�-[��:Q�mܸ���t]�!����.�EhHRR���
bӦM*e'�B!��uXXX0k�,f͚�o��Fpp0�֭c޼y|��899i�y��033��9s��>�H9~���������dz}�v%1�uF�111P�zu����Z��w��
��"##>|��ШQ�|_C~އ�ԫW��7or��i�J-�O�P�>===233y��	���@�UΞ=�Ve��~P�a*?siffF\\�N����Z9~��y������ܹ���@:t�u~�\�?����]��ϋ��qQ*����̉��	���$''cbb�����d��B!�B�			888p���W9B�...,]��]�vѻwo]�#�e���˖-�G�DDD�`�U۶m%�BQ�9::I5�b[�b߾}���q��%��ҨY�&�:ub���T�TIiw��}V�X���y��)]�t�o�Q�ߺu{{{�����_�~��矄��cff��qUt		��ӓ�g�R�B�u�Ɣ)S�*L���_�\��#G����B�
6l�z�R�#55"##�{�.5k���O?eԨQj;s>~����ڴiC�ڵ��u����ʊ���J�*U^�B!����ٶm���B�R���[[�|�N�#{�]�[�lI˖-Y�x1��ф���hѢQ:���~Ӻ���t�ޝ�ׯ��w�1w�\�{�=.^��w�}�Ѷs�ά[�www���hܸ1>$((�
6`eeŪU��5~a�y��1�u�F\\�~��r�ѣGԨQCI2�u���C~��޽;����^��r��ѳgOjԨ����ٷok׮�gϞ��U�y}rҩS'֭[ǂ�;w.���\�pA�C�J��ի���n݊��=w��a�…9�=�|%�s�α`�z�衴��\��ٓ�+W�`����[�7o��˗�?���~�!�{�&""�Q�F1f��v튉�	���c�޽�Y���O�ҳgO��o�����u�(��M^�I�&$&&��X��B!�B��.22���cbb����Kl�S!Dᰰ��k׮����b_!�x�lllptt��ՕnݺI�1�aҤIL�4I�a!D�T,.|}}�W;���HHH�=R�<~���#G��������_y���~��XYYq��IΞ=K��͕sgϞ%!!��m�bff��qUƎ��Z�����?�̋/pww�8;;s��=�5׮]c�̙<���}����3\\\�p���Ν;p��y|||�R��w�&55Um�KkkkN�8��={����4!�:ckk������B�b�����ׯ��닂��>;v�cǎx{{�{�n6m�D�ʕ�l��agg�/����@����_��͛Z�6d5|�p���8{�,C�Q;W�bE\]]�=~a�٩S'v���̙3�9s��K�.amm�$���SSS�oߞ�����8p�111,[��e˖i�էO�����ggg���ϭ[�9r�ڹ����ԩ���,]���K�h�\�F�qYZZ��g�)��3�C�a߾}\�|�1c�(�{��,����ݝ����{���鉧��F�Ν;���Q����g��Ra|��eNڷo��9�<�Z�Rk��F�L�B!��(�x���3g�X�v�R	RQ��7GGGn޼I�
t�B�)K�,�iӦxyy��MфB�ҢX&\lڴ	��ӧӷo_���8w�cǎ%::Zi�a�033c޼yXXXp��9�E$����<y�������;w���qU�y�fϞM�:u�'  �(	�ׯ�޽{XZZ2o�<j֬���[�l!  @Yhąh֬�|�
�����dz`�N�8��m۰���ȑ#4m�T#ձ#G�H…B!�%XA-�4���C�>}tJ�~��\�����x���???|||8t�)))4lؐ!C�0s�L�j�����v�Z8@RR�+W�U�V���ШQ�|�^}~��Wddd����iܸ1C��ƍ����y�f����6m+V� 11�gϞ�{�r�ʱl�2�����_�~�:���ӬY3��O�=���!'U�T!00�իW���111�k׮�=��U�*m]]]���'22��O�bee����~��־===�5k111ԨQ��={jT���\�������ٷoO�<�cǎ����{�n��


Y�p!�b˖-�;w�G���[o�`gg����%~m����qQ*�����I�=X�t)���6L����ӽ{�B�>!ʺ���u�V]�!�BQ�ݿ�aÆ�ҥK�8q��CB#�������z��|U�B��ׯ���ә?>C�����uHB�6n�Hzz���B�RO/� �|f�q�F��������U��S-v�����ŋ\�r��W�r��I��������ɓ0���8|}}iӦ��Ǒ#G�<y��_FF�z�"##�ݻwc``@FF=z�B�
l߾�r���y\յ��{����L׮]����ĉ��D���x��r��A�q��U�m�F�z���o���ΎV�Z���@�^�HJJb��ݘ����s��}z��A�:u�����|�&���t���'##C�h��UX*\!D�177���[[[广��v����(q?�
<���`��7n
�z�ܹC߾}�W�۶m+�~E��}P}6�[�NqV��/
���U�V����֭[�?j%$$`gg�رc5jT��*DV���===���qrr^~,�(�I�&����__B!DV�����~�7o�]�v:�HQ͙3�+Vp���<m�"��𤥥aiiɿ��o��b�l����úC!�����T��pq��=\]]�x�ƹ�(�}�6�Z�
��-[�=/_�<���#00���h�t��ѣGINNf̘1J�E^�U177W�vj|��r��?��I�&�^�[���P�]�vMy����Α٩���!��t(���.\`���\�t�������LjժŇ~H�>}�]���[��l���j����e���\�z���*W����ݺu�U�V�=v��4�X
K^�x�8
�~��WΞ=��9�gϞ��_I��]CU�B�����̟?�������3t�P\]]y��!3g�d���/?l����?gРA�?���P*T�@�޽Y�x1����Ɠ��¼y�

%!!SSS���+VTک�5�={�ԩSY�~=�˗g�ĉ|��ܿ�	&�}�v

���e���j;��w��g�2u�T���(W�U�Veɒ%���-������ŋ̞=�͛7s��M

i֬�����O>����T�O����
�����dzh�"@�wOQ4�}ŕ��3����L�255eȐ!:�N�ҧ(VB!�/������Jǎ	

�V�Z�IQL�=�y����O?I"�B�a+V��ӓ������B�t�БI�&1i�$]�!�e�K�Ⱦ;`n�.^���/bffFǎ177�����L��=�|y�������ٱc]�ta�Ν���cgg��qUT���w��vL�W�6����ѧ���F;ձ��+�B��o�����ƾ���ϟ�z�j���4�ݹs�;w�p��L�B�֭_#ڒ�ٳg����v�ѣG������5&LP�Y0?
�=-��f{ IDAT�.^��ƍ�����dڴi4h�@�*'`֬Y���(�}||�_�>AAAJ��ӧOزe���2'Ndݺu�����Ç9u�իW�:fZZ�;wV��->>�p��	v�ޭ��ĉ�*}s�ΥaÆ�\�R����ʏ?����>����s��ܿ���V�Z����s���ӧ��+ϟ={FLL111<z�S�/+���O,\�����Q�zuƌ��8�p� �+###fϞ��ɓ:t(۶m���[-ALQ8�3O!^�T�B��'O�0v�X6m�Č3�5k�ֿG!�J�z��ׯ����s�B耝�ݻwg„	�:uJ�zI!�B�b�/�j�[@@���'..N9���A���133#..�S�Namm��?��F���գ]�v9r����s��!:v쨶�s^�ͫ:u���p��5,--slgjjJ||<۷o�β&&&$&&�������ڹ��d��B!Jmɩ�HTT������kkk�֭ˋ/���cǎ��Ʋl�2�-[����Ϗ��*U����=m۶�f͚<~��3g��ѣG��B�{*�/�/_�e�nݺ��퍧��,\��Ξ=KDD�.k֬��ˋ�3gҴiS"##�W��W���ۛ��]��ڵ�.]����y�&?������:�?�@ll,m۶eժU4k֌+W�0v�X���K@@�ZU�'Np��,,,����9s&�Ǐ��?�ҥKԯ_�E�1g��o�Zc5i҄u���������ٲe666899)U.�&���A~��W:w�̳g�ذa�Ǐg���J…�����g׮]ܸq�gϞQ�N���3jԨ2WHW�}�Y�֭?~�RYg„	�R
K�����,��r�TJ!��t����ܹs����2[qV��ƍ�[�n�;w�>�@��!D�����|�ʕ+�ʁBQĊe…ʱc��֭qqq|����G�Q�F
z���ʕ+Y�`�~�-͛7����̟?_k���=z��Ç���P�q�}������d�,X@�j��&44333�l��ܑuݺu������F�ƍy��!AAAlذ+++V�Z�\L���H||�FbE||��F!�(�T�d!��y�&���0k�,7n�v���KKK<==���!22��.ĸt����ؘ�s���o+��z�->��>��C�M�ơC�������B��.[�n����K9֫W/v���֭[8p��+>�̙�T�1b^^^���1o�<6l�,����͓'O4^�r�J�������accCxxx�	��Û6m��w�^~�X�n�5"((H#	bŊ4o��)S�0s�L�>}��ի��W���+�̙�T�(�X˗/�q�Ɣ+W���{�����:����$''���������ƍcܸqj��qrr���:V\߇�H�ԥ�Q(��S�����GGG]�!�BQj�����ӴiSN�:E���u���ҥM�4��ח�+W�:!�(s7n���+�f�bРAʦvB!�(|�2�S�N�ܹ��3g2s�L��.]��ښ!C��o�>._�̘1c��=z�P���С�k�&))	333>����W#F� 22��g�ҧO�s�G�V>���(Ξ=ː!C��U�XWWW�y���9x� �ϟ��1QU٣C�y�Q!�(����o���9u�iii���ѯ_?�.]
�'j������?s��1<x@����С���(�T�K�,a���\�r���3t�P������ٳY�d	���f�^V�ڽ{77n����z��iӆA�Q�bE�ć�	(y?22���Lz�ꥑl�Հ044Tl�*�'O�����y��!իW�m۶8::R�R�����yPPk׮�رcЪU+�Qu#�����C6m��ɓ'��h۶��ώ*������V-�"���z��}��޽{����Ɵ�{�m��;�y�o"?s�U~��'O��s�N�5k���\�fM��}v��I߾}�\��k]Ki��r^����������F������s|�իWԾ?du��9�c-[�TW�REy����+�����Y�f��
*�����WY�d	#G�dϞ=�ٳ��ݙ2eJ��'�B!�BQ�����W_�l�2&N�Ȓ%K��U�"����pqq��Ãŋcll�됄��qwwgÆ
|��7�Y�F��!���������q���
���044����S�m޼CCC���ppp�z��ҽ{w��ݵ����������GOO�@�敉�	������P�Jhڴ)�-R۹��ؘ�����055�\�rT�Z�N�:�n�:��=z�R�JDGGk����1ݻw�W�B!DI���SfΜɡC�HII!##�7n(�Y���3g�~����������ݻ����p�B��rgϞ͹s��HII!22���\�~=O�<Q*T���(;�����s�ݻǮ]�X�vm�ן����w�e�fn���1q�D���^{jj*�ܹ����+�GDD0s�L���r+7���DEE)s��!<<<HII)�?y�3fp�RRRHOO����,[�Lc�˗/h���TI�/^,P�yQ�9~�}[�׳�˜9r���4Z�h��-Z����ѣG_�ZJ��hʕ+��ח/��s�zs{������d�cFFFZ۾*΂�ehh��k�8p 			о}{RSSqww�_���R]P!�B�T��h�ԩS�:u�T�B!D�$$$бcG���	

b���l!�(��Ç�s6lؠ�P��L266f���Hek!���
U�Ta��Z�eߍ�r��L�>��ӧ����1c�h��8?��Է����˱Ϭ�V����,7�+W���	�ݗ8}�4cǎ�Y�B�z;v�௿��v��L�4��
r�����y��Z��۷s��u7n��ѣ�_�>��'~~~�;w�еkW��ԫW�	&`bbBxx8���?~\�y� }���1o�<�"�Ν;5j�:uBOO��W�2{�l���9W>��w��ȱbC^d�}۶mܾ}[m��_����˹u�[�ne��ԩS|��74k֌��8���IJJbǎJ�����۷���Dݺu�4i
4�ʕ+���h����/�*�N�:�Z^���=ͮ s���V%k��W)Ƚ��9����U
��͕6�X���;F�Ν���iӦ9��A�\�|��7o��;�i|or��ի3b�F��ɓ'���Y�hS�N��ťH�B!�x�/����j����~��LJ͛7����g�}�����f!�B����݋��&&&?~\���BD�j�4h����7N��!D�4h� V�Z�_|�ѣG56�B!��+�	"w���DDD���������2d�G'�BLN���

�ĉ�˄H,--qqq�Ht<v��'O�v���j&L�/� ::Zc������)}��!<<�'O��V�}��Q~��G233���#::���xΟ?��n������-^ۇ*9�y�D�챫��ر�7i҄ѣG3�|�?^�Q�F)��,,,3f����ĉJ������J�F������ѣ�����~���Y ���L���7��(���-������eNnܸ�L�NuL�F��1c�D�V����Q
��k��p�B���X�|9͛7�޽{���,Y��Ν;���B����
COO���L������/�������Q�FѡC��1zzz����!�o���U:<xP��O���၃���M����1caaa9VB!D����ϟϜ9s������ccc]�%�(%ƍG@@���?�u8BQ������퍕�����5J�!	!���$\�@FFF̞=�ɓ'3t�P��.����T�XQ��	!�E��?�4wd׶C��;w�8q�־nݺ�q���Ly\�re���3{������E���V�B���3���	III$&&��+�~s�=����x���j����
4��~������ 11Q9���WŪJZ�kV&&&ܽ{��w�*��Q]_�5
^d�_uߪ�VY#{NA���2'������JuL�F��:u�Ю];�cVVV9��ӧOg�֭=z�֭[���T�?��C��W�c���+�'O��q~�ڵ�]�V�Xjjj�*�!��x���r�R\�������=h� 6m�D`` �Ǐ�atB!�(��߿���3{���ˋ/��B�!	!J+++ڴi����$\!���hт	&��7����@�j�t�BQ�H�E	պukƏϒ%K�0a�Z��qTB!D�e_�Z�����	ڪ8�*yA[5��
�Ϭ"����nݺ�i�3335j�ԩSs�;��[ZZ���ıc�pttTk�Ӝ�*��h[ܯ�����e��ٕ+WNk����j}�&��T�"�8�2���ݻ����'�cbb����u�6ǯ�o� �zvy�U���IuLJ��_~�E�{�ڵqrr���#����z��G���߲e��Z�*�|�	�~�-|�A��W�cLHH���ܺu��5k*�D�X��.ШQ#�����_-B!�"_^�x���{���Ν;`nnN�~����Sk������?���ܽ{��5k�駟2j�(

��%�d}��Ǐ			�M�6J:��u�beeEHHC��J�*oઅBQ������/8t��FBQXƍ���K�.�V�Z�G!ʤ9s�i�&f͚Ųe�t�BQ�H�E	��䄓����B!޸�u���p��e�ŷ�/_�h[�V-���OV�XQh�F�gΜ`޼yT�Z�۷o+�?�5) ��w�֍��(�m�F˖-iԨ��v�ZX�U�ڵIHH�ҥK4o�\9~��%%>===233y��)�*Ur��p����}�>�V���׭[�۷os��EZ�h��z��F��ݻs��!�l�B�֭�_��F��7o�m�6�v�Z���"?s\�
�^�˜T�V�{����c���?Vڔ%ׯ_����xyyi311aǎ����A���������^���5���7�^&��*fdM.377���\y~��uƌ��B!Dq�[��(Z>>>�������tΝ;ǹs�x��	��ٳg���(	��\@@�ϟ���'�d�ݻw��������9kkkN�8��={���/īB!DI��닫�+;v$((H@!������/�g���G!ʤjժ�`�ƍ��ѣi֬��CB!J���jW!��
R-.Y�f
W�^���\�r�5k�h��裏X�l7n��ŋ<|���� ��9s�=~a�y��i��ӹq����������vd�������?�0k�,����y�&��餧�s��mv�ޭ|���*mڴ��Ϗ+W�(�v�ZeQ3�$��۷���4n߾���f����{z��E���h߾}��_U���Ϗ.�s�]���U�&M��OHKKc�̙DDDp��}�?ν{�ؾ};�f�"--��?����{�@�k{O_g��Ra��y��
��j�^uL�F��:~�8aaa�C!�(raaa�o������|�r�;ơC��߱6oެ�

�…4k֌�7r��qBCCiѢ'N�P��ccc�����*Ϗ9h���:�j#�B��+33��C�2q�D���صk�$[!����Çg��չV�BQ�F�I�-�4i��CB!J�p!�B��w��>|������smkgg�ɓ'�r�
_��ڹ
*������Ϗ>��C���ハ���7nТE�V�Jrr2�'O�V�Z�X�"��9�r���믿�m�6eOvu��eԨQ���_�~?~�;w�0c��s�����?�Q��iӆ�{��a�6l��Vi"���zK�=577��O?U�����KLL7o�d�������k]�?v�X���9v��ׯg���m>��#\\\
���4���qQ*�{=/sҪU+bcc�v����jm�]���$Q�899��0�B�"�q�F��BYdee���Y�
[�J�HII!88���8:uꄃ�j�"##X�`����aÆ̞=;;;v�܉��]�㨪:���;�T	��*?
!��l�����cǎj��	!DQsqqa�ҥ�ڵ�޽{�:!�(��Y�|9��ք�����됄B�RA*\!��X


%44T빊+2{�l:w�L�*U(W�
4`�ĉ(m+U��ܹs�ݻ7�j�B__cccڴi����k~a�9b�����X�"4jԈ)S�(x�ڵKiW�vm�IOO/�����1�E�ѣG���ahh���>5jԠM�6L�2��K�Ҽy�W�^�re�ϟOϞ=�Q���O�^��?>���J�aÆacc���1�h�"�d�����V�ZQ�\9jԨ���-�f�*�{j``��9s����jժ`mm�رc��o``���+nnn�nݚ*U����OժU�����͍iӦahhX����3�E�0��I���X�"���5^����J�*)�m�B!�(n�L�B�
�����ˋ�>���������ݺu[[[�����TI�d�<x��*U�h�SS�B!D����.�B�7��‚�]�����P��Lk׮Æ
��Օ��]�#�B�
z�����Ӂj5U7��)��.,,@��k~Bs���ddd������+��0ݽ{�	&P�vm�U#D�5`���l���Q��l޼���p�/_N�ڵHJJ�/�`�����Y�����9^^^���*���9r��#+:���U-�?B!J��>�-韷���������9QU�(ʊ�<z􈨨(~��Μ9��n7a��gYkkk�={�c����8q�~����IOO'&&���ՋWgddЮ];

9z�h�^�(�
��$�B!D~�����������B��q��],,,pqq���u8B!D�W�.�ׯ/�B���P6��g�RRRx���o�f�ʕ���{:�P�_����f͚�رC9�c�jժE�>}t�e��˗��ء��L�:��S�JR�B�b�jժ������Ϗ?����3�=���Sicjj
���ۉ���O�l����5Ω���!�B!�.���bjj��իu�B�i�j�bΜ9xyyq��U]�#�B�x�_�$>��c>�����V!�B��'��g�֮]�ڵk��U�ZU�Y_QrT�X�	&��w�ѷo_8����Q�BG'D��_r��7���������a���dff��g�aaaA�-�x�B!Dn���GBBӧO�W�^4nܘ?���]�ΝY�n���Ѹqc>|HPP6l��ʊU�V/+dffr��-�ׯ@�&MHLL$>>^#�">>^i#�B!��R�|yF��ʕ+�3g����I!ʬ��dzf�\]]�6�B!D�z…�d�B�$33S�!!J��#GbjjJtt4			���cbb‡~���5j��u�B����d�0h� ,--u�������O�>���e7�3c����022z�a
!��rvvf��,\�����kժ��x���DEEq��Y��֮bŊ���*ϫW�΃�߿?���l߾����s��AΟ?��/�����СCa_������	!�ȍ��U'�G�f������O899�:!�(�ʗ/���7]�t!""�޽{�:$!���*����Т�ZQBmܸ��[��:!D)���O�޽��R����X��/
���B������c�
bӦM2~�xF'��8�EŦ���S�|yBCC�����̌:��쬴366&  ��k�r�����\�2�Z���ŅF�)m�M�Ɗ+HLL�ٳg��у�K�Ͱa��b�����ؘ�ݻ��+B�|!�"+���(��~�mlmm��!�бΝ;��舫�+ݺu�B�
�I!�(��,���ѱ��B�P����B!�(s���/V�\ɑ#GHII�A�6�^�z��{��1~~~�߿����S�fM�t�˜1c066V�YYY���'gϞ�B�
t�֍)S�(�^�x���{���Ν;`nnN�~����S�+����X屟�ӦM��‚U�V���J��W]wNc?~����͵�� IDATڴiC�ڵ�6u����ʊ���J�*U�F!�E���[[�W��Z�*S�Ne�ԩ��������F�X�ʕqrr��ߟ���~�m8}�4cǎ�R�J�!D� B����UW�ƍ�{��;w�>�@��!D��d�,--Y�x1�G!�(��u�B!�BQZ=x�ggg"""x��!\�v��3g�}�v�]JJ
��9�6m⯿�"##���D6n�ȨQ�HMM��{�ر�8q���4���������T����v�ZnݺEzz:����;w�y�����===y���Z�Ca^�6�w�&55kkk�s��֤���gϞ|�#�B����ԭ[W�����`LMM2d�#B!�B���ڵ+����:!�(��ׯό3X�p!�n��u8B!D�Td.^WRR��='N� =='''֭[�,|N;p��BCC����]�v0 _c
!�B!�(=֯_Ͻ{����d޼yԬY///�l�B@@}����$..���~��s�ҴiS.\����׮]cݺu�?^��w�y�ٳgS�N���	�������˱��"==��;w�p�B6o���ժYh�ݷaÆ`hhX�ם��G��iӦ���9r{{�|�$��l�ZY�0�3��edd��ٳ�<y2C�`۶mx{{S�b�7�B�6n���u�B����uB�JOOfΜ��ŋ�*�
!�x�\]]	`ڴi����:!���)�	3f��ԩS��{���0��������a���dff��g�aaaA�-t�BQ�l۶���]�!�B�Ç��W_Q�~}��ݕ��(�7o��~�7�|�ĉٿ�F…������	�ѣG�J�*���Bpp0qqqt��	���!C�ly�nm._��L(ɮA�jm�B���u�֌?�%K�0a�Z�j�㨄�"e��lٸq#[�n�uB�����qwwgÆ
�7N��!D�V�B����ӧ�s�κI!�(Q�m��ٳg�u��ddd0{����&v{��)888`jj
@����1caaayB!DIТEI�B�"֫W/�ի��0�m;[����'M�4ɵ]BB�2�"��-[��������jժ�x�B96e��̙CLL111���2r�H�����*�!��z��<x��*U�h�SS�B!��MW�(jNNN899�:!D1�����B�A���p!J��ի3p�@|}}%�B!��޽{ӻwo&M��o��F���v�BQ���_M�B���ХZ�iee���^�v�|�IJJb�ʱA��i�&5v"B!�*ggg���u�B�F�����&Pdg``��8666�k׎��(~��Μ9�ʕ+	

b„	��ۿr��~���T�|���׹n�k���5Ω���
!�B!�B!�޸q�裏8|�0����B�2��ˋ>���+W2i�$]�#�B��2M1뮣mڴ^&fdO�P=		��ӓ�g�R�B�u�Ɣ)S���_������سgw����sss��뇝��F<���,\����(*V�HϞ=�0a*T���DŽ��ЦMj׮���nݺXYY�СC���)�B�5���l۶M�a!D���六����(Vt��u�:u��?�v����9��W�7o����Ӵm�V9~��i��b~U�Z[[[lmm�p����c���xzz�)�";===233y��	���\�vM�]^�[INN���D�\rr��F!�B!Dٔ��Hݺuu�(!�~B�ڴi�������p!��@�ƍquu��Ã��IB!D˄��;v���"--����/^�����?����<==�s��q��9�<y����O�>��G�/�/6n�HFFnnn�޽���T���5Ʋ���ĉ�ٳ�@�Y�B�Ҩ|��xyy�:!�(����]� �����’%KX�`ժU��ۛ��P���زe�:ubݺu,X���s�biiɅ����СC���ׯ			L�>�^�zѸqc���@�:Fff&�nݢ~����Y�zu<x�֭[����Ν;,\���׭m�&M����H||�FbE||��F!�BQr>|����s��a���y��9�kצm۶�1�޽{�:�7BU�/33�P��~�:����۷�+W���c�T�B�ƍ�޽;��9
6,�1ߔ5k��������q���3�r��X�\9�T�B�
�ڵ+&L��w�͵�׽]�Ev/^��ߟp��5�<yB�*U����{��5�
���~�,7n�ƍc�ҥԪUK��!D����ƍ�>}:�֭�u8B!D�P,.�U���;���ٳ�S����p�.���X�|9VVV����s�N.\��͛5.���oBCC155eŊ���p�%��ȑ#4m�Tc,ձ#G�H…B��Ջ^�z�:!�(�$�1b����={�>}���=z����ٙ���s��-F��֮~������ٙ�p�B���V�Z)�UI�����Ԕ�۷��g�N�g�ҥ,]�@��y�nmc�oߞ�r��y�8Ο?,E!D���4(���IJJb����ڵK���۷�}�6?��3�z�bӦMT�ZUQ�\���nnn�������s>��ɓ�<y�E�1q�D-ZD�
tm��3F�!�����y��!�O����ӬX��5k�0d�]�V������/Y�j��{�ĉ�8q�E�1e�,XP�?��E��hРA|����3}�t]�#�e^�J�X�d	�}�...�k�N�!	!���K�P%P��x^,�sssSv�<x0<z�(��*U"%%���`����ԩ888hm����./�G�&$$����+�/_��L��N����B!�B����Ą��@|||8v�iii4jԈ�ÇӵkW�]�*Ud���DEEq��}LLL�ڵ+�G�.�"����S�|yBCC�����̌:��쬴�6m+V� 11�gϞ�ڧ��+���DFF���S��������O?-�uk�G�,]����h�
��ott4���t��=��!���ۺu+[�n�uB!
诿���ښ��8�ի�ԩS���Oy��w)W�7n� ,,�ŋ�s�Nlmmٻw/���㊝����={������8��-[R�zu=zĩS�fÆ
,[��ӧO�{���t���R� {����ߜ;w�e˖�}�v�
F���5���k(iii��ٓ�b``��!Cprr�U�VZ��%K�p��"""�H�mi�k!�;###���իqssC___�!	!D���舯�/_|�Ǐ���B!�+��O(��͕ǪE(�w��jʔ)̙3���bbb�e�ȑ899Q�bE���5R���[�?x�x�@&;�1U!�B���y��k�SOJJbǎ�9s�{��Q�|y�ԩC�6m���O166.�`��Z�>~��WΞ=@����ٳg��&�(;�իǂ^�����M�����6*�v���[[�\�������&Oc1}�t��贵��uk�r��899���OBBo��6			�>}��c�R�R�\�BQ�Ȃ8!�(�F�A\\;vd�֭T�VM�|�&M�1cvvvt�Ё��j�*&N����K777���x�wزe-[�T;_�F
�u�F�nݘ8q"���<x��S��b�
E]6P�vm�v�J׮]���Y�x1cǎ��&�%;WWW<���9aaay�'###�������Q�B��2~�x�-[FDD}���u8B!oooZ�lI@@�F��u8B!D���.�/�PU�(HE���p�����666�k׎��(~��Μ9�ʕ+	

b„	��۫�744̵?՘�2=U���B!Dv�/&66��n޼ɬY�x��r,==��7or��M����;w.5j�(��K��/�q�F~��233�6m
4���uhBQ�9;;App������)C��qtB!tA�L-�(�I�&����:����3�|~��W���/jԨA�.]pww���R�}^���=.66�E�Err2fff8::2c��
>���ٵk�j�"<<\#�"�f͚�p�B\\\X�f�F�ťK����ػw/w�ޥV�Zt��www7n��ueffr��I���k�;FŊ�С3f�࣏>�x�իW��ػw/��FFF���ckk��ɓ�^C~c�M~޿�ׯ��パ��w�I�&��ݺuk"""�裏X�j�&MR{M�9�&����:���Ϭ�Uq�כ�g�J˩S��駟<x�ֱU����e˖-����$''S�Z5ڶm�W_}E�N��5~A��.0w�\����Çi֬s�̡o߾Zc�x�"~~~ɻロkLY�Iooo&N�HÆ
��K`` ��=W�^�Z�jt���5k��^���r��{�%Y�ƍ�޽;+W���!�(&�5k����o����z��I!�(�JE����Z�����طo�ׯ���S#��ULLLHLL$99�s���J!�B��*���u�����S�7oΐ!C033###���8֭[Ǎ7ظqc��-�uU���X�|9666ԪU�nݺ��퍧����hB��I�!@a+���e����g�f���:�m۶���-����
���QǑQ򄅅agg��0�M�>}x��r,11��7��?�L�^��է����������s�X\\�-bϞ=DGGS�re���pqq�ӦÇ���X�������"��'�ׯ租~�w�q5����_�e��2�Q�~
&#Y&��cM��en�Xo�m$�fH�P%F1�ƾDHh�a�-�1����~�sw:�t'�|<zL]�ky�s�s��zoݺ�v��i��ĉ899���d���m�6v��Łh޼�R��ɓ|��$''+e������˚5k8~�8��׿�$��t}�V�^Mff&#F�x�f�F�1d�V�\ɪU�X�`A��e܅�g]���.

����ݝ��H�
�%''���Dll�Z�_�ETT;v� 22�.]�h���Ǟ={�֭�Z�3g�Э[7֭[�u���`2339r�K7[��|N�^���s�j�Y�`�Zf�NDD?��S��!/�5F�w���=z� !![[[}�#��5kaaaxzz����p�B�b���[�nܹs�)S�ЩS'jժ���_@=[FAծ]���Dn޼�����͛J!�B����WY0/�]�r��c�baa���u���믿f�ر�	غu+>T��S�NDEE�u�V\]]��B��>��#<<<X�p!�G��I�&z�J!�>�������0�x�H���ҫW/���7n������űz�j���pss��ŋXYY)�e+�7oS�N`ժUJ��71b/^�`�ȑL�<�*U�p��q�™3g�?>�g��ȑ#t�ܹ@�P�D	��,���������S�u��ܹs�U�W�^��ӓ�����Å�\��F�C��cǎ�?�ƍs��I�ʵk���o��_���ƍ#99�aÆ1i�$�W�NFF'N�`���\�p�Y�f)�^5��
��ݻ�=zh~U\]]Y�r%���ө]Qŭ�<�,+�6o�9�+��e����K���Y�r%M�4��А��8ƍGtt4s��-�F���ǣG�pssS�x{{ckk�o���ĉ5j�ֱ8�󆿾}��r�J~��W�.�N�����}��5�ڵk��?�!22�p��U*V�X�/�����ҥ�>�{~B!�����ח�C�2|�p5j�B�b���b��x{{��ハ��ڵ�,�hѢ$>>^�}||<�Z�*|�B!����Bll,iiiT�Z�nݺ��w��5���ؼy3���<|���e�ҪU+z�쩶�R��c�…�]��+W�`bbB���8p�ډں�9s�L.\H��ՙ1cǏg׮]ܸq�gϞQ�lY�6mJ�~�(Y���6g?��*�eʔ᯿���V6\�XYY)}�����ၥ�%��=���J�{��1v�X*U�����Ns���ʦM�8q��=�lٲ4k֌޽{cnn�q��ׯgժUDGGcbbB�&M�߿�Z
���L6m�ıc���?166�Z�j�iӆO?�4�y+h���T���hР�ک�*T�~��DEEѵkW�F!��M2Q_nnn��V!�B�\��������ɷ�~��;88����K�,a���j�s;~�8^^^L�8Q�w��={F߾}Y�b�RުU+6l�@ӦM����
���֭[�Z�l)))�iӆ-[�(�]կ_�-[�Ю];��ߏ����jݺ�Z��|�	?��m۶�رcjuO�>
���/��}h������4hЀ��e1�ƖSa�˗/+����? !!A�vE���7���UժU���	�			`ݺuj�C7k֌u��Q�V-Ν;W�13?��<�m۶jm7n�Ν;iժǏ���իԫW�@������C�r�S����S2�ԫW���Y�=  ��ӧ�4�Jq~��]add�ȑ#Y�`s���Ȟ%�B?
D@@cƌ��rp�B���˫��N��ۢ�=z���E�:u055������f͚�s�}����>|X���Ç)]�4�۷/�ЅB<}�///:DJJ
ܸqC�l����ϙ5kܿ������O�lق�����mfΜ���y��)))�ٳG-5za�\�v-���J6���0/^�o��Ɠ'Ox��<`ǎj�j��={�T�+$$��/�����o�R��ر#��Ƈd������u��'O�0}�t����믿����_���Rҫ�z�j8��y��!�O�NJJ�R'44�͛7s��=222HKK�ʕ+�\���۷�9wmw��Q��Ҵ��ѨQ#���^�CU!�B!�B��Au��W_}�����;�w�γ�Ǐӯ_?222��Ϙ7o��_������deeq��
���ӧ�.]Z�;Q�g�&M��vP���!�'O`ǎZۏ=Z���? ))I�\��S�N������W�V�~}����s�N�ŖSa?�f���/�?'U���T��iS��u�g]��献T�<{�,�z���;YYYZ
�������2���m۶0y�d�6���J��T�S�L�Ŧ�zN&''k�>}�t��9c��#�5F�w���;���lذAߡ!���X�lG���g!�"�6Å�����ڰQ�z...�������R�J�����ի�s�U�T�Ν;���1b��ӛ�B�j�o���A�J�3f5k��ʕ+,]�����ݶm׮]�V�Z6�jժq��]9�<���W�l`mm��ѣ)_�<[�la˖-�8q��Ç�ϪU����*�'�����7����000��ի̜9S9�*<<\#CCa�o׮���lذ���"""011�v��|���|��J\]�t!**��[�����飏>�i�"##�}���cu��5�-[ƭ[�غu+���j}���2u�T4h����Y�t)���g���J]Շ��z:t�U�V�s�N�t��S�vgΜ�f͚}���(udS�B!�o����`�bbbx��9nnny.-�._�L�ڵ��so����8)w,9���+��Բ8
!^�.ٙM�:�^��Ç��ckkˆ
022R��ʈ�:��e,--y�����:/���jsn��5���j�����>�d�ԩ|��DGG
d���駟ҵkW�t邩�i�ŖSa�ҥK��c?~��R�E�E�9fa��u�u�&�3�Rmr�e�����߈���ĉ������U�������x�6m��M��͵����������=�ޜ��'�h-W�w�ҥ��[q~��]R�bE�������2d���B����3d�&M�����+m�B!�Ez�p�<x0�+WVҺBv�W+++��ȄB��C�>}Ծ�+����?������ؘz��1r�H�~UV�;�5j`hh�￯�6�-C�СC������TY�����٥KeSd��߸q#666>|��Q�l��ɓ|�0�;::�l�2|||pss�~��$$$ĤI���*�K���ٙ��]��.55�K�.aff���es�z�F��<�j�� IDATV�k�fذa�8qB#Vwww5j���1vvv��
U_��~��v��IRR��΄����������Fkkk�>Te9OiB!�B��M����IMM%==��;$��?�����; �XΜ9���'Nd„	,[�L�S����Z����p,,,����lٲuT
�G�Y��й3��6�x����;[��}����/زe�ZV������Y���={R�^=�_�^d��T��������������*S«(Lܺγ���sFW��U��G�>���
...|���ٳ�?��S�13��+��!���r�sR���Ν;@�Z��^�P���rU|9�$�8���=z4����օB藷�7���̝;Wߡ!��N��p�133c�̙�;���':/]��'�B�ݽ{��u몕��޽{@ީ�oݺ�Q�J�
�O�*L��?8��￙?��M^v"Ya�W�Y�&5k֤{��<���[��i�&���?~<]�ve�Ν����4jԈ��8233iԨ��i�/��?��@��S�cu��}�s��X�N��A�����ٳg9{�,7n���?�s�Δ(Q"�/h�Ǐ��SN�2U!D�Jhh���B!D1�Zķb�
>��#�ż���5�rg�Pe�x-^�ӧO�>}:�z�RN9�ѣӦMcӦM����ָ���]$%%���#��I\�x��c�b``����5��9Frr2)))�U�V�:u�]�vѬY��ֿr�
M�6�k׮�_��^���#?~L�r�4ڨN��~Na|���|���ܺu��{�r���9•+W�v�_�5���E[a����s��I~��'���
|����93�攕�����ZYZZZ��
�ͳ���sF�Φ��lp�S��{��F�T�P��u�*
�0�j���#��S�z��}������gm6m���AZ%��U�ym)��#Ļ���ƍ������B�U�X�ٳg3~�x�|N/�B�pQ�>��#<<<X�p!��+?�B!�ț��=U6���9�ޘ���?murӖM���"U�9�[q��u*W�LӦM�Z�*���|��7����
"--�����LLL�֭�6m��ٳJy�2eh߾=���W�^����@��:��l��;�zN�7u���/9���#
6��ɓ�۷�˗/����ׯ�۷��wA۩�%�*�2]�W��3��ݻ�;!�B�a/�l��`aoo������o,����`�߿����R֯_?6l�@pp0z�N�[[[bcc9v�;v,p���4\]]y��	�g����%Ϻ666���O�-^ڷ��+K�,aŊ�7N9)>/?��3IIIj����p��ibbb�С�FU&U��ƣ�jժ��_��_�}�v�v�,�/��
�����˪U�9r$
4P����J�ƍqvv���7�k�&>>�~��~����А��L�<y����ڵkEwN�g]��9�2/^� 00�>�&?�Ӆ1b��5�<�����2s*�|4hЀ#G�p��i���5��;���;.$  ��C�j<'����#((CCC�����ӧi۶�F��܇��8���.���૯�b���yf�B��yxx�رcٵk���B!����u:ssscѢE,Z�H��I!�B�ʕ+p��e���?C�)˗/'<<\�+,,L��O��o����j�<��ŋ"�f͚�޽[k_�l!�?��ڵ+&&&�ܹ���8

iܸ�K�+�J�*p��%�r�Ϫ{��ʕ+Z���R�tiڴiÜ9s�7oݺu#%%��k��SAکNBS���IU�*��	!�B!�<�f��M������̢E��ܹ3t�҅ŋ����ч��=����mۖ�#G��gdd���K�֭i۶-@���S�N�e˖�iӆ3f�����޽{9r$NNNJ.T6��W5���<y²e�pqq�y��t����ӕ:��������v�Ν���3eʔ<cINN&,,��M�*B������i�;KQ�T��Ν�5�Oxx8t��I�|„	�;wN�J��6m��z�j�k���P�F
���?�}��$&&ҷo_���ܾ}��bhhȄ	���>�___��<233���:_5j�����~�M㚶lE[a�>��	&���3:u�Dll�Z�s�����#�/_N���=z4;v�ٳg�k׎֭[��/[�,111�Yܺ�3����tQy��]L�6��~�
[[[�t�o݄��qm����O�>}鸅���?��E�i��������֖������4:t����[111t�ԉ��tF��g�E�i��x���гgO�k��R�����cffƪU���B����X�t){��a�֭�G!�(6$ÅB!�:���lܸ�~�����ԬY�k׮)'������u�V���{�J���IJJb���DFFR�~}f̘��E�g\\͛7��۬X�B)W�F700 ++�{��aee��:u�…����<y�v��aee���Ϲp�k֬Q�̩\�r�mۖݻw���E�ڵ_z�6M�6�Ν;2f�lll�v�����+W�T�+W�(���<-񫯾�����Ӻuk�W�Nbb"��u#����Q�<��ݻ+T�Tr.B?K�.%44T�a!�o��2ቼ���0t�P�_���%&&JLLAAA�����Y�x1���j�
 {�ޖ-[��W�ZE�*Uشi.\�O���_044T�v[�b�Ƣ���D���HJJb��ٯ|����9R��O�

">>???

�2e
gΜ��ח&M�P�re���R�JL�:�_�U��v��ɓ'Z
:::��ݻ5C
!����˗/��ѣt��ooo6lHtt4aaa�Y�ccc����6���,_���
�nݺ�f�5j���S�reƎ���Ǐg̘1|��jmiڴ);v�A��?��;R�Z5�?εk�رc�-�xyy��V?j�(�-[����ѣ�����ڒ���ԩS9p����|��W�<������LJ޽{�����H�%�t钲	$�	�E[a?�>��������8880p�@���G�ƍiڴ)�ϟ��ˋ��@��������1�lْ���Npp0���ܹs��˗�����q�:ϐ}�Jrr2[�l�{��dff晱�M>g򓑑���ɩS����c��ݘ���z��|�˄��			L�0�3fP�B.]�������z���F6��
3Æ
c����޽�޽{3g�lmm�z�*ӦM#:::��|}}�����_qtt�����ߟƍS�L=zDll,��������������M*QQQ��ۗY�fQ�fM.]���ɓ9r�|�Ff��|)�s_�w���C�aŊL�4�Yz�B�9�Z��_�~|��7t�Ё�%K�;$!�B�dÅB!�:�;w�ȑ#ܹsOO�|�v�ޝ�'Or��&O��v�D�<X��Ϗ?��C���營���7nШQ#,--y��1cǎ�bŊ,_�\��?��c\\\���d�Ν�ܹSc,kkk�Q��⢤	ն1� �u�Ɖ'�w��ɈVVV�	i9�)SF�q����cǎ��ݻw'00�U�Vi�~T�^�<�)h�&M�p��)4�S�*W�9B�9nnn����;!��


�����p��)%C�S�׭[��שR�
s�̡nݺ\�p��ӧ�����5k���P�f͚i,؋��gÆ
T�^�u�����vvvl޼�ʕ+�v�Z9t��nÆ
L�2��]�b``����1b��7��Z�~=.\�A�L�:n޼���7111DFFҽ{w,,,�5kxyy�d�����2�X�=
@ݺu5�W�=zT6\�U�R���Pz���޽{i֬�F5j�����u��9J�.�gߪ
~�j����www�͛Ǽy���5oޜ)S���ըQCY�|���<-���ŬY�����}BBB�ݻ7DDD�]/Q�!!!T�^=��?��\�xggg��U�Ta���%��<~�=o�6m��o�e޼y噍B����ߟ9s�`dd��O�6�]�v���@�V���2|��"�[�y���8@�޽���6����LN/۰T�ti~��G��"�L�4��Ç�b�
��.ӧO',,��W�r��I�U��o_��6n��g�}��͛ټy�Z��� ����Q155�_~a���,[��5k�(�fdd�رc�?>%J������1b���j�+W&""Bc1`q}��/ĻhԨQ,Y���۷����p�B����K�:uX�`ӧO�w8B!���q!�BK������,Y��3gҦM,,,022�F�ʇ�&&&J]sss�̙C�Ν�X�"����.]��M�2w��Be)(�>���K)Y�$&&&�����_+��رC�W�R%

y��y��0`���4mڔr��ahh���	5j���,--5b433S�W-��U�R��;w.:tP�.W��:ub�ܹZ?��<y2M�4��Ȉr�����Œ3��v��1j�(>��LLL011�jժt�ޝѣG�OA۵hт�%Kr��i�>N�>�����vB!�����W�zY�6�����ӓ�
bbb‡~�ԩSطo�F�h=yʔ)ԪUSSS���x��S�N�z��(Q����c�ݡC�8y�$���cǎ|���̟?��Q������7vvvQ�fMfΜ	d��ҴiS��܈��e�С�>}WWW�숹]�|@�BD�ߪ�:B�׫S�N���1d��V����	eʔ�}���޽�Q�F�տv��c2��ұcG�{�=LMM�S�s��a���ZOAmР�ϟ'00�:`ee���	%K���Ύ#Fp����*]�v%66�`ee���1VVV4�3g�н{w��CKKK������C�z�033���[[[Əϙ3g4^�26]?###f̘��7���oiժ�˗��Ȉ�%KR�zu:w��…�1c%J�`޼y�l�R�{{{�=���e˖��Ԕf͚�}�v�
Vdqf�����С�J���ؘ��?߹|Sϙ�S�B�9s&			wذa�]��F�Q�D	,--i׮۷og����ⷀ���W��hѢqqq4HiS�~}~��'\]]4�������d�.]�Ĕ)S������###�{�=�5kƴiӸz�*�}�]��-z��́�����ؘ�5k2q�DΟ?���i�/�ϗ�<��x������d^BQ|T�ROOO|||�y��B!�� �sͫNPSu��9��B����P�nݪ�z�/CB�b�gϞddd�d�ƍ��\����OF�M�J��f��9}�4�����ښ�קO�b�{�ƍٲe˖-�R�Jܿ�������GNdŚ��
K�,QN���a���2Dϑ�>���U-r�,�B���z�m������e�B�U
�9\��A[VGGG���9z��"�gϞѢELMM9v�Z�cǎ�m�P���CU����F�*�0n�8.^��s���U�E�<{�,�v���j�K���4h			ԬY����k���888����1?��111!:::�8D�+�O�x{W_�~ݼy___.\��l@B׮]���;;�׺�R�5D^�����Qeڻr�
����G!DϞ=�aÆԫW���Y��!�ze��:V-�B!�(j�
"--
www177��ݻ�^��:u��9·[ZZiii���O@��^�Dݺu�СCl߾]Y��}�v*V�H�.]�������Ԯ]���IOO�C�$%%aii�Ν;���-^}��޽���9~�8����������'����5�Ի� �_&<<��Ǐ�v�%!DA�~�)��#����<���h^�2��l����//^�jժ|��'���P�~�"}-|�"��Ȥ�Z��~Ue�:B!�z��,_�\�a�b��ܜ�O�r��jժ�q}ժU|��Go:4!�;�K�.T�V
/^��p�B�P�D	�-[�g�}��ݻqvv�wHB!����7779I!��U�֭ٽ{7�V�R>�Q�����y�hРA�5jԠM�6z�FJ�,��ѣ�7o���d�����?�yij{!�(
�Ǐ��E�`�$%%���ā�q-^uί\�°a�HMMU���ӹ|�2�/_f۶m�^�Zɜ$��̙3����q�F����۷/vvv4j�Hߡ	!�������߉���Y�fJy\\VVV�=Ն��� ʖ-���ו����VVVܼy�m۶螖/_NBB����…�����7��ۦ|��$&&��cʗ/�v����J!�B��5kƁ�۷/.�Y�f�(Q�7n�j�*,X������mehh�ȑ#�?>s�����L�!	!���ٙ�ݻ3v�XΝ;�����CB!��7\9r��K�u�B�wHxx��CB�������Ν;<�������ҫW/ʕ+���j�ʕ#%%����3bĈ���.�W����Я_?�ի�稄�,��"""���o�Ndd�l���U�|ѢE���ҬY3ƎK͚5�����ŋ,Z��K�.�����ٳ�(���U6=}���ӧӫW/ep�=�6m�6m�څ����k֬��ۛ9s�(�͛@�V��X,��Ѵk׎�ׯ��{���D�r�000 ++�[�nQ�Z5��nӦ
k֬��ӓI�&Q�V-=z��������'  ��'OJ�F���Ã
6ЪU+�6m
�5�ڵk����͛756VܼyS�#�B��âE����O9s��~���u|||prrz�	!����̜9�������B�\/^L�z�X�t)�Ǐ�w8B!�^���[�n�i�&z��]�]!�r�6m�wB�w���!�;w�s��坤Z`��
y�\B��9y�$e˖e���9r����������;�wʹs��;w.����4n�oooz��#G�b����quuU���dž
���C��	!�	̾}��u�C�Q�V�Z5����ɉ��(������Ҹ~��%)[�,>�G�XYY�m۶���_p�Ν;ǀԮ�,Y�q������̙3177g���3s�L���nj3ظq#ZciѢ$>>�&M�����
,B!�x5M�4��,Z��]�v���s*W�L˖-;v,�S�P�}�����_6\!D1�0q�DfϞM����\���CB!޸"�p�R\�	!�'44�����;!�B!���?���ѣ���P�F

D�N��:���2a���씍jO�<a����ٳ�?���
*бcG���155Uk�޽lڴ�K�.���F�
prr���ssse��c�2�2@dd$���t��333:t�@XX���6L�n~����.]ʑ#Gx��)6664��S��ŗ;޼�C�����Y�x1۷o��ؘ>}�0r�H?~���9t�&&&�nݚI�&Q�T)�ς΅j���0/^̹s�(Q��ڵ�믿���,�9���$00�ݻws��=LLL����[�nt��]�˕+�����
*ժUS�=99�.]�P�lY�l٢�M�֭[��у*U�Q��U���	d߾}���_T�P��m�2|�pJ�.�qG���LJ={�`jjJ˖-3f*TP��s?�m���LXXM�6�R�JJy�ʕ���',,��baa�BDa2�XXX�ʕ+9p����˗��O?eذaXZZ��H�M�8���>̋/�U��ƍ�q�F�0a˗/'11���t��(]�4AAA�Z�����s��}J�*E�&M9r$��������0k�,������fҤI̘1�Ν�5��>����Ç3h� ��>L�ҥi߾}̘B!ޔ���%K��5���,��/�x�F�E��͉���y��G!D.S�La�ڵL�<��k��;!��{m.�B!�B���Ç<x0<P�����ŋt��U���ŋINNV����3r�H.\��Թw�AAA������,�_�b�W�V�/11���0����={v�q�2d/��& IDATHؾ};�r...����m�6���100�'����������۷�:�.]R6[�
___�l٢��j�*�T�¦M���LKK�_~��А3fj.F���Ǐ�>7o�Lff&���y����Ǻu딟�?���9�<���j����ݙ;w.Ç���?�e˖4h��>-,,�۷/AAA���8;;+�:@�֭u�=%%��C�r��u�Mbb"����������Z����WNFOKK#**���8֯_�,.��3o�v��ɓ'8::j����HLL�w�gϞZ�B]�!�L�2L�4�I�&����[XX������Õ����eLKKK������<�̝;��s�j����-�R�J�����ի�s�U�T�Ν;���1b����B!����&M����/.��277g������www�`*�����U�B!�B�w�ڵky�����c˖-:t��?���� ��5k���ѣ����s��4h@hh('N� <<�F�Cdd��vÆ
@�i@G��رc�\��>��J�:uJ�Y�qN�<�ݻw����V�Z���agg�ݻw�\����BBB�}�6���M``�ZF�Š��gÆ
;v��#G�'k�y�f�=�,4UmF(�\T�^�-[�p��Q��������\�dٲeDGGs��!�L��ƍ��������Ғ�k�2l�0>��F�Exx��I����ܜ5k֨�����V�;��u�~�:U�TQ�իWcmmMBB��8G�a�ҥDGG���5w��e���J]�?���;z�(u����CU��#���0x�`*W�LHH�R����cdB!�B��l��ф�����;!�Z��ٓ���3f�^�x��p�B�7�������Ԯ][�C��u�V���IJJ��‚�����G��lٲ�Ƕ��
��u
���@�)}���sDB!�5QQQ�o�^�a!��#G�0q�D�U����g��������={�����޴0s�L�w�NTTݻw��������ŋ�ر��W�r��I ;KA~tP6���ѭ[7,X@DDM�6}��{zzҰaC�4i´i�3fL�1�̔)S�� nnn���3�N�J���8p ���J������I��Ƿ������o|��椤����qrr�W�^���Kk}�i�/^�ĉ���r��N�<Ixx8+V��bŊ�)S�^�z�n�:�;���#��ɜ={�R�JѤI�b�}��L�:�����}�����1���
6��ӓѣG��~������]�|@y�s�Q��Z!�o333fΜ�رc8p ��;�ҥK)Y����B!�BW���c�ĉ���E�YW!D����iذ!����5J��!�o�?j����9x���gϞ����޽{����o:ġC�h߾=�f�R[pRc7gΜ��Ϗ�7���E߾}����Q�F�M!�;$##����C!�?�j�{N����޽����T�Unݺ�����			�<`ܸq\�xQ�^VVV���2Nrr2���`ѢE,Z�H�����III�t��j����͛4n�X�<�����9�����666�fff�t�m}ZZZ����o|_�5�f����?~�+V0d�����]4Z�n]�֭�_|Azz:k֬!00����dolٸq#���8::r��1^�xA���16V��e�߹s��d���1S=�srppP�Y����۷_�����ÇXXXh�*S�B�裏���`�…@�I�E�{�B!���effƗ_~�ʕ+�<y2FFF�I!D.u��a̘1L�>�>}�P�|y}�$�B���
�Z>w�\���K�ҥqww�m۶��_�����?~�����ك��	�g�.����拧O�2}�tz�ꅕ�=z�`ڴilڴI�!�BWK�,aɒ%�C!�Pc``�S�ܛ�_�Q"g�
___.^�HժU��O����~���.��8;w�$===�Ϟ=c�ΝY�:l ����[VV�r=�8J�(�����0�6�b�M[��>����888p�"""8{�,����_��ѣGӳgOZ�j�ӧO����R�Jj}���2x�`����ʕ�gϞ�����Ç���"v�CI�M��9羠��[A۩�E��*��O!�Ń��nnn�C�w���$�B�w�ȑ#Y�d	۷o�[�n�G!�^^^���0}�t�����B�F�mÅ�dQ}o:���#**
KKK����N�,W��:u��WWW����ի
6�_��Qpp0������U)�ׯ6l 88=F'��]�v�Z���/���֚��,�����������ի�s�VVVܼy�m۶)��ZpDٲe�~��r=##Cc!|aƉ��`�ҥ8::j\?v�cƌ!22Rc�EnU�V�ڵk�={��?�X)?{��F]���HMMU2gh�6�t��Weii���...\�p��{��v�Z/^�l�[�.���l޼YkmU����O?��ƍ9v�����h�B�������߉���Y�fJy\\��9:w���ę3g��t�m
Ү|��$&&��c���?~��B!��Z�lIxx���B!�(R���8;;���/.��������LJ�C�2l�0���B!Ļ(��"��xyyѶm[�7o΀ؽ{7������<y²e�pqq�y��t���4s���GDD�
R�l�S�r�0`?���F?Ϟ=c֬Y�lْ�m����Ń^:��{INNfѢEt���t���ŋ5N�T�MHH��Ã�-[�駟2o�<�>}�����$  �=zмysZ�n͗_~�֭[5�
�iӦj'qV�\{{{���HNN�:?B!�.T��B�>QQQܽ{W�a�UT�.\Hbb"iii���boo����mڴ��ӓK�.������/���{���9r�F���h��ӹt�ӦMSʓ�����T{��-�ǹz�*/^�>�y��Zcn޼9իW�…\�z5�k߾=���#>>���Ο?ϼy�4�6�lݺ��O�r��u|||��0
3�/�mλu놽�=?��O�<�V�Z����Y'���do�Y�`			������¡C��8q�Z�*+V�[�n�ܹ���$�����{O�؝����ܹsdddp��9�1Җ5c�ܹ��y��������t���
ڮv���6��*S�B!�B!��ѣG�g��\���P�B�aРA4k���f$B!�z�p����T��ݹ}��Rv��%�N��Q7==��#Gr����޽{������9�N�lݺu�1�lْ�K�*�=�4�|�m�@ZZQQQ��ű~�z,--��RRR:t��ɦ������CPP���jmF���������͛������???֭[����9�ϟ�󤦦ҿv��œ'O��z���HLL�w���J!���\\\X�d���B�w�ll�ݗ_~ɞ={8w�]�tQ�6lذ����/8p��ΝS6쫔,Y�q��)?;99���^^^}]�t	GGGʖ-�Ç�ѣVVVl۶���puuU6�f``���+���'22�����y���g�Ν����|���΅��[�l��������e�Jۜ<ooo|||46�4i�D��M�68����7�q�F���W�Θ1c4�
ĦM��#
b���۷�[�n1d��kժU�(��&r?���գo߾j���S�v-Z������k�~N�B!�eG�Q>�B��#Ż�S�NT�^�+V��BQL�|�r���Y�n��wHB!�kU,3\���p��m���	

"::���@��*�ׯ�…4hЀ��PN�8Axx8�5"&&���HN�:��9u����	���U�1����ܿ_�ڑ#GX�t)���amm�ݻwY�~}�c�n�:�_�N�*U��^�z5���$$$�f��6իWg˖-=zTY<��~�-[X�l���:t�)S��-�8z�(u���CU��#�B!��������3���P�n]�ϟO�N�^ھt����憕�FFFXZZ���Ě5k�N�8q"��Θ��ajjJ����7oÇ���ڄ	�R�
FFFJǂ��sv�؁��%�;w�7�.]�`aa��;x��y�������Ņ��{ccc���={6���J�q��ѫW/ʔ)���)���L�>��s�+]漠��y�=���N�:���bjj���
_|��f�Rk?v�X���prr�bŊbjj����F���T2��T�T)������ӧ�*U��ȈJ�*ѯ_?֬Y��@�ŋӲeK����T��
"  @����s*h��>�sss>����Ç)]���aE!����|ɗ|�%�mYYY�%_�%_��
		�?=B�v����5�5k֐����p�B�Q�F>�)S�(�ۅB�w��paoo_��S�N)<==iذ!�}��i�4N�ܳg���X[[P�fMfΜI��݉���{��yƥZ@al��Tdee��7�)S�(�u6l�OOOF�������ȷߜ���~�ԩS�ꫯطo�F�&M�Z�j@��AAAj��������BHHׯ_��ɉ^�zѫW/�~._�do�ȭF�ju�B!��]dmm���w�u��@`ii�7�|�7�|�oy���t��쌳���㘘��w��|cP133S۴���+WN##ǽ{��P��Z�S�LQ6���w^c�R^�9/h�y͹��...�������C�ꪨ�oV�^��5k�c~�eʔaҤIL�4�@�)SF�B���ܿ�x
ҮT�R����z�j�ܹC�*U�s�qqq�1B#ۧ�)<<\�!�Vk֬��CB!�����̙3	

-Pb!��1g���Ù={6.�w8B!�kS,3\ܼy�ƍ��7i�D��[�������/�&����|�Re�P-�˝;w���{!E�F��}�v�}�5Ƈ~�V����w�j����Q�W�V�����}��ה(Q��Ǐ�d����KPPiiij�<|��^����LUG!�o��^�}��O�>�\G�/�9<u����6�~�����/���E2v��Ǜx<_���a�Ν�������Ν;_�?!��Z�n���=?��IIIdffr��
%SA��E�<y���~����9"�<x0�+WV;�3$$+++��ȄB!�B!�>T�P�޽{����P�B�|��̙3��K�r��%}�#�B�6o,�E�U�-�;=3w6	m���e��)%%%��7�޽{�ݻ�/��2�z��A�-"ɝC��аh����@������qvv����ٳg�g����=��={�����LR�!�o���/�N���\�B����q��q��$N�:ũS�pttd���j���B�y�x�"���,Z����,&L�@�5�S���C�ԩS'~��'|||���Q�V�lY����Z�n�|oggG׮]������1s�LƎ�l:���d�ҥ�,YR��	!��$.ī			���M�aQ�\�|�ڵk����Õ����@!��X888p��1��B�<>���@ƌ��ݻ��B�Z��
��Z�*׮]��ٳ|���J�ٳg5�ZYYq��M�mۆ����c��ٓ��(���iժ���u�\�ºu���9�;wN�@p��>���b�����{\����$��T�9��̡LK5����r�!Zh�c�5_9�J6k�v
�F�q��!�IL��ä�HJ���u}�����
���^���z�_﫫��z=_/K.\�@bb��މ���>x�󅓓NNN$''�k�.V�ZE@@�*���ܜ��t���077W;?++KUG!��Vqɩ�r&..CCCH�.]�[�.���=z���H���/�U��ĉ�Շ�LJ$_@^^�}����ԫW�w�}���@d�����M�&Mؾ};�ϟ��4hЀ��~www��A��կ_���,������jժ�Ig������Tm9���u�S!��M&�Q>����>��S��ݫ��ފ�;!!��� ֮]�B�`�С�jՊ:<�8�B]�ҥ���|����p!��XժU	

��ޞu��1x�`]�$�BT��ق������p��q<x@RR,Ш۽{w|||8y�$>�ƍ,Y�kkk<<<Tu�*\�tIU־}{���Knn.���DDDp��U<x@zz:aaa�7��w���{�i}C���WgBB~~~��ݻؾ�֭~~~;v�p��1�u��ۗ<x����kkk֯_Onn.-[��U�V����Ut.^��ц�LW��!�x9
2DVoϭ�'O��������׏��룧�G�:uppp��ח:u���ӧu�eӦMdffҧOUY�>}���dӦM:�L�痞�...�����۷���x�n�ʌ3$��	DEE��~�,Y�L�Q��Re����7�|�7�|����u�B!�x��ݻ��}��]f͚ŠA�������gggfΜ�ݻw�q�B!D�������z���CBQ��]�2z�h�M�Fnn���B!*\���bĈ����\�p�1c�[w̘1�ٳ�cǎ1r�H�cL�2E����)���8;;caa�֭[������c�Ν��O��ݙ5k�����4�l۶-C�-��\]]ٽ{7�.]���M�X�&M4�J���???����W;Vp�Ȯ]��w�^�?������ǁ�%|!�O�͛7	�ȑ#���Ѹqc�����ŋ�U�����_9p�������boo����	�-bժU�>}}}}�~�mF���*~Yۜ;w.�-�iӦ̙3���8���Ο?Ͻ{�055�s��>������*m��Q�q(�}(nrrrX�n�֭[���ҥK���a�cPT��0�/_΁��קS�N�1SSS���2��n��_~�СCܻw�.]�0~�x�1ܽ{7NNN4j�H�8שS�~���Ν;UI�����LJ�q*���ޗGy�e��999DEEѮ];���T�u���7� **�~��Q�V�'�!�B!��y�ܡ�2&�
u���ddd0l�0U�����_

���S��	!��1t�P�M���������u8B!����O�֭��/��u8B!D���ŭ�X�fM���qrr��ĄjժѪU+�/��ի�����T�Zccc�u��ʕ+�ve�6m�5�jժܿ_U^�zu���	������055��������kjԨ�5ހ����V����g�����Ojq�wA�k�&44�!C�P�~}�V�J���>|8+W���ظ���9;;3{�l^�u�W�N���i޼9cƌa޼y�z�{���А��X�6bcc122R�<"�B��ݻw�={6111ܹs�p��y�$�����7o�7o&##�p��56l؀��?�=�8g�ܹ$%%q��=�ܹÎ;X�z���j�*rrr077`͚5��?�����Ç�~�:۷og����^y�/��ơ,���q���e֬YDEEq��
�8l۶�ٳg���W�W�X��={T����0k�,�ܹ��S�����a�̙DGGs�����ٷoK�,��ԩS��&5E��z�ĉr�_���}yT��4c��~����LסC���믿��Z�B!�(L�@����N����#666��Ջ�S��o߾�ҷ��u��Et!22��S�2u�T�Dz!ċ��ի̙3�w�}�
FTT�F���l�����틍�
|��(��Ξ=���'vvv��ٓ�����#~��'���y��qpp`�رj;^|�,�����ȑ#����:�b*�u�wvv6k֬�s��j��5l�kkk֬YCvvv1#.�B��j֬�رc	��G!D16l��ٳ���9����B!*T����1{�l����4����>�)���#���Ewpp����̱֩S�؉�E��-�N�:x{{���]l{E%�h+wrr��ɩ�jժ���+V� 55U�sjj*���L�0Am�c!�B�~��7�^�J����4i����O�&00���L��[�n�ܹs�l��� IDATْq��ѤI�\�Bpp0IIIDGGӳgO�s,--�����ܜ
6�a�<��ɠ<m6nܘ/��R����Vwww�u�F�*U8s�s�����ޭ�<��GI�P��P�8lٲ�˗/��q��9���;.]�ĦM��V�+�#G�0c�ڵkGJJ
���ddd��o���,�Xnݺ���6lȤI�h֬�O�&((H��7o��֠A��UR�E=>
+��t�
�Q��xܖ�&$$��k�i�߼ysUI&B!���O?e�޽��޻w�ٳg�k�.��7oCLL�z�b޼yj��TDߕMBBAAA�]��B�СCiժ��Di!��/33WWW�_��*;{�,�g���Ç����;w���G��������NDD��񄄄h|65a���������#Պ�AAA�$%%���DNN#F�(1�������*��?������V㘭�-����8�L1	!�/���0`���BQ�I�&�|�r�N��ƍu�BQa*e…�����L�>GGG����x�".�cǎ:������ʶm�W%|���caa�ȑ#u�B�]Q��GFF����iժm۶���???���O>Q}H��+�������_bcc5&y��GXXX��a�rrr���>�@�d�z�j
)))���r��E�?<ޑ�8��<J������lc„	�6Z�n͸q�����N�pwwWM�iժ�Ǐ��/�$>>^�fYƲ�h�Bu��ƍc��j}+w4�V��?�
��e��4�3�%���mi�D�Z������2YQ��A~~���B!��u���:���޽{������k�.���pww�G�4hЀ��,���駟رc����ݝ+��ʖ|q��]f͚ŠA�T�3����9s&�֭�f͚:�PQ�V�Z���i۶-_~�%u����o�e�ƍ����V�^MJJ
�5b����iӆ��df͚�ٳgY�r%���jm7mڔ�s�ҠAV�XAHH��Ѫ��
6��w�ammM~~>QQQ����v�ZF���ÇU;Kh{�|��		)s2\i�������@�6m4�U��߿_.�B���7oN�޽����%�B!*9}}}�,YB�޽����y�t�BQ!*e�E�>}X�~=�������355�XYWT��5k2w�\>��F�<^900G'�B�ϕ+W� �} ��!k�ĉZۺt�FY�ƍU_תU�G�=Q��ݣ�n޼�…�V�S�6�����ǣG�x�������S�+��q(�}P*<W�^'hk###�ȶJҾ}{��_�u��J�JeKe�ʤ�±dnnεk׸v�jB�6��333+W��Q�1.��+��F�d���V�1Q�r��� e���x�u��E�-�B���*��&�>K���DEEallLHH͚5S333�O�>���0l�0���4ho����~�BCC���PK�>|8���������OF�<XR��|�ܷo�}�M�4���G���:�|l߾=3f�`�ĉ�޽[�9���[��#		��۪ㆆ�ܹs���pRRR�֭�
bРA���ȑ��y��׭ͩS���	%�)�(�!�/#///���ǩS�4>�BQ�8::���̤I�HJJ�F��I!�xb�2�B�f���9�<��ߧA����۸���y_QzVVVxzz�h�"���N�:�8*!�/���������]81�J�*%�)L�n*�͂�:������BÆ
�ܹ3�7�E�L�:�ض���ڵ���"33S��P׮]S�+��q(*�����h��_�?e�M��Z���6&��e,�ڍ�p?�8��ڵk������~\\��~y�ōqi�}Y��禰Ҍ�2^m�,��k�ۤI��4i���B!D%s��uٷow�ޥy��=�3f��sssY�b;v��ڵkԭ[���www�D܂�&{l޼�ѣG�%[dff�ȑ#	d�ƍ����v��ߏ��?;v�z�����1i�$�֭[l�ڒN���	f���ܸq��u�ңGƏ����F;k֬!  �cǎQ�F
�}�]&O��ڍ�ѣG��������>͛7���j+�fgg�f�:w���aÆX[[�f�F���5��\���ɐ�����ʝ��Լys����ƀ�{�'Of޼y���Ǐ?����...�^\���풔��������G�,S�B!^F�>���*?��K�,�u8B!J���ҦM���[�O���p�B�'V).���pqq���EסK׫�=-���!�x�5lؐ���S�N�GU�m��z��q�����{�իW!�WD�G���/�T}8|��e��j��_�_y�����믿�n��Zu�,�r�R�~}RSS9y��j�'O�P��*U��P(�{�.���@�"�>}�7�xC�͂�l�e,6l��˗9q�:tP��9sF�n�^����a�ƍXYYi�.�e�z��Y��K�,c�4U��Mi���Ą�ׯ����������٪:��7b�"""t�B�̔��* ''www��^'O�T%[t��}<<<HNNV��������	

*6Z�����ؘ���$!!A��…ٺu+yyyDEE���HXX��udiܹs��>�Hm����t"""���'$$D�Ki„	�������_y��j���� V�^�����ORRIII���0b����rss���Ո��֖��x���OX��B��gW���I:(n����yh���������͛9z�(?��aaaxyy����-
.r��}��Orݲ��BQ<===�N��ŋu�B�RhҤ	ӧO��חQ�F��3n!�����	B!�ű��e�ڵ,[���������k�;w�e˖i�}뭷شiK�,ᣏ>�iӦܾ}��~��-[���o0gΜ2�_�m&&&��os��e~��GU��;w�S��*� --
�2�okk�?��Cdd$zzz���abb­[������_O�)��܇�t�ܙ��T����4i͛7�ܹs,_�x������1YYY�ڵ�^�zq��uU=m�.]������еkWU������k֬!88��'ҺukΟ?�j��֭[���@LL�g�f�����`bb�͛79p��ׯ'//;;;^��rů���$c�4U��MiƤY�f\�~�+W�h$V(W�,�J����Oxx���B!����6mڤ�0����\�|KKK���KڴiCRR3g�$##C�nXX��ɴk׎3fмys.^�������lٲ����r7���NWz�W4�طo���t�ܙ'N0s�L�\�BXX���E�]��իIII�Q�F̟?�6mڐ��̬Y�8{�,+W����S휦M�2w�\4h��+		!::Z�p�a����;������'**
֮]�J�ؿ?�}W?e���%�B�L�
���9{�,m۶-����%.\ 11�.]������C�bll���NNN$''�k�.V�ZE@@@��o�����v:{��F��^�6��椧���������1e\�r!��e�����B��g�}Fhh(����y�B��$\!��ӷo_���Gjj�j�GQ��C�8}�4���ڱ5j���Z�+�ͷ�z������

�8~��y:t�J2��O�W���}���ٳ'���=z���0���4�z�w�֭[)���r�ҿ<HZZ3g�T;faa��~���s���ܹ������@m����ԩ�W���y���Uߗe,���G\\.\`�ܹ��]��&�4a����9p��V�bժUu�z�-<<<����Gae㧩"~nJ3&�:u����Z'7('C<�$�{�f��C!�x����_�e�AI�&::��o�:ub�̙L�4I���;��������^{��s�2`������"��\��Z��߂W�L�m���ӧ�v�x��7����ˋ��h���h����3c�&N���ݻ5��V��7b�BBB�}��긡�!w��!<<����u�ƠA�4h�Z;��6m��2�,�$
!�]�ve͚5,Z�???LLL$22�ƍ�q�F�u��ʕ+���c����mۖ��d,X���}���߿?���L�>�>}�вeK���_@sw�B��K�J���Ԕ��L6m���IKK��߿�׭��֭[����ŋ5+�+y�nݺ��!�B!��b``@@@���xxx��5�BQY��B!�EFF�����s�Υ{��Ԯ]��U�ҬY3&N��xjhh����۷/���COO###:w�o�V���6ǎ���-���ӢE&O����}�vU���룧�G~~~�������裏hݺ5�����:t���///�T�R�q(�}(J�Z�������===����ӧ����UF����#FFF���ӡC�"�>��s:u�DժU133��ɉ9s�񡯯ϼy�ptt���}}}lmm�0a������2e
���XYYQ�vm���066���ooo�M�F�������Ǔ���T?7���]�b``����q�������jҚB!�x�('�v��Q��S�Nu/]������֪�$m+�T�~}��Ҋ�����V� ��	�/_.�͢�h߾�Z�r�%�7o�\����1�=R�M�<�5jǷ�~�СC			!//O����Lj׮�ч�LYG��;v,���;v�>�;;;�|�ƍS�suu�I�&�����憍�
nnn\�r�&M����V澕:�������o��Z���󽩩)�����ׯ�6��,^�{{{����fY�[[���;�?�Ѯ�L&'	!�B!�7�W�^L�4��:!��ܞ�噴'�BQZu����?V+�v��-����puu-q��<��?i��j�b���Z�\����V������.z��M�޽K�[\���K{�j_���[�����{��522b���Ŷ��Wڱ�Y�f�bT�ʪ4�k{|�x-����w�%��$?7���5kҷo_6l�@FF�j�ZFF'O�dȐ!���ũS�*dӘ�6m����ǹ}�6�k��?��������Ux���Ç?q�%�r�
aaa��ő�����>���
��Æ
SM}�T�GFF<��;dȐ
�M!���σ�y~,��������8QН;w�=ޱcG���صkcǎ-�ޮ]�T�+�;�2�AO�b�Q*�@QX�U�stt��Ɔ={��y�f�=�?�@XX^^^8P�\m1+��!��g�7ya��愆�ā��ˣE��3��={��ծ]���P�.]ʞ={�q������ٓq�ƕ�oyggg�U�Fdd$)))4n�{{{��#�M���Ozz�jW��L�2===v��ݻw���f֬Yj;n�庵�ݻwo/^Lll,�G�Vk766###z��U��B!�B]�}�������
!�ϋ
O�(�Z�B!��0z�h���pww���CCC�\�Š+x���u��A����OLL����*���~�^�z|�:�N����Oٻw�M��w��g�VM�T�y�&111���ЫW/�͛W�;�"��:}�4�ƍ#''GUv��}N�:ũS�غu++V�кj��.!!��� ֮]�B�`�С�j�J�z�B��7n̹s�8z�(o������ѣu-,,�x�"[�n��¢�}
8���(BCC����E�uN�>��իT;gt��1��턄^}��2�biiɅHLL�K�.����D�r]<����	'''���ٵk�V�"  @�pannNzz:YYY����������#�x�XZZ���Wb�:u���퍷�w���z���\��TGGGK�G͚5�>}��"��溵�]�V-\\\X�b���4j�x�KQbb"&L��а�v�B�d!��dΞ��Z�n͔)S�3gÇ�^�z�I!�(��Y
K!��rpp`��帹�1l�0�N��?�����������}����^^^DGGs��5�]�Ftt4���ԨQC��	Qj{��}�6|}}ٵkFFFL�<�-[�p��A���O���,--ٱc_~�e��y���g����7ߐ��C�.]��� ..�}���l�2^�u���

z�q�“��ݻw�5k�
���KKK����9s&w�ޭ�H���P��`��?΃HJJb��u�w����'O���Çܸq�%K�`mm������r��K�.��ڷoO߾}�����ݝ���^�ʃHOO',,�q��q��]�{�=�	o����8Tx�^���ºu����ǎ�;vLu���%^!�����ښ��ד��K˖-iժ��;�r��/j��,��ݼ��E���JÆ
	W����caa�ȑ#u�B�lݺu�[�N�a!�KK��Ee���C�Z��1c��CB!ʥ�w�طo#F���f�/�B����9777,,,���%55���|���i߾=�
���L�!��>�ʬm۶6���P�N۶mu��Vbb"QQQB�f�T�����ӧ6666���(
ěo������رc��	�&&&T�V��;��燳�3����e��Rhh(6LU6|�p~��BCC����atB��1����.0f̘b�3�={�p��1�I�L�2E����)���8;;caa�֭[��$߻w��;w@@@�F?ݻwg֬YZc033ӈ�m۶:�ľruue���\�tI��R�&M4�J���???����W;֩S'��]�ve�޽?~\����@�>�O��:I;߽(j֬�ܹs��O5j[�l!00G'�%���E�a!�K)""B��J��Ȉ����Q�F1a„���T!�xZ*<�BI&T!
�xB�����G߾}�۷��Cy�U��o����4�wL*��STnW�^�~`���ܹs�f͚1z�h��飪�|888�iӦѪU+~��'rssY�b;v��ڵkԭ[���www�W���׮]�X�n'O�$//��u�ҭ[7<==144T{�Y��r�Ri�ټy3�G�VK�(��̌�#G�ƍU	�>��ߏ��?;v�z�����1i�$�֭�V�p��c���&88�ݻws��
�֭K�=?~<FFF�Y�����;F�5x��w�<y25k�T���ի\�~]�p�ԤIU����|�����a�����K�pvv�Q�Fl޼�L����JO�G�̟�IZZ���4oޜ���3`���]�󲳳Y�f
�;w�~����
bmm͚5k5j�k�F!�G�M�Y�&���Ý;wx��9r$�g�V�=jddDHH˗/'::���jժE�N����E���ӦM��'==����ʫW����?111lܸ���$n߾M�:u���ÀT;j��9s�����̌��{O�}Q}T�vmBCCY�t){���ƍ���ӳgOƍ���q�ƶ ggg�U�Fdd$)))4n�{{{\]]U�z����ŋ���e���jm���bdd��yD!XYY���ɢE�����HXB!�B������駟����_��ڹU!�x<��!�B!��y������+ׯ_W��={�ٳg���C���V?  ���lՄ�������Arr��NZZ!!!?~��� �$���+V�����Κ5k�}�6_|�E�q����G�;���Ύ��@4�-\�P�Rv^^QQQ$&&V�əw��ᣏ>RM�T^sDD��񄄄`hh�v΄	���R��믿���#|||Tu����e���|�����Ѯ];��ڪ]�6C�%$$��;w���:h�SI���J3�AAA�^�ZuN~~>III$%%���Sd{i��?������V�
[[[�����?8p��~��ygff��ٳ�����������:u*S�N-�MGGG��-�988���X�:u�x��2��-�N�:x{{���]l{E%�h+wrr��ɩ�jժ���+V� 55�F����Jbb"&L�})�x6d'�����EV�B<������ ���I�*U��ښ�+W2v�X]�$�B��^�U�B!�B�۪U��~�:m۶eÆ
������Q���^c���}(� IDAT��䈰�0���i׮<x���H:t�@||<[�lQ���/�0}�t����_��ҥK��+=���Ç��/K?׮]��¢�k�W����8�o�>9p�!!!XZZr����Š���իW���B�F�		��X�KKKΞ=�ʕ+5�iڴ)6l`�������V��?���cccV�ZŸq�x�w��㏉��T[�{Ĉj�L����/S�幦��`Æ
|��w8p����O��ڵk��oY�ۿ?mڴ�hCY��#�/���Y�~=�o��ѣG�?�y��бcGG�bruu�aÆ�������ñ��`�ȑ:�L!�B<-�֭cݺu�C!^X�<+�W:t��Ã�?��[�n�:!���^�.N�:E�֭u�Odd$qqq�����B!�BQ	�۷��>��&M���㣶�BA#G��z���w���������㤌�s�2`����0`�x��B��ĉl߾�3g�p��!��	�)K?�d�jՊ�P(�/h��骝�|�M|||���"::OO�b�-H�����Ûo�	@���1c'Nd����y{{��ň#		���m+W�>q��ȑ#$$$p��!"##����W�u��aРA�^�����[[[���9z�(�jբS�Ne�<�T��444�Ν;������B�n�4h�
*v�K{ީS���	%�5k�L��B�h����������_혩�)�Ǐ�Qd/��5k2w�\>��F���-[��@��	!�B��%<<\v�B��$""��ݐ����K"##�3gK�,�u8B!D��4	�~�){��}�[$�OBBAAA�]��B�СCiժ:tx�1	!��͖-[�V�B!�kkk�2�k�+W��:I_91]�ҥK899i���Y��ׯ_gʔ)�8qB������S�~}���HKKS%h�����_������ׯ�/_.6΢�h߾�Z�r%q�Լys�����<z��>ڴiC�6m3f���g�ʕ��_��W_�e֮]Khh(������_<|����~[#1����sM��ɓ'3o�<��∋������
�b'������Lj׮�ц�LYG!^4�d��۷s��y�߿O�
x��qww��PT+++<==Y�h^^^ɎB!�B!���gbb����1�ƍ�]�v�I!�(�K�p�w�^��s��]f͚ŠA������ٙ�3g�n�:j֬�L�B!t��Օ^�z�:!�x�Ibw�T�R�L��n%'Jܹ⫯��ĉ4nܘw�y��͛��o�jIJ�ӱcG���صkcǎ-�]�v��V8	A�p���Wb��Q\�����km���ޞ�w��1A�z�긺���e��̌����lj��U�U��sM�OGGGlllسg�7o��ѣ�������������]��ע�*��� ��===\\\*�*�O{� ]y�^���.�/�u���:!�B�'����ҥK�4i�w��u8B!D�t�p�\Y�E����P2226l��l�����/��������B�g�C�2	X!�N���A���ᅵ={��mۖ�m.^��֭[UI�EQ&���`jj
@JJ��4&旧��Ehh(����h�B���ӧY�z5�8~��1��Ax��W��0KKK.\�@bb"]�tQ�'&&����ڴiÑ#G���_���5�_�x�L,5j�ׯg�ڵ���_���ѵk�2�_�k*�x��䄓�����ڵ�U�VPd�Ei�377'==���,��������R�B!��[�&M<x���B��s�B�Ozz:
6�uB��OOO��[[[֭['�!���*�����{�nnܸAݺu�ѣ�Ǐ���HU��č��'3h+߿?����ر��իcggǤI��[�n��͚5k�ܹ�ڪ�
6��ښ5k�0j�(j׮]��B!�B�v�ʚ5kX�h~~~���Hdd$�7f�ƍŞ߽{wV�\�����޴lْ[�n��?����5?���9��w�%%%�/��BU~��m��̨R�

��K�.ѤI�2�Ӿ}{���˶m�pwwg������sss�_��Ν;Y�lw����Ӛ������y���IJJ����޽{��h���nݺ�r�J����?>m۶%99��w�(����9r�!!!ܹs�?��&M�p��}�9�7�|����իG���Y�~=
�����cbbR��sM������������ӧ-[�����w�(���nݚ��t.^���X�LRiݺu��C!�B<[vvv����:!�ⅳo�>V�Zž}��x�">�~��t�҅�c�ҷo_]��L(w@-i��Ұ���cǎt�ؑ!C�о}�"�=z���HHHH --�֊�=�jժԮ]�f͚ѳgO����\ئ�ƿ"�cE8q�+V� ::��gϒ��C�ڵiժ�z���ݝf͚Ux�˖-��ۛ�7oj�lc$����ƆѣG3m�4��}�9�B!DeS).�ܹ�G}���gzz:������a���p�B�n�
@^^QQQ$&&���������������1[[[�����?�]�R!�x�mٲ�-[��:!��Hcǎeǎ;v�>�@�ظq�J<̘1�ٳ�cǎ1r�H�cL�2E�}�n݈��b���̞=[���'Obkk���)���8;;caa�֭[��������c�Ν��_��ݙ5k���233c̘1jem۶e�С���Y���+�w��ҥK����kҤ�FYit�ޝQ�F���?�v�Z֮]�Q�iӦL�4I�|��Ѭ[�(_���J3�����������Z�N�:Oi��ڵ+{������?~(��!�B�g'""�#F�:!�:"�+^FFcƌa����._���˗���_�ӧ���K��%yY����}�v�o�Ή'ذaC�u�̙��͛�at��Ç�u����$&&�߳l�2��y_Dyyy|����O<z�H�ح[����'>>��2y�d����]|��Ə_am	!*�…y����U-h%�BTF�2�b��դ��ШQ#�ϟO�6mHNNf֬Y�={��+W���Y�
�>Qx�
x�BA`` �;w�ĉ̜9�+W�V!��߿�6m�h��,ۿ�$\!�x!M�2�?�P�a!�KO[��sssBCC	

����ѢEƌCϞ=K<��Ȉ���/_Ntt4ԪU�N�:���A�-Tu?��3<x@ll,>�e˖�9�����ڵk���eڴi|������s���2�P�zu������a�ƍ$%%q��m�ԩ������C����9s�����̌��{www�W����-��j׮Mhh(K�.eϞ=ܸqsssz��ɸq���'�|B�.]X�~=���7nܠZ�j�U��u��Z�j��.�S�k*�x:;;S�Z5"##UQ4n�{{{\]]������ݛŋ��ѣ�ڈ����Ȉ^�z�kL��i1b�6m�uBQ�DFF�:!��PDD��M�\�z[[[RRR���d�ԩ�������T�Z���ϳn�:���+���prrb�ΝT�V)��TZ-Z�`ǎܿ_�0%��1M�6U��<+�����͛7IJJbɒ%lݺ�ѣGcjj��sʋ�T����{��޽{���g�ȑ���ЩS'LMM�}�6G�!<<����E�q��Q�m�V�IEy��Z��Q�
�7o��޸��ѲeK]�$�Bh��^�)J*?|�0����8�|�Mڷoό3�8q"�w�.S"DI�O���|��o��プ�����ϩS���+k��
OYG!�x����agg��0�B�YZZ���WlmI�J���L�:��S��F�ڵ���J[���8::����ʕXP�N/^\lmqj�:u���퍷�w��5�E����`ccSl��=zx�:���^+w������KO'''������-�ҜW�V-\\\X�b���4j����T�0aB��**�e��A����iҤ���O�<?
!��%??_.���cǒ���;�æM�011Q;޺ukfΜɀ���g�޽���OL�8QG?����C`` 111������CNN�G����A�O���>��קgϞ��ٓ�?������	&p��9jԨ����)S��w�^�7oκu��ر��q333�}�]�}�]&N����;v����?׺c������ɲe˘2e
������B!��������$���t_�r�B�+<1�C���m!+Bff&�xRMa�2e!�B!�B<���ܽ{�e˖0j�(G����l۶���pU�Hxx8�9R��	!�v���B!�/��/������իW133�G����жm[��U�T)��«�>|���g����hܸ1�f�̙����Ʋ}�v�իdž
4�-
j׮���xxx�l�2����'O�`�v��ɵkרW��z����G����R(:t��?��```���=3g�䭷��8�̙3|��7�ܹ�����5kҼys�����O�^CYc+NY2�b۶mZ.�mۦ�W\�Ey?e��iS��(�Ǒ#GX�~=#F�(��<~��G6n��?��CVV&&&t�҅�>��nݺ����<&����?>�v��֭[�k׎y��ѯ_?�1�8q���`���رc���j�1YYY�m�6�z�-�8q�ڂ9�

�믿�̙3���УGf͚E�v�4�k�^gQ��2�<�V������уm۶i�#�BTzϪ�Ç��+�\�G�y������/Sl��yT����9<��G�G����e�y�@!�B!�����@�޽INN�U�V���O�!�D͚5�;w.[�l!--���4�l��ܹs100�uxB�U�*U��O�/""B�?�B<��v����T�(IzBQ������o�l�2���_�߿Ozz:XYYU�6k֬����U����a���\�~���|RRRX�p!���ꆅ���ၙ�Y�}�3���X:�V�m�6:u���ի�r�
���\�r�U�VѱcGv��Yd������h���u�[�n��ޞ��=t�VVV,]��s��q��}���8r�s�Υcǎ\�z��b+�I�_�n�044T%V�m�6�ѣ�S�,�,������	��-[�����M׮]�:u*���dff���CnܸATT=z�(Ӫ��yL�رkkk֬Yõk����'!!�����~�


�ѣGxxxPR��R�pss��Ç�X�Bk����777N�8���~�:���X[[W����Y�U���<x0S�L�޽{�G!��P)w�����…$&&ҥKUybb"��*U��P(���Q�Bp���2�w��1���U�'$$����$�������NVV���jDz��Tu�B!�B��ԯ_���,������jժ�Ig������dѢExyyѩS'G%��0`...�C��ΐ!Ct�O��O?e�޽ZoKHH ((��kעP(:t(�Z�R�h/������dРAdgg3e�<==y�WHLLdŊ������‰'��h�A`��̘1��˗��ϟ?τ	x��!|���4jԈ��8���HHH`�…|���۷�ԫiרQ;;;����t�
�ݻw�߿?����lْ3g������͛2d���4l�P�M777��}>��S:v�ȡC��裏8w�_~��Z�”)S���fܸqx{{ӴiS<x������"99�y����?THl���;eb��3g�v	8q�)))���CCç�Y�YQ>��9Rl=�9�o��ҥK�ԩzzz$&&2e�8���/|�A�}��1q��-\\\T��ѢE���>��3>��c�}�ٳx�z�,��ҥKٹs'����g̘���
�/�C��;w�����c˖-�9�3g�P�^�w����)�i�<�[�hmڴa�ƍ6L��!��O(<<\Q�������Jaee���w�}����R899)�=����W=zTѯ_?������o�U��ի����J���?+rss�ΝS�5J�}kkk������ŋ10@�������W9rDѷo_����b�����ԩSVVV����[�Z���o������O?-q̄xޕ��B!�B�����(\\\��^!�xQ�������"�B���<�^���*�s���\E߾}K�,Q�(������}�!
!�3QY���
???������Δ)S�=�t�E�j����>S;���C��8�СC
@ѬY3UY�Z��"++��>�3c���޽���Çj�>|��޽�������C��ݻw+����Z����PܼyS��Ǐ+���e��VPy�_��~���6�G�P(���k����4�/�8Ci��t^A999
@ahhXlM�6UZ��9sFkE�R���W_}�=z��8'??_acc��/����,a$�ݸqC�}Q�Ѯ];���
��_�8E��?�U��B<�s���:!�B+��&h<���4i҄��T��ܰ����͍+W�ФI���Tu�u���ŋ���gȐ!���h�ijj
���3���S;fffƘ1c���aܸq���Ӷm[�Z!�t����Ǐk�W���ۗjl�B!�B!�B!�(
kkk�]�_4���ddd��~:|�p222

�adB!�Q��>q�D��������?�l#++��Ç��c���jL������YF����K�el���D�ɾ�%���IS�H�e~�-R�|-e�K"�H������0C����:Ϸ�9�i!��u]�:�s?�y�sJ:��dһwo.\�v��899i�kiiIvv6W�\Q�=z���a!�D]hh(��Δ)���L�2̜9�}��i=ҤImm۶ 55U�������Ɔ�����/�XӦM���&%%��b˩$^?~��W�v�s��1~a�e�P�O�<ɷߟ�Ivv��
�|��rA��سg3g��8�\�rJ���T�Z�jU�bS�R�
iiiZ�Ϟ=��+�{q������B�
�ׯ_�!!�Z�Z�ELL�ֲ�FFF�����_P�V-ʖ-K�Z����/�U~�����
DժU��קcǎ̞=[�3f��Ԕ�e˒���vlٲet�ܙr��Q�V-����'���%2���aDD�F���

����m�B!�B!�BZa'$$`iiI߾}���ʷoVV�����Ғ���"�S����U��x]�?>�c�fڴiX[[ӱcGF�����sJBI�g`` ӧOg����@dB���������Ύ:еkWF���ݻ5�����r�Jlmm�С���g͚5j���2--��[�ҦMjժ��]�6���lݺ���,BQx			��������hڴ)/^���ƍ��?���ܜ-[�P�lY��.]��?�)��v�B�jQun�vUl����k�U�\@�"���Ǐg�С���affƨQ�عs��z��ƖSI�~u�֥iӦDDD(s~��}�;����ֹ(��3�/�Ç��A$))�={�0{�l���111 ;;[���Pm&ۦM��t��Ak{�J���ݻw�;�O>�ڮ��ܹs�/�W��Y!�B��r�@^�V����3�����X�"...������N氶����:ϱ~���6N�ʕqtt��ˋ��LMMHII!..����+��B!�B!�BQ��4iB�ƍILL$22��]���ĉܸq����k�qT�7�|Ñ#G4�����������Z��3g8s����̙3G�^��9u��V�b۶mdgg���@Æ
iѢEi�&D��Z�
???�ӧO9{�,gϞ��Ç2���&L��,��q������dzj�*�]�sڿ?���t��Q�Xǎ����8��N!Dq�ZE �~6l 00###����V��F��W�077'&&�s��Ѯ];����̤\��-�Q-&�k###���sSU9��ȑ#�Z�*?������_��닯�/
4���ō-��~*666���O���bgg���_233�nQ�f�_U��:��l۶
WWW����5fQ��9�+1�w���ްaCbccIHH�3)C�3g�`aa��x�5����S�(�W��Y!��ga IDATB��W6��M3b����K@@��D���	C�-��B!��ͳ}�vP�a!�/���K;��F^��3p�@~��Gv�ޝo�Ů]����{����*�9����͍�~��Z�j1q�D:u�DժU���ٹs'~~~̜9�
6��G�����#fϞ͠A���h���5k۷o�bŊ��ųs�NV�\���%O�>%$$�mۦ$\������@�f�puu�A�$''���Ntt4���0�����EΟqǎ�q��1�ڎ;&	B�
�\�2���ܻw/���yILLdʔ)������O�&M�#--��4F�.]���a���:%\\�p�6m�п�������ݻ���166�8G�[�j�������Ϲz�*aaaDFFɅ�|�2S�N%88��c+�뗓*�b�޽��ٱw�^��e�_X�����驵=~��D��]MAe�����P~�!���ԫW�5jиqc6l��EyO�ιw�իW�8��ZDz��"66����B%\���ѳgO���VŞW�.^��gQ4'N���ի���-Ю];���J;!�"	/IŊ�;w.S�Laذa�bŊW2�^!�B!^wO�>�/�(�0�B�i[�[�{�f���;v�۷ok�E��ݻ=z�
*Я_�W�/22�������V�Zʱ:u�0y�d*U�Ě5kX�f
k׮-�h5���p��-��}��lٲ���J1:�S�,��E&gU�T�@RRݺucРA4H�_hh(���ԩS����3w�\@HHH�I��ϟ�nݺ��ի��G!ī��ܜ��X~��7����y�?f������?`kk�g�
G||<�:u*�ڃf���]��iӦ)���e׮]����-�oР'O�$::�>}�h�s��	�_I233cԨQ�5
�_�����+��K:���~�u�ܙ*U��o�>���ٿ?�+W�O>y)��L�2dee����������ž��g�X�~=���Ϸ����d���j�nܸ�|����o�0(�{�Y�fDFFr��I���5���w˱cDzd�<==3f͚5�76���8���)S��G�����ɓ���C�=**
��?���q��*?��Y�b�7o.�0�o���K;!���o٢D�n�'''�,Y’%K�4i���B!�B�   ���ly�C�<ޚ�(����ڂ㬬,<==����C�t�ڕQ�F�{�n�OŊ�ׯϞ=cϞ=Z��믿��������8+,,�	&Э[7ڷoϧ�~ʒ%KHOO�9>�;w���?гgO:v�ȬY��Fa����t�R���ĸl�2<x�5���Xz��	��333Y�x1]�v�G�xzz�w8uuu�s��t�ޝ����]��y�99�G�Z6L-�"'&N��QaZ����zz:+W���֖:п֬YCFF��[�n�M�6j�׮]KKK�n�JZZ��1�x]L�:���X�|9x{{k���e���V����T�,.]���8w��к0Vզ�#��ՠZ��`�2335�����Q�`ƌ�9sF�
���ݻ���q,>>===%1�W�����͛888���k�X�d	eʔaƌJ{�޽X�x1YYYj�dee�d� ���^�z�����h�ر�F[I�V��/�r��aeeō7ؼy3�nݢG����uU�Z5���5�y{{���f��?���ܜO?�4߾�ߋT��l�2��G�8nQ���9K�.�Dvv�rNn���L�<�ǏӧO��~������!##��'�Y�c�ҥmϞ=cѢE�T	R��W�W��Y���c���N�Ǜ�B����
�QZ���Q�؄B!��[�b�����B���v��U�V���<��)gϞ��ٳ<|��!C��j�ȑ#�v��
���k׮�X�u��M�n�Jjj*?��N񥥥1z�hRRR������IE��ƌCRR�Z��7o&::ooo*U��vβe�HKK�HpX�x1;w�T�oذSSS�o�NBB�|G�{�R�L���{�x�t��Y�|w,�\�2cƌ)�}f�322�0a�r��|�Yooo���Y�j�����IOO׺x�cǎDGGs��BB�*�g_%]�G��ִoߞ��p���8}�4k֬��ߟI�&)��$hK��I��X�.Ϊ��?��B�.'''V�^ͱc��ӧ���4oޜ�Ǐ�u�V|}})W�����9����^���͛���W���'�f�|||�]�6S�L��Ȉ��(���kF��v���iӦ
���Y�f|��7���333�>}��˗ٷoK�.���̙3Gm��'�r�J>������s��%\]]	�R�JL�<��s��_��ၽ�=���Gǎ100�ܹsJH�]�K2���~y���aǎ̙3Gy�2��E�Ν	

bܸq���`iiIJJ
�W�.R���L���bbbX�j�|��xyyQ�\�˷��̸t�3f��￧F��;w�E��i�&�ߝ;w4�q�V���W_}Ųe�8p����̟?sss.^�ȬY�8~�x��-^��?����ұcG�!Chٲ%U�V�޽{��Ʋy�f��̤[�nZ�*TBBBppp`޼yԯ_�s��1s�L"##��4*c����Ν;0`YYY����Ua���B!D�y�.�B!�B��N�8���۱��/�P�B�j����kK�$�r�J,--y��)!!!xxx�m�6%�A�|��ǜ>}��'O�U]�����ի4nܘ&M��e�\\\�߿?zzz�={�����s|�6m"%%�������
r��YeAR^rW�Pɹ���Ϗ��$LMM�?>�7&!!�ٳgs��%|}}qrrR;�~��x{{k,J���g˖-ԭ[???<==���aÆ�ر�ڵk�q�F֯_�ѣG��t��������ܹ���i�s�[a�0����OBB͚5��Օ
������;���+;�;v�ƍk\G�v��1I���*U�`kk���-			����q�F�-[���MLLHNNfϞ=���z��իs��M�߿O���Վݿ_�#���ajj��͛4haaa�k�N�Ϛ5khѢ��\��{��

�*���‚5k�0v�X.\�…�u����z��)��/^���B�e�2g��͛���{����=AAA�700   ��u�������;���HLL���Z㸩�)?�����(�_^��틞����K�EI���Y�f��~.]�D�.]Ԏ�_��q���{~A�A���lڴ��]����3�ƍc�ڵ��g�f�֭\�x���33�|�U�����۶m�w���ر�;v�������ѣ)[���x����ݻ��3g�r�J|}}��[ٲe�2e
�-ʷ�I`` �Ǐ��|�v��Q�B��֭[��yA^ɿ��('N�P��	!Dq�k׮�w�oI�B!�B�Frtt$  ���B!^�͛7+�o���r�k�ٽR�J<x�����֭�
R*U�4p�@N�>��ݻծ�k�.�s�=Jvv6����۷OY��֞Sxx8���4m��V�Z��w�1e������Çpss�y��|��Ǹ��2y�d:��p1t�P�;����`aa<����ӓ'O����,@6l�ׯW@C��lٲ<{�����v߅����P��ݩS��<Ae�ܹ0���%���Z�ԫWO�����>����\\\�����‚�������+��w�/nnn8;;caa��{��gӦMXZZ���	<_�����իW���5��͛$''k$V$''+}�B�Zlll���cѢE���r��M*U�D۶m���o���R����B�1z�h,,,X�p!Ǐ'==����3d����[���5k�ٳg���c�Ν�>}�۷oS�lY����޽;�&M⣏>�:f������e�…�����?�P�fM���pqqњp[U�T���,Z���� �\��ӧO�W��}�3gΤf͚/,�¾~y111�e˖���ҴiS�+�������رc̛7���>|H˖-�={6���+0�"�r����;�аaC����0a��N�~��W�|�r100�m۶L�:�~��aaa��������)y�(�N�:���	

���Q�F̛7F��Q)QE__��˗3i�$���8x� .\��ÇѨQ#���=z4|�A�����ӨQ#ƌC\\fff8gggjԨ����LJ�'��'O�]�v��OQ�Yߊ+ؼysi�!�x���X�a!^I�B!�B!�B�֙:u*���#**���(֮]��ѣqtt��
�W�^,]��C����J�*UHMM%,,CCCz���}�6ӦM#11Qc̼v���ڵkJb�J˖-�=O[rIn)))��dm׾~���9�d��r.fι��A���+V�8�8�T�V-�]�ƍ7�_���>���<|�Pm���wa�_�3�����X.]��|}��]�����T}�x]�1www<<<���P;֪U+��#GΙ3g:t�Z�
*0m�4�y�jո{�.vvv����g�:u�đ#G���W�.<��h�F-���аaC���t��i�.]������+���"�٤I6mڤs��~���xժUqww��ݽTb+��ߵN�<Y���r�U�V
:�0��+LLÇg���Z�6�aÆ*�¾'���ٸq�F�*1���e���Z+�E��͕���ԫW�}��i=�����Ϣ�d�.!DqT�J��ya	_|�ŋ���5�}���A!�B!�B�Ar'��O�t`mmM���	'((�ӧO�f�����4i�ڮ���������ۇ�����###��?�\-Ac���$&&����'�РA�6mZ这�c�^�Q�܋�G)��ڪ[Zw(S�L�cg��7oεk����L���?5jM�6��ˋ�e��y=m�]��/haMΊ�c�͏�M>�%I���%��Ύr��HRR�>]�taĈJ?CCC���ٰa��֭[T�\�V�Z1a���͕�3f�`���ܼy���z����?�LDD���È�

Kt�k!�B��U�J�x��.\P*�a�Z�n��CB!��(�Of��̰��/��
!��A!�B��Ο?���sNG�e�����Ǔ�����}�vvvt�ܹ��.�"Ԣ�e���Q�{P�����u��eȐ!��ׯH�.	���DEEо}{��B!^�*U�`kk���-			����q�F�-[��p�������i�~������T�V
@Yp����S���ORR���t��QiW��^u����?�$..�v��)�qqq@�������S߾}			!  ���Վgee���Ivv6���S�-
s߅����ٳgO�sW�zun޼����^��ڱ���+}�xݩ~��J�*L�>��ӧ�����kkk��ʕ+��舗�)))���ϫ����1~�x��;B!��hڵkGxx8,Y��v��a``��+Wذa?���ƍ+�H�B!�x1J<�s��%�(D!�B!�x�}��79rD#9�ɓ'̙3���0������G�r��Q����7o^��Iul�ݓ'O�p���=���|��'/=�S�N�j�*�m�Fvv64lؐ-Z��X��m��g�������666XXX��_P�|y��fff�iӆ��h8��hժU��?N�^�HJJ�~P�SSS5��ӧk֬��ݝ~���͛s��y,XP�;��nݺ��닻�;��ϧI�&$$$�p�B�t�R�1tU�<��鑝��իW133�C��jՊ��XF���ɓ�С*T�…�[����(:u�ĠA��t߅���ݻ��닛����XXXp��=���ٴi���xzzШQ#n޼Irr�FbErr��G��#F�w�^pvv   �Z��	!�B��.]JϞ=9u�={��8������ݺu{��	!�x-ܼy�ڵk�vBQd%�p�y�f�RҗB�A���K;!�B!^�#G�hm_�`aaa2v�Xz�����������ӓ��Pʗ/���cK��䞋�w����?¦M�^z�ţG��={6�
Rvƶ��c֬Yl߾��+��x��m0b���������C�X�V���3p�@���Y�x1��b~�nݺœ9s�3g���s�ΩUL��СC	��j�����[Y�_T#F��СC\�z�ѣG�333�h{t��jժq��]���011aϞ=xxx0q�D._������ݻwg������)m�����ȑ#	�̙3�+T���iӔ�:u�ȑ#���k��T�3^f‹x{�U���^��9*V��ܹs�2e
Æ
 88�+VP�B���B!ě�U�V�={��K���~���O�>}J�ڵ�ܹ3S�L�}����o���H6n�Hdd$���<{��Z�jѮ];F�U�ջ_&��z���,�ߋ
��c5֒�Gm�������\�t��bddDÆ
���b�رԫW�D���_pvv����8���U!JZ�'\���K!^S�7of��ݥ�B!��*..����T������.�������}��<���
D���K/හ��13f� $$���ė>����n�b��Jۗ_~ɖ-[�������$����,��\�r������O�.]1b��s�u�F��չs����t��]�Ϸ�~Kff&<{��ʕ+WX�~=۶m�)�B__���׳r�J���x��!�|�	nnn�߿_�����֭[Gxx8w�ܡz����ٓ����*U���u�f̘��ի�y�&���������r�
zzz�oߞ�Ҷm�b�wa����ooo6l��Ç�u��+W�U�VL�0sss�o�޽��矉��`���j׉�����++���f!�
�[���ɉ%K�0iҤ<�B!DѼ��{,_��Tc�Ÿ�mu��-F�ɾ}�4�]�v�k׮�c�lllزe�K���x�<~��o��OOO���Ԏݻw���h���Y�hS�N���]k�ʹ��B��^X…�������5���SI�B!���۷o�b�
"##y��
4`���ʎ�9p������Ehh(���5jԠo߾�;}}}@}�X��1110|��<w�166f�С�X��]�v)	��;vBCC��קs��|���ԨQ#߱s~�������9t�w�ܡF���уq��ahh�q��[��l�2Μ9����z�b�ԩŮ��˜j���"33о�QA����NJ+h֬����y���899�p�B�œ���\�~www:t�֭[iӦ
�j�R�Ԯ]KKK�n�ʰa�022�^�BhҖ�akk������([�l��FFF���k=������h��r�ʸ�����R`���*_�jU���qvvη_^�-n���dmm�����~6L��^��7n��T����ә>}z��ttt��ˋ��LMMHII!..����S�R%��G��zӪ�9::���X�a!�B!D�����ر#IIIԩS��ӧӷo_>��ʖ-˕+Wؾ};�/&$$[[[<H�r/lY�!��7����Ǐ�ӧG��|��:GGGZ�jE�j�HMM%66���6m�Ē%K8}�4{��-Ѥ���Is-�x��)��B!�B����CƎKHH���<}��s��)�9edd0a�6n����y��)7n��ۛ�S�j����ӧ�ڵk��:w���S�4�-Z��={���cRSS			a��Ѥ���z�<x�1cưe����o233�y�&�7of�ر���k�3~�x���y��1���gǎ,[��P��V�9���Ivv6w��Qv�mڴ��q]�I�L����6o��J�ݻw�~�����~��ӵ�vޱcG��ӕ�!��7b�j׮M@@�����	C�-�ȄB!�B�*5jIII|��'���|��74i҄�+���O�F��5k�����G���ӳ����iӦq��4h��'ظq#�{��f͚�+Wcccz�ꅏ�'N��N�:���2s���]!^)oU�����<v��Q�O����5�۷��ʊ�ӧ�Bƶ��T�q�U_��> IDAT���X��!�B!�K��kרS����?~���׫UP�'!!�f͚�y�fN�8A`` -Z� ::���`@}�ؘ��?�����I�1���{��RѹEFF�b�
�?���7u������;vn~~~$%%ajj�ܷ��u���ҥKj�T�֭�Ν;9v��G������T����M�9�OAs�_|mڴ�w��8p��e���W_z�LLL�裏x��qqq����L�2;v�Ǐ@۶m�T�ǎ�q��q��T}�B�X�"s��%88�7np��
����;w.*T(��B!�B��Vrr2�ƍ���LLL2d			Z������-&&{{{j֬���>
4��Ņ�����`߾}ԬY��;w��;��w�f�����_~�8~��9F����)������2r�H.^���}������у�+R�Z5lmm����z�ŋ�0a�����;�кuk�͛ǽ{���S���S�ׯ0?~�����ڵ+իW�\�rԨQ�~��^�۶m�Y�f�����3f̘~�����_�CCCBCCiٲe��nݺ�R�bŊ$%%������I�&�/_��5k���|�������r{�߳B���[S;�o��ȑ#�L�<yœ9sSk���9z�(G���ʊy�桯�_�c�jN�:ŪU�ضm���888аaCZ�hQڡ	!�B!��Jpss�y���jՊY�f��_��


��ݝ:u�P�~}�Νˀ		a��y����P`9gU	]m�t]\\�j͛7��͍I�&q��a���
�_m���������ɓ9t�����133`Ȑ!x{{��FnŝS(���-[��͛3~�x��]���ʊ�g�Cǎ9q����|����ڵ���Hz����{��6i�[��F\���S�#�B�7C�֭qrrR*lM�4�V�Z�rTB!�%gȐ!�޽���B�7���K;�7RDD�~���g�j�;w�dǎ����+VT{�q�Fƌógϔ���$-Zā����r��ʆR&L��ظ��F�IӦMi۶�Z�޽{����ѣGJ���ٸq#���ؽ{7�z��z�'NЭ[7eC�Ǐ�g����Oxx8:tP�������ٓ��4�-##���Xbcc�%**�w�}�Db��E�~*iiit�֍��X��;w�¾}���O?�z���''NT�_�v
ooo�l���ݻ����)��ޣ��YYYL�0�>�@�1Z�h��ѣY�n^^^,X�@��O?�����������<�AW��{V�zk.�9��}�����ahh�رc�ѣ�.���'**
OOOBCC)_�<?��C����%_<z�ٳg3h� e�U;;;f͚���5~�B!�B�׍��
���%''h��m��իW����:ΥK��V�Z�Nƪ�mRRR����o�^�*Q�ڵk������Z�j�_��qN�
���T�@VV�F���ߛ��(�B��D_jj*'N$99��}�j}��:O�z�b���ʵ8���NNN���<xPI�(S�]�v��ݻi��jS�B!ě���GG��C��d��B�]^��������B����lɻ{�.�
"--�iӦ����{�G\\^^^x{{���Hbb�Zsm�f-\�WWW6lؠ�_�r�������3&L��̙3155%**�ѣGs��)-Z��Q����_�~:݃���;wVk�y�&��ѣG|��g,X�.^����AAA|��$$$P�vm�k�=��}���7�вeK~��wƌ��˗���ٻw��wڴi�����W_���Lݺu����ĉL�4����͛ǚ5kJ$��������Ã��X�6mʺu�hժeʔ!..�iӦq��q,X�g���i��ѣ?��͚5���˸���k�.���KΝ;G͚5K�U�7
��,7֭[���&\���Ҿ}{~��gZ�h��˗���f�С\�x��5k*���ھ_r{�߳B��[�%\�0�f�A\\!!!T�Roooe�Hccclllh߾=�&$$�A�);Y�i|||�u��Vھ��K�lق��O�vHB!�B��U�?�i+a[�s�|έe˖ܸq���0F��g?U%Fm�}sW�P%<�)S&߱u�-�B�|������(�;�P�9�R�
�g�fĈ,\��jժ)�'
�{�jժ��̙3g�{�.���k׎jժѲeK"##IOO'!!�-ZP�Z5��-VU[I͵B!�x�|����B�!00��CB!
eݺuܺu777~��G��}���o�###�/_��իՎ�Ŝ9s���o�6Z����ɓ'888�v�Z��K�.lٲ�6mڰi�&%�B�YX�ƍ�|_+W��t�ޝ�;w*�94mڔ�;wҫW/>̪U���W׮]�b��O��_�ѣ����Zߓ'O�x�b�y��gJݺu#00�f͚�,^/nl9��뗗������6kk׮~~~XXXp�̙<�oٲ%���W>�jܸ1;v��ʊ��0֭[ǬY�J�/^�@�&M
u��
�.\�����~ȡC��M��4i®]�����ӓٳgjL�W�=+�x���J�������'vvvt�Ё�]�2j�(��&���Y�r%���t�Ё����f�222�>9w����T�0|�p�d�����:t(�v�ҸΓ'O�7o�;w�G�̙3�۷o8vίU���X�t)����}��|��,[�Lca���K�.���D�Ν�ٳ'.T+���<����u�Vڴi��sj�ڵ���d�֭je��B!��u��Py���8}���9��ʮ0{���z����|�8p �<�=��
.\���о�L�?ڞ:u
@�r�*u���oH���yQv�)���)oN>��C�
Fvv6���j���p�dmmMVV7n��Ç�nR�;w���Ǭ[�N�C�J������Fl�6U!�B!�y����ly�C��[�x�����C�<^�C�ծ��'O�z|�ر����y��>_~�%�����ݛ��?x� �֍�---����ʕ+J�j���a!�D]hh(����>�)S��3g�o�>��O�4I��m۶���>k���!  ����K9ִiS������%[N%����?�$;;[-�BE�9T�u�����il���Ƿ�~�Vu!/E�G�kT�j������}^kFgϞ�$[��|�t������Y!�ۭ�*\�gժU����O�r��YΞ=�Ç2dL�0�����7�&>>�U�V廓�j�L׮]�s�άX�BY��ӢE�سg�?&$$���8����xt��ƌCRR��v��M6o�Ltt4���T�TI����+/?~̎;������
�}���Ozz:;vԈ�cǎDGGs�eQ�B!�B�i����|�2.d���|��$&&j�1�{�����憳�3ܻw6mڄ��%�����?�fggs��U��̀����׏�{�2v�XƍGϞ=�^�:�o������/<z�>}�ТE�,X��y��Y����ݻ��G�عu��
___��ݙ?>M�4!!!A��.]�obuT�9͋.s��1c�JJJ
�ׯgƌʱ��SϞ=Y�d	;v�P.:u�IJe�زe�rM�F�q��M���5+T;X5j�H��B!�B!�x0@mWo!�%g���Z7.E�ZX�FT��ڌ7�?��sss�l�BٲeՎ�6�RU(H�*U�w�iii�^0�;^Ղ��T�ymfnn��V�re@�
���+�F����?~x���gϞ��ߟO?�}}��-��x�t�����Att4'N�P6��/)VۺL�6m����X�E��J�*��B���ݻ����'�hmW�Ϲs�t+�W�=+�x���	;w��������ӧ������m۔Dh֬���4hЀ��d��݉��&88��T�ȹ��?�����{���[�4�EFF�b�
ڴiCbb"�f��������ع���������)��ϧq��$$$0{�l.]�����Fvkݺu�;w.�.^^^x{{s��a%�B�y<v�������رc�p!�B!�xc
2�������矌92߾#G�$<<�3g�(U*T���iӔ�ժU��ݻ���abb�$컹����<Ȳe�X�l��8ݻwϳܮ���F�M�4������s1b���ի�=Z혙��FۋR�9͋.s���+��3~�x�o����]�
3OիW�U�V���ШQ#��dݺuy��v�~����":u�đ#G�����)>>xy�/B�*۾};�˗/�0��Tm߾��CB�
y��]�����޾��B�7�ӧO%ᢄ�����6l�@`` FFFQ�Z5�><t�XannNLL�Ν�]�v:�����VIAU� ��FFF<|�P��
*�4.<���jժ��������_��닯�/
4�ԯ_�Db˩���.�mۆ���چں�k�nU{zzz��(�=6lؐ��X�С�N����[XXh=^�F
��Q�׋�U~�
!�n/-�B�tPP{LL��Y@RRݺucРA4H���|���;u���~��̝;�€�)##@�\Sn��CmY�...Jb���qsscҤI>|Xk���>|x��y���lVWWW&O�̡C�4�����R:d�������uϟ?<_��[�z��!�B!ě�bŊ�_��U�Vq��Q<x@���:t(s��Q۽���ooo6l��Ç�u��+W�U�VL�0Am�3f�z�jn޼��@__�=ʮ]�8{�,���T�Z��>���[�qٲe|���DEEallL�>};v�Z�y�����>>>�[����p�ܹC����ٳ'_}�U�*7Ga�4/��IAZ�j�_|��m�X�t)�V�
?O������h$It�ܙ�[�ҽ{w��޽{���?����ՎEDD`hh�����!�o�ݻw�b!�[�/�(��B!��S�reRSS�w�^��I$&&2e�����I�&y����ƃt�K�.��İ�~�..\�@�6m�߿?������7�ݻ���166�8GU�@U��>��s>��s�^�JXX���DFFr��._��ԩS	.�؊��b������~�!���ԫW�5jиqc6l��y��{|�w
��(�heeEll,����J�P%����S�񒸟����Y!��핬p1u�T�͛GTTQQQ�]��ѣG��訖�v��Ulmm�^��rR�j��ƍܸqCI\�&%%E�[���՞�h��k׮�;v^c�.ֲeK�_��qN�
��U�;r�=�u�޽�/�/'U���B!�B������3g�Zۍ7͝Z�T����ә>}z�״�����:��]�v�7�"/U�V��.���*/V�Zggg����^^Us��W�1�>��i^��eNt���o���o��z}]�	���;;;��3f0c���ʕ+��舗�)))����V���T�R��
!ěL�f8B�6qtt��ѱ��B!�Kr��y5j�ʍHTT�|��$�
!���������o�ѷo_��{��1�&==�~�!�u��|�_\\���t�ԩ�k<��˗�v�Z�M��um_N�v�"55===�1O�<Itt4}���8�ĉJ��dffƨQ�5j���+���'<<���V��OW,��ӓ��ǫS}���n�)SF�ӧOk�<��~�Y�f�P�{;v,K�,��ӓ1c��4N\\��ޔ)SF���ɓ'�ѣ�F��w��k`�U~�
!�n/-�"��Uem���i߾=���q��i֬Y���?�&Mb�@��T��e˖ܸq���0��6aaaJ��rW�P%<h���(r&P�V�|y�뜿(��:��s�Ŭj�v}!�B!�xSt�ڕ��t\\\�����А��d-Zh���%iĈ�ݻ���%�#  �Z��	!D�E<B��_M�ΝK;!�B��o���#G�贱���ԩS�Z��m۶������
6T6&B��Y�>}���e��XYYi�	����}���Ϙ1�3g�`ggǬY���{�������契p�G}Dݺu���?h۶-VVV��������<7g�v�K�,�L�2j?��ݛ�'O�x�b�����fee�d� �J�Q�^=�������iӦj�:v�ѿ$c+��+���Æ
�8�l�2��G�i���d��t颶333��yo8�SQ���ܜɓ'�����Ӈݻw+�v����f��ddd0iҤ<+w,]�T#��ٳg�窪u�*zzzdgg癐�ӫ��B��J&+��R�
���xyy���Lj#HMMU�����={��񈎎�w�v�<�a\�p???�q�̙3j�O�:�|��>W�N�y�`N��{-,]�z��ܿ_�|U���B!�B��lll���G��m�{{{bbb�V��ƍ+�ś�bŊ̝;���`�gpp0s��U�R)�o��۷+����}�v�b�B!�x�9r��ѣG̞=�A�abbB�:u��ŏ=z�Q
!D�srr�jժ;v�>}���Ǐ9|�0�Ǐgذa�+Wwww���`V�^M������+pC�'b``���������ߤ��s��!�ȑ#��Y�~=5j�`߾}4k֌իW���Dff&�=">>��~�	KKKn߾ͬY�ԪL�8###>���			ddd���������T�T�ɓ'{���K���	

��Çdff�Tl�Y��$c+��Wfff�������gϞ��0|�p%�Ν;ZϏ��dȐ!�?���N�:E�>}�����̌1cƼ�{\�x1�z�"%%��;2j�(<ȝ;w������8p��#GҩS'nܸA�n�X�ti��������s�����̙3|��DFF�hT�044`�Νdff�����_����*\�g�}FJJ
...���`aa�_��Wu�޽;��������쌅������ߟM�6aii���'�,��W�*�~�����׏�{�2v�XƍGϞ=�^�:�o������/<z�>}�h��_�`�����?��ٳ�?X�{�V�h;�nݺ��닻�;��ϧI�&$$$(Y�]�tya�بQ#n޼Irr�FbErr��G!�B!�T��Θ���o�>�\�BFF�.:t`�رԪU��Co�֭[���q~ҤI�jժ��B�WG@@��A�BwR�Z!��*�˥Q�A����n�R��E�[�l���''�R�N!���Ԕ͛73h� ���h׮�F�5k֨�����6��k���
���k֬a�ر,\�PY�ҡC\\\���ի�,<�x�b���˖-˜9s�7o�Z�{�G@@����v������֭�g�����

"11kkk�㦦����O/$���~����̸q�X�v-k׮U;6{�l�n��ŋ���ߵ�]�r%C�e˖-j�5k�d׮]CQ�Q__��{�2s�LV�\���/���Z�([�,S�LaѢE�K`` �Ǐ'00P��v��il$ֺuk��ñ��W�T�����Y!���L�1b���xxx���v,�B��#GΙ3g:t�Z�
*0m�4�y�jո{�.vvv����g����x��	dٲej�T�w���ٳ��jll��YڤI
;�=:t��W�jd����i��B�y�ԩG�!>��ٻ�������OO(�a&x�����=��m�l���9�y���Ԕ�%j����ene�&�Xfzg[)!["v�-�ܔ�P�t� ����ϑ�|���>�Ŭ�>k��̠���2K-�������!"""""r�hڴ)F���/���Kkl����>����㏼��$''SPP@׮]�>}�e\���|�l�¡C��t��۷��f���Vk͉#���]����Z�lɣ�>ʂptt�ƍlٲ��r��Z�hA�n�?~<~~~V}�sZZ���-[��x�bz����͛�LZ�U^Ѽ�;??���xluc��;b0���gڴi�Z,*"Ґ�;���t^}�U�����ɉx�%K�0z�h�����W�1����ѣ�W����r�}�Ȓ%Kl.r�۷/'O�d����޽��������f͚����C=�h�� IDAT�����hs�q����W_�z�j>��3~��'�nF�Mhh(�{���<lquu����|��G|��w\�v��]�2~�x��p��w�YlU}��b֬Y�lْ�_�o����-[��`��x�	z�����ټy3&L(u~`` ���s����ƍ����qww��9:88��3�|������O�׿��իWqqq�W�^�=���`��
�8q"�z��g�!==OOO&L�@HH�۷/�>&&�����"))�_���;��C~ϊȝ�n	�-��y��$$$���
@�Ν1bAAA�v���DGG��;�p��a.^�H�֭���b�ܹt����v���lڴ���\�-�������?��?��ɓ\�r�6m���?�???F�Yf�k׮��_$%%���{��3g���P��7sqq!&&���z�#G�p��%���x�G�5k���?��|njúu�HJJb���V}$%%���\�{�|�2AAA���ϖ���,V�X����7n<��3�������ő��Jtt4NNNV}ϙ3���<������q�aaalܸ��۷[�_�v��'Or��I�^�J```��]�����*��[�y�r�
�.U���Mjj*���TD�vӳgO���*�?��O��1bD�o~ܲeKf͚ŬY��5f�>}x��w+ݾ��*�oӦ
DDD�%���~U�{����V�M�6�iӦ���ĉ�vx�n5�c���m�R�����/��Tۮ]���'�ج+k�
�=+"w������/����suueѢE,Z���v>>>6��19rd��eiӦ
�֭��ضNڴiCHH!!!�WV�����<��[��h4ENN�:u ''���t�̙S��ӧOӫW/��S��loU�v�%!!����ʤI��e\��l۶����>}����/Ӿ}{^�u>��C���-�۷o';;�N�:�j�*z��ͩS�X�|9YYYlݺ�y��Y�ݥK��ù�{���"::�Ç[.v��
��
0\�v�����Ν;	������}��Gtt��M@kk�e����`�n����d%\�����H����H�Dǎ������������ԩS�����������H���/T�.���8��ĉlܸ�%K��x�b6l�@zz�����`0X�ׅcǎ�d�<==qrr",,���4>��CK�ÇF�~�hѢ���g�ҥ:t�T�!!!xzzҲeK���+W,��]��ƒ�����HKKc�޽���ԩUN��ʼm9}�4�{Bɭ�v�j�FDDDDD�1j�;\H�rtt$<<��޲��޽{Y�~=�Z��st""""""UG\\����F��ѣ��8���EQQ˗/'  www���Y�l�v���ѱ^�)���*ܥ.''����[�8Ъ��u���򳫫+7nܰ�-X���+W���BJJ
o��&�����J��0'8TUe�m��˗pqq)Ug.3�i��p!�
b޼y�Y��������e�DDDDDD��������a���H=3�
���ZLL/^䩧���M�2���{����͛g��DDDD��n�N��{�&Mjt��	�jѢE���0t�P�9�G}��_�o���;�?>&L�p��v�0�L�1KJJJ��d��s�6mZ��\V��UDDDDD�!S�E55�?��F�F�����!C�0d�{�!"""
L~~>[�l�СC\�t�������3{�l���-��Z�us���ʓ�����$11��s�=G���ke����<��x֮]KFF-[���Ge��V;QEbb"?���۷���g�̙V����󉏏g��t��RޱcG���L�6��]qEDDDD��=��ÿ��o����ӧO��<<<����IOO���1==���[U�����닯�/�N���>c۶m�]��R	�jҤ	&���W�Z>�dee�jW�y����Fnn.yyy���Y����Yڈ��H�f2�����ݔN?id


x�gx����������%..��3gRXXX����۷���b�\����	�ʕ+�:NM̙3���T�������>`�ڵ�����Ν˶m�8�<׮]�…DGG�`����8p���B���K����Maa!��y������eذa�Y����\���y��0<�䓖v�F� ""���~��7222X�z5#F�����Ǐ�`0��SXXH�=�ٳ'`{w�s��U�g�v�سgEEEdggY�y��W�^�={�T��2s��H	""""""�(���ѤI:t�С�>�_r��}�v����ԩ���?~���(<<<���b�֭U���]&���J�:q��1֯_���lj����Ã��ϳcǎZ�&�t���ݻINN&88�Ç[�w���S��۷/qqq|��$$$0`�RSSٻw��mrr2�{�.5����FDDDD�^�~�i���������3Ç'!!�Y�fY����INN���:���`Ο?�����*������d�ȑ<�������eigN��gܸq�iNY�n#F�`ҤI�m۶��5�9Y#33�T���$��������.��;��z�����w"""R�C�����,�aaa��������t�R�}�Y:ļy�j-���P�n���#,,����s���Z�&BBB��� 00���h�8��������}��Gxx8~~~�߿�r
v��i�$�[u��ժ�����P��ĕ���FLL7n���ӽ{wf̘�#�<bi���BLLo��G��ҥK�����#�0k�,\]]�<���?͛7'!!���l:w�̈#,��/fӦM���RRRRn�.�iӦ$&&RTT��``���<���՚���njúu�HJJb���V�&%%�����ѣ��|�������.�,�b׮]uյ�ܦ����ԕ!C�0d�{�!"""
XNN�{�������ku��C�Z=0`?��C��Sݺu��l^0v��
Kٹs��y~VV���˗/�/L�����FDDDDĞ<<<�����]�6m		!$$��ve%��*���-������J����Hhh(�����̼m�ݺuk�F#QQQ���ЩS'��X���̙3''�r�iHv�ڥ�x���H��Y�ŤI��k�R���;[T�N�7'��d2ѤI�
�,{��ͭ�~7�Ӵi�Z�&Z�ha��<��q��������g.�5������4|AAA|������ZPbccqwwg�ԩv�ND�j�]����"""R%��pa41��ݭ����������H�yxx�ߓ��n�3Vzz:��&M�`2��z�*��΀�n����aI8q���{o��S����9{�,���z~lqss#77���<��ܬ����,mDDDDD*r�utm�Jb�Xstt$<<���iӦ�w�^֯_O�V����H����k�0DDD�6S�	ǎc����ݭ�4"			�ADDDDDDDD�0�F�b�֭DDD�j�*���éS�X�z5#F���m׮�/_fϞ=L�0�.Y�Os�Ĺs����{�WX�j��8y�$�3�VǩK=�[�n%,,���z��/��Ž;x��w1l޼�^�z����ٳgK%V�={��FDDDDDnO�
b޼y�Y��������e�DD�f���;v��a�H#��s�1|�p{�!"���.Ν;Ǯ]��8qbmw-"��]�v�;�Cq��!Ν;Gpp�U����U٨Q�ؽ{7�֭cݺux{{��Ӝ0���;�����u�]̘1ê}�>}�<yr��e���w�1cG�!##��S�ZյjՊ�Z6��G����Yj�Uff&`��"""""R�D�p�F�F�����/��BkE��v�څ������zT�	f�����*..���@{�!""""""""�Ty�\\\���᭷��ȑ#\�t	777y�f͚������…iڴ)���a0X�|9�?��U��/fӦM���RRRbU�v�Z^|�ERRR�뮻x�ǘ9s&�:N]rvv&::�w�y�Çs��EZ�n���s�Υ{�cƌaݺu$%%1}�t�~���pvvf������������-F����X{�!"��&M��;�gu�p!""""""""""Ґ�iӆ��BBB�m���Hhh(���V�&t������S�X�]+�j�����ve�g���ՕE��hѢr�hݺ5F����(rrr�ԩ999���3g����*������������HC����������������/((��;Z�%266www�N�j��DDDDDDDDDDDD����������ի�LHH %%��C�2iҤZ[DDDDDDDDDD�v���Hxx8�?�<ӦM`�޽�_��V�Z�9:�O�v�E��CD�Qڵk��Ch�.^��رci۶-�~�)?��~~~t�Ё����;��.�k���Z�)""u�N�x�8z�h��M�i�'N�`�ƍ�ܹ����ɓ�ٳ'���EDDDDDDDDDDnW�
b޼y�Y��������e�DDDD���ٳ�={��;�*�����zܷo_��Ԑ��z��[�:ED����	G���>���X�|9������ϲe�صk����������������^����h4b4������؉�d�w"""�RV…��.�k�tl����`�����>|�����ŋ<��S��)S���{�üy��������������������M�4��!����B�`^�x�-[��e���
6�aÆ�f��D�:ED�>4�.nܸ��-[8x� .\�E�t�֍������X_�ܚ���g��k�.���[���i߾=�F�b޼y899Y��e�/^LϞ=�.�n�3??���xL�,m:v�` >>�iӦ���R�ϊ���������������Hök�.&N�h�HDD'����㏼��$''SPP@׮]�>}:cǎ�j���ϖ-[8t��.]�}��<���̞=gggK;���x֮]KFF-[���Ge����j�^��:�͛7�yCn[�ͻ����SDD�K�L�ظq#۷o�<�v�'O���ɓ\�z����2�}��7����*���%>>�+W���K/Yխ]����|��pou�
�.U���Mjj*d„	������������������H���h�w""�R\\\���j�����a4�ҥ|����̘1��={W�q\�|��� ~��gKYVV+V���7����y����-�rss���#55���h�M���̙C^^���|�ܸq���0�f�5�*��&�E�:ED��4�w��޽�}+��Ǐ��
�Ν;�Ǵ�4���{���P�������[o�@RRR����>���y饗��399�޽{�:�\fn#""""""""""�/00�&M��С����������T,33��}��|\׶m���?�L�>}ؽ{7��9O>�$��іv۷o';;�N�:���lj����Ã��,�n�Z��.]��{�n���	���Ö����4�yfm�[�:ED���m����u*�<--
'''


���%;;�Q�F@@@@��|���L&���>��Μ9×_~	���y��S����Pn��O�~��U׮]�ڈ���������H�JHH�w"��!C��;�͜`q����|\׎;��%K��� ,,̲��9Q",,�~��п�.]ʳ�>ˡC��7o��9!!!�>����ʕ+�����4��:L[*;o[��SDD�K�%\TłX�r%)))�����o��h�U�V���?�p�B���Ru&��T��?��\�|�Ru�2s�s�>}�^�z٬KHH %%��C�2iҤ�MDD*p�
�_{�5^{�5��U�V�j�*�R�:Ԧ�������YNN�{���h��ͺu�f�����7nX�j�^Ӭ2�0m��mѺN�/��pq�ņ�B��E���C��ȑ#|��G|��׼���ر����3a„2�y���o�ܹ3�ӟ�֭���X+�Ui�r�iӦ���eږ[DDDDDDDDD�nhA�H����b4�����H���/p��Q��_N�8�ƍٹs'&��ɓ'ӳgO`�HED�!��Û(nբE�rǩ�zM���a�L&˘%%%��k2o����R�����___���ؾ};AAA\�r��kז{������,X��q��Y���oU����
����Ru�2s�}����L&:tT���u��Q��EEE,_�����������ߟe˖QTTT�Q��HY���زe}��%--�
6���EZZ��K��sYYY���� ==ݪ���ݽZ�Ww�fỶW�^��ٚ[e�m��u��H}i�	�Ǐ�`0��SXXH�=�ٳ'`;��ܹs��8~�8%%%|��,[��R~�ʕrǶէy���gϖjo.�ΖV""""""""""""""""w"����`�wu&&&��/��SOYʦL��ŋ����cd""r���L�[��ða�X�f
�����k�a0x��'-�F�@DD���oddd�z�jF�Q�kc��ڵk��={(**";;����j�[�:EDĞd�EPP����9�|���0�Q3������,�+V���ۛ�S����rη�~[�ض�4��n������:*""""""""""""""""R?nܸ��͛��d�ȑ<����ٳ�T���B6l؀��/>� �ƍ�7ޠ�����愑�H��󉏏g��t��Ҧcǎ�����ϯÙ��HU4�����~777222������IHH`֬Y�vAAAxzz���Cpp0C�%88�������Ippp�Ǯ�zͲ��q�[��#F0i�$ڶm[�yk]���ؓ�.��f��ߟ+V�?��֭3f�`�ʕ�v�/�S�N4k���vɒ%�����舃���?�W�f����ܹ�ܸl�9f����HJJ*�>))	gggF�]��ADDDDDDDDDDn_�O���8��\���X�h�-��q\DDDD��ظq#���Ν�ڵkr��I^~�ebcc-�JJJ�;w.۶m��\�v�.͂�q�F��8p���B���K�y{{SXX��k}~""R=�&X��z\��܈�����Z�hA�޽y��W;v�����111L�4�:ЬY3:t�)Sغu+���U�&�5˲p�BhӦ
x{{�|��j�[�:EDĞ��;��������[n|||��\\\�����ޜt���a��֭[c4���"''�N�:���Czz:s���ɩ�9����������H���/p���2�o��Ʃi,'N�`�ƍ�ܹ����ɓ�ٳ'�C�"""""��޽�
6`0�v����'22��;w��;8u�}��e�ҥt�֍�g�Ajj*{����Ϗ��4K����������ݻT���d&L�P����ٿ���O?��.qxxx����fmڴ!$$����rە�]�����,kGGGBCC	

��}e�u�""bO
6ᢡ	

��?&66�r����;S�N�st""""""""""Rߎ=j�qn�㴭E^�@QQ˗/'  www�#.[��]�v���X�q����H�W�l����5�����ƒ��ͨQ�   ��]bb"xxxp�}���������ϯ�q̻�u�ҥT]׮]�ڈ��H�i]����%\T���#���<���L�6
��{��~�zZ�je��DDDDDDDDDD�������.^��SO=e)�2e
�111̛7ώщ�����n���\����RRRx��7	�h4Z��8w�@�w����*w�˗/���R��\fn#""����kJ�eU��u��H}P�E4�y��f��ϟ�����������g˖-:t�K�.Ѿ}{~�afϞ�����]Y�7��v[����DFF������Ç�瞣}���2NUEbb"?���۷���g�̙888Ɓx饗;v���3b�0 IDAT���o,[��G}�O?��f,������3x�`:t�`iӱcG���L�6��b3�s�k������0t�P�9�G}��_�o���;�?>&L�d2��OAAA��M�4�iӦ���e�6"""R3Z�)""uM	Ud41��CDDDDDDDDDD�����g�y���lKYnn.qqq������S���ꫯ�o�>���ٿ?����رWW�Z�"%%%̝;�S�NY�.\�@tt4���lܸ��M�ʉ'x�����cǎ���I�X�t�U���8@aa!��ޥ꼽�IMM����k"""""���ꊯ�/����:u��>��m۶�v�Z�5���;gϞe߾}���Wy777rss������ͪ.//��FDDn/ډ��ҺN�K�S�EDDDDDDDDDD��۷���M�N�������DEE���AVV[�n�R7��=--��܏;���9~�8���xxxp��yv��Q��Tdǎ�:u��}��_|ABB 55��{�����ʕ+�z�*+V��ƍ���\�z���p\]]ˌ%99�޽{��\fn#""""bO�Ǐ�`0��SXXH�=�ٳ'-Z���{衇��w����o�~�:�.]��+���s�Zښw�8w�W�^�={�T�2siؔp!""""""""""�%��`u�W~��a�S����E���ߟ�K�p�СZ�-44oooZ�hA�~�����$&&AϞ=i֬��w����߿��v���F���+�y�����SO��;��ӧ�ҥK���]�Z����� "##9r$>���Z�����nƌt�ڕ���N�ʐ!C3f�.�Z�b�…���ڵ��ߟq��0l�0233K�`.1bD�PDDDDDDj[s{ """"""""""R�rrr�߿�U���8�|��7t�P���~��q*b�ˮ������,������/���ɓ�w�}���w�c\�|�}��[���mDDDDD̪�{[m�y��$$$���
@�Ν1b�%��ٙ��h�y�>�ŋiݺ5^^^̝;��ݻ[�.^��M�6���KII	cƌaݺu$%%1}�t����pvvf���0c��:K�0o�(""""""""""Rn]�e�͢*�nܸQf��d�|�m^8UY͛[�n�i��O�d���L�r�

j<�9v[s3��o""""�P������|3WWW-ZĢE��m��ハ��UY�֭1�DEE���C�N������ә3gNNN՟���T[\\qqq�CDDDn#��p1|�pj�[�j�����'==�!C�X����pww��5i����իWqvvJ�Q���K��'���{ku�����s��Y���g5Dzlڴ���,���éS�ظqc��������%//777����<K�;IPP�1���������;S�N�st""w��{???{�!"����1�H�W�vS"""""""""""�̨Q���� ##��~����V�^
��#,m۵k��={(**";;����R}�wm8w�\��W^y���L~��7N�8ADDcƌ��q*��CƷ�~��׹t���_1̝;���/�$..�����_~�e�������gϖ�\fn#""""R��P'G}stt$<<��{�r��.\��޽{	�U�V��������TO��pq��1k�[iDL&��C�;LPP��ܹs[�yzzZ��5�ݻw�n�:֭[���w�>۵k��˗���ݝ}��Y���.f̘aվO�>L�<�VǩȌ38r���۪U+.\@~~>���899��K/Ѽys��Ù2e
/��";w�����f,Æ
��ѣdff���e5Fff&`��"""""r�4h���c͚5̟?��5���ԟ���g�0D�����h4�;�'��pa��"r���8%d��������H�IKK+���Ņ���z�-�9¥K�pss�Ga֬Y���Z�.\���M����HQQ���˗��[��x�b6m�Dnn.%%%Vuk׮��_$%%���{��3g���P��T��ٙ��h�y�>�ŋiݺ5^^^̝;��ݻɏ?��ʕ+�����Ã��^|�E"##y�Wl�2f�֭[GRRӧO�?))	gggF�]��EDDD��U�u���h4j1��Hb4����w"r3�,"w�:K�iHڴiCHH!!!�stt$44���P��[~������S�X�]+�r��ι���+�-bѢEe�y�Wx�WJ�?��<����Һuk�F#QQQ���ЩS'rrrHOOgΜ9899�������������HC���w_|��Ν�w"�@yzz2d�{�!""U��Lll�%�%66www�N�j���v��"�7]ߋ���������L	vv��iz�����NHH %%��C�2iҤ�MDDDDD����g�0D��Җ�""�GGG���y���6m{��e����j������N�Dno�����9%\��/��ѣG����c�8q��7�s�NL&�'O�gϞ0�����K.DĖ��@{� ""�4h� �͛ǚ5k�?>^^^v�J}~�=�^���DDD�LkEDDj�.���ѣ
n좢"�/_N@@�������l�2v�څ��c}�)"""""""""r[��
v�ш�h�w""""bG			�ADDD�A�ڢ���ŋyꩧ,eS�L��#&&�y���1:i����Ν;g�0D�N<==2d����ۄ>?�4l����'�;�1@㽱�����TM�N����y�7HNN�����]�2}�tƎk�.??�-[�p��!.]�D���y�ᇙ={6��Ζv����x֮]KFF-[���Ge�����7n�e�<ȅhѢݺuc���Y�u��iii���l���ŋ�ٳ'�7o.�"�VyE�.k�|���<x0:t���ر#����x�M����K�^�
�_����8{�!"vb4����w"""r�����M�"""""UW�5�f���DEE����O?�D���y��Ǚ9s&�����ԦF�pq��e������-eYYY�X���ׯ3n�8


x�g��ζ����%..���T���qrr��{Μ9���P\\�|��7`�ƍl߾��ڵk�<y��'Or��U+��ڵ���[]���m9p����x{{���&55��2a„*�$"""""RZ�!rg��$""""�����I�"w���@� ""R�]sXRR�ܹs9uꔥ����&33��7Ҵi�2��A��k�	۶m���O�>���˴oߞ�_�?����hK�����ΦS�N�Z��޽{s��)�/_NVV[�n-�EV�.]�{�!**���h>lI�ؽ{76l�`0p��5���Odd$;w�$00�j7[[��w�}DGG[2Nks�e����@�޽K�k.KNN�Ŕ���������Ի��@���c�0DDDDD�			�ADD�W�5�;v��ԩS��ۗ�K�ҭ[7Ξ=KDD����ݻ???��E�6��رc,Y�OOO���,If����������t�R�}�Y:T*�"$$��g`` ���\�r�R���DAA���dgg3j�(�t�S�N�r�T~޶�>}�=��V]�v�j#"""""""""R_&N�h�Dn['N���@DDD�.�z]DDnw�Ą��m�X��Tv�abb"xxx���9<<???��ߏ��_��h����H��K…�����8�<�z�*�]NN�{���h��ͺu�f�����7nX�,X�ʕ+III!%%�7�|���`�F#�Z��T�拗���m�|�2...���e�6"""""""w���\:v�h�0DD�x�c���������4f�]sx��9|}}m����U�8Z#(""RuM�@]iҤI�ο9��V-Z�(w>��V�XA���)..�7�`�ر|�����-L&��璒�R�5���ܦMK�-�e5}^EDDDDD�cǎ1k�,z��-[��s������;�zӤI�:���7߰x�b
D�6mh޼9�ڵcȐ!,[������x��mn�
u7��2�o�0??�
bŊ������""����t��Q�g�_c����w�fm�Qգ�b��9�R��PWs����4����P�5�7�������z�����T^��pQ���s�=���&++�>}�����Ã����t�b)OOO��ݽZ㻺���닯�/�N���>c۶m�]��	&T��&M�`2��z�*��΀�l����777rss������ͪμ8��r�;�ŋ�1c�|�I��~��~��>���c���{�YvI��)..�^`��ͥn���/����Jjj*���*, ""��&	55{��Z�>]�~�_~����������]�v���B�6m���H����a4���mgҤI�A�g�9��DDDDD�ʬ9tww��ٳ�۷�Zk�FPDD���%���
F||<k֬!""��m۲~�z�ܹ3~�!�F�b�֭DDD�j�*���éS�X�z5#F�����Ǐ'''���PƎK�=����
���d2q��9<==��]�v\�|�={�0a�.\�@ddd��mk�^�z����ٳgK]4�={��FDDDDDD����ۛ��l<<<X�h�?�8��{/͚5��c׮]���k�߿___>��S�7o��kUqq1�=�G��E�L�:�ш���ڵ�ʕ+|��W������f����k>���ZM�(KEw��/��~�:?��#���

��o�eժU�Y����Ԟ�'2q�D{�!"Re��P7ʺ&7߉��\����DDDDD�ʮ9|衇غu+aaa���УG~��v���ヒ�``��̀����Ԗ�B5O?�4nnnddd��?���Ç�����Y�,킂����$''���`�Jpp0�ϟ��ӓ���*�@dd$#G��$,,///K�v�����ϸq���sԨQ�[��#F0i�$ڶm[�y�{ذadff���\V����駟&;;�?��O���^�O�>8::���@�^�X�l���i۶-G��|�-[�p!G��[�n|��l۶�1c�p��wӼys��.}�Qbbb��/��� 11����/���5k�������ܹ��݀�����?}v���{HDDDD����3fеkW222�:u*C�a̘1��jՊ�Z�j����H�h�	nnn�����ニ�-Z��w�޼�꫌;����Ņ��&M�D�h֬:t`ʔ)lݺ�Z����b�
��?����ݺucƌ�\���n���t�ԉf͚QRRRn�.$  �6m�����7˗/���m�=f����HJJ*�oRR��Ό=��χ�����Hm8{�,�g���ӓ�-[���N`` �N��پI�&�JKKc�ĉ�}�ݖ�r���X�KJJ�O>���f���6����k١���.U���D�N�ppp�S�N̘1�3gΔ;/�/����~GGGڵk���/���6�;s�s�Υ{��lْ�m�2h� V�\�/��b��V���~�|�
[�l��ٙ��DXn߃
��l�~�z�����o~�bbb�ӧ-Z����f��ɥ��p���{���P}���5t�Prss����*����""���ӧ�����0z�h�,YBVVV�Ɠ����E�X�h���N鳃����~v����b^�uF����͛7�}��<��9r���w��I߾}qpp�s��<��3u>��|�z]DDDD�r���HKK��1+����ٙ��h�F#���4k�WWWF��֭[�v��A�Zb����X����Xn/o����`0�~��K�?�`2���~ێ�Ic�/DDDD��h4��Fc��o��矛\]]M@��U�V��?���9���|8::Z�ߺu��Y�f6�8�TPP`i;{�l`Z�|y��[\\lJJJ2���V���krtt�9f�֭M���e�+%%�ԪU�R�988�����[����jrqq)��ڵ�)77��b�UU_�%K����ŋ+���͙3���.]j3��^{�f-[�4�۷�T{[Gys��׳��my���-�qU�(���^g���{ "w�[��nѢE�A��;ӠA��=F�i:{�l����W_�F�a:��)''�4|�pӉ'�e�;��d2U�zA�Jϫ1v�����\�b���*snM�4��\pko��f����k�=T�ߍʖ�L����Eק�i��H�4���D�j�R=AAAt�ؑ��XKYll,���L�:Վ������ȝ��������…9s�EEE?~��3gRRR��h�…V�L�RGDD����wޱ���w�1g��_��ܹs���())���?�{��8q�W_}��رc<����C˖->|8����\�z�)���?~<������dff2~�x�^�ʤI�l�L��?αcǸz�*G��[�n������/[�]�p!���̚5�3g�PRRBaa!��O�>|���VwG�il7���g�����_��_�ɓ'�駟ڬ_�t)C�%%%���b������˯���ԩS�駟����cv�{�,��zV��_�̙3����e�*�QU�=i��=j����ʘ��Fjj*}���իV�Du�����˗���;����l�2����||�s�Ý�١*"##�ꫯ����9v�������ƒ>��d�W^)�������_��S�N��ORTTĔ)S,�'j{�����������LkEDD���5�c}Ewת�!5���f6l�����ϛ�
f��?�aﰤ�""""bV�;
EDD�SXX����[ov��qS���M�iɒ%Vu!!!&�4y��R�}�嗥vhݺ�	0���;fy�.]jL=���Vuׯ_7=��C6�����ܹsK�y��!`j۶�U��n����J����iL��ͪ�m���._�l�\�t���q����TXXX�|^z�
�SV]}��7�W�cԨQ����
�P��z��t�1��j�!��|G|;�q��ӠA�L>>>uǦM�L�6��㏖�.�lڴiS������SCR��}v��>;�R�ul�.]L�Ϳy�9s��������4]�vͪ�ƍ�Gy��V�ZU's���Pu�۪|&0������4$�}}ژ�;j��H�5���D�j�Å�2h� �͛ǚ5kX�f
��������a��������?��g��Y?s�L<XfyyyL�2��~��1cưz�j�z����+u��`�d2��w�Y��wbvvv��L�%&&BӦ�ϛ6m�_��>����ϟ?�T�<��+W��;w��رc�����������d2���Sk�ݬ:��9�6m�T��\]]��ϷY�|�r��n��9���׳2���9r$o��6����jժ�}TEm�����5����`૯���f�ܹ����B6���{tT���O�@$S�؀�A-喱�-ڂH5��&�`"Ap!"���-��T���1	"�D.-��r
�����x� �K
�����1�L����$�_ke��g����Lf�w���,]������KO=���/_���"�cܺuK+V�P\\�z��GyD�=��6l���N�6�\����~[��կԳgO=��Z�x��^�Z�V�M�6�n�I%��;��~�5k���Vhh���u��2�LZ�fM�}7�)�w��'O���fs�����>I��;3gΔ���S����~��Hro<Q�s���!�u�1G��W^��X�V#�G�f��f��a��9"I
���?���r�=���:y�:t���������'NH��t��VL!!!�����+W�x�(�t���N����֡C�2ew�u��� K�1c��{�9�ݻW{��t{"�/~�=��Sz��'Xc��T��/((HW�^�������T�D�����.�~�aIұc��n���|?K��l���?^/��>��c�i�F��銈�p�$��&>�PW/^�+W�8&�iH�b� IDAT„	��2I:s�RSS����e˖9&/[�L�V�rԻq�>�Ç���@����{��U�3Fyyy���g�*==]���JMMUPPP��Z��'OJ�Z�lY�ݽ�~��
ջw�21���[���ںu���V�@E;�yc������?��eggk���:x��kW\}�I?�'�=Zi�U9ǚ�"_jFC���A��.^�ݻ��W�>PFF�����q�F�hѢL��ݽc�}’'􋋋�^���\ބ���`IRAA���<� ))I�ׯw�3���i�ʕ2d�z�!���Ս����QQQ��4��999������V�Z�,�?��=Q��+>>>��{������OG�U\\�nܸQ�㺫��S�K�ڵӞ={4�|I��իu��u��I���ڿ�222ԵkWeggkӦM�}ׯ_/IZ�t���ݫ]�v��W_�$�]�V��x�Z��׫V�R^^�"""�����{�*%%E���:q�V�\Y������XG��k��&I�ի�c�'1�s-$iϞ=��|�L,�2{��;�ycO�]�V�۷W������w����w�}W�qCy充���*�XC��@ձ����w^����-��V��͛7��{��Q���K�����ի��CU؆���'�����_�e˖JHHp��']�t��>��5�c��_����/t��)���j��ю�
_}���L�R+�U�0`�$)##ãs��̔$���p�����~>͛7�����,OHH�>��#���*;;[�gϮtWw�~��G�V�s
�a2��~*+�������geeI�,X���(����]�v�;w�$i˖-����;X,edd���СCe�Z+]�}�vI�̙3չsg�K�.�1c�$i۶me��N��]��={jԨQ:r�BBB4f̘*���8~��$�M�6e�j۶�S��;�ycO����g�Q^^�x�͞=[)))ڸq�����J����DUα&������c��������ͣ��_��g�yF����7o�bbbʭ۾}{IRnn�[�~�g$I��wt��'�|�˗/��ǧL����.�ٿ�S����{N))):~��6o�,IڱcG��V��o�ر���ӊ+�~O<���T���j���.�|��.���'I�ҥ��1�f��J�>}4i�$I�[o�UnL����Y�՝x���+�ڬ���`��ow��iIRLL��„��XI҉'u�L��F�i߾}z�w4b������P-??_R��[�n��o���Fc-������
4Hiii
�R��^��/J�aRvI�2{��;�ycO���뒤+V��ѣ�?�F�����'�ܺu��rYn��S�N��P�s���!�u��k�Ç��C���w�<1h� ����믿����y(����#F�'�p���iӔ�����8͚5��6}�Q<xP)))�ӧ�Ӷ��\��?U�6mt��II��~�3
0@YYY1b�֭[��si_��-Z$___M�6�Q����/�Лo���:&�K�'�,Z�HR�Ok�D۶mu��)����'?��Ӷ޽{��_��U��С�^|�E���{4h�6l�P���%egg+66VEEE�4i������z�ǜ�n޼������!C�8m����fӭ[����+u�~��w���֭[�3g�襗^���7�	W�ԢE]�pA���z��G�����z�^U?�P]V��鵽�(]^R�'FH���SR�;�8P={�Ԏ;�q�F:tH˗/��ի5iҤ2}�;ʛ�[�XK��z��U��^{��/����b�p�<a_�6jԨ2�/^�ڵk.�ȱh�"�����;���Xo��$U�PǮ*�XC������u��
���H�?�"22RÆ
���h�
�<6q�D5k�L{��ѠA������ׯk���?~�F�%-X���ϦM���s��Z�jU���^x�5j�Hiii�1c����[j۶m���&%%9퓜��V�Z����:u��_yyy*..ֵkה�����zK&�I�ϟ׬Y�����/(88X۷oW\\��9���"9rDqqqڱc������/V��9R��<++K*..Vnn��f���pj#������oꗿ�����ջwo=��s��_��.���X�ϟ�֭[����>}��̙3�߿��~��rcٲe�F��cǎ���H999z��'�{�n�w�}e��a����U\\����r�]��;BBB��[oI������2u���+Iz���{�n]�~]_}���N���˗{�^U�g��'<l޼YV���O黶���(&&F)))Z�j�u��e�ɺ����K��T���K>i��b���1�s-Z�l)I�t�R���e�:@u1v�3���t{�ͷ�~��7o�����}�Y��I�p��w�ޭ��x?~\EEE:p�
�}��)22Rcƌ��s����:p[�=���چ
�ww[5Y,[
����;��l����r_���?��֤I�$�?˗/w�]nݒ?%����|||\��ի��ڵke�:|���ﯰ
???ۜ9s\�צM�l�5r�_�F�l�|�I�}\�^�K�.�|�rc�����<y��b����c�2e���ϯ�k��K/ٮ_�^�5��Ȱ�hѢ��[�����ٯ���͸:׺z?��Ϯ_�~6I�{��VPP����m�7vorr��mW�}����A��b����<��Ѷ��h��-]��m{��lG���Ο?o{��wm��Ѷ���;����آ��m������[QQ��/��-::���Q�d2٢��m�N�*�NLL��СC�7n�:d{ꩧl��Ѷw�y�Fc��z��I��^��S�ڢ��m_|�E�����[tt��W^q;Fx���'o�I����w���c��qK�̞=��[����V�^�r�{���w\M�cu����nU�#��&��B}��6���'\P���j�������5k�L�֭[��/8�ꫯ<nc���ڹs��x�	5o�\���z���k�i���jܸq�}:u�Ç+99Y�
RXX�ԸqcEEEi���:p��͛�ͧ�zJ��ߕ�����0���+,,L�>��8���X��Õ���ݻW��?=��CjҤ����աC���+:p�ڴiSk�y����w�ѱc��ꫯ�d2)$$D~~~j޼�z��Y�f����}�]5jԨ�8�
�;v�d2���_�ڵ�o~�>|X?��O��OKKӠA�t�]w���_��{o�ǯ�����������_k�…N�L&���٣���h�B����ѣ����?jܸq�U�������m�*''G			�ѣ��q}��Gjܸ�^~�eG���DI�…��#��W�^�9s�$�{��z-Z��$���驧�r����|�=Z={���ѣ��7�(22�̓��kUx��עO�>�����2�����W����;TO};�cܸq���յkW5j�H!!!��/�?��?�fϞ-IZ�b����㕑���zH���{��/�СCN�{�u��"_���f�٪s���t����-��̔$U�k�P||�$�b��|
�$I�=��\����b��lv��*L&�$�j���v��e}�ھ}�Ν;���Kݻwׄ	ԡC���6mRFF����$I?��կ_?%&&*88X��u�V����:{���7o�O?�T�t��%����v�ء.�e˖��/~�q��)$$��c��8�q7Fw�EAA��x�	u��Q�����q����S[�lQPP��1�3��y�k�@����$>>^����mP�233�ݿ��uIB�J��@]�h�AHH��N���S�Vz������TXg�8p`��f͚i���>}z����BOc�ܻw�u��f�RRR������IR~~�<���dz�Ԋ=z�ƍF���6l�"##�@-�����}��o߾5h`��?�I�ű��b�(,,L			G�ɓ'k���F��9_�
W�&M4w�\mڴIgΜљ3g�i�&͝;W�76:<�rU�	����ĉ�h�"IҤI�Խ{w���.@�f�ٌH2��2��F��6_��6,�(����������X��P�2335l�0��Pdff*  ��0x	��w"�@CÂ�W�qㆆnt�KmذA6l0:^���.��`8��"��bt�K�l6�C�E?�
.�[�d�v��mtҷo_M�<��0x1�bT��ɓշo_�è1��F~�����ؿ�233��233��~����233��*�����ӧ��F1~��=�p�
f�Y���0Ա��x�CPOX,��f����C���D~���'\�‚�R���ʜ;wN�V���׿�U_��bcc�-[��W8~��:v��umgddh߾}���={j���u���~p׮]ڰa�rssu��e�?�����Էo�o�d2I��Vk��]��P�?T��������+I��O~��S�N���M^y��ܹӐɕ�}�-[�Lk׮��fӈ#��]��y�Ԇ���?�3g�>��3���^�v�Ү]�4`�͛7O���5ڶ�!�?T�������Ly���t;w��]��ٳgk�С
Sxx����4k�,]�v����v��������ԴiSM�2E�6m����u�V͟?_��������~��m�j�z����C�?��Xp�J&���j�*IRrr�L&�֬Y#IZ�t�L&��a�iii:wy�G�ȑ#u��9����!��F:x�l٢���\�R			
�����n
<X+W���w߭-[�(''��xk����������v�~���/_�={���իj۶��}�Y
<ةޕ+W����m۶�…jժ�{�1=���jڴ���}�ך5k�x�b���Q�F��/�)S��I�&��[�n)99Y[�nՙ3g�����駟Vll�ӱJ�n�Z�'''kڴi���Ҋ+��䪼��.��+W�h͚5z���ӺukDŽ�Q�F)88س7�jp�_�+,,TJJ������wߩU�Vz�'4v�XJ*�ܸq�$��g�U۶m]�r��w+!!AK�,�'�|�Ν;;gϞ=Z�p������}�j���jժU�m��ύ�O���N�������d����_�l6�M�6��㏕�����$EEE)==���x�u��yGى'4g�ݼySO=��$��ի3f�����Ξ=���tegg+55UAAAN�?~�.]�$I�~��>��cݺuK3gΔ$-[��qw^I�q�>�Ç���@���ƿx�b]�r�i�RM��+�~��
ջw�2�z����lmݺUC��(&���~���H&LБ#GuϜ9���T���jٲe�-��ч�$=��#�ӷo_-Y�D(����6o�,�v��e�<xP�W�VHH���ld~B>�����Ԇ�^ 77W�ԩS'��kۇ~����롇���k�.��׿�$���:�Z�Jyyy���Pjj���ݫ������ĉZ�re�c�i�F�ׯמ={4z�hI����ׯ_/IZ�t���ݫ]�v��W_�$�]�V��e�Vk�;϶k�N{�����k���k{Ϟ=��|��q�e�:�w�UIZ�z��9�N�:)==]���WFF��v���lmڴIR���w�}'I
�0�{�W�t�ܹ2�v�ޭ%K�h�޽JMMUxx�����^��¶K3*?��`���&������~򓟸|]�v��-I��o~���Hi�̙�Z���O���fΜ�Ν;+  @]�tь3$I۶m+s��ӧ+22R�5r�m���ˎ�;�Z,edd���СCe�Z�=+�������Z;oW�?.���ڶm�T��0�LN?��ۯfeeI�,X���(����]�v�;w�$i˖-�TTT$I��6���%����ݻ�Թsg���KN�v���	������$\��}��}bЛo�)�ɤ���/���^{�������7�H�:v�Xa���|IR�.]�ʻu��t��ڷo�=$$D�t��-Gٔ)SԨQ#�۷O��F����T]�~����<��y�r��EIRppp�m�2{ꊻ���ӧ%I111N�6bcc%I'N������PIҙ3g*�g��K�ٳ���]�J�����
�Y^F�'��k�?@m`�����%'@�Pa;ԟ��g͙3G]�t��׵|�r
<X��[�wwڒwӶ߉��ꜷ}__߲��`/��u@��V��OE����8Q�իW+�n�,��g�UXϾ�^���Oǰ���֪����|w*����7c��+Y�V%''K�:u�$�ժ�K�J��w��rrem�я~$��Y���K�<�TnV��CBB����Z�J����|��/^\���'*8�\�����J˖-%I�.]*��^f�@]r�_��ٛ7o.�p�j�*;;��6�"IJKK+����/�j�*Ir<9�������$�w�}n��mF�'��k�nc�5�����+�)W��B�>}$I�-�ٳgu��u���2�L����׿I҂������b����7ސ$����㶟~�i�L&�[�N�������%��mO�>]�1[�h!Iڰa��]����<-\������;J�N�:U�2{ꊻ�꣏>*I�9s��;��7o�…z�d2�4a�G]W�`�.]�_�J���;v�����ߪ��XgϞ��ի5n�8]�vM�
R׮]����+77W���:p�,X Iz���+l�4#������i��W��0a��SVV�rrr��O:m7n����Dm۶M�O���ѣ��EFF�)sGbb�,X�����Խ{w��-Z��ŋ���0m޼��c���_�ׯ׻ᆱw�}W�Իw�2��=oWm���G;w�Tnn�S���aU&�P�IIIڱc�rrr����T�q��z�����gΜ����?��_��ŋ������>�ٳg�����VRR�S�C=�#FT�v�s6*?!�?0~���.^�����N��B˖-�����*88Xz����^�v�VZZ�����P���)44T#G��ʕ+�q�qqq�3g�x�*00P�۷WRR��͛�7m�4EDD���OEEE��_�СCլY3�w��.'{�{ޮ�~�����?���q?��s5m�T�zP��*���r���jӦM���*�٬��0���)$$D����ʕ+��^^��j����ׯ��7o.___�h�B�<�/^���zK�5r��ŋշo_���+44T�>��V�X����J�.���|F`���j���f���/I�X,._��[�b�RRR�a�EDDH��������k�رGo��W|||d�Xd6�]�n�L&�$��h��!�
��D����}�p�y@C�.@�KLLT�֭�&�X,���)!!���@]!�.�/x+����w��i
���FhҤ��Ν��^zI�F��$mڴIK�,Q�ƍ
���x+�އ�ފ�VDGGk�ĉZ�h�$iҤI�޽��Q��D>�]|_�F,�s
�� IDAT�{�I�{��f��f���^h�9
��MC��5|_�6�F�mXpP
.J�7:$)==]���F��f������񊏏7:^�����А��`�ɓ'+66��0$22��x����C�=zB�b�x7�{4$�F�mx��pK�,Qzz��a0��l��b1:^l���F��k�Ef���0j������!a��+0!�3����z��Mꊏ���!�
��w"�@C�ktކ��w��Ǐ�cǎ.�eddh߾}���={j���uw����b2�ʔ����Y�f�ڵ�Ə�:�Y<�&��?@�c�x�W�s�NY��2�8�e˖i�ڵ��l1b����ԵkW"��RQm�[�n����ە����>�H�����.�	`<�`_��N�s�N��׮]��ٳ5t�P���)<<\qqq�5k��]�V�Qp�)��6��ju�dggk�ƍ�֭�


��z��&�w`��`���0�L2�LF�Q����t��9=��3���#G�ܹsJKK302�_C�|}}����������z��&���w��gj�����Ο?�%K�h��ݺv�ڷo�g�}V3f̐t���v���JIIQVV����;�j�JO<�Ǝ���@Ir��e��j��ʕ+Z�f�~�a���:�n�Z&�Ik֬ѨQ�\�
@�r��-%''k�֭:s�Ծ}{=��ӊ���T~-IW�\Qrr��mۦ.�U�Vz����ϫiӦe�KNNִi��+VHr/OpG�6m$I�.]r*w7Fw���x�&��?@��*PPP��c��믿v�;v�1Y����"M�0AG�q��9sF������ղe���[��&?��S�w��e����[���ںu��Rͳ�γl�2�Z���ƍ:|��>�����Ǘ��իW5f����9�Ξ=���tegg+55UAAAN�,^�XW�\qL��n�P�ɓ'%I-[��R��^r�s��aq��p��X,������T�ݻW���Nw��[�z��9�N�:)==]���WFF��v���lmڴI��m�V��={$I>�`�c���u�g֯_/IZ�t���ݫ]�v��W_�$�]�VR�}�U�������G>������p�8qB+W�,�^�v�g�͟?_��yBE���u��Q���k��^�z9�y�;�B"7���4,<��L&�[�%' մ�۷K�fΜ�Ν;K��w�Y�fi���Nu���$I,Pxx��ۓ-�Ν���XmٲE����u��qIR�6m�lk۶�S�Y���W��b�(//O����СC5t��J�q�t��E3f�Ћ/��m۶i�ĉN�$$$(00��yBy��1c�T)Fw��	��?�3
5�T�ԩS��nݺ9�w�޽L�ӧOK�bbb\�ĉ�u��EIRppp�m�2{�)S�h޼yڷo���ۧ?��=z��f�7n\����n/`(ɞ|��7e��Ov��n� I~~~����q��),,�J1�{-�M�1~����U�γ�;���i�c�ٜ^���TZ���W�V��~L__�2��e���N�I�0p�@���S;v��ƍu��!-_�\�W�֤I�4d��ۿu�V��J>�B�z�Pݼ�U��^r�7�~�gj.����c}��W:t�~���9�:T�nXX�N�:�͛7;�q�]-[��ٳgu��%�l��iۥK�u@Մ��(&&F111:r�>��3}��Z�xq�.���u��I<xP=z�p�<xP����'T��ݹ�&��?@�R��7�a����7�xC���*..��Ç��o���裏J�fΜ�cǎ��͛�p��{�=�L&M�0�Q�~��ӧO;�:v�(I:u�T�c���u�g�~�i�L&�[�N�������%I
p�s�G���_��`���䨸�X999�|�_�~���I�P���� 7<��p@�����E'O�TRRR�u����c����(!!�i[�ƍ���/;^�h�B/^T\\���´y�f���G;w�Tnn��w��nn�$�&t���`�-\�P.t�V��u�G'&&j۶m:}��F��oddd�2W<��“ݽ�&��?@��.���j��j��6�4i���d��Ĩy���WTT��ϟ/I
t�mڴ�RSSe6�&???������Z�r���e�M����������H���+((H��y�8>��s5m��q�\PVE�B\\��̙�x@���
T��핔��y��9�ꣃ�������Ç+44T~~~


�ȑ#�r�J���T�'yBUx��ׂ���>�P]<��J�}�ݚ3g�Sٙ3g$I�Z�r*		�ԩS5u��
�9p�@
8Щ쮻��lVJJ����!I�����5~�xU�t�c���(&&��:��hIj֬��O���ӧW�E����*;Ny܍Qr�Z��U��p@y��L&�[�N�/_֭[����q��nݺ�h{���jݺ�,���b�(,,L			5�@e�M�0~���'\�=��T+ǵZ�<x�֭[��j�…N�[�h���F�lҤ��Ν��^zI�F��$mڴIK�,Q�ƍk�-�ʐ��!b�p.������?���׿����"��G?R�^�4v�X����x���њ8q�-Z$I�4i��w�^�����p�hXXp���Vk����Wf�Yf����pň6�Cn�����]�F�mXpP
.J�7:$)==]7n�0:u,33Sf���0����ڰa��a���D~�����у�R�jذa�ѣ��a�rÆ
3:��6l�"##��F1~��=\7y�dM�<��0�����0:^������`���x������fY,����|||���,��f��a���w#�@C‚�W`Bp���7:�Dlll��0ԕ�ÇB�`�x'�{44,�x�aÆiذaF���mذ����
J�;�N�hh|����*`2�$IV���Hn;~��:v��r[FF����'I�ٳ��^���*�G�a�J�U�f�ԵkW�?^:t�N�����hXXp@=��+�h�Ν.'o8p@˖-�ڵke��4b�EEE�k׮D
������[�n����ە����>�H���5چ+�*������fV��k�N�s�N��׮]��ٳ5t�P���)<<\qqq�5k��]�V�Q���G�žX�Veggk�ƍ�֭�


��X;����hXXp�7L&�L&��ax���4�;wN�<�l�ȑ:w�������eD���뫈������$�߿��ۤ����5�C�}�F�7�Oвߥ�֭[JNN�֭[u���}��z������z�TXX���eee��S�V���Oh�ر
t��tLW�\њ5k���+44�Q�u��2�LZ�f�F�����ڹ@���t��%''k۶m�p�Z�j��{L�?���6m�vmڴ�$]�tɩ��㻛;�ލ�4,,��˖-ӪU��oܸ�Ç����*((P||�G����4a�9r�Q�̙3JMMUnn��-[&_��P�駟���P�{�.��w������֭[5dȐj�;
�իW5f����9�Ξ=���tegg+55UAAAn��ɓ���-[V����@�������~�zI�ҥK�w�^�ڵK����$i�ڵ�[�z��9�N�:)==]���WFF��v���lmڴI�wȵ�n�g�I҃>X&V{��w���U�V)//OJMM�޽{������p�8qB+W�������:z�^{�5IR�^��<9���}?P�0~���'\���dr���d����W��b�(//O����СC5t��*���ʒ$-X�@��ᒤv��i�ܹ���Ֆ-[<Ǐ�$�iӦ̶�m�:����n��}�vI�̙3չsgIR�.]4c����ڶm�&N��v�!!!3fL���n�@������i<�L�2E�5Ҿ}���;�hĈJMM��׫T���Ӓ����L&Ǐ}�ԉ'*���ŋ�����2��e�:�Y~~��ۋ J�֭�$�o���~~~��{4h� ���),,�J�w7w����P����*}�Y��i�򎴥
8P={�Ԏ;�q�F:tH˗/��ի5i�$
2ģz6����^�Z�vI��o�{*���uhhj+W�u�G��������1~`�5�'\ࡐ����(%%E�V�Rbb�._��ŋ{\�~�͛7�j�����ή0��-[J�.]�Tf���^8�$<xЩ����*�����@���/\��~Z&�I�֭Saa��~EEEI�<��裏J�fΜ�cǎ��͛�p��{�=�L&M�0�Q�~��ӧO;�:v�(I:u�T�X�e�:��\������$-X�@999*..VNN��x�
IR�~��զ'�w7w����P���Ibb�,X��j�…Nۺw��q���$�رC999JHHp�׸qc���ˎ�-Z��ŋ���0m޼Y}���Ν;����t\I��͕T�ɢ4�����Dm۶M�O���ѣ��GFF�)�'�w7w����P��@�a�Ze�Z
�!..Ns���<���@�}��JJJҼy�<�״iS����l6+,,L~~~
		Q����r�J���N�6M���SQQ�$���WPP�>���2�~���jڴ�P�W�QQ��
VZZ�����P���)44T#G��ʕ+R�x<9���}?�>����x�p5A+&&F111���n���M�:US�N����5p�@����Kf�Y)))���WDD�$)??_���Ti4t��QIj֬��O���ӧWz��L�����wc�
O���KLLT�֭e�Xe�EaaaJHH002P�T�!�>�p��L&S��*w�6B�&M4w�\���K5j�$iӦMZ�d�7nlpt�������p.h���5q�D-Z�H�4i�$u����@m��P|��{Xp���˝dk��l��l6:PG��a�p�!P9_��6,�(����������X��P�2335l�0��Pdff*  ��0x	��w"�@CÂ�W�qㆆnt�KmذA6l0:^���.��`8��"��bt�K�l6�C�E?�
.�[�d�v��mtҷo_M�<��0x1�bT��ɓշo_�è1��F~�����ؿ�233��233��~����233��*�����ӧ��F1~��=�p�
f�Y���0Ա��x�CPOX,��f����C���D~���'\�‚�R���;����ձcG��222�o�>IRϞ=5|��o�^C�,�8��\j:	�ڄ�_+��bae�L�Y���HVT/�@H��9��t��$�J*dK�@��N�iV�B����߶>�W��\{��~�l�=��y.ٟ�=\guF1��Ɓ���(
���u�]Y�lY�����3{��,Z�(MMM���K3jԨ�p�	E��i:�3�ym5�>�@��-v�_�lٲvǷmۖ��?�&MJYYY���3a„�w�}ٶm�~��:�3�ym5��@�h��Ǩ��Leee���g�͛��~�)�]vYa���/�O?��y��13�ݧơX��S;��v�ؑ9s���w��?�����g�ȑ���3~���[�n�ܹs�dɒ����9�Cr����k�MIII��������!�7o�…s�)�d��ᅘ�;,���Y�pa���2d?��ȏ?��g�}6˗/ϖ-[r�G��+��y��"n��͙3gN�.]�_�5�rH�<��\��<xp!��X�paf͚����x�9묳r��g�I�V�tTg4�3gN��5*�?�|��jo���Ɓ��z
Љٳg��_,|���?��_��/�������$���s�7f��Յ�~�!uuuY�jUfϞ��};~��;3�[�f̘1m��3&+V�Ȼロ�'����b�ƍ�2eJ~���ؚ5k����\�$ٲeK��暬]���aÆ���gŊ���ˠA�Z���nȦM��$��G^{��ر#3f�H���3�f���͛[l�ޛ�n�����ޥ��Y�xq��g��'�|�?�0ӧOO�,Z����K/e���9��cS__��>�,/��rN8ᄬX�"o��f��O�nhh(|_�|y��裏n�C�XsP/��B~��s�1Y�xq>���\t�EI����B܋/���k�fĈ����'�|��s禼�<k֬���ۜ�����ŋ�|��L�:5I���w�&��hv�Gf���y�����8���@��
t[���]o��po4hP�lْd�ڵ;vl&M��I�&��[�dI�d�̙)//O�sS�>����������;���_�d�f�֎8�1@q|���I�{�'I�3f�BѬ�Qbƌ9��$�|���r�-Y�tin��?3mڴ�9kkkSWW��~��p��5Ig&O�����]�u���5����N�-��G�t��o�C=�O?�4�~�i�{�L�:55550`@!nݺuI����vϳf͚N��q��$ɐ!C�kk���X�/7Q'���$=zt�q�ׯO����N<����#G>���&Iv��Q�jMҙ�Mػ���n������E��V�M��+��f�7n\N=��|�y�7��_��g��K/���o�9'NL�455uz�-[�tz�O�>I��}��9�<�Ǟ�-�gEk�����:]�I:���-���
�ܾ}{��{2o5���CZ�������������NuuuV�^���{//��Bf͚U�0UVV�o��6o��V���v�Æ
ˆ
�iӦ6�űM�6b�����f�zh��Y�&�sL�q����o�r��TUU�W�\�$�U+$]�IvE�>}��Ԕ��=�N�S��:�q�/�~�=�>�(���SYY�W_}5[�n�����5*I�'Q�q�I�3f䫯�����_�5O=�T*++s�7b��4�nݺ���ѣ�$�~�m��ǚc��8�Ӓ$O<�D6lؐ?��#�?�x*++s�E�Ǝ�$�9sf��_���1�<�H����O��
*KIDAT�kw�&i�����$y��׳m۶�]�6�>��n�[����7\@'�L���3g��Gm��N*|�ꪫ����1�'On7`���q���|p6nܘ	&���,o��VN;�,[�,�V�jq�$Y�jU��ۜ	�=W_}u�,Y���Ɯ��-�]w�u��S�L�ҥK�nݺL�:�E\EEE����jM�^�ё�c�f���y��'��O&Iƌ�&���V�@o�
�


ihhدל0aBx�u�Q)))IIIIF�����*=�P!n����KMMM���ү_����f�ر�?~����}��1bD����۷'I�9�4(}�Q�>��<8g�}���0СaÆe޼y7n\������裏�c�=���;�7dȐ̛7/�\rI��~��e�����3�������Z��Wgt�;�ȤI�2t�Д��d̘1����w{�j���������թ���׸����y睹��;;�7n\ƍ�b젃JMMM�Ν����gĈI����g�ʕ��2hРݟ�W���g�̙�7t��L�6-ӦM�4�����w�&i��������3}����ʼ�8���@��
�ML�2%�vX,XP[�`A���2y��"f���8�o���=o��ǫ���'���i�������n�W\�$y��7���Og���5�zK]Л�q�nz��	��������O>97�tS�x�$��7ߜ�N:��Y�5��-�}K�=^o{�tMMMjjj���H��.�M�8t��{`��[��
�h�h�b'IR__����b�AMMM�Sz�������;
���~��K}@o�������[3~��b�IEEE�S���_~��)@�VUUU��*�����&.(����^�	�{.���b�t#��/}��@w�
E}}}��닝�
���;����Mmmm���	����d}�������-�}�Y֭[W�4�n���"UUU�N(�W^y��)@�VUU����b��e�г����4\�ҷ�	t7.Z�pЊ��V4\����
�h�hE�@+$���It'�ݶ��&��IEND�B`�PK��Zũ�

data/PEAR/package.dtdnu�[���<!--
     This is the PEAR package description, version 1.0.
     It should be used with the informal public identifier:

         "-//PHP Group//DTD PEAR Package 1.0//EN//XML"

     Copyright (c) 1997-2005 The PHP Group             


     This source file is subject to the New BSD License,
     that is bundled with this package in the file LICENSE, and is
     available at through the world-wide-web at
     http://opensource.org/licenses/bsd-license.php.
     If you did not receive a copy of the New BSD License and are unable to
     obtain it through the world-wide-web, please send a note to
     license@php.net so we can mail you a copy immediately.

     Authors:
         Stig S. Bakken <ssb@fast.no>
         Gregory Beaver <cellog@php.net>

  -->
<!ENTITY % NUMBER "CDATA">
<!ELEMENT package (name,summary,description,license?,maintainers,release,changelog?)>
<!ATTLIST package type    (source|binary|empty) "empty"
                  version CDATA                 #REQUIRED
                  packagerversion CDATA         #IMPLIED>

<!ELEMENT name (#PCDATA)>

<!ELEMENT summary (#PCDATA)>

<!ELEMENT license (#PCDATA)>

<!ELEMENT description (#PCDATA)>

<!ELEMENT maintainers (maintainer)+>

<!ELEMENT maintainer (user|role|name|email)+>

<!ELEMENT user (#PCDATA)>

<!ELEMENT role (#PCDATA)>

<!ELEMENT email (#PCDATA)>

<!ELEMENT changelog (release)+>

<!ELEMENT release (version,date,license,state,notes,warnings?,provides*,deps?,configureoptions?,filelist?)>

<!ELEMENT version (#PCDATA)>

<!ELEMENT date (#PCDATA)>

<!ELEMENT state (#PCDATA)>

<!ELEMENT notes (#PCDATA)>

<!ELEMENT warnings (#PCDATA)>

<!ELEMENT deps (dep*)>

<!ELEMENT dep (#PCDATA)>
<!ATTLIST dep type    (pkg|ext|php) #REQUIRED
	                       rel     (has|eq|lt|le|gt|ge)                          #IMPLIED
	                       version CDATA                                     #IMPLIED
	                       optional (yes|no)     'no'>

<!ELEMENT configureoptions (configureoption)+>

<!ELEMENT configureoption EMPTY>
<!ATTLIST configureoption name CDATA #REQUIRED
                                           default CDATA #IMPLIED
                                           prompt CDATA #REQUIRED>

<!ELEMENT provides EMPTY>
<!ATTLIST provides type (ext|prog|class|function|feature|api) #REQUIRED
                                name CDATA #REQUIRED
                                extends CDATA #IMPLIED>
<!ELEMENT filelist (dir|file)+>

<!ELEMENT dir (dir|file)+>
<!ATTLIST dir name           CDATA #REQUIRED
              role           (php|ext|src|test|doc|data|script) 'php'
              baseinstalldir CDATA #IMPLIED>

<!ELEMENT file (replace*)>
<!ATTLIST file role           (php|ext|src|test|doc|data|script) 'php'
               debug          (na|on|off)        'na'
               format         CDATA              #IMPLIED
               baseinstalldir CDATA              #IMPLIED
               platform       CDATA              #IMPLIED
               md5sum         CDATA              #IMPLIED
               name           CDATA              #REQUIRED
               install-as     CDATA              #IMPLIED>

<!ELEMENT replace EMPTY>
<!ATTLIST replace type (php-const|pear-config|package-info) #REQUIRED
                              from CDATA #REQUIRED
                              to CDATA #REQUIRED>


PK��Z������data/PEAR/template.specnu�[���Summary: PEAR: @summary@
Name: @rpm_package@
Version: @version@
Release: 1
License: @release_license@
Group: Development/Libraries
Source: http://@master_server@/get/@package@-%{version}.tgz
BuildRoot: %{_tmppath}/%{name}-root
URL: http://@master_server@/package/@package@
Prefix: %{_prefix}
BuildArchitectures: @arch@
@extra_headers@

%description
@description@

%prep
rm -rf %{buildroot}/*
%setup -c -T
# XXX Source files location is missing here in pear cmd
pear -v -c %{buildroot}/pearrc \
        -d php_dir=%{_libdir}/php/pear \
        -d doc_dir=/docs \
        -d bin_dir=%{_bindir} \
        -d data_dir=%{_libdir}/php/pear/data \
        -d test_dir=%{_libdir}/php/pear/tests \
        -d ext_dir=%{_libdir} \@extra_config@
        -s

%build
echo BuildRoot=%{buildroot}

%postun
# if refcount = 0 then package has been removed (not upgraded)
if [ "$1" -eq "0" ]; then
    pear uninstall --nodeps -r @possible_channel@@package@
    rm @rpm_xml_dir@/@package@.xml
fi


%post
# if refcount = 2 then package has been upgraded
if [ "$1" -ge "2" ]; then
    pear upgrade --nodeps -r @rpm_xml_dir@/@package@.xml
else
    pear install --nodeps -r @rpm_xml_dir@/@package@.xml
fi

%install
pear -c %{buildroot}/pearrc install --nodeps -R %{buildroot} \
        $RPM_SOURCE_DIR/@package@-%{version}.tgz
rm %{buildroot}/pearrc
rm %{buildroot}/%{_libdir}/php/pear/.filemap
rm %{buildroot}/%{_libdir}/php/pear/.lock
rm -rf %{buildroot}/%{_libdir}/php/pear/.registry
if [ "@doc_files@" != "" ]; then
     mv %{buildroot}/docs/@package@/* .
     rm -rf %{buildroot}/docs
fi
mkdir -p %{buildroot}@rpm_xml_dir@
tar -xzf $RPM_SOURCE_DIR/@package@-%{version}.tgz package@package2xml@.xml
cp -p package@package2xml@.xml %{buildroot}@rpm_xml_dir@/@package@.xml

#rm -rf %{buildroot}/*
#pear -q install -R %{buildroot} -n package@package2xml@.xml
#mkdir -p %{buildroot}@rpm_xml_dir@
#cp -p package@package2xml@.xml %{buildroot}@rpm_xml_dir@/@package@.xml

%files
    %defattr(-,root,root)
    %doc @doc_files@
    /
PK��Z�>��data/Archive/design/design.txtnu�[���eZ publish Enterprise Component: Archive, Design
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Introduction
============

Purpose of the Archive package
------------------------------

The archive package takes care of the different archive and compression
formats and handles them universally. Archive provides the basic
implementation to extract and create the whole or a part of the archive.

Some research will be done during the design phase whether the PHP stream
wrapper classes can be used to provide a common interface. 


Current implementation
----------------------

The current implementation implements only the Tar archive. The implemented 
algorithm doesn't support many (or if possible all) Tar archive-types.
Furthermore, a clean up of the design and code will be done to provide a
better interface.


Requirements
============

Design goals
------------

The Archive package should (at least) provide a low-level interface where
simply (a part of) the files can be extracted to a specific location or an
archive can be extended with new files. On top of this interface a part of a
virtual file system can be build. In another package?


Design
======

Introduction
------------

In the design we make a distinction between archivers and compression
libraries. If a format supports both, it is categorized as an archiver.

The compression libraries, if not available in PHP, will be implemented as a
stream. The stream functions from PHP have a different resource handler for
files and directories. Therefore they are hard to combine and makes it
impractical to use them in an archive (which is streamed). 


Supported file formats
----------------------

Archivers: 
Tar, is a pure archive format. 
Zip, is an archive plus compression algorithm. 

Compressions:
gzip, implemented as stream in PHP (zlib).
bzip2, implemented as stream in PHP (bzip2).


Since the most common compression formats are already available in PHP, we can
simple use the stream functions to access them. (And use them directly in the
archiver).

PK��Z�g�3�{
�{
%data/Archive/design/class_diagram.pngnu�[����PNG


IHDR��X�)bKGD������� IDATx���{T�U���W��	��h��N^�3i㤩y=h:�x��i*W�ۘ}C�r��/%�RP��Xi��%/��&�L��x�1R$D���:g8@���c-֜�?��|>�d�z��]



T=���	p�8Ն�T�SPm(N@��8Ն�T�SPm(N@��8����܋��ۧ�˗@
�/�`tj-vN��?^IIIF�P͒��t��!�cP��s
�(11���QDD�����9Ն�S�������ˍ��
����^0:u;�PΟ?���$�c����$:t���)�@
JLL4:�J���0:u;���P��jCq
*�ʕ+FG��)�V���P�
���
(##�F�wqq���K�}�2lk��*|�
�������P�%$$(77W������>���D(*22R׮]3:��(N�Z\\�$�g�qh�v*((0t�T7�S@�e�Z������߯��_͛7��b�7�|ct4��)@�ΝSdd�ՠA���)""BǏ/v����]��X,5j�x�yzz�]�vz��Wu���s�Y�F�4n�85n�Xcǎu�/-۹s��裏�q��2dH��H�Ν;գGyzz���GO=���9Rj�S�N���E-[�T^^^�c���ԲeK�x���*���K
0@^^^����СCu����n�W�}|��rqqQPPP�YN�<)=���ϯ��5��깽{��S�N�����[����r��裏j�������ˡ�f����C�6m�իWu��m�>}Zo�����飬�,�9�ܹ����K��>��]�~��ܹSj�ɓ'�ȑ#���V�ƍ+�E�6nܨ'�xB���۷u��5%''�W�^���/K���}�������b�l߾]�}�����k/֨��RV�R�>}�{�n����ڵkڶm�z��Th΢������s��Է�~�4�o��$iРAru�OV�2��~걌��9R���z�����S�n�ҁ4e�����l6�����+((p�����_����Ϝ9�iӦ�Ν;�>}�Μ9���\�ٳG=�=�7�|�)�'�|�+W�(88X&�I�Խ{w������OK�����u��u���;��"IS�N���?��g�*77W����C=������O�Y"##%I�W�.�zll�$iʔ)�*�^���ɓ��_�Z���SVV�>��s�k�N����j{�Eۅ�l�{cƌ���B�’��%I���{5�����Uzz��̙�e˖顇RÆ
գG}��5k��_����{��y<�H�^y���f��U�V��Ԙ1c�Emڴ����z�>�H��n�:�9���$I&Lp践m�K2o�<������[��"I�&Mҟ��g�n�Z�ի�V�Z%駝FJ���O�y���u���k����.�9RR��KY�]*��%�>}�h˖-�ի�5j��}��>�$}����kI�{�G����B����?:p�\]]5hР
�j�S��l��<����^���cǎ�~��ƍ���<
4H�/v���g�I�fΜ��]�ɤ���9sơ��~жm���⢈��k&L���������?���o߾N}�b3c����={J��^�ZbIjР��y����i͚5�֯_�۷ok���jذ���y/���s�9�u��M�t�ƍ
�Y��ڵ�~�a:tH�������S~~��w�-ZTh=P{P�@=v��qI���_�;kt��Q�OG��$22RgϞ�C=��>�Hnnn����$I�;w.s��>�H?�������@�k�[�V߾}��?jÆ
%�ѪU+���d�i׮�S_�F�$Iw�ܹ�N�*I���q�/z��T��RܱK��䡇r�kܸ�$)??���Z��އ���>���ڶm���v�G�po�8�z���`�4��?Tbb��6m����o���qs��MIR�&Mʜ�vd��ݻ�-������V8R�,6����Na:tP�^�t��)�ݻW�d�Xd�Zխ[7u���>��沈l;�T��އ�ߣ}l)999ڹs�$�S�WP�@=f�
�ڵk��Q�� �~��f͚%�_�^:t(u
[a��?~\_~�e��>|X�~�m��V$KU+�{Jq��H�{/u�#�<���`m߾]ǏWJJ������秮]�T�S��lǷ|���^NN�Ǝ���l���k:th�cm��X��2ͽf�I҄	J-�?~���(o��6z�h5k�L[�nUNN�դI�7�a\E�K]5f�ݹsGQQQ��Ζ$=��rqq18�
�P�=����7�xCyyyN�����t���/����T�1B���+u����K�V�^�t�j����Emڴ�$ݹsG�ׯ�$=����;s�LIҺu�ʼ�Hy�T///EDD�ڵkZ�t��^���c�:3T�b[I~~~��o;�g�֭z뭷$q���S��fΜ���O����O<�Ç+''G�w�ִi�4a����+**����d���{�ԩ�֮]{��-f̘�
(66Vs���w�}���l�ڵKcǎ�$M�4I��c�]�tI&�Iݺu+uޞ={�k׮�t�v��Y��-O��)IZ�t�$�#}���#يk�l٢��<������z�G�������]�����P�(!!A^^^��?���ݻ���KPtt�rss�|�ru����E�I�RSSդI����c����ߗ���/^��-[�q���/�o��F={�ԫ��*I����$=��se�o�=���)O��ҩS'u��MYYYz�GԽ{w�1y/���NJ{O��裏J�F�%5hР�s�3��W�^��l�x�P�
<X_}��&O��V�Z���C��w��q�رC3f�p�����kL�<Y)))����f͚���S���/��k���jذ��]����d�h�¾��ݘ�f5k�L���t�ڵ*�R�l���k�Myߋ�bcc��O�q��rww��~��r�a;�G�H�5.F��^��������-���ĉ
����N�8��� �#+""B�_l8��s
�}�vIҰa�jma
�w�����t��5�X�B�4�|���Fq
Ӽys�g�٬�]��T�S`�V�Z)##CO=��V�ZetP
(N�aΟ?otP�\��{�)�6��ڸ��d���FGP	III2��F��Na�j@``�F�et�4j�(u�����)�@
Wxx��1�Gq
5 !!AF�P�f���㍎@�Aq
5(11��*�"3ʏ�jШQ�����n�jt�W���Eq
�@zz�L&�~��_I�.\� �ɤ�����8y�d�\;11Q���?��c����>�V�U�ԱcG�vHH�a�j��^zI)))�X,�j�G�j�ʕڸq�


4f��K�.5���b�j���Sl�.%%�֭}��-͟?_#G��������5b�͛7O�nݪ���)�d2�֮]+I�����d҆
$I+V���d22&J���t�;��7n�8���+66�d��}��wz�����~ݼySmڴ�3�<���;����Ttt�v�ڥ�^������H5i��>�VP�a�-[�L���jР�~��_������$I������֎;t��eyxx�]�vzꩧ4l�0��
�X,�����z���U�V9�)�����wIkgffjÆ
z�����kӲeK{qф	Դi���{�)�V$q��)��f�n�Z�7o��jդI�����jϑ����'��ի����4-X�@w��ѐ!C$I7o�Գ�>�ӧO��]�rE			:|��bbbԨQ#���M���ׯK�rrr�y�f���k�ܹ���+W�w���۷o�믿��_���,EDD�5��e˔���P$R��]�O?�T���
s��Çkǎz��˕	�^ı>�j�J�BBB�mW�5k���ի�С��l٢={�h��ᒤ�����k�����
PLL�8�իW���_iii���s��u��ڲe���߯ɓ'K�v��m��e�I?_t��ٳG����$i�ƍ�w:�X,N;��m�V���עE����KZ{�������`�ym}�1��)�V�ұc�b��m߾}��W^yE���jԨ��Ν+�Ţ�����q����s�S�N���P�Ν5g�IҮ]���={�ՠA�.(7nܰ_�����D���9r�,����˔������.�ɓ'%�T|ST�6m��w�`��$��d/�X�t�L&�>��I�믿nS�.]�$Ij߾}��.^�(I�ܹ�C׮]�)�]�v����ޒ���|{���{5h�@ԟ��'�3F111���)s~[1Hy�������!Ijڴ��5[�m@}Gq
����K��_�ؤ(�R�8p�>��c-X�@�;wVNN���}
<X�7o.�%�RPP`�����t�2�m�����R���>W�{�)�b�(::Z�"�Ţ+VH�BCCe�X�?���$����:���_���W_9���~~~Z���[C���ի�v�ZM�8Q7n�вe�*4��($++��Wܽ����ӢEI��ם��lc�;�S0��j��SqJq�ЫW/I��o��+W�(''�~��������'I���Rjj���򔚚�ŋK�z��]z�)�L&mڴI���z��$��]WΟ?�9}||$I[�nխ[�t��i-Y���]�ڶ��Ν;�4���"�܋܍@}V�S~���j�ΝJMMՓO>�pm�ԩ��'NԮ]�t��yM�<�a\``�S_YL�8QQQQZ�d�SIhh������2224b����i۶m%�ٯ_?mٲE���}�]IRXX�Ӹ��wqk���K)))�Z�9���Ê�܋�9-F��o�5�E������մiSyxx(88Xo���l״iS���j�������|}}5n�8�����ۻ�k�1B,�/~�yzz���S�ڵӤI���k��ǽ���
����rssK���_�ȑ#u�}����Saaa�?~�ﻸ�
�F�i�޽N��ݻWM�4��?^��p/r)(((0:����EDD��l�6�U�Vi���ںu�$I/^԰a�4m�4M�2�������b�����S*`�ĉjٲ�CQB||����4~�x��.�Fwg2��e^��R-��^^^Z�p�f͚�	&H�����|�r5l���t��)�裏j�̙z��%I�=��BCC
NP�P�@�'���l��l6:@��jtܻ(N@��8�����'IIIFGP	III5j��1�S(N��=��@��8�`6�e6����8�S�������ˍ��
����^0:u����Ο?���$�c����$:t���)�@
JLL4:�J���0:u;���P��jñ>����<x��5k��>�L.\аa�����۷W��'O�T����L&�]�g�XƖԮ�K�.i���:x�\�"��g?S߾}5v�Xy{{�j��kK�{W��ѿ_�O�l<xP�ԣG�=�R���Q�@-`�Z%I;vth���T��/��RRRjU�©S�4u�Teee�rssu��I�<yR۶m��ի���+��{���ww��Q�\�R7nTAA�ƌ��� u����h�s(N�(�8�֮N)))�^/K�EUf���;���R���5k�,�m�Vyyy���o��;��ĉZ�r�-Z$��P��\���X c��׭[�4�|�9R~~~��#Fh޼yJJJ���W��@}�jt�+��d�Y�v�$)::Z&�I6l�$�X��Lǟ�kRSS%Io�񆂂���
�k׮����$�۷�Ȉ��bcc�����c��ƍ���t�����{�)�!W�^Ղ4`����S�Ǐ׎;�E.�eggkŊ:t�z��!C���Wnn�}L��7GY��e�cӼys��(�Ţ]�v�z��G�р4}��R���w����~��_�G�;v��o����־�%e,��*�������;C��7�ѣ��|�I-[�L7o�,v���<-]�T}��р�j�*I���5g�����������pDSE3����+33S6l�c�=f?J�Z�li/��̬pV�c}0��S�N�l6�u��ڼy��V�&M���� %$$��geeiʔ)�pႽ�ĉ�3g��ܹ���>}��?n�|��bbbd�Z�r�J���\�jy�L�2Eo��"##5|�p���+$$D�^{ٲe���t(D(���M�8ѡ@&--M,Н;w4dȐrg)kƚxE׼y�}�Y�>}�>�ʕ+JHH��Ç�F�9̱t�Rmٲ�������${�������������?V*sI��>��Segg+,,�i���0>|X;v���O?]-Y���9�Y�VIRHHH�m���x]�pA������с]l����u��q���(!!A�Rbb��t�Ç+99Y�dl��m
?T��<ʚ�f��ኊ�����֬Y��S��o߾�1c�vø�=�m�V���עE�ʕy͚5�z��:t�-[�hϞ=>|�$)&&�Lk�Uь�}^6�yWE�\�v�N�>�������ի��ﯴ�4���9�a�Z��G�/���d����i���ڿ�"##%I{��t撔�y�߿_��4���6T
�S0���cǎŶmv��-I�;w�:u�$���j޼yNs�ܹS���� ����m۶Z�p�$9MS*�g�ںu�֭[��^&�IV�UK�.��l���2�=~�xyzz�;�}�$I���ըQ#͝;W�E��_�=_y2��+�fq�_�;w���c;F��W_}U?��<==e6�%I?����̙�֭[�A��0a������.�y^'O��$�n��i�6m�8�U�c}0H��!�.]��K��ۯ���^�uI?��q��9IR׮]��4����%IC�-v��2��n U�'88X����4i�rss���h���[ϫ$����t�$�}���~y�X��U�wUt͋/J�:w���o�}�=��
?��G��k����˫�5�����!Ijڴ��8[�m��@SPP��vqq�똢n޼Y���<yz��-�ɤ��t�q����8q�$��eZ��]S
g*|L�Mqϵ�Mь5�ʺ�L~~~��4hPl��k��Y��e{��e��UŻ���)�&�y IDAT�b��ȑ#���THH����t���w�Shh����Ʒj�J��׿t��1u������1�����t��9m۶M~~~�~/wS�<���:r�6oެ3f8]�� S�(++KM�4�T�N$>�����+--M:t��5Jb���ٳg��W_�{�����ʞ��*��jѢ��\���ׯ�E��lG����)�j�J�BBB�m���K�/^,�ժ��<}���Z�x�����K��Ν�'N�Ν;�����?�Y&�IӧO����a;�:�'ϸq�$I111z뭷������\ݼyS{���+���0gy���G��u�VݺuK�O�֒%K����K���o�ʕ+����ҥKe2�4|��R�.�%)��*����$EEE)55UyyyJMM��~��ݻ�׬*�y^���lEN��j�('�vN�@�)N����'�|��g�jҤI��;i�$}���JMM����5l�P/������㣌��1B~~~ڶm[en��y���	&hݺuڸq�6n��4_�֭��/T����-[���w�ջ�+I
s���V;w�Tjj��|�I�kS�N-u�Q��<��2q�D�ڵK�ϟ��ɓ�:��&�y^�z�RJJ��V�BCC����ͅ8�E�����|��7�¼����C��Y�frwwWPP�-Z$I���mҤ�bbbd6����'777y{{�_�~���s���_V@@���ܔ��[-�Y�<�4k�,�\�R����< WWWyzz*((H3f�кu�컓��^|�E�9R��w�<==����;�kѢ�bcc5p�@5m�T
֛o������vYר��U�6m���X�=Z���rss����ƍ���8y{{W��U�<�kРAjԨ�����4�޽{դI�.E�j��{MBB�"""d�g�h�*]�|YC���������|~�^�j�*�^�Z[�nU@@�$��ŋ6l��M��)S���݈�IR|||�m����)�}���dҦM�t��
����̙3z��$I]�v58!P7L�8Q-[�t((�������ӱ@��(N���%�d�
0@ݺuӨQ�d�X�����H�u����.\���d]�|Y�/_Vrr�.\��
�{���@�̞=[������u������TϞ=5e�����3}�Q͜9So���$��Shh����7Q�@���*��,��lt�O���@��8Ն�Tw�P����@%��f�#P�P�@
Wbb��1T���@�#P�p��
;�P��ۧ���c�f�Y���F��Π8�TPP`t�@��DZ>�6���p��@zz��f͚��>Ӆ4l�0���j���վ�ɓ'վ}{�>��$I�X,�~���*�=ۘ�)���)11Q�$���C�G�68��(N��Z����;:�CBB�}�^zI)))�����:z�V�\��7���@cƌQPP��t�bt4�P�@-PRq��]�RRR*���,j):wEwi�	�n����5r�H���I�F��y��)))I^^^'0�����L&��g�ڵ����h�L&mذA��bŊ2mc���*==]cǎ���7N��銍�50��(N��z��,X��gϞ?~�v��a/r),;;[+V��СCճgO
2D��rss�c
��9ʢ�l�4͜9S����/�ŋ�֭[����j��z��w˼~ff����aÆ)??�����e2���SO9d�����k�)<<\Ђt��U����m6lؠ�{L������-[ڋ�233�|O��S0��b��bQBB�$�u�ֲX,����$��HRVV��L���۷�ƍ�}��N�8�9s�8͝����ӧk͚5�t�n߾�˗/+&&F���8�ôi�t��a�����ڼy��-[V�?��OZ�~�Z�j����2�ӴiS�3F.\�g�}�pmϞ=��>}�8��ڶm�rrrt��
m߾]�'O֍7�c��?��Segg+,,�)_XX�����cǎ2�����f�Z%I!!!Ŷm���u�����+&&FPtt��N6�ׯ�������:tH����ҥ�>���dI���>nWV�֭�e��߿_�'O�$�޽�ر˖-S||�ڶm�+V�Q�F�Z+""B�5���؊Sz���пo�>-_�\PLL����u��%�_��>���P����/I
v�f볍�o(N�`�b��;۶�v̝;W�:u����BCC5o�<�9w��)I���RPP����Զm[-\�P��}��j���fϞ���@5h�@��3�Ͳe˔�� ooo���{�.�Z��w�F��S�N�/����Q;ǎS�ƍ�0��W_UXX�<<<ԩS'͝;W�c�Ly��ɓ'%�T�ST�6m��7�F��2�L�K�j�ҥ��믿��_]�O���;wN�ԵkW��-������K��Z��iii^F�ڵ���w���X���L���z�*����q�F���*,,L_|��ܹ��={����O�=z8��t�"I�pႽ�<�0##C�OGe볍�o�9�:��������r�1Eݼy�J3�������6f�Y
6TAA�V�ZU�7o���~ZG���j�޽{%9�#ɩX�V4���?���m�W��6��Ҟ����S0��bё#G����������~���PEGG;�oժ�����رc�֭���رcNs����ܹsڶm������^*����~-_�\{������աC�
�5a�mڴI7n�_|!WWW����i\jj���5G��$���?�����h�BW�\���բE�kׯ_�����9Y�VIRHHH����qI��ŋe�Z�������Z�/vۿI�ܹsu��	ݹsG������?�d2i����=l��!""B=�$�/�K��y���SO�O>э7��#��Y�fN��x�
�3<z��$I�
��)�3l߾�$ُ^*��gP߰s
*OqJDD�>���={V�&M*u�I�&���?Wjj�Ə�p�aÆz���meddhĈ���Ӷm���a�0��R�͕�����̙�g�}Vбc�Թs�
��3�())IR�G�H?T�v��Acƌ����{�꥔�Y�V���:���Ӓ����9-F��oڅyyy)::ZC�U�f���� -Z�H����iۤI����l6���Onnn�V�~�簋��/�������)77���n:u��ÇK���)�7��ӧO�c�-[���p������W�<�V�ZU�g8h� 5j�H{��uZk�޽jҤ�}���ƥ������k!�?�E�U����2d�������\���5{��Ջ/��֭[k����l��T�/6�V���ի�u�VH�.^��aÆiڴi�2eJ����!I���/�
�X�9�:�O�>2�Lڴi�nܸ���|�9sF����$�k׮'4Vvv����{}���	&��'NT˖-��������t,@}�ntP6�֦M��d�-Y��ᚏ��"##
JV;>�'((HC�������p�B͚5�^�����˗�aÆ5��6�8�:b���
���3g�(77W>��z��)S�����舆����e2�4w�\����x�G}T3g���o�-Iz��Z�9j�S�#\]]e6�e6���R+m߾��c,K���8r5:�]���P��j�nt�ѣG@%$%%�l6�:��S����5j��1TҨQ�Խ{w�cP��s
5 <<\���F�j�)Ԁ��EDD@0�͊��7:u�)Ԡ��D�#���(?�S�A�F�2:�Jغu���s\��{;��<yR�۷���.]���u��A]�rE���~��}�j�ر�К&�I�d�X*���u��AIR�=4z��Y�^Eq
��K/�����J�:uJS�NUVV��/77W'O��ɓ'�m�6�^�Z���U�fu8z�V�\��7���@cƌQPP��t�bt4�:�c}��RRR*=�;C��,u��]			:x��ۧ>�@���/t��e�\��BkZ,�)b�u��ϟ��#G���O���1b��͛�[�nU���*�S�EL&����$55U���o(((H���jذ��v��(IҾ}���xW���JOO�رc�}�ƍSzz�bcc
LP�Q�@=V��haLff��y���7�Q�=��Ojٲe�y��<͛7�$]�z��Z``�,�v��Uꚶ�G�р4}��bs��iii�9s�����_�R�/v����իZ�`���={j���ڱcG���a�=��c���$�e˖2�Lڰa�233��DP�)��͛7���꣏>�w�}���<]�rE			�2e�����O�2E��+V��ѣ�}�v��^�l�233�D�3m�4>|X999�~��6oެe˖ٯgeeiʔ)ھ}�nܸ�۷o�ĉ�3g��\�~������t-,,L���ڱcG�����8�z�b�8|��׮]�ӧO+  @111:p�V�^-���)..�a��Ç+**J���Z�f��N���}�jƌJLLTnn�]״i۶���߯E����u��ڲe���߯ɓ'K�v��m��.����~������߿_��t��g��8َ�)�蚢�5�V�1w�\u��I�ܹ�}��=�
8P[�nպu�����d2�j�j�ҥ2����S��Ǐ/OOϻ��={�ՠAEDDH�nܸQ�=���j޼yNs�<yR�O/E�i��aʇ����ŋ��Ν;;�w��U�t�ҥ��I�&i����?����H�={Vo��V�ֶ��M�v�쟽��%I�����s��9d�	

u�+##C�ԴiS�k�>������ϊic�%�hmQ��æw�޺u떶o��td����&N����h<x�Lk�e�I���vqq)q\AA�C����>WW�][_ik�d�����K����+�~[�����,Iڼys�s�v0)��:�j�J�t��1���mIjѢ�$��N�l}�1(�S��l;��?��ׯ_?IRTT�RSS������T-^�X�O��،7N����zKiii����͛7�g����+�������fU{���%I�/��jU^^����k�=־}{I�-�)��g���X�9eddhĈ���Ӷm�4q�D�ڵK�ϟ��ɓ�:���_&Lкu�q�Fmܸ�i�֭[�^(uͪ�O>�DgϞդI�J۫W/����j�*44���j��X���c�j��"��R�k����
����rss%IM�6Ull�F�-___������W�ƍS\\�����5k�V�\�~�������<==�3fhݺu���)uͪ�����h
:T͚5��������h�"I����}�A�ԨQ#�ݻ�i��{��I�&��XP>�@=7p�@
8Щ������ٳ5{��2�ӣG��ѣ�k�T�S����$�y��Z�`�C��˗%I�����q��2��Z�z�.^����I�ŋ��W_iڴijԨ�]�
�a�pO�ӧ�L&�6mڤ7n(??_gΜ�k��&I�ڵ���'�e˖�����������O�Ǐ����vN�0�L�2oM!T��M�6iɒ%Z�d��5EFF:�yyyi�…�5k�&L� IJNN����հa��
���>�����G�T�=0b�7�T�F�XCkLlD��z�Fj�z�Ln�ME�L�d���4�˭`�P�R5����W#JT�Q��0D�G~���Ay�}�f�a���{}�&3��7k�9<��ϟ���PmݺU���S������$�<3h� ͞=[˗/�$���늈�h���Sp�'m���C�E��Y���3�;���Es
��)h3^F�Q���kt-������x�c�VhN�%$$hW4��,�,��1�vGs
�`���Z�r��1����7�0:n���<
*++���kt-����������)�����#h��jt�;���М�6ñ>@����۷o�������/����
жm������	ۗ�lnR��fs��l���tO999ڷo�$i�СJHH04��)<��Ν���»6W�ܹS�/_�$]�|Y;w����?ߞqTjj�֯_���zM�8Qaaa
7:�)<�
����K�^z�%}��'���{�S�l�ilw�wL���բE�'��$I����…���+___C�x���ln�2��ܹs��_����@���P�.]TRR���FG��������kҤI��ɓ'�����00���97r���\�R�w�Vmm����W^yE,�伋GMM�V�^���}��W�֭�^|�E%%%���G��a�$//O�n�ҋ/�(___������V^^�^{�5�|���?�����XW�^��?�W^yEcƌ�����A�nݺ���4m߾]UUU�V�>}4n�8�?��u�q�w�_�۷O+V��'�|"///%$$h֬Y����{ァ]�v���[#F�����|���r劲��5x�`9�{��!�٬��lM�:U�����6��@s
n�ڵkJJJ��ӧcǎs4�ܮ��N�f��ѣGcUUUJOOWYY�RSS���j�����O$Icǎ�$���(;;[���JJJR���.]Ҵi�t��������[o��͛�w4��9kHMM�ڵku�|�9�#G��ڵk�Z�ͪk
��6m����~������:�t��u��O�����~��f���O?UMM����\揊�RII��o߮	&�ں��c}p���:}����������{�*--�i��u����ѣz�駕������+''G���*))Q^^�$�]Rl6��_��W�={Vaaaz�'$Iaaa
�ٳg�j%飏>҅��SOiӦMڵk�^~�eIRzzz�뚺I�&���7ڻw�v�ڥ7�|S��~��f׵���2��О={4k�,IҲe���驍7���X3f̐$�ڵ��]\\,I�ׯ���1{
�QhN�@f���Oc�}��$)99Y�������"""�p�B��H��,Y���0yzz�w��JII�$mٲ���M��L�ƍ'I��㏝�w��-I������Pu��Y��ɲ�l�����次s�Β�m�������*..N6�ͩ���u���7��O<!Y,I��_��W�^�ر��N�*I�����u���K�z���2��?�T`���M�:uJ�4p�@������JI��Ӑ�Ǐ7:ו+W�c�Iү~�+��W�r����t��U���ՈB IDATI�Ξ=+I�۷o��nj]s��L���ۧ}���?��?5}�tY,u�ԩ�u��ٛb$�O�>��}}}]�kκ/]�$I�w����k���)�~�ΝG��m\���띮;t����;k�t���F�o۶Muuu��|���ڶm[�9�Ժ����֭[��[oi���~��>��C�3F7nlv]k�رc�����9�ˆ�ik�h+����ٳ����>|XC�q�>|إ�d2�ԩS��ϗ�dj�\�#nV�\���(��{���o����<���I��w�/��RǏ�SO=u�w7���kPLL�bbbt��Q��/�G}�+Vh„	ͮ3Js�ݵkW�;wN����ڵ��=�QAw��7vN�M�5J��t�R����ƍ:r䈖.]�R��s�I����u��1ݼyS/^�| �٬Y�f9j�;k؏�����?��?��������DFF�W�^:z�>��sIҰa�$I˗/׹s�t��u����2��z���6��9k7n��f�6lؠ��=��
�$y{{7��H�Y��� ��O�����$����)�	�ժm۶��ɓJLLl�611Q;w�Tii��L��t�S�N�3g��:00P�.]Rll�L&�~��J�&M�t�#a:t�I�&��S^^��Ν����*((Pii�^z�%���^{��sS뚳�iӦiɒ%Z�l��-[�T��:#5g�Æ
Saa����\򗕕I��}�ٶ
�vN�b��d�����뫴�4��ĨK�.���RXX�/^,I���q���)==]�E&�I���
�ȑ#�f���4�͛���yzz�ڵkںu���Ѭ/����u�V}��7�ڵ�222������_����ׯ��{�=�3��\S뚳���X���[z��'���#���G���z�w�]g��{����ܹ����\�STT$???ǎ;F�P___ot6YYY�Z���5{�uk����رc����V?l�V���ի�y�f���H�Μ9����k�̙JJJ28���j�J�233�.l���1b��f�6lؠ˗/�֭[���p�1p�@��ӦMS�=��#233e2�\�0�)�	��7˖-Stt�����x�l6jƌ'�|}}������<UUU���JyyyJIIQ�N��� /����?�BCC�u�VUTT���NݻwWdd����dtDdРA�={��/_.Iz���ap*�oќ������b��b1:
@��T��6Cs
��)h3^F�QҡC�#h!��bt�
�)���Ç+''��ZAhh��p+��6��)��ݻw�j�@+�X,���4:n���Q}}���Mf4���М�6ñ>@����۷�Ә�lv����Q�n�4t�P%&&*88�Ms�3�l�6��.''G���$
:T			�2/�Ì�qs��Uaaa�@���t��YmڴI۶mSjj�����)���������׫��^'NTXX���Í���hN�WXX��ۛV���kUTT(55U����/~�mڴI���m���vL���բE�'��$I����…����f�xx���ln�8�Eǎ��O�?��?����J���F�j����?^�&Mr�M�<Y�ϟWFF�����)��.護�Rtt�"##5e�m߾��������7�QLL�"##5v�X}�ᇪ��s��Lsc������(IڵkW�歬�����Ǎ�����/�l0�?���������C�jҤIڲe��{��~I�r劲��5x�`9�{��!�٬��l]�r�I��8�7q��5%%%���ӎ�cǎi��.�uuu�5k��=����Rzz���ʔ��*�������K�>���f�*�٬����*--U�������:s挞y�����e�K�.iڴi�p�c���z뭷t��M�;�����OUSS���(�����TRR��۷k„	���i��������ӧ���t�ݻWiiiN�}ح[�NG���O?���,�߿_999
WII����$I6����fs����{L����͞����?���P�����>҅��SOiӦMڵk�^~�eIRzzz�sHRqq�$�_�~.����5h>�S0��ؚ;��ih���>�$%''����VDD�.\��ނ�IҒ%K&OOO���[)))���18�u��MI���?7bk�#G��c�=���}��7��7n���@AAA1bD�s�޽[���\����ܹ����e����?���_^^.I�ի��|�?��S
��c}p�N��$
8�i<""¥���R��໎?��<��u�=����ƍ���)::Z{��Quu�f̘!OO��?{��$�o߾�fk�/]�$I�w����k�|4�`�;�ѱ����:���N�:t�g͝�^��Ԉwu�IғO>y_���裏��'�(::Z[�l����Ə��ZkC���N�
��cM��hN�M���S_|�>�!C�8�>�Rk2�t��)����d2�z�o��FYYY��=��~�
�СCU\\���2�ڵK?��t�g�w�/��RǏ�SO=u׺���ڵ�Ν;���ju����^uu�����Q�FI��.]���2ݸqCG��ҥK]j�{�9IRrr��;��7o��ŋ��d6�5k�,G�}W�Q8����UVV����g�����ѣG�׼�4a�ݼyS������S\\\��6L��|�r�;wNׯ_��/�٬�_~��r؏��t;�ؽ��ݱs
n�j�j۶m:y��MLL�Ν;UZZ�)S�8��ԩ��̙�ԥK�+�ɤ��|�z�QCw
�{�'oo�W��}�Y���ٳ�ӎ0
��O������꥗^r���k��W�aÆ���Peee���p�-++s���a� 6�M6���{���JKKSLL��t�"///���i��Œ$G�������e�Xd2���驀��9Rk֬q�	d޼y
		�����������^�ziҤI����'�|��~s�$�?^�����n�v��=�����������{Ocƌ���G�V�ΝUTT�2_QQ��������:������MVV��V����yݚ���4v�X+//���(X�j�V�^�͛7+$$D�t���?^3g�TRR��	�Z��������;��&F�!�٬
6���˺u�***��;�H�hpB�5m�4���é� 33S&���X 4�)�	��5˖-Stt�����x�l6jƌ't_���JIIQ^^����TUU���<����S�NF�pk^FM3�|���j�֭���P]]��w���H%%%)((��nmРA�={��/_.Iz���ap*�Gs
n���C�E���(-�/@��X��S�fhN@��2:�����#h���\Y,�c�V�9�v���x�ch���x=��3F����s
�`���>|��1�vGs
� ++KV���Z��bQff��1p4�Ўrrr���h2��hN����@l޼��������)@����۷�Ә�lnҳ6��U�k��d���m�9��w��_999ڷo�$i�СJHHh�Bs
���s窰��ݚ7�{>4��JMM���U__��'*,,L���FG�Sx�6z���H�5_K�c�KS2���jkk�h�"����d2I�bcc�p�B�����׷U��6��2��M>N�_:��&M���<y�Ο?�������)��.護�Rtt�"##5e�m߾��������7�QLL�"##5v�X}�ᇪ��s��LKc��?~\�g�������HK�.Ummm���>p���e�Z���P�Ǐ׭[��橬���lָq�Z��>׬Y���\��_��W��O~��C�꥗^Ҋ+t����q��
����1b�����j�*IRuu�,X��Ç����o��k׮�W���kLS~�5fggk��


r����Cf�Y��ٺr��}g���&�]����$�>}�1v��1-X������N�f��ѣGcUUUJOOWYY�RSS���6=�3g�Tuu�$��ڸq�nݺ����{>�b�
]�rEÇװaÔ���?���z���5�v�$�1�E9�s�4�^��W_}U'N�pԜ;wNYYY*))Qzz�:w����_�6mr\��w�SHH�rss����ӟ�$����-�|7�}�駪��QTT��{���TRR��۷k„	m�<z�97����ӧO+88X���ڻw���Ҝv��[�n��=���~ZYYYڿ�rrr������I�l6�����tmgߵ��?
�ի�6mڤ��bM�>]���g�5i�޽{���X�/��jU�Ν�f��{sʳ�>��
�}.IZ�v�N�8����]�z����u��q��TVV�?��ڳg�c�e˖���S7nTqq�f̘ᔻ%�囹�oI*..�$�����=�1{
@k�9ݭ!��q{�Grr����/oooEDDh�….�-((�$-Y�Daaa���T�޽���"IڲeK��i���


Uǎe�Z%I�/_nҳS�L����$�������]{����4��w��EDD�(��sI
�8v�ٱc��;�|�M=������b�$}���Z�`�z�ꥎ;j�ԩ���M�-4�]^^.��&�;=���N5��c}p�N��$
8�i��&���JIRLLL��:~�x��mh7�������s@@�$�֭[Mz��a7e��_�^���Ҟ={t��MEFF����1��z�\gΜ�$
0�i��Ϟ=��}�:~��ȟۿ���o�9��}Ҝ��K�$I���.u�1{
@k�9�٘`�%������z��:ܳ�NW�^mj�f�v��P��ܾ��$=��c�0a����TVV���"I
��\w�u7�5�t�ر�q��ݜ�9�o�嵐�����Cs
n�gϞ��/t��a
2�1~��a�Z�ɤS�N)??_&��=c���S�jÆ
Z�~����#
6���	�ɓ'u��!=��3��C�I�����ڵ�Ν;���ju�����;�Z�}��^p�F�%IZ�t����t��
9rDK�.u�}��$I���:v�n޼��/�>��l֬Y���]2�Gô���/��/7n��mۦ˗/�?���t���F�)IZ�d�JKKu��
���:�ok���V��Ed?&�v��ۏ+h)vN�MX�Vm۶M'O�Tbbb�����ڹs�JKK5e��{�:uҜ9sׁ���t�bcce2�����To?j�n;��!���!���rss%�]�ȴiӴc�UVVj���N�BCC]�$�}6L���*++SDD�SmYY����vN�b�������뫴�4��ĨK�.���RXX�/^,I���q���)==]�E&�I���
�ȑ#�f���1�͛���yzz����mx��}�;�q�<bĈ6���﯌�%$$(((H���


��ɓ�f��ɼ��9��ѣG�s��***ryOQQ������������F��a���%��*�_�w^����*�;V������k��?���4g����K7n4:��[�j�V�^�͛7+$$D�t���?^3g�TRR��	\V�U������5pac��Ĉ#d6��a�]�|Y�n�REE��y�I��
N�jjjt��E����$i�ԩ'z8L�6M=z�pj���̔�dr9�����f̘1ڰa��-[�e˖9�Ԍ3J�vn?�',,Lcǎ50�����W)))���wG�O^^�V�\�N�:�<lhN�M̟?_���ںu�***TWW��ݻ+22RIII


2:b�

Ruu��f�������it��ƠA�4{�l-_�\���+""��T�aDs
n���C�E���(�f˖-FGx�=j�=cx/�S�fhN@��2:����\�#h���\����Bs
�(!!��@��9�v`�Xd�X���;�Sh�w��ʕ+���>\o���1pF�QPYY���\�ch���\�߿���vN����@X�V�#�v�9m�����*//W߾}�w�}���:t萾��+����d2)22RV�U�������fI��fkq}NN����'I:t�Z)%�Å�qs��Uaa�Kƍ7���*??����JUVV��?�ҥK��϶W���������׫��^'NTXX���Í���Xq���
�/_�\����ر�^}�Uegg���XEEEJKKӈ#t��u%''�…��8���Z�h����d2����X-\�P���F�x�М��l6;��1���wmܸQ>>>����/�ۿ����_�U;v����"""�b�
��G?RMM�6n�ht�v�������kҤI��ɓ'�����00���c}p#.\�ʕ+�{�n��֪O�>z�W�`�Ir:����F�W�VAA����+u��M/���������#IN�0��m6�6nܨ��zM�<YO?��]�̜9S;vT�~�\ޓ���y��),,L�V��$]�rEiiiڱc�.^��nݺ)::Z3f̐��_�Ynw����X˖-SAA�|||4|�p����֭[���ŋ���V������Utt����ʕ+�������ѣ��f����5u�T���7i^�G�)��k׮)))I�O�v�;v��&���:͚5KG�u�UUU)==]eeeJMM����7P�7�=��L�{���ŋ��b�
]�r���q��U���:q℣�ܹs���RII����չs�F绛��{O������ׯk˖-:t�֭[����F��r劦O��3g�8ƶmۦk׮��~�駪��QTT�˽��(���h���0a�}��aı>����L�>}Z���JOO�޽{���洃�ݺu�t��Q=���������������p���(//O���$6��q]UU%Iz����;o�޽U\\�h^Y�v�N�8���G�իW+88XǏך5k�{�ݻwk�ʕڻw������g�jݺu�|�����Μ9��={꣏>r|��?�ܥ���X��v�����k�-�S0��lv���g�}&IJNNV�������-\�����%K�(,,L����ݻ�RRR$I[�li4׭[�$I:t�g�;��M�2�q|���0���ˎ;�Ԙ7�|SQQQ�V�������4gcv��)IZ�`�����;��/�K����rIR�^�\��y�5���&N�:%I8p��xDD�Kmee�$)&&��w?~�ѹ���t��Y}���ݻ���u�u�~l΀����9{��}�#Ieꓮ IDATC�u��$�#���^ӿ�s��ҥK�$�{�1{
�Es
��XI�H��]}}��uC���Ys��W�6zРA:{�����?kƌM�|��wMi�}������;�WWWw�://������q�M�����ov�;�~��kk��(�X�DϞ=%I�v��Z�L&�$)??_6���OIII�s���J�֮]����ow��W�킃�%I�r�_�3K�l�v�c���^JKK��<(I���w�\��z���2�ڮ]�J����]����5��)��Q�FI��.]���2ݸqCG��ҥK]j�{�9IRrr��;��7o��ŋ��d6�5k�,G���~�$��?P\\��_���^{M+W�Tyy����TWW���
���j�ԩN�h�ȑ#%IK�,Qii�nܸ���RG�g�}�Q(Iڼy�jkku��	-[���~��w���Z�d�$i�����/8r8p@7n����7���.�}�����#�ng���[����Z�ڶm�N�<����Fk�s�N���jʔ)N�:u�9s�8�u��%����d2)??_���\^^^Z�~�֮]��k�68WϞ=��o�3��iӴc�UVVj���N�BCC��F��M�6�׿��~��_K�������{��<��S�8q�=sM�2E��_T^^�t���ѣ]�P�
���B���)""��}��ۛl��)<P���4���Wiii���Q�.]��奰�0-^�X�������Szz�,�L&�<==��#Gj͚5N�{̛7O!!!���T]]�c���S���Sff�����}O;v�������4r�H-Y�D6l�3�<sϵ���+##C			


�������4y�d�Y�F��9s�(..N��w��㣨�(-Z���^�b��.///�W^ѪU�������(--Mqqq
����F����d��ѣG�s��***r�WTT$???�7�V����z�C���ʒ�j����;�[SUU�Ǝ���`����df�Y�����V�Z�իWk���
		�$�9sF�Ǐ�̙3����nY��V�$)33��k����)��#F�l6kÆ
�|��nݺ���
���;������0m�4���é!33S&���%p�nc̘1��e˖)::ZC�Q||�l6�5c��>|}}������<UUU���JyyyJIIQ�N�����2:h����+44T[�nUEE����Խ{wEFF*))IAAAFG|d4H�g�����%I����"""N�`�97���!��"��bt���f3ln~Mñ>h34���М�6�et%:t0:��X,FG��М@;>|�rrr�������±>h3�@;ؽ{��V��1��Ţ��L�c�6hN����@�d@�q���)h3�T^^��}�:���fI��f3"R�f���Ѿ}�$IC�UBBB���ihN�7w�\ڄҖ<���T�_�^����8q����nt4�G��+,,4:B����բE�'�ɤ��`���j�…���5:�#�� f��q�
Z.##C�ϟפI�c�'O��畑�a`2�G��F.\���+Wj��ݪ��U�>}��+�h����t4OMM�V�^���}��W�֭�^|�E%%%���G��a�?7v���&;;[+V�Pii�:v������~&___G�+W����;v��ŋ�֭����5c����9���ŋ��o���B���*::ڱ�;5e]�����5x�`9�{��!�٬��lM�:U����t��)��k׮)))I�O�v�;v��&���:͚5KG�u�UUU)==]eeeJMM���o�6s�LUWWK��_���7�֭[JNN�$]�zU����N�8�x�ܹs���RII����չsgI�6�L�>]gΜq�n۶M׮]kѺ>��S���(**��=QQQ*))���5a„���7���Mdff����
Vzz���ݫ��4�]A�֭[��G��駟VVV���߯��������Dyyy��wI��l��r�^�ziӦM*..����%I�}���ڵku��	���8��^�Z���:~��֬Y����3gΨgϞ�裏����{]�T\\,I�ׯ��{�c���S0��lv��ظ��#99Y�������"""�p�B��H��,Y���0yzz�w��JII�$mٲ�E��ϟ���Pu��QV�U�t��e���0���ˎ;�;w�$-X�@�����/٢u���K����N�?��S
���&N�:%I8p��xDD�Kmee�$)&&��w?~�EY����9  @�t��-ǘ���8=g�~��Yǘ������7X{���ҥK�$�:���m��t�1:�]R;^�����C�����իW��A��ލ�7�7��ٳޙ����)�Y�=����Fq���d���97ѳgO}��:|����?|��K��dҩS����/��Ԟ1%I���:y�:�g�y�1~��!G>��={�ĉ:p����eee.�mκ�v�s�Ω��Z]�vu�W]]�@�r�_��iԨQ���K����L7n�Б#G�t�R���{N�����cǎ��͛�x�>����f͚5�Qk�=�~dNk9r�$iɒ%*--Ս7TZZ����:j_x�G�t��
��oӻ�ۢu���W�?�C��}�^����)�	�ժm۶��ɓJLLl�611Q;w�Tii��L��t�S�N�3g��:00P�.]Rll�L&����[�uڴiڱc�*++5}�t�{���NcS�L�_�����kƌ��ѣG�4�4g]Æ
Saa�����Tkߕ�&�
vN�b��d�����뫴�4��ĨK�.���RXX�/^,I���q���)==]�E&�I���
�ȑ#�f��C�͛���yzz����U���﯌�%$$(((H���


��ɓ�f�8j}||������8���G�F�Rrr��{���ѣG�s��***ryOQQ��������t����7:���,Y�V����5UUUi�ر
V^^^��ߝ�Z�J�W���͛"I:s�Ə��3g*))��p7V�U������5pac��Ĉ#d6��a�]�|Y�n�REE��y�I��
N��6m�z����8���)���r,��)��1c�H��-[���h
2D����l
Ԍ3N���UJJ����TUU���*���)%%E�:u2:�#����i�ϟ���PmݺU���S������$�4h� ͞=[˗/�$���늈�08����܄���,�,��Q��
�8��6Cs
��)h3^F�Q���`t-���+��bt�
;��BCCot-�g�y���vN�>\Ç7:��hN�dee�j�@+�X,���4:n���QNN���Mf4�)����x�#h�͛7��at<��9���\}��u3�͒$����M�k�s999ڷo�$i�СJHHh�|0�)<��Ν����f7����*55U�ׯW}}�&N����0���
���><�
[��fk�Ɩ��Z-Z�Hqqq2�L
Vll�.\����6���� f��q�
��������kҤI��ɓ'�����00������;����?�w�;	5-���Ҩ�%:�z�t��Ȼ�ǟ�c6�u�-Z���
��bb�"�B's!�2��o7@Q��s�p�r$����<��{}��u]c�s>_�@.^������ӧ�;w&((����I-,X����:w��������̴�wLqcr�39r���`�u��O<��ٳ�t��GѧO>��#���Y�v-;v�A��~
6�`0�v�Z��Ӌ���������������J�@DDD
��7�S�NY�RRR�:u�M���L&L�@rr����ٳ�������…qv.��_|���Tn޼ɗ_~Ivv6o����~�!aaa�nݚ����e�222�ҥ�M�.]����HLL�<�L�]���������������*����Taaa�:u�F���ݻY�x�UE�իW���L�6m'!!���ڵkGbb"QQQ�L&���du\RM�6eÆ
���3v�X�m�f���	��f�����@�V�lƘ��}DDDDDDDDDDDD��2o����8���;�z�-�q*W����/ӦM��w�֭̚5\\\x�ᇙ1c���e|e0y�d���pss#00���4�~���'<<>��S<<<,�>�MtɭY�fV}DDDDDDDDDDDD�m}DDD*�'Nо}{�v___��'O�   ��\G�)��l5o���9�$;;ۦ_xx8���\�r����[�]�|�5j،3����������������I�)"""�{s�������ɱ:vrr*�On׮]+l��V�re��b43�lذ��7o�h�"�ϟo3��ٶ؛�-��EDDDDDDDDDDD��"""RA4i҄_��������gi߿�M_OOON�8�ƍ���,�0���^�^�z|��'�ر���d}�Q�֭˹s�HMM�nݺV�RSS-}DDDDDDDDDDDD�e�1d�/����ٳg���DVVd���6}{��
�[o�EJJ
w���ҥK|���&L�`�k�<b�
�����?���h��}K�{���}DDDDDDDDDDDD��)"""D`` �|�
Ǐg̘1��3f۷o�Y��R�
�&M�׮]�˗/3d�<==ٸq�U�VC��PQ���0u�T��yv�����i۶-]�v%66���$|}}��$%%н{�R�CDDDDDDDDDDDDJ�*�����GL&S�IU�Ve���P�V-*U����3g�����ҷz�ꄄ�`4������z�����˭�����4n�233�����׿���zJ���qww'..Φ\\իW�T����*����T u��a���VmgϞ�^�zV����k���k��ٯ_?���g�^��(���5�0��N��ԩS-�ժU�h4�l�2N�>M�ƍ8}�4�����_��ݽPq�������������c�r���HѣG�ׯ'--���l�;�;�@���a�=z4
6$,,������͖E""""""""""""r�Qr���H1`��̙C�>}���cذa�L&j׮���a٨Z�*3f� **��g�r��Y����1cU�Tqtx""""""""""""Rm�#""RAL�<///6o�̱c����䡇�s�Ό7�
8:�2ӡC����;w./��2����JDDDDDDDDDDDD
C�)"""���3F�����P�A�v��L�����������������H�Qr������������������%�����������������H����DDD$����ADJ 22�aÆ9:�
E�)"""�h���ADDDDDDDDDDDD�\)9EDD��F�F���)wJN);w��O>qt"R
�u��+����0DDDDDDDDDDD*gG ""� 8y�$����CDJ(22���G�!""""""""""R��r���H9���pt"R����ADDDDDDDDDD��Q�)3JN�2�m}DDD�ÇӢE�q���iٲ%-Z��_�~x{{ی9r�111>|����l�R�5
&��d��!""�={���������d��]dd��C�\����ԩ���)7JNy��������Z%�\�t���x����ߘ={�͸�K���ߖg����?�p�B֭[GNN#F���LJv��9:4�r�M����h$,,��a��������%����<�bcc�<רQ#����������IHHࡇ���Z��*�ܸq���~��C����	��!C�6m���T�Z�L������a4������ADDDDDD��9�EDDDʋ�`�lws?�'--��Z�8p����yhh(.\`�ȑ��Q�Fq��BCC������������ȃI�SDDD*��/��'��s�NnܸA���y��:u*`]�$##�e˖�u�V���z����q�����
`�c���9:u�Ć
����m۶��]�v���GTT�M�������$%%��7oR�^=z��Epp0���y������ŋ���t���գO�>�?��ի�ĺx�b�x�
|||X�h���]���;ҠAK��
b0X�v-�>�,5j�(�}�#���tt"//��2�[DDDDDD��(9EDD���~�:�ƍ�ԩS����Kbʽ233�0a��ɖ��g�BRR.�ڦ'/;v��ٙ]�vli߹s'NNN���ٌ����Y�l�U۹s�X�v-iii̜9��Z׮]����ѣV����ILL$$$Ē�b6�|���-�([�l!##�.]���ߥK����g�)��EDD�����D8F����0G�!""""""�0��GDD���ԩS4jԈ��v����ŋ�*���^����dڴiCxx8			DDDЮ];-�N�Zb2���<<<hٲ%��ҥK���-������ԩS�f�5k�0e����ٵk_|�qqqy^�ʕ+9z�(�7�\߲e�hԨG�a���6c~�a���-	/����j�ʦ����GDD�AFNN�^z�U/���跼��������)9EDDā��+��m۶��[o��S�re|}}�6m�ͼ[�n`֬Y��������?̌3���.t��:u"''Dz�Ϯ]����ɳ,��;����y��Gټy3�1�>p�:J^�]_۶m-�a���;�1AAA�-�>@ӦMm�6k�̪��������������m�#""RA�8q����[������=y�$v�:r�H����#44�]�v1p�@K���-}�ne�I�&q��!�s999y�s��iڶmk�n��3g�،1'��]�|�5j��5���������������H�Pr������F�\%%w��r'x899�'��*��ֶm[���سg�o�&!!�R�Ş>��C�ѤIz��I���iݺ5Ç/������ܽUS�{��l[��f�~������������H�Qr���HѤI~��W���oU�d���6}===9q�7n��ӳD뺺������ݻٰa���t�Ё*U���g�BBB�]�6G�����ʢR%�A5j����ٷo�ՖA���\SA�֭˹s�HMM�nݺV�RSS-}DDD�b�|�2���dff����ٳg�S�N��oNr-(��ƕD^	����xxxТE��ĉ�\爘��vQ�����Z��v�?*ۏ����}�o߾̞=���$���8x� �g϶�ۻwo�z�-RRR�s��.]��?�`00a�K_�/��[�cN�	

�J���ݻ���$%%�iӦY������ի�f��deeq��u�޽�5[�h��ҽ�m�>"""R񄇇���	@ff&k֬qpDOvv6W�^%!!�7�|��={�����DDDDDDD�N�)"""D`` ͚5��~c̘1������~�ͦ�1ch֬�o�} IDAT ((�N�:ѿV�ZE�*U�4i�����ɐ!C8p�ݵ��(/^�:�ǜd2}�t�t�BPP?����|JJ��q�G���ˋӧO3v�X���;v,gΜ��ˋ�c��sw��ڵ+III6��m�Ir������x�笎�w999��a^�����ܹs�_��?��O$&&2k�,��V�r_k^/{cDDDDDDD�l)9EDD�>b2�0�Lv�U�Z�ŋ@�Z��T�>>>̜9����Y���			�h4��鉋���Ջ�˗[Uy�7hܸ1...�O"��#�XJ�רQ�V�Z�y
o��&����jժ���ҺukfϞ���X�n��q5j� 44��ÇӠA\\\hР�F�b���xxx�s���߿?������ٜ����z��
4"""R�$%%��?P�^=>��3�ԩ��d⧟~rthJ�ʕy衇x�gX�j+W�tpT"""""""�G���
�N�:L�>�o���={�N����W��U_^{�56n�HBB�}�s�����۪_�~����IHH`˖-�m����111�L&�mۆ���?B��[�F
f͚E\\�v�bŊ��ۗ���c2���㏹s�e�{լY�ɓ'MBB��Ѽ���6�)y%�T�V
��Ⱦ}�8}��������۷��� �����"""�'N0~�x���pss��ӓ��@����wrr*��dbذaԯ_WWW�7oΔ)S�v�Z�q�X��Q�FQ�Z5F�i՞_l'N��C�T�VͦR\qbغu+������R�vm
�޽{�����ɉ�
���e�oVV
6��7+�s)s5��g�i\JJ
�G��q�Ƹ��Ҹqcƌ�/�������{%%%ѴiS:t���)��=���x"""""""%����T=z�`0�~�z�������رc���;�$��]ff&�(�D�ѣGӰaC���,maaaxzzT�뉈�������㏳d�~��7�0���t�Ё���"�Y�jU��+V������x�"�o���ѣ������у�ׯ��q��V�^
�����W�^mI|��رcٻw/T�V�D���JpO>�$			ܾ}��W�E׮]�������LJ�={r��y6m�d�Ott4�ϟ�gϞ���e�\~��GZ�lY�1�6m��ח�+Wr��n߾͙3gX�b�۷��o��S�|����={r��%>���ׯ_�-%e�DDDDDDDJN� ��9s�ӧ~~~6��D�ڵ-�����͛g�cR~�WժU�1cQQQ�={��g�Ō3�R�J��'""�Gq��e�Jzz:�&M�_~�ƍ�޽�q�Ƒ����h������c�5k��ҥK-_;v�_|�;w�0a��;Fff&;v��ۛ�����&�o���s��ѪU+p�ꇏ�gϞ�T��/����IMMe޼y%��^`�ĉ?~���Lv�܉��77o��_��W���f[�l��󡡡�7(�s�Kvv6/^d�����3���J�ƞ;w��#Gr��

DRR�n�"))�A�q��u�ιs�,cJr��v��O<�������ڵk��-M��DDDDDDD4JN� &O��k��F�V��R�
���xzz2d����hܸ��C,�.P�R%Z�h�o�Q&kt�Ё��`�Ν�ܹsy���-��DDD�(���.\��ԩS�?>���T�R�,Y«��Jjj*�~�i���ٳ��ӧ��ob4-�-Zĭ[�1b��9͚5�r��t�ޝ5k��j�*�9�/_���>k�n>6��˴i�hӦ
������1c���iڴ)�+W�k׮,Z�����|cy�g�S��7o�J※?'mڴ�ڵk3t�P���%�K...ԯ_�aÆq��i�L��/��o�f,�ڵk��ݛ
6кuk\]]iݺ56l�w��\�r��ZƔ�>l޼�'�|�7n�O<�g��l1UX���yP)9EDD��pvv�h4�j�*v��Ibb"7nd�ԩ4h���ڇ~Ȟ={��ۻ��1�̛7�y��1jԨ2[GDD�¼��ĉ�7W򈉉�s���TF�EVV���g���V��[�ی5���p��1��+W��q�F����:������DTTW�\�3��={ڴ'��^zɦ�s��\�x1�8���x�����bŊV�V�^��۷	

�T|+�璗��~��~��B�ߺu+p7i���WJ������&����>�_����s��-V�Z��gY(�� """"""� Pr���������������݊�[��n������s��q���Y�f
...V�9@۶mך5k�u��z������\ӦM�ٳ'�n�b�ڵy�ѤI����bּys�6www�ܹS�xs�������[�@ɟK�-��ܹÕ+W���gԨQlݺ�.]����R`��5����7����_�>�9���Lrrr�>���m1��U\��y�)9EDDDDDDDHKK+Q��K�A�5��믩]��M�k׮P�z�B�e޲g۶mv��o�n��s�HIc1suu-�{=��t�ڕ�����8L&III�����[�������L�Z��ҥaaa�����HKKcʔ)�MOO�f͚v�רQ��ׯ[�Jr�k֬���999�?����"�QZJ�9�������<h��""""""""T�V
��W��[y�^e�C��ꫯ�����իy��G�]Ü�P���d����B�MLL�СC��[�XJ[��)���@ɞKa����䟂��ORSSힿz��U�~]���c�֯_������6�D���~"""""""tJN)G�>�^zU�Wxx���)3����ڵ�H�n޼�ȑ#����w�!   Ͼ��p���
5��+x��g�M

��_E���
>�Z�j��W_q��M"""�^�:�F���W��RT�n�*����%&&�=���`��ޯ�s�[�n�c�=����Y����T���9��������QUrt"""�nݺ��0D�xyy9:�2��O�w�^�{�=���K�Jֿ2���`Ĉ��/!::���op��´i��]�w���۷�e˖ѵkW�sIII<��c4mڔ�Ǐs��V�^
�ĉ�788�իW�j�*�{�=\\\
�ޢ�R�V�J`` �~�)|�/^dܸq6�����ʕ+h۶m�}����?��|@�~�pv��3O���̝;�'�x��^���W^�o��o�a����ر''��\f���s��S�!88��5kϓO>Ibb"7o�d۶m���<��T�T�Y�fY�DEE�駟�㏳r��^z�%���

e�ԩ�?������;F�	��1c����̙3����s�δoߞ3gΰu��B]oQb)+�Ǐ�>l���=��deeq��Q�{�=&O��M)�K/�D�5ضmC�!99���L���2d۷o����*��4�˗/�~���ܹ�/�����ZZ��9�������<H�rrrr����Mxx8�����3k>���h4`y_��ED�GNNN���a4��+::��C�r��
�s}��g���K�c���?�P`���!$$�q��a���;w�ᆪJ�*�1���BCC�$�t�R^x�F��ڵk,�2y�꣰��4_^��שS'y��8p��y��\�]�0ƍǒ%K
�ƍ6l��m����X�v-��j/���i�&�~�ij֬Irr2�5ʷa���|�y`��~~��I�SDDD�QNN�^z�U�_���+"�G2`�����رciҤ	�+W�f͚��ۗ���?����E^c�ر�����Z�j���J˖-y��wٶmU�T��իDEEQ�n]Ku���Fjժ��_�իWK-��f��b�j�YQ�KA���h֬#G�d���6�)�8p {��%((OOO*U����'�=�?���Mb
��}~ꩧ�8q"���n�TJ�9�������<H*�EDDDDDDD>>>,[��P}�\�R�5�w�N����<_�V�<�S�����&����+iKQ���|~��y����.�s)h͒���GY�jU��+���`�,XP��Y+����DDDDDDD�.UN�2��)"""��ÇiѢ�����lْ-ZЯ_?���m�9r���>LJJ
[�l�`0`2��'�<DDD�g����>|�C�yP)9EDD����k�Lr��%��㉏���~c���6�.]ʷ�~[��ڏ?��…Y�n999�1ڵk���DDDDDDDDDDDD8��GDD���F����@vv�U{vv6			<��C6cL&�C��ܸq���~��C����I�F�2dӦM�ƍ�KDDDDDDDDDDD�A������`�l�s?�'--��Z�8p���t:u����ʅ9r��mԨQ\�p���PF&"""""""""""�`Rr���Hr��E�O�N�>}�ܹ3AAA����Mj���`��йsg�g�}Fff��Ͻc��aN>����jߵk~~~61��||������֭O<��g϶�d���μy�xꩧ��駟f���\�v��{��O�>L�0�2~�ڵt�ؑ
X�7l����ڵkIOO������������HYPr���Hq��uƍGtt4iiiܾ}����N�j�733�	&�b�
Μ9��۷9{�,!!!����٦'/;v���ْ�b�s�N����&����_$11��7o���ʗ_~���-�]����?Ϛ5k8�<YYY�;w���pƍGFF�͜���'==ݒ��e�222�ҥ�M�.]����ALLL�c��Sr���HƩS�hԨ!!!�޽�ŋ[U1[�z5��ɴiӆ��p����]�v$&&��d��1�LV��lْÇs��%�n��_~�ooo�ԩS�6mʆ
���g�رl۶�r~�ʕ=z�ƍ[�oٲe4jԈ#G��|�r�9~�a���9s&�{��V�Z��5��#""""""""""""e���y���F'�v��dI�x뭷x����eڴi���+V��n�
��Y�hԨp7�cƌ<���h\�;u�Drr2�v�b��ڵ���˖?�5y�d���$$$���4�y{�׶m[�N��ĉ�����3((WWW���Ç���0�5k�̪���ȃ,22�ʕ+;:�Bdd$Æ
st"""""""���
�ĉ�o�ު���צ�ɓ'�;ב#G
�������V�)�h޼��k��N�>
�MH���zϜ9c3�9������ԨQæ����GDD�A��W_��W_9:y@(9EDDāro�c�����^999V�NNN���ڵk�
��m����ƞ={�}�6			T�\�nRL~�t����roKn�VM�w^gg۝�mEY[DD䏨��DDDDDDDDDJ��SDDD*�&M��믿��~��%�������ɉ'ظq#���%Z���___v��͆
HOO�C�T�R�D��֨Q#�?ξ}���ڷo@���nݺ�;w���T�֭ku.55��GDD�A6|�pG� ��֭��V�"""""""%�H�:y�$			�CD��������˯����ٳy��wiٲ%�b���6}{������y뭷�<y2�<�W�^e��լZ�
����E����Drrr8y�$^^^v���c��݄���ɳ�ի˗/g֬Y���<��$''[��{���ѢEΝ;lj'l�P��"�hѢ�c�H"##6l��#y0DFFZUy)9EJ�Ν;	tt"�`4	st����@����?Θ1c��;f��o�΁

�:W�J&M�d9�]�6�/_fȐ!xzz�q�F����(/^�:.M�G�����ɓ�;�ꜗ��M�=]�v%66���$�m������%�����х��a4��A�'gG L999z饗^�~=�(1�L�L&��V���ŋ	�V�ZT�T	fΜ	��~Ǭz�ꄄ�`4������Ku�{�����4n�233��#�P�NjԨA�V�J�-jԨAhh(Ç�A����РAF��������(p�������N\\�͹��8�W�N߾}K=vɛ*����T u��a���VmgϞ�^�zV����k���k��ٯ_?���gՖ;A��ɉ����s�-�8���5k2y�d&O��o�y�Y�Z5�F#˖-����4n��ӧO�o�>^|�E����[DDDDDDDDDDDDJ��S�L�<y���G�!"���W�l�GңG222�2e
����z��8q�������;8���ѣٴiaaa�$���0<==m�8[.\`��ԪU�o���S�N1x�`4h@ttt��g0���Ç[Uz+��Z�*>>><���t�ҥX�4�����`Ϟ=���3|��r[[DDDDDDD�4)9E��Ν;������h$,,��a������3gs�̱:W�vmƏ���/U�Veƌ���<��DEE��'�P�JG'""r�KJJ�u��V�mڴ)��_�ubcc�V\7n�`������g�…����q���d�…�[����F�����ڵ+��EDDDDDDDJ��S�\���8:��)��p&O�����7o�رcdff��CѹsgƍG�
�}�C�3w�\^~�e|}}���HŐWr�����N����-��srr�r�
.$**�%K�99�4�*ȍ7x��:t(���2�iӦIժU�-�Ҡ��
����ш�htt(��H���g���,^��r�`�,XPn�CJ���u���W^!**��~���!�+44�.0r�HKۨQ�X�f
���;0:��svt"""""""RqƌcՖ����``�֭V�bbb0���K�>}�0a�e>sr̽I2��ddd�`��ܹ3��>#33�б;;�5H���HOO�gϞ<���l��'O��`00hРR�+;;�E�1d�:w�L�=����W_}e�/==��k�ұcG��x
6�`0�v�Z���}�""""""""�%���8ȹs������pw���Dxx8M�6�d2�|�r|||0�Llܸ�C����a���~ki�|�2gΜ��ՕnݺY��ϟOzzz��$���d„	�X��3g�p��mΞ=KHH���mK�r�
~�!�
�F��1�S�NY��c�z��Q*q-\���K�r��In߾MFF�_��aaa�~[�l!##�.]�جץK222,�[DDDDDDD��Pr�H._����NNN���q���r]���	''�rWZv���/�@�V�pww��͍&M�0t�P6mڔ�8G�]ޖ,YB�V��m=�-���؂�DDDD��KJJ�M�6v�===y�Ǹs���� ++��ggg���y��X???���-k<������3s�L����2Ȝ0�z�j���iӦ
���$$$A�v�HLL$**��������ƍ	`���>������[q���)ݻw/��6l���i����ر�)S��n�:K���x����f�#"""""""RQTrt"����pK���L֬Y��/����_.\`̘1l޼��ܩS�8u�_~�%`͚5xxx8 �ǽ���������@dd$F���a���sBI�֭���ۗ�b2��ҥ			����׿������ܹ�?��ϖ��{��Z#((WW�"�e�.h֬Y4j����2c�Ltt4�.�\)))l۶�~��P�fM��ʕ+ٵk]�t!==����S�Z5|}}K%.www�]�FXXG��W�^:��C�Z�y��a�n��ܚ5kf�GDDDDDDD��P��<�?5��s�Y��rrr���)�5ϟ?O�Νټy3�5b�ܹ���Odddp��-RRRx��w�Q�������U�1�]�^��H�xyy1l�0G�!"%4l�0:u���0DDJ�������|��`�o���wߵ������zHLLnnnS�re�8III8;;�l�cN�(��'O`U
Ŝ�q�����UNL&NM� IDAT���|����2u�T֯_o��������ڵ�;w�йsg*U�s=E����;nnn�ٳ�?��#Fb�4cf��Y�F
���m�]�SDDDDDDD��T9EĎ��$~���ի�g�}���b2��駟�>1(w��o��ѣ��ٓ����Z�jY�oѢӦMc��t�ޝ��X-Z�ĉ�H��֭ݺust""""%֠Aڶmˁ�|�2۷o�S�NԮ]���۳s�N222HNN�]�vԮ]�j|Q��&K_�v��9�U�F�>}�fȐ!,[��R��N�:<��3������D\\pwK�Ҋ�_�~����}�v���k����g�}��իy��y�g,�g:;�~��ܦ-6EDDDDDD��Q�q�'N0~�x���pss��ӓ��@����wrr*��dbذaԯ_WWW�7oΔ)S���+5jժUc�ȑV��v��	:t�@�j�8p`�c�������quu�v��4��{����?����
6̳JIVV
6��7+�s���c���ԯ_�
6�$�ܫM�6̙3�%K���޼y�?��=zP�n]*U�D�z�xꩧؾ}��1=���	�{���O��-�{#����뽕����/Կaz���
t�?)""��d2�x�b����&�����kU��&Zdgg�b�
�_�nI��֭7o��/��ڵk6[����'7n���JLL,�\իW --ͪ��g���Օu�ֱk�.����ڵk�����A@@˖-c�ʕ�=���4�ϟo�S�n]RSSm�3�����������T��"��O?m��s��Ά
���/0`@��Z����+x���s玥��ѣ�������G�jլ�ܹs�իW�o���s�Y>�6{�l\\\�a�ر�D�{�.N,�֭�h4���
�իW���"&&�;vбcG�q���гgObccٴi�
������ٳ'>>>@џ��^M�0�:u��y_�ƌC�֭���{�(כ��N�^�lW.]�Dtt4�7o&**���~��Z��Uq�,��$���KY���h"""����SD�,))	���b�^O<�s����/��$�t�ڕ���f�z��U�8��������ɓxyyлwo�/_�[o���ɓy�G�z�*�W�fժU-Z����ٜ:u�?���*f���4h�ׯ'''��m�Z%ߗ4�A�q��i�L�€x�G����\��e�-Zp��9N�8a��r��	K��D�)��/_f�С���3i�$����ӟ�ľ}�X�l!!!�F:d�$�/�<{�l�N�
�ҥK-�ǎ��_�Ν;L�0���4nܘ={�0v�X~��G��}fΜi5�7�|ùs�hժ��N�:�����?�̖-[��/�������"==�D����L�8��^{�F����Ș1c8r���׿����e�����Ʋl�2��)��Ǎ��ܹ���z*�8������&E��9s�w�^Z�n�_|���/����۷�I�&�{�n�{�<�S�=���Y��k�vr�[�$��tq��]Sy)i��aÆ9:)������!�����$�ԭ[�RQ�E�4h���M��?��S�NѲe�b��W�vm._�̐!C���d�ƍ�3��۷s������W�R�I�&ٝ���r�\�2���6��=������>%�k���̚5�9s�X*J����Z��ڵ+���$%%Y���Ϥ��DDDDDDDD�7��G�/��…L�:�������M�*U�gɒ%��ꫤ���駟�;Ϟ={�>}:o��&F��rnѢEܺu�#F��ӬY3*W�L���-��[�j�͜˗/�t����|>/ӦM�M�6xxxиq��w+�|���4mڔʕ+ӵkW�'���g��N�:l޼�s��Y��p��6m�v�ږ}֋�\̟�kժU��VQ�7,,��+WҵkW�V�����:ub�ʕ8p ϵ�=���Y��[I����^�ٮ��J�}-""""��;姟~�:έ_�~�m��9��[����4n�233��[񘓝===qqq��Ã^�z�|��BU�T���קO�>,Y��v����`�=J5�!C�0}�tZ�l����e+�1c���;�X����www���l⋋��z����۷����8��+E!RL���Z�A�>6�֭���={��
�̓��L�֭�رc�{����Ү];�?N���ٴi��v;:t`�޽����R1/W�\��ӓ��L�?n)�w�0��WWWΞ=K�ڵ�ƚ�����b����b�/99�&�###�jժ���BVV��q�{>i�$>��#�̙�?��K����������|��'@񞋋����ܹsg����z�r��*U�����e���k�{Vř�$Ϸ��]SQ�Nr�d/V{m%y_���0'�>��
�������V�;����e˖�hт~�����m3�ȑ#���p��aRRRزeK��d����d�{w������Dn߾��h�$�ۯ��_�b+my}�;7��T.�FDD{����ߟ�Ç;4���G��JD������$��>�����1i�$�6mjٲ�-ZIJe�ꫯ,I�O�f���⋖�R1��L��G"99��Ͽ��K��Ə�����f͚5V�)p���m۶-t\k֬�֭[����*1�ٳ'۷og�ڵ���Kv�hҤ�M[qb1k޼�M���;p7Y� /��}�!!!V�)����=�^�Jzz:5k�,0���z�=�O?�Dbb"			�۷�����gU�9K�|s+�{��k*�Ĉ�x_�c�������Z%2\�t���x����ߘ={�͸�K���ߖg�6�M��޽{-�/^,�5��/���?�p�B֭[GNN#F�������EDD-##�7n�d����fy=z4�6m",,�ɓ'w<==m����"���V�~K�.%""�5j��_�T1�v�p��ra�?m�m۶|+M,_�<��s"EIc1suu-�{=��t�ڕ��x����޽;&����$���x���-}��\���1�L���ЩS�B���ʢR%����z׭[�ԩS9z�h�Ɓ�gU�9K�|s+�{#�k*%�]'666�s�5"!!���l��H���$$$��Cq�����n2�y���?��:���Ō3�4{��<Ur��_uG'�ܸq���~��C�Zֆ´iӈ���jժ�ODD$�{+ ���0p�@FU�Veƌ��꫖D���(>���T����DDDDDDDD���{p���y�W�������^��C��ꫯ�����իy��G�]Ü8P���d����B�MLL�СC��[�XJ�/�@HH`�j
﹘��/�v?��3u��-�O����3r�H�=J˖-y��Y�l_�5?��s��Y�Ϸ$�
G�ȱ�OC��o)������q��A�����^褴�b���`0���\�>)���\�p��#GZ�F�Ņ,�
��4h�777�v��G}dS��:t�@pp0s��e�ܹ������::,�bQr�8���7�v�*Ҹ�7o2r�H222x�wȳ�y{����Bͽb�
�n���nN�0�/���RچN�Z��ꫯ�y�&T�^�Q�FY�+�s1�����?'==�������IKK˷2Ma���{���:�̙3;v,VUL����t��|��}o�*r��ŋ�>}:}��s��c7�%##�@�Ν8p �}�����>���7�9�$>>ު������ƙ��μy�xꩧ��駟f���v��.]��̙3y�'�ҥӦM###æ_��cǎ�c{�q��y�����?�F�Itt������0a�z���=w�\K<y�/{k���9r���`�u��O<��ٳ�q��[{��`0����|@�=�ӧ�- 55��S�ҭ[7z���?��O�_�n5ga���׽v�Z:v�H�
,�
6�`0�v��B��BDD�<EGG��l��/G3�̛7�y����7��D�)�O>�$p7����{EDD���Ā���x�
8`� ?�{�`ٲe6璒�prr�Y�f���{������E�&0�_1�)��Ը��B�<olJM�u{($�nk�̘O(b�鄅����)y���D�1R@p����Y����������s�7�\����;wظq#����}�
		`Æ
e�Q�XGGG����v�K�,��ի6�b��\�g�}�~������СCK��lt���.]���-ӧO��JMMJ^~ٲe��幹[�1+r}��9�g*��Q<α?.nܸ��q㈋�#;;�[�nq��YfϞmѷ���I�&�n�:.^�ȭ[��t����L�2��I[�<����IG���Ʀ����\Ǝ��͛�|�2�o�&33�M�61n�8�׉��ƌ�Ν;�~�:|��焆����.++���`>��3�]���۷IMMe޼y�ڵ���>��7�$99���\S�111����k����'����͛7�~�:۶m3{ݩK�,!66���<����裏صk��_�����͛�����g��t�R�~�}��/�������b~___��򈏏�����M�)b!!!ԭ[���D^|�E�͸}��1q�DF�I�53�s�N��}ڷo���Xy�뿨Y�&QQQ̞=�˗/����޽{M�>F�
@||</^��ǧ�*Fݺu�S�N\�x�={���x�ˣ2a��ލI�\�*v]"""hذ!�w�]�v�������q��m���III�����W�^eΜ9t��ᡏ������t��e�ܹ�w�}ǨQ��n����/�t̊\_cb��۹}����@E�Au�8������…���ɑ#G���(�۽7n���Ӵk׎M�6q��1bcc�ر#III�ܹ���d�>���f�\\\x��9w���ի|��������~��s�_����4<<<Lq�Y�wwwRSSY�v���
��ȠI�&�[��tL����ǃb7Z�nW�^�M�6l߾���?���rg�7o`֬Y$&&r��a>��C<X�9�s��6m���ILLd̘1�۷��<RRRؼy3�fҤI���cggǶm�HLL4����������Ӻuk���m�+񈈈���������o��S�*<<<شi���|��Wt��GGG���CDD,_���;��Y�p!'O��N�:��ؔ�cԲeKV�Z���
�/�q��Ԯ]�?��|��wt�֍Y�f�nN�<�L����ts�$��Qi߾=�>�,7n����i���*r]�5kƾ}�hٲ%?��#���*-Z����'''��?0s�L�r$,��c�9s&p��A�ƍ�Q��ڵcÆ
̝;��-[��_?�1+r};w�������f͚@ůAu�8�nM��VJ[��h�1Q!44����coo���w�����saaaxyyaggG��͙?>@�Kڔ�K�.���>|����_GJ��C��
/{��5�ݿ?�gϦm۶�c��_�Z��СC̘1OOO���

%99�O>����|��״iӆݻw��w�y����<�h�̙xzzR�fM������.��ǬY�hٲ%����ٳgӴiSj֬i�u��u�~�}:w�p/٦8c)cy2(9E�����8q�1c�ФI���[�.���#>>�����2��?�{�1cƐ������'�ի���O?�4�-b߾}ԪU�k׮�s�N4h`�r� ��z���駟r�ڵJ��Q3~���)F�.F�ڵ�ԩSDDD��/��憽�=�j���ˋ�'r���JKL?~<�֭�cǎԬY����?��.\�ܹsX�z�#���7**�_|�ڵkS�F
~��ߙ�U�T�s쏃���ЩS'�vooo���������%�4��Vea�(U49�h{q��q_�x��v���^]I}+�q�V�Zݷ�իW5j�F�⭷�b˖-���PXXX�9�s�Z�haz���X.�����''��vtt�د<�OYYY8;;[�cl3��	

*5�_?��O�lڴ���"""""""VW��ȓ��ˋ5k֔�ﯿ�Z�9z��IϞ=K�^�^=����5����E<e�q��X�3^i���رc;v��.�u)�f͚�?���Ǘ{ߊ��FrIF�i�P��*2&��6k֌ݻw����נ�篢c�o����<��/c��R�r1`y�ml,�9{�5/O%�:P�fM�=ʭ[�8v옩�Iy��ha��x�5jT�?QJ:?%Y�d	gΜ�I�&<��s�hт�m�2dȐJ��~�&�����e����U������ry~����4���Q����Mll��Cy���yR)9EDD�1ѤI~�����[��%�~��E_777Ο?Ϯ]�pss{�y��ȑ#l߾���:w�\j�'www~��'N�8a��ω'L�=���4���|}}M�)))sQO=�?��3����iӦ�~G� 22WWWS��۷o�9i�<��qP�ߧ
������iР��6�RA��EDDDDDDDDDD�M�)"""��~����?�x�b-Z��O?͙3gX�x�E����k��̙3iٲ%׮]c�ƍlذ��T666���^�7:�}�Y�9BTT�Y�Eq�{�f�ڵ����h�"ڴi��ӧMq�0��/�j�*���X�p!�۷�ܹs����>O�u�ޝ���.]JXX���c������ҤI>����G��o߾����p�BS{vv6���/�*�9x��U�Vdffr��y�$��TZbIDD�ʬ
&"ec0����v"""""""V����DPP��9?���G��o�ѣG��~N�<Ɉ#̶ժU��S���������E@@nnn�ڵ�b<c2�իW͞�$88��{����Θ1c̶yzz���1�����s��1a�S�/�`JdxX���
{����ɓ���Kfۊ.Cֻwo���7o��ͳ��ٳ�����|��<��Խ{wHII�X��X�qK��-����`0X;�'BPP��C�:[k """����Lrrr�������ߟz��Q�F
���L�=L}�ԩCdd$�777���pqq1U�(Z�b���xxx`ggGAAA�s�lْ������L�֭K=ggg���2d�5��ΎF�1|�p֮]����������ꊃ����#44��'�4h@TT~~~8;;cooO�֭y�w�߿��ߌ3������ڶm��ŋMI3[�l�v��s�}z�prr���<x�:u�Я_��_DDDDDDDDDDD�̦�����A�oǦM�

�kU���HI��$4��.��qT����.]b������s��J_��V�^͚5kرcddd0h� &N�ȸq�a�_�D����ƬRJ��"�h��"""""""$�r����c�W�^����������ݻw���Y�`�:u�r�"�Ӹqc�.��Ѹ��Y,$""�8:w�\��;66�iӦ1m�4bcc�0*���a�DDD�l�����Lxx8���f�\]]M�ψX���#�����_g�ȑ�ܹ��˗S�V-+G'""�p�x�
J]��Zs?~��+W�e�
:t(^^^t�ر��)N�)"""���3g�����ݻ���)((੧��[�n�7�F�Y;D�Ν;�ҥK�<y2���V�JDD��%$$T�����;w.��������9sغu+���U���������%�H�غu��C�jl�֭<��aT{�����C)����<�|||�R!D�'**�+W�0l�0S����ټy3QQQ���X1:%�H2d��C���˗Y�j������ҬY3F�E��������޽{��_hذ!}��a„	ԩS��Ϙdòe�8y�$5k֤o߾L�2�TU��ݻDDDϥK�����E�8�A���U�qrr��qDDӧO��ˋիW���SR������srr����g�1��׸qc|||���a�ȑ8;;��B��������T"%��#�oL������HYeee�իW�|"5 IDATMm���̛7�;w�0`�rss;v,iii�~���lڴ���$"##qrr2{�ĉ\�~��7o�m�6�޽Khh(+W�d������n��ԩS�:u�7n�-[FNNN��[,�q��/� //___�m���$%%��/�\��DDDDDDDD*��S�:t�˗/�v"��ѣ������+Z�nW�^�M�6���[4lؐw�}�O>����HS����IKK��ÃE�ѺukN�>�ܹsIMMe�ڵK�4mڔ�����SO�f�"##ٷo�)9e����X�nݺE\\���lٲ��� �*)%-wԼys"##qpp���.m���DZ�nm1��-11Q�)"""""""bUJN�G*==��[�2x�`k�""��֭[����vUb�֭�AD��]#"�eE���_{II��СC̘1OOOBCCM	$F���3mk߾=:t`��ټ���ݻ�"9e�̙�1������$;;۴��ɉ��\���IKK�w��X�G�Q��(�q��ܹs����5kf�GDDDDDDD�Z��"U"66��!�H5V��C��v""""��ŋhժ�}�edd�R��ԩ��8E�h��������w�ڦL�‚8z�(G��>`̘1jժU���� �U��.IVV���یm�>""""""""֢��*`00�CDDD�T�+��o��G����/�lR\�J}%����G׮]ٿ?�~�)�~�-�V�b�ƍL�<�L��V5����4gAA���9n㾶��یm{^EDDDDDDD��SDDD���C�X�|����JУG^{�5k�!"���SO���?���J�6mJ�����O?�ĉ'�ҥ���ĉ���Uh~��������|��W�[��e˖�)9�8
�q�u�� 55բ_Y��$
4 33��ׯӠA�mׯ_7��&˯ՈT�+W����C߾}�p�>>>��������c�^�î�m��OϞ=;v,���U�&xll,ӦMcڴiZ�I�HOOg�֭�CD�֭[9v옵����޽;K�.%33��7o�d�|||��l�׻wo���8y�$�o���ɓ,^���={�{������L^^-[����(��Jzz��tuu`ǎ��瓖�Fxxx������K�?�b\c[E��L��"V���@۶m͞�k׮J��7HHH��2���|��L�2��+W���V��Js��qV�\ɖ-[(,,d�Сxyyѱc�*�_�I��/��[PP��C�M{�Wسg'O�䥗^2�6~�x����`���Kzz:cƌ1����i�V������n�@���mz���JVV����k׮R��ݻ7۷o�������ע_Y�����w�NBB)))fq¿�cW$YGDDDDDDD�2�r�XUi�)��-99�,�#!!����믉����ߟ�w����cUf\����ܹs	���
www�3g���U������T/��?U�
���������Ӻuk�y��
����DEE1d�5j����5b���]��r���y�x��qpp����-Z0z�h,X`�7}�t<<<�������cN�:���@�֭������̝;���]��/��NNN<x�b܃R�N���W��!"""""""R�T9E�\�eu"""���0=_�b+V���B+���
�����^c�Ν|��w�龢���r�
Æ
3�
>�͛7EHH���'���;aaa�W�n]fΜ�̙3�ۯ���%������������+����̚5�Y�f=�Y����k׮��``͚5ddd���@FF'N�`�ĉ899�w\�GM�S�Z���a���fmIII����g��v|||������������äI�L��c�&�m���cŊ���ӭ[7��U�����lm�yթS����{�9
�ݻw�������cZ�a�{�.�W�&  �nݺѫW/^y�v��a�/''����y�5jdjoܸ1>>>��Đ��S�c��׹s�,ڌ�AE�}�Y���nj3HMM�����ޕEll,ӦMcڴiZ.IDDD�h���4nܘ��hS[tt4nnn�1Š���������ܣ�)R����?���`�iӦl۶���F�����6m�ҥK0�3gΐ��g��W||<_~���4qVV/^���=z��Z�l999f�RPP��I�8}����ҥKDFF����ʕ+M�'����_Y�|9:t(���|��f�v;p��z�b����ʕ+Y�~��߭[�8u��N��ƍ��_���W�羾�$%%��/�|�����o�ABBB��Uݽ{�_��}�����Ć
���|d����\��-[�PXX�СC���cǎSDDDʦ�	�e�8Vά.�?>���:#G�`�Ν,_��Z�jY9:UN+JII�]�v%>wss��w���ĉܾ}��{�bkkKbb"7o�4��g�5+WܼysY�p��E?�,���ƍ9}�4�ڵcӦM;v���X:v�HRR;w�,�x�V�ׯ�v���ߟ	&������ڵk�5&���ٳR�ھ};poy�#G�p�S�-[���%&&кuk��1����oWBB�}�_����IJJ��O?�S�Nܸq��>����{���|�ΝK`` nnn�����9s�����EDDDW�;w&$$��K��t�R&O�������T9E�ȘPҶm����׏S�N������/ǎ#;;�?���|��':t��}���}�����1b�˸\PXX���$����3h� ���4hP��:{�,���3UI�[�.����_��Ç���KNN�~�-�k׾�����ɉ��\���IKK�w��h6�qY��M�Z�׬Y3�>"R5��D��������Ã7�|�aÆq�ر*�!**�+W�0l�0S����ټy3QQQ���TyL"""O�������`�v""""""""��"U�x	�%K��d���E��h�"���x��wM~���S�fMBBB��?���_~iJN����W�^fc,�#==�������^��7np��1����ٳg���mJ1b[�l!**
___>̝;w�֭5j��'Y���L�‚8z�(G��>`̘1���YYY��%��3���H�p��U�/_ΡC���ϧE��5�ٳg�Eyyy�Y��={�����
�?��q�ƙ���&�'1Ƙ�v��u�������[�r��Yn޼IÆ
�ݻ7!!!899=p���<���ٿ?�j���_d���ԬY���bbbx�g̖lkܸ1>>>���0r��_�DDDDDDDDDDDD�:���Tk�5�C��={���,���O�.]puu�S�N:t���<N�>Mǎquu5ۿ�US
�=77��cԮ]�>}���f�Ӷ������/s��qRRR8x� poI�ʊ��Ϗݻw3o�<:t�͛7Y�j���g۶m�~666��J�ی}D�nܸ��q㈋�#;;�[�nq��YSbJQL�4�u��q��EnݺťK����dʔ)ܽ{��b�駟hР���>��7�$99���\n߾Mff&111����i�Y�fG^^YYYlڴ����o��_|�yyy���Z����K^^���ul""""""""""""R���"U.99���ڵkGrr2+V���ۛ��d��K��{�.�֭�ƍ����=zp��M>��Crss-��(777v��e��'))��cթS���l���#G���-[8|�0���t�޽R�rqq��ߟ5kְ~�z������fٲe�>ƛ��+m+z�YD�+::�.���Ndd$G�!""¬���ƍ9}�4�ڵcӦM;v���X:v�HRR;w�̫�}�-��۷9s挩�U�n�L�6o��K0ILL����|���D��믿��M��۷ϴ=11�֭[[�fl3���A��U�����SJz^���G�.]j��aLN�޽;˖-3��ݻw�㰱�������t<==x���Y�v-���̜9��-[r��56n�Ȇ
���a�����ݻ\�p�w�}��mۚm������Laa!:t�^�z������`֬Y��ߟ�-[���?`ooo��U�Vdffr��y�$���ϛ��ȣS|���ړ��MI����o����7g�^{�5��{�� ,,www�7o���4hqqq4�btqqa�ر������3gΰ{�n���{���k�lU���׿ҼysƏOLL���i��s�/+T�q)7c)]PP;v�v"O��[�b0���������U)9E��<�)
40UTiժ��B@ӦM���~Džx��M�E���Օ��,pssc׮]�=����s��IF�aֿV�ZL�:�ıJ�ykooOHH�E��Q�غu+`�����LXX���Kix{{�w�ޝ��RRR������A�
�H�1&�u��ɬ���/@zz:���%����Z����_�>�;wf���f��W�^e�ԩ�9s�b�-Mf����nݺfKeee���l�����GDDDJ6x�`k� �D<x0]�t�v"""""""V������(�}������HNN�H��ѣ111^�g�����dffRPP�[�'22��>��}��q��j׮���7�&M2�qZ�5j������F�U�qծ]��W�^�W@@5j� 66���4�4iBϞ=	6�{�x�8x� �F�2���ԩS�~��=�xE��/kcLt���:�=lllا��V2yP,E-Y��3g�ФI�{�9Z�hA۶m2dH��rpp��v���Z�Lhl+�|���ȿ���Z;y�(9E�"..��_~y�X�O�>��ӧ[��v#�x���~~~�\\\�6mӦM�o\���A���[�^�������j׮��``͚5ddd���@FF'N�`�ĉ899���D�kҤ	?���~�-�>����zR����ϟg׮]�,UG� 22WWWS���۷�Q���ѠA233�~���rdׯ_7���)�S���������������(9E����呟����wF�i�x�����ψ��f�̙DGG���f�|��XW�~���X�x1�-�駟�̙3,^�آ���?�ڵk	

e�̙�lْk׮�q�F6l؀���W��ݠ*,,$==OOχ��ȑ#��ۗ��4.\hj��Φ~��5_�V������I(�e�Z�j��� ""�[7h� ���y"Y;�Sr�H+������b4������y���M�2;w�d���ԪU˪������ >��s~��'F�}߾�G�f����<y�"ѬV�ZL�:����Օ��,pssc׮]��w�����1o�<�͛g���ٳ���>�|ݻw'!!������Ͷ��+�����X<x0��v"O�;vX;���v"O�F�Q�fM�w��{g����C�s�΄���t�R�.]��ɓ-n��H�HNN.u�0GGG"""�^�zԨQ///SuS�:u���`���
;;;\\\�ݻ7k׮5�.2}�t<<<�������±Ϙ1???qpp�m۶,^��	&�e˖���^��ɉ�Zl;x� u�ԡ_�~>�|��"R����B���z�<�ׯoQ��ҥK4l�Ь��ŅiӦ1mڴ����營��E{iI2�qvv&,,��m����+m���k��`0�f�222��� ##�'N0q�D��������<|||����Ν;g�e�7wll,G��k׮2�*Cy(��"""��ի>>>|���dggs��]~��G,X@�N��a��q��DGG�ڢ��qss�X�HDDD�<�x�
������Ǐg�ʕ̘1��ӧ�b�
N�8Q���������T��SDDD��� <<�>}����2x�`���quu5�N�[������ٹs'�.]�ҥK�ܹ����S�V-k�'"""�����j7w~~>s��%00777���	`Μ9���Wq�""""""""�����̙3�6m�[��V�Z������F@@��Ѧ%n��;w&$$��K��t�R&O��������M���1-�#�ŕ+W6l��m���\�r���(+F&"""""""Rv5��<lll���Ts���!T{�������΅���o�/����OBB�����Ӈٳg��7//�5kְg����ѰaC��?1n�8L��޽KDD���\�t	{{{Z�h���4h�Y"��qrr��qDDӧO��ˋիW��)���˗/�j�*��ͥY�f�5�T���srr����g��Q�F�>�7��LJ��F����syN��������H�Sr�<R=z� 66��a��c�����!���������0f�222Lm��97nܰ�[PP��I�8}����ҥKDFF����ʕ+���W0v�ʕ�_����֭[�:u�S�Nq��
���۲e����1K)���,����z���-55�y��q��P�_|�yyy���Zl�%))���x^~��r�$"""""""RՔ�""""""""�†
��ȠI�&���[xyyq��)�͛g�w�ƍ�>}�v��1{�lZ�h����	#))��;w���l߾�+V���í[����#<<�-[�dV%�x5��͛iV��,֭[�իWiӦ
o��
6��w��O>!22��:wbb"�[���ؖ�����v���9v옵�yh���t����a�����&(9E�C���h""����hk�!"""��*����KJܨ,���`��ٴm�ooo��׿�믛�ݳgaaa����H�ϟϠA����3%�899���Ktt4iii��ݛ��@�ۈ#ʝ���̘1�T-044�����{��9�6mj��Y�ff}D�}$"���JDDD��(9E�Daa��C�j�I�������!��C2�AD�7�…�o�ެ�S�N}����/q���T��)S��`��=�ѣG��3f��Z�j�)6c2Hy]�x�V�Z�{߬�,���-�ی}D�#}$"��'��*�����*УGbcc���T��ED~k�WD��7���Fv��5jX~|�޹����~~~t�ڕ����駟��߲j�*6n���ɓ˴,NiUS
M	��&9ٸ�����6c���EDDDDDD�q����4iBZZ�|�
���������nnn�?�]�v����]\\���ߟӧO��W_�n�:�-[V���lll(,,�ƍԩS0��b��SO���?���J�6m�5G�
�����4h�l���M}D����t�;f�0DD��ӓ.]�X;��$%��Ts�Ν�P��G=wll,G��k׮2�*Cy�h�u���9."��⋬Z����0.\H���9w�o���E����k��̙3iٲ%׮]c�ƍlذV�^
������`֬Y��ߟ�-[���?`oooӘp�����JY���dee�c�^~�e.]�Dxx�E��ݻ�ҥK	�^�z,_����X�4i�'�|R�ܭZ�"33����[$��?��G���!y\����ȣ���j�7� !!�J�h�e��Ǐ�r�J�l�Baa!C���ˋ�;Vy�"���.�x�M�GkĈ|��W�;w�	&��_x�S2���ѣٿ?'O�dĈf�jժ�ԩSMσ��	#<<�"������ؘp����v�*5�޽{�}�v�{�=�{�=�j/F���
{����ɓ���Kf�Ə߹�w�NBB)))fq¿����ٳ�E����L�DDDD-�E�E��HHH�vs���3w�\qss��ݝ���̙C~~~G)"""""�Jrrr�'�;88A`` ���888Я_?BCC-�֩S���Hnnn������B�޽Y�v�YE����͛��O?����hтѣG�`�S��ӧ��ၝ���u�ԩR�n]�e�ܹ�4h@TT~~~8;;cooO�֭y�w�߿�}�~�prr���<x�:u�Я_��Xie- IDAT+S��|||�R!D�'**�+W�0l�0S����ټy3QQQ���X1:y�ծ]�Y�f1k�,����/���0m�4�M���q����o???���8/���c��tww',,��s׮]����5k��������N�8�ĉqrr��""""""""Ձ�S�v��eV�ZEbb"���4k֌Q�F�}{
 ''�������/��BÆ
�ӧ&L�N�:�~�$����-[�ɓ'�Y�&}��eʔ)8::p��]"""����ҥK���ӢEȠA���*�899��8""��ӧ�����իKM�)��A�]��999�����3�ШQ#S�ƍ���CLL#G���ٹ|BD��ܹsf�.��#[[[�֭Kǎ�8q"����*�2y�Ɏ�5�266��G�еkW�b�DDD����g��̙3�������b9#��J�)�����"88��W���RSS�7ow��a�����2v�X���L�233ٴiIIIDFFZ|Sm�ĉ\�~��7o�m�6�޽k*E�r�J֯_o���-N�:ũS��q�F��7]�l999fI"�y�%��/���+qu___��������_.WL"b]o��			eJ��{�.���+���#))�
6���YQJi�?�ʕ+ٲe���:///:v�h��DD�7����Pݒ?�GGG�ϟ�믿�ȑ#عs'˗/�V�ZV�N�ɐ�����888p��%�ׯ_e����PXXX%�=k���v,��*�IcV�9+�X�ZU��DDDD��l�����[���W�ҦM�o�΁��@dd�����IKK��Ã��H�9š5kpww'55��k�Z�ݴiS�o�Nbb"cƌ`߾}��۷o`Ŋ9r��JAoٲ0�`���ޛ7oNbb".���.m���DZ�nm1����GD			��n|HNN&))�O?��N�:q��
>��*��lJz�|��/���|�ΝK`` nnn�����9s��Ϸvx"""RI:w�LHHK�.e�ҥL�<oook�%��شi�y�f+G$"""""�Q���ҾiW��Q�<t�3f�0}�?44�T��ȘTJ����С�g���W_e�޽�����3s�LӘAAADFF���m����Dnn.��Ѥ��ѻwo	,s�#F������G]��.ɹs�{�7�5k�̬��TLu]6�����|�M�
ƱcǬ�-**�+W�0l�0S����ټy3QQQ����)�u���`�0D�H�/&�5���׳v�Z&O�lݠ�@'���_]y��r�<�.^�@�V���/##���RT�N���)�E���...���0��L�B͚59z�(�.C�%22��7o�9~c2Hy���K��������6c����<W�^e޼y��Ӈnݺ1b�������H����cŊ���ӭ[7��U�L���(�1I͸�Yy�,:�7�|C�>}�4i�Y��۷Y�d	�z��O�>�^��4��ٳ�ѣ�?�<���͍7J=��w�z�j�֭�z��W^aǎf�_I�(''������?��?�ڵ+/��˖-#77��}SSS			�G���d���fUN�KNN111<��3fK�5n�bbb���)~�DDDDD�RRR���ѰaCV�ZE���INN�ᄈvh""""""�%��U]"��%d�bل�[\�d������;����w�f޼yt�Ё�7o�j�*���϶m��4iUS�~������)+㾶��/ƶ�=�"R�7n0n�8�������֭[�={�ٳg[�-((`ҤI�[���/r��-.]�Ddd$S�L��kXY���O4h���\�l999f�K�,!66���<����裏صk��_�����͛�����g��t��R�\�r%}����ܺu���<N�:�[o�Ettt������رcټy3�/_���dff�i�&ƍG^^��>'N$))��7or��u�m�Ʋe���_|A^^���s������G|||�������T'�ϟg„	xzzR�fM���

����%����y�Oq���<���������-Z0k�,���֭[ܫPX�vmS�Bc��b;�<�;w�v��0�cسg]�v��WWW�7�|s�8���bccC�ƍ�}�v�}o߾M�ƍM���{]*��ٳ��၃��=����}�so޼ɻ�K�^�hР5jԠaÆ���'����c���~7KSU�a��={�,�F����
{{{Z�l����J��,�""""��)9E�XO=�����������'�ڍ����*4�������Y�����Lvv��
��0��-ZA��c+�q��x�x���mEoT�H劎��…���ɑ#G����H�ظq#�O��]�vlڴ�cǎKǎIJJb�Ν%&���۷9s��-�[�n垳��͛����…��SRRؼy3�6UU	��Ύm۶���Ȅ	8p�@��n߾�+Vp��8��Y�زeK���~�z������0]�5k����Njj���wQM�6e���$&&2f���Kȕ'���DZ�nm1����GDDDD�:;x� �۷���;?��3���Ν;W�1͞�[���]����s��UnݺEZZ���z�2�<��Ν;lܸ���O�nܸ�;w��7�1c���7ߐ��G�ڵ*��~��_�رcܺu�k׮�s�N�w���_]j^^^<��s\�|��>���>qqq\�|��{///��\��|��gx{{�~�z�.^�Ⱥu��ԩ_~���>�9�999t�ޝiӦq��A����s����qqq��Ӈ���r,������[�����76l 33�۷o���ʔ)S����*�oRDDDD�F
k b-ݻw'&&��K�F�z�X�|9���4i҄O>��޽{�v�Z���X�hmڴ����,^���={�{������Y��߿?-[���,���������}�tuu%++�;v���/s�ҥ�ȕ��K��U�Vdffr��y�$���ϛ��Hٕ��N���dSChh(�۷��ۛ9s���k���߳gaaa�$��͛3�|
D\\�
z�]\\;v�C�9bĈ+A͚5��-[`0X�z5������ٳMK
�9����挜�����%::���4z��M`` ����W\IפC�̞=�W_}��{�b��̙3M��AAADFF���]�XΝ;�{����K������u�V��"��lݺ���[;�j+++���@rrr�:u*!!!��w��ĉ�Y����HgΜ1��P�ʱF�/6U��裏L�?��#'N�Ν;L�4�7�|�=ʘ1c8~�8��E��Nff&�[�6�/�ҥ^^^���/�������ϩS����4-�Y�XƏϫ��ʴi�pww'))�ѣG����[o�ŧ�~Zj,&L !!�5k�0p�@��QQQ�7��u)���L�
F~~>��ߦe˖|�������駟2d�N�>M�ƍ+t����oh۶-~�!������r��	�N�ʑ#Gx��y饗*|����e�[�����@~~>C�e������8}�43g����~$祤�I�:JN�'�+��ž={8y�ś���Ǜ�w�^���M�p7���h+���`����H �6=6&����Ʈ]�J�w��l߾���{���{�ĥ�z�%�ݽ{wHII1��U9��%�H���:u�d�^�� ==�ǪH�$;;;�ׯO�Ν?~�ه=�ӘDQ\�D7'''��-Z��&dI�L�‚8z�(G��>`̘1jժU�~�edd�R�2^��/Z�S�\\\���KVV���sی}DDD�۱c;v�v""|��\�r���P�z�-S{׮]�ڵ+��μ����fۋ;z�(���`ƌ�6c��СC��L�={�d���<��3lذ�"!�X	q�ȑf�#G�d�ܹ�]����)s�̡]�v����_�XF�m��I���Y�z5}���رc�����/��ݻw���iJ��r�
�}�������ʺ.�b�
rssy���پ}�i��m۲}�v���˾}�X�r�i��C���ׯ7{�ܥK֯_O˖-9y�d�c/��<%%Q��Þ��.�]�y+r~?��C�_�N������1�w�ؑ��8z��ő#G*����7)""""UG�H�P��$*[�
������ggg���iݺ5������DEE1d�5j����5b���]��Bod�7oO?�4�uqG�͂L��O����vvv�w̩S�Hݺuqpp��ח�s�V��K���^��ɉ�Z�{��A�ԩC�~��}>D�d�׿⯃����[%}�����yi1;v�ݻw��[oYT�Ȝ%UM�Y�f���*���Ϗݻ�?��?.�:��KTE��mޢG���Mq,n�&����š�½3�XW�CZȺ��U4oN��(B�-�ܔM$cS�?�P���ޢdj)D����2̀�������<b���~?�u
��|���,_��g�}�;w�i�&&L���ݻkܯ��'�TT�BVmc����X�j�����<��f�z��˗�bϲ�̯~�+��-�<���_�7o�dڴi���2n�8k�[˲0��J�f������6�?��{��Y�fL�>�f[`` ͚5#%%�~��Ҹ^x�����b��oصY�Z�v�Z�q����f̘Aii)}�Ͷ�۷s��]�	�uq]��R�344��o~��_��?���^�sx��y�f��;��	����:���P�.���̳h�"�}Z�ha��u_y�~'EDDD��r�4i���DFF>��c�=Fhh(���U��,��Q���_��,|}}��nnn,Y��%K�<�u����m۶�d2K^^ݺu�W8~�8s�ε�p "u�{��|��8q��{��~��	����.�gϞ:-�[g�Y����\���>��#֮]˫��Z�~�yzzr��y�?���?om?~�8@��Cub�ԩ���ܼy�n�5�RG�EDD�L���D��#F�-�)���������U�mΜ9�?�'�x��;wҼys��*�+Ve�Ν���7�G��[j�G����<x���D�I#p�o��j�E�*���a�ݻ���gϞͺu눋�����>P7ץ:,����<K{�J�sϝ;�7�|Cff&G����f6׼�Im����=�Չ���;ou��S�4h��q��a�s�;)""""
G�SD�F����ڵ��]_			��ȣ�R�hժU���PZZ�ɓ'��
=z4aaa�>}�{��q��u��?`4�7o����)˲<�U�9��/���h��?����>}����
�V0�n��F�@dd$��ٔ�����m�&�Yꬺ�X�>�,�T�����H"""���$'';;�&#99��K�4e�n�z�~~�!III�k׎?��Ot���������{��,铖�F�f����爣xj�Ee�'��駟f����o�V����"''��{����[�>�u�����a�X�,-,,�����ڵ�޽{ӻwo���x�HMM�￯m���]�[��k����o�x���DDDD�K�S�Q3��2nC/!�(qss#""�X�\NIIa����ү"R?�O������	��opp0$;;�.q�u��,\���C�ܸq{��U|5���ITTQQQ6�ʗ�n?G�8p��/2s�L�m^^^vmu����IOO'''�.Ɯ��v�1""�4$$$`2���H�PqI�նm[nݺŏ?�Xi�BeN�:łh֬۷o�駟�t���n߾]�9rss����jŐ��ɩS��۷o���4��6{�l222���c�ȑ��X��u��v����?r��M:v�h�����S>����;vX�z�)&O�LϞ=�ܹ3}����И4���yks~۵k�͛7+��哑6>i<T9EDjlРA����f�֬Y����VD�/++���bbb���}���h�oooV�X��E���N\\&�	��@������`ԨQlٲŦ���ŋ�֭͛7����ֱ�dΆ�������yꩧpuu��Օ޽{̻�[�~�k׎��x�L�B�.]h޼9]�taڴilٲ�z�yܸq�i��z�cy�����ZmGDDDD��z�'��_�Z���ܹ�ԩS)**��w߭r�d�r8�$��裏�l6W��$�[�WGMc�kS�L�}��|��ܹs���$��ݙ6m�M��^�������L��-U��/iT�s�����y�fN�:Ŋ+�9s&~~~6�W���j~����]�[��kI$;|���1�=Zg񉈈�H#b�C			��/���ED1�Lf��T�󟢆|?�|��yРA�^z�^Ɨ��>0�F�K��m�.]2�F��;1�Gף�~%"�>����P�s�_M��5�{h�ҥf�<|�p�ݻw��ڵ��Ǐo�>�|3`���7���U�…̀�����ݶ�'O�s�=�f��\ZZj���4�#G�T9�_��W3`���4���ZہJ��&�Tg���W�n9w��0Ϛ5ˮOm�˃b�l�ѣG��ݻg��޽{�Q�F���ŋ��5=����f�\XXh����֘o߾]�c��1>h_Gm
q��j�ڜߨ�(3`9r���ń	�r^�����H�OUN�����~��h��?�֭[�����ZMc�N�PZPP]�v%!!�ږ����`�[ZIDD��;s�L�ے��X�h�-"))�����{�1222��/~Aff&w��!--��s�H�-������ƍ�߿?[�n�Y�fU���oЪU+���Y�t)�}�EEE8p��S�X�Nݿ?�/_�h4��s�U9�СC8p �/_&55�Z�[�X�˜9sX�z5`������o�A�v�HKK��ߟ��\JJJ�����ߟ�ҦM~��_��S�s���ܯ��w�q��=���f̘��5k���_��P�R���ż�9�o����C����Ϝ8q���N�>͔)S*����"""""u���1�hQ���G�Δ�x?\�j�yРA/���M�i:����Ç7_�|�|��e��������_g���z߯D�ч*��-Zd4h��mG�5�9�|��es^^�yĈ�cǎ5p��(k��~���C�}������Zݠ�cӦM6�
Ti���bcc�͚5s�o�С���b��l6O�2�����u����n̯�����������U�����{�93`�_��U:nM�K�9krmRRR̭Z�rدU�V�?��v������TDze��}��1�?�����8ڷ����6���[���_�۷o�p��[�:�4�k���)"""?���,Z���}�Һuk\\\0������@�nݜ�8��A�		a͚5�Y����������DDD���t�����,[��I�&a0�����ߟ��p���8J��k„	?~��3gҽ{wZ�l�c�=�رcٿ?o��M�o����s̜9���tƏO���quu婧�b�ʕ���Ѻuk~��GRRR�ԩ��ǃ�L&ڷoϟ��'~���:���Y��8��bQ��R[/��G�%  ��@�-0̘1�cǎ1q�D�}jrgϞ�G}Āhժ�����+V�`ٲel޼�N���4��yk{~�‰'�={�����ۗ;vXg񉈈�H����H�0e�g� "�Xrr2&���a4z...�L&�+��ׅ�����@VV��#�?���\�z��K�iӦ�s�N���			qbt"M���7������?�j��#G2r��J��o߾Ɖimڴ���l6?t,5���U����?p�\��Y���~�m۶�h����3f0c���&C��>��}��>�]�[����������暉���H�Q��W^^^L�<��a�H#7y�d��yg�!""""���k�X�|9cƌa�С��~�F�5aƢ���
6����СCy饗شi%%%�>�)?FAA���<�.]�X�t����Hbb"�|�""""""""M�*�H�1b#F�pv""""""�PXXȬY��t钵����,]�ԮoII�i� IDAT	���#77��v��������!::����ٷoEEE6�n۰a����d������yT""""""""��)R�v��A�f���C=��>}��߲DDDD���t���������_cS��b������ү_?v���#GHJJb��dff����.K���e}���@߾}�ƶ�Y�����������Q�iIII�AD����2e�g� "!99����0DD�E�%s*k/��Q����������Λo�i�755���H<==�իL�8��{�2q��J�:s�=z��ֳgO�>""""""""�p��"
b����AD�O?���!�;///��<&O����?��0DDY.\`�6�>>>v}/^�����ñΞ=[�\7n��]�vv�,m�>""""""""�p��"""�F���#�����H�*VD�TL��J)�1��6ϛ5k��>ݾ}���1]\�W<��9�WDDDDDDDDjN�)"4ԇ�gΜ��'���9j3wRR�`Ȑ!Z�D��ر�I-_$�(3�L$$$8;�GR�����o9q��=����ĉv}
.\`Ϟ=��թS'���y�&�:u��v��MkyxJNq���~���t�܅X��ǎ#::�]�va6�y���f��
�ȣ())��!��CP���H�;v,�~�-�V�b�ʕ<��S�:u�U�V�=z4[�l!,,���P���Ï?����ٶmF��͛7�+���f.^����O>�$���\�p�.	Ų���n&y�(9E�I��������,[��I�&Y�<�'<<���d���2L�G��ɓ���<�O?���!��<ҦO������	��opp0$;;����m�[�f�…��:t�ƍ���c0سgÇ'==���|||l����`�ȑus`"@rr��C�Trr�>��GJN�F��k��?���s��U�N�jm�6m;w�$>>���'F'"""""
�����Ctt4_~�%�oߦW�^�|�r\]]�}��݉����?$--��W�Ҷm[|||�7oO<���ŋٸq#������0n�8֭[ǡC��1c�M���ݝ�c�6́�4Z6XDDDDD��Rr�4iׯ_g�ƍ���S\\̘1cX�t�þEEE��ƒ����O�Ν?~<�fͲ�����������ϕ+Whٲ%�{���_f�ĉ�?�q����e�9&&�ŋ�����͛+M�q��w߱i�&222�}�6={�dƌL�0�ʹ

HLLd��t���ڧk׮�F	�]�v59�"�q�������/,\\\x��0`s�ε�ҧ1��d�ƘLy��e�o���Ç��ϧe˖���?y��:u*6�]kG�X���8|�0C��""MXǎY�|�Mە+W�ܹ�M����-bѢEU���닯��M[۶m1�L��ƒ��G�n�������̝;�6m�<��`2�0�L�CDDDDDD�H�)�d0s�L���m��9���v}KJJ�7o���ֶ+W�GNN��Ѹ���֭[���޽�ɓ'9y�$���L�>����]�����$��q�AAA\�v��v��Y�/_ν{�x饗*�w߾}1l�0�mÆ
#33�����ꫯ�(&i��~�m��ӫ��PVV�?�@ZZ���l۶
//��R�����ٳm��URR™3g8s�{��!66����\�t��1���ٵkf���^{
ooo���DD����g?����%K���닻�;.\෿�-��������HHH 44�����RA"R{_}��ׯwv""4b��|�Mg�!"""�HRr�4Y۶m#//��ݻ��{�����ɓ'���ؾ};�����׏�K�һwo.\�@dd$������X��|��'lذ���ݻwٻw/QQQ�ڵ��ӧ�TIq�a�^�������R}�׮]�駟�ޣs��ۿ������㥗^�t���k7��-##C�)"�����*���(++�ʕ+DDDp��1>��CV�XQ�!V[}']4��������ϳ`�z��Eii)�N���=�O�&::�z�t��k�c-..fٲeL�4	�����?���$''���� q��H�9��V����0a�1QQQDEE�l�Сs�̩�9��܈��`��������iݺu��%Ҕ]�x���d&O���PDD*���L˖-������#K�)��}�Y��>�;x� K�.�g���LJ��7,X���ojj*���xzz�H"""�8q"{��&��iӆ۷o�����s�5j�&MbҤIՎ-  �Ɖ)p�N$�w�y�Z� ,,�����{��z��a��gϞ6}D��4�ec�sqq�[�n��׿f�ԩ9r��!5i��������o��-Z0p�@"##����������իL�:��6m�4v��I||<!!!N�NDDZhh(^^^������;%%%<���:�Y�fո�du4���֬Y��������yD�R�""�Uu*^����H�)9E��K�.п�vGe�/^�����ñΞ=k�������w�����>|�>���3gb2��}�%��._���O>Y�}oܸ@�v��Y�,}D�y�]����ꫯ(..�w��̘1��K��I-EEE��ƒ����O�Ν?~<�fͲ&��O
�Ib�%���͛6�ՙ��\111,^�ooo6o�lm?|�0k׮�?��?hѢS�La޼yܼy����|�嗴lْ���g���Ҷm[��PVVFLL����ʕ+�lْ޽{���/[�
k���9*(( &&�p��u:w�̘1c�3g���v�&&&�v�Z���iժ/��"o����BHuc�ر#�}�׮]�&�Xxyy��Yٵ~е��Q����ӂ�<x�͗�]�v�h4���H``��7�����g���&�	��Tos8�9EDDDDDDD�%��ST�0���f��-Z�����ا�۷o[���eȐ!<x�?��O�8q�M�6�}�v�ϟ_�eq*��b6�i֬%%%v�-�jò�����6K�Ì/"����Y�fY��N�>m�¿����͛Gnn���ʕ+��ő��Ctt����:�<�:uz�9׮]KAA��]ЫW��.���ҭ[7�����߹s��>���_��a����lݺ���ݻ�<y��'ORXXh�+���*�}�6���:�Ν�����c�233����M�66�̝;ך�s��v��MYY���UMb�5k�>s���W^aĈ��ׯVe�+�=(���N���GQQÆ
��6l�0233ٿ��������R"?qݻw��ѣ6�999v}
{��!++��i����???bccٺu+AAAܺu��k��*VKRHaa���|�����mb���b��m忄�������K����$..���������۷o'77�~���c��9BRR 33����6)��V���RN�:�ʕ+:th��,�W�^ddd�b�
����v���_��W�͛@TT͛7g���ddd0g�����J�$�lذ�����/���%K��k׮��h�֭�;w�nݺY�Ill,����={�-[���ӣG>��222�9s&iii���W^!22>��#fϞ�/��o�ARR�M"ヮueע����u���@߾}�Y�,}DDDD��u��U�F#/��"p�ڭ�hd„	N���p�R�U͝��ĢE�X�h��m�*)9E��_��DFFr��QJKK��ox����=���0N�>ͽ{��~�:��0��/N^~�e�F#�1EEE���ooo�;�-	'�%��ҡC>��S���9w�QQQv����5k����Ν;�^����+��R�ܖ��.\�`7���6��HՌF�ͣ�vK@XX����e˖���n7njj*p�=��ۛ�͛ӫW/"""ػwo�b2d���������믿�Ps8��d���郫�������t�Rz��A�V�'�YX��$$$����?���I���ʲI��n��]�g�}�Z%�v�������E�V��UPnݺU�X|}}���Oٶm��կ0����z�jL&��}��Wٵ�i�5y�Z>�,U�e�;g~/""""
�r��3�<c�_�~N��1y��+���̹�;Ftt4���/fÆ
?~��#��
-�#MV@@_|�gΜ��}0n�8����`<Hvv66�Z�n�…�σ�����$**�.�����s��q�������Si��F��O>aݺu�[������/IMM%;;�����6{��*�>|8��������	��Ph�ȑ��("����4p�@�������3???�cզ�@����ر#�
b�����R��Ӓ�PQ�d�������������}뭷x��w9|�0��>`�̙�L&Z�n]�~������ڴ[���˗�)���=t,}���o߾SRR–-[����w���W���4�_���_���7h׮��6K�����ԭ�ӧ;�N��Ȓp-�U��by�ԥ��7�����Y�l�&M��]���Oxx8����{MDDDDD�%�H��e$ꃫ�+111lذ�/�����B^x����طo�M_www�����IKK��ի�m��͛�O<a����O�-HJJ�ܹs��%�F�IPP����ŋٸq#���6�.8�p�B\\\HMM�����Ȳe�?~�M�N�:Ott4_�5w���'� 88�����U�=n�8֭[ǡC��1c�͸���ݝ�c����HuT|��TI��}�l6�<�TC��OE�o߮n��~��͜�U�hժ��v��}�eȐ!<x�?��O�8q�M�6�}�v�ϟϫ��Z�~�U>Y�"GU�j�ȑ#)..f�޽vK渺�DLL��V�թ�R��-��:��9��������Ѳ"
�����!4:�+GZ���c}�a�6l��ύ�j���\�z��S�ZۦM��Ν;���'$$ĉщ����Hc��i�ڶm˒%KX�d�M��=<<<�k�>���_��,|}}�}�p�:@u����$22��s�m���Dll,yyyt��
�_���̝;צz��4��ݻ���r��	�{�9k��'�.\���={l���'g�Y����\���>��#֮]k�tR�~�yzzr��y�?���?om�����y�N,}����ѣ�޽�7�x�nK��&�<���N;u�D~~>7oޤS�N6�,�5Ul�k�}��6m"##�۷oӳgOf̘��	l�Á�~�:�;wf̘1̙3wwwk?K�Mbb"k׮%;;�V�Z��/��[oY���������r�
-[��w�޼���L�8�f��?geeY���a���x{{�y��Joxp���l<x�M�|׮]1�$&&�B������4]JN��� >��3

 !!��`����4��c���߲j�*V�\�SO=ũS�X�j�]�ѣG�e����

�O�>���l߾�m۶a4ټy3p�2��l��ŋuGgM�l(/��2yyy,Y��	&ЧO����m��hԨQlٲ���HV�\��O?Mnn����f9���2m�4�=J\\�o��W^��ˋ���=���{�u���k]���N�|�I���p�]�%���O""R7�L���D���DBB���hT,I���0�L��уݻw���Cpp0����ر���q�AAA\�v��v��Y�/_ν{�x饗��� _�uk�\���|v��Aff&qqqv7�̝;ךt}��v��MYYaaaDGG�u�Vk��w�r��IN�<Iaaa��_[�v-v���ٷoEEE��6l����߿��(EDDDD�Ѧ�i��x�*똛�,X����@RRRX�~=�[�vrt"2}�t>��sΟ?Oppp�}���9x� ���v�e�[�f�…��:t�ƍ���c0سgO��ɜ
%((���H�����������S�~��?p�/^d�̙6ۼ�����2�ѣGȶm�صk�v��G������uu��R������IOO'''��<����K��KHH�d29;�&�:	M���}���s���}��G\�v���~���{�Ν;�o��o��$..Κ��u�VΝ;G�n�X�r%}��%77�e˖q��Y�l�b��M�=������'66���8��Ҭ�)�|�	p�"���ݻwٻw/QQQ�ڵ��ӧ�TIq�yV�^������2�59�������Ws��Җ�����Ѱu�E��4h!!!�Y��5k�0��*�������U�_111���Ѿ}{Z�h���7+V���0��ݝ��8L&���͛���a��Q���ŋ�֭͛7����ֱ�dΆ�������yꩧpuu��Օ޽{̻�[�~�k׎��x�L�B�.]h޼9]�taڴilٲ�z�`��DGG3j�(��������ꊷ�7o��۶m�C��uu��R���q�hӦ
���СC���3v��z�SDDDDK2�3�<��y}�ꫯx�w���M�6���������Gk���4����߿?-[���g�e�ҥ8p�n���P���hժ�5I�֭[��J+			$%%��?0i�$���HII�V�5NL��q;r���~�ME={���#"""""b��)Ҩ�‰s�L&�E)�Hu�ؑ�˗۴]�r�Ν;۴{xx�h�"-ZT嘾�����ڵ��=��sV6�ö;���營�_��T����{�1BCC�ˡ�d��ګ3��!C2dH��:��sn+k���m۶�L&bcc��ˣ[�n���q��q�ΝkW]DDDD
��^��իW[��\���+W�����˗�/'������>k�>p�@�q��ݻ��gK�zYY������w�����>|�>���3gb2��]�֒RS�=nGnܸ�O֯��f�#"""""b��)"""??���0�|���ܺu���2����[�iX>q���N����ڵ+			ֶ�����P"""�b4+]v6))ɚ���������j֬�C�_>٤��-[V9���/��Y�|9�>�,w��aӦML�0�ݻwWk�ʪ���f�ώ�&>�q[�uq��h����UDDDDD=JN���0aQQQ�3��{�ɓ'���E��3g��#�����͍��RRR�r�
W�\!%%����j�-*""�,ǎ#::�w�y�ŋ�a��?��D~�������_�~dee�a�|||�K��wU����g�V������w���`0�j~������e�֭q��-֮][��,I!����6G�V��v�S�Nܼy�n����GDDDDD�B�)"""?���,Z���}�Һuk\\\0������`]Eęj�:4h!!!�Y��5k�0�||||����H��l�2&M���`������)..vvx"?	999���G�����X�f
���ܹs�իWc4y�W��F�@dd$��ٔ�����ͪU�9rd��~�嗭U����ӧ��ހ�+/^|�:t��O?����s��U��v4�e)�.؍ki��rA"""""�hk���iHNNvv"҈%''3y�dg��蹸�`2�0�L�E�R�}��-"�X����?U���\�z��S�ZۦM��Ν;���'$$ĉщ�44��_�򗤦����Ϳ�˿�l�={��砠 8�ŋ�9s�M?///���

"22���(�����:t�ƍ���c0سgO�c�5�O>��u�ֱn�:�
fׯ���h��Ç���NNN�]R���&YGDDDDDmJN�1e�g� """"""u�/� 99�ӧOs��:w�̨Q�		�M�6�?\222���"55WWWF���o�I�Ν��դ/@QQ��������ӹsgƏϬY�puu�711��kג��M�V�x��y뭷pss���~�:7n$==���bƌ�ҥK펽�����DL�.]��]�v�h4���H`` �ڵ{��,�H�����7��<o�:u">>���h���k�ܹ�O<App0?��ϭ�ڵkG||<��<����ԩ?��ϙ={65���ߟ-Z���Ĺs��޽;#G�$((��o���lܸ���|JJJ�s�…������Jqq1F��e˖1~��Z���Ǎ�9��� IDAT�u�8t�3f̰�СC���3v���y�)9E��y�|����ڴ��瓘�ȭ[�X�b�Ͷ����;��ܹ�޽{9~�8۷o��B�:}KJJ�7o�����\�B\\999DGG��b���ܹs�y�u�ݻwSVVFXXp?�d�̙���Y�����),,�;�}��QTT���a����d������U�Eٻw����/N���ӓ����{��

%44��~�U�r���營�_������[�9���X�d	K�,y`�����۶m��d"66���<�ҝyyy?~��s�Z�EDDDDD,��"�ꫯ�b����CD~,wĊ���H�s�N�,Y�K/�D�f�8y�$s���СCv�-<�S�N��˗پ}���7��}�vrss�ׯK�.�w��\�p���H233IIIa�ĉ6��у���qbcc���#--͚��m�6����޽;���ޜ<y��˗�OFF}����fi���Pr��<�������HHH�&�$$$`0prt"""""�)9E��ŋINNf����ED���dZ�l��0Drr��C���׈ȣ̲�̓ڳ�����/1�͜:u�?���������	��۷��X�d���H���	c�������%�T�ojj*���xzzЫW/"""�8q"{��KN	

�����ӧǭ[���<�ҥKy�g����7��
,��̙3�����z��i�GD^e�O���#�`nnnDDD�`�HIIa����n���щ����Hc��iIII�AD��ӧ;;�3e�g� """�Ю]��…9u��6��l�6d����ҥK��{��E�J��8{��][�޽�?[�*++��Y��߿��~��ƍ�k��n����GD�Q5h� BBBX�f
��������Q�����Hc���`2�0�L�CDDD�R+X*8�,�z�jN�:E���y��ݻ7�<�L���-Z�~�`I
qqq�U_G	0�9��R�R_�f��[Ƭ8v�x���(~K��9D�vT���ߺ"""""R]JNi_}��ׯwv"RF���o���0DD��������ѡCΝ;g�^ZZj�ԑ��m�,DZc����'�����`0p����ك�`��C�{��;w��G�Z���ɱ�۩S'���y�&�:u��v��Mk��yhU�-���ĢE�X�h��;iB.^�Hrr��������̑#G���H���_SRR��ӧ	��ߺu˦��ONN���;v���Hƍg7fu��=���0N�>ͽ{��~�:��0�̛7����_����H�=Jii)�|�
��]�'�|�.�m��Y����������*��Թ��~���t�%g�;Ftt4�v��l6��k����m]C]D}JJ�i�>}��CiF��޽{Y�|9˗/��~��i��#;v$88ئ��O?�k��f�ou�s��A���	��ۺuk.\X�c
�/��̙3̙3��>n�8�$��Ç���NNN>>>6�,�VF�Y�DDDDDDDDU��"R������l�2&M���`������)..n�(EDDDDD�����0��w���777\]]y�gX�j�5�c׮]6�׮]ˈ#hѢ]�taƌl޼WWW������ݝ��8L&���͛���Q�زeK������äI��С����;���0���ƍ�M�6:t�nۡC�pwwg�ر5�A�Q׬Y3=��C�F�رc���&EDDDi��"��e=��>�|���s��U�N�jm�6m;w�$>>���'F'"""""R}�ڵ�.�SQ��#�=��֭��������a]2�*���騽m۶,Y��%K�Tٷm۶�L&bcc��ˣ[�n���q��q�ΝK�6mx"Mň#TERD~���������#K�)Ҥ]�v������W_Q\\L�޽�1cK�.l?�,**"66���T���{:w����5k��>K�M�����((( 11���ӥKk��]�b4ILL$00�v��5�a���9s������,\\\x��0`s���'���X�^���~�;233�{�.&��-[��ObLJJ����2�)S��U�"""�D��g����@hh(			���DDDDDDDD�:%�H�UXXȬY��t钵�����Ĕ�JJJ�7o���ֶ+W�GNN��Ѹ�T�J־}�(**�Ys�bذadff��~^}�Շ<*��{��IOO�V�GYY?��iiidff�m۶:��(<<��G�Z�_�v��;v�����ڵ���k�����7x�PEDD�	sss#""�@JJ
�ׯ�u��N�N�q�ꫯ�>}���y ��DBB���y$)9E����.]����'�}����ɓ���s��U��۷o'77�~���t�Rz��ͅ���$33���&N�HVV��%�222�۷�]����%���S���W����YYYW�\!""�cǎ���bŊ:�';;�>��A�QZZJDDD��*..fٲeL�4	�����?���$''���VWa���H4h� BBBX�f
��������Q�4^f���!��TJIt""""�K�)����p�^���#--
���0����������6}SSS�������^�z�ĉٻw/'N�t�3g�УG�m={���#"M������Ņnݺ��_���S�r�ȑ:�����.�5kf]:�6���z�*S�N��M�6��;wOHH�C�+"""��ɿi��d2a2����������H�V�:$"��.0p�@�vGw�]�x???�F��aIH9{�l�sݸq�v���m��Y���T�ڵk,_��1c�0t�Pؿ��}����"6l؀��C�套^bӦM���X�������$�ݼy�n��G�2f��͛W�X*�3x�`��򱅅�a4ٻw�;��9F��%K�PPP@bb"��K�.�~]�v�h4���HAAA��WDDDDDDDDDDDDjO�S�)*���JK�6k��}*�}�v��-c����Y��+"R^aa!�f��ҥKֶӧO�t�R��%%%̛7���\kە+W���#''���h��I�u��y:u�d�m�ڵXB�:�%K�p��1V�^���]�v%??���(�t�b=�����aÆٍ1l�0233ٿ��Tq��W�2a�ڷo�_��.]��ĉ�ҥ�]Rz}8s�O>�����s���P�L��pg|���s^�z���wdffr��]L&��կj<Uz���ݻ�$���<Q��+^�P�X-q>�y�ɾU�MJJ����2��׹����H]R�i��w���'l�+>0�ٳ���,�Gfff�sY��-_a�����^���t���������_cS�b������ү_?v���#GHJJb��dff����~HeyO�Jii)�N�b�ʕ:ԮO�^����`Ŋ5����k׎w�}���B�/_NYY����Jaa!xxx���@߾}�ư�Y�������������3��<�ׯ_����o3}�t�ۢ���z�j���P���IKK�������]�V�s�5��ǬKU]��رcDGG��;�x�b6l���ǝ�����4��"M�رc���oY�j+W�䩧��ԩS�Z�ʮ��ѣٲeaaa���ҧO~��G�o�ζm�0�l޼�_�l6s��E���x��'����…vI(���
�i���YYY�������߿?p)���p�|�M�����DFF���	�O���`�ĉ�ݻ׺4Ymc�����_�k��յ^b�<x0&����^�uN�<ɴi�x��}Μ9�c	��z��i�GDD���>}:�~����i���1�L��Q�,9��>���W�����իW�f͚z��!dgg�0h� JKKk�e73\�|���Z�je��QWUe�:MU׻.T'VgT��(..fٲeL�4�z3���?���$''�����DDDD�ѧ�i��O������	��opp0$;;����m�[�f�…��:t�ƍ���c0سgÇ'==���|||l��|�2r�Ⱥ90ydY��h�^�}��ŋ���9��ٳ���y��t�ؑA�1{�l�Y�Y?�;����s��N�<I�^�����l�q�p��JE�6K��d����A�I�<y2�?����ht%����c}�a�6l��/���IKKc���N��.Y�Q�F#͚5�����JJJx�w(**bݺut���ǔ��իW�:u��mڴi�ܹ���xBBB������<ꔜ"��3>dpss#&&���h���Kn߾M�^�`���6����LJ~HZZW�^�m۶���0o�<�x�	k�ŋ�q�F���)))`ܸq�[��C�1c��8:���;cǎm��F��_u֏6��6ϛ5k��>ݾ}��!�=���uKMX΋���*��6G�NDD�Q�����DDj�ڵk�_��������bz��͌3X�t)`��KQQ��������ӹsgƏϬY����O�q��o~��N���~�;��yڴiSe|�s�֭�_��~���e��~�������j�*�χ����|�2������:��wbb"k׮%;;�V�Z��/��[oY+a�?���kAA1118p��ׯӹsgƌÜ9spww�򘣢�8s�o�����ge���<##���(RSSquueĈ���t�ܹʹ�ƾ}�X�b&L����焇���/��al��cbbX�x1����
�_|���ɜ>}�;w�йsgF�EHH�_�q�Z���2ׯ_g�ƍ���S\\̘1c��������m��ڵ+F����D��!""""R��"MZǎY�|�Mە+W� ���`ѢE,Z���1}}}�>0h۶-&����X����֭yyy?~��s��Zi:�w�η�~ˉ'l��9q�]_����سg���&
��bٸq#gϞ�駟&77���h���N�:����͛7�T�y󦵏��HS��L��gY�R������7L&=z�`���������7;v�/,,d֬Y\�t��v��i�_—��0o�<rss�mW�\!..������&�W���ŬY�شi��ф��Vڷ:s�;����s��)������߿����/��7np��ek�ƃ̝;�wΝ;wؽ{7eee���U���۷y���9w-??�;v���I\\\��Y}�駤�����˴i���o�[���c�u�޽?~��۷���Q�q�[�d	ǎc�����еkW��󉊊�K�.,]��&9ő�k�RPP`M���������{TUu���$r)�Q��LK�b���~�K��1R�X�N�Q��q�̘8Xr������,1 .�� ���h�H~���p9�/�k��d��?��l��s����Ĕ��GEEk֬��\뻓뵲��PRR���߿�k׮��8p���*���nȐ!ddd��7�0mڴ8*!�B!�Iq�xd
>���*|}}?~<������fܩ�����_�~������TABaȸq�׿�źu�X�v-�>�,����[�N/vԨQl߾|||x�g���_���bǎ����w��jՊ��ZΞ=���s��mL.�u��	bbb0`۶m��ۛ��X�
��سgO���(..�+BQ�H�ٳg��B�qwwG�ј:
!	s��1u
�5e��}�\VDGGs��9y����ի999P^^�E^^}����Ϗ�ݻS\\LHH$&&���3jFC#FΛ7�����k�.&M������|������ԩS2������;���HOO�ƍ�m�V=/��B�nhz��'	

�S�NDDD��jINNV�S:�/���ӧOӥK֮]K�^����c�ʕ�}�v�S��~�z�z�)���VG�a���4���|8�<QQQ�eh
(�r,666�^�oooٶm�V��ڵk�_�[[�&��nݺ��jՑJbcc��—ɓ'ӪU+rrrX�hiii�i(��F$m�cȎ;())��ɉ���=z����w3ԍXЫW/�uJ[zz��!�B��F�S�}��7�w"33�I�&�k�.BCC	

�Yogg�…[t�����t�R�Ν@bb"�7o�m۶-�/!��iΜ9�߿���OO�Fc===9|�0���zpm۶eٲe겝��/_f�ԩ888�w��cri���J���h׮k֬��ܜ�� fϞͪU�عs'666:���rssqqq��C��wذawvpB!�jƌ̘1��i�Hسg��S��)������"99���E�>��Ņ���~�m�؃���#PWx���;III
~�_���9������DGGӺuk����sܸq��䐙�ɐ!C8~�8���|��W9r��cǪ�aԨQ�����G��`Μ9h�Z***����y�߿?~~~���|��wz#���`nn·~h�h�����������ߟ%K����l�8��
��R�믓����ٳuFm�����:�����֒��Ͼ}��駟8q�в����z��a������{�=�.]�[XX�2�׵kW�!�B!�)N�,�M��}�8s����t�ԉ�^z	///��W[���fÆ
,Y�D�S!ģ����,--	',,���T�^�J�n���� 00P�C4kkk�Z-�}���ɔ��cee����/�駟Vc�}�]>��c��ʨ��n�c2&��

�…�^�Z�����V�ZEhh(���L�0�M�6���Ƽy�t�HKK���Zg>w!�B!ĽS�����׳~�zuy�ڵ�]��{���~X�[C���={�)S��wQQ�Q���׏iӦ�k�.v��a�f���s�ر���U�}��7<��cx{{���|��jq���ÇoV�ݻwWV�ƹy�f��)����_�]9��ϟ�i���e�ʕ�?���P�����Y0`�ΔM�j�}r}K�,������Э[7�z�fo[�X.^�Ȳe����׋�����\wr�*�L),R����@�(3�)mJ�B!�w������k.3334�=���B<<����---�C�:��,_���˗7����?~�^������77�����-88���`��W^y�W^yE]���B��AII	]�t�>|=u��-2�?!�B<�Mќ�>����75�Hs���s��1�����^{��AP�(�U�VM��w;�^���[������c��>;v�H����������>|�_|;;;��y�9BUUyyy0;;�f�צM�gC��X
�DDD����F�1x���\�#ie_fff��_K����+������ɉ#Fн{w����⯵wr�*���9��^�γ��׎B!�
��!��1|�p����e���X[[S\\�|�3�Q7�|���k��������wppЛbH!��A���EXX;w���3gңGu!�w����<y��ҷo_�o��ѣGy뭷pqq!<<\'��ɉ��_���:Ӵ���z};88P\\�޽{qpph�|���X�b>>>�����>ǏϩS����Ϲv�nnn���������~�իW�=�ϝptt���ԩS���j��S�t���ㄇ�3`��)c�����S���SO=u�}*>��c����ݻ7yyy���5�&	C��?�V�	�>}Z]_SSc��Xwr�:99q��iN�<�N����V�۷����+W�о}{�uW�\Qc�B!��[L[�.�B�f�4iP7���ѣy��1c�����ٱp�Bgx����$((���DJKK)--%11��� ڶmk��B����l�Q?��\�~��+W2}�tpttd�ԩp���ۏw��z߾}
.�J��sݺu���RSSCNN�֭ӋU�:���)((���ҥK��o��Օŋ���H��*�=z4Ç'##�9f������/�┡C��ȑ#���N)�		!;;��������:l�0.\����?O<�����n����>�YYYj�τ	��XN�8ALL@�����Bll,'N�Pc�y�G�����������;�Wa̵S�ĉ�����J�� IDAT�ɓ�����?m�gϞ�Y�Rڔ!�B!�9E!�x@������̾}�8s����t�ԉ�^z	///:v�h��K��ۛ
6us���^!��Zj���"##)//g֬Yj��ٳ���%22ooof'D�S�2g������?����g��zzzr��a����FLl۶-˖-S����|�2S�N����{�6ڷ��/���TUU�>۷o���������S}/��O��?��s����϶ب/��?>�}�gϞe��:뜝�ն��X~��W�
i�
{{{��w��̜9�`|SӨeffRYYIPP�ڵc͚5�����ٳY�j;w����ƨ�{�ȑ$%%�7�.@AA��h%�˘k�>:Daa��
+&L�+B:t()))����'V~��b$!�B!�9E��Z���<�!�111�~�z �����hرcG�!##��{����'�)M�h4|��G|��G̞=���!��C��x�bF����ӟ�Ć
t��uuu��Օ�~��իW�����ѣ	��ŋ:�PUUŖ-[�2e
/���'Of�֭TWW취�ooo���3f�֭�e�ҥK�Y��1c�0d��J�i��TVVǠA�t��ܹ3������QYYy�9q/�/F���u�oeiiIxx8S�L�'���ܜ=z�f�,,,�Xkkk�Z-�Z�n���-#G�d���:�C���t�֭҅[�ұcG�,Y��n�>�nj�/PFQ�S�����k��Fǎiݺ5;vd���l߾[[[RSS[l�7n���
sss:v�ȼy�ضm��sh���P.\�������@ݔE>>>���
�|�X�����cii���}��aݺuj�Ν;o;�[{����‚��p�O�����7��	&Ю];����֥��amm��P$�B!��Ъ�����I��GLLs��A��Ξ=����M���A����o=g����M����zXY�`����0�^	!~�Z�"::�Fcp�!�����'�ap�I�&�_+}L�2���D�8GGG����/>�������ˋ��<��������aff����?Ε+Wtb_}�U����J<<<())щ6l��Eޭ�˜�e���_6�xv��Ehh(˖-S�RDEE�i�&�{�=�M��d^��x�~���JKK�<y2���z��"#r�޶mۈ��`Ϟ=t��������Y�h^^^&�д��k!�B�{(SFNB!�B!�Qbcc���-��������Oޑ}��6o��ѣG�j�8::r��y���n+6**���<���KLLǏ'>>����a��'�|�ݻw����NS�����߱c%%%899��s��Q���駟=ʨ(��0�x����ի�^?J�#��d��Ḻ��k�.***�y�&gΜa���<���&�P������ܹ�N�Ett4zS
	!�B���M��x�9rD�N.!�0D��ȝ(B!�&�PAE����LRSS���%??�}����O?q��	�^��ׇ��/C��_�~����d�����6:�������7t�֍�� ���IJJ���]�_�����;��Z-�Ç���G�>}pqq��c�ҥ���;f��u�6�u��U'F��ɤI�ԑ��)Zvvv�T+B��YZZ�ҥK�;w.���l޼��mۚ8;!�B��qO�4B��<JEl�Z�2u
B�;��4B�(�x�"˖-#??_o�����Y0`�Ν��سg�uSRTT��ֽ{w�gez��7o�mJ�����ٮ��Zbz
c����������)mJ���l߾}�9s���j:u��K/����;v4u�B<���76l`ɒ%����8+!�B�(��!��pss#>>��i!Z�r׽B<l�Y(#�*�X�~=���8991b��w�N�>}x���mn���Rbf�?�psb�����-mڴQ6T0��Y���
�����s��IA�x�����h�P���|�e��B!�0)NB!�B!�Q�;�V�����ӧO��kjjt�:���u����੧���9��w�^Z�prr���Ӝ<yR�V 77�E�o�1�Ӿ}{��ʸr�
�۷�Yw��5F!�B!��~"�)B�g�;1>>^�x��
ޕ(���9r䑚�H���F�!::��i!�}��ѣ�;�ӧO�f�����{{{u988��k���ϒ��CHH&L��9��F�b��������3�<ï��JTT;v��Օm۶u,'Nd�֭����f����Gaa!���F�s;�9��={RVVFqq�^Jqq�#�B!�Bq?��!YYY����s�Njkk�9s&=z�P�_B<��]q�"3!��3r�H���$00Po}AA���#���xzz����ݛ�3g�mۜXOOO>Lvv6:�m۶eٲeF�����������&LP�>�c�g�С����������N�2�˰a��j�B!�B!�ƒ�!ׯ_g�ʕL�>]�y�ԩ��������3B!�B<l��X�b555�������3����3gg�Ν:�)7ndժU;v{{{&N����z}7'����V�g�}Frr2���XYY�����ŋy�駍>^���ٲe��ڵk�18`t�0�x&L���M�HKKc޼y:����amm͸q��j�B�.Vq?KHH@�ј:
!�B������BcS��������Y�f�m�g�&66���H���M��B!��Qccc�N�S߭��(�q6m�Ԭ��kkk����Y�|y�q
��4�nee���/���M��~��m�{<VVVh4"""())�K�.���p��)-ZD�v횝�����33f�0uBѨ3f��/�:
!�B�����¡C�HHH����7nСCF��������R��Nhh(���777�~�m:t�gL,@UU<x�_~��:���/�ݽ���ƍ�����c�ر���;:#�\�t��?�����_���ѣ����;���J���4h;vT�;w�+qqq̝;�;=�B�GXaa!={��k?�<QQQ;v���2ڴi���GF���Y����Uc�e�a||<ǎ`��r�B!)����믿&::���qppЛH�����nnn�NC!�B!�	Iq���}��'DDD贕��GEEk֬�Y���w�^nܸARR�N�"**J�K���VWW�x�b�����JKK�j��������N��-�ʕ+j�_~�%7o�����+8Y�`%%%�6����ڵkz�����t��V2�������M���YB����/!%%E����'o���kSuu5����w�^"""t
��,���عs'���̜9�=z0`��{��B!��XZZ�ҥK�;w.���l޼��mۚ8;!����0g�S�!�M�h4DGG�:
!�B������^ll,���L�<�V�Z���âE�HKKӋ?r��7ofРA�����_����FEE���G߾}���{��BFF���������OD�N����@�Ւ�����ر������x����ѣ999�Ozz:�z��[�����Kq�ⶥ��l�裏�v�/��"K�.�[�n��Ԑ���G}DAAaaaj��1��\���ӧ����ԩS	 !!Ag�*!�B�����fÆ
,Y�g%D����M��B4H��B!�.)N&�L��T{ff&�����֒��Ͼ}��駟8q�W�^�����We�_�~����d������S�{��ABBBptt�[�n���NRR�^q������@ݛ�VKEE���������ѧO\\\x�X�t�N_���@]�K}]�vՉB<����8M��� 88�'�xsss��yBBB�:u*G���9EFFR^^άY�ԶٳgKdd���B!L˘�i4��Fc�4�h�3f�:!�hО={L��B!�CM�S�}��ŋ,[����|�u���zm��YV�y8w��mŞ={�)S�̯��H��{������@7o�T۔���맳���?����˗����[��)1B���ŋټy3G���t�ޝy������~�SUUEDD�_~�C�����xyyaaa��/�����…\�xQ-NQ8;;�}�T��
J\s�)����4h��TB�;w��Օ��8�Νk�R!�B!�B!�B����h��[�_����|���1bݻw�O�>���k�67׽���33�ۊ5Ts+C���i�F��U�Vz�>�]?�[�7���fhB��ϵk�����)�+((PSnU]]��ŋ���S�JKK�j����f�u�V^^^�p�B^}�U����۷��kܝ2&�PUU��xu�!C�����7�|#Ӝ	!�B�)//gҤI<��|��;wwww:v�HRR�]�aa!={�4�.55�={����KEE666<��sL�:777�xcF�4{��i�������������FÛo���훺��F����/[$����v�o�9�]�ɵ���s^��R���s��1����>KB!��^��q�S�Di�Z���8}������F��#;;[��bVVO=��^�͉upp�����{����������O���ɓ:_�����Ŷoߞ��2�\�B���u�]�rE�B<����9w����������Ջ��(//׉���"//��}����G���)..&$$���qww'33���^}�U���غu+��9��9��ߟQ�F���3�I}��KMM%  ���*�u��y���ЫW/�})m���R�"�B!�F�<D��XY�۷�]�_��RRR�޿���or��!�����?������ʸq�X�zu���N�<�._�x��1r���%5�>J���c�Ν���2s�Lz�衎-�B!�)Hq�x`=z��c�r��i֬Y��WTT`oo�.�v�Z�}�Yrrr		`„	z}6'vԨQl߾|||x�g���_���bǎ����m�6��e�ĉlݺ���֬YC�~�(,,$88X/�gϞ���Q\\�W�R\\��!L
�yU�=33���d����i�\\\���։?x� !!!8::Э[7���pww'))I-�h���?~<���?~��'O���ʼn'����O>��C��DEE�y�fn޼ɐ!C��[c�,,,��ҫ�k׮:1B!�h\BBB���&�hXBB3f�0u����S��)%%�`{pp0����///F�M�N��r�
ǎc۶m<x�6m��|Nej���|��'8�����o����xxx��c�1gΜ&�Ւ�$
=�-�9���0��\���ӧ�7�M�:������4YnB!���&�)�7r�H���$00Po}AA���#���xzz����ݛ�3g�mۜXOOO>Lvv6:�m۶eٲeF�����������&LPNC�%%%���\\\\t�)�6�������i���p��Y�L�b����"��ݫW/z�ꅧ�'���l߾���p>��C֯_��v555�[����̙3��K��S����˗���ыSڔ!�B4nϞ=�ٳ��i!a�
����	W��l�–-[���N�"))	[[[�Z�Zu�%M�4���3k�,����>}�z��)�(����jժEFu���fŊTUU�i�&����'22���rf͚��͞=���X"##�6avB!��Qff�����	��aŊ�?KKK,,,�ӧ�֭S�:v�ܩ�q�F���077�cǎ̛7�m۶|3ޜXkkk�Z-�Z�n���-#G�d���5j������L�>;;;,,,7n���z�&L�]�v����KKK��ښq��������l����Vg�U�Vz�֏���ի��6l���z�A�k���N�fHEE������M�6�l�2�0��<��u{��f�\!�BWmm�<�!�{����6���C��ŋ2z�h^z�%<<<��opuu�+v���b˖-L�2��^z�ɓ'�u�V���՘[�����~޼y:�)����Wob�ꫯ�ҥK�Y��1c�0d�u���Rr+**���777ƌúu�~����4h��ree%}����
��O�7nl�!@hh(���,]�T����W���7V�^����G�&00����Օ��$�������ꊯ�o�ϩ��ɓ'=z4�/V�:��ŋ9r�zn6l�`�sT��^�
i�5TYYI\\�
�cǎj{�Νquu%..�����>.!�B!�"�{666����:����gӦM�껹����,_���˗7�P���v+++|}}�m4���
�FCDD%%%t�����N�:ŢE�h׮]�� �x�999���~��^xAm���b(..f�޽�0���ի'O���/������+��*Qֿ��;�����ޞ?������Q��۷����+W��Msv��5F!��{��L���777��8u�����?�h4<��|��������I�=���Q�]�����ΝS�


����뻺��ŋ����������j���%,,���2��XÇo����ؼy3YYY
�TVV�`�JJJԶ���s�ڵF�6dѢE�{�7n��_r��M�7;���ի����>}Zm+++#&&����Zm��-�ٳ���DƏ��ٳ���|�޽{�\���8u�QQQ���6��[���������qqq�s�Δ��Jǎ�����o�m���7RYY�n|��'DDD�Ĕ��GEEE�M�t'פ1�Ё����eZ1d�222��o�6mZ�B!�Ƒ�S�x̟?�Ν;��i�����TCB���2JҺu���ͥ�����֭[�;j�(��β��~��w.]����7\]]u�SFQ����Z-~�!EEETWWs��URSSY�b��~�������7NNN|���S��S����g����hVB!ģ&!!���S�!�##!!��Ǐ�:���2eq߾}
.+���9w����h�Z�=Jxx������(����۷/111?~���x@FF���G���_�,����`p�IŎ;())Q�)y���O��mȓO>��ݻIOOg��$''�����/8}�4]�tQ�]DD����}�v��+((`���<��S��#Gؼy3G�E�������牊�2��4b衰��a���\�v���@n޼ɪU��v�AAA���6xݺu#==]-:����
_��������O�b�X��i�5i�1�Pzz:Pw�I}J�#�B!Ľ&#�����$((��K�2w�\ټy3m۶5qvB�{eΜ9�߿���OO�Fc===9|�0���zElm۶eٲe겝��/_f�ԩ888�w�^F��ܹsٱc;w�ԛB
�>m��Oe�����L�<�`Lff�Qy:���rssqqqщU>�6lXC�D!�����F�ј:
!	s��1u
�5�o�>}�\V(E�����2...�/9x� !!!8::uE	AAA���������{�9)Ӭ��7��imm�ο�>|???��\\\x�X�ti�����ン�3Pw]i�Z***���й�߿?~~~���|��wx{{�lSQQ������|��F����뫎�ѯ_?���Y�d	���z�2ƠA��h4DGG�믓����ٳuFm�����tީ����֒��Ͼ}��駟8q���t�Ƹ�kҘk����{�^�2E�#�B!Ľ&�)B< ���76l`ɒ%z_�
!|
Mu�j��ᄅ�����իW�֭�|�fmm�V���>#99���r���pqqa���<���j����LYY��\�K�.��_d׮]���\�t	sss�v�ʘ1c�={�O+fL�&L`ӦM���1o�<�~��Ұ��VG�B!�B���4�~�z֯_�.�]���k�u���y��}6��
9e���.**j4��;RZZJii�Zb�2͊��[�4DJQ���q4G����hI�� IDAT���qn޼��vJ��G�Tr8��N{mm-+W��󄆆�E
�<x���t�e�Uc��[�d	Ǐ'''�nݺ��[o5{��r��E�-[F~~�^lCEG�䪸�kҘk����@�(3�)mJ�B!�������1oo�M�@���ݍB<����	�i+--�C�:��,_���˗7����?~��u��P�!��On���iee�F�!""����t��}�z��)-Zt��2B!�B��[��e���b�kjD�����R:ğ����:��7���U��Ő6mڨ?:nc5T�Azz:���c��V��Oٗ��ig�����+������ɉ#Fн{w����k��֢���kҘkH�.�g��%�!�B!n�i�
!��ن���+�v����7or��V�^
�ޝw����ӹsg���ն��h�B!�h)���:�<(�������N�e(��ǰa�x������[,�;ɻ)���j�rc�Q<�233	�o߾dff�e��n4���L�����?���O�e��ݫӏ����h4�iӦ�����?��/�"H��ɓ:���E��2�̩S�tڕe�|?~���p`�C�����Y���੧���>�1EEE��ݛӧOv�};v�V�;C7-mMM�媸�kҘk�}��\�rEo�Ҧ�!�Bq�Iq�B�4i����=�^x�3f������.4q�w���%AAA$&&��l'&&D۶mM��B!1aaa����:
�_��?��;���練��EXX+V���w�e˖-z_��G���z߾}
.�J��sݺu���RSSCNN�֭Ӌ5j�����s��%���������ŋ�Xe	e�����W^���
///bbb�p�555����o����י8q�:e�!'N $$��'ORSSÏ?�Hppp�O�9r��Cvv6555dgg��nذa\�p�x�	BCCiݺ�m�388X}����		�k�'N� &&���jqqq!66�'N�1��Ӧ=z���j


P�+**�(_�1�d}�\C={�P����Ҧ�!�Bq�ɴ>B!����ggg���Ǚ3g����S�N���Kxyy5:��d�x{{�a��n�qC��!�B�mUUU�_�^���^SF�����?��aaa$&&��^x�$95��\���ӧ�#	L�:������4q��^2�8eΜ9�߿���OO�F��������dgg데ضm[�-[�.���q��e�N����{���~��7���[6n��ƍ��3j�(V�\�h.:t���B�
&L�`���n�?>�}�gϞe��:뜝�ն��X~��W�
ij*W{{{��w��̜9�`|S#/effRYYIPP�ڵc͚5�����ٳY�j;w���Ʀ��Ԑ�#G���D``���2��ܚØk�>c���C����Bnn��d�K)FB!��^��qO��<�B��KBB���i�����h4r�@΃Bq(_6��lРA>|���d��xShժ�������$&&��?�,��DFFR^^άY�ԶٳgKdd$���&�N�k��Q�k�Pq���%��ᄅ�����իW�֭baa��Z[[��j���HNN���+++\\\X�x1O?��������SVVFuu��naaAhh(���|��W���PQQ��?�s�=���;Ço�-,,g˖-:t�k׮1b����9p��8#���ɧ�~��Ç�t��۷g̘1����������b�ܸq#�V��رc���3q�D���t�'c���r��V�^�NU��舏��V�"44�����SCV�XAMM
iii����<��3xxxp�����ٹsg��sM�g�54a�6m�DZZ����Y�������:
�B!��������ٙ3f�:
!�}nƌ��⋦NC!�B�СC$$$PPP��7�С#G���ۛv���-pIOO'44��baa���o��6:tP�3&�F-��������/t�Ё�_~Y��O�߸�86n�Hvv6�=�cǎ�w����ҥK|��Ǥ��p��uF����_����c֬Y|�ᇼ���q�P�OK�����lmm�dlee%���|��w\�t�:0z�h.\����غu+���\�z��]�2o�<u�Ɇlڴ���D�L��;�Cee%qqq4HgԿΝ;���J\\s������6�^<����t�����F����F�(--�{����e���,_���>Ǐ���\?|��f�(�.[YY��닯�o���m36��������v���ຆ4��M�6������W^�W^Q�
=�
����F�r���S������^�wr
YYY��h�������.]�PRR©S�X�hQ��W	!�Bq7Iq������pss3uB!�B!Z�'�|BDD�N[YYqqqTTT�f��u|�:�7HJJ�ԩSDEE�w�[]]��ŋ���S�+--E�Ւ��KXX�Z��X�hW�\Q����/�y�&���@]�Ƃ())Q�ٿ?׮]k�<8;;����֭[	k�K߻�?���7o�����z�*���:�O�V���ʈ��!##�V�~yy��e�ϟ�ŋ�آ�"���ߙ<y��}���%::�>}��_�8p���*��2�������M�f��G���é����ח���cmmMqq1|��?���3�0�|���k��������qppЛRH!�B�{ɬ�!n_LL�Z���<�!�&s��1�K�B!�h���X|}}IOO����O?�
��ȑ#l޼��G���jqtt��DEE�VlTTyyy��ۗ���?N||< ##���D�~�|�Iv��Mzz:, 99Y]�c�JJJprr���?��ѣ�����O?5z.�͛G�n�صk�:Eɽ���>ƍ�޽{�2e����}���>}�.]���j9z�(8::RTT������?���/һwov��Mjj*���*Z��`�7n$::�nݺ�e���%==�^�z�m��)1Bԧ����ѣy��1c������5y�񨰴�$((���DJKK)--%11��� ڶmk��B!�#LFN�D||��SB���”�^{��)!�@BB���i!�]�L/�T{ff&�����֒��Ͼ}��駟8q�P7*G}����h�����ߟ%K��������ѱ $$GGG�u�FPP���$%%���ӯ�����@�ߟZ����
u��Ç���O�>�����{�t��ϛ��9������DGGӺu��ﶂ������D)��_�~���???�|�M���;�\9r�+V�����_q���7���-����8���@]�P}]�vՉ�>�wx߾}�9s���j:u��K/������TQB<����76l`ɒ%����8+!�B��qO̘1��)!�c{��1u
w�����
��1c/�����B��x�"˖-#??_o]mm�^��u���s�n+��ٳL�2�`~EEEzmݻwWV
&n޼��)�+���Lү_?�M�Ʈ]�رc���Mn�233՟�]�����裏��󣢢��ӧ�N�����:�ʱ�?^mS~�ٳg�r����I������u��˗�����NiSb������F#���[_��i��B!���Hq�Bq������f�4�B!T�Ee�C_4�_����|���1bݻw�O�>
�gn���Rbf�?�psb
�����-mڴQnժ��z��}�ϧ!o��)))���g�ر
���֪����nV��aee��ѣy�駙:u*
�4��b��s��F��ݻ�q�۶mc�ƍz}zޕ6c�'�B!�B����B�{�������Y�|9˗/�)��xH���ЪU+y�C��Q��L!r��1�Z-���'O�Y_SS�����������SO=��wsbػw/���z��������	��'O����6k{+++V�X�o��FHH��V��.�]�����NY[[�LYT�2ҩS�tڕe�t��	h~�˗/g�…��������k߾=W�\��NiSb�B!�B�p��S�0����/����1++���0v��Imm-3gΤG��P�B���	�`��!��u��QƎ��ӧY�f��^QQ������ڵky��g���Q�7&L���gsbG�������LJg�y�_����(v�؁��+۶m3�X&N��֭[			a͚5��׏��B�������ѣ>|8���z����|�2{��aڴi���jT���y�&�Ν��+}��i0v�ȑl߾���֮]K�޽���cݺu6L�:t(qqqlذ����x�	6o�L||<NNN|��Wz�ϙ3���$�����OزeP75PYY���zE(���j�B!�B!>R�"�	���l�~�:+W�d����jS�N%  ���,--�e�B��`ƌ�NAq���c���0r�H���$00Po}AAC�Q�������ԉ�ݻ73g��۶9����>|���l<<<tb۶m˲eˌ>&:Daa�:���(�����Kff&UUU:�#G�d���lڴ�M�6蜣ۡL�T_�6m�np������w�q��Y,X�����Y����3$;;�?��O:�o��[�n������:G��~���:���rssqqq��F������IHH0u
BѠ����F!��.��q_hl.�GIdd$���̚5Km�={6���DFF6��B!�B���ޟ�X����������y�g����̙3����s�N�‹�7�j�*�;���='N������kmm�V���>#99���r���pqqa���<���F������lٲ�C�q��5F����?hv?;vdɒ%|��:�˖-��̌�r��u\]]Y�r%/���ѹbnn����=���ͣo߾
����ɧ�~��Ç�t��۷g̘1�����ڪ��۷'22���0�=ʍ7x�����d̘1
�_�~����޽�O>��m۶1a�6m�DZZ���ӉOKK��ښq�������^{��)!�B!�0)N�.�u�V��ӹz�*]�ve޼yL�4I�i���~��λ�K�=ضm[��UUUDDDp��A~��:t��/�����G\\7n$;;��{��c���;�`ii�sgۭ�UVVǠA��ر�ӹsg\]]���c�ܹ��ش�B]���:C�7tn}�SQa||<ǎ`���Bq��ب���w�#��\-�)͍���e���,_��Ѹ��^1�nee���/�����6�7�̙3�F�������
��ؿ��?�����������
>ߍ����???u���
�FCDD%%%t�����N�:ŢE�h׮]����F�A�ј:
!�B!�&$�)�w��e�ϟ�ŋն��"���ߙ<y�m��q�F*++u
A�WWW�x�b���Ԙ��R�Z-������aff��ǢE��r�
7n���/���͛���7�ρ���28��!C����o�aڴi�u�Bѐ���/����W�&����",,��;wR[[�̙3�ѣ0ujB!������믿&::Z-������Ao�&��8r��7o6uB�$777�~�mS�!�B�P2k:D���Ϲx�"�{�f��ݤ���ꫯ��jo��nݺ���Κ5km���"//��}����lj��g��ddd������O>��ݻIOOW��NNNt�&���T�����ի�^J�#�-)%%E�My}��u��vS�~�:+W�d���888����ԩS	��NO!�B���Ғ�� )--������D���h۶���w�ٳgIHH0uBѨ���?n�4�B!Z2r�0�����ߞ��ɑ#G��9͝���ot�����08�y������#PW����;III���������:g��Z-��SXX���׵kW�!�ë�)�D�"##)//g֬Yj��ٳ���%22ooof'�B!�8p ���lذ�%K����b�Ľo���As��1u
B!�5)N�����гg��W)�h���ٳL�2�`|QQ�^[���՟mmm�y�f��\���ٻ������/PP1�\����`*kJX�o%�%��( �yKwK��2KEtͼ`	xET�`Ŕm� ��zAB-�0�K"r	E~�;'�pf@@}?�y�|�g�y��9�̙�yn��n/KiS�!�\׮]c�ڵ9r���ڷo���,4�Z���	&..��W�bmmͰaØ2e���W:)��Ę��\^{�5�4iBTT��g�.]b��Ѵlْ���Z]wBB���ann��˵���X�>�+1DDDгgO�i�Z�h���#L�8Q�{�B!>Cn%9�����{M�!�B!�B�j"�)�F���X��&&&����D}MQQQ��tUM��^RRR�n߾��fff���o�J��_�*�6C�B�x���cʔ)\�|Ym;w�RZQQ3f� --Mm���$$$���Tu���Q�F����������e�`���Y�|9111˩S�S���}߾}���ӧO�����CRR���g̘1��W!�B!�B!�Ba<IN��_��~��W.\�@�.]��gbbBII	yyyXZZ�����Ɔ��tbbb������ӬY3�����ɡY�f�rrr�>B�'Wxx8�/_��֖%K�йsgΜ9������}���HKK��ޞо}{����'))���hF�Errr����� ""�M�6�LN�߿�F�#G��v�Zz���ٳg����ʕ+�������;ܯ�йsg�ؔ���INB!�����f���<��S��?����ˌ5��͛�з��y����|F2�s��2�k�(o
�*��:�=/j+}ƾ�q2f�
ymE}###ILL�W�^�7��X�B!ģ�r�LQ
����ʕ+��ʢ���+V����믿��kҤ	_}�\�x����Jo�����r��9����~�:k֬��ё3f�N��2e�9mQzz�V��Q�@,�0����ƣ���ߏ�u놙����i�7..���S��ڵcѢEUv��q�Ƹ����?p��Q�T;�O��aÆ888h�?>}���̌nݺ��뫱o��~��yڴi��2M��G!�BQ;���еkW���}��.};��"���q��Iy��7o�֭�ԩS5�B!��&R9E�zo��qqq�����k�i,�:u���A����b��լ^�@�4���������驱�~��̙3��u6i҄7n0z�hlll����o߾:t���T�/s��2e+!�,J�Z�=4�˾g���o...:�U������ر���P����ѣG)..�w��ԭ���F�^�4�w��@c�"Cb�q�p����6��B!����!_�	Q����k:�Z�����t�С����j{�c2���0�}^T}Ƶ&Ǿ���>�WWW�:��ѣ���c�ΝXXX�XlB!��zHr��*�`ԬY3BCC	�رcҡC���y饗�~s���Ԕ��8


ptt�>`ذa����Ғ��6n�ȁ���V�̘1�:��y��~�z���(**��ٙիW����F���x,--:th��EQ�rOQRR��\��TQ��n߾�o�ԴiSƌöm�HMM%>>НPW6Y�޽{���Y�͐ؕ}/�z�Ҧk|�B�'YdddM� ��u��5B��k*��� ������֭cݺu�D2��b���dgg3~�x�m„	l߾���Pu�_!�B���H�����߿�>̟?����k����Q���.tXYY1w�\�Ν[a�����	'''���
���Npp0�l����N�:����iРA��B<�Z�j�O?���ӧy��ӧOk����!==�������i�ĉ�ڵ�;vp��QLMM�i�JKIIѸ}��I�y��bo֬YYY���ЬY3�e999j!�B!ģ�ڵk�]��� IDAT#G�PPP@������b������|��������իX[[3l�0�L����9��Ԫe�a��Z�����ի��/���ٳժJ���(ƌC�V�����Z�ȑ#�r�
QQQ�j�J��)���� �͛���6l�޽{��~233133�}���9�Q�Fil��o�e�Ν�;w���B���4h3gά�kSe�Zy���ȪU�����Mݺu7n3f� ''��˗s��a���0`>>>4l�P]����8Tt^�36���			���9��������ں��ސ����_��C�QPP��!C����rss����gϞ4o�\moѢ���DDD0q�D�UQ�B!��C�S��E&M�Ğ={������plll��B<y��O?�IJe�X�x1�>�,gϞeٲeZ}̦M����LJ�;r��M���غu+���lذ�_Y����K�.}G��O?�ȑ#ٵk%%%<��s<��SZ��.]��~��5����٨�;u�DVV���ZI(�4H�:u2j��B��ոq�j:!�8����t����?����;mڴa��ݤ����퍝�۶mS����1e��)Aϝ;���"f̘AZZ�ږ��IHH���ꬾX�O��&��{�n�ݻ����F�֭[����w�}GJJ
ݺuS���������/�H�V��ڟU�V����&�e�u��;w8s�gΜ!//O�����?'88Xc]YYYDDDp��->���*%�V�X����q�FZ�l�Ν;�}/,,dϞ=������o}�AC���Q,_�����_ll,�N�",,++���~*󻒛���ɓ���P۾������۷���|�S���Ӈ��$���Ϙ1c�`��B!Dm�p>�	!�baa��E����&33���L���Y�h��ׯ��5��Ã�m��믿���M�^�x�7���_��z{{Ӷm[RRR�����_��ٙ�[�R�~}�̙��mҤ	p��#F����:%��)}�@J�S�N%++�.]����fT�JueN�Ҕ��bB!�d��ᔔ��C򨆇��{M���j����:�+��ù|�2������p��1���4�0(���HKK��ޞm۶q��q"##�޽;IIIDGG��#����d��6m�EBB�'O�:�*_��ٳG�=66WWW����v�ڑ���&L(I�֭�رc>|X�>�c��u۷o`���$$$p��Q���u
ׇ%55��۷s��Qf̘@@@u��a���$$$0m�4>��ΐ��g�;/c�Gq��֮]˱c�		��֖+W��s�u>*b̹�غu+�jՊ͛7���?���V߄�:wLiS�!�B�Ǘ$�Q�<���̜9��+W�r�Jf͚���CM�%��&]��� ((�z�)�֭����z��t�]KKKBBBpww��Ɔ:u�`eeŠA�شi�F5�y��ѲeK�ԩCQQ�ѱ�.�<`��}V�ZE�~��[�.͛7��ˋ
6���3
4�y!0>>KKK�j�>	!�B!.%�k׮:�+�___�u놙����i�3..���S��ڵcѢE�������[��^�zj�[�n��;h� �6mJ\\w����ݻ���Ѽys�s�1�����9K�r&<<���H~��w\]]INN�H@8|�0�}�]�ta�޽�Y���˗p�����͟?��;bnn�&u���,X��6m�P�^=&N��9�+6>���.�����S��}���̌nݺ��w�Kv2Fe~W<���ڵ��;���C�����[e�m�V��B!�x|ɴ>B�B���rg�B��M��p�B����L�y�����;w.s�έp�NNN899U�G�;O�>
ܿ�Ԯ];�}7n��ի�.}coذ!������A˖-����ԩSL�>�J�DB!�BT��V�X��+��/f�����#ʴ�=z��x��z.]������m_�p����ԩCqq1w����Lkyaa�گ���۫?+S�ܻwO�v�֭�ȑ#	

%>>�!C�p��Qrrr�6m��~c�G��_1{�l>��#ILL���?g��ɸ��kT�v�s����ٳZ�,))ѹ��R�F�ҟ�J�������}�AC���Q���K�y���4��*͘�?��]Q�(=%h��ܸq�F�i-Sڔ>B!���%�S�B�GĀpttd׮]ܺu�{�����?��G�/U���|�_�Η_~	��U]&M�D�-W���ñ����ӳZcB!ģ����###������j�JQZ�$��)�A@7n@vv����
J��J'�芭��_SSS����+U���2j�(��1�S�j
ܿ)a�޽,\���{���B>��3���ݻ�~+V���ٳ�j�
OOO>���j{ϫW���vSӊ/a2>���.�������[W�R%�I���2�+�kˮ�l���ؕ6}~_�B!ģM*�!����Ç�k�.�X֤Iu���Vz
;;;F�Q�۷��`ѢE���;jbLtt4k׮}�oB!��w�}�C����ɓ�c�JJJpss���N��]a���dN�8��iӰ��gӦM;v�����888�ѿU�V���O�>}�^xAmW*8�fccCzz:111���[�v�q�qqqx{{k-W�U�С���.��֖^�z���@jj*�f�4o�\�S�QXYY��₋�iii|��l޼�U�V1f�		�I�&\�xQ]�ݻwu&�$C�G�qХ��&%%E���ɓ'x�g�l�9�Z�j�ŋ9q�}��Qە��Jk֬YYY���ЬY3�eʔFeۅB!��G*�!���ΝK�Ν�_�>������0z�h����)m�[��ͩW�}��e���:K[?l�?�<3g�d�ʕ�\��Y�f�,�-�BQ�C��l/((�>���lmm=z4~~~Ts�B<^�/����u>/m�С,[����T�޽˙3gX�l�V�����˹s�(..��Y�GGGf̘��U�5(ӛ���_|�֭[�z�*���dgg�}�v6n��+��R���ƌCqq1������j�g�ȑj%��|:v숝��Ω��;FQQ�Ν���Om�u�Vev��0d|�]煢��f�ҥ�~��I���pvv��mT��R�N�8�ݻw����Y�t�V_e�#ez�Ҕ��� 	!�B��S�Js���;w�tB�Zl�Ν�;��è�LMMqww��ݽ�C���>��}m��86B!ģL�[�:���BCC���f���jۄ	ؾ};���̜9����fHr����|�
����j&�y{{s��ARRR����_�>s��Q�7i҄7n0z�hlll���aԨQ8p���D֬YÚ5k����k�UY����Ӽys���iժ�FeC��<�&M���_g%�҉��
"66���p�B���;wN�JFm`��;�΋���M�j��]�t��ͭʶQ�s��ӓo������kTruvv�JB�۷/�"55U�F�����!�BQ�Ir���ƍ���B!�BT��~���>����n߾M۶m���b���j��\ʶ+σ���7ovvvlذ��v���|��������իX[[3l�0�L�����ֶ"""X�j)))ԫW��_~�ٳgcaa�1mB��rss����gϞSl�h�GGG"""�8q"�5����S6���x^���AAAr��an߾M�v����d�…���������q�F8@vv6
6���3fhL�3o�<֯_OVVEEEԩS�5k��7�|�O?�D~~>���������1�ie���2j�(���=z�Z�Ø�)��ѣ�[�.����T4�Z����L�4I��{�q��]���)..�cǎxzz���?Ď;j]r�!��8�:/�{lV�ZŇ~Hbb"M�6�W^�?��*sn���ĺu��o���c�����o�>����ά^����x���4����cii�V,B!��/������B<>�mۆ��rZ	!*���������xe��Q��C����J�311!<<\�0V�yy*��r��
��ݹv�ֲ?�P�&`hrʳ�>���6l�q��EEEL�2���4����bjj���ƍ�������_���W#9E���̮]�`Μ9�{�",,�իW���1c�h�^œ��Cu~���dĈ���]����=���6l�@pp0_}��:-qFF�F�b���L�2��#|2߯�B!�Q�TNՑ#GX�vmM�!�x��׏��~���B!�zؼy3׮]�K�.,Y�kkk>��S���b�T�ڵ#$$D���aaa���aooςh߾=�������Dtt4�F��XG�6mX�h��_&$$����Krr��/�ܹ�V�J[BB�$�Q
@~~>������	KKK���Y�|9=z����4i{��!<<�~҇���֔B��J�B��z���ׯ_M�!�P��"�K�.�s�NƎ[ӡ!j��;wbffV�aT��;w�tB�J��k��3]�Ct�'''s����[����__�J����s����qqq���ckk�O`Y�h�F�"66V+9���G���Ã��nݺUa<�ϟ�'��նm[�>B��k���j5����eM�4aڴi5�B,Z��w�y��'�ڵk�_�~
G��Q�O��[!�x��ܹS볲�I�SD��������X��3�3E!���+W�ЩS�*]����K�.��⢳����ڷo��lee��{�*��ƍ4j�Hk�Ҧ�B<\J��޽{���)**�/��{�fʔ)4o޼�CB<���?�̙3Y�r%�f������zr�3ͣB�Nj��IM� �p��"�BTwww��/�B�Z��t6��in�^�*))Q_STTTn?]USt����T��۷ok���ԧo�J?SSS�eJ�\��z�����*�D����D~��B!�\��"�BT�#G��v�ښCQ�����o�]�a!D���_�¯��ʅ�ҥK��LLL())!//KKK@wUC��ؐ��NLL666�^_y�5kFVV9994k�LcYNN��G!��Q&�~����oӯ_��C�o��	�knpGGG��/��СCy���B�(ۭ(V]}���H�Ν�ܹse�&!�p��%u>_!ģk�Ν?~���B�׷o_V�\IVV����X�GGG^�u�_�&M�ꫯ(((��ŋTz����חs��Q\\���Y�f
���̘1��u*P�)���i���ӵ�+mU=��B!Du۹s�\�B���Ν;5>�
QӤr�xb���:tH�R�������$%%�u�VZ�n]
Q�gH��ɓ'	dǎ�����憝�ݻw��x�x�Ir��6��A!j�7�x���8RRRx��4�M�:U�yРADEE�z�jV�^
@�>}*�}ooo<HJJ
�����ׯϜ9s^g�&M�q��G���Ɔ�����ˡC�HMM��A�jj*���7~G�B!j���p�rI!32
��m�r�xb:t�������#))�����=z����ƍjl�v+��l������>�WWWlll���e�����QPP�з/�B!��}�h֬���899ѨQ#����ܹ3˗/g���j�9s����J�ƍ177�O�>|�����Ғ����ݱ���N�:XYY1h� 6m�dT5�y��ѲeK�ԩCQQ���4hЀ��x�����XZZ2t��J�O
y�C򨵏m۶��ۤB!�cM*��ZA����*�<���)-[���g���OT9���P���?~��6a��o�Nhh(3gά��B!�5����
�XXX0�|�ϟ��^��_y�+��hee�N=Z}���䄓��F[Æ
qww'88���Z�l	@FF�N�b���4hР��!�_�~RER�H��j�B!�OIN��k׮�v�Z�9BAA�۷��ˋ����	&..��W�bmmͰaØ2e
����0��'1�M�6���h�������_�_����5C�aڴiXZZ���ݻGPP���'33333ڷo�ȑ#5j�ΘʋUW�ơ�6""�U�V���B�z�x�嗙={6�"""�ٳ'͛7W_ߢE���`�ĉ4j��c'���Ο?�q�q��Ԗ��+W�Fbb"YYY������8����cee�ѿ����'###ILL�W�^�7�Z�+�B��M�4�={����p�콍��֔BB!�B�����E�-j:�ǚ���:Ir������2e
�/_V�Ν;�&��VTTČ3HKKS�233			!55���@LM����_~Vܾ}�7�|��/�mYYYl۶���$BBB�;�ٲe���Ν;�9s�3gΐ������ѱ�b���j�Maa!�w��޽{����o�>���u�	ߧO���ؿ?cƌ1:n!D�{��w9t�P�I41�?��ԩS���Sۊ��8�<�ϟ'&&���`5ɮ���ɓ'	dǎ�����憝�ݻw��ЄB�'����-�w�a�ĉDGG�v�Z�ׯ_��	�h8r�H��y!Duqww'<<����q�666annNff&M�6��훘�PRRR-��*G�a���9r���t���i޼9/��"o�����j��Uڗ_~������{�l��c���U�N5jD۶my饗�5k�<�A�i�=Ɔ2d�j�+j{|BT㿥�����s��elmm			�رciT�P���������=۶m���DFFҽ{w������4hu�ݻw9{�,�/�w���-[�p��EZ�l�����-.\`ӦMjߨ�(֭[DZc�8|��Z�zǎ:��o��ġhӦ
QQQ$$$0y�d8�.OHH�s��Z�Uڔ>B�GסC��ڔ����;�פO>����<^|�E�m�Fbb"G���/���g�%33���@����-Ou�gAA|�������`kk��ѣ��󣠠�o_!�{���9s&+W�d�ʕ̚5��K�GNII�<�!y�ڇ��{M�M
#l۶���"��J۷o��j���l�N���ٸq#�Ν������"._���ݻy��x��W�u�V��:m�4n޼Y�1T�����7or��)>���t�BXXXM�e��>�B�Ǐ$������]I��[�n���������z������Ύ:u�Ю];-Z@ll�Q1��Ջ�'������o����OW|�=��Z�����W�\Ndd$���;���$''��3�2$����[��^�z�L���<�<��tF��m�V���j�}_����ҥK����nݺԯ_�=z���ܿ�6

%;;���ǫm&L ;;�����L!�
www>��>��&L�P��!�BPo�����x^�)IQ���~�w���ݻ[[[V�\��O~~>���Νc���4jԈ��X\\\�{�n��X��Mh+**��~�?��#F����///���S�k��I'�)��KOO�G���R�t�...�%�F��…F�P�N�~�i^y�BCC���Q�edd��s�i�F��ʕ+j��ٳ�W����|�駸��Baa�Qq�fH���۫?[YYp��=��ƍ4j�H�J��GQ=�]��…2d�{���ӓ����Lj���gݺu���лwoF��g�}��M�L�Wnn.dԨQ�p����ё�#Gj���?�࣏>�_�~2��r��5�u��B)ժk=�[�&99YM�+o��O�8��!C�1c��1Q�_�p��3gү_?^z�%�-[�U�D�c���KDD={�Ԩ
֢E��� 77W�!B!�B!�xb����kkk>��3�6mJrr2��}M�V+���\�x�������ҥK,,,077�S�N���q��Q�z�):Ć
j:�Z��̌�͛��K/���%%%L�>�?�����B�ZI�SD�0f���Y���{P���۷������ݻ�%K��"�K�/j���ػw/.�瞣����>���Ç�{�n�c3��8fff�Ϻ�Si35�~�P�ʛoQQ����2e
���ܺu�;w�p��9�BRiEEE̘1�͛7s���ܹCff&!!!̞=��}5j��N�� IDAT777._�����e�`���˗/'&&���BnݺEll,�'O֨�dh�S�L\�n'O��Ν;F�ӪU�����9u\iӧO'))���Brrrؽ{7�V�R�r����G~~>}���Z֧O���ٿ�Q�#�B!ģ ;;GGG^~�e._����#Ç���U�le��U���2$��T�4䵺�ꊫO�>�������*CT��FFF2w�\�ΝKddd��'��$==�iӦ�U�mll��� --Mg�>�JNNf�ر<��Ә��Ӿ}{�ϟ_�5�͛7���6l�P�H��W[zz:�?�<
6dĈ���Wv�ի���4i҄�#Gr�ĉ
��011�E��V)�{�.-Z�P�+9.����ݻ���~���(�z�r���ޞ�����K��ƞ�}�C���‚&M����BRRR��K?��V�q,,,��O?e��4k֌�u�bmmͫ�������X�lddd�k׮
�I�}���;�c�s��1i�$Z�l���9-[���ۛ�Q��ۧ����t��󘘘���OW�u�Gcϟs����免�
ffft�ؑ5k�Ty|��;B�V��"j�V�Zp��i������ILL�V�Krr��9U����S�Ni�+�KWY��J\\\f˖-L�4�[�ni|�Yq�Y�f���h-Sڔ>B��/<<�˗/ckkKHHǎ#((Hg"EXXiii��۳m�6�?Ndd$ݻw'))I�JLW��!<<<hР�V�T%9����G�a�ڵ;v���lmm�r��|��Ʈx������ʊ͛73u�T�[o�Edd�F���o�v�HHH��?�p�۴iCTT			L�<�sz50�X%$$йsg�eJ��G!�B��Qjj*]�v�xnoo�P�����?lչ�GEQQW�\!**���ǫS��*��ɓ��{�1o�<֭[�u�M�'U||<ݺu��/���_������,�m����?Oll��봰��x�y�fz��Ů]��v�w����ŋ,_����������b�z�2���oXX����0y�dN�8A~~>
6�T,;v��W^���ܹs��7oM߾}���ʍ��Ύ���o�� 66��~����_�z\���1c�Z��"������k�^�����0�PXX�͛7������;v�1��8���ҷo_�ΝK||<7nܠ����ׯː!C����m�*bjj�̙3��_�`�X{��g�زe�z�+Wؼy3=z�кY��}�ٳ'�<�?��#gϞ���_����f��0t�=bccqpp`�֭deeq��].\���ٳ�d�������!j��5�2t�P~��'�-[��ŋy��g9{�,˖-��;x�`6mڄ��/>>>t�ؑ�7o�֭[qttT�Й��PRR¥K�hݺ���
4�M�6�����ŋ�ҥiiij|���9r$̟?��ÇӱcG~��W@��IY��jH��ԩYYY���k%�(�-u����
!�Tޝgeۓ����___�u�ܟ���Ϗ��~[�\\���j�Z�v�X�h�F�"66V��27n���+[�l��ѣ��Ӈ��\N�>MÆ
��`�?�Z!�[�n���2k�,8�~x3&v'''���8{�,Ǐ�ĉ�<y�����H>��s�~���'������㣾{xx�Q�Őc��᧫2W۶m5�!�U��Ã������≰s�N���k:�Z�����r�С
���_�mU�>�V��t��?��3���$&&�������Tvl

��puuUo�=z4~~~�ܹ��x�x�ܸqWWWrss�3g3g���8u�����������ٳg5n��U�|ٲejEٍ7��?��3ӧO����3f��ӲeK�<y2'O�d���Z7}��7deeѹsg�:ڋ/����?�����׏?�ș3ghݺ�:����L�:����o̝;[[[�����…,Y�D��]�iӦq��!����)�K

��l�q9r����j�q�V�^=����f��<y2Æ
��wߥG�|��w�����O,Y�DM�Q���GE�uǀ�N�8A׮]��/ppp��ԔS�N1g��;�ҥKy���C(cV^�}����6�}�gee1~�x


9r$K�.�cǎ�������_3n�8���hѢ�^����F@@_���MzJ2OUW�3f�9�^����;�����G��3ϐ�����K�.���J�5�B�vR9E�z�mۖ_�oooz���o��&u����M۶mIII��ӓ_|ggg�n�J����3g�ڷI�&����)w5i�$Z�nMFF�'O�W�^L�<�+W�кuk��z�/��m�����___�/pK�'VC��W߾}�?/
�����"�0��֣G�v]��.]���E�l���q�…*���ӓz����=Jqq1�{��n]�<�^�zi<�޽;p�lwU�޹sg���Y�v-�~�-ӦM�_~���^��$�<H���՟����i�9V7n��O�T�Ҧ�B!��رc;vlM�!�c�ر���5F�S�o�-[����#�[���ihD�W�^=�}�Y>��S���z�*111�Ghh(����t p����l�s�O�/�����l,X��U��С��קW�^|�嗼��;���~��
ד���…x�4�67l�������9m۶��̌����}�v�nݪ�N���ĉ5ڕ�e�����燽�=VVV�lٲR����&֬YC�6m033�o߾ꍲǏ�0�1c�дiS���KVV�Ʋ��l���C�&Mpuu�;.ʵ*]�{�U��a��DEEѷo_4h����i��=jTL��cxx8[�l�o߾XXXP�^=^|�E�oc�u=�2�!����cƺ2�oY�֭���<���(�v특�9]�v%**�������>�7Ю*s��U�;���)���:�g�TaƎ�1��_|ANNÇ'""�N�:annN��݉����k���q����)�V���
�������ܾ}�v������…5�p���$$$��7r�����;�g̘A�Ծ���c���deeiL�`�F��_|����~�:͚5㥗^b�ԩꗖp?��nݺDFFr��E�+���WWt�'VC�З��3�W�&>>^-�������Ғ�C��^!ğʾ�)^+z_,�ɮ���(8G�!�6mʘ1cضm����������&�(	��5{���)(( 66Vk�sss&M�DPP���z�>US@��Uy~@�c���*Y��U�
!��P���5�B�޽{��~233133�}���9R��b~~>������q��U���6lS�LQ��/������o�>>��c��}������x��5�ޗޖ�sPP������N�"��o�e�Ν�;w���B���4h3gΤA��Y�~�3V�~�:�ׯ�СC0d��*�!����f��>|X��
<G}�077���z���E�j��ĉu�L ē@�d�M��)S��駟��~�,Y��ONN&L��ݻ8;;kUDW�#����9::�N������ִ^'Nd�…DGG�→7~�5p�@�6cbQ���[Zm�{��ڵk��'�yyy�z�j6o��￯.�Ν;xzzR�~}���RPP��X�=f͚���/hT$6����/����g������?��C����cƺ2�oYJek�k��������8p��{��<ֺ��G�t�ؑ�Ǐ����������{��ѻwo�
��e�8s�(ۙ;w��k�֭�￯��ye�t����$��GBӦM��jEff&����VVV̝;W��)S@�e̅�ƍ��ハ���������Ra��1�UW���Q�>�moذ!�������f^fddp��)�O�n�!��Z�j�O?���ӧ�n�O���kccCzz:111:K�U��'�k�.v��ѣG155U�/�����q���ɓ���{�Ν9q��w��y@�+���*}C�U�f����"''G�XNN��G!��*��(D�swwW���)� ~�����iӦ
�w�&55ooo���ضm��?00P�[�Ν;�9s�3gΐ���~9YTTČ3HKKS�fffBjj*���U��`����<y�+V���@�-���"  ��͛�`���]V�ZEnn��%��Npp�F���,"""�u���$�Q�����e���ddd�m�|�
yyyFŢT���նʌ���ݷo������Ӈ��$���Ϙ1c��/!u�Ã�ϔ��-K�jۡC�o�N�:u4�+r�{�9��ھ};���V�]V�iӆ�r��A"""t^/�?+\T6E�*�
��yqq�_?u�TV�^MHH�FrJ�)}���bee�͛7��ͥq���G�ʞ�oV4l�ЬHl]DZ��/�ߓ������9u���㌥�?h��º������[�zK_�,Mi/��uy���͍%K�Ûo�	�NyUє>�/]�s+{��{��={��^�z�V���t�QIr���@~~>������	KKK���Y�|9�=e��Z�&MbϞ=����I/���������Y��	�d:t(?��˖-c���<�쳜={V�����i�&|}}���cǎܼy���0�n݊���zG���	%%%\�tI����~�iF�ɮ]�())��㩧���t�R5�3g�����Q�ѐ�'L���'		��ۼ���nݚ��"N�8�'�|��SQ�� ��N�:���Ezz�V��\өS���B�'רQ�4ʩ!��wtMʴ����:�+����?���s�����c�u����HKK��ޞо}{����'))���hF��Q����x*�RHyM�F��裏�9s&.dÆ
|�����b�
�����v���V*QJ�ϟ?�#F`bb™3g�>}�Z�R�X+�	K߱�e�֭dddЪU+�,Y���gΜѺ�L_M�6��͛j�>�P���;�			��i.����INO,}�Y��o�ƍDFFҨQ#���k�UL�
��T�P��9p�@��כ6m*79E�M��Ģзoy�t�B߾}IHH >>�������Ljj*/��ݺuS�s\:t�@rr2�Ν�{���w�jTA��T�J��<�c�,X�V��.?��3�AS���cƺ2�oY����&2)��KJ-︌7�%K���_��oRXX�Vi�(9�Xƞ���?�x�Wi��+�;%7��G�$��Zo����ڵ���4�5i҄iӦ�PdO-Z�;C���ڵk��B��yxx��7���/����]a_ooo<HJJ�V"Y����3g���I�&ܸq�ѣGcccc��^^^�ܹ�=�ܿ�X6�.]����fT�f�ĉlݺ�;v�c��m�iӆ��~[}^U�[C�U߾}9t����888h,S.̗7�B!��Ǝ�رck:!�_}�UM�P�)�v��U�sE�
�}�6���\�x�A���ꊫ��F?�lmm����-bԨQ��Ɩ�pa��={��q�|�MΜ9Ä	ʽ۸,OOO�/5>LII	gϞe�޽���|��w@�N�Z��:x� ,P�������?x�w�E�*P�K�ʌ���=�<p�scYm۶��#ē�aÆܺu��7o\m��ٳ���;���F�.]��Fnn.�o��kiii���$%%q��Y�	hUKU�:u*			���п�US�8
=.J�˾}��JN���ٳ'#F� ,,���քm۶�I��>�,cǎ�m۶X[[ӹsg���ڶ�����<ƌuU���5��͛���	��)ɤJ�}����s����ƒ��Ư��J~~>666�Ftc�ј�Q�F���;^�%�<*�SBT��q/�|||�;w.�;w�~�����bcc��ѣ	7(U��g�̙�\���+W2k�,�/P�U#99��;�,,,

��Ņ��z��u�bgg��#.}1��Ғ����ݱ���N�:XYY1h� 6mڤQ�c޼y�lْ:u�PTTdt�?�0@g�U�Vѯ_?�֭K������bÆ
F���;�ȠA�x��155���;;;�z�-�nݪqgNU�oE9V���4h�@�����XZZ2t�Ї�B!�5���GGG���X�b���|��7,^�X�0{�l�իGbb"�~�)nnn���PXX���K�.��UV^���&Y�W~^��GY�f͢C��9s�v���]��(I�k׮��兗�K�,aǎꝻ啵�7��*3V�/_и���p|��5��nƌ����q���Ng�M�#ēH����ѣ�������Ǔ���G}T�4��t8Jr�l޼�?�tIII��'��>����7���z�������B"##���d„	��9.�Ǐ�O{�Ty�ȿ��/nݺ�Q����-]��
6p��Y>��c&O�����FUc�*Oqq1AAA�1�R�2f���U֕���s����5���͍��b�������W^y(��3�Ɯ?J�]bb��u�8q����Q'�SD�gjj�������ar���6m�U&933kkk�v+++�Ν�ܹs+\���NNN�y�EM�ӧO��8k׮��>�7f���\���+z��U�ܝe����l���@�cհaC���	&##CM�����ԩSL�>]J4
!�x��?^+U�t�����oҧO�����XU����Q<�1���E_�΁�)22R��ܫW/ƍWm��srr�W�^<x�����ӧO��g�ƬY��iW��P��G�J٩ V�X�ٳgiժ�}��t�ڵ���ʌ��ڲ�(]��ʗ6�>���V�q���a���p*m��2!���
'N�`�ҥ:T�w<22777�
Fll��>o�<RRR=z4~~~nc��:u���`���,55������iӆ_~����b������
�;s�Lu��K�R�N��!�<xxx�~�zV�X��kט2e��4-��^x��C�����v�*�z��˗Y�r%���̛7�Rۭej�{���|�.��\�T�/mժU��W�������=:t��^�Ժ�kc������ٙ����X�'''�e���c�ʕ���K�۸q�X�h_}���8�0����ј�g�ȑ;v��������o���x�I�!��1`�ٵk�n��޽{����|��G��w�UV~~>ׯ_��/�t��1�XM�4�-Z�����ccc�5��B�8{��w��RPP��ӧ�={v�w��W��b�9PN�<I`` ����cݺu�:u�ڶ�$KNNV�.���'99�u������U����
���ٲe�&M�֭[_��������z�X�~=.\�K�.\�x���@�ץ$K���0{�l����޽[�X��V�Z�ws���;wضm�
R�+3���Y�f���h�CiS��$�9s&�7&!!�W^y���$
9p�ӧOg�ĉԭ[�5��Ѭ_��nݺ�e˖&x���[ԫW���P,X�o��F~~>����jʔ����ʕ+8::>pڔ޽{ӣG�\��Nc� ���L�6
��d�S��q� ((kkk��݋��=�ׯ��ŋܽ{���RSS��?����#׮]��Ϗ�{���5����ݻw���ܺuk�~��o��Fqq1��=^^^Iׯ_�T|w��%33������	��̌��`��5ƌ�1�oyc��[oѨQ#8��ѣIKK���w�qQ���_" 7Q�T`�|E1/���e��-4���Jد̌�jTR�)^��R�bYJ��(�!��0M�L)��b��s�q��:������1�s>�9s<��y�ϻ���B<==9p�VVV�&�2p�@z�!***8|�0����>8�R-9�-9^x�����/�yyyTWWs��	fΜY�*w���m�$�!�w	myDD'N��G��ۛ��\���/�w���<y2�������z��{As�+KKK���HMM������RSS	����� �BEzzz��7L���k��݋��7n�P�d��)#�V����s�V���bŊxyy������wUU���~�Md2d��麦M��$�WVVҿ\\\033S�=������r�'��� IDAT�	�_�ΥK�x���quu%  @髽a�-o�R_�5���>���F�������[��Ç+76�<p�ʕVū՜cu���z
���p���������[e(�����CAAK�,����ɉɓ'�k�84tl;Jә3g�ն�ɑ��hk��������Ғ�����{KKK&N��Z������k�2|�pemI��ǏcccC�v����߿?6l�]�v�Z��=z`mm�O<���~��ѣ	`���@m)���Y�1͉�v:t(�>�(<��C<��cz}Z�@m����ӿN�>͋/����3fffXYY��C�ŋY�r��Uk��R�<���ޘ��ѡC�&-Ԗ0�ѣ���2��[��b�
�����9�7��fff8::���޽{���!))��r��ђcݒ�c��?�	�FC�عs'��C�<��;wҡC4
�{�n�͚5Ky=f�lmm[��ƴ�8����%%%�Ν;�g��N�8p ����$~��O	�Hr�Bq�

b�ҥ8LLLppp����F����Ӻu�F�3fk֬i�0�����W�<�����^��իW�x�bF�a��B�Z���M*5c�ڵ�K�.���K|��F�H������r���IR���.k����IN���j�Ǐ��ѣ	

����ߟ>}�p��q|||x�ǘ<y2[�n��‚W^yE�kgg�����${�u��eee���aeeśo�����2���SVV֤mե=d�ʕ������ÿ��oe��'\���s�n���À8�<.dԨQ�����1���3f���9r[[[�y��D��CǶ��j��E�6nܸ�I�{�ԩS9v�s�ΥgϞ���ѩS'&M��޽{y�t�������ܹsIOOgʔ)t��sss|�A�z�-��ߏ�����;���t��U系!*��Ν;�s�N~���[��}��Ш)Z�}_��B~~>j����z
��̰����ŅE�q��Q�Ĕ�n�%bccyꩧ�����Ԕ?��OMZn��lٲEI�����'���O?��7�dŊlڴ�U񙚚boo���aaa�:u��ӧ�j�u��X7��m�?��3|��7�������)���r���V�k�2{���O�7�8��5jyyy,X�@9^$>>������)!ڂ֍+%DImV!DcT*��Ch�LLLP�Tm�X5��e[~�vh�{��_!��>/^d�ڵ<x���*����%$$�����$::���4~��W���2e
������@'F����!��ϵ�Q7����Z;}��t����L�8���-��/��a����(//�O�>���6���5kHMM��Ã%K�p��
�j5{��333����6mZ�~���ZͲe�pqqQ~m�~jב��Mdd$�~�)���̜9���._��;�CFFfff�?��� ��zCn~_���x�駱��#%%E�f�ٳg�����ɉ��b����@S�!��Ǽ�����F�I�nݔ�=z���JBBs�̡cǎMyKDݜ��Mh2����鉩�)III��eƍ�$�@�y�G}����p���֌1�������]�l�ׯ��M.p���~���x�
ptt$((��_����~��fm��^�?� 33��ׯӿ|||8}�4j����D���Zo]�9V7377G�V�n�:���+***��Lhh({��i����qpp`���̙3��ݻ��o�q0tl����ɓY�f
�������l?33&M���#+Ľ��Ņ���&����Z��q��5�ֹs�f�lfee�OMMM�ci����r���c޼y�n�9�K]:t`��,X���˶d�-=F}�����?o�:}}}���Zs��1�,В�����)�m�{ܜ�c0h� �n���m7�X]�~��w�������6�8��ڒ@ڲ��3�[qN
a,��"n��cǒ��d�0�wm-G!�B�UTT0�|Ν;���8qBIL�������
����bbb((( **J'Y��~��7֮]Ԗ�hHyy9���Snh�?���xrrr������
���R����x��ԩS�\���ׯ�;�{gF�a���ӮQQQ���)}�]�F~~>���TTT0{��f�w]������)���O�w�}���e���>��ɉ��d�=�z�*�}�&&&����
�d�}�ر#�f�"&&�/��R��|FFP[*r����ٜs���|Ϟ=TVV�����FNN{��eƌ
�h��ݿ����{xx�����zmmmY�t)K�.m�������՜��~�`)����/��/ip[�m�cǎ����ws����j�oS���e���	�+`�oKXh�q0tl�����5*����h����Q.���9v��-һn
!��u�N�>])�(��?HY!�B!�B4�F��ܹs8::��ÇQ��:#Phm۶���B�B||<G�!))��Ç���Cjj*�{�277��̺� &M�Į]����лY{���8���prrR⍎���ёS�N�y�f��-[�x�"�
"%%����}�Ybbb�?22�FC߾}Y�n�r#S��n�:>LFF�r711��*r��}����śo����*((`���:t����v$������'�����_m"IC1��̞=+++���7n\��@Sϡ��,��?�6m!Ľ��Ϗ=z��h�6�F���>>>F�L!������o�>}�u��(%r��9E�Vl��`B���J��!H!�B�Y�%@�ܞ�����

e�С�1��˗��K/��OKK <<\)yѷo_��˜>}:�w�nU��'N��~��h�wذa�����/�o�>���P[B;�_hh(����I||<����_�[[[e������h4����0a^^^xyy�x�����)iӜ��
���@���6m�?��!!!�����Z�Vs���&�v�ҩS'�������СC���QVVF^^�RF�>�9��z�O�<	��c]}����#���YZZ��/��ӟ���ڵk���0rtB!Ľ�K�.�k�J��?l�h�� �)⎐�gB���OIl�ڵ3vB�VR�T�A!��̙3z?&J08{�,@��8N�:����Y����#G��������\�Ro�Gqq1P��Q�6���YiӾ0`@�b��������~��x@��d��x�
������f�ƍ̝;�JU�
�放�&Qh5g?���g������kKK��h����Cbb"������q��!�_���ѣ15��'��CM=楥�@m鏛i۴}���Gy���@V�^
��ŋL�B!D��ٓ��R�M�ƦM����$9E!��ƎKRR���B�ڧ��^ssR�vĔ��%n~�P"nc+���75D���L�8�~�����Ittt�G$�q�^[s��U*)))\�z�M�6��swwgԨQ8p��;w���dž
ضm�/fƌ����ꎚ�C��աC��&&-���ҥKf̘A||<dff�%}Ҝs���\�>�Om�$�qQ�T��.�B�Fڤs!��e�4!�B!��ճgO���t�o�ppp`׮]�������iU,666\�r��>�R0ǎ�i�Nkc�޽;��]�.]�…��Ƞ��Pg���-DGG���W�\�Ib�U����[}�˜9s077'11�C�abb˜1c\Wsϡ��]�,U�m�B!�B!D���)��k��z�-ۘ���V8y�d���6$))���lF��̙3oUhB�[���U�"!�e*�
�Fc�0�¨&M��?���U�x뭷x����X�j�^���͛7JPP�����g۶mlݺWWWeH�v��QSS�ٳg��ƍ�;w���{�����w„	l޼���p�z�-
Daa�oݑ;ƌCBB�W�&<<�Ν;�v�Z����ٳ'��׿��?{�lv��ͩS�ظq#�֭`ڴi�ԩS�߿??��fff
�_K4g?o��ޗx�iӦ���SSSða��ܹ�2��9Мs���|���?�3g��%�h�V��B!�B!tIr�F�ꫯ�����Ę�G�Ebb"555̚5�~�#B�J�
I.�h�$�L!j͞=�/���������s��?�����<^y�e��Ύ��R<==qpp`׮]:��{��̌���zc���c߾}�={��s����ի�N�_��W���8~�8O?��N�\���			a޼y>|���<�
������DDD��̈#ꍷ�����Rs�___�����C�@sΡ��1cƐ��NAA��{QPP`06!�B!�B��$��6�V�jb��Q�����e���X�b^^^��ƞ��,_����d,--oU�B!�B��TCߣ,--Q��DEE���Ayy9}����LJ�+Wbnn��!&&��>�����s�����1b���O�l�2֯_��穮�n0>SSS���x衇�eȐ!���ر#���|�8p�K�.ѵkW�x�	,X����ҷk׮�����Ç�z�*�����ߟ'�x��m:�g�}���6n�ȦM������Ԕ��$����ڒH�ƍ��ϯ��k�����Ҕ����Zy=~�x�y�΁�CM=�'Of͚5dff���Cff&666L�4��D�_�mYrr2*���a��ٳٱc���B!�=L�SD�К�=����X.\��s�=��=���l߾�����B!�B�[�K�.�\�R����{{{�v[[[�.]�ҥK\���;���z���h��N�

"((���	o�6BBB		�i����ã�m6g����o�io�w���<z��M߾}u��w4���skkkT*������@qq1ǎcѢEXYY5u�D#z�ꅷ����B�y{{��c�;��k�Bܛ���-�+ĝ$�)�ͻ9q�ƍ��j���KII	fff8;;3m�4�O�~K����Mdd$�~�)���̜9���._��;�CFFfff�?��� �/��YYYDDD������9cǎ套^R~��;����5vvv���`bb��?{�,���899�s�N���HHH`�ȑt��M�ףG\]]IHH`Μ9t�رU�Bq9y�$P���4h����n���IIIdgg0j�(y�S!�h��㩬�$88wwwlll8s���?���#mQee%UUU|��̙3Ǩ���g���h�d�F����^� �:cǎe�ر�C!D=�����B!���"�:QQQ���)�׮]#??���|***�={v������L��G899���Laa!W�^��>��Ą�_]g�w�yG��~��Uv��ͱc�ضm[��(Ϛ5������K���222��u�g�*++qss�[���999�ݻ�3f��!�'���*�����UG�%**���Djjj�5k...>�ء	!�m�ԩS��㏉�� ""Bg���.4Rd�-�[���Ņg�yƈ�Ԗ�
��_VeRSSY�v-F��^K~�B��M�R��h��׮];c� ��6�h4�u�:ѶHr���h�F֭[���+׮]c���DDD���h�ǎ�#�����؂��o�N�޽���cӦMDDD����'�|B�=زej�ZI����]���#G��w߱|�r~��g�m�F`` ���zO�_�|���6o�l09eܸq@�,�ۮ�-++K�S�M���n������+V��元����,_����d,--��B�6ѫW/>��sN�>Muu5ݻwg���̟?_g�G!��u���˗quu%44����;$y�Y�z5�/fĈF���%O�!ڲ�=�n���r�R!�12B�hk$9EE}�"7�J�������FCQQ&L���//�[_pp0���j��7m����BBB�ݻ7P;��Z������׎l2t�PBCCY�x1���'00��6;uꄗ�qqq:t777���������Z�q��ɓJu���G����c�R9����X.\��s�=��=���l߾����z��B!�����J%70D��޽��!$�����m���^;v�0vF���-�i!�B�V��"�:K�,�7� ;;���l6n��ܹsQ�T���ܛ�P^[YY)������
=M?j�(�imi�s��5�]�����͍C�q��uF���i����R:v쨷��M�Gq�x�"k׮��TUU��쌯�/!!!�������h�����_���gʔ)̟?sss@7)���17n�@�V�w�^JJJ033��ٙiӦ1}�t��M��nLj��e˖���¦M���ҥK�_����t����8q�r|�*++#!!��#G�<�ݣG\]]IHH`Μ9��B!�B!�B!���$9E��7>�sC��ݝQ�Fq�v��I^^6l`۶m,^������С��v�&-�M$Ѻq�F���ҥ3f� >>���233�����4�.m����TQQ����u�N�8a0񢺺���
����bbb((( **��״����"..N��v�������SQQ��ے�"##)++k�D@YYs�Υ��Xi��/�����g�*++����rss#''��{�J�4!�B!D��<yR���������jr�!ׅ����5ߘۖ�!�mɭ�+%�bkk������������Ǖ+W���4vh?~\g��ѣ���O��Ι3sss9t�&&&�3F�ߵkW�儴m�>B�{�F��ܹs8::��ÇQ��6�m�Faa!C�!>>�#G�����������!55�M
���mU9���֭[��Ç��� 88����f�VW߾}�����7�l0��[�R\\LϞ=ٲe�r����{��YYY8Po��M�G!�B!���W_U�ov��Q���x��X�l�֭�رcw8B!��JC�|cn[>o�B�52r���L�6���b����:u*���租~�������z��y뭷x����'<<�ɓ'+}ڵkGMM
gϞ�W�^J�<��i��㏩��aذat��Y�?`�Ο?ϙ3g�PΜ9��B���i�=77�����СC1b˗/祗^�韖�@xx8���@m�GXXӧOg���z�vZ��ʊ��r4
EEEL�0///���Z����N���8p����������_��{��Iz��>}���B!�5���m�����d����������
�WUU�b�
���ppp��ӓ�˗����`i!�mS}�|cn[>o�B�E��"�:~~~���ADD�μ#F\����Z�)��.]�����6h� f͚�L���QZZ���'�ڵK����Krr2�[�`̘1���SPP����B��	h?��N��k�ٳg���0��S�N5�����s��u�]�f���իW�~ZK�,�7� ;;���l6n��ܹsQ�TXXX�*6m�Hc�%���;Z73���R:v�7Oۦ�#�B�kv���;��B�hN��Ull,.\��Sڞ�y�o�Nll,���F�N!v?\���y#��-���&4�YOOOLMMIJJ�����={2n�8���nW���믿Nvv6]�tᩧ�b���:O�/[�����s��y���u����V^�?^g��ɓY�f
�������������ƆI�&݆�B�7_���%���Fg�]�v���Yyyy��;u�Dii).\���Io~II��O��ݝQ�Fq�v��I^^6l`۶m,^��3f�8����Rw�7o��T�O�q31ѯr�m3tl�B��]c��Bq��x�"k׮��TUU��쌯�/!!!����J���IKK��_��ޞ)S���S�!�������HHH`�ȑ:�Y{�聫�+			̙3�`�B��~��6l�@VV������___�N��ӯ���Z;}��t����L�8��bcc���^�������t�Ё'�|�%K�(��ܸq�Z�޽{)))���ggg�M����[�5_�Z�V�l�2\\\شiS���jol���F!��F�SD�g����G�O�7�lK�7��S�N�Y���m������np^^^P[j�o߾:󬭭Q�TDGGS\\��4...��� IDATرc,Z�++��-��;��ٓ~����<}�Q�]{ͨ���3gΰk�.e����۷/�������(%�����nkk�\��ꫯزe���JrJkckHϞ=)**�o����Mi׎,UW׮]9�<�/_�+�v��e��Bq��9s��C�3v�X�R��m���`����(�'N�PSꪮ�&  ���B�������


���2����g�*++u��h�������޽{��NB!jG������ŋJ۩S�X�r%ׯ_�g�jv�7o��@+���牏�'''������-Z��t��U>��nܸAhh(QQQ���)��]�F~~>���TTT0{��F㏌����L'I�V�!�y#�����ے⎫���ҥK|��̙3�`????z��F�Q�4
���ܑX�w�vT�U�VQPP��A~~>�V����ʉ'�~�:�.]����Օ����vtm�����غu+���+ׯ_�…l߾��>����zJYfڴi������SYYI���qqq�)
ԜؚKOxx8�|�
���~�-o���^��-�T��M�G!���$''+eD��_rr2G�1v���s�����HLL�F�V���m�6
2d���9r���$�NNN������L����tVV�[��M�G!D�-[�p��E
DJJ
<�����(����(**���I��GGG���ȩS�ؼy�޺{��MJJ
YYY̝;��Y)))�[��Ç���App0���@��|��}����śo�y�[>o�B�md�!ڐ�%|\\\��~���$,,��_~YI`IMMe�ڵXXXܑX�w��ٳ��/���
�fR���?���zIk���+ʴ�����xzz���]��>}:���';;������_oO?���u��Ϗ��p"""�����;bĈ��\>>>|��W�<y��*�'O�KB3f������ieܸq-�E!�h�4
*���aq_h�S����jo�ȸ͡�	�СC���/˗/��&--
�M�wttjo:���1}�tv�ޭ�y0��ɓ@��Л���G��B�m�:}��A^{�5z���^����h��6���^|�E���G``��2AAA�:gϞMLLW�\Q�[YYQ^^�F�����	&��兗�W����ir�꺚�߆��B��JFN�
�֭:t`̘1�Y��������G!00�իW�z�j/^�wsUq�1􄅖��%j�:w�)...ʓu������J�������ckk˄	ؼy�Έ ˖-��ɉ���S]]
@���y������ưað�����[[[��܈��$,,Lu��ӓ�+W��bnn���9�������o�(��277G�V��兝����L�4���ɓ'ceeEff�޼��Llll�d�B!��&m��?��n�7�h����*��	)�N�jp[���t��Qo��M�G!D���h|t���b�6!�.�]�������׶��ܸqCi[�d	:t ;;���{�Y�f�իW��6����߆��B��JFN�jm���ݻ��_�R�ӎB�g�t��ʕ+u�JJJ����i���e�ҥ,]���u�������޾}{����nr|xxx4گ��5t]�o���5����0������F�RMqq1NNN@�ǎcѢEz���B!�����k�Ŀ�O�ק��Fg�n"~}}nV^^��|�:ML�ԶڮBK[�N���X7��fu�Pڎ��;�F���ܹ���<6l��m�X�x13f�ht����RSS�lS��X]��o��B�V��)B!�]b��񸺺���s��nܸ��ӧ�QIn~�O4��Ϗ=z��h�6�F����^�!!�B���׎N`
�S�߸q�7o�����Ԕmh�$%%�j=��1�㤤$%q��c#�M={� //O���iv�ڥ�zY�_NNN���ڵ+�/_֛�m�BQ�{��@�Si˭;vL�];���7���-DGG���W�\!22�E��&�TTT(m�����m�|�!�h�$9E!��KL�:���&N�ȣ�>���7�����ٱp�B#Gx����$,,���TJJJ())!55���0,,,��Bq�y��W�={���P4'���*���X�dI�7��-**�.;�6��ѣDEE��k��l�2֭[�wSK�۴�<W�ZEAA������Z�J���?@hh('N���\�t���WWW��ڛ��R@����RBui�ZS�T!�Ecƌ`��՜?��W�������ʳ�>��0a���?~�?����Ǐ+��q��5{�ӦMS����������G]�{ͯ���;v젪����""""Z���y#��n"e}�B��DPP�z����?����TWWӽ{wF�����֭��C�+=��#�z�j/^l���B!n���tc����x�C������o�Ejj*~�!�>���E*++y��w���WUUU�X�///�ijOOO�/_Nrr2���F�P�	�g��/�����߿�����8p��Ǐ덴haa�+���L���QZZ���'�ڵ�1cƐ��NAA��w����e7O��^�׿����4�?��O?�3o���k???����ٳg�;w�N�^�z�5������DDD�%�Խ����g„	����f�֬Y����^���|�!���Hr��#fΜi��mXrr2*���a�y&&&�T*9V��W!�B��Ċ6Cԯ]�vt�҅�^z���T���[c�Ԡ�#Gr���߯�q?����…<��sJ���?��ۉ��%00Ј�ݟ�q����D�VEFF������V�\�������Ɔ��>��#���υ���fĈЯ_?��e�X�~=�ϟ����ɓ'�f�233�Չ#33e$!�h��q��ڵ+���DEEq��a�^�J�~���'�P�u�ؑ��X>��8��K��ڵ+O<�,��ֶ������Ԕ��$�����rp�ƍ���O�g�_�W^y��Ҩ����Օ+V0eʔ�|�!���Hr���z�ꅷ����B�q���<��c�C!�B4�ŋY�v-���
ggg|}}			to^TVVMZZ���+���L�2����+7~��0u_���W_}Err2'N���ի���3a�����ƍ��j���KII	fff8;;3m�4�O���xLLj�'���4gYYj��}��q��%���8q".�[��_~aÆ
deeQ^^N�>}�U�>�g͚5������%K�����������=��r\�o�on�Ngggɧ�~���)3g�$  �˗/��;�����Ǐ'((kkk��VVV�j�*��ӱ��`�����t��U�_c�Tݸ�j5˖-��ŅM�6QVVFBB#G����G���������9s�رc��X��t��ʕ+u�JJJ����i���e�ҥ,]���u�������fmm�J�"::���b���(..�رc,Z�����Bq�rtt$<<��~�:u"((������7��v<<<\��k~}۰��$88����F�7e���F!��D�S�m5v�XƎk�0�B!�B�B̟?�s��)m'N�PSꪮ�&  ���B�������


���R�:Zk�ƍDGG봝?����\�›o�	@TTqqqJ�k׮���O~~>̞=�����X�v-ӦMk�oyy9���S����ONN111�
���R����x��ԩS�\���ׯ��3���{gF�a��,\�Pg^�^��?>6l **��8�����L��G899�����W�^��>��Ą�_]g���P233���;v��_��h�����S������)�({�졲���0�nnn���w�^f̘q��h�ƏOee%������cccÙ3gx�wx��o�������h4�=�F����^� !�����F!D[$�)ⶊ��oяzB���J�B��;!�B���s��������wH~~>˗/�…:}�m�Faa!C�!$$gggΜ9Cxx8999���2}�trss[]Jh�����3�Ю];���Y�h���(��֭��Օk׮�{�n"""HLLd���M����*Zz� 7������'''�z�-Haa!+V��ԩSl޼Y))�e�.^�ȠA�������=���׿���1��I||<}��eݺu������/���?f�ԩ2���������۷ӻwo���شi�����'�УG�lقZ�&##Co��'O�q�F��w�}NJ+(..f�֭���@�ϩ����KLL�2�JVVԋAۖ��%�)m���k�Bnn.S�N��?&""�����vvv��n.KKK���x�嗙3g����]��[�-!��Sn�uZ��|�!�h�$9E�III�Aц�OIl3g�4vB�VHNNF�R;!��-껩ps{nn.���jG�:t(#F�`�����K:��������Mc����޽[/���222��������?���믿jG+Ѳ������FCQQ&L���//�V�p��	��߯7�z]��߰a�		��_d߾}Jr��x���ի��\hh��ukSlmmY�~=��������|�r�͛���w4
�۷o�N�L������M�6����z��
��9sP��\�|Yo���PF�	�СC	

%00����+�)-9�|||t��<y@���>}������� z������ӧ����{��=�����}�Uy�Y�z5�/fĈ�|;B!�o�y#�����qGx{{;!D�c�c�p���K��B����y�nj�Bݙ3g�r�~�>{�,P;��!�N��eq]�x�W^y��No^MM��zɒ%���dgg����ƍ�;w.*��YO��}�����#G��������\�Ro�Kqq1P��R��x����J�����S||<eee���o<���:t(3f���?f�֭���7i
�g�[����ז���.s2���-!ՒsJ�p�UZZ
@ǎ��j۴}����'�MLLP�Tw<��B��EF8i���F!D["�)B!�0v�XƎk�0�B!�u�M���ة��Ю]�F�ܬ�&������w�ѳgO���?������F�swwgԨQ8p��;w���dž
ضm�/nQ)kkk&N�H�~����$::��#�ܸqC���1m�J�"%%��W��i�&"##���#==�?��'�|��~555J,�����С��v�&D������.-9�ꎚRw;��Ҷ5��!�B!��~��"ڼ��o���$���5j���B�H||�}U�H�{�J�B��;!�0��={��?���ǣ�>������upp�̙3�ڵ�����[LLvvv)��LMk
������
�ꫯزe���-JNѲ���ʕ+��qtt���رc:#r;v@�8u�ޝ�~��S�N1hРF��t�R���Y�v-6����5���AAA�����o׮555TTT(�v+G��ٷ�~�3"�����֭8��v����|�2]�vՙ�-7ts�B!�B!ZN�S�h�ѣG���"11���f͚���Ç7vhB��TRR��CB��$�	!D�I�&��?�j�*�z�-|�A���;V�Z����g��̈́��D�������ٶm[�n��ՕM�6�M�8{�,�z�jq|���'�����7�|Si�r�
]�taڴi�ԩS�߿??��fffJ���s��
Ν;�{�����;a�6o�Lxx8o���
���P9~�ƍS��3���V�^Mxx8�;wf�ڵ$%%ѳgO��������޽�S�N�q�F֭[�`�'Nd���ddd�ͳ������;v0c�JJJ���hp}���[o��o2`��?��o�
�3�KsΩ�0����s���$m٪��RB!�B!D�$9E�zTUU�b�
����'�<==Y�|9���
��B��x{{;!D+�ر��!!D�0{�l���~��G�������ρ8~�8>>>:�,,,x�W�im"���'�ڵK��vd͛iGڜ0a�w�f�ʕ�\�R�߉'pss��Ϗ��p"""�-F���x���48��Ϗ}��q��Y�Ν�3�W�^:m��_IKK���<���:},X`p��۷'$$�y��q��a���6lX�����Kee�N��	HIIa͚5�Y�77����
�;��� ڜs�>cƌ!==���������M�Frr��CB�z%''�׿�$''�$�
!�B�j��"�c��1$66�.��s�)m�?�<۷o'66���B!��n��3KKK�j5QQQdddP^^N߾}���a�ʕ���+}mll���ᣏ>b���\�pkkkF�A@@���S�.[�����s��y�����k����Aff&ׯ_������p��i�j5��������鉩�)IIIJٟ�={2n�8���Z���)vvv<��C���2dȐz�v�ؑ��X>��8��K��ڵ+O<�,���V�۵kWbcc�������\�z�~������O<Q�6�ʳ�>KJJ
7nlt$�nݺ�x�b��贿��+������FUU����X��)S�4���
		�������cccäI��C�J��S��<y2k֬!33___�y���ʶŭ%�����ڱc�<�!�B��J�S�]i͚5������%K���$::���4~��W���2e
�����ܜ��2�~�i���HII���DY�ٳg�����ɉ�;wRVVFBB#G��[�nJ�=z���JBBs�̡cǎw|߅���$�z����{{{F����?����l{��ɓ'�>�zRR����5J~LB!��ҥ���$%%%������ڲt�R�.]��:���qww�ko��#;v$<<�༅�L{xx���q[�i��N�

"((����ݯ��BHHH�}�5k�f��i���$88�����Wߺ��^wZ[ʧ!M=��۾��5*����h���qrr����cǎ�h�"����C4�J�B�R;!�����1vB!��Hr����{h4���X]]M@@���J���bbb((( **��;2k�,bbb���/u~`���?~<{�졲���P�nnn���w�^f̘q;wU!n���j~��gRRR��/���b�С��W_}���t���u��Q���HLL����Y�f������Í�B�V�?���J���qww��Ɔ3g���;����9B!����g�}�F�Q��4
z�D�<x��k�;!�h�رcy饗��'�!Ľ륗^b�ر�CL�"D��F��o߾�[�Ny�i۶m2d����9r�III>���RSS�ں�VVVl޼Yg���m=鬬,���M�G!����V'khב��KVV۶mcԨQTVV�����[���JOO7�v����X�b^^^888��舧�'˗/�9FB!�j�ԩDDD0q�D}�Q���������No�!�"KKK���HMM������RSS	�������SΞ=Krr���B�%''s��c�a���r�B�{Prr2gϞ5vB(d�a��Kj�{S422���xlmmY�~�N
4��Õ�}��%,,��ӧ�{�n�O�N�N����"..�C����FYYyyyJ}j�-%лwo�����G!n�;YJ�C�<����{�������]�v��2@ll,.\��Sڞ�y�o�Nll,���F�N!�0��� z������ӧ����{��=�����G�-{�Gd���,^�X�m@�zIII�A!�5{�lc�`T�FJ�	!�=�]�v�A��"���������o��(�Y��?u����LJ��Dbccqss�СC\�~�ѣGcjZ�_�����W~3m���B�)7'�ܸq�Z�޽{)))���ggg�M����ӛ�^333���			!##CIN�y{�i�ZͲe�pqqaӦMTVVMZZ���+���L�2����cnn���_~��
6���Eyy9}����Wy�n���1����V�ٷo�.]��ޞ�'��1E IDATp�Blll������s簳�#%%��w��Y<==qrrb�Ν�������ȑ#un����WWW�3g���!��~abb�J��� �B!�Bq�Ir�0��Gh�H*�����^�ʦM����T����4����r�u�.]�1c������	����7����K-m�d
!�-**���8e�ڵk��瓟�OEEE���>|8��}�}###)++S7���	���P�SRRBLLDEE)����R����x��ԩS�\���ׯ��3�Ի���r�͛GQQ��v��y������!&&F)�vs�cǎe̘1�����_����іv?~<{�졲�777�������a�޽̘1��c%�B!�B!�B!@�λm�ҥK���:7Aصk���z�rrrt�5g����ILL�СC���0f�e~׮]�|��^�6m!�0���֭[��Ç��� 88����݇UU��b"Hy��~�9�x�ƌ�d�EM�Ԍ� �mE��9�d\�QSD����
0e+7�SzbR��d�k��A�<��ɐ:!
�����׸ـ��.�k��z���k����>����Fm�G�|�����uww'77�7�|���
y�Gزe�ӟHOOg�ȑ:t�;v�~��ǜ;w��~��۷��~~�����X*Z�q�M�6QTTD�~�HJJ��$&&ҷo_N�>�ƍ��u֬Yt���&�R�b)R���`ذa6۳�YbDDDDDDjS�t���鄅����DD�H}���H�Rq��+�f�b��lذ�h�g�����ɓ����?����x{{�p�B��<��L�4��?���/���x�X>t�P���mr��YbDD�������v��b6�IOO������>|ت �!~��cz��̞=�j��={����';v��ݝ��(233����k�1`��v�Jdd$���}��ݷop��1b���<��DDD��_ԛ��O`` ��_���/���;vggg����}11p�@��
4�*FDDDDD��W_}�Α,�9B\\���K�.e�ڵ=z��3��"""�O�)Үt�ؑ��:t��9v�s��eРA?~�ٳg��O0a�6o�L�.]X�d�Ͷ�̙cLt�>�1�JAA��z���눈��ŋs�}�����|����IJJ�ʕ+�ޖe���ݻ�6�R�aq������
j&O�ܜ����o��V�WRR���>j��c�Ym��\gϞ�}��Grr2_~�%?��O>��Q�s���u�f�=K�%FDD���5k:tЏ~��
?[�l��%/�,;;����*V�XA`` nnn��ۗ���/_NUUU+g)"roS_-""�n�x�H+�u
��1b?���پ};6l >>����裏طoeee�S�.4F[��������Z6a�V�^MNNs�̱Z�������Ǐo�Q��ت�YFIiH������ѣ�����O?�رc�_����BCC�2eJ���������6��QS�Я.�.]2^w�С�95ԍ7�\V3�=z0e��l�BAA999�u��%G�^K[K���HkѰ�"�o���N�]h��(99���2f̘a�͜9��[����LHH���������"""-I�)����nDD�1������1dCXF]8p ���V˜��1�L$&&RRRB�~���O�=z��i��ؓ��+������SXX�޽{��㏉��mpqʵk׌�9}}}��������ܹ77�zcz�!����q��i~��F�o߾���G��'�0�-ê�n�AAAl۶���4���K��z��Iii)�������j���r#FDDDDDڿ7n�����ݻ9{�,���xxx0i�$c4H���Jٳg�}��z���g���Fa|��Z��w[���2j�(z��m����oooRSS	

�uG�{ݹs�X�f
���
�̙c�#����j��K�)rϩ������?��y��6���|��g��f���0�͸��1{��V�WD�.�&M����e˖��/0d��������x������_�a����k���DŽ	��3�<�ƍ���$<<�!C��ߓ����͛�&>>�9mZjj*�V�"::�x�5k֐��N������������3g�O�����q�F��������?Laa!������|�A&M�Ķmۨ����G�0�:���R���m�P������jڴi�NA�c2�0��NCjǦM���׮]#??���|._�̬Y��z�*.���Ј={�,IIIW���v���e>>>:t�ݻw7jL�{��˗�?>�|��v��I��WA}���H[�����:����''N�5��ɉ��(-Zd��ر�5k�ХK�V�UD�>���DGGCLL��2//�Z׹�ɐ[������6�����s璕�����m���t�’%K�����/سgǏ�g?��U�K/�d��޽;.\   777v��Ipp0_|�gΜa޼yV�0���>s��!##�-j3f���؜ǂ��Z�io�f3&���i��,�
�6m߾��k����͵k����$&&���4��/%%���By�"""��𠸸���h:Ď;�<y2��uڋ��\�
f���-77W7<EDj0��|��7��ۗ��z�aÆ�������)++��U_-""Ҷ�8E�9�{����ooo"##�رc���?�8!!!�Z�
����:o����	���7  �N�:���NQQ���gܸq�v�Ν;���ƓO>IPP=�P�rvqq!))��>��}��QVV���3^^^,\�����={�$99���8<ȕ+W<x0s����?���t�R֭[Gii)W�^�[�n$''�_��_deeq��yz��ɏ�c^z�%\]]������֢E�	&�z�jrrr�3g�ղ��\\\?~|�Α�����ت�x�f{c>'5V׮]�t�f����"|}}	$00�*nϞ=DGGӷo_��݉��b���dff�Lt�S�N7���iРAV1""mE[���@dd$#F�n>��|�r^y��X��"""m��S䞓��٨x�ɤ'
E�M�탾��?���MZ���Է
WWW�����v���Kttt�1~~~���ٴ������ӭ��v�{��1��
���V˜��1�L$&&RRRB�~�())��ѣ,X���]�ֻ}i/^�o�A^^yyylذ�y��a2��F�=s�@���N�>]�~.\��,����f���L���c�Y����j��M�)"""rϨ������?��������`>��3�f�Qc6�qss���HDD�^T�0�]�vZ�	��:u��C�6y���t���=z4ӦM�S���uj^���[���ϏѣG���ŧ�~ʱc�X�~=)))���S7TWW׻�K�.ջ�C�888�,��YbDDڊ��O[��k�3�W����m*N�{ƭS�xzz2q��Z㜜����bѢEFˎ;X�f��ӓ"""rwy��W���n�
�#G�GZZ���L�>OOOF�y�3�;����������{����k����Q\\�Ν;qssk�>z��Iii)�������jYyy�#""������p��1��?��h���{+��"""m�m������]�w���w�}�3�իWӱc�:c�qBBBX�j�V�"44��!cEDD�E�n���m�c���M^����+V���}��%  ��˗SUUu��;iҤIx{{�m�6*++2d���8::q�<�����<y�~��������ooo.\h�Z���L/#2Y������9�6��ܭƏ�;�CAAׯ_'??�w�y�&V}���Hۦ�S�Uddd�;i�222�:u��Ӑ{@fff��M&&����i��9l{{���LYY3f�0�fΜ�֭[INN&$$ĎىH]������&&&����e��ϝ;���,�?n3�g�.]X�d��{��\�p������عs'cƌ!;;��������ƍw�OD�ݛ5k��9����ܹs�U_-""Ҷ�8EZ����{�,\�q�			�޽��g���與��&Mb���wd_yyy�������t�ԉiӦ�p�B���y��wٿ?���<��S������l�~nn.111�ٳ�Ν;3v�X^y�z��ew�kggg�w����qp���gΜ!  �~���駟RQQAjj*�F��w��F\�>}�&55��� �u�֬s!r��G1\@@�:u"==���"���ƍ#88؈sqq!))��>��}��QVV���3^^^,\�����K�.eݺu���r��U&L���ի���aΜ9V9������b� "�V٣�vrr"!!���8���ϥK�pwwg��٬\��Ν;��EDD�6�H���""""""w���86m�d��v�������s��ef͚��}���{l߾�x��Gѯ_?222(,,�ʕ+|��g888��[����s�N#.33��G�������k���>}:III������h߿?O=��v���m���p��!v��͔)S�qD���������8WWW����7���Ϫπ��n&����DJJJ�ׯ%%%=z�еkצ���]�G��\�Ҫ��ٳF����j��K�)Ң8��5k읆���'WEDDD�����]�ooo�]�Fff&111����Z�r�H%5�TnAA[�ne�lڴ���xbbb����w��}����?&!!�(�����Q�8q�˗/��o�%%%���>l3"Lyy9���lܸ���˰�6�f�����\���ゃ����0�̈́��`6�qss��~BDDnzꩧ���dٲe������Bqq1�.�=��ݟ�j����iQgΜ!##��S��;i�222ptt�w�"##��)�H3�����U,R���‘�]�r��%�f3EEE���H``��oٲe2�9Jg||<���?���`����@yyy��[F61b�������o�>BBBj���O`` �6m��/���LJ��
�;fp��)#�[
4�*FD��b��h��)������bѢE�c�֬YC�.]Z5�;�%��^x�m۶CLL����ݻ���/��}��i9*N�V���n�D�
�ü�ӦM�w
""""w��ŋy�7���#//�
60o�<L&S�_�7���СC�׷����a�vrr�s�ѣG[�9r$�|�M���={6iii$''���×_~�?���O>I�N7�V�p�ݺu�Y��f��{��?NHH�V� 44�(t[���0�?����/W�^塇��'�d��������S}���H�Pq���H+0�L�L&{�!"""R���"5�������G�&++�O?��cǎ�~�zRRR

�#���w�}��;884h}K!�ō7�~�=�2e
[�l�������_S�t�С�mY�,1"�x�=�IK��C�۴d?���`�~S}���ȝ���Vp�֬Yc�4D�;v,����is\]]���ߟ��B�����Lll�)Ni��Ǐ[
9��������m�6�����/qpp`̘1��={RZZJyy9={��Z�2�P�v�{I�/�G�7'xzz:aaa���i�"��3gΐ��a�4D��222�ӟ�d�4DDڜI�&���Ͷmۨ��dȐ!xzz���h��nz��)((��9r���h&L�`�XF79s�պ>� �&M���?��ŋ��G?�0�[�*..�ٯ���i�DDDDDDDD�59E����*��ٵIx�����HKK�����ӧ���i�Y."R���o�fͲw
""mRpp0������c���˫�unŤ6wzx�=z0w�\���~��ӧ�w�΅��͍�;w��̙c�:���1c��Φ����x

j]GDDDDDDD�^���:dgg��^UUŊ+���
����/_NFFNNN��������H�hLqH@@�:u"==���"���ϸq�n�%66��_���<z��O~��ϟO�Ν���K��n�:JKK�z�������맞z�jل	X�z5999̙3�jYNN...�?��J�}��N$"�V�L&{�`7�f��"""ҢT�"m�剹;�d\KHNN����3fm3g�d�֭$''b��DDDDDDZ^m�����oҺM�ol������ի�ݗ��~~~�.;v�����j���3&����DJJJ�ׯ%%%=z�еk�z�-r7;v�F��va���N�.�G��ܽ�x�	{� bPq��y�•��Tbcc9~�8��w�=��/��������D����w�}G�^�x��筞����d׮]��曼��ƺ��9˗/������>LEE����5�޽{1}���ۛ��T����֭[���75���v��ߺݚ��S�������0z�h�M�֬퉈������J������

�5.88��>���Lxx8f�777fϞ�j����������E*N�vc�����p��~���q��
"##�z�*.����X��ٳ$%%QPP@\\,[��#G���{����E�>}(--%&&�޽{aU�r�]�vQYY�����2:��ݻ�2eJ����ȑ#��ő��Fuu5ӧO��ӓ�#G�;5�z�:����''N�5��ɉ��(-Zd��ر�5k�ХK�V�U��:p���v�d2a6��F��D""w/��|OO['m��S��8p QQQ<��C$&&���ľ}��└�
y�G�����Ã��b���9t�;v�`���t�֍7�x���V�\I||<���:�/_����ՕÇ�:R@nn.Æ
���Җ����iwb곆l�NO�VUUŊ+���
����/_NFF��X""""mM�޽)//��ۛ��H:v�Xg��?NHH�V� 44//��JU�ͫ���w
""u�׋�t�RD��ӡC{� bE�)buM/Q�������Ɯ��f�"))��/���@tt4}����ݝ��(&O�Lff&�'O`ԨQF��/�H~~>3g��?��?��ԩS��B��
d#"�wj
��$99���2f̘a�͜9��[����LHH����]s�����lT��dҍ�T�"톇�������7nmgΜ��߿�O�>m�>44�?��O����������6�.Э[7�e�6K��ȝV�p�ƍ$$$�{�nΞ=���#L�4�(ƻ��Mee%����ٳ���^�z���3�|:w�l�UTT���ʨQ��ݻ��ާO���IMM%((��~UDDDDDDDDDDDD�*N��yó!7B�׵
Cu��a/]�Ԙkeٯ����2K�����ǦM���׮]#??���|._��b��^�z��RXXh��={���$


���3��]�vQYY�����v|||8t��w��th"""""�d�5e]#ߪ���y��)�j�oȱB㎷1�l/���<om]zz:yyy�=�iӦ�9#���յ"""�2T�"w
777���ٹs'nnn��_�n�O���������8����]�gϞ���R^^NϞ=�����1""�a����]�ooo�]�Fff&111����Z�Rח����/%%���By�"""��𠸸���h:Ď;��[rss6l��v,m���*N��W_}����6_�ִ��v�����HKK�����ӧ����ȑ#흚H���յ"""�rT�"w�g�y��7Ixx8C���'%%�͛7���M||<_}�[�la�ȑ����֭[7n�F�n��R]]͙3g0`C�������b�"���b#FD���*��^ۇ�]�r��%�f3EEE���H```��j�g�����۷/���DEE1y�d233��S�N0p�@��4�*FDDDZϬY���O읆�=!##��d�4�j/�
���m�֔Q�o�1�l縶��VUUU�b�
���X�|9899�9C��U��kEDD�e��M"�N͝;�A�q��qfϞ�O<��	ؼy3]�taɒ%TTTE׮]y��7�ԩ���_�����fL IDATݻ7���8q"cƌ����f���q�Ƶ����,^�����<>���O�NRRW�\�s�Ç��gΜ���ooo��R�r��i#�…t���f;�6K�������S�2u�T{�!rϘ:u*O<��h,�-D��JNN����3fm3gΤ�����d;f&����O�ZiY9Eڄ;�4���III|��G�۷���2������b�…<���������oO���ۗ��p^�ubbbx��Y�t)�֭�����W�0a�V�^MNNs�̱�NN...�?���""���<������ѣ�����O?�رc�_����BCC[l�����z�_�t�xݡCl�a-m�i���NAD�IΟ?Ϻu���Φ���g�}����Zc+**HHH�/�����Ջg�}��_~#�ƍ$$$�{�nΞ=���#L�4�(�o���`�����ҥK���$>>�h���#66����S�NL�6��R^^λ����qtt䩧�"<<gggc�{��%##��'Or��z�ꅯ�/!!!t����&sSGGi�q6F�\�Ĺ���$11�={���w�ѫW/��y�ϟO�Ν����N�w�nw����X����%&&�={�йsgƎ�+��B�^���}RSS5j�{�6��郷�7����P�H[И~�!�y]ׯ�����i��@\[���+aaa���չ���~���~ۦ��?�)?��O��~~~���Y�8;;c2�HLL����~��PRR�ѣGY�`��!SD�5������?����ݻ��?�����+Nqss�����;wC�֥gϞ���R^^n3Zyy�#"""�G��"��d2a6��F�VQQ��y�())1�>��s._�l{��%^|�E�������R�l�¡C�HJJ2�����cӦMFܵk����'??�˗/3k֬&�ۘ,bcc�����)
��{�}�v�G}D�~���Ƞ���+W���g����믿��
HLL��Vii)���\�x�7�|�I����l�����W��p�B#��ٳ$%%QPP@\\��Es~'{Λz<�.;w�4�2339z�()))����k�.*++������LJC��{���A��zM6�:��������F
��>�l6��l��͍ٳg�9;��L�4����-[�/���!C������c��g�a�ƍDFFΐ!C����IIIa���x{{�СC)--���ئ���؈��5y�dL&����'4��A�m޼�������[o����'����\��&vӦMѯ_?~��_3l�0
Y�b�O�f�ƍ����k׮��ۛk׮���ILLiii����5�ŭR5&www����F�SIoݺ���i�&��㉉���ӓ��w��Ӈ�?�������o��u�V�-[�ĉ�С���,X����#禎����l������
y�G�����Ã��b���9t�;v�0F`h��D]�!�N�ŁX�f
�F��ĉ,_��o���������0l�0��-m�����.mVC��^�u]��VDDDZ��SD��ɉ��(-ZDPP;v�`͚5t����ىȽ$88���hbbb����Z����b��;w.YYY?~ܦ(�K�.,Y��x?f����)((�ɩ���q�ƵX�"""R��S�2u�T{�!rO��O�B�UW�G�Ç���@DDÇn~�կ~ŢE�����@dd$#F���G%""�_��|��ƍ��]�r��%�f3EEE���H```���19X̞=ۦ0n:2�9
O||<���?���`����`�P	��~���9q������ꫯ��X[�8����bϞ=DGG�|�����ɓ���4�S��;��s���u}�(#F� 22���P���g��S�NۻՠA��bDjjL?�RzM6�:��������&x���			aժU�����`�w4��|@@�:u"==�B����7����J����裏طoeee8;;����…<x�;a�V�^MNNs�̱�NNN...�?��r���7�|`@X<��c6���}��Zc���[�m��ż����呗�dž
�7o&��·��19XXn~�t�h��N����a�vrr�Y�ܹs,Y��'N�,����'��k�q6GS�ř3g�u��O�6^7�w¢�缩�c1z�h��#G��u�\�p�nݺ٬oi�Ĉ�E
�&s��F׊��H�Sq�H�L&
�-"���/@�����}�u[ۺ������Vﶜ��1�L$&&RRRB�~���_`=z����EDD�u4u
�z���L�6�E�mY���������������ͥ1����t���7%�:�"�A����ˍ��7�;uj�כ7nܰi���c���dee�駟r��1֯_OJJ
���w|���r��m����v�z���{�q��	�����O?���Ço�~���l�������:�Is~'{Λz<5�-��;t�P�6-m����O���^����k�kEDD��5�\�&
�O�>��f��l6���f3-��������(++�wTUUq��1/^̡C��N��9B\\���K�.e�ڵ=z��i��������?�٪�2]�,�9Լ>,���ܬ�]]]�'11�M�6�ŋ���mr��͡%X
ْ��X�x1'N�Z~���f�-gCX�عs'�����7�w�5���?n��ȑ#�ۿ���ֳgO�Z���YbDڪ�\����kҵ"""��T�""""-��ɉ��(v��ٳg9{�,;v� **�C"���H�d����*++y��`F�c����b�����s��
>��C��t;UUU�X����@����۷/,_����*{�'��~�͟��g�_��_���~�m�X___#����\�~��Ǐ��;�0n�8#vҤIx{{�m�6*++2d���8::69�����<�իW9y�$˗/7�/^��k$˔�і��>�<�����<y�~��������ooo.\h�6�w���v�s~�����p��u�9Btt4ps�]��A���6�[�n�^H��i�5٘뼶�W׊��H�Ӵ>"""���qBBBX�j���xyy�9+�OK�>j�(���طo�q#�:t�@�=x�Wرc��_���$''SVVƌ3���3g�u�V���			�cv"-o����ݻ�S�N���/�&L����_|��3g�7o�ղX�MLL111V���ҘZ���/����\���+W�,?y�$>>>t�ޝ.���;w�l�>��q6�ܹs������6#xv�҅%K���;Q�yk�9�Sz��ܹs��~�a�O�n�3f����N[Fj+ED"�i�5٘뼶�W׊��H���)�*:t���G?u�lٲ��ݔ��������̙3흎���4����Q�p��
���	��'�䩧�����|�I���W��s���7�����Q��]{S88�z���嶱������?e����g?#66�K�.������_��c���̘1������c���<�쳬^���gjj*�F��w��F\�>}�&55������H�UߨL�;w&!!���@�w�N�Ν?~<���6�ݺu#99�iӦѻwo:v�H�޽�9s&7n���Ո
`�ʕ����;�;w�s��xxx0w�\�x�&Kcrh)���~~~899ѹsg��;�c�����t�R���Gǎ�z�j�����!\\\HJJ�d2���Fǎquu��ח�7Z����߉��[C���رc�ԩ�{�fΜ9���ӹsg#f„	t�ڕ����srrpqqa���w4/�{5w�h�5٘뼶�W׊��H���)ҢƎKzz����v`���NADDDD�(..�M�6�]�F~~>���\�|�Y�fY�0����~�z���o�
���?X�f
ps��\�t�_|���"�����-[�p��!����ڵ+.\ 88�s����O�f�ʕ���L�8��}|���f�n��ܵk����>m���áC�ؽ{7S�Li���3���,[��e˖Y��v���'<<�A����?�����k�
ن�P�v��ޭ[7c���n}���??�&��;�
�f�ew����FXX�msk��Dm筡�N�����F!c]���1�L$&&RRRB�~�())��ѣ,X����K��jh?��뼶�W׊��H���)"""""""�,۷o`�ڵ<x����7��zJ|Μ9����m�6c���bu��ۛ��dzs�N����n�fӦMѯ_?���8x� �����ۗӧO�q�F#��?�ܹs<���l߾����������Z���l��ݝ�k�7@rss6l��:�6K���HM��������l���f���l�?���ZiY9EZԁl�����d���'""""���)rj���v׮]�t�f����"|}}	$00��u�ԉ�˗��/��[oa6��رc��N�<ɾ}��=`߾}DFF2b�}�Q"""��/�_|AHHp��0ܜ�2J`ddd�S���”-[����ʺu묦�8u��YoРAV1"""5999ŢE�

`ǎ�Y��.]��9;�ܩ�kj�)�t�����,�H�����w
"҆�KEl:t�w
"�L&���)���9�/�7� //���<6l��y�0�L�~�?b��L�¶m�ؼy3s��m�|o��q��e��?���ŋ�,�)))n������o�5�,��ڠ��l�@EE���?x��e.\nNQ���#""R�����V�Z@hh(^^^v�J��ѵ"""�rT�"""�
ƎKzz����;����ݦ擩�'`�Ī���G�&++�O?��cǎ�~�zRRR

eʔ)u������dgg����s��W]]m�^�z�!�� ���<��<�����67nܰiklQ��db���\�r���xbccm���`;;��ME�""����&a2�Tl/-��G8ii�VDDDZ��""""""""���ꊿ�?���lڴ���`.^�hUdQggg^{�5���m��Rtq��e�����w6y�����/�ӷo_�=j�ny���f�=��C@�s
��_`����z��	@yy��z�6K��������H[��SD���������`���L�6�Us������E"w3�Ʉ�l�w""mʤI�())aٲe���2����o8::�v�g�}���z�����,�޽;.\�O>aʔ)�={����;���7��o��>|x�����lܸ���h~��_���SXX�;���q��1cƐ��ʪU�����`͚5���ӿ~����l֬Ydffr��i6l�ڵk��S���R\\lS�R\\lĈ��������U*Ni�#G�GZZ���L�>OOOF�i��D�
����w
"�*2�]pp0��������xyy5h˖-����TVVZ�����}�vV�^��ի���iV���jrtt$$$�������/8s���ͳZ6`���_���ٳ��Ǐ��*���^�u�;v$""�_|��r��1}�QƌCvv66糠��.�ikT�"�UUU�X����@c�怀�/_NFFNNNv�PDDDDD�ij5�.t�ԉ��t����߿?�ƍ#88�A��ݻ7�����7��j_�d	�ٳ���*���Y�b�?�|���:u�{���G?bΜ9<��#u�v�֍��d�����,Ο?OϞ=���K/�����۳gO��������\�r���3w�\~��׹�#F���۷�a����0a�W�&''�9s�X����������2DZ�F���,##��d�4�f֬Y|��'�NCDDD�b*N�6��)sڲ��d��ʘ1c��6s�L�n�Jrrr�O܉������W�}v���߿���j���L�>ݪ��ɉe˖�lٲz�u��
�C��~���	��}��%::����� ""�x����d"11������@II	G�e��t������ˀ�:u�����ԩSy�'읆]���;M�:��;
��S�ͳ�$$$�t�R<==���������D����w�}G�^�x���?>�;w���޽{�����ɓ\�r�^�z���KHH�՗x�ϟgݺudggSUUų�>k���EEE����5�޽{�}���ۛ��T����֭[K��5���!�f�`m�j�[��*==���<F��'<EDD�����0��Fa��l��͍ٳg�9;���;��c��;
�Czz��S�{��S�݈������(�z�*.���Ј9{�,III���6l 11�j{������r��E�|�M�f�ɼy�())1�>��s._�l�Ϯ]�����u�s:��ݻ�2eJ�^DDZ͑#G���#--���j�O����'#G��wj"""rsrr"**�E���;X�f
]�t�sv"�۲e�fͲw""�e2�0��N��u���)��H1���uҶ�8E�
www����QRRR(,,�G!""�������СC�ر�ɓ'�u�V�-[�ĉ�С���,X����c�7o���������[o���I~~>+W���'77�aÆ�,�����8ED�6�YKh�sPUUŊ+���
����/_NFFNNN-���<��㄄��j�*BCC���sV"
�'�E�-�׋�&O����""w�.m��S�.,�+ܮ�֛��g϶��gϞ=DGGӷo_�fKTT�'O&33�(Nٿ?��՜8q�?��|���|��W\�t��fVVps~��Ç���ů~�+-Zd�۩S�8p��q4�*FD��Zsz����LYY3f�0�fΜ�֭[INN&$$Ďى����|�[7����:u��S��'�|b��j�ԩ�EDD�E�8E�
K��ř3g�5������s�αd�N�8aW]]m���o1b�U�c�=f�ޅ�֭��2K�%FD�N�Y�r��
ؽ{7gϞ���&M�d�5�޽{�����ɓ\�r�^�z���KHH]�v��)!!��K����I||<�ϟgݺudggSUUų�>KDDD�r�y,�SSS�������w�}<��s,^��ޑNV�^͎;�g���TTT���ʨQ��)���郷�7���������������H�T�"vQsD���p�)`]TR�[GDy�8q�����駟��Ã�Ç�ge�f�mw�d{�X��tpp�Yfi�\�"Ғ���شi��ڵk��瓟���˗�5�
HLL�j+--%55��/��oZ-�������(ꨨ�`޼y���1��9�/_nrN�Y�`���\�r���wܸq����Z�?���f3Ç��_`׮]TVV���c���áC�ؽ{��k�˜:u��C���=��G�l��������Gii)��������x�駙1c�����GM������0z�h
S/rQ?mM�����W*N�v��͍��bv�܉��[���?�����޽;EEE���ׯөS'���OQQ��nN�l�gϞ���R^^NϞ=��Yn��l���o��ڵk��ڵkdffCZZ�MqJ]S��f�֭,[���'ҡC���Y�`9996����$%%���7o���������[o���I~~>+W�l���k�DEE��C���HRR���8%66�-[�����ڵk�Q`rss6l��:����\�������E^}�U���5����+/��ՃW�^�ԩS�:u��;w���h5�dk8r�qqq���Q]]�������d�ȑ�����>����O��H{��i��y�6n�Hdd$���2�����6oތ���1����y��(**�z��ŋ��у���'�_����h�|�MF���S�x��m�?t�PJKK)..�)B)..6bDD�SW�H��>�w�ڕK�.a6�)**��ח��@���������ĉ���믿櫯��G���={��WYYYDDD0|�p����կ~ŢE���_M���0�Y�f����ŋm�,�)����[���I�S�N7]j�L-g�i�222ptt�wm`� IDAT"�����N�j�4����N�My����|�2O<��-��ݝ�ׯs��	��}N�<I\\��Zk�,���bŊ��|�r222��UD�?����O��H{��i��ΝKVVǏg���V˺t�’%K�����dff�r��Z��?y�$>>>̞=��{�r��)c��	&'cƌ!;;��������YFZ7n\��SD�.�/�7� //���<6l��y�0�Lt���&�!C�Z�;w�%K�p��	��ڦU�oX|��7�1ª����3�����0^[
Nnܸa�e���C���?x��e.\�[�n6�Y�,1"""��'�|�'�|b�4DD��{
��Ǐ��o�7��~�Lj��&  ��jN��ɔ��1c��m�̙lݺ���dBBBZ5�{��i�S?-""홊S�Mh��...$%%��G�o�>���pvv��ˋ�2x�`#���^�������?0d�fϞ�����@ZZ>>>t�ܙ��֮]�޽{�|�2O?�4����ڵ�j�&L`������0g��e999���0~�����g���!��ϏѣG���ŧ�~ʱc�X�~=)))���6k����{�'Nп�~�i<<<>|x�s��:j
����f!K�N-�ǭO~w�С�8����۹r�
������ڬ���`�����m����������Νc͚58p���*<<<�3g�����Jٳg�}��z���g�����[����
׆��b�޽dddp��I�\�B�^��%$$Ęz��[����l���x��g��m�-ǚ���ҥK���4F�ѣ���9w�q��b����{��d-q
͵�����TF�e5EE�>}�&55����Z2�֧~Z����i���S�ͫ�MWWW����wݺu#::��e������y\�e����(��b*:._p�eR�p/��B�PW�ƅQ�&jX#�9d�i���Y�ILJ�Tb\�P���I��"� ���d9���:��~�繯�x���z�###֮]�ڵk����������ɡs�����p��Y�.]��G�B�SSSlmm���%33��G����o��S����M�6\�|Y�^RRRe�I�.]�|�2�O����FiW�,�+���k�???�����̤o߾������G~~��rm���J!������TQF�����uF�VXXȢE��Y��L�],..��Օ��L�-77���`222��(�6j2�;

��?//���pn߾�,�PPP�����Q�}�����k������@�b�E�ؼy3K�,aڴi�9������Rp5�����i|�T���!55����Z}�B�
��I��/��B!ʫ���B<c����ر#*�JiS�T���k-5$�um�ԩX[[��STTDϞ=�ի@�} =u����\�x����+�o߮r�ɓ'�����ӧ)))��g���uWm8::*�k�رCi�ݻ7��2n����!�MYTTQQQ�C�gFTT)))���S�T\�z�N�:̩S�Ը`��w�^233�߿?aaa�����IMM%&&м)--�»�+{<����`�ڵ$%%q��I>��S��l�j�}�999t�҅��P�5����_��‚��$�"+��i����Ԕ��P/^̘1cx��7���������r�Q��Un�����ǚ��@�>}��R���!tK����$O!�(OfN�

���bŊ̛7������hժ���B<휝������mVVV�:�رc���e�ƍlܸQk�ŋ+�#B��ɉ�G�r��%��&M�Ta�ZeS���Z�͚5cݺu,\��S�Nq��9��#8q�Z�O=�˨Q��,!�B�T*�C�g�����Ch�*���|{ZZǎ��ӓ�^z	x��g���Z��9rxX,ߩS'��>///��숍���ήN_KMƌ������.��W_��?��w�p���Ǐ`ݺu���Oy�o��6+V���kvrr�Z�.!;q�D.\�@JJ
�O��̙3|��wDFF�c�^x�Ǟ��{����Gii)666ʬ�5��ҥKt��M�ݻw��#��{��%OK�BQ��8E�Z<x0nnnlݺ�e˖�����U�"{{{�7oNdd���N�.]5j��ε�c͚5���������ٳ'NNN���OQeq���������s��Q
3f���>|�V�Յ�^z�iӦ͎;عs'�&Mb۶m$$$0�|��			3a�E,�B!ijM]�>h� ������r�
���+++�ZcV�����ٚ�y��uV�ZŅ�����)?���P_�U+j:����ae���C�>}pqq����ݻwȇ~Ȗ-[*ݯ�������V�X�,Q�Xo޼	<\��<u���B�$O���i4�$O!�P��!ꀃ���u(��w}ඵ���bU�=�����r�Dy�΄Rձ���X�v-k׮}l<�-�)߯����oݺu����@PP999t�����Ξ=�ҥK�iN�B!��W���?�ы�zzz��Sޣw�ו���e�.\�@�.]3f�����׏Y�fUx���n�\�+�'y����5jw��%66Vk���	$99��qn߾��ի9}�4-Z������Z�X�����R�U�B�
�Ӓ���i!�5!�)B!�����3�B�R���<\����'''G'�B4չ0Q�"##�/݇�u�@���ҥ?��#�Νc�СJ��s���������177o��j2�:ӦMe6LxxG{����ҥ�/_����3W��}��+ӧON�>���y��7���gE���z�ʕ+��_h۶-~�!�U�fff��呟�����ƶ��|��B�$OK��<-��q*�
%�B�244��ˋ��rss���%&&///Z�j���B�9s���֬Y��ի���ٳ�KQ��Kl����dddPRR���y������7OOO.^�ȃ�q��1��ָ��*}�ws��0xR5S�ԩSs��E֯_��߾}�ɓ'�����ӧ)))��g���u2~ys��^������ʢ���;w�Ϛ5k4�*��Ņ_~��.]�Z�Ϛ�ڻwo�\�nS�B��i���I�BQ�̜"�B�����֭[X�lY��#!���ݽ{�
60c��.N{{{֯_OTT���:�PQ_�����qqq�����Ǐ'==]k�V�Z�j�*�y�6m�y�&������s��'��&c�;���X6n��ƍ��u��Elllprr��ѣ\�tIcy�I�&i]���7n�����>#""����>ݺuc����_PP�/���o�Qa�����:b�N�8AFF���2���F�z�kB�?�Ӓ�%O!�x)N
B�XBT%**
]�!���AޓB!�ôi��u]/�S����]�Ɯ9s���s�o�>BBBpss�atB�ڪ*�H@@���ܹs���ظq#J_ccc���ٵkǎ�ڵkaee���+=z�P��^���۷���Gqq��^�1׬YCII				<x�={����O?�D`` ���```@`` ���=z���Bƌ���'�~��b�
�
����ύ7h޼9ݻw��W_e�ܹ�n���SMc�4i۶m#!!����k'!!ccce�!D��<-yZ�B���++++�u�����#�Ubb"~~~:�J��9R��wtt@�R�2�Z)��?B4M���Ӑ��M�?����3�O�&==�^�z=v===T*�RxY�ye�*N�h۶mۈ����֖�+WPTTDPPG����]�v���k,Z�


x���iӦ
�����w��+W�`ooO�Ν9p���O��#۷o׈��͍��:����cω
�Y���!?�����oЩS'bbb�B�v��IPP_|��;w '';;;�.]ʢE�t�xZ<K��I�>|���~���h�2�Q
i2s��W#G�d�ȑ�C!�B!����2X�v-�{�&--�Z�)
壏>B�Rѯ_?eJ���b\]]���T����LFF���0{�l�����o�8q��7>>�ѣGp��a���������Ɔ��T���>}z}�T!���=���"֮]�ĉ166&;;�>��A��8BQ_���9t�*�
�a������rBݑ<��<-�����E�'����<�!y<���E!�Bh���f��񸻻�z�jRRR�߿���R����R�������_�F|�޽dffҿ���HII!22�������9���H�֭ٽ{��q��)�5ꓒ��ӧ�V�6u!��gʔ)�����+�0t�PfΜIZZmڴQ
������///bbb���%77������hժ���B����]���BT�̜"Ddd��CB4b�RaʬY�t�����d�K!D�


e�����ԩS�r:���c�ot)___���055e��혚�*ێ9���7�:u���///��숍���Ύ�{�3f�g�N�<���
�;wNY��ҥKt��M+��ݻk�B<}<<<�ڵ+_}�?�����t�Ё�_~�E�Ѿ}{]�(���qssc�֭,[�L�� �h$O?�$O!��)N
b�̙�Aш}�����u��Ur�O��3g2l�0]�!�x���o,Y��/��www�{�Fy�aXXܺu�^xA�v��lmm+�7++K���ɉ��BBB�����ɓ<x�_~���~uq��MLLL���nS�B<}�qpp�B�g���ѸI���/��q�8E!�h#G�d�ȑ�C!�M@TTnnn���p�ĉ���Q�3��o������ܻw��;w���l+++�r�;w�(?�mۖ�ӧFFF			������^�(Oݦ�#�B!�B!)N��"�.�Irr2Ç��?�xʄ��=S�	�4spp@�R�:!�S��͛,[����/^�֭[+�%�1qww�]�v���Off&}����ܜ��l<����c�5o�<>��s"""8y�$����1B�nffF^^������i웟���B!�B!������9s���"""(++c�����Ջ��:4!D����uB�Z�"3!D}9t��/F__���X&O��됪��ё��X���رc����7�ݻw��鉇�={����7{����>��ښ�;w*�y��:u*��9eee0��^�޻wo�������*B���V�!�B!�B��G�S��D]ΘR��w�a�f̘��Mhoo��뉊���аA�B4��3g�:!D-|���A�}�6�����䄟�mڴ�uX5ҬY3֭[�…9u��Νc�����p��q���qrr�اU�V�Z�J�X���'**
�\�`Ĉ�8q������4�eddT���qQ��B��(**��&**�-Z�:!�B<Ť8E4
���NSµkט3g��6w�\���GHHnnn:�N!�BQ_���[,X�ݻwٿ?����ICM>����KL�6���hv��Ν;166&88�]�vq��1�]����VVV���ңG��)?�=ZcۤI�ضm			̟?_c[BB���L�0���Rѐd	c!�h�����!C!��J�SD��.\	d������K�������� �9��N�v�x��X�h�ٳ???�����ݻ�c�������￯�奭�-���+��ެ[�����8����%==��-[2~�xV�\�1�ɍ7ؾ};'N���ݻ���+��UPP@xx8C��}��J{ǎ���&<<�y��5�u�
�6�|��IǨ�~���$''0|�p��Z!�3�����k���i�رc��灦����֭��cjj���;����:�s��֭ی��ppp ((���:w�@NNgϞe�ҥ�n�I^���988����0�BT���L�!!�� �)�����@�Ҷ��WWW233�>������A@@&L��Ϗ.PTT�|Q�7�|��ܼy�_�F�YiK�.%??�{���~JKK����,X����e�������B�c>|���"lll����ؐ��J\\ӧO�ѹB���̙3AYY�gϦW�^8Pס	!���ԩS8;;s��u��٣��ͳ�����w����y��U���ٙC��R����@�Rann.�R�F,11???]�!��5r�H�/_��0��4$�O��˗Wy�S�������.���x��wػw/�����ߟ��0RRR���d�������9��y��gϞ����o��}}}����w���5ʇZ��vݺu#::���$,X��cǔ�}�999t�҅��PN�:E`` ?��ֱ����ӧ��6u���B�����g�=�ݻwٰa3f��ܜN�:aoo���{�n��+�B�Zqq1����=KKKΟ?/��=z4�&M"33�^�z��oT����///bbb���%77������hժUG-���+W���0��JQQQ����:�����<-�O���(�\���0�P��)B'��?<����NNN(Ϗ9���7�:u�xyyaggGll,vvvL�0���ϓ�����
)))ܾ}�iӦ������DƏ���7���=<<�ڵ+���s��me���ǁ�SZ���+++�~�mV�X�q�K�.^��޽�F!ij�6K�4!!!\�v�9s�(ms��e߾}��������B��q��9����|�2۷og�������:�F�}�����cmm���'͚5����qssc�֭,[�++��
UQ����A!*����tJ�R�lB��Dc#�)��Pk��+�lmm+쟕�����裏��qqq�l�777���K����8E__�ѣGW����򳩩)���J�իWx饗4�4h�ֱn޼	�����6u���B�/\)--%00���8rssiѢ���L�:;;�:C�<<<___���iٲ%�Ǐg�ʕVz�m۶���-+W�������p��,�бcG���	g޼y�D!��)*))a˖-lڴ��C�r�����bcck���A.�!�B!�B4!R�"t���ՙ)��YS��ʪ�Ν;��;�@zz:7o����6�6m�0h� )**"33��ҦM�*�ۢE��*�q���ys�n���W�R�IU��2�ٳGy~��}Ο?���),,��;~�.]J~~>���c���������Ya��>��JE�~�X�d	������666��������,n!�BW.^�����Νc��͸��W�w�B!�B!��)NM���9���<xss�*�N�8��g�Jaa!#G�`�ȑ����駟r�Ν�.�S]�t���˜>}Z��z٠G������G~~>fff���˷!�Ztt4���X[[s��}bcc���!""�N�S�u놗�:t ((���`�;Vaq���/aaaXXX���O�֭HJJ�O�>Z��ے���8E!D�VZZ��������/���밄BT�ҥK���[y>i�$^|�Ez���ĉ�ѣ��>YYY���q��%.^���Ç�4��f�|�Ʈk׮��������qpp`���Z��Z�����V�Dxyiii�f����H���>|8�f��i<B4e��T��y��8p K�.�0�R}�ƒ�ʓ|(�BMn�M�����ӓ�/��nܸ�����5���J�W_}}}}������1�}��0v��Z�5y�d���9}�4%%%|���l޼Y������l�m��t!�.����ǵ?J]�R�����֭[̘1���4bbb�4N�v�J˖-���۷ok�S�����}�ve�3x�E<,t)O�t���B����O���+xxx�v�ZN�:%�)B�����*�q�IIIT�~�v�"88���$nܸ��jY�~=ǎ������b�_�^�cVt���3g��p�3 IDAT��5kX�z5����={V�a	�$�$�r��-�;�…�r�J=G'G�B�G��)��rqq��㤧���䤱�U�V�Z�Jynff���iii��ݛ���/�����ի��⋏���:���8z�(�.]R����wݔ/B1b'N� ##+++�m�VF�U똄O��+W�i�&���INNfǎ,X�Z�jU�cYZZ*?�NJKK�����PPP��[�x��m7o����Dk?u���Bє������իWӭ[7RRR4h��ê����\\�988�:Q�'NT��S�N���PZZ��4[ii))))t�Ё�~��!¬�.���tv���)))��˫^��|5��5Y"\�3ܽ{�
60c��F{{{֯_OTT���:�O����<
���KKK�����ˋ3gΰk�.�}�����;?�:��'�P!DyR�"�'����ؘ��`v��űcǸv�FFFXYY���5e�ĉIKK�*�9r$���u�����������s��Q
3f���ZS�N�4�m۶�������5�%$$`ll̄	�$.!D�T�/�ʛ8q"Ç���8p�s����'��w�^�-[V���h�B�YOO��~DGGs��=v�܉����~�~���n���B!Dc���âE�8r��W�fӦM�l�R�aU)22R�!���ڵ��Ch�rÇ'::����3`��===���ƍW�V�DII	�����a``��X����p��5�̙��͝;�}��������v[�.O__�Ν;��̙3���]��L�|(��<)N�^U蚚�����c�coo����V��իY�z�cǭ,��ڍ��X�v-k׮��������C�Ν��_p�={��K�*�v!DELMM�����֖��L�=Jhh(���uZ�R]���k�???������T�3033#//���|���4����W�!�MEXXo���ڵ#!!��_~Y�!	!�S�������ݻw���d����[��ޥ����� �9��N�v�x��X�h�R�Q~i���6l���$%%i��<y��C�VX�RPP@`` �~�-7nܠ]�v���+,Y�ccc��7n�`���8q��w���+�(��Q��{4�!C�(�*z����|�	IIIܹs��ݻ3�|�L��1�ѣG�����ŋܻw�v��1v�X���hݺu�竢1�{�������Kzz:-[�d���\���\%''���˗_~I��͙5k�������O�-=z4)Ǭ�I�����2d�2s3@ǎ���&<<�y��U8��O���ӕQ/)����&c>:V`` �W��W�^�ܹ����k(--%00���8rssiѢ���L�:;;;%��k�|\�X$
!�����c���:t�J���*�
sss�劄�QS�N%''��k�2e�z���/��h�t�����%++�;v���@�޽���#;;[�E��Y�޽<^!����_������9o��>>>M��|֬Y�A�g���*�J�a4i���,Z���W�*m/^������WWW233����\������   ���2d����<yR�����D���:t��>w��a�…\�|Yi���#,,���T�����,X�������_Maa�cc���7o�����ו���,6n�ȃx�7��Ki웗�Gxx8�o߮Ѳ59jK�.U."߻w����SZZ���g�_se�l�Btt��|׮]t�ܙ��(�r��=:���>��P����Ç)**���Fk|RSS������$B�7]�����π�MPO2���/��������٣<��>�ϟ��*�pV�_y������C!�y���B�:ahh���111��撛�KLL^^^�j�J��	!1ggg|||=z4/����A��ʪ�}���+|ԥf͚�n�:���8u��Ν`Ĉdddh�n+��B�����пRRR��o���kR�)j*����2y�C
�ppp����J���իt�ԉ��`N�:E``��C��{����I���	#%%���HHjj�2�ɣw����iݍojjʋ/�ȥK��q��@�~�G��m�Vk�={�p��e:w��D�N����b���J��>�����t�Bhh��~��Ǟ��Ů����۷/������3m�4����~���`�ڵ$%%q��I>��S����5�&�@�[�n�,5,�رc�=5�����}�8y�$�������͚5c���$%%�d������~HJJ�O�>Z���}�x��"O�WRR…x�4f6��e5����
�4���.p��ԩS���+��GDDԸ_y������C!���!�������֭[ٺu+˖-��²��V��j���lܸ�_|�����ŅM�6�s�U{饗�/<w����I�hݺ����066f„	
�BQ]������0u�T&O�Lzz:����B�&��������<==y饗hѢVVV�_�^�G���ۛ^�zѬY3,,,��� 66��16���2e)��'ORVVưa�*�_Q�Pf���o��Ǐ`ݺu���OyMo��v��{���D֬YC׮]iݺ5���������S��w�}G߾}�ꫯ������w��DM΁���]�v�e˖�]��o߮���ڵk�ٳ'J����֭[G�n�hٲ%���4����ҥK��yT���5��4�<�hÇg޼ydffbjj�…k5�����r?jO�O�S��T*"##�u�3f� --M�X���ʫ�|\�X$
!���,�#D#��� wS	!�TQъ��-���O�ou�U�_u��[�Nc�V###

"''�Ν;����ٳgY�ti���\!���ȑ#,\����b8P�߽B!�z)�A�i�Wtsϕ+W*��YYY�w�С���p��I�x�
�H��%}e��h����_�6��/��R�}�z��-�z��uV�ZŅ������h̚�5KKK�gSSSJKKk4��<z���؆��Z���t��MLLL�����}�x��*O?�Y�f�mۖ���x�b���k5�����'�'�\��M�6���Lrr2;v�`��888h̪^�~��G>�n,��BTD�S�B�`���9t�*�
�����899�8:!�BSaa!k֬a�Ν̘1�O>��v���:�gޥK�*��Irr2Çg֬Y
������ᆵ���|�����c��W��@@˖-INN�����(��DE��8��ۼy�}e[��Ȗ-[�p�]�ta̘1XZZү_�:ͣU��h�B���1�T˖-+l�ׯzr񚼟ԱWtLu[}�>!�CS��ս!�IƬh�x�|R�ĉ>|8Ǐ��;w�O>���{��l�2�O�^�~�U�|\�X$
!����!������Ŋ+��Mcbb����N!���%&&���­[�cΜ9�I��_9q�D�!Μ9C@@���1{�lz����u���u�҅��s��i�Zr��9�����dggs��A��柄��VVV�:u���h


<xp��_:u���?��ٳg5��9{��ۣ����˜>}�=##�V1?�C����/deeѷo�J������iӦ
�/_V����T�h�&�)����̌��<���133�ئ^ڣ|�x6������MVV�;w������t���KcV����23rff&G�%44___����{T}����"�P!DEjV�)�BQK���͍�[��u�V�-[V��B��r��=֬YØ1cx����Ȑ”F�ĉ�߽{�
60c�����ԩ����_���w�6p�B��0a���}222())���Z}Ǎ���'/^�ܸq��?�kkk\]]��껶��=TD}�5$$@�_ycǎ��ۛ��tJJJHOOW�5j��w���J�ӧOSRR����͛�>50b��n�J^^���c˖-X[[3m�4���N������/�~�z�����@��WM�ASP���zf/��&�R�=n�%����Å8t�۶m㭷�b������CCCz���ɓ���uj��e������P�N����5��9EEE��ٓ^�z�3�T�_y������C!���SD�����uB�F,**��3g�:рppp�uB!����4����z�*���,\�P�!�Tu�mo,BBB�v�F!�ܹsٷo!!!����0:!D]ptt�믿����ťʾ...?~���t��C[�jŪU���mڴ��͛���cnn�����.F�~����8;;���r��,X���k׮mNNN=z�K�.�d��}ҤI^�{��9r�������/^��<v�Xbccٸq#7n�:�ŋ�������9h
j�~1b'N� ##C�&��8M�8GT��\�p��/���I^^YYYdee��/�(˧t��KKKz��ȑ#�ѣW�^e͚5��\M�.�tu�d̆��쌷�7>>>���hl{4�T�_Eǯ�|\�X$
!�����!�|!�B!������y�=z4���t��M�a5j�(�������N˖-?~<+W����P�[TTDPPG����]�v���k,Z�������w�eʔ)ʾ_�5�ׯg���|��7Z㧥�QPP@xx8C��}��J��;bmmMxx8�����Ĥ^ω���*�344$00������s�899�q�F%�̮]�8v�׮]���+++\]]�ѣ��w���l߾���<���+�gϞ�mۖ�7obbbB�>}*���Ą��>��S�?΍7033��W_e��Ř��*}
��ߟ�G�RXXȘ1c��X���		!  �S�Nq��=z�聋������o͚5���������ٳ'NNN���O���M��WM�ASP��ӤI�ضm			̟?_�8			+�K��������,[�Li[�p!�Ǐ�G�����Xk____:t�@�Ν2�Zi�y�:j2fC����y��DFF*K�u�҅Q�F���\�~��G>�n,��BTD����L�A��GXX�����JQ����T*G����CɏB<�秧!_	������ٙ��L|||x뭷��ßzzz�T*eֲ��+S��)�m�=���f�ڴi��������E�����u��C����>̞=���"����ر#yyy̙3�֭[�+���u���4>��s|||X�j������˶m�x��>}z��W���,��А��rssy�7�ԩ111u~|!jj�Ν��_(E999��ٱt�R-Z��Eej���_����'�v����???
��������/ky�=�߇OB��K��א�^�jH��SD�JLL���O�a!���#G�|�r]�!�B�gDii)���lذ�p��Yz��밚�nݺ���E�

"88�cǎ)�){��%33�����n�:,--�����ۛ��Tbbb�����ĄM�6����ƍٹs'�����lٲSSS���*,�IJJ�p&u[RR���č=���"֮]�ĉ166&;;�>����h(���:t�J������\k)��h׮�~�)K�.eٲe2��K���{�Ѷm�
�IKK�}��DGG3j�(^x���nI��I>BQ���zu������9s��CB4bQQQ�h�B�a4���(]� ����F��Ï?����������;xxxм�|<V~<�����v�
<��788�۷o+ۏ9���7�:u���///��숍�����!C����J�b�…�?��s�2t��*�t�@�K1u��]����2e�2S����ƶ6mڰd�E&�&CCC���X�b��� &&???Z�j���D}�����ɓ����n�:"##�����ŋ���W�ݾ}���,<x��Y�x��}��a��ь7�I�&�����Ԝ�iQ��C!��ɷo�ADFF�:!D#V~���٬Y�t�B��*++c�Ν�Y��=z���ʀtV�fii���^����Ti�r�
������|ٲe���p��y,,,��_���n޼	�����6u�����R�}��W���OӡC^~�e-ZD���u��������֭[���߬��t�h(zzz���`gg�{��[o�E`` ۷og����>}���RN�8���	���$&&OPP666����L�<�?��|I�"yZTD�B�GIq�B�dG!�B�~��.\ȱc�����w���@�a5*�ΈT��Ny��~����������1�ܹS�+��ѻ���m�&�hZ��s�hR�*��y�����p�B��`cc���3��ޜ>}�:йsg��#S�L ??���8bccٺu+t�ޝɓ'��o0v�XZ�n�˗V!�Ӣ2�B�&�)B!DHLL���O�a!�ȑ#Y�|���B�@hh(+V���ܜ��D�
�됞���dggs��A�������deeѷo_233	��ݽ�}������#??333�m���J!�B]�۷/G�%**�իWӷo_���3iҤ
�?��s̜9��3gRZZʿ��/:Dll,���0n�8&N���ѣ0`͚5k�W%�BQsڷ	!4X[[W��zE"##qww���]�3B(�\�BTT���B�RTT)))�CQM���S�Ne���������R��ƍ���'/^�ܸq��?�kkk\]]���}�aaa8���`���طo�}���G=�z� �޽{����5��M�G!�BWfΜɅX�l�p������gȐ!xyy���ʯ��ʎ;066f���<��m�2e���}�ݻW�/C!����)Bԡ3g�@DDeee̞=�^�z1p�@]�&�h$�hM�����Q�!!�)**
777LLL���o3f��Cz&���p��q���qrr��֪U+V�Z@AA^^^�nݚw�}��͛����ܹsy�w�����Ą6m�p��M���177���1�'N�����~}FF�F�j�,�BQ�֭[�
�'*$�С...���PVVFff&���$$$�{�n<<<�!j!�B��!�)Bԑ�w�a�f̘�LWmoo��뉊����P�
!�B��u�˗/G�R�x�b�n݊�����j����j}ccc���ٵkǎ�ڵkaee���+=z���LJ�~��M�6ѩS':uꄇ���>>>l޼�իW�}�v���(..`ҤIl۶����ϟ�1~BB���L�0�֯EQ{�ُ���rpph�q�Ն������_�~��曵>����ܐ!�B�z%�)�QP/�S_~�JHH׮]cΜ9J�ܹsٷo!!!����0:!�B!�~_�5�- 66�ɓ'�8��We��*j755U�>���͛ټy�V����'��?)�'N��ĉ5����@PP999t�����Ξ=�ҥKiݺu�^��~�9Rf�B4	]�v�u:!9Z!�^���hL�8E4z���Gnn.-Z���Ғ�S�bgg�ѷ����� �9��N�v�x��X�hOܷ�m۶���-+W�������p�B���~;v��ښ��p�͛'wl
!j���|���+{��%99���<Z�h���ƌÜ9s055��p�����I_{M����$99��Ç3k֬�'�B7


X�z5���?�={6�|�	mڴ�uX�9;;s��!T*�2��J����\k9!!�B!�B��8E4z�ٳGy~��}Ο?���),,T�,..��Օ��L�onn.���ddd���~�����G�R��ׯK�,����acc����Ɔ��T���>}z�O�B<�����c���*m���\�t�K�.q��A���4
�5gΜ!  �����ʘ={6�z�b��M!DN�8����g


���`�̙�I耡�!^^^�X��y������Z��qtB���DY*B�$888�R��h�3g�0hР:����K�����x_�9G!�^*������q�8E4z������cmm��������LJ���ˍ�{����I���Y�n���dgg���Mjj*111�L+5�(___��°�����_�:))	�>}�h�nKJ�lr
 IDATJ��!D��f鳿���2l�0V�X���%%%\�p�����\�x����}��:�����ow��eÆ
̘1sss���Y�~=QQQ��B!j��ݻ�[�???^�u�С���:4x�`���غu+˖-���J�Q	!�$L���Ԧ���Ύ4�<'/���.\������eמ��F�֭�s�*��˗/3v�Xf̘��34�9rooo:u����^^^�����Ԥ���0��Ԕ�۷k,q��%�u���w��G!�Rۥ{*�����͛y���h޼9�
���{{{�ț$$$�k׮1g��m�ܹ�۷������t�B��RRRpqqQf?tvv�uH��ppp��*B!�hp�uB!�����Fo�ʕlڴ���d���ٱc,���Acz�+W�`kk[�q������ZXX�p=�[�n��/(�n޼	�����~�6u!�xR�WJKK	$..���\Z�h���%S�N�*�k۶-���ׯ_W�SԺv������_�6m����ٕ+W����s��8p@�'99___���K�7oάY�puu%??�>����xZ�h��ѣ����Ȩ֯]�<<<___���iٲ%�Ǐg�ʕU�t�m�6bbb���e�ʕΐ!C4�5�ر#��ք��3o޼
s�B��U\\̦M�زe�ƍ#..�.]��:,!�B!�B!�c�?��u/--M�QU�ĉ�ꫯظq#�޽{|��'L�2����+�>n��;w�<Q_5u1LYY;w��ئ��ы�j�6�:KQ�صkW�\��q��y����i���h�"�,Y���?gΜ��Z�411a���\�z�o��Fc[||<�G��h߲e���q��mv������_�B\\��ݣ���C�)��ו�K����ʽ{����g������V���>b�޽t�҅%K�p��a��������occCQQqqqu�B��;w�C���?��ϏÇKa�B<C���+���:~��W�lق��=666�3GGG�}�v��U��l����������Ndd������ܹ�ڵk����e˖8p�s��q��=�ORRzzz|��g�������ǬY�4������x^~��ݻ���1ƣ��?�	&`ddD�v�x��7),,�蛗�ǂh׮���8::V�}vii)7n�w�޴l�^~�ev��U����:O?�јHB!d��D���bkk���-���=z���P|}}�>}:���dggs��A��ͫ<^M�����Ӯ];������'33��}�`ffF^^������i엟���B��
���?���ܿ���X|||����X+yڴi��'�Jhh(0�q��agg����p����pv���ĉ�c��SF��GFF���[�n�ٳ��;w���C�^�ؿ?;v$44���@�u�[�nxyyѡC����رcxzzj�U/�faa���?�[�~�ЧO�}�mIII��!�
�w�q9�����!s�->"��	帓S�t�f���qZ�4Śϴ�Ќ��ULсf�"9�O�U����a�:���v���u�����ۭۭ^��~=���r]��~�JKKY�r%~~~����={sss}�%��!��?0{�l����Ŝ?���ϳ{�nBBB�*)6o��6����_u���JPPQQQ�����caaA�~���uUTT�����k������q�Ʊw�^@ii)���>|8�;w�ʕ+xxxЩS'>��Sbbbj=��˗�'%%��{�j��hggǍ7(((`ӦM�������!C�t��m۶i$�x{{�j�*�秪N�0i(�ཐ9T!�� �)���0a���x{{���/ӣG~��g�4i��c��������E�=��?g�֭XYY)Ot�[������\�x��7�~�zz��INN�/_�HB�|���G!���.����>�7oޜ;w���K����eʔ)L�2E�>njØ1c����ĉ�>}���TN�<Itt47n��'��u��L�2�/����G�bmm��۷9{�,-Z����Rm���������2�i�&���O�,YB�.]�>}:���J�^}���s��@���Ub���	�|�	&&&�6��7�X+�ڵ�Z!�օpqq!55�+V�h�"��
��صk����������x���E�5k֐�����?>ݺu������L֬YCVVAAA,_���Ǫo��w�t�R�L����eoo���/1115.�*DC�f�N�:��ٴi�{�f�ĉ�����w�
���[�laԨQ̘1�������B^^;v�M�6���+�R*W��6�?�����2��ҭJϞ=ټy3�<�+V�`Ŋ|��Jr��ի�t�ݻw'""�~��q��q�O���U�ٳgvvv�u�V<<<��1�_�̓U���A7$2�
!��o�D����@@@Æ
c����/����ҵkW���pvvf��;��[�ҬY3.\X���5nܘ%K�ШQ#�;�ٳg2dPQ=�*U[�JBq�,X@ӦM9~�8}����:����a��ի����[�����3g�~��'��i���iڴ)aaa=z���R���znk��;U5@���A�������2�~۶m������j�n޼	T,iT��M�G!ăQ^^����ׯ����?<==%1��L�:��S��;!S�Ne���p��aHKK`ŊXXX`hhH�f�x�����ȑ#�>�",,���\�M���988����|f�a�ZVe������CCCZ�n��W��1��r��!lllHLLd޼y�5J�1�}�Y6oެ1�����ѣ����wԕ��P%�駼��1l�06nܨ���-[7�����[o�u�%�k���i�dB!�&�SD�PSF���=���DGG+�
���:t���o�CCC����9x� ��������t�޽N}��ӧ�&M"66��7�i�&Ǝ�ڵkIJJbƌj����hٲ%�G����B<���N�1c�0h� �u�7l�@xx8s��U��:t(������k��622��Ņ��`���m۶e���l۶���t����}UմiS��=���+hU^ӹ*GGGbcc)**bӦMj<N[�����-��~]�|��3gr��a�,Y�����|/q/�xU��TVVFpp0����ڵk4i�sss&L��ĉ�۶m[~��W�_��O<���s�ε�\v��u֭[Ǒ#G(,,��ܜ3f�d�����FFFHZZM�6eԨQ,X�@-q�����Đ��EQQ�۷����7o�v�rL�}n�ڮ�;88OOO,,,�J��������o��F���y饗�5k���+T$�GFF2`��ϓO?�4VVVDFF2}�t��B4d.\�[�nZ��;w�N�:)����������y��g	��1��ݻ��{۶m��p.^��$Ѩ6Lc_�W�f�̙�۷�}���t�R|||X�`�]c���ΕP�y��y�6n߾ͫ��J�6m���U���ʕ+���өS'���+e����������666̛7���۫�[�P!��n$9E<Ə�������ĄE��hѢz����%K�7�-Z���ё������.��ٜ9s777�jBQ_LLL�92##�����e���^�zq��iv���[o�����cU�3�O�Ύ;�����ѣ(��6�-�}���[��Ç������>@�v�����֭[K���!��.��		aѢE<��3;vL�ʼO$�R���ё��}��H	

�/�P��믿8w��Ν#??'''e۬Y�X�bs��aҤI���лw�Z'?���3k�,~���-++K����ܔ�EEE�ܹ���2��ƍ			Q{LNN������)KՇ��@n߾�\-..��ݝ���ϵk�

%==��� ���޽{)((���Zc���֤���o�>��mUW+�iY�ھ��������zR�����lڴi�;�]�vBrr2>>>�^��V��J��R�y��Z�j�T���3f�����ÀfRχ~��ݻ���;>>�3g��T�9T!��;IN�������7��������������	&������7/��2=z���Կ�ppp���ӄ��r��&M�D�Ν)..���ӬY�;;;��?��L�0�;vP^^N߾}5�2|�899�ŋٸq#�ׯ*�%�������I(�ĝ�K	!��׮]c���|��,Z�����4k�L�a=�&N��������P9IBԟ��X�b	+++���/���	 **J�O�4�-Z�a��l�–-[022�o߾���1q�D��UEDD��/�бcG��}z��Źs��%77W�c�t邟�O=�!!!���r��A%9e���x{{3n�85jĹs�pssS*W�T%Eݺu#44Ty����dddлwo�,Y���9�/_��ߟ������3���@�MU�ڒ���ªx�t�ڕ�����O?ѥK��Z�LXyY�d	�Νc���<y�w�y��>�H�1�U�=����9|�0/����^�nemڴ�7��7���ɓ�ܹ�?��^b�J�����н΃NNNDFF�y�f��)U+9r�u��1`�233���ի������S� s�BQ�$�QO������c���L�>���8֭['_�!����	�('kii��ngg����ٺu+QQQDEEi�K�.̛7O�}ƌ���ڗ�/��/_�Vոqc�,Y›o�ɱc�8{�,}��eȐ!:t���t��������.�����H�ΝK�6m8t�666��0u�T�N���0�x,�ڵK�!4X�}�ڮ�sA��͹s�\�t	[[[�L�”)S��s̘1�3���LN�8��ӧIMM��ɓDGG�q�F�|�I��=x� >>>���������s����;w*.��������l?|�0���dff���r��N�<	��;w����Ւo��eJ:v�T$����1q�D�����ϟ�za�k׮j}�x�L�4���Y�~=}�����L5j������8p��>�8��Q����7n#F�*�������?`aaQ�ׯ_g͚5�^�;;;8�S��������֭[<x0������i�577�ҥKlذggg���,T[��Ӻ̕��C��u��L�2�/����G�bmm��۷9{�,-Z�����[�rҧO|||�;w.T�SdB!�N�S��G������C)�8w�\�7�BQ]�1���144$::�K�.`ff�СCqqqQ�;�|Ȏ;����q����t�ڕ�#G���u��-Z(�k[��aӧO&M�Dll,7ndӦM�;��kג��Č3�'%%ѲeKF�������u��u<<<رc���Z�J�!��&,�����?~��72s�Lk�I�W�^���WWW���ټy3����Z���+Wj}������?��^�w>����瘟 */�q��u.\Hff��c�.�q�T@U�\�P�ڕ/^߼y�X�*U���ooov���ѣG�߿�ڶ�͛+	$��Ÿ��ҪU+�n�J�&Mزe}����Ņs����O��O���KϞ=�ҥ?��S��Е��';w�$55��Ç+�I^^^������$V�O�̕��C���ٙ��(��°����ѣ���2x�`
�/�
4H��~���-U$s�BQw��"D=stt���B��B[����0\ՠA�4>d��ٳg��;<�u�v�xtm�m2N�~�C[�%K���wܢE			!;;�N�:���͙3gpssӚ�#������3gFFF�ݻW�E������3::Z)�?h� ^{�zW�����5>f�
Dbb"_}�gϞeÆ
���3w�\e���C�RXXH||<:tPۇ��...W�$FeU�F5jTm��K�j�r�J233133c��ᘛ���s��4ϔ��+�...��_�%��R�r�j��Tm5!�֭[s��Q�/_Η_~Ivv6t�Ё��x���p��I~��g�l٢$zu�ڕ�����₇�۶m��?��LJ+W���V;���	Æ
c�����hڴ)���x{{�c����0a�~���\����M�4�O>!##��ݻ�ꫯjT�N]���̕��C��m۶L�<�m۶����,���Jn�dURa�9P�P!���$9E!�


(,,��>P�+{T�����7����P�V���)���z�N!yyy,X����0\\\���iݺ���B���T�����������_�Z!�����(	��߿�-[��$���ՋӧO�s�N�z�-�}����v�P��̌������ٳ���J�*��.T�0����i�@��	PRR�q�TE�|H~~>-[�t�2`jj��˗ٽ{��lIuڵkGNN�nݢ]�vj�nݺ���aԦM>��#>��#�b	.@-idȐ!���O��1c�Z��iӦ1mڴ��Q��������a�6l�p׾3g�d�̙�MNх.s�.�P}�>}:;v� **��G�b``��!C4�����-Y���
�?��:�.s�B���O]B!�xl
6��cǒ������ƍ�wH����1~~~���q��5�]�F\\~~~5�BQ{�O�>�����W_�y�fIL:;u�T�VM�Naa!K�.eʔ)���ұcG�������/���	&`eeŎ;(((�G�XXX�UK��$�U�Vq��E����s��f������U;����|@zz:%%%�;w�>��DZc�(..&++___�=//���z�2��̲k�.
�t�N�U���LJ��,JKK�q��1VVV���+}{��	���S��M�G�x�e��e�6���'�d„	�ٳ���<�����Oh�[�b�{jj*����;�N��*�B���)B!��СCnݺ���>>>4n�X�!�w�����ÃիW0w��אBQ;x{{���=�6m�}���K��XB�aFnn���l߾���0<<<��*�������Q�}���ӧOg�֭DEE���.]�0o޼j�rrrbϞ=���O����K������dzl�2�-[��=++kkkڴi�͛7�����ԔݻwckkKll,k׮e�ڵX[[�zlWWWIKKӨ٬Y3.\��=d�:Dzz�����t@��B�Ǐ.s�.�y�.f̘ALLP��նm[�؟}�Y^��:�.s�B�N*���Q�F�#?�#?�l۶M�Ӕ�">>���d>��c�u�e����Y��5k�(wX
!���cǎѯ_?����/رc�$�<"���������ӌ1B�т�֯_���<x0�ƍcÆ
��_`ee���JJ
VVV$$$���?+++��ۧ�[5��/��၍�
#G��>Шpr��
�/_�ȑ#�����ח����v��m"##0`�����~+++"##�}�v����z�TG���gٲe�����###���quu��S�;�|��������'���###,,,x뭷غu�R�Dccc���?~<O<����XXX�|�r���t~��/f̘1cdd�s�=�|��9s�$OOO:u�D�ƍ�yt�…L�2�֭[cdd���5K�.���-[�$44GGGLMMiܸ1&&&��ڲy�f���ǎK���IJJ��ORR-[�T�%!}5�Ӻ̕��C��hѢ��aô�	���CCC:t�3شiS�c�9T!�P'�S�}eccCtt���B<:w���BQO���O�}�]V�^��ѣ9x� �:u�wX�>���JGqq1���ddd(}�]�Fhh(���1z�h֭[Gff&4o��}����w�)_�߼y��W�bdd���M�q���q��-���عs'eee���	'3g�$;;[y̞={������޽{)((�Z���ښ�������ɓu:VB�{��b���?~|�?h� 
T�ڶm�Q��ڵkj���]���ުU+e���T	*cƌa̘1jۍ�����ۻ�1jJ�111aѢE,Z���>Pq1��ё�������ϳ}u�� IDAT��9s�nnn�<.���+���y���$6�={���խ[7�}Z�n�T���̡B!D�H�!�B!��&55+++6l��
����ĔGX�n�HNNV�
'##�޽{�m�6N�8Att4���#%%���8LMM�׿�Eii)gΜ����```@rr2EEE����_x����ҥ���$''3s�L<�lߺu+��٘���e��;Fpp0.\��Wrr2�z��ئjS�B<�
���;v� //���2~��G�B���?���/�~�i"""����LMM5��B<��\YPP��7����>}�_�P!��oR9E�WG����I�a!���j҄B�p)))��ߟ��kkk����?��ﰄ*/�SS{�;S����ʜ����cǎ@E���'N$>>��'2z�hΝ;ǩS�����ĉ���1i�$���K�9¨Q���;;�c���R*�999J^^��=11�%K���s�`ii�;�����u��y�"ᥪ�]���B<^~�ev��A@@j�ڴi�V��Qdll������W.���űn�:�5k���
EC�++/�caa��q��2�
!����@����;!D�8%�5j�H�!!���C������Ņ���+W2o�<�P��@���r���j�ٸx�"�F�⣏>R]���GӦM����믿��S�S�.*hcnn��nbb@YY���/�ЧO��i����͛@ŒU��T}��Uܷ�~ˏ?�Hqq1O=��f֬Y��f���������ի�;w.���z�Jѐ4Թ�C�ܺu+++|||hܸ��A�P!���$�!����
���CQTw�!*.��t�R�����ӧ��?���DU��WL��^Y�)p��ܹT\$�۷/iiiܼy���DH�6mx���9r�dddЯ_?ڴiS�~�4i���-XW�
5�Q=^[���M��x�����')�1BԤ�Ε���w�S�����B�Ir�B!�B���㏸��r��q�}�]����^��SSS._���ݻ155���1c8s�[�l!??�"�7%%�O?��;w��uI��033�ҥK�>}kkk�]�lPe�ڵ#''�[�nѮ];�m�n�R�!�B!�B�ړo�C�����S�aԋ�z.���?~�A���k���>��ϑ#G�勄x�9::��0�Л��r>��3<==�֭)))���W�a���Ύ͛7��プ�=z��?� <<��[�beeŦM�9r$�W�f�ΝJrʐ!Cd�������s\/��"6l��ߟ�˗ӧOΟ?ϊ+4���ٓ��._����r��e��B!�B!��=IN
��o�͡C�Hi�����Kjj*AAADEEQ^^�믿��������H����J�!6I2����lf͚EBB���,_�\cY�xsuu%11���4���ն5k֌�*�k�KKKN�:EϞ=�С]�t�g��_~���]+�Ԇ��3�����̙3Gi;v��p�2d�:Dzz:���j�T�V�z�1	!�B!�B<N$9E4x��w��>�Kaa!K�.eʔ)ʗ�����������=�!�B!DU���̛7���ۓ���������T߲eKBCC����9x� ����h�KKK����޽�Z�1c�p��)�d"##�eI###���Y�~=���'??��Ç����޽{��;��kג��Č3Զ%%%ѲeKF�]/q	񸑪�B��,&&GGG}��7NNN�ڵK�a!��&�)�A�������&,,���\�M���988�}�v�������ctB!��Q����[o�ŗ_~ɿ��oh޼���zV�g7-ZĢE��{{{���5�===�����š��E�x{{���]c�-Z���HHH���t��	��t������5 ��:w��ԩS��B�h�ԩ8P�a���B�h�:u*�;w�wB($9E4h���ʿ�:uJ�=88OOO,,,شiS�I.U�UGFFHZZM�6eԨQ,X�@��ȯ��ʆ
HNN�Ν;t�ڕ3f���/����~bbb��ʢ������ckk���͛7���BBB����۷祗^b֬Yje�o߾Mdd$PJ^<���XYY����iժ���Z!��RZ�nM�~�pssӸ#�>���j�*RRR�믿pttd��̀ڞCU
-Y�~����ӳgO��t9���?~�A���Bԣ��X�z�-������1b��C�pqq�o�!""///"""055�X�Hqw666����;!�Ո���wB!�xHr�x�r��m�D
]���q��-���عs'eee���p��M\\\�~���/�l�2JKK7n7n$$$Dm�999DFF������˫����www222��k׮Jzz:AAA�w�^


����؏��5)))�۷�ɓ'��x!�è�����������֭[�=��חӧO+W��qU����СC������JPPQQQ�����caaA�~��O!����̛7���p�|�M111�wXB<0�����1�|�O�@\\�֭�Y�fz�N��϶m�prr�wBqW���DDD�;��Q�F�A!�}�X/['IN
Z�*)�.\u�֍��P��"��ҥ~~~<��S�������-[�p��u�}�Y��}ڷo�G}ė_~Ihh����}�v���7n�5�ܹs������T�s	'##�޽{�d���͹|�2�������ĉHNN�W�^�EՖ��,�)B�G^�y����k׮���Gjj*��y�I�u���T$#��ߟ������i�
�:Jm�q?t��=�SXX�ҥK�2e
���@�������ĨUBB�ޞ={�5keee|��׼��+�I��߿?�^���s�bii�稄x�ɝ�B���qO��8q�\�B�G�T�
�$���nI���w�p���\��///�.o'''BCC���S�9r�ŋ+�|||���ÇS^^Nff&�~�-.\��ɓܹs���cǎ@Eҍ��'N$>>^IN9�<P�TSU׮]�!NuY��qg``@�N����˴i�8q�D��QRRT��F���=��q��&,,���\�M���988�}�v������x�1	�0���gѢE|��g����|��'�m�V�a	�W���r�F�z4u�T}� ��ڵk��CЫ�S��<-�B��J�S�CM��QW�����2�eeeJ�իW�ٳg���~�:.$33Sc[yyy���r�
�Ǐ׺��ŋ��7o��U�V�Tm�>B�G�*q%88OOO,,,شi�������o��F���y饗�5k�Z"�jǏ'00����CCC^{�5��ݹu�~�!��I�&6///Z�h�����s�nܸA���1bs�̡e˖\�r�ɓ'cffFll���0aW�^%6633�Z�~7��=�rm�}�hV����a�޽,_���_~Y�g�|}}5j�~.���n��>���D�qؿ?111deeQTTD������Ã�͛�WmIY���H�f�x���;w.M�6U�dd$P[��駟��ʊ��H�O����L!��#G����ʭ[�����/��B!�B!��J�S�^T�P�J�]�,//W��,..���M�4Q~׶�fm��\�r%������1|�p���y��jU.�n�+�+���100��j��A�x�r��m�|qq1���ddd(}�]�Fhh(���i�+W�TK�����ԩ111�~�����o000��w�*�7�|�K�.)����a۶m���J�Ν�����ɓ���ѧO�oZZ���833�:�^��~�	�v��ݗcVoooRSSY�r%���<������@�X�dI���M�ks�7o�������v�7n�HHH�Z���"##��˫��?���=z�HTٶm%%%xyy�w�^


����x���5)))�۷O���.���X�t)��������SO�;,!��9�|�7%��/������	{��/Uk��؃��Y]���T�W��>�z�*���?~����4i�3�<���Ù6m�rs�JM��~��ؕEGGs��q
$������뿡U��@!����_u�!�J����W�*Wѕ���C��/44�0n�8��� �155`��ݜ:uJ�'%%E髺�W����m�.�
!-ݺu#99Y��NFF�{�f۶m�8q���h���GJJ
qqq�HOOg���=zwwwhܸ1;w�$99�9s�K��|��\�t�N�:ʱc�		�cǎ\�x�͛7(	�|�ڸ���L�2�αWURRBff&���<xp���_t���Z�j�{�G~~>˖-����w�}���|���4�@��/R��hS5�ڞ���zΫS�q߾};P�`����ѣG���OHJJR������MRR��l����������K#6U���B�S�Nѿ���	櫯���!�����~''�j�'&&*�?��员���"{<���888͕+W(..&??����������J�����I�cW���JPP�/��ӓ���s��}�%��t}�7$2!��'�SD�רQ#��˹r�
�;w��o�6m�y�&�v�b���\�v�N�(�2���HV�^���?O<��֭#::333���K��ǎcԨQ\�tI��<ڶm�����ٱy�f|||���G��������u�V����%z��INN�/_�HB�|���G��.�j{�����jw�%$$���Oǎ��d???&N�H||<'NT۟��7=z���ёM�6���d�e���ӧ���J���Q*���ۗ%K�������ၭ�-m۶%!!OOO�4iBII				t�ЁaÆ�9������	o���F{}��0`���DDD��or��9x�tڏ6U��y���缲��ÇS^^Nff&�~�-.\��ɓ�zE�����;t��
�ٳgɍ7���ϟ�^V�2ղ�>Bu���>���6���x��%�h���Q�$)��bbbd���СC5n�ꫯx��W��믉��c̘1"4�d��ڌU��Y����|����֭���f����

R�s�����9�Jaa!K�.eʔ)��o�����������#��{�t}�7��) �B�IN
�*����SSSv��]m_[[[bccY�v-k׮�Z�x�
HKK��W_U�6{�l�q���Y�l˖-��OVV���Z����+����������f͚�p�B��!C�p��!��ӱ��T뛞��СC�|�Յw�+W�0~�x���U���Vy�sss�wm\�����D�ʞ�y��+���!&L ,,���$F��ѣG�u�s�̡q��u���ƍӶm[�����ٳ����1���s�r��	Ν;G�n���Sm_]�H�m�Ceu=�թ�_�~�������-g�ҽ{w�֭[PVV��ݼy��ZS��M�G���tf̘����	����,��ڵk�v��wB��!-Ӑ���ɓ'iӦ
���9r�)))���Ri�>IKK`Ŋ<��@�g�����9r�>ClP������U*M888�}�v���4nX�>ܯyZ^��F�!�IN
BMof===��O��ɡ����,\�(,,��ʊ�K���K/�)�v��FPPǎ�����ݻ����ȑ#�~�/������$JKK�ѣ�����������ҲeKBCC����9x� ����h�KKK����.΍;��kג��Č3�bMJJ�e˖�=�N�U�U��|ȯ���.�k�TѴiS�}
��_��I�&�e����kF�A||<jI�;�%H}3}���΃J}�����+W������Ç��ܜ�{N����Uӵůj��B�����իW���biiə3g�jJ��S�DA!�hH���f߾}\�v�&M�`nn΄	4�BBB����۷祗^b֬Y���U�}��������^z	ccc^|�E"##���S�a��ッ�������B���믿�a�����s�]�veƌ����ϱ�����i֬/��"s��U�˫Ɖ��e��ɘ�����	&p��Ubcc133����|~�e�m��믿r��u��J�Ν�Ʃ�Uw.��U[�����ƾ�5�{���}�6���0�:(�O?�4VVVDFF2}�t��B�/U���2o���6T�(�n�:�9Baa!���̘1�%K���U=622���@���hڴ)�F�b��j7��߿������(**�}��������A���e>B!t$�)��3f�F���>���퍷�w���{����;���_c��Z���Ϝ9s�ߵ=�XaѢE,Z���qZ�h���#!!!dggөS'���3g����v7���`jj��˗ٽ{�֪!��cǎ���O�9s��*�5l+�߱cG
Drr2���>|��Ç�}P~��Wv���O�x�"�>�,�un�]΃>?~���Pڴi��K���%%%����v�ڑ��í[�4��S-KT�]��Յpqq���Ӽ��{xzz*���I�dA!D����a޼y���_|����_q��9Ν;G~~>NNN���NFF��ڵk������NPP�]������7nPQu122�ݻw3k�,��Ё��ܾ}[��s��M\\\�~�����ŋ,[����Re�*���=z��(�m�6JJJ���R�׹sg���8y�$iii�R�PQ} ;;��bffV/ǣ�t{֬Y�X��9s�0i�$lll�ݻw����z.jK�sv/�ƨ��ڻw/Z+F[[[���¾}��<yr��+��j;oý�����5k���Җ���$�h���|PTT�Ν;)++�����7�����"##���S��2!�x\ܟOB����Ņ��~����-""SSS�e���;;;|||��ʢ���7n���cee���{��ekk���?iii�������|h.-6y�dJKKquu����)S��-��=�ɓ'ٶm���#44KKK�o��ɓ'�;|�σ�;v���b����U����+���Y҅j��˗/klS�U^�H��Qyy9�ׯ�_�~q��)���Jb� &&���}�!�c#&&�'N�;����B���9v��VnN���R�������A�޽ٶm'N� ::�~�����B\\�~�ҩS��>y�$W�^���B�4faa���W�^����nݺ����\�ܲeׯ_��g�%66�Ç3i�$�"��������h�����<�u,�E�o��F�=>>@��U��Q�����]�:��I����Ą-[�0{�l��[o�Ett�ZE��h��ڪ�9��صU5F]�Wrr2�z��د�M�G}��
��������_~�cǎ���r��1���kLP�ҥ���$''3s�L@}�ݾ};P�8����ѣG���O��*� �B�+��"�C���???�ϟ���Ӂ�R��֭�Y�fz�N����$&&������֬Y3.\Xoc���p��\��|pW�ܹ�F�СC�С��������/�-��9��۷���y��,_�CCC���ppp��w�%**�^˧�z4[[[���Y�l˖-�؞�����5mڴ��͛���cjj��ݻk=Ɛ!C8t����XZZ�mKOON������?��op��!�,Y���o��:���������w�u�%;Tm?u�͛7�Ν;DDDp��%lmm�2e�F|BBP��ݱcG�⢟��'N$>>^c9��T��Vɘ0a�V�⫯�b���svvV[j�ȑ#@�rН;w*�Uw�W��;�Э[7fϞMdd$7n�����֖�mے�����'M�4������:t�a���x�U]�VU����ĉ�>}���TN�<Itt47n��'����U�Em�z��E�u9^�ϟ*.�WյkW�>B�]��j;o����_�T���T������׷��e^^^����ɉ��P�f�ÇS^^NO^� IDATff&�~�-.\Pn@���e>B��!B�����ÃիW0w�\�sB��S]�hٲ%���|���<x���\Z�h���%���t�޽��kժaaa|��$&&r��
ڵk�ȑ#�={6&&&j�
�8q"������k��~����q���_y��/
:v숗��.�X�����<<h�/������$JKK�ѣ��������5���|��'����.��Ǝ�ڵkIJJbƌjے��hٲ%�G��ϧ%�Cc˖-̟?�N�:q��1��rB!���{�q��q�?�ƍ�9s&���j7먪�?^�~.^�X�8�o���Y��5k�h�9x� w�ܡe˖j��*W�^j_ѯ��֭[PVV�����!&L ,,���$F��ѣG�u�s��Q*��x�����\��Ջ^�z)U87o�Lpp0�V�b�ʕw�깨-]�ٽ��.���͛Zo�P����/�������_UA���Wk��;ssss�w�(����ׯ�p�B2335[^^^�~�B�!��IN�!���(w:
���A-ZĢE��]�[�n����ƺ�ՙ3gs�̩v{mc�)κ��q+��X�Bk��+���+��R�j3�Jm�C}�s]�{�V��׺���]Qu��E�8::Bvv6�:u ;;�3g����F���u�[��ݯ��ʜ9s���Y�p!��T�BѠU}��J���p̘14���D���+Ξ=ˆ
g�ܹ�27w�`x�����s���?���={�h�_�RG��ѵ�ǤI�زe_�5#F� >>^�A@�^�ǽ�e�C�RXXH||��2FFF�������k5vuDz��\9/�γ��.cT�.�K��~���x.B�2OWU�y�>_�U_G5�*W���o�ʕdffbff����177����^�k��@!���$�!�B������|�
J�NDD����5	񨋉���ÃV�Zq�����t�0�\�4h�N�
���	�Ǐg���ddd��~�l�B``�r���Ԕ˗/�{�nLMMuC��Ϻu밶���~��Q�͛G\\\�KS�<��S����\�x�g�}V�X�cǎ4���d���9|�0ÇW��{���^�2v�^�8}�4;w�䭷��خ�����km4jԈ��r���7�*���9�����x�k׎��nݺE�v�ԶݺuK�#���fޮ�׿������ٳgՖ�>{�l�cW�w

�M�6\�tI�^RR����Kl2!����ݼB!�zfll���qqq\�v�k׮����T����7o���믿���=gϞ��!�HMM%((�ŋ������9s挾�B�h„	XYY�c�


�ѣ����vvv������Eii)7n���?���
www���Nr��	.\ 33���<Xk��K�.dddp�…c2d�W�&''���"V�\����&M��P7y�dJKK��/�&��r<�.c;88�W�Z�ŋ)..�Ν;>|�ŋ��4�_MT�w��Eaa!�.]"  @�_mϙ��k;Fut9^�e�T�+S�=�����Im����R-����NII	�Ν�>���q��1���������Wi���d>B!t!�S�B!�C���xxx�z�j�Ν[��B<J���fϞ�������I������K�2e��S{{{|}}������X�
!j���4.�U~����Jbb"iii��5k�…��۴i�͛7������TI�6mZ�K 4jԈiӦ����o�]m�o��			����ꫯ�m�={v�]:�:�������Z���x�7]ƶ��c���lݺ���(���4�ץK�͛��]���޽��Xlmm���e�ڵ�]�@ke�ڞ3mc�v���r��¡C�HOO�����T��B�j;o��_���{��᧟~��յ^ⷵ�%>>�e˖�l�2��YYYX[[�| �B�@�S�!%��5������Q�a!R���2���J^^�-"$$ggg֭[�ܙ'D}�u霆(,,���\�M���988�}�v�������ctB��j�o���144$::ZYV��̌�C�����kٲ%���|���<x���\Z�h���%���t��]�����'�|BNN���|������+��端�ʆ
���ok�Xڮ];���

�رcѽ{w\]]9rdmK��8q"������k$��r<ꛮcϟ?���c����{nܸ���!]�ve�ȑ888мys���W\\\c,.�����
���b�ҥ���Kj�j{δ�]�1��x�;��kג��Č3����D˖-�JB�']��v��_�ULPP��Ν;t��
ggg�-[������u��Ŕ�����Dii)=z��ٙ����`��������@!��A����r}!۶m���	�?�#G��n�:=G%�x���(_�999�ϐ�I����B��S��Q�����̜9���B6n܈����C�F��$�U��:5%����̾}��v�M�4��ܜ	&0q�D���������o��F���y饗�5k�ƅ����ڵk����w�qUU��_�T�*�	j�w3��
�ZjY��x���15%/X)�(���P��1LK/(���:2B�r�A������䠼���g�z�um��v��K�.%++�7�|��_~�m۶i����LBBǎ�Y�fO:�BTI]��A�	���ر___�9B۶mHMMe„	,Z�����8�gO]�+���&--���~KKKBCC
�S#���4u��όK2r�x�lmm���5tB!�B<�rssquu��ۛ�'�}�vZ�nm�D����޽{�Ϗ=">>���xrrr��9���899�����MKK��Ϗ�����166�pݒ��׿HϞ=Y�p!'N� 77W��666���p��I&M�T�"�B�0�;F`` ...��$
�i@�x�
6L��4f��6mJJJ
��9}��5p�O��B!����QM��ߏ����ȏ���40�B���ŋX[[�޽{9t�$��;|�0[�n�…�;wWWW<�� 11�^�z��~.^�Hpp0}��!&&F�
֊�-��ˋ��@:v��֭[�!ߣ���޽��:�2M!��Ycbb���;���������Fhh(���4n����	Q�ƍ��
5j`ʔ)\�t�-Z(���+��B<+d�Q#���
���K�)S�N5tB�*		�a/E����g���xzz��k�q��)e�f!��T9O*�t����dggHrr2#F�`���L�<Y�nXXXZZбcG��ݙ0aǏW��H]
///��ߏ��۶m���LYv��Mڷo��O:tЪ#�B<���뇳�37n`���X[[8*!j����ڵ��o��~ ??�^x���3��:��/��B�g�$��1e�C� ��Ŏ9b���v��I_(�s`ʔ)8��a�:��ի888������7.�����a	�X�t)�ׯ'::���h�o��ܹsQ��Zog޾};;;��IJJ�T]��������o��Ɵ��'e���h֬��z�2M!��Y�V�%�^�y������B�~��"�B�[[[lmm
�B�Z���OOO֯_π�z�*�:u2tX���t��g͈)%�ƌàA�8{�,_�5W�^��LJ��/^̤I�(***����l���P��>|���<v�؁����L��el�;���L���B!�B!j�$��:���ղn�>i�₃����`РA2m�B������EB<��j5����C<�nܸ���#W�^��O?e���z�Q[���agg�������:u�={����$�XXX����ѣG���(s{���|�rZ�jŖ-[8w�������sss���������\k���L��B!�B!�x�$9E�*�r�
���<x���"�M�F�.]�ӧ��CB�B����AQ�d&����B�l�ªU��ٳ'��׿���B�V�Ǐ'55WWWƍG�Ν�駟hР�Ro�ȑ�޽777\\\�ܹ3���;�۷�JŎ;*\���3gr��q���ؾ};[�n�k׮��������������B!�B!�O�$��:�<#����Ç�Y��ɓ'+o���۳z�jBBB011��0�ϑ)S�:!D9r��!���?��;����Y�z5�V��~}��&j?<<<ذa6l�Zfmm������ٳg���c֬YZ�7n̲e�*U��z��j�*�͛Dž�z�*���
C�!<<�����:th�w^Qi!!!�A!JR��ۄ��h%!�BT7��)j��L�S����������ӕ�3fp����qvv6`tB!���***⫯�bŊ�oߞ�/ҷo_C�%��������S�~}���INN��ʊ�C�����kڴ)~~~�ڵ�3gΐ��A�&M�����ɉ�^z�RuK�ݻ7'N����l߾�;v0v�X6o�LDDs��ѪAӦM=zte��dd!����9"/d!�⩒�Qkݾ}�I�&aee��Çu��?�;w�p��a���8u�!!!ܸq���<Z�jň#pvv���To��b�ݻǶm���Ç�5�U�V鬛��EPP����u��Jy�6mP�T1{�l�5kV�C!�O�͛7u�����Ӽys���âE��|@TY|��������#�j5�w�*��Ltt4�
��B��s����#,,�+V�~�z5jd谄�0;;;���X��̌�˗�|��j����U�Vi}wkҤ	j�___RSSi۶-�����ƲhѢR�+
!��Z�F�V:!��(**2tB!��$9E�Z�ڵC�R��G�޽�eqqq���2p�@���ؾ};���Z맧�ă�����fVVs��%55U)������ѩ{��	rss����YfccCLL'O�dҤI��e!��q|�����J�(,,��~�̙3��İo�>ڵkW��^��˗/+��޽[��]�rooo<HQQӦM�K�.��ӧ��
!D��x�b��͉��`��I�皃�ǎ#00���Й:H��DFF�e�C�!�Odkk˒%KF��y��d�lmm
�:!ʢI�8v�V�����<y2��Օ��(Ο?ϗ_~	<������Gjj*VVV�ٳ�.�s�Nnݺ�S7**
��ݻ�,Ӕi�!Dm^��K�.)?111|�����ۗ��v��U������}�vbbbX�j��~E=|��5k�0y�d,,,�����ޞիW�����]!�t��]�N��Z�f�̙���Jb�5���wwwBCCIKK#--���P���iܸ����θ}�6!!!�C!��ŋ
�A���H?-�ϡ��n߾m�0�P��)� �M��<::��-[*C�7hЀ�����hݺ5Æ
�ܹsq��u���[nݺ��@vvv��:{�,�x8�={`mm�G}�￯U��͛�o�^g;:tЪ#��o�����ؘ�m���2}��ræ��x|���hذa�����OFFӧOW�f̘�����ٹ��
!Dy����p�B6lȉ'=z��C�N�ׯ���lܸ�ŋcmmm਄�����
�B�j�̙���e
6!�x�:!���)�V�_�>�Ǐ��(�ϟ'33�	&P�^=��s��aΜ9��/��$''�/��КB�o߾:u�߿@�f�t�i�4u��:�c����<x0Æ
�w��ȑ#:usssٺu+vvv<���~���:�U*U���%i��233uֿ|�2�F���ɩB��������ⱹ���R���4���;T*�����iڂ���߿?�[�V�i��JEPPYYY��_!�����L?~<���:���"����j6m�ĦM��1c���B!�B!��sd�a%G(k���'�g����F�����166f„	JOOO�_����Ç�S�N��ٳ�sejYJ&�ԯ��_E�mhl���)��D!Du�f�޽��G�O||<999�>���899�����MKK��Ϗ�������]��?`nn����ˋ��,%!��cquu�ʕ+xzzbmmM�6mHOOgÆ
�nݚU�Vp��	rss����ن��
111�<yR�>N!�[XX���#??����;;;C�$�B!�B!�#�)�ֳ��dРADEE�����s�>|�֛�������ѢEe�x<M�������HNN����Z4tꚛ����Nff��Z�h��
!De>|��[��R�x��ǏgÆ
<xPIN	 11�^�z�j�*:u�DJJ
���ʄ	�t�R��*((�֭[|��g<X�Nǎ���S��)o,��O�f�X�~=��ά]��;v�n�:rrr���������(�w﮳
MYTT�$�!�]NN+W�dǎL�<Z�je谄BQ��7oҵkW��Μ9Chh(׮]#;;�nݺ1j�(Ə�w$]Q>5=�mpp�r�pРA~�MaXe��������<x�333���*M]��[5ѿ�g�cM�%㩎��ܹC@@��Ѥ��ӠA���?3|�p�O��ܛ�(�=m�l�8�	!�Hr�x&L�4���������ɓ�ֻp�������|���J��hٲ��y�������Ã�?��޽{s��M>��S��]�v%==����$�����B���/�%�/]����)������̈#�<y�N���������www&L����ǵF��L|fff̛7O�|֬YZ7�3�����V�	d޼y���3c��Թy�&�)���С�V!��.�ϟgΜ9���o�߿��ӧ:$!�B��> <<\�!]nn.����?^�<..���8���X�v-#F���hEe\�rooo<HQQӦM�K�.����С	!ʡ�~Z��ٳ<x�x���ٳ�3�&C�S����`�rrr����|n޼�͛79z�(���ʋ�O:O�!�.N�CB�M�S�3a�С�nݚ������@�1��Ǐ�v�Z֮]����7�N�PҬY�8u�7o�d�…J�رc���!C�NBB���Z�4#�:��(�O�t�R֯_Ott4���l߾��s�V�iܸ�R����N!���T���իG˖-�ׯ,���B��&��iDzx�b.^�H||<;v���߿@�ی�2M!��������[���7����W_��#��MfΜ���&�x��j��Cz����-wss��nݚw�}�!C�мys~��>�޽{���ٵk/��r
G�쫩�>d͚5L�<Y����ޞիW���I��!����i�������z�o�����P�&��d"Dyڪ�x6m�DNN�ߧcǎp��u6m�č7�V^~�{�ٶ�\��B�$��Z�I$3a�v�܉��=FFFZ�W�\IAA���t�ܙY�f��?�s�N<X�䔆
�s�N�n�ʩS����a��ḹ�q��	��cǎe���DDD0g��e4mڔѣG��!ꪒ�_Y�k�3�A�q��Y���k�^����,^�X�������6���+ߓ�:�:c��u���Xg����D!*�ʕ+̙3����o�΂�Ol���sڵkg��	5=݋>���DDDвeKv�ޭ5����%�������������
�(���?Z��͘1��������T�i���t���{Z�h��~Hdd$111���/��������~�������ӷo_<<<���'22Ґ!�*rB]��"�.�ͤ�f͚���Q�z%�h�Gt�&Mpuu��յ̺M�4A�V���Kjj*m۶ 55���X-Z����wL!*���;;;���HLL�ԩS�ٳ///%9��‚���=j�7��V,۶m#))�=z������7˗/W�������Nff���k���J!�����<<<��_����
�����⋆K!�xn�s�NN�<IZZ
4�S�N�?^g���$r� IDAT�\|}}	��_�U�V���̟?_I�/>�i�G�`���Z�)�M�6���"�u�U����Ν;9}�4��ݣU�V�5��ҴiS���������o��~��L�:'''233����9w�
4`ذa���ФI�����ذaaaa4l�[[[�,YB�V�t�ڹs'+V��K�.�ر��ǩ"Ǿ���=ܮ�

��ˋ��85j�k���ҥK��г��

���Z�M�6�T*����={���6��SS��Fhh(�����������Dhh��Ke�����>>>DEE���M��3g�ƍ�����\6l�ٳgiܸ1���:�/�Q�FZ�>|�I�&aee��Çu�3~�x�ܹ��Ç���*w\Q�I&�H�-[��_~��ݻJr�F�v��)�v.J�U_���ٓ�~R�q��B�'�)BT���ǎ#00���`֬Y�N�?~<������2n�8:w��O?�@�
�z#G�d��ݸ�����B�Ν����	`߾}�T*����EEEܾ}����Y�X���g�����Ӈ;v���́:t(����k׮�������������k׮ճ�B�:�ƍ̞=�k׮���ɒ%K��$Dm5u�TC� D��V�	4t�4ooo��ݫ|~�������Ǔ���LU���������Jݴ�4���HHH��ۻ��v||<�x:��4i҄y��i�egg3o�<�������t���OLL~~~:/1yzzj=�ܵkm۶%$$D�?//�cǎall̺u����ϕd���<�?Nll,���i���"++Ky@V��T�c_�z%U��-Z�Hy� //�C�QXX���'N� 77W�H�666���p��I�%!D��T?
�G��ox���SJq��Q�ϟ�w�ܒ}��qpp��ݻJ���$֮]���l[��Օ��������OAA��l@�]�v�T*���{����ݻ��,..���T���U��ʪh������O?e�…L�8[[[z��u_��J����9���\;�:$���T!����wwwBCCIKK#--���P���iܸ���B<gذaÆ
c��ʍ7kkk����#:t ..�Y�f1p�@Ǝ˾}�hܸ1˖-S�h�x<�iu~y�L,呕����;���|���ԯ__��n�:������HNHH�ن�l�СU�;!D]SXX��͛����^�z\�|��K�Jb�x&RTT$?�#?5�V�
�_���I�غu+.\�ܹsʨ�T����H�^�ؿ?/^$88�>}�Chh(����K�����PF�-��{����L۶m����…���biiIRR�w��Y'!!�p��y�������իǡC����RF>w�����lٲ�.��燥�%w��!  @�nǎ�����?��q����֫�c׾}{>LTTs���̙3��(�w﮳��LSGQ=j����/.ݹs�.]�йsg�t�B�.]�s�N�#�������ݻw�ѣ��ܹsL�8???����7������P�j)��I:8v�V�����<yr��GI*�J�OET��'��ၙ�{��a��>�w�}���`���e�?�=�U�s���˫*�N�	!�~rU�*�ׯ���lܸ��7�x�b���BQe}a���g�ڵt�֍�
ҰaC:uꄣ�#�ׯW�5m�???�j5ԫW333F���ݻ�FY�bm۶�^�zZ_ �KEb)�
6��/���₥�%�x�w222ذacǎ��Ԕ���mDDDдiSF�]�B�?���F���Ņ�>����H����BQ1�=P�W�9#00���`~��7&O�̥K��������A�.]�W�;v�����C��ԫWx��Z���nnn��ݛ
��+��j�*N�>�����+�;w�aÆJ���_V�ZE���iԨ�g��7=i�mllhР�{�V^^��t֬YZ�
T�8��ؗ�^u;ڵkG�F���<x�,�y�&�8���:h�B��6�Ӏ���/Z�?����Z�z%����HV�\I�v�055��͍K�.��Cg��>���;bbb�L�Ij,iĈ�lْ��0=z<�6,,�֭[3lذj;�U��njÑ#Gطo�*����<==Q�����j��(������ʵS�CB��L�#D5P���&��F���agg��zfff,_���˗�Yo̘1�3F���o�U�������e�~�)�~��N�7�|�7�|S�ܤI�j5������*o=���ˢE�t��B}����ꫯX�b�۷��ŋ�����a	!�u�ҥKY�~=���DGG�}�v�Ν�Z��������~oJJJ*��֭[���?���Fǎ��)**"''��M�*e������+Zu57ܹsGg;œ��?�ԩ�򻉉I��4H�s�>}���u�j�iT�8��ؗ�^I�9vŏ�f
��	E����Y�f:�j�4u�գ��鬬,%imӦMlڴI�Ι3g�����A�/��/�}y꥗^R~o޼9Pz2c���?~<���DDD0j�(Ο?Off&.T�!+{<*;HqU9ݻw�{��8::�����ݻٹs'_|����Ol��(������ʵS�CB����"�B�璃�mڴ!00P)��‚Y�f02!ij"--�q����쌳�3�.]��!�y���}	V�r����e�B<�4#G�AR_��1c���oY�v-���
yyy���0n�8:��[TTTf����e.�ݻ7�ϟ/�εk�9r$������en��X5j����S֯��ޡ�-}�|;�"ǩ�Ǿ��ʫ�cנA�w###��2}�BS�o=!����O��wO�����/�}��Nyɾ���@EG��8q"���|��7��5����0a�R��ǣ**�СCQ�Tddd��kذ�2yttt��.�X�I�y����ImhT��)�!!��OFNB!�s���www��}e(���P�l�R�[{B��ŋ177'""���:$!j�>�����jyc�Ъk_�\����7����iӦѥKe$!Dՙ��)�I&&&r��)��ك���&M��‚���=���E��x�78~�8����7��-[j-/,,dǎ��o*o�[ZZ��?�������J\�-..Nk��+W���/>q݊�����+�i;sss���������\k�f����B����~Z3�ϖ-[����Y~��y�,YBhh(�'O.s[/��?��III��ѣ±<���%�
"**���Ν;����iݺ�R��ǣ**�v��ݹ|�2���w��Y����?��$###�����R�sV�6JS��%�!!��OFNB!�s�_�~8;;�q�F6n���ŋ���6tXB�Z��ݻL�:�Zʹiӈ����!�7tզ:���Ç�Y��ɓ'caa���%����^���VC�B���ǣR����Nnn.�;w�K�.��(#G���͍7n��p��=�����R�prrR�j�X��0x�`������_qtt��ɓdee���#�]��ҥK���fȐ!Z=G����qqq�g�}<~㼺}��$$$PPP��+W���`�رO\�"ǩ�Ǿ��Jz�N3݃�aiq����B���&��[�nq��u^|��R��
<���ۓ��ȭ[�ʌyȐ!lܸ���t������D�R1q��J	m�&M�?�P��)�0S��Q�*��3����/� ))���|���9w�+W���&�Ζ�E�9r�����̆
t���k��m��"�K�CB����"jDHH��CB�b!!!L�2��a��Z�F�V:!�3 44��ҰaCN�8��ѣ
��y�y�i�'##��ӧ+e3f��������l��x>888���
t$O@wtt��ٳ����L�ٸqc�-[�|nѢ�������=
��
x��w���êU�tb9r$�|��p��>}�۷o3w�\���ڵ�)�-[����Q��G�L�6��V�8��ؗ�^IO��
2���pt�NHH�NuYM��Ç`���N�bdd�������	

�>(5�w�y���0���x뭷��-X��|;�C��u��ddd`eeŀ��W�xT���=r�HfϞ;}�8x� ��^���Y�d���>#F�����l޼�͛7����L_��m�49^rB�$9EԈ�S�:!�B!�z���>�w�������o4o���a	Qk�B�x��;w�b�
�t�Ž;JMr)Y�����qqq4jԈ�^{��K�bbb����/����CTT���t�Ё9s�0n�8�6N�:EHH7n� //�V�Z1b����155-u_rss�%,,�_��V�Z��o0�|��糲�

���ZC��i��JEPP�gϦY�f>�B�5e%����S�~}���INN��ʊ�C�����kڴ)~~~�ڵ�3gΐ��A�&M�����ɉ�^zI��b�
�m�Fzz:���Jy˖-ٻw/������~��ȈA�1i�$��͚5��ߟ/����g�r��=���y��WY�`fff�q��xyy�n�:���iٲ%����NU�������+�i��cDzy�f"""�3g�ֲ���6m*��BT�!�霜���[���x��7ˌ����LJo��V+Y�$sss�����…�����K/���ȫ��Z��R&ccc&L��Ν;����I����nm����g�����ڵkܻw����ӡC^}�Uf̘����R���>˖-��ؘ��0>|�J�b͚5���Z��{��]�6��x�uH!�3****2t��~fΜ���BT�̙34p$�W�?��Q��C��y��ӧO3w�\���عs'vvv�I�jgddD``�2�X�ϥyRRIqœS�u��͛7y�7���+��Ҽysev��'�������Q��ܽ{W'�u����o�}�v|}}��۸q�b+�/���̟?���D�����c��3%���gÆ
,[�L�.h�y�f>��#&M��7�?���KF�*�;v���ˑ#Gh۶-���L�0�E�1�|G(j���_W��C!D��uH��ߋZ撌�"����H�l�b�0��[[�2�dB!�Snn.���x{{3q�D���KZ�je谄x&OD�`�cǎ������}}ڷo���;/��������q��%9eϞ=ܽ{�=z��V�Z�׿�������)�)��Օ��~###���Y�he�K@@�����ՋU�VѩS'RRR��� &&���P&L�@TTݻw��MYTT�$�!D
spp�رc���<N2���Й�A!��nrB]��"��۷o”)S��		�A���F���:!D��5χ.���ݻwٻw���o}�OzS֬Y�NLpqq�]�v��7����x��<22��+W*���ܔ��s��QTT�����o�u���=���e���������www&L����Ǖ䔛7o��jJ�С�V!�5���www��}fϞ
@hh([�l�q���N!��N�CB�K�SD�6tB�Z����ϳ�S�:!������Y�n_|��G��̙3�кB��IȨ�N�:)����PXX��ݹs��]�����w�l�2�_����IS�ܾ}�ԩ�������߿@�f�t�i�4u�BԬ~������ƍX�x1����J!D]!�!!��&�)B!D
P��2��B�իWqpp 99,X�������V)9"JYS����QS�����w�����_|D=}�O���ӓ�ׯcee�����ԩ={�,W��W��������X���L�!Du�h�\��q!��$�!!��INB!j@dd$[�l1tB�j`kk˒%K�(���<==Y�~= 66��;:,!�###�����ɡiӦ���#��/��O?���D�=J�
���-Z� 99YY^PP@���o�XXX����ѣG���(3sss���������\kYff�RG!�B!��.�}�G��J�ҙ/���f���,_�\�1B�}�6!!!�CQE!!!\�x��a�r�q����|��'|�駄��Kb��D3�f���hC�9�ÇINNfÆ
�n{Ȑ!lܸ���t������D�R1q�D��.\ ??�7n�z�j�������ȑ#pss�ƍ���ܻw����o�T*�������RRRt�֔=i
"!�B!�B�睌�"�>�����*�z�����9x� EEEL�6�.]�ЧO�j�T��5!�m3g�4t����زe}�={��_��W��+!*�E�ܿ{{{,,,8z�h�uG���Çټy3�7o��Ʀ�m���;����[o���l��Z�?~��kײv�Z��ܸq������ٳg���c֬YZ�5nܘe˖)��Bxx8			:��'$$0t��J�B!�B!��@�SD�R2	%<<���|��!k֬a����p����^����LLL�܆B!�(����ΝKDD�W�fժU�N�!�([YI�+V�`۶m������_�v�-[���1aaa<|��JŚ5kx�7*���9���x{{s�����x饗ptt��W_U�\����"""��?�ܹ3�f��~`�Ν<x��ҴiS���صkgΜ!##�&M�`mm���/����رcټy3̙3G+ֈ��6m��ѣ+��B<o4#	!Dm�V�
��̜9S^�B!�S%wiE���j��#����?L�>])�1c���gggF'�BQw����|�r���?s�����g萄xn�3�1c�h���}���WWW\]]ˬ_���---���(3�f͚�Zg�…�����L���,M�4A�V���Kjj*m۶ 55���X-Z���i���ygkk+�H
!�	�ڵ3t!}�B<�h��P:!J�w�^T*���Z�111�T*��´����P�T�<y�J�J����ˌ5J�\S��]�x9@nn.[�n��Ύ����o����F`VVAAA��ߟ֭[+�mڴA�RDVVV�!��.7o��)�����ѣY�r%III��^�>W��_�JEzz�β۷ok��/���IMME�R)od�k�2q=M5}^ʒ���ʕ+>|8666x{{W��+�䦗�niii���[,\�����KS�5���6m���baa�3-�B!�B!D]$#��Zk���lٲ��ׯ�����iv��I���*C#߿�;w�аaClmm�mxyy�����8�$���899�����������GBB���?��:q����z�K���!&&��'O2iҤ�!�x
>������5RUaa!���gΜ!&&�}��U�
���W\�=8w�����i�FkYdd$
6$??���(����\�vM�Nu����yy�իWs��e��ݻw���+W������)**bڴit�҅>}�T5T!��wߥE����k�-(�5���www��}fϞ
@hh([�l�q���NË����"���Z��lZWL�:��!!�xJ��u�v��QkYXX���/Oll,666p��i������"//�ƍ�������K�ر#~~~4l�Pg��.]�;�P@@�����ՋU�VѩS'RRR��� &&���P&L�@TTݻw�پ�,**J�S��Fxxx�ˋ�����������Ε+Wصk�q��W��={*�)�F��Z�IN�9s&���DFF�$�h5�)%�>*��R���I���ؾ};������ww�Jm��Ç�Y��ɓ'caa���=�W�&$$��
[�1���g���<x'''����4ib谄uX�~�pvvf�ƍ,^�kkkG%D�RTTd���Tu=�N^
!�������!�E��Qr����5#�h�]�x�0~�x�����䔑#Gj�3k�,��)e�L���A�.]�W�;vT�?~\�����}��:��С�V!�x�Ӷm[>��C�q\S4I%�G���Ӯ]�rSSS�y�LMM���љv�dr��&�KAA�lll\�kiq���ddd0}�t�lƌddd���_�XE�t��1z��EDD�}�>>>��"���j5�6mbӦM̘1���!�B!�B���"j��] IDAT��^{
###%9��ɓ4j�ggg4h�?��O�qr���1Æ
�Z_� R�o����N+QF3ZJRR�R����4k�Lg;�2M!����w�v�ZF����5k'O��I��I[�n��Ύ����o��㣕��/�<4	x���Z�N���ɉ#F0h� �z�-6n�Hnnn�����e�ڵ6�1c�������_�I%ׯ_�Z'&&�G�1p�@LMM4hyyy:#�ܸqCk;�ۯJ\YYYlڴ�7�|S�w///�����v�+Oi���/_fԨQ899i�ד�������Zqj~wssC�Ri%l|��w�T*\]]��D������kӦ
*���� ���ʵ�B<x�����[o�ꫯϘ1c�B!�B!�B�'�i}�A��^A��:���
qqqܿ��g�2p�@Z�hA߾}���$77���D���C�-�̛֭�Ob���G�pX�ƺy^�22KQ999̟?���Y)�q��V�ҩ��������(#iii�����������~��~��G��͕��۷���U/==��� <xP�if\]]9�<�8qb������B���i۶-������OXYY��NmȐ!���r��i"##���Q������Ғ�͛Wxˊ_�͛Grr�־�߿���������{Z�
///�������7���ʕ+W�����ښ6mڐ��Ά
hݺ����ĉ���*�8bbb8y�L'���ٳ8::���C:�3��B!Deܼy��]�j��'a\s��=���q=�f]�N�Zf��l�������`РA��B�F_?�q��BCC�v����t�֍Q�F1~�x�/��ueK鯅B�9E�zcƌ����={�������-�d^^_~�%���:S�T���G��ҥK:?111J]����	/��P!�$00���KKK����p�;w��}B#  ���Dz������x�"�����Ӈ��BCC훗�>�,\�~�O>����+�8<NR�����|��DDD����~����`"""�)_Μ9�,�ٳ'�=�O��!C�`dd�L�V�~iS�T5��{����L۶m�s��닥�%III�޽[o�����ѱcG����$��)o<͚5c������v�Z
Y�n999���cff��|u��]g�2M!J���C�-[ƫ��J�~������!�BT�>���3g:���ddd:�*�r�
��ެ\��+V�u�Vbcc
��RZ?���˒%KX�r%ܿ���|���ؼy3�Ǐ��ٳ5p-V�5O�k!�5EFN�ޫ���ƍ9t����2d������#F��𶍌�(**��۴k���#G�{�n���pqq�s������o�>T*;v��k׮��������������B���$C���ѻwo���Y�z5K�,Ѫ���������www&L����Ǖ�ɞ��7��̘7o��ܹsq��u���[nݺ���3�Mi>��#:v���

�޽{���ݻs��I;v,������ȠK�.��O'v�֍�ׯ��?��/>19��q�;7���
�V�������8;;W��Ҕ��h̚5Kk��7�ѿ�j5���̛7���xf̘���:7o��7Qq���4u����ŋ8::������?s��1tHB<7fΜɑ#G�uBHHj���a=����\^��I��&���xzz�q��j�vMy��!k֬a���ʋ`����^����LLL��YPZ?������iݺ5�.C��y����/>|��{����k�.^~����v*�XJ-��&Ir�����ͱ���ҥKt��U5�}��������[�n�NѢE�߿���==zGGGΞ=K\\�f�Ҫ߸qc�-[�|2d���$$$`mm�U7!!��C�V8.!Dݠ/�@scS��ַo_��%��۷o`gg������J�W�^=Z�lI�~�X�`�V?{��]�-[���u�{��h/���f����B����)��Q4I����\�~���H^|�E�]���~E=)���T�qBJq�su�ΝJ�[^e�
M���7�x�b.^�H||<;v���߿@�P��2M!����g���xzz2r�HN�<�L�%���)S�:!�)S�0p�@C��Lx֦�yZ����ٳg9s�L��\������PF��1c��߿���5�6�ӑ��DDDвeKv�ޭ5ʰ��%�������������
�@�k!�5I�SD��?fnjåK�t=lmm	

���+V�m�6�������iӦ����k�.Μ9CFFM�4���'''���cǎe���DDD��AӦM=zt�bB�M�022zb���;�	��悧�'ׯ_��ʊ�ÇөS'z��Y��h���O�n�066�ƍ*ӿ�KN�ꫯ���dƌܺu###�S�TG\�)��RRQQ�r�4כ���M���P��F*B���ƺ3Ij��u[||<�g�&))�-[����$�N��f����A!*�����;wr��I���hР�:ub���:�������KXX���+�Z��7�`�������_�����[�x��裏�>}:_|���Դ�N�:EHH7n� //�V�Z1b�����u5qFGG����7�|C����:u*NNNdff��s��94h��a�pqq�I�&ޏ��,����߿��C�6mڠR�

b���z�؅Ϯ�ꧏ=
��ٳ�N
0m�4����֭�VyVV;w�����ܻw�V�Z1j�(.\HӦMuګl�Y�}����� �������Q�F���k,]��R����B!j�$��g���=���:�+V�`Ŋ:��(Y>f�ƌ�S��̌�˗�|��2�jҤ	j�___RSSi۶-���X-Z��B������VVV��?���իZӤ\�zU����)))=z�R�HUFtt4~~~�h����deyAA��W��SSS:t�@rr2������cffF�^����у�-[Kll,���t�������������j������9�L�������(%U�l۶���$z��Abb"���Z�Nsss������ԙ�.33S�#���ƍY�n�����իt����a	�\��/!j�f:DQy����ݻW����#��㉏�'''��3g�������������#!!ooo���OKe�i׮������ooo\\\J������*KOO'((����k-���������]�vѶm[BBB����8v���Ƭ[���q��	rss���щ��Ɔ��N�<ɤI��<vB�gKM������Q�KӤI�i�����7o�����t���OLL~~~:��*�gVu���E�)�Z���8t��������z���BQ�$9E�*rpp�رc*7���ЙH!�k����?���>�O>�[�n\�~��>�L��ȑ#ٽ{7nnn���йsg~��wطo*��;v�K��}�6�ڵ�r�.\��^#99Y��hٲe���ѣ�����RXX����Ηo###lll�?��=��j��G��h�n=`��2�f�I��V�	���ya�Z�RKM��#���)%5
H(���-D."�	���I�vEC��g��d2�M���s<c>�<��7a��;7��,����͍/����� ��׿fޛg�2,�m�6F��ŋ	��x�Òk���=ʦM��۷/�֭��ߟ͛73h� ���@Ϟ=���%;;�l�a骞={V�AJ�v��Y|}}9v�˖-c���5�i$Ryxx���m�0D�Cg�T��so���899q�����&**�x�7n�HVVO?�4.�k׮dggDZZ���xxx�����YOJZ����%)o<�M�8�ݻw��W_�ꫯ�
�7ؼy3���4hЀ�'O2}�t��gff�y�f:w�̆
X�n�����у����:�~�zBCC9t�P���0�eI�Yʒ����)򈩩<}��㍢�a�Ο?O�N���_�J�^�������ܹs|��fK�T4gV�����ܹ3���<�������Y�hQ��R�ZDDj���TR���	d֬YL�0���XV�ZE�fͬ���U�Ǐg����dҤIe֝4i���ddd�
�k֬s��1>7��������8����܈��cɒ%,Y��l��ӧqqq�t{O=�;v��ȑ#@�wŸ���c���Ҍ�+Ke���\�p�ɓ'�lspp0)sssc�֭|��G|��G%ލRU�Ki,�F�#//���@Z�h���O�F�䭷�b�ҥDEEѺukHBB���8::��#33�l�>�_���		!  ��={���^jNj�T�ѣG3z�hk�!R/l۶��!�Z�
�(^���N�-�q�����?777������2��o�>����ر#]�t!00���JR]*O�F�X�x1����_�Edd$
64�w��!���8u��v���ٳ=z(y�΀��w�ܟ�gݺu����,\��Ν;���

5ށo�q�9s���=��&uD�v��y�aÆܽ{���Kr��A-ZD�>}x�gX�p!�ӟ8p�����ʾ�"�h����ƏOxx8ׯ_/�(_��HM���*Я_?���Y�b3f�0��D���	

%$$�C�q��
�t邏�K�,1Y[�U�V�����s��A.]�D˖-qtt��Ϗnݺ�Λ7�O>����\


*���),,$11��w�ҽ{w|||��

%**
�J�׻wo�c�v8;;ӨQ#
��N�L\�[�&""�O?����x�\�B۶my��:u*���ƺs���Ɔ}��q��-���x�x�W�,���)���`~���-[f���cǎ,X���K��|��#�裏HLLd�ĉ&�HLL�U�V���KUv�R����L�4�C��p�B/^L�ƍ������R�g�fٲe�������ڵk�<y2���&7]�pww��c�2��̐R���ӧOF��W_}ŗ_~Y��/_fΜ9�:u�l[QQ�Yك3>�|Ń�)6o޼R�q��U�N��uD��QSy�}�����O\�x�.]��X���999��)z��g����SќY��W�=�O�wS��|-""5M�SD��������*��㏛�Jr��EڵkgRnkk�ܹs�;wn��>|8Ç7+��K�֭[T�iӦ��^im�T޻w�r�֪U+RSSK�^|����c��e����`   ��xʊ�4e�/�5R�~,�������k���k��-[���ۛ��0rrr�S����p��q�O�n�����ׯg֬Yt�ԉ���R�������[f���>(::�����3cƌ��xE����-�wz���8;;�7�|É'X�f
7ndƌ�%J��f�N�����3			|��g���fۗ/_ΩS����gȐ!t�ڕ޽{���6mZb�ÖT��84hP�>
e�:"R���<ݧO~��'���K�����oӻwo���J�yʠ�͙�}}E�у7{�7�*_��HM���Zh���������iժ����o�uW�Hm����Ν;���4扌�����l�!y���/L�6�;v0s�L>��C-�("���#$$���(���;v,=z�o߾�MD*���www������b����_���+W;=������f������Y9���ӲeK�ϟςJ�A�0/<<�6m�p��y���B5��W��G۶m����ڵk�m��d�aي��"�h��<��+�Gdd$���*�?���{��n�:���x�׌S:v��?��O�?΀���?n������2�k�i��)"""5��W_�/�2l�0�{�9F�Mzz:mڴ1��D�6k޼9������r��E.^�Hll,����P�������Os��I8���_�K׀��(==�RKiܺu���{///����ر#���,^��[�nUa�"R�F����_}����t�ޝ=z�w�:�E�q��i�޽˕+W���qrr����X�p7�a���`I<�6l�&--��:)))p��i/^l,�~�z�ˎð�Evv��~e.u!"������?�<������L�4��{����ǝ;w����={6���8///�����

"##���B222���4hP���
��ώ�J:���""R�4s���H-�`�صk?��<��<���L�2����[;D�r�ׯ����X��3f���h娤����o̘1�-[�0u�TV�XQ�z�"R�X��Nm��K�7n��쭷�b���DDD���o��D��|}}	

"88���`�m�m9i�$������0���Y�f̙3��M�6\�zOOO���ؾ}{��mI<e	 ==���|�r777���X�d�ٲ��O���ť��Yr$!!���L���333���	,"U�&�tpp0����o.\h�СC��_�j�$���/�…L�<٤����Y�5U�gǃJ:���""R�48Ej��%���v����
���:/���\?�޽�)S���/�l�D��.\���Q����g�֭f�G���?��֭[���g������p��in߾M�v�pss��ߟ-Z��FI�b�\��'�|BBB�n�bذa%vD���e����o2��C�899�e�&L��Ar"�TY��<==iԨ����ek���4h����z�Z�"<<��?���r��%Z�l���#~~~t���Xw޼y|��'���RPPP-�dI<ei߾=3f�����I����),,$11��w�ҽ{w|||��

%**�J�Xr#F�࣏>"11��'��'11�V�Z��K/U:&�y�%O?���lذ���h���[~��4h���3�F���3��u��DDD�駟ϕ+Wh۶-/��S�N��ֶ*NQ���ώ�t.��ED��ip�T+WWW��������ADD�H^^�����>c�ر�Y��6m�X;,�899q��Q222�ӧ�q[FF9990{{{֮]KXX���sssٲeׯ_��/W�yyyL�<���c��ݻ�y�Y�={����_bG���iii�ݻ�Q�F���E�qww�����lmm�;w.s��-�����>|�Y�%3F�[�k����;v,cǎ5)kݺ5AAA%�p9��mIyy��e˖x{{FNN�:u ''��Ǐ3}��R(�H�VSy�iӦL�0�	&�;��{��`��2�U6g�d�-�>K:���""R�l�������<:x�gغu+QQQl޼YSD1��;w�4)�������͛7���HJJ"99�O?��'fy}�����`oo���III!44��gϚ�MJJ�W�^f�e�:""R}|}}�С���Ʋ��H���̖��Q�����S�Z>|����[;����M�	�����,\���?���_���P�x�	k�%"0,�����T�q���Ǽy�hܸ1����۷����3x�`:DQQ�N�b׮]�={��G�p�ƍr��…�ݻ7�����/a֬Y&uϜ9@�Ν���O����Ӽys�5k�qV���XV�ZE�fͬ���(_��HM���EEE�ADj��4��A��AD*�����!�:�������Cxx��z�"��iԨ#G�$""���D�
Frr2׮]cڴi4l��˗/3g�N�:e�K�G�駟L�x��g��^�z���Eq�2C�^�����ߟ+V0c������|-""5E�SDDDj���+����CD������C�5�ܹ�����ٵk�ΏHV|]zÌ)%�c��o�~�zv���aÈ�����c��˗s��)���2d]�v�w�ތ3Ƣ�Y�hi��+
�@`�U�
e,,"Rs���5�[D�P�����)"""5���A�"�H���d�ĉ�9s��+W�?�I�"�Hǎqvv&))���L:Đ!Ch߾��Njj*���i�������8��8{{{Ο?ϱc�pqq1�gff��m۶-���\�v��mۚl�v횱����������,�[�D���Z�<::��s�2w�\͖ """��{��|�r���h֬Ǐ�������C�F���ݻ�
!� IDATL�4������J����BAA�O�f������ׯ����_~��� �;Faa!��=|�Yݞ={���m��Pf�#""""""""5G3��Tл�KBBB�S\��w���EQQcǎ�G�����
���5��V��W�����o&M��ѣGY�l��ͣaÆ�KD�dРA�oߞK�.aoo�s�=g���͍��8�,Y’%K�^��i��PJ������9s�ӦM3��1�l��IHH 33GGG�m��V
T�c����)"���Pb��[�x�������OOO/^LLL͛7��0E�J\]]5k�H=Q��***bݺu̟?�nݺ���F�>}���T���?���BCC���4�;�|
ILL��ݻt��~��BCC���*��&M���իٿ?7o�dȐ!,Z��={���1b}����L�8�d[bb"�Z�⥗^*���6f�k� "R����zu�Aq�Ǐg۶m�CDDDa�"R�"""�t��ƍ3����[l޼�����������z�a-"����w�y���`��.]J�&M����ӦM3���A�[�&((���SҠ��-[@@@@�u[�l���7aaa���ЩS'rrr8~�8ӧO�E�?0�R�=��a���i���0��aX�r��ȣi���꧐ZE�S�^�w�����ݻ��/Ҹqc�v��ȑ#���0����OXX�����_�]�v���+L�2�����d�ox���N^^[�l����o��X�C�899�e�&L�@�֭k�EDDD*��/����3vvv>|��~Q+"u���/;w�$22����>>>V�N�~ruu�����a��H)4������
N�z!$$�
6�߹s��'Or��In޼���(((��Ϗ��,c݋/Nff&!!!��ؔ�Ξ={���/qjj���ػw/�F��£�Z�.]��#۶mc�̙iiB�3�7oN`` �f�b„	��Ʋj�*�5kf��D�M�6�{�ͼ������v5���""�舌�����I�)R/lݺ�իW���ĝ;w���#88���(�$7n$++���~��ҵkW���	

"--���X<<<HOO7�1� ))	�^�z��`(KJJ�����n����G�7oη�~�СC������뇿�?+V�`ƌ8::Z9*ѝ�"R��At�yČ3��!�����Z�h��7����󸹹��兗��I�}��Dǎ�ҥ���xxxg�ЃΜ9@�ΝͶ=��&uDDDDj��~���3g�q�F�y�V�\�������0ooou���2�G��v""�ڶm��C��ѣG+O���H����q�G���#�a���,[����TRSSY�v-�'O����dZ�.���^�~Ν;Wf;W�^�u��f�e�:""""�ž}�x��w�;v���^�vH""""""""""��������3���|��7�8q�5kְq�Ff̘a\f�����ܸq��통9mll̶ʴ~�����7o�d����[���c���'���[;,�s��z��i|^�2�ŕ�Nu���K���8k�����/s��ulmmٽ{7M�4��v�{�k�)�U���^T���hRSSpvv�RR.���-���te(O�Hu���q�����www������b����_���+W���ّ����۱������mے��˵k�h۶�ɶk׮눈��X��Ç�4i����7of�ر�IDDD�F���$$$�ڎ<)���x�_����׉��g���V��n��ߋ�������(**b�ر��у�}�Vi;�hQ�~t(OW�i��48Eꅑ#G���C@@���*ݻw���q���zC��/�`ѢE,X���ݻ���e�ƍ|��899�n�:�(EEE\�pz��Inn.���f�P����uDDDD���ۼ��{�\��W^y��>��B�rE�n���1�_HD�OLL�G��vR���k�P+��N�o����_�;vk�NϚ<�U�Vu�^ܺu���{///����,^�����7o^�mʣAy�d�ӕ�<mJyZDj��H����KPP����lstt4>�4i���ddd���cR�Y�f̙3��M�6\�zOOO���ؾ};$!!���L��dff0hР�><�r9v�&Lয়~"44�w�y��!���l۶�m۶Y;�^�A���\�=J�6m����r��a����_x�'��\�t�q����z�-6o�LDD���V�N,�<-�<]�)O�HM��v"5��ӓ%K��?��&M�ФI�v�ʤI�X�l��^�V����;;;6l���-nnn|��&��̛7�N�:ѰaC


1b-Z� 11�,���DZ�j�K/�T�,"""���B��}����С�"R��G?�����Hk���y���cݺuxzz���3x�`�~������z�j���y���y�7X�f���W����+�<m�߿???���pvv��_gŊ���Իr�
�>/��...,^�ج�����رc6??�
oY������������V�\ɍ7J�Gaa!˗/g��6�8k�k�X�p!���:��K�r��M�Xbcc�w����
͛7��_�޽{���Z�/���ҥKy��qvvfܸq��ŕx����,Y����3|�pV�\��n�΅�߿?���%�g�ȑ����8ó%ב�1�;w\]]y�����u떱N�>6�����3d�<<<�w�I;.\��ɉ�#G���-[�пڷoo�סC���زeyyy�>>�>�i�i���Q���@3�H�����C����2w�\�Ν[f��Ç�M;ײeK���	#''�N�:������Ǚ>}:-Z���A����X(++___���{�/_άY�hР���+3f��C�w\]]�9s��è�BBBذa��;w8y�$'O���͛�?���������2ֽx�"���dff��M�ޯgI�k׮%,,����lٲ��ׯ���;�&O�LNN����ݻK���1�\����<�N��(��7n��;�p��y��۴iiii����}7�|�r�n�j|���өS'bbb��t��mv�܉��
K�.5�-**bǎ�������l���ۙ2eJ�����ի���r��ec�s�αd��޽kܷA@@������M�6QXXȂL�988����ѣG��ȠO�>�m���0`����k�ڝ>}:׮]�ׯ���{��hѢ���p�\]]8p ���|��&ߑ:t����g����qqq1۟��iii�ݻ�Q�FU��ĺ��������EDF3��T1___:t�`rWTdd$vvvfK����T�{��b�
���GÆ
9v��g��!&&���k�!Ro���p��k�Q�:�V�^MJJ
�"  ���(c��7�����O?ͦM�8r������ۗ��4�]�.I���n�D���~�+o��7o�w�%%%���̧�~
`2�_~INN����_����BCC9{�l��7�ҥIII�N��{I��gÆ
�?�N�:NJJ
aaat�ؑs����_��#33�͛7���l�C>88��
��_���ĴiӀu�=z����=zн{wz��A�=���K]z�x��ׯ����<��Slݺ�C���on���~����h�K <x�Ķ�y;w�4)7�����T�}ˮU�Ν;�u�V����<y�I���x�?�-Z�����Ȱ�yRR�z�2��Pf�#u���4(O�DyZD�_4s������45��e���	d֬YL�0�?mݪU�h֬Y��""""��?��ĉIKKc�ҥ,X��F���Kdd$����C�^0�).�J�.�xyzz:-Z��ƍDFFr��y������2v�۷��� :v���	��Ã��8<<<��8,i�СCq��)v���ٳg9z�(��r
���,\��޽{����_��f͚U�c���I�&�>��1t�-Z��x��3�<�…�ӟ�ā�7�G@@�����ۛu���￳p�B:w���	

5�In`�,~�ȑ#����7�|C�����Ç�?>�c(�.����/t����S��e��\�Rb]777�q���Ǽy�hܸ1����۷�����\��kw���c?~<���\�~�\�}�=��cxyy�a����qqq!//�'NвeK8s���|ГO>iRGj�i�iP�V�V����o�E�A�~��gŊ̘1�A/"""R]�����Ϙ7o]�t!--�g�y��a����T��ٳY�l�������v�Z&O�������@.\(ui�s�Ε���nv*�)kI��/_fΜ9�:uʬ^QQ���O?�`�����>k�������$���U|?��-��
j���6�GϞ=��\J�k׮��͛77{]^^������?��<x�7nЪU�2�6�`,e�֭���c�=ܟ��$�5b�ȑDDD���Ȱa�HNN�ڵkL�6��
�v-�1��jkk[f��?o>>>DEE������ܽ{���88��ի�n��l�2C�۔��S�����ED�E�S�֨�N������D����Ô)S�w�����Ur�����Hu)i��������3���|��7�8q�5kְq�Ff̘a�����Ò<x�{U����˗s��)���2d]�v�w�ތ3��}�wI��U䘫����N��M��XncS���w裂���:���;�w�6���xܖ.}i�{��7Y�~=;v�`ذa���acccr�}M]��76>��q?���5�M�6���i\�İTăm��~ʴ�h�<�<
����""���)"""""u�ƍ�9s&�ڵ#11����!��X͙3gJ��2::���T����:D�v������www���ؿ?�ׯg�ʕ�NO;;;���پ};vvv5�%mrPxx8mڴ���텅�4j�{{{Ο?ϱc�pqq1n��̬T�խcǎ�����0�X~��q�*�ϰTĪU�LΑArr23g�$66֬ӳ�'�x���s����SOUY�;v��ٙ��$2339t�C��}���:��}�Ą	�ꫯ���"99h�޶m[rss�v�m۶5y�a����Rw)O+O?Hy�vP��ڤ�a�"""""Rk]�|///&N����Ǐ����}�]Ə_������ϟϼy�X�z��Kx��F����_}����t�ޝ=z�w:�E�q��i�޽˕+W���qrr����X�p�a�����M���


8}�4�/6�_�~��_~��� �;Faa!��=|�A��_]��܌qgddPXXHFF~�!`z�ve�={�S�N����������ӹsg���8{�l��3tҭX����\n߾����qrr��7߬��G��ݻw�4if���}������9r$�w�����'��o�f�n0���m�ZCYy���MyZy�A���GyZD�2͜"""""R���2m�4�5kƷ�~˰aì����%$$�X~��-�{�=����w9zzz�x�bbbbh޼yM�)"���KPP����lstt4>�4i���ddd���cR�Y�f̙3��M�6\�zOOO���ؾ}{�b��M777���X�d	K�,1���ӧqqq��LJ���s���M�f�>b���#Kگn���8p�.0y�d�mfe��7�0nܸR�hР�ƍ�o����������f߾}ddd�믛l�:uj��<h� ڷoϥK������3�^�Ѱ�Ji,]J�"�'N$&&0��8p 			dff���¿f����p�.����S���i�����*YD���������]�ƬY�X�~=����Z�
[[[k�%"R�EDDp��%ƍg,{뭷ؼy3���[1:1(�s��ӓF�m\^��ޞA����k�תU+������9x� �.]�e˖8::���G�n݌u�͛�'�|Bnn.�ے6�ϟOaa!���ܽ{��ݻ����?�@hh(QQQ���ФIBCCY�z5�����͛2�E��gϞ
�_�Z�nMDD�~�)���\�r��m���/0u��*���Ν;�ڵ[[[^{�2���Y��]�v1s��R�mۖ��BBBHII���t�֍I�&��/T:f<<<

���Ӭ�������hٲ����M��1��>����D&N�h�-11�V�Z��K/U>p������<]���E�.kPTTTd� �ѱi�&Ə��:|�0�V��rT"R����1L�i͐DDj�}����;�PPP@hh(����ID�
i\���ܻw���P����ŋiܸ1]�ve�ȑxxx�����',,�}���믿Ү];^y��L�B�&M���HLOO'//��^{�����O>1����Off&;w�u���w�R����>��S�����E�ђ��Ȝ9s�ܹ3_���u��ƶm��ԩ999xxx0}�t�L�R�!��>������T�G%O��稜I��)R�\]]quu�v""""uZ~~>���g�ڵxyy�f�ڵkg�DD*%$$�
6�߹s��'Or��In޼i�*((��Ϗ��,c݋/Nff&!!!��ؔ�Ξ={�������l���iii�ݻ�Q�FU�щ��<����u��}�&L(����/;w�$22��|��ٙ-�!""UGyZDj�ҿ��KII�o߾lٲ�M�6��)"�Hغu+�W�&%%�C�@TT���ƍ����駟fӦM9r���h���KZZ�����4������III����,C���������1bYYY��у7�x��z͛7'00���X.^��ŋ���%00�f͚�p�""����6�9E�Ř1c����a111�VND�����K��b�
^z�%����ر����2-Z��ƍDFFr��y���������ˤ޾}�

2�.]����qqqf�=�̙3t���lۓO>iRGDDDʯ}��\�v
'''-ZDÆ
K�ۯ_?���Y�b3f��ѱ�B����E�����R�=��a�H7z�h`�0DD���c�ĉdgg�f��N�J�
���<œ�������:̞=�e˖���Jjj*k׮e���x{{�ܝw�����K�Ϲs��l��ի�n��l���PGDDD�/..΢���޺ID�)O�Hm��)R�\]]quu�v""""uRaa!�������������X;,�j1|�p�������o��ĉ�Y���72c�F�@QQQ���q�F��
��ll�W66�i��������H����Z����L�4����/_�̙3K�H��=KJilmmqww��ݝ��,������Y�r�qp������l߾;;;��h۶-���\�v��mۚl�v횱���������T}�-""""bE���㣏>��ё�w���ٳ50EDy#G���ɉ������|�w�N�=hܸ���СCX�h�O���ݻ\�r��?�'''����u
3���ٳ'���f1�uDDDDDDDD�zh�+��x��INNf���,\��F��'������Lpp��6GGG��I�&OFF>>>&��5kƜ9s��۴i�իW�����Ύ�۷3p�@���4�/@ff&�
�������X;�R���0z�hk�a5111&�EDDD�����#�ի����EDDD����ܹs�ܹ3G���g��vH""5��ӓF�������gРA&���jՊ��p>��s<ȥK�hٲ%������ѭ[7c�y����'����KAA#F�࣏>"11��'�Đ��H�V�x饗j�Ed̘1�ADDJ�m�6�m�f�0DDD���)"u�ƍ�9s����J�x�"S�Ne���̛7�e˖ѴiSk�%"b���?����-s��e�ܹe�>|8Ç7)kٲ%��ބ�����C�N�������L�>�-ZT� D䡼���v""R���"k� """�����W�\!''�>}�X;��-[�0c�ڴiCBB�vH""����/;�-# IDATw�$22������RA"R�>̪U�����C�����5���ȣk�̙���Z;@�SD�'N��3�X9��˗/����W_}������iٲ���y(''�j�ozzz��4͛7'00�Y�f1a�bccY�j͚5��XD�.��ѣ���H�bbbhܸ��ð����i�GLLL�C�H�SDꀌ����;;;k�""""ڱcS�L�I�&�ٳ��^z��!���K�����ߟ+V0c���H�m�DDJ5~�xk�`U���Z�MD�ӠAk� bB�SD�'Nh��:��̝;���0|}}���y�Ǭ���Ejz������N+���: ##777k�!"""�t�&O�̭[�غu+o����C�
N��
����5k��C�����'  ����|�M֮]K����������̙3����|Ĉ���gϞ>�nݺ���ܹs�ݻ�3g�p��i���S�1999�����s�K�.����4�ܹ���7_|�Y��V�|�[U3��0���5OyDGG���
���3cƌ�j<"uYE�sAu�_�|h�W��ߋ�()FK�uy>�+KE�T��n_��"�6
N��N�>��N�>}�������ȑ#L�0�˗/�a�|||���������w�%!!��s�ʕ+$%%���ď?�ȇ~h���?��o���&C5�x�b�;f|~���jo���%��;BBB��������c�ңG���k��D����E��"�>
N��222hܸ1�{��v("""R����-[����y��9x� �:u�vX""e?~<�Ǐ�v"������C�$$$���cǎ9r�{��accc,�w�G��'��_~��0K����`�ڵ��׏��B�5���WMto��;��݁}��-�{�=��������ӓŋC��ͭ�H]SV��Ϭ����k�UC��"�����rǏ�W�^4n��ڡ���H1'N���חs�αj�*���hР���)Stt��C�w�B�`�i�����֭[9y�$�<�<##���<�Jll���+,,
ФI��"���K�7n��쭷�b���DDD���o��D*�6�iy��3T�~���Z��� """b}���,_��e˖��s�q��	�v�j�DDDDY���#44��{�r��E7nL׮]9r$&u���	c߾}��믴k׎W^y�)S�q:X|�`g�غu+III&��$''��sϕ88%//���P8��+Wh׮Æ
cڴi�j�ʤ�+W��OHHH�֭[6����x|�޿㶒��_~a͚5$%%q��
�|�I&N�ȫ��j�����������ܾ}�v����憿�?-Z�(�|��fyρ�[�la�ʕdddдiS^|�EfϞ]�;�K;W����\��;vШQ#ƌ���׮]�o���q��<�вeK�>�s=�{˖-��ߟ����;t耓�[�la„	�n�����j:O[������hP�<nI��c


e޼y��уu��Y|�e���<]�j	K>C���*�����~}�3T�����Z�����CDDD���g�2a�N�8�|�ܹsM�z��ƌc�D�ooo"##�F�†
���ܹ�ɓ'9y�$7o�4.UVPP���YYYƺ/^$<<���LBBB��[������!99��N�ÇӠA�{�9��ܸq�w�y�����rssٴiiii���;}���<y2999ƺ�w���͛���]�z___._�l,;w�K�,��ݻ����������L^���˖-[�~�:�~�۴�L�>�k׮p��m���k�ݻǢE�,>��,_���[�����t�ԉ���r��mv�܉��
K�.,�����C~~>...f������޽{5jT��HmR�y���YޜhI��1�\����<����(������PKX�5>�*����G��g�H��o�Ej�_����\͜"""R�z�j����ݻw�?��0o�<
L�:)22���"��G?5����m�_�G��Sl��դ��p��!���2�۸q#YYY<���lڴ�#G�M߾}IKK3�v�������fw;����?��3g�p��._��ٳg�֭�?��Y�6l��t�ԉ��pRRR�cǎ�;w�/���X��/�$''{{{֯_OJJ
����={����a��_��˗/��SO�u�V:ěo�	@xx����͛ ))���d>��S-jӒs`йsg�,5�'O��=����d���$''���@pp0
6�믿&))�iӦp��!���{=$%%ЫW/��
e�:"�����NNN��g��ryr"X��-iߠK�.$%%�8����]�~*��+�C-aI\U���0����T�o׷>CE�}�.R�?~�>}�X9��-;;�_|��s�2o�<RRRxꩧ�����H�VZgKI冻�###�����~��ˋ��t�N�}��D�=hذ!]�t!00����r�7`�����K�$''STTĀJ�oP�h�"���C�ƍy�g�S�8p�X7>>��һwo7n���#��_���>|�������@�-X�h�������:�ѣGyꩧصk�1��߀�w�[’s`�`�hڴ�qf��ׯ[~�e�{��4i��8`��g�…t�ܙ�M�2a��,.`�t���`��|�I�:"uEm���eI��͉������O�,�R|?��͡��$.k|�UFu_����P��C���b'O��C�<���EDD��
c�ܹ����?HII����ٳg�l�2RSSIMMe�ڵL�<ooo�5kf�w�����K�Ϲs����s�=GDD��ɼ���A*%-���/>��>��?�l,�駟��u�����={�Y����̙3�S�N�m+**��MK΁A׮]��mmm�w�E�>̃���*l�y��f���z�z�*�[�6�g(3�y�t�.m'��vK�,oN�$�W�
�%)��������PKXWM~�Yr�KS����]��?48E�;~������_~��w�y�]�v1w�\��׿�|�&""�&×��/��;(�*����3g�<��򈎎&55gggƌS�}ʣ��%J*>|8��������7�p��	֬Y�ƍ�1c�F���dɝ��<�M�6%55�;w�p���Ö(i��!���6jTu_�6hР\��/_ΩS����gȐ!t�ڕ޽{W��oY�M7nl|\ޘ-մi���D�%ד!���i(����.�=O��%m�7'Z��+r�U1k�%�)+OW4�V���M�o�Q���p}�3T�����Z,##��Ç[;�z'&&{�1puu�vH"""���w�%!!��l���;BBB��������c�ңG���[E�J}gkk���;���dee��~֯_�ʕ+���vvvdgg�}�v���*�^�&Mptt$%%��[����G�~�J�ܱcG���r��q���6?���=�ϟ�رc����333+�x�	~��GΝ;W撔�e���i�������{Ќ%�.��zj۶-���\�v��mۚl3,sQ�\�QS�y��,i��9ђ<n�c.Mm�Ӗ�e�Ϸʨ�Q���*RT��F��;w���SDDDj�իWy뭷;v,���?~\SDD���t�����E			��ǭ[�x������Ύ�;�����ŋ�u�VD)��ȑ#qrr⫯�"??��ݻӣG�t捡C��h�"N�>�ݻw�r�
�1NNN�����5LG_�>&fŹ��DFF���ddd��0h� cݗ_~�X�رc������X�b���ܾ}��˗���ěo�iV?%%���N�>��ŋ��ׯ_�w�,9u�%דa����l��ʪb�*���Zy�<,i��a9ђ<^���Km�Ӗ�U՟oխ��G��g�H���SDj���,�ܹc������T��;w2u�Tlll���3�#."""��K�7n��쭷�b���DDD���o���Q���KPP����l{p��I�&OFF>>>&��5kƜ9s��۴i�իW�����Ύ�۷��k�r��e���x�.\���ɓM�988�������~Μ9ôiӌ�#F�(�c�"�~�m���GFF����ɶ�S����ǒ%KX�d��~N�>���K�Η%�.��z8p 			dff�-�d�Ӽ�
�����tyX�fys�%yܒ�����tiKey[WU�U��~���[��"��fN��222hڴ)�z��v("""����<�N��믿�/��ɓ'50ED�������燛���μ���X����|c'''�������Y�l���6�%K�;u+R�{wWe����L(�Q�\FR-�(7r�e�I3sD
������\��1�Qt��L��r�� ��8j��7-E�G�s��9�����羯s]��:�}A������̙3�=zкuk�w�μy����.��'NA@@/��"S�N-4{ǥK���x��iӦ
�Ǐ�8��0��:u�d~Jд���%���~`�ĉt�ܙV�Zѿ6l�P���}vE�obm�gdd�b�
�{�9jժe�^�N���Y�b�t�TRw���W�^L�0�'�|����`��ˋ��&O�l.W�zubcc	���'''����СK�,�x�v���ԭ[''�B�I�ƍ�Q�nnnw����͍ŋӷo_jժ����j�b��,Y�wwwsY���…�ݻ7�t�Bdd�M}v'5k�d���t��777���yꩧ�>}:/��ܘ1c�ڵ+����5k�ԩS�7�V�\	X�_����[�nT�V��;w�g�ΝT�^�.]����EJ]y��aK�֎���㶴_���8mK\��������_�o��<�������6z�h�lق�h�w("""���<x0ׯ_g��������!���:���	,��̟?�E��綾^�>~Mr�ѣ�֭�(��c�g�Rٖ����:�C�j���g�ܹ8::Z�����&7y��W�_�fdd0p�@Ξ=kQ�^0!Z܍SE�7�{��'9z�(������}O������e�L�8q"ݻw���J�INN���?��S�M��ȑ#	

�(���w�{�=^{�"c��L}_��(!!��� L_;|-RQ��İh�"֮]Kݺu8{�,={�$,,��C��9B���4^��߇""�M�Cˆ�{)g�5s�H9�����������nܸ�ȑ#�ԩO?�4���JL)����;v,�w�fϞ=,X���'�v����ٳٻw/���<��c�;w���������СC4oޜ�����ǪU��e�����[4h��5kؽ{�y
�ڼ��O>��ٳԫW��K��w�^.\����ﭳ��F��{�ns⎭��ҥK����f͚5�ر�W_}���Xs9k>��	3������w��
P��m�2""Ypp0u�ԱHf�����ӳ�R"""�+����"RN<x�g�y��a���T8�����Ϗŋ��N�ڵ���H��c�����������ͬY��>}:׮]+T~�ر�i�ggg�y��l��+l)�i�&���hҤ	NNN4jԈI�&��ͻ�K����Z�����W���o۶
�q��ѬY3�������޳�{�4p�@C����w���2-w����V����$''��g������gK�=z�%����
Z���\]]�4i�֭��?�u��1i�$\\\����H��ߡ"�C{ "�]�p��/���c�PDDD*�[�n�0m�4:v��ƍ�W����)�[���d�ȑ>|�P����hժ��kӌ���}�ʞ9s�e	���8q��6///�M���暷��/�@@�-�l�V�����[��Ν���~v����/_��ͭP9�6S����g�%""�3f��o���g�DDD�?�����"R�����(��IOOgРA;v�ٳg������y |��>|�z��Ѿ}{���h֬}��-�|�*�_5��*O�jMٻ%Q5������E���:�]0��*n֔��<s<���ž�n�[�;��Ϯ`�w���M������T&����;��~��TlJN)���Ҩ[�.�>���C�
�h4��S�%a�1u�^����̘1��'���GJJ
O<��}i[D�Ab�%�(III�������ɓ'�srr,�:RSS-fb1�����-T�5e===9}�4�ׯ���Ӧ�*N�z�8y�$�M�6�����RA���q��u�W�=㋵j׮�w�}lj'�.����]~��{͚5�p�W�\�f͚��\�b.#"""""""�W�GZD��RRR4k������={V��0�?�/��ĉ�<y2;w�Tb���=ػw/���9r���Ǜ�_�zբܔ)SHOO'''��HTTݺu+T�5e;v�@dd$G����\�t�Y�f���Oxx��������(8@NN�~�-S�L��.k�C֮]ˍ78y�$ӦM+q}m۶`ƌ\�p���,>��C���y��W���ggJ5-����iy�ӧOj۴�nK�������HŦ�SDʡ��T^~�e{�!""��n��<�ϟϘ1chڴ)���4o���a��<�:t�
�0a&L(��ȑ#��ԨQ����2�����ׯ�{�)¶m�HMMe�e]\\9r���4p�@�l��ѣGy�7�ۻu�Vd�Ž�Сk֬���;���,��V�fӦME���a�,ڵ�����������OOO֯_oS��mۖ�۷���^(�4�/�P����fN)gn޼ɑ#G���w("""���nݺ��;�0z�h��ۧ��{4f��v튫�+��f͚1u�TsR�ʕ+-�GGG@�*U�U��
"&&��P�nk�V�^���X������	www:t�%KJ4#��``�…���]�t!22�溬1r�Hz����?��`�M�6����%��f͚,^���]���憳�3O=�ӧO祗^2����=z4u����ɉ��l��~�֭ժUc�Ν�bݹs'իW�K�.%>^�8����$$$�{����� ��я~��)o���������h4���Ƿ�~{ǵ�ED�r�v���_Y�jgϞ��ӓ�� ��}\\\d���,[���_�ބ�����ӧ�����6�hM������5�={����J�>}�1c=��7n�֭����Ջ���f�vnn.�&Mb�ʕ�:u
��@���2dC�����.]�;#��'K�.�矷�""���������������\�e�âE�X�v-u����ٳ��ٓ��0��W$AAA�����"2�j���̙3�۷��Q���]���iٲ%P��������T-[��~��@�} b�d-�#R�<xWWW�4ib�PDD�β���ر�ō�ӧO����ꫯpttd޼y�ܹ���z����S�~}Μ9CDDu��e���~�dm�u�ؑK�.���ILL�o�f�…���ϴmۖ�'O�ߓ���իW�?v�X�����_ggg���DRRW�^eԨQw�~��7�x�/�����~���(\]]�>)=�����_�">>�w�}��f���g�e�DDDDDDD��Qr�H9������7U�����>��#���iٲ%1114oޜcǎ��͛���e�С<��#,]��Ν;3h� �l�Bpp0W�^��O?��Ã��<��'�'γ����6mʒ%Kx��Ǚ2e
S�L��>3'�̘1��'O��O���/III�������_ұcG�����O���`Μ9wMNY�z5��ḹ��u�VڷoO}."""%���ʤI�x�w̿�׭[��ٳ-fb��i׮]�DDʳ���
9S�������!��H�L)R���H9s��A|}}������V�`�������ۛ%K���OgN�ԩ#G�$::������x�w�ܹsO� IDAT��a2g�7n�ȑ#�2e
�/_6�_�v-,0/�Ӯ];�ϟ������W�Ε+W�����o��gϞ>��Ç�1�~����~���x�
ƌ3�K����}<��DDD0c��|�M������'Z]\DʳʞD���""��aE��B�)"���y�W�����Ǐ�Q�FE�OKK�xŦM�HJJ��ۛiӦ�z͛77��F���暷�8q�֭[[��]�v��1c���lܸ��7��Ɉ#�V�Z�1}��:���\֯__(�EDD�#�q�YV,�����%"""""""�8�;�ՙ3g�t�fN�2�(W�\)v��Y�%i�`0ܱ����uvv.T����={���XڶmKff&���<������X���� ,,��^z�^x���t%������������<4s�H9b4qppPr���аaC�=ʩS�hР�]ˏ7���4�{�9����{�=fΜY�mX�q��|���ر���w��IIIE����`��<�o���իW3}�tF�Exx8�v�bРAddd�r�J���S*�����ȃ��ѣ4m�����(��1��<2������E�k0x��Giժ!!!<��c6�YR�cy?��s�slժU�kժ}������ܳ��gGGG~�a|}}	�'��_!Z��g��߉�DD$?͜"R������养���C�r��W_~�������p��ƌ����:u2�ݺu+3g�$  �ݻwӮ];f͚�֭[�eL��;v�DmXk������c�nݺ���	+T����ϟOFF>>>����|i���Ř1ch߾=O?�4���JL����?d�0l���]����9w�k֬�������;�ڝ�1���ܹs3f�G�fΜ9�����EJΖ1477��~������!C�p�̙2�N�Fc�����SD��ѨYSDD�l�ر�]��={����Z�V�}�?��3!!!�����'�����ҥK���!88���4y�~��p��E�6mJ�
8u��m�b��Ѭ^���H������ѣG-ʾ���ADD��>�}�Y���{���js,""R��� ֮]k�0D*���D��o��텶���ËRT��Q��,�'���s��M����1w�\�����̚5kpuu-��l��"(��q��>�{�����^�z1~�x�[�܋��������\Ο?ϤI�0�|���|�e���z�)oc�� )�fN)GRRRhѢ����r��fϞ=�1�
P�JjԨAϞ=IJJ2�Έ����cΜ94l��e��9s��ߛ�>f͚E�F��R�
7o޴�
[T�Z�m۶1|�p~��P�jU���˂
�
cѢE�����₋�͚5�m۶�ٳ�:uꐚ����RԧO�B%r��Ӈ�-[�;��������ȃ�jժ<��̜9�&M�����_���aU8�/��ŋ���߼m��\�x�ŋ�12y���q��ё�u���?��}���9��Mc���E3����.]����JN̜9��3g[&!!����B�
ĠA�̯���o�-m���Y���ݝy��1o޼��


5'�:t��_��Htt4������H�X�j��C�I���g�(8���uRR���|��T�R��}�Ε+W�>}:;v��ٙv�������C�����dѢElڴ�������G��=C��`0�����p�B6n����qvv��ˋW^y��={�1n�-[����ȑ#G�����G�C�DDDP�Z�R9�w��ʹi�شi�����~�m}��},\���[�r��%}�Q:u��o�A��խ���ٙ��ƍǎ;�۷��mX�9���1��y�…�=�&M�S*���Γ�α��V�X�s�=G�Z��e�ԩ���?+V���_����H$?[�Gk��;��wҠA�\�bs���*�k��1X�_֖+��l�V�XAtt4���T�Z�Ν;3b��,'�Ƣ1HDD����r´֢����(77���h��}Z�hAJJ
�7�wX""""����Y�f����LݺuILL�СCdee��GGG&N�@vv6����2�ϟ'66���t�Ν���/Qϝ;�e˖��ݺu���4��Ҹ~�:AAA��7�|-Zd��…�X���W�Z����c2}�t��$YYYlذ������pww�KoZ�v�C���ɓ�'$$��~bcc��5�0}v����q/�Cigtt47b�䟟��I~_}�����iӦо6mڰ�~6n��k��fe��ܝ�ף-cmI�:u
��5k�����Ҿ����J:Εd3'�dee�z�jrss����)�A""R%���)))ԩSǼ����He����������ĉ��������P���X�v��� 11���@{��@)j��;IOOg���4hЀe˖ôi�hҤ	�W��N�:,]����c�����8t�͛7gܸqxyyq��i���ؿ?�֭3?n�19g�����u�6l`ڴi�\�����b�^�|9cǎ�{��888���FXX;w�,��1ٵk�g������Ì?�s��g^�Z˖-��ɓԭ[����/<��S:t����'N�d���Q�?��s�ڰ�s(��%I�F%9�F�k1����<)�۽{7O=�T��4m۽{�nK���z�v��u�������L�:�֭[���2����5]�*�8%�4h��I��]�6�-"66����ڜ�bm,�DD�8%O?�Re45k���T*yyy̟?222ؿ?�ƍSb��H)�ӧ}��w"��Ӈ�-[�;�r������nۭ5v�X7n��`0'ݼy�q��ѠA�V��믿X.��i�&���hҤ	NNN4jԈI�&�a�sY������Z���~��޽{���̺u��ߎ;��o����7�f�b���/O������6mpvv�g�1�d����ғ����3�<���3>>>�7��[��T��۷�R��g(mi�^>�;)�q8��Ml(��g�y��ѣG�_�7ɯaÆeD�Ėq���і�֖�Z�j�믿ΡC�pwwgȐ!��fi_�Y�_%�J2����ԯ_��U��M�^�js,�DD�8�9E��0������ȃ��cȐ!|��׼��L�8��/}DD�ޭZ���!���WM�65�;��^^^����zߙ3g�ѣG���8q��#F0y�d���HJJb�������������9r$�.�///�ԎǤU�V�MG}���w��(gϞ����b{�-8w�M����xxx����|��P��4�p-������I~�/_��ͭ�>�6S��b�h�Xk'''jԨ���>˰a�,f(/I��}Mdm��MIƱ��`Z�-77��X4��Hq��"Rdffr��Q͜"""�B\\o��u��a׮]zrXDDD��*�$`��
wR�j�"�;:�y����?[E׮]iժ۶m���?��̛7���8�|��;.U��r��a�իG������Y�f��۷T��$��$��Fk�o��7/mq��|���q/�CI��8�K�/��g�y����C�m���ʈ܉-㴵ף-c����$m��5]���U��ܝ�1ggg�#��Ec���G�)"�@ZZ�o�Vr���Th/^d���|��g���;DEEY�4�����������ӧY�~����qww�G���уC��e��.]Jtt�o&%%k�1��ɓ�999�J�Ejj��rF�����6��c�q��)RRR,��SRR��7�[�n���@�J�FI?�;)��,�{9Oj֬Ʌ�r�
5kִ�gZf��v��`�h�X[�Ѧ5��J2Ε�8fM,�DD�8��/"%������O<�C)k֬�駟�?���7of�̙JL����6-�P:v�@dd$G����\�t�Y�f���Oxx���+�����?�~�)���4nܘ&M�E?y^T�{��%;;�#G�0~�x�W���qM�2���trrr0�DEEЭ[7��2%�DEE���JNN���L�:�^x�uܼy���tF����ǩ[��E,��a��`��,-w;O�:�Lˎ�>}�P}�m��&)
�^�����5����bm�t�+�q��X4��Hq4s�H9`4��Tv""R���O�������1d�����������X��Ã˗/ӫW/<==Y�~}��¶m�HMMe��\\\9r��upp0QQQL�6�iӦY����c�:t`Æ
L�0�	&��ȑ#�iӦԎ�F����Xl�_�~6��֭[9s������ׯ_h�I��[�swwg���75mi���V%=��d�yR�9ֶm[�o�Nzzz�~HOO�o��T�^�����5����bm�t�+�q��X4��Hq4s�H9`4iѢ���)U_~�%O?�4[�l�/���?Vb�����+99����"��=��u����Dvvv��_�zubcc	���'''����СK�,�xʻW�^L�0�'�|����`��ˋ��&O�|ǸnjC׮]quu�`0ЬY3�N��o��ʕ+K�����	�J�*ԪU�A���`��.777/^L߾}�U�NNNԪU��d����74hЀ����|�r�|���a��`��W֞'E�cݺu�Z�j�ܹ�P�;w�z��t�ҥ̏A*�;���^�����5����bm�t�+�q��X4��Hq������Hev��m����?��������=���`����_�~����F��KDDDD����0}�X����J���,[LL�-b�ڵԭ[��g�ҳgO���:t��#,������/�uE���@||<���E��W�D���R�$k�;;r�7n����ޡ���ܳ]�vѢE֬Y�ʕ+Y�|�SDDDDDD���`�ԩc�X���g�eMDDJ�� )��SD��h4b0h޼��C)���,ƌC���i֬��������a������TJ���L�4�u��q��yΟ?Ϻu�4i...�OD*8�A""R�*�@��KII�Y�f8;;�;�INN&88����2d�{�$"""""R�=��DDD0c��|�M������T�DD� %��ؙ�h�E��CDD�f�n���+QQQ�k׎
6РA{�%"""""��D.H``����JJc����e}D�,%%___{�!""b���tZ�lɌ3���f���JL�")9EĎN�:��˗5s���<0n߾�������Ņ���z�-��������������SZ�GĎRRRptt����ޡ�������_BBB��o�<y2�G������a�����������H9��;JII���777{�"""R���<bbb3fM�4!99��͛�;,y������!��+11���@{�a7AAA�]���a���H��;2�����;�b}��w2�����w�}��'b0������<@�ׯO�>}������Ӈ�-[�;��-"R1��Ӈ����;3%��ؑ�hd���CDD�HK�.�w��ӓ]�vU�/�DDDD��`�0DD��V��w"""R	(9E�N~��G���;Z�ha�PDDD,������|������DEE���j�DDDD����@PP�������@�����}���`�DD�����W�e�|Qr������(9EDDʕ��D"""pssc�֭�o���!����H�'�E�<��It={���K�
�o߾�AĂ�SD�$%%OOOj׮m�PDDD�駟x뭷HHH`ذa̘1777{�%""""H�>}���H�֮]k��O�>�EDD�L)9E�N8��������/�d�Сlذ���wv�HDDDDDDDDDDD*%���IJJ
�z��w""R�edd0z�h���ү_?��P�F
{�%""""R����HNN6o;z�(M�6��:�&��QQ}S�Z�NY�b��nժU$%%ЪU+M�/R����8��z���SD���;vL3�����l߾�������ʕ+5u�����TZ�ӟؾ}{���)��hd�ܹ�\����<���G�&M�]�Ha|�.""�+%���AZZ�oߦE��EDD*�7n0n�8fϞ��/��…�]�����o
��ܾ}{��-RЍ7x����ݻ7�����Ջ��Ǔ�������#)?������e�Nt����Xr�w"���h��ݝF��;�D��ۇ���/&66��?�\�)""""Rn���[�\�ȃj���\�x������
0��/�x�b;F&rw�m��]DDĒ�SD�h4ҢE����T�n�b�ĉP�^=����wX"""""w�l�2���			�ؾ�~���ٴi��=z����ƍ�7Q8@�N�,o���Z�kff&s�̡G��nݚ�ݻ3o�<����Lm�8q���x���:u*7nܰ(��?0q�D:w�L�V��߿?6l(TgFF}���hժ/��2���\�v�P�K�.���/ҦMƏOfff������[�IJe�����С��?f̘Q(����ν��V�X�s�=G�Z����ԩ���?+V� ##�^�I�.rss����W�^�nݚv��1x�`֮][��5�ҝ����Ƞ}����ٓ��\�}gΜ��ߟW^yŢ�7o2y�d�ԩ&L��,Q�t����XҲ>"v`4	�w""R	���3h� �;��ٳ	Wr�����<0�t���ٳ9|�0���T�V
��7�y�f�t���˗9w����{���h222,n�Mvv6���:tȼ����ƒ���ܹsqt�����¸r�
YYY�^����\"##��lq��ĉL�0�۷oӽ{w�]�Ɛ!C8y�܅HHH`�����ƚ�.##���PΞ=k.��_r���{�[�-	[b�?>�-�x��X�bW�^�>�9撜Ͻ������LڴiS��6mڰ�~6n��k��fk����ܹsY�l����[�HKK#--��ׯܟ���͍~����͛�ڵ�yߎ;h׮��{�O����_��
6���B\\���6Ǯ�]DD�0͜"r���䐖����o��o4K9"�888覦�����L�>\\\0�>\c�����<P<==y�駹}�6)))�/߭lݺGGGv��MVV�Kb6���?oN�hԨ�w�6'$䗜�l�o�븸8:D���IHH`߾}�Z�
___���Ϻu늌��~Q?EiРk֬a��݄����_��/]���ooo֬YÎ;x��W���5�[�l'O��nݺ��Ʋw�^-Z�c�=Ɖ'X�d���'�|�ٳg�W�K�.e�޽,\���Ǐ�ϖ~��ޒ�-�,_���cDz{�n���Âعsg���I�so���<��S�ʚ��ʈ<h֬Y��9sػw/;v�`�ر�\��\��k����ZAAAT�V�b��_�S^x���v�b����ݻ���X{�1Ν;G\\�ͱ��w��(9E�>���o�y�&~~~6��gϞ%z���T.Ǐ�^`�ĉL�<��;wҸqc{�%""""b��d���M3��nL�۷��W���+����Ů]��_�S:v�h���16�fZ.(**�&M����D�F��4i@���Ļ�K����Z��yV��W�����m̘1ԯ_�jժIrr2�}����)�%22�g�yggg|||7n[�n5�ݶm�ƍ�Y�f8;;����{�wO�`K�%aK,;v��o���ۛ���̚5��ӧX,sTV}aR��;z�(�KRRA
6�(#RX;N���xV�Z�O?�D�޽INN�Hڸ_���?L�޽9v�{��~�-��<��C��g;v,mڴ��ٙg�y�<�U��A[b�.""R�����RRRpqq)2c�n>���2�HDD*���<�Ν�رciڴ)���4o���a�����ܓΝ;3s�Lsr�ƍ�Z�*|��l޼�Ν;������c��L7mq��z��Q�'N���'�����6-���k�v��9�6mz�zL����XloѢ�E=��=�<�L�e�l���N�Up�[b���9r$�.T.//�D1���]
 IDAT(x�]�|�eɑ�L�LeD4#F�`���$%%������	

%00s����%1p�@V�\��ŋiӦ
{����۴nݚ*U,o��j���i�s�8ak��EDD
Sr��}f4y����+""r/N�>Mhh(;v�`ܸq�?ggg{�%""""R���	�d��|||HMM����l۶��-[���A�-صk���:t___<<<,�k�)`��P���o܋����.˙?���tl����l�[�-	[b���9|�0��գ}��xyyѬY3���[d���&�=����XxBs�6-�*�-�t׮]iժ۶m���?��̛7���8�|�M^{�5��5j���^#!!���t�^���׽i������w�´��H�v�cǎ�Q�FT�Z�p��-�z����888��'�X�7!!���k񇪃����m4lؐ��H�6�/--�.]���C�裏2|�p�_�nQ�…����裏���JPPP��c���˄	hڴ)U�V��͍֭[����S������.]���.\`�޽L�<Y�)""""R�t�ڕ��\�.]���	   ���,,X��k�
-�SR����_�����B?���/�v�v���gx�ǀ_f�����t<����eM�"�gK?�RoI�KRR����1��ݻ[ԕ��cs̥qNԬY�+W��g�f*#� rww�G�,Z��e˖�իW���6�����믿��``�ʕ�ٳGGGڶm[�\jj��k���o��Ů�]DD�0%������,:v�������Gvv6YYY���н{ws���y�x���y뭷�S�9s����֭˂lj����DEEY��_ǎټy3���\�t���F�i���?Ӷm[/^̥K����"!!��k�ر��/�رcdggs��5���6l��t��H��x�W

eذa��?�)4������HE��/�����ի��)��˗/�C�6�mz��`Nr����ȑ#ܾ}�K�.1k�,���	/���t|3f��…dee�����ϫ��j.g:(RSS���!55��S�����w�3�=p�999|��L�2�P���-��DI>��{����͑#G?~�y�իW˴/�cZ����Ӆ����m	'���W^��ߟO?����L7nL�&M�Y�l����m����W^y�/����W����O��#�*7e�������h4@�n�J��w�´��H�裏HNN�e˖�������SO=����7o&66��C���#��t�R:w�̠A�زe�9���O?��Ã��<��,�F���9v�aaam�״iS�,Y��?Δ)S�2e
�}�.~����ɓ<��������KRR���z�c4���/��cǎdgg��'���9s5jTYu��H����HDDnnnlݺ�����;$�2S�fM���HNN�iӦԪU�
������OZ�b-._�L�^����d�������m�6RSS8p�Ey��|�[�xQKa���ٴi���������
f�wpp0[�n�̙3���Z��_��Ŷ��e��=�o�a�ޭ[�B7Qm�[�-	[b�С6l`„	L�0�P]G��M�6e��i۶-۷o'==???�}��Z�ZnD�ALTTӦMcڴi���\KE��%1h� �⯱5jb���ۛ~���(v]�"""�i��2�j�*�w|}}IKK��ɉ��8�:u��ȑ#پ};l۶���~�Ν;��F�*U�fɒ%��0�3g�7������˗�׮]��x���1�k׎�����z��DGG3w�\.^������������U�$""ֻ|�2�_�~��Ջ�*1EDDDD*Ӳ��ڵ+P�f�i��.�3z�h�֭������/�w������'NNN���ӡC�,Yrߞv�Y�&�/�k׮�������SO=����y饗�����X�x1}���V�Z899Q�V-��%Kpww7�5,\��޽{���`�K�.DFFjߖ~��ޒ�%�1c�еkW\]]14k֌�S��PV�\Y�}Q�nݺQ�Z5v��Yh�Ν;�^�:]�t)i���;�ӽz�b„	<��^^^���0y�ds9[�����x衇�n׮]�e���	�J�*ԪU�A���`(Q��EDD
s��?����jժq�ƍb�רQ�K�.�_߼y��{���4����������yQ3��҆�7o�4�Q�������E�...ܼy���L\]]�u]�v
777��+V� 44�C�jՈ��dĈT�V�#""��׿�Űa�ptt��?6OA-""""R�$$$d���k��,&&�E��v�Z�֭�ٳg�ٳ'aaa�f@��'((����"_W$���X��f�Ν�9�
���31�xe��V��."�V��{)��5s�H��ͽ�+W��ϔHRm��.�ӗE�4ʿ6�I���9{�,����mۖ��L"##y��lj����DD�ή^��СCy��y��IKKSb�������(88�:u�X$<������Yh��7���\�t���E.[_�t����XRr�Hjذ!�N�"//�ڵk��G���G^^999�ǍGZZ�=��~�-���m�)؆57n��;,�'%%Y��Ã���k�.���ϟ��g~��'F�es�""bi�����~�zV�^�'�|�������puueҤI�[�����s��y֭[ǤI�,fP�{׮];�u�ơC�hҤ	ݻw����z����2�ꫯ�W_}�?�@�
3ft���\v�̜֭9���v��M�v�5k[�n5�1�rr�ر"�8p�999\�p��6�5`����رc�n�b������*��元����'##|||�ZDD�67n�`�ȑt��	???����ի����{�����3�1co��&~~~�K�©U�U�V�m۶�������Ǡ�]DD�WyZ�U��\�r�V�Zq�ȑB��U�Ʈ]�hѢ?��3�<�W�\��4lؐS�N��・�;iii<��#Ԯ]��/РAN�:eu�krK�˾�7oҺuk�F�E��|�r��, <<����ѣ���u�%""f���#$$����3k�,�����������

2wP�Hy`^���������x�|-""��{)g�5s�Hz��ٳg#F��G����5jгgO����I#|��w̙3ǼLOÆ
�3g��=̚5�F�Q�Jn޼Y��
P�J�"۰EժUٶmÇ�7��
U�V�o߾,X��Pٰ�0-Z���...���мysƎ�ҥKK�s""�Svv6���P�^=��Ҕ�""""""""""""�*�@�����`�̙�9s�իW*���@BBB��
bРA�������Ŷ1s��;�R�JEmwwwg޼y̛7�eCCC	

�c�""rg$88�'N0{�l����3[������������<�4s��}b4K4����Tl999DEE��������>|�SDDDDDDDDDDD����)"��O?����?%������Ǐ��hdʔ)�5
GG�����HŔ��h�DD����H�>}���$&&���l�0DDD�Sr��}`4��"""�/K�͝;��c����������������H��۷��C�b�]���k��;����"r�Fj׮�c�=f�PDD��N�>Mhh(;v�`ܸq�?^O&����H�H``����b����;���"r���h�aѢE�5����{����o�DDDDDDD����V""��o�M@@�����"r_8p��={�;�����3l�0���3j�(�����b�DDDDD�Tbb��C)���D���c�0��x]Y�WD��HLL�I)W��"R�2339z�(����EDD�`Ŋ���xxx�}�ve�����H��'�ED���Z�MD��qpp�w"��"R�RSS�}�����d._�LDD�V�"<<����o<��C�KDDDD����������XPr�H3�������e�PDD�>�׿�ŰaèR�
_}�]�t�wH""""""""""""v���2f4iѢ�����^�ʨQ�X�hd���xxx�;,����?����mG��iӦ�\���o�<*�oʢ^k�)�X�U��Z����$Z�j��
EDJ��SDʘ�h$  ��a��Hۺu+���ܸq�իWӫW/{�$"""""""�ӟ�����}�TF���s�r�J����ׯM�4����ޡ��<Д�"R�rrrHOO����C�2����رc�;w.���*��ϧV�Z�KDDDDDDD�T0	e���eV�HA7n��ߧw��xzzЫW/ƏObb"���v�PD��h�D*�o�����,Z�ha�PDD��ݻ___���X�l�W�Vb��������TH���V/�#�Z�x1/^����m��ŋ,^�؎���<���"R�RRRpqq����ޡ��H)���&22�^x///���8p������-[���?!!!��ߏ��?�6m��ޣG���ٸq�9��t�ԉ��p�2	&2L����L�̙C�=hݺ5ݻwg޼ydgg��q��:q���/2u�TnܸaQ��~`�ĉt�ܙV�Zѿ6l�P�Ό�>��#��?ЪU+^~�e����v�Z���.]�>��_�M�6�?����"c��l��$l�e˖-���ӡCs̘1�P<e�ŝ{�X���{���:u����ϊ+��ȸ�n�����H2�<���T��KMD��8x� ����<y�y��1l�0����������}ץKfϞ��Ç��̤Z�jlܸ�͛7ӥK._�̹s�0�눎�&##æ�h���	�СC�m�ϟ'66���t�Ν���?�ƕ+W���b������i>���`�{w_ӵ��}��T�@/1�\T�R1��V�m�����^-m�V�Һ��jk���耢���� !�Tj�	WB"2�����M�d8G�H����~4g��~�q���ZW�\��s��I���{JNN֋/�(I�q���S�N��EFF*88X{�����m����۷�.\�`k�n�:�����up�_g8�e�̙�7o^��###�l�2���h„	gv晸�������~:]�O?����٣����W^q����)@�:p��ի�������I�&�Q�F*V��8�P��[�˗W�ڵ������0I�eӦM*P��~��7���K�"""$I�5�bHR�J���o��
R

M��ŋu��ժUK���ڽ{�BBBT�^=�ٳG�V����:b��Ş�+���o����}�J�~��W�E��ʕ+�Q�����{mݺU/��$i����v���t��)=��Ú?�v�ܩy��顇�ɓ'�p�B[ۯ��Z.\У�>�E�i�Ν�3g�N�8�.�#��~��^�dY�t�$)((H����v�ءٳgK��mۖ����g��~�$=�����Z�Y�Gq
�K�1
�O<��(�;t��Q����>Ї~�-[��r�ʮ��k2*F�}�udk���ݻ�:(>>^۷o���)͛7Os��ݻ���ݡl��&M���U��`���T����}I�;��3�z�-U�PA
�$���ض[�mԨQ�P��
.�1c�(44T?����e̘1�S�����T�n]�=Z��i�&[�͛7K�F���5k���M����;�sG��~��H��[�j�޽�Q��~��'}��g���%)�4G�u-�n��;&��=��ci��\#@.9}���]���)�����h������ۧ5j�:�=��g�է�~j+NY�~�<<<4d��^�Z7nԳ�>���(P@M�6M���CG�={V�Ծ}{��O�<iw}�X�#�'/^\�߿/����I��U��i?�ii�֭�f���[��H���%Iu�Ա�65G��#�Zev�n=ő,W�\ш#�￧kg�q*�3����^TT�$�X�b��Z�Y�Gq
�K���U�@ծ]��QN8}�����;vh�ر=z�
��?�^�`-F�W�P�n]<xPQQQڼy�|}}���'�xB۷oW\\��9�z�����;;���"�-`�'��w���������t��ԅ.V�s���^ʑ��H��p$˔)S����G����*W���5k�s��v���kau��g��
��xº�)��y|�䒰�0����hѢ��pмy���o�B�
ڽ{7S�d�u��
ӢE�+???I������٣ٳg�ƍ��qV���u�����*_�|���|P�Ν�ɓ'3m���ҟ����0����և��IR�sx��Gu��)�߿_O?��m�uZ������G��ڵK�4�|[�ҩS�lۓ��T�P�\�)]��"##u��5�.]:Ͷk׮������@�O7D��v��E�k�N��Ja
@Z�l�
�モ$[qJ�&M$IK�.�$5k��ᾭ#UX�m�d+r3f��=���d���_���԰aC
4��sq����N����H���kʔ)jذ�^z�%[;�yO�4ITRR�<�ɓ'K��y�[۶m����߿_III:|��>���t�w�:8ү3��';w�TBB��=��c��������Ȉuz�3gΤ�f]��N��1r
�K����ꫯ�: ��-[��^{M���ڼy��(�\�ҥU�~}����Z�j*[��$�bŊz�Gt��yU�^ݩ-�����_~Y�˗׏?��޽{k���:x�w����F�a�/��D�7eQf���
6��j׮]�m�?�ի�6mڤ�gϪo߾i�U�P!ͺ�ݻ�_~ѱc�4`��6mڤ+�p�:8ү3�ҬY3�]�V���{�t}=zTO?�t�]��4i�D[�lQDD��ׯ�f�u��ԅD�0r
����u��իW��QY�r�:w�u��E�����&444��֭[KJ���,�N�3r�H=���*X��$IE�������˫`��*^���5k��޵�-J�.��u��*V���������?���?okW�X1-X�@�;wVٲeU�`A�-[Vݺu�…U�xq[[www͙3G;v�������ժU+�3&������G��5J�[��������U�fMM�<�V���7����H�6mT�pam۶-ݶm۶�hѢjժ����{c�qu �ټy��7o������vu@V�Z����]����K��Y,-Y�Dv_��Y�fi޼yZ�b���.��������8!�}|��=&��S�\�x���G]�vM�{�V�Զm[:t���>׫W/�+WNK�,��[�d�ʗ/�n� �c(NrAxx��֭��;6mڤ:u�hݺuZ�r�.\�%J�:����￯U�V��ŋ�x�V�Z���_�����yZ!W򣰰0�l���1����)((H_|�:v�3f�L�2���ҠA
2DS�N�$���k�_���S@�Gq
��u����曮��_;w�T�^�t����?�aN
P@@��c@�´>@;|��T�^=WG��ޭ[��g�yF�+W֡C�(L��9�a������P���]�kPϞ=u��͘1C����,��c�w9�a���U��
��\!))I&L����J�.���p
0����s ����1���ѣGիW/:tHS�L����U����	T``��c�|�� ����륗^ru�����h���=z��ԩ����3�@6����: �����:`Cq
��Ξ=���(խ[��Q�q��i���G;v��رc5z�h�VȦN�:�:���
�����d�X���c��Ν��#G�bŊڽ{��x�	W��m(NrPXX����x�⮎���BR2 IDAT�ԿmذA#G���������XyB``�]�G(NrPxx8S�@.[�x���2e�h۶mjܸ��#�!!!��p___WG�}�� ����gϞ���ҕ+W4d�}��:t�>��#.\�ձ�N�:�:�Q�䐘��:uJ���su�wV�Z����S7nT�-\	�T����"<<\����t��5���[:tP۶mNa
@��)@	����*V���(�/lذA���SBB�V�\���ۻ:���)@	cJ����2d�ڴi���zJ��a��䐰�0=��3��y���ջwoEGG+88X]�vuu$�!FNr@RR�>��u�:
�I�n�RPP����U�zuEDDP��O0r
��;���x��'8p@={��ٳg5g�����Ց��9�����j֬��(�g$%%i„	�U�ҥNa
@>��)@W͚5�����(�'9rD�z���Ç5e�
>\
P3��)�5k�h�֭�~��m]xx��֭��T�7���h�ԩjР�
,�����_���)��
		����J�,��\ݻwWhh��+�7n�:ܳ������k̘1z��w�}�vU�^�ձ��(NT�zu(P@�}��:v쨨�(����/�P�%T�F
u��Y��?��k׮�:.��1Fs��Q�z�t��u�ٳG�G�V�B�.p?�c��Cy����խ[7������ݶ�ܹsڷo�BCC���r��:q�,���k]�pA����ƍ��[oiܸqi�w ��O�U�RE���:u�T��(}�Q=�裺v�
,�o������ŋk���*S���nݪƍ�:\�i}U�TI�������� 
0@��ջ���p��e���+�ٳ��wﮰ�0
S�c��8�x��z�u���t�&L����D}�.H�����k������ƍբEWG��1r
��t�)G�������t��.J��=z�W^ы/���R�I��8�R�J�y���U�fM
0�E��56lؠ~��)))I�W��/���H��0r
�*U��ĉ��˗/׆
��_�`��.LwOll���6mڨI�&����0�0r
��9sFIIIJHH�ȑ#ճgO5i�����ؾ}�z����h�k׮���{#�N�\��u��Y}��G�z��>��#W��\�Q�F���_իWWDD�)�#�N���$�_�^����5q�D�+W�ũ w����W�^:���̙�~���:��1Ƹ:��.]ZQQQ�^��<(777WG�\�����'jҤIjڴ��ϟ��+�:�PFN�%I���(L�o9rD={����O>�DC���bqu,�!\ȫ�5k�ʕ+�u�֮�9.%%ES�NU�
���0
6��8���ImڴѦM�\r��!�3F���mۦ*U��:�(�1Ƹ:���������1 �c4k�,�5J>>>Z�h��֭��X��B9p�)�s�ΩM�6>|�^�u�ٳ���B�\kѢEz���U�|ym߾]������|$NjS������@:Z�d��cy��˗5h� �\�RÇפI������X�grm䔐����(��������H�"ڴi����]	�T��t��)���X����<)::ZÇ��ŋկ_?}��'*^���c ˵�poY�n���ﯔ��^�Z/��#�>���)���L� Ghɒ%���9ׯ_�ȑ#5w�\u��E_~��J�*��X����%K�(  ��1܇���)!!!w�P�!>���e����Gׯ_�7�|ô{��dW�Ν]�}���a�;�b�
WG�x�;V�~��ڵk�9s��tu,�0�_������#44T�z�҅4�|����Ցp�8�|"11Q'NԤI�ԴiS�]�V+Vtu,����L �%K�(  ��1��YTT�ʗ/��������ŋ*U��];��b�$c��~w�z��J��^^W���-""B={�Աc���'�h�С�B�����;wvu��8�>���IRBB��.]��^{�ũ�HNN�ԩS5n�8կ__aaa�R���c�E:u����pu��…%I={�L�^g�qو#�cg��+y�o'N��3�<�q��i���ڶm�)��P�r����о}�T�L͘1C�J�Rhh�>��h�,c4s�LիWO���


��o����:8-22����2����\v��
0@*T����ʗ/���@9r�n{�Œ�r���Pu��I<����U�re�ƍ�Z�h�$�[�n*R���v�f}f�Μ9�
�H�"z���8�$mذAO=��������:h�����8~��,�ʕ+���$�m���T�\9[{+G�˝��e�nf���;wNmڴ����5r�H�޽[�j�ru,�iQQQ����b�����������w�N���y���{�쮻S���4h�jԨ�…�P�B*S�����������v��;w���͒��BF�WQ����mۦ:u�h�ܹ:w����`5h�@k׮u�O//�4�-Z���zJ�~���\����D�:uJ���6m����t}$''k��Œ�oJ�/^����L3���W���W\\��)rGY$�o�Q۶m�{�n%&&��իZ�j��4i��{�f��jժ�ץK��f��m֮]�K�.���_U�V��;�%�����ޢE�T�vm�;wN����Ə/777W��Hpp�$I			Z�t���Y�F�R�F�4{�l����y󦒓���_��~�رcU�J}��w�0`��^���ٗ2����\��;��1b�N�8��7oj�Ν�߿���/����n�4i�m�W_}e�����8p����5h� �>}Z			ںu�|||t�}���鲭[�N���z���հaCI�����V���/�����N�8�C��ڵk�6m�e��W_}UC�՟����m߾]>>>����ĉ3�2`�IҼy��n_�`�$������/wý�
�k]�tI:tP߾}էO�߿_�5ru, G,\�P��Z_����\y쬖��w�ܹ�:u�<==�������q㆒��t��mܸQ/��bbbԭ[7����Z����\2{�l]�|Y�G��'�|"yzzꩧ��ܹs����ڵk���/3�g׮]z�$��ר�m�f�ҭ[�ԥK͜9S�=�������3���믿Nק�C�=z�Yo}�ՇBcǎU�Z�T�xq=���w�E�z���>�L+V�����4i�Y�fI�v�ޝi�W^yE�J��O?�����4�._��5k����[;v�t�ři��+�������U�V-:tH�6mҧ�~�n- ����о}�T�L͘1C�J�Rhh�>��hpЧ�~*IZ�l�ƍ�ڵk�H�"*X��J�.��-[��������e2 �8%�X��:t���֑<֯_�a׮]S�nݔ���6m�h���i�oܸQ�4dȐt�6l�P��>}:���h��㏲X,
L��G��X,Z�j����3����n�3Y��n]�ƍ%IW�\�0�$yxx�gϞJJJҢE��l[�x�ս{wyzzJʙ��[��l�(u��M]�t��/����p����8s��
*���C�˗W``��9b��3Ř����ԩ�x�����r��


ҍ72�e���[�n*R���v�f}f�Μ9�
�H�"z���8�$mذAO=��������:h�����8~��,�ʕ+���$�m���T�\9[{+G�˝p����l'N��$�i�&�~G�-Iڼy��\�����yV���<+�dt4Cv�����}?+Z�������O?�:�]�O�ְa�T�jUyyy�D��_����}�?�8p�)]l��L[�d�I�������FR�Kɒ%3�s��F����1QQQ�/^�H2W�^�v�/���H2͛7���Y�fF��1cF�m�̱��9���߭[�2ݞ�ÇI�jժi�ժU�H2���u�ޗ��8r�Y�ˉg&?0��իW���˛�~���O���{�#ﷶn�j�w�����ӬY�&�>Y�[��啦�…M���}�'̍7�#))ɔ+W�H2{��5��k�.#ɔ/_�$%%�=k�-Z��}ݥK��X�-[��(P��5ڳgO�9�1����H2+V���y�ʕF��ϑ���q6[�J��$3{�l�r�[no��=��d�=�ϊ#͐չ9s/R��dɒ_߯2��
07ntu�48��3 �T�Xќ?�־C�N��S�<6�y{9%�����Q����J!!!*V��V�\)oo�tm��Y�h�l�N��믿��A�_�f6�O�…s$�������V�F
5i�DǏ׶m�$��W�jԨ��ԩck{��%7����111�߿�ڵk��-[�СCj۶��c!���Rǎu��u�1B'N��͛7�s�N���_			
�ŋ��g�I�L�4ɶ�����}}��i
8P���4h�N�>���mݺU>>>:p�>���t�֭[���H=���jذ�$���WU�V�ŋ���?gzn'N�СC�t��5M�6펲Hҫ����C���?�TBB��o�.���g9̀$I��ͳ�}����o4g����l�aÆI��V�Zi�̙:r�RRR2=�����u�uV�yV��,{����w��;C��X��*�=LIIѥK�Էo_���h��񮎖ƈ#�V�Z),,L			����֭[U�~}�9sFAAA��+W�tYVWy@N��0r�ߜI��ȑ#�p���b���+WfخX�b�:�Hv�#G���ߺ>'�d�_f��_�p��dz��m�1fȐ!F��3gN�v�ޗ��:���uw���9��/��b*V�hʖ-k���;W�=.��&M�d$�1c���gĈ�n�ڹs�)T���dF��f�[o��n���{�I��K��cǎF��4iR��|�d:u�d7���P{#t8���߰a���q�F#�<���0Ƙ��xS�T)S�P!s���4�.]�d��܌����y�1�������f���l)))fԨQ�F�)Z���7���_�'�m����{�;yVr*C���N���#��n�ږ�f͚f�ĉ�ԩS���dt/���I�����2���n$������?~�H2��޶uw�s˝r�p�c�����#Iڱc�C���ǫk׮������վ}��V�\Y����-Z$I�ѣ�ݿ��.ݻwO�>;͒�:w%KjŊ���WHH��-�nݺ�i��}���lrO\\���g�}V
4СC����/�:�5k�H��jw�u$����g�ǵk�ԭ[7%%%�M�6�<yr��7n�$
2$ݾ
6�1F�O�N�>::Z?���,��l�ѣ�,�V�Z����s����[�L����[׸qcIҕ+W2�!I�ٳ����ҽZ�x�ս{wyzzJʙ��[��f�X4e�<xP#G�T�Z�d�Xt��
mٲE�'OV˖-U�Z5mݺթl���Y�
����I�2eԭ[7m߾]͚5����U�re5n�XӧOWddd��ƍ


R�J�����{LcƌQ|||�v�F{L�X�;wN�z��< wwwթSG_�u��(��%J�H���o�U�-T�dI����bŊz���m�GJRJJ��{�=U�VM*V��7n�f�)G�]�|�AI�;BN�*Ud�QTT��ZY��>֯�l٢ҥK�E��ڤfo}V�7�c69]���)=z��d�4ib�m��o�$��sϥY��k�I��_6)))��ג}��I��СC�9ȍ1&))�<��CF�ٽ{w���ر�H2=�P��nU&	�H������[����$ӿ�tm��/Ye͌�}�s6���S��ر�T�R�x{{������q��d�����w�F�(Y�d���ܹ��d|||LTTT��Ό���_I�y��v�7k��H23f�H�͚9666G�X��u�V�۳Zo��jժi�ժU�H2���u�ޗ��~$'����h���?�>���m��.\�H2���&444���=�jߌ��ɳ�SR��wnwz/���)���JLL4?���ٳ�)^��)X��iݺ��?���w��MӰaC����Ϛ���4�3[�1&22Ҕ/_����.�ߋ˗/�޽{I�w�I�m�ر�G��v�F�ʰݴiӜ:wc��3g��dJ�*e�~�m�u��,�_�~}�_ׯ_�X,ӽ{�����ٹ��_{)N�%�ϟ7%J�0�L˖-��ݻ�͛7ͦM�̀����)T��9p�m��+WI�N�:�ƍY�������K���Hk~��S�fM#Ɍ7�c�ڵk�$Ӱa�l��'�$��O?��e�KFG�d��̶g�><<�H2E�1�̮]�ҵq�d'kf��a����� ?���7o���)X��i۶�9���#!����f���
�=�ܹs�$S�X1s��a�m�Ӹd4]�=O>�d�r5j�(ݾ����L��|?ҤI#�lݺ�����~�ޗ��~�N�����Ę���ɱB`g�Qf�s�Y�������8%���8b^z�%���a<<<��/�l���[�i���8q��d|}}́Lbb�9|�����3��ܹs3�wժU�hѢF�y��Ǎ1Ƽ����u�?n�_�n^}�U#�]X�ZfײO�>�
?�ǚ1c����3�����_5R�� �u�֙[�n��ׯ�3f)�QΜ�ҥKM�ʕm9===M�-�_|a�.�󳷮{��i�g������Q�(N�Mk֬1^^^���nРA�~�ڼy��b�ۮq�ƶ_>Z���̈�è.]���e����f�n��Q�FF��]�v��:z_��53�0��l��S�_�߿�ԪU�+V�̞=;�Q�{��~˙�!��9b
.l,�Y�re��+��1�#�dw9r�H��3�7��,Y���v{�.\h$�޽{c�2d��d�̙������n�q&��0�ܹsY��|����.x�*Kv���n��͛7���ϊ3���N�������)�]�z�L�:5��Ç�pt��թS�H2�N�J���ɓF����ԩSm�E�=����T�V�H2;w���ؙ}��W��Y�lY�}RRR�޽{�ܹsͰa�l������6�L�֭ʹi������n�1���f����瞳�W�zus�…t�g�������Ye����(�{{��X���WXX����G}Tnnn*Q��Z�j����k��i����o߾ڲe��{�9��իW�|�_�U����z��V�Z�ҥK�k׮��7  @%K��ʕ+u���˒� I�߿�m�/wӽ�
��IJJ҄	���ҥK+<<\��bqu4�c>>>��;v8�_||��v��8�?^�۷ϰm�ʕ%I��{ѢE��=z���ҽ{�4���,9�s��*Y��V�X���x����hѢ�֭[�v�ޗ���lu�֕$���Y�uww��ĜR���?���ťۖ��~V�ɐ�{�9����ҥKգG�=Z^^^jڴ�/^�)S��p�����ĉ��J�*�b���9:t(M���D���_#G�TJJ��x�
�^�Z%J��$�>}Z���Od�\R��v횾��[���_�ڵ�fΜik�ʁ� IDATw��E=��z��'�ꫯ���?��Çm}XM�:U^^^Z�~��|�Mծ][�&MJ�L8z�5h�@AAAZ�v��\��q����ѣ>|x�ιZ�jٻ8�q���8%�U�ZU����ٳg�����W�j���jժU����љ~Hc]n��3�h�ڵ���֭[���k�ر���$�,YR7o�ԕ+W�] R�paEGG��͛*Y��$ex|G���Um�l�~�����/h�/�ɚ{�f֟����9�ƍ룏>Ҕ)S�i�&���pu,�ڶm+I��������b���O�~�ȑ:x�^~�e�;6�c4o�\�4o޼t�"""d�X��c�I�����x�bI�СC3�wȐ!�����Z��ə�u&Kn���R``��^��)S��ʕ+�ڵ��-������np&[�޽%I�Ǐ��3���ɒ$??�4뭅z)))g����$�ٳ'ݶ�����Ǚg%���d�ʽ�$&&j���
T�r�ԫW/%%%髯�ҥK��e��}������k�l_GEE�U�V�7o����5�|M�6�V$�=�/�W^yE���$i�ĉ�mÆ
Ӿ}����7�|S,���ֵkW]�pA���W�&M�1c��GѬY�l�9��E��b��…��yzz��ߖ$�����:ό~L�sɭ[��m��9"��baZ��i}�%''��������������Ց�Od�����M�%�$ӲeK�{�ns��M�i�&3`����n
*d8`�g�ʕF��S���q�F�Y�?n<<<�$��;���Hk~�����ƍ3��v�Z#�4l�0[��OI槟~��S&�F8�%;�e�=�����F�mʍ]�v�k��}�N������:g�%&&���~�H2f�Сf۶m�ڵk&))�\�|٬Y�Ƽ��KF�)T��ٱcG��Z��Y�|�ILL4�n��yw��H2>>>f۶m��͛��ɓfĈ������<+�et&CV���s��og��INN6�7o64�J�2�����/���\�|9�>��:M̟��i��G�#ɔ-[�l߾�n;k�={�dy�̮ydd��d���l�-j$�9[?			v�ڳg�y�����s7�#Ɍ;���0#ɔ(Q"���蜭S���:j�޽��g����(�{{)N�'P�����ɓ���ϸ���?��$&&�:�G�o�Y��xyy�>4�}�1cF��
4Ȱm�%�y���>�}iܸ��y�1ƘΝ;If���:Ϲs�I�K�.�uY}���,��ϙ��F�I�v�����}�N��8�3٢��L�֭�|n�/n�/_�n�f͚e��eu�{��MS�z�3gN��;��d���Y��3�"uߎ����F�y�G�$S�n]3e�s�̙L�sTPP��d�~�i�o�>���h.^�hF�i$��͛c�)Y����.�ɬ�c���Μ9cbcc�k��f�75{�<))�;v̴k��H2����m֢����?��͛f߾}�nݺ�~.]�d�1�R�J�{cnݺe������x$��n�1����d,�6l�9x𠉏�7W�^5+W���w�޶}���c�2=gc�y��$3u�Ts��
a6l��}v���c���y�)�+RRŘ3L�"ELݺuMXX��#!r�ֱc�L߾}ͣ�>j���L�%L�V����ӵ�~�Hq�1�lݺ�<��s�dɒ����T�^�|�&>>�cLtt����4�K�N��FbccMɒ%�������6�d�@#�,��Fq�W_}e$��>�,Ӝ�ܗ�d͌#�)�d�Z�n��ѣ��V��)\��)P��)^���5�Ǐ7���v�;}��i۶�)R��)T��y�G���j߾}�}�����۸��___�z��,�w�Y�,���sn��g�S:u�d��G�8|�p�m��\�^�j�W�n�{K�…��������/�r������_�͑����n�m�fk߽{�L�[Gv�5kV�mڷoo�/��ne-Z�h�V�Z�Q]ʖ-k�V�b�t�>����m۶��g���;6�Z�I5�tV``�m���_�3%IK�,����;wN���ӯ�����zK�ƍ�����c!���X,-Y�D��?���+W�^g��ŋ*_�|��d�>�	&�~ЅT�xq5m�T&LP�ڵ��k���������?+..N�k�VPP�:v�h7Gjnnnz�Ըqc�5J����mW�^ՠA��z�j%''�N�:z��7��������?�5k�H��ϟ�/��RG��$����]�vz��U�dI[��9��֯_��3gjϞ=�t����T�Z5u��Q��׿T�hQ[�e˖i̘1:{��ʔ)��/���V���5j�BBB��͛뫯���?��}v���c�+��y�)��-Z�H����ʗ/����`�i������)�ℬ�Sr;���@�}!�����]�tI:tP߾}էO�߿�� �Sp����U�V-:tH�6mҧ�~*///W��7n�PPP�*U�$=��c3f����mm���|���i�
�$M�>=�46���i^g��ߣ�X,:tH�Z�R�"ET�L
<X���i�FFF�o߾*S������7n�;������{�V��<<<T�X15n�X_}���
�=�����DEE��^�7�|�W_}US�NU�b�\�O��ǫy��


��;s�&M��={���V�4c�m۶MÆ
����*T���g�jȐ!��~��i���wt�Ԛ7o����K��Y�f)99Ys�̑$]�zUM�4ѩS�l�+&&&�񃂂����:!!A�v�Ү]��7�x������)8`͚5�U���mۦ�k�j����rԴi�*___8p@���:|������q�F͟?_�T�dI-Z�H111�ٳ����իW/[1H�"Ed����d����#�jժ��㊋�Ә1c$I?��m�ԩSu��)���h��ݺu떶l٢����Zвn�:ݺuKׯ_׌3$I��yN\F���V�b
����ř�:<=�*111�߿�ڵk�֭[+""Bm۶uu,@>"IZ�t��ի�B�
�F�Z�p�$i��Ŷ�-Z�Ј#�e����i���>|x�����?W�*U���#FH�{41�+VH�fϞ�F����]M�6�̙3�U�hQI�'�|�/��B�/_��e���ӧ�� o�i}���l���;Q�BWG�}jӦM�۷����r�J�o��Ց�؉'$I�*U���СCi^O�4I6lЮ]�T�F
}��G���r��T�V-�ץJ��$����֝<yR�Ըq�4�5m�4]_S�NU߾}�~�z�_�^��ƌ���_*\�p���}ӧO���]@����U�
�Ĵ>d ..NÇ׳�>�F�)""��@�K]�aϵk�2�f�Xr�����:ePꩄ$���-]ۮ]��…�?��4ib�*�GѬY��u�ݻwk��宎���˗k��ݮ�Y��S�o߮����>��@@@��,Y���Ol߾]�{�Vtt����յkWWG�'{�1;vL���*V��e�ѣG�СCz��'�w�^���;9~��R��>��[����n׮]v�{{{�O�>�ӧ���ݫ�N���x�

4(G2�9�<ܛ��+��⮍�b�aaaaqz	�[߮p����רQ�����ի+""�������%,ǎ��wIv���'���{�J����'�I�x�m�K/�$�����߯��$EFFjԨQ�X,jѢ��߃�u�&I8p��nݪ��D�ٳGL׶r�ʲX,�9s��_���u�nݺ�Ҏ� ��S�+BCCիW/�?^s��Q�~�\	�???����:�b���…�yxxh„	��?����X�9Rqqq�:u�x������ȑ#U�paթSG������9r�>��s���


Ҋ+�c�5h� �1
.�iӦ9�{�ȑ���t������w���Vpc��[oiРA2d���f[�}ܛ�O���۷�:p��������]Bq
ྗ����'jҤIjڴ�֮]�cSwC�
T�BW���ڷo�	&�~ЅT�xq5m�T&LP�ڵ%�=��_��E��gϞ�}�-�^�ziҤI
�g�}�nݺ�`���u�$�D�ڱcG��p����6oެ�� }����Q�4{�l-]�4Mہ���M_~���9"I���Q�v���o;{��%�w�����թS'WG�;˗/�����c��,���+00P�no}�˗/��Wɒ%�q�F�?^���?U�lY�]�6'��5
6̲Mhhh���vVHH�mn���zJ�;w���W�Ρl��׀�"""ԳgO;vL}�j���We��
ng�X�d��J�~��� �
u��)���5k�y]�V-�e��8�/��B�|�1�ҥ��V��z��:�3���5u�T�7N���WXX��T���X�C(�y�=[�b}��eg�;!�v7o�Իᆱ�;�|�򒤗_~Ycǎ������啣����ĉ�ի���߯���k�ȑ*X���c���秐�W������:���K�S�M{3g�͙3����?������݂t��eu��ն�[�nZ�t�,X�!C��0��1F_|񅂂�T�Z5���2R�
*�B�
���-\ ��_��iӦ�^�SO=�v���O>э7Ҵkذ�6l�[�ni������S�-��{��ʕ+��������۫q��z��5c�%$$���ɓ2d����ԲeKM�<Y7o�t����f&��_��e˖��'�Tٲem�˕+��
jٲe�~���Y /;s挞}�Y���9r�v��Ma
��.**J�X,���PTT�]=��bqjzHg�s��x�]�W��Ҽ�̹�8%44T���
�$U�XQ���Z�p�$�jժ�6�t��
���OK�.եK�������H������Kw��?�X?��������kתo߾�����IHHРA��ٻ����ODp�DK=b�`�I�J�S8O8@�8uL=J~AM�IjJ��
PTL+,25'4�v�������9䄄�?��}�n@Pp;�׵��׽���k��:{�^��l�2N�<���IOO'22��cǒ��c�����INN&33��/�f����J�*=�o�����Z�li�O˖-���`Æ
%���ȃ*""N�:Ů]��>}:vvv�NKDDDDDC��������X�b��3z4t����)������H�:sJjj*���۷��/_Α#G�Y�&����ڵ���jԨAZZ����V;v�`����ڵ���HjԨ�ɓ'���6�DGGs��A��݉��e������ѤI��������v�ڬ]���;w��-[�<?�(���(9�ܹ�
X�cl3ƈ�<���y��W	$00����)N��X�6�~���撛�{��+������SO1~�x��+""""""{ �S5j�綑��#$$������$88�͛7[�=i�$Z�l���������q�FBCCqss��֖�u�2m�4,�

�V�Z�)S����R܊���Ç��4��S��Y��ȣn�ʕ���s��!�m��{g�������Xjj*?��#ժUcѢET�R�������C�o�!$$�2eʰv�Z�%�EDDDDD�c���"�Y?�̙����ׯ`ƌf���8qOOO�~�{�9N�<i1�����v�&M8~����رc�����lb�4--͢_WWW�w'''�<����-_t��(���q��
*X�cl������ogϞ�O�>���ҷo_���G�֭���������GG�%00�􂑋���y������s;��@�޽y�'�����ՕI�&q�ʕ|�Z�l����\�r���Ϭ��܎=J�f�(W�����=�7_����ޞʕ+ӵkW~����_����z��dgg����M���M�FE�/�IKK��ח��/^L�����7����(6l���O<�}��5�8'""""""�Ϫ3�ܫ��BJ�.�gl�R�;�;M��x;;;��L���h���s42�ݏ�ED�%>>www������oY�h�ʕ�vZ"""""r%&&������NVV�N�"66�f͚�9S�8::�m/[�ooo>��3Ξ=���9r��g���z��E7n�0-7m\������ܸq���駟���0��s7��Z��W^y�ݻws��u���O���iժ?��C�y���Ѷm[N�>��_�gLBB�O��m۶����w_�^�J�����?=z4���z����{�G@@?��3��ٜ={���8����ꫯ�ܟ������ܙU�S������c0X�`M�6��e�F��ݻ׬㶋���)))f�{���o����xܺu���$99���^%ǪU�p��E�~�m��G�ŋ�k׮���+�߿��_~��i������}v��yz����˗7n����v��v�b�Сdee���Kzz��q������P�O>����~c���ܸq�#F��o������۩W�{��a�����_��S�NѠA�l�-Z���͍��t������?�������ŋ̛7�r6lo��������bǎԫW���L�y�s	 """�QQQ:������_���Tڴi�������MRR���8p���/��qW�������H��6s�q�Lww�<�oծ];BCCIII!;;����}�]ڴicq�̙3IMM%;;�={��(t���Ӿ}{BBB8t�7n��ܹs|��xyy1bĈb:ۻW��}�Y����3�cDD7n�q�Ƭ_��/����K�R�bEk�%"""""V����3g�LXX�����ooo>��c�|�M.^��G}T`?IIIL�:��'���kڷd����/�����ŋ�S�vvv�iӆ+V�駟Z�t�R
d�n�6����ɓqww��ɉ�5k�S.���|��Ԯ];;;Z�jŒ%Kؽ{w����ٓ*U���7�p��)�}gΜ�믿�r�����(��2{�lV�^M͚5Y�z���EQ�~}6o�L�-(S�
6���?�}��\�x�tDDDDDD��<�)~~~ԪU�'N���7�<y�Z�j`qL�*U���ۛaÆq��)6lH߾}M1���ԩS���H�-�ԩ�~�)�7�$N�H��c�V��\�ؖW!������ի�5�N�:���Mjj*>>>�NKDDDDD�ȸ��o���~�L6lȷ��/ҿ����ԩ���(�M�60j�(�c��������~3k�p��֭��Ɔ��4h666���s�…|�j۶�E���b4r�H��^x��g��@�2e<x0���,[��l_tt4ׯ_g�888�s_6n�HHHeʔa͚5<���X�)S�X,�T�T)�z�-�|EDDDDD��<0�)0۾U�
����O�>8;;ckk���3���g�ҥ899YF�֭)]�4���<�%K�`ooo�)_�<��������₭�-NNN�k׎�K�>��%�N�:Q�lY-�ILL�|��Z�BD	;v��ӓU�VK\\ժU�vZ"""""ben.�lccc�iԨps�������z��b�
lmm�������Y�V�X�_�E�v�U��پڵkӶm[���/V�\�oO?��E���b���j�V�lYnܸq��
@dd�Y��K���ߗ�~��~��q��
>��#Z�hq�
�W�@���8t��=�/""""""�J[k��m���X�"AAA���+��1��ɉ���3~���C���-��y[�˕+���/�8q�4��'ػw/Ç7=dyeff2e�����ܹ3�1...�NKDDDDD�.]���O>����8*T���_~I�ʕ-b�\��|����K�lٲ���������bt�\w�aÆ�jՊ�;w���H�6m0���������a�������A���-4 IDAT�9�<#F�`Ȑ!��7���
���UDDDDDD���fN�����G��Չ��1�������������Ƚ14k֌��p���ꫯT�""""""fʕ+���Innn���f���y��7���!::��
8Fa<�?�P����d~���B��M.���S�5��:�}��ѪU+�ϟ_,y�w����O*U�T,㈈������8����ȴiӈ��'==���t���6m�i�_�����y��y��^�:)))�򦜈����<z�ի���_��233�ׯL�>�|c�������e˖0hР3�/�����>}�P�R%���233����|������,�n�˼y�X�b5j���>��ήX����lOJJ�n�$)��SA͚5cԨQ̝;��s�2z�h�6mj�DD�,55�-Z0w�\���شi�k׶vZ"""""�z�W�9s&������ⰱ��K�.f�&L %%�=z0y���h߾=�RSS����N�:ܸq���h�x��5j�~�i�3��k.%��ё��2g�Ξ=K�~�,�����y�f�z�-���Y�f
իW/���͛g�v��
fϞ
@Ϟ=�m,��+N1k�au���̛7�y��Y��""�3>�������{�������EDDDDDF�EŊٹs'���
���dff�e��ΠA�(]�4����c���裏���`���w��1r�Hʔ)CTT����>}���6o�L�~��`Æ
�<y///����}�x��8y�$7n,�%����9s�%}���رc��ۗ7n�`�����5焄���ˡC����"%%�W_}�;v�����bODDDDDD��y���?��M�6����L�>���D�y�k�%"""""��5k���#�}�-Z���ё:NVV��ϧI�&�c������B��山���c��3ϰh�"lllx��w�^�:�ʕ��_����L�4	��K�0z��B�o�=�xܝ%�������?�իWiܸ1-Z���)�}���9{�,Ç���w��$..��7ҠAʔ)���'�ׯ�z��|��Z[DDDDD��8EDD���,X��&M������`୷�����ک������C�K�.�ݻ����~�i���X�"/��26l`�ȑf�k��`۶mt�ܙJ�*aooO����1c[�l����?�����x�V�j���N|}}�T�_~�%��g��RҌ���5k�QQ�˺u�J4�޽{�u�V���(]�4u��e�ĉ�߿�ƍ���""""""����N@DD��ѣ�}�v����<y2vvv�NKDDDDDRnnnDDD*�…w5F�6mhӦM��+U�ĵk׊�gٲe-���ͽ�\��_~�:nȐ!2�c�����/w���;����?���=�#""""""�sߊS���s���G��ի�vR"""?~<�j�b���4m���)�������������H1*�e}jժE�޽Kzy���;�u��ᕞ�Ϋ������9r$�A�)"""""""""""""���9�u�ִnݺ�����ʕ+=z4U�V%11�^x��)�������������H	)����XP�È�c��ח��k�!��̙3�9��?��7�x�Y�fQ�lYk�%"""""""""""""%�ċS������P"�R���o�ڵ�9GGG6m�D����������<Frss���������c�����~
%"��/����)�]�p�cƌ!::�!C���������������g���:������+����[;%�Ϭ^�r���t�B�J�شiǏ�[�n8;;���`������`0��>̳�>[`LI9y�$���$%%q��)���xꩧh۶-����/3�|���HJJ��ۛ>}��Xn"b}�/_f„	|�����ۗ�>��*U�X;-������ШQ#�mwww��t'���?ٶm�})D��/��°aøz���-++�Çs��a֭[GDD���=���ٳ���j�*rss�۷/nnn4i��ک�H	ضm���:�/_fժUZ�MDDDD���׭���cg�����Z;
�"+e��+N1n?�Y!ʶm��SR�͛�իWiѢ���$%%�c�>��c�ׯOzz:.,�<
�ڵkL�2�^�z���B�5�ѣ�'O�ڵk�NOD�ѵk�7n:t�q�Ƥ���0EDDDD�ԢE�}+�ݻ7-Z��v""""""Ef��S�K��*<<���p��X�`�Uf'y����0s�L*U�@�ҥy��

�G��رÚ)�����̙3�����ֿV�XATT�F��bv"R\v�ލ��?���DFF���g�DDDDD���3�1c�X;
y�X}Y��0��ܹ�Y�f�q�F���iݺ5cƌ�Z�jf�/_&<<�͛7s��9�U�F��|�򦸜����ٰa���������J׮]�֭������&��[�i
���ؕ+WFJJ
eʔᥗ^b�ر8::�b�T���ӧ9{���8ŨV�Zy�ddd�ƍ��?�V��;wf�С����u��>��������a�ر\�|��+WҼys�e��W����+W�dРAT�P��~E������ә3g�۷gÆ
<����NKDDDDDJЀ����v"�-___bbb��������H�X�8�X@��/����K�ڵY�f
����������C�ٳg�n�:233IHH`�޽DGG�����+W2dG�1w��)bccINN&22��e��p�B�/_n��~�:���g���\�z��9%��Çs��E��Y����BBBL1C�e�̙ҽ{wZ�n���;vvvy摕�ň#8x��8�Ajj*.�T�RE����OLL�5"00�o�����Z�li߲eK���ٰa={�,�Z�ȃi߾}���������1b666�NKDDDDD�;;;�q\�
��y�������5Yu���T����ܾݎ;�?>͛7��f��ɜ<y���h��0˗/�ȑ#ԬY�3fРA<Ȕ)SHKKc�ҥ�صk�7������$$$0k�,V�Z�珽�fI�]Q�0�]�6ӦM��'�$""���H�l�bV�ҽ{wʕ+ǢE�X�l˖-���OOOڷoO�n��f8�����������+G�%44���d���M��%�Vaaa���R�n],X`*�ٹs'
4�8�ضs�N��<d���	

e�̙�hт}�����j�DDDDD�>�ݻ7�{��v"��/����)������ܕ����O��(�5�s�v�&M�e˖������a*�زe�)�=$$������$88�͛7�b�E111���q��z��` >>��έ(yQ�V-ʔ)c*��t�E\ǎ��/���Oy�7���"55�9s������a�ݸq#������akkKݺu�6m			wkd,Lqrr⣏>2�`p��a�f����ԩc#"����/0k�,fϞ�֭[U�""""""""""""""���)ƙG��̙Ü9sL�3f�`ƌ���$���f�5i���Ǐ��N�8����Y�s�=�ɓ'Mmcǎe���$%%�����ŋ	�����>���at�x�E999��ѠA4h���?YYY,]����p�{�=�<v�>>>y����f�^�X#��K�/_�…<���}�ϟ�B�
�ی1"�`���!,,�)S�����O?�D�����������<�Μ9C�.]�T��6m���t��
gg�<_|y>|�g�}��;..���$��s�>}����DDDDDD�fՙS��ti�Zc�F�Rw>���<:v��7�|�ԩS���$33�E�ѥK֬YS<I"#;;;�w��mڴ��ˋ3g�X쳷������ 77��|�\�rW�F�B���\�,Yb��xy�c[^�)"�_���m�”)Sرc�
SDDDDD$_�͔��2Ώ���y.%m����…�8q"&L`���ݻ�>g(""""""�*����Á�&,�iӦ��V)))f�{���o����F�?���...f�NNN�����������ҥK�����95��hР@��3G�̋A��[���?���wk4~�xؾ};4�Z�*/^�8��f��Onn.,��Ã�W����Lpp�E�������ȭ�����f۶m��׮]cʔ)���jԨA�=�<y2׮]��Y������ȣ�j3���Laޢ�9s&���dgg�g�BCC�ԩ�)�]�v������Bvv6)))�����G��v튗��}�<��3���泘��8ۇq��%���߿?������{������ŕ+Wؾ};'N�}���c��CBB8t�7n��ܹs|��xyy1bĈ���Հ�W��/6���5����f�)lE�`G�套^b���L�0�ݻw[,S&"""""b���e�,_����p���X�r%,�X�YQQQ�9s�~������ϙ3g����bf""""""����wS�R�J�����6lH߾}M�~~~l޼�cǎ`[�V-�6???BCC�5k�f�2�mڴi�yT�\����ӣG\\\X�n�ELQ�(����3h� >��SV�ZŪU�,bj׮͘1cL���lݺ���h���q��*�V���3d�v��ž}����U�Vl۶���T��i��wS�#"%+""������SO�k�.=<����ӧY�h;w��ʕ+ԩS���ӥK��˗/��͛9w�ժU�C�R�|yS��7�ʕ+	#%%�2e���K/1v�X��K9����a���ӱ����Օ�]�ҭ[7��n�n0L���Ù0annn,Y��,�Vy�������ˬ\���͛���l��^����hРAT�P�h7BDDDDDD���)0��KXX�[��t��8;;3x�`�,Y����)�B�
DEEѧO��������ٙ����t�R���L�=z�`�ԩԯ_{{{���quu��ߟ�ӧ�DŽ	�Y�&���dee�S�<���7�d�…�k׎'�x�R�Jaoo���#G���O?�r�ʦ�������/...������D�v�X�t���%E�����ݻw�7{J�N�([�,���񉉉�/_��_~������'N�ꫯH`` ?���
SDDDDD�P�K���7_�1,]�77�<�p.n�ϟ��Ϗ����?�����l��Ҙ:u���EW�\aȐ!�X��ӧO���ͩS����e�СdddX�=|�p��������ŋ�Y��lY���'�p��1�_�NFF����w�!&&�P����q��e�"��<�|��dddвeK�}-[�$##�
6)��Ym攄���M�6��+�*.((����;������S`��N:v�Hǎ�)J�=�ɯ���oo�������Ǐg�����Wn�����˕+���/�8q��5k7��w�^�Nٲe}"Rr���3fժUc���j���)������C�nf�-N˖-��ٳ4lؐw�y�jժ�����k������9r�5k�dƌ4hЀ�2e����X�t)�F�2�v��L�6�'�|���"##ٲe!!!�]����Eׯ_'!!�Y�f�j�*`6KJ^�V�֭Kdd�ًX�u���s�N4h`ѯ�m�Ν��ٳH9���������j3����Ϗ�ի��!������A"r��9s��={2x�`�޽{U�""""""w�X�ҨQ�<�Kڎ;�8q"�jբlٲ���`0����Mq[�l $$������4�t�y�f������U�eʔa��\�tɴ�NLLqqq\�p�^�za0���/T�,raJQ�;/�n�ܮN�:f1"""""""wK�)R��6m��񤧧���N||<ӦM�����<�֮]K�ƍ���ٴi����lF"""""rW������2a̙3///֯_��3L1%��ɓ.M7gu���4k���������q�朜S�رc)S�III������ۗ��H233�����
{�y9�<ps���ی1"""""""wK�)R�5kƨQ��;w.s��e���4m���i�<�Ο?���ٳ'���)))t���i�������3�{:��b�����8Nǎ��o�:u*���dff�h�"�t�š5k
5~~����暾geeY쿗�6[���cBc۽^W���8�`0��<<|}}�7o��ͣ���NG���_����֭[��o��OLo��������-��@xx8���,X@ӦMM�vJ��ΓO>	@ZZZ�q5j�`�޽f��m�����	"""X�|9~~~\�t�������Xr��US[^�V���KժU�x��>c�1FDDDDDD�n=�)""ro.]��СCy��Wy��ٿ?�����GHjj*p�8%��U�V̝;�S�N���iZb�{�v��JJJ
��٤�����ЦM�"�ݵkW����������g����
�{֕cǎݱ�ʕ+��_p��5�9¬Y���۸�ѣG-�5���rA"""""""�*m�DD�dm޼����]�ƚ5k�ѣ��S�GЃP��믳q�FRRRx��W�
6����Ϗ͛7s��1��jժe�V~~~���2k�,��[�7�\�2�ϟ�G�����nݺ|�l׮k׮�>�>�e˖q�=��nժ۶m#55�bf�=��b�[i��G�իW=z4/��͚5c���*L�s{1ʁ̶U�Eǎ�P�vvv4hЀٳgӥKS\�
����O�>8;;ckk���3���g�ҥw��i�=�:u*������{{{\]]�g��馸	&P�fMlmm���*��q��ѫW/*V����=-[�dʔ)w}�y�ݩS'ʖ-Kbb�E�����/_��_~���CDDDDDD�V�m�իW߯�D��z�jz��m�4;v��ߟ.K�~���������<�̶7m�d�<jԨAhh��*V�HPPAAA��B�������S`;v�cǎ���ёI�&1iҤ;����\�r�����'�Y�&'N�`�޽>��e�د������ȝܷ�>}�ܯ�DD[���L�2���0:w�������������_�5111�b���\\\8p����GA��������[�È�<�~~~?~���p�b�DDDDDD,xyy�H���>"w���ȴi�x��74h���̟?+g'""""""��/Nٱc���/�aD�1кukƌc�48YYYL�>�9s�Ю];�]������H�f�5js��`���4m���Y������ȣ�ċS�;��ի�ݻwI%"��իWcggg�48�����Ϗ��4�ϟψ#����vZ""""""��'.̀,""""""%�ċS������P"�0`��Sx�dgg3g��O����?Ͼ}�puu�vZ""""""""""""""�[q��������_�}��1s�LƏO�R�����������������H���L��DNNs��5����?2a����������������푚9���x0�.���#))	ooo���c�D�a�믿���Orr2o��6AAA�.�H�'\DDDDD"�W��[�n�NC䱳z�jz��m�4DDDDDD�Lټ����…Y�j������777�4ib��D����˒%K�8q"���#99OOOk�%"""""���ׯ��)4���k׮1e�z�ꅋ�=z�`��ɬ^�GGG+g("��G�2l�0�l�BPPo��6����NKDDDDDs111���X;
y�<0�)�<�"**�3g�Я_?S[���Y�bQQQ�5ʊىȃ*""������SO��Ӽysk�$"""""����ٱc���yl�nݚ1c�X;
�"y`�S�����,Z���;wr���ԩ���ҥK��]�|���p6o�̹s�V�:t 00���˛�rrrgÆ
���cgg���+]�lN' IDATv�XC9##���6n���A�j��ܹ3C�5�����ˬ\���͛���lj�^�:^^^�\��A�Q�B�b�J"�KOOgذa|��7�?�3f���`�DDDDDDLv����ի�ݻ��Sy�^�;;;k�!"""""RdEq��������ٳ����4�N�ʍ7x���<�ʕ+2�#G���N�:Ell,���DFFR�lY.\����Mqׯ_g����߿��W�2`����1b4Ŧ��Ijj*.�T�R|��dddвeK��Z�lIrr26l�gϞ�puD�Q�r�JF�M�ʕٶm�[��vJ""""""y���>"V`|F)"""""�)e�
cٲe�={��
�v�Z�o�N���������˗s��j֬Idd$�v�"""�5j����ҥKM�k׮`���ڵ��۷3i�$V�Ze�����������ݻ����I�&$''o�ݹs'
4����f���י3g�ի�����ۗ}���0EDDDDDDDDDDDDDV+N���2��n\�x�ĉԪU��e���`���?�w�-[����vvvxzz��͛M��Tbbb����…�����`Vp�q�FBCCqss��֖�u�2m�4L���v���թS�,FDOk׮�q��6m�ĢE�(W����)6Ų>'O���g�-�q'N����Ӭ���3�`�رL�>���$���X�x1������`�;v�>>>y����f�~��y*T�`gl3ƈ���…�3���h�BXXNNN�NKDDDDD䞝9s�.]�P�R%6m������֭���f/�<�/F�}[�l!>>�p���ׯO��ڵk��zJ��Ç��<� ��oA��1����7���#))	ooo���c�|DDDDDD6V+N��eA?4mll�u윜���;����֭[���/ٷo�-"::�ѣGӳgOrss�ʕ+y�*e9A�����MD|�ׯg�С�����W_���)���������T5jd����n���"##�I�&�ߛ�������Bdd$S�N�]�v%��?��O�m�f���={��p�BV�ZEnn.}����͍&M�X;5���Ֆ�)�'�|0���0jԨ�޽{�ڍ�...f�NNN�����������ҥK����b�Ǭ[���`�INN6�V�Z��/Z�fl3ƈȣ�ҥK:�.]�жm[RSSU�""""""����S��������{���y��ٰa�w�&>>�\��[o����K4�m۶�h�R8׮]cʔ)���jԨA�=�<y2׮]�vz""""""���8�U�V̝;�S�N���ɜ9s���{��g|�%44������III��w��M�6�خ]�����g�}FFF�<�nnn��ٙ�ڷo�|Pq��!nܸ��s������bĈ�X㴫G�����V�S��ȃk���xxx�n�:>��3bbb�R����)^^^�������ˋ�+W�`��̹�;v���H�*UX�t)���U�T��֖5j��o0b�nܸ��E�����QQQ�9s�~������ϙ3g����bf""""""�-�S���:7n$%%�W_}�l߰a��=��Ϗ͛7s��1�ժUˬ��Ϗ��Pf͚ŬY��b�6mj�����֭[IIIa�fq�7δݪU+�m�Fjj�Y𿷆n-��G�q:�ҽ{w/^�������*c�Jxx8&L��͍%K�7GEDD�q�F����U�F�Ν:t(���f�|��w�^��C����I�j�h׮�F��lٲ��s����G�m�6�]�F���kݺu4(��n}��%77���뛵6o㹯\����0RRR(S�/��cǎ���Ѭ��֥��n������(��w�rrrgÆ
���cgg���+]�v�[�n��/_��ʕ+i޼��?իW7^
4�
*�uy�=0�)��[�jU���X�p!�v�"33�z�����ϋ/���q*T **����lݺ�s��Q�jU^|�E�
����)�G��.]���8�9��O?M�6m���3ŕ/_���H>���l�™3g(W�M�6eĈԫW�۩S'>��<x�Yn����/_��_~���JD��=����={��˗[�������<*��u~��|}}�]�6k֬!55��܈���8.,,�˗/��🕕ň#8x�)&==���HRSSY�p!�Jݜx���DDD��w��)V�\ɥK��׿��,0�ĉ�����s��U�|�K�g��K�r�2d�Y[Q�6>|�i����L֬YCNN!!!��mt�u+�(־Gws�o�^.4��p��u�������z�*��o�%##��-[Z�ѲeK���ٰa={�,��y�=0�)wR�F
BCC�ɫ��bŊt�1|||���c����Ǐg���ƕ+W___"""8q�5k��ĉ�ݻ��Ç��+"b}���L�2���0:w�̖-[L��������<ʌ3ź���}��u�i��"::�����Npp0���=z���P������7�l�b�
&M��k�����
���g���$&&����O9q�O?�4��nnn�߿��S�Z�s��9�"��+J�F�k�fڴi<��DDDɖ-[		1�%%��]�_��^��e�%kߣ��ַ_��k��[j��$$$0k�,V�Ze*Nٹs'
4���ضs�N�������B�;�Ƚ���z����Ę�bbbpqq�,
"� ��@�f�'<<����J�)"""""��0�4j�(���
8�l��7������ԭ[�iӦ���`�ݾ};?��
6�o���?d���\�r��u�V���iԨvvv4mڔ�����E>������鼋��QPP�jբL�2�b�K�.j�ۯ[a�Eq��=��k}��2�,C\\.\�W�^���Mq�nݮN�:f1""""""R��f攇���#ӦM��7�dРA���3�|������ׯ��;����������+�G��3o̙3�9s昶g̘��3�@��7:v�@�3ۦ�����={�q�����?[���暾?~���{��8ggg�?Nzz:u���3���\�^�J����*o#WWW�w��Ӆ-�����Z䧠�o��־Gws�o�^cǎe���$%%�����ŋ	�����y��灛K����f����8�>h֬�F�b�ܹ�=��M�Z9+).)))���s��a���x�7����vZ""""""�[g��;R�:�Ɯ9s���y��i۶-���4jԈ>}�����}�.m�X��Ã�Ǐ���[�r�^�u5jDDD���E�������!o�n�����n���׫cǎx{{�u�V���K���ǢE����f��Ѧez���T)�ɧ�m��/"""""R8*N�O|}}�v"R�����3gӧO��g߾}ԫW��i�������w���~����@���Y�t)�v����M�6%<<�P����p��Q֭[���K��IIIDFFR�re�9bڟ��M�ҥy��9r�?��-[�4�7.9t�Ν;���@LL]�t�J�*f�srrX�d	������7-T��KBa�Eq��=*�k��䄏�>>><x���e˖f*N�Z�*�N���ŋT�Z��/�bDDDDDD��,�ED�:D�֭�1c3g�d۶m*L�ǚ�����=���h߾=!!!:t�7np��9>��C���1b��1�v�"++�C�1y�dS��K�x�W

姟~";;�0s�L��^x��6m�����?6l����\�~�0v�X���hժ�z������8#�q�¸ӵ(־G�q��v튗��}�<��3����3�<��=zԢc�1FDDDDDD
��SDD� ''����L�F����iذ������(N�g�֭���0p�@�}�7δݮ];�:u*S�N���СC�lْ���w�q��aM�;u�g��Y�9r$���+����۷oό3̖s)JޅU�reΟ?O�=pqqaݺu���Zkߣ��~~~���2k�,f͚e��֥�[�jŶm�HMM�X���w�6m�8�������h��B���_i߾=o���&Mb׮]*L���^�r����(_�<��������₭�-NNN�k׎�K���R1q�D:v숣�#���4jԈw�}�Tܰj�*���	�W�^T�\{{{^~�eBBB�̡J�*,_��7�|�F�Q�lYʕ+Nj/�ȢE�x�ppp��k„	ԬY[[[���
�-�(־G�q�{��ԩS�_�>��������ꊿ�?ӧO7�u�ԉ�e˒��h�Gbb"�˗��_.�5y�����g����0c��m�{���KLL��+��{q��iv��aZS�v���,Y���'R�^=�-[����=�+"""""�0���Wq�y�-Y�������j֬	��'�֭Çg�С�5��(""""")C�/�Ӻuk���JzyԪU���q��[�&--������z�l��ΐ!CزeAAA�������{"""""""������믿&&&��� �f!����ŲB""""""�?-�#"����_�����k
�l�27n��Ύ;�9s�
SDDDDDDD#���L�6���x���IOO'>>�iӦY,�$""""""�+�Sv�ءe}D�Xܺ�Oq���9s&�-�q�ƴk׎��H:w�L`` 			���̜9GG�bWDDDDDDD͚5cԨQ̝;�ѣGӴiS+g%"""""�p)������5��<����-==��{w^ӵ�q�iBi
M���TL�������j��:���[��-RT+�J�V�ƚ��M"�j��PR��D����oN&�d��z�<�^{����lIO����s�μ��;|��>�����cǎ�s�N5j��������//��CDDDDD$�Ҳ>"��IJJ�G�<���,\��h���pqq!88��~�M�)""""""""""""""�@�)"��7n!!!�Z�
ggg����	???�l�B```.F("""""""""""""�xh�d��˗���CHH���xyy�d�BCC���ض�y���2Vb:q��+W�y\r���P�~}�v횥�D�M�61e�,X@͚5S�oԨ~�!Æ
�E����_.D)"""""""""""""��3�)>>>:t�ؾr�J.F��>��#v�ܙ�D�Ç���˪U�0�Lt��
77�4oȋ<	Ο?O�^��޽;H��G}ĬY�hݺ51B�����a��c�d2�v"�    ��y"yyy�v""""""6�3�)aaa̟?�:u�p��]Ə�#��JBHv͵s��,7>>�1c�йsg\]]�ԩ>>>�^�''�,�/��ܽ{��ݻS�xq���+�}7o�d׮]l۶�;vp��a�_��-�DDr�� ����?���a��#�>�cǎ����lٲ�����������-s��]�������-��h���\�|��ݻm=z�`Ŋ,^��!C��bt"ߘ1c8t���ޞm۶�m�6�o�NHHIIIT�V��͛���C�&M(Z�hn�-"��.]��v"�ILLTr����������d�G&9%#����u���X��ǢE�زe��7%J���^���YJp=z4�6mb�ĉ�i��h߸q#>>>���L�:5U����c�…l޼��/���@Ŋ�С���Q��M>ޚ�����\���u����b��,YV�\I�^�(R�H��_$/Y�v-S�N�|���s��m*U�D�f��h֬��ϋ�������mΜ9Z�G$yyy����a�������$O$�dVBB�&22�h�x�"~~~DDD���K�|�25�ȑ#9|�0ӧO�v�ڔ,Y���h�N�����F�Js���/˖-3�	'<<�[�n����1��i�&������L5���'!!!l޼�7�|3S�.���={�H޺w��ʕ�o߾4k֌2e��rt""�#   �""b2�r;�cts\$w�}�������Uy"9��*))-_����H���5j+V$**�ɓ'BPPP�k$'�\�V,E�a„	2��cDz`�ƍǭ[��>}:���i�_�f
s����Ã��D֯_�ԩSY�j���鞯5c���@ժUS�ܶw�^%��a�ڵ|��W4k֌J�*�v8""9*000�C�<&  @����������H�˵��@R�ے��Җ-[�<y2�J��B�
�?��;�~��4�S�U�n]�I���~���pz���/��r��M���9s�M�6�s��t���dzv�'(W�\�9ʗ/o�G�q�����v""M�.]r;�c��""""""""""9.OTNɬ�g�о}�4��>}:�v[b�}�]8@xx8*Tx��C�2a����	f������///
(�-ccbb���]R2�����������d�˗/ӦM�y�~��Ν;Gǎqqqa���9z�'NP�re���*�&���RJ�"nzq�ϟ�r�����M۶m�-�ܒQ��@����_�>]�v}��������H�ɵ䔔�ffٞyк�7o�̶cY�e˖ԯ_�;v�v�Z~��7�͛����y��w3\j�ڱvvv�˗/��6s��@���-����s�}�;w���ϖ�;w�p��IƍG�…iҤIn��#>���/�V��d2ѭ[7��ܨY�fn�&""""""�c]9��Օ��(֭[���k���/�����T�V���H|}}>|x�c���i߾=�۷'22��[��t�Rf͚�ar��c�/Ntt4ׯ_�x���_�n��kbbbpuu%!!GGG.^�H�b����	�J�ήq�eϞ=,]��={�ERR...ԫW��}����vnǝ�G96�']z�)�휲s���?*I+)㈉��/�`���|��erJ||<cƌ�s���gt�:u��LJիW����������HNK]Z�1ҬY3F�����IJJ��ի̞=���<H@@5k���Ϗڵk�b�
<��:���w�}G\\�*U���
����v��D��5�����Ju|s[��""""yA@@			$$$�bŊ\���f^V�q��|��7?~���x8w���=�ڵ�m۶ܸq#���<����Z�l.��Ã�+W0w�\���y�+V��?��cǎ�r49c���\�|��ݻm=z�����,^�8#���NN�ӧ�˗',,��={R�^=Z�jŷ�~K�6lX�����@ll,�Ǐ�`��L�8���z��7n���i�ݻwo�N��+��B�
=z4�k�6�-Z���믿n�؆
�{2)9s[�ƍ�y	EDDD)K�,୷޲�~ԙL��^��ҥK4hЀ
6P�T)f̘�ѣG����Ν;?~�I�&Q�H֯_O���{��C�QDD�\���c��t�ԉ
��+�зo_~���T}���;w.�۷�A�����̛7�HX,�^�~���O�fȐ!4jԈ�͛3e����-�^�z��'Ҽys<==���!..��c����2�֜�٥K�7n���*��ק{��_�>U���XfΜI۶m�_�>�ڵc֬Y���6���_���Ń^֞{ll,+W��nݺ����%K�4���MDDDDDD�̲>9QZ�p������7߰}�v._�L�B��]�6��^���S�N�ҥKL�0�R�JP�T)>��Sƍ�ԩS����S��ԩO=�����9s�2e�иqc#���?��/�$::���ڱ�Z��/�`���ƍ�ݻwS�paZ�h��s�
��믔(Q�y����O?�ѣGs|����o߾�9s�&M���?��3�X�\�2>>>t�ؑƍ�s�N,X�{wK��H^f�\��ɓxyyQ�\9���{"""�ӧnnn�}}}�
+������έ[���WJ<x0���Fߋ/���GDD����˗3�^
4�X����|���ܻw�xP(66�~��q��yc�ƍ�u���`W� IDAT�0�L���0s�L ��G��LL�{��ʕ+F�ӧO3v�X������n޼��o�m|�M@@!!!���Q�`A�8f͚Ell��\b˹oڴ���8<==S����$$$�͛7?p�k���L����T	,)����������Y�n`۶m̘1#���}|��焆�Ҷm[�9ڶmKhh����VL�۷g����۷�}���j�*�{�=�)b�iٲ%k׮�lڴɦ��
��ˋ#G�X|Hp��y�9BϞ=S}� """b��)[�,������ooo��"����=�+���P�t�³�>���#+Vd�ȑ���Mn�ҥ���
2�›�3�-**�:u�P�P!��LVbزe�����ё�E�ҡC:�a'O���Ύ�%K�[���ݻ�,Y��of�uٽ{76l��g�e͚5�S�swwg�ԩ|����r���k��k�\DD�ʕ�N�:����F��S��������3�P�N&L���k�R͓޿��O޾`�*U�����*Ub�����Ǐ�L�28::R�j�t�4�5n��f������ٚ5k��K��߿�]�v1r�HV�Ze�[�|9���������f͚����χ �J�i)W�k֬a�޽�����۷����[Ο?O�2eX�t)���g�…�:u*��(�q�֭K�V�ؼy3���0�������]�r�jժ�f�v���o������oٲe�9s�ҥK������Y�h�J�����iV��P�{��e�ĉ6��޽{�Z�j�}�6sy|���M�޽)Y�$���F���?������3#�G��ݻ�Q�_�5��			Ɠ�u��I�,��899Yl/]�������w�q��9s�ӦM�W^I�ۤ�$�ƾ�2���˗/')))����ǡC�����P�BY���4kݺ5 11�k׮DÆ
9x�`�q���ѤI.]���?��f����s��%�4i���`�u1�V��X�b�6p9�ݻw���盙G���<x�&M�p��U�̙ó�>k�שS�����������_�ΡC�?~<�j��ҥK��'N�w�����ܽ{�ӧO��[o�y�f�w�΄	8w����?~�~��Y܌ͭ�ED�ʜ�b��r��Ќ��?������?t�ܙ��P���-[�0y�d��ܰ���B�
�? S�M��駟I��J.7n�0��ر�Q�FQ�zu�]�6����m:���=�j���/�L�(c��ٳ�O>���e�R�`AF�Mhh(?���Ϝ`3z�hjԨ���/���F�`۶m�b�ٳ'����:�'N��}R*_��Ey|)9�1������	

��ŋ\�x��� ƏO�r;<y���йsgbcc6l�N�">>����ӿ�����ŋ�L&S��ɓ'�����?���A��������?HHH`׮]���>|�iӦ��m�ƍDGGS�jU�M�z�pss��ŋ���r��)��ù~��Q6?��0���{�?���������/���۷���2�e�,Z�(��
���2w]�7�RV�KO���iԨ��M�̞of��ʵ0۵k͛7�֭[�]���
��
Fll,�ԩS$$$��۩V���'&L�굲֗_~��ŋ�v��.]�]�v�L&z��ƍ���#66��g�ҪU+�̙c1Gn�-"�Y�J �Ē�ӧ���ƍ�4i�E���C��?~������K�n��������={�_I6yő�;����փ��T�bE�{ggg�ݻg��;w�5jX��U��Uql۶�ʕ+���k���f[�…����2b����K/��y���I$f��{LL�E�_3s���������<�����S�C�aƌ̘1�w�}�ڵk�vX"""�ꫯ�|�2�F�b֬Y���(P������_��r��u�����	f�ر��'w����},�Ν;t�֍���S�|yhܸ1+V�O�\^�W�^�����'��・�;��Δ.]:K���J#�gϦ\�r888аaC,X��2���7ߤX�blذ���h�}�/_���hѢt����u����.����of��ʵذa�[�&>>�իWӼys�����+p�F�/����NNN4mڔ��@֮]��*___�����O?�����\��N߾})\�0eʔa�������z�""K˖-ٰacǎ套^���̛7�6m����L&S��ز����Z��[��z�)��wvvf̘1$&&2e��%�R#=��?��謑<�&��	����9�|�Rin�j�""""""��Sr�c��ˋ�3g2s�Lz���ለ��#̼��{w�~s%�͛7�;����ѣw�ޥU�VL�2�b�/����!CR����d2��X����?�[�;;;���Y�^����#((���'ݸ�4i��-3�����;��4h��+Wҍ�W)y뭷�{�.K�.�ط|�r�ٳ�Q�.3�%>>�…g��l9��ě�k��w�ѱcG�ܹ÷�~�믿��O�2ehӦ
������_ƾ�իc2���ȳK�ƍ-��K4F�Y�
�����ED2+44�����Nhh(s���v��iV)qvv�}��,Z��e˖ѻwonܸ��Y��>����[�.͊'!!!�,-�O:tȢݼ��5�T�B�^���sɗ
����\M�T�R9rĢݼm>fFl9��ŋ��'�dn3��Ǘ�SDDDD���H�
	;;�T_իW�/��������/�b�
���-��o��,#��+Vp���6mJٲe-��+W�&M�p��V�\���(Y��,y�����������Ϣ=�>���b^z e�Cf�r���7+ע{��$$$`2�Ҽ��F�`�����ٓ�e�R�lY���˚5kHHH�����&[�'�S��K�d~r���HV������N�C�xxx��w�G�J��D���5k��ѣ9~�8III\�z�ٳg���������prZ�֭�<y2���ݻ=z��?�ܦy�~�mJ�.�?��c$���r��%�f̘Att4�o�6�Wz�7�~M�65���ݻ���I�),�z��e�̕ݒ3�=h)"���3*""""���O����o�!00�"E��v�Z�-�����-=�K�l߾=Ò�K�,I���/�"����,mo�jժѰaC�����ݻiܸ1���DDD���/S�F
�of��/�@hh(Ǐ�^�zV��{�n���r���7+��駟�D��<y��r���T���ό'����/�,Y’%K�X�"�7o6*�d��N�TI[�ɍ�ED�–�޽{3y�d�N��ԩS-�%_��O�>�ر���0z��iѯ@�6��.Z�(111t��	WWW֭[g����#��Wu�FϞ=ٺu+'N�`�F{�V��L�H����ƍcРA�^��7�|������˖-[�]�v}͉�p��߶mgϞ�_�~�ʖ-��-��ްaCv��IDDD���F�I���M�SDDDD�B�
p��5L&S�_iU9v�~�!vvv,_��jժexs2ƒDFFr��A�����p��1��f&�얲zJZUS s��|�gӦMV�r��I�/��Wfd&ެ\�]�v��wߑ?~"##S-%e��o�믿������3�����:th��L&S��۷o�gfe6n�ܐ2��ѣ��u�ԉ�c�R�Jqtt�bŊ��Ӈ	&�
.���^^^���boo���3M�6eɒ%7>��cJ�.����C�.����…�ܹ3E���ё-Z0z�h��]�6]�v%))��3g����Y�x1-[��H�"888P�jU�M�F�6m�~E�a���t�����qqq�G�,Y�Ĩ��]�ުU+
,��ݻS�۽{7��E���d""""""��ؙ��5�6>�5ow��%;#"O�իW��兿�?���ƶ�ȓ$��[Y}[W�N:���y�׬w��m�իGXX'Nd̘1�U�G�aϞ=F��1��ӧӫW/�-[�n�^�z�|�rF�a���JZ����<h�����O�R��x�"eʔ���\�xѢ�Hf�KHH��գdɒ�<y�"E�d�ڴi�9��={���f�|3ov\�ٳg3t�P9r�U�V�j��~���_�"E�XTs����޽{ܼy�H�1;z�q�՚k��}��m���}""�����1�ՂX�h?��#�K���t�ؑA��JΕ���QDDDDD����R�lY%��H�u����e	DD$sZ�n
���ݻwS�������[���rXX�:u���'�c4k��E�������˗ ))��˗��{�e8�!C���oӬ��Xr������\�v��ӧs���w�ji��\��_~�-ZM�n݈��K7�s��1c����������L��q->��Z�nMBB�H�(_�<vvv���yzz�9�yY����T���nrZf�y��ݛ�%KZ$P������-��DDDDDD$0e3SL+"b��������a��䊔ﷲ�׹s�LO?��	05o��t�S||�i۶m���MO=������Ƙ�kךS�5L7o�|�1N�<iʟ?�	0���6EGG�nݺeںu��z��&�4n�8��d2�_���<<<���V�Z&��a��
H���%k��hz���	0*T�����S���u1�L�?���T�D	`z���M������ݔ��h���3�����O�nz��L�i�رVǝ��ě]�"::���Ϛ���#G�SժUM�7o6ݼyӔ��h
7�j����t�b1W�L��^0�޽�o:}��iذa�
�|�3�/3q�*�~����%��_�{L2#44�԰aCӅL.\05l���믿�vXy�~EDDDD$�:���)�m}�K_���>|�/'o&����&''�tϛ7Ϣ�:u���ܢE�Lvvvi�kР�)>>�d2�L]�v5�ŋ[��_mLݺu3��:~fb�v��g4��_6�_|1�ym�.f���J�*exm����LL��f&��?��	0=��Ӧ��ϛL&��릪U��O�ҥM����<�HBI��p��L]k[�e&n[)9ED����]���MÇ7
>�����I�y�<��S<$����P"�2��,""9�M�69r�iӦ�e����)X� /��2�|�	-Z�����|�~��Q�R%�L��������B�
x{{��'��?~�]�FPPŋ�{��V�����'�|�ڵk�v��<�L�Ē�HHH���O�������ݝ��p�-[ƚ5k��߸r�
����-[�f͚�����/f�9e&��m۶����ח��{�5k��������6mk׮�?� 11����ӡCF����>k1���{��e„	�޽�[�nQ�V-ƌC۶m8p`��V�L�"""�2///���r;�v&S��سA@@�����)�ED2Ü�b^�:嶈ȓD�D$���XC��<:��("""""yTh�܎@DDDDDDDDDDDDDDDD_mY�GՉ'�\��E����Dž��Z�Mo;�hݺ57n��ٙ�7��蘥9�@����_�>]�v��DDDDDDDDDDDDDDD$3��䔏>���;wf9�$'�ر�7np��
v��A˖-s9���������j�*L&ݺu��͍�5k�vh"""""""�e�s;�'��ի�����0DDDDDDl�D'��ܹ3��$��Tb�ڵkh׮?��AAAODrJ||<cƌ�s�θ��ЩS'|||X�z5NNN��������ȓ�^�zJL�%]�t�^�z������������Z�q��)Z�(#F�`Ϟ=���p��%�{��/G-^��˗/ӽ{w��G��X��ŋ3dȐ\�NDDDDDDD>��>���CDDDDDDD�G&9�A�\�œ9sسg���T�X���z�Q�F�I-qqq,Z��-[���S�D	^{�5���#�d���g&1ƚ��ē\PP�����^��ɉ֭[�r�J���0`@���.]b޼y�ݻ��7oR�|y�z�-ڴi��~��{��=.\��͛�x�"T�X�:бcG����Ʋr�J�֭�����^�dI<<<X�r%�z��H�"��"""""""�����	��0D�X^^^����v""""""6��)�nݢ���;w�h;~�����\BB�&22�h�x�"~~~DDD���K�|�Jܙ��d2��O?��о}{V�\ɺu��߿?vvvF���z��͕+W��ӧO3v�X����9��gK����,[��藘�Hxx8���ܺuooo��mڴ���8<==S���������y�f�|�M�^|��9.�̟��������5y"9��ߟs��Q�T)>��3�V�Jxx8>>>\�|٢���ˉ����ݝQ�FQ�bE����<y2!!!ѱcGBCCX�$yu��l��bm<f�…���Q�R%���pss��ɓ���R�n]��ҥK�r�
ժU��>�D������~����H:���-�Y���s����Abb"�ׯg�ԩ�Z��c��~{���jժ�^Gs�޽{��"""""""�˺t�B�.]r;�'Ώ?���!������d��+!������WF�۷o`���ԨQj׮���O�y�l���ɓqss��ޞ
*0~�x֯_��g��x�����UM1�Сk׮�h߳g�|�	e˖�`���=���P~�����o�����C������?t�ܙ��P�<l�w��	ʕ+��u,_��E��D唨�(jժe�^�v�T}Ϟ=�_
'-�O�����THI�-���Ʋm�6fΜ�̙3S�߾};7oޤp��\�p�ʕ+g���l�w�СL�0���`����?>�����ˋ
��/&&�"E��:����GDDDRK���Hn�|�2mڴ�g��_~�ܹst���yh(�ʸ'N�x�g �ؾ};AAA=z��7oR�J���ѡC�4?��K�z�Ҫ"���H�%�_�>}��T�R�zLk�W�8%[?˳f^�)��=�"��	�~��t��5K󉈈���<�r-9%�n�Ag2�,�Ӻ��OJ7o޴6�laK<7n$!!!�w��a�ƍt����&���l��e˖ԯ_�;v�v�Z~��7�͛����y��w��w��g�1_��}�m��&""�Z�F���0DDDD����z�������}�;w��R�@\\#G�d߾}�aaa�������رciڴi����F			\�p�5kְq�F|}}�Q�F��Iq��a|}}Y�j&��nݺ���F͚5s;4�l�'*��)S�����~���_~�h���R�uuu%**�u�����0�L�-񘗸�3g������۷�>���� #9��㯿�����T�V-ݹ��g�����L���i߾=���lݺ��K�2k�,#���~ŋ'::��ׯS�xq��\�~��#"""""""���S���-e��Ν;�<��ѣٷo...���;4lؐ��~�K�.�f��-[ƈ#��ox���|���A�Q���Ν;������̈#X�f
NNN�zLk��Z����c���xƌC�Ν���:uꄏ��W����y���-Z��3e�&M�D�*U8v�S�LIշY�f,Y��ѣG�駟R�R%�]�������o���`����*&���g�R�l����xN�:űc�x���iРA�s5hЀr��ɩS��T�
6d�ʕ̘1�ɓ'��3�0g�)S�?����ly�:t���9r$mڴ�R�J���_888q[ۯr��DGG�*	ż�Sv��y��ٳoo��CD�UPy���GY�p!.4��Ν�ܹs��{��a���+V�%K����b�+U��d޼y̛7�����b�9/��T�R�������ݛ�'O�n�:-?�E�/����t���h�ѣ+V�`���2$��~y"9��ۛ�7��ҧO����Ӈ;vFϞ=-�(P�aÆ�E�%&&�N�:���ʺu�=vk�Y�v-ݻwOw�;;;�w�δi�

⣏�<� IDAT>�o߾lٲ���0ڵkg��������ݻ7�'Of�ԩL�:բo�ڵm�װaCv��IDD�E;��)�ƍ��ڈ���n.�����&"������,Y��h		aȐ!L�2�-Z��۷�…L�<�Q�F��^>��c���X�`�E��I2)�k��űh�"�l����M�%x���߿?����8��C�z��HLI�[�n�L&�T�����k7o�w)�m��<�ʕ+�5kaaa�ϟ�W_}��C�����k����èQ�صk�Er�֭[Y�z5Ǐ��۔(Q��M�2d�
,��14�V���,\��m۶q��UJ�(����/H�…m�/���b�u���e�ʕԭ[���Xɒ%���`�ʕ��Ջ"E�d:^�GM���,444�?�X�p!�۷�g�ᩧ���͍�'X�qW�pa���������{{{���iڴ)K�,������S�ti���IHHȑ�&���D6l؀��3m۶�p�v��Q�H6l�@bb"ŋg��Ŵlْ"E����@ժU�6mmڴ1�Y�ϖׯS�N�;�*U���舣�#+V�O�>L�0��~�Z��`���޽;�y�޽�…[|@%"""""""���:�+W���P#��͍��P#��رc����7o��/��b����p��iԨ��>k�,bcc�MIKBB�f�ҥ\�p���D.^����C��޽{F���p�C4�)T�o��v�}$��H�nK�f�
"$$�۷os��u���{f͚��X�j֬	��S������3b�BCC�y�&w��%::��+W�zH)���M�͛7y��Y�b�.]2�����沛-�iӦM��ť�����'qqq�τ�������"OTN(V�cǎ�h�x�"%J��hwvvf���><�9[�lI˖-S��R^6eߴ�>(�n�j�񜜜ؾ}�E[�R��<y��Z�����?�Ծ}�l�W�P!���X�h�ϟ�t���?�#G�0hРL=1#"""""""��򩻻{�ۮ����⋄��s��<==�{�.۶m#_�|�ݻ�۷oS�@c��/�l�y@�
���xX�,y����,_����H���5j+V$**�ɓ'BPP;v��ի��9%��H�nK�f�ʕc���<��s,Z�???�o���ѣ�}��Q�X1�]�f��X���#G��cggGxx8�
2@J�֌�Ųe�8s��K�fҤIT�Z���Hƌ��ӧY�dI��夵,U�XĖ�w�^�V��js�޽{y��7�>������ȣ���W^y���;nܸ��{���?���j���%���ݛ�%K���o�������j�!���˗�����W_�ܹsxxxXTO{�.\����~J�&Mhܸ1L��åK��8q"mڴ�^�z�hтQ�F�����G�7$��'N�H�σ��r��蛑��@#	9000�󉈈�dN(�^�z�ۀQ�|��ܸq�:p��m���c1�Y�f��ٳg��)ٲe�'O���
{{{*T�����X�~����� ͊$�)��H�nK�f�~�)e˖%����m7n��r�III<���w۵k�Z�jlذ�ٳg3m�4�~%��delZ�t�=�5j���K/�d,	�m�6�紖-��>�\�r��)_��E��E���ҦM���;�N����gѢE8p`.E&���ɉ�����ҫW/����3g
���DDD��n��`~�bbbx���ᅪ�C�q��!#	���ŋ��ݛ�����a����ٳ�E�Q�R���>b�Ν6?M�(;|�0����Z�
��D�n�pss3�󋈈dE�$��ӧ3}�tc{ҤIL�4	���������͛7�?~��O?��/��«��JDD����W^���|��gϞH����ӧ��]\\8w�/^�B�
i�7�Lܺu�…��Yz瑲ݖ��*V�h|���dO�͕+W����%o6lǎK��d2=p�̎M���x饗,���]�p!�q��ϖ�d~[�H�T��m��������<�Dr��i�
6������s�=G�
�߿�Mkˣ�N�:2�3f���R�v�\�JDD$��	�eѢE����xzz2f����X�l~~~̛7�"9e������������)S���'�&M"""�ٳg���-q��!�s����l9��Ϙ1c�ܹ3���t��	V�^���S.G(""O^z�%��ˆ��aǎԫW��E�R�V-���C\\���ԬY�"��j
<8�!y��5jp��9��ۗnr�ѣG�۷/իWgѢEF�����HHHH���G�v[b7spp0�7ǒ:@�*U���ӧs��1ʔ)C�&M�X�"իW�k׮�/+cm��Up���d�&��.jmn���&"""""�(��)������//��E]o��Ik	���p�Bc{�ܹ̝;��&W�K��9�g�}���~??�T��������)V�p�)��>���;r���w^�x�b._�L��ݍ�=z�b�
/^̐!Cr1:y���r��!���;K�,a�������Ԯ]��=@˖-9r�K�.�֭[4j��F��W_}�͛7S-�Y���DEE�n�:#Q3=����ׯ��ߟ6m��C��ݻǂ0�L�m��HL���KUQ%��&9{NJLL$  ��M�������DgΜ1�߽{�b��26-�J���?��ȑ#ԫW�h?r�@��~�\��ŋ���)^��ž�ׯ}DDDDDD'���EDDD�t��%ƍǫ��J����޽;�ׯ����၇���_����i����	

�T�R��߿��+Z�nm�w˖-�����!d��g͒�xO�>͐!ChԨ͛7gʔ)��ǧ�g�>�v[lݺ���ӴiS�ׯO�v�1cqqq�����1f�^y�Z�l�g�}�իWx���8�ΝK���iР���:���K��vll,+W��nݺK�,���+W�$66��sI)�ҁ-%ؼys�����`$�4l��+V�I�2W�0/�I.�G����$%%q��UfϞ�����{�
P�vm���o�����͛���%11��G�2t�P���iذ!�;w6ƙ�+~��G���9s�L��3Öح��k��;w��СC9u��K��U�V���߿����?�����nN@��k-�ɓ'�ݻw	cʔ)4n�ئ�la�u�\�2QQQ��1���������<.�D�����ɓ'���\�r|���DDDЧO��܌'_���{��ʕ+F��ӧ;v,III�����Ϛ5���X#�������ٲep���O>�Īs���_��ݼ�ƠA���Po߾��Ͻ{�=z��sXk���,Z�Ȣ-::��+Wr��
&N�h�o����޽��p��?r��A������SJHH`��DFFm/^��Ϗ��|}}���6m"..OO�T�xzz��͛y��7�t�"""�$�/^�ڵkJ�ʕ���ʕ��8w�U�T�T���E�C�N�puueݺu��Ӈ;vFϞ=-�(P�aÆY�M�:�w�y����Q�F�:F�f͘4i���+M�6e͚5|��|��i���V��n��^���K�uvvfڴi�5mڔ���3v�XƎ�j�������L�֎�V�޽ٶmgϞ�_�~�ʖ-��-;�r�6l�Ν;���H�����&'iDDDDDDr�*�����<Ƭ�I�t�R�\�B�j�X�f
�v��7��YO�B�
�ݻ�H��u<�/}�������Ė-[�>}:III�O||<_|�d�־�+W�5kְw�^㦄y����/sj�G�'�G��޽{ٷo�QƜ��܉'�?>�����ϏҥKs��y����t��|�r"##qww'  �H͚5			!((��w�^�V��js�����HV�|�q��Q��Z�l	��	o����%}>��cJ�.����QQ�p������八�+���8;;ӴiS�,Y��JE�b�X�l~�!իW�`��*T��͛3o�<����6l�0:w���O?���#����3&S琜��[#��(=����+W��ݻ�b�
�T�b���O>�e˖899���H��ՙ2e��^mժU��ڱ�*R��/�k׮���`oo���=z�`ɒ%8;;�4�-l�N�Z��`��i�7ܽ{7��E�9������Hn�3�L��0  ooo�Ӛ���0"��K�.���ۀ�-"�$I�VZo�&N�HPP�~�)]�v��LJ�72f�:t�`�{��7���b��ż����m@@nnn6�O˭[�1b���0�A����Ν;6���P��ФI�4cK�Lbn[�|�q#���R!!!i�Mk��2�c2�8v�'O��ԩS<x�3g�`gg��-�Ϟ=ۢ
LHHC��B�
�{���ѣ�N�"((�X"	�ܹst�ؑڵk�p�Bڴi��˗ٴiŋ����ի�jՊ�{���9�s�Ǘ-�OD�ɕ��/�=&�u,`ѢE��㏔.]����ӱcG
D������GɣBڲ>]�v}X�y�,�>}�t�O�nlO�4�I�&�.\�X��}���-�m�\�B�1bo��k׮M39��͛>���0>���T�)R�bE�{����ݳ9Vk\�r�aÆq�رT�Һ��Z���K��D��={���ۧ������111��'�S2���������ѻwo~��g������O��	&�����y�xr���^^^9}�;;;��;::fi|J�����O�}gΜaԨQ\�p�Y�f���i��Y��A�O�αc�(S�M�4�bŊT�^=�d��X����=ƃ�Zܼy3���^��ܖӯ�����Xrrrb���|�������� �̙�j�(��A�'��ٳ�9s���aD�	ШQ#>���CD$O

�СC8www�,Y���y���-�|1{��믿8}�4ժU��x֎oٲ%111�Y���e���;����7o�̄	pqqa�ҥ<���6�����GѢE��	6fw��婧��6��ѣԪU����_(S�L��puu%**�u�֥z�R*^�8���\�~=ղ>ׯ_7�������U�N�Œ3x��w�]�v.G%"""""�3R?>��Ξ=��իs�0"�[�z5��0DD򔈈�����N�aÆ̘1���hn߾��������7�x౬ߴiS���Kbbb�w����f���^3�=z\\\���{��)�J"��s2c���$$$p��q|||��7nX�4i$&&�믿���ꫯ�;w�f�=z4Ǐ'))��W�2{�l<<<<x��׼�RTTT�y�m�Y�IDDDD���ˋ�3g2s�Lz���ለ�������b��%"�!oo��AD$ϱ%9�o߾lٲ���0ڵkg�o��<���̾}�غu+[�n��W�fMz��ml���F�J�-�<nhh�cˌ�E�C�N�puueݺuV�mڴ)�ׯg�ر�;6��Ǐ[,MT�Z5���cѧr�����O�>�ر���0z��i��@�6��nذ!��޽�EY�
�r�]r���5CLE+t���59�b�i�I��h���\�23c㠉"���j��<���i31SZE����e�< �z\W�2�����k�����lݺ����'qM?�>�h��ODDDDDDDDDD�^7�s�����Ԏ��(�x]^ӦM���'((�ƍӠAڷoϼy��߿�5�U��=<<X�l�<�ԯ_ƍǒ%Kprr2�ެ“�:u*���8::R\\lױӦM#((ggg����ر#s��aܸq�^��">""�~����䄇�Æ
#&&��
Vz777���0�qww'00����N(�����Ņ�۷[��}�v���*-��nY���֯_o��g��^^^DGGWSU�Hu����,3gμf\zz�5c��[e�V��:((��� ��иq�J@���|�9���;������Vy���+F����X���� //�}��1~�x\\\�\CDDDDDDDDDD�z��)G��x�����Ǚ> 0�V���c���:th�1��$�=���ٵkݻw��DDDD��			aݺu$&&@bb"��j[ ��HIIa�����]'%%�!C��v""""""v���S^y��n�z�z,^����@<==k;��w�^/^��ի)++cذa���ҹs��NMDDD����LTT�'O&88���T-ZD�F�j9;��._��PDDDDDDD����┭[�V9_����Q�RTT���Y�`�
_�V�t�3g�d��
Ddd$)))8;;�r�""""w�.]�0q�D�ߘ�&M��ϯ����(11�����NCDDDDDDD�ۦ8��mWs3u�ڕ-[��y�fz��]���H||<�O���3�
>�U�V�ĉk1;����h�h4�v""R�-Z������NC�իW/^z��NCDDDDD�.��@u�9s�Y�fѧOz��ȑ#IKK����\�bRTT�{�ǀ�ѣO?�4K�,����S�[kTWu��N>��899��oSTTt�6n�Ȅ	�{����g��ǚ�,))a���<��c��Ӈ�K�p��9"""�ի�{���^��ŋ5����B����ڵ���D͛7��ߟ��$
�y]"""""""r�ٽ{7)))����])%%�ݻw�v""""""v�m:�T��ŋ�;�'N��>LDD�Ulqq1&L����|������a���88ܺ����ӢEƎ˒%KX�x1aaa����k1v��)���8�<o������Y�f���G}���7)))���g֭[�����������_RTTD@@�U�dff���Ƴ�>[��ۓ�h��>"�`Ĉ��������H�ԉ�)����8q///���عs'111]9LV�X���y�Y�r%�w�&99�Ν;���Ijj*`�}PVV���L�F*�g���S���GZ�n�'�|BNNN��Z�
���p222رc~�!۷o�����aժU�ر�	&0w�\���O���`ܸql۶�Fב��@����o3ň��������������ȝ��:�TV�Qq<++�͛70c�:u�������V��nذ���h���hݺ5QQQ8����3p�z-U�i>���'22�1c���o�������Uܶm�(++�СC|���|����_��…V����m�����ҥK��_����e˖ùs�jtG�0�W^�V�,bDDD��:thm� "u����[�Nl듛���?l1���g{��q`s��G�V�������z��ԩ�>�,�|�	�1�F���9s�S�L�СCVseeeVc<�k��mڴ1���|]�QPP@�ƍ��Lc��~-Z�`Ȑ!�����A���ݙb���ܨ�9r����q��ͤ��r�.\�@�v��ӧ�<��cn�'�|�3g�����͛[�?~�A��_�[�����"&//�g�y�_��W|��畞�:������ٵkݻwW��������-Rk�)��^��W,��W��5c*��M�f��|���?�u�V��׿��OX�ϟ?�C������?N�6m�رc���nذ��q��wx��:L�[k��l}�DDD�fz��E�^�j;
�;�+���֭[k�X������pv��a1���Mvv6qqq̚5�����r�:�m�6<hU����������dddX�8p���=n�}߻w/�/f��Ք��1l�0|}}�ܹ�u�+""""""�V':������7���W_��#��ǿ��+�X��@nn.k׮�`0��4m��|\]]�6maaaDGG[͛�􈋋�I�&;v�<_RRB���m��:�6mʩS�8w�M�6��3mTq\DDDjn�ʕ�1����:�Z��""w���[�n��L��1c;v��ӓ^x��={r�=���?�f��/_����裏��o~s��߱cGsqJ�>},�L�)#F� >>���t�┃�.N���ҥK̜9������4h��������$,""""""7N�(N�۷/�|�
s��a��ٴk׎��+ IDATC�1g���޽{�����3�m۶����eŊ|������t�R�j����2�?N�-nJ��S�>}���c��m۶Jcv���O<��c�x�7���ϟ����^�<��S���͵*B1m�t#ڰ���������NADꘕ+W�����;Tmo�s�IOOg���xxx�������y��ˋ_|�,Y’%K��nx��S��IQQ{����Ņ��իW���Iqq1NNN�������>}��{�<6|�pV�ZE||<'N��9�������M�Dqʈ#��/���5jT���F�b˖-dgg3r�H��F�1e���&M�PPP��A�0�]����nO>U	'++���"��@֯_ϬY��5k��q�&  ����s={�d�֭������g������>z�9�����!C��v
"R�\�|Y�)"Rk6n�HJJ
����Y�f2q�D\\\*=�̙3,Z����t.]�D�6m���HDD`YSXXHLL�6m��ٳ4k֌>}�0n�8����q�B����N����/K�.�(�1}]>�������;w.[�l�Q�F<��L�4ɼŲ�]�v�p�B��P�~}�ʄ	8w����c۶m4hЀ�{���0\]]��[[��7l�0���h׮��ڔ_RR.$;;��
��O���/���l.*9t�����\�|�^�z���B���ٴiYYY�JKK9|�0����EEE��Ʋa�~��G�5k�SO=�رc-�b
IJJ�k׮��y������Dpp0�7�y_EDDDDD�9�v&YYY�>I���LLL��{�~������;���Ǧ��qqq�F������HBB�Eǎ�S���퍣�#���7��ɧ*���L�4�j|ڴi��쌓�;vdΜ9�7�իW����ׯ...l߾�j��۷���F߾}oH^"""""""R�|�L�>���,.\�@II	�N�"))��s�Vz�ŋ;v,�ׯ��\�|�Ç�Sʻp�cƌaժU����s�\���c�Z=�p�B
+-��Jxx8�ׯ������V�\ɻ�k7�|���)**��|��G�]��?��Ϥ�����?SXXȺu�X�`������W
����+cƌ����^�?���L~��gΝ;ǧ�~�…��{������|LFF�En�z�����w�}GQQ^^^�s�=��}/..f„	,[���'Or��e��󉋋��_������_RTTd�������HKK���EDDDDD�~u�s
����Ug���|�5kf1���Nhh(���U�DPP�ո=�f+��:���\�Æ
cذac�7&::�f��@������u���b4���%//ooo���طo�Ǐ��	(��N�>M������{��?�ɉ'8p ����_����s��I�y�v��Mii)�۷'88�fg�~��?��]�vq��Y����ڵ+�Ǐ�e˖�埪-�aÆ�lْ#F���r?}�4o�����`��HBBp�,8r�H�������ڵ��ݻ3t�Л�����Z�jp���駟�^�z�߿�����|��$11�'N���śo�I���ٿ?����>}�"v���;vooofϞM���9x� 3g���ѣ$$$Xm�Һuk���,�2)�����~����d�>IIIl޼���0����V�ZE˖-Y�|9K�.e�ܹ����駟Ҽys�-[FLL���gϞ0��R]���-[�}��Gll,qqql޼�3fбcG���8x� >>>�uqJϞ=�W������jK���+Vp��A|�A"""hӦ
���DGG���Ijj*�ȯ}��V��222x��g���""PK��Zߦ��data/File/design/design.txtnu�[���PK��Z 1D\  !data/File/design/requirements.txtnu�[���PK��Z�rCBB$data/File/design/file_operations.pngnu�[���PK��ZXV���0�0data/File/design/md5.pngnu�[���PK��Z�
[�o�odata/File/design/file.xmlnu�[���PK��Z�\����"data/File/design/class_diagram.pngnu�[���PK��Z6E�WWdata/Mail_mimeDecode/xmail.xslnu�[���PK��Z�
$v66data/Mail_mimeDecode/xmail.dtdnu�[���PK��Z�Z��aa.filemapnu�[���PK��Z}�g�.channels/__uri.regnu�[���PK��Z^q++.channels/pecl.php.net.regnu�[���PK��Z��0��.channels/components.ez.no.regnu�[���PK��Z�H:{��.channels/pear.symfony.com.regnu�[���PK��Zl�|��.channels/pear.phpunit.de.regnu�[���PK��Z�t�.channels/.alias/ezc.txtnu�[���PK��Z�o/�.channels/.alias/phpdocs.txtnu�[���PK��Z\���.channels/.alias/symfony2.txtnu�[���PK��ZT�Y.channels/.alias/phpunit.txtnu�[���PK��Z� ��.channels/.alias/pear.txtnu�[���PK��Zui<�.channels/.alias/pecl.txtnu�[���PK��ZE�Q.channels/doc.php.net.regnu�[���PK��Z|K3�((.channels/pear.php.net.regnu�[���PK��Z��0AC5C5Console/Getopt.phpnu�[���PK��ZP'hB�&�&Mail.phpnu�[���PK��Z�܄�����#.pkgxml/Symfony2_Security-2.4.3.xmlnu�[���PK��Z'J�z++.pkgxml/symfony2.xmlnu�[���PK��Z^\F[[%.pkgxml/Symfony2_Serializer-2.4.3.xmlnu�[���PK��Z�$n��7�7&.pkgxml/Symfony2_ClassLoader-2.4.3.xmlnu�[���PK��Zȗ��!.pkgxml/Pear_Net_Socket-1.2.2.xmlnu�[���PK��Z��n�++.pkgxml/Symfony2_Yaml-2.4.3.xmlnu�[���PK��Z}3YN��.pkgxml/eZc_Archive-1.4.1.xmlnu�[���PK��Z��b�8�8!.pkgxml/Symfony2_Config-2.4.3.xmlnu�[���PK��Z�$v��*.pkgxml/Symfony2_OptionsResolver-2.4.3.xmlnu�[���PK��Z�/�h����".pkgxml/Pear_Mail_Mime-1.10.11.xmlnu�[���PK��ZtWY�n�n%.pkgxml/Symfony2_HttpKernel-2.4.3.xmlnu�[���PK��Z�1��ss..pkgxml/Symfony2_DependencyInjection-2.4.3.xmlnu�[���PK��Z=��4��(.pkgxml/Symfony2_MonologBridge-2.4.3.xmlnu�[���PK��Z�7�p�K�K.pkgxml/XML_Util.xmlnu�[���PK��Z��-=-=".pkgxml/Symfony2_Routing-2.4.3.xmlnu�[���PK��Z�|g��$.pkgxml/Symfony2_Validator-2.4.3.xmlnu�[���PK��Z�d+)SS!.pkgxml/Symfony2_Locale-2.4.3.xmlnu�[���PK��Z%ONO��&.pkgxml/Pear_Mail_mimeDecode-1.5.6.xmlnu�[���PK��Z�*�OO.pkgxml/ezc.xmlnu�[���PK��Z#�r�

 .pkgxml/Pear_Net_SMTP-1.10.0.xmlnu�[���PK��Za������.pkgxml/Symfony2_Form-2.4.3.xmlnu�[���PK��Z�Q���?�? .pkgxml/Pear_Net_Sieve-1.4.5.xmlnu�[���PK��Z��F��%.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu�[���PK��Z?�4��
�
%.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu�[���PK��Z��t8��%.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUri   URI of the namespace
     * @param bool   $multiline      whether to create a multiline tag where each
     *                               attribute gets written to a single line
     * @param string $indent         string used to indent attributes (_auto indents
     *                               attributes so they start at the same column)
     * @param string $linebreak      string used for linebreaks
     * @param bool   $sortAttributes Whether to sort the attributes or not
     *
     * @return string XML start element
     * @see    createEndElement(), createTag()
     */
    public static function createStartElement(
        $qname, $attributes = array(), $namespaceUri = null,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true
    ) {
        // if no attributes hav been set, use empty attributes
        if (!isset($attributes) || !is_array($attributes)) {
            $attributes = array();
        }

        if ($namespaceUri != null) {
            $parts = XML_Util::splitQualifiedName($qname);
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($qname)+2));
            }
        }

        if ($namespaceUri != null) {
            // is a namespace given
            if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
            } else {
                // define this Uri as the default namespace
                $attributes['xmlns'] = $namespaceUri;
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $attributes, $sortAttributes,
            $multiline, $indent, $linebreak
        );
        $element = sprintf('<%s%s>', $qname, $attList);
        return  $element;
    }

    /**
     * Create an end element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createEndElement('myNs:myTag');
     * </code>
     *
     * @param string $qname qualified tagname (including namespace)
     *
     * @return string XML end element
     * @see    createStartElement(), createTag()
     */
    public static function createEndElement($qname)
    {
        $element = sprintf('</%s>', $qname);
        return $element;
    }

    /**
     * Create an XML comment
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createComment('I am a comment');
     * </code>
     *
     * @param string $content content of the comment
     *
     * @return string XML comment
     */
    public static function createComment($content)
    {
        $comment = sprintf('<!-- %s -->', $content);
        return $comment;
    }

    /**
     * Create a CData section
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create a CData section
     * $tag = XML_Util::createCDataSection('I am content.');
     * </code>
     *
     * @param string $data data of the CData section
     *
     * @return string CData section with content
     */
    public static function createCDataSection($data)
    {
        return sprintf(
            '<![CDATA[%s]]>',
            preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data))
        );
    }

    /**
     * Split qualified name and return namespace and local part
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // split qualified tag
     * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
     * </code>
     * the returned array will contain two elements:
     * <pre>
     * array(
     *     'namespace' => 'xslt',
     *     'localPart' => 'stylesheet'
     * );
     * </pre>
     *
     * @param string $qname     qualified tag name
     * @param string $defaultNs default namespace (optional)
     *
     * @return array array containing namespace and local part
     */
    public static function splitQualifiedName($qname, $defaultNs = null)
    {
        if (strstr($qname, ':')) {
            $tmp = explode(':', $qname);
            return array(
                'namespace' => $tmp[0],
                'localPart' => $tmp[1]
            );
        }
        return array(
            'namespace' => $defaultNs,
            'localPart' => $qname
        );
    }

    /**
     * Check, whether string is valid XML name
     *
     * <p>XML names are used for tagname, attribute names and various
     * other, lesser known entities.</p>
     * <p>An XML name may only consist of alphanumeric characters,
     * dashes, undescores and periods, and has to start with a letter
     * or an underscore.</p>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // verify tag name
     * $result = XML_Util::isValidName('invalidTag?');
     * if (is_a($result, 'PEAR_Error')) {
     *    print 'Invalid XML name: ' . $result->getMessage();
     * }
     * </code>
     *
     * @param string $string string that should be checked
     *
     * @return mixed true, if string is a valid XML name, PEAR error otherwise
     *
     * @todo support for other charsets
     * @todo PEAR CS - unable to avoid 85-char limit on second preg_match
     */
    public static function isValidName($string)
    {
        // check for invalid chars
        if (!is_string($string) || !strlen($string) || !preg_match('/^[[:alpha:]_]\\z/', $string[0])) {
            return XML_Util::raiseError(
                'XML names may only start with letter or underscore',
                XML_UTIL_ERROR_INVALID_START
            );
        }

        // check for invalid chars
        $match = preg_match(
            '/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?'
            . '[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/',
            $string
        );
        if (!$match) {
            return XML_Util::raiseError(
                'XML names may only contain alphanumeric '
                . 'chars, period, hyphen, colon and underscores',
                XML_UTIL_ERROR_INVALID_CHARS
            );
        }
        // XML name is valid
        return true;
    }

    /**
     * Replacement for XML_Util::raiseError
     *
     * Avoids the necessity to always require
     * PEAR.php
     *
     * @param string $msg  error message
     * @param int    $code error code
     *
     * @return PEAR_Error
     * @todo   PEAR CS - should this use include_once instead?
     */
    public static function raiseError($msg, $code)
    {
        include_once 'PEAR.php';
        return PEAR::raiseError($msg, $code);
    }
}
?>
PK��Z#F��:�:pearcmd.phpnu�[���<?php
/**
 * PEAR, the PHP Extension and Application Repository
 *
 * Command line interface
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Stig Bakken <ssb@php.net>
 * @author    Tomas V.V.Cox <cox@idecnet.com>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 */

@ob_end_clean();
if (!defined('PEAR_RUNTYPE')) {
    // this is defined in peclcmd.php as 'pecl'
    define('PEAR_RUNTYPE', 'pear');
}
define('PEAR_IGNORE_BACKTRACE', 1);
/**
 * @nodep Gtk
 */
//the space is needed for windows include paths with trailing backslash
// http://pear.php.net/bugs/bug.php?id=19482
if ('/opt/alt/php74/usr/share/pear ' != '@'.'include_path'.'@ ') {
    ini_set('include_path', trim('/opt/alt/php74/usr/share/pear '). PATH_SEPARATOR .  get_include_path());
    $raw = false;
} else {
    // this is a raw, uninstalled pear, either a cvs checkout, or php distro
    ini_set('include_path', dirname(__DIR__) . PATH_SEPARATOR . get_include_path());
    $raw = true;
}
@ini_set('allow_url_fopen', true);
@set_time_limit(0);
ob_implicit_flush(true);
@ini_set('track_errors', true);
@ini_set('html_errors', false);
$_PEAR_PHPDIR = '#$%^&*';
set_error_handler('error_handler');

$pear_package_version = "1.10.16";

require_once 'PEAR.php';
require_once 'PEAR/Frontend.php';
require_once 'PEAR/Config.php';
require_once 'PEAR/Command.php';
require_once 'Console/Getopt.php';


PEAR_Command::setFrontendType('CLI');
$all_commands = PEAR_Command::getCommands();

$argv = Console_Getopt::readPHPArgv();
// fix CGI sapi oddity - the -- in pear.bat/pear is not removed
if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
    unset($argv[1]);
    $argv = array_values($argv);
}
$progname = PEAR_RUNTYPE;
array_shift($argv);
$options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV");
if (PEAR::isError($options)) {
    usage($options);
}

$opts = $options[0];

$fetype = 'CLI';
if ($progname == 'gpear' || $progname == 'pear-gtk') {
    $fetype = 'Gtk2';
} else {
    foreach ($opts as $opt) {
        if ($opt[0] == 'G') {
            $fetype = 'Gtk2';
        }
    }
}

$pear_user_config = '';
$pear_system_config = '';
$store_user_config = false;
$store_system_config = false;
$verbose = 1;

foreach ($opts as $opt) {
    switch ($opt[0]) {
    case 'c':
        $pear_user_config = $opt[1];
        break;
    case 'C':
        $pear_system_config = $opt[1];
        break;
    }
}

PEAR_Command::setFrontendType($fetype);
$ui = &PEAR_Command::getFrontendObject();
$config = &PEAR_Config::singleton($pear_user_config, $pear_system_config);

if (PEAR::isError($config)) {
    $_file = '';
    if ($pear_user_config !== false) {
        $_file .= $pear_user_config;
    }
    if ($pear_system_config !== false) {
        $_file .= '/' . $pear_system_config;
    }
    if ($_file == '/') {
        $_file = 'The default config file';
    }
    $config->getMessage();
    $ui->outputData("ERROR: $_file is not a valid config file or is corrupted.");
    // We stop, we have no idea where we are :)
    exit(1);
}

// this is used in the error handler to retrieve a relative path
$_PEAR_PHPDIR = $config->get('php_dir');
$ui->setConfig($config);
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError"));

$verbose = $config->get("verbose");
$cmdopts = array();

if ($raw) {
    if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) {
        $found = false;
        foreach ($opts as $opt) {
            if ($opt[0] == 'd' || $opt[0] == 'D') {
                // the user knows what they are doing, and are setting config values
                $found = true;
            }
        }
        if (!$found) {
            // no prior runs, try to install PEAR
            $parent = dirname(__FILE__);
            if (strpos($parent, 'scripts')) {
                $grandparent = dirname($parent);
                $packagexml = $grandparent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $grandparent;
            } else {
                $packagexml = $parent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $parent;
            }
            if (file_exists($packagexml)) {
                $options[1] = array(
                    'install',
                    $packagexml
                );
                $config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php');
                $config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data');
                $config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs');
                $config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests');
                $config->set(
                    'ext_dir',
                    $pearbase . DIRECTORY_SEPARATOR . 'extensions'
                );
                $config->set('bin_dir', $pearbase);
                $config->mergeConfigFile($pearbase . 'pear.ini', false);
                $config->store();
                $config->set('auto_discover', 1);
            }
        }
    }
}
foreach ($opts as $opt) {
    $param = !empty($opt[1]) ? $opt[1] : true;
    switch ($opt[0]) {
    case 'd':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected -d config_value=value, ' .
                'received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'user');
        break;
    case 'D':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'system');
        break;
    case 's':
        $store_user_config = true;
        break;
    case 'S':
        $store_system_config = true;
        break;
    case 'u':
        $config->remove($param, 'user');
        break;
    case 'v':
        $config->set('verbose', $config->get('verbose') + 1);
        break;
    case 'q':
        $config->set('verbose', $config->get('verbose') - 1);
        break;
    case 'V':
        usage(null, 'version');
    case 'c':
    case 'C':
        break;
    default:
        // all non pear params goes to the command
        $cmdopts[$opt[0]] = $param;
        break;
    }
}

if ($store_system_config) {
    $config->store('system');
}

if ($store_user_config) {
    $config->store('user');
}

$command = (isset($options[1][0])) ? $options[1][0] : null;
if (empty($command) && ($store_user_config || $store_system_config)) {
    exit;
}

if ($fetype == 'Gtk2') {
    if (!$config->validConfiguration()) {
        PEAR::raiseError(
            "CRITICAL ERROR: no existing valid configuration files found in " .
            "files '$pear_user_config' or '$pear_system_config', " .
            "please copy an existing configuration file to one of these " .
            "locations, or use the -c and -s options to create one"
        );
    }
    Gtk::main();
} else {
    do {
        if ($command == 'help') {
            usage(null, isset($options[1][1]) ? $options[1][1] : null);
        }

        if (!$config->validConfiguration()) {
            PEAR::raiseError(
                "CRITICAL ERROR: no existing valid configuration files found " .
                "in files '$pear_user_config' or '$pear_system_config', " .
                "please copy an existing configuration file to one of " .
                "these locations, or use the -c and -s options to create one"
            );
        }

        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        $cmd = PEAR_Command::factory($command, $config);
        PEAR::popErrorHandling();
        if (PEAR::isError($cmd)) {
            usage(null, isset($options[1][0]) ? $options[1][0] : null);
        }

        $short_args = $long_args = null;
        PEAR_Command::getGetoptArgs($command, $short_args, $long_args);
        array_shift($options[1]);
        $tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args);

        if (PEAR::isError($tmp)) {
            break;
        }

        list($tmpopt, $params) = $tmp;
        $opts = array();
        foreach ($tmpopt as $foo => $tmp2) {
            list($opt, $value) = $tmp2;
            if ($value === null) {
                $value = true; // options without args
            }

            if (strlen($opt) == 1) {
                $cmdoptions = $cmd->getOptions($command);
                foreach ($cmdoptions as $o => $d) {
                    if (isset($d['shortopt']) && $d['shortopt'] == $opt) {
                        $opts[$o] = $value;
                    }
                }
            } else {
                if (substr($opt, 0, 2) == '--') {
                    $opts[substr($opt, 2)] = $value;
                }
            }
        }

        $ok = $cmd->run($command, $opts, $params);
        if ($ok === false) {
            PEAR::raiseError("unknown command `$command'");
        }

        if (PEAR::isError($ok)) {
            PEAR::setErrorHandling(
                PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")
            );
            PEAR::raiseError($ok);
        }
    } while (false);
}

// {{{ usage()

/**
 * Display usage information
 *
 * @param mixed $error       Optional error message
 * @param mixed $helpsubject Optional subject/command to display help for
 *
 * @return void
 */
function usage($error = null, $helpsubject = null)
{
    global $progname, $all_commands;
    $stdout = fopen('php://stdout', 'w');
    if (PEAR::isError($error)) {
        fputs($stdout, $error->getMessage() . "\n");
    } elseif ($error !== null) {
        fputs($stdout, "$error\n");
    }

    if ($helpsubject != null) {
        $put = cmdHelp($helpsubject);
    } else {
        $put = "Commands:\n";
        $maxlen = max(array_map("strlen", $all_commands));
        $formatstr = "%-{$maxlen}s  %s\n";
        ksort($all_commands);
        foreach ($all_commands as $cmd => $class) {
            $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd));
        }
        $put .=
            "Usage: $progname [options] command [command-options] <parameters>\n".
            "Type \"$progname help options\" to list all options.\n".
            "Type \"$progname help shortcuts\" to list all command shortcuts.\n".
            "Type \"$progname help version\" or ".
            "\"$progname version\" to list version information.\n".
            "Type \"$progname help <command>\" to get the help ".
            "for the specified command.";
    }
    fputs($stdout, "$put\n");
    fclose($stdout);

    if ($error === null) {
        exit(0);
    }
    exit(1);
}

/**
 * Return help string for specified command
 *
 * @param string $command Command to return help for
 *
 * @return void
 */
function cmdHelp($command)
{
    global $progname, $all_commands, $config;
    if ($command == "options") {
        return
        "Options:\n".
        "     -v         increase verbosity level (default 1)\n".
        "     -q         be quiet, decrease verbosity level\n".
        "     -c file    find user configuration in `file'\n".
        "     -C file    find system configuration in `file'\n".
        "     -d foo=bar set user config variable `foo' to `bar'\n".
        "     -D foo=bar set system config variable `foo' to `bar'\n".
        "     -G         start in graphical (Gtk) mode\n".
        "     -s         store user configuration\n".
        "     -S         store system configuration\n".
        "     -u foo     unset `foo' in the user configuration\n".
        "     -h, -?     display help/usage (this message)\n".
        "     -V         version information\n";
    } elseif ($command == "shortcuts") {
        $sc = PEAR_Command::getShortcuts();
        $ret = "Shortcuts:\n";
        foreach ($sc as $s => $c) {
            $ret .= sprintf("     %-8s %s\n", $s, $c);
        }
        return $ret;

    } elseif ($command == "version") {
        return "PEAR Version: ".$GLOBALS['pear_package_version'].
               "\nPHP Version: ".phpversion().
               "\nZend Engine Version: ".zend_version().
               "\nRunning on: ".php_uname();

    } elseif ($help = PEAR_Command::getHelp($command)) {
        if (is_string($help)) {
            return "$progname $command [options] $help\n";
        }

        if ($help[1] === null) {
            return "$progname $command $help[0]";
        }

        return "$progname $command [options] $help[0]\n$help[1]";
    }

    return "Command '$command' is not valid, try '$progname help'";
}

// }}}

/**
 * error_handler
 *
 * @param mixed $errno  Error number
 * @param mixed $errmsg Message
 * @param mixed $file   Filename
 * @param mixed $line   Line number
 *
 * @access public
 * @return boolean
 */
function error_handler($errno, $errmsg, $file, $line)
{
    if ((!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) && ($errno & E_STRICT)) {
        return; // E_STRICT
    }
    if ($errno & E_DEPRECATED) {
        return; // E_DEPRECATED
    }
    if (!(error_reporting() & $errno) &&
        isset($GLOBALS['config']) &&
        $GLOBALS['config']->get('verbose') < 4
    ) {
        return false; // @silenced error, show all if debug is high enough
    }
    $errortype = array (
        E_DEPRECATED  => 'Deprecated Warning',
        E_ERROR   =>  "Error",
        E_WARNING   =>  "Warning",
        E_PARSE   =>  "Parsing Error",
        E_NOTICE   =>  "Notice",
        E_CORE_ERROR  =>  "Core Error",
        E_CORE_WARNING  =>  "Core Warning",
        E_COMPILE_ERROR  =>  "Compile Error",
        E_COMPILE_WARNING =>  "Compile Warning",
        E_USER_ERROR =>  "User Error",
        E_USER_WARNING =>  "User Warning",
        E_USER_NOTICE =>  "User Notice"
    );
    if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) {
        $errortype[E_STRICT] = 'Strict Warning';
    }
    $prefix = $errortype[$errno];
    global $_PEAR_PHPDIR;
    if (stristr($file, $_PEAR_PHPDIR)) {
        $file = substr($file, strlen($_PEAR_PHPDIR) + 1);
    } else {
        $file = basename($file);
    }
    print "\n$prefix: $errmsg in $file on line $line\n";
    return false;
}


/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * indent-tabs-mode: nil
 * mode: php
 * End:
 */
// vim600:syn=php
PK��Z�0$�-- .pkgxml/Pear_File_MARC-1.4.1.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.10.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
 <name>File_MARC</name>
 <channel>pear.php.net</channel>
 <summary>Parse, modify, and create MARC records</summary>
 <description>The standard for machine-readable cataloging (MARC) records is documented at http://loc.gov/marc/. This package enables you to read existing MARC records from a file, string, or (using the YAZ extension), from a Z39.50 source. You can also use this package to create new MARC records.

This package is based on the PHP MARC package, originally called &quot;php-marc&quot;, that is part of the Emilda Project (http://www.emilda.org).  Christoffer Landtman generously agreed to make the &quot;php-marc&quot; code available under the GNU LGPL so it could be used as the basis of this PEAR package.</description>
 <lead>
  <name>Dan Scott</name>
  <user>dbs</user>
  <email>dbs@php.net</email>
  <active>yes</active>
 </lead>
 <date>2019-11-13</date>
 <time>17:33:33</time>
 <version>
  <release>1.4.1</release>
  <api>1.4.0</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license uri="http://www.gnu.org/copyleft/lesser.html">GNU Lesser General Public License</license>
 <notes>
1.4.1
  * Reintroduce include_path to composer.json
 </notes>
 <contents>
  <dir baseinstalldir="File" name="/">
   <file baseinstalldir="/" md5sum="ffe2590635f404af055fe731da105939" name="File/MARC/Lint/CodeData.php" role="php" />
   <file baseinstalldir="/" md5sum="a3b9e1c817e67f59add05593500d463e" name="File/MARC/Control_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="acba4463f8e40d6ee4e7ba1f2dc53123" name="File/MARC/Data_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="378f483ec1fd161cd9dfb9b05db58d66" name="File/MARC/Exception.php" role="php" />
   <file baseinstalldir="/" md5sum="a9ba69030cbf4847292b9975e9d922c6" name="File/MARC/Field.php" role="php" />
   <file baseinstalldir="/" md5sum="c37351c7c80927ce6bb1e662510f9183" name="File/MARC/Lint.php" role="php" />
   <file baseinstalldir="/" md5sum="c5ac39e3d25eb0108b9dd5ad8466c821" name="File/MARC/List.php" role="php" />
   <file baseinstalldir="/" md5sum="7af6ce78cde4bb246e4e96709e90d2c0" name="File/MARC/Record.php" role="php" />
   <file baseinstalldir="/" md5sum="df5f97139685f0ad04e47fdbb67e3968" name="File/MARC/Subfield.php" role="php" />
   <file baseinstalldir="/" md5sum="6e102262dfd5d65d8d5a6221dfc74edd" name="File/MARC.php" role="php" />
   <file baseinstalldir="/" md5sum="8b64040d2d18ac4b994595a148266a66" name="File/MARCBASE.php" role="php" />
   <file baseinstalldir="/" md5sum="f5a17a60d34e84e2ee7ca1e5c5c6c620" name="File/MARCXML.php" role="php" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="examples/example.mrc" role="doc" />
   <file baseinstalldir="File" md5sum="1aea40df9f1c2e32f8e065fe8da0a3b5" name="examples/marc_yaz.php" role="doc" />
   <file baseinstalldir="File" md5sum="70ae317e0890d5896e3ffccdd293369a" name="examples/read.php" role="doc" />
   <file baseinstalldir="File" md5sum="54efb9d920ac775bfc847a83a2dec73a" name="examples/subfields.php" role="doc" />
   <file baseinstalldir="File" md5sum="14297da35b510c496cd1f328cf3bb301" name="tests/bad_example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="0dd4c6dbad6e8608d0ebf9d24425955d" name="tests/bad_example.xml" role="test" />
   <file baseinstalldir="File" md5sum="216a6f9d53f6d3d8e22d81fdc10f4bc1" name="tests/camel.mrc" role="test" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="tests/example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="9455aec3371f79cf7d31281fd03f5171" name="tests/marc_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="577e2f5f89fd48cf1a3576a29d2958f8" name="tests/marc_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a6a586354b9a06c880c2a7470dd828d7" name="tests/marc_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1c7e2fc5572a0f9362a771c260a1fe3" name="tests/marc_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="84f85ac7f8a2532e4e90ccde7764556a" name="tests/marc_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="889e5e906a97de7a0e94b0c5f30e70e7" name="tests/marc_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="be823dc8a8efb408de06371ab802efcc" name="tests/marc_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="af44490aafea44e5120f881cb81cdad9" name="tests/marc_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ac9f2a7aeb24900a11f5102744179ae3" name="tests/marc_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5e43eb5cddbb4f2bd0d6405cd95b80aa" name="tests/marc_010.phpt" role="test" />
   <file baseinstalldir="File" md5sum="2e1cd8509c0bf04ec77fc0f51375f611" name="tests/marc_011.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bc49ca48623102c8ac07679fa77a3dd9" name="tests/marc_012.phpt" role="test" />
   <file baseinstalldir="File" md5sum="245a3b20e0da1973535503e28efd1d3a" name="tests/marc_013.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ce69aa734856dd40d60d30c77bdef53a" name="tests/marc_014.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7b61cdd31035e60682fa92c5d519d997" name="tests/marc_015.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7f4f597fe1adaa3507eb87fc4875dbd2" name="tests/marc_016.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4262efd5fcacbd7503323681f4552430" name="tests/marc_017.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ee1623d7bda54ba4f741b2319b158f82" name="tests/marc_018.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8006c03fbab0f04377342086fafd3982" name="tests/marc_019.phpt" role="test" />
   <file baseinstalldir="File" md5sum="f5ae5b25e0ac1104314433d9e5b1f7fe" name="tests/marc_020.phpt" role="test" />
   <file baseinstalldir="File" md5sum="94d8f99e86585671a1b2d3043aeb6360" name="tests/marc_021.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bb891a890effe0e77e1759043f4846d8" name="tests/marc_022.phpt" role="test" />
   <file baseinstalldir="File" md5sum="faf77dcb5cdd002c09169a14bfded65e" name="tests/marc_023.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0e6c4a23f5da7df64fdd4b3b1149bbee" name="tests/marc_16783.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4ea8b3520beda378db15960f1c50493a" name="tests/marc_field_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="743850ef61df69c4340be44a03bccb5a" name="tests/marc_field_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8c765f1398b49df257d86d22ac6e4f8d" name="tests/marc_field_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d4216cf930a308e0d02553bd3914f294" name="tests/marc_field_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dd59514b474b78371ad522a3e13b76b7" name="tests/marc_field_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5295bfd02a8424acac1c91de26b552c7" name="tests/marc_field_21246.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6f95f09442ccf6b93df92986f58b270d" name="tests/marc_lint_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="18d721f8871edd925624ccbdd15444fb" name="tests/marc_lint_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4eb86a2f4e0a74dedcb0bf2511da6ca1" name="tests/marc_lint_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="10430fee0a1352d0528f1507b34c57e1" name="tests/marc_lint_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0dcd07a18577d7b22392a2214cd6436c" name="tests/marc_lint_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fd17798fc535562e5e64461f449516b2" name="tests/marc_record_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="141b455ccf67a60c4eac44c77960f2e2" name="tests/marc_subfield_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1e23464ee0eec47ddca2af9a9922926" name="tests/marc_subfield_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="1d7903e8c244d647220b318b4bc758d1" name="tests/marc_xml_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="22cae3c752d843b78f583dcd92801534" name="tests/marc_xml_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="c0716d23e0f960abf8d53ad6014a413a" name="tests/marc_xml_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7645fa19e28aca041a124fc5e2c12bd3" name="tests/marc_xml_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b08b28c3251625b8b6e4d7ab376b0185" name="tests/marc_xml_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6cd0934ddbf65d2d7e9ea5d108977ff7" name="tests/marc_xml_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ffdce4aa190268fa7cbbf3bb45383abf" name="tests/marc_xml_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="998a4c1ce00ff100f39ffa9fc49a212f" name="tests/marc_xml_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a38a67c590869f2b0a4859a910fd9e89" name="tests/marc_xml_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="db39c5055a570fcda12bb7c5fa1e3b4d" name="tests/marc_xml_16642.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dc075f4a271bd7182378a3874bd5b39e" name="tests/marc_xml_namespace.phpt" role="test" />
   <file baseinstalldir="File" md5sum="208200d9a979ac360c4d326e9789b6b7" name="tests/marc_xml_namespace_prefix.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d87774ede82222cfc12b2c2a06f57a3a" name="tests/marc_xml_rsinger.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fb44e3eb69f1a37115235fc829c39542" name="tests/namespace.xml" role="test" />
   <file baseinstalldir="File" md5sum="e6de4d809b0af5dd99fd352eb60616a1" name="tests/skipif.inc" role="test" />
   <file baseinstalldir="File" md5sum="a0166a4ff0bc0bb283e854f11beaa793" name="tests/music.mrc" role="test" />
   <file baseinstalldir="File" md5sum="993ce494befbc25dc1326527b30b4782" name="tests/music.xml" role="test" />
   <file baseinstalldir="File" md5sum="6b0c87f0cd459ed7322c25d403b164cc" name="tests/bigarchive.xml" role="test" />
   <file baseinstalldir="File" md5sum="be850aa6ab4ac52b8c6c214c30b574af" name="tests/onerecord.xml" role="test" />
   <file baseinstalldir="File" md5sum="4f43fec7b276267eec5258044853ccc8" name="tests/sandburg.mrc" role="test" />
   <file baseinstalldir="File" md5sum="e216b95f905dd240c9bde372950e4073" name="tests/sandburg.xml" role="test" />
   <file baseinstalldir="File" md5sum="e81a92188ea0dcd9c108a63fb32b3f4f" name="tests/xmlescape.mrc" role="test" />
   <file baseinstalldir="File" md5sum="8f9f63ed6a80191d89a2296fa4c1a30b" name="CHANGELOG" role="doc" />
   <file baseinstalldir="File" md5sum="fbc093901857fcd118f065f900982c24" name="LICENSE" role="doc" />
  </dir>
 </contents>
 <dependencies>
  <required>
   <php>
    <min>5.6</min>
   </php>
   <pearinstaller>
    <min>1.4.0</min>
   </pearinstaller>
  </required>
  <optional>
   <package>
    <name>Validate_ISPN</name>
    <channel>pear.php.net</channel>
   </package>
  </optional>
 </dependencies>
 <phprelease />
</package>
PKm�ZPi��.depdbnu�[���PKm�Z�{��
�Mail/null.phpnu�[���PKm�ZE@�%>>
Mail/sendmail.phpnu�[���PKm�Z��A~�{�{�;Mail/RFC822.phpnu�[���PKn�Z�+V����
[�Mail/mime.phpnu�[���PKn�Zx�ع���D�Mail/mimeDecode.phpnu�[���PKn�ZB�_Ǭ=�=
@(Mail/smtp.phpnu�[���PKn�ZwԐE;E;)fMail/smtpmx.phpnu�[���PKn�Z�؛�J�J���Mail/mimePart.phpnu�[���PKn�ZB��shh
8YMail/mock.phpnu�[���PKn�Z@iE�\\
�lMail/mail.phpnu�[���PKn�Zv�.locknu�[���PKn�Z�*�z%-%- ��Structures/LinkedList/Double.phpnu�[���PKn�Z����p:p:  �Structures/LinkedList/Single.phpnu�[���PKn�ZUyv���Structures/Graph.phpnu�[���PKn�Z�C� + +CStructures/Graph/Node.phpnu�[���PKn�Z9����,�1Structures/Graph/Manipulator/AcyclicTest.phpnu�[���PKn�Z~(�htt2�HStructures/Graph/Manipulator/TopologicalSorter.phpnu�[���PKn�Z�J�}
}
_dAuth/SASL/Anonymous.phpnu�[���PKn�ZP(~�T
T
#rAuth/SASL/CramMD5.phpnu�[���PKn�Z����==�Auth/SASL/Plain.phpnu�[���PKn�Z�<� OO<�Auth/SASL/Login.phpnu�[���PKn�Z%ׅtg!g!ΘAuth/SASL/DigestMD5.phpnu�[���PKn�Z�T�|�Auth/SASL/Common.phpnu�[���PKn�ZvR�r,,��Auth/SASL/External.phpnu�[���PKn�Zќ��0�0H�Auth/SASL/SCRAM.phpnu�[���PKn�Z2r����
�	Auth/SASL.phpnu�[���PKn�Z�T�,�,�OS/Guess.phpnu�[���PKn�Z�����KPEAR/Config.phpnu�[���PKn�Z�`�eEAEA
.ZPEAR/REST.phpnu�[���PKn�Z��ym6m6��PEAR/Exception.phpnu�[���PKn�Zr"����_�PEAR/ChannelFile.phpnu�[���PKn�Z��gk�U�U?�PEAR/Validate.phpnu�[���PKn�Zd֣S��u�PEAR/Command/Pickle.xmlnu�[���PKn�Z�z��k<k<W�PEAR/Command/Config.phpnu�[���PKn�Z݄<ii	1PEAR/Command/Mirror.xmlnu�[���PKn�Z,��t"u"u�3PEAR/Command/Remote.phpnu�[���PKn�Z
�\���"�PEAR/Command/Remote.xmlnu�[���PKn�Zj���!�!X�PEAR/Command/Install.xmlnu�[���PKo�Z�%q������PEAR/Command/Channels.phpnu�[���PKo�Znmi?;�;��[	PEAR/Command/Install.phpnu�[���PKo�Z�X�

#
PEAR/Command/Auth.phpnu�[���PKo�Z���s6
6
T-
PEAR/Command/Config.xmlnu�[���PKo�Z�%Fii�:
PEAR/Command/Test.xmlnu�[���PKo�ZZ h66A
PEAR/Command/Package.xmlnu�[���PKo�Z�w��zz�]
PEAR/Command/Channels.xmlnu�[���PKo�Z+9ҜҜ�n
PEAR/Command/Package.phpnu�[���PKo�Z
u����PEAR/Command/Build.xmlnu�[���PKo�Z������
PEAR/Command/Mirror.phpnu�[���PKp�Z,_�h/h/�PEAR/Command/Test.phpnu�[���PKp�Z�%sp  6OPEAR/Command/Common.phpnu�[���PKp�Z0(;rʹʹ�oPEAR/Command/Registry.phpnu�[���PKp�Z�4�{���$PEAR/Command/Auth.xmlnu�[���PKp�Z��#S
S
�)PEAR/Command/Build.phpnu�[���PKp�Z���u��S4PEAR/Command/Registry.xmlnu�[���PKp�Z�P>>�;PEAR/Command/Pickle.phpnu�[���PKp�Z��T�I�I�yPEAR/Builder.phpnu�[���PKp�Z[
�W��3�PEAR/XMLParser.phpnu�[���PKp�Zl(e���t�PEAR/Downloader.phpnu�[���PKp�Z�b������
PEAR/ErrorStack.phpnu�[���PKp�Z(Pz����ePEAR/Proxy.phpnu�[���PKp�Z��'����|PEAR/RunTest.phpnu�[���PKq�Zj�y99�	PEAR/Validator/PECL.phpnu�[���PKq�Zp�����aPEAR/Dependency2.phpnu�[���PKq�Z��wv@@��PEAR/PackageFile/v2.phpnu�[���PKq�ZC�8�L�L!:�PEAR/PackageFile/v2/Validator.phpnu�[���PKq�Z���=_�_�6PEAR/PackageFile/v2/rw.phpnu�[���PKq�Z�5�������,PEAR/PackageFile/v1.phpnu�[���PKq�Z�ɁɁ!��PEAR/PackageFile/Generator/v2.phpnu�[���PKq�Z`�=����!�tPEAR/PackageFile/Generator/v1.phpnu�[���PKr�Z��OWHH�9PEAR/PackageFile/Parser/v2.phpnu�[���PKr�Z�_=�@�@`FPEAR/PackageFile/Parser/v1.phpnu�[���PKr�Zc��__5�PEAR/DependencyDB.phpnu�[���PKr�Z�@P��{�PEAR/ChannelFile/Parser.phpnu�[���PKr�Z��_�0�0r�PEAR/Command.phpnu�[���PKr�Z�ٲ�=�==PEAR/PackageFile.phpnu�[���PKr�Z�JD��g\PEAR/Task/Replace.phpnu�[���PKr�Z&%75))�wPEAR/Task/Windowseol/rw.phpnu�[���PKr�Z�3}}PEAR/Task/Replace/rw.phpnu�[���PKr�Z&
i."x�PEAR/Task/Postinstallscript/rw.phpnu�[���PKr�Z�-!�PEAR/Task/Common.phpnu�[���PKr�ZD$���I�PEAR/Task/Windowseol.phpnu�[���PKr�ZZ�E�x9x9��PEAR/Task/Postinstallscript.phpnu�[���PKr�Z\k��K�PEAR/Task/Unixeol/rw.phpnu�[���PKr�Z�������PEAR/Task/Unixeol.phpnu�[���PKr�Z�W�f���PEAR/REST/10.phpnu�[���PKr�Z��Y�;;ąPEAR/REST/13.phpnu�[���PKr�Z,#y��+�+�PEAR/REST/11.phpnu�[���PKr�Z��U  D�PEAR/Packager.phpnu�[���PKr�ZZ�bgbg�PEAR/Common.phpnu�[���PKr�Z$���(�(FsPEAR/Registry.phpnu�[���PKr�Z��	MdMd?�PEAR/Frontend/CLI.phpnu�[���PKr�Z��

�PEAR/Installer/Role/Doc.phpnu�[���PKr�Z��/��)PEAR/Installer/Role/Cfg.xmlnu�[���PKr�Z>1H���PEAR/Installer/Role/Www.xmlnu�[���PKr�Z�?m

PEAR/Installer/Role/Php.phpnu�[���PKr�Z*Y|	%%`PEAR/Installer/Role/Man.phpnu�[���PKr�Z���BB�PEAR/Installer/Role/Ext.xmlnu�[���PKr�Zp��""]PEAR/Installer/Role/Src.xmlnu�[���PKr�Zh&P*���PEAR/Installer/Role/Doc.xmlnu�[���PKr�ZB] ���PEAR/Installer/Role/Test.xmlnu�[���PKr�Zz�q����PEAR/Installer/Role/Php.xmlnu�[���PKr�Z	��
|PEAR/Installer/Role/Data.phpnu�[���PKs�Z�0�c���PEAR/Installer/Role/Man.xmlnu�[���PKs�Z��K

�PEAR/Installer/Role/Ext.phpnu�[���PKs�ZY��� PEAR/Installer/Role/Test.phpnu�[���PKs�Z@v�а�z#PEAR/Installer/Role/Script.xmlnu�[���PKs�Zf�sz��x%PEAR/Installer/Role/Data.xmlnu�[���PKs�Z?���GGV'PEAR/Installer/Role/Common.phpnu�[���PKs�Z�^D{		�?PEAR/Installer/Role/Www.phpnu�[���PKs�Z�Ƥ?CPEAR/Installer/Role/Cfg.phpnu�[���PKs�Z��[�	SPEAR/Installer/Role/Script.phpnu�[���PKs�Z��srrjVPEAR/Installer/Role/Src.phpnu�[���PKs�ZV�Z���'ZPEAR/Installer/Role.phpnu�[���PKs�Z�{�	�)�)*yPEAR/Downloader/Package.phpnu�[���PKs�Z.�4���$�PEAR/Frontend.phpnu�[���PKs�Z،�w��_�PEAR/Installer.phpnu�[���PKs�ZXxo��-j�Symfony/Bridge/Doctrine/Logger/DbalLogger.phpnu�[���PKs�Ze�OO&b�Symfony/Bridge/Doctrine/autoloader.phpnu�[���PKs�Z��X+��8�Symfony/Bridge/Doctrine/CacheWarmer/ProxyCacheWarmer.phpnu�[���PKs�Z	�9,��5i�Symfony/Bridge/Doctrine/Form/DoctrineOrmExtension.phpnu�[���PKs�Z�0���NX�Symfony/Bridge/Doctrine/Form/EventListener/MergeDoctrineCollectionListener.phpnu�[���PKs�Z!%d==A��Symfony/Bridge/Doctrine/Form/ChoiceList/EntityLoaderInterface.phpnu�[���PKs�Z�	?x�7�7<4�Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.phpnu�[���PKs�ZGC�t��A<-Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.phpnu�[���PKs�Z`.
qpp7�9Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.phpnu�[���PKs�ZCi�PPMZQSymfony/Bridge/Doctrine/Form/DataTransformer/CollectionToArrayTransformer.phpnu�[���PKs�Z憝��0'YSymfony/Bridge/Doctrine/Form/Type/EntityType.phpnu�[���PKs�ZS;,:��2-]Symfony/Bridge/Doctrine/Form/Type/DoctrineType.phpnu�[���PKs�ZW&v��<�wSymfony/Bridge/Doctrine/Security/User/EntityUserProvider.phpnu�[���PKs�Z�����Et�Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.phpnu�[���PKs�Z(��y��9�Symfony/Bridge/Doctrine/Validator/DoctrineInitializer.phpnu�[���PKs�ZQГ��>�Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.phpnu�[���PKs�Z:�d�G5�Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.phpnu�[���PKs�Z�Ta�==B��Symfony/Bridge/Doctrine/ExpressionLanguage/DoctrineParserCache.phpnu�[���PKs�Z��qm
m
-m�Symfony/Bridge/Doctrine/RegistryInterface.phpnu�[���PKs�Zlf/�qq=7�Symfony/Bridge/Doctrine/DataFixtures/ContainerAwareLoader.phpnu�[���PKs�Z����=�Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.phpnu�[���PKs�Z�����C��Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerSchema.phpnu�[���PKs�ZOlQ�996��Symfony/Bridge/Doctrine/ContainerAwareEventManager.phpnu�[���PKs�Z؈����3D�Symfony/Bridge/Doctrine/Test/DoctrineTestHelper.phpnu�[���PKs�Z̳֨�+��Symfony/Bridge/Doctrine/ManagerRegistry.phpnu�[���PKs�Z+çxAA?�Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.phpnu�[���PKs�Z*�+��J�JIBSymfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.phpnu�[���PKs�Z���*��SVaSymfony/Bridge/Doctrine/DependencyInjection/Security/UserProvider/EntityFactory.phpnu�[���PKs�Z��㛕�Q�hSymfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterMappingsPass.phpnu�[���PKs�Z~�YAAeԀSymfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.phpnu�[���PKs�Z��,���S��Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/DoctrineValidationPass.phpnu�[���PKs�Z��4NN%,�Symfony/Bridge/Monolog/autoloader.phpnu�[���PKs�Z��մ��1ϡSymfony/Bridge/Monolog/Handler/FirePHPHandler.phpnu�[���PKs�Z��Zv��/©Symfony/Bridge/Monolog/Handler/DebugHandler.phpnu�[���PKs�Z�y���1دSymfony/Bridge/Monolog/Handler/ConsoleHandler.phpnu�[���PKs�Z��*vv5�Symfony/Bridge/Monolog/Handler/SwiftMailerHandler.phpnu�[���PKs�Z���"II3��Symfony/Bridge/Monolog/Handler/ChromePhpHandler.phpnu�[���PKs�Z��;��	�	!��Symfony/Bridge/Monolog/Logger.phpnu�[���PKs�Z��b115��Symfony/Bridge/Monolog/Formatter/ConsoleFormatter.phpnu�[���PKt�Z�,��1l�Symfony/Bridge/Monolog/Processor/WebProcessor.phpnu�[���PKt�Z�$�KK"l�Symfony/Bridge/Twig/autoloader.phpnu�[���PKt�Z�)�UU1	�Symfony/Bridge/Twig/Translation/TwigExtractor.phpnu�[���PKt�Z6DZ77*��Symfony/Bridge/Twig/Node/StopwatchNode.phpnu�[���PKt�Z,
�@��5P�Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.phpnu�[���PKt�Z�
�s>>*ESymfony/Bridge/Twig/Node/FormThemeNode.phpnu�[���PKt�ZP�IAA3�Symfony/Bridge/Twig/Node/TransDefaultDomainNode.phpnu�[���PKt�Z�U,tt,�Symfony/Bridge/Twig/Node/FormEnctypeNode.phpnu�[���PKt�Zʦ\�G
G
&QSymfony/Bridge/Twig/Node/TransNode.phpnu�[���PKt�Z���^��,�%Symfony/Bridge/Twig/Node/RenderBlockNode.phpnu�[���PKt�Z�vq�)+Symfony/Bridge/Twig/Form/TwigRenderer.phpnu�[���PKt�Zb�3�}}8q1Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.phpnu�[���PKt�Z��Qkk2V4Symfony/Bridge/Twig/Form/TwigRendererInterface.phpnu�[���PKt�Z��<��/#7Symfony/Bridge/Twig/Form/TwigRendererEngine.phpnu�[���PKt�Z�GTSymfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.phpnu�[���PKt�Z�)�[n	n	)�`Symfony/Bridge/Twig/NodeVisitor/Scope.phpnu�[���PKt�Z�tA�:`jSymfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.phpnu�[���PKt�Z��9292B�xSymfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twignu�[���PKt�Z��[[Dy�Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twignu�[���PKt�Z.��8H�Symfony/Bridge/Twig/TokenParser/StopwatchTokenParser.phpnu�[���PKt�Z�%]�
�
4��Symfony/Bridge/Twig/TokenParser/TransTokenParser.phpnu�[���PKt�Z�/�	�	:��Symfony/Bridge/Twig/TokenParser/TransChoiceTokenParser.phpnu�[���PKt�Z>����8>�Symfony/Bridge/Twig/TokenParser/FormThemeTokenParser.phpnu�[���PKt�Zʶ�̭�Ao�Symfony/Bridge/Twig/TokenParser/TransDefaultDomainTokenParser.phpnu�[���PKt�Z�9�=KK/��Symfony/Bridge/Twig/Extension/FormExtension.phpnu�[���PKt�Z��|/7�Symfony/Bridge/Twig/Extension/YamlExtension.phpnu�[���PKt�Z��&�a
a
5��Symfony/Bridge/Twig/Extension/HttpKernelExtension.phpnu�[���PKt�ZKΙ���5v�Symfony/Bridge/Twig/Extension/ExpressionExtension.phpnu�[���PKt�Z`�fS..2� Symfony/Bridge/Twig/Extension/RoutingExtension.phpnu�[���PKt�Z�5��mm4] Symfony/Bridge/Twig/Extension/StopwatchExtension.phpnu�[���PKt�Z�?���6. Symfony/Bridge/Twig/Extension/TranslationExtension.phpnu�[���PKt�Zd���oo3�! Symfony/Bridge/Twig/Extension/SecurityExtension.phpnu�[���PKt�Z�����/a' Symfony/Bridge/Twig/Extension/CodeExtension.phpnu�[���PKu�Z^D��dd"sG Symfony/Bridge/Twig/TwigEngine.phpnu�[���PKu�Z�4˵��()V Symfony/Component/Finder/Shell/Shell.phpnu�[���PKu�Z5��K��*^ Symfony/Component/Finder/Shell/Command.phpnu�[���PKu�Z�5�9(�v Symfony/Component/Finder/SplFileInfo.phpnu�[���PKu�Z%uM�PP'X~ Symfony/Component/Finder/autoloader.phpnu�[���PKu�Z��99C� Symfony/Component/Finder/Exception/ShellCommandFailureException.phpnu�[���PKu�Z�7��9�� Symfony/Component/Finder/Exception/ExceptionInterface.phpnu�[���PKu�Z�cWޫ�<� Symfony/Component/Finder/Exception/AccessDeniedException.phpnu�[���PKu�Z>�@��>� Symfony/Component/Finder/Exception/AdapterFailureException.phpnu�[���PKu�ZP�����D	� Symfony/Component/Finder/Exception/OperationNotPermitedException.phpnu�[���PKu�Z��� ��6� Symfony/Component/Finder/Comparator/DateComparator.phpnu�[���PKu�Z|F�z

2?� Symfony/Component/Finder/Comparator/Comparator.phpnu�[���PKu�Z�P�

8�� Symfony/Component/Finder/Comparator/NumberComparator.phpnu�[���PKu�Z�g@Mbb!2� Symfony/Component/Finder/Glob.phpnu�[���PKu�Z�d�V�V#� Symfony/Component/Finder/Finder.phpnu�[���PKu�Zils_��>
!Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.phpnu�[���PKu�Z��ɔ�
�
7u!Symfony/Component/Finder/Iterator/FilePathsIterator.phpnu�[���PKu�Z�,G��4n!Symfony/Component/Finder/Iterator/FilterIterator.phpnu�[���PKu�Z�ʽ���?q#!Symfony/Component/Finder/Iterator/FilecontentFilterIterator.phpnu�[���PKu�Z�

���@~+!Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.phpnu�[���PKu�Z��z":�2!Symfony/Component/Finder/Iterator/CustomFilterIterator.phpnu�[���PKu�Z{�^ǽ�<N9!Symfony/Component/Finder/Iterator/FilenameFilterIterator.phpnu�[���PKu�Z�d����Dw@!Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.phpnu�[���PKu�Zx�P���=�F!Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.phpnu�[���PKu�Z ��U��=�L!Symfony/Component/Finder/Iterator/DateRangeFilterIterator.phpnu�[���PKu�Z�n bb<�R!Symfony/Component/Finder/Iterator/FileTypeFilterIterator.phpnu�[���PKu�Z��j��	�	6�X!Symfony/Component/Finder/Iterator/SortableIterator.phpnu�[���PKu�Z���)��8�b!Symfony/Component/Finder/Iterator/PathFilterIterator.phpnu�[���PKu�Z�6s��@�j!Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.phpnu�[���PKu�Z��&
&
2Gw!Symfony/Component/Finder/Expression/Expression.phpnu�[���PKu�Z�"HH6ρ!Symfony/Component/Finder/Expression/ValueInterface.phpnu�[���PKu�Z�E�,}�!Symfony/Component/Finder/Expression/Glob.phpnu�[���PKu�Z��(�-�!Symfony/Component/Finder/Expression/Regex.phpnu�[���PKu�Z9!�2{
{
/D�!Symfony/Component/Finder/Adapter/PhpAdapter.phpnu�[���PKu�Z����5�!Symfony/Component/Finder/Adapter/AdapterInterface.phpnu�[���PKu�Z��kA�
�
34�!Symfony/Component/Finder/Adapter/BsdFindAdapter.phpnu�[���PKu�Z�}]�
�
3��!Symfony/Component/Finder/Adapter/GnuFindAdapter.phpnu�[���PKu�ZQJ)�)8��!Symfony/Component/Finder/Adapter/AbstractFindAdapter.phpnu�[���PKu�Z�	4�"Symfony/Component/Finder/Adapter/AbstractAdapter.phpnu�[���PKu�Z����:;"Symfony/Component/Translation/Extractor/ChainExtractor.phpnu�[���PKu�ZArP�>%"Symfony/Component/Translation/Extractor/ExtractorInterface.phpnu�[���PKu�Zb*0�oo4�#"Symfony/Component/Translation/PluralizationRules.phpnu�[���PKu�Z�q��UU,<"Symfony/Component/Translation/autoloader.phpnu�[���PKu�Z�<qNN10>"Symfony/Component/Translation/MessageSelector.phpnu�[���PKu�Z�س��:�J"Symfony/Component/Translation/Catalogue/MergeOperation.phpnu�[���PKu�ZY[�>*P"Symfony/Component/Translation/Catalogue/OperationInterface.phpnu�[���PKu�Z��fb�
�
=�U"Symfony/Component/Translation/Catalogue/AbstractOperation.phpnu�[���PKu�Z��ӄ�9�c"Symfony/Component/Translation/Catalogue/DiffOperation.phpnu�[���PKu�Z�6�"��>�i"Symfony/Component/Translation/Exception/ExceptionInterface.phpnu�[���PKu�ZDŽ���D�k"Symfony/Component/Translation/Exception/InvalidResourceException.phpnu�[���PKv�Z�2B��E2n"Symfony/Component/Translation/Exception/NotFoundResourceException.phpnu�[���PKv�Z�y4��2�p"Symfony/Component/Translation/MessageCatalogue.phpnu�[���PKv�Z%�Mt8��"Symfony/Component/Translation/MetadataAwareInterface.phpnu�[���PKv�Z�d�<<4��"Symfony/Component/Translation/IdentityTranslator.phpnu�[���PKv�Z�e�G��,��"Symfony/Component/Translation/Translator.phpnu�[���PKv�Z��֛�;u�"Symfony/Component/Translation/MessageCatalogueInterface.phpnu�[���PKv�ZM�
���9{�"Symfony/Component/Translation/Dumper/IcuResFileDumper.phpnu�[���PKv�Zਪ(5u�"Symfony/Component/Translation/Dumper/PoFileDumper.phpnu�[���PKv�Z���%LL6��"Symfony/Component/Translation/Dumper/PhpFileDumper.phpnu�[���PKv�Z�<̧��8��"Symfony/Component/Translation/Dumper/XliffFileDumper.phpnu�[���PKv�Z>{GG5��"Symfony/Component/Translation/Dumper/QtFileDumper.phpnu�[���PKv�Z���667Z�"Symfony/Component/Translation/Dumper/YamlFileDumper.phpnu�[���PKv�ZoB���6��"Symfony/Component/Translation/Dumper/CsvFileDumper.phpnu�[���PKv�ZB^�[[3*�"Symfony/Component/Translation/Dumper/FileDumper.phpnu�[���PKv�Z�:$}}7�"Symfony/Component/Translation/Dumper/JsonFileDumper.phpnu�[���PKv�Z&X����6�#Symfony/Component/Translation/Dumper/IniFileDumper.phpnu�[���PKv�Z��<**8
#Symfony/Component/Translation/Dumper/DumperInterface.phpnu�[���PKv�Z����A	A	5�#Symfony/Component/Translation/Dumper/MoFileDumper.phpnu�[���PKv�Zg�?Z�
�
*B#Symfony/Component/Translation/Interval.phpnu�[���PKv�Z�3����5�#Symfony/Component/Translation/TranslatorInterface.phpnu�[���PKv�ZP�?�}}:�%#Symfony/Component/Translation/Writer/TranslationWriter.phpnu�[���PKv�ZN@���6�-#Symfony/Component/Translation/Loader/IniFileLoader.phpnu�[���PKv�Z�T�93#Symfony/Component/Translation/Loader/IcuDatFileLoader.phpnu�[���PKv�ZCS�z
z
9�9#Symfony/Component/Translation/Loader/IcuResFileLoader.phpnu�[���PKv�Z��v���5�D#Symfony/Component/Translation/Loader/MoFileLoader.phpnu�[���PKv�ZR����4&\#Symfony/Component/Translation/Loader/ArrayLoader.phpnu�[���PKv�Z�'s�u	u	7&d#Symfony/Component/Translation/Loader/JsonFileLoader.phpnu�[���PKv�Z�i�3"
"
6n#Symfony/Component/Translation/Loader/CsvFileLoader.phpnu�[���PKv�Z_��BB8�x#Symfony/Component/Translation/Loader/XliffFileLoader.phpnu�[���PKv�Zl#�tt84�#Symfony/Component/Translation/Loader/LoaderInterface.phpnu�[���PKv�Z�*���5�#Symfony/Component/Translation/Loader/PoFileLoader.phpnu�[���PKv�Z�r��;;6o�#Symfony/Component/Translation/Loader/PhpFileLoader.phpnu�[���PKv�Z:�	Z�"�"B�#Symfony/Component/Translation/Loader/schema/dic/xliff-core/xml.xsdnu�[���PKv�Z�xO��T�#Symfony/Component/Translation/Loader/schema/dic/xliff-core/xliff-core-1.2-strict.xsdnu�[���PKv�Z)-d+�	�	5�g%Symfony/Component/Translation/Loader/QtFileLoader.phpnu�[���PKv�Z:����7�q%Symfony/Component/Translation/Loader/YamlFileLoader.phpnu�[���PKw�Z�V�˽�.-z%Symfony/Component/Routing/Annotation/Route.phpnu�[���PKw�Z�<ѹ�+H�%Symfony/Component/Routing/CompiledRoute.phpnu�[���PKw�ZU8���-\�%Symfony/Component/Routing/RouterInterface.phpnu�[���PKw�ZU�cQQ(>�%Symfony/Component/Routing/autoloader.phpnu�[���PKw�Z����'�'+�%Symfony/Component/Routing/RouteCompiler.phpnu�[���PKw�Z��%�%$�%Symfony/Component/Routing/Router.phpnu�[���PKw�Z���q
q
6n�%Symfony/Component/Routing/Matcher/ApacheUrlMatcher.phpnu�[���PKw�Z	�ڗ9E�%Symfony/Component/Routing/Matcher/UrlMatcherInterface.phpnu�[���PKw�Z`�u���=��%Symfony/Component/Routing/Matcher/RequestMatcherInterface.phpnu�[���PKw�Z[z�dd<�&Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.phpnu�[���PKw�Z?�|{��:�&Symfony/Component/Routing/Matcher/Dumper/MatcherDumper.phpnu�[���PKw�Z�x}�44=�&Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.phpnu�[���PKw�Z�bz#z#@A&Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.phpnu�[���PKw�Z�`=e&Symfony/Component/Routing/Matcher/Dumper/DumperCollection.phpnu�[���PKw�Z�N�
�
C�s&Symfony/Component/Routing/Matcher/Dumper/DumperPrefixCollection.phpnu�[���PKw�Z(� ���C�~&Symfony/Component/Routing/Matcher/Dumper/MatcherDumperInterface.phpnu�[���PKw�ZY�IWW8��&Symfony/Component/Routing/Matcher/Dumper/DumperRoute.phpnu�[���PKw�Z�'��9��&Symfony/Component/Routing/Matcher/TraceableUrlMatcher.phpnu�[���PKw�ZGj�C""0��&Symfony/Component/Routing/Matcher/UrlMatcher.phpnu�[���PKw�Z� ��ffE'�&Symfony/Component/Routing/Matcher/RedirectableUrlMatcherInterface.phpnu�[���PKw�Z����==K�&Symfony/Component/Routing/Exception/MissingMandatoryParametersException.phpnu�[���PKw�Zj`j�A��&Symfony/Component/Routing/Exception/InvalidParameterException.phpnu�[���PKw�Znj�W��>/�&Symfony/Component/Routing/Exception/RouteNotFoundException.phpnu�[���PKw�Z��)���:��&Symfony/Component/Routing/Exception/ExceptionInterface.phpnu�[���PKw�Z����JJA��&Symfony/Component/Routing/Exception/MethodNotAllowedException.phpnu�[���PKw�Z?�]�//Af�&Symfony/Component/Routing/Exception/ResourceNotFoundException.phpnu�[���PKw�Z��^�==#�&Symfony/Component/Routing/Route.phpnu�[���PKw�Zr�����:i	'Symfony/Component/Routing/RequestContextAwareInterface.phpnu�[���PKw�Z|,{Ȫ�-p'Symfony/Component/Routing/RouteCollection.phpnu�[���PKw�Z�h�,w)'Symfony/Component/Routing/RequestContext.phpnu�[���PKw�Zմ���I�C'Symfony/Component/Routing/Generator/ConfigurableRequirementsInterface.phpnu�[���PKw�Z�
��1�148M'Symfony/Component/Routing/Generator/UrlGenerator.phpnu�[���PKw�Z�1O�
�
Az'Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.phpnu�[���PKw�Zu�'��>��'Symfony/Component/Routing/Generator/Dumper/GeneratorDumper.phpnu�[���PKw�Z�4��G��'Symfony/Component/Routing/Generator/Dumper/GeneratorDumperInterface.phpnu�[���PKw�Z����@@=�'Symfony/Component/Routing/Generator/UrlGeneratorInterface.phpnu�[���PKw�Zn���hh2Ȥ'Symfony/Component/Routing/Loader/ClosureLoader.phpnu�[���PKw�Z��?�		>��'Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.phpnu�[���PKw�Z~ޟ
�
9�'Symfony/Component/Routing/Loader/AnnotationFileLoader.phpnu�[���PKw�Z~L�W��:�'Symfony/Component/Routing/Loader/AnnotationClassLoader.phpnu�[���PKw�ZP�i{��2��'Symfony/Component/Routing/Loader/PhpFileLoader.phpnu�[���PKw�Z?-[��	�	?5�'Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsdnu�[���PKw�Zأ2D$D$2L�'Symfony/Component/Routing/Loader/XmlFileLoader.phpnu�[���PKw�ZpB�Q Q 3�(Symfony/Component/Routing/Loader/YamlFileLoader.phpnu�[���PKx�ZqF��>>4�5(Symfony/Component/Routing/RouteCompilerInterface.phpnu�[���PKx�Z0���QQ(H9(Symfony/Component/Process/autoloader.phpnu�[���PKx�Zg��'�'*�:(Symfony/Component/Process/ProcessPipes.phpnu�[���PKx�Z��2�{{@6c(Symfony/Component/Process/Exception/ProcessTimedOutException.phpnu�[���PKx�Z�<���:!j(Symfony/Component/Process/Exception/ExceptionInterface.phpnu�[���PKx�Z>H����8:l(Symfony/Component/Process/Exception/RuntimeException.phpnu�[���PKx�Z��W��6�n(Symfony/Component/Process/Exception/LogicException.phpnu�[���PKx�Z˅����@�p(Symfony/Component/Process/Exception/InvalidArgumentException.phpnu�[���PKx�Z��_��>s(Symfony/Component/Process/Exception/ProcessFailedException.phpnu�[���PKx�Z@s�(�x(Symfony/Component/Process/PhpProcess.phpnu�[���PKx�Z�nL	L	*�(Symfony/Component/Process/ProcessUtils.phpnu�[���PKy�Z�!,$

.��(Symfony/Component/Process/ExecutableFinder.phpnu�[���PKy�Z!/���,�(Symfony/Component/Process/ProcessBuilder.phpnu�[���PKy�Zy>�8��1�(Symfony/Component/Process/PhpExecutableFinder.phpnu�[���PKy�Z��M��%ު(Symfony/Component/Process/Process.phpnu�[���PKy�Z[i55ERA)Symfony/Component/Serializer/Normalizer/SerializerAwareNormalizer.phpnu�[���PKy�Z=Vxe::A�D)Symfony/Component/Serializer/Normalizer/NormalizableInterface.phpnu�[���PKy�Z��SVV<�J)Symfony/Component/Serializer/Normalizer/CustomNormalizer.phpnu�[���PKy�Z��,,BiR)Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.phpnu�[���PKy�Z"p�yy?q)Symfony/Component/Serializer/Normalizer/NormalizerInterface.phpnu�[���PKy�Z�qU���C�u)Symfony/Component/Serializer/Normalizer/DenormalizableInterface.phpnu�[���PKz�Z���A�{)Symfony/Component/Serializer/Normalizer/DenormalizerInterface.phpnu�[���PKz�Z���OO9t�)Symfony/Component/Serializer/SerializerAwareInterface.phpnu�[���PKz�Z��TT+,�)Symfony/Component/Serializer/autoloader.phpnu�[���PKz�Zx蕰

4ۅ)Symfony/Component/Serializer/SerializerInterface.phpnu�[���PKz�Z,�c��9L�)Symfony/Component/Serializer/Encoder/EncoderInterface.phpnu�[���PKz�Z��[�5�53i�)Symfony/Component/Serializer/Encoder/XmlEncoder.phpnu�[���PKz�Z�<=ggD��)Symfony/Component/Serializer/Encoder/NormalizationAwareInterface.phpnu�[���PKz�ZV��O��5��)Symfony/Component/Serializer/Encoder/ChainDecoder.phpnu�[���PKz�Z�=��?��)Symfony/Component/Serializer/Encoder/SerializerAwareEncoder.phpnu�[���PKz�Zv:�hh3[�)Symfony/Component/Serializer/Encoder/JsonEncode.phpnu�[���PKz�Z��@���3&�)Symfony/Component/Serializer/Encoder/JsonDecode.phpnu�[���PKz�ZS R�	�	5q�)Symfony/Component/Serializer/Encoder/ChainEncoder.phpnu�[���PKz�Z�o�vv4��)Symfony/Component/Serializer/Encoder/JsonEncoder.phpnu�[���PKz�Z|ͼ���9��)Symfony/Component/Serializer/Encoder/DecoderInterface.phpnu�[���PKz�ZA�A
��4�*Symfony/Component/Serializer/Exception/Exception.phpnu�[���PKz�Z�^L��?�*Symfony/Component/Serializer/Exception/UnsupportedException.phpnu�[���PKz�Z�h=��;�*Symfony/Component/Serializer/Exception/RuntimeException.phpnu�[���PKz�ZJ���9�*Symfony/Component/Serializer/Exception/LogicException.phpnu�[���PKz�ZT��Y��C	*Symfony/Component/Serializer/Exception/InvalidArgumentException.phpnu�[���PKz�Z[�����Ci*Symfony/Component/Serializer/Exception/UnexpectedValueException.phpnu�[���PKz�Zʪ2/&/&+�
*Symfony/Component/Serializer/Serializer.phpnu�[���PKz�ZFP�PP'<4*Symfony/Component/Locale/autoloader.phpnu�[���PKz�Z�Q�UUL�5*Symfony/Component/Locale/Exception/MethodArgumentNotImplementedException.phpnu�[���PKz�Z��E>�9*Symfony/Component/Locale/Exception/NotImplementedException.phpnu�[���PKz�ZS�?a%%D#=*Symfony/Component/Locale/Exception/MethodNotImplementedException.phpnu�[���PKz�Z���ssQ�@*Symfony/Component/Locale/Exception/MethodArgumentValueNotImplementedException.phpnu�[���PKz�Z�C��*�D*Symfony/Component/Locale/Stub/StubIntl.phpnu�[���PKz�Z&�����5�G*Symfony/Component/Locale/Stub/StubNumberFormatter.phpnu�[���PKz�Zv/�@�J*Symfony/Component/Locale/Stub/DateFormat/Hour2401Transformer.phpnu�[���PKz�Z��S@PN*Symfony/Component/Locale/Stub/DateFormat/TimeZoneTransformer.phpnu�[���PKz�Z}��""A�Q*Symfony/Component/Locale/Stub/DateFormat/DayOfYearTransformer.phpnu�[���PKz�Z�X�<oU*Symfony/Component/Locale/Stub/DateFormat/AmPmTransformer.phpnu�[���PKz�Z���<�X*Symfony/Component/Locale/Stub/DateFormat/YearTransformer.phpnu�[���PKz�Zmў?O\*Symfony/Component/Locale/Stub/DateFormat/QuarterTransformer.phpnu�[���PKz�Zg[ep>�_*Symfony/Component/Locale/Stub/DateFormat/MinuteTransformer.phpnu�[���PKz�Z:6""ARc*Symfony/Component/Locale/Stub/DateFormat/DayOfWeekTransformer.phpnu�[���PKz�Z9�u@�f*Symfony/Component/Locale/Stub/DateFormat/Hour1200Transformer.phpnu�[���PKz�Zk&"M@qj*Symfony/Component/Locale/Stub/DateFormat/Hour1201Transformer.phpnu�[���PKz�Z�����;�m*Symfony/Component/Locale/Stub/DateFormat/DayTransformer.phpnu�[���PKz�Z��@fq*Symfony/Component/Locale/Stub/DateFormat/Hour2400Transformer.phpnu�[���PKz�Z�Ed��8�t*Symfony/Component/Locale/Stub/DateFormat/Transformer.phpnu�[���PKz�Zt�z

=Ox*Symfony/Component/Locale/Stub/DateFormat/MonthTransformer.phpnu�[���PKz�Zk�H<�{*Symfony/Component/Locale/Stub/DateFormat/FullTransformer.phpnu�[���PKz�Z�3�X>6*Symfony/Component/Locale/Stub/DateFormat/SecondTransformer.phpnu�[���PKz�Z�
�

<��*Symfony/Component/Locale/Stub/DateFormat/HourTransformer.phpnu�[���PKz�Z���?��.-�*Symfony/Component/Locale/Stub/StubCollator.phpnu�[���PK{�Zq��*((,�*Symfony/Component/Locale/Stub/StubLocale.phpnu�[���PK{�Z� S���7��*Symfony/Component/Locale/Stub/StubIntlDateFormatter.phpnu�[���PK{�Zl�l��#��*Symfony/Component/Locale/Locale.phpnu�[���PK{�Z�t�TT+��*Symfony/Component/Filesystem/autoloader.phpnu�[���PK{�Z��dP��@b�*Symfony/Component/Filesystem/Exception/FileNotFoundException.phpnu�[���PK{�Z3{����=��*Symfony/Component/Filesystem/Exception/ExceptionInterface.phpnu�[���PK{�ZoC�~��?��*Symfony/Component/Filesystem/Exception/IOExceptionInterface.phpnu�[���PK{�Z;�{��6ͷ*Symfony/Component/Filesystem/Exception/IOException.phpnu�[���PK{�ZOظ�GG+�*Symfony/Component/Filesystem/Filesystem.phpnu�[���PK{�Z)��.�.'T+Symfony/Component/Form/FormRenderer.phpnu�[���PK{�Z�C����.]2+Symfony/Component/Form/ButtonTypeInterface.phpnu�[���PK{�ZK'�$��&�4+Symfony/Component/Form/FormBuilder.phpnu�[���PK{�Z&�"̰T�T,�S+Symfony/Component/Form/FormConfigBuilder.phpnu�[���PK{�ZE1�'��4��+Symfony/Component/Form/SubmitButtonTypeInterface.phpnu�[���PK{�Z�d��'�+Symfony/Component/Form/FormRegistry.phpnu�[���PK{�ZÊM'%%.н+Symfony/Component/Form/FormConfigInterface.phpnu�[���PK{�Z��@@/S�+Symfony/Component/Form/FormTypeGuesserChain.phpnu�[���PK{�ZR����+��+Symfony/Component/Form/Guess/ValueGuess.phpnu�[���PK{�Z�511&,�+Symfony/Component/Form/Guess/Guess.phpnu�[���PK{�Z���  *��+Symfony/Component/Form/Guess/TypeGuess.phpnu�[���PK{�Z�0\ZZ.-�+Symfony/Component/Form/CallbackTransformer.phpnu�[���PK{�Z4�Nz"z"!�,Symfony/Component/Form/Button.phpnu�[���PK{�Z-�9NN%�%,Symfony/Component/Form/autoloader.phpnu�[���PK{�Z�/��tt%S',Symfony/Component/Form/FormEvents.phpnu�[���PK{�Z�����,,,Symfony/Component/Form/FormTypeInterface.phpnu�[���PK{�Z�>���09,Symfony/Component/Form/FormRegistryInterface.phpnu�[���PK{�Z��?zz3?,Symfony/Component/Form/FormTypeGuesserInterface.phpnu�[���PK{�Z��*��+�G,Symfony/Component/Form/ResolvedFormType.phpnu�[���PK{�ZObX�qq'6f,Symfony/Component/Form/SubmitButton.phpnu�[���PK|�Z�p��1�j,Symfony/Component/Form/AbstractRendererEngine.phpnu�[���PK|�ZDjN,1�,Symfony/Component/Form/AbstractExtension.phpnu�[���PK|�Zf#jK��6��,Symfony/Component/Form/FormRendererEngineInterface.phpnu�[���PK|�Z���1�1���,Symfony/Component/Form/Form.phpnu�[���PK|�Z�di���;A-Symfony/Component/Form/Exception/BadMethodCallException.phpnu�[���PK|�Z�W�

:yC-Symfony/Component/Form/Exception/AlreadyBoundException.phpnu�[���PK|�Z(ddB�E-Symfony/Component/Form/Exception/InvalidConfigurationException.phpnu�[���PK|�Z�_c==<�G-Symfony/Component/Form/Exception/UnexpectedTypeException.phpnu�[���PK|�Z�S�D��BoJ-Symfony/Component/Form/Exception/TransformationFailedException.phpnu�[���PK|�Z��9�L-Symfony/Component/Form/Exception/OutOfBoundsException.phpnu�[���PK}�Z�y�u��7�N-Symfony/Component/Form/Exception/ExceptionInterface.phpnu�[���PK}�ZN����5
Q-Symfony/Component/Form/Exception/RuntimeException.phpnu�[���PK}�ZK�9���>OS-Symfony/Component/Form/Exception/AlreadySubmittedException.phpnu�[���PK}�Z1�;TT:�U-Symfony/Component/Form/Exception/ErrorMappingException.phpnu�[���PK}�Z��+RR8oW-Symfony/Component/Form/Exception/StringCastException.phpnu�[���PK}�Z��X��3)Y-Symfony/Component/Form/Exception/LogicException.phpnu�[���PK}�Z�gBz��=d[-Symfony/Component/Form/Exception/InvalidArgumentException.phpnu�[���PK}�Z�1��88'�]-Symfony/Component/Form/AbstractType.phpnu�[���PK}�Z�I	�66.Ub-Symfony/Component/Form/Util/OrderedHashMap.phpnu�[���PK}�Z�h��''6�t-Symfony/Component/Form/Util/OrderedHashMapIterator.phpnu�[���PK}�Z��F228v�-Symfony/Component/Form/Util/VirtualFormAwareIterator.phpnu�[���PK}�Zy���$$(�-Symfony/Component/Form/Util/FormUtil.phpnu�[���PK}�Z<����8��-Symfony/Component/Form/Util/InheritDataAwareIterator.phpnu�[���PK}�Z�QT�pp.�-Symfony/Component/Form/SubmitButtonBuilder.phpnu�[���PK}�Z�z5���2��-Symfony/Component/Form/ResolvedFormTypeFactory.phpnu�[���PK}�ZSf��
	
	-��-Symfony/Component/Form/PreloadedExtension.phpnu�[���PK}�Z>��*ii&�-Symfony/Component/Form/FormFactory.phpnu�[���PK}�Z�\�g��2˳-Symfony/Component/Form/RequestHandlerInterface.phpnu�[���PK}�Z+q�DAA7ɶ-Symfony/Component/Form/Test/FormPerformanceTestCase.phpnu�[���PK}�ZsŪ�,q�-Symfony/Component/Form/Test/TypeTestCase.phpnu�[���PK}�Z�,�7//7�-Symfony/Component/Form/Test/DeprecationErrorHandler.phpnu�[���PK}�ZB�4I++7k�-Symfony/Component/Form/Test/FormIntegrationTestCase.phpnu�[���PK}�Z��m�yy4��-Symfony/Component/Form/Test/FormBuilderInterface.phpnu�[���PK}�Za(0kk-��-Symfony/Component/Form/Test/FormInterface.phpnu�[���PK}�Z�n����1��-Symfony/Component/Form/FormExtensionInterface.phpnu�[���PK}�Z|G����4��-Symfony/Component/Form/ResolvedFormTypeInterface.phpnu�[���PK}�Z{d���!�!5��-Symfony/Component/Form/FormConfigBuilderInterface.phpnu�[���PK}�ZɃT���6.Symfony/Component/Form/FormFactoryBuilderInterface.phpnu�[���PK}�Z�N̷;m.Symfony/Component/Form/ResolvedFormTypeFactoryInterface.phpnu�[���PK}�Z2��-�.Symfony/Component/Form/FormFactoryBuilder.phpnu�[���PK}�Z���C��0d$.Symfony/Component/Form/AbstractTypeExtension.phpnu�[���PK}�Z�E���0�(.Symfony/Component/Form/FormRendererInterface.phpnu�[���PK}�Z�:		/�5.Symfony/Component/Form/FormBuilderInterface.phpnu�[���PK}�Z��Z)��/R?.Symfony/Component/Form/FormFactoryInterface.phpnu�[���PK}�Z�YB���.EP.Symfony/Component/Form/ReversedTransformer.phpnu�[���PK}�Z�r�WW3�U.Symfony/Component/Form/DataTransformerInterface.phpnu�[���PK}�ZW�b�[H[H(Eb.Symfony/Component/Form/ButtonBuilder.phpnu�[���PK}�Z��n��?��.Symfony/Component/Form/Resources/translations/validators.en.xlfnu�[���PK}�Z誫���?�.Symfony/Component/Form/Resources/translations/validators.sk.xlfnu�[���PK}�Z�<�yy?=�.Symfony/Component/Form/Resources/translations/validators.uk.xlfnu�[���PK}�Z:����?%�.Symfony/Component/Form/Resources/translations/validators.pl.xlfnu�[���PK��Z��
���?[�.Symfony/Component/Form/Resources/translations/validators.pt.xlfnu�[���PK��Z�%��?��.Symfony/Component/Form/Resources/translations/validators.lv.xlfnu�[���PK��Z္o33D��.Symfony/Component/Form/Resources/translations/validators.sr_Cyrl.xlfnu�[���PK��Z����?��.Symfony/Component/Form/Resources/translations/validators.fi.xlfnu�[���PK��Z0h���?��.Symfony/Component/Form/Resources/translations/validators.es.xlfnu�[���PK��Z�TI��?,�.Symfony/Component/Form/Resources/translations/validators.de.xlfnu�[���PK��Z!�aZ��?~�.Symfony/Component/Form/Resources/translations/validators.it.xlfnu�[���PK��Z �!���?��.Symfony/Component/Form/Resources/translations/validators.ca.xlfnu�[���PK��Z���?��.Symfony/Component/Form/Resources/translations/validators.mn.xlfnu�[���PK��Z���-��?X�.Symfony/Component/Form/Resources/translations/validators.ru.xlfnu�[���PK��Z�3Ե^^?T�.Symfony/Component/Form/Resources/translations/validators.bg.xlfnu�[���PK��ZE��d��?!�.Symfony/Component/Form/Resources/translations/validators.ro.xlfnu�[���PK��ZO���?r�.Symfony/Component/Form/Resources/translations/validators.nl.xlfnu�[���PK��ZS�*��?��.Symfony/Component/Form/Resources/translations/validators.et.xlfnu�[���PK��Z�V5?��.Symfony/Component/Form/Resources/translations/validators.fa.xlfnu�[���PK��Z��q��?J�.Symfony/Component/Form/Resources/translations/validators.id.xlfnu�[���PK��Z�
���?w/Symfony/Component/Form/Resources/translations/validators.cs.xlfnu�[���PK��Z�8,:��B�/Symfony/Component/Form/Resources/translations/validators.zh_CN.xlfnu�[���PK��Z�H�q��?�
/Symfony/Component/Form/Resources/translations/validators.lt.xlfnu�[���PK��Z�_8��?�/Symfony/Component/Form/Resources/translations/validators.fr.xlfnu�[���PK��Z�A�4��?�/Symfony/Component/Form/Resources/translations/validators.gl.xlfnu�[���PK��Z
b�8��?4/Symfony/Component/Form/Resources/translations/validators.hr.xlfnu�[���PK��ZWgUugg?]/Symfony/Component/Form/Resources/translations/validators.nb.xlfnu�[���PK��Zٻ��||?3/Symfony/Component/Form/Resources/translations/validators.eu.xlfnu�[���PK��Z�4@���B#/Symfony/Component/Form/Resources/translations/validators.pt_BR.xlfnu�[���PK��Z��5��?Q'/Symfony/Component/Form/Resources/translations/validators.sl.xlfnu�[���PK��Z�*{���?m+/Symfony/Component/Form/Resources/translations/validators.lb.xlfnu�[���PK��Zbe�@��?�//Symfony/Component/Form/Resources/translations/validators.hu.xlfnu�[���PK��Z_Π��?4/Symfony/Component/Form/Resources/translations/validators.el.xlfnu�[���PK��ZX�����?9/Symfony/Component/Form/Resources/translations/validators.da.xlfnu�[���PK��Z���?�</Symfony/Component/Form/Resources/translations/validators.ja.xlfnu�[���PK��Zs>�ll?AA/Symfony/Component/Form/Resources/translations/validators.sv.xlfnu�[���PK��Zy��99?E/Symfony/Component/Form/Resources/translations/validators.hy.xlfnu�[���PK��Z|��C?�I/Symfony/Component/Form/Resources/translations/validators.ar.xlfnu�[���PK��Zr���DBN/Symfony/Component/Form/Resources/translations/validators.sr_Latn.xlfnu�[���PK��ZNP\��?dR/Symfony/Component/Form/Resources/translations/validators.he.xlfnu�[���PK��Z�xfh..6dV/Symfony/Component/Form/Resources/config/validation.xmlnu�[���PK��ZR}��jj.�X/Symfony/Component/Form/DataMapperInterface.phpnu�[���PK��Z�s�� � (�]/Symfony/Component/Form/FormInterface.phpnu�[���PK��Z���"��$�~/Symfony/Component/Form/FormEvent.phpnu�[���PK��Z�=�MM5Ӄ/Symfony/Component/Form/FormTypeExtensionInterface.phpnu�[���PK��Z�}p�

$��/Symfony/Component/Form/FormError.phpnu�[���PK��Z�	���/ܖ/Symfony/Component/Form/NativeRequestHandler.phpnu�[���PK��Z���*��O'�/Symfony/Component/Form/Extension/Validator/EventListener/ValidationListener.phpnu�[���PK��Z��Ck��@5�/Symfony/Component/Form/Extension/Validator/Util/ServerParams.phpnu�[���PK��Z2=[<((A1�/Symfony/Component/Form/Extension/Validator/ValidatorExtension.phpnu�[���PK��Z}>�ُ�?��/Symfony/Component/Form/Extension/Validator/Constraints/Form.phpnu�[���PK��Z�-�P��H��/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.phpnu�[���PK��Zl�Ct*t*C��/Symfony/Component/Form/Extension/Validator/ValidatorTypeGuesser.phpnu�[���PK��ZɥS��T�
0Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPathIterator.phpnu�[���PK��Z�\T��K0Symfony/Component/Form/Extension/Validator/ViolationMapper/RelativePath.phpnu�[���PK��ZC_�hU+U+N0Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.phpnu�[���PK��Z�k�t==W�@0Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapperInterface.phpnu�[���PK��Z�-��!!L�E0Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPath.phpnu�[���PK��Zf����
�
JR_0Symfony/Component/Form/Extension/Validator/ViolationMapper/MappingRule.phpnu�[���PK��Z�����J�j0Symfony/Component/Form/Extension/Validator/Type/BaseValidatorExtension.phpnu�[���PK��ZeBR�	�	N�p0Symfony/Component/Form/Extension/Validator/Type/FormTypeValidatorExtension.phpnu�[���PK��Z͚>�@@R+{0Symfony/Component/Form/Extension/Validator/Type/RepeatedTypeValidatorExtension.phpnu�[���PK��Z1���P�0Symfony/Component/Form/Extension/Validator/Type/SubmitTypeValidatorExtension.phpnu�[���PK��Z���,QQC��0Symfony/Component/Form/Extension/Templating/TemplatingExtension.phpnu�[���PK��Zզ�Y��HL�0Symfony/Component/Form/Extension/Templating/TemplatingRendererEngine.phpnu�[���PK��Z䋧��U��0Symfony/Component/Form/Extension/HttpFoundation/EventListener/BindRequestListener.phpnu�[���PK��Z�j��=
=
PԦ0Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationRequestHandler.phpnu�[���PK��Z��Q��K��0Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationExtension.phpnu�[���PK��Z�PffX��0Symfony/Component/Form/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.phpnu�[���PK��Z"�q���7��0Symfony/Component/Form/Extension/Csrf/CsrfExtension.phpnu�[���PK��Z�C���J��0Symfony/Component/Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.phpnu�[���PK��Z[^����J��0Symfony/Component/Form/Extension/Csrf/CsrfProvider/SessionCsrfProvider.phpnu�[���PK��Z%�G���L�0Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderInterface.phpnu�[���PK��Z�����JI�0Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderAdapter.phpnu�[���PK��ZR�'WTTN��0Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfTokenManagerAdapter.phpnu�[���PK��Z�?�ooNy�0Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.phpnu�[���PK��Z��
f��Df�0Symfony/Component/Form/Extension/Csrf/Type/FormTypeCsrfExtension.phpnu�[���PK��ZC�W���7�
1Symfony/Component/Form/Extension/Core/CoreExtension.phpnu�[���PK��Z�:AAD�1Symfony/Component/Form/Extension/Core/EventListener/TrimListener.phpnu�[���PK��Zõe��O�1Symfony/Component/Form/Extension/Core/EventListener/MergeCollectionListener.phpnu�[���PK��Z>Q?��N�+1Symfony/Component/Form/Extension/Core/EventListener/FixUrlProtocolListener.phpnu�[���PK��Zb����P�11Symfony/Component/Form/Extension/Core/EventListener/FixCheckboxInputListener.phpnu�[���PK��Z\��//J�=1Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.phpnu�[���PK��Z?D���M�Q1Symfony/Component/Form/Extension/Core/EventListener/FixRadioInputListener.phpnu�[���PK��Z�jю��E�Z1Symfony/Component/Form/Extension/Core/ChoiceList/SimpleChoiceList.phpnu�[���PK��Z�
�##E�p1Symfony/Component/Form/Extension/Core/ChoiceList/ObjectChoiceList.phpnu�[���PK��Zl_R(H��1Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceListInterface.phpnu�[���PK��Z�В4
4
C�1Symfony/Component/Form/Extension/Core/ChoiceList/LazyChoiceList.phpnu�[���PK��Z'���??��1Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceList.phpnu�[���PK��Z��&PP9��1Symfony/Component/Form/Extension/Core/View/ChoiceView.phpnu�[���PK��Z��

Gl�1Symfony/Component/Form/Extension/Core/DataMapper/PropertyPathMapper.phpnu�[���PK��ZO�#�#�#\�2Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.phpnu�[���PK��Z)b�""^)2Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.phpnu�[���PK��Ze�^�		V�?2Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.phpnu�[���PK��Z���Þ
�
XVI2Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.phpnu�[���PK��Zc�8V�	�	N|T2Symfony/Component/Form/Extension/Core/DataTransformer/DataTransformerChain.phpnu�[���PK��Z�;�dd]�^2Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.phpnu�[���PK��Z�Z�eTwo2Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToArrayTransformer.phpnu�[���PK��ZL�px&&Y�2Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.phpnu�[���PK��Z����		V��2Symfony/Component/Form/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.phpnu�[���PK��Z'tqk55ZJ�2Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.phpnu�[���PK��Z���ggT	�2Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToValuesTransformer.phpnu�[���PK��ZUd�q]�2Symfony/Component/Form/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.phpnu�[���PK��ZΎgW� � U��2Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToStringTransformer.phpnu�[���PK��Z�"h���R��2Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToValueTransformer.phpnu�[���PK��Z�H��		Q��2Symfony/Component/Form/Extension/Core/DataTransformer/ArrayToPartsTransformer.phpnu�[���PK��Z/C���QO�2Symfony/Component/Form/Extension/Core/DataTransformer/BaseDateTimeTransformer.phpnu�[���PK��Z���T��T��2Symfony/Component/Form/Extension/Core/DataTransformer/BooleanToStringTransformer.phpnu�[���PK��Z]��yD	D	[/3Symfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.phpnu�[���PK��Z���/�+�+9�
3Symfony/Component/Form/Extension/Core/Type/ChoiceType.phpnu�[���PK��Z��h��9:3Symfony/Component/Form/Extension/Core/Type/ButtonType.phpnu�[���PK��ZD�U��9s>3Symfony/Component/Form/Extension/Core/Type/SubmitType.phpnu�[���PK��Z񍢸��;�B3Symfony/Component/Form/Extension/Core/Type/CurrencyType.phpnu�[���PK��Z�Ѝ'��9�F3Symfony/Component/Form/Extension/Core/Type/HiddenType.phpnu�[���PK��Z���D��9�J3Symfony/Component/Form/Extension/Core/Type/LocaleType.phpnu�[���PK��ZuƵ�``:O3Symfony/Component/Form/Extension/Core/Type/IntegerType.phpnu�[���PK��Za����8�W3Symfony/Component/Form/Extension/Core/Type/ResetType.phpnu�[���PK��Z옇���;'[3Symfony/Component/Form/Extension/Core/Type/PasswordType.phpnu�[���PK��Zٝ��GG7]`3Symfony/Component/Form/Extension/Core/Type/BaseType.phpnu�[���PK��ZZ���^^:r3Symfony/Component/Form/Extension/Core/Type/PercentType.phpnu�[���PK��Z��TT;�w3Symfony/Component/Form/Extension/Core/Type/CheckboxType.phpnu�[���PK��Z&ߏ�vv;��3Symfony/Component/Form/Extension/Core/Type/BirthdayType.phpnu�[���PK��Z7pO�LL8s�3Symfony/Component/Form/Extension/Core/Type/RadioType.phpnu�[���PK��Z�G�oo7'�3Symfony/Component/Form/Extension/Core/Type/FileType.phpnu�[���PK��Z�8��JJ9��3Symfony/Component/Form/Extension/Core/Type/SearchType.phpnu�[���PK��Z�_��LL;��3Symfony/Component/Form/Extension/Core/Type/TimezoneType.phpnu�[���PK��Z���HH8g�3Symfony/Component/Form/Extension/Core/Type/EmailType.phpnu�[���PK��Z[Gԃ��=�3Symfony/Component/Form/Extension/Core/Type/CollectionType.phpnu�[���PK��Z�t�II;1�3Symfony/Component/Form/Extension/Core/Type/TextareaType.phpnu�[���PK��Z����;�3Symfony/Component/Form/Extension/Core/Type/LanguageType.phpnu�[���PK��ZT;���7��3Symfony/Component/Form/Extension/Core/Type/TextType.phpnu�[���PK��ZH?!a��7J�3Symfony/Component/Form/Extension/Core/Type/TimeType.phpnu�[���PK��Z�� &�'�';��3Symfony/Component/Form/Extension/Core/Type/DateTimeType.phpnu�[���PK��Z�q���6��3Symfony/Component/Form/Extension/Core/Type/UrlType.phpnu�[���PK��Z9�;�3Symfony/Component/Form/Extension/Core/Type/RepeatedType.phpnu�[���PK��ZM2\3,3,7E4Symfony/Component/Form/Extension/Core/Type/DateType.phpnu�[���PK��Za�LŢ�:�34Symfony/Component/Form/Extension/Core/Type/CountryType.phpnu�[���PK��ZC�i���9�74Symfony/Component/Form/Extension/Core/Type/NumberType.phpnu�[���PK��Z:�y�

7;@4Symfony/Component/Form/Extension/Core/Type/FormType.phpnu�[���PK��Z5�S
��8�\4Symfony/Component/Form/Extension/Core/Type/MoneyType.phpnu�[���PK��Z6s���D�i4Symfony/Component/Form/Extension/DataCollector/FormDataCollector.phpnu�[���PK��ZI��2

Vȇ4Symfony/Component/Form/Extension/DataCollector/EventListener/DataCollectorListener.phpnu�[���PK��Z�T���Mc�4Symfony/Component/Form/Extension/DataCollector/FormDataCollectorInterface.phpnu�[���PK��Z����M��4Symfony/Component/Form/Extension/DataCollector/FormDataExtractorInterface.phpnu�[���PK��Z|�
]��W�4Symfony/Component/Form/Extension/DataCollector/Proxy/ResolvedTypeDataCollectorProxy.phpnu�[���PK��Z�((^6�4Symfony/Component/Form/Extension/DataCollector/Proxy/ResolvedTypeFactoryDataCollectorProxy.phpnu�[���PK��Z��#�11I�4Symfony/Component/Form/Extension/DataCollector/DataCollectorExtension.phpnu�[���PK��Z%�`��D��4Symfony/Component/Form/Extension/DataCollector/FormDataExtractor.phpnu�[���PK��Z�1�
uuR��4Symfony/Component/Form/Extension/DataCollector/Type/DataCollectorTypeExtension.phpnu�[���PK��ZuUS�WWU��4Symfony/Component/Form/Extension/DependencyInjection/DependencyInjectionExtension.phpnu�[���PK��Z(s
//-a�4Symfony/Component/Form/ClickableInterface.phpnu�[���PK��ZH��
�
#��4Symfony/Component/Form/FormView.phpnu�[���PK��Z
�͋ �4Symfony/Component/Form/Forms.phpnu�[���PK��Z\�F1_
5Symfony/Component/Security/Acl/Voter/AclVoter.phpnu�[���PK��Z\!�	HH2�#5Symfony/Component/Security/Acl/Voter/FieldVote.phpnu�[���PK��ZP͡��Am'5Symfony/Component/Security/Acl/Exception/AclNotFoundException.phpnu�[���PK��Z�k�q��6�)5Symfony/Component/Security/Acl/Exception/Exception.phpnu�[���PK��Z�W�L�+5Symfony/Component/Security/Acl/Exception/ConcurrentModificationException.phpnu�[���PK��Z���OI}.5Symfony/Component/Security/Acl/Exception/InvalidDomainObjectException.phpnu�[���PK��Z]��_""E15Symfony/Component/Security/Acl/Exception/NotAllAclsFoundException.phpnu�[���PK��Z�B�l��@�55Symfony/Component/Security/Acl/Exception/NoAceFoundException.phpnu�[���PK��Z[�z�B�85Symfony/Component/Security/Acl/Exception/SidNotLoadedException.phpnu�[���PK��Z��5�

F;5Symfony/Component/Security/Acl/Exception/AclAlreadyExistsException.phpnu�[���PK��Zt��:�=5Symfony/Component/Security/Acl/Dbal/MutableAclProvider.phpnu�[���PK��Z�^�+f+f3��5Symfony/Component/Security/Acl/Dbal/AclProvider.phpnu�[���PK��ZK� V��.n,6Symfony/Component/Security/Acl/Dbal/Schema.phpnu�[���PK��ZNTA�]]5�D6Symfony/Component/Security/Acl/Domain/AuditLogger.phpnu�[���PK��Z�.��**>sJ6Symfony/Component/Security/Acl/Domain/UserSecurityIdentity.phpnu�[���PK��Z��C3��:W6Symfony/Component/Security/Acl/Domain/DoctrineAclCache.phpnu�[���PK��Z(]���D#p6Symfony/Component/Security/Acl/Domain/PermissionGrantingStrategy.phpnu�[���PK��Z%�}`M`M-k�6Symfony/Component/Security/Acl/Domain/Acl.phpnu�[���PK��Z����K(�6Symfony/Component/Security/Acl/Domain/SecurityIdentityRetrievalStrategy.phpnu�[���PK��Z�X�
/	/	<K�6Symfony/Component/Security/Acl/Domain/AclCollectionCache.phpnu�[���PK��Z5D�[/��6Symfony/Component/Security/Acl/Domain/Entry.phpnu�[���PK��Z�pU���4H7Symfony/Component/Security/Acl/Domain/FieldEntry.phpnu�[���PK��Z^@�.YY8R7Symfony/Component/Security/Acl/Domain/ObjectIdentity.phpnu�[���PK��Z0F���I7Symfony/Component/Security/Acl/Domain/ObjectIdentityRetrievalStrategy.phpnu�[���PK��ZtA)�==>J7Symfony/Component/Security/Acl/Domain/RoleSecurityIdentity.phpnu�[���PK��Z�#��~~<�#7Symfony/Component/Security/Acl/Resources/bin/generateSql.phpnu�[���PK��Zj~	cFF7�+7Symfony/Component/Security/Acl/Resources/schema/db2.sqlnu�[���PK��ZT��skk>�87Symfony/Component/Security/Acl/Resources/schema/postgresql.sqlnu�[���PK��ZJx�.

9eE7Symfony/Component/Security/Acl/Resources/schema/mssql.sqlnu�[���PK��ZfZ��^^9�R7Symfony/Component/Security/Acl/Resources/schema/mysql.sqlnu�[���PK��Z��c�
�
;�^7Symfony/Component/Security/Acl/Resources/schema/drizzle.sqlnu�[���PK��Z�C� ;;:�i7Symfony/Component/Security/Acl/Resources/schema/oracle.sqlnu�[���PK��Z��d��:I�7Symfony/Component/Security/Acl/Resources/schema/sqlite.sqlnu�[���PK��Zw���D��7Symfony/Component/Security/Acl/Permission/PermissionMapInterface.phpnu�[���PK��Z�ep�gg9��7Symfony/Component/Security/Acl/Permission/MaskBuilder.phpnu�[���PK��Z� c0��@ͫ7Symfony/Component/Security/Acl/Permission/BasicPermissionMap.phpnu�[���PK��Z6����<��7Symfony/Component/Security/Acl/Model/MutableAclInterface.phpnu�[���PK��Z[Ob3SK�7Symfony/Component/Security/Acl/Model/SecurityIdentityRetrievalStrategyInterface.phpnu�[���PK��ZX	��>��7Symfony/Component/Security/Acl/Model/DomainObjectInterface.phpnu�[���PK��Z�5Ayy@
�7Symfony/Component/Security/Acl/Model/ObjectIdentityInterface.phpnu�[���PK��Zt��@��7Symfony/Component/Security/Acl/Model/AuditableEntryInterface.phpnu�[���PK��Z-癥��Lk�7Symfony/Component/Security/Acl/Model/PermissionGrantingStrategyInterface.phpnu�[���PK��Z�����=��7Symfony/Component/Security/Acl/Model/AclProviderInterface.phpnu�[���PK��Z�#���:&�7Symfony/Component/Security/Acl/Model/AclCacheInterface.phpnu�[���PK��Zӗ&1>��7Symfony/Component/Security/Acl/Model/AuditableAclInterface.phpnu�[���PK��Z�ݤUU<�7Symfony/Component/Security/Acl/Model/FieldEntryInterface.phpnu�[���PK��Z�
�8FF7�7Symfony/Component/Security/Acl/Model/EntryInterface.phpnu�[���PK��ZH<J��=��7Symfony/Component/Security/Acl/Model/AuditLoggerInterface.phpnu�[���PK��Z���77B�8Symfony/Component/Security/Acl/Model/SecurityIdentityInterface.phpnu�[���PK��Z�𕛼�5L8Symfony/Component/Security/Acl/Model/AclInterface.phpnu�[���PK��Z�W}��Qm8Symfony/Component/Security/Acl/Model/ObjectIdentityRetrievalStrategyInterface.phpnu�[���PK��Zj���D�8Symfony/Component/Security/Acl/Model/MutableAclProviderInterface.phpnu�[���PK��Z��W"RR)�8Symfony/Component/Security/autoloader.phpnu�[���PK��Z�DXVV,t8Symfony/Component/Security/Http/Firewall.phpnu�[���PK��Z"�C��/&'8Symfony/Component/Security/Http/FirewallMap.phpnu�[���PK��Z�יK--8Symfony/Component/Security/Http/EntryPoint/FormAuthenticationEntryPoint.phpnu�[���PK��Z�<ݐppL�58Symfony/Component/Security/Http/EntryPoint/BasicAuthenticationEntryPoint.phpnu�[���PK��Z)'_++P�:8Symfony/Component/Security/Http/EntryPoint/AuthenticationEntryPointInterface.phpnu�[���PK��ZtZ�)K	K	MN?8Symfony/Component/Security/Http/EntryPoint/DigestAuthenticationEntryPoint.phpnu�[���PK��Z�����LI8Symfony/Component/Security/Http/EntryPoint/RetryAuthenticationEntryPoint.phpnu�[���PK��Z��`C��-,P8Symfony/Component/Security/Http/HttpUtils.phpnu�[���PK��Z^�V��N^h8Symfony/Component/Security/Http/Authorization/AccessDeniedHandlerInterface.phpnu�[���PK��Z��̗��W�l8Symfony/Component/Security/Http/Firewall/UsernamePasswordFormAuthenticationListener.phpnu�[���PK��Znz+S�
�
?8Symfony/Component/Security/Http/Firewall/RememberMeListener.phpnu�[���PK��Zlٯ��L6�8Symfony/Component/Security/Http/Firewall/AnonymousAuthenticationListener.phpnu�[���PK��Z�����>��8Symfony/Component/Security/Http/Firewall/ListenerInterface.phpnu�[���PK��Z�|L@**;��8Symfony/Component/Security/Http/Firewall/LogoutListener.phpnu�[���PK��Z�Bb

?J�8Symfony/Component/Security/Http/Firewall/SwitchUserListener.phpnu�[���PK��Z(�T	b!b!>��8Symfony/Component/Security/Http/Firewall/ExceptionListener.phpnu�[���PK��Z׺�=��G��8Symfony/Component/Security/Http/Firewall/X509AuthenticationListener.phpnu�[���PK��Z׿ͼ� � I��8Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.phpnu�[���PK��Z~�k��<19Symfony/Component/Security/Http/Firewall/ChannelListener.phpnu�[���PK��Z��6'6'K�9Symfony/Component/Security/Http/Firewall/AbstractAuthenticationListener.phpnu�[���PK��Z�"?���<?A9Symfony/Component/Security/Http/Firewall/ContextListener.phpnu�[���PK��Z�����MSY9Symfony/Component/Security/Http/Firewall/SimpleFormAuthenticationListener.phpnu�[���PK��Z+/��Z	Z	;�q9Symfony/Component/Security/Http/Firewall/AccessListener.phpnu�[���PK��Z�Z���Mg{9Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.phpnu�[���PK��Zn��L��9Symfony/Component/Security/Http/Firewall/SimplePreAuthenticationListener.phpnu�[���PK��Z�&!�
�
H+�9Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.phpnu�[���PK��Z2j���-$�9Symfony/Component/Security/Http/AccessMap.phpnu�[���PK��Z/�``6x�9Symfony/Component/Security/Http/AccessMapInterface.phpnu�[���PK��Z��\\��8>�9Symfony/Component/Security/Http/FirewallMapInterface.phpnu�[���PK��Z	z��J��9Symfony/Component/Security/Http/RememberMe/RememberMeServicesInterface.phpnu�[���PK��ZP�ڕ��?��9Symfony/Component/Security/Http/RememberMe/ResponseListener.phpnu�[���PK��Z���s44U�9Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.phpnu�[���PK��Z�*�b�&�&I��9Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.phpnu�[���PK��Z�a�$��K!
:Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.phpnu�[���PK��Z:�&�GGR!:Symfony/Component/Security/Http/Session/SessionAuthenticationStrategyInterface.phpnu�[���PK��Z��La[[I�":Symfony/Component/Security/Http/Session/SessionAuthenticationStrategy.phpnu�[���PK��Za7�llF�):Symfony/Component/Security/Http/Logout/DefaultLogoutSuccessHandler.phpnu�[���PK��Z1��d��H�.:Symfony/Component/Security/Http/Logout/LogoutSuccessHandlerInterface.phpnu�[���PK��Z\ü���?�2:Symfony/Component/Security/Http/Logout/SessionLogoutHandler.phpnu�[���PK��Z6O����A07:Symfony/Component/Security/Http/Logout/LogoutHandlerInterface.phpnu�[���PK��Z�ddF�;:Symfony/Component/Security/Http/Logout/CookieClearingLogoutHandler.phpnu�[���PK��Z/ sG��2xA:Symfony/Component/Security/Http/SecurityEvents.phpnu�[���PK��Z�NA��X�E:Symfony/Component/Security/Http/Authentication/AuthenticationSuccessHandlerInterface.phpnu�[���PK��Z������V/K:Symfony/Component/Security/Http/Authentication/DefaultAuthenticationFailureHandler.phpnu�[���PK��Z��H]X�X:Symfony/Component/Security/Http/Authentication/AuthenticationFailureHandlerInterface.phpnu�[���PK��Z�xGAAV^:Symfony/Component/Security/Http/Authentication/DefaultAuthenticationSuccessHandler.phpnu�[���PK��ZAH\ݞ�N�j:Symfony/Component/Security/Http/Authentication/SimpleAuthenticationHandler.phpnu�[���PK��Z�D����9|:Symfony/Component/Security/Http/Event/SwitchUserEvent.phpnu�[���PK��ZZ�v}?^�:Symfony/Component/Security/Http/Event/InteractiveLoginEvent.phpnu�[���PK��Z��VǴ�=L�:Symfony/Component/Security/Csrf/CsrfTokenManagerInterface.phpnu�[���PK��Z&%�L
L
4m�:Symfony/Component/Security/Csrf/CsrfTokenManager.phpnu�[���PK��Z�����
�
J�:Symfony/Component/Security/Csrf/TokenStorage/NativeSessionTokenStorage.phpnu�[���PK��Z�����Fn�:Symfony/Component/Security/Csrf/TokenStorage/TokenStorageInterface.phpnu�[���PK��Z��]N
N
Dq�:Symfony/Component/Security/Csrf/TokenStorage/SessionTokenStorage.phpnu�[���PK��ZeI����D3�:Symfony/Component/Security/Csrf/Exception/TokenNotFoundException.phpnu�[���PK��Z��=H��:Symfony/Component/Security/Csrf/TokenGenerator/UriSafeTokenGenerator.phpnu�[���PK��ZJ,p���J�:Symfony/Component/Security/Csrf/TokenGenerator/TokenGeneratorInterface.phpnu�[���PK��Z���O-3�:Symfony/Component/Security/Csrf/CsrfToken.phpnu�[���PK��Z��S��<��:Symfony/Component/Security/Core/SecurityContextInterface.phpnu�[���PK��Z�}�ww?��:Symfony/Component/Security/Core/Role/RoleHierarchyInterface.phpnu�[���PK��Z� �w??6m�:Symfony/Component/Security/Core/Role/RoleHierarchy.phpnu�[���PK��Z�Ħ-�:Symfony/Component/Security/Core/Role/Role.phpnu�[���PK��ZX�S�007t�:Symfony/Component/Security/Core/Role/SwitchUserRole.phpnu�[���PK��Z�'c��6�:Symfony/Component/Security/Core/Role/RoleInterface.phpnu�[���PK��ZE� �D�:Symfony/Component/Security/Core/Encoder/PasswordEncoderInterface.phpnu�[���PK��ZÆ��	�	A��:Symfony/Component/Security/Core/Encoder/BCryptPasswordEncoder.phpnu�[���PK��Z��^��H�:Symfony/Component/Security/Core/Encoder/MessageDigestPasswordEncoder.phpnu�[���PK��Z,>"�D�:Symfony/Component/Security/Core/Encoder/PlaintextPasswordEncoder.phpnu�[���PK��Z�;D��:b;Symfony/Component/Security/Core/Encoder/EncoderFactory.phpnu�[���PK��Z!�@

A�
;Symfony/Component/Security/Core/Encoder/Pbkdf2PasswordEncoder.phpnu�[���PK��Z#�MMqqCx;Symfony/Component/Security/Core/Encoder/EncoderFactoryInterface.phpnu�[���PK��Z�7���
�
?\;Symfony/Component/Security/Core/Encoder/BasePasswordEncoder.phpnu�[���PK��Z��
�77O�*;Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.phpnu�[���PK��Z��i��Fi1;Symfony/Component/Security/Core/Validator/Constraints/UserPassword.phpnu�[���PK��Z����Es4;Symfony/Component/Security/Core/Exception/BadCredentialsException.phpnu�[���PK��Z���zz=}7;Symfony/Component/Security/Core/Exception/LockedException.phpnu�[���PK��Zb��M<<Fd:;Symfony/Component/Security/Core/Exception/UnsupportedUserException.phpnu�[���PK��Z�z�&��I=;Symfony/Component/Security/Core/Exception/CredentialsExpiredException.phpnu�[���PK��Z��Xss=9@;Symfony/Component/Security/Core/Exception/LogoutException.phpnu�[���PK��Z
�04}}GC;Symfony/Component/Security/Core/Exception/UsernameNotFoundException.phpnu�[���PK��Z#��q44Q
I;Symfony/Component/Security/Core/Exception/InsufficientAuthenticationException.phpnu�[���PK��Z�5]���I�L;Symfony/Component/Security/Core/Exception/SessionUnavailableException.phpnu�[���PK��ZD��9��D�P;Symfony/Component/Security/Core/Exception/TokenNotFoundException.phpnu�[���PK��Zh�c��B�S;Symfony/Component/Security/Core/Exception/CookieTheftException.phpnu�[���PK��Z��A���@/W;Symfony/Component/Security/Core/Exception/ExceptionInterface.phpnu�[���PK��ZqUSą�CYY;Symfony/Component/Security/Core/Exception/AccessDeniedException.phpnu�[���PK��Z�'��EQ\;Symfony/Component/Security/Core/Exception/AuthenticationException.phpnu�[���PK��Z�
	��>�c;Symfony/Component/Security/Core/Exception/RuntimeException.phpnu�[���PK��Z@�	���G0f;Symfony/Component/Security/Core/Exception/ProviderNotFoundException.phpnu�[���PK��Z�ĸ���X�i;Symfony/Component/Security/Core/Exception/AuthenticationCredentialsNotFoundException.phpnu�[���PK��Z:���AADm;Symfony/Component/Security/Core/Exception/AccountStatusException.phpnu�[���PK��Z7w�-��L�r;Symfony/Component/Security/Core/Exception/AuthenticationServiceException.phpnu�[���PK��ZxB��EIv;Symfony/Component/Security/Core/Exception/AccountExpiredException.phpnu�[���PK��Z�և��?Ny;Symfony/Component/Security/Core/Exception/DisabledException.phpnu�[���PK��Ze���CA|;Symfony/Component/Security/Core/Exception/NonceExpiredException.phpnu�[���PK��Zʝ�9Fo;Symfony/Component/Security/Core/Exception/InvalidArgumentException.phpnu�[���PK��Z�O���G�;Symfony/Component/Security/Core/Exception/InvalidCsrfTokenException.phpnu�[���PK��Z�Õ�

5�;Symfony/Component/Security/Core/Util/SecureRandom.phpnu�[���PK��ZU��a��4e�;Symfony/Component/Security/Core/Util/StringUtils.phpnu�[���PK��Z��T�,,3��;Symfony/Component/Security/Core/Util/ClassUtils.phpnu�[���PK��Z�	���>8�;Symfony/Component/Security/Core/Util/SecureRandomInterface.phpnu�[���PK��Z�m2���G1�;Symfony/Component/Security/Core/Authorization/AccessDecisionManager.phpnu�[���PK��Z�З~��Ak�;Symfony/Component/Security/Core/Authorization/Voter/RoleVoter.phpnu�[���PK��Z~f�J��;Symfony/Component/Security/Core/Authorization/Voter/RoleHierarchyVoter.phpnu�[���PK��Z��`c��G]�;Symfony/Component/Security/Core/Authorization/Voter/ExpressionVoter.phpnu�[���PK��Z�X,mJ��;Symfony/Component/Security/Core/Authorization/Voter/AuthenticatedVoter.phpnu�[���PK��Z�>��F*�;Symfony/Component/Security/Core/Authorization/Voter/VoterInterface.phpnu�[���PK��Z�:22PR�;Symfony/Component/Security/Core/Authorization/AccessDecisionManagerInterface.phpnu�[���PK��Zѵ^��D��;Symfony/Component/Security/Core/Authorization/ExpressionLanguage.phpnu�[���PK��Z����=��;Symfony/Component/Security/Core/User/UserCheckerInterface.phpnu�[���PK��Z��^ 
 
:�;Symfony/Component/Security/Core/User/ChainUserProvider.phpnu�[���PK��ZD�$..4r<Symfony/Component/Security/Core/User/UserChecker.phpnu�[���PK��Z��6bYY>
<Symfony/Component/Security/Core/User/AdvancedUserInterface.phpnu�[���PK��Z����	�	6�<Symfony/Component/Security/Core/User/UserInterface.phpnu�[���PK��Z/!�=�"<Symfony/Component/Security/Core/User/InMemoryUserProvider.phpnu�[���PK��Z��//;]/<Symfony/Component/Security/Core/User/EquatableInterface.phpnu�[���PK��Zs�v�W	W	>�3<Symfony/Component/Security/Core/User/UserProviderInterface.phpnu�[���PK��Z��1G	G	-�=<Symfony/Component/Security/Core/User/User.phpnu�[���PK��Z'�za!!3`G<Symfony/Component/Security/Core/SecurityContext.phpnu�[���PK��Z��l�8�R<Symfony/Component/Security/Core/AuthenticationEvents.phpnu�[���PK��Zx��$ccPOW<Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.phpnu�[���PK��Z¬>
##R2f<Symfony/Component/Security/Core/Authentication/SimplePreAuthenticatorInterface.phpnu�[���PK��Z��W��O�h<Symfony/Component/Security/Core/Authentication/SimpleAuthenticatorInterface.phpnu�[���PK��Z>,�vvX%l<Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.phpnu�[���PK��Z�U#s<Symfony/Component/Security/Core/Authentication/Provider/DaoAuthenticationProvider.phpnu�[���PK��Z�b�yyVƂ<Symfony/Component/Security/Core/Authentication/Provider/UserAuthenticationProvider.phpnu�[���PK��Z�J�A��\ŗ<Symfony/Component/Security/Core/Authentication/Provider/RememberMeAuthenticationProvider.phpnu�[���PK��Z��X���[$�<Symfony/Component/Security/Core/Authentication/Provider/AnonymousAuthenticationProvider.phpnu�[���PK��Z��a�""[b�<Symfony/Component/Security/Core/Authentication/Provider/AuthenticationProviderInterface.phpnu�[���PK��Zun\�
�
b�<Symfony/Component/Security/Core/Authentication/Provider/PreAuthenticatedAuthenticationProvider.phpnu�[���PK��Z��r3WWW��<Symfony/Component/Security/Core/Authentication/AuthenticationTrustResolverInterface.phpnu�[���PK��Z�Zvm��St�<Symfony/Component/Security/Core/Authentication/RememberMe/InMemoryTokenProvider.phpnu�[���PK��Z���QZZV��<Symfony/Component/Security/Core/Authentication/RememberMe/PersistentTokenInterface.phpnu�[���PK��Z
�TO��Mx�<Symfony/Component/Security/Core/Authentication/RememberMe/PersistentToken.phpnu�[���PK��Z
C�f��T��<Symfony/Component/Security/Core/Authentication/RememberMe/TokenProviderInterface.phpnu�[���PK��ZJ-W;::S��<Symfony/Component/Security/Core/Authentication/SimpleFormAuthenticatorInterface.phpnu�[���PK��Z:�6��Nv�<Symfony/Component/Security/Core/Authentication/AuthenticationTrustResolver.phpnu�[���PK��Zf�	�Q��<Symfony/Component/Security/Core/Authentication/AuthenticationManagerInterface.phpnu�[���PK��Zγ�__N�<Symfony/Component/Security/Core/Authentication/Token/PreAuthenticatedToken.phpnu�[���PK��Z��4��F��<Symfony/Component/Security/Core/Authentication/Token/AbstractToken.phpnu�[���PK��Z�tC��G)=Symfony/Component/Security/Core/Authentication/Token/TokenInterface.phpnu�[���PK��Z{Z�--G�=Symfony/Component/Security/Core/Authentication/Token/AnonymousToken.phpnu�[���PK��Z�6��`
`
N&=Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.phpnu�[���PK��Z��w�	�	H*=Symfony/Component/Security/Core/Authentication/Token/RememberMeToken.phpnu�[���PK��Zm�|JJK�3=Symfony/Component/Security/Core/Resources/translations/security.sr_Cyrl.xlfnu�[���PK��Z&MЎ�
�
F�C=Symfony/Component/Security/Core/Resources/translations/security.es.xlfnu�[���PK��ZM-�@F�Q=Symfony/Component/Security/Core/Resources/translations/security.fa.xlfnu�[���PK��Zd�e��
�
F�a=Symfony/Component/Security/Core/Resources/translations/security.fr.xlfnu�[���PK��Z�)�
�
F�o=Symfony/Component/Security/Core/Resources/translations/security.ro.xlfnu�[���PK��Z�y��
�
F�}=Symfony/Component/Security/Core/Resources/translations/security.gl.xlfnu�[���PK��Z��u^
^
F�=Symfony/Component/Security/Core/Resources/translations/security.sv.xlfnu�[���PK��Z���ţ
�
F��=Symfony/Component/Security/Core/Resources/translations/security.ca.xlfnu�[���PK��Zo'�N�
�
Fϧ=Symfony/Component/Security/Core/Resources/translations/security.de.xlfnu�[���PK��Z.W�
�
F
�=Symfony/Component/Security/Core/Resources/translations/security.no.xlfnu�[���PK��Z��ق
�
F�=Symfony/Component/Security/Core/Resources/translations/security.sk.xlfnu�[���PK��Z�w=���F�=Symfony/Component/Security/Core/Resources/translations/security.ru.xlfnu�[���PK��ZUɎd
d
F3�=Symfony/Component/Security/Core/Resources/translations/security.sl.xlfnu�[���PK��Z���
�
F
�=Symfony/Component/Security/Core/Resources/translations/security.lb.xlfnu�[���PK��Z�#@�y
y
IW�=Symfony/Component/Security/Core/Resources/translations/security.pt_PT.xlfnu�[���PK��ZYW��g
g
KI>Symfony/Component/Security/Core/Resources/translations/security.sr_Latn.xlfnu�[���PK��Z�=���
�
I+>Symfony/Component/Security/Core/Resources/translations/security.pt_BR.xlfnu�[���PK��Z(���
�
F&(>Symfony/Component/Security/Core/Resources/translations/security.cs.xlfnu�[���PK��ZO�
�
F'6>Symfony/Component/Security/Core/Resources/translations/security.it.xlfnu�[���PK��ZTk�f��F+D>Symfony/Component/Security/Core/Resources/translations/security.ar.xlfnu�[���PK��Z��|H�
�
F[S>Symfony/Component/Security/Core/Resources/translations/security.hu.xlfnu�[���PK��Z�p�U�
�
Fa>Symfony/Component/Security/Core/Resources/translations/security.nl.xlfnu�[���PK��Z'���{
{
F�o>Symfony/Component/Security/Core/Resources/translations/security.tr.xlfnu�[���PK��ZU����F�}>Symfony/Component/Security/Core/Resources/translations/security.el.xlfnu�[���PK��Z.�X:
:
F�>Symfony/Component/Security/Core/Resources/translations/security.en.xlfnu�[���PK��Z�d
�
�
F��>Symfony/Component/Security/Core/Resources/translations/security.pl.xlfnu�[���PK��Z5�˙��F��>Symfony/Component/Security/Core/Resources/translations/security.ua.xlfnu�[���PK��Zz��
J
J
F��>Symfony/Component/Security/Core/Resources/translations/security.da.xlfnu�[���PK��Z��Eh��Dj�>Symfony/Component/Security/Core/Event/AuthenticationFailureEvent.phpnu�[���PK��Z+\�
//=��>Symfony/Component/Security/Core/Event/AuthenticationEvent.phpnu�[���PK��Z���(SSA,�>Symfony/Component/Security/Resources/translations/security.bg.xlfnu�[���PK��Zm�|JJF��>Symfony/Component/Security/Resources/translations/security.sr_Cyrl.xlfnu�[���PK��Z&MЎ�
�
A��>Symfony/Component/Security/Resources/translations/security.es.xlfnu�[���PK��ZM-�@A�>Symfony/Component/Security/Resources/translations/security.fa.xlfnu�[���PK��Z���An?Symfony/Component/Security/Resources/translations/security.vi.xlfnu�[���PK��Zd�e��
�
A�?Symfony/Component/Security/Resources/translations/security.fr.xlfnu�[���PK��Z�)�
�
A.)?Symfony/Component/Security/Resources/translations/security.ro.xlfnu�[���PK��Z�y��
�
A,7?Symfony/Component/Security/Resources/translations/security.gl.xlfnu�[���PK��Z��u^
^
A<E?Symfony/Component/Security/Resources/translations/security.sv.xlfnu�[���PK��Z���ţ
�
AS?Symfony/Component/Security/Resources/translations/security.ca.xlfnu�[���PK��Zo'�N�
�
Aa?Symfony/Component/Security/Resources/translations/security.de.xlfnu�[���PK��Z����
�
AXo?Symfony/Component/Security/Resources/translations/security.no.xlfnu�[���PK��Z�R�wD
D
AN}?Symfony/Component/Security/Resources/translations/security.id.xlfnu�[���PK��Z��ق
�
A�?Symfony/Component/Security/Resources/translations/security.sk.xlfnu�[���PK��Z�w=���A��?Symfony/Component/Security/Resources/translations/security.ru.xlfnu�[���PK��ZUɎd
d
A$�?Symfony/Component/Security/Resources/translations/security.sl.xlfnu�[���PK��Z]��W
W
A��?Symfony/Component/Security/Resources/translations/security.hr.xlfnu�[���PK��Z���
�
A��?Symfony/Component/Security/Resources/translations/security.lb.xlfnu�[���PK��Z�#@�y
y
D�?Symfony/Component/Security/Resources/translations/security.pt_PT.xlfnu�[���PK��ZYW��g
g
F��?Symfony/Component/Security/Resources/translations/security.sr_Latn.xlfnu�[���PK��Z���Y�
�
D��?Symfony/Component/Security/Resources/translations/security.pt_BR.xlfnu�[���PK��Z(���
�
A�?Symfony/Component/Security/Resources/translations/security.cs.xlfnu�[���PK��ZO�
�
A�
@Symfony/Component/Security/Resources/translations/security.it.xlfnu�[���PK��ZTk�f��A�@Symfony/Component/Security/Resources/translations/security.ar.xlfnu�[���PK��Z��|H�
�
A�'@Symfony/Component/Security/Resources/translations/security.hu.xlfnu�[���PK��Z�p�U�
�
A6@Symfony/Component/Security/Resources/translations/security.nl.xlfnu�[���PK��Z'���{
{
AID@Symfony/Component/Security/Resources/translations/security.tr.xlfnu�[���PK��ZU����A5R@Symfony/Component/Security/Resources/translations/security.el.xlfnu�[���PK��Z��Dt��D�b@Symfony/Component/Security/Resources/translations/security.zh_CN.xlfnu�[���PK��Z.�X:
:
A�o@Symfony/Component/Security/Resources/translations/security.en.xlfnu�[���PK��Z�d
�
�
A�}@Symfony/Component/Security/Resources/translations/security.pl.xlfnu�[���PK��Z�f488A��@Symfony/Component/Security/Resources/translations/security.ja.xlfnu�[���PK��Z5�˙��AC�@Symfony/Component/Security/Resources/translations/security.ua.xlfnu�[���PK��Z��J
J
A7�@Symfony/Component/Security/Resources/translations/security.da.xlfnu�[���PK��Z�@V��@�@Symfony/Component/Validator/ConstraintViolationListInterface.phpnu�[���PK��Zz��911::�@Symfony/Component/Validator/ObjectInitializerInterface.phpnu�[���PK��Z,�'��<��@Symfony/Component/Validator/ConstraintValidatorInterface.phpnu�[���PK��ZK��}}1��@Symfony/Component/Validator/DefaultTranslator.phpnu�[���PK��Z�����3��@Symfony/Component/Validator/ConstraintViolation.phpnu�[���PK��ZS�b'b'0��@Symfony/Component/Validator/ValidatorBuilder.phpnu�[���PK��Z�S�UU>�ASymfony/Component/Validator/GroupSequenceProviderInterface.phpnu�[���PK��Z�d�)xASymfony/Component/Validator/Validator.phpnu�[���PK��Z��&{{9�2ASymfony/Component/Validator/ValidatorBuilderInterface.phpnu�[���PK��Zo��SS*�HASymfony/Component/Validator/autoloader.phpnu�[���PK��Z����C0C09{JASymfony/Component/Validator/ExecutionContextInterface.phpnu�[���PK��Z}`���9'{ASymfony/Component/Validator/PropertyMetadataInterface.phpnu�[���PK��Z�޽/!/!0z�ASymfony/Component/Validator/ExecutionContext.phpnu�[���PK��Z+s���:	�ASymfony/Component/Validator/ConstraintValidatorFactory.phpnu�[���PK��Z�Sq�KK1l�ASymfony/Component/Validator/MetadataInterface.phpnu�[���PK��Z�R'<�ASymfony/Component/Validator/ConstraintViolationInterface.phpnu�[���PK��ZƭW��*��ASymfony/Component/Validator/Constraint.phpnu�[���PK��Z|����6l�ASymfony/Component/Validator/Mapping/GetterMetadata.phpnu�[���PK��Zr
���8��ASymfony/Component/Validator/Mapping/PropertyMetadata.phpnu�[���PK��Z�t�././5��ASymfony/Component/Validator/Mapping/ClassMetadata.phpnu�[���PK��Z��!"	"	7wBSymfony/Component/Validator/Mapping/ElementMetadata.phpnu�[���PK��Z�/�;aa6)BSymfony/Component/Validator/Mapping/MemberMetadata.phpnu�[���PK��Z+�d%%<�@BSymfony/Component/Validator/Mapping/Cache/CacheInterface.phpnu�[���PK��Z����6XEBSymfony/Component/Validator/Mapping/Cache/ApcCache.phpnu�[���PK��Zd#[N��<IJBSymfony/Component/Validator/Mapping/ClassMetadataFactory.phpnu�[���PK��Z��ʚ��9�WBSymfony/Component/Validator/Mapping/Loader/FileLoader.phpnu�[���PK��Zk�G+��=�[BSymfony/Component/Validator/Mapping/Loader/AbstractLoader.phpnu�[���PK��ZRᠯ��=dBSymfony/Component/Validator/Mapping/Loader/XmlFilesLoader.phpnu�[���PK��Z�?��>gBSymfony/Component/Validator/Mapping/Loader/YamlFilesLoader.phpnu�[���PK��Z�����:jBSymfony/Component/Validator/Mapping/Loader/LoaderChain.phpnu�[���PK��ZT�b��AAqBSymfony/Component/Validator/Mapping/Loader/StaticMethodLoader.phpnu�[���PK��Z�>�??>�wBSymfony/Component/Validator/Mapping/Loader/LoaderInterface.phpnu�[���PK��Z���*��:8zBSymfony/Component/Validator/Mapping/Loader/FilesLoader.phpnu�[���PK��ZTO��--c)�BSymfony/Component/Validator/Mapping/Loader/schema/dic/constraint-mapping/constraint-mapping-1.0.xsdnu�[���PK��Z;Q�F11<�BSymfony/Component/Validator/Mapping/Loader/XmlFileLoader.phpnu�[���PK��Z	lw#QQ?��BSymfony/Component/Validator/Mapping/Loader/AnnotationLoader.phpnu�[���PK��Z'��pkk=F�BSymfony/Component/Validator/Mapping/Loader/YamlFileLoader.phpnu�[���PK��Z�۔��@�BSymfony/Component/Validator/Mapping/BlackholeMetadataFactory.phpnu�[���PK��Z�L8��
�
:$�BSymfony/Component/Validator/ValidationVisitorInterface.phpnu�[���PK��ZQ���VV:j�BSymfony/Component/Validator/Exception/MappingException.phpnu�[���PK��Z��y��@*�BSymfony/Component/Validator/Exception/BadMethodCallException.phpnu�[���PK��ZL�ЉRRA��BSymfony/Component/Validator/Exception/InvalidOptionsException.phpnu�[���PK��Zk1+WW<V�BSymfony/Component/Validator/Exception/ValidatorException.phpnu�[���PK��Z�b�<<A�BSymfony/Component/Validator/Exception/UnexpectedTypeException.phpnu�[���PK��Z�1�"ccG��BSymfony/Component/Validator/Exception/ConstraintDefinitionException.phpnu�[���PK��Z�T����<��BSymfony/Component/Validator/Exception/ExceptionInterface.phpnu�[���PK��Zz����:��BSymfony/Component/Validator/Exception/RuntimeException.phpnu�[���PK��Z��x��A�BSymfony/Component/Validator/Exception/NoSuchMetadataException.phpnu�[���PK��Zu��RRA�BSymfony/Component/Validator/Exception/MissingOptionsException.phpnu�[���PK��ZM��#^^B�BSymfony/Component/Validator/Exception/GroupDefinitionException.phpnu�[���PK��Z�\��B��BSymfony/Component/Validator/Exception/InvalidArgumentException.phpnu�[���PK��Z�U�<<3!�BSymfony/Component/Validator/ClassBasedInterface.phpnu�[���PK��Z;5t��7��BSymfony/Component/Validator/ConstraintViolationList.phpnu�[���PK��ZAbI̲�1�CSymfony/Component/Validator/ValidationVisitor.phpnu�[���PK��Zbh��B�$CSymfony/Component/Validator/PropertyMetadataContainerInterface.phpnu�[���PK��ZY����8*CSymfony/Component/Validator/MetadataFactoryInterface.phpnu�[���PK��ZD#��?�?DX.CSymfony/Component/Validator/Resources/translations/validators.en.xlfnu�[���PK��Z-���uCuCDgnCSymfony/Component/Validator/Resources/translations/validators.sk.xlfnu�[���PK��Z�τ}K}KDP�CSymfony/Component/Validator/Resources/translations/validators.uk.xlfnu�[���PK��Z��-�1�1DA�CSymfony/Component/Validator/Resources/translations/validators.cy.xlfnu�[���PK��Z�m�w�B�BD�0DSymfony/Component/Validator/Resources/translations/validators.pl.xlfnu�[���PK��Z@T�\44D�sDSymfony/Component/Validator/Resources/translations/validators.af.xlfnu�[���PK��Z�b�@�@DB�DSymfony/Component/Validator/Resources/translations/validators.pt.xlfnu�[���PK��Ze]߭A�AII�DSymfony/Component/Validator/Resources/translations/validators.sr_Cyrl.xlfnu�[���PK��Z�a�2�2Do+ESymfony/Component/Validator/Resources/translations/validators.fi.xlfnu�[���PK��Z��"}2A2AD�^ESymfony/Component/Validator/Resources/translations/validators.es.xlfnu�[���PK��Zs�E#�A�AD6�ESymfony/Component/Validator/Resources/translations/validators.de.xlfnu�[���PK��Z=^��::D��ESymfony/Component/Validator/Resources/translations/validators.it.xlfnu�[���PK��Z	���AADFSymfony/Component/Validator/Resources/translations/validators.ca.xlfnu�[���PK��ZD��#"#"Dx^FSymfony/Component/Validator/Resources/translations/validators.mn.xlfnu�[���PK��Z��-tZMZMD�FSymfony/Component/Validator/Resources/translations/validators.ru.xlfnu�[���PK��Z<��bKKD��FSymfony/Component/Validator/Resources/translations/validators.bg.xlfnu�[���PK��Z����A�ADoGSymfony/Component/Validator/Resources/translations/validators.ro.xlfnu�[���PK��Z�ժN@@D�\GSymfony/Component/Validator/Resources/translations/validators.nl.xlfnu�[���PK��Z�%�N�=�=DW�GSymfony/Component/Validator/Resources/translations/validators.et.xlfnu�[���PK��Z
��GGDs�GSymfony/Component/Validator/Resources/translations/validators.fa.xlfnu�[���PK��Z-�L>L>D�"HSymfony/Component/Validator/Resources/translations/validators.id.xlfnu�[���PK��Z˺�Q1Q1D�aHSymfony/Component/Validator/Resources/translations/validators.tr.xlfnu�[���PK��Z	�)�B�BDp�HSymfony/Component/Validator/Resources/translations/validators.cs.xlfnu�[���PK��Z�6��%=%=G��HSymfony/Component/Validator/Resources/translations/validators.zh_CN.xlfnu�[���PK��Z�PhBhBDAISymfony/Component/Validator/Resources/translations/validators.lt.xlfnu�[���PK��Z���+BBDWISymfony/Component/Validator/Resources/translations/validators.fr.xlfnu�[���PK��Z(��=A=AD��ISymfony/Component/Validator/Resources/translations/validators.gl.xlfnu�[���PK��Z���wX@X@DN�ISymfony/Component/Validator/Resources/translations/validators.hr.xlfnu�[���PK��ZY�.3�5�5DJSymfony/Component/Validator/Resources/translations/validators.sq.xlfnu�[���PK��Z(�eeD3RJSymfony/Component/Validator/Resources/translations/validators.nb.xlfnu�[���PK��Z���t�A�ADrJSymfony/Component/Validator/Resources/translations/validators.eu.xlfnu�[���PK��Z1ar�==Ga�JSymfony/Component/Validator/Resources/translations/validators.zh_TW.xlfnu�[���PK��Z�T�л@�@G��JSymfony/Component/Validator/Resources/translations/validators.pt_BR.xlfnu�[���PK��Z���1�1D3KSymfony/Component/Validator/Resources/translations/validators.no.xlfnu�[���PK��Z��n�C�CDWeKSymfony/Component/Validator/Resources/translations/validators.sl.xlfnu�[���PK��Zq�b�?�?D��KSymfony/Component/Validator/Resources/translations/validators.lb.xlfnu�[���PK��Z93XaoAoAD�KSymfony/Component/Validator/Resources/translations/validators.hu.xlfnu�[���PK��Z����M�MD,LSymfony/Component/Validator/Resources/translations/validators.el.xlfnu�[���PK��Z��9>�5�5D@zLSymfony/Component/Validator/Resources/translations/validators.da.xlfnu�[���PK��Z���AAD��LSymfony/Component/Validator/Resources/translations/validators.ja.xlfnu�[���PK��Z�Q>�?�?D �LSymfony/Component/Validator/Resources/translations/validators.sv.xlfnu�[���PK��Zv_��w,w,D2MSymfony/Component/Validator/Resources/translations/validators.hy.xlfnu�[���PK��Z����O�OD_MSymfony/Component/Validator/Resources/translations/validators.ar.xlfnu�[���PK��Z�1�^�4�4I=�MSymfony/Component/Validator/Resources/translations/validators.sr_Latn.xlfnu�[���PK��Z@T'%�B�BDt�MSymfony/Component/Validator/Resources/translations/validators.vi.xlfnu�[���PK��Z��tý5�5D�'NSymfony/Component/Validator/Resources/translations/validators.he.xlfnu�[���PK��Z��D��<�]NSymfony/Component/Validator/Constraints/NotNullValidator.phpnu�[���PK��ZD~�SS2"aNSymfony/Component/Validator/Constraints/Choice.phpnu�[���PK��Z�~%ɋ�1�eNSymfony/Component/Validator/Constraints/Valid.phpnu�[���PK��Z�+��6�iNSymfony/Component/Validator/Constraints/NotEqualTo.phpnu�[���PK��Zm�Լ\\ClNSymfony/Component/Validator/Constraints/NotIdenticalToValidator.phpnu�[���PK��ZĿ:�KK6�nNSymfony/Component/Validator/Constraints/Expression.phpnu�[���PK��Z�خ
zz?�sNSymfony/Component/Validator/Constraints/Collection/Optional.phpnu�[���PK��Z\,y�zz?�vNSymfony/Component/Validator/Constraints/Collection/Required.phpnu�[���PK��Z
��n��?kyNSymfony/Component/Validator/Constraints/CollectionValidator.phpnu�[���PK��Z��y:g�NSymfony/Component/Validator/Constraints/BlankValidator.phpnu�[���PK��Z�+����0؅NSymfony/Component/Validator/Constraints/Iban.phpnu�[���PK��Z����	�	=�NSymfony/Component/Validator/Constraints/CallbackValidator.phpnu�[���PK��Z�}�&&25�NSymfony/Component/Validator/Constraints/Length.phpnu�[���PK��Z�b�=nn9��NSymfony/Component/Validator/Constraints/IsbnValidator.phpnu�[���PK��Z�<W���:��NSymfony/Component/Validator/Constraints/RegexValidator.phpnu�[���PK��Z^r��

4��NSymfony/Component/Validator/Constraints/Language.phpnu�[���PK��Z���,,0e�NSymfony/Component/Validator/Constraints/Isbn.phpnu�[���PK��Z�EW^��<�NSymfony/Component/Validator/Constraints/CountryValidator.phpnu�[���PK��Zzet�	�	?\�NSymfony/Component/Validator/Constraints/ExpressionValidator.phpnu�[���PK��Z�	�00/��NSymfony/Component/Validator/Constraints/Url.phpnu�[���PK��Z�V`���9"�NSymfony/Component/Validator/Constraints/IbanValidator.phpnu�[���PK��Z��vbb@6�NSymfony/Component/Validator/Constraints/GreaterThanValidator.phpnu�[���PK��ZS탟0�NSymfony/Component/Validator/Constraints/Date.phpnu�[���PK��Z�|4XX8j�NSymfony/Component/Validator/Constraints/UrlValidator.phpnu�[���PK��Zw���3*�NSymfony/Component/Validator/Constraints/NotNull.phpnu�[���PK��ZS�n���0��NSymfony/Component/Validator/Constraints/Null.phpnu�[���PK��Z�o�o��:��NSymfony/Component/Validator/Constraints/RangeValidator.phpnu�[���PK��Z�

4��NSymfony/Component/Validator/Constraints/Currency.phpnu�[���PK��Zrs+���4O�NSymfony/Component/Validator/Constraints/Optional.phpnu�[���PK��Z����449G�NSymfony/Component/Validator/Constraints/IssnValidator.phpnu�[���PK��Z�qp""0�NSymfony/Component/Validator/Constraints/File.phpnu�[���PK��Z5�ʟ��9f�NSymfony/Component/Validator/Constraints/DateValidator.phpnu�[���PK��Z0@���9�OSymfony/Component/Validator/Constraints/NullValidator.phpnu�[���PK��Z�>
i//5�OSymfony/Component/Validator/Constraints/Existence.phpnu�[���PK��ZtUה�4k	OSymfony/Component/Validator/Constraints/Required.phpnu�[���PK��Zm��\\>cOSymfony/Component/Validator/Constraints/AbstractComparison.phpnu�[���PK��Zc��y

4-OSymfony/Component/Validator/Constraints/DateTime.phpnu�[���PK��Zl˘��
�
7�OSymfony/Component/Validator/Constraints/IpValidator.phpnu�[���PK��Z�\\=�OSymfony/Component/Validator/Constraints/LessThanValidator.phpnu�[���PK��Z�U�4Y OSymfony/Component/Validator/Constraints/NotBlank.phpnu�[���PK��Z<8�S��:�"OSymfony/Component/Validator/Constraints/ImageValidator.phpnu�[���PK��Z��Lֻ�6�9OSymfony/Component/Validator/Constraints/CardScheme.phpnu�[���PK��Z��"��?�<OSymfony/Component/Validator/Constraints/CardSchemeValidator.phpnu�[���PK��ZN3�0/MOSymfony/Component/Validator/Constraints/Type.phpnu�[���PK��Z@vqq9�POSymfony/Component/Validator/Constraints/FileValidator.phpnu�[���PK��Z�'����1oiOSymfony/Component/Validator/Constraints/Count.phpnu�[���PK��Z�̢�VV@�oOSymfony/Component/Validator/Constraints/IdenticalToValidator.phpnu�[���PK��Zd�X�BB0~rOSymfony/Component/Validator/Constraints/Issn.phpnu�[���PK��Z�ଏ�A uOSymfony/Component/Validator/Constraints/GroupSequenceProvider.phpnu�[���PK��Z��}a��7 wOSymfony/Component/Validator/Constraints/GreaterThan.phpnu�[���PK��Z�Ǧ��3xyOSymfony/Component/Validator/Constraints/EqualTo.phpnu�[���PK��Zb+��9�{OSymfony/Component/Validator/Constraints/LuhnValidator.phpnu�[���PK��Z�ٜ?��0ŃOSymfony/Component/Validator/Constraints/True.phpnu�[���PK��Z?����G"�OSymfony/Component/Validator/Constraints/AbstractComparisonValidator.phpnu�[���PK��Z�̋	�	1y�OSymfony/Component/Validator/Constraints/Regex.phpnu�[���PK��Z��BB1e�OSymfony/Component/Validator/Constraints/Range.phpnu�[���PK��Z[�A���;�OSymfony/Component/Validator/Constraints/LessThanOrEqual.phpnu�[���PK��Zq;O3q�OSymfony/Component/Validator/Constraints/Country.phpnu�[���PK��Z5����:ܢOSymfony/Component/Validator/Constraints/EmailValidator.phpnu�[���PK��Z�`�v��;/�OSymfony/Component/Validator/Constraints/LocaleValidator.phpnu�[���PK��Z'㔘7��OSymfony/Component/Validator/Constraints/IdenticalTo.phpnu�[���PK��Z��/�OSymfony/Component/Validator/Constraints/All.phpnu�[���PK��Z{���UU?w�OSymfony/Component/Validator/Constraints/NotEqualToValidator.phpnu�[���PK��Z�ɑ559;�OSymfony/Component/Validator/Constraints/TrueValidator.phpnu�[���PK��Z�(.wwGٿOSymfony/Component/Validator/Constraints/GreaterThanOrEqualValidator.phpnu�[���PK��Z���(��9��OSymfony/Component/Validator/Constraints/TimeValidator.phpnu�[���PK��Z�Fn���8�OSymfony/Component/Validator/Constraints/AllValidator.phpnu�[���PK��Z�c����.�OSymfony/Component/Validator/Constraints/Ip.phpnu�[���PK��ZHð�2R�OSymfony/Component/Validator/Constraints/Locale.phpnu�[���PK��ZQ��=��OSymfony/Component/Validator/Constraints/LanguageValidator.phpnu�[���PK��ZaHβ;+�OSymfony/Component/Validator/Constraints/ChoiceValidator.phpnu�[���PK��Z�{HH1�OSymfony/Component/Validator/Constraints/Email.phpnu�[���PK��Zx�.`ss4��OSymfony/Component/Validator/Constraints/Callback.phpnu�[���PK��Z�����=��OSymfony/Component/Validator/Constraints/DateTimeValidator.phpnu�[���PK��Z�&����0�OSymfony/Component/Validator/Constraints/Luhn.phpnu�[���PK��Z�F���9<�OSymfony/Component/Validator/Constraints/TypeValidator.phpnu�[���PK��Z���&��=1�OSymfony/Component/Validator/Constraints/NotBlankValidator.phpnu�[���PK��Ze8�B�
�
6�PSymfony/Component/Validator/Constraints/Collection.phpnu�[���PK��ZI7U���1�PSymfony/Component/Validator/Constraints/False.phpnu�[���PK��Z�Q�>MPSymfony/Component/Validator/Constraints/GreaterThanOrEqual.phpnu�[���PK��Z��l��1�PSymfony/Component/Validator/Constraints/Blank.phpnu�[���PK��Z�CG^LL<PSymfony/Component/Validator/Constraints/EqualToValidator.phpnu�[���PK��Z^�T:�PSymfony/Component/Validator/Constraints/FalseValidator.phpnu�[���PK��ZO��qqD^PSymfony/Component/Validator/Constraints/LessThanOrEqualValidator.phpnu�[���PK��Z����vv9CPSymfony/Component/Validator/Constraints/GroupSequence.phpnu�[���PK��Z_��1"PSymfony/Component/Validator/Constraints/Image.phpnu�[���PK��Z��F;��;''PSymfony/Component/Validator/Constraints/LengthValidator.phpnu�[���PK��Z!xHH:e0PSymfony/Component/Validator/Constraints/CountValidator.phpnu�[���PK��Z��708PSymfony/Component/Validator/Constraints/Time.phpnu�[���PK��ZN�H���4y:PSymfony/Component/Validator/Constraints/LessThan.phpnu�[���PK��Ze��:�<PSymfony/Component/Validator/Constraints/NotIdenticalTo.phpnu�[���PK��Z�Z�=D?PSymfony/Component/Validator/Constraints/CurrencyValidator.phpnu�[���PK��ZGk	��3�DPSymfony/Component/Validator/ConstraintValidator.phpnu�[���PK��ZK�OC�GPSymfony/Component/Validator/ConstraintValidatorFactoryInterface.phpnu�[���PK��Z�8Wc��?KKPSymfony/Component/Validator/GlobalExecutionContextInterface.phpnu�[���PK��Zxf�JJ*KSPSymfony/Component/Validator/Validation.phpnu�[���PK��Zn�r�
�
2�WPSymfony/Component/Validator/ValidatorInterface.phpnu�[���PK��ZC���9MfPSymfony/Component/Templating/StreamingEngineInterface.phpnu�[���PK��Z<,��}}2�jPSymfony/Component/Templating/TemplateReference.phpnu�[���PK��Z�m�tTT+�rPSymfony/Component/Templating/autoloader.phpnu�[���PK��Z����;EtPSymfony/Component/Templating/TemplateReferenceInterface.phpnu�[���PK��ZJ� ���2k|PSymfony/Component/Templating/DebuggerInterface.phpnu�[���PK��ZDZ�_++<�PSymfony/Component/Templating/TemplateNameParserInterface.phpnu�[���PK��Z���3�PSymfony/Component/Templating/TemplateNameParser.phpnu�[���PK��Z�����0Y�PSymfony/Component/Templating/EngineInterface.phpnu�[���PK��Z��b�NN2n�PSymfony/Component/Templating/Asset/PathPackage.phpnu�[���PK��Z���TT1�PSymfony/Component/Templating/Asset/UrlPackage.phpnu�[���PK��Z�o##.ӞPSymfony/Component/Templating/Asset/Package.phpnu�[���PK��Zp�vj��7T�PSymfony/Component/Templating/Asset/PackageInterface.phpnu�[���PK��Z�'��4��PSymfony/Component/Templating/Storage/FileStorage.phpnu�[���PK��Z(�"w��6��PSymfony/Component/Templating/Storage/StringStorage.phpnu�[���PK��Zπ\�0��PSymfony/Component/Templating/Storage/Storage.phpnu�[���PK��Z��>3�PSymfony/Component/Templating/Loader/ChainLoader.phpnu�[���PK��Z�b��8��PSymfony/Component/Templating/Loader/FilesystemLoader.phpnu�[���PK��Z�g((.��PSymfony/Component/Templating/Loader/Loader.phpnu�[���PK��Zy�A�nn3o�PSymfony/Component/Templating/Loader/CacheLoader.phpnu�[���PK��ZI<�D��7@�PSymfony/Component/Templating/Loader/LoaderInterface.phpnu�[���PK��Z+�r�mm3|�PSymfony/Component/Templating/Helper/SlotsHelper.phpnu�[���PK��ZV¤՟�4L�PSymfony/Component/Templating/Helper/AssetsHelper.phpnu�[���PK��ZԷ����7O�PSymfony/Component/Templating/Helper/HelperInterface.phpnu�[���PK��Z����



8U�PSymfony/Component/Templating/Helper/CoreAssetsHelper.phpnu�[���PK��Z�NO��.�QSymfony/Component/Templating/Helper/Helper.phpnu�[���PK��Z_6H1%QSymfony/Component/Templating/DelegatingEngine.phpnu�[���PK��Z?w
y=y=*�QSymfony/Component/Templating/PhpEngine.phpnu�[���PK��Z6�H	��$lTQSymfony/Component/Yaml/Unescaper.phpnu�[���PK��Z�8�n�	�	!_fQSymfony/Component/Yaml/Dumper.phpnu�[���PK��Z�bNN%DpQSymfony/Component/Yaml/autoloader.phpnu�[���PK��Z��X��[�[!�qQSymfony/Component/Yaml/Parser.phpnu�[���PK��Z7MӺ

��QSymfony/Component/Yaml/Yaml.phpnu�[���PK��Z�+�l��7+�QSymfony/Component/Yaml/Exception/ExceptionInterface.phpnu�[���PK��Z�|�-��5X�QSymfony/Component/Yaml/Exception/RuntimeException.phpnu�[���PK��Z�����
�
3��QSymfony/Component/Yaml/Exception/ParseException.phpnu�[���PK��Zؙ՚��2��QSymfony/Component/Yaml/Exception/DumpException.phpnu�[���PK��Z)%�,m
m
"2�QSymfony/Component/Yaml/Escaper.phpnu�[���PK��Zq+�3�?�?!�QSymfony/Component/Yaml/Inline.phpnu�[���PK��Z�ݣ�"�"6�=RSymfony/Component/HttpFoundation/ResponseHeaderBag.phpnu�[���PK��Z�}��xx.�`RSymfony/Component/HttpFoundation/ServerBag.phpnu�[���PK��Z�_DK�
�
5�oRSymfony/Component/HttpFoundation/RedirectResponse.phpnu�[���PK��Z�s
��5�zRSymfony/Component/HttpFoundation/StreamedResponse.phpnu�[���PK��Z��F��+��RSymfony/Component/HttpFoundation/Cookie.phpnu�[���PK��Z�6=��
�
,��RSymfony/Component/HttpFoundation/IpUtils.phpnu�[���PK��ZP�i���,ƩRSymfony/Component/HttpFoundation/FileBag.phpnu�[���PK��Z1y��<�RSymfony/Component/HttpFoundation/RequestMatcherInterface.phpnu�[���PK��ZPE�
XX/f�RSymfony/Component/HttpFoundation/autoloader.phpnu�[���PK��Z8{?���3�RSymfony/Component/HttpFoundation/RequestMatcher.phpnu�[���PK��Z�͢|1Y�RSymfony/Component/HttpFoundation/JsonResponse.phpnu�[���PK��ZVk�b335��RSymfony/Component/HttpFoundation/AcceptHeaderItem.phpnu�[���PK��Zn��OO=k�RSymfony/Component/HttpFoundation/ExpressionRequestMatcher.phpnu�[���PK��Z�a.1'�RSymfony/Component/HttpFoundation/AcceptHeader.phpnu�[���PK��Z\�8��1�SSymfony/Component/HttpFoundation/ParameterBag.phpnu�[���PK��Z��6��B�(SSymfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.phpnu�[���PK��Z5p1��J�7SSymfony/Component/HttpFoundation/File/MimeType/FileinfoMimeTypeGuesser.phpnu�[���PK��Z�qx��L?SSymfony/Component/HttpFoundation/File/MimeType/ExtensionGuesserInterface.phpnu�[���PK��Z�J��LBSSymfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.phpnu�[���PK��Z2�k�	�	C/KSSymfony/Component/HttpFoundation/File/MimeType/ExtensionGuesser.phpnu�[���PK��Z�w�nM�M�KKUSSymfony/Component/HttpFoundation/File/MimeType/MimeTypeExtensionGuesser.phpnu�[���PK��Z�	�L��K�SSymfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesserInterface.phpnu�[���PK��Z�)���.^�SSymfony/Component/HttpFoundation/File/File.phpnu�[���PK��Z�s�-��IQ�SSymfony/Component/HttpFoundation/File/Exception/FileNotFoundException.phpnu�[���PK��Z�S��==Kz�SSymfony/Component/HttpFoundation/File/Exception/UnexpectedTypeException.phpnu�[���PK��Z�1�e��I2TSymfony/Component/HttpFoundation/File/Exception/AccessDeniedException.phpnu�[���PK��Z�gr��CbTSymfony/Component/HttpFoundation/File/Exception/UploadException.phpnu�[���PK��Zo�����A�TSymfony/Component/HttpFoundation/File/Exception/FileException.phpnu�[���PK��Z��ގ�#�#6�TSymfony/Component/HttpFoundation/File/UploadedFile.phpnu�[���PK��Z�7�E	E	13,TSymfony/Component/HttpFoundation/RequestStack.phpnu�[���PK��Z��W���;�5TSymfony/Component/HttpFoundation/Session/Flash/FlashBag.phpnu�[���PK��Z�@��WWECTSymfony/Component/HttpFoundation/Session/Flash/AutoExpireFlashBag.phpnu�[���PK��Za����D�QTSymfony/Component/HttpFoundation/Session/Flash/FlashBagInterface.phpnu�[���PK��Z�=�\\=�YTSymfony/Component/HttpFoundation/Session/SessionInterface.phpnu�[���PK��Z�:au774�lTSymfony/Component/HttpFoundation/Session/Session.phpnu�[���PK��ZM&z�rr@G�TSymfony/Component/HttpFoundation/Session/SessionBagInterface.phpnu�[���PK��Z��eL)�TSymfony/Component/HttpFoundation/Session/Attribute/AttributeBagInterface.phpnu�[���PK��Z��(���C��TSymfony/Component/HttpFoundation/Session/Attribute/AttributeBag.phpnu�[���PK��Z�0�H66MߘTSymfony/Component/HttpFoundation/Session/Attribute/NamespacedAttributeBag.phpnu�[���PK��Z�t�3�3I��TSymfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.phpnu�[���PK��Zގ�!L��TSymfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.phpnu�[���PK��Z��$�

K6�TSymfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.phpnu�[���PK��Z����33Q�TSymfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.phpnu�[���PK��Z�>�q��O}USymfony/Component/HttpFoundation/Session/Storage/Handler/NullSessionHandler.phpnu�[���PK��Zi����R�USymfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.phpnu�[���PK��ZOZ�P""NUSymfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.phpnu�[���PK��Zk��4{{T�<USymfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.phpnu�[���PK��Zu�Y0��U�HUSymfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.phpnu�[���PK��Zڏ۹�
�
S�OUSymfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.phpnu�[���PK��Z�����U[USymfony/Component/HttpFoundation/Session/Storage/Handler/WriteCheckSessionHandler.phpnu�[���PK��Z�zu00LwcUSymfony/Component/HttpFoundation/Session/Storage/PhpBridgeSessionStorage.phpnu�[���PK��Zmwȡ��N#kUSymfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.phpnu�[���PK��Z�2�]��H!sUSymfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.phpnu�[���PK��Z�A��F�USymfony/Component/HttpFoundation/Session/Storage/Proxy/NativeProxy.phpnu�[���PK��Z��g_��@��USymfony/Component/HttpFoundation/Session/Storage/MetadataBag.phpnu�[���PK��Z��?�yyL��USymfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.phpnu�[���PK��Z�K>��2��USymfony/Component/HttpFoundation/ApacheRequest.phpnu�[���PK��Zq�ugd�d�,��USymfony/Component/HttpFoundation/Request.phpnu�[���PK��Zd�}޷%�%7S�VSymfony/Component/HttpFoundation/BinaryFileResponse.phpnu�[���PK��Z���pߋߋ-q�VSymfony/Component/HttpFoundation/Response.phpnu�[���PK��Z?`
�y	y	L�2WSymfony/Component/HttpFoundation/Resources/stubs/SessionHandlerInterface.phpnu�[���PK��ZEY���.�<WSymfony/Component/HttpFoundation/HeaderBag.phpnu�[���PK��Z9�;""'�\WSymfony/Component/BrowserKit/Cookie.phpnu�[���PK��Z.�TT+7WSymfony/Component/BrowserKit/autoloader.phpnu�[���PK��Z�����*�WSymfony/Component/BrowserKit/CookieJar.phpnu�[���PK��Z����
�
(ݞWSymfony/Component/BrowserKit/Request.phpnu�[���PK��Zl�-
-
)(�WSymfony/Component/BrowserKit/Response.phpnu�[���PK��Z㩑eCC'��WSymfony/Component/BrowserKit/Client.phpnu�[���PK��Z��/		(!�WSymfony/Component/BrowserKit/History.phpnu�[���PK��Z��V<nn2�XSymfony/Component/DomCrawler/FormFieldRegistry.phpnu�[���PK��ZLo�TT+gXSymfony/Component/DomCrawler/autoloader.phpnu�[���PK��Z���%XSymfony/Component/DomCrawler/Link.phpnu�[���PK��Z\Ud��	�	0�2XSymfony/Component/DomCrawler/Field/FormField.phpnu�[���PK��ZbڋvB
B
4�<XSymfony/Component/DomCrawler/Field/FileFormField.phpnu�[���PK��Z�	Y[$[$6`JXSymfony/Component/DomCrawler/Field/ChoiceFormField.phpnu�[���PK��Z
ʀ���8!oXSymfony/Component/DomCrawler/Field/TextareaFormField.phpnu�[���PK��Z�����5hsXSymfony/Component/DomCrawler/Field/InputFormField.phpnu�[���PK��Z<�4{bb(PyXSymfony/Component/DomCrawler/Crawler.phpnu�[���PK��Z�
�H7H7%��XSymfony/Component/DomCrawler/Form.phpnu�[���PK��Z�����!�!2aYSymfony/Component/CssSelector/XPath/Translator.phpnu�[���PK��Z��r771J5YSymfony/Component/CssSelector/XPath/XPathExpr.phpnu�[���PK��Z
���;�@YSymfony/Component/CssSelector/XPath/TranslatorInterface.phpnu�[���PK��Z��u��C�EYSymfony/Component/CssSelector/XPath/Extension/FunctionExtension.phpnu�[���PK��Z�܍��L	^YSymfony/Component/CssSelector/XPath/Extension/AttributeMatchingExtension.phpnu�[���PK��Z�Ѽ`PP?WqYSymfony/Component/CssSelector/XPath/Extension/NodeExtension.phpnu�[���PK��Z$p��BB?�YSymfony/Component/CssSelector/XPath/Extension/HtmlExtension.phpnu�[���PK��Zc�-��CǧYSymfony/Component/CssSelector/XPath/Extension/AbstractExtension.phpnu�[���PK��Z��x=	=	F�YSymfony/Component/CssSelector/XPath/Extension/CombinationExtension.phpnu�[���PK��Z ����FʶYSymfony/Component/CssSelector/XPath/Extension/PseudoClassExtension.phpnu�[���PK��Z���||D�YSymfony/Component/CssSelector/XPath/Extension/ExtensionInterface.phpnu�[���PK��Zu�UU,��YSymfony/Component/CssSelector/autoloader.phpnu�[���PK��Z,+?��;��YSymfony/Component/CssSelector/Node/CombinedSelectorNode.phpnu�[���PK��Z�r�I��4��YSymfony/Component/CssSelector/Node/NodeInterface.phpnu�[���PK��Z����3��YSymfony/Component/CssSelector/Node/SelectorNode.phpnu�[���PK��Z�pM2��3��YSymfony/Component/CssSelector/Node/AbstractNode.phpnu�[���PK��Z�Г^FF2��YSymfony/Component/CssSelector/Node/ElementNode.phpnu�[���PK��Z�.��221x�YSymfony/Component/CssSelector/Node/PseudoNode.phpnu�[���PK��Z	�i���0�YSymfony/Component/CssSelector/Node/ClassNode.phpnu�[���PK��Z����bb3Z�YSymfony/Component/CssSelector/Node/NegationNode.phpnu�[���PK��Z�x�2ZSymfony/Component/CssSelector/Node/Specificity.phpnu�[���PK��Z�#^[��/�ZSymfony/Component/CssSelector/Node/HashNode.phpnu�[���PK��ZF��K
K
4�ZSymfony/Component/CssSelector/Node/AttributeNode.phpnu�[���PK��Z�x�3�ZSymfony/Component/CssSelector/Node/FunctionNode.phpnu�[���PK��Zm��c��B ZSymfony/Component/CssSelector/Exception/InternalErrorException.phpnu�[���PK��Z��מ�@#ZSymfony/Component/CssSelector/Exception/SyntaxErrorException.phpnu�[���PK��Z/pTС�D#+ZSymfony/Component/CssSelector/Exception/ExpressionErrorException.phpnu�[���PK��Zgf�GBB>8.ZSymfony/Component/CssSelector/Exception/ExceptionInterface.phpnu�[���PK��Z'[|ɀ�:�0ZSymfony/Component/CssSelector/Exception/ParseException.phpnu�[���PK��Z^�}		-�3ZSymfony/Component/CssSelector/CssSelector.phpnu�[���PK��Z5#� HH<4=ZSymfony/Component/CssSelector/Parser/Shortcut/HashParser.phpnu�[���PK��Zҵܗ��C�CZSymfony/Component/CssSelector/Parser/Shortcut/EmptyStringParser.phpnu�[���PK��ZTR#[PP=IZSymfony/Component/CssSelector/Parser/Shortcut/ClassParser.phpnu�[���PK��Z�Z�>��?�OZSymfony/Component/CssSelector/Parser/Shortcut/ElementParser.phpnu�[���PK��Z���QQ4�UZSymfony/Component/CssSelector/Parser/TokenStream.phpnu�[���PK��Z��6\5
5
>~dZSymfony/Component/CssSelector/Parser/Handler/StringHandler.phpnu�[���PK��Z8�D�^^?!oZSymfony/Component/CssSelector/Parser/Handler/CommentHandler.phpnu�[���PK��Z�X{��<�sZSymfony/Component/CssSelector/Parser/Handler/HashHandler.phpnu�[���PK��Zh��ffAJ{ZSymfony/Component/CssSelector/Parser/Handler/HandlerInterface.phpnu�[���PK��Ze'n��>!ZSymfony/Component/CssSelector/Parser/Handler/NumberHandler.phpnu�[���PK��Z�#BT�ZSymfony/Component/CssSelector/Parser/Handler/IdentifierHandler.phpnu�[���PK��Z����BȌZSymfony/Component/CssSelector/Parser/Handler/WhitespaceHandler.phpnu�[���PK��Z6N�D1D1/̑ZSymfony/Component/CssSelector/Parser/Parser.phpnu�[���PK��Z;���		/o�ZSymfony/Component/CssSelector/Parser/Reader.phpnu�[���PK��Z�AEo118��ZSymfony/Component/CssSelector/Parser/ParserInterface.phpnu�[���PK��Z�zZ<��.u�ZSymfony/Component/CssSelector/Parser/Token.phpnu�[���PK��Z>�<��
�
D��ZSymfony/Component/CssSelector/Parser/Tokenizer/TokenizerPatterns.phpnu�[���PK��Z�S�kFF<��ZSymfony/Component/CssSelector/Parser/Tokenizer/Tokenizer.phpnu�[���PK��Z ��W55DZ�ZSymfony/Component/CssSelector/Parser/Tokenizer/TokenizerEscaping.phpnu�[���PK��Zb�k���+�ZSymfony/Component/EventDispatcher/Event.phpnu�[���PK��Z��YY0�[Symfony/Component/EventDispatcher/autoloader.phpnu�[���PK��Z�
���M�	[Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.phpnu�[���PK��Z,��DD2�[Symfony/Component/EventDispatcher/GenericEvent.phpnu�[���PK��ZcG�11>�[Symfony/Component/EventDispatcher/EventSubscriberInterface.phpnu�[���PK��Zs���> #[Symfony/Component/EventDispatcher/ImmutableEventDispatcher.phpnu�[���PK��ZU����>G,[Symfony/Component/EventDispatcher/EventDispatcherInterface.phpnu�[���PK��Z��NmCu8[Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.phpnu�[���PK��ZY�"��5S[Symfony/Component/EventDispatcher/EventDispatcher.phpnu�[���PK��Z x��
�
1%i[Symfony/Component/Console/Command/ListCommand.phpnu�[���PK��Z�Ƙ�7@7@-Ft[Symfony/Component/Console/Command/Command.phpnu�[���PK��Z�m_
_
1ڴ[Symfony/Component/Console/Command/HelpCommand.phpnu�[���PK��Z\0�E��+��[Symfony/Component/Console/ConsoleEvents.phpnu�[���PK��Z2V��#��[Symfony/Component/Console/Shell.phpnu�[���PK��Z�.�QQ(;�[Symfony/Component/Console/autoloader.phpnu�[���PK��Z�hr�f
f
6��[Symfony/Component/Console/Tester/ApplicationTester.phpnu�[���PK��Z~H(R2��[Symfony/Component/Console/Tester/CommandTester.phpnu�[���PK��Z�Q�)�)-.�[Symfony/Component/Console/Input/ArgvInput.phpnu�[���PK��Z��'��1C'\Symfony/Component/Console/Input/InputArgument.phpnu�[���PK��Z�AM662{4\Symfony/Component/Console/Input/InputInterface.phpnu�[���PK��Z��O�VV/E\Symfony/Component/Console/Input/InputOption.phpnu�[���PK��Z1�E(0(03�\\Symfony/Component/Console/Input/InputDefinition.phpnu�[���PK��Z�΂=�
�
/S�\Symfony/Component/Console/Input/StringInput.phpnu�[���PK��Zgm()��\Symfony/Component/Console/Input/Input.phpnu�[���PK��Zp���%%.�\Symfony/Component/Console/Input/ArrayInput.phpnu�[���PK��Z9K�h^^7��\Symfony/Component/Console/Input/InputAwareInterface.phpnu�[���PK��Zonj�&&<N�\Symfony/Component/Console/Formatter/OutputFormatterStyle.phpnu�[���PK��Z��l���7��\Symfony/Component/Console/Formatter/OutputFormatter.phpnu�[���PK��Z5����E�\Symfony/Component/Console/Formatter/OutputFormatterStyleInterface.phpnu�[���PK��Z�v��
�
A ]Symfony/Component/Console/Formatter/OutputFormatterStyleStack.phpnu�[���PK��ZJp����@u
]Symfony/Component/Console/Formatter/OutputFormatterInterface.phpnu�[���PK��Z��0�KK;�]Symfony/Component/Console/Output/ConsoleOutputInterface.phpnu�[���PK��Z��ϱ}}2~]Symfony/Component/Console/Output/ConsoleOutput.phpnu�[���PK��Z��z�MM4]$]Symfony/Component/Console/Output/OutputInterface.phpnu�[���PK��ZF�$_��/0]Symfony/Component/Console/Output/NullOutput.phpnu�[���PK��Zs�Q;;+A7]Symfony/Component/Console/Output/Output.phpnu�[���PK��Z�,Q�MM1�G]Symfony/Component/Console/Output/StreamOutput.phpnu�[���PK��Zt|X4hh3�T]Symfony/Component/Console/Output/BufferedOutput.phpnu�[���PK��Z�L�UҊҊ)PX]Symfony/Component/Console/Application.phpnu�[���PK��Z���	�	.{�]Symfony/Component/Console/Helper/HelperSet.phpnu�[���PK��Z�z����4��]Symfony/Component/Console/Helper/HelperInterface.phpnu�[���PK��ZZ\���+�]Symfony/Component/Console/Helper/Helper.phpnu�[���PK��Zg�se��4�]Symfony/Component/Console/Helper/FormatterHelper.phpnu�[���PK��Z��2204^Symfony/Component/Console/Helper/TableHelper.phpnu�[���PK��Z"U�1

5�3^Symfony/Component/Console/Helper/DescriptorHelper.phpnu�[���PK��Zs� H��5>^Symfony/Component/Console/Helper/InputAwareHelper.phpnu�[���PK��Z|po.o.3^A^Symfony/Component/Console/Helper/ProgressHelper.phpnu�[���PK��Z&�>@>@10p^Symfony/Component/Console/Helper/DialogHelper.phpnu�[���PK��ZD��uu7ϰ^Symfony/Component/Console/Descriptor/JsonDescriptor.phpnu�[���PK��Z�m��
�
3��^Symfony/Component/Console/Descriptor/Descriptor.phpnu�[���PK��Z�lP�..;��^Symfony/Component/Console/Descriptor/MarkdownDescriptor.phpnu�[���PK��Z�s�X�
�
?c�^Symfony/Component/Console/Descriptor/ApplicationDescription.phpnu�[���PK��Zﶲ��%�%6��^Symfony/Component/Console/Descriptor/XmlDescriptor.phpnu�[���PK��Z����7�_Symfony/Component/Console/Descriptor/TextDescriptor.phpnu�[���PK��ZJZ0<��<@;_Symfony/Component/Console/Descriptor/DescriptorInterface.phpnu�[���PK��Z���v$$7�>_Symfony/Component/Console/Resources/bin/hiddeninput.exenu�[���PK��Z||-&��7�b_Symfony/Component/Console/Event/ConsoleCommandEvent.phpnu�[���PK��Z�Z��&&9e_Symfony/Component/Console/Event/ConsoleTerminateEvent.phpnu�[���PK��Zs�KAA9�j_Symfony/Component/Console/Event/ConsoleExceptionEvent.phpnu�[���PK��Z��
���0Tq_Symfony/Component/Console/Event/ConsoleEvent.phpnu�[���PK��Z]�='YY0lw_Symfony/Component/OptionsResolver/autoloader.phpnu�[���PK��Z��sZ��G%y_Symfony/Component/OptionsResolver/Exception/InvalidOptionsException.phpnu�[���PK��Z�yPH��I�{_Symfony/Component/OptionsResolver/Exception/OptionDefinitionException.phpnu�[���PK��ZE@�^��B~_Symfony/Component/OptionsResolver/Exception/ExceptionInterface.phpnu�[���PK��Zp����G'�_Symfony/Component/OptionsResolver/Exception/MissingOptionsException.phpnu�[���PK��Z��G��>��_Symfony/Component/OptionsResolver/OptionsResolverInterface.phpnu�[���PK��Z^�R��<�<-�_Symfony/Component/OptionsResolver/Options.phpnu�[���PK��Z}���8%8%5��_Symfony/Component/OptionsResolver/OptionsResolver.phpnu�[���PK��ZfJ���5�`Symfony/Component/Config/Definition/NodeInterface.phpnu�[���PK��Z��jkk3w`Symfony/Component/Config/Definition/IntegerNode.phpnu�[���PK��Za�Vp0E`Symfony/Component/Config/Definition/EnumNode.phpnu�[���PK��ZUn=#'#';�`Symfony/Component/Config/Definition/PrototypedArrayNode.phpnu�[���PK��ZU��''1?=`Symfony/Component/Config/Definition/Processor.phpnu�[���PK��Z�C����;�H`Symfony/Component/Config/Definition/Exception/Exception.phpnu�[���PK��Z5-���O�J`Symfony/Component/Config/Definition/Exception/InvalidConfigurationException.phpnu�[���PK��Z����C2N`Symfony/Component/Config/Definition/Exception/UnsetKeyException.phpnu�[���PK��Z��@��F�P`Symfony/Component/Config/Definition/Exception/InvalidTypeException.phpnu�[���PK��Z]F4���L$S`Symfony/Component/Config/Definition/Exception/InvalidDefinitionException.phpnu�[���PK��Z�|�EEGzU`Symfony/Component/Config/Definition/Exception/DuplicateKeyException.phpnu�[���PK��Z�:2&QQM6X`Symfony/Component/Config/Definition/Exception/ForbiddenOverwriteException.phpnu�[���PK��Z#
֕44D[`Symfony/Component/Config/Definition/Builder/NormalizationBuilder.phpnu�[���PK��ZV�hU��;�a`Symfony/Component/Config/Definition/Builder/TreeBuilder.phpnu�[���PK��Z��ʍ��B�h`Symfony/Component/Config/Definition/Builder/EnumNodeDefinition.phpnu�[���PK��Z���{{<�m`Symfony/Component/Config/Definition/Builder/MergeBuilder.phpnu�[���PK��Z,��l[[A�s`Symfony/Component/Config/Definition/Builder/ValidationBuilder.phpnu�[���PK��ZP����E�x`Symfony/Component/Config/Definition/Builder/BooleanNodeDefinition.phpnu�[���PK��Z�e�@��F�|`Symfony/Component/Config/Definition/Builder/VariableNodeDefinition.phpnu�[���PK��Z��8�8C��`Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.phpnu�[���PK��Z �"�$$;�`Symfony/Component/Config/Definition/Builder/ExprBuilder.phpnu�[���PK��Z�3d�__M��`Symfony/Component/Config/Definition/Builder/ParentNodeDefinitionInterface.phpnu�[���PK��Z�mc��Dr�`Symfony/Component/Config/Definition/Builder/ScalarNodeDefinition.phpnu�[���PK��Z'nڭE��`Symfony/Component/Config/Definition/Builder/IntegerNodeDefinition.phpnu�[���PK��Zt�p��C<�`Symfony/Component/Config/Definition/Builder/FloatNodeDefinition.phpnu�[���PK��ZU��=��C��`Symfony/Component/Config/Definition/Builder/NodeParentInterface.phpnu�[���PK��Z �}��;��`Symfony/Component/Config/Definition/Builder/NodeBuilder.phpnu�[���PK��Z~�G�XXE��`Symfony/Component/Config/Definition/Builder/NumericNodeDefinition.phpnu�[���PK��Z��K��>�`Symfony/Component/Config/Definition/Builder/NodeDefinition.phpnu�[���PK��Z����3!aSymfony/Component/Config/Definition/BooleanNode.phpnu�[���PK��Z�+;;2/!aSymfony/Component/Config/Definition/ScalarNode.phpnu�[���PK��Zm�+��1�%aSymfony/Component/Config/Definition/FloatNode.phpnu�[���PK��Zi
�>>B*aSymfony/Component/Config/Definition/Dumper/YamlReferenceDumper.phpnu�[���PK��Z�2��&�&A�AaSymfony/Component/Config/Definition/Dumper/XmlReferenceDumper.phpnu�[���PK��Z$�¸	�	4�haSymfony/Component/Config/Definition/VariableNode.phpnu�[���PK��ZG4�*�*1�raSymfony/Component/Config/Definition/ArrayNode.phpnu�[���PK��Z*���dd>)�aSymfony/Component/Config/Definition/ConfigurationInterface.phpnu�[���PK��Z��eww>��aSymfony/Component/Config/Definition/PrototypeNodeInterface.phpnu�[���PK��Z-*ҹ--3�aSymfony/Component/Config/Definition/NumericNode.phpnu�[���PK��Z��B�""0p�aSymfony/Component/Config/Definition/BaseNode.phpnu�[���PK��Z0��007��aSymfony/Component/Config/Definition/ReferenceDumper.phpnu�[���PK��Z`�PP'm�aSymfony/Component/Config/autoloader.phpnu�[���PK��ZfK�EDD7�aSymfony/Component/Config/Resource/ResourceInterface.phpnu�[���PK��Z��T!!2��aSymfony/Component/Config/Resource/FileResource.phpnu�[���PK��Z�
#�
�
7B�aSymfony/Component/Config/Resource/DirectoryResource.phpnu�[���PK��Z�C3kll1z�aSymfony/Component/Config/FileLocatorInterface.phpnu�[���PK��Z7�TTQG�aSymfony/Component/Config/Exception/FileLoaderImportCircularReferenceException.phpnu�[���PK��Z��W�	�	>�aSymfony/Component/Config/Exception/FileLoaderLoadException.phpnu�[���PK��Z��k��*�aSymfony/Component/Config/Util/XmlUtils.phpnu�[���PK��ZI��(�bSymfony/Component/Config/FileLocator.phpnu�[���PK��Z__wP<
<
.'%bSymfony/Component/Config/Loader/FileLoader.phpnu�[���PK��Z���))4�2bSymfony/Component/Config/Loader/DelegatingLoader.phpnu�[���PK��Z������;N9bSymfony/Component/Config/Loader/LoaderResolverInterface.phpnu�[���PK��ZHPʉ�2�<bSymfony/Component/Config/Loader/LoaderResolver.phpnu�[���PK��Z�=���*~DbSymfony/Component/Config/Loader/Loader.phpnu�[���PK��Z���4993�LbSymfony/Component/Config/Loader/LoaderInterface.phpnu�[���PK��Z��:a�
�
(CRbSymfony/Component/Config/ConfigCache.phpnu�[���PK��Z\�[���0�]bSymfony/Component/HttpKernel/KernelInterface.phpnu�[���PK��Z�?.��\�\'�qbSymfony/Component/HttpKernel/Kernel.phpnu�[���PK��Z���?��bSymfony/Component/HttpKernel/CacheClearer/ChainCacheClearer.phpnu�[���PK��ZYxځ55C��bSymfony/Component/HttpKernel/CacheClearer/CacheClearerInterface.phpnu�[���PK��Z�zTT+Z�bSymfony/Component/HttpKernel/autoloader.phpnu�[���PK��Z_��S77A	�bSymfony/Component/HttpKernel/CacheWarmer/CacheWarmerInterface.phpnu�[���PK��Z���^FF>��bSymfony/Component/HttpKernel/CacheWarmer/WarmableInterface.phpnu�[���PK��Z��8ee8e�bSymfony/Component/HttpKernel/CacheWarmer/CacheWarmer.phpnu�[���PK��Z�R�!MMA2�bSymfony/Component/HttpKernel/CacheWarmer/CacheWarmerAggregate.phpnu�[���PK��Z��KK3��bSymfony/Component/HttpKernel/Debug/ErrorHandler.phpnu�[���PK��Z���9��7��bSymfony/Component/HttpKernel/Debug/ExceptionHandler.phpnu�[���PK��Z�eڮ55?��bSymfony/Component/HttpKernel/Debug/TraceableEventDispatcher.phpnu�[���PK��Z>�<���/$cSymfony/Component/HttpKernel/Log/NullLogger.phpnu�[���PK��Z~�[�

4M)cSymfony/Component/HttpKernel/Log/LoggerInterface.phpnu�[���PK��ZJ��=[[9�.cSymfony/Component/HttpKernel/Log/DebugLoggerInterface.phpnu�[���PK��Z���ss-�2cSymfony/Component/HttpKernel/KernelEvents.phpnu�[���PK��ZE^����?R?cSymfony/Component/HttpKernel/EventListener/ProfilerListener.phpnu�[���PK��Z����
�
?JUcSymfony/Component/HttpKernel/EventListener/FragmentListener.phpnu�[���PK��Z@S��>BccSymfony/Component/HttpKernel/EventListener/SessionListener.phpnu�[���PK��Z�|$���CXicSymfony/Component/HttpKernel/EventListener/ErrorsLoggerListener.phpnu�[���PK��Z���$$G�ncSymfony/Component/HttpKernel/EventListener/StreamedResponseListener.phpnu�[���PK��Z��	���@1tcSymfony/Component/HttpKernel/EventListener/ExceptionListener.phpnu�[���PK��ZP�C�yy?��cSymfony/Component/HttpKernel/EventListener/ResponseListener.phpnu�[���PK��ZS
�"P
P
=m�cSymfony/Component/HttpKernel/EventListener/LocaleListener.phpnu�[���PK��Z/�)A
A
B*�cSymfony/Component/HttpKernel/EventListener/TestSessionListener.phpnu�[���PK��Z�	��--=ݣcSymfony/Component/HttpKernel/EventListener/RouterListener.phpnu�[���PK��Z��^��:w�cSymfony/Component/HttpKernel/EventListener/EsiListener.phpnu�[���PK��ZqK-##@z�cSymfony/Component/HttpKernel/Fragment/InlineFragmentRenderer.phpnu�[���PK��Zm���33B
�cSymfony/Component/HttpKernel/Fragment/RoutableFragmentRenderer.phpnu�[���PK��Z�j�g�	�	=��cSymfony/Component/HttpKernel/Fragment/EsiFragmentRenderer.phpnu�[���PK��Z��R��9
�cSymfony/Component/HttpKernel/Fragment/FragmentHandler.phpnu�[���PK��Z5앾��BdSymfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.phpnu�[���PK��Zz�����C)dSymfony/Component/HttpKernel/Fragment/FragmentRendererInterface.phpnu�[���PK��Z�ST��;s dSymfony/Component/HttpKernel/Exception/FlattenException.phpnu�[���PK��Z[G�??B�#dSymfony/Component/HttpKernel/Exception/BadRequestHttpException.phpnu�[���PK��Z��7��Gm'dSymfony/Component/HttpKernel/Exception/TooManyRequestsHttpException.phpnu�[���PK��ZW1�d��8m,dSymfony/Component/HttpKernel/Exception/HttpException.phpnu�[���PK��ZN�0�;;@v0dSymfony/Component/HttpKernel/Exception/ConflictHttpException.phpnu�[���PK��ZC%؝SSL!4dSymfony/Component/HttpKernel/Exception/UnsupportedMediaTypeHttpException.phpnu�[���PK��Z���EEE�7dSymfony/Component/HttpKernel/Exception/NotAcceptableHttpException.phpnu�[���PK��Z�Ѕ33<�;dSymfony/Component/HttpKernel/Exception/GoneHttpException.phpnu�[���PK��Z^���>I?dSymfony/Component/HttpKernel/Exception/FatalErrorException.phpnu�[���PK��Z)8*uuD6BdSymfony/Component/HttpKernel/Exception/AccessDeniedHttpException.phpnu�[���PK��Z�+�~~LFdSymfony/Component/HttpKernel/Exception/PreconditionRequiredHttpException.phpnu�[���PK��Z+�;XXJJdSymfony/Component/HttpKernel/Exception/ServiceUnavailableHttpException.phpnu�[���PK��Z*���D�NdSymfony/Component/HttpKernel/Exception/UnauthorizedHttpException.phpnu�[���PK��Z�瞻??@2SdSymfony/Component/HttpKernel/Exception/NotFoundHttpException.phpnu�[���PK��Z<��~��H�VdSymfony/Component/HttpKernel/Exception/MethodNotAllowedHttpException.phpnu�[���PK��Z�� GGF;[dSymfony/Component/HttpKernel/Exception/LengthRequiredHttpException.phpnu�[���PK��Z�;C�OOJ�^dSymfony/Component/HttpKernel/Exception/PreconditionFailedHttpException.phpnu�[���PK��ZrQrW��A�bdSymfony/Component/HttpKernel/Exception/HttpExceptionInterface.phpnu�[���PK��Z�^t�4�edSymfony/Component/HttpKernel/TerminableInterface.phpnu�[���PK��Z���=AA4ijdSymfony/Component/HttpKernel/HttpKernelInterface.phpnu�[���PK��Z�k�t$$+pdSymfony/Component/HttpKernel/HttpKernel.phpnu�[���PK��Z����b
b
9p�dSymfony/Component/HttpKernel/HttpCache/StoreInterface.phpnu�[���PK��ZM~��CCL;�dSymfony/Component/HttpKernel/HttpCache/EsiResponseCacheStrategyInterface.phpnu�[���PK��Z�w�n n .��dSymfony/Component/HttpKernel/HttpCache/Esi.phpnu�[���PK��Z�#��[�[4��dSymfony/Component/HttpKernel/HttpCache/HttpCache.phpnu�[���PK��Z�K:�1�10!eSymfony/Component/HttpKernel/HttpCache/Store.phpnu�[���PK��Z/��)�	�	C5SeSymfony/Component/HttpKernel/HttpCache/EsiResponseCacheStrategy.phpnu�[���PK��Z�J�z��*�]eSymfony/Component/HttpKernel/UriSigner.phpnu�[���PK��Z��d��3�deSymfony/Component/HttpKernel/Config/FileLocator.phpnu�[���PK��Z!���ll.�jeSymfony/Component/HttpKernel/Bundle/Bundle.phpnu�[���PK��Z�3�a��7m�eSymfony/Component/HttpKernel/Bundle/BundleInterface.phpnu�[���PK��ZB�Wzll@��eSymfony/Component/HttpKernel/Profiler/MongoDbProfilerStorage.phpnu�[���PK��Z���

2��eSymfony/Component/HttpKernel/Profiler/Profiler.phpnu�[���PK��Z$���	�	B�eSymfony/Component/HttpKernel/Profiler/MemcachedProfilerStorage.phpnu�[���PK��Z�rLU��B�eSymfony/Component/HttpKernel/Profiler/ProfilerStorageInterface.phpnu�[���PK��ZT��sX	X	>u�eSymfony/Component/HttpKernel/Profiler/MysqlProfilerStorage.phpnu�[���PK��ZN����'�'>;�eSymfony/Component/HttpKernel/Profiler/RedisProfilerStorage.phpnu�[���PK��Z�����<lfSymfony/Component/HttpKernel/Profiler/PdoProfilerStorage.phpnu�[���PK��ZiY~2
2
Am$fSymfony/Component/HttpKernel/Profiler/MemcacheProfilerStorage.phpnu�[���PK��Z� ��1/fSymfony/Component/HttpKernel/Profiler/Profile.phpnu�[���PK��Z�t��E*DfSymfony/Component/HttpKernel/Profiler/BaseMemcacheProfilerStorage.phpnu�[���PK��Zt}�[��?�bfSymfony/Component/HttpKernel/Profiler/SqliteProfilerStorage.phpnu�[���PK��Z\Y�`��=�ufSymfony/Component/HttpKernel/Profiler/FileProfilerStorage.phpnu�[���PK��Z��,&&8�fSymfony/Component/HttpKernel/Event/PostResponseEvent.phpnu�[���PK��Z
�7���9��fSymfony/Component/HttpKernel/Event/FinishRequestEvent.phpnu�[���PK��Z�`g��:̜fSymfony/Component/HttpKernel/Event/FilterResponseEvent.phpnu�[���PK��Z٨�.kkJ��fSymfony/Component/HttpKernel/Event/GetResponseForControllerResultEvent.phpnu�[���PK��Z9�I��7ܩfSymfony/Component/HttpKernel/Event/GetResponseEvent.phpnu�[���PK��Z�9����CίfSymfony/Component/HttpKernel/Event/GetResponseForExceptionEvent.phpnu�[���PK��Z�%���	�	<�fSymfony/Component/HttpKernel/Event/FilterControllerEvent.phpnu�[���PK��Z}�x��2@�fSymfony/Component/HttpKernel/Event/KernelEvent.phpnu�[���PK��ZN�#�FF'~�fSymfony/Component/HttpKernel/Client.phpnu�[���PK��Z�
<I�fSymfony/Component/HttpKernel/DataCollector/LateDataCollectorInterface.phpnu�[���PK��Z�8���E��fSymfony/Component/HttpKernel/DataCollector/ExceptionDataCollector.phpnu�[���PK��Z�2��~~B��fSymfony/Component/HttpKernel/DataCollector/ConfigDataCollector.phpnu�[���PK��Z��.�E�
gSymfony/Component/HttpKernel/DataCollector/DataCollectorInterface.phpnu�[���PK��Z��޹�B(gSymfony/Component/HttpKernel/DataCollector/LoggerDataCollector.phpnu�[���PK��Z�@:o	o	BSgSymfony/Component/HttpKernel/DataCollector/RouterDataCollector.phpnu�[���PK��Z��+66A4&gSymfony/Component/HttpKernel/DataCollector/Util/ValueExporter.phpnu�[���PK��ZIYz��(�(C�+gSymfony/Component/HttpKernel/DataCollector/RequestDataCollector.phpnu�[���PK��Z����
�
A9UgSymfony/Component/HttpKernel/DataCollector/EventDataCollector.phpnu�[���PK��ZƏGV��@*`gSymfony/Component/HttpKernel/DataCollector/TimeDataCollector.phpnu�[���PK��Zn�--<8mgSymfony/Component/HttpKernel/DataCollector/DataCollector.phpnu�[���PK��Z(���;	;	B�rgSymfony/Component/HttpKernel/DataCollector/MemoryDataCollector.phpnu�[���PK��Z^/|GooG~|gSymfony/Component/HttpKernel/Controller/ControllerResolverInterface.phpnu�[���PK��Z��|�Gd�gSymfony/Component/HttpKernel/Controller/TraceableControllerResolver.phpnu�[���PK��Z�xXX?�gSymfony/Component/HttpKernel/Controller/ControllerReference.phpnu�[���PK��ZNC��tt>��gSymfony/Component/HttpKernel/Controller/ControllerResolver.phpnu�[���PK��Z;��M��>��gSymfony/Component/HttpKernel/DependencyInjection/Extension.phpnu�[���PK��Z�6�V
V
M�gSymfony/Component/HttpKernel/DependencyInjection/ContainerAwareHttpKernel.phpnu�[���PK��Z�k���J��gSymfony/Component/HttpKernel/DependencyInjection/RegisterListenersPass.phpnu�[���PK��Z���u__J�gSymfony/Component/HttpKernel/DependencyInjection/ConfigurableExtension.phpnu�[���PK��Z&!#ffT��gSymfony/Component/HttpKernel/DependencyInjection/MergeExtensionConfigurationPass.phpnu�[���PK��ZQNR��J��gSymfony/Component/HttpKernel/DependencyInjection/AddClassesToCachePass.phpnu�[���PK��Z���a��9�gSymfony/Component/ClassLoader/ApcUniversalClassLoader.phpnu�[���PK��Z��PЩ
�
3u�gSymfony/Component/ClassLoader/XcacheClassLoader.phpnu�[���PK��Z"�K�UU,��gSymfony/Component/ClassLoader/autoloader.phpnu�[���PK��Z��A���02�gSymfony/Component/ClassLoader/MapClassLoader.phpnu�[���PK��Zw�!�));��gSymfony/Component/ClassLoader/DebugUniversalClassLoader.phpnu�[���PK��Z�v�	.	.7#�gSymfony/Component/ClassLoader/ClassCollectionLoader.phpnu�[���PK��Z�a.e"e"6�-hSymfony/Component/ClassLoader/UniversalClassLoader.phpnu�[���PK��Z��S�

2^PhSymfony/Component/ClassLoader/DebugClassLoader.phpnu�[���PK��Z��O���5�]hSymfony/Component/ClassLoader/WinCacheClassLoader.phpnu�[���PK��Z�?wy�
�
34mhSymfony/Component/ClassLoader/ClassMapGenerator.phpnu�[���PK��ZlO�ݫ�0i{hSymfony/Component/ClassLoader/ApcClassLoader.phpnu�[���PK��Zv��'��-t�hSymfony/Component/ClassLoader/ClassLoader.phpnu�[���PK��Z��]
I
I
:S�hSymfony/Component/DependencyInjection/SimpleXMLElement.phpnu�[���PK��Zl5����/�hSymfony/Component/DependencyInjection/Alias.phpnu�[���PK��Z���Ma�hSymfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.phpnu�[���PK��Z��ҳ��H��hSymfony/Component/DependencyInjection/LazyProxy/PhpDumper/NullDumper.phpnu�[���PK��Z����JJV%�hSymfony/Component/DependencyInjection/LazyProxy/Instantiator/InstantiatorInterface.phpnu�[���PK��Z�i�nnX��hSymfony/Component/DependencyInjection/LazyProxy/Instantiator/RealServiceInstantiator.phpnu�[���PK��Z$�772��hSymfony/Component/DependencyInjection/Variable.phpnu�[���PK��Z���U" " C��hSymfony/Component/DependencyInjection/ParameterBag/ParameterBag.phpnu�[���PK��ZܮP8�	�	L�hSymfony/Component/DependencyInjection/ParameterBag/ParameterBagInterface.phpnu�[���PK��Zך�I>�hSymfony/Component/DependencyInjection/ParameterBag/FrozenParameterBag.phpnu�[���PK��Z�,x�mm/��hSymfony/Component/DependencyInjection/Scope.phpnu�[���PK��Z��]]4��hSymfony/Component/DependencyInjection/autoloader.phpnu�[���PK��Z_��J8DiSymfony/Component/DependencyInjection/ScopeInterface.phpnu�[���PK��Z�BtBBJ�iSymfony/Component/DependencyInjection/IntrospectableContainerInterface.phpnu�[���PK��Z
O�,��J�iSymfony/Component/DependencyInjection/Exception/BadMethodCallException.phpnu�[���PK��Z����L�iSymfony/Component/DependencyInjection/Exception/ServiceNotFoundException.phpnu�[���PK��Z�{����H	iSymfony/Component/DependencyInjection/Exception/OutOfBoundsException.phpnu�[���PK��Z��9FOiSymfony/Component/DependencyInjection/Exception/ExceptionInterface.phpnu�[���PK��Z�
+��D�iSymfony/Component/DependencyInjection/Exception/RuntimeException.phpnu�[���PK��Z��\�
�
N6iSymfony/Component/DependencyInjection/Exception/ParameterNotFoundException.phpnu�[���PK��ZI_���Jv!iSymfony/Component/DependencyInjection/Exception/InactiveScopeException.phpnu�[���PK��Z���z��S�%iSymfony/Component/DependencyInjection/Exception/ScopeWideningInjectionException.phpnu�[���PK��Zl.��B�-iSymfony/Component/DependencyInjection/Exception/LogicException.phpnu�[���PK��Z��]���U&0iSymfony/Component/DependencyInjection/Exception/ServiceCircularReferenceException.phpnu�[���PK��Z��L�4iSymfony/Component/DependencyInjection/Exception/InvalidArgumentException.phpnu�[���PK��Z= ԥ�S37iSymfony/Component/DependencyInjection/Exception/ScopeCrossingInjectionException.phpnu�[���PK��Z�qB��W[?iSymfony/Component/DependencyInjection/Exception/ParameterCircularReferenceException.phpnu�[���PK��Zq8I���A�CiSymfony/Component/DependencyInjection/ContainerAwareInterface.phpnu�[���PK��Z-&�����:�FiSymfony/Component/DependencyInjection/ContainerBuilder.phpnu�[���PK��Z��c!89894��iSymfony/Component/DependencyInjection/Definition.phpnu�[���PK��Z�u�ii8HjSymfony/Component/DependencyInjection/ContainerAware.phpnu�[���PK��Z�H8��=jSymfony/Component/DependencyInjection/ContainerAwareTrait.phpnu�[���PK��Z����By
jSymfony/Component/DependencyInjection/TaggedContainerInterface.phpnu�[���PK��Z��A�:$:$;�
jSymfony/Component/DependencyInjection/Dumper/YamlDumper.phpnu�[���PK��ZN/�++7}2jSymfony/Component/DependencyInjection/Dumper/Dumper.phpnu�[���PK��Z����%�%?6jSymfony/Component/DependencyInjection/Dumper/GraphvizDumper.phpnu�[���PK��Z"�^� � �:y\jSymfony/Component/DependencyInjection/Dumper/PhpDumper.phpnu�[���PK��Z}���@	kSymfony/Component/DependencyInjection/Dumper/DumperInterface.phpnu�[���PK��Z���*�*:PkSymfony/Component/DependencyInjection/Dumper/XmlDumper.phpnu�[���PK��Z;Yޯ��<U7kSymfony/Component/DependencyInjection/ExpressionLanguage.phpnu�[���PK��ZU穌PP=�<kSymfony/Component/DependencyInjection/DefinitionDecorator.phpnu�[���PK��Z-R�],,3=OkSymfony/Component/DependencyInjection/Reference.phpnu�[���PK��ZU��a--;�UkSymfony/Component/DependencyInjection/Loader/FileLoader.phpnu�[���PK��ZӸBj>dZkSymfony/Component/DependencyInjection/Loader/IniFileLoader.phpnu�[���PK��Z�
���>�akSymfony/Component/DependencyInjection/Loader/ClosureLoader.phpnu�[���PK��Z���((>PhkSymfony/Component/DependencyInjection/Loader/PhpFileLoader.phpnu�[���PK��Z�z#aQ�nkSymfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsdnu�[���PK��ZL����8�8>u�kSymfony/Component/DependencyInjection/Loader/XmlFileLoader.phpnu�[���PK��Z!+���+�+?��kSymfony/Component/DependencyInjection/Loader/YamlFileLoader.phpnu�[���PK��Z��Gp5
5
;��kSymfony/Component/DependencyInjection/Compiler/Compiler.phpnu�[���PK��Z�0є##?m�kSymfony/Component/DependencyInjection/Compiler/RepeatedPass.phpnu�[���PK��ZL��FFU�lSymfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.phpnu�[���PK��ZC�\Z��=�lSymfony/Component/DependencyInjection/Compiler/PassConfig.phpnu�[���PK��Zx�7���L�-lSymfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphEdge.phpnu�[���PK��Z�� �M84lSymfony/Component/DependencyInjection/Compiler/CheckReferenceValidityPass.phpnu�[���PK��Z�i�Z�
�
N�JlSymfony/Component/DependencyInjection/Compiler/RemoveUnusedDefinitionsPass.phpnu�[���PK��Z�!�?��K	VlSymfony/Component/DependencyInjection/Compiler/RemovePrivateAliasesPass.phpnu�[���PK��Z��U*''Pw[lSymfony/Component/DependencyInjection/Compiler/RemoveAbstractDefinitionsPass.phpnu�[���PK��Z��m��O`lSymfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.phpnu�[���PK��Z�iJT�
�
O�rlSymfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.phpnu�[���PK��Z��PPQ��lSymfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.phpnu�[���PK��ZV�%))H��lSymfony/Component/DependencyInjection/Compiler/ServiceReferenceGraph.phpnu�[���PK��Z[���	�	L*�lSymfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphNode.phpnu�[���PK��Z��ϒ��Q��lSymfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.phpnu�[���PK��Z���nnSƸlSymfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.phpnu�[���PK��ZX�\\R��lSymfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.phpnu�[���PK��Z�_9��H��lSymfony/Component/DependencyInjection/Compiler/CompilerPassInterface.phpnu�[���PK��Z��Eų�J��lSymfony/Component/DependencyInjection/Compiler/RepeatablePassInterface.phpnu�[���PK��Zb[_�66_$�lSymfony/Component/DependencyInjection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.phpnu�[���PK��Z@��q	q	N��lSymfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.phpnu�[���PK��Z��ddN��lSymfony/Component/DependencyInjection/Compiler/CheckDefinitionValidityPass.phpnu�[���PK��Z�ۻǠ�O��lSymfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.phpnu�[���PK��Z�����C�mSymfony/Component/DependencyInjection/Compiler/LoggingFormatter.phpnu�[���PK��Z����EBEB3
mSymfony/Component/DependencyInjection/Container.phpnu�[���PK��Z�E�?<�LmSymfony/Component/DependencyInjection/ContainerInterface.phpnu�[���PK��Z�o
�=.\mSymfony/Component/DependencyInjection/Extension/Extension.phpnu�[���PK��ZDS�F�kmSymfony/Component/DependencyInjection/Extension/ExtensionInterface.phpnu�[���PK��Z��J��S$rmSymfony/Component/DependencyInjection/Extension/ConfigurationExtensionInterface.phpnu�[���PK��ZC��oMMM�vmSymfony/Component/DependencyInjection/Extension/PrependExtensionInterface.phpnu�[���PK��Z��F"��3UymSymfony/Component/DependencyInjection/Parameter.phpnu�[���PK��Z��
����
�|mNet/IDNA2.phpnu�[���PK��Z���S66�oNet/IDNA2/Exception.phpnu�[���PK��Z&��#rr oNet/IDNA2/Exception/Nameprep.phpnu�[���PK��Z����Z�Z�
�oNet/Sieve.phpnu�[���PK��Zz��|����w�oNet/SMTP.phpnu�[���PK��Z���NFUFU3�pNet/Socket.phpnu�[���PK��Z
��p.depdblocknu�[���PK��Z'P���
�
��pezc/Base/metadata.phpnu�[���PK��Z:��||��pezc/Base/ezc_bootstrap.phpnu�[���PK��Z�������pezc/Base/options/autoload.phpnu�[���PK��Z|R��)��pezc/Base/structs/repository_directory.phpnu�[���PK��ZS�،��&_qezc/Base/structs/file_find_context.phpnu�[���PK��Zj��_qezc/Base/metadata/tarball.phpnu�[���PK��Zmyv		�qezc/Base/metadata/pear.phpnu�[���PK��Z�B�X�+�++qezc/Base/features.phpnu�[���PK��Zl��VV%�Vqezc/Base/exceptions/setting_value.phpnu�[���PK��ZHDfPEE&�\qezc/Base/exceptions/file_not_found.phpnu�[���PK��Z��Ū��!*aqezc/Base/exceptions/exception.phpnu�[���PK��Z�@c��* eqezc/Base/exceptions/property_not_found.phpnu�[���PK��Zu�3� nhqezc/Base/exceptions/whatever.phpnu�[���PK��Z�b�993�mqezc/Base/exceptions/functionality_not_supported.phpnu�[���PK��Z��ll.`qqezc/Base/exceptions/invalid_callback_class.phpnu�[���PK��Z��!���*uqezc/Base/exceptions/file_io.phpnu�[���PK��Z�ӥ�'I{qezc/Base/exceptions/file_permission.phpnu�[���PK��Z²Gi��E�qezc/Base/exceptions/value.phpnu�[���PK��Z�R�~11+S�qezc/Base/exceptions/extension_not_found.phpnu�[���PK��ZՆ��((&ߎqezc/Base/exceptions/file_exception.phpnu�[���PK��Z�aa+]�qezc/Base/exceptions/property_permission.phpnu�[���PK��Z^M�@@,�qezc/Base/exceptions/invalid_parent_class.phpnu�[���PK��Z�{��QQ6��qezc/Base/exceptions/double_class_repository_prefix.phpnu�[���PK��Z����0l�qezc/Base/exceptions/init_callback_configured.phpnu�[���PK��Z��rr v�qezc/Base/exceptions/autoload.phpnu�[���PK��Z�ם�OO)8�qezc/Base/exceptions/setting_not_found.phpnu�[���PK��ZUJX���qezc/Base/options.phpnu�[���PK��Z��4QEQE�qezc/Base/file.phpnu�[���PK��ZS]�KK�rezc/Base/init.phpnu�[���PK��Z��/��#/rezc/Base/interfaces/persistable.phpnu�[���PK��Z4�ei��"xrezc/Base/interfaces/exportable.phpnu�[���PK��ZPBs|��1trezc/Base/interfaces/configuration_initializer.phpnu�[���PK��Z�%�NN["rezc/Base/base_autoload.phpnu�[���PK��Z�xr44�.rezc/Base/struct.phpnu�[���PK��Z��<�V�Vj2rezc/Base/base.phpnu�[���PK��Z�B!)s,s,s�rezc/ConsoleTools/table/row.phpnu�[���PK��Z'�rw��4�rezc/ConsoleTools/table/cell.phpnu�[���PK��Z��\Ѫ7�7 ��rezc/ConsoleTools/progressbar.phpnu�[���PK��Z	L�^zsezc/ConsoleTools/statusbar.phpnu�[���PK��Z5���tt%�sezc/ConsoleTools/console_autoload.phpnu�[���PK��Z���O��!�7sezc/ConsoleTools/tools/string.phpnu�[���PK��Z;o�!"�Msezc/ConsoleTools/dialog_viewer.phpnu�[���PK��Z����+IUsezc/ConsoleTools/dialog/question_dialog.phpnu�[���PK��ZegO���<�usezc/ConsoleTools/dialog/validators/question_dialog_regex.phpnu�[���PK��Z��,M??;͉sezc/ConsoleTools/dialog/validators/question_dialog_type.phpnu�[���PK��Z�����:w�sezc/ConsoleTools/dialog/validators/menu_dialog_default.phpnu�[���PK��Z��-�>b�sezc/ConsoleTools/dialog/validators/question_dialog_mapping.phpnu�[���PK��ZH�!���A��sezc/ConsoleTools/dialog/validators/question_dialog_collection.phpnu�[���PK��Zkx2���'-�sezc/ConsoleTools/dialog/menu_dialog.phpnu�[���PK��Z��%p%pftezc/ConsoleTools/table.phpnu�[���PK��Z�,���,�vtezc/ConsoleTools/options/question_dialog.phpnu�[���PK��Zͅ���(�tezc/ConsoleTools/options/progressbar.phpnu�[���PK��Z��y��&Y�tezc/ConsoleTools/options/statusbar.phpnu�[���PK��Z��88HH"P�tezc/ConsoleTools/options/table.phpnu�[���PK��Z*��..#�tezc/ConsoleTools/options/dialog.phpnu�[���PK��Z��BB,k�tezc/ConsoleTools/options/progressmonitor.phpnu�[���PK��Z'��J

#	�tezc/ConsoleTools/options/output.phpnu�[���PK��Z���Q��(��tezc/ConsoleTools/options/menu_dialog.phpnu�[���PK��Z��c�gg*��tezc/ConsoleTools/structs/output_format.phpnu�[���PK��Z#�j�''+y�tezc/ConsoleTools/structs/output_formats.phpnu�[���PK��Z�!{D��(�uezc/ConsoleTools/structs/option_rule.phpnu�[���PK��Z\)�|��1'uezc/ConsoleTools/exceptions/argument_too_many.phpnu�[���PK��Z�:�<&+uezc/ConsoleTools/exceptions/option_string_not_wellformed.phpnu�[���PK��Z�%�agg:�.uezc/ConsoleTools/exceptions/option_mandatory_violation.phpnu�[���PK��ZJ�8��&n2uezc/ConsoleTools/exceptions/option.phpnu�[���PK��Z�����<D5uezc/ConsoleTools/exceptions/argument_mandatory_violation.phpnu�[���PK��Z��:49uezc/ConsoleTools/exceptions/option_exclusion_violation.phpnu�[���PK��Z����5�>uezc/ConsoleTools/exceptions/option_type_violation.phpnu�[���PK��Z7���)Duezc/ConsoleTools/exceptions/exception.phpnu�[���PK��Ze�8##1Fuezc/ConsoleTools/exceptions/option_not_exists.phpnu�[���PK��Za��rr7�Iuezc/ConsoleTools/exceptions/argument_type_violation.phpnu�[���PK��ZX�XDD;dNuezc/ConsoleTools/exceptions/argument_already_registered.phpnu�[���PK��Z] 5��(Uuezc/ConsoleTools/exceptions/argument.phpnu�[���PK��Z��ī�2�Wuezc/ConsoleTools/exceptions/no_position_stored.phpnu�[���PK��Z a�3[uezc/ConsoleTools/exceptions/invalid_option_name.phpnu�[���PK��Z|�����9}^uezc/ConsoleTools/exceptions/option_already_registered.phpnu�[���PK��Z�J���:�auezc/ConsoleTools/exceptions/option_arguments_violation.phpnu�[���PK��Z�BW9��5�euezc/ConsoleTools/exceptions/invalid_output_target.phpnu�[���PK��Z��H��6)iuezc/ConsoleTools/exceptions/no_valid_dialog_result.phpnu�[���PK��Z=��?��,Rluezc/ConsoleTools/exceptions/dialog_abort.phpnu�[���PK��Z�ř��4douezc/ConsoleTools/exceptions/option_missing_value.phpnu�[���PK��Z��;Msuezc/ConsoleTools/exceptions/option_dependency_violation.phpnu�[���PK��Zs��

/�xuezc/ConsoleTools/exceptions/option_no_alias.phpnu�[���PK��Z��vv61|uezc/ConsoleTools/exceptions/option_too_many_values.phpnu�[���PK��Z=	�R�L�L!
�uezc/ConsoleTools/input/option.phpnu�[���PK��Z
t�^^$�uezc/ConsoleTools/input/arguments.phpnu�[���PK��Z�%�663��uezc/ConsoleTools/input/help_generators/standard.phpnu�[���PK��Z�p���#F"vezc/ConsoleTools/input/argument.phpnu�[���PK��Z�&�T��.�<vezc/ConsoleTools/input/validators/standard.phpnu�[���PK��ZT\�G�G��Qvezc/ConsoleTools/input.phpnu�[���PK��Z�Jq�VV$Kwezc/ConsoleTools/progressmonitor.phpnu�[���PK��ZwQO~4�wezc/ConsoleTools/interfaces/input_help_generator.phpnu�[���PK��Z�9c"9]0wezc/ConsoleTools/interfaces/question_dialog_validator.phpnu�[���PK��Z%uu/�3wezc/ConsoleTools/interfaces/input_validator.phpnu�[���PK��Z�+���5�8wezc/ConsoleTools/interfaces/menu_dialog_validator.phpnu�[���PK��ZA�
NS
S
&�;wezc/ConsoleTools/interfaces/dialog.phpnu�[���PK��Ze��ެ�01Fwezc/ConsoleTools/interfaces/dialog_validator.phpnu�[���PK��Z���4�J�J=Lwezc/ConsoleTools/output.phpnu�[���PK��Zunš�w�wA�wezc/Archive/archive.phpnu�[���PK��ZԢ"$fIfI|xezc/Archive/file/block_file.phpnu�[���PK��Z�cp'
(
(#1Yxezc/Archive/file/character_file.phpnu�[���PK��Z$�^�3�3��xezc/Archive/file/file.phpnu�[���PK��Z��5�
�
 ��xezc/Archive/archive_autoload.phpnu�[���PK��ZU��+77��xezc/Archive/utils/stat_mode.phpnu�[���PK��Z��0���8�xezc/Archive/utils/checksums.phpnu�[���PK��Z	�z��/�xezc/Archive/utils/file_type.phpnu�[���PK��Z}�sb�	�	B�xezc/Archive/options/archive.phpnu�[���PK��Zf� S	S	0yezc/Archive/structs/file.phpnu�[���PK��Z�L��<< �yezc/Archive/exceptions/empty.phpnu�[���PK��Z�����'[yezc/Archive/exceptions/unknown_type.phpnu�[���PK��Z�G��MM$�yezc/Archive/exceptions/exception.phpnu�[���PK��Z&Y���#)yezc/Archive/exceptions/checksum.phpnu�[���PK��Z�0dii%)yezc/Archive/exceptions/block_size.phpnu�[���PK��Z�N�8TT �yezc/Archive/exceptions/value.phpnu�[���PK��Z�9+II�"yezc/Archive/exceptions/io.phpnu�[���PK��Z}�H���-!%yezc/Archive/exceptions/internal_exception.phpnu�[���PK��Z �����'(yezc/Archive/exceptions/entry_prefix.phpnu�[���PK��Z�h��A�AY+yezc/Archive/entry.phpnu�[���PK��Z�\�^G^G-"myezc/Archive/zip/headers/central_directory.phpnu�[���PK��ZK���`c`c&ݴyezc/Archive/zip/headers/local_file.phpnu�[���PK��Z�
�,�#�#1�zezc/Archive/zip/headers/central_directory_end.phpnu�[���PK��ZXA�V�V�<zezc/Archive/zip/zip.phpnu�[���PK��Z�<��#˓zezc/Archive/interfaces/callback.phpnu�[���PK��Z�靽�	�	��zezc/Archive/tar/pax.phpnu�[���PK��Z�31��	�	��zezc/Archive/tar/ustar.phpnu�[���PK��Z=��

��zezc/Archive/tar/gnu.phpnu�[���PK��Z�$�����zezc/Archive/tar/headers/pax.phpnu�[���PK��Z�M��9�9!�zezc/Archive/tar/headers/ustar.phpnu�[���PK��ZNv�nn>{ezc/Archive/tar/headers/gnu.phpnu�[���PK��Z^���8�8�{ezc/Archive/tar/headers/v7.phpnu�[���PK��Z���BLBL�L{ezc/Archive/tar/v7.phpnu�[���PK��Z��
--{�{ezc/File/file_autoload.phpnu�[���PK��Z��K���{ezc/File/file.phpnu�[���PK��Z��5�
�
!.�{ezc/autoload/archive_autoload.phpnu�[���PK��Z5���tt!-�{ezc/autoload/console_autoload.phpnu�[���PK��Z��
--�{ezc/autoload/file_autoload.phpnu�[���PK��Z�%�NNm�{ezc/autoload/base_autoload.phpnu�[���PK��Z���=YY	�{Archive/Tar.phpnu�[���PK��Z�/f��P)}File/MARCBASE.phpnu�[���PK��Z5F	'�"�"=}File/MARCXML.phpnu�[���PK��ZSbw�{7{7
�_}File/MARC.phpnu�[���PK��Z�9g4xUxU��}File/MARC/Record.phpnu�[���PK��Z(#�~��h�}File/MARC/Exception.phpnu�[���PK��Z�S��hh5~File/MARC/List.phpnu�[���PK��Z�+�����&~File/MARC/Field.phpnu�[���PK��Z�IC�(A(A�@~File/MARC/Lint/CodeData.phpnu�[���PK��ZR��A;A;a�~File/MARC/Data_Field.phpnu�[���PK��Zlz�`�~File/MARC/Control_Field.phpnu�[���PK��ZɌ5��9�9L�~File/MARC/Lint.phpnu�[���PK��Z7�*c��Y
�File/MARC/Subfield.phpnu�[���PK��Z�1����5a!�test/Structures_LinkedList/tests/single_link_007.phptnu�[���PK��Z�Z�x��5�&�test/Structures_LinkedList/tests/single_link_002.phptnu�[���PK��Z(��  .�)�test/Structures_LinkedList/tests/link_004.phptnu�[���PK��Z���|��5,�test/Structures_LinkedList/tests/SingleLinkTester.phpnu�[���PK��Z髂[��5N.�test/Structures_LinkedList/tests/single_link_006.phptnu�[���PK��Zs��DHH.�2�test/Structures_LinkedList/tests/link_007.phptnu�[���PK��Z�����.E8�test/Structures_LinkedList/tests/link_005.phptnu�[���PK��Z�#,E��5~=�test/Structures_LinkedList/tests/single_link_005.phptnu�[���PK��Z����/�B�test/Structures_LinkedList/tests/LinkTester.phpnu�[���PK��Z� ���.E�test/Structures_LinkedList/tests/link_001.phptnu�[���PK��Z骗���.II�test/Structures_LinkedList/tests/link_006.phptnu�[���PK��Z��)��.�M�test/Structures_LinkedList/tests/link_002.phptnu�[���PK��Z�4����5�P�test/Structures_LinkedList/tests/single_link_001.phptnu�[���PK��Z)�y--5�T�test/Structures_LinkedList/tests/single_link_004.phptnu�[���PK��Z�K��5fW�test/Structures_LinkedList/tests/single_link_003.phptnu�[���PK��Z�o���.�[�test/Structures_LinkedList/tests/link_003.phptnu�[���PK��Z�x`(��`�test/Mail/tests/bug17317.phptnu�[���PK��Z��q/���a�test/Mail/tests/13659.phptnu�[���PK��Z�ó����d�test/Mail/tests/9137_2.phptnu�[���PK��Zw������i�test/Mail/tests/smtp_error.phptnu�[���PK��Z)f$�!!"m�test/Mail/tests/rfc822.phptnu�[���PK��Z8x�����x�test/Mail/tests/bug17178.phptnu�[���PK��Z*�����y�test/Mail/tests/9137.phptnu�[���PK��ZF�}�test/Finder/Symfony/Component/Finder/Tests/Fixtures/with space/foo.txtnu�[���PK��ZAg~�test/Finder/Symfony/Component/Finder/Tests/Fixtures/A/B/C/abc.datnu�[���PK��Z>�~�test/Finder/Symfony/Component/Finder/Tests/Fixtures/A/B/ab.datnu�[���PK��Z;F�test/Finder/Symfony/Component/Finder/Tests/Fixtures/A/a.datnu�[���PK��Z9��test/Finder/Symfony/Component/Finder/Tests/Fixtures/one/anu�[���PK��Z@��test/Finder/Symfony/Component/Finder/Tests/Fixtures/one/b/d.neonnu�[���PK��Z@���test/Finder/Symfony/Component/Finder/Tests/Fixtures/one/b/c.neonnu�[���PK��Zo�5|=���test/Finder/Symfony/Component/Finder/Tests/Fixtures/dolor.txtnu�[���PK��Z'���))=���test/Finder/Symfony/Component/Finder/Tests/Fixtures/ipsum.txtnu�[���PK��Z��55=��test/Finder/Symfony/Component/Finder/Tests/Fixtures/lorem.txtnu�[���PK��ZE���test/Finder/Symfony/Component/Finder/Tests/Fixtures/copy/A/a.dat.copynu�[���PK��ZK1��test/Finder/Symfony/Component/Finder/Tests/Fixtures/copy/A/B/C/abc.dat.copynu�[���PK��ZH���test/Finder/Symfony/Component/Finder/Tests/Fixtures/copy/A/B/ab.dat.copynu�[���PK��Z˟�ׄ	�	L$��test/Finder/Symfony/Component/Finder/Tests/Comparator/DateComparatorTest.phpnu�[���PK��Z�W.�//N$��test/Finder/Symfony/Component/Finder/Tests/Comparator/NumberComparatorTest.phpnu�[���PK��Z��Ŗ�Hќ�test/Finder/Symfony/Component/Finder/Tests/Comparator/ComparatorTest.phpnu�[���PK��Z6G��mwmw9ߤ�test/Finder/Symfony/Component/Finder/Tests/FinderTest.phpnu�[���PK��Z+드44L��test/Finder/Symfony/Component/Finder/Tests/Iterator/RealIteratorTestCase.phpnu�[���PK��Z:@���
�
Me(�test/Finder/Symfony/Component/Finder/Tests/Iterator/FilePathsIteratorTest.phpnu�[���PK��Z�qbe�
�
U�3�test/Finder/Symfony/Component/Finder/Tests/Iterator/FilecontentFilterIteratorTest.phpnu�[���PK��ZYbk�MMR�>�test/Finder/Symfony/Component/Finder/Tests/Iterator/FileTypeFilterIteratorTest.phpnu�[���PK��Z���Ŋ�V�E�test/Finder/Symfony/Component/Finder/Tests/Iterator/RecursiveDirectoryIteratorTest.phpnu�[���PK��Z4/aaZ�N�test/Finder/Symfony/Component/Finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.phpnu�[���PK��Z��nI��N�U�test/Finder/Symfony/Component/Finder/Tests/Iterator/PathFilterIteratorTest.phpnu�[���PK��Z��++V%c�test/Finder/Symfony/Component/Finder/Tests/Iterator/MultiplePcreFilterIteratorTest.phpnu�[���PK��Z�7Wa	a	L�k�test/Finder/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.phpnu�[���PK��Z�7���R�u�test/Finder/Symfony/Component/Finder/Tests/Iterator/FilenameFilterIteratorTest.phpnu�[���PK��Z߫����P-|�test/Finder/Symfony/Component/Finder/Tests/Iterator/CustomFilterIteratorTest.phpnu�[���PK��Z��o�
�
G���test/Finder/Symfony/Component/Finder/Tests/Iterator/MockSplFileInfo.phpnu�[���PK��ZZo�*))Tҏ�test/Finder/Symfony/Component/Finder/Tests/Iterator/DepthRangeFilterIteratorTest.phpnu�[���PK��Z�S�@��test/Finder/Symfony/Component/Finder/Tests/Iterator/Iterator.phpnu�[���PK��Z���FS��test/Finder/Symfony/Component/Finder/Tests/Iterator/SizeRangeFilterIteratorTest.phpnu�[���PK��Z-���66J���test/Finder/Symfony/Component/Finder/Tests/Iterator/FilterIteratorTest.phpnu�[���PK��Z{�)\o	o	H3��test/Finder/Symfony/Component/Finder/Tests/Iterator/IteratorTestCase.phpnu�[���PK��Z�[+((L��test/Finder/Symfony/Component/Finder/Tests/Iterator/MockFileListIterator.phpnu�[���PK��Z(��g==S���test/Finder/Symfony/Component/Finder/Tests/Iterator/DateRangeFilterIteratorTest.phpnu�[���PK��Z�|ߐ�H~��test/Finder/Symfony/Component/Finder/Tests/Expression/ExpressionTest.phpnu�[���PK��Z�9]��C�Ătest/Finder/Symfony/Component/Finder/Tests/Expression/RegexTest.phpnu�[���PK��Z7u��ttB�Ԃtest/Finder/Symfony/Component/Finder/Tests/Expression/GlobTest.phpnu�[���PK��Z`�2��G�ۂtest/Finder/Symfony/Component/Finder/Tests/FakeAdapter/NamedAdapter.phpnu�[���PK��ZI����G�߂test/Finder/Symfony/Component/Finder/Tests/FakeAdapter/DummyAdapter.phpnu�[���PK��Z/��00M4�test/Finder/Symfony/Component/Finder/Tests/FakeAdapter/UnsupportedAdapter.phpnu�[���PK��Z��mmI��test/Finder/Symfony/Component/Finder/Tests/FakeAdapter/FailingAdapter.phpnu�[���PK��Z���555��test/Finder/Symfony/Component/Finder/phpunit.xml.distnu�[���PK��Z9���Ka�test/TwigBridge/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.phpnu�[���PK��Z�O#�''O���test/TwigBridge/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.phpnu�[���PK��Z�h�H	H	@T$�test/TwigBridge/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.phpnu�[���PK��Zͅi�99<.�test/TwigBridge/Symfony/Bridge/Twig/Tests/TwigEngineTest.phpnu�[���PK��Zk�K�a�6�test/TwigBridge/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationDefaultDomainNodeVisitorTest.phpnu�[���PK��Z¶
���TMC�test/TwigBridge/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationNodeVisitorTest.phpnu�[���PK��Zj|$		J�L�test/TwigBridge/Symfony/Bridge/Twig/Tests/NodeVisitor/TwigNodeProvider.phpnu�[���PK��Z�6��!!CAV�test/TwigBridge/Symfony/Bridge/Twig/Tests/NodeVisitor/ScopeTest.phpnu�[���PK��Z#�
�
R�X�test/TwigBridge/Symfony/Bridge/Twig/Tests/TokenParser/FormThemeTokenParserTest.phpnu�[���PK��Z��x��LTg�test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/RoutingExtensionTest.phpnu�[���PK��Z:��WWT�o�test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.phpnu�[���PK��Zt�9A
A
Oq~�test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.phpnu�[���PK��Z�V�%33R1��test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/page_dynamic_extends.html.twignu�[���PK��Z�]��U扃test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubFilesystemLoader.phpnu�[���PK��Z*��n**O���test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubTranslator.phpnu�[���PK��Z̙nsG,��test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/theme_use.html.twignu�[���PK��Z�+����I���test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/CodeExtensionTest.phpnu�[���PK��Z%o��	�	N$��test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/StopwatchExtensionTest.phpnu�[���PK��Z��ߋ��Oe��test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/ExpressionExtensionTest.phpnu�[���PK��Z��,'KKJe��test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/parent_label.html.twignu�[���PK��Z�����P*��test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.phpnu�[���PK��Z(���CNǃtest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/theme.html.twignu�[���PK��Z��i�!!R�ȃtest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.phpnu�[���PK��ZҺ
�VVIS�test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/child_label.html.twignu�[���PK��Z�tdK"�test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/theme_extends.html.twignu�[���PK��Z��b���L��test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/custom_widgets.html.twignu�[���PK��ZPcc4��test/TwigBridge/Symfony/Bridge/Twig/phpunit.xml.distnu�[���PK��Zh�9=UUO��test/Translation/Symfony/Component/Translation/Tests/IdentityTranslatorTest.phpnu�[���PK��Z���*|1|1Gr��test/Translation/Symfony/Component/Translation/Tests/TranslatorTest.phpnu�[���PK��Zl.!���Oe)�test/Translation/Symfony/Component/Translation/Tests/PluralizationRulesTest.phpnu�[���PK��Z�h�l��T�9�test/Translation/Symfony/Component/Translation/Tests/Catalogue/DiffOperationTest.phpnu�[���PK��Z$͒ϛ�U�A�test/Translation/Symfony/Component/Translation/Tests/Catalogue/MergeOperationTest.phpnu�[���PK��Zײ�))X�I�test/Translation/Symfony/Component/Translation/Tests/Catalogue/AbstractOperationTest.phpnu�[���PK��Z0�2��E�R�test/Translation/Symfony/Component/Translation/Tests/IntervalTest.phpnu�[���PK��Z��V��Q�W�test/Translation/Symfony/Component/Translation/Tests/Dumper/IniFileDumperTest.phpnu�[���PK��Z`��׹�S�[�test/Translation/Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.phpnu�[���PK��Z����Q`�test/Translation/Symfony/Component/Translation/Tests/Dumper/PhpFileDumperTest.phpnu�[���PK��Z����R5d�test/Translation/Symfony/Component/Translation/Tests/Dumper/YamlFileDumperTest.phpnu�[���PK��Zub/��TZh�test/Translation/Symfony/Component/Translation/Tests/Dumper/IcuResFileDumperTest.phpnu�[���PK��Z�����Q�m�test/Translation/Symfony/Component/Translation/Tests/Dumper/CsvFileDumperTest.phpnu�[���PK��Z�����P�q�test/Translation/Symfony/Component/Translation/Tests/Dumper/MoFileDumperTest.phpnu�[���PK��Z�BY���P�u�test/Translation/Symfony/Component/Translation/Tests/Dumper/QtFileDumperTest.phpnu�[���PK��Z��IIRz�test/Translation/Symfony/Component/Translation/Tests/Dumper/JsonFileDumperTest.phpnu�[���PK��Z&��ݙ�P�~�test/Translation/Symfony/Component/Translation/Tests/Dumper/PoFileDumperTest.phpnu�[���PK��Z8^�k��S�test/Translation/Symfony/Component/Translation/Tests/Loader/XliffFileLoaderTest.phpnu�[���PK��Z��|=��P��test/Translation/Symfony/Component/Translation/Tests/Loader/QtFileLoaderTest.phpnu�[���PK��Z���3Q$��test/Translation/Symfony/Component/Translation/Tests/Loader/LocalizedTestCase.phpnu�[���PK��Z���Q���test/Translation/Symfony/Component/Translation/Tests/Loader/PhpFileLoaderTest.phpnu�[���PK��Z~�		RS��test/Translation/Symfony/Component/Translation/Tests/Loader/YamlFileLoaderTest.phpnu�[���PK��Z�$X

P�test/Translation/Symfony/Component/Translation/Tests/Loader/PoFileLoaderTest.phpnu�[���PK��Z[����Q���test/Translation/Symfony/Component/Translation/Tests/Loader/CsvFileLoaderTest.phpnu�[���PK��Z/�݂�Q���test/Translation/Symfony/Component/Translation/Tests/Loader/IniFileLoaderTest.phpnu�[���PK��Z��j��T�Ȅtest/Translation/Symfony/Component/Translation/Tests/Loader/IcuResFileLoaderTest.phpnu�[���PK��ZP�e��RЄtest/Translation/Symfony/Component/Translation/Tests/Loader/JsonFileLoaderTest.phpnu�[���PK��Z����Pلtest/Translation/Symfony/Component/Translation/Tests/Loader/MoFileLoaderTest.phpnu�[���PK��Z�)�	�	�	T��test/Translation/Symfony/Component/Translation/Tests/Loader/IcuDatFileLoaderTest.phpnu�[���PK��ZM��MD�test/Translation/Symfony/Component/Translation/Tests/MessageCatalogueTest.phpnu�[���PK��Z���  L��test/Translation/Symfony/Component/Translation/Tests/MessageSelectorTest.phpnu�[���PK��Z��W44Jx �test/Translation/Symfony/Component/Translation/Tests/fixtures/resources.monu�[���PK��Z!f����J&!�test/Translation/Symfony/Component/Translation/Tests/fixtures/resources.ponu�[���PK��Z=BsR-"�test/Translation/Symfony/Component/Translation/Tests/fixtures/empty-translation.ponu�[���PK��ZG�"�test/Translation/Symfony/Component/Translation/Tests/fixtures/empty.ininu�[���PK��ZYڸCQ=#�test/Translation/Symfony/Component/Translation/Tests/fixtures/resources-clean.xlfnu�[���PK��Z�:�++K�%�test/Translation/Symfony/Component/Translation/Tests/fixtures/resources.phpnu�[���PK��ZGg&�test/Translation/Symfony/Component/Translation/Tests/fixtures/empty.ymlnu�[���PK��ZH�&�test/Translation/Symfony/Component/Translation/Tests/fixtures/empty.jsonnu�[���PK��ZY���44IV'�test/Translation/Symfony/Component/Translation/Tests/fixtures/resname.xlfnu�[���PK��ZG*�test/Translation/Symfony/Component/Translation/Tests/fixtures/empty.xlfnu�[���PK��Z;.�BBHz*�test/Translation/Symfony/Component/Translation/Tests/fixtures/plurals.ponu�[���PK��Z�ߞL4+�test/Translation/Symfony/Component/Translation/Tests/fixtures/malformed.jsonnu�[���PK��Z�.�zzK�+�test/Translation/Symfony/Component/Translation/Tests/fixtures/resources.xlfnu�[���PK��Z�e2~K�.�test/Translation/Symfony/Component/Translation/Tests/fixtures/non-valid.ymlnu�[���PK��Z�'�F

K:/�test/Translation/Symfony/Component/Translation/Tests/fixtures/resources.ininu�[���PK��Z� TTK�/�test/Translation/Symfony/Component/Translation/Tests/fixtures/non-valid.xlfnu�[���PK��ZF�1�test/Translation/Symfony/Component/Translation/Tests/fixtures/empty.ponu�[���PK��ZG2�test/Translation/Symfony/Component/Translation/Tests/fixtures/empty.csvnu�[���PK��Z*֔�JJH{2�test/Translation/Symfony/Component/Translation/Tests/fixtures/plurals.monu�[���PK��Z+�L�TTW=3�test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/res/en.resnu�[���PK��Zw˦(||W4�test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/fr.resnu�[���PK��ZX��**W5�test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/fr.txtnu�[���PK��ZrQ�``^�5�test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/resources.datnu�[���PK��Z�M�RxxW�7�test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/en.resnu�[���PK��Z�g.�`�8�test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/packagelist.txtnu�[���PK��Z�25�''WW9�test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/en.txtnu�[���PK��Z��<�d:�test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/corrupted/resources.datnu�[���PK��ZF�:�test/Translation/Symfony/Component/Translation/Tests/fixtures/empty.monu�[���PK��Z��jjM;�test/Translation/Symfony/Component/Translation/Tests/fixtures/withdoctype.xlfnu�[���PK��Z̉^2��J�<�test/Translation/Symfony/Component/Translation/Tests/fixtures/encoding.xlfnu�[���PK��Z�B$$G@?�test/Translation/Symfony/Component/Translation/Tests/fixtures/valid.csvnu�[���PK��Z����L�?�test/Translation/Symfony/Component/Translation/Tests/fixtures/resources.jsonnu�[���PK��Z�C(���Jk@�test/Translation/Symfony/Component/Translation/Tests/fixtures/resources.tsnu�[���PK��Z/�
��W�A�test/Translation/Symfony/Component/Translation/Tests/fixtures/invalid-xml-resources.xlfnu�[���PK��Z���		KE�test/Translation/Symfony/Component/Translation/Tests/fixtures/resources.ymlnu�[���PK��Z�D��``K�E�test/Translation/Symfony/Component/Translation/Tests/fixtures/resources.csvnu�[���PK��Z^C�	::?{F�test/Translation/Symfony/Component/Translation/phpunit.xml.distnu�[���PK��Z���LLE$J�test/Routing/Symfony/Component/Routing/Tests/Annotation/RouteTest.phpnu�[���PK��Z�%��])])B�P�test/Routing/Symfony/Component/Routing/Tests/RouteCompilerTest.phpnu�[���PK��Z1�d	nnM�z�test/Routing/Symfony/Component/Routing/Tests/Fixtures/CustomXmlFileLoader.phpnu�[���PK��ZC�}�test/Routing/Symfony/Component/Routing/Tests/Fixtures/annotated.phpnu�[���PK��Z?~�test/Routing/Symfony/Component/Routing/Tests/Fixtures/empty.ymlnu�[���PK��Z�/���F�~�test/Routing/Symfony/Component/Routing/Tests/Fixtures/validpattern.ymlnu�[���PK��Z�M��Fہ�test/Routing/Symfony/Component/Routing/Tests/Fixtures/validpattern.xmlnu�[���PK��Z�/�$>>V	��test/Routing/Symfony/Component/Routing/Tests/Fixtures/nonesense_resource_plus_path.ymlnu�[���PK��Z��==F͇�test/Routing/Symfony/Component/Routing/Tests/Fixtures/nonvalidkeys.ymlnu�[���PK��Z�ie��I���test/Routing/Symfony/Component/Routing/Tests/Fixtures/namespaceprefix.xmlnu�[���PK��Z#q��//D���test/Routing/Symfony/Component/Routing/Tests/Fixtures/missing_id.xmlnu�[���PK��Zx'�	11EZ��test/Routing/Symfony/Component/Routing/Tests/Fixtures/withdoctype.xmlnu�[���PK��Z�;h�%%P��test/Routing/Symfony/Component/Routing/Tests/Fixtures/RedirectableUrlMatcher.phpnu�[���PK��Zs��[//F���test/Routing/Symfony/Component/Routing/Tests/Fixtures/missing_path.xmlnu�[���PK��Z�e2~BJ��test/Routing/Symfony/Component/Routing/Tests/Fixtures/nonvalid.ymlnu�[���PK��Zix��77F���test/Routing/Symfony/Component/Routing/Tests/Fixtures/validpattern.phpnu�[���PK��Z�G�V,+,+Mm��test/Routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.phpnu�[���PK��ZT����MÅtest/Routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.phpnu�[���PK��Z@4��P9Ʌtest/Routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.apachenu�[���PK��ZBx�6��P�߅test/Routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.apachenu�[���PK��Zn�k�//M�test/Routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.phpnu�[���PK��Z�p��B��test/Routing/Symfony/Component/Routing/Tests/Fixtures/nonvalid.xmlnu�[���PK��Zͼ�n!!F��test/Routing/Symfony/Component/Routing/Tests/Fixtures/nonvalidnode.xmlnu�[���PK��ZT��Se�test/Routing/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/BarClass.phpnu�[���PK��Z���GGS��test/Routing/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/FooClass.phpnu�[���PK��Z�zUUX^�test/Routing/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/AbstractClass.phpnu�[���PK��Z�M�tC;�test/Routing/Symfony/Component/Routing/Tests/Fixtures/nonvalid2.ymlnu�[���PK��Z�b�G��test/Routing/Symfony/Component/Routing/Tests/Fixtures/validresource.xmlnu�[���PK��Z��q�GN�test/Routing/Symfony/Component/Routing/Tests/Fixtures/nonvalidroute.xmlnu�[���PK��Z��ϮBBD��test/Routing/Symfony/Component/Routing/Tests/Fixtures/incomplete.ymlnu�[���PK��Z�J?�L� �test/Routing/Symfony/Component/Routing/Tests/Fixtures/special_route_name.ymlnu�[���PK��Z�q�99Y2!�test/Routing/Symfony/Component/Routing/Tests/Fixtures/nonesense_type_without_resource.ymlnu�[���PK��ZjX���G�!�test/Routing/Symfony/Component/Routing/Tests/Fixtures/validresource.ymlnu�[���PK��Z>^#�test/Routing/Symfony/Component/Routing/Tests/Fixtures/foo1.xmlnu�[���PK��Z=�#�test/Routing/Symfony/Component/Routing/Tests/Fixtures/foo.xmlnu�[���PK��Z��/��
�
C9$�test/Routing/Symfony/Component/Routing/Tests/RequestContextTest.phpnu�[���PK��Z���
�
P�2�test/Routing/Symfony/Component/Routing/Tests/Matcher/TraceableUrlMatcherTest.phpnu�[���PK��Zt�kT�B�BG�@�test/Routing/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.phpnu�[���PK��Zȁ@���Z���test/Routing/Symfony/Component/Routing/Tests/Matcher/Dumper/DumperPrefixCollectionTest.phpnu�[���PK��Z)�#0%%T>��test/Routing/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.phpnu�[���PK��ZU���Tù�test/Routing/Symfony/Component/Routing/Tests/Matcher/Dumper/DumperCollectionTest.phpnu�[���PK��Z�IQ��W&��test/Routing/Symfony/Component/Routing/Tests/Matcher/Dumper/ApacheMatcherDumperTest.phpnu�[���PK��Z�̼�aaM�׆test/Routing/Symfony/Component/Routing/Tests/Matcher/ApacheUrlMatcherTest.phpnu�[���PK��ZA ���Sr�test/Routing/Symfony/Component/Routing/Tests/Matcher/RedirectableUrlMatcherTest.phpnu�[���PK��Z%"�?7?7D��test/Routing/Symfony/Component/Routing/Tests/RouteCollectionTest.phpnu�[���PK��Z kl�g�gKM,�test/Routing/Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.phpnu�[���PK��Z������Xo��test/Routing/Symfony/Component/Routing/Tests/Generator/Dumper/PhpGeneratorDumperTest.phpnu�[���PK��Z8!!&GGB餇test/Routing/Symfony/Component/Routing/Tests/CompiledRouteTest.phpnu�[���PK��Z���k��I���test/Routing/Symfony/Component/Routing/Tests/Loader/ClosureLoaderTest.phpnu�[���PK��Z�����Q寇test/Routing/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTest.phpnu�[���PK��Zg�U��I3Çtest/Routing/Symfony/Component/Routing/Tests/Loader/PhpFileLoaderTest.phpnu�[���PK��Z{��t��Jdˇtest/Routing/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.phpnu�[���PK��Z6����U_݇test/Routing/Symfony/Component/Routing/Tests/Loader/AnnotationDirectoryLoaderTest.phpnu�[���PK��ZM�~�##I��test/Routing/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.phpnu�[���PK��Z|�C44T*��test/Routing/Symfony/Component/Routing/Tests/Loader/AbstractAnnotationLoaderTest.phpnu�[���PK��Zu��;P�test/Routing/Symfony/Component/Routing/Tests/Loader/AnnotationFileLoaderTest.phpnu�[���PK��Z��;b�test/Routing/Symfony/Component/Routing/Tests/RouterTest.phpnu�[���PK��Zu��A�,�,:��test/Routing/Symfony/Component/Routing/Tests/RouteTest.phpnu�[���PK��Z~�6673E�test/Routing/Symfony/Component/Routing/phpunit.xml.distnu�[���PK��Z��W8j#j#.�H�test/Structures_Graph/tests/BasicGraphTest.phpnu�[���PK��Z6��:UU5�l�test/Structures_Graph/tests/TopologicalSorterTest.phpnu�[���PK��Z�V���(Rt�test/Structures_Graph/tests/AllTests.phpnu�[���PK��Z���/fv�test/Structures_Graph/tests/AcyclicTestTest.phpnu�[���PK��Z���ii&�{�test/Structures_Graph/tests/helper.incnu�[���PK��Z��+\MMH�}�test/Process/Symfony/Component/Process/Tests/PhpExecutableFinderTest.phpnu�[���PK��Z#�Te��test/Process/Symfony/Component/Process/Tests/PipeStdinInStdoutStdErrStreamSelect.phpnu�[���PK��Z�WKo�
�
Ktest/Process/Symfony/Component/Process/Tests/ProcessFailedExceptionTest.phpnu�[���PK��ZC�u^UUA���test/Process/Symfony/Component/Process/Tests/ProcessUtilsTest.phpnu�[���PK��Z[�VAChChDÜ�test/Process/Symfony/Component/Process/Tests/AbstractProcessTest.phpnu�[���PK��Z=�,j��?z�test/Process/Symfony/Component/Process/Tests/SignalListener.phpnu�[���PK��Z���
��B��test/Process/Symfony/Component/Process/Tests/SimpleProcessTest.phpnu�[���PK��Z�+�v,,CR �test/Process/Symfony/Component/Process/Tests/NonStopableProcess.phpnu�[���PK��Zm�����M�#�test/Process/Symfony/Component/Process/Tests/ProcessInSigchildEnvironment.phpnu�[���PK��Z����L3&�test/Process/Symfony/Component/Process/Tests/SigchildDisabledProcessTest.phpnu�[���PK��ZH��sppC^F�test/Process/Symfony/Component/Process/Tests/ProcessBuilderTest.phpnu�[���PK��Zx[��?A^�test/Process/Symfony/Component/Process/Tests/PhpProcessTest.phpnu�[���PK��Z钊�\\KQa�test/Process/Symfony/Component/Process/Tests/SigchildEnabledProcessTest.phpnu�[���PK��Zp\H7(s�test/Process/Symfony/Component/Process/phpunit.xml.distnu�[���PK��Z2�c�$�$E�v�test/Serializer/Symfony/Component/Serializer/Tests/SerializerTest.phpnu�[���PK��Z�m�))P̛�test/Serializer/Symfony/Component/Serializer/Tests/Normalizer/TestNormalizer.phpnu�[���PK��Z$ѕ�Vu��test/Serializer/Symfony/Component/Serializer/Tests/Normalizer/CustomNormalizerTest.phpnu�[���PK��Z��P1!!\��test/Serializer/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.phpnu�[���PK��Z�qBBR�ɉtest/Serializer/Symfony/Component/Serializer/Tests/Normalizer/TestDenormalizer.phpnu�[���PK��Z��K�__Ku͉test/Serializer/Symfony/Component/Serializer/Tests/Fixtures/ScalarDummy.phpnu�[���PK��Z��_��PO҉test/Serializer/Symfony/Component/Serializer/Tests/Fixtures/TraversableDummy.phpnu�[���PK��ZG��5��\�ԉtest/Serializer/Symfony/Component/Serializer/Tests/Fixtures/NormalizableTraversableDummy.phpnu�[���PK��Z�LY��E�ىtest/Serializer/Symfony/Component/Serializer/Tests/Fixtures/Dummy.phpnu�[���PK��ZY["�uuS9߉test/Serializer/Symfony/Component/Serializer/Tests/Fixtures/DenormalizableDummy.phpnu�[���PK��Zf|�B.B.M1�test/Serializer/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.phpnu�[���PK��ZF��		N��test/Serializer/Symfony/Component/Serializer/Tests/Encoder/JsonEncoderTest.phpnu�[���PK��Z���99=s�test/Serializer/Symfony/Component/Serializer/phpunit.xml.distnu�[���PK��Z�Ǫ���9�test/Locale/Symfony/Component/Locale/Tests/LocaleTest.phpnu�[���PK��Z<��B%�test/Locale/Symfony/Component/Locale/Tests/Stub/StubLocaleTest.phpnu�[���PK��Z+��hh5�+�test/Locale/Symfony/Component/Locale/phpunit.xml.distnu�[���PK��Z�;�I_/�test/Filesystem/Symfony/Component/Filesystem/Tests/FilesystemTestCase.phpnu�[���PK��Z'B 0�o�oE�=�test/Filesystem/Symfony/Component/Filesystem/Tests/FilesystemTest.phpnu�[���PK��Z��í�D ��test/Filesystem/Symfony/Component/Filesystem/Tests/ExceptionTest.phpnu�[���PK��Z�Ejc		=��test/Filesystem/Symfony/Component/Filesystem/phpunit.xml.distnu�[���PK��Z�ag�@<@<B���test/Form/Symfony/Component/Form/Tests/AbstractTableLayoutTest.phpnu�[���PK��Z���KKB=�test/Form/Symfony/Component/Form/Tests/FormPerformanceTestCase.phpnu�[���PK��Z@U���=���test/Form/Symfony/Component/Form/Tests/AbstractLayoutTest.phpnu�[���PK��Z����:lڋtest/Form/Symfony/Component/Form/Tests/Guess/GuessTest.phpnu�[���PK��Z�uEsދtest/Form/Symfony/Component/Form/Tests/Fixtures/CustomArrayObject.phpnu�[���PK��Z�x���:��test/Form/Symfony/Component/Form/Tests/Fixtures/Author.phpnu�[���PK��Z3X�test/Form/Symfony/Component/Form/Tests/Fixtures/foonu�[���PK��Z[��َ�G��test/Form/Symfony/Component/Form/Tests/Fixtures/FooTypeBazExtension.phpnu�[���PK��Z���*��;��test/Form/Symfony/Component/Form/Tests/Fixtures/FooType.phpnu�[���PK��Z:�.z��F�test/Form/Symfony/Component/Form/Tests/Fixtures/AlternatingRowType.phpnu�[���PK��Z֫�v��>��test/Form/Symfony/Component/Form/Tests/Fixtures/AuthorType.phpnu�[���PK��Z#�o>��test/Form/Symfony/Component/Form/Tests/Fixtures/FooSubType.phpnu�[���PK��Z��8���A6��test/Form/Symfony/Component/Form/Tests/Fixtures/TestExtension.phpnu�[���PK��Z��x�

GO�test/Form/Symfony/Component/Form/Tests/Fixtures/FooTypeBarExtension.phpnu�[���PK��Zm^�2++P��test/Form/Symfony/Component/Form/Tests/Fixtures/FooSubTypeWithParentInstance.phpnu�[���PK��Z��!u��G~	�test/Form/Symfony/Component/Form/Tests/Fixtures/FixedFilterListener.phpnu�[���PK��ZŲ��UUH��test/Form/Symfony/Component/Form/Tests/Fixtures/FixedDataTransformer.phpnu�[���PK��ZJ����R�R:X�test/Form/Symfony/Component/Form/Tests/FormFactoryTest.phpnu�[���PK��ZȔfVA6A6Bgh�test/Form/Symfony/Component/Form/Tests/Util/OrderedHashMapTest.phpnu�[���PK��Z�z�nznz;��test/Form/Symfony/Component/Form/Tests/CompoundFormTest.phpnu�[���PK��Z���dA��test/Form/Symfony/Component/Form/Tests/FormFactoryBuilderTest.phpnu�[���PK��Z̈́����;g!�test/Form/Symfony/Component/Form/Tests/FormRegistryTest.phpnu�[���PK��Z]�9�}}9�@�test/Form/Symfony/Component/Form/Tests/FormConfigTest.phpnu�[���PK��Z�>)�bbE�S�test/Form/Symfony/Component/Form/Tests/AbstractRequestHandlerTest.phpnu�[���PK��Zū@d22?xq�test/Form/Symfony/Component/Form/Tests/ResolvedFormTypeTest.phpnu�[���PK��ZO� )KKB���test/Form/Symfony/Component/Form/Tests/FormIntegrationTestCase.phpnu�[���PK��Z��K)ooF���test/Form/Symfony/Component/Form/Tests/CompoundFormPerformanceTest.phpnu�[���PK��Ztٴ��;���test/Form/Symfony/Component/Form/Tests/FormRendererTest.phpnu�[���PK��Z�d�!!C⯍test/Form/Symfony/Component/Form/Tests/NativeRequestHandlerTest.phpnu�[���PK��Z�����:vǍtest/Form/Symfony/Component/Form/Tests/FormBuilderTest.phpnu�[���PK��ZRmhZTZT@��test/Form/Symfony/Component/Form/Tests/AbstractDivLayoutTest.phpnu�[���PK��Zk/6;}8�test/Form/Symfony/Component/Form/Tests/AbstractFormTest.phpnu�[���PK��ZrM�{�{9�D�test/Form/Symfony/Component/Form/Tests/SimpleFormTest.phpnu�[���PK��Zۿt��c��test/Form/Symfony/Component/Form/Tests/Extension/Validator/EventListener/ValidationListenerTest.phpnu�[���PK��Z�EY޵�T�Վtest/Form/Symfony/Component/Form/Tests/Extension/Validator/Util/ServerParamsTest.phpnu�[���PK��Z�l"�	�	W�ێtest/Form/Symfony/Component/Form/Tests/Extension/Validator/ValidatorTypeGuesserTest.phpnu�[���PK��Z��
g��test/Form/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorPerformanceTest.phpnu�[���PK��Zِ�GbGb\��test/Form/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.phpnu�[���PK��Z�$�Ǵ�`TN�test/Form/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationPathTest.phpnu�[���PK��Z�@1�,�,b�l�test/Form/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.phpnu�[���PK��Z`f�[��P˙�test/Form/Symfony/Component/Form/Tests/Extension/Validator/Type/TypeTestCase.phpnu�[���PK��ZY��
xx^��test/Form/Symfony/Component/Form/Tests/Extension/Validator/Type/BaseValidatorExtensionTest.phpnu�[���PK��ZS�m�d��test/Form/Symfony/Component/Form/Tests/Extension/Validator/Type/SubmitTypeValidatorExtensionTest.phpnu�[���PK��Z7>lˉ�b���test/Form/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.phpnu�[���PK��Z1���� � i���test/Form/Symfony/Component/Form/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.phpnu�[���PK��Zf͍ffdґtest/Form/Symfony/Component/Form/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.phpnu�[���PK��Z%u����^�ؑtest/Form/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/SessionCsrfProviderTest.phpnu�[���PK��Z_Nn���^�test/Form/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/DefaultCsrfProviderTest.phpnu�[���PK��Z�A��b��test/Form/Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.phpnu�[���PK��Z�L?��.�.X��test/Form/Symfony/Component/Form/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.phpnu�[���PK��Z��܏##WN"�test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/Fixtures/randomhashnu�[���PK��Z��**a�"�test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.phpnu�[���PK��Z��!��$�$^�/�test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/ResizeFormListenerTest.phpnu�[���PK��Zfk5s3	3	X)U�test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/TrimListenerTest.phpnu�[���PK��ZB+�K��n�^�test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayObjectTest.phpnu�[���PK��Z�@ڦt-b�test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerCustomArrayObjectTest.phpnu�[���PK��ZЭ
���h�e�test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayTest.phpnu�[���PK��Z��ggbi�test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.phpnu�[���PK��Z�O�&c	p�test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.phpnu�[���PK��Z���� � Y���test/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.phpnu�[���PK��Z�.�p))S<��test/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ChoiceListTest.phpnu�[���PK��Z�![���[�Ētest/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.phpnu�[���PK��Z�gUI��WJ�test/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.phpnu�[���PK��ZR��
�
Yv�test/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.phpnu�[���PK��Z��x��`���test/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.phpnu�[���PK��Z?�R8�.�.[��test/Form/Symfony/Component/Form/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.phpnu�[���PK��Z���4��f/7�test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ChoiceToValueTransformerTest.phpnu�[���PK��Z�����qx?�test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.phpnu�[���PK��ZWs�**r�N�test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.phpnu�[���PK��Z�Ub,,Zoy�test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeTestCase.phpnu�[���PK��Z�}��!
!
l%|�test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToTimestampTransformerTest.phpnu�[���PK��Z��=�C?C?h≓test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToArrayTransformerTest.phpnu�[���PK��Z���e�ɓtest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ArrayToPartsTransformerTest.phpnu�[���PK��Z\R��bSؓtest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DataTransformerChainTest.phpnu�[���PK��Z�6���hl�test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.phpnu�[���PK��ZY@zjjo��test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.phpnu�[���PK��Z]e"��j��test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.phpnu�[���PK��ZN�z.z.q��test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.phpnu�[���PK��Z��`nonop�3�test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.phpnu�[���PK��Z�?+�<<j��test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ValueToDuplicatesTransformerTest.phpnu�[���PK��ZfJ��eٯ�test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BaseDateTimeTransformerTest.phpnu�[���PK��Z�.bc))hv��test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ChoicesToValuesTransformerTest.phpnu�[���PK��ZJW����i7��test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.phpnu�[���PK��Z��W@@O�ؔtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/LanguageTypeTest.phpnu�[���PK��Zx���aaM~ߔtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/LocaleTypeTest.phpnu�[���PK��Z�C���M\�test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/ButtonTypeTest.phpnu�[���PK��Z�'�\�\KZ�test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.phpnu�[���PK��Zvzw�LLQWD�test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.phpnu�[���PK��Z�(��__O$_�test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/PasswordTypeTest.phpnu�[���PK��Zx�=�t=t=Oe�test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.phpnu�[���PK��ZP�!���J���test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/UrlTypeTest.phpnu�[���PK��ZX�:::K/��test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/TypeTestCase.phpnu�[���PK��Z����N䬕test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/CountryTypeTest.phpnu�[���PK��Z�_*G��X���test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypePerformanceTest.phpnu�[���PK��Z�{MK��K>��test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/BaseTypeTest.phpnu�[���PK��Zސ/���Oaʕtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/TimezoneTypeTest.phpnu�[���PK��ZdwҢSJSJK�Εtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.phpnu�[���PK��Z/����L��test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/MoneyTypeTest.phpnu�[���PK��Z���J��M� �test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/NumberTypeTest.phpnu�[���PK��Z�}�C%%Md(�test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/SubmitTypeTest.phpnu�[���PK��Z�!]i00O/�test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/CurrencyTypeTest.phpnu�[���PK��Z�IJ��O�3�test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/CheckboxTypeTest.phpnu�[���PK��Z�ñI��O�F�test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/RepeatedTypeTest.phpnu�[���PK��Zk�ƅ��N$\�test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/IntegerTypeTest.phpnu�[���PK��ZI��E����M�_�test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.phpnu�[���PK��Z�jGgJgJK��test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.phpnu�[���PK��Z&����K�M�test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.phpnu�[���PK��Z����>�>XW�test/Form/Symfony/Component/Form/Tests/Extension/DataCollector/FormDataCollectorTest.phpnu�[���PK��Zb�,�<<]���test/Form/Symfony/Component/Form/Tests/Extension/DataCollector/DataCollectorExtensionTest.phpnu�[���PK��Z�{�(�,�,XT��test/Form/Symfony/Component/Form/Tests/Extension/DataCollector/FormDataExtractorTest.phpnu�[���PK��Z��q��f�ɗtest/Form/Symfony/Component/Form/Tests/Extension/DataCollector/Type/DataCollectorTypeExtensionTest.phpnu�[���PK��Z�'�@�ϗtest/Form/Symfony/Component/Form/Tests/AbstractExtensionTest.phpnu�[���PK��Z�g	�331bԗtest/Form/Symfony/Component/Form/phpunit.xml.distnu�[���PK��Z�ԍZP5P5I�חtest/Security/Symfony/Component/Security/Acl/Tests/Voter/AclVoterTest.phpnu�[���PK��Z�޻>�Q�QR�
�test/Security/Symfony/Component/Security/Acl/Tests/Dbal/MutableAclProviderTest.phpnu�[���PK��Z�
�� � T�_�test/Security/Symfony/Component/Security/Acl/Tests/Dbal/AclProviderBenchmarkTest.phpnu�[���PK��Z�'(��'�'K��test/Security/Symfony/Component/Security/Acl/Tests/Dbal/AclProviderTest.phpnu�[���PK��Z�ˆ5M=��test/Security/Symfony/Component/Security/Acl/Tests/Domain/AuditLoggerTest.phpnu�[���PK��Z6x�}&&Ḻ�test/Security/Symfony/Component/Security/Acl/Tests/Domain/FieldEntryTest.phpnu�[���PK��Z��+&Pn��test/Security/Symfony/Component/Security/Acl/Tests/Domain/ObjectIdentityTest.phpnu�[���PK��Z_�~��aʘtest/Security/Symfony/Component/Security/Acl/Tests/Domain/ObjectIdentityRetrievalStrategyTest.phpnu�[���PK��Z��HHRϘtest/Security/Symfony/Component/Security/Acl/Tests/Domain/DoctrineAclCacheTest.phpnu�[���PK��Z��v��\�ۘtest/Security/Symfony/Component/Security/Acl/Tests/Domain/PermissionGrantingStrategyTest.phpnu�[���PK��Z/bAbAEo��test/Security/Symfony/Component/Security/Acl/Tests/Domain/AclTest.phpnu�[���PK��Z5�VF8�test/Security/Symfony/Component/Security/Acl/Tests/Domain/RoleSecurityIdentityTest.phpnu�[���PK��Z��a((VK?�test/Security/Symfony/Component/Security/Acl/Tests/Domain/UserSecurityIdentityTest.phpnu�[���PK��Z�am��c�J�test/Security/Symfony/Component/Security/Acl/Tests/Domain/SecurityIdentityRetrievalStrategyTest.phpnu�[���PK��ZF��@�
�
Gh�test/Security/Symfony/Component/Security/Acl/Tests/Domain/EntryTest.phpnu�[���PK��Z���yyX.v�test/Security/Symfony/Component/Security/Acl/Tests/Permission/BasicPermissionMapTest.phpnu�[���PK��ZeE���Q/y�test/Security/Symfony/Component/Security/Acl/Tests/Permission/MaskBuilderTest.phpnu�[���PK��Zܲ#&;;=���test/Security/Symfony/Component/Security/Acl/phpunit.xml.distnu�[���PK��ZC��)!"!"V9��test/Security/Symfony/Component/Security/Tests/Http/Firewall/ExceptionListenerTest.phpnu�[���PK��Zs�f�[[L૙test/Security/Symfony/Component/Security/Tests/Core/User/UserCheckerTest.phpnu�[���PK��Z����!!U���test/Security/Symfony/Component/Security/Tests/Core/User/InMemoryUserProviderTest.phpnu�[���PK��Z2�nBB`]Ùtest/Security/Symfony/Component/Security/Tests/Core/Authentication/Token/RememberMeTokenTest.phpnu�[���PK��Z9�#�		9/̙test/Security/Symfony/Component/Security/phpunit.xml.distnu�[���PK��Zg3�%%D�Йtest/Security/Symfony/Component/Security/Http/Tests/FirewallTest.phpnu�[���PK��Z��+MbbG:�test/Security/Symfony/Component/Security/Http/Tests/FirewallMapTest.phpnu�[���PK��Z����%�%E�test/Security/Symfony/Component/Security/Http/Tests/HttpUtilsTest.phpnu�[���PK��Z�ck�~
~
c	�test/Security/Symfony/Component/Security/Http/Tests/EntryPoint/FormAuthenticationEntryPointTest.phpnu�[���PK��Ze���d"�test/Security/Symfony/Component/Security/Http/Tests/EntryPoint/BasicAuthenticationEntryPointTest.phpnu�[���PK��Z-Ɔ��dq(�test/Security/Symfony/Component/Security/Http/Tests/EntryPoint/RetryAuthenticationEntryPointTest.phpnu�[���PK��ZGrT�		e�0�test/Security/Symfony/Component/Security/Http/Tests/EntryPoint/DigestAuthenticationEntryPointTest.phpnu�[���PK��ZҒ)��WF:�test/Security/Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.phpnu�[���PK��Z�G��

T�O�test/Security/Symfony/Component/Security/Http/Tests/Firewall/ChannelListenerTest.phpnu�[���PK��Z�e��
�
d>h�test/Security/Symfony/Component/Security/Http/Tests/Firewall/AnonymousAuthenticationListenerTest.phpnu�[���PK��Z��K�$$`_s�test/Security/Symfony/Component/Security/Http/Tests/Firewall/BasicAuthenticationListenerTest.phpnu�[���PK��Z��l���O�test/Security/Symfony/Component/Security/Http/Tests/Firewall/DigestDataTest.phpnu�[���PK��Zj�z9�"�"TC��test/Security/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.phpnu�[���PK��Z<��%%ezךtest/Security/Symfony/Component/Security/Http/Tests/Firewall/AbstractPreAuthenticatedListenerTest.phpnu�[���PK��Zq���S%��test/Security/Symfony/Component/Security/Http/Tests/Firewall/AccessListenerTest.phpnu�[���PK��Z�V�k��S��test/Security/Symfony/Component/Security/Http/Tests/Firewall/LogoutListenerTest.phpnu�[���PK��Z���@&@&W�8�test/Security/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.phpnu�[���PK��Z�LMM_�_�test/Security/Symfony/Component/Security/Http/Tests/Firewall/X509AuthenticationListenerTest.phpnu�[���PK��Zx��W��Evn�test/Security/Symfony/Component/Security/Http/Tests/AccessMapTest.phpnu�[���PK��Z���F8F8mu�test/Security/Symfony/Component/Security/Http/Tests/RememberMe/PersistentTokenBasedRememberMeServicesTest.phpnu�[���PK��Z�䗥1#1#ab��test/Security/Symfony/Component/Security/Http/Tests/RememberMe/AbstractRememberMeServicesTest.phpnu�[���PK��Z�gZ)Z)c$қtest/Security/Symfony/Component/Security/Http/Tests/RememberMe/TokenBasedRememberMeServicesTest.phpnu�[���PK��Z��ʅ
�
W��test/Security/Symfony/Component/Security/Http/Tests/RememberMe/ResponseListenerTest.phpnu�[���PK��ZY�Ң	�	a�test/Security/Symfony/Component/Security/Http/Tests/Session/SessionAuthenticationStrategyTest.phpnu�[���PK��Z�
{{^P�test/Security/Symfony/Component/Security/Http/Tests/Logout/DefaultLogoutSuccessHandlerTest.phpnu�[���PK��Z]�ͷ��WY�test/Security/Symfony/Component/Security/Http/Tests/Logout/SessionLogoutHandlerTest.phpnu�[���PK��Zk��^��test/Security/Symfony/Component/Security/Http/Tests/Logout/CookieClearingLogoutHandlerTest.phpnu�[���PK��Z$a��n#�test/Security/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationFailureHandlerTest.phpnu�[���PK��Z/w!w!f|?�test/Security/Symfony/Component/Security/Http/Tests/Authentication/SimpleAuthenticationHandlerTest.phpnu�[���PK��Zid]z��n�a�test/Security/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationSuccessHandlerTest.phpnu�[���PK��Z?k,.<<>!y�test/Security/Symfony/Component/Security/Http/phpunit.xml.distnu�[���PK��Z�|G

b�|�test/Security/Symfony/Component/Security/Csrf/Tests/TokenStorage/NativeSessionTokenStorageTest.phpnu�[���PK��Z���WW\u��test/Security/Symfony/Component/Security/Csrf/Tests/TokenStorage/SessionTokenStorageTest.phpnu�[���PK��Z�-�kkLX��test/Security/Symfony/Component/Security/Csrf/Tests/CsrfTokenManagerTest.phpnu�[���PK��Z�3�z((`?��test/Security/Symfony/Component/Security/Csrf/Tests/TokenGenerator/UriSafeTokenGeneratorTest.phpnu�[���PK��Z��*�<<>�Ŝtest/Security/Symfony/Component/Security/Csrf/phpunit.xml.distnu�[���PK��ZׄHAnnK�ɜtest/Security/Symfony/Component/Security/Core/Tests/SecurityContextTest.phpnu�[���PK��ZxF�E�ٜtest/Security/Symfony/Component/Security/Core/Tests/Role/RoleTest.phpnu�[���PK��Zt�S��Nܜtest/Security/Symfony/Component/Security/Core/Tests/Role/RoleHierarchyTest.phpnu�[���PK��Z��{{O+�test/Security/Symfony/Component/Security/Core/Tests/Role/SwitchUserRoleTest.phpnu�[���PK��Zr��nnY%�test/Security/Symfony/Component/Security/Core/Tests/Encoder/Pbkdf2PasswordEncoderTest.phpnu�[���PK��Z6���\�test/Security/Symfony/Component/Security/Core/Tests/Encoder/PlaintextPasswordEncoderTest.phpnu�[���PK��ZL�'��WW��test/Security/Symfony/Component/Security/Core/Tests/Encoder/BasePasswordEncoderTest.phpnu�[���PK��Z%�s�R��test/Security/Symfony/Component/Security/Core/Tests/Encoder/EncoderFactoryTest.phpnu�[���PK��Ze5���`E�test/Security/Symfony/Component/Security/Core/Tests/Encoder/MessageDigestPasswordEncoderTest.phpnu�[���PK��Z!�?��	�	Y��test/Security/Symfony/Component/Security/Core/Tests/Encoder/BCryptPasswordEncoderTest.phpnu�[���PK��Z�����g%�test/Security/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.phpnu�[���PK��Z�KN��Mc7�test/Security/Symfony/Component/Security/Core/Tests/Util/SecureRandomTest.phpnu�[���PK��Zn�;�SSL�N�test/Security/Symfony/Component/Security/Core/Tests/Util/StringUtilsTest.phpnu�[���PK��Z�����K�Q�test/Security/Symfony/Component/Security/Core/Tests/Util/ClassUtilsTest.phpnu�[���PK��ZI-���_�X�test/Security/Symfony/Component/Security/Core/Tests/Authorization/AccessDecisionManagerTest.phpnu�[���PK��Z�bdw�
�
\po�test/Security/Symfony/Component/Security/Core/Tests/Authorization/ExpressionLanguageTest.phpnu�[���PK��Z�Ƕ'�
�
_�}�test/Security/Symfony/Component/Security/Core/Tests/Authorization/Voter/ExpressionVoterTest.phpnu�[���PK��Zjq�o��Y식test/Security/Symfony/Component/Security/Core/Tests/Authorization/Voter/RoleVoterTest.phpnu�[���PK��Z�R�MMb��test/Security/Symfony/Component/Security/Core/Tests/Authorization/Voter/RoleHierarchyVoterTest.phpnu�[���PK��Z��� ,
,
b���test/Security/Symfony/Component/Security/Core/Tests/Authorization/Voter/AuthenticatedVoterTest.phpnu�[���PK��ZLS�(��E���test/Security/Symfony/Component/Security/Core/Tests/User/UserTest.phpnu�[���PK��Z��qR쵝test/Security/Symfony/Component/Security/Core/Tests/User/ChainUserProviderTest.phpnu�[���PK��Z�$��s�͝test/Security/Symfony/Component/Security/Core/Tests/Authentication/Provider/AnonymousAuthenticationProviderTest.phpnu�[���PK��ZP��[.[.m6֝test/Security/Symfony/Component/Security/Core/Tests/Authentication/Provider/DaoAuthenticationProviderTest.phpnu�[���PK��Zו�Gi&i&n.�test/Security/Symfony/Component/Security/Core/Tests/Authentication/Provider/UserAuthenticationProviderTest.phpnu�[���PK��Z�75ttt5,�test/Security/Symfony/Component/Security/Core/Tests/Authentication/Provider/RememberMeAuthenticationProviderTest.phpnu�[���PK��Z���ZZzM<�test/Security/Symfony/Component/Security/Core/Tests/Authentication/Provider/PreAuthenticatedAuthenticationProviderTest.phpnu�[���PK��Z�����hQP�test/Security/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationProviderManagerTest.phpnu�[���PK��Z ����k�f�test/Security/Symfony/Component/Security/Core/Tests/Authentication/RememberMe/InMemoryTokenProviderTest.phpnu�[���PK��ZB�����euo�test/Security/Symfony/Component/Security/Core/Tests/Authentication/RememberMe/PersistentTokenTest.phpnu�[���PK��ZI?��

f�s�test/Security/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationTrustResolverTest.phpnu�[���PK��Z�B3��$�$^�~�test/Security/Symfony/Component/Security/Core/Tests/Authentication/Token/AbstractTokenTest.phpnu�[���PK��Z�j��KKf룞test/Security/Symfony/Component/Security/Core/Tests/Authentication/Token/UsernamePasswordTokenTest.phpnu�[���PK��Zd���f̫�test/Security/Symfony/Component/Security/Core/Tests/Authentication/Token/PreAuthenticatedTokenTest.phpnu�[���PK��Z��ۛ��_T��test/Security/Symfony/Component/Security/Core/Tests/Authentication/Token/AnonymousTokenTest.phpnu�[���PK��Z]�P�<<>ַ�test/Security/Symfony/Component/Security/Core/phpunit.xml.distnu�[���PK��Z���n��L���test/Validator/Symfony/Component/Validator/Tests/ConstraintViolationTest.phpnu�[���PK��ZzJ.4�
�
P�test/Validator/Symfony/Component/Validator/Tests/ConstraintViolationListTest.phpnu�[���PK��Z�p��ggXLϞtest/Validator/Symfony/Component/Validator/Tests/Fixtures/FailingConstraintValidator.phpnu�[���PK��Z5*�I;Ҟtest/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintB.phpnu�[���PK��Z]�qqI�Ԟtest/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintC.phpnu�[���PK��Z���&��I�מtest/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintA.phpnu�[���PK��Zߛ��[[D�ڞtest/Validator/Symfony/Component/Validator/Tests/Fixtures/Entity.phpnu�[���PK��Zp�Tq��Zm�test/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintWithValueAsDefault.phpnu�[���PK��Z@��w��Q��test/Validator/Symfony/Component/Validator/Tests/Fixtures/FakeMetadataFactory.phpnu�[���PK��Z��a�CCM��test/Validator/Symfony/Component/Validator/Tests/Fixtures/EntityInterface.phpnu�[���PK��Z?>��Rf�test/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintAValidator.phpnu�[���PK��Z^t��M��test/Validator/Symfony/Component/Validator/Tests/Fixtures/ClassConstraint.phpnu�[���PK��Z��88J��test/Validator/Symfony/Component/Validator/Tests/Fixtures/EntityParent.phpnu�[���PK��Z�h��Y���test/Validator/Symfony/Component/Validator/Tests/Fixtures/GroupSequenceProviderEntity.phpnu�[���PK��Z�5>��Q)��test/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintWithValue.phpnu�[���PK��Z=�2O/��test/Validator/Symfony/Component/Validator/Tests/Fixtures/FailingConstraint.phpnu�[���PK��ZO��l99G��test/Validator/Symfony/Component/Validator/Tests/Fixtures/Reference.phpnu�[���PK��Z2�	���Ov�test/Validator/Symfony/Component/Validator/Tests/Fixtures/InvalidConstraint.phpnu�[���PK��Zj�/���Iv�test/Validator/Symfony/Component/Validator/Tests/Fixtures/FilesLoader.phpnu�[���PK��ZY��/K�test/Validator/Symfony/Component/Validator/Tests/Fixtures/CallbackClass.phpnu�[���PK��Z���JJX
�test/Validator/Symfony/Component/Validator/Tests/Fixtures/InvalidConstraintValidator.phpnu�[���PK��ZG#i��P��test/Validator/Symfony/Component/Validator/Tests/Fixtures/PropertyConstraint.phpnu�[���PK��Z�Ε_))I6�test/Validator/Symfony/Component/Validator/Tests/ValidatorBuilderTest.phpnu�[���PK��Z��>���N��test/Validator/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.phpnu�[���PK��ZF���U:�test/Validator/Symfony/Component/Validator/Tests/Mapping/ClassMetadataFactoryTest.phpnu�[���PK��Z)����P`J�test/Validator/Symfony/Component/Validator/Tests/Mapping/ElementMetadataTest.phpnu�[���PK��Z�D��O�S�test/Validator/Symfony/Component/Validator/Tests/Mapping/MemberMetadataTest.phpnu�[���PK��ZW_Ϙ�O�`�test/Validator/Symfony/Component/Validator/Tests/Mapping/GetterMetadataTest.phpnu�[���PK��Z"��,�	�	O�f�test/Validator/Symfony/Component/Validator/Tests/Mapping/Cache/ApcCacheTest.phpnu�[���PK��Zos%�eeY�p�test/Validator/Symfony/Component/Validator/Tests/Mapping/BlackholeMetadataFactoryTest.phpnu�[���PK��Zu��gS�t�test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/LoaderChainTest.phpnu�[���PK��Z�=����bk��test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping-non-strings.xmlnu�[���PK��Z�D�k��Vك�test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.xmlnu�[���PK��Z�-���V(��test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.ymlnu�[���PK��Z{�%uZn��test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/StaticMethodLoaderTest.phpnu�[���PK��Z���mX��test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/AnnotationLoaderTest.phpnu�[���PK��Z��N��V�Ÿtest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.phpnu�[���PK��ZN�;��O�ԟtest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/withdoctype.xmlnu�[���PK��ZQ�֟test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/empty-mapping.ymlnu�[���PK��Z�Qi���Unןtest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/XmlFileLoaderTest.phpnu�[���PK��Z�e2~Tz�test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/nonvalid-mapping.ymlnu�[���PK��Z����^�test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/AbstractMethodStaticLoader.phpnu�[���PK��ZF���<<S��test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/FilesLoaderTest.phpnu�[���PK��Z{�d���QD�test/Validator/Symfony/Component/Validator/Tests/Mapping/PropertyMetadataTest.phpnu�[���PK��Z��~6�F�FJl��test/Validator/Symfony/Component/Validator/Tests/ValidationVisitorTest.phpnu�[���PK��ZK��y'$'$B�A�test/Validator/Symfony/Component/Validator/Tests/ValidatorTest.phpnu�[���PK��Z�P�6�)�)IEf�test/Validator/Symfony/Component/Validator/Tests/ExecutionContextTest.phpnu�[���PK��Z����QK��test/Validator/Symfony/Component/Validator/Tests/Constraints/AllValidatorTest.phpnu�[���PK��Z�ĀDDSl��test/Validator/Symfony/Component/Validator/Tests/Constraints/RegexValidatorTest.phpnu�[���PK��Z�Q�]3��test/Validator/Symfony/Component/Validator/Tests/Constraints/LessThanOrEqualValidatorTest.phpnu�[���PK��Z�;�55Rз�test/Validator/Symfony/Component/Validator/Tests/Constraints/IssnValidatorTest.phpnu�[���PK��Z����K1K1P�͠test/Validator/Symfony/Component/Validator/Tests/Constraints/IpValidatorTest.phpnu�[���PK��Z�rH���iR��test/Validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorCustomArrayObjectTest.phpnu�[���PK��Z�GRf��U��test/Validator/Symfony/Component/Validator/Tests/Constraints/NotNullValidatorTest.phpnu�[���PK��Z���I��O�
�test/Validator/Symfony/Component/Validator/Tests/Constraints/CollectionTest.phpnu�[���PK��Z���W��X(�test/Validator/Symfony/Component/Validator/Tests/Constraints/FileValidatorObjectTest.phpnu�[���PK��Zs{*pQQR��test/Validator/Symfony/Component/Validator/Tests/Constraints/TrueValidatorTest.phpnu�[���PK��Z�|�++Wr#�test/Validator/Symfony/Component/Validator/Tests/Constraints/Fixtures/test_portrait.gifnu�[���PK��ZJ��++X$$�test/Validator/Symfony/Component/Validator/Tests/Constraints/Fixtures/test_landscape.gifnu�[���PK��ZЍ��!!N�$�test/Validator/Symfony/Component/Validator/Tests/Constraints/Fixtures/test.gifnu�[���PK��Z)m�RTv(�test/Validator/Symfony/Component/Validator/Tests/Constraints/LengthValidatorTest.phpnu�[���PK��Z��̈́
�
T�A�test/Validator/Symfony/Component/Validator/Tests/Constraints/LocaleValidatorTest.phpnu�[���PK��Z�s�VVXM�test/Validator/Symfony/Component/Validator/Tests/Constraints/NotEqualToValidatorTest.phpnu�[���PK��Z���8w
w
S�S�test/Validator/Symfony/Component/Validator/Tests/Constraints/EmailValidatorTest.phpnu�[���PK��Z�w88\�^�test/Validator/Symfony/Component/Validator/Tests/Constraints/CountValidatorCountableTest.phpnu�[���PK��Z];XwwS�b�test/Validator/Symfony/Component/Validator/Tests/Constraints/BlankValidatorTest.phpnu�[���PK��Z3�ê�
�
d�j�test/Validator/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.phpnu�[���PK��Z7��a��Ty�test/Validator/Symfony/Component/Validator/Tests/Constraints/ChoiceValidatorTest.phpnu�[���PK��Z�2�(�(RC��test/Validator/Symfony/Component/Validator/Tests/Constraints/FileValidatorTest.phpnu�[���PK��Z�����X~¡test/Validator/Symfony/Component/Validator/Tests/Constraints/CardSchemeValidatorTest.phpnu�[���PK��Z{r>K��R�աtest/Validator/Symfony/Component/Validator/Tests/Constraints/IsbnValidatorTest.phpnu�[���PK��ZjTL�99U��test/Validator/Symfony/Component/Validator/Tests/Constraints/EqualToValidatorTest.phpnu�[���PK��Z�$&��Y��test/Validator/Symfony/Component/Validator/Tests/Constraints/IdenticalToValidatorTest.phpnu�[���PK��Z��|=��c�test/Validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorArrayObjectTest.phpnu�[���PK��Z�z0���U`��test/Validator/Symfony/Component/Validator/Tests/Constraints/CountryValidatorTest.phpnu�[���PK��Z�rZcc\s	�test/Validator/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToValidatorTest.phpnu�[���PK��Z�C��NNQb�test/Validator/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.phpnu�[���PK��Z(�3��J1'�test/Validator/Symfony/Component/Validator/Tests/Constraints/ValidTest.phpnu�[���PK��Z���A��VO*�test/Validator/Symfony/Component/Validator/Tests/Constraints/CurrencyValidatorTest.phpnu�[���PK��ZB����H�6�test/Validator/Symfony/Component/Validator/Tests/Constraints/AllTest.phpnu�[���PK��Z�p�)D
D
R
;�test/Validator/Symfony/Component/Validator/Tests/Constraints/LuhnValidatorTest.phpnu�[���PK��Z��͸�S�H�test/Validator/Symfony/Component/Validator/Tests/Constraints/RangeValidatorTest.phpnu�[���PK��ZQ��s(s(Va�test/Validator/Symfony/Component/Validator/Tests/Constraints/CallbackValidatorTest.phpnu�[���PK��Z@*�VHHR��test/Validator/Symfony/Component/Validator/Tests/Constraints/DateValidatorTest.phpnu�[���PK��Z�� BTTRѕ�test/Validator/Symfony/Component/Validator/Tests/Constraints/TimeValidatorTest.phpnu�[���PK��Z�i�KKS���test/Validator/Symfony/Component/Validator/Tests/Constraints/FalseValidatorTest.phpnu�[���PK��ZϏ�R��Xu��test/Validator/Symfony/Component/Validator/Tests/Constraints/CountValidatorArrayTest.phpnu�[���PK��ZqC����V���test/Validator/Symfony/Component/Validator/Tests/Constraints/LanguageValidatorTest.phpnu�[���PK��Zֆ���SV��test/Validator/Symfony/Component/Validator/Tests/Constraints/CountValidatorTest.phpnu�[���PK��Z��LwwY�̢test/Validator/Symfony/Component/Validator/Tests/Constraints/GreaterThanValidatorTest.phpnu�[���PK��Z���kkV�Ԣtest/Validator/Symfony/Component/Validator/Tests/Constraints/FileValidatorPathTest.phpnu�[���PK��Z׫��`�آtest/Validator/Symfony/Component/Validator/Tests/Constraints/GreaterThanOrEqualValidatorTest.phpnu�[���PK��ZW�@� � R3ߢtest/Validator/Symfony/Component/Validator/Tests/Constraints/IbanValidatorTest.phpnu�[���PK��Z�y7{==R`�test/Validator/Symfony/Component/Validator/Tests/Constraints/TypeValidatorTest.phpnu�[���PK��Z\z?�+�+X�test/Validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorTest.phpnu�[���PK��ZC���77VkB�test/Validator/Symfony/Component/Validator/Tests/Constraints/LessThanValidatorTest.phpnu�[���PK��Zb���ggV(J�test/Validator/Symfony/Component/Validator/Tests/Constraints/DateTimeValidatorTest.phpnu�[���PK��Z;���,,XW�test/Validator/Symfony/Component/Validator/Tests/Constraints/ExpressionValidatorTest.phpnu�[���PK��Z�Zf^
^
V�n�test/Validator/Symfony/Component/Validator/Tests/Constraints/NotBlankValidatorTest.phpnu�[���PK��Z}mW��]�y�test/Validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorArrayTest.phpnu�[���PK��Z�r3UUR|�test/Validator/Symfony/Component/Validator/Tests/Constraints/NullValidatorTest.phpnu�[���PK��Z0�h'��Sۃ�test/Validator/Symfony/Component/Validator/Tests/Constraints/ImageValidatorTest.phpnu�[���PK��Z�d��..C<��test/Validator/Symfony/Component/Validator/Tests/ConstraintTest.phpnu�[���PK��Z��,Q88;ݶ�test/Validator/Symfony/Component/Validator/phpunit.xml.distnu�[���PK��Z�����K���test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Logger/DbalLoggerTest.phpnu�[���PK��Zl;���?�ˣtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/bootstrap.phpnu�[���PK��Z1g��P�ͣtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/SingleIntIdEntity.phpnu�[���PK��ZI>�[��Zѣtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/SingleIntIdNoToStringEntity.phpnu�[���PK��Z�+�88SEԣtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/CompositeIntIdEntity.phpnu�[���PK��Z�ͭ��Pأtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/AssociationEntity.phpnu�[���PK��Z��3Nuܣtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/GroupableEntity.phpnu�[���PK��Z��!��S�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/SingleStringIdEntity.phpnu�[���PK��Z6i+**T_�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/ContainerAwareFixture.phpnu�[���PK��ZИ�m��O
�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/DoubleNameEntity.phpnu�[���PK��Z�%b�99V��test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/CompositeStringIdEntity.phpnu�[���PK��Z�'N|qqC@�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/User.phpnu�[���PK��Z��.���I$�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/DoctrineOrmTestCase.phpnu�[���PK��Z��۵��U���test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/DoctrineOrmTypeGuesserTest.phpnu�[���PK��Z��`Հ�p�
�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleStringIdTest.phpnu�[���PK��Z�'�;�!�!a�
�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/GenericEntityChoiceListTest.phpnu�[���PK��Z9&���0�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleStringIdWithQueryBuilderTest.phpnu�[���PK��Zb#����m�4�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListSingleIntIdTest.phpnu�[���PK��ZAGA��};�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleIntIdWithQueryBuilderTest.phpnu�[���PK��Z�~h���}�?�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListCompositeIdWithQueryBuilderTest.phpnu�[���PK��Z�'j��nD�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/LoadedEntityChoiceListSingleStringIdTest.phpnu�[���PK��Z�0�e��k�G�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/LoadedEntityChoiceListSingleIntIdTest.phpnu�[���PK��Z��V
zzm�J�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListCompositeIdTest.phpnu�[���PK��Z��*��mN�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListCompositeIdTest.phpnu�[���PK��Z�n<-	-	_zT�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.phpnu�[���PK��Z�-��1
1
b6^�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListTest.phpnu�[���PK��Zc�&zzm�h�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleIntIdTest.phpnu�[���PK��Z�ǜ"��kl�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/LoadedEntityChoiceListCompositeIdTest.phpnu�[���PK��Z_UNF��po�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListSingleStringIdTest.phpnu�[���PK��ZYv�:B	B	k�u�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/DataTransformer/CollectionToArrayTransformerTest.phpnu�[���PK��Z��(iiN��test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.phpnu�[���PK��Z�I�m��YL�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypePerformanceTest.phpnu�[���PK��Z�;��
�
Z~��test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Security/User/EntityUserProviderTest.phpnu�[���PK��Z}��u>u>_��test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueValidatorTest.phpnu�[���PK��Z���,��`�E�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/ExpressionLanguage/DoctrineParserCacheTest.phpnu�[���PK��Z�$K�BBTiM�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/ContainerAwareEventManagerTest.phpnu�[���PK��Z�9qq[/U�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/DataFixtures/ContainerAwareLoaderTest.phpnu�[���PK��ZC�II[+Y�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/HttpFoundation/DbalSessionHandlerTest.phpnu�[���PK��Z�l��]�\�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.phpnu�[���PK��ZO����Ls�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPassTest.phpnu�[���PK��Z�ޠ�77<��test/DoctrineBridge/Symfony/Bridge/Doctrine/phpunit.xml.distnu�[���PK��Z&�ǦGGN���test/MonologBridge/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.phpnu�[���PK��Z�o.���No��test/MonologBridge/Symfony/Bridge/Monolog/Tests/Processor/WebProcessorTest.phpnu�[���PK��Z��Ki66:ܭ�test/MonologBridge/Symfony/Bridge/Monolog/phpunit.xml.distnu�[���PK��Z}/�66M|��test/Templating/Symfony/Component/Templating/Tests/TemplateNameParserTest.phpnu�[���PK��Z���xxL/��test/Templating/Symfony/Component/Templating/Tests/Fixtures/SimpleHelper.phpnu�[���PK��Z�`�2M#��test/Templating/Symfony/Component/Templating/Tests/Fixtures/templates/foo.phpnu�[���PK��Z=D����N���test/Templating/Symfony/Component/Templating/Tests/Storage/FileStorageTest.phpnu�[���PK��Z`7�SSP���test/Templating/Symfony/Component/Templating/Tests/Storage/StringStorageTest.phpnu�[���PK��ZS	�٦�J�¥test/Templating/Symfony/Component/Templating/Tests/Storage/StorageTest.phpnu�[���PK��Z��7���H�ťtest/Templating/Symfony/Component/Templating/Tests/Loader/LoaderTest.phpnu�[���PK��ZWl�‡�R�˥test/Templating/Symfony/Component/Templating/Tests/Loader/FilesystemLoaderTest.phpnu�[���PK��Z���
�
M�ܥtest/Templating/Symfony/Component/Templating/Tests/Loader/CacheLoaderTest.phpnu�[���PK��ZˡA`��M<�test/Templating/Symfony/Component/Templating/Tests/Loader/ChainLoaderTest.phpnu�[���PK��Z�`n}�
�
N��test/Templating/Symfony/Component/Templating/Tests/Helper/AssetsHelperTest.phpnu�[���PK��Z�q=R

H��test/Templating/Symfony/Component/Templating/Tests/Helper/HelperTest.phpnu�[���PK��ZM<��Rd�test/Templating/Symfony/Component/Templating/Tests/Helper/CoreAssetsHelperTest.phpnu�[���PK��Z0�nl

M��test/Templating/Symfony/Component/Templating/Tests/Helper/SlotsHelperTest.phpnu�[���PK��Z��`#`#Dw�test/Templating/Symfony/Component/Templating/Tests/PhpEngineTest.phpnu�[���PK��Z�氵�KK:�test/Templating/Symfony/Component/Templating/Tests/DelegatingEngineTest.phpnu�[���PK��Z�%�D99={O�test/Templating/Symfony/Component/Templating/phpunit.xml.distnu�[���PK��Z��Q��5!S�test/Yaml/Symfony/Component/Yaml/Tests/DumperTest.phpnu�[���PK��Z�����Ch�test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsBlockMapping.ymlnu�[���PK��Z��UU=&l�test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfCompact.ymlnu�[���PK��Z�5�R[[B�w�test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsAnchorAlias.ymlnu�[���PK��ZU���;�{�test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfTests.ymlnu�[���PK��Z�@�UU>��test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfComments.ymlnu�[���PK��ZÇ��--Iڊ�test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/unindentedCollections.ymlnu�[���PK��Z�>;���F���test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsNullsAndEmpties.ymlnu�[���PK��Zt��rqqA���test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsErrorTests.ymlnu�[���PK��ZZ{k�XXF���test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsFlowCollections.ymlnu�[���PK��Z�*���EQ��test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/escapedCharacters.ymlnu�[���PK��Z֋�O��A���test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsBasicTests.ymlnu�[���PK��ZګغzzD ��test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsFoldedScalars.ymlnu�[���PK��Z���889Ŧtest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/index.ymlnu�[���PK��Z%MC��H�Ʀtest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsDocumentSeparator.ymlnu�[���PK��Z;:�QJJ>!ͦtest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfMergeKey.ymlnu�[���PK��ZZ��>�Ѧtest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/embededPhp.ymlnu�[���PK��Z�<�=fҦtest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfObjects.ymlnu�[���PK��Z�$R��D�Ӧtest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsTypeTransfers.ymlnu�[���PK��Z����<G�test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfQuotes.ymlnu�[���PK��ZܷU�1�1�L��test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.ymlnu�[���PK��Z~;�p2p25E��test/Yaml/Symfony/Component/Yaml/Tests/ParserTest.phpnu�[���PK��Z=a�o[%[%5ȧtest/Yaml/Symfony/Component/Yaml/Tests/InlineTest.phpnu�[���PK��Z`�@ee3��test/Yaml/Symfony/Component/Yaml/Tests/YamlTest.phpnu�[���PK��Z��?o��=��test/Yaml/Symfony/Component/Yaml/Tests/ParseExceptionTest.phpnu�[���PK��Z�>[331���test/Yaml/Symfony/Component/Yaml/phpunit.xml.distnu�[���PK��Z����)L��test/Console_Getopt/tests/001-getopt.phptnu�[���PK��Z��'s��test/Console_Getopt/tests/bug11068.phptnu�[���PK��Z���'��test/Console_Getopt/tests/bug10557.phptnu�[���PK��Z��|EE'(�test/Console_Getopt/tests/bug13140.phptnu�[���PK��Z��mg�
�
J�	�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.phpnu�[���PK��Z��O+�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/RequestStackTest.phpnu�[���PK��Z��lOD
D
O��test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ResponseTestCase.phpnu�[���PK��Z�F�9bbIs+�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/CookieTest.phpnu�[���PK��Z�q�H��SN>�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/RedirectResponseTest.phpnu�[���PK��Zqr��



[�G�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ExpressionRequestMatcherTest.phpnu�[���PK��Z_�|���UFR�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/BinaryFileResponseTest.phpnu�[���PK��Z��@LLJto�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/FileBagTest.phpnu�[���PK��Z�m��..L:��test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/HeaderBagTest.phpnu�[���PK��Z��܏##Q䟨test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/Fixtures/test.gifnu�[���PK��Z�+�vZ���test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/Fixtures/.unknownextensionnu�[���PK��ZY��test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/Fixtures/directory/.emptynu�[���PK��Z��܏##M���test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/Fixtures/testnu�[���PK��Z~rM;;Y<��test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/MimeType/MimeTypeTest.phpnu�[���PK��Z��##L��test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/FileTest.phpnu�[���PK��Z��t�AAT�Ǩtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/UploadedFileTest.phpnu�[���PK��Z�ʾV�
�
Sd�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/StreamedResponseTest.phpnu�[���PK��ZM�{��c��test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Flash/AutoExpireFlashBagTest.phpnu�[���PK��Z��ƒ��Y��test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Flash/FlashBagTest.phpnu�[���PK��Z0�����a�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Attribute/AttributeBagTest.phpnu�[���PK��Z)��kc,�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Attribute/NamespacedAttributeBagTest.phpnu�[���PK��Z��ppR
B�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/SessionTest.phpnu�[���PK��Z>��*i�[�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockFileSessionStorageTest.phpnu�[���PK��Z5�h���o�k�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeSessionHandlerTest.phpnu�[���PK��Z1�Mf
f
qq�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.phpnu�[���PK��Z�+?�

s�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.phpnu�[���PK��Z>��$$pÉ�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.phpnu�[���PK��Z`����r���test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.phpnu�[���PK��Z�c=��s��test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/WriteCheckSessionHandlerTest.phpnu�[���PK��Z�Qttl0��test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.phpnu�[���PK��Z+�ɠ��m@˩test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NullSessionHandlerTest.phpnu�[���PK��Z��x�..j`ҩtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/PhpBridgeSessionStorageTest.phpnu�[���PK��Z�����j(�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockArraySessionStorageTest.phpnu�[���PK��Zt䪑�$�$g��test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.phpnu�[���PK��Z�@|B``d�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/NativeProxyTest.phpnu�[���PK��ZF�++f�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/AbstractProxyTest.phpnu�[���PK��ZČ#��l�,�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.phpnu�[���PK��ZT �S��^I9�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/MetadataBagTest.phpnu�[���PK��Z��7�
�
S�H�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/AcceptHeaderItemTest.phpnu�[���PK��Z�`k OW�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/JsonResponseTest.phpnu�[���PK��Z�E����Q�p�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/RequestMatcherTest.phpnu�[���PK��Z����,�,Tڀ�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.phpnu�[���PK��Zk\B��r�rK>��test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ResponseTest.phpnu�[���PK��ZAk�B#B#O�!�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ParameterBagTest.phpnu�[���PK��Z��q��JBE�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/RequestTest.phpnu�[���PK��Z%�bD�
�
P{Y�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ApacheRequestTest.phpnu�[���PK��Z�1r�
�
O�d�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/AcceptHeaderTest.phpnu�[���PK��Z��?�L�r�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ServerBagTest.phpnu�[���PK��Z���bppEK��test/HttpFoundation/Symfony/Component/HttpFoundation/phpunit.xml.distnu�[���PK��Z��J=�'�'D0��test/BrowserKit/Symfony/Component/BrowserKit/Tests/CookieJarTest.phpnu�[���PK��ZN�4Z�c�cA���test/BrowserKit/Symfony/Component/BrowserKit/Tests/ClientTest.phpnu�[���PK��Z�ɹ(RRA��test/BrowserKit/Symfony/Component/BrowserKit/Tests/CookieTest.phpnu�[���PK��ZK����B�/�test/BrowserKit/Symfony/Component/BrowserKit/Tests/HistoryTest.phpnu�[���PK��Z{2�wC�>�test/BrowserKit/Symfony/Component/BrowserKit/Tests/ResponseTest.phpnu�[���PK��Z|����B�K�test/BrowserKit/Symfony/Component/BrowserKit/Tests/RequestTest.phpnu�[���PK��Z�p6ll=�S�test/BrowserKit/Symfony/Component/BrowserKit/phpunit.xml.distnu�[���PK��Z?7��EE9�W�test/Net_IDNA2/tests/draft-josefsson-idn-test-vectors.phpnu�[���PK��ZE��mm&��test/Net_IDNA2/tests/Net_IDNA2Test.phpnu�[���PK��Z.��
��"ڥ�test/XML_RPC/tests/extra-lines.phpnu�[���PK��Z|�E)���test/XML_RPC/tests/empty-value-struct.phpnu�[���PK��Z�3l�** Y��test/XML_RPC/tests/protoport.phpnu�[���PK��Z�B���test/XML_RPC/tests/allgot.incnu�[���PK��Z��̢�	�	��test/XML_RPC/tests/types.phpnu�[���PK��ZJ����@�test/XML_RPC/tests/encode.phpnu�[���PK��Z���XX ^��test/XML_RPC/tests/test_Dump.phpnu�[���PK��Z$]���"�test/XML_RPC/tests/empty-value.phpnu�[���PK��Zb��)))%Q	�test/XML_RPC/tests/actual-request.phpnu�[���PK��Zw�۴��M��test/DomCrawler/Symfony/Component/DomCrawler/Tests/Fixtures/windows-1250.htmlnu�[���PK��Z�x�H��test/DomCrawler/Symfony/Component/DomCrawler/Tests/Fixtures/no-extensionnu�[���PK��Zl�#8��Bm�test/DomCrawler/Symfony/Component/DomCrawler/Tests/CrawlerTest.phpnu�[���PK��Z��Ջ==Ptest/DomCrawler/Symfony/Component/DomCrawler/Tests/Field/ChoiceFormFieldTest.phpnu�[���PK��Z�n���R�ݮtest/DomCrawler/Symfony/Component/DomCrawler/Tests/Field/TextareaFormFieldTest.phpnu�[���PK��Z�!
D��J��test/DomCrawler/Symfony/Component/DomCrawler/Tests/Field/FormFieldTest.phpnu�[���PK��Z2$�G��N;�test/DomCrawler/Symfony/Component/DomCrawler/Tests/Field/FormFieldTestCase.phpnu�[���PK��Z���QQOT�test/DomCrawler/Symfony/Component/DomCrawler/Tests/Field/InputFormFieldTest.phpnu�[���PK��Z�5�||N$��test/DomCrawler/Symfony/Component/DomCrawler/Tests/Field/FileFormFieldTest.phpnu�[���PK��Z�3��ʖʖ?�test/DomCrawler/Symfony/Component/DomCrawler/Tests/FormTest.phpnu�[���PK��Zm�Y���?W��test/DomCrawler/Symfony/Component/DomCrawler/Tests/LinkTest.phpnu�[���PK��Z)q0�ll=y��test/DomCrawler/Symfony/Component/DomCrawler/phpunit.xml.distnu�[���PK��Z��H�77LR��test/CssSelector/Symfony/Component/CssSelector/Tests/XPath/Fixtures/ids.htmlnu�[���PK��ZmiĪ:�:S��test/CssSelector/Symfony/Component/CssSelector/Tests/XPath/Fixtures/shakespear.htmlnu�[���PK��Z�B�==L��test/CssSelector/Symfony/Component/CssSelector/Tests/XPath/Fixtures/lang.xmlnu�[���PK��Z1�HCHCM��test/CssSelector/Symfony/Component/CssSelector/Tests/XPath/TranslatorTest.phpnu�[���PK��Zo,q��M�A�test/CssSelector/Symfony/Component/CssSelector/Tests/Node/ElementNodeTest.phpnu�[���PK��Z�BնVVJ�E�test/CssSelector/Symfony/Component/CssSelector/Tests/Node/HashNodeTest.phpnu�[���PK��ZV=��hhK�I�test/CssSelector/Symfony/Component/CssSelector/Tests/Node/ClassNodeTest.phpnu�[���PK��Zg$i���N|M�test/CssSelector/Symfony/Component/CssSelector/Tests/Node/NegationNodeTest.phpnu�[���PK��Zj�
��V�Q�test/CssSelector/Symfony/Component/CssSelector/Tests/Node/CombinedSelectorNodeTest.phpnu�[���PK��Z�(yآ�NW�test/CssSelector/Symfony/Component/CssSelector/Tests/Node/FunctionNodeTest.phpnu�[���PK��Z�Y���N6^�test/CssSelector/Symfony/Component/CssSelector/Tests/Node/AbstractNodeTest.phpnu�[���PK��Z_�Ӵ�Nub�test/CssSelector/Symfony/Component/CssSelector/Tests/Node/SelectorNodeTest.phpnu�[���PK��Z���uuM�f�test/CssSelector/Symfony/Component/CssSelector/Tests/Node/SpecificityTest.phpnu�[���PK��Z� _ӽ�O�k�test/CssSelector/Symfony/Component/CssSelector/Tests/Node/AttributeNodeTest.phpnu�[���PK��Z�WDL�q�test/CssSelector/Symfony/Component/CssSelector/Tests/Node/PseudoNodeTest.phpnu�[���PK��Z�/D�Hpu�test/CssSelector/Symfony/Component/CssSelector/Tests/CssSelectorTest.phpnu�[���PK��Z�u̱��Z��test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Shortcut/ElementParserTest.phpnu�[���PK��Z[�nы�Xg��test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Shortcut/ClassParserTest.phpnu�[���PK��Z>�]��^z��test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Shortcut/EmptyStringParserTest.phpnu�[���PK��Z[N�eeW���test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Shortcut/HashParserTest.phpnu�[���PK��Z^���2�2J旰test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/ParserTest.phpnu�[���PK��Z+��̭�Y˰test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/NumberHandlerTest.phpnu�[���PK��Z��˶]:Ѱtest/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/IdentifierHandlerTest.phpnu�[���PK��Z��_/RRZ�װtest/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/CommentHandlerTest.phpnu�[���PK��ZĈ���[�ްtest/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/AbstractHandlerTest.phpnu�[���PK��Z ���]��test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/WhitespaceHandlerTest.phpnu�[���PK��Z�쓱��Y5�test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/StringHandlerTest.phpnu�[���PK��ZC�U�rrW��test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/HashHandlerTest.phpnu�[���PK��Z%9�j~~J���test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/ReaderTest.phpnu�[���PK��Z�}��qqO��test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/TokenStreamTest.phpnu�[���PK��Z���Hmm?��test/CssSelector/Symfony/Component/CssSelector/phpunit.xml.distnu�[���PK��Z�X,�/�/Td�test/EventDispatcher/Symfony/Component/EventDispatcher/Tests/EventDispatcherTest.phpnu�[���PK��Z���aa]uF�test/EventDispatcher/Symfony/Component/EventDispatcher/Tests/ImmutableEventDispatcherTest.phpnu�[���PK��ZYQ_AAbcR�test/EventDispatcher/Symfony/Component/EventDispatcher/Tests/ContainerAwareEventDispatcherTest.phpnu�[���PK��Z��nuJ6p�test/EventDispatcher/Symfony/Component/EventDispatcher/Tests/EventTest.phpnu�[���PK��Z\2��
�
Q�x�test/EventDispatcher/Symfony/Component/EventDispatcher/Tests/GenericEventTest.phpnu�[���PK��Z�MqqG6��test/EventDispatcher/Symfony/Component/EventDispatcher/phpunit.xml.distnu�[���PK��Z��C	C	H��test/Console/Symfony/Component/Console/Tests/Command/ListCommandTest.phpnu�[���PK��Zo�"�Z9Z9Dٔ�test/Console/Symfony/Component/Console/Tests/Command/CommandTest.phpnu�[���PK��Zb�y�11H�αtest/Console/Symfony/Component/Console/Tests/Command/HelpCommandTest.phpnu�[���PK��Zu��d��MPڱtest/Console/Symfony/Component/Console/Tests/Fixtures/application_astext1.txtnu�[���PK��Z��c��Gzޱtest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_3.mdnu�[���PK��Z���ooK�߱test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_2.jsonnu�[���PK��Z��f���J��test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_2.xmlnu�[���PK��Z9y�X��B��test/Console/Symfony/Component/Console/Tests/Fixtures/command_1.mdnu�[���PK��Z�S��G��test/Console/Symfony/Component/Console/Tests/Fixtures/command_asxml.txtnu�[���PK��Z�^t�^^L�test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_1.xmlnu�[���PK��ZP����G��test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_4.mdnu�[���PK��Z���G�test/Console/Symfony/Component/Console/Tests/Fixtures/BarBucCommand.phpnu�[���PK��ZW'��L:�test/Console/Symfony/Component/Console/Tests/Fixtures/application_asxml2.txtnu�[���PK��Z&���VI�test/Console/Symfony/Component/Console/Tests/Fixtures/application_renderexception1.txtnu�[���PK��Z��XX��H[��test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_3.xmlnu�[���PK��Z��G��H���test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_1.xmlnu�[���PK��ZY'�A��L��test/Console/Symfony/Component/Console/Tests/Fixtures/DescriptorCommand1.phpnu�[���PK��ZCQu��L��test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_4.xmlnu�[���PK��Z�!�"��J�test/Console/Symfony/Component/Console/Tests/Fixtures/application_run3.txtnu�[���PK��Z�e�d��E�test/Console/Symfony/Component/Console/Tests/Fixtures/Foo4Command.phpnu�[���PK��Zz�Ռ��I�test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_2.mdnu�[���PK��Z�t;�aaH�test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_4.txtnu�[���PK��Z a���I��test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_4.jsonnu�[���PK��Z�F:cL��test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_3.xmlnu�[���PK��ZoY���H|�test/Console/Symfony/Component/Console/Tests/Fixtures/application_1.jsonnu�[���PK��Z#��"��D��test/Console/Symfony/Component/Console/Tests/Fixtures/command_2.jsonnu�[���PK��Z9�*A��E%�test/Console/Symfony/Component/Console/Tests/Fixtures/TestCommand.phpnu�[���PK��Z�'�̒�CT�test/Console/Symfony/Component/Console/Tests/Fixtures/command_1.txtnu�[���PK��Z<|�4UUEY�test/Console/Symfony/Component/Console/Tests/Fixtures/Foo1Command.phpnu�[���PK��ZL#�test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_1.txtnu�[���PK��Z��<]]K��test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_1.jsonnu�[���PK��Z۴�2��Iw�test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_2.jsonnu�[���PK��Z�q+��P� �test/Console/Symfony/Component/Console/Tests/Fixtures/DescriptorApplication1.phpnu�[���PK��Z��[���K�"�test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_2.mdnu�[���PK��Z��#��F�#�test/Console/Symfony/Component/Console/Tests/Fixtures/application_2.mdnu�[���PK��Z��$$M�?�test/Console/Symfony/Component/Console/Tests/Fixtures/application_astext2.txtnu�[���PK��Zg��/11J~C�test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_2.txtnu�[���PK��Z[��%��D)D�test/Console/Symfony/Component/Console/Tests/Fixtures/command_1.jsonnu�[���PK��Z�Z�o��FaE�test/Console/Symfony/Component/Console/Tests/Fixtures/application_1.mdnu�[���PK��Zia����JuT�test/Console/Symfony/Component/Console/Tests/Fixtures/definition_asxml.txtnu�[���PK��Z�_�n��J�Y�test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_1.xmlnu�[���PK��Z�: 8��J�Z�test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_3.xmlnu�[���PK��Z��-��_H\�test/Console/Symfony/Component/Console/Tests/Fixtures/application_renderexception3decorated.txtnu�[���PK��Z�@�]"]"Gh_�test/Console/Symfony/Component/Console/Tests/Fixtures/application_2.xmlnu�[���PK��Z�K@�bbH<��test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_2.txtnu�[���PK��Zp�����K��test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_3.mdnu�[���PK��Z�A�(ffC@��test/Console/Symfony/Component/Console/Tests/Fixtures/command_2.xmlnu�[���PK��Z��,���K��test/Console/Symfony/Component/Console/Tests/Fixtures/definition_astext.txtnu�[���PK��Z�I���Hq��test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_4.xmlnu�[���PK��Zu$´!!H���test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_1.txtnu�[���PK��Z���$$MT��test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_4.jsonnu�[���PK��Z3�P���L���test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_2.xmlnu�[���PK��ZѸ�;;Lb��test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_2.txtnu�[���PK��Z��a66G��test/Console/Symfony/Component/Console/Tests/Fixtures/application_1.txtnu�[���PK��Z����MƓ�test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_1.jsonnu�[���PK��ZX� �,,Ja��test/Console/Symfony/Component/Console/Tests/Fixtures/application_run2.txtnu�[���PK��Z󚲱}}K��test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_3.jsonnu�[���PK��Z1"8MMP���test/Console/Symfony/Component/Console/Tests/Fixtures/DescriptorApplication2.phpnu�[���PK��Z#ɤb��M̜�test/Console/Symfony/Component/Console/Tests/Fixtures/application_gethelp.txtnu�[���PK��Z�(���G���test/Console/Symfony/Component/Console/Tests/Fixtures/application_2.txtnu�[���PK��Z;`�ML���test/Console/Symfony/Component/Console/Tests/Fixtures/application_asxml1.txtnu�[���PK��ZW��،�I���test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_3.mdnu�[���PK��Z��X��I���test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_1.jsonnu�[���PK��Z�
c�D���test/Console/Symfony/Component/Console/Tests/Fixtures/FooCommand.phpnu�[���PK��ZG u=��Vòtest/Console/Symfony/Component/Console/Tests/Fixtures/application_renderexception3.txtnu�[���PK��ZK3Ųtest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_1.mdnu�[���PK��Z���==L�Ųtest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_3.txtnu�[���PK��Z�����HgƲtest/Console/Symfony/Component/Console/Tests/Fixtures/command_astext.txtnu�[���PK��Z�J�2H�ɲtest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_2.xmlnu�[���PK��Zl�T���GN˲test/Console/Symfony/Component/Console/Tests/Fixtures/application_1.xmlnu�[���PK��Z�Y-͡�Gi޲test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_1.mdnu�[���PK��Z(?hJ�߲test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_1.txtnu�[���PK��Z�e::J�test/Console/Symfony/Component/Console/Tests/Fixtures/application_run1.txtnu�[���PK��Z��x�44H��test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_3.txtnu�[���PK��Z6 �_AAEw�test/Console/Symfony/Component/Console/Tests/Fixtures/Foo3Command.phpnu�[���PK��Z��I��I-�test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_3.jsonnu�[���PK��ZXz�??LB�test/Console/Symfony/Component/Console/Tests/Fixtures/DescriptorCommand2.phpnu�[���PK��Z*[Ǿ44K��test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_4.mdnu�[���PK��Z	�Ӹ�G��test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_2.mdnu�[���PK��Z��U���B��test/Console/Symfony/Component/Console/Tests/Fixtures/command_2.mdnu�[���PK��Z8�UT

J2�test/Console/Symfony/Component/Console/Tests/Fixtures/application_run4.txtnu�[���PK��Z1G~"//G��test/Console/Symfony/Component/Console/Tests/Fixtures/FoobarCommand.phpnu�[���PK��Z�/""��E_�test/Console/Symfony/Component/Console/Tests/Fixtures/Foo5Command.phpnu�[���PK��Z�Xl��V_��test/Console/Symfony/Component/Console/Tests/Fixtures/application_renderexception4.txtnu�[���PK��Z*�q��M���test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_3.jsonnu�[���PK��Z��EOOC���test/Console/Symfony/Component/Console/Tests/Fixtures/command_1.xmlnu�[���PK��Z�NY__J���test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_3.txtnu�[���PK��Z�����MY��test/CoPK��Zߦ��data/File/design/design.txtnu�[���PK��Z 1D\  !data/File/design/requirements.txtnu�[���PK��Z�rCBB$data/File/design/file_operations.pngnu�[���PK��ZXV���0�0data/File/design/md5.pngnu�[���PK��Z�
[�o�odata/File/design/file.xmlnu�[���PK��Z�\����"data/File/design/class_diagram.pngnu�[���PK��Z6E�WWdata/Mail_mimeDecode/xmail.xslnu�[���PK��Z�
$v66data/Mail_mimeDecode/xmail.dtdnu�[���PK��Z�Z��aa.filemapnu�[���PK��Z}�g�.channels/__uri.regnu�[���PK��Z^q++.channels/pecl.php.net.regnu�[���PK��Z��0��.channels/components.ez.no.regnu�[���PK��Z�H:{��.channels/pear.symfony.com.regnu�[���PK��Zl�|��.channels/pear.phpunit.de.regnu�[���PK��Z�t�.channels/.alias/ezc.txtnu�[���PK��Z�o/�.channels/.alias/phpdocs.txtnu�[���PK��Z\���.channels/.alias/symfony2.txtnu�[���PK��ZT�Y.channels/.alias/phpunit.txtnu�[���PK��Z� ��.channels/.alias/pear.txtnu�[���PK��Zui<�.channels/.alias/pecl.txtnu�[���PK��ZE�Q.channels/doc.php.net.regnu�[���PK��Z|K3�((.channels/pear.php.net.regnu�[���PK��Z��0AC5C5Console/Getopt.phpnu�[���PK��ZP'hB�&�&Mail.phpnu�[���PK��Z�܄�����#.pkgxml/Symfony2_SPK��Z 1D\  !data/File/design/requirements.txtnu�[���PK��Z�rCBB$data/File/design/file_operations.pngnu�[���PK��ZXV���0�0data/File/design/md5.pngnu�[���PK��Z�
[�o�odata/File/design/file.xmlnu�[���PK��Z�\����"data/File/design/class_diagram.pngnu�[���PK��Z6E�WWdata/Mail_mimeDecode/xmail.xslnu�[���PK��Z�
$v66data/Mail_mimeDecode/xmail.dtdnu�[���PK��Z�Z��aa.filemapnu�[���PK��Z}�g�.channels/__uri.regnu�[���PK��Z^q++.channels/pecl.php.net.regnu�[���PK��Z��0��.channels/components.ez.no.regnu�[���PK��Z�H:{��.channels/pear.symfony.com.rPK��Z�rCBB$data/File/design/file_operations.pngnu�[���PK��ZXV���0�0data/File/design/md5.pngnu�[���PK��Z�
[�o�odata/File/design/file.xmlnu�[���PK��Z�\����"data/File/design/class_diagram.pngnu�[���PK��Z6E�WWdata/Mail_mimeDecode/xmail.xslnu�[���PK��Z�
$v66data/Mail_mimeDecode/xmail.dtdnu�[���PK��Z�Z��aa.filemapnu�[���PK��Z}�g�.channels/__uri.regnu�[���PK��Z^q++.channels/pecl.php.net.regnu�[���PK��Z��0��.channels/components.ez.no.regnu�[���PK��Z�H:{��.channels/pear.symfony.com.regnu�[���PK��Zl�|��.channels/pear.phpunit.de.regnu�[���PK��Z�t�.channels/.alias/ezc.txtnu�[���PK��Z�o/�.channels/.alias/phpdocs.txtnu�[���PK��Z\���.channels/.alias/symfony2.txtnu�[���PK��ZT�Y.channels/.alias/phpunit.txtnu�[���PK��Z� ��.channels/.alias/pear.txtnu�[���PK��Zui<�.channels/.alias/pecl.txtnu�[���PK��ZE�Q.channels/doc.php.net.regnu�[���PK��Z|K3�((.channels/pear.php.net.regnu�[���PK��Z��0AC5C5Console/Getopt.phpnu�[���PK��ZP'hB�&�&Mail.phpnu�[���PK��Z�܄�����#.pkgxml/Symfony2_Security-2.4.3.xmlnu�[���PK��Z'J�z++.pkgxml/symfony2.xmlnu�[���PK��Z^\F[[%.pkgxml/Symfony2_Serializer-2.4.3.xmlnu�[���PK��Z�$n��7�7&.pkgxml/Symfony2_ClassLoader-2.4.3.xmlnu�[���PK��Zȗ��!.pkgxml/Pear_Net_Socket-1.2.2.xmlnu�[���PK��Z��n�++.pkgxml/Symfony2_Yaml-2.4.3.xmlnu�[���PK��Z}3YN��.pkgxml/eZc_Archive-1.4.1.xmlnu�[���PK��Z��b�8�8!.pkgxml/Symfony2_Config-2.4.3.xmlnu�[���PK��Z�$v��*.pkgxml/Symfony2_OptionsResolver-2.4.3.xmlnu�[���PK��Z�/�h����".pkgxml/Pear_Mail_Mime-1.10.11.xmlnu�[���PK��ZtWY�n�n%.pkgxml/Symfony2_HttpKernel-2.4.3.xmlnu�[���PK��Z�1��ss..pkgxml/Symfony2_DependencyInjection-2.4.3.xmlnu�[���PK��Z=��4��(.pkgxml/Symfony2_MonologBridge-2.4.3.xmlnu�[���PK��Z�7�p�K�K.pkgxml/XML_Util.xmlnu�[���PK��Z��-=-=".pkgxml/Symfony2_Routing-2.4.3.xmlnu�[���PK��Z�|g��$.pkgxml/Symfony2_Validator-2.4.3.xmlnu�[���PK��Z�d+)SS!.pkgxml/Symfony2_Locale-2.4.3.xmlnu�[���PK��Z%ONO��&.pkgxml/Pear_Mail_mimeDecode-1.5.6.xmlnu�[���PK��Z�*�OO.pkgxml/ezc.xmlnu�[���PK��Z#�r�

 .pkgxml/Pear_Net_SMTP-1.10.0.xmlnu�[���PK��Za������.pkgxml/Symfony2_Form-2.4.3.xmlnu�[���PK��Z�Q���?�? .pkgxml/Pear_Net_Sieve-1.4.5.xmlnu�[���PK��Z��F��%.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu�[���PK��Z?�4��
�
%.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu�[���PK��Z��t8��%.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[�PK��ZXV���0�0data/File/design/md5.pngnu�[���PK��Z�
[�o�odata/File/design/file.xmlnu�[���PK��Z�\����"data/File/design/class_diagram.pngnu�[���PK��Z6E�WWdata/Mail_mimeDecode/xmail.xslnu�[���PK��Z�
$v66data/Mail_mimeDecode/xmail.dtdnu�[���PK��Z�Z��aa.filemapnu�[���PK��Z}�g�.channels/__uri.regnu�[���PK��Z^q++.channels/pecl.php.net.regnu�[���PK��Z��0��.channels/components.ez.no.regnu�[���PK��Z�H:{��.channels/pear.symfony.com.regnu�[���PK��Zl�|��.channels/pear.phpunit.de.regnu�[���PK��Z�t�.channels/.alias/ezc.txtnu�[���PK��Z�o/�.channels/.alias/phpdocs.txtnu�[���PK��Z\���.channels/.alias/symfony2.txtnu�[���PK��ZT�Y.channels/.alias/phpunit.txtnu�[���PK��Z� ��.channels/.alias/pear.txtnu�[���PK��Zui<�.channels/.alias/pecl.txtnu�[���PK��ZE�Q.channels/doc.php.net.regnu�[���PK��Z|K3�((.channels/pear.php.net.regnu�[���PK��Z��0AC5C5Console/Getopt.phpnu�[���PK��ZP'hB�&�&Mail.phpnu�[���PK��Z�܄�����#.pkgxml/Symfony2_Security-2.4.3.xmlnu�[���PK��Z'J�z++.pkgxml/symfony2.xmlnu�[���PK��Z^\F[[%.pkgxml/Symfony2_Serializer-2.4.3.xmlnu�[���PK��Z�$n��7�7&.pkgxml/Symfony2_ClassLoader-2.4.3.xmlnu�[���PK��Zȗ��!.pkgxml/Pear_Net_Socket-1.2.2.xmlnu�[���PK��Z��n�++.pkgxml/Symfony2_Yaml-2.4.3.xmlnu�[���PK��Z}3YN��.pkgxml/eZc_Archive-1.4.1.xmlnu�[���PK��Z��b�8�8!.pkgxml/Symfony2_Config-2.4.3.xmlnu�[���PK��Z�$v��*.pkgxml/Symfony2_OptionsResolver-2.4.3.xmlnu�[���PK��Z�/�h����".pkgxml/Pear_Mail_Mime-1.10.11.xmlnu�[���PK��ZtWY�n�n%.pkgxml/Symfony2_HttpKernel-2.4.3.xmlnu�[���PK��Z�1��ss..pkgxml/Symfony2_DependencyInjection-2.4.3.xmlnu�[���PK��Z=��4��(.pkgxml/Symfony2_MonologBridge-2.4.3.xmlnu�[���PK��Z�7�p�K�K.pkgxml/XML_Util.xmlnu�[���PK��Z��-=-=".pkgxml/Symfony2_Routing-2.4.3.xmlnu�[���PK��Z�|g��$.pkgxml/Symfony2_Validator-2.4.3.xmlnu�[���PK��Z�d+)SS!.pkgxml/Symfony2_Locale-2.4.3.xmlnu�[���PK��Z%ONO��&.pkgxml/Pear_Mail_mimeDecode-1.5.6.xmlnu�[���PK��Z�*�OO.pkgxml/ezc.xmlnu�[���PK��Z#�r�

 .pkgxml/Pear_Net_SMTP-1.10.0.xmlnu�[���PK��Za������.pkgxml/Symfony2_Form-2.4.3.xmlnu�[���PK��Z�Q���?�? .pkgxml/Pear_Net_Sieve-1.4.5.xmlnu�[���PK��Z��F��%.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu�[���PK��Z?�4��
�
%.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu�[���PK��Z��t8��%.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTPK��Z�
[�o�odata/File/design/file.xmlnu�[���PK��Z�\����"data/File/design/class_diagram.pngnu�[���PK��Z6E�WWdata/Mail_mimeDecode/xmail.xslnu�[���PK��Z�
$v66data/Mail_mimeDecode/xmail.dtdnu�[���PK��Z�Z��aa.filemapnu�[���PK��Z}�g�.channels/__uri.regnu�[���PK��Z^q++.channels/pecl.php.net.regnu�[���PK��Z��0��.channels/components.ez.no.regnu�[���PK��Z�H:{��.channels/pear.symfony.com.regnu�[���PK��Zl�|��.channels/pear.phpunit.de.regnu�[���PK��Z�t�.channels/.alias/ezc.txtnu�[���PK��Z�o/�.channels/.alias/phpdocs.txtnu�[���PK��Z\���.channels/.alias/symfony2.txtnu�[���PK��ZT�Y.channels/.alias/phpunit.txtnu�[���PK��Z� ��.channels/.alias/pear.txtnu�[���PK��Zui<�.channels/.alias/pecl.txtnu�[���PK��ZE�Q.channels/doc.php.net.regnu�[���PK��Z|K3�((.channels/pear.php.net.regnu�[���PK��Z��0AC5C5Console/Getopt.phpnu�[���PK��ZP'hB�&�&Mail.phpnu�[���PK��Z�܄�����#.pkgxml/Symfony2_Security-2.4.3.xmlnu�[���PK��Z'J�z++.pkgxml/symfony2.xmlnu�[���PK��Z^\F[[%.pkgxml/Symfony2_Serializer-2.4.3.xmlnu�[���PK��Z�$n��7�7&.pkgxml/Symfony2_ClassLoader-2.4.3.xmlnu�[���PK��Zȗ��!.pkgxml/Pear_Net_Socket-1.2.2.xmlnu�[���PK��Z��n�++.pkgxml/Symfony2_Yaml-2.4.3.xmlnu�[���PK��Z}3YN��.pkgxml/eZc_Archive-1.4.1.xmlnu�[���PK��Z��b�8�8!.pkgxml/Symfony2_Config-2.4.3.xmlnu�[���PK��Z�$v��*.pkgxml/Symfony2_OptionsResolver-2.4.3.xmlnu�[���PK��Z�/�h����".pkgxml/Pear_Mail_Mime-1.10.11.xmlnu�[���PK��ZtWY�n�n%.pkgxml/Symfony2_HttpKernel-2.4.3.xmlnu�[���PK��Z�1��ss..pkgxml/Symfony2_DependencyInjection-2.4.3.xmlnu�[���PK��Z=��4��(.pkgxml/Symfony2_MonologBridge-2.4.3.xmlnu�[���PK��Z�7�p�K�K.pkgxml/XML_Util.xmlnu�[���PK��Z��-=-=".pkgxml/Symfony2_Routing-2.4.3.xmlnu�[���PK��Z�|g��$.pkgxml/Symfony2_Validator-2.4.3.xmlnu�[���PK��Z�d+)SS!.pkgxml/Symfony2_Locale-2.4.3.xmlnu�[���PK��Z%ONO��&.pkgxml/Pear_Mail_mimeDecode-1.5.6.xmlnu�[���PK��Z�*�OO.pkgxml/ezc.xmlnu�[���PK��Z#�r�

 .pkgxml/Pear_Net_SMTP-1.10.0.xmlnu�[���PK��Za������.pkgxml/Symfony2_Form-2.4.3.xmlnu�[���PK��Z�Q���?�? .pkgxml/Pear_Net_Sieve-1.4.5.xmlnu�[���PK��Z��F��%.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu�[���PK��Z?�4��
�
%.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu�[���PK��Z��t8��%.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUri   URI of the namespace
     * @param bool   $multiline      whether to create a multiline tag where each
     *                               attribute gets written to a single line
     * @param string $indent         string used to indent attributes (_auto indents
     *                               attributes so they start at the same column)
     * @param string $linebreak      string used for linebreaks
     * @param bool   $sortAttributes Whether to sort the attributes or not
     *
     * @return string XML start element
     * @see    createEndElement(), createTag()
     */
    public static function createStartElement(
        $qname, $attributes = array(), $namespaceUri = null,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true
    ) {
        // if no attributes hav been set, use empty attributes
        if (!isset($attributes) || !is_array($attributes)) {
            $attributes = array();
        }

        if ($namespaceUri != null) {
            $parts = XML_Util::splitQualifiedName($qname);
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($qname)+2));
            }
        }

        if ($namespaceUri != null) {
            // is a namespace given
            if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
            } else {
                // define this Uri as the default namespace
                $attributes['xmlns'] = $namespaceUri;
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $attributes, $sortAttributes,
            $multiline, $indent, $linebreak
        );
        $element = sprintf('<%s%s>', $qname, $attList);
        return  $element;
    }

    /**
     * Create an end element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createEndElement('myNs:myTag');
     * </code>
     *
     * @param string $qname qualified tagname (including namespace)
     *
     * @return string XML end element
     * @see    createStartElement(), createTag()
     */
    public static function createEndElement($qname)
    {
        $element = sprintf('</%s>', $qname);
        return $element;
    }

    /**
     * Create an XML comment
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createComment('I am a comment');
     * </code>
     *
     * @param string $content content of the comment
     *
     * @return string XML comment
     */
    public static function createComment($content)
    {
        $comment = sprintf('<!-- %s -->', $content);
        return $comment;
    }

    /**
     * Create a CData section
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create a CData section
     * $tag = XML_Util::createCDataSection('I am content.');
     * </code>
     *
     * @param string $data data of the CData section
     *
     * @return string CData section with content
     */
    public static function createCDataSection($data)
    {
        return sprintf(
            '<![CDATA[%s]]>',
            preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data))
        );
    }

    /**
     * Split qualified name and return namespace and local part
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // split qualified tag
     * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
     * </code>
     * the returned array will contain two elements:
     * <pre>
     * array(
     *     'namespace' => 'xslt',
     *     'localPart' => 'stylesheet'
     * );
     * </pre>
     *
     * @param string $qname     qualified tag name
     * @param string $defaultNs default namespace (optional)
     *
     * @return array array containing namespace and local part
     */
    public static function splitQualifiedName($qname, $defaultNs = null)
    {
        if (strstr($qname, ':')) {
            $tmp = explode(':', $qname);
            return array(
                'namespace' => $tmp[0],
                'localPart' => $tmp[1]
            );
        }
        return array(
            'namespace' => $defaultNs,
            'localPart' => $qname
        );
    }

    /**
     * Check, whether string is valid XML name
     *
     * <p>XML names are used for tagname, attribute names and various
     * other, lesser known entities.</p>
     * <p>An XML name may only consist of alphanumeric characters,
     * dashes, undescores and periods, and has to start with a letter
     * or an underscore.</p>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // verify tag name
     * $result = XML_Util::isValidName('invalidTag?');
     * if (is_a($result, 'PEAR_Error')) {
     *    print 'Invalid XML name: ' . $result->getMessage();
     * }
     * </code>
     *
     * @param string $string string that should be checked
     *
     * @return mixed true, if string is a valid XML name, PEAR error otherwise
     *
     * @todo support for other charsets
     * @todo PEAR CS - unable to avoid 85-char limit on second preg_match
     */
    public static function isValidName($string)
    {
        // check for invalid chars
        if (!is_string($string) || !strlen($string) || !preg_match('/^[[:alpha:]_]\\z/', $string[0])) {
            return XML_Util::raiseError(
                'XML names may only start with letter or underscore',
                XML_UTIL_ERROR_INVALID_START
            );
        }

        // check for invalid chars
        $match = preg_match(
            '/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?'
            . '[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/',
            $string
        );
        if (!$match) {
            return XML_Util::raiseError(
                'XML names may only contain alphanumeric '
                . 'chars, period, hyphen, colon and underscores',
                XML_UTIL_ERROR_INVALID_CHARS
            );
        }
        // XML name is valid
        return true;
    }

    /**
     * Replacement for XML_Util::raiseError
     *
     * Avoids the necessity to always require
     * PEAR.php
     *
     * @param string $msg  error message
     * @param int    $code error code
     *
     * @return PEAR_Error
     * @todo   PEAR CS - should this use include_once instead?
     */
    public static function raiseError($msg, $code)
    {
        include_once 'PEAR.php';
        return PEAR::raiseError($msg, $code);
    }
}
?>
PK��Z#F��:�:pearcmd.phpnu�[���<?php
/**
 * PEAR, the PHP Extension and Application Repository
 *
 * Command line interface
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Stig Bakken <ssb@php.net>
 * @author    Tomas V.V.Cox <cox@idecnet.com>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 */

@ob_end_clean();
if (!defined('PEAR_RUNTYPE')) {
    // this is defined in peclcmd.php as 'pecl'
    define('PEAR_RUNTYPE', 'pear');
}
define('PEAR_IGNORE_BACKTRACE', 1);
/**
 * @nodep Gtk
 */
//the space is needed for windows include paths with trailing backslash
// http://pear.php.net/bugs/bug.php?id=19482
if ('/opt/alt/php74/usr/share/pear ' != '@'.'include_path'.'@ ') {
    ini_set('include_path', trim('/opt/alt/php74/usr/share/pear '). PATH_SEPARATOR .  get_include_path());
    $raw = false;
} else {
    // this is a raw, uninstalled pear, either a cvs checkout, or php distro
    ini_set('include_path', dirname(__DIR__) . PATH_SEPARATOR . get_include_path());
    $raw = true;
}
@ini_set('allow_url_fopen', true);
@set_time_limit(0);
ob_implicit_flush(true);
@ini_set('track_errors', true);
@ini_set('html_errors', false);
$_PEAR_PHPDIR = '#$%^&*';
set_error_handler('error_handler');

$pear_package_version = "1.10.16";

require_once 'PEAR.php';
require_once 'PEAR/Frontend.php';
require_once 'PEAR/Config.php';
require_once 'PEAR/Command.php';
require_once 'Console/Getopt.php';


PEAR_Command::setFrontendType('CLI');
$all_commands = PEAR_Command::getCommands();

$argv = Console_Getopt::readPHPArgv();
// fix CGI sapi oddity - the -- in pear.bat/pear is not removed
if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
    unset($argv[1]);
    $argv = array_values($argv);
}
$progname = PEAR_RUNTYPE;
array_shift($argv);
$options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV");
if (PEAR::isError($options)) {
    usage($options);
}

$opts = $options[0];

$fetype = 'CLI';
if ($progname == 'gpear' || $progname == 'pear-gtk') {
    $fetype = 'Gtk2';
} else {
    foreach ($opts as $opt) {
        if ($opt[0] == 'G') {
            $fetype = 'Gtk2';
        }
    }
}

$pear_user_config = '';
$pear_system_config = '';
$store_user_config = false;
$store_system_config = false;
$verbose = 1;

foreach ($opts as $opt) {
    switch ($opt[0]) {
    case 'c':
        $pear_user_config = $opt[1];
        break;
    case 'C':
        $pear_system_config = $opt[1];
        break;
    }
}

PEAR_Command::setFrontendType($fetype);
$ui = &PEAR_Command::getFrontendObject();
$config = &PEAR_Config::singleton($pear_user_config, $pear_system_config);

if (PEAR::isError($config)) {
    $_file = '';
    if ($pear_user_config !== false) {
        $_file .= $pear_user_config;
    }
    if ($pear_system_config !== false) {
        $_file .= '/' . $pear_system_config;
    }
    if ($_file == '/') {
        $_file = 'The default config file';
    }
    $config->getMessage();
    $ui->outputData("ERROR: $_file is not a valid config file or is corrupted.");
    // We stop, we have no idea where we are :)
    exit(1);
}

// this is used in the error handler to retrieve a relative path
$_PEAR_PHPDIR = $config->get('php_dir');
$ui->setConfig($config);
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError"));

$verbose = $config->get("verbose");
$cmdopts = array();

if ($raw) {
    if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) {
        $found = false;
        foreach ($opts as $opt) {
            if ($opt[0] == 'd' || $opt[0] == 'D') {
                // the user knows what they are doing, and are setting config values
                $found = true;
            }
        }
        if (!$found) {
            // no prior runs, try to install PEAR
            $parent = dirname(__FILE__);
            if (strpos($parent, 'scripts')) {
                $grandparent = dirname($parent);
                $packagexml = $grandparent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $grandparent;
            } else {
                $packagexml = $parent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $parent;
            }
            if (file_exists($packagexml)) {
                $options[1] = array(
                    'install',
                    $packagexml
                );
                $config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php');
                $config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data');
                $config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs');
                $config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests');
                $config->set(
                    'ext_dir',
                    $pearbase . DIRECTORY_SEPARATOR . 'extensions'
                );
                $config->set('bin_dir', $pearbase);
                $config->mergeConfigFile($pearbase . 'pear.ini', false);
                $config->store();
                $config->set('auto_discover', 1);
            }
        }
    }
}
foreach ($opts as $opt) {
    $param = !empty($opt[1]) ? $opt[1] : true;
    switch ($opt[0]) {
    case 'd':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected -d config_value=value, ' .
                'received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'user');
        break;
    case 'D':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'system');
        break;
    case 's':
        $store_user_config = true;
        break;
    case 'S':
        $store_system_config = true;
        break;
    case 'u':
        $config->remove($param, 'user');
        break;
    case 'v':
        $config->set('verbose', $config->get('verbose') + 1);
        break;
    case 'q':
        $config->set('verbose', $config->get('verbose') - 1);
        break;
    case 'V':
        usage(null, 'version');
    case 'c':
    case 'C':
        break;
    default:
        // all non pear params goes to the command
        $cmdopts[$opt[0]] = $param;
        break;
    }
}

if ($store_system_config) {
    $config->store('system');
}

if ($store_user_config) {
    $config->store('user');
}

$command = (isset($options[1][0])) ? $options[1][0] : null;
if (empty($command) && ($store_user_config || $store_system_config)) {
    exit;
}

if ($fetype == 'Gtk2') {
    if (!$config->validConfiguration()) {
        PEAR::raiseError(
            "CRITICAL ERROR: no existing valid configuration files found in " .
            "files '$pear_user_config' or '$pear_system_config', " .
            "please copy an existing configuration file to one of these " .
            "locations, or use the -c and -s options to create one"
        );
    }
    Gtk::main();
} else {
    do {
        if ($command == 'help') {
            usage(null, isset($options[1][1]) ? $options[1][1] : null);
        }

        if (!$config->validConfiguration()) {
            PEAR::raiseError(
                "CRITICAL ERROR: no existing valid configuration files found " .
                "in files '$pear_user_config' or '$pear_system_config', " .
                "please copy an existing configuration file to one of " .
                "these locations, or use the -c and -s options to create one"
            );
        }

        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        $cmd = PEAR_Command::factory($command, $config);
        PEAR::popErrorHandling();
        if (PEAR::isError($cmd)) {
            usage(null, isset($options[1][0]) ? $options[1][0] : null);
        }

        $short_args = $long_args = null;
        PEAR_Command::getGetoptArgs($command, $short_args, $long_args);
        array_shift($options[1]);
        $tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args);

        if (PEAR::isError($tmp)) {
            break;
        }

        list($tmpopt, $params) = $tmp;
        $opts = array();
        foreach ($tmpopt as $foo => $tmp2) {
            list($opt, $value) = $tmp2;
            if ($value === null) {
                $value = true; // options without args
            }

            if (strlen($opt) == 1) {
                $cmdoptions = $cmd->getOptions($command);
                foreach ($cmdoptions as $o => $d) {
                    if (isset($d['shortopt']) && $d['shortopt'] == $opt) {
                        $opts[$o] = $value;
                    }
                }
            } else {
                if (substr($opt, 0, 2) == '--') {
                    $opts[substr($opt, 2)] = $value;
                }
            }
        }

        $ok = $cmd->run($command, $opts, $params);
        if ($ok === false) {
            PEAR::raiseError("unknown command `$command'");
        }

        if (PEAR::isError($ok)) {
            PEAR::setErrorHandling(
                PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")
            );
            PEAR::raiseError($ok);
        }
    } while (false);
}

// {{{ usage()

/**
 * Display usage information
 *
 * @param mixed $error       Optional error message
 * @param mixed $helpsubject Optional subject/command to display help for
 *
 * @return void
 */
function usage($error = null, $helpsubject = null)
{
    global $progname, $all_commands;
    $stdout = fopen('php://stdout', 'w');
    if (PEAR::isError($error)) {
        fputs($stdout, $error->getMessage() . "\n");
    } elseif ($error !== null) {
        fputs($stdout, "$error\n");
    }

    if ($helpsubject != null) {
        $put = cmdHelp($helpsubject);
    } else {
        $put = "Commands:\n";
        $maxlen = max(array_map("strlen", $all_commands));
        $formatstr = "%-{$maxlen}s  %s\n";
        ksort($all_commands);
        foreach ($all_commands as $cmd => $class) {
            $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd));
        }
        $put .=
            "Usage: $progname [options] command [command-options] <parameters>\n".
            "Type \"$progname help options\" to list all options.\n".
            "Type \"$progname help shortcuts\" to list all command shortcuts.\n".
            "Type \"$progname help version\" or ".
            "\"$progname version\" to list version information.\n".
            "Type \"$progname help <command>\" to get the help ".
            "for the specified command.";
    }
    fputs($stdout, "$put\n");
    fclose($stdout);

    if ($error === null) {
        exit(0);
    }
    exit(1);
}

/**
 * Return help string for specified command
 *
 * @param string $command Command to return help for
 *
 * @return void
 */
function cmdHelp($command)
{
    global $progname, $all_commands, $config;
    if ($command == "options") {
        return
        "Options:\n".
        "     -v         increase verbosity level (default 1)\n".
        "     -q         be quiet, decrease verbosity level\n".
        "     -c file    find user configuration in `file'\n".
        "     -C file    find system configuration in `file'\n".
        "     -d foo=bar set user config variable `foo' to `bar'\n".
        "     -D foo=bar set system config variable `foo' to `bar'\n".
        "     -G         start in graphical (Gtk) mode\n".
        "     -s         store user configuration\n".
        "     -S         store system configuration\n".
        "     -u foo     unset `foo' in the user configuration\n".
        "     -h, -?     display help/usage (this message)\n".
        "     -V         version information\n";
    } elseif ($command == "shortcuts") {
        $sc = PEAR_Command::getShortcuts();
        $ret = "Shortcuts:\n";
        foreach ($sc as $s => $c) {
            $ret .= sprintf("     %-8s %s\n", $s, $c);
        }
        return $ret;

    } elseif ($command == "version") {
        return "PEAR Version: ".$GLOBALS['pear_package_version'].
               "\nPHP Version: ".phpversion().
               "\nZend Engine Version: ".zend_version().
               "\nRunning on: ".php_uname();

    } elseif ($help = PEAR_Command::getHelp($command)) {
        if (is_string($help)) {
            return "$progname $command [options] $help\n";
        }

        if ($help[1] === null) {
            return "$progname $command $help[0]";
        }

        return "$progname $command [options] $help[0]\n$help[1]";
    }

    return "Command '$command' is not valid, try '$progname help'";
}

// }}}

/**
 * error_handler
 *
 * @param mixed $errno  Error number
 * @param mixed $errmsg Message
 * @param mixed $file   Filename
 * @param mixed $line   Line number
 *
 * @access public
 * @return boolean
 */
function error_handler($errno, $errmsg, $file, $line)
{
    if ((!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) && ($errno & E_STRICT)) {
        return; // E_STRICT
    }
    if ($errno & E_DEPRECATED) {
        return; // E_DEPRECATED
    }
    if (!(error_reporting() & $errno) &&
        isset($GLOBALS['config']) &&
        $GLOBALS['config']->get('verbose') < 4
    ) {
        return false; // @silenced error, show all if debug is high enough
    }
    $errortype = array (
        E_DEPRECATED  => 'Deprecated Warning',
        E_ERROR   =>  "Error",
        E_WARNING   =>  "Warning",
        E_PARSE   =>  "Parsing Error",
        E_NOTICE   =>  "Notice",
        E_CORE_ERROR  =>  "Core Error",
        E_CORE_WARNING  =>  "Core Warning",
        E_COMPILE_ERROR  =>  "Compile Error",
        E_COMPILE_WARNING =>  "Compile Warning",
        E_USER_ERROR =>  "User Error",
        E_USER_WARNING =>  "User Warning",
        E_USER_NOTICE =>  "User Notice"
    );
    if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) {
        $errortype[E_STRICT] = 'Strict Warning';
    }
    $prefix = $errortype[$errno];
    global $_PEAR_PHPDIR;
    if (stristr($file, $_PEAR_PHPDIR)) {
        $file = substr($file, strlen($_PEAR_PHPDIR) + 1);
    } else {
        $file = basename($file);
    }
    print "\n$prefix: $errmsg in $file on line $line\n";
    return false;
}


/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * indent-tabs-mode: nil
 * mode: php
 * End:
 */
// vim600:syn=php
PK��Z�0$�-- .pkgxml/Pear_File_MARC-1.4.1.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.10.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
 <name>File_MARC</name>
 <channel>pear.php.net</channel>
 <summary>Parse, modify, and create MARC records</summary>
 <description>The standard for machine-readable cataloging (MARC) records is documented at http://loc.gov/marc/. This package enables you to read existing MARC records from a file, string, or (using the YAZ extension), from a Z39.50 source. You can also use this package to create new MARC records.

This package is based on the PHP MARC package, originally called &quot;php-marc&quot;, that is part of the Emilda Project (http://www.emilda.org).  Christoffer Landtman generously agreed to make the &quot;php-marc&quot; code available under the GNU LGPL so it could be used as the basis of this PEAR package.</description>
 <lead>
  <name>Dan Scott</name>
  <user>dbs</user>
  <email>dbs@php.net</email>
  <active>yes</active>
 </lead>
 <date>2019-11-13</date>
 <time>17:33:33</time>
 <version>
  <release>1.4.1</release>
  <api>1.4.0</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license uri="http://www.gnu.org/copyleft/lesser.html">GNU Lesser General Public License</license>
 <notes>
1.4.1
  * Reintroduce include_path to composer.json
 </notes>
 <contents>
  <dir baseinstalldir="File" name="/">
   <file baseinstalldir="/" md5sum="ffe2590635f404af055fe731da105939" name="File/MARC/Lint/CodeData.php" role="php" />
   <file baseinstalldir="/" md5sum="a3b9e1c817e67f59add05593500d463e" name="File/MARC/Control_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="acba4463f8e40d6ee4e7ba1f2dc53123" name="File/MARC/Data_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="378f483ec1fd161cd9dfb9b05db58d66" name="File/MARC/Exception.php" role="php" />
   <file baseinstalldir="/" md5sum="a9ba69030cbf4847292b9975e9d922c6" name="File/MARC/Field.php" role="php" />
   <file baseinstalldir="/" md5sum="c37351c7c80927ce6bb1e662510f9183" name="File/MARC/Lint.php" role="php" />
   <file baseinstalldir="/" md5sum="c5ac39e3d25eb0108b9dd5ad8466c821" name="File/MARC/List.php" role="php" />
   <file baseinstalldir="/" md5sum="7af6ce78cde4bb246e4e96709e90d2c0" name="File/MARC/Record.php" role="php" />
   <file baseinstalldir="/" md5sum="df5f97139685f0ad04e47fdbb67e3968" name="File/MARC/Subfield.php" role="php" />
   <file baseinstalldir="/" md5sum="6e102262dfd5d65d8d5a6221dfc74edd" name="File/MARC.php" role="php" />
   <file baseinstalldir="/" md5sum="8b64040d2d18ac4b994595a148266a66" name="File/MARCBASE.php" role="php" />
   <file baseinstalldir="/" md5sum="f5a17a60d34e84e2ee7ca1e5c5c6c620" name="File/MARCXML.php" role="php" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="examples/example.mrc" role="doc" />
   <file baseinstalldir="File" md5sum="1aea40df9f1c2e32f8e065fe8da0a3b5" name="examples/marc_yaz.php" role="doc" />
   <file baseinstalldir="File" md5sum="70ae317e0890d5896e3ffccdd293369a" name="examples/read.php" role="doc" />
   <file baseinstalldir="File" md5sum="54efb9d920ac775bfc847a83a2dec73a" name="examples/subfields.php" role="doc" />
   <file baseinstalldir="File" md5sum="14297da35b510c496cd1f328cf3bb301" name="tests/bad_example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="0dd4c6dbad6e8608d0ebf9d24425955d" name="tests/bad_example.xml" role="test" />
   <file baseinstalldir="File" md5sum="216a6f9d53f6d3d8e22d81fdc10f4bc1" name="tests/camel.mrc" role="test" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="tests/example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="9455aec3371f79cf7d31281fd03f5171" name="tests/marc_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="577e2f5f89fd48cf1a3576a29d2958f8" name="tests/marc_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a6a586354b9a06c880c2a7470dd828d7" name="tests/marc_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1c7e2fc5572a0f9362a771c260a1fe3" name="tests/marc_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="84f85ac7f8a2532e4e90ccde7764556a" name="tests/marc_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="889e5e906a97de7a0e94b0c5f30e70e7" name="tests/marc_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="be823dc8a8efb408de06371ab802efcc" name="tests/marc_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="af44490aafea44e5120f881cb81cdad9" name="tests/marc_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ac9f2a7aeb24900a11f5102744179ae3" name="tests/marc_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5e43eb5cddbb4f2bd0d6405cd95b80aa" name="tests/marc_010.phpt" role="test" />
   <file baseinstalldir="File" md5sum="2e1cd8509c0bf04ec77fc0f51375f611" name="tests/marc_011.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bc49ca48623102c8ac07679fa77a3dd9" name="tests/marc_012.phpt" role="test" />
   <file baseinstalldir="File" md5sum="245a3b20e0da1973535503e28efd1d3a" name="tests/marc_013.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ce69aa734856dd40d60d30c77bdef53a" name="tests/marc_014.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7b61cdd31035e60682fa92c5d519d997" name="tests/marc_015.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7f4f597fe1adaa3507eb87fc4875dbd2" name="tests/marc_016.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4262efd5fcacbd7503323681f4552430" name="tests/marc_017.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ee1623d7bda54ba4f741b2319b158f82" name="tests/marc_018.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8006c03fbab0f04377342086fafd3982" name="tests/marc_019.phpt" role="test" />
   <file baseinstalldir="File" md5sum="f5ae5b25e0ac1104314433d9e5b1f7fe" name="tests/marc_020.phpt" role="test" />
   <file baseinstalldir="File" md5sum="94d8f99e86585671a1b2d3043aeb6360" name="tests/marc_021.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bb891a890effe0e77e1759043f4846d8" name="tests/marc_022.phpt" role="test" />
   <file baseinstalldir="File" md5sum="faf77dcb5cdd002c09169a14bfded65e" name="tests/marc_023.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0e6c4a23f5da7df64fdd4b3b1149bbee" name="tests/marc_16783.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4ea8b3520beda378db15960f1c50493a" name="tests/marc_field_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="743850ef61df69c4340be44a03bccb5a" name="tests/marc_field_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8c765f1398b49df257d86d22ac6e4f8d" name="tests/marc_field_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d4216cf930a308e0d02553bd3914f294" name="tests/marc_field_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dd59514b474b78371ad522a3e13b76b7" name="tests/marc_field_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5295bfd02a8424acac1c91de26b552c7" name="tests/marc_field_21246.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6f95f09442ccf6b93df92986f58b270d" name="tests/marc_lint_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="18d721f8871edd925624ccbdd15444fb" name="tests/marc_lint_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4eb86a2f4e0a74dedcb0bf2511da6ca1" name="tests/marc_lint_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="10430fee0a1352d0528f1507b34c57e1" name="tests/marc_lint_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0dcd07a18577d7b22392a2214cd6436c" name="tests/marc_lint_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fd17798fc535562e5e64461f449516b2" name="tests/marc_record_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="141b455ccf67a60c4eac44c77960f2e2" name="tests/marc_subfield_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1e23464ee0eec47ddca2af9a9922926" name="tests/marc_subfield_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="1d7903e8c244d647220b318b4bc758d1" name="tests/marc_xml_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="22cae3c752d843b78f583dcd92801534" name="tests/marc_xml_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="c0716d23e0f960abf8d53ad6014a413a" name="tests/marc_xml_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7645fa19e28aca041a124fc5e2c12bd3" name="tests/marc_xml_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b08b28c3251625b8b6e4d7ab376b0185" name="tests/marc_xml_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6cd0934ddbf65d2d7e9ea5d108977ff7" name="tests/marc_xml_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ffdce4aa190268fa7cbbf3bb45383abf" name="tests/marc_xml_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="998a4c1ce00ff100f39ffa9fc49a212f" name="tests/marc_xml_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a38a67c590869f2b0a4859a910fd9e89" name="tests/marc_xml_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="db39c5055a570fcda12bb7c5fa1e3b4d" name="tests/marc_xml_16642.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dc075f4a271bd7182378a3874bd5b39e" name="tests/marc_xml_namespace.phpt" role="test" />
   <file baseinstalldir="File" md5sum="208200d9a979ac360c4d326e9789b6b7" name="tests/marc_xml_namespace_prefix.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d87774ede82222cfc12b2c2a06f57a3a" name="tests/marc_xml_rsinger.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fb44e3eb69f1a37115235fc829c39542" name="tests/namespace.xml" role="test" />
   <file baseinstalldir="File" md5sum="e6de4d809b0af5dd99fd352eb60616a1" name="tests/skipif.inc" role="test" />
   <file baseinstalldir="File" md5sum="a0166a4ff0bc0bb283e854f11beaa793" name="tests/music.mrc" role="test" />
   <file baseinstalldir="File" md5sum="993ce494befbc25dc1326527b30b4782" name="tests/music.xml" role="test" />
   <file baseinstalldir="File" md5sum="6b0c87f0cd459ed7322c25d403b164cc" name="tests/bigarchive.xml" role="test" />
   <file baseinstalldir="File" md5sum="be850aa6ab4ac52b8c6c214c30b574af" name="tests/onerecord.xml" role="test" />
   <file baseinstalldir="File" md5sum="4f43fec7b276267eec5258044853ccc8" name="tests/sandburg.mrc" role="test" />
   <file baseinstalldir="File" md5sum="e216b95f905dd240c9bde372950e4073" name="tests/sandburg.xml" role="test" />
   <file baseinstalldir="File" md5sum="e81a92188ea0dcd9c108a63fb32b3f4f" name="tests/xmlescape.mrc" role="test" />
   <file baseinstalldir="File" md5sum="8f9f63ed6a80191d89a2296fa4c1a30b" name="CHANGELOG" role="doc" />
   <file baseinstalldir="File" md5sum="fbc093901857fcd118f065f900982c24" name="LICENSE" role="doc" />
  </dir>
 </contents>
 <dependencies>
  <required>
   <php>
    <min>5.6</min>
   </php>
   <pearinstaller>
    <min>1.4.0</min>
   </pearinstaller>
  </required>
  <optional>
   <package>
    <name>Validate_ISPN</name>
    <channel>pear.php.net</channel>
   </package>
  </optional>
 </dependencies>
 <phprelease />
</package>
PKm�ZPi��.depdbnu�[���PKm�Z�{��
�Mail/null.phpnu�[���PKm�ZE@�%>>
Mail/sendmail.phpnu�[���PKm�Z��A~�{�{�;Mail/RFC822.phpnu�[���PKn�Z�+V����
[�Mail/mime.phpnu�[���PKn�Zx�ع���D�Mail/mimeDecode.phpnu�[���PKn�ZB�_Ǭ=�=
@(Mail/smtp.phpnu�[���PKn�ZwԐE;E;)fMail/smtpmx.phpnu�[���PKn�Z�؛�J�J���Mail/mimePart.phpnu�[���PKn�ZB��shh
8YMail/mock.phpnu�[���PKn�Z@iE�\\
�lMail/mail.phpnu�[���PKn�Zv�.locknu�[���PKn�Z�*�z%-%- ��Structures/LinkedList/Double.phpnu�[���PKn�Z����p:p:  �Structures/LinkedList/Single.phpnu�[���PKn�ZUyv���Structures/Graph.phpnu�[���PKn�Z�C� + +CStructures/Graph/Node.phpnu�[���PKn�Z9����,�1Structures/Graph/Manipulator/AcyclicTest.phpnu�[���PKn�Z~(�htt2�HStructures/Graph/Manipulator/TopologicalSorter.phpnu�[���PKn�Z�J�}
}
_dAuth/SASL/Anonymous.phpnu�[���PKn�ZP(~�T
T
#rAuth/SASL/CramMD5.phpnu�[���PKn�Z����==�Auth/SASL/Plain.phpnu�[���PKn�Z�<� OO<�Auth/SASL/Login.phpnu�[���PKn�Z%ׅtg!g!ΘAuth/SASL/DigestMD5.phpnu�[���PKn�Z�T�|�Auth/SASL/Common.phpnu�[���PKn�ZvR�r,,��Auth/SASL/External.phpnu�[���PKn�Zќ��0�0H�Auth/SASL/SCRAM.phpnu�[���PKn�Z2r����
�	Auth/SASL.phpnu�[���PKn�Z�T�,�,�OS/Guess.phpnu�[���PKn�Z�����KPEAR/Config.phpnu�[���PKn�Z�`�eEAEA
.ZPEAR/REST.phpnu�[���PKn�Z��ym6m6��PEAR/Exception.phpnu�[���PKn�Zr"����_�PEAR/ChannelFile.phpnu�[���PKn�Z��gk�U�U?�PEAR/Validate.phpnu�[���PKn�Zd֣S��u�PEAR/Command/Pickle.xmlnu�[���PKn�Z�z��k<k<W�PEAR/Command/Config.phpnu�[���PKn�Z݄<ii	1PEAR/Command/Mirror.xmlnu�[���PKn�Z,��t"u"u�3PEAR/Command/Remote.phpnu�[���PKn�Z
�\���"�PEAR/Command/Remote.xmlnu�[���PKn�Zj���!�!X�PEAR/Command/Install.xmlnu�[���PKo�Z�%q������PEAR/Command/Channels.phpnu�[���PKo�Znmi?;�;��[	PEAR/Command/Install.phpnu�[���PKo�Z�X�

#
PEAR/Command/Auth.phpnu�[���PKo�Z���s6
6
T-
PEAR/Command/Config.xmlnu�[���PKo�Z�%Fii�:
PEAR/Command/Test.xmlnu�[���PKo�ZZ h66A
PEAR/Command/Package.xmlnu�[���PKo�Z�w��zz�]
PEAR/Command/Channels.xmlnu�[���PKo�Z+9ҜҜ�n
PEAR/Command/Package.phpnu�[���PKo�Z
u����PEAR/Command/Build.xmlnu�[���PKo�Z������
PEAR/Command/Mirror.phpnu�[���PKp�Z,_�h/h/�PEAR/Command/Test.phpnu�[���PKp�Z�%sp  6OPEAR/Command/Common.phpnu�[���PKp�Z0(;rʹʹ�oPEAR/Command/Registry.phpnu�[���PKp�Z�4�{���$PEAR/Command/Auth.xmlnu�[���PKp�Z��#S
S
�)PEAR/Command/Build.phpnu�[���PKp�Z���u��S4PEAR/Command/Registry.xmlnu�[���PKp�Z�P>>�;PEAR/Command/Pickle.phpnu�[���PKp�Z��T�I�I�yPEAR/Builder.phpnu�[���PKp�Z[
�W��3�PEAR/XMLParser.phpnu�[���PKp�Zl(e���t�PEAR/Downloader.phpnu�[���PKp�Z�b������
PEAR/ErrorStack.phpnu�[���PKp�Z(Pz����ePEAR/Proxy.phpnu�[���PKp�Z��'����|PEAR/RunTest.phpnu�[���PKq�Zj�y99�	PEAR/Validator/PECL.phpnu�[���PKq�Zp�����aPEAR/Dependency2.phpnu�[���PKq�Z��wv@@��PEAR/PackageFile/v2.phpnu�[���PKq�ZC�8�L�L!:�PEAR/PackageFile/v2/Validator.phpnu�[���PKq�Z���=_�_�6PEAR/PackageFile/v2/rw.phpnu�[���PKq�Z�5�������,PEAR/PackageFile/v1.phpnu�[���PKq�Z�ɁɁ!��PEAR/PackageFile/Generator/v2.phpnu�[���PKq�Z`�=����!�tPEAR/PackageFile/Generator/v1.phpnu�[���PKr�Z��OWHH�9PEAR/PackageFile/Parser/v2.phpnu�[���PKr�Z�_=�@�@`FPEAR/PackageFile/Parser/v1.phpnu�[���PKr�Zc��__5�PEAR/DependencyDB.phpnu�[���PKr�Z�@P��{�PEAR/ChannelFile/Parser.phpnu�[���PKr�Z��_�0�0r�PEAR/Command.phpnu�[���PKr�Z�ٲ�=�==PEAR/PackageFile.phpnu�[���PKr�Z�JD��g\PEAR/Task/Replace.phpnu�[���PKr�Z&%75))�wPEAR/Task/Windowseol/rw.phpnu�[���PKr�Z�3}}PEAR/Task/Replace/rw.phpnu�[���PKr�Z&
i."x�PEAR/Task/Postinstallscript/rw.phpnu�[���PKr�Z�-!�PEAR/Task/Common.phpnu�[���PKr�ZD$���I�PEAR/Task/Windowseol.phpnu�[���PKr�ZZ�E�x9x9��PEAR/Task/Postinstallscript.phpnu�[���PKr�Z\k��K�PEAR/Task/Unixeol/rw.phpnu�[���PKr�Z�������PEAR/Task/Unixeol.phpnu�[���PKr�Z�W�f���PEAR/REST/10.phpnu�[���PKr�Z��Y�;;ąPEAR/REST/13.phpnu�[���PKr�Z,#y��+�+�PEAR/REST/11.phpnu�[���PKr�Z��U  D�PEAR/Packager.phpnu�[���PKr�ZZ�bgbg�PEAR/Common.phpnu�[���PKr�Z$���(�(FsPEAR/Registry.phpnu�[���PKr�Z��	MdMd?�PEAR/Frontend/CLI.phpnu�[���PKr�Z��

�PEAR/Installer/Role/Doc.phpnu�[���PKr�Z��/��)PEAR/Installer/Role/Cfg.xmlnu�[���PKr�Z>1H���PEAR/Installer/Role/Www.xmlnu�[���PKr�Z�?m

PEAR/Installer/Role/Php.phpnu�[���PKr�Z*Y|	%%`PEAR/Installer/Role/Man.phpnu�[���PKr�Z���BB�PEAR/Installer/Role/Ext.xmlnu�[���PKr�Zp��""]PEAR/Installer/Role/Src.xmlnu�[���PKr�Zh&P*���PEAR/Installer/Role/Doc.xmlnu�[���PKr�ZB] ���PEAR/Installer/Role/Test.xmlnu�[���PKr�Zz�q����PEAR/Installer/Role/Php.xmlnu�[���PKr�Z	��
|PEAR/Installer/Role/Data.phpnu�[���PKs�Z�0�c���PEAR/Installer/Role/Man.xmlnu�[���PKs�Z��K

�PEAR/Installer/Role/Ext.phpnu�[���PKs�ZY��� PEAR/Installer/Role/Test.phpnu�[���PKs�Z@v�а�z#PEAR/Installer/Role/Script.xmlnu�[���PKs�Zf�sz��x%PEAR/Installer/Role/Data.xmlnu�[���PKs�Z?���GGV'PEAR/Installer/Role/Common.phpnu�[���PKs�Z�^D{		�?PEAR/Installer/Role/Www.phpnu�[���PKs�Z�Ƥ?CPEAR/Installer/Role/Cfg.phpnu�[���PKs�Z��[�	SPEAR/Installer/Role/Script.phpnu�[���PKs�Z��srrjVPEAR/Installer/Role/Src.phpnu�[���PKs�ZV�Z���'ZPEAR/Installer/Role.phpnu�[���PKs�Z�{�	�)�)*yPEAR/Downloader/Package.phpnu�[���PKs�Z.�4���$�PEAR/Frontend.phpnu�[���PKs�Z،�w��_�PEAR/Installer.phpnu�[���PKs�ZXxo��-j�Symfony/Bridge/Doctrine/Logger/DbalLogger.phpnu�[���PKs�Ze�OO&b�Symfony/Bridge/Doctrine/autoloader.phpnu�[���PKs�Z��X+��8�Symfony/Bridge/Doctrine/CacheWarmer/ProxyCacheWarmer.phpnu�[���PKs�Z	�9,��5i�Symfony/Bridge/Doctrine/Form/DoctrineOrmExtension.phpnu�[���PKs�Z�0���NX�Symfony/Bridge/Doctrine/Form/EventListener/MergeDoctrineCollectionListener.phpnu�[���PKs�Z!%d==A��Symfony/Bridge/Doctrine/Form/ChoiceList/EntityLoaderInterface.phpnu�[���PKs�Z�	?x�7�7<4�Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.phpnu�[���PKs�ZGC�t��A<-Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.phpnu�[���PKs�Z`.
qpp7�9Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.phpnu�[���PKs�ZCi�PPMZQSymfony/Bridge/Doctrine/Form/DataTransformer/CollectionToArrayTransformer.phpnu�[���PKs�Z憝��0'YSymfony/Bridge/Doctrine/Form/Type/EntityType.phpnu�[���PKs�ZS;,:��2-]Symfony/Bridge/Doctrine/Form/Type/DoctrineType.phpnu�[���PKs�ZW&v��<�wSymfony/Bridge/Doctrine/Security/User/EntityUserProvider.phpnu�[���PKs�Z�����Et�Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.phpnu�[���PKs�Z(��y��9�Symfony/Bridge/Doctrine/Validator/DoctrineInitializer.phpnu�[���PKs�ZQГ��>�Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.phpnu�[���PKs�Z:�d�G5�Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.phpnu�[���PKs�Z�Ta�==B��Symfony/Bridge/Doctrine/ExpressionLanguage/DoctrineParserCache.phpnu�[���PKs�Z��qm
m
-m�Symfony/Bridge/Doctrine/RegistryInterface.phpnu�[���PKs�Zlf/�qq=7�Symfony/Bridge/Doctrine/DataFixtures/ContainerAwareLoader.phpnu�[���PKs�Z����=�Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.phpnu�[���PKs�Z�����C��Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerSchema.phpnu�[���PKs�ZOlQ�996��Symfony/Bridge/Doctrine/ContainerAwareEventManager.phpnu�[���PKs�Z؈����3D�Symfony/Bridge/Doctrine/Test/DoctrineTestHelper.phpnu�[���PKs�Z̳֨�+��Symfony/Bridge/Doctrine/ManagerRegistry.phpnu�[���PKs�Z+çxAA?�Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.phpnu�[���PKs�Z*�+��J�JIBSymfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.phpnu�[���PKs�Z���*��SVaSymfony/Bridge/Doctrine/DependencyInjection/Security/UserProvider/EntityFactory.phpnu�[���PKs�Z��㛕�Q�hSymfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterMappingsPass.phpnu�[���PKs�Z~�YAAeԀSymfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.phpnu�[���PKs�Z��,���S��Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/DoctrineValidationPass.phpnu�[���PKs�Z��4NN%,�Symfony/Bridge/Monolog/autoloader.phpnu�[���PKs�Z��մ��1ϡSymfony/Bridge/Monolog/Handler/FirePHPHandler.phpnu�[���PKs�Z��Zv��/©Symfony/Bridge/Monolog/Handler/DebugHandler.phpnu�[���PKs�Z�y���1دSymfony/Bridge/Monolog/Handler/ConsoleHandler.phpnu�[���PKs�Z��*vv5�Symfony/Bridge/Monolog/Handler/SwiftMailerHandler.phpnu�[���PKs�Z���"II3��Symfony/Bridge/Monolog/Handler/ChromePhpHandler.phpnu�[���PKs�Z��;��	�	!��Symfony/Bridge/Monolog/Logger.phpnu�[���PKs�Z��b115��Symfony/Bridge/Monolog/Formatter/ConsoleFormatter.phpnu�[���PKt�Z�,��1l�Symfony/Bridge/Monolog/Processor/WebProcessor.phpnu�[���PKt�Z�$�KK"l�Symfony/Bridge/Twig/autoloader.phpnu�[���PKt�Z�)�UU1	�Symfony/Bridge/Twig/Translation/TwigExtractor.phpnu�[���PKt�Z6DZ77*��Symfony/Bridge/Twig/Node/StopwatchNode.phpnu�[���PKt�Z,
�@��5P�Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.phpnu�[���PKt�Z�
�s>>*ESymfony/Bridge/Twig/Node/FormThemeNode.phpnu�[���PKt�ZP�IAA3�Symfony/Bridge/Twig/Node/TransDefaultDomainNode.phpnu�[���PKt�Z�U,tt,�Symfony/Bridge/Twig/Node/FormEnctypeNode.phpnu�[���PKt�Zʦ\�G
G
&QSymfony/Bridge/Twig/Node/TransNode.phpnu�[���PKt�Z���^��,�%Symfony/Bridge/Twig/Node/RenderBlockNode.phpnu�[���PKt�Z�vq�)+Symfony/Bridge/Twig/Form/TwigRenderer.phpnu�[���PKt�Zb�3�}}8q1Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.phpnu�[���PKt�Z��Qkk2V4Symfony/Bridge/Twig/Form/TwigRendererInterface.phpnu�[���PKt�Z��<��/#7Symfony/Bridge/Twig/Form/TwigRendererEngine.phpnu�[���PKt�Z�GTSymfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.phpnu�[���PKt�Z�)�[n	n	)�`Symfony/Bridge/Twig/NodeVisitor/Scope.phpnu�[���PKt�Z�tA�:`jSymfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.phpnu�[���PKt�Z��9292B�xSymfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twignu�[���PKt�Z��[[Dy�Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twignu�[���PKt�Z.��8H�Symfony/Bridge/Twig/TokenParser/StopwatchTokenParser.phpnu�[���PKt�Z�%]�
�
4��Symfony/Bridge/Twig/TokenParser/TransTokenParser.phpnu�[���PKt�Z�/�	�	:��Symfony/Bridge/Twig/TokenParser/TransChoiceTokenParser.phpnu�[���PKt�Z>����8>�Symfony/Bridge/Twig/TokenParser/FormThemeTokenParser.phpnu�[���PKt�Zʶ�̭�Ao�Symfony/Bridge/Twig/TokenParser/TransDefaultDomainTokenParser.phpnu�[���PKt�Z�9�=KK/��Symfony/Bridge/Twig/Extension/FormExtension.phpnu�[���PKt�Z��|/7�Symfony/Bridge/Twig/Extension/YamlExtension.phpnu�[���PKt�Z��&�a
a
5��Symfony/Bridge/Twig/Extension/HttpKernelExtension.phpnu�[���PKt�ZKΙ���5v�Symfony/Bridge/Twig/Extension/ExpressionExtension.phpnu�[���PKt�Z`�fS..2� Symfony/Bridge/Twig/Extension/RoutingExtension.phpnu�[���PKt�Z�5��mm4] Symfony/Bridge/Twig/Extension/StopwatchExtension.phpnu�[���PKt�Z�?���6. Symfony/Bridge/Twig/Extension/TranslationExtension.phpnu�[���PKt�Zd���oo3�! Symfony/Bridge/Twig/Extension/SecurityExtension.phpnu�[���PKt�Z�����/a' Symfony/Bridge/Twig/Extension/CodeExtension.phpnu�[���PKu�Z^D��dd"sG Symfony/Bridge/Twig/TwigEngine.phpnu�[���PKu�Z�4˵��()V Symfony/Component/Finder/Shell/Shell.phpnu�[���PKu�Z5��K��*^ Symfony/Component/Finder/Shell/Command.phpnu�[���PKu�Z�5�9(�v Symfony/Component/Finder/SplFileInfo.phpnu�[���PKu�Z%uM�PP'X~ Symfony/Component/Finder/autoloader.phpnu�[���PKu�Z��99C� Symfony/Component/Finder/Exception/ShellCommandFailureException.phpnu�[���PKu�Z�7��9�� Symfony/Component/Finder/Exception/ExceptionInterface.phpnu�[���PKu�Z�cWޫ�<� Symfony/Component/Finder/Exception/AccessDeniedException.phpnu�[���PKu�Z>�@��>� Symfony/Component/Finder/Exception/AdapterFailureException.phpnu�[���PKu�ZP�����D	� Symfony/Component/Finder/Exception/OperationNotPermitedException.phpnu�[���PKu�Z��� ��6� Symfony/Component/Finder/Comparator/DateComparator.phpnu�[���PKu�Z|F�z

2?� Symfony/Component/Finder/Comparator/Comparator.phpnu�[���PKu�Z�P�

8�� Symfony/Component/Finder/Comparator/NumberComparator.phpnu�[���PKu�Z�g@Mbb!2� Symfony/Component/Finder/Glob.phpnu�[���PKu�Z�d�V�V#� Symfony/Component/Finder/Finder.phpnu�[���PKu�Zils_��>
!Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.phpnu�[���PKu�Z��ɔ�
�
7u!Symfony/Component/Finder/Iterator/FilePathsIterator.phpnu�[���PKu�Z�,G��4n!Symfony/Component/Finder/Iterator/FilterIterator.phpnu�[���PKu�Z�ʽ���?q#!Symfony/Component/Finder/Iterator/FilecontentFilterIterator.phpnu�[���PKu�Z�

���@~+!Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.phpnu�[���PKu�Z��z":�2!Symfony/Component/Finder/Iterator/CustomFilterIterator.phpnu�[���PKu�Z{�^ǽ�<N9!Symfony/Component/Finder/Iterator/FilenameFilterIterator.phpnu�[���PKu�Z�d����Dw@!Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.phpnu�[���PKu�Zx�P���=�F!Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.phpnu�[���PKu�Z ��U��=�L!Symfony/Component/Finder/Iterator/DateRangeFilterIterator.phpnu�[���PKu�Z�n bb<�R!Symfony/Component/Finder/Iterator/FileTypeFilterIterator.phpnu�[���PKu�Z��j��	�	6�X!Symfony/Component/Finder/Iterator/SortableIterator.phpnu�[���PKu�Z���)��8�b!Symfony/Component/Finder/Iterator/PathFilterIterator.phpnu�[���PKu�Z�6s��@�j!Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.phpnu�[���PKu�Z��&
&
2Gw!Symfony/Component/Finder/Expression/Expression.phpnu�[���PKu�Z�"HH6ρ!Symfony/Component/Finder/Expression/ValueInterface.phpnu�[���PKu�Z�E�,}�!Symfony/Component/Finder/Expression/Glob.phpnu�[���PKu�Z��(�-�!Symfony/Component/Finder/Expression/Regex.phpnu�[���PKu�Z9!�2{
{
/D�!Symfony/Component/Finder/Adapter/PhpAdapter.phpnu�[���PKu�Z����5�!Symfony/Component/Finder/Adapter/AdapterInterface.phpnu�[���PKu�Z��kA�
�
34�!Symfony/Component/Finder/Adapter/BsdFindAdapter.phpnu�[���PKu�Z�}]�
�
3��!Symfony/Component/Finder/Adapter/GnuFindAdapter.phpnu�[���PKu�ZQJ)�)8��!Symfony/Component/Finder/Adapter/AbstractFindAdapter.phpnu�[���PKu�Z�	4�"Symfony/Component/Finder/Adapter/AbstractAdapter.phpnu�[���PKu�Z����:;"Symfony/Component/Translation/Extractor/ChainExtractor.phpnu�[���PKu�ZArP�>%"Symfony/Component/Translation/Extractor/ExtractorInterface.phpnu�[���PKu�Zb*0�oo4�#"Symfony/Component/Translation/PluralizationRules.phpnu�[���PKu�Z�q��UU,<"Symfony/Component/Translation/autoloader.phpnu�[���PKu�Z�<qNN10>"Symfony/Component/Translation/MessageSelector.phpnu�[���PKu�Z�س��:�J"Symfony/Component/Translation/Catalogue/MergeOperation.phpnu�[���PKu�ZY[�>*P"Symfony/Component/Translation/Catalogue/OperationInterface.phpnu�[���PKu�Z��fb�
�
=�U"Symfony/Component/Translation/Catalogue/AbstractOperation.phpnu�[���PKu�Z��ӄ�9�c"Symfony/Component/Translation/Catalogue/DiffOperation.phpnu�[���PKu�Z�6�"��>�i"Symfony/Component/Translation/Exception/ExceptionInterface.phpnu�[���PKu�ZDŽ���D�k"Symfony/Component/Translation/Exception/InvalidResourceException.phpnu�[���PKv�Z�2B��E2n"Symfony/Component/Translation/Exception/NotFoundResourceException.phpnu�[���PKv�Z�y4��2�p"Symfony/Component/Translation/MessageCatalogue.phpnu�[���PKv�Z%�Mt8��"Symfony/Component/Translation/MetadataAwareInterface.phpnu�[���PKv�Z�d�<<4��"Symfony/Component/Translation/IdentityTranslator.phpnu�[���PKv�Z�e�G��,��"Symfony/Component/Translation/Translator.phpnu�[���PKv�Z��֛�;u�"Symfony/Component/Translation/MessageCatalogueInterface.phpnu�[���PKv�ZM�
���9{�"Symfony/Component/Translation/Dumper/IcuResFileDumper.phpnu�[���PKv�Zਪ(5u�"Symfony/Component/Translation/Dumper/PoFileDumper.phpnu�[���PKv�Z���%LL6��"Symfony/Component/Translation/Dumper/PhpFileDumper.phpnu�[���PKv�Z�<̧��8��"SymfoPK��Z�\����"data/File/design/class_diagram.pngnu�[���PK��Z6E�WWdata/Mail_mimeDecode/xmail.xslnu�[���PK��Z�
$v66data/Mail_mimeDecode/xmail.dtdnu�[���PK��Z�Z��aa.filemapnu�[���PK��Z}�g�.channels/__uri.regnu�[���PK��Z^q++.channels/pecl.php.net.regnu�[���PK��Z��0��.channels/components.ez.no.regnu�[���PK��Z�H:{��.channels/pear.syPK��Z6E�WWdata/Mail_mimeDecode/xmail.xslnu�[���PK��Z�
$v66data/Mail_mimeDecode/xmail.dtdnu�[���PK��Z�Z��aa.filemapnu�[���PK��Z}�g�.channels/__uri.regnu�[���PK��Z^q++.channels/pecl.php.net.regnu�[���PK��Z��0��.channels/components.ez.no.regnu�[���PK��Z�H:{��.channels/pear.symfony.com.regnu�[���PK��Zl�|��.channels/pear.phpunit.de.regnu�[���PK��Z�t�.channels/.alias/ezc.txtnu�[���PK��Z�o/�.channels/.alias/phpdocs.txtnu�[���PK��Z\���.channels/.alias/symfony2.txtnu�[���PK��ZT�Y.channels/.alias/phpunit.txtnu�[���PK��Z� ��.channels/.alias/pear.txtnu�[���PK��Zui<�.channels/.alias/pecl.txtnu�[���PK��ZE�Q.channels/doc.php.net.regnu�[���PK��Z|K3�((.channels/pear.php.net.regnu�[���PK��Z��0AC5C5Console/Getopt.phpnu�[���PK��ZP'hB�&�&Mail.phpnu�[���PK��Z�܄�����#.pkgxml/Symfony2_Security-2.4.3.xmlnu�[���PK��Z'J�z++.pkgxml/symfony2.xmlnu�[���PK��Z^\F[[%.pkgxml/Symfony2_Serializer-2.4.3.xmlnu�[���PK��Z�$n��7�7&.pkgxml/Symfony2_ClassLoader-2.4.3.xmlnu�[���PK��Zȗ��!.pkgxml/Pear_Net_Socket-1.2.2.xmlnu�[���PK��Z��n�++.pkgxml/Symfony2_Yaml-2.4.3.xmlnu�[���PK��Z}3YN��.pkgxml/eZc_Archive-1.4.1.xmlnu�[���PK��Z��b�8�8!.pkgxml/Symfony2_Config-2.4.3.xmlnu�[���PK��Z�$v��*.pkgxml/Symfony2_OptionsResolver-2.4.3.xmlnu�[���PK��Z�/�h����".pkgxml/Pear_Mail_Mime-1.10.11.xmlnu�[���PK��ZtWY�n�n%.pkgxml/Symfony2_HttpKernel-2.4.3.xmlnu�[���PK��ZPK��Z�
$v66data/Mail_mimeDecode/xmail.dtdnu�[���PK��Z�Z��aa.filemapnu�[���PK��Z}�g�.channels/__uri.regnu�[���PK��Z^q++.channels/pecl.php.net.regnu�[���PK��Z��0��.channels/components.ez.no.regnu�[���PK��Z�H:{��.channels/pear.symfony.com.regnu�[���PK��Zl�|��.channels/pear.phpunit.de.regnu�[���PK��Z�t�.channels/.alias/ezc.txtnu�[���PK��Z�o/�.channels/.alias/phpdocs.txtnu�[PK��Z�Z��aa.filemapnu�[���PK��Z}�g�.channels/__uri.regnu�[���PK��Z^q++.channels/pecl.php.net.regnu�[���PK��Z��0��.channels/components.ez.no.regnu�[���PK��Z�H:{��.channels/pear.symfony.com.regnu�[���PK��Zl�|��.channels/pear.phpunit.de.regnu�[���PK��Z�t�.channels/.alias/ezc.txtnu�[���PK��Z�o/�.channels/.alias/phpdocs.txtnu�[���PK��Z\���.channels/.alias/symfony2.txtnu�[���PK��ZT�Y.channels/.alias/phpunit.txtnu�[���PK��Z� ��.channels/.alias/pear.txtnu�[���PK��Zui<�.channels/.alias/pecl.txtnu�[���PK��ZE�Q.channels/doc.php.net.regnu�[���PK��Z|K3�((.channels/pear.php.net.regnu�[���PK��Z��0AC5C5Console/Getopt.phpnu�[���PK��ZP'hB�&�&Mail.phpnu�[���PK��Z�܄�����#.pkgxml/Symfony2_Security-2.4.3.xmlnu�[���PK��Z'J�z++.pkgxml/symfony2.xmlnu�[���PK��Z^\F[[%.pkgxml/Symfony2_Serializer-2.4.3.xmlnu�[���PK��Z�$n��7�7&.pkgxml/Symfony2_ClassLoader-2.4.3.xmlnu�[���PK��Zȗ��!.pkgxml/Pear_Net_Socket-1.2.2.xmlnu�[���PK��Z��n�++.pkgxml/Symfony2_Yaml-2.4.3.xmlnu�[���PK��Z}3YN��.pkgxml/eZc_Archive-1.4.1.xmlnu�[���PK��Z��b�8�8!.pkgxml/Symfony2_Config-2.4.3.xmlnu�[���PK��Z�$v��*.pkgxml/Symfony2_OptionsResolver-2.4.3.xmlnu�[���PK��Z�/�h����".pkgxml/Pear_Mail_Mime-1.10.11.xmlnu�[���PK��ZtWY�n�n%.pkgxml/Symfony2_HttpKernel-2.4.3.xmlnu�[���PK��Z�1��ss..pkgxml/Symfony2_DependencyInjection-2.4.3.xmlnu�[���PK��Z=��4��(.pkgxml/Symfony2_MonologBridge-2.4.3.xmlnu�[���PK��Z�7�p�K�K.pkgxml/XML_Util.xmlnu�[���PK��Z��-=-=".pkgxml/Symfony2_Routing-2.4.3.xmlnu�[���PK��Z�|g��$.pkgxml/Symfony2_Validator-2.4.3.xmlnu�[���PK��Z�d+)SS!.pkgxml/Symfony2_Locale-2.4.3.xmlnu�[���PK��Z%ONO��&.pkgxml/Pear_Mail_mimeDecode-1.5.6.xmlnu�[���PK��Z�*�OO.pkgxml/ezc.xmlnu�[���PK��Z#�r�

 .pkgxml/Pear_Net_SMTP-1.10.0.xmlnu�[���PK��Za������.pkgxml/Symfony2_Form-2.4.3.xmlnu�[���PK��Z�Q���?�? .pkgxml/Pear_Net_Sieve-1.4.5.xmlnu�[���PK��Z��F��%.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu�[���PK��Z?�4��
�
%.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu�[���PK��Z��t8��%.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.PK��Z}�g�.channels/__uri.regnu�[���PK��Z^q++.channels/pecl.php.net.regnu�[���PK��Z��0��.channels/components.ez.no.regnu�[���PK��Z�H:{��.channels/pear.symfony.com.regnu�[���PK��Zl�|��.channePK��Z^q++.channels/pecl.php.net.regnu�[���PK��Z��0��.channels/components.ez.no.regnu�[���PK��Z�H:{��.channels/pear.symfony.com.regnu�[���PK��Zl�|��.channels/pear.phpunit.de.regnu�[���PK��Z�t�.channels/.alias/ezc.txtnu�[���PK��Z�o/�.channels/.alias/phpdocs.txtnu�[���PK��Z\���.channels/.alias/symfony2.txtnu�[���PK��ZT�Y.channels/.alias/phpunit.txtnu�[���PK��Z� ��PK��Z��0��.channels/components.ez.no.regnu�[���PK��Z�H:{��.channels/pear.symfony.com.regnu�[���PK��Zl�|��.channels/pear.phpunit.de.regnu�[���PK��Z�t�.channels/.alias/ezc.txtnu�[���PK��Z�o/�.channels/.alias/phpdocs.txtnu�[���PK��Z\���.channels/.alias/symfony2.txtnu�[���PK��ZT�Y.channels/.alias/phpunit.txtnu�[���PK��Z� ��.channels/.alias/pear.txtnu�[���PK��Zui<�.channels/.alias/pecl.txtnu�[���PK��ZE�Q.channels/doc.php.net.regnu�[���PK��Z|K3�((.PK��Z�H:{��.channels/pear.symfony.com.regnu�[���PK��Zl�|��.channels/pear.phpunit.de.regnu�[���PK��Z�t�.channels/.alias/ezc.txtnu�[���PK��Z�o/�.channels/.alias/phpdocs.txtnu�[���PK��Z\���.channels/.alias/symfony2.txtnu�[���PK��ZT�Y.channels/.alias/phpunit.txtnu�[���PK��Z� ��.channels/.alias/pear.txtnu�[���PK��Zui<�.channels/.alias/pecl.txtnu�[���PK��ZE�Q.channels/doc.php.net.regnu�[���PK��Z|K3�((.channels/pear.php.net.regnu�[���PK��Z��0AC5C5Console/Getopt.phpnu�[���PK��ZP'hB�&�&Mail.phpnu�[���PK��Z�܄�����#.pkgxml/Symfony2_Security-2.4.3.xmlnu�[���PK��Z'J�z++.pkgxml/symfony2.xmPK��Zl�|��.channels/pear.phpunit.de.regnu�[���PK��Z�t�.channels/.alias/ezc.txtnu�[���PK��Z�o/�.channels/.alias/phpdocs.txtnu�[���PK��Z\���.channels/.alias/symfony2.txtnu�[���PK��ZT�Y.channels/.alias/phpunit.txtnu�[���PK��Z� ��.channels/.alias/pear.txtnu�[���PK��Zui<�.channels/.alias/pecl.txtnu�[���PK��ZE�Q.channels/doc.php.net.regnu�[���PK��Z|K3�((.channels/pear.php.net.regnu�[���PK��Z��0AC5C5Console/Getopt.phpnu�[���PK��ZP'hB�&�&Mail.phpnu�[���PK��Z�܄�����#.pkgxml/Symfony2_Security-2.4.3.xmlnu�[���PK��Z'J�z++.pkgxml/symfony2.xmlnu�[���PK��Z^\F[[%.pkgxml/Symfony2_SeriPK��Z�t�.channels/.alias/ezc.txtnu�[���PK��Z�oPK��Z�o/�.channels/.alias/phpdocs.txtnu�[���PK�PK��Z\���.channels/.alias/symfony2.txtnu�[���PK��ZTPK��ZT�Y.channels/.alias/phpunit.txtnu�[���PK��Z�PK��Z� ��.channels/.alias/pear.txtnu�[���PK�PK��Zui<�.channels/.alias/pecl.txtnu�[���PK�PK��ZE�Q.channels/doc.php.net.regnu�[���PK��Z|K3�((.channels/pear.php.net.regnu�[���PK��Z��0AC5C5Console/Getopt.phpnu�[���PK��ZP'hB�&�&Mail.phpnu�[���PK��Z�܄�����#.pkgxml/Symfony2_Security-2.4.3.xmlnu�[���PK��Z'J�z++.pkgxml/symfony2.xmlnu�[���PK��Z^\F[[%.pkgxml/Symfony2_Serializer-2.4.3.xmlnu�[���PK��Z�$n��7�7&.pkgxml/Symfony2_ClassLoader-2.4.3.xmlnu�[���PK��Z�PK��Z|K3�((.channels/pear.php.net.regnu�[���PK��Z��0AC5C5Console/Getopt.phpnu�[���PK��ZP'hB�&�&Mail.phpnu�[���PK��Z�܄�����#.pkgxml/Symfony2_Security-2.4.3.xmlnu�[���PK��Z'J�z++.pkgxml/symfony2.xmlnu�[���PK��Z^\F[[%.pkgxml/Symfony2_Serializer-2.4.3.xmlnu�[���PK��Z�$n��7�7&.pkgxml/Symfony2_ClassLoader-2.4.3.xmlnu�[���PK��Zȗ��!.pkgxml/Pear_Net_Socket-1.2.2.xmlnu�[���PK��Z��n�++PK��Z��0AC5C5Console/Getopt.phpnu�[���PK��ZP'hB�&�&Mail.phpnu�[���PK��Z�܄�����#.pkgxml/Symfony2_Security-2.4.3.xmlnu�[���PK��Z'J�z++.pkgxml/symfony2.xmlnu�[���PK��Z^\F[[%.pkgxml/Symfony2_Serializer-2.4.3.xmlnu�[���PK��Z�$n��7�7&.pkgxml/Symfony2_ClassLoader-2.4.3.xmlnu�[���PK��Zȗ��!.pkgxml/Pear_Net_Socket-1.2.2.xmlnu�[���PK��Z��n�++.pkgxml/Symfony2_Yaml-2.4.3.xmlnu�[���PK��Z}3YN��.pkgxml/eZc_Archive-1.4.1.xmlnu�[���PK��Z��b�8�8!.pkgxml/Symfony2_Config-2.4.3.xmlnu�[���PK��Z�$v��*.pkgxml/Symfony2_OptionsResolver-2.4.3.xmlnu�[���PK��Z�/�h����".pkgxml/Pear_Mail_Mime-1.10.11.xmlnu�[���PK��ZtWY�n�n%.pkgxml/Symfony2_HttpKernel-2.4.3.xmlnu�[���PK��Z�1��ss..pkgxml/Symfony2_DependencyInjection-2.4.3.xmlnu�[���PK��Z=��4��(.pkgxml/Symfony2_MonologBridge-2.4.3.xmlnu�[���PK��Z�7�p�K�K.pkgxml/XML_Util.xmlnu�[���PK��Z��-=-=".pkgxml/Symfony2_Routing-2.4.3.xmlnu�[���PK��Z�|g��$.pkgxml/Symfony2_Validator-2.4.3.xmlnu�[���PK��Z�d+)SS!.pkgxml/Symfony2_Locale-2.4.3.xmlnu�[���PK��Z%ONO��&.pkgxml/Pear_Mail_mimeDecode-1.5.6.xmlnu�[���PK��Z�*�OO.pkgxml/ezc.xmlnu�[���PK��Z#�r�

 .pkgxml/Pear_Net_SMTP-1.10.0.xmlnu�[���PK��Za������.pkgxml/Symfony2_Form-2.4.3.xmlnu�[���PK��Z�Q���?�? .pkgxml/Pear_Net_Sieve-1.4.5.xmlnu�[���PK��Z��F��%.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu�[���PK��Z?�4��
�
%.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu�[���PK��Z��t8��%.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&' PK��ZP'hB�&�&Mail.phpnu�[���PK��Z�܄�����#.pkgxml/Symfony2_Security-2.4.3.xmlnu�[���PK��Z'J�z++.pkgxml/symfony2.xmlnu�[���PK��Z^\F[[%.pkgxml/Symfony2_Serializer-2.4.3.xmlnu�[���PK��Z�$n��7�7&.pkgxml/Symfony2_ClassLoader-2.4.3.xmlnu�[���PK��Zȗ��!.pkgxml/Pear_Net_Socket-1.2.2.xmlnu�[���PK��Z��n�++.pkgxml/Symfony2_Yaml-2.4.3.xmlnu�[���PK��Z}3YN��.pkgxml/eZc_Archive-1.4.1.xmlnu�[���PK��Z��b�8�8!.pkgxml/Symfony2_Config-2.4.3.xmlnu�[���PK��Z�$v��*.pkgxml/Symfony2_OptionsResolver-2.4.3.xmlnu�[���PK��Z�/�h����".pkgxml/Pear_Mail_Mime-1.10.11.xmlnu�[���PK��ZtWY�n�n%.pkgxml/Symfony2_HttpKernel-2.4.3.xmlnu�[���PK��Z�1��ss..pkgxml/Symfony2_DependencyInjection-2.4.3.xmlnu�[���PK��Z=��4��(.pkgxml/Symfony2_MonologBridge-2.4.3.xmlnu�[���PK��Z�7�p�K�K.pkgxml/XML_Util.xmlnu�[���PK��Z��-=-=".pkgxml/Symfony2_Routing-2.4.3.xmlnu�[���PK��Z�|g��$.pkgxml/Symfony2_Validator-2.4.3.xmlnu�[���PK��Z�d+)SS!.pkgxml/Symfony2_Locale-2.4.3.xmlnu�[���PK��Z%ONO��&.pkgxml/Pear_Mail_mimeDecode-1.5.6.xmlnu�[���PK��Z�*�OO.pkgxml/ezc.xmlnu�[���PK��Z#�r�

 .pkgxml/Pear_Net_SMTP-1.10.0.xmlnu�[���PK��Za������.pkgxml/Symfony2_Form-2.4.3.xmlnu�[���PK��Z�Q���?�? .pkgxml/Pear_Net_Sieve-1.4.5.xmlnu�[���PK��Z��F��%.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu�[���PK��Z?�4��
�
%.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu�[���PK��Z��t8��%.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-PK��Z�܄�����#.pkgxml/Symfony2_Security-2.4.3.xmlnu�[���PK��Z'J�z++.pkgxml/symfony2.xmlnu�[���PK��Z^\F[[%.pkgxml/Symfony2_Serializer-2.4.3.xmlnu�[���PK��Z�$n��7�7&.pkgxml/Symfony2_ClassLoader-2.4.3.xmlnu�[���PK��Zȗ��!.pkgxml/Pear_Net_Socket-1.2.2.xmlnu�[���PK��Z��n�++.pkgxml/Symfony2_Yaml-2.4.3.xmlnu�[���PK��Z}3YN��.pkgxml/eZc_Archive-1.4.1.xmlnu�[���PK��Z��b�8�8!.pkgxml/Symfony2_Config-2.4.3.xmlnu�[���PK��Z�$v��*.pkgxml/Symfony2_OptionsResolver-2.4.3.xmlnu�[���PK��Z�/�h����".pkgxml/Pear_Mail_Mime-1.10.11.xmlnu�[���PK��ZtWY�n�n%.pkgxml/Symfony2_HttpKernel-2.4.3.xmlnu�[���PK��Z�1��ss..pkgxml/Symfony2_DependencyInjection-2.4.3.xmlnu�[���PK��Z=��4��(.pkgxml/Symfony2_MonologBridge-2.4.3.xmlnu�[���PK��Z�7�p�K�K.pkgxml/XML_Util.xmlnu�[���PK��Z��-=-=".pkgxml/Symfony2_Routing-2.4.3.xmlnu�[���PK��Z�|g��$.pkgxml/Symfony2_Validator-2.4.3.xmlnu�[���PK��Z�d+)SS!.pkgxml/Symfony2_Locale-2.4.3.xmlnu�[���PK��Z%ONO��&.pkgxml/Pear_Mail_mimeDecode-1.5.6.xmlnu�[���PK��Z�*�OO.pkgxml/ezc.xmlnu�[���PK��Z#�r�

 .pkgxml/Pear_Net_SMTP-1.10.0.xmlnu�[���PK��Za������.pkgxml/Symfony2_Form-2.4.3.xmlnu�[���PK��Z�Q���?�? .pkgxml/Pear_Net_Sieve-1.4.5.xmlnu�[���PK��Z��F��%.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu�[���PK��Z?�4��
�
%.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu�[���PK��Z��t8��%.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUri   URI of the namespace
     * @param bool   $multiline      whether to create a multiline tag where each
     *                               attribute gets written to a single line
     * @param string $indent         string used to indent attributes (_auto indents
     *                               attributes so they start at the same column)
     * @param string $linebreak      string used for linebreaks
     * @param bool   $sortAttributes Whether to sort the attributes or not
     *
     * @return string XML start element
     * @see    createEndElement(), createTag()
     */
    public static function createStartElement(
        $qname, $attributes = array(), $namespaceUri = null,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true
    ) {
        // if no attributes hav been set, use empty attributes
        if (!isset($attributes) || !is_array($attributes)) {
            $attributes = array();
        }

        if ($namespaceUri != null) {
            $parts = XML_Util::splitQualifiedName($qname);
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($qname)+2));
            }
        }

        if ($namespaceUri != null) {
            // is a namespace given
            if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
            } else {
                // define this Uri as the default namespace
                $attributes['xmlns'] = $namespaceUri;
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $attributes, $sortAttributes,
            $multiline, $indent, $linebreak
        );
        $element = sprintf('<%s%s>', $qname, $attList);
        return  $element;
    }

    /**
     * Create an end element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createEndElement('myNs:myTag');
     * </code>
     *
     * @param string $qname qualified tagname (including namespace)
     *
     * @return string XML end element
     * @see    createStartElement(), createTag()
     */
    public static function createEndElement($qname)
    {
        $element = sprintf('</%s>', $qname);
        return $element;
    }

    /**
     * Create an XML comment
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createComment('I am a comment');
     * </code>
     *
     * @param string $content content of the comment
     *
     * @return string XML comment
     */
    public static function createComment($content)
    {
        $comment = sprintf('<!-- %s -->', $content);
        return $comment;
    }

    /**
     * Create a CData section
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create a CData section
     * $tag = XML_Util::createCDataSection('I am content.');
     * </code>
     *
     * @param string $data data of the CData section
     *
     * @return string CData section with content
     */
    public static function createCDataSection($data)
    {
        return sprintf(
            '<![CDATA[%s]]>',
            preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data))
        );
    }

    /**
     * Split qualified name and return namespace and local part
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // split qualified tag
     * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
     * </code>
     * the returned array will contain two elements:
     * <pre>
     * array(
     *     'namespace' => 'xslt',
     *     'localPart' => 'stylesheet'
     * );
     * </pre>
     *
     * @param string $qname     qualified tag name
     * @param string $defaultNs default namespace (optional)
     *
     * @return array array containing namespace and local part
     */
    public static function splitQualifiedName($qname, $defaultNs = null)
    {
        if (strstr($qname, ':')) {
            $tmp = explode(':', $qname);
            return array(
                'namespace' => $tmp[0],
                'localPart' => $tmp[1]
            );
        }
        return array(
            'namespace' => $defaultNs,
            'localPart' => $qname
        );
    }

    /**
     * Check, whether string is valid XML name
     *
     * <p>XML names are used for tagname, attribute names and various
     * other, lesser known entities.</p>
     * <p>An XML name may only consist of alphanumeric characters,
     * dashes, undescores and periods, and has to start with a letter
     * or an underscore.</p>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // verify tag name
     * $result = XML_Util::isValidName('invalidTag?');
     * if (is_a($result, 'PEAR_Error')) {
     *    print 'Invalid XML name: ' . $result->getMessage();
     * }
     * </code>
     *
     * @param string $string string that should be checked
     *
     * @return mixed true, if string is a valid XML name, PEAR error otherwise
     *
     * @todo support for other charsets
     * @todo PEAR CS - unable to avoid 85-char limit on second preg_match
     */
    public static function isValidName($string)
    {
        // check for invalid chars
        if (!is_string($string) || !strlen($string) || !preg_match('/^[[:alpha:]_]\\z/', $string[0])) {
            return XML_Util::raiseError(
                'XML names may only start with letter or underscore',
                XML_UTIL_ERROR_INVALID_START
            );
        }

        // check for invalid chars
        $match = preg_match(
            '/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?'
            . '[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/',
            $string
        );
        if (!$match) {
            return XML_Util::raiseError(
                'XML names may only contain alphanumeric '
                . 'chars, period, hyphen, colon and underscores',
                XML_UTIL_ERROR_INVALID_CHARS
            );
        }
        // XML name is valid
        return true;
    }

    /**
     * Replacement for XML_Util::raiseError
     *
     * Avoids the necessity to always require
     * PEAR.php
     *
     * @param string $msg  error message
     * @param int    $code error code
     *
     * @return PEAR_Error
     * @todo   PEAR CS - should this use include_once instead?
     */
    public static function raiseError($msg, $code)
    {
        include_once 'PEAR.php';
        return PEAR::raiseError($msg, $code);
    }
}
?>
PK��Z#F��:�:pearcmd.phpnu�[���<?php
/**
 * PEAR, the PHP Extension and Application Repository
 *
 * Command line interface
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Stig Bakken <ssb@php.net>
 * @author    Tomas V.V.Cox <cox@idecnet.com>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 */

@ob_end_clean();
if (!defined('PEAR_RUNTYPE')) {
    // this is defined in peclcmd.php as 'pecl'
    define('PEAR_RUNTYPE', 'pear');
}
define('PEAR_IGNORE_BACKTRACE', 1);
/**
 * @nodep Gtk
 */
//the space is needed for windows include paths with trailing backslash
// http://pear.php.net/bugs/bug.php?id=19482
if ('/opt/alt/php74/usr/share/pear ' != '@'.'include_path'.'@ ') {
    ini_set('include_path', trim('/opt/alt/php74/usr/share/pear '). PATH_SEPARATOR .  get_include_path());
    $raw = false;
} else {
    // this is a raw, uninstalled pear, either a cvs checkout, or php distro
    ini_set('include_path', dirname(__DIR__) . PATH_SEPARATOR . get_include_path());
    $raw = true;
}
@ini_set('allow_url_fopen', true);
@set_time_limit(0);
ob_implicit_flush(true);
@ini_set('track_errors', true);
@ini_set('html_errors', false);
$_PEAR_PHPDIR = '#$%^&*';
set_error_handler('error_handler');

$pear_package_version = "1.10.16";

require_once 'PEAR.php';
require_once 'PEAR/Frontend.php';
require_once 'PEAR/Config.php';
require_once 'PEAR/Command.php';
require_once 'Console/Getopt.php';


PEAR_Command::setFrontendType('CLI');
$all_commands = PEAR_Command::getCommands();

$argv = Console_Getopt::readPHPArgv();
// fix CGI sapi oddity - the -- in pear.bat/pear is not removed
if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
    unset($argv[1]);
    $argv = array_values($argv);
}
$progname = PEAR_RUNTYPE;
array_shift($argv);
$options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV");
if (PEAR::isError($options)) {
    usage($options);
}

$opts = $options[0];

$fetype = 'CLI';
if ($progname == 'gpear' || $progname == 'pear-gtk') {
    $fetype = 'Gtk2';
} else {
    foreach ($opts as $opt) {
        if ($opt[0] == 'G') {
            $fetype = 'Gtk2';
        }
    }
}

$pear_user_config = '';
$pear_system_config = '';
$store_user_config = false;
$store_system_config = false;
$verbose = 1;

foreach ($opts as $opt) {
    switch ($opt[0]) {
    case 'c':
        $pear_user_config = $opt[1];
        break;
    case 'C':
        $pear_system_config = $opt[1];
        break;
    }
}

PEAR_Command::setFrontendType($fetype);
$ui = &PEAR_Command::getFrontendObject();
$config = &PEAR_Config::singleton($pear_user_config, $pear_system_config);

if (PEAR::isError($config)) {
    $_file = '';
    if ($pear_user_config !== false) {
        $_file .= $pear_user_config;
    }
    if ($pear_system_config !== false) {
        $_file .= '/' . $pear_system_config;
    }
    if ($_file == '/') {
        $_file = 'The default config file';
    }
    $config->getMessage();
    $ui->outputData("ERROR: $_file is not a valid config file or is corrupted.");
    // We stop, we have no idea where we are :)
    exit(1);
}

// this is used in the error handler to retrieve a relative path
$_PEAR_PHPDIR = $config->get('php_dir');
$ui->setConfig($config);
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError"));

$verbose = $config->get("verbose");
$cmdopts = array();

if ($raw) {
    if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) {
        $found = false;
        foreach ($opts as $opt) {
            if ($opt[0] == 'd' || $opt[0] == 'D') {
                // the user knows what they are doing, and are setting config values
                $found = true;
            }
        }
        if (!$found) {
            // no prior runs, try to install PEAR
            $parent = dirname(__FILE__);
            if (strpos($parent, 'scripts')) {
                $grandparent = dirname($parent);
                $packagexml = $grandparent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $grandparent;
            } else {
                $packagexml = $parent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $parent;
            }
            if (file_exists($packagexml)) {
                $options[1] = array(
                    'install',
                    $packagexml
                );
                $config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php');
                $config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data');
                $config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs');
                $config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests');
                $config->set(
                    'ext_dir',
                    $pearbase . DIRECTORY_SEPARATOR . 'extensions'
                );
                $config->set('bin_dir', $pearbase);
                $config->mergeConfigFile($pearbase . 'pear.ini', false);
                $config->store();
                $config->set('auto_discover', 1);
            }
        }
    }
}
foreach ($opts as $opt) {
    $param = !empty($opt[1]) ? $opt[1] : true;
    switch ($opt[0]) {
    case 'd':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected -d config_value=value, ' .
                'received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'user');
        break;
    case 'D':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'system');
        break;
    case 's':
        $store_user_config = true;
        break;
    case 'S':
        $store_system_config = true;
        break;
    case 'u':
        $config->remove($param, 'user');
        break;
    case 'v':
        $config->set('verbose', $config->get('verbose') + 1);
        break;
    case 'q':
        $config->set('verbose', $config->get('verbose') - 1);
        break;
    case 'V':
        usage(null, 'version');
    case 'c':
    case 'C':
        break;
    default:
        // all non pear params goes to the command
        $cmdopts[$opt[0]] = $param;
        break;
    }
}

if ($store_system_config) {
    $config->store('system');
}

if ($store_user_config) {
    $config->store('user');
}

$command = (isset($options[1][0])) ? $options[1][0] : null;
if (empty($command) && ($store_user_config || $store_system_config)) {
    exit;
}

if ($fetype == 'Gtk2') {
    if (!$config->validConfiguration()) {
        PEAR::raiseError(
            "CRITICAL ERROR: no existing valid configuration files found in " .
            "files '$pear_user_config' or '$pear_system_config', " .
            "please copy an existing configuration file to one of these " .
            "locations, or use the -c and -s options to create one"
        );
    }
    Gtk::main();
} else {
    do {
        if ($command == 'help') {
            usage(null, isset($options[1][1]) ? $options[1][1] : null);
        }

        if (!$config->validConfiguration()) {
            PEAR::raiseError(
                "CRITICAL ERROR: no existing valid configuration files found " .
                "in files '$pear_user_config' or '$pear_system_config', " .
                "please copy an existing configuration file to one of " .
                "these locations, or use the -c and -s options to create one"
            );
        }

        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        $cmd = PEAR_Command::factory($command, $config);
        PEAR::popErrorHandling();
        if (PEAR::isError($cmd)) {
            usage(null, isset($options[1][0]) ? $options[1][0] : null);
        }

        $short_args = $long_args = null;
        PEAR_Command::getGetoptArgs($command, $short_args, $long_args);
        array_shift($options[1]);
        $tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args);

        if (PEAR::isError($tmp)) {
            break;
        }

        list($tmpopt, $params) = $tmp;
        $opts = array();
        foreach ($tmpopt as $foo => $tmp2) {
            list($opt, $value) = $tmp2;
            if ($value === null) {
                $value = true; // options without args
            }

            if (strlen($opt) == 1) {
                $cmdoptions = $cmd->getOptions($command);
                foreach ($cmdoptions as $o => $d) {
                    if (isset($d['shortopt']) && $d['shortopt'] == $opt) {
                        $opts[$o] = $value;
                    }
                }
            } else {
                if (substr($opt, 0, 2) == '--') {
                    $opts[substr($opt, 2)] = $value;
                }
            }
        }

        $ok = $cmd->run($command, $opts, $params);
        if ($ok === false) {
            PEAR::raiseError("unknown command `$command'");
        }

        if (PEAR::isError($ok)) {
            PEAR::setErrorHandling(
                PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")
            );
            PEAR::raiseError($ok);
        }
    } while (false);
}

// {{{ usage()

/**
 * Display usage information
 *
 * @param mixed $error       Optional error message
 * @param mixed $helpsubject Optional subject/command to display help for
 *
 * @return void
 */
function usage($error = null, $helpsubject = null)
{
    global $progname, $all_commands;
    $stdout = fopen('php://stdout', 'w');
    if (PEAR::isError($error)) {
        fputs($stdout, $error->getMessage() . "\n");
    } elseif ($error !== null) {
        fputs($stdout, "$error\n");
    }

    if ($helpsubject != null) {
        $put = cmdHelp($helpsubject);
    } else {
        $put = "Commands:\n";
        $maxlen = max(array_map("strlen", $all_commands));
        $formatstr = "%-{$maxlen}s  %s\n";
        ksort($all_commands);
        foreach ($all_commands as $cmd => $class) {
            $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd));
        }
        $put .=
            "Usage: $progname [options] command [command-options] <parameters>\n".
            "Type \"$progname help options\" to list all options.\n".
            "Type \"$progname help shortcuts\" to list all command shortcuts.\n".
            "Type \"$progname help version\" or ".
            "\"$progname version\" to list version information.\n".
            "Type \"$progname help <command>\" to get the help ".
            "for the specified command.";
    }
    fputs($stdout, "$put\n");
    fclose($stdout);

    if ($error === null) {
        exit(0);
    }
    exit(1);
}

/**
 * Return help string for specified command
 *
 * @param string $command Command to return help for
 *
 * @return void
 */
function cmdHelp($command)
{
    global $progname, $all_commands, $config;
    if ($command == "options") {
        return
        "Options:\n".
        "     -v         increase verbosity level (default 1)\n".
        "     -q         be quiet, decrease verbosity level\n".
        "     -c file    find user configuration in `file'\n".
        "     -C file    find system configuration in `file'\n".
        "     -d foo=bar set user config variable `foo' to `bar'\n".
        "     -D foo=bar set system config variable `foo' to `bar'\n".
        "     -G         start in graphical (Gtk) mode\n".
        "     -s         store user configuration\n".
        "     -S         store system configuration\n".
        "     -u foo     unset `foo' in the user configuration\n".
        "     -h, -?     display help/usage (this message)\n".
        "     -V         version information\n";
    } elseif ($command == "shortcuts") {
        $sc = PEAR_Command::getShortcuts();
        $ret = "Shortcuts:\n";
        foreach ($sc as $s => $c) {
            $ret .= sprintf("     %-8s %s\n", $s, $c);
        }
        return $ret;

    } elseif ($command == "version") {
        return "PEAR Version: ".$GLOBALS['pear_package_version'].
               "\nPHP Version: ".phpversion().
               "\nZend Engine Version: ".zend_version().
               "\nRunning on: ".php_uname();

    } elseif ($help = PEAR_Command::getHelp($command)) {
        if (is_string($help)) {
            return "$progname $command [options] $help\n";
        }

        if ($help[1] === null) {
            return "$progname $command $help[0]";
        }

        return "$progname $command [options] $help[0]\n$help[1]";
    }

    return "Command '$command' is not valid, try '$progname help'";
}

// }}}

/**
 * error_handler
 *
 * @param mixed $errno  Error number
 * @param mixed $errmsg Message
 * @param mixed $file   Filename
 * @param mixed $line   Line number
 *
 * @access public
 * @return boolean
 */
function error_handler($errno, $errmsg, $file, $line)
{
    if ((!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) && ($errno & E_STRICT)) {
        return; // E_STRICT
    }
    if ($errno & E_DEPRECATED) {
        return; // E_DEPRECATED
    }
    if (!(error_reporting() & $errno) &&
        isset($GLOBALS['config']) &&
        $GLOBALS['config']->get('verbose') < 4
    ) {
        return false; // @silenced error, show all if debug is high enough
    }
    $errortype = array (
        E_DEPRECATED  => 'Deprecated Warning',
        E_ERROR   =>  "Error",
        E_WARNING   =>  "Warning",
        E_PARSE   =>  "Parsing Error",
        E_NOTICE   =>  "Notice",
PK��Z'J�z++.pkgxml/symfony2.xmlnu�[���PK��Z^\F[[%.pkgxml/Symfony2_Serializer-2.4.3.xmlnu�[���PK��Z�$n��7�7&.pkgxml/Symfony2_ClassLoader-2.4.3.xmlnu�[���PK��Zȗ��!.pkgxml/Pear_Net_Socket-1.2.2.xmlnu�[���PK��Z��n�++.pkgxml/Symfony2_Yaml-2.4.3.xmlnu�[���PK��Z}3YN��.pkgxml/eZc_Archive-1.4.1.xmlnu�[���PK��Z��b�8�8!.pkgxml/Symfony2_Config-2.4.3.xmlnu�[���PK��Z�$v��*.pkgxml/Symfony2_OptionsResolver-2.4.3.xmlnu�[���PK��Z�/�h����".pkgxml/Pear_Mail_Mime-1.10.11.xmlnu�[���PK��ZtWY�n�n%.pkgxml/Symfony2_HttpKernel-2.4.3.xmlnu�[���PK��Z�1��ss..pkgxml/Symfony2_DependencyInjectioPK��Z^\F[[%.pkgxml/Symfony2_Serializer-2.4.3.xmlnu�[���PK��Z�$n��7�7&.pkgxml/Symfony2_ClassLoader-2.4.3.xmlnu�[���PK��Zȗ��!.pkgxml/Pear_Net_Socket-1.2.2.xmlnu�[���PK��Z��n�++.pkgxml/Symfony2_Yaml-2.4.3.xmlnu�[���PK��Z}3YN��.pkgxml/eZc_Archive-1.4.1.xmlnu�[���PK��Z��b�8�8!.pkgxml/Symfony2_Config-2.4.3.xmlnu�[���PK��Z�$v��*.pkgxml/Symfony2_OptionsResolver-2.4.3.xmlnu�[���PK��Z�/�h����".pkgxml/Pear_Mail_Mime-1.10.11.xmlnu�[���PK��ZtWY�n�n%.pkgxml/Symfony2_HttpKernel-2.4.3.xmlnu�[���PK��Z�1��ss..pkgxml/Symfony2_DependencyInjection-2.4.3.xmlnu�[���PK��Z=��4��(.pkgxml/Symfony2_MonologBridge-2.4.3.xmlnu�[���PK��Z�7�p�K�K.pkgxml/XML_Util.xmlnu�[���PK��Z��-=-=".pkgxml/Symfony2_Routing-2.4.3.xmlnu�[���PK��Z�|g��$.pkgxml/Symfony2_Validator-2.4.3.xmlnu�[���PK��Z�d+)SS!.pkgxml/Symfony2_Locale-2.4.3.xmlnu�[���PK��Z%ONO��&.pkgxml/Pear_Mail_mimeDecode-1.5.6.xmlnu�[���PK��Z�*�OO.pkgxml/ezc.xmlnu�[���PK��Z#�r�

 .pkgxml/Pear_Net_SMTP-1.10.0.xmlnu�[���PK��Za������.pkgxml/Symfony2_Form-2.4.3.xmlnu�[���PK��Z�Q���?�? .pkgxml/Pear_Net_Sieve-1.4.5.xmlnu�[���PK��Z��F��%.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu�[���PK��Z?�4��
�
%.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu�[���PK��Z��t8��%.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registryPK��Z�$n��7�7&.pkgxml/Symfony2_ClassLoader-2.4.3.xmlnu�[���PK��Zȗ��!.pkgxml/Pear_Net_Socket-1.2.2.xmlnu�[���PK��Z��n�++.pkgxml/Symfony2_Yaml-2.4.3.xmlnu�[���PK��Z}3YN��.pkgxml/eZc_Archive-1.4.1.xmlnu�[���PK��Z��b�8�8!.pkgxml/Symfony2_Config-2.4.3.xmlnu�[���PK��Z�$v��*.pkgxml/Symfony2_OptionsResolver-2.4.3.xmlnu�[���PK��Z�/�h����".pkgxml/Pear_Mail_Mime-1.10.11.xmlnu�[���PK��ZtWY�n�n%.pkgxml/Symfony2_HttpKernel-2.4.3.xmlnu�[���PK��Z�1��ss..pkgxml/Symfony2_DependencyInjection-2.4.3.xmlnu�[���PK��Z=��4��(.pkgxml/Symfony2_MonologBridge-2.4.3.xmlnu�[���PK��Z�7�p�K�K.pkgxml/XML_Util.xmlnu�[���PK��Z��-=-=".pkgxml/Symfony2_Routing-2.4.3.xmlnu�[���PK��Z�|g��$.pkgxml/Symfony2_Validator-2.4.3.xmlnu�[���PK��Z�d+)SS!.pkgxml/Symfony2_Locale-2.4.3.xmlnu�[���PK��Z%ONO��&.pkgxml/Pear_Mail_mimeDecode-1.5.6.xmlnu�[���PK��Z�*�OO.pkgxml/ezc.xmlnu�[���PK��Z#�r�

 .pkgxml/Pear_Net_SMTP-1.10.0.xmlnu�[���PK��Za������.pkgxml/Symfony2_Form-2.4.3.xmlnu�[���PK��Z�Q���?�? .pkgxml/Pear_Net_Sieve-1.4.5.xmlnu�[���PK��Z��F��%.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu�[���PK��Z?�4��
�
%.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu�[���PK��Z��t8��%.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *PK��Zȗ��!.pkgxml/Pear_Net_Socket-1.2.2.xmlnu�[���PK��Z��n�++.pkgxml/Symfony2_Yaml-2.4.3.xmlnu�[���PK��Z}3YN��.pkgxml/eZc_Archive-1.4.1.xmlnu�[���PK��Z��b�8�8!.pkgxml/Symfony2_Config-2.4.3.xmlnu�[���PK��Z�$v��*.pkgxml/Symfony2_OptionsResolver-2.4.3.xmlnu�[���PK��Z�/�h����".pkgxml/Pear_Mail_Mime-1.10.11.xmlnu�[���PK��ZtWY�n�n%.pkgxml/Symfony2_HttpKernel-2.4.3.xmlnu�[���PK��Z�1��ss..pkgxml/Symfony2_DependencyInjection-2.4.3.xmlnu�[���PK��Z=��4��(.pkgxml/Symfony2_MonologBridge-2.4.3.xmlnu�[���PK��Z�7�p�K�K.pkgxml/XML_Util.xmlnu�[���PK��Z��-=-=".pkgxml/Symfony2_Routing-2.4.3.xmlnu�[���PK��Z�|g��$.pkgxml/Symfony2_Validator-2.4.3.xmlnu�[���PK��Z�d+)SS!.pkgxml/Symfony2_Locale-2.4.3.xmlnu�[���PK��Z%ONO��&.pkgxml/Pear_Mail_mimeDecode-1.5.6.xmlnu�[���PK��Z�*�OO.pkgxml/ezc.xmlnu�[���PK��Z#�r�

 .pkgxml/Pear_Net_SMTP-1.10.0.xmlnu�[���PK��Za������.pkgxml/Symfony2_Form-2.4.3.xmlnu�[���PK��Z�Q���?�? .pkgxml/Pear_Net_Sieve-1.4.5.xmlnu�[���PK��Z��F��%.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu�[���PK��Z?�4��
�
%.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu�[���PK��Z��t8��%.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�PK��Z��n�++.pkgxml/Symfony2_Yaml-2.4.3.xmlnu�[���PK��Z}3YN��.pkgxml/eZc_Archive-1.4.1.xmlnu�[���PK��Z��b�8�8!.pkgxml/Symfony2_Config-2.4.3.xmlnu�[���PK��Z�$v��*.pkgxml/Symfony2_OptionsResolver-2.4.3.xmlnu�[���PK��Z�/�h����".pkgxml/Pear_Mail_Mime-1.10.11.xmlnu�[���PK��ZtWY�n�n%.pkgxml/Symfony2_HttpKernel-2.4.3.xmlnu�[���PK��Z�1��ss..pkgxml/Symfony2_DependencyInjection-2.4.3.xmlnu�[���PK��Z=��4��(.pkgxml/Symfony2_MonologBridge-2.4.3.xmlnu�[���PK��Z�7�p�K�K.pkgxml/XML_Util.xmlnu�[���PK��Z��-=-=".pkgxml/Symfony2_Routing-2.4.3.xmlnu�[���PK��Z�|g��$.pkgxml/Symfony2_Validator-2.4.3.xmlnu�[���PK��Z�d+)SS!.pkgxml/Symfony2_Locale-2.4.3.xmlnu�[���PK��Z%ONO��&.pkgxml/Pear_Mail_mimeDecode-1.5.6.xmlnu�[���PK��Z�*�OO.pkgxml/ezc.xmlnu�[���PK��Z#�r�

 .pkgxml/Pear_Net_SMTP-1.10.0.xmlnu�[���PK��Za������.pkgxml/Symfony2_Form-2.4.3.xmlnu�[���PK��Z�Q���?�? .pkgxml/Pear_Net_Sieve-1.4.5.xmlnu�[���PK��Z��F��%.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu�[���PK��Z?�4��
�
%.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu�[���PK��Z��t8��%.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getoptPK��Z}3YN��.pkgxml/eZc_Archive-1.4.1.xmlnu�[���PK��Z��b�8�8!.pkgxml/Symfony2_Config-2.4.3.xmlnu�[���PK��Z�$v��*.pkgxml/Symfony2_OptionsResolver-2.4.3.xmlnu�[���PK��Z�/�h����".pkgxml/Pear_Mail_Mime-1.10.11.xmlnu�[���PK��ZtWY�n�n%.pkgxml/Symfony2_HttpKernel-2.4.3.xmlnu�[���PK��Z�1��ss..pkgxml/Symfony2_DependencyInjection-2.4.3.xmlnu�[���PK��Z=��4��(.pkgxml/Symfony2_MonologBridge-2.4.3.xmlnu�[���PK��Z�7�p�K�K.pkgxml/XML_Util.xmlnu�[���PK��Z��-=-=".pkgxml/Symfony2_Routing-2.4.3.xmlnu�[���PK��Z�|g��$.pkgxml/Symfony2_Validator-2.4.3.xmlnu�[���PK��Z�d+)SS!.pkgxml/Symfony2_Locale-2.4.3.xmlnu�[���PK��Z%ONO��&.pkgxml/Pear_Mail_mimeDecode-1.5.6.xmlnu�[���PK��Z�*�OO.pkgxml/ezc.xmlnu�[���PK��Z#�r�

 .pkgxml/Pear_Net_SMTP-1.10.0.xmlnu�[���PK��Za������.pkgxml/Symfony2_Form-2.4.3.xmlnu�[���PK��Z�Q���?�? .pkgxml/Pear_Net_Sieve-1.4.5.xmlnu�[���PK��Z��F��%.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu�[���PK��Z?�4��
�
%.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu�[���PK��Z��t8��%.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) PK��Z��b�8�8!.pkgxml/Symfony2_Config-2.4.3.xmlnu�[���PK��Z�$v��*.pkgxml/Symfony2_OptionsResolver-2.4.3.xmlnu�[���PK��Z�/�h����".pkgxml/Pear_Mail_Mime-1.10.11.xmlnu�[���PK��ZtWY�n�n%.pkgxml/Symfony2_HttpKernel-2.4.3.xmlnu�[���PK��Z�1��ss..pkgxml/Symfony2_DependencyInjection-2.4.3.xmlnu�[���PK��Z=��4��(.pkgxml/Symfony2_MonologBridge-2.4.3.xmlnu�[���PK��Z�7�p�K�K.pkgxml/XML_Util.xmlnu�[���PK��Z��-=-=".pkgxml/Symfony2_Routing-2.4.3.xmlnu�[���PK��Z�|g��$.pkgxml/Symfony2_Validator-2.4.3.xmlnu�[���PK��Z�d+)SS!.pkgxml/Symfony2_Locale-2.4.3.xmlnu�[���PK��Z%ONO��&.pkgxml/Pear_Mail_mimeDecode-1.5.6.xmlnu�[���PK��Z�*�OO.pkgxml/ezc.xmlnu�[���PK��Z#�r�

 .pkgxml/Pear_Net_SMTP-1.10.0.xmlnu�[���PK��Za������.pkgxml/Symfony2_Form-2.4.3.xmlnu�[���PK��Z�Q���?�? .pkgxml/Pear_Net_Sieve-1.4.5.xmlnu�[���PK��Z��F��%.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu�[���PK��Z?�4��
�
%.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu�[���PK��Z��t8��%.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                sPK��Z�$v��*.pkgxml/Symfony2_OptionsResolver-2.4.3.xmlnu�[���PK��Z�/�h����".pkgxml/Pear_Mail_Mime-1.10.11.xmlnu�[���PK��ZtWY�n�n%.pkgxml/Symfony2_HttpKernel-2.4.3.xmlnu�[���PK��Z�1��ss..pkgxml/Symfony2_DependencyInjection-2.4.3.xmlnu�[���PK��Z=��4��(.pkgxml/Symfony2_MonologBridge-2.4.3.xmlnu�[���PK��Z�7�p�K�K.pkgxml/XML_Util.xmlnu�[���PK��Z��-=-=".pkgxml/Symfony2_Routing-2.4.3.xmlnu�[���PK��Z�|g��$.pkgxml/Symfony2_Validator-2.4.3.xmlnu�[���PK��Z�d+)SS!.pkgxml/Symfony2_Locale-2.4.3.xmlnu�[���PK��Z%ONO��&.pkgxml/Pear_Mail_mimeDecode-1.5.6.xmlnu�[���PK��Z�*�OO.pkgxml/ezc.xmlnu�[���PK��Z#�r�

 .pkgxml/Pear_Net_SMTP-1.10.0.xmlnu�[���PK��Za������.pkgxml/Symfony2_Form-2.4.3.xmlnu�[���PK��Z�Q���?�? .pkgxml/Pear_Net_Sieve-1.4.5.xmlnu�[���PK��Z��F��%.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu�[���PK��Z?�4��
�
%.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu�[���PK��Z��t8��%.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PKPK��Z�/�h����".pkgxml/Pear_Mail_Mime-1.10.11.xmlnu�[���PK��ZtWY�n�n%.pkgxml/Symfony2_HttpKernel-2.4.3.xmlnu�[���PK��Z�1��ss..pkgxml/Symfony2_DependencyInjection-2.4.3.xmlnu�[���PK��Z=��4��(.pkgxml/Symfony2_MonologBridge-2.4.3.xmlnu�[���PK��Z�7�p�K�K.pkgxml/XML_Util.xmlnu�[���PK��Z��-=-=".pkgxml/Symfony2_Routing-2.4.3.xmlnu�[���PK��Z�|g��$.pkgxml/Symfony2_Validator-2.4.3.xmlnu�[���PK��Z�d+)SS!.pkgxml/Symfony2_Locale-2.4.3.xmlnu�[���PK��Z%ONO��&.pkgxml/Pear_Mail_mimeDecode-1.5.6.xmlnu�[���PK��Z�*�OO.pkgxml/ezc.xmlnu�[���PK��Z#�r�

 .pkgxml/Pear_Net_SMTP-1.10.0.xmlnu�[���PK��Za������.pkgxml/Symfony2_Form-2.4.3.xmlnu�[���PK��Z�Q���?�? .pkgxml/Pear_Net_Sieve-1.4.5.xmlnu�[���PK��Z��F��%.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu�[���PK��Z?�4��
�
%.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu�[���PK��Z��t8��%.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUri   URI of the namespace
     * @param bool   $multiline      whether to create a multiline tag where each
     *                               attribute gets written to a single line
     * @param string $indent         string used to indent attributes (_auto indents
     *                               attributes so they start at the same column)
     * @param string $linebreak      string used for linebreaks
     * @param bool   $sortAttributes Whether to sort the attributes or not
     *
     * @return string XML start element
     * @see    createEndElement(), createTag()
     */
    public static function createStartElement(
        $qname, $attributes = array(), $namespaceUri = null,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true
    ) {
        // if no attributes hav been set, use empty attributes
        if (!isset($attributes) || !is_array($attributes)) {
            $attributes = array();
        }

        if ($namespaceUri != null) {
            $parts = XML_Util::splitQualifiedName($qname);
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($qname)+2));
            }
        }

        if ($namespaceUri != null) {
            // is a namespace given
            if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
            } else {
                // define this Uri as the default namespace
                $attributes['xmlns'] = $namespaceUri;
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $attributes, $sortAttributes,
            $multiline, $indent, $linebreak
        );
        $element = sprintf('<%s%s>', $qname, $attList);
        return  $element;
    }

    /**
     * Create an end element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createEndElement('myNs:myTag');
     * </code>
     *
     * @param string $qname qualified tagname (including namespace)
     *
     * @return string XML end element
     * @see    createStartElement(), createTag()
     */
    public static function createEndElement($qname)
    {
        $element = sprintf('</%s>', $qname);
        return $element;
    }

    /**
     * Create an XML comment
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createComment('I am a comment');
     * </code>
     *
     * @param string $content content of the comment
     *
     * @return string XML comment
     */
    public static function createComment($content)
    {
        $comment = sprintf('<!-- %s -->', $content);
        return $comment;
    }

    /**
     * Create a CData section
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create a CData section
     * $tag = XML_Util::createCDataSection('I am content.');
     * </code>
     *
     * @param string $data data of the CData section
     *
     * @return string CData section with content
     */
    public static function createCDataSection($data)
    {
        return sprintf(
            '<![CDATA[%s]]>',
            preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data))
        );
    }

    /**
     * Split qualified name and return namespace and local part
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // split qualified tag
     * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
     * </code>
     * the returned array will contain two elements:
     * <pre>
     * array(
     *     'namespace' => 'xslt',
     *     'localPart' => 'stylesheet'
     * );
     * </pre>
     *
     * @param string $qname     qualified tag name
     * @param string $defaultNs default namespace (optional)
     *
     * @return array array containing namespace and local part
     */
    public static function splitQualifiedName($qname, $defaultNs = null)
    {
        if (strstr($qname, ':')) {
            $tmp = explode(':', $qname);
            return array(
                'namespace' => $tmp[0],
                'localPart' => $tmp[1]
            );
        }
        return array(
            'namespace' => $defaultNs,
            'localPart' => $qname
        );
    }

    /**
     * Check, whether string is valid XML name
     *
     * <p>XML names are used for tagname, attribute names and various
     * other, lesser known entities.</p>
     * <p>An XML name may only consist of alphanumeric characters,
     * dashes, undescores and periods, and has to start with a letter
     * oPK��ZtWY�n�n%.pkgxml/Symfony2_HttpKernel-2.4.3.xmlnu�[���PK��Z�1��ss..pkgxml/Symfony2_DependencyInjection-2.4.3.xmlnu�[���PK��Z=��4��(.pkgxml/Symfony2_MonologBridge-2.4.3.xmlnu�[���PK��Z�7�p�K�K.pkgxml/XML_Util.xmlnu�[���PK��Z��-=-=".pkgxml/Symfony2_Routing-2.4.3.xmlnu�[���PK��Z�|g��$.pkgxml/Symfony2_Validator-2.4.3.xmlnu�[���PK��Z�d+)SS!.pkgxml/Symfony2_Locale-2.4.3.xmlnu�[���PK��Z%ONO��&.pkgxml/Pear_Mail_mimeDecode-1.5.6.xmlnu�[���PK��Z�*�OO.pkgxml/ezc.xmlnu�[���PK��Z#�r�

 .pkgxml/Pear_Net_SMTP-1.10.0.xmlnu�[���PK��Za������.pkgxml/Symfony2_Form-2.4.3.xmlnu�[���PK��Z�Q���?�? .pkgxml/Pear_Net_Sieve-1.4.5.xmlnu�[���PK��Z��F��%.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu�[���PK��Z?�4��
�
%.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu�[���PK��Z��t8��%.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-PK��Z�1��ss..pkgxml/Symfony2_DependencyInjection-2.4.3.xmlnu�[���PK��Z=��4��(.pkgxml/Symfony2_MonologBridge-2.4.3.xmlnu�[���PK��Z�7�p�K�K.pkgxml/XML_Util.xmlnu�[���PK��Z��-=-=".pkgxml/Symfony2_Routing-2.4.3.xmlnu�[���PK��Z�|g��$.pkgxml/Symfony2_Validator-2.4.3.xmlnu�[���PK��Z�d+)SS!.pkgxml/Symfony2_Locale-2.4.3.xmlnu�[���PK��Z%ONO��&.pkgxml/Pear_Mail_mimeDecode-1.5.6.xmlnu�[���PK��Z�*�OO.pkgxml/ezc.xmlnu�[���PK��Z#�r�

 .pkgxml/Pear_Net_SMTP-1.10.0.xmlnu�[���PK��Za������.pkgxml/Symfony2_Form-2.4.3.xmlnu�[���PK��Z�Q���?�? .pkgxml/Pear_Net_Sieve-1.4.5.xmlnu�[���PK��Z��F��%.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu�[���PK��Z?�4��
�
%.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu�[���PK��Z��t8��%.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        /PK��Z=��4��(.pkgxml/Symfony2_MonologBridge-2.4.3.xmlnu�[���PK��Z�7�p�K�K.pkgxml/XML_Util.xmlnu�[���PK��Z��-=-=".pkgxml/Symfony2_Routing-2.4.3.xmlnu�[���PK��Z�|g��$.pkgxml/Symfony2_Validator-2.4.3.xmlnu�[���PK��Z�d+)SS!.pkgxml/Symfony2_Locale-2.4.3.xmlnu�[���PK��Z%ONO��&.pkgxml/Pear_Mail_mimeDecode-1.5.6.xmlnu�[���PK��Z�*�OO.pkgxml/ezc.xmlnu�[���PK��Z#�r�

 .pkgxml/Pear_Net_SMTP-1.10.0.xmlnu�[���PK��Za������.pkgxml/Symfony2_Form-2.4.3.xmlnu�[���PK��Z�Q���?�? .pkgxml/Pear_Net_Sieve-1.4.5.xmlnu�[���PK��Z��F��%.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu�[���PK��Z?�4��
�
%.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu�[���PK��Z��t8��%.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/PK��Z�7�p�K�K.pkgxml/XML_Util.xmlnu�[���PK��Z��-=-=".pkgxml/Symfony2_Routing-2.4.3.xmlnu�[���PK��Z�|g��$.pkgxml/Symfony2_Validator-2.4.3.xmlnu�[���PK��Z�d+)SS!.pkgxml/Symfony2_Locale-2.4.3.xmlnu�[���PK��Z%ONO��&.pkgxml/Pear_Mail_mimeDecode-1.5.6.xmlnu�[���PK��Z�*�OO.pkgxml/ezc.xmlnu�[���PK��Z#�r�

 .pkgxml/Pear_Net_SMTP-1.10.0.xmlnu�[���PK��Za������.pkgxml/Symfony2_Form-2.4.3.xmlnu�[���PK��Z�Q���?�? .pkgxml/Pear_Net_Sieve-1.4.5.xmlnu�[���PK��Z��F��%.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu�[���PK��Z?�4��
�
%.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu�[���PK��Z��t8��%.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replPK��Z��-=-=".pkgxml/Symfony2_Routing-2.4.3.xmlnu�[���PK��Z�|g��$.pkgxml/Symfony2_Validator-2.4.3.xmlnu�[���PK��Z�d+)SS!.pkgxml/Symfony2_Locale-2.4.3.xmlnu�[���PK��Z%ONO��&.pkgxml/Pear_Mail_mimeDecode-1.5.6.xmlnu�[���PK��Z�*�OO.pkgxml/ezc.xmlnu�[���PK��Z#�r�

 .pkgxml/Pear_Net_SMTP-1.10.0.xmlnu�[���PK��Za������.pkgxml/Symfony2_Form-2.4.3.xmlnu�[���PK��Z�Q���?�? .pkgxml/Pear_Net_Sieve-1.4.5.xmlnu�[���PK��Z��F��%.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu�[���PK��Z?�4��
�
%.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu�[���PK��Z��t8��%.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-PK��Z�|g��$.pkgxml/Symfony2_Validator-2.4.3.xmlnu�[���PK��Z�d+)SS!.pkgxml/Symfony2_Locale-2.4.3.xmlnu�[���PK��Z%ONO��&.pkgxml/Pear_Mail_mimeDecode-1.5.6.xmlnu�[���PK��Z�*�OO.pkgxml/ezc.xmlnu�[���PK��Z#�r�

 .pkgxml/Pear_Net_SMTP-1.10.0.xmlnu�[���PK��Za������.pkgxml/Symfony2_Form-2.4.3.xmlnu�[���PK��Z�Q���?�? .pkgxml/Pear_Net_Sieve-1.4.5.xmlnu�[���PK��Z��F��%.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu�[���PK��Z?�4��
�
%.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu�[���PK��Z��t8��%.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUri   URI of the namespace
     * @param bool   $multiline      whether to create a multiline tag where each
     *                               attribute gets written to a single line
     * @param string $indent         string used to indent attributes (_auto indents
     *                               attributes so they start at the same column)
     * @param string $linebreak      string used for linebreaks
     * @param bool   $sortAttributes Whether to sort the attributes or not
     *
     * @return string XML start element
     * @see    createEndElement(), createTag()
     */
    public static function createStartElement(
        $qname, $attributes = array(), $namespaceUri = null,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true
    ) {
        // if no attributes hav been set, use empty attributes
        if (!isset($attributes) || !is_array($attributes)) {
            $attributes = array();
        }

        if ($namespaceUri != null) {
            $parts = XML_Util::splitQualifiedName($qname);
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($qname)+2));
            }
        }

        if ($namespaceUri != null) {
            // is a namespace given
            if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
            } else {
                // define this Uri as the default namespace
                $attributes['xmlns'] = $namespaceUri;
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $attributes, $sortAttributes,
            $multiline, $indent, $linebreak
        );
        $element = sprintf('<%s%s>', $qname, $attList);
        return  $element;
    }

    /**
     * Create an end element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createEndElement('myNs:myTag');
     * </code>
     *
     * @param string $qname qualified tagname (including namespace)
     *
     * @return string XML end element
     * @see    createStartElement(), createTag()
     */
    public static function createEndElement($qname)
    {
        $element = sprintf('</%s>', $qname);
        return $element;
    }

    /**
     * Create an XML comment
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createComment('I am a comment');
     * </code>
     *
     * @param string $content content of the comment
     *
     * @return string XML comment
     */
    public static function createComment($content)
    {
        $comment = sprintf('<!-- %s -->', $content);
        return $comment;
    }

    /**
     * Create a CData section
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create a CData section
     * $tag = XML_Util::createCDataSection('I am content.');
     * </code>
     *
     * @param string $data data of the CData section
     *
     * @return string CData section with content
     */
    public static function createCDataSection($data)
    {
        return sprintf(
            '<![CDATA[%s]]>',
            preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data))
        );
    }

    /**
     * Split qualified name and return namespace and local part
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // split qualified tag
     * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
     * </code>
     * the returned array will contain two elements:
     * <pre>
     * array(
     *     'namespace' => 'xslt',
     *     'localPart' => 'stylesheet'
     * );
     * </pre>
     *
     * @param string $qname     qualified tag name
     * @param string $defaultNs default namespace (optional)
     *
     * @return array array containing namespace and local part
     */
    public static function splitQualifiedName($qname, $defaultNs = null)
    {
        if (strstr($qname, ':')) {
            $tmp = explode(':', $qname);
            return array(
                'namespace' => $tmp[0],
                'localPart' => $tmp[1]
            );
        }
        return array(
            'namespace' => $defaultNs,
            'localPart' => $qname
        );
    }

    /**
     * Check, whether string is valid XML name
     *
     * <p>XML names are used for tagname, attribute names and various
     * other, lesser known entities.</p>
     * <p>An XML name may only consist of alphanumeric characters,
     * dashes, undescores and periods, and has to start with a letter
     * or an underscore.</p>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // verify tag name
     * $result = XML_Util::isValidName('invalidTag?');
     * if (is_a($result, 'PEAR_Error')) {
     *    print 'Invalid XML name: ' . $result->getMessage();
     * }
     * </code>
     *
     * @param string $string string that should be checked
     *
     * @return mixed true, if string is a valid XML name, PEAR error otherwise
     *
     * @todo support for other charsets
     * @todo PEAR CS - unable to avoid 85-char limit on second preg_match
     */
    public static function isValidName($string)
    {
        // check for invalid chars
        if (!is_string($string) || !strlen($string) || !preg_match('/^[[:alpha:]_]\\z/', $string[0])) {
            return XML_Util::raiseError(
                'XML names may only start with letter or underscore',
                XML_UTIL_ERROR_INVALID_START
            );
        }

        // check for invalid chars
        $match = preg_match(
            '/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?'
            . '[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/',
            $string
        );
        if (!$match) {
            return XML_Util::raiseError(
                'XML names may only contain alphanumeric '
                . 'chars, period, hyphen, colon and underscores',
                XML_UTIL_ERROR_INVALID_CHARS
            );
        }
        // XML name is valid
        return true;
    }

    /**
     * Replacement for XML_Util::raiseError
     *
     * Avoids the necessity to always require
     * PEAR.php
     *
     * @param string $msg  error message
     * @param int    $code error code
     *
     * @return PEAR_Error
     * @todo   PEAR CS - should this use include_once instead?
     */
    public static function raiseError($msg, $code)
    {
        include_once 'PEAR.php';
        return PEAR::raiseError($msg, $code);
    }
}
?>
PK��Z#F��:�:pearcmd.phpnu�[���<?php
/**
 * PEAR, the PHP Extension and Application Repository
 *
 * Command line interface
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Stig Bakken <ssb@php.net>
 * @author    Tomas V.V.Cox <cox@idecnet.com>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 */

@ob_end_clean();
if (!defined('PEAR_RUNTYPE')) {
    // this is defined in peclcmd.php as 'pecl'
    define('PEAR_RUNTYPE', 'pear');
}
define('PEAR_IGNORE_BACKTRACE', 1);
/**
 * @nodep Gtk
 */
//the space is needed for windows include paths with trailing backslash
// http://pear.php.net/bugs/bug.php?id=19482
if ('/opt/alt/php74/usr/share/pear ' != '@'.'include_path'.'@ ') {
    ini_set('include_path', trim('/opt/alt/php74/usr/share/pear '). PATH_SEPARATOR .  get_include_path());
    $raw = false;
} else {
    // this is a raw, uninstalled pear, either a cvs checkout, or php distro
    ini_set('include_path', dirname(__DIR__) . PATH_SEPARATOR . get_include_path());
    $raw = true;
}
@ini_set('allow_url_fopen', true);
@set_time_limit(0);
ob_implicit_flush(true);
@ini_set('track_errors', true);
@ini_set('html_errors', false);
$_PEAR_PHPDIR = '#$%^&*';
set_error_handler('error_handler');

$pear_package_version = "1.10.16";

require_once 'PEAR.php';
require_once 'PEAR/Frontend.php';
require_once 'PEAR/Config.php';
require_once 'PEAR/Command.php';
require_once 'Console/Getopt.php';


PEAR_Command::setFrontendType('CLI');
$all_commands = PEAR_Command::getCommands();

$argv = Console_Getopt::readPHPArgv();
// fix CGI sapi oddity - the -- in pear.bat/pear is not removed
if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
    unset($argv[1]);
    $argv = array_values($argv);
}
$progname = PEAR_RUNTYPE;
array_shift($argv);
$options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV");
if (PEAR::isError($options)) {
    usage($options);
}

$opts = $options[0];

$fetype = 'CLI';
if ($progname == 'gpear' || $progname == 'pear-gtk') {
    $fetype = 'Gtk2';
} else {
    foreach ($opts as $opt) {
        if ($opt[0] == 'G') {
            $fetype = 'Gtk2';
        }
    }
}

$pear_user_config = '';
$pear_system_config = '';
$store_user_config = false;
$store_system_config = false;
$verbose = 1;

foreach ($opts as $opt) {
    switch ($opt[0]) {
    case 'c':
        $pear_user_config = $opt[1];
        break;
    case 'C':
        $pear_system_config = $opt[1];
        break;
    }
}

PEAR_Command::setFrontendType($fetype);
$ui = &PEAR_Command::getFrontendObject();
$config = &PEAR_Config::singleton($pear_user_config, $pear_system_config);

if (PEAR::isError($config)) {
    $_file = '';
    if ($pear_user_config !== false) {
        $_file .= $pear_user_config;
    }
    if ($pear_system_config !== false) {
        $_file .= '/' . $pear_system_config;
    }
    if ($_file == '/') {
        $_file = 'The default config file';
    }
    $config->getMessage();
    $ui->outputData("ERROR: $_file is not a valid config file or is corrupted.");
    // We stop, we have no idea where we are :)
    exit(1);
}

// this is used in the error handler to retrieve a relative path
$_PEAR_PHPDIR = $config->get('php_dir');
$ui->setConfig($config);
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError"));

$verbose = $config->get("verbose");
$cmdopts = array();

if ($raw) {
    if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) {
        $found = false;
        foreach ($opts as $opt) {
            if ($opt[0] == 'd' || $opt[0] == 'D') {
                // the user knows what they are doing, and are setting config values
                $found = true;
            }
        }
        if (!$found) {
            // no prior runs, try to install PEAR
            $parent = dirname(__FILE__);
            if (strpos($parent, 'scripts')) {
                $PK��Z�d+)SS!.pkgxml/Symfony2_Locale-2.4.3.xmlnu�[���PK��Z%ONO��&.pkgxml/Pear_Mail_mimeDecode-1.5.6.xmlnu�[���PK��Z�*�OO.pkgxml/ezc.xmlnu�[���PK��Z#�r�

 .pkgxml/Pear_Net_SMTP-1.10.0.xmlnu�[���PK��Za������.pkgxml/Symfony2_Form-2.4.3.xmlnu�[���PK��Z�Q���?�? .pkgxml/Pear_Net_Sieve-1.4.5.xmlnu�[���PK��Z��F��%.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu�[���PK��Z?�4��
�
%.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu�[���PK��Z��t8��%.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z%ONO��&.pkgxml/Pear_Mail_mimeDecode-1.5.6.xmlnu�[���PK��Z�*�OO.pkgxml/ezc.xmlnu�[���PK��Z#�r�

 .pkgxml/Pear_Net_SMTP-1.10.0.xmlnu�[���PK��Za������.pkgxml/Symfony2_Form-2.4.3.xmlnu�[���PK��Z�Q���?�? .pkgxml/Pear_Net_Sieve-1.4.5.xmlnu�[���PK��Z��F��%.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu�[���PK��Z?�4��
�
%.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu�[���PK��Z��t8��%.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not bPK��Z�*�OO.pkgxml/ezc.xmlnu�[���PK��Z#�r�

 .pkgxml/Pear_Net_SMTP-1.10.0.xmlnu�[���PK��Za������.pkgxml/Symfony2_Form-2.4.3.xmlnu�[���PK��Z�Q���?�? .pkgxml/Pear_Net_Sieve-1.4.5.xmlnu�[���PK��Z��F��%.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu�[���PK��Z?�4��
�
%.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu�[���PK��Z��t8��%.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK�PK��Z#�r�

 .pkgxml/Pear_Net_SMTP-1.10.0.xmlnu�[���PK��Za������.pkgxml/Symfony2_Form-2.4.3.xmlnu�[���PK��Z�Q���?�? .pkgxml/Pear_Net_Sieve-1.4.5.xmlnu�[���PK��Z��F��%.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu�[���PK��Z?�4��
�
%.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu�[���PK��Z��t8��%.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translatPK��Za������.pkgxml/Symfony2_Form-2.4.3.xmlnu�[���PK��Z�Q���?�? .pkgxml/Pear_Net_Sieve-1.4.5.xmlnu�[���PK��Z��F��%.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu�[���PK��Z?�4��
�
%.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu�[���PK��Z��t8��%.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUri   URI of the namespace
     * @param bool   $multiline      whether to create a multiline tag where each
     *                               attribute gets written to a single line
     * @param string $indent         string used to indent attributes (_auto indents
     *                               attributes so they start at the same column)
     * @param string $linebreak      string used for linebreaks
     * @param bool   $sortAttributes Whether to sort the attributes or not
     *
     * @return string XML start element
     * @see    createEndElement(), createTag()
     */
    public static function createStartElement(
        $qname, $attributes = array(), $namespaceUri = null,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true
    ) {
        // if no attributes hav been set, use empty attributes
        if (!isset($attributes) || !is_array($attributes)) {
            $attributes = array();
        }

        if ($namespaceUri != null) {
            $parts = XML_Util::splitQualifiedName($qname);
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($qname)+2));
            }
        }

        if ($namespaceUri != null) {
            // is a namespace given
            if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
            } else {
                // define this Uri as the default namespace
                $attributes['xmlns'] = $namespaceUri;
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $attributes, $sortAttributes,
            $multiline, $indent, $linebreak
        );
        $element = sprintf('<%s%s>', $qname, $attList);
        return  $element;
    }

    /**
     * Create an end element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createEndElement('myNs:myTag');
     * </code>
     *
     * @param string $qname qualified tagname (including namespace)
     *
     * @return string XML end element
     * @see    createStartElement(), createTag()
     */
    public static function createEndElement($qname)
    {
        $element = sprintf('</%s>', $qname);
        return $element;
    }

    /**
     * Create an XML comment
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createComment('I am a comment');
     * </code>
     *
     * @param string $content content of the comment
     *
     * @return string XML comment
     */
    public static function createComment($content)
    {
        $comment = sprintf('<!-- %s -->', $content);
        return $comment;
    }

    /**
     * Create a CData section
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create a CData section
     * $tag = XML_Util::createCDataSection('I am content.');
     * </code>
     *
     * @param string $data data of the CData section
     *
     * @return string CData section with content
     */
    public static function createCDataSection($data)
    {
        return sprintf(
            '<![CDATA[%s]]>',
            preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data))
        );
    }

    /**
     * Split qualified name and return namespace and local part
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // split qualified tag
     * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
     * </code>
     * the returned array will contain two elements:
     * <pre>
     * array(
     *     'namespace' => 'xslt',
     *     'localPart' => 'stylesheet'
     * );
     * </pre>
     *
     * @param string $qname     qualified tag name
     * @param string $defaultNs default namespace (optional)
     *
     * @return array array containing namespace and local part
     */
    public static function splitQualifiedName($qname, $defaultNs = null)
    {
        if (strstr($qname, ':')) {
            $tmp = explode(':', $qname);
            return array(
                'namespace' => $tmp[0],
                'localPart' => $tmp[1]
            );
        }
        return array(
            'namespace' => $defaultNs,
            'localPart' => $qname
        );
    }

    /**
     * Check, whether string is valid XML name
     *
     * <p>XML names are used for tagname, attribute names and various
     * other, lesser known entities.</p>
     * <p>An XML name may only consist of alphanumeric characters,
     * dashes, undescores and periods, and has to start with a letter
     * or an underscore.</p>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // verify tag name
     * $result = XML_Util::isValidName('invalidTag?');
     * if (is_a($result, 'PEAR_Error')) {
     *    print 'Invalid XML name: ' . $result->getMessage();
     * }
     * </code>
     *
     * @param string $string string that should be checked
     *
     * @return mixed true, if string is a valid XML name, PEAR error otherwise
     *
     * @todo support for other charsets
     * @todo PEAR CS - unable to avoid 85-char limit on second preg_match
     */
    public static function isValidName($string)
    {
        // check for invalid chars
        if (!is_string($string) || !strlen($string) || !preg_match('/^[[:alpha:]_]\\z/', $string[0])) {
            return XML_Util::raiseError(
                'XML names may only start with letter or underscore',
                XML_UTIL_ERROR_INVALID_START
            );
        }

        // check for invalid chars
        $match = preg_match(
            '/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?'
            . '[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/',
            $string
        );
        if (!$match) {
            return XML_Util::raiseError(
                'XML names may only contain alphanumeric '
                . 'chars, period, hyphen, colon and underscores',
                XML_UTIL_ERROR_INVALID_CHARS
            );
        }
        // XML name is valid
        return true;
    }

    /**
     * Replacement for XML_Util::raiseError
     *
     * Avoids the necessity to always require
     * PEAR.php
     *
     * @param string $msg  error message
     * @param int    $code error code
     *
     * @return PEAR_Error
     * @todo   PEAR CS - should this use include_once instead?
     */
    public static function raiseError($msg, $code)
    {
        include_once 'PEAR.php';
        return PEAR::raiseError($msg, $code);
    }
}
?>
PK��Z#F��:�:pearcmd.phpnu�[���<?php
/**
 * PEAR, the PHP Extension and Application Repository
 *
 * Command line interface
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Stig Bakken <ssb@php.net>
 * @author    Tomas V.V.Cox <cox@idecnet.com>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 */

@ob_end_clean();
if (!defined('PEAR_RUNTYPE')) {
    // this is defined in peclcmd.php as 'pecl'
    define('PEAR_RUNTYPE', 'pear');
}
define('PEAR_IGNORE_BACKTRACE', 1);
/**
 * @nodep Gtk
 */
//the space is needed for windows include paths with trailing backslash
// http://pear.php.net/bugs/bug.php?id=19482
if ('/opt/alt/php74/usr/share/pear ' != '@'.'include_path'.'@ ') {
    ini_set('include_path', trim('/opt/alt/php74/usr/share/pear '). PATH_SEPARATOR .  get_include_path());
    $raw = false;
} else {
    // this is a raw, uninstalled pear, either a cvs checkout, or php distro
    ini_set('include_path', dirname(__DIR__) . PATH_SEPARATOR . get_include_path());
    $raw = true;
}
@ini_set('allow_url_fopen', true);
@set_time_limit(0);
ob_implicit_flush(true);
@ini_set('track_errors', true);
@ini_set('html_errors', false);
$_PEAR_PHPDIR = '#$%^&*';
set_error_handler('error_handler');

$pear_package_version = "1.10.16";

require_once 'PEAR.php';
require_once 'PEAR/Frontend.php';
require_once 'PEAR/Config.php';
require_once 'PEAR/Command.php';
require_once 'Console/Getopt.php';


PEAR_Command::setFrontendType('CLI');
$all_commands = PEAR_Command::getCommands();

$argv = Console_Getopt::readPHPArgv();
// fix CGI sapi oddity - the -- in pear.bat/pear is not removed
if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
    unset($argv[1]);
    $argv = array_values($argv);
}
$progname = PEAR_RUNTYPE;
array_shift($argv);
$options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV");
if (PEAR::isError($options)) {
    usage($options);
}

$opts = $options[0];

$fetype = 'CLI';
if ($progname == 'gpear' || $progname == 'pear-gtk') {
    $fetype = 'Gtk2';
} else {
    foreach ($opts as $opt) {
        if ($opt[0] == 'G') {
            $fetype = 'Gtk2';
        }
    }
}

$pear_user_config = '';
$pear_system_config = '';
$store_user_config = false;
$store_system_config = false;
$verbose = 1;

foreach ($opts as $opt) {
    switch ($opt[0]) {
    case 'c':
        $pear_user_config = $opt[1];
        break;
    case 'C':
        $pear_system_config = $opt[1];
        break;
    }
}

PEAR_Command::setFrontendType($fetype);
$ui = &PEAR_Command::getFrontendObject();
$config = &PEAR_Config::singleton($pear_user_config, $pear_system_config);

if (PEAR::isError($config)) {
    $_file = '';
    if ($pear_user_config !== false) {
        $_file .= $pear_user_config;
    }
    if ($pear_system_config !== false) {
        $_file .= '/' . $pear_system_config;
    }
    if ($_file == '/') {
        $_file = 'The default config file';
    }
    $config->getMessage();
    $ui->outputData("ERROR: $_file is not a valid config file or is corrupted.");
    // We stop, we have no idea where we are :)
    exit(1);
}

// this is used in the error handler to retrieve a relative path
$_PEAR_PHPDIR = $config->get('php_dir');
$ui->setConfig($config);
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError"));

$verbose = $config->get("verbose");
$cmdopts = array();

if ($raw) {
    if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) {
        $found = false;
        foreach ($opts as $opt) {
            if ($opt[0] == 'd' || $opt[0] == 'D') {
                // the user knows what they are doing, and are setting config values
                $found = true;
            }
        }
        if (!$found) {
            // no prior runs, try to install PEAR
            $parent = dirname(__FILE__);
            if (strpos($parent, 'scripts')) {
                $grandparent = dirname($parent);
                $packagexml = $grandparent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $grandparent;
            } else {
                $packagexml = $parent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $parent;
            }
            if (file_exists($packagexml)) {
                $options[1] = array(
                    'install',
                    $packagexml
                );
                $config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php');
                $config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data');
                $config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs');
                $config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests');
                $config->set(
                    'ext_dir',
                    $pearbase . DIRECTORY_SEPARATOR . 'extensions'
                );
                $config->set('bin_dir', $pearbase);
                $config->mergeConfigFile($pearbase . 'pear.ini', false);
                $config->store();
                $config->set('auto_discover', 1);
            }
        }
    }
}
foreach ($opts as $opt) {
    $param = !empty($opt[1]) ? $opt[1] : true;
    switch ($opt[0]) {
    case 'd':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected -d config_value=value, ' .
                'received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'user');
        break;
    case 'D':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'system');
        break;
    case 's':
        $store_user_config = true;
        break;
    case 'S':
        $store_system_config = true;
        break;
    case 'u':
        $config->remove($param, 'user');
        break;
    case 'v':
        $config->set('verbose', $config->get('verbose') + 1);
        break;
    case 'q':
        $config->set('verbose', $config->get('verbose') - 1);
        break;
    case 'V':
        usage(null, 'version');
    case 'c':
    case 'C':
        break;
    default:
        // all non pear params goes to the command
        $cmdopts[$opt[0]] = $param;
        break;
    }
}

if ($store_system_config) {
    $config->store('system');
}

if ($store_user_config) {
    $config->store('user');
}

$command = (isset($options[1][0])) ? $options[1][0] : null;
if (empty($command) && ($store_user_config || $store_system_config)) {
    exit;
}

if ($fetype == 'Gtk2') {
    if (!$config->validConfiguration()) {
        PEAR::raiseError(
            "CRITICAL ERROR: no existing valid configuration files found in " .
            "files '$pear_user_config' or '$pear_system_config', " .
            "please copy an existing configuration file to one of these " .
            "locations, or use the -c and -s options to create one"
        );
    }
    Gtk::main();
} else {
    do {
        if ($command == 'help') {
            usage(null, isset($options[1][1]) ? $options[1][1] : null);
        }

        if (!$config->validConfiguration()) {
            PEAR::raiseError(
                "CRITICAL ERROR: no existing valid configuration files found " .
                "in files '$pear_user_config' or '$pear_system_config', " .
                "please copy an existing configuration file to one of " .
                "these locations, or use the -c and -s options to create one"
            );
        }

        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        $cmd = PEAR_Command::factory($command, $config);
        PEAR::popErrorHandling();
        if (PEAR::isError($cmd)) {
            usage(null, isset($options[1][0]) ? $options[1][0] : null);
        }

        $short_args = $long_args = null;
        PEAR_Command::getGetoptArgs($command, $short_args, $long_args);
        array_shift($options[1]);
        $tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args);

        if (PEAR::isError($tmp)) {
            break;
        }

        list($tmpopt, $params) = $tmp;
        $opts = array();
        foreach ($tmpopt as $foo => $tmp2) {
            list($opt, $value) = $tmp2;
            if ($value === null) {
                $value = true; // options without args
            }

            if (strlen($opt) == 1) {
                $cmdoptions = $cmd->getOptions($command);
                foreach ($cmdoptions as $o => $d) {
                    if (isset($d['shortopt']) && $d['shortopt'] == $opt) {
                        $opts[$o] = $value;
                    }
                }
            } else {
                if (substr($opt, 0, 2) == '--') {
                    $opts[substr($opt, 2)] = $value;
                }
            }
        }

        $ok = $cmd->run($command, $opts, $params);
        if ($ok === false) {
            PEAR::raiseError("unknown command `$command'");
      PK��Z�Q���?�? .pkgxml/Pear_Net_Sieve-1.4.5.xmlnu�[���PK��Z��F��%.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu�[���PK��Z?�4��
�
%.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu�[���PK��Z��t8��%.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     *PK��Z��F��%.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu�[���PK��Z?�4��
�
%.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu�[���PK��Z��t8��%.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinPK��Z?�4��
�
%.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu�[���PK��Z��t8��%.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�PK��Z��t8��%.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z>t�B�B&.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *        PK��Z��c��� .pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PKPK��Z���>`-`- .pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
            PK��Z�oA A .pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * DoPK��Z�3'�C�C).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                PK��Z�����.pkgxml/Symfony2.listnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��Z8���.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PKPK��Zu&6��%�%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_UtiPK��Zz�WzDD .pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PKPK��Z��UU�_�_".pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
   PK��Z����.pkgxml/Pear.listnu�[���PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.PK��Z�k�b��*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PKPK��Z�3�--,.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.rPK��Zs�YY".pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or withPK��Z�n�J/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
 PK��ZZ2�iHH.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.rPK��ZA��~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITPK��Z�
v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
    PK��Z�܋Fcc.pkgxml/eZc.listnu�[���PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%PK��Z���\\.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�PK��Z��IZ��%.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('PK��Zn#)v�>�>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
    PK��ZT�v�S)S).registry/mail.regnu�[���PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
   PK��Z�K<uvuv.registry/xml_util.regnu�[���PK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUri   URI of the namespace
     * @param bool   $multiline      whether to create a multiline tag where each
     *                               attribute gets written to a single line
     * @param string $indent         string used to indent attributes (_auto indents
     *                               attributes so they start at the same column)
     * @param string $linebreak      string used for linebreaks
     * @param bool   $sortAttributes Whether to sort the attributes or not
     *
     * @return string XML start element
     * @see    createEndElement(), createTag()
     */
    public static function createStartElement(
        $qname, $attributes = array(), $namPK��Z�EINJNJ/.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    PK��ZI6�����/.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUri   URI of the namespace
     * @param bool   $multiline      whether to create a multiline tag where each
     *                               attribute gets written to a single line
     * @param string $indent         string used to indent attributes (_auto indents
     *                               attributes so they start at the same column)
     * @param string $linebreak      string used for linebreaks
     * @param bool   $sortAttributes Whether to sort the attributes or not
     *
     * @return string XML start element
     * @see    createEndElement(), createTag()
     */
    public static function createStartElement(
        $qname, $attributes = array(), $namespaceUri = null,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true
    ) {
        // if no attributes hav been set, use empty attributes
        if (!isset($attributes) || !is_array($attributes)) {
            $attributes = array();
        }

        if ($namespaceUri != null) {
            $parts = XML_Util::splitQualifiedName($qname);
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($qname)+2));
            }
        }

        if ($namespaceUri != null) {
            // is a namespace given
            if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
            } else {
                // define this Uri as the default namespace
                $attributes['xmlns'] = $namespaceUri;
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $attributes, $sortAttributes,
            $multiline, $indent, $linebreak
        );
        $element = sprintf('<%s%s>', $qname, $attList);
        return  $element;
    }

    /**
     * Create an end element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createEndElement('myNs:myTag');
     * </code>
     *
     * @param string $qname qualified tagname (including namespace)
     *
     * @return string XML end element
     * @see    createStartElement(), createTag()
     */
    public static function createEndElement($qname)
    {
        $element = sprintf('</%s>', $qname);
        return $element;
    }

    /**
     * Create an XML comment
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createComment('I am a comment');
     * </code>
     *
     * @param string $content content of the comment
     *
     * @return string XML comment
     */
    public static function createComment($content)
    {
        $comment = sprintf('<!-- %s -->', $content);
        return $comment;
    }

    /**
     * Create a CData section
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create a CData section
     * $tag = XML_Util::createCDataSection('I am content.');
     * </code>
     *
     * @param string $data data of the CData section
     *
     * @return string CData section with content
     */
    public static function createCDataSection($data)
    {
        return sprintf(
            '<![CDATA[%s]]>',
            preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data))
        );
    }

    /**
     * Split qualified name and return namespace and local part
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // split qualified tag
     * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
     * </code>
     * the returned array will contain two elements:
     * <pre>
     * array(
     *     'namespace' => 'xslt',
     *     'localPart' => 'stylesheet'
     * );
     * </pre>
     *
     * @param string $qname     qualified tag name
     * @param string $defaultNs default namespace (optional)
     *
     * @return array array containing namespace and local part
     */
    public static function splitQualifiedName($qname, $defaultNs = null)
    {
        if (strstr($qname, ':')) {
            $tmp = explode(':', $qname);
            return array(
                'namespace' => $tmp[0],
                'localPart' => $tmp[1]
            );
        }
        return array(
            'namespace' => $defaultNs,
            'localPart' => $qname
        );
    }

    /**
     * Check, whether string is valid XML name
     *
     * <p>XML names are used for tagname, attribute names and various
     * other, lesser known entities.</p>
     * <p>An XML name may only consist of alphanumeric characters,
     * dashes, undescores and periods, and has to start with a letter
     * or an underscore.</p>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // verify tag name
     * $result = XML_Util::isValidName('invalidTag?');
     * if (is_a($result, 'PEAR_Error')) {
     *    print 'Invalid XML name: ' . $result->getMessage();
     * }
     * </code>
     *
     * @param string $string string that should be checked
     *
     * @return mixed true, if string is a valid XML name, PEAR error otherwise
     *
     * @todo support for other charsets
     * @todo PEAR CS - unable to avoid 85-char limit on second preg_match
     */
    public static function isValidName($string)
    {
        // check for invalid chars
        if (!is_string($string) || !strlen($string) || !preg_match('/^[[:alpha:]_]\\z/', $string[0])) {
            return XML_Util::raiseError(
                'XML names may only start with letter or underscore',
                XML_UTIL_ERROR_INVALID_START
            );
        }

        // check for invalid chars
        $match = preg_match(
            '/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?'
            . '[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/',
            $string
        );
        if (!$match) {
            return XML_Util::raiseError(
                'XML names may only contain alphanumeric '
                . 'chars, period, hyphen, colon and underscores',
                XML_UTIL_ERROR_INVALID_CHARS
            );
        }
        // XML name is valid
        return true;
    }

    /**
     * Replacement for XML_Util::raiseError
     *
     * Avoids the necessity to always require
     * PEAR.php
     *
     * @param string $msg  error message
     * @param int    $code error code
     *
     * @return PEAR_Error
     * @todo   PEAR CS - should this use include_once instead?
     */
    public static function raiseError($msg, $code)
    {
        include_once 'PEAR.php';
        return PEAR::raiseError($msg, $code);
    }
}
?>
PK��Z#F��:�:pearcmd.phpnu�[���<?php
/**
 * PEAR, the PHP Extension and Application Repository
 *
 * Command line interface
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Stig Bakken <ssb@php.net>
 * @author    Tomas V.V.Cox <cox@idecnet.com>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 */

@ob_end_clean();
if (!defined('PEAR_RUNTYPE')) {
    // this is defined in peclcmd.php as 'pecl'
    define('PEAR_RUNTYPE', 'pear');
}
define('PEAR_IGNORE_BACKTRACE', 1);
/**
 * @nodep Gtk
 */
//the space is needed for windows include paths with trailing backslash
// http://pear.php.net/bugs/bug.php?id=19482
if ('/opt/alt/php74/usr/share/pear ' != '@'.'include_path'.'@ ') {
    ini_set('include_path', trim('/opt/alt/php74/usr/share/pear '). PATH_SEPARATOR .  get_include_path());
    $raw = false;
} else {
    // this is a raw, uninstalled pear, either a cvs checkout, or php distro
    ini_set('include_path', dirname(__DIR__) . PATH_SEPARATOR . get_include_path());
    $raw = true;
}
@ini_set('allow_url_fopen', true);
@set_time_limit(0);
ob_implicit_flush(true);
@ini_set('track_errors', true);
@ini_set('html_errors', false);
$_PEAR_PHPDIR = '#$%^&*';
set_error_handler('error_handler');

$pear_package_version = "1.10.16";

require_once 'PEAR.php';
require_once 'PEAR/Frontend.php';
require_once 'PEAR/Config.php';
require_once 'PEAR/Command.php';
require_once 'Console/Getopt.php';


PEAR_Command::setFrontendType('CLI');
$all_commands = PEAR_Command::getCommands();

$argv = Console_Getopt::readPHPArgv();
// fix CGI sapi oddity - the -- in pear.bat/pear is not removed
if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
    unset($argv[1]);
    $argv = array_values($argv);
}
$progname = PEAR_RUNTYPE;
array_shift($argv);
$options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV");
if (PEAR::isError($options)) {
    usage($options);
}

$opts = $options[0];

$fetype = 'CLI';
if ($progname == 'gpear' || $progname == 'pear-gtk') {
    $fetype = 'Gtk2';
} else {
    foreach ($opts as $opt) {
        if ($opt[0] == 'G') {
            $fetype = 'Gtk2';
        }
    }
}

$pear_user_config = '';
$pear_system_config = '';
$store_user_config = false;
$store_system_config = false;
$verbose = 1;

foreach ($opts as $opt) {
    switch ($opt[0]) {
    case 'c':
        $pear_user_config = $opt[1];
        break;
    case 'C':
        $pear_system_config = $opt[1];
        break;
    }
}

PEAR_Command::setFrontendType($fetype);
$ui = &PEAR_Command::getFrontendObject();
$config = &PEAR_Config::singleton($pear_user_config, $pear_system_config);

if (PEAR::isError($config)) {
    $_file = '';
    if ($pear_user_config !== false) {
        $_file .= $pear_user_config;
    }
    if ($pear_system_config !== false) {
        $_file .= '/' . $pear_system_config;
    }
    if ($_file == '/') {
        $_file = 'The default config file';
    }
    $config->getMessage();
    $ui->outputData("ERROR: $_file is not a valid config file or is corrupted.");
    // We stop, we have no idea where we are :)
    exit(1);
}

// this is used in the error handler to retrieve a relative path
$_PEAR_PHPDIR = $config->get('php_dir');
$ui->setConfig($config);
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError"));

$verbose = $config->get("verbose");
$cmdopts = array();

if ($raw) {
    if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) {
        $found = false;
        foreach ($opts as $opt) {
            if ($opt[0] == 'd' || $opt[0] == 'D') {
                // the user knows what they are doing, and are setting config values
                $found = true;
            }
        }
        if (!$found) {
            // no prior runs, try to install PEAR
            $parent = dirname(__FILE__);
            if (strpos($parent, 'scripts')) {
                $grandparent = dirname($parent);
                $packagexml = $grandparent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $grandparent;
            } else {
                $packagexml = $parent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $parent;
            }
            if (file_exists($packagexml)) {
                $options[1] = array(
                    'install',
                    $packagexml
                );
                $config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php');
                $config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data');
                $config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs');
                $config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests');
                $config->set(
                    'ext_dir',
                    $pearbase . DIRECTORY_SEPARATOR . 'extensions'
                );
                $config->set('bin_dir', $pearbase);
                $config->mergeConfigFile($pearbase . 'pear.ini', false);
                $config->store();
                $config->set('auto_discover', 1);
            }
        }
    }
}
foreach ($opts as $opt) {
    $param = !empty($opt[1]) ? $opt[1] : true;
    switch ($opt[0]) {
    case 'd':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected -d config_value=value, ' .
                'received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'user');
        break;
    case 'D':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'system');
        break;
    case 's':
        $store_user_config = true;
        break;
    case 'S':
        $store_system_config = true;
        break;
    case 'u':
        $config->remove($param, 'user');
        break;
    case 'v':
        $config->set('verbose', $config->get('verbose') + 1);
        break;
    case 'q':
        $config->set('verbose', $config->get('verbose') - 1);
        break;
    case 'V':
        usage(null, 'version');
    case 'c':
    case 'C':
        break;
    default:
        // all non pear params goes to the command
        $cmdopts[$opt[0]] = $param;
        break;
    }
}

if ($store_system_config) {
    $config->store('system');
}

if ($store_user_config) {
    $config->store('user');
}

$command = (isset($options[1][0])) ? $options[1][0] : null;
if (empty($command) && ($store_user_config || $store_system_config)) {
    exit;
}

if ($fetype == 'Gtk2') {
    if (!$config->validConfiguration()) {
        PEAR::raiseError(
            "CRITICAL ERROR: no existing valid configuration files found in " .
            "files '$pear_user_config' or '$pear_system_config', " .
            "please copy an existing configuration file to one of these " .
            "locations, or use the -c and -s options to create one"
        );
    }
    Gtk::main();
} else {
    do {
        if ($command == 'help') {
            usage(null, isset($options[1][1]) ? $options[1][1] : null);
        }

        if (!$config->validConfiguration()) {
            PEAR::raiseError(
                "CRITICAL ERROR: no existing valid configuration files found " .
                "in files '$pear_user_config' or '$pear_system_config', " .
                "please copy an existing configuration file to one of " .
                "these locations, or use the -c and -s options to create one"
            );
        }

        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        $cmd = PEAR_Command::factory($command, $config);
        PEAR::popErrorHandling();
        if (PEAR::isError($cmd)) {
            usage(null, isset($options[1][0]) ? $options[1][0] : null);
        }

        $short_args = $long_args = null;
        PEAR_Command::getGetoptArgs($command, $short_args, $long_args);
        array_shift($options[1]);
        $tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args);

        if (PEAR::isError($tmp)) {
            break;
        }

        list($tmpopt, $params) = $tmp;
        $opts = array();
        foreach ($tmpopt as $foo => $tmp2) {
            list($opt, $value) = $tmp2;
            if ($value === null) {
                $value = true; // options without args
            }

            if (strlen($opt) == 1) {
                $cmdoptions = $cmd->getOptions($command);
                foreach ($cmdoptions as $o => $d) {
                    if (isset($d['shortopt']) && $d['shortopt'] == $opt) {
                        $opts[$o] = $value;
                    }
                }
            } else {
                if (substr($opt, 0, 2) == '--') {
                    $opts[substr($opt, 2)] = $value;
                }
            }
        }

        $ok = $cmd->run($command, $opts, $params);
        if ($ok === false) {
            PEAR::raiseError("unknown command `$command'");
        }

        if (PEAR::isError($ok)) {
            PEAR::setErrorHandling(
                PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")
            );
            PEAR::raiseError($ok);
        }
    } while (false);
}

// {{{ usage()

/**
 * Display usage information
 *
 * @param mixed $error       Optional error message
 * @param mixed $helpsubject Optional subject/command to display help for
 *
 * @return void
 */
function usage($error = null, $helpsubject = null)
{
    global $progname, $all_commands;
    $stdout = fopen('php://stdout', 'w');
    if (PEAR::isError($error)) {
        fputs($stdout, $error->getMessage() . "\n");
    } elseif ($error !== null) {
        fputs($stdout, "$error\n");
    }

    if ($helpsubject != null) {
        $put = cmdHelp($helpsubject);
    } else {
        $put = "Commands:\n";
        $maxlen = max(array_map("strlen", $all_commands));
        $formatstr = "%-{$maxlen}s  %s\n";
        ksort($all_commands);
        foreach ($all_commands as $cmd => $class) {
            $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd));
        }
        $put .=
            "Usage: $progname [options] command [command-options] <parameters>\n".
            "Type \"$progname help options\" to list all options.\n".
            "Type \"$progname help shortcuts\" to list all command shortcuts.\n".
            "Type \"$progname help version\" or ".
            "\"$progname version\" to list version information.\n".
            "Type \"$progname help <command>\" to get the help ".
            "for the specified command.";
    }
    fputs($stdout, "$put\n");
    fclose($stdout);

    if ($error === null) {
        exit(0);
    }
    exit(1);
}

/**
 * Return help string for specified command
 *
 * @param string $command Command to return help for
 *
 * @return void
 */
function cmdHelp($command)
{
    global $progname, $all_commands, $config;
    if ($command == "options") {
        return
        "Options:\n".
        "     -v         increase verbosity level (default 1)\n".
        "     -q         be quiet, decrease verbosity level\n".
        "     -c file    find user configuration in `file'\n".
        "     -C file    find system configuration in `file'\n".
        "     -d foo=bar set user config variable `foo' to `bar'\n".
        "     -D foo=bar set system config variable `foo' to `bar'\n".
        "     -G         start in graphical (Gtk) mode\n".
        "     -s         store user configuration\n".
        "     -S         store system configuration\n".
        "     -u foo     unset `foo' in the user configuration\n".
        "     -h, -?     display help/usage (this message)\n".
        "     -V         version information\n";
    } elseif ($command == "shortcuts") {
        $sc = PEAR_Command::getShortcuts();
        $ret = "Shortcuts:\n";
        foreach ($sc as $s => $c) {
            $ret .= sprintf("     %-8s %s\n", $s, $c);
        }
        return $ret;

    } elseif ($command == "version") {
        return "PEAR Version: ".$GLOBALS['pear_package_version'].
               "\nPHP Version: ".phpversion().
               "\nZend Engine Version: ".zend_version().
               "\nRunning on: ".php_uname();

    } elseif ($help = PEAR_Command::getHelp($command)) {
        if (is_string($help)) {
            return "$progname $command [options] $help\n";
        }

        if ($help[1] === null) {
            return "$progname $command $help[0]";
        }

        return "$progname $command [options] $help[0]\n$help[1]";
    }

    return "Command '$command' is not valid, try '$progname help'";
}

// }}}

/**
 * error_handler
 *
 * @param mixed $errno  Error number
 * @param mixed $errmsg Message
 * @param mixed $file   Filename
 * @param mixed $line   Line number
 *
 * @access public
 * @return boolean
 */
function error_handler($errno, $errmsg, $file, $line)
{
    if ((!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) && ($errno & E_STRICT)) {
        return; // E_STRICT
    }
    if ($errno & E_DEPRECATED) {
        return; // E_DEPRECATED
    }
    if (!(error_reporting() & $errno) &&
        isset($GLOBALS['config']) &&
        $GLOBALS['config']->get('verbose') < 4
    ) {
        return false; // @silenced error, show all if debug is high enough
    }
    $errortype = array (
        E_DEPRECATED  => 'Deprecated Warning',
        E_ERROR   =>  "Error",
        E_WARNING   =>  "Warning",
        E_PARSE   =>  "Parsing Error",
        E_NOTICE   =>  "Notice",
        E_CORE_ERROR  =>  "Core Error",
        E_CORE_WARNING  =>  "Core Warning",
        E_COMPILE_ERROR  =>  "Compile Error",
        E_COMPILE_WARNING =>  "Compile Warning",
        E_USER_ERROR =>  "User Error",
        E_USER_WARNING =>  "User Warning",
        E_USER_NOTICE =>  "User Notice"
    );
    if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) {
        $errortype[E_STRICT] = 'Strict Warning';
    }
    $prefix = $errortype[$errno];
    global $_PEAR_PHPDIR;
    if (stristr($file, $_PEAR_PHPDIR)) {
        $file = substr($file, strlen($_PEAR_PHPDIR) + 1);
    } else {
        $file = basename($file);
    }
    print "\n$prefix: $errmsg in $file on line $line\n";
    return false;
}


/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * indent-tabs-mode: nil
 * mode: php
 * End:
 */
// vim600:syn=php
PK��Z�0$�-- .pkgxml/Pear_File_MARC-1.4.1.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.10.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
 <name>File_MARC</name>
 <channel>pear.php.net</channel>
 <summary>Parse, modify, and create MARC records</summary>
 <description>The standard for machine-readable cataloging (MARC) records is documented at http://loc.gov/marc/. This package enables you to read existing MARC records from a file, string, or (using the YAZ extension), from a Z39.50 source. You can also use this package to create new MARC records.

This package is based on the PHP MARC package, originally called &quot;php-marc&quot;, that is part of the Emilda Project (http://www.emilda.org).  Christoffer Landtman generously agreed to make the &quot;php-marc&quot; code available under the GNU LGPL so it could be used as the basis of this PEAR package.</description>
 <lead>
  <name>Dan Scott</name>
  <user>dbs</user>
  <email>dbs@php.net</email>
  <active>yes</active>
 </lead>
 <date>2019-11-13</date>
 <time>17:33:33</time>
 <version>
  <release>1.4.1</release>
  <api>1.4.0</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license uri="http://www.gnu.org/copyleft/lesser.html">GNU Lesser General Public License</license>
 <notes>
1.4.1
  * Reintroduce include_path to composer.json
 </notes>
 <contents>
  <dir baseinstalldir="File" name="/">
   <file baseinstalldir="/" md5sum="ffe2590635f404af055fe731da105939" name="File/MARC/Lint/CodeData.php" role="php" />
   <file baseinstalldir="/" md5sum="a3b9e1c817e67f59add05593500d463e" name="File/MARC/Control_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="acba4463f8e40d6ee4e7ba1f2dc53123" name="File/MARC/Data_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="378f483ec1fd161cd9dfb9b05db58d66" name="File/MARC/Exception.php" role="php" />
   <file baseinstalldir="/" md5sum="a9ba69030cbf4847292b9975e9d922c6" name="File/MARC/Field.php" role="php" />
   <file baseinstalldir="/" md5sum="c37351c7c80927ce6bb1e662510f9183" name="File/MARC/Lint.php" role="php" />
   <file baseinstalldir="/" md5sum="c5ac39e3d25eb0108b9dd5ad8466c821" name="File/MARC/List.php" role="php" />
   <file baseinstalldir="/" md5sum="7af6ce78cde4bb246e4e96709e90d2c0" name="File/MARC/Record.php" role="php" />
   <file baseinstalldir="/" md5sum="df5f97139685f0ad04e47fdbb67e3968" name="File/MARC/Subfield.php" role="php" />
   <file baseinstalldir="/" md5sum="6e102262dfd5d65d8d5a6221dfc74edd" name="File/MARC.php" role="php" />
   <file baseinstalldir="/" md5sum="8b64040d2d18ac4b994595a148266a66" name="File/MARCBASE.php" role="php" />
   <file baseinstalldir="/" md5sum="f5a17a60d34e84e2ee7ca1e5c5c6c620" name="File/MARCXML.php" role="php" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="examples/example.mrc" role="doc" />
   <file baseinstalldir="File" md5sum="1aea40df9f1c2e32f8e065fe8da0a3b5" name="examples/marc_yaz.php" role="doc" />
   <file baseinstalldir="File" md5sum="70ae317e0890d5896e3ffccdd293369a" name="examples/read.php" role="doc" />
   <file baseinstalldir="File" md5sum="54efb9d920ac775bfc847a83a2dec73a" name="examples/subfields.php" role="doc" />
   <file baseinstalldir="File" md5sum="14297da35b510c496cd1f328cf3bb301" name="tests/bad_example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="0dd4c6dbad6e8608d0ebf9d24425955d" name="tests/bad_example.xml" role="test" />
   <file baseinstalldir="File" md5sum="216a6f9d53f6d3d8e22d81fdc10f4bc1" name="tests/camel.mrc" role="test" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="tests/example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="9455aec3371f79cf7d31281fd03f5171" name="tests/marc_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="577e2f5f89fd48cf1a3576a29d2958f8" name="tests/marc_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a6a586354b9a06c880c2a7470dd828d7" name="tests/marc_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1c7e2fc5572a0f9362a771c260a1fe3" name="tests/marc_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="84f85ac7f8a2532e4e90ccde7764556a" name="tests/marc_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="889e5e906a97de7a0e94b0c5f30e70e7" name="tests/marc_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="be823dc8a8efb408de06371ab802efcc" name="tests/marc_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="af44490aafea44e5120f881cb81cdad9" name="tests/marc_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ac9f2a7aeb24900a11f5102744179ae3" name="tests/marc_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5e43eb5cddbb4f2bd0d6405cd95b80aa" name="tests/marc_010.phpt" role="test" />
   <file baseinstalldir="File" md5sum="2e1cd8509c0bf04ec77fc0f51375f611" name="tests/marc_011.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bc49ca48623102c8ac07679fa77a3dd9" name="tests/marc_012.phpt" role="test" />
   <file baseinstalldir="File" md5sum="245a3b20e0da1973535503e28efd1d3a" name="tests/marc_013.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ce69aa734856dd40d60d30c77bdef53a" name="tests/marc_014.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7b61cdd31035e60682fa92c5d519d997" name="tests/marc_015.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7f4f597fe1adaa3507eb87fc4875dbd2" name="tests/marc_016.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4262efd5fcacbd7503323681f4552430" name="tests/marc_017.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ee1623d7bda54ba4f741b2319b158f82" name="tests/marc_018.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8006c03fbab0f04377342086fafd3982" name="tests/marc_019.phpt" role="test" />
   <file baseinstalldir="File" md5sum="f5ae5b25e0ac1104314433d9e5b1f7fe" name="tests/marc_020.phpt" role="test" />
   <file baseinstalldir="File" md5sum="94d8f99e86585671a1b2d3043aeb6360" name="tests/marc_021.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bb891a890effe0e77e1759043f4846d8" name="tests/marc_022.phpt" role="test" />
   <file baseinstalldir="File" md5sum="faf77dcb5cdd002c09169a14bfded65e" name="tests/marc_023.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0e6c4a23f5da7df64fdd4b3b1149bbee" name="tests/marc_16783.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4ea8b3520beda378db15960f1c50493a" name="tests/marc_field_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="743850ef61df69c4340be44a03bccb5a" name="tests/marc_field_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8c765f1398b49df257d86d22ac6e4f8d" name="tests/marc_field_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d4216cf930a308e0d02553bd3914f294" name="tests/marc_field_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dd59514b474b78371ad522a3e13b76b7" name="tests/marc_field_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5295bfd02a8424acac1c91de26b552c7" name="tests/marc_field_21246.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6f95f09442ccf6b93df92986f58b270d" name="tests/marc_lint_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="18d721f8871edd925624ccbdd15444fb" name="tests/marc_lint_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4eb86a2f4e0a74dedcb0bf2511da6ca1" name="tests/marc_lint_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="10430fee0a1352d0528f1507b34c57e1" name="tests/marc_lint_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0dcd07a18577d7b22392a2214cd6436c" name="tests/marc_lint_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fd17798fc535562e5e64461f449516b2" name="tests/marc_record_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="141b455ccf67a60c4eac44c77960f2e2" name="tests/marc_subfield_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1e23464ee0eec47ddca2af9a9922926" name="tests/marc_subfield_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="1d7903e8c244d647220b318b4bc758d1" name="tests/marc_xml_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="22cae3c752d843b78f583dcd92801534" name="tests/marc_xml_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="c0716d23e0f960abf8d53ad6014a413a" name="tests/marc_xml_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7645fa19e28aca041a124fc5e2c12bd3" name="tests/marc_xml_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b08b28c3251625b8b6e4d7ab376b0185" name="tests/marc_xml_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6cd0934ddbf65d2d7e9ea5d108977ff7" name="tests/marc_xml_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ffdce4aa190268fa7cbbf3bb45383abf" name="tests/marc_xml_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="998a4c1ce00ff100f39ffa9fc49a212f" name="tests/marc_xml_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a38a67c590869f2b0a4859a910fd9e89" name="tests/marc_xml_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="db39c5055a570fcda12bb7c5fa1e3b4d" name="tests/marc_xml_16642.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dc075f4a271bd7182378a3874bd5b39e" name="tests/marc_xml_namespace.phpt" role="test" />
   <file baseinstalldir="File" md5sum="208200d9a979ac360c4d326e9789b6b7" name="tests/marc_xml_namespace_prefix.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d87774ede82222cfc12b2c2a06f57a3a" name="tests/marc_xml_rsinger.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fb44e3eb69f1a37115235fc829c39542" name="tests/namespace.xml" role="test" />
   <file baseinstalldir="File" md5sum="e6de4d809b0af5dd99fd352eb60616a1" name="tests/skipif.inc" role="test" />
   <file baseinstalldir="File" md5sum="a0166a4ff0bc0bb283e854f11beaa793" name="tests/music.mrc" role="test" />
   <file baseinstalldir="File" md5sum="993ce494befbc25dc1326527b30b4782" name="tests/music.xml" role="test" />
   <file baseinstalldir="File" md5sum="6b0c87f0cd459ed7322c25d403b164cc" name="tests/bigarchive.xml" role="test" />
   <file baseinstalldir="File" md5sum="be850aa6ab4ac52b8c6c214c30b574af" name="tests/onerecord.xml" role="test" />
   <file baseinstalldir="File" md5sum="4f43fec7b276267eec5258044853ccc8" name="tests/sandburg.mrc" role="test" />
   <file baseinstalldir="File" md5sum="e216b95f905dd240c9bde372950e4073" name="tests/sandburg.xml" role="test" />
   <file baseinstalldir="File" md5sum="e81a92188ea0dcd9c108a63fb32b3f4f" name="tests/xmlescape.mrc" role="test" />
   <file baseinstalldir="File" md5sum="8f9f63ed6a80191d89a2296fa4c1a30b" name="CHANGELOG" role="doc" />
   <file baseinstalldir="File" md5sum="fbc093901857fcd118f065f900982c24" name="LICENSE" role="doc" />
  </dir>
 </contents>
 <dependencies>
  <required>
   <php>
    <min>5.6</min>
   </php>
   <pearinstaller>
    <min>1.4.0</min>
   </pearinstaller>
  </required>
  <optional>
   <package>
    <name>Validate_ISPN</name>
    <channel>pear.php.net</channel>
   </package>
  </optional>
 </dependencies>
 <phprelease />
</package>
PKm�ZPi��.depdbnu�[���PKm�Z�{��
�Mail/null.phpnu�[���PKm�ZE@�%>>
Mail/sendmail.phpnu�[���PKm�Z��A~�{�{�;Mail/RFC822.phpnu�[���PKn�Z�+V����
[�Mail/mime.phpnu�[���PKn�Zx�ع���D�Mail/mimeDecode.phpnu�[���PKn�ZB�_Ǭ=�=
@(Mail/smtp.phpnu�[���PKn�ZwԐE;E;)fMail/smtpmx.phpnu�[���PKn�Z�؛�J�J���Mail/mimePart.phpnu�[���PKn�ZB��shh
8YMail/mock.phpnu�[���PKn�Z@iE�\\
�lMail/mail.phpnu�[���PKn�Zv�.locknu�[���PKn�Z�*�z%-%- ��Structures/LinkedList/Double.phpnu�[���PKn�Z����p:p:  �Structures/LinkedList/Single.phpnu�[���PKn�ZUyv���Structures/Graph.phpnu�[���PKn�Z�C� + +CStructures/Graph/Node.phpnu�[���PKn�Z9����,�1Structures/Graph/Manipulator/AcyclicTest.phpnu�[���PKn�Z~(�htt2�HStructures/Graph/Manipulator/TopologicalSorter.phpnu�[���PKn�Z�J�}
}
_dAuth/SASL/Anonymous.phpnu�[���PKn�ZP(~�T
T
#rAuth/SASL/CramMD5.phpnu�[���PKn�Z����==�Auth/SASL/Plain.phpnu�[���PKn�Z�<� OO<�Auth/SASL/Login.phpnu�[���PKn�Z%ׅtg!g!ΘAuth/SASL/DigestMD5.phpnu�[���PKn�Z�T�|�Auth/SASL/Common.phpnu�[���PKn�ZvR�r,,��Auth/SASL/External.phpnu�[���PKn�Zќ��0�0H�Auth/SASL/SCRAM.phpnu�[���PKn�Z2r����
�	Auth/SASL.phpnu�[���PKn�Z�T�,�,�OS/Guess.phpnu�[���PKn�Z�����KPEAR/Config.phpnu�[���PKn�Z�`�eEAEA
.ZPEAR/REST.phpnu�[���PKn�Z��ym6m6��PEAR/Exception.phpnu�[���PKn�Zr"����_�PEAR/ChannelFile.phpnu�[���PKn�Z��gk�U�U?�PEAR/Validate.phpnu�[���PKn�Zd֣S��u�PEAR/Command/Pickle.xmlnu�[���PKn�Z�z��k<k<W�PEAR/Command/Config.phpnu�[���PKn�Z݄<ii	1PEAR/Command/Mirror.xmlnu�[���PKn�Z,��t"u"u�3PEAR/Command/Remote.phpnu�[���PKn�Z
�\���"�PEAR/Command/Remote.xmlnu�[���PKn�Zj���!�!X�PEAR/Command/Install.xmlnu�[���PKo�Z�%q������PEAR/Command/Channels.phpnu�[���PKo�Znmi?;�;��[	PEAR/Command/Install.phpnu�[���PKo�Z�X�

#
PEAR/Command/Auth.phpnu�[���PKo�Z���s6
6
T-
PEAR/Command/Config.xmlnu�[���PKo�Z�%Fii�:
PEAR/Command/Test.xmlnu�[���PKo�ZZ h66A
PEAR/Command/Package.xmlnu�[���PKo�Z�w��zz�]
PEAR/Command/Channels.xmlnu�[���PKo�Z+9ҜҜ�n
PEAR/Command/Package.phpnu�[���PKo�Z
u����PEAR/Command/Build.xmlnu�[���PKo�Z������
PEAR/Command/Mirror.phpnu�[���PKp�Z,_�h/h/�PEAR/Command/Test.phpnu�[���PKp�Z�%sp  6OPEAR/Command/Common.phpnu�[���PKp�Z0(;rʹʹ�oPEAR/Command/Registry.phpnu�[���PKp�Z�4�{���$PEAR/Command/Auth.xmlnu�[���PKp�Z��#S
S
�)PEAR/Command/Build.phpnu�[���PKp�Z���u��S4PEAR/Command/Registry.xmlnu�[���PKp�Z�P>>�;PEAR/Command/Pickle.phpnu�[���PKp�Z��T�I�I�yPEAR/Builder.phpnu�[���PKp�Z[
�W��3�PEAR/XMLParser.phpnu�[���PKp�Zl(e���t�PEAR/Downloader.phpnu�[���PKp�Z�b������
PEAR/ErrorStack.phpnu�[���PKp�Z(Pz����ePEAR/Proxy.phpnu�[���PKp�Z��'����|PEAR/RunTest.phpnu�[���PKq�Zj�y99�	PEAR/Validator/PECL.phpnu�[���PKq�Zp�����aPEAR/Dependency2.phpnu�[���PKq�Z��wv@@��PEAR/PackageFile/v2.phpnu�[���PKq�ZC�8�L�L!:�PEAR/PackageFile/v2/Validator.phpnu�[���PKq�Z���=_�_�6PEAR/PackageFile/v2/rw.phpnu�[���PKq�Z�5�������,PEAR/PackageFile/v1.phpnu�[���PKq�Z�ɁɁ!��PEAR/PackageFile/Generator/v2.phpnu�[���PKq�Z`�=����!�tPEAR/PackageFile/Generator/v1.phpnu�[���PKr�Z��OWHH�9PEAR/PackageFile/Parser/v2.phpnu�[���PKr�Z�_=�@�@`FPEAR/PackageFile/Parser/v1.phpnu�[���PKr�Zc��__5�PEAR/DependencyDB.phpnu�[���PKr�Z�@P��{�PEAR/ChannelFile/Parser.phpnu�[���PKr�Z��_�0�0r�PEAR/Command.phpnu�[���PKr�Z�ٲ�=�==PEAR/PackageFile.phpnu�[���PKr�Z�JD��g\PEAR/Task/Replace.phpnu�[���PKr�Z&%75))�wPEAR/Task/Windowseol/rw.phpnu�[���PKr�Z�3}}PEAR/Task/Replace/rw.phpnu�[���PKr�Z&
i."x�PEAR/Task/Postinstallscript/rw.phpnu�[���PKr�Z�-!�PEAR/Task/Common.phpnu�[���PKr�ZD$���I�PEAR/Task/Windowseol.phpnu�[���PKr�ZZ�E�x9x9��PEAR/Task/Postinstallscript.phpnu�[���PKr�Z\k��K�PEAR/Task/Unixeol/rw.phpnu�[���PKr�Z�������PEAR/Task/Unixeol.phpnu�[���PKr�Z�W�f���PEAR/REST/10.phpnu�[���PKr�Z��Y�;;ąPEAR/REST/13.phpnu�[���PKr�Z,#y��+�+�PEAR/REST/11.phpnu�[���PKr�Z��U  D�PEAR/Packager.phpnu�[���PKr�ZZ�bgbg�PEAR/Common.phpnu�[���PKr�Z$���(�(FsPEAR/Registry.phpnu�[���PKr�Z��	MdMd?�PEAR/Frontend/CLI.phpnu�[���PKr�Z��

�PEAR/Installer/Role/Doc.phpnu�[���PKr�Z��/��)PEAR/Installer/Role/Cfg.xmlnu�[���PKr�Z>1H���PEAR/Installer/Role/Www.xmlnu�[���PKr�Z�?m

PEAR/Installer/Role/Php.phpnu�[���PKr�Z*Y|	%%`PEAR/Installer/Role/Man.phpnu�[���PKr�Z���BB�PEAR/Installer/Role/Ext.xmlnu�[���PKr�Zp��""]PEAR/Installer/Role/Src.xmlnu�[���PKr�Zh&P*���PEAR/Installer/Role/Doc.xmlnu�[���PKr�ZB] ���PEAR/Installer/Role/Test.xmlnu�[���PKr�Zz�q����PEAR/Installer/Role/Php.xmlnu�[���PKr�Z	��
|PEAR/Installer/Role/Data.phpnu�[���PKs�Z�0�c���PEAR/Installer/Role/Man.xmlnu�[���PKs�Z��K

�PEAR/Installer/Role/Ext.phpnu�[���PKs�ZY��� PEAR/Installer/Role/Test.phpnu�[���PKs�Z@v�а�z#PEAR/Installer/Role/Script.xmlnu�[���PKs�Zf�sz��x%PEAR/Installer/Role/Data.xmlnu�[���PKs�Z?���GGV'PEAR/Installer/Role/Common.phpnu�[���PKs�Z�^D{		�?PEAR/Installer/Role/Www.phpnu�[���PKs�Z�Ƥ?CPEAR/Installer/Role/Cfg.phpnu�[���PKs�Z��[�	SPEAR/Installer/Role/Script.phpnu�[���PKs�Z��srrjVPEAR/Installer/Role/Src.phpnu�[���PKs�ZV�Z���'ZPEAR/Installer/Role.phpnu�[���PKs�Z�{�	�)�)*yPEAR/Downloader/Package.phpnu�[���PKs�Z.�4���$�PEAR/Frontend.phpnu�[���PKs�Z،�w��_�PEAR/Installer.phpnu�[���PKs�ZXxo��-j�Symfony/Bridge/Doctrine/Logger/DbalLogger.phpnu�[���PKs�Ze�OO&b�Symfony/Bridge/Doctrine/autoloader.phpnu�[���PKs�Z��X+��8�Symfony/Bridge/Doctrine/CacheWarmer/ProxyCacheWarmer.phpnu�[���PKs�Z	�9,��5i�Symfony/Bridge/Doctrine/Form/DoctrineOrmExtension.phpnu�[���PKs�Z�0���NX�Symfony/Bridge/Doctrine/Form/EventListener/MergeDoctrineCollectionListener.phpnu�[���PKs�Z!%d==A��Symfony/Bridge/Doctrine/Form/ChoiceList/EntityLoaderInterface.phpnu�[���PKs�Z�	?x�7�7<4�Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.phpnu�[���PKs�ZGC�t��A<-Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.phpnu�[���PKs�Z`.
qpp7�9Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.phpnu�[���PKs�ZCi�PPMZQSymfony/Bridge/Doctrine/Form/DataTransformer/CollectionToArrayTransformer.phpnu�[���PKs�Z憝��0'YSymfony/Bridge/Doctrine/Form/Type/EntityType.phpnu�[���PKs�ZS;,:��2-]Symfony/Bridge/Doctrine/Form/Type/DoctrineType.phpnu�[���PKs�ZW&v��<�wSymfony/Bridge/Doctrine/Security/User/EntityUserProvider.phpnu�[���PKs�Z�����Et�Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.phpnu�[���PKs�Z(��y��9�Symfony/Bridge/Doctrine/Validator/DoctrineInitializer.phpnu�[���PKs�ZQГ��>�Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.phpnu�[���PKs�Z:�d�G5�Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.phpnu�[���PKs�Z�Ta�==B��Symfony/Bridge/Doctrine/ExpressionLanguage/DoctrineParserCache.phpnu�[���PKs�Z��qm
m
-m�Symfony/Bridge/Doctrine/RegistryInterface.phpnu�[���PKs�Zlf/�qq=7�Symfony/Bridge/Doctrine/DataFixtures/ContainerAwareLoader.phpnu�[���PKs�Z����=�Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.phpnu�[���PKs�Z�����C��Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerSchema.phpnu�[���PKs�ZOlQ�996��Symfony/Bridge/Doctrine/ContainerAwareEventManager.phpnu�[���PKs�Z؈����3D�Symfony/Bridge/Doctrine/Test/DoctrineTestHelper.phpnu�[���PKs�Z̳֨�+��Symfony/Bridge/Doctrine/ManagerRegistry.phpnu�[���PKs�Z+çxAA?�Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.phpnu�[���PKs�Z*�+��J�JIBSymfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.phpnu�[���PKs�Z���*��SVaSymfony/Bridge/Doctrine/DependencyInjection/Security/UserProvider/EntityFactory.phpnu�[���PKs�Z��㛕�Q�hSymfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterMappingsPass.phpnu�[���PKs�Z~�YAAeԀSymfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.phpnu�[���PKs�Z��,���S��Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/DoctrineValidationPass.phpnu�[���PKs�Z��4NN%,�Symfony/Bridge/Monolog/autoloader.phpnu�[���PKs�Z��մ��1ϡSymfony/Bridge/Monolog/Handler/FirePHPHandler.phpnu�[���PKs�Z��Zv��/©Symfony/Bridge/Monolog/Handler/DebugHandler.phpnu�[���PKs�Z�y���1دSymfony/Bridge/Monolog/Handler/ConsoleHandler.phpnu�[���PKs�Z��*vv5�Symfony/Bridge/Monolog/Handler/SwiftMailerHandler.phpnu�[���PKs�Z���"II3��Symfony/Bridge/Monolog/Handler/ChromePhpHandler.phpnu�[���PKs�Z��;��	�	!��Symfony/Bridge/Monolog/Logger.phpnu�[���PKs�Z��b115��Symfony/Bridge/Monolog/Formatter/ConsoleFormatter.phpnu�[���PKt�Z�,��1l�Symfony/Bridge/Monolog/Processor/WebProcessor.phpnu�[���PKt�Z�$�KK"l�Symfony/Bridge/Twig/autoloader.phpnu�[���PKt�Z�)�UU1	�Symfony/Bridge/Twig/Translation/TwigExtractor.phpnu�[���PKt�Z6DZ77*��Symfony/Bridge/Twig/Node/StopwatchNode.phpnu�[���PKt�Z,
�@��5P�Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.phpnu�[���PKt�Z�
�s>>*ESymfony/Bridge/Twig/Node/FormThemeNode.phpnu�[���PKt�ZP�IAA3�Symfony/Bridge/Twig/Node/TransDefaultDomainNode.phpnu�[���PKt�Z�U,tt,�Symfony/Bridge/Twig/Node/FormEnctypeNode.phpnu�[���PKt�Zʦ\�G
G
&QSymfony/Bridge/Twig/Node/TransNode.phpnu�[���PKt�Z���^��,�%Symfony/Bridge/Twig/Node/RenderBlockNode.phpnu�[���PKt�Z�vq�)+Symfony/Bridge/Twig/Form/TwigRenderer.phpnu�[���PKt�Zb�3�}}8q1Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.phpnu�[���PKt�Z��Qkk2V4Symfony/Bridge/Twig/Form/TwigRendererInterface.phpnu�[���PKt�Z��<��/#7Symfony/Bridge/Twig/Form/TwigRendererEngine.phpnu�[���PKt�Z�GTSymfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.phpnu�[���PKt�Z�)�[n	n	)�`Symfony/Bridge/Twig/NodeVisitor/Scope.phpnu�[���PKt�Z�tA�:`jSymfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.phpnu�[���PKt�Z��9292B�xSymfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twignu�[���PKt�Z��[[Dy�Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twignu�[���PKt�Z.��8H�Symfony/Bridge/Twig/TokenParser/StopwatchTokenParser.phpnu�[���PKt�Z�%]�
�
4��Symfony/Bridge/Twig/TokenParser/TransTokenParser.phpnu�[���PKt�Z�/�	�	:��Symfony/Bridge/Twig/TokenParser/TransChoiceTokenParser.phpnu�[���PKt�Z>����8>�Symfony/Bridge/Twig/TokenParser/FormThemeTokenParser.phpnu�[���PKt�Zʶ�̭�Ao�Symfony/Bridge/Twig/TokenParser/TransDefaultDomainTokenParser.phpnu�[���PKt�Z�9�=KK/��Symfony/Bridge/Twig/Extension/FormExtension.phpnu�[���PKt�Z��|/7�Symfony/Bridge/Twig/Extension/YamlExtension.phpnu�[���PKt�Z��&�a
a
5��Symfony/Bridge/Twig/Extension/HttpKernelExtension.phpnu�[���PKt�ZKΙ���5v�Symfony/Bridge/Twig/Extension/ExpressionExtension.phpnu�[���PKt�Z`�fS..2� Symfony/Bridge/Twig/Extension/RoutingExtension.phpnu�[���PKt�Z�5��mm4] Symfony/Bridge/Twig/Extension/StopwatchExtension.phpnu�[���PKt�Z�?���6. Symfony/Bridge/Twig/Extension/TranslationExtension.phpnu�[���PKt�Zd���oo3�! Symfony/Bridge/Twig/Extension/SecurityExtension.phpnu�[���PKt�Z�����/a' Symfony/Bridge/Twig/Extension/CodeExtension.phpnu�[���PKu�Z^D��dd"sG Symfony/Bridge/Twig/TwigEngine.phpnu�[���PKu�Z�4˵��()V Symfony/Component/Finder/Shell/Shell.phpnu�[���PKu�Z5��K��*^ Symfony/Component/Finder/Shell/Command.phpnu�[���PKu�Z�5�9(�v Symfony/Component/Finder/SplFileInfo.phpnu�[���PKu�Z%uM�PP'X~ Symfony/Component/Finder/autoloader.phpnu�[���PKu�Z��99C� Symfony/Component/Finder/Exception/ShellCommandFailureException.phpnu�[���PKu�Z�7��9�� Symfony/Component/Finder/Exception/ExceptionInterface.phpnu�[���PKu�Z�cWޫ�<� Symfony/Component/Finder/Exception/AccessDeniedException.phpnu�[���PKu�Z>�@��>� Symfony/Component/Finder/Exception/AdapterFailureException.phpnu�[���PKu�ZP�����D	� Symfony/Component/Finder/Exception/OperationNotPermitedException.phpnu�[���PKu�Z��� ��6� Symfony/Component/Finder/Comparator/DateComparator.phpnu�[���PKu�Z|F�z

2?� Symfony/Component/Finder/Comparator/Comparator.phpnu�[���PKu�Z�P�

8�� Symfony/Component/Finder/Comparator/NumberComparator.phpnu�[���PKu�Z�g@Mbb!2� Symfony/Component/Finder/Glob.phpnu�[���PKu�Z�d�V�V#� Symfony/Component/Finder/Finder.phpnu�[���PKu�Zils_��>
!Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.phpnu�[���PKu�Z��ɔ�
�
7u!Symfony/Component/Finder/Iterator/FilePathsIterator.phpnu�[���PKu�Z�,G��4n!Symfony/Component/Finder/Iterator/FilterIterator.phpnu�[���PKu�Z�ʽ���?q#!Symfony/Component/Finder/Iterator/FilecontentFilterIterator.phpnu�[���PKu�Z�

���@~+!Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.phpnu�[���PKu�Z��z":�2!Symfony/Component/Finder/Iterator/CustomFilterIterator.phpnu�[���PKu�Z{�^ǽ�<N9!Symfony/Component/Finder/Iterator/FilenameFilterIterator.phpnu�[���PKu�Z�d����Dw@!Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.phpnu�[���PKu�Zx�P���=�F!Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.phpnu�[���PKu�Z ��U��=�L!Symfony/Component/Finder/Iterator/DateRangeFilterIterator.phpnu�[���PKu�Z�n bb<�R!Symfony/Component/Finder/Iterator/FileTypeFilterIterator.phpnu�[���PKu�Z��j��	�	6�X!Symfony/Component/Finder/Iterator/SortableIterator.phpnu�[���PKu�Z���)��8�b!Symfony/Component/Finder/Iterator/PathFilterIterator.phpnu�[���PKu�Z�6s��@�j!Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.phpnu�[���PKu�Z��&
&
2Gw!Symfony/Component/Finder/Expression/Expression.phpnu�[���PKu�Z�"HH6ρ!Symfony/Component/Finder/Expression/ValueInterface.phpnu�[���PKu�Z�E�,}�!Symfony/Component/Finder/Expression/Glob.phpnu�[���PKu�Z��(�-�!Symfony/Component/Finder/Expression/Regex.phpnu�[���PKu�Z9!�2{
{
/D�!Symfony/Component/Finder/Adapter/PhpAdapter.phpnu�[���PKu�Z����5�!Symfony/Component/Finder/Adapter/AdapterInterface.phpnu�[���PKu�Z��kA�
�
34�!Symfony/Component/Finder/Adapter/BsdFindAdapter.phpnu�[���PKu�Z�}]�
�
3��!Symfony/Component/Finder/Adapter/GnuFindAdapter.phpnu�[���PKu�ZQJ)�)8��!Symfony/Component/Finder/Adapter/AbstractFindAdapter.phpnu�[���PKu�Z�	4�"Symfony/Component/Finder/Adapter/AbstractAdapter.phpnu�[���PKu�Z����:;"Symfony/Component/Translation/Extractor/ChainExtractor.phpnu�[���PKu�ZArP�>%"Symfony/Component/Translation/Extractor/ExtractorInterface.phpnu�[���PKu�Zb*0�oo4�#"Symfony/Component/Translation/PluralizationRules.phpnu�[���PKu�Z�q��UU,<"Symfony/Component/Translation/autoloader.phpnu�[���PKu�Z�<qNN10>"Symfony/Component/Translation/MessageSelector.phpnu�[���PKu�Z�س��:�J"Symfony/Component/Translation/Catalogue/MergeOperation.phpnu�[���PKu�ZY[�>*P"Symfony/Component/Translation/Catalogue/OperationInterface.phpnu�[���PKu�Z��fb�
�
=�U"Symfony/Component/Translation/Catalogue/AbstractOperation.phpnu�[���PKu�Z��ӄ�9�c"Symfony/Component/Translation/Catalogue/DiffOperation.phpnu�[���PKu�Z�6�"��>�i"Symfony/Component/Translation/Exception/ExceptionInterface.phpnu�[���PKu�ZDŽ���D�k"Symfony/Component/Translation/Exception/InvalidResourceException.phpnu�[���PKv�Z�2B��E2n"Symfony/Component/Translation/Exception/NotFoundResourceException.phpnu�[���PKv�Z�y4��2�p"Symfony/Component/Translation/MessageCatalogue.phpnu�[���PKv�Z%�Mt8��"Symfony/Component/Translation/MetadataAwareInterface.phpnu�[���PKv�Z�d�<<4��"Symfony/Component/Translation/IdentityTranslator.phpnu�[���PKv�Z�e�G��,��"Symfony/Component/Translation/Translator.phpnu�[���PKv�Z��֛�;u�"Symfony/Component/Translation/MessageCatalogueInterface.phpnu�[���PKv�ZM�
���9{�"Symfony/Component/Translation/Dumper/IcuResFileDumper.phpnu�[���PKv�Zਪ(5u�"Symfony/Component/Translation/Dumper/PoFileDumper.phpnu�[���PKv�Z���%LL6��"Symfony/Component/Translation/Dumper/PhpFileDumper.phpnu�[���PKv�Z�<̧��8��"Symfony/Component/Translation/Dumper/XliffFileDumper.phpnu�[���PKv�Z>{GG5��"Symfony/Component/Translation/Dumper/QtFileDumper.phpnu�[���PKv�Z���667Z�"Symfony/Component/Translation/Dumper/YamlFileDumper.phpnu�[���PKv�ZoB���6��"Symfony/Component/Translation/Dumper/CsvFileDumper.phpnu�[���PKv�ZB^�[[3*�"Symfony/Component/Translation/Dumper/FileDumper.phpnu�[���PKv�Z�:$}}7�"Symfony/Component/Translation/Dumper/JsonFileDumper.phpnu�[���PKv�Z&X����6�#Symfony/Component/Translation/Dumper/IniFileDumper.phpnu�[���PKv�Z��<**8
#Symfony/Component/Translation/Dumper/DumperInterface.phpnu�[���PKv�Z����A	A	5�#Symfony/Component/Translation/Dumper/MoFileDumper.phpnu�[���PKv�Zg�?Z�
�
*B#Symfony/Component/Translation/Interval.phpnu�[���PKv�Z�3����5�#Symfony/Component/Translation/TranslatorInterface.phpnu�[���PKv�ZP�?�}}:�%#Symfony/Component/Translation/Writer/TranslationWriter.phpnu�[���PKv�ZN@���6�-#Symfony/Component/Translation/Loader/IniFileLoader.phpnu�[���PKv�Z�T�93#Symfony/Component/Translation/Loader/IcuDatFileLoader.phpnu�[���PKv�ZCS�z
z
9�9#Symfony/Component/Translation/Loader/IcuResFileLoader.phpnu�[���PKv�Z��v���5�D#Symfony/Component/Translation/Loader/MoFileLoader.phpnu�[���PKv�ZR����4&\#Symfony/Component/Translation/Loader/ArrayLoader.phpnu�[���PKv�Z�'s�u	u	7&d#Symfony/Component/Translation/Loader/JsonFileLoader.phpnu�[���PKv�Z�i�3"
"
6n#Symfony/Component/Translation/Loader/CsvFileLoader.phpnu�[���PKv�Z_��BB8�x#Symfony/Component/Translation/Loader/XliffFileLoader.phpnu�[���PKv�Zl#�tt84�#Symfony/Component/Translation/Loader/LoaderInterface.phpnu�[���PKv�Z�*���5�#Symfony/Component/Translation/Loader/PoFileLoader.phpnu�[���PKv�Z�r��;;6o�#Symfony/Component/Translation/Loader/PhpFileLoader.phpnu�[���PKv�Z:�	Z�"�"B�#Symfony/Component/Translation/Loader/schema/dic/xliff-core/xml.xsdnu�[���PKv�Z�xO��T�#Symfony/Component/Translation/Loader/schema/dic/xliff-core/xliff-core-1.2-strict.xsdnu�[���PKv�Z)-d+�	�	5�g%Symfony/Component/Translation/Loader/QtFileLoader.phpnu�[���PKv�Z:����7�q%Symfony/Component/Translation/Loader/YamlFileLoader.phpnu�[���PKw�Z�V�˽�.-z%Symfony/Component/Routing/Annotation/Route.phpnu�[���PKw�Z�<ѹ�+H�%Symfony/Component/Routing/CompiledRoute.phpnu�[���PKw�ZU8���-\�%Symfony/Component/Routing/RouterInterface.phpnu�[���PKw�ZU�cQQ(>�%Symfony/Component/Routing/autoloader.phpnu�[���PKw�Z����'�'+�%Symfony/Component/Routing/RouteCompiler.phpnu�[���PKw�Z��%�%$�%Symfony/Component/Routing/Router.phpnu�[���PKw�Z���q
q
6n�%Symfony/Component/Routing/Matcher/ApacheUrlMatcher.phpnu�[���PKw�Z	�ڗ9E�%Symfony/Component/Routing/Matcher/UrlMatcherInterface.phpnu�[���PKw�Z`�u���=��%Symfony/Component/Routing/Matcher/RequestMatcherInterface.phpnu�[���PKw�Z[z�dd<�&Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.phpnu�[���PKw�Z?�|{��:�&Symfony/Component/Routing/Matcher/Dumper/MatcherDumper.phpnu�[���PKw�Z�x}�44=�&Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.phpnu�[���PKw�Z�bz#z#@A&Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.phpnu�[���PKw�Z�`=e&Symfony/Component/Routing/Matcher/Dumper/DumperCollection.phpnu�[���PKw�Z�N�
�
C�s&Symfony/Component/Routing/Matcher/Dumper/DumperPrefixCollection.phpnu�[���PKw�Z(� ���C�~&Symfony/Component/Routing/Matcher/Dumper/MatcherDumperInterface.phpnu�[���PKw�ZY�IWW8��&Symfony/Component/Routing/Matcher/Dumper/DumperRoute.phpnu�[���PKw�Z�'��9��&Symfony/Component/Routing/Matcher/TraceableUrlMatcher.phpnu�[���PKw�ZGj�C""0��&Symfony/Component/Routing/Matcher/UrlMatcher.phpnu�[���PKw�Z� ��ffE'�&Symfony/Component/Routing/Matcher/RedirectableUrlMatcherInterface.phpnu�[���PKw�Z����==K�&Symfony/Component/Routing/Exception/MissingMandatoryParametersException.phpnu�[���PKw�Zj`j�A��&Symfony/Component/Routing/Exception/InvalidParameterException.phpnu�[���PKw�Znj�W��>/�&Symfony/Component/Routing/Exception/RouteNotFoundException.phpnu�[���PKw�Z��)���:��&Symfony/Component/Routing/Exception/ExceptionInterface.phpnu�[���PKw�Z����JJA��&Symfony/Component/Routing/Exception/MethodNotAllowedException.phpnu�[���PKw�Z?�]�//Af�&Symfony/Component/Routing/Exception/ResourceNotFoundException.phpnu�[���PKw�Z��^�==#�&Symfony/Component/Routing/Route.phpnu�[���PKw�Zr�����:i	'Symfony/Component/Routing/RequestContextAwareInterface.phpnu�[���PKw�Z|,{Ȫ�-p'Symfony/Component/Routing/RouteCollection.phpnu�[���PKw�Z�h�,w)'Symfony/Component/Routing/RequestContext.phpnu�[���PKw�Zմ���I�C'Symfony/Component/Routing/Generator/ConfigurableRequirementsInterface.phpnu�[���PKw�Z�
��1�148M'Symfony/Component/Routing/Generator/UrlGenerator.phpnu�[���PKw�Z�1O�
�
Az'Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.phpnu�[���PKw�Zu�'��>��'Symfony/Component/Routing/Generator/Dumper/GeneratorDumper.phpnu�[���PKw�Z�4��G��'Symfony/Component/Routing/Generator/Dumper/GeneratorDumperInterface.phpnu�[���PKw�Z����@@=�'Symfony/Component/Routing/Generator/UrlGeneratorInterface.phpnu�[���PKw�Zn���hh2Ȥ'Symfony/Component/Routing/Loader/ClosureLoader.phpnu�[���PKw�Z��?�		>��'Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.phpnu�[���PKw�Z~ޟ
�
9�'Symfony/Component/Routing/Loader/AnnotationFileLoader.phpnu�[���PKw�Z~L�W��:�'Symfony/Component/Routing/Loader/AnnotationClassLoader.phpnu�[���PKw�ZP�i{��2��'Symfony/Component/Routing/Loader/PhpFileLoader.phpnu�[���PKw�Z?-[��	�	?5�'Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsdnu�[���PKw�Zأ2D$D$2L�'Symfony/Component/Routing/Loader/XmlFileLoader.phpnu�[���PKw�ZpB�Q Q 3�(Symfony/Component/Routing/Loader/YamlFileLoader.phpnu�[���PKx�ZqF��>>4�5(Symfony/Component/Routing/RouteCompilerInterface.phpnu�[���PKx�Z0���QQ(H9(Symfony/Component/Process/autoloader.phpnu�[���PKx�Zg��'�'*�:(Symfony/Component/Process/ProcessPipes.phpnu�[���PKx�Z��2�{{@6c(Symfony/Component/Process/Exception/ProcessTimedOutException.phpnu�[���PKx�Z�<���:!j(Symfony/Component/Process/Exception/ExceptionInterface.phpnu�[���PKx�Z>H����8:l(Symfony/Component/Process/Exception/RuntimeException.phpnu�[���PKx�Z��W��6�n(Symfony/Component/Process/Exception/LogicException.phpnu�[���PKx�Z˅����@�p(Symfony/Component/Process/Exception/InvalidArgumentException.phpnu�[���PKx�Z��_��>s(Symfony/Component/Process/Exception/ProcessFailedException.phpnu�[���PKx�Z@s�(�x(Symfony/Component/Process/PhpProcess.phpnu�[���PKx�Z�nL	L	*�(Symfony/Component/Process/ProcessUtils.phpnu�[���PKy�Z�!,$

.��(Symfony/Component/Process/ExecutableFinder.phpnu�[���PKy�Z!/���,�(Symfony/Component/Process/ProcessBuilder.phpnu�[���PKy�Zy>�8��1�(Symfony/Component/Process/PhpExecutableFinder.phpnu�[���PKy�Z��M��%PK��Z��w�dd3.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUri   URI of the namespace
     * @param bool   $multiline      whether to create a multiline tag where each
     *                               attribute gets written to a single line
     * @param string $indent         string used to indent attributes (_auto indents
     *                               attributes so they start at the same column)
     * @param string $linebreak      string used for linebreaks
     * @param bool   $sortAttributes Whether to sort the attributes or not
     *
     * @return string XML start element
     * @see    createEndElement(), createTag()
     */
    public static function createStartElement(
        $qname, $attributes = array(), $namespaceUri = null,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true
    ) {
        // if no attributes hav been set, use empty attributes
        if (!isset($attributes) || !is_array($attributes)) {
            $attributes = array();
        }

        if ($namespaceUri != null) {
            $parts = XML_Util::splitQualifiedName($qname);
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($qname)+2));
            }
        }

        if ($namespaceUri != null) {
            // is a namespace given
            if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
            } else {
                // define this Uri as the default namespace
                $attributes['xmlns'] = $namespaceUri;
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $attributes, $sortAttributes,
            $multiline, $indent, $linebreak
        );
        $element = sprintf('<%s%s>', $qname, $attList);
        return  $element;
    }

    /**
     * Create an end element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createEndElement('myNs:myTag');
     * </code>
     *
     * @param string $qname qualified tagname (including namespace)
     *
     * @return string XML end element
     * @see    createStartElement(), createTag()
     */
    public static function createEndElement($qname)
    {
        $element = sprintf('</%s>', $qname);
        return $element;
    }

    /**
     * Create an XML comment
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createComment('I am a comment');
     * </code>
     *
     * @param string $content content of the comment
     *
     * @return string XML comment
     */
    public static function createComment($content)
    {
        $comment = sprintf('<!-- %s -->', $content);
        return $comment;
    }

    /**
     * Create a CData section
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create a CData section
     * $tag = XML_Util::createCDataSection('I am content.');
     * </code>
     *
     * @param string $data data of the CData section
     *
     * @return string CData section with content
     */
    public static function createCDataSection($data)
    {
        return sprintf(
            '<![CDATA[%s]]>',
            preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data))
        );
    }

    /**
     * Split qualified name and return namespace and local part
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // split qualified tag
     * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
     * </code>
     * the returned array will contain two elements:
     * <pre>
     * array(
     *     'namespace' => 'xslt',
     *     'localPart' => 'stylesheet'
     * );
     * </pre>
     *
     * @param string $qname     qualified tag name
     * @param string $defaultNs default namespace (optional)
     *
     * @return array array containing namespace and local part
     */
    public static function splitQualifiedName($qname, $defaultNs = null)
    {
        if (strstr($qname, ':')) {
            $tmp = explode(':', $qname);
            return array(
                'namespace' => $tmp[0],
                'localPart' => $tmp[1]
            );
        }
        return array(
            'namespace' => $defaultNs,
            'localPart' => $qname
        );
    }

    /**
     * Check, whether string is valid XML name
     *
     * <p>XML names are used for tagname, attribute names and various
     * other, lesser known entities.</p>
     * <p>An XML name may only consist of alphanumeric characters,
     * dashes, undescores and periods, and has to start with a letter
     * or an underscore.</p>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // verify tag name
     * $result = XML_Util::isValidName('invalidTag?');
     * if (is_a($result, 'PEAR_Error')) {
     *    print 'Invalid XML name: ' . $result->getMessage();
     * }
     * </code>
     *
     * @param string $string string that should be checked
     *
     * @return mixed true, if string is a valid XML name, PEAR error otherwise
     *
     * @todo support for other charsets
     * @todo PEAR CS - unable to avoid 85-char limit on second preg_match
     */
    public static function isValidName($string)
    {
        // check for invalid chars
        if (!is_string($string) || !strlen($string) || !preg_match('/^[[:alpha:]_]\\z/', $string[0])) {
            return XML_Util::raiseError(
                'XML names may only start with letter or underscore',
                XML_UTIL_ERROR_INVALID_START
            );
        }

        // check for invalid chars
        $match = preg_match(
            '/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?'
            . '[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/',
            $string
        );
        if (!$match) {
            return XML_Util::raiseError(
                'XML names may only contain alphanumeric '
                . 'chars, period, hyphen, colon and underscores',
                XML_UTIL_ERROR_INVALID_CHARS
            );
        }
        // XML name is valid
        return true;
    }

    /**
     * Replacement for XML_Util::raiseError
     *
     * Avoids the necessity to always require
     * PEAR.php
     *
     * @param string $msg  error message
     * @param int    $code error code
     *
     * @return PEAR_Error
     * @todo   PEAR CS - should this use include_once instead?
     */
    public static function raiseError($msg, $code)
    {
        include_once 'PEAR.php';
        return PEAR::raiseError($msg, $code);
    }
}
?>
PK��Z#F��:�:pearcmd.phpnu�[���<?php
/**
 * PEAR, the PHP Extension and Application Repository
 *
 * Command line interface
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Stig Bakken <ssb@php.net>
 * @author    Tomas V.V.Cox <cox@idecnet.com>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 */

@ob_end_clean();
if (!defined('PEAR_RUNTYPE')) {
    // this is defined in peclcmd.php as 'pecl'
    define('PEAR_RUNTYPE', 'pear');
}
define('PEAR_IGNORE_BACKTRACE', 1);
/**
 * @nodep Gtk
 */
//the space is needed for windows include paths with trailing backslash
// http://pear.php.net/bugs/bug.php?id=19482
if ('/opt/alt/php74/usr/share/pear ' != '@'.'include_path'.'@ ') {
    ini_set('include_path', trim('/opt/alt/php74/usr/share/pear '). PATH_SEPARATOR .  get_include_path());
    $raw = false;
} else {
    // this is a raw, uninstalled pear, either a cvs checkout, or php distro
    ini_set('include_path', dirname(__DIR__) . PATH_SEPARATOR . get_include_path());
    $raw = true;
}
@ini_set('allow_url_fopen', true);
@set_time_limit(0);
ob_implicit_flush(true);
@ini_set('track_errors', true);
@ini_set('html_errors', false);
$_PEAR_PHPDIR = '#$%^&*';
set_error_handler('error_handler');

$pear_package_version = "1.10.16";

require_once 'PEAR.php';
require_once 'PEAR/Frontend.php';
require_once 'PEAR/Config.php';
require_once 'PEAR/Command.php';
require_once 'Console/Getopt.php';


PEAR_Command::setFrontendType('CLI');
$all_commands = PEAR_Command::getCommands();

$argv = Console_Getopt::readPHPArgv();
// fix CGI sapi oddity - the -- in pear.bat/pear is not removed
if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
    unset($argv[1]);
    $argv = array_values($argv);
}
$progname = PEAR_RUNTYPE;
array_shift($argv);
$options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV");
if (PEAR::isError($options)) {
    usage($options);
}

$opts = $options[0];

$fetype = 'CLI';
if ($progname == 'gpear' || $progname == 'pear-gtk') {
    $fetype = 'Gtk2';
} else {
    foreach ($opts as $opt) {
        if ($opt[0] == 'G') {
            $fetype = 'Gtk2';
        }
    }
}

$pear_user_config = '';
$pear_system_config = '';
$store_user_config = false;
$store_system_config = false;
$verbose = 1;

foreach ($opts as $opt) {
    switch ($opt[0]) {
    case 'c':
        $pear_user_config = $opt[1];
        break;
    case 'C':
        $pear_system_config = $opt[1];
        break;
    }
}

PEAR_Command::setFrontendType($fetype);
$ui = &PEAR_Command::getFrontendObject();
$config = &PEAR_Config::singleton($pear_user_config, $pear_system_config);

if (PEAR::isError($config)) {
    $_file = '';
    if ($pear_user_config !== false) {
        $_file .= $pear_user_config;
    }
    if ($pear_system_config !== false) {
        $_file .= '/' . $pear_system_config;
    }
    if ($_file == '/') {
        $_file = 'The default config file';
    }
    $config->getMessage();
    $ui->outputData("ERROR: $_file is not a valid config file or is corrupted.");
    // We stop, we have no idea where we are :)
    exit(1);
}

// this is used in the error handler to retrieve a relative path
$_PEAR_PHPDIR = $config->get('php_dir');
$ui->setConfig($config);
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError"));

$verbose = $config->get("verbose");
$cmdopts = array();

if ($raw) {
    if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) {
        $found = false;
        foreach ($opts as $opt) {
            if ($opt[0] == 'd' || $opt[0] == 'D') {
                // the user knows what they are doing, and are setting config values
                $found = true;
            }
        }
        if (!$found) {
            // no prior runs, try to install PEAR
            $parent = dirname(__FILE__);
            if (strpos($parent, 'scripts')) {
                $grandparent = dirname($parent);
                $packagexml = $grandparent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $grandparent;
            } else {
                $packagexml = $parent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $parent;
            }
            if (file_exists($packagexml)) {
                $options[1] = array(
                    'install',
                    $packagexml
                );
                $config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php');
                $config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data');
                $config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs');
                $config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests');
                $config->set(
                    'ext_dir',
                    $pearbase . DIRECTORY_SEPARATOR . 'extensions'
                );
                $config->set('bin_dir', $pearbase);
                $config->mergeConfigFile($pearbase . 'pear.ini', false);
                $config->store();
                $config->set('auto_discover', 1);
            }
        }
    }
}
foreach ($opts as $opt) {
    $param = !empty($opt[1]) ? $opt[1] : true;
    switch ($opt[0]) {
    case 'd':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected -d config_value=value, ' .
                'received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'user');
        break;
    case 'D':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'system');
        break;
    case 's':
        $store_user_config = true;
        break;
    case 'S':
        $store_system_config = true;
        break;
    case 'u':
        $config->remove($param, 'user');
        break;
    case 'v':
        $config->set('verbose', $config->get('verbose') + 1);
        break;
    case 'q':
        $config->set('verbose', $config->get('verbose') - 1);
        break;
    case 'V':
        usage(null, 'version');
    case 'c':
    case 'C':
        break;
    default:
        // all non pear params goes to the command
        $cmdopts[$opt[0]] = $param;
        break;
    }
}

if ($store_system_config) {
    $config->store('system');
}

if ($store_user_config) {
    $config->store('user');
}

$command = (isset($options[1][0])) ? $options[1][0] : null;
if (empty($command) && ($store_user_config || $store_system_config)) {
    exit;
}

if ($fetype == 'Gtk2') {
    if (!$config->validConfiguration()) {
        PEAR::raiseError(
            "CRITICAL ERROR: no existing valid configuration files found in " .
            "files '$pear_user_config' or '$pear_system_config', " .
            "please copy an existing configuration file to one of these " .
            "locations, or use the -c and -s options to create one"
        );
    }
    Gtk::main();
} else {
    do {
        if ($command == 'help') {
            usage(null, isset($options[1][1]) ? $options[1][1] : null);
        }

        if (!$config->validConfiguration()) {
            PEAR::raiseError(
                "CRITICAL ERROR: no existing valid configuration files found " .
                "in files '$pear_user_config' or '$pear_system_config', " .
                "please copy an existing configuration file to one of " .
                "these locations, or use the -c and -s options to create one"
            );
        }

        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        $cmd = PEAR_Command::factory($command, $config);
        PEAR::popErrorHandling();
        if (PEAR::isError($cmd)) {
            usage(null, isset($options[1][0]) ? $options[1][0] : null);
        }

        $short_args = $long_args = null;
        PEAR_Command::getGetoptArgs($command, $short_args, $long_args);
        array_shift($options[1]);
        $tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args);

        if (PEAR::isError($tmp)) {
            break;
        }

        list($tmpopt, $params) = $tmp;
        $opts = array();
        foreach ($tmpopt as $foo => $tmp2) {
            list($opt, $value) = $tmp2;
            if ($value === null) {
                $value = true; // options without args
            }

            if (strlen($opt) == 1) {
                $cmdoptions = $cmd->getOptions($command);
                foreach ($cmdoptions as $o => $d) {
                    if (isset($d['shortopt']) && $d['shortopt'] == $opt) {
                        $opts[$o] = $value;
                    }
                }
            } else {
                if (substr($opt, 0, 2) == '--') {
                    $opts[substr($opt, 2)] = $value;
                }
            }
        }

        $ok = $cmd->run($command, $opts, $params);
        if ($ok === false) {
            PEAR::raiseError("unknown command `$command'");
        }

        if (PEAR::isError($ok)) {
            PEAR::setErrorHandling(
                PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")
            );
            PEAR::raiseError($ok);
        }
    } while (false);
}

// {{{ usage()

/**
 * Display usage information
 *
 * @param mixed $error       Optional error message
 * @param mixed $helpsubject Optional subject/command to display help for
 *
 * @return void
 */
function usage($error = null, $helpsubject = null)
{
    global $progname, $all_commands;
    $stdout = fopen('php://stdout', 'w');
    if (PEAR::isError($error)) {
        fputs($stdout, $error->getMessage() . "\n");
    } elseif ($error !== null) {
        fputs($stdout, "$error\n");
    }

    if ($helpsubject != null) {
        $put = cmdHelp($helpsubject);
    } else {
        $put = "Commands:\n";
        $maxlen = max(array_map("strlen", $all_commands));
        $formatstr = "%-{$maxlen}s  %s\n";
        ksort($all_commands);
        foreach ($all_commands as $cmd => $class) {
            $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd));
        }
        $put .=
            "Usage: $progname [options] command [command-options] <parameters>\n".
            "Type \"$progname help options\" to list all options.\n".
            "Type \"$progname help shortcuts\" to list all command shortcuts.\n".
            "Type \"$progname help version\" or ".
            "\"$progname version\" to list version information.\n".
            "Type \"$progname help <command>\" to get the help ".
            "for the specified command.";
    }
    fputs($stdout, "$put\n");
    fclose($stdout);

    if ($error === null) {
        exit(0);
    }
    exit(1);
}

/**
 * Return help string for specified command
 *
 * @param string $command Command to return help for
 *
 * @return void
 */
function cmdHelp($command)
{
    global $progname, $all_commands, $config;
    if ($command == "options") {
        return
        "Options:\n".
        "     -v         increase verbosity level (default 1)\n".
        "     -q         be quiet, decrease verbosity level\n".
        "     -c file    find user configuration in `file'\n".
        "     -C file    find system configuration in `file'\n".
        "     -d foo=bar set user config variable `foo' to `bar'\n".
        "     -D foo=bar set system config variable `foo' to `bar'\n".
        "     -G         start in graphical (Gtk) mode\n".
        "     -s         store user configuration\n".
        "     -S         store system configuration\n".
        "     -u foo     unset `foo' in the user configuration\n".
        "     -h, -?     display help/usage (this message)\n".
        "     -V         version information\n";
    } elseif ($command == "shortcuts") {
        $sc = PEAR_Command::getShortcuts();
        $ret = "Shortcuts:\n";
        foreach ($sc as $s => $c) {
            $ret .= sprintf("     %-8s %s\n", $s, $c);
        }
        return $ret;

    } elseif ($command == "version") {
        return "PEAR Version: ".$GLOBALS['pear_package_version'].
               "\nPHP Version: ".phpversion().
               "\nZend Engine Version: ".zend_version().
               "\nRunning on: ".php_uname();

    } elseif ($help = PEAR_Command::getHelp($command)) {
        if (is_string($help)) {
            return "$progname $command [options] $help\n";
        }

        if ($help[1] === null) {
            return "$progname $command $help[0]";
        }

        return "$progname $command [options] $help[0]\n$help[1]";
    }

    return "Command '$command' is not valid, try '$progname help'";
}

// }}}

/**
 * error_handler
 *
 * @param mixed $errno  Error number
 * @param mixed $errmsg Message
 * @param mixed $file   Filename
 * @param mixed $line   Line number
 *
 * @access public
 * @return boolean
 */
function error_handler($errno, $errmsg, $file, $line)
{
    if ((!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) && ($errno & E_STRICT)) {
        return; // E_STRICT
    }
    if ($errno & E_DEPRECATED) {
        return; // E_DEPRECATED
    }
    if (!(error_reporting() & $errno) &&
        isset($GLOBALS['config']) &&
        $GLOBALS['config']->get('verbose') < 4
    ) {
        return false; // @silenced error, show all if debug is high enough
    }
    $errortype = array (
        E_DEPRECATED  => 'Deprecated Warning',
        E_ERROR   =>  "Error",
        E_WARNING   =>  "Warning",
        E_PARSE   =>  "Parsing Error",
        E_NOTICE   =>  "Notice",
        E_CORE_ERROR  =>  "Core Error",
        E_CORE_WARNING  =>  "Core Warning",
        E_COMPILE_ERROR  =>  "Compile Error",
        E_COMPILE_WARNING =>  "Compile Warning",
        E_USER_ERROR =>  "User Error",
        E_USER_WARNING =>  "User Warning",
        E_USER_NOTICE =>  "User Notice"
    );
    if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) {
        $errortype[E_STRICT] = 'Strict Warning';
    }
    $prefix = $errortype[$errno];
    global $_PEAR_PHPDIR;
    if (stristr($file, $_PEAR_PHPDIR)) {
        $file = substr($file, strlen($_PEAR_PHPDIR) + 1);
    } else {
        $file = basename($file);
    }
    print "\n$prefix: $errmsg in $file on line $line\n";
    return false;
}


/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * indent-tabs-mode: nil
 * mode: php
 * End:
 */
// vim600:syn=php
PK��Z�0$�-- .pkgxml/Pear_File_MARC-1.4.1.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.10.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
 <name>File_MARC</name>
 <channel>pear.php.net</channel>
 <summary>Parse, modify, and create MARC records</summary>
 <description>The standard for machine-readable cataloging (MARC) records is documented at http://loc.gov/marc/. This package enables you to read existing MARC records from a file, string, or (using the YAZ extension), from a Z39.50 source. You can also use this package to create new MARC records.

This package is based on the PHP MARC package, originally called &quot;php-marc&quot;, that is part of the Emilda Project (http://www.emilda.org).  Christoffer Landtman generously agreed to make the &quot;php-marc&quot; code available under the GNU LGPL so it could be used as the basis of this PEAR package.</description>
 <lead>
  <name>Dan Scott</name>
  <user>dbs</user>
  <email>dbs@php.net</email>
  <active>yes</active>
 </lead>
 <date>2019-11-13</date>
 <time>17:33:33</time>
 <version>
  <release>1.4.1</release>
  <api>1.4.0</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license uri="http://www.gnu.org/copyleft/lesser.html">GNU Lesser General Public License</license>
 <notes>
1.4.1
  * Reintroduce include_path to composer.json
 </notes>
 <contents>
  <dir baseinstalldir="File" name="/">
   <file baseinstalldir="/" md5sum="ffe2590635f404af055fe731da105939" name="File/MARC/Lint/CodeData.php" role="php" />
   <file baseinstalldir="/" md5sum="a3b9e1c817e67f59add05593500d463e" name="File/MARC/Control_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="acba4463f8e40d6ee4e7ba1f2dc53123" name="File/MARC/Data_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="378f483ec1fd161cd9dfb9b05db58d66" name="File/MARC/Exception.php" role="php" />
   <file baseinstalldir="/" md5sum="a9ba69030cbf4847292b9975e9d922c6" name="File/MARC/Field.php" role="php" />
   <file baseinstalldir="/" md5sum="c37351c7c80927ce6bb1e662510f9183" name="File/MARC/Lint.php" role="php" />
   <file baseinstalldir="/" md5sum="c5ac39e3d25eb0108b9dd5ad8466c821" name="File/MARC/List.php" role="php" />
   <file baseinstalldir="/" md5sum="7af6ce78cde4bb246e4e96709e90d2c0" name="File/MARC/Record.php" role="php" />
   <file baseinstalldir="/" md5sum="df5f97139685f0ad04e47fdbb67e3968" name="File/MARC/Subfield.php" role="php" />
   <file baseinstalldir="/" md5sum="6e102262dfd5d65d8d5a6221dfc74edd" name="File/MARC.php" role="php" />
   <file baseinstalldir="/" md5sum="8b64040d2d18ac4b994595a148266a66" name="File/MARCBASE.php" role="php" />
   <file baseinstalldir="/" md5sum="f5a17a60d34e84e2ee7ca1e5c5c6c620" name="File/MARCXML.php" role="php" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="examples/example.mrc" role="doc" />
   <file baseinstalldir="File" md5sum="1aea40df9f1c2e32f8e065fe8da0a3b5" name="examples/marc_yaz.php" role="doc" />
   <file baseinstalldir="File" md5sum="70ae317e0890d5896e3ffccdd293369a" name="examples/read.php" role="doc" />
   <file baseinstalldir="File" md5sum="54efb9d920ac775bfc847a83a2dec73a" name="examples/subfields.php" role="doc" />
   <file baseinstalldir="File" md5sum="14297da35b510c496cd1f328cf3bb301" name="tests/bad_example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="0dd4c6dbad6e8608d0ebf9d24425955d" name="tests/bad_example.xml" role="test" />
   <file baseinstalldir="File" md5sum="216a6f9d53f6d3d8e22d81fdc10f4bc1" name="tests/camel.mrc" role="test" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="tests/example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="9455aec3371f79cf7d31281fd03f5171" name="tests/marc_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="577e2f5f89fd48cf1a3576a29d2958f8" name="tests/marc_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a6a586354b9a06c880c2a7470dd828d7" name="tests/marc_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1c7e2fc5572a0f9362a771c260a1fe3" name="tests/marc_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="84f85ac7f8a2532e4e90ccde7764556a" name="tests/marc_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="889e5e906a97de7a0e94b0c5f30e70e7" name="tests/marc_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="be823dc8a8efb408de06371ab802efcc" name="tests/marc_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="af44490aafea44e5120f881cb81cdad9" name="tests/marc_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ac9f2a7aeb24900a11f5102744179ae3" name="tests/marc_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5e43eb5cddbb4f2bd0d6405cd95b80aa" name="tests/marc_010.phpt" role="test" />
   <file baseinstalldir="File" md5sum="2e1cd8509c0bf04ec77fc0f51375f611" name="tests/marc_011.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bc49ca48623102c8ac07679fa77a3dd9" name="tests/marc_012.phpt" role="test" />
   <file baseinstalldir="File" md5sum="245a3b20e0da1973535503e28efd1d3a" name="tests/marc_013.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ce69aa734856dd40d60d30c77bdef53a" name="tests/marc_014.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7b61cdd31035e60682fa92c5d519d997" name="tests/marc_015.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7f4f597fe1adaa3507eb87fc4875dbd2" name="tests/marc_016.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4262efd5fcacbd7503323681f4552430" name="tests/marc_017.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ee1623d7bda54ba4f741b2319b158f82" name="tests/marc_018.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8006c03fbab0f04377342086fafd3982" name="tests/marc_019.phpt" role="test" />
   <file baseinstalldir="File" md5sum="f5ae5b25e0ac1104314433d9e5b1f7fe" name="tests/marc_020.phpt" role="test" />
   <file baseinstalldir="File" md5sum="94d8f99e86585671a1b2d3043aeb6360" name="tests/marc_021.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bb891a890effe0e77e1759043f4846d8" name="tests/marc_022.phpt" role="test" />
   <file baseinstalldir="File" md5sum="faf77dcb5cdd002c09169a14bfded65e" name="tests/marc_023.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0e6c4a23f5da7df64fdd4b3b1149bbee" name="tests/marc_16783.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4ea8b3520beda378db15960f1c50493a" name="tests/marc_field_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="743850ef61df69c4340be44a03bccb5a" name="tests/marc_field_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8c765f1398b49df257d86d22ac6e4f8d" name="tests/marc_field_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d4216cf930a308e0d02553bd3914f294" name="tests/marc_field_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dd59514b474b78371ad522a3e13b76b7" name="tests/marc_field_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5295bfd02a8424acac1c91de26b552c7" name="tests/marc_field_21246.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6f95f09442ccf6b93df92986f58b270d" name="tests/marc_lint_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="18d721f8871edd925624ccbdd15444fb" name="tests/marc_lint_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4eb86a2f4e0a74dedcb0bf2511da6ca1" name="tests/marc_lint_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="10430fee0a1352d0528f1507b34c57e1" name="tests/marc_lint_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0dcd07a18577d7b22392a2214cd6436c" name="tests/marc_lint_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fd17798fc535562e5e64461f449516b2" name="tests/marc_record_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="141b455ccf67a60c4eac44c77960f2e2" name="tests/marc_subfield_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1e23464ee0eec47ddca2af9a9922926" name="tests/marc_subfield_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="1d7903e8c244d647220b318b4bc758d1" name="tests/marc_xml_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="22cae3c752d843b78f583dcd92801534" name="tests/marc_xml_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="c0716d23e0f960abf8d53ad6014a413a" name="tests/marc_xml_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7645fa19e28aca041a124fc5e2c12bd3" name="tests/marc_xml_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b08b28c3251625b8b6e4d7ab376b0185" name="tests/marc_xml_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6cd0934ddbf65d2d7e9ea5d108977ff7" name="tests/marc_xml_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ffdce4aa190268fa7cbbf3bb45383abf" name="tests/marc_xml_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="998a4c1ce00ff100f39ffa9fc49a212f" name="tests/marc_xml_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a38a67c590869f2b0a4859a910fd9e89" name="tests/marc_xml_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="db39c5055a570fcda12bb7c5fa1e3b4d" name="tests/marc_xml_16642.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dc075f4a271bd7182378a3874bd5b39e" name="tests/marc_xml_namespace.phpt" role="test" />
   <file baseinstalldir="File" md5sum="208200d9a979ac360c4d326e9789b6b7" name="tests/marc_xml_namespace_prefix.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d87774ede82222cfc12b2c2a06f57a3a" name="tests/marc_xml_rsinger.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fb44e3eb69f1a37115235fc829c39542" name="tests/namespace.xml" role="test" />
   <file baseinstalldir="File" md5sum="e6de4d809b0af5dd99fd352eb60616a1" name="tests/skipif.inc" role="test" />
   <file baseinstalldir="File" md5sum="a0166a4ff0bc0bb283e854f11beaa793" name="tests/music.mrc" role="test" />
   <file baseinstalldir="File" md5sum="993ce494befbc25dc1326527b30b4782" name="tests/music.xml" role="test" />
   <file baseinstalldir="File" md5sum="6b0c87f0cd459ed7322c25d403b164cc" name="tests/bigarchive.xml" role="test" />
   <file baseinstalldir="File" md5sum="be850aa6ab4ac52b8c6c214c30b574af" name="tests/onerecord.xml" role="test" />
   <file baseinstalldir="File" md5sum="4f43fec7b276267eec5258044853ccc8" name="tests/sandburg.mrc" role="test" />
   <file baseinstalldir="File" md5sum="e216b95f905dd240c9bde372950e4073" name="tests/sandburg.xml" role="test" />
   <file baseinstalldir="File" md5sum="e81a92188ea0dcd9c108a63fb32b3f4f" name="tests/xmlescape.mrc" role="test" />
   <file baseinstalldir="File" md5sum="8f9f63ed6a80191d89a2296fa4c1a30b" name="CHANGELOG" role="doc" />
   <file baseinstalldir="File" md5sum="fbc093901857fcd118f065f900982c24" name="LICENSE" role="doc" />
  </dir>
 </contents>
 <dependencies>
  <required>
   <php>
    <min>5.6</min>
   </php>
   <pearinstaller>
    <min>1.4.0</min>
   </pearinstaller>
  </required>
  <optional>
   <package>
    <name>Validate_ISPN</name>
    <channel>pear.php.net</channel>
   </package>
  </optional>
 </dependencies>
 <phprelease />
</package>
PKm�ZPi��.depdbnu�[���PKm�Z�{��
�Mail/null.phpnu�[���PKm�ZE@�%>>
Mail/sendmail.phpnu�[���PKm�Z��A~�{�{�;Mail/RFC822.phpnu�[���PKn�Z�+V����
[�Mail/mime.phpnu�[���PKn�Zx�ع���D�Mail/mimeDecode.phpnu�[���PKn�ZB�_Ǭ=�=
@(Mail/smtp.phpnu�[���PKn�ZwԐE;E;)fMail/smtpmx.phpnu�[���PKn�Z�؛�J�J���Mail/mimePart.phpnu�[���PKn�ZB��shh
8YMail/mock.phpnu�[���PKn�Z@iE�\\
�lMail/mail.phpnu�[���PKn�Zv�.locknu�[���PKn�Z�*�z%-%- ��Structures/LinkedList/Double.phpnu�[���PKn�Z����p:p:  �Structures/LinkedList/Single.phpnu�[���PKn�ZUyv���Structures/Graph.phpnu�[���PKn�Z�C� + +CStructures/Graph/Node.phpnu�[���PKn�Z9����,�1Structures/Graph/Manipulator/AcyclicTest.phpnu�[���PKn�Z~(�htt2�HStructures/Graph/Manipulator/TopologicalSorter.phpnu�[���PKn�Z�J�}
}
_dAuth/SASL/Anonymous.phpnu�[���PKn�ZP(~�T
T
#rAuth/SASL/CramMD5.phpnu�[���PKn�Z����==�Auth/SASL/Plain.phpnu�[���PKn�Z�<� OO<�Auth/SASL/Login.phpnu�[���PKn�Z%ׅtg!g!ΘAuth/SASL/DigestMD5.phpnu�[���PKn�Z�T�|�Auth/SASL/Common.phpnu�[���PKn�ZvR�r,,��Auth/SASL/External.phpnu�[���PKn�Zќ��0�0H�Auth/SASL/SCRAM.phpnu�[���PKn�Z2r����
�	Auth/SASL.phpnu�[���PKn�Z�T�,�,�OS/Guess.phpnu�[���PKn�Z�����KPEAR/Config.phpnu�[���PKn�Z�`�eEAEA
.ZPEAR/REST.phpnu�[���PKn�Z��ym6m6��PEAR/Exception.phpnu�[���PKn�Zr"����_�PEAR/ChannelFile.phpnu�[���PKn�Z��gk�U�U?�PEAR/Validate.phpnu�[���PKn�Zd֣S��u�PEAR/Command/Pickle.xmlnu�[���PKn�Z�z��k<k<W�PEAR/Command/Config.phpnu�[���PKn�Z݄<ii	1PEAR/Command/Mirror.xmlnu�[���PKn�Z,��t"u"u�3PEAR/Command/Remote.phpnu�[���PKn�Z
�\���"�PEAR/Command/Remote.xmlnu�[���PKn�Zj���!�!X�PEAR/Command/Install.xmlnu�[���PKo�Z�%q������PEAR/Command/Channels.phpnu�[���PKo�Znmi?;�;��[	PEAR/Command/Install.phpnu�[���PKo�Z�X�

#
PEAR/Command/Auth.phpnu�[���PKo�Z���s6
6
T-
PEAR/Command/Config.xmlnu�[���PKo�Z�%Fii�:
PEAR/Command/Test.xmlnu�[���PKo�ZZ h66A
PEAR/Command/Package.xmlnu�[���PKo�Z�w��zz�]
PEAR/Command/Channels.xmlnu�[���PKo�Z+9ҜҜ�n
PEAR/Command/Package.phpnu�[���PKo�Z
u����PEAR/Command/Build.xmlnu�[���PKo�Z������
PEAR/Command/Mirror.phpnu�[���PKp�Z,_�h/h/�PEAR/Command/Test.phpnu�[���PKp�Z�%sp  6OPEAR/Command/Common.phpnu�[���PKp�Z0(;rʹʹ�oPEAR/Command/Registry.phpnu�[���PKp�Z�4�{���$PEAR/Command/Auth.xmlnu�[���PKp�Z��#S
S
�)PEAR/Command/Build.phpnu�[���PKp�Z���u��S4PEAR/Command/Registry.xmlnu�[���PKp�Z�P>>�;PEAR/Command/Pickle.phpnu�[���PKp�Z��T�I�I�yPEAR/Builder.phpnu�[���PKp�Z[
�W��3�PEAR/XMLParser.phpnu�[���PKp�Zl(e���t�PEAR/Downloader.phpnu�[���PKp�Z�b������
PEAR/ErrorStack.phpnu�[���PKp�Z(Pz����ePEAR/Proxy.phpnu�[���PKp�Z��'����|PEAR/RunTest.phpnu�[���PKq�Zj�y99�	PEAR/Validator/PECL.phpnu�[���PKq�Zp�����aPEAR/Dependency2.phpnu�[���PKq�Z��wv@@��PEAR/PackageFile/v2.phpnu�[���PKq�ZC�8�L�L!:�PEAR/PackageFile/v2/Validator.phpnu�[���PKq�Z���=_�_�6PEAR/PackageFile/v2/rw.phpnu�[���PKq�Z�5�������,PEAR/PackageFile/v1.phpnu�[���PKq�Z�ɁɁ!��PEAR/PackageFile/Generator/v2.phpnu�[���PKq�Z`�=����!�tPEAR/PackageFile/Generator/v1.phpnu�[���PKPK��Z�N��&�&2.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With PK��Z���f�f0.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUri   URI of the namespace
     * @param bool   $multiline      whether to create a multiline tag where each
     *                               attribute gets written to a single line
     * @param string $indent         string used to indent attributes (_auto indents
     *                               attributes so they start at the same column)
     * @param string $linebreak      string used for linebreaks
     * @param bool   $sortAttributes Whether to sort the attributes or not
     *
     * @return string XML start element
     * @see    createEndElement(), createTag()
     */
    public static function createStartElement(
        $qname, $attributes = array(), $namespaceUri = null,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true
    ) {
        // if no attributes hav been set, use empty attributes
        if (!isset($attributes) || !is_array($attributes)) {
            $attributes = array();
        }

        if ($namespaceUri != null) {
            $parts = XML_Util::splitQualifiedName($qname);
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($qname)+2));
            }
        }

        if ($namespaceUri != null) {
            // is a namespace given
            if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
            } else {
                // define this Uri as the default namespace
                $attributes['xmlns'] = $namespaceUri;
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $attributes, $sortAttributes,
            $multiline, $indent, $linebreak
        );
        $element = sprintf('<%s%s>', $qname, $attList);
        return  $element;
    }

    /**
     * Create an end element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createEndElement('myNs:myTag');
     * </code>
     *
     * @param string $qname qualified tagname (including namespace)
     *
     * @return string XML end element
     * @see    createStartElement(), createTag()
     */
    public static function createEndElement($qname)
    {
        $element = sprintf('</%s>', $qname);
        return $element;
    }

    /**
     * Create an XML comment
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createComment('I am a comment');
     * </code>
     *
     * @param string $content content of the comment
     *
     * @return string XML comment
     */
    public static function createComment($content)
    {
        $comment = sprintf('<!-- %s -->', $content);
        return $comment;
    }

    /**
     * Create a CData section
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create a CData section
     * $tag = XML_Util::createCDataSection('I am content.');
     * </code>
     *
     * @param string $data data of the CData section
     *
     * @return string CData section with content
     */
    public static function createCDataSection($data)
    {
        return sprintf(
            '<![CDATA[%s]]>',
            preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data))
        );
    }

    /**
     * Split qualified name and return namespace and local part
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // split qualified tag
     * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
     * </code>
     * the returned array will contain two elements:
     * <pre>
     * array(
     *     'namespace' => 'xslt',
     *     'localPart' => 'stylesheet'
     * );
     * </pre>
     *
     * @param string $qname     qualified tag name
     * @param string $defaultNs default namespace (optional)
     *
     * @return array array containing namespace and local part
     */
    public static function splitQualifiedName($qname, $defaultNs = null)
    {
        if (strstr($qname, ':')) {
            $tmp = explode(':', $qname);
            return array(
                'namespace' => $tmp[0],
                'localPart' => $tmp[1]
            );
        }
        return array(
            'namespace' => $defaultNs,
            'localPart' => $qname
        );
    }

    /**
     * Check, whether string is valid XML name
     *
     * <p>XML names are used for tagname, attribute names and various
     * other, lesser known entities.</p>
     * <p>An XML name may only consist of alphanumeric characters,
     * dashes, undescores and periods, and has to start with a letter
     * or an underscore.</p>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // verify tag name
     * $result = XML_Util::isValidName('invalidTag?');
     * if (is_a($result, 'PEAR_Error')) {
     *    print 'Invalid XML name: ' . $result->getMessage();
     * }
     * </code>
     *
     * @param string $string string that should be checked
     *
     * @return mixed true, if string is a valid XML name, PEAR error otherwise
     *
     * @todo support for other charsets
     * @todo PEAR CS - unable to avoid 85-char limit on second preg_match
     */
    public static function isValidName($string)
    {
        // check for invalid chars
        if (!is_string($string) || !strlen($string) || !preg_match('/^[[:alpha:]_]\\z/', $string[0])) {
            return XML_Util::raiseError(
                'XML names may only start with letter or underscore',
                XML_UTIL_ERROR_INVALID_START
            );
        }

        // check for invalid chars
        $match = preg_match(
            '/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?'
            . '[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/',
            $string
        );
        if (!$match) {
            return XML_Util::raiseError(
                'XML names may only contain alphanumeric '
                . 'chars, period, hyphen, colon and underscores',
                XML_UTIL_ERROR_INVALID_CHARS
            );
        }
        // XML name is valid
        return true;
    }

    /**
     * Replacement for XML_Util::raiseError
     *
     * Avoids the necessity to always require
     * PEAR.php
     *
     * @param string $msg  error message
     * @param int    $code error code
     *
     * @return PEAR_Error
     * @todo   PEAR CS - should this use include_once instead?
     */
    public static function raiseError($msg, $code)
    {
        include_once 'PEAR.php';
        return PEAR::raiseError($msg, $code);
    }
}
?>
PK��Z#F��:�:pearcmd.phpnu�[���<?php
/**
 * PEAR, the PHP Extension and Application Repository
 *
 * Command line interface
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Stig Bakken <ssb@php.net>
 * @author    Tomas V.V.Cox <cox@idecnet.com>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 */

@ob_end_clean();
if (!defined('PEAR_RUNTYPE')) {
    // this is defined in peclcmd.php as 'pecl'
    define('PEAR_RUNTYPE', 'pear');
}
define('PEAR_IGNORE_BACKTRACE', 1);
/**
 * @nodep Gtk
 */
//the space is needed for windows include paths with trailing backslash
// http://pear.php.net/bugs/bug.php?id=19482
if ('/opt/alt/php74/usr/share/pear ' != '@'.'include_path'.'@ ') {
    ini_set('include_path', trim('/opt/alt/php74/usr/share/pear '). PATH_SEPARATOR .  get_include_path());
    $raw = false;
} else {
    // this is a raw, uninstalled pear, either a cvs checkout, or php distro
    ini_set('include_path', dirname(__DIR__) . PATH_SEPARATOR . get_include_path());
    $raw = true;
}
@ini_set('allow_url_fopen', true);
@set_time_limit(0);
ob_implicit_flush(true);
@ini_set('track_errors', true);
@ini_set('html_errors', false);
$_PEAR_PHPDIR = '#$%^&*';
set_error_handler('error_handler');

$pear_package_version = "1.10.16";

require_once 'PEAR.php';
require_once 'PEAR/Frontend.php';
require_once 'PEAR/Config.php';
require_once 'PEAR/Command.php';
require_once 'Console/Getopt.php';


PEAR_Command::setFrontendType('CLI');
$all_commands = PEAR_Command::getCommands();

$argv = Console_Getopt::readPHPArgv();
// fix CGI sapi oddity - the -- in pear.bat/pear is not removed
if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
    unset($argv[1]);
    $argv = array_values($argv);
}
$progname = PEAR_RUNTYPE;
array_shift($argv);
$options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV");
if (PEAR::isError($options)) {
    usage($options);
}

$opts = $options[0];

$fetype = 'CLI';
if ($progname == 'gpear' || $progname == 'pear-gtk') {
    $fetype = 'Gtk2';
} else {
    foreach ($opts as $opt) {
        if ($opt[0] == 'G') {
            $fetype = 'Gtk2';
        }
    }
}

$pear_user_config = '';
$pear_system_config = '';
$store_user_config = false;
$store_system_config = false;
$verbose = 1;

foreach ($opts as $opt) {
    switch ($opt[0]) {
    case 'c':
        $pear_user_config = $opt[1];
        break;
    case 'C':
        $pear_system_config = $opt[1];
        break;
    }
}

PEAR_Command::setFrontendType($fetype);
$ui = &PEAR_Command::getFrontendObject();
$config = &PEAR_Config::singleton($pear_user_config, $pear_system_config);

if (PEAR::isError($config)) {
    $_file = '';
    if ($pear_user_config !== false) {
        $_file .= $pear_user_config;
    }
    if ($pear_system_config !== false) {
        $_file .= '/' . $pear_system_config;
    }
    if ($_file == '/') {
        $_file = 'The default config file';
    }
    $config->getMessage();
    $ui->outputData("ERROR: $_file is not a valid config file or is corrupted.");
    // We stop, we have no idea where we are :)
    exit(1);
}

// this is used in the error handler to retrieve a relative path
$_PEAR_PHPDIR = $config->get('php_dir');
$ui->setConfig($config);
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError"));

$verbose = $config->get("verbose");
$cmdopts = array();

if ($raw) {
    if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) {
        $found = false;
        foreach ($opts as $opt) {
            if ($opt[0] == 'd' || $opt[0] == 'D') {
                // the user knows what they are doing, and are setting config values
                $found = true;
            }
        }
        if (!$found) {
            // no prior runs, try to install PEAR
            $parent = dirname(__FILE__);
            if (strpos($parent, 'scripts')) {
                $grandparent = dirname($parent);
                $packagexml = $grandparent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $grandparent;
            } else {
                $packagexml = $parent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $parent;
            }
            if (file_exists($packagexml)) {
                $options[1] = array(
                    'install',
                    $packagexml
                );
                $config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php');
                $config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data');
                $config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs');
                $config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests');
                $config->set(
                    'ext_dir',
                    $pearbase . DIRECTORY_SEPARATOR . 'extensions'
                );
                $config->set('bin_dir', $pearbase);
                $config->mergeConfigFile($pearbase . 'pear.ini', false);
                $config->store();
                $config->set('auto_discover', 1);
            }
        }
    }
}
foreach ($opts as $opt) {
    $param = !empty($opt[1]) ? $opt[1] : true;
    switch ($opt[0]) {
    case 'd':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected -d config_value=value, ' .
                'received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'user');
        break;
    case 'D':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'system');
        break;
    case 's':
        $store_user_config = true;
        break;
    case 'S':
        $store_system_config = true;
        break;
    case 'u':
        $config->remove($param, 'user');
        break;
    case 'v':
        $config->set('verbose', $config->get('verbose') + 1);
        break;
    case 'q':
        $config->set('verbose', $config->get('verbose') - 1);
        break;
    case 'V':
        usage(null, 'version');
    case 'c':
    case 'C':
        break;
    default:
        // all non pear params goes to the command
        $cmdopts[$opt[0]] = $param;
        break;
    }
}

if ($store_system_config) {
    $config->store('system');
}

if ($store_user_config) {
    $config->store('user');
}

$command = (isset($options[1][0])) ? $options[1][0] : null;
if (empty($command) && ($store_user_config || $store_system_config)) {
    exit;
}

if ($fetype == 'Gtk2') {
    if (!$config->validConfiguration()) {
        PEAR::raiseError(
            "CRITICAL ERROR: no existing valid configuration files found in " .
            "files '$pear_user_config' or '$pear_system_config', " .
            "please copy an existing configuration file to one of these " .
            "locations, or use the -c and -s options to create one"
        );
    }
    Gtk::main();
} else {
    do {
        if ($command == 'help') {
            usage(null, isset($options[1][1]) ? $options[1][1] : null);
        }

        if (!$config->validConfiguration()) {
            PEAR::raiseError(
                "CRITICAL ERROR: no existing valid configuration files found " .
                "in files '$pear_user_config' or '$pear_system_config', " .
                "please copy an existing configuration file to one of " .
                "these locations, or use the -c and -s options to create one"
            );
        }

        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        $cmd = PEAR_Command::factory($command, $config);
        PEAR::popErrorHandling();
        if (PEAR::isError($cmd)) {
            usage(null, isset($options[1][0]) ? $options[1][0] : null);
        }

        $short_args = $long_args = null;
        PEAR_Command::getGetoptArgs($command, $short_args, $long_args);
        array_shift($options[1]);
        $tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args);

        if (PEAR::isError($tmp)) {
            break;
        }

        list($tmpopt, $params) = $tmp;
        $opts = array();
        foreach ($tmpopt as $foo => $tmp2) {
            list($opt, $value) = $tmp2;
            if ($value === null) {
                $value = true; // options without args
            }

            if (strlen($opt) == 1) {
                $cmdoptions = $cmd->getOptions($command);
                foreach ($cmdoptions as $o => $d) {
                    if (isset($d['shortopt']) && $d['shortopt'] == $opt) {
                        $opts[$o] = $value;
                    }
                }
            } else {
                if (substr($opt, 0, 2) == '--') {
                    $opts[substr($opt, 2)] = $value;
                }
            }
        }

        $ok = $cmd->run($command, $opts, $params);
        if ($ok === false) {
            PEAR::raiseError("unknown command `$command'");
        }

        if (PEAR::isError($ok)) {
            PEAR::setErrorHandling(
                PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")
            );
            PEAR::raiseError($ok);
        }
    } while (false);
}

// {{{ usage()

/**
 * Display usage information
 *
 * @param mixed $error       Optional error message
 * @param mixed $helpsubject Optional subject/command to display help for
 *
 * @return void
 */
function usage($error = null, $helpsubject = null)
{
    global $progname, $all_commands;
    $stdout = fopen('php://stdout', 'w');
    if (PEAR::isError($error)) {
        fputs($stdout, $error->getMessage() . "\n");
    } elseif ($error !== null) {
        fputs($stdout, "$error\n");
    }

    if ($helpsubject != null) {
        $put = cmdHelp($helpsubject);
    } else {
        $put = "Commands:\n";
        $maxlen = max(array_map("strlen", $all_commands));
        $formatstr = "%-{$maxlen}s  %s\n";
        ksort($all_commands);
        foreach ($all_commands as $cmd => $class) {
            $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd));
        }
        $put .=
            "Usage: $progname [options] command [command-options] <parameters>\n".
            "Type \"$progname help options\" to list all options.\n".
            "Type \"$progname help shortcuts\" to list all command shortcuts.\n".
            "Type \"$progname help version\" or ".
            "\"$progname version\" to list version information.\n".
            "Type \"$progname help <command>\" to get the help ".
            "for the specified command.";
    }
    fputs($stdout, "$put\n");
    fclose($stdout);

    if ($error === null) {
        exit(0);
    }
    exit(1);
}

/**
 * Return help string for specified command
 *
 * @param string $command Command to return help for
 *
 * @return void
 */
function cmdHelp($command)
{
    global $progname, $all_commands, $config;
    if ($command == "options") {
        return
        "Options:\n".
        "     -v         increase verbosity level (default 1)\n".
        "     -q         be quiet, decrease verbosity level\n".
        "     -c file    find user configuration in `file'\n".
        "     -C file    find system configuration in `file'\n".
        "     -d foo=bar set user config variable `foo' to `bar'\n".
        "     -D foo=bar set system config variable `foo' to `bar'\n".
        "     -G         start in graphical (Gtk) mode\n".
        "     -s         store user configuration\n".
        "     -S         store system configuration\n".
        "     -u foo     unset `foo' in the user configuration\n".
        "     -h, -?     display help/usage (this message)\n".
        "     -V         version information\n";
    } elseif ($command == "shortcuts") {
        $sc = PEAR_Command::getShortcuts();
        $ret = "Shortcuts:\n";
        foreach ($sc as $s => $c) {
            $ret .= sprintf("     %-8s %s\n", $s, $c);
        }
        return $ret;

    } elseif ($command == "version") {
        return "PEAR Version: ".$GLOBALS['pear_package_version'].
               "\nPHP Version: ".phpversion().
               "\nZend Engine Version: ".zend_version().
               "\nRunning on: ".php_uname();

    } elseif ($help = PEAR_Command::getHelp($command)) {
        if (is_string($help)) {
            return "$progname $command [options] $help\n";
        }

        if ($help[1] === null) {
            return "$progname $command $help[0]";
        }

        return "$progname $command [options] $help[0]\n$help[1]";
    }

    return "Command '$command' is not valid, try '$progname help'";
}

// }}}

/**
 * error_handler
 *
 * @param mixed $errno  Error number
 * @param mixed $errmsg Message
 * @param mixed $file   Filename
 * @param mixed $line   Line number
 *
 * @access public
 * @return boolean
 */
function error_handler($errno, $errmsg, $file, $line)
{
    if ((!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) && ($errno & E_STRICT)) {
        return; // E_STRICT
    }
    if ($errno & E_DEPRECATED) {
        return; // E_DEPRECATED
    }
    if (!(error_reporting() & $errno) &&
        isset($GLOBALS['config']) &&
        $GLOBALS['config']->get('verbose') < 4
    ) {
        return false; // @silenced error, show all if debug is high enough
    }
    $errortype = array (
        E_DEPRECATED  => 'Deprecated Warning',
        E_ERROR   =>  "Error",
        E_WARNING   =>  "Warning",
        E_PARSE   =>  "Parsing Error",
        E_NOTICE   =>  "Notice",
        E_CORE_ERROR  =>  "Core Error",
        E_CORE_WARNING  =>  "Core Warning",
        E_COMPILE_ERROR  =>  "Compile Error",
        E_COMPILE_WARNING =>  "Compile Warning",
        E_USER_ERROR =>  "User Error",
        E_USER_WARNING =>  "User Warning",
        E_USER_NOTICE =>  "User Notice"
    );
    if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) {
        $errortype[E_STRICT] = 'Strict Warning';
    }
    $prefix = $errortype[$errno];
    global $_PEAR_PHPDIR;
    if (stristr($file, $_PEAR_PHPDIR)) {
        $file = substr($file, strlen($_PEAR_PHPDIR) + 1);
    } else {
        $file = basename($file);
    }
    print "\n$prefix: $errmsg in $file on line $line\n";
    return false;
}


/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * indent-tabs-mode: nil
 * mode: php
 * End:
 */
// vim600:syn=php
PK��Z�0$�-- .pkgxml/Pear_File_MARC-1.4.1.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.10.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
 <name>File_MARC</name>
 <channel>pear.php.net</channel>
 <summary>Parse, modify, and create MARC records</summary>
 <description>The standard for machine-readable cataloging (MARC) records is documented at http://loc.gov/marc/. This package enables you to read existing MARC records from a file, string, or (using the YAZ extension), from a Z39.50 source. You can also use this package to create new MARC records.

This package is based on the PHP MARC package, originally called &quot;php-marc&quot;, that is part of the Emilda Project (http://www.emilda.org).  Christoffer Landtman generously agreed to make the &quot;php-marc&quot; code available under the GNU LGPL so it could be used as the basis of this PEAR package.</description>
 <lead>
  <name>Dan Scott</name>
  <user>dbs</user>
  <email>dbs@php.net</email>
  <active>yes</active>
 </lead>
 <date>2019-11-13</date>
 <time>17:33:33</time>
 <version>
  <release>1.4.1</release>
  <api>1.4.0</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license uri="http://www.gnu.org/copyleft/lesser.html">GNU Lesser General Public License</license>
 <notes>
1.4.1
  * Reintroduce include_path to composer.json
 </notes>
 <contents>
  <dir baseinstalldir="File" name="/">
   <file baseinstalldir="/" md5sum="ffe2590635f404af055fe731da105939" name="File/MARC/Lint/CodeData.php" role="php" />
   <file baseinstalldir="/" md5sum="a3b9e1c817e67f59add05593500d463e" name="File/MARC/Control_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="acba4463f8e40d6ee4e7ba1f2dc53123" name="File/MARC/Data_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="378f483ec1fd161cd9dfb9b05db58d66" name="File/MARC/Exception.php" role="php" />
   <file baseinstalldir="/" md5sum="a9ba69030cbf4847292b9975e9d922c6" name="File/MARC/Field.php" role="php" />
   <file baseinstalldir="/" md5sum="c37351c7c80927ce6bb1e662510f9183" name="File/MARC/Lint.php" role="php" />
   <file baseinstalldir="/" md5sum="c5ac39e3d25eb0108b9dd5ad8466c821" name="File/MARC/List.php" role="php" />
   <file baseinstalldir="/" md5sum="7af6ce78cde4bb246e4e96709e90d2c0" name="File/MARC/Record.php" role="php" />
   <file baseinstalldir="/" md5sum="df5f97139685f0ad04e47fdbb67e3968" name="File/MARC/Subfield.php" role="php" />
   <file baseinstalldir="/" md5sum="6e102262dfd5d65d8d5a6221dfc74edd" name="File/MARC.php" role="php" />
   <file baseinstalldir="/" md5sum="8b64040d2d18ac4b994595a148266a66" name="File/MARCBASE.php" role="php" />
   <file baseinstalldir="/" md5sum="f5a17a60d34e84e2ee7ca1e5c5c6c620" name="File/MARCXML.php" role="php" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="examples/example.mrc" role="doc" />
   <file baseinstalldir="File" md5sum="1aea40df9f1c2e32f8e065fe8da0a3b5" name="examples/marc_yaz.php" role="doc" />
   <file baseinstalldir="File" md5sum="70ae317e0890d5896e3ffccdd293369a" name="examples/read.php" role="doc" />
   <file baseinstalldir="File" md5sum="54efb9d920ac775bfc847a83a2dec73a" name="examples/subfields.php" role="doc" />
   <file baseinstalldir="File" md5sum="14297da35b510c496cd1f328cf3bb301" name="tests/bad_example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="0dd4c6dbad6e8608d0ebf9d24425955d" name="tests/bad_example.xml" role="test" />
   <file baseinstalldir="File" md5sum="216a6f9d53f6d3d8e22d81fdc10f4bc1" name="tests/camel.mrc" role="test" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="tests/example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="9455aec3371f79cf7d31281fd03f5171" name="tests/marc_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="577e2f5f89fd48cf1a3576a29d2958f8" name="tests/marc_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a6a586354b9a06c880c2a7470dd828d7" name="tests/marc_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1c7e2fc5572a0f9362a771c260a1fe3" name="tests/marc_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="84f85ac7f8a2532e4e90ccde7764556a" name="tests/marc_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="889e5e906a97de7a0e94b0c5f30e70e7" name="tests/marc_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="be823dc8a8efb408de06371ab802efcc" name="tests/marc_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="af44490aafea44e5120f881cb81cdad9" name="tests/marc_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ac9f2a7aeb24900a11f5102744179ae3" name="tests/marc_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5e43eb5cddbb4f2bd0d6405cd95b80aa" name="tests/marc_010.phpt" role="test" />
   <file baseinstalldir="File" md5sum="2e1cd8509c0bf04ec77fc0f51375f611" name="tests/marc_011.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bc49ca48623102c8ac07679fa77a3dd9" name="tests/marc_012.phpt" role="test" />
   <file baseinstalldir="File" md5sum="245a3b20e0da1973535503e28efd1d3a" name="tests/marc_013.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ce69aa734856dd40d60d30c77bdef53a" name="tests/marc_014.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7b61cdd31035e60682fa92c5d519d997" name="tests/marc_015.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7f4f597fe1adaa3507eb87fc4875dbd2" name="tests/marc_016.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4262efd5fcacbd7503323681f4552430" name="tests/marc_017.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ee1623d7bda54ba4f741b2319b158f82" name="tests/marc_018.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8006c03fbab0f04377342086fafd3982" name="tests/marc_019.phpt" role="test" />
   <file baseinstalldir="File" md5sum="f5ae5b25e0ac1104314433d9e5b1f7fe" name="tests/marc_020.phpt" role="test" />
   <file baseinstalldir="File" md5sum="94d8f99e86585671a1b2d3043aeb6360" name="tests/marc_021.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bb891a890effe0e77e1759043f4846d8" name="tests/marc_022.phpt" role="test" />
   <file baseinstalldir="File" md5sum="faf77dcb5cdd002c09169a14bfded65e" name="tests/marc_023.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0e6c4a23f5da7df64fdd4b3b1149bbee" name="tests/marc_16783.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4ea8b3520beda378db15960f1c50493a" name="tests/marc_field_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="743850ef61df69c4340be44a03bccb5a" name="tests/marc_field_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8c765f1398b49df257d86d22ac6e4f8d" name="tests/marc_field_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d4216cf930a308e0d02553bd3914f294" name="tests/marc_field_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dd59514b474b78371ad522a3e13b76b7" name="tests/marc_field_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5295bfd02a8424acac1c91de26b552c7" name="tests/marc_field_21246.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6f95f09442ccf6b93df92986f58b270d" name="tests/marc_lint_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="18d721f8871edd925624ccbdd15444fb" name="tests/marc_lint_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4eb86a2f4e0a74dedcb0bf2511da6ca1" name="tests/marc_lint_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="10430fee0a1352d0528f1507b34c57e1" name="tests/marc_lint_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0dcd07a18577d7b22392a2214cd6436c" name="tests/marc_lint_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fd17798fc535562e5e64461f449516b2" name="tests/marc_record_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="141b455ccf67a60c4eac44c77960f2e2" name="tests/marc_subfield_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1e23464ee0eec47ddca2af9a9922926" name="tests/marc_subfield_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="1d7903e8c244d647220b318b4bc758d1" name="tests/marc_xml_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="22cae3c752d843b78f583dcd92801534" name="tests/marc_xml_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="c0716d23e0f960abf8d53ad6014a413a" name="tests/marc_xml_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7645fa19e28aca041a124fc5e2c12bd3" name="tests/marc_xml_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b08b28c3251625b8b6e4d7ab376b0185" name="tests/marc_xml_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6cd0934ddbf65d2d7e9ea5d108977ff7" name="tests/marc_xml_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ffdce4aa190268fa7cbbf3bb45383abf" name="tests/marc_xml_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="998a4c1ce00ff100f39ffa9fc49a212f" name="tests/marc_xml_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a38a67c590869f2b0a4859a910fd9e89" name="tests/marc_xml_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="db39c5055a570fcda12bb7c5fa1e3b4d" name="tests/marc_xml_16642.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dc075f4a271bd7182378a3874bd5b39e" name="tests/marc_xml_namespace.phpt" role="test" />
   <file baseinstalldir="File" md5sum="208200d9a979ac360c4d326e9789b6b7" name="tests/marc_xml_namespace_prefix.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d87774ede82222cfc12b2c2a06f57a3a" name="tests/marc_xml_rsinger.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fb44e3eb69f1a37115235fc829c39542" name="tests/namespace.xml" role="test" />
   <file baseinstalldir="File" md5sum="e6de4d809b0af5dd99fd352eb60616a1" name="tests/skipif.inc" role="test" />
   <file baseinstalldir="File" md5sum="a0166a4ff0bc0bb283e854f11beaa793" name="tests/music.mrc" role="test" />
   <file baseinstalldir="File" md5sum="993ce494befbc25dc1326527b30b4782" name="tests/music.xml" role="test" />
   <file baseinstalldir="File" md5sum="6b0c87f0cd459ed7322c25d403b164cc" name="tests/bigarchive.xml" role="test" />
   <file baseinstalldir="File" md5sum="be850aa6ab4ac52b8c6c214c30b574af" name="tests/onerecord.xml" role="test" />
   <file baseinstalldir="File" md5sum="4f43fec7b276267eec5258044853ccc8" name="tests/sandburg.mrc" role="test" />
   <file baseinstalldir="File" md5sum="e216b95f905dd240c9bde372950e4073" name="tests/sandburg.xml" role="test" />
   <file baseinstalldir="File" md5sum="e81a92188ea0dcd9c108a63fb32b3f4f" name="tests/xmlescape.mrc" role="test" />
   <file baseinstalldir="File" md5sum="8f9f63ed6a80191d89a2296fa4c1a30b" name="CHANGELOG" role="doc" />
   <file baseinstalldir="File" md5sum="fbc093901857fcd118f065f900982c24" name="LICENSE" role="doc" />
  </dir>
 </contents>
 <dependencies>
  <required>
   <php>
    <min>5.6</min>
   </php>
   <pearinstaller>
    <min>1.4.0</min>
   </pearinstaller>
  </required>
  <optional>
   <package>
    <name>Validate_ISPN</name>
    <channel>pear.php.net</channel>
   </package>
  </optional>
 </dependencies>
 <phprelease />
</package>
PKm�ZPi��.depdbnu�[���PKm�Z�{��
�Mail/null.phpnu�[���PKm�ZE@�%>>
Mail/sendmail.phpnu�[���PKm�Z��A~�{�{�;Mail/RFC822.phpnu�[���PKn�Z�+V����
[�Mail/mime.phpnu�[���PKn�Zx�ع���D�Mail/mimeDecode.phpnu�[���PKn�ZB�_Ǭ=�=
@(Mail/smtp.phpnu�[���PKn�ZwԐE;E;)fMail/smtpmx.phpnu�[���PKn�Z�؛�J�J���Mail/mimePart.phpnu�[���PKn�ZB��shh
8YMail/mock.phpnu�[���PKn�Z@iE�\\
�lMail/mail.phpnu�[���PKn�Zv�.locknu�[���PKn�Z�*�z%-%- ��Structures/LinkedList/Double.phpnu�[���PKn�Z����p:p:  �Structures/LinkedList/Single.phpnu�[���PKn�ZUyv���Structures/Graph.phpnu�[���PKn�Z�C� + +CStructures/Graph/Node.phpnu�[���PKn�Z9����,�1Structures/Graph/Manipulator/AcyclicTest.phpnu�[���PKn�Z~(�htt2�HStructures/Graph/Manipulator/TopologicalSorter.phpnu�[���PKn�Z�J�}
}
_dAuth/SASL/Anonymous.phpnu�[���PKn�ZP(~�T
T
#rAuth/SASL/CramMD5.phpnu�[���PKn�Z����==�Auth/SASL/Plain.phpnu�[���PKn�Z�<� OO<�Auth/SASL/Login.phpnu�[���PKn�Z%ׅtg!g!ΘAuth/SASL/DigestMD5.phpnu�[���PKn�Z�T�|�Auth/SASL/Common.phpnu�[���PKn�ZvR�r,,��Auth/SASL/External.phpnu�[���PKn�Zќ��0�0H�Auth/SASL/SCRAM.phpnu�[���PKn�Z2r����
�	Auth/SASL.phpnu�[���PKn�Z�T�,�,�OS/Guess.phpnu�[���PKn�Z�����KPEAR/Config.phpnu�[���PKn�Z�`�eEAEA
.ZPEAR/REST.phpnu�[���PKn�Z��ym6m6��PEAR/Exception.phpnu�[���PKn�Zr"����_�PEAR/ChannelFile.phpnu�[���PKn�Z��gk�U�U?�PEAR/Validate.phpnu�[���PKn�Zd֣S��u�PEAR/Command/Pickle.xmlnu�[���PKn�Z�z��k<k<W�PEAR/Command/Config.phpnu�[���PKn�Z݄<ii	1PEAR/Command/Mirror.xmlnu�[���PKn�Z,��t"u"u�3PEAR/Command/Remote.phpnu�[���PKn�Z
�\���"�PEAR/Command/Remote.xmlnu�[���PKn�Zj���!�!X�PEAR/Command/Install.xmlnu�[���PKo�Z�%q������PEAR/Command/Channels.phpnu�[���PKo�Znmi?;�;��[	PEAR/Command/Install.phpnu�[���PKo�Z�X�

#
PEAR/Command/Auth.phpnu�[���PKo�Z���s6
6
T-
PEAR/Command/Config.xmlnu�[���PKo�Z�%Fii�:
PEAR/Command/Test.xmlnu�[���PKo�ZZ h66A
PEAR/Command/Package.xmlnu�[���PKo�Z�w��zz�]
PEAR/Command/Channels.xmlnu�[���PKo�Z+9ҜҜ�n
PEAR/Command/Package.phpnu�[���PKo�Z
u����PEAR/Command/Build.xmlnu�[���PKo�Z������
PEAR/Command/Mirror.phpnu�[���PKp�Z,_�h/h/�PEAR/Command/Test.phpnu�[���PKp�Z�%sp  6OPEAR/Command/Common.phpnu�[���PKp�Z0(;rʹʹ�oPEAR/Command/Registry.phpnu�[���PKp�Z�4�{���$PEAR/Command/Auth.xmlnu�[���PKp�Z��#S
S
�)PEAR/Command/Build.phpnu�[���PKp�Z���u��S4PEAR/Command/Registry.xmlnu�[���PKp�Z�P>>�;PEAR/Command/Pickle.phpnu�[���PKp�Z��T�I�I�yPEAR/Builder.phpnu�[���PKp�Z[
�W��3�PEAR/XMLParser.phpnu�[���PKp�Zl(e���t�PEAR/Downloader.phpnu�[���PKp�Z�b������
PEAR/ErrorStack.phpnu�[���PKp�Z(Pz����ePEAR/Proxy.phpnu�[���PKp�Z��'����|PEAR/RunTest.phpnu�[���PKq�Zj�y99�	PEAR/Validator/PECL.phpnu�[���PKq�Zp�����aPEAR/Dependency2.phpnu�[���PKq�Z��wv@@��PEAR/PackageFile/v2.phpnu�[���PKq�ZC�8�L�L!:�PEAR/PackageFile/v2/Validator.phpnu�[���PKq�Z���=_�_�6PEAR/PackageFile/v2/rw.phpnu�[���PKq�Z�5�������,PEAR/PackageFile/v1.phpnu�[���PKq�Z�ɁɁ!��PEAR/PackageFile/Generator/v2.phpnu�[���PKq�Z`�=����!�tPEAR/PackageFile/Generator/v1.phpnu�[���PKr�Z��OWHH�9PEAR/PackageFile/Parser/v2.phpnu�[���PKr�Z�_=�@�@`FPEAR/PackageFile/Parser/v1.phpnu�[���PKr�Zc��__5�PEAR/DependencyDB.phpnu�[���PKr�Z�@P��{�PEAR/ChannelFile/Parser.phpnu�[���PKr�Z��_�0�0r�PEAR/Command.phpnu�[���PKr�Z�ٲ�=�==PEAR/PackageFile.phpnu�[���PKr�Z�JD��g\PEAR/Task/Replace.phpnu�[���PKr�Z&%75))�wPEAR/Task/Windowseol/rw.phpnu�[���PKr�Z�3}}PEAR/Task/Replace/rw.phpnu�[���PKr�Z&
i."x�PEAR/Task/Postinstallscript/rw.phpnu�[���PKr�Z�-!�PEAR/Task/Common.phpnu�[���PKr�ZD$���I�PEAR/Task/Windowseol.phpnu�[���PKr�ZZ�E�x9x9��PEAR/Task/Postinstallscript.phpnu�[���PKr�Z\k��K�PEAR/Task/Unixeol/rw.phpnu�[���PKr�Z�������PEAR/Task/Unixeol.phpnu�[���PKr�Z�W�f���PEAR/REST/10.phpnu�[���PKr�Z��Y�;;ąPEAR/REST/13.phpnu�[���PKr�Z,#y��+�+�PEAR/REST/11.phpnu�[���PKr�Z��U  D�PEAR/Packager.phpnu�[���PKr�ZZ�bgbg�PEAR/Common.phpnu�[���PKr�Z$���(�(FsPEAR/Registry.phpnu�[���PKr�Z��	MdMd?�PEAR/Frontend/CLI.phpnu�[���PKr�Z��

�PEAR/Installer/Role/Doc.phpnu�[���PKr�Z��/��)PEAR/Installer/Role/Cfg.xmlnu�[���PKr�Z>1H���PEAR/Installer/Role/Www.xmlnu�[���PKr�Z�?m

PEAR/Installer/Role/Php.phpnu�[���PKr�Z*Y|	%%`PEAR/Installer/Role/Man.phpnu�[���PKr�Z���BB�PEAR/Installer/Role/Ext.xmlnu�[���PKr�Zp��""]PEAR/Installer/Role/Src.xmlnu�[���PKr�Zh&P*���PEAR/Installer/Role/Doc.xmlnu�[���PKr�ZB] ���PEAR/Installer/Role/Test.xmlnu�[���PKr�Zz�q����PEAR/Installer/Role/Php.xmlnu�[���PKr�Z	��
|PEAR/Installer/Role/Data.phpnu�[���PKs�Z�0�c���PEAR/Installer/Role/Man.xmlnu�[���PKs�Z��K

�PEAR/Installer/Role/Ext.phpnu�[���PKs�ZY��� PEAR/Installer/Role/Test.phpnu�[���PKs�Z@v�а�z#PEAR/Installer/Role/Script.xmlnu�[���PKs�Zf�sz��x%PEAR/Installer/Role/Data.xmlnu�[���PKs�Z?���GGV'PEAR/Installer/Role/Common.phpnu�[���PKs�Z�^D{		�?PEAR/Installer/Role/Www.phpnu�[���PKs�Z�Ƥ?CPEAR/Installer/Role/Cfg.phpnu�[���PKs�Z��[�	SPEAR/Installer/Role/Script.phpnu�[���PKs�Z��srrjVPEAR/Installer/Role/Src.phpnu�[���PKs�ZV�Z���'ZPEAR/Installer/Role.phpnu�[���PKs�Z�{�	�)�)*yPEAR/Downloader/Package.phpnu�[���PKs�Z.�4���$�PEAR/Frontend.phpnu�[���PKs�Z،�w��_�PEAR/Installer.phpnu�[���PKs�ZXxo��-j�Symfony/Bridge/Doctrine/Logger/DbalLogger.phpnu�[���PKs�Ze�OO&b�Symfony/Bridge/Doctrine/autoloader.phpnu�[���PKs�Z��X+��8�Symfony/Bridge/Doctrine/CacheWarmer/ProxyCacheWarmer.phpnu�[���PKs�Z	�9,��5i�Symfony/Bridge/Doctrine/Form/DoctrineOrmExtension.phpnu�[���PKs�Z�0���NX�Symfony/Bridge/Doctrine/Form/EventListener/MergeDoctrineCollectionListener.phpnu�[���PKs�Z!%d==A��Symfony/Bridge/Doctrine/Form/ChoiceList/EntityLoaderInterface.phpnu�[���PKs�Z�	?x�7�7<4�Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.phpnu�[���PKs�ZGC�t��A<-Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.phpnu�[���PKs�Z`.
qpp7�9Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.phpnu�[���PKs�ZCi�PPMZQSymfony/Bridge/Doctrine/Form/DataTransformer/CollectionToArrayTransformer.phpnu�[���PKs�Z憝��0'YSymfony/Bridge/Doctrine/Form/Type/EntityType.phpnu�[���PKs�ZS;,:��2-]Symfony/Bridge/Doctrine/Form/Type/DoctrineType.phpnu�[���PKs�ZW&v��<�wSymfony/Bridge/Doctrine/Security/User/EntityUserProvider.phpnu�[���PKs�Z�����Et�Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.phpnu�[���PKs�Z(��y��9�Symfony/Bridge/Doctrine/Validator/DoctrineInitializer.phpnu�[���PKs�ZQГ��>�Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.phpnu�[���PKs�Z:�d�G5�Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.phpnu�[���PKs�Z�Ta�==B��Symfony/Bridge/Doctrine/ExpressionLanguage/DoctrineParserCache.phpnu�[���PKs�Z��qm
m
-m�Symfony/Bridge/Doctrine/RegistryInterface.phpnu�[���PKs�Zlf/�qq=7�Symfony/Bridge/Doctrine/DataFixtures/ContainerAwareLoader.phpnu�[���PKs�Z����=�Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.phpnu�[���PKs�Z�����C��Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerSchema.phpnu�[���PKs�ZOlQ�996��Symfony/Bridge/Doctrine/ContainerAwareEventManager.phpnu�[���PKs�Z؈����3D�Symfony/Bridge/Doctrine/Test/DoctrineTestHelper.phpnu�[���PKs�Z̳֨�+��Symfony/Bridge/Doctrine/ManagerRegistry.phpnu�[���PKs�Z+çxAA?�Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.phpnu�[���PKs�Z*�+��J�JIBSymfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.phpnu�[���PKs�Z���*��SVaSymfony/Bridge/Doctrine/DependencyInjection/Security/UserProvider/EntityFactory.phpnu�[���PKs�Z��㛕�Q�hSymfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterMappingsPass.phpnu�[���PKs�Z~�YAAeԀSymfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.phpnu�[���PKs�Z��,���S��Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/DoctrineValidationPass.phpnu�[���PKs�Z��4NN%,�Symfony/Bridge/Monolog/autoloader.phpnu�[���PKs�Z��մ��1ϡSymfony/Bridge/Monolog/Handler/FirePHPHandler.phpnu�[���PKs�Z��Zv��/©Symfony/Bridge/Monolog/Handler/DebugHandler.phpnu�[���PKs�Z�y���1دSymfony/Bridge/Monolog/Handler/ConsoleHandler.phpnu�[���PKs�Z��*vv5�Symfony/Bridge/Monolog/Handler/SwiftMailerHandler.phpnu�[���PKs�Z���"II3��Symfony/Bridge/Monolog/Handler/ChromePhpHandler.phpnu�[���PKs�Z��;��	�	!��Symfony/Bridge/Monolog/Logger.phpnu�[���PKs�Z��b115��Symfony/Bridge/Monolog/Formatter/ConsoleFormatter.phpnu�[���PKt�Z�,��1l�Symfony/Bridge/Monolog/Processor/WebProcessor.phpnu�[���PKt�Z�$�KK"l�Symfony/Bridge/Twig/autoloader.phpnu�[���PKt�Z�)�UU1	�Symfony/Bridge/Twig/Translation/TwigExtractor.phpnu�[���PKt�Z6DZ77*��Symfony/Bridge/Twig/Node/StopwatchNode.phpnu�[���PKt�Z,
�@��5P�Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.phpnu�[���PKt�Z�
�s>>*ESymfony/Bridge/Twig/Node/FormThemeNode.phpnu�[���PKt�ZP�IAA3�Symfony/Bridge/Twig/Node/TransDefaultDomainNode.phpnu�[���PKt�Z�U,tt,�Symfony/Bridge/Twig/Node/FormEnctypeNode.phpnu�[���PKt�Zʦ\�G
G
&QSymfony/Bridge/Twig/Node/TransNode.phpnu�[���PKt�Z���^��,�%Symfony/Bridge/Twig/Node/RenderBlockNode.phpnu�[���PKt�Z�vq�)+Symfony/Bridge/Twig/Form/TwigRenderer.phpnu�[���PKt�Zb�3�}}8q1Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.phpnu�[���PKt�Z��Qkk2V4Symfony/Bridge/Twig/Form/TwigRendererInterface.phpnu�[���PKt�Z��<��/#7Symfony/Bridge/Twig/Form/TwigRendererEngine.phpnu�[���PKt�Z�GTSymfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.phpnu�[���PKt�Z�)�[n	n	)�`Symfony/Bridge/Twig/NodeVisitor/Scope.phpnu�[���PKt�Z�tA�:`jSymfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.phpnu�[���PKt�Z��9292B�xSymfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twignu�[���PKt�Z��[[Dy�Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twignu�[���PKt�Z.��8H�Symfony/Bridge/Twig/TokenParser/StopwatchTokenParser.phpnu�[���PKt�Z�%]�
�
4��Symfony/Bridge/Twig/TokenParser/TransTokenParser.phpnu�[���PKt�Z�/�	�	:��Symfony/Bridge/Twig/TokenParser/TransChoiceTokenParser.phpnu�[���PKt�Z>����8>�Symfony/Bridge/Twig/TokenParser/FormThemeTokenParser.phpnu�[���PKt�Zʶ�̭�Ao�Symfony/Bridge/Twig/TokenParser/TransDefaultDomainTokenParser.phpnu�[���PKt�Z�9�=KK/��Symfony/Bridge/Twig/Extension/FormExtension.phpnu�[���PKt�Z��|/7�Symfony/Bridge/Twig/Extension/YamlExtension.phpnu�[���PKt�Z��&�a
a
5��Symfony/Bridge/Twig/Extension/HttpKernelExtension.phpnu�[���PKt�ZKΙ���5v�Symfony/Bridge/Twig/Extension/ExpressionExtension.phpnu�[���PKt�Z`�fS..2� Symfony/Bridge/Twig/Extension/RoutingExtension.phpnu�[���PKt�Z�5��mm4] Symfony/Bridge/Twig/Extension/StopwatchExtension.phpnu�[���PKt�Z�?���6. Symfony/Bridge/Twig/Extension/TranslationExtension.phpnu�[���PKt�Zd���oo3�! Symfony/Bridge/Twig/Extension/SecurityExtension.phpnu�[���PKt�Z�����/a' Symfony/Bridge/Twig/Extension/CodeExtension.phpnu�[���PKu�Z^D��dd"sG Symfony/Bridge/Twig/TwigEngine.phpnu�[���PKu�Z�4˵��()V Symfony/Component/Finder/Shell/Shell.phpnu�[���PKu�Z5��K��*^ Symfony/Component/Finder/Shell/Command.phpnu�[���PKu�Z�5�9(�v Symfony/Component/Finder/SplFileInfo.phpnu�[���PKu�Z%uM�PP'X~ Symfony/Component/Finder/autoloader.phpnu�[���PKu�Z��99C� Symfony/Component/Finder/Exception/ShellCommandFailureException.phpnu�[���PKu�Z�7��9�� Symfony/Component/Finder/Exception/ExceptionInterface.phpnu�[���PKu�Z�cWޫ�<� Symfony/Component/Finder/Exception/AccessDeniedException.phpnu�[���PKu�Z>�@��>� Symfony/Component/Finder/Exception/AdapterFailureException.phpnu�[���PKu�ZP�����D	� Symfony/Component/Finder/Exception/OperationNotPermitedException.phpnu�[���PKu�Z��� ��6� Symfony/Component/Finder/Comparator/DateComparator.phpnu�[���PKu�Z|F�z

2?� Symfony/Component/Finder/Comparator/Comparator.phpnu�[���PKu�Z�P�

8�� Symfony/Component/Finder/Comparator/NumberComparator.phpnu�[���PKu�Z�g@Mbb!2� Symfony/Component/Finder/Glob.phpnu�[���PKu�Z�d�V�V#� Symfony/Component/Finder/Finder.phpnu�[���PKu�Zils_��>
!Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.phpnu�[���PKu�Z��ɔ�
�
7u!Symfony/Component/Finder/Iterator/FilePathsIterator.phpnu�[���PKu�Z�,G��4n!Symfony/Component/Finder/Iterator/FilterIterator.phpnu�[���PKu�Z�ʽ���?q#!Symfony/Component/Finder/Iterator/FilecontentFilterIterator.phpnu�[���PKu�Z�

���@~+!Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.phpnu�[���PKu�Z��z":�2!Symfony/Component/Finder/Iterator/CustomFilterIterator.phpnu�[���PKu�Z{�^ǽ�<N9!Symfony/Component/Finder/Iterator/FilenameFilterIterator.phpnu�[���PKu�Z�d����Dw@!Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.phpnu�[���PKu�Zx�P���=�F!Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.phpnu�[���PKu�Z ��U��=�L!Symfony/Component/Finder/Iterator/DateRangeFilterIterator.phpnu�[���PKu�Z�n bb<�R!Symfony/Component/Finder/Iterator/FileTypeFilterIterator.phpnu�[���PKu�Z��j��	�	6�X!Symfony/Component/Finder/Iterator/SortableIterator.phpnu�[���PKu�Z���)��8�b!Symfony/Component/Finder/Iterator/PathFilterIterator.phpnu�[���PKu�Z�6s��@�j!Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.phpnu�[���PKu�Z��&
&
2Gw!Symfony/Component/Finder/Expression/Expression.phpnu�[���PKu�Z�"HH6ρ!Symfony/Component/Finder/Expression/ValueInterface.phpnu�[���PKu�Z�E�,}�!Symfony/Component/Finder/Expression/Glob.phpnu�[���PKu�Z��(�-�!Symfony/Component/Finder/Expression/Regex.phpnu�[���PKu�Z9!�2{
{
/D�!Symfony/Component/Finder/Adapter/PhpAdapter.phpnu�[���PKu�Z����5�!Symfony/Component/Finder/Adapter/AdapterInterface.phpnu�[���PKu�Z��kA�
�
34�!Symfony/Component/Finder/Adapter/BsdFindAdapter.phpnu�[���PKu�Z�}]�
�
3��!Symfony/Component/Finder/Adapter/GnuFindAdapter.phpnu�[���PKu�ZQJ)�)8��!Symfony/Component/Finder/Adapter/AbstractFindAdapter.phpnu�[���PKu�Z�	4�"Symfony/Component/Finder/Adapter/AbstractAdapter.phpnu�[���PKu�Z����:;"Symfony/Component/Translation/Extractor/ChainExtractor.phpnu�[���PKu�ZArP�>%"Symfony/Component/Translation/Extractor/ExtractorInterface.phpnu�[���PKu�Zb*0�oo4�#"Symfony/Component/Translation/PluralizationRules.phpnu�[���PKu�Z�q��UU,<"Symfony/Component/Translation/autoloader.phpnu�[���PKu�Z�<qNN10>"Symfony/Component/Translation/MessageSelector.phpnu�[���PKu�Z�س��:�J"Symfony/Component/Translation/Catalogue/MergeOperation.phpnu�[���PKu�ZY[�>*P"Symfony/Component/Translation/Catalogue/OperationInterface.phpnu�[���PKu�Z��fb�
�
=�U"Symfony/Component/Translation/Catalogue/AbstractOperation.phpnu�[���PKu�Z��ӄ�9�c"Symfony/Component/Translation/Catalogue/DiffOperation.phpnu�[���PKu�Z�6�"��>�i"Symfony/Component/Translation/Exception/ExceptionInterface.phpnu�[���PKu�ZDŽ���D�k"Symfony/Component/Translation/Exception/InvalidResourceException.phpnu�[���PKv�Z�2B��E2n"Symfony/Component/Translation/Exception/NotFoundResourceException.phpnu�[���PKv�Z�y4��2�p"Symfony/Component/Translation/MessageCatalogue.phpnu�[���PKv�Z%�Mt8��"Symfony/Component/Translation/MetadataAwareInterface.phpnu�[���PKv�Z�d�<<4��"Symfony/Component/Translation/IdentityTranslator.phpnu�[���PKv�Z�e�G��,��"Symfony/Component/Translation/Translator.phpnu�[���PKv�Z��֛�;u�"Symfony/Component/Translation/MessageCatalogueInterface.phpnu�[���PKv�ZM�
���9{�"Symfony/Component/Translation/Dumper/IcuResFileDumper.phpnu�[���PKv�Zਪ(5u�"Symfony/Component/Translation/Dumper/PoFileDumper.phpnu�[���PKv�Z���%LL6��"Symfony/Component/Translation/Dumper/PhpFileDumper.phpnu�[���PKv�Z�<̧��8��"Symfony/Component/Translation/Dumper/XliffFileDumper.phpnu�[���PKv�Z>{GG5��"Symfony/Component/Translation/Dumper/QtFileDumper.phpnu�[���PKv�Z���667Z�"Symfony/Component/Translation/Dumper/YamlFileDumper.phpnu�[���PKv�ZoB���6��"Symfony/Component/Translation/Dumper/CsvFileDumper.phpnu�[���PKv�ZB^�[[3*�"Symfony/Component/Translation/Dumper/FileDumper.phpnu�[���PKv�Z�:$}}7�"Symfony/Component/Translation/Dumper/JsonFileDumper.phpnu�[���PKv�Z&X����6�#Symfony/Component/Translation/Dumper/IniFileDumper.phpnu�[���PKv�Z��<**8
#Symfony/Component/Translation/Dumper/DumperInterface.phpnu�[���PKv�Z����A	A	5�#Symfony/Component/Translation/Dumper/MoFileDumper.phpnu�[���PKv�Zg�?Z�
�
*B#Symfony/Component/Translation/Interval.phpnu�[���PKv�Z�3����5�#Symfony/Component/Translation/TranslatorInterface.phpnu�[���PKv�ZP�?�}}:�%#Symfony/Component/Translation/Writer/TranslationWriter.phpnu�[���PKv�ZN@���6�-#Symfony/Component/Translation/Loader/IniFileLoader.phpnu�[���PKv�Z�T�93#Symfony/Component/Translation/Loader/IcuDatFileLoader.phpnu�[���PKv�ZCS�z
z
9�9#Symfony/Component/Translation/Loader/IcuResFileLoader.phpnu�[���PKv�Z��v���5�D#Symfony/Component/Translation/Loader/MoFileLoader.phpnu�[���PKv�ZR����4&\#Symfony/Component/Translation/Loader/ArrayLoader.phpnu�[���PKv�Z�'s�u	u	7&d#Symfony/Component/Translation/Loader/JsonFileLoader.phpnu�[���PKv�Z�i�3"
"
6n#Symfony/Component/Translation/Loader/CsvFileLoader.phpnu�[���PKv�Z_��BB8�x#Symfony/Component/Translation/Loader/XliffFileLoader.phpnu�[���PKv�Zl#�tt84�#Symfony/Component/Translation/Loader/LoaderInterface.phpnu�[���PKv�Z�*���5�#Symfony/Component/Translation/Loader/PoFileLoader.phpnu�[���PKv�Z�r��;;6o�#Symfony/Component/Translation/Loader/PhpFileLoader.phpnu�[���PKv�Z:�	Z�"�"B�#Symfony/Component/Translation/Loader/schema/dic/xliff-core/xml.xsdnu�[���PKv�Z�xO��T�#Symfony/Component/Translation/Loader/schema/dic/xliff-core/xliff-core-1.2-strict.xsdnu�[���PKv�Z)-d+�	�	5�g%Symfony/Component/Translation/Loader/QtFileLoader.phpnu�[���PKv�Z:����7�q%Symfony/Component/Translation/Loader/YamlFileLoader.phpnu�[���PKw�Z�V�˽�.-z%Symfony/Component/Routing/Annotation/Route.phpnu�[���PKw�Z�<ѹ�+H�%Symfony/Component/Routing/CompiledRoute.phpnu�[���PKw�ZU8���-\�%Symfony/Component/Routing/RouterInterface.phpnu�[���PKw�ZU�cQQ(>�%Symfony/Component/Routing/autoloader.phpnu�[���PKw�Z����'�'+�%Symfony/Component/Routing/RouteCompiler.phpnu�[���PKw�Z��%�%$�%Symfony/Component/Routing/Router.phpnu�[���PKw�Z���q
q
6n�%Symfony/Component/Routing/Matcher/ApacheUrlMatcher.phpnu�[���PKw�Z	�ڗ9E�%Symfony/Component/Routing/Matcher/UrlMatcherInterface.phpnu�[���PKw�Z`�u���=��%Symfony/Component/Routing/Matcher/RequestMatcherInterface.phpnu�[���PKw�Z[z�dd<�&Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.phpnu�[���PKw�Z?�|{��:�&Symfony/Component/Routing/Matcher/Dumper/MatcherDumper.phpnu�[���PKw�Z�x}�44=�&Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.phpnu�[���PKw�Z�bz#z#@A&Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.phpnu�[���PKw�Z�`=e&Symfony/Component/Routing/Matcher/Dumper/DumperCollection.phpnu�[���PKw�Z�N�
�
C�s&Symfony/Component/Routing/Matcher/Dumper/DumperPrefixCollection.phpnu�[���PKw�Z(� ���C�~&Symfony/Component/Routing/Matcher/Dumper/MatcherDumperInterface.phpnu�[���PKw�ZY�IWW8��&Symfony/Component/Routing/Matcher/Dumper/DumperRoute.phpnu�[���PKw�Z�'��9��&Symfony/Component/Routing/Matcher/TraceableUrlMatcher.phpnu�[���PKw�ZGj�C""0��&Symfony/Component/Routing/Matcher/UrlMatcher.phpnu�[���PKw�Z� ��ffE'�&Symfony/Component/Routing/Matcher/RedirectableUrlMatcherInterface.phpnu�[���PKw�Z����==K�&Symfony/Component/Routing/Exception/MissingMandatoryParametersException.phpnu�[���PKw�Zj`j�A��&Symfony/Component/Routing/Exception/InvalidParameterException.phpnu�[���PKw�Znj�W��>/�&Symfony/Component/Routing/Exception/RouteNotFoundException.phpnu�[���PKw�Z��)���:��&Symfony/Component/Routing/Exception/ExceptionInterface.phpnu�[���PKw�Z����JJA��&Symfony/Component/Routing/Exception/MethodNotAllowedException.phpnu�[���PKw�Z?�]�//Af�&Symfony/Component/Routing/Exception/ResourceNotFoundException.phpnu�[���PKw�Z��^�==#�&Symfony/Component/Routing/Route.phpnu�[���PKw�Zr�����:i	'Symfony/Component/Routing/RequestContextAwareInterface.phpnu�[���PKw�Z|,{Ȫ�-p'Symfony/Component/Routing/RouteCollection.phpnu�[���PKw�Z�h�,w)'Symfony/Component/Routing/RequestContext.phpnu�[���PKw�Zմ���I�C'Symfony/Component/Routing/Generator/ConfigurableRequirementsInterface.phpnu�[���PKw�Z�
��1�148M'Symfony/Component/Routing/Generator/UrlGenerator.phpnu�[���PKw�Z�1O�
�
Az'Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.phpnu�[���PKw�Zu�'��>��'Symfony/Component/Routing/Generator/Dumper/GeneratorDumper.phpnu�[���PKw�Z�4��G��'Symfony/Component/Routing/Generator/Dumper/GeneratorDumperInterface.phpnu�[���PKw�Z����@@=�'Symfony/Component/Routing/Generator/UrlGeneratorInterface.phpnu�[���PKw�Zn���hh2Ȥ'Symfony/Component/Routing/Loader/ClosureLoader.phpnu�[���PKw�Z��?�		>��'Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.phpnu�[���PKw�Z~ޟ
�
9�'Symfony/Component/Routing/Loader/AnnotationFileLoader.phpnu�[���PKw�Z~L�W��:�'Symfony/Component/Routing/Loader/AnnotationClassLoader.phpnu�[���PKw�ZP�i{��2��'Symfony/Component/Routing/Loader/PhpFileLoader.phpnu�[���PKw�Z?-[��	�	?5�'Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsdnu�[���PKw�Zأ2D$D$2L�'Symfony/Component/Routing/Loader/XmlFileLoader.phpnu�[���PKw�ZpB�Q Q 3�(Symfony/Component/Routing/Loader/YamlFileLoader.phpnu�[���PKx�ZqF��>>4�5(Symfony/Component/Routing/RouteCompilerInterface.phpnu�[���PKx�Z0���QQ(H9(Symfony/Component/Process/autoloader.phpnu�[���PKx�Zg��'�'*�:(Symfony/Component/Process/ProcessPipes.phpnu�[���PKx�Z��2�{{@6c(Symfony/Component/Process/Exception/ProcessTimedOutException.phpnu�[���PKx�Z�<���:!j(Symfony/Component/Process/Exception/ExceptionInterface.phpnu�[���PKx�Z>H����8:l(Symfony/Component/Process/Exception/RuntimeException.phpnu�[���PKx�Z��W��6�n(Symfony/Component/Process/Exception/LogicException.phpnu�[���PKx�Z˅����@�p(Symfony/Component/Process/Exception/InvalidArgumentException.phpnu�[���PKx�Z��_��>s(Symfony/Component/Process/Exception/ProcessFailedException.phpnu�[���PKx�Z@s�(�x(Symfony/Component/Process/PhpProcess.phpnu�[���PKx�Z�nL	L	*�(Symfony/Component/Process/ProcessUtils.phpnu�[���PKy�Z�!,$

.��(Symfony/Component/Process/ExecutableFinder.phpnu�[���PKy�Z!/���,�(Symfony/Component/Process/ProcessBuilder.phpnu�[���PKy�Zy>�8��1�(Symfony/Component/Process/PhpExecutableFinder.phpnu�[���PKy�Z��M��%ު(Symfony/Component/Process/Process.phpnu�[���PKy�Z[i55ERA)Symfony/Component/Serializer/Normalizer/SerializerAwareNormalizer.phpnu�[���PKy�Z=Vxe::A�D)Symfony/Component/Serializer/Normalizer/NormalizableInterface.phpnu�[���PKy�Z��SVV<�J)Symfony/Component/Serializer/Normalizer/CustomNormalizer.phpnu�[���PKy�Z��,,BiR)Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.phpnu�[���PKy�Z"p�yy?q)Symfony/Component/Serializer/Normalizer/NormalizerInterface.phpnu�[���PKy�Z�qU���C�u)Symfony/Component/Serializer/Normalizer/DenormalizableInterface.phpnu�[���PKz�Z���A�{)Symfony/Component/Serializer/Normalizer/DenormalizerInterface.phpnu�[���PKz�Z���OO9t�)Symfony/Component/Serializer/SerializerAwareInterface.phpnu�[���PKz�Z��TT+,�)Symfony/Component/Serializer/autoloader.phpnu�[���PKz�Zx蕰

4ۅ)Symfony/Component/Serializer/SerializerInterface.phpnu�[���PKz�Z,�c��9L�)Symfony/Component/Serializer/Encoder/EncoderInterface.phpnu�[���PKz�Z��[�5�53i�)Symfony/Component/Serializer/Encoder/XmlEncoder.phpnu�[���PKz�Z�<=ggD��)Symfony/Component/Serializer/Encoder/NormalizationAwareInterface.phpnu�[���PKz�ZV��O��5��)Symfony/Component/Serializer/Encoder/ChainDecoder.phpnu�[���PKz�Z�=��?��)Symfony/Component/Serializer/Encoder/SerializerAwareEncoder.phpnu�[���PKz�Zv:�hh3[�)Symfony/Component/Serializer/Encoder/JsonEncode.phpnu�[���PKz�Z��@���3&�)Symfony/Component/Serializer/Encoder/JsonDecode.phpnu�[���PKz�ZS R�	�	5q�)Symfony/Component/Serializer/Encoder/ChainEncoder.phpnu�[���PKz�Z�o�vv4��)Symfony/Component/Serializer/Encoder/JsonEncoder.phpnu�[���PKz�Z|ͼ���9��)Symfony/Component/Serializer/Encoder/DecoderInterface.phpnu�[���PKz�ZA�A
��4�*Symfony/Component/Serializer/Exception/Exception.phpnu�[���PKz�Z�^L��?�*Symfony/Component/Serializer/Exception/UnsupportedException.phpnu�[���PKz�Z�h=��;�*Symfony/Component/Serializer/Exception/RuntimeException.phpnu�[���PKz�ZJ���9�*Symfony/Component/Serializer/Exception/LogicException.phpnu�[���PKz�ZT��Y��C	*Symfony/Component/Serializer/Exception/InvalidArgumentException.phpnu�[���PKz�Z[�����Ci*Symfony/Component/Serializer/Exception/UnexpectedValueException.phpnu�[���PKz�Zʪ2/&/&+�
*Symfony/Component/Serializer/Serializer.phpnu�[���PKz�ZFP�PP'<4*Symfony/Component/Locale/autoloader.phpnu�[���PKz�Z�Q�UUL�5*Symfony/Component/Locale/Exception/MethodArgumentNotImplementedException.phpnu�[���PKz�Z��E>�9*Symfony/Component/Locale/Exception/NotImplementedException.phpnu�[���PKz�ZS�?a%%D#=*Symfony/Component/Locale/Exception/MethodNotImplementedException.phpnu�[���PKz�Z���ssQ�@*Symfony/Component/Locale/Exception/MethodArgumentValueNotImplementedException.phpnu�[���PKz�Z�C��*�D*Symfony/Component/Locale/Stub/StubIntl.phpnu�[���PKz�Z&�����5�G*Symfony/Component/Locale/Stub/StubNumberFormatter.phpnu�[���PKz�Zv/�@�J*Symfony/Component/Locale/Stub/DateFormat/Hour2401Transformer.phpnu�[���PKz�Z��S@PN*Symfony/Component/Locale/Stub/DateFormat/TimeZoneTransformer.phpnu�[���PKz�Z}��""A�Q*Symfony/Component/Locale/Stub/DateFormat/DayOfYearTransformer.phpnu�[���PKz�Z�X�<oU*Symfony/Component/Locale/Stub/DateFormat/AmPmTransformer.phpnu�[���PKz�Z���<�X*Symfony/Component/Locale/Stub/DateFormat/YearTransformer.phpnu�[���PKz�Zmў?O\*Symfony/Component/Locale/Stub/DateFormat/QuarterTransformer.phpnu�[���PKz�Zg[ep>�_*Symfony/Component/Locale/Stub/DateFormat/MinuteTransformer.phpnu�[���PKz�Z:6""ARc*Symfony/Component/Locale/Stub/DateFormat/DayOfWeekTransformer.phpnu�[���PKz�Z9�u@�f*Symfony/Component/Locale/Stub/DateFormat/Hour1200Transformer.phpnu�[���PKz�Zk&"M@qj*Symfony/Component/Locale/Stub/DateFormat/Hour1201Transformer.phpnu�[���PKz�Z�����;�m*Symfony/Component/Locale/Stub/DateFormat/DayTransformer.phpnu�[���PKz�Z��@fq*Symfony/Component/Locale/Stub/DateFormat/Hour2400Transformer.phpnu�[���PKz�Z�Ed��8�t*Symfony/Component/Locale/Stub/DateFormat/Transformer.phpnu�[���PKz�Zt�z

=Ox*Symfony/Component/Locale/Stub/DateFormat/MonthTransformer.phpnu�[���PKz�Zk�H<�{*Symfony/Component/Locale/Stub/DateFormat/FullTransformer.phpnu�[���PKz�Z�3�X>6*Symfony/Component/Locale/Stub/DateFormat/SecondTransformer.phpnu�[���PKz�Z�
�

<��*Symfony/Component/Locale/Stub/DateFormat/HourTransformer.phpnu�[���PKz�Z���?��.-�*Symfony/Component/Locale/Stub/StubCollator.phpnu�[���PK{�Zq��*((,�*Symfony/Component/Locale/Stub/StubLocale.phpnu�[���PK{�Z� S���7��*Symfony/Component/Locale/Stub/StubIntlDateFormatter.phpnu�[���PK{�Zl�l��#��*Symfony/Component/Locale/Locale.phpnu�[���PK{�Z�t�TT+��*Symfony/Component/Filesystem/autoloader.phpnu�[���PK{�Z��dP��@b�*Symfony/Component/Filesystem/Exception/FileNotFoundException.phpnu�[���PK{�Z3{����=��*Symfony/Component/Filesystem/Exception/ExceptionInterface.phpnu�[���PK{�ZoC�~��?��*Symfony/Component/Filesystem/Exception/IOExceptionInterface.phpnu�[���PK{�Z;�{��6ͷ*Symfony/Component/Filesystem/Exception/IOException.phpnu�[���PK{�ZOظ�GG+�*Symfony/Component/Filesystem/Filesystem.phpnu�[���PK{�Z)��.�.'T+Symfony/Component/Form/FormRenderer.phpnu�[���PK{�Z�C����.]2+Symfony/Component/Form/ButtonTypeInterface.phpnu�[���PK{�ZK'�$��&�4+Symfony/Component/Form/FormBuilder.phpnu�[���PK{�Z&�"̰T�T,�S+Symfony/Component/Form/FormConfigBuilder.phpnu�[���PK{�ZE1�'��4��+Symfony/Component/Form/SubmitButtonTypeInterface.phpnu�[���PK{�Z�d��'�+Symfony/Component/Form/FormRegistry.phpnu�[���PK{�ZÊM'%%.н+Symfony/Component/Form/FormConfigInterface.phpnu�[���PK{�Z��@@/S�+Symfony/Component/Form/FormTypeGuesserChain.phpnu�[���PK{�ZR����+��+Symfony/Component/Form/Guess/ValueGuess.phpnu�[���PK{�Z�511&,�+Symfony/Component/Form/Guess/Guess.phpnu�[���PK{�Z���  *��+Symfony/Component/Form/Guess/TypeGuess.phpnu�[���PK{�Z�0\ZZ.-�+Symfony/Component/Form/CallbackTransformer.phpnu�[���PK{�Z4�Nz"z"!�,Symfony/Component/Form/Button.phpnu�[���PK{�Z-�9NN%�%,Symfony/Component/Form/autoloader.phpnu�[���PK{�Z�/��tt%S',Symfony/Component/Form/FormEvents.phpnu�[���PK{�Z�����,,,Symfony/Component/Form/FormTypeInterface.phpnu�[���PK{�Z�>���09,Symfony/Component/Form/FormRegistryInterface.phpnu�[���PK{�Z��?zz3?,Symfony/Component/Form/FormTypeGuesserInterface.phpnu�[���PK{�Z��*��+�G,Symfony/Component/Form/ResolvedFormType.phpnu�[���PK{�ZObX�qq'6f,Symfony/Component/Form/SubmitButton.phpnu�[���PK|�Z�p��1�j,Symfony/Component/Form/AbstractRendererEngine.phpnu�[���PK|�ZDjN,1�,Symfony/Component/Form/AbstractExtension.phpnu�[���PK|�Zf#jK��6��,Symfony/Component/Form/FormRendererEngineInterface.phpnu�[���PK|�Z���1�1���,Symfony/Component/Form/Form.phpnu�[���PK|�Z�di���;A-Symfony/Component/Form/Exception/BadMethodCallException.phpnu�[���PK|�Z�W�

:yC-Symfony/Component/Form/Exception/AlreadyBoundException.phpnu�[���PK|�Z(ddB�E-Symfony/Component/Form/Exception/InvalidConfigurationException.phpnu�[���PK|�Z�_c==<�G-Symfony/Component/Form/Exception/UnexpectedTypeException.phpnu�[���PK|�Z�S�D��BoJ-Symfony/Component/Form/Exception/TransformationFailedException.phpnu�[���PK|�Z��9�L-Symfony/Component/Form/Exception/OutOfBoundsException.phpnu�[���PK}�Z�y�u��7�N-Symfony/Component/Form/Exception/ExceptionInterface.phpnu�[���PK}�ZN����5
Q-Symfony/Component/Form/Exception/RuntimeException.phpnu�[���PK}�ZK�9���>OS-Symfony/Component/Form/Exception/AlreadySubmittedException.phpnu�[���PK}�Z1�;TT:�U-Symfony/Component/Form/Exception/ErrorMappingException.phpnu�[���PK}�Z��+RR8oW-Symfony/Component/Form/Exception/StringCastException.phpnu�[���PK}�Z��X��3)Y-Symfony/Component/Form/Exception/LogicException.phpnu�[���PK}�Z�gBz��=d[-Symfony/Component/Form/Exception/InvalidArgumentException.phpnu�[���PK}�Z�1��88'�]-Symfony/Component/Form/AbstractType.phpnu�[���PK}�Z�I	�66.Ub-Symfony/Component/Form/Util/OrderedHashMap.phpnu�[���PK}�Z�h��''6�t-Symfony/Component/Form/Util/OrderedHashMapIterator.phpnu�[���PK}�Z��F228v�-Symfony/Component/Form/Util/VirtualFormAwareIterator.phpnu�[���PK}�Zy���$$(�-Symfony/Component/Form/Util/FormUtil.phpnu�[���PK}�Z<����8��-Symfony/Component/Form/Util/InheritDataAwareIterator.phpnu�[���PK}�Z�QT�pp.�-Symfony/Component/Form/SubmitButtonBuilder.phpnu�[���PK}�Z�z5���2��-Symfony/Component/Form/ResolvedFormTypeFactory.phpnu�[���PK}�ZSf��
	
	-��-Symfony/Component/Form/PreloadedExtension.phpnu�[���PK}�Z>��*ii&�-Symfony/Component/Form/FormFactory.phpnu�[���PK}�Z�\�g��2˳-Symfony/Component/Form/RequestHandlerInterface.phpnu�[���PK}�Z+q�DAA7ɶ-Symfony/Component/Form/Test/FormPerformanceTestCase.phpnu�[���PK}�ZsŪ�,q�-Symfony/Component/Form/Test/TypeTestCase.phpnu�[���PK}�Z�,�7//7�-Symfony/Component/Form/Test/DeprecationErrorHandler.phpnu�[���PK}�ZB�4I++7k�-Symfony/Component/Form/Test/FormIntegrationTestCase.phpnu�[���PK}�Z��m�yy4��-Symfony/Component/Form/Test/FormBuilderInterface.phpnu�[���PK}�Za(0kk-��-Symfony/Component/Form/Test/FormInterface.phpnu�[���PK}�Z�n����1��-Symfony/Component/Form/FormExtensionInterface.phpnu�[���PK}�Z|G����4��-Symfony/Component/Form/ResolvedFormTypeInterface.phpnu�[���PK}�Z{d���!�!5��-Symfony/Component/Form/FormConfigBuilderInterface.phpnu�[���PK}�ZɃT���6.Symfony/Component/Form/FormFactoryBuilderInterface.phpnu�[���PK}�Z�N̷;m.Symfony/Component/Form/ResolvedFormTypeFactoryInterface.phpnu�[���PK}�Z2��-�.Symfony/Component/Form/FormFactoryBuilder.phpnu�[���PK}�Z���C��0d$.Symfony/Component/Form/AbstractTypeExtension.phpnu�[���PK}�Z�E���0�(.Symfony/Component/Form/FormRendererInterface.phpnu�[���PK}�Z�:		/�5.Symfony/Component/Form/FormBuilderInterface.phpnu�[���PK}�Z��Z)��/R?.Symfony/Component/Form/FormFactoryInterface.phpnu�[���PK}�Z�YB���.EP.Symfony/Component/Form/ReversedTransformer.phpnu�[���PK}�Z�r�WW3�U.Symfony/Component/Form/DataTransformerInterface.phpnu�[���PK}�ZW�b�[H[H(Eb.Symfony/Component/Form/ButtonBuilder.phpnu�[���PK}�Z��n��?��.Symfony/Component/Form/Resources/translations/validators.en.xlfnu�[���PK}�Z誫���?�.Symfony/Component/Form/Resources/translations/validators.sk.xlfnu�[���PK}�Z�<�yy?=�.Symfony/Component/Form/Resources/translations/validators.uk.xlfnu�[���PK}�Z:����?%�.Symfony/Component/Form/Resources/translations/validators.pl.xlfnu�[���PK��Z��
���?[�.Symfony/Component/Form/Resources/translations/validators.pt.xlfnu�[���PK��Z�%��?��.Symfony/Component/Form/Resources/translations/validators.lv.xlfnu�[���PK��Z္o33D��.Symfony/Component/Form/Resources/translations/validators.sr_Cyrl.xlfnu�[���PK��Z����?��.Symfony/Component/Form/Resources/translations/validators.fi.xlfnu�[���PK��Z0h���?��.Symfony/Component/Form/Resources/translations/validators.es.xlfnu�[���PK��Z�TI��?,�.Symfony/Component/Form/Resources/translations/validators.de.xlfnu�[���PK��Z!�aZ��?~�.Symfony/Component/Form/Resources/translations/validators.it.xlfnu�[���PK��Z �!���?��.Symfony/Component/Form/Resources/translations/validators.ca.xlfnu�[���PK��Z���?��.Symfony/Component/Form/Resources/translations/validators.mn.xlfnu�[���PK��Z���-��?X�.Symfony/Component/Form/Resources/translations/validators.ru.xlfnu�[���PK��Z�3Ե^^?T�.Symfony/Component/Form/Resources/translations/validators.bg.xlfnu�[���PK��ZE��d��?!�.Symfony/Component/Form/Resources/translations/validators.ro.xlfnu�[���PK��ZO���?r�.Symfony/Component/Form/Resources/translations/validators.nl.xlfnu�[���PK��ZS�*��?��.Symfony/Component/Form/Resources/translations/validators.et.xlfnu�[���PK��Z�V5?��.Symfony/Component/Form/Resources/translations/validators.fa.xlfnu�[���PK��Z��q��?J�.Symfony/Component/Form/Resources/translations/validators.id.xlfnu�[���PK��Z�
���?w/Symfony/Component/Form/Resources/translations/validators.cs.xlfnu�[���PK��Z�8,:��B�/Symfony/Component/Form/Resources/translations/validators.zh_CN.xlfnu�[���PK��Z�H�q��?�
/Symfony/Component/Form/Resources/translations/validators.lt.xlfnu�[���PK��Z�_8��?�/Symfony/Component/Form/Resources/translations/validators.fr.xlfnu�[���PK��Z�A�4��?�/Symfony/Component/Form/Resources/translations/validators.gl.xlfnu�[���PK��Z
b�8��?4/Symfony/Component/Form/Resources/translations/validators.hr.xlfnu�[���PK��ZWgUugg?]/Symfony/Component/Form/Resources/translations/validators.nb.xlfnu�[���PK��Zٻ��||?3/Symfony/Component/Form/Resources/translations/validators.eu.xlfnu�[���PK��Z�4@���B#/Symfony/Component/Form/Resources/translations/validators.pt_BR.xlfnu�[���PK��Z��5��?Q'/Symfony/Component/Form/Resources/translations/validators.sl.xlfnu�[���PK��Z�*{���?m+/Symfony/Component/Form/Resources/translations/validators.lb.xlfnu�[���PK��Zbe�@��?�//Symfony/Component/Form/Resources/translations/validators.hu.xlfnu�[���PK��Z_Π��?4/Symfony/Component/Form/Resources/translations/validators.el.xlfnu�[���PK��ZX�����?9/Symfony/Component/Form/Resources/translations/validators.da.xlfnu�[���PK��Z���?�</Symfony/Component/Form/Resources/translations/validators.ja.xlfnu�[���PK��Zs>�ll?AA/Symfony/Component/Form/Resources/translations/validators.sv.xlfnu�[���PK��Zy��99?E/Symfony/Component/Form/Resources/translations/validators.hy.xlfnu�[���PK��Z|��C?�I/Symfony/Component/Form/Resources/translations/validators.ar.xlfnu�[���PK��Zr���DBN/Symfony/Component/Form/Resources/translations/validators.sr_Latn.xlfnu�[���PK��ZNP\��?dR/Symfony/Component/Form/Resources/translations/validators.he.xlfnu�[���PK��Z�xfh..6dV/Symfony/Component/Form/Resources/config/validation.xmlnu�[���PK��ZR}��jj.�X/Symfony/Component/Form/DataMapperInterface.phpnu�[���PK��Z�s�� � (�]/Symfony/Component/Form/FormInterface.phpnu�[���PK��Z���"��$�~/Symfony/Component/Form/FormEvent.phpnu�[���PK��Z�=�MM5Ӄ/Symfony/Component/Form/FormTypeExtensionInterface.phpnu�[���PK��Z�}p�

$��/Symfony/Component/Form/FormError.phpnu�[���PK��Z�	���/ܖ/Symfony/Component/Form/NativeRequestHandler.phpnu�[���PK��Z���*��O'�/Symfony/Component/Form/Extension/Validator/EventListener/ValidationListener.phpnu�[���PK��Z��Ck��@5�/Symfony/Component/Form/Extension/Validator/Util/ServerParams.phpnu�[���PK��Z2=[<((A1�/Symfony/Component/Form/Extension/Validator/ValidatorExtension.phpnu�[���PK��Z}>�ُ�?��/Symfony/Component/Form/Extension/Validator/Constraints/Form.phpnu�[���PK��Z�-�P��H��/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.phpnu�[���PK��Zl�Ct*t*C��/Symfony/Component/Form/Extension/Validator/ValidatorTypeGuesser.phpnu�[���PK��ZɥS��T�
0Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPathIterator.phpnu�[���PK��Z�\T��K0Symfony/Component/Form/Extension/Validator/ViolationMapper/RelativePath.phpnu�[���PK��ZC_�hU+U+N0Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.phpnu�[���PK��Z�k�t==W�@0Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapperInterface.phpnu�[���PK��Z�-��!!L�E0Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPath.phpnu�[���PK��Zf����
�
JR_0Symfony/Component/Form/Extension/Validator/ViolationMapper/MappingRule.phpnu�[���PK��Z�����J�j0Symfony/Component/Form/Extension/Validator/Type/BaseValidatorExtension.phpnu�[���PK��ZeBR�	�	N�p0Symfony/Component/Form/Extension/Validator/Type/FormTypeValidatorExtension.phpnu�[���PK��Z͚>�@@R+{0Symfony/Component/Form/Extension/Validator/Type/RepeatedTypeValidatorExtension.phpnu�[���PK��Z1���P�0Symfony/Component/Form/Extension/Validator/Type/SubmitTypeValidatorExtension.phpnu�[���PK��Z���,QQC��0Symfony/Component/Form/Extension/Templating/TemplatingExtension.phpnu�[���PK��Zզ�Y��HL�0Symfony/Component/Form/Extension/Templating/TemplatingRendererEngine.phpnu�[���PK��Z䋧��U��0Symfony/Component/Form/Extension/HttpFoundation/EventListener/BindRequestListener.phpnu�[���PK��Z�j��=
=
PԦ0Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationRequestHandler.phpnu�[���PK��Z��Q��K��0Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationExtension.phpnu�[���PK��Z�PffX��0Symfony/Component/Form/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.phpnu�[���PK��Z"�q���7��0Symfony/Component/Form/Extension/Csrf/CsrfExtension.phpnu�[���PK��Z�C���J��0Symfony/Component/Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.phpnu�[���PK��Z[^����J��0Symfony/Component/Form/Extension/Csrf/CsrfProvider/SessionCsrfProvider.phpnu�[���PK��Z%�G���L�0Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderInterface.phpnu�[���PK��Z�����JI�0Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderAdapter.phpnu�[���PK��ZR�'WTTN��0Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfTokenManagerAdapter.phpnu�[���PK��Z�?�ooNy�0Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.phpnu�[���PK��Z��
f��Df�0Symfony/Component/Form/Extension/Csrf/Type/FormTypeCsrfExtension.phpnu�[���PK��ZC�W���7�
1Symfony/Component/Form/Extension/Core/CoreExtension.phpnu�[���PK��Z�:AAD�1Symfony/Component/Form/Extension/Core/EventListener/TrimListener.phpnu�[���PK��Zõe��O�1Symfony/Component/Form/Extension/Core/EventListener/MergeCollectionListener.phpnu�[���PK��Z>Q?��N�+1Symfony/Component/Form/Extension/Core/EventListener/FixUrlProtocolListener.phpnu�[���PK��Zb����P�11Symfony/Component/Form/Extension/Core/EventListener/FixCheckboxInputListener.phpnu�[���PK��Z\��//J�=1Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.phpnu�[���PK��Z?D���M�Q1Symfony/Component/Form/Extension/Core/EventListener/FixRadioInputListener.phpnu�[���PK��Z�jю��E�Z1Symfony/Component/Form/Extension/Core/ChoiceList/SimpleChoiceList.phpnu�[���PK��Z�
�##E�p1Symfony/Component/Form/Extension/Core/ChoiceList/ObjectChoiceList.phpnu�[���PK��Zl_R(H��1Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceListInterface.phpnu�[���PK��Z�В4
4
C�1Symfony/Component/Form/Extension/Core/ChoiceList/LazyChoiceList.phpnu�[���PK��Z'���??��1Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceList.phpnu�[���PK��Z��&PP9��1Symfony/Component/Form/Extension/Core/View/ChoiceView.phpnu�[���PK��Z��

Gl�1Symfony/Component/Form/Extension/Core/DataMapper/PropertyPathMapper.phpnu�[���PK��ZO�#�#�#\�2Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.phpnu�[���PK��Z)b�""^)2Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.phpnu�[���PK��Ze�^�		V�?2Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.phpnu�[���PK��Z���Þ
�
XVI2Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.phpnu�[���PK��Zc�8V�	�	N|T2Symfony/Component/Form/Extension/Core/DataTransformer/DataTransformerChain.phpnu�[���PK��Z�;�dd]�^2Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.phpnu�[���PK��Z�Z�eTwo2Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToArrayTransformer.phpnu�[���PK��ZL�px&&Y�2Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.phpnu�[���PK��Z����		V��2Symfony/Component/Form/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.phpnu�[���PK��Z'tqk55ZJ�2Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.phpnu�[���PK��Z���ggT	�2Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToValuesTransformer.phpnu�[���PK��ZUd�q]�2Symfony/Component/Form/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.phpnu�[���PK��ZΎgW� � U��2Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToStringTransformer.phpnu�[���PK��Z�"h���R��2Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToValueTransformer.phpnu�[���PK��Z�H��		Q��2Symfony/Component/Form/Extension/Core/DataTransformer/ArrayToPartsTransformer.phpnu�[���PK��Z/C���QO�2Symfony/Component/Form/Extension/Core/DataTransformer/BaseDateTimeTransformer.phpnu�[���PK��Z���T��T��2Symfony/Component/Form/Extension/Core/DataTransformer/BooleanToStringTransformer.phpnu�[���PK��Z]��yD	D	[/3Symfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.phpnu�[���PK��Z���/�+�+9�
3Symfony/Component/Form/Extension/Core/Type/ChoiceType.phpnu�[���PK��Z��h��9:3Symfony/Component/Form/Extension/Core/Type/ButtonType.phpnu�[���PK��ZD�U��9s>3Symfony/Component/Form/Extension/Core/Type/SubmitType.phpnu�[���PK��Z񍢸��;�B3Symfony/Component/Form/Extension/Core/Type/CurrencyType.phpnu�[���PK��Z�Ѝ'��9�F3Symfony/Component/Form/Extension/Core/Type/HiddenType.phpnu�[���PK��Z���D��9�J3Symfony/Component/Form/Extension/Core/Type/LocaleType.phpnu�[���PK��ZuƵ�``:O3Symfony/Component/Form/Extension/Core/Type/IntegerType.phpnu�[���PK��Za����8�W3Symfony/Component/Form/Extension/Core/Type/ResetType.phpnu�[���PK��Z옇���;'[3Symfony/Component/Form/Extension/Core/Type/PasswordType.phpnu�[���PK��Zٝ��GG7]`3Symfony/Component/Form/Extension/Core/Type/BaseType.phpnu�[���PK��ZZ���^^:r3Symfony/Component/Form/Extension/Core/Type/PercentType.phpnu�[���PK��Z��TT;�w3Symfony/Component/Form/Extension/Core/Type/CheckboxType.phpnu�[���PK��Z&ߏ�vv;��3Symfony/Component/Form/Extension/Core/Type/BirthdayType.phpnu�[���PK��Z7pO�LL8s�3Symfony/Component/Form/Extension/Core/Type/RadioType.phpnu�[���PK��Z�G�oo7'�3Symfony/Component/Form/Extension/Core/Type/FileType.phpnu�[���PK��Z�8��JJ9��3Symfony/Component/Form/Extension/Core/Type/SearchType.phpnu�[���PK��Z�_��LL;��3Symfony/Component/Form/Extension/Core/Type/TimezoneType.phpnu�[���PK��Z���HH8g�3Symfony/Component/Form/Extension/Core/Type/EmailType.phpnu�[���PK��Z[Gԃ��=�3Symfony/Component/Form/Extension/Core/Type/CollectionType.phpnu�[���PK��Z�t�II;1�3Symfony/Component/Form/Extension/Core/Type/TextareaType.phpnu�[���PK��Z����;�3Symfony/Component/Form/Extension/Core/Type/LanguageType.phpnu�[���PK��ZT;���7��3Symfony/Component/Form/Extension/Core/Type/TextType.phpnu�[���PK��ZH?!a��7J�3Symfony/Component/Form/Extension/Core/Type/TimeType.phpnu�[���PK��Z�� &�'�';��3Symfony/Component/Form/Extension/Core/Type/DateTimeType.phpnu�[���PK��Z�q���6��3Symfony/Component/Form/Extension/Core/Type/UrlType.phpnu�[���PK��Z9�;�3Symfony/Component/Form/Extension/Core/Type/RepeatedType.phpnu�[���PK��ZM2\3,3,7E4Symfony/Component/Form/Extension/Core/Type/DateType.phpnu�[���PK��Za�LŢ�:�34Symfony/Component/Form/Extension/Core/Type/CountryType.phpnu�[���PK��ZC�i���9�74Symfony/Component/Form/Extension/Core/Type/NumberType.phpnu�[���PK��Z:�y�

7;@4Symfony/Component/Form/Extension/Core/Type/FormType.phpnu�[���PK��Z5�S
��8�\4Symfony/Component/Form/Extension/Core/Type/MoneyType.phpnu�[���PK��Z6s���D�i4Symfony/Component/Form/Extension/DataCollector/FormDataCollector.phpnu�[���PK��ZI��2

Vȇ4Symfony/Component/Form/Extension/DataCollector/EventListener/DataCollectorListener.phpnu�[���PK��Z�T���Mc�4Symfony/Component/Form/Extension/DataCollector/FormDataCollectorInterface.phpnu�[���PK��Z����M��4Symfony/Component/Form/Extension/DataCollector/FormDataExtractorInterface.phpnu�[���PK��Z|�
]��W�4Symfony/Component/Form/Extension/DataCollector/Proxy/ResolvedTypeDataCollectorProxy.phpnu�[���PK��Z�((^6�4Symfony/Component/Form/Extension/DataCollector/Proxy/ResolvedTypeFactoryDataCollectorProxy.phpnu�[���PK��Z��#�11I�4Symfony/Component/Form/Extension/DataCollector/DataCollectorExtension.phpnu�[���PK��Z%�`��D��4Symfony/Component/Form/Extension/DataCollector/FormDataExtractor.phpnu�[���PK��Z�1�
uuR��4Symfony/Component/Form/Extension/DataCollector/Type/DataCollectorTypeExtension.phpnu�[���PK��ZuUS�WWU��4Symfony/Component/Form/Extension/DependencyInjection/DependencyInjectionExtension.phpnu�[���PK��Z(s
//-a�4Symfony/Component/Form/ClickableInterface.phpnu�[���PK��ZH��
�
#��4Symfony/Component/Form/FormView.phpnu�[���PK��Z
�͋ �4Symfony/Component/Form/Forms.phpnu�[���PK��Z\�F1_
5Symfony/Component/Security/Acl/Voter/AclVoter.phpnu�[���PK��Z\!�	HH2�#5Symfony/Component/Security/Acl/Voter/FieldVote.phpnu�[���PK��ZP͡��Am'5Symfony/Component/Security/Acl/Exception/AclNotFoundException.phpnu�[���PK��Z�k�q��6�)5Symfony/Component/Security/Acl/Exception/Exception.phpnu�[���PK��Z�W�L�+5Symfony/Component/Security/Acl/Exception/ConcurrentModificationException.phpnu�[���PK��Z���OI}.5Symfony/Component/Security/Acl/Exception/InvalidDomainObjectException.phpnu�[���PK��Z]��_""E15Symfony/Component/Security/Acl/Exception/NotAllAclsFoundException.phpnu�[���PK��Z�B�l��@�55Symfony/Component/Security/Acl/Exception/NoAceFoundException.phpnu�[���PK��Z[�z�B�85Symfony/Component/Security/Acl/Exception/SidNotLoadedException.phpnu�[���PK��Z��5�

F;5Symfony/Component/Security/Acl/Exception/AclAlreadyExistsException.phpnu�[���PK��Zt��:�=5Symfony/Component/Security/Acl/Dbal/MutableAclProvider.phpnu�[���PK��Z�^�+f+f3��5Symfony/Component/Security/Acl/Dbal/AclProvider.phpnu�[���PK��ZK� V��.n,6Symfony/Component/Security/Acl/Dbal/Schema.phpnu�[���PK��ZNTA�]]5�D6Symfony/Component/Security/Acl/Domain/AuditLogger.phpnu�[���PK��Z�.��**>sJ6Symfony/Component/Security/Acl/Domain/UserSecurityIdentity.phpnu�[���PK��Z��C3��:W6Symfony/Component/Security/Acl/Domain/DoctrineAclCache.phpnu�[���PK��Z(]���D#p6Symfony/Component/Security/Acl/Domain/PermissionGrantingStrategy.phpnu�[���PK��Z%�}`M`M-k�6Symfony/Component/Security/Acl/Domain/Acl.phpnu�[���PK��Z����K(�6Symfony/Component/Security/Acl/Domain/SecurityIdentityRetrievalStrategy.phpnu�[���PK��Z�X�
/	/	<K�6Symfony/Component/Security/Acl/Domain/AclCollectionCache.phpnu�[���PK��Z5D�[/��6Symfony/Component/Security/Acl/Domain/Entry.phpnu�[���PK��Z�pU���4H7Symfony/Component/Security/Acl/Domain/FieldEntry.phpnu�[���PK��Z^@�.YY8R7Symfony/Component/Security/Acl/Domain/ObjectIdentity.phpnu�[���PK��Z0F���I7Symfony/Component/Security/Acl/Domain/ObjectIdentityRetrievalStrategy.phpnu�[���PK��ZtA)�==>J7Symfony/Component/Security/Acl/Domain/RoleSecurityIdentity.phpnu�[���PK��Z�#��~~<�#7Symfony/Component/Security/Acl/Resources/bin/generateSql.phpnu�[���PK��Zj~	cFF7�+7Symfony/Component/Security/Acl/Resources/schema/db2.sqlnu�[���PK��ZT��skk>�87Symfony/Component/Security/Acl/Resources/schema/postgresql.sqlnu�[���PK��ZJx�.

9eE7Symfony/Component/Security/Acl/Resources/schema/mssql.sqlnu�[���PK��ZfZ��^^9�R7Symfony/Component/Security/Acl/Resources/schema/mysql.sqlnu�[���PK��Z��c�
�
;�^7Symfony/Component/Security/Acl/Resources/schema/drizzle.sqlnu�[���PK��Z�C� ;;:�i7Symfony/Component/Security/Acl/Resources/schema/oracle.sqlnu�[���PK��Z��d��:I�7Symfony/Component/Security/Acl/Resources/schema/sqlite.sqlnu�[���PK��Zw���D��7Symfony/Component/Security/Acl/Permission/PermissionMapInterface.phpnu�[���PK��Z�ep�gg9��7Symfony/Component/Security/Acl/Permission/MaskBuilder.phpnu�[���PK��Z� c0��@ͫ7Symfony/Component/Security/Acl/Permission/BasicPermissionMap.phpnu�[���PK��Z6����<��7Symfony/Component/Security/Acl/Model/MutableAclInterface.phpnu�[���PK��Z[Ob3SK�7Symfony/Component/Security/Acl/Model/SecurityIdentityRetrievalStrategyInterface.phpnu�[���PK��ZX	��>��7Symfony/Component/Security/Acl/Model/DomainObjectInterface.phpnu�[���PK��Z�5Ayy@
�7Symfony/Component/Security/Acl/Model/ObjectIdentityInterface.phpnu�[���PK��Zt��@��7Symfony/Component/Security/Acl/Model/AuditableEntryInterface.phpnu�[���PK��Z-癥��Lk�7Symfony/Component/Security/Acl/Model/PermissionGrantingStrategyInterface.phpnu�[���PK��Z�����=��7Symfony/Component/Security/Acl/Model/AclProviderInterface.phpnu�[���PK��Z�#���:&�7Symfony/Component/Security/Acl/Model/AclCacheInterface.phpnu�[���PK��Zӗ&1>��7Symfony/Component/Security/Acl/Model/AuditableAclInterface.phpnu�[���PK��Z�ݤUU<�7Symfony/Component/Security/Acl/Model/FieldEntryInterface.phpnu�[���PK��Z�
�8FF7�7Symfony/Component/Security/Acl/Model/EntryInterface.phpnu�[���PK��ZH<J��=��7Symfony/Component/Security/Acl/Model/AuditLoggerInterface.phpnu�[���PK��Z���77B�8Symfony/Component/Security/Acl/Model/SecurityIdentityInterface.phpnu�[���PK��Z�𕛼�5L8Symfony/Component/Security/Acl/Model/AclInterface.phpnu�[���PK��Z�W}��Qm8Symfony/Component/Security/Acl/Model/ObjectIdentityRetrievalStrategyInterface.phpnu�[���PK��Zj���D�8Symfony/Component/Security/Acl/Model/MutableAclProviderInterface.phpnu�[���PK��Z��W"RR)�8Symfony/Component/Security/autoloader.phpnu�[���PK��Z�DXVV,t8Symfony/Component/Security/Http/Firewall.phpnu�[���PK��Z"�C��/&'8Symfony/Component/Security/Http/FirewallMap.phpnu�[���PK��Z�יK--8Symfony/Component/Security/Http/EntryPoint/FormAuthenticationEntryPoint.phpnu�[���PK��Z�<ݐppL�58Symfony/Component/Security/Http/EntryPoint/BasicAuthenticationEntryPoint.phpnu�[���PK��Z)'_++P�:8Symfony/Component/Security/Http/EntryPoint/AuthenticationEntryPointInterface.phpnu�[���PK��ZtZ�)K	K	MN?8Symfony/Component/Security/Http/EntryPoint/DigestAuthenticationEntryPoint.phpnu�[���PK��Z�����LI8Symfony/Component/Security/Http/EntryPoint/RetryAuthenticationEntryPoint.phpnu�[���PK��Z��`C��-,P8Symfony/Component/Security/Http/HttpUtils.phpnu�[���PK��Z^�V��N^h8Symfony/Component/Security/Http/Authorization/AccessDeniedHandlerInterface.phpnu�[���PK��Z��̗��W�l8Symfony/Component/Security/Http/Firewall/UsernamePasswordFormAuthenticationListener.phpnu�[���PK��Znz+S�
�
?8Symfony/Component/Security/Http/Firewall/RememberMeListener.phpnu�[���PK��Zlٯ��L6�8Symfony/Component/Security/Http/Firewall/AnonymousAuthenticationListener.phpnu�[���PK��Z�����>��8Symfony/Component/Security/Http/Firewall/ListenerInterface.phpnu�[���PK��Z�|L@**;��8Symfony/Component/Security/Http/Firewall/LogoutListener.phpnu�[���PK��Z�Bb

?J�8Symfony/Component/Security/Http/Firewall/SwitchUserListener.phpnu�[���PK��Z(�T	b!b!>��8Symfony/Component/Security/Http/Firewall/ExceptionListener.phpnu�[���PK��Z׺�=��G��8Symfony/Component/Security/Http/Firewall/X509AuthenticationListener.phpnu�[���PK��Z׿ͼ� � I��8Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.phpnu�[���PK��Z~�k��<19Symfony/Component/Security/Http/Firewall/ChannelListener.phpnu�[���PK��Z��6'6'K�9Symfony/Component/Security/Http/Firewall/AbstractAuthenticationListener.phpnu�[���PK��Z�"?���<?A9Symfony/Component/Security/Http/Firewall/ContextListener.phpnu�[���PK��Z�����MSY9Symfony/Component/Security/Http/Firewall/SimpleFormAuthenticationListener.phpnu�[���PK��Z+/��Z	Z	;�q9Symfony/Component/Security/Http/Firewall/AccessListener.phpnu�[���PK��Z�Z���Mg{9Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.phpnu�[���PK��Zn��L��9Symfony/Component/Security/Http/Firewall/SimplePreAuthenticationListener.phpnu�[���PK��Z�&!�
�
H+�9Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.phpnu�[���PK��Z2j���-$�9Symfony/Component/Security/Http/AccessMap.phpnu�[���PK��Z/�``6x�9Symfony/Component/Security/Http/AccessMapInterface.phpnu�[���PK��Z��\\��8>�9Symfony/Component/Security/Http/FirewallMapInterface.phpnu�[���PK��Z	z��J��9Symfony/Component/Security/Http/RememberMe/RememberMeServicesInterface.phpnu�[���PK��ZP�ڕ��?��9Symfony/Component/Security/Http/RememberMe/ResponseListener.phpnu�[���PK��Z���s44U�9Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.phpnu�[���PK��Z�*�b�&�&I��9Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.phpnu�[���PK��Z�a�$��K!
:Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.phpnu�[���PK��Z:�&�GGR!:Symfony/Component/Security/Http/Session/SessionAuthenticationStrategyInterface.phpnu�[���PK��Z��La[[I�":Symfony/Component/Security/Http/Session/SessionAuthenticationStrategy.phpnu�[���PK��Za7�llF�):Symfony/Component/Security/Http/Logout/DefaultLogoutSuccessHandler.phpnu�[���PK��Z1��d��H�.:Symfony/Component/Security/Http/Logout/LogoutSuccessHandlerInterface.phpnu�[���PK��Z\ü���?�2:Symfony/Component/Security/Http/Logout/SessionLogoutHandler.phpnu�[���PK��Z6O����A07:Symfony/Component/Security/Http/Logout/LogoutHandlerInterface.phpnu�[���PK��Z�ddF�;:Symfony/Component/Security/Http/Logout/CookieClearingLogoutHandler.phpnu�[���PK��Z/ sG��2xA:Symfony/Component/Security/Http/SecurityEvents.phpnu�[���PK��Z�NA��X�E:Symfony/Component/Security/Http/Authentication/AuthenticationSuccessHandlerInterface.phpnu�[���PK��Z������V/K:Symfony/Component/Security/Http/Authentication/DefaultAuthenticationFailureHandler.phpnu�[���PK��Z��H]X�X:Symfony/Component/Security/Http/Authentication/AuthenticationFailureHandlerInterface.phpnu�[���PK��Z�xGAAV^:Symfony/Component/Security/Http/Authentication/DefaultAuthenticationSuccessHandler.phpnu�[���PK��ZAH\ݞ�N�j:Symfony/Component/Security/Http/Authentication/SimpleAuthenticationHandler.phpnu�[���PK��Z�D����9|:Symfony/Component/Security/Http/Event/SwitchUserEvent.phpnu�[���PK��ZZ�v}?^�:Symfony/Component/Security/Http/Event/InteractiveLoginEvent.phpnu�[���PK��Z��VǴ�=L�:Symfony/Component/Security/Csrf/CsrfTokenManagerInterface.phpnu�[���PK��Z&%�L
L
4m�:Symfony/Component/Security/Csrf/CsrfTokenManager.phpnu�[���PK��Z�����
�
J�:Symfony/Component/Security/Csrf/TokenStorage/NativeSessionTokenStorage.phpnu�[���PK��Z�����Fn�:Symfony/Component/Security/Csrf/TokenStorage/TokenStorageInterface.phpnu�[���PK��Z��]N
N
Dq�:Symfony/Component/Security/Csrf/TokenStorage/SessionTokenStorage.phpnu�[���PK��ZeI����D3�:Symfony/Component/Security/Csrf/Exception/TokenNotFoundException.phpnu�[���PK��Z��=H��:Symfony/Component/Security/Csrf/TokenGenerator/UriSafeTokenGenerator.phpnu�[���PK��ZJ,p���J�:Symfony/Component/Security/Csrf/TokenGenerator/TokenGeneratorInterface.phpnu�[���PK��Z���O-3�:Symfony/Component/Security/Csrf/CsrfToken.phpnu�[���PK��Z��S��<��:Symfony/Component/Security/Core/SecurityContextInterface.phpnu�[���PK��Z�}�ww?��:Symfony/Component/Security/Core/Role/RoleHierarchyInterface.phpnu�[���PK��Z� �w??6m�:Symfony/Component/Security/Core/Role/RoleHierarchy.phpnu�[���PK��Z�Ħ-�:Symfony/Component/Security/Core/Role/Role.phpnu�[���PK��ZX�S�007t�:Symfony/Component/Security/Core/Role/SwitchUserRole.phpnu�[���PK��Z�'c��6�:Symfony/Component/Security/Core/Role/RoleInterface.phpnu�[���PK��ZE� �D�:Symfony/Component/Security/Core/Encoder/PasswordEncoderInterface.phpnu�[���PK��ZÆ��	�	A��:Symfony/Component/Security/Core/Encoder/BCryptPasswordEncoder.phpnu�[���PK��Z��^��H�:Symfony/Component/Security/Core/Encoder/MessageDigestPasswordEncoder.phpnu�[���PK��Z,>"�D�:Symfony/Component/Security/Core/Encoder/PlaintextPasswordEncoder.phpnu�[���PK��Z�;D��:b;Symfony/Component/Security/Core/Encoder/EncoderFactory.phpnu�[���PK��Z!�@

A�
;Symfony/Component/Security/Core/Encoder/Pbkdf2PasswordEncoder.phpnu�[���PK��Z#�MMqqCx;Symfony/Component/Security/Core/Encoder/EncoderFactoryInterface.phpnu�[���PK��Z�7���
�
?\;Symfony/Component/Security/Core/Encoder/BasePasswordEncoder.phpnu�[���PK��Z��
�77O�*;Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.phpnu�[���PK��Z��i��Fi1;Symfony/Component/Security/Core/Validator/Constraints/UserPassword.phpnu�[���PK��Z����Es4;Symfony/Component/Security/Core/Exception/BadCredentialsException.phpnu�[���PK��Z���zz=}7;Symfony/Component/Security/Core/Exception/LockedException.phpnu�[���PK��Zb��M<<Fd:;Symfony/Component/Security/Core/Exception/UnsupportedUserException.phpnu�[���PK��Z�z�&��I=;Symfony/Component/Security/Core/Exception/CredentialsExpiredException.phpnu�[���PK��Z��Xss=9@;Symfony/Component/Security/Core/Exception/LogoutException.phpnu�[���PK��Z
�04}}GC;Symfony/Component/Security/Core/Exception/UsernameNotFoundException.phpnu�[���PK��Z#��q44Q
I;Symfony/Component/Security/Core/Exception/InsufficientAuthenticationException.phpnu�[���PK��Z�5]���I�L;Symfony/Component/Security/Core/Exception/SessionUnavailableException.phpnu�[���PK��ZD��9��D�P;Symfony/Component/Security/Core/Exception/TokenNotFoundException.phpnu�[���PK��Zh�c��B�S;Symfony/Component/Security/Core/Exception/CookieTheftException.phpnu�[���PK��Z��A���@/W;Symfony/Component/Security/Core/Exception/ExceptionInterface.phpnu�[���PK��ZqUSą�CYY;Symfony/Component/Security/Core/Exception/AccessDeniedException.phpnu�[���PK��Z�'��EQ\;Symfony/Component/Security/Core/Exception/AuthenticationException.phpnu�[���PK��Z�
	��>�c;Symfony/Component/Security/Core/Exception/RuntimeException.phpnu�[���PK��Z@�	���G0f;Symfony/Component/Security/Core/Exception/ProviderNotFoundException.phpnu�[���PK��Z�ĸ���X�i;Symfony/Component/Security/Core/Exception/AuthenticationCredentialsNotFoundException.phpnu�[���PK��Z:���AADm;Symfony/Component/Security/Core/Exception/AccountStatusException.phpnu�[���PK��Z7w�-��L�r;Symfony/Component/Security/Core/Exception/AuthenticationServiceException.phpnu�[���PK��ZxB��EIv;Symfony/Component/Security/Core/Exception/AccountExpiredException.phpnu�[���PK��Z�և��?Ny;Symfony/Component/Security/Core/Exception/DisabledException.phpnu�[���PK��Ze���CA|;Symfony/Component/Security/Core/Exception/NonceExpiredException.phpnu�[���PK��Zʝ�9Fo;Symfony/Component/Security/Core/Exception/InvalidArgumentException.phpnu�[���PK��Z�O���G�;Symfony/Component/Security/Core/Exception/InvalidCsrfTokenException.phpnu�[���PK��Z�Õ�

5�;Symfony/Component/Security/Core/Util/SecureRandom.phpnu�[���PK��ZU��a��4e�;Symfony/Component/Security/Core/Util/StringUtils.phpnu�[���PK��Z��T�,,3��;Symfony/Component/Security/Core/Util/ClassUtils.phpnu�[���PK��Z�	���>8�;Symfony/Component/Security/Core/Util/SecureRandomInterface.phpnu�[���PK��Z�m2���G1�;Symfony/Component/Security/Core/Authorization/AccessDecisionManager.phpnu�[���PK��Z�З~��Ak�;Symfony/Component/Security/Core/Authorization/Voter/RoleVoter.phpnu�[���PK��Z~f�J��;Symfony/Component/Security/Core/Authorization/Voter/RoleHierarchyVoter.phpnu�[���PK��Z��`c��G]�;Symfony/Component/Security/Core/Authorization/Voter/ExpressionVoter.phpnu�[���PK��Z�X,mJ��;Symfony/Component/Security/Core/Authorization/Voter/AuthenticatedVoter.phpnu�[���PK��Z�>��F*�;Symfony/Component/Security/Core/Authorization/Voter/VoterInterface.phpnu�[���PK��Z�:22PR�;Symfony/Component/Security/Core/Authorization/AccessDecisionManagerInterface.phpnu�[���PK��Zѵ^��D��;Symfony/Component/Security/Core/Authorization/ExpressionLanguage.phpnu�[���PK��Z����=��;Symfony/Component/Security/Core/User/UserCheckerInterface.phpnu�[���PK��Z��^ 
 
:�;Symfony/Component/Security/Core/User/ChainUserProvider.phpnu�[���PK��ZD�$..4r<Symfony/Component/Security/Core/User/UserChecker.phpnu�[���PK��Z��6bYY>
<Symfony/Component/Security/Core/User/AdvancedUserInterface.phpnu�[���PK��Z����	�	6�<Symfony/Component/Security/Core/User/UserInterface.phpnu�[���PK��Z/!�=�"<Symfony/Component/Security/Core/User/InMemoryUserProvider.phpnu�[���PK��Z��//;]/<Symfony/Component/Security/Core/User/EquatableInterface.phpnu�[���PK��Zs�v�W	W	>�3<Symfony/Component/Security/Core/User/UserProviderInterface.phpnu�[���PK��Z��1G	G	-�=<Symfony/Component/Security/Core/User/User.phpnu�[���PK��Z'�za!!3`G<Symfony/Component/Security/Core/SecurityContext.phpnu�[���PK��Z��l�8�R<Symfony/Component/Security/Core/AuthenticationEvents.phpnu�[���PK��Zx��$ccPOW<Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.phpnu�[���PK��Z¬>
##R2f<Symfony/Component/Security/Core/Authentication/SimplePreAuthenticatorInterface.phpnu�[���PK��Z��W��O�h<Symfony/Component/Security/Core/Authentication/SimpleAuthenticatorInterface.phpnu�[���PK��Z>,�vvX%l<Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.phpnu�[���PK��Z�U#s<Symfony/Component/Security/Core/Authentication/Provider/DaoAuthenticationProvider.phpnu�[���PK��Z�b�yyVƂ<Symfony/Component/Security/Core/Authentication/Provider/UserAuthenticationProvider.phpnu�[���PK��Z�J�A��\ŗ<Symfony/Component/Security/Core/Authentication/Provider/RememberMeAuthenticationProvider.phpnu�[���PK��Z��X���[$�<Symfony/Component/Security/Core/Authentication/Provider/AnonymousAuthenticationProvider.phpnu�[���PK��Z��a�""[b�<Symfony/Component/Security/Core/Authentication/Provider/AuthenticationProviderInterface.phpnu�[���PK��Zun\�
�
b�<Symfony/Component/Security/Core/Authentication/Provider/PreAuthenticatedAuthenticationProvider.phpnu�[���PK��Z��r3WWW��<Symfony/Component/Security/Core/Authentication/AuthenticationTrustResolverInterface.phpnu�[���PK��Z�Zvm��St�<Symfony/Component/Security/Core/Authentication/RememberMe/InMemoryTokenProvider.phpnu�[���PK��Z���QZZV��<Symfony/Component/Security/Core/Authentication/RememberMe/PersistentTokenInterface.phpnu�[���PK��Z
�TO��Mx�<Symfony/Component/Security/Core/Authentication/RememberMe/PersistentToken.phpnu�[���PK��Z
C�f��T��<Symfony/Component/Security/Core/Authentication/RememberMe/TokenProviderInterface.phpnu�[���PK��ZJ-W;::S��<Symfony/Component/Security/Core/Authentication/SimpleFormAuthenticatorInterface.phpnu�[���PK��Z:�6��Nv�<Symfony/Component/Security/Core/Authentication/AuthenticationTrustResolver.phpnu�[���PK��Zf�	�Q��<Symfony/Component/Security/Core/Authentication/AuthenticationManagerInterface.phpnu�[���PK��Zγ�__N�<Symfony/Component/Security/Core/Authentication/Token/PreAuthenticatedToken.phpnu�[���PK��Z��4��F��<Symfony/Component/Security/Core/Authentication/Token/AbstractToken.phpnu�[���PK��Z�tC��G)=Symfony/Component/Security/Core/Authentication/Token/TokenInterface.phpnu�[���PK��Z{Z�--G�=Symfony/Component/Security/Core/Authentication/Token/AnonymousToken.phpnu�[���PK��Z�6��`
`
N&=Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.phpnu�[���PK��Z��w�	�	H*=Symfony/Component/Security/Core/Authentication/Token/RememberMeToken.phpnu�[���PK��Zm�|JJK�3=Symfony/Component/Security/Core/Resources/translations/security.sr_Cyrl.xlfnu�[���PK��Z&MЎ�
�
F�C=Symfony/Component/Security/Core/Resources/translations/security.es.xlfnu�[���PK��ZM-�@F�Q=Symfony/Component/Security/Core/Resources/translations/security.fa.xlfnu�[���PK��Zd�e��
�
F�a=Symfony/Component/Security/Core/Resources/translations/security.fr.xlfnu�[���PK��Z�)�
�
F�o=Symfony/Component/Security/Core/Resources/translations/security.ro.xlfnu�[���PK��Z�y��
�
F�}=Symfony/Component/Security/Core/Resources/translations/security.gl.xlfnu�[���PK��Z��u^
^
F�=Symfony/Component/Security/Core/Resources/translations/security.sv.xlfnu�[���PK��Z���ţ
�
F��=Symfony/Component/Security/Core/Resources/translations/security.ca.xlfnu�[���PK��Zo'�N�
�
Fϧ=Symfony/Component/Security/Core/Resources/translations/security.de.xlfnu�[���PK��Z.W�
�
F
�=Symfony/Component/Security/Core/Resources/translations/security.no.xlfnu�[���PK��Z��ق
�
F�=Symfony/Component/Security/Core/Resources/translations/security.sk.xlfnu�[���PK��Z�w=���F�=Symfony/Component/Security/Core/Resources/translations/security.ru.xlfnu�[���PK��ZUɎd
d
F3�=Symfony/Component/Security/Core/Resources/translations/security.sl.xlfnu�[���PK��Z���
�
F
�=Symfony/Component/Security/Core/Resources/translations/security.lb.xlfnu�[���PK��Z�#@�y
y
IW�=Symfony/Component/Security/Core/Resources/translations/security.pt_PT.xlfnu�[���PK��ZYW��g
g
KI>Symfony/Component/Security/Core/Resources/translations/security.sr_Latn.xlfnu�[���PK��Z�=���
�
I+>Symfony/Component/Security/Core/Resources/translations/security.pt_BR.xlfnu�[���PK��Z(���
�
F&(>Symfony/Component/Security/Core/Resources/translations/security.cs.xlfnu�[���PK��ZO�
�
F'6>Symfony/Component/Security/Core/Resources/translations/security.it.xlfnu�[���PK��ZTk�f��F+D>Symfony/Component/Security/Core/Resources/translations/security.ar.xlfnu�[���PK��Z��|H�
�
F[S>Symfony/Component/Security/Core/Resources/translations/security.hu.xlfnu�[���PK��Z�p�U�
�
Fa>Symfony/Component/Security/Core/Resources/translations/security.nl.xlfnu�[���PK��Z'���{
{
F�o>Symfony/Component/Security/Core/Resources/translations/security.tr.xlfnu�[���PK��ZU����F�}>Symfony/Component/Security/Core/Resources/translations/security.el.xlfnu�[���PK��Z.�X:
:
F�>Symfony/Component/Security/Core/Resources/translations/security.en.xlfnu�[���PK��Z�d
�
�
F��>Symfony/Component/Security/Core/Resources/translations/security.pl.xlfnu�[���PK��Z5�˙��F��>Symfony/Component/Security/Core/Resources/translations/security.ua.xlfnu�[���PK��Zz��
J
J
F��>Symfony/Component/Security/Core/Resources/translations/security.da.xlfnu�[���PK��Z��Eh��Dj�>Symfony/Component/Security/Core/Event/AuthenticationFailureEvent.phpnu�[���PK��Z+\�
//=��>Symfony/Component/Security/Core/Event/AuthenticationEvent.phpnu�[���PK��Z���(SSA,�>Symfony/Component/Security/Resources/translations/security.bg.xlfnu�[���PK��Zm�|JJF��>Symfony/Component/Security/Resources/translations/security.sr_Cyrl.xlfnu�[���PK��Z&MЎ�
�
A��>Symfony/Component/Security/Resources/translations/security.es.xlfnu�[���PK��ZM-�@A�>Symfony/Component/Security/Resources/translations/security.fa.xlfnu�[���PK��Z���An?Symfony/Component/Security/Resources/translations/security.vi.xlfnu�[���PK��Zd�e��
�
A�?Symfony/Component/Security/Resources/translations/security.fr.xlfnu�[���PK��Z�)�
�
A.)?Symfony/Component/Security/Resources/translations/security.ro.xlfnu�[���PK��Z�y��
�
A,7?Symfony/Component/Security/Resources/translations/security.gl.xlfnu�[���PK��Z��u^
^
A<E?Symfony/Component/Security/Resources/translations/security.sv.xlfnu�[���PK��Z���ţ
�
AS?Symfony/Component/Security/Resources/translations/security.ca.xlfnu�[���PK��Zo'�N�
�
Aa?Symfony/Component/Security/Resources/translations/security.de.xlfnu�[���PK��Z����
�
AXo?Symfony/Component/Security/Resources/translations/security.no.xlfnu�[���PK��Z�R�wD
D
AN}?Symfony/Component/Security/Resources/translations/security.id.xlfnu�[���PK��Z��ق
�
A�?Symfony/Component/Security/Resources/translations/security.sk.xlfnu�[���PK��Z�w=���A��?Symfony/Component/Security/Resources/translations/security.ru.xlfnu�[���PK��ZUɎd
d
A$�?Symfony/Component/Security/Resources/translations/security.sl.xlfnu�[���PK��Z]��W
W
A��?Symfony/Component/Security/Resources/translations/security.hr.xlfnu�[���PK��Z���
�
A��?Symfony/Component/Security/Resources/translations/security.lb.xlfnu�[���PK��Z�#@�y
y
D�?Symfony/Component/Security/Resources/translations/security.pt_PT.xlfnu�[���PK��ZYW��g
g
F��?Symfony/Component/Security/Resources/translations/security.sr_Latn.xlfnu�[���PK��Z���Y�
�
D��?Symfony/Component/Security/Resources/translations/security.pt_BR.xlfnu�[���PK��Z(���
�
A�?Symfony/Component/Security/Resources/translations/security.cs.xlfnu�[���PK��ZO�
�
A�
@Symfony/Component/Security/Resources/translations/security.it.xlfnu�[���PK��ZTk�f��A�@Symfony/Component/Security/Resources/translations/security.ar.xlfnu�[���PK��Z��|H�
�
A�'@Symfony/Component/Security/Resources/translations/security.hu.xlfnu�[���PK��Z�p�U�
�
A6@Symfony/Component/Security/Resources/translations/security.nl.xlfnu�[���PK��Z'���{
{
AID@Symfony/Component/Security/Resources/translations/security.tr.xlfnu�[���PK��ZU����A5R@Symfony/Component/Security/Resources/translations/security.el.xlfnu�[���PK��Z��Dt��D�b@Symfony/Component/Security/Resources/translations/security.zh_CN.xlfnu�[���PK��Z.�X:
:
A�o@Symfony/Component/Security/Resources/translations/security.en.xlfnu�[���PK��Z�d
�
�
A�}@Symfony/Component/Security/Resources/translations/security.pl.xlfnu�[���PK��Z�f488A��@Symfony/Component/Security/Resources/translations/security.ja.xlfnu�[���PK��Z5�˙��AC�@Symfony/Component/Security/Resources/translations/security.ua.xlfnu�[���PK��Z��J
J
A7�@Symfony/Component/Security/Resources/translations/security.da.xlfnu�[���PK��Z�@V��@�@Symfony/Component/Validator/ConstraintViolationListInterface.phpnu�[���PK��Zz��911::�@Symfony/Component/Validator/ObjectInitializerInterface.phpnu�[���PK��Z,�'��<��@Symfony/Component/Validator/ConstraintValidatorInterface.phpnu�[���PK��ZK��}}1��@Symfony/Component/Validator/DefaultTranslator.phpnu�[���PK��Z�����3��@Symfony/Component/Validator/ConstraintViolation.phpnu�[���PK��ZS�b'b'0��@Symfony/Component/Validator/ValidatorBuilder.phpnu�[���PK��Z�S�UU>�ASymfony/Component/Validator/GroupSequenceProviderInterface.phpnu�[���PK��Z�d�)xASymfony/Component/Validator/Validator.phpnu�[���PK��Z��&{{9�2ASymfony/Component/Validator/ValidatorBuilderInterface.phpnu�[���PK��Zo��SS*�HASymfony/Component/Validator/autoloader.phpnu�[���PK��Z����C0C09{JASymfony/Component/Validator/ExecutionContextInterface.phpnu�[���PK��Z}`���9'{ASymfony/Component/Validator/PropertyMetadataInterface.phpnu�[���PK��Z�޽/!/!0z�ASymfony/Component/Validator/ExecutionContext.phpnu�[���PK��Z+s���:	�ASymfony/Component/Validator/ConstraintValidatorFactory.phpnu�[���PK��Z�Sq�KK1l�ASymfony/Component/Validator/MetadataInterface.phpnu�[���PK��Z�R'<�ASymfony/Component/Validator/ConstraintViolationInterface.phpnu�[���PK��ZƭW��*��ASymfony/Component/Validator/Constraint.phpnu�[���PK��Z|����6l�ASymfony/Component/Validator/Mapping/GetterMetadata.phpnu�[���PK��Zr
���8��ASymfony/Component/Validator/Mapping/PropertyMetadata.phpnu�[���PK��Z�t�././5��ASymfony/Component/Validator/Mapping/ClassMetadata.phpnu�[���PK��Z��!"	"	7wBSymfony/Component/Validator/Mapping/ElementMetadata.phpnu�[���PK��Z�/�;aa6)BSymfony/Component/Validator/Mapping/MemberMetadata.phpnu�[���PK��Z+�d%%<�@BSymfony/Component/Validator/Mapping/Cache/CacheInterface.phpnu�[���PK��Z����6XEBSymfony/Component/Validator/Mapping/Cache/ApcCache.phpnu�[���PK��Zd#[N��<IJBSymfony/Component/Validator/Mapping/ClassMetadataFactory.phpnu�[���PK��Z��ʚ��9�WBSymfony/Component/Validator/Mapping/Loader/FileLoader.phpnu�[���PK��Zk�G+��=�[BSymfony/Component/Validator/Mapping/Loader/AbstractLoader.phpnu�[���PK��ZRᠯ��=dBSymfony/Component/Validator/Mapping/Loader/XmlFilesLoader.phpnu�[���PK��Z�?��>gBSymfony/Component/Validator/Mapping/Loader/YamlFilesLoader.phpnu�[���PK��Z�����:jBSymfony/Component/Validator/Mapping/Loader/LoaderChain.phpnu�[���PK��ZT�b��AAqBSymfony/Component/Validator/Mapping/Loader/StaticMethodLoader.phpnu�[���PK��Z�>�??>�wBSymfony/Component/Validator/Mapping/Loader/LoaderInterface.phpnu�[���PK��Z���*��:8zBSymfony/Component/Validator/Mapping/Loader/FilesLoader.phpnu�[���PK��ZTO��--c)�BSymfony/Component/Validator/Mapping/Loader/schema/dic/constraint-mapping/constraint-mapping-1.0.xsdnu�[���PK��Z;Q�F11<�BSymfony/Component/Validator/Mapping/Loader/XmlFileLoader.phpnu�[���PK��Z	lw#QQ?��BSymfony/Component/Validator/Mapping/Loader/AnnotationLoader.phpnu�[���PK��Z'��pkk=F�BSymfony/Component/Validator/Mapping/Loader/YamlFileLoader.phpnu�[���PK��Z�۔��@�BSymfony/Component/Validator/Mapping/BlackholeMetadataFactory.phpnu�[���PK��Z�L8��
�
:$�BSymfony/Component/Validator/ValidationVisitorInterface.phpnu�[���PK��ZQ���VV:j�BSymfony/Component/Validator/Exception/MappingException.phpnu�[���PK��Z��y��@*�BSymfony/Component/Validator/Exception/BadMethodCallException.phpnu�[���PK��ZL�ЉRRA��BSymfony/Component/Validator/Exception/InvalidOptionsException.phpnu�[���PK��Zk1+WW<V�BSymfony/Component/Validator/Exception/ValidatorException.phpnu�[���PK��Z�b�<<A�BSymfony/Component/Validator/Exception/UnexpectedTypeException.phpnu�[���PK��Z�1�"ccG��BSymfony/Component/Validator/Exception/ConstraintDefinitionException.phpnu�[���PK��Z�T����<��BSymfony/Component/Validator/Exception/ExceptionInterface.phpnu�[���PK��Zz����:��BSymfony/Component/Validator/Exception/RuntimeException.phpnu�[���PK��Z��x��A�BSymfony/Component/Validator/Exception/NoSuchMetadataException.phpnu�[���PK��Zu��RRA�BSymfony/Component/Validator/Exception/MissingOptionsException.phpnu�[���PK��ZM��#^^B�BSymfony/Component/Validator/Exception/GroupDefinitionException.phpnu�[���PK��Z�\��B��BSymfony/Component/Validator/Exception/InvalidArgumentException.phpnu�[���PK��Z�U�<<3!�BSymfony/Component/Validator/ClassBasedInterface.phpnu�[���PK��Z;5t��7��BSymfony/Component/Validator/ConstraintViolationList.phpnu�[���PK��ZAbI̲�1�CSymfony/Component/Validator/ValidationVisitor.phpnu�[���PK��Zbh��B�$CSymfony/Component/Validator/PropertyMetadataContainerInterface.phpnu�[���PK��ZY����8*CSymfony/Component/Validator/MetadataFactoryInterface.phpnu�[���PK��ZD#��?�?DX.CSymfony/Component/Validator/Resources/translations/validators.en.xlfnu�[���PK��Z-���uCuCDgnCSymfony/Component/Validator/Resources/translations/validators.sk.xlfnu�[���PK��Z�τ}K}KDP�CSymfony/Component/Validator/Resources/translations/validators.uk.xlfnu�[���PK��Z��-�1�1DA�CSymfony/Component/Validator/Resources/translations/validators.cy.xlfnu�[���PK��Z�m�w�B�BD�0DSymfony/Component/Validator/Resources/translations/validators.pl.xlfnu�[���PK��Z@T�\44D�sDSymfony/Component/Validator/Resources/translations/validators.af.xlfnu�[���PK��Z�b�@�@DB�DSymfony/Component/Validator/Resources/translations/validators.pt.xlfnu�[���PK��Ze]߭A�AII�DSymfony/Component/Validator/Resources/translations/validators.sr_Cyrl.xlfnu�[���PK��Z�a�2�2Do+ESymfony/Component/Validator/Resources/translations/validators.fi.xlfnu�[���PK��Z��"}2A2AD�^ESymfony/Component/Validator/Resources/translations/validators.es.xlfnu�[���PK��Zs�E#�A�AD6�ESymfony/Component/Validator/Resources/translations/validators.de.xlfnu�[���PK��Z=^��::D��ESymfony/Component/Validator/Resources/translations/validators.it.xlfnu�[���PK��Z	���AADFSymfony/Component/Validator/Resources/translations/validators.ca.xlfnu�[���PK��ZD��#"#"Dx^FSymfony/Component/Validator/Resources/translations/validators.mn.xlfnu�[���PK��Z��-tZMZMD�FSymfony/Component/Validator/Resources/translations/validators.ru.xlfnu�[���PK��Z<��bKKD��FSymfony/Component/Validator/Resources/translations/validators.bg.xlfnu�[���PK��Z����A�ADoGSymfony/Component/Validator/Resources/translations/validators.ro.xlfnu�[���PK��Z�ժN@@D�\GSymfony/Component/Validator/Resources/translations/validators.nl.xlfnu�[���PK��Z�%�N�=�=DW�GSymfony/Component/Validator/Resources/translations/validators.et.xlfnu�[���PK��Z
��GGDs�GSymfony/Component/Validator/Resources/translations/validators.fa.xlfnu�[���PK��Z-�L>L>D�"HSymfony/Component/Validator/Resources/translations/validators.id.xlfnu�[���PK��Z˺�Q1Q1D�aHSymfony/Component/Validator/Resources/translations/validators.tr.xlfnu�[���PK��Z	�)�B�BDp�HSymfony/Component/Validator/Resources/translations/validators.cs.xlfnu�[���PK��Z�6��%=%=G��HSymfony/Component/Validator/Resources/translations/validators.zh_CN.xlfnu�[���PK��Z�PhBhBDAISymfony/Component/Validator/Resources/translations/validators.lt.xlfnu�[���PK��Z���+BBDWISymfony/Component/Validator/Resources/translations/validators.fr.xlfnu�[���PK��Z(��=A=AD��ISymfony/Component/Validator/Resources/translations/validators.gl.xlfnu�[���PK��Z���wX@X@DN�ISymfony/Component/Validator/Resources/translations/validators.hr.xlfnu�[���PK��ZY�.3�5�5DJSymfony/Component/Validator/Resources/translations/validators.sq.xlfnu�[���PK��Z(�eeD3RJSymfony/Component/Validator/Resources/translations/validators.nb.xlfnu�[���PK��Z���t�A�ADrJSymfony/Component/Validator/Resources/translations/validators.eu.xlfnu�[���PK��Z1ar�==Ga�JSymfony/Component/Validator/Resources/translations/validators.zh_TW.xlfnu�[���PK��Z�T�л@�@G��JSymfony/Component/Validator/Resources/translations/validators.pt_BR.xlfnu�[���PK��Z���1�1D3KSymfony/Component/Validator/Resources/translations/validators.no.xlfnu�[���PK��Z��n�C�CDWeKSymfony/Component/Validator/Resources/translations/validators.sl.xlfnu�[���PK��Zq�b�?�?D��KSymfony/Component/Validator/Resources/translations/validators.lb.xlfnu�[���PK��Z93XaoAoAD�KSymfony/Component/Validator/Resources/translations/validators.hu.xlfnu�[���PK��Z����M�MD,LSymfony/Component/Validator/Resources/translations/validators.el.xlfnu�[���PK��Z��9>�5�5D@zLSymfony/Component/Validator/Resources/translations/validators.da.xlfnu�[���PK��Z���AAD��LSymfony/Component/Validator/Resources/translations/validators.ja.xlfnu�[���PK��Z�Q>�?�?D �LSymfony/Component/Validator/Resources/translations/validators.sv.xlfnu�[���PK��Zv_��w,w,D2MSymfony/Component/Validator/Resources/translations/validators.hy.xlfnu�[���PK��Z����O�OD_MSymfony/Component/Validator/Resources/translations/validators.ar.xlfnu�[���PK��Z�1�^�4�4I=�MSymfony/Component/Validator/Resources/translations/validators.sr_Latn.xlfnu�[���PK��Z@T'%�B�BDt�MSymfony/Component/Validator/Resources/translations/validators.vi.xlfnu�[���PK��Z��tý5�5D�'NSymfony/Component/Validator/Resources/translations/validators.he.xlfnu�[���PK��Z��D��<�]NSymfony/Component/Validator/Constraints/NotNullValidator.phpnu�[���PK��ZD~�SS2"aNSymfony/Component/Validator/Constraints/Choice.phpnu�[���PK��Z�~%ɋ�1�eNSymfony/Component/Validator/Constraints/Valid.phpnu�[���PK��Z�+��6�iNSymfony/Component/Validator/Constraints/NotEqualTo.phpnu�[���PK��Zm�Լ\\ClNSymfony/Component/Validator/Constraints/NotIdenticalToValidator.phpnu�[���PK��ZĿ:�KK6�nNSymfony/Component/Validator/Constraints/Expression.phpnu�[���PK��Z�خ
zz?�sNSymfony/Component/Validator/Constraints/Collection/Optional.phpnu�[���PK��Z\,y�zz?�vNSymfony/Component/Validator/Constraints/Collection/Required.phpnu�[���PK��Z
��n��?kyNSymfony/Component/Validator/Constraints/CollectionValidator.phpnu�[���PK��Z��y:g�NSymfony/Component/Validator/Constraints/BlankValidator.phpnu�[���PK��Z�+����0؅NSymfony/Component/Validator/Constraints/Iban.phpnu�[���PK��Z����	�	=�NSymfony/Component/Validator/Constraints/CallbackValidator.phpnu�[���PK��Z�}�&&25�NSymfony/Component/Validator/Constraints/Length.phpnu�[���PK��Z�b�=nn9��NSymfony/Component/Validator/Constraints/IsbnValidator.phpnu�[���PK��Z�<W���:��NSymfony/Component/Validator/Constraints/RegexValidator.phpnu�[���PK��Z^r��

4��NSymfony/Component/Validator/Constraints/Language.phpnu�[���PK��Z���,,0e�NSymfony/Component/Validator/Constraints/Isbn.phpnu�[���PK��Z�EW^��<�NSymfony/Component/Validator/Constraints/CountryValidator.phpnu�[���PK��Zzet�	�	?\�NSymfony/Component/Validator/Constraints/ExpressionValidator.phpnu�[���PK��Z�	�00/��NSymfony/Component/Validator/Constraints/Url.phpnu�[���PK��Z�V`���9"�NSymfony/Component/Validator/Constraints/IbanValidator.phpnu�[���PK��Z��vbb@6�NSymfony/Component/Validator/Constraints/GreaterThanValidator.phpnu�[���PK��ZS탟0�NSymfony/Component/Validator/Constraints/Date.phpnu�[���PK��Z�|4XX8j�NSymfony/Component/Validator/Constraints/UrlValidator.phpnu�[���PK��Zw���3*�NSymfony/Component/Validator/Constraints/NotNull.phpnu�[���PK��ZS�n���0��NSymfony/Component/Validator/Constraints/Null.phpnu�[���PK��Z�o�o��:��NSymfony/Component/Validator/Constraints/RangeValidator.phpnu�[���PK��Z�

4��NSymfony/Component/Validator/Constraints/Currency.phpnu�[���PK��Zrs+���4O�NSymfony/Component/Validator/Constraints/Optional.phpnu�[���PK��Z����449G�NSymfony/Component/Validator/Constraints/IssnValidator.phpnu�[���PK��Z�qp""0�NSymfony/Component/Validator/Constraints/File.phpnu�[���PK��Z5�ʟ��9f�NSymfony/Component/Validator/Constraints/DateValidator.phpnu�[���PK��Z0@���9�OSymfony/Component/Validator/Constraints/NullValidator.phpnu�[���PK��Z�>
i//5�OSymfony/Component/Validator/Constraints/Existence.phpnu�[���PK��ZtUה�4k	OSymfony/Component/Validator/Constraints/Required.phpnu�[���PK��Zm��\\>cOSymfony/Component/Validator/Constraints/AbstractComparison.phpnu�[���PK��Zc��y

4-OSymfony/Component/Validator/Constraints/DateTime.phpnu�[���PK��Zl˘��
�
7�OSymfony/Component/Validator/Constraints/IpValidator.phpnu�[���PK��Z�\\=�OSymfony/Component/Validator/Constraints/LessThanValidator.phpnu�[���PK��Z�U�4Y OSymfony/Component/Validator/Constraints/NotBlank.phpnu�[���PK��Z<8�S��:�"OSymfony/Component/Validator/Constraints/ImageValidator.phpnu�[���PK��Z��Lֻ�6�9OSymfony/Component/Validator/Constraints/CardScheme.phpnu�[���PK��Z��"��?�<OSymfony/Component/Validator/Constraints/CardSchemeValidator.phpnu�[���PK��ZN3�0/MOSymfony/Component/Validator/Constraints/Type.phpnu�[���PK��Z@vqq9�POSymfony/Component/Validator/Constraints/FileValidator.phpnu�[���PK��Z�'����1oiOSymfony/Component/Validator/Constraints/Count.phpnu�[���PK��Z�̢�VV@�oOSymfony/Component/Validator/Constraints/IdenticalToValidator.phpnu�[���PK��Zd�X�BB0~rOSymfony/Component/Validator/Constraints/Issn.phpnu�[���PK��Z�ଏ�A uOSymfony/Component/Validator/Constraints/GroupSequenceProvider.phpnu�[���PK��Z��}a��7 wOSymfony/Component/Validator/Constraints/GreaterThan.phpnu�[���PK��Z�Ǧ��3xyOSymfony/Component/Validator/Constraints/EqualTo.phpnu�[���PK��Zb+��9�{OSymfony/Component/Validator/Constraints/LuhnValidator.phpnu�[���PK��Z�ٜ?��0ŃOSymfony/Component/Validator/Constraints/True.phpnu�[���PK��Z?����G"�OSymfony/Component/Validator/Constraints/AbstractComparisonValidator.phpnu�[���PK��Z�̋	�	1y�OSymfony/Component/Validator/Constraints/Regex.phpnu�[���PK��Z��BB1e�OSymfony/Component/Validator/Constraints/Range.phpnu�[���PK��Z[�A���;�OSymfony/Component/Validator/Constraints/LessThanOrEqual.phpnu�[���PK��Zq;O3q�OSymfony/Component/Validator/Constraints/Country.phpnu�[���PK��Z5����:ܢOSymfony/Component/Validator/Constraints/EmailValidator.phpnu�[���PK��Z�`�v��;/�OSymfony/Component/Validator/Constraints/LocaleValidator.phpnu�[���PK��Z'㔘7��OSymfony/Component/Validator/Constraints/IdenticalTo.phpnu�[���PK��Z��/�OSymfony/Component/Validator/Constraints/All.phpnu�[���PK��Z{���UU?w�OSymfony/Component/Validator/Constraints/NotEqualToValidator.phpnu�[���PK��Z�ɑ559;�OSymfony/Component/Validator/Constraints/TrueValidator.phpnu�[���PK��Z�(.wwGٿOSymfony/Component/Validator/Constraints/GreaterThanOrEqualValidator.phpnu�[���PK��Z���(��9��OSymfony/Component/Validator/Constraints/TimeValidator.phpnu�[���PK��Z�Fn���8�OSymfony/Component/Validator/Constraints/AllValidator.phpnu�[���PK��Z�c����.�OSymfony/Component/Validator/Constraints/Ip.phpnu�[���PK��ZHð�2R�OSymfony/Component/Validator/Constraints/Locale.phpnu�[���PK��ZQ��=��OSymfony/Component/Validator/Constraints/LanguageValidator.phpnu�[���PK��ZaHβ;+�OSymfony/Component/Validator/Constraints/ChoiceValidator.phpnu�[���PK��Z�{HH1�OSymfony/Component/Validator/Constraints/Email.phpnu�[���PK��Zx�.`ss4��OSymfony/Component/Validator/Constraints/Callback.phpnu�[���PK��Z�����=��OSymfony/Component/Validator/Constraints/DateTimeValidator.phpnu�[���PK��Z�&����0�OSymfony/Component/Validator/Constraints/Luhn.phpnu�[���PK��Z�F���9<�OSymfony/Component/Validator/Constraints/TypeValidator.phpnu�[���PK��Z���&��=1�OSymfony/Component/Validator/Constraints/NotBlankValidator.phpnu�[���PK��Ze8�B�
�
6�PSymfony/Component/Validator/Constraints/Collection.phpnu�[���PK��ZI7U���1�PSymfony/Component/Validator/Constraints/False.phpnu�[���PK��Z�Q�>MPSymfony/Component/Validator/Constraints/GreaterThanOrEqual.phpnu�[���PK��Z��l��1�PSymfony/Component/Validator/Constraints/Blank.phpnu�[���PK��Z�CG^LL<PSymfony/Component/Validator/Constraints/EqualToValidator.phpnu�[���PK��Z^�T:�PSymfony/Component/Validator/Constraints/FalseValidator.phpnu�[���PK��ZO��qqD^PSymfony/Component/Validator/Constraints/LessThanOrEqualValidator.phpnu�[���PK��Z����vv9CPSymfony/Component/Validator/Constraints/GroupSequence.phpnu�[���PK��Z_��1"PSymfony/Component/Validator/Constraints/Image.phpnu�[���PK��Z��F;��;''PSymfony/Component/Validator/Constraints/LengthValidator.phpnu�[���PK��Z!xHH:e0PSymfony/Component/Validator/Constraints/CountValidator.phpnu�[���PK��Z��708PSymfony/Component/Validator/Constraints/Time.phpnu�[���PK��ZN�H���4y:PSymfony/Component/Validator/Constraints/LessThan.phpnu�[���PK��Ze��:�<PSymfony/Component/Validator/Constraints/NotIdenticalTo.phpnu�[���PK��Z�Z�=D?PSymfony/Component/Validator/Constraints/CurrencyValidator.phpnu�[���PK��ZGk	��3�DPSymfony/Component/Validator/ConstraintValidator.phpnu�[���PK��ZK�OC�GPSymfony/Component/Validator/ConstraintValidatorFactoryInterface.phpnu�[���PK��Z�8Wc��?KKPSymfony/Component/Validator/GlobalExecutionContextInterface.phpnu�[���PK��Zxf�JJ*KSPSymfony/Component/Validator/Validation.phpnu�[���PK��Zn�r�
�
2�WPSymfony/Component/Validator/ValidatorInterface.phpnu�[���PK��ZC���9MfPSymfony/Component/Templating/StreamingEngineInterface.phpnu�[���PK��Z<,��}}2�jPSymfony/Component/Templating/TemplateReference.phpnu�[���PK��Z�m�tTT+�rPSymfony/Component/Templating/autoloader.phpnu�[���PK��Z����;EtPSymfony/Component/Templating/TemplateReferenceInterface.phpnu�[���PK��ZJ� ���2k|PSymfony/Component/Templating/DebuggerInterface.phpnu�[���PK��ZDZ�_++<�PSymfony/Component/Templating/TemplateNameParserInterface.phpnu�[���PK��Z���3�PSymfony/Component/Templating/TemplateNameParser.phpnu�[���PK��Z�����0Y�PSymfony/Component/Templating/EngineInterface.phpnu�[���PK��Z��b�NN2n�PSymfony/Component/Templating/Asset/PathPackage.phpnu�[���PK��Z���TT1�PSymfony/Component/Templating/Asset/UrlPackage.phpnu�[���PK��Z�o##.ӞPSymfony/Component/Templating/Asset/Package.phpnu�[���PK��Zp�vj��7T�PSymfony/Component/Templating/Asset/PackageInterface.phpnu�[���PK��Z�'��4��PSymfony/Component/Templating/Storage/FileStorage.phpnu�[���PK��Z(�"w��6��PSymfony/Component/Templating/Storage/StringStorage.phpnu�[���PK��Zπ\�0��PSymfony/Component/Templating/Storage/Storage.phpnu�[���PK��Z��>3�PSymfony/Component/Templating/Loader/ChainLoader.phpnu�[���PK��Z�b��8��PSymfony/Component/Templating/Loader/FilesystemLoader.phpnu�[���PK��Z�g((.��PSymfony/Component/Templating/Loader/Loader.phpnu�[���PK��Zy�A�nn3o�PSymfony/Component/Templating/Loader/CacheLoader.phpnu�[���PK��ZI<�D��7@�PSymfony/Component/Templating/Loader/LoaderInterface.phpnu�[���PK��Z+�r�mm3|�PSymfony/Component/Templating/Helper/SlotsHelper.phpnu�[���PK��ZV¤՟�4L�PSymfony/Component/Templating/Helper/AssetsHelper.phpnu�[���PK��ZԷ����7O�PSymfony/Component/Templating/Helper/HelperInterface.phpnu�[���PK��Z����



8U�PSymfony/Component/Templating/Helper/CoreAssetsHelper.phpnu�[���PK��Z�NO��.�QSymfony/Component/Templating/Helper/Helper.phpnu�[���PK��Z_6H1%QSymfony/Component/Templating/DelegatingEngine.phpnu�[���PK��Z?w
y=y=*�QSymfony/Component/Templating/PhpEngine.phpnu�[���PK��Z6�H	��$lTQSymfony/Component/Yaml/Unescaper.phpnu�[���PK��Z�8�n�	�	!_fQSymfony/Component/Yaml/Dumper.phpnu�[���PK��Z�bNN%DpQSymfony/Component/Yaml/autoloader.phpnu�[���PK��Z��X��[�[!�qQSymfony/Component/Yaml/Parser.phpnu�[���PK��Z7MӺ

��QSymfony/Component/Yaml/Yaml.phpnu�[���PK��Z�+�l��7+�QSymfony/Component/Yaml/Exception/ExceptionInterface.phpnu�[���PK��Z�|�-��5X�QSymfony/Component/Yaml/Exception/RuntimeException.phpnu�[���PK��Z�����
�
3��QSymfony/Component/Yaml/Exception/ParseException.phpnu�[���PK��Zؙ՚��2��QSymfony/Component/Yaml/Exception/DumpException.phpnu�[���PK��Z)%�,m
m
"2�QSymfony/Component/Yaml/Escaper.phpnu�[���PK��Zq+�3�?�?!�QSymfony/Component/Yaml/Inline.phpnu�[���PK��Z�ݣ�"�"6�=RSymfony/Component/HttpFoundation/ResponseHeaderBag.phpnu�[���PK��Z�}��xx.�`RSymfony/Component/HttpFoundation/ServerBag.phpnu�[���PK��Z�_DK�
�
5�oRSymfony/Component/HttpFoundation/RedirectResponse.phpnu�[���PK��Z�s
��5�zRSymfony/Component/HttpFoundation/StreamedResponse.phpnu�[���PK��Z��F��+��RSymfony/Component/HttpFoundation/Cookie.phpnu�[���PK��Z�6=��
�
,��RSymfony/Component/HttpFoundation/IpUtils.phpnu�[���PK��ZP�i���,ƩRSymfony/Component/HttpFoundation/FileBag.phpnu�[���PK��Z1y��<�RSymfony/Component/HttpFoundation/RequestMatcherInterface.phpnu�[���PK��ZPE�
XX/f�RSymfony/Component/HttpFoundation/autoloader.phpnu�[���PK��Z8{?���3�RSymfony/Component/HttpFoundation/RequestMatcher.phpnu�[���PK��Z�͢|1Y�RSymfony/Component/HttpFoundation/JsonResponse.phpnu�[���PK��ZVk�b335��RSymfony/Component/HttpFoundation/AcceptHeaderItem.phpnu�[���PK��Zn��OO=k�RSymfony/Component/HttpFoundation/ExpressionRequestMatcher.phpnu�[���PK��Z�a.1'�RSymfony/Component/HttpFoundation/AcceptHeader.phpnu�[���PK��Z\�8��1�SSymfony/Component/HttpFoundation/ParameterBag.phpnu�[���PK��Z��6��B�(SSymfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.phpnu�[���PK��Z5p1��J�7SSymfony/Component/HttpFoundation/File/MimeType/FileinfoMimeTypeGuesser.phpnu�[���PK��Z�qx��L?SSymfony/Component/HttpFoundation/File/MimeType/ExtensionGuesserInterface.phpnu�[���PK��Z�J��LBSSymfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.phpnu�[���PK��Z2�k�	�	C/KSSymfony/Component/HttpFoundation/File/MimeType/ExtensionGuesser.phpnu�[���PK��Z�w�nM�M�KKUSSymfony/Component/HttpFoundation/File/MimeType/MimeTypeExtensionGuesser.phpnu�[���PK��Z�	�L��K�SSymfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesserInterface.phpnu�[���PK��Z�)���.^�SSymfony/Component/HttpFoundation/File/File.phpnu�[���PK��Z�s�-��IQ�SSymfony/Component/HttpFoundation/File/Exception/FileNotFoundException.phpnu�[���PK��Z�S��==Kz�SSymfony/Component/HttpFoundation/File/Exception/UnexpectedTypeException.phpnu�[���PK��Z�1�e��I2TSymfony/Component/HttpFoundation/File/Exception/AccessDeniedException.phpnu�[���PK��Z�gr��CbTSymfony/Component/HttpFoundation/File/Exception/UploadException.phpnu�[���PK��Zo�����A�TSymfony/Component/HttpFoundation/File/Exception/FileException.phpnu�[���PK��Z��ގ�#�#6�TSymfony/Component/HttpFoundation/File/UploadedFile.phpnu�[���PK��Z�7�E	E	13,TSymfony/Component/HttpFoundation/RequestStack.phpnu�[���PK��Z��W���;�5TSymfony/Component/HttpFoundation/Session/Flash/FlashBag.phpnu�[���PK��Z�@��WWECTSymfony/Component/HttpFoundation/Session/Flash/AutoExpireFlashBag.phpnu�[���PK��Za����D�QTSymfony/Component/HttpFoundation/Session/Flash/FlashBagInterface.phpnu�[���PK��Z�=�\\=�YTSymfony/Component/HttpFoundation/Session/SessionInterface.phpnu�[���PK��Z�:au774�lTSymfony/Component/HttpFoundation/Session/Session.phpnu�[���PK��ZM&z�rr@G�TSymfony/Component/HttpFoundation/Session/SessionBagInterface.phpnu�[���PK��Z��eL)�TSymfony/Component/HttpFoundation/Session/Attribute/AttributeBagInterface.phpnu�[���PK��Z��(���C��TSymfony/Component/HttpFoundation/Session/Attribute/AttributeBag.phpnu�[���PK��Z�0�H66MߘTSymfony/Component/HttpFoundation/Session/Attribute/NamespacedAttributeBag.phpnu�[���PK��Z�t�3�3I��TSymfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.phpnu�[���PK��Zގ�!L��TSymfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.phpnu�[���PK��Z��$�

K6�TSymfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.phpnu�[���PK��Z����33Q�TSymfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.phpnu�[���PK��Z�>�q��O}USymfony/Component/HttpFoundation/Session/Storage/Handler/NullSessionHandler.phpnu�[���PK��Zi����R�USymfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.phpnu�[���PK��ZOZ�P""NUSymfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.phpnu�[���PK��Zk��4{{T�<USymfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.phpnu�[���PK��Zu�Y0��U�HUSymfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.phpnu�[���PK��Zڏ۹�
�
S�OUSymfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.phpnu�[���PK��Z�����U[USymfony/Component/HttpFoundation/Session/Storage/Handler/WriteCheckSessionHandler.phpnu�[���PK��Z�zu00LwcUSymfony/Component/HttpFoundation/Session/Storage/PhpBridgeSessionStorage.phpnu�[���PK��Zmwȡ��N#kUSymfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.phpnu�[���PK��Z�2�]��H!sUSymfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.phpnu�[���PK��Z�A��F�USymfony/Component/HttpFoundation/Session/Storage/Proxy/NativeProxy.phpnu�[���PK��Z��g_��@��USymfony/Component/HttpFoundation/Session/Storage/MetadataBag.phpnu�[���PK��Z��?�yyL��USymfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.phpnu�[���PK��Z�K>��2��USymfony/Component/HttpFoundation/ApacheRequest.phpnu�[���PK��Zq�ugd�d�,��USymfony/Component/HttpFoundation/Request.phpnu�[���PK��Zd�}޷%�%7S�VSymfony/Component/HttpFoundation/BinaryFileResponse.phpnu�[���PK��Z���pߋߋ-q�VSymfony/Component/HttpFoundation/Response.phpnu�[���PK��Z?`
�y	y	L�2WSymfony/Component/HttpFoundation/Resources/stubs/SessionHandlerInterface.phpnu�[���PK��ZEY���.�<WSymfony/Component/HttpFoundation/HeaderBag.phpnu�[���PK��Z9�;""'�\WSymfony/Component/BrowserKit/Cookie.phpnu�[���PK��Z.�TT+7WSymfony/Component/BrowserKit/autoloader.phpnu�[���PK��Z�����*�WSymfony/Component/BrowserKit/CookieJar.phpnu�[���PK��Z����
�
(ݞWSymfony/Component/BrowserKit/Request.phpnu�[���PK��Zl�-
-
)(�WSymfony/Component/BrowserKit/Response.phpnu�[���PK��Z㩑eCC'��WSymfony/Component/BrowserKit/Client.phpnu�[���PK��Z��/		(!�WSymfony/Component/BrowserKit/History.phpnu�[���PK��Z��V<nn2�XSymfony/Component/DomCrawler/FormFieldRegistry.phpnu�[���PK��ZLo�TT+gXSymfony/Component/DomCrawler/autoloader.phpnu�[���PK��Z���%XSymfony/Component/DomCrawler/Link.phpnu�[���PK��Z\Ud��	�	0�2XSymfony/Component/DomCrawler/Field/FormField.phpnu�[���PK��ZbڋvB
B
4�<XSymfony/Component/DomCrawler/Field/FileFormField.phpnu�[���PK��Z�	Y[$[$6`JXSymfony/Component/DomCrawler/Field/ChoiceFormField.phpnu�[���PK��Z
ʀ���8!oXSymfony/Component/DomCrawler/Field/TextareaFormField.phpnu�[���PK��Z�����5hsXSymfony/Component/DomCrawler/Field/InputFormField.phpnu�[���PK��Z<�4{bb(PyXSymfony/Component/DomCrawler/Crawler.phpnu�[���PK��Z�
�H7H7%��XSymfony/Component/DomCrawler/Form.phpnu�[���PK��Z�����!�!2aYSymfony/Component/CssSelector/XPath/Translator.phpnu�[���PK��Z��r771J5YSymfony/Component/CssSelector/XPath/XPathExpr.phpnu�[���PK��Z
���;�@YSymfony/Component/CssSelector/XPath/TranslatorInterface.phpnu�[���PK��Z��u��C�EYSymfony/Component/CssSelector/XPath/Extension/FunctionExtension.phpnu�[���PK��Z�܍��L	^YSymfony/Component/CssSelector/XPath/Extension/AttributeMatchingExtension.phpnu�[���PK��Z�Ѽ`PP?WqYSymfony/Component/CssSelector/XPath/Extension/NodeExtension.phpnu�[���PK��Z$p��BB?�YSymfony/Component/CssSelector/XPath/Extension/HtmlExtension.phpnu�[���PK��Zc�-��CǧYSymfony/Component/CssSelector/XPath/Extension/AbstractExtension.phpnu�[���PK��Z��x=	=	F�YSymfony/Component/CssSelector/XPath/Extension/CombinationExtension.phpnu�[���PK��Z ����FʶYSymfony/Component/CssSelector/XPath/Extension/PseudoClassExtension.phpnu�[���PK��Z���||D�YSymfony/Component/CssSelector/XPath/Extension/ExtensionInterface.phpnu�[���PK��Zu�UU,��YSymfony/Component/CssSelector/autoloader.phpnu�[���PK��Z,+?��;��YSymfony/Component/CssSelector/Node/CombinedSelectorNode.phpnu�[���PK��Z�r�I��4��YSymfony/Component/CssSelector/Node/NodeInterface.phpnu�[���PK��Z����3��YSymfony/Component/CssSelector/Node/SelectorNode.phpnu�[���PK��Z�pM2��3��YSymfony/Component/CssSelector/Node/AbstractNode.phpnu�[���PK��Z�Г^FF2��YSymfony/Component/CssSelector/Node/ElementNode.phpnu�[���PK��Z�.��221x�YSymfony/Component/CssSelector/Node/PseudoNode.phpnu�[���PK��Z	�i���0�YSymfony/Component/CssSelector/Node/ClassNode.phpnu�[���PK��Z����bb3Z�YSymfony/Component/CssSelector/Node/NegationNode.phpnu�[���PK��Z�x�2ZSymfony/Component/CssSelector/Node/Specificity.phpnu�[���PK��Z�#^[��/�ZSymfony/Component/CssSelector/Node/HashNode.phpnu�[���PK��ZF��K
K
4�ZSymfony/Component/CssSelector/Node/AttributeNode.phpnu�[���PK��Z�x�3�ZSymfony/Component/CssSelector/Node/FunctionNode.phpnu�[���PK��Zm��c��B ZSymfony/Component/CssSelector/Exception/InternalErrorException.phpnu�[���PK��Z��מ�@#ZSymfony/Component/CssSelector/Exception/SyntaxErrorException.phpnu�[���PK��Z/pTС�D#+ZSymfony/Component/CssSelector/Exception/ExpressionErrorException.phpnu�[���PK��Zgf�GBB>8.ZSymfony/Component/CssSelector/Exception/ExceptionInterface.phpnu�[���PK��Z'[|ɀ�:�0ZSymfony/Component/CssSelector/Exception/ParseException.phpnu�[���PK��Z^�}		-�3ZSymfony/Component/CssSelector/CssSelector.phpnu�[���PK��Z5#� HH<4=ZSymfony/Component/CssSelector/Parser/Shortcut/HashParser.phpnu�[���PK��Zҵܗ��C�CZSymfony/Component/CssSelector/Parser/Shortcut/EmptyStringParser.phpnu�[���PK��ZTR#[PP=IZSymfony/Component/CssSelector/Parser/Shortcut/ClassParser.phpnu�[���PK��Z�Z�>��?�OZSymfony/Component/CssSelector/Parser/Shortcut/ElementParser.phpnu�[���PK��Z���QQ4�UZSymfony/Component/CssSelector/Parser/TokenStream.phpnu�[���PK��Z��6\5
5
>~dZSymfony/Component/CssSelector/Parser/Handler/StringHandler.phpnu�[���PK��Z8�D�^^?!oZSymfony/Component/CssSelector/Parser/Handler/CommentHandler.phpnu�[���PK��Z�X{��<�sZSymfony/Component/CssSelector/Parser/Handler/HashHandler.phpnu�[���PK��Zh��ffAJ{ZSymfony/Component/CssSelector/Parser/Handler/HandlerInterface.phpnu�[���PK��Ze'n��>!ZSymfony/Component/CssSelector/Parser/Handler/NumberHandler.phpnu�[���PK��Z�#BT�ZSymfony/Component/CssSelector/Parser/Handler/IdentifierHandler.phpnu�[���PK��Z����BȌZSymfony/Component/CssSelector/Parser/Handler/WhitespaceHandler.phpnu�[���PK��Z6N�D1D1/̑ZSymfony/Component/CssSelector/Parser/Parser.phpnu�[���PK��Z;���		/o�ZSymfony/Component/CssSelector/Parser/Reader.phpnu�[���PK��Z�AEo118��ZSymfony/Component/CssSelector/Parser/ParserInterface.phpnu�[���PK��Z�zZ<��.u�ZSymfony/Component/CssSelector/Parser/Token.phpnu�[���PK��Z>�<��
�
D��ZSymfony/Component/CssSelector/Parser/Tokenizer/TokenizerPatterns.phpnu�[���PK��Z�S�kFF<��ZSymfony/Component/CssSelector/Parser/Tokenizer/Tokenizer.phpnu�[���PK��Z ��W55DZ�ZSymfony/Component/CssSelector/Parser/Tokenizer/TokenizerEscaping.phpnu�[���PK��Zb�k���+�ZSymfony/Component/EventDispatcher/Event.phpnu�[���PK��Z��YY0�[Symfony/Component/EventDispatcher/autoloader.phpnu�[���PK��Z�
���M�	[Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.phpnu�[���PK��Z,��DD2�[Symfony/Component/EventDispatcher/GenericEvent.phpnu�[���PK��ZcG�11>�[Symfony/Component/EventDispatcher/EventSubscriberInterface.phpnu�[���PK��Zs���> #[Symfony/Component/EventDispatcher/ImmutableEventDispatcher.phpnu�[���PK��ZU����>G,[Symfony/Component/EventDispatcher/EventDispatcherInterface.phpnu�[���PK��Z��NmCu8[Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.phpnu�[���PK��ZY�"��5S[Symfony/Component/EventDispatcher/EventDispatcher.phpnu�[���PK��Z x��
�
1%i[Symfony/Component/Console/Command/ListCommand.phpnu�[���PK��Z�Ƙ�7@7@-Ft[Symfony/Component/Console/Command/Command.phpnu�[���PK��Z�m_
_
1ڴ[Symfony/Component/Console/Command/HelpCommand.phpnu�[���PK��Z\0�E��+��[Symfony/Component/Console/ConsoleEvents.phpnu�[���PK��Z2V��#��[Symfony/Component/Console/Shell.phpnu�[���PK��Z�.�QQ(;�[Symfony/Component/Console/autoloader.phpnu�[���PK��Z�hr�f
f
6��[Symfony/Component/Console/Tester/ApplicationTester.phpnu�[���PK��Z~H(R2��[Symfony/Component/Console/Tester/CommandTester.phpnu�[���PK��Z�Q�)�)-.�[Symfony/Component/Console/Input/ArgvInput.phpnu�[���PK��Z��'��1C'\Symfony/Component/Console/Input/InputArgument.phpnu�[���PK��Z�AM662{4\Symfony/Component/Console/Input/InputInterface.phpnu�[���PK��Z��O�VV/E\Symfony/Component/Console/Input/InputOption.phpnu�[���PK��Z1�E(0(03�\\Symfony/Component/Console/Input/InputDefinition.phpnu�[���PK��Z�΂=�
�
/S�\Symfony/Component/Console/Input/StringInput.phpnu�[���PK��Zgm()��\Symfony/Component/Console/Input/Input.phpnu�[���PK��Zp���%%.�\Symfony/Component/Console/Input/ArrayInput.phpnu�[���PK��Z9K�h^^7��\Symfony/Component/Console/Input/InputAwareInterface.phpnu�[���PK��Zonj�&&<N�\Symfony/Component/Console/Formatter/OutputFormatterStyle.phpnu�[���PK��Z��l���7��\Symfony/Component/Console/Formatter/OutputFormatter.phpnu�[���PK��Z5����E�\Symfony/Component/Console/Formatter/OutputFormatterStyleInterface.phpnu�[���PK��Z�v��
�
A ]Symfony/Component/Console/Formatter/OutputFormatterStyleStack.phpnu�[���PK��ZJp����@u
]Symfony/Component/Console/Formatter/OutputFormatterInterface.phpnu�[���PK��Z��0�KK;�]Symfony/Component/Console/Output/ConsoleOutputInterface.phpnu�[���PK��Z��ϱ}}2~]Symfony/Component/Console/Output/ConsoleOutput.phpnu�[���PK��Z��z�MM4]$]Symfony/Component/Console/Output/OutputInterface.phpnu�[���PK��ZF�$_��/0]Symfony/Component/Console/Output/NullOutput.phpnu�[���PK��Zs�Q;;+A7]Symfony/Component/Console/Output/Output.phpnu�[���PK��Z�,Q�MM1�G]Symfony/Component/Console/Output/StreamOutput.phpnu�[���PK��Zt|X4hh3�T]Symfony/Component/Console/Output/BufferedOutput.phpnu�[���PK��Z�L�UҊҊ)PX]Symfony/Component/Console/Application.phpnu�[���PK��Z���	�	.{�]Symfony/Component/Console/Helper/HelperSet.phpnu�[���PK��Z�z����4��]Symfony/Component/Console/Helper/HelperInterface.phpnu�[���PK��ZZ\���+�]Symfony/Component/Console/Helper/Helper.phpnu�[���PK��Zg�se��4�]Symfony/Component/Console/Helper/FormatterHelper.phpnu�[���PK��Z��2204^Symfony/Component/Console/Helper/TableHelper.phpnu�[���PK��Z"U�1

5�3^Symfony/Component/Console/Helper/DescriptorHelper.phpnu�[���PK��Zs� H��5>^Symfony/Component/Console/Helper/InputAwareHelper.phpnu�[���PK��Z|po.o.3^A^Symfony/Component/Console/Helper/ProgressHelper.phpnu�[���PK��Z&�>@>@10p^Symfony/Component/Console/Helper/DialogHelper.phpnu�[���PK��ZD��uu7ϰ^Symfony/Component/Console/Descriptor/JsonDescriptor.phpnu�[���PK��Z�m��
�
3��^Symfony/Component/Console/Descriptor/Descriptor.phpnu�[���PK��Z�lP�..;��^Symfony/Component/Console/Descriptor/MarkdownDescriptor.phpnu�[���PK��Z�s�X�
�
?c�^Symfony/Component/Console/Descriptor/ApplicationDescription.phpnu�[���PK��Zﶲ��%�%6��^Symfony/Component/Console/Descriptor/XmlDescriptor.phpnu�[���PK��Z����7�_Symfony/Component/Console/Descriptor/TextDescriptor.phpnu�[���PK��ZJZ0<��<@;_Symfony/Component/Console/Descriptor/DescriptorInterface.phpnu�[���PK��Z���v$$7�>_Symfony/Component/Console/Resources/bin/hiddeninput.exenu�[���PK��Z||-&��7�b_Symfony/Component/Console/Event/ConsoleCommandEvent.phpnu�[���PK��Z�Z��&&9e_Symfony/Component/Console/Event/ConsoleTerminateEvent.phpnu�[���PK��Zs�KAA9�j_Symfony/Component/Console/Event/ConsoleExceptionEvent.phpnu�[���PK��Z��
���0Tq_Symfony/Component/Console/Event/ConsoleEvent.phpnu�[���PK��Z]�='YY0lw_Symfony/Component/OptionsResolver/autoloader.phpnu�[���PK��Z��sZ��G%y_Symfony/Component/OptionsResolver/Exception/InvalidOptionsException.phpnu�[���PK��Z�yPH��I�{_Symfony/Component/OptionsResolver/Exception/OptionDefinitionException.phpnu�[���PK��ZE@�^��B~_Symfony/Component/OptionsResolver/Exception/ExceptionInterface.phpnu�[���PK��Zp����G'�_Symfony/Component/OptionsResolver/Exception/MissingOptionsException.phpnu�[���PK��Z��G��>��_Symfony/Component/OptionsResolver/OptionsResolverInterface.phpnu�[���PK��Z^�R��<�<-�_Symfony/Component/OptionsResolver/Options.phpnu�[���PK��Z}���8%8%5��_Symfony/Component/OptionsResolver/OptionsResolver.phpnu�[���PK��ZfJ���5�`Symfony/Component/Config/Definition/NodeInterface.phpnu�[���PK��Z��jkk3w`Symfony/Component/Config/Definition/IntegerNode.phpnu�[���PK��Za�Vp0E`Symfony/Component/Config/Definition/EnumNode.phpnu�[���PK��ZUn=#'#';�`Symfony/Component/Config/Definition/PrototypedArrayNode.phpnu�[���PK��ZU��''1?=`Symfony/Component/Config/Definition/Processor.phpnu�[���PK��Z�C����;�H`Symfony/Component/Config/Definition/Exception/Exception.phpnu�[���PK��Z5-���O�J`Symfony/Component/Config/Definition/Exception/InvalidConfigurationException.phpnu�[���PK��Z����C2N`Symfony/Component/Config/Definition/Exception/UnsetKeyException.phpnu�[���PK��Z��@��F�P`Symfony/Component/Config/Definition/Exception/InvalidTypeException.phpnu�[���PK��Z]F4���L$S`Symfony/Component/Config/Definition/Exception/InvalidDefinitionException.phpnu�[���PK��Z�|�EEGzU`Symfony/Component/Config/Definition/Exception/DuplicateKeyException.phpnu�[���PK��Z�:2&QQM6X`Symfony/Component/Config/Definition/Exception/ForbiddenOverwriteException.phpnu�[���PK��Z#
֕44D[`Symfony/Component/Config/Definition/Builder/NormalizationBuilder.phpnu�[���PK��ZV�hU��;�a`Symfony/Component/Config/Definition/Builder/TreeBuilder.phpnu�[���PK��Z��ʍ��B�h`Symfony/Component/Config/Definition/Builder/EnumNodeDefinition.phpnu�[���PK��Z���{{<�m`Symfony/Component/Config/Definition/Builder/MergeBuilder.phpnu�[���PK��Z,��l[[A�s`Symfony/Component/Config/Definition/Builder/ValidationBuilder.phpnu�[���PK��ZP����E�x`Symfony/Component/Config/Definition/Builder/BooleanNodeDefinition.phpnu�[���PK��Z�e�@��F�|`Symfony/Component/Config/Definition/Builder/VariableNodeDefinition.phpnu�[���PK��Z��8�8C��`Symfony/Component/ConfigPK��Z�ۧY̟̟1.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUri   URI of the namespace
     * @param bool   $multiline      whether to create a multiline tag where each
     *                               attribute gets written to a single line
     * @param string $indent         string used to indent attributes (_auto indents
     *                               attributes so they start at the same column)
     * @param string $linebreak      string used for linebreaks
     * @param bool   $sortAttributes Whether to sort the attributes or not
     *
     * @return string XML start element
     * @see    createEndElement(), createTag()
     */
    public static function createStartElement(
        $qname, $attributes = array(), $namespaceUri = null,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true
    ) {
        // if no attributes hav been set, use empty attributes
        if (!isset($attributes) || !is_array($attributes)) {
            $attributes = array();
        }

        if ($namespaceUri != null) {
            $parts = XML_Util::splitQualifiedName($qname);
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($qname)+2));
            }
        }

        if ($namespaceUri != null) {
            // is a namespace given
            if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
            } else {
                // define this Uri as the default namespace
                $attributes['xmlns'] = $namespaceUri;
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $attributes, $sortAttributes,
            $multiline, $indent, $linebreak
        );
        $element = sprintf('<%s%s>', $qname, $attList);
        return  $element;
    }

    /**
     * Create an end element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createEndElement('myNs:myTag');
     * </code>
     *
     * @param string $qname qualified tagname (including namespace)
     *
     * @return string XML end element
     * @see    createStartElement(), createTag()
     */
    public static function createEndElement($qname)
    {
        $element = sprintf('</%s>', $qname);
        return $element;
    }

    /**
     * Create an XML comment
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createComment('I am a comment');
     * </code>
     *
     * @param string $content content of the comment
     *
     * @return string XML comment
     */
    public static function createComment($content)
    {
        $comment = sprintf('<!-- %s -->', $content);
        return $comment;
    }

    /**
     * Create a CData section
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create a CData section
     * $tag = XML_Util::createCDataSection('I am content.');
     * </code>
     *
     * @param string $data data of the CData section
     *
     * @return string CData section with content
     */
    public static function createCDataSection($data)
    {
        return sprintf(
            '<![CDATA[%s]]>',
            preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data))
        );
    }

    /**
     * Split qualified name and return namespace and local part
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // split qualified tag
     * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
     * </code>
     * the returned array will contain two elements:
     * <pre>
     * array(
     *     'namespace' => 'xslt',
     *     'localPart' => 'stylesheet'
     * );
     * </pre>
     *
     * @param string $qname     qualified tag name
     * @param string $defaultNs default namespace (optional)
     *
     * @return array array containing namespace and local part
     */
    public static function splitQualifiedName($qname, $defaultNs = null)
    {
        if (strstr($qname, ':')) {
            $tmp = explode(':', $qname);
            return array(
                'namespace' => $tmp[0],
                'localPart' => $tmp[1]
            );
        }
        return array(
            'namespace' => $defaultNs,
            'localPart' => $qname
        );
    }

    /**
     * Check, whether string is valid XML name
     *
     * <p>XML names are used for tagname, attribute names and various
     * other, lesser known entities.</p>
     * <p>An XML name may only consist of alphanumeric characters,
     * dashes, undescores and periods, and has to start with a letter
     * or an underscore.</p>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // verify tag name
     * $result = XML_Util::isValidName('invalidTag?');
     * if (is_a($result, 'PEAR_Error')) {
     *    print 'Invalid XML name: ' . $result->getMessage();
     * }
     * </code>
     *
     * @param string $string string that should be checked
     *
     * @return mixed true, if string is a valid XML name, PEAR error otherwise
     *
     * @todo support for other charsets
     * @todo PEAR CS - unable to avoid 85-char limit on second preg_match
     */
    public static function isValidName($string)
    {
        // check for invalid chars
        if (!is_string($string) || !strlen($string) || !preg_match('/^[[:alpha:]_]\\z/', $string[0])) {
            return XML_Util::raiseError(
                'XML names may only start with letter or underscore',
                XML_UTIL_ERROR_INVALID_START
            );
        }

        // check for invalid chars
        $match = preg_match(
            '/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?'
            . '[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/',
            $string
        );
        if (!$match) {
            return XML_Util::raiseError(
                'XML names may only contain alphanumeric '
                . 'chars, period, hyphen, colon and underscores',
                XML_UTIL_ERROR_INVALID_CHARS
            );
        }
        // XML name is valid
        return true;
    }

    /**
     * Replacement for XML_Util::raiseError
     *
     * Avoids the necessity to always require
     * PEAR.php
     *
     * @param string $msg  error message
     * @param int    $code error code
     *
     * @return PEAR_Error
     * @todo   PEAR CS - should this use include_once instead?
     */
    public static function raiseError($msg, $code)
    {
        include_once 'PEAR.php';
        return PEAR::raiseError($msg, $code);
    }
}
?>
PK��Z#F��:�:pearcmd.phpnu�[���<?php
/**
 * PEAR, the PHP Extension and Application Repository
 *
 * Command line interface
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Stig Bakken <ssb@php.net>
 * @author    Tomas V.V.Cox <cox@idecnet.com>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 */

@ob_end_clean();
if (!defined('PEAR_RUNTYPE')) {
    // this is defined in peclcmd.php as 'pecl'
    define('PEAR_RUNTYPE', 'pear');
}
define('PEAR_IGNORE_BACKTRACE', 1);
/**
 * @nodep Gtk
 */
//the space is needed for windows include paths with trailing backslash
// http://pear.php.net/bugs/bug.php?id=19482
if ('/opt/alt/php74/usr/share/pear ' != '@'.'include_path'.'@ ') {
    ini_set('include_path', trim('/opt/alt/php74/usr/share/pear '). PATH_SEPARATOR .  get_include_path());
    $raw = false;
} else {
    // this is a raw, uninstalled pear, either a cvs checkout, or php distro
    ini_set('include_path', dirname(__DIR__) . PATH_SEPARATOR . get_include_path());
    $raw = true;
}
@ini_set('allow_url_fopen', true);
@set_time_limit(0);
ob_implicit_flush(true);
@ini_set('track_errors', true);
@ini_set('html_errors', false);
$_PEAR_PHPDIR = '#$%^&*';
set_error_handler('error_handler');

$pear_package_version = "1.10.16";

require_once 'PEAR.php';
require_once 'PEAR/Frontend.php';
require_once 'PEAR/Config.php';
require_once 'PEAR/Command.php';
require_once 'Console/Getopt.php';


PEAR_Command::setFrontendType('CLI');
$all_commands = PEAR_Command::getCommands();

$argv = Console_Getopt::readPHPArgv();
// fix CGI sapi oddity - the -- in pear.bat/pear is not removed
if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
    unset($argv[1]);
    $argv = array_values($argv);
}
$progname = PEAR_RUNTYPE;
array_shift($argv);
$options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV");
if (PEAR::isError($options)) {
    usage($options);
}

$opts = $options[0];

$fetype = 'CLI';
if ($progname == 'gpear' || $progname == 'pear-gtk') {
    $fetype = 'Gtk2';
} else {
    foreach ($opts as $opt) {
        if ($opt[0] == 'G') {
            $fetype = 'Gtk2';
        }
    }
}

$pear_user_config = '';
$pear_system_config = '';
$store_user_config = false;
$store_system_config = false;
$verbose = 1;

foreach ($opts as $opt) {
    switch ($opt[0]) {
    case 'c':
        $pear_user_config = $opt[1];
        break;
    case 'C':
        $pear_system_config = $opt[1];
        break;
    }
}

PEAR_Command::setFrontendType($fetype);
$ui = &PEAR_Command::getFrontendObject();
$config = &PEAR_Config::singleton($pear_user_config, $pear_system_config);

if (PEAR::isError($config)) {
    $_file = '';
    if ($pear_user_config !== false) {
        $_file .= $pear_user_config;
    }
    if ($pear_system_config !== false) {
        $_file .= '/' . $pear_system_config;
    }
    if ($_file == '/') {
        $_file = 'The default config file';
    }
    $config->getMessage();
    $ui->outputData("ERROR: $_file is not a valid config file or is corrupted.");
    // We stop, we have no idea where we are :)
    exit(1);
}

// this is used in the error handler to retrieve a relative path
$_PEAR_PHPDIR = $config->get('php_dir');
$ui->setConfig($config);
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError"));

$verbose = $config->get("verbose");
$cmdopts = array();

if ($raw) {
    if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) {
        $found = false;
        foreach ($opts as $opt) {
            if ($opt[0] == 'd' || $opt[0] == 'D') {
                // the user knows what they are doing, and are setting config values
                $found = true;
            }
        }
        if (!$found) {
            // no prior runs, try to install PEAR
            $parent = dirname(__FILE__);
            if (strpos($parent, 'scripts')) {
                $grandparent = dirname($parent);
                $packagexml = $grandparent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $grandparent;
            } else {
                $packagexml = $parent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $parent;
            }
            if (file_exists($packagexml)) {
                $options[1] = array(
                    'install',
                    $packagexml
                );
                $config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php');
                $config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data');
                $config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs');
                $config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests');
                $config->set(
                    'ext_dir',
                    $pearbase . DIRECTORY_SEPARATOR . 'extensions'
                );
                $config->set('bin_dir', $pearbase);
                $config->mergeConfigFile($pearbase . 'pear.ini', false);
                $config->store();
                $config->set('auto_discover', 1);
            }
        }
    }
}
foreach ($opts as $opt) {
    $param = !empty($opt[1]) ? $opt[1] : true;
    switch ($opt[0]) {
    case 'd':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected -d config_value=value, ' .
                'received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'user');
        break;
    case 'D':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'system');
        break;
    case 's':
        $store_user_config = true;
        break;
    case 'S':
        $store_system_config = true;
        break;
    case 'u':
        $config->remove($param, 'user');
        break;
    case 'v':
        $config->set('verbose', $config->get('verbose') + 1);
        break;
    case 'q':
        $config->set('verbose', $config->get('verbose') - 1);
        break;
    case 'V':
        usage(null, 'version');
    case 'c':
    case 'C':
        break;
    default:
        // all non pear params goes to the command
        $cmdopts[$opt[0]] = $param;
        break;
    }
}

if ($store_system_config) {
    $config->store('system');
}

if ($store_user_config) {
    $config->store('user');
}

$command = (isset($options[1][0])) ? $options[1][0] : null;
if (empty($command) && ($store_user_config || $store_system_config)) {
    exit;
}

if ($fetype == 'Gtk2') {
    if (!$config->validConfiguration()) {
        PEAR::raiseError(
            "CRITICAL ERROR: no existing valid configuration files found in " .
            "files '$pear_user_config' or '$pear_system_config', " .
            "please copy an existing configuration file to one of these " .
            "locations, or use the -c and -s options to create one"
        );
    }
    Gtk::main();
} else {
    do {
        if ($command == 'help') {
            usage(null, isset($options[1][1]) ? $options[1][1] : null);
        }

        if (!$config->validConfiguration()) {
            PEAR::raiseError(
                "CRITICAL ERROR: no existing valid configuration files found " .
                "in files '$pear_user_config' or '$pear_system_config', " .
                "please copy an existing configuration file to one of " .
                "these locations, or use the -c and -s options to create one"
            );
        }

        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        $cmd = PEAR_Command::factory($command, $config);
        PEAR::popErrorHandling();
        if (PEAR::isError($cmd)) {
            usage(null, isset($options[1][0]) ? $options[1][0] : null);
        }

        $short_args = $long_args = null;
        PEAR_Command::getGetoptArgs($command, $short_args, $long_args);
        array_shift($options[1]);
        $tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args);

        if (PEAR::isError($tmp)) {
            break;
        }

        list($tmpopt, $params) = $tmp;
        $opts = array();
        foreach ($tmpopt as $foo => $tmp2) {
            list($opt, $value) = $tmp2;
            if ($value === null) {
                $value = true; // options without args
            }

            if (strlen($opt) == 1) {
                $cmdoptions = $cmd->getOptions($command);
                foreach ($cmdoptions as $o => $d) {
                    if (isset($d['shortopt']) && $d['shortopt'] == $opt) {
                        $opts[$o] = $value;
                    }
                }
            } else {
                if (substr($opt, 0, 2) == '--') {
                    $opts[substr($opt, 2)] = $value;
                }
            }
        }

        $ok = $cmd->run($command, $opts, $params);
        if ($ok === false) {
            PEAR::raiseError("unknown command `$command'");
        }

        if (PEAR::isError($ok)) {
            PEAR::setErrorHandling(
                PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")
            );
            PEAR::raiseError($ok);
        }
    } while (false);
}

// {{{ usage()

/**
 * Display usage information
 *
 * @param mixed $error       Optional error message
 * @param mixed $helpsubject Optional subject/command to display help for
 *
 * @return void
 */
function usage($error = null, $helpsubject = null)
{
    global $progname, $all_commands;
    $stdout = fopen('php://stdout', 'w');
    if (PEAR::isError($error)) {
        fputs($stdout, $error->getMessage() . "\n");
    } elseif ($error !== null) {
        fputs($stdout, "$error\n");
    }

    if ($helpsubject != null) {
        $put = cmdHelp($helpsubject);
    } else {
        $put = "Commands:\n";
        $maxlen = max(array_map("strlen", $all_commands));
        $formatstr = "%-{$maxlen}s  %s\n";
        ksort($all_commands);
        foreach ($all_commands as $cmd => $class) {
            $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd));
        }
        $put .=
            "Usage: $progname [options] command [command-options] <parameters>\n".
            "Type \"$progname help options\" to list all options.\n".
            "Type \"$progname help shortcuts\" to list all command shortcuts.\n".
            "Type \"$progname help version\" or ".
            "\"$progname version\" to list version information.\n".
            "Type \"$progname help <command>\" to get the help ".
            "for the specified command.";
    }
    fputs($stdout, "$put\n");
    fclose($stdout);

    if ($error === null) {
        exit(0);
    }
    exit(1);
}

/**
 * Return help string for specified command
 *
 * @param string $command Command to return help for
 *
 * @return void
 */
function cmdHelp($command)
{
    global $progname, $all_commands, $config;
    if ($command == "options") {
        return
        "Options:\n".
        "     -v         increase verbosity level (default 1)\n".
        "     -q         be quiet, decrease verbosity level\n".
        "     -c file    find user configuration in `file'\n".
        "     -C file    find system configuration in `file'\n".
        "     -d foo=bar set user config variable `foo' to `bar'\n".
        "     -D foo=bar set system config variable `foo' to `bar'\n".
        "     -G         start in graphical (Gtk) mode\n".
        "     -s         store user configuration\n".
        "     -S         store system configuration\n".
        "     -u foo     unset `foo' in the user configuration\n".
        "     -h, -?     display help/usage (this message)\n".
        "     -V         version information\n";
    } elseif ($command == "shortcuts") {
        $sc = PEAR_Command::getShortcuts();
        $ret = "Shortcuts:\n";
        foreach ($sc as $s => $c) {
            $ret .= sprintf("     %-8s %s\n", $s, $c);
        }
        return $ret;

    } elseif ($command == "version") {
        return "PEAR Version: ".$GLOBALS['pear_package_version'].
               "\nPHP Version: ".phpversion().
               "\nZend Engine Version: ".zend_version().
               "\nRunning on: ".php_uname();

    } elseif ($help = PEAR_Command::getHelp($command)) {
        if (is_string($help)) {
            return "$progname $command [options] $help\n";
        }

        if ($help[1] === null) {
            return "$progname $command $help[0]";
        }

        return "$progname $command [options] $help[0]\n$help[1]";
    }

    return "Command '$command' is not valid, try '$progname help'";
}

// }}}

/**
 * error_handler
 *
 * @param mixed $errno  Error number
 * @param mixed $errmsg Message
 * @param mixed $file   Filename
 * @param mixed $line   Line number
 *
 * @access public
 * @return boolean
 */
function error_handler($errno, $errmsg, $file, $line)
{
    if ((!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) && ($errno & E_STRICT)) {
        return; // E_STRICT
    }
    if ($errno & E_DEPRECATED) {
        return; // E_DEPRECATED
    }
    if (!(error_reporting() & $errno) &&
        isset($GLOBALS['config']) &&
        $GLOBALS['config']->get('verbose') < 4
    ) {
        return false; // @silenced error, show all if debug is high enough
    }
    $errortype = array (
        E_DEPRECATED  => 'Deprecated Warning',
        E_ERROR   =>  "Error",
        E_WARNING   =>  "Warning",
        E_PARSE   =>  "Parsing Error",
        E_NOTICE   =>  "Notice",
        E_CORE_ERROR  =>  "Core Error",
        E_CORE_WARNING  =>  "Core Warning",
        E_COMPILE_ERROR  =>  "Compile Error",
        E_COMPILE_WARNING =>  "Compile Warning",
        E_USER_ERROR =>  "User Error",
        E_USER_WARNING =>  "User Warning",
        E_USER_NOTICE =>  "User Notice"
    );
    if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) {
        $errortype[E_STRICT] = 'Strict Warning';
    }
    $prefix = $errortype[$errno];
    global $_PEAR_PHPDIR;
    if (stristr($file, $_PEAR_PHPDIR)) {
        $file = substr($file, strlen($_PEAR_PHPDIR) + 1);
    } else {
        $file = basename($file);
    }
    print "\n$prefix: $errmsg in $file on line $line\n";
    return false;
}


/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * indent-tabs-mode: nil
 * mode: php
 * End:
 */
// vim600:syn=php
PK��Z�0$�-- .pkgxml/Pear_File_MARC-1.4.1.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.10.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
 <name>File_MARC</name>
 <channel>pear.php.net</channel>
 <summary>Parse, modify, and create MARC records</summary>
 <description>The standard for machine-readable cataloging (MARC) records is documented at http://loc.gov/marc/. This package enables you to read existing MARC records from a file, string, or (using the YAZ extension), from a Z39.50 source. You can also use this package to create new MARC records.

This package is based on the PHP MARC package, originally called &quot;php-marc&quot;, that is part of the Emilda Project (http://www.emilda.org).  Christoffer Landtman generously agreed to make the &quot;php-marc&quot; code available under the GNU LGPL so it could be used as the basis of this PEAR package.</description>
 <lead>
  <name>Dan Scott</name>
  <user>dbs</user>
  <email>dbs@php.net</email>
  <active>yes</active>
 </lead>
 <date>2019-11-13</date>
 <time>17:33:33</time>
 <version>
  <release>1.4.1</release>
  <api>1.4.0</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license uri="http://www.gnu.org/copyleft/lesser.html">GNU Lesser General Public License</license>
 <notes>
1.4.1
  * Reintroduce include_path to composer.json
 </notes>
 <contents>
  <dir baseinstalldir="File" name="/">
   <file baseinstalldir="/" md5sum="ffe2590635f404af055fe731da105939" name="File/MARC/Lint/CodeData.php" role="php" />
   <file baseinstalldir="/" md5sum="a3b9e1c817e67f59add05593500d463e" name="File/MARC/Control_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="acba4463f8e40d6ee4e7ba1f2dc53123" name="File/MARC/Data_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="378f483ec1fd161cd9dfb9b05db58d66" name="File/MARC/Exception.php" role="php" />
   <file baseinstalldir="/" md5sum="a9ba69030cbf4847292b9975e9d922c6" name="File/MARC/Field.php" role="php" />
   <file baseinstalldir="/" md5sum="c37351c7c80927ce6bb1e662510f9183" name="File/MARC/Lint.php" role="php" />
   <file baseinstalldir="/" md5sum="c5ac39e3d25eb0108b9dd5ad8466c821" name="File/MARC/List.php" role="php" />
   <file baseinstalldir="/" md5sum="7af6ce78cde4bb246e4e96709e90d2c0" name="File/MARC/Record.php" role="php" />
   <file baseinstalldir="/" md5sum="df5f97139685f0ad04e47fdbb67e3968" name="File/MARC/Subfield.php" role="php" />
   <file baseinstalldir="/" md5sum="6e102262dfd5d65d8d5a6221dfc74edd" name="File/MARC.php" role="php" />
   <file baseinstalldir="/" md5sum="8b64040d2d18ac4b994595a148266a66" name="File/MARCBASE.php" role="php" />
   <file baseinstalldir="/" md5sum="f5a17a60d34e84e2ee7ca1e5c5c6c620" name="File/MARCXML.php" role="php" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="examples/example.mrc" role="doc" />
   <file baseinstalldir="File" md5sum="1aea40df9f1c2e32f8e065fe8da0a3b5" name="examples/marc_yaz.php" role="doc" />
   <file baseinstalldir="File" md5sum="70ae317e0890d5896e3ffccdd293369a" name="examples/read.php" role="doc" />
   <file baseinstalldir="File" md5sum="54efb9d920ac775bfc847a83a2dec73a" name="examples/subfields.php" role="doc" />
   <file baseinstalldir="File" md5sum="14297da35b510c496cd1f328cf3bb301" name="tests/bad_example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="0dd4c6dbad6e8608d0ebf9d24425955d" name="tests/bad_example.xml" role="test" />
   <file baseinstalldir="File" md5sum="216a6f9d53f6d3d8e22d81fdc10f4bc1" name="tests/camel.mrc" role="test" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="tests/example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="9455aec3371f79cf7d31281fd03f5171" name="tests/marc_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="577e2f5f89fd48cf1a3576a29d2958f8" name="tests/marc_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a6a586354b9a06c880c2a7470dd828d7" name="tests/marc_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1c7e2fc5572a0f9362a771c260a1fe3" name="tests/marc_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="84f85ac7f8a2532e4e90ccde7764556a" name="tests/marc_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="889e5e906a97de7a0e94b0c5f30e70e7" name="tests/marc_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="be823dc8a8efb408de06371ab802efcc" name="tests/marc_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="af44490aafea44e5120f881cb81cdad9" name="tests/marc_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ac9f2a7aeb24900a11f5102744179ae3" name="tests/marc_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5e43eb5cddbb4f2bd0d6405cd95b80aa" name="tests/marc_010.phpt" role="test" />
   <file baseinstalldir="File" md5sum="2e1cd8509c0bf04ec77fc0f51375f611" name="tests/marc_011.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bc49ca48623102c8ac07679fa77a3dd9" name="tests/marc_012.phpt" role="test" />
   <file baseinstalldir="File" md5sum="245a3b20e0da1973535503e28efd1d3a" name="tests/marc_013.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ce69aa734856dd40d60d30c77bdef53a" name="tests/marc_014.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7b61cdd31035e60682fa92c5d519d997" name="tests/marc_015.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7f4f597fe1adaa3507eb87fc4875dbd2" name="tests/marc_016.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4262efd5fcacbd7503323681f4552430" name="tests/marc_017.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ee1623d7bda54ba4f741b2319b158f82" name="tests/marc_018.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8006c03fbab0f04377342086fafd3982" name="tests/marc_019.phpt" role="test" />
   <file baseinstalldir="File" md5sum="f5ae5b25e0ac1104314433d9e5b1f7fe" name="tests/marc_020.phpt" role="test" />
   <file baseinstalldir="File" md5sum="94d8f99e86585671a1b2d3043aeb6360" name="tests/marc_021.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bb891a890effe0e77e1759043f4846d8" name="tests/marc_022.phpt" role="test" />
   <file baseinstalldir="File" md5sum="faf77dcb5cdd002c09169a14bfded65e" name="tests/marc_023.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0e6c4a23f5da7df64fdd4b3b1149bbee" name="tests/marc_16783.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4ea8b3520beda378db15960f1c50493a" name="tests/marc_field_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="743850ef61df69c4340be44a03bccb5a" name="tests/marc_field_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8c765f1398b49df257d86d22ac6e4f8d" name="tests/marc_field_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d4216cf930a308e0d02553bd3914f294" name="tests/marc_field_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dd59514b474b78371ad522a3e13b76b7" name="tests/marc_field_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5295bfd02a8424acac1c91de26b552c7" name="tests/marc_field_21246.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6f95f09442ccf6b93df92986f58b270d" name="tests/marc_lint_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="18d721f8871edd925624ccbdd15444fb" name="tests/marc_lint_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4eb86a2f4e0a74dedcb0bf2511da6ca1" name="tests/marc_lint_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="10430fee0a1352d0528f1507b34c57e1" name="tests/marc_lint_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0dcd07a18577d7b22392a2214cd6436c" name="tests/marc_lint_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fd17798fc535562e5e64461f449516b2" name="tests/marc_record_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="141b455ccf67a60c4eac44c77960f2e2" name="tests/marc_subfield_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1e23464ee0eec47ddca2af9a9922926" name="tests/marc_subfield_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="1d7903e8c244d647220b318b4bc758d1" name="tests/marc_xml_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="22cae3c752d843b78f583dcd92801534" name="tests/marc_xml_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="c0716d23e0f960abf8d53ad6014a413a" name="tests/marc_xml_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7645fa19e28aca041a124fc5e2c12bd3" name="tests/marc_xml_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b08b28c3251625b8b6e4d7ab376b0185" name="tests/marc_xml_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6cd0934ddbf65d2d7e9ea5d108977ff7" name="tests/marc_xml_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ffdce4aa190268fa7cbbf3bb45383abf" name="tests/marc_xml_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="998a4c1ce00ff100f39ffa9fc49a212f" name="tests/marc_xml_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a38a67c590869f2b0a4859a910fd9e89" name="tests/marc_xml_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="db39c5055a570fcda12bb7c5fa1e3b4d" name="tests/marc_xml_16642.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dc075f4a271bd7182378a3874bd5b39e" name="tests/marc_xml_namespace.phpt" role="test" />
   <file baseinstalldir="File" md5sum="208200d9a979ac360c4d326e9789b6b7" name="tests/marc_xml_namespace_prefix.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d87774ede82222cfc12b2c2a06f57a3a" name="tests/marc_xml_rsinger.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fb44e3eb69f1a37115235fc829c39542" name="tests/namespace.xml" role="test" />
   <file baseinstalldir="File" md5sum="e6de4d809b0af5dd99fd352eb60616a1" name="tests/skipif.inc" role="test" />
   <file baseinstalldir="File" md5sum="a0166a4ff0bc0bb283e854f11beaa793" name="tests/music.mrc" role="test" />
   <file baseinstalldir="File" md5sum="993ce494befbc25dc1326527b30b4782" name="tests/music.xml" role="test" />
   <file baseinstalldir="File" md5sum="6b0c87f0cd459ed7322c25d403b164cc" name="tests/bigarchive.xml" role="test" />
   <file baseinstalldir="File" md5sum="be850aa6ab4ac52b8c6c214c30b574af" name="tests/onerecord.xml" role="test" />
   <file baseinstalldir="File" md5sum="4f43fec7b276267eec5258044853ccc8" name="tests/sandburg.mrc" role="test" />
   <file baseinstalldir="File" md5sum="e216b95f905dd240c9bde372950e4073" name="tests/sandburg.xml" role="test" />
   <file baseinstalldir="File" md5sum="e81a92188ea0dcd9c108a63fb32b3f4f" name="tests/xmlescape.mrc" role="test" />
   <file baseinstalldir="File" md5sum="8f9f63ed6a80191d89a2296fa4c1a30b" name="CHANGELOG" role="doc" />
   <file baseinstalldir="File" md5sum="fbc093901857fcd118f065f900982c24" name="LICENSE" role="doc" />
  </dir>
 </contents>
 <dependencies>
  <required>
   <php>
    <min>5.6</min>
   </php>
   <pearinstaller>
    <min>1.4.0</min>
   </pearinstaller>
  </required>
  <optional>
   <package>
    <name>Validate_ISPN</name>
    <channel>pear.php.net</channel>
   </package>
  </optional>
 </dependencies>
 <phprelease />
</package>
PKm�ZPi��.depdbnu�[���PKm�Z�{��
�Mail/null.phpnu�[���PKm�ZE@�%>>
Mail/sendmail.phpnu�[���PKm�Z��A~�{�{�;Mail/RFC822.phpnu�[���PKn�Z�+V����
[�Mail/mime.phpnu�[���PKn�Zx�ع���D�Mail/mimeDecode.phpnu�[���PKn�ZB�_Ǭ=�=
@(Mail/smtp.phpnu�[���PKn�ZwԐE;E;)fMail/smtpmx.phpnu�[���PKn�Z�؛�J�J���Mail/mimePart.phpnu�[���PKn�ZB��shh
8YMail/mock.phpnu�[���PKn�Z@iE�\\
�lMail/mail.phpnu�[���PKn�Zv�.locknu�[���PKn�Z�*�z%-%- ��Structures/LinkedList/Double.phpnu�[���PKn�Z����p:p:  �Structures/LinkedList/Single.phpnu�[���PKn�ZUyv���Structures/Graph.phpnu�[���PKn�Z�C� + +CStructures/Graph/Node.phpnu�[���PKn�Z9����,�1Structures/Graph/Manipulator/AcyclicTest.phpnu�[���PKn�Z~(�htt2�HStructures/Graph/Manipulator/TopologicalSorter.phpnu�[���PKn�Z�J�}
}
_dAuth/SASL/Anonymous.phpnu�[���PKn�ZP(~�T
T
#rAuth/SASL/CramMD5.phpnu�[���PKn�Z����==�Auth/SASL/Plain.phpnu�[���PKn�Z�<� OO<�Auth/SASL/Login.phpnu�[���PKn�Z%ׅtg!g!ΘAuth/SASL/DigestMD5.phpnu�[���PKn�Z�T�|�Auth/SASL/Common.phpnu�[���PKn�ZvR�r,,��Auth/SASL/External.phpnu�[���PKn�Zќ��0�0H�Auth/SASL/SCRAM.phpnu�[���PKn�Z2r����
�	Auth/SASL.phpnu�[���PKn�Z�T�,�,�OS/Guess.phpnu�[���PKn�Z�����KPEAR/Config.phpnu�[���PKn�Z�`�eEAEA
.ZPEAR/REST.phpnu�[���PKn�Z��ym6m6��PEAR/Exception.phpnu�[���PKn�Zr"����_�PEAR/ChannelFile.phpnu�[���PKn�Z��gk�U�U?�PEAR/Validate.phpnu�[���PKn�Zd֣S��u�PEAR/Command/Pickle.xmlnu�[���PKn�Z�z��k<k<W�PEAR/Command/Config.phpnu�[���PKn�Z݄<ii	1PEAR/Command/Mirror.xmlnu�[���PKn�Z,��t"u"u�3PEAR/Command/Remote.phpnu�[���PKn�Z
�\���"�PEAR/Command/Remote.xmlnu�[���PKn�Zj���!�!X�PEAR/Command/Install.xmlnu�[���PKo�Z�%q������PEAR/Command/Channels.phpnu�[���PKo�Znmi?;�;��[	PEAR/Command/Install.phpnu�[���PKo�Z�X�

#
PEAR/Command/Auth.phpnu�[���PKo�Z���s6
6
T-
PEAR/Command/Config.xmlnu�[���PKo�Z�%Fii�:
PEAR/Command/Test.xmlnu�[���PKo�ZZ h66A
PEAR/Command/Package.xmlnu�[���PKo�Z�w��zz�]
PEAR/Command/Channels.xmlnu�[���PKo�Z+9ҜҜ�n
PEAR/Command/Package.phpnu�[���PKo�Z
u����PEAR/Command/Build.xmlnu�[���PKo�Z������
PEAR/Command/Mirror.phpnu�[���PKp�Z,_�h/h/�PEAR/Command/Test.phpnu�[���PKp�Z�%sp  6OPEAR/Command/Common.phpnu�[���PKp�Z0(;rʹʹ�oPEAR/Command/Registry.phpnu�[���PKp�Z�4�{���$PEAR/Command/Auth.xmlnu�[���PKp�Z��#S
S
�)PEAR/Command/Build.phpnu�[���PKp�Z���u��S4PEAR/Command/Registry.xmlnu�[���PKp�Z�P>>�;PEAR/Command/Pickle.phpnu�[���PKp�Z��T�I�I�yPEAR/Builder.phpnu�[���PKp�Z[
�W��3�PEAR/XMLParser.phpnu�[���PKp�Zl(e���t�PEAR/Downloader.phpnu�[���PKp�Z�b������
PEAR/ErrorStack.phpnu�[���PKp�Z(Pz����ePEAR/Proxy.phpnu�[���PKp�Z��'����|PEAR/RunTest.phpnu�[���PKq�Zj�y99�	PEAR/Validator/PECL.phpnu�[���PKq�Zp�����aPEAR/Dependency2.phpnu�[���PKq�Z��wv@@��PEAR/PackageFile/v2.phpnu�[���PKq�ZC�8�L�L!:�PEAR/PackageFile/v2/Validator.phpnu�[���PKq�Z���=_�_�6PEAR/PackageFile/v2/rw.phpnu�[���PKq�Z�5�������,PEAR/PackageFile/v1.phpnu�[���PKq�Z�ɁɁ!��PEAR/PackageFile/Generator/v2.phpnu�[���PKq�Z`�=����!�tPEAR/PackageFile/Generator/v1.phpnu�[���PKr�Z��OWHH�9PEAR/PackageFile/Parser/v2.phpnu�[���PKr�Z�_=�@�@`FPEAR/PackageFile/Parser/v1.phpnu�[���PKr�Zc��__5�PEAR/DependencyDB.phpnu�[���PKr�Z�@P��{�PEAR/ChannelFile/Parser.phpnu�[���PKr�Z��_�0�0r�PEAR/Command.phpnu�[���PKr�Z�ٲ�=�==PEAR/PackageFile.phpnu�[���PKr�Z�JD��g\PEAR/Task/Replace.phpnu�[���PKr�Z&%75))�wPEAR/Task/Windowseol/rw.phpnu�[���PKr�Z�3}}PEAR/Task/Replace/rw.phpnu�[���PKr�Z&
i."x�PEAR/Task/Postinstallscript/rw.phpnu�[���PKr�Z�-!�PEAR/Task/Common.phpnu�[���PKr�ZD$���I�PEAR/Task/Windowseol.phpnu�[���PKr�ZZ�E�x9x9��PEAR/Task/Postinstallscript.phpnu�[���PKr�Z\k��K�PEAR/Task/Unixeol/rw.phpnu�[���PKr�Z�������PEAR/Task/Unixeol.phpnu�[���PKr�Z�W�f���PEAR/REST/10.phpnu�[���PKr�Z��Y�;;ąPEAR/REST/13.phpnu�[���PKr�Z,#y��+�+�PEAR/REST/11.phpnu�[���PKr�Z��U  D�PEAR/Packager.phpnu�[���PKr�ZZ�bgbg�PEAR/Common.phpnu�[���PKr�Z$���(�(FsPEAR/Registry.phpnu�[���PKr�Z��	MdMd?�PEAR/Frontend/CLI.phpnu�[���PKr�Z��

�PEAR/Installer/Role/Doc.phpnu�[���PKr�Z��/��)PEAR/Installer/Role/Cfg.xmlnu�[���PKr�Z>1H���PEAR/Installer/Role/Www.xmlnu�[���PKr�Z�?m

PEAR/Installer/Role/Php.phpnu�[���PKr�Z*Y|	%%`PEAR/Installer/Role/Man.phpnu�[���PKr�Z���BB�PEAR/Installer/Role/Ext.xmlnu�[���PKr�Zp��""]PEAR/Installer/Role/Src.xmlnu�[���PKr�Zh&P*���PEAR/Installer/Role/Doc.xmlnu�[���PKr�ZB] ���PEAR/Installer/Role/Test.xmlnu�[���PKr�Zz�q����PEAR/Installer/Role/Php.xmlnu�[���PKr�Z	��
|PEAR/Installer/Role/Data.phpnu�[���PKs�Z�0�c���PEAR/Installer/Role/Man.xmlnu�[���PKs�Z��K

�PEAR/Installer/Role/Ext.phpnu�[���PKs�ZY��� PEAR/Installer/Role/Test.phpnu�[���PKs�Z@v�а�z#PEAR/Installer/Role/Script.xmlnu�[���PKs�Zf�sz��x%PEAR/Installer/Role/Data.xmlnu�[���PKs�Z?���GGV'PEAR/Installer/Role/Common.phpnu�[���PKs�Z�^D{		�?PEAR/Installer/Role/Www.phpnu�[���PKs�Z�Ƥ?CPEAR/Installer/Role/Cfg.phpnu�[���PKs�Z��[�	SPEAR/Installer/Role/Script.phpnu�[���PKs�Z��srrjVPEAR/Installer/Role/Src.phpnu�[���PKs�ZV�Z���'ZPEAR/Installer/Role.phpnu�[���PKs�Z�{�	�)�)*yPEAR/Downloader/Package.phpnu�[���PKs�Z.�4���$�PEAR/Frontend.phpnu�[���PKs�Z،�w��_�PEAR/Installer.phpnu�[���PKs�ZXxo��-j�Symfony/Bridge/Doctrine/Logger/DbalLogger.phpnu�[���PKs�Ze�OO&b�Symfony/Bridge/Doctrine/autoloader.phpnu�[���PKs�Z��X+��8�Symfony/Bridge/Doctrine/CacheWarmer/ProxyCacheWarmer.phpnu�[���PKs�Z	�9,��5i�Symfony/Bridge/Doctrine/Form/DoctrineOrmExtension.phpnu�[���PKs�Z�0���NX�Symfony/Bridge/Doctrine/Form/EventListener/MergeDoctrineCollectionListener.phpnu�[���PKs�Z!%d==A��Symfony/Bridge/Doctrine/Form/ChoiceList/EntityLoaderInterface.phpnu�[���PKs�Z�	?x�7�7<4�Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.phpnu�[���PKs�ZGC�t��A<-Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.phpnu�[���PKs�Z`.
qpp7�9Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.phpnu�[���PKs�ZCi�PPMZQSymfony/Bridge/Doctrine/Form/DataTransformer/CollectionToArrayTransformer.phpnu�[���PKs�Z憝��0'YSymfony/Bridge/Doctrine/Form/Type/EntityType.phpnu�[���PKs�ZS;,:��2-]Symfony/Bridge/Doctrine/Form/Type/DoctrineType.phpnu�[���PKs�ZW&v��<�wSymfony/Bridge/Doctrine/Security/User/EntityUserProvider.phpnu�[���PKs�Z�����Et�Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.phpnu�[���PKs�Z(��y��9�Symfony/Bridge/Doctrine/Validator/DoctrineInitializer.phpnu�[���PKs�ZQГ��>�Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.phpnu�[���PKs�Z:�d�G5�Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.phpnu�[���PKs�Z�Ta�==B��Symfony/Bridge/Doctrine/ExpressionLanguage/DoctrineParserCache.phpnu�[���PKs�Z��qm
m
-m�Symfony/Bridge/Doctrine/RegistryInterface.phpnu�[���PKs�Zlf/�qq=7�Symfony/Bridge/Doctrine/DataFixtures/ContainerAwareLoader.phpnu�[���PKs�Z����=�Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.phpnu�[���PKs�Z�����C��Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerSchema.phpnu�[���PKs�ZOlQ�996��Symfony/Bridge/Doctrine/ContainerAwareEventManager.phpnu�[���PKs�Z؈����3D�Symfony/Bridge/Doctrine/Test/DoctrineTestHelper.phpnu�[���PKs�Z̳֨�+��Symfony/Bridge/Doctrine/ManagerRegistry.phpnu�[���PKs�Z+çxAA?�Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.phpnu�[���PKs�Z*�+��J�JIBSymfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.phpnu�[���PKs�Z���*��SVaSymfony/Bridge/Doctrine/DependencyInjection/Security/UserProvider/EntityFactory.phpnu�[���PKs�Z��㛕�Q�hSymfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterMappingsPass.phpnu�[���PKs�Z~�YAAeԀSymfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.phpnu�[���PKs�Z��,���S��Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/DoctrineValidationPass.phpnu�[���PKs�Z��4NN%,�Symfony/Bridge/Monolog/autoloader.phpnu�[���PKs�Z��մ��1ϡSymfony/Bridge/Monolog/Handler/FirePHPHandler.phpnu�[���PKs�Z��Zv��/©Symfony/Bridge/Monolog/Handler/DebugHandler.phpnu�[���PKs�Z�y���1دSymfony/Bridge/Monolog/Handler/ConsoleHandler.phpnu�[���PKs�Z��*vv5�Symfony/Bridge/Monolog/Handler/SwiftMailerHandler.phpnu�[���PKs�Z���"II3��Symfony/Bridge/Monolog/Handler/ChromePhpHandler.phpnu�[���PKs�Z��;��	�	!��Symfony/Bridge/Monolog/Logger.phpnu�[���PKs�Z��b115��Symfony/Bridge/Monolog/Formatter/ConsoleFormatter.phpnu�[���PKt�Z�,��1l�Symfony/Bridge/Monolog/Processor/WebProcessor.phpnu�[���PKt�Z�$�KK"l�Symfony/Bridge/Twig/autoloader.phpnu�[���PKt�Z�)�UU1	�Symfony/Bridge/Twig/Translation/TwigExtractor.phpnu�[���PKt�Z6DZ77*��Symfony/Bridge/Twig/Node/StopwatchNode.phpnu�[���PKt�Z,
�@��5P�Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.phpnu�[���PKt�Z�
�s>>*ESymfony/Bridge/Twig/Node/FormThemeNode.phpnu�[���PKt�ZP�IAA3�Symfony/Bridge/Twig/Node/TransDefaultDomainNode.phpnu�[���PKt�Z�U,tt,�Symfony/Bridge/Twig/Node/FormEnctypeNode.phpnu�[���PKt�Zʦ\�G
G
&QSymfony/Bridge/Twig/Node/TransNode.phpnu�[���PKt�Z���^��,�%Symfony/Bridge/Twig/Node/RenderBlockNode.phpnu�[���PKt�Z�vq�)+Symfony/Bridge/Twig/Form/TwigRenderer.phpnu�[���PKt�Zb�3�}}8q1Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.phpnu�[���PKt�Z��Qkk2V4Symfony/Bridge/Twig/Form/TwigRendererInterface.phpnu�[���PKt�Z��<��/#7Symfony/Bridge/Twig/Form/TwigRendererEngine.phpnu�[���PKt�Z�GTSymfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.phpnu�[���PKt�Z�)�[n	n	)�`Symfony/Bridge/Twig/NodeVisitor/Scope.phpnu�[���PKt�Z�tA�:`jSymfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.phpnu�[���PKt�Z��9292B�xSymfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twignu�[���PKt�Z��[[Dy�Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twignu�[���PKt�Z.��8H�Symfony/Bridge/Twig/TokenParser/StopwatchTokenParser.phpnu�[���PKt�Z�%]�
�
4��Symfony/Bridge/Twig/TokenParser/TransTokenParser.phpnu�[���PKt�Z�/�	�	:��Symfony/Bridge/Twig/TokenParser/TransChoiceTokenParser.phpnu�[���PKt�Z>����8>�Symfony/Bridge/Twig/TokenParser/FormThemeTokenParser.phpnu�[���PKt�Zʶ�̭�Ao�Symfony/Bridge/Twig/TokenParser/TransDefaultDomainTokenParser.phpnu�[���PKt�Z�9�=KK/��Symfony/Bridge/Twig/Extension/FormExtension.phpnu�[���PKt�Z��|/7�Symfony/Bridge/Twig/Extension/YamlExtension.phpnu�[���PKt�Z��&�a
a
5��Symfony/Bridge/Twig/Extension/HttpKernelExtension.phpnu�[���PKt�ZKΙ���5v�Symfony/Bridge/Twig/Extension/ExpressionExtension.phpnu�[���PKt�Z`�fS..2� Symfony/Bridge/Twig/Extension/RoutingExtension.phpnu�[���PKt�Z�5��mm4] Symfony/Bridge/Twig/Extension/StopwatchExtension.phpnu�[���PKt�Z�?���6. Symfony/Bridge/Twig/Extension/TranslationExtension.phpnu�[���PKt�Zd���oo3�! Symfony/Bridge/Twig/Extension/SecurityExtension.phpnu�[���PKt�Z�����/a' Symfony/Bridge/Twig/Extension/CodeExtension.phpnu�[���PKu�Z^D��dd"sG Symfony/Bridge/Twig/TwigEngine.phpnu�[���PKu�Z�4˵��()V Symfony/Component/Finder/Shell/Shell.phpnu�[���PKu�Z5��K��*^ Symfony/Component/Finder/Shell/Command.phpnu�[���PKu�Z�5�9(�v Symfony/Component/Finder/SplFileInfo.phpnu�[���PKu�Z%uM�PP'X~ Symfony/Component/Finder/autoloader.phpnu�[���PKu�Z��99C� Symfony/Component/Finder/Exception/ShellCommandFailureException.phpnu�[���PKu�Z�7��9�� Symfony/Component/Finder/Exception/ExceptionInterface.phpnu�[���PKu�Z�cWޫ�<� Symfony/Component/Finder/Exception/AccessDeniedException.phpnu�[���PKu�Z>�@��>� Symfony/Component/Finder/Exception/AdapterFailureException.phpnu�[���PKu�ZP�����D	� Symfony/Component/Finder/Exception/OperationNotPermitedException.phpnu�[���PKu�Z��� ��6� Symfony/Component/Finder/Comparator/DateComparator.phpnu�[���PKu�Z|F�z

2?� Symfony/Component/Finder/Comparator/Comparator.phpnu�[���PKu�Z�P�

8�� Symfony/Component/Finder/Comparator/NumberComparator.phpnu�[���PKu�Z�g@Mbb!2� Symfony/Component/Finder/Glob.phpnu�[���PKu�Z�d�V�V#� Symfony/Component/Finder/Finder.phpnu�[���PKu�Zils_��>
!Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.phpnu�[���PKu�Z��ɔ�
�
7u!Symfony/Component/Finder/Iterator/FilePathsIterator.phpnu�[���PKu�Z�,G��4n!Symfony/Component/Finder/Iterator/FilterIterator.phpnu�[���PKu�Z�ʽ���?q#!Symfony/Component/Finder/Iterator/FilecontentFilterIterator.phpnu�[���PKu�Z�

���@~+!Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.phpnu�[���PKu�Z��z":�2!Symfony/Component/Finder/Iterator/CustomFilterIterator.phpnu�[���PKu�Z{�^ǽ�<N9!Symfony/Component/Finder/Iterator/FilenameFilterIterator.phpnu�[���PKu�Z�d����Dw@!Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.phpnu�[���PKu�Zx�P���=�F!Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.phpnu�[���PKu�Z ��U��=�L!Symfony/Component/Finder/Iterator/DateRangeFilterIterator.phpnu�[���PKu�Z�n bb<�R!Symfony/Component/Finder/Iterator/FileTypeFilterIterator.phpnu�[���PKu�Z��j��	�	6�X!Symfony/Component/Finder/Iterator/SortableIterator.phpnu�[���PKu�Z���)��8�b!Symfony/Component/Finder/Iterator/PathFilterIterator.phpnu�[���PKu�Z�6s��@�j!Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.phpnu�[���PKu�Z��&
&
2Gw!Symfony/Component/Finder/Expression/Expression.phpnu�[���PKu�Z�"HH6ρ!Symfony/Component/Finder/Expression/ValueInterface.phpnu�[���PKu�Z�E�,}�!Symfony/Component/Finder/Expression/Glob.phpnu�[���PKu�Z��(�-�!Symfony/Component/Finder/Expression/Regex.phpnu�[���PKu�Z9!�2{
{
/D�!Symfony/Component/Finder/Adapter/PhpAdapter.phpnu�[���PKu�Z����5�!Symfony/Component/Finder/Adapter/AdapterInterface.phpnu�[���PKu�Z��kA�
�
34�!Symfony/Component/Finder/Adapter/BsdFindAdapter.phpnu�[���PKu�Z�}]�
�
3��!Symfony/Component/Finder/Adapter/GnuFindAdapter.phpnu�[���PKu�ZQJ)�)8��!Symfony/Component/Finder/Adapter/AbstractFindAdapter.phpnu�[���PKu�Z�	4�"Symfony/Component/Finder/Adapter/AbstractAdapter.phpnu�[���PKu�Z����:;"Symfony/Component/Translation/Extractor/ChainExtractor.phpnu�[���PKu�ZArP�>%"Symfony/Component/Translation/Extractor/ExtractorInterface.phpnu�[���PKu�Zb*0�oo4�#"Symfony/Component/Translation/PluralizationRules.phpnu�[���PKu�Z�q��UU,<"Symfony/Component/Translation/autoloader.phpnu�[���PKu�Z�<qNN10>"Symfony/Component/Translation/MessageSelector.phpnu�[���PKu�Z�س��:�J"Symfony/Component/Translation/Catalogue/MergeOperation.phpnu�[���PKu�ZY[�>*P"Symfony/Component/Translation/Catalogue/OperationInterface.phpnu�[���PKu�Z��fb�
�
=�U"Symfony/Component/Translation/Catalogue/AbstractOperation.phpnu�[���PKu�Z��ӄ�9�c"Symfony/Component/Translation/Catalogue/DiffOperation.phpnu�[���PKu�Z�6�"��>�i"Symfony/Component/Translation/Exception/ExceptionInterface.phpnu�[���PKu�ZDŽ���D�k"Symfony/Component/Translation/Exception/InvalidResourceException.phpnu�[���PKv�Z�2B��E2n"Symfony/Component/Translation/Exception/NotFoundResourceException.phpnu�[���PKv�Z�y4��2�p"Symfony/Component/Translation/MessageCatalogue.phpnu�[���PKv�Z%�Mt8��"Symfony/Component/Translation/MetadataAwareInterface.phpnu�[���PKv�Z�d�<<4��"Symfony/Component/Translation/IdentityTranslator.phpnu�[���PKv�Z�e�G��,��"Symfony/Component/Translation/Translator.phpnu�[���PKv�Z��֛�;u�"Symfony/Component/Translation/MessageCatalogueInterface.phpnu�[���PKv�ZM�
���9{�"Symfony/Component/Translation/Dumper/IcuResFileDumper.phpnu�[���PKv�Zਪ(5u�"Symfony/Component/Translation/Dumper/PoFileDumper.phpnu�[���PKv�Z���%LL6��"Symfony/Component/Translation/Dumper/PhpFileDumper.phpnu�[���PKv�Z�<̧��8��"Symfony/Component/Translation/Dumper/XliffFileDumper.phpnu�[���PKv�Z>{GG5��"Symfony/Component/Translation/Dumper/QtFileDumper.phpnu�[���PKv�Z���667Z�"Symfony/Component/Translation/Dumper/YamlFileDumper.phpnu�[���PKv�ZoB���6��"Symfony/Component/Translation/Dumper/CsvFileDumper.phpnu�[���PKv�ZB^�[[3*�"Symfony/Component/Translation/Dumper/FileDumper.phpnu�[���PKv�Z�:$}}7�"Symfony/Component/Translation/Dumper/JsonFileDumper.phpnu�[���PKv�Z&X����6�#Symfony/Component/Translation/Dumper/IniFileDumper.phpnu�[���PKv�Z��<**8
#Symfony/Component/Translation/Dumper/DumperInterface.phpnu�[���PKv�Z����A	A	5�#Symfony/Component/Translation/Dumper/MoFileDumper.phpnu�[���PKv�Zg�?Z�
�
*B#Symfony/Component/Translation/Interval.phpnu�[���PKv�Z�3����5�#Symfony/Component/Translation/TranslatorInterface.phpnu�[���PKv�ZP�?�}}:�%#Symfony/Component/Translation/Writer/TranslationWriter.phpnu�[���PKv�ZN@���6�-#Symfony/Component/Translation/Loader/IniFileLoader.phpnu�[���PKv�Z�T�93#Symfony/Component/Translation/Loader/IcuDatFileLoader.phpnu�[���PKv�ZCS�z
z
9�9#Symfony/Component/Translation/Loader/IcuResFileLoader.phpnu�[���PKv�Z��v���5�D#Symfony/Component/Translation/Loader/MoFileLoader.phpnu�[���PKv�ZR����4&\#Symfony/Component/Translation/Loader/ArrayLoader.phpnu�[���PKv�Z�'s�u	u	7&d#Symfony/Component/Translation/Loader/JsonFileLoader.phpnu�[���PKv�Z�i�3"
"
6n#Symfony/Component/Translation/Loader/CsvFileLoader.phpnu�[���PKv�Z_��BB8�x#Symfony/Component/Translation/Loader/XliffFileLoader.phpnu�[���PKv�Zl#�tt84�#Symfony/Component/Translation/Loader/LoaderInterface.phpnu�[���PKv�Z�*���5�#Symfony/Component/Translation/Loader/PoFileLoader.phpnu�[���PKv�Z�r��;;6o�#Symfony/Component/Translation/Loader/PhpFileLoader.phpnu�[���PKv�Z:�	Z�"�"B�#Symfony/Component/Translation/Loader/schema/dic/xliff-core/xml.xsdnu�[���PKv�Z�xO��T�#Symfony/Component/Translation/Loader/schema/dic/xliff-core/xliff-core-1.2-strict.xsdnu�[���PKv�Z)-d+�	�	5�g%Symfony/Component/Translation/Loader/QtFileLoader.phpnu�[���PKv�Z:����7�q%Symfony/Component/Translation/Loader/YamlFileLoader.phpnu�[���PKw�Z�V�˽�.-z%Symfony/Component/Routing/Annotation/Route.phpnu�[���PKw�Z�<ѹ�+H�%Symfony/Component/Routing/CompiledRoute.phpnu�[���PKw�ZU8���-\�%Symfony/Component/Routing/RouterInterface.phpnu�[���PKw�ZU�cQQ(>�%Symfony/Component/Routing/autoloader.phpnu�[���PKw�Z����'�'+�%Symfony/Component/Routing/RouteCompiler.phpnu�[���PKw�Z��%�%$�%Symfony/Component/Routing/Router.phpnu�[���PKw�Z���q
q
6n�%Symfony/Component/Routing/Matcher/ApacheUrlMatcher.phpnu�[���PKw�Z	�ڗ9E�%Symfony/Component/Routing/Matcher/UrlMatcherInterface.phpnu�[���PKw�Z`�u���=��%Symfony/Component/Routing/Matcher/RequestMatcherInterface.phpnu�[���PKw�Z[z�dd<�&Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.phpnu�[���PKw�Z?�|{��:�&Symfony/Component/Routing/Matcher/Dumper/MatcherDumper.phpnu�[���PKw�Z�x}�44=�&Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.phpnu�[���PKw�Z�bz#z#@A&Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.phpnu�[���PKw�Z�`=e&Symfony/Component/Routing/Matcher/Dumper/DumperCollection.phpnu�[���PKw�Z�N�
�
C�s&Symfony/Component/Routing/Matcher/Dumper/DumperPrefixCollection.phpnu�[���PKw�Z(� ���C�~&Symfony/Component/Routing/Matcher/Dumper/MatcherDumperInterface.phpnu�[���PKw�ZY�IWW8��&Symfony/Component/Routing/Matcher/Dumper/DumperRoute.phpnu�[���PKw�Z�'��9��&Symfony/Component/Routing/Matcher/TraceableUrlMatcher.phpnu�[���PKw�ZGj�C""0��&Symfony/Component/Routing/Matcher/UrlMatcher.phpnu�[���PKw�Z� ��ffE'�&Symfony/Component/Routing/Matcher/RedirectableUrlMatcherInterface.phpnu�[���PKw�Z����==K�&Symfony/Component/Routing/Exception/MissingMandatoryParametersException.phpnu�[���PKw�Zj`j�A��&Symfony/Component/Routing/Exception/InvalidParameterException.phpnu�[���PKw�Znj�W��>/�&Symfony/Component/Routing/Exception/RouteNotFoundException.phpnu�[���PKw�Z��)���:��&Symfony/Component/Routing/Exception/ExceptionInterface.phpnu�[���PKw�Z����JJA��&Symfony/Component/Routing/Exception/MethodNotAllowedException.phpnu�[���PKw�Z?�]�//Af�&Symfony/Component/Routing/Exception/ResourceNotFoundException.phpnu�[���PKw�Z��^�==#�&Symfony/Component/Routing/Route.phpnu�[���PKw�Zr�����:i	'Symfony/Component/Routing/RequestContextAwareInterface.phpnu�[���PKw�Z|,{Ȫ�-p'Symfony/Component/Routing/RouteCollection.phpnu�[���PKw�Z�h�,w)'Symfony/Component/Routing/RequestContext.phpnu�[���PKw�Zմ���I�C'Symfony/Component/Routing/Generator/ConfigurableRequirementsInterface.phpnu�[���PKw�Z�
��1�148M'Symfony/Component/Routing/Generator/UrlGenerator.phpnu�[���PKw�Z�1O�
�
Az'Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.phpnu�[���PKw�Zu�'��>��'Symfony/Component/Routing/Generator/Dumper/GeneratorDumper.phpnu�[���PKw�Z�4��G��'Symfony/Component/Routing/Generator/Dumper/GeneratorDumperInterface.phpnu�[���PKw�Z����@@=�'Symfony/Component/Routing/Generator/UrlGeneratorInterface.phpnu�[���PKw�Zn���hh2Ȥ'Symfony/Component/Routing/Loader/ClosureLoader.phpnu�[���PKw�Z��?�		>��'Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.phpnu�[���PKw�Z~ޟ
�
9�'Symfony/Component/Routing/Loader/AnnotationFileLoader.phpnu�[���PKw�Z~L�W��:�'Symfony/Component/Routing/Loader/AnnotationClassLoader.phpnu�[���PKw�ZP�i{��2��'Symfony/Component/Routing/Loader/PhpFileLoader.phpnu�[���PKw�Z?-[��	�	?5�'Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsdnu�[���PKw�Zأ2D$D$2L�'Symfony/Component/Routing/Loader/XmlFileLoader.phpnu�[���PKw�ZpB�Q Q 3�(Symfony/Component/Routing/Loader/YamlFileLoader.phpnu�[���PKx�ZqF��>>4�5(Symfony/Component/Routing/RouteCompilerInterface.phpnu�[���PKx�Z0���QQ(H9(Symfony/Component/Process/autoloader.phpnu�[���PKx�Zg��'�'*�:(Symfony/Component/Process/ProcessPipes.phpnu�[���PKx�Z��2�{{@6c(Symfony/Component/Process/Exception/ProcessTimedOutException.phpnu�[���PKx�Z�<���:!j(Symfony/Component/Process/Exception/ExceptionInterface.phpnu�[���PKx�Z>H����8:l(Symfony/Component/Process/Exception/RuntimeException.phpnu�[���PKx�Z��W��6�n(Symfony/Component/Process/Exception/LogicException.phpnu�[���PKx�Z˅����@�p(Symfony/Component/Process/Exception/InvalidArgumentException.phpnu�[���PKx�Z��_��>s(Symfony/Component/Process/Exception/ProcessFailedException.phpnu�[���PKx�Z@s�(�x(Symfony/Component/Process/PhpProcess.phpnu�[���PKx�Z�nL	L	*�(Symfony/Component/Process/ProcessUtils.phpnu�[���PKy�Z�!,$

.��(Symfony/Component/Process/ExecutableFinder.phpnu�[���PKy�Z!/���,�(Symfony/Component/Process/ProcessBuilder.phpnu�[���PKy�Zy>�8��1�(Symfony/Component/Process/PhpExecutableFinder.phpnu�[���PKy�Z��M��%ު(Symfony/Component/Process/Process.phpnu�[���PKy�Z[i55ERA)Symfony/Component/Serializer/Normalizer/SerializerAwareNormalizer.phpnu�[���PKy�Z=Vxe::A�D)Symfony/Component/Serializer/Normalizer/NormalizableInterface.phpnu�[���PKy�Z��SVV<�J)Symfony/Component/Serializer/Normalizer/CustomNormalizer.phpnu�[���PKy�Z��,,BiR)Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.phpnu�[���PKy�Z"p�yy?q)Symfony/Component/Serializer/Normalizer/NormalizerInterface.phpnu�[���PKy�Z�qU���C�u)Symfony/Component/Serializer/Normalizer/DenormalizableInterface.phpnu�[���PKz�Z���A�{)Symfony/Component/Serializer/Normalizer/DenormalizerInterface.phpnu�[���PKz�Z���OO9t�)Symfony/Component/Serializer/SerializerAwareInterface.phpnu�[���PKz�Z��TT+,�)Symfony/Component/Serializer/autoloader.phpnu�[���PKz�Zx蕰

4ۅ)Symfony/Component/Serializer/SerializerInterface.phpnu�[���PKz�Z,�c��9L�)Symfony/Component/Serializer/Encoder/EncoderInterface.phpnu�[���PKz�Z��[�5�53i�)Symfony/Component/Serializer/Encoder/XmlEncoder.phpnu�[���PKz�Z�<=ggD��)Symfony/Component/Serializer/Encoder/NormalizationAwareInterface.phpnu�[���PKz�ZV��O��5��)Symfony/Component/Serializer/Encoder/ChainDecoder.phpnu�[���PKz�Z�=��?��)Symfony/Component/Serializer/Encoder/SerializerAwareEncoder.phpnu�[���PKz�Zv:�hh3[�)Symfony/Component/Serializer/Encoder/JsonEncode.phpnu�[���PKz�Z��@���3&�)Symfony/Component/Serializer/Encoder/JsonDecode.phpnu�[���PKz�ZS R�	�	5q�)Symfony/Component/Serializer/Encoder/ChainEncoder.phpnu�[���PKz�Z�o�vv4��)Symfony/Component/Serializer/Encoder/JsonEncoder.phpnu�[���PKz�Z|ͼ���9��)Symfony/Component/Serializer/Encoder/DecoderInterface.phpnu�[���PKz�ZA�A
��4�*Symfony/Component/Serializer/Exception/Exception.phpnu�[���PKz�Z�^L��?�*Symfony/Component/Serializer/Exception/UnsupportedException.phpnu�[���PKz�Z�h=��;�*Symfony/Component/Serializer/Exception/RuntimeException.phpnu�[���PKz�ZJ���9�*Symfony/Component/Serializer/Exception/LogicException.phpnu�[���PKz�ZT��Y��C	*Symfony/Component/Serializer/Exception/InvalidArgumentException.phpnu�[���PKz�Z[�����Ci*Symfony/Component/Serializer/Exception/UnexpectedValueException.phpnu�[���PKz�Zʪ2/&/&+�
*Symfony/Component/Serializer/Serializer.phpnu�[���PKz�ZFP�PP'<4*Symfony/Component/Locale/autoloader.phpnu�[���PKz�Z�Q�UUL�5*Symfony/Component/Locale/Exception/MethodArgumentNotImplementedException.phpnu�[���PKz�Z��E>�9*Symfony/Component/Locale/Exception/NotImplementedException.phpnu�[���PKz�ZS�?a%%D#=*Symfony/Component/Locale/Exception/MethodNotImplementedException.phpnu�[���PKz�Z���ssQ�@*Symfony/Component/Locale/Exception/MethodArgumentValueNotImplementedException.phpnu�[���PKz�Z�C��*�D*Symfony/Component/Locale/Stub/StubIntl.phpnu�[���PKz�Z&�����5�G*Symfony/Component/Locale/Stub/StubNumberFormatter.phpnu�[���PKz�Zv/�@�J*Symfony/Component/Locale/Stub/DateFormat/Hour2401Transformer.phpnu�[���PKz�Z��S@PN*Symfony/Component/Locale/Stub/DateFormat/TimeZoneTransformer.phpnu�[���PKz�Z}��""A�Q*Symfony/Component/Locale/Stub/DateFormat/DayOfYearTransformer.phpnu�[���PKz�Z�X�<oU*Symfony/Component/Locale/Stub/DateFormat/AmPmTransformer.phpnu�[���PKz�Z���<�X*Symfony/Component/Locale/Stub/DateFormat/YearTransformer.phpnu�[���PKz�Zmў?O\*Symfony/Component/Locale/Stub/DateFormat/QuarterTransformer.phpnu�[���PKz�Zg[ep>�_*Symfony/Component/Locale/Stub/DateFormat/MinuteTransformer.phpnu�[���PKz�Z:6""ARc*Symfony/Component/Locale/Stub/DateFormat/DayOfWeekTransformer.phpnu�[���PKz�Z9�u@�f*Symfony/Component/Locale/Stub/DateFormat/Hour1200Transformer.phpnu�[���PKz�Zk&"M@qj*Symfony/Component/Locale/Stub/DateFormat/Hour1201Transformer.phpnu�[���PKz�Z�����;�m*Symfony/Component/Locale/Stub/DateFormat/DayTransformer.phpnu�[���PKz�Z��@fq*Symfony/Component/Locale/Stub/DateFormat/Hour2400Transformer.phpnu�[���PKz�Z�Ed��8�t*Symfony/Component/Locale/Stub/DateFormat/Transformer.phpnu�[���PKz�Zt�z

=Ox*Symfony/Component/Locale/Stub/DateFormat/MonthTransformer.phpnu�[���PKz�Zk�H<�{*Symfony/Component/Locale/Stub/DateFormat/FullTransformer.phpnu�[���PKz�Z�3�X>6*Symfony/Component/Locale/Stub/DateFormat/SecondTransformer.phpnu�[���PKz�Z�
�

<��*Symfony/Component/Locale/Stub/DateFormat/HourTransformer.phpnu�[���PKz�Z���?��.-�*Symfony/Component/Locale/Stub/StubCollator.phpnu�[���PK{�Zq��*((,�*Symfony/Component/Locale/Stub/StubLocale.phpnu�[���PK{�Z� S���7��*Symfony/Component/Locale/Stub/StubIntlDateFormatter.phpnu�[���PK{�Zl�l��#��*Symfony/Component/Locale/Locale.phpnu�[���PK{�Z�t�TT+��*Symfony/Component/Filesystem/autoloader.phpnu�[���PK{�Z��dP��@b�*Symfony/Component/Filesystem/Exception/FileNotFoundException.phpnu�[���PK{�Z3{����=��*Symfony/Component/Filesystem/Exception/ExceptionInterface.phpnu�[���PK{�ZoC�~��?��*Symfony/Component/Filesystem/Exception/IOExceptionInterface.phpnu�[���PK{�Z;�{��6ͷ*Symfony/Component/Filesystem/Exception/IOException.phpnu�[���PK{�ZOظ�GG+�*Symfony/Component/Filesystem/Filesystem.phpnu�[���PK{�Z)��.�.'T+Symfony/Component/Form/FormRenderer.phpnu�[���PK{�Z�C����.]2+Symfony/Component/Form/ButtonTypeInterface.phpnu�[���PK{�ZK'�$��&�4+Symfony/Component/Form/FormBuilder.phpnu�[���PK{�Z&�"̰T�T,�S+Symfony/Component/Form/FormConfigBuilder.phpnu�[���PK{�ZE1�'��4��+Symfony/Component/Form/SubmitButtonTypeInterface.phpnu�[���PK{�Z�d��'�+Symfony/Component/Form/FormRegistry.phpnu�[���PK{�ZÊM'%%.н+Symfony/Component/Form/FormConfigInterface.phpnu�[���PK{�Z��@@/S�+Symfony/Component/Form/FormTypeGuesserChain.phpnu�[���PK{�ZR����+��+Symfony/Component/Form/Guess/ValueGuess.phpnu�[���PK{�Z�511&,�+Symfony/Component/Form/Guess/Guess.phpnu�[���PK{�Z���  *��+Symfony/Component/Form/Guess/TypeGuess.phpnu�[���PK{�Z�0\ZZ.-�+Symfony/Component/Form/CallbackTransformer.phpnu�[���PK{�Z4�Nz"z"!�,Symfony/Component/Form/Button.phpnu�[���PK{�Z-�9NN%�%,Symfony/Component/Form/autoloader.phpnu�[���PK{�Z�/��tt%S',Symfony/Component/Form/FormEvents.phpnu�[���PK{�Z�����,,,Symfony/Component/Form/FormTypeInterface.phpnu�[���PK{�Z�>���09,Symfony/Component/Form/FormRegistryInterface.phpnu�[���PK{�Z��?zz3?,Symfony/Component/Form/FormTypeGuesserInterface.phpnu�[���PK{�Z��*��+�G,Symfony/Component/Form/ResolvedFormType.phpnu�[���PK{�ZObX�qq'6f,Symfony/Component/Form/SubmitButton.phpnu�[���PK|�Z�p��1�j,Symfony/Component/Form/AbstractRendererEngine.phpnu�[���PK|�ZDjN,1�,Symfony/Component/Form/AbstractExtension.phpnu�[���PK|�Zf#jK��6��,Symfony/Component/Form/FormRendererEngineInterface.phpnu�[���PK|�Z���1�1���,Symfony/Component/Form/Form.phpnu�[���PK|�Z�di���;A-Symfony/Component/Form/Exception/BadMethodCallException.phpnu�[���PK|�Z�W�

:yC-Symfony/Component/Form/Exception/AlreadyBoundException.phpnu�[���PK|�Z(ddB�E-Symfony/Component/Form/Exception/InvalidConfigurationException.phpnu�[���PK|�Z�_c==<�G-Symfony/Component/Form/Exception/UnexpectedTypeException.phpnu�[���PK|�Z�S�D��BoJ-Symfony/Component/Form/Exception/TransformationFailedException.phpnu�[���PK|�Z��9�L-Symfony/Component/Form/Exception/OutOfBoundsException.phpnu�[���PK}�Z�y�u��7�N-Symfony/Component/Form/Exception/ExceptionInterface.phpnu�[���PK}�ZN����5
Q-Symfony/Component/Form/Exception/RuntimeException.phpnu�[���PK}�ZK�9���>OS-Symfony/Component/Form/Exception/AlreadySubmittedException.phpnu�[���PK}�Z1�;TT:�U-Symfony/Component/Form/Exception/ErrorMappingException.phpnu�[���PK}�Z��+RR8oW-Symfony/Component/Form/Exception/StringCastException.phpnu�[���PK}�Z��X��3)Y-Symfony/Component/Form/Exception/LogicException.phpnu�[���PK}�Z�gBz��=d[-Symfony/Component/Form/Exception/InvalidArgumentException.phpnu�[���PK}�Z�1��88'�]-Symfony/Component/Form/AbstractType.phpnu�[���PK}�Z�I	�66.Ub-Symfony/Component/Form/Util/OrderedHashMap.phpnu�[���PK}�Z�h��''6�t-Symfony/Component/Form/Util/OrderedHashMapIterator.phpnu�[���PK}�Z��F228v�-Symfony/Component/Form/Util/VirtualFormAwareIterator.phpnu�[���PK}�Zy���$$(�-Symfony/Component/Form/Util/FormUtil.phpnu�[���PK}�Z<����8��-Symfony/Component/Form/Util/InheritDataAwareIterator.phpnu�[���PK}�Z�QT�pp.�-Symfony/Component/Form/SubmitButtonBuilder.phpnu�[���PK}�Z�z5���2��-Symfony/Component/Form/ResolvedFormTypeFactory.phpnu�[���PK}�ZSf��
	
	-��-Symfony/Component/Form/PreloadedExtension.phpnu�[���PK}�Z>��*ii&�-Symfony/Component/Form/FormFactory.phpnu�[���PK}�Z�\�g��2˳-Symfony/Component/Form/RequestHandlerInterface.phpnu�[���PK}�Z+q�DAA7ɶ-Symfony/Component/Form/Test/FormPerformanceTestCase.phpnu�[���PK}�ZsŪ�,q�-Symfony/Component/Form/Test/TypeTestCase.phpnu�[���PK}�Z�,�7//7�-Symfony/Component/Form/Test/DeprecationErrorHandler.phpnu�[���PK}�ZB�4I++7k�-Symfony/Component/Form/Test/FormIntegrationTestCase.phpnu�[���PK}�Z��m�yy4��-Symfony/Component/Form/Test/FormBuilderInterface.phpnu�[���PK}�Za(0kk-��-Symfony/Component/Form/Test/FormInterface.phpnu�[���PK}�Z�n����1��-Symfony/Component/Form/FormExtensionInterface.phpnu�[���PK}�Z|G����4��-Symfony/Component/Form/ResolvedFormTypeInterface.phpnu�[���PK}�Z{d���!�!5��-Symfony/Component/Form/FormConfigBuilderInterface.phpnu�[���PK}�ZɃT���6.Symfony/Component/Form/FormFactoryBuilderInterface.phpnu�[���PK}�Z�N̷;m.Symfony/Component/Form/ResolvedFormTypeFactoryInterface.phpnu�[���PK}�Z2��-�.Symfony/Component/Form/FormFactoryBuilder.phpnu�[���PK}�Z���C��0d$.Symfony/Component/Form/AbstractTypeExtension.phpnu�[���PK}�Z�E���0�(.Symfony/Component/Form/FormRendererInterface.phpnu�[���PK}�Z�:		/�5.Symfony/Component/Form/FormBuilderInterface.phpnu�[���PK}�Z��Z)��/R?.Symfony/Component/Form/FormFactoryInterface.phpnu�[���PK}�Z�YB���.EP.Symfony/Component/Form/ReversedTransformer.phpnu�[���PK}�Z�r�WW3�U.Symfony/Component/Form/DataTransformerInterface.phpnu�[���PK}�ZW�b�[H[H(Eb.Symfony/Component/Form/ButtonBuilder.phpnu�[���PK}�Z��n��?��.Symfony/Component/Form/Resources/translations/validators.en.xlfnu�[���PK}�Z誫���?�.Symfony/Component/Form/Resources/translations/validators.sk.xlfnu�[���PK}�Z�<�yy?=�.Symfony/Component/Form/Resources/translations/validators.uk.xlfnu�[���PK}�Z:����?%�.Symfony/Component/Form/Resources/translations/validators.pl.xlfnu�[���PK��Z��
���?[�.Symfony/Component/Form/Resources/translations/validators.pt.xlfnu�[���PK��Z�%��?��.Symfony/Component/Form/Resources/translations/validators.lv.xlfnu�[���PK��Z္o33D��.Symfony/Component/Form/Resources/translations/validators.sr_Cyrl.xlfnu�[���PK��Z����?��.Symfony/Component/Form/Resources/translations/validators.fi.xlfnu�[���PK��Z0h���?��.Symfony/Component/Form/Resources/translations/validators.es.xlfnu�[���PK��Z�TI��?,�.Symfony/Component/Form/Resources/translations/validators.de.xlfnu�[���PK��Z!�aZ��?~�.Symfony/Component/Form/Resources/translations/validators.it.xlfnu�[���PK��Z �!���?��.Symfony/Component/Form/Resources/translations/validators.ca.xlfnu�[���PK��Z���?��.Symfony/Component/Form/Resources/translations/validators.mn.xlfnu�[���PK��Z���-��?X�.Symfony/Component/Form/Resources/translations/validators.ru.xlfnu�[���PK��Z�3Ե^^?T�.Symfony/Component/Form/Resources/translations/validators.bg.xlfnu�[���PK��ZE��d��?!�.Symfony/Component/Form/Resources/translations/validators.ro.xlfnu�[���PK��ZO���?r�.Symfony/Component/Form/Resources/translations/validators.nl.xlfnu�[���PK��ZS�*��?��.Symfony/Component/Form/Resources/translations/validators.et.xlfnu�[���PK��Z�V5?��.Symfony/Component/Form/Resources/translations/validators.fa.xlfnu�[���PK��Z��q��?J�.Symfony/Component/Form/Resources/translations/validators.id.xlfnu�[���PK��Z�
���?w/Symfony/Component/Form/Resources/translations/validators.cs.xlfnu�[���PK��Z�8,:��B�/Symfony/Component/Form/Resources/translations/validators.zh_CN.xlfnu�[���PK��Z�H�q��?�
/Symfony/Component/Form/Resources/translations/validators.lt.xlfnu�[���PK��Z�_8��?�/Symfony/Component/Form/Resources/translations/validators.fr.xlfnu�[���PK��Z�A�4��?�/Symfony/Component/Form/Resources/translations/validators.gl.xlfnu�[���PK��Z
b�8��?4/Symfony/Component/Form/Resources/translations/validators.hr.xlfnu�[���PK��ZWgUugg?]/Symfony/Component/Form/Resources/translations/validators.nb.xlfnu�[���PK��Zٻ��||?3/Symfony/Component/Form/Resources/translations/validators.eu.xlfnu�[���PK��Z�4@���B#/Symfony/Component/Form/Resources/translations/validators.pt_BR.xlfnu�[���PK��Z��5��?Q'/Symfony/Component/Form/Resources/translations/validators.sl.xlfnu�[���PK��Z�*{���?m+/Symfony/Component/Form/Resources/translations/validators.lb.xlfnu�[���PK��Zbe�@��?�//Symfony/Component/Form/Resources/translations/validators.hu.xlfnu�[���PK��Z_Π��?4/Symfony/Component/Form/Resources/translations/validators.el.xlfnu�[���PK��ZX�����?9/Symfony/Component/Form/Resources/translations/validators.da.xlfnu�[���PK��Z���?�</Symfony/Component/Form/Resources/translations/validators.ja.xlfnu�[���PK��Zs>�ll?AA/Symfony/Component/Form/Resources/translations/validators.sv.xlfnu�[���PK��Zy��99?E/Symfony/Component/Form/Resources/translations/validators.hy.xlfnu�[���PK��Z|��C?�I/Symfony/Component/Form/Resources/translations/validators.ar.xlfnu�[���PK��Zr���DBN/Symfony/Component/Form/Resources/translations/validators.sr_Latn.xlfnu�[���PK��ZNP\��?dR/Symfony/Component/Form/Resources/translations/validators.he.xlfnu�[���PK��Z�xfh..6dV/Symfony/Component/Form/Resources/config/validation.xmlnu�[���PK��ZR}��jj.�X/Symfony/Component/Form/DataMapperInterface.phpnu�[���PK��Z�s�� � (�]/Symfony/Component/Form/FormInterface.phpnu�[���PK��Z���"��$�~/Symfony/Component/Form/FormEvent.phpnu�[���PK��Z�=�MM5Ӄ/Symfony/Component/Form/FormTypeExtensionInterface.phpnu�[���PK��Z�}p�

$��/Symfony/Component/Form/FormError.phpnu�[���PK��Z�	���/ܖ/Symfony/Component/Form/NativeRequestHandler.phpnu�[���PK��Z���*��O'�/Symfony/Component/Form/Extension/Validator/EventListener/ValidationListener.phpnu�[���PK��Z��Ck��@5�/Symfony/Component/Form/Extension/Validator/Util/ServerParams.phpnu�[���PK��Z2=[<((A1�/Symfony/Component/Form/Extension/Validator/ValidatorExtension.phpnu�[���PK��Z}>�ُ�?��/Symfony/Component/Form/Extension/Validator/Constraints/Form.phpnu�[���PK��Z�-�P��H��/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.phpnu�[���PK��Zl�Ct*t*C��/Symfony/Component/Form/Extension/Validator/ValidatorTypeGuesser.phpnu�[���PK��ZɥS��T�
0Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPathIterator.phpnu�[���PK��Z�\T��K0Symfony/Component/Form/Extension/Validator/ViolationMapper/RelativePath.phpnu�[���PK��ZC_�hU+U+N0Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.phpnu�[���PK��Z�k�t==W�@0Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapperInterface.phpnu�[���PK��Z�-��!!L�E0Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPath.phpnu�[���PK��Zf����
�
JR_0Symfony/Component/Form/Extension/Validator/ViolationMapper/MappingRule.phpnu�[���PK��Z�����J�j0Symfony/Component/Form/Extension/Validator/Type/BaseValidatorExtension.phpnu�[���PK��ZeBR�	�	N�p0Symfony/Component/Form/Extension/Validator/Type/FormTypeValidatorExtension.phpnu�[���PK��Z͚>�@@R+{0Symfony/Component/Form/Extension/Validator/Type/RepeatedTypeValidatorExtension.phpnu�[���PK��Z1���P�0Symfony/Component/Form/Extension/Validator/Type/SubmitTypeValidatorExtension.phpnu�[���PK��Z���,QQC��0Symfony/Component/Form/Extension/Templating/TemplatingExtension.phpnu�[���PK��Zզ�Y��HL�0Symfony/Component/Form/Extension/Templating/TemplatingRendererEngine.phpnu�[���PK��Z䋧��U��0Symfony/Component/Form/Extension/HttpFoundation/EventListener/BindRequestListener.phpnu�[���PK��Z�j��=
=
PԦ0Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationRequestHandler.phpnu�[���PK��Z��Q��K��0Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationExtension.phpnu�[���PK��Z�PffX��0Symfony/Component/Form/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.phpnu�[���PK��Z"�q���7��0Symfony/Component/Form/Extension/Csrf/CsrfExtension.phpnu�[���PK��Z�C���J��0Symfony/Component/Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.phpnu�[���PK��Z[^����J��0Symfony/Component/Form/Extension/Csrf/CsrfProvider/SessionCsrfProvider.phpnu�[���PK��Z%�G���L�0Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderInterface.phpnu�[���PK��Z�����JI�0Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderAdapter.phpnu�[���PK��ZR�'WTTN��0Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfTokenManagerAdapter.phpnu�[���PK��Z�?�ooNy�0Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.phpnu�[���PK��Z��
f��Df�0Symfony/Component/Form/Extension/Csrf/Type/FormTypeCsrfExtension.phpnu�[���PK��ZC�W���7�
1Symfony/Component/Form/Extension/Core/CoreExtension.phpnu�[���PK��Z�:AAD�1Symfony/Component/Form/Extension/Core/EventListener/TrimListener.phpnu�[���PK��Zõe��O�1Symfony/Component/Form/Extension/Core/EventListener/MergeCollectionListener.phpnu�[���PK��Z>Q?��N�+1Symfony/Component/Form/Extension/Core/EventListener/FixUrlProtocolListener.phpnu�[���PK��Zb����P�11Symfony/Component/Form/Extension/Core/EventListener/FixCheckboxInputListener.phpnu�[���PK��Z\��//J�=1Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.phpnu�[���PK��Z?D���M�Q1Symfony/Component/Form/Extension/Core/EventListener/FixRadioInputListener.phpnu�[���PK��Z�jю��E�Z1Symfony/Component/Form/Extension/Core/ChoiceList/SimpleChoiceList.phpnu�[���PK��Z�
�##E�p1Symfony/Component/Form/Extension/Core/ChoiceList/ObjectChoiceList.phpnu�[���PK��Zl_R(H��1Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceListInterface.phpnu�[���PK��Z�В4
4
C�1Symfony/Component/Form/Extension/Core/ChoiceList/LazyChoiceList.phpnu�[���PK��Z'���??��1Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceList.phpnu�[���PK��Z��&PP9��1Symfony/Component/Form/Extension/Core/View/ChoiceView.phpnu�[���PK��Z��

Gl�1Symfony/Component/Form/Extension/Core/DataMapper/PropertyPathMapper.phpnu�[���PK��ZO�#�#�#\�2Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.phpnu�[���PK��Z)b�""^)2Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.phpnu�[���PK��Ze�^�		V�?2Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.phpnu�[���PK��Z���Þ
�
XVI2Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.phpnu�[���PK��Zc�8V�	�	N|T2Symfony/Component/Form/Extension/Core/DataTransformer/DataTransformerChain.phpnu�[���PK��Z�;�dd]�^2Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.phpnu�[���PK��Z�Z�eTwo2Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToArrayTransformer.phpnu�[���PK��ZL�px&&Y�2Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.phpnu�[���PK��Z����		V��2Symfony/Component/Form/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.phpnu�[���PK��Z'tqk55ZJ�2Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.phpnu�[���PK��Z���ggT	�2Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToValuesTransformer.phpnu�[���PK��ZUd�q]�2Symfony/Component/Form/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.phpnu�[���PK��ZΎgW� � U��2Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToStringTransformer.phpnu�[���PK��Z�"h���R��2Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToValueTransformer.phpnu�[���PK��Z�H��		Q��2Symfony/Component/Form/Extension/Core/DataTransformer/ArrayToPartsTransformer.phpnu�[���PK��Z/C���QO�2Symfony/Component/Form/Extension/Core/DataTransformer/BaseDateTimeTransformer.phpnu�[���PK��Z���T��T��2Symfony/Component/Form/Extension/Core/DataTransformer/BooleanToStringTransformer.phpnu�[���PK��Z]��yD	D	[/3Symfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.phpnu�[���PK��Z���/�+�+9�
3Symfony/Component/Form/Extension/Core/Type/ChoiceType.phpnu�[���PK��Z��h��9:3Symfony/Component/Form/Extension/Core/Type/ButtonType.phpnu�[���PK��ZD�U��9s>3Symfony/Component/Form/Extension/Core/Type/SubmitType.phpnu�[���PK��Z񍢸��;�B3Symfony/Component/Form/Extension/Core/Type/CurrencyType.phpnu�[���PK��Z�Ѝ'��9�F3Symfony/Component/Form/Extension/Core/Type/HiddenType.phpnu�[���PK��Z���D��9�J3Symfony/Component/Form/Extension/Core/Type/LocaleType.phpnu�[���PK��ZuƵ�``:O3Symfony/Component/Form/Extension/Core/Type/IntegerType.phpnu�[���PK��Za����8�W3Symfony/Component/Form/Extension/Core/Type/ResetType.phpnu�[���PK��Z옇���;'[3Symfony/Component/Form/Extension/Core/Type/PasswordType.phpnu�[���PK��Zٝ��GG7]`3Symfony/Component/Form/Extension/Core/Type/BaseType.phpnu�[���PK��ZZ���^^:r3Symfony/Component/Form/Extension/Core/Type/PercentType.phpnu�[���PK��Z��TT;�w3Symfony/Component/Form/Extension/Core/Type/CheckboxType.phpnu�[���PK��Z&ߏ�vv;��3Symfony/Component/Form/Extension/Core/Type/BirthdayType.phpnu�[���PK��Z7pO�LL8s�3Symfony/Component/Form/Extension/Core/Type/RadioType.phpnu�[���PK��Z�G�oo7'�3Symfony/Component/Form/Extension/Core/Type/FileType.phpnu�[���PK��Z�8��JJ9��3Symfony/Component/Form/Extension/Core/Type/SearchType.phpnu�[���PK��Z�_��LL;��3Symfony/Component/Form/Extension/Core/Type/TimezoneType.phpnu�[���PK��Z���HH8g�3Symfony/Component/Form/Extension/Core/Type/EmailType.phpnu�[���PK��Z[Gԃ��=�3Symfony/Component/Form/Extension/Core/Type/CollectionType.phpnu�[���PK��Z�t�II;1�3Symfony/Component/Form/Extension/Core/Type/TextareaType.phpnu�[���PK��Z����;�3Symfony/Component/Form/Extension/Core/Type/LanguageType.phpnu�[���PK��ZT;���7��3Symfony/Component/Form/Extension/Core/Type/TextType.phpnu�[���PK��ZH?!a��7J�3Symfony/Component/Form/Extension/Core/Type/TimeType.phpnu�[���PK��Z�� &�'�';��3Symfony/Component/Form/Extension/Core/Type/DateTimeType.phpnu�[���PK��Z�q���6��3Symfony/Component/Form/Extension/Core/Type/UrlType.phpnu�[���PK��Z9�;�3Symfony/Component/Form/Extension/Core/Type/RepeatedType.phpnu�[���PK��ZM2\3,3,7E4Symfony/Component/Form/Extension/Core/Type/DateType.phpnu�[���PK��Za�LŢ�:�34Symfony/Component/Form/Extension/Core/Type/CountryType.phpnu�[���PK��ZC�i���9�74Symfony/Component/Form/Extension/Core/Type/NumberType.phpnu�[���PK��Z:�y�

7;@4Symfony/Component/Form/Extension/Core/Type/FormType.phpnu�[���PK��Z5�S
��8�\4Symfony/Component/Form/Extension/Core/Type/MoneyType.phpnu�[���PK��Z6s���D�i4Symfony/Component/Form/Extension/DataCollector/FormDataCollector.phpnu�[���PK��ZI��2

Vȇ4Symfony/Component/Form/Extension/DataCollector/EventListener/DataCollectorListener.phpnu�[���PK��Z�T���Mc�4Symfony/Component/Form/Extension/DataCollector/FormDataCollectorInterface.phpnu�[���PK��Z����M��4Symfony/Component/Form/Extension/DataCollector/FormDataExtractorInterface.phpnu�[���PK��Z|�
]��W�4Symfony/Component/Form/Extension/DataCollector/Proxy/ResolvedTypeDataCollectorProxy.phpnu�[���PK��Z�((^6�4Symfony/Component/Form/Extension/DataCollector/Proxy/ResolvedTypeFactoryDataCollectorProxy.phpnu�[���PK��Z��#�11I�4Symfony/Component/Form/Extension/DataCollector/DataCollectorExtension.phpnu�[���PK��Z%�`��D��4Symfony/Component/Form/Extension/DataCollector/FormDataExtractor.phpnu�[���PK��Z�1�
uuR��4Symfony/Component/Form/Extension/DataCollector/Type/DataCollectorTypeExtension.phpnu�[���PK��ZuUS�WWU��4Symfony/Component/Form/Extension/DependencyInjection/DependencyInjectionExtension.phpnu�[���PK��Z(s
//-a�4Symfony/Component/Form/ClickableInterface.phpnu�[���PK��ZH��
�
#��4Symfony/Component/Form/FormView.phpnu�[���PK��Z
�͋ �4Symfony/Component/Form/Forms.phpnu�[���PK��Z\�F1_
5Symfony/Component/Security/Acl/Voter/AclVoter.phpnu�[���PK��Z\!�	HH2�#5Symfony/Component/Security/Acl/Voter/FieldVote.phpnu�[���PK��ZP͡��Am'5Symfony/Component/Security/Acl/Exception/AclNotFoundException.phpnu�[���PK��Z�k�q��6�)5Symfony/Component/Security/Acl/Exception/Exception.phpnu�[���PK��Z�W�L�+5Symfony/Component/Security/Acl/Exception/ConcurrentModificationException.phpnu�[���PK��Z���OI}.5Symfony/Component/Security/Acl/Exception/InvalidDomainObjectException.phpnu�[���PK��Z]��_""E15Symfony/Component/Security/Acl/Exception/NotAllAclsFoundException.phpnu�[���PK��Z�B�l��@�55Symfony/Component/Security/Acl/Exception/NoAceFoundException.phpnu�[���PK��Z[�z�B�85Symfony/Component/Security/Acl/Exception/SidNotLoadedException.phpnu�[���PK��Z��5�

F;5Symfony/Component/Security/Acl/Exception/AclAlreadyExistsException.phpnu�[���PK��Zt��:�=5Symfony/Component/Security/Acl/Dbal/MutableAclProvider.phpnu�[���PK��Z�^�+f+f3��5Symfony/Component/Security/Acl/Dbal/AclProvider.phpnu�[���PK��ZK� V��.n,6Symfony/Component/Security/Acl/Dbal/Schema.phpnu�[���PK��ZNTA�]]5�D6Symfony/Component/Security/Acl/Domain/AuditLogger.phpnu�[���PK��Z�.��**>sJ6Symfony/Component/Security/Acl/Domain/UserSecurityIdentity.phpnu�[���PK��Z��C3��:W6Symfony/Component/Security/Acl/Domain/DoctrineAclCache.phpnu�[���PK��Z(]���D#p6Symfony/Component/Security/Acl/Domain/PermissionGrantingStrategy.phpnu�[���PK��Z%�}`M`M-k�6Symfony/Component/Security/Acl/Domain/Acl.phpnu�[���PK��Z����K(�6Symfony/Component/Security/Acl/Domain/SecurityIdentityRetrievalStrategy.phpnu�[���PK��Z�X�
/	/	<K�6Symfony/Component/Security/Acl/Domain/AclCollectionCache.phpnu�[���PK��Z5D�[/��6Symfony/Component/Security/Acl/Domain/Entry.phpnu�[���PK��Z�pU���4H7Symfony/Component/Security/Acl/Domain/FieldEntry.phpnu�[���PK��Z^@�.YY8R7Symfony/Component/Security/Acl/Domain/ObjectIdentity.phpnu�[���PK��Z0F���I7Symfony/Component/Security/Acl/Domain/ObjectIdentityRetrievalStrategy.phpnu�[���PK��ZtA)�==>J7Symfony/Component/Security/Acl/Domain/RoleSecurityIdentity.phpnu�[���PK��Z�#��~~<�#7Symfony/Component/Security/Acl/Resources/bin/generateSql.phpnu�[���PK��Zj~	cFF7�+7Symfony/Component/Security/Acl/Resources/schema/db2.sqlnu�[���PK��ZT��skk>�87Symfony/Component/Security/Acl/Resources/schema/postgresql.sqlnu�[���PK��ZJx�.

9eE7Symfony/Component/Security/Acl/Resources/schema/mssql.sqlnu�[���PK��ZfZ��^^9�R7Symfony/Component/Security/Acl/Resources/schema/mysql.sqlnu�[���PK��Z��c�
�
;�^7Symfony/Component/Security/Acl/Resources/schema/drizzle.sqlnu�[���PK��Z�C� ;;:�i7Symfony/Component/Security/Acl/Resources/schema/oracle.sqlnu�[���PK��Z��d��:I�7Symfony/Component/Security/Acl/Resources/schema/sqlite.sqlnu�[���PK��Zw���D��7Symfony/Component/Security/Acl/Permission/PermissionMapInterface.phpnu�[���PK��Z�ep�gg9��7Symfony/Component/Security/Acl/Permission/MaskBuilder.phpnu�[���PK��Z� c0��@ͫ7Symfony/Component/Security/Acl/Permission/BasicPermissionMap.phpnu�[���PK��Z6����<��7Symfony/Component/Security/Acl/Model/MutableAclInterface.phpnu�[���PK��Z[Ob3SK�7Symfony/Component/Security/Acl/Model/SecurityIdentityRetrievalStrategyInterface.phpnu�[���PK��ZX	��>��7Symfony/Component/Security/Acl/Model/DomainObjectInterface.phpnu�[���PK��Z�5Ayy@
�7Symfony/Component/Security/Acl/Model/ObjectIdentityInterface.phpnu�[���PK��Zt��@��7Symfony/Component/Security/Acl/Model/AuditableEntryInterface.phpnu�[���PK��Z-癥��Lk�7Symfony/Component/Security/Acl/Model/PermissionGrantingStrategyInterface.phpnu�[���PK��Z�����=��7Symfony/Component/Security/Acl/Model/AclProviderInterface.phpnu�[���PK��Z�#���:&�7Symfony/Component/Security/Acl/Model/AclCacheInterface.phpnu�[���PK��Zӗ&1>��7Symfony/Component/Security/Acl/Model/AuditableAclInterface.phpnu�[���PK��Z�ݤUU<�7Symfony/Component/Security/Acl/Model/FieldEntryInterface.phpnu�[���PK��Z�
�8FF7�7Symfony/Component/Security/Acl/Model/EntryInterface.phpnu�[���PK��ZH<J��=��7Symfony/Component/Security/Acl/Model/AuditLoggerInterface.phpnu�[���PK��Z���77B�8Symfony/Component/Security/Acl/Model/SecurityIdentityInterface.phpnu�[���PK��Z�𕛼�5L8Symfony/Component/Security/Acl/Model/AclInterface.phpnu�[���PK��Z�W}��Qm8Symfony/Component/Security/Acl/Model/ObjectIdentityRetrievalStrategyInterface.phpnu�[���PK��Zj���D�8Symfony/Component/Security/Acl/Model/MutableAclProviderInterface.phpnu�[���PK��Z��W"RR)�8Symfony/Component/Security/autoloader.phpnu�[���PK��Z�DXVV,t8Symfony/Component/Security/Http/Firewall.phpnu�[���PK��Z"�C��/&'8Symfony/Component/Security/Http/FirewallMap.phpnu�[���PK��Z�יK--8Symfony/Component/Security/Http/EntryPoint/FormAuthenticationEntryPoint.phpnu�[���PK��Z�<ݐppL�58Symfony/Component/Security/Http/EntryPoint/BasicAuthenticationEntryPoint.phpnu�[���PK��Z)'_++P�:8Symfony/Component/Security/Http/EntryPoint/AuthenticationEntryPointInterface.phpnu�[���PK��ZtZ�)K	K	MN?8Symfony/Component/Security/Http/EntryPoint/DigestAuthenticationEntryPoint.phpnu�[���PK��Z�����LI8Symfony/Component/Security/Http/EntryPoint/RetryAuthenticationEntryPoint.phpnu�[���PK��Z��`C��-,P8Symfony/Component/Security/Http/HttpUtils.phpnu�[���PK��Z^�V��N^h8Symfony/Component/Security/Http/Authorization/AccessDeniedHandlerInterface.phpnu�[���PK��Z��̗��W�l8Symfony/Component/Security/Http/Firewall/UsernamePasswordFormAuthenticationListener.phpnu�[���PK��Znz+S�
�
?8Symfony/Component/Security/Http/Firewall/RememberMeListener.phpnu�[���PK��Zlٯ��L6�8Symfony/Component/Security/Http/Firewall/AnonymousAuthenticationListener.phpnu�[���PK��Z�����>��8Symfony/Component/Security/Http/Firewall/ListenerInterface.phpnu�[���PK��Z�|L@**;��8Symfony/Component/Security/Http/Firewall/LogoutListener.phpnu�[���PK��Z�Bb

?J�8Symfony/Component/Security/Http/Firewall/SwitchUserListener.phpnu�[���PK��Z(�T	b!b!>��8Symfony/Component/Security/Http/Firewall/ExceptionListener.phpnu�[���PK��Z׺�=��G��8Symfony/Component/Security/Http/Firewall/X509AuthenticationListener.phpnu�[���PK��Z׿ͼ� � I��8Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.phpnu�[���PK��Z~�k��<19Symfony/Component/Security/Http/Firewall/ChannelListener.phpnu�[���PK��Z��6'6'K�9Symfony/Component/Security/Http/Firewall/AbstractAuthenticationListener.phpnu�[���PK��Z�"?���<?A9Symfony/Component/Security/Http/Firewall/ContextListener.phpnu�[���PK��Z�����MSY9Symfony/Component/Security/Http/Firewall/SimpleFormAuthenticationListener.phpnu�[���PK��Z+/��Z	Z	;�q9Symfony/Component/Security/Http/Firewall/AccessListener.phpnu�[���PK��Z�Z���Mg{9Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.phpnu�[���PK��Zn��L��9Symfony/Component/Security/Http/Firewall/SimplePreAuthenticationListener.phpnu�[���PK��Z�&!�
�
H+�9Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.phpnu�[���PK��Z2j���-$�9Symfony/Component/Security/Http/AccessMap.phpnu�[���PK��Z/�``6x�9Symfony/Component/Security/Http/AccessMapInterface.phpnu�[���PK��Z��\\��8>�9Symfony/Component/Security/Http/FirewallMapInterface.phpnu�[���PK��Z	z��J��9Symfony/Component/Security/Http/RememberMe/RememberMeServicesInterface.phpnu�[���PK��ZP�ڕ��?��9Symfony/Component/Security/Http/RememberMe/ResponseListener.phpnu�[���PK��Z���s44U�9Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.phpnu�[���PK��Z�*�b�&�&I��9Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.phpnu�[���PK��Z�a�$��K!
:Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.phpnu�[���PK��Z:�&�GGR!:Symfony/Component/Security/Http/Session/SessionAuthenticationStrategyInterface.phpnu�[���PK��Z��La[[I�":Symfony/Component/Security/Http/Session/SessionAuthenticationStrategy.phpnu�[���PK��Za7�llF�):Symfony/Component/Security/Http/Logout/DefaultLogoutSuccessHandler.phpnu�[���PK��Z1��d��H�.:Symfony/Component/Security/Http/Logout/LogoutSuccessHandlerInterface.phpnu�[���PK��Z\ü���?�2:Symfony/Component/Security/Http/Logout/SessionLogoutHandler.phpnu�[���PK��Z6O����A07:Symfony/Component/Security/Http/Logout/LogoutHandlerInterface.phpnu�[���PK��Z�ddF�;:Symfony/Component/Security/Http/Logout/CookieClearingLogoutHandler.phpnu�[���PK��Z/ sG��2xA:Symfony/Component/Security/Http/SecurityEvents.phpnu�[���PK��Z�NA��X�E:Symfony/Component/Security/Http/Authentication/AuthenticationSuccessHandlerInterface.phpnu�[���PK��Z������V/K:Symfony/Component/Security/Http/Authentication/DefaultAuthenticationFailureHandler.phpnu�[���PK��Z��H]X�X:Symfony/Component/Security/Http/Authentication/AuthenticationFailureHandlerInterface.phpnu�[���PK��Z�xGAAV^:Symfony/Component/Security/Http/Authentication/DefaultAuthenticationSuccessHandler.phpnu�[���PK��ZAH\ݞ�N�j:Symfony/Component/Security/Http/Authentication/SimpleAuthenticationHandler.phpnu�[���PK��Z�D����9|:Symfony/Component/Security/Http/Event/SwitchUserEvent.phpnu�[���PK��ZZ�v}?^�:Symfony/Component/Security/Http/Event/InteractiveLoginEvent.phpnu�[���PK��Z��VǴ�=L�:Symfony/Component/Security/Csrf/CsrfTokenManagerInterface.phpnu�[���PK��Z&%�L
L
4m�:Symfony/Component/Security/Csrf/CsrfTokenManager.phpnu�[���PK��Z�����
�
J�:Symfony/Component/Security/Csrf/TokenStorage/NativeSessionTokenStorage.phpnu�[���PK��Z�����Fn�:Symfony/Component/Security/Csrf/TokenStorage/TokenStorageInterface.phpnu�[���PK��Z��]N
N
Dq�:Symfony/Component/Security/Csrf/TokenStorage/SessionTokenStorage.phpnu�[���PK��ZeI����D3�:Symfony/Component/Security/Csrf/Exception/TokenNotFoundException.phpnu�[���PK��Z��=H��:Symfony/Component/Security/Csrf/TokenGenerator/UriSafeTokenGenerator.phpnu�[���PK��ZJ,p���J�:Symfony/Component/Security/Csrf/TokenGenerator/TokenGeneratorInterface.phpnu�[���PK��Z���O-3�:Symfony/Component/Security/Csrf/CsrfToken.phpnu�[���PK��Z��S��<��:Symfony/Component/Security/Core/SecurityContextInterface.phpnu�[���PK��Z�}�ww?��:Symfony/Component/Security/Core/Role/RoleHierarchyInterface.phpnu�[���PK��Z� �w??6m�:Symfony/Component/Security/Core/Role/RoleHierarchy.phpnu�[���PK��Z�Ħ-�:Symfony/Component/Security/Core/Role/Role.phpnu�[���PK��ZX�S�007t�:Symfony/Component/Security/Core/Role/SwitchUserRole.phpnu�[���PK��Z�'c��6�:Symfony/Component/Security/Core/Role/RoleInterface.phpnu�[���PK��ZE� �D�:Symfony/Component/Security/Core/Encoder/PasswordEncoderInterface.phpnu�[���PK��ZÆ��	�	A��:Symfony/Component/Security/Core/Encoder/BCryptPasswordEncoder.phpnu�[���PK��Z��^��H�:Symfony/Component/Security/Core/Encoder/MessageDigestPasswordEncoder.phpnu�[���PK��Z,>"�D�:Symfony/Component/Security/Core/Encoder/PlaintextPasswordEncoder.phpnu�[���PK��Z�;D��:b;Symfony/Component/Security/Core/Encoder/EncoderFactory.phpnu�[���PK��Z!�@

A�
;Symfony/Component/Security/Core/Encoder/Pbkdf2PasswordEncoder.phpnu�[���PK��Z#�MMqqCx;Symfony/Component/Security/Core/Encoder/EncoderFactoryInterface.phpnu�[���PK��Z�7���
�
?\;Symfony/Component/Security/Core/Encoder/BasePasswordEncoder.phpnu�[���PK��Z��
�77O�*;Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.phpnu�[���PK��Z��i��Fi1;Symfony/Component/Security/Core/Validator/Constraints/UserPassword.phpnu�[���PK��Z����Es4;Symfony/Component/Security/Core/Exception/BadCredentialsException.phpnu�[���PK��Z���zz=}7;Symfony/Component/Security/Core/Exception/LockedException.phpnu�[���PK��Zb��M<<Fd:;Symfony/Component/Security/Core/Exception/UnsupportedUserException.phpnu�[���PK��Z�z�&��I=;Symfony/Component/Security/Core/Exception/CredentialsExpiredException.phpnu�[���PK��Z��Xss=9@;Symfony/Component/Security/Core/Exception/LogoutException.phpnu�[���PK��Z
�04}}GC;Symfony/Component/Security/Core/Exception/UsernameNotFoundException.phpnu�[���PK��Z#��q44Q
I;Symfony/Component/Security/Core/Exception/InsufficientAuthenticationException.phpnu�[���PK��Z�5]���I�L;Symfony/Component/Security/Core/Exception/SessionUnavailableException.phpnu�[���PK��ZD��9��D�P;Symfony/Component/Security/Core/Exception/TokenNotFoundException.phpnu�[���PK��Zh�c��B�S;Symfony/Component/Security/Core/Exception/CookieTheftException.phpnu�[���PK��Z��A���@/W;Symfony/Component/Security/Core/Exception/ExceptionInterface.phpnu�[���PK��ZqUSą�CYY;Symfony/Component/Security/Core/Exception/AccessDeniedException.phpnu�[���PK��Z�'��EQ\;Symfony/Component/Security/Core/Exception/AuthenticationException.phpnu�[���PK��Z�
	��>�c;Symfony/Component/Security/Core/Exception/RuntimeException.phpnu�[���PK��Z@�	���G0f;Symfony/Component/Security/Core/Exception/ProviderNotFoundException.phpnu�[���PK��Z�ĸ���X�i;Symfony/Component/Security/Core/Exception/AuthenticationCredentialsNotFoundException.phpnu�[���PK��Z:���AADm;Symfony/Component/Security/Core/Exception/AccountStatusException.phpnu�[���PK��Z7w�-��L�r;Symfony/Component/Security/Core/Exception/AuthenticationServiceException.phpnu�[���PK��ZxB��EIv;Symfony/Component/Security/Core/Exception/AccountExpiredException.phpnu�[���PK��Z�և��?Ny;Symfony/Component/Security/Core/Exception/DisabledException.phpnu�[���PK��Ze���CA|;Symfony/Component/Security/Core/Exception/NonceExpiredException.phpnu�[���PK��Zʝ�9Fo;Symfony/Component/Security/Core/Exception/InvalidArgumentException.phpnu�[���PK��Z�O���G�;Symfony/Component/Security/Core/Exception/InvalidCsrfTokenException.phpnu�[���PK��Z�Õ�

5�;Symfony/Component/Security/Core/Util/SecureRandom.phpnu�[���PK��ZU��a��4e�;Symfony/Component/Security/Core/Util/StringUtils.phpnu�[���PK��Z��T�,,3��;Symfony/Component/Security/Core/Util/ClassUtils.phpnu�[���PK��Z�	���>8�;Symfony/Component/Security/Core/Util/SecureRandomInterface.phpnu�[���PK��Z�m2���G1�;Symfony/Component/Security/Core/Authorization/AccessDecisionManager.phpnu�[���PK��Z�З~��Ak�;Symfony/Component/Security/Core/Authorization/Voter/RoleVoter.phpnu�[���PK��Z~f�J��;Symfony/Component/Security/Core/Authorization/Voter/RoleHierarchyVoter.phpnu�[���PK��Z��`c��G]�;Symfony/Component/Security/Core/Authorization/Voter/ExpressionVoter.phpnu�[���PK��Z�X,mJ��;Symfony/Component/Security/Core/Authorization/Voter/AuthenticatedVoter.phpnu�[���PK��Z�>��F*�;Symfony/Component/Security/Core/Authorization/Voter/VoterInterface.phpnu�[���PK��Z�:22PR�;Symfony/Component/Security/Core/Authorization/AccessDecisionManagerInterface.phpnu�[���PK��Zѵ^��D��;Symfony/Component/Security/Core/Authorization/ExpressionLanguage.phpnu�[���PK��Z����=��;Symfony/Component/Security/Core/User/UserCheckerInterface.phpnu�[���PK��Z��^ 
 
:�;Symfony/Component/Security/Core/User/ChainUserProvider.phpnu�[���PK��ZD�$..4r<Symfony/Component/Security/Core/User/UserChecker.phpnu�[���PK��Z��6bYY>
<Symfony/Component/Security/Core/User/AdvancedUserInterface.phpnu�[���PK��Z����	�	6�<Symfony/Component/Security/Core/User/UserInterface.phpnu�[���PK��Z/!�=�"<Symfony/Component/Security/Core/User/InMemoryUserProvider.phpnu�[���PK��Z��//;]/<Symfony/Component/Security/Core/User/EquatableInterface.phpnu�[���PK��Zs�v�W	W	>�3<Symfony/Component/Security/Core/User/UserProviderInterface.phpnu�[���PK��Z��1G	G	-�=<Symfony/Component/Security/Core/User/User.phpnu�[���PK��Z'�za!!3`G<Symfony/Component/Security/Core/SecurityContext.phpnu�[���PK��Z��l�8�R<Symfony/Component/Security/Core/AuthenticationEvents.phpnu�[���PK��Zx��$ccPOW<Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.phpnu�[���PK��Z¬>
##R2f<Symfony/Component/Security/Core/Authentication/SimplePreAuthenticatorInterface.phpnu�[���PK��Z��W��O�h<Symfony/Component/Security/Core/Authentication/SimpleAuthenticatorInterface.phpnu�[���PK��Z>,�vvX%l<Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.phpnu�[���PK��Z�U#s<Symfony/Component/Security/Core/Authentication/Provider/DaoAuthenticationProvider.phpnu�[���PK��Z�b�yyVƂ<Symfony/Component/Security/Core/Authentication/Provider/UserAuthenticationProvider.phpnu�[���PK��Z�J�A��\ŗ<Symfony/Component/Security/Core/Authentication/Provider/RememberMeAuthenticationProvider.phpnu�[���PK��Z��X���[$�<Symfony/Component/Security/Core/Authentication/Provider/AnonymousAuthenticationProvider.phpnu�[���PK��Z��a�""[b�<Symfony/Component/Security/Core/Authentication/Provider/AuthenticationProviderInterface.phpnu�[���PK��Zun\�
�
b�<Symfony/Component/Security/Core/Authentication/Provider/PreAuthenticatedAuthenticationProvider.phpnu�[���PK��Z��r3WWW��<Symfony/Component/Security/Core/Authentication/AuthenticationTrustResolverInterface.phpnu�[���PK��Z�Zvm��St�<Symfony/Component/Security/Core/Authentication/RememberMe/InMemoryTokenProvider.phpnu�[���PK��Z���QZZV��<Symfony/Component/Security/Core/Authentication/RememberMe/PersistentTokenInterface.phpnu�[���PK��Z
�TO��Mx�<Symfony/Component/Security/Core/Authentication/RememberMe/PersistentToken.phpnu�[���PK��Z
C�f��T��<Symfony/Component/Security/Core/Authentication/RememberMe/TokenProviderInterface.phpnu�[���PK��ZJ-W;::S��<Symfony/Component/Security/Core/Authentication/SimpleFormAuthenticatorInterface.phpnu�[���PK��Z:�6��Nv�<Symfony/Component/Security/Core/Authentication/AuthenticationTrustResolver.phpnu�[���PK��Zf�	�Q��<Symfony/Component/Security/Core/Authentication/AuthenticationManagerInterface.phpnu�[���PK��Zγ�__N�<Symfony/Component/Security/Core/Authentication/Token/PreAuthenticatedToken.phpnu�[���PK��Z��4��F��<Symfony/Component/Security/Core/Authentication/Token/AbstractToken.phpnu�[���PK��Z�tC��G)=Symfony/Component/Security/Core/Authentication/Token/TokenInterface.phpnu�[���PK��Z{Z�--G�=Symfony/Component/Security/Core/Authentication/Token/AnonymousToken.phpnu�[���PK��Z�6��`
`
N&=Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.phpnu�[���PK��Z��w�	�	H*=Symfony/Component/Security/Core/Authentication/Token/RememberMeToken.phpnu�[���PK��Zm�|JJK�3=Symfony/Component/Security/Core/Resources/translations/security.sr_Cyrl.xlfnu�[���PK��Z&MЎ�
�
F�C=Symfony/Component/Security/Core/Resources/translations/security.es.xlfnu�[���PK��ZM-�@F�Q=Symfony/Component/Security/Core/Resources/translations/security.fa.xlfnu�[���PK��Zd�e��
�
F�a=Symfony/Component/Security/Core/Resources/translations/security.fr.xlfnu�[���PK��Z�)�
�
F�o=Symfony/Component/Security/Core/Resources/translations/security.ro.xlfnu�[���PK��Z�y��
�
F�}=Symfony/Component/Security/Core/Resources/translations/security.gl.xlfnu�[���PK��Z��u^
^
F�=Symfony/Component/Security/Core/Resources/translations/security.sv.xlfnu�[���PK��Z���ţ
�
F��=Symfony/Component/Security/Core/Resources/translations/security.ca.xlfnu�[���PK��Zo'�N�
�
Fϧ=Symfony/Component/Security/Core/Resources/translations/security.de.xlfnu�[���PK��Z.W�
�
F
�=Symfony/Component/Security/Core/Resources/translations/security.no.xlfnu�[���PK��Z��ق
�
F�=Symfony/Component/Security/Core/Resources/translations/security.sk.xlfnu�[���PK��Z�w=���F�=Symfony/Component/Security/Core/Resources/translations/security.ru.xlfnu�[���PK��ZUɎd
d
F3�=Symfony/Component/Security/Core/Resources/translations/security.sl.xlfnu�[���PK��Z���
�
F
�=Symfony/Component/Security/Core/Resources/translations/security.lb.xlfnu�[���PK��Z�#@�y
y
IW�=Symfony/Component/Security/Core/Resources/translations/security.pt_PT.xlfnu�[���PK��ZYW��g
g
KI>Symfony/Component/Security/Core/Resources/translations/security.sr_Latn.xlfnu�[���PK��Z�=���
�
I+>Symfony/Component/Security/Core/Resources/translations/security.pt_BR.xlfnu�[���PK��Z(���
�
F&(>Symfony/Component/Security/Core/Resources/translations/security.cs.xlfnu�[���PK��ZO�
�
F'6>Symfony/Component/Security/Core/Resources/translations/security.it.xlfnu�[���PK��ZTk�f��F+D>Symfony/Component/Security/Core/Resources/translations/security.ar.xlfnu�[���PK��Z��|H�
�
F[S>Symfony/Component/Security/Core/Resources/translations/security.hu.xlfnu�[���PK��Z�p�U�
�
Fa>Symfony/Component/Security/Core/Resources/translations/security.nl.xlfnu�[���PK��Z'���{
{
F�o>Symfony/Component/Security/Core/Resources/translations/security.tr.xlfnu�[���PK��ZU����F�}>Symfony/Component/Security/Core/Resources/translations/security.el.xlfnu�[���PK��Z.�X:
:
F�>Symfony/Component/Security/Core/Resources/translations/security.en.xlfnu�[���PK��Z�d
�
�
F��>Symfony/Component/Security/Core/Resources/translations/security.pl.xlfnu�[���PK��Z5�˙��F��>Symfony/Component/Security/Core/Resources/translations/security.ua.xlfnu�[���PK��Zz��
J
J
F��>Symfony/Component/Security/Core/Resources/translations/security.da.xlfnu�[���PK��Z��Eh��Dj�>Symfony/Component/Security/Core/Event/AuthenticationFailureEvent.phpnu�[���PK��Z+\�
//=��>Symfony/Component/Security/Core/Event/AuthenticationEvent.phpnu�[���PK��Z���(SSA,�>Symfony/Component/Security/Resources/translations/security.bg.xlfnu�[���PK��Zm�|JJF��>Symfony/Component/Security/Resources/translations/security.sr_Cyrl.xlfnu�[���PK��Z&MЎ�
�
A��>Symfony/Component/Security/Resources/translations/security.es.xlfnu�[���PK��ZM-�@A�>Symfony/Component/Security/Resources/translations/security.fa.xlfnu�[���PK��Z���An?Symfony/Component/Security/Resources/translations/security.vi.xlfnu�[���PK��Zd�e��
�
A�?Symfony/Component/Security/Resources/translations/security.fr.xlfnu�[���PK��Z�)�
�
A.)?Symfony/Component/Security/Resources/translations/security.ro.xlfnu�[���PK��Z�y��
�
A,7?Symfony/Component/Security/Resources/translations/security.gl.xlfnu�[���PK��Z��u^
^
A<E?Symfony/Component/Security/Resources/translations/security.sv.xlfnu�[���PK��Z���ţ
�
AS?Symfony/Component/Security/Resources/translations/security.ca.xlfnu�[���PK��Zo'�N�
�
Aa?Symfony/Component/Security/Resources/translations/security.de.xlfnu�[���PK��Z����
�
AXo?Symfony/Component/Security/Resources/translations/security.no.xlfnu�[���PK��Z�R�wD
D
AN}?Symfony/Component/Security/Resources/translations/security.id.xlfnu�[���PK��Z��ق
�
A�?Symfony/Component/Security/Resources/translations/security.sk.xlfnu�[���PK��Z�w=���A��?Symfony/Component/Security/Resources/translations/security.ru.xlfnu�[���PK��ZUɎd
d
A$�?Symfony/Component/Security/Resources/translations/security.sl.xlfnu�[���PK��Z]��W
W
A��?Symfony/Component/Security/Resources/translations/security.hr.xlfnu�[���PK��Z���
�
A��?Symfony/Component/Security/Resources/translations/security.lb.xlfnu�[���PK��Z�#@�y
y
D�?Symfony/Component/Security/Resources/translations/security.pt_PT.xlfnu�[���PK��ZYW��g
g
F��?Symfony/Component/Security/Resources/translations/security.sr_Latn.xlfnu�[���PK��Z���Y�
�
D��?Symfony/Component/Security/Resources/translations/security.pt_BR.xlfnu�[���PK��Z(���
�
A�?Symfony/Component/Security/Resources/translations/security.cs.xlfnu�[���PK��ZO�
�
A�
@Symfony/Component/Security/Resources/translations/security.it.xlfnu�[���PK��ZTk�f��A�@Symfony/Component/Security/Resources/translations/security.ar.xlfnu�[���PK��Z��|H�
�
A�'@Symfony/Component/Security/Resources/translations/security.hu.xlfnu�[���PK��Z�p�U�
�
A6@Symfony/Component/Security/Resources/translations/security.nl.xlfnu�[���PK��Z'���{
{
AID@Symfony/Component/Security/Resources/translations/security.tr.xlfnu�[���PK��ZU����A5R@Symfony/Component/Security/Resources/translations/security.el.xlfnu�[���PK��Z��Dt��D�b@Symfony/Component/Security/Resources/translations/security.zh_CN.xlfnu�[���PK��Z.�X:
:
A�o@Symfony/Component/Security/Resources/translations/security.en.xlfnu�[���PK��Z�d
�
�
A�}@Symfony/Component/Security/Resources/translations/security.pl.xlfnu�[���PK��Z�f488A��@Symfony/Component/Security/Resources/translations/security.ja.xlfnu�[���PK��Z5�˙��AC�@Symfony/Component/Security/Resources/translations/security.ua.xlfnu�[���PK��Z��J
J
A7�@Symfony/Component/Security/Resources/translations/security.da.xlfnu�[���PK��Z�@V��@�@Symfony/Component/Validator/ConstraintViolationListInterface.phpnu�[���PK��Zz��911::�@Symfony/Component/Validator/ObjectInitializerInterface.phpnu�[���PK��Z,�'��<��@Symfony/Component/Validator/ConstraintValidatorInterface.phpnu�[���PK��ZK��}}1��@Symfony/Component/Validator/DefaultTranslator.phpnu�[���PK��Z�����3��@Symfony/Component/Validator/ConstraintViolation.phpnu�[���PK��ZS�b'b'0��@Symfony/Component/Validator/ValidatorBuilder.phpnu�[���PK��Z�S�UU>�ASymfony/Component/Validator/GroupSequenceProviderInterface.phpnu�[���PK��Z�d�)xASymfony/Component/Validator/Validator.phpnu�[���PK��Z��&{{9�2ASymfony/Component/Validator/ValidatorBuilderInterface.phpnu�[���PK��Zo��SS*�HASymfony/Component/Validator/autoloader.phpnu�[���PK��Z����C0C09{JASymfony/Component/Validator/ExecutionContextInterface.phpnu�[���PK��Z}`���9'{ASymfony/Component/Validator/PropertyMetadataInterface.phpnu�[���PK��Z�޽/!/!0z�ASymfony/Component/Validator/ExecutionContext.phpnu�[���PK��Z+s���:	�ASymfony/Component/Validator/ConstraintValidatorFactory.phpnu�[���PK��Z�Sq�KK1l�ASymfony/Component/Validator/MetadataInterface.phpnu�[���PK��Z�R'<�ASymfony/Component/Validator/ConstraintViolationInterface.phpnu�[���PK��ZƭW��*��ASymfony/Component/Validator/Constraint.phpnu�[���PK��Z|����6l�ASymfony/Component/Validator/Mapping/GetterMetadata.phpnu�[���PK��Zr
���8��ASymfony/Component/Validator/Mapping/PropertyMetadata.phpnu�[���PK��Z�t�././5��ASymfony/Component/Validator/Mapping/ClassMetadata.phpnu�[���PK��Z��!"	"	7wBSymfony/Component/Validator/Mapping/ElementMetadata.phpnu�[���PK��Z�/�;aa6)BSymfony/Component/Validator/Mapping/MemberMetadata.phpnu�[���PK��Z+�d%%<�@BSymfony/Component/Validator/Mapping/Cache/CacheInterface.phpnu�[���PK��Z����6XEBSymfony/Component/Validator/Mapping/Cache/ApcCache.phpnu�[���PK��Zd#[N��<IJBSymfony/Component/Validator/Mapping/ClassMetadataFactory.phpnu�[���PK��Z��ʚ��9�WBSymfony/Component/Validator/Mapping/Loader/FileLoader.phpnu�[���PK��Zk�G+��=�[BSymfony/Component/Validator/Mapping/Loader/AbstractLoader.phpnu�[���PK��ZRᠯ��=dBSymfony/Component/Validator/Mapping/Loader/XmlFilesLoader.phpnu�[���PK��Z�?��>gBSymfony/Component/Validator/Mapping/Loader/YamlFilesLoader.phpnu�[���PK��Z�����:jBSymfony/Component/Validator/Mapping/Loader/LoaderChain.phpnu�[���PK��ZT�b��AAqBSymfony/Component/Validator/Mapping/Loader/StaticMethodLoader.phpnu�[���PK��Z�>�??>�wBSymfony/Component/Validator/Mapping/Loader/LoaderInterface.phpnu�[���PK��Z���*��:8zBSymfony/Component/Validator/Mapping/Loader/FilesLoader.phpnu�[���PK��ZTO��--c)�BSymfony/Component/Validator/Mapping/Loader/schema/dic/constraint-mapping/constraint-mapping-1.0.xsdnu�[���PK��Z;Q�F11<�BSymfony/Component/Validator/Mapping/Loader/XmlFileLoader.phpnu�[���PK��PK��Zh������..registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUri   URI of the namespace
     * @param bool   $multiline      whether to create a multiline tag where each
     *                               attribute gets written to a single line
     * @param string $indent         string used to indent attributes (_auto indents
     *                               attributes so they start at the same column)
     * @param string $linebreak      string used for linebreaks
     * @param bool   $sortAttributes Whether to sort the attributes or not
     *
     * @return string XML start element
     * @see    createEndElement(), createTag()
     */
    public static function createStartElement(
        $qname, $attributes = array(), $namespaceUri = null,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true
    ) {
        // if no attributes hav been set, use empty attributes
        if (!isset($attributes) || !is_array($attributes)) {
            $attributes = array();
        }

        if ($namespaceUri != null) {
            $parts = XML_Util::splitQualifiedName($qname);
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($qname)+2));
            }
        }

        if ($namespaceUri != null) {
            // is a namespace given
            if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
            } else {
                // define this Uri as the default namespace
                $attributes['xmlns'] = $namespaceUri;
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $attributes, $sortAttributes,
            $multiline, $indent, $linebreak
        );
        $element = sprintf('<%s%s>', $qname, $attList);
        return  $element;
    }

    /**
     * Create an end element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createEndElement('myNs:myTag');
     * </code>
     *
     * @param string $qname qualified tagname (including namespace)
     *
     * @return string XML end element
     * @see    createStartElement(), createTag()
     */
    public static function createEndElement($qname)
    {
        $element = sprintf('</%s>', $qname);
        return $element;
    }

    /**
     * Create an XML comment
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createComment('I am a comment');
     * </code>
     *
     * @param string $content content of the comment
     *
     * @return string XML comment
     */
    public static function createComment($content)
    {
        $comment = sprintf('<!-- %s -->', $content);
        return $comment;
    }

    /**
     * Create a CData section
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create a CData section
     * $tag = XML_Util::createCDataSection('I am content.');
     * </code>
     *
     * @param string $data data of the CData section
     *
     * @return string CData section with content
     */
    public static function createCDataSection($data)
    {
        return sprintf(
            '<![CDATA[%s]]>',
            preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data))
        );
    }

    /**
     * Split qualified name and return namespace and local part
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // split qualified tag
     * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
     * </code>
     * the returned array will contain two elements:
     * <pre>
     * array(
     *     'namespace' => 'xslt',
     *     'localPart' => 'stylesheet'
     * );
     * </pre>
     *
     * @param string $qname     qualified tag name
     * @param string $defaultNs default namespace (optional)
     *
     * @return array array containing namespace and local part
     */
    public static function splitQualifiedName($qname, $defaultNs = null)
    {
        if (strstr($qname, ':')) {
            $tmp = explode(':', $qname);
            return array(
                'namespace' => $tmp[0],
                'localPart' => $tmp[1]
            );
        }
        return array(
            'namespace' => $defaultNs,
            'localPart' => $qname
        );
    }

    /**
     * Check, whether string is valid XML name
     *
     * <p>XML names are used for tagname, attribute names and various
     * other, lesser known entities.</p>
     * <p>An XML name may only consist of alphanumeric characters,
     * dashes, undescores and periods, and has to start with a letter
     * or an underscore.</p>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // verify tag name
     * $result = XML_Util::isValidName('invalidTag?');
     * if (is_a($result, 'PEAR_Error')) {
     *    print 'Invalid XML name: ' . $result->getMessage();
     * }
     * </code>
     *
     * @param string $string string that should be checked
     *
     * @return mixed true, if string is a valid XML name, PEAR error otherwise
     *
     * @todo support for other charsets
     * @todo PEAR CS - unable to avoid 85-char limit on second preg_match
     */
    public static function isValidName($string)
    {
        // check for invalid chars
        if (!is_string($string) || !strlen($string) || !preg_match('/^[[:alpha:]_]\\z/', $string[0])) {
            return XML_Util::raiseError(
                'XML names may only start with letter or underscore',
                XML_UTIL_ERROR_INVALID_START
            );
        }

        // check for invalid chars
        $match = preg_match(
            '/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?'
            . '[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/',
            $string
        );
        if (!$match) {
            return XML_Util::raiseError(
                'XML names may only contain alphanumeric '
                . 'chars, period, hyphen, colon and underscores',
                XML_UTIL_ERROR_INVALID_CHARS
            );
        }
        // XML name is valid
        return true;
    }

    /**
     * Replacement for XML_Util::raiseError
     *
     * Avoids the necessity to always require
     * PEAR.php
     *
     * @param string $msg  error message
     * @param int    $code error code
     *
     * @return PEAR_Error
     * @todo   PEAR CS - should this use include_once instead?
     */
    public static function raiseError($msg, $code)
    {
        include_once 'PEAR.php';
        return PEAR::raiseError($msg, $code);
    }
}
?>
PK��Z#F��:�:pearcmd.phpnu�[���<?php
/**
 * PEAR, the PHP Extension and Application Repository
 *
 * Command line interface
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Stig Bakken <ssb@php.net>
 * @author    Tomas V.V.Cox <cox@idecnet.com>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 */

@ob_end_clean();
if (!defined('PEAR_RUNTYPE')) {
    // this is defined in peclcmd.php as 'pecl'
    define('PEAR_RUNTYPE', 'pear');
}
define('PEAR_IGNORE_BACKTRACE', 1);
/**
 * @nodep Gtk
 */
//the space is needed for windows include paths with trailing backslash
// http://pear.php.net/bugs/bug.php?id=19482
if ('/opt/alt/php74/usr/share/pear ' != '@'.'include_path'.'@ ') {
    ini_set('include_path', trim('/opt/alt/php74/usr/share/pear '). PATH_SEPARATOR .  get_include_path());
    $raw = false;
} else {
    // this is a raw, uninstalled pear, either a cvs checkout, or php distro
    ini_set('include_path', dirname(__DIR__) . PATH_SEPARATOR . get_include_path());
    $raw = true;
}
@ini_set('allow_url_fopen', true);
@set_time_limit(0);
ob_implicit_flush(true);
@ini_set('track_errors', true);
@ini_set('html_errors', false);
$_PEAR_PHPDIR = '#$%^&*';
set_error_handler('error_handler');

$pear_package_version = "1.10.16";

require_once 'PEAR.php';
require_once 'PEAR/Frontend.php';
require_once 'PEAR/Config.php';
require_once 'PEAR/Command.php';
require_once 'Console/Getopt.php';


PEAR_Command::setFrontendType('CLI');
$all_commands = PEAR_Command::getCommands();

$argv = Console_Getopt::readPHPArgv();
// fix CGI sapi oddity - the -- in pear.bat/pear is not removed
if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
    unset($argv[1]);
    $argv = array_values($argv);
}
$progname = PEAR_RUNTYPE;
array_shift($argv);
$options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV");
if (PEAR::isError($options)) {
    usage($options);
}

$opts = $options[0];

$fetype = 'CLI';
if ($progname == 'gpear' || $progname == 'pear-gtk') {
    $fetype = 'Gtk2';
} else {
    foreach ($opts as $opt) {
        if ($opt[0] == 'G') {
            $fetype = 'Gtk2';
        }
    }
}

$pear_user_config = '';
$pear_system_config = '';
$store_user_config = false;
$store_system_config = false;
$verbose = 1;

foreach ($opts as $opt) {
    switch ($opt[0]) {
    case 'c':
        $pear_user_config = $opt[1];
        break;
    case 'C':
        $pear_system_config = $opt[1];
        break;
    }
}

PEAR_Command::setFrontendType($fetype);
$ui = &PEAR_Command::getFrontendObject();
$config = &PEAR_Config::singleton($pear_user_config, $pear_system_config);

if (PEAR::isError($config)) {
    $_file = '';
    if ($pear_user_config !== false) {
        $_file .= $pear_user_config;
    }
    if ($pear_system_config !== false) {
        $_file .= '/' . $pear_system_config;
    }
    if ($_file == '/') {
        $_file = 'The default config file';
    }
    $config->getMessage();
    $ui->outputData("ERROR: $_file is not a valid config file or is corrupted.");
    // We stop, we have no idea where we are :)
    exit(1);
}

// this is used in the error handler to retrieve a relative path
$_PEAR_PHPDIR = $config->get('php_dir');
$ui->setConfig($config);
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError"));

$verbose = $config->get("verbose");
$cmdopts = array();

if ($raw) {
    if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) {
        $found = false;
        foreach ($opts as $opt) {
            if ($opt[0] == 'd' || $opt[0] == 'D') {
                // the user knows what they are doing, and are setting config values
                $found = true;
            }
        }
        if (!$found) {
            // no prior runs, try to install PEAR
            $parent = dirname(__FILE__);
            if (strpos($parent, 'scripts')) {
                $grandparent = dirname($parent);
                $packagexml = $grandparent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $grandparent;
            } else {
                $packagexml = $parent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $parent;
            }
            if (file_exists($packagexml)) {
                $options[1] = array(
                    'install',
                    $packagexml
                );
                $config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php');
                $config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data');
                $config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs');
                $config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests');
                $config->set(
                    'ext_dir',
                    $pearbase . DIRECTORY_SEPARATOR . 'extensions'
                );
                $config->set('bin_dir', $pearbase);
                $config->mergeConfigFile($pearbase . 'pear.ini', false);
                $config->store();
                $config->set('auto_discover', 1);
            }
        }
    }
}
foreach ($opts as $opt) {
    $param = !empty($opt[1]) ? $opt[1] : true;
    switch ($opt[0]) {
    case 'd':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected -d config_value=value, ' .
                'received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'user');
        break;
    case 'D':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'system');
        break;
    case 's':
        $store_user_config = true;
        break;
    case 'S':
        $store_system_config = true;
        break;
    case 'u':
        $config->remove($param, 'user');
        break;
    case 'v':
        $config->set('verbose', $config->get('verbose') + 1);
        break;
    case 'q':
        $config->set('verbose', $config->get('verbose') - 1);
        break;
    case 'V':
        usage(null, 'version');
    case 'c':
    case 'C':
        break;
    default:
        // all non pear params goes to the command
        $cmdopts[$opt[0]] = $param;
        break;
    }
}

if ($store_system_config) {
    $config->store('system');
}

if ($store_user_config) {
    $config->store('user');
}

$command = (isset($options[1][0])) ? $options[1][0] : null;
if (empty($command) && ($store_user_config || $store_system_config)) {
    exit;
}

if ($fetype == 'Gtk2') {
    if (!$config->validConfiguration()) {
        PEAR::raiseError(
            "CRITICAL ERROR: no existing valid configuration files found in " .
            "files '$pear_user_config' or '$pear_system_config', " .
            "please copy an existing configuration file to one of these " .
            "locations, or use the -c and -s options to create one"
        );
    }
    Gtk::main();
} else {
    do {
        if ($command == 'help') {
            usage(null, isset($options[1][1]) ? $options[1][1] : null);
        }

        if (!$config->validConfiguration()) {
            PEAR::raiseError(
                "CRITICAL ERROR: no existing valid configuration files found " .
                "in files '$pear_user_config' or '$pear_system_config', " .
                "please copy an existing configuration file to one of " .
                "these locations, or use the -c and -s options to create one"
            );
        }

        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        $cmd = PEAR_Command::factory($command, $config);
        PEAR::popErrorHandling();
        if (PEAR::isError($cmd)) {
            usage(null, isset($options[1][0]) ? $options[1][0] : null);
        }

        $short_args = $long_args = null;
        PEAR_Command::getGetoptArgs($command, $short_args, $long_args);
        array_shift($options[1]);
        $tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args);

        if (PEAR::isError($tmp)) {
            break;
        }

        list($tmpopt, $params) = $tmp;
        $opts = array();
        foreach ($tmpopt as $foo => $tmp2) {
            list($opt, $value) = $tmp2;
            if ($value === null) {
                $value = true; // options without args
            }

            if (strlen($opt) == 1) {
                $cmdoptions = $cmd->getOptions($command);
                foreach ($cmdoptions as $o => $d) {
                    if (isset($d['shortopt']) && $d['shortopt'] == $opt) {
                        $opts[$o] = $value;
                    }
                }
            } else {
                if (substr($opt, 0, 2) == '--') {
                    $opts[substr($opt, 2)] = $value;
                }
            }
        }

        $ok = $cmd->run($command, $opts, $params);
        if ($ok === false) {
            PEAR::raiseError("unknown command `$command'");
        }

        if (PEAR::isError($ok)) {
            PEAR::setErrorHandling(
                PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")
            );
            PEAR::raiseError($ok);
        }
    } while (false);
}

// {{{ usage()

/**
 * Display usage information
 *
 * @param mixed $error       Optional error message
 * @param mixed $helpsubject Optional subject/command to display help for
 *
 * @return void
 */
function usage($error = null, $helpsubject = null)
{
    global $progname, $all_commands;
    $stdout = fopen('php://stdout', 'w');
    if (PEAR::isError($error)) {
        fputs($stdout, $error->getMessage() . "\n");
    } elseif ($error !== null) {
        fputs($stdout, "$error\n");
    }

    if ($helpsubject != null) {
        $put = cmdHelp($helpsubject);
    } else {
        $put = "Commands:\n";
        $maxlen = max(array_map("strlen", $all_commands));
        $formatstr = "%-{$maxlen}s  %s\n";
        ksort($all_commands);
        foreach ($all_commands as $cmd => $class) {
            $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd));
        }
        $put .=
            "Usage: $progname [options] command [command-options] <parameters>\n".
            "Type \"$progname help options\" to list all options.\n".
            "Type \"$progname help shortcuts\" to list all command shortcuts.\n".
            "Type \"$progname help version\" or ".
            "\"$progname version\" to list version information.\n".
            "Type \"$progname help <command>\" to get the help ".
            "for the specified command.";
    }
    fputs($stdout, "$put\n");
    fclose($stdout);

    if ($error === null) {
        exit(0);
    }
    exit(1);
}

/**
 * Return help string for specified command
 *
 * @param string $command Command to return help for
 *
 * @return void
 */
function cmdHelp($command)
{
    global $progname, $all_commands, $config;
    if ($command == "options") {
        return
        "Options:\n".
        "     -v         increase verbosity level (default 1)\n".
        "     -q         be quiet, decrease verbosity level\n".
        "     -c file    find user configuration in `file'\n".
        "     -C file    find system configuration in `file'\n".
        "     -d foo=bar set user config variable `foo' to `bar'\n".
        "     -D foo=bar set system config variable `foo' to `bar'\n".
        "     -G         start in graphical (Gtk) mode\n".
        "     -s         store user configuration\n".
        "     -S         store system configuration\n".
        "     -u foo     unset `foo' in the user configuration\n".
        "     -h, -?     display help/usage (this message)\n".
        "     -V         version information\n";
    } elseif ($command == "shortcuts") {
        $sc = PEAR_Command::getShortcuts();
        $ret = "Shortcuts:\n";
        foreach ($sc as $s => $c) {
            $ret .= sprintf("     %-8s %s\n", $s, $c);
        }
        return $ret;

    } elseif ($command == "version") {
        return "PEAR Version: ".$GLOBALS['pear_package_version'].
               "\nPHP Version: ".phpversion().
               "\nZend Engine Version: ".zend_version().
               "\nRunning on: ".php_uname();

    } elseif ($help = PEAR_Command::getHelp($command)) {
        if (is_string($help)) {
            return "$progname $command [options] $help\n";
        }

        if ($help[1] === null) {
            return "$progname $command $help[0]";
        }

        return "$progname $command [options] $help[0]\n$help[1]";
    }

    return "Command '$command' is not valid, try '$progname help'";
}

// }}}

/**
 * error_handler
 *
 * @param mixed $errno  Error number
 * @param mixed $errmsg Message
 * @param mixed $file   Filename
 * @param mixed $line   Line number
 *
 * @access public
 * @return boolean
 */
function error_handler($errno, $errmsg, $file, $line)
{
    if ((!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) && ($errno & E_STRICT)) {
        return; // E_STRICT
    }
    if ($errno & E_DEPRECATED) {
        return; // E_DEPRECATED
    }
    if (!(error_reporting() & $errno) &&
        isset($GLOBALS['config']) &&
        $GLOBALS['config']->get('verbose') < 4
    ) {
        return false; // @silenced error, show all if debug is high enough
    }
    $errortype = array (
        E_DEPRECATED  => 'Deprecated Warning',
        E_ERROR   =>  "Error",
        E_WARNING   =>  "Warning",
        E_PARSE   =>  "Parsing Error",
        E_NOTICE   =>  "Notice",
        E_CORE_ERROR  =>  "Core Error",
        E_CORE_WARNING  =>  "Core Warning",
        E_COMPILE_ERROR  =>  "Compile Error",
        E_COMPILE_WARNING =>  "Compile Warning",
        E_USER_ERROR =>  "User Error",
        E_USER_WARNING =>  "User Warning",
        E_USER_NOTICE =>  "User Notice"
    );
    if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) {
        $errortype[E_STRICT] = 'Strict Warning';
    }
    $prefix = $errortype[$errno];
    global $_PEAR_PHPDIR;
    if (stristr($file, $_PEAR_PHPDIR)) {
        $file = substr($file, strlen($_PEAR_PHPDIR) + 1);
    } else {
        $file = basename($file);
    }
    print "\n$prefix: $errmsg in $file on line $line\n";
    return false;
}


/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * indent-tabs-mode: nil
 * mode: php
 * End:
 */
// vim600:syn=php
PK��Z�0$�-- .pkgxml/Pear_File_MARC-1.4.1.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.10.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
 <name>File_MARC</name>
 <channel>pear.php.net</channel>
 <summary>Parse, modify, and create MARC records</summary>
 <description>The standard for machine-readable cataloging (MARC) records is documented at http://loc.gov/marc/. This package enables you to read existing MARC records from a file, string, or (using the YAZ extension), from a Z39.50 source. You can also use this package to create new MARC records.

This package is based on the PHP MARC package, originally called &quot;php-marc&quot;, that is part of the Emilda Project (http://www.emilda.org).  Christoffer Landtman generously agreed to make the &quot;php-marc&quot; code available under the GNU LGPL so it could be used as the basis of this PEAR package.</description>
 <lead>
  <name>Dan Scott</name>
  <user>dbs</user>
  <email>dbs@php.net</email>
  <active>yes</active>
 </lead>
 <date>2019-11-13</date>
 <time>17:33:33</time>
 <version>
  <release>1.4.1</release>
  <api>1.4.0</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license uri="http://www.gnu.org/copyleft/lesser.html">GNU Lesser General Public License</license>
 <notes>
1.4.1
  * Reintroduce include_path to composer.json
 </notes>
 <contents>
  <dir baseinstalldir="File" name="/">
   <file baseinstalldir="/" md5sum="ffe2590635f404af055fe731da105939" name="File/MARC/Lint/CodeData.php" role="php" />
   <file baseinstalldir="/" md5sum="a3b9e1c817e67f59add05593500d463e" name="File/MARC/Control_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="acba4463f8e40d6ee4e7ba1f2dc53123" name="File/MARC/Data_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="378f483ec1fd161cd9dfb9b05db58d66" name="File/MARC/Exception.php" role="php" />
   <file baseinstalldir="/" md5sum="a9ba69030cbf4847292b9975e9d922c6" name="File/MARC/Field.php" role="php" />
   <file baseinstalldir="/" md5sum="c37351c7c80927ce6bb1e662510f9183" name="File/MARC/Lint.php" role="php" />
   <file baseinstalldir="/" md5sum="c5ac39e3d25eb0108b9dd5ad8466c821" name="File/MARC/List.php" role="php" />
   <file baseinstalldir="/" md5sum="7af6ce78cde4bb246e4e96709e90d2c0" name="File/MARC/Record.php" role="php" />
   <file baseinstalldir="/" md5sum="df5f97139685f0ad04e47fdbb67e3968" name="File/MARC/Subfield.php" role="php" />
   <file baseinstalldir="/" md5sum="6e102262dfd5d65d8d5a6221dfc74edd" name="File/MARC.php" role="php" />
   <file baseinstalldir="/" md5sum="8b64040d2d18ac4b994595a148266a66" name="File/MARCBASE.php" role="php" />
   <file baseinstalldir="/" md5sum="f5a17a60d34e84e2ee7ca1e5c5c6c620" name="File/MARCXML.php" role="php" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="examples/example.mrc" role="doc" />
   <file baseinstalldir="File" md5sum="1aea40df9f1c2e32f8e065fe8da0a3b5" name="examples/marc_yaz.php" role="doc" />
   <file baseinstalldir="File" md5sum="70ae317e0890d5896e3ffccdd293369a" name="examples/read.php" role="doc" />
   <file baseinstalldir="File" md5sum="54efb9d920ac775bfc847a83a2dec73a" name="examples/subfields.php" role="doc" />
   <file baseinstalldir="File" md5sum="14297da35b510c496cd1f328cf3bb301" name="tests/bad_example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="0dd4c6dbad6e8608d0ebf9d24425955d" name="tests/bad_example.xml" role="test" />
   <file baseinstalldir="File" md5sum="216a6f9d53f6d3d8e22d81fdc10f4bc1" name="tests/camel.mrc" role="test" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="tests/example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="9455aec3371f79cf7d31281fd03f5171" name="tests/marc_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="577e2f5f89fd48cf1a3576a29d2958f8" name="tests/marc_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a6a586354b9a06c880c2a7470dd828d7" name="tests/marc_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1c7e2fc5572a0f9362a771c260a1fe3" name="tests/marc_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="84f85ac7f8a2532e4e90ccde7764556a" name="tests/marc_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="889e5e906a97de7a0e94b0c5f30e70e7" name="tests/marc_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="be823dc8a8efb408de06371ab802efcc" name="tests/marc_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="af44490aafea44e5120f881cb81cdad9" name="tests/marc_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ac9f2a7aeb24900a11f5102744179ae3" name="tests/marc_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5e43eb5cddbb4f2bd0d6405cd95b80aa" name="tests/marc_010.phpt" role="test" />
   <file baseinstalldir="File" md5sum="2e1cd8509c0bf04ec77fc0f51375f611" name="tests/marc_011.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bc49ca48623102c8ac07679fa77a3dd9" name="tests/marc_012.phpt" role="test" />
   <file baseinstalldir="File" md5sum="245a3b20e0da1973535503e28efd1d3a" name="tests/marc_013.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ce69aa734856dd40d60d30c77bdef53a" name="tests/marc_014.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7b61cdd31035e60682fa92c5d519d997" name="tests/marc_015.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7f4f597fe1adaa3507eb87fc4875dbd2" name="tests/marc_016.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4262efd5fcacbd7503323681f4552430" name="tests/marc_017.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ee1623d7bda54ba4f741b2319b158f82" name="tests/marc_018.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8006c03fbab0f04377342086fafd3982" name="tests/marc_019.phpt" role="test" />
   <file baseinstalldir="File" md5sum="f5ae5b25e0ac1104314433d9e5b1f7fe" name="tests/marc_020.phpt" role="test" />
   <file baseinstalldir="File" md5sum="94d8f99e86585671a1b2d3043aeb6360" name="tests/marc_021.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bb891a890effe0e77e1759043f4846d8" name="tests/marc_022.phpt" role="test" />
   <file baseinstalldir="File" md5sum="faf77dcb5cdd002c09169a14bfded65e" name="tests/marc_023.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0e6c4a23f5da7df64fdd4b3b1149bbee" name="tests/marc_16783.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4ea8b3520beda378db15960f1c50493a" name="tests/marc_field_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="743850ef61df69c4340be44a03bccb5a" name="tests/marc_field_002.phpt" role="tPK��Z�������2.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUri   URI of the namespace
     * @param bool   $multiline      whether to create a multiline tag where each
     *                               attribute gets written to a single line
     * @param string $indent         string used to indent attributes (_auto indents
     *                               attributes so they start at the same column)
     * @param string $linebreak      string used for linebreaks
     * @param bool   $sortAttributes Whether to sort the attributes or not
     *
     * @return string XML start element
     * @see    createEndElement(), createTag()
     */
    public static function createStartElement(
        $qname, $attributes = array(), $namespaceUri = null,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true
    ) {
        // if no attributes hav been set, use empty attributes
        if (!isset($attributes) || !is_array($attributes)) {
            $attributes = array();
        }

        if ($namespaceUri != null) {
            $parts = XML_Util::splitQualifiedName($qname);
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($qname)+2));
            }
        }

        if ($namespaceUri != null) {
            // is a namespace given
            if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
            } else {
                // define this Uri as the default namespace
                $attributes['xmlns'] = $namespaceUri;
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $attributes, $sortAttributes,
            $multiline, $indent, $linebreak
        );
        $element = sprintf('<%s%s>', $qname, $attList);
        return  $element;
    }

    /**
     * Create an end element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createEndElement('myNs:myTag');
     * </code>
     *
     * @param string $qname qualified tagname (including namespace)
     *
     * @return string XML end element
     * @see    createStartElement(), createTag()
     */
    public static function createEndElement($qname)
    {
        $element = sprintf('</%s>', $qname);
        return $element;
    }

    /**
     * Create an XML comment
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createComment('I am a comment');
     * </code>
     *
     * @param string $content content of the comment
     *
     * @return string XML comment
     */
    public static function createComment($content)
    {
        $comment = sprintf('<!-- %s -->', $content);
        return $comment;
    }

    /**
     * Create a CData section
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create a CData section
     * $tag = XML_Util::createCDataSection('I am content.');
     * </code>
     *
     * @param string $data data of the CData section
     *
     * @return string CData section with content
     */
    public static function createCDataSection($data)
    {
        return sprintf(
            '<![CDATA[%s]]>',
            preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data))
        );
    }

    /**
     * Split qualified name and return namespace and local part
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // split qualified tag
     * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
     * </code>
     * the returned array will contain two elements:
     * <pre>
     * array(
     *     'namespace' => 'xslt',
     *     'localPart' => 'stylesheet'
     * );
     * </pre>
     *
     * @param string $qname     qualified tag name
     * @param string $defaultNs default namespace (optional)
     *
     * @return array array containing namespace and local part
     */
    public static function splitQualifiedName($qname, $defaultNs = null)
    {
        if (strstr($qname, ':')) {
            $tmp = explode(':', $qname);
            return array(
                'namespace' => $tmp[0],
                'localPart' => $tmp[1]
            );
        }
        return array(
            'namespace' => $defaultNs,
            'localPart' => $qname
        );
    }

    /**
     * Check, whether string is valid XML name
     *
     * <p>XML names are used for tagname, attribute names and various
     * other, lesser known entities.</p>
     * <p>An XML name may only consist of alphanumeric characters,
     * dashes, undescores and periods, and has to start with a letter
     * or an underscore.</p>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // verify tag name
     * $result = XML_Util::isValidName('invalidTag?');
     * if (is_a($result, 'PEAR_Error')) {
     *    print 'Invalid XML name: ' . $result->getMessage();
     * }
     * </code>
     *
     * @param string $string string that should be checked
     *
     * @return mixed true, if string is a valid XML name, PEAR error otherwise
     *
     * @todo support for other charsets
     * @todo PEAR CS - unable to avoid 85-char limit on second preg_match
     */
    public static function isValidName($string)
    {
        // check for invalid chars
        if (!is_string($string) || !strlen($string) || !preg_match('/^[[:alpha:]_]\\z/', $string[0])) {
            return XML_Util::raiseError(
                'XML names may only start with letter or underscore',
                XML_UTIL_ERROR_INVALID_START
            );
        }

        // check for invalid chars
        $match = preg_match(
            '/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?'
            . '[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/',
            $string
        );
        if (!$match) {
            return XML_Util::raiseError(
                'XML names may only contain alphanumeric '
                . 'chars, period, hyphen, colon and underscores',
                XML_UTIL_ERROR_INVALID_CHARS
            );
        }
        // XML name is valid
        return true;
    }

    /**
     * Replacement for XML_Util::raiseError
     *
     * Avoids the necessity to always require
     * PEAR.php
     *
     * @param string $msg  error message
     * @param int    $code error code
     *
     * @return PEAR_Error
     * @todo   PEAR CS - should this use include_once instead?
     */
    public static function raiseError($msg, $code)
    {
        include_once 'PEAR.php';
        return PEAR::raiseError($msg, $code);
    }
}
?>
PK��Z#F��:�:pearcmd.phpnu�[���<?php
/**
 * PEAR, the PHP Extension and Application Repository
 *
 * Command line interface
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Stig Bakken <ssb@php.net>
 * @author    Tomas V.V.Cox <cox@idecnet.com>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 */

@ob_end_clean();
if (!defined('PEAR_RUNTYPE')) {
    // this is defined in peclcmd.php as 'pecl'
    define('PEAR_RUNTYPE', 'pear');
}
define('PEAR_IGNORE_BACKTRACE', 1);
/**
 * @nodep Gtk
 */
//the space is needed for windows include paths with trailing backslash
// http://pear.php.net/bugs/bug.php?id=19482
if ('/opt/alt/php74/usr/share/pear ' != '@'.'include_path'.'@ ') {
    ini_set('include_path', trim('/opt/alt/php74/usr/share/pear '). PATH_SEPARATOR .  get_include_path());
    $raw = false;
} else {
    // this is a raw, uninstalled pear, either a cvs checkout, or php distro
    ini_set('include_path', dirname(__DIR__) . PATH_SEPARATOR . get_include_path());
    $raw = true;
}
@ini_set('allow_url_fopen', true);
@set_time_limit(0);
ob_implicit_flush(true);
@ini_set('track_errors', true);
@ini_set('html_errors', false);
$_PEAR_PHPDIR = '#$%^&*';
set_error_handler('error_handler');

$pear_package_version = "1.10.16";

require_once 'PEAR.php';
require_once 'PEAR/Frontend.php';
require_once 'PEAR/Config.php';
require_once 'PEAR/Command.php';
require_once 'Console/Getopt.php';


PEAR_Command::setFrontendType('CLI');
$all_commands = PEAR_Command::getCommands();

$argv = Console_Getopt::readPHPArgv();
// fix CGI sapi oddity - the -- in pear.bat/pear is not removed
if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
    unset($argv[1]);
    $argv = array_values($argv);
}
$progname = PEAR_RUNTYPE;
array_shift($argv);
$options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV");
if (PEAR::isError($options)) {
    usage($options);
}

$opts = $options[0];

$fetype = 'CLI';
if ($progname == 'gpear' || $progname == 'pear-gtk') {
    $fetype = 'Gtk2';
} else {
    foreach ($opts as $opt) {
        if ($opt[0] == 'G') {
            $fetype = 'Gtk2';
        }
    }
}

$pear_user_config = '';
$pear_system_config = '';
$store_user_config = false;
$store_system_config = false;
$verbose = 1;

foreach ($opts as $opt) {
    switch ($opt[0]) {
    case 'c':
        $pear_user_config = $opt[1];
        break;
    case 'C':
        $pear_system_config = $opt[1];
        break;
    }
}

PEAR_Command::setFrontendType($fetype);
$ui = &PEAR_Command::getFrontendObject();
$config = &PEAR_Config::singleton($pear_user_config, $pear_system_config);

if (PEAR::isError($config)) {
    $_file = '';
    if ($pear_user_config !== false) {
        $_file .= $pear_user_config;
    }
    if ($pear_system_config !== false) {
        $_file .= '/' . $pear_system_config;
    }
    if ($_file == '/') {
        $_file = 'The default config file';
    }
    $config->getMessage();
    $ui->outputData("ERROR: $_file is not a valid config file or is corrupted.");
    // We stop, we have no idea where we are :)
    exit(1);
}

// this is used in the error handler to retrieve a relative path
$_PEAR_PHPDIR = $config->get('php_dir');
$ui->setConfig($config);
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError"));

$verbose = $config->get("verbose");
$cmdopts = array();

if ($raw) {
    if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) {
        $found = false;
        foreach ($opts as $opt) {
            if ($opt[0] == 'd' || $opt[0] == 'D') {
                // the user knows what they are doing, and are setting config values
                $found = true;
            }
        }
        if (!$found) {
            // no prior runs, try to install PEAR
            $parent = dirname(__FILE__);
            if (strpos($parent, 'scripts')) {
                $grandparent = dirname($parent);
                $packagexml = $grandparent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $grandparent;
            } else {
                $packagexml = $parent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $parent;
            }
            if (file_exists($packagexml)) {
                $options[1] = array(
                    'install',
                    $packagexml
                );
                $config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php');
                $config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data');
                $config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs');
                $config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests');
                $config->set(
                    'ext_dir',
                    $pearbase . DIRECTORY_SEPARATOR . 'extensions'
                );
                $config->set('bin_dir', $pearbase);
                $config->mergeConfigFile($pearbase . 'pear.ini', false);
                $config->store();
                $config->set('auto_discover', 1);
            }
        }
    }
}
foreach ($opts as $opt) {
    $param = !empty($opt[1]) ? $opt[1] : true;
    switch ($opt[0]) {
    case 'd':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected -d config_value=value, ' .
                'received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'user');
        break;
    case 'D':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'system');
        break;
    case 's':
        $store_user_config = true;
        break;
    case 'S':
        $store_system_config = true;
        break;
    case 'u':
        $config->remove($param, 'user');
        break;
    case 'v':
        $config->set('verbose', $config->get('verbose') + 1);
        break;
    case 'q':
        $config->set('verbose', $config->get('verbose') - 1);
        break;
    case 'V':
        usage(null, 'version');
    case 'c':
    case 'C':
        break;
    default:
        // all non pear params goes to the command
        $cmdopts[$opt[0]] = $param;
        break;
    }
}

if ($store_system_config) {
    $config->store('system');
}

if ($store_user_config) {
    $config->store('user');
}

$command = (isset($options[1][0])) ? $options[1][0] : null;
if (empty($command) && ($store_user_config || $store_system_config)) {
    exit;
}

if ($fetype == 'Gtk2') {
    if (!$config->validConfiguration()) {
        PEAR::raiseError(
            "CRITICAL ERROR: no existing valid configuration files found in " .
            "files '$pear_user_config' or '$pear_system_config', " .
            "please copy an existing configuration file to one of these " .
            "locations, or use the -c and -s options to create one"
        );
    }
    Gtk::main();
} else {
    do {
        if ($command == 'help') {
            usage(null, isset($options[1][1]) ? $options[1][1] : null);
        }

        if (!$config->validConfiguration()) {
            PEAR::raiseError(
                "CRITICAL ERROR: no existing valid configuration files found " .
                "in files '$pear_user_config' or '$pear_system_config', " .
                "please copy an existing configuration file to one of " .
                "these locations, or use the -c and -s options to create one"
            );
        }

        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        $cmd = PEAR_Command::factory($command, $config);
        PEAR::popErrorHandling();
        if (PEAR::isError($cmd)) {
            usage(null, isset($options[1][0]) ? $options[1][0] : null);
        }

        $short_args = $long_args = null;
        PEAR_Command::getGetoptArgs($command, $short_args, $long_args);
        array_shift($options[1]);
        $tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args);

        if (PEAR::isError($tmp)) {
            break;
        }

        list($tmpopt, $params) = $tmp;
        $opts = array();
        foreach ($tmpopt as $foo => $tmp2) {
            list($opt, $value) = $tmp2;
            if ($value === null) {
                $value = true; // options without args
            }

            if (strlen($opt) == 1) {
                $cmdoptions = $cmd->getOptions($command);
                foreach ($cmdoptions as $o => $d) {
                    if (isset($d['shortopt']) && $d['shortopt'] == $opt) {
                        $opts[$o] = $value;
                    }
                }
            } else {
                if (substr($opt, 0, 2) == '--') {
                    $opts[substr($opt, 2)] = $value;
                }
            }
        }

        $ok = $cmd->run($command, $opts, $params);
        if ($ok === false) {
            PEAR::raiseError("unknown command `$command'");
        }

        if (PEAR::isError($ok)) {
            PEAR::setErrorHandling(
                PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")
            );
            PEAR::raiseError($ok);
        }
    } while (false);
}

// {{{ usage()

/**
 * Display usage information
 *
 * @param mixed $error       Optional error message
 * @param mixed $helpsubject Optional subject/command to display help for
 *
 * @return void
 */
function usage($error = null, $helpsubject = null)
{
    global $progname, $all_commands;
    $stdout = fopen('php://stdout', 'w');
    if (PEAR::isError($error)) {
        fputs($stdout, $error->getMessage() . "\n");
    } elseif ($error !== null) {
        fputs($stdout, "$error\n");
    }

    if ($helpsubject != null) {
        $put = cmdHelp($helpsubject);
    } else {
        $put = "Commands:\n";
        $maxlen = max(array_map("strlen", $all_commands));
        $formatstr = "%-{$maxlen}s  %s\n";
        ksort($all_commands);
        foreach ($all_commands as $cmd => $class) {
            $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd));
        }
        $put .=
            "Usage: $progname [options] command [command-options] <parameters>\n".
            "Type \"$progname help options\" to list all options.\n".
            "Type \"$progname help shortcuts\" to list all command shortcuts.\n".
            "Type \"$progname help version\" or ".
            "\"$progname version\" to list version information.\n".
            "Type \"$progname help <command>\" to get the help ".
            "for the specified command.";
    }
    fputs($stdout, "$put\n");
    fclose($stdout);

    if ($error === null) {
        exit(0);
    }
    exit(1);
}

/**
 * Return help string for specified command
 *
 * @param string $command Command to return help for
 *
 * @return void
 */
function cmdHelp($command)
{
    global $progname, $all_commands, $config;
    if ($command == "options") {
        return
        "Options:\n".
        "     -v         increase verbosity level (default 1)\n".
        "     -q         be quiet, decrease verbosity level\n".
        "     -c file    find user configuration in `file'\n".
        "     -C file    find system configuration in `file'\n".
        "     -d foo=bar set user config variable `foo' to `bar'\n".
        "     -D foo=bar set system config variable `foo' to `bar'\n".
        "     -G         start in graphical (Gtk) mode\n".
        "     -s         store user configuration\n".
        "     -S         store system configuration\n".
        "     -u foo     unset `foo' in the user configuration\n".
        "     -h, -?     display help/usage (this message)\n".
        "     -V         version information\n";
    } elseif ($command == "shortcuts") {
        $sc = PEAR_Command::getShortcuts();
        $ret = "Shortcuts:\n";
        foreach ($sc as $s => $c) {
            $ret .= sprintf("     %-8s %s\n", $s, $c);
        }
        return $ret;

    } elseif ($command == "version") {
        return "PEAR Version: ".$GLOBALS['pear_package_version'].
               "\nPHP Version: ".phpversion().
               "\nZend Engine Version: ".zend_version().
               "\nRunning on: ".php_uname();

    } elseif ($help = PEAR_Command::getHelp($command)) {
        if (is_string($help)) {
            return "$progname $command [options] $help\n";
        }

        if ($help[1] === null) {
            return "$progname $command $help[0]";
        }

        return "$progname $command [options] $help[0]\n$help[1]";
    }

    return "Command '$command' is not valid, try '$progname help'";
}

// }}}

/**
 * error_handler
 *
 * @param mixed $errno  Error number
 * @param mixed $errmsg Message
 * @param mixed $file   Filename
 * @param mixed $line   Line number
 *
 * @access public
 * @return boolean
 */
function error_handler($errno, $errmsg, $file, $line)
{
    if ((!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) && ($errno & E_STRICT)) {
        return; // E_STRICT
    }
    if ($errno & E_DEPRECATED) {
        return; // E_DEPRECATED
    }
    if (!(error_reporting() & $errno) &&
        isset($GLOBALS['config']) &&
        $GLOBALS['config']->get('verbose') < 4
    ) {
        return false; // @silenced error, show all if debug is high enough
    }
    $errortype = array (
        E_DEPRECATED  => 'Deprecated Warning',
        E_ERROR   =>  "Error",
        E_WARNING   =>  "Warning",
        E_PARSE   =>  "Parsing Error",
        E_NOTICE   =>  "Notice",
        E_CORE_ERROR  =>  "Core Error",
        E_CORE_WARNING  =>  "Core Warning",
        E_COMPILE_ERROR  =>  "Compile Error",
        E_COMPILE_WARNING =>  "Compile Warning",
        E_USER_ERROR =>  "User Error",
        E_USER_WARNING =>  "User Warning",
        E_USER_NOTICE =>  "User Notice"
    );
    if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) {
        $errortype[E_STRICT] = 'Strict Warning';
    }
    $prefix = $errortype[$errno];
    global $_PEAR_PHPDIR;
    if (stristr($file, $_PEAR_PHPDIR)) {
        $file = substr($file, strlen($_PEAR_PHPDIR) + 1);
    } else {
        $file = basename($file);
    }
    print "\n$prefix: $errmsg in $file on line $line\n";
    return false;
}


/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * indent-tabs-mode: nil
 * mode: php
 * End:
 */
// vim600:syn=php
PK��Z�0$�-- .pkgxml/Pear_File_MARC-1.4.1.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.10.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
 <name>File_MARC</name>
 <channel>pear.php.net</channel>
 <summary>Parse, modify, and create MARC records</summary>
 <description>The standard for machine-readable cataloging (MARC) records is documented at http://loc.gov/marc/. This package enables you to read existing MARC records from a file, string, or (using the YAZ extension), from a Z39.50 source. You can also use this package to create new MARC records.

This package is based on the PHP MARC package, originally called &quot;php-marc&quot;, that is part of the Emilda Project (http://www.emilda.org).  Christoffer Landtman generously agreed to make the &quot;php-marc&quot; code available under the GNU LGPL so it could be used as the basis of this PEAR package.</description>
 <lead>
  <name>Dan Scott</name>
  <user>dbs</user>
  <email>dbs@php.net</email>
  <active>yes</active>
 </lead>
 <date>2019-11-13</date>
 <time>17:33:33</time>
 <version>
  <release>1.4.1</release>
  <api>1.4.0</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license uri="http://www.gnu.org/copyleft/lesser.html">GNU Lesser General Public License</license>
 <notes>
1.4.1
  * Reintroduce include_path to composer.json
 </notes>
 <contents>
  <dir baseinstalldir="File" name="/">
   <file baseinstalldir="/" md5sum="ffe2590635f404af055fe731da105939" name="File/MARC/Lint/CodeData.php" role="php" />
   <file baseinstalldir="/" md5sum="a3b9e1c817e67f59add05593500d463e" name="File/MARC/Control_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="acba4463f8e40d6ee4e7ba1f2dc53123" name="File/MARC/Data_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="378f483ec1fd161cd9dfb9b05db58d66" name="File/MARC/Exception.php" role="php" />
   <file baseinstalldir="/" md5sum="a9ba69030cbf4847292b9975e9d922c6" name="File/MARC/Field.php" role="php" />
   <file baseinstalldir="/" md5sum="c37351c7c80927ce6bb1e662510f9183" name="File/MARC/Lint.php" role="php" />
   <file baseinstalldir="/" md5sum="c5ac39e3d25eb0108b9dd5ad8466c821" name="File/MARC/List.php" role="php" />
   <file baseinstalldir="/" md5sum="7af6ce78cde4bb246e4e96709e90d2c0" name="File/MARC/Record.php" role="php" />
   <file baseinstalldir="/" md5sum="df5f97139685f0ad04e47fdbb67e3968" name="File/MARC/Subfield.php" role="php" />
   <file baseinstalldir="/" md5sum="6e102262dfd5d65d8d5a6221dfc74edd" name="File/MARC.php" role="php" />
   <file baseinstalldir="/" md5sum="8b64040d2d18ac4b994595a148266a66" name="File/MARCBASE.php" role="php" />
   <file baseinstalldir="/" md5sum="f5a17a60d34e84e2ee7ca1e5c5c6c620" name="File/MARCXML.php" role="php" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="examples/example.mrc" role="doc" />
   <file baseinstalldir="File" md5sum="1aea40df9f1c2e32f8e065fe8da0a3b5" name="examples/marc_yaz.php" role="doc" />
   <file baseinstalldir="File" md5sum="70ae317e0890d5896e3ffccdd293369a" name="examples/read.php" role="doc" />
   <file baseinstalldir="File" md5sum="54efb9d920ac775bfc847a83a2dec73a" name="examples/subfields.php" role="doc" />
   <file baseinstalldir="File" md5sum="14297da35b510c496cd1f328cf3bb301" name="tests/bad_example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="0dd4c6dbad6e8608d0ebf9d24425955d" name="tests/bad_example.xml" role="test" />
   <file baseinstalldir="File" md5sum="216a6f9d53f6d3d8e22d81fdc10f4bc1" name="tests/camel.mrc" role="test" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="tests/example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="9455aec3371f79cf7d31281fd03f5171" name="tests/marc_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="577e2f5f89fd48cf1a3576a29d2958f8" name="tests/marc_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a6a586354b9a06c880c2a7470dd828d7" name="tests/marc_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1c7e2fc5572a0f9362a771c260a1fe3" name="tests/marc_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="84f85ac7f8a2532e4e90ccde7764556a" name="tests/marc_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="889e5e906a97de7a0e94b0c5f30e70e7" name="tests/marc_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="be823dc8a8efb408de06371ab802efcc" name="tests/marc_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="af44490aafea44e5120f881cb81cdad9" name="tests/marc_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ac9f2a7aeb24900a11f5102744179ae3" name="tests/marc_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5e43eb5cddbb4f2bd0d6405cd95b80aa" name="tests/marc_010.phpt" role="test" />
   <file baseinstalldir="File" md5sum="2e1cd8509c0bf04ec77fc0f51375f611" name="tests/marc_011.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bc49ca48623102c8ac07679fa77a3dd9" name="tests/marc_012.phpt" role="test" />
   <file baseinstalldir="File" md5sum="245a3b20e0da1973535503e28efd1d3a" name="tests/marc_013.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ce69aa734856dd40d60d30c77bdef53a" name="tests/marc_014.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7b61cdd31035e60682fa92c5d519d997" name="tests/marc_015.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7f4f597fe1adaa3507eb87fc4875dbd2" name="tests/marc_016.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4262efd5fcacbd7503323681f4552430" name="tests/marc_017.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ee1623d7bda54ba4f741b2319b158f82" name="tests/marc_018.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8006c03fbab0f04377342086fafd3982" name="tests/marc_019.phpt" role="test" />
   <file baseinstalldir="File" md5sum="f5ae5b25e0ac1104314433d9e5b1f7fe" name="tests/marc_020.phpt" role="test" />
   <file baseinstalldir="File" md5sum="94d8f99e86585671a1b2d3043aeb6360" name="tests/marc_021.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bb891a890effe0e77e1759043f4846d8" name="tests/marc_022.phpt" role="test" />
   <file baseinstalldir="File" md5sum="faf77dcb5cdd002c09169a14bfded65e" name="tests/marc_023.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0e6c4a23f5da7df64fdd4b3b1149bbee" name="tests/marc_16783.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4ea8b3520beda378db15960f1c50493a" name="tests/marc_field_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="743850ef61df69c4340be44a03bccb5a" name="tests/marc_field_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8c765f1398b49df257d86d22ac6e4f8d" name="tests/marc_field_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d4216cf930a308e0d02553bd3914f294" name="tests/marc_field_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dd59514b474b78371ad522a3e13b76b7" name="tests/marc_field_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5295bfd02a8424acac1c91de26b552c7" name="tests/marc_field_21246.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6f95f09442ccf6b93df92986f58b270d" name="tests/marc_lint_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="18d721f8871edd925624ccbdd15444fb" name="tests/marc_lint_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4eb86a2f4e0a74dedcb0bf2511da6ca1" name="tests/marc_lint_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="10430fee0a1352d0528f1507b34c57e1" name="tests/marc_lint_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0dcd07a18577d7b22392a2214cd6436c" name="tests/marc_lint_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fd17798fc535562e5e64461f449516b2" name="tests/marc_record_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="141b455ccf67a60c4eac44c77960f2e2" name="tests/marc_subfield_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1e23464ee0eec47ddca2af9a9922926" name="tests/marc_subfield_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="1d7903e8c244d647220b318b4bc758d1" name="tests/marc_xml_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="22cae3c752d843b78f583dcd92801534" name="tests/marc_xml_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="c0716d23e0f960abf8d53ad6014a413a" name="tests/marc_xml_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7645fa19e28aca041a124fc5e2c12bd3" name="tests/marc_xml_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b08b28c3251625b8b6e4d7ab376b0185" name="tests/marc_xml_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6cd0934ddbf65d2d7e9ea5d108977ff7" name="tests/marc_xml_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ffdce4aa190268fa7cbbf3bb45383abf" name="tests/marc_xml_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="998a4c1ce00ff100f39ffa9fc49a212f" name="tests/marc_xml_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a38a67c590869f2b0a4859a910fd9e89" name="tests/marc_xml_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="db39c5055a570fcda12bb7c5fa1e3b4d" name="tests/marc_xml_16642.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dc075f4a271bd7182378a3874bd5b39e" name="tests/marc_xml_namespace.phpt" role="test" />
   <file baseinstalldir="File" md5sum="208200d9a979ac360c4d326e9789b6b7" name="tests/marc_xml_namespace_prefix.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d87774ede82222cfc12b2c2a06f57a3a" name="tests/marc_xml_rsinger.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fb44e3eb69f1a37115235fc829c39542" name="tests/namespace.xml" role="test" />
   <file baseinstalldir="File" md5sum="e6de4d809b0af5dd99fd352eb60616a1" name="tests/skipif.inc" role="test" />
   <file baseinstalldir="File" md5sum="a0166a4ff0bc0bb283e854f11beaa793" name="tests/music.mrc" role="test" />
   <file baseinstalldir="File" md5sum="993ce494befbc25dc1326527b30b4782" name="tests/music.xml" role="test" />
   <file baseinstalldir="File" md5sum="6b0c87f0cd459ed7322c25d403b164cc" name="tests/bigarchive.xml" role="test" />
   <file baseinstalldir="File" md5sum="be850aa6ab4ac52b8c6c214c30b574af" name="tests/onerecord.xml" role="test" />
   <file baseinstalldir="File" md5sum="4f43fec7b276267eec5258044853ccc8" name="tests/sandburg.mrc" role="test" />
   <file baseinstalldir="File" md5sum="e216b95f905dd240c9bde372950e4073" name="tests/sandburg.xml" role="test" />
   <file baseinstalldir="File" md5sum="e81a92188ea0dcd9c108a63fb32b3f4f" name="tests/xmlescape.mrc" role="test" />
   <file baseinstalldir="File" md5sum="8f9f63ed6a80191d89a2296fa4c1a30b" name="CHANGELOG" role="doc" />
   <file baseinstalldir="File" md5sum="fbc093901857fcd118f065f900982c24" name="LICENSE" role="doc" />
  </dir>
 </contents>
 <dependencies>
  <required>
   <php>
    <min>5.6</min>
   </php>
   <pearinstaller>
    <min>1.4.0</min>
   </pearinstaller>
  </required>
  <optional>
   <package>
    <name>Validate_ISPN</name>
    <channel>pear.php.net</channel>
   </package>
  </optional>
 </dependencies>
 <phprelease />
</package>
PKm�ZPi��.depdbnu�[���PKm�Z�{��
�Mail/null.phpnu�[���PKm�ZE@�%>>
Mail/sendmail.phpnu�[���PKm�Z��A~�{�{�;Mail/RFC822.phpnu�[���PKn�Z�+V����
[�Mail/mime.phpnu�[���PKn�Zx�ع���D�Mail/mimeDecode.phpnu�[���PKn�ZB�_Ǭ=�=
@(Mail/smtp.phpnu�[���PKn�ZwԐE;E;)fMail/smtpmx.phpnu�[���PKn�Z�؛�J�J���Mail/mimePart.phpnu�[���PKn�ZB��shh
8YMail/mock.phpnu�[���PKn�Z@iE�\\
�lMail/mail.phpnu�[���PKn�Zv�.locknu�[���PKn�Z�*�z%-%- ��Structures/LinkedList/Double.phpnu�[���PKn�Z����p:p:  �Structures/LinkedList/Single.phpnu�[���PKn�ZUyv���Structures/Graph.phpnu�[���PKn�Z�C� + +CStructures/Graph/Node.phpnu�[���PKn�Z9����,�1Structures/Graph/Manipulator/AcyclicTest.phpnu�[���PKn�Z~(�htt2�HStructures/Graph/Manipulator/TopologicalSorter.phpnu�[���PKn�Z�J�}
}
_dAuth/SASL/Anonymous.phpnu�[���PKn�ZP(~�T
T
#rAuth/SASL/CramMD5.phpnu�[���PKn�Z����==�Auth/SASL/Plain.phpnu�[���PKn�Z�<� OO<�Auth/SASL/Login.phpnu�[���PKn�Z%ׅtg!g!ΘAuth/SASL/DigestMD5.phpnu�[���PKn�Z�T�|�Auth/SASL/Common.phpnu�[���PKn�ZvR�r,,��Auth/SASL/External.phpnu�[���PKn�Zќ��0�0H�Auth/SASL/SCRAM.phpnu�[���PKn�Z2r����
�	Auth/SASL.phpnu�[���PKn�Z�T�,�,�OS/Guess.phpnu�[���PKn�Z�����KPEAR/Config.phpnu�[���PKn�Z�`�eEAEA
.ZPEAR/REST.phpnu�[���PKn�Z��ym6m6��PEAR/Exception.phpnu�[���PKn�Zr"����_�PEAR/ChannelFile.phpnu�[���PKn�Z��gk�U�U?�PEAR/Validate.phpnu�[���PKn�Zd֣S��u�PEAR/Command/Pickle.xmlnu�[���PKn�Z�z��k<k<W�PEAR/Command/Config.phpnu�[���PKn�Z݄<ii	1PEAR/Command/Mirror.xmlnu�[���PKn�Z,��t"u"u�3PEAR/Command/Remote.phpnu�[���PKn�Z
�\���"�PEAR/Command/Remote.xmlnu�[���PKn�Zj���!�!X�PEAR/Command/Install.xmlnu�[���PKo�Z�%q������PEAR/Command/Channels.phpnu�[���PKo�Znmi?;�;��[	PEAR/Command/Install.phpnu�[���PKo�Z�X�

#
PEAR/Command/Auth.phpnu�[���PKo�Z���s6
6
T-
PEAR/Command/Config.xmlnu�[���PKo�Z�%Fii�:
PEAR/Command/Test.xmlnu�[���PKo�ZZ h66A
PEAR/Command/Package.xmlnu�[���PKo�Z�w��zz�]
PEAR/Command/Channels.xmlnu�[���PKo�Z+9ҜҜ�n
PEAR/Command/Package.phpnu�[���PKo�Z
u����PEAR/Command/Build.xmlnu�[���PKo�Z������
PEAR/Command/Mirror.phpnu�[���PKp�Z,_�h/h/�PEAR/Command/Test.phpnu�[���PKp�Z�%sp  6OPEAR/Command/Common.phpnu�[���PKp�Z0(;rʹʹ�oPEAR/Command/Registry.phpnu�[���PKp�Z�4�{���$PEAR/Command/Auth.xmlnu�[���PKp�Z��#S
S
�)PEAR/Command/Build.phpnu�[���PKp�Z���u��S4PEAR/Command/Registry.xmlnu�[���PKp�Z�P>>�;PEAR/Command/Pickle.phpnu�[���PKp�Z��T�I�I�yPEAR/Builder.phpnu�[���PKp�Z[
�W��3�PEAR/XMLParser.phpnu�[���PKp�Zl(e���t�PEAR/Downloader.phpnu�[���PKp�Z�b������
PEAR/ErrorStack.phpnu�[���PKp�Z(Pz����ePEAR/Proxy.phpnu�[���PKp�Z��'����|PEAR/RunTest.phpnu�[���PKq�Zj�y99�	PEAR/Validator/PECL.phpnu�[���PKq�Zp�����aPEAR/Dependency2.phpnu�[���PKq�Z��wv@@��PEAR/PackageFile/v2.phpnu�[���PKq�ZC�8�L�L!:�PEAR/PackageFile/v2/Validator.phpnu�[���PKq�Z���=_�_�6PEAR/PackageFile/v2/rw.phpnu�[���PKq�Z�5�������,PEAR/PackageFile/v1.phpnu�[���PKq�Z�ɁɁ!��PEAR/PackageFile/Generator/v2.phpnu�[���PKq�Z`�=����!�tPEAR/PackageFile/Generator/v1.phpnu�[���PKr�Z��OWHH�9PEAR/PackageFile/Parser/v2.phpnu�[���PKr�Z�_=�@�@`FPEAR/PackageFile/Parser/v1.phpnu�[���PKr�Zc��__5�PEAR/DependencyDB.phpnu�[���PKr�Z�@P��{�PEAR/ChannelFile/Parser.phpnu�[���PKr�Z��_�0�0r�PEAR/Command.phpnu�[���PKr�Z�ٲ�=�==PEAR/PackageFile.phpnu�[���PKr�Z�JD��g\PEAR/Task/Replace.phpnu�[���PKr�Z&%75))�wPEAR/Task/Windowseol/rw.phpnu�[���PKr�Z�3}}PEAR/Task/Replace/rw.phpnu�[���PKr�Z&
i."x�PEAR/Task/Postinstallscript/rw.phpnu�[���PKr�Z�-!�PEAR/Task/Common.phpnu�[���PKr�ZD$���I�PEAR/Task/Windowseol.phpnu�[���PKr�ZZ�E�x9x9��PEAR/Task/Postinstallscript.phpnu�[���PKr�Z\k��K�PEAR/Task/Unixeol/rw.phpnu�[���PKr�Z�������PEAR/Task/Unixeol.phpnu�[���PKr�Z�W�f���PEAR/REST/10.phpnu�[���PKr�Z��Y�;;ąPEAR/REST/13.phpnu�[���PKr�Z,#y��+�+�PEAR/REST/11.phpnu�[���PKr�Z��U  D�PEAR/Packager.phpnu�[���PKr�ZZ�bgbg�PEAR/Common.phpnu�[���PKr�Z$���(�(FsPEAR/Registry.phpnu�[���PKr�Z��	MdMd?�PEAR/Frontend/CLI.phpnu�[���PKr�Z��

�PEAR/Installer/Role/Doc.phpnu�[���PKr�Z��/��)PEAR/Installer/Role/Cfg.xmlnu�[���PKr�Z>1H���PEAR/Installer/Role/Www.xmlnu�[���PKr�Z�?m

PEAR/Installer/Role/Php.phpnu�[���PKr�Z*Y|	%%`PEAR/Installer/Role/Man.phpnu�[���PKr�Z���BB�PEAR/Installer/Role/Ext.xmlnu�[���PKr�Zp��""]PEAR/Installer/Role/Src.xmlnu�[���PKr�Zh&P*���PEAR/Installer/Role/Doc.xmlnu�[���PKr�ZB] ���PEAR/Installer/Role/Test.xmlnu�[���PKr�Zz�q����PEAR/Installer/Role/Php.xmlnu�[���PKr�Z	��
|PEAR/Installer/Role/Data.phpnu�[���PKs�Z�0�c���PEAR/Installer/Role/Man.xmlnu�[���PKs�Z��K

�PEAR/Installer/Role/Ext.phpnu�[���PKs�ZY��� PEAR/Installer/Role/Test.phpnu�[���PKs�Z@v�а�z#PEAR/Installer/Role/Script.xmlnu�[���PKs�Zf�sz��x%PEAR/Installer/Role/Data.xmlnu�[���PKs�Z?���GGV'PEAR/Installer/Role/Common.phpnu�[���PKs�Z�^D{		�?PEAR/Installer/Role/Www.phpnu�[���PKs�Z�Ƥ?CPEAR/Installer/Role/Cfg.phpnu�[���PKs�Z��[�	SPEAR/Installer/Role/Script.phpnu�[���PKs�Z��srrjVPEAR/Installer/Role/Src.phpnu�[���PKs�ZV�Z���'ZPEAR/Installer/Role.phpnu�[���PKs�Z�{�	�)�)*yPEAR/Downloader/Package.phpnu�[���PKs�Z.�4���$�PEAR/Frontend.phpnu�[���PKs�Z،�w��_�PEAR/Installer.phpnu�[���PKs�ZXxo��-j�Symfony/Bridge/Doctrine/Logger/DbalLogger.phpnu�[���PKs�Ze�OO&b�Symfony/Bridge/Doctrine/autoloader.phpnu�[���PKs�Z��X+��8�Symfony/Bridge/Doctrine/CacheWarmer/ProxyCacheWarmer.phpnu�[���PKs�Z	�9,��5i�Symfony/Bridge/Doctrine/Form/DoctrineOrmExtension.phpnu�[���PKs�Z�0���NX�Symfony/Bridge/Doctrine/Form/EventListener/MergeDoctrineCollectionListener.phpnu�[���PKs�Z!%d==A��Symfony/Bridge/Doctrine/Form/ChoiceList/EntityLoaderInterface.phpnu�[���PKs�Z�	?x�7�7<4�Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.phpnu�[���PKs�ZGC�t��A<-Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.phpnu�[���PKs�Z`.
qpp7�9Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.phpnu�[���PKs�ZCi�PPMZQSymfony/Bridge/Doctrine/Form/DataTransformer/CollectionToArrayTransformer.phpnu�[���PKs�Z憝��0'YSymfony/Bridge/Doctrine/Form/Type/EntityType.phpnu�[���PKs�ZS;,:��2-]Symfony/Bridge/Doctrine/Form/Type/DoctrineType.phpnu�[���PKs�ZW&v��<�wSymfony/Bridge/Doctrine/Security/User/EntityUserProvider.phpnu�[���PKs�Z�����Et�Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.phpnu�[���PKs�Z(��y��9�Symfony/Bridge/Doctrine/Validator/DoctrineInitializer.phpnu�[���PKs�ZQГ��>�Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.phpnu�[���PKs�Z:�d�G5�Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.phpnu�[���PKs�Z�Ta�==B��Symfony/Bridge/Doctrine/ExpressionLanguage/DoctrineParserCache.phpnu�[���PKs�Z��qm
m
-m�Symfony/Bridge/Doctrine/RegistryInterface.phpnu�[���PKs�Zlf/�qq=7�Symfony/Bridge/Doctrine/DataFixtures/ContainerAwareLoader.phpnu�[���PKs�Z����=�Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.phpnu�[���PKs�Z�����C��Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerSchema.phpnu�[���PKs�ZOlQ�996��Symfony/Bridge/Doctrine/ContainerAwareEventManager.phpnu�[���PKs�Z؈����3D�Symfony/Bridge/Doctrine/Test/DoctrineTestHelper.phpnu�[���PKs�Z̳֨�+��Symfony/Bridge/Doctrine/ManagerRegistry.phpnu�[���PKs�Z+çxAA?�Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.phpnu�[���PKs�Z*�+��J�JIBSymfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.phpnu�[���PKs�Z���*��SVaSymfony/Bridge/Doctrine/DependencyInjection/Security/UserProvider/EntityFactory.phpnu�[���PKs�Z��㛕�Q�hSymfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterMappingsPass.phpnu�[���PKs�Z~�YAAeԀSymfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.phpnu�[���PKs�Z��,���S��Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/DoctrineValidationPass.phpnu�[���PKs�Z��4NN%,�Symfony/Bridge/Monolog/autoloader.phpnu�[���PKs�Z��մ��1ϡSymfony/Bridge/Monolog/Handler/FirePHPHandler.phpnu�[���PKs�Z��Zv��/©Symfony/Bridge/Monolog/Handler/DebugHandler.phpnu�[���PKs�Z�y���1دSymfony/Bridge/Monolog/Handler/ConsoleHandler.phpnu�[���PKs�Z��*vv5�Symfony/Bridge/Monolog/Handler/SwiftMailerHandler.phpnu�[���PKs�Z���"II3��Symfony/Bridge/Monolog/Handler/ChromePhpHandler.phpnu�[���PKs�Z��;��	�	!��Symfony/Bridge/Monolog/Logger.phpnu�[���PKs�Z��b115��Symfony/Bridge/Monolog/Formatter/ConsoleFormatter.phpnu�[���PKt�Z�,��1l�Symfony/Bridge/Monolog/Processor/WebProcessor.phpnu�[���PKt�Z�$�KK"l�Symfony/Bridge/Twig/autoloader.phpnu�[���PKt�Z�)�UU1	�Symfony/Bridge/Twig/Translation/TwigExtractor.phpnu�[���PKt�Z6DZ77*��Symfony/Bridge/Twig/Node/StopwatchNode.phpnu�[���PKt�Z,
�@��5P�Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.phpnu�[���PKt�Z�
�s>>*ESymfony/Bridge/Twig/Node/FormThemeNode.phpnu�[���PKt�ZP�IAA3�Symfony/Bridge/Twig/Node/TransDefaultDomainNode.phpnu�[���PKt�Z�U,tt,�Symfony/Bridge/Twig/Node/FormEnctypeNode.phpnu�[���PKt�Zʦ\�G
G
&QSymfony/Bridge/Twig/Node/TransNode.phpnu�[���PKt�Z���^��,�%Symfony/Bridge/Twig/Node/RenderBlockNode.phpnu�[���PKt�Z�vq�)+Symfony/Bridge/Twig/Form/TwigRenderer.phpnu�[���PKt�Zb�3�}}8q1Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.phpnu�[���PKt�Z��Qkk2V4Symfony/Bridge/Twig/Form/TwigRendererInterface.phpnu�[���PKt�Z��<��/#7Symfony/Bridge/Twig/Form/TwigRendererEngine.phpnu�[���PKt�Z�GTSymfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.phpnu�[���PKt�Z�)�[n	n	)�`Symfony/Bridge/Twig/NodeVisitor/Scope.phpnu�[���PKt�Z�tA�:`jSymfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.phpnu�[���PKt�Z��9292B�xSymfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twignu�[���PKt�Z��[[Dy�Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twignu�[���PKt�Z.��8H�Symfony/Bridge/Twig/TokenParser/StopwatchTokenParser.phpnu�[���PKt�Z�%]�
�
4��Symfony/Bridge/Twig/TokenParser/TransTokenParser.phpnu�[���PKt�Z�/�	�	:��Symfony/Bridge/Twig/TokenParser/TransChoiceTokenParser.phpnu�[���PKt�Z>����8>�Symfony/Bridge/Twig/TokenParser/FormThemeTokenParser.phpnu�[���PKt�Zʶ�̭�Ao�Symfony/Bridge/Twig/TokenParser/TransDefaultDomainTokenParser.phpnu�[���PKt�Z�9�=KK/��Symfony/Bridge/Twig/Extension/FormExtension.phpnu�[���PKt�Z��|/7�Symfony/Bridge/Twig/Extension/YamlExtension.phpnu�[���PKt�Z��&�a
a
5��Symfony/Bridge/Twig/Extension/HttpKernelExtension.phpnu�[���PKt�ZKΙ���5v�Symfony/Bridge/Twig/Extension/ExpressionExtension.phpnu�[���PKt�Z`�fS..2� Symfony/Bridge/Twig/Extension/RoutingExtension.phpnu�[���PKt�Z�5��mm4] Symfony/Bridge/Twig/Extension/StopwatchExtension.phpnu�[���PKt�Z�?���6. Symfony/Bridge/Twig/Extension/TranslationExtension.phpnu�[���PKt�Zd���oo3�! Symfony/Bridge/Twig/Extension/SecurityExtension.phpnu�[���PKt�Z�����/a' Symfony/Bridge/Twig/Extension/CodeExtension.phpnu�[���PKu�Z^D��dd"sG Symfony/Bridge/Twig/TwigEngine.phpnu�[���PKu�Z�4˵��()V Symfony/Component/Finder/Shell/Shell.phpnu�[���PKu�Z5��K��*^ Symfony/Component/Finder/Shell/Command.phpnu�[���PKu�Z�5�9(�v Symfony/Component/Finder/SplFileInfo.phpnu�[���PKu�Z%uM�PP'X~ Symfony/Component/Finder/autoloader.phpnu�[���PKu�Z��99C� Symfony/Component/Finder/Exception/ShellCommandFailureException.phpnu�[���PKu�Z�7��9�� Symfony/Component/Finder/Exception/ExceptionInterface.phpnu�[���PKu�Z�cWޫ�<� Symfony/Component/Finder/Exception/AccessDeniedException.phpnu�[���PKu�Z>�@��>� Symfony/Component/Finder/Exception/AdapterFailureException.phpnu�[���PKu�ZP�����D	� Symfony/Component/Finder/Exception/OperationNotPermitedException.phpnu�[���PKu�Z��� ��6� Symfony/Component/Finder/Comparator/DateComparator.phpnu�[���PKu�Z|F�z

2?� Symfony/Component/Finder/Comparator/Comparator.phpnu�[���PKu�Z�P�

8�� Symfony/Component/Finder/Comparator/NumberComparator.phpnu�[���PKu�Z�g@Mbb!2� Symfony/Component/Finder/Glob.phpnu�[���PKu�Z�d�V�V#� Symfony/Component/Finder/Finder.phpnu�[���PKu�Zils_��>
!Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.phpnu�[���PKu�Z��ɔ�
�
7u!Symfony/Component/Finder/Iterator/FilePathsIterator.phpnu�[���PKu�Z�,G��4n!Symfony/Component/Finder/Iterator/FilterIterator.phpnu�[���PKu�Z�ʽ���?q#!Symfony/Component/Finder/Iterator/FilecontentFilterIterator.phpnu�[���PKu�Z�

���@~+!Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.phpnu�[���PKu�Z��z":�2!Symfony/Component/Finder/Iterator/CustomFilterIterator.phpnu�[���PKu�Z{�^ǽ�<N9!Symfony/Component/Finder/Iterator/FilenameFilterIterator.phpnu�[���PKu�Z�d����Dw@!Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.phpnu�[���PKu�Zx�P���=�F!Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.phpnu�[���PKu�Z ��U��=�L!Symfony/Component/Finder/Iterator/DateRangeFilterIterator.phpnu�[���PKu�Z�n bb<�R!Symfony/Component/Finder/Iterator/FileTypeFilterIterator.phpnu�[���PKu�Z��j��	�	6�X!Symfony/Component/Finder/Iterator/SortableIterator.phpnu�[���PKu�Z���)��8�b!Symfony/Component/Finder/Iterator/PathFilterIterator.phpnu�[���PKu�Z�6s��@�j!Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.phpnu�[���PKu�Z��&
&
2Gw!Symfony/Component/Finder/Expression/Expression.phpnu�[���PKu�Z�"HH6ρ!Symfony/Component/Finder/Expression/ValueInterface.phpnu�[���PKu�Z�E�,}�!Symfony/Component/Finder/Expression/Glob.phpnu�[���PKu�Z��(�-�!Symfony/Component/Finder/Expression/Regex.phpnu�[���PKu�Z9!�2{
{
/D�!Symfony/Component/Finder/Adapter/PhpAdapter.phpnu�[���PKu�Z����5�!Symfony/Component/Finder/Adapter/AdapterInterface.phpnu�[���PKu�Z��kA�
�
34�!Symfony/Component/Finder/Adapter/BsdFindAdapter.phpnu�[���PKu�Z�}]�
�
3��!Symfony/Component/Finder/Adapter/GnuFindAdapter.phpnu�[���PKu�ZQJ)�)8��!Symfony/Component/Finder/Adapter/AbstractFindAdapter.phpnu�[���PKu�Z�	4�"Symfony/Component/Finder/Adapter/AbstractAdapter.phpnu�[���PKu�Z����:;"Symfony/Component/Translation/Extractor/ChainExtractor.phpnu�[���PKu�ZArP�>%"Symfony/Component/Translation/Extractor/ExtractorInterface.phpnu�[���PKu�Zb*0�oo4�#"Symfony/Component/Translation/PluralizationRules.phpnu�[���PKu�Z�q��UU,<"Symfony/Component/Translation/autoloader.phpnu�[���PKu�Z�<qNN10>"Symfony/Component/Translation/MessageSelector.phpnu�[���PKu�Z�س��:�J"Symfony/Component/Translation/Catalogue/MergeOperation.phpnu�[���PKu�ZY[�>*P"Symfony/Component/Translation/Catalogue/OperationInterface.phpnu�[���PKu�Z��fb�
�
=�U"Symfony/Component/Translation/Catalogue/AbstractOperation.phpnu�[���PKu�Z��ӄ�9�c"Symfony/Component/Translation/Catalogue/DiffOperation.phpnu�[���PKu�Z�6�"��>�i"Symfony/Component/Translation/Exception/ExceptionInterface.phpnu�[���PKu�ZDŽ���D�k"Symfony/Component/Translation/Exception/InvalidResourceException.phpnu�[���PKv�Z�2B��E2n"Symfony/Component/Translation/Exception/NotFoundResourceException.phpnu�[���PKv�Z�y4��2�p"Symfony/Component/Translation/MessageCatalogue.phpnu�[���PKv�Z%�Mt8��"Symfony/Component/Translation/MetadataAwareInterface.phpnu�[���PKv�Z�d�<<4��"Symfony/Component/Translation/IdentityTranslator.phpnu�[���PKv�Z�e�G��,��"Symfony/Component/Translation/Translator.phpnu�[���PKv�Z��֛�;u�"Symfony/Component/Translation/MessageCatalogueInterface.phpnu�[���PKv�ZM�
���9{�"Symfony/Component/Translation/Dumper/IcuResFileDumper.phpnu�[���PKv�Zਪ(5u�"Symfony/Component/Translation/Dumper/PoFileDumper.phpnu�[���PKv�Z���%LL6��"Symfony/Component/Translation/Dumper/PhpFileDumper.phpnu�[���PKv�Z�<̧��8��"Symfony/Component/Translation/Dumper/XliffFileDumper.phpnu�[���PKv�Z>{GG5��"Symfony/Component/Translation/Dumper/QtFileDumper.phpnu�[���PKv�Z���667Z�"Symfony/Component/Translation/Dumper/YamlFileDumper.phpnu�[���PKv�ZoB���6��"Symfony/Component/Translation/Dumper/CsvFileDumper.phpnu�[���PKv�ZB^�[[3*�"Symfony/Component/Translation/Dumper/FileDumper.phpnu�[���PKv�Z�:$}}7�"Symfony/Component/Translation/Dumper/JsonFileDumper.phpnu�[���PKv�Z&X����6�#Symfony/Component/Translation/Dumper/IniFileDumper.phpnu�[���PKv�Z��<**8
#Symfony/Component/Translation/Dumper/DumperInterface.phpnu�[���PKv�Z����A	A	5�#Symfony/Component/Translation/Dumper/MoFileDumper.phpnu�[���PKv�Zg�?Z�
�
*B#Symfony/Component/Translation/Interval.phpnu�[���PKv�Z�3����5�#Symfony/Component/Translation/TranslatorInterface.phpnu�[���PKv�ZP�?�}}:�%#Symfony/Component/Translation/Writer/TranslationWriter.phpnu�[���PKv�ZN@���6�-#Symfony/Component/Translation/Loader/IniFileLoader.phpnu�[���PKv�Z�T�93#Symfony/Component/Translation/Loader/IcuDatFileLoader.phpnu�[���PKv�ZCS�z
z
9�9#Symfony/Component/Translation/Loader/IcuResFileLoader.phpnu�[���PKv�Z��v���5�D#Symfony/Component/Translation/Loader/MoFileLoader.phpnu�[���PKv�ZR����4&\#Symfony/Component/Translation/Loader/ArrayLoader.phpnu�[���PKv�Z�'s�u	u	7&d#Symfony/Component/Translation/Loader/JsonFileLoader.phpnu�[���PKv�Z�i�3"
"
6n#Symfony/Component/Translation/Loader/CsvFileLoader.phpnu�[���PKv�Z_��BB8�x#Symfony/Component/Translation/Loader/XliffFileLoader.phpnu�[���PKv�Zl#�tt84�#Symfony/Component/Translation/Loader/LoaderInterface.phpnu�[���PKv�Z�*���5�#Symfony/Component/Translation/Loader/PoFileLoader.phpnu�[���PKv�Z�r��;;6o�#Symfony/Component/Translation/Loader/PhpFileLoader.phpnu�[���PKv�Z:�	Z�"�"B�#Symfony/Component/Translation/Loader/schema/dic/xliff-core/xml.xsdnu�[���PKv�Z�xO��T�#Symfony/Component/Translation/Loader/schema/dic/xliff-core/xliff-core-1.2-strict.xsdnu�[���PKv�Z)-d+�	�	5�g%Symfony/Component/Translation/Loader/QtFileLoader.phpnu�[���PKv�Z:����7�q%Symfony/Component/Translation/Loader/YamlFileLoader.phpnu�[���PKw�Z�V�˽�.-z%Symfony/Component/Routing/Annotation/Route.phpnu�[���PKw�Z�<ѹ�+H�%Symfony/Component/Routing/CompiledRoute.phpnu�[���PKw�ZU8���-\�%Symfony/Component/Routing/RouterInterface.phpnu�[���PKw�ZU�cQQ(>�%Symfony/Component/Routing/autoloader.phpnu�[���PKw�Z����'�'+�%Symfony/Component/Routing/RouteCompiler.phpnu�[���PKw�Z��%�%$�%Symfony/Component/Routing/Router.phpnu�[���PKw�Z���q
q
6n�%Symfony/Component/Routing/Matcher/ApacheUrlMatcher.phpnu�[���PKw�Z	�ڗ9E�%Symfony/Component/Routing/Matcher/UrlMatcherInterface.phpnu�[���PKw�Z`�u���=��%Symfony/Component/Routing/Matcher/RequestMatcherInterface.phpnu�[���PKw�Z[z�dd<�&Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.phpnu�[���PKw�Z?�|{��:�&Symfony/Component/Routing/Matcher/Dumper/MatcherDumper.phpnu�[���PKw�Z�x}�44=�&Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.phpnu�[���PKw�Z�bz#z#@A&Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.phpnu�[���PKw�Z�`=e&Symfony/Component/Routing/Matcher/Dumper/DumperCollection.phpnu�[���PKw�Z�N�
�
C�s&Symfony/Component/Routing/Matcher/Dumper/DumperPrefixCollection.phpnu�[���PKw�Z(� ���C�~&Symfony/Component/Routing/Matcher/Dumper/MatcherDumperInterface.phpnu�[���PKw�ZY�IWW8��&Symfony/Component/Routing/Matcher/Dumper/DumperRoute.phpnu�[���PKw�Z�'��9��&Symfony/Component/Routing/Matcher/TraceableUrlMatcher.phpnu�[���PKw�ZGj�C""0��&Symfony/Component/Routing/Matcher/UrlMatcher.phpnu�[���PKw�Z� ��ffE'�&Symfony/Component/Routing/Matcher/RedirectableUrlMatcherInterface.phpnu�[���PKw�Z����==K�&Symfony/Component/Routing/Exception/MissingMandatoryParametersException.phpnu�[���PKw�Zj`j�A��&Symfony/Component/Routing/Exception/InvalidParameterException.phpnu�[���PKw�Znj�W��>/�&Symfony/Component/Routing/Exception/RouteNotFoundException.phpnu�[���PKw�Z��)���:��&Symfony/Component/Routing/Exception/ExceptionInterface.phpnu�[���PKw�Z����JJA��&Symfony/Component/Routing/Exception/MethodNotAllowedException.phpnu�[���PKw�Z?�]�//Af�&Symfony/Component/Routing/Exception/ResourceNotFoundException.phpnu�[���PKw�Z��^�==#�&Symfony/Component/Routing/Route.phpnu�[���PKw�Zr�����:i	'Symfony/Component/Routing/RequestContextAwareInterface.phpnu�[���PKw�Z|,{Ȫ�-p'Symfony/Component/Routing/RouteCollection.phpnu�[���PKw�Z�h�,w)'Symfony/Component/Routing/RequestContext.phpnu�[���PKw�Zմ���I�C'Symfony/Component/Routing/Generator/ConfigurableRequirementsInterface.phpnu�[���PKw�Z�
��1�148M'Symfony/Component/Routing/Generator/UrlGenerator.phpnu�[���PKw�Z�1O�
�
Az'Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.phpnu�[���PKw�Zu�'��>��'Symfony/Component/Routing/Generator/Dumper/GeneratorDumper.phpnu�[���PKw�Z�4��G��'Symfony/Component/Routing/Generator/Dumper/GeneratorDumperInterface.phpnu�[���PKw�Z����@@=�'Symfony/Component/Routing/Generator/UrlGeneratorInterface.phpnu�[���PKw�Zn���hh2Ȥ'Symfony/Component/Routing/Loader/ClosureLoader.phpnu�[���PKw�Z��?�		>��'Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.phpnu�[���PKw�Z~ޟ
�
9�'Symfony/Component/Routing/Loader/AnnotationFileLoader.phpnu�[���PKw�Z~L�W��:�'Symfony/Component/Routing/Loader/AnnotationClassLoader.phpnu�[���PKw�ZP�i{��2��'Symfony/Component/Routing/Loader/PhpFileLoader.phpnu�[���PKw�Z?-[��	�	?5�'Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsdnu�[���PKw�Zأ2D$D$2L�'Symfony/Component/Routing/Loader/XmlFileLoader.phpnu�[���PKw�ZpB�Q Q 3�(Symfony/Component/Routing/Loader/YamlFileLoader.phpnu�[���PKx�ZqF��>>4�5(Symfony/Component/Routing/RouteCompilerInterface.phpnu�[���PKx�Z0���QQ(H9(Symfony/Component/Process/autoloader.phpnu�[���PKx�Zg��'�'*�:(Symfony/Component/Process/ProcessPipes.phpnu�[���PKx�Z��2�{{@6c(Symfony/Component/Process/Exception/ProcessTimedOutException.phpnu�[���PKx�Z�<���:!j(Symfony/Component/Process/Exception/ExceptionInterface.phpnu�[���PKx�Z>H����8:l(Symfony/Component/Process/Exception/RuntimeException.phpnu�[���PKx�Z��W��6�n(Symfony/Component/Process/Exception/LogicException.phpnu�[���PKx�Z˅����@�p(Symfony/Component/Process/Exception/InvalidArgumentException.phpnu�[���PKx�Z��_��>s(Symfony/Component/Process/Exception/ProcessFailedException.phpnu�[���PKx�Z@s�(�x(Symfony/Component/Process/PhpProcess.phpnu�[���PKx�Z�nL	L	*�(Symfony/Component/Process/ProcessUtils.phpnu�[���PKy�Z�!,$

.��(Symfony/Component/Process/ExecutableFinder.phpnu�[���PKy�Z!/���,�(Symfony/Component/Process/ProcessBuilder.phpnu�[���PKy�Zy>�8��1�(Symfony/Component/Process/PhpExecutableFinder.phpnu�[���PKy�Z��M��%ު(Symfony/Component/Process/Process.phpnu�[���PKy�Z[i55ERA)Symfony/Component/Serializer/Normalizer/SerializerAwareNormalizer.phpnu�[���PKy�Z=Vxe::A�D)Symfony/Component/Serializer/Normalizer/NormalizableInterface.phpnu�[���PKy�Z��SVV<�J)Symfony/Component/Serializer/Normalizer/CustomNormalizer.phpnu�[���PKy�Z��,,BiR)Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.phpnu�[���PKy�Z"p�yy?q)Symfony/Component/Serializer/Normalizer/NormalizerInterface.phpnu�[���PKy�Z�qU���C�u)Symfony/Component/Serializer/Normalizer/DenormalizableInterface.phpnu�[���PKz�Z���A�{)Symfony/Component/Serializer/Normalizer/DenormalizerInterface.phpnu�[���PKz�Z���OO9t�)Symfony/Component/Serializer/SerializerAwareInterface.phpnu�[���PKz�Z��TT+,�)Symfony/Component/Serializer/autoloader.phpnu�[���PKz�Zx蕰

4ۅ)Symfony/Component/Serializer/SerializerInterface.phpnu�[���PKz�Z,�c��9L�)Symfony/Component/Serializer/Encoder/EncoderInterface.phpnu�[���PKz�Z��[�5�53i�)Symfony/Component/Serializer/Encoder/XmlEncoder.phpnu�[���PKz�Z�<=ggD��)Symfony/Component/Serializer/Encoder/NormalizationAwareInterface.phpnu�[���PKz�ZV��O��5��)Symfony/Component/Serializer/Encoder/ChainDecoder.phpnu�[���PKz�Z�=��?��)Symfony/Component/Serializer/Encoder/SerializerAwareEncoder.phpnu�[���PKz�Zv:�hh3[�)Symfony/Component/Serializer/Encoder/JsonEncode.phpnu�[���PKz�Z��@���3&�)Symfony/Component/Serializer/Encoder/JsonDecode.phpnu�[���PKz�ZS R�	�	5q�)Symfony/Component/Serializer/Encoder/ChainEncoder.phpnu�[���PKz�Z�o�vv4��)Symfony/Component/Serializer/Encoder/JsonEncoder.phpnu�[���PKz�Z|ͼ���9��)Symfony/Component/Serializer/Encoder/DecoderInterface.phpnu�[���PKz�ZA�A
��4�*Symfony/Component/Serializer/Exception/Exception.phpnu�[���PKz�Z�^L��?�*Symfony/Component/Serializer/Exception/UnsupportedException.phpnu�[���PKz�Z�h=��;�*Symfony/Component/Serializer/Exception/RuntimeException.phpnu�[���PKz�ZJ���9�*Symfony/Component/Serializer/Exception/LogicException.phpnu�[���PKz�ZT��Y��C	*Symfony/Component/Serializer/Exception/InvalidArgumentException.phpnu�[���PKz�Z[�����Ci*Symfony/Component/Serializer/Exception/UnexpectedValueException.phpnu�[���PKz�Zʪ2/&/&+�
*Symfony/Component/Serializer/Serializer.phpnu�[���PKz�ZFP�PP'<4*Symfony/Component/Locale/autoloader.phpnu�[���PKz�Z�Q�UUL�5*Symfony/Component/Locale/Exception/MethodArgumentNotImplementedException.phpnu�[���PKz�Z��E>�9*Symfony/Component/Locale/Exception/NotImplementedException.phpnu�[���PKz�ZS�?a%%D#=*Symfony/Component/Locale/Exception/MethodNotImplementedException.phpnu�[���PKz�Z���ssQ�@*Symfony/Component/Locale/Exception/MethodArgumentValueNotImplementedException.phpnu�[���PKz�Z�C��*�D*Symfony/Component/Locale/Stub/StubIntl.phpnu�[���PKz�Z&�����5�G*Symfony/Component/Locale/Stub/StubNumberFormatter.phpnu�[���PKz�Zv/�@�J*Symfony/Component/Locale/Stub/DateFormat/Hour2401Transformer.phpnu�[���PKz�Z��S@PN*Symfony/Component/Locale/Stub/DateFormat/TimeZoneTransformer.phpnu�[���PKz�Z}��""A�Q*Symfony/Component/Locale/Stub/DateFormat/DayOfYearTransformer.phpnu�[���PKz�Z�X�<oU*Symfony/Component/Locale/Stub/DateFormat/AmPmTransformer.phpnu�[���PKz�Z���<�X*Symfony/Component/Locale/Stub/DateFormat/YearTransformer.phpnu�[���PKz�Zmў?O\*Symfony/Component/Locale/Stub/DateFormat/QuarterTransformer.phpnu�[���PKz�Zg[ep>�_*Symfony/Component/Locale/Stub/DateFormat/MinuteTransformer.phpnu�[���PKz�Z:6""ARc*Symfony/Component/Locale/Stub/DateFormat/DayOfWeekTransformer.phpnu�[���PKz�Z9�u@�f*Symfony/Component/Locale/Stub/DateFormat/Hour1200Transformer.phpnu�[���PKz�Zk&"M@qj*Symfony/Component/Locale/Stub/DateFormat/Hour1201Transformer.phpnu�[���PKz�Z�����;�m*Symfony/Component/Locale/Stub/DateFormat/DayTransformer.phpnu�[���PKz�Z��@fq*Symfony/Component/Locale/Stub/DateFormat/Hour2400Transformer.phpnu�[���PKz�Z�Ed��8�t*Symfony/Component/Locale/Stub/DateFormat/Transformer.phpnu�[���PKz�Zt�z

=Ox*Symfony/Component/Locale/Stub/DateFormat/MonthTransformer.phpnu�[���PKz�Zk�H<�{*Symfony/Component/Locale/Stub/DateFormat/FullTransformer.phpnu�[���PKz�Z�3�X>6*Symfony/Component/Locale/Stub/DateFormat/SecondTransformer.phpnu�[���PKz�Z�
�

<��*Symfony/Component/Locale/Stub/DateFormat/HourTransformer.phpnu�[���PKz�Z���?��.-�*Symfony/Component/Locale/Stub/StubCollator.phpnu�[���PK{�Zq��*((,�*Symfony/Component/Locale/Stub/StubLocale.phpnu�[���PK{�Z� S���7��*Symfony/Component/Locale/Stub/StubIntlDateFormatter.phpnu�[���PK{�Zl�l��#��*Symfony/Component/Locale/Locale.phpnu�[���PK{�Z�t�TT+��*Symfony/Component/Filesystem/autoloader.phpnu�[���PK{�Z��dP��@b�*Symfony/Component/Filesystem/Exception/FileNotFoundException.phpnu�[���PK{�Z3{����=��*Symfony/Component/Filesystem/Exception/ExceptionInterface.phpnu�[���PK{�ZoC�~��?��*Symfony/Component/Filesystem/Exception/IOExceptionInterface.phpnu�[���PK{�Z;�{��6ͷ*Symfony/Component/Filesystem/Exception/IOException.phpnu�[���PK{�ZOظ�GG+�*Symfony/Component/Filesystem/Filesystem.phpnu�[���PK{�Z)��.�.'T+Symfony/Component/Form/FormRenderer.phpnu�[���PK{�Z�C����.]2+Symfony/Component/Form/ButtonTypeInterface.phpnu�[���PK{�ZK'�$��&�4+Symfony/Component/Form/FormBuilder.phpnu�[���PK{�Z&�"̰T�T,�S+Symfony/Component/Form/FormConfigBuilder.phpnu�[���PK{�ZE1�'��4��+Symfony/Component/Form/SubmitButtonTypeInterface.phpnu�[���PK{�Z�d��'�+Symfony/Component/Form/FormRegistry.phpnu�[���PK{�ZÊM'%%.н+Symfony/Component/Form/FormConfigInterface.phpnu�[���PK{�Z��@@/S�+Symfony/Component/Form/FormTypeGuesserChain.phpnu�[���PK{�ZR����+��+Symfony/Component/Form/Guess/ValueGuess.phpnu�[���PK{�Z�511&,�+Symfony/Component/Form/Guess/Guess.phpnu�[���PK{�Z���  *��+Symfony/Component/Form/Guess/TypeGuess.phpnu�[���PK{�Z�0\ZZ.-�+Symfony/Component/Form/CallbackTransformer.phpnu�[���PK{�Z4�Nz"z"!�,Symfony/Component/Form/Button.phpnu�[���PK{�Z-�9NN%�%,Symfony/Component/Form/autoloader.phpnu�[���PK{�Z�/��tt%S',Symfony/Component/Form/FormEvents.phpnu�[���PK{�Z�����,,,Symfony/Component/Form/FormTypeInterface.phpnu�[���PK{�Z�>���09,Symfony/Component/Form/FormRegistryInterface.phpnu�[���PK{�Z��?zz3?,Symfony/Component/Form/FormTypeGuesserInterface.phpnu�[���PK{�Z��*��+�G,Symfony/Component/Form/ResolvedFormType.phpnu�[���PK{�ZObX�qq'6f,Symfony/Component/Form/SubmitButton.phpnu�[���PK|�Z�p��1�j,Symfony/Component/Form/AbstractRendererEngine.phpnu�[���PK|�ZDjN,1�,Symfony/Component/Form/AbstractExtension.phpnu�[���PK|�Zf#jK��6��,Symfony/Component/Form/FormRendererEngineInterface.phpnu�[���PK|�Z���1�1���,Symfony/Component/Form/Form.phpnu�[���PK|�Z�di���;A-Symfony/Component/Form/Exception/BadMethodCallException.phpnu�[���PK|�Z�W�

:yC-Symfony/Component/Form/Exception/AlreadyBoundException.phpnu�[���PK|�Z(ddB�E-Symfony/Component/Form/Exception/InvalidConfigurationException.phpnu�[���PK|�Z�_c==<�G-Symfony/Component/Form/Exception/UnexpectedTypeException.phpnu�[���PK|�Z�S�D��BoJ-Symfony/Component/Form/Exception/TransformationFailedException.phpnu�[���PK|�Z��9�L-Symfony/Component/Form/Exception/OutOfBoundsException.phpnu�[���PK}�Z�y�u��7�N-Symfony/Component/Form/Exception/ExceptionInterface.phpnu�[���PK}�ZN����5
Q-Symfony/Component/Form/Exception/RuntimeException.phpnu�[���PK}�ZK�9���>OS-Symfony/Component/Form/Exception/AlreadySubmittedException.phpnu�[���PK}�Z1�;TT:�U-Symfony/Component/Form/Exception/ErrorMappingException.phpnu�[���PK}�Z��+RR8oW-Symfony/Component/Form/Exception/StringCastException.phpnu�[���PK}�Z��X��3)Y-Symfony/Component/Form/Exception/LogicException.phpnu�[���PK}�Z�gBz��=d[-Symfony/Component/Form/Exception/InvalidArgumentException.phpnu�[���PK}�Z�1��88'�]-Symfony/Component/Form/AbstractType.phpnu�[���PK}�Z�I	�66.Ub-Symfony/Component/Form/Util/OrderedHashMap.phpnu�[���PK}�Z�h��''6�t-Symfony/Component/Form/Util/OrderedHashMapIterator.phpnu�[���PK}�Z��F228v�-Symfony/Component/Form/Util/VirtualFormAwareIterator.phpnu�[���PK}�Zy���$$(�-Symfony/Component/Form/Util/FormUtil.phpnu�[���PK}�Z<����8��-Symfony/Component/Form/Util/InheritDataAwareIterator.phpnu�[���PK}�Z�QT�pp.�-Symfony/Component/Form/SubmitButtonBuilder.phpnu�[���PK}�Z�z5���2��-Symfony/Component/Form/ResolvedFormTypeFactory.phpnu�[���PK}�ZSf��
	
	-��-Symfony/Component/Form/PreloadedExtension.phpnu�[���PK}�Z>��*ii&�-Symfony/Component/Form/FormFactory.phpnu�[���PK}�Z�\�g��2˳-Symfony/Component/Form/RequestHandlerInterface.phpnu�[���PK}�Z+q�DAA7ɶ-Symfony/Component/Form/Test/FormPerformanceTestCase.phpnu�[���PK}�ZsŪ�,q�-Symfony/Component/Form/Test/TypeTestCase.phpnu�[���PK}�Z�,�7//7�-Symfony/Component/Form/Test/DeprecationErrorHandler.phpnu�[���PK}�ZB�4I++7k�-Symfony/Component/Form/Test/FormIntegrationTestCase.phpnu�[���PK}�Z��m�yy4��-Symfony/Component/Form/Test/FormBuilderInterface.phpnu�[���PK}�Za(0kk-��-Symfony/Component/Form/Test/FormInterface.phpnu�[���PK}�Z�n����1��-Symfony/Component/Form/FormExtensionInterface.phpnu�[���PK}�Z|G����4��-Symfony/Component/Form/ResolvedFormTypeInterface.phpnu�[���PK}�Z{d���!�!5��-Symfony/Component/Form/FormConfigBuilderInterface.phpnu�[���PK}�ZɃT���6.Symfony/Component/Form/FormFactoryBuilderInterface.phpnu�[���PK}�Z�N̷;m.Symfony/Component/Form/ResolvedFormTypeFactoryInterface.phpnu�[���PK}�Z2��-�.Symfony/Component/Form/FormFactoryBuilder.phpnu�[���PK}�Z���C��0d$.Symfony/Component/Form/AbstractTypeExtension.phpnu�[���PK}�Z�E���0�(.Symfony/Component/Form/FormRendererInterface.phpnu�[���PK}�Z�:		/�5.Symfony/Component/Form/FormBuilderInterface.phpnu�[���PK}�Z��Z)��/R?.Symfony/Component/Form/FormFactoryInterface.phpnu�[���PK}�Z�YB���.EP.Symfony/Component/Form/ReversedTransformer.phpnu�[���PK}�Z�r�WW3�U.Symfony/Component/Form/DataTransformerInterface.phpnu�[���PK}�ZW�b�[H[H(Eb.Symfony/Component/Form/ButtonBuilder.phpnu�[���PK}�Z��n��?��.Symfony/Component/Form/Resources/translations/validators.en.xlfnu�[���PK}�Z誫���?�.Symfony/Component/Form/Resources/translations/validators.sk.xlfnu�[���PK}�Z�<�yy?=�.Symfony/Component/Form/Resources/translations/validators.uk.xlfnu�[���PK}�Z:����?%�.Symfony/Component/Form/Resources/translations/validators.pl.xlfnu�[���PK��Z��
���?[�.Symfony/Component/Form/Resources/translations/validators.pt.xlfnu�[���PK��Z�%��?��.Symfony/Component/Form/Resources/translations/validators.lv.xlfnu�[���PK��Z္o33D��.Symfony/Component/Form/Resources/translations/validators.sr_Cyrl.xlfnu�[���PK��Z����?��.Symfony/Component/Form/Resources/translations/validators.fi.xlfnu�[���PK��Z0h���?��.Symfony/Component/Form/Resources/translations/validators.es.xlfnu�[���PK��Z�TI��?,�.Symfony/Component/Form/Resources/translations/validators.de.xlfnu�[���PK��Z!�aZ��?~�.Symfony/Component/Form/Resources/translations/validators.it.xlfnu�[���PK��Z �!���?��.Symfony/Component/Form/Resources/translations/validators.ca.xlfnu�[���PK��Z���?��.Symfony/Component/Form/Resources/translations/validators.mn.xlfnu�[���PK��Z���-��?X�.Symfony/Component/Form/Resources/translations/validators.ru.xlfnu�[���PK��Z�3Ե^^?T�.Symfony/Component/Form/Resources/translations/validators.bg.xlfnu�[���PK��ZE��d��?!�.Symfony/Component/Form/Resources/translations/validators.ro.xlfnu�[���PK��ZO���?r�.Symfony/Component/Form/Resources/translations/validators.nl.xlfnu�[���PK��ZS�*��?��.Symfony/Component/Form/Resources/translations/validators.et.xlfnu�[���PK��Z�V5?��.Symfony/Component/Form/Resources/translations/validators.fa.xlfnu�[���PK��Z��q��?J�.Symfony/Component/Form/Resources/translations/validators.id.xlfnu�[���PK��Z�
���?w/Symfony/Component/Form/Resources/translations/validators.cs.xlfnu�[���PK��Z�8,:��B�/Symfony/Component/Form/Resources/translations/validators.zh_CN.xlfnu�[���PK��Z�H�q��?�
/Symfony/Component/Form/Resources/translations/validators.lt.xlfnu�[���PK��Z�_8��?�/Symfony/Component/Form/ResoPK��Z|L(�t�t�3.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUri   URI of the namespace
     * @param bool   $multiline      whether to create a multiline tag where each
     *                               attribute gets written to a single line
     * @param string $indent         string used to indent attributes (_auto indents
     *                               attributes so they start at the same column)
     * @param string $linebreak      string used for linebreaks
     * @param bool   $sortAttributes Whether to sort the attributes or not
     *
     * @return string XML start element
     * @see    createEndElement(), createTag()
     */
    public static function createStartElement(
        $qname, $attributes = array(), $namespaceUri = null,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true
    ) {
        // if no attributes hav been set, use empty attributes
        if (!isset($attributes) || !is_array($attributes)) {
            $attributes = array();
        }

        if ($namespaceUri != null) {
            $parts = XML_Util::splitQualifiedName($qname);
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($qname)+2));
            }
        }

        if ($namespaceUri != null) {
            // is a namespace given
            if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
            } else {
                // define this Uri as the default namespace
                $attributes['xmlns'] = $namespaceUri;
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $attributes, $sortAttributes,
            $multiline, $indent, $linebreak
        );
        $element = sprintf('<%s%s>', $qname, $attList);
        return  $element;
    }

    /**
     * Create an end element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createEndElement('myNs:myTag');
     * </code>
     *
     * @param string $qname qualified tagname (including namespace)
     *
     * @return string XML end element
     * @see    createStartElement(), createTag()
     */
    public static function createEndElement($qname)
    {
        $element = sprintf('</%s>', $qname);
        return $element;
    }

    /**
     * Create an XML comment
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createComment('I am a comment');
     * </code>
     *
     * @param string $content content of the comment
     *
     * @return string XML comment
     */
    public static function createComment($content)
    {
        $comment = sprintf('<!-- %s -->', $content);
        return $comment;
    }

    /**
     * Create a CData section
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create a CData section
     * $tag = XML_Util::createCDataSection('I am content.');
     * </code>
     *
     * @param string $data data of the CData section
     *
     * @return string CData section with content
     */
    public static function createCDataSection($data)
    {
        return sprintf(
            '<![CDATA[%s]]>',
            preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data))
        );
    }

    /**
     * Split qualified name and return namespace and local part
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // split qualified tag
     * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
     * </code>
     * the returned array will contain two elements:
     * <pre>
     * array(
     *     'namespace' => 'xslt',
     *     'localPart' => 'stylesheet'
     * );
     * </pre>
     *
     * @param string $qname     qualified tag name
     * @param string $defaultNs default namespace (optional)
     *
     * @return array array containing namespace and local part
     */
    public static function splitQualifiedName($qname, $defaultNs = null)
    {
        if (strstr($qname, ':')) {
            $tmp = explode(':', $qname);
            return array(
                'namespace' => $tmp[0],
                'localPart' => $tmp[1]
            );
        }
        return array(
            'namespace' => $defaultNs,
            'localPart' => $qname
        );
    }

    /**
     * Check, whether string is valid XML name
     *
     * <p>XML names are used for tagname, attribute names and various
     * other, lesser known entities.</p>
     * <p>An XML name may only consist of alphanumeric characters,
     * dashes, undescores and periods, and has to start with a letter
     * or an underscore.</p>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // verify tag name
     * $result = XML_Util::isValidName('invalidTag?');
     * if (is_a($result, 'PEAR_Error')) {
     *    print 'Invalid XML name: ' . $result->getMessage();
     * }
     * </code>
     *
     * @param string $string string that should be checked
     *
     * @return mixed true, if string is a valid XML name, PEAR error otherwise
     *
     * @todo support for other charsets
     * @todo PEAR CS - unable to avoid 85-char limit on second preg_match
     */
    public static function isValidName($string)
    {
        // check for invalid chars
        if (!is_string($string) || !strlen($string) || !preg_match('/^[[:alpha:]_]\\z/', $string[0])) {
            return XML_Util::raiseError(
                'XML names may only start with letter or underscore',
                XML_UTIL_ERROR_INVALID_START
            );
        }

        // check for invalid chars
        $match = preg_match(
            '/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?'
            . '[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/',
            $string
        );
        if (!$match) {
            return XML_Util::raiseError(
                'XML names may only contain alphanumeric '
                . 'chars, period, hyphen, colon and underscores',
                XML_UTIL_ERROR_INVALID_CHARS
            );
        }
        // XML name is valid
        return true;
    }

    /**
     * Replacement for XML_Util::raiseError
     *
     * Avoids the necessity to always require
     * PEAR.php
     *
     * @param string $msg  error message
     * @param int    $code error code
     *
     * @return PEAR_Error
     * @todo   PEAR CS - should this use include_once instead?
     */
    public static function raiseError($msg, $code)
    {
        include_once 'PEAR.php';
        return PEAR::raiseError($msg, $code);
    }
}
?>
PK��Z#F��:�:pearcmd.phpnu�[���<?php
/**
 * PEAR, the PHP Extension and Application Repository
 *
 * Command line interface
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Stig Bakken <ssb@php.net>
 * @author    Tomas V.V.Cox <cox@idecnet.com>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 */

@ob_end_clean();
if (!defined('PEAR_RUNTYPE')) {
    // this is defined in peclcmd.php as 'pecl'
    define('PEAR_RUNTYPE', 'pear');
}
define('PEAR_IGNORE_BACKTRACE', 1);
/**
 * @nodep Gtk
 */
//the space is needed for windows include paths with trailing backslash
// http://pear.php.net/bugs/bug.php?id=19482
if ('/opt/alt/php74/usr/share/pear ' != '@'.'include_path'.'@ ') {
    ini_set('include_path', trim('/opt/alt/php74/usr/share/pear '). PATH_SEPARATOR .  get_include_path());
    $raw = false;
} else {
    // this is a raw, uninstalled pear, either a cvs checkout, or php distro
    ini_set('include_path', dirname(__DIR__) . PATH_SEPARATOR . get_include_path());
    $raw = true;
}
@ini_set('allow_url_fopen', true);
@set_time_limit(0);
ob_implicit_flush(true);
@ini_set('track_errors', true);
@ini_set('html_errors', false);
$_PEAR_PHPDIR = '#$%^&*';
set_error_handler('error_handler');

$pear_package_version = "1.10.16";

require_once 'PEAR.php';
require_once 'PEAR/Frontend.php';
require_once 'PEAR/Config.php';
require_once 'PEAR/Command.php';
require_once 'Console/Getopt.php';


PEAR_Command::setFrontendType('CLI');
$all_commands = PEAR_Command::getCommands();

$argv = Console_Getopt::readPHPArgv();
// fix CGI sapi oddity - the -- in pear.bat/pear is not removed
if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
    unset($argv[1]);
    $argv = array_values($argv);
}
$progname = PEAR_RUNTYPE;
array_shift($argv);
$options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV");
if (PEAR::isError($options)) {
    usage($options);
}

$opts = $options[0];

$fetype = 'CLI';
if ($progname == 'gpear' || $progname == 'pear-gtk') {
    $fetype = 'Gtk2';
} else {
    foreach ($opts as $opt) {
        if ($opt[0] == 'G') {
            $fetype = 'Gtk2';
        }
    }
}

$pear_user_config = '';
$pear_system_config = '';
$store_user_config = false;
$store_system_config = false;
$verbose = 1;

foreach ($opts as $opt) {
    switch ($opt[0]) {
    case 'c':
        $pear_user_config = $opt[1];
        break;
    case 'C':
        $pear_system_config = $opt[1];
        break;
    }
}

PEAR_Command::setFrontendType($fetype);
$ui = &PEAR_Command::getFrontendObject();
$config = &PEAR_Config::singleton($pear_user_config, $pear_system_config);

if (PEAR::isError($config)) {
    $_file = '';
    if ($pear_user_config !== false) {
        $_file .= $pear_user_config;
    }
    if ($pear_system_config !== false) {
        $_file .= '/' . $pear_system_config;
    }
    if ($_file == '/') {
        $_file = 'The default config file';
    }
    $config->getMessage();
    $ui->outputData("ERROR: $_file is not a valid config file or is corrupted.");
    // We stop, we have no idea where we are :)
    exit(1);
}

// this is used in the error handler to retrieve a relative path
$_PEAR_PHPDIR = $config->get('php_dir');
$ui->setConfig($config);
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError"));

$verbose = $config->get("verbose");
$cmdopts = array();

if ($raw) {
    if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) {
        $found = false;
        foreach ($opts as $opt) {
            if ($opt[0] == 'd' || $opt[0] == 'D') {
                // the user knows what they are doing, and are setting config values
                $found = true;
            }
        }
        if (!$found) {
            // no prior runs, try to install PEAR
            $parent = dirname(__FILE__);
            if (strpos($parent, 'scripts')) {
                $grandparent = dirname($parent);
                $packagexml = $grandparent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $grandparent;
            } else {
                $packagexml = $parent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $parent;
            }
            if (file_exists($packagexml)) {
                $options[1] = array(
                    'install',
                    $packagexml
                );
                $config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php');
                $config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data');
                $config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs');
                $config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests');
                $config->set(
                    'ext_dir',
                    $pearbase . DIRECTORY_SEPARATOR . 'extensions'
                );
                $config->set('bin_dir', $pearbase);
                $config->mergeConfigFile($pearbase . 'pear.ini', false);
                $config->store();
                $config->set('auto_discover', 1);
            }
        }
    }
}
foreach ($opts as $opt) {
    $param = !empty($opt[1]) ? $opt[1] : true;
    switch ($opt[0]) {
    case 'd':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected -d config_value=value, ' .
                'received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'user');
        break;
    case 'D':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'system');
        break;
    case 's':
        $store_user_config = true;
        break;
    case 'S':
        $store_system_config = true;
        break;
    case 'u':
        $config->remove($param, 'user');
        break;
    case 'v':
        $config->set('verbose', $config->get('verbose') + 1);
        break;
    case 'q':
        $config->set('verbose', $config->get('verbose') - 1);
        break;
    case 'V':
        usage(null, 'version');
    case 'c':
    case 'C':
        break;
    default:
        // all non pear params goes to the command
        $cmdopts[$opt[0]] = $param;
        break;
    }
}

if ($store_system_config) {
    $config->store('system');
}

if ($store_user_config) {
    $config->store('user');
}

$command = (isset($options[1][0])) ? $options[1][0] : null;
if (empty($command) && ($store_user_config || $store_system_config)) {
    exit;
}

if ($fetype == 'Gtk2') {
    if (!$config->validConfiguration()) {
        PEAR::raiseError(
            "CRITICAL ERROR: no existing valid configuration files found in " .
            "files '$pear_user_config' or '$pear_system_config', " .
            "please copy an existing configuration file to one of these " .
            "locations, or use the -c and -s options to create one"
        );
    }
    Gtk::main();
} else {
    do {
        if ($command == 'help') {
            usage(null, isset($options[1][1]) ? $options[1][1] : null);
        }

        if (!$config->validConfiguration()) {
            PEAR::raiseError(
                "CRITICAL ERROR: no existing valid configuration files found " .
                "in files '$pear_user_config' or '$pear_system_config', " .
                "please copy an existing configuration file to one of " .
                "these locations, or use the -c and -s options to create one"
            );
        }

        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        $cmd = PEAR_Command::factory($command, $config);
        PEAR::popErrorHandling();
        if (PEAR::isError($cmd)) {
            usage(null, isset($options[1][0]) ? $options[1][0] : null);
        }

        $short_args = $long_args = null;
        PEAR_Command::getGetoptArgs($command, $short_args, $long_args);
        array_shift($options[1]);
        $tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args);

        if (PEAR::isError($tmp)) {
            break;
        }

        list($tmpopt, $params) = $tmp;
        $opts = array();
        foreach ($tmpopt as $foo => $tmp2) {
            list($opt, $value) = $tmp2;
            if ($value === null) {
                $value = true; // options without args
            }

            if (strlen($opt) == 1) {
                $cmdoptions = $cmd->getOptions($command);
                foreach ($cmdoptions as $o => $d) {
                    if (isset($d['shortopt']) && $d['shortopt'] == $opt) {
                        $opts[$o] = $value;
                    }
                }
            } else {
                if (substr($opt, 0, 2) == '--') {
                    $opts[substr($opt, 2)] = $value;
                }
            }
        }

        $ok = $cmd->run($command, $opts, $params);
        if ($ok === false) {
            PEAR::raiseError("unknown command `$command'");
        }

        if (PEAR::isError($ok)) {
            PEAR::setErrorHandling(
                PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")
            );
            PEAR::raiseError($ok);
        }
    } while (false);
}

// {{{ usage()

/**
 * Display usage information
 *
 * @param mixed $error       Optional error message
 * @param mixed $helpsubject Optional subject/command to display help for
 *
 * @return void
 */
function usage($error = null, $helpsubject = null)
{
    global $progname, $all_commands;
    $stdout = fopen('php://stdout', 'w');
    if (PEAR::isError($error)) {
        fputs($stdout, $error->getMessage() . "\n");
    } elseif ($error !== null) {
        fputs($stdout, "$error\n");
    }

    if ($helpsubject != null) {
        $put = cmdHelp($helpsubject);
    } else {
        $put = "Commands:\n";
        $maxlen = max(array_map("strlen", $all_commands));
        $formatstr = "%-{$maxlen}s  %s\n";
        ksort($all_commands);
        foreach ($all_commands as $cmd => $class) {
            $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd));
        }
        $put .=
            "Usage: $progname [options] command [command-options] <parameters>\n".
            "Type \"$progname help options\" to list all options.\n".
            "Type \"$progname help shortcuts\" to list all command shortcuts.\n".
            "Type \"$progname help version\" or ".
            "\"$progname version\" to list version information.\n".
            "Type \"$progname help <command>\" to get the help ".
            "for the specified command.";
    }
    fputs($stdout, "$put\n");
    fclose($stdout);

    if ($error === null) {
        exit(0);
    }
    exit(1);
}

/**
 * Return help string for specified command
 *
 * @param string $command Command to return help for
 *
 * @return void
 */
function cmdHelp($command)
{
    global $progname, $all_commands, $config;
    if ($command == "options") {
        return
        "Options:\n".
        "     -v         increase verbosity level (default 1)\n".
        "     -q         be quiet, decrease verbosity level\n".
        "     -c file    find user configuration in `file'\n".
        "     -C file    find system configuration in `file'\n".
        "     -d foo=bar set user config variable `foo' to `bar'\n".
        "     -D foo=bar set system config variable `foo' to `bar'\n".
        "     -G         start in graphical (Gtk) mode\n".
        "     -s         store user configuration\n".
        "     -S         store system configuration\n".
        "     -u foo     unset `foo' in the user configuration\n".
        "     -h, -?     display help/usage (this message)\n".
        "     -V         version information\n";
    } elseif ($command == "shortcuts") {
        $sc = PEAR_Command::getShortcuts();
        $ret = "Shortcuts:\n";
        foreach ($sc as $s => $c) {
            $ret .= sprintf("     %-8s %s\n", $s, $c);
        }
        return $ret;

    } elseif ($command == "version") {
        return "PEAR Version: ".$GLOBALS['pear_package_version'].
               "\nPHP Version: ".phpversion().
               "\nZend Engine Version: ".zend_version().
               "\nRunning on: ".php_uname();

    } elseif ($help = PEAR_Command::getHelp($command)) {
        if (is_string($help)) {
            return "$progname $command [options] $help\n";
        }

        if ($help[1] === null) {
            return "$progname $command $help[0]";
        }

        return "$progname $command [options] $help[0]\n$help[1]";
    }

    return "Command '$command' is not valid, try '$progname help'";
}

// }}}

/**
 * error_handler
 *
 * @param mixed $errno  Error number
 * @param mixed $errmsg Message
 * @param mixed $file   Filename
 * @param mixed $line   Line number
 *
 * @access public
 * @return boolean
 */
function error_handler($errno, $errmsg, $file, $line)
{
    if ((!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) && ($errno & E_STRICT)) {
        return; // E_STRICT
    }
    if ($errno & E_DEPRECATED) {
        return; // E_DEPPK��Z�����6.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUri   URI of the namespace
     * @param bool   $multiline      whether to create a multiline tag where each
     *                               attribute gets written to a single line
     * @param string $indent         string used to indent attributes (_auto indents
     *                               attributes so they start at the same column)
     * @param string $linebreak      string used for linebreaks
     * @param bool   $sortAttributes Whether to sort the attributes or not
     *
     * @return string XML start element
     * @see    createEndElement(), createTag()
     */
    public static function createStartElement(
        $qname, $attributes = array(), $namespaceUri = null,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true
    ) {
        // if no attributes hav been set, use empty attributes
        if (!isset($attributes) || !is_array($attributes)) {
            $attributes = array();
        }

        if ($namespaceUri != null) {
            $parts = XML_Util::splitQualifiedName($qname);
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($qname)+2));
            }
        }

        if ($namespaceUri != null) {
            // is a namespace given
            if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
            } else {
                // define this Uri as the default namespace
                $attributes['xmlns'] = $namespaceUri;
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $attributes, $sortAttributes,
            $multiline, $indent, $linebreak
        );
        $element = sprintf('<%s%s>', $qname, $attList);
        return  $element;
    }

    /**
     * Create an end element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createEndElement('myNs:myTag');
     * </code>
     *
     * @param string $qname qualified tagname (including namespace)
     *
     * @return string XML end element
     * @see    createStartElement(), createTag()
     */
    public static function createEndElement($qname)
    {
        $element = sprintf('</%s>', $qname);
        return $element;
    }

    /**
     * Create an XML comment
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createComment('I am a comment');
     * </code>
     *
     * @param string $content content of the comment
     *
     * @return string XML comment
     */
    public static function createComment($content)
    {
        $comment = sprintf('<!-- %s -->', $content);
        return $comment;
    }

    /**
     * Create a CData section
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create a CData section
     * $tag = XML_Util::createCDataSection('I am content.');
     * </code>
     *
     * @param string $data data of the CData section
     *
     * @return string CData section with content
     */
    public static function createCDataSection($data)
    {
        return sprintf(
            '<![CDATA[%s]]>',
            preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data))
        );
    }

    /**
     * Split qualified name and return namespace and local part
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // split qualified tag
     * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
     * </code>
     * the returned array will contain two elements:
     * <pre>
     * array(
     *     'namespace' => 'xslt',
     *     'localPart' => 'stylesheet'
     * );
     * </pre>
     *
     * @param string $qname     qualified tag name
     * @param string $defaultNs default namespace (optional)
     *
     * @return array array containing namespace and local part
     */
    public static function splitQualifiedName($qname, $defaultNs = null)
    {
        if (strstr($qname, ':')) {
            $tmp = explode(':', $qname);
            return array(
                'namespace' => $tmp[0],
                'localPart' => $tmp[1]
            );
        }
        return array(
            'namespace' => $defaultNs,
            'localPart' => $qname
        );
    }

    /**
     * Check, whether string is valid XML name
     *
     * <p>XML names are used for tagname, attribute names and various
     * other, lesser known entities.</p>
     * <p>An XML name may only consist of alphanumeric characters,
     * dashes, undescores and periods, and has to start with a letter
     * or an underscore.</p>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // verify tag name
     * $result = XML_Util::isValidName('invalidTag?');
     * if (is_a($result, 'PEAR_Error')) {
     *    print 'Invalid XML name: ' . $result->getMessage();
     * }
     * </code>
     *
     * @param string $string string that should be checked
     *
     * @return mixed true, if string is a valid XML name, PEAR error otherwise
     *
     * @todo support for other charsets
     * @todo PEAR CS - unable to avoid 85-char limit on second preg_match
     */
    public static function isValidName($string)
    {
        // check for invalid chars
        if (!is_string($string) || !strlen($string) || !preg_match('/^[[:alpha:]_]\\z/', $string[0])) {
            return XML_Util::raiseError(
                'XML names may only start with letter or underscore',
                XML_UTIL_ERROR_INVALID_START
            );
        }

        // check for invalid chars
        $match = preg_match(
            '/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?'
            . '[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/',
            $string
        );
        if (!$match) {
            return XML_Util::raiseError(
                'XML names may only contain alphanumeric '
                . 'chars, period, hyphen, colon and underscores',
                XML_UTIL_ERROR_INVALID_CHARS
            );
        }
        // XML name is valid
        return true;
    }

    /**
     * Replacement for XML_Util::raiseError
     *
     * Avoids the necessity to always require
     * PEAR.php
     *
     * @param string $msg  error message
     * @param int    $code error code
     *
     * @return PEAR_Error
     * @todo   PEAR CS - should this use include_once instead?
     */
    public static function raiseError($msg, $code)
    {
        include_once 'PEAR.php';
        return PEAR::raiseError($msg, $code);
    }
}
?>
PK��Z#F��:�:pearcmd.phpnu�[���<?php
/**
 * PEAR, the PHP Extension and Application Repository
 *
 * Command line interface
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Stig Bakken <ssb@php.net>
 * @author    Tomas V.V.Cox <cox@idecnet.com>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 */

@ob_end_clean();
if (!defined('PEAR_RUNTYPE')) {
    // this is defined in peclcmd.php as 'pecl'
    define('PEAR_RUNTYPE', 'pear');
}
define('PEAR_IGNORE_BACKTRACE', 1);
/**
 * @nodep Gtk
 */
//the space is needed for windows include paths with trailing backslash
// http://pear.php.net/bugs/bug.php?id=19482
if ('/opt/alt/php74/usr/share/pear ' != '@'.'include_path'.'@ ') {
    ini_set('include_path', trim('/opt/alt/php74/usr/share/pear '). PATH_SEPARATOR .  get_include_path());
    $raw = false;
} else {
    // this is a raw, uninstalled pear, either a cvs checkout, or php distro
    ini_set('include_path', dirname(__DIR__) . PATH_SEPARATOR . get_include_path());
    $raw = true;
}
@ini_set('allow_url_fopen', true);
@set_time_limit(0);
ob_implicit_flush(true);
@ini_set('track_errors', true);
@ini_set('html_errors', false);
$_PEAR_PHPDIR = '#$%^&*';
set_error_handler('error_handler');

$pear_package_version = "1.10.16";

require_once 'PEAR.php';
require_once 'PEAR/Frontend.php';
require_once 'PEAR/Config.php';
require_once 'PEAR/Command.php';
require_once 'Console/Getopt.php';


PEAR_Command::setFrontendType('CLI');
$all_commands = PEAR_Command::getCommands();

$argv = Console_Getopt::readPHPArgv();
// fix CGI sapi oddity - the -- in pear.bat/pear is not removed
if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
    unset($argv[1]);
    $argv = array_values($argv);
}
$progname = PEAR_RUNTYPE;
array_shift($argv);
$options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV");
if (PEAR::isError($options)) {
    usage($options);
}

$opts = $options[0];

$fetype = 'CLI';
if ($progname == 'gpear' || $progname == 'pear-gtk') {
    $fetype = 'Gtk2';
} else {
    foreach ($opts as $opt) {
        if ($opt[0] == 'G') {
            $fetype = 'Gtk2';
        }
    }
}

$pear_user_config = '';
$pear_system_config = '';
$store_user_config = false;
$store_system_config = false;
$verbose = 1;

foreach ($opts as $opt) {
    switch ($opt[0]) {
    case 'c':
        $pear_user_config = $opt[1];
        break;
    case 'C':
        $pear_system_config = $opt[1];
        break;
    }
}

PEAR_Command::setFrontendType($fetype);
$ui = &PEAR_Command::getFrontendObject();
$config = &PEAR_Config::singleton($pear_user_config, $pear_system_config);

if (PEAR::isError($config)) {
    $_file = '';
    if ($pear_user_config !== false) {
        $_file .= $pear_user_config;
    }
    if ($pear_system_config !== false) {
        $_file .= '/' . $pear_system_config;
    }
    if ($_file == '/') {
        $_file = 'The default config file';
    }
    $config->getMessage();
    $ui->outputData("ERROR: $_file is not a valid config file or is corrupted.");
    // We stop, we have no idea where we are :)
    exit(1);
}

// this is used in the error handler to retrieve a relative path
$_PEAR_PHPDIR = $config->get('php_dir');
$ui->setConfig($config);
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError"));

$verbose = $config->get("verbose");
$cmdopts = array();

if ($raw) {
    if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) {
        $found = false;
        foreach ($opts as $opt) {
            if ($opt[0] == 'd' || $opt[0] == 'D') {
                // the user knows what they are doing, and are setting config values
                $found = true;
            }
        }
        if (!$found) {
            // no prior runs, try to install PEAR
            $parent = dirname(__FILE__);
            if (strpos($parent, 'scripts')) {
                $grandparent = dirname($parent);
                $packagexml = $grandparent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $grandparent;
            } else {
                $packagexml = $parent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $parent;
            }
            if (file_exists($packagexml)) {
                $options[1] = array(
                    'install',
                    $packagexml
                );
                $config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php');
                $config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data');
                $config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs');
                $config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests');
                $config->set(
                    'ext_dir',
                    $pearbase . DIRECTORY_SEPARATOR . 'extensions'
                );
                $config->set('bin_dir', $pearbase);
                $config->mergeConfigFile($pearbase . 'pear.ini', false);
                $config->store();
                $config->set('auto_discover', 1);
            }
        }
    }
}
foreach ($opts as $opt) {
    $param = !empty($opt[1]) ? $opt[1] : true;
    switch ($opt[0]) {
    case 'd':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected -d config_value=value, ' .
                'received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'user');
        break;
    case 'D':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'system');
        break;
    case 's':
        $store_user_config = true;
        break;
    case 'S':
        $store_system_config = true;
        break;
    case 'u':
        $config->remove($param, 'user');
        break;
    case 'v':
        $config->set('verbose', $config->get('verbose') + 1);
        break;
    case 'q':
        $config->set('verbose', $config->get('verbose') - 1);
        break;
    case 'V':
        usage(null, 'version');
    case 'c':
    case 'C':
        break;
    default:
        // all non pear params goes to the command
        $cmdopts[$opt[0]] = $param;
        break;
    }
}

if ($store_system_config) {
    $config->store('system');
}

if ($store_user_config) {
    $config->store('user');
}

$command = (isset($options[1][0])) ? $options[1][0] : null;
if (empty($command) && ($store_user_config || $store_system_config)) {
    exit;
}

if ($fetype == 'Gtk2') {
    if (!$config->validConfiguration()) {
        PEAR::raiseError(
            "CRITICAL ERROR: no existing valid configuration files found in " .
            "files '$pear_user_config' or '$pear_system_config', " .
            "please copy an existing configuration file to one of these " .
            "locations, or use the -c and -s options to create one"
        );
    }
    Gtk::main();
} else {
    do {
        if ($command == 'help') {
            usage(null, isset($options[1][1]) ? $options[1][1] : null);
        }

        if (!$config->validConfiguration()) {
            PEAR::raiseError(
                "CRITICAL ERROR: no existing valid configuration files found " .
                "in files '$pear_user_config' or '$pear_system_config', " .
                "please copy an existing configuration file to one of " .
                "these locations, or use the -c and -s options to create one"
            );
        }

        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        $cmd = PEAR_Command::factory($command, $config);
        PEAR::popErrorHandling();
        if (PEAR::isError($cmd)) {
            usage(null, isset($options[1][0]) ? $options[1][0] : null);
        }

        $short_args = $long_args = null;
        PEAR_Command::getGetoptArgs($command, $short_args, $long_args);
        array_shift($options[1]);
        $tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args);

        if (PEAR::isError($tmp)) {
            break;
        }

        list($tmpopt, $params) = $tmp;
        $opts = array();
        foreach ($tmpopt as $foo => $tmp2) {
            list($opt, $value) = $tmp2;
            if ($value === null) {
                $value = true; // options without args
            }

            if (strlen($opt) == 1) {
                $cmdoptions = $cmd->getOptions($command);
                foreach ($cmdoptions as $o => $d) {
                    if (isset($d['shortopt']) && $d['shortopt'] == $opt) {
                        $opts[$o] = $value;
                    }
                }
            } else {
                if (substr($opt, 0, 2) == '--') {
                    $opts[substr($opt, 2)] = $value;
                }
            }
        }

        $ok = $cmd->run($command, $opts, $params);
        if ($ok === false) {
            PEAR::raiseError("unknown command `$command'");
        }

        if (PEAR::isError($ok)) {
            PEAR::setErrorHandling(
                PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")
            );
            PEAR::raiseError($ok);
        }
    } while (false);
}

// {{{ usage()

/**
 * Display usage information
 *
 * @param mixed $error       Optional error message
 * @param mixed $helpsubject Optional subject/command to display help for
 *
 * @return void
 */
function usage($error = null, $helpsubject = null)
{
    global $progname, $all_commands;
    $stdout = fopen('php://stdout', 'w');
    if (PEAR::isError($error)) {
        fputs($stdout, $error->getMessage() . "\n");
    } elseif ($error !== null) {
        fputs($stdout, "$error\n");
    }

    if ($helpsubject != null) {
        $put = cmdHelp($helpsubject);
    } else {
        $put = "Commands:\n";
        $maxlen = max(array_map("strlen", $all_commands));
        $formatstr = "%-{$maxlen}s  %s\n";
        ksort($all_commands);
        foreach ($all_commands as $cmd => $class) {
            $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd));
        }
        $put .=
            "Usage: $progname [options] command [command-options] <parameters>\n".
            "Type \"$progname help options\" to list all options.\n".
            "Type \"$progname help shortcuts\" to list all command shortcuts.\n".
            "Type \"$progname help version\" or ".
            "\"$progname version\" to list version information.\n".
            "Type \"$progname help <command>\" to get the help ".
            "for the specified command.";
    }
    fputs($stdout, "$put\n");
    fclose($stdout);

    if ($error === null) {
        exit(0);
    }
    exit(1);
}

/**
 * Return help string for specified command
 *
 * @param string $command Command to return help for
 *
 * @return void
 */
function cmdHelp($command)
{
    global $progname, $all_commands, $config;
    if ($command == "options") {
        return
        "Options:\n".
        "     -v         increase verbosity level (default 1)\n".
        "     -q         be quiet, decrease verbosity level\n".
        "     -c file    find user configuration in `file'\n".
        "     -C file    find system configuration in `file'\n".
        "     -d foo=bar set user config variable `foo' to `bar'\n".
        "     -D foo=bar set system config variable `foo' to `bar'\n".
        "     -G         start in graphical (Gtk) mode\n".
        "     -s         store user configuration\n".
        "     -S         store system configuration\n".
        "     -u foo     unset `foo' in the user configuration\n".
        "     -h, -?     display help/usage (this message)\n".
        "     -V         version information\n";
    } elseif ($command == "shortcuts") {
        $sc = PEAR_Command::getShortcuts();
        $ret = "Shortcuts:\n";
        foreach ($sc as $s => $c) {
            $ret .= sprintf("     %-8s %s\n", $s, $c);
        }
        return $ret;

    } elseif ($command == "version") {
        return "PEAR Version: ".$GLOBALS['pear_package_version'].
               "\nPHP Version: ".phpversion().
               "\nZend Engine Version: ".zend_version().
               "\nRunning on: ".php_uname();

    } elseif ($help = PEAR_Command::getHelp($command)) {
        if (is_string($help)) {
            return "$progname $command [options] $help\n";
        }

        if ($help[1] === null) {
            return "$progname $command $help[0]";
        }

        return "$progname $command [options] $help[0]\n$help[1]";
    }

    return "Command '$command' is not valid, try '$progname help'";
}

// }}}

/**
 * error_handler
 *
 * @param mixed $errno  Error number
 * @param mixed $errmsg Message
 * @param mixed $file   Filename
 * @param mixed $line   Line number
 *
 * @access public
 * @return boolean
 */
function error_handler($errno, $errmsg, $file, $line)
{
    if ((!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) && ($errno & E_STRICT)) {
        return; // E_STRICT
    }
    if ($errno & E_DEPRECATED) {
        return; // E_DEPRECATED
    }
    if (!(error_reporting() & $errno) &&
        isset($GLOBALS['config']) &&
        $GLOBALS['config']->get('verbose') < 4
    ) {
        return false; // @silenced error, show all if debug is high enough
    }
    $errortype = array (
        E_DEPRECATED  => 'Deprecated Warning',
        E_ERROR   =>  "Error",
        E_WARNING   =>  "Warning",
        E_PARSE   =>  "Parsing Error",
        E_NOTICE   =>  "Notice",
        E_CORE_ERROR  =>  "Core Error",
        E_CORE_WARNING  =>  "Core Warning",
        E_COMPILE_ERROR  =>  "Compile Error",
        E_COMPILE_WARNING =>  "Compile Warning",
        E_USER_ERROR =>  "User Error",
        E_USER_WARNING =>  "User Warning",
        E_USER_NOTICE =>  "User Notice"
    );
    if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) {
        $errortype[E_STRICT] = 'Strict Warning';
    }
    $prefix = $errortype[$errno];
    global $_PEAR_PHPDIR;
    if (stristr($file, $_PEAR_PHPDIR)) {
        $file = substr($file, strlen($_PEAR_PHPDIR) + 1);
    } else {
        $file = basename($file);
    }
    print "\n$prefix: $errmsg in $file on line $line\n";
    return false;
}


/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * indent-tabs-mode: nil
 * mode: php
 * End:
 */
// vim600:syn=php
PK��Z�0$�-- .pkgxml/Pear_File_MARC-1.4.1.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.10.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
 <name>File_MARC</name>
 <channel>pear.php.net</channel>
 <summary>Parse, modify, and create MARC records</summary>
 <description>The standard for machine-readable cataloging (MARC) records is documented at http://loc.gov/marc/. This package enables you to read existing MARC records from a file, string, or (using the YAZ extension), from a Z39.50 source. You can also use this package to create new MARC records.

This package is based on the PHP MARC package, originally called &quot;php-marc&quot;, that is part of the Emilda Project (http://www.emilda.org).  Christoffer Landtman generously agreed to make the &quot;php-marc&quot; code available under the GNU LGPL so it could be used as the basis of this PEAR package.</description>
 <lead>
  <name>Dan Scott</name>
  <user>dbs</user>
  <email>dbs@php.net</email>
  <active>yes</active>
 </lead>
 <date>2019-11-13</date>
 <time>17:33:33</time>
 <version>
  <release>1.4.1</release>
  <api>1.4.0</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license uri="http://www.gnu.org/copyleft/lesser.html">GNU Lesser General Public License</license>
 <notes>
1.4.1
  * Reintroduce include_path to composer.json
 </notes>
 <contents>
  <dir baseinstalldir="File" name="/">
   <file baseinstalldir="/" md5sum="ffe2590635f404af055fe731da105939" name="File/MARC/Lint/CodeData.php" role="php" />
   <file baseinstalldir="/" md5sum="a3b9e1c817e67f59add05593500d463e" name="File/MARC/Control_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="acba4463f8e40d6ee4e7ba1f2dc53123" name="File/MARC/Data_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="378f483ec1fd161cd9dfb9b05db58d66" name="File/MARC/Exception.php" role="php" />
   <file baseinstalldir="/" md5sum="a9ba69030cbf4847292b9975e9d922c6" name="File/MARC/Field.php" role="php" />
   <file baseinstalldir="/" md5sum="c37351c7c80927ce6bb1e662510f9183" name="File/MARC/Lint.php" role="php" />
   <file baseinstalldir="/" md5sum="c5ac39e3d25eb0108b9dd5ad8466c821" name="File/MARC/List.php" role="php" />
   <file baseinstalldir="/" md5sum="7af6ce78cde4bb246e4e96709e90d2c0" name="File/MARC/Record.php" role="php" />
   <file baseinstalldir="/" md5sum="df5f97139685f0ad04e47fdbb67e3968" name="File/MARC/Subfield.php" role="php" />
   <file baseinstalldir="/" md5sum="6e102262dfd5d65d8d5a6221dfc74edd" name="File/MARC.php" role="php" />
   <file baseinstalldir="/" md5sum="8b64040d2d18ac4b994595a148266a66" name="File/MARCBASE.php" role="php" />
   <file baseinstalldir="/" md5sum="f5a17a60d34e84e2ee7ca1e5c5c6c620" name="File/MARCXML.php" role="php" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="examples/example.mrc" role="doc" />
   <file baseinstalldir="File" md5sum="1aea40df9f1c2e32f8e065fe8da0a3b5" name="examples/marc_yaz.php" role="doc" />
   <file baseinstalldir="File" md5sum="70ae317e0890d5896e3ffccdd293369a" name="examples/read.php" role="doc" />
   <file baseinstalldir="File" md5sum="54efb9d920ac775bfc847a83a2dec73a" name="examples/subfields.php" role="doc" />
   <file baseinstalldir="File" md5sum="14297da35b510c496cd1f328cf3bb301" name="tests/bad_example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="0dd4c6dbad6e8608d0ebf9d24425955d" name="tests/bad_example.xml" role="test" />
   <file baseinstalldir="File" md5sum="216a6f9d53f6d3d8e22d81fdc10f4bc1" name="tests/camel.mrc" role="test" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="tests/example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="9455aec3371f79cf7d31281fd03f5171" name="tests/marc_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="577e2f5f89fd48cf1a3576a29d2958f8" name="tests/marc_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a6a586354b9a06c880c2a7470dd828d7" name="tests/marc_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1c7e2fc5572a0f9362a771c260a1fe3" name="tests/marc_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="84f85ac7f8a2532e4e90ccde7764556a" name="tests/marc_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="889e5e906a97de7a0e94b0c5f30e70e7" name="tests/marc_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="be823dc8a8efb408de06371ab802efcc" name="tests/marc_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="af44490aafea44e5120f881cb81cdad9" name="tests/marc_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ac9f2a7aeb24900a11f5102744179ae3" name="tests/marc_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5e43eb5cddbb4f2bd0d6405cd95b80aa" name="tests/marc_010.phpt" role="test" />
   <file baseinstalldir="File" md5sum="2e1cd8509c0bf04ec77fc0f51375f611" name="tests/marc_011.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bc49ca48623102c8ac07679fa77a3dd9" name="tests/marc_012.phpt" role="test" />
   <file baseinstalldir="File" md5sum="245a3b20e0da1973535503e28efd1d3a" name="tests/marc_013.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ce69aa734856dd40d60d30c77bdef53a" name="tests/marc_014.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7b61cdd31035e60682fa92c5d519d997" name="tests/marc_015.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7f4f597fe1adaa3507eb87fc4875dbd2" name="tests/marc_016.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4262efd5fcacbd7503323681f4552430" name="tests/marc_017.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ee1623d7bda54ba4f741b2319b158f82" name="tests/marc_018.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8006c03fbab0f04377342086fafd3982" name="tests/marc_019.phpt" role="test" />
   <file baseinstalldir="File" md5sum="f5ae5b25e0ac1104314433d9e5b1f7fe" name="tests/marc_020.phpt" role="test" />
   <file baseinstalldir="File" md5sum="94d8f99e86585671a1b2d3043aeb6360" name="tests/marc_021.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bb891a890effe0e77e1759043f4846d8" name="tests/marc_022.phpt" role="test" />
   <file baseinstalldir="File" md5sum="faf77dcb5cdd002c09169a14bfded65e" name="tests/marc_023.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0e6c4a23f5da7df64fdd4b3b1149bbee" name="tests/marc_16783.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4ea8b3520beda378db15960f1c50493a" name="tests/marc_field_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="743850ef61df69c4340be44a03bccb5a" name="tests/marc_field_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8c765f1398b49df257d86d22ac6e4f8d" name="tests/marc_field_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d4216cf930a308e0d02553bd3914f294" name="tests/marc_field_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dd59514b474b78371ad522a3e13b76b7" name="tests/marc_field_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5295bfd02a8424acac1c91de26b552c7" name="tests/marc_field_21246.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6f95f09442ccf6b93df92986f58b270d" name="tests/marc_lint_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="18d721f8871edd925624ccbdd15444fb" name="tests/marc_lint_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4eb86a2f4e0a74dedcb0bf2511da6ca1" name="tests/marc_lint_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="10430fee0a1352d0528f1507b34c57e1" name="tests/marc_lint_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0dcd07a18577d7b22392a2214cd6436c" name="tests/marc_lint_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fd17798fc535562e5e64461f449516b2" name="tests/marc_record_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="141b455ccf67a60c4eac44c77960f2e2" name="tests/marc_subfield_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1e23464ee0eec47ddca2af9a9922926" name="tests/marc_subfield_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="1d7903e8c244d647220b318b4bc758d1" name="tests/marc_xml_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="22cae3c752d843b78f583dcd92801534" name="tests/marc_xml_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="c0716d23e0f960abf8d53ad6014a413a" name="tests/marc_xml_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7645fa19e28aca041a124fc5e2c12bd3" name="tests/marc_xml_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b08b28c3251625b8b6e4d7ab376b0185" name="tests/marc_xml_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6cd0934ddbf65d2d7e9ea5d108977ff7" name="tests/marc_xml_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ffdce4aa190268fa7cbbf3bb45383abf" name="tests/marc_xml_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="998a4c1ce00ff100f39ffa9fc49a212f" name="tests/marc_xml_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a38a67c590869f2b0a4859a910fd9e89" name="tests/marc_xml_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="db39c5055a570fcda12bb7c5fa1e3b4d" name="tests/marc_xml_16642.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dc075f4a271bd7182378a3874bd5b39e" name="tests/marc_xml_namespace.phpt" role="test" />
   <file baseinstalldir="File" md5sum="208200d9a979ac360c4d326e9789b6b7" name="tests/marc_xml_namespace_prefix.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d87774ede82222cfc12b2c2a06f57a3a" name="tests/marc_xml_rsinger.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fb44e3eb69f1a37115235fc829c39542" name="tests/namespace.xml" role="test" />
   <file baseinstalldir="File" md5sum="e6de4d809b0af5dd99fd352eb60616a1" name="tests/skipif.inc" role="test" />
   <file baseinstalldir="File" md5sum="a0166a4ff0bc0bb283e854f11beaa793" name="tests/music.mrc" role="test" />
   <file baseinstalldir="File" md5sum="993ce494befbc25dc1326527b30b4782" name="tests/music.xml" role="test" />
   <file baseinstalldir="File" md5sum="6b0c87f0cd459ed7322c25d403b164cc" name="tests/bigarchive.xml" role="test" />
   <file baseinstalldir="File" md5sum="be850aa6ab4ac52b8c6c214c30b574af" name="tests/onerecord.xml" role="test" />
   <file baseinstalldir="File" md5sum="4f43fec7b276267eec5258044853ccc8" name="tests/sandburg.mrc" role="test" />
   <file baseinstalldir="File" md5sum="e216b95f905dd240c9bde372950e4073" name="tests/sandburg.xml" role="test" />
   <file baseinstalldir="File" md5sum="e81a92188ea0dcd9c108a63fb32b3f4f" name="tests/xmlescape.mrc" role="test" />
   <file baseinstalldir="File" md5sum="8f9f63ed6a80191d89a2296fa4c1a30b" name="CHANGELOG" role="doc" />
   <file baseinstalldir="File" md5sum="fbc093901857fcd118f065f900982c24" name="LICENSE" role="doc" />
  </dir>
 </contents>
 <dependencies>
  <required>
   <php>
    <min>5.6</min>
   </php>
   <pearinstaller>
    <min>1.4.0</min>
   </pearinstaller>
  </required>
  <optional>
   <package>
    <name>Validate_ISPN</name>
    <channel>pear.php.net</channel>
   </package>
  </optional>
 </dependencies>
 <phprelease />
</package>
PKm�ZPi��.depdbnu�[���PKm�Z�{��
�Mail/null.phpnu�[���PKm�ZE@�%>>
Mail/sendmail.phpnu�[���PKm�Z��A~�{�{�;Mail/RFC822.phpnu�[���PKn�Z�+V����
[�Mail/mime.phpnu�[���PKn�Zx�ع���D�Mail/mimeDecode.phpnu�[���PKn�ZB�_Ǭ=�=
@(Mail/smtp.phpnu�[���PKn�ZwԐE;E;)fMail/smtpmx.phpnu�[���PKn�Z�؛�J�J���Mail/mimePart.phpnu�[���PKn�ZB��shh
8YMail/mock.phpnu�[���PKn�Z@iE�\\
�lMail/mail.phpnu�[���PKn�Zv�.locknu�[���PKn�Z�*�z%-%- ��Structures/LinkedList/Double.phpnu�[���PKn�Z����p:p:  �Structures/LinkedList/Single.phpnu�[���PKn�ZUyv���Structures/Graph.phpnu�[���PKn�Z�C� + +CStructures/Graph/Node.phpnu�[���PKn�Z9����,�1Structures/Graph/Manipulator/AcyclicTest.phpnu�[���PKn�Z~(�htt2�HStructures/Graph/Manipulator/TopologicalSorter.phpnu�[���PKn�Z�J�}
}
_dAuth/SASL/Anonymous.phpnu�[���PKn�ZP(~�T
T
#rAuth/SASL/CramMD5.phpnu�[���PKn�Z����==�Auth/SASL/Plain.phpnu�[���PKn�Z�<� OO<�Auth/SASL/Login.phpnu�[���PKn�Z%ׅtg!g!ΘAuth/SASL/DigestMD5.phpnu�[���PKn�Z�T�|�Auth/SASL/Common.phpnu�[���PKn�ZvR�r,,��Auth/SASL/External.phpnu�[���PKn�Zќ��0�0H�Auth/SASL/SCRAM.phpnu�[���PKn�Z2r����
�	Auth/SASL.phpnu�[���PKn�Z�T�,�,�OS/Guess.phpnu�[���PKn�Z�����KPEAR/Config.phpnu�[���PKn�Z�`�eEAEA
.ZPEAR/REST.phpnu�[���PKn�Z��ym6m6��PEAR/Exception.phpnu�[���PKn�Zr"����_�PEAR/ChannelFile.phpnu�[���PKn�Z��gk�U�U?�PEAR/Validate.phpnu�[���PKn�Zd֣S��u�PEAR/Command/Pickle.xmlnu�[���PKn�Z�z��k<k<W�PEAR/Command/Config.phpnu�[���PKn�Z݄<ii	1PEAR/Command/Mirror.xmlnu�[���PKn�Z,��t"u"u�3PEAR/Command/Remote.phpnu�[���PKn�Z
�\���"�PEAR/Command/Remote.xmlnu�[���PKn�Zj���!�!X�PEAR/Command/Install.xmlnu�[���PKo�Z�%q������PEAR/Command/Channels.phpnu�[���PKo�Znmi?;�;��[	PEAR/Command/Install.phpnu�[���PKo�Z�X�

#
PEAR/Command/Auth.phpnu�[���PKo�Z���s6
6
T-
PEAR/Command/Config.xmlnu�[���PKo�Z�%Fii�:
PEAR/Command/Test.xmlnu�[���PKo�ZZ h66A
PEAR/Command/Package.xmlnu�[���PKo�Z�w��zz�]
PEAR/Command/Channels.xmlnu�[���PKo�Z+9ҜҜ�n
PEAR/Command/Package.phpnu�[���PKo�Z
u����PEAR/Command/Build.xmlnu�[���PKo�Z������
PEAR/Command/Mirror.phpnu�[���PKp�Z,_�h/h/�PEAR/Command/Test.phpnu�[���PKp�Z�%sp  6OPEAR/Command/Common.phpnu�[���PKp�Z0(;rʹʹ�oPEAR/Command/Registry.phpnu�[���PKp�Z�4�{���$PEAR/Command/Auth.xmlnu�[���PKp�Z��#S
S
�)PEAR/Command/Build.phpnu�[���PKp�Z���u��S4PEAR/Command/Registry.xmlnu�[���PKp�Z�P>>�;PEAR/Command/Pickle.phpnu�[���PKp�Z��T�I�I�yPEAR/Builder.phpnu�[���PKp�Z[
�W��3�PEAR/XMLParser.phpnu�[���PKp�Zl(e���t�PEAR/Downloader.phpnu�[���PKp�Z�b������
PEAR/ErrorStack.phpnu�[���PKp�Z(Pz����ePEAR/Proxy.phpnu�[���PKp�Z��'����|PEAR/RunTest.phpnu�[���PKq�Zj�y99�	PEAR/Validator/PECL.phpnu�[���PKq�Zp�����aPEAR/Dependency2.phpnu�[���PKq�Z��wv@@��PEAR/PackageFile/v2.phpnu�[���PKq�ZC�8�L�L!:�PEAR/PackageFile/v2/Validator.phpnu�[���PKq�Z���=_�_�6PEAR/PackageFile/v2/rw.phpnu�[���PKq�Z�5�������,PEAR/PackageFile/v1.phpnu�[���PKq�Z�ɁɁ!��PEAR/PackageFile/Generator/v2.phpnu�[���PKq�Z`�=����!�tPEAR/PackageFile/Generator/v1.phpnu�[���PKr�Z��OWHH�9PEAR/PackageFile/Parser/v2.phpnu�[���PKr�Z�_=�@�@`FPEAR/PackageFile/Parser/v1.phpnu�[���PKr�Zc��__5�PEAR/DependencyDB.phpnu�[���PKr�Z�@P��{�PEAR/ChannelFile/Parser.phpnu�[���PKr�Z��_�0�0r�PEAR/Command.phpnu�[���PKr�Z�ٲ�=�==PEAR/PackageFile.phpnu�[���PKr�Z�JD��g\PEAR/Task/Replace.phpnu�[���PKr�Z&%75))�wPEAR/Task/Windowseol/rw.phpnu�[���PKr�Z�3}}PEAR/Task/Replace/rw.phpnu�[���PKr�Z&
i."x�PEAR/Task/Postinstallscript/rw.phpnu�[���PKr�Z�-!�PEAR/Task/Common.phpnu�[���PKr�ZD$���I�PEAR/Task/Windowseol.phpnu�[���PKr�ZZ�E�x9x9��PEAR/Task/Postinstallscript.phpnu�[���PKr�Z\k��K�PEAR/Task/Unixeol/rw.phpnu�[���PKr�Z�������PEAR/Task/Unixeol.phpnu�[���PKr�Z�W�f���PEAR/REST/10.phpnu�[���PKr�Z��Y�;;ąPEAR/REST/13.phpnu�[���PKr�Z,#y��+�+�PEAR/REST/11.phpnu�[���PKr�Z��U  D�PEAR/Packager.phpnu�[���PKr�ZZ�bgbg�PEAR/Common.phpnu�[���PKr�Z$���(�(FsPEAR/Registry.phpnu�[���PKr�Z��	MdMd?�PEAR/Frontend/CLI.phpnu�[���PKr�Z��

�PEAR/Installer/Role/Doc.phpnu�[���PKr�Z��/��)PEAR/Installer/Role/Cfg.xmlnu�[���PKr�Z>1H���PK��Z����/�/�2.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUri   URI of the namespace
     * @param bool   $multiline      whether to create a multiline tag where each
     *                               attribute gets written to a single line
     * @param string $indent         string used to indent attributes (_auto indents
     *                               attributes so they start at the same column)
     * @param string $linebreak      string used for linebreaks
     * @param bool   $sortAttributes Whether to sort the attributes or not
     *
     * @return string XML start element
     * @see    createEndElement(), createTag()
     */
    public static function createStartElement(
        $qname, $attributes = array(), $namespaceUri = null,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true
    ) {
        // if no attributes hav been set, use empty attributes
        if (!isset($attributes) || !is_array($attributes)) {
            $attributes = array();
        }

        if ($namespaceUri != null) {
            $parts = XML_Util::splitQualifiedName($qname);
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($qname)+2));
            }
        }

        if ($namespaceUri != null) {
            // is a namespace given
            if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
            } else {
                // define this Uri as the default namespace
                $attributes['xmlns'] = $namespaceUri;
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $attributes, $sortAttributes,
            $multiline, $indent, $linebreak
        );
        $element = sprintf('<%s%s>', $qname, $attList);
        return  $element;
    }

    /**
     * Create an end element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createEndElement('myNs:myTag');
     * </code>
     *
     * @param string $qname qualified tagname (including namespace)
     *
     * @return string XML end element
     * @see    createStartElement(), createTag()
     */
    public static function createEndElement($qname)
    {
        $element = sprintf('</%s>', $qname);
        return $element;
    }

    /**
     * Create an XML comment
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createComment('I am a comment');
     * </code>
     *
     * @param string $content content of the comment
     *
     * @return string XML comment
     */
    public static function createComment($content)
    {
        $comment = sprintf('<!-- %s -->', $content);
        return $comment;
    }

    /**
     * Create a CData section
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create a CData section
     * $tag = XML_Util::createCDataSection('I am content.');
     * </code>
     *
     * @param string $data data of the CData section
     *
     * @return string CData section with content
     */
    public static function createCDataSection($data)
    {
        return sprintf(
            '<![CDATA[%s]]>',
            preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data))
        );
    }

    /**
     * Split qualified name and return namespace and local part
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // split qualified tag
     * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
     * </code>
     * the returned array will contain two elements:
     * <pre>
     * array(
     *     'namespace' => 'xslt',
     *     'localPart' => 'stylesheet'
     * );
     * </pre>
     *
     * @param string $qname     qualified tag name
     * @param string $defaultNs default namespace (optional)
     *
     * @return array array containing namespace and local part
     */
    public static function splitQualifiedName($qname, $defaultNs = null)
    {
        if (strstr($qname, ':')) {
            $tmp = explode(':', $qname);
            return array(
                'namespace' => $tmp[0],
                'localPart' => $tmp[1]
            );
        }
        return array(
            'namespace' => $defaultNs,
            'localPart' => $qname
        );
    }

    /**
     * Check, whether string is valid XML name
     *
     * <p>XML names are used for tagname, attribute names and various
     * other, lesser known entities.</p>
     * <p>An XML name may only consist of alphanumeric characters,
     * dashes, undescores and periods, and has to start with a letter
     * or an underscore.</p>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // verify tag name
     * $result = XML_Util::isValidName('invalidTag?');
     * if (is_a($result, 'PEAR_Error')) {
     *    print 'Invalid XML name: ' . $result->getMessage();
     * }
     * </code>
     *
     * @param string $string string that should be checked
     *
     * @return mixed true, if string is a valid XML name, PEAR error otherwise
     *
     * @todo support for other charsets
     * @todo PEAR CS - unable to avoid 85-char limit on second preg_match
     */
    public static function isValidName($string)
    {
        // check for invalid chars
        if (!is_string($string) || !strlen($string) || !preg_match('/^[[:alpha:]_]\\z/', $string[0])) {
            return XML_Util::raiseError(
                'XML names may only start with letter or underscore',
                XML_UTIL_ERROR_INVALID_START
            );
        }

        // check for invalid chars
        $match = preg_match(
            '/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?'
            . '[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/',
            $string
        );
        if (!$match) {
            return XML_Util::raiseError(
                'XML names may only contain alphanumeric '
                . 'chars, period, hyphen, colon and underscores',
                XML_UTIL_ERROR_INVALID_CHARS
            );
        }
        // XML name is valid
        return true;
    }

    /**
     * Replacement for XML_Util::raiseError
     *
     * Avoids the necessity to always require
     * PEAR.php
     *
     * @param string $msg  error message
     * @param int    $code error code
     *
     * @return PEAR_Error
     * @todo   PEAR CS - should this use include_once instead?
     */
    public static function raiseError($msg, $code)
    {
        include_once 'PEAR.php';
        return PEAR::raiseError($msg, $code);
    }
}
?>
PK��Z#F��:�:pearcmd.phpnu�[���<?php
/**
 * PEAR, the PHP Extension and Application Repository
 *
 * Command line interface
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Stig Bakken <ssb@php.net>
 * @author    Tomas V.V.Cox <cox@idecnet.com>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 */

@ob_end_clean();
if (!defined('PEAR_RUNTYPE')) {
    // this is defined in peclcmd.php as 'pecl'
    define('PEAR_RUNTYPE', 'pear');
}
define('PEAR_IGNORE_BACKTRACE', 1);
/**
 * @nodep Gtk
 */
//the space is needed for windows include paths with trailing backslash
// http://pear.php.net/bugs/bug.php?id=19482
if ('/opt/alt/php74/usr/share/pear ' != '@'.'include_path'.'@ ') {
    ini_set('include_path', trim('/opt/alt/php74/usr/share/pear '). PATH_SEPARATOR .  get_include_path());
    $raw = false;
} else {
    // this is a raw, uninstalled pear, either a cvs checkout, or php distro
    ini_set('include_path', dirname(__DIR__) . PATH_SEPARATOR . get_include_path());
    $raw = true;
}
@ini_set('allow_url_fopen', true);
@set_time_limit(0);
ob_implicit_flush(true);
@ini_set('track_errors', true);
@ini_set('html_errors', false);
$_PEAR_PHPDIR = '#$%^&*';
set_error_handler('error_handler');

$pear_package_version = "1.10.16";

require_once 'PEAR.php';
require_once 'PEAR/Frontend.php';
require_once 'PEAR/Config.php';
require_once 'PEAR/Command.php';
require_once 'Console/Getopt.php';


PEAR_Command::setFrontendType('CLI');
$all_commands = PEAR_Command::getCommands();

$argv = Console_Getopt::readPHPArgv();
// fix CGI sapi oddity - the -- in pear.bat/pear is not removed
if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
    unset($argv[1]);
    $argv = array_values($argv);
}
$progname = PEAR_RUNTYPE;
array_shift($argv);
$options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV");
if (PEAR::isError($options)) {
    usage($options);
}

$opts = $options[0];

$fetype = 'CLI';
if ($progname == 'gpear' || $progname == 'pear-gtk') {
    $fetype = 'Gtk2';
} else {
    foreach ($opts as $opt) {
        if ($opt[0] == 'G') {
            $fetype = 'Gtk2';
        }
    }
}

$pear_user_config = '';
$pear_system_config = '';
$store_user_config = false;
$store_system_config = PK��Z��m�(�(7.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as dPK��ZN�� ��..registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUri   URI of the namespace
     * @param bool   $multiline      whether to create a multiline tag where each
     *                               attribute gets written to a single line
     * @param string $indent         string used to indent attributes (_auto indents
     *                               attributes so they start at the same column)
     * @param string $linebreak      string used for linebreaks
     * @param bool   $sortAttributes Whether to sort the attributes or not
     *
     * @return string XML start element
     * @see    createEndElement(), createTag()
     */
    public static function createStartElement(
        $qname, $attributes = array(), $namespaceUri = null,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true
    ) {
        // if no attributes hav been set, use empty attributes
        if (!isset($attributes) || !is_array($attributes)) {
            $attributes = array();
        }

        if ($namespaceUri != null) {
            $parts = XML_Util::splitQualifiedName($qname);
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($qname)+2));
            }
        }

        if ($namespaceUri != null) {
            // is a namespace given
            if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
            } else {
                // define this Uri as the default namespace
                $attributes['xmlns'] = $namespaceUri;
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $attributes, $sortAttributes,
            $multiline, $indent, $linebreak
        );
        $element = sprintf('<%s%s>', $qname, $attList);
        return  $element;
    }

    /**
     * Create an end element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createEndElement('myNs:myTag');
     * </code>
     *
     * @param string $qname qualified tagname (including namespace)
     *
     * @return string XML end element
     * @see    createStartElement(), createTag()
     */
    public static function createEndElement($qname)
    {
        $element = sprintf('</%s>', $qname);
        return $element;
    }

    /**
     * Create an XML comment
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createComment('I am a comment');
     * </code>
     *
     * @param string $content content of the comment
     *
     * @return string XML comment
     */
    public static function createComment($content)
    {
        $comment = sprintf('<!-- %s -->', $content);
        return $comment;
    }

    /**
     * Create a CData section
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create a CData section
     * $tag = XML_Util::createCDataSection('I am content.');
     * </code>
     *
     * @param string $data data of the CData section
     *
     * @return string CData section with content
     */
    public static function createCDataSection($data)
    {
        return sprintf(
            '<![CDATA[%s]]>',
            preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data))
        );
    }

    /**
     * Split qualified name and return namespace and local part
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // split qualified tag
     * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
     * </code>
     * the returned array will contain two elements:
     * <pre>
     * array(
     *     'namespace' => 'xslt',
     *     'localPart' => 'stylesheet'
     * );
     * </pre>
     *
     * @param string $qname     qualified tag name
     * @param string $defaultNs default namespace (optional)
     *
     * @return array array containing namespace and local part
     */
    public static function splitQualifiedName($qname, $defaultNs = null)
    {
        if (strstr($qname, ':')) {
            $tmp = explode(':', $qname);
            return array(
                'namespace' => $tmp[0],
                'localPart' => $tmp[1]
            );
        }
        return array(
            'namespace' => $defaultNs,
            'localPart' => $qname
        );
    }

    /**
     * Check, whether string is valid XML name
     *
     * <p>XML names are used for tagname, attribute names and various
     * other, lesser known entities.</p>
     * <p>An XML name may only consist of alphanumeric characters,
     * dashes, undescores and periods, and has to start with a letter
     * or an underscore.</p>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // verify tag name
     * $result = XML_Util::isValidName('invalidTag?');
     * if (is_a($result, 'PEAR_Error')) {
     *    print 'Invalid XML name: ' . $result->getMessage();
     * }
     * </code>
     *
     * @param string $string string that should be checked
     *
     * @return mixed true, if string is a valid XML name, PEAR error otherwise
     *
     * @todo support for other charsets
     * @todo PEAR CS - unable to avoid 85-char limit on second preg_match
     */
    public static function isValidName($string)
    {
        // check for invalid chars
        if (!is_string($string) || !strlen($string) || !preg_match('/^[[:alpha:]_]\\z/', $string[0])) {
            return XML_Util::raiseError(
                'XML names may only start with letter or underscore',
                XML_UTIL_ERROR_INVALID_START
            );
        }

        // check for invalid chars
        $match = preg_match(
            '/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?'
            . '[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/',
            $string
        );
        if (!$match) {
            return XML_Util::raiseError(
                'XML names may only contain alphanumeric '
                . 'chars, period, hyphen, colon and underscores',
                XML_UTIL_ERROR_INVALID_CHARS
            );
        }
        // XML name is valid
        return true;
    }

    /**
     * Replacement for XML_Util::raiseError
     *
     * Avoids the necessity to always require
     * PEAR.php
     *
     * @param string $msg  error message
     * @param int    $code error code
     *
     * @return PEAR_Error
     * @todo   PEAR CS - should this use include_once instead?
     */
    public static function raiseError($msg, $code)
    {
        include_once 'PEAR.php';
        return PEAR::raiseError($msg, $code);
    }
}
?>
PK��Z#F��:�:pearcmd.phpnu�[���<?php
/**
 * PEAR, the PHP Extension and Application Repository
 *
 * Command line interface
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Stig Bakken <ssb@php.net>
 * @author    Tomas V.V.Cox <cox@idecnet.com>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 */

@ob_end_clean();
if (!defined('PEAR_RUNTYPE')) {
    // this is defined in peclcmd.php as 'pecl'
    define('PEAR_RUNTYPE', 'pear');
}
define('PEAR_IGNORE_BACKTRACE', 1);
/**
 * @nodep Gtk
 */
//the space is needed for windows include paths with trailing backslash
// http://pear.php.net/bugs/bug.php?id=19482
if ('/opt/alt/php74/usr/share/pear ' != '@'.'include_path'.'@ ') {
    ini_set('include_path', trim('/opt/alt/php74/usr/share/pear '). PATH_SEPARATOR .  get_include_path());
    $raw = false;
} else {
    // this is a raw, uninstalled pear, either a cvs checkout, or php distro
    ini_set('include_path', dirname(__DIR__) . PATH_SEPARATOR . get_include_path());
    $raw = true;
}
@ini_set('allow_url_fopen', true);
@set_time_limit(0);
ob_implicit_flush(true);
@ini_set('track_errors', true);
@ini_set('html_errors', false);
$_PEAR_PHPDIR = '#$%^&*';
set_error_handler('error_handler');

$pear_package_version = "1.10.16";

require_once 'PEAR.php';
require_once 'PEAR/Frontend.php';
require_once 'PEAR/Config.php';
require_once 'PEAR/Command.php';
require_once 'Console/Getopt.php';


PEAR_Command::setFrontendType('CLI');
$all_commands = PEAR_Command::getCommands();

$argv = Console_Getopt::readPHPArgv();
// fix CGI sapi oddity - the -- in pear.bat/pear is not removed
if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
    unset($argv[1]);
    $argv = array_values($argv);
}
$progname = PEAR_RUNTYPE;
array_shift($argv);
$options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV");
if (PEAR::isError($options)) {
    usage($options);
}

$opts = $options[0];

$fetype = 'CLI';
if ($progname == 'gpear' || $progname == 'pear-gtk') {
    $fetype = 'Gtk2';
} else {
    foreach ($opts as $opt) {
        if ($opt[0] == 'G') {
            $fetype = 'Gtk2';
        }
    }
}

$pear_user_config = '';
$pear_system_config = '';
$store_user_config = false;
$store_system_config = false;
$verbose = 1;

foreach ($opts as $opt) {
    switch ($opt[0]) {
    case 'c':
        $pear_user_config = $opt[1];
        break;
    case 'C':
        $pear_system_config = $opt[1];
        break;
    }
}

PEAR_Command::setFrontendType($fetype);
$ui = &PEAR_Command::getFrontendObject();
$config = &PEAR_Config::singleton($pear_user_config, $pear_system_config);

if (PEAR::isError($config)) {
    $_file = '';
    if ($pear_user_config !== false) {
        $_file .= $pear_user_config;
    }
    if ($pear_system_config !== false) {
        $_file .= '/' . $pear_system_config;
    }
    if ($_file == '/') {
        $_file = 'The default config file';
    }
    $config->getMessage();
    $ui->outputData("ERROR: $_file is not a valid config file or is corrupted.");
    // We stop, we have no idea where we are :)
    exit(1);
}

// this is used in the error handler to retrieve a relative path
$_PEAR_PHPDIR = $config->get('php_dir');
$ui->setConfig($config);
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError"));

$verbose = $config->get("verbose");
$cmdopts = array();

if ($raw) {
    if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) {
        $found = false;
        foreach ($opts as $opt) {
            if ($opt[0] == 'd' || $opt[0] == 'D') {
                // the user knows what they are doing, and are setting config values
                $found = true;
            }
        }
        if (!$found) {
            // no prior runs, try to install PEAR
            $parent = dirname(__FILE__);
            if (strpos($parent, 'scripts')) {
                $grandparent = dirname($parent);
                $packagexml = $grandparent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $grandparent;
            } else {
                $packagexml = $parent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $parent;
            }
            if (file_exists($packagexml)) {
                $options[1] = array(
                    'install',
                    $packagexml
                );
                $config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php');
                $config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data');
                $config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs');
                $config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests');
                $config->set(
                    'ext_dir',
                    $pearbase . DIRECTORY_SEPARATOR . 'extensions'
                );
                $config->set('bin_dir', $pearbase);
                $config->mergeConfigFile($pearbase . 'pear.ini', false);
                $config->store();
                $config->set('auto_discover', 1);
            }
        }
    }
}
foreach ($opts as $opt) {
    $param = !empty($opt[1]) ? $opt[1] : true;
    switch ($opt[0]) {
    case 'd':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected -d config_value=value, ' .
                'received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'user');
        break;
    case 'D':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'system');
        break;
    case 's':
        $store_user_config = true;
        break;
    case 'S':
        $store_system_config = true;
        break;
    case 'u':
        $config->remove($param, 'user');
        break;
    case 'v':
        $config->set('verbose', $config->get('verbose') + 1);
        break;
    case 'q':
        $config->set('verbose', $config->get('verbose') - 1);
        break;
    case 'V':
        usage(null, 'version');
    case 'c':
    case 'C':
        break;
    default:
        // all non pear params goes to the command
        $cmdopts[$opt[0]] = $param;
        break;
    }
}

if ($store_system_config) {
    $config->store('system');
}

if ($store_user_config) {
    $config->store('user');
}

$command = (isset($options[1][0])) ? $options[1][0] : null;
if (empty($command) && ($store_user_config || $store_system_config)) {
    exit;
}

if ($fetype == 'Gtk2') {
    if (!$config->validConfiguration()) {
        PEAR::raiseError(
            "CRITICAL ERROR: no existing valid configuration files found in " .
            "files '$pear_user_config' or '$pear_system_config', " .
            "please copy an existing configuration file to one of these " .
            "locations, or use the -c and -s options to create one"
        );
    }
    Gtk::main();
} else {
    do {
        if ($command == 'help') {
            usage(null, isset($options[1][1]) ? $options[1][1] : null);
        }

        if (!$config->validConfiguration()) {
            PEAR::raiseError(
                "CRITICAL ERROR: no existing valid configuration files found " .
                "in files '$pear_user_config' or '$pear_system_config', " .
                "please copy an existing configuration file to one of " .
                "these locations, or use the -c and -s options to create one"
            );
        }

        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        $cmd = PEAR_Command::factory($command, $config);
        PEAR::popErrorHandling();
        if (PEAR::isError($cmd)) {
            usage(null, isset($options[1][0]) ? $options[1][0] : null);
        }

        $short_args = $long_args = null;
        PEAR_Command::getGetoptArgs($command, $short_args, $long_args);
        array_shift($options[1]);
        $tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args);

        if (PEAR::isError($tmp)) {
            break;
        }

        list($tmpopt, $params) = $tmp;
        $opts = array();
        foreach ($tmpopt as $foo => $tmp2) {
            list($opt, $value) = $tmp2;
            if ($value === null) {
                $value = true; // options without args
            }

            if (strlen($opt) == 1) {
                $cmdoptions = $cmd->getOptions($command);
                foreach ($cmdoptions as $o => $d) {
                    if (isset($d['shortopt']) && $d['shortopt'] == $opt) {
                        $opts[$o] = $value;
                    }
                }
            } else {
                if (substr($opt, 0, 2) == '--') {
                    $opts[substr($opt, 2)] = $value;
                }
            }
        }

        $ok = $cmd->run($command, $opts, $params);
        if ($ok === false) {
            PEAR::raiseError("unknown command `$command'");
        }

        if (PEAR::isError($ok)) {
            PEAR::setErrorHandling(
                PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")
            );
            PEAR::raiseError($ok);
        }
    } while (false);
}

// {{{ usage()

/**
 * Display usage information
 *
 * @param mixed $error       Optional error message
 * @param mixed $helpsubject Optional subject/command to display help for
 *
 * @return void
 */
function usage($error = null, $helpsubject = null)
{
    global $progname, $all_commands;
    $stdout = fopen('php://stdout', 'w');
    if (PEAR::isError($error)) {
        fputs($stdout, $error->getMessage() . "\n");
    } elseif ($error !== null) {
        fputs($stdout, "$error\n");
    }

    if ($helpsubject != null) {
        $put = cmdHelp($helpsubject);
    } else {
        $put = "Commands:\n";
        $maxlen = max(array_map("strlen", $all_commands));
        $formatstr = "%-{$maxlen}s  %s\n";
        ksort($all_commands);
        foreach ($all_commands as $cmd => $class) {
            $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd));
        }
        $put .=
            "Usage: $progname [options] command [command-options] <parameters>\n".
            "Type \"$progname help options\" to list all options.\n".
            "Type \"$progname help shortcuts\" to list all command shortcuts.\n".
            "Type \"$progname help version\" or ".
            "\"$progname version\" to list version information.\n".
            "Type \"$progname help <command>\" to get the help ".
            "for the specified command.";
    }
    fputs($stdout, "$put\n");
    fclose($stdout);

    if ($error === null) {
        exit(0);
    }
    exit(1);
}

/**
 * Return help string for specified command
 *
 * @param string $command Command to return help for
 *
 * @return void
 */
function cmdHelp($command)
{
    global $progname, $all_commands, $config;
    if ($command == "options") {
        return
        "Options:\n".
        "     -v         increase verbosity level (default 1)\n".
        "     -q         be quiet, decrease verbosity level\n".
        "     -c file    find user configuration in `file'\n".
        "     -C file    find system configuration in `file'\n".
        "     -d foo=bar set user config variable `foo' to `bar'\n".
        "     -D foo=bar set system config variable `foo' to `bar'\n".
        "     -G         start in graphical (Gtk) mode\n".
        "     -s         store user configuration\n".
        "     -S         store system configuration\n".
        "     -u foo     unset `foo' in the user configuration\n".
        "     -h, -?     display help/usage (this message)\n".
        "     -V         version information\n";
    } elseif ($command == "shortcuts") {
        $sc = PEAR_Command::getShortcuts();
        $ret = "Shortcuts:\n";
        foreach ($sc as $s => $c) {
            $ret .= sprintf("     %-8s %s\n", $s, $c);
        }
        return $ret;

    } elseif ($command == "version") {
        return "PEAR Version: ".$GLOBALS['pear_package_version'].
               "\nPHP Version: ".phpversion().
               "\nZend Engine Version: ".zend_version().
               "\nRunning on: ".php_uname();

    } elseif ($help = PEAR_Command::getHelp($command)) {
        if (is_string($help)) {
            return "$progname $command [options] $help\n";
        }

        if ($help[1] === null) {
            return "$progname $command $help[0]";
        }

        return "$progname $command [options] $help[0]\n$help[1]";
    }

    return "Command '$command' is not valid, try '$progname help'";
}

// }}}

/**
 * error_handler
 *
 * @param mixed $errno  Error number
 * @param mixed $errmsg Message
 * @param mixed $file   Filename
 * @param mixed $line   Line number
 *
 * @access public
 * @return boolean
 */
function error_handler($errno, $errmsg, $file, $line)
{
    if ((!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) && ($errno & E_STRICT)) {
        return; // E_STRICT
    }
    if ($errno & E_DEPRECATED) {
        return; // E_DEPRECATED
    }
    if (!(error_reporting() & $errno) &&
        isset($GLOBALS['config']) &&
        $GLOBALS['config']->get('verbose') < 4
    ) {
        return false; // @silenced error, show all if debug is high enough
    }
    $errortype = array (
        E_DEPRECATED  => 'Deprecated Warning',
        E_ERROR   =>  "Error",
        E_WARNING   =>  "Warning",
        E_PARSE   =>  "Parsing Error",
        E_NOTICE   =>  "Notice",
        E_CORE_ERROR  =>  "Core Error",
        E_CORE_WARNING  =>  "Core Warning",
        E_COMPILE_ERROR  =>  "Compile Error",
        E_COMPILE_WARNING =>  "Compile Warning",
        E_USER_ERROR =>  "User Error",
        E_USER_WARNING =>  "User Warning",
        E_USER_NOTICE =>  "User Notice"
    );
    if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) {
 PK��ZH����,.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUri   URI of the namespace
     * @param bool   $multiline      whether to create a multiline tag where each
     *                               attribute gets written to a single line
     * @param string $indent         string used to indent attributes (_auto indents
     *                               attributes so they start at the same column)
     * @param string $linebreak      string used for linebreaks
     * @param bool   $sortAttributes Whether to sort the attributes or not
     *
     * @return string XML start element
     * @see    createEndElement(), createTag()
     */
    public static function createStartElement(
        $qname, $attributes = array(), $namespaceUri = null,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true
    ) {
        // if no attributes hav been set, use empty attributes
        if (!isset($attributes) || !is_array($attributes)) {
            $attributes = array();
        }

        if ($namespaceUri != null) {
            $parts = XML_Util::splitQualifiedName($qname);
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($qname)+2));
            }
        }

        if ($namespaceUri != null) {
            // is a namespace given
            if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
            } else {
                // define this Uri as the default namespace
                $attributes['xmlns'] = $namespaceUri;
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $attributes, $sortAttributes,
            $multiline, $indent, $linebreak
        );
        $element = sprintf('<%s%s>', $qname, $attList);
        return  $element;
    }

    /**
     * Create an end element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createEndElement('myNs:myTag');
     * </code>
     *
     * @param string $qname qualified tagname (including namespace)
     *
     * @return string XML end element
     * @see    createStartElement(), createTag()
     */
    public static function createEndElement($qname)
    {
        $element = sprintf('</%s>', $qname);
        return $element;
    }

    /**
     * Create an XML comment
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createComment('I am a comment');
     * </code>
     *
     * @param string $content content of the comment
     *
     * @return string XML comment
     */
    public static function createComment($content)
    {
        $comment = sprintf('<!-- %s -->', $content);
        return $comment;
    }

    /**
     * Create a CData section
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create a CData section
     * $tag = XML_Util::createCDataSection('I am content.');
     * </code>
     *
     * @param string $data data of the CData section
     *
     * @return string CData section with content
     */
    public static function createCDataSection($data)
    {
        return sprintf(
            '<![CDATA[%s]]>',
            preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data))
        );
    }

    /**
     * Split qualified name and return namespace and local part
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // split qualified tag
     * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
     * </code>
     * the returned array will contain two elements:
     * <pre>
     * array(
     *     'namespace' => 'xslt',
     *     'localPart' => 'stylesheet'
     * );
     * </pre>
     *
     * @param string $qname     qualified tag name
     * @param string $defaultNs default namespace (optional)
     *
     * @return array array containing namespace and local part
     */
    public static function splitQualifiedName($qname, $defaultNs = null)
    {
        if (strstr($qname, ':')) {
            $tmp = explode(':', $qname);
            return array(
                'namespace' => $tmp[0],
                'localPart' => $tmp[1]
            );
        }
        return array(
            'namespace' => $defaultNs,
            'localPart' => $qname
        );
    }

    /**
     * Check, whether string is valid XML name
     *
     * <p>XML names are used for tagname, attribute names and various
     * other, lesser known entities.</p>
     * <p>An XML name may only consist of alphanumeric characters,
     * dashes, undescores and periods, and has to start with a letter
     * or an underscore.</p>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // verify tag name
     * $result = XML_Util::isValidName('invalidTag?');
     * if (is_a($result, 'PEAR_Error')) {
     *    print 'Invalid XML name: ' . $result->getMessage();
     * }
     * </code>
     *
     * @param string $string string that should be checked
     *
     * @return mixed true, if string is a valid XML name, PEAR error otherwise
     *
     * @todo support for other charsets
     * @todo PEAR CS - unable to avoid 85-char limit on second preg_match
     */
    public static function isValidName($string)
    {
        // check for invalid chars
        if (!is_string($string) || !strlen($string) || !preg_match('/^[[:alpha:]_]\\z/', $string[0])) {
            return XML_Util::raiseError(
                'XML names may only start with letter or underscore',
                XML_UTIL_ERROR_INVALID_START
            );
        }

        // check for invalid chars
        $match = preg_match(
            '/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?'
            . '[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/',
            $string
        );
        if (!$match) {
            return XML_Util::raiseError(
                'XML names may only contain alphanumeric '
                . 'chars, period, hyphen, colon and underscores',
                XML_UTIL_ERROR_INVALID_CHARS
            );
        }
        // XML name is valid
        return true;
    }

    /**
     * Replacement for XML_Util::raiseError
     *
     * Avoids the necessity to always require
     * PEAR.php
     *
     * @param string $msg  error message
     * @param int    $code error code
     *
     * @return PEAR_Error
     * @todo   PEAR CS - should this use include_once instead?
     */
    public static function raiseError($msg, $code)
    {
        include_once 'PEAR.php';
        return PEAR::raiseError($msg, $code);
    }
}
?>
PK��Z#F��:�:pearcmd.phpnu�[���<?php
/**
 * PEAR, the PHP Extension and Application Repository
 *
 * Command line interface
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Stig Bakken <ssb@php.net>
 * @author    Tomas V.V.Cox <cox@idecnet.com>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 */

@ob_end_clean();
if (!defined('PEAR_RUNTYPE')) {
    // this is defined in peclcmd.php as 'pecl'
    define('PEAR_RUNTYPE', 'pear');
}
define('PEAR_IGNORE_BACKTRACE', 1);
/**
 * @nodep Gtk
 */
//the space is needed for windows include paths with trailing backslash
// http://pear.php.net/bugs/bug.php?id=19482
if ('/opt/alt/php74/usr/share/pear ' != '@'.'include_path'.'@ ') {
    ini_set('include_path', trim('/opt/alt/php74/usr/share/pear '). PATH_SEPARATOR .  get_include_path());
    $raw = false;
} else {
    // this is a raw, uninstalled pear, either a cvs checkout, or php distro
    ini_set('include_path', dirname(__DIR__) . PATH_SEPARATOR . get_include_path());
    $raw = true;
}
@ini_set('allow_url_fopen', true);
@set_time_limit(0);
ob_implicit_flush(true);
@ini_set('track_errors', true);
@ini_set('html_errors', false);
$_PEAR_PHPDIR = '#$%^&*';
set_error_handler('error_handler');

$pear_package_version = "1.10.16";

require_once 'PEAR.php';
require_once 'PEAR/Frontend.php';
require_once 'PEAR/Config.php';
require_once 'PEAR/Command.php';
require_once 'Console/Getopt.php';


PEAR_Command::setFrontendType('CLI');
$all_commands = PEAR_Command::getCommands();

$argv = Console_Getopt::readPHPArgv();
// fix CGI sapi oddity - the -- in pear.bat/pear is not removed
if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
    unset($argv[1]);
    $argv = array_values($argv);
}
$progname = PEAR_RUNTYPE;
array_shift($argv);
$options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV");
if (PEAR::isError($options)) {
    usage($options);
}

$opts = $options[0];

$fetype = 'CLI';
if ($progname == 'gpear' || $progname == 'pear-gtk') {
    $fetype = 'Gtk2';
} else {
    foreach ($opts as $opt) {
        if ($opt[0] == 'G') {
            $fetype = 'Gtk2';
        }
    }
}

$pear_user_config = '';
$pear_system_config = '';
$store_user_config = false;
$store_system_config = false;
$verbose = 1;

foreach ($opts as $opt) {
    switch ($opt[0]) {
    case 'c':
        $pear_user_config = $opt[1];
        break;
    case 'C':
        $pear_system_config = $opt[1];
        break;
    }
}

PEAR_Command::setFrontendType($fetype);
$ui = &PEAR_Command::getFrontendObject();
$config = &PEAR_Config::singleton($pear_user_config, $pear_system_config);

if (PEAR::isError($config)) {
    $_file = '';
    if ($pear_user_config !== false) {
        $_file .= $pear_user_config;
    }
    if ($pear_system_config !== false) {
        $_file .= '/' . $pear_system_config;
    }
    if ($_file == '/') {
        $_file = 'The default config file';
    }
    $config->getMessage();
    $ui->outputData("ERROR: $_file is not a valid config file or is corrupted.");
    // We stop, we have no idea where we are :)
    exit(1);
}

// this is used in the error handler to retrieve a relative path
$_PEAR_PHPDIR = $config->get('php_dir');
$ui->setConfig($config);
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError"));

$verbose = $config->get("verbose");
$cmdopts = array();

if ($raw) {
    if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) {
        $found = false;
        foreach ($opts as $opt) {
            if ($opt[0] == 'd' || $opt[0] == 'D') {
                // the user knows what they are doing, and are setting config values
                $found = true;
            }
        }
        if (!$found) {
            // no prior runs, try to install PEAR
            $parent = dirname(__FILE__);
            if (strpos($parent, 'scripts')) {
                $grandparent = dirname($parent);
                $packagexml = $grandparent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $grandparent;
            } else {
                $packagexml = $parent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $parent;
            }
            if (file_exists($packagexml)) {
                $options[1] = array(
                    'install',
                    $packagexml
                );
                $config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php');
                $config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data');
                $config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs');
                $config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests');
                $config->set(
                    'ext_dir',
                    $pearbase . DIRECTORY_SEPARATOR . 'extensions'
                );
                $config->set('bin_dir', $pearbase);
                $config->mergeConfigFile($pearbase . 'pear.ini', false);
                $config->store();
                $config->set('auto_discover', 1);
            }
        }
    }
}
foreach ($opts as $opt) {
    $param = !empty($opt[1]) ? $opt[1] : true;
    switch ($opt[0]) {
    case 'd':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected -d config_value=value, ' .
                'received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'user');
        break;
    case 'D':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'system');
        break;
    case 's':
        $store_user_config = true;
        break;
    case 'S':
        $store_system_config = true;
        break;
    case 'u':
        $config->remove($param, 'user');
        break;
    case 'v':
        $config->set('verbose', $config->get('verbose') + 1);
        break;
    case 'q':
        $config->set('verbose', $config->get('verbose') - 1);
        break;
    case 'V':
        usage(null, 'version');
    case 'c':
    case 'C':
        break;
    default:
        // all non pear params goes to the command
        $cmdopts[$opt[0]] = $param;
        break;
    }
}

if ($store_system_config) {
    $config->store('system');
}

if ($store_user_config) {
    $config->store('user');
}

$command = (isset($options[1][0])) ? $options[1][0] : null;
if (empty($command) && ($store_user_config || $store_system_config)) {
    exit;
}

if ($fetype == 'Gtk2') {
    if (!$config->validConfiguration()) {
        PEAR::raiseError(
            "CRITICAL ERROR: no existing valid configuration files found in " .
            "files '$pear_user_config' or '$pear_system_config', " .
            "please copy an existing configuration file to one of these " .
            "locations, or use the -c and -s options to create one"
        );
    }
    Gtk::main();
} else {
    do {
        if ($command == 'help') {
            usage(null, isset($options[1][1]) ? $options[1][1] : null);
        }

        if (!$config->validConfiguration()) {
            PEAR::raiseError(
                "CRITICAL ERROR: no existing valid configuration files found " .
                "in files '$pear_user_config' or '$pear_system_config', " .
                "please copy an existing configuration file to one of " .
                "these locations, or use the -c and -s options to create one"
            );
        }

        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        $cmd = PEAR_Command::factory($command, $config);
        PEAR::popErrorHandling();
        if (PEAR::isError($cmd)) {
            usage(null, isset($options[1][0]) ? $options[1][0] : null);
        }

        $short_args = $long_args = null;
        PEAR_Command::getGetoptArgs($command, $short_args, $long_args);
        array_shift($options[1]);
        $tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args);

        if (PEAR::isError($tmp)) {
            break;
        }

        list($tmpopt, $params) = $tmp;
        $opts = array();
        foreach ($tmpopt as $foo => $tmp2) {
            list($opt, $value) = $tmp2;
            if ($value === null) {
                $value = true; // options without args
            }

            if (strlen($opt) == 1) {
                $cmdoptions = $cmd->getOptions($command);
                foreach ($cmdoptions as $o => $d) {
                    if (isset($d['shortopt']) && $d['shortopt'] == $opt) {
                        $opts[$o] = $value;
                    }
                }
            } else {
                if (substr($opt, 0, 2) == '--') {
                    $opts[substr($opt, 2)] = $value;
                }
            }
        }

        $ok = $cmd->run($command, $opts, $params);
        if ($ok === false) {
            PEAR::raiseError("unknown command `$command'");
        }

        if (PEAR::isError($ok)) {
            PEAR::setErrorHandling(
                PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")
            );
            PEAR::raiseError($ok);
        }
    } while (false);
}

// {{{ usage()

/**
 * Display usage information
 *
 * @param mixed $error       Optional error message
 * @param mixed $helpsubject Optional subject/command to display help for
 *
 * @return void
 */
function usage($error = null, $helpsubject = null)
{
    global $progname, $all_commands;
    $stdout = fopen('php://stdout', 'w');
    if (PEAR::isError($error)) {
        fputs($stdout, $error->getMessage() . "\n");
    } elseif ($error !== null) {
        fputs($stdout, "$error\n");
    }

    if ($helpsubject != null) {
        $put = cmdHelp($helpsubject);
    } else {
        $put = "Commands:\n";
        $maxlen = max(array_map("strlen", $all_commands));
        $formatstr = "%-{$maxlen}s  %s\n";
        ksort($all_commands);
        foreach ($all_commands as $cmd => $class) {
            $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd));
        }
        $put .=
            "Usage: $progname [options] command [command-options] <parameters>\n".
            "Type \"$progname help options\" to list all options.\n".
            "Type \"$progname help shortcuts\" to list all command shortcuts.\n".
            "Type \"$progname help version\" or ".
            "\"$progname version\" to list version information.\n".
            "Type \"$progname help <command>\" to get the help ".
            "for the specified command.";
    }
    fputs($stdout, "$put\n");
    fclose($stdout);

    if ($error === null) {
        exit(0);
    }
    exit(1);
}

/**
 * Return help string for specified command
 *
 * @param string $command Command to return help for
 *
 * @return void
 */
function cmdHelp($command)
{
    global $progname, $all_commands, $config;
    if ($command == "options") {
        return
        "Options:\n".
        "     -v         increase verbosity level (default 1)\n".
        "     -q         be quiet, decrease verbosity level\n".
        "     -c file    find user configuration in `file'\n".
        "     -C file    find system configuration in `file'\n".
        "     -d foo=bar set user config variable `foo' to `bar'\n".
        "     -D foo=bar set system config variable `foo' to `bar'\n".
        "     -G         start in graphical (Gtk) mode\n".
        "     -s         store user configuration\n".
        "     -S         store system configuration\n".
        "     -u foo     unset `foo' in the user configuration\n".
        "     -h, -?     display help/usage (this message)\n".
        "     -V         version information\n";
    } elseif ($command == "shortcuts") {
        $sc = PEAR_Command::getShortcuts();
        $ret = "Shortcuts:\n";
        foreach ($sc as $s => $c) {
            $ret .= sprintf("     %-8s %s\n", $s, $c);
        }
        return $ret;

    } elseif ($command == "version") {
        return "PEAR Version: ".$GLOBALS['pear_package_version'].
               "\nPHP Version: ".phpversion().
               "\nZend Engine Version: ".zend_version().
               "\nRunning on: ".php_uname();

    } elseif ($help = PEAR_Command::getHelp($command)) {
        if (is_string($help)) {
            return "$progname $command [options] $help\n";
        }

        if ($help[1] === null) {
            return "$progname $command $help[0]";
        }

        return "$progname $command [options] $help[0]\n$help[1]";
    }

    return "Command '$command' is not valid, try '$progname help'";
}

// }}}

/**
 * error_handler
 *
 * @param mixed $errno  Error number
 * @param mixed $errmsg Message
 * @param mixed $file   Filename
 * @param mixed $line   Line number
 *
 * @access public
 * @return boolean
 */
function error_handler($errno, $errmsg, $file, $line)
{
    if ((!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) && ($errno & E_STRICT)) {
        return; // E_STRICT
    }
    if ($errno & E_DEPRECATED) {
        return; // E_DEPRECATED
    }
    if (!(error_reporting() & $errno) &&
        isset($GLOBALS['config']) &&
        $GLOBALS['config']->get('verbose') < 4
    ) {
        return false; // @silenced error, show all if debug is high enough
    }
    $errortype = array (
        E_DEPRECATED  => 'Deprecated Warning',
        E_ERROR   =>  "Error",
        E_WARNING   =>  "Warning",
        E_PARSE   =>  "Parsing Error",
        E_NOTICE   =>  "Notice",
        E_CORE_ERROR  =>  "Core Error",
        E_CORE_WARNING  =>  "Core Warning",
        E_COMPILE_ERROR  =>  "Compile Error",
        E_COMPILE_WARNING =>  "Compile Warning",
        E_USER_ERROR =>  "User Error",
        E_USER_WARNING =>  "User Warning",
        E_USER_NOTICE =>  "User Notice"
    );
    if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) {
        $errortype[E_STRICT] = 'Strict Warning';
    }
    $prefix = $errortype[$errno];
    global $_PEAR_PHPDIR;
    if (stristr($file, $_PEAR_PHPDIR)) {
        $file = substr($file, strlen($_PEAR_PHPDIR) + 1);
    } else {
        $file = basename($file);
    }
    print "\n$prefix: $errmsg in $file on line $line\n";
    return false;
}


/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * indent-tabs-mode: nil
 * mode: php
 * End:
 */
// vim600:syn=php
PK��Z�0$�-- .pkgxml/Pear_File_MARC-1.4.1.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.10.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
 <name>File_MARC</name>
 <channel>pear.php.net</channel>
 <summary>Parse, modify, and create MARC records</summary>
 <description>The standard for machine-readable cataloging (MARC) records is documented at http://loc.gov/marc/. This package enables you to read existing MARC records from a file, string, or (using the YAZ extension), from a Z39.50 source. You can also use this package to create new MARC records.

This package is based on the PHP MARC package, originally called &quot;php-marc&quot;, that is part of the Emilda Project (http://www.emilda.org).  Christoffer Landtman generously agreed to make the &quot;php-marc&quot; code available under the GNU LGPL so it could be used as the basis of this PEAR package.</description>
 <lead>
  <name>Dan Scott</name>
  <user>dbs</user>
  <email>dbs@php.net</email>
  <active>yes</active>
 </lead>
 <date>2019-11-13</date>
 <time>17:33:33</time>
 <version>
  <release>1.4.1</release>
  <api>1.4.0</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license uri="http://www.gnu.org/copyleft/lesser.html">GNU Lesser General Public License</license>
 <notes>
1.4.1
  * Reintroduce include_path to composer.json
 </notes>
 <contents>
  <dir baseinstalldir="File" name="/">
   <file baseinstalldir="/" md5sum="ffe2590635f404af055fe731da105939" name="File/MARC/Lint/CodeData.php" role="php" />
   <file baseinstalldir="/" md5sum="a3b9e1c817e67f59add05593500d463e" name="File/MARC/Control_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="acba4463f8e40d6ee4e7ba1f2dc53123" name="File/MARC/Data_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="378f483ec1fd161cd9dfb9b05db58d66" name="File/MARC/Exception.php" role="php" />
   <file baseinstalldir="/" md5sum="a9ba69030cbf4847292b9975e9d922c6" name="File/MARC/Field.php" role="php" />
   <file baseinstalldir="/" md5sum="c37351c7c80927ce6bb1e662510f9183" name="File/MARC/Lint.php" role="php" />
   <file baseinstalldir="/" md5sum="c5ac39e3d25eb0108b9dd5ad8466c821" name="File/MARC/List.php" role="php" />
   <file baseinstalldir="/" md5sum="7af6ce78cde4bb246e4e96709e90d2c0" name="File/MARC/Record.php" role="php" />
   <file baseinstalldir="/" md5sum="df5f97139685f0ad04e47fdbb67e3968" name="File/MARC/Subfield.php" role="php" />
   <file baseinstalldir="/" md5sum="6e102262dfd5d65d8d5a6221dfc74edd" name="File/MARC.php" role="php" />
   <file baseinstalldir="/" md5sum="8b64040d2d18ac4b994595a148266a66" name="File/MARCBASE.php" role="php" />
   <file baseinstalldir="/" md5sum="f5a17a60d34e84e2ee7ca1e5c5c6c620" name="File/MARCXML.php" role="php" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="examples/example.mrc" role="doc" />
   <file baseinstalldir="File" md5sum="1aea40df9f1c2e32f8e065fe8da0a3b5" name="examples/marc_yaz.php" role="doc" />
   <file baseinstalldir="File" md5sum="70ae317e0890d5896e3ffccdd293369a" name="examples/read.php" role="doc" />
   <file baseinstalldir="File" md5sum="54efb9d920ac775bfc847a83a2dec73a" name="examples/subfields.php" role="doc" />
   <file baseinstalldir="File" md5sum="14297da35b510c496cd1f328cf3bb301" name="tests/bad_example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="0dd4c6dbad6e8608d0ebf9d24425955d" name="tests/bad_example.xml" role="test" />
   <file baseinstalldir="File" md5sum="216a6f9d53f6d3d8e22d81fdc10f4bc1" name="tests/camel.mrc" role="test" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="tests/example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="9455aec3371f79cf7d31281fd03f5171" name="tests/marc_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="577e2f5f89fd48cf1a3576a29d2958f8" name="tests/marc_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a6a586354b9a06c880c2a7470dd828d7" name="tests/marc_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1c7e2fc5572a0f9362a771c260a1fe3" name="tests/marc_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="84f85ac7f8a2532e4e90ccde7764556a" name="tests/marc_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="889e5e906a97de7a0e94b0c5f30e70e7" name="tests/marc_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="be823dc8a8efb408de06371ab802efcc" name="tests/marc_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="af44490aafea44e5120f881cb81cdad9" name="tests/marc_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ac9f2a7aeb24900a11f5102744179ae3" name="tests/marc_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5e43eb5cddbb4f2bd0d6405cd95b80aa" name="tests/marc_010.phpt" role="test" />
   <file baseinstalldir="File" md5sum="2e1cd8509c0bf04ec77fc0f51375f611" name="tests/marc_011.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bc49ca48623102c8ac07679fa77a3dd9" name="tests/marc_012.phpt" role="test" />
   <file baseinstalldir="File" md5sum="245a3b20e0da1973535503e28efd1d3a" name="tests/marc_013.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ce69aa734856dd40d60d30c77bdef53a" name="tests/marc_014.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7b61cdd31035e60682fa92c5d519d997" name="tests/marc_015.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7f4f597fe1adaa3507eb87fc4875dbd2" name="tests/marc_016.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4262efd5fcacbd7503323681f4552430" name="tests/marc_017.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ee1623d7bda54ba4f741b2319b158f82" name="tests/marc_018.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8006c03fbab0f04377342086fafd3982" name="tests/marc_019.phpt" role="test" />
   <file baseinstalldir="File" md5sum="f5ae5b25e0ac1104314433d9e5b1f7fe" name="tests/marc_020.phpt" role="test" />
   <file baseinstalldir="File" md5sum="94d8f99e86585671a1b2d3043aeb6360" name="tests/marc_021.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bb891a890effe0e77e1759043f4846d8" name="tests/marc_022.phpt" role="test" />
   <file baseinstalldir="File" md5sum="faf77dcb5cdd002c09169a14bfded65e" name="tests/marc_023.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0e6c4a23f5da7df64fdd4b3b1149bbee" name="tests/marc_16783.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4ea8b3520beda378db15960f1c50493a" name="tests/marc_field_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="743850ef61df69c4340be44a03bccb5a" name="tests/marc_field_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8c765f1398b49df257d86d22ac6e4f8d" name="tests/marc_field_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d4216cf930a308e0d02553bd3914f294" name="tests/marc_field_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dd59514b474b78371ad522a3e13b76b7" name="tests/marc_field_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5295bfd02a8424acac1c91de26b552c7" name="tests/marc_field_21246.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6f95f09442ccf6b93df92986f58b270d" name="tests/marc_lint_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="18d721f8871edd925624ccbdd15444fb" name="tests/marc_lint_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4eb86a2f4e0a74dedcb0bf2511da6ca1" name="tests/marc_lint_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="10430fee0a1352d0528f1507b34c57e1" name="tests/marc_lint_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0dcd07a18577d7b22392a2214cd6436c" name="tests/marc_lint_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fd17798fc535562e5e64461f449516b2" name="tests/marc_record_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="141b455ccf67a60c4eac44c77960f2e2" name="tests/marc_subfield_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1e23464ee0eec47ddca2af9a9922926" name="tests/marc_subfield_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="1d7903e8c244d647220b318b4bc758d1" name="tests/marc_xml_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="22cae3c752d843b78f583dcd92801534" name="tests/marc_xml_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="c0716d23e0f960abf8d53ad6014a413a" name="tests/marc_xml_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7645fa19e28aca041a124fc5e2c12bd3" name="tests/marc_xml_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b08b28c3251625b8b6e4d7ab376b0185" name="tests/marc_xml_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6cd0934ddbf65d2d7e9ea5d108977ff7" name="tests/marc_xml_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ffdce4aa190268fa7cbbf3bb45383abf" name="tests/marc_xml_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="998a4c1ce00ff100f39ffa9fc49a212f" name="tests/marc_xml_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a38a67c590869f2b0a4859a910fd9e89" name="tests/marc_xml_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="db39c5055a570fcda12bb7c5fa1e3b4d" name="tests/marc_xml_16642.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dc075f4a271bd7182378a3874bd5b39e" name="tests/marc_xml_namespace.phpt" role="test" />
   <file baseinstalldir="File" md5sum="208200d9a979ac360c4d326e9789b6b7" name="tests/marc_xml_namespace_prefix.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d87774ede82222cfc12b2c2a06f57a3a" name="tests/marc_xml_rsinger.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fb44e3eb69f1a37115235fc829c39542" name="tests/namespace.xml" role="test" />
   <file baseinstalldir="File" md5sum="e6de4d809b0af5dd99fd352eb60616a1" name="tests/skipif.inc" role="test" />
   <file baseinstalldir="File" md5sum="a0166a4ff0bc0bb283e854f11beaa793" name="tests/music.mrc" role="test" />
   <file baseinstalldir="File" md5sum="993ce494befbc25dc1326527b30b4782" name="tests/music.xml" role="test" />
   <file baseinstalldir="File" md5sum="6b0c87f0cd459ed7322c25d403b164cc" name="tests/bigarchive.xml" role="test" />
   <file baseinstalldir="File" md5sum="be850aa6ab4ac52b8c6c214c30b574af" name="tests/onerecord.xml" role="test" />
   <file baseinstalldir="File" md5sum="4f43fec7b276267eec5258044853ccc8" name="tests/sandburg.mrc" role="test" />
   <file baseinstalldir="File" md5sum="e216b95f905dd240c9bde372950e4073" name="tests/sandburg.xml" role="test" />
   <file baseinstalldir="File" md5sum="e81a92188ea0dcd9c108a63fb32b3f4f" name="tests/xmlescape.mrc" role="test" />
   <file baseinstalldir="File" md5sum="8f9f63ed6a80191d89a2296fa4c1a30b" name="CHANGELOG" role="doc" />
   <file baseinstalldir="File" md5sum="fbc093901857fcd118f065f900982c24" name="LICENSE" role="doc" />
  </dir>
 </contents>
 <dependencies>
  <required>
   <php>
    <min>5.6</min>
   </php>
   <pearinstaller>
    <min>1.4.0</min>
   </pearinstaller>
  </required>
  <optional>
   <package>
    <name>Validate_ISPN</name>
    <channel>pear.php.net</channel>
   </package>
  </optional>
 </dependencies>
 <phprelease />
</package>
PKm�ZPi��.depdbnu�[���PKm�Z�{��
�Mail/null.phpnu�[���PKm�ZE@�%>>
Mail/sendmail.phpnu�[���PKm�Z��A~�{�{�;Mail/RFC822.phpnu�[���PKn�Z�+V����
[�Mail/mime.phpnu�[���PKn�Zx�ع���D�Mail/mimeDecode.phpnu�[���PKn�ZB�_Ǭ=�=
@(Mail/smtp.phpnu�[���PKn�ZwԐE;E;)fMail/smtpmx.phpnu�[���PKn�Z�؛�J�J���Mail/mimePart.phpnu�[���PKn�ZB��shh
8YMail/mock.phpnu�[���PKn�Z@iE�\\
�lMail/mail.phpnu�[���PKn�Zv�.locknu�[���PKn�Z�*�z%-%- ��Structures/LinkedList/Double.phpnu�[���PKn�Z����p:p:  �Structures/LinkedList/Single.phpnu�[���PKn�ZUyv���Structures/Graph.phpnu�[���PKn�Z�C� + +CStructures/Graph/Node.phpnu�[���PKn�Z9����,�1Structures/Graph/Manipulator/AcyclicTest.phpnu�[���PKn�Z~(�htt2�HStructures/Graph/Manipulator/TopologicalSorter.phpnu�[���PKn�Z�J�}
}
_dAuth/SASL/Anonymous.phpnu�[���PKn�ZP(~�T
T
#rAuth/SASL/CramMD5.phpnu�[���PKn�Z����==�Auth/SASL/Plain.phpnu�[���PKn�Z�<� OO<�Auth/SASL/Login.phpnu�[���PKn�Z%ׅtg!g!ΘAuth/SASL/DigestMD5.phpnu�[���PKn�Z�T�|�Auth/SASL/Common.phpnu�[���PKn�ZvR�r,,��Auth/SASL/External.phpnu�[���PKn�Zќ��0�0H�Auth/SASL/SCRAM.phpnu�[���PKn�Z2r����
�	Auth/SASL.phpnu�[���PKn�Z�T�,�,�OS/Guess.phpnu�[���PKn�Z�����KPEAR/Config.phpnu�[���PKn�Z�`�eEAEA
.ZPEAR/REST.phpnu�[���PKn�Z��ym6m6��PEAR/Exception.phpnu�[���PKn�Zr"����_�PEAR/ChannelFile.phpnu�[���PKn�Z��gk�U�U?�PEAR/Validate.phpnu�[���PKn�Zd֣S��u�PEAR/Command/Pickle.xmlnu�[���PKn�Z�z��k<k<W�PEAR/Command/Config.phpnu�[���PKn�Z݄<ii	1PEAR/Command/Mirror.xmlnu�[���PKn�Z,��t"u"u�3PEAR/Command/Remote.phpnu�[���PKn�Z
�\���"�PEAR/Command/Remote.xmlnu�[���PKn�Zj���!�!X�PEAR/Command/Install.xmlnu�[���PKo�Z�%q������PEAR/Command/Channels.phpnu�[���PKo�Znmi?;�;��[	PEAR/Command/Install.phpnu�[���PKo�Z�X�

#
PEAR/Command/Auth.phpnu�[���PKo�Z���s6
6
T-
PEAR/Command/Config.xmlnu�[���PKo�Z�%Fii�:
PEAR/Command/Test.xmlnu�[���PKo�ZZ h66A
PEAR/Command/Package.xmlnu�[���PKo�Z�w��zz�]
PEAR/Command/Channels.xmlnu�[���PKo�Z+9ҜҜ�n
PEAR/Command/Package.phpnu�[���PKo�Z
u����PEAR/Command/Build.xmlnu�[���PKo�Z������
PEAR/Command/Mirror.phpnu�[���PKp�Z,_�h/h/�PEAR/Command/Test.phpnu�[���PKp�Z�%sp  6OPEAR/Command/Common.phpnu�[���PKp�Z0(;rʹʹ�oPEAR/Command/Registry.phpnu�[���PKp�Z�4�{���$PEAR/Command/Auth.xmlnu�[���PKp�Z��#S
S
�)PEAR/Command/Build.phpnu�[���PKp�Z���u��S4PEAR/Command/Registry.xmlnu�[���PKp�Z�P>>�;PEAR/Command/Pickle.phpnu�[���PKp�Z��T�I�I�yPEAR/Builder.phpnu�[���PKp�Z[
�W��3�PEAR/XMLParser.phpnu�[���PKp�Zl(e���t�PEAR/Downloader.phpnu�[���PKp�Z�b������
PEAR/ErrorStack.phpnu�[���PKp�Z(Pz����ePEAR/Proxy.phpnu�[���PKp�Z��'����|PEAR/RunTest.phpnu�[���PKq�Zj�y99�	PEAR/Validator/PECL.phpnu�[���PKq�Zp�����aPEAR/Dependency2.phpnu�[���PKq�Z��wv@@��PEAR/PackageFile/v2.phpnu�[���PKq�ZC�8�L�L!:�PEAR/PackageFile/v2/Validator.phpnu�[���PKq�Z���=_�_�6PEAR/PackageFile/v2/rw.phpnu�[���PKq�Z�5�������,PEAR/PackageFile/v1.phpnu�[���PKq�Z�ɁɁ!��PEAR/PackageFile/Generator/v2.phpnu�[���PKq�Z`�=����!�tPEAR/PackageFile/Generator/v1.phpnu�[���PKr�Z��OWHH�9PEAR/PackageFile/Parser/v2.phpnu�[���PKr�Z�_=�@�@`FPEAR/PackageFile/Parser/v1.phpnu�[���PKr�Zc��__5�PEAR/DependencyDB.phpnu�[���PKr�Z�@P��{�PEAR/ChannelFile/Parser.phpnu�[���PKr�Z��_�0�0r�PEAR/Command.phpnu�[���PKr�Z�ٲ�=�==PEAR/PackageFile.phpnu�[���PKr�Z�JD��g\PEAR/Task/Replace.phpnu�[���PKr�Z&%75))�wPEAR/Task/Windowseol/rw.phpnu�[���PKr�Z�3}}PEAR/Task/Replace/rw.phpnu�[���PKr�Z&
i."x�PEAR/Task/Postinstallscript/rw.phpnu�[���PKr�Z�-!�PEAR/Task/Common.phpnu�[���PKr�ZD$���I�PEAR/Task/Windowseol.phpnu�[���PKr�ZZ�E�x9x9��PEAR/Task/Postinstallscript.phpnu�[���PKr�Z\k��K�PEAR/Task/Unixeol/rw.phpnu�[���PKr�Z�������PEAR/Task/Unixeol.phpnu�[���PKr�Z�W�f���PEAR/REST/10.phpnu�[���PKr�Z��Y�;;ąPEAR/REST/13.phpnu�[���PKr�Z,#y��+�+�PEAR/REST/11.phpnu�[���PKr�Z��U  D�PEAR/Packager.phpnu�[���PKr�ZZ�bgbg�PEAR/Common.phpnu�[���PKr�Z$���(�(FsPEAR/Registry.phpnu�[���PKr�Z��	MdMd?�PEAR/Frontend/CLI.phpnu�[���PKr�Z��

�PEAR/Installer/Role/Doc.phpnu�[���PKr�Z��/��)PEAR/Installer/Role/Cfg.xmlnu�[���PKr�Z>1H���PEAR/Installer/Role/Www.xmlnu�[���PKr�Z�?m

PEAR/Installer/Role/Php.phpnu�[���PKr�Z*Y|	%%`PEAR/Installer/Role/Man.phpnu�[���PKr�Z���BB�PEAR/Installer/Role/Ext.xmlnu�[���PKr�Zp��""]PEAR/Installer/Role/Src.xmlnu�[���PKr�Zh&P*���PEAR/Installer/Role/Doc.xmlnu�[���PKr�ZB] ���PEAR/Installer/Role/Test.xmlnu�[���PKr�Zz�q����PEAR/Installer/Role/Php.xmlnu�[���PKr�Z	��
|PEAR/Installer/Role/Data.phpnu�[���PKs�Z�0�c���PEAR/Installer/Role/Man.xmlnu�[���PKs�Z��K

�PEAR/Installer/Role/Ext.phpnu�[���PKs�ZY��� PEAR/Installer/Role/Test.phpnu�[���PKs�Z@v�а�z#PEAR/Installer/Role/Script.xmlnu�[���PKs�Zf�sz��x%PEAR/Installer/Role/Data.xmlnu�[���PKs�Z?���GGV'PEAR/Installer/Role/Common.phpnu�[���PKs�Z�^D{		�?PEAR/Installer/Role/Www.phpnu�[���PKs�Z�Ƥ?CPEAR/Installer/Role/Cfg.phpnu�[���PKs�Z��[�	SPEAR/Installer/Role/Script.phpnu�[���PKs�Z��srrjVPEAR/Installer/Role/Src.phpnu�[���PKs�ZV�Z���'ZPEAR/Installer/Role.phpnu�[���PKs�Z�{�	�)�)*yPEAR/Downloader/Package.phpnu�[���PKs�Z.�4���$�PEAR/Frontend.phpnu�[���PKs�Z،�w��_�PEAR/Installer.phpnu�[���PKs�ZXxo��-j�Symfony/Bridge/Doctrine/Logger/DbalLogger.phpnu�[���PKs�Ze�OO&b�Symfony/Bridge/Doctrine/autoloader.phpnu�[���PKs�Z��X+��8�Symfony/Bridge/Doctrine/CacheWarmer/ProxyCacheWarmer.phpnu�[���PKs�Z	�9,��5i�Symfony/Bridge/Doctrine/Form/DoctrineOrmExtension.phpnu�[���PKs�Z�0���NX�Symfony/Bridge/Doctrine/Form/EventListener/MergeDoctrineCollectionListener.phpnu�[���PKs�Z!%d==A��Symfony/Bridge/Doctrine/Form/ChoiceList/EntityLoaderInterface.phpnu�[���PKs�Z�	?x�7�7<4�Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.phpnu�[���PKs�ZGC�t��A<-Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.phpnu�[���PKs�Z`.
qpp7�9Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.phpnu�[���PKs�ZCi�PPMZQSymfony/Bridge/Doctrine/Form/DataTransformer/CollectionToArrayTransformer.phpnu�[���PKs�Z憝��0'YSymfony/Bridge/Doctrine/Form/Type/EntityType.phpnu�[���PKs�ZS;,:��2-]Symfony/Bridge/Doctrine/Form/Type/DoctrineType.phpnu�[���PKs�ZW&v��<�wSymfony/Bridge/Doctrine/Security/User/EntityUserProvider.phpnu�[���PKs�Z�����Et�Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.phpnu�[���PKs�Z(��y��9�Symfony/Bridge/Doctrine/Validator/DoctrineInitializer.phpnu�[���PKs�ZQГ��>�Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.phpnu�[���PKs�Z:�d�G5�Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.phpnu�[���PKs�Z�Ta�==B��Symfony/Bridge/Doctrine/ExpressionLanguage/DoctrineParserCache.phpnu�[���PKs�Z��qm
m
-m�Symfony/Bridge/Doctrine/RegistryInterface.phpnu�[���PKs�Zlf/�qq=7�Symfony/Bridge/Doctrine/DataFixtures/ContainerAwareLoader.phpnu�[���PKs�Z����=�Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.phpnu�[���PKs�Z�����C��Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerSchema.phpnu�[���PKs�ZOlQ�996��Symfony/Bridge/Doctrine/ContainerAwareEventManager.phpnu�[���PKs�Z؈����3D�Symfony/Bridge/Doctrine/Test/DoctrineTestHelper.phpnu�[���PKs�Z̳֨�+��Symfony/Bridge/Doctrine/ManagerRegistry.phpnu�[���PKs�Z+çxAA?�Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.phpnu�[���PKs�Z*�+��J�JIBSymfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.phpnu�[���PKs�Z���*��SVaSymfony/Bridge/Doctrine/DependencyInjection/Security/UserProvider/EntityFactory.phpnu�[���PKs�Z��㛕�Q�hSymfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterMappingsPass.phpnu�[���PKs�Z~�YAAeԀSymfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.phpnu�[���PKs�Z��,���S��Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/DoctrineValidationPass.phpnu�[���PKs�Z��4NN%,�Symfony/Bridge/Monolog/autoloader.phpnu�[���PKs�Z��մ��1ϡSymfony/Bridge/Monolog/Handler/FirePHPHandler.phpnu�[���PKs�Z��Zv��/©Symfony/Bridge/Monolog/Handler/DebugHandler.phpnu�[���PKs�Z�y���1دSymfony/Bridge/Monolog/Handler/ConsoleHandler.phpnu�[���PKs�Z��*vv5�Symfony/Bridge/Monolog/Handler/SwiftMailerHandler.phpnu�[���PKs�Z���"II3��Symfony/Bridge/Monolog/Handler/ChromePhpHandler.phpnu�[���PKs�Z��;��	�	!��Symfony/Bridge/Monolog/Logger.phpnu�[���PKs�Z��b115��Symfony/Bridge/Monolog/Formatter/ConsoleFormatter.phpnu�[���PKt�Z�,��1l�Symfony/Bridge/Monolog/Processor/WebProcessor.phpnu�[���PKt�Z�$�KK"l�Symfony/Bridge/Twig/autoloader.phpnu�[���PKt�Z�)�UU1	�Symfony/Bridge/Twig/Translation/TwigExtractor.phpnu�[���PKt�Z6DZ77*��Symfony/Bridge/Twig/Node/StopwatchNode.phpnu�[���PKt�Z,
�@��5P�Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.phpnu�[���PKt�Z�
�s>>*ESymfony/Bridge/Twig/Node/FormThemeNode.phpnu�[���PKt�ZP�IAA3�Symfony/Bridge/Twig/Node/TransDefaultDomainNode.phpnu�[���PKt�Z�U,tt,�Symfony/Bridge/Twig/Node/FormEnctypeNode.phpnu�[���PKt�Zʦ\�G
G
&QSymfony/Bridge/Twig/Node/TransNode.phpnu�[���PKt�Z���^��,�%Symfony/Bridge/Twig/Node/RenderBlockNode.phpnu�[���PKt�Z�vq�)+Symfony/Bridge/Twig/Form/TwigRenderer.phpnu�[���PKt�Zb�3�}}8q1Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.phpnu�[���PKt�Z��Qkk2V4Symfony/Bridge/Twig/Form/TwigRendererInterface.phpnu�[���PKt�Z��<��/#7Symfony/Bridge/Twig/Form/TwigRendererEngine.phpnu�[���PKt�Z�GTSymfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.phpnu�[���PKt�Z�)�[n	n	)�`Symfony/Bridge/Twig/NodeVisitor/Scope.phpnu�[���PKt�Z�tA�:`jSymfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.phpnu�[���PKt�Z��9292B�xSymfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twignu�[���PKt�Z��[[Dy�Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twignu�[���PKt�Z.��8H�Symfony/Bridge/Twig/TokenParser/StopwatchTokenParser.phpnu�[���PKt�Z�%]�
�
4��Symfony/Bridge/Twig/TokenParser/TransTokenParser.phpnu�[���PKt�Z�/�	�	:��Symfony/Bridge/Twig/TokenParser/TransChoiceTokenParser.phpnu�[���PKt�Z>����8>�Symfony/Bridge/Twig/TokenParser/FormThemeTokenParser.phpnu�[���PKt�Zʶ�̭�Ao�Symfony/Bridge/Twig/TokenParser/TransDefaultDomainTokenParser.phpnu�[���PKt�Z�9�=KK/��Symfony/Bridge/Twig/Extension/FormExtension.phpnu�[���PKt�Z��|/7�Symfony/Bridge/Twig/Extension/YamlExtension.phpnu�[���PKt�Z��&�a
a
5��Symfony/Bridge/Twig/Extension/HttpKernelExtension.phpnu�[���PKt�ZKΙ���5v�Symfony/Bridge/Twig/Extension/ExpressionExtension.phpnu�[���PKt�Z`�fS..2� Symfony/Bridge/Twig/Extension/RoutingExtension.phpnu�[���PKt�Z�5��mm4] Symfony/Bridge/Twig/Extension/StopwatchExtension.phpnu�[���PKt�Z�?���6. Symfony/Bridge/Twig/Extension/TranslationExtension.phpnu�[���PKt�Zd���oo3�! Symfony/Bridge/Twig/Extension/SecurityExtension.phpnu�[���PKt�Z�����/a' Symfony/Bridge/Twig/Extension/CodeExtension.phpnu�[���PKu�Z^D��dd"sG Symfony/Bridge/Twig/TwigEngine.phpnu�[���PKu�Z�4˵��()V Symfony/Component/Finder/Shell/Shell.phpnu�[���PKu�Z5��K��*^ Symfony/Component/Finder/Shell/Command.phpnu�[���PKu�Z�5�9(�v Symfony/Component/Finder/SplFileInfo.phpnu�[���PKu�Z%uM�PP'X~ Symfony/Component/Finder/autoloader.phpnu�[���PKu�Z��99C� Symfony/Component/Finder/Exception/ShellCommandFailureException.phpnu�[���PKu�Z�7��9�� Symfony/Component/Finder/Exception/ExceptionInterface.phpnu�[���PKu�Z�cWޫ�<� Symfony/Component/Finder/Exception/AccessDeniedException.phpnu�[���PKu�Z>�@��>� Symfony/Component/Finder/Exception/AdapterFailureException.phpnu�[���PKu�ZP�����D	� Symfony/Component/Finder/Exception/OperationNotPermitedException.phpnu�[���PKu�Z��� ��6� Symfony/Component/Finder/Comparator/DateComparator.phpnu�[���PKu�Z|F�z

2?� Symfony/Component/Finder/Comparator/Comparator.phpnu�[���PKu�Z�P�

8�� Symfony/Component/Finder/Comparator/NumberComparator.phpnu�[���PKu�Z�g@Mbb!2� Symfony/Component/Finder/Glob.phpnu�[���PKu�Z�d�V�V#� Symfony/Component/Finder/Finder.phpnu�[���PKu�Zils_��>
!Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.phpnu�[���PKu�Z��ɔ�
�
7u!Symfony/Component/Finder/Iterator/FilePathsIterator.phpnu�[���PKu�Z�,G��4n!Symfony/Component/Finder/Iterator/FilterIterator.phpnu�[���PKu�Z�ʽ���?q#!Symfony/Component/Finder/Iterator/FilecontentFilterIterator.phpnu�[���PKu�Z�

���@~+!Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.phpnu�[���PKu�Z��z":�2!Symfony/Component/Finder/Iterator/CustomFilterIterator.phpnu�[���PKu�Z{�^ǽ�<N9!Symfony/Component/Finder/Iterator/FilenameFilterIterator.phpnu�[���PKu�Z�d����Dw@!Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.phpnu�[���PKu�Zx�P���=�F!Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.phpnu�[���PKu�Z ��U��=�L!Symfony/Component/Finder/Iterator/DateRangeFilterIterator.phpnu�[���PKu�Z�n bb<�R!Symfony/Component/Finder/Iterator/FileTypeFilterIterator.phpnu�[���PKu�Z��j��	�	6�X!Symfony/Component/Finder/Iterator/SortableIterator.phpnu�[���PKu�Z���)��8�b!Symfony/Component/Finder/Iterator/PathFilterIterator.phpnu�[���PKu�Z�6s��@�j!Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.phpnu�[���PKu�Z��&
&
2Gw!Symfony/Component/Finder/Expression/Expression.phpnu�[���PKu�Z�"HH6ρ!Symfony/Component/Finder/Expression/ValueInterface.phpnu�[���PKu�Z�E�,}�!Symfony/Component/Finder/Expression/Glob.phpnu�[���PKu�Z��(�-�!Symfony/Component/Finder/Expression/Regex.phpnu�[���PKu�Z9!�2{
{
/D�!Symfony/Component/Finder/Adapter/PhpAdapter.phpnu�[���PKu�Z����5�!Symfony/Component/Finder/Adapter/AdapterInterface.phpnu�[���PKu�Z��kA�
�
34�!Symfony/Component/Finder/Adapter/BsdFindAdapter.phpnu�[���PKu�Z�}]�
�
3��!Symfony/Component/Finder/Adapter/GnuFindAdapter.phpnu�[���PKu�ZQJ)�)8��!Symfony/Component/Finder/Adapter/AbstractFindAdapter.phpnu�[���PKu�Z�	4�"Symfony/Component/Finder/Adapter/AbstractAdapter.phpnu�[���PKu�Z����:;"Symfony/Component/Translation/Extractor/ChainExtractor.phpnu�[���PKu�ZArP�>%"Symfony/Component/Translation/Extractor/ExtractorInterface.phpnu�[���PKu�Zb*0�oo4�#"Symfony/Component/Translation/PluralizationRules.phpnu�[���PKu�Z�q��UU,<"Symfony/Component/Translation/autoloader.phpnu�[���PKu�Z�<qNN10>"Symfony/Component/Translation/MessageSelector.phpnu�[���PKu�Z�س��:�J"Symfony/Component/Translation/Catalogue/MergeOperation.phpnu�[���PKu�ZY[�>*P"Symfony/Component/Translation/Catalogue/OperationInterface.phpnu�[���PKu�Z��fb�
�
=�U"Symfony/Component/Translation/Catalogue/AbstractOperation.phpnu�[���PKu�Z��ӄ�9�c"Symfony/Component/Translation/Catalogue/DiffOperation.phpnu�[���PKu�Z�6�"��>�i"Symfony/Component/Translation/Exception/ExceptionInterface.phpnu�[���PKu�ZDŽ���D�k"Symfony/Component/Translation/Exception/InvalidResourceException.phpnu�[���PKv�Z�2B��E2n"Symfony/Component/Translation/Exception/NotFoundResourceException.phpnu�[���PKv�Z�y4��2�p"Symfony/Component/Translation/MessageCatalogue.phpnu�[���PKv�Z%�Mt8��"Symfony/Component/Translation/MetadataAwareInterface.phpnu�[���PKv�Z�d�<<4��"Symfony/Component/Translation/IdentityTranslator.phpnu�[���PKv�Z�e�G��,��"Symfony/Component/Translation/Translator.phpnu�[���PKv�Z��֛�;u�"Symfony/Component/Translation/MessageCatalogueInterface.phpnu�[���PKv�ZM�
���9{�"Symfony/Component/Translation/Dumper/IcuResFileDumper.phpnu�[���PKv�Zਪ(5u�"Symfony/Component/Translation/Dumper/PoFileDumper.phpnu�[���PKv�Z���%LL6��"Symfony/Component/Translation/Dumper/PhpFileDumper.phpnu�[���PKv�Z�<̧��8��"Symfony/Component/Translation/Dumper/XliffFileDumper.phpnu�[���PKv�Z>{GG5��"Symfony/Component/Translation/Dumper/QtFileDumper.phpnu�[���PKv�Z���667Z�"Symfony/Component/Translation/Dumper/YamlFileDumper.phpnu�[���PKv�ZoB���6��"Symfony/Component/Translation/Dumper/CsvFileDumper.phpnu�[���PKv�ZB^�[[3*�"Symfony/Component/Translation/Dumper/FileDumper.phpnu�[���PKv�Z�:$}}7�"Symfony/Component/Translation/Dumper/JsonFileDumper.phpnu�[���PKv�Z&X����6�#Symfony/Component/Translation/Dumper/IniFileDumper.phpnu�[���PKv�Z��<**8
#Symfony/Component/Translation/Dumper/DumperInterface.phpnu�[���PKv�Z����A	A	5�#Symfony/Component/Translation/Dumper/MoFileDumper.phpnu�[���PKv�Zg�?Z�
�
*B#Symfony/Component/Translation/Interval.phpnu�[���PKv�Z�3����5�#Symfony/Component/Translation/TranslatorInterface.phpnu�[���PKv�ZP�?�}}:�%#Symfony/Component/Translation/Writer/TranslationWriter.phpnu�[���PKv�ZN@���6�-#Symfony/Component/Translation/Loader/IniFileLoader.phpnu�[���PKv�Z�T�93#Symfony/Component/Translation/Loader/IcuDatFileLoader.phpnu�[���PKv�ZCS�z
z
9�9#Symfony/Component/Translation/Loader/IcuResFileLoader.phpnu�[���PKv�Z��v���5�D#Symfony/Component/Translation/Loader/MoFileLoader.phpnu�[���PKv�ZR����4&\#Symfony/Component/Translation/Loader/ArrayLoader.phpnu�[���PKv�Z�'s�u	u	7&d#Symfony/Component/Translation/Loader/JsonFileLoader.phpnu�[���PKv�Z�i�3"
"
6n#Symfony/Component/Translation/Loader/CsvFileLoader.phpnu�[���PKv�Z_��BB8�x#Symfony/Component/Translation/Loader/XliffFileLoader.phpnu�[���PKv�Zl#�tt84�#Symfony/Component/Translation/Loader/LoaderInterface.phpnu�[���PKv�Z�*���5�#Symfony/Component/Translation/Loader/PoFileLoader.phpnu�[���PKv�Z�r��;;6o�#Symfony/Component/Translation/Loader/PhpFileLoader.phpnu�[���PKv�Z:�	Z�"�"B�#Symfony/Component/Translation/Loader/schema/dic/xliff-core/xml.xsdnu�[���PKv�Z�xO��T�#Symfony/Component/Translation/Loader/schema/dic/xliff-core/xliff-core-1.2-strict.xsdnu�[���PKv�Z)-d+�	�	5�g%Symfony/Component/Translation/Loader/QtFileLoader.phpnu�[���PKv�Z:����7�q%Symfony/Component/Translation/Loader/YamlFileLoader.phpnu�[���PKw�Z�V�˽�.-z%Symfony/Component/Routing/Annotation/Route.phpnu�[���PKw�Z�<ѹ�+H�%Symfony/Component/Routing/CompiledRoute.phpnu�[���PKw�ZU8���-\�%Symfony/Component/Routing/RouterInterface.phpnu�[���PKw�ZU�cQQ(>�%Symfony/Component/Routing/autoloader.phpnu�[���PKw�Z����'�'+�%Symfony/Component/Routing/RouteCompiler.phpnu�[���PKw�Z��%�%$�%Symfony/Component/Routing/Router.phpnu�[���PKw�Z���q
q
6n�%Symfony/Component/Routing/Matcher/ApacheUrlMatcher.phpnu�[���PKw�Z	�ڗ9E�%Symfony/Component/Routing/Matcher/UrlMatcherInterface.phpnu�[���PKw�Z`�u���=��%Symfony/Component/Routing/Matcher/RequestMatcherInterface.phpnu�[���PKw�Z[z�dd<�&Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.phpnu�[���PKw�Z?�|{��:�&Symfony/Component/Routing/Matcher/Dumper/MatcherDumper.phpnu�[���PKw�Z�x}�44=�&Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.phpnu�[���PKw�Z�bz#z#@A&Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.phpnu�[���PKw�Z�`=e&Symfony/Component/Routing/Matcher/Dumper/DumperCollection.phpnu�[���PKw�Z�N�
�
C�s&Symfony/Component/Routing/Matcher/Dumper/DumperPrefixCollection.phpnu�[���PKw�Z(� ���C�~&Symfony/Component/Routing/Matcher/Dumper/MatcherDumperInterface.phpnu�[���PKw�ZY�IWW8��&Symfony/Component/Routing/Matcher/Dumper/DumperRoute.phpnu�[���PKw�Z�'��9��&Symfony/Component/Routing/Matcher/TraceableUrlMatcher.phpnu�[���PKw�ZGj�C""0��&Symfony/Component/Routing/Matcher/UrlMatcher.phpnu�[���PKw�Z� ��ffE'�&Symfony/Component/Routing/Matcher/RedirectableUrlMatcherInterface.phpnu�[���PKw�Z����==K�&Symfony/Component/Routing/Exception/MissingMandatoryParametersException.phpnu�[���PKw�Zj`j�A��&Symfony/Component/Routing/Exception/InvalidParameterException.phpnu�[���PKw�Znj�W��>/�&Symfony/Component/Routing/Exception/RouteNotFoundException.phpnu�[���PKw�Z��)���:��&Symfony/Component/Routing/Exception/ExceptionInterface.phpnu�[���PKw�Z����JJA��&Symfony/Component/Routing/Exception/MethodNotAllowedException.phpnu�[���PKw�Z?�]�//Af�&Symfony/Component/Routing/Exception/ResourceNotFoundException.phpnu�[���PKw�Z��^�==#�&Symfony/Component/Routing/Route.phpnu�[���PKw�Zr�����:i	'Symfony/Component/Routing/RequestContextAwareInterface.phpnu�[���PKw�Z|,{Ȫ�-p'Symfony/Component/Routing/RouteCollection.phpnu�[���PKw�Z�h�,w)'Symfony/Component/Routing/RequestContext.phpnu�[���PKw�Zմ���I�C'Symfony/Component/Routing/Generator/ConfigurableRequirementsInterface.phpnu�[���PKw�Z�
��1�148M'Symfony/Component/Routing/Generator/UrlGenerator.phpnu�[���PKw�Z�1O�
�
Az'Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.phpnu�[���PKw�Zu�'��>��'Symfony/Component/Routing/Generator/Dumper/GeneratorDumper.phpnu�[���PKw�Z�4��G��'Symfony/Component/Routing/Generator/Dumper/GeneratorDumperInterface.phpnu�[���PKw�Z����@@=�'Symfony/Component/Routing/Generator/UrlGeneratorInterface.phpnu�[���PKw�Zn���hh2Ȥ'Symfony/Component/Routing/Loader/ClosureLoader.phpnu�[���PKw�Z��?�		>��'Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.phpnu�[���PKw�Z~ޟ
�
9�'Symfony/Component/Routing/Loader/AnnotationFileLoader.phpnu�[���PKw�Z~L�W��:�'Symfony/Component/Routing/Loader/AnnotationClassLoader.phpnu�[���PKw�ZP�i{��2��'Symfony/Component/Routing/Loader/PhpFileLoader.phpnu�[���PKw�Z?-[��	�	?5�'Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsdnu�[���PKw�Zأ2D$D$2L�'Symfony/Component/Routing/Loader/XmlFileLoader.phpnu�[���PKw�ZpB�Q Q 3�(Symfony/Component/Routing/Loader/YamlFileLoader.phpnu�[���PKx�ZqF��>>4�5(Symfony/Component/Routing/RouteCompilerInterface.phpnu�[���PKx�Z0���QQ(H9(Symfony/Component/Process/autoloader.phpnu�[���PKx�Zg��'�'*�:(Symfony/Component/Process/ProcessPipes.phpnu�[���PKx�Z��2�{{@6c(Symfony/Component/Process/Exception/ProcessTimedOutException.phpnu�[���PKx�Z�<���:!j(Symfony/Component/Process/Exception/ExceptionInterface.phpnu�[���PKx�Z>H����8:l(Symfony/Component/Process/Exception/RuntimeException.phpnu�[���PKx�Z��W��6�n(Symfony/Component/Process/Exception/LogicException.phpnu�[���PKx�Z˅����@�p(Symfony/Component/Process/Exception/InvalidArgumentException.phpnu�[���PKx�Z��_��>s(Symfony/Component/Process/Exception/ProcessFailedException.phpnu�[���PKx�Z@s�(�x(Symfony/Component/Process/PhpProcess.phpnu�[���PKx�Z�nL	L	*�(Symfony/Component/Process/ProcessUtils.phpnu�[���PKy�Z�!,$

.��(Symfony/Component/Process/ExecutableFinder.phpnu�[���PKy�Z!/���,�(Symfony/Component/Process/ProcessBuilder.phpnu�[���PKy�Zy>�8��1�(Symfony/Component/Process/PhpExecutableFinder.phpnu�[���PKy�Z��M��%ު(Symfony/Component/Process/Process.phpnu�[���PKy�Z[i55ERA)Symfony/Component/Serializer/Normalizer/SerializerAwareNormalizer.phpnu�[���PKy�Z=Vxe::A�D)Symfony/Component/Serializer/Normalizer/NormalizableInterface.phpnu�[���PKy�Z��SVV<�J)Symfony/Component/Serializer/Normalizer/CustomNormalizer.phpnu�[���PKy�Z��,,BiR)Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.phpnu�[���PKy�Z"p�yy?q)Symfony/Component/Serializer/Normalizer/NormalizerInterface.phpnu�[���PKy�Z�qU���C�u)Symfony/Component/Serializer/Normalizer/DenormalizableInterface.phpnu�[���PKz�Z���A�{)Symfony/Component/Serializer/Normalizer/DenormalizerInterface.phpnu�[���PKz�Z���OO9t�)Symfony/Component/Serializer/SerializerAwareInterface.phpnu�[���PKz�Z��TT+,�)Symfony/Component/Serializer/autoloader.phpnu�[���PKz�Zx蕰

4ۅ)Symfony/Component/Serializer/SerializerInterface.phpnu�[���PKz�Z,�c��9L�)Symfony/Component/Serializer/Encoder/EncoderInterface.phpnu�[���PKz�Z��[�5�53i�)Symfony/Component/Serializer/Encoder/XmlEncoder.phpnu�[���PKz�Z�<=ggD��)Symfony/Component/Serializer/Encoder/NormalizationAwareInterface.phpnu�[���PKz�ZV��O��5��)Symfony/Component/Serializer/Encoder/ChainDecoder.phpnu�[���PKz�Z�=��?��)Symfony/Component/Serializer/Encoder/SerializerAwareEncoder.phpnu�[���PKz�Zv:�hh3[�)Symfony/Component/Serializer/Encoder/JsonEncode.phpnu�[���PKz�Z��@���3&�)Symfony/Component/Serializer/Encoder/JsonDecode.phpnu�[���PKz�ZS R�	�	5q�)Symfony/Component/Serializer/Encoder/ChainEncoder.phpnu�[���PKz�Z�o�vv4��)Symfony/Component/Serializer/Encoder/JsonEncoder.phpnu�[���PKz�Z|ͼ���9��)Symfony/Component/Serializer/Encoder/DecoderInterface.phpnu�[���PKz�ZA�A
��4�*Symfony/Component/Serializer/Exception/Exception.phpnu�[���PKz�Z�^L��?�*Symfony/Component/Serializer/Exception/UnsupportedException.phpnu�[���PKz�Z�h=��;�*Symfony/Component/Serializer/Exception/RuntimeException.phpnu�[���PKz�ZJ���9�*Symfony/Component/Serializer/Exception/LogicException.phpnu�[���PKz�ZT��Y��C	*Symfony/Component/Serializer/Exception/InvalidArgumentException.phpnu�[���PKz�Z[�����Ci*Symfony/Component/Serializer/Exception/UnexpectedValueException.phpnu�[���PKz�Zʪ2/&/&+�
*Symfony/Component/Serializer/Serializer.phpnu�[���PKz�ZFP�PP'<4*Symfony/Component/Locale/autoloader.phpnu�[���PKz�Z�Q�UUL�5*Symfony/Component/Locale/Exception/MethodArgumentNotImplementedException.phpnu�[���PKz�Z��E>�9*Symfony/Component/Locale/Exception/NotImplementedException.phpnu�[���PKz�ZS�?a%%D#=*Symfony/Component/Locale/Exception/MethodNotImplementedException.phpnu�[���PKz�Z���ssQ�@*Symfony/Component/Locale/Exception/MethodArgumentValueNotImplementedException.phpnu�[���PKz�Z�C��*�D*Symfony/Component/Locale/Stub/StubIntl.phpnu�[���PKz�Z&�����5�G*Symfony/Component/Locale/Stub/StubNumberFormatter.phpnu�[���PKz�Zv/�@�J*Symfony/Component/Locale/Stub/DateFormat/Hour2401Transformer.phpnu�[���PKz�Z��S@PN*Symfony/Component/Locale/Stub/DateFormat/TimeZoneTransformer.phpnu�[���PKz�Z}��""A�Q*Symfony/Component/Locale/Stub/DateFormat/DayOfYearTransformer.phpnu�[���PKz�Z�X�<oU*Symfony/Component/Locale/Stub/DateFormat/AmPmTransformer.phpnu�[���PKz�Z���<�X*Symfony/Component/Locale/Stub/DateFormat/YearTransformer.phpnu�[���PKz�Zmў?O\*Symfony/Component/Locale/Stub/DateFormat/QuarterTransformer.phpnu�[���PKz�Zg[ep>�_*Symfony/Component/Locale/Stub/DateFormat/MinuteTransformer.phpnu�[���PKz�Z:6""ARc*Symfony/Component/Locale/Stub/DateFormat/DayOfWeekTransformer.phpnu�[���PKz�Z9�u@�f*Symfony/Component/Locale/Stub/DateFormat/Hour1200Transformer.phpnu�[���PKz�Zk&"M@qj*Symfony/Component/Locale/Stub/DateFormat/Hour1201Transformer.phpnu�[���PKz�Z�����;�m*Symfony/Component/Locale/Stub/DateFormat/DayTransformer.phpnu�[���PKz�Z��@fq*Symfony/Component/Locale/Stub/DateFormat/Hour2400Transformer.phpnu�[���PKz�Z�Ed��8�t*Symfony/Component/Locale/Stub/DateFormat/Transformer.phpnu�[���PKz�Zt�z

=Ox*Symfony/Component/Locale/Stub/DateFormat/MonthTransformer.phpnu�[���PKz�Zk�H<�{*Symfony/Component/Locale/Stub/DateFormat/FullTransformer.phpnu�[���PKz�Z�3�X>6*Symfony/Component/Locale/Stub/DateFormat/SecondTransformer.phpnu�[���PKz�Z�
�

<��*Symfony/Component/Locale/Stub/DateFormat/HourTransformer.phpnu�[���PKz�Z���?��.-�*Symfony/Component/Locale/Stub/StubCollator.phpnu�[���PK{�Zq��*((,�*Symfony/Component/Locale/Stub/StubLocale.phpnu�[���PK{�Z� S���7��*Symfony/Component/Locale/Stub/StubIntlDateFormatter.phpnu�[���PK{�Zl�l��#��*Symfony/Component/Locale/Locale.phpnu�[���PK{�Z�t�TT+��*Symfony/Component/Filesystem/autoloader.phpnu�[���PK{�Z��dP��@b�*Symfony/Component/Filesystem/Exception/FileNotFoundException.phpnu�[���PK{�Z3{����=��*Symfony/Component/Filesystem/Exception/ExceptionInterface.phpnu�[���PK{�ZoC�~��?��*Symfony/Component/Filesystem/Exception/IOExceptionInterface.phpnu�[���PK{�Z;�{��6ͷ*Symfony/Component/Filesystem/Exception/IOException.phpnu�[���PK{�ZOظ�GG+�*Symfony/Component/Filesystem/Filesystem.phpnu�[���PK{�Z)��.�.'T+Symfony/Component/Form/FormRenderer.phpnu�[���PK{�Z�C����.]2+Symfony/Component/Form/ButtonTypeInterface.phpnu�[���PK{�ZK'�$��&�4+Symfony/Component/Form/FormBuilder.phpnu�[���PK{�Z&�"̰T�T,�S+Symfony/Component/Form/FormConfigBuilder.phpnu�[���PK{�ZE1�'��4��+Symfony/Component/Form/SubmitButtonTypeInterface.phpnu�[���PK{�Z�d��'�+Symfony/Component/Form/FormRegistry.phpnu�[���PK{�ZÊM'%%.н+Symfony/Component/Form/FormConfigInterface.phpnu�[���PK{�Z��@@/S�+Symfony/Component/Form/FormTypeGuesserChain.phpnu�[���PK{�ZR����+��+Symfony/Component/Form/Guess/ValueGuess.phpnu�[���PK{�Z�511&,�+Symfony/Component/Form/Guess/Guess.phpnu�[���PK{�Z���  *��+Symfony/Component/Form/Guess/TypeGuess.phpnu�[���PK{�Z�0\ZZ.-�+Symfony/Component/Form/CallbackTransformer.phpnu�[���PK{�Z4�Nz"z"!�,Symfony/Component/Form/Button.phpnu�[���PK{�Z-�9NN%�%,Symfony/Component/Form/autoloader.phpnu�[���PK{�Z�/��tt%S',Symfony/Component/Form/FormEvents.phpnu�[���PK{�Z�����,,,Symfony/Component/Form/FormTypeInterface.phpnu�[���PK{�Z�>���09,Symfony/Component/Form/FormRegistryInterface.phpnu�[���PK{�Z��?zz3?,Symfony/Component/Form/FormTypeGuesserInterface.phpnu�[���PK{�Z��*��+�G,Symfony/Component/Form/ResolvedFormType.phpnu�[���PK{�ZObX�qq'6f,Symfony/Component/Form/SubmitButton.phpnu�[���PK|�Z�p��1�j,Symfony/Component/Form/AbstractRendererEngine.phpnu�[���PK|�ZDjN,1�,Symfony/Component/Form/AbstractExtension.phpnu�[���PK|�Zf#jK��6��,Symfony/Component/Form/FormRendererEngineInterface.phpnu�[���PK|�Z���1�1���,Symfony/Component/Form/Form.phpnu�[���PK|�Z�di���;A-Symfony/Component/Form/Exception/BadMethodCallException.phpnu�[���PK|�Z�W�

:yC-Symfony/Component/Form/Exception/AlreadyBoundException.phpnu�[���PK|�Z(ddB�E-Symfony/Component/Form/Exception/InvalidConfigurationException.phpnu�[���PK|�Z�_c==<�G-Symfony/Component/Form/Exception/UnexpectedTypeException.phpnu�[���PK|�Z�S�D��BoJ-Symfony/Component/Form/Exception/TransformationFailedException.phpnu�[���PK|�Z��9�L-Symfony/Component/Form/Exception/OutOfBoundsException.phpnu�[���PK}�Z�y�u��7�N-Symfony/Component/Form/Exception/ExceptionInterface.phpnu�[���PK}�ZN����5
Q-Symfony/Component/Form/Exception/RuntimeException.phpnu�[���PK}�ZK�9���>OS-Symfony/Component/Form/Exception/AlreadySubmittedException.phpnu�[���PK}�Z1�;TT:�U-Symfony/Component/Form/Exception/ErrorMappingException.phpnu�[���PK}�Z��+RR8oW-Symfony/Component/Form/Exception/StringCastException.phpnu�[���PK}�Z��X��3)Y-Symfony/Component/Form/Exception/LogicException.phpnu�[���PK}�Z�gBz��=d[-Symfony/Component/Form/Exception/InvalidArgumentException.phpnu�[���PK}�Z�1��88'�]-Symfony/Component/Form/AbstractType.phpnu�[���PK}�Z�I	�66.Ub-Symfony/Component/Form/Util/OrderedHashMap.phpnu�[���PK}�Z�h��''6�t-Symfony/Component/Form/Util/OrderedHashMapIterator.phpnu�[���PK}�Z��F228v�-Symfony/Component/Form/Util/VirtualFormAwareIterator.phpnu�[���PK}�Zy���$$(�-Symfony/Component/Form/Util/FormUtil.phpnu�[���PK}�Z<����8��-Symfony/Component/Form/Util/InheritDataAwareIterator.phpnu�[���PK}�Z�QT�pp.�-Symfony/Component/Form/SubmitButtonBuilder.phpnu�[���PK}�Z�z5���2��-Symfony/Component/Form/ResolvedFormTypeFactory.phpnu�[���PK}�ZSf��
	
	-��-Symfony/Component/Form/PreloadedExtension.phpnu�[���PK}�Z>��*ii&�-Symfony/Component/Form/FormFactory.phpnu�[���PK}�Z�\�g��2˳-Symfony/Component/Form/RequestHandlerInterface.phpnu�[���PK}�Z+q�DAA7ɶ-Symfony/Component/Form/Test/FormPerformanceTestCase.phpnu�[���PK}�ZsŪ�,q�-Symfony/Component/Form/Test/TypeTestCase.phpnu�[���PK}�Z�,�7//7�-Symfony/Component/Form/Test/DeprecationErrorHandler.phpnu�[���PK}�ZB�4I++7k�-Symfony/Component/Form/Test/FormIntegrationTestCase.phpnu�[���PK}�Z��m�yy4��-Symfony/Component/Form/Test/FormBuilderInterface.phpnu�[���PK}�Za(0kk-��-Symfony/Component/Form/Test/FormInterface.phpnu�[���PK}�Z�n����1��-Symfony/Component/Form/FormExtensionInterface.phpnu�[���PK}�Z|G����4��-Symfony/Component/Form/ResolvedFormTypeInterface.phpnu�[���PK}�Z{d���!�!5��-Symfony/Component/Form/FormConfigBuilderInterface.phpnu�[���PK}�ZɃT���6.Symfony/Component/Form/FormFactoryBuilderInterface.phpnu�[���PK}�Z�N̷;m.Symfony/Component/Form/ResolvedFormTypeFactoryInterface.phpnu�[���PK}�Z2��-�.Symfony/Component/Form/FormFactoryBuilder.phpnu�[���PK}�Z���C��0d$.Symfony/Component/Form/AbstractTypeExtension.phpnu�[���PK}�Z�E���0�(.Symfony/Component/Form/FormRendererInterface.phpnu�[���PK}�Z�:		/�5.Symfony/Component/Form/FormBuilderInterface.phpnu�[���PK}�Z��Z)��/R?.Symfony/Component/Form/FormFactoryInterface.phpnu�[���PK}�Z�YB���.EP.Symfony/Component/Form/ReversedTransformer.phpnu�[���PK}�Z�r�WW3�U.Symfony/Component/Form/DataTransformerInterface.phpnu�[���PK}�ZW�b�[H[H(Eb.Symfony/Component/Form/ButtonBuilder.phpnu�[���PK}�Z��n��?��.Symfony/Component/Form/Resources/translations/validators.en.xlfnu�[���PK}�Z誫���?�.Symfony/Component/Form/Resources/translations/validators.sk.xlfnu�[���PK}�Z�<�yy?=�.Symfony/Component/Form/Resources/translations/validators.uk.xlfnu�[���PK}�Z:����?%�.Symfony/Component/Form/Resources/translations/validators.pl.xlfnu�[���PK��Z��
���?[�.Symfony/Component/Form/Resources/translations/validators.pt.xlfnu�[���PK��Z�%��?��.Symfony/Component/Form/Resources/translations/validators.lv.xlfnu�[���PK��Z္o33D��.Symfony/Component/Form/Resources/translations/validators.sr_Cyrl.xlfnu�[���PK��Z����?��.Symfony/Component/Form/Resources/translations/validators.fi.xlfnu�[���PK��Z0h���?��.Symfony/Component/Form/Resources/translations/validators.es.xlfnu�[���PK��Z�TI��?,�.Symfony/Component/Form/Resources/translations/validators.de.xlfnu�[���PK��Z!�aZ��?~�.Symfony/Component/Form/Resources/translations/validators.it.xlfnu�[���PK��Z �!���?��.Symfony/Component/Form/Resources/translations/validators.ca.xlfnu�[���PK��Z���?��.Symfony/Component/Form/Resources/translations/validators.mn.xlfnu�[���PK��Z���-��?X�.Symfony/Component/Form/Resources/translations/validators.ru.xlfnu�[���PK��Z�3Ե^^?T�.Symfony/Component/Form/Resources/translations/validators.bg.xlfnu�[���PK��ZE��d��?!�.Symfony/Component/Form/Resources/translations/validators.ro.xlfnu�[���PK��ZO���?r�.Symfony/Component/Form/Resources/translations/validators.nl.xlfnu�[���PK��ZS�*��?��.Symfony/Component/Form/Resources/translations/validators.et.xlfnu�[���PK��Z�V5?��.Symfony/Component/Form/Resources/translations/validators.fa.xlfnu�[���PK��Z��q��?J�.Symfony/Component/Form/Resources/translations/validators.id.xlfnu�[���PK��Z�
���?w/Symfony/Component/Form/Resources/translations/validators.cs.xlfnu�[���PK��Z�8,:��B�/Symfony/Component/Form/Resources/translations/validators.zh_CN.xlfnu�[���PK��Z�H�q��?�
/Symfony/Component/Form/Resources/translations/validators.lt.xlfnu�[���PK��Z�_8��?�/Symfony/Component/Form/Resources/translations/validators.fr.xlfnu�[���PK��Z�A�4��?�/Symfony/Component/Form/Resources/translations/validators.gl.xlfnu�[���PK��Z
b�8��?4/Symfony/Component/Form/Resources/translations/validators.hr.xlfnu�[���PK��ZWgUugg?]/Symfony/Component/Form/Resources/translations/validators.nb.xlfnu�[���PK��Zٻ��||?3/Symfony/Component/Form/Resources/translations/validators.eu.xlfnu�[���PK��Z�4@���B#/Symfony/Component/Form/Resources/translations/validators.pt_BR.xlfnu�[���PK��Z��5��?Q'/Symfony/Component/Form/Resources/translations/validators.sl.xlfnu�[���PK��Z�*{���?m+/Symfony/Component/Form/Resources/translations/validators.lb.xlfnu�[���PK��Zbe�@��?�//Symfony/Component/Form/Resources/translations/validators.hu.xlfnu�[���PK��Z_Π��?4/Symfony/Component/Form/Resources/translations/validators.el.xlfnu�[���PK��ZX�����?9/Symfony/Component/Form/Resources/translations/validators.da.xlfnu�[���PK��Z���?�</Symfony/Component/Form/Resources/translations/validators.ja.xlfnu�[���PK��Zs>�ll?AA/Symfony/Component/Form/Resources/translations/validators.sv.xlfnu�[���PK��Zy��99?E/Symfony/Component/Form/Resources/translations/validators.hy.xlfnu�[���PK��Z|��C?�I/Symfony/Component/Form/Resources/translations/validators.ar.xlfnu�[���PK��Zr���DBN/Symfony/Component/Form/Resources/translations/validators.sr_Latn.xlfnu�[���PK��ZNP\��?dR/Symfony/Component/Form/Resources/translations/validators.he.xlfnu�[���PK��Z�xfh..6dV/Symfony/Component/Form/Resources/config/validation.xmlnu�[���PK��ZR}��jj.�X/Symfony/Component/Form/DataMapperInterface.phpnu�[���PK��Z�s�� � (�]/Symfony/Component/Form/FormInterface.phpnu�[���PK��Z���"��$�~/Symfony/Component/Form/FormEvent.phpnu�[���PK��Z�=�MM5Ӄ/Symfony/Component/Form/FormTypeExtensionInterface.phpnu�[���PK��Z�}p�

$��/Symfony/Component/Form/FormError.phpnu�[���PK��Z�	���/ܖ/Symfony/Component/Form/NativeRequestHandler.phpnu�[���PK��Z���*��O'�/Symfony/Component/Form/Extension/Validator/EventListener/ValidationListener.phpnu�[���PK��Z��Ck��@5�/Symfony/Component/Form/Extension/Validator/Util/ServerParams.phpnu�[���PK��Z2=[<((A1�/Symfony/Component/Form/Extension/Validator/ValidatorExtension.phpnu�[���PK��Z}>�ُ�?��/Symfony/Component/Form/Extension/Validator/Constraints/Form.phpnu�[���PK��Z�-�P��H��/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.phpnu�[���PK��Zl�Ct*t*C��/Symfony/Component/Form/Extension/Validator/ValidatorTypeGuesser.phpnu�[���PK��ZɥS��T�
0Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPathIterator.phpnu�[���PK��Z�\T��K0Symfony/Component/Form/Extension/Validator/ViolationMapper/RelativePath.phpnu�[���PK��ZC_�hU+U+N0Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.phpnu�[���PK��Z�k�t==W�@0Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapperInterface.phpnu�[���PK��Z�-��!!L�E0Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPath.phpnu�[���PK��Zf����
�
JR_0Symfony/Component/Form/Extension/Validator/ViolationMapper/MappingRule.phpnu�[���PK��Z�����J�j0Symfony/Component/Form/Extension/Validator/Type/BaseValidatorExtension.phpnu�[���PK��ZeBR�	�	N�p0Symfony/Component/Form/Extension/Validator/Type/FormTypeValidatorExtension.phpnu�[���PK��Z͚>�@@R+{0Symfony/Component/Form/Extension/Validator/Type/RepeatedTypeValidatorExtension.phpnu�[���PK��Z1���P�0Symfony/Component/Form/Extension/Validator/Type/SubmitTypeValidatorExtension.phpnu�[���PK��Z���,QQC��0Symfony/Component/Form/Extension/Templating/TemplatingExtension.phpnu�[���PK��Zզ�Y��HL�0Symfony/Component/Form/Extension/Templating/TemplatingRendererEngine.phpnu�[���PK��Z䋧��U��0Symfony/Component/Form/Extension/HttpFoundation/EventListener/BindRequestListener.phpnu�[���PK��Z�j��=
=
PԦ0Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationRequestHandler.phpnu�[���PK��Z��Q��K��0Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationExtension.phpnu�[���PK��Z�PffX��0Symfony/Component/Form/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.phpnu�[���PK��Z"�q���7��0Symfony/Component/Form/Extension/Csrf/CsrfExtension.phpnu�[���PK��Z�C���J��0Symfony/Component/Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.phpnu�[���PK��Z[^����J��0Symfony/Component/Form/Extension/Csrf/CsrfProvider/SessionCsrfProvider.phpnu�[���PK��Z%�G���L�0Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderInterface.phpnu�[���PK��Z�����JI�0Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderAdapter.phpnu�[���PK��ZR�'WTTN��0Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfTokenManagerAdapter.phpnu�[���PK��Z�?�ooNy�0Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.phpnu�[���PK��Z��
f��Df�0Symfony/Component/Form/Extension/Csrf/Type/FormTypeCsrfExtension.phpnu�[���PK��ZC�W���7�
1Symfony/Component/Form/Extension/Core/CoreExtension.phpnu�[���PK��Z�:AAD�1Symfony/Component/Form/Extension/Core/EventListener/TrimListener.phpnu�[���PK��Zõe��O�1Symfony/Component/Form/Extension/Core/EventListener/MergeCollectionListener.phpnu�[���PK��Z>Q?��N�+1Symfony/Component/Form/Extension/Core/EventListener/FixUrlProtocolListener.phpnu�[���PK��Zb����P�11Symfony/Component/Form/Extension/Core/EventListener/FixCheckboxInputListener.phpnu�[���PK��Z\��//J�=1Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.phpnu�[���PK��Z?D���M�Q1Symfony/Component/Form/Extension/Core/EventListener/FixRadioInputListener.phpnu�[���PK��Z�jю��E�Z1Symfony/Component/Form/Extension/Core/ChoiceList/SimpleChoiceList.phpnu�[���PK��Z�
�##E�p1Symfony/Component/Form/Extension/Core/ChoiceList/ObjectChoiceList.phpnu�[���PK��Zl_R(H��1Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceListInterface.phpnu�[���PK��Z�В4
4
C�1Symfony/Component/Form/Extension/Core/ChoiceList/LazyChoiceList.phpnu�[���PK��Z'���??��1Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceList.phpnu�[���PK��Z��&PP9��1Symfony/Component/Form/Extension/Core/View/ChoiceView.phpnu�[���PK��Z��

Gl�1Symfony/Component/Form/Extension/Core/DataMapper/PropertyPathMapper.phpnu�[���PK��ZO�#�#�#\�2Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.phpnu�[���PK��Z)b�""^)2Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.phpnu�[���PK��Ze�^�		V�?2Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.phpnu�[���PK��Z���Þ
�
XVI2Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.phpnu�[���PK��Zc�8V�	�	N|T2Symfony/Component/Form/Extension/Core/DataTransformer/DataTransformerChain.phpnu�[���PK��Z�;�dd]�^2Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.phpnu�[���PK��Z�Z�eTwo2Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToArrayTransformer.phpnu�[���PK��ZL�px&&Y�2Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.phpnu�[���PK��Z����		V��2Symfony/Component/Form/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.phpnu�[���PK��Z'tqk55ZJ�2Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.phpnu�[���PK��Z���ggT	�2Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToValuesTransformer.phpnu�[���PK��ZUd�q]�2Symfony/Component/Form/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.phpnu�[���PK��ZΎgW� � U��2Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToStringTransformer.phpnu�[���PK��Z�"h���R��2Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToValueTransformer.phpnu�[���PK��Z�H��		Q��2Symfony/Component/Form/Extension/Core/DataTransformer/ArrayToPartsTransformer.phpnu�[���PK��Z/C���QO�2Symfony/Component/Form/Extension/Core/DataTransformer/BaseDateTimeTransformer.phpnu�[���PK��Z���T��T��2Symfony/Component/Form/Extension/Core/DataTransformer/BooleanToStringTransformer.phpnu�[���PK��Z]��yD	D	[/3Symfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.phpnu�[���PK��Z���/�+�+9�
3Symfony/Component/Form/Extension/Core/Type/ChoiceType.phpnu�[���PK��Z��h��9:3Symfony/Component/Form/Extension/Core/Type/ButtonType.phpnu�[���PK��ZD�U��9s>3Symfony/Component/Form/Extension/Core/Type/SubmitType.phpnu�[���PK��Z񍢸��;�B3Symfony/Component/Form/Extension/Core/Type/CurrencyType.phpnu�[���PK��Z�Ѝ'��9�F3Symfony/Component/Form/Extension/Core/Type/HiddenType.phpnu�[���PK��Z���D��9�J3Symfony/Component/Form/Extension/Core/Type/LocaleType.phpnu�[���PK��ZuƵ�``:O3Symfony/Component/Form/Extension/Core/Type/IntegerType.phpnu�[���PK��Za����8�W3Symfony/Component/Form/Extension/Core/Type/ResetType.phpnu�[���PK��Z옇���;'[3Symfony/Component/Form/Extension/Core/Type/PasswordType.phpnu�[���PK��Zٝ��GG7]`3Symfony/Component/Form/Extension/Core/Type/BaseType.phpnu�[���PK��ZZ���^^:r3Symfony/Component/Form/Extension/Core/Type/PercentType.phpnu�[���PK��Z��TT;�w3Symfony/Component/Form/Extension/Core/Type/CheckboxType.phpnu�[���PK��Z&ߏ�vv;��3Symfony/Component/Form/Extension/Core/Type/BirthdayType.phpnu�[���PK��Z7pO�LL8s�3Symfony/Component/Form/Extension/Core/Type/RadioType.phpnu�[���PK��Z�G�oo7'�3Symfony/Component/Form/Extension/Core/Type/FileType.phpnu�[���PK��Z�8��JJ9��3Symfony/Component/Form/Extension/Core/Type/SearchType.phpnu�[���PK��Z�_��LL;��3Symfony/Component/Form/Extension/Core/Type/TimezoneType.phpnu�[���PK��Z���HH8g�3Symfony/Component/Form/Extension/Core/Type/EmailType.phpnu�[���PK��Z[Gԃ��=�3Symfony/Component/Form/Extension/Core/Type/CollectionType.phpnu�[���PK��Z�t�II;1�3Symfony/Component/Form/Extension/Core/Type/TextareaType.phpnu�[���PK��Z����;�3Symfony/Component/Form/Extension/Core/Type/LanguageType.phpnu�[���PK��ZT;���7��3Symfony/Component/Form/Extension/Core/Type/TextType.phpnu�[���PK��ZH?!a��7J�3Symfony/Component/Form/Extension/Core/Type/TimeType.phpnu�[���PK��Z�� &�'�';��3Symfony/Component/Form/Extension/Core/Type/DateTimeType.phpnu�[���PK��Z�q���6��3Symfony/Component/Form/Extension/Core/Type/UrlType.phpnu�[���PK��Z9�;�3Symfony/Component/Form/Extension/Core/Type/RepeatedType.phpnu�[���PK��ZM2\3,3,7E4Symfony/Component/Form/Extension/Core/Type/DateType.phpnu�[���PK��Za�LŢ�:�34Symfony/Component/Form/Extension/Core/Type/CountryType.phpnu�[���PK��ZC�i���9�74Symfony/Component/Form/Extension/Core/Type/NumberType.phpnu�[���PK��Z:�y�

7;@4Symfony/Component/Form/Extension/Core/Type/FormType.phpnu�[���PK��Z5�S
��8�\4Symfony/Component/Form/Extension/Core/Type/MoneyType.phpnu�[���PK��Z6s���D�i4Symfony/Component/Form/Extension/DataCollector/FormDataCollector.phpnu�[���PK��ZI��2

Vȇ4Symfony/Component/Form/Extension/DataCollector/EventListener/DataCollectorListener.phpnu�[���PK��Z�T���Mc�4Symfony/Component/Form/Extension/DataCollector/FormDataCollectorInterface.phpnu�[���PK��Z����M��4Symfony/Component/Form/Extension/DataCollector/FormDataExtractorInterface.phpnu�[���PK��Z|�
]��W�4Symfony/Component/Form/Extension/DataCollector/Proxy/ResolvedTypeDataCollectorProxy.phpnu�[���PK��Z�((^6�4Symfony/Component/Form/Extension/DataCollector/Proxy/ResolvedTypeFactoryDataCollectorProxy.phpnu�[���PK��Z��#�11I�4Symfony/Component/Form/Extension/DataCollector/DataCollectorExtension.phpnu�[���PK��Z%�`��D��4Symfony/Component/Form/Extension/DataCollector/FormDataExtractor.phpnu�[���PK��Z�1�
uuR��4Symfony/Component/Form/Extension/DataCollector/Type/DataCollectorTypeExtension.phpnu�[���PK��ZuUS�WWU��4Symfony/Component/Form/Extension/DependencyInjection/DependencyInjectionExtension.phpnu�[���PK��Z(s
//-a�4Symfony/Component/Form/ClickableInterface.phpnu�[���PK��ZH��
�
#��4Symfony/Component/Form/FormView.phpnu�[���PK��Z
�͋ �4Symfony/Component/Form/Forms.phpnu�[���PK��Z\�F1_
5Symfony/Component/Security/Acl/Voter/AclVoter.phpnu�[���PK��Z\!�	HH2�#5Symfony/Component/Security/Acl/Voter/FieldVote.phpnu�[���PK��ZP͡��Am'5Symfony/Component/Security/Acl/Exception/AclNotFoundException.phpnu�[���PK��Z�k�q��6�)5Symfony/Component/Security/Acl/Exception/Exception.phpnu�[���PK��Z�W�L�+5Symfony/Component/Security/Acl/Exception/ConcurrentModificationException.phpnu�[���PK��Z���OI}.5Symfony/Component/Security/Acl/Exception/InvalidDomainObjectException.phpnu�[���PK��Z]��_""E15Symfony/Component/Security/Acl/Exception/NotAllAclsFoundException.phpnu�[���PK��Z�B�l��@�55Symfony/Component/Security/Acl/Exception/NoAceFoundException.phpnu�[���PK��Z[�z�B�85Symfony/Component/Security/Acl/Exception/SidNotLoadedException.phpnu�[���PK��Z��5�

F;5Symfony/Component/Security/Acl/Exception/AclAlreadyExistsException.phpnu�[���PK��Zt��:�=5Symfony/Component/Security/Acl/Dbal/MutableAclProvider.phpnu�[���PK��Z�^�+f+f3��5Symfony/Component/Security/Acl/Dbal/AclProvider.phpnu�[���PK��ZK� V��.n,6Symfony/Component/Security/Acl/Dbal/Schema.phpnu�[���PK��ZNTA�]]5�D6Symfony/Component/Security/Acl/Domain/AuditLogger.phpnu�[���PK��Z�.��**>sJ6Symfony/Component/Security/Acl/Domain/UserSecurityIdentity.phpnu�[���PK��Z��C3��:W6Symfony/Component/Security/Acl/Domain/DoctrineAclCache.phpnu�[���PK��Z(]���D#p6Symfony/Component/Security/Acl/Domain/PermissionGrantingStrategy.phpnu�[���PK��Z%�}`M`M-k�6Symfony/Component/Security/Acl/Domain/Acl.phpnu�[���PK��Z����K(�6Symfony/Component/Security/Acl/Domain/SecurityIdentityRetrievalStrategy.phpnu�[���PK��Z�X�
/	/	<K�6Symfony/Component/Security/Acl/Domain/AclCollectionCache.phpnu�[���PK��Z5D�[/��6Symfony/Component/Security/Acl/Domain/Entry.phpnu�[���PK��Z�pU���4H7Symfony/Component/Security/Acl/Domain/FieldEntry.phpnu�[���PK��Z^@�.YY8R7Symfony/Component/Security/Acl/Domain/ObjectIdentity.phpnu�[���PK��Z0F���I7Symfony/Component/Security/Acl/Domain/ObjectIdentityRetrievalStrategy.phpnu�[���PK��ZtA)�==>J7Symfony/Component/Security/Acl/Domain/RoleSecurityIdentity.phpnu�[���PK��Z�#��~~<�#7Symfony/Component/Security/Acl/Resources/bin/generateSql.phpnu�[���PK��Zj~	cFF7�+7Symfony/Component/Security/Acl/Resources/schema/db2.sqlnu�[���PK��ZT��skk>�87Symfony/Component/Security/Acl/Resources/schema/postgresql.sqlnu�[���PK��ZJx�.

9eE7Symfony/Component/Security/Acl/Resources/schema/mssql.sqlnu�[���PK��ZfZ��^^9�R7Symfony/Component/Security/Acl/Resources/schema/mysql.sqlnu�[���PK��Z��c�
�
;�^7Symfony/Component/Security/Acl/Resources/schema/drizzle.sqlnu�[���PK��Z�C� ;;:�i7Symfony/Component/Security/Acl/Resources/schema/oracle.sqlnu�[���PK��Z��d��:I�7Symfony/Component/Security/Acl/Resources/schema/sqlite.sqlnu�[���PK��Zw���D��7Symfony/Component/Security/Acl/Permission/PermissionMapInterface.phpnu�[���PK��Z�ep�gg9��7Symfony/Component/Security/Acl/Permission/MaskBuilder.phpnu�[���PK��Z� c0��@ͫ7Symfony/Component/Security/Acl/Permission/BasicPermissionMap.phpnu�[���PK��Z6����<��7Symfony/Component/Security/Acl/Model/MutableAclInterface.phpnu�[���PK��Z[Ob3SK�7Symfony/Component/Security/Acl/Model/SecurityIdentityRetrievalStrategyInterface.phpnu�[���PK��ZX	��>��7Symfony/Component/Security/Acl/Model/DomainObjectInterface.phpnu�[���PK��Z�5Ayy@
�7Symfony/Component/Security/Acl/Model/ObjectIdentityInterface.phpnu�[���PK��Zt��@��7Symfony/Component/Security/Acl/Model/AuditableEntryInterface.phpnu�[���PK��Z-癥��Lk�7Symfony/Component/Security/Acl/Model/PermissionGrantingStrategyInterface.phpnu�[���PK��Z�����=��7Symfony/Component/Security/Acl/Model/AclProviderInterface.phpnu�[���PK��Z�#���:&�7Symfony/Component/Security/Acl/Model/AclCacheInterface.phpnu�[���PK��Zӗ&1>��7Symfony/Component/Security/Acl/Model/AuditableAclInterface.phpnu�[���PK��Z�ݤUU<�7Symfony/Component/Security/Acl/Model/FieldEntryInterface.phpnu�[���PK��Z�
�8FF7�7Symfony/Component/Security/Acl/Model/EntryInterface.phpnu�[���PK��ZH<J��=��7Symfony/Component/Security/Acl/Model/AuditLoggerInterface.phpnu�[���PK��Z���77B�8Symfony/Component/Security/Acl/Model/SecurityIdentityInterface.phpnu�[���PK��Z�𕛼�5L8Symfony/Component/Security/Acl/Model/AclInterface.phpnu�[���PK��Z�W}��Qm8Symfony/Component/Security/Acl/Model/ObjectIdentityRetrievalStrategyInterface.phpnu�[���PK��Zj���D�8Symfony/Component/Security/Acl/Model/MutableAclProviderInterface.phpnu�[���PK��Z��W"RR)�8Symfony/Component/Security/autoloader.phpnu�[���PK��Z�DXVV,t8Symfony/Component/Security/Http/Firewall.phpnu�[���PK��Z"�C��/&'8Symfony/Component/Security/Http/FirewallMap.phpnu�[���PK��Z�יK--8Symfony/Component/Security/Http/EntryPoint/FormAuthenticationEntryPoint.phpnu�[���PK��Z�<ݐppL�58Symfony/Component/Security/Http/EntryPoint/BasicAuthenticationEntryPoint.phpnu�[���PK��Z)'_++P�:8Symfony/Component/Security/Http/EntryPoint/AuthenticationEntryPointInterface.phpnu�[���PK��ZtZ�)K	K	MN?8Symfony/Component/Security/Http/EntryPoint/DigestAuthenticationEntryPoint.phpnu�[���PK��Z�����LI8Symfony/Component/Security/Http/EntryPoint/RetryAuthenticationEntryPoint.phpnu�[���PK��Z��`C��-,P8Symfony/Component/Security/Http/HttpUtils.phpnu�[���PK��Z^�V��N^h8Symfony/Component/Security/Http/Authorization/AccessDeniedHandlerInterface.phpnu�[���PK��Z��̗��W�l8Symfony/Component/Security/Http/Firewall/UsernamePasswordFormAuthenticationListener.phpnu�[���PK��Znz+S�
�
?8Symfony/Component/Security/Http/Firewall/RememberMeListener.phpnu�[���PK��Zlٯ��L6�8Symfony/Component/Security/Http/Firewall/AnonymousAuthenticationListener.phpnu�[���PK��Z�����>��8Symfony/Component/Security/Http/Firewall/ListenerInterface.phpnu�[���PK��Z�|L@**;��8Symfony/Component/Security/Http/Firewall/LogoutListener.phpnu�[���PK��Z�Bb

?J�8Symfony/Component/Security/Http/Firewall/SwitchUserListener.phpnu�[���PK��Z(�T	b!b!>��8Symfony/Component/Security/Http/Firewall/ExceptionListener.phpnu�[���PK��Z׺�=��G��8Symfony/Component/Security/Http/Firewall/X509AuthenticationListener.phpnu�[���PK��Z׿ͼ� � I��8Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.phpnu�[���PK��Z~�k��<19Symfony/Component/Security/Http/Firewall/ChannelListener.phpnu�[���PK��Z��6'6'K�9Symfony/Component/Security/Http/Firewall/AbstractAuthenticationListener.phpnu�[���PK��Z�"?���<?A9Symfony/Component/Security/Http/Firewall/ContextListener.phpnu�[���PK��Z�����MSY9Symfony/Component/Security/Http/Firewall/SimpleFormAuthenticationListener.phpnu�[���PK��Z+/��Z	Z	;�q9Symfony/Component/Security/Http/Firewall/AccessListener.phpnu�[���PK��Z�Z���Mg{9Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.phpnu�[���PK��Zn��L��9Symfony/Component/Security/Http/Firewall/SimplePreAuthenticationListener.phpnu�[���PK��Z�&!�
�
H+�9Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.phpnu�[���PK��Z2j���-$�9Symfony/Component/Security/Http/AccessMap.phpnu�[���PK��Z/�``6x�9Symfony/Component/Security/Http/AccessMapInterface.phpnu�[���PK��Z��\\��8>�9Symfony/Component/Security/Http/FirewallMapInterface.phpnu�[���PK��Z	z��J��9Symfony/Component/Security/Http/RememberMe/RememberMeServicesInterface.phpnu�[���PK��ZP�ڕ��?��9Symfony/Component/Security/Http/RememberMe/ResponseListener.phpnu�[���PK��Z���s44U�9Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.phpnu�[���PK��Z�*�b�&�&I��9Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.phpnu�[���PK��Z�a�$��K!
:Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.phpnu�[���PK��Z:�&�GGR!:Symfony/Component/Security/Http/Session/SessionAuthenticationStrategyInterface.phpnu�[���PK��Z��La[[I�":Symfony/Component/Security/Http/Session/SessionAuthenticationStrategy.phpnu�[���PK��Za7�llF�):Symfony/Component/Security/Http/Logout/DefaultLogoutSuccessHandler.phpnu�[���PK��Z1��d��H�.:Symfony/Component/Security/Http/Logout/LogoutSuccessHandlerInterface.phpnu�[���PK��Z\ü���?�2:Symfony/Component/Security/Http/Logout/SessionLogoutHandler.phpnu�[���PK��Z6O����A07:Symfony/Component/Security/Http/Logout/LogoutHandlerInterface.phpnu�[���PK��Z�ddF�;:Symfony/Component/Security/Http/Logout/CookieClearingLogoutHandler.phpnu�[���PK��Z/ sG��2xA:Symfony/Component/Security/Http/SecurityEvents.phpnu�[���PK��Z�NA��X�E:Symfony/Component/Security/Http/Authentication/AuthenticationSuccessHandlerInterface.phpnu�[���PK��Z������V/K:Symfony/Component/Security/Http/Authentication/DefaultAuthenticationFailureHandler.phpnu�[���PK��Z��H]X�X:Symfony/Component/Security/Http/Authentication/AuthenticationFailureHandlerInterface.phpnu�[���PK��Z�xGAAV^:Symfony/Component/Security/Http/Authentication/DefaultAuthenticationSuccessHandler.phpnu�[���PK��ZAH\ݞ�N�j:Symfony/Component/Security/Http/Authentication/SimpleAuthenticationHandler.phpnu�[���PK��Z�D����9|:Symfony/Component/Security/Http/Event/SwitchUserEvent.phpnu�[���PK��ZZ�v}?^�:Symfony/Component/Security/Http/Event/InteractiveLoginEvent.phpnu�[���PK��Z��VǴ�=L�:Symfony/Component/Security/Csrf/CsrfTokenManagerInterface.phpnu�[���PK��Z&%�L
L
4m�:Symfony/Component/Security/Csrf/CsrfTokenManager.phpnu�[���PK��Z�����
�
J�:Symfony/Component/Security/Csrf/TokenStorage/NativeSessionTokenStorage.phpnu�[���PK��Z�����Fn�:Symfony/Component/Security/Csrf/TokenStorage/TokenStorageInterface.phpnu�[���PK��Z��]N
N
Dq�:Symfony/Component/Security/Csrf/TokenStorage/SessionTokenStorage.phpnu�[���PK��ZeI����D3�:Symfony/Component/Security/Csrf/Exception/TokenNotFoundException.phpnu�[���PK��Z��=H��:Symfony/Component/Security/Csrf/TokenGenerator/UriSafeTokenGenerator.phpnu�[���PK��ZJ,p���J�:Symfony/Component/Security/Csrf/TokenGenerator/TokenGeneratorInterface.phpnu�[���PK��Z���O-3�:Symfony/Component/Security/Csrf/CsrfToken.phpnu�[���PK��Z��S��<��:Symfony/Component/Security/Core/SecurityContextInterface.phpnu�[���PK��Z�}�ww?��:Symfony/Component/Security/Core/Role/RoleHierarchyInterface.phpnu�[���PK��Z� �w??6m�:Symfony/Component/Security/Core/Role/RoleHierarchy.phpnu�[���PK��Z�Ħ-�:Symfony/Component/Security/Core/Role/Role.phpnu�[���PK��ZX�S�007t�:Symfony/Component/Security/Core/Role/SwitchUserRole.phpnu�[���PK��Z�'c��6�:Symfony/Component/Security/Core/Role/RoleInterface.phpnu�[���PK��ZE� �D�:Symfony/Component/Security/Core/Encoder/PasswordEncoderInterface.phpnu�[���PK��ZÆ��	�	A��:Symfony/Component/Security/Core/Encoder/BCryptPasswordEncoder.phpnu�[���PK��Z��^��H�:Symfony/Component/Security/Core/Encoder/MessageDigestPasswordEncoder.phpnu�[���PK��Z,>"�D�:Symfony/Component/Security/Core/Encoder/PlaintextPasswordEncoder.phpnu�[���PK��Z�;D��:b;Symfony/Component/Security/Core/Encoder/EncoderFactory.phpnu�[���PK��Z!�@

A�
;Symfony/Component/Security/Core/Encoder/Pbkdf2PasswordEncoder.phpnu�[���PK��Z#�MMqqCx;Symfony/Component/Security/Core/Encoder/EncoderFactoryInterface.phpnu�[���PK��Z�7���
�
?\;Symfony/Component/Security/Core/Encoder/BasePasswordEncoder.phpnu�[���PK��Z��
�77O�*;Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.phpnu�[���PK��Z��i��Fi1;Symfony/Component/Security/Core/Validator/Constraints/UserPassword.phpnu�[���PK��Z����Es4;Symfony/Component/Security/Core/Exception/BadCredentialsException.phpnu�[���PK��Z���zz=}7;Symfony/Component/Security/Core/Exception/LockedException.phpnu�[���PK��Zb��M<<Fd:;Symfony/Component/Security/Core/Exception/UnsupportedUserException.phpnu�[���PK��Z�z�&��I=;Symfony/Component/Security/Core/Exception/CredentialsExpiredException.phpnu�[���PK��Z��Xss=9@;Symfony/Component/Security/Core/Exception/LogoutException.phpnu�[���PK��Z
�04}}GC;Symfony/Component/Security/Core/Exception/UsernameNotFoundException.phpnu�[���PK��Z#��q44Q
I;Symfony/Component/Security/Core/Exception/InsufficientAuthenticationException.phpnu�[���PK��Z�5]���I�L;Symfony/Component/Security/Core/Exception/SessionUnavailableException.phpnu�[���PK��ZD��9��D�P;Symfony/Component/Security/Core/Exception/TokenNotFoundException.phpnu�[���PK��Zh�c��B�S;Symfony/Component/Security/Core/Exception/CookieTheftException.phpnu�[���PK��Z��A���@/W;Symfony/Component/Security/Core/Exception/ExceptionInterface.phpnu�[���PK��ZqUSą�CYY;Symfony/Component/Security/Core/Exception/AccessDeniedException.phpnu�[���PK��Z�'��EQ\;Symfony/Component/Security/Core/Exception/AuthenticationException.phpnu�[���PK��Z�
	��>�c;Symfony/Component/Security/Core/Exception/RuntimeException.phpnu�[���PK��Z@�	���G0f;Symfony/Component/Security/Core/Exception/ProviderNotFoundException.phpnu�[���PK��Z�ĸ���X�i;Symfony/Component/Security/Core/Exception/AuthenticationCredentialsNotFoundException.phpnu�[���PK��Z:���AADm;Symfony/Component/Security/Core/Exception/AccountStatusException.phpnu�[���PK��Z7w�-��L�r;Symfony/Component/Security/Core/Exception/AuthenticationServiceException.phpnu�[���PK��ZxB��EIv;Symfony/Component/Security/Core/Exception/AccountExpiredException.phpnu�[���PK��Z�և��?Ny;Symfony/Component/Security/Core/Exception/DisabledException.phpnu�[���PK��Ze���CA|;Symfony/Component/Security/Core/Exception/NonceExpiredException.phpnu�[���PK��Zʝ�9Fo;Symfony/Component/Security/Core/Exception/InvalidArgumentException.phpnu�[���PK��Z�O���G�;Symfony/Component/Security/Core/Exception/InvalidCsrfTokenException.phpnu�[���PK��Z�Õ�

5�;Symfony/Component/Security/Core/Util/SecureRandom.phpnu�[���PK��ZU��a��4e�;Symfony/Component/Security/Core/Util/StringUtils.phpnu�[���PK��Z��T�,,3��;Symfony/Component/Security/Core/Util/ClassUtils.phpnu�[���PK��Z�	���>8�;Symfony/Component/Security/Core/Util/SecureRandomInterface.phpnu�[���PK��Z�m2���G1�;Symfony/Component/Security/Core/Authorization/AccessDecisionManager.phpnu�[���PK��Z�З~��Ak�;Symfony/Component/Security/Core/Authorization/Voter/RoleVoter.phpnu�[���PK��Z~f�J��;Symfony/Component/Security/Core/Authorization/Voter/RoleHierarchyVoter.phpnu�[���PK��Z��`c��G]�;Symfony/Component/Security/Core/Authorization/Voter/ExpressionVoter.phpnu�[���PK��Z�X,mJ��;Symfony/Component/Security/Core/Authorization/Voter/AuthenticatedVoter.phpnu�[���PK��Z�>��F*�;Symfony/Component/Security/Core/Authorization/Voter/VoterInterface.phpnu�[���PK��Z�:22PR�;Symfony/Component/Security/Core/Authorization/AccessDecisionManagerInterface.phpnu�[���PK��Zѵ^��D��;Symfony/Component/Security/Core/Authorization/ExpressionLanguage.phpnu�[���PK��Z����=��;Symfony/Component/Security/Core/User/UserCheckerInterface.phpnu�[���PK��Z��^ 
 
:�;Symfony/Component/Security/Core/User/ChainUserProvider.phpnu�[���PK��ZD�$..4r<Symfony/Component/Security/Core/User/UserChecker.phpnu�[���PK��Z��6bYY>
<Symfony/Component/Security/Core/User/AdvancedUserInterface.phpnu�[���PK��Z����	�	6�<Symfony/Component/Security/Core/User/UserInterface.phpnu�[���PK��Z/!�=�"<Symfony/Component/Security/Core/User/InMemoryUserProvider.phpnu�[���PK��Z��//;]/<Symfony/Component/Security/Core/User/EquatableInterface.phpnu�[���PK��Zs�v�W	W	>�3<Symfony/Component/Security/Core/User/UserProviderInterface.phpnu�[���PK��Z��1G	G	-�=<Symfony/Component/Security/Core/User/User.phpnu�[���PK��Z'�za!!3`G<Symfony/Component/Security/Core/SecurityContext.phpnu�[���PK��Z��l�8�R<Symfony/Component/Security/Core/AuthenticationEvents.phpnu�[���PK��Zx��$ccPOW<Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.phpnu�[���PK��Z¬>
##R2f<Symfony/Component/Security/Core/Authentication/SimplePreAuthenticatorInterface.phpnu�[���PK��Z��W��O�h<Symfony/Component/Security/Core/Authentication/SimpleAuthenticatorInterface.phpnu�[���PK��Z>,�vvX%l<Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.phpnu�[���PK��Z�U#s<Symfony/Component/Security/Core/Authentication/Provider/DaoAuthenticationProvider.phpnu�[���PK��Z�b�yyVƂ<Symfony/Component/Security/Core/Authentication/Provider/UserAuthenticationProvider.phpnu�[���PK��Z�J�A��\ŗ<Symfony/Component/Security/Core/Authentication/Provider/RememberMeAuthenticationProvider.phpnu�[���PK��Z��X���[$�<Symfony/Component/Security/Core/Authentication/Provider/AnonymousAuthenticationProvider.phpnu�[���PK��Z��a�""[b�<Symfony/Component/Security/Core/Authentication/Provider/AuthenticationProviderInterface.phpnu�[���PK��Zun\�
�
b�<Symfony/Component/Security/Core/Authentication/Provider/PreAuthenticatedAuthenticationProvider.phpnu�[���PK��Z��r3WWW��<Symfony/Component/Security/Core/Authentication/AuthenticationTrustResolverInterface.phpnu�[���PK��Z�Zvm��St�<Symfony/Component/Security/Core/Authentication/RememberMe/InMemoryTokenProvider.phpnu�[���PK��Z���QZZV��<Symfony/Component/Security/Core/Authentication/RememberMe/PersistentTokenInterface.phpnu�[���PK��Z
�TO��Mx�<Symfony/Component/Security/Core/Authentication/RememberMe/PersistentToken.phpnu�[���PK��Z
C�f��T��<Symfony/Component/Security/Core/Authentication/RememberMe/TokenProviderInterface.phpnu�[���PK��ZJ-W;::S��<Symfony/Component/Security/Core/Authentication/SimpleFormAuthenticatorInterface.phpnu�[���PK��Z:�6��Nv�<Symfony/Component/Security/Core/Authentication/AuthenticationTrustResolver.phpnu�[���PK��Zf�	�Q��<Symfony/Component/Security/Core/Authentication/AuthenticationManagerInterface.phpnu�[���PK��Zγ�__N�<Symfony/Component/Security/Core/Authentication/Token/PreAuthenticatedToken.phpnu�[���PK��Z��4��F��<Symfony/Component/Security/Core/Authentication/Token/AbstractToken.phpnu�[���PK��Z�tC��G)=Symfony/Component/Security/Core/Authentication/Token/TokenInterface.phpnu�[���PK��Z{Z�--G�=Symfony/Component/Security/Core/Authentication/Token/AnonymousToken.phpnu�[���PK��Z�6��`
`
N&=Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.phpnu�[���PK��Z��w�	�	H*=Symfony/Component/Security/Core/Authentication/Token/RememberMeToken.phpnu�[���PK��Zm�|JJK�3=Symfony/Component/Security/Core/Resources/translations/security.sr_Cyrl.xlfnu�[���PK��Z&MЎ�
�
F�C=Symfony/Component/Security/Core/Resources/translations/security.es.xlfnu�[���PK��ZM-�@F�Q=Symfony/Component/Security/Core/Resources/translations/security.fa.xlfnu�[���PK��Zd�e��
�
F�a=Symfony/Component/Security/Core/Resources/translations/security.fr.xlfnu�[���PK��Z�)�
�
F�o=Symfony/Component/Security/Core/Resources/translations/security.ro.xlfnu�[���PK��Z�y��
�
F�}=Symfony/Component/Security/Core/Resources/translations/security.gl.xlfnu�[���PK��Z��u^
^
F�=Symfony/Component/Security/Core/Resources/translations/security.sv.xlfnu�[���PK��Z���ţ
�
F��=Symfony/Component/Security/Core/Resources/translations/security.ca.xlfnu�[���PK��Zo'�N�
�
Fϧ=Symfony/Component/Security/Core/Resources/translations/security.de.xlfnu�[���PK��Z.W�
�
F
�=Symfony/Component/Security/Core/Resources/translations/security.no.xlfnu�[���PK��Z��ق
�
F�=Symfony/Component/Security/Core/Resources/translations/security.sk.xlfnu�[���PK��Z�w=���F�=Symfony/Component/Security/Core/Resources/translations/security.ru.xlfnu�[���PK��ZUɎd
d
F3�=Symfony/Component/Security/Core/Resources/translations/security.sl.xlfnu�[���PK��Z���
�
F
�=Symfony/Component/Security/Core/Resources/translations/security.lb.xlfnu�[���PK��Z�#@�y
y
IW�=Symfony/Component/Security/Core/Resources/translations/security.pt_PT.xlfnu�[���PK��ZYW��g
g
KI>Symfony/Component/Security/Core/Resources/translations/security.sr_Latn.xlfnu�[���PK��Z�=���
�
I+>Symfony/Component/Security/Core/Resources/translations/security.pt_BR.xlfnu�[���PK��Z(���
�
F&(>Symfony/Component/Security/Core/Resources/translations/security.cs.xlfnu�[���PK��ZO�
�
F'6>Symfony/Component/Security/Core/Resources/translations/security.it.xlfnu�[���PK��ZTk�f��F+D>Symfony/Component/Security/Core/Resources/translations/security.ar.xlfnu�[���PK��Z��|H�
�
F[S>Symfony/Component/Security/Core/Resources/translations/security.hu.xlfnu�[���PK��Z�p�U�
�
Fa>Symfony/Component/Security/Core/Resources/translations/security.nl.xlfnu�[���PK��Z'���{
{
F�o>Symfony/Component/Security/Core/Resources/translations/security.tr.xlfnu�[���PK��ZU����F�}>Symfony/Component/Security/Core/Resources/translations/security.el.xlfnu�[���PK��Z.�X:
:
F�>Symfony/Component/Security/Core/Resources/translations/security.en.xlfnu�[���PK��Z�d
�
�
F��>Symfony/Component/Security/Core/Resources/translations/security.pl.xlfnu�[���PK��Z5�˙��F��>Symfony/Component/Security/Core/Resources/translations/security.ua.xlfnu�[���PK��Zz��
J
J
F��>Symfony/Component/Security/Core/Resources/translations/security.da.xlfnu�[���PK��Z��Eh��Dj�>Symfony/Component/Security/Core/Event/AuthenticationFailureEvent.phpnu�[���PK��Z+\�
//=��>Symfony/Component/Security/Core/Event/AuthenticationEvent.phpnu�[���PK��Z���(SSA,�>Symfony/Component/Security/Resources/translations/security.bg.xlfnu�[���PK��Zm�|JJF��>Symfony/Component/Security/Resources/translations/security.sr_Cyrl.xlfnu�[���PK��Z&MЎ�
�
A��>Symfony/Component/Security/Resources/translations/security.es.xlfnu�[���PK��ZM-�@A�>Symfony/Component/Security/Resources/translations/security.fa.xlfnu�[���PK��Z���An?Symfony/Component/Security/Resources/translations/security.vi.xlfnu�[���PK��Zd�e��
�
A�?Symfony/Component/Security/Resources/translations/security.fr.xlfnu�[���PK��Z�)�
�
A.)?Symfony/Component/Security/Resources/translations/security.ro.xlfnu�[���PK��Z�y��
�
A,7?Symfony/Component/Security/Resources/translations/security.gl.xlfnu�[���PK��Z��u^
^
A<E?Symfony/Component/Security/Resources/translations/security.sv.xlfnu�[���PK��Z���ţ
�
AS?Symfony/Component/Security/Resources/translations/security.ca.xlfnu�[���PK��Zo'�N�
�
Aa?Symfony/Component/Security/Resources/translations/security.de.xlfnu�[���PK��Z����
�
AXo?Symfony/Component/Security/Resources/translations/security.no.xlfnu�[���PK��Z�R�wD
D
AN}?Symfony/Component/Security/Resources/translations/security.id.xlfnu�[���PK��Z��ق
�
A�?Symfony/Component/Security/Resources/translations/security.sk.xlfnu�[���PK��Z�w=���A��?Symfony/Component/Security/Resources/translations/security.ru.xlfnu�[���PK��ZUɎd
d
A$�?Symfony/Component/Security/Resources/translations/security.sl.xlfnu�[���PK��Z]��W
W
A��?Symfony/Component/Security/Resources/translations/security.hr.xlfnu�[���PK��Z���
�
A��?Symfony/Component/Security/Resources/translations/security.lb.xlfnu�[���PK��Z�#@�y
y
D�?Symfony/Component/Security/Resources/translations/security.pt_PT.xlfnu�[���PK��ZYW��g
g
F��?Symfony/Component/Security/Resources/translations/security.sr_Latn.xlfnu�[���PK��Z���Y�
�
D��?Symfony/Component/Security/Resources/translations/security.pt_BR.xlfnu�[���PK��Z(���
�
A�?Symfony/Component/Security/Resources/translations/security.cs.xlfnu�[���PK��ZO�
�
A�
@Symfony/Component/Security/Resources/translations/security.it.xlfnu�[���PK��ZTk�f��A�@Symfony/Component/Security/Resources/translations/security.ar.xlfnu�[���PK��Z��|H�
�
A�'@Symfony/Component/Security/Resources/translations/security.hu.xlfnu�[���PK��Z�p�U�
�
A6@Symfony/Component/Security/Resources/translations/security.nl.xlfnu�[���PK��Z'���{
{
AID@Symfony/Component/Security/Resources/translations/security.tr.xlfnu�[���PK��ZU����A5R@Symfony/Component/Security/Resources/translations/security.el.xlfnu�[���PK��Z��Dt��D�b@Symfony/Component/Security/Resources/translations/security.zh_CN.xlfnu�[���PK��Z.�X:
:
A�o@Symfony/Component/Security/Resources/translations/security.en.xlfnu�[���PK��Z�d
�
�
A�}@Symfony/Component/Security/Resources/translations/security.pl.xlfnu�[���PK��Z�f488A��@Symfony/Component/Security/Resources/translations/security.ja.xlfnu�[���PK��Z5�˙��AC�@Symfony/Component/Security/Resources/translations/security.ua.xlfnu�[���PK��Z��J
J
A7�@Symfony/Component/Security/Resources/translations/security.da.xlfnu�[���PK��Z�@V��@�@Symfony/Component/Validator/ConstraintViolationListInterface.phpnu�[���PK��Zz��911::�@Symfony/Component/Validator/ObjectInitializerInterface.phpnu�[���PK��Z,�'��<��@Symfony/Component/Validator/ConstraintValidatorInterface.phpnu�[���PK��ZK��}}1��@Symfony/Component/Validator/DefaultTranslator.phpnu�[���PK��Z�����3��@Symfony/Component/Validator/ConstraintViolation.phpnu�[���PK��ZS�b'b'0��@Symfony/Component/Validator/ValidatorBuilder.phpnu�[���PK��Z�S�UU>�ASymfony/Component/Validator/GroupSequenceProviderInterface.phpnu�[���PK��Z�d�)xASymfony/Component/Validator/Validator.phpnu�[���PK��Z��&{{9�2ASymfony/Component/Validator/ValidatorBuilderInterface.phpnu�[���PK��Zo��SS*�HASymfony/Component/Validator/autoloader.phpnu�[���PK��Z����C0C09{JASymfony/Component/Validator/ExecutionContextInterface.phpnu�[���PK��Z}`���9'{ASymfony/Component/Validator/PropertyMetadataInterface.phpnu�[���PK��Z�޽/!/!0z�ASymfony/Component/Validator/ExecutionContext.phpnu�[���PK��Z+s���:	�ASymfony/Component/Validator/ConstraintValidatorFactory.phpnu�[���PK��Z�Sq�KK1l�ASymfony/Component/Validator/MetadataInterface.phpnu�[���PK��Z�R'<�ASymfony/Component/Validator/ConstraintViolationInterface.phpnu�[���PK��ZƭW��*��ASymfony/Component/Validator/Constraint.phpnu�[���PK��Z|����6l�ASymfony/Component/Validator/Mapping/GetterMetadata.phpnu�[���PK��Zr
���8��ASymfony/Component/Validator/Mapping/PropertyMetadata.phpnu�[���PK��Z�t�././5��ASymfony/Component/Validator/Mapping/ClassMetadata.phpnu�[���PK��Z��!"	"	7wBSymfony/Component/Validator/Mapping/ElementMetadata.phpnu�[���PK��Z�/�;aa6)BSymfony/Component/Validator/Mapping/MemberMetadata.phpnu�[���PK��Z+�d%%<�@BSymfony/Component/Validator/Mapping/Cache/CacheInterface.phpnu�[���PK��Z����6XEBSymfony/Component/Validator/Mapping/Cache/ApcCache.phpnu�[���PK��Zd#[N��<IJBSymfony/Component/Validator/Mapping/ClassMetadataFactory.phpnu�[���PK��Z��ʚ��9�WBSymfony/Component/Validator/Mapping/Loader/FileLoader.phpnu�[���PK��Zk�G+��=�[BSymfony/Component/Validator/Mapping/Loader/AbstractLoader.phpnu�[���PK��ZRᠯ��=dBSymfony/Component/Validator/Mapping/Loader/XmlFilesLoader.phpnu�[���PK��Z�?��>gBSymfony/Component/Validator/Mapping/Loader/YamlFilesLoader.phpnu�[���PK��Z�����:jBSymfony/Component/Validator/Mapping/Loader/LoaderChain.phpnu�[���PK��ZT�b��AAqBSymfony/Component/Validator/Mapping/Loader/StaticMethodLoader.phpnu�[���PK��Z�>�??>�wBSymfony/Component/Validator/Mapping/Loader/LoaderInterface.phpnu�[���PK��Z���*��:8zBSymfony/Component/Validator/Mapping/Loader/FilesLoader.phpnu�[���PK��ZTO��--c)�BSymfony/Component/Validator/Mapping/Loader/schema/dic/constraint-mapping/constraint-mapping-1.0.xsdnu�[���PK��Z;Q�F11<�BSymfony/Component/Validator/Mapping/Loader/XmlFileLoader.phpnu�[���PK��Z	lw#QQ?��BSymfony/Component/Validator/Mapping/Loader/AnnotationLoader.phpnu�[���PK��Z'��pkk=F�BSymfony/Component/Validator/Mapping/Loader/YamlFileLoader.phpnu�[���PK��Z�۔��@�BSymfony/Component/Validator/Mapping/BlackholeMetadataFactory.phpnu�[���PK��Z�L8��
�
:$�BSymfony/Component/Validator/ValidationVisitorInterface.phpnu�[���PK��ZQ���VV:j�BSymfony/Component/Validator/Exception/MappingException.phpnu�[���PK��Z��y��@*�BSymfony/Component/Validator/Exception/BadMethodCallException.phpnu�[���PK��ZL�ЉRRA��BSymfony/Component/Validator/Exception/InvalidOptionsException.phpnu�[���PK��Zk1+WW<V�BSymfony/Component/Validator/Exception/ValidatorException.phpnu�[���PK��Z�b�<<A�BSymfony/Component/Validator/Exception/UnexpectedTypeException.phpnu�[���PK��Z�1�"ccG��BSymfony/Component/Validator/Exception/ConstraintDefinitionException.phpnu�[���PK��Z�T����<��BSymfony/Component/Validator/Exception/ExceptionInterface.phpnu�[���PK��Zz����:��BSymfony/Component/Validator/Exception/RuntimeException.phpnu�[���PK��Z��x��A�BSymfony/Component/Validator/Exception/NoSuchMetadataException.phpnu�[���PK��Zu��RRA�BSymfony/Component/Validator/Exception/MissingOptionsException.phpnu�[���PK��ZM��#^^B�BSymfony/Component/Validator/Exception/GroupDefinitionException.phpnu�[���PK��Z�\��B��BSymfony/Component/Validator/Exception/InvalidArgumentException.phpnu�[���PK��Z�U�<<3!�BSymfony/Component/Validator/ClassBasedInterface.phpnu�[���PK��Z;5t��7��BSymfony/Component/Validator/ConstraintViolationList.phpnu�[���PK��ZAbI̲�1�CSymfony/Component/Validator/ValidationVisitor.phpnu�[���PK��Zbh��B�$CSymfony/Component/Validator/PropertyMetadataContainerInterface.phpnu�[���PK��ZY����8*CSymfony/Component/Validator/MetadataFactoryInterface.phpnu�[���PK��ZD#��?�?DX.CSymfony/Component/Validator/Resources/translations/validators.en.xlfnu�[���PK��Z-���uCuCDgnCSymfony/Component/Validator/Resources/translations/validators.sk.xlfnu�[���PK��Z�τ}K}KDP�CSymfony/Component/Validator/Resources/translations/validators.uk.xlfnu�[���PK��Z��-�1�1DA�CSymfony/Component/Validator/Resources/translations/validators.cy.xlfnu�[���PK��Z�m�w�B�BD�0DSymfony/Component/Validator/Resources/translations/validators.pl.xlfnu�[���PK��Z@T�\44D�sDSymfony/Component/Validator/Resources/translations/validators.af.xlfnu�[���PK��Z�b�@�@DB�DSymfony/Component/Validator/Resources/translations/validators.pt.xlfnu�[���PK��Ze]߭A�AII�DSymfony/Component/Validator/Resources/translations/validators.sr_Cyrl.xlfnu�[���PK��Z�a�2�2Do+ESymfony/Component/Validator/Resources/translations/validators.fi.xlfnu�[���PK��Z��"}2A2AD�^ESymfony/Component/Validator/Resources/translations/validators.es.xlfnu�[���PK��Zs�E#�A�AD6�ESymfony/Component/Validator/Resources/translations/validators.de.xlfnu�[���PK��Z=^��::D��ESymfony/Component/Validator/Resources/translations/validators.it.xlfnu�[���PK��Z	���AADFSymfony/Component/Validator/Resources/translations/validators.ca.xlfnu�[���PK��ZD��#"#"Dx^FSymfony/Component/Validator/Resources/translations/validators.mn.xlfnu�[���PK��Z��-tZMZMD�FSymfony/Component/Validator/Resources/translations/validators.ru.xlfnu�[���PK��Z<��bKKD��FSymfony/Component/Validator/Resources/translations/validators.bg.xlfnu�[���PK��Z����A�ADoGSymfony/Component/Validator/Resources/translations/validators.ro.xlfnu�[���PK��Z�ժN@@D�\GSymfony/Component/Validator/Resources/translations/validators.nl.xlfnu�[���PK��Z�%�N�=�=DW�GSymfony/Component/Validator/Resources/translations/validators.et.xlfnu�[���PK��Z
��GGDs�GSymfony/Component/Validator/Resources/translations/validators.fa.xlfnu�[���PK��Z-�L>L>D�"HSymfony/Component/Validator/Resources/translations/validators.id.xlfnu�[���PK��Z˺�Q1Q1D�aHSymfony/Component/Validator/Resources/translations/validators.tr.xlfnu�[���PK��Z	�)�B�BDp�HSymfony/Component/Validator/Resources/translations/validators.cs.xlfnu�[���PK��Z�6��%=%=G��HSymfony/Component/Validator/Resources/translations/validators.zh_CN.xlfnu�[���PK��Z�PhBhBDAISymfony/Component/Validator/Resources/translations/validators.lt.xlfnu�[���PK��Z���+BBDWISymfony/Component/Validator/Resources/translations/validators.fr.xlfnu�[���PK��Z(��=A=AD��ISymfony/Component/Validator/Resources/translations/validators.gl.xlfnu�[���PK��Z���wX@X@DN�ISymfony/Component/Validator/Resources/translations/validators.hr.xlfnu�[���PK��ZY�.3�5�5DJSymfony/Component/Validator/Resources/translations/validators.sq.xlfnu�[���PK��Z(�eeD3RJSymfony/Component/Validator/Resources/translations/validators.nb.xlfnu�[���PK��Z���t�A�ADrJSymfony/Component/Validator/Resources/translations/validators.eu.xlfnu�[���PK��Z1ar�==Ga�JSymfony/Component/Validator/Resources/translations/validators.zh_TW.xlfnu�[���PK��Z�T�л@�@G��JSymfony/Component/Validator/Resources/translations/validators.pt_BR.xlfnu�[���PK��Z���1�1D3KSymfony/Component/Validator/Resources/translations/validators.no.xlfnu�[���PK��Z��n�C�CDWeKSymfony/Component/Validator/Resources/translations/validators.sl.xlfnu�[���PK��Zq�b�?�?D��KSymfony/Component/Validator/Resources/translations/validators.lb.xlfnu�[���PK��Z93XaoAoAD�KSymfony/Component/Validator/Resources/translations/validators.hu.xlfnu�[���PK��Z����M�MD,LSymfony/Component/Validator/Resources/translations/validators.el.xlfnu�[���PK��Z��9>�5�5D@zLSymfony/Component/Validator/Resources/translations/validators.da.xlfnu�[���PK��Z���AAD��LSymfony/Component/Validator/Resources/translations/validators.ja.xlfnu�[���PK��Z�Q>�?�?D �LSymfony/Component/Validator/Resources/translations/validators.sv.xlfnu�[���PK��Zv_��w,w,D2MSymfony/Component/Validator/Resources/translations/validators.hy.xlfnu�[���PK��Z����O�OD_MSymfony/Component/Validator/Resources/translations/validators.ar.xlfnu�[���PK��Z�1�^�4�4I=�MSymfony/Component/Validator/Resources/translations/validators.sr_Latn.xlfnu�[���PK��Z@T'%�B�BDt�MSymfony/Component/Validator/Resources/translations/validators.vi.xlfnu�[���PK��Z��tý5�5D�'NSymfony/Component/Validator/Resources/translations/validators.he.xlfnu�[���PK��Z��D��<�]NSymfony/Component/Validator/Constraints/NotNullValidator.phpnu�[���PK��ZD~�SS2"aNSymfony/Component/Validator/Constraints/Choice.phpnu�[���PK��Z�~%ɋ�1�eNSymfony/Component/Validator/Constraints/Valid.phpnu�[���PK��Z�+��6�iNSymfony/Component/Validator/Constraints/NotEqualTo.phpnu�[���PK��Zm�Լ\\ClNSymfony/Component/Validator/Constraints/NotIdenticalToValidator.phpnu�[���PK��ZĿ:�KK6�nNSymfony/Component/Validator/Constraints/Expression.phpnu�[���PK��Z�خ
zz?�sNSymfony/Component/Validator/Constraints/Collection/Optional.phpnu�[���PK��Z\,y�zz?�vNSymfony/Component/Validator/Constraints/Collection/Required.phpnu�[���PK��Z
��n��?kyNSymfony/Component/Validator/Constraints/CollectionValidator.phpnu�[���PK��Z��y:g�NSymfony/Component/Validator/Constraints/BlankValidator.phpnu�[���PK��Z�+����0؅NSymfony/Component/Validator/Constraints/Iban.phpnu�[���PK��Z����	�	=�NSymfony/Component/Validator/Constraints/CallbackValidator.phpnu�[���PK��Z�}�&&25�NSymfony/Component/Validator/Constraints/Length.phpnu�[���PK��Z�b�=nn9��NSymfony/Component/Validator/Constraints/IsbnValidator.phpnu�[���PK��Z�<W���:��NSymfony/Component/Validator/Constraints/RegexValidator.phpnu�[���PK��Z^r��

4��NSymfony/Component/Validator/Constraints/Language.phpnu�[���PK��Z���,,0e�NSymfony/Component/Validator/Constraints/Isbn.phpnu�[���PK��Z�EW^��<�NSymfony/Component/Validator/Constraints/CountryValidator.phpnu�[���PK��Zzet�	�	?\�NSymfony/Component/Validator/Constraints/ExpressionValidator.phpnu�[���PK��Z�	�00/��NSymfony/Component/Validator/Constraints/Url.phpnu�[���PK��Z�V`���9"�NSymfony/Component/Validator/Constraints/IbanValidator.phpnu�[���PK��Z��vbb@6�NSymfony/Component/Validator/Constraints/GreaterThanValidator.phpnu�[���PK��ZS탟0�NSymfony/Component/Validator/Constraints/Date.phpnu�[���PK��Z�|4XX8j�NSymfony/Component/Validator/Constraints/UrlValidator.phpnu�[���PK��Zw���3*�NSymfony/Component/Validator/Constraints/NotNull.phpnu�[���PK��ZS�n���0��NSymfony/Component/Validator/Constraints/Null.phpnu�[���PK��Z�o�o��:��NSymfony/Component/Validator/Constraints/RangeValidator.phpnu�[���PK��Z�

4��NSymfony/Component/Validator/Constraints/Currency.phpnu�[���PK��Zrs+���4O�NSymfony/Component/Validator/Constraints/Optional.phpnu�[���PK��Z����449G�NSymfony/Component/Validator/Constraints/IssnValidator.phpnu�[���PK��Z�qp""0�NSymfony/Component/Validator/Constraints/File.phpnu�[���PK��Z5�ʟ��9f�NSymfony/Component/Validator/Constraints/DateValidator.phpnu�[���PK��Z0@���9�OSymfony/Component/Validator/Constraints/NullValidator.phpnu�[���PK��Z�>
i//5�OSymfony/Component/Validator/Constraints/Existence.phpnu�[���PK��ZtUה�4k	OSymfony/Component/Validator/Constraints/Required.phpnu�[���PK��Zm��\\>cOSymfony/Component/Validator/Constraints/AbstractComparison.phpnu�[���PK��Zc��y

4-OSymfony/Component/Validator/Constraints/DateTime.phpnu�[���PK��Zl˘��
�
7�OSymfony/Component/Validator/Constraints/IpValidator.phpnu�[���PK��Z�\\=�OSymfony/Component/Validator/Constraints/LessThanValidator.phpnu�[���PK��Z�U�4Y OSymfony/Component/Validator/Constraints/NotBlank.phpnu�[���PK��Z<8�S��:�"OSymfony/Component/Validator/Constraints/ImageValidator.phpnu�[���PK��Z��Lֻ�6�9OSymfony/Component/Validator/Constraints/CardScheme.phpnu�[���PK��Z��"��?�<OSymfony/Component/Validator/Constraints/CardSchemeValidator.phpnu�[���PK��ZN3�0/MOSymfony/Component/Validator/Constraints/Type.phpnu�[���PK��Z@vqq9�POSymfony/Component/Validator/Constraints/FileValidator.phpnu�[���PK��Z�'����1oiOSymfony/Component/Validator/Constraints/Count.phpnu�[���PK��Z�̢�VV@�oOSymfony/Component/Validator/Constraints/IdenticalToValidator.phpnu�[���PK��Zd�X�BB0~rOSymfony/Component/Validator/Constraints/Issn.phpnu�[���PK��Z�ଏ�A uOSymfony/Component/Validator/Constraints/GroupSequenceProvider.phpnu�[���PK��Z��}a��7 wOSymfony/Component/Validator/Constraints/GreaterThan.phpnu�[���PK��Z�Ǧ��3xyOSymfony/Component/Validator/Constraints/EqualTo.phpnu�[���PK��Zb+��9�{OSymfony/Component/Validator/Constraints/LuhnValidator.phpnu�[���PK��Z�ٜ?��0ŃOSymfony/Component/Validator/Constraints/True.phpnu�[���PK��Z?����G"�OSymfony/Component/Validator/Constraints/AbstractComparisonValidator.phpnu�[���PK��Z�̋	�	1y�OSymfony/Component/Validator/Constraints/Regex.phpnu�[���PK��Z��BB1e�OSymfony/Component/Validator/Constraints/Range.phpnu�[���PK��Z[�A���;�OSymfony/Component/Validator/Constraints/LessThanOrEqual.phpnu�[���PK��Zq;O3q�OSymfony/Component/Validator/Constraints/Country.phpnu�[���PK��Z5����:ܢOSymfony/Component/Validator/Constraints/EmailValidator.phpnu�[���PK��Z�`�v��;/�OSymfony/Component/Validator/Constraints/LocaleValidator.phpnu�[���PK��Z'㔘7��OSymfony/Component/Validator/Constraints/IdenticalTo.phpnu�[���PK��Z��/�OSymfony/Component/Validator/Constraints/All.phpnu�[���PK��Z{���UU?w�OSymfony/Component/Validator/Constraints/NotEqualToValidator.phpnu�[���PK��Z�ɑ559;�OSymfony/Component/Validator/Constraints/TrueValidator.phpnu�[���PK��Z�(.wwGٿOSymfony/Component/Validator/Constraints/GreaterThanOrEqualValidator.phpnu�[���PK��Z���(��9��OSymfony/Component/Validator/Constraints/TimeValidator.phpnu�[���PK��Z�Fn���8�OSymfony/Component/Validator/Constraints/AllValidator.phpnu�[���PK��Z�c����.�OSymfony/Component/Validator/Constraints/Ip.phpnu�[���PK��ZHð�2R�OSymfony/Component/Validator/Constraints/Locale.phpnu�[���PK��ZQ��=��OSymfony/Component/Validator/Constraints/LanguageValidator.phpnu�[���PK��ZaHβ;+�OSymfony/Component/Validator/Constraints/ChoiceValidator.phpnu�[���PK��Z�{HH1�OSymfony/Component/Validator/Constraints/Email.phpnu�[���PK��Zx�.`ss4��OSymfony/Component/Validator/Constraints/Callback.phpnu�[���PK��Z�����=��OSymfony/Component/Validator/Constraints/DateTimeValidator.phpnu�[���PK��Z�&����0�OSymfony/Component/Validator/Constraints/Luhn.phpnu�[���PK��Z�F���9<�OSymfony/Component/Validator/Constraints/TypeValidator.phpnu�[���PK��Z���&��=1�OSymfony/Component/Validator/Constraints/NotBlankValidator.phpnu�[���PK��Ze8�B�
�
6�PSymfony/Component/Validator/Constraints/Collection.phpnu�[���PK��ZI7U���1�PSymfony/Component/Validator/Constraints/False.phpnu�[���PK��Z�Q�>MPSymfony/Component/Validator/Constraints/GreaterThanOrEqual.phpnu�[���PK��Z��l��1�PSymfony/Component/Validator/Constraints/Blank.phpnu�[���PK��Z�CG^LL<PSymfony/Component/Validator/Constraints/EqualToValidator.phpnu�[���PK��Z^�T:�PSymfony/Component/Validator/Constraints/FalseValidator.phpnu�[���PK��ZO��qqD^PSymfony/Component/Validator/Constraints/LessThanOrEqualValidator.phpnu�[���PK��Z����vv9CPSymfony/Component/Validator/Constraints/GroupSequence.phpnu�[���PK��Z_��1"PSymfony/Component/Validator/Constraints/Image.phpnu�[���PK��Z��F;��;''PSymfony/Component/Validator/Constraints/LengthValidator.phpnu�[���PK��Z!xHH:e0PSymfony/Component/Validator/Constraints/CountValidator.phpnu�[���PK��Z��708PSymfony/Component/Validator/Constraints/Time.phpnu�[���PK��ZN�H���4y:PSymfony/Component/Validator/Constraints/LessThan.phpnu�[���PK��Ze��:�<PSymfony/Component/Validator/Constraints/NotIdenticalTo.phpnu�[���PK��Z�Z�=D?PSymfony/Component/Validator/Constraints/CurrencyValidator.phpnu�[���PK��ZGk	��3�DPSymfony/Component/Validator/ConstraintValidator.phpnu�[���PK��ZK�OC�GPSymfony/Component/Validator/ConstraintValidatorFactoryInterface.phpnu�[���PK��Z�8Wc��?KKPSymfony/Component/Validator/GlobalExecutionContextInterface.phpnu�[���PK��Zxf�JJ*KSPSymfony/Component/Validator/Validation.phpnu�[���PK��Zn�r�
�
2�WPSymfony/Component/Validator/ValidatorInterface.phpnu�[���PK��ZC���9MfPSymfony/Component/Templating/StreamingEngineInterface.phpnu�[���PK��Z<,��}}2�jPSymfony/Component/Templating/TemplateReference.phpnu�[���PK��Z�m�tTT+�rPSymfony/Component/Templating/autoloader.phpnu�[���PK��Z����;EtPSymfony/Component/Templating/TemplateReferenceInterface.phpnu�[���PK��ZJ� ���2k|PSymfony/Component/Templating/DebuggerInterface.phpnu�[���PK��ZDZ�_++<�PSymfony/Component/Templating/TemplateNameParserInterface.phpnu�[���PK��Z���3�PSymfony/Component/Templating/TemplateNameParser.phpnu�[���PK��Z�����0Y�PSymfony/Component/Templating/EngineInterface.phpnu�[���PK��Z��b�NN2n�PSymfony/Component/Templating/Asset/PathPackage.phpnu�[���PK��Z���TT1�PSymfony/Component/Templating/Asset/UrlPackage.phpnu�[���PK��Z�o##.ӞPSymfony/Component/Templating/Asset/Package.phpnu�[���PK��Zp�vj��7T�PSymfony/Component/Templating/Asset/PackageInterface.phpnu�[���PK��Z�'��4��PSymfony/Component/Templating/Storage/FileStorage.phpnu�[���PK��Z(�"w��6��PSymfony/Component/Templating/Storage/StringStorage.phpnu�[���PK��Zπ\�0��PSymfony/Component/Templating/Storage/Storage.phpnu�[���PK��Z��>3�PSymfony/Component/Templating/Loader/ChainLoader.phpnu�[���PK��Z�b��8��PSymfony/Component/Templating/Loader/FilesystemLoader.phpnu�[���PK��Z�g((.��PSymfony/Component/Templating/Loader/Loader.phpnu�[���PK��Zy�A�nn3o�PSymfony/Component/Templating/Loader/CacheLoader.phpnu�[���PK��ZI<�D��7@�PSymfony/Component/Templating/Loader/LoaderInterface.phpnu�[���PK��Z+�r�mm3|�PSymfony/Component/Templating/Helper/SlotsHelper.phpnu�[���PK��ZV¤՟�4L�PSymfony/Component/Templating/Helper/AssetsHelper.phpnu�[���PK��ZԷ����7O�PSymfony/Component/Templating/Helper/HelperInterface.phpnu�[���PK��Z����



8U�PSymfony/Component/Templating/Helper/CoreAssetsHelper.phpnu�[���PK��Z�NO��.�QSymfony/Component/Templating/Helper/Helper.phpnu�[���PK��Z_6H1%QSymfony/Component/Templating/DelegatingEngine.phpnu�[���PK��Z?w
y=y=*�QSymfony/Component/Templating/PhpEngine.phpnu�[���PK��Z6�H	��$lTQSymfony/Component/Yaml/Unescaper.phpnu�[���PK��Z�8�n�	�	!_fQSymfony/Component/Yaml/Dumper.phpnu�[���PK��Z�bNN%DpQSymfony/Component/Yaml/autoloader.phpnu�[���PK��Z��X��[�[!�qQSymfony/Component/Yaml/Parser.phpnu�[���PK��Z7MӺ

��QSymfony/Component/Yaml/Yaml.phpnu�[���PK��Z�+�l��7+�QSymfony/Component/Yaml/Exception/ExceptionInterface.phpnu�[���PK��Z�|�-��5X�QSymfony/Component/Yaml/Exception/RuntimeException.phpnu�[���PK��Z�����
�
3��QSymfony/Component/Yaml/Exception/ParseException.phpnu�[���PK��Zؙ՚��2��QSymfony/Component/Yaml/Exception/DumpException.phpnu�[���PK��Z)%�,m
m
"2�QSymfony/Component/Yaml/Escaper.phpnu�[���PK��Zq+�3�?�?!�QSymfony/Component/Yaml/Inline.phpnu�[���PK��Z�ݣ�"�"6�=RSymfony/Component/HttpFoundation/ResponseHeaderBag.phpnu�[���PK��Z�}��xx.�`RSymfony/Component/HttpFoundation/ServerBag.phpnu�[���PK��Z�_DK�
�
5�oRSymfony/Component/HttpFoundation/RedirectResponse.phpnu�[���PK��Z�s
��5�zRSymfony/Component/HttpFoundation/StreamedResponse.phpnu�[���PK��Z��F��+��RSymfony/Component/HttpFoundation/Cookie.phPK��Zǯ6B�+�+5.registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
     PK��Z�w��=h=h2.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        ifPK��Z��Dž�.�.2.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encodingPK��ZZ��G3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCPK��Z����Y�Y,.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where ePK��Z�Gl9n9n2.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUri   URI of the namespace
     * @param bool   $multiline      whether to create a multiline tag where each
     *                               attribute gets written to a single line
     * @param string $indent         string used to indent attributes (_auto indents
     *                               attributes so they start at the same column)
     * @param string $linebreak      string used for linebreaks
     * @param bool   $sortAttributes Whether to sort the attributes or not
     *
     * @return string XML sPK��Z�pUx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . PK��Z/����3.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUri   URI of the namespace
     * @param bool   $multiline      whether to create a multiline tag where each
     *                               attribute gets written to a single line
     * @param string $indent         string used to indent attributes (_auto indents
     *                               attributes so they start at the same column)
     * @param string $linebreak      string used for linebreaks
     * @param bool   $sortAttributes Whether to sort the attributes or not
     *
     * @return string XML start element
     * @see    createEndElement(), createTag()
     */
    public static function createStartElement(
        $qname, $attributes = array(), $namespaceUri = null,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true
    ) {
        // if no attributes hav been set, use empty attributes
        if (!isset($attributes) || !is_array($attributes)) {
            $attributes = array();
        }

        if ($namespaceUri != null) {
            $parts = XML_Util::splitQualifiedName($qname);
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($qname)+2));
            }
        }

        if ($namespaceUri != null) {
            // is a namespace given
            if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
            } else {
                // define this Uri as the default namespace
                $attributes['xmlns'] = $namespaceUri;
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $attributes, $sortAttributes,
            $multiline, $indent, $linebreak
        );
        $element = sprintf('<%s%s>', $qname, $attList);
        return  $element;
    }

    /**
     * Create an end element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createEndElement('myNs:myTag');
     * </code>
     *
     * @param string $qname qualified tagname (including namespace)
     *
     * @return string XML end element
     * @see    createStartElement(), createTag()
     */
    public static function createEndElement($qname)
    {
        $element = sprintf('</%s>', $qname);
        return $element;
    }

    /**
     * Create an XML comment
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createComment('I am a comment');
     * </code>
     *
     * @param string $content content of the comment
     *
     * @return string XML comment
     */
    public static function createComment($content)
    {
        $comment = sprintf('<!-- %s -->', $content);
        return $comment;
    }

    /**
     * Create a CData section
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create a CData section
     * $tag = XML_Util::createCDataSection('I am content.');
     * </code>
     *
     * @param string $data data of the CData section
     *
     * @return string CData section with content
     */
    public static function createCDataSection($data)
    {
        return sprintf(
            '<![CDATA[%s]]>',
            preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data))
        );
    }

    /**
     * Split qualified name and return namespace and local part
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // split qualified tag
     * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
     * </code>
     * the returned array will contain two elements:
     * <pre>
     * array(
     *     'namespace' => 'xslt',
     *     'localPart' => 'stylesheet'
     * );
     * </pre>
     *
     * @param string $qname     qualified tag name
     * @param string $defaultNs default namespace (optional)
     *
     * @return array array containing namespace and local part
     */
    public static function splitQualifiedName($qname, $defaultNs = null)
    {
        if (strstr($qname, ':')) {
            $tmp = explode(':', $qname);
            return array(
                'namespace' => $tmp[0],
                'localPart' => $tmp[1]
            );
        }
        return array(
            'namespace' => $defaultNs,
            'localPart' => $qname
        );
    }

    /**
     * Check, whether string is valid XML name
     *
     * <p>XML names are used for tagname, attribute names and various
     * other, lesser known entities.</p>
     * <p>An XML name may only consist of alphanumeric characters,
     * dashes, undescores and periods, and has to start with a letter
     * or an underscore.</p>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // verify tag name
     * $result = XML_Util::isValidName('invalidTag?');
     * if (is_a($result, 'PEAR_Error')) {
     *    print 'Invalid XML name: ' . $result->getMessage();
     * }
     * </code>
     *
     * @param string $string string that should be checked
     *
     * @return mixed true, if string is a valid XML name, PEAR error otherwise
     *
     * @todo support for other charsets
     * @todo PEAR CS - unable to avoid 85-char limit on second preg_match
     */
    public static function isValidName($string)
    {
        // check for invalid chars
        if (!is_string($string) || !strlen($string) || !preg_match('/^[[:alpha:]_]\\z/', $string[0])) {
            return XML_Util::raiseError(
                'XML names may only start with letter or underscore',
                XML_UTIL_ERROR_INVALID_START
            );
        }

        // check for invalid chars
        $match = preg_match(
            '/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?'
            . '[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/',
            $string
        );
        if (!$match) {
            return XML_Util::raiseError(
                'XML names may only contain alphanumeric '
                . 'chars, period, hyphen, colon and underscores',
                XML_UTIL_ERROR_INVALID_CHARS
            );
        }
        // XML name is valid
        return true;
    }

    /**
     * Replacement for XML_Util::raiseError
     *
     * Avoids the necessity to always require
     * PEAR.php
     *
     * @param string $msg  error message
     * @param int    $code error code
     *
     * @return PEAR_Error
     * @todo   PEAR CS - should this use include_once instead?
     */
    public static function raiseError($msg, $code)
    {
        include_once 'PEAR.php';
        return PEAR::raiseError($msg, $code);
    }
}
?>
PK��Z#F��:�:pearcmd.phpnu�[���<?php
/**
 * PEAR, the PHP Extension and Application Repository
 *
 * Command line interface
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Stig Bakken <ssb@php.net>
 * @author    Tomas V.V.Cox <cox@idecnet.com>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 */

@ob_end_clean();
if (!defined('PEAR_RUNTYPE')) {
    // this is defined in peclcmd.php as 'pecl'
    define('PEAR_RUNTYPE', 'pear');
}
define('PEAR_IGNORE_BACKTRACE', 1);
/**
 * @nodep Gtk
 */
//the space is needed for windows include paths with trailing backslash
// http://pear.php.net/bugs/bug.php?id=19482
if ('/opt/alt/php74/usr/share/pear ' != '@'.'include_path'.'@ ') {
    ini_set('include_path', trim('/opt/alt/php74/usr/share/pear '). PATH_SEPARATOR .  get_include_path());
    $raw = false;
} else {
    // this is a raw, uninstalled pear, either a cvs checkout, or php distro
    ini_set('include_path', dirname(__DIR__) . PATH_SEPARATOR . get_include_path());
    $raw = true;
}
@ini_set('allow_url_fopen', true);
@set_time_limit(0);
ob_implicit_flush(true);
@ini_set('track_errors', true);
@ini_set('html_errors', false);
$_PEAR_PHPDIR = '#$%^&*';
set_error_handler('error_handler');

$pear_package_version = "1.10.16";

require_once 'PEAR.php';
require_once 'PEAR/Frontend.php';
require_once 'PEAR/Config.php';
require_once 'PEAR/Command.php';
require_once 'Console/Getopt.php';


PEAR_Command::setFrontendType('CLI');
$all_commands = PEAR_Command::getCommands();

$argv = Console_Getopt::readPHPArgv();
// fix CGI sapi oddity - the -- in pear.bat/pear is not removed
if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
    unset($argv[1]);
    $argv = array_values($argv);
}
$progname = PEAR_RUNTYPE;
array_shift($argv);
$options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV");
if (PEAR::isError($options)) {
    usage($options);
}

$opts = $options[0];

$fetype = 'CLI';
if ($progname == 'gpear' || $progname == 'pear-gtk') {
    $fetype = 'Gtk2';
} else {
    foreach ($opts as $opt) {
        if ($opt[0] == 'G') {
            $fetype = 'Gtk2';
        }
    }
}

$pear_user_config = '';
$pear_system_config = '';
$store_user_config = false;
$store_system_config = false;
$verbose = 1;

foreach ($opts as $opt) {
    switch ($opt[0]) {
    case 'c':
        $pear_user_config = $opt[1];
        break;
    case 'C':
        $pear_system_config = $opt[1];
        break;
    }
}

PEAR_Command::setFrontendType($fetype);
$ui = &PEAR_Command::getFrontendObject();
$config = &PEAR_Config::singleton($pear_user_config, $pear_system_config);

if (PEAR::isError($config)) {
    $_file = '';
    if ($pear_user_config !== false) {
        $_file .= $pear_user_config;
    }
    if ($pear_system_config !== false) {
        $_file .= '/' . $pear_system_config;
    }
    if ($_file == '/') {
        $_file = 'The default config file';
    }
    $config->getMessage();
    $ui->outputData("ERROR: $_file is not a valid config file or is corrupted.");
    // We stop, we have no idea where we are :)
    exit(1);
}

// this is used in the error handler to retrieve a relative path
$_PEAR_PHPDIR = $config->get('php_dir');
$ui->setConfig($config);
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError"));

$verbose = $config->get("verbose");
$cmdopts = array();

if ($raw) {
    if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) {
        $found = false;
        foreach ($opts as $opt) {
            if ($opt[0] == 'd' || $opt[0] == 'D') {
                // the user knows what they are doing, and are setting config values
                $found = true;
            }
        }
        if (!$found) {
            // no prior runs, try to install PEAR
            $parent = dirname(__FILE__);
            if (strpos($parent, 'scripts')) {
                $grandparent = dirname($parent);
                $packagexml = $grandparent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $grandparent;
            } else {
                $packagexml = $parent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $parent;
            }
            if (file_exists($packagexml)) {
                $options[1] = array(
                    'install',
                    $packagexml
                );
                $config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php');
                $config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data');
                $config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs');
                $config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests');
                $config->set(
                    'ext_dir',
                    $pearbase . DIRECTORY_SEPARATOR . 'extensions'
                );
                $config->set('bin_dir', $pearbase);
                $config->mergeConfigFile($pearbase . 'pear.ini', false);
                $config->store();
                $config->set('auto_discover', 1);
            }
        }
    }
}
foreach ($opts as $opt) {
    $param = !empty($opt[1]) ? $opt[1] : true;
    switch ($opt[0]) {
    case 'd':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected -d config_value=value, ' .
                'received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'user');
        break;
    case 'D':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'system');
        break;
    case 's':
        $store_user_config = true;
        break;
    case 'S':
        $store_system_config = true;
        break;
    case 'u':
        $config->remove($param, 'user');
        break;
    case 'v':
        $config->set('verbose', $config->get('verbose') + 1);
        break;
    case 'q':
        $config->set('verbose', $config->get('verbose') - 1);
        break;
    case 'V':
        usage(null, 'version');
    case 'c':
    case 'C':
        break;
    default:
        // all non pear params goes to the command
        $cmdopts[$opt[0]] = $param;
        break;
    }
}

if ($store_system_config) {
    $config->store('system');
}

if ($store_user_config) {
    $config->store('user');
}

$command = (isset($options[1][0])) ? $options[1][0] : null;
if (empty($command) && ($store_user_config || $store_system_config)) {
    exit;
}

if ($fetype == 'Gtk2') {
    if (!$config->validConfiguration()) {
        PEAR::raiseError(
            "CRITICAL ERROR: no existing valid configuration files found in " .
            "files '$pear_user_config' or '$pear_system_config', " .
            "please copy an existing configuration file to one of these " .
            "locations, or use the -c and -s options to create one"
        );
    }
    Gtk::main();
} else {
    do {
        if ($command == 'help') {
            usage(null, isset($options[1][1]) ? $options[1][1] : null);
        }

        if (!$config->validConfiguration()) {
            PEAR::raiseError(
                "CRITICAL ERROR: no existing valid configuration files found " .
                "in files '$pear_user_config' or '$pear_system_config', " .
                "please copy an existing configuration file to one of " .
                "these locations, or use the -c and -s options to create one"
            );
        }

        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        $cmd = PEAR_Command::factory($command, $config);
        PEAR::popErrorHandling();
        if (PEAR::isError($cmd)) {
            usage(null, isset($options[1][0]) ? $options[1][0] : null);
        }

        $short_args = $long_args = null;
        PEAR_Command::getGetoptArgs($command, $short_args, $long_args);
        array_shift($options[1]);
        $tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args);

        if (PEAR::isError($tmp)) {
            break;
        }

        list($tmpopt, $params) = $tmp;
        $opts = array();
        foreach ($tmpopt as $foo => $tmp2) {
            list($opt, $value) = $tmp2;
            if ($value === null) {
                $value = true; // options without args
            }

            if (strlen($opt) == 1) {
                $cmdoptions = $cmd->getOptions($command);
                foreach ($cmdoptions as $o => $d) {
                    if (isset($d['shortopt']) && $d['shortopt'] == $opt) {
                        $opts[$o] = $value;
                    }
                }
            } else {
                if (substr($opt, 0, 2) == '--') {
                    $opts[substr($opt, 2)] = $value;
                }
            }
        }

        $ok = $cmd->run($command, $opts, $params);
        if ($ok === false) {
            PEAR::raiseError("unknown command `$command'");
        }

        if (PEAR::isError($ok)) {
            PEAR::setErrorHandling(
                PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")
            );
            PEAR::raiseError($ok);
        }
    } while (false);
}

// {{{ usage()

/**
 * Display usage information
 *
 * @param mixed $error       Optional error message
 * @param mixed $helpsubject Optional subject/command to display help for
 *
 * @return void
 */
function usage($error = null, $helpsubject = null)
{
    global $progname, $all_commands;
    $stdout = fopen('php://stdout', 'w');
    if (PEAR::isError($error)) {
        fputs($stdout, $error->getMessage() . "\n");
    } elseif ($error !== null) {
        fputs($stdout, "$error\n");
    }

    if ($helpsubject != null) {
        $put = cmdHelp($helpsubject);
    } else {
        $put = "Commands:\n";
        $maxlen = max(array_map("strlen", $all_commands));
        $formatstr = "%-{$maxlen}s  %s\n";
        ksort($all_commands);
        foreach ($all_commands as $cmd => $class) {
            $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd));
        }
        $put .=
            "Usage: $progname [options] command [command-options] <parameters>\n".
            "Type \"$progname help options\" to list all options.\n".
            "Type \"$progname help shortcuts\" to list all command shortcuts.\n".
            "Type \"$progname help version\" or ".
            "\"$progname version\" to list version information.\n".
            "Type \"$progname help <command>\" to get the help ".
            "for the specified command.";
    }
    fputs($stdout, "$put\n");
    fclose($stdout);

    if ($error === null) {
        exit(0);
    }
    exit(1);
}

/**
 * Return help string for specified command
 *
 * @param string $command Command to return help for
 *
 * @return void
 */
function cmdHelp($command)
{
    global $progname, $all_commands, $config;
    if ($command == "options") {
        return
        "Options:\n".
        "     -v         increase verbosity level (default 1)\n".
        "     -q         be quiet, decrease verbosity level\n".
        "     -c file    find user configuration in `file'\n".
        "     -C file    find system configuration in `file'\n".
        "     -d foo=bar set user config variable `foo' to `bar'\n".
        "     -D foo=bar set system config variable `foo' to `bar'\n".
        "     -G         start in graphical (Gtk) mode\n".
        "     -s         store user configuration\n".
        "     -S         store system configuration\n".
        "     -u foo     unset `foo' in the user configuration\n".
        "     -h, -?     display help/usage (this message)\n".
        "     -V         version information\n";
    } elseif ($command == "shortcuts") {
        $sc = PEAR_Command::getShortcuts();
        $ret = "Shortcuts:\n";
        foreach ($sc as $s => $c) {
            $ret .= sprintf("     %-8s %s\n", $s, $c);
        }
        return $ret;

    } elseif ($command == "version") {
        return "PEAR Version: ".$GLOBALS['pear_package_version'].
               "\nPHP Version: ".phpversion().
               "\nZend Engine Version: ".zend_version().
               "\nRunning on: ".php_uname();

    } elseif ($help = PEAR_Command::getHelp($command)) {
        if (is_string($help)) {
            return "$progname $command [options] $help\n";
        }

        if ($help[1] === null) {
            return "$progname $command $help[0]";
        }

        return "$progname $command [options] $help[0]\n$help[1]";
    }

    return "Command '$command' is not valid, try '$progname help'";
}

// }}}

/**
 * error_handler
 *
 * @param mixed $errno  Error number
 * @param mixed $errmsg Message
 * @param mixed $file   Filename
 * @param mixed $line   Line number
 *
 * @access public
 * @return boolean
 */
function error_handler($errno, $errmsg, $file, $line)
{
    if ((!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) && ($errno & E_STRICT)) {
        return; // E_STRICT
    }
    if ($errno & E_DEPRECATED) {
        return; // E_DEPRECATED
    }
    if (!(error_reporting() & $errno) &&
        isset($GLOBALS['config']) &&
        $GLOBALS['config']->get('verbose') < 4
    ) {
        return false; // @silenced error, show all if debug is high enough
    }
    $errortype = array (
        E_DEPRECATED  => 'Deprecated Warning',
        E_ERROR   =>  "Error",
        E_WARNING   =>  "Warning",
        E_PARSE   =>  "Parsing Error",
        E_NOTICE   =>  "Notice",
        E_CORE_ERROR  =>  "Core Error",
        E_CORE_WARNING  =>  "Core Warning",
        E_COMPILE_ERROR  =>  "Compile Error",
        E_COMPILE_WARNING =>  "Compile Warning",
        E_USER_ERROR =>  "User Error",
        E_USER_WARNING =>  "User Warning",
        E_USER_NOTICE =>  "User Notice"
    );
    if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) {
        $errortype[E_STRICT] = 'Strict Warning';
    }
    $prefix = $errortype[$errno];
    global $_PEAR_PHPDIR;
    if (stristr($file, $_PEAR_PHPDIR)) {
        $file = substr($file, strlen($_PEAR_PHPDIR) + 1);
    } else {
        $file = basename($file);
    }
    print "\n$prefix: $errmsg in $file on line $line\n";
    return false;
}


/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * indent-tabs-mode: nil
 * mode: php
 * End:
 */
// vim600:syn=php
PK��Z�0$�-- .pkgxml/Pear_File_MARC-1.4.1.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.10.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
 <name>File_MARC</name>
 <channel>pear.php.net</channel>
 <summary>Parse, modify, and create MARC records</summary>
 <description>The standard for machine-readable cataloging (MARC) records is documented at http://loc.gov/marc/. This package enables you to read existing MARC records from a file, string, or (using the YAZ extension), from a Z39.50 source. You can also use this package to create new MARC records.

This package is based on the PHP MARC package, originally called &quot;php-marc&quot;, that is part of the Emilda Project (http://www.emilda.org).  Christoffer Landtman generously agreed to make the &quot;php-marc&quot; code available under the GNU LGPL so it could be used as the basis of this PEAR package.</description>
 <lead>
  <name>Dan Scott</name>
  <user>dbs</user>
  <email>dbs@php.net</email>
  <active>yes</active>
 </lead>
 <date>2019-11-13</date>
 <time>17:33:33</time>
 <version>
  <release>1.4.1</release>
  <api>1.4.0</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license uri="http://www.gnu.org/copyleft/lesser.html">GNU Lesser General Public License</license>
 <notes>
1.4.1
  * Reintroduce include_path to composer.json
 </notes>
 <contents>
  <dir baseinstalldir="File" name="/">
   <file baseinstalldir="/" md5sum="ffe2590635f404af055fe731da105939" name="File/MARC/Lint/CodeData.php" role="php" />
   <file baseinstalldir="/" md5sum="a3b9e1c817e67f59add05593500d463e" name="File/MARC/Control_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="acba4463f8e40d6ee4e7ba1f2dc53123" name="File/MARC/Data_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="378f483ec1fd161cd9dfb9b05db58d66" name="File/MARC/Exception.php" role="php" />
   <file baseinstalldir="/" md5sum="a9ba69030cbf4847292b9975e9d922c6" name="File/MARC/Field.php" role="php" />
   <file baseinstalldir="/" md5sum="c37351c7c80927ce6bb1e662510f9183" name="File/MARC/Lint.php" role="php" />
   <file baseinstalldir="/" md5sum="c5ac39e3d25eb0108b9dd5ad8466c821" name="File/MARC/List.php" role="php" />
   <file baseinstalldir="/" md5sum="7af6ce78cde4bb246e4e96709e90d2c0" name="File/MARC/Record.php" role="php" />
   <file baseinstalldir="/" md5sum="df5f97139685f0ad04e47fdbb67e3968" name="File/MARC/Subfield.php" role="php" />
   <file baseinstalldir="/" md5sum="6e102262dfd5d65d8d5a6221dfc74edd" name="File/MARC.php" role="php" />
   <file baseinstalldir="/" md5sum="8b64040d2d18ac4b994595a148266a66" name="File/MARCBASE.php" role="php" />
   <file baseinstalldir="/" md5sum="f5a17a60d34e84e2ee7ca1e5c5c6c620" name="File/MARCXML.php" role="php" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="examples/example.mrc" role="doc" />
   <file baseinstalldir="File" md5sum="1aea40df9f1c2e32f8e065fe8da0a3b5" name="examples/marc_yaz.php" role="doc" />
   <file baseinstalldir="File" md5sum="70ae317e0890d5896e3ffccdd293369a" name="examples/read.php" role="doc" />
   <file baseinstalldir="File" md5sum="54efb9d920ac775bfc847a83a2dec73a" name="examples/subfields.php" role="doc" />
   <file baseinstalldir="File" md5sum="14297da35b510c496cd1f328cf3bb301" name="tests/bad_example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="0dd4c6dbad6e8608d0ebf9d24425955d" name="tests/bad_example.xml" role="test" />
   <file baseinstalldir="File" md5sum="216a6f9d53f6d3d8e22d81fdc10f4bc1" name="tests/camel.mrc" role="test" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="tests/example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="9455aec3371f79cf7d31281fd03f5171" name="tests/marc_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="577e2f5f89fd48cf1a3576a29d2958f8" name="tests/marc_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a6a586354b9a06c880c2a7470dd828d7" name="tests/marc_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1c7e2fc5572a0f9362a771c260a1fe3" name="tests/marc_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="84f85ac7f8a2532e4e90ccde7764556a" name="tests/marc_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="889e5e906a97de7a0e94b0c5f30e70e7" name="tests/marc_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="be823dc8a8efb408de06371ab802efcc" name="tests/marc_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="af44490aafea44e5120f881cb81cdad9" name="tests/marc_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ac9f2a7aeb24900a11f5102744179ae3" name="tests/marc_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5e43eb5cddbb4f2bd0d6405cd95b80aa" name="tests/marc_010.phpt" role="test" />
   <file baseinstalldir="File" md5sum="2e1cd8509c0bf04ec77fc0f51375f611" name="tests/marc_011.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bc49ca48623102c8ac07679fa77a3dd9" name="tests/marc_012.phpt" role="test" />
   <file baseinstalldir="File" md5sum="245a3b20e0da1973535503e28efd1d3a" name="tests/marc_013.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ce69aa734856dd40d60d30c77bdef53a" name="tests/marc_014.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7b61cdd31035e60682fa92c5d519d997" name="tests/marc_015.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7f4f597fe1adaa3507eb87fc4875dbd2" name="tests/marc_016.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4262efd5fcacbd7503323681f4552430" name="tests/marc_017.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ee1623d7bda54ba4f741b2319b158f82" name="tests/marc_018.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8006c03fbab0f04377342086fafd3982" name="tests/marc_019.phpt" role="test" />
   <file baseinstalldir="File" md5sum="f5ae5b25e0ac1104314433d9e5b1f7fe" name="tests/marc_020.phpt" role="test" />
   <file baseinstalldir="File" md5sum="94d8f99e86585671a1b2d3043aeb6360" name="tests/marc_021.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bb891a890effe0e77e1759043f4846d8" name="tests/marc_022.phpt" role="test" />
   <file baseinstalldir="File" md5sum="faf77dcb5cdd002c09169a14bfded65e" name="tests/marc_023.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0e6c4a23f5da7df64fdd4b3b1149bbee" name="tests/marc_16783.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4ea8b3520beda378db15960f1c50493a" name="tests/marc_field_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="743850ef61df69c4340be44a03bccb5a" name="tests/marc_field_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8c765f1398b49df257d86d22ac6e4f8d" name="tests/marc_field_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d4216cf930a308e0d02553bd3914f294" name="tests/marc_field_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dd59514b474b78371ad522a3e13b76b7" name="tests/marc_field_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5295bfd02a8424acac1c91de26b552c7" name="tests/marc_field_21246.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6f95f09442ccf6b93df92986f58b270d" name="tests/marc_lint_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="18d721f8871edd925624ccbdd15444fb" name="tests/marc_lint_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4eb86a2f4e0a74dedcb0bf2511da6ca1" name="tests/marc_lint_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="10430fee0a1352d0528f1507b34c57e1" name="tests/marc_lint_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0dcd07a18577d7b22392a2214cd6436c" name="tests/marc_lint_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fd17798fc535562e5e64461f449516b2" name="tests/marc_record_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="141b455ccf67a60c4eac44c77960f2e2" name="tests/marc_subfield_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1e23464ee0eec47ddca2af9a9922926" name="tests/marc_subfield_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="1d7903e8c244d647220b318b4bc758d1" name="tests/marc_xml_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="22cae3c752d843b78f583dcd92801534" name="tests/marc_xml_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="c0716d23e0f960abf8d53ad6014a413a" name="tests/marc_xml_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7645fa19e28aca041a124fc5e2c12bd3" name="tests/marc_xml_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b08b28c3251625b8b6e4d7ab376b0185" name="tests/marc_xml_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6cd0934ddbf65d2d7e9ea5d108977ff7" name="tests/marc_xml_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ffdce4aa190268fa7cbbf3bb45383abf" name="tests/marc_xml_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="998a4c1ce00ff100f39ffa9fc49a212f" name="tests/marc_xml_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a38a67c590869f2b0a4859a910fd9e89" name="tests/marc_xml_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="db39c5055a570fcda12bb7c5fa1e3b4d" name="tests/marc_xml_16642.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dc075f4a271bd7182378a3874bd5b39e" name="tests/marc_xml_namespace.phpt" role="test" />
   <file baseinstalldir="File" md5sum="208200d9a979ac360c4d326e9789b6b7" name="tests/marc_xml_namespace_prefix.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d87774ede82222cfc12b2c2a06f57a3a" name="tests/marc_xml_rsinger.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fb44e3eb69f1a37115235fc829c39542" name="tests/namespace.xml" role="test" />
   <file baseinstalldir="File" md5sum="e6de4d809b0af5dd99fd352eb60616a1" name="tests/skipif.inc" role="test" />
   <file baseinstalldir="File" md5sum="a0166a4ff0bc0bb283e854f11beaa793" name="tests/music.mrc" role="test" />
   <file baseinstalldir="File" md5sum="993ce494befbc25dc1326527b30b4782" name="tests/music.xml" role="test" />
   <file baseinstalldir="File" md5sum="6b0c87f0cd459ed7322c25d403b164cc" name="tests/bigarchive.xml" role="test" />
   <file baseinstalldir="File" md5sum="be850aa6ab4ac52b8c6c214c30b574af" name="tests/onerecord.xml" role="test" />
   <file baseinstalldir="File" md5sum="4f43fec7b276267eec5258044853ccc8" name="tests/sandburg.mrc" role="test" />
   <file baseinstalldir="File" md5sum="e216b95f905dd240c9bde372950e4073" name="tests/sandburg.xml" role="test" />
   <file baseinstalldir="File" md5sum="e81a92188ea0dcd9c108a63fb32b3f4f" name="tests/xmlescape.mrc" role="test" />
   <file baseinstalldir="File" md5sum="8f9f63ed6a80191d89a2296fa4c1a30b" name="CHANGELOG" role="doc" />
   <file baseinstalldir="File" md5sum="fbc093901857fcd118f065f900982c24" name="LICENSE" role="doc" />
  </dir>
 </contents>
 <dependencies>
  <required>
   <php>
    <min>5.6</min>
   </php>
   <pearinstaller>
    <min>1.4.0</min>
   </pearinstaller>
  </required>
  <optional>
   <package>
    <name>Validate_ISPN</name>
    <channel>pear.php.net</channel>
   </package>
  </optional>
 </dependencies>
 <phprelease />
</package>
PKm�ZPi��.depdbnu�[���PKm�Z�{��
�Mail/null.phpnu�[���PKm�ZE@�%>>
Mail/sendmail.phpnu�[���PKm�Z��A~�{�{�;Mail/RFC822.phpnu�[���PKn�Z�+V����
[�Mail/mime.phpnu�[���PKn�Zx�ع���D�Mail/mimeDecode.phpnu�[���PKn�ZB�_Ǭ=�=
@(Mail/smtp.phpnu�[���PKn�ZwԐE;E;)fMail/smtpmx.phpnu�[���PKn�Z�؛�J�J���Mail/mimePart.phpnu�[���PKn�ZB��shh
8YMail/mock.phpnu�[���PKn�Z@iE�\\
�lMail/mail.phpnu�[���PKn�Zv�.locknu�[���PKn�Z�*�z%-%- ��Structures/LinkedList/Double.phpnu�[���PKn�Z����p:p:  �Structures/LinkedList/Single.phpnu�[���PKn�ZUyv���Structures/Graph.phpnu�[���PKn�Z�C� + +CStructures/Graph/Node.phpnu�[���PKn�Z9����,�1Structures/Graph/Manipulator/AcyclicTest.phpnu�[���PKn�Z~(�htt2�HStructures/Graph/Manipulator/TopologicalSorter.phpnu�[���PKn�Z�J�}
}
_dAuth/SASL/Anonymous.phpnu�[���PKn�ZP(~�T
T
#rAuth/SASL/CramMD5.phpnu�[���PKn�Z����==�Auth/SASL/Plain.phpnu�[���PKn�Z�<� OO<�Auth/SASL/Login.phpnu�[���PK��Z�
��d�d�/.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUri   URI of the namespace
     * @param bool   $multiline      whether to create a multiline tag where each
     *                               attribute gets written to a single line
     * @param string $indent         string used to indent attributes (_auto indents
     *                               attributes so they start at the same column)
     * @param string $linebreak      string used for linebreaks
     * @param bool   $sortAttributes Whether to sort the attributes or not
     *
     * @return string XML start element
     * @see    createEndElement(), createTag()
     */
    public static function createStartElement(
        $qname, $attributes = array(), $namespaceUri = null,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true
    ) {
        // if no attributes hav been set, use empty attributes
        if (!isset($attributes) || !is_array($attributes)) {
            $attributes = array();
        }

        if ($namespaceUri != null) {
            $parts = XML_Util::splitQualifiedName($qname);
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($qname)+2));
            }
        }

        if ($namespaceUri != null) {
            // is a namespace given
            if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
            } else {
                // define this Uri as the default namespace
                $attributes['xmlns'] = $namespaceUri;
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $attributes, $sortAttributes,
            $multiline, $indent, $linebreak
        );
        $element = sprintf('<%s%s>', $qname, $attList);
        return  $element;
    }

    /**
     * Create an end element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createEndElement('myNs:myTag');
     * </code>
     *
     * @param string $qname qualified tagname (including namespace)
     *
     * @return string XML end element
     * @see    createStartElement(), createTag()
     */
    public static function createEndElement($qname)
    {
        $element = sprintf('</%s>', $qname);
        return $element;
    }

    /**
     * Create an XML comment
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createComment('I am a comment');
     * </code>
     *
     * @param string $content content of the comment
     *
     * @return string XML comment
     */
    public static function createComment($content)
    {
        $comment = sprintf('<!-- %s -->', $content);
        return $comment;
    }

    /**
     * Create a CData section
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create a CData section
     * $tag = XML_Util::createCDataSection('I am content.');
     * </code>
     *
     * @param string $data data of the CData section
     *
     * @return string CData section with content
     */
    public static function createCDataSection($data)
    {
        return sprintf(
            '<![CDATA[%s]]>',
            preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data))
        );
    }

    /**
     * Split qualified name and return namespace and local part
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // split qualified tag
     * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
     * </code>
     * the returned array will contain two elements:
     * <pre>
     * array(
     *     'namespace' => 'xslt',
     *     'localPart' => 'stylesheet'
     * );
     * </pre>
     *
     * @param string $qname     qualified tag name
     * @param string $defaultNs default namespace (optional)
     *
     * @return array array containing namespace and local part
     */
    public static function splitQualifiedName($qname, $defaultNs = null)
    {
        if (strstr($qname, ':')) {
            $tmp = explode(':', $qname);
            return array(
                'namespace' => $tmp[0],
                'localPart' => $tmp[1]
            );
        }
        return array(
            'namespace' => $defaultNs,
            'localPart' => $qname
        );
    }

    /**
     * Check, whether string is valid XML name
     *
     * <p>XML names are used for tagname, attribute names and various
     * other, lesser known entities.</p>
     * <p>An XML name may only consist of alphanumeric characters,
     * dashes, undescores and periods, and has to start with a letter
     * or an underscore.</p>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // verify tag name
     * $result = XML_Util::isValidName('invalidTag?');
     * if (is_a($result, 'PEAR_Error')) {
     *    print 'Invalid XML name: ' . $result->getMessage();
     * }
     * </code>
     *
     * @param string $string string that should be checked
     *
     * @return mixed true, if string is a valid XML name, PEAR error otherwise
     *
     * @todo support for other charsets
     * @todo PEAR CS - unable to avoid 85-char limit on second preg_match
     */
    public static function isValidName($string)
    {
        // check for invalid chars
        if (!is_string($string) || !strlen($string) || !preg_match('/^[[:alpha:]_]\\z/', $string[0])) {
            return XML_Util::raiseError(
                'XML names may only start with letter or underscore',
                XML_UTIL_ERROR_INVALID_START
            );
        }

        // check for invalid chars
        $match = preg_match(
            '/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?'
            . '[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/',
            $string
        );
        if (!$match) {
            return XML_Util::raiseError(
                'XML names may only contain alphanumeric '
                . 'chars, period, hyphen, colon and underscores',
                XML_UTIL_ERROR_INVALID_CHARS
            );
        }
        // XML name is valid
        return true;
    }

    /**
     * Replacement for XML_Util::raiseError
     *
     * Avoids the necessity to always require
     * PEAR.php
     *
     * @param string $msg  error message
     * @param int    $code error code
     *
     * @return PEAR_Error
     * @todo   PEAR CS - should this use include_once instead?
     */
    public static function raiseError($msg, $code)
    {
        include_once 'PEAR.php';
        return PEAR::raiseError($msg, $code);
    }
}
?>
PK��Z#F��:�:pearcmd.phpnu�[���<?php
/**
 * PEAR, the PHP Extension and Application Repository
 *
 * Command line interface
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Stig Bakken <ssb@php.net>
 * @author    Tomas V.V.Cox <cox@idecnet.com>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 */

@ob_end_clean();
if (!defined('PEAR_RUNTYPE')) {
    // this is defined in peclcmd.php as 'pecl'
    define('PEAR_RUNTYPE', 'pear');
}
define('PEAR_IGNORE_BACKTRACE', 1);
/**
 * @nodep Gtk
 */
//the space is needed for windows include paths with trailing backslash
// http://pear.php.net/bugs/bug.php?id=19482
if ('/opt/alt/php74/usr/share/pear ' != '@'.'include_path'.'@ ') {
    ini_set('include_path', trim('/opt/alt/php74/usr/share/pear '). PATH_SEPARATOR .  get_include_path());
    $raw = false;
} else {
    // this is a raw, uninstalled pear, either a cvs checkout, or php distro
    ini_set('include_path', dirname(__DIR__) . PATH_SEPARATOR . get_include_path());
    $raw = true;
}
@ini_set('allow_url_fopen', true);
@set_time_limit(0);
ob_implicit_flush(true);
@ini_set('track_errors', true);
@ini_set('html_errors', false);
$_PEAR_PHPDIR = '#$%^&*';
set_error_handler('error_handler');

$pear_package_version = "1.10.16";

require_once 'PEAR.php';
require_once 'PEAR/Frontend.php';
require_once 'PEAR/Config.php';
require_once 'PEAR/Command.php';
require_once 'Console/Getopt.php';


PEAR_Command::setFrontendType('CLI');
$all_commands = PEAR_Command::getCommands();

$argv = Console_Getopt::readPHPArgv();
// fix CGI sapi oddity - the -- in pear.bat/pear is not removed
if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
    unset($argv[1]);
    $argv = array_values($argv);
}
$progname = PEAR_RUNTYPE;
array_shift($argv);
$options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV");
if (PEAR::isError($options)) {
    usage($options);
}

$opts = $options[0];

$fetype = 'CLI';
if ($progname == 'gpear' || $progname == 'pear-gtk') {
    $fetype = 'Gtk2';
} else {
    foreach ($opts as $opt) {
        if ($opt[0] == 'G') {
            $fetype = 'Gtk2';
        }
    }
}

$pear_user_config = '';
$pear_system_config = '';
$store_user_config = false;
$store_system_config = false;
$verbose = 1;

foreach ($opts as $opt) {
    switch ($opt[0]) {
    case 'c':
        $pear_user_config = $opt[1];
        break;
    case 'C':
        $pear_system_config = $opt[1];
        break;
    }
}

PEAR_Command::setFrontendType($fetype);
$ui = &PEAR_Command::getFrontendObject();
$config = &PEAR_Config::singleton($pear_user_config, $pear_system_config);

if (PEAR::isError($config)) {
    $_file = '';
    if ($pear_user_config !== false) {
        $_file .= $pear_user_config;
    }
    if ($pear_system_config !== false) {
        $_file .= '/' . $pear_system_config;
    }
    if ($_file == '/') {
        $_file = 'The default config file';
    }
    $config->getMessage();
    $ui->outputData("ERROR: $_file is not a valid config file or is corrupted.");
    // We stop, we have no idea where we are :)
    exit(1);
}

// this is used in the error handler to retrieve a relative path
$_PEAR_PHPDIR = $config->get('php_dir');
$ui->setConfig($config);
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError"));

$verbose = $config->get("verbose");
$cmdopts = array();

if ($raw) {
    if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) {
        $found = false;
        foreach ($opts as $opt) {
            if ($opt[0] == 'd' || $opt[0] == 'D') {
                // the user knows what they are doing, and are setting config values
                $found = true;
            }
        }
        if (!$found) {
            // no prior runs, try to install PEAR
            $parent = dirname(__FILE__);
            if (strpos($parent, 'scripts')) {
                $grandparent = dirname($parent);
                $packagexml = $grandparent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $grandparent;
            } else {
                $packagexml = $parent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $parent;
            }
            if (file_exists($packagexml)) {
                $options[1] = array(
                    'install',
                    $packagexml
                );
                $config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php');
                $config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data');
                $config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs');
                $config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests');
                $config->set(
                    'ext_dir',
                    $pearbase . DIRECTORY_SEPARATOR . 'extensions'
                );
                $config->set('bin_dir', $pearbase);
                $config->mergeConfigFile($pearbase . 'pear.ini', false);
                $config->store();
                $config->set('auto_discover', 1);
            }
        }
    }
}
foreach ($opts as $opt) {
    $param = !empty($opt[1]) ? $opt[1] : true;
    switch ($opt[0]) {
    case 'd':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected -d config_value=value, ' .
                'received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'user');
        break;
    case 'D':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'system');
        break;
    case 's':
        $store_user_config = true;
        break;
    case 'S':
        $store_system_config = true;
        break;
    case 'u':
        $config->remove($param, 'user');
        break;
    case 'v':
        $config->set('verbose', $config->get('verbose') + 1);
        break;
    case 'q':
        $config->set('verbose', $config->get('verbose') - 1);
        break;
    case 'V':
        usage(null, 'version');
    case 'c':
    case 'C':
        break;
    default:
        // all non pear params goes to the command
        $cmdopts[$opt[0]] = $param;
        break;
    }
}

if ($store_system_config) {
    $config->store('system');
}

if ($store_user_config) {
    $config->store('user');
}

$command = (isset($options[1][0])) ? $options[1][0] : null;
if (empty($command) && ($store_user_config || $store_system_config)) {
    exit;
}

if ($fetype == 'Gtk2') {
    if (!$config->validConfiguration()) {
        PEAR::raiseError(
            "CRITICAL ERROR: no existing valid configuration files found in " .
            "files '$pear_user_config' or '$pear_system_config', " .
            "please copy an existing configuration file to one of these " .
            "locations, or use the -c and -s options to create one"
        );
    }
    Gtk::main();
} else {
    do {
        if ($command == 'help') {
            usage(null, isset($options[1][1]) ? $options[1][1] : null);
        }

        if (!$config->validConfiguration()) {
            PEAR::raiseError(
                "CRITICAL ERROR: no existing valid configuration files found " .
                "in files '$pear_user_config' or '$pear_system_config', " .
                "please copy an existing configuration file to one of " .
                "these locations, or use the -c and -s options to create one"
            );
        }

        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        $cmd = PEAR_Command::factory($command, $config);
        PEAR::popErrorHandling();
        if (PEAR::isError($cmd)) {
            usage(null, isset($options[1][0]) ? $options[1][0] : null);
        }

        $short_args = $long_args = null;
        PEAR_Command::getGetoptArgs($command, $short_args, $long_args);
        array_shift($options[1]);
        $tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args);

        if (PEAR::isError($tmp)) {
            break;
        }

        list($tmpopt, $params) = $tmp;
        $opts = array();
        foreach ($tmpopt as $foo => $tmp2) {
            list($opt, $value) = $tmp2;
            if ($value === null) {
                $value = true; // options without args
            }

            if (strlen($opt) == 1) {
                $cmdoptions = $cmd->getOptions($command);
                foreach ($cmdoptions as $o => $d) {
                    if (isset($d['shortopt']) && $d['shortopt'] == $opt) {
                        $opts[$o] = $value;
                    }
                }
            } else {
                if (substr($opt, 0, 2) == '--') {
                    $opts[substr($opt, 2)] = $value;
                }
            }
        }

        $ok = $cmd->run($command, $opts, $params);
        if ($ok === false) {
            PEAR::raiseError("unknown command `$command'");
        }

        if (PEAR::isError($ok)) {
            PEAR::setErrorHandling(
                PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")
            );
            PEAR::raiseError($ok);
        }
    } while (false);
}

// {{{ usage()

/**
 * Display usage information
 *
 * @param mixed $error       Optional error message
 * @param mixed $helpsubject Optional subject/command to display help for
 *
 * @return void
 */
function usage($error = null, $helpsubject = null)
{
    global $progname, $all_commands;
    $stdout = fopen('php://stdout', 'w');
    if (PEAR::isError($error)) {
        fputs($stdout, $error->getMessage() . "\n");
    } elseif ($error !== null) {
        fputs($stdout, "$error\n");
    }

    if ($helpsubject != null) {
        $put = cmdHelp($helpsubject);
    } else {
        $put = "Commands:\n";
        $maxlen = max(array_map("strlen", $all_commands));
        $formatstr = "%-{$maxlen}s  %s\n";
        ksort($all_commands);
        foreach ($all_commands as $cmd => $class) {
            $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd));
        }
        $put .=
            "Usage: $progname [options] command [command-options] <parameters>\n".
            "Type \"$progname help options\" to list all options.\n".
            "Type \"$progname help shortcuts\" to list all command shortcuts.\n".
            "Type \"$progname help version\" or ".
            "\"$progname version\" to list version information.\n".
            "Type \"$progname help <command>\" to get the help ".
            "for the specified command.";
    }
    fputs($stdout, "$put\n");
    fclose($stdout);

    if ($error === null) {
        exit(0);
    }
    exit(1);
}

/**
 * Return help string for specified command
 *
 * @param string $command Command to return help for
 *
 * @return void
 */
function cmdHelp($command)
{
    global $progname, $all_commands, $config;
    if ($command == "options") {
        return
        "Options:\n".
        "     -v         increase verbosity level (default 1)\n".
        "     -q         be quiet, decrease verbosity level\n".
        "     -c file    find user configuration in `file'\n".
        "     -C file    find system configuration in `file'\n".
        "     -d foo=bar set user config variable `foo' to `bar'\n".
        "     -D foo=bar set system config variable `foo' to `bar'\n".
        "     -G         start in graphical (Gtk) mode\n".
        "     -s         store user configuration\n".
        "     -S         store system configuration\n".
        "     -u foo     unset `foo' in the user configuration\n".
        "     -h, -?     display help/usage (this message)\n".
        "     -V         version information\n";
    } elseif ($command == "shortcuts") {
        $sc = PEAR_Command::getShortcuts();
        $ret = "Shortcuts:\n";
        foreach ($sc as $s => $c) {
            $ret .= sprintf("     %-8s %s\n", $s, $c);
        }
        return $ret;

    } elseif ($command == "version") {
        return "PEAR Version: ".$GLOBALS['pear_package_version'].
               "\nPHP Version: ".phpversion().
               "\nZend Engine Version: ".zend_version().
               "\nRunning on: ".php_uname();

    } elseif ($help = PEAR_Command::getHelp($command)) {
        if (is_string($help)) {
            return "$progname $command [options] $help\n";
        }

        if ($help[1] === null) {
            return "$progname $command $help[0]";
        }

        return "$progname $command [options] $help[0]\n$help[1]";
    }

    return "Command '$command' is not valid, try '$progname help'";
}

// }}}

/**
 * error_handler
 *
 * @param mixed $errno  Error number
 * @param mixed $errmsg Message
 * @param mixed $file   Filename
 * @param mixed $line   Line number
 *
 * @access public
 * @return boolean
 */
function error_handler($errno, $errmsg, $file, $line)
{
    if ((!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) && ($errno & E_STRICT)) {
        return; // E_STRICT
    }
    if ($errno & E_DEPRECATED) {
        return; // E_DEPRECATED
    }
    if (!(error_reporting() & $errno) &&
        isset($GLOBALS['config']) &&
        $GLOBALS['config']->get('verbose') < 4
    ) {
        return false; // @silenced error, show all if debug is high enough
    }
    $errortype = array (
        E_DEPRECATED  => 'Deprecated Warning',
        E_ERROR   =>  "Error",
        E_WARNING   =>  "Warning",
        E_PARSE   =>  "Parsing Error",
        E_NOTICE   =>  "Notice",
        E_CORE_ERROR  =>  "Core Error",
        E_CORE_WARNING  =>  "Core Warning",
        E_COMPILE_ERROR  =>  "Compile Error",
        E_COMPILE_WARNING =>  "Compile Warning",
        E_USER_ERROR =>  "User Error",
        E_USER_WARNING =>  "User Warning",
        E_USER_NOTICE =>  "User Notice"
    );
    if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) {
        $errortype[E_STRICT] = 'Strict Warning';
    }
    $prefix = $errortype[$errno];
    global $_PEAR_PHPDIR;
    if (stristr($file, $_PEAR_PHPDIR)) {
        $file = substr($file, strlen($_PEAR_PHPDIR) + 1);
    } else {
        $file = basename($file);
    }
    print "\n$prefix: $errmsg in $file on line $line\n";
    return false;
}


/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * indent-tabs-mode: nil
 * mode: php
 * End:
 */
// vim600:syn=php
PK��Z�0$�-- .pkgxml/Pear_File_MARC-1.4.1.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.10.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
 <name>File_MARC</name>
 <channel>pear.php.net</channel>
 <summary>Parse, modify, and create MARC records</summary>
 <description>The standard for machine-readable cataloging (MARC) records is documented at http://loc.gov/marc/. This package enables you to read existing MARC records from a file, string, or (using the YAZ extension), from a Z39.50 source. You can also use this package to create new MARC records.

This package is based on the PHP MARC package, originally called &quot;php-marc&quot;, that is part of the Emilda Project (http://www.emilda.org).  Christoffer Landtman generously agreed to make the &quot;php-marc&quot; code available under the GNU LGPL so it could be used as the basis of this PEAR package.</description>
 <lead>
  <name>Dan Scott</name>
  <user>dbs</user>
  <email>dbs@php.net</email>
  <active>yes</active>
 </lead>
 <date>2019-11-13</date>
 <time>17:33:33</time>
 <version>
  <release>1.4.1</release>
  <api>1.4.0</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license uri="http://www.gnu.org/copyleft/lesser.html">GNU Lesser General Public License</license>
 <notes>
1.4.1
  * Reintroduce include_path to composer.json
 </notes>
 <contents>
  <dir baseinstalldir="File" name="/">
   <file baseinstalldir="/" md5sum="ffe2590635f404af055fe731da105939" name="File/MARC/Lint/CodeData.php" role="php" />
   <file baseinstalldir="/" md5sum="a3b9e1c817e67f59add05593500d463e" name="File/MARC/Control_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="acba4463f8e40d6ee4e7ba1f2dc53123" name="File/MARC/Data_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="378f483ec1fd161cd9dfb9b05db58d66" name="File/MARC/Exception.php" role="php" />
   <file baseinstalldir="/" md5sum="a9ba69030cbf4847292b9975e9d922c6" name="File/MARC/Field.php" role="php" />
   <file baseinstalldir="/" md5sum="c37351c7c80927ce6bb1e662510f9183" name="File/MARC/Lint.php" role="php" />
   <file baseinstalldir="/" md5sum="c5ac39e3d25eb0108b9dd5ad8466c821" name="File/MARC/List.php" role="php" />
   <file baseinstalldir="/" md5sum="7af6ce78cde4bb246e4e96709e90d2c0" name="File/MARC/Record.php" role="php" />
   <file baseinstalldir="/" md5sum="df5f97139685f0ad04e47fdbb67e3968" name="File/MARC/Subfield.php" role="php" />
   <file baseinstalldir="/" md5sum="6e102262dfd5d65d8d5a6221dfc74edd" name="File/MARC.php" role="php" />
   <file baseinstalldir="/" md5sum="8b64040d2d18ac4b994595a148266a66" name="File/MARCBASE.php" role="php" />
   <file baseinstalldir="/" md5sum="f5a17a60d34e84e2ee7ca1e5c5c6c620" name="File/MARCXML.php" role="php" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="examples/example.mrc" role="doc" />
   <file baseinstalldir="File" md5sum="1aea40df9f1c2e32f8e065fe8da0a3b5" name="examples/marc_yaz.php" role="doc" />
   <file baseinstalldir="File" md5sum="70ae317e0890d5896e3ffccdd293369a" name="examples/read.php" role="doc" />
   <file baseinstalldir="File" md5sum="54efb9d920ac775bfc847a83a2dec73a" name="examples/subfields.php" role="doc" />
   <file baseinstalldir="File" md5sum="14297da35b510c496cd1f328cf3bb301" name="tests/bad_example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="0dd4c6dbad6e8608d0ebf9d24425955d" name="tests/bad_example.xml" role="test" />
   <file baseinstalldir="File" md5sum="216a6f9d53f6d3d8e22d81fdc10f4bc1" name="tests/camel.mrc" role="test" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="tests/example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="9455aec3371f79cf7d31281fd03f5171" name="tests/marc_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="577e2f5f89fd48cf1a3576a29d2958f8" name="tests/marc_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a6a586354b9a06c880c2a7470dd828d7" name="tests/marc_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1c7e2fc5572a0f9362a771c260a1fe3" name="tests/marc_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="84f85ac7f8a2532e4e90ccde7764556a" name="tests/marc_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="889e5e906a97de7a0e94b0c5f30e70e7" name="tests/marc_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="be823dc8a8efb408de06371ab802efcc" name="tests/marc_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="af44490aafea44e5120f881cb81cdad9" name="tests/marc_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ac9f2a7aeb24900a11f5102744179ae3" name="tests/marc_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5e43eb5cddbb4f2bd0d6405cd95b80aa" name="tests/marc_010.phpt" role="test" />
   <file baseinstalldir="File" md5sum="2e1cd8509c0bf04ec77fc0f51375f611" name="tests/marc_011.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bc49ca48623102c8ac07679fa77a3dd9" name="tests/marc_012.phpt" role="test" />
   <file baseinstalldir="File" md5sum="245a3b20e0da1973535503e28efd1d3a" name="tests/marc_013.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ce69aa734856dd40d60d30c77bdef53a" name="tests/marc_014.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7b61cdd31035e60682fa92c5d519d997" name="tests/marc_015.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7f4f597fe1adaa3507eb87fc4875dbd2" name="tests/marc_016.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4262efd5fcacbd7503323681f4552430" name="tests/marc_017.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ee1623d7bda54ba4f741b2319b158f82" name="tests/marc_018.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8006c03fbab0f04377342086fafd3982" name="tests/marc_019.phpt" role="test" />
   <file baseinstalldir="File" md5sum="f5ae5b25e0ac1104314433d9e5b1f7fe" name="tests/marc_020.phpt" role="test" />
   <file baseinstalldir="File" md5sum="94d8f99e86585671a1b2d3043aeb6360" name="tests/marc_021.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bb891a890effe0e77e1759043f4846d8" name="tests/marc_022.phpt" role="test" />
   <file baseinstalldir="File" md5sum="faf77dcb5cdd002c09169a14bfded65e" name="tests/marc_023.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0e6c4a23f5da7df64fdd4b3b1149bbee" name="tests/marc_16783.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4ea8b3520beda378db15960f1c50493a" name="tests/marc_field_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="743850ef61df69c4340be44a03bccb5a" name="tests/marc_field_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8c765f1398b49df257d86d22ac6e4f8d" name="tests/marc_field_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d4216cf930a308e0d02553bd3914f294" name="tests/marc_field_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dd59514b474b78371ad522a3e13b76b7" name="tests/marc_field_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5295bfd02a8424acac1c91de26b552c7" name="tests/marc_field_21246.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6f95f09442ccf6b93df92986f58b270d" name="tests/marc_lint_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="18d721f8871edd925624ccbdd15444fb" name="tests/marc_lint_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4eb86a2f4e0a74dedcb0bf2511da6ca1" name="tests/marc_lint_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="10430fee0a1352d0528f1507b34c57e1" name="tests/marc_lint_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0dcd07a18577d7b22392a2214cd6436c" name="tests/marc_lint_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fd17798fc535562e5e64461f449516b2" name="tests/marc_record_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="141b455ccf67a60c4eac44c77960f2e2" name="tests/marc_subfield_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1e23464ee0eec47ddca2af9a9922926" name="tests/marc_subfield_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="1d7903e8c244d647220b318b4bc758d1" name="tests/marc_xml_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="22cae3c752d843b78f583dcd92801534" name="tests/marc_xml_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="c0716d23e0f960abf8d53ad6014a413a" name="tests/marc_xml_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7645fa19e28aca041a124fc5e2c12bd3" name="tests/marc_xml_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b08b28c3251625b8b6e4d7ab376b0185" name="tests/marc_xml_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6cd0934ddbf65d2d7e9ea5d108977ff7" name="tests/marc_xml_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ffdce4aa190268fa7cbbf3bb45383abf" name="tests/marc_xml_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="998a4c1ce00ff100f39ffa9fc49a212f" name="tests/marc_xml_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a38a67c590869f2b0a4859a910fd9e89" name="tests/marc_xml_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="db39c5055a570fcda12bb7c5fa1e3b4d" name="tests/marc_xml_16642.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dc075f4a271bd7182378a3874bd5b39e" name="tests/marc_xml_namespace.phpt" role="test" />
   <file baseinstalldir="File" md5sum="208200d9a979ac360c4d326e9789b6b7" name="tests/marc_xml_namespace_prefix.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d87774ede82222cfc12b2c2a06f57a3a" name="tests/marc_xml_rsinger.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fb44e3eb69f1a37115235fc829c39542" name="tests/namespace.xml" role="test" />
   <file baseinstalldir="File" md5sum="e6de4d809b0af5dd99fd352eb60616a1" name="tests/skipif.inc" role="test" />
   <file baseinstalldir="File" md5sum="a0166a4ff0bc0bb283e854f11beaa793" name="tests/music.mrc" role="test" />
   <file baseinstalldir="File" md5sum="993ce494befbc25dc1326527b30b4782" name="tests/music.xml" role="test" />
   <file baseinstalldir="File" md5sum="6b0c87f0cd459ed7322c25d403b164cc" name="tests/bigarchive.xml" role="test" />
   <file baseinstalldir="File" md5sum="be850aa6ab4ac52b8c6c214c30b574af" name="tests/onerecord.xml" role="test" />
   <file baseinstalldir="File" md5sum="4f43fec7b276267eec5258044853ccc8" name="tests/sandburg.mrc" role="test" />
   <file baseinstalldir="File" md5sum="e216b95f905dd240c9bde372950e4073" name="tests/sandburg.xml" role="test" />
   <file baseinstalldir="File" md5sum="e81a92188ea0dcd9c108a63fb32b3f4f" name="tests/xmlescape.mrc" role="test" />
   <file baseinstalldir="File" md5sum="8f9f63ed6a80191d89a2296fa4c1a30b" name="CHANGELOG" role="doc" />
   <file baseinstalldir="File" md5sum="fbc093901857fcd118f065f900982c24" name="LICENSE" role="doc" />
  </dir>
 </contents>
 <dependencies>
  <required>
   <php>
    <min>5.6</min>
   </php>
   <pearinstaller>
    <min>1.4.0</min>
   </pearinstaller>
  </required>
  <optional>
   <package>
    <name>Validate_ISPN</name>
    <channel>pear.php.net</channel>
   </package>
  </optional>
 </dependencies>
 <phprelease />
</package>
PKm�ZPi��.depdbnu�[���PKm�Z�{��
�Mail/null.phpnu�[���PKm�ZE@�%>>
Mail/sendmail.phpnu�[���PKm�Z��A~�{�{�;Mail/RFC822.phpnu�[���PKn�Z�+V����
[�Mail/mime.phpnu�[���PKn�Zx�ع���D�Mail/mimeDecode.phpnu�[���PKn�ZB�_Ǭ=�=
@(Mail/smtp.phpnu�[���PKn�ZwԐE;E;)fMail/smtpmx.phpnu�[���PKn�Z�؛�J�J���Mail/mimePart.phpnu�[���PKn�ZB��shh
8YMail/mock.phpnu�[���PKn�Z@iE�\\
�lMail/mail.phpnu�[���PKn�Zv�.locknu�[���PKn�Z�*�z%-%- ��Structures/LinkedList/Double.phpnu�[���PKn�Z����p:p:  �Structures/LinkedList/Single.phpnu�[���PKn�ZUyv���Structures/Graph.phpnu�[���PKn�Z�C� + +CStructures/Graph/Node.phpnu�[���PKn�Z9����,�1Structures/Graph/Manipulator/AcyclicTest.phpnu�[���PKn�Z~(�htt2�HStructures/Graph/Manipulator/TopologicalSorter.phpnu�[���PKPK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified PK��Z��7Tg�g�;.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUri   URI of the namespace
     * @param bool   $multiline      whether to create a multiline tag where each
     *                               attribute gets written to a single line
     * @param string $indent         string used to indent attributes (_auto indents
     *                               attributes so they start at the same column)
     * @param string $linebreak      string used for linebreaks
     * @param bool   $sortAttributes Whether to sort the attributes or not
     *
     * @return string XML start element
     * @see    createEndElement(), createTag()
     */
    public static function createStartElement(
        $qname, $attributes = array(), $namespaceUri = null,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true
    ) {
        // if no attributes hav been set, use empty attributes
        if (!isset($attributes) || !is_array($attributes)) {
            $attributes = array();
        }

        if ($namespaceUri != null) {
            $parts = XML_Util::splitQualifiedName($qname);
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($qname)+2));
            }
        }

        if ($namespaceUri != null) {
            // is a namespace given
            if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
            } else {
                // define this Uri as the default namespace
                $attributes['xmlns'] = $namespaceUri;
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $attributes, $sortAttributes,
            $multiline, $indent, $linebreak
        );
        $element = sprintf('<%s%s>', $qname, $attList);
        return  $element;
    }

    /**
     * Create an end element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createEndElement('myNs:myTag');
     * </code>
     *
     * @param string $qname qualified tagname (including namespace)
     *
     * @return string XML end element
     * @see    createStartElement(), createTag()
     */
    public static function createEndElement($qname)
    {
        $element = sprintf('</%s>', $qname);
        return $element;
    }

    /**
     * Create an XML comment
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createComment('I am a comment');
     * </code>
     *
     * @param string $content content of the comment
     *
     * @return string XML comment
     */
    public static function createComment($content)
    {
        $comment = sprintf('<!-- %s -->', $content);
        return $comment;
    }

    /**
     * Create a CData section
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create a CData section
     * $tag = XML_Util::createCDataSection('I am content.');
     * </code>
     *
     * @param string $data data of the CData section
     *
     * @return string CData section with content
     */
    public static function createCDataSection($data)
    {
        return sprintf(
            '<![CDATA[%s]]>',
            preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data))
        );
    }

    /**
     * Split qualified name and return namespace and local part
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // split qualified tag
     * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
     * </code>
     * the returned array will contain two elements:
     * <pre>
     * array(
     *     'namespace' => 'xslt',
     *     'localPart' => 'stylesheet'
     * );
     * </pre>
     *
     * @param string $qname     qualified tag name
     * @param string $defaultNs default namespace (optional)
     *
     * @return array array containing namespace and local part
     */
    public static function splitQualifiedName($qname, $defaultNs = null)
    {
        if (strstr($qname, ':')) {
            $tmp = explode(':', $qname);
            return array(
                'namespace' => $tmp[0],
                'localPart' => $tmp[1]
            );
        }
        return array(
            'namespace' => $defaultNs,
            'localPart' => $qname
        );
    }

    /**
     * Check, whether string is valid XML name
     *
     * <p>XML names are used for tagname, attribute names and various
     * other, lesser known entities.</p>
     * <p>An XML name may only consist of alphanumeric characters,
     * dashes, undescores and periods, and has to start with a letter
     * or an underscore.</p>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // verify tag name
     * $result = XML_Util::isValidName('invalidTag?');
     * if (is_a($result, 'PEAR_Error')) {
     *    print 'Invalid XML name: ' . $result->getMessage();
     * }
     * </code>
     *
     * @param string $string string that should be checked
     *
     * @return mixed true, if string is a valid XML name, PEAR error otherwise
     *
     * @todo support for other charsets
     * @todo PEAR CS - unable to avoid 85-char limit on second preg_match
     */
    public static function isValidName($string)
    {
        // check for invalid chars
        if (!is_string($string) || !strlen($string) || !preg_match('/^[[:alpha:]_]\\z/', $string[0])) {
            return XML_Util::raiseError(
                'XML names may only start with letter or underscore',
                XML_UTIL_ERROR_INVALID_START
            );
        }

        // check for invalid chars
        $match = preg_match(
            '/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?'
            . '[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/',
            $string
        );
        if (!$match) {
            return XML_Util::raiseError(
                'XML names may only contain alphanumeric '
                . 'chars, period, hyphen, colon and underscores',
                XML_UTIL_ERROR_INVALID_CHARS
            );
        }
        // XML name is valid
        return true;
    }

    /**
     * Replacement for XML_Util::raiseError
     *
     * Avoids the necessity to always require
     * PEAR.php
     *
     * @param string $msg  error message
     * @param int    $code error code
     *
     * @return PEAR_Error
     * @todo   PEAR CS - should this use include_once instead?
     */
    public static function raiseError($msg, $code)
    {
        include_once 'PEAR.php';
        return PEAR::raiseError($msg, $code);
    }
}
?>
PK��Z#F��:�:pearcmd.phpnu�[���<?php
/**
 * PEAR, the PHP Extension and Application Repository
 *
 * Command line interface
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Stig Bakken <ssb@php.net>
 * @author    Tomas V.V.Cox <cox@idecnet.com>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 */

@ob_end_clean();
if (!defined('PEAR_RUNTYPE')) {
    // this is defined in peclcmd.php as 'pecl'
    define('PEAR_RUNTYPE', 'pear');
}
define('PEAR_IGNORE_BACKTRACE', 1);
/**
 * @nodep Gtk
 */
//the space is needed for windows include paths with trailing backslash
// http://pear.php.net/bugs/bug.php?id=19482
if ('/opt/alt/php74/usr/share/pear ' != '@'.'include_path'.'@ ') {
    ini_set('include_path', trim('/opt/alt/php74/usr/share/pear '). PATH_SEPARATOR .  get_include_path());
    $raw = false;
} else {
    // this is a raw, uninstalled pear, either a cvs checkout, or php distro
    ini_set('include_path', dirname(__DIR__) . PATH_SEPARATOR . get_include_path());
    $raw = true;
}
@ini_set('allow_url_fopen', true);
@set_time_limit(0);
ob_implicit_flush(true);
@ini_set('track_errors', true);
@ini_set('html_errors', false);
$_PEAR_PHPDIR = '#$%^&*';
set_error_handler('error_handler');

$pear_package_version = "1.10.16";

require_once 'PEAR.php';
require_once 'PEAR/Frontend.php';
require_once 'PEAR/Config.php';
require_once 'PEAR/Command.php';
require_once 'Console/Getopt.php';


PEAR_Command::setFrontendType('CLI');
$all_commands = PEAR_Command::getCommands();

$argv = Console_Getopt::readPHPArgv();
// fix CGI sapi oddity - the -- in pear.bat/pear is not removed
if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
    unset($argv[1]);
    $argv = array_values($argv);
}
$progname = PEAR_RUNTYPE;
array_shift($argv);
$options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV");
if (PEAR::isError($options)) {
    usage($options);
}

$opts = $options[0];

$fetype = 'CLI';
if ($progname == 'gpear' || $progname == 'pear-gtk') {
    $fetype = 'Gtk2';
} else {
    foreach ($opts as $opt) {
        if ($opt[0] == 'G') {
            $fetype = 'Gtk2';
        }
    }
}

$pear_user_config = '';
$pear_system_config = '';
$store_user_config = false;
$store_system_config = false;
$verbose = 1;

foreach ($opts as $opt) {
    switch ($opt[0]) {
    case 'c':
        $pear_user_config = $opt[1];
        break;
    case 'C':
        $pear_system_config = $opt[1];
        break;
    }
}

PEAR_Command::setFrontendType($fetype);
$ui = &PEAR_Command::getFrontendObject();
$config = &PEAR_Config::singleton($pear_user_config, $pear_system_config);

if (PEAR::isError($config)) {
    $_file = '';
    if ($pear_user_config !== false) {
        $_file .= $pear_user_config;
    }
    if ($pear_system_config !== false) {
        $_file .= '/' . $pear_system_config;
    }
    if ($_file == '/') {
        $_file = 'The default config file';
    }
    $config->getMessage();
    $ui->outputData("ERROR: $_file is not a valid config file or is corrupted.");
    // We stop, we have no idea where we are :)
    exit(1);
}

// this is used in the error handler to retrieve a relative path
$_PEAR_PHPDIR = $config->get('php_dir');
$ui->setConfig($config);
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError"));

$verbose = $config->get("verbose");
$cmdopts = array();

if ($raw) {
    if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) {
        $found = false;
        foreach ($opts as $opt) {
            if ($opt[0] == 'd' || $opt[0] == 'D') {
                // the user knows what they are doing, and are setting config values
                $found = true;
            }
        }
        if (!$found) {
            // no prior runs, try to install PEAR
            $parent = dirname(__FILE__);
            if (strpos($parent, 'scripts')) {
                $grandparent = dirname($parent);
                $packagexml = $grandparent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $grandparent;
            } else {
                $packagexml = $parent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $parent;
            }
            if (file_exists($packagexml)) {
                $options[1] = array(
                    'install',
                    $packagexml
                );
                $config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php');
                $config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data');
                $config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs');
                $config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests');
                $config->set(
                    'ext_dir',
                    $pearbase . DIRECTORY_SEPARATOR . 'extensions'
                );
                $config->set('bin_dir', $pearbase);
                $config->mergeConfigFile($pearbase . 'pear.ini', false);
                $config->store();
                $config->set('auto_discover', 1);
            }
        }
    }
}
foreach ($opts as $opt) {
    $param = !empty($opt[1]) ? $opt[1] : true;
    switch ($opt[0]) {
    case 'd':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected -d config_value=value, ' .
                'received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'user');
        break;
    case 'D':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'system');
        break;
    case 's':
        $store_user_config = true;
        break;
    case 'S':
        $store_system_config = true;
        break;
    case 'u':
        $config->remove($param, 'user');
        break;
    case 'v':
        $config->set('verbose', $config->get('verbose') + 1);
        break;
    case 'q':
        $config->set('verbose', $config->get('verbose') - 1);
        break;
    case 'V':
        usage(null, 'version');
    case 'c':
    case 'C':
        break;
    default:
        // all non pear params goes to the command
        $cmdopts[$opt[0]] = $param;
        break;
    }
}

if ($store_system_config) {
    $config->store('system');
}

if ($store_user_config) {
    $config->store('user');
}

$command = (isset($options[1][0])) ? $options[1][0] : null;
if (empty($command) && ($store_user_config || $store_system_config)) {
    exit;
}

if ($fetype == 'Gtk2') {
    if (!$config->validConfiguration()) {
        PEAR::raiseError(
            "CRITICAL ERROR: no existing valid configuration files found in " .
            "files '$pear_user_config' or '$pear_system_config', " .
            "please copy an existing configuration file to one of these " .
            "locations, or use the -c and -s options to create one"
        );
    }
    Gtk::main();
} else {
    do {
        if ($command == 'help') {
            usage(null, isset($options[1][1]) ? $options[1][1] : null);
        }

        if (!$config->validConfiguration()) {
            PEAR::raiseError(
                "CRITICAL ERROR: no existing valid configuration files found " .
                "in files '$pear_user_config' or '$pear_system_config', " .
                "please copy an existing configuration file to one of " .
                "these locations, or use the -c and -s options to create one"
            );
        }

        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        $cmd = PEAR_Command::factory($command, $config);
        PEAR::popErrorHandling();
        if (PEAR::isError($cmd)) {
            usage(null, isset($options[1][0]) ? $options[1][0] : null);
        }

        $short_args = $long_args = null;
        PEAR_Command::getGetoptArgs($command, $short_args, $long_args);
        array_shift($options[1]);
        $tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args);

        if (PEAR::isError($tmp)) {
            break;
        }

        list($tmpopt, $params) = $tmp;
        $opts = array();
        foreach ($tmpopt as $foo => $tmp2) {
            list($opt, $value) = $tmp2;
            if ($value === null) {
                $value = true; // options without args
            }

            if (strlen($opt) == 1) {
                $cmdoptions = $cmd->getOptions($command);
                foreach ($cmdoptions as $o => $d) {
                    if (isset($d['shortopt']) && $d['shortopt'] == $opt) {
                        $opts[$o] = $value;
                    }
                }
            } else {
                if (substr($opt, 0, 2) == '--') {
                    $opts[substr($opt, 2)] = $value;
                }
            }
        }

        $ok = $cmd->run($command, $opts, $params);
        if ($ok === false) {
            PEAR::raiseError("unknown command `$command'");
        }

        if (PEAR::isError($ok)) {
            PEAR::setErrorHandling(
                PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")
            );
            PEAR::raiseError($ok);
        }
    } while (false);
}

// {{{ usage()

/**
 * Display usage information
 *
 * @param mixed $error       Optional error message
 * @param mixed $helpsubject Optional subject/command to display help for
 *
 * @return void
 */
function usage($error = null, $helpsubject = null)
{
    global $progname, $all_commands;
    $stdout = fopen('php://stdout', 'w');
    if (PEAR::isError($error)) {
        fputs($stdout, $error->getMessage() . "\n");
    } elseif ($error !== null) {
        fputs($stdout, "$error\n");
    }

    if ($helpsubject != null) {
        $put = cmdHelp($helpsubject);
    } else {
        $put = "Commands:\n";
        $maxlen = max(array_map("strlen", $all_commands));
        $formatstr = "%-{$maxlen}s  %s\n";
        ksort($all_commands);
        foreach ($all_commands as $cmd => $class) {
            $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd));
        }
        $put .=
            "Usage: $progname [options] command [command-options] <parameters>\n".
            "Type \"$progname help options\" to list all options.\n".
            "Type \"$progname help shortcuts\" to list all command shortcuts.\n".
            "Type \"$progname help version\" or ".
            "\"$progname version\" to list version information.\n".
            "Type \"$progname help <command>\" to get the help ".
            "for the specified command.";
    }
    fputs($stdout, "$put\n");
    fclose($stdout);

    if ($error === null) {
        exit(0);
    }
    exit(1);
}

/**
 * Return help string for specified command
 *
 * @param string $command Command to return help for
 *
 * @return void
 */
function cmdHelp($command)
{
    global $progname, $all_commands, $config;
    if ($command == "options") {
        return
        "Options:\n".
        "     -v         increase verbosity level (default 1)\n".
        "     -q         be quiet, decrease verbosity level\n".
        "     -c file    find user configuration in `file'\n".
        "     -C file    find system configuration in `file'\n".
        "     -d foo=bar set user config variable `foo' to `bar'\n".
        "     -D foo=bar set system config variable `foo' to `bar'\n".
        "     -G         start in graphical (Gtk) mode\n".
        "     -s         store user configuration\n".
        "     -S         store system configuration\n".
        "     -u foo     unset `foo' in the user configuration\n".
        "     -h, -?     display help/usage (this message)\n".
        "     -V         version information\n";
    } elseif ($command == "shortcuts") {
        $sc = PEAR_Command::getShortcuts();
        $ret = "Shortcuts:\n";
        foreach ($sc as $s => $c) {
            $ret .= sprintf("     %-8s %s\n", $s, $c);
        }
        return $ret;

    } elseif ($command == "version") {
        return "PEAR Version: ".$GLOBALS['pear_package_version'].
               "\nPHP Version: ".phpversion().
               "\nZend Engine Version: ".zend_version().
               "\nRunning on: ".php_uname();

    } elseif ($help = PEAR_Command::getHelp($command)) {
        if (is_string($help)) {
            return "$progname $command [options] $help\n";
        }

        if ($help[1] === null) {
            return "$progname $command $help[0]";
        }

        return "$progname $command [options] $help[0]\n$help[1]";
    }

    return "Command '$command' is not valid, try '$progname help'";
}

// }}}

/**
 * error_handler
 *
 * @param mixed $errno  Error number
 * @param mixed $errmsg Message
 * @param mixed $file   Filename
 * @param mixed $line   Line number
 *
 * @access public
 * @return boolean
 */
function error_handler($errno, $errmsg, $file, $line)
{
    if ((!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) && ($errno & E_STRICT)) {
        return; // E_STRICT
    }
    if ($errno & E_DEPRECATED) {
        return; // E_DEPRECATED
    }
    if (!(error_reporting() & $errno) &&
        isset($GLOBALS['config']) &&
        $GLOBALS['config']->get('verbose') < 4
    ) {
        return false; // @silenced error, show all if debug is high enough
    }
    $errortype = array (
        E_DEPRECATED  => 'Deprecated Warning',
        E_ERROR   =>  "Error",
        E_WARNING   =>  "Warning",
        E_PARSE   =>  "Parsing Error",
        E_NOTICE   =>  "Notice",
        E_CORE_ERROR  =>  "Core Error",
        E_CORE_WARNING  =>  "Core Warning",
        E_COMPILE_ERROR  =>  "Compile Error",
        E_COMPILE_WARNING =>  "Compile Warning",
        E_USER_ERROR =>  "User Error",
        E_USER_WARNING =>  "User Warning",
        E_USER_NOTICE =>  "User Notice"
    );
    if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) {
        $errortype[E_STRICT] = 'Strict Warning';
    }
    $prefix = $errortype[$errno];
    global $_PEAR_PHPDIR;
    if (stristr($file, $_PEAR_PHPDIR)) {
        $file = substr($file, strlen($_PEAR_PHPDIR) + 1);
    } else {
        $file = basename($file);
    }
    print "\n$prefix: $errmsg in $file on line $line\n";
    return false;
}


/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * indent-tabs-mode: nil
 * mode: php
 * End:
 */
// vim600:syn=php
PK��Z�0$�-- .pkgxml/Pear_File_MARC-1.4.1.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.10.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
 <name>File_MARC</name>
 <channel>pear.php.net</channel>
 <summary>Parse, modify, and create MARC records</summary>
 <description>The standard for machine-readable cataloging (MARC) records is documented at http://loc.gov/marc/. This package enables you to read existing MARC records from a file, string, or (using the YAZ extension), from a Z39.50 source. You can also use this package to create new MARC records.

This package is based on the PHP MARC package, originally called &quot;php-marc&quot;, that is part of the Emilda Project (http://www.emilda.org).  Christoffer Landtman generously agreed to make the &quot;php-marc&quot; code available under the GNU LGPL so it could be used as the basis of this PEAR package.</description>
 <lead>
  <name>Dan Scott</name>
  <user>dbs</user>
  <email>dbs@php.net</email>
  <active>yes</active>
 </lead>
 <date>2019-11-13</date>
 <time>17:33:33</time>
 <version>
  <release>1.4.1</release>
  <api>1.4.0</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license uri="http://www.gnu.org/copyleft/lesser.html">GNU Lesser General Public License</license>
 <notes>
1.4.1
  * Reintroduce include_path to composer.json
 </notes>
 <contents>
  <dir baseinstalldir="File" name="/">
   <file baseinstalldir="/" md5sum="ffe2590635f404af055fe731da105939" name="File/MARC/Lint/CodeData.php" role="php" />
   <file baseinstalldir="/" md5sum="a3b9e1c817e67f59add05593500d463e" name="File/MARC/Control_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="acba4463f8e40d6ee4e7ba1f2dc53123" name="File/MARC/Data_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="378f483ec1fd161cd9dfb9b05db58d66" name="File/MARC/Exception.php" role="php" />
   <file baseinstalldir="/" md5sum="a9ba69030cbf4847292b9975e9d922c6" name="File/MARC/Field.php" role="php" />
   <file baseinstalldir="/" md5sum="c37351c7c80927ce6bb1e662510f9183" name="File/MARC/Lint.php" role="php" />
   <file baseinstalldir="/" md5sum="c5ac39e3d25eb0108b9dd5ad8466c821" name="File/MARC/List.php" role="php" />
   <file baseinstalldir="/" md5sum="7af6ce78cde4bb246e4e96709e90d2c0" name="File/MARC/Record.php" role="php" />
   <file baseinstalldir="/" md5sum="df5f97139685f0ad04e47fdbb67e3968" name="File/MARC/Subfield.php" role="php" />
   <file baseinstalldir="/" md5sum="6e102262dfd5d65d8d5a6221dfc74edd" name="File/MARC.php" role="php" />
   <file baseinstalldir="/" md5sum="8b64040d2d18ac4b994595a148266a66" name="File/MARCBASE.php" role="php" />
   <file baseinstalldir="/" md5sum="f5a17a60d34e84e2ee7ca1e5c5c6c620" name="File/MARCXML.php" role="php" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="examples/example.mrc" role="doc" />
   <file baseinstalldir="File" md5sum="1aea40df9f1c2e32f8e065fe8da0a3b5" name="examples/marc_yaz.php" role="doc" />
   <file baseinstalldir="File" md5sum="70ae317e0890d5896e3ffccdd293369a" name="examples/read.php" role="doc" />
   <file baseinstalldir="File" md5sum="54efb9d920ac775bfc847a83a2dec73a" name="examples/subfields.php" role="doc" />
   <file baseinstalldir="File" md5sum="14297da35b510c496cd1f328cf3bb301" name="tests/bad_example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="0dd4c6dbad6e8608d0ebf9d24425955d" name="tests/bad_example.xml" role="test" />
   <file baseinstalldir="File" md5sum="216a6f9d53f6d3d8e22d81fdc10f4bc1" name="tests/camel.mrc" role="test" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="tests/example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="9455aec3371f79cf7d31281fd03f5171" name="tests/marc_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="577e2f5f89fd48cf1a3576a29d2958f8" name="tests/marc_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a6a586354b9a06c880c2a7470dd828d7" name="tests/marc_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1c7e2fc5572a0f9362a771c260a1fe3" name="tests/marc_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="84f85ac7f8a2532e4e90ccde7764556a" name="tests/marc_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="889e5e906a97de7a0e94b0c5f30e70e7" name="tests/marc_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="be823dc8a8efb408de06371ab802efcc" name="tests/marc_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="af44490aafea44e5120f881cb81cdad9" name="tests/marc_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ac9f2a7aeb24900a11f5102744179ae3" name="tests/marc_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5e43eb5cddbb4f2bd0d6405cd95b80aa" name="tests/marc_010.phpt" role="test" />
   <file baseinstalldir="File" md5sum="2e1cd8509c0bf04ec77fc0f51375f611" name="tests/marc_011.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bc49ca48623102c8ac07679fa77a3dd9" name="tests/marc_012.phpt" role="test" />
   <file baseinstalldir="File" md5sum="245a3b20e0da1973535503e28efd1d3a" name="tests/marc_013.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ce69aa734856dd40d60d30c77bdef53a" name="tests/marc_014.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7b61cdd31035e60682fa92c5d519d997" name="tests/marc_015.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7f4f597fe1adaa3507eb87fc4875dbd2" name="tests/marc_016.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4262efd5fcacbd7503323681f4552430" name="tests/marc_017.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ee1623d7bda54ba4f741b2319b158f82" name="tests/marc_018.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8006c03fbab0f04377342086fafd3982" name="tests/marc_019.phpt" role="test" />
   <file baseinstalldir="File" md5sum="f5ae5b25e0ac1104314433d9e5b1f7fe" name="tests/marc_020.phpt" role="test" />
   <file baseinstalldir="File" md5sum="94d8f99e86585671a1b2d3043aeb6360" name="tests/marc_021.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bb891a890effe0e77e1759043f4846d8" name="tests/marc_022.phpt" role="test" />
   <file baseinstalldir="File" md5sum="faf77dcb5cdd002c09169a14bfded65e" name="tests/marc_023.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0e6c4a23f5da7df64fdd4b3b1149bbee" name="tests/marc_16783.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4ea8b3520beda378db15960f1c50493a" name="tests/marc_field_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="743850ef61df69c4340be44a03bccb5a" name="tests/marc_field_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8c765f1398b49df257d86d22ac6e4f8d" name="tests/marc_field_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d4216cf930a308e0d02553bd3914f294" name="tests/marc_field_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dd59514b474b78371ad522a3e13b76b7" name="tests/marc_field_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5295bfd02a8424acac1c91de26b552c7" name="tests/marc_field_21246.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6f95f09442ccf6b93df92986f58b270d" name="tests/marc_lint_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="18d721f8871edd925624ccbdd15444fb" name="tests/marc_lint_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4eb86a2f4e0a74dedcb0bf2511da6ca1" name="tests/marc_lint_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="10430fee0a1352d0528f1507b34c57e1" name="tests/marc_lint_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0dcd07a18577d7b22392a2214cd6436c" name="tests/marc_lint_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fd17798fc535562e5e64461f449516b2" name="tests/marc_record_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="141b455ccf67a60c4eac44c77960f2e2" name="tests/marc_subfield_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1e23464ee0eec47ddca2af9a9922926" name="tests/marc_subfield_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="1d7903e8c244d647220b318b4bc758d1" name="tests/marc_xml_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="22cae3c752d843b78f583dcd92801534" name="tests/marc_xml_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="c0716d23e0f960abf8d53ad6014a413a" name="tests/marc_xml_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7645fa19e28aca041a124fc5e2c12bd3" name="tests/marc_xml_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b08b28c3251625b8b6e4d7ab376b0185" name="tests/marc_xml_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6cd0934ddbf65d2d7e9ea5d108977ff7" name="tests/marc_xml_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ffdce4aa190268fa7cbbf3bb45383abf" name="tests/marc_xml_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="998a4c1ce00ff100f39ffa9fc49a212f" name="tests/marc_xml_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a38a67c590869f2b0a4859a910fd9e89" name="tests/marc_xml_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="db39c5055a570fcda12bb7c5fa1e3b4d" name="tests/marc_xml_16642.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dc075f4a271bd7182378a3874bd5b39e" name="tests/marc_xml_namespace.phpt" role="test" />
   <file baseinstalldir="File" md5sum="208200d9a979ac360c4d326e9789b6b7" name="tests/marc_xml_namespace_prefix.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d87774ede82222cfc12b2c2a06f57a3a" name="tests/marc_xml_rsinger.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fb44e3eb69f1a37115235fc829c39542" name="tests/namespace.xml" role="test" />
   <file baseinstalldir="File" md5sum="e6de4d809b0af5dd99fd352eb60616a1" name="tests/skipif.inc" role="test" />
   <file baseinstalldir="File" md5sum="a0166a4ff0bc0bb283e854f11beaa793" name="tests/music.mrc" role="test" />
   <file baseinstalldir="File" md5sum="993ce494befbc25dc1326527b30b4782" name="tests/music.xml" role="test" />
   <file baseinstalldir="File" md5sum="6b0c87f0cd459ed7322c25d403b164cc" name="tests/bigarchive.xml" role="test" />
   <file baseinstalldir="File" md5sum="be850aa6ab4ac52b8c6c214c30b574af" name="tests/onerecord.xml" role="test" />
   <file baseinstalldir="File" md5sum="4f43fec7b276267eec5258044853ccc8" name="tests/sandburg.mrc" role="test" />
   <file baseinstalldir="File" md5sum="e216b95f905dd240c9bde372950e4073" name="tests/sandburg.xml" role="test" />
   <file baseinstalldir="File" md5sum="e81a92188ea0dcd9c108a63fb32b3f4f" name="tests/xmlescape.mrc" role="test" />
   <file baseinstalldir="File" md5sum="8f9f63ed6a80191d89a2296fa4c1a30b" name="CHANGELOG" role="doc" />
   <file baseinstalldir="File" md5sum="fbc093901857fcd118f065f900982c24" name="LICENSE" role="doc" />
  </dir>
 </contents>
 <dependencies>
  <required>
   <php>
    <min>5.6</min>
   </php>
   <pearinstaller>
    <min>1.4.0</min>
   </pearinstaller>
  </required>
  <optional>
   <package>
    <name>Validate_ISPN</name>
    <channel>pear.php.net</channel>
   </package>
  </optional>
 </dependencies>
 <phprelease />
</package>
PKm�ZPi��.depdbnu�[���PKm�Z�{��
�Mail/null.phpnu�[���PKm�ZE@�%>>
Mail/sendmail.phpnu�[���PKm�Z��A~�{�{�;Mail/RFC822.phpnu�[���PKn�Z�+V����
[�Mail/mime.phpnu�[���PKn�Zx�ع���D�Mail/mimeDecode.phpnu�[���PKn�ZB�_Ǭ=�=
@(Mail/smtp.phpnu�[���PKn�ZwԐE;E;)fMail/smtpmx.phpnu�[���PKn�Z�؛�J�J���Mail/mimePart.phpnu�[���PKn�ZB��shh
8YMail/mock.phpnu�[���PKn�Z@iE�\\
�lMail/mail.phpnu�[���PKn�Zv�.locknu�[���PKn�Z�*�z%-%- ��Structures/LinkedList/Double.phpnu�[���PKn�Z����p:p:  �Structures/LinkedList/Single.phpnu�[���PKn�ZUyv���Structures/Graph.phpnu�[���PKn�Z�C� + +CStructures/Graph/Node.phpnu�[���PKn�Z9����,�1Structures/Graph/Manipulator/AcyclicTest.phpnu�[���PKn�Z~(�htt2�HStructures/Graph/Manipulator/TopologicalSorter.phpnu�[���PKn�Z�J�}
}
_dAuth/SASL/Anonymous.phpnu�[���PKn�ZP(~�T
T
#rAuth/SASL/CramMD5.phpnu�[���PKn�Z����==�Auth/SASL/Plain.phpnu�[���PKn�Z�<� OO<�Auth/SASL/Login.phpnu�[���PKn�Z%ׅtg!g!ΘAuth/SASL/DigestMD5.phpnu�[���PKn�Z�T�|�Auth/SASL/Common.phpnu�[���PKn�ZvR�r,,��Auth/SASL/External.phpnu�[���PKn�Zќ��0�0H�Auth/SASL/SCRAM.phpnu�[���PKn�Z2r����
�	Auth/SASL.phpnu�[���PKn�Z�T�,�,�OS/Guess.phpnu�[���PKn�Z�����KPEAR/Config.phpnu�[���PKn�Z�`�eEAEA
.ZPEAR/REST.phpnu�[���PKn�Z��ym6m6��PEAR/Exception.phpnu�[���PKn�Zr"����_�PEAR/ChannelFile.phpnu�[���PKn�Z��gk�U�U?�PEAR/Validate.phpnu�[���PKn�Zd֣S��u�PEAR/Command/Pickle.xmlnu�[���PKn�Z�z��k<k<W�PEAR/Command/Config.phpnu�[���PKn�Z݄<ii	1PEAR/Command/Mirror.xmlnu�[���PKn�Z,��t"u"u�3PEAR/Command/Remote.phpnu�[���PKn�Z
�\���"�PEAR/Command/Remote.xmlnu�[���PKn�Zj���!�!X�PEAR/Command/Install.xmlnu�[���PKo�Z�%q������PEAR/Command/Channels.phpnu�[���PKo�Znmi?;�;��[	PEAR/Command/Install.phpnu�[���PKo�Z�X�

#
PEAR/Command/Auth.phpnu�[���PKo�Z���s6
6
T-
PEAR/Command/Config.xmlnu�[���PKo�Z�%Fii�:
PEAR/Command/Test.xmlnu�[���PKo�ZZ h66A
PEAR/Command/Package.xmlnu�[���PKo�Z�w��zz�]
PEAR/Command/Channels.xmlnu�[���PKo�Z+9ҜҜ�n
PEAR/Command/Package.phpnu�[���PKo�Z
u����PEAR/Command/Build.xmlnu�[���PKo�Z������
PEAR/Command/Mirror.phpnu�[���PKp�Z,_�h/h/�PEAR/Command/Test.phpnu�[���PKp�Z�%sp  6OPEAR/Command/Common.phpnu�[���PKp�Z0(;rʹʹ�oPEAR/Command/Registry.phpnu�[���PKp�Z�4�{���$PEAR/Command/Auth.xmlnu�[���PKp�Z��#S
S
�)PEAR/Command/Build.phpnu�[���PKp�Z���u��S4PEAR/Command/Registry.xmlnu�[���PKp�Z�P>>�;PEAR/Command/Pickle.phpnu�[���PKp�Z��T�I�I�yPEAR/Builder.phpnu�[���PKp�Z[
�W��3�PEAR/XMLParser.phpnu�[���PKp�Zl(e���t�PEAR/Downloader.phpnu�[���PKp�Z�b������
PEAR/ErrorStack.phpnu�[���PKp�Z(Pz����ePEAR/Proxy.phpnu�[���PKp�Z��'����|PEAR/RunTest.phpnu�[���PKq�Zj�y99�	PEAR/Validator/PECL.phpnu�[���PKq�Zp�����aPEAR/Dependency2.phpnu�[���PKq�Z��wv@@��PEAR/PackageFile/v2.phpnu�[���PKq�ZC�8�L�L!:�PEAR/PackageFile/v2/Validator.phpnu�[���PKq�Z���=_�_�6PEAR/PackageFile/v2/rw.phpnu�[���PKq�Z�5�������,PEAR/PackageFile/v1.phpnu�[���PKq�Z�ɁɁ!��PEAR/PackageFile/Generator/v2.phpnu�[���PKq�Z`�=����!�tPEAR/PackageFile/Generator/v1.phpnu�[���PKr�Z��OWHH�9PEAR/PackageFile/Parser/v2.phpnu�[���PKr�Z�_=�@�@`FPEAR/PackageFile/Parser/v1.phpnu�[���PKr�Zc��__5�PEAR/DependencyDB.phpnu�[���PKr�Z�@P��{�PEAR/ChannelFile/Parser.phpnu�[���PKr�Z��_�0�0r�PEAR/Command.phpnu�[���PKr�Z�ٲ�=�==PEAR/PackageFile.phpnu�[���PKr�Z�JD��g\PEAR/Task/Replace.phpnu�[���PKr�Z&%75))�wPEAR/Task/Windowseol/rw.phpnu�[���PKr�Z�3}}PEAR/Task/Replace/rw.phpnu�[���PKr�Z&
i."x�PEAR/Task/Postinstallscript/rw.phpnu�[���PKr�Z�-!�PEAR/Task/Common.phpnu�[���PKr�ZD$���I�PEAR/Task/Windowseol.phpnu�[���PKr�ZZ�E�x9x9��PEAR/Task/Postinstallscript.phpnu�[���PKr�Z\k��K�PEAR/Task/Unixeol/rw.phpnu�[���PKr�Z�������PEAR/Task/Unixeol.phpnu�[���PKr�Z�W�f���PEAR/REST/10.phpnu�[���PKr�Z��Y�;;ąPEAR/REST/13.phpnu�[���PKr�Z,#y��+�+�PEAR/REST/11.phpnu�[���PKr�Z��U  D�PEAR/Packager.phpnu�[���PKr�ZZ�bgbg�PEAR/Common.phpnu�[���PKr�Z$���(�(FsPEAR/Registry.phpnu�[���PKr�Z��	MdMd?�PEAR/Frontend/CLI.phpnu�[���PKr�Z��

�PEAR/Installer/Role/Doc.phpnu�[���PKr�Z��/��)PEAR/Installer/Role/Cfg.xmlnu�[���PKr�Z>1H���PEAR/Installer/Role/Www.xmlnu�[���PKr�Z�?m

PEAR/Installer/Role/Php.phpnu�[���PKr�Z*Y|	%%`PEAR/Installer/Role/Man.phpnu�[���PKr�Z���BB�PEAR/Installer/Role/Ext.xmlnu�[���PKr�Zp��""]PEAR/Installer/Role/Src.xmlnu�[���PKr�Zh&P*���PEAR/Installer/Role/Doc.xmlnu�[���PKr�ZB] ���PEAR/Installer/Role/Test.xmlnu�[���PKr�Zz�q����PEAR/Installer/Role/Php.xmlnu�[���PKr�Z	��
|PEAR/Installer/Role/Data.phpnu�[���PKs�Z�0�c���PEAR/Installer/Role/Man.xmlnu�[���PKs�Z��K

�PEAR/Installer/Role/Ext.phpnu�[���PKs�ZY��� PEAR/Installer/Role/Test.phpnu�[���PKs�Z@v�а�z#PEAR/Installer/Role/Script.xmlnu�[���PKs�Zf�sz��x%PEAR/Installer/Role/Data.xmlnu�[���PKs�Z?���GGV'PEAR/Installer/Role/Common.phpnu�[���PKs�Z�^D{		�?PEAR/Installer/Role/Www.phpnu�[���PKs�Z�Ƥ?CPEAR/Installer/Role/Cfg.phpnu�[���PKs�Z��[�	SPEAR/Installer/Role/Script.phpnu�[���PKs�Z��srrjVPEAR/Installer/Role/Src.phpnu�[���PKs�ZV�Z���'ZPEAR/Installer/Role.phpnu�[���PKs�Z�{�	�)�)*yPEAR/Downloader/Package.phpnu�[���PKs�Z.�4���$�PEAR/Frontend.phpnu�[���PKs�Z،�w��_�PEAR/Installer.phpnu�[���PKs�ZXxo��-j�Symfony/Bridge/Doctrine/Logger/DbalLogger.phpnu�[���PKs�Ze�OO&b�Symfony/Bridge/Doctrine/autoloader.phpnu�[���PKs�Z��X+��8�Symfony/Bridge/Doctrine/CacheWarmer/ProxyCacheWarmer.phpnu�[���PKs�Z	�9,��5i�Symfony/Bridge/Doctrine/Form/DoctrineOrmExtension.phpnu�[���PKs�Z�0���NX�Symfony/Bridge/Doctrine/Form/EventListener/MergeDoctrineCollectionListener.phpnu�[���PKs�Z!%d==A��Symfony/Bridge/Doctrine/Form/ChoiceList/EntityLoaderInterface.phpnu�[���PKs�Z�	?x�7�7<4�Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.phpnu�[���PKs�ZGC�t��A<-Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.phpnu�[���PKs�Z`.
qpp7�9Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.phpnu�[���PKs�ZCi�PPMZQSymfony/Bridge/Doctrine/Form/DataTransformer/CollectionToArrayTransformer.phpnu�[���PKs�Z憝��0'YSymfony/Bridge/Doctrine/Form/Type/EntityType.phpnu�[���PKs�ZS;,:��2-]Symfony/Bridge/Doctrine/Form/Type/DoctrineType.phpnu�[���PKs�ZW&v��<�wSymfony/Bridge/Doctrine/Security/User/EntityUserProvider.phpnu�[���PKs�Z�����Et�Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.phpnu�[���PKs�Z(��y��9�Symfony/Bridge/Doctrine/Validator/DoctrineInitializer.phpnu�[���PKs�ZQГ��>�Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.phpnu�[���PKs�Z:�d�G5�Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.phpnu�[���PKs�Z�Ta�==B��Symfony/Bridge/Doctrine/ExpressionLanguage/DoctrineParserCache.phpnu�[���PKs�Z��qm
m
-m�Symfony/Bridge/Doctrine/RegistryInterface.phpnu�[���PKs�Zlf/�qq=7�Symfony/Bridge/Doctrine/DataFixtures/ContainerAwareLoader.phpnu�[���PKs�Z����=�Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.phpnu�[���PKs�Z�����C��Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerSchema.phpnu�[���PKs�ZOlQ�996��Symfony/Bridge/Doctrine/ContainerAwareEventManager.phpnu�[���PKs�Z؈����3D�Symfony/Bridge/Doctrine/Test/DoctrineTestHelper.phpnu�[���PKs�Z̳֨�+��Symfony/Bridge/Doctrine/ManagerRegistry.phpnu�[���PKs�Z+çxAA?�Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.phpnu�[���PKs�Z*�+��J�JIBSymfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.phpnu�[���PKs�Z���*��SVaSymfony/Bridge/Doctrine/DependencyInjection/Security/UserProvider/EntityFactory.phpnu�[���PKs�Z��㛕�Q�hSymfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterMappingsPass.phpnu�[���PKs�Z~�YAAeԀSymfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.phpnu�[���PKs�Z��,���S��Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/DoctrineValidationPass.phpnu�[���PKs�Z��4NN%,�Symfony/Bridge/Monolog/autoloader.phpnu�[���PKs�Z��մ��1ϡSymfony/Bridge/Monolog/Handler/FirePHPHandler.phpnu�[���PKs�Z��Zv��/©Symfony/Bridge/Monolog/Handler/DebugHandler.phpnu�[���PKs�Z�y���1دSymfony/Bridge/Monolog/Handler/ConsoleHandler.phpnu�[���PKs�Z��*vv5�Symfony/Bridge/Monolog/Handler/SwiftMailerHandler.phpnu�[���PKs�Z���"II3��Symfony/Bridge/Monolog/Handler/ChromePhpHandler.phpnu�[���PKs�Z��;��	�	!��Symfony/Bridge/Monolog/Logger.phpnu�[���PKs�Z��b115��Symfony/Bridge/Monolog/Formatter/ConsoleFormatter.phpnu�[���PKt�Z�,��1l�Symfony/Bridge/Monolog/Processor/WebProcessor.phpnu�[���PKt�Z�$�KK"l�Symfony/Bridge/Twig/autoloader.phpnu�[���PKt�Z�)�UU1	�Symfony/Bridge/Twig/Translation/TwigExtractor.phpnu�[���PKt�Z6DZ77*��Symfony/Bridge/Twig/Node/StopwatchNode.phpnu�[���PKt�Z,
�@��5P�Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.phpnu�[���PKt�Z�
�s>>*ESymfony/Bridge/Twig/Node/FormThemeNode.phpnu�[���PKt�ZP�IAA3�Symfony/Bridge/Twig/Node/TransDefaultDomainNode.phpnu�[���PKt�Z�U,tt,�Symfony/Bridge/Twig/Node/FormEnctypeNode.phpnu�[���PKt�Zʦ\�G
G
&QSymfony/Bridge/Twig/Node/TransNode.phpnu�[���PKt�Z���^��,�%Symfony/Bridge/Twig/Node/RenderBlockNode.phpnu�[���PKt�Z�vq�)+Symfony/Bridge/Twig/Form/TwigRenderer.phpnu�[���PKt�Zb�3�}}8q1Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.phpnu�[���PKt�Z��Qkk2V4Symfony/Bridge/Twig/Form/TwigRendererInterface.phpnu�[���PKt�Z��<��/#7Symfony/Bridge/Twig/Form/TwigRendererEngine.phpnu�[���PKt�Z�GTSymfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.phpnu�[���PKt�Z�)�[n	n	)�`Symfony/Bridge/Twig/NodeVisitor/Scope.phpnu�[���PKt�Z�tA�:`jSymfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.phpnu�[���PKt�Z��9292B�xSymfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twignu�[���PKt�Z��[[Dy�Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twignu�[���PKt�Z.��8H�Symfony/Bridge/Twig/TokenParser/StopwatchTokenParser.phpnu�[���PKt�Z�%]�
�
4��Symfony/Bridge/Twig/TokenParser/TransTokenParser.phpnu�[���PKt�Z�/�	�	:��Symfony/Bridge/Twig/TokenParser/TransChoiceTokenParser.phpnu�[���PKt�Z>����8>�Symfony/Bridge/Twig/TokenParser/FormThemeTokenParser.phpnu�[���PKt�Zʶ�̭�Ao�Symfony/Bridge/Twig/TokenParser/TransDefaultDomainTokenParser.phpnu�[���PKt�Z�9�=KK/��Symfony/Bridge/Twig/Extension/FormExtension.phpnu�[���PKt�Z��|/7�Symfony/Bridge/Twig/Extension/YamlExtension.phpnu�[���PKt�Z��&�a
a
5��Symfony/Bridge/Twig/Extension/HttpKernelExtension.phpnu�[���PKt�ZKΙ���5v�Symfony/Bridge/Twig/Extension/ExpressionExtension.phpnu�[���PKt�Z`�fS..2� Symfony/Bridge/Twig/Extension/RoutingExtension.phpnu�[���PKt�Z�5��mm4] Symfony/Bridge/Twig/Extension/StopwatchExtension.phpnu�[���PKt�Z�?���6. Symfony/Bridge/Twig/Extension/TranslationExtension.phpnu�[���PKt�Zd���oo3�! Symfony/Bridge/Twig/Extension/SecurityExtension.phpnu�[���PKt�Z�����/a' Symfony/Bridge/Twig/Extension/CodeExtension.phpnu�[���PKu�Z^D��dd"sG Symfony/Bridge/Twig/TwigEngine.phpnu�[���PKu�Z�4˵��()V Symfony/Component/Finder/Shell/Shell.phpnu�[���PKu�Z5��K��*^ Symfony/Component/Finder/Shell/Command.phpnu�[���PKu�Z�5�9(�v Symfony/Component/Finder/SplFileInfo.phpnu�[���PKu�Z%uM�PP'X~ Symfony/Component/Finder/autoloader.phpnu�[���PKu�Z��99C� Symfony/Component/Finder/Exception/ShellCommandFailureException.phpnu�[���PKu�Z�7��9�� Symfony/Component/Finder/Exception/ExceptionInterface.phpnu�[���PKu�Z�cWޫ�<� Symfony/Component/Finder/Exception/AccessDeniedException.phpnu�[���PKu�Z>�@��>� Symfony/Component/Finder/Exception/AdapterFailureException.phpnu�[���PKu�ZP�����D	� Symfony/Component/Finder/Exception/OperationNotPermitedException.phpnu�[���PKu�Z��� ��6� Symfony/Component/Finder/Comparator/DateComparator.phpnu�[���PKu�Z|F�z

2?� Symfony/Component/Finder/Comparator/Comparator.phpnu�[���PKu�Z�P�

8�� Symfony/Component/Finder/Comparator/NumberComparator.phpnu�[���PKu�Z�g@Mbb!2� Symfony/Component/Finder/Glob.phpnu�[���PKu�Z�d�V�V#� Symfony/Component/Finder/Finder.phpnu�[���PKu�Zils_��>
!Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.phpnu�[���PKu�Z��ɔ�
�
7u!Symfony/Component/Finder/Iterator/FilePathsIterator.phpnu�[���PKu�Z�,G��4n!Symfony/Component/Finder/Iterator/FilterIterator.phpnu�[���PKu�Z�ʽ���?q#!Symfony/Component/Finder/Iterator/FilecontentFilterIterator.phpnu�[���PKu�Z�

���@~+!Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.phpnu�[���PKu�Z��z":�2!Symfony/Component/Finder/Iterator/CustomFilterIterator.phpnu�[���PKu�Z{�^ǽ�<N9!Symfony/Component/Finder/Iterator/FilenameFilterIterator.phpnu�[���PKu�Z�d����Dw@!Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.phpnu�[���PKu�Zx�P���=�F!Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.phpnu�[���PKu�Z ��U��=�L!Symfony/Component/Finder/Iterator/DateRangeFilterIterator.phpnu�[���PKu�Z�n bb<�R!Symfony/Component/Finder/Iterator/FileTypeFilterIterator.phpnu�[���PKu�Z��j��	�	6�X!Symfony/Component/Finder/Iterator/SortableIterator.phpnu�[���PKu�Z���)��8�b!Symfony/Component/Finder/Iterator/PathFilterIterator.phpnu�[���PKu�Z�6s��@�j!Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.phpnu�[���PKu�Z��&
&
2Gw!Symfony/Component/Finder/Expression/Expression.phpnu�[���PKu�Z�"HH6ρ!Symfony/Component/Finder/Expression/ValueInterface.phpnu�[���PKu�Z�E�,}�!Symfony/Component/Finder/Expression/Glob.phpnu�[���PKu�Z��(�-�!Symfony/Component/Finder/Expression/Regex.phpnu�[���PKu�Z9!�2{
{
/D�!Symfony/Component/Finder/Adapter/PhpAdapter.phpnu�[���PKu�Z����5�!Symfony/Component/Finder/Adapter/AdapterInterface.phpnu�[���PKu�Z��kA�
�
34�!Symfony/Component/Finder/Adapter/BsdFindAdapter.phpnu�[���PKu�Z�}]�
�
3��!Symfony/Component/Finder/Adapter/GnuFindAdapter.phpnu�[���PKu�ZQJ)�)8��!Symfony/Component/Finder/Adapter/AbstractFindAdapter.phpnu�[���PKu�Z�	4�"Symfony/Component/Finder/Adapter/AbstractAdapter.phpnu�[���PKu�Z����:;"Symfony/Component/Translation/Extractor/ChainExtractor.phpnu�[���PKu�ZArP�>%"Symfony/Component/Translation/Extractor/ExtractorInterface.phpnu�[���PKu�Zb*0�oo4�#"Symfony/Component/Translation/PluralizationRules.phpnu�[���PKu�Z�q��UU,<"Symfony/Component/Translation/autoloader.phpnu�[���PKu�Z�<qNN10>"Symfony/Component/Translation/MessageSelector.phpnu�[���PKu�Z�س��:�J"Symfony/Component/Translation/Catalogue/MergeOperation.phpnu�[���PKu�ZY[�>*P"Symfony/Component/Translation/Catalogue/OperationInterface.phpnu�[���PKu�Z��fb�
�
=�U"Symfony/Component/Translation/Catalogue/AbstractOperation.phpnu�[���PKu�Z��ӄ�9�c"Symfony/Component/Translation/Catalogue/DiffOperation.phpnu�[���PKu�Z�6�"��>�i"Symfony/Component/Translation/Exception/ExceptionInterface.phpnu�[���PKu�ZDŽ���D�k"Symfony/Component/Translation/Exception/InvalidResourceException.phpnu�[���PKv�Z�2B��E2n"Symfony/Component/Translation/Exception/NotFoundResourceException.phpnu�[���PKv�Z�y4��2�p"Symfony/Component/Translation/MessageCatalogue.phpnu�[���PKv�Z%�Mt8��"Symfony/Component/Translation/MetadataAwareInterface.phpnu�[���PKv�Z�d�<<4��"Symfony/Component/Translation/IdentityTranslator.phpnu�[���PKv�Z�e�G��,��"Symfony/Component/Translation/Translator.phpnu�[���PKv�Z��֛�;u�"Symfony/Component/Translation/MessageCatalogueInterface.phpnu�[���PKv�ZM�
���9{�"Symfony/Component/Translation/Dumper/IcuResFileDumper.phpnu�[���PKv�Zਪ(5u�"Symfony/Component/Translation/Dumper/PoFileDumper.phpnu�[���PKv�Z���%LL6��"Symfony/Component/Translation/Dumper/PhpFileDumper.phpnu�[���PKv�Z�<̧��8��"Symfony/Component/Translation/Dumper/XliffFileDumper.phpnu�[���PKv�Z>{GG5��"Symfony/Component/Translation/Dumper/QtFileDumper.phpnu�[���PKv�Z���667Z�"Symfony/Component/Translation/Dumper/YamlFileDumper.phpnu�[���PKv�ZoB���6��"Symfony/Component/Translation/Dumper/CsvFileDumper.phpnu�[���PKv�ZB^�[[3*�"Symfony/Component/Translation/Dumper/FileDumper.phpnu�[���PKv�Z�:$}}7�"Symfony/Component/Translation/Dumper/JsonFileDumper.phpnu�[���PKv�Z&X����6�#Symfony/Component/Translation/Dumper/IniFileDumper.phpnu�[���PKv�Z��<**8
#Symfony/Component/Translation/Dumper/DumperInterface.phpnu�[���PKv�Z����A	A	5�#Symfony/Component/Translation/Dumper/MoFileDumper.phpnu�[���PKv�Zg�?Z�
�
*B#Symfony/Component/Translation/Interval.phpnu�[���PKv�Z�3����5�#Symfony/Component/Translation/TranslatorInterface.phpnu�[���PKv�ZP�?�}}:�%#Symfony/Component/Translation/Writer/TranslationWriter.phpnu�[���PKv�ZN@���6�-#Symfony/Component/Translation/Loader/IniFileLoader.phpnu�[���PKv�Z�T�93#Symfony/Component/Translation/Loader/IcuDatFileLoader.phpnu�[���PKv�ZCS�z
z
9�9#Symfony/Component/Translation/Loader/IcuResFileLoader.phpnu�[���PKv�Z��v���5�D#Symfony/Component/Translation/Loader/MoFileLoader.phpnu�[���PKv�ZR����4&\#Symfony/Component/Translation/Loader/ArrayLoader.phpnu�[���PKv�Z�'s�u	u	7&d#Symfony/Component/Translation/Loader/JsonFileLoader.phpnu�[���PKv�Z�i�3"
"
6n#Symfony/Component/Translation/Loader/CsvFileLoader.phpnu�[���PKv�Z_��BB8�x#Symfony/Component/Translation/Loader/XliffFileLoader.phpnu�[���PKv�Zl#�tt84�#Symfony/Component/Translation/Loader/LoaderInterface.phpnu�[���PKv�Z�*���5�#Symfony/Component/Translation/Loader/PoFileLoader.phpnu�[���PKv�Z�r��;;6o�#Symfony/Component/Translation/Loader/PhpFileLoader.phpnu�[���PKv�Z:�	Z�"�"B�#Symfony/Component/Translation/Loader/schema/dic/xliff-core/xml.xsdnu�[���PKv�Z�xO��T�#Symfony/Component/Translation/Loader/schema/dic/xliff-core/xliff-core-1.2-strict.xsdnu�[���PKv�Z)-d+�	�	5�g%Symfony/Component/Translation/Loader/QtFileLoader.phpnu�[���PKv�Z:����7�q%Symfony/Component/Translation/Loader/YamlFileLoader.phpnu�[���PKw�Z�V�˽�.-z%Symfony/Component/Routing/Annotation/Route.phpnu�[���PKw�Z�<ѹ�+H�%Symfony/Component/Routing/CompiledRoute.phpnu�[���PKw�ZU8���-\�%Symfony/Component/Routing/RouterInterface.phpnu�[���PKw�ZU�cQQ(>�%Symfony/Component/Routing/autoloader.phpnu�[���PKw�Z����'�'+�%Symfony/Component/Routing/RouteCompiler.phpnu�[���PKw�Z��%�%$�%Symfony/Component/Routing/Router.phpnu�[���PKw�Z���q
q
6n�%Symfony/Component/Routing/Matcher/ApacheUrlMatcher.phpnu�[���PKw�Z	�ڗ9E�%Symfony/Component/Routing/Matcher/UrlMatcherInterface.phpnu�[���PKw�Z`�u���=��%Symfony/Component/Routing/Matcher/RequestMatcherInterface.phpnu�[���PKw�Z[z�dd<�&Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.phpnu�[���PKw�Z?�|{��:�&Symfony/Component/Routing/Matcher/Dumper/MatcherDumper.phpnu�[���PKw�Z�x}�44=�&Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.phpnu�[���PKw�Z�bz#z#@A&Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.phpnu�[���PKw�Z�`=e&Symfony/Component/Routing/Matcher/Dumper/DumperCollection.phpnu�[���PKw�Z�N�
�
C�s&Symfony/Component/Routing/Matcher/Dumper/DumperPrefixCollection.phpnu�[���PKw�Z(� ���C�~&Symfony/Component/Routing/Matcher/Dumper/MatcherDumperInterface.phpnu�[���PKw�ZY�IWW8��&Symfony/Component/Routing/Matcher/Dumper/DumperRoute.phpnu�[���PKw�Z�'��9��&Symfony/Component/Routing/Matcher/TraceableUrlMatcher.phpnu�[���PKw�ZGj�C""0��&Symfony/Component/Routing/Matcher/UrlMatcher.phpnu�[���PKw�Z� ��ffE'�&Symfony/Component/Routing/Matcher/RedirectableUrlMatcherInterface.phpnu�[���PKw�Z����==K�&Symfony/Component/Routing/Exception/MissingMandatoryParametersException.phpnu�[���PKw�Zj`j�A��&Symfony/Component/Routing/Exception/InvalidParameterException.phpnu�[���PKw�Znj�W��>/�&Symfony/Component/Routing/Exception/RouteNotFoundException.phpnu�[���PKw�Z��)���:��&Symfony/Component/Routing/Exception/ExceptionInterface.phpnu�[���PKw�Z����JJA��&Symfony/Component/Routing/Exception/MethodNotAllowedException.phpnu�[���PKw�Z?�]�//Af�&Symfony/Component/Routing/Exception/ResourceNotFoundException.phpnu�[���PKw�Z��^�==#�&Symfony/Component/Routing/Route.phpnu�[���PKw�Zr�����:i	'Symfony/Component/Routing/RequestContextAwareInterface.phpnu�[���PKw�Z|,{Ȫ�-p'Symfony/Component/Routing/RouteCollection.phpnu�[���PKw�Z�h�,w)'Symfony/Component/Routing/RequestContext.phpnu�[���PKw�Zմ���I�C'Symfony/Component/Routing/Generator/ConfigurableRequirementsInterface.phpnu�[���PKw�Z�
��1�148M'Symfony/Component/Routing/Generator/UrlGenerator.phpnu�[���PKw�Z�1O�
�
Az'Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.phpnu�[���PKw�Zu�'��>��'Symfony/Component/Routing/Generator/Dumper/GeneratorDumper.phpnu�[���PKw�Z�4��G��'Symfony/Component/Routing/Generator/Dumper/GeneratorDumperInterface.phpnu�[���PKw�Z����@@=�'Symfony/Component/Routing/Generator/UrlGeneratorInterface.phpnu�[���PKw�Zn���hh2Ȥ'Symfony/Component/Routing/Loader/ClosureLoader.phpnu�[���PKw�Z��?�		>��'Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.phpnu�[���PKw�Z~ޟ
�
9�'Symfony/Component/Routing/Loader/AnnotationFileLoader.phpnu�[���PKw�Z~L�W��:�'Symfony/Component/Routing/Loader/AnnotationClassLoader.phpnu�[���PKw�ZP�i{��2��'Symfony/Component/Routing/Loader/PhpFileLoader.phpnu�[���PKw�Z?-[��	�	?5�'Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsdnu�[���PKw�Zأ2D$D$2L�'Symfony/Component/Routing/Loader/XmlFileLoader.phpnu�[���PKw�ZpB�Q Q 3�(Symfony/Component/Routing/Loader/YamlFileLoader.phpnu�[���PKx�ZqF��>>4�5(Symfony/Component/Routing/RouteCompilerInterface.phpnu�[���PKx�Z0���QQ(H9(Symfony/Component/Process/autoloader.phpnu�[���PKx�Zg��'�'*�:(Symfony/Component/Process/ProcessPipes.phpnu�[���PKx�Z��2�{{@6c(Symfony/Component/Process/Exception/ProcessTimedOutException.phpnu�[���PKx�Z�<���:!j(Symfony/Component/Process/Exception/ExceptionInterface.phpnu�[���PKx�Z>H����8:l(Symfony/Component/Process/Exception/RuntimeException.phpnu�[���PKx�Z��W��6�n(Symfony/Component/Process/Exception/LogicException.phpnu�[���PKx�Z˅����@�p(Symfony/Component/Process/Exception/InvalidArgumentException.phpnu�[���PKx�Z��_��>s(Symfony/Component/Process/Exception/ProcessFailedException.phpnu�[���PKx�Z@s�(�x(Symfony/Component/Process/PhpProcess.phpnu�[���PKx�Z�nL	L	*�(Symfony/Component/Process/ProcessUtils.phpnu�[���PKy�Z�!,$

.��(Symfony/Component/Process/ExecutableFinder.phpnu�[���PKy�Z!/���,�(Symfony/Component/Process/ProcessBuilder.phpnu�[���PKy�Zy>�8��1�(Symfony/Component/Process/PhpExecutableFinder.phpnu�[���PKy�Z��M��%ު(Symfony/Component/Process/Process.phpnu�[���PKy�Z[i55ERA)Symfony/Component/Serializer/Normalizer/SerializerAwareNormalizer.phpnu�[���PKy�Z=Vxe::A�D)Symfony/Component/Serializer/Normalizer/NormalizableInterface.phpnu�[���PKy�Z��SVV<�J)Symfony/Component/Serializer/Normalizer/CustomNormalizer.phpnu�[���PKy�Z��,,BiR)Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.phpnu�[���PKy�Z"p�yy?q)Symfony/Component/Serializer/Normalizer/NormalizerInterface.phpnu�[���PKy�Z�qU���C�u)Symfony/Component/Serializer/Normalizer/DenormalizableInterface.phpnu�[���PKz�Z���A�{)Symfony/Component/Serializer/Normalizer/DenormalizerInterface.phpnu�[���PKz�Z���OO9t�)Symfony/Component/Serializer/SerializerAwareInterface.phpnu�[���PKz�Z��TT+,�)Symfony/Component/Serializer/autoloader.phpnu�[���PKz�Zx蕰

4ۅ)Symfony/Component/Serializer/SerializerInterface.phpnu�[���PKz�Z,�c��9L�)Symfony/Component/Serializer/Encoder/EncoderInterface.phpnu�[���PKz�Z��[�5�53i�)Symfony/Component/Serializer/Encoder/XmlEncoder.phpnu�[���PKz�Z�<=ggD��)Symfony/Component/Serializer/Encoder/NormalizationAwareInterface.phpnu�[���PKz�ZV��O��5��)Symfony/Component/Serializer/Encoder/ChainDecoder.phpnu�[���PKz�Z�=��?��)Symfony/Component/Serializer/Encoder/SerializerAwareEncoder.phpnu�[���PKz�Zv:�hh3[�)Symfony/Component/Serializer/Encoder/JsonEncode.phpnu�[���PKz�Z��@���3&�)Symfony/Component/Serializer/Encoder/JsonDecode.phpnu�[���PKz�ZS R�	�	5q�)Symfony/Component/Serializer/Encoder/ChainEncoder.phpnu�[���PKz�Z�o�vv4��)Symfony/Component/Serializer/Encoder/JsonEncoder.phpnu�[���PKz�Z|ͼ���9��)Symfony/Component/Serializer/Encoder/DecoderInterface.phpnu�[���PKz�ZA�A
��4�*Symfony/Component/Serializer/Exception/Exception.phpnu�[���PKz�Z�^L��?�*Symfony/Component/Serializer/Exception/UnsupportedException.phpnu�[���PKz�Z�h=��;�*Symfony/Component/Serializer/Exception/RuntimeException.phpnu�[���PKz�ZJ���9�*Symfony/Component/Serializer/Exception/LogicException.phpnu�[���PKz�ZT��Y��C	*Symfony/Component/Serializer/Exception/InvalidArgumentException.phpnu�[���PKz�Z[�����Ci*Symfony/Component/Serializer/Exception/UnexpectedValueException.phpnu�[���PKz�Zʪ2/&/&+�
*Symfony/Component/Serializer/Serializer.phpnu�[���PKz�ZFP�PP'<4*Symfony/Component/Locale/autoloader.phpnu�[���PKz�Z�Q�UUL�5*Symfony/Component/Locale/Exception/MethodArgumentNotImplementedException.phpnu�[���PKz�Z��E>�9*Symfony/Component/Locale/Exception/NotImplementedException.phpnu�[���PKz�ZS�?a%%D#=*Symfony/Component/Locale/Exception/MethodNotImplementedException.phpnu�[���PKz�Z���ssQ�@*Symfony/Component/Locale/Exception/MethodArgumentValueNotImplementedException.phpnu�[���PKz�Z�C��*�D*Symfony/Component/Locale/Stub/StubIntl.phpnu�[���PKz�Z&�����5�G*Symfony/Component/Locale/Stub/StubNumberFormatter.phpnu�[���PKz�Zv/�@�J*Symfony/Component/Locale/Stub/DateFormat/Hour2401Transformer.phpnu�[���PKz�Z��S@PN*Symfony/Component/Locale/Stub/DateFormat/TimeZoneTransformer.phpnu�[���PKz�Z}��""A�Q*Symfony/Component/Locale/Stub/DateFormat/DayOfYearTransformer.phpnu�[���PKz�Z�X�<oU*Symfony/Component/Locale/Stub/DateFormat/AmPmTransformer.phpnu�[���PKz�Z���<�X*Symfony/Component/Locale/Stub/DateFormat/YearTransformer.phpnu�[���PKz�Zmў?O\*Symfony/Component/Locale/Stub/DateFormat/QuarterTransformer.phpnu�[���PKz�Zg[ep>�_*Symfony/Component/Locale/Stub/DateFormat/MinuteTransformer.phpnu�[���PKz�Z:6""ARc*Symfony/Component/Locale/Stub/DateFormat/DayOfWeekTransformer.phpnu�[���PKz�Z9�u@�f*Symfony/Component/Locale/Stub/DateFormat/Hour1200Transformer.phpnu�[���PKz�Zk&"M@qj*Symfony/Component/Locale/Stub/DateFormat/Hour1201Transformer.phpnu�[���PKz�Z�����;�m*Symfony/Component/Locale/Stub/DateFormat/DayTransformer.phpnu�[���PKz�Z��@fq*Symfony/Component/Locale/Stub/DateFormat/Hour2400Transformer.phpnu�[���PKz�Z�Ed��8�t*Symfony/Component/Locale/Stub/DateFormat/Transformer.phpnu�[���PKz�Zt�z

=Ox*Symfony/Component/Locale/Stub/DateFormat/MonthTransformer.phpnu�[���PKz�Zk�H<�{*Symfony/Component/Locale/Stub/DateFormat/FullTransformer.phpnu�[���PKz�Z�3�X>6*Symfony/Component/Locale/Stub/DateFormat/SecondTransformer.phpnu�[���PKz�Z�
�

<��*Symfony/Component/Locale/Stub/DateFormat/HourTransformer.phpnu�[���PKz�Z���?��.-�*Symfony/Component/Locale/Stub/StubCollator.phpnu�[���PK{�Zq��*((,�*Symfony/Component/Locale/Stub/StubLocale.phpnu�[���PK{�Z� S���7��*Symfony/Component/Locale/Stub/StubIntlDateFormatter.phpnu�[���PK{�Zl�l��#��*Symfony/Component/Locale/Locale.phpnu�[���PK{�Z�t�TT+��*Symfony/Component/Filesystem/autoloader.phpnu�[���PK{�Z��dP��@b�*Symfony/Component/Filesystem/Exception/FileNotFoundException.phpnu�[���PK{�Z3{����=��*Symfony/Component/Filesystem/Exception/ExceptionInterface.phpnu�[���PK{�ZoC�~��?��*Symfony/Component/Filesystem/Exception/IOExceptionInterface.phpnu�[���PK{�Z;�{��6ͷ*Symfony/Component/Filesystem/Exception/IOException.phpnu�[���PK{�ZOظ�GG+�*Symfony/Component/Filesystem/Filesystem.phpnu�[���PK{�Z)��.�.'T+Symfony/Component/Form/FormRenderer.phpnu�[���PK{�Z�C����.]2+Symfony/Component/Form/ButtonTypeInterface.phpnu�[���PK{�ZK'�$��&�4+Symfony/Component/Form/FormBuilder.phpnu�[���PK{�Z&�"̰T�T,�S+Symfony/Component/Form/FormConfigBuilder.phpnu�[���PK{�ZE1�'��4��+Symfony/Component/Form/SubmitButtonTypeInterface.phpnu�[���PK{�Z�d��'�+Symfony/Component/Form/FormRegistry.phpnu�[���PK{�ZÊM'%%.н+Symfony/Component/Form/FormConfigInterface.phpnu�[���PK{�Z��@@/S�+Symfony/Component/Form/FormTypeGuesserChain.phpnu�[���PK{�ZR����+��+Symfony/Component/Form/Guess/ValueGuess.phpnu�[���PK{�Z�511&,�+Symfony/Component/Form/Guess/Guess.phpnu�[���PK{�Z���  *��+Symfony/Component/Form/Guess/TypeGuess.phpnu�[���PK{�Z�0\ZZ.-�+Symfony/Component/Form/CallbackTransformer.phpnu�[���PK{�Z4�Nz"z"!�,Symfony/Component/Form/Button.phpnu�[���PK{�Z-�9NN%�%,Symfony/Component/Form/autoloader.phpnu�[���PK{�Z�/��tt%S',Symfony/Component/Form/FormEvents.phpnu�[���PK{�Z�����,,,Symfony/Component/Form/FormTypeInterface.phpnu�[���PK{�Z�>���09,Symfony/Component/Form/FormRegistryInterface.phpnu�[���PK{�Z��?zz3?,Symfony/Component/Form/FormTypeGuesserInterface.phpnu�[���PK{�Z��*��+�G,Symfony/Component/Form/ResolvedFormType.phpnu�[���PK{�ZObX�qq'6f,Symfony/Component/Form/SubmitButton.phpnu�[���PK|�Z�p��1�j,Symfony/Component/Form/AbstractRendererEngine.phpnu�[���PK|�ZDjN,1�,Symfony/Component/Form/AbstractExtension.phpnu�[���PK|�Zf#jK��6��,Symfony/Component/Form/FormRendererEngineInterface.phpnu�[���PK|�Z���1�1���,Symfony/Component/Form/Form.phpnu�[���PK|�Z�di���;A-Symfony/Component/Form/Exception/BadMethodCallException.phpnu�[���PK|�Z�W�

:yC-Symfony/Component/Form/Exception/AlreadyBoundException.phpnu�[���PK|�Z(ddB�E-Symfony/Component/Form/Exception/InvalidConfigurationException.phpnu�[���PK|�Z�_c==<�G-Symfony/Component/Form/Exception/UnexpectedTypeException.phpnu�[���PK|�Z�S�D��BoJ-Symfony/Component/Form/Exception/TransformationFailedException.phpnu�[���PK|�Z��9�L-Symfony/Component/Form/Exception/OutOfBoundsException.phpnu�[���PK}�Z�y�u��7�N-Symfony/Component/Form/Exception/ExceptionInterface.phpnu�[���PK}�ZN����5
Q-Symfony/Component/Form/Exception/RuntimeException.phpnu�[���PK}�ZK�9���>OS-Symfony/Component/Form/Exception/AlreadySubmittedException.phpnu�[���PK}�Z1�;TT:�U-Symfony/Component/Form/Exception/ErrorMappingException.phpnu�[���PK}�Z��+RR8oW-Symfony/Component/Form/Exception/StringCastException.phpnu�[���PK}�Z��X��3)Y-Symfony/Component/Form/Exception/LogicException.phpnu�[���PK}�Z�gBz��=d[-Symfony/Component/Form/Exception/InvalidArgumentException.phpnu�[���PK}�Z�1��88'�]-Symfony/Component/Form/AbstractType.phpnu�[���PK}�Z�I	�66.Ub-Symfony/Component/Form/Util/OrderedHashMap.phpnu�[���PK}�Z�h��''6�t-Symfony/Component/Form/Util/OrderedHashMapIterator.phpnu�[���PK}�Z��F228v�-Symfony/Component/Form/Util/VirtualFormAwareIterator.phpnu�[���PK}�Zy���$$(�-Symfony/Component/Form/Util/FormUtil.phpnu�[���PK}�Z<����8��-Symfony/Component/Form/Util/InheritDataAwareIterator.phpnu�[���PK}�Z�QT�pp.�-Symfony/Component/Form/SubmitButtonBuilder.phpnu�[���PK}�Z�z5���2��-Symfony/Component/Form/ResolvedFormTypeFactory.phpnu�[���PK}�ZSf��
	
	-��-Symfony/Component/Form/PreloadedExtension.phpnu�[���PK}�Z>��*ii&�-Symfony/Component/Form/FormFactory.phpnu�[���PK}�Z�\�g��2˳-Symfony/Component/Form/RequestHandlerInterface.phpnu�[���PK}�Z+q�DAA7ɶ-Symfony/Component/Form/Test/FormPerformanceTestCase.phpnu�[���PK}�ZsŪ�,q�-Symfony/Component/Form/Test/TypeTestCase.phpnu�[���PK}�Z�,�7//7�-Symfony/Component/Form/Test/DeprecationErrorHandler.phpnu�[���PK}�ZB�4I++7k�-Symfony/Component/Form/Test/FormIntegrationTestCase.phpnu�[���PK}�Z��m�yy4��-Symfony/Component/Form/Test/FormBuilderInterface.phpnu�[���PK}�Za(0kk-��-Symfony/Component/Form/Test/FormInterface.phpnu�[���PK}�Z�n����1��-Symfony/Component/Form/FormExtensionInterface.phpnu�[���PK}�Z|G����4��-Symfony/Component/Form/ResolvedFormTypeInterface.phpnu�[���PK}�Z{d���!�!5��-Symfony/Component/Form/FormConfigBuilderInterface.phpnu�[���PK}�ZɃT���6.Symfony/Component/Form/FormFactoryBuilderInterface.phpnu�[���PK}�Z�N̷;m.Symfony/Component/Form/ResolvedFormTypeFactoryInterface.phpnu�[���PK}�Z2��-�.Symfony/Component/Form/FormFactoryBuilder.phpnu�[���PK}�Z���C��0d$.Symfony/Component/Form/AbstractTypeExtension.phpnu�[���PK}�Z�E���0�(.Symfony/Component/Form/FormRendererInterface.phpnu�[���PK}�Z�:		/�5.Symfony/Component/Form/FormBuilderInterface.phpnu�[���PK}�Z��Z)��/R?.Symfony/Component/Form/FormFactoryInterface.phpnu�[���PK}�Z�YB���.EP.Symfony/Component/Form/ReversedTransformer.phpnu�[���PK}�Z�r�WW3�U.Symfony/Component/Form/DataTransformerInterface.phpnu�[���PK}�ZW�b�[H[H(Eb.Symfony/Component/Form/ButtonBuilder.phpnu�[���PK}�Z��n��?��.Symfony/Component/Form/Resources/translations/validators.en.xlfnu�[���PK}�Z誫���?�.Symfony/Component/Form/Resources/translations/validators.sk.xlfnu�[���PK}�Z�<�yy?=�.Symfony/Component/Form/Resources/translations/validators.uk.xlfnu�[���PK}�Z:����?%�.Symfony/Component/Form/Resources/translations/validators.pl.xlfnu�[���PK��Z��
���?[�.Symfony/Component/Form/Resources/translations/validators.pt.xlfnu�[���PK��Z�%��?��.Symfony/Component/Form/Resources/translations/validators.lv.xlfnu�[���PK��Z္o33D��.Symfony/Component/Form/Resources/translations/validators.sr_Cyrl.xlfnu�[���PK��Z����?��.Symfony/Component/Form/Resources/translations/validators.fi.xlfnu�[���PK��Z0h���?��.Symfony/Component/Form/Resources/translations/validators.es.xlfnu�[���PK��Z�TI��?,�.Symfony/Component/Form/Resources/translations/validators.de.xlfnu�[���PK��Z!�aZ��?~�.Symfony/Component/Form/Resources/translations/validators.it.xlfnu�[���PK��Z �!���?��.Symfony/Component/Form/Resources/translations/validators.ca.xlfnu�[���PK��Z���?��.Symfony/Component/Form/Resources/translations/validators.mn.xlfnu�[���PK��Z���-��?X�.Symfony/Component/Form/Resources/translations/validators.ru.xlfnu�[���PK��Z�3Ե^^?T�.Symfony/Component/Form/Resources/translations/validators.bg.xlfnu�[���PK��ZE��d��?!�.Symfony/Component/Form/Resources/translations/validators.ro.xlfnu�[���PK��ZO���?r�.Symfony/Component/Form/Resources/translations/validators.nl.xlfnu�[���PK��ZS�*��?��.Symfony/Component/Form/Resources/translations/validators.et.xlfnu�[���PK��Z�V5?��.Symfony/Component/Form/Resources/translations/validators.fa.xlfnu�[���PK��Z��q��?J�.Symfony/Component/Form/Resources/translations/validators.id.xlfnu�[���PK��Z�
���?w/Symfony/Component/Form/Resources/translations/validators.cs.xlfnu�[���PK��Z�8,:��B�/Symfony/Component/Form/Resources/translations/validators.zh_CN.xlfnu�[���PK��Z�H�q��?�
/Symfony/Component/Form/Resources/translations/validators.lt.xlfnu�[���PK��Z�_8��?�/Symfony/Component/Form/Resources/translations/validators.fr.xlfnu�[���PK��Z�A�4��?�/Symfony/Component/Form/Resources/translations/validators.gl.xlfnu�[���PK��Z
b�8��?4/Symfony/Component/Form/Resources/translations/validators.hr.xlfnu�[���PK��ZWgUugg?]/Symfony/Component/Form/Resources/translations/validators.nb.xlfnu�[���PK��Zٻ��||?3/Symfony/Component/Form/Resources/translations/validators.eu.xlfnu�[���PK��Z�4@���B#/Symfony/Component/Form/Resources/translations/validators.pt_BR.xlfnu�[���PK��Z��5��?Q'/Symfony/Component/Form/Resources/translations/validators.sl.xlfnu�[���PK��Z�*{���?m+/Symfony/Component/Form/Resources/translations/validators.lb.xlfnu�[���PK��Zbe�@��?�//Symfony/Component/Form/Resources/translations/validators.hu.xlfnu�[���PK��Z_Π��?4/Symfony/Component/Form/Resources/translations/validators.el.xlfnu�[���PK��ZX�����?9/Symfony/Component/Form/Resources/translations/validators.da.xlfnu�[���PK��Z���?�</Symfony/Component/Form/Resources/translations/validators.ja.xlfnu�[���PK��Zs>�ll?AA/Symfony/Component/Form/Resources/translations/validators.sv.xlfnu�[���PK��Zy��99?E/Symfony/Component/Form/Resources/translations/validators.hy.xlfnu�[���PK��Z|��C?�I/Symfony/Component/Form/Resources/translations/validators.ar.xlfnu�[���PK��Zr���DBN/Symfony/Component/Form/Resources/translations/validators.sr_Latn.xlfnu�[���PK��ZNP\��?dR/Symfony/Component/Form/Resources/translations/validators.he.xlfnu�[���PK��Z�xfh..6dV/Symfony/Component/Form/Resources/config/validation.xmlnu�[���PK��ZR}��jj.�X/Symfony/Component/Form/DataMapperInterface.phpnu�[���PK��Z�s�� � (�]/Symfony/Component/Form/FormInterface.phpnu�[���PK��Z���"��$�~/Symfony/Component/Form/FormEvent.phpnu�[���PK��Z�=�MM5Ӄ/Symfony/Component/Form/FormTypeExtensionInterface.phpnu�[���PK��Z�}p�

$��/Symfony/Component/Form/FormError.phpnu�[���PK��Z�	���/ܖ/Symfony/Component/Form/NativeRequestHandler.phpnu�[���PK��Z���*��O'�/Symfony/Component/Form/Extension/Validator/EventListener/ValidationListener.phpnu�[���PK��Z��Ck��@5�/Symfony/Component/Form/Extension/Validator/Util/ServerParams.phpnu�[���PK��Z2=[<((A1�/Symfony/Component/Form/Extension/Validator/ValidatorExtension.phpnu�[���PK��Z}>�ُ�?��/Symfony/Component/Form/Extension/Validator/Constraints/Form.phpnu�[���PK��Z�-�P��H��/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.phpnu�[���PK��Zl�Ct*t*C��/Symfony/Component/Form/Extension/Validator/ValidatorTypeGuesser.phpnu�[���PK��ZɥS��T�
0Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPathIterator.phpnu�[���PK��Z�\T��K0Symfony/Component/Form/Extension/Validator/ViolationMapper/RelativePath.phpnu�[���PK��ZC_�hU+U+N0Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.phpnu�[���PK��Z�k�t==W�@0Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapperInterface.phpnu�[���PK��Z�-��!!L�E0Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPath.phpnu�[���PK��Zf����
�
JR_0Symfony/Component/Form/Extension/Validator/ViolationMapper/MappingRule.phpnu�[���PK��Z�����J�j0Symfony/Component/Form/Extension/Validator/Type/BaseValidatorExtension.phpnu�[���PK��ZeBR�	�	N�p0Symfony/Component/Form/Extension/Validator/Type/FormTypeValidatorExtension.phpnu�[���PK��Z͚>�@@R+{0Symfony/Component/Form/Extension/Validator/Type/RepeatedTypeValidatorExtension.phpnu�[���PK��Z1���P�0Symfony/Component/Form/Extension/Validator/Type/SubmitTypeValidatorExtension.phpnu�[���PK��Z���,QQC��0Symfony/Component/Form/Extension/Templating/TemplatingExtension.phpnu�[���PK��Zզ�Y��HL�0Symfony/Component/Form/Extension/Templating/TemplatingRendererEngine.phpnu�[���PK��Z䋧��U��0Symfony/Component/Form/Extension/HttpFoundation/EventListener/BindRequestListener.phpnu�[���PK��Z�j��=
=
PԦ0Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationRequestHandler.phpnu�[���PK��Z��Q��K��0Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationExtension.phpnu�[���PK��Z�PffX��0Symfony/Component/Form/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.phpnu�[���PK��Z"�q���7��0Symfony/Component/Form/Extension/Csrf/CsrfExtension.phpnu�[���PK��Z�C���J��0Symfony/Component/Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.phpnu�[���PK��Z[^����J��0Symfony/Component/Form/Extension/Csrf/CsrfProvider/SessionCsrfProvider.phpnu�[���PK��Z%�G���L�0Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderInterface.phpnu�[���PK��Z�����JI�0Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderAdapter.phpnu�[���PK��ZR�'WTTN��0Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfTokenManagerAdapter.phpnu�[���PK��Z�?�ooNy�0Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.phpnu�[���PK��Z��
f�PK��Z���	��6.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUri   URI of the namespace
     * @param bool   $multiline      whether to create a multiline tag where each
     *                               attribute gets written to a single line
     * @param string $indent         string used to indent attributes (_auto indents
     *                               attributes so they start at the same column)
     * @param string $linebreak      string used for linebreaks
     * @param bool   $sortAttributes Whether to sort the attributes or not
     *
     * @return string XML start element
     * @see    createEndElement(), createTag()
     */
    public static function createStartElement(
        $qname, $attributes = array(), $namespaceUri = null,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true
    ) {
        // if no attributes hav been set, use empty attributes
        if (!isset($attributes) || !is_array($attributes)) {
            $attributes = array();
        }

        if ($namespaceUri != null) {
            $parts = XML_Util::splitQualifiedName($qname);
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($qname)+2));
            }
        }

        if ($namespaceUri != null) {
            // is a namespace given
            if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
            } else {
                // define this Uri as the default namespace
                $attributes['xmlns'] = $namespaceUri;
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $attributes, $sortAttributes,
            $multiline, $indent, $linebreak
        );
        $element = sprintf('<%s%s>', $qname, $attList);
        return  $element;
    }

    /**
     * Create an end element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createEndElement('myNs:myTag');
     * </code>
     *
     * @param string $qname qualified tagname (including namespace)
     *
     * @return string XML end element
     * @see    createStartElement(), createTag()
     */
    public static function createEndElement($qname)
    {
        $element = sprintf('</%s>', $qname);
        return $element;
    }

    /**
     * Create an XML comment
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createComment('I am a comment');
     * </code>
     *
     * @param string $content content of the comment
     *
     * @return string XML comment
     */
    public static function createComment($content)
    {
        $comment = sprintf('<!-- %s -->', $content);
        return $comment;
    }

    /**
     * Create a CData section
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create a CData section
     * $tag = XML_Util::createCDataSection('I am content.');
     * </code>
     *
     * @param string $data data of the CData section
     *
     * @return string CData section with content
     */
    public static function createCDataSection($data)
    {
        return sprintf(
            '<![CDATA[%s]]>',
            preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data))
        );
    }

    /**
     * Split qualified name and return namespace and local part
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // split qualified tag
     * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
     * </code>
     * the returned array will contain two elements:
     * <pre>
     * array(
     *     'namespace' => 'xslt',
     *     'localPart' => 'stylesheet'
     * );
     * </pre>
     *
     * @param string $qname     qualified tag name
     * @param string $defaultNs default namespace (optional)
     *
     * @return array array containing namespace and local part
     */
    public static function splitQualifiedName($qname, $defaultNs = null)
    {
        if (strstr($qname, ':')) {
            $tmp = explode(':', $qname);
            return array(
                'namespace' => $tmp[0],
                'localPart' => $tmp[1]
            );
        }
        return array(
            'namespace' => $defaultNs,
            'localPart' => $qname
        );
    }

    /**
     * Check, whether string is valid XML name
     *
     * <p>XML names are used for tagname, attribute names and various
     * other, lesser known entities.</p>
     * <p>An XML name may only consist of alphanumeric characters,
     * dashes, undescores and periods, and has to start with a letter
     * or an underscore.</p>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // verify tag name
     * $result = XML_Util::isValidName('invalidTag?');
     * if (is_a($result, 'PEAR_Error')) {
     *    print 'Invalid XML name: ' . $result->getMessage();
     * }
     * </code>
     *
     * @param string $string string that should be checked
     *
     * @return mixed true, if string is a valid XML name, PEAR error otherwise
     *
     * @todo support for other charsets
     * @todo PEAR CS - unable to avoid 85-char limit on second preg_match
     */
    public static function isValidName($string)
    {
        // check for invalid chars
        if (!is_string($string) || !strlen($string) || !preg_match('/^[[:alpha:]_]\\z/', $string[0])) {
            return XML_Util::raiseError(
                'XML names may only start with letter or underscore',
                XML_UTIL_ERROR_INVALID_START
            );
        }

        // check for invalid chars
        $match = preg_match(
            '/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?'
            . '[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/',
            $string
        );
        if (!$match) {
            return XML_Util::raiseError(
                'XML names may only contain alphanumeric '
                . 'chars, period, hyphen, colon and underscores',
                XML_UTIL_ERROR_INVALID_CHARS
            );
        }
        // XML name is valid
        return true;
    }

    /**
     * Replacement for XML_Util::raiseError
     *
     * Avoids the necessity to always require
     * PEAR.php
     *
     * @param string $msg  error message
     * @param int    $code error code
     *
     * @return PEAR_Error
     * @todo   PEAR CS - should this use include_once instead?
     */
    public static function raiseError($msg, $code)
    {
        include_once 'PEAR.php';
        return PEAR::raiseError($msg, $code);
    }
}
?>
PK��Z#F��:�:pearcmd.phpnu�[���<?php
/**
 * PEAR, the PHP Extension and Application Repository
 *
 * Command line interface
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Stig Bakken <ssb@php.net>
 * @author    Tomas V.V.Cox <cox@idecnet.com>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 */

@ob_end_clean();
if (!defined('PEAR_RUNTYPE')) {
    // this is defined in peclcmd.php as 'pecl'
    define('PEAR_RUNTYPE', 'pear');
}
define('PEAR_IGNORE_BACKTRACE', 1);
/**
 * @nodep Gtk
 */
//the space is needed for windows include paths with trailing backslash
// http://pear.php.net/bugs/bug.php?id=19482
if ('/opt/alt/php74/usr/share/pear ' != '@'.'include_path'.'@ ') {
    ini_set('include_path', trim('/opt/alt/php74/usr/share/pear '). PATH_SEPARATOR .  get_include_path());
    $raw = false;
} else {
    // this is a raw, uninstalled pear, either a cvs checkout, or php distro
    ini_set('include_path', dirname(__DIR__) . PATH_SEPARATOR . get_include_path());
    $raw = true;
}
@ini_set('allow_url_fopen', true);
@set_time_limit(0);
ob_implicit_flush(true);
@ini_set('track_errors', true);
@ini_set('html_errors', false);
$_PEAR_PHPDIR = '#$%^&*';
set_error_handler('error_handler');

$pear_package_version = "1.10.16";

require_once 'PEAR.php';
require_once 'PEAR/Frontend.php';
require_once 'PEAR/Config.php';
require_once 'PEAR/Command.php';
require_once 'Console/Getopt.php';


PEAR_Command::setFrontendType('CLI');
$all_commands = PEAR_Command::getCommands();

$argv = Console_Getopt::readPHPArgv();
// fix CGI sapi oddity - the -- in pear.bat/pear is not removed
if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
    unset($argv[1]);
    $argv = array_values($argv);
}
$progname = PEAR_RUNTYPE;
array_shift($argv);
$options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV");
if (PEAR::isError($options)) {
    usage($options);
}

$opts = $options[0];

$fetype = 'CLI';
if ($progname == 'gpear' || $progname == 'pear-gtk') {
    $fetype = 'Gtk2';
} else {
    foreach ($opts as $opt) {
        if ($opt[0] == 'G') {
            $fetype = 'Gtk2';
        }
    }
}

$pear_user_config = '';
$pear_system_config = '';
$store_user_config = false;
$store_system_config = false;
$verbose = 1;

foreach ($opts as $opt) {
    switch ($opt[0]) {
    case 'c':
        $pear_user_config = $opt[1];
        break;
    case 'C':
        $pear_system_config = $opt[1];
        break;
    }
}

PEAR_Command::setFrontendType($fetype);
$ui = &PEAR_Command::getFrontendObject();
$config = &PEAR_Config::singleton($pear_user_config, $pear_system_config);

if (PEAR::isError($config)) {
    $_file = '';
    if ($pear_user_config !== false) {
        $_file .= $pear_user_config;
    }
    if ($pear_system_config !== false) {
        $_file .= '/' . $pear_system_config;
    }
    if ($_file == '/') {
        $_file = 'The default config file';
    }
    $config->getMessage();
    $ui->outputData("ERROR: $_file is not a valid config file or is corrupted.");
    // We stop, we have no idea where we are :)
    exit(1);
}

// this is used in the error handler to retrieve a relative path
$_PEAR_PHPDIR = $config->get('php_dir');
$ui->setConfig($config);
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError"));

$verbose = $config->get("verbose");
$cmdopts = array();

if ($raw) {
    if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) {
        $found = false;
        foreach ($opts as $opt) {
            if ($opt[0] == 'd' || $opt[0] == 'D') {
                // the user knows what they are doing, and are setting config values
                $found = true;
            }
        }
        if (!$found) {
            // no prior runs, try to install PEAR
            $parent = dirname(__FILE__);
            if (strpos($parent, 'scripts')) {
                $grandparent = dirname($parent);
                $packagexml = $grandparent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $grandparent;
            } else {
                $packagexml = $parent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $parent;
            }
            if (file_exists($packagexml)) {
                $options[1] = array(
                    'install',
                    $packagexml
                );
                $config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php');
                $config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data');
                $config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs');
                $config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests');
                $config->set(
                    'ext_dir',
                    $pearbase . DIRECTORY_SEPARATOR . 'extensions'
                );
                $config->set('bin_dir', $pearbase);
                $config->mergeConfigFile($pearbase . 'pear.ini', false);
                $config->store();
                $config->set('auto_discover', 1);
            }
        }
    }
}
foreach ($opts as $opt) {
    $param = !empty($opt[1]) ? $opt[1] : true;
    switch ($opt[0]) {
    case 'd':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected -d config_value=value, ' .
                'received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'user');
        break;
    case 'D':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'system');
        break;
    case 's':
        $store_user_config = true;
        break;
    case 'S':
        $store_system_config = true;
        break;
    case 'u':
        $config->remove($param, 'user');
        break;
    case 'v':
        $config->set('verbose', $config->get('verbose') + 1);
        break;
    case 'q':
        $config->set('verbose', $config->get('verbose') - 1);
        break;
    case 'V':
        usage(null, 'version');
    case 'c':
    case 'C':
        break;
    default:
        // all non pear params goes to the command
        $cmdopts[$opt[0]] = $param;
        break;
    }
}

if ($store_system_config) {
    $config->store('system');
}

if ($store_user_config) {
    $config->store('user');
}

$command = (isset($options[1][0])) ? $options[1][0] : null;
if (empty($command) && ($store_user_config || $store_system_config)) {
    exit;
}

if ($fetype == 'Gtk2') {
    if (!$config->validConfiguration()) {
        PEAR::raiseError(
            "CRITICAL ERROR: no existing valid configuration files found in " .
            "files '$pear_user_config' or '$pear_system_config', " .
            "please copy an existing configuration file to one of these " .
            "locations, or use the -c and -s options to create one"
        );
    }
    Gtk::main();
} else {
    do {
        if ($command == 'help') {
            usage(null, isset($options[1][1]) ? $options[1][1] : null);
        }

        if (!$config->validConfiguration()) {
            PEAR::raiseError(
                "CRITICAL ERROR: no existing valid configuration files found " .
                "in files '$pear_user_config' or '$pear_system_config', " .
                "please copy an existing configuration file to one of " .
                "these locations, or use the -c and -s options to create one"
            );
        }

        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        $cmd = PEAR_Command::factory($command, $config);
        PEAR::popErrorHandling();
        if (PEAR::isError($cmd)) {
            usage(null, isset($options[1][0]) ? $options[1][0] : null);
        }

        $short_args = $long_args = null;
        PEAR_Command::getGetoptArgs($command, $short_args, $long_args);
        array_shift($options[1]);
        $tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args);

        if (PEAR::isError($tmp)) {
            break;
        }

        list($tmpopt, $params) = $tmp;
        $opts = array();
        foreach ($tmpopt as $foo => $tmp2) {
            list($opt, $value) = $tmp2;
            if ($value === null) {
                $value = true; // options without args
            }

            if (strlen($opt) == 1) {
                $cmdoptions = $cmd->getOptions($command);
                foreach ($cmdoptions as $o => $d) {
                    if (isset($d['shortopt']) && $d['shortopt'] == $opt) {
                        $opts[$o] = $value;
                    }
                }
            } else {
                if (substr($opt, 0, 2) == '--') {
                    $opts[substr($opt, 2)] = $value;
                }
            }
        }

        $ok = $cmd->run($command, $opts, $params);
        if ($ok === false) {
            PEAR::raiseError("unknown command `$command'");
        }

        if (PEAR::isError($ok)) {
            PEAR::setErrorHandling(
                PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")
            );
            PEAR::raiseError($ok);
        }
    } while (false);
}

// {{{ usage()

/**
 * Display usage information
 *
 * @param mixed $error       Optional error message
 * @param mixed $helpsubject Optional subject/command to display help for
 *
 * @return void
 */
function usage($error = null, $helpsubject = null)
{
    global $progname, $all_commands;
    $stdout = fopen('php://stdout', 'w');
    if (PEAR::isError($error)) {
        fputs($stdout, $error->getMessage() . "\n");
    } elseif ($error !== null) {
        fputs($stdout, "$error\n");
    }

    if ($helpsubject != null) {
        $put = cmdHelp($helpsubject);
    } else {
        $put = "Commands:\n";
        $maxlen = max(array_map("strlen", $all_commands));
        $formatstr = "%-{$maxlen}s  %s\n";
        ksort($all_commands);
        foreach ($all_commands as $cmd => $class) {
            $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd));
        }
        $put .=
            "Usage: $progname [options] command [command-options] <parameters>\n".
            "Type \"$progname help options\" to list all options.\n".
            "Type \"$progname help shortcuts\" to list all command shortcuts.\n".
            "Type \"$progname help version\" or ".
            "\"$progname version\" to list version information.\n".
            "Type \"$progname help <command>\" to get the help ".
            "for the specified command.";
    }
    fputs($stdout, "$put\n");
    fclose($stdout);

    if ($error === null) {
        exit(0);
    }
    exit(1);
}

/**
 * Return help string for specified command
 *
 * @param string $command Command to return help for
 *
 * @return void
 */
function cmdHelp($command)
{
    global $progname, $all_commands, $config;
    if ($command == "options") {
        return
        "Options:\n".
        "     -v         increase verbosity level (default 1)\n".
        "     -q         be quiet, decrease verbosity level\n".
        "     -c file    find user configuration in `file'\n".
        "     -C file    find system configuration in `file'\n".
        "     -d foo=bar set user config variable `foo' to `bar'\n".
        "     -D foo=bar set system config variable `foo' to `bar'\n".
        "     -G         start in graphical (Gtk) mode\n".
        "     -s         store user configuration\n".
        "     -S         store system configuration\n".
        "     -u foo     unset `foo' in the user configuration\n".
        "     -h, -?     display help/usage (this message)\n".
        "     -V         version information\n";
    } elseif ($command == "shortcuts") {
        $sc = PEAR_Command::getShortcuts();
        $ret = "Shortcuts:\n";
        foreach ($sc as $s => $c) {
            $ret .= sprintf("     %-8s %s\n", $s, $c);
        }
        return $ret;

    } elseif ($command == "version") {
        return "PEAR Version: ".$GLOBALS['pear_package_version'].
               "\nPHP Version: ".phpversion().
               "\nZend Engine Version: ".zend_version().
               "\nRunning on: ".php_uname();

    } elseif ($help = PEAR_Command::getHelp($command)) {
        if (is_string($help)) {
            return "$progname $command [options] $help\n";
        }

        if ($help[1] === null) {
            return "$progname $command $help[0]";
        }

        return "$progname $command [options] $help[0]\n$help[1]";
    }

    return "Command '$command' is not valid, try '$progname help'";
}

// }}}

/**
 * error_handler
 *
 * @param mixed $errno  Error number
 * @param mixed $errmsg Message
 * @param mixed $file   Filename
 * @param mixed $line   Line number
 *
 * @access public
 * @return boolean
 */
function error_handler($errno, $errmsg, $file, $line)
{
    if ((!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) && ($errno & E_STRICT)) {
        return; // E_STRICT
    }
    if ($errno & E_DEPRECATED) {
        return; // E_DEPRECATED
    }
    if (!(error_reporting() & $errno) &&
        isset($GLOBALS['config']) &&
        $GLOBALS['config']->get('verbose') < 4
    ) {
        return false; // @silenced error, show all if debug is high enough
    }
    $errortype = array (
        E_DEPRECATED  => 'Deprecated Warning',
        E_ERROR   =>  "Error",
        E_WARNING   =>  "Warning",
        E_PARSE   =>  "Parsing Error",
        E_NOTICE   =>  "Notice",
        E_CORE_ERROR  =>  "Core Error",
        E_CORE_WARNING  =>  "Core Warning",
        E_COMPILE_ERROR  =>  "Compile Error",
        E_COMPILE_WARNING =>  "Compile Warning",
        E_USER_ERROR =>  "User Error",
        E_USER_WARNING =>  "User Warning",
        E_USER_NOTICE =>  "User Notice"
    );
    if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) {
        $errortype[E_STRICT] = 'Strict Warning';
    }
    $prefix = $errortype[$errno];
    global $_PEAR_PHPDIR;
    if (stristr($file, $_PEAR_PHPDIR)) {
        $file = substr($file, strlen($_PEAR_PHPDIR) + 1);
    } else {
        $file = basename($file);
    }
    print "\n$prefix: $errmsg in $file on line $line\n";
    return false;
}


/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * indent-tabs-mode: nil
 * mode: php
 * End:
 */
// vim600:syn=php
PK��Z�0$�-- .pkgxml/Pear_File_MARC-1.4.1.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.10.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
 <name>File_MARC</name>
 <channel>pear.php.net</channel>
 <summary>Parse, modify, and create MARC records</summary>
 <description>The standard for machine-readable cataloging (MARC) records is documented at http://loc.gov/marc/. This package enables you to read existing MARC records from a file, string, or (using the YAZ extension), from a Z39.50 source. You can also use this package to create new MARC records.

This package is based on the PHP MARC package, originally called &quot;php-marc&quot;, that is part of the Emilda Project (http://www.emilda.org).  Christoffer Landtman generously agreed to make the &quot;php-marc&quot; code available under the GNU LGPL so it could be used as the basis of this PEAR package.</description>
 <lead>
  <name>Dan Scott</name>
  <user>dbs</user>
  <email>dbs@php.net</email>
  <active>yes</active>
 </lPK��Z��
��W�W.registry/archive_tar.regnu�[���PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                 PK��Z��I\ENEN.registry/net_sieve.regnu�[���PK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributPK��ZV���)�).registry/console_getopt.regnu�[���PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
        PK��Z0-�(�(�.registry/file_marc.regnu�[���PK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUri   URI of the namespace
     * @param bool   $multiline      whether to create a multiline tag where each
     *                               attribute gets written to a single line
     * @param string $indent         string used to indent attributes (_auto indents
     *                               attributes so they start at the same column)
     * @param string $linebreak      string used for linebreaks
     * @param bool   $sortAttributes Whether to sort the attributes or not
     *
     * @return string XML start element
     * @see    createEndElement(), createTag()
     */
    public static function createStartElement(
        $qname, $attributes = array(), $namespaceUri = null,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true
    ) {
        // if no attributes hav been set, use empty attributes
        if (!isset($attributes) || !is_array($attributes)) {
            $attributes = array();
        }

        if ($namespaceUri != null) {
            $parts = XML_Util::splitQualifiedName($qname);
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($qname)+2));
            }
        }

        if ($namespaceUri != null) {
            // is a namespace given
            if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
            } else {
                // define this Uri as the default namespace
                $attributes['xmlns'] = $namespaceUri;
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $attributes, $sortAttributes,
            $multiline, $indent, $linebreak
        );
        $element = sprintf('<%s%s>', $qname, $attList);
        return  $element;
    }

    /**
     * Create an end element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createEndElement('myNs:myTag');
     * </code>
     *
     * @param string $qname qualified tagname (including namespace)
     *
     * @return string XML end element
     * @see    createStartElement(), createTag()
     */
    public static function createEndElement($qname)
    {
        $element = sprintf('</%s>', $qname);
        return $element;
    }

    /**
     * Create an XML comment
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createComment('I am a comment');
     * </code>
     *
     * @param string $content content of the comment
     *
     * @return string XML comment
     */
    public static function createComment($content)
    {
        $comment = sprintf('<!-- %s -->', $content);
        return $comment;
    }

    /**
     * Create a CData section
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create a CData section
     * $tag = XML_Util::createCDataSection('I am content.');
     * </code>
     *
     * @param string $data data of the CData section
     *
     * @return string CData section with content
     */
    public static function createCDataSection($data)
    {
        return sprintf(
            '<![CDATA[%s]]>',
            preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data))
        );
    }

    /**
     * Split qualified name and return namespace and local part
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // split qualified tag
     * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
     * </code>
     * the returned array will contain two elements:
     * <pre>
     * array(
     *     'namespace' => 'xslt',
     *     'localPart' => 'stylesheet'
     * );
     * </pre>
     *
     * @param string $qname     qualified tag name
     * @param string $defaultNs default namespace (optional)
     *
     * @return array array containing namespace and local part
     */
    public static function splitQualifiedName($qname, $defaultNs = null)
    {
        if (strstr($qname, ':')) {
            $tmp = explode(':', $qname);
            return array(
                'namespace' => $tmp[0],
                'localPart' => $tmp[1]
            );
        }
        return array(
            'namespace' => $defaultNs,
            'localPart' => $qname
        );
    }

    /**
     * Check, whether string is valid XML name
     *
     * <p>XML names are used for tagname, attribute names and various
     * other, lesser known entities.</p>
     * <p>An XML name may only consist of alphanumeric characters,
     * dashes, undescores and periods, and has to start with a letter
     * or an underscore.</p>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // verify tag name
     * $result = XML_Util::isValidName('invalidTag?');
     * if (is_a($result, 'PEAR_Error')) {
     *    print 'Invalid XML name: ' . $result->getMessage();
     * }
     * </code>
     *
     * @param string $string string that should be checked
     *
     * @return mixed true, if string is a valid XML name, PEAR error otherwise
     *
     * @todo support for other charsets
     * @todo PEAR CS - unable to avoid 85-char limit on second preg_match
     */
    public static function isValidName($string)
    {
        // check for invalid chars
        if (!is_string($string) || !strlen($string) || !preg_match('/^[[:alpha:]_]\\z/', $string[0])) {
            return XML_Util::raiseError(
                'XML names may only start with letter or underscore',
                XML_UTIL_ERROR_INVALID_START
            );
        }

        // check for invalid chars
        $match = preg_match(
            '/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?'
            . '[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/',
            $string
        );
        if (!$match) {
            return XML_Util::raiseError(
                'XML names may only contain alphanumeric '
                . 'chars, period, hyphen, colon and underscores',
                XML_UTIL_ERROR_INVALID_CHARS
            );
        }
        // XML name is valid
        return true;
    }

    /**
     * Replacement for XML_Util::raiseError
     *
     * Avoids the necessity to always require
     * PEAR.php
     *
     * @param string $msg  error message
     * @param int    $code error code
     *
     * @return PEAR_Error
     * @todo   PEAR CS - should this use include_once instead?
     */
    public static function raiseError($msg, $code)
    {
        include_once 'PEAR.php';
        return PEAR::raiseError($msg, $code);
    }
}
?>
PK��Z#F��:�:pearcmd.phpnu�[���<?php
/**
 * PEAR, the PHP Extension and Application Repository
 *
 * Command line interface
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Stig Bakken <ssb@php.net>
 * @author    Tomas V.V.Cox <cox@idecnet.com>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 */

@ob_end_clean();
if (!defined('PEAR_RUNTYPE')) {
    // this is defined in peclcmd.php as 'pecl'
    define('PEAR_RUNTYPE', 'pear');
}
define('PEAR_IGNORE_BACKTRACE', 1);
/**
 * @nodep Gtk
 */
//the space is needed for windows include paths with trailing backslash
// http://pear.php.net/bugs/bug.php?id=19482
if ('/opt/alt/php74/usr/share/pear ' != '@'.'include_path'.'@ ') {
    ini_set('include_path', trim('/opt/alt/php74/usr/share/pear '). PATH_SEPARATOR .  get_include_path());
    $raw = false;
} else {
    // this is a raw, uninstalled pear, either a cvs checkout, or php distro
    ini_set('include_path', dirname(__DIR__) . PATH_SEPARATOR . get_include_path());
    $raw = true;
}
@ini_set('allow_url_fopen', true);
@set_time_limit(0);
ob_implicit_flush(true);
@ini_set('track_errors', true);
@ini_set('html_errors', false);
$_PEAR_PHPDIR = '#$%^&*';
set_error_handler('error_handler');

$pear_package_version = "1.10.16";

require_once 'PEAR.php';
require_once 'PEAR/Frontend.php';
require_once 'PEAR/Config.php';
require_once 'PEAR/Command.php';
require_once 'Console/Getopt.php';


PEAR_Command::setFrontendType('CLI');
$all_commands = PEAR_Command::getCommands();

$argv = Console_Getopt::readPHPArgv();
// fix CGI sapi oddity - the -- in pear.bat/pear is not removed
if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
    unset($argv[1]);
    $argv = array_values($argv);
}
$progname = PEAR_RUNTYPE;
array_shift($argv);
$options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV");
if (PEAR::isError($options)) {
    usage($options);
}

$opts = $options[0];

$fetype = 'CLI';
if ($progname == 'gpear' || $progname == 'pear-gtk') {
    $fetype = 'Gtk2';
} else {
    foreach ($opts as $opt) {
        if ($opt[0] == 'G') {
            $fetype = 'Gtk2';
        }
    }
}

$pear_user_config = '';
$pear_system_config = '';
$store_user_config = false;
$store_system_config = false;
$verbose = 1;

foreach ($opts as $opt) {
    switch ($opt[0]) {
    case 'c':
        $pear_user_config = $opt[1];
        break;
    case 'C':
        $pear_system_config = $opt[1];
        break;
    }
}

PEAR_Command::setFrontendType($fetype);
$ui = &PEAR_Command::getFrontendObject();
$config = &PEAR_Config::singleton($pear_user_config, $pear_system_config);

if (PEAR::isError($config)) {
    $_file = '';
    if ($pear_user_config !== false) {
        $_file .= $pear_user_config;
    }
    if ($pear_system_config !== false) {
        $_file .= '/' . $pear_system_config;
    }
    if ($_file == '/') {
        $_file = 'The default config file';
    }
    $config->getMessage();
    $ui->outputData("ERROR: $_file is not a valid config file or is corrupted.");
    // We stop, we have no idea where we are :)
    exit(1);
}

// this is used in the error handler to retrieve a relative path
$_PEAR_PHPDIR = $config->get('php_dir');
$ui->setConfig($config);
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError"));

$verbose = $config->get("verbose");
$cmdopts = array();

if ($raw) {
    if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) {
        $found = false;
        foreach ($opts as $opt) {
            if ($opt[0] == 'd' || $opt[0] == 'D') {
                // the user knows what they are doing, and are setting config values
                $found = true;
            }
        }
        if (!$found) {
            // no prior runs, try to install PEAR
            $parent = dirname(__FILE__);
            if (strpos($parent, 'scripts')) {
                $grandparent = dirname($parent);
                $packagexml = $grandparent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $grandparent;
            } else {
                $packagexml = $parent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $parent;
            }
            if (file_exists($packagexml)) {
                $options[1] = array(
                    'install',
                    $packagexml
                );
                $config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php');
                $config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data');
                $config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs');
                $config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests');
                $config->set(
                    'ext_dir',
                    $pearbase . DIRECTORY_SEPARATOR . 'extensions'
                );
                $config->set('bin_dir', $pearbase);
                $config->mergeConfigFile($pearbase . 'pear.ini', false);
                $config->store();
                $config->set('auto_discover', 1);
            }
        }
    }
}
foreach ($opts as $opt) {
    $param = !empty($opt[1]) ? $opt[1] : true;
    switch ($opt[0]) {
    case 'd':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected -d config_value=value, ' .
                'received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'user');
        break;
    case 'D':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'system');
        break;
    case 's':
        $store_user_config = true;
        break;
    case 'S':
        $store_system_config = true;
        break;
    case 'u':
        $config->remove($param, 'user');
        break;
    case 'v':
        $config->set('verbose', $config->get('verbose') + 1);
        break;
    case 'q':
        $config->set('verbose', $config->get('verbose') - 1);
        break;
    case 'V':
        usage(null, 'version');
    case 'c':
    case 'C':
        break;
    default:
        // all non pearPK��Z�-"D�D�.registry/pear.regnu�[���PK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUri   URI of the namespace
     * @param bool   $multiline      whether to create a multiline tag where each
     *                               attribute gets written to a single line
     * @param string $indent         string used to indent attributes (_auto indents
     *                               attributes so they start at the same column)
     * @param string $linebreak      string used for linebreaks
     * @param bool   $sortAttributes Whether to sort the attributes or not
     *
     * @return string XML start element
     * @see    createEndElement(), createTag()
     */
    public static function createStartElement(
        $qname, $attributes = array(), $namespaceUri = null,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true
    ) {
        // if no attributes hav been set, use empty attributes
        if (!isset($attributes) || !is_array($attributes)) {
            $attributes = array();
        }

        if ($namespaceUri != null) {
            $parts = XML_Util::splitQualifiedName($qname);
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($qname)+2));
            }
        }

        if ($namespaceUri != null) {
            // is a namespace given
            if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
            } else {
                // define this Uri as the default namespace
                $attributes['xmlns'] = $namespaceUri;
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $attributes, $sortAttributes,
            $multiline, $indent, $linebreak
        );
        $element = sprintf('<%s%s>', $qname, $attList);
        return  $element;
    }

    /**
     * Create an end element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createEndElement('myNs:myTag');
     * </code>
     *
     * @param string $qname qualified tagname (including namespace)
     *
     * @return string XML end element
     * @see    createStartElement(), createTag()
     */
    public static function createEndElement($qname)
    {
        $element = sprintf('</%s>', $qname);
        return $element;
    }

    /**
     * Create an XML comment
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createComment('I am a comment');
     * </code>
     *
     * @param string $content content of the comment
     *
     * @return string XML comment
     */
    public static function createComment($content)
    {
        $comment = sprintf('<!-- %s -->', $content);
        return $comment;
    }

    /**
     * Create a CData section
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create a CData section
     * $tag = XML_Util::createCDataSection('I am content.');
     * </code>
     *
     * @param string $data data of the CData section
     *
     * @return string CData section with content
     */
    public static function createCDataSection($data)
    {
        return sprintf(
            '<![CDATA[%s]]>',
            preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data))
        );
    }

    /**
     * Split qualified name and return namespace and local part
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // split qualified tag
     * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
     * </code>
     * the returned array will contain two elements:
     * <pre>
     * array(
     *     'namespace' => 'xslt',
     *     'localPart' => 'stylesheet'
     * );
     * </pre>
     *
     * @param string $qname     qualified tag name
     * @param string $defaultNs default namespace (optional)
     *
     * @return array array containing namespace and local part
     */
    public static function splitQualifiedName($qname, $defaultNs = null)
    {
        if (strstr($qname, ':')) {
            $tmp = explode(':', $qname);
            return array(
                'namespace' => $tmp[0],
                'localPart' => $tmp[1]
            );
        }
        return array(
            'namespace' => $defaultNs,
            'localPart' => $qname
        );
    }

    /**
     * Check, whether string is valid XML name
     *
     * <p>XML names are used for tagname, attribute names and various
     * other, lesser known entities.</p>
     * <p>An XML name may only consist of alphanumeric characters,
     * dashes, undescores and periods, and has to start with a letter
     * or an underscore.</p>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // verify tag name
     * $result = XML_Util::isValidName('invalidTag?');
     * if (is_a($result, 'PEAR_Error')) {
     *    print 'Invalid XML name: ' . $result->getMessage();
     * }
     * </code>
     *
     * @param string $string string that should be checked
     *
     * @return mixed true, if string is a valid XML name, PEAR error otherwise
     *
     * @todo support for other charsets
     * @todo PEAR CS - unable to avoid 85-char limit on second preg_match
     */
    public static function isValidName($string)
    {
        // check for invalid chars
        if (!is_string($string) || !strlen($string) || !preg_match('/^[[:alpha:]_]\\z/', $string[0])) {
            return XML_Util::raiseError(
                'XML names may only start with letter or underscore',
                XML_UTIL_ERROR_INVALID_START
            );
        }

        // check for invalid chars
        $match = preg_match(
            '/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?'
            . '[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/',
            $string
        );
        if (!$match) {
            return XML_Util::raiseError(
                'XML names may only contain alphanumeric '
                . 'chars, period, hyphen, colon and underscores',
                XML_UTIL_ERROR_INVALID_CHARS
            );
        }
        // XML name is valid
        return true;
    }

    /**
     * Replacement for XML_Util::raiseError
     *
     * Avoids the necessity to always require
     * PEAR.php
     *
     * @param string $msg  error message
     * @param int    $code error code
     *
     * @return PEAR_Error
     * @todo   PEAR CS - should this use include_once instead?
     */
    public static function raiseError($msg, $code)
    {
        include_once 'PEAR.php';
        return PEAR::raiseError($msg, $code);
    }
}
?>
PK��Z#F��:�:pearcmd.phpnu�[���<?php
/**
 * PEAR, the PHP Extension and Application Repository
 *
 * Command line interface
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Stig Bakken <ssb@php.net>
 * @author    Tomas V.V.Cox <cox@idecnet.com>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 */

@ob_end_clean();
if (!defined('PEAR_RUNTYPE')) {
    // this is defined in peclcmd.php as 'pecl'
    define('PEAR_RUNTYPE', 'pear');
}
define('PEAR_IGNORE_BACKTRACE', 1);
/**
 * @nodep Gtk
 */
//the space is needed for windows include paths with trailing backslash
// http://pear.php.net/bugs/bug.php?id=19482
if ('/opt/alt/php74/usr/share/pear ' != '@'.'include_path'.'@ ') {
    ini_set('include_path', trim('/opt/alt/php74/usr/share/pear '). PATH_SEPARATOR .  get_include_path());
    $raw = false;
} else {
    // this is a raw, uninstalled pear, either a cvs checkout, or php distro
    ini_set('include_path', dirname(__DIR__) . PATH_SEPARATOR . get_include_path());
    $raw = true;
}
@ini_set('allow_url_fopen', true);
@set_time_limit(0);
ob_implicit_flush(true);
@ini_set('track_errors', true);
@ini_set('html_errors', false);
$_PEAR_PHPDIR = '#$%^&*';
set_error_handler('error_handler');

$pear_package_version = "1.10.16";

require_once 'PEAR.php';
require_once 'PEAR/Frontend.php';
require_once 'PEAR/Config.php';
require_once 'PEAR/Command.php';
require_once 'Console/Getopt.php';


PEAR_Command::setFrontendType('CLI');
$all_commands = PEAR_Command::getCommands();

$argv = Console_Getopt::readPHPArgv();
// fix CGI sapi oddity - the -- in pear.bat/pear is not removed
if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
    unset($argv[1]);
    $argv = array_values($argv);
}
$progname = PEAR_RUNTYPE;
array_shift($argv);
$options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV");
if (PEAR::isError($options)) {
    usage($options);
}

$opts = $options[0];

$fetype = 'CLI';
if ($progname == 'gpear' || $progname == 'pear-gtk') {
    $fetype = 'Gtk2';
} else {
    foreach ($opts as $opt) {
        if ($opt[0] == 'G') {
            $fetype = 'Gtk2';
        }
    }
}

$pear_user_config = '';
$pear_system_config = '';
$store_user_config = false;
$store_system_config = false;
$verbose = 1;

foreach ($opts as $opt) {
    switch ($opt[0]) {
    case 'c':
        $pear_user_config = $opt[1];
        break;
    case 'C':
        $pear_system_config = $opt[1];
        break;
    }
}

PEAR_Command::setFrontendType($fetype);
$ui = &PEAR_Command::getFrontendObject();
$config = &PEAR_Config::singleton($pear_user_config, $pear_system_config);

if (PEAR::isError($config)) {
    $_file = '';
    if ($pear_user_config !== false) {
        $_file .= $pear_user_config;
    }
    if ($pear_system_config !== false) {
        $_file .= '/' . $pear_system_config;
    }
    if ($_file == '/') {
        $_file = 'The default config file';
    }
    $config->getMessage();
    $ui->outputData("ERROR: $_file is not a valid config file or is corrupted.");
    // We stop, we have no idea where we are :)
    exit(1);
}

// this is used in the error handler to retrieve a relative path
$_PEAR_PHPDIR = $config->get('php_dir');
$ui->setConfig($config);
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError"));

$verbose = $config->get("verbose");
$cmdopts = array();

if ($raw) {
    if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) {
        $found = false;
        foreach ($opts as $opt) {
            if ($opt[0] == 'd' || $opt[0] == 'D') {
                // the user knows what they are doing, and are setting config values
                $found = true;
            }
        }
        if (!$found) {
            // no prior runs, try to install PEAR
            $parent = dirname(__FILE__);
            if (strpos($parent, 'scripts')) {
                $grandparent = dirname($parent);
                $packagexml = $grandparent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $grandparent;
            } else {
                $packagexml = $parent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $parent;
            }
            if (file_exists($packagexml)) {
                $options[1] = array(
                    'install',
                    $packagexml
                );
                $config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php');
                $config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data');
                $config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs');
                $config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests');
                $config->set(
                    'ext_dir',
                    $pearbase . DIRECTORY_SEPARATOR . 'extensions'
                );
                $config->set('bin_dir', $pearbase);
                $config->mergeConfigFile($pearbase . 'pear.ini', false);
                $config->store();
                $config->set('auto_discover', 1);
            }
        }
    }
}
foreach ($opts as $opt) {
    $param = !empty($opt[1]) ? $opt[1] : true;
    switch ($opt[0]) {
    case 'd':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected -d config_value=value, ' .
                'received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'user');
        break;
    case 'D':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'system');
        break;
    case 's':
        $store_user_config = true;
        break;
    case 'S':
        $store_system_config = true;
        break;
    case 'u':
        $config->remove($param, 'user');
        break;
    case 'v':
        $config->set('verbose', $config->get('verbose') + 1);
        break;
    case 'q':
        $config->set('verbose', $config->get('verbose') - 1);
        break;
    case 'V':
        usage(null, 'version');
    case 'c':
    case 'C':
        break;
    default:
        // all non pear params goes to the command
        $cmdopts[$opt[0]] = $param;
        break;
    }
}

if ($store_system_config) {
    $config->store('system');
}

if ($store_user_config) {
    $config->store('user');
}

$command = (isset($options[1][0])) ? $options[1][0] : null;
if (empty($command) && ($store_user_config || $store_system_config)) {
    exit;
}

if ($fetype == 'Gtk2') {
    if (!$config->validConfiguration()) {
        PEAR::raiseError(
            "CRITICAL ERROR: no existing valid configuration files found in " .
            "files '$pear_user_config' or '$pear_system_config', " .
            "please copy an existing configuration file to one of these " .
            "locations, or use the -c and -s options to create one"
        );
    }
    Gtk::main();
} else {
    do {
        if ($command == 'help') {
            usage(null, isset($options[1][1]) ? $options[1][1] : null);
        }

        if (!$config->validConfiguration()) {
            PEAR::raiseError(
                "CRITICAL ERROR: no existing valid configuration files found " .
                "in files '$pear_user_config' or '$pear_system_config', " .
                "please copy an existing configuration file to one of " .
                "these locations, or use the -c and -s options to create one"
            );
        }

        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        $cmd = PEAR_Command::factory($command, $config);
        PEAR::popErrorHandling();
        if (PEAR::isError($cmd)) {
            usage(null, isset($options[1][0]) ? $options[1][0] : null);
        }

        $short_args = $long_args = null;
        PEAR_Command::getGetoptArgs($command, $short_args, $long_args);
        array_shift($options[1]);
        $tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args);

        if (PEAR::isError($tmp)) {
            break;
        }

        list($tmpopt, $params) = $tmp;
        $opts = array();
        foreach ($tmpopt as $foo => $tmp2) {
            list($opt, $value) = $tmp2;
            if ($value === null) {
                $value = true; // options without args
            }

            if (strlen($opt) == 1) {
                $cmdoptions = $cmd->getOptions($command);
                foreach ($cmdoptions as $o => $d) {
                    if (isset($d['shortopt']) && $d['shortopt'] == $opt) {
                        $opts[$o] = $value;
                    }
                }
            } else {
                if (substr($opt, 0, 2) == '--') {
                    $opts[substr($opt, 2)] = $value;
                }
            }
        }

        $ok = $cmd->run($command, $opts, $params);
        if ($ok === false) {
            PEAR::raiseError("unknown command `$command'");
        }

        if (PEAR::isError($ok)) {
            PEAR::setErrorHandling(
                PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")
            );
            PEAR::raiseError($ok);
        }
    } while (false);
}

// {{{ usage()

/**
 * Display usage information
 *
 * @param mixed $error       Optional error message
 * @param mixed $helpsubject Optional subject/command to display help for
 *
 * @return void
 */
function usage($error = null, $helpsubject = null)
{
    global $progname, $all_commands;
    $stdout = fopen('php://stdout', 'w');
    if (PEAR::isError($error)) {
        fputs($stdout, $error->getMessage() . "\n");
    } elseif ($error !== null) {
        fputs($stdout, "$error\n");
    }

    if ($helpsubject != null) {
        $put = cmdHelp($helpsubject);
    } else {
        $put = "Commands:\n";
        $maxlen = max(array_map("strlen", $all_commands));
        $formatstr = "%-{$maxlen}s  %s\n";
        ksort($all_commands);
        foreach ($all_commands as $cmd => $class) {
            $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd));
        }
        $put .=
            "Usage: $progname [options] command [command-options] <parameters>\n".
            "Type \"$progname help options\" to list all options.\n".
            "Type \"$progname help shortcuts\" to list all command shortcuts.\n".
            "Type \"$progname help version\" or ".
            "\"$progname version\" to list version information.\n".
            "Type \"$progname help <command>\" to get the help ".
            "for the specified command.";
    }
    fputs($stdout, "$put\n");
    fclose($stdout);

    if ($error === null) {
        exit(0);
    }
    exit(1);
}

/**
 * Return help string for specified command
 *
 * @param string $command Command to return help for
 *
 * @return void
 */
function cmdHelp($command)
{
    global $progname, $all_commands, $config;
    if ($command == "options") {
        return
        "Options:\n".
        "     -v         increase verbosity level (default 1)\n".
        "     -q         be quiet, decrease verbosity level\n".
        "     -c file    find user configuration in `file'\n".
        "     -C file    find system configuration in `file'\n".
        "     -d foo=bar set user config variable `foo' to `bar'\n".
        "     -D foo=bar set system config variable `foo' to `bar'\n".
        "     -G         start in graphical (Gtk) mode\n".
        "     -s         store user configuration\n".
        "     -S         store system configuration\n".
        "     -u foo     unset `foo' in the user configuration\n".
        "     -h, -?     display help/usage (this message)\n".
        "     -V         version information\n";
    } elseif ($command == "shortcuts") {
        $sc = PEAR_Command::getShortcuts();
        $ret = "Shortcuts:\n";
        foreach ($sc as $s => $c) {
            $ret .= sprintf("     %-8s %s\n", $s, $c);
        }
        return $ret;

    } elseif ($command == "version") {
        return "PEAR Version: ".$GLOBALS['pear_package_version'].
               "\nPHP Version: ".phpversion().
               "\nZend Engine Version: ".zend_version().
               "\nRunning on: ".php_uname();

    } elseif ($help = PEAR_Command::getHelp($command)) {
        if (is_string($help)) {
            return "$progname $command [options] $help\n";
        }

        if ($help[1] === null) {
            return "$progname $command $help[0]";
        }

        return "$progname $command [options] $help[0]\n$help[1]";
    }

    return "Command '$command' is not valid, try '$progname help'";
}

// }}}

/**
 * error_handler
 *
 * @param mixed $errno  Error number
 * @param mixed $errmsg Message
 * @param mixed $file   Filename
 * @param mixed $line   Line number
 *
 * @access public
 * @return boolean
 */
function error_handler($errno, $errmsg, $file, $line)
{
    if ((!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) && ($errno & E_STRICT)) {
        return; // E_STRICT
    }
    if ($errno & E_DEPRECATED) {
        return; // E_DEPRECATED
    }
    if (!(error_reporting() & $errno) &&
        isset($GLOBALS['config']) &&
        $GLOBALS['config']->get('verbose') < 4
    ) {
        return false; // @silenced error, show all if debug is high enough
    }
    $errortype = array (
        E_DEPRECATED  => 'Deprecated Warning',
        E_ERROR   =>  "Error",
        E_WARNING   =>  "Warning",
        E_PARSE   =>  "Parsing Error",
        E_NOTICE   =>  "Notice",
        E_CORE_ERROR  =>  "Core Error",
        E_CORE_WARNING  =>  "Core Warning",
        E_COMPILE_ERROR  =>  "Compile Error",
        E_COMPILE_WARNING =>  "Compile Warning",
        E_USER_ERROR =>  "User Error",
        E_USER_WARNING =>  "User Warning",
        E_USER_NOTICE =>  "User Notice"
    );
    if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) {
        $errortype[E_STRICT] = 'Strict Warning';
    }
    $prefix = $errortype[$errno];
    global $_PEAR_PHPDIR;
    if (stristr($file, $_PEAR_PHPDIR)) {
        $file = substr($file, strlen($_PEAR_PHPDIR) + 1);
    } else {
        $file = basename($file);
    }
    print "\n$prefix: $errmsg in $file on line $line\n";
    return false;
}


/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * indent-tabs-mode: nil
 * mode: php
 * End:
 */
// vim600:syn=php
PK��Z�0$�-- .pkgxml/Pear_File_MARC-1.4.1.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.10.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
 <name>File_MARC</name>
 <channel>pear.php.net</channel>
 <summary>Parse, modify, and create MARC records</summary>
 <description>The standard for machine-readable cataloging (MARC) records is documented at http://loc.gov/marc/. This package enables you to read existing MARC records from a file, string, or (using the YAZ extension), from a Z39.50 source. You can also use this package to create new MARC records.

This package is based on the PHP MARC package, originally called &quot;php-marc&quot;, that is part of the Emilda Project (http://www.emilda.org).  Christoffer Landtman generously agreed to make the &quot;php-marc&quot; code available under the GNU LGPL so it could be used as the basis of this PEAR package.</description>
 <lead>
  <name>Dan Scott</name>
  <user>dbs</user>
  <email>dbs@php.net</email>
  <active>yes</active>
 </lead>
 <date>2019-11-13</date>
 <time>17:33:33</time>
 <version>
  <release>1.4.1</release>
  <api>1.4.0</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license uri="http://www.gnu.org/copyleft/lesser.html">GNU Lesser General Public License</license>
 <notes>
1.4.1
  * Reintroduce include_path to composer.json
 </notes>
 <contents>
  <dir baseinstalldir="File" name="/">
   <file baseinstalldir="/" md5sum="ffe2590635f404af055fe731da105939" name="File/MARC/Lint/CodeData.php" role="php" />
   <file baseinstalldir="/" md5sum="a3b9e1c817e67f59add05593500d463e" name="File/MARC/Control_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="acba4463f8e40d6ee4e7ba1f2dc53123" name="File/MARC/Data_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="378f483ec1fd161cd9dfb9b05db58d66" name="File/MARC/Exception.php" role="php" />
   <file baseinstalldir="/" md5sum="a9ba69030cbf4847292b9975e9d922c6" name="File/MARC/Field.php" role="php" />
   <file baseinstalldir="/" md5sum="c37351c7c80927ce6bb1e662510f9183" name="File/MARC/Lint.php" role="php" />
   <file baseinstalldir="/" md5sum="c5ac39e3d25eb0108b9dd5ad8466c821" name="File/MARC/List.php" role="php" />
   <file baseinstalldir="/" md5sum="7af6ce78cde4bb246e4e96709e90d2c0" name="File/MARC/Record.php" role="php" />
   <file baseinstalldir="/" md5sum="df5f97139685f0ad04e47fdbb67e3968" name="File/MARC/Subfield.php" role="php" />
   <file baseinstalldir="/" md5sum="6e102262dfd5d65d8d5a6221dfc74edd" name="File/MARC.php" role="php" />
   <file baseinstalldir="/" md5sum="8b64040d2d18ac4b994595a148266a66" name="File/MARCBASE.php" role="php" />
   <file baseinstalldir="/" md5sum="f5a17a60d34e84e2ee7ca1e5c5c6c620" name="File/MARCXML.php" role="php" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="examples/example.mrc" role="doc" />
   <file baseinstalldir="File" md5sum="1aea40df9f1c2e32f8e065fe8da0a3b5" name="examples/marc_yaz.php" role="doc" />
   <file baseinstalldir="File" md5sum="70ae317e0890d5896e3ffccdd293369a" name="examples/read.php" role="doc" />
   <file baseinstalldir="File" md5sum="54efb9d920ac775bfc847a83a2dec73a" name="examples/subfields.php" role="doc" />
   <file baseinstalldir="File" md5sum="14297da35b510c496cd1f328cf3bb301" name="tests/bad_example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="0dd4c6dbad6e8608d0ebf9d24425955d" name="tests/bad_example.xml" role="test" />
   <file baseinstalldir="File" md5sum="216a6f9d53f6d3d8e22d81fdc10f4bc1" name="tests/camel.mrc" role="test" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="tests/example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="9455aec3371f79cf7d31281fd03f5171" name="tests/marc_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="577e2f5f89fd48cf1a3576a29d2958f8" name="tests/marc_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a6a586354b9a06c880c2a7470dd828d7" name="tests/marc_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1c7e2fc5572a0f9362a771c260a1fe3" name="tests/marc_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="84f85ac7f8a2532e4e90ccde7764556a" name="tests/marc_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="889e5e906a97de7a0e94b0c5f30e70e7" name="tests/marc_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="be823dc8a8efb408de06371ab802efcc" name="tests/marc_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="af44490aafea44e5120f881cb81cdad9" name="tests/marc_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ac9f2a7aeb24900a11f5102744179ae3" name="tests/marc_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5e43eb5cddbb4f2bd0d6405cd95b80aa" name="tests/marc_010.phpt" role="test" />
   <file baseinstalldir="File" md5sum="2e1cd8509c0bf04ec77fc0f51375f611" name="tests/marc_011.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bc49ca48623102c8ac07679fa77a3dd9" name="tests/marc_012.phpt" role="test" />
   <file baseinstalldir="File" md5sum="245a3b20e0da1973535503e28efd1d3a" name="tests/marc_013.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ce69aa734856dd40d60d30c77bdef53a" name="tests/marc_014.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7b61cdd31035e60682fa92c5d519d997" name="tests/marc_015.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7f4f597fe1adaa3507eb87fc4875dbd2" name="tests/marc_016.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4262efd5fcacbd7503323681f4552430" name="tests/marc_017.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ee1623d7bda54ba4f741b2319b158f82" name="tests/marc_018.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8006c03fbab0f04377342086fafd3982" name="tests/marc_019.phpt" role="test" />
   <file baseinstalldir="File" md5sum="f5ae5b25e0ac1104314433d9e5b1f7fe" name="tests/marc_020.phpt" role="test" />
   <file baseinstalldir="File" md5sum="94d8f99e86585671a1b2d3043aeb6360" name="tests/marc_021.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bb891a890effe0e77e1759043f4846d8" name="tests/marc_022.phpt" role="test" />
   <file baseinstalldir="File" md5sum="faf77dcb5cdd002c09169a14bfded65e" name="tests/marc_023.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0e6c4a23f5da7df64fdd4b3b1149bbee" name="tests/marc_16783.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4ea8b3520beda378db15960f1c50493a" name="tests/marc_field_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="743850ef61df69c4340be44a03bccb5a" name="tests/marc_field_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8c765f1398b49df257d86d22ac6e4f8d" name="tests/marc_field_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d4216cf930a308e0d02553bd3914f294" name="tests/marc_field_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dd59514b474b78371ad522a3e13b76b7" name="tests/marc_field_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5295bfd02a8424acac1c91de26b552c7" name="tests/marc_field_21246.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6f95f09442ccf6b93df92986f58b270d" name="tests/marc_lint_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="18d721f8871edd925624ccbdd15444fb" name="tests/marc_lint_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4eb86a2f4e0a74dedcb0bf2511da6ca1" name="tests/marc_lint_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="10430fee0a1352d0528f1507b34c57e1" name="tests/marc_lint_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0dcd07a18577d7b22392a2214cd6436c" name="tests/marc_lint_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fd17798fc535562e5e64461f449516b2" name="tests/marc_record_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="141b455ccf67a60c4eac44c77960f2e2" name="tests/marc_subfield_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1e23464ee0eec47ddca2af9a9922926" name="tests/marc_subfield_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="1d7903e8c244d647220b318b4bc758d1" name="tests/marc_xml_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="22cae3c752d843b78f583dcd92801534" name="tests/marc_xml_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="c0716d23e0f960abf8d53ad6014a413a" name="tests/marc_xml_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7645fa19e28aca041a124fc5e2c12bd3" name="tests/marc_xml_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b08b28c3251625b8b6e4d7ab376b0185" name="tests/marc_xml_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6cd0934ddbf65d2d7e9ea5d108977ff7" name="tests/marc_xml_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ffdce4aa190268fa7cbbf3bb45383abf" name="tests/marc_xml_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="998a4c1ce00ff100f39ffa9fc49a212f" name="tests/marc_xml_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a38a67c590869f2b0a4859a910fd9e89" name="tests/marc_xml_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="db39c5055a570fcda12bb7c5fa1e3b4d" name="tests/marc_xml_16642.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dc075f4a271bd7182378a3874bd5b39e" name="tests/marc_xml_namespace.phpt" role="test" />
   <file baseinstalldir="File" md5sum="208200d9a979ac360c4d326e9789b6b7" name="tests/marc_xml_namespace_prefix.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d87774ede82222cfc12b2c2a06f57a3a" name="tests/marc_xml_rsinger.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fb44e3eb69f1a37115235fc829c39542" name="tests/namespace.xml" role="test" />
   <file baseinstalldir="File" md5sum="e6de4d809b0af5dd99fd352eb60616a1" name="tests/skipif.inc" role="test" />
   <file baseinstalldir="File" md5sum="a0166a4ff0bc0bb283e854f11beaa793" name="tests/music.mrc" role="test" />
   <file baseinstalldir="File" md5sum="993ce494befbc25dc1326527b30b4782" name="tests/music.xml" role="test" />
   <file baseinstalldir="File" md5sum="6b0c87f0cd459ed7322c25d403b164cc" name="tests/bigarchive.xml" role="test" />
   <file baseinstalldir="File" md5sum="be850aa6ab4ac52b8c6c214c30b574af" name="tests/onerecord.xml" role="test" />
   <file baseinstalldir="File" md5sum="4f43fec7b276267eec5258044853ccc8" name="tests/sandburg.mrc" role="test" />
   <file baseinstalldir="File" md5sum="e216b95f905dd240c9bde372950e4073" name="tests/sandburg.xml" role="test" />
   <file baseinstalldir="File" md5sum="e81a92188ea0dcd9c108a63fb32b3f4f" name="tests/xmlescape.mrc" role="test" />
   <file baseinstalldir="File" md5sum="8f9f63ed6a80191d89a2296fa4c1a30b" name="CHANGELOG" role="doc" />
   <file baseinstalldir="File" md5sum="fbc093901857fcd118f065f900982c24" name="LICENSE" role="doc" />
  </dir>
 </contents>
 <dependencies>
  <required>
   <php>
    <min>5.6</min>
   </php>
   <pearinstaller>
    <min>1.4.0</min>
   </pearinstaller>
  </required>
  <optional>
   <package>
    <name>Validate_ISPN</name>
    <channel>pear.php.net</channel>
   </package>
  </optional>
 </dependencies>
 <phprelease />
</package>
PKm�ZPi��.depdbnu�[���PKm�Z�{��
�Mail/null.phpnu�[���PKm�ZE@�%>>
Mail/sendmail.phpnu�[���PKm�Z��A~�{�{�;Mail/RFC822.phpnu�[���PKn�Z�+V����
[�Mail/mime.phpnu�[���PKn�Zx�ع���D�Mail/mimeDecode.phpnu�[���PKn�ZB�_Ǭ=�=
@(Mail/smtp.phpnu�[���PKn�ZwԐE;E;)fMail/smtpmx.phpnu�[���PKn�Z�؛�J�J���Mail/mimePart.phpnu�[���PKn�ZB��shh
8YMail/mock.phpnu�[���PKn�Z@iE�\\
�lMail/mail.phpnu�[���PKn�Zv�.locknu�[���PKn�Z�*�z%-%- ��Structures/LinkedList/Double.phpnu�[���PKn�Z����p:p:  �Structures/LinkedList/Single.phpnu�[���PKn�ZUyv���Structures/Graph.phpnu�[���PKn�Z�C� + +CStructures/Graph/Node.phpnu�[���PKn�Z9����,�1Structures/Graph/Manipulator/AcyclicTest.phpnu�[���PKn�Z~(�htt2�HStructures/Graph/Manipulator/TopologicalSorter.phpnu�[���PKn�Z�J�}
}
_dAuth/SASL/Anonymous.phpnu�[���PKn�ZP(~�T
T
#rAuth/SASL/CramMD5.phpnu�[���PKn�Z����==�Auth/SASL/Plain.phpnu�[���PKn�Z�<� OO<�Auth/SASL/Login.phpnu�[���PKn�Z%ׅtg!g!ΘAuth/SASL/DigestMD5.phpnu�[���PKn�Z�T�|�Auth/SASL/Common.phpnu�[���PKn�ZvR�r,,��Auth/SASL/External.phpnu�[���PKn�Zќ��0�0H�Auth/SASL/SCRAM.phpnu�[���PKn�Z2r����
�	Auth/SASL.phpnu�[���PKn�Z�T�,�,�OS/Guess.phpnu�[���PKn�Z�����KPEAR/Config.phpnu�[���PKn�Z�`�eEAEA
.ZPEAR/REST.phpnu�[���PKn�Z��ym6m6��PEAR/Exception.phpnu�[���PKn�Zr"����_�PEAR/ChannelFile.phpnu�[���PKn�Z��gk�U�U?�PEAR/Validate.phpnu�[���PKn�Zd֣S��u�PEAR/Command/Pickle.xmlnu�[���PKn�Z�z��k<k<W�PEAR/Command/Config.phpnu�[���PKn�Z݄<ii	1PEAR/Command/Mirror.xmlnu�[���PKn�Z,��t"u"u�3PEAR/Command/Remote.phpnu�[���PKn�Z
�\���"�PEAR/Command/Remote.xmlnu�[���PKn�Zj���!�!X�PEAR/Command/Install.xmlnu�[���PKo�Z�%q������PEAR/Command/Channels.phpnu�[���PKo�Znmi?;�;��[	PEAR/Command/Install.phpnu�[���PKo�Z�X�

#
PEAR/Command/Auth.phpnu�[���PKo�Z���s6
6
T-
PEAR/Command/Config.xmlnu�[���PKo�Z�%Fii�:
PEAR/Command/Test.xmlnu�[���PKo�ZZ h66A
PEAR/Command/Package.xmlnu�[���PKo�Z�w��zz�]
PEAR/Command/Channels.xmlnu�[���PKo�Z+9ҜҜ�n
PEAR/Command/Package.phpnu�[���PKo�Z
u����PEAR/Command/Build.xmlnu�[���PKo�Z������
PEAR/Command/Mirror.phpnu�[���PKp�Z,_�h/h/�PEAR/Command/Test.phpnu�[���PKp�Z�%sp  6OPEAR/Command/Common.phpnu�[���PKp�Z0(;rʹʹ�oPEAR/Command/Registry.phpnu�[���PKp�Z�4�{���$PEAR/Command/Auth.xmlnu�[���PKp�Z��#S
S
�)PEAR/Command/Build.phpnu�[���PKp�Z���u��S4PEAR/Command/Registry.xmlnu�[���PKp�Z�P>>�;PEAR/Command/Pickle.phpnu�[���PKp�Z��T�I�I�yPEAR/Builder.phpnu�[���PKp�Z[
�W��3�PEAR/XMLParser.phpnu�[���PKp�Zl(e���t�PEAR/Downloader.phpnu�[���PKp�Z�b������
PEAR/ErrorStack.phpnu�[���PKp�Z(Pz����ePEAR/Proxy.phpnu�[���PKp�Z��'����|PEAR/RunTest.phpnu�[���PKq�Zj�y99�	PEAR/Validator/PECL.phpnu�[���PKq�Zp�����aPEAR/Dependency2.phpnu�[���PKq�Z��wv@@��PEAR/PackageFile/v2.phpnu�[���PKq�ZC�8�L�L!:�PEAR/PackageFile/v2/Validator.phpnu�[���PKq�Z���=_�_�6PEAR/PackageFile/v2/rw.phpnu�[���PKq�Z�5�������,PEAR/PackageFile/v1.phpnu�[���PKq�Z�ɁɁ!��PEAR/PackageFile/Generator/v2.phpnu�[���PKq�Z`�=����!�tPEAR/PackageFile/Generator/v1.phpnu�[���PKr�Z��OWHH�9PEAR/PackageFile/Parser/v2.phpnu�[���PKr�Z�_=�@�@`FPEAR/PackageFile/Parser/v1.phpnu�[���PKr�Zc��__5�PEAR/DependencyDB.phpnu�[���PKr�Z�@P��{�PEAR/ChannelFile/Parser.phpnu�[���PKr�Z��_�0�0r�PEAR/Command.phpnu�[���PKr�Z�ٲ�=�==PEAR/PackageFile.phpnu�[���PKr�Z�JD��g\PEAR/Task/Replace.phpnu�[���PKr�Z&%75))�wPEAR/Task/Windowseol/rw.phpnu�[���PKr�Z�3}}PEAR/Task/Replace/rw.phpnu�[���PKr�Z&
i."x�PEAR/Task/Postinstallscript/rw.phpnu�[���PKr�Z�-!�PEAR/Task/Common.phpnu�[���PKr�ZD$���I�PEAR/Task/Windowseol.phpnu�[���PKr�ZZ�E�x9x9��PEAR/Task/Postinstallscript.phpnu�[���PKr�Z\k��K�PEAR/Task/Unixeol/rw.phpnu�[���PKr�Z�������PEAR/Task/Unixeol.phpnu�[���PKr�Z�W�f���PEAR/REST/10.phpnu�[���PKr�Z��Y�;;ąPEAR/REST/13.phpnu�[���PKr�Z,#y��+�+�PEAR/REST/11.phpnu�[���PKr�Z��U  D�PEAR/Packager.phpnu�[���PKr�ZZ�bgbg�PEAR/Common.phpnu�[���PKr�Z$���(�(FsPEAR/Registry.phpnu�[���PKr�Z��	MdMd?�PEAR/Frontend/CLI.phpnu�[���PKr�Z��

�PEAR/Installer/Role/Doc.phpnu�[���PKr�Z��/��)PEAR/Installer/Role/Cfg.xmlnu�[���PKr�Z>1H���PEAR/Installer/Role/Www.xmlnu�[���PKr�Z�?m

PEAR/Installer/Role/Php.phpnu�[���PKr�Z*Y|	%%`PEAR/Installer/Role/Man.phpnu�[���PKr�Z���BB�PEAR/Installer/Role/Ext.xmlnu�[���PKr�Zp��""]PEAR/Installer/Role/Src.xmlnu�[���PKr�Zh&P*���PEAR/Installer/Role/Doc.xmlnu�[���PKr�ZB] ���PEAR/Installer/Role/Test.xmlnu�[���PKr�Zz�q����PEAR/Installer/Role/Php.xmlnu�[���PKr�Z	��
|PEAR/Installer/Role/Data.phpnu�[���PKs�Z�0�c���PEAR/Installer/Role/Man.xmlnu�[���PKs�Z��K

�PEAR/Installer/Role/Ext.phpnu�[���PKs�ZY��� PEAR/Installer/Role/Test.phpnu�[���PKs�Z@v�а�z#PEAR/Installer/Role/Script.xmlnu�[���PKs�Zf�sz��x%PEAR/Installer/Role/Data.xmlnu�[���PKs�Z?���GGV'PEAR/Installer/Role/Common.phpnu�[���PKs�Z�^D{		�?PEAR/Installer/Role/Www.phpnu�[���PKs�Z�Ƥ?CPEAR/Installer/Role/Cfg.phpnu�[���PKs�Z��[�	SPEAR/Installer/Role/Script.phpnu�[���PKs�Z��srrjVPEAR/Installer/Role/Src.phpnu�[���PKs�ZV�Z���'ZPEAR/Installer/Role.phpnu�[���PKs�Z�{�	�)�)*yPEAR/Downloader/Package.phpnu�[���PKs�Z.�4���$�PEAR/Frontend.phpnu�[���PKs�Z،�w��_�PEAR/Installer.phpnu�[���PKs�ZXxo��-j�Symfony/Bridge/Doctrine/Logger/DbalLogger.phpnu�[���PKs�Ze�OO&b�Symfony/Bridge/Doctrine/autoloader.phpnu�[���PKs�Z��X+��8�Symfony/Bridge/Doctrine/CacheWarmer/ProxyCacheWarmer.phpnu�[���PKs�Z	�9,��5i�Symfony/Bridge/Doctrine/Form/DoctrineOrmExtension.phpnu�[���PKs�Z�0���NX�Symfony/Bridge/Doctrine/Form/EventListener/MergeDoctrineCollectionListener.phpnu�[���PKs�Z!%d==A��Symfony/Bridge/Doctrine/Form/ChoiceList/EntityLoaderInterface.phpnu�[���PKs�Z�	?x�7�7<4�Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.phpnu�[���PKs�ZGC�t��A<-Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.phpnu�[���PKs�Z`.
qpp7�9Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.phpnu�[���PKs�ZCi�PPMZQSymfony/Bridge/Doctrine/Form/DataTransformer/CollectionToArrayTransformer.phpnu�[���PKs�Z憝��0'YSymfony/Bridge/Doctrine/Form/Type/EntityType.phpnu�[���PKs�ZS;,:��2-]Symfony/Bridge/Doctrine/Form/Type/DoctrineType.phpnu�[���PKs�ZW&v��<�wSymfony/Bridge/Doctrine/Security/User/EntityUserProvider.phpnu�[���PKs�Z�����Et�Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.phpnu�[���PKs�Z(��y��9�Symfony/Bridge/Doctrine/Validator/DoctrineInitializer.phpnu�[���PKs�ZQГ��>�Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.phpnu�[���PKs�Z:�d�G5�Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.phpnu�[���PKs�Z�Ta�==B��Symfony/Bridge/Doctrine/ExpressionLanguage/DoctrineParserCache.phpnu�[���PKs�Z��qm
m
-m�Symfony/Bridge/Doctrine/RegistryInterface.phpnu�[���PKs�Zlf/�qq=7�Symfony/Bridge/Doctrine/DataFixtures/ContainerAwareLoader.phpnu�[���PKs�Z����=�Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.phpnu�[���PKs�Z�����C��Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerSchema.phpnu�[���PKs�ZOlQ�996��Symfony/Bridge/Doctrine/ContainerAwareEventManager.phpnu�[���PKs�Z؈����3D�Symfony/Bridge/Doctrine/Test/DoctrineTestHelper.phpnu�[���PKs�Z̳֨�+��Symfony/Bridge/Doctrine/ManagerRegistry.phpnu�[���PKs�Z+çxAA?�Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.phpnu�[���PKs�Z*�+��J�JIBSymfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.phpnu�[���PKs�Z���*��SVaSymfony/Bridge/Doctrine/DependencyInjection/Security/UserProvider/EntityFactory.phpnu�[���PKs�Z��㛕�Q�hSymfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterMappingsPass.phpnu�[���PKs�Z~�YAAeԀSymfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.phpnu�[���PKs�Z��,���S��Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/DoctrineValidationPass.phpnu�[���PKs�Z��4NN%,�Symfony/Bridge/Monolog/autoloader.phpnu�[���PKs�Z��մ��1ϡSymfony/Bridge/Monolog/Handler/FirePHPHandler.phpnu�[���PKs�Z��Zv��/©Symfony/Bridge/Monolog/Handler/DebugHandler.phpnu�[���PKs�Z�y���1دSymfony/Bridge/Monolog/Handler/ConsoleHandler.phpnu�[���PKs�Z��*vv5�Symfony/Bridge/Monolog/Handler/SwiftMailerHandler.phpnu�[���PKs�Z���"II3��Symfony/Bridge/Monolog/Handler/ChromePhpHandler.phpnu�[���PKs�Z��;��	�	!��Symfony/Bridge/Monolog/Logger.phpnu�[���PKs�Z��b115��Symfony/Bridge/Monolog/Formatter/ConsoleFormatter.phpnu�[���PKt�Z�,��1l�Symfony/Bridge/Monolog/Processor/WebProcessor.phpnu�[���PKt�Z�$�KK"l�Symfony/Bridge/Twig/autoloader.phpnu�[���PKt�Z�)�UU1	�Symfony/Bridge/Twig/Translation/TwigExtractor.phpnu�[���PKt�Z6DZ77*��Symfony/Bridge/Twig/Node/StopwatchNode.phpnu�[���PKt�Z,
�@��5P�Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.phpnu�[���PKt�Z�
�s>>*ESymfony/Bridge/Twig/Node/FormThemeNode.phpnu�[���PKt�ZP�IAA3�Symfony/Bridge/Twig/Node/TransDefaultDomainNode.phpnu�[���PKt�Z�U,tt,�Symfony/Bridge/Twig/Node/FormEnctypeNode.phpnu�[���PKt�Zʦ\�G
G
&QSymfony/Bridge/Twig/Node/TransNode.phpnu�[���PKt�Z���^��,�%Symfony/Bridge/Twig/Node/RenderBlockNode.phpnu�[���PKt�Z�vq�)+Symfony/Bridge/Twig/Form/TwigRenderer.phpnu�[���PKt�Zb�3�}}8q1Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.phpnu�[���PKt�Z��Qkk2V4Symfony/Bridge/Twig/Form/TwigRendererInterface.phpnu�[���PKt�Z��<��/#7Symfony/Bridge/Twig/Form/TwigRendererEngine.phpnu�[���PKt�Z�GTSymfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.phpnu�[���PKt�Z�)�[n	n	)�`Symfony/Bridge/Twig/NodeVisitor/Scope.phpnu�[���PKt�Z�tA�:`jSymfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.phpnu�[���PKt�Z��9292B�xSymfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twignu�[���PKt�Z��[[Dy�Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twignu�[���PKt�Z.��8H�Symfony/Bridge/Twig/TokenParser/StopwatchTokenParser.phpnu�[���PKt�Z�%]�
�
4��Symfony/Bridge/Twig/TokenParser/TransTokenParser.phpnu�[���PKt�Z�/�	�	:��Symfony/Bridge/Twig/TokenParser/TransChoiceTokenParser.phpnu�[���PKt�Z>����8>�Symfony/Bridge/Twig/TokenParser/FormThemeTokenParser.phpnu�[���PKt�Zʶ�̭�Ao�Symfony/Bridge/Twig/TokenParser/TransDefaultDomainTokenParser.phpnu�[���PKt�Z�9�=KK/��Symfony/Bridge/Twig/Extension/FormExtension.phpnu�[���PKt�Z��|/7�Symfony/Bridge/Twig/Extension/YamlExtension.phpnu�[���PKt�Z��&�a
a
5��Symfony/Bridge/Twig/Extension/HttpKernelExtension.phpnu�[���PKt�ZKΙ���5v�Symfony/Bridge/Twig/Extension/ExpressionExtension.phpnu�[���PKt�Z`�fS..2� Symfony/Bridge/Twig/Extension/RoutingExtension.phpnu�[���PKt�Z�5��mm4] Symfony/Bridge/Twig/Extension/StopwatchExtension.phpnu�[���PKt�Z�?���6. Symfony/Bridge/Twig/Extension/TranslationExtension.phpnu�[���PKt�Zd���oo3�! Symfony/Bridge/Twig/Extension/SecurityExtension.phpnu�[���PKt�Z�����/a' Symfony/Bridge/Twig/Extension/CodeExtension.phpnu�[���PKu�Z^D��dd"sG Symfony/Bridge/Twig/TwigEngine.phpnu�[���PKu�Z�4˵��()V Symfony/Component/Finder/Shell/Shell.phpnu�[���PKu�Z5��K��*^ Symfony/Component/Finder/Shell/Command.phpnu�[���PKu�Z�5�9(�v Symfony/Component/Finder/SplFileInfo.phpnu�[���PKu�Z%uM�PP'X~ Symfony/Component/Finder/autoloader.phpnu�[���PKu�Z��99C� Symfony/Component/Finder/Exception/ShellCommandFailureException.phpnu�[���PKu�Z�7��9�� Symfony/Component/Finder/Exception/ExceptionInterface.phpnu�[���PKu�Z�cWޫ�<� Symfony/Component/Finder/Exception/AccessDeniedException.phpnu�[���PKu�Z>�@��>� Symfony/Component/Finder/Exception/AdapterFailureException.phpnu�[���PKu�ZP�����D	� Symfony/Component/Finder/Exception/OperationNotPermitedException.phpnu�[���PKu�Z��� ��6� Symfony/Component/Finder/Comparator/DateComparator.phpnu�[���PKu�Z|F�z

2?� Symfony/Component/Finder/Comparator/Comparator.phpnu�[���PKu�Z�P�

8�� Symfony/Component/Finder/Comparator/NumberComparator.phpnu�[���PKu�Z�g@Mbb!2� Symfony/Component/Finder/Glob.phpnu�[���PKu�Z�d�V�V#� Symfony/Component/Finder/Finder.phpnu�[���PKu�Zils_��>
!Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.phpnu�[���PKu�Z��ɔ�
�
7u!Symfony/Component/Finder/Iterator/FilePathsIterator.phpnu�[���PKu�Z�,G��4n!Symfony/Component/Finder/Iterator/FilterIterator.phpnu�[���PKu�Z�ʽ���?q#!Symfony/Component/Finder/Iterator/FilecontentFilterIterator.phpnu�[���PKu�Z�

���@~+!Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.phpnu�[���PKu�Z��z":�2!Symfony/Component/Finder/Iterator/CustomFilterIterator.phpnu�[���PKu�Z{�^ǽ�<N9!Symfony/Component/Finder/Iterator/FilenameFilterIterator.phpnu�[���PKu�Z�d����Dw@!Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.phpnu�[���PKu�Zx�P���=�F!Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.phpnu�[���PKu�Z ��U��=�L!Symfony/Component/Finder/Iterator/DateRangeFilterIterator.phpnu�[���PKu�Z�n bb<�R!Symfony/Component/Finder/Iterator/FileTypeFilterIterator.phpnu�[���PKu�Z��j��	�	6�X!Symfony/Component/Finder/Iterator/SortableIterator.phpnu�[���PKu�Z���)��8�b!Symfony/Component/Finder/Iterator/PathFilterIterator.phpnu�[���PKu�Z�6s��@�j!Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.phpnu�[���PKu�Z��&
&
2Gw!Symfony/Component/Finder/Expression/Expression.phpnu�[���PKu�Z�"HH6ρ!Symfony/Component/Finder/Expression/ValueInterface.phpnu�[���PKu�Z�E�,}�!Symfony/Component/Finder/Expression/Glob.phpnu�[���PKu�Z��(�-�!Symfony/Component/Finder/Expression/Regex.phpnu�[���PKu�Z9!�2{
{
/D�!Symfony/Component/Finder/Adapter/PhpAdapter.phpnu�[���PKu�Z����5�!Symfony/Component/Finder/Adapter/AdapterInterface.phpnu�[���PKu�Z��kA�
�
34�!Symfony/Component/Finder/Adapter/BsdFindAdapter.phpnu�[���PKu�Z�}]�
�
3��!Symfony/Component/Finder/Adapter/GnuFindAdapter.phpnu�[���PKu�ZQJ)�)8��!Symfony/Component/Finder/Adapter/AbstractFindAdapter.phpnu�[���PKu�Z�	4�"Symfony/Component/Finder/Adapter/AbstractAdapter.phpnu�[���PKu�Z����:;"Symfony/Component/Translation/Extractor/ChainExtractor.phpnu�[���PKu�ZArP�>%"Symfony/Component/Translation/Extractor/ExtractorInterface.phpnu�[���PKu�Zb*0�oo4�#"Symfony/Component/Translation/PluralizationRules.phpnu�[���PKu�Z�q��UU,<"Symfony/Component/Translation/autoloader.phpnu�[���PKu�Z�<qNN10>"Symfony/Component/Translation/MessageSelector.phpnu�[���PKu�Z�س��:�J"Symfony/Component/Translation/Catalogue/MergeOperation.phpnu�[���PKu�ZY[�>*P"Symfony/Component/Translation/Catalogue/OperationInterface.phpnu�[���PKu�Z��fb�
�
=�U"Symfony/Component/Translation/Catalogue/AbstractOperation.phpnu�[���PKu�Z��ӄ�9�c"Symfony/Component/Translation/Catalogue/DiffOperation.phpnu�[���PKu�Z�6�"��>�i"Symfony/Component/Translation/Exception/ExceptionInterface.phpnu�[���PKu�ZDŽ���D�k"Symfony/Component/Translation/Exception/InvalidResourceException.phpnu�[���PKv�Z�2B��E2n"Symfony/Component/Translation/Exception/NotFoundResourceException.phpnu�[���PKv�Z�y4��2�p"Symfony/Component/Translation/MessageCatalogue.phpnu�[���PKv�Z%�Mt8��"Symfony/Component/Translation/MetadataAwareInterface.phpnu�[���PKv�Z�d�<<4��"Symfony/Component/Translation/IdentityTranslator.phpnu�[���PKv�Z�e�G��,��"Symfony/Component/Translation/Translator.phpnu�[���PKv�Z��֛�;u�"Symfony/Component/Translation/MessageCatalogueInterface.phpnu�[���PKv�ZM�
���9{�"Symfony/Component/Translation/Dumper/IcuResFileDumper.phpnu�[���PKv�Zਪ(5u�"Symfony/Component/Translation/Dumper/PoFileDumper.phpnu�[���PKv�Z���%LL6��"Symfony/Component/Translation/Dumper/PhpFileDumper.phpnu�[���PKv�Z�<̧��8��"Symfony/Component/Translation/Dumper/XliffFileDumper.phpnu�[���PKv�Z>{GG5��"Symfony/Component/Translation/Dumper/QtFileDumper.phpnu�[���PKv�Z���667Z�"Symfony/Component/Translation/Dumper/YamlFileDumper.phpnu�[���PKv�ZoB���6��"Symfony/Component/Translation/Dumper/CsvFileDumper.phpnu�[���PKv�ZB^�[[3*�"Symfony/Component/Translation/Dumper/FileDumper.phpnu�[���PKv�Z�:$}}7�"Symfony/Component/Translation/Dumper/JsonFileDumper.phpnu�[���PKv�Z&X����6�#Symfony/Component/Translation/Dumper/IniFileDumper.phpnu�[���PKv�Z��<**8
#Symfony/Component/Translation/Dumper/DumperInterface.phpnu�[���PKv�Z����A	A	5�#Symfony/Component/Translation/Dumper/MoFileDumper.phpnu�[���PKv�Zg�?Z�
�
*B#Symfony/Component/Translation/Interval.phpnu�[���PKv�Z�3����5�#Symfony/Component/Translation/TranslatorInterface.phpnu�[���PKv�ZP�?�}}:�%#Symfony/Component/Translation/Writer/TranslationWriter.phpnu�[���PKv�ZN@���6�-#Symfony/Component/Translation/Loader/IniFileLoader.phpnu�[���PKv�Z�T�93#Symfony/Component/Translation/Loader/IcuDatFileLoader.phpnu�[���PKv�ZCS�z
z
9�9#Symfony/Component/Translation/Loader/IcuResFileLoader.phpnu�[���PKv�Z��v���5�D#Symfony/Component/Translation/Loader/MoFileLoader.phpnu�[���PKv�ZR����4&\#Symfony/Component/Translation/Loader/ArrayLoader.phpnu�[���PKv�Z�'s�u	u	7&d#Symfony/Component/Translation/Loader/JsonFileLoader.phpnu�[���PKv�Z�i�3"
"
6n#Symfony/Component/Translation/Loader/CsvFileLoader.phpnu�[���PKv�Z_��BB8�x#Symfony/Component/Translation/Loader/XliffFileLoader.phpnu�[���PKv�Zl#�tt84�#Symfony/Component/Translation/Loader/LoaderInterface.phpnu�[���PKv�Z�*���5�#Symfony/Component/Translation/Loader/PoFileLoader.phpnu�[���PKv�Z�r��;;6o�#Symfony/Component/Translation/Loader/PhpFileLoader.phpnu�[���PKv�Z:�	Z�"�"B�#Symfony/Component/Translation/Loader/schema/dic/xliff-core/xml.xsdnu�[���PKv�Z�xO��T�#Symfony/Component/Translation/Loader/schema/dic/xliff-core/xliff-core-1.2-strict.xsdnu�[���PKv�Z)-d+�	�	5�g%Symfony/Component/Translation/Loader/QtFileLoader.phpnu�[���PKv�Z:����7�q%Symfony/Component/Translation/Loader/YamlFileLoader.phpnu�[���PKw�Z�V�˽�.-z%Symfony/Component/Routing/Annotation/Route.phpnu�[���PKw�Z�<ѹ�+H�%Symfony/Component/Routing/CompiledRoute.phpnu�[���PKw�ZU8���-\�%Symfony/Component/Routing/RouterInterface.phpnu�[���PKw�ZU�cQQ(>�%Symfony/Component/Routing/autoloader.phpnu�[���PKw�Z����'�'+�%Symfony/Component/Routing/RouteCompiler.phpnu�[���PKw�Z��%�%$�%Symfony/Component/Routing/Router.phpnu�[���PKw�Z���q
q
6n�%Symfony/Component/Routing/Matcher/ApacheUrlMatcher.phpnu�[���PKw�Z	�ڗ9E�%Symfony/Component/Routing/Matcher/UrlMatcherInterface.phpnu�[���PKw�Z`�u���=��%Symfony/Component/Routing/Matcher/RequestMatcherInterface.phpnu�[���PKw�Z[z�dd<�&Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.phpnu�[���PKw�Z?�|{��:�&Symfony/Component/Routing/Matcher/Dumper/MatcherDumper.phpnu�[���PKw�Z�x}�44=�&Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.phpnu�[���PKw�Z�bz#z#@A&Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.phpnu�[���PKw�Z�`=e&Symfony/Component/Routing/Matcher/Dumper/DumperCollection.phpnu�[���PKw�Z�N�
�
C�s&Symfony/Component/Routing/Matcher/Dumper/DumperPrefixCollection.phpnu�[���PKw�Z(� ���C�~&Symfony/Component/Routing/Matcher/Dumper/MatcherDumperInterface.phpnu�[���PKw�ZY�IWW8��&Symfony/Component/Routing/Matcher/Dumper/DumperRoute.phpnu�[���PKw�Z�'��9��&Symfony/Component/Routing/Matcher/TraceableUrlMatcher.phpnu�[���PKw�ZGj�C""0��&Symfony/Component/Routing/Matcher/UrlMatcher.phpnu�[���PKw�Z� ��ffE'�&Symfony/Component/Routing/Matcher/RedirectableUrlMatcherInterface.phpnu�[���PKw�Z����==K�&Symfony/Component/Routing/Exception/MissingMandatoryParametersException.phpnu�[���PKw�Zj`j�A��&Symfony/Component/Routing/Exception/InvalidParameterException.phpnu�[���PKw�Znj�W��>/�&Symfony/Component/Routing/Exception/RouteNotFoundException.phpnu�[���PKw�Z��)���:��&Symfony/Component/Routing/Exception/ExceptionInterface.phpnu�[���PKw�Z����JJA��&Symfony/Component/Routing/Exception/MethodNotAllowedException.phpnu�[���PKw�Z?�]�//Af�&Symfony/Component/Routing/Exception/ResourceNotFoundException.phpnu�[���PKw�Z��^�==#�&Symfony/Component/Routing/Route.phpnu�[���PKw�Zr�����:i	'Symfony/Component/Routing/RequestContextAwareInterface.phpnu�[���PKw�Z|,{Ȫ�-p'Symfony/Component/Routing/RouteCollection.phpnu�[���PKw�Z�h�,w)'Symfony/Component/Routing/RequestContext.phpnu�[���PKw�Zմ���I�C'Symfony/Component/Routing/Generator/ConfigurableRequirementsInterface.phpnu�[���PKw�Z�
��1�148M'Symfony/Component/Routing/Generator/UrlGenerator.phpnu�[���PKw�Z�1O�
�
Az'Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.phpnu�[���PKw�Zu�'��>��'Symfony/Component/Routing/Generator/Dumper/GeneratorDumper.phpnu�[���PKw�Z�4��G��'Symfony/Component/Routing/Generator/Dumper/GeneratorDumperInterface.phpnu�[���PKw�Z����@@=�'Symfony/Component/Routing/Generator/UrlGeneratorInterface.phpnu�[���PKw�Zn���hh2Ȥ'Symfony/Component/Routing/Loader/ClosureLoader.phpnu�[���PKw�Z��?�		>��'Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.phpnu�[���PKw�Z~ޟ
�
9�'Symfony/Component/Routing/Loader/AnnotationFileLoader.phpnu�[���PKw�Z~L�W��:�'Symfony/Component/Routing/Loader/AnnotationClassLoader.phpnu�[���PKw�ZP�i{��2��'Symfony/Component/Routing/Loader/PhpFileLoader.phpnu�[���PKw�Z?-[��	�	?5�'Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsdnu�[���PKw�Zأ2D$D$2L�'Symfony/Component/Routing/Loader/XmlFileLoader.phpnu�[���PKw�ZpB�Q Q 3�(Symfony/Component/Routing/Loader/YamlFileLoader.phpnu�[���PKx�ZqF��>>4�5(Symfony/Component/Routing/RouteCompilerInterface.phpnu�[���PKx�Z0���QQ(H9(Symfony/Component/Process/autoloader.phpnu�[���PKx�Zg��'�'*�:(Symfony/Component/Process/ProcessPipes.phpnu�[���PKx�Z��2�{{@6c(Symfony/Component/Process/Exception/ProcessTimedOutException.phpnu�[���PKx�Z�<���:!j(Symfony/Component/Process/Exception/ExceptionInterface.phpnu�[���PKx�Z>H����8:l(Symfony/Component/Process/Exception/RuntimeException.phpnu�[���PKx�Z��W��6�n(Symfony/Component/Process/Exception/LogicException.phpnu�[���PKx�Z˅����@�p(Symfony/Component/Process/Exception/InvalidArgumentException.phpnu�[���PKx�Z��_��>s(Symfony/Component/Process/Exception/ProcessFailedException.phpnu�[���PKx�Z@s�(�x(Symfony/Component/Process/PhpProcess.phpnu�[���PKx�Z�nL	L	*�(Symfony/Component/Process/ProcessUtils.phpnu�[���PKy�Z�!,$

.��(Symfony/Component/Process/ExecutableFinder.phpnu�[���PKy�Z!/���,�(Symfony/Component/Process/ProcessBuilder.phpnu�[���PKy�Zy>�8��1�(Symfony/Component/Process/PhpExecutableFinder.phpnu�[���PKy�Z��M��%ު(Symfony/Component/Process/Process.phpnu�[���PKy�Z[i55ERA)Symfony/Component/Serializer/Normalizer/SerializerAwareNormalizer.phpnu�[���PKy�Z=Vxe::A�D)Symfony/Component/Serializer/Normalizer/NormalizableInterface.phpnu�[���PKy�Z��SVV<�J)Symfony/Component/Serializer/Normalizer/CustomNormalizer.phpnu�[���PKy�Z��,,BiR)Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.phpnu�[���PKy�Z"p�yy?q)Symfony/Component/Serializer/Normalizer/NormalizerInterface.phpnu�[���PKy�Z�qU���C�u)Symfony/Component/Serializer/Normalizer/DenormalizableInterface.phpnu�[���PKz�Z���A�{)Symfony/Component/Serializer/Normalizer/DenormalizerInterface.phpnu�[���PKz�Z���OO9t�)Symfony/Component/Serializer/SerializerAwareInterface.phpnu�[���PKz�Z��TT+,�)Symfony/Component/Serializer/autoloader.phpnu�[���PKz�Zx蕰

4ۅ)Symfony/Component/Serializer/SerializerInterface.phpnu�[���PKz�Z,�c��9L�)Symfony/Component/Serializer/Encoder/EncoderInterface.phpnu�[���PKz�Z��[�5�53i�)Symfony/Component/Serializer/Encoder/XmlEncoder.phpnu�[���PKz�Z�<=ggD��)Symfony/Component/Serializer/Encoder/NormalizationAwareInterface.phpnu�[���PKz�ZV��O��5��)Symfony/Component/Serializer/Encoder/ChainDecoder.phpnu�[���PKz�Z�=��?��)Symfony/Component/Serializer/Encoder/SerializerAwareEncoder.phpnu�[���PKz�Zv:�hh3[�)Symfony/Component/Serializer/Encoder/JsonEncode.phpnu�[���PKz�Z��@���3&�)Symfony/Component/Serializer/Encoder/JsonDecode.phpnu�[���PKz�ZS R�	�	5q�)Symfony/Component/Serializer/Encoder/ChainEncoder.phpnu�[���PKz�Z�o�vv4��)Symfony/Component/Serializer/Encoder/JsonEncoder.phpnu�[���PKz�Z|ͼ���9��)Symfony/Component/Serializer/Encoder/DecoderInterface.phpnu�[���PKz�ZA�A
��4�*Symfony/Component/Serializer/Exception/Exception.phpnu�[���PKz�Z�^L��?�*Symfony/Component/Serializer/Exception/UnsupportedException.phpnu�[���PKz�Z�h=��;�*Symfony/Component/Serializer/Exception/RuntimeException.phpnu�[���PKz�ZJ���9�*Symfony/Component/Serializer/Exception/LogicException.phpnu�[���PKz�ZT��Y��C	*Symfony/Component/Serializer/Exception/InvalidArgumentException.phpnu�[���PKz�Z[�����Ci*Symfony/Component/Serializer/Exception/UnexpectedValueException.phpnu�[���PKz�Zʪ2/&/&+�
*Symfony/Component/Serializer/Serializer.phpnu�[���PKz�ZFP�PP'<4*Symfony/Component/Locale/autoloader.phpnu�[���PKz�Z�Q�UUL�5*Symfony/Component/Locale/Exception/MethodArgumentNotImplementedException.phpnu�[���PKz�Z��E>�9*Symfony/Component/Locale/Exception/NotImplementedException.phpnu�[���PKz�ZS�?a%%D#=*Symfony/Component/Locale/Exception/MethodNotImplementedException.phpnu�[���PKz�Z���ssQ�@*Symfony/Component/Locale/Exception/MethodArgumentValueNotImplementedException.phpnu�[���PKz�Z�C��*�D*Symfony/Component/Locale/Stub/StubIntl.phpnu�[���PKz�Z&�����5�G*Symfony/Component/Locale/Stub/StubNumberFormatter.phpnu�[���PKz�Zv/�@�J*Symfony/Component/Locale/Stub/DateFormat/Hour2401Transformer.phpnu�[���PKz�Z��S@PN*Symfony/Component/Locale/Stub/DateFormat/TimeZoneTransformer.phpnu�[���PKz�Z}��""A�Q*Symfony/Component/Locale/Stub/DateFormat/DayOfYearTransformer.phpnu�[���PKz�Z�X�<oU*Symfony/Component/Locale/Stub/DateFormat/AmPmTransformer.phpnu�[���PKz�Z���<�X*Symfony/Component/Locale/Stub/DateFormat/YearTransformer.phpnu�[���PKz�Zmў?O\*Symfony/Component/Locale/Stub/DateFormat/QuarterTransformer.phpnu�[���PKz�Zg[ep>�_*Symfony/Component/Locale/Stub/DateFormat/MinuteTransformer.phpnu�[���PKz�Z:6""ARc*Symfony/CoPK��Zb'��:+:+.registry/mail_mimedecode.regnu�[���PK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype dePK��Zm��II.registry/net_smtp.regnu�[���PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
  PK��Z��=.registry/net_idna2.regnu�[���PK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        casePK��Zl���.�.�.registry/mail_mime.regnu�[���PK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUri   URI of the namespace
     * @param bool   $multiline      whether to create a multiline tag where each
     *                               attribute gets written to a single line
     * @param string $indent         string used to indent attributes (_auto indents
     *                               attributes so they start at the same column)
     * @param string $linebreak      string used for linebreaks
     * @param bool   $sortAttributes Whether to sort the attributes or not
     *
     * @return string XML start element
     * @see    createEndElement(), createTag()
     */
    public static function createStartElement(
        $qname, $attributes = array(), $namespaceUri = null,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true
    ) {
        // if no attributes hav been set, use empty attributes
        if (!isset($attributes) || !is_array($attributes)) {
            $attributes = array();
        }

        if ($namespaceUri != null) {
            $parts = XML_Util::splitQualifiedName($qname);
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($qname)+2));
            }
        }

        if ($namespaceUri != null) {
            // is a namespace given
            if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
            } else {
                // define this Uri as the default namespace
                $attributes['xmlns'] = $namespaceUri;
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $attributes, $sortAttributes,
            $multiline, $indent, $linebreak
        );
        $element = sprintf('<%s%s>', $qname, $attList);
        return  $element;
    }

    /**
     * Create an end element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createEndElement('myNs:myTag');
     * </code>
     *
     * @param string $qname qualified tagname (including namespace)
     *
     * @return string XML end element
     * @see    createStartElement(), createTag()
     */
    public static function createEndElement($qname)
    {
        $element = sprintf('</%s>', $qname);
        return $element;
    }

    /**
     * Create an XML comment
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createComment('I am a comment');
     * </code>
     *
     * @param string $content content of the comment
     *
     * @return string XML comment
     */
    public static function createComment($content)
    {
        $comment = sprintf('<!-- %s -->', $content);
        return $comment;
    }

    /**
     * Create a CData section
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create a CData section
     * $tag = XML_Util::createCDataSection('I am content.');
     * </code>
     *
     * @param string $data data of the CData section
     *
     * @return string CData section with content
     */
    public static function createCDataSection($data)
    {
        return sprintf(
            '<![CDATA[%s]]>',
            preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data))
        );
    }

    /**
     * Split qualified name and return namespace and local part
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // split qualified tag
     * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
     * </code>
     * the returned array will contain two elements:
     * <pre>
     * array(
     *     'namespace' => 'xslt',
     *     'localPart' => 'stylesheet'
     * );
     * </pre>
     *
     * @param string $qname     qualified tag name
     * @param string $defaultNs default namespace (optional)
     *
     * @return array array containing namespace and local part
     */
    public static function splitQualifiedName($qname, $defaultNs = null)
    {
        if (strstr($qname, ':')) {
            $tmp = explode(':', $qname);
            return array(
                'namespace' => $tmp[0],
                'localPart' => $tmp[1]
            );
        }
        return array(
            'namespace' => $defaultNs,
            'localPart' => $qname
        );
    }

    /**
     * Check, whether string is valid XML name
     *
     * <p>XML names are used for tagname, attribute names and various
     * other, lesser known entities.</p>
     * <p>An XML name may only consist of alphanumeric characters,
     * dashes, undescores and periods, and has to start with a letter
     * or an underscore.</p>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // verify tag name
     * $result = XML_Util::isValidName('invalidTag?');
     * if (is_a($result, 'PEAR_Error')) {
     *    print 'Invalid XML name: ' . $result->getMessage();
     * }
     * </code>
     *
     * @param string $string string that should be checked
     *
     * @return mixed true, if string is a valid XML name, PEAR error otherwise
     *
     * @todo support for other charsets
     * @todo PEAR CS - unable to avoid 85-char limit on second preg_match
     */
    public static function isValidName($string)
    {
        // check for invalid chars
        if (!is_string($string) || !strlen($string) || !preg_match('/^[[:alpha:]_]\\z/', $string[0])) {
            return XML_Util::raiseError(
                'XML names may only start with letter or underscore',
                XML_UTIL_ERROR_INVALID_START
            );
        }

        // check for invalid chars
        $match = preg_match(
            '/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?'
            . '[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/',
            $string
        );
        if (!$match) {
            return XML_Util::raiseError(
                'XML names may only contain alphanumeric '
                . 'chars, period, hyphen, colon and underscores',
                XML_UTIL_ERROR_INVALID_CHARS
            );
        }
        // XML name is valid
        return true;
    }

    /**
     * Replacement for XML_Util::raiseError
     *
     * Avoids the necessity to always require
     * PEAR.php
     *
     * @param string $msg  error message
     * @param int    $code error code
     *
     * @return PEAR_Error
     * @todo   PEAR CS - should this use include_once instead?
     */
    public static function raiseError($msg, $code)
    {
        include_once 'PEAR.php';
        return PEAR::raiseError($msg, $code);
    }
}
?>
PK��Z#F��:�:pearcmd.phpnu�[���<?php
/**
 * PEAR, the PHP Extension and Application Repository
 *
 * Command line interface
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Stig Bakken <ssb@php.net>
 * @author    Tomas V.V.Cox <cox@idecnet.com>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 */

@ob_end_clean();
if (!defined('PEAR_RUNTYPE')) {
    // this is defined in peclcmd.php as 'pecl'
    define('PEAR_RUNTYPE', 'pear');
}
define('PEAR_IGNORE_BACKTRACE', 1);
/**
 * @nodep Gtk
 */
//the space is needed for windows include paths with trailing backslash
// http://pear.php.net/bugs/bug.php?id=19482
if ('/opt/alt/php74/usr/share/pear ' != '@'.'include_path'.'@ ') {
    ini_set('include_path', trim('/opt/alt/php74/usr/share/pear '). PATH_SEPARATOR .  get_include_path());
    $raw = false;
} else {
    // this is a raw, uninstalled pear, either a cvs checkout, or php distro
    ini_set('include_path', dirname(__DIR__) . PATH_SEPARATOR . get_include_path());
    $raw = true;
}
@ini_set('allow_url_fopen', true);
@set_time_limit(0);
ob_implicit_flush(true);
@ini_set('track_errors', true);
@ini_set('html_errors', false);
$_PEAR_PHPDIR = '#$%^&*';
set_error_handler('error_handler');

$pear_package_version = "1.10.16";

require_once 'PEAR.php';
require_once 'PEAR/Frontend.php';
require_once 'PEAR/Config.php';
require_once 'PEAR/Command.php';
require_once 'Console/Getopt.php';


PEAR_Command::setFrontendType('CLI');
$all_commands = PEAR_Command::getCommands();

$argv = Console_Getopt::readPHPArgv();
// fix CGI sapi oddity - the -- in pear.bat/pear is not removed
if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
    unset($argv[1]);
    $argv = array_values($argv);
}
$progname = PEAR_RUNTYPE;
array_shift($argv);
$options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV");
if (PEAR::isError($options)) {
    usage($options);
}

$opts = $options[0];

$fetype = 'CLI';
if ($progname == 'gpear' || $progname == 'pear-gtk') {
    $fetype = 'Gtk2';
} else {
    foreach ($opts as $opt) {
        if ($opt[0] == 'G') {
            $fetype = 'Gtk2';
        }
    }
}

$pear_user_config = '';
$pear_system_config = '';
$store_user_config = false;
$store_system_config = false;
$verbose = 1;

foreach ($opts as $opt) {
    switch ($opt[0]) {
    case 'c':
        $pear_user_config = $opt[1];
        break;
    case 'C':
        $pear_system_config = $opt[1];
        break;
    }
}

PEAR_Command::setFrontendType($fetype);
$ui = &PEAR_Command::getFrontendObject();
$config = &PEAR_Config::singleton($pear_user_config, $pear_system_config);

if (PEAR::isError($config)) {
    $_file = '';
    if ($pear_user_config !== false) {
        $_file .= $pear_user_config;
    }
    if ($pear_system_config !== false) {
        $_file .= '/' . $pear_system_config;
    }
    if ($_file == '/') {
        $_file = 'The default config file';
    }
    $config->getMessage();
    $ui->outputData("ERROR: $_file is not a valid config file or is corrupted.");
    // We stop, we have no idea where we are :)
    exit(1);
}

// this is used in the error handler to retrieve a relative path
$_PEAR_PHPDIR = $config->get('php_dir');
$ui->setConfig($config);
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError"));

$verbose = $config->get("verbose");
$cmdopts = array();

if ($raw) {
    if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) {
        $found = false;
        foreach ($opts as $opt) {
            if ($opt[0] == 'd' || $opt[0] == 'D') {
                // the user knows what they are doing, and are setting config values
                $found = true;
            }
        }
        if (!$found) {
            // no prior runs, try to install PEAR
            $parent = dirname(__FILE__);
            if (strpos($parent, 'scripts')) {
                $grandparent = dirname($parent);
                $packagexml = $grandparent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $grandparent;
            } else {
                $packagexml = $parent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $parent;
            }
            if (file_exists($packagexml)) {
                $options[1] = array(
                    'install',
                    $packagexml
                );
                $config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php');
                $config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data');
                $config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs');
                $config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests');
                $config->set(
                    'ext_dir',
                    $pearbase . DIRECTORY_SEPARATOR . 'extensions'
                );
                $config->set('bin_dir', $pearbase);
                $config->mergeConfigFile($pearbase . 'pear.ini', false);
                $config->store();
                $config->set('auto_discover', 1);
            }
        }
    }
}
foreach ($opts as $opt) {
    $param = !empty($opt[1]) ? $opt[1] : true;
    switch ($opt[0]) {
    case 'd':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected -d config_value=value, ' .
                'received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'user');
        break;
    case 'D':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'system');
        break;
    case 's':
        $store_user_config = true;
        break;
    case 'S':
        $store_system_config = true;
        break;
    case 'u':
        $config->remove($param, 'user');
        break;
    case 'v':
        $config->set('verbose', $config->get('verbose') + 1);
        break;
    case 'q':
        $config->set('verbose', $config->get('verbose') - 1);
        break;
    case 'V':
        usage(null, 'version');
    case 'c':
    case 'C':
        break;
    default:
        // all non pear params goes to the command
        $cmdopts[$opt[0]] = $param;
        break;
    }
}

if ($store_system_config) {
    $config->store('system');
}

if ($store_user_config) {
    $config->store('user');
}

$command = (isset($options[1][0])) ? $options[1][0] : null;
if (empty($command) && ($store_user_config || $store_system_config)) {
    exit;
}

if ($fetype == 'Gtk2') {
    if (!$config->validConfiguration()) {
        PEAR::raiseError(
            "CRITICAL ERROR: no existing valid configuration files found in " .
            "files '$pear_user_config' or '$pear_system_config', " .
            "please copy an existing configuration file to one of these " .
            "locations, or use the -c and -s options to create one"
        );
    }
    Gtk::main();
} else {
    do {
        if ($command == 'help') {
            usage(null, isset($options[1][1]) ? $options[1][1] : null);
        }

        if (!$config->validConfiguration()) {
            PEAR::raiseError(
                "CRITICAL ERROR: no existing valid configuration files found " .
                "in files '$pear_user_config' or '$pear_system_config', " .
                "please copy an existing configuration file to one of " .
                "these locations, or use the -c and -s options to create one"
            );
        }

        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        $cmd = PEAR_Command::factory($command, $config);
        PEAR::popErrorHandling();
        if (PEAR::isError($cmd)) {
            usage(null, isset($options[1][0]) ? $options[1][0] : null);
        }

        $short_args = $long_args = null;
        PEAR_Command::getGetoptArgs($command, $short_args, $long_args);
        array_shift($options[1]);
        $tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args);

        if (PEAR::isError($tmp)) {
            break;
        }

        list($tmpopt, $params) = $tmp;
        $opts = array();
        foreach ($tmpopt as $foo => $tmp2) {
            list($opt, $value) = $tmp2;
            if ($value === null) {
                $value = true; // options without args
            }

            if (strlen($opt) == 1) {
                $cmdoptions = $cmd->getOptions($command);
                foreach ($cmdoptions as $o => $d) {
                    if (isset($d['shortopt']) && $d['shortopt'] == $opt) {
                        $opts[$o] = $value;
                    }
                }
            } else {
                if (substr($opt, 0, 2) == '--') {
                    $opts[substr($opt, 2)] = $value;
                }
            }
        }

        $ok = $cmd->run($command, $opts, $params);
        if ($ok === false) {
            PEAR::raiseError("unknown command `$command'");
        }

        if (PEAR::isError($ok)) {
            PEAR::setErrorHandling(
                PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")
            );
            PEAR::raiseError($ok);
        }
    } while (false);
}

// {{{ usage()

/**
 * Display usage information
 *
 * @param mixed $error       Optional error message
 * @param mixed $helpsubject Optional subject/command to display help for
 *
 * @return void
 */
function usage($error = null, $helpsubject = null)
{
    global $progname, $all_commands;
    $stdout = fopen('php://stdout', 'w');
    if (PEAR::isError($error)) {
        fputs($stdout, $error->getMessage() . "\n");
    } elseif ($error !== null) {
        fputs($stdout, "$error\n");
    }

    if ($helpsubject != null) {
        $put = cmdHelp($helpsubject);
    } else {
        $put = "Commands:\n";
        $maxlen = max(array_map("strlen", $all_commands));
        $formatstr = "%-{$maxlen}s  %s\n";
        ksort($all_commands);
        foreach ($all_commands as $cmd => $class) {
            $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd));
        }
        $put .=
            "Usage: $progname [options] command [command-options] <parameters>\n".
            "Type \"$progname help options\" to list all options.\n".
            "Type \"$progname help shortcuts\" to list all command shortcuts.\n".
            "Type \"$progname help version\" or ".
            "\"$progname version\" to list version information.\n".
            "Type \"$progname help <command>\" to get the help ".
            "for the specified command.";
    }
    fputs($stdout, "$put\n");
    fclose($stdout);

    if ($error === null) {
        exit(0);
    }
    exit(1);
}

/**
 * Return help string for specified command
 *
 * @param string $command Command to return help for
 *
 * @return void
 */
function cmdHelp($command)
{
    global $progname, $all_commands, $config;
    if ($command == "options") {
        return
        "Options:\n".
        "     -v         increase verbosity level (default 1)\n".
        "     -q         be quiet, decrease verbosity level\n".
        "     -c file    find user configuration in `file'\n".
        "     -C file    find system configuration in `file'\n".
        "     -d foo=bar set user config variable `foo' to `bar'\n".
        "     -D foo=bar set system config variable `foo' to `bar'\n".
        "     -G         start in graphical (Gtk) mode\n".
        "     -s         store user configuration\n".
        "     -S         store system configuration\n".
        "     -u foo     unset `foo' in the user configuration\n".
        "     -h, -?     display help/usage (this message)\n".
        "     -V         version information\n";
    } elseif ($command == "shortcuts") {
        $sc = PEAR_Command::getShortcuts();
        $ret = "Shortcuts:\n";
        foreach ($sc as $s => $c) {
            $ret .= sprintf("     %-8s %s\n", $s, $c);
        }
        return $ret;

    } elseif ($command == "version") {
        return "PEAR Version: ".$GLOBALS['pear_package_version'].
               "\nPHP Version: ".phpversion().
               "\nZend Engine Version: ".zend_version().
               "\nRunning on: ".php_uname();

    } elseif ($help = PEAR_Command::getHelp($command)) {
        if (is_string($help)) {
            return "$progname $command [options] $help\n";
        }

        if ($help[1] === null) {
            return "$progname $command $help[0]";
        }

        return "$progname $command [options] $help[0]\n$help[1]";
    }

    return "Command '$command' is not valid, try '$progname help'";
}

// }}}

/**
 * error_handler
 *
 * @param mixed $errno  Error number
 * @param mixed $errmsg Message
 * @param mixed $file   Filename
 * @param mixed $line   Line number
 *
 * @access public
 * @return boolean
 */
function error_handler($errno, $errmsg, $file, $line)
{
    if ((!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) && ($errno & E_STRICT)) {
        return; // E_STRICT
    }
    if ($errno & E_DEPRECATED) {
        return; // E_DEPRECATED
    }
    if (!(error_reporting() & $errno) &&
        isset($GLOBALS['config']) &&
        $GLOBALS['config']->get('verbose') < 4
    ) {
        return false; // @silenced error, show all if debug is high enough
    }
    $errortype = array (
        E_DEPRECATED  => 'Deprecated Warning',
        E_ERROR   =>  "Error",
        E_WARNING   =>  "Warning",
        E_PARSE   =>  "Parsing Error",
        E_NOTICE   =>  "Notice",
        E_CORE_ERROR  =>  "Core Error",
        E_CORE_WARNING  =>  "Core Warning",
        E_COMPILE_ERROR  =>  "Compile Error",
        E_COMPILE_WARNING =>  "Compile Warning",
        E_USER_ERROR =>  "User Error",
        E_USER_WARNING =>  "User Warning",
        E_USER_NOTICE =>  "User Notice"
    );
    if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) {
        $errortype[E_STRICT] = 'Strict Warning';
    }
    $prefix = $errortype[$errno];
    global $_PEAR_PHPDIR;
    if (stristr($file, $_PEAR_PHPDIR)) {
        $file = substr($file, strlen($_PEAR_PHPDIR) + 1);
    } else {
        $file = basename($file);
    }
    print "\n$prefix: $errmsg in $file on line $line\n";
    return false;
}


/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * indent-tabs-mode: nil
 * mode: php
 * End:
 */
// vim600:syn=php
PK��Z�0$�-- .pkgxml/Pear_File_MARC-1.4.1.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.10.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
 <name>File_MARC</name>
 <channel>pear.php.net</channel>
 <summary>Parse, modify, and create MARC records</summary>
 <description>The standard for machine-readable cataloging (MARC) records is documented at http://loc.gov/marc/. This package enables you to read existing MARC records from a file, string, or (using the YAZ extension), from a Z39.50 source. You can also use this package to create new MARC records.

This package is based on the PHP MARC package, originally called &quot;php-marc&quot;, that is part of the Emilda Project (http://www.emilda.org).  Christoffer Landtman generously agreed to make the &quot;php-marc&quot; code available under the GNU LGPL so it could be used as the basis of this PEAR package.</description>
 <lead>
  <name>Dan Scott</name>
  <user>dbs</user>
  <email>dbs@php.net</email>
  <active>yes</active>
 </lead>
 <date>2019-11-13</date>
 <time>17:33:33</time>
 <version>
  <release>1.4.1</release>
  <api>1.4.0</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license uri="http://www.gnu.org/copyleft/lesser.html">GNU Lesser General Public License</license>
 <notes>
1.4.1
  * Reintroduce include_path to composer.json
 </notes>
 <contents>
  <dir baseinstalldir="File" name="/">
   <file baseinstalldir="/" md5sum="ffe2590635f404af055fe731da105939" name="File/MARC/Lint/CodeData.php" role="php" />
   <file baseinstalldir="/" md5sum="a3b9e1c817e67f59add05593500d463e" name="File/MARC/Control_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="acba4463f8e40d6ee4e7ba1f2dc53123" name="File/MARC/Data_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="378f483ec1fd161cd9dfb9b05db58d66" name="File/MARC/Exception.php" role="php" />
   <file baseinstalldir="/" md5sum="a9ba69030cbf4847292b9975e9d922c6" name="File/MARC/Field.php" role="php" />
   <file baseinstalldir="/" md5sum="c37351c7c80927ce6bb1e662510f9183" name="File/MARC/Lint.php" role="php" />
   <file baseinstalldir="/" md5sum="c5ac39e3d25eb0108b9dd5ad8466c821" name="File/MARC/List.php" role="php" />
   <file baseinstalldir="/" md5sum="7af6ce78cde4bb246e4e96709e90d2c0" name="File/MARC/Record.php" role="php" />
   <file baseinstalldir="/" md5sum="df5f97139685f0ad04e47fdbb67e3968" name="File/MARC/Subfield.php" role="php" />
   <file baseinstalldir="/" md5sum="6e102262dfd5d65d8d5a6221dfc74edd" name="File/MARC.php" role="php" />
   <file baseinstalldir="/" md5sum="8b64040d2d18ac4b994595a148266a66" name="File/MARCBASE.php" role="php" />
   <file baseinstalldir="/" md5sum="f5a17a60d34e84e2ee7ca1e5c5c6c620" name="File/MARCXML.php" role="php" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="examples/example.mrc" role="doc" />
   <file baseinstalldir="File" md5sum="1aea40df9f1c2e32f8e065fe8da0a3b5" name="examples/marc_yaz.php" role="doc" />
   <file baseinstalldir="File" md5sum="70ae317e0890d5896e3ffccdd293369a" name="examples/read.php" role="doc" />
   <file baseinstalldir="File" md5sum="54efb9d920ac775bfc847a83a2dec73a" name="examples/subfields.php" role="doc" />
   <file baseinstalldir="File" md5sum="14297da35b510c496cd1f328cf3bb301" name="tests/bad_example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="0dd4c6dbad6e8608d0ebf9d24425955d" name="tests/bad_example.xml" role="test" />
   <file baseinstalldir="File" md5sum="216a6f9d53f6d3d8e22d81fdc10f4bc1" name="tests/camel.mrc" role="test" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="tests/example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="9455aec3371f79cf7d31281fd03f5171" name="tests/marc_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="577e2f5f89fd48cf1a3576a29d2958f8" name="tests/marc_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a6a586354b9a06c880c2a7470dd828d7" name="tests/marc_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1c7e2fc5572a0f9362a771c260a1fe3" name="tests/marc_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="84f85ac7f8a2532e4e90ccde7764556a" name="tests/marc_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="889e5e906a97de7a0e94b0c5f30e70e7" name="tests/marc_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="be823dc8a8efb408de06371ab802efcc" name="tests/marc_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="af44490aafea44e5120f881cb81cdad9" name="tests/marc_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ac9f2a7aeb24900a11f5102744179ae3" name="tests/marc_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5e43eb5cddbb4f2bd0d6405cd95b80aa" name="tests/marc_010.phpt" role="test" />
   <file baseinstalldir="File" md5sum="2e1cd8509c0bf04ec77fc0f51375f611" name="tests/marc_011.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bc49ca48623102c8ac07679fa77a3dd9" name="tests/marc_012.phpt" role="test" />
   <file baseinstalldir="File" md5sum="245a3b20e0da1973535503e28efd1d3a" name="tests/marc_013.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ce69aa734856dd40d60d30c77bdef53a" name="tests/marc_014.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7b61cdd31035e60682fa92c5d519d997" name="tests/marc_015.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7f4f597fe1adaa3507eb87fc4875dbd2" name="tests/marc_016.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4262efd5fcacbd7503323681f4552430" name="tests/marc_017.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ee1623d7bda54ba4f741b2319b158f82" name="tests/marc_018.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8006c03fbab0f04377342086fafd3982" name="tests/marc_019.phpt" role="test" />
   <file baseinstalldir="File" md5sum="f5ae5b25e0ac1104314433d9e5b1f7fe" name="tests/marc_020.phpt" role="test" />
   <file baseinstalldir="File" md5sum="94d8f99e86585671a1b2d3043aeb6360" name="tests/marc_021.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bb891a890effe0e77e1759043f4846d8" name="tests/marc_022.phpt" role="test" />
   <file baseinstalldir="File" md5sum="faf77dcb5cdd002c09169a14bfded65e" name="tests/marc_023.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0e6c4a23f5da7df64fdd4b3b1149bbee" name="tests/marc_16783.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4ea8b3520beda378db15960f1c50493a" name="tests/marc_field_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="743850ef61df69c4340be44a03bccb5a" name="tests/marc_field_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8c765f1398b49df257d86d22ac6e4f8d" name="tests/marc_field_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d4216cf930a308e0d02553bd3914f294" name="tests/marc_field_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dd59514b474b78371ad522a3e13b76b7" name="tests/marc_field_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5295bfd02a8424acac1c91de26b552c7" name="tests/marc_field_21246.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6f95f09442ccf6b93df92986f58b270d" name="tests/marc_lint_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="18d721f8871edd925624ccbdd15444fb" name="tests/marc_lint_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4eb86a2f4e0a74dedcb0bf2511da6ca1" name="tests/marc_lint_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="10430fee0a1352d0528f1507b34c57e1" name="tests/marc_lint_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0dcd07a18577d7b22392a2214cd6436c" name="tests/marc_lint_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fd17798fc535562e5e64461f449516b2" name="tests/marc_record_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="141b455ccf67a60c4eac44c77960f2e2" name="tests/marc_subfield_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1e23464ee0eec47ddca2af9a9922926" name="tests/marc_subfield_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="1d7903e8c244d647220b318b4bc758d1" name="tests/marc_xml_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="22cae3c752d843b78f583dcd92801534" name="tests/marc_xml_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="c0716d23e0f960abf8d53ad6014a413a" name="tests/marc_xml_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7645fa19e28aca041a124fc5e2c12bd3" name="tests/marc_xml_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b08b28c3251625b8b6e4d7ab376b0185" name="tests/marc_xml_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6cd0934ddbf65d2d7e9ea5d108977ff7" name="tests/marc_xml_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ffdce4aa190268fa7cbbf3bb45383abf" name="tests/marc_xml_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="998a4c1ce00ff100f39ffa9fc49a212f" name="tests/marc_xml_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a38a67c590869f2b0a4859a910fd9e89" name="tests/marc_xml_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="db39c5055a570fcda12bb7c5fa1e3b4d" name="tests/marc_xml_16642.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dc075f4a271bd7182378a3874bd5b39e" name="tests/marc_xml_namespace.phpt" role="test" />
   <file baseinstalldir="File" md5sum="208200d9a979ac360c4d326e9789b6b7" name="tests/marc_xml_namespace_prefix.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d87774ede82222cfc12b2c2a06f57a3a" name="tests/marc_xml_rsinger.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fb44e3eb69f1a37115235fc829c39542" name="tests/namespace.xml" role="test" />
   <file baseinstalldPK��Z;�,6,6#.registry/structures_linkedlist.regnu�[���PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'PK��ZI�<�++.registry/structures_graph.regnu�[���PK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtdPK��Zh;.1{1{.registry/xml_rpc.regnu�[���PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUri   URI of the namespace
     * @param bool   $multiline      whether to create a multiline tag where each
     *                               attribute gets written to a single line
     * @param string $indent         string used to indent attributes (_auto indents
     *                               attributes so they start at the same column)
     * @param string $linebreak      string used for linebreaks
     * @param bool   $sortAttributes Whether to sort the attributes or not
     *
     * @return string XML start element
     * @see    createEndElement(), createTag()
     */
    public static function createStartElement(
        $qname, $attributes = array(), $namespaceUri = null,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true
    ) {
        // if no attributes hav been set, use empty attributes
        if (!isset($attributes) || !is_array($attributes)) {
            $attributes = array();
        }

        if ($namespaceUri != null) {
            $parts = XML_Util::splitQualifiedName($qname);
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($qname)+2));
            }
        }

        if ($namespaceUri != null) {
            // is a namespace given
            if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
            } else {
                // define this Uri as the default namespace
                $attributes['xmlns'] = $namespaceUri;
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $attributes, $sortAttributes,
            $multiline, $indent, $linebreak
        );
        $element = sprintf('<%s%s>', $qname, $attList);
        return  $element;
    }

    /**
     * Create an end element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createEndElement('myNs:myTag');
     * </code>
     *
     * @param string $qname qualified tagname (including namespace)
     *
     * @return string XML end element
     * @see    createStartElement(), createTag()
     */
    public static function createEndElement($qname)
    {
        $element = sprintf('</%s>', $qname);
        return $element;
    }

    /**
     * Create an XML comment
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createComment('I am a comment');
     * </code>
     *
     * @param string $content content of the comment
     *
     * @return string XML comment
     */
    public static function createComment($content)
    {
        $comment = sprintf('<!-- %s -->', $content);
        return $comment;
    }

    /**
     * Create a CData section
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create a CData section
     * $tag = XML_Util::createCDataSection('I am content.');
     * </code>
     *
     * @param string $data data of the CData section
     *
     * @return string CData section with content
     */
    public static function createCDataSection($data)
    {
        return sprintf(
            '<![CDATA[%s]]>',
            preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data))
        );
    }

    /**
     * Split qualified name and return namespace and local part
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // split qualified tag
     * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
     * </code>
     * the returned array will contain two elements:
     * <pre>
     * array(
     *     'namespace' => 'xslt',
     *     'localPart' => 'stylesheet'
     * );
     * </pre>
     *
     * @param string $qname     qualified tag name
     * @param string $defaultNs default namespace (optional)
     *
     * @return array array containing namespace and local part
     */
    public static function splitQualifiedName($qname, $defaultNs = null)
    {
        if (strstr($qname, ':')) {
            $tmp = explode(':', $qname);
            return array(
                'namespace' => $tmp[0],
                'localPart' => $tmp[1]
            );
        }
        return array(
            'namespace' => $defaultNs,
            'localPart' => $qname
        );
    }

    /**
     * Check, whether string is valid XML name
     *
     * <p>XML names are used for tagname, attribute names and various
     * other, lesser known entities.</p>
     * <p>An XML name may only consist of alphanumeric characters,
     * dashes, undescores and periods, and has to start with a letter
     * or an underscore.</p>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // verify tag name
     * $result = XML_Util::isValidName('invalidTag?');
     * if (is_a($result, 'PEAR_Error')) {
     *    print 'Invalid XML name: ' . $result->getMessage();
     * }
     * </code>
     *
     * @param string $string string that should be checked
     *
     * @return mixed true, if string is a valid XML name, PEAR error otherwise
     *
     * @todo support for other charsets
     * @todo PEAR CS - PK��Zf&�}"",.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quPK��Z��2a�e�e/.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUPK��Z�D�}����4.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUri   URI of the namespace
     * @param bool   $multiline      whether to create a multiline tag where each
     *                               attribute gets written to a single line
     * @param string $indent         string used to indent attributes (_auto indents
     *                               attributes so they start at the same column)
     * @param string $linebreak      string used for linebreaks
     * @param bool   $sortAttributes Whether to sort the attributes or not
     *
     * @return string XML start element
     * @see    createEndElement(), createTag()
     */
    public static function createStartElement(
        $qname, $attributes = array(), $namespaceUri = null,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true
    ) {
        // if no attributes hav been set, use empty attributes
        if (!isset($attributes) || !is_array($attributes)) {
            $attributes = array();
        }

        if ($namespaceUri != null) {
            $parts = XML_Util::splitQualifiedName($qname);
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($qname)+2));
            }
        }

        if ($namespaceUri != null) {
            // is a namespace given
            if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
            } else {
                // define this Uri as the default namespace
                $attributes['xmlns'] = $namespaceUri;
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $attributes, $sortAttributes,
            $multiline, $indent, $linebreak
        );
        $element = sprintf('<%s%s>', $qname, $attList);
        return  $element;
    }

    /**
     * Create an end element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createEndElement('myNs:myTag');
     * </code>
     *
     * @param string $qname qualified tagname (including namespace)
     *
     * @return string XML end element
     * @see    createStartElement(), createTag()
     */
    public static function createEndElement($qname)
    {
        $element = sprintf('</%s>', $qname);
        return $element;
    }

    /**
     * Create an XML comment
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createComment('I am a comment');
     * </code>
     *
     * @param string $content content of the comment
     *
     * @return string XML comment
     */
    public static function createComment($content)
    {
        $comment = sprintf('<!-- %s -->', $content);
        return $comment;
    }

    /**
     * Create a CData section
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create a CData section
     * $tag = XML_Util::createCDataSection('I am content.');
     * </code>
     *
     * @param string $data data of the CData section
     *
     * @return string CData section with content
     */
    public static function createCDataSection($data)
    {
        return sprintf(
            '<![CDATA[%s]]>',
            preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data))
        );
    }

    /**
     * Split qualified name and return namespace and local part
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // split qualified tag
     * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
     * </code>
     * the returned array will contain two elements:
     * <pre>
     * array(
     *     'namespace' => 'xslt',
     *     'localPart' => 'stylesheet'
     * );
     * </pre>
     *
     * @param string $qname     qualified tag name
     * @param string $defaultNs default namespace (optional)
     *
     * @return array array containing namespace and local part
     */
    public static function splitQualifiedName($qname, $defaultNs = null)
    {
        if (strstr($qname, ':')) {
            $tmp = explode(':', $qname);
            return array(
                'namespace' => $tmp[0],
                'localPart' => $tmp[1]
            );
        }
        return array(
            'namespace' => $defaultNs,
            'localPart' => $qname
        );
    }

    /**
     * Check, whether string is valid XML name
     *
     * <p>XML names are used for tagname, attribute names and various
     * other, lesser known entities.</p>
     * <p>An XML name may only consist of alphanumeric characters,
     * dashes, undescores and periods, and has to start with a letter
     * or an underscore.</p>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // verify tag name
     * $result = XML_Util::isValidName('invalidTag?');
     * if (is_a($result, 'PEAR_Error')) {
     *    print 'Invalid XML name: ' . $result->getMessage();
     * }
     * </code>
     *
     * @param string $string string that should be checked
     *
     * @return mixed true, if string is a valid XML name, PEAR error otherwise
     *
     * @todo support for other charsets
     * @todo PEAR CS - unable to avoid 85-char limit on second preg_match
     */
    public static function isValidName($string)
    {
        // check for invalid chars
        if (!is_string($string) || !strlen($string) || !preg_match('/^[[:alpha:]_]\\z/', $string[0])) {
            return XML_Util::raiseError(
                'XML names may only start with letter or underscore',
                XML_UTIL_ERROR_INVALID_START
            );
        }

        // check for invalid chars
        $match = preg_match(
            '/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?'
            . '[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/',
            $string
        );
        if (!$match) {
            return XML_Util::raiseError(
                'XML names may only contain alphanumeric '
                . 'chars, period, hyphen, colon and underscores',
                XML_UTIL_ERROR_INVALID_CHARS
            );
        }
        // XML name is valid
        return true;
    }

    /**
     * Replacement for XML_Util::raiseError
     *
     * Avoids the necessity to always require
     * PEAR.php
     *
     * @param string $msg  error message
     * @param int    $code error code
     *
     * @return PEAR_Error
     * @todo   PEAR CS - should this use include_once instead?
     */
    public static function raiseError($msg, $code)
    {
        include_once 'PEAR.php';
        return PEAR::raiseError($msg, $code);
    }
}
?>
PK��Z#F��:�:pearcmd.phpnu�[���<?php
/**
 * PEAR, the PHP Extension and Application Repository
 *
 * Command line interface
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Stig Bakken <ssb@php.net>
 * @author    Tomas V.V.Cox <cox@idecnet.com>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 */

@ob_end_clean();
if (!defined('PEAR_RUNTYPE')) {
    // this is defined in peclcmd.php as 'pecl'
    define('PEAR_RUNTYPE', 'pear');
}
define('PEAR_IGNORE_BACKTRACE', 1);
/**
 * @nodep Gtk
 */
//the space is needed for windows include paths with trailing backslash
// http://pear.php.net/bugs/bug.php?id=19482
if ('/opt/alt/php74/usr/share/pear ' != '@'.'include_path'.'@ ') {
    ini_set('include_path', trim('/opt/alt/php74/usr/share/pear '). PATH_SEPARATOR .  get_include_path());
    $raw = false;
} else {
    // this is a raw, uninstalled pear, either a cvs checkout, or php distro
    ini_set('include_path', dirname(__DIR__) . PATH_SEPARATOR . get_include_path());
    $raw = true;
}
@ini_set('allow_url_fopen', true);
@set_time_limit(0);
ob_implicit_flush(true);
@ini_set('track_errors', true);
@ini_set('html_errors', false);
$_PEAR_PHPDIR = '#$%^&*';
set_error_handler('error_handler');

$pear_package_version = "1.10.16";

require_once 'PEAR.php';
require_once 'PEAR/Frontend.php';
require_once 'PEAR/Config.php';
require_once 'PEAR/Command.php';
require_once 'Console/Getopt.php';


PEAR_Command::setFrontendType('CLI');
$all_commands = PEAR_Command::getCommands();

$argv = Console_Getopt::readPHPArgv();
// fix CGI sapi oddity - the -- in pear.bat/pear is not removed
if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
    unset($argv[1]);
    $argv = array_values($argv);
}
$progname = PEAR_RUNTYPE;
array_shift($argv);
$options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV");
if (PEAR::isError($options)) {
    usage($options);
}

$opts = $options[0];

$fetype = 'CLI';
if ($progname == 'gpear' || $progname == 'pear-gtk') {
    $fetype = 'Gtk2';
} else {
    foreach ($opts as $opt) {
        if ($opt[0] == 'G') {
            $fetype = 'Gtk2';
        }
    }
}

$pear_user_config = '';
$pear_system_config = '';
$store_user_config = false;
$store_system_config = false;
$verbose = 1;

foreach ($opts as $opt) {
    switch ($opt[0]) {
    case 'c':
        $pear_user_config = $opt[1];
        break;
    case 'C':
        $pear_system_config = $opt[1];
        break;
    }
}

PEAR_Command::setFrontendType($fetype);
$ui = &PEAR_Command::getFrontendObject();
$config = &PEAR_Config::singleton($pear_user_config, $pear_system_config);

if (PEAR::isError($config)) {
    $_file = '';
    if ($pear_user_config !== false) {
        $_file .= $pear_user_config;
    }
    if ($pear_system_config !== false) {
        $_file .= '/' . $pear_system_config;
    }
    if ($_file == '/') {
        $_file = 'The default config file';
    }
    $config->getMessage();
    $ui->outputData("ERROR: $_file is not a valid config file or is corrupted.");
    // We stop, we have no idea where we are :)
    exit(1);
}

// this is used in the error handler to retrieve a relative path
$_PEAR_PHPDIR = $config->get('php_dir');
$ui->setConfig($config);
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError"));

$verbose = $config->get("verbose");
$cmdopts = array();

if ($raw) {
    if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) {
        $found = false;
        foreach ($opts as $opt) {
            if ($opt[0] == 'd' || $opt[0] == 'D') {
                // the user knows what they are doing, and are setting config values
                $found = true;
            }
        }
        if (!$found) {
            // no prior runs, try to install PEAR
            $parent = dirname(__FILE__);
            if (strpos($parent, 'scripts')) {
                $grandparent = dirname($parent);
                $packagexml = $grandparent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $grandparent;
            } else {
                $packagexml = $parent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $parent;
            }
            if (file_exists($packagexml)) {
                $options[1] = array(
                    'install',
                    $packagexml
                );
                $config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php');
                $config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data');
                $config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs');
                $config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests');
                $config->set(
                    'ext_dir',
                    $pearbase . DIRECTORY_SEPARATOR . 'extensions'
                );
                $config->set('bin_dir', $pearbase);
                $config->mergeConfigFile($pearbase . 'pear.ini', false);
                $config->store();
                $config->set('auto_discover', 1);
            }
        }
    }
}
foreach ($opts as $opt) {
    $param = !empty($opt[1]) ? $opt[1] : true;
    switch ($opt[0]) {
    case 'd':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected -d config_value=value, ' .
                'received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'user');
        break;
    case 'D':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'system');
        break;
    case 's':
        $store_user_config = true;
        break;
    case 'S':
        $store_system_config = true;
        break;
    case 'u':
        $config->remove($param, 'user');
        break;
    case 'v':
        $config->set('verbose', $config->get('verbose') + 1);
        break;
    case 'q':
        $config->set('verbose', $config->get('verbose') - 1);
        break;
    case 'V':
        usage(null, 'version');
    case 'c':
    case 'C':
        break;
    default:
        // all non pear params goes to the command
        $cmdopts[$opt[0]] = $param;
        break;
    }
}

if ($store_system_config) {
    $config->store('system');
}

if ($store_user_config) {
    $config->store('user');
}

$command = (isset($options[1][0])) ? $options[1][0] : null;
if (empty($command) && ($store_user_config || $store_system_config)) {
    exit;
}

if ($fetype == 'Gtk2') {
    if (!$config->validConfiguration()) {
        PEAR::raiseError(
            "CRITICAL ERROR: no existing valid configuration files found in " .
            "files '$pear_user_config' or '$pear_system_config', " .
            "please copy an existing configuration file to one of these " .
            "locations, or use the -c and -s options to create one"
        );
    }
    Gtk::main();
} else {
    do {
        if ($command == 'help') {
            usage(null, isset($options[1][1]) ? $options[1][1] : null);
        }

        if (!$config->validConfiguration()) {
            PEAR::raiseError(
                "CRITICAL ERROR: no existing valid configuration files found " .
                "in files '$pear_user_config' or '$pear_system_config', " .
                "please copy an existing configuration file to one of " .
                "these locations, or use the -c and -s options to create one"
            );
        }

        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        $cmd = PEAR_Command::factory($command, $config);
        PEAR::popErrorHandling();
        if (PEAR::isError($cmd)) {
            usage(null, isset($options[1][0]) ? $options[1][0] : null);
        }

        $short_args = $long_args = null;
        PEAR_Command::getGetoptArgs($command, $short_args, $long_args);
        array_shift($options[1]);
        $tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args);

        if (PEAR::isError($tmp)) {
            break;
        }

        list($tmpopt, $params) = $tmp;
        $opts = array();
        foreach ($tmpopt as $foo => $tmp2) {
            list($opt, $value) = $tmp2;
            if ($value === null) {
                $value = true; // options without args
            }

            if (strlen($opt) == 1) {
                $cmdoptions = $cmd->getOptions($command);
                foreach ($cmdoptions as $o => $d) {
                    if (isset($d['shortopt']) && $d['shortopt'] == $opt) {
                        $opts[$o] = $value;
                    }
                }
            } else {
                if (substr($opt, 0, 2) == '--') {
                    $opts[substr($opt, 2)] = $value;
                }
            }
        }

        $ok = $cmd->run($command, $opts, $params);
        if ($ok === false) {
            PEAR::raiseError("unknown command `$command'");
        }

        if (PEAR::isError($ok)) {
            PEAR::setErrorHandling(
                PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")
            );
            PEAR::raiseError($ok);
        }
    } while (false);
}

// {{{ usage()

/**
 * Display usage information
 *
 * @param mixed $error       Optional error message
 * @param mixed $helpsubject Optional subject/command to display help for
 *
 * @return void
 */
function usage($error = null, $helpsubject = null)
{
    global $progname, $all_commands;
    $stdout = fopen('php://stdout', 'w');
    if (PEAR::isError($error)) {
        fputs($stdout, $error->getMessage() . "\n");
    } elseif ($error !== null) {
        fputs($stdout, "$error\n");
    }

    if ($helpsubject != null) {
        $put = cmdHelp($helpsubject);
    } else {
        $put = "Commands:\n";
        $maxlen = max(array_map("strlen", $all_commands));
        $formatstr = "%-{$maxlen}s  %s\n";
        ksort($all_commands);
        foreach ($all_commands as $cmd => $class) {
            $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd));
        }
        $put .=
            "Usage: $progname [options] command [command-options] <parameters>\n".
            "Type \"$progname help options\" to list all options.\n".
            "Type \"$progname help shortcuts\" to list all command shortcuts.\n".
            "Type \"$progname help version\" or ".
            "\"$progname version\" to list version information.\n".
            "Type \"$progname help <command>\" to get the help ".
            "for the specified command.";
    }
    fputs($stdout, "$put\n");
    fclose($stdout);

    if ($error === null) {
        exit(0);
    }
    exit(1);
}

/**
 * Return help string for specified command
 *
 * @param string $command Command to return help for
 *
 * @return void
 */
function cmdHelp($command)
{
    global $progname, $all_commands, $config;
    if ($command == "options") {
        return
        "Options:\n".
        "     -v         increase verbosity level (default 1)\n".
        "     -q         be quiet, decrease verbosity level\n".
        "     -c file    find user configuration in `file'\n".
        "     -C file    find system configuration in `file'\n".
        "     -d foo=bar set user config variable `foo' to `bar'\n".
        "     -D foo=bar set system config variable `foo' to `bar'\n".
        "     -G         start in graphical (Gtk) mode\n".
        "     -s         store user configuration\n".
        "     -S         store system configuration\n".
        "     -u foo     unset `foo' in the user configuration\n".
        "     -h, -?     display help/usage (this message)\n".
        "     -V         version information\n";
    } elseif ($command == "shortcuts") {
        $sc = PEAR_Command::getShortcuts();
        $ret = "Shortcuts:\n";
        foreach ($sc as $s => $c) {
            $ret .= sprintf("     %-8s %s\n", $s, $c);
        }
        return $ret;

    } elseif ($command == "version") {
        return "PEAR Version: ".$GLOBALS['pear_package_version'].
               "\nPHP Version: ".phpversion().
               "\nZend Engine Version: ".zend_version().
               "\nRunning on: ".php_uname();

    } elseif ($help = PEAR_Command::getHelp($command)) {
        if (is_string($help)) {
            return "$progname $command [options] $help\n";
        }

        if ($help[1] === null) {
            return "$progname $command $help[0]";
        }

        return "$progname $command [options] $help[0]\n$help[1]";
    }

    return "Command '$command' is not valid, try '$progname help'";
}

// }}}

/**
 * error_handler
 *
 * @param mixed $errno  Error number
 * @param mixed $errmsg Message
 * @param mixed $file   Filename
 * @param mixed $line   Line number
 *
 * @access public
 * @return boolean
 */
function error_handler($errno, $errmsg, $file, $line)
{
    if ((!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) && ($errno & E_STRICT)) {
        return; // E_STRICT
    }
    if ($errno & E_DEPRECATED) {
        return; // E_DEPRECATED
    }
    if (!(error_reporting() & $errno) &&
        isset($GLOBALS['config']) &&
        $GLOBALS['config']->get('verbose') < 4
    ) {
        return false; // @silenced error, show all if debug is high enough
    }
    $errortype = array (
        E_DEPRECATED  => 'Deprecated Warning',
        E_ERROR   =>  "Error",
        E_WARNING   =>  "Warning",
        E_PARSE   =>  "Parsing Error",
        E_NOTICE   =>  "Notice",
        E_CORE_ERROR  =>  "Core Error",
        E_CORE_WARNING  =>  "Core Warning",
        E_COMPILE_ERROR  =>  "Compile Error",
        E_COMPILE_WARNING =>  "Compile Warning",
        E_USER_ERROR =>  "User Error",
        E_USER_WARNING =>  "User Warning",
        E_USER_NOTICE =>  "User Notice"
    );
    if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) {
        $errortype[E_STRICT] = 'Strict Warning';
    }
    $prefix = $errortype[$errno];
    global $_PEAR_PHPDIR;
    if (stristr($file, $_PEAR_PHPDIR)) {
        $file = substr($file, strlen($_PEAR_PHPDIR) + 1);
    } else {
        $file = basename($file);
    }
    print "\n$prefix: $errmsg in $file on line $line\n";
    return false;
}


/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * indent-tabs-mode: nil
 * mode: php
 * End:
 */
// vim600:syn=php
PK��Z�0$�-- .pkgxml/Pear_File_MARC-1.4.1.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.10.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
 <name>File_MARC</name>
 <channel>pear.php.net</channel>
 <summary>Parse, modify, and create MARC records</summary>
 <description>The standard for machine-readable cataloging (MARC) records is documented at http://loc.gov/marc/. This package enables you to read existing MARC records from a file, string, or (using the YAZ extension), from a Z39.50 source. You can also use this package to create new MARC records.

This package is based on the PHP MARC package, originally called &quot;php-marc&quot;, that is part of the Emilda Project (http://www.emilda.org).  Christoffer Landtman generously agreed to make the &quot;php-marc&quot; code available under the GNU LGPL so it could be used as the basis of this PEAR package.</description>
 <lead>
  <name>Dan Scott</name>
  <user>dbs</user>
  <email>dbs@php.net</email>
  <active>yes</active>
 </lead>
 <date>2019-11-13</date>
 <time>17:33:33</time>
 <version>
  <release>1.4.1</release>
  <api>1.4.0</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license uri="http://www.gnu.org/copyleft/lesser.html">GNU Lesser General Public License</license>
 <notes>
1.4.1
  * Reintroduce include_path to composer.json
 </notes>
 <contents>
  <dir baseinstalldir="File" name="/">
   <file baseinstalldir="/" md5sum="ffe2590635f404af055fe731da105939" name="File/MARC/Lint/CodeData.php" role="php" />
   <file baseinstalldir="/" md5sum="a3b9e1c817e67f59add05593500d463e" name="File/MARC/Control_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="acba4463f8e40d6ee4e7ba1f2dc53123" name="File/MARC/Data_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="378f483ec1fd161cd9dfb9b05db58d66" name="File/MARC/Exception.php" role="php" />
   <file baseinstalldir="/" md5sum="a9ba69030cbf4847292b9975e9d922c6" name="File/MARC/Field.php" role="php" />
   <file baseinstalldir="/" md5sum="c37351c7c80927ce6bb1e662510f9183" name="File/MARC/Lint.php" role="php" />
   <file baseinstalldir="/" md5sum="c5ac39e3d25eb0108b9dd5ad8466c821" name="File/MARC/List.php" role="php" />
   <file baseinstalldir="/" md5sum="7af6ce78cde4bb246e4e96709e90d2c0" name="File/MARC/Record.php" role="php" />
   <file baseinstalldir="/" md5sum="df5f97139685f0ad04e47fdbb67e3968" name="File/MARC/Subfield.php" role="php" />
   <file baseinstalldir="/" md5sum="6e102262dfd5d65d8d5a6221dfc74edd" name="File/MARC.php" role="php" />
   <file baseinstalldir="/" md5sum="8b64040d2d18ac4b994595a148266a66" name="File/MARCBASE.php" role="php" />
   <file baseinstalldir="/" md5sum="f5a17a60d34e84e2ee7ca1e5c5c6c620" name="File/MARCXML.php" role="php" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="examples/example.mrc" role="doc" />
   <file baseinstalldir="File" md5sum="1aea40df9f1c2e32f8e065fe8da0a3b5" name="examples/marc_yaz.php" role="doc" />
   <file baseinstalldir="File" md5sum="70ae317e0890d5896e3ffccdd293369a" name="examples/read.php" role="doc" />
   <file baseinstalldir="File" md5sum="54efb9d920ac775bfc847a83a2dec73a" name="examples/subfields.php" role="doc" />
   <file baseinstalldir="File" md5sum="14297da35b510c496cd1f328cf3bb301" name="tests/bad_example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="0dd4c6dbad6e8608d0ebf9d24425955d" name="tests/bad_example.xml" role="test" />
   <file baseinstalldir="File" md5sum="216a6f9d53f6d3d8e22d81fdc10f4bc1" name="tests/camel.mrc" role="test" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="tests/example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="9455aec3371f79cf7d31281fd03f5171" name="tests/marc_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="577e2f5f89fd48cf1a3576a29d2958f8" name="tests/marc_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a6a586354b9a06c880c2a7470dd828d7" name="tests/marc_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1c7e2fc5572a0f9362a771c260a1fe3" name="tests/marc_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="84f85ac7f8a2532e4e90ccde7764556a" name="tests/marc_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="889e5e906a97de7a0e94b0c5f30e70e7" name="tests/marc_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="be823dc8a8efb408de06371ab802efcc" name="tests/marc_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="af44490aafea44e5120f881cb81cdad9" name="tests/marc_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ac9f2a7aeb24900a11f5102744179ae3" name="tests/marc_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5e43eb5cddbb4f2bd0d6405cd95b80aa" name="tests/marc_010.phpt" role="test" />
   <file baseinstalldir="File" md5sum="2e1cd8509c0bf04ec77fc0f51375f611" name="tests/marc_011.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bc49ca48623102c8ac07679fa77a3dd9" name="tests/marc_012.phpt" role="test" />
   <file baseinstalldir="File" md5sum="245a3b20e0da1973535503e28efd1d3a" name="tests/marc_013.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ce69aa734856dd40d60d30c77bdef53a" name="tests/marc_014.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7b61cdd31035e60682fa92c5d519d997" name="tests/marc_015.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7f4f597fe1adaa3507eb87fc4875dbd2" name="tests/marc_016.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4262efd5fcacbd7503323681f4552430" name="tests/marc_017.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ee1623d7bda54ba4f741b2319b158f82" name="tests/marc_018.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8006c03fbab0f04377342086fafd3982" name="tests/marc_019.phpt" role="test" />
   <file baseinstalldir="File" md5sum="f5ae5b25e0ac1104314433d9e5b1f7fe" name="tests/marc_020.phpt" role="test" />
   <file baseinstalldir="File" md5sum="94d8f99e86585671a1b2d3043aeb6360" name="tests/marc_021.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bb891a890effe0e77e1759043f4846d8" name="tests/marc_022.phpt" role="test" />
   <file baseinstalldir="File" md5sum="faf77dcb5cdd002c09169a14bfded65e" name="tests/marc_023.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0e6c4a23f5da7df64fdd4b3b1149bbee" name="tests/marc_16783.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4ea8b3520beda378db15960f1c50493a" name="tests/marc_field_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="743850ef61df69c4340be44a03bccb5a" name="tests/marc_field_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8c765f1398b49df257d86d22ac6e4f8d" name="tests/marc_field_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d4216cf930a308e0d02553bd3914f294" name="tests/marc_field_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dd59514b474b78371ad522a3e13b76b7" name="tests/marc_field_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5295bfd02a8424acac1c91de26b552c7" name="tests/marc_field_21246.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6f95f09442ccf6b93df92986f58b270d" name="tests/marc_lint_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="18d721f8871edd925624ccbdd15444fb" name="tests/marc_lint_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4eb86a2f4e0a74dedcb0bf2511da6ca1" name="tests/marc_lint_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="10430fee0a1352d0528f1507b34c57e1" name="tests/marc_lint_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0dcd07a18577d7b22392a2214cd6436c" name="tests/marc_lint_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fd17798fc535562e5e64461f449516b2" name="tests/marc_record_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="141b455ccf67a60c4eac44c77960f2e2" name="tests/marc_subfield_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1e23464ee0eec47ddca2af9a9922926" name="tests/marc_subfield_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="1d7903e8c244d647220b318b4bc758d1" name="tests/marc_xml_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="22cae3c752d843b78f583dcd92801534" name="tests/marc_xml_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="c0716d23e0f960abf8d53ad6014a413a" name="tests/marc_xml_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7645fa19e28aca041a124fc5e2c12bd3" name="tests/marc_xml_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b08b28c3251625b8b6e4d7ab376b0185" name="tests/marc_xml_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6cd0934ddbf65d2d7e9ea5d108977ff7" name="tests/marc_xml_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ffdce4aa190268fa7cbbf3bb45383abf" name="tests/marc_xml_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="998a4c1ce00ff100f39ffa9fc49a212f" name="tests/marc_xml_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a38a67c590869f2b0a4859a910fd9e89" name="tests/marc_xml_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="db39c5055a570fcda12bb7c5fa1e3b4d" name="tests/marc_xml_16642.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dc075f4a271bd7182378a3874bd5b39e" name="tests/marc_xml_namespace.phpt" role="test" />
   <file baseinstalldir="File" md5sum="208200d9a979ac360c4d326e9789b6b7" name="tests/marc_xml_namespace_prefix.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d87774ede82222cfc12b2c2a06f57a3a" name="tests/marc_xml_rsinger.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fb44e3eb69f1a37115235fc829c39542" name="tests/namespace.xml" role="test" />
   <file baseinstalldir="File" md5sum="e6de4d809b0af5dd99fd352eb60616a1" name="tests/skipif.inc" role="test" />
   <file baseinstalldir="File" md5sum="a0166a4ff0bc0bb283e854f11beaa793" name="tests/music.mrc" role="test" />
   <file baseinstalldir="File" md5sum="993ce494befbc25dc1326527b30b4782" name="tests/music.xml" role="test" />
   <file baseinstalldir="File" md5sum="6b0c87f0cd459ed7322c25d403b164cc" name="tests/bigarchive.xml" role="test" />
   <file baseinstalldir="File" md5sum="be850aa6ab4ac52b8c6c214c30b574af" name="tests/onerecord.xml" role="test" />
   <file baseinstalldir="File" md5sum="4f43fec7b276267eec5258044853ccc8" name="tests/sandburg.mrc" role="test" />
   <file baseinstalldir="File" md5sum="e216b95f905dd240c9bde372950e4073" name="tests/sandburg.xml" role="test" />
   <file baseinstalldir="File" md5sum="e81a92188ea0dcd9c108a63fb32b3f4f" name="tests/xmlescape.mrc" role="test" />
   <file baseinstalldir="File" md5sum="8f9f63ed6a80191d89a2296fa4c1a30b" name="CHANGELOG" role="doc" />
   <file baseinstalldir="File" md5sum="fbc093901857fcd118f065f900982c24" name="LICENSE" role="doc" />
  </dir>
 </contents>
 <dependencies>
  <required>
   <php>
    <min>5.6</min>
   </php>
   <pearinstaller>
    <min>1.4.0</min>
   </pearinstaller>
  </required>
  <optional>
   <package>
    <name>Validate_ISPN</name>
    <channel>pear.php.net</channel>
   </package>
  </optional>
 </dependencies>
 <phprelease />
</package>
PKm�ZPi�PK��ZY�:�4p4p,.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUri   URI of the namespace
     * @param bool   $multiline      whether to create a multiline tag where each
     *                               attribute gets written to a single line
     * @param string $indent         string used to indent attributes (_auto indents
     *                               attributes so they start at the same column)
     * @param string $linebreak      string used for linebreaks
     * @param bool   $sortAttributes Whether to sort the attributes or not
     *
     * @return string XML start element
     * @see    createEndElement(), createTag()
     */
    public static function createStartElement(
        $qname, $attributes = array(), $namespaceUri = null,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true
    ) {
        // if no attributes hav been set, use empty attributes
        if (!isset($attributes) || !is_array($attributes)) {
            $attributes = array();
        }

        if ($namespaceUri != null) {
            $parts = XML_Util::splitQualifiedName($qname);
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($qname)+2));
            }
        }

        if ($namespaceUri != null) {
            // is a namespace given
            if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
            } else {
                // define this Uri as the default namespace
                $attributes['xmlns'] = $namespaceUri;
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $attributes, $sortAttributes,
            $multiline, $indent, $linebreak
        );
        $element = sprintf('<%s%s>', $qname, $attList);
        return  $element;
    }

    /**
     * Create an end element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createEndElement('myNs:myTag');
     * </code>
     *
     * @param string $qname qualified tagname (including namespace)
     *
     * @return string XML end element
     * @see    createStartElement(), createTag()
     */
    public static function createEndElement($qname)
    {
        $element = sprintf('</%s>', $qname);
        return $element;
    }

    /**
     * Create an XML comment
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createComment('I am a comment');
     * </code>
     *
     * @param string $content content of the comment
     *
     * @return string XML comment
     */
    public static function createComment($content)
    {
        $comment = sprintf('<!-- %s -->PK��ZD
�M��.registry/net_socket.regnu�[���PK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $striPK��Z*�:�|&|&.registry/auth_sasl.regnu�[���PK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return spPK��ZG�J�W�WXML/RPC/Server.phpnu�[���PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
     PK��ZioK��XML/RPC/Dump.phpnu�[���PK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $strPK��Z�/=�����XML/RPC.phpnu�[���PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUri   URI of the namespace
     * @param bool   $multiline      whether to create a multiline tag where each
     *                               attribute gets written to a single line
     * @param string $indent         string used to indent attributes (_auto indents
     *                               attributes so they start at the same column)
     * @param string $linebreak      string used for linebreaks
     * @param bool   $sortAttributes Whether to sort the attributes or not
     *
     * @return string XML start element
     * @see    createEndElement(), createTag()
     */
    public static function createStartElement(
        $qname, $attributes = array(), $namespaceUri = null,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true
    ) {
        // if no attributes hav been set, use empty attributes
        if (!isset($attributes) || !is_array($attributes)) {
            $attributes = array();
        }

        if ($namespaceUri != null) {
            $parts = XML_Util::splitQualifiedName($qname);
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($qname)+2));
            }
        }

        if ($namespaceUri != null) {
            // is a namespace given
            if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
            } else {
                // define this Uri as the default namespace
                $attributes['xmlns'] = $namespaceUri;
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $attributes, $sortAttributes,
            $multiline, $indent, $linebreak
        );
        $element = sprintf('<%s%s>', $qname, $attList);
        return  $element;
    }

    /**
     * Create an end element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createEndElement('myNs:myTag');
     * </code>
     *
     * @param string $qname qualified tagname (including namespace)
     *
     * @return string XML end element
     * @see    createStartElement(), createTag()
     */
    public static function createEndElement($qname)
    {
        $element = sprintf('</%s>', $qname);
        return $element;
    }

    /**
     * Create an XML comment
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createComment('I am a comment');
     * </code>
     *
     * @param string $content content of the comment
     *
     * @return string XML comment
     */
    public static function createComment($content)
    {
        $comment = sprintf('<!-- %s -->', $content);
        return $comment;
    }

    /**
     * Create a CData section
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create a CData section
     * $tag = XML_Util::createCDataSection('I am content.');
     * </code>
     *
     * @param string $data data of the CData section
     *
     * @return string CData section with content
     */
    public static function createCDataSection($data)
    {
        return sprintf(
            '<![CDATA[%s]]>',
            preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data))
        );
    }

    /**
     * Split qualified name and return namespace and local part
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // split qualified tag
     * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
     * </code>
     * the returned array will contain two elements:
     * <pre>
     * array(
     *     'namespace' => 'xslt',
     *     'localPart' => 'stylesheet'
     * );
     * </pre>
     *
     * @param string $qname     qualified tag name
     * @param string $defaultNs default namespace (optional)
     *
     * @return array array containing namespace and local part
     */
    public static function splitQualifiedName($qname, $defaultNs = null)
    {
        if (strstr($qname, ':')) {
            $tmp = explode(':', $qname);
            return array(
                'namespace' => $tmp[0],
                'localPart' => $tmp[1]
            );
        }
        return array(
            'namespace' => $defaultNs,
            'localPart' => $qname
        );
    }

    /**
     * Check, whether string is valid XML name
     *
     * <p>XML names are used for tagname, attribute names and various
     * other, lesser known entities.</p>
     * <p>An XML name may only consist of alphanumeric characters,
     * dashes, undescores and periods, and has to start with a letter
     * or an underscore.</p>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // verify tag name
     * $result = XML_Util::isValidName('invalidTag?');
     * if (is_a($result, 'PEAR_Error')) {
     *    print 'Invalid XML name: ' . $result->getMessage();
     * }
     * </code>
     *
     * @param string $string string that should be checked
     *
     * @return mixed true, if string is a valid XML name, PEAR error otherwise
     *
     * @todo support for other charsets
     * @todo PEAR CS - unable to avoid 85-char limit on second preg_match
     */
    public static function isValidName($string)
    {
        // check for invalid chars
        if (!is_string($string) || !strlen($string) || !preg_match('/^[[:alpha:]_]\\z/', $string[0])) {
            return XML_Util::raiseError(
                'XML names may only start with letter or underscore',
                XML_UTIL_ERROR_INVALID_START
            );
        }

        // check for invalid chars
        $match = preg_match(
            '/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?'
            . '[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/',
            $string
        );
        if (!$match) {
            return XML_Util::raiseError(
                'XML names may only contain alphanumeric '
                . 'chars, period, hyphen, colon and underscores',
                XML_UTIL_ERROR_INVALID_CHARS
            );
        }
        // XML name is valid
        return true;
    }

    /**
     * Replacement for XML_Util::raiseError
     *
     * Avoids the necessity to always require
     * PEAR.php
     *
     * @param string $msg  error message
     * @param int    $code error code
     *
     * @return PEAR_Error
     * @todo   PEAR CS - should this use include_once instead?
     */
    public static function raiseError($msg, $code)
    {
        include_once 'PEAR.php';
        return PEAR::raiseError($msg, $code);
    }
}
?>
PK��Z#F��:�:pearcmd.phpnu�[���<?php
/**
 * PEAR, the PHP Extension and Application Repository
 *
 * Command line interface
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Stig Bakken <ssb@php.net>
 * @author    Tomas V.V.Cox <cox@idecnet.com>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 */

@ob_end_clean();
if (!defined('PEAR_RUNTYPE')) {
    // this is defined in peclcmd.php as 'pecl'
    define('PEAR_RUNTYPE', 'pear');
}
define('PEAR_IGNORE_BACKTRACE', 1);
/**
 * @nodep Gtk
 */
//the space is needed for windows include paths with trailing backslash
// http://pear.php.net/bugs/bug.php?id=19482
if ('/opt/alt/php74/usr/share/pear ' != '@'.'include_path'.'@ ') {
    ini_set('include_path', trim('/opt/alt/php74/usr/share/pear '). PATH_SEPARATOR .  get_include_path());
    $raw = false;
} else {
    // this is a raw, uninstalled pear, either a cvs checkout, or php distro
    ini_set('include_path', dirname(__DIR__) . PATH_SEPARATOR . get_include_path());
    $raw = true;
}
@ini_set('allow_url_fopen', true);
@set_time_limit(0);
ob_implicit_flush(true);
@ini_set('track_errors', true);
@ini_set('html_errors', false);
$_PEAR_PHPDIR = '#$%^&*';
set_error_handler('error_handler');

$pear_package_version = "1.10.16";

require_once 'PEAR.php';
require_once 'PEAR/Frontend.php';
require_once 'PEAR/Config.php';
require_once 'PEAR/Command.php';
require_once 'Console/Getopt.php';


PEAR_Command::setFrontendType('CLI');
$all_commands = PEAR_Command::getCommands();

$argv = Console_Getopt::readPHPArgv();
// fix CGI sapi oddity - the -- in pear.bat/pear is not removed
if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
    unset($argv[1]);
    $argv = array_values($argv);
}
$progname = PEAR_RUNTYPE;
array_shift($argv);
$options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV");
if (PEAR::isError($options)) {
    usage($options);
}

$opts = $options[0];

$fetype = 'CLI';
if ($progname == 'gpear' || $progname == 'pear-gtk') {
    $fetype = 'Gtk2';
} else {
    foreach ($opts as $opt) {
        if ($opt[0] == 'G') {
            $fetype = 'Gtk2';
        }
    }
}

$pear_user_config = '';
$pear_system_config = '';
$store_user_config = false;
$store_system_config = false;
$verbose = 1;

foreach ($opts as $opt) {
    switch ($opt[0]) {
    case 'c':
        $pear_user_config = $opt[1];
        break;
    case 'C':
        $pear_system_config = $opt[1];
        break;
    }
}

PEAR_Command::setFrontendType($fetype);
$ui = &PEAR_Command::getFrontendObject();
$config = &PEAR_Config::singleton($pear_user_config, $pear_system_config);

if (PEAR::isError($config)) {
    $_file = '';
    if ($pear_user_config !== false) {
        $_file .= $pear_user_config;
    }
    if ($pear_system_config !== false) {
        $_file .= '/' . $pear_system_config;
    }
    if ($_file == '/') {
        $_file = 'The default config file';
    }
    $config->getMessage();
    $ui->outputData("ERROR: $_file is not a valid config file or is corrupted.");
    // We stop, we have no idea where we are :)
    exit(1);
}

// this is used in the error handler to retrieve a relative path
$_PEAR_PHPDIR = $config->get('php_dir');
$ui->setConfig($config);
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError"));

$verbose = $config->get("verbose");
$cmdopts = array();

if ($raw) {
    if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) {
        $found = false;
        foreach ($opts as $opt) {
            if ($opt[0] == 'd' || $opt[0] == 'D') {
                // the user knows what they are doing, and are setting config values
                $found = true;
            }
        }
        if (!$found) {
            // no prior runs, try to install PEAR
            $parent = dirname(__FILE__);
            if (strpos($parent, 'scripts')) {
                $grandparent = dirname($parent);
                $packagexml = $grandparent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $grandparent;
            } else {
                $packagexml = $parent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $parent;
            }
            if (file_exists($packagexml)) {
                $options[1] = array(
                    'install',
                    $packagexml
                );
                $config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php');
                $config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data');
                $config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs');
                $config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests');
                $config->set(
                    'ext_dir',
                    $pearbase . DIRECTORY_SEPARATOR . 'extensions'
                );
                $config->set('bin_dir', $pearbase);
                $config->mergeConfigFile($pearbase . 'pear.ini', false);
                $config->store();
                $config->set('auto_discover', 1);
            }
        }
    }
}
foreach ($opts as $opt) {
    $param = !empty($opt[1]) ? $opt[1] : true;
    switch ($opt[0]) {
    case 'd':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected -d config_value=value, ' .
                'received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'user');
        break;
    case 'D':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'system');
        break;
    case 's':
        $store_user_config = true;
        break;
    case 'S':
        $store_system_config = true;
        break;
    case 'u':
        $config->remove($param, 'user');
        break;
    case 'v':
        $config->set('verbose', $config->get('verbose') + 1);
        break;
    case 'q':
        $config->set('verbose', $config->get('verbose') - 1);
        break;
    case 'V':
        usage(null, 'version');
    case 'c':
    case 'C':
        break;
    default:
        // all non pear params goes to the command
        $cmdopts[$opt[0]] = $param;
        break;
    }
}

if ($store_system_config) {
    $config->store('system');
}

if ($store_user_config) {
    $config->store('user');
}

$command = (isset($options[1][0])) ? $options[1][0] : null;
if (empty($command) && ($store_user_config || $store_system_config)) {
    exit;
}

if ($fetype == 'Gtk2') {
    if (!$config->validConfiguration()) {
        PEAR::raiseError(
            "CRITICAL ERROR: no existing valid configuration files found in " .
            "files '$pear_user_config' or '$pear_system_config', " .
            "please copy an existing configuration file to one of these " .
            "locations, or use the -c and -s options to create one"
        );
    }
    Gtk::main();
} else {
    do {
        if ($command == 'help') {
            usage(null, isset($options[1][1]) ? $options[1][1] : null);
        }

        if (!$config->validConfiguration()) {
            PEAR::raiseError(
                "CRITICAL ERROR: no existing valid configuration files found " .
                "in files '$pear_user_config' or '$pear_system_config', " .
                "please copy an existing configuration file to one of " .
                "these locations, or use the -c and -s options to create one"
            );
        }

        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        $cmd = PEAR_Command::factory($command, $config);
        PEAR::popErrorHandling();
        if (PEAR::isError($cmd)) {
            usage(null, isset($options[1][0]) ? $options[1][0] : null);
        }

        $short_args = $long_args = null;
        PEAR_Command::getGetoptArgs($command, $short_args, $long_args);
        array_shift($options[1]);
        $tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args);

        if (PEAR::isError($tmp)) {
            break;
        }

        list($tmpopt, $params) = $tmp;
        $opts = array();
        foreach ($tmpopt as $foo => $tmp2) {
            list($opt, $value) = $tmp2;
            if ($value === null) {
                $value = true; // options without args
            }

            if (strlen($opt) == 1) {
                $cmdoptions = $cmd->getOptions($command);
                foreach ($cmdoptions as $o => $d) {
                    if (isset($d['shortopt']) && $d['shortopt'] == $opt) {
                        $opts[$o] = $value;
                    }
                }
            } else {
                if (substr($opt, 0, 2) == '--') {
                    $opts[substr($opt, 2)] = $value;
                }
            }
        }

        $ok = $cmd->run($command, $opts, $params);
        if ($ok === false) {
            PEAR::raiseError("unknown command `$command'");
        }

        if (PEAR::isError($ok)) {
            PEAR::setErrorHandling(
                PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")
            );
            PEAR::raiseError($ok);
        }
    } while (false);
}

// {{{ usage()

/**
 * Display usage information
 *
 * @param mixed $error       Optional error message
 * @param mixed $helpsubject Optional subject/command to display help for
 *
 * @return void
 */
function usage($error = null, $helpsubject = null)
{
    global $progname, $all_commands;
    $stdout = fopen('php://stdout', 'w');
    if (PEAR::isError($error)) {
        fputs($stdout, $error->getMessage() . "\n");
    } elseif ($error !== null) {
        fputs($stdout, "$error\n");
    }

    if ($helpsubject != null) {
        $put = cmdHelp($helpsubject);
    } else {
        $put = "Commands:\n";
        $maxlen = max(array_map("strlen", $all_commands));
        $formatstr = "%-{$maxlen}s  %s\n";
        ksort($all_commands);
        foreach ($all_commands as $cmd => $class) {
            $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd));
        }
        $put .=
            "Usage: $progname [options] command [command-options] <parameters>\n".
            "Type \"$progname help options\" to list all options.\n".
            "Type \"$progname help shortcuts\" to list all command shortcuts.\n".
            "Type \"$progname help version\" or ".
            "\"$progname version\" to list version information.\n".
            "Type \"$progname help <command>\" to get the help ".
            "for the specified command.";
    }
    fputs($stdout, "$put\n");
    fclose($stdout);

    if ($error === null) {
        exit(0);
    }
    exit(1);
}

/**
 * Return help string for specified command
 *
 * @param string $command Command to return help for
 *
 * @return void
 */
function cmdHelp($command)
{
    global $progname, $all_commands, $config;
    if ($command == "options") {
        return
        "Options:\n".
        "     -v         increase verbosity level (default 1)\n".
        "     -q         be quiet, decrease verbosity level\n".
        "     -c file    find user configuration in `file'\n".
        "     -C file    find system configuration in `file'\n".
        "     -d foo=bar set user config variable `foo' to `bar'\n".
        "     -D foo=bar set system config variable `foo' to `bar'\n".
        "     -G         start in graphical (Gtk) mode\n".
        "     -s         store user configuration\n".
        "     -S         store system configuration\n".
        "     -u foo     unset `foo' in the user configuration\n".
        "     -h, -?     display help/usage (this message)\n".
        "     -V         version information\n";
    } elseif ($command == "shortcuts") {
        $sc = PEAR_Command::getShortcuts();
        $ret = "Shortcuts:\n";
        foreach ($sc as $s => $c) {
            $ret .= sprintf("     %-8s %s\n", $s, $c);
        }
        return $ret;

    } elseif ($command == "version") {
        return "PEAR Version: ".$GLOBALS['pear_package_version'].
               "\nPHP Version: ".phpversion().
               "\nZend Engine Version: ".zend_version().
               "\nRunning on: ".php_uname();

    } elseif ($help = PEAR_Command::getHelp($command)) {
        if (is_string($help)) {
            return "$progname $command [options] $help\n";
        }

        if ($help[1] === null) {
            return "$progname $command $help[0]";
        }

        return "$progname $command [options] $help[0]\n$help[1]";
    }

    return "Command '$command' is not valid, try '$progname help'";
}

// }}}

/**
 * error_handler
 *
 * @param mixed $errno  Error number
 * @param mixed $errmsg Message
 * @param mixed $file   Filename
 * @param mixed $line   Line number
 *
 * @access public
 * @return boolean
 */
function error_handler($errno, $errmsg, $file, $line)
{
    if ((!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) && ($errno & E_STRICT)) {
        return; // E_STRICT
    }
    if ($errno & E_DEPRECATED) {
        return; // E_DEPRECATED
    }
    if (!(error_reporting() & $errno) &&
        isset($GLOBALS['config']) &&
        $GLOBALS['config']->get('verbose') < 4
    ) {
        return false; // @silenced error, show all if debug is high enough
    }
    $errortype = array (
        E_DEPRECATED  => 'Deprecated Warning',
        E_ERROR   =>  "Error",
        E_WARNING   =>  "Warning",
        E_PARSE   =>  "Parsing Error",
        E_NOTICE   =>  "Notice",
        E_CORE_ERROR  =>  "Core Error",
        E_CORE_WARNING  =>  "Core Warning",
        E_COMPILE_ERROR  =>  "Compile Error",
        E_COMPILE_WARNING =>  "Compile Warning",
        E_USER_ERROR =>  "User Error",
        E_USER_WARNING =>  "User Warning",
        E_USER_NOTICE =>  "User Notice"
    );
    if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) {
        $errortype[E_STRICT] = 'Strict Warning';
    }
    $prefix = $errortype[$errno];
    global $_PEAR_PHPDIR;
    if (stristr($file, $_PEAR_PHPDIR)) {
        $file = substr($file, strlen($_PEAR_PHPDIR) + 1);
    } else {
        $file = basename($file);
    }
    print "\n$prefix: $errmsg in $file on line $line\n";
    return false;
}


/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * indent-tabs-mode: nil
 * mode: php
 * End:
 */
// vim600:syn=php
PK��Z�0$�-- .pkgxml/Pear_File_MARC-1.4.1.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.10.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
 <name>File_MARC</name>
 <channel>pear.php.net</channel>
 <summary>Parse, modify, and create MARC records</summary>
 <description>The standard for machine-readable cataloging (MARC) records is documented at http://loc.gov/marc/. This package enables you to read existing MARC records from a file, string, or (using the YAZ extension), from a Z39.50 source. You can also use this package to create new MARC records.

This package is based on the PHP MARC package, originally called &quot;php-marc&quot;, that is part of the Emilda Project (http://www.emilda.org).  Christoffer Landtman generously agreed to make the &quot;php-marc&quot; code available under the GNU LGPL so it could be used as the basis of this PEAR package.</description>
 <lead>
  <name>Dan Scott</name>
  <user>dbs</user>
  <email>dbs@php.net</email>
  <active>yes</active>
 </lead>
 <date>2019-11-13</date>
 <time>17:33:33</time>
 <version>
  <release>1.4.1</release>
  <api>1.4.0</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license uri="http://www.gnu.org/copyleft/lesser.html">GNU Lesser General Public License</license>
 <notes>
1.4.1
  * Reintroduce include_path to composer.json
 </notes>
 <contents>
  <dir baseinstalldir="File" name="/">
   <file baseinstalldir="/" md5sum="ffe2590635f404af055fe731da105939" name="File/MARC/Lint/CodeData.php" role="php" />
   <file baseinstalldir="/" md5sum="a3b9e1c817e67f59add05593500d463e" name="File/MARC/Control_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="acba4463f8e40d6ee4e7ba1f2dc53123" name="File/MARC/Data_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="378f483ec1fd161cd9dfb9b05db58d66" name="File/MARC/Exception.php" role="php" />
   <file baseinstalldir="/" md5sum="a9ba69030cbf4847292b9975e9d922c6" name="File/MARC/Field.php" role="php" />
   <file baseinstalldir="/" md5sum="c37351c7c80927ce6bb1e662510f9183" name="File/MARC/Lint.php" role="php" />
   <file baseinstalldir="/" md5sum="c5ac39e3d25eb0108b9dd5ad8466c821" name="File/MARC/List.php" role="php" />
   <file baseinstalldir="/" md5sum="7af6ce78cde4bb246e4e96709e90d2c0" name="File/MARC/Record.php" role="php" />
   <file baseinstalldir="/" md5sum="df5f97139685f0ad04e47fdbb67e3968" name="File/MARC/Subfield.php" role="php" />
   <file baseinstalldir="/" md5sum="6e102262dfd5d65d8d5a6221dfc74edd" name="File/MARC.php" role="php" />
   <file baseinstalldir="/" md5sum="8b64040d2d18ac4b994595a148266a66" name="File/MARCBASE.php" role="php" />
   <file baseinstalldir="/" md5sum="f5a17a60d34e84e2ee7ca1e5c5c6c620" name="File/MARCXML.php" role="php" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="examples/example.mrc" role="doc" />
   <file baseinstalldir="File" md5sum="1aea40df9f1c2e32f8e065fe8da0a3b5" name="examples/marc_yaz.php" role="doc" />
   <file baseinstalldir="File" md5sum="70ae317e0890d5896e3ffccdd293369a" name="examples/read.php" role="doc" />
   <file baseinstalldir="File" md5sum="54efb9d920ac775bfc847a83a2dec73a" name="examples/subfields.php" role="doc" />
   <file baseinstalldir="File" md5sum="14297da35b510c496cd1f328cf3bb301" name="tests/bad_example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="0dd4c6dbad6e8608d0ebf9d24425955d" name="tests/bad_example.xml" role="test" />
   <file baseinstalldir="File" md5sum="216a6f9d53f6d3d8e22d81fdc10f4bc1" name="tests/camel.mrc" role="test" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="tests/example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="9455aec3371f79cf7d31281fd03f5171" name="tests/marc_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="577e2f5f89fd48cf1a3576a29d2958f8" name="tests/marc_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a6a586354b9a06c880c2a7470dd828d7" name="tests/marc_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1c7e2fc5572a0f9362a771c260a1fe3" name="tests/marc_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="84f85ac7f8a2532e4e90ccde7764556a" name="tests/marc_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="889e5e906a97de7a0e94b0c5f30e70e7" name="tests/marc_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="be823dc8a8efb408de06371ab802efcc" name="tests/marc_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="af44490aafea44e5120f881cb81cdad9" name="tests/marc_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ac9f2a7aeb24900a11f5102744179ae3" name="tests/marc_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5e43eb5cddbb4f2bd0d6405cd95b80aa" name="tests/marc_010.phpt" role="test" />
   <file baseinstalldir="File" md5sum="2e1cd8509c0bf04ec77fc0f51375f611" name="tests/marc_011.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bc49ca48623102c8ac07679fa77a3dd9" name="tests/marc_012.phpt" role="test" />
   <file baseinstalldir="File" md5sum="245a3b20e0da1973535503e28efd1d3a" name="tests/marc_013.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ce69aa734856dd40d60d30c77bdef53a" name="tests/marc_014.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7b61cdd31035e60682fa92c5d519d997" name="tests/marc_015.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7f4f597fe1adaa3507eb87fc4875dbd2" name="tests/marc_016.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4262efd5fcacbd7503323681f4552430" name="tests/marc_017.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ee1623d7bda54ba4f741b2319b158f82" name="tests/marc_018.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8006c03fbab0f04377342086fafd3982" name="tests/marc_019.phpt" role="test" />
   <file baseinstalldir="File" md5sum="f5ae5b25e0ac1104314433d9e5b1f7fe" name="tests/marc_020.phpt" role="test" />
   <file baseinstalldir="File" md5sum="94d8f99e86585671a1b2d3043aeb6360" name="tests/marc_021.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bb891a890effe0e77e1759043f4846d8" name="tests/marc_022.phpt" role="test" />
   <file baseinstalldir="File" md5sum="faf77dcb5cdd002c09169a14bfded65e" name="tests/marc_023.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0e6c4a23f5da7df64fdd4b3b1149bbee" name="tests/marc_16783.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4ea8b3520beda378db15960f1c50493a" name="tests/marc_field_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="743850ef61df69c4340be44a03bccb5a" name="tests/marc_field_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8c765f1398b49df257d86d22ac6e4f8d" name="tests/marc_field_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d4216cf930a308e0d02553bd3914f294" name="tests/marc_field_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dd59514b474b78371ad522a3e13b76b7" name="tests/marc_field_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5295bfd02a8424acac1c91de26b552c7" name="tests/marc_field_21246.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6f95f09442ccf6b93df92986f58b270d" name="tests/marc_lint_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="18d721f8871edd925624ccbdd15444fb" name="tests/marc_lint_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4eb86a2f4e0a74dedcb0bf2511da6ca1" name="tests/marc_lint_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="10430fee0a1352d0528f1507b34c57e1" name="tests/marc_lint_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0dcd07a18577d7b22392a2214cd6436c" name="tests/marc_lint_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fd17798fc535562e5e64461f449516b2" name="tests/marc_record_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="141b455ccf67a60c4eac44c77960f2e2" name="tests/marc_subfield_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1e23464ee0eec47ddca2af9a9922926" name="tests/marc_subfield_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="1d7903e8c244d647220b318b4bc758d1" name="tests/marc_xml_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="22cae3c752d843b78f583dcd92801534" name="tests/marc_xml_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="c0716d23e0f960abf8d53ad6014a413a" name="tests/marc_xml_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7645fa19e28aca041a124fc5e2c12bd3" name="tests/marc_xml_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b08b28c3251625b8b6e4d7ab376b0185" name="tests/marc_xml_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6cd0934ddbf65d2d7e9ea5d108977ff7" name="tests/marc_xml_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ffdce4aa190268fa7cbbf3bb45383abf" name="tests/marc_xml_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="998a4c1ce00ff100f39ffa9fc49a212f" name="tests/marc_xml_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a38a67c590869f2b0a4859a910fd9e89" name="tests/marc_xml_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="db39c5055a570fcda12bb7c5fa1e3b4d" name="tests/marc_xml_16642.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dc075f4a271bd7182378a3874bd5b39e" name="tests/marc_xml_namespace.phpt" role="test" />
   <file baseinstalldir="File" md5sum="208200d9a979ac360c4d326e9789b6b7" name="tests/marc_xml_namespace_prefix.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d87774ede82222cfc12b2c2a06f57a3a" name="tests/marc_xml_rsinger.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fb44e3eb69f1a37115235fc829c39542" name="tests/namespace.xml" role="test" />
   <file baseinstalldir="File" md5sum="e6de4d809b0af5dd99fd352eb60616a1" name="tests/skipif.inc" role="test" />
   <file baseinstalldir="File" md5sum="a0166a4ff0bc0bb283e854f11beaa793" name="tests/music.mrc" role="test" />
   <file baseinstalldir="File" md5sum="993ce494befbc25dc1326527b30b4782" name="tests/music.xml" role="test" />
   <file baseinstalldir="File" md5sum="6b0c87f0cd459ed7322c25d403b164cc" name="tests/bigarchive.xml" role="test" />
   <file baseinstalldir="File" md5sum="be850aa6ab4ac52b8c6c214c30b574af" name="tests/onerecord.xml" role="test" />
   <file baseinstalldir="File" md5sum="4f43fec7b276267eec5258044853ccc8" name="tests/sandburg.mrc" role="test" />
   <file baseinstalldir="File" md5sum="e216b95f905dd240c9bde372950e4073" name="tests/sandburg.xml" role="test" />
   <file baseinstalldir="File" md5sum="e81a92188ea0dcd9c108a63fb32b3f4f" name="tests/xmlescape.mrc" role="test" />
   <file baseinstalldir="File" md5sum="8f9f63ed6a80191d89a2296fa4c1a30b" name="CHANGELOG" role="doc" />
   <file baseinstalldir="File" md5sum="fbc093901857fcd118f065f900982c24" name="LICENSE" role="doc" />
  </dir>
 </contents>
 <dependencies>
  <required>
   <php>
    <min>5.6</min>
   </php>
   <pearinstaller>
    <min>1.4.0</min>
   </pearinstaller>
  </required>
  <optional>
   <package>
    <name>Validate_ISPN</name>
    <channel>pear.php.net</channel>
   </package>
  </optional>
 </dependencies>
 <phprelease />
</package>
PKm�ZPi��.depdbnu�[���PKm�Z�{��
�Mail/null.phpnu�[���PKm�ZE@�%>>
Mail/sendmail.phpnu�[���PKm�Z��A~�{�{�;Mail/RFC822.phpnu�[���PKn�Z�+V����
[�Mail/mime.phpnu�[���PKn�Zx�ع���D�Mail/mimeDecode.phpnu�[���PKn�ZB�_Ǭ=�=
@(Mail/smtp.phpnu�[���PKn�ZwԐE;E;)fMail/smtpmx.phpnu�[���PKn�Z�؛�J�J���Mail/mimePart.phpnu�[���PKn�ZB��shh
8YMail/mock.phpnu�[���PKn�Z@iE�\\
�lMail/mail.phpnu�[���PKn�Zv�.locknu�[���PKn�Z�*�z%-%- PK��Zc���}�}XML/Util.phpnu�[���<?php
/**
 * XML_Util
 *
 * XML Utilities package
 *
 * PHP versions 4 and 5
 *
 * LICENSE:
 *
 * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/XML_Util
 */

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_CHARS', 51);

/**
 * Error code for invalid chars in XML name
 */
define('XML_UTIL_ERROR_INVALID_START', 52);

/**
 * Error code for non-scalar tag content
 */
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);

/**
 * Error code for missing tag name
 */
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);

/**
 * Replace XML entities
 */
define('XML_UTIL_REPLACE_ENTITIES', 1);

/**
 * Embedd content in a CData Section
 */
define('XML_UTIL_CDATA_SECTION', 5);

/**
 * Do not replace entitites
 */
define('XML_UTIL_ENTITIES_NONE', 0);

/**
 * Replace all XML entitites
 * This setting will replace <, >, ", ' and &
 */
define('XML_UTIL_ENTITIES_XML', 1);

/**
 * Replace only required XML entitites
 * This setting will replace <, " and &
 */
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);

/**
 * Replace HTML entitites
 * @link http://www.php.net/htmlentities
 */
define('XML_UTIL_ENTITIES_HTML', 3);

/**
 * Do not collapse any empty tags.
 */
define('XML_UTIL_COLLAPSE_NONE', 0);

/**
 * Collapse all empty tags.
 */
define('XML_UTIL_COLLAPSE_ALL', 1);

/**
 * Collapse only empty XHTML tags that have no end tag.
 */
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);

/**
 * Utility class for working with XML documents
 *
 * @category  XML
 * @package   XML_Util
 * @author    Stephan Schmidt <schst@php.net>
 * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
 * @license   http://opensource.org/licenses/bsd-license New BSD License
 * @version   Release: 1.4.5
 * @link      http://pear.php.net/package/XML_Util
 */
class XML_Util
{
    /**
     * Return API version
     *
     * @return string $version API version
     */
    public static function apiVersion()
    {
        return '1.4';
    }

    /**
     * Replace XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be replaced.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites:
     * $string = XML_Util::replaceEntities('This string contains < & >.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // replace XML entites in UTF-8:
     * $string = XML_Util::replaceEntities(
     *     'This string contains < & > as well as ä, ö, ß, à and ê',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the htmlentities() function
     *
     * @return string string with replaced chars
     * @see    reverseEntities()
     */
    public static function replaceEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&'  => '&amp;',
                    '>'  => '&gt;',
                    '<'  => '&lt;',
                    '"'  => '&quot;',
                    '\'' => '&apos;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&' => '&amp;',
                    '<' => '&lt;',
                    '"' => '&quot;'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return htmlentities($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Reverse XML entities
     *
     * With the optional second parameter, you may select, which
     * entities should be reversed.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites:
     * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
     * </code>
     *
     * With the optional third parameter, you may pass the character encoding
     * <code>
     * require_once 'XML/Util.php';
     *
     * // reverse XML entites in UTF-8:
     * $string = XML_Util::reverseEntities(
     *     'This string contains &lt; &amp; &gt; as well as'
     *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
     *     XML_UTIL_ENTITIES_HTML,
     *     'UTF-8'
     * );
     * </code>
     *
     * @param string $string          string where XML special chars
     *                                should be replaced
     * @param int    $replaceEntities setting for entities in attribute values
     *                                (one of XML_UTIL_ENTITIES_XML,
     *                                XML_UTIL_ENTITIES_XML_REQUIRED,
     *                                XML_UTIL_ENTITIES_HTML)
     * @param string $encoding        encoding value (if any)...
     *                                must be a valid encoding as determined
     *                                by the html_entity_decode() function
     *
     * @return string string with replaced chars
     * @see    replaceEntities()
     */
    public static function reverseEntities(
        $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
    ) {
        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_XML:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&gt;'   => '>',
                    '&lt;'   => '<',
                    '&quot;' => '"',
                    '&apos;' => '\''
                )
            );
            break;
        case XML_UTIL_ENTITIES_XML_REQUIRED:
            return strtr(
                $string,
                array(
                    '&amp;'  => '&',
                    '&lt;'   => '<',
                    '&quot;' => '"'
                )
            );
            break;
        case XML_UTIL_ENTITIES_HTML:
            return html_entity_decode($string, ENT_COMPAT, $encoding);
            break;
        }
        return $string;
    }

    /**
     * Build an xml declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get an XML declaration:
     * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
     * </code>
     *
     * @param string $version    xml version
     * @param string $encoding   character encoding
     * @param bool   $standalone document is standalone (or not)
     *
     * @return string xml declaration
     * @uses   attributesToString() to serialize the attributes of the
     *         XML declaration
     */
    public static function getXMLDeclaration(
        $version = '1.0', $encoding = null, $standalone = null
    ) {
        $attributes = array(
            'version' => $version,
        );
        // add encoding
        if ($encoding !== null) {
            $attributes['encoding'] = $encoding;
        }
        // add standalone, if specified
        if ($standalone !== null) {
            $attributes['standalone'] = $standalone ? 'yes' : 'no';
        }

        return sprintf(
            '<?xml%s?>',
            XML_Util::attributesToString($attributes, false)
        );
    }

    /**
     * Build a document type declaration
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // get a doctype declaration:
     * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
     * </code>
     *
     * @param string $root        name of the root tag
     * @param string $uri         uri of the doctype definition
     *                            (or array with uri and public id)
     * @param string $internalDtd internal dtd entries
     *
     * @return string doctype declaration
     * @since  0.2
     */
    public static function getDocTypeDeclaration(
        $root, $uri = null, $internalDtd = null
    ) {
        if (is_array($uri)) {
            $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
        } elseif (!empty($uri)) {
            $ref = sprintf(' SYSTEM "%s"', $uri);
        } else {
            $ref = '';
        }

        if (empty($internalDtd)) {
            return sprintf('<!DOCTYPE %s%s>', $root, $ref);
        } else {
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
        }
    }

    /**
     * Create string representation of an attribute list
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // build an attribute string
     * $att = array(
     *              'foo'   =>  'bar',
     *              'argh'  =>  'tomato'
     *            );
     *
     * $attList = XML_Util::attributesToString($att);
     * </code>
     *
     * @param array      $attributes attribute array
     * @param bool|array $sort       sort attribute list alphabetically,
     *                               may also be an assoc array containing
     *                               the keys 'sort', 'multiline', 'indent',
     *                               'linebreak' and 'entities'
     * @param bool       $multiline  use linebreaks, if more than
     *                               one attribute is given
     * @param string     $indent     string used for indentation of
     *                               multiline attributes
     * @param string     $linebreak  string used for linebreaks of
     *                               multiline attributes
     * @param int        $entities   setting for entities in attribute values
     *                               (one of XML_UTIL_ENTITIES_NONE,
     *                               XML_UTIL_ENTITIES_XML,
     *                               XML_UTIL_ENTITIES_XML_REQUIRED,
     *                               XML_UTIL_ENTITIES_HTML)
     *
     * @return string string representation of the attributes
     * @uses   replaceEntities() to replace XML entities in attribute values
     * @todo   allow sort also to be an options array
     */
    public static function attributesToString(
        $attributes, $sort = true, $multiline = false,
        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
    ) {
        /*
         * second parameter may be an array
         */
        if (is_array($sort)) {
            if (isset($sort['multiline'])) {
                $multiline = $sort['multiline'];
            }
            if (isset($sort['indent'])) {
                $indent = $sort['indent'];
            }
            if (isset($sort['linebreak'])) {
                $multiline = $sort['linebreak'];
            }
            if (isset($sort['entities'])) {
                $entities = $sort['entities'];
            }
            if (isset($sort['sort'])) {
                $sort = $sort['sort'];
            } else {
                $sort = true;
            }
        }
        $string = '';
        if (is_array($attributes) && !empty($attributes)) {
            if ($sort) {
                ksort($attributes);
            }
            if (!$multiline || count($attributes) == 1) {
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        if ($entities === XML_UTIL_CDATA_SECTION) {
                            $entities = XML_UTIL_ENTITIES_XML;
                        }
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    $string .= ' ' . $key . '="' . $value . '"';
                }
            } else {
                $first = true;
                foreach ($attributes as $key => $value) {
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
                        $value = XML_Util::replaceEntities($value, $entities);
                    }
                    if ($first) {
                        $string .= ' ' . $key . '="' . $value . '"';
                        $first   = false;
                    } else {
                        $string .= $linebreak . $indent . $key . '="' . $value . '"';
                    }
                }
            }
        }
        return $string;
    }

    /**
     * Collapses empty tags.
     *
     * @param string $xml  XML
     * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
     *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
     *
     * @return string XML
     */
    public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
    {
        if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
            // it's already an empty tag
            return $xml;
        }
        switch ($mode) {
            case XML_UTIL_COLLAPSE_ALL:
                $preg1 =
                    '~<' .
                        '(?:' .
                            '(https?://[^:\s]+:\w+)' .  // <http://foo.com:bar  ($1)
                            '|(\w+:\w+)' .              // <foo:bar             ($2)
                            '|(\w+)' .                  // <foo                 ($3)
                        ')+' .
                        '([^>]*)' .                     // attributes           ($4)
                    '>' .
                    '<\/(\1|\2|\3)>' .                  // 1, 2, or 3 again     ($5)
                    '~s'
                ;
                $preg2 =
                    '<' .
                        '${1}${2}${3}' .    // tag (only one should have been populated)
                        '${4}' .            // attributes
                    ' />'
                ;
                return (preg_replace($preg1, $preg2, $xml)?:$xml);
                break;
            case XML_UTIL_COLLAPSE_XHTML_ONLY:
                return (
                    preg_replace(
                        '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                        . 'param)([^>]*)><\/\\1>/s',
                        '<\\1\\2 />',
                        $xml
                    ) ?: $xml
                );
                break;
            case XML_UTIL_COLLAPSE_NONE:
                // fall thru
            default:
                return $xml;
        }
    }

    /**
     * Create a tag
     *
     * This method will call XML_Util::createTagFromArray(), which
     * is more flexible.
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML tag:
     * $tag = XML_Util::createTag('myNs:myTag',
     *     array('foo' => 'bar'),
     *     'This is inside the tag',
     *     'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname           qualified tagname (including namespace)
     * @param array  $attributes      array containg attributes
     * @param mixed  $content         the content
     * @param string $namespaceUri    URI of the namespace
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where
     *                                each attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     * @see    createTagFromArray()
     * @uses   createTagFromArray() to create the tag
     */
    public static function createTag(
        $qname, $attributes = array(), $content = null,
        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        $tag = array(
            'qname'      => $qname,
            'attributes' => $attributes
        );

        // add tag content
        if ($content !== null) {
            $tag['content'] = $content;
        }

        // add namespace Uri
        if ($namespaceUri !== null) {
            $tag['namespaceUri'] = $namespaceUri;
        }

        return XML_Util::createTagFromArray(
            $tag, $replaceEntities, $multiline,
            $indent, $linebreak, $sortAttributes,
            $collapseTagMode
        );
    }

    /**
     * Create a tag from an array.
     * This method awaits an array in the following format
     * <pre>
     * array(
     *     // qualified name of the tag
     *     'qname' => $qname
     *
     *     // namespace prefix (optional, if qname is specified or no namespace)
     *     'namespace' => $namespace
     *
     *     // local part of the tagname (optional, if qname is specified)
     *     'localpart' => $localpart,
     *
     *     // array containing all attributes (optional)
     *     'attributes' => array(),
     *
     *     // tag content (optional)
     *     'content' => $content,
     *
     *     // namespaceUri for the given namespace (optional)
     *     'namespaceUri' => $namespaceUri
     * )
     * </pre>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * $tag = array(
     *     'qname'        => 'foo:bar',
     *     'namespaceUri' => 'http://foo.com',
     *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
     *     'content'      => 'I\'m inside the tag',
     * );
     * // creating a tag with qualified name and namespaceUri
     * $string = XML_Util::createTagFromArray($tag);
     * </code>
     *
     * @param array  $tag             tag definition
     * @param int    $replaceEntities whether to replace XML special chars in
     *                                content, embedd it in a CData section
     *                                or none of both
     * @param bool   $multiline       whether to create a multiline tag where each
     *                                attribute gets written to a single line
     * @param string $indent          string used to indent attributes
     *                                (_auto indents attributes so they start
     *                                at the same column)
     * @param string $linebreak       string used for linebreaks
     * @param bool   $sortAttributes  Whether to sort the attributes or not
     * @param int    $collapseTagMode How to handle a content-less, and thus collapseable, tag
     *
     * @return string XML tag
     *
     * @see  createTag()
     * @uses attributesToString() to serialize the attributes of the tag
     * @uses splitQualifiedName() to get local part and namespace of a qualified name
     * @uses createCDataSection()
     * @uses collapseEmptyTags()
     * @uses raiseError()
     */
    public static function createTagFromArray(
        $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
    ) {
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
            return XML_Util::raiseError(
                'Supplied non-scalar value as tag content',
                XML_UTIL_ERROR_NON_SCALAR_CONTENT
            );
        }

        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
            return XML_Util::raiseError(
                'You must either supply a qualified name '
                . '(qname) or local tag name (localPart).',
                XML_UTIL_ERROR_NO_TAG_NAME
            );
        }

        // if no attributes hav been set, use empty attributes
        if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
            $tag['attributes'] = array();
        }

        if (isset($tag['namespaces'])) {
            foreach ($tag['namespaces'] as $ns => $uri) {
                $tag['attributes']['xmlns:' . $ns] = $uri;
            }
        }

        if (!isset($tag['qname'])) {
            // qualified name is not given

            // check for namespace
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
            } else {
                $tag['qname'] = $tag['localPart'];
            }
        } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
            // namespace URI is set, but no namespace

            $parts = XML_Util::splitQualifiedName($tag['qname']);

            $tag['localPart'] = $parts['localPart'];
            if (isset($parts['namespace'])) {
                $tag['namespace'] = $parts['namespace'];
            }
        }

        if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
            // is a namespace given
            if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                $tag['attributes']['xmlns:' . $tag['namespace']]
                    = $tag['namespaceUri'];
            } else {
                // define this Uri as the default namespace
                $tag['attributes']['xmlns'] = $tag['namespaceUri'];
            }
        }

        if (!array_key_exists('content', $tag)) {
            $tag['content'] = '';
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($tag['qname'])+2));
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $tag['attributes'],
            $sortAttributes, $multiline, $indent, $linebreak
        );

        switch ($replaceEntities) {
        case XML_UTIL_ENTITIES_NONE:
            break;
        case XML_UTIL_CDATA_SECTION:
            $tag['content'] = XML_Util::createCDataSection($tag['content']);
            break;
        default:
            $tag['content'] = XML_Util::replaceEntities(
                $tag['content'], $replaceEntities
            );
            break;
        }
        $tag = sprintf(
            '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
            $tag['qname']
        );

        return self::collapseEmptyTags($tag, $collapseTagMode);
    }

    /**
     * Create a start element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createStartElement('myNs:myTag',
     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
     * </code>
     *
     * @param string $qname          qualified tagname (including namespace)
     * @param array  $attributes     array containg attributes
     * @param string $namespaceUri   URI of the namespace
     * @param bool   $multiline      whether to create a multiline tag where each
     *                               attribute gets written to a single line
     * @param string $indent         string used to indent attributes (_auto indents
     *                               attributes so they start at the same column)
     * @param string $linebreak      string used for linebreaks
     * @param bool   $sortAttributes Whether to sort the attributes or not
     *
     * @return string XML start element
     * @see    createEndElement(), createTag()
     */
    public static function createStartElement(
        $qname, $attributes = array(), $namespaceUri = null,
        $multiline = false, $indent = '_auto', $linebreak = "\n",
        $sortAttributes = true
    ) {
        // if no attributes hav been set, use empty attributes
        if (!isset($attributes) || !is_array($attributes)) {
            $attributes = array();
        }

        if ($namespaceUri != null) {
            $parts = XML_Util::splitQualifiedName($qname);
        }

        // check for multiline attributes
        if ($multiline === true) {
            if ($indent === '_auto') {
                $indent = str_repeat(' ', (strlen($qname)+2));
            }
        }

        if ($namespaceUri != null) {
            // is a namespace given
            if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
            } else {
                // define this Uri as the default namespace
                $attributes['xmlns'] = $namespaceUri;
            }
        }

        // create attribute list
        $attList = XML_Util::attributesToString(
            $attributes, $sortAttributes,
            $multiline, $indent, $linebreak
        );
        $element = sprintf('<%s%s>', $qname, $attList);
        return  $element;
    }

    /**
     * Create an end element
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createEndElement('myNs:myTag');
     * </code>
     *
     * @param string $qname qualified tagname (including namespace)
     *
     * @return string XML end element
     * @see    createStartElement(), createTag()
     */
    public static function createEndElement($qname)
    {
        $element = sprintf('</%s>', $qname);
        return $element;
    }

    /**
     * Create an XML comment
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create an XML start element:
     * $tag = XML_Util::createComment('I am a comment');
     * </code>
     *
     * @param string $content content of the comment
     *
     * @return string XML comment
     */
    public static function createComment($content)
    {
        $comment = sprintf('<!-- %s -->', $content);
        return $comment;
    }

    /**
     * Create a CData section
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // create a CData section
     * $tag = XML_Util::createCDataSection('I am content.');
     * </code>
     *
     * @param string $data data of the CData section
     *
     * @return string CData section with content
     */
    public static function createCDataSection($data)
    {
        return sprintf(
            '<![CDATA[%s]]>',
            preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data))
        );
    }

    /**
     * Split qualified name and return namespace and local part
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // split qualified tag
     * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
     * </code>
     * the returned array will contain two elements:
     * <pre>
     * array(
     *     'namespace' => 'xslt',
     *     'localPart' => 'stylesheet'
     * );
     * </pre>
     *
     * @param string $qname     qualified tag name
     * @param string $defaultNs default namespace (optional)
     *
     * @return array array containing namespace and local part
     */
    public static function splitQualifiedName($qname, $defaultNs = null)
    {
        if (strstr($qname, ':')) {
            $tmp = explode(':', $qname);
            return array(
                'namespace' => $tmp[0],
                'localPart' => $tmp[1]
            );
        }
        return array(
            'namespace' => $defaultNs,
            'localPart' => $qname
        );
    }

    /**
     * Check, whether string is valid XML name
     *
     * <p>XML names are used for tagname, attribute names and various
     * other, lesser known entities.</p>
     * <p>An XML name may only consist of alphanumeric characters,
     * dashes, undescores and periods, and has to start with a letter
     * or an underscore.</p>
     *
     * <code>
     * require_once 'XML/Util.php';
     *
     * // verify tag name
     * $result = XML_Util::isValidName('invalidTag?');
     * if (is_a($result, 'PEAR_Error')) {
     *    print 'Invalid XML name: ' . $result->getMessage();
     * }
     * </code>
     *
     * @param string $string string that should be checked
     *
     * @return mixed true, if string is a valid XML name, PEAR error otherwise
     *
     * @todo support for other charsets
     * @todo PEAR CS - unable to avoid 85-char limit on second preg_match
     */
    public static function isValidName($string)
    {
        // check for invalid chars
        if (!is_string($string) || !strlen($string) || !preg_match('/^[[:alpha:]_]\\z/', $string[0])) {
            return XML_Util::raiseError(
                'XML names may only start with letter or underscore',
                XML_UTIL_ERROR_INVALID_START
            );
        }

        // check for invalid chars
        $match = preg_match(
            '/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?'
            . '[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/',
            $string
        );
        if (!$match) {
            return XML_Util::raiseError(
                'XML names may only contain alphanumeric '
                . 'chars, period, hyphen, colon and underscores',
                XML_UTIL_ERROR_INVALID_CHARS
            );
        }
        // XML name is valid
        return true;
    }

    /**
     * Replacement for XML_Util::raiseError
     *
     * Avoids the necessity to always require
     * PEAR.php
     *
     * @param string $msg  error message
     * @param int    $code error code
     *
     * @return PEAR_Error
     * @todo   PEAR CS - should this use include_once instead?
     */
    public static function raiseError($msg, $code)
    {
        include_once 'PEAR.php';
        return PEAR::raiseError($msg, $code);
    }
}
?>
PK��Z#F��:�:pearcmd.phpnu�[���<?php
/**
 * PEAR, the PHP Extension and Application Repository
 *
 * Command line interface
 *
 * PHP versions 4 and 5
 *
 * @category  pear
 * @package   PEAR
 * @author    Stig Bakken <ssb@php.net>
 * @author    Tomas V.V.Cox <cox@idecnet.com>
 * @copyright 1997-2009 The Authors
 * @license   http://opensource.org/licenses/bsd-license.php New BSD License
 * @link      http://pear.php.net/package/PEAR
 */

@ob_end_clean();
if (!defined('PEAR_RUNTYPE')) {
    // this is defined in peclcmd.php as 'pecl'
    define('PEAR_RUNTYPE', 'pear');
}
define('PEAR_IGNORE_BACKTRACE', 1);
/**
 * @nodep Gtk
 */
//the space is needed for windows include paths with trailing backslash
// http://pear.php.net/bugs/bug.php?id=19482
if ('/opt/alt/php74/usr/share/pear ' != '@'.'include_path'.'@ ') {
    ini_set('include_path', trim('/opt/alt/php74/usr/share/pear '). PATH_SEPARATOR .  get_include_path());
    $raw = false;
} else {
    // this is a raw, uninstalled pear, either a cvs checkout, or php distro
    ini_set('include_path', dirname(__DIR__) . PATH_SEPARATOR . get_include_path());
    $raw = true;
}
@ini_set('allow_url_fopen', true);
@set_time_limit(0);
ob_implicit_flush(true);
@ini_set('track_errors', true);
@ini_set('html_errors', false);
$_PEAR_PHPDIR = '#$%^&*';
set_error_handler('error_handler');

$pear_package_version = "1.10.16";

require_once 'PEAR.php';
require_once 'PEAR/Frontend.php';
require_once 'PEAR/Config.php';
require_once 'PEAR/Command.php';
require_once 'Console/Getopt.php';


PEAR_Command::setFrontendType('CLI');
$all_commands = PEAR_Command::getCommands();

$argv = Console_Getopt::readPHPArgv();
// fix CGI sapi oddity - the -- in pear.bat/pear is not removed
if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
    unset($argv[1]);
    $argv = array_values($argv);
}
$progname = PEAR_RUNTYPE;
array_shift($argv);
$options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV");
if (PEAR::isError($options)) {
    usage($options);
}

$opts = $options[0];

$fetype = 'CLI';
if ($progname == 'gpear' || $progname == 'pear-gtk') {
    $fetype = 'Gtk2';
} else {
    foreach ($opts as $opt) {
        if ($opt[0] == 'G') {
            $fetype = 'Gtk2';
        }
    }
}

$pear_user_config = '';
$pear_system_config = '';
$store_user_config = false;
$store_system_config = false;
$verbose = 1;

foreach ($opts as $opt) {
    switch ($opt[0]) {
    case 'c':
        $pear_user_config = $opt[1];
        break;
    case 'C':
        $pear_system_config = $opt[1];
        break;
    }
}

PEAR_Command::setFrontendType($fetype);
$ui = &PEAR_Command::getFrontendObject();
$config = &PEAR_Config::singleton($pear_user_config, $pear_system_config);

if (PEAR::isError($config)) {
    $_file = '';
    if ($pear_user_config !== false) {
        $_file .= $pear_user_config;
    }
    if ($pear_system_config !== false) {
        $_file .= '/' . $pear_system_config;
    }
    if ($_file == '/') {
        $_file = 'The default config file';
    }
    $config->getMessage();
    $ui->outputData("ERROR: $_file is not a valid config file or is corrupted.");
    // We stop, we have no idea where we are :)
    exit(1);
}

// this is used in the error handler to retrieve a relative path
$_PEAR_PHPDIR = $config->get('php_dir');
$ui->setConfig($config);
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError"));

$verbose = $config->get("verbose");
$cmdopts = array();

if ($raw) {
    if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) {
        $found = false;
        foreach ($opts as $opt) {
            if ($opt[0] == 'd' || $opt[0] == 'D') {
                // the user knows what they are doing, and are setting config values
                $found = true;
            }
        }
        if (!$found) {
            // no prior runs, try to install PEAR
            $parent = dirname(__FILE__);
            if (strpos($parent, 'scripts')) {
                $grandparent = dirname($parent);
                $packagexml = $grandparent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $grandparent;
            } else {
                $packagexml = $parent . DIRECTORY_SEPARATOR . 'package2.xml';
                $pearbase = $parent;
            }
            if (file_exists($packagexml)) {
                $options[1] = array(
                    'install',
                    $packagexml
                );
                $config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php');
                $config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data');
                $config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs');
                $config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests');
                $config->set(
                    'ext_dir',
                    $pearbase . DIRECTORY_SEPARATOR . 'extensions'
                );
                $config->set('bin_dir', $pearbase);
                $config->mergeConfigFile($pearbase . 'pear.ini', false);
                $config->store();
                $config->set('auto_discover', 1);
            }
        }
    }
}
foreach ($opts as $opt) {
    $param = !empty($opt[1]) ? $opt[1] : true;
    switch ($opt[0]) {
    case 'd':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected -d config_value=value, ' .
                'received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'user');
        break;
    case 'D':
        if ($param === true) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "-d"' . "\n"
            );
        }
        $possible = explode('=', $param);
        if (count($possible) != 2) {
            die(
                'Invalid usage of "-d" option, expected ' .
                '-d config_value=value, received "' . $param . '"' . "\n"
            );
        }
        list($key, $value) = explode('=', $param);
        $config->set($key, $value, 'system');
        break;
    case 's':
        $store_user_config = true;
        break;
    case 'S':
        $store_system_config = true;
        break;
    case 'u':
        $config->remove($param, 'user');
        break;
    case 'v':
        $config->set('verbose', $config->get('verbose') + 1);
        break;
    case 'q':
        $config->set('verbose', $config->get('verbose') - 1);
        break;
    case 'V':
        usage(null, 'version');
    case 'c':
    case 'C':
        break;
    default:
        // all non pear params goes to the command
        $cmdopts[$opt[0]] = $param;
        break;
    }
}

if ($store_system_config) {
    $config->store('system');
}

if ($store_user_config) {
    $config->store('user');
}

$command = (isset($options[1][0])) ? $options[1][0] : null;
if (empty($command) && ($store_user_config || $store_system_config)) {
    exit;
}

if ($fetype == 'Gtk2') {
    if (!$config->validConfiguration()) {
        PEAR::raiseError(
            "CRITICAL ERROR: no existing valid configuration files found in " .
            "files '$pear_user_config' or '$pear_system_config', " .
            "please copy an existing configuration file to one of these " .
            "locations, or use the -c and -s options to create one"
        );
    }
    Gtk::main();
} else {
    do {
        if ($command == 'help') {
            usage(null, isset($options[1][1]) ? $options[1][1] : null);
        }

        if (!$config->validConfiguration()) {
            PEAR::raiseError(
                "CRITICAL ERROR: no existing valid configuration files found " .
                "in files '$pear_user_config' or '$pear_system_config', " .
                "please copy an existing configuration file to one of " .
                "these locations, or use the -c and -s options to create one"
            );
        }

        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        $cmd = PEAR_Command::factory($command, $config);
        PEAR::popErrorHandling();
        if (PEAR::isError($cmd)) {
            usage(null, isset($options[1][0]) ? $options[1][0] : null);
        }

        $short_args = $long_args = null;
        PEAR_Command::getGetoptArgs($command, $short_args, $long_args);
        array_shift($options[1]);
        $tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args);

        if (PEAR::isError($tmp)) {
            break;
        }

        list($tmpopt, $params) = $tmp;
        $opts = array();
        foreach ($tmpopt as $foo => $tmp2) {
            list($opt, $value) = $tmp2;
            if ($value === null) {
                $value = true; // options without args
            }

            if (strlen($opt) == 1) {
                $cmdoptions = $cmd->getOptions($command);
                foreach ($cmdoptions as $o => $d) {
                    if (isset($d['shortopt']) && $d['shortopt'] == $opt) {
                        $opts[$o] = $value;
                    }
                }
            } else {
                if (substr($opt, 0, 2) == '--') {
                    $opts[substr($opt, 2)] = $value;
                }
            }
        }

        $ok = $cmd->run($command, $opts, $params);
        if ($ok === false) {
            PEAR::raiseError("unknown command `$command'");
        }

        if (PEAR::isError($ok)) {
            PEAR::setErrorHandling(
                PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")
            );
            PEAR::raiseError($ok);
        }
    } while (false);
}

// {{{ usage()

/**
 * Display usage information
 *
 * @param mixed $error       Optional error message
 * @param mixed $helpsubject Optional subject/command to display help for
 *
 * @return void
 */
function usage($error = null, $helpsubject = null)
{
    global $progname, $all_commands;
    $stdout = fopen('php://stdout', 'w');
    if (PEAR::isError($error)) {
        fputs($stdout, $error->getMessage() . "\n");
    } elseif ($error !== null) {
        fputs($stdout, "$error\n");
    }

    if ($helpsubject != null) {
        $put = cmdHelp($helpsubject);
    } else {
        $put = "Commands:\n";
        $maxlen = max(array_map("strlen", $all_commands));
        $formatstr = "%-{$maxlen}s  %s\n";
        ksort($all_commands);
        foreach ($all_commands as $cmd => $class) {
            $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd));
        }
        $put .=
            "Usage: $progname [options] command [command-options] <parameters>\n".
            "Type \"$progname help options\" to list all options.\n".
            "Type \"$progname help shortcuts\" to list all command shortcuts.\n".
            "Type \"$progname help version\" or ".
            "\"$progname version\" to list version information.\n".
            "Type \"$progname help <command>\" to get the help ".
            "for the specified command.";
    }
    fputs($stdout, "$put\n");
    fclose($stdout);

    if ($error === null) {
        exit(0);
    }
    exit(1);
}

/**
 * Return help string for specified command
 *
 * @param string $command Command to return help for
 *
 * @return void
 */
function cmdHelp($command)
{
    global $progname, $all_commands, $config;
    if ($command == "options") {
        return
        "Options:\n".
        "     -v         increase verbosity level (default 1)\n".
        "     -q         be quiet, decrease verbosity level\n".
        "     -c file    find user configuration in `file'\n".
        "     -C file    find system configuration in `file'\n".
        "     -d foo=bar set user config variable `foo' to `bar'\n".
        "     -D foo=bar set system config variable `foo' to `bar'\n".
        "     -G         start in graphical (Gtk) mode\n".
        "     -s         store user configuration\n".
        "     -S         store system configuration\n".
        "     -u foo     unset `foo' in the user configuration\n".
        "     -h, -?     display help/usage (this message)\n".
        "     -V         version information\n";
    } elseif ($command == "shortcuts") {
        $sc = PEAR_Command::getShortcuts();
        $ret = "Shortcuts:\n";
        foreach ($sc as $s => $c) {
            $ret .= sprintf("     %-8s %s\n", $s, $c);
        }
        return $ret;

    } elseif ($command == "version") {
        return "PEAR Version: ".$GLOBALS['pear_package_version'].
               "\nPHP Version: ".phpversion().
               "\nZend Engine Version: ".zend_version().
               "\nRunning on: ".php_uname();

    } elseif ($help = PEAR_Command::getHelp($command)) {
        if (is_string($help)) {
            return "$progname $command [options] $help\n";
        }

        if ($help[1] === null) {
            return "$progname $command $help[0]";
        }

        return "$progname $command [options] $help[0]\n$help[1]";
    }

    return "Command '$command' is not valid, try '$progname help'";
}

// }}}

/**
 * error_handler
 *
 * @param mixed $errno  Error number
 * @param mixed $errmsg Message
 * @param mixed $file   Filename
 * @param mixed $line   Line number
 *
 * @access public
 * @return boolean
 */
function error_handler($errno, $errmsg, $file, $line)
{
    if ((!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) && ($errno & E_STRICT)) {
        return; // E_STRICT
    }
    if ($errno & E_DEPRECATED) {
        return; // E_DEPRECATED
    }
    if (!(error_reporting() & $errno) &&
        isset($GLOBALS['config']) &&
        $GLOBALS['config']->get('verbose') < 4
    ) {
        return false; // @silenced error, show all if debug is high enough
    }
    $errortype = array (
        E_DEPRECATED  => 'Deprecated Warning',
        E_ERROR   =>  "Error",
        E_WARNING   =>  "Warning",
        E_PARSE   =>  "Parsing Error",
        E_NOTICE   =>  "Notice",
        E_CORE_ERROR  =>  "Core Error",
        E_CORE_WARNING  =>  "Core Warning",
        E_COMPILE_ERROR  =>  "Compile Error",
        E_COMPILE_WARNING =>  "Compile Warning",
        E_USER_ERROR =>  "User Error",
        E_USER_WARNING =>  "User Warning",
        E_USER_NOTICE =>  "User Notice"
    );
    if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) {
        $errortype[E_STRICT] = 'Strict Warning';
    }
    $prefix = $errortype[$errno];
    global $_PEAR_PHPDIR;
    if (stristr($file, $_PEAR_PHPDIR)) {
        $file = substr($file, strlen($_PEAR_PHPDIR) + 1);
    } else {
        $file = basename($file);
    }
    print "\n$prefix: $errmsg in $file on line $line\n";
    return false;
}


/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * indent-tabs-mode: nil
 * mode: php
 * End:
 */
// vim600:syn=php
PK��Z�0$�-- .pkgxml/Pear_File_MARC-1.4.1.xmlnu�[���<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.10.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
 <name>File_MARC</name>
 <channel>pear.php.net</channel>
 <summary>Parse, modify, and create MARC records</summary>
 <description>The standard for machine-readable cataloging (MARC) records is documented at http://loc.gov/marc/. This package enables you to read existing MARC records from a file, string, or (using the YAZ extension), from a Z39.50 source. You can also use this package to create new MARC records.

This package is based on the PHP MARC package, originally called &quot;php-marc&quot;, that is part of the Emilda Project (http://www.emilda.org).  Christoffer Landtman generously agreed to make the &quot;php-marc&quot; code available under the GNU LGPL so it could be used as the basis of this PEAR package.</description>
 <lead>
  <name>Dan Scott</name>
  <user>dbs</user>
  <email>dbs@php.net</email>
  <active>yes</active>
 </lead>
 <date>2019-11-13</date>
 <time>17:33:33</time>
 <version>
  <release>1.4.1</release>
  <api>1.4.0</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license uri="http://www.gnu.org/copyleft/lesser.html">GNU Lesser General Public License</license>
 <notes>
1.4.1
  * Reintroduce include_path to composer.json
 </notes>
 <contents>
  <dir baseinstalldir="File" name="/">
   <file baseinstalldir="/" md5sum="ffe2590635f404af055fe731da105939" name="File/MARC/Lint/CodeData.php" role="php" />
   <file baseinstalldir="/" md5sum="a3b9e1c817e67f59add05593500d463e" name="File/MARC/Control_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="acba4463f8e40d6ee4e7ba1f2dc53123" name="File/MARC/Data_Field.php" role="php" />
   <file baseinstalldir="/" md5sum="378f483ec1fd161cd9dfb9b05db58d66" name="File/MARC/Exception.php" role="php" />
   <file baseinstalldir="/" md5sum="a9ba69030cbf4847292b9975e9d922c6" name="File/MARC/Field.php" role="php" />
   <file baseinstalldir="/" md5sum="c37351c7c80927ce6bb1e662510f9183" name="File/MARC/Lint.php" role="php" />
   <file baseinstalldir="/" md5sum="c5ac39e3d25eb0108b9dd5ad8466c821" name="File/MARC/List.php" role="php" />
   <file baseinstalldir="/" md5sum="7af6ce78cde4bb246e4e96709e90d2c0" name="File/MARC/Record.php" role="php" />
   <file baseinstalldir="/" md5sum="df5f97139685f0ad04e47fdbb67e3968" name="File/MARC/Subfield.php" role="php" />
   <file baseinstalldir="/" md5sum="6e102262dfd5d65d8d5a6221dfc74edd" name="File/MARC.php" role="php" />
   <file baseinstalldir="/" md5sum="8b64040d2d18ac4b994595a148266a66" name="File/MARCBASE.php" role="php" />
   <file baseinstalldir="/" md5sum="f5a17a60d34e84e2ee7ca1e5c5c6c620" name="File/MARCXML.php" role="php" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="examples/example.mrc" role="doc" />
   <file baseinstalldir="File" md5sum="1aea40df9f1c2e32f8e065fe8da0a3b5" name="examples/marc_yaz.php" role="doc" />
   <file baseinstalldir="File" md5sum="70ae317e0890d5896e3ffccdd293369a" name="examples/read.php" role="doc" />
   <file baseinstalldir="File" md5sum="54efb9d920ac775bfc847a83a2dec73a" name="examples/subfields.php" role="doc" />
   <file baseinstalldir="File" md5sum="14297da35b510c496cd1f328cf3bb301" name="tests/bad_example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="0dd4c6dbad6e8608d0ebf9d24425955d" name="tests/bad_example.xml" role="test" />
   <file baseinstalldir="File" md5sum="216a6f9d53f6d3d8e22d81fdc10f4bc1" name="tests/camel.mrc" role="test" />
   <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="tests/example.mrc" role="test" />
   <file baseinstalldir="File" md5sum="9455aec3371f79cf7d31281fd03f5171" name="tests/marc_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="577e2f5f89fd48cf1a3576a29d2958f8" name="tests/marc_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a6a586354b9a06c880c2a7470dd828d7" name="tests/marc_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1c7e2fc5572a0f9362a771c260a1fe3" name="tests/marc_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="84f85ac7f8a2532e4e90ccde7764556a" name="tests/marc_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="889e5e906a97de7a0e94b0c5f30e70e7" name="tests/marc_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="be823dc8a8efb408de06371ab802efcc" name="tests/marc_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="af44490aafea44e5120f881cb81cdad9" name="tests/marc_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ac9f2a7aeb24900a11f5102744179ae3" name="tests/marc_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5e43eb5cddbb4f2bd0d6405cd95b80aa" name="tests/marc_010.phpt" role="test" />
   <file baseinstalldir="File" md5sum="2e1cd8509c0bf04ec77fc0f51375f611" name="tests/marc_011.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bc49ca48623102c8ac07679fa77a3dd9" name="tests/marc_012.phpt" role="test" />
   <file baseinstalldir="File" md5sum="245a3b20e0da1973535503e28efd1d3a" name="tests/marc_013.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ce69aa734856dd40d60d30c77bdef53a" name="tests/marc_014.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7b61cdd31035e60682fa92c5d519d997" name="tests/marc_015.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7f4f597fe1adaa3507eb87fc4875dbd2" name="tests/marc_016.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4262efd5fcacbd7503323681f4552430" name="tests/marc_017.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ee1623d7bda54ba4f741b2319b158f82" name="tests/marc_018.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8006c03fbab0f04377342086fafd3982" name="tests/marc_019.phpt" role="test" />
   <file baseinstalldir="File" md5sum="f5ae5b25e0ac1104314433d9e5b1f7fe" name="tests/marc_020.phpt" role="test" />
   <file baseinstalldir="File" md5sum="94d8f99e86585671a1b2d3043aeb6360" name="tests/marc_021.phpt" role="test" />
   <file baseinstalldir="File" md5sum="bb891a890effe0e77e1759043f4846d8" name="tests/marc_022.phpt" role="test" />
   <file baseinstalldir="File" md5sum="faf77dcb5cdd002c09169a14bfded65e" name="tests/marc_023.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0e6c4a23f5da7df64fdd4b3b1149bbee" name="tests/marc_16783.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4ea8b3520beda378db15960f1c50493a" name="tests/marc_field_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="743850ef61df69c4340be44a03bccb5a" name="tests/marc_field_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="8c765f1398b49df257d86d22ac6e4f8d" name="tests/marc_field_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d4216cf930a308e0d02553bd3914f294" name="tests/marc_field_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dd59514b474b78371ad522a3e13b76b7" name="tests/marc_field_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="5295bfd02a8424acac1c91de26b552c7" name="tests/marc_field_21246.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6f95f09442ccf6b93df92986f58b270d" name="tests/marc_lint_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="18d721f8871edd925624ccbdd15444fb" name="tests/marc_lint_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="4eb86a2f4e0a74dedcb0bf2511da6ca1" name="tests/marc_lint_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="10430fee0a1352d0528f1507b34c57e1" name="tests/marc_lint_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="0dcd07a18577d7b22392a2214cd6436c" name="tests/marc_lint_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fd17798fc535562e5e64461f449516b2" name="tests/marc_record_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="141b455ccf67a60c4eac44c77960f2e2" name="tests/marc_subfield_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b1e23464ee0eec47ddca2af9a9922926" name="tests/marc_subfield_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="1d7903e8c244d647220b318b4bc758d1" name="tests/marc_xml_001.phpt" role="test" />
   <file baseinstalldir="File" md5sum="22cae3c752d843b78f583dcd92801534" name="tests/marc_xml_002.phpt" role="test" />
   <file baseinstalldir="File" md5sum="c0716d23e0f960abf8d53ad6014a413a" name="tests/marc_xml_003.phpt" role="test" />
   <file baseinstalldir="File" md5sum="7645fa19e28aca041a124fc5e2c12bd3" name="tests/marc_xml_004.phpt" role="test" />
   <file baseinstalldir="File" md5sum="b08b28c3251625b8b6e4d7ab376b0185" name="tests/marc_xml_005.phpt" role="test" />
   <file baseinstalldir="File" md5sum="6cd0934ddbf65d2d7e9ea5d108977ff7" name="tests/marc_xml_006.phpt" role="test" />
   <file baseinstalldir="File" md5sum="ffdce4aa190268fa7cbbf3bb45383abf" name="tests/marc_xml_007.phpt" role="test" />
   <file baseinstalldir="File" md5sum="998a4c1ce00ff100f39ffa9fc49a212f" name="tests/marc_xml_008.phpt" role="test" />
   <file baseinstalldir="File" md5sum="a38a67c590869f2b0a4859a910fd9e89" name="tests/marc_xml_009.phpt" role="test" />
   <file baseinstalldir="File" md5sum="db39c5055a570fcda12bb7c5fa1e3b4d" name="tests/marc_xml_16642.phpt" role="test" />
   <file baseinstalldir="File" md5sum="dc075f4a271bd7182378a3874bd5b39e" name="tests/marc_xml_namespace.phpt" role="test" />
   <file baseinstalldir="File" md5sum="208200d9a979ac360c4d326e9789b6b7" name="tests/marc_xml_namespace_prefix.phpt" role="test" />
   <file baseinstalldir="File" md5sum="d87774ede82222cfc12b2c2a06f57a3a" name="tests/marc_xml_rsinger.phpt" role="test" />
   <file baseinstalldir="File" md5sum="fb44e3eb69f1a37115235fc829c39542" name="tests/namespace.xml" role="test" />
   <file baseinstalldir="File" md5sum="e6de4d809b0af5dd99fd352eb60616a1" name="tests/skipif.inc" role="test" />
   <file baseinstalldir="File" md5sum="a0166a4ff0bc0bb283e854f11beaa793" name="tests/music.mrc" role="test" />
   <file baseinstalldir="File" md5sum="993ce494befbc25dc1326527b30b4782" name="tests/music.xml" role="test" />
   <file baseinstalldir="File" md5sum="6b0c87f0cd459ed7322c25d403b164cc" name="tests/bigarchive.xml" role="test" />
   <file baseinstalldir="File" md5sum="be850aa6ab4ac52b8c6c214c30b574af" name="tests/onerecord.xml" role="test" />
   <file baseinstalldir="File" md5sum="4f43fec7b276267eec5258044853ccc8" name="tests/sandburg.mrc" role="test" />
   <file baseinstalldir="File" md5sum="e216b95f905dd240c9bde372950e4073" name="tests/sandburg.xml" role="test" />
   <file baseinstalldir="File" md5sum="e81a92188ea0dcd9c108a63fb32b3f4f" name="tests/xmlescape.mrc" role="test" />
   <file baseinstalldir="File" md5sum="8f9f63ed6a80191d89a2296fa4c1a30b" name="CHANGELOG" role="doc" />
   <file baseinstalldir="File" md5sum="fbc093901857fcd118f065f900982c24" name="LICENSE" role="doc" />
  </dir>
 </contents>
 <dependencies>
  <required>
   <php>
    <min>5.6</min>
   </php>
   <pearinstaller>
    <min>1.4.0</min>
   </pearinstaller>
  </required>
  <optional>
   <package>
    <name>Validate_ISPN</name>
    <channel>pear.php.net</channel>
   </package>
  </optional>
 </dependencies>
 <phprelease />
</package>
PKm�ZPi��.depdbnu�[���PKm�Z�{��
�Mail/null.phpnu�[���PKm�ZE@�%>>
Mail/sendmail.phpnu�[���PKm�Z��A~�{�{�;Mail/RFC822.phpnu�[���PKn�Z�+V����
[�Mail/mime.phpnu�[���PKn�Zx�ع���D�Mail/mimeDecode.phpnu�[���PKn�ZB�_Ǭ=�=
@(Mail/smtp.phpnu�[���PKn�ZwԐE;E;)fMail/smtpmx.phpnu�[���PKn�Z�؛�J�J���Mail/mimePart.phpnu�[���PKn�ZB��shh
8YMail/mock.phpnu�[���PKn�Z@iE�\\
�lMail/mail.phpnu�[���PKn�Zv�.locknu�[���PKn�Z�*�z%-%- ��Structures/LinkedList/Double.phpnu�[���PKn�Z����p:p:  �Structures/LinkedList/Single.phpnu�[���PKn�ZUyv���Structures/Graph.phpnu�[���PKn�Z�C� + +CStructures/Graph/Node.phpnu�[���PKn�Z9����,�1Structures/Graph/Manipulator/AcyclicTest.phpnu�[���PKn�Z~(�htt2�HStructures/Graph/Manipulator/TopologicalSorter.phpnu�[���PKn�Z�J�}
}
_dAuth/SASL/Anonymous.phpnu�[���PKn�ZP(~�T
T
#rAuth/SASL/CramMD5.phpnu�[���PKn�Z����==�Auth/SASL/Plain.phpnu�[���PKn�Z�<� OO<�Auth/SASL/Login.phpnu�[���PKn�Z%ׅtg!g!ΘAuth/SASL/DigestMD5.phpnu�[���PKn�Z�T�|�Auth/SASL/Common.phpnu�[���PKn�ZvR�r,,��Auth/SASL/External.phpnu�[���PKn�Zќ��0�0H�Auth/SASL/SCRAM.phpnu�[���PKn�Z2r����
�	Auth/SASL.phpnu�[���PKn�Z�T�,�,�OS/Guess.phpnu�[���PKn�Z�����KPEAR/Config.phpnu�[���PKn�Z�`�eEAEA
.ZPEAR/REST.phpnu�[���PKn�Z��ym6m6��PEAR/Exception.phpnu�[���PKn�Zr"����_�PEAR/ChannelFile.phpnu�[���PKn�Z��gk�U�U?�PEAR/Validate.phpnu�[���PKn�Zd֣S��u�PEAR/Command/Pickle.xmlnu�[���PKn�Z�z��k<k<W�PEAR/Command/Config.phpnu�[���PKn�Z݄<ii	1PEAR/Command/Mirror.xmlnu�[���PKn�Z,��t"u"u�3PEAR/Command/Remote.phpnu�[���PKn�Z
�\���"�PEAR/Command/Remote.xmlnu�[���PKn�Zj���!�!X�PEAR/Command/Install.xmlnu�[���PKo�Z�%q������PEAR/Command/Channels.phpnu�[���PKo�Znmi?;�;��[	PEAR/Command/Install.phpnu�[���PKo�Z�X�

#
PEAR/Command/Auth.phpnu�[���PKo�Z���s6
6
T-
PEAR/Command/Config.xmlnu�[���PKo�Z�%Fii�:
PEAR/Command/Test.xmlnu�[���PKo�ZZ h66A
PEAR/Command/Package.xmlnu�[���PKo�Z�w��zz�]
PEAR/Command/Channels.xmlnu�[���PKo�Z+9ҜҜ�n
PEAR/Command/Package.phpnu�[���PKo�Z
u����PEAR/Command/Build.xmlnu�[���PKo�Z������
PEAR/Command/Mirror.phpnu�[���PKp�Z,_�h/h/�PEAR/Command/Test.phpnu�[���PKp�Z�%sp  6OPEAR/Command/Common.phpnu�[���PKp�Z0(;rʹʹ�oPEAR/Command/Registry.phpnu�[���PKp�Z�4�{���$PEAR/Command/Auth.xmlnu�[���PKp�Z��#S
S
�)PEAR/Command/Build.phpnu�[���PKp�Z���u��S4PEAR/Command/Registry.xmlnu�[���PKp�Z�P>>�;PEAR/Command/Pickle.phpnu�[���PKp�Z��T�I�I�yPEAR/Builder.phpnu�[���PKp�Z[
�W��3�PEAR/XMLParser.phpnu�[���PKp�Zl(e���t�PEAR/Downloader.phpnu�[���PKp�Z�b������
PEAR/ErrorStack.phpnu�[���PKp�Z(Pz����ePEAR/Proxy.phpnu�[���PKp�Z��'����|PEAR/RunTest.phpnu�[���PKq�Zj�y99�	PEAR/Validator/PECL.phpnu�[���PKq�Zp�����aPEAR/Dependency2.phpnu�[���PKq�Z��wv@@��PEAR/PackageFile/v2.phpnu�[���PKq�ZC�8�L�L!:�PEAR/PackageFile/v2/Validator.phpnu�[���PKq�Z���=_�_�6PEAR/PackageFile/v2/rw.phpnu�[���PKq�Z�5�������,PEAR/PackageFile/v1.phpnu�[���PKq�Z�ɁɁ!��PEAR/PackageFile/Generator/v2.phpnu�[���PKq�Z`�=����!�tPEAR/PackageFile/Generator/v1.phpnu�[���PKr�Z��OWHH�9PEAR/PackageFile/Parser/v2.phpnu�[���PKr�Z�_=�@�@`FPEAR/PackageFile/Parser/v1.phpnu�[���PKr�Zc��__5�PEAR/DependencyDB.phpnu�[���PKr�Z�@P��{�PEAR/ChannelFile/Parser.phpnu�[���PKr�Z��_�0�0r�PEAR/Command.phpnu�[���PKr�Z�ٲ�=�==PEAR/PackageFile.phpnu�[���PKr�Z�JD��g\PEAR/Task/Replace.phpnu�[���PKr�Z&%75))�wPEAR/Task/Windowseol/rw.phpnu�[���PKr�Z�3}}PEAR/Task/Replace/rw.phpnu�[���PKr�Z&
i."x�PEAR/Task/Postinstallscript/rw.phpnu�[���PKr�Z�-!�PEAR/Task/Common.phpnu�[���PKr�ZD$���I�PEAR/Task/Windowseol.phpnu�[���PKr�ZZ�E�x9x9��PEAR/Task/Postinstallscript.phpnu�[���PKr�Z\k��K�PEAR/Task/Unixeol/rw.phpnu�[���PKr�Z�������PEAR/Task/Unixeol.phpnu�[���PKr�Z�W�f���PEAR/REST/10.phpnu�[���PKr�Z��Y�;;ąPEAR/REST/13.phpnu�[���PKr�Z,#y��+�+�PEAR/REST/11.phpnu�[���PKr�Z��U  D�PEAR/Packager.phpnu�[���PKr�ZZ�bgbg�PEAR/Common.phpnu�[���PKr�Z$���(�(FsPEAR/Registry.phpnu�[���PKr�Z��	MdMd?�PEAR/Frontend/CLI.phpnu�[���PKr�Z��

�PEAR/Installer/Role/Doc.phpnu�[���PKr�Z��/��)PEAR/Installer/Role/Cfg.xmlnu�[���PKr�Z>1H���PEAR/Installer/Role/Www.xmlnu�[���PKr�Z�?m

PEAR/Installer/Role/Php.phpnu�[���PKr�Z*Y|	%%`PEAR/Installer/Role/Man.phpnu�[���PKr�Z���BB�PEAR/Installer/Role/Ext.xmlnu�[���PKr�Zp��""]PEAR/Installer/Role/Src.xmlnu�[���PKr�Zh&P*���PEAR/Installer/Role/Doc.xmlnu�[���PKr�ZB] ���PEAR/Installer/Role/Test.xmlnu�[���PKr�Zz�q����PEAR/Installer/Role/Php.xmlnu�[���PKr�Z	��
|PEAR/Installer/Role/Data.phpnu�[���PKs�Z�0�c���PEAR/Installer/Role/Man.xmlnu�[���PKs�Z��K

�PEAR/Installer/Role/Ext.phpnu�[���PKs�ZY��� PEAR/Installer/Role/Test.phpnu�[���PKs�Z@v�а�z#PEAR/Installer/Role/Script.xmlnu�[���PKs�Zf�sz��x%PEAR/Installer/Role/Data.xmlnu�[���PKs�Z?���GGV'PEAR/Installer/Role/Common.phpnu�[���PKs�Z�^D{		�?PEAR/Installer/Role/Www.phpnu�[���PKs�Z�Ƥ?CPEAR/Installer/Role/Cfg.phpnu�[���PKs�Z��[�	SPEAR/Installer/Role/Script.phpnu�[���PKs�Z��srrjVPEAR/Installer/Role/Src.phpnu�[���PKs�ZV�Z���'ZPEAR/Installer/Role.phpnu�[���PKs�Z�{�	�)�)*yPEAR/Downloader/Package.phpnu�[���PKs�Z.�4���$�PEAR/Frontend.phpnu�[���PKs�Z،�w��_�PEAR/Installer.phpnu�[���PKs�ZXxo��-j�Symfony/Bridge/Doctrine/Logger/DbalLogger.phpnu�[���PKs�Ze�OO&b�Symfony/Bridge/Doctrine/autoloader.phpnu�[���PKs�Z��X+��8�Symfony/Bridge/Doctrine/CacheWarmer/ProxyCacheWarmer.phpnu�[���PKs�Z	�9,��5i�Symfony/Bridge/Doctrine/Form/DoctrineOrmExtension.phpnu�[���PKs�Z�0���NX�Symfony/Bridge/Doctrine/Form/EventListener/MergeDoctrineCollectionListener.phpnu�[���PKs�Z!%d==A��Symfony/Bridge/Doctrine/Form/ChoiceList/EntityLoaderInterface.phpnu�[���PKs�Z�	?x�7�7<4�Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.phpnu�[���PKs�ZGC�t��A<-Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.phpnu�[���PKs�Z`.
qpp7�9Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.phpnu�[���PKs�ZCi�PPMZQSymfony/Bridge/Doctrine/Form/DataTransformer/CollectionToArrayTransformer.phpnu�[���PKs�Z憝��0'YSymfony/Bridge/Doctrine/Form/Type/EntityType.phpnu�[���PKs�ZS;,:��2-]Symfony/Bridge/Doctrine/Form/Type/DoctrineType.phpnu�[���PKs�ZW&v��<�wSymfony/Bridge/Doctrine/Security/User/EntityUserProvider.phpnu�[���PKs�Z�����Et�Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.phpnu�[���PKs�Z(��y��9�Symfony/Bridge/Doctrine/Validator/DoctrineInitializer.phpnu�[���PKs�ZQГ��>�Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.phpnu�[���PKs�Z:�d�G5�Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.phpnu�[���PKs�Z�Ta�==B��Symfony/Bridge/Doctrine/ExpressionLanguage/DoctrineParserCache.phpnu�[���PKs�Z��qm
m
-m�Symfony/Bridge/Doctrine/RegistryInterface.phpnu�[���PKs�Zlf/�qq=7�Symfony/Bridge/Doctrine/DataFixtures/ContainerAwareLoader.phpnu�[���PKs�Z����=�Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.phpnu�[���PKs�Z�����C��Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerSchema.phpnu�[���PKs�ZOlQ�996��Symfony/Bridge/Doctrine/ContainerAwareEventManager.phpnu�[���PKs�Z؈����3D�Symfony/Bridge/Doctrine/Test/DoctrineTestHelper.phpnu�[���PKs�Z̳֨�+��Symfony/Bridge/Doctrine/ManagerRegistry.phpnu�[���PKs�Z+çxAA?�Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.phpnu�[���PKs�Z*�+��J�JIBSymfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.phpnu�[���PKs�Z���*��SVaSymfony/Bridge/Doctrine/DependencyInjection/Security/UserProvider/EntityFactory.phpnu�[���PKs�Z��㛕�Q�hSymfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterMappingsPass.phpnu�[���PKs�Z~�YAAeԀSymfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.phpnu�[���PKs�Z��,���S��Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/DoctrineValidationPass.phpnu�[���PKs�Z��4NN%,�Symfony/Bridge/Monolog/autoloader.phpnu�[���PKs�Z��մ��1ϡSymfony/Bridge/Monolog/Handler/FirePHPHandler.phpnu�[���PKs�Z��Zv��/©Symfony/Bridge/Monolog/Handler/DebugHandler.phpnu�[���PKs�Z�y���1دSymfony/Bridge/Monolog/Handler/ConsoleHandler.phpnu�[���PKs�Z��*vv5�Symfony/Bridge/Monolog/Handler/SwiftMailerHandler.phpnu�[���PKs�Z���"II3��Symfony/Bridge/Monolog/Handler/ChromePhpHandler.phpnu�[���PKs�Z��;��	�	!��Symfony/Bridge/Monolog/Logger.phpnu�[���PKs�Z��b115��Symfony/Bridge/Monolog/Formatter/ConsoleFormatter.phpnu�[���PKt�Z�,��1l�Symfony/Bridge/Monolog/Processor/WebProcessor.phpnu�[���PKt�Z�$�KK"l�Symfony/Bridge/Twig/autoloader.phpnu�[���PKt�Z�)�UU1	�Symfony/Bridge/Twig/Translation/TwigExtractor.phpnu�[���PKt�Z6DZ77*��Symfony/Bridge/Twig/Node/StopwatchNode.phpnu�[���PKt�Z,
�@��5P�Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.phpnu�[���PKt�Z�
�s>>*ESymfony/Bridge/Twig/Node/FormThemeNode.phpnu�[���PKt�ZP�IAA3�Symfony/Bridge/Twig/Node/TransDefaultDomainNode.phpnu�[���PKt�Z�U,tt,�Symfony/Bridge/Twig/Node/FormEnctypeNode.phpnu�[���PKt�Zʦ\�G
G
&QSymfony/Bridge/Twig/Node/TransNode.phpnu�[���PKt�Z���^��,�%Symfony/Bridge/Twig/Node/RenderBlockNode.phpnu�[���PKt�Z�vq�)+Symfony/Bridge/Twig/Form/TwigRenderer.phpnu�[���PKt�Zb�3�}}8q1Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.phpnu�[���PKt�Z��Qkk2V4Symfony/Bridge/Twig/Form/TwigRendererInterface.phpnu�[���PKt�Z��<��/#7Symfony/Bridge/Twig/Form/TwigRendererEngine.phpnu�[���PKt�Z�GTSymfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.phpnu�[���PKt�Z�)�[n	n	)�`Symfony/Bridge/Twig/NodeVisitor/Scope.phpnu�[���PKt�Z�tA�:`jSymfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.phpnu�[���PKt�Z��9292B�xSymfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twignu�[���PKt�Z��[[Dy�Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twignu�[���PKt�Z.��8H�Symfony/Bridge/Twig/TokenParser/StopwatchTokenParser.phpnu�[���PKt�Z�%]�
�
4��Symfony/Bridge/Twig/TokenParser/TransTokenParser.phpnu�[���PKt�Z�/�	�	:��Symfony/Bridge/Twig/TokenParser/TransChoiceTokenParser.phpnu�[���PKt�Z>����8>�Symfony/Bridge/Twig/TokenParser/FormThemeTokenParser.phpnu�[���PKt�Zʶ�̭�Ao�Symfony/Bridge/Twig/TokenParser/TransDefaultDomainTokenParser.phpnu�[���PKt�Z�9�=KK/��Symfony/Bridge/Twig/Extension/FormExtension.phpnu�[���PKt�Z��|/7�Symfony/Bridge/Twig/Extension/YamlExtension.phpnu�[���PKt�Z��&�a
a
5��Symfony/Bridge/Twig/Extension/HttpKernelExtension.phpnu�[���PKt�ZKΙ���5v�Symfony/Bridge/Twig/Extension/ExpressionExtension.phpnu�[���PKt�Z`�fS..2� Symfony/Bridge/Twig/Extension/RoutingExtension.phpnu�[���PKt�Z�5��mm4] Symfony/Bridge/Twig/Extension/StopwatchExtension.phpnu�[���PKt�Z�?���6. Symfony/Bridge/Twig/Extension/TranslationExtension.phpnu�[���PKt�Zd���oo3�! Symfony/Bridge/Twig/Extension/SecurityExtension.phpnu�[���PKt�Z�����/a' Symfony/Bridge/Twig/Extension/CodeExtension.phpnu�[���PKu�Z^D��dd"sG Symfony/Bridge/Twig/TwigEngine.phpnu�[���PKu�Z�4˵��()V Symfony/Component/Finder/Shell/Shell.phpnu�[���PKu�Z5��K��*^ Symfony/Component/Finder/Shell/Command.phpnu�[���PKu�Z�5�9(�v Symfony/Component/Finder/SplFileInfo.phpnu�[���PKu�Z%uM�PP'X~ Symfony/Component/Finder/autoloader.phpnu�[���PKu�Z��99C� Symfony/Component/Finder/Exception/ShellCommandFailureException.phpnu�[���PKu�Z�7��9�� Symfony/Component/Finder/Exception/ExceptionInterface.phpnu�[���PKu�Z�cWޫ�<� Symfony/Component/Finder/Exception/AccessDeniedException.phpnu�[���PKu�Z>�@��>� Symfony/Component/Finder/Exception/AdapterFailureException.phpnu�[���PKu�ZP�����D	� Symfony/Component/Finder/Exception/OperationNotPermitedException.phpnu�[���PKu�Z��� ��6� Symfony/Component/Finder/Comparator/DateComparator.phpnu�[���PKu�Z|F�z

2?� Symfony/Component/Finder/Comparator/Comparator.phpnu�[���PKu�Z�P�

8�� Symfony/Component/Finder/Comparator/NumberComparator.phpnu�[���PKu�Z�g@Mbb!2� Symfony/Component/Finder/Glob.phpnu�[���PKu�Z�d�V�V#� Symfony/Component/Finder/Finder.phpnu�[���PKu�Zils_��>
!Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.phpnu�[���PKu�Z��ɔ�
�
7u!Symfony/Component/Finder/Iterator/FilePathsIterator.phpnu�[���PKu�Z�,G��4n!Symfony/Component/Finder/Iterator/FilterIterator.phpnu�[���PKu�Z�ʽ���?q#!Symfony/Component/Finder/Iterator/FilecontentFilterIterator.phpnu�[���PKu�Z�

���@~+!Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.phpnu�[���PKu�Z��z":�2!Symfony/Component/Finder/Iterator/CustomFilterIterator.phpnu�[���PKu�Z{�^ǽ�<N9!Symfony/Component/Finder/Iterator/FilenameFilterIterator.phpnu�[���PKu�Z�d����Dw@!Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.phpnu�[���PKu�Zx�P���=�F!Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.phpnu�[���PKu�Z ��U��=�L!Symfony/Component/Finder/Iterator/DateRangeFilterIterator.phpnu�[���PKu�Z�n bb<�R!Symfony/Component/Finder/Iterator/FileTypeFilterIterator.phpnu�[���PKu�Z��j��	�	6�X!Symfony/Component/Finder/Iterator/SortableIterator.phpnu�[���PKu�Z���)��8�b!Symfony/Component/Finder/Iterator/PathFilterIterator.phpnu�[���PKu�Z�6s��@�j!Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.phpnu�[���PKu�Z��&
&
2Gw!Symfony/Component/Finder/Expression/Expression.phpnu�[���PKu�Z�"HH6ρ!Symfony/Component/Finder/Expression/ValueInterface.phpnu�[���PKu�Z�E�,}�!Symfony/Component/Finder/Expression/Glob.phpnu�[���PKu�Z��(�-�!Symfony/Component/Finder/Expression/Regex.phpnu�[���PKu�Z9!�2{
{
/D�!Symfony/Component/Finder/Adapter/PhpAdapter.phpnu�[���PKu�Z����5�!Symfony/Component/Finder/Adapter/AdapterInterface.phpnu�[���PKu�Z��kA�
�
34�!Symfony/Component/Finder/Adapter/BsdFindAdapter.phpnu�[���PKu�Z�}]�
�
3��!Symfony/Component/Finder/Adapter/GnuFindAdapter.phpnu�[���PKu�ZQJ)�)8��!Symfony/Component/Finder/Adapter/AbstractFindAdapter.phpnu�[���PKu�Z�	4�"Symfony/Component/Finder/Adapter/AbstractAdapter.phpnu�[���PKu�Z����:;"Symfony/Component/Translation/Extractor/ChainExtractor.phpnu�[���PKu�ZArP�>%"Symfony/Component/Translation/Extractor/ExtractorInterface.phpnu�[���PKu�Zb*0�oo4�#"Symfony/Component/Translation/PluralizationRules.phpnu�[���PKu�Z�q��UU,<"Symfony/Component/Translation/autoloader.phpnu�[���PKu�Z�<qNN10>"Symfony/Component/Translation/MessageSelector.phpnu�[���PKu�Z�س��:�J"Symfony/Component/Translation/Catalogue/MergeOperation.phpnu�[���PKu�ZY[�>*P"Symfony/Component/Translation/Catalogue/OperationInterface.phpnu�[���PKu�Z��fb�
�
=�U"Symfony/Component/Translation/Catalogue/AbstractOperation.phpnu�[���PKu�Z��ӄ�9�c"Symfony/Component/Translation/Catalogue/DiffOperation.phpnu�[���PKu�Z�6�"��>�i"Symfony/Component/Translation/Exception/ExceptionInterface.phpnu�[���PKu�ZDŽ���D�k"Symfony/Component/Translation/Exception/InvalidResourceException.phpnu�[���PKv�Z�2B��E2n"Symfony/Component/Translation/Exception/NotFoundResourceException.phpnu�[���PKv�Z�y4��2�p"Symfony/Component/Translation/MessageCatalogue.phpnu�[���PKv�Z%�Mt8��"Symfony/Component/Translation/MetadataAwareInterface.phpnu�[���PKv�Z�d�<<4��"Symfony/Component/Translation/IdentityTranslator.phpnu�[���PKv�Z�e�G��,��"Symfony/Component/Translation/Translator.phpnu�[���PKv�Z��֛�;u�"Symfony/Component/Translation/MessageCatalogueInterface.phpnu�[���PKv�ZM�
���9{�"Symfony/Component/Translation/Dumper/IcuResFileDumper.phpnu�[���PKv�Zਪ(5u�"Symfony/Component/Translation/Dumper/PoFileDumper.phpnu�[���PKv�Z���%LL6��"Symfony/Component/Translation/Dumper/PhpFileDumper.phpnu�[���PKv�Z�<̧��8��"Symfony/Component/Translation/Dumper/XliffFileDumper.phpnu�[���PKv�Z>{GG5��"Symfony/Component/Translation/Dumper/QtFileDumper.phpnu�[���PKv�Z���667Z�"Symfony/Component/Translation/Dumper/YamlFileDumper.phpnu�[���PKv�ZoB���6��"Symfony/Component/Translation/Dumper/CsvFileDumper.phpnu�[���PKv�ZB^�[[3*�"Symfony/Component/Translation/Dumper/FileDumper.phpnu�[���PKv�Z�:$}}7�"Symfony/Component/Translation/Dumper/JsonFileDumper.phpnu�[���PKv�Z&X����6�#Symfony/Component/Translation/Dumper/IniFileDumper.phpnu�[���PKv�Z��<**8
#Symfony/Component/Translation/Dumper/DumperInterface.phpnu�[���PKv�Z����A	A	5�#Symfony/Component/Translation/Dumper/MoFileDumper.phpnu�[���PKv�Zg�?Z�
�
*B#Symfony/Component/Translation/Interval.phpnu�[���PKv�Z�3����5�#Symfony/Component/Translation/TranslatorInterface.phpnu�[���PKv�ZP�?�}}:�%#Symfony/Component/Translation/Writer/TranslationWriter.phpnu�[���PKv�ZN@���6�-#Symfony/Component/Translation/Loader/IniFileLoader.phpnu�[���PKv�Z�T�93#Symfony/Component/Translation/Loader/IcuDatFileLoader.phpnu�[���PKv�ZCS�z
z
9�9#Symfony/Component/Translation/Loader/IcuResFileLoader.phpnu�[���PKv�Z��v���5�D#Symfony/Component/Translation/Loader/MoFileLoader.phpnu�[���PKv�ZR����4&\#Symfony/Component/Translation/Loader/ArrayLoader.phpnu�[���PKv�Z�'s�u	u	7&d#Symfony/Component/Translation/Loader/JsonFileLoader.phpnu�[���PKv�Z�i�3"
"
6n#Symfony/Component/Translation/Loader/CsvFileLoader.phpnu�[���PKv�Z_��BB8�x#Symfony/Component/Translation/Loader/XliffFileLoader.phpnu�[���PKv�Zl#�tt84�#Symfony/Component/Translation/Loader/LoaderInterface.phpnu�[���PKv�Z�*���5�#Symfony/Component/Translation/Loader/PoFileLoader.phpnu�[���PKv�Z�r��;;6o�#Symfony/Component/Translation/Loader/PhpFileLoader.phpnu�[���PKv�Z:�	Z�"�"B�#Symfony/Component/Translation/Loader/schema/dic/xliff-core/xml.xsdnu�[���PKv�Z�xO��T�#Symfony/Component/Translation/Loader/schema/dic/xliff-core/xliff-core-1.2-strict.xsdnu�[���PKv�Z)-d+�	�	5�g%Symfony/Component/Translation/Loader/QtFileLoader.phpnu�[���PKv�Z:����7�q%Symfony/Component/Translation/Loader/YamlFileLoader.phpnu�[���PKw�Z�V�˽�.-z%Symfony/Component/Routing/Annotation/Route.phpnu�[���PKw�Z�<ѹ�+H�%Symfony/Component/Routing/CompiledRoute.phpnu�[���PKw�ZU8���-\�%Symfony/Component/Routing/RouterInterface.phpnu�[���PKw�ZU�cQQ(>�%Symfony/Component/Routing/autoloader.phpnu�[���PKw�Z����'�'+�%Symfony/Component/Routing/RouteCompiler.phpnu�[���PKw�Z��%�%$�%Symfony/Component/Routing/Router.phpnu�[���PKw�Z���q
q
6n�%Symfony/Component/Routing/Matcher/ApacheUrlMatcher.phpnu�[���PKw�Z	�ڗ9E�%Symfony/Component/Routing/Matcher/UrlMatcherInterface.phpnu�[���PKw�Z`�u���=��%Symfony/Component/Routing/Matcher/RequestMatcherInterface.phpnu�[���PKw�Z[z�dd<�&Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.phpnu�[���PKw�Z?�|{��:�&Symfony/Component/Routing/Matcher/Dumper/MatcherDumper.phpnu�[���PKw�Z�x}�44=�&Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.phpnu�[���PKw�Z�bz#z#@A&Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.phpnu�[���PKw�Z�`=e&Symfony/Component/Routing/Matcher/Dumper/DumperCollection.phpnu�[���PKw�Z�N�
�
C�s&Symfony/Component/Routing/Matcher/Dumper/DumperPrefixCollection.phpnu�[���PKw�Z(� ���C�~&Symfony/Component/Routing/Matcher/Dumper/MatcherDumperInterface.phpnu�[���PKw�ZY�IWW8��&Symfony/Component/Routing/Matcher/Dumper/DumperRoute.phpnu�[���PKw�Z�'��9��&Symfony/Component/Routing/Matcher/TraceableUrlMatcher.phpnu�[���PKw�ZGj�C""0��&Symfony/Component/Routing/Matcher/UrlMatcher.phpnu�[���PKw�Z� ��ffE'�&Symfony/Component/Routing/Matcher/RedirectableUrlMatcherInterface.phpnu�[���PKw�Z����==K�&Symfony/Component/Routing/Exception/MissingMandatoryParametersException.phpnu�[���PKw�Zj`j�A��&Symfony/Component/Routing/Exception/InvalidParameterException.phpnu�[���PKw�Znj�W��>/�&Symfony/Component/Routing/Exception/RouteNotFoundException.phpnu�[���PKw�Z��)���:��&Symfony/Component/Routing/Exception/ExceptionInterface.phpnu�[���PKw�Z����JJA��&Symfony/Component/Routing/Exception/MethodNotAllowedException.phpnu�[���PKw�Z?�]�//Af�&Symfony/Component/Routing/Exception/ResourceNotFoundException.phpnu�[���PKw�Z��^�==#�&Symfony/Component/Routing/Route.phpnu�[���PKw�Zr�����:i	'Symfony/Component/Routing/RequestContextAwareInterface.phpnu�[���PKw�Z|,{Ȫ�-p'Symfony/Component/Routing/RouteCollection.phpnu�[���PKw�Z�h�,w)'Symfony/Component/Routing/RequestContext.phpnu�[���PKw�Zմ���I�C'Symfony/Component/Routing/Generator/ConfigurableRequirementsInterface.phpnu�[���PKw�Z�
��1�148M'Symfony/Component/Routing/Generator/UrlGenerator.phpnu�[���PKw�Z�1O�
�
Az'Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.phpnu�[���PKw�Zu�'��>��'Symfony/Component/Routing/Generator/Dumper/GeneratorDumper.phpnu�[���PKw�Z�4��G��'Symfony/Component/Routing/Generator/Dumper/GeneratorDumperInterface.phpnu�[���PKw�Z����@@=�'Symfony/Component/Routing/Generator/UrlGeneratorInterface.phpnu�[���PKw�Zn���hh2Ȥ'Symfony/Component/Routing/Loader/ClosureLoader.phpnu�[���PKw�Z��?�		>��'Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.phpnu�[���PKw�Z~ޟ
�
9�'Symfony/Component/Routing/Loader/AnnotationFileLoader.phpnu�[���PKw�Z~L�W��:�'Symfony/Component/Routing/Loader/AnnotationClassLoader.phpnu�[���PKw�ZP�i{��2��'Symfony/Component/Routing/Loader/PhpFileLoader.phpnu�[���PKw�Z?-[��	�	?5�'Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsdnu�[���PKw�Zأ2D$D$2L�'Symfony/Component/Routing/Loader/XmlFileLoader.phpnu�[���PKw�ZpB�Q Q 3�(Symfony/Component/Routing/Loader/YamlFileLoader.phpnu�[���PKx�ZqF��>>4�5(Symfony/Component/Routing/RouteCompilerInterface.phpnu�[���PKx�Z0���QQ(H9(Symfony/Component/Process/autoloader.phpnu�[���PKx�Zg��'�'*�:(Symfony/Component/Process/ProcessPipes.phpnu�[���PKx�Z��2�{{@6c(Symfony/Component/Process/Exception/ProcessTimedOutException.phpnu�[���PKx�Z�<���:!j(Symfony/Component/Process/Exception/ExceptionInterface.phpnu�[���PKx�Z>H����8:l(Symfony/Component/Process/Exception/RuntimeException.phpnu�[���PKx�Z��W��6�n(Symfony/Component/Process/Exception/LogicException.phpnu�[���PKx�Z˅����@�p(Symfony/Component/Process/Exception/InvalidArgumentException.phpnu�[���PKx�Z��_��>s(Symfony/Component/Process/Exception/ProcessFailedException.phpnu�[���PKx�Z@s�(�x(Symfony/Component/Process/PhpProcess.phpnu�[���PKx�Z�nL	L	*�(Symfony/Component/Process/ProcessUtils.phpnu�[���PKy�Z�!,$

.��(Symfony/Component/Process/ExecutableFinder.phpnu�[���PKy�Z!/���,�(Symfony/Component/Process/ProcessBuilder.phpnu�[���PKy�Zy>�8��1�(Symfony/Component/Process/PhpExecutableFinder.phpnu�[���PKy�Z��M��%ު(Symfony/Component/Process/Process.phpnu�[���PKy�Z[i55ERA)Symfony/Component/Serializer/Normalizer/SerializerAwareNormalizer.phpnu�[���PKy�Z=Vxe::A�D)Symfony/Component/Serializer/Normalizer/NormalizableInterface.phpnu�[���PKy�Z��SVV<�J)Symfony/Component/Serializer/Normalizer/CustomNormalizer.phpnu�[���PKy�Z��,,BiR)Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.phpnu�[���PKy�Z"p�yy?q)Symfony/Component/Serializer/Normalizer/NormalizerInterface.phpnu�[���PKy�Z�qU���C�u)Symfony/Component/Serializer/Normalizer/DenormalizableInterface.phpnu�[���PKz�Z���A�{)Symfony/Component/Serializer/Normalizer/DenormalizerInterface.phpnu�[���PKz�Z���OO9t�)Symfony/Component/Serializer/SerializerAwareInterface.phpnu�[���PKz�Z��TT+,�)Symfony/Component/Serializer/autoloader.phpnu�[���PKz�Zx蕰

4ۅ)Symfony/Component/Serializer/SerializerInterface.phpnu�[���PKz�Z,�c��9L�)Symfony/Component/Serializer/Encoder/EncoderInterface.phpnu�[���PKz�Z��[�5�53i�)Symfony/Component/Serializer/Encoder/XmlEncoder.phpnu�[���PKz�Z�<=ggD��)Symfony/Component/Serializer/Encoder/NormalizationAwareInterface.phpnu�[���PKz�ZV��O��5��)Symfony/Component/Serializer/Encoder/ChainDecoder.phpnu�[���PKz�Z�=��?��)Symfony/Component/Serializer/Encoder/SerializerAwareEncoder.phpnu�[���PKz�Zv:�hh3[�)Symfony/Component/Serializer/Encoder/JsonEncode.phpnu�[���PKz�Z��@���3&�)Symfony/Component/Serializer/Encoder/JsonDecode.phpnu�[���PKz�ZS R�	�	5q�)Symfony/Component/Serializer/Encoder/ChainEncoder.phpnu�[���PKz�Z�o�vv4��)Symfony/Component/Serializer/Encoder/JsonEncoder.phpnu�[���PKz�Z|ͼ���9��)Symfony/Component/Serializer/Encoder/DecoderInterface.phpnu�[���PKz�ZA�A
��4�*Symfony/Component/Serializer/Exception/Exception.phpnu�[���PKz�Z�^L��?�*Symfony/Component/Serializer/Exception/UnsupportedException.phpnu�[���PKz�Z�h=��;�*Symfony/Component/Serializer/Exception/RuntimeException.phpnu�[���PKz�ZJ���9�*Symfony/Component/Serializer/Exception/LogicException.phpnu�[���PKz�ZT��Y��C	*Symfony/Component/Serializer/Exception/InvalidArgumentException.phpnu�[���PKz�Z[�����Ci*Symfony/Component/Serializer/Exception/UnexpectedValueException.phpnu�[���PKz�Zʪ2/&/&+�
*Symfony/Component/Serializer/Serializer.phpnu�[���PKz�ZFP�PP'<4*Symfony/Component/Locale/autoloader.phpnu�[���PKz�Z�Q�UUL�5*Symfony/Component/Locale/Exception/MethodArgumentNotImplementedException.phpnu�[���PKz�Z��E>�9*Symfony/Component/Locale/Exception/NotImplementedException.phpnu�[���PKz�ZS�?a%%D#=*Symfony/Component/Locale/Exception/MethodNotImplementedException.phpnu�[���PKz�Z���ssQ�@*Symfony/Component/Locale/Exception/MethodArgumentValueNotImplementedException.phpnu�[���PKz�Z�C��*�D*Symfony/Component/Locale/Stub/StubIntl.phpnu�[���PKz�Z&�����5�G*Symfony/Component/Locale/Stub/StubNumberFormatter.phpnu�[���PKz�Zv/�@�J*Symfony/Component/Locale/Stub/DateFormat/Hour2401Transformer.phpnu�[���PKz�Z��S@PN*Symfony/Component/Locale/Stub/DateFormat/TimeZoneTransformer.phpnu�[���PKz�Z}��""A�Q*Symfony/Component/Locale/Stub/DateFormat/DayOfYearTransformer.phpnu�[���PKz�Z�X�<oU*Symfony/Component/Locale/Stub/DateFormat/AmPmTransformer.phpnu�[���PKz�Z���<�X*Symfony/Component/Locale/Stub/DateFormat/YearTransformer.phpnu�[���PKz�Zmў?O\*Symfony/Component/Locale/Stub/DateFormat/QuarterTransformer.phpnu�[���PKz�Zg[ep>�_*Symfony/Component/Locale/Stub/DateFormat/MinuteTransformer.phpnu�[���PKz�Z:6""ARc*Symfony/Component/Locale/Stub/DateFormat/DayOfWeekTransformer.phpnu�[���PKz�Z9�u@�f*Symfony/Component/Locale/Stub/DateFormat/Hour1200Transformer.phpnu�[���PKz�Zk&"M@qj*Symfony/Component/Locale/Stub/DateFormat/Hour1201Transformer.phpnu�[���PKz�Z�����;�m*Symfony/Component/Locale/Stub/DateFormat/DayTransformer.phpnu�[���PKz�Z��@fq*Symfony/Component/Locale/Stub/DateFormat/Hour2400Transformer.phpnu�[���PKz�Z�Ed��8�t*Symfony/Component/Locale/Stub/DateFormat/Transformer.phpnu�[���PKz�Zt�z

=Ox*Symfony/Component/Locale/Stub/DateFormat/MonthTransformer.phpnu�[���PKz�Zk�H<�{*Symfony/Component/Locale/Stub/DateFormat/FullTransformer.phpnu�[���PKz�Z�3�X>6*Symfony/Component/Locale/Stub/DateFormat/SecondTransformer.phpnu�[���PKz�Z�
�

<��*Symfony/Component/Locale/Stub/DateFormat/HourTransformer.phpnu�[���PKz�Z���?��.-�*Symfony/Component/Locale/Stub/StubCollator.phpnu�[���PK{�Zq��*((,�*Symfony/Component/Locale/Stub/StubLocale.phpnu�[���PK{�Z� S���7��*Symfony/Component/Locale/Stub/StubIntlDateFormatter.phpnu�[���PK{�Zl�l��#��*Symfony/Component/Locale/Locale.phpnu�[���PK{�Z�t�TT+��*Symfony/Component/Filesystem/autoloader.phpnu�[���PK{�Z��dP��@b�*Symfony/Component/Filesystem/Exception/FileNotFoundException.phpnu�[���PK{�Z3{����=��*Symfony/Component/Filesystem/Exception/ExceptionInterface.phpnu�[���PK{�ZoC�~��?��*Symfony/Component/Filesystem/Exception/IOExceptionInterface.phpnu�[���PK{�Z;�{��6ͷ*Symfony/Component/Filesystem/Exception/IOException.phpnu�[���PK{�ZOظ�GG+�*Symfony/Component/Filesystem/Filesystem.phpnu�[���PK{�Z)��.�.'T+Symfony/Component/Form/FormRenderer.phpnu�[���PK{�Z�C����.]2+Symfony/Component/Form/ButtonTypeInterface.phpnu�[���PK{�ZK'�$��&�4+Symfony/Component/Form/FormBuilder.phpnu�[���PK{�Z&�"̰T�T,�S+Symfony/Component/Form/FormConfigBuilder.phpnu�[���PK{�ZE1�'��4��+Symfony/Component/Form/SubmitButtonTypeInterface.phpnu�[���PK{�Z�d��'�+Symfony/Component/Form/FormRegistry.phpnu�[���PK{�ZÊM'%%.н+Symfony/Component/Form/FormConfigInterface.phpnu�[���PK{�Z��@@/S�+Symfony/Component/Form/FormTypeGuesserChain.phpnu�[���PK{�ZR����+��+Symfony/Component/Form/Guess/ValueGuess.phpnu�[���PK{�Z�511&,�+Symfony/Component/Form/Guess/Guess.phpnu�[���PK{�Z���  *��+Symfony/Component/Form/Guess/TypeGuess.phpnu�[���PK{�Z�0\ZZ.-�+Symfony/Component/Form/CallbackTransformer.phpnu�[���PK{�Z4�Nz"z"!�,Symfony/Component/Form/Button.phpnu�[���PK{�Z-�9NN%�%,Symfony/Component/Form/autoloader.phpnu�[���PK{�Z�/��tt%S',Symfony/Component/Form/FormEvents.phpnu�[���PK{�Z�����,,,Symfony/Component/Form/FormTypeInterface.phpnu�[���PK{�Z�>���09,Symfony/Component/Form/FormRegistryInterface.phpnu�[���PK{�Z��?zz3?,Symfony/Component/Form/FormTypeGuesserInterface.phpnu�[���PK{�Z��*��+�G,Symfony/Component/Form/ResolvedFormType.phpnu�[���PK{�ZObX�qq'6f,Symfony/Component/Form/SubmitButton.phpnu�[���PK|�Z�p��1�j,Symfony/Component/Form/AbstractRendererEngine.phpnu�[���PK|�ZDjN,1�,Symfony/Component/Form/AbstractExtension.phpnu�[���PK|�Zf#jK��6��,Symfony/Component/Form/FormRendererEngineInterface.phpnu�[���PK|�Z���1�1���,Symfony/Component/Form/Form.phpnu�[���PK|�Z�di���;A-Symfony/Component/Form/Exception/BadMethodCallException.phpnu�[���PK|�Z�W�

:yC-Symfony/Component/Form/Exception/AlreadyBoundException.phpnu�[���PK|�Z(ddB�E-Symfony/Component/Form/Exception/InvalidConfigurationException.phpnu�[���PK|�Z�_c==<�G-Symfony/Component/Form/Exception/UnexpectedTypeException.phpnu�[���PK|�Z�S�D��BoJ-Symfony/Component/Form/Exception/TransformationFailedException.phpnu�[���PK|�Z��9�L-Symfony/Component/Form/Exception/OutOfBoundsException.phpnu�[���PK}�Z�y�u��7�N-Symfony/Component/Form/Exception/ExceptionInterface.phpnu�[���PK}�ZN����5
Q-Symfony/Component/Form/Exception/RuntimeException.phpnu�[���PK}�ZK�9���>OS-Symfony/Component/Form/Exception/AlreadySubmittedException.phpnu�[���PK}�Z1�;TT:�U-Symfony/Component/Form/Exception/ErrorMappingException.phpnu�[���PK}�Z��+RR8oW-Symfony/Component/Form/Exception/StringCastException.phpnu�[���PK}�Z��X��3)Y-Symfony/Component/Form/Exception/LogicException.phpnu�[���PK}�Z�gBz��=d[-Symfony/Component/Form/Exception/InvalidArgumentException.phpnu�[���PK}�Z�1��88'�]-Symfony/Component/Form/AbstractType.phpnu�[���PK}�Z�I	�66.Ub-Symfony/Component/Form/Util/OrderedHashMap.phpnu�[���PK}�Z�h��''6�t-Symfony/Component/Form/Util/OrderedHashMapIterator.phpnu�[���PK}�Z��F228v�-Symfony/Component/Form/Util/VirtualFormAwareIterator.phpnu�[���PK}�Zy���$$(�-Symfony/Component/Form/Util/FormUtil.phpnu�[���PK}�Z<����8��-Symfony/Component/Form/Util/InheritDataAwareIterator.phpnu�[���PK}�Z�QT�pp.�-Symfony/Component/Form/SubmitButtonBuilder.phpnu�[���PK}�Z�z5���2��-Symfony/Component/Form/ResolvedFormTypeFactory.phpnu�[���PK}�ZSf��
	
	-��-Symfony/Component/Form/PreloadedExtension.phpnu�[���PK}�Z>��*ii&�-Symfony/Component/Form/FormFactory.phpnu�[���PK}�Z�\�g��2˳-Symfony/Component/Form/RequestHandlerInterface.phpnu�[���PK}�Z+q�DAA7ɶ-Symfony/Component/Form/Test/FormPerformanceTestCase.phpnu�[���PK}�ZsŪ�,q�-Symfony/Component/Form/Test/TypeTestCase.phpnu�[���PK}�Z�,�7//7�-Symfony/Component/Form/Test/DeprecationErrorHandler.phpnu�[���PK}�ZB�4I++7k�-Symfony/Component/Form/Test/FormIntegrationTestCase.phpnu�[���PK}�Z��m�yy4��-Symfony/Component/Form/Test/FormBuilderInterface.phpnu�[���PK}�Za(0kk-��-Symfony/Component/Form/Test/FormInterface.phpnu�[���PK}�Z�n����1��-Symfony/Component/Form/FormExtensionInterface.phpnu�[���PK}�Z|G����4��-Symfony/Component/Form/ResolvedFormTypeInterface.phpnu�[���PK}�Z{d���!�!5��-Symfony/Component/Form/FormConfigBuilderInterface.phpnu�[���PK}�ZɃT���6.Symfony/Component/Form/FormFactoryBuilderInterface.phpnu�[���PK}�Z�N̷;m.Symfony/Component/Form/ResolvedFormTypeFactoryInterface.phpnu�[���PK}�Z2��-�.Symfony/Component/Form/FormFactoryBuilder.phpnu�[���PK}�Z���C��0d$.Symfony/Component/Form/AbstractTypeExtension.phpnu�[���PK}�Z�E���0�(.Symfony/Component/Form/FormRendererInterface.phpnu�[���PK}�Z�:		/�5.Symfony/Component/Form/FormBuilderInterface.phpnu�[���PK}�Z��Z)��/R?.Symfony/Component/Form/FormFactoryInterface.phpnu�[���PK}�Z�YB���.EP.Symfony/Component/Form/ReversedTransformer.phpnu�[���PK}�Z�r�WW3�U.Symfony/Component/Form/DataTransformerInterface.phpnu�[���PK}�ZW�b�[H[H(Eb.Symfony/Component/Form/ButtonBuilder.phpnu�[���PK}�Z��n��?��.Symfony/Component/Form/Resources/translations/validators.en.xlfnu�[���PK}�Z誫���?�.Symfony/Component/Form/Resources/translations/validators.sk.xlfnu�[���PK}�Z�<�yy?=�.Symfony/Component/Form/Resources/translations/validators.uk.xlfnu�[���PK}�Z:����?%�.Symfony/Component/Form/Resources/translations/validators.pl.xlfnu�[���PK��Z��
���?[�.Symfony/Component/Form/Resources/translations/validators.pt.xlfnu�[���PK��Z�%��?��.Symfony/Component/Form/Resources/translations/validators.lv.xlfnu�[���PK��Z္o33D��.Symfony/Component/Form/Resources/translations/validators.sr_Cyrl.xlfnu�[���PK��Z����?��.Symfony/Component/Form/Resources/translations/validators.fi.xlfnu�[���PK��Z0h���?��.Symfony/Component/Form/Resources/translations/validators.es.xlfnu�[���PK��Z�TI��?,�.Symfony/Component/Form/Resources/translations/validators.de.xlfnu�[���PK��Z!�aZ��?~�.Symfony/Component/Form/Resources/translations/validators.it.xlfnu�[���PK��Z �!���?��.Symfony/Component/Form/Resources/translations/validators.ca.xlfnu�[���PK��Z���?��.Symfony/Component/Form/Resources/translations/validators.mn.xlfnu�[���PK��Z���-��?X�.Symfony/Component/Form/Resources/translations/validators.ru.xlfnu�[���PK��Z�3Ե^^?T�.Symfony/Component/Form/Resources/translations/validators.bg.xlfnu�[���PK��ZE��d��?!�.Symfony/Component/Form/Resources/translations/validators.ro.xlfnu�[���PK��ZO���?r�.Symfony/Component/Form/Resources/translations/validators.nl.xlfnu�[���PK��ZS�*��?��.Symfony/Component/Form/Resources/translations/validators.et.xlfnu�[���PK��Z�V5?��.Symfony/Component/Form/Resources/translations/validators.fa.xlfnu�[���PK��Z��q��?J�.Symfony/Component/Form/Resources/translations/validators.id.xlfnu�[���PK��Z�
���?w/Symfony/Component/Form/Resources/translations/validators.cs.xlfnu�[���PK��Z�8,:��B�/Symfony/Component/Form/Resources/translations/validators.zh_CN.xlfnu�[���PK��Z�H�q��?�
/Symfony/Component/Form/Resources/translations/validators.lt.xlfnu�[���PK��Z�_8��?�/Symfony/Component/Form/Resources/translations/validators.fr.xlfnu�[���PK��Z�A�4��?�/Symfony/Component/Form/Resources/translations/validators.gl.xlfnu�[���PK��Z
b�8��?4/Symfony/Component/Form/Resources/translations/validators.hr.xlfnu�[���PK��ZWgUugg?]/Symfony/Component/Form/Resources/translations/validators.nb.xlfnu�[���PK��Zٻ��||?3/Symfony/Component/Form/Resources/translations/validators.eu.xlfnu�[���PK��Z�4@���B#/Symfony/Component/Form/Resources/translations/validators.pt_BR.xlfnu�[���PK��Z��5��?Q'/Symfony/Component/Form/Resources/translations/validators.sl.xlfnu�[���PK��Z�*{���?m+/Symfony/Component/Form/Resources/translations/validators.lb.xlfnu�[���PK��Zbe�@��?�//Symfony/Component/Form/Resources/translations/validators.hu.xlfnu�[���PK��Z_Π��?4/Symfony/Component/Form/Resources/translations/validators.el.xlfnu�[���PK��ZX�����?9/Symfony/Component/Form/Resources/translations/validators.da.xlfnu�[���PK��Z���?�</Symfony/Component/Form/Resources/translations/validators.ja.xlfnu�[���PK��Zs>�ll?AA/Symfony/Component/Form/Resources/translations/validators.sv.xlfnu�[���PK��Zy��99?E/Symfony/Component/Form/Resources/translations/validators.hy.xlfnu�[���PK��Z|��C?�I/Symfony/Component/Form/Resources/translations/validators.ar.xlfnu�[���PK��Zr���DBN/Symfony/Component/Form/Resources/translations/validators.sr_Latn.xlfnu�[���PK��ZNP\��?dR/Symfony/Component/Form/Resources/translations/validators.he.xlfnu�[���PK��Z�xfh..6dV/Symfony/Component/Form/Resources/config/validation.xmlnu�[���PK��ZR}��jj.�X/Symfony/Component/Form/DataMapperInterface.phpnu�[���PK��Z�s�� � (�]/Symfony/Component/Form/FormInterface.phpnu�[���PK��Z���"��$�~/Symfony/Component/Form/FormEvent.phpnu�[���PK��Z�=�MM5Ӄ/Symfony/Component/Form/FormTypeExtensionInterface.phpnu�[���PK��Z�}p�

$��/Symfony/Component/Form/FormError.phpnu�[���PK��Z�	���/ܖ/Symfony/Component/Form/NativeRequestHandler.phpnu�[���PK��Z���*��O'�/Symfony/Component/Form/Extension/Validator/EventListener/ValidationListener.phpnu�[���PK��Z��Ck��@5�/Symfony/Component/Form/Extension/Validator/Util/ServerParams.phpnu�[���PK��Z2=[<((A1�/Symfony/Component/Form/Extension/Validator/ValidatorExtension.phpnu�[���PK��Z}>�ُ�?��/Symfony/Component/Form/Extension/Validator/Constraints/Form.phpnu�[���PK��Z�-�P��H��/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.phpnu�[���PK��Zl�Ct*t*C��/Symfony/Component/Form/Extension/Validator/ValidatorTypeGuesser.phpnu�[���PK��ZɥS��T�
0Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPathIterator.phpnu�[���PK��Z�\T��K0Symfony/Component/Form/Extension/Validator/ViolationMapper/RelativePath.phpnu�[���PK��ZC_�hU+U+N0Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.phpnu�[���PK��Z�k�t==W�@0Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapperInterface.phpnu�[���PK��Z�-��!!L�E0Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPath.phpnu�[���PK��Zf����
�
JR_0Symfony/Component/Form/Extension/Validator/ViolationMapper/MappingRule.phpnu�[���PK��Z�����J�j0Symfony/Component/Form/Extension/Validator/Type/BaseValidatorExtension.phpnu�[���PK��ZeBR�	�	N�p0Symfony/Component/Form/Extension/Validator/Type/FormTypeValidatorExtension.phpnu�[���PK��Z͚>�@@R+{0Symfony/Component/Form/Extension/Validator/Type/RepeatedTypeValidatorExtension.phpnu�[���PK��Z1���P�0Symfony/Component/Form/Extension/Validator/Type/SubmitTypeValidatorExtension.phpnu�[���PK��Z���,QQC��0Symfony/Component/Form/Extension/Templating/TemplatingExtension.phpnu�[���PK��Zզ�Y��HL�0Symfony/Component/Form/Extension/Templating/TemplatingRendererEngine.phpnu�[���PK��Z䋧��U��0Symfony/Component/Form/Extension/HttpFoundation/EventListener/BindRequestListener.phpnu�[���PK��Z�j��=
=
PԦ0Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationRequestHandler.phpnu�[���PK��Z��Q��K��0Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationExtension.phpnu�[���PK��Z�PffX��0Symfony/Component/Form/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.phpnu�[���PK��Z"�q���7��0Symfony/Component/Form/Extension/Csrf/CsrfExtension.phpnu�[���PK��Z�C���J��0Symfony/Component/Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.phpnu�[���PK��Z[^����J��0Symfony/Component/Form/Extension/Csrf/CsrfProvider/SessionCsrfProvider.phpnu�[���PK��Z%�G���L�0Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderInterface.phpnu�[���PK��Z�����JI�0Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderAdapter.phpnu�[���PK��ZR�'WTTN��0Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfTokenManagerAdapter.phpnu�[���PK��Z�?�ooNy�0Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.phpnu�[���PK��Z��
f��Df�0Symfony/Component/Form/Extension/Csrf/Type/FormTypeCsrfExtension.phpnu�[���PK��ZC�W���7�
1Symfony/Component/Form/Extension/Core/CoreExtension.phpnu�[���PK��Z�:AAD�1Symfony/Component/Form/Extension/Core/EventListener/TrimListener.phpnu�[���PK��Zõe��O�1Symfony/Component/Form/Extension/Core/EventListener/MergeCollectionListener.phpnu�[���PK��Z>Q?��N�+1Symfony/Component/Form/Extension/Core/EventListener/FixUrlProtocolListener.phpnu�[���PK��Zb����P�11Symfony/Component/Form/Extension/Core/EventListener/FixCheckboxInputListener.phpnu�[���PK��Z\��//J�=1Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.phpnu�[���PK��Z?D���M�Q1Symfony/Component/Form/Extension/Core/EventListener/FixRadioInputListener.phpnu�[���PK��Z�jю��E�Z1Symfony/Component/Form/Extension/Core/ChoiceList/SimpleChoiceList.phpnu�[���PK��Z�
�##E�p1Symfony/Component/Form/Extension/Core/ChoiceList/ObjectChoiceList.phpnu�[���PK��Zl_R(H��1Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceListInterface.phpnu�[���PK��Z�В4
4
C�1Symfony/Component/Form/Extension/Core/ChoiceList/LazyChoiceList.phpnu�[���PK��Z'���??��1Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceList.phpnu�[���PK��Z��&PP9��1Symfony/Component/Form/Extension/Core/View/ChoiceView.phpnu�[���PK��Z��

Gl�1Symfony/Component/Form/Extension/Core/DataMapper/PropertyPathMapper.phpnu�[���PK��ZO�#�#�#\�2Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.phpnu�[���PK��Z)b�""^)2Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.phpnu�[���PK��Ze�^�		V�?2Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.phpnu�[���PK��Z���Þ
�
XVI2Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.phpnu�[���PK��Zc�8V�	�	N|T2Symfony/Component/Form/Extension/Core/DataTransformer/DataTransformerChain.phpnu�[���PK��Z�;�dd]�^2Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.phpnu�[���PK��Z�Z�eTwo2Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToArrayTransformer.phpnu�[���PK��ZL�px&&Y�2Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.phpnu�[���PK��Z����		V��2Symfony/Component/Form/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.phpnu�[���PK��Z'tqk55ZJ�2Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.phpnu�[���PK��Z���ggT	�2Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToValuesTransformer.phpnu�[���PK��ZUd�q]�2Symfony/Component/Form/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.phpnu�[���PK��ZΎgW� � U��2Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToStringTransformer.phpnu�[���PK��Z�"h���R��2Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToValueTransformer.phpnu�[���PK��Z�H��		Q��2Symfony/Component/Form/Extension/Core/DataTransformer/ArrayToPartsTransformer.phpnu�[���PK��Z/C���QO�2Symfony/Component/Form/Extension/Core/DataTransformer/BaseDateTimeTransformer.phpnu�[���PK��Z���T��T��2Symfony/Component/Form/Extension/Core/DataTransformer/BooleanToStringTransformer.phpnu�[���PK��Z]��yD	D	[/3Symfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.phpnu�[���PK��Z���/�+�+9�
3Symfony/Component/Form/Extension/Core/Type/ChoiceType.phpnu�[���PK��Z��h��9:3Symfony/Component/Form/Extension/Core/Type/ButtonType.phpnu�[���PK��ZD�U��9s>3Symfony/Component/Form/Extension/Core/Type/SubmitType.phpnu�[���PK��Z񍢸��;�B3Symfony/Component/Form/Extension/Core/Type/CurrencyType.phpnu�[���PK��Z�Ѝ'��9�F3Symfony/Component/Form/Extension/Core/Type/HiddenType.phpnu�[���PK��Z���D��9�J3Symfony/Component/Form/Extension/Core/Type/LocaleType.phpnu�[���PK��ZuƵ�``:O3Symfony/Component/Form/Extension/Core/Type/IntegerType.phpnu�[���PK��Za����8�W3Symfony/Component/Form/Extension/Core/Type/ResetType.phpnu�[���PK��Z옇���;'[3Symfony/Component/Form/Extension/Core/Type/PasswordType.phpnu�[���PK��Zٝ��GG7]`3Symfony/Component/Form/Extension/Core/Type/BaseType.phpnu�[���PK��ZZ���^^:r3Symfony/Component/Form/Extension/Core/Type/PercentType.phpnu�[���PK��Z��TT;�w3Symfony/Component/Form/Extension/Core/Type/CheckboxType.phpnu�[���PK��Z&ߏ�vv;��3Symfony/Component/Form/Extension/Core/Type/BirthdayType.phpnu�[���PK��Z7pO�LL8s�3Symfony/Component/Form/Extension/Core/Type/RadioType.phpnu�[���PK��Z�G�oo7'�3Symfony/Component/Form/Extension/Core/Type/FileType.phpnu�[���PK��Z�8��JJ9��3Symfony/Component/Form/Extension/Core/Type/SearchType.phpnu�[���PK��Z�_��LL;��3Symfony/Component/Form/Extension/Core/Type/TimezoneType.phpnu�[���PK��Z���HH8g�3Symfony/Component/Form/Extension/Core/Type/EmailType.phpnu�[���PK��Z[Gԃ��=�3Symfony/Component/Form/Extension/Core/Type/CollectionType.phpnu�[���PK��Z�t�II;1�3Symfony/Component/Form/Extension/Core/Type/TextareaType.phpnu�[���PK��Z����;�3Symfony/Component/Form/Extension/Core/Type/LanguageType.phpnu�[���PK��ZT;���7��3Symfony/Component/Form/Extension/Core/Type/TextType.phpnu�[���PK��ZH?!a��7J�3Symfony/Component/Form/Extension/Core/Type/TimeType.phpnu�[���PK��Z�� &�'�';��3Symfony/Component/Form/Extension/Core/Type/DateTimeType.phpnu�[���PK��Z�q���6��3Symfony/Component/Form/Extension/Core/Type/UrlType.phpnu�[���PK��Z9�;�3Symfony/Component/Form/Extension/Core/Type/RepeatedType.phpnu�[���PK��ZM2\3,3,7E4Symfony/Component/Form/Extension/Core/Type/DateType.phpnu�[���PK��Za�LŢ�:�34Symfony/Component/Form/Extension/Core/Type/CountryType.phpnu�[���PK��ZC�i���9�74Symfony/Component/Form/Extension/Core/Type/NumberType.phpnu�[���PK��Z:�y�

7;@4Symfony/Component/Form/Extension/Core/Type/FormType.phpnu�[���PK��Z5�S
��8�\4Symfony/Component/Form/Extension/Core/Type/MoneyType.phpnu�[���PK��Z6s���D�i4Symfony/Component/Form/Extension/DataCollector/FormDataCollector.phpnu�[���PK��ZI��2

Vȇ4Symfony/Component/Form/Extension/DataCollector/EventListener/DataCollectorListener.phpnu�[���PK��Z�T���Mc�4Symfony/Component/Form/Extension/DataCollector/FormDataCollectorInterface.phpnu�[���PK��Z����M��4Symfony/Component/Form/Extension/DataCollector/FormDataExtractorInterface.phpnu�[���PK��Z|�
]��W�4Symfony/Component/Form/Extension/DataCollector/Proxy/ResolvedTypeDataCollectorProxy.phpnu�[���PK��Z�((^6�4Symfony/Component/Form/Extension/DataCollector/Proxy/ResolvedTypeFactoryDataCollectorProxy.phpnu�[���PK��Z��#�11I�4Symfony/Component/Form/Extension/DataCollector/DataCollectorExtension.phpnu�[���PK��Z%�`��D��4Symfony/Component/Form/Extension/DataCollector/FormDataExtractor.phpnu�[���PK��Z�1�
uuR��4Symfony/Component/Form/Extension/DataCollector/Type/DataCollectorTypeExtension.phpnu�[���PK��ZuUS�WWU��4Symfony/Component/Form/Extension/DependencyInjection/DependencyInjectionExtension.phpnu�[���PK��Z(s
//-a�4Symfony/Component/Form/ClickableInterface.phpnu�[���PK��ZH��
�
#��4Symfony/Component/Form/FormView.phpnu�[���PK��Z
�͋ �4Symfony/Component/Form/Forms.phpnu�[���PK��Z\�F1_
5Symfony/Component/Security/Acl/Voter/AclVoter.phpnu�[���PK��Z\!�	HH2�#5Symfony/Component/Security/Acl/Voter/FieldVote.phpnu�[���PK��ZP͡��Am'5Symfony/Component/Security/Acl/Exception/AclNotFoundException.phpnu�[���PK��Z�k�q��6�)5Symfony/Component/Security/Acl/Exception/Exception.phpnu�[���PK��Z�W�L�+5Symfony/Component/Security/Acl/Exception/ConcurrentModificationException.phpnu�[���PK��Z���OI}.5Symfony/Component/Security/Acl/Exception/InvalidDomainObjectException.phpnu�[���PK��Z]��_""E15Symfony/Component/Security/Acl/Exception/NotAllAclsFoundException.phpnu�[���PK��Z�B�l��@�55Symfony/Component/Security/Acl/Exception/NoAceFoundException.phpnu�[���PK��Z[�z�B�85Symfony/Component/Security/Acl/Exception/SidNotLoadedException.phpnu�[���PK��Z��5�

F;5Symfony/Component/Security/Acl/Exception/AclAlreadyExistsException.phpnu�[���PK��Zt��:�=5Symfony/Component/Security/Acl/Dbal/MutableAclProvider.phpnu�[���PK��Z�^�+f+f3��5Symfony/Component/Security/Acl/Dbal/AclProvider.phpnu�[���PK��ZK� V��.n,6Symfony/Component/Security/Acl/Dbal/Schema.phpnu�[���PK��ZNTA�]]5�D6Symfony/Component/Security/Acl/Domain/AuditLogger.phpnu�[���PK��Z�.��**>sJ6Symfony/Component/Security/Acl/Domain/UserSecurityIdentity.phpnu�[���PK��Z��C3��:W6Symfony/Component/Security/Acl/Domain/DoctrineAclCache.phpnu�[���PK��Z(]���D#p6Symfony/Component/Security/Acl/Domain/PermissionGrantingStrategy.phpnu�[���PK��Z%�}`M`M-k�6Symfony/Component/Security/Acl/Domain/Acl.phpnu�[���PK��Z����K(�6Symfony/Component/Security/Acl/Domain/SecurityIdentityRetrievalStrategy.phpnu�[���PK��Z�X�
/	/	<K�6Symfony/Component/Security/Acl/Domain/AclCollectionCache.phpnu�[���PK��Z5D�[/��6Symfony/Component/Security/Acl/Domain/Entry.phpnu�[���PK��Z�pU���4H7Symfony/Component/Security/Acl/Domain/FieldEntry.phpnu�[���PK��Z^@�.YY8R7Symfony/Component/Security/Acl/Domain/ObjectIdentity.phpnu�[���PK��Z0F���I7Symfony/Component/Security/Acl/Domain/ObjectIdentityRetrievalStrategy.phpnu�[���PK��ZtA)�==>J7Symfony/Component/Security/Acl/Domain/RoleSecurityIdentity.phpnu�[���PK��Z�#��~~<�#7Symfony/Component/Security/Acl/Resources/bin/generateSql.phpnu�[���PK��Zj~	cFF7�+7Symfony/Component/Security/Acl/Resources/schema/db2.sqlnu�[���PK��ZT��skk>�87Symfony/Component/Security/Acl/Resources/schema/postgresql.sqlnu�[���PK��ZJx�.

9eE7Symfony/Component/Security/Acl/Resources/schema/mssql.sqlnu�[���PK��ZfZ��^^9�R7Symfony/Component/Security/Acl/Resources/schema/mysql.sqlnu�[���PK��Z��c�
�
;�^7Symfony/Component/Security/Acl/Resources/schema/drizzle.sqlnu�[���PK��Z�C� ;;:�i7Symfony/Component/Security/Acl/Resources/schema/oracle.sqlnu�[���PK��Z��d��:I�7Symfony/Component/Security/Acl/Resources/schema/sqlite.sqlnu�[���PK��Zw���D��7Symfony/Component/Security/Acl/Permission/PermissionMapInterface.phpnu�[���PK��Z�ep�gg9��7Symfony/Component/Security/Acl/Permission/MaskBuilder.phpnu�[���PK��Z� c0��@ͫ7Symfony/Component/Security/Acl/Permission/BasicPermissionMap.phpnu�[���PK��Z6����<��7Symfony/Component/Security/Acl/Model/MutableAclInterface.phpnu�[���PK��Z[Ob3SK�7Symfony/Component/Security/Acl/Model/SecurityIdentityRetrievalStrategyInterface.phpnu�[���PK��ZX	��>��7Symfony/Component/Security/Acl/Model/DomainObjectInterface.phpnu�[���PK��Z�5Ayy@
�7Symfony/Component/Security/Acl/Model/ObjectIdentityInterface.phpnu�[���PK��Zt��@��7Symfony/Component/Security/Acl/Model/AuditableEntryInterface.phpnu�[���PK��Z-癥��Lk�7Symfony/Component/Security/Acl/Model/PermissionGrantingStrategyInterface.phpnu�[���PK��Z�����=��7Symfony/Component/Security/Acl/Model/AclProviderInterface.phpnu�[���PK��Z�#���:&�7Symfony/Component/Security/Acl/Model/AclCacheInterface.phpnu�[���PK��Zӗ&1>��7Symfony/Component/Security/Acl/Model/AuditableAclInterface.phpnu�[���PK��Z�ݤUU<�7Symfony/Component/Security/Acl/Model/FieldEntryInterface.phpnu�[���PK��Z�
�8FF7�7Symfony/Component/Security/Acl/Model/EntryInterface.phpnu�[���PK��ZH<J��=��7Symfony/Component/Security/Acl/Model/AuditLoggerInterface.phpnu�[���PK��Z���77B�8Symfony/Component/Security/Acl/Model/SecurityIdentityInterface.phpnu�[���PK��Z�𕛼�5L8Symfony/Component/Security/Acl/Model/AclInterface.phpnu�[���PK��Z�W}��Qm8Symfony/Component/Security/Acl/Model/ObjectIdentityRetrievalStrategyInterface.phpnu�[���PK��Zj���D�8Symfony/Component/Security/Acl/Model/MutableAclProviderInterface.phpnu�[���PK��Z��W"RR)�8Symfony/Component/Security/autoloader.phpnu�[���PK��Z�DXVV,t8Symfony/Component/Security/Http/Firewall.phpnu�[���PK��Z"�C��/&'8Symfony/Component/Security/Http/FirewallMap.phpnu�[���PK��Z�יK--8Symfony/Component/Security/Http/EntryPoint/FormAuthenticationEntryPoint.phpnu�[���PK��Z�<ݐppL�58Symfony/Component/Security/Http/EntryPoint/BasicAuthenticationEntryPoint.phpnu�[���PK��Z)'_++P�:8Symfony/Component/Security/Http/EntryPoint/AuthenticationEntryPointInterface.phpnu�[���PK��ZtZ�)K	K	MN?8Symfony/Component/Security/Http/EntryPoint/DigestAuthenticationEntryPoint.phpnu�[���PK��Z�����LI8Symfony/Component/Security/Http/EntryPoint/RetryAuthenticationEntryPoint.phpnu�[���PK��Z��`C��-,P8Symfony/Component/Security/Http/HttpUtils.phpnu�[���PK��Z^�V��N^h8Symfony/Component/Security/Http/Authorization/AccessDeniedHandlerInterface.phpnu�[���PK��Z��̗��W�l8Symfony/Component/Security/Http/Firewall/UsernamePasswordFormAuthenticationListener.phpnu�[���PK��Znz+S�
�
?8Symfony/Component/Security/Http/Firewall/RememberMeListener.phpnu�[���PK��Zlٯ��L6�8Symfony/Component/Security/Http/Firewall/AnonymousAuthenticationListener.phpnu�[���PK��Z�����>��8Symfony/Component/Security/Http/Firewall/ListenerInterface.phpnu�[���PK��Z�|L@**;��8Symfony/Component/Security/Http/Firewall/LogoutListener.phpnu�[���PK��Z�Bb

?J�8Symfony/Component/Security/Http/Firewall/SwitchUserListener.phpnu�[���PK��Z(�T	b!b!>��8Symfony/Component/Security/Http/Firewall/ExceptionListener.phpnu�[���PK��Z׺�=��G��8Symfony/Component/Security/Http/Firewall/X509AuthenticationListener.phpnu�[���PK��Z׿ͼ� � I��8Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.phpnu�[���PK��Z~�k��<19Symfony/Component/Security/Http/Firewall/ChannelListener.phpnu�[���PK��Z��6'6'K�9Symfony/Component/Security/Http/Firewall/AbstractAuthenticationListener.phpnu�[���PK��Z�"?���<?A9Symfony/Component/Security/Http/Firewall/ContextListener.phpnu�[���PK��Z�����MSY9Symfony/Component/Security/Http/Firewall/SimpleFormAuthenticationListener.phpnu�[���PK��Z+/��Z	Z	;�q9Symfony/Component/Security/Http/Firewall/AccessListener.phpnu�[���PK��Z�Z���Mg{9Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.phpnu�[���PK��Zn��L��9Symfony/Component/Security/Http/Firewall/SimplePreAuthenticationListener.phpnu�[���PK��Z�&!�
�
H+�9Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.phpnu�[���PK��Z2j���-$�9Symfony/Component/Security/Http/AccessMap.phpnu�[���PK��Z/�``6x�9Symfony/Component/Security/Http/AccessMapInterface.phpnu�[���PK��Z��\\��8>�9Symfony/Component/Security/Http/FirewallMapInterface.phpnu�[���PK��Z	z��J��9Symfony/Component/Security/Http/RememberMe/RememberMeServicesInterface.phpnu�[���PK��ZP�ڕ��?��9Symfony/Component/Security/Http/RememberMe/ResponseListener.phpnu�[���PK��Z���s44U�9Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.phpnu�[���PK��Z�*�b�&�&I��9Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.phpnu�[���PK��Z�a�$��K!
:Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.phpnu�[���PK��Z:�&�GGR!:Symfony/Component/Security/Http/Session/SessionAuthenticationStrategyInterface.phpnu�[���PK��Z��La[[I�":Symfony/Component/Security/Http/Session/SessionAuthenticationStrategy.phpnu�[���PK��Za7�llF�):Symfony/Component/Security/Http/Logout/DefaultLogoutSuccessHandler.phpnu�[���PK��Z1��d��H�.:Symfony/Component/Security/Http/Logout/LogoutSuccessHandlerInterface.phpnu�[���PK��Z\ü���?�2:Symfony/Component/Security/Http/Logout/SessionLogoutHandler.phpnu�[���PK��Z6O����A07:Symfony/Component/Security/Http/Logout/LogoutHandlerInterface.phpnu�[���PK��Z�ddF�;:Symfony/Component/Security/Http/Logout/CookieClearingLogoutHandler.phpnu�[���PK��Z/ sG��2xA:Symfony/Component/Security/Http/SecurityEvents.phpnu�[���PK��Z�NA��X�E:Symfony/Component/Security/Http/Authentication/AuthenticationSuccessHandlerInterface.phpnu�[���PK��Z������V/K:Symfony/Component/Security/Http/Authentication/DefaultAuthenticationFailureHandler.phpnu�[���PK��Z��H]X�X:Symfony/Component/Security/Http/Authentication/AuthenticationFailureHandlerInterface.phpnu�[���PK��Z�xGAAV^:Symfony/Component/Security/Http/Authentication/DefaultAuthenticationSuccessHandler.phpnu�[���PK��ZAH\ݞ�N�j:Symfony/Component/Security/Http/Authentication/SimpleAuthenticationHandler.phpnu�[���PK��Z�D����9|:Symfony/Component/Security/Http/Event/SwitchUserEvent.phpnu�[���PK��ZZ�v}?^�:Symfony/Component/Security/Http/Event/InteractiveLoginEvent.phpnu�[���PK��Z��VǴ�=L�:Symfony/Component/Security/Csrf/CsrfTokenManagerInterface.phpnu�[���PK��Z&%�L
L
4m�:Symfony/Component/Security/Csrf/CsrfTokenManager.phpnu�[���PK��Z�����
�
J�:Symfony/Component/Security/Csrf/TokenStorage/NativeSessionTokenStorage.phpnu�[���PK��Z�����Fn�:Symfony/Component/Security/Csrf/TokenStorage/TokenStorageInterface.phpnu�[���PK��Z��]N
N
Dq�:Symfony/Component/Security/Csrf/TokenStorage/SessionTokenStorage.phpnu�[���PK��ZeI����D3�:Symfony/Component/Security/Csrf/Exception/TokenNotFoundException.phpnu�[���PK��Z��=H��:Symfony/Component/Security/Csrf/TokenGenerator/UriSafeTokenGenerator.phpnu�[���PK��ZJ,p���J�:Symfony/Component/Security/Csrf/TokenGenerator/TokenGeneratorInterface.phpnu�[���PK��Z���O-3�:Symfony/Component/Security/Csrf/CsrfToken.phpnu�[���PK��Z��S��<��:Symfony/Component/Security/Core/SecurityContextInterface.phpnu�[���PK��Z�}�ww?��:Symfony/Component/Security/Core/Role/RoleHierarchyInterface.phpnu�[���PK��Z� �w??6m�:Symfony/Component/Security/Core/Role/RoleHierarchy.phpnu�[���PK��Z�Ħ-�:Symfony/Component/Security/Core/Role/Role.phpnu�[���PK��ZX�S�007t�:Symfony/Component/Security/Core/Role/SwitchUserRole.phpnu�[���PK��Z�'c��6�:Symfony/Component/Security/Core/Role/RoleInterface.phpnu�[���PK��ZE� �D�:Symfony/Component/Security/Core/Encoder/PasswordEncoderInterface.phpnu�[���PK��ZÆ��	�	A��:Symfony/Component/Security/Core/Encoder/BCryptPasswordEncoder.phpnu�[���PK��Z��^��H�:Symfony/Component/Security/Core/Encoder/MessageDigestPasswordEncoder.phpnu�[���PK��Z,>"�D�:Symfony/Component/Security/Core/Encoder/PlaintextPasswordEncoder.phpnu�[���PK��Z�;D��:b;Symfony/Component/Security/Core/Encoder/EncoderFactory.phpnu�[���PK��Z!�@

A�
;Symfony/Component/Security/Core/Encoder/Pbkdf2PasswordEncoder.phpnu�[���PK��Z#�MMqqCx;Symfony/Component/Security/Core/Encoder/EncoderFactoryInterface.phpnu�[���PK��Z�7���
�
?\;Symfony/Component/Security/Core/Encoder/BasePasswordEncoder.phpnu�[���PK��Z��
�77O�*;Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.phpnu�[���PK��Z��i��Fi1;Symfony/Component/Security/Core/Validator/Constraints/UserPassword.phpnu�[���PK��Z����Es4;Symfony/Component/Security/Core/Exception/BadCredentialsException.phpnu�[���PK��Z���zz=}7;Symfony/Component/Security/Core/Exception/LockedException.phpnu�[���PK��Zb��M<<Fd:;Symfony/Component/Security/Core/Exception/UnsupportedUserException.phpnu�[���PK��Z�z�&��I=;Symfony/Component/Security/Core/Exception/CredentialsExpiredException.phpnu�[���PK��Z��Xss=9@;Symfony/Component/Security/Core/Exception/LogoutException.phpnu�[���PK��Z
�04}}GC;Symfony/Component/Security/Core/Exception/UsernameNotFoundException.phpnu�[���PK��Z#��q44Q
I;Symfony/Component/Security/Core/Exception/InsufficientAuthenticationException.phpnu�[���PK��Z�5]���I�L;Symfony/Component/Security/Core/Exception/SessionUnavailableException.phpnu�[���PK��ZD��9��D�P;Symfony/Component/Security/Core/Exception/TokenNotFoundException.phpnu�[���PK��Zh�c��B�S;Symfony/Component/Security/Core/Exception/CookieTheftException.phpnu�[���PK��Z��A���@/W;Symfony/Component/Security/Core/Exception/ExceptionInterface.phpnu�[���PK��ZqUSą�CYY;Symfony/Component/Security/Core/Exception/AccessDeniedException.phpnu�[���PK��Z�'��EQ\;Symfony/Component/Security/Core/Exception/AuthenticationException.phpnu�[���PK��Z�
	��>�c;Symfony/Component/Security/Core/Exception/RuntimeException.phpnu�[���PK��Z@�	���G0f;Symfony/Component/Security/Core/Exception/ProviderNotFoundException.phpnu�[���PK��Z�ĸ���X�i;Symfony/Component/Security/Core/Exception/AuthenticationCredentialsNotFoundException.phpnu�[���PK��Z:���AADm;Symfony/Component/Security/Core/Exception/AccountStatusException.phpnu�[���PK��Z7w�-��L�r;Symfony/Component/Security/Core/Exception/AuthenticationServiceException.phpnu�[���PK��ZxB��EIv;Symfony/Component/Security/Core/Exception/AccountExpiredException.phpnu�[���PK��Z�և��?Ny;Symfony/Component/Security/Core/Exception/DisabledException.phpnu�[���PK��Ze���CA|;Symfony/Component/Security/Core/Exception/NonceExpiredException.phpnu�[���PK��Zʝ�9Fo;Symfony/Component/Security/Core/Exception/InvalidArgumentException.phpnu�[���PK��Z�O���G�;Symfony/Component/Security/Core/Exception/InvalidCsrfTokenException.phpnu�[���PK��Z�Õ�

5�;Symfony/Component/Security/Core/Util/SecureRandom.phpnu�[���PK��ZU��a��4e�;Symfony/Component/Security/Core/Util/StringUtils.phpnu�[���PK��Z��T�,,3��;Symfony/Component/Security/Core/Util/ClassUtils.phpnu�[���PK��Z�	���>8�;Symfony/Component/Security/Core/Util/SecureRandomInterface.phpnu�[���PK��Z�m2���G1�;Symfony/Component/Security/Core/Authorization/AccessDecisionManager.phpnu�[���PK��Z�З~��Ak�;Symfony/Component/Security/Core/Authorization/Voter/RoleVoter.phpnu�[���PK��Z~f�J��;Symfony/Component/Security/Core/Authorization/Voter/RoleHierarchyVoter.phpnu�[���PK��Z��`c��G]�;Symfony/Component/Security/Core/Authorization/Voter/ExpressionVoter.phpnu�[���PK��Z�X,mJ��;Symfony/Component/Security/Core/Authorization/Voter/AuthenticatedVoter.phpnu�[���PK��Z�>��F*�;Symfony/Component/Security/Core/Authorization/Voter/VoterInterface.phpnu�[���PK��Z�:22PR�;Symfony/Component/Security/Core/Authorization/AccessDecisionManagerInterface.phpnu�[���PK��Zѵ^��D��;Symfony/Component/Security/Core/Authorization/ExpressionLanguage.phpnu�[���PK��Z����=��;Symfony/Component/Security/Core/User/UserCheckerInterface.phpnu�[���PK��Z��^ 
 
:�;Symfony/Component/Security/Core/User/ChainUserProvider.phpnu�[���PK��ZD�$..4r<Symfony/Component/Security/Core/User/UserChecker.phpnu�[���PK��Z��6bYY>
<Symfony/Component/Security/Core/User/AdvancedUserInterface.phpnu�[���PK��Z����	�	6�<Symfony/Component/Security/Core/User/UserInterface.phpnu�[���PK��Z/!�=�"<Symfony/Component/Security/Core/User/InMemoryUserProvider.phpnu�[���PK��Z��//;]/<Symfony/Component/Security/Core/User/EquatableInterface.phpnu�[���PK��Zs�v�W	W	>�3<Symfony/Component/Security/Core/User/UserProviderInterface.phpnu�[���PK��Z��1G	G	-�=<Symfony/Component/Security/Core/User/User.phpnu�[���PK��Z'�za!!3`G<Symfony/Component/Security/Core/SecurityContext.phpnu�[���PK��Z��l�8�R<Symfony/Component/Security/Core/AuthenticationEvents.phpnu�[���PK��Zx��$ccPOW<Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.phpnu�[���PK��Z¬>
##R2f<Symfony/Component/Security/Core/Authentication/SimplePreAuthenticatorInterface.phpnu�[���PK��Z��W��O�h<Symfony/Component/Security/Core/Authentication/SimpleAuthenticatorInterface.phpnu�[���PK��Z>,�vvX%l<Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.phpnu�[���PK��Z�U#s<Symfony/Component/Security/Core/Authentication/Provider/DaoAuthenticationProvider.phpnu�[���PK��Z�b�yyVƂ<Symfony/Component/Security/Core/Authentication/Provider/UserAuthenticationProvider.phpnu�[���PK��Z�J�A��\ŗ<Symfony/Component/Security/Core/Authentication/Provider/RememberMeAuthenticationProvider.phpnu�[���PK��Z��X���[$�<Symfony/Component/Security/Core/Authentication/Provider/AnonymousAuthenticationProvider.phpnu�[���PK��Z��a�""[b�<Symfony/Component/Security/Core/Authentication/Provider/AuthenticationProviderInterface.phpnu�[���PK��Zun\�
�
b�<Symfony/Component/Security/Core/Authentication/Provider/PreAuthenticatedAuthenticationProvider.phpnu�[���PK��Z��r3WWW��<Symfony/Component/Security/Core/Authentication/AuthenticationTrustResolverInterface.phpnu�[���PK��Z�Zvm��St�<Symfony/Component/Security/Core/Authentication/RememberMe/InMemoryTokenProvider.phpnu�[���PK��Z���QZZV��<Symfony/Component/Security/Core/Authentication/RememberMe/PersistentTokenInterface.phpnu�[���PK��Z
�TO��Mx�<Symfony/Component/Security/Core/Authentication/RememberMe/PersistentToken.phpnu�[���PK��Z
C�f��T��<Symfony/Component/Security/Core/Authentication/RememberMe/TokenProviderInterface.phpnu�[���PK��ZJ-W;::S��<Symfony/Component/Security/Core/Authentication/SimpleFormAuthenticatorInterface.phpnu�[���PK��Z:�6��Nv�<Symfony/Component/Security/Core/Authentication/AuthenticationTrustResolver.phpnu�[���PK��Zf�	�Q��<Symfony/Component/Security/Core/Authentication/AuthenticationManagerInterface.phpnu�[���PK��Zγ�__N�<Symfony/Component/Security/Core/Authentication/Token/PreAuthenticatedToken.phpnu�[���PK��Z��4��F��<Symfony/Component/Security/Core/Authentication/Token/AbstractToken.phpnu�[���PK��Z�tC��G)=Symfony/Component/Security/Core/Authentication/Token/TokenInterface.phpnu�[���PK��Z{Z�--G�=Symfony/Component/Security/Core/Authentication/Token/AnonymousToken.phpnu�[���PK��Z�6��`
`
N&=Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.phpnu�[���PK��Z��w�	�	H*=Symfony/Component/Security/Core/Authentication/Token/RememberMeToken.phpnu�[���PK��Zm�|JJK�3=Symfony/Component/Security/Core/Resources/translations/security.sr_Cyrl.xlfnu�[���PK��Z&MЎ�
�
F�C=Symfony/Component/Security/Core/Resources/translations/security.es.xlfnu�[���PK��ZM-�@F�Q=Symfony/Component/Security/Core/Resources/translations/security.fa.xlfnu�[���PK��Zd�e��
�
F�a=Symfony/Component/Security/Core/Resources/translations/security.fr.xlfnu�[���PK��Z�)�
�
F�o=Symfony/Component/Security/Core/Resources/translations/security.ro.xlfnu�[���PK��Z�y��
�
F�}=Symfony/Component/Security/Core/Resources/translations/security.gl.xlfnu�[���PK��Z��u^
^
F�=Symfony/Component/Security/Core/Resources/translations/security.sv.xlfnu�[���PK��Z���ţ
�
F��=Symfony/Component/Security/Core/Resources/translations/security.ca.xlfnu�[���PK��Zo'�N�
�
Fϧ=Symfony/Component/Security/Core/Resources/translations/security.de.xlfnu�[���PK��Z.W�
�
F
�=Symfony/Component/Security/Core/Resources/translations/security.no.xlfnu�[���PK��Z��ق
�
F�=Symfony/Component/Security/Core/Resources/translations/security.sk.xlfnu�[���PK��Z�w=���F�=Symfony/Component/Security/Core/Resources/translations/security.ru.xlfnu�[���PK��ZUɎd
d
F3�=Symfony/Component/Security/Core/Resources/translations/security.sl.xlfnu�[���PK��Z���
�
F
�=Symfony/Component/Security/Core/Resources/translations/security.lb.xlfnu�[���PK��Z�#@�y
y
IW�=Symfony/Component/Security/Core/Resources/translations/security.pt_PT.xlfnu�[���PK��ZYW��g
g
KI>Symfony/Component/Security/Core/Resources/translations/security.sr_Latn.xlfnu�[���PK��Z�=���
�
I+>Symfony/Component/Security/Core/Resources/translations/security.pt_BR.xlfnu�[���PK��Z(���
�
F&(>Symfony/Component/Security/Core/Resources/translations/security.cs.xlfnu�[���PK��ZO�
�
F'6>Symfony/Component/Security/Core/Resources/translations/security.it.xlfnu�[���PK��ZTk�f��F+D>Symfony/Component/Security/Core/Resources/translations/security.ar.xlfnu�[���PK��Z��|H�
�
F[S>Symfony/Component/Security/Core/Resources/translations/security.hu.xlfnu�[���PK��Z�p�U�
�
Fa>Symfony/Component/Security/Core/Resources/translations/security.nl.xlfnu�[���PK��Z'���{
{
F�o>Symfony/Component/Security/Core/Resources/translations/security.tr.xlfnu�[���PK��ZU����F�}>Symfony/Component/Security/Core/Resources/translations/security.el.xlfnu�[���PK��Z.�X:
:
F�>Symfony/Component/Security/Core/Resources/translations/security.en.xlfnu�[���PK��Z�d
�
�
F��>Symfony/Component/Security/Core/Resources/translations/security.pl.xlfnu�[���PK��Z5�˙��F��>Symfony/Component/Security/Core/Resources/translations/security.ua.xlfnu�[���PK��Zz��
J
J
F��>Symfony/Component/Security/Core/Resources/translations/security.da.xlfnu�[���PK��Z��Eh��Dj�>Symfony/Component/Security/Core/Event/AuthenticationFailureEvent.phpnu�[���PK��Z+\�
//=��>Symfony/Component/Security/Core/Event/AuthenticationEvent.phpnu�[���PK��Z���(SSA,�>Symfony/Component/Security/Resources/translations/security.bg.xlfnu�[���PK��Zm�|JJF��>Symfony/Component/Security/Resources/translations/security.sr_Cyrl.xlfnu�[���PK��Z&MЎ�
�
A��>Symfony/Component/Security/Resources/translations/security.es.xlfnu�[���PK��ZM-�@A�>Symfony/Component/Security/Resources/translations/security.fa.xlfnu�[���PK��Z���An?Symfony/Component/Security/Resources/translations/security.vi.xlfnu�[���PK��Zd�e��
�
A�?Symfony/Component/Security/Resources/translations/security.fr.xlfnu�[���PK��Z�)�
�
A.)?Symfony/Component/Security/Resources/translations/security.ro.xlfnu�[���PK��Z�y��
�
A,7?Symfony/Component/Security/Resources/translations/security.gl.xlfnu�[���PK��Z��u^
^
A<E?Symfony/Component/Security/Resources/translations/security.sv.xlfnu�[���PK��Z���ţ
�
AS?Symfony/Component/Security/Resources/translations/security.ca.xlfnu�[���PK��Zo'�N�
�
Aa?Symfony/Component/Security/Resources/translations/security.de.xlfnu�[���PK��Z����
�
AXo?Symfony/Component/Security/Resources/translations/security.no.xlfnu�[���PK��Z�R�wD
D
AN}?Symfony/Component/Security/Resources/translations/security.id.xlfnu�[���PK��Z��ق
�
A�?Symfony/Component/Security/Resources/translations/security.sk.xlfnu�[���PK��Z�w=���A��?Symfony/Component/Security/Resources/translations/security.ru.xlfnu�[���PK��ZUɎd
d
A$�?Symfony/Component/Security/Resources/translations/security.sl.xlfnu�[���PK��Z]��W
W
A��?Symfony/Component/Security/Resources/translations/security.hr.xlfnu�[���PK��Z���
�
A��?Symfony/Component/Security/Resources/translations/security.lb.xlfnu�[���PK��Z�#@�y
y
D�?Symfony/Component/Security/Resources/translations/security.pt_PT.xlfnu�[���PK��ZYW��g
g
F��?Symfony/Component/Security/Resources/translations/security.sr_Latn.xlfnu�[���PK��Z���Y�
�
D��?Symfony/Component/Security/Resources/translations/security.pt_BR.xlfnu�[���PK��Z(���
�
A�?Symfony/Component/Security/Resources/translations/security.cs.xlfnu�[���PK��ZO�
�
A�
@Symfony/Component/Security/Resources/translations/security.it.xlfnu�[���PK��ZTk�f��A�@Symfony/Component/Security/Resources/translations/security.ar.xlfnu�[���PK��Z��|H�
�
A�'@Symfony/Component/Security/Resources/translations/security.hu.xlfnu�[���PK��Z�p�U�
�
A6@Symfony/Component/Security/Resources/translations/security.nl.xlfnu�[���PK��Z'���{
{
AID@Symfony/Component/Security/Resources/translations/security.tr.xlfnu�[���PK��ZU����A5R@Symfony/Component/Security/Resources/translations/security.el.xlfnu�[���PK��Z��Dt��D�b@Symfony/Component/Security/Resources/translations/security.zh_CN.xlfnu�[���PK��Z.�X:
:
A�o@Symfony/Component/Security/Resources/translations/security.en.xlfnu�[���PK��Z�d
�
�
A�}@Symfony/Component/Security/Resources/translations/security.pl.xlfnu�[���PK��Z�f488A��@Symfony/Component/Security/Resources/translations/security.ja.xlfnu�[���PK��Z5�˙��AC�@Symfony/Component/Security/Resources/translations/security.ua.xlfnu�[���PK��Z��J
J
A7�@Symfony/Component/Security/Resources/translations/security.da.xlfnu�[���PK��Z�@V��@�@Symfony/Component/Validator/ConstraintViolationListInterface.phpnu�[���PK��Zz��911::�@Symfony/Component/Validator/ObjectInitializerInterface.phpnu�[���PK��Z,�'��<��@Symfony/Component/Validator/ConstraintValidatorInterface.phpnu�[���PK��ZK��}}1��@Symfony/Component/Validator/DefaultTranslator.phpnu�[���PK��Z�����3��@Symfony/Component/Validator/ConstraintViolation.phpnu�[���PK��ZS�b'b'0��@Symfony/Component/Validator/ValidatorBuilder.phpnu�[���PK��Z�S�UU>�ASymfony/Component/Validator/GroupSequenceProviderInterface.phpnu�[���PK��Z�d�)xASymfony/Component/Validator/Validator.phpnu�[���PK��Z��&{{9�2ASymfony/Component/Validator/ValidatorBuilderInterface.phpnu�[���PK��Zo��SS*�HASymfony/Component/Validator/autoloader.phpnu�[���PK��Z����C0C09{JASymfony/Component/Validator/ExecutionContextInterface.phpnu�[���PK��Z}`���9'{ASymfony/Component/Validator/PropertyMetadataInterface.phpnu�[���PK��Z�޽/!/!0z�ASymfony/Component/Validator/ExecutionContext.phpnu�[���PK��Z+s���:	�ASymfony/Component/Validator/ConstraintValidatorFactory.phpnu�[���PK��Z�Sq�KK1l�ASymfony/Component/Validator/MetadataInterface.phpnu�[���PK��Z�R'<�ASymfony/Component/Validator/ConstraintViolationInterface.phpnu�[���PK��ZƭW��*��ASymfony/Component/Validator/Constraint.phpnu�[���PK��Z|����6l�ASymfony/Component/Validator/Mapping/GetterMetadata.phpnu�[���PK��Zr
���8��ASymfony/Component/Validator/Mapping/PropertyMetadata.phpnu�[���PK��Z�t�././5��ASymfony/Component/Validator/Mapping/ClassMetadata.phpnu�[���PK��Z��!"	"	7wBSymfony/Component/Validator/Mapping/ElementMetadata.phpnu�[���PK��Z�/�;aa6)BSymfony/Component/Validator/Mapping/MemberMetadata.phpnu�[���PK��Z+�d%%<�@BSymfony/Component/Validator/Mapping/Cache/CacheInterface.phpnu�[���PK��Z����6XEBSymfony/Component/Validator/Mapping/Cache/ApcCache.phpnu�[���PK��Zd#[N��<IJBSymfony/Component/Validator/Mapping/ClassMetadataFactory.phpnu�[���PK��Z��ʚ��9�WBSymfony/Component/Validator/Mapping/Loader/FileLoader.phpnu�[���PK��Zk�G+��=�[BSymfony/Component/Validator/Mapping/Loader/AbstractLoader.phpnu�[���PK��ZRᠯ��=dBSymfony/Component/Validator/Mapping/Loader/XmlFilesLoader.phpnu�[���PK��Z�?��>gBSymfony/Component/Validator/Mapping/Loader/YamlFilesLoader.phpnu�[���PK��Z�����:jBSymfony/Component/Validator/Mapping/Loader/LoaderChain.phpnu�[���PK��ZT�b��AAqBSymfony/Component/Validator/Mapping/Loader/StaticMethodLoader.phpnu�[���PK��Z�>�??>�wBSymfony/Component/Validator/Mapping/Loader/LoaderInterface.phpnu�[���PK��Z���*��:8zBSymfony/Component/Validator/Mapping/Loader/FilesLoader.phpnu�[���PK��ZTO��--c)�BSymfony/Component/Validator/Mapping/Loader/schema/dic/constraint-mapping/constraint-mapping-1.0.xsdnu�[���PK��Z;Q�F11<�BSymfony/Component/Validator/Mapping/Loader/XmlFileLoader.phpnu�[���PK��Z	lw#QQ?��BSymfony/Component/Validator/Mapping/Loader/AnnotationLoader.phpnu�[���PK��Z'��pkk=F�BSymfony/Component/Validator/Mapping/Loader/YamlFileLoader.phpnu�[���PK��Z�۔��@�BSymfony/Component/Validator/Mapping/BlackholeMetadataFactory.phpnu�[���PK��Z�L8��
�
:$�BSymfony/Component/Validator/ValidationVisitorInterface.phpnu�[���PK��ZQ���VV:j�BSymfony/Component/Validator/Exception/MappingException.phpnu�[���PK��Z��y��@*�BSymfony/Component/Validator/Exception/BadMethodCallException.phpnu�[���PK��ZL�ЉRRA��BSymfony/Component/Validator/Exception/InvalidOptionsException.phpnu�[���PK��Zk1+WW<V�BSymfony/Component/Validator/Exception/ValidatorException.phpnu�[���PK��Z�b�<<A�BSymfony/Component/Validator/Exception/UnexpectedTypeException.phpnu�[���PK��Z�1�"ccG��BSymfony/Component/Validator/Exception/ConstraintDefinitionException.phpnu�[���PK��Z�T����<��BSymfony/Component/Validator/Exception/ExceptionInterface.phpnu�[���PK��Zz����:��BSymfony/Component/Validator/Exception/RuntimeException.phpnu�[���PK��Z��x��A�BSymfony/Component/Validator/Exception/NoSuchMetadataException.phpnu�[���PK��Zu��RRA�BSymfony/Component/Validator/Exception/MissingOptionsException.phpnu�[���PK��ZM��#^^B�BSymfony/Component/Validator/Exception/GroupDefinitionException.phpnu�[���PK��Z�\��B��BSymfony/Component/Validator/Exception/InvalidArgumentException.phpnu�[���PK��Z�U�<<3!�BSymfony/Component/Validator/ClassBasedInterface.phpnu�[���PK��Z;5t��7��BSymfony/Component/Validator/ConstraintViolationList.phpnu�[���PK��ZAbI̲�1�CSymfony/Component/Validator/ValidationVisitor.phpnu�[���PK��Zbh��B�$CSymfony/Component/Validator/PropertyMetadataContainerInterface.phpnu�[���PK��ZY����8*CSymfony/Component/Validator/MetadataFactoryInterface.phpnu�[���PK��ZD#��?�?DX.CSymfony/Component/Validator/Resources/translations/validators.en.xlfnu�[���PK��Z-���uCuCDgnCSymfony/Component/Validator/Resources/translations/validators.sk.xlfnu�[���PK��Z�τ}K}KDP�CSymfony/Component/Validator/Resources/translations/validators.uk.xlfnu�[���PK��Z��-�1�1DA�CSymfony/Component/Validator/Resources/translations/validators.cy.xlfnu�[���PK��Z�m�w�B�BD�0DSymfony/Component/Validator/Resources/translations/validators.pl.xlfnu�[���PK��Z@T�\44D�sDSymfony/Component/Validator/Resources/translations/validators.af.xlfnu�[���PK��Z�b�@�@DB�DSymfony/Component/Validator/Resources/translations/validators.pt.xlfnu�[���PK��Ze]߭A�AII�DSymfony/Component/Validator/Resources/translations/validators.sr_Cyrl.xlfnu�[���PK��Z�a�2�2Do+ESymfony/Component/Validator/Resources/translations/validators.fi.xlfnu�[���PK��Z��"}2A2AD�^ESymfony/Component/Validator/Resources/translations/validators.es.xlfnu�[���PK��Zs�E#�A�AD6�ESymfony/Component/Validator/Resources/translations/validators.de.xlfnu�[���PK��Z=^��::D��ESymfony/Component/Validator/Resources/translations/validators.it.xlfnu�[���PK��Z	���AADFSymfony/Component/Validator/Resources/translations/validators.ca.xlfnu�[���PK��ZD��#"#"Dx^FSymfony/Component/Validator/Resources/translations/validators.mn.xlfnu�[���PK��Z��-tZMZMD�FSymfony/Component/Validator/Resources/translations/validators.ru.xlfnu�[���PK��Z<��bKKD��FSymfony/Component/Validator/Resources/translations/validators.bg.xlfnu�[���PK��Z����A�ADoGSymfony/Component/Validator/Resources/translations/validators.ro.xlfnu�[���PK��Z�ժN@@D�\GSymfony/Component/Validator/Resources/translations/validators.nl.xlfnu�[���PK��Z�%�N�=�=DW�GSymfony/Component/Validator/Resources/translations/validators.et.xlfnu�[���PK��Z
��GGDs�GSymfony/Component/Validator/Resources/translations/validators.fa.xlfnu�[���PK��Z-�L>L>D�"HSymfony/Component/Validator/Resources/translations/validators.id.xlfnu�[���PK��Z˺�Q1Q1D�aHSymfony/Component/Validator/Resources/translations/validators.tr.xlfnu�[���PK��Z	�)�B�BDp�HSymfony/Component/Validator/Resources/translations/validators.cs.xlfnu�[���PK��Z�6��%=%=G��HSymfony/Component/Validator/Resources/translations/validators.zh_CN.xlfnu�[���PK��Z�PhBhBDAISymfony/Component/Validator/Resources/translations/validators.lt.xlfnu�[���PK��Z���+BBDWISymfony/Component/Validator/Resources/translations/validators.fr.xlfnu�[���PK��Z(��=A=AD��ISymfony/Component/Validator/Resources/translations/validators.gl.xlfnu�[���PK��Z���wX@X@DN�ISymfony/Component/Validator/Resources/translations/validators.hr.xlfnu�[���PK��ZY�.3�5�5DJSymfony/Component/Validator/Resources/translations/validators.sq.xlfnu�[���PK��Z(�eeD3RJSymfony/Component/Validator/Resources/translations/validators.nb.xlfnu�[���PK��Z���t�A�ADrJSymfony/Component/Validator/Resources/translations/validators.eu.xlfnu�[���PK��Z1ar�==Ga�JSymfony/Component/Validator/Resources/translations/validators.zh_TW.xlfnu�[���PK��Z�T�л@�@G��JSymfony/Component/Validator/Resources/translations/validators.pt_BR.xlfnu�[���PK��Z���1�1D3KSymfony/Component/Validator/Resources/translations/validators.no.xlfnu�[���PK��Z��n�C�CDWeKSymfony/Component/Validator/Resources/translations/validators.sl.xlfnu�[���PK��Zq�b�?�?D��KSymfony/Component/Validator/Resources/translations/validators.lb.xlfnu�[���PK��Z93XaoAoAD�KSymfony/Component/Validator/Resources/translations/validators.hu.xlfnu�[���PK��Z����M�MD,LSymfony/Component/Validator/Resources/translations/validators.el.xlfnu�[���PK��Z��9>�5�5D@zLSymfony/Component/Validator/Resources/translations/validators.da.xlfnu�[���PK��Z���AAD��LSymfony/Component/Validator/Resources/translations/validators.ja.xlfnu�[���PK��Z�Q>�?�?D �LSymfony/Component/Validator/Resources/translations/validators.sv.xlfnu�[���PK��Zv_��w,w,D2MSymfony/Component/Validator/Resources/translations/validators.hy.xlfnu�[���PK��Z����O�OD_MSymfony/Component/Validator/Resources/translations/validators.ar.xlfnu�[���PK��Z�1�^�4�4I=�MSymfony/Component/Validator/Resources/translations/validators.sr_Latn.xlfnu�[���PK��Z@T'%�B�BDt�MSymfony/Component/Validator/Resources/translations/validators.vi.xlfnu�[���PK��Z��tý5�5D�'NSymfony/Component/Validator/Resources/translations/validators.he.xlfnu�[���PK��Z��D��<�]NSymfony/Component/Validator/Constraints/NotNullValidator.phpnu�[���PK��ZD~�SS2"aNSymfony/Component/Validator/Constraints/Choice.phpnu�[���PK��Z�~%ɋ�1�eNSymfony/Component/Validator/Constraints/Valid.phpnu�[���PK��Z�+��6�iNSymfony/Component/Validator/Constraints/NotEqualTo.phpnu�[���PK��Zm�Լ\\ClNSymfony/Component/Validator/Constraints/NotIdenticalToValidator.phpnu�[���PK��ZĿ:�KK6�nNSymfony/Component/Validator/Constraints/Expression.phpnu�[���PK��Z�خ
zz?�sNSymfony/Component/Validator/Constraints/Collection/Optional.phpnu�[���PK��Z\,y�zz?�vNSymfony/Component/Validator/Constraints/Collection/Required.phpnu�[���PK��Z
��n��?kyNSymfony/Component/Validator/Constraints/CollectionValidator.phpnu�[���PK��Z��y:g�NSymfony/Component/Validator/Constraints/BlankValidator.phpnu�[���PK��Z�+����0؅NSymfony/Component/Validator/Constraints/Iban.phpnu�[���PK��Z����	�	=�NSymfony/Component/Validator/Constraints/CallbackValidator.phpnu�[���PK��Z�}�&&25�NSymfony/Component/Validator/Constraints/Length.phpnu�[���PK��Z�b�=nn9��NSymfony/Component/Validator/Constraints/IsbnValidator.phpnu�[���PK��Z�<W���:��NSymfony/Component/Validator/Constraints/RegexValidator.phpnu�[���PK��Z^r��

4��NSymfony/Component/Validator/Constraints/Language.phpnu�[���PK��Z���,,0e�NSymfony/Component/Validator/Constraints/Isbn.phpnu�[���PK��Z�EW^��<�NSymfony/Component/Validator/Constraints/CountryValidator.phpnu�[���PK��Zzet�	�	?\�NSymfony/Component/Validator/Constraints/ExpressionValidator.phpnu�[���PK��Z�	�00/��NSymfony/Component/Validator/Constraints/Url.phpnu�[���PK��Z�V`���9"�NSymfony/Component/Validator/Constraints/IbanValidator.phpnu�[���PK��Z��vbb@6�NSymfony/Component/Validator/Constraints/GreaterThanValidator.phpnu�[���PK��ZS탟0�NSymfony/Component/Validator/Constraints/Date.phpnu�[���PK��Z�|4XX8j�NSymfony/Component/Validator/Constraints/UrlValidator.phpnu�[���PK��Zw���3*�NSymfony/Component/Validator/Constraints/NotNull.phpnu�[���PK��ZS�n���0��NSymfony/Component/Validator/Constraints/Null.phpnu�[���PK��Z�o�o��:��NSymfony/Component/Validator/Constraints/RangeValidator.phpnu�[���PK��Z�

4��NSymfony/Component/Validator/Constraints/Currency.phpnu�[���PK��Zrs+���4O�NSymfony/Component/Validator/Constraints/Optional.phpnu�[���PK��Z����449G�NSymfony/Component/Validator/Constraints/IssnValidator.phpnu�[���PK��Z�qp""0�NSymfony/Component/Validator/Constraints/File.phpnu�[���PK��Z5�ʟ��9f�NSymfony/Component/Validator/Constraints/DateValidator.phpnu�[���PK��Z0@���9�OSymfony/Component/Validator/Constraints/NullValidator.phpnu�[���PK��Z�>
i//5�OSymfony/Component/Validator/Constraints/Existence.phpnu�[���PK��ZtUה�4k	OSymfony/Component/Validator/Constraints/Required.phpnu�[���PK��Zm��\\>cOSymfony/Component/Validator/Constraints/AbstractComparison.phpnu�[���PK��Zc��y

4-OSymfony/Component/Validator/Constraints/DateTime.phpnu�[���PK��Zl˘��
�
7�OSymfony/Component/Validator/Constraints/IpValidator.phpnu�[���PK��Z�\\=�OSymfony/Component/Validator/Constraints/LessThanValidator.phpnu�[���PK��Z�U�4Y OSymfony/Component/Validator/Constraints/NotBlank.phpnu�[���PK��Z<8�S��:�"OSymfony/Component/Validator/Constraints/ImageValidator.phpnu�[���PK��Z��Lֻ�6�9OSymfony/Component/Validator/Constraints/CardScheme.phpnu�[���PK��Z��"��?�<OSymfony/Component/Validator/Constraints/CardSchemeValidator.phpnu�[���PK��ZN3�0/MOSymfony/Component/Validator/Constraints/Type.phpnu�[���PK��Z@vqq9�POSymfony/Component/Validator/Constraints/FileValidator.phpnu�[���PK��Z�'����1oiOSymfony/Component/Validator/Constraints/Count.phpnu�[���PK��Z�̢�VV@�oOSymfony/Component/Validator/Constraints/IdenticalToValidator.phpnu�[���PK��Zd�X�BB0~rOSymfony/Component/Validator/Constraints/Issn.phpnu�[���PK��Z�ଏ�A uOSymfony/Component/Validator/Constraints/GroupSequenceProvider.phpnu�[���PK��Z��}a��7 wOSymfony/Component/Validator/Constraints/GreaterThan.phpnu�[���PK��Z�Ǧ��3xyOSymfony/Component/Validator/Constraints/EqualTo.phpnu�[���PK��Zb+��9�{OSymfony/Component/Validator/Constraints/LuhnValidator.phpnu�[���PK��Z�ٜ?��0ŃOSymfony/Component/Validator/Constraints/True.phpnu�[���PK��Z?����G"�OSymfony/Component/Validator/Constraints/AbstractComparisonValidator.phpnu�[���PK��Z�̋	�	1y�OSymfony/Component/Validator/Constraints/Regex.phpnu�[���PK��Z��BB1e�OSymfony/Component/Validator/Constraints/Range.phpnu�[���PK��Z[�A���;�OSymfony/Component/Validator/Constraints/LessThanOrEqual.phpnu�[���PK��Zq;O3q�OSymfony/Component/Validator/Constraints/Country.phpnu�[���PK��Z5����:ܢOSymfony/Component/Validator/Constraints/EmailValidator.phpnu�[���PK��Z�`�v��;/�OSymfony/Component/Validator/Constraints/LocaleValidator.phpnu�[���PK��Z'㔘7��OSymfony/Component/Validator/Constraints/IdenticalTo.phpnu�[���PK��Z��/�OSymfony/Component/Validator/Constraints/All.phpnu�[���PK��Z{���UU?w�OSymfony/Component/Validator/Constraints/NotEqualToValidator.phpnu�[���PK��Z�ɑ559;�OSymfony/Component/Validator/Constraints/TrueValidator.phpnu�[���PK��Z�(.wwGٿOSymfony/Component/Validator/Constraints/GreaterThanOrEqualValidator.phpnu�[���PK��Z���(��9��OSymfony/Component/Validator/Constraints/TimeValidator.phpnu�[���PK��Z�Fn���8�OSymfony/Component/Validator/Constraints/AllValidator.phpnu�[���PK��Z�c����.�OSymfony/Component/Validator/Constraints/Ip.phpnu�[���PK��ZHð�2R�OSymfony/Component/Validator/Constraints/Locale.phpnu�[���PK��ZQ��=��OSymfony/Component/Validator/Constraints/LanguageValidator.phpnu�[���PK��ZaHβ;+�OSymfony/Component/Validator/Constraints/ChoiceValidator.phpnu�[���PK��Z�{HH1�OSymfony/Component/Validator/Constraints/Email.phpnu�[���PK��Zx�.`ss4��OSymfony/Component/Validator/Constraints/Callback.phpnu�[���PK��Z�����=��OSymfony/Component/Validator/Constraints/DateTimeValidator.phpnu�[���PK��Z�&����0�OSymfony/Component/Validator/Constraints/Luhn.phpnu�[���PK��Z�F���9<�OSymfony/Component/Validator/Constraints/TypeValidator.phpnu�[���PK��Z���&��=1�OSymfony/Component/Validator/Constraints/NotBlankValidator.phpnu�[���PK��Ze8�B�
�
6�PSymfony/Component/Validator/Constraints/Collection.phpnu�[���PK��ZI7U���1�PSymfony/Component/Validator/Constraints/False.phpnu�[���PK��Z�Q�>MPSymfony/Component/Validator/Constraints/GreaterThanOrEqual.phpnu�[���PK��Z��l��1�PSymfony/Component/Validator/Constraints/Blank.phpnu�[���PK��Z�CG^LL<PSymfony/Component/Validator/Constraints/EqualToValidator.phpnu�[���PK��Z^�T:�PSymfony/Component/Validator/Constraints/FalseValidator.phpnu�[���PK��ZO��qqD^PSymfony/Component/Validator/Constraints/LessThanOrEqualValidator.phpnu�[���PK��Z����vv9CPSymfony/Component/Validator/Constraints/GroupSequence.phpnu�[���PK��Z_��1"PSymfony/Component/Validator/Constraints/Image.phpnu�[���PK��Z��F;��;''PSymfony/Component/Validator/Constraints/LengthValidator.phpnu�[���PK��Z!xHH:e0PSymfony/Component/Validator/Constraints/CountValidator.phpnu�[���PK��Z��708PSymfony/Component/Validator/Constraints/Time.phpnu�[���PK��ZN�H���4y:PSymfony/Component/Validator/Constraints/LessThan.phpnu�[���PK��Ze��:�<PSymfony/Component/Validator/Constraints/NotIdenticalTo.phpnu�[���PK��Z�Z�=D?PSymfony/Component/Validator/Constraints/CurrencyValidator.phpnu�[���PK��ZGk	��3�DPSymfony/Component/Validator/ConstraintValidator.phpnu�[���PK��ZK�OC�GPSymfony/Component/Validator/ConstraintValidatorFactoryInterface.phpnu�[���PK��Z�8Wc��?KKPSymfony/Component/Validator/GlobalExecutionContextInterface.phpnu�[���PK��Zxf�JJ*KSPSymfony/Component/Validator/Validation.phpnu�[���PK��Zn�r�
�
2�WPSymfony/Component/Validator/ValidatorInterface.phpnu�[���PK��ZC���9MfPSymfony/Component/Templating/StreamingEngineInterface.phpnu�[���PK��Z<,��}}2�jPSymfony/Component/Templating/TemplateReference.phpnu�[���PK��Z�m�tTT+�rPSymfony/Component/Templating/autoloader.phpnu�[���PK��Z����;EtPSymfony/Component/Templating/TemplateReferenceInterface.phpnu�[���PK��ZJ� ���2k|PSymfony/Component/Templating/DebuggerInterface.phpnu�[���PK��ZDZ�_++<�PSymfony/Component/Templating/TemplateNameParserInterface.phpnu�[���PK��Z���3�PSymfony/Component/Templating/TemplateNameParser.phpnu�[���PK��Z�����0Y�PSymfony/Component/Templating/EngineInterface.phpnu�[���PK��Z��b�NN2n�PSymfony/Component/Templating/Asset/PathPackage.phpnu�[���PK��Z���TT1�PSymfony/Component/Templating/Asset/UrlPackage.phpnu�[���PK��Z�o##.ӞPSymfony/Component/Templating/Asset/Package.phpnu�[���PK��Zp�vj��7T�PSymfony/Component/Templating/Asset/PackageInterface.phpnu�[���PK��Z�'��4��PSymfony/Component/Templating/Storage/FileStorage.phpnu�[���PK��Z(�"w��6��PSymfony/Component/Templating/Storage/StringStorage.phpnu�[���PK��Zπ\�0��PSymfony/Component/Templating/Storage/Storage.phpnu�[���PK��Z��>3�PSymfony/Component/Templating/Loader/ChainLoader.phpnu�[���PK��Z�b��8��PSymfony/Component/Templating/Loader/FilesystemLoader.phpnu�[���PK��Z�g((.��PSymfony/Component/Templating/Loader/Loader.phpnu�[���PK��Zy�A�nn3o�PSymfony/Component/Templating/Loader/CacheLoader.phpnu�[���PK��ZI<�D��7@�PSymfony/Component/Templating/Loader/LoaderInterface.phpnu�[���PK��Z+�r�mm3|�PSymfony/Component/Templating/Helper/SlotsHelper.phpnu�[���PK��ZV¤՟�4L�PSymfony/Component/Templating/Helper/AssetsHelper.phpnu�[���PK��ZԷ����7O�PSymfony/Component/Templating/Helper/HelperInterface.phpnu�[���PK��Z����



8U�PSymfony/Component/Templating/Helper/CoreAssetsHelper.phpnu�[���PK��Z�NO��.�QSymfony/Component/Templating/Helper/Helper.phpnu�[���PK��Z_6H1%QSymfony/Component/Templating/DelegatingEngine.phpnu�[���PK��Z?w
y=y=*�QSymfony/Component/Templating/PhpEngine.phpnu�[���PK��Z6�H	��$lTQSymfony/Component/Yaml/Unescaper.phpnu�[���PK��Z�8�n�	�	!_fQSymfony/Component/Yaml/Dumper.phpnu�[���PK��Z�bNN%DpQSymfony/Component/Yaml/autoloader.phpnu�[���PK��Z��X��[�[!�qQSymfony/Component/Yaml/Parser.phpnu�[���PK��Z7MӺ

��QSymfony/Component/Yaml/Yaml.phpnu�[���PK��Z�+�l��7+�QSymfony/Component/Yaml/Exception/ExceptionInterface.phpnu�[���PK��Z�|�-��5X�QSymfony/Component/Yaml/Exception/RuntimeException.phpnu�[���PK��Z�����
�
3��QSymfony/Component/Yaml/Exception/ParseException.phpnu�[���PK��Zؙ՚��2��QSymfony/Component/Yaml/Exception/DumpException.phpnu�[���PK��Z)%�,m
m
"2�QSymfony/Component/Yaml/Escaper.phpnu�[���PK��Zq+�3�?�?!�QSymfony/Component/Yaml/Inline.phpnu�[���PK��Z�ݣ�"�"6�=RSymfony/Component/HttpFoundation/ResponseHeaderBag.phpnu�[���PK��Z�}��xx.�`RSymfony/Component/HttpFoundation/ServerBag.phpnu�[���PK��Z�_DK�
�
5�oRSymfony/Component/HttpFoundation/RedirectResponse.phpnu�[���PK��Z�s
��5�zRSymfony/Component/HttpFoundation/StreamedResponse.phpnu�[���PK��Z��F��+��RSymfony/Component/HttpFoundation/Cookie.phpnu�[���PK��Z�6=��
�
,��RSymfony/Component/HttpFoundation/IpUtils.phpnu�[���PK��ZP�i���,ƩRSymfony/Component/HttpFoundation/FileBag.phpnu�[���PK��Z1y��<�RSymfony/Component/HttpFoundation/RequestMatcherInterface.phpnu�[���PK��ZPE�
XX/f�RSymfony/Component/HttpFoundation/autoloader.phpnu�[���PK��Z8{?���3�RSymfony/Component/HttpFoundation/RequestMatcher.phpnu�[���PK��Z�͢|1Y�RSymfony/Component/HttpFoundation/JsonResponse.phpnu�[���PK��ZVk�b335��RSymfony/Component/HttpFoundation/AcceptHeaderItem.phpnu�[���PK��Zn��OO=k�RSymfony/Component/HttpFoundation/ExpressionRequestMatcher.phpnu�[���PK��Z�a.1'�RSymfony/Component/HttpFoundation/AcceptHeader.phpnu�[���PK��Z\�8��1�SSymfony/Component/HttpFoundation/ParameterBag.phpnu�[���PK��Z��6��B�(SSymfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.phpnu�[���PK��Z5p1��J�7SSymfony/Component/HttpFoundation/File/MimeType/FileinfoMimeTypeGuesser.phpnu�[���PK��Z�qx��L?SSymfony/Component/HttpFoundation/File/MimeType/ExtensionGuesserInterface.phpnu�[���PK��Z�J��LBSSymfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.phpnu�[���PK��Z2�k�	�	C/KSSymfony/Component/HttpFoundation/File/MimeType/ExtensionGuesser.phpnu�[���PK��Z�w�nM�M�KKUSSymfony/Component/HttpFoundation/File/MimeType/MimeTypeExtensionGuesser.phpnu�[���PK��Z�	�L��K�SSymfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesserInterface.phpnu�[���PK��Z�)���.^�SSymfony/Component/HttpFoundation/File/File.phpnu�[���PK��Z�s�-��IQ�SSymfony/Component/HttpFoundation/File/Exception/FileNotFoundException.phpnu�[���PK��Z�S��==Kz�SSymfony/Component/HttpFoundation/File/Exception/UnexpectedTypeException.phpnu�[���PK��Z�1�e��I2TSymfony/Component/HttpFoundation/File/Exception/AccessDeniedException.phpnu�[���PK��Z�gr��CbTSymfony/Component/HttpFoundation/File/Exception/UploadException.phpnu�[���PK��Zo�����A�TSymfony/Component/HttpFoundation/File/Exception/FileException.phpnu�[���PK��Z��ގ�#�#6�TSymfony/Component/HttpFoundation/File/UploadedFile.phpnu�[���PK��Z�7�E	E	13,TSymfony/Component/HttpFoundation/RequestStack.phpnu�[���PK��Z��W���;�5TSymfony/Component/HttpFoundation/Session/Flash/FlashBag.phpnu�[���PK��Z�@��WWECTSymfony/Component/HttpFoundation/Session/Flash/AutoExpireFlashBag.phpnu�[���PK��Za����D�QTSymfony/Component/HttpFoundation/Session/Flash/FlashBagInterface.phpnu�[���PK��Z�=�\\=�YTSymfony/Component/HttpFoundation/Session/SessionInterface.phpnu�[���PK��Z�:au774�lTSymfony/Component/HttpFoundation/Session/Session.phpnu�[���PK��ZM&z�rr@G�TSymfony/Component/HttpFoundation/Session/SessionBagInterface.phpnu�[���PK��Z��eL)�TSymfony/Component/HttpFoundation/Session/Attribute/AttributeBagInterface.phpnu�[���PK��Z��(���C��TSymfony/Component/HttpFoundation/Session/Attribute/AttributeBag.phpnu�[���PK��Z�0�H66MߘTSymfony/Component/HttpFoundation/Session/Attribute/NamespacedAttributeBag.phpnu�[���PK��Z�t�3�3I��TSymfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.phpnu�[���PK��Zގ�!L��TSymfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.phpnu�[���PK��Z��$�

K6�TSymfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.phpnu�[���PK��Z����33Q�TSymfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.phpnu�[���PK��Z�>�q��O}USymfony/Component/HttpFoundation/Session/Storage/Handler/NullSessionHandler.phpnu�[���PK��Zi����R�USymfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.phpnu�[���PK��ZOZ�P""NUSymfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.phpnu�[���PK��Zk��4{{T�<USymfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.phpnu�[���PK��Zu�Y0��U�HUSymfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.phpnu�[���PK��Zڏ۹�
�
S�OUSymfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.phpnu�[���PK��Z�����U[USymfony/Component/HttpFoundation/Session/Storage/Handler/WriteCheckSessionHandler.phpnu�[���PK��Z�zu00LwcUSymfony/Component/HttpFoundation/Session/Storage/PhpBridgeSessionStorage.phpnu�[���PK��Zmwȡ��N#kUSymfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.phpnu�[���PK��Z�2�]��H!sUSymfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.phpnu�[���PK��Z�A��F�USymfony/Component/HttpFoundation/Session/Storage/Proxy/NativeProxy.phpnu�[���PK��Z��g_��@��USymfony/Component/HttpFoundation/Session/Storage/MetadataBag.phpnu�[���PK��Z��?�yyL��USymfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.phpnu�[���PK��Z�K>��2��USymfony/Component/HttpFoundation/ApacheRequest.phpnu�[���PK��Zq�ugd�d�,��USymfony/Component/HttpFoundation/Request.phpnu�[���PK��Zd�}޷%�%7S�VSymfony/Component/HttpFoundation/BinaryFileResponse.phpnu�[���PK��Z���pߋߋ-q�VSymfony/Component/HttpFoundation/Response.phpnu�[���PK��Z?`
�y	y	L�2WSymfony/Component/HttpFoundation/Resources/stubs/SessionHandlerInterface.phpnu�[���PK��ZEY���.�<WSymfony/Component/HttpFoundation/HeaderBag.phpnu�[���PK��Z9�;""'�\WSymfony/Component/BrowserKit/Cookie.phpnu�[���PK��Z.�TT+7WSymfony/Component/BrowserKit/autoloader.phpnu�[���PK��Z�����*�WSymfony/Component/BrowserKit/CookieJar.phpnu�[���PK��Z����
�
(ݞWSymfony/Component/BrowserKit/Request.phpnu�[���PK��Zl�-
-
)(�WSymfony/Component/BrowserKit/Response.phpnu�[���PK��Z㩑eCC'��WSymfony/Component/BrowserKit/Client.phpnu�[���PK��Z��/		(!�WSymfony/Component/BrowserKit/History.phpnu�[���PK��Z��V<nn2�XSymfony/Component/DomCrawler/FormFieldRegistry.phpnu�[���PK��ZLo�TT+gXSymfony/Component/DomCrawler/autoloader.phpnu�[���PK��Z���%XSymfony/Component/DomCrawler/Link.phpnu�[���PK��Z\Ud��	�	0�2XSymfony/Component/DomCrawler/Field/FormField.phpnu�[���PK��ZbڋvB
B
4�<XSymfony/Component/DomCrawler/Field/FileFormField.phpnu�[���PK��Z�	Y[$[$6`JXSymfony/Component/DomCrawler/Field/ChoiceFormField.phpnu�[���PK��Z
ʀ���8!oXSymfony/Component/DomCrawler/Field/TextareaFormField.phpnu�[���PK��Z�����5hsXSymfony/Component/DomCrawler/Field/InputFormField.phpnu�[���PK��Z<�4{bb(PyXSymfony/Component/DomCrawler/Crawler.phpnu�[���PK��Z�
�H7H7%��XSymfony/Component/DomCrawler/Form.phpnu�[���PK��Z�����!�!2aYSymfony/Component/CssSelector/XPath/Translator.phpnu�[���PK��Z��r771J5YSymfony/Component/CssSelector/XPath/XPathExpr.phpnu�[���PK��Z
���;�@YSymfony/Component/CssSelector/XPath/TranslatorInterface.phpnu�[���PK��Z��u��C�EYSymfony/Component/CssSelector/XPath/Extension/FunctionExtension.phpnu�[���PK��Z�܍��L	^YSymfony/Component/CssSelector/XPath/Extension/AttributeMatchingExtension.phpnu�[���PK��Z�Ѽ`PP?WqYSymfony/Component/CssSelector/XPath/Extension/NodeExtension.phpnu�[���PK��Z$p��BB?�YSymfony/Component/CssSelector/XPath/Extension/HtmlExtension.phpnu�[���PK��Zc�-��CǧYSymfony/Component/CssSelector/XPath/Extension/AbstractExtension.phpnu�[���PK��Z��x=	=	F�YSymfony/Component/CssSelector/XPath/Extension/CombinationExtension.phpnu�[���PK��Z ����FʶYSymfony/Component/CssSelector/XPath/Extension/PseudoClassExtension.phpnu�[���PK��Z���||D�YSymfony/Component/CssSelector/XPath/Extension/ExtensionInterface.phpnu�[���PK��Zu�UU,��YSymfony/Component/CssSelector/autoloader.phpnu�[���PK��Z,+?��;��YSymfony/Component/CssSelector/Node/CombinedSelectorNode.phpnu�[���PK��Z�r�I��4��YSymfony/Component/CssSelector/Node/NodeInterface.phpnu�[���PK��Z����3��YSymfony/Component/CssSelector/Node/SelectorNode.phpnu�[���PK��Z�pM2��3��YSymfony/Component/CssSelector/Node/AbstractNode.phpnu�[���PK��Z�Г^FF2��YSymfony/Component/CssSelector/Node/ElementNode.phpnu�[���PK��Z�.��221x�YSymfony/Component/CssSelector/Node/PseudoNode.phpnu�[���PK��Z	�i���0�YSymfony/Component/CssSelector/Node/ClassNode.phpnu�[���PK��Z����bb3Z�YSymfony/Component/CssSelector/Node/NegationNode.phpnu�[���PK��Z�x�2ZSymfony/Component/CssSelector/Node/Specificity.phpnu�[���PK��Z�#^[��/�ZSymfony/Component/CssSelector/Node/HashNode.phpnu�[���PK��ZF��K
K
4�ZSymfony/Component/CssSelector/Node/AttributeNode.phpnu�[���PK��Z�x�3�ZSymfony/Component/CssSelector/Node/FunctionNode.phpnu�[���PK��Zm��c��B ZSymfony/Component/CssSelector/Exception/InternalErrorException.phpnu�[���PK��Z��מ�@#ZSymfony/Component/CssSelector/Exception/SyntaxErrorException.phpnu�[���PK��Z/pTС�D#+ZSymfony/Component/CssSelector/Exception/ExpressionErrorException.phpnu�[���PK��Zgf�GBB>8.ZSymfony/Component/CssSelector/Exception/ExceptionInterface.phpnu�[���PK��Z'[|ɀ�:�0ZSymfony/Component/CssSelector/Exception/ParseException.phpnu�[���PK��Z^�}		-�3ZSymfony/Component/CssSelector/CssSelector.phpnu�[���PK��Z5#� HH<4=ZSymfony/Component/CssSelector/Parser/Shortcut/HashParser.phpnu�[���PK��Zҵܗ��C�CZSymfony/Component/CssSelector/Parser/Shortcut/EmptyStringParser.phpnu�[���PK��ZTR#[PP=IZSymfony/Component/CssSelector/Parser/Shortcut/ClassParser.phpnu�[���PK��Z�Z�>��?�OZSymfony/Component/CssSelector/Parser/Shortcut/ElementParser.phpnu�[���PK��Z���QQ4�UZSymfony/Component/CssSelector/Parser/TokenStream.phpnu�[���PK��Z��6\5
5
>~dZSymfony/Component/CssSelector/Parser/Handler/StringHandler.phpnu�[���PK��Z8�D�^^?!oZSymfony/Component/CssSelector/Parser/Handler/CommentHandler.phpnu�[���PK��Z�X{��<�sZSymfony/Component/CssSelector/Parser/Handler/HashHandler.phpnu�[���PK��Zh��ffAJ{ZSymfony/Component/CssSelector/Parser/Handler/HandlerInterface.phpnu�[���PK��Ze'n��>!ZSymfony/Component/CssSelector/Parser/Handler/NumberHandler.phpnu�[���PK��Z�#BT�ZSymfony/Component/CssSelector/Parser/Handler/IdentifierHandler.phpnu�[���PK��Z����BȌZSymfony/Component/CssSelector/Parser/Handler/WhitespaceHandler.phpnu�[���PK��Z6N�D1D1/̑ZSymfony/Component/CssSelector/Parser/Parser.phpnu�[���PK��Z;���		/o�ZSymfony/Component/CssSelector/Parser/Reader.phpnu�[���PK��Z�AEo118��ZSymfony/Component/CssSelector/Parser/ParserInterface.phpnu�[���PK��Z�zZ<��.u�ZSymfony/Component/CssSelector/Parser/Token.phpnu�[���PK��Z>�<��
�
D��ZSymfony/Component/CssSelector/Parser/Tokenizer/TokenizerPatterns.phpnu�[���PK��Z�S�kFF<��ZSymfony/Component/CssSelector/Parser/Tokenizer/Tokenizer.phpnu�[���PK��Z ��W55DZ�ZSymfony/Component/CssSelector/Parser/Tokenizer/TokenizerEscaping.phpnu�[���PK��Zb�k���+�ZSymfony/Component/EventDispatcher/Event.phpnu�[���PK��Z��YY0�[Symfony/Component/EventDispatcher/autoloader.phpnu�[���PK��Z�
���M�	[Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.phpnu�[���PK��Z,��DD2�[Symfony/Component/EventDispatcher/GenericEvent.phpnu�[���PK��ZcG�11>�[Symfony/Component/EventDispatcher/EventSubscriberInterface.phpnu�[���PK��Zs���> #[Symfony/Component/EventDispatcher/ImmutableEventDispatcher.phpnu�[���PK��ZU����>G,[Symfony/Component/EventDispatcher/EventDispatcherInterface.phpnu�[���PK��Z��NmCu8[Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.phpnu�[���PK��ZY�"��5S[Symfony/Component/EventDispatcher/EventDispatcher.phpnu�[���PK��Z x��
�
1%i[Symfony/Component/Console/Command/ListCommand.phpnu�[���PK��Z�Ƙ�7@7@-Ft[Symfony/Component/Console/Command/Command.phpnu�[���PK��Z�m_
_
1ڴ[Symfony/Component/Console/Command/HelpCommand.phpnu�[���PK��Z\0�E��+��[Symfony/Component/Console/ConsoleEvents.phpnu�[���PK��Z2V��#��[Symfony/Component/Console/Shell.phpnu�[���PK��Z�.�QQ(;�[Symfony/Component/Console/autoloader.phpnu�[���PK��Z�hr�f
f
6��[Symfony/Component/Console/Tester/ApplicationTester.phpnu�[���PK��Z~H(R2��[Symfony/Component/Console/Tester/CommandTester.phpnu�[���PK��Z�Q�)�)-.�[Symfony/Component/Console/Input/ArgvInput.phpnu�[���PK��Z��'��1C'\Symfony/Component/Console/Input/InputArgument.phpnu�[���PK��Z�AM662{4\Symfony/Component/Console/Input/InputInterface.phpnu�[���PK��Z��O�VV/E\Symfony/Component/Console/Input/InputOption.phpnu�[���PK��Z1�E(0(03�\\Symfony/Component/Console/Input/InputDefinition.phpnu�[���PK��Z�΂=�
�
/S�\Symfony/Component/Console/Input/StringInput.phpnu�[���PK��Zgm()��\Symfony/Component/Console/Input/Input.phpnu�[���PK��Zp���%%.�\Symfony/Component/Console/Input/ArrayInput.phpnu�[���PK��Z9K�h^^7��\Symfony/Component/Console/Input/InputAwareInterface.phpnu�[���PK��Zonj�&&<N�\Symfony/Component/Console/Formatter/OutputFormatterStyle.phpnu�[���PK��Z��l���7��\Symfony/Component/Console/Formatter/OutputFormatter.phpnu�[���PK��Z5����E�\Symfony/Component/Console/Formatter/OutputFormatterStyleInterface.phpnu�[���PK��Z�v��
�
A ]Symfony/Component/Console/Formatter/OutputFormatterStyleStack.phpnu�[���PK��ZJp����@u
]Symfony/Component/Console/Formatter/OutputFormatterInterface.phpnu�[���PK��Z��0�KK;�]Symfony/Component/Console/Output/ConsoleOutputInterface.phpnu�[���PK��Z��ϱ}}2~]Symfony/Component/Console/Output/ConsoleOutput.phpnu�[���PK��Z��z�MM4]$]Symfony/Component/Console/Output/OutputInterface.phpnu�[���PK��ZF�$_��/0]Symfony/Component/Console/Output/NullOutput.phpnu�[���PK��Zs�Q;;+A7]Symfony/Component/Console/Output/Output.phpnu�[���PK��Z�,Q�MM1�G]Symfony/Component/Console/Output/StreamOutput.phpnu�[���PK��Zt|X4hh3�T]Symfony/Component/Console/Output/BufferedOutput.phpnu�[���PK��Z�L�UҊҊ)PX]Symfony/Component/Console/Application.phpnu�[���PK��Z���	�	.{�]Symfony/Component/Console/Helper/HelperSet.phpnu�[���PK��Z�z����4��]Symfony/Component/Console/Helper/HelperInterface.phpnu�[���PK��ZZ\���+�]Symfony/Component/Console/Helper/Helper.phpnu�[���PK��Zg�se��4�]Symfony/Component/Console/Helper/FormatterHelper.phpnu�[���PK��Z��2204^Symfony/Component/Console/Helper/TableHelper.phpnu�[���PK��Z"U�1

5�3^Symfony/Component/Console/Helper/DescriptorHelper.phpnu�[���PK��Zs� H��5>^Symfony/Component/Console/Helper/InputAwareHelper.phpnu�[���PK��Z|po.o.3^A^Symfony/Component/Console/Helper/ProgressHelper.phpnu�[���PK��Z&�>@>@10p^Symfony/Component/Console/Helper/DialogHelper.phpnu�[���PK��ZD��uu7ϰ^Symfony/Component/Console/Descriptor/JsonDescriptor.phpnu�[���PK��Z�m��
�
3��^Symfony/Component/Console/Descriptor/Descriptor.phpnu�[���PK��Z�lP�..;��^Symfony/Component/Console/Descriptor/MarkdownDescriptor.phpnu�[���PK��Z�s�X�
�
?c�^Symfony/Component/Console/Descriptor/ApplicationDescription.phpnu�[���PK��Zﶲ��%�%6��^Symfony/Component/Console/Descriptor/XmlDescriptor.phpnu�[���PK��Z����7�_Symfony/Component/Console/Descriptor/TextDescriptor.phpnu�[���PK��ZJZ0<��<@;_Symfony/Component/Console/Descriptor/DescriptorInterface.phpnu�[���PK��Z���v$$7�>_Symfony/Component/Console/Resources/bin/hiddeninput.exenu�[���PK��Z||-&��7�b_Symfony/Component/Console/Event/ConsoleCommandEvent.phpnu�[���PK��Z�Z��&&9e_Symfony/Component/Console/Event/ConsoleTerminateEvent.phpnu�[���PK��Zs�KAA9�j_Symfony/Component/Console/Event/ConsoleExceptionEvent.phpnu�[���PK��Z��
���0Tq_Symfony/Component/Console/Event/ConsoleEvent.phpnu�[���PK��Z]�='YY0lw_Symfony/Component/OptionsResolver/autoloader.phpnu�[���PK��Z��sZ��G%y_Symfony/Component/OptionsResolver/Exception/InvalidOptionsException.phpnu�[���PK��Z�yPH��I�{_Symfony/Component/OptionsResolver/Exception/OptionDefinitionException.phpnu�[���PK��ZE@�^��B~_Symfony/Component/OptionsResolver/Exception/ExceptionInterface.phpnu�[���PK��Zp����G'�_Symfony/Component/OptionsResolver/Exception/MissingOptionsException.phpnu�[���PK��Z��G��>��_Symfony/Component/OptionsResolver/OptionsResolverInterface.phpnu�[���PK��Z^�R��<�<-�_Symfony/Component/OptionsResolver/Options.phpnu�[���PK��Z}���8%8%5��_Symfony/Component/OptionsResolver/OptionsResolver.phpnu�[���PK��ZfJ���5�`Symfony/Component/Config/Definition/NodeInterface.phpnu�[���PK��Z��jkk3w`Symfony/Component/Config/Definition/IntegerNode.phpnu�[���PK��Za�Vp0E`Symfony/Component/Config/Definition/EnumNode.phpnu�[���PK��ZUn=#'#';�`Symfony/Component/Config/Definition/PrototypedArrayNode.phpnu�[���PK��ZU��''1?=`Symfony/Component/Config/Definition/Processor.phpnu�[���PK��Z�C����;�H`Symfony/Component/Config/Definition/Exception/Exception.phpnu�[���PK��Z5-���O�J`Symfony/Component/Config/Definition/Exception/InvalidConfigurationException.phpnu�[���PK��Z����C2N`Symfony/Component/Config/Definition/Exception/UnsetKeyException.phpnu�[���PK��Z��@��F�P`Symfony/Component/Config/Definition/Exception/InvalidTypeException.phpnu�[���PK��Z]F4���L$S`Symfony/Component/Config/Definition/Exception/InvalidDefinitionException.phpnu�[���PK��Z�|�EEGzU`Symfony/Component/Config/Definition/Exception/DuplicateKeyException.phpnu�[���PK��Z�:2&QQM6X`Symfony/Component/Config/Definition/Exception/ForbiddenOverwriteException.phpnu�[���PK��Z#
֕44D[`Symfony/Component/Config/Definition/Builder/NormalizationBuilder.phpnu�[���PK��ZV�hU��;�a`Symfony/Component/Config/Definition/Builder/TreeBuilder.phpnu�[���PK��Z��ʍ��B�h`Symfony/Component/Config/Definition/Builder/EnumNodeDefinition.phpnu�[���PK��Z���{{<�m`Symfony/Component/Config/Definition/Builder/MergeBuilder.phpnu�[���PK��Z,��l[[A�s`Symfony/Component/Config/Definition/Builder/ValidationBuilder.phpnu�[���PK��ZP����E�x`Symfony/Component/Config/Definition/Builder/BooleanNodeDefinition.phpnu�[���PK��Z�e�@��F�|`Symfony/Component/Config/Definition/Builder/VariableNodeDefinition.phpnu�[���PK��Z��8�8C��`Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.phpnu�[���PK��Z �"�$$;�`Symfony/Component/Config/Definition/Builder/ExprBuilder.phpnu�[���PK��Z�3d�__M��`Symfony/Component/Config/Definition/Builder/ParentNodeDefinitionInterface.phpnu�[���PK��Z�mc��Dr�`Symfony/Component/Config/Definition/Builder/ScalarNodeDefinition.phpnu�[���PK��Z'nڭE��`Symfony/Component/Config/Definition/Builder/IntegerNodeDefinition.phpnu�[���PK��Zt�p��C<�`Symfony/Component/Config/Definition/Builder/FloatNodeDefinition.phpnu�[���PK��ZU��=��C��`Symfony/Component/Config/Definition/Builder/NodeParentInterface.phpnu�[���PK��Z �}��;��`Symfony/Component/Config/Definition/Builder/NodeBuilder.phpnu�[���PK��Z~�G�XXE��`Symfony/Component/Config/Definition/Builder/NumericNodeDefinition.phpnu�[���PK��Z��K��>�`Symfony/Component/Config/Definition/Builder/NodeDefinition.phpnu�[���PK��Z����3!aSymfony/Component/Config/Definition/BooleanNode.phpnu�[���PK��Z�+;;2/!aSymfony/Component/Config/Definition/ScalarNode.phpnu�[���PK��Zm�+��1�%aSymfony/Component/Config/Definition/FloatNode.phpnu�[���PK��Zi
�>>B*aSymfony/Component/Config/Definition/Dumper/YamlReferenceDumper.phpnu�[���PK��Z�2��&�&A�AaSymfony/Component/Config/Definition/Dumper/XmlReferenceDumper.phpnu�[���PK��Z$�¸	�	4�haSymfony/Component/Config/Definition/VariableNode.phpnu�[���PK��ZG4�*�*1�raSymfony/Component/Config/Definition/ArrayNode.phpnu�[���PK��Z*���dd>)�aSymfony/Component/Config/Definition/ConfigurationInterface.phpnu�[���PK��Z��eww>��aSymfony/Component/Config/Definition/PrototypeNodeInterface.phpnu�[���PK��Z-*ҹ--3�aSymfony/Component/Config/Definition/NumericNode.phpnu�[���PK��Z��B�""0p�aSymfony/Component/Config/Definition/BaseNode.phpnu�[���PK��Z0��007��aSymfony/Component/Config/Definition/ReferenceDumper.phpnu�[���PK��Z`�PP'm�aSymfony/Component/Config/autoloader.phpnu�[���PK��ZfK�EDD7�aSymfony/Component/Config/Resource/ResourceInterface.phpnu�[���PK��Z��T!!2��aSymfony/Component/Config/Resource/FileResource.phpnu�[���PK��Z�
#�
�
7B�aSymfony/Component/Config/Resource/DirectoryResource.phpnu�[���PK��Z�C3kll1z�aSymfony/Component/Config/FileLocatorInterface.phpnu�[���PK��Z7�TTQG�aSymfony/Component/Config/Exception/FileLoaderImportCircularReferenceException.phpnu�[���PK��Z��W�	�	>�aSymfony/Component/Config/Exception/FileLoaderLoadException.phpnu�[���PK��Z��k��*�aSymfony/Component/Config/Util/XmlUtils.phpnu�[���PK��ZI��(�bSymfony/Component/Config/FileLocator.phpnu�[���PK��Z__wP<
<
.'%bSymfony/Component/Config/Loader/FileLoader.phpnu�[���PK��Z���))4�2bSymfony/Component/Config/Loader/DelegatingLoader.phpnu�[���PK��Z������;N9bSymfony/Component/Config/Loader/LoaderResolverInterface.phpnu�[���PK��ZHPʉ�2�<bSymfony/Component/Config/Loader/LoaderResolver.phpnu�[���PK��Z�=���*~DbSymfony/Component/Config/Loader/Loader.phpnu�[���PK��Z���4993�LbSymfony/Component/Config/Loader/LoaderInterface.phpnu�[���PK��Z��:a�
�
(CRbSymfony/Component/Config/ConfigCache.phpnu�[���PK��Z\�[���0�]bSymfony/Component/HttpKernel/KernelInterface.phpnu�[���PK��Z�?.��\�\'�qbSymfony/Component/HttpKernel/Kernel.phpnu�[���PK��Z���?��bSymfony/Component/HttpKernel/CacheClearer/ChainCacheClearer.phpnu�[���PK��ZYxځ55C��bSymfony/Component/HttpKernel/CacheClearer/CacheClearerInterface.phpnu�[���PK��Z�zTT+Z�bSymfony/Component/HttpKernel/autoloader.phpnu�[���PK��Z_��S77A	�bSymfony/Component/HttpKernel/CacheWarmer/CacheWarmerInterface.phpnu�[���PK��Z���^FF>��bSymfony/Component/HttpKernel/CacheWarmer/WarmableInterface.phpnu�[���PK��Z��8ee8e�bSymfony/Component/HttpKernel/CacheWarmer/CacheWarmer.phpnu�[���PK��Z�R�!MMA2�bSymfony/Component/HttpKernel/CacheWarmer/CacheWarmerAggregate.phpnu�[���PK��Z��KK3��bSymfony/Component/HttpKernel/Debug/ErrorHandler.phpnu�[���PK��Z���9��7��bSymfony/Component/HttpKernel/Debug/ExceptionHandler.phpnu�[���PK��Z�eڮ55?��bSymfony/Component/HttpKernel/Debug/TraceableEventDispatcher.phpnu�[���PK��Z>�<���/$cSymfony/Component/HttpKernel/Log/NullLogger.phpnu�[���PK��Z~�[�

4M)cSymfony/Component/HttpKernel/Log/LoggerInterface.phpnu�[���PK��ZJ��=[[9�.cSymfony/Component/HttpKernel/Log/DebugLoggerInterface.phpnu�[���PK��Z���ss-�2cSymfony/Component/HttpKernel/KernelEvents.phpnu�[���PK��ZE^����?R?cSymfony/Component/HttpKernel/EventListener/ProfilerListener.phpnu�[���PK��Z����
�
?JUcSymfony/Component/HttpKernel/EventListener/FragmentListener.phpnu�[���PK��Z@S��>BccSymfony/Component/HttpKernel/EventListener/SessionListener.phpnu�[���PK��Z�|$���CXicSymfony/Component/HttpKernel/EventListener/ErrorsLoggerListener.phpnu�[���PK��Z���$$G�ncSymfony/Component/HttpKernel/EventListener/StreamedResponseListener.phpnu�[���PK��Z��	���@1tcSymfony/Component/HttpKernel/EventListener/ExceptionListener.phpnu�[���PK��ZP�C�yy?��cSymfony/Component/HttpKernel/EventListener/ResponseListener.phpnu�[���PK��ZS
�"P
P
=m�cSymfony/Component/HttpKernel/EventListener/LocaleListener.phpnu�[���PK��Z/�)A
A
B*�cSymfony/Component/HttpKernel/EventListener/TestSessionListener.phpnu�[���PK��Z�	��--=ݣcSymfony/Component/HttpKernel/EventListener/RouterListener.phpnu�[���PK��Z��^��:w�cSymfony/Component/HttpKernel/EventListener/EsiListener.phpnu�[���PK��ZqK-##@z�cSymfony/Component/HttpKernel/Fragment/InlineFragmentRenderer.phpnu�[���PK��Zm���33B
�cSymfony/Component/HttpKernel/Fragment/RoutableFragmentRenderer.phpnu�[���PK��Z�j�g�	�	=��cSymfony/Component/HttpKernel/Fragment/EsiFragmentRenderer.phpnu�[���PK��Z��R��9
�cSymfony/Component/HttpKernel/Fragment/FragmentHandler.phpnu�[���PK��Z5앾��BdSymfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.phpnu�[���PK��Zz�����C)dSymfony/Component/HttpKernel/Fragment/FragmentRendererInterface.phpnu�[���PK��Z�ST��;s dSymfony/Component/HttpKernel/Exception/FlattenException.phpnu�[���PK��Z[G�??B�#dSymfony/Component/HttpKernel/Exception/BadRequestHttpException.phpnu�[���PK��Z��7��Gm'dSymfony/Component/HttpKernel/Exception/TooManyRequestsHttpException.phpnu�[���PK��ZW1�d��8m,dSymfony/Component/HttpKernel/Exception/HttpException.phpnu�[���PK��ZN�0�;;@v0dSymfony/Component/HttpKernel/Exception/ConflictHttpException.phpnu�[���PK��ZC%؝SSL!4dSymfony/Component/HttpKernel/Exception/UnsupportedMediaTypeHttpException.phpnu�[���PK��Z���EEE�7dSymfony/Component/HttpKernel/Exception/NotAcceptableHttpException.phpnu�[���PK��Z�Ѕ33<�;dSymfony/Component/HttpKernel/Exception/GoneHttpException.phpnu�[���PK��Z^���>I?dSymfony/Component/HttpKernel/Exception/FatalErrorException.phpnu�[���PK��Z)8*uuD6BdSymfony/Component/HttpKernel/Exception/AccessDeniedHttpException.phpnu�[���PK��Z�+�~~LFdSymfony/Component/HttpKernel/Exception/PreconditionRequiredHttpException.phpnu�[���PK��Z+�;XXJJdSymfony/Component/HttpKernel/Exception/ServiceUnavailableHttpException.phpnu�[���PK��Z*���D�NdSymfony/Component/HttpKernel/Exception/UnauthorizedHttpException.phpnu�[���PK��Z�瞻??@2SdSymfony/Component/HttpKernel/Exception/NotFoundHttpException.phpnu�[���PK��Z<��~��H�VdSymfony/Component/HttpKernel/Exception/MethodNotAllowedHttpException.phpnu�[���PK��Z�� GGF;[dSymfony/Component/HttpKernel/Exception/LengthRequiredHttpException.phpnu�[���PK��Z�;C�OOJ�^dSymfony/Component/HttpKernel/Exception/PreconditionFailedHttpException.phpnu�[���PK��ZrQrW��A�bdSymfony/Component/HttpKernel/Exception/HttpExceptionInterface.phpnu�[���PK��Z�^t�4�edSymfony/Component/HttpKernel/TerminableInterface.phpnu�[���PK��Z���=AA4ijdSymfony/Component/HttpKernel/HttpKernelInterface.phpnu�[���PK��Z�k�t$$+pdSymfony/Component/HttpKernel/HttpKernel.phpnu�[���PK��Z����b
b
9p�dSymfony/Component/HttpKernel/HttpCache/StoreInterface.phpnu�[���PK��ZM~��CCL;�dSymfony/Component/HttpKernel/HttpCache/EsiResponseCacheStrategyInterface.phpnu�[���PK��Z�w�n n .��dSymfony/Component/HttpKernel/HttpCache/Esi.phpnu�[���PK��Z�#��[�[4��dSymfony/Component/HttpKernel/HttpCache/HttpCache.phpnu�[���PK��Z�K:�1�10!eSymfony/Component/HttpKernel/HttpCache/Store.phpnu�[���PK��Z/��)�	�	C5SeSymfony/Component/HttpKernel/HttpCache/EsiResponseCacheStrategy.phpnu�[���PK��Z�J�z��*�]eSymfony/Component/HttpKernel/UriSigner.phpnu�[���PK��Z��d��3�deSymfony/Component/HttpKernel/Config/FileLocator.phpnu�[���PK��Z!���ll.�jeSymfony/Component/HttpKernel/Bundle/Bundle.phpnu�[���PK��Z�3�a��7m�eSymfony/Component/HttpKernel/Bundle/BundleInterface.phpnu�[���PK��ZB�Wzll@��eSymfony/Component/HttpKernel/Profiler/MongoDbProfilerStorage.phpnu�[���PK��Z���

2��eSymfony/Component/HttpKernel/Profiler/Profiler.phpnu�[���PK��Z$���	�	B�eSymfony/Component/HttpKernel/Profiler/MemcachedProfilerStorage.phpnu�[���PK��Z�rLU��B�eSymfony/Component/HttpKernel/Profiler/ProfilerStorageInterface.phpnu�[���PK��ZT��sX	X	>u�eSymfony/Component/HttpKernel/Profiler/MysqlProfilerStorage.phpnu�[���PK��ZN����'�'>;�eSymfony/Component/HttpKernel/Profiler/RedisProfilerStorage.phpnu�[���PK��Z�����<lfSymfony/Component/HttpKernel/Profiler/PdoProfilerStorage.phpnu�[���PK��ZiY~2
2
Am$fSymfony/Component/HttpKernel/Profiler/MemcacheProfilerStorage.phpnu�[���PK��Z� ��1/fSymfony/Component/HttpKernel/Profiler/Profile.phpnu�[���PK��Z�t��E*DfSymfony/Component/HttpKernel/Profiler/BaseMemcacheProfilerStorage.phpnu�[���PK��Zt}�[��?�bfSymfony/Component/HttpKernel/Profiler/SqliteProfilerStorage.phpnu�[���PK��Z\Y�`��=�ufSymfony/Component/HttpKernel/Profiler/FileProfilerStorage.phpnu�[���PK��Z��,&&8�fSymfony/Component/HttpKernel/Event/PostResponseEvent.phpnu�[���PK��Z
�7���9��fSymfony/Component/HttpKernel/Event/FinishRequestEvent.phpnu�[���PK��Z�`g��:̜fSymfony/Component/HttpKernel/Event/FilterResponseEvent.phpnu�[���PK��Z٨�.kkJ��fSymfony/Component/HttpKernel/Event/GetResponseForControllerResultEvent.phpnu�[���PK��Z9�I��7ܩfSymfony/Component/HttpKernel/Event/GetResponseEvent.phpnu�[���PK��Z�9����CίfSymfony/Component/HttpKernel/Event/GetResponseForExceptionEvent.phpnu�[���PK��Z�%���	�	<�fSymfony/Component/HttpKernel/Event/FilterControllerEvent.phpnu�[���PK��Z}�x��2@�fSymfony/Component/HttpKernel/Event/KernelEvent.phpnu�[���PK��ZN�#�FF'~�fSymfony/Component/HttpKernel/Client.phpnu�[���PK��Z�
<I�fSymfony/Component/HttpKernel/DataCollector/LateDataCollectorInterface.phpnu�[���PK��Z�8���E��fSymfony/Component/HttpKernel/DataCollector/ExceptionDataCollector.phpnu�[���PK��Z�2��~~B��fSymfony/Component/HttpKernel/DataCollector/ConfigDataCollector.phpnu�[���PK��Z��.�E�
gSymfony/Component/HttpKernel/DataCollector/DataCollectorInterface.phpnu�[���PK��Z��޹�B(gSymfony/Component/HttpKernel/DataCollector/LoggerDataCollector.phpnu�[���PK��Z�@:o	o	BSgSymfony/Component/HttpKernel/DataCollector/RouterDataCollector.phpnu�[���PK��Z��+66A4&gSymfony/Component/HttpKernel/DataCollector/Util/ValueExporter.phpnu�[���PK��ZIYz��(�(C�+gSymfony/Component/HttpKernel/DataCollector/RequestDataCollector.phpnu�[���PK��Z����
�
A9UgSymfony/Component/HttpKernel/DataCollector/EventDataCollector.phpnu�[���PK��ZƏGV��@*`gSymfony/Component/HttpKernel/DataCollector/TimeDataCollector.phpnu�[���PK��Zn�--<8mgSymfony/Component/HttpKernel/DataCollector/DataCollector.phpnu�[���PK��Z(���;	;	B�rgSymfony/Component/HttpKernel/DataCollector/MemoryDataCollector.phpnu�[���PK��Z^/|GooG~|gSymfony/Component/HttpKernel/Controller/ControllerResolverInterface.phpnu�[���PK��Z��|�Gd�gSymfony/Component/HttpKernel/Controller/TraceableControllerResolver.phpnu�[���PK��Z�xXX?�gSymfony/Component/HttpKernel/Controller/ControllerReference.phpnu�[���PK��ZNC��tt>��gSymfony/Component/HttpKernel/Controller/ControllerResolver.phpnu�[���PK��Z;��M��>��gSymfony/Component/HttpKernel/DependencyInjection/Extension.phpnu�[���PK��Z�6�V
V
M�gSymfony/Component/HttpKernel/DependencyInjection/ContainerAwareHttpKernel.phpnu�[���PK��Z�k���J��gSymfony/Component/HttpKernel/DependencyInjection/RegisterListenersPass.phpnu�[���PK��Z���u__J�gSymfony/Component/HttpKernel/DependencyInjection/ConfigurableExtension.phpnu�[���PK��Z&!#ffT��gSymfony/Component/HttpKernel/DependencyInjection/MergeExtensionConfigurationPass.phpnu�[���PK��ZQNR��J��gSymfony/Component/HttpKernel/DependencyInjection/AddClassesToCachePass.phpnu�[���PK��Z���a��9�gSymfony/Component/ClassLoader/ApcUniversalClassLoader.phpnu�[���PK��Z��PЩ
�
3u�gSymfony/Component/ClassLoader/XcacheClassLoader.phpnu�[���PK��Z"�K�UU,��gSymfony/Component/ClassLoader/autoloader.phpnu�[���PK��Z��A���02�gSymfony/Component/ClassLoader/MapClassLoader.phpnu�[���PK��Zw�!�));��gSymfony/Component/ClassLoader/DebugUniversalClassLoader.phpnu�[���PK��Z�v�	.	.7#�gSymfony/Component/ClassLoader/ClassCollectionLoader.phpnu�[���PK��Z�a.e"e"6�-hSymfony/Component/ClassLoader/UniversalClassLoader.phpnu�[���PK��Z��S�

2^PhSymfony/Component/ClassLoader/DebugClassLoader.phpnu�[���PK��Z��O���5�]hSymfony/Component/ClassLoader/WinCacheClassLoader.phpnu�[���PK��Z�?wy�
�
34mhSymfony/Component/ClassLoader/ClassMapGenerator.phpnu�[���PK��ZlO�ݫ�0i{hSymfony/Component/ClassLoader/ApcClassLoader.phpnu�[���PK��Zv��'��-t�hSymfony/Component/ClassLoader/ClassLoader.phpnu�[���PK��Z��]
I
I
:S�hSymfony/Component/DependencyInjection/SimpleXMLElement.phpnu�[���PK��Zl5����/�hSymfony/Component/DependencyInjection/Alias.phpnu�[���PK��Z���Ma�hSymfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.phpnu�[���PK��Z��ҳ��H��hSymfony/Component/DependencyInjection/LazyProxy/PhpDumper/NullDumper.phpnu�[���PK��Z����JJV%�hSymfony/Component/DependencyInjection/LazyProxy/Instantiator/InstantiatorInterface.phpnu�[���PK��Z�i�nnX��hSymfony/Component/DependencyInjection/LazyProxy/Instantiator/RealServiceInstantiator.phpnu�[���PK��Z$�772��hSymfony/Component/DependencyInjection/Variable.phpnu�[���PK��Z���U" " C��hSymfony/Component/DependencyInjection/ParameterBag/ParameterBag.phpnu�[���PK��ZܮP8�	�	L�hSymfony/Component/DependencyInjection/ParameterBag/ParameterBagInterface.phpnu�[���PK��Zך�I>�hSymfony/Component/DependencyInjection/ParameterBag/FrozenParameterBag.phpnu�[���PK��Z�,x�mm/��hSymfony/Component/DependencyInjection/Scope.phpnu�[���PK��Z��]]4��hSymfony/Component/DependencyInjection/autoloader.phpnu�[���PK��Z_��J8DiSymfony/Component/DependencyInjection/ScopeInterface.phpnu�[���PK��Z�BtBBJ�iSymfony/Component/DependencyInjection/IntrospectableContainerInterface.phpnu�[���PK��Z
O�,��J�iSymfony/Component/DependencyInjection/Exception/BadMethodCallException.phpnu�[���PK��Z����L�iSymfony/Component/DependencyInjection/Exception/ServiceNotFoundException.phpnu�[���PK��Z�{����H	iSymfony/Component/DependencyInjection/Exception/OutOfBoundsException.phpnu�[���PK��Z��9FOiSymfony/Component/DependencyInjection/Exception/ExceptionInterface.phpnu�[���PK��Z�
+��D�iSymfony/Component/DependencyInjection/Exception/RuntimeException.phpnu�[���PK��Z��\�
�
N6iSymfony/Component/DependencyInjection/Exception/ParameterNotFoundException.phpnu�[���PK��ZI_���Jv!iSymfony/Component/DependencyInjection/Exception/InactiveScopeException.phpnu�[���PK��Z���z��S�%iSymfony/Component/DependencyInjection/Exception/ScopeWideningInjectionException.phpnu�[���PK��Zl.��B�-iSymfony/Component/DependencyInjection/Exception/LogicException.phpnu�[���PK��Z��]���U&0iSymfony/Component/DependencyInjection/Exception/ServiceCircularReferenceException.phpnu�[���PK��Z��L�4iSymfony/Component/DependencyInjection/Exception/InvalidArgumentException.phpnu�[���PK��Z= ԥ�S37iSymfony/Component/DependencyInjection/Exception/ScopeCrossingInjectionException.phpnu�[���PK��Z�qB��W[?iSymfony/Component/DependencyInjection/Exception/ParameterCircularReferenceException.phpnu�[���PK��Zq8I���A�CiSymfony/Component/DependencyInjection/ContainerAwareInterface.phpnu�[���PK��Z-&�����:�FiSymfony/Component/DependencyInjection/ContainerBuilder.phpnu�[���PK��Z��c!89894��iSymfony/Component/DependencyInjection/Definition.phpnu�[���PK��Z�u�ii8HjSymfony/Component/DependencyInjection/ContainerAware.phpnu�[���PK��Z�H8��=jSymfony/Component/DependencyInjection/ContainerAwareTrait.phpnu�[���PK��Z����By
jSymfony/Component/DependencyInjection/TaggedContainerInterface.phpnu�[���PK��Z��A�:$:$;�
jSymfony/Component/DependencyInjection/Dumper/YamlDumper.phpnu�[���PK��ZN/�++7}2jSymfony/Component/DependencyInjection/Dumper/Dumper.phpnu�[���PK��Z����%�%?6jSymfony/Component/DependencyInjection/Dumper/GraphvizDumper.phpnu�[���PK��Z"�^� � �:y\jSymfony/Component/DependencyInjection/Dumper/PhpDumper.phpnu�[���PK��Z}���@	kSymfony/Component/DependencyInjection/Dumper/DumperInterface.phpnu�[���PK��Z���*�*:PkSymfony/Component/DependencyInjection/Dumper/XmlDumper.phpnu�[���PK��Z;Yޯ��<U7kSymfony/Component/DependencyInjection/ExpressionLanguage.phpnu�[���PK��ZU穌PP=�<kSymfony/Component/DependencyInjection/DefinitionDecorator.phpnu�[���PK��Z-R�],,3=OkSymfony/Component/DependencyInjection/Reference.phpnu�[���PK��ZU��a--;�UkSymfony/Component/DependencyInjection/Loader/FileLoader.phpnu�[���PK��ZӸBj>dZkSymfony/Component/DependencyInjection/Loader/IniFileLoader.phpnu�[���PK��Z�
���>�akSymfony/Component/DependencyInjection/Loader/ClosureLoader.phpnu�[���PK��Z���((>PhkSymfony/Component/DependencyInjection/Loader/PhpFileLoader.phpnu�[���PK��Z�z#aQ�nkSymfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsdnu�[���PK��ZL����8�8>u�kSymfony/Component/DependencyInjection/Loader/XmlFileLoader.phpnu�[���PK��Z!+���+�+?��kSymfony/Component/DependencyInjection/Loader/YamlFileLoader.phpnu�[���PK��Z��Gp5
5
;��kSymfony/Component/DependencyInjection/Compiler/Compiler.phpnu�[���PK��Z�0є##?m�kSymfony/Component/DependencyInjection/Compiler/RepeatedPass.phpnu�[���PK��ZL��FFU�lSymfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.phpnu�[���PK��ZC�\Z��=�lSymfony/Component/DependencyInjection/Compiler/PassConfig.phpnu�[���PK��Zx�7���L�-lSymfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphEdge.phpnu�[���PK��Z�� �M84lSymfony/Component/DependencyInjection/Compiler/CheckReferenceValidityPass.phpnu�[���PK��Z�i�Z�
�
N�JlSymfony/Component/DependencyInjection/Compiler/RemoveUnusedDefinitionsPass.phpnu�[���PK��Z�!�?��K	VlSymfony/Component/DependencyInjection/Compiler/RemovePrivateAliasesPass.phpnu�[���PK��Z��U*''Pw[lSymfony/Component/DependencyInjection/Compiler/RemoveAbstractDefinitionsPass.phpnu�[���PK��Z��m��O`lSymfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.phpnu�[���PK��Z�iJT�
�
O�rlSymfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.phpnu�[���PK��Z��PPQ��lSymfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.phpnu�[���PK��ZV�%))H��lSymfony/Component/DependencyInjection/Compiler/ServiceReferenceGraph.phpnu�[���PK��Z[���	�	L*�lSymfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphNode.phpnu�[���PK��Z��ϒ��Q��lSymfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.phpnu�[���PK��Z���nnSƸlSymfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.phpnu�[���PK��ZX�\\R��lSymfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.phpnu�[���PK��Z�_9��H��lSymfony/Component/DependencyInjection/Compiler/CompilerPassInterface.phpnu�[���PK��Z��Eų�J��lSymfony/Component/DependencyInjection/Compiler/RepeatablePassInterface.phpnu�[���PK��Zb[_�66_$�lSymfony/Component/DependencyInjection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.phpnu�[���PK��Z@��q	q	N��lSymfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.phpnu�[���PK��Z��ddN��lSymfony/Component/DependencyInjection/Compiler/CheckDefinitionValidityPass.phpnu�[���PK��Z�ۻǠ�O��lSymfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.phpnu�[���PK��Z�����C�mSymfony/Component/DependencyInjection/Compiler/LoggingFormatter.phpnu�[���PK��Z����EBEB3
mSymfony/Component/DependencyInjection/Container.phpnu�[���PK��Z�E�?<�LmSymfony/Component/DependencyInjection/ContainerInterface.phpnu�[���PK��Z�o
�=.\mSymfony/Component/DependencyInjection/Extension/Extension.phpnu�[���PK��ZDS�F�kmSymfony/Component/DependencyInjection/Extension/ExtensionInterface.phpnu�[���PK��Z��J��S$rmSymfony/Component/DependencyInjection/Extension/ConfigurationExtensionInterface.phpnu�[���PK��ZC��oMMM�vmSymfony/Component/DependencyInjection/Extension/PrependExtensionInterface.phpnu�[���PK��Z��F"��3UymSymfony/Component/DependencyInjection/Parameter.phpnu�[���PK��Z��
����
�|mNet/IDNA2.phpnu�[���PK��Z���S66�oNet/IDNA2/Exception.phpnu�[���PK��Z&��#rr oNet/IDNA2/Exception/Nameprep.phpnu�[���PK��Z����Z�Z�
�oNet/Sieve.phpnu�[���PK��Zz��|����w�oNet/SMTP.phpnu�[���PK��Z���NFUFU3�pNet/Socket.phpnu�[���PK��Z
��p.depdblocknu�[���PK��Z'P���
�
��pezc/Base/metadata.phpnu�[���PK��Z:��||��pezc/Base/ezc_bootstrap.phpnu�[���PK��Z�������pezc/Base/options/autoload.phpnu�[���PK��Z|R��)��pezc/Base/structs/repository_directory.phpnu�[���PK��ZS�،��&_qezc/Base/structs/file_find_context.phpnu�[���PK��Zj��_qezc/Base/metadata/tarball.phpnu�[���PK��Zmyv		�qezc/Base/metadata/pear.phpnu�[���PK��Z�B�X�+�++qezc/Base/features.phpnu�[���PK��Zl��VV%�Vqezc/Base/exceptions/setting_value.phpnu�[���PK��ZHDfPEE&�\qezc/Base/exceptions/file_not_found.phpnu�[���PK��Z��Ū��!*aqezc/Base/exceptions/exception.phpnu�[���PK��Z�@c��* eqezc/Base/exceptions/property_not_found.phpnu�[���PK��Zu�3� nhqezc/Base/exceptions/whatever.phpnu�[���PK��Z�b�993�mqezc/Base/exceptions/functionality_not_supported.phpnu�[���PK��Z��ll.`qqezc/Base/exceptions/invalid_callback_class.phpnu�[���PK��Z��!���*uqezc/Base/exceptions/file_io.phpnu�[���PK��Z�ӥ�'I{qezc/Base/exceptions/file_permission.phpnu�[���PK��Z²Gi��E�qezc/Base/exceptions/value.phpnu�[���PK��Z�R�~11+S�qezc/Base/exceptions/extension_not_found.phpnu�[���PK��ZՆ��((&ߎqezc/Base/exceptions/file_exception.phpnu�[���PK��Z�aa+]�qezc/Base/exceptions/property_permission.phpnu�[���PK��Z^M�@@,�qezc/Base/exceptions/invalid_parent_class.phpnu�[���PK��Z�{��QQ6��qezc/Base/exceptions/double_class_repository_prefix.phpnu�[���PK��Z����0l�qezc/Base/exceptions/init_callback_configured.phpnu�[���PK��Z��rr v�qezc/Base/exceptions/autoload.phpnu�[���PK��Z�ם�OO)8�qezc/Base/exceptions/setting_not_found.phpnu�[���PK��ZUJX���qezc/Base/options.phpnu�[���PK��Z��4QEQE�qezc/Base/file.phpnu�[���PK��ZS]�KK�rezc/Base/init.phpnu�[���PK��Z��/��#/rezc/Base/interfaces/persistable.phpnu�[���PK��Z4�ei��"xrezc/Base/interfaces/exportable.phpnu�[���PK��ZPBs|��1trezc/Base/interfaces/configuration_initializer.phpnu�[���PK��Z�%�NN["rezc/Base/base_autoload.phpnu�[���PK��Z�xr44�.rezc/Base/struct.phpnu�[���PK��Z��<�V�Vj2rezc/Base/base.phpnu�[���PK��Z�B!)s,s,s�rezc/ConsoleTools/table/row.phpnu�[���PK��Z'�rw��4�rezc/ConsoleTools/table/cell.phpnu�[���PK��Z��\Ѫ7�7 ��rezc/ConsoleTools/progressbar.phpnu�[���PK��Z	L�^zsezc/ConsoleTools/statusbar.phpnu�[���PK��Z5���tt%�sezc/ConsoleTools/console_autoload.phpnu�[���PK��Z���O��!�7sezc/ConsoleTools/tools/string.phpnu�[���PK��Z;o�!"�Msezc/ConsoleTools/dialog_viewer.phpnu�[���PK��Z����+IUsezc/ConsoleTools/dialog/question_dialog.phpnu�[���PK��ZegO���<�usezc/ConsoleTools/dialog/validators/question_dialog_regex.phpnu�[���PK��Z��,M??;͉sezc/ConsoleTools/dialog/validators/question_dialog_type.phpnu�[���PK��Z�����:w�sezc/ConsoleTools/dialog/validators/menu_dialog_default.phpnu�[���PK��Z��-�>b�sezc/ConsoleTools/dialog/validators/question_dialog_mapping.phpnu�[���PK��ZH�!���A��sezc/ConsoleTools/dialog/validators/question_dialog_collection.phpnu�[���PK��Zkx2���'-�sezc/ConsoleTools/dialog/menu_dialog.phpnu�[���PK��Z��%p%pftezc/ConsoleTools/table.phpnu�[���PK��Z�,���,�vtezc/ConsoleTools/options/question_dialog.phpnu�[���PK��Zͅ���(�tezc/ConsoleTools/options/progressbar.phpnu�[���PK��Z��y��&Y�tezc/ConsoleTools/options/statusbar.phpnu�[���PK��Z��88HH"P�tezc/ConsoleTools/options/table.phpnu�[���PK��Z*��..#�tezc/ConsoleTools/options/dialog.phpnu�[���PK��Z��BB,k�tezc/ConsoleTools/options/progressmonitor.phpnu�[���PK��Z'��J

#	�tezc/ConsoleTools/options/output.phpnu�[���PK��Z���Q��(��tezc/ConsoleTools/options/menu_dialog.phpnu�[���PK��Z��c�gg*��tezc/ConsoleTools/structs/output_format.phpnu�[���PK��Z#�j�''+y�tezc/ConsoleTools/structs/output_formats.phpnu�[���PK��Z�!{D��(�uezc/ConsoleTools/structs/option_rule.phpnu�[���PK��Z\)�|��1'uezc/ConsoleTools/exceptions/argument_too_many.phpnu�[���PK��Z�:�<&+uezc/ConsoleTools/exceptions/option_string_not_wellformed.phpnu�[���PK��Z�%�agg:�.uezc/ConsoleTools/exceptions/option_mandatory_violation.phpnu�[���PK��ZJ�8��&n2uezc/ConsoleTools/exceptions/option.phpnu�[���PK��Z�����<D5uezc/ConsoleTools/exceptions/argument_mandatory_violation.phpnu�[���PK��Z��:49uezc/ConsoleTools/exceptions/option_exclusion_violation.phpnu�[���PK��Z����5�>uezc/ConsoleTools/exceptions/option_type_violation.phpnu�[���PK��Z7���)Duezc/ConsoleTools/exceptions/exception.phpnu�[���PK��Ze�8##1Fuezc/ConsoleTools/exceptions/option_not_exists.phpnu�[���PK��Za��rr7�Iuezc/ConsoleTools/exceptions/argument_type_violation.phpnu�[���PK��ZX�XDD;dNuezc/ConsoleTools/exceptions/argument_already_registered.phpnu�[���PK��Z] 5��(Uuezc/ConsoleTools/exceptions/argument.phpnu�[���PK��Z��ī�2�Wuezc/ConsoleTools/exceptions/no_position_stored.phpnu�[���PK��Z a�3[uezc/ConsoleTools/exceptions/invalid_option_name.phpnu�[���PK��Z|�����9}^uezc/ConsoleTools/exceptions/option_already_registered.phpnu�[���PK��Z�J���:�auezc/ConsoleTools/exceptions/option_arguments_violation.phpnu�[���PK��Z�BW9��5�euezc/ConsoleTools/exceptions/invalid_output_target.phpnu�[���PK��Z��H��6)iuezc/ConsoleTools/exceptions/no_valid_dialog_result.phpnu�[���PK��Z=��?��,Rluezc/ConsoleTools/exceptions/dialog_abort.phpnu�[���PK��Z�ř��4douezc/ConsoleTools/exceptions/option_missing_value.phpnu�[���PK��Z��;Msuezc/ConsoleTools/exceptions/option_dependency_violation.phpnu�[���PK��Zs��

/�xuezc/ConsoleTools/exceptions/option_no_alias.phpnu�[���PK��Z��vv61|uezc/ConsoleTools/exceptions/option_too_many_values.phpnu�[���PK��Z=	�R�L�L!
�uezc/ConsoleTools/input/option.phpnu�[���PK��Z
t�^^$�uezc/ConsoleTools/input/arguments.phpnu�[���PK��Z�%�663��uezc/ConsoleTools/input/help_generators/standard.phpnu�[���PK��Z�p���#F"vezc/ConsoleTools/input/argument.phpnu�[���PK��Z�&�T��.�<vezc/ConsoleTools/input/validators/standard.phpnu�[���PK��ZT\�G�G��Qvezc/ConsoleTools/input.phpnu�[���PK��Z�Jq�VV$Kwezc/ConsoleTools/progressmonitor.phpnu�[���PK��ZwQO~4�wezc/ConsoleTools/interfaces/input_help_generator.phpnu�[���PK��Z�9c"9]0wezc/ConsoleTools/interfaces/question_dialog_validator.phpnu�[���PK��Z%uu/�3wezc/ConsoleTools/interfaces/input_validator.phpnu�[���PK��Z�+���5�8wezc/ConsoleTools/interfaces/menu_dialog_validator.phpnu�[���PK��ZA�
NS
S
&�;wezc/ConsoleTools/interfaces/dialog.phpnu�[���PK��Ze��ެ�01Fwezc/ConsoleTools/interfaces/dialog_validator.phpnu�[���PK��Z���4�J�J=Lwezc/ConsoleTools/output.phpnu�[���PK��Zunš�w�wA�wezc/Archive/archive.phpnu�[���PK��ZԢ"$fIfI|xezc/Archive/file/block_file.phpnu�[���PK��Z�cp'
(
(#1Yxezc/Archive/file/character_file.phpnu�[���PK��Z$�^�3�3��xezc/Archive/file/file.phpnu�[���PK��Z��5�
�
 ��xezc/Archive/archive_autoload.phpnu�[���PK��ZU��+77��xezc/Archive/utils/stat_mode.phpnu�[���PK��Z��0���8�xezc/Archive/utils/checksums.phpnu�[���PK��Z	�z��/�xezc/Archive/utils/file_type.phpnu�[���PK��Z}�sb�	�	B�xezc/Archive/options/archive.phpnu�[���PK��Zf� S	S	0yezc/Archive/structs/file.phpnu�[���PK��Z�L��<< �yezc/Archive/exceptions/empty.phpnu�[���PK��Z�����'[yezc/Archive/exceptions/unknown_type.phpnu�[���PK��Z�G��MM$�yezc/Archive/exceptions/exception.phpnu�[���PK��Z&Y���#)yezc/Archive/exceptions/checksum.phpnu�[���PK��Z�0dii%)yezc/Archive/exceptions/block_size.phpnu�[���PK��Z�N�8TT �yezc/Archive/exceptions/value.phpnu�[���PK��Z�9+II�"yezc/Archive/exceptions/io.phpnu�[���PK��Z}�H���-!%yezc/Archive/exceptions/internal_exception.phpnu�[���PK��Z �����'(yezc/Archive/exceptions/entry_prefix.phpnu�[���PK��Z�h��A�AY+yezc/Archive/entry.phpnu�[���PK��Z�\�^G^G-"myezc/Archive/zip/headers/central_directory.phpnu�[���PK��ZK���`c`c&ݴyezc/Archive/zip/headers/local_file.phpnu�[���PK��Z�
�,�#�#1�zezc/Archive/zip/headers/central_directory_end.phpnu�[���PK��ZXA�V�V�<zezc/Archive/zip/zip.phpnu�[���PK��Z�<��#˓zezc/Archive/interfaces/callback.phpnu�[���PK��Z�靽�	�	��zezc/Archive/tar/pax.phpnu�[���PK��Z�31��	�	��zezc/Archive/tar/ustar.phpnu�[���PK��Z=��

��zezc/Archive/tar/gnu.phpnu�[���PK��Z�$�����zezc/Archive/tar/headers/pax.phpnu�[���PK��Z�M��9�9!�zezc/Archive/tar/headers/ustar.phpnu�[���PK��ZNv�nn>{ezc/Archive/tar/headers/gnu.phpnu�[���PK��Z^���8�8�{ezc/Archive/tar/headers/v7.phpnu�[���PK��Z���BLBL�L{ezc/Archive/tar/v7.phpnu�[���PK��Z��
--{�{ezc/File/file_autoload.phpnu�[���PK��Z��K���{ezc/File/file.phpnu�[���PK��Z��5�
�
!.�{ezc/autoload/archive_autoload.phpnu�[���PK��Z5���tt!-�{ezc/autoload/console_autoload.phpnu�[���PK��Z��
--�{ezc/autoload/file_autoload.phpnu�[���PK��Z�%�NNm�{ezc/autoload/base_autoload.phpnu�[���PK��Z���=YY	�{Archive/Tar.phpnu�[���PK��Z�/f��P)}File/MARCBASE.phpnu�[���PK��Z5F	'�"�"=}File/MARCXML.phpnu�[���PK��ZSbw�{7{7
�_}File/MARC.phpnu�[���PK��Z�9g4xUxU��}File/MARC/Record.phpnu�[���PK��Z(#�~��h�}File/MARC/Exception.phpnu�[���PK��Z�S��hh5~File/MARC/List.phpnu�[���PK��Z�+�����&~File/MARC/Field.phpnu�[���PK��Z�IC�(A(A�@~File/MARC/Lint/CodeData.phpnu�[���PK��ZR��A;A;a�~File/MARC/Data_Field.phpnu�[���PK��Zlz�`�~File/MARC/Control_Field.phpnu�[���PK��ZɌ5��9�9L�~File/MARC/Lint.phpnu�[���PK��Z7�*c��Y
�File/MARC/Subfield.phpnu�[���PK��Z�1����5a!�test/Structures_LinkedList/tests/single_link_007.phptnu�[���PK��Z�Z�x��5�&�test/Structures_LinkedList/tests/single_link_002.phptnu�[���PK��Z(��  .�)�test/Structures_LinkedList/tests/link_004.phptnu�[���PK��Z���|��5,�test/Structures_LinkedList/tests/SingleLinkTester.phpnu�[���PK��Z髂[��5N.�test/Structures_LinkedList/tests/single_link_006.phptnu�[���PK��Zs��DHH.�2�test/Structures_LinkedList/tests/link_007.phptnu�[���PK��Z�����.E8�test/Structures_LinkedList/tests/link_005.phptnu�[���PK��Z�#,E��5~=�test/Structures_LinkedList/tests/single_link_005.phptnu�[���PK��Z����/�B�test/Structures_LinkedList/tests/LinkTester.phpnu�[���PK��Z� ���.E�test/Structures_LinkedList/tests/link_001.phptnu�[���PK��Z骗���.II�test/Structures_LinkedList/tests/link_006.phptnu�[���PK��Z��)��.�M�test/Structures_LinkedList/tests/link_002.phptnu�[���PK��Z�4����5�P�test/Structures_LinkedList/tests/single_link_001.phptnu�[���PK��Z)�y--5�T�test/Structures_LinkedList/tests/single_link_004.phptnu�[���PK��Z�K��5fW�test/Structures_LinkedList/tests/single_link_003.phptnu�[���PK��Z�o���.�[�test/Structures_LinkedList/tests/link_003.phptnu�[���PK��Z�x`(��`�test/Mail/tests/bug17317.phptnu�[���PK��Z��q/���a�test/Mail/tests/13659.phptnu�[���PK��Z�ó����d�test/Mail/tests/9137_2.phptnu�[���PK��Zw������i�test/Mail/tests/smtp_error.phptnu�[���PK��Z)f$�!!"m�test/Mail/tests/rfc822.phptnu�[���PK��Z8x�����x�test/Mail/tests/bug17178.phptnu�[���PK��Z*�����y�test/Mail/tests/9137.phptnu�[���PK��ZF�}�test/Finder/Symfony/Component/Finder/Tests/Fixtures/with space/foo.txtnu�[���PK��ZAg~�test/Finder/Symfony/Component/Finder/Tests/Fixtures/A/B/C/abc.datnu�[���PK��Z>�~�test/Finder/Symfony/Component/Finder/Tests/Fixtures/A/B/ab.datnu�[���PK��Z;F�test/Finder/Symfony/Component/Finder/Tests/Fixtures/A/a.datnu�[���PK��Z9��test/Finder/Symfony/Component/Finder/Tests/Fixtures/one/anu�[���PK��Z@��test/Finder/Symfony/Component/Finder/Tests/Fixtures/one/b/d.neonnu�[���PK��Z@���test/Finder/Symfony/Component/Finder/Tests/Fixtures/one/b/c.neonnu�[���PK��Zo�5|=���test/Finder/Symfony/Component/Finder/Tests/Fixtures/dolor.txtnu�[���PK��Z'���))=���test/Finder/Symfony/Component/Finder/Tests/Fixtures/ipsum.txtnu�[���PK��Z��55=��test/Finder/Symfony/Component/Finder/Tests/Fixtures/lorem.txtnu�[���PK��ZE���test/Finder/Symfony/Component/Finder/Tests/Fixtures/copy/A/a.dat.copynu�[���PK��ZK1��test/Finder/Symfony/Component/Finder/Tests/Fixtures/copy/A/B/C/abc.dat.copynu�[���PK��ZH���test/Finder/Symfony/Component/Finder/Tests/Fixtures/copy/A/B/ab.dat.copynu�[���PK��Z˟�ׄ	�	L$��test/Finder/Symfony/Component/Finder/Tests/Comparator/DateComparatorTest.phpnu�[���PK��Z�W.�//N$��test/Finder/Symfony/Component/Finder/Tests/Comparator/NumberComparatorTest.phpnu�[���PK��Z��Ŗ�Hќ�test/Finder/Symfony/Component/Finder/Tests/Comparator/ComparatorTest.phpnu�[���PK��Z6G��mwmw9ߤ�test/Finder/Symfony/Component/Finder/Tests/FinderTest.phpnu�[���PK��Z+드44L��test/Finder/Symfony/Component/Finder/Tests/Iterator/RealIteratorTestCase.phpnu�[���PK��Z:@���
�
Me(�test/Finder/Symfony/Component/Finder/Tests/Iterator/FilePathsIteratorTest.phpnu�[���PK��Z�qbe�
�
U�3�test/Finder/Symfony/Component/Finder/Tests/Iterator/FilecontentFilterIteratorTest.phpnu�[���PK��ZYbk�MMR�>�test/Finder/Symfony/Component/Finder/Tests/Iterator/FileTypeFilterIteratorTest.phpnu�[���PK��Z���Ŋ�V�E�test/Finder/Symfony/Component/Finder/Tests/Iterator/RecursiveDirectoryIteratorTest.phpnu�[���PK��Z4/aaZ�N�test/Finder/Symfony/Component/Finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.phpnu�[���PK��Z��nI��N�U�test/Finder/Symfony/Component/Finder/Tests/Iterator/PathFilterIteratorTest.phpnu�[���PK��Z��++V%c�test/Finder/Symfony/Component/Finder/Tests/Iterator/MultiplePcreFilterIteratorTest.phpnu�[���PK��Z�7Wa	a	L�k�test/Finder/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.phpnu�[���PK��Z�7���R�u�test/Finder/Symfony/Component/Finder/Tests/Iterator/FilenameFilterIteratorTest.phpnu�[���PK��Z߫����P-|�test/Finder/Symfony/Component/Finder/Tests/Iterator/CustomFilterIteratorTest.phpnu�[���PK��Z��o�
�
G���test/Finder/Symfony/Component/Finder/Tests/Iterator/MockSplFileInfo.phpnu�[���PK��ZZo�*))Tҏ�test/Finder/Symfony/Component/Finder/Tests/Iterator/DepthRangeFilterIteratorTest.phpnu�[���PK��Z�S�@��test/Finder/Symfony/Component/Finder/Tests/Iterator/Iterator.phpnu�[���PK��Z���FS��test/Finder/Symfony/Component/Finder/Tests/Iterator/SizeRangeFilterIteratorTest.phpnu�[���PK��Z-���66J���test/Finder/Symfony/Component/Finder/Tests/Iterator/FilterIteratorTest.phpnu�[���PK��Z{�)\o	o	H3��test/Finder/Symfony/Component/Finder/Tests/Iterator/IteratorTestCase.phpnu�[���PK��Z�[+((L��test/Finder/Symfony/Component/Finder/Tests/Iterator/MockFileListIterator.phpnu�[���PK��Z(��g==S���test/Finder/Symfony/Component/Finder/Tests/Iterator/DateRangeFilterIteratorTest.phpnu�[���PK��Z�|ߐ�H~��test/Finder/Symfony/Component/Finder/Tests/Expression/ExpressionTest.phpnu�[���PK��Z�9]��C�Ătest/Finder/Symfony/Component/Finder/Tests/Expression/RegexTest.phpnu�[���PK��Z7u��ttB�Ԃtest/Finder/Symfony/Component/Finder/Tests/Expression/GlobTest.phpnu�[���PK��Z`�2��G�ۂtest/Finder/Symfony/Component/Finder/Tests/FakeAdapter/NamedAdapter.phpnu�[���PK��ZI����G�߂test/Finder/Symfony/Component/Finder/Tests/FakeAdapter/DummyAdapter.phpnu�[���PK��Z/��00M4�test/Finder/Symfony/Component/Finder/Tests/FakeAdapter/UnsupportedAdapter.phpnu�[���PK��Z��mmI��test/Finder/Symfony/Component/Finder/Tests/FakeAdapter/FailingAdapter.phpnu�[���PK��Z���555��test/Finder/Symfony/Component/Finder/phpunit.xml.distnu�[���PK��Z9���Ka�test/TwigBridge/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.phpnu�[���PK��Z�O#�''O���test/TwigBridge/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.phpnu�[���PK��Z�h�H	H	@T$�test/TwigBridge/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.phpnu�[���PK��Zͅi�99<.�test/TwigBridge/Symfony/Bridge/Twig/Tests/TwigEngineTest.phpnu�[���PK��Zk�K�a�6�test/TwigBridge/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationDefaultDomainNodeVisitorTest.phpnu�[���PK��Z¶
���TMC�test/TwigBridge/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationNodeVisitorTest.phpnu�[���PK��Zj|$		J�L�test/TwigBridge/Symfony/Bridge/Twig/Tests/NodeVisitor/TwigNodeProvider.phpnu�[���PK��Z�6��!!CAV�test/TwigBridge/Symfony/Bridge/Twig/Tests/NodeVisitor/ScopeTest.phpnu�[���PK��Z#�
�
R�X�test/TwigBridge/Symfony/Bridge/Twig/Tests/TokenParser/FormThemeTokenParserTest.phpnu�[���PK��Z��x��LTg�test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/RoutingExtensionTest.phpnu�[���PK��Z:��WWT�o�test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.phpnu�[���PK��Zt�9A
A
Oq~�test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.phpnu�[���PK��Z�V�%33R1��test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/page_dynamic_extends.html.twignu�[���PK��Z�]��U扃test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubFilesystemLoader.phpnu�[���PK��Z*��n**O���test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubTranslator.phpnu�[���PK��Z̙nsG,��test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/theme_use.html.twignu�[���PK��Z�+����I���test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/CodeExtensionTest.phpnu�[���PK��Z%o��	�	N$��test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/StopwatchExtensionTest.phpnu�[���PK��Z��ߋ��Oe��test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/ExpressionExtensionTest.phpnu�[���PK��Z��,'KKJe��test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/parent_label.html.twignu�[���PK��Z�����P*��test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.phpnu�[���PK��Z(���CNǃtest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/theme.html.twignu�[���PK��Z��i�!!R�ȃtest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.phpnu�[���PK��ZҺ
�VVIS�test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/child_label.html.twignu�[���PK��Z�tdK"�test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/theme_extends.html.twignu�[���PK��Z��b���L��test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/custom_widgets.html.twignu�[���PK��ZPcc4��test/TwigBridge/Symfony/Bridge/Twig/phpunit.xml.distnu�[���PK��Zh�9=UUO��test/Translation/Symfony/Component/Translation/Tests/IdentityTranslatorTest.phpnu�[���PK��Z���*|1|1Gr��test/Translation/Symfony/Component/Translation/Tests/TranslatorTest.phpnu�[���PK��Zl.!���Oe)�test/Translation/Symfony/Component/Translation/Tests/PluralizationRulesTest.phpnu�[���PK��Z�h�l��T�9�test/Translation/Symfony/Component/Translation/Tests/Catalogue/DiffOperationTest.phpnu�[���PK��Z$͒ϛ�U�A�test/Translation/Symfony/Component/Translation/Tests/Catalogue/MergeOperationTest.phpnu�[���PK��Zײ�))X�I�test/Translation/Symfony/Component/Translation/Tests/Catalogue/AbstractOperationTest.phpnu�[���PK��Z0�2��E�R�test/Translation/Symfony/Component/Translation/Tests/IntervalTest.phpnu�[���PK��Z��V��Q�W�test/Translation/Symfony/Component/Translation/Tests/Dumper/IniFileDumperTest.phpnu�[���PK��Z`��׹�S�[�test/Translation/Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.phpnu�[���PK��Z����Q`�test/Translation/Symfony/Component/Translation/Tests/Dumper/PhpFileDumperTest.phpnu�[���PK��Z����R5d�test/Translation/Symfony/Component/Translation/Tests/Dumper/YamlFileDumperTest.phpnu�[���PK��Zub/��TZh�test/Translation/Symfony/Component/Translation/Tests/Dumper/IcuResFileDumperTest.phpnu�[���PK��Z�����Q�m�test/Translation/Symfony/Component/Translation/Tests/Dumper/CsvFileDumperTest.phpnu�[���PK��Z�����P�q�test/Translation/Symfony/Component/Translation/Tests/Dumper/MoFileDumperTest.phpnu�[���PK��Z�BY���P�u�test/Translation/Symfony/Component/Translation/Tests/Dumper/QtFileDumperTest.phpnu�[���PK��Z��IIRz�test/Translation/Symfony/Component/Translation/Tests/Dumper/JsonFileDumperTest.phpnu�[���PK��Z&��ݙ�P�~�test/Translation/Symfony/Component/Translation/Tests/Dumper/PoFileDumperTest.phpnu�[���PK��Z8^�k��S�test/Translation/Symfony/Component/Translation/Tests/Loader/XliffFileLoaderTest.phpnu�[���PK��Z��|=��P��test/Translation/Symfony/Component/Translation/Tests/Loader/QtFileLoaderTest.phpnu�[���PK��Z���3Q$��test/Translation/Symfony/Component/Translation/Tests/Loader/LocalizedTestCase.phpnu�[���PK��Z���Q���test/Translation/Symfony/Component/Translation/Tests/Loader/PhpFileLoaderTest.phpnu�[���PK��Z~�		RS��test/Translation/Symfony/Component/Translation/Tests/Loader/YamlFileLoaderTest.phpnu�[���PK��Z�$X

P�test/Translation/Symfony/Component/Translation/Tests/Loader/PoFileLoaderTest.phpnu�[���PK��Z[����Q���test/Translation/Symfony/Component/Translation/Tests/Loader/CsvFileLoaderTest.phpnu�[���PK��Z/�݂�Q���test/Translation/Symfony/Component/Translation/Tests/Loader/IniFileLoaderTest.phpnu�[���PK��Z��j��T�Ȅtest/Translation/Symfony/Component/Translation/Tests/Loader/IcuResFileLoaderTest.phpnu�[���PK��ZP�e��RЄtest/Translation/Symfony/Component/Translation/Tests/Loader/JsonFileLoaderTest.phpnu�[���PK��Z����Pلtest/Translation/Symfony/Component/Translation/Tests/Loader/MoFileLoaderTest.phpnu�[���PK��Z�)�	�	�	T��test/Translation/Symfony/Component/Translation/Tests/Loader/IcuDatFileLoaderTest.phpnu�[���PK��ZM��MD�test/Translation/Symfony/Component/Translation/Tests/MessageCatalogueTest.phpnu�[���PK��Z���  L��test/Translation/Symfony/Component/Translation/Tests/MessageSelectorTest.phpnu�[���PK��Z��W44Jx �test/Translation/Symfony/Component/Translation/Tests/fixtures/resources.monu�[���PK��Z!f����J&!�test/Translation/Symfony/Component/Translation/Tests/fixtures/resources.ponu�[���PK��Z=BsR-"�test/Translation/Symfony/Component/Translation/Tests/fixtures/empty-translation.ponu�[���PK��ZG�"�test/Translation/Symfony/Component/Translation/Tests/fixtures/empty.ininu�[���PK��ZYڸCQ=#�test/Translation/Symfony/Component/Translation/Tests/fixtures/resources-clean.xlfnu�[���PK��Z�:�++K�%�test/Translation/Symfony/Component/Translation/Tests/fixtures/resources.phpnu�[���PK��ZGg&�test/Translation/Symfony/Component/Translation/Tests/fixtures/empty.ymlnu�[���PK��ZH�&�test/Translation/Symfony/Component/Translation/Tests/fixtures/empty.jsonnu�[���PK��ZY���44IV'�test/Translation/Symfony/Component/Translation/Tests/fixtures/resname.xlfnu�[���PK��ZG*�test/Translation/Symfony/Component/Translation/Tests/fixtures/empty.xlfnu�[���PK��Z;.�BBHz*�test/Translation/Symfony/Component/Translation/Tests/fixtures/plurals.ponu�[���PK��Z�ߞL4+�test/Translation/Symfony/Component/Translation/Tests/fixtures/malformed.jsonnu�[���PK��Z�.�zzK�+�test/Translation/Symfony/Component/Translation/Tests/fixtures/resources.xlfnu�[���PK��Z�e2~K�.�test/Translation/Symfony/Component/Translation/Tests/fixtures/non-valid.ymlnu�[���PK��Z�'�F

K:/�test/Translation/Symfony/Component/Translation/Tests/fixtures/resources.ininu�[���PK��Z� TTK�/�test/Translation/Symfony/Component/Translation/Tests/fixtures/non-valid.xlfnu�[���PK��ZF�1�test/Translation/Symfony/Component/Translation/Tests/fixtures/empty.ponu�[���PK��ZG2�test/Translation/Symfony/Component/Translation/Tests/fixtures/empty.csvnu�[���PK��Z*֔�JJH{2�test/Translation/Symfony/Component/Translation/Tests/fixtures/plurals.monu�[���PK��Z+�L�TTW=3�test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/res/en.resnu�[���PK��Zw˦(||W4�test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/fr.resnu�[���PK��ZX��**W5�test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/fr.txtnu�[���PK��ZrQ�``^�5�test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/resources.datnu�[���PK��Z�M�RxxW�7�test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/en.resnu�[���PK��Z�g.�`�8�test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/packagelist.txtnu�[���PK��Z�25�''WW9�test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/en.txtnu�[���PK��Z��<�d:�test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/corrupted/resources.datnu�[���PK��ZF�:�test/Translation/Symfony/Component/Translation/Tests/fixtures/empty.monu�[���PK��Z��jjM;�test/Translation/Symfony/Component/Translation/Tests/fixtures/withdoctype.xlfnu�[���PK��Z̉^2��J�<�test/Translation/Symfony/Component/Translation/Tests/fixtures/encoding.xlfnu�[���PK��Z�B$$G@?�test/Translation/Symfony/Component/Translation/Tests/fixtures/valid.csvnu�[���PK��Z����L�?�test/Translation/Symfony/Component/Translation/Tests/fixtures/resources.jsonnu�[���PK��Z�C(���Jk@�test/Translation/Symfony/Component/Translation/Tests/fixtures/resources.tsnu�[���PK��Z/�
��W�A�test/Translation/Symfony/Component/Translation/Tests/fixtures/invalid-xml-resources.xlfnu�[���PK��Z���		KE�test/Translation/Symfony/Component/Translation/Tests/fixtures/resources.ymlnu�[���PK��Z�D��``K�E�test/Translation/Symfony/Component/Translation/Tests/fixtures/resources.csvnu�[���PK��Z^C�	::?{F�test/Translation/Symfony/Component/Translation/phpunit.xml.distnu�[���PK��Z���LLE$J�test/Routing/Symfony/Component/Routing/Tests/Annotation/RouteTest.phpnu�[���PK��Z�%��])])B�P�test/Routing/Symfony/Component/Routing/Tests/RouteCompilerTest.phpnu�[���PK��Z1�d	nnM�z�test/Routing/Symfony/Component/Routing/Tests/Fixtures/CustomXmlFileLoader.phpnu�[���PK��ZC�}�test/Routing/Symfony/Component/Routing/Tests/Fixtures/annotated.phpnu�[���PK��Z?~�test/Routing/Symfony/Component/Routing/Tests/Fixtures/empty.ymlnu�[���PK��Z�/���F�~�test/Routing/Symfony/Component/Routing/Tests/Fixtures/validpattern.ymlnu�[���PK��Z�M��Fہ�test/Routing/Symfony/Component/Routing/Tests/Fixtures/validpattern.xmlnu�[���PK��Z�/�$>>V	��test/Routing/Symfony/Component/Routing/Tests/Fixtures/nonesense_resource_plus_path.ymlnu�[���PK��Z��==F͇�test/Routing/Symfony/Component/Routing/Tests/Fixtures/nonvalidkeys.ymlnu�[���PK��Z�ie��I���test/Routing/Symfony/Component/Routing/Tests/Fixtures/namespaceprefix.xmlnu�[���PK��Z#q��//D���test/Routing/Symfony/Component/Routing/Tests/Fixtures/missing_id.xmlnu�[���PK��Zx'�	11EZ��test/Routing/Symfony/Component/Routing/Tests/Fixtures/withdoctype.xmlnu�[���PK��Z�;h�%%P��test/Routing/Symfony/Component/Routing/Tests/Fixtures/RedirectableUrlMatcher.phpnu�[���PK��Zs��[//F���test/Routing/Symfony/Component/Routing/Tests/Fixtures/missing_path.xmlnu�[���PK��Z�e2~BJ��test/Routing/Symfony/Component/Routing/Tests/Fixtures/nonvalid.ymlnu�[���PK��Zix��77F���test/Routing/Symfony/Component/Routing/Tests/Fixtures/validpattern.phpnu�[���PK��Z�G�V,+,+Mm��test/Routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.phpnu�[���PK��ZT����MÅtest/Routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.phpnu�[���PK��Z@4��P9Ʌtest/Routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.apachenu�[���PK��ZBx�6��P�߅test/Routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.apachenu�[���PK��Zn�k�//M�test/Routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.phpnu�[���PK��Z�p��B��test/Routing/Symfony/Component/Routing/Tests/Fixtures/nonvalid.xmlnu�[���PK��Zͼ�n!!F��test/Routing/Symfony/Component/Routing/Tests/Fixtures/nonvalidnode.xmlnu�[���PK��ZT��Se�test/Routing/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/BarClass.phpnu�[���PK��Z���GGS��test/Routing/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/FooClass.phpnu�[���PK��Z�zUUX^�test/Routing/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/AbstractClass.phpnu�[���PK��Z�M�tC;�test/Routing/Symfony/Component/Routing/Tests/Fixtures/nonvalid2.ymlnu�[���PK��Z�b�G��test/Routing/Symfony/Component/Routing/Tests/Fixtures/validresource.xmlnu�[���PK��Z��q�GN�test/Routing/Symfony/Component/Routing/Tests/Fixtures/nonvalidroute.xmlnu�[���PK��Z��ϮBBD��test/Routing/Symfony/Component/Routing/Tests/Fixtures/incomplete.ymlnu�[���PK��Z�J?�L� �test/Routing/Symfony/Component/Routing/Tests/Fixtures/special_route_name.ymlnu�[���PK��Z�q�99Y2!�test/Routing/Symfony/Component/Routing/Tests/Fixtures/nonesense_type_without_resource.ymlnu�[���PK��ZjX���G�!�test/Routing/Symfony/Component/Routing/Tests/Fixtures/validresource.ymlnu�[���PK��Z>^#�test/Routing/Symfony/Component/Routing/Tests/Fixtures/foo1.xmlnu�[���PK��Z=�#�test/Routing/Symfony/Component/Routing/Tests/Fixtures/foo.xmlnu�[���PK��Z��/��
�
C9$�test/Routing/Symfony/Component/Routing/Tests/RequestContextTest.phpnu�[���PK��Z���
�
P�2�test/Routing/Symfony/Component/Routing/Tests/Matcher/TraceableUrlMatcherTest.phpnu�[���PK��Zt�kT�B�BG�@�test/Routing/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.phpnu�[���PK��Zȁ@���Z���test/Routing/Symfony/Component/Routing/Tests/Matcher/Dumper/DumperPrefixCollectionTest.phpnu�[���PK��Z)�#0%%T>��test/Routing/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.phpnu�[���PK��ZU���Tù�test/Routing/Symfony/Component/Routing/Tests/Matcher/Dumper/DumperCollectionTest.phpnu�[���PK��Z�IQ��W&��test/Routing/Symfony/Component/Routing/Tests/Matcher/Dumper/ApacheMatcherDumperTest.phpnu�[���PK��Z�̼�aaM�׆test/Routing/Symfony/Component/Routing/Tests/Matcher/ApacheUrlMatcherTest.phpnu�[���PK��ZA ���Sr�test/Routing/Symfony/Component/Routing/Tests/Matcher/RedirectableUrlMatcherTest.phpnu�[���PK��Z%"�?7?7D��test/Routing/Symfony/Component/Routing/Tests/RouteCollectionTest.phpnu�[���PK��Z kl�g�gKM,�test/Routing/Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.phpnu�[���PK��Z������Xo��test/Routing/Symfony/Component/Routing/Tests/Generator/Dumper/PhpGeneratorDumperTest.phpnu�[���PK��Z8!!&GGB餇test/Routing/Symfony/Component/Routing/Tests/CompiledRouteTest.phpnu�[���PK��Z���k��I���test/Routing/Symfony/Component/Routing/Tests/Loader/ClosureLoaderTest.phpnu�[���PK��Z�����Q寇test/Routing/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTest.phpnu�[���PK��Zg�U��I3Çtest/Routing/Symfony/Component/Routing/Tests/Loader/PhpFileLoaderTest.phpnu�[���PK��Z{��t��Jdˇtest/Routing/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.phpnu�[���PK��Z6����U_݇test/Routing/Symfony/Component/Routing/Tests/Loader/AnnotationDirectoryLoaderTest.phpnu�[���PK��ZM�~�##I��test/Routing/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.phpnu�[���PK��Z|�C44T*��test/Routing/Symfony/Component/Routing/Tests/Loader/AbstractAnnotationLoaderTest.phpnu�[���PK��Zu��;P�test/Routing/Symfony/Component/Routing/Tests/Loader/AnnotationFileLoaderTest.phpnu�[���PK��Z��;b�test/Routing/Symfony/Component/Routing/Tests/RouterTest.phpnu�[���PK��Zu��A�,�,:��test/Routing/Symfony/Component/Routing/Tests/RouteTest.phpnu�[���PK��Z~�6673E�test/Routing/Symfony/Component/Routing/phpunit.xml.distnu�[���PK��Z��W8j#j#.�H�test/Structures_Graph/tests/BasicGraphTest.phpnu�[���PK��Z6��:UU5�l�test/Structures_Graph/tests/TopologicalSorterTest.phpnu�[���PK��Z�V���(Rt�test/Structures_Graph/tests/AllTests.phpnu�[���PK��Z���/fv�test/Structures_Graph/tests/AcyclicTestTest.phpnu�[���PK��Z���ii&�{�test/Structures_Graph/tests/helper.incnu�[���PK��Z��+\MMH�}�test/Process/Symfony/Component/Process/Tests/PhpExecutableFinderTest.phpnu�[���PK��Z#�Te��test/Process/Symfony/Component/Process/Tests/PipeStdinInStdoutStdErrStreamSelect.phpnu�[���PK��Z�WKo�
�
Ktest/Process/Symfony/Component/Process/Tests/ProcessFailedExceptionTest.phpnu�[���PK��ZC�u^UUA���test/Process/Symfony/Component/Process/Tests/ProcessUtilsTest.phpnu�[���PK��Z[�VAChChDÜ�test/Process/Symfony/Component/Process/Tests/AbstractProcessTest.phpnu�[���PK��Z=�,j��?z�test/Process/Symfony/Component/Process/Tests/SignalListener.phpnu�[���PK��Z���
��B��test/Process/Symfony/Component/Process/Tests/SimpleProcessTest.phpnu�[���PK��Z�+�v,,CR �test/Process/Symfony/Component/Process/Tests/NonStopableProcess.phpnu�[���PK��Zm�����M�#�test/Process/Symfony/Component/Process/Tests/ProcessInSigchildEnvironment.phpnu�[���PK��Z����L3&�test/Process/Symfony/Component/Process/Tests/SigchildDisabledProcessTest.phpnu�[���PK��ZH��sppC^F�test/Process/Symfony/Component/Process/Tests/ProcessBuilderTest.phpnu�[���PK��Zx[��?A^�test/Process/Symfony/Component/Process/Tests/PhpProcessTest.phpnu�[���PK��Z钊�\\KQa�test/Process/Symfony/Component/Process/Tests/SigchildEnabledProcessTest.phpnu�[���PK��Zp\H7(s�test/Process/Symfony/Component/Process/phpunit.xml.distnu�[���PK��Z2�c�$�$E�v�test/Serializer/Symfony/Component/Serializer/Tests/SerializerTest.phpnu�[���PK��Z�m�))P̛�test/Serializer/Symfony/Component/Serializer/Tests/Normalizer/TestNormalizer.phpnu�[���PK��Z$ѕ�Vu��test/Serializer/Symfony/Component/Serializer/Tests/Normalizer/CustomNormalizerTest.phpnu�[���PK��Z��P1!!\��test/Serializer/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.phpnu�[���PK��Z�qBBR�ɉtest/Serializer/Symfony/Component/Serializer/Tests/Normalizer/TestDenormalizer.phpnu�[���PK��Z��K�__Ku͉test/Serializer/Symfony/Component/Serializer/Tests/Fixtures/ScalarDummy.phpnu�[���PK��Z��_��PO҉test/Serializer/Symfony/Component/Serializer/Tests/Fixtures/TraversableDummy.phpnu�[���PK��ZG��5��\�ԉtest/Serializer/Symfony/Component/Serializer/Tests/Fixtures/NormalizableTraversableDummy.phpnu�[���PK��Z�LY��E�ىtest/Serializer/Symfony/Component/Serializer/Tests/Fixtures/Dummy.phpnu�[���PK��ZY["�uuS9߉test/Serializer/Symfony/Component/Serializer/Tests/Fixtures/DenormalizableDummy.phpnu�[���PK��Zf|�B.B.M1�test/Serializer/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.phpnu�[���PK��ZF��		N��test/Serializer/Symfony/Component/Serializer/Tests/Encoder/JsonEncoderTest.phpnu�[���PK��Z���99=s�test/Serializer/Symfony/Component/Serializer/phpunit.xml.distnu�[���PK��Z�Ǫ���9�test/Locale/Symfony/Component/Locale/Tests/LocaleTest.phpnu�[���PK��Z<��B%�test/Locale/Symfony/Component/Locale/Tests/Stub/StubLocaleTest.phpnu�[���PK��Z+��hh5�+�test/Locale/Symfony/Component/Locale/phpunit.xml.distnu�[���PK��Z�;�I_/�test/Filesystem/Symfony/Component/Filesystem/Tests/FilesystemTestCase.phpnu�[���PK��Z'B 0�o�oE�=�test/Filesystem/Symfony/Component/Filesystem/Tests/FilesystemTest.phpnu�[���PK��Z��í�D ��test/Filesystem/Symfony/Component/Filesystem/Tests/ExceptionTest.phpnu�[���PK��Z�Ejc		=��test/Filesystem/Symfony/Component/Filesystem/phpunit.xml.distnu�[���PK��Z�ag�@<@<B���test/Form/Symfony/Component/Form/Tests/AbstractTableLayoutTest.phpnu�[���PK��Z���KKB=�test/Form/Symfony/Component/Form/Tests/FormPerformanceTestCase.phpnu�[���PK��Z@U���=���test/Form/Symfony/Component/Form/Tests/AbstractLayoutTest.phpnu�[���PK��Z����:lڋtest/Form/Symfony/Component/Form/Tests/Guess/GuessTest.phpnu�[���PK��Z�uEsދtest/Form/Symfony/Component/Form/Tests/Fixtures/CustomArrayObject.phpnu�[���PK��Z�x���:��test/Form/Symfony/Component/Form/Tests/Fixtures/Author.phpnu�[���PK��Z3X�test/Form/Symfony/Component/Form/Tests/Fixtures/foonu�[���PK��Z[��َ�G��test/Form/Symfony/Component/Form/Tests/Fixtures/FooTypeBazExtension.phpnu�[���PK��Z���*��;��test/Form/Symfony/Component/Form/Tests/Fixtures/FooType.phpnu�[���PK��Z:�.z��F�test/Form/Symfony/Component/Form/Tests/Fixtures/AlternatingRowType.phpnu�[���PK��Z֫�v��>��test/Form/Symfony/Component/Form/Tests/Fixtures/AuthorType.phpnu�[���PK��Z#�o>��test/Form/Symfony/Component/Form/Tests/Fixtures/FooSubType.phpnu�[���PK��Z��8���A6��test/Form/Symfony/Component/Form/Tests/Fixtures/TestExtension.phpnu�[���PK��Z��x�

GO�test/Form/Symfony/Component/Form/Tests/Fixtures/FooTypeBarExtension.phpnu�[���PK��Zm^�2++P��test/Form/Symfony/Component/Form/Tests/Fixtures/FooSubTypeWithParentInstance.phpnu�[���PK��Z��!u��G~	�test/Form/Symfony/Component/Form/Tests/Fixtures/FixedFilterListener.phpnu�[���PK��ZŲ��UUH��test/Form/Symfony/Component/Form/Tests/Fixtures/FixedDataTransformer.phpnu�[���PK��ZJ����R�R:X�test/Form/Symfony/Component/Form/Tests/FormFactoryTest.phpnu�[���PK��ZȔfVA6A6Bgh�test/Form/Symfony/Component/Form/Tests/Util/OrderedHashMapTest.phpnu�[���PK��Z�z�nznz;��test/Form/Symfony/Component/Form/Tests/CompoundFormTest.phpnu�[���PK��Z���dA��test/Form/Symfony/Component/Form/Tests/FormFactoryBuilderTest.phpnu�[���PK��Z̈́����;g!�test/Form/Symfony/Component/Form/Tests/FormRegistryTest.phpnu�[���PK��Z]�9�}}9�@�test/Form/Symfony/Component/Form/Tests/FormConfigTest.phpnu�[���PK��Z�>)�bbE�S�test/Form/Symfony/Component/Form/Tests/AbstractRequestHandlerTest.phpnu�[���PK��Zū@d22?xq�test/Form/Symfony/Component/Form/Tests/ResolvedFormTypeTest.phpnu�[���PK��ZO� )KKB���test/Form/Symfony/Component/Form/Tests/FormIntegrationTestCase.phpnu�[���PK��Z��K)ooF���test/Form/Symfony/Component/Form/Tests/CompoundFormPerformanceTest.phpnu�[���PK��Ztٴ��;���test/Form/Symfony/Component/Form/Tests/FormRendererTest.phpnu�[���PK��Z�d�!!C⯍test/Form/Symfony/Component/Form/Tests/NativeRequestHandlerTest.phpnu�[���PK��Z�����:vǍtest/Form/Symfony/Component/Form/Tests/FormBuilderTest.phpnu�[���PK��ZRmhZTZT@��test/Form/Symfony/Component/Form/Tests/AbstractDivLayoutTest.phpnu�[���PK��Zk/6;}8�test/Form/Symfony/Component/Form/Tests/AbstractFormTest.phpnu�[���PK��ZrM�{�{9�D�test/Form/Symfony/Component/Form/Tests/SimpleFormTest.phpnu�[���PK��Zۿt��c��test/Form/Symfony/Component/Form/Tests/Extension/Validator/EventListener/ValidationListenerTest.phpnu�[���PK��Z�EY޵�T�Վtest/Form/Symfony/Component/Form/Tests/Extension/Validator/Util/ServerParamsTest.phpnu�[���PK��Z�l"�	�	W�ێtest/Form/Symfony/Component/Form/Tests/Extension/Validator/ValidatorTypeGuesserTest.phpnu�[���PK��Z��
g��test/Form/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorPerformanceTest.phpnu�[���PK��Zِ�GbGb\��test/Form/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.phpnu�[���PK��Z�$�Ǵ�`TN�test/Form/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationPathTest.phpnu�[���PK��Z�@1�,�,b�l�test/Form/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.phpnu�[���PK��Z`f�[��P˙�test/Form/Symfony/Component/Form/Tests/Extension/Validator/Type/TypeTestCase.phpnu�[���PK��ZY��
xx^��test/Form/Symfony/Component/Form/Tests/Extension/Validator/Type/BaseValidatorExtensionTest.phpnu�[���PK��ZS�m�d��test/Form/Symfony/Component/Form/Tests/Extension/Validator/Type/SubmitTypeValidatorExtensionTest.phpnu�[���PK��Z7>lˉ�b���test/Form/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.phpnu�[���PK��Z1���� � i���test/Form/Symfony/Component/Form/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.phpnu�[���PK��Zf͍ffdґtest/Form/Symfony/Component/Form/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.phpnu�[���PK��Z%u����^�ؑtest/Form/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/SessionCsrfProviderTest.phpnu�[���PK��Z_Nn���^�test/Form/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/DefaultCsrfProviderTest.phpnu�[���PK��Z�A��b��test/Form/Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.phpnu�[���PK��Z�L?��.�.X��test/Form/Symfony/Component/Form/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.phpnu�[���PK��Z��܏##WN"�test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/Fixtures/randomhashnu�[���PK��Z��**a�"�test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.phpnu�[���PK��Z��!��$�$^�/�test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/ResizeFormListenerTest.phpnu�[���PK��Zfk5s3	3	X)U�test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/TrimListenerTest.phpnu�[���PK��ZB+�K��n�^�test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayObjectTest.phpnu�[���PK��Z�@ڦt-b�test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerCustomArrayObjectTest.phpnu�[���PK��ZЭ
���h�e�test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayTest.phpnu�[���PK��Z��ggbi�test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.phpnu�[���PK��Z�O�&c	p�test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.phpnu�[���PK��Z���� � Y���test/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.phpnu�[���PK��Z�.�p))S<��test/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ChoiceListTest.phpnu�[���PK��Z�![���[�Ētest/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.phpnu�[���PK��Z�gUI��WJ�test/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.phpnu�[���PK��ZR��
�
Yv�test/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.phpnu�[���PK��Z��x��`���test/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.phpnu�[���PK��Z?�R8�.�.[��test/Form/Symfony/Component/Form/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.phpnu�[���PK��Z���4��f/7�test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ChoiceToValueTransformerTest.phpnu�[���PK��Z�����qx?�test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.phpnu�[���PK��ZWs�**r�N�test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.phpnu�[���PK��Z�Ub,,Zoy�test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeTestCase.phpnu�[���PK��Z�}��!
!
l%|�test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToTimestampTransformerTest.phpnu�[���PK��Z��=�C?C?h≓test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToArrayTransformerTest.phpnu�[���PK��Z���e�ɓtest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ArrayToPartsTransformerTest.phpnu�[���PK��Z\R��bSؓtest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DataTransformerChainTest.phpnu�[���PK��Z�6���hl�test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.phpnu�[���PK��ZY@zjjo��test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.phpnu�[���PK��Z]e"��j��test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.phpnu�[���PK��ZN�z.z.q��test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.phpnu�[���PK��Z��`nonop�3�test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.phpnu�[���PK��Z�?+�<<j��test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ValueToDuplicatesTransformerTest.phpnu�[���PK��ZfJ��eٯ�test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BaseDateTimeTransformerTest.phpnu�[���PK��Z�.bc))hv��test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ChoicesToValuesTransformerTest.phpnu�[���PK��ZJW����i7��test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.phpnu�[���PK��Z��W@@O�ؔtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/LanguageTypeTest.phpnu�[���PK��Zx���aaM~ߔtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/LocaleTypeTest.phpnu�[���PK��Z�C���M\�test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/ButtonTypeTest.phpnu�[���PK��Z�'�\�\KZ�test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.phpnu�[���PK��Zvzw�LLQWD�test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.phpnu�[���PK��Z�(��__O$_�test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/PasswordTypeTest.phpnu�[���PK��Zx�=�t=t=Oe�test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.phpnu�[���PK��ZP�!���J���test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/UrlTypeTest.phpnu�[���PK��ZX�:::K/��test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/TypeTestCase.phpnu�[���PK��Z����N䬕test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/CountryTypeTest.phpnu�[���PK��Z�_*G��X���test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypePerformanceTest.phpnu�[���PK��Z�{MK��K>��test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/BaseTypeTest.phpnu�[���PK��Zސ/���Oaʕtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/TimezoneTypeTest.phpnu�[���PK��ZdwҢSJSJK�Εtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.phpnu�[���PK��Z/����L��test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/MoneyTypeTest.phpnu�[���PK��Z���J��M� �test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/NumberTypeTest.phpnu�[���PK��Z�}�C%%Md(�test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/SubmitTypeTest.phpnu�[���PK��Z�!]i00O/�test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/CurrencyTypeTest.phpnu�[���PK��Z�IJ��O�3�test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/CheckboxTypeTest.phpnu�[���PK��Z�ñI��O�F�test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/RepeatedTypeTest.phpnu�[���PK��Zk�ƅ��N$\�test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/IntegerTypeTest.phpnu�[���PK��ZI��E����M�_�test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.phpnu�[���PK��Z�jGgJgJK��test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.phpnu�[���PK��Z&����K�M�test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.phpnu�[���PK��Z����>�>XW�test/Form/Symfony/Component/Form/Tests/Extension/DataCollector/FormDataCollectorTest.phpnu�[���PK��Zb�,�<<]���test/Form/Symfony/Component/Form/Tests/Extension/DataCollector/DataCollectorExtensionTest.phpnu�[���PK��Z�{�(�,�,XT��test/Form/Symfony/Component/Form/Tests/Extension/DataCollector/FormDataExtractorTest.phpnu�[���PK��Z��q��f�ɗtest/Form/Symfony/Component/Form/Tests/Extension/DataCollector/Type/DataCollectorTypeExtensionTest.phpnu�[���PK��Z�'�@�ϗtest/Form/Symfony/Component/Form/Tests/AbstractExtensionTest.phpnu�[���PK��Z�g	�331bԗtest/Form/Symfony/Component/Form/phpunit.xml.distnu�[���PK��Z�ԍZP5P5I�חtest/Security/Symfony/Component/Security/Acl/Tests/Voter/AclVoterTest.phpnu�[���PK��Z�޻>�Q�QR�
�test/Security/Symfony/Component/Security/Acl/Tests/Dbal/MutableAclProviderTest.phpnu�[���PK��Z�
�� � T�_�test/Security/Symfony/Component/Security/Acl/Tests/Dbal/AclProviderBenchmarkTest.phpnu�[���PK��Z�'(��'�'K��test/Security/Symfony/Component/Security/Acl/Tests/Dbal/AclProviderTest.phpnu�[���PK��Z�ˆ5M=��test/Security/Symfony/Component/Security/Acl/Tests/Domain/AuditLoggerTest.phpnu�[���PK��Z6x�}&&Ḻ�test/Security/Symfony/Component/Security/Acl/Tests/Domain/FieldEntryTest.phpnu�[���PK��Z��+&Pn��test/Security/Symfony/Component/Security/Acl/Tests/Domain/ObjectIdentityTest.phpnu�[���PK��Z_�~��aʘtest/Security/Symfony/Component/Security/Acl/Tests/Domain/ObjectIdentityRetrievalStrategyTest.phpnu�[���PK��Z��HHRϘtest/Security/Symfony/Component/Security/Acl/Tests/Domain/DoctrineAclCacheTest.phpnu�[���PK��Z��v��\�ۘtest/Security/Symfony/Component/Security/Acl/Tests/Domain/PermissionGrantingStrategyTest.phpnu�[���PK��Z/bAbAEo��test/Security/Symfony/Component/Security/Acl/Tests/Domain/AclTest.phpnu�[���PK��Z5�VF8�test/Security/Symfony/Component/Security/Acl/Tests/Domain/RoleSecurityIdentityTest.phpnu�[���PK��Z��a((VK?�test/Security/Symfony/Component/Security/Acl/Tests/Domain/UserSecurityIdentityTest.phpnu�[���PK��Z�am��c�J�test/Security/Symfony/Component/Security/Acl/Tests/Domain/SecurityIdentityRetrievalStrategyTest.phpnu�[���PK��ZF��@�
�
Gh�test/Security/Symfony/Component/Security/Acl/Tests/Domain/EntryTest.phpnu�[���PK��Z���yyX.v�test/Security/Symfony/Component/Security/Acl/Tests/Permission/BasicPermissionMapTest.phpnu�[���PK��ZeE���Q/y�test/Security/Symfony/Component/Security/Acl/Tests/Permission/MaskBuilderTest.phpnu�[���PK��Zܲ#&;;=���test/Security/Symfony/Component/Security/Acl/phpunit.xml.distnu�[���PK��ZC��)!"!"V9��test/Security/Symfony/Component/Security/Tests/Http/Firewall/ExceptionListenerTest.phpnu�[���PK��Zs�f�[[L૙test/Security/Symfony/Component/Security/Tests/Core/User/UserCheckerTest.phpnu�[���PK��Z����!!U���test/Security/Symfony/Component/Security/Tests/Core/User/InMemoryUserProviderTest.phpnu�[���PK��Z2�nBB`]Ùtest/Security/Symfony/Component/Security/Tests/Core/Authentication/Token/RememberMeTokenTest.phpnu�[���PK��Z9�#�		9/̙test/Security/Symfony/Component/Security/phpunit.xml.distnu�[���PK��Zg3�%%D�Йtest/Security/Symfony/Component/Security/Http/Tests/FirewallTest.phpnu�[���PK��Z��+MbbG:�test/Security/Symfony/Component/Security/Http/Tests/FirewallMapTest.phpnu�[���PK��Z����%�%E�test/Security/Symfony/Component/Security/Http/Tests/HttpUtilsTest.phpnu�[���PK��Z�ck�~
~
c	�test/Security/Symfony/Component/Security/Http/Tests/EntryPoint/FormAuthenticationEntryPointTest.phpnu�[���PK��Ze���d"�test/Security/Symfony/Component/Security/Http/Tests/EntryPoint/BasicAuthenticationEntryPointTest.phpnu�[���PK��Z-Ɔ��dq(�test/Security/Symfony/Component/Security/Http/Tests/EntryPoint/RetryAuthenticationEntryPointTest.phpnu�[���PK��ZGrT�		e�0�test/Security/Symfony/Component/Security/Http/Tests/EntryPoint/DigestAuthenticationEntryPointTest.phpnu�[���PK��ZҒ)��WF:�test/Security/Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.phpnu�[���PK��Z�G��

T�O�test/Security/Symfony/Component/Security/Http/Tests/Firewall/ChannelListenerTest.phpnu�[���PK��Z�e��
�
d>h�test/Security/Symfony/Component/Security/Http/Tests/Firewall/AnonymousAuthenticationListenerTest.phpnu�[���PK��Z��K�$$`_s�test/Security/Symfony/Component/Security/Http/Tests/Firewall/BasicAuthenticationListenerTest.phpnu�[���PK��Z��l���O�test/Security/Symfony/Component/Security/Http/Tests/Firewall/DigestDataTest.phpnu�[���PK��Zj�z9�"�"TC��test/Security/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.phpnu�[���PK��Z<��%%ezךtest/Security/Symfony/Component/Security/Http/Tests/Firewall/AbstractPreAuthenticatedListenerTest.phpnu�[���PK��Zq���S%��test/Security/Symfony/Component/Security/Http/Tests/Firewall/AccessListenerTest.phpnu�[���PK��Z�V�k��S��test/Security/Symfony/Component/Security/Http/Tests/Firewall/LogoutListenerTest.phpnu�[���PK��Z���@&@&W�8�test/Security/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.phpnu�[���PK��Z�LMM_�_�test/Security/Symfony/Component/Security/Http/Tests/Firewall/X509AuthenticationListenerTest.phpnu�[���PK��Zx��W��Evn�test/Security/Symfony/Component/Security/Http/Tests/AccessMapTest.phpnu�[���PK��Z���F8F8mu�test/Security/Symfony/Component/Security/Http/Tests/RememberMe/PersistentTokenBasedRememberMeServicesTest.phpnu�[���PK��Z�䗥1#1#ab��test/Security/Symfony/Component/Security/Http/Tests/RememberMe/AbstractRememberMeServicesTest.phpnu�[���PK��Z�gZ)Z)c$қtest/Security/Symfony/Component/Security/Http/Tests/RememberMe/TokenBasedRememberMeServicesTest.phpnu�[���PK��Z��ʅ
�
W��test/Security/Symfony/Component/Security/Http/Tests/RememberMe/ResponseListenerTest.phpnu�[���PK��ZY�Ң	�	a�test/Security/Symfony/Component/Security/Http/Tests/Session/SessionAuthenticationStrategyTest.phpnu�[���PK��Z�
{{^P�test/Security/Symfony/Component/Security/Http/Tests/Logout/DefaultLogoutSuccessHandlerTest.phpnu�[���PK��Z]�ͷ��WY�test/Security/Symfony/Component/Security/Http/Tests/Logout/SessionLogoutHandlerTest.phpnu�[���PK��Zk��^��test/Security/Symfony/Component/Security/Http/Tests/Logout/CookieClearingLogoutHandlerTest.phpnu�[���PK��Z$a��n#�test/Security/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationFailureHandlerTest.phpnu�[���PK��Z/w!w!f|?�test/Security/Symfony/Component/Security/Http/Tests/Authentication/SimpleAuthenticationHandlerTest.phpnu�[���PK��Zid]z��n�a�test/Security/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationSuccessHandlerTest.phpnu�[���PK��Z?k,.<<>!y�test/Security/Symfony/Component/Security/Http/phpunit.xml.distnu�[���PK��Z�|G

b�|�test/Security/Symfony/Component/Security/Csrf/Tests/TokenStorage/NativeSessionTokenStorageTest.phpnu�[���PK��Z���WW\u��test/Security/Symfony/Component/Security/Csrf/Tests/TokenStorage/SessionTokenStorageTest.phpnu�[���PK��Z�-�kkLX��test/Security/Symfony/Component/Security/Csrf/Tests/CsrfTokenManagerTest.phpnu�[���PK��Z�3�z((`?��test/Security/Symfony/Component/Security/Csrf/Tests/TokenGenerator/UriSafeTokenGeneratorTest.phpnu�[���PK��Z��*�<<>�Ŝtest/Security/Symfony/Component/Security/Csrf/phpunit.xml.distnu�[���PK��ZׄHAnnK�ɜtest/Security/Symfony/Component/Security/Core/Tests/SecurityContextTest.phpnu�[���PK��ZxF�E�ٜtest/Security/Symfony/Component/Security/Core/Tests/Role/RoleTest.phpnu�[���PK��Zt�S��Nܜtest/Security/Symfony/Component/Security/Core/Tests/Role/RoleHierarchyTest.phpnu�[���PK��Z��{{O+�test/Security/Symfony/Component/Security/Core/Tests/Role/SwitchUserRoleTest.phpnu�[���PK��Zr��nnY%�test/Security/Symfony/Component/Security/Core/Tests/Encoder/Pbkdf2PasswordEncoderTest.phpnu�[���PK��Z6���\�test/Security/Symfony/Component/Security/Core/Tests/Encoder/PlaintextPasswordEncoderTest.phpnu�[���PK��ZL�'��WW��test/Security/Symfony/Component/Security/Core/Tests/Encoder/BasePasswordEncoderTest.phpnu�[���PK��Z%�s�R��test/Security/Symfony/Component/Security/Core/Tests/Encoder/EncoderFactoryTest.phpnu�[���PK��Ze5���`E�test/Security/Symfony/Component/Security/Core/Tests/Encoder/MessageDigestPasswordEncoderTest.phpnu�[���PK��Z!�?��	�	Y��test/Security/Symfony/Component/Security/Core/Tests/Encoder/BCryptPasswordEncoderTest.phpnu�[���PK��Z�����g%�test/Security/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.phpnu�[���PK��Z�KN��Mc7�test/Security/Symfony/Component/Security/Core/Tests/Util/SecureRandomTest.phpnu�[���PK��Zn�;�SSL�N�test/Security/Symfony/Component/Security/Core/Tests/Util/StringUtilsTest.phpnu�[���PK��Z�����K�Q�test/Security/Symfony/Component/Security/Core/Tests/Util/ClassUtilsTest.phpnu�[���PK��ZI-���_�X�test/Security/Symfony/Component/Security/Core/Tests/Authorization/AccessDecisionManagerTest.phpnu�[���PK��Z�bdw�
�
\po�test/Security/Symfony/Component/Security/Core/Tests/Authorization/ExpressionLanguageTest.phpnu�[���PK��Z�Ƕ'�
�
_�}�test/Security/Symfony/Component/Security/Core/Tests/Authorization/Voter/ExpressionVoterTest.phpnu�[���PK��Zjq�o��Y식test/Security/Symfony/Component/Security/Core/Tests/Authorization/Voter/RoleVoterTest.phpnu�[���PK��Z�R�MMb��test/Security/Symfony/Component/Security/Core/Tests/Authorization/Voter/RoleHierarchyVoterTest.phpnu�[���PK��Z��� ,
,
b���test/Security/Symfony/Component/Security/Core/Tests/Authorization/Voter/AuthenticatedVoterTest.phpnu�[���PK��ZLS�(��E���test/Security/Symfony/Component/Security/Core/Tests/User/UserTest.phpnu�[���PK��Z��qR쵝test/Security/Symfony/Component/Security/Core/Tests/User/ChainUserProviderTest.phpnu�[���PK��Z�$��s�͝test/Security/Symfony/Component/Security/Core/Tests/Authentication/Provider/AnonymousAuthenticationProviderTest.phpnu�[���PK��ZP��[.[.m6֝test/Security/Symfony/Component/Security/Core/Tests/Authentication/Provider/DaoAuthenticationProviderTest.phpnu�[���PK��Zו�Gi&i&n.�test/Security/Symfony/Component/Security/Core/Tests/Authentication/Provider/UserAuthenticationProviderTest.phpnu�[���PK��Z�75ttt5,�test/Security/Symfony/Component/Security/Core/Tests/Authentication/Provider/RememberMeAuthenticationProviderTest.phpnu�[���PK��Z���ZZzM<�test/Security/Symfony/Component/Security/Core/Tests/Authentication/Provider/PreAuthenticatedAuthenticationProviderTest.phpnu�[���PK��Z�����hQP�test/Security/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationProviderManagerTest.phpnu�[���PK��Z ����k�f�test/Security/Symfony/Component/Security/Core/Tests/Authentication/RememberMe/InMemoryTokenProviderTest.phpnu�[���PK��ZB�����euo�test/Security/Symfony/Component/Security/Core/Tests/Authentication/RememberMe/PersistentTokenTest.phpnu�[���PK��ZI?��

f�s�test/Security/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationTrustResolverTest.phpnu�[���PK��Z�B3��$�$^�~�test/Security/Symfony/Component/Security/Core/Tests/Authentication/Token/AbstractTokenTest.phpnu�[���PK��Z�j��KKf룞test/Security/Symfony/Component/Security/Core/Tests/Authentication/Token/UsernamePasswordTokenTest.phpnu�[���PK��Zd���f̫�test/Security/Symfony/Component/Security/Core/Tests/Authentication/Token/PreAuthenticatedTokenTest.phpnu�[���PK��Z��ۛ��_T��test/Security/Symfony/Component/Security/Core/Tests/Authentication/Token/AnonymousTokenTest.phpnu�[���PK��Z]�P�<<>ַ�test/Security/Symfony/Component/Security/Core/phpunit.xml.distnu�[���PK��Z���n��L���test/Validator/Symfony/Component/Validator/Tests/ConstraintViolationTest.phpnu�[���PK��ZzJ.4�
�
P�test/Validator/Symfony/Component/Validator/Tests/ConstraintViolationListTest.phpnu�[���PK��Z�p��ggXLϞtest/Validator/Symfony/Component/Validator/Tests/Fixtures/FailingConstraintValidator.phpnu�[���PK��Z5*�I;Ҟtest/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintB.phpnu�[���PK��Z]�qqI�Ԟtest/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintC.phpnu�[���PK��Z���&��I�מtest/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintA.phpnu�[���PK��Zߛ��[[D�ڞtest/Validator/Symfony/Component/Validator/Tests/Fixtures/Entity.phpnu�[���PK��Zp�Tq��Zm�test/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintWithValueAsDefault.phpnu�[���PK��Z@��w��Q��test/Validator/Symfony/Component/Validator/Tests/Fixtures/FakeMetadataFactory.phpnu�[���PK��Z��a�CCM��test/Validator/Symfony/Component/Validator/Tests/Fixtures/EntityInterface.phpnu�[���PK��Z?>��Rf�test/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintAValidator.phpnu�[���PK��Z^t��M��test/Validator/Symfony/Component/Validator/Tests/Fixtures/ClassConstraint.phpnu�[���PK��Z��88J��test/Validator/Symfony/Component/Validator/Tests/Fixtures/EntityParent.phpnu�[���PK��Z�h��Y���test/Validator/Symfony/Component/Validator/Tests/Fixtures/GroupSequenceProviderEntity.phpnu�[���PK��Z�5>��Q)��test/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintWithValue.phpnu�[���PK��Z=�2O/��test/Validator/Symfony/Component/Validator/Tests/Fixtures/FailingConstraint.phpnu�[���PK��ZO��l99G��test/Validator/Symfony/Component/Validator/Tests/Fixtures/Reference.phpnu�[���PK��Z2�	���Ov�test/Validator/Symfony/Component/Validator/Tests/Fixtures/InvalidConstraint.phpnu�[���PK��Zj�/���Iv�test/Validator/Symfony/Component/Validator/Tests/Fixtures/FilesLoader.phpnu�[���PK��ZY��/K�test/Validator/Symfony/Component/Validator/Tests/Fixtures/CallbackClass.phpnu�[���PK��Z���JJX
�test/Validator/Symfony/Component/Validator/Tests/Fixtures/InvalidConstraintValidator.phpnu�[���PK��ZG#i��P��test/Validator/Symfony/Component/Validator/Tests/Fixtures/PropertyConstraint.phpnu�[���PK��Z�Ε_))I6�test/Validator/Symfony/Component/Validator/Tests/ValidatorBuilderTest.phpnu�[���PK��Z��>���N��test/Validator/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.phpnu�[���PK��ZF���U:�test/Validator/Symfony/Component/Validator/Tests/Mapping/ClassMetadataFactoryTest.phpnu�[���PK��Z)����P`J�test/Validator/Symfony/Component/Validator/Tests/Mapping/ElementMetadataTest.phpnu�[���PK��Z�D��O�S�test/Validator/Symfony/Component/Validator/Tests/Mapping/MemberMetadataTest.phpnu�[���PK��ZW_Ϙ�O�`�test/Validator/Symfony/Component/Validator/Tests/Mapping/GetterMetadataTest.phpnu�[���PK��Z"��,�	�	O�f�test/Validator/Symfony/Component/Validator/Tests/Mapping/Cache/ApcCacheTest.phpnu�[���PK��Zos%�eeY�p�test/Validator/Symfony/Component/Validator/Tests/Mapping/BlackholeMetadataFactoryTest.phpnu�[���PK��Zu��gS�t�test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/LoaderChainTest.phpnu�[���PK��Z�=����bk��test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping-non-strings.xmlnu�[���PK��Z�D�k��Vك�test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.xmlnu�[���PK��Z�-���V(��test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.ymlnu�[���PK��Z{�%uZn��test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/StaticMethodLoaderTest.phpnu�[���PK��Z���mX��test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/AnnotationLoaderTest.phpnu�[���PK��Z��N��V�Ÿtest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.phpnu�[���PK��ZN�;��O�ԟtest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/withdoctype.xmlnu�[���PK��ZQ�֟test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/empty-mapping.ymlnu�[���PK��Z�Qi���Unןtest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/XmlFileLoaderTest.phpnu�[���PK��Z�e2~Tz�test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/nonvalid-mapping.ymlnu�[���PK��Z����^�test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/AbstractMethodStaticLoader.phpnu�[���PK��ZF���<<S��test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/FilesLoaderTest.phpnu�[���PK��Z{�d���QD�test/Validator/Symfony/Component/Validator/Tests/Mapping/PropertyMetadataTest.phpnu�[���PK��Z��~6�F�FJl��test/Validator/Symfony/Component/Validator/Tests/ValidationVisitorTest.phpnu�[���PK��ZK��y'$'$B�A�test/Validator/Symfony/Component/Validator/Tests/ValidatorTest.phpnu�[���PK��Z�P�6�)�)IEf�test/Validator/Symfony/Component/Validator/Tests/ExecutionContextTest.phpnu�[���PK��Z����QK��test/Validator/Symfony/Component/Validator/Tests/Constraints/AllValidatorTest.phpnu�[���PK��Z�ĀDDSl��test/Validator/Symfony/Component/Validator/Tests/Constraints/RegexValidatorTest.phpnu�[���PK��Z�Q�]3��test/Validator/Symfony/Component/Validator/Tests/Constraints/LessThanOrEqualValidatorTest.phpnu�[���PK��Z�;�55Rз�test/Validator/Symfony/Component/Validator/Tests/Constraints/IssnValidatorTest.phpnu�[���PK��Z����K1K1P�͠test/Validator/Symfony/Component/Validator/Tests/Constraints/IpValidatorTest.phpnu�[���PK��Z�rH���iR��test/Validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorCustomArrayObjectTest.phpnu�[���PK��Z�GRf��U��test/Validator/Symfony/Component/Validator/Tests/Constraints/NotNullValidatorTest.phpnu�[���PK��Z���I��O�
�test/Validator/Symfony/Component/Validator/Tests/Constraints/CollectionTest.phpnu�[���PK��Z���W��X(�test/Validator/Symfony/Component/Validator/Tests/Constraints/FileValidatorObjectTest.phpnu�[���PK��Zs{*pQQR��test/Validator/Symfony/Component/Validator/Tests/Constraints/TrueValidatorTest.phpnu�[���PK��Z�|�++Wr#�test/Validator/Symfony/Component/Validator/Tests/Constraints/Fixtures/test_portrait.gifnu�[���PK��ZJ��++X$$�test/Validator/Symfony/Component/Validator/Tests/Constraints/Fixtures/test_landscape.gifnu�[���PK��ZЍ��!!N�$�test/Validator/Symfony/Component/Validator/Tests/Constraints/Fixtures/test.gifnu�[���PK��Z)m�RTv(�test/Validator/Symfony/Component/Validator/Tests/Constraints/LengthValidatorTest.phpnu�[���PK��Z��̈́
�
T�A�test/Validator/Symfony/Component/Validator/Tests/Constraints/LocaleValidatorTest.phpnu�[���PK��Z�s�VVXM�test/Validator/Symfony/Component/Validator/Tests/Constraints/NotEqualToValidatorTest.phpnu�[���PK��Z���8w
w
S�S�test/Validator/Symfony/Component/Validator/Tests/Constraints/EmailValidatorTest.phpnu�[���PK��Z�w88\�^�test/Validator/Symfony/Component/Validator/Tests/Constraints/CountValidatorCountableTest.phpnu�[���PK��Z];XwwS�b�test/Validator/Symfony/Component/Validator/Tests/Constraints/BlankValidatorTest.phpnu�[���PK��Z3�ê�
�
d�j�test/Validator/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.phpnu�[���PK��Z7��a��Ty�test/Validator/Symfony/Component/Validator/Tests/Constraints/ChoiceValidatorTest.phpnu�[���PK��Z�2�(�(RC��test/Validator/Symfony/Component/Validator/Tests/Constraints/FileValidatorTest.phpnu�[���PK��Z�����X~¡test/Validator/Symfony/Component/Validator/Tests/Constraints/CardSchemeValidatorTest.phpnu�[���PK��Z{r>K��R�աtest/Validator/Symfony/Component/Validator/Tests/Constraints/IsbnValidatorTest.phpnu�[���PK��ZjTL�99U��test/Validator/Symfony/Component/Validator/Tests/Constraints/EqualToValidatorTest.phpnu�[���PK��Z�$&��Y��test/Validator/Symfony/Component/Validator/Tests/Constraints/IdenticalToValidatorTest.phpnu�[���PK��Z��|=��c�test/Validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorArrayObjectTest.phpnu�[���PK��Z�z0���U`��test/Validator/Symfony/Component/Validator/Tests/Constraints/CountryValidatorTest.phpnu�[���PK��Z�rZcc\s	�test/Validator/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToValidatorTest.phpnu�[���PK��Z�C��NNQb�test/Validator/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.phpnu�[���PK��Z(�3��J1'�test/Validator/Symfony/Component/Validator/Tests/Constraints/ValidTest.phpnu�[���PK��Z���A��VO*�test/Validator/Symfony/Component/Validator/Tests/Constraints/CurrencyValidatorTest.phpnu�[���PK��ZB����H�6�test/Validator/Symfony/Component/Validator/Tests/Constraints/AllTest.phpnu�[���PK��Z�p�)D
D
R
;�test/Validator/Symfony/Component/Validator/Tests/Constraints/LuhnValidatorTest.phpnu�[���PK��Z��͸�S�H�test/Validator/Symfony/Component/Validator/Tests/Constraints/RangeValidatorTest.phpnu�[���PK��ZQ��s(s(Va�test/Validator/Symfony/Component/Validator/Tests/Constraints/CallbackValidatorTest.phpnu�[���PK��Z@*�VHHR��test/Validator/Symfony/Component/Validator/Tests/Constraints/DateValidatorTest.phpnu�[���PK��Z�� BTTRѕ�test/Validator/Symfony/Component/Validator/Tests/Constraints/TimeValidatorTest.phpnu�[���PK��Z�i�KKS���test/Validator/Symfony/Component/Validator/Tests/Constraints/FalseValidatorTest.phpnu�[���PK��ZϏ�R��Xu��test/Validator/Symfony/Component/Validator/Tests/Constraints/CountValidatorArrayTest.phpnu�[���PK��ZqC����V���test/Validator/Symfony/Component/Validator/Tests/Constraints/LanguageValidatorTest.phpnu�[���PK��Zֆ���SV��test/Validator/Symfony/Component/Validator/Tests/Constraints/CountValidatorTest.phpnu�[���PK��Z��LwwY�̢test/Validator/Symfony/Component/Validator/Tests/Constraints/GreaterThanValidatorTest.phpnu�[���PK��Z���kkV�Ԣtest/Validator/Symfony/Component/Validator/Tests/Constraints/FileValidatorPathTest.phpnu�[���PK��Z׫��`�آtest/Validator/Symfony/Component/Validator/Tests/Constraints/GreaterThanOrEqualValidatorTest.phpnu�[���PK��ZW�@� � R3ߢtest/Validator/Symfony/Component/Validator/Tests/Constraints/IbanValidatorTest.phpnu�[���PK��Z�y7{==R`�test/Validator/Symfony/Component/Validator/Tests/Constraints/TypeValidatorTest.phpnu�[���PK��Z\z?�+�+X�test/Validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorTest.phpnu�[���PK��ZC���77VkB�test/Validator/Symfony/Component/Validator/Tests/Constraints/LessThanValidatorTest.phpnu�[���PK��Zb���ggV(J�test/Validator/Symfony/Component/Validator/Tests/Constraints/DateTimeValidatorTest.phpnu�[���PK��Z;���,,XW�test/Validator/Symfony/Component/Validator/Tests/Constraints/ExpressionValidatorTest.phpnu�[���PK��Z�Zf^
^
V�n�test/Validator/Symfony/Component/Validator/Tests/Constraints/NotBlankValidatorTest.phpnu�[���PK��Z}mW��]�y�test/Validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorArrayTest.phpnu�[���PK��Z�r3UUR|�test/Validator/Symfony/Component/Validator/Tests/Constraints/NullValidatorTest.phpnu�[���PK��Z0�h'��Sۃ�test/Validator/Symfony/Component/Validator/Tests/Constraints/ImageValidatorTest.phpnu�[���PK��Z�d��..C<��test/Validator/Symfony/Component/Validator/Tests/ConstraintTest.phpnu�[���PK��Z��,Q88;ݶ�test/Validator/Symfony/Component/Validator/phpunit.xml.distnu�[���PK��Z�����K���test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Logger/DbalLoggerTest.phpnu�[���PK��Zl;���?�ˣtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/bootstrap.phpnu�[���PK��Z1g��P�ͣtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/SingleIntIdEntity.phpnu�[���PK��ZI>�[��Zѣtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/SingleIntIdNoToStringEntity.phpnu�[���PK��Z�+�88SEԣtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/CompositeIntIdEntity.phpnu�[���PK��Z�ͭ��Pأtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/AssociationEntity.phpnu�[���PK��Z��3Nuܣtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/GroupableEntity.phpnu�[���PK��Z��!��S�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/SingleStringIdEntity.phpnu�[���PK��Z6i+**T_�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/ContainerAwareFixture.phpnu�[���PK��ZИ�m��O
�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/DoubleNameEntity.phpnu�[���PK��Z�%b�99V��test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/CompositeStringIdEntity.phpnu�[���PK��Z�'N|qqC@�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/User.phpnu�[���PK��Z��.���I$�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/DoctrineOrmTestCase.phpnu�[���PK��Z��۵��U���test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/DoctrineOrmTypeGuesserTest.phpnu�[���PK��Z��`Հ�p�
�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleStringIdTest.phpnu�[���PK��Z�'�;�!�!a�
�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/GenericEntityChoiceListTest.phpnu�[���PK��Z9&���0�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleStringIdWithQueryBuilderTest.phpnu�[���PK��Zb#����m�4�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListSingleIntIdTest.phpnu�[���PK��ZAGA��};�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleIntIdWithQueryBuilderTest.phpnu�[���PK��Z�~h���}�?�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListCompositeIdWithQueryBuilderTest.phpnu�[���PK��Z�'j��nD�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/LoadedEntityChoiceListSingleStringIdTest.phpnu�[���PK��Z�0�e��k�G�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/LoadedEntityChoiceListSingleIntIdTest.phpnu�[���PK��Z��V
zzm�J�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListCompositeIdTest.phpnu�[���PK��Z��*��mN�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListCompositeIdTest.phpnu�[���PK��Z�n<-	-	_zT�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.phpnu�[���PK��Z�-��1
1
b6^�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListTest.phpnu�[���PK��Zc�&zzm�h�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleIntIdTest.phpnu�[���PK��Z�ǜ"��kl�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/LoadedEntityChoiceListCompositeIdTest.phpnu�[���PK��Z_UNF��po�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListSingleStringIdTest.phpnu�[���PK��ZYv�:B	B	k�u�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/DataTransformer/CollectionToArrayTransformerTest.phpnu�[���PK��Z��(iiN��test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.phpnu�[���PK��Z�I�m��YL�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypePerformanceTest.phpnu�[���PK��Z�;��
�
Z~��test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Security/User/EntityUserProviderTest.phpnu�[���PK��Z}��u>u>_��test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueValidatorTest.phpnu�[���PK��Z���,��`�E�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/ExpressionLanguage/DoctrineParserCacheTest.phpnu�[���PK��Z�$K�BBTiM�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/ContainerAwareEventManagerTest.phpnu�[���PK��Z�9qq[/U�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/DataFixtures/ContainerAwareLoaderTest.phpnu�[���PK��ZC�II[+Y�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/HttpFoundation/DbalSessionHandlerTest.phpnu�[���PK��Z�l��]�\�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.phpnu�[���PK��ZO����Ls�test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPassTest.phpnu�[���PK��Z�ޠ�77<��test/DoctrineBridge/Symfony/Bridge/Doctrine/phpunit.xml.distnu�[���PK��Z&�ǦGGN���test/MonologBridge/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.phpnu�[���PK��Z�o.���No��test/MonologBridge/Symfony/Bridge/Monolog/Tests/Processor/WebProcessorTest.phpnu�[���PK��Z��Ki66:ܭ�test/MonologBridge/Symfony/Bridge/Monolog/phpunit.xml.distnu�[���PK��Z}/�66M|��test/Templating/Symfony/Component/Templating/Tests/TemplateNameParserTest.phpnu�[���PK��Z���xxL/��test/Templating/Symfony/Component/Templating/Tests/Fixtures/SimpleHelper.phpnu�[���PK��Z�`�2M#��test/Templating/Symfony/Component/Templating/Tests/Fixtures/templates/foo.phpnu�[���PK��Z=D����N���test/Templating/Symfony/Component/Templating/Tests/Storage/FileStorageTest.phpnu�[���PK��Z`7�SSP���test/Templating/Symfony/Component/Templating/Tests/Storage/StringStorageTest.phpnu�[���PK��ZS	�٦�J�¥test/Templating/Symfony/Component/Templating/Tests/Storage/StorageTest.phpnu�[���PK��Z��7���H�ťtest/Templating/Symfony/Component/Templating/Tests/Loader/LoaderTest.phpnu�[���PK��ZWl�‡�R�˥test/Templating/Symfony/Component/Templating/Tests/Loader/FilesystemLoaderTest.phpnu�[���PK��Z���
�
M�ܥtest/Templating/Symfony/Component/Templating/Tests/Loader/CacheLoaderTest.phpnu�[���PK��ZˡA`��M<�test/Templating/Symfony/Component/Templating/Tests/Loader/ChainLoaderTest.phpnu�[���PK��Z�`n}�
�
N��test/Templating/Symfony/Component/Templating/Tests/Helper/AssetsHelperTest.phpnu�[���PK��Z�q=R

H��test/Templating/Symfony/Component/Templating/Tests/Helper/HelperTest.phpnu�[���PK��ZM<��Rd�test/Templating/Symfony/Component/Templating/Tests/Helper/CoreAssetsHelperTest.phpnu�[���PK��Z0�nl

M��test/Templating/Symfony/Component/Templating/Tests/Helper/SlotsHelperTest.phpnu�[���PK��Z��`#`#Dw�test/Templating/Symfony/Component/Templating/Tests/PhpEngineTest.phpnu�[���PK��Z�氵�KK:�test/Templating/Symfony/Component/Templating/Tests/DelegatingEngineTest.phpnu�[���PK��Z�%�D99={O�test/Templating/Symfony/Component/Templating/phpunit.xml.distnu�[���PK��Z��Q��5!S�test/Yaml/Symfony/Component/Yaml/Tests/DumperTest.phpnu�[���PK��Z�����Ch�test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsBlockMapping.ymlnu�[���PK��Z��UU=&l�test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfCompact.ymlnu�[���PK��Z�5�R[[B�w�test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsAnchorAlias.ymlnu�[���PK��ZU���;�{�test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfTests.ymlnu�[���PK��Z�@�UU>��test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfComments.ymlnu�[���PK��ZÇ��--Iڊ�test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/unindentedCollections.ymlnu�[���PK��Z�>;���F���test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsNullsAndEmpties.ymlnu�[���PK��Zt��rqqA���test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsErrorTests.ymlnu�[���PK��ZZ{k�XXF���test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsFlowCollections.ymlnu�[���PK��Z�*���EQ��test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/escapedCharacters.ymlnu�[���PK��Z֋�O��A���test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsBasicTests.ymlnu�[���PK��ZګغzzD ��test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsFoldedScalars.ymlnu�[���PK��Z���889Ŧtest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/index.ymlnu�[���PK��Z%MC��H�Ʀtest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsDocumentSeparator.ymlnu�[���PK��Z;:�QJJ>!ͦtest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfMergeKey.ymlnu�[���PK��ZZ��>�Ѧtest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/embededPhp.ymlnu�[���PK��Z�<�=fҦtest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfObjects.ymlnu�[���PK��Z�$R��D�Ӧtest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsTypeTransfers.ymlnu�[���PK��Z����<G�test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfQuotes.ymlnu�[���PK��ZܷU�1�1�L��test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.ymlnu�[���PK��Z~;�p2p25E��test/Yaml/Symfony/Component/Yaml/Tests/ParserTest.phpnu�[���PK��Z=a�o[%[%5ȧtest/Yaml/Symfony/Component/Yaml/Tests/InlineTest.phpnu�[���PK��Z`�@ee3��test/Yaml/Symfony/Component/Yaml/Tests/YamlTest.phpnu�[���PK��Z��?o��=��test/Yaml/Symfony/Component/Yaml/Tests/ParseExceptionTest.phpnu�[���PK��Z�>[331���test/Yaml/Symfony/Component/Yaml/phpunit.xml.distnu�[���PK��Z����)L��test/Console_Getopt/tests/001-getopt.phptnu�[���PK��Z��'s��test/Console_Getopt/tests/bug11068.phptnu�[���PK��Z���'��test/Console_Getopt/tests/bug10557.phptnu�[���PK��Z��|EE'(�test/Console_Getopt/tests/bug13140.phptnu�[���PK��Z��mg�
�
J�	�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.phpnu�[���PK��Z��O+�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/RequestStackTest.phpnu�[���PK��Z��lOD
D
O��test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ResponseTestCase.phpnu�[���PK��Z�F�9bbIs+�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/CookieTest.phpnu�[���PK��Z�q�H��SN>�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/RedirectResponseTest.phpnu�[���PK��Zqr��



[�G�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ExpressionRequestMatcherTest.phpnu�[���PK��Z_�|���UFR�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/BinaryFileResponseTest.phpnu�[���PK��Z��@LLJto�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/FileBagTest.phpnu�[���PK��Z�m��..L:��test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/HeaderBagTest.phpnu�[���PK��Z��܏##Q䟨test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/Fixtures/test.gifnu�[���PK��Z�+�vZ���test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/Fixtures/.unknownextensionnu�[���PK��ZY��test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/Fixtures/directory/.emptynu�[���PK��Z��܏##M���test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/Fixtures/testnu�[���PK��Z~rM;;Y<��test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/MimeType/MimeTypeTest.phpnu�[���PK��Z��##L��test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/FileTest.phpnu�[���PK��Z��t�AAT�Ǩtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/UploadedFileTest.phpnu�[���PK��Z�ʾV�
�
Sd�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/StreamedResponseTest.phpnu�[���PK��ZM�{��c��test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Flash/AutoExpireFlashBagTest.phpnu�[���PK��Z��ƒ��Y��test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Flash/FlashBagTest.phpnu�[���PK��Z0�����a�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Attribute/AttributeBagTest.phpnu�[���PK��Z)��kc,�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Attribute/NamespacedAttributeBagTest.phpnu�[���PK��Z��ppR
B�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/SessionTest.phpnu�[���PK��Z>��*i�[�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockFileSessionStorageTest.phpnu�[���PK��Z5�h���o�k�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeSessionHandlerTest.phpnu�[���PK��Z1�Mf
f
qq�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.phpnu�[���PK��Z�+?�

s�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.phpnu�[���PK��Z>��$$pÉ�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.phpnu�[���PK��Z`����r���test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.phpnu�[���PK��Z�c=��s��test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/WriteCheckSessionHandlerTest.phpnu�[���PK��Z�Qttl0��test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.phpnu�[���PK��Z+�ɠ��m@˩test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NullSessionHandlerTest.phpnu�[���PK��Z��x�..j`ҩtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/PhpBridgeSessionStorageTest.phpnu�[���PK��Z�����j(�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockArraySessionStorageTest.phpnu�[���PK��Zt䪑�$�$g��test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.phpnu�[���PK��Z�@|B``d�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/NativeProxyTest.phpnu�[���PK��ZF�++f�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/AbstractProxyTest.phpnu�[���PK��ZČ#��l�,�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.phpnu�[���PK��ZT �S��^I9�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/MetadataBagTest.phpnu�[���PK��Z��7�
�
S�H�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/AcceptHeaderItemTest.phpnu�[���PK��Z�`k OW�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/JsonResponseTest.phpnu�[���PK��Z�E����Q�p�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/RequestMatcherTest.phpnu�[���PK��Z����,�,Tڀ�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.phpnu�[���PK��Zk\B��r�rK>��test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ResponseTest.phpnu�[���PK��ZAk�B#B#O�!�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ParameterBagTest.phpnu�[���PK��Z��q��JBE�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/RequestTest.phpnu�[���PK��Z%�bD�
�
P{Y�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ApacheRequestTest.phpnu�[���PK��Z�1r�
�
O�d�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/AcceptHeaderTest.phpnu�[���PK��Z��?�L�r�test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ServerBagTest.phpnu�[���PK��Z���bppEK��test/HttpFoundation/Symfony/Component/HttpFoundation/phpunit.xml.distnu�[���PK��Z��J=�'�'D0��test/BrowserKit/Symfony/Component/BrowserKit/Tests/CookieJarTest.phpnu�[���PK��ZN�4Z�c�cA���test/BrowserKit/Symfony/Component/BrowserKit/Tests/ClientTest.phpnu�[���PK��Z�ɹ(RRA��test/BrowserKit/Symfony/Component/BrowserKit/Tests/CookieTest.phpnu�[���PK��ZK����B�/�test/BrowserKit/Symfony/Component/BrowserKit/Tests/HistoryTest.phpnu�[���PK��Z{2�wC�>�test/BrowserKit/Symfony/Component/BrowserKit/Tests/ResponseTest.phpnu�[���PK��Z|����B�K�test/BrowserKit/Symfony/Component/BrowserKit/Tests/RequestTest.phpnu�[���PK��Z�p6ll=�S�test/BrowserKit/Symfony/Component/BrowserKit/phpunit.xml.distnu�[���PK��Z?7��EE9�W�test/Net_IDNA2/tests/draft-josefsson-idn-test-vectors.phpnu�[���PK��ZE��mm&��test/Net_IDNA2/tests/Net_IDNA2Test.phpnu�[���PK��Z.��
��"ڥ�test/XML_RPC/tests/extra-lines.phpnu�[���PK��Z|�E)���test/XML_RPC/tests/empty-value-struct.phpnu�[���PK��Z�3l�** Y��test/XML_RPC/tests/protoport.phpnu�[���PK��Z�B���test/XML_RPC/tests/allgot.incnu�[���PK��Z��̢�	�	��test/XML_RPC/tests/types.phpnu�[���PK��ZJ����@�test/XML_RPC/tests/encode.phpnu�[���PK��Z���XX ^��test/XML_RPC/tests/test_Dump.phpnu�[���PK��Z$]���"�test/XML_RPC/tests/empty-value.phpnu�[���PK��Zb��)))%Q	�test/XML_RPC/tests/actual-request.phpnu�[���PK��Zw�۴��M��test/DomCrawler/Symfony/Component/DomCrawler/Tests/Fixtures/windows-1250.htmlnu�[���PK��Z�x�H��test/DomCrawler/Symfony/Component/DomCrawler/Tests/Fixtures/no-extensionnu�[���PK��Zl�#8��Bm�test/DomCrawler/Symfony/Component/DomCrawler/Tests/CrawlerTest.phpnu�[���PK��Z��Ջ==Ptest/DomCrawler/Symfony/Component/DomCrawler/Tests/Field/ChoiceFormFieldTest.phpnu�[���PK��Z�n���R�ݮtest/DomCrawler/Symfony/Component/DomCrawler/Tests/Field/TextareaFormFieldTest.phpnu�[���PK��Z�!
D��J��test/DomCrawler/Symfony/Component/DomCrawler/Tests/Field/FormFieldTest.phpnu�[���PK��Z2$�G��N;�test/DomCrawler/Symfony/Component/DomCrawler/Tests/Field/FormFieldTestCase.phpnu�[���PK��Z���QQOT�test/DomCrawler/Symfony/Component/DomCrawler/Tests/Field/InputFormFieldTest.phpnu�[���PK��Z�5�||N$��test/DomCrawler/Symfony/Component/DomCrawler/Tests/Field/FileFormFieldTest.phpnu�[���PK��Z�3��ʖʖ?�test/DomCrawler/Symfony/Component/DomCrawler/Tests/FormTest.phpnu�[���PK��Zm�Y���?W��test/DomCrawler/Symfony/Component/DomCrawler/Tests/LinkTest.phpnu�[���PK��Z)q0�ll=y��test/DomCrawler/Symfony/Component/DomCrawler/phpunit.xml.distnu�[���PK��Z��H�77LR��test/CssSelector/Symfony/Component/CssSelector/Tests/XPath/Fixtures/ids.htmlnu�[���PK��ZmiĪ:�:S��test/CssSelector/Symfony/Component/CssSelector/Tests/XPath/Fixtures/shakespear.htmlnu�[���PK��Z�B�==L��test/CssSelector/Symfony/Component/CssSelector/Tests/XPath/Fixtures/lang.xmlnu�[���PK��Z1�HCHCM��test/CssSelector/Symfony/Component/CssSelector/Tests/XPath/TranslatorTest.phpnu�[���PK��Zo,q��M�A�test/CssSelector/Symfony/Component/CssSelector/Tests/Node/ElementNodeTest.phpnu�[���PK��Z�BնVVJ�E�test/CssSelector/Symfony/Component/CssSelector/Tests/Node/HashNodeTest.phpnu�[���PK��ZV=��hhK�I�test/CssSelector/Symfony/Component/CssSelector/Tests/Node/ClassNodeTest.phpnu�[���PK��Zg$i���N|M�test/CssSelector/Symfony/Component/CssSelector/Tests/Node/NegationNodeTest.phpnu�[���PK��Zj�
��V�Q�test/CssSelector/Symfony/Component/CssSelector/Tests/Node/CombinedSelectorNodeTest.phpnu�[���PK��Z�(yآ�NW�test/CssSelector/Symfony/Component/CssSelector/Tests/Node/FunctionNodeTest.phpnu�[���PK��Z�Y���N6^�test/CssSelector/Symfony/Component/CssSelector/Tests/Node/AbstractNodeTest.phpnu�[���PK��Z_�Ӵ�Nub�test/CssSelector/Symfony/Component/CssSelector/Tests/Node/SelectorNodeTest.phpnu�[���PK��Z���uuM�f�test/CssSelector/Symfony/Component/CssSelector/Tests/Node/SpecificityTest.phpnu�[���PK��Z� _ӽ�O�k�test/CssSelector/Symfony/Component/CssSelector/Tests/Node/AttributeNodeTest.phpnu�[���PK��Z�WDL�q�test/CssSelector/Symfony/Component/CssSelector/Tests/Node/PseudoNodeTest.phpnu�[���PK��Z�/D�Hpu�test/CssSelector/Symfony/Component/CssSelector/Tests/CssSelectorTest.phpnu�[���PK��Z�u̱��Z��test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Shortcut/ElementParserTest.phpnu�[���PK��Z[�nы�Xg��test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Shortcut/ClassParserTest.phpnu�[���PK��Z>�]��^z��test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Shortcut/EmptyStringParserTest.phpnu�[���PK��Z[N�eeW���test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Shortcut/HashParserTest.phpnu�[���PK��Z^���2�2J旰test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/ParserTest.phpnu�[���PK��Z+��̭�Y˰test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/NumberHandlerTest.phpnu�[���PK��Z��˶]:Ѱtest/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/IdentifierHandlerTest.phpnu�[���PK��Z��_/RRZ�װtest/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/CommentHandlerTest.phpnu�[���PK��ZĈ���[�ްtest/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/AbstractHandlerTest.phpnu�[���PK��Z ���]��test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/WhitespaceHandlerTest.phpnu�[���PK��Z�쓱��Y5�test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/StringHandlerTest.phpnu�[���PK��ZC�U�rrW��test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/HashHandlerTest.phpnu�[���PK��Z%9�j~~J���test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/ReaderTest.phpnu�[���PK��Z�}��qqO��test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/TokenStreamTest.phpnu�[���PK��Z���Hmm?��test/CssSelector/Symfony/Component/CssSelector/phpunit.xml.distnu�[���PK��Z�X,�/�/Td�test/EventDispatcher/Symfony/Component/EventDispatcher/Tests/EventDispatcherTest.phpnu�[���PK��Z���aa]uF�test/EventDispatcher/Symfony/Component/EventDispatcher/Tests/ImmutableEventDispatcherTest.phpnu�[���PK��ZYQ_AAbcR�test/EventDispatcher/Symfony/Component/EventDispatcher/Tests/ContainerAwareEventDispatcherTest.phpnu�[���PK��Z��nuJ6p�test/EventDispatcher/Symfony/Component/EventDispatcher/Tests/EventTest.phpnu�[���PK��Z\2��
�
Q�x�test/EventDispatcher/Symfony/Component/EventDispatcher/Tests/GenericEventTest.phpnu�[���PK��Z�MqqG6��test/EventDispatcher/Symfony/Component/EventDispatcher/phpunit.xml.distnu�[���PK��Z��C	C	H��test/Console/Symfony/Component/Console/Tests/Command/ListCommandTest.phpnu�[���PK��Zo�"�Z9Z9Dٔ�test/Console/Symfony/Component/Console/Tests/Command/CommandTest.phpnu�[���PK��Zb�y�11H�αtest/Console/Symfony/Component/Console/Tests/Command/HelpCommandTest.phpnu�[���PK��Zu��d��MPڱtest/Console/Symfony/Component/Console/Tests/Fixtures/application_astext1.txtnu�[���PK��Z��c��Gzޱtest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_3.mdnu�[���PK��Z���ooK�߱test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_2.jsonnu�[���PK��Z��f���J��test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_2.xmlnu�[���PK��Z9y�X��B��test/Console/Symfony/Component/Console/Tests/Fixtures/command_1.mdnu�[���PK��Z�S��G��test/Console/Symfony/Component/Console/Tests/Fixtures/command_asxml.txtnu�[���PK��Z�^t�^^L�test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_1.xmlnu�[���PK��ZP����G��test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_4.mdnu�[���PK��Z���G�test/Console/Symfony/Component/Console/Tests/Fixtures/BarBucCommand.phpnu�[���PK��ZW'��L:�test/Console/Symfony/Component/Console/Tests/Fixtures/application_asxml2.txtnu�[���PK��Z&���VI�test/Console/Symfony/Component/Console/Tests/Fixtures/application_renderexception1.txtnu�[���PK��Z��XX��H[��test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_3.xmlnu�[���PK��Z��G��H���test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_1.xmlnu�[���PK��ZY'�A��L��test/Console/Symfony/Component/Console/Tests/Fixtures/DescriptorCommand1.phpnu�[���PK��ZCQu��L��test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_4.xmlnu�[���PK��Z�!�"��J�test/Console/Symfony/Component/Console/Tests/Fixtures/application_run3.txtnu�[���PK��Z�e�d��E�test/Console/Symfony/Component/Console/Tests/Fixtures/Foo4Command.phpnu�[���PK��Zz�Ռ��I�test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_2.mdnu�[���PK��Z�t;�aaH�test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_4.txtnu�[���PK��Z a���I��test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_4.jsonnu�[���PK��Z�F:cL��test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_3.xmlnu�[���PK��ZoY���H|�test/Console/Symfony/Component/Console/Tests/Fixtures/application_1.jsonnu�[���PK��Z#��"��D��test/Console/Symfony/Component/Console/Tests/Fixtures/command_2.jsonnu�[���PK��Z9�*A��E%�test/Console/Symfony/Component/Console/Tests/Fixtures/TestCommand.phpnu�[���PK��Z�'�̒�CT�test/Console/Symfony/Component/Console/Tests/Fixtures/command_1.txtnu�[���PK��Z<|�4UUEY�test/Console/Symfony/Component/Console/Tests/Fixtures/Foo1Command.phpnu�[���PK��ZL#�test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_1.txtnu�[���PK��Z��<]]K��test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_1.jsonnu�[���PK��Z۴�2��Iw�test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_2.jsonnu�[���PK��Z�q+��P� �test/Console/Symfony/Component/Console/Tests/Fixtures/DescriptorApplication1.phpnu�[���PK��Z��[���K�"�test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_2.mdnu�[���PK��Z��#��F�#�test/Console/Symfony/Component/Console/Tests/Fixtures/application_2.mdnu�[���PK��Z��$$M�?�test/Console/Symfony/Component/Console/Tests/Fixtures/application_astext2.txtnu�[���PK��Zg��/11J~C�test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_2.txtnu�[���PK��Z[��%��D)D�test/Console/Symfony/Component/Console/Tests/Fixtures/command_1.jsonnu�[���PK��Z�Z�o��FaE�test/Console/Symfony/Component/Console/Tests/Fixtures/application_1.mdnu�[���PK��Zia����JuT�test/Console/Symfony/Component/Console/Tests/Fixtures/definition_asxml.txtnu�[���PK��Z�_�n��J�Y�test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_1.xmlnu�[���PK��Z�: 8��J�Z�test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_3.xmlnu�[���PK��Z��-��_H\�test/Console/Symfony/Component/Console/Tests/Fixtures/application_renderexception3decorated.txtnu�[���PK��Z�@�]"]"Gh_�test/Console/Symfony/Component/Console/Tests/Fixtures/application_2.xmlnu�[���PK��Z�K@�bbH<��test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_2.txtnu�[���PK��Zp�����K��test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_3.mdnu�[���PK��Z�A�(ffC@��test/Console/Symfony/Component/Console/Tests/Fixtures/command_2.xmlnu�[���PK��Z��,���K��test/Console/Symfony/Component/Console/Tests/Fixtures/definition_astext.txtnu�[���PK��Z�I���Hq��test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_4.xmlnu�[���PK��Zu$´!!H���test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_1.txtnu�[���PK��Z���$$MT��test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_4.jsonnu�[���PK��Z3�P���L���test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_2.xmlnu�[���PK��ZѸ�;;Lb��test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_2.txtnu�[���PK��Z��a66G��test/Console/Symfony/Component/Console/Tests/Fixtures/application_1.txtnu�[���PK��Z����MƓ�test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_1.jsonnu�[���PK��ZX� �,,Ja��test/Console/Symfony/Component/Console/Tests/Fixtures/application_run2.txtnu�[���PK��Z󚲱}}K��test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_3.jsonnu�[���PK��Z1"8MMP���test/Console/Symfony/Component/Console/Tests/Fixtures/DescriptorApplication2.phpnu�[���PK��Z#ɤb��M̜�test/Console/Symfony/Component/Console/Tests/Fixtures/application_gethelp.txtnu�[���PK��Z�(���G���test/Console/Symfony/Component/Console/Tests/Fixtures/application_2.txtnu�[���PK��Z;`�ML���test/Console/Symfony/Component/Console/Tests/Fixtures/application_asxml1.txtnu�[���PK��ZW��،�I���test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_3.mdnu�[���PK��Z��X��I���test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_1.jsonnu�[���PK��Z�
c�D���test/Console/Symfony/Component/Console/Tests/Fixtures/FooCommand.phpnu�[���PK��ZG u=��Vòtest/Console/Symfony/Component/Console/Tests/Fixtures/application_renderexception3.txtnu�[���PK��ZK3Ųtest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_1.mdnu�[���PK��Z���==L�Ųtest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_3.txtnu�[���PK��Z�����HgƲtest/Console/Symfony/Component/Console/Tests/Fixtures/command_astext.txtnu�[���PK��Z�J�2H�ɲtest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_2.xmlnu�[���PK��Zl�T���GN˲test/Console/Symfony/Component/Console/Tests/Fixtures/application_1.xmlnu�[���PK��Z�Y-͡�Gi޲test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_1.mdnu�[���PK��Z(?hJ�߲test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_1.txtnu�[���PK��Z�e::J�test/Console/Symfony/Component/Console/Tests/Fixtures/application_run1.txtnu�[���PK��Z��x�44H��test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_3.txtnu�[���PK��Z6 �_AAEw�test/Console/Symfony/Component/Console/Tests/Fixtures/Foo3Command.phpnu�[���PK��Z��I��I-�test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_3.jsonnu�[���PK��ZXz�??LB�test/Console/Symfony/Component/Console/Tests/Fixtures/DescriptorCommand2.phpnu�[���PK��Z*[Ǿ44K��test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_4.mdnu�[���PK��Z	�Ӹ�G��test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_2.mdnu�[���PK��Z��U���B��test/Console/Symfony/Component/Console/Tests/Fixtures/command_2.mdnu�[���PK��Z8�UT

J2�test/Console/Symfony/Component/Console/Tests/Fixtures/application_run4.txtnu�[���PK��Z1G~"//G��test/Console/Symfony/Component/Console/Tests/Fixtures/FoobarCommand.phpnu�[���PK��Z�/""��E_�test/Console/Symfony/Component/Console/Tests/Fixtures/Foo5Command.phpnu�[���PK��Z�Xl��V_��test/Console/Symfony/Component/Console/Tests/Fixtures/application_renderexception4.txtnu�[���PK��Z*�q��M���test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_3.jsonnu�[���PK��Z��EOOC���test/Console/Symfony/Component/Console/Tests/Fixtures/command_1.xmlnu�[���PK��Z�NY__J���test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_3.txtnu�[���PK��Z�����MY��test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_2.jsonnu�[���PK��Zh����C`��test/Console/Symfony/Component/Console/Tests/Fixtures/command_2.txtnu�[���PK��Z�	���E��test/Console/Symfony/Component/Console/Tests/Fixtures/Foo2Command.phpnu�[���PK��Z,DŽ���V/��test/Console/Symfony/Component/Console/Tests/Fixtures/application_renderexception2.txtnu�[���PK��Z.p�~~L��test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_4.txtnu�[���PK��Z��M��H��test/Console/Symfony/Component/Console/Tests/Fixtures/application_2.jsonnu�[���PK��Z��ttI��test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_1.mdnu�[���PK��ZQ��d	d	M��test/Console/Symfony/Component/Console/Tests/Tester/ApplicationTesterTest.phpnu�[���PK��Z�x0mBBI�(�test/Console/Symfony/Component/Console/Tests/Tester/CommandTesterTest.phpnu�[���PK��Z�����Fu4�test/Console/Symfony/Component/Console/Tests/Input/StringInputTest.phpnu�[���PK��Z��p���@�G�test/Console/Symfony/Component/Console/Tests/Input/InputTest.phpnu�[���PK��Z�9I;;D�]�test/Console/Symfony/Component/Console/Tests/Input/ArgvInputTest.phpnu�[���PK��Z��@�H�HJ0��test/Console/Symfony/Component/Console/Tests/Input/InputDefinitionTest.phpnu�[���PK��Z1E��<<EJ�test/Console/Symfony/Component/Console/Tests/Input/ArrayInputTest.phpnu�[���PK��ZKU�#�#F���test/Console/Symfony/Component/Console/Tests/Input/InputOptionTest.phpnu�[���PK��ZF�5��Hh�test/Console/Symfony/Component/Console/Tests/Input/InputArgumentTest.phpnu�[���PK��Z��Ĕ���@�+�test/Console/Symfony/Component/Console/Tests/ApplicationTest.phpnu�[���PK��Z�r�HwwS�ϴtest/Console/Symfony/Component/Console/Tests/Formatter/OutputFormatterStyleTest.phpnu�[���PK��Z� R�wwX�޴test/Console/Symfony/Component/Console/Tests/Formatter/OutputFormatterStyleStackTest.phpnu�[���PK��Z]6\���N��test/Console/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.phpnu�[���PK��Z����H��test/Console/Symfony/Component/Console/Tests/Output/StreamOutputTest.phpnu�[���PK��Z;�!��Fu
�test/Console/Symfony/Component/Console/Tests/Output/NullOutputTest.phpnu�[���PK��Z}�R��I��test/Console/Symfony/Component/Console/Tests/Output/ConsoleOutputTest.phpnu�[���PK��Z�����B�test/Console/Symfony/Component/Console/Tests/Output/OutputTest.phpnu�[���PK��ZgO��
�
K}+�test/Console/Symfony/Component/Console/Tests/Helper/FormatterHelperTest.phpnu�[���PK��Z�L��"�"H�6�test/Console/Symfony/Component/Console/Tests/Helper/DialogHelperTest.phpnu�[���PK��Z+��vvE(Z�test/Console/Symfony/Component/Console/Tests/Helper/HelperSetTest.phpnu�[���PK��Z]_Դ3)3)Gs�test/Console/Symfony/Component/Console/Tests/Helper/TableHelperTest.phpnu�[���PK��Z"
U���J���test/Console/Symfony/Component/Console/Tests/Helper/ProgressHelperTest.phpnu�[���PK��ZK� 99N��test/Console/Symfony/Component/Console/Tests/Descriptor/TextDescriptorTest.phpnu�[���PK��Z1H�DDDRɽ�test/Console/Symfony/Component/Console/Tests/Descriptor/MarkdownDescriptorTest.phpnu�[���PK��ZoW��::N���test/Console/Symfony/Component/Console/Tests/Descriptor/JsonDescriptorTest.phpnu�[���PK��Z���66MGõtest/Console/Symfony/Component/Console/Tests/Descriptor/XmlDescriptorTest.phpnu�[���PK��Z�ž_JJK�ŵtest/Console/Symfony/Component/Console/Tests/Descriptor/ObjectsProvider.phpnu�[���PK��Z}�
��R�ѵtest/Console/Symfony/Component/Console/Tests/Descriptor/AbstractDescriptorTest.phpnu�[���PK��Z?�UHii7�test/Console/Symfony/Component/Console/phpunit.xml.distnu�[���PK��Ze�>��4�4/��test/XML_Util/tests/CreateTagFromArrayTests.phpnu�[���PK��Z�C���,��test/XML_Util/tests/ReplaceEntitiesTests.phpnu�[���PK��Zیu���'"+�test/XML_Util/tests/ApiVersionTests.phpnu�[���PK��Z�Gs���$V,�test/XML_Util/tests/Bug5392Tests.phpnu�[���PK��Z4e��jj/�/�test/XML_Util/tests/CreateCDataSectionTests.phpnu�[���PK��Z|�\5.r1�test/XML_Util/tests/CollapseEmptyTagsTests.phpnu�[���PK��Z��GG/�B�test/XML_Util/tests/SplitQualifiedNameTests.phpnu�[���PK��ZYq���%wF�test/XML_Util/tests/Bug21184Tests.phpnu�[���PK��Z>�M���$�H�test/XML_Util/tests/Bug4950Tests.phpnu�[���PK��Z�YR�""/�K�test/XML_Util/tests/CreateStartElementTests.phpnu�[���PK��Zܬ$���2<a�test/XML_Util/tests/GetDocTypeDeclarationTests.phpnu�[���PK��Z��G%�h�test/XML_Util/tests/Bug21177Tests.phpnu�[���PK��Z��۩��%m�test/XML_Util/tests/Bug18343Tests.phpnu�[���PK��Zz��t��,'t�test/XML_Util/tests/ReverseEntitiesTests.phpnu�[���PK��Z~�$[ee-Y��test/XML_Util/tests/CreateEndElementTests.phpnu�[���PK��Z���!��)��test/XML_Util/tests/AbstractUnitTests.phpnu�[���PK��Z�m4�**&��test/XML_Util/tests/CreateTagTests.phpnu�[���PK��ZDf:��.���test/XML_Util/tests/GetXmlDeclarationTests.phpnu�[���PK��ZZ�t�/���test/XML_Util/tests/AttributesToStringTests.phpnu�[���PK��Zݑh���(�̶test/XML_Util/tests/IsValidNameTests.phpnu�[���PK��Z���TT*նtest/XML_Util/tests/CreateCommentTests.phpnu�[���PK��Z�rv��'�ֶtest/XML_Util/tests/RaiseErrorTests.phpnu�[���PK��ZF1y��A�AT�ضtest/OptionsResolver/Symfony/Component/OptionsResolver/Tests/OptionsResolverTest.phpnu�[���PK��Zν�3;3;L��test/OptionsResolver/Symfony/Component/OptionsResolver/Tests/OptionsTest.phpnu�[���PK��Z��*/AAG�V�test/OptionsResolver/Symfony/Component/OptionsResolver/phpunit.xml.distnu�[���PK��Z<ȸB!!SZ�test/Net_SMTP/tests/auth.phptnu�[���PK��Z�߁Q��"�\�test/Net_SMTP/tests/quotedata.phptnu�[���PK��Z�*�W���d�test/Net_SMTP/tests/basic.phptnu�[���PK��Z�6����#�h�test/Net_SMTP/tests/config.php.distnu�[���PK��Z�iH���F�j�test/Config/Symfony/Component/Config/Tests/Definition/EnumNodeTest.phpnu�[���PK��Zhͼ��K�o�test/Config/Symfony/Component/Config/Tests/Definition/NormalizationTest.phpnu�[���PK��Z�hE--GP��test/Config/Symfony/Component/Config/Tests/Definition/ArrayNodeTest.phpnu�[���PK��Z����I�test/Config/Symfony/Component/Config/Tests/Definition/IntegerNodeTest.phpnu�[���PK��Z&]��G��test/Config/Symfony/Component/Config/Tests/Definition/FloatNodeTest.phpnu�[���PK��Z�-1��Q���test/Config/Symfony/Component/Config/Tests/Definition/Builder/ExprBuilderTest.phpnu�[���PK��Z<�C��X÷test/Config/Symfony/Component/Config/Tests/Definition/Builder/EnumNodeDefinitionTest.phpnu�[���PK��ZwX��Yrȷtest/Config/Symfony/Component/Config/Tests/Definition/Builder/ArrayNodeDefinitionTest.phpnu�[���PK��Z
Kmޮ
�
Q��test/Config/Symfony/Component/Config/Tests/Definition/Builder/NodeBuilderTest.phpnu�[���PK��Z�����Q�test/Config/Symfony/Component/Config/Tests/Definition/Builder/TreeBuilderTest.phpnu�[���PK��ZEj~�jj[p�test/Config/Symfony/Component/Config/Tests/Definition/Builder/NumericNodeDefinitionTest.phpnu�[���PK��ZjO灃�He
�test/Config/Symfony/Component/Config/Tests/Definition/ScalarNodeTest.phpnu�[���PK��Z�y���X`�test/Config/Symfony/Component/Config/Tests/Definition/Dumper/YamlReferenceDumperTest.phpnu�[���PK��Z~�P+W��test/Config/Symfony/Component/Config/Tests/Definition/Dumper/XmlReferenceDumperTest.phpnu�[���PK��ZD�99C'#�test/Config/Symfony/Component/Config/Tests/Definition/MergeTest.phpnu�[���PK��ZA�RRJ�7�test/Config/Symfony/Component/Config/Tests/Definition/FinalizationTest.phpnu�[���PK��Z{���I�@�test/Config/Symfony/Component/Config/Tests/Definition/BooleanNodeTest.phpnu�[���PK��Z%Jbx��Q�F�test/Config/Symfony/Component/Config/Tests/Definition/PrototypedArrayNodeTest.phpnu�[���PK��Z�b�..Db�test/Config/Symfony/Component/Config/Tests/Fixtures/Util/invalid.xmlnu�[���PK��Zc=���J�b�test/Config/Symfony/Component/Config/Tests/Fixtures/Util/document_type.xmlnu�[���PK��ZGɩ�SSK�c�test/Config/Symfony/Component/Config/Tests/Fixtures/Util/invalid_schema.xmlnu�[���PK��Z\�XXB�d�test/Config/Symfony/Component/Config/Tests/Fixtures/Util/valid.xmlnu�[���PK��Z�&�Cie�test/Config/Symfony/Component/Config/Tests/Fixtures/Util/schema.xsdnu�[���PK��Z�r_���Q�f�test/Config/Symfony/Component/Config/Tests/Fixtures/Builder/BarNodeDefinition.phpnu�[���PK��Z��@��V5i�test/Config/Symfony/Component/Config/Tests/Fixtures/Builder/VariableNodeDefinition.phpnu�[���PK��Z�u�;ssK�k�test/Config/Symfony/Component/Config/Tests/Fixtures/Builder/NodeBuilder.phpnu�[���PK��Z�����
�
Z�o�test/Config/Symfony/Component/Config/Tests/Fixtures/Configuration/ExampleConfiguration.phpnu�[���PK��ZA�z�test/Config/Symfony/Component/Config/Tests/Fixtures/Again/foo.xmlnu�[���PK��Z;
{�test/Config/Symfony/Component/Config/Tests/Fixtures/foo.xmlnu�[���PK��Z������Mu{�test/Config/Symfony/Component/Config/Tests/Resource/DirectoryResourceTest.phpnu�[���PK��Z�D-��H͑�test/Config/Symfony/Component/Config/Tests/Resource/FileResourceTest.phpnu�[���PK��Z��s@	��test/Config/Symfony/Component/Config/Tests/Util/XmlUtilsTest.phpnu�[���PK��Z Z��^^>���test/Config/Symfony/Component/Config/Tests/ConfigCacheTest.phpnu�[���PK��ZK�OCC>Yøtest/Config/Symfony/Component/Config/Tests/FileLocatorTest.phpnu�[���PK��ZL��{D
Ҹtest/Config/Symfony/Component/Config/Tests/Loader/FileLoaderTest.phpnu�[���PK��Z5bc�@@@��test/Config/Symfony/Component/Config/Tests/Loader/LoaderTest.phpnu�[���PK��Zoq*,��J��test/Config/Symfony/Component/Config/Tests/Loader/DelegatingLoaderTest.phpnu�[���PK��Z�YH�test/Config/Symfony/Component/Config/Tests/Loader/LoaderResolverTest.phpnu�[���PK��Z�Y�hh5m�test/Config/Symfony/Component/Config/phpunit.xml.distnu�[���PK��Z����$:
�test/Net_Sieve/tests/largescript.sivnu�[���PK��Z�g��-�-"i(�test/Net_Sieve/tests/SieveTest.phpnu�[���PK��Z�Y�npp$yV�test/Net_Sieve/tests/config.php.distnu�[���PK��Zҵ3��>=W�test/Mail_mimeDecode/tests/semicolon_content_type_bug1724.phptnu�[���PK��Zs��%��2D[�test/Mail_mimeDecode/tests/parse_header_value.phptnu�[���PK��Z�?7|�f�fA:c�test/HttpKernel/Symfony/Component/HttpKernel/Tests/KernelTest.phpnu�[���PK��Z6^P�Yiʼtest/HttpKernel/Symfony/Component/HttpKernel/Tests/CacheClearer/ChainCacheClearerTest.phpnu�[���PK��Z32ET��SѼtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/TestEventDispatcher.phpnu�[���PK��Zg&��k<Լtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionAbsentBundle/ExtensionAbsentBundle.phpnu�[���PK��Zx���isּtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/Command/BarCommand.phpnu�[���PK��Z��W���i�ؼtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/Command/FooCommand.phpnu�[���PK��Z`Aļ��m_ۼtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/ExtensionPresentBundle.phpnu�[���PK��ZO�g�VV��ݼtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/DependencyInjection/ExtensionPresentExtension.phpnu�[���PK��ZGQ�>`
`
i��test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/cache/test/MockObjectTestProjectContainer.phpnu�[���PK��Z#��R��test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/cache/test/classes.mapnu�[���PK��ZQ6�test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Bundle2Bundle/foo.txtnu�[���PK��Zq�}VffU��test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/KernelForOverrideName.phpnu�[���PK��ZY��test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ChildBundle/Resources/foo.txtnu�[���PK��ZZ+�test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ChildBundle/Resources/hide.txtnu�[���PK��ZQ��test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle/foo.txtnu�[���PK��ZQ6�test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle/bar.txtnu�[���PK��Z[��test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle/Resources/foo.txtnu�[���PK��ZWB�test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/FooBundle/foo.txtnu�[���PK��ZY��test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/ChildBundle/foo.txtnu�[���PK��Z[R�test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/Bundle1Bundle/foo.txtnu�[���PK��ZY��test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/BaseBundle/hide.txtnu�[���PK��ZXf�test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/BaseBundle/Resources/foo.txtnu�[���PK��ZY��test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/BaseBundle/Resources/hide.txtnu�[���PK��Z&#�Jw��test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/TestClient.phpnu�[���PK��Zy��h��M��test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/KernelForTest.phpnu�[���PK��Z�0����Ls��test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/FooBarBundle.phpnu�[���PK��Z��?ɜ�k���test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionLoadedBundle/ExtensionLoadedBundle.phpnu�[���PK��Z��_�TT���test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionLoadedBundle/DependencyInjection/ExtensionLoadedExtension.phpnu�[���PK��Z���S��[��test/HttpKernel/Symfony/Component/HttpKernel/Tests/CacheWarmer/CacheWarmerAggregateTest.phpnu�[���PK��Z���,%%R\�test/HttpKernel/Symfony/Component/HttpKernel/Tests/CacheWarmer/CacheWarmerTest.phpnu�[���PK��Z0��GGE�test/HttpKernel/Symfony/Component/HttpKernel/Tests/TestHttpKernel.phpnu�[���PK��Zq��A��test/HttpKernel/Symfony/Component/HttpKernel/Tests/ClientTest.phpnu�[���PK��Z݂(�$�$Y�6�test/HttpKernel/Symfony/Component/HttpKernel/Tests/Debug/TraceableEventDispatcherTest.phpnu�[���PK��Z���!/
/
Y\�test/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/FragmentListenerTest.phpnu�[���PK��Z�W:ttZ�i�test/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/ExceptionListenerTest.phpnu�[���PK��Z(��kkY�{�test/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/ProfilerListenerTest.phpnu�[���PK��Z=v?�
�
T���test/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/EsiListenerTest.phpnu�[���PK��Zp�66W>��test/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.phpnu�[���PK��Z���uu\���test/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/TestSessionListenerTest.phpnu�[���PK��Z�,ph
h
Y���test/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/ResponseListenerTest.phpnu�[���PK��ZK�(^��W�ɽtest/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/LocaleListenerTest.phpnu�[���PK��Z�o�M��\*ڽtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fragment/HIncludeFragmentRendererTest.phpnu�[���PK��Z�
��((\G�test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fragment/RoutableFragmentRendererTest.phpnu�[���PK��Z�v��Z���test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.phpnu�[���PK��Z;����
�
Sr�test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fragment/FragmentHandlerTest.phpnu�[���PK��Z�҃��	�	W�%�test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fragment/EsiFragmentRendererTest.phpnu�[���PK��Zp����=0�test/HttpKernel/Symfony/Component/HttpKernel/Tests/Logger.phpnu�[���PK��Z��m*����Ni<�test/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.phpnu�[���PK��Z�t~		Ov��test/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpCache/TestHttpKernel.phpnu�[���PK��Z`��uNNH��test/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.phpnu�[���PK��Z���JJW�"�test/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpCache/TestMultipleHttpKernel.phpnu�[���PK��Z�VPR�+�test/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTestCase.phpnu�[���PK��Z����Z&Z&J@�test/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.phpnu�[���PK��Z�`1M�f�test/HttpKernel/Symfony/Component/HttpKernel/Tests/Config/FileLocatorTest.phpnu�[���PK��ZK�w��Hrm�test/HttpKernel/Symfony/Component/HttpKernel/Tests/Bundle/BundleTest.phpnu�[���PK��Z!�g���[�v�test/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/MemcacheProfilerStorageTest.phpnu�[���PK��Z�[���\|�test/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/MemcachedProfilerStorageTest.phpnu�[���PK��ZT���
�
Wt��test/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/FileProfilerStorageTest.phpnu�[���PK��Z�,���)�)[⌿test/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/AbstractProfilerStorageTest.phpnu�[���PK��Z�.�\��RK��test/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/Mock/MemcachedMock.phpnu�[���PK��Zi�]��Qwȿtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/Mock/MemcacheMock.phpnu�[���PK��Ze��K

N�ݿtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/Mock/RedisMock.phpnu�[���PK��Z`ej��Z�test/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/MongoDbProfilerStorageTest.phpnu�[���PK��Zp3hNNYE�test/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/SqliteProfilerStorageTest.phpnu�[���PK��Z�FE��X
�test/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/RedisProfilerStorageTest.phpnu�[���PK��Z�&2TTL[�test/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/ProfilerTest.phpnu�[���PK��Z�Uu֝�D+�test/HttpKernel/Symfony/Component/HttpKernel/Tests/UriSignerTest.phpnu�[���PK��Zbҏ�^^\<�test/HttpKernel/Symfony/Component/HttpKernel/Tests/DataCollector/MemoryDataCollectorTest.phpnu�[���PK��Z�C���Z&#�test/HttpKernel/Symfony/Component/HttpKernel/Tests/DataCollector/TimeDataCollectorTest.phpnu�[���PK��Z���	�	\�)�test/HttpKernel/Symfony/Component/HttpKernel/Tests/DataCollector/ConfigDataCollectorTest.phpnu�[���PK��Z�}#��_�3�test/HttpKernel/Symfony/Component/HttpKernel/Tests/DataCollector/ExceptionDataCollectorTest.phpnu�[���PK��Z�J�֌�]9�test/HttpKernel/Symfony/Component/HttpKernel/Tests/DataCollector/RequestDataCollectorTest.phpnu�[���PK��Z���i	i	\.Y�test/HttpKernel/Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.phpnu�[���PK��Zg�]�>*>*E#c�test/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpKernelTest.phpnu�[���PK��Zz*V%%X֍�test/HttpKernel/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.phpnu�[���PK��Ze�
֮�nf��test/HttpKernel/Symfony/Component/HttpKernel/Tests/DependencyInjection/MergeExtensionConfigurationPassTest.phpnu�[���PK��ZV���^^d���test/HttpKernel/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterListenersPassTest.phpnu�[���PK��Z�C�hhg��test/HttpKernel/Symfony/Component/HttpKernel/Tests/DependencyInjection/ContainerAwareHttpKernelTest.phpnu�[���PK��Z��x99=��test/HttpKernel/Symfony/Component/HttpKernel/phpunit.xml.distnu�[���PK��Z;�{��'I�test/Mail_Mime/tests/test_Bug_GH19.phptnu�[���PK��Z�E�oo(��test/Mail_Mime/tests/test_Bug_13962.phptnu�[���PK��ZԢ��``(L�test/Mail_Mime/tests/test_Bug_21255.phptnu�[���PK��Zi;���)�test/Mail_Mime/tests/test_Bug_7561_1.phptnu�[���PK��Ze;�I(��test/Mail_Mime/tests/test_Bug_21205.phptnu�[���PK��ZY�����'X��test/Mail_Mime/tests/test_Bug_GH26.phptnu�[���PK��Z��RoUU(���test/Mail_Mime/tests/test_Bug_20226.phptnu�[���PK��Zg��+��(O��test/Mail_Mime/tests/test_Bug_13444.phptnu�[���PK��Z%��BB'E�test/Mail_Mime/tests/test_Bug_GH16.phptnu�[���PK��Z�-7c77)��test/Mail_Mime/tests/test_Bug_3513_2.phptnu�[���PK��Z�(V,��(n�test/Mail_Mime/tests/test_Bug_12411.phptnu�[���PK��Z��qS��*O�test/Mail_Mime/tests/test_Bug_10999_1.phptnu�[���PK��Z29r���'��test/Mail_Mime/tests/encoding_case.phptnu�[���PK��ZM�-\��(��test/Mail_Mime/tests/test_Bug_17175.phptnu�[���PK��ZّB�
�
*��test/Mail_Mime/tests/qp_encoding_test.phptnu�[���PK��Z)#��pp(-#�test/Mail_Mime/tests/test_Bug_18772.phptnu�[���PK��Z2!�B��,�&�test/Mail_Mime/tests/test_linebreak_dot.phptnu�[���PK��ZB&���(�-�test/Mail_Mime/tests/test_Bug_12466.phptnu�[���PK��Z�M�U..(�/�test/Mail_Mime/tests/test_Bug_20273.phptnu�[���PK��Z[��b��3�1�test/Mail_Mime/tests/content_transfer_encoding.phptnu�[���PK��Z�k�0(�5�test/Mail_Mime/tests/test_Bug_20564.phptnu�[���PK��Z�a�[��(�6�test/Mail_Mime/tests/class-filename.phptnu�[���PK��Z���o		(38�test/Mail_Mime/tests/test_Bug_14529.phptnu�[���PK��ZCz2�}}(�:�test/Mail_Mime/tests/test_Bug_12165.phptnu�[���PK��ZYa�k!!8i<�test/Mail_Mime/tests/sleep_wakeup_EOL-bug3488-part1.phptnu�[���PK��Z@�/�NN(�>�test/Mail_Mime/tests/test_Bug_21206.phptnu�[���PK��Z�8��)�A�test/Mail_Mime/tests/test_Bug_3513_1.phptnu�[���PK��Z5����(�C�test/Mail_Mime/tests/test_Bug_21098.phptnu�[���PK��Z���v��)�E�test/Mail_Mime/tests/test_Bug_8541_1.phptnu�[���PK��ZUi�E!E!2�G�test/Mail_Mime/tests/headers_without_mbstring.phptnu�[���PK��Z��(�i�test/Mail_Mime/tests/test_Bug_21027.phptnu�[���PK��Z`�~@*t��test/Mail_Mime/tests/test_Bug_12385_1.phptnu�[���PK��Z�zŬ�(�test/Mail_Mime/tests/test_Bug_11731.phptnu�[���PK��ZX��b��(�test/Mail_Mime/tests/test_Bug_14779.phptnu�[���PK��Z�I�zz(.��test/Mail_Mime/tests/test_Bug_20563.phptnu�[���PK��ZZX�Hww)��test/Mail_Mime/tests/test_Bug_3513_3.phptnu�[���PK��Z������(В�test/Mail_Mime/tests/test_Bug_15320.phptnu�[���PK��Z�-b2(���test/Mail_Mime/tests/test_Bug_13032.phptnu�[���PK��Z%+2PP(i��test/Mail_Mime/tests/test_Bug_18083.phptnu�[���PK��ZQi�"--(��test/Mail_Mime/tests/test_Bug_11381.phptnu�[���PK��Z�X�##(���test/Mail_Mime/tests/test_Bug_19497.phptnu�[���PK��Z�'�'')��test/Mail_Mime/tests/test_Bug_8386_1.phptnu�[���PK��Z��1d��(���test/Mail_Mime/tests/test_Bug_17025.phptnu�[���PK��Ze�@Q__(���test/Mail_Mime/tests/test_Bug_14780.phptnu�[���PK��Z�
Ǟ		2<��test/Mail_Mime/tests/test_linebreak_larger_76.phptnu�[���PK��Zܶg�hh)���test/Mail_Mime/tests/test_Bug_9722_1.phptnu�[���PK��Z�YcLYY(b��test/Mail_Mime/tests/test_Bug_16539.phptnu�[���PK��Z��((*�test/Mail_Mime/tests/test_Bug_10596_1.phptnu�[���PK��Z9��::*��test/Mail_Mime/tests/test_Bug_10816_1.phptnu�[���PK��Z��᠗"�"/)�test/Mail_Mime/tests/headers_with_mbstring.phptnu�[���PK��Z���|JJ8��test/Mail_Mime/tests/sleep_wakeup_EOL-bug3488-part2.phptnu�[���PK��Z�{�	�	*��test/File_MARC/tests/marc_xml_rsinger.phptnu�[���PK��Za!���"��test/File_MARC/tests/namespace.xmlnu�[���PK��Z44�-��(�!�test/File_MARC/tests/marc_field_003.phptnu�[���PK��Z�c����(�(�test/File_MARC/tests/marc_xml_16642.phptnu�[���PK��Z�è{{"�,�test/File_MARC/tests/marc_020.phptnu�[���PK��ZҔ��	�	$�<�test/File_MARC/tests/marc_16783.phptnu�[���PK��ZF�-//(�F�test/File_MARC/tests/marc_field_002.phptnu�[���PK��Z��	\��'9I�test/File_MARC/tests/marc_lint_001.phptnu�[���PK��ZrP��&5[�test/File_MARC/tests/marc_xml_004.phptnu�[���PK��Z�0�S��+�f�test/File_MARC/tests/marc_subfield_001.phptnu�[���PK��Zx;��##"�i�test/File_MARC/tests/marc_006.phptnu�[���PK��Z}&�
GG'Fo�test/File_MARC/tests/marc_lint_004.phptnu�[���PK��Z�cܯ�&��test/File_MARC/tests/marc_xml_006.phptnu�[���PK��Z���
��(��test/File_MARC/tests/marc_field_005.phptnu�[���PK��Z��%Hhh"8��test/File_MARC/tests/marc_003.phptnu�[���PK��Z(���NN��test/File_MARC/tests/camel.mrcnu�[���PK��Z�p�޸�"���test/File_MARC/tests/marc_007.phptnu�[���PK��Z����1�1&���test/File_MARC/tests/marc_xml_008.phptnu�[���PK��Z)�]�
�
"p��test/File_MARC/tests/marc_005.phptnu�[���PK��Z	V�U,,*q��test/File_MARC/tests/marc_field_21246.phptnu�[���PK��Z�_|6	6	'���test/File_MARC/tests/marc_lint_002.phptnu�[���PK��Z�=O	
	
!��test/File_MARC/tests/sandburg.xmlnu�[���PK��Z�s}���3��test/File_MARC/tests/marc_xml_namespace_prefix.phptnu�[���PK��Z!Ņ\��&��test/File_MARC/tests/marc_xml_001.phptnu�[���PK��ZF;�Re%e%"/0�test/File_MARC/tests/marc_004.phptnu�[���PK��Z�jS�"�U�test/File_MARC/tests/marc_015.phptnu�[���PK��Z7�"Di�test/File_MARC/tests/marc_009.phptnu�[���PK��Z(Y����"�o�test/File_MARC/tests/xmlescape.mrcnu�[���PK��Z�2�.ii"�r�test/File_MARC/tests/marc_018.phptnu�[���PK��Z8��11)��test/File_MARC/tests/marc_record_001.phptnu�[���PK��Z2�����test/File_MARC/tests/skipif.incnu�[���PK��Z\.i�vv!��test/File_MARC/tests/sandburg.mrcnu�[���PK��Z#c����"҇�test/File_MARC/tests/onerecord.xmlnu�[���PK��Z�_X���(��test/File_MARC/tests/marc_field_004.phptnu�[���PK��Z.%�``"��test/File_MARC/tests/marc_010.phptnu�[���PK��ZB�1��
�
'ë�test/File_MARC/tests/marc_lint_005.phptnu�[���PK��Zye@��&���test/File_MARC/tests/marc_xml_007.phptnu�[���PK��Z�����"κ�test/File_MARC/tests/marc_008.phptnu�[���PK��Z+W��
�
#���test/File_MARC/tests/bigarchive.xmlnu�[���PK��Z��ԛ�
�
"��test/File_MARC/tests/marc_014.phptnu�[���PK��Z�����,P��test/File_MARC/tests/marc_xml_namespace.phptnu�[���PK��Zf��~(|��test/File_MARC/tests/marc_field_001.phptnu�[���PK��Z���YY&S��test/File_MARC/tests/marc_xml_009.phptnu�[���PK��Z~N0�:: ��test/File_MARC/tests/example.mrcnu�[���PK��Z}۶\pp$���test/File_MARC/tests/bad_example.xmlnu�[���PK��Z9�DD"P	�test/File_MARC/tests/marc_017.phptnu�[���PK��Z�&��cc"��test/File_MARC/tests/marc_002.phptnu�[���PK��Z�����&�,�test/File_MARC/tests/marc_xml_005.phptnu�[���PK��Z�5;�-�-�2�test/File_MARC/tests/music.xmlnu�[���PK��Z��`��"�`�test/File_MARC/tests/marc_012.phptnu�[���PK��Z�S3"�g�test/File_MARC/tests/marc_021.phptnu�[���PK��Z<��--+Y{�test/File_MARC/tests/marc_subfield_002.phptnu�[���PK��Z�f==$��test/File_MARC/tests/bad_example.mrcnu�[���PK��Z�kP�"r��test/File_MARC/tests/marc_023.phptnu�[���PK��ZW��))"��test/File_MARC/tests/marc_019.phptnu�[���PK��Z�泮�[��test/File_MARC/tests/music.mrcnu�[���PK��ZE4kL�	�	"W��test/File_MARC/tests/marc_001.phptnu�[���PK��Z�#"�
)
)"t��test/File_MARC/tests/marc_022.phptnu�[���PK��Z�p̎u1u1"���test/File_MARC/tests/marc_016.phptnu�[���PK��ZO~iK!K!"��test/File_MARC/tests/marc_013.phptnu�[���PK��Ze����
�
"42�test/File_MARC/tests/marc_011.phptnu�[���PK��Z�>���&I=�test/File_MARC/tests/marc_xml_003.phptnu�[���PK��ZN���&&&xC�test/File_MARC/tests/marc_xml_002.phptnu�[���PK��Zy���
�
'�Q�test/File_MARC/tests/marc_lint_003.phptnu�[���PK��Z]�Q�� � R6]�test/ClassLoader/Symfony/Component/ClassLoader/Tests/ClassCollectionLoaderTest.phpnu�[���PK��Zh4A!AAO\~�test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike2/Bar.phpnu�[���PK��Z��2[AAO�test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike2/Baz.phpnu�[���PK��Z���	AAO��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike2/Foo.phpnu�[���PK��Z�Cq�""U���test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeParent.phpnu�[���PK��Z�֡Z  XC��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeInterface.phpnu�[���PK��ZKG9Ո�U��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/multipleNs.phpnu�[���PK��Z�Қ`���test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/sameNsMultipleClasses.phpnu�[���PK��Z.~�oDDT���test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeClass.phpnu�[���PK��Z�R��Th��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/notPhpFile.mdnu�[���PK��Z��iT	��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/notAClass.phpnu�[���PK��Z�{�tKK^���test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/C/B/Bar.phpnu�[���PK��ZP�F\KK^���test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/C/B/Foo.phpnu�[���PK��Z�Lk�KK^[��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/A/B/Bar.phpnu�[���PK��Zv�գKK^4��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/A/B/Foo.phpnu�[���PK��Z��cZZa
��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/C/B/Bar.phpnu�[���PK��ZLVAKZZa���test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/C/B/Foo.phpnu�[���PK��ZKa�AAa��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/A/B/Bar.phpnu�[���PK��Z����AAa���test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/A/B/Foo.phpnu�[���PK��Z��@OOQ���test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced2/Bar.phpnu�[���PK��Z
Z3bOOQW��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced2/Baz.phpnu�[���PK��Zd�0OOQ'��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced2/Foo.phpnu�[���PK��Z��55P���test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Bar.phpnu�[���PK��Zᒟ�55P���test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Baz.phpnu�[���PK��Z��R�55Pa��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Foo.phpnu�[���PK��Z�UX�Y��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/WithComments.phpnu�[���PK��Z�d�Q���test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/includepath/Foo.phpnu�[���PK��Zl�@@NL��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/Bar.phpnu�[���PK��Z��q�@@N
��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/Baz.phpnu�[���PK��Z�Ӽ�@@NȞ�test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/Foo.phpnu�[���PK��Z5J�DDW���test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/WithComments.phpnu�[���PK��Z�>�X��MQ��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/deps/traits.phpnu�[���PK��Z:5T+O���test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/php5.4/traits.phpnu�[���PK��Z�
N�77[+��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/ATrait.phpnu�[���PK��Z��`�RR_��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/CInterface.phpnu�[���PK��Z��;;VΥ�test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/A.phpnu�[���PK��Z ��LLV���test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/D.phpnu�[���PK��Zt��LLVa��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/E.phpnu�[���PK��Z��HGG[3��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/BTrait.phpnu�[���PK��Z��LqGGV��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/B.phpnu�[���PK��Z[�"�77[ҩ�test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/CTrait.phpnu�[���PK��Z���Z??_���test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/GInterface.phpnu�[���PK��Z�6S�II]b��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/C/Bar.phpnu�[���PK��Z	���II]8��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/C/Foo.phpnu�[���PK��Z&F�II]��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/A/Bar.phpnu�[���PK��Z���II]��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/A/Foo.phpnu�[���PK��Z�]�>XX`���test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/C/Bar.phpnu�[���PK��Z~�(XX`���test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/C/Foo.phpnu�[���PK��Z99A??`���test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/A/Bar.phpnu�[���PK��Z���i??`Y��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/A/Foo.phpnu�[���PK��Zn��DD[(��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Pearlike2/FooBar.phpnu�[���PK��Z�gy�RR]���test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Namespaced2/FooBar.phpnu�[���PK��Z[�“88\ֵ�test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Namespaced/FooBar.phpnu�[���PK��Zx�wCCZ���test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Pearlike/FooBar.phpnu�[���PK��Z>\oNNig��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/ApcPrefixCollision/A/B/Bar.phpnu�[���PK��Z���GNNiN��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/ApcPrefixCollision/A/B/Foo.phpnu�[���PK��Z�F�EEi5��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/NamespaceCollision/A/B/Bar.phpnu�[���PK��Z]�[�EEi��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/NamespaceCollision/A/B/Foo.phpnu�[���PK��Z/5�<<W��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/FooBar.phpnu�[���PK��Zے�99T���test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Bar.phpnu�[���PK��Z$�y99Tq��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Baz.phpnu�[���PK��Z0- +99T.��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Foo.phpnu�[���PK��ZyQUmDDR���test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike/Bar.phpnu�[���PK��Z��&DDR���test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike/Baz.phpnu�[���PK��Z���EDDRw��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike/Foo.phpnu�[���PK��Z�7LLh=��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/ApcPrefixCollision/A/Bar.phpnu�[���PK��Z.��&LLh!��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/ApcPrefixCollision/A/Foo.phpnu�[���PK��Z4���CCh��test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/NamespaceCollision/A/Bar.phpnu�[���PK��Z�qo�CCh���test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/NamespaceCollision/A/Foo.phpnu�[���PK��Z/5�<<`���test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/fallback/Namespaced/FooBar.phpnu�[���PK��Z���GGb���test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/fallback/Apc/Pearlike/FooBar.phpnu�[���PK��Z�M��� � H`��test/ClassLoader/Symfony/Component/ClassLoader/Tests/ClassLoaderTest.phpnu�[���PK��Ze:{a��T���test/ClassLoader/Symfony/Component/ClassLoader/Tests/ApcUniversalClassLoaderTest.phpnu�[���PK��Z8`�##Q
�test/ClassLoader/Symfony/Component/ClassLoader/Tests/UniversalClassLoaderTest.phpnu�[���PK��Z\|����N�3�test/ClassLoader/Symfony/Component/ClassLoader/Tests/ClassMapGeneratorTest.phpnu�[���PK��Z�)mm?�K�test/ClassLoader/Symfony/Component/ClassLoader/phpunit.xml.distnu�[���PK��Zy�MV����]�O�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.phpnu�[���PK��Z�[��V���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/ParameterTest.phpnu�[���PK��Z~O�99kV��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/LazyProxy/PhpDumper/NullDumperTest.phpnu�[���PK��ZI8�i��{*��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/LazyProxy/Instantiator/RealServiceInstantiatorTest.phpnu�[���PK��Z���//\���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/simple.phpnu�[���PK��ZG3G@��`w��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.phpnu�[���PK��ZE�))a���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.phpnu�[���PK��Zo�Tb_G��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.phpnu�[���PK��Z,�j���_��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.phpnu�[���PK��Z$�oyy`@�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services11.phpnu�[���PK��Z��:A!!hI$�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.phpnu�[���PK��Z��7/��_D�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.phpnu�[���PK��Z�(]

_+J�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services1.xmlnu�[���PK��Z�ibĤ�_�K�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services5.xmlnu�[���PK��Z�![�`�N�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services10.xmlnu�[���PK��Zu�

_�Q�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4.xmlnu�[���PK��Z�_�+WW_2T�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services7.xmlnu�[���PK��Zx'�	11aV�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/withdoctype.xmlnu�[���PK��Z�w�zhh_�V�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services8.xmlnu�[���PK��Z���<ii`�Z�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services13.xmlnu�[���PK��Zp�Ԡ��_�\�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services6.xmlnu�[���PK��Z˕n%%^f�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/nonvalid.xmlnu�[���PK��Z��Pggj�f�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4_bad_import.xmlnu�[���PK��Z\_���_�h�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services3.xmlnu�[���PK��Z]2�
��i1k�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extension2/services.xmlnu�[���PK��Z	�_�m�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services2.xmlnu�[���PK��Z������iHs�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extension1/services.xmlnu�[���PK��ZB�X�

_�u�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xmlnu�[���PK��Z�^����jȃ�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services1.xmlnu�[���PK��ZŃ����j6��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services5.xmlnu�[���PK��Zҗ'y��j���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services4.xmlnu�[���PK��Z��	j��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services7.xmlnu�[���PK��Zix�C��j���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services6.xmlnu�[���PK��Z>U���jM��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services3.xmlnu�[���PK��Z�}��j���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services2.xmlnu�[���PK��Z��33eٕ�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services10.dotnu�[���PK��Zh	�	�	d���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dotnu�[���PK��ZՁ1*,,g#��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services10-1.dotnu�[���PK��Z&�WWd��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services1.dotnu�[���PK��ZŏD�;;eѧ�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services13.dotnu�[���PK��Z��8BBe���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services14.dotnu�[���PK��Z�N�{rryx��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectWithXsdExtensionInPhar.pharnu�[���PK��Z�
��^���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/foo.phpnu�[���PK��Z��]���e���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/createphar.phpnu�[���PK��Z.Y<ҿ�k(��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectExtension.phpnu�[���PK��ZAov:ZZb���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.phpnu�[���PK��ZRK:��mn��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/schema/project-1.0.xsdnu�[���PK��Z��[[r���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectWithXsdExtension.phpnu�[���PK��Z����`���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services8.ymlnu�[���PK��Z�|��DD`���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services3.ymlnu�[���PK��Z6�e3��`���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services6.ymlnu�[���PK��ZV�v�==`��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4.ymlnu�[���PK��Z#�&#`���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/nonvalid1.ymlnu�[���PK��Zy��??k���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4_bad_import.ymlnu�[���PK��Z�*_6��^`��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag3.ymlnu�[���PK��Zzb��nn^���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag1.ymlnu�[���PK��Z����''`���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services7.ymlnu�[���PK��Z�%/���aF��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services10.ymlnu�[���PK��Z��2`e��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services1.ymlnu�[���PK��Z�MuAa���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services11.ymlnu�[���PK��Z}�>���^���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag2.ymlnu�[���PK��Z:�Ʋ��`���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services2.ymlnu�[���PK��ZW�%`
��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/nonvalid2.ymlnu�[���PK��Z|�w���`���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.ymlnu�[���PK��Z����GGa���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services13.ymlnu�[���PK��Z۴)�++^���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/nonvalid.ininu�[���PK��Zpu��((aL��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters2.ininu�[���PK��Zs4��''`��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters.ininu�[���PK��Z5l%%a���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters1.ininu�[���PK��Z�Fm��hr��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/interfaces2.phpnu�[���PK��Z4h���g���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container8.phpnu�[���PK��Z�	Z��g���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.phpnu�[���PK��Z���33h��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container11.phpnu�[���PK��Z��|h��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/interfaces1.phpnu�[���PK��ZC�ݲ;;hz��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container10.phpnu�[���PK��ZBreOOhM��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container13.phpnu�[���PK��Z�*�EEh4�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container12.phpnu�[���PK��Z�1�v��h�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container14.phpnu�[���PK��Z
�^��lg�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/ParameterBag/FrozenParameterBagTest.phpnu�[���PK��Z$����9�9f��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/ParameterBag/ParameterBagTest.phpnu�[���PK��Z��
�
W�E�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/CrossCheckTest.phpnu�[���PK��Z2+`��	�	^�S�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.phpnu�[���PK��Zv��b7^�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Dumper/GraphvizDumperTest.phpnu�[���PK��Z�)���]�j�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.phpnu�[���PK��Z�"��."."]W|�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.phpnu�[���PK��Z����V��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/ReferenceTest.phpnu�[���PK��Zł``aA��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Loader/ClosureLoaderTest.phpnu�[���PK��ZSR���a2��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.phpnu�[���PK��Z�kV�0�0b`��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.phpnu�[���PK��ZQ&I�8a8aa���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.phpnu�[���PK��Z���
�
a�B�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Loader/IniFileLoaderTest.phpnu�[���PK��Z'����	�	rN�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInvalidReferencesPassTest.phpnu�[���PK��Z��'{{q�X�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/CheckCircularReferencesPassTest.phpnu�[���PK��Z>�"��p�e�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/CheckReferenceValidityPassTest.phpnu�[���PK��Z]����tr�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.phpnu�[���PK��Z}1H@@x���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/ReplaceAliasByActualDefinitionPassTest.phpnu�[���PK��Z��f00r���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.phpnu�[���PK��ZO����a^��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.phpnu�[���PK��Z@|޵�����test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/CheckExceptionOnInvalidReferenceBehaviorPassTest.phpnu�[���PK��Z@�w��q���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/CheckDefinitionValidityPassTest.phpnu�[���PK��Z�~�``rT��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/AnalyzeServiceReferencesPassTest.phpnu�[���PK��Z��I�
�
qV��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/RemoveUnusedDefinitionsPassTest.phpnu�[���PK��Z
T^�??t���test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveReferencesToAliasesPassTest.phpnu�[���PK��Z���e�5�5Wy��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/DefinitionTest.phpnu�[���PK��Z+��E�
�
`��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/DefinitionDecoratorTest.phpnu�[���PK��Z�K5��W�WV�)�test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/ContainerTest.phpnu�[���PK��Z`��=�	�	`7��test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Extension/ExtensionTest.phpnu�[���PK��Z���uuO���test/DependencyInjection/Symfony/Component/DependencyInjection/phpunit.xml.distnu�[���PK��Z�'7,�������PEAR.phpnu�[���PK��Z�o�P�P
�System.phpnu�[���PK��ZZ�Vdcc�o�peclcmd.phpnu�[���PK��Z��j��-t�data/Base/design/design.txtnu�[���PK��Zu+��S�S�"8u�data/Base/design/class_diagram.pngnu�[���PK��Zy��
�
#��data/ConsoleTools/design/design.txtnu�[���PK��Z���?�T�T'��data/ConsoleTools/design/design-1.3.txtnu�[���PK��Z�>�5AA$�i�data/ConsoleTools/design/console.pngnu�[���PK��Z_x��!�!/��data/ConsoleTools/design/console_parameters.pngnu�[���PK��Z�YǾ����$��data/ConsoleTools/design/console.xmlnu�[���PK��Z�>'�J
�J
*��data/ConsoleTools/design/class_diagram.pngnu�[���PK��Zũ�

��data/PEAR/package.dtdnu�[���PK��Z�������data/PEAR/template.specnu�[���PK��Z�>��9�data/Archive/design/design.txtnu�[���PK��Z�g�3�{
�{
%� �data/Archive/design/class_diagram.pngnu�[���PK��Zߦ��Ҝ�data/File/design/design.txtnu�[���PK��Z 1D\  !��data/File/design/requirements.txtnu�[���PK��Z�rCBB$\��data/File/design/file_operations.pngnu�[���PK��ZXV���0�0��data/File/design/md5.pngnu�[���PK��Z�
[�o�o��data/File/design/file.xmlnu�[���PK��Z�\����"�Z�data/File/design/class_diagram.pngnu�[���PK��Z6E�WW]�data/Mail_mimeDecode/xmail.xslnu�[���PK��Z�
$v66�e�data/Mail_mimeDecode/xmail.dtdnu�[���PK��Z�Z��aa8h�.filemapnu�[���PK��Z}�g�х�.channels/__uri.regnu�[���PK��Z^q++��.channels/pecl.php.net.regnu�[���PK��Z��0�����.channels/components.ez.no.regnu�[���PK��Z�H:{�����.channels/pear.symfony.com.regnu�[���PK��Zl�|�����.channels/pear.phpunit.de.regnu�[���PK��Z�t�r��.channels/.alias/ezc.txtnu�[���PK��Z�o/�ʔ�.channels/.alias/phpdocs.txtnu�[���PK��Z\���!��.channels/.alias/symfony2.txtnu�[���PK��ZT�Y~��.channels/.alias/phpunit.txtnu�[���PK��Z� ��ٕ�.channels/.alias/pear.txtnu�[���PK��Zui<�.��.channels/.alias/pecl.txtnu�[���PK��ZE�Q���.channels/doc.php.net.regnu�[���PK��Z|K3�((��.channels/pear.php.net.regnu�[���PK��Z��0AC5C5S��Console/Getopt.phpnu�[���PK��ZP'hB�&�&���Mail.phpnu�[���PK��Z�܄�����#���.pkgxml/Symfony2_Security-2.4.3.xmlnu�[���PK��Z'J�z++���.pkgxml/symfony2.xmlnu�[���PK��Z^\F[[%���.pkgxml/Symfony2_Serializer-2.4.3.xmlnu�[���PK��Z�$n��7�7&���.pkgxml/Symfony2_ClassLoader-2.4.3.xmlnu�[���PK��Zȗ��!�#�.pkgxml/Pear_Net_Socket-1.2.2.xmlnu�[���PK��Z��n�++	,�.pkgxml/Symfony2_Yaml-2.4.3.xmlnu�[���PK��Z}3YN���D�.pkgxml/eZc_Archive-1.4.1.xmlnu�[���PK��Z��b�8�8!�b�.pkgxml/Symfony2_Config-2.4.3.xmlnu�[���PK��Z�$v��*���.pkgxml/Symfony2_OptionsResolver-2.4.3.xmlnu�[���PK��Z�/�h����"��.pkgxml/Pear_Mail_Mime-1.10.11.xmlnu�[���PK��ZtWY�n�n%�:�.pkgxml/Symfony2_HttpKernel-2.4.3.xmlnu�[���PK��Z�1��ss.8��.pkgxml/Symfony2_DependencyInjection-2.4.3.xmlnu�[���PK��Z=��4��(��.pkgxml/Symfony2_MonologBridge-2.4.3.xmlnu�[���PK��Z�7�p�K�K�*�.pkgxml/XML_Util.xmlnu�[���PK��Z��-=-="`v�.pkgxml/Symfony2_Routing-2.4.3.xmlnu�[���PK��Z�|g��$߳�.pkgxml/Symfony2_Validator-2.4.3.xmlnu�[���PK��Z�d+)SS!#\�.pkgxml/Symfony2_Locale-2.4.3.xmlnu�[���PK��Z%ONO��&�r�.pkgxml/Pear_Mail_mimeDecode-1.5.6.xmlnu�[���PK��Z�*�OO��.pkgxml/ezc.xmlnu�[���PK��Z#�r�

 ���.pkgxml/Pear_Net_SMTP-1.10.0.xmlnu�[���PK��Za������؜�.pkgxml/Symfony2_Form-2.4.3.xmlnu�[���PK��Z�Q���?�? �Y�.pkgxml/Pear_Net_Sieve-1.4.5.xmlnu�[���PK��Z��F��%ʙ�.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu�[���PK��Z?�4��
�
%���.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu�[���PK��Z��t8��%7��.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu�[���PK��Z>t�B�B&��.pkgxml/Symfony2_Translation-2.4.3.xmlnu�[���PK��Z��c��� D	�.pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[���PK��Z���>`-`- y �.pkgxml/Pear_File_MARC-1.3.0.xmlnu�[���PK��Z�oA A )N�.pkgxml/eZc_Base-1.8.xmlnu�[���PK��Z�3'�C�C)�n�.pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu�[���PK��Z��������.pkgxml/Symfony2.listnu�[���PK��Z8���Ƶ�.pkgxml/phpunit.xmlnu�[���PK��Zu&6��%�%%��.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu�[���PK��Zz�WzDD 6��.pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[���PK��Z��UU�_�_"���.pkgxml/Symfony2_Console-2.4.3.xmlnu�[���PK��Z�����K�.pkgxml/Pear.listnu�[���PK��Z�k�b��*.M�.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu�[���PK��Z�3�--,\�.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[���PK��Zs�YY"�m�.pkgxml/Symfony2_Process-2.4.3.xmlnu�[���PK��Z�n�J/J/)B��.pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu�[���PK��ZZ2�iHH��.pkgxml/Pear_Mail-1.4.1.xmlnu�[���PK��ZA��~0~0&x��.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu�[���PK��Z�
v~[0[0!L��.pkgxml/Symfony2_Finder-2.4.3.xmlnu�[���PK��Z�܋Fcc�"�.pkgxml/eZc.listnu�[���PK��Z���\\�#�.pkgxml/eZc_File-1.2.xmlnu�[���PK��Z��IZ��%?0�.pkgxml/Symfony2_Templating-2.4.3.xmlnu�[���PK��Zn#)v�>�>"M�.pkgxml/eZc_ConsoleTools-1.6.1.xmlnu�[���PK��ZT�v�S)S)<��.registry/mail.regnu�[���PK��Z�K<uvuvѵ�.registry/xml_util.regnu�[���PK��Z�EINJNJ/�,�.registry/.channel.pear.symfony.com/process.regnu�[���PK��ZI6�����/9w�.registry/.channel.pear.symfony.com/console.regnu�[���PK��Z��w�dd39��.registry/.channel.pear.symfony.com/translation.regnu�[���PK��Z�N��&�&2�.registry/.channel.pear.symfony.com/filesystem.regnu�[���PK��Z���f�f0W-�.registry/.channel.pear.symfony.com/security.regnu�[���PK��Z�ۧY̟̟1���.registry/.channel.pear.symfony.com/validator.regnu�[���PK��Zh������.�4�.registry/.channel.pear.symfony.com/config.regnu�[���PK��Z�������2�.registry/.channel.pear.symfony.com/httpkernel.regnu�[���PK��Z|L(�t�t�3�.registry/.channel.pear.symfony.com/cssselector.regnu�[���PK��Z�����6ޝ.registry/.channel.pear.symfony.com/httpfoundation.regnu�[���PK��Z����/�/�22�.registry/.channel.pear.symfony.com/twigbridge.regnu�[���PK��Z��m�(�(7�C.registry/.channel.pear.symfony.com/optionsresolver.regnu�[���PK��ZN�� ��.�l.registry/.channel.pear.symfony.com/finder.regnu�[���PK��ZH����,f/.registry/.channel.pear.symfony.com/form.regnu�[���PK��Zǯ6B�+�+5�..registry/.channel.pear.symfony.com/monologbridge.regnu�[���PK��Z�w��=h=h2�Z.registry/.channel.pear.symfony.com/serializer.regnu�[���PK��Z��Dž�.�.2R�.registry/.channel.pear.symfony.com/browserkit.regnu�[���PK��ZZ��G3G37f�.registry/.channel.pear.symfony.com/eventdispatcher.regnu�[���PK��Z����Y�Y,&	.registry/.channel.pear.symfony.com/yaml.regnu�[���PK��Z�Gl9n9n2^�	.registry/.channel.pear.symfony.com/templating.regnu�[���PK��Z�pUx@x@2��	.registry/.channel.pear.symfony.com/domcrawler.regnu�[���PK��Z/����3�/
.registry/.channel.pear.symfony.com/classloader.regnu�[���PK��Z�
��d�d�/A%.registry/.channel.pear.symfony.com/routing.regnu�[���PK��Z��זR�R..registry/.channel.pear.symfony.com/locale.regnu�[���PK��Z��7Tg�g�;�k.registry/.channel.pear.symfony.com/dependencyinjection.regnu�[���PK��Z���	��6�F.registry/.channel.pear.symfony.com/doctrinebridge.regnu�[���PK��Z��
��W�WO.registry/archive_tar.regnu�[���PK��Z��I\ENEN8c.registry/net_sieve.regnu�[���PK��ZV���)�)ı.registry/console_getopt.regnu�[���PK��Z0-�(�(���.registry/file_marc.regnu�[���PK��Z�-"D�D�Nz.registry/pear.regnu�[���PK��Zb'��:+:+�.registry/mail_mimedecode.regnu�[���PK��Zm��II[1.registry/net_smtp.regnu�[���PK��Z��=�K.registry/net_idna2.regnu�[���PK��Zl���.�.�<e.registry/mail_mime.regnu�[���PK��Z;�,6,6#�I.registry/structures_linkedlist.regnu�[���PK��ZI�<�++0�.registry/structures_graph.regnu�[���PK��Zh;.1{1{��.registry/xml_rpc.regnu�[���PK��Zf&�}"",'.registry/.channel.components.ez.no/file.regnu�[���PK��Z��2a�e�e/mI.registry/.channel.components.ez.no/archive.regnu�[���PK��Z�D�}����4~�.registry/.channel.components.ez.no/consoletools.regnu�[���PK��ZY�:�4p4p,��.registry/.channel.components.ez.no/base.regnu�[���PK��ZD
�M��>.registry/net_socket.regnu�[���PK��Z*�:�|&|&O.registry/auth_sasl.regnu�[���PK��ZG�J�W�W@XML/RPC/Server.phpnu�[���PK��ZioK���XML/RPC/Dump.phpnu�[���PK��Z�/=������XML/RPC.phpnu�[���PK��Zc���}�}"�XML/Util.phpnu�[���PK��Z#F��:�:pearcmd.phpnu�[���PK��Z�0$�-- �O.pkgxml/Pear_File_MARC-1.4.1.xmlnu�[���PK���@0}